rtquery.c revision 18316
118316Swollman/*- 218316Swollman * Copyright (c) 1982, 1986, 1993 318316Swollman * The Regents of the University of California. All rights reserved. 418316Swollman * 518316Swollman * Redistribution and use in source and binary forms, with or without 618316Swollman * modification, are permitted provided that the following conditions 718316Swollman * are met: 818316Swollman * 1. Redistributions of source code must retain the above copyright 918316Swollman * notice, this list of conditions and the following disclaimer. 1018316Swollman * 2. Redistributions in binary form must reproduce the above copyright 1118316Swollman * notice, this list of conditions and the following disclaimer in the 1218316Swollman * documentation and/or other materials provided with the distribution. 1318316Swollman * 3. All advertising materials mentioning features or use of this software 1418316Swollman * must display the following acknowledgement: 1518316Swollman * This product includes software developed by the University of 1618316Swollman * California, Berkeley and its contributors. 1718316Swollman * 4. Neither the name of the University nor the names of its contributors 1818316Swollman * may be used to endorse or promote products derived from this software 1918316Swollman * without specific prior written permission. 2018316Swollman * 2118316Swollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2218316Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2318316Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2418316Swollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2518316Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2618316Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2718316Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2818316Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2918316Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3018316Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3118316Swollman * SUCH DAMAGE. 3218316Swollman */ 3318316Swollman 3418316Swollmanchar copyright[] = 3518316Swollman"@(#) Copyright (c) 1982, 1986, 1993\n\ 3618316Swollman The Regents of the University of California. All rights reserved.\n"; 3718316Swollman 3818316Swollman#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__) 3918316Swollmanstatic char sccsid[] = "@(#)query.c 8.1 (Berkeley) 6/5/93"; 4018316Swollman#elif defined(__NetBSD__) 4118316Swollmanstatic char rcsid[] = "$NetBSD$"; 4218316Swollman#endif 4318316Swollman#ident "$Revision: 1.9 $" 4418316Swollman 4518316Swollman#include <sys/param.h> 4618316Swollman#include <sys/protosw.h> 4718316Swollman#include <sys/socket.h> 4818316Swollman#include <sys/time.h> 4918316Swollman#include <netinet/in.h> 5018316Swollman#define RIPVERSION RIPv2 5118316Swollman#include <protocols/routed.h> 5218316Swollman#include <arpa/inet.h> 5318316Swollman#include <netdb.h> 5418316Swollman#include <errno.h> 5518316Swollman#include <unistd.h> 5618316Swollman#include <stdio.h> 5718316Swollman#include <stdlib.h> 5818316Swollman#include <string.h> 5918316Swollman#ifdef sgi 6018316Swollman#include <strings.h> 6118316Swollman#include <bstring.h> 6218316Swollman#endif 6318316Swollman 6418316Swollman#ifndef sgi 6518316Swollman#define _HAVE_SIN_LEN 6618316Swollman#endif 6718316Swollman 6818316Swollman#define WTIME 15 /* Time to wait for all responses */ 6918316Swollman#define STIME (250*1000) /* usec to wait for another response */ 7018316Swollman 7118316Swollmanint s; 7218316Swollman 7318316Swollmanchar *pgmname; 7418316Swollman 7518316Swollmanunion { 7618316Swollman struct rip rip; 7718316Swollman char packet[MAXPACKETSIZE+MAXPATHLEN]; 7818316Swollman} omsg_buf; 7918316Swollman#define OMSG omsg_buf.rip 8018316Swollmanint omsg_len = sizeof(struct rip); 8118316Swollman 8218316Swollmanunion { 8318316Swollman struct rip rip; 8418316Swollman char packet[MAXPACKETSIZE+1024]; 8518316Swollman } imsg_buf; 8618316Swollman#define IMSG imsg_buf.rip 8718316Swollman 8818316Swollmanint nflag; /* numbers, no names */ 8918316Swollmanint pflag; /* play the `gated` game */ 9018316Swollmanint ripv2 = 1; /* use RIP version 2 */ 9118316Swollmanint wtime = WTIME; 9218316Swollmanint rflag; /* 1=ask about a particular route */ 9318316Swollmanint trace; 9418316Swollmanint not_trace; 9518316Swollman 9618316Swollmanstruct timeval sent; /* when query sent */ 9718316Swollman 9818316Swollmanstatic void rip_input(struct sockaddr_in*, int); 9918316Swollmanstatic int out(char *); 10018316Swollmanstatic void trace_loop(char *argv[]); 10118316Swollmanstatic void query_loop(char *argv[], int); 10218316Swollmanstatic int getnet(char *, struct netinfo *); 10318316Swollmanstatic u_int std_mask(u_int); 10418316Swollman 10518316Swollman 10618316Swollmanint 10718316Swollmanmain(int argc, 10818316Swollman char *argv[]) 10918316Swollman{ 11018316Swollman int ch, bsize; 11118316Swollman char *p, *options, *value; 11218316Swollman 11318316Swollman OMSG.rip_nets[0].n_dst = RIP_DEFAULT; 11418316Swollman OMSG.rip_nets[0].n_family = RIP_AF_UNSPEC; 11518316Swollman OMSG.rip_nets[0].n_metric = htonl(HOPCNT_INFINITY); 11618316Swollman 11718316Swollman pgmname = argv[0]; 11818316Swollman while ((ch = getopt(argc, argv, "np1w:r:t:")) != EOF) 11918316Swollman switch (ch) { 12018316Swollman case 'n': 12118316Swollman not_trace = 1; 12218316Swollman nflag = 1; 12318316Swollman break; 12418316Swollman 12518316Swollman case 'p': 12618316Swollman not_trace = 1; 12718316Swollman pflag = 1; 12818316Swollman break; 12918316Swollman 13018316Swollman case '1': 13118316Swollman ripv2 = 0; 13218316Swollman break; 13318316Swollman 13418316Swollman case 'w': 13518316Swollman not_trace = 1; 13618316Swollman wtime = (int)strtoul(optarg, &p, 0); 13718316Swollman if (*p != '\0' 13818316Swollman || wtime <= 0) 13918316Swollman goto usage; 14018316Swollman break; 14118316Swollman 14218316Swollman case 'r': 14318316Swollman not_trace = 1; 14418316Swollman if (rflag) 14518316Swollman goto usage; 14618316Swollman rflag = getnet(optarg, &OMSG.rip_nets[0]); 14718316Swollman if (!rflag) { 14818316Swollman struct hostent *hp = gethostbyname(optarg); 14918316Swollman if (hp == 0) { 15018316Swollman fprintf(stderr, "%s: %s:", 15118316Swollman pgmname, optarg); 15218316Swollman herror(0); 15318316Swollman exit(1); 15418316Swollman } 15518316Swollman bcopy(hp->h_addr, &OMSG.rip_nets[0].n_dst, 15618316Swollman sizeof(OMSG.rip_nets[0].n_dst)); 15718316Swollman OMSG.rip_nets[0].n_family = RIP_AF_INET; 15818316Swollman OMSG.rip_nets[0].n_mask = -1; 15918316Swollman rflag = 1; 16018316Swollman } 16118316Swollman break; 16218316Swollman 16318316Swollman case 't': 16418316Swollman trace = 1; 16518316Swollman options = optarg; 16618316Swollman while (*options != '\0') { 16718316Swollman char *traceopts[] = { 16818316Swollman# define TRACE_ON 0 16918316Swollman "on", 17018316Swollman# define TRACE_MORE 1 17118316Swollman "more", 17218316Swollman# define TRACE_OFF 2 17318316Swollman "off", 17418316Swollman# define TRACE_DUMP 3 17518316Swollman "dump", 17618316Swollman 0 17718316Swollman }; 17818316Swollman switch (getsubopt(&options,traceopts,&value)) { 17918316Swollman case TRACE_ON: 18018316Swollman OMSG.rip_cmd = RIPCMD_TRACEON; 18118316Swollman if (!value 18218316Swollman || strlen(value) > MAXPATHLEN) 18318316Swollman goto usage; 18418316Swollman break; 18518316Swollman case TRACE_MORE: 18618316Swollman if (value) 18718316Swollman goto usage; 18818316Swollman OMSG.rip_cmd = RIPCMD_TRACEON; 18918316Swollman value = ""; 19018316Swollman break; 19118316Swollman case TRACE_OFF: 19218316Swollman if (value) 19318316Swollman goto usage; 19418316Swollman OMSG.rip_cmd = RIPCMD_TRACEOFF; 19518316Swollman value = ""; 19618316Swollman break; 19718316Swollman case TRACE_DUMP: 19818316Swollman if (value) 19918316Swollman goto usage; 20018316Swollman OMSG.rip_cmd = RIPCMD_TRACEON; 20118316Swollman value = "dump/../table"; 20218316Swollman break; 20318316Swollman default: 20418316Swollman goto usage; 20518316Swollman } 20618316Swollman strcpy((char*)OMSG.rip_tracefile, value); 20718316Swollman omsg_len += strlen(value) - sizeof(OMSG.ripun); 20818316Swollman } 20918316Swollman break; 21018316Swollman 21118316Swollman default: 21218316Swollman goto usage; 21318316Swollman } 21418316Swollman argv += optind; 21518316Swollman argc -= optind; 21618316Swollman if ((not_trace && trace) || argc == 0) { 21718316Swollmanusage: fprintf(stderr, "%s: [-np1v] [-r tgt_rt] [-w wtime]" 21818316Swollman " host1 [host2 ...]\n" 21918316Swollman "or\t-t {on=filename|more|off} host1 host2 ...\n", 22018316Swollman pgmname); 22118316Swollman exit(1); 22218316Swollman } 22318316Swollman 22418316Swollman s = socket(AF_INET, SOCK_DGRAM, 0); 22518316Swollman if (s < 0) { 22618316Swollman perror("socket"); 22718316Swollman exit(2); 22818316Swollman } 22918316Swollman 23018316Swollman /* be prepared to receive a lot of routes */ 23118316Swollman for (bsize = 127*1024; ; bsize -= 1024) { 23218316Swollman if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, 23318316Swollman &bsize, sizeof(bsize)) == 0) 23418316Swollman break; 23518316Swollman if (bsize <= 4*1024) { 23618316Swollman perror("setsockopt SO_RCVBUF"); 23718316Swollman break; 23818316Swollman } 23918316Swollman } 24018316Swollman 24118316Swollman if (trace) 24218316Swollman trace_loop(argv); 24318316Swollman else 24418316Swollman query_loop(argv, argc); 24518316Swollman /* NOTREACHED */ 24618316Swollman} 24718316Swollman 24818316Swollman 24918316Swollman/* tell the target hosts about tracing 25018316Swollman */ 25118316Swollmanstatic void 25218316Swollmantrace_loop(char *argv[]) 25318316Swollman{ 25418316Swollman struct sockaddr_in myaddr; 25518316Swollman int res; 25618316Swollman 25718316Swollman if (geteuid() != 0) { 25818316Swollman (void)fprintf(stderr, "-t requires UID 0\n"); 25918316Swollman exit(1); 26018316Swollman } 26118316Swollman 26218316Swollman if (ripv2) { 26318316Swollman OMSG.rip_vers = RIPv2; 26418316Swollman } else { 26518316Swollman OMSG.rip_vers = RIPv1; 26618316Swollman } 26718316Swollman 26818316Swollman bzero(&myaddr, sizeof(myaddr)); 26918316Swollman myaddr.sin_family = AF_INET; 27018316Swollman#ifdef _HAVE_SIN_LEN 27118316Swollman myaddr.sin_len = sizeof(myaddr); 27218316Swollman#endif 27318316Swollman myaddr.sin_port = htons(IPPORT_RESERVED-1); 27418316Swollman while (bind(s, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { 27518316Swollman if (errno != EADDRINUSE 27618316Swollman || myaddr.sin_port == 0) { 27718316Swollman perror("bind"); 27818316Swollman exit(2); 27918316Swollman } 28018316Swollman myaddr.sin_port = htons(ntohs(myaddr.sin_port)-1); 28118316Swollman } 28218316Swollman 28318316Swollman res = 1; 28418316Swollman while (*argv != 0) { 28518316Swollman if (out(*argv++) <= 0) 28618316Swollman res = 0; 28718316Swollman } 28818316Swollman exit(res); 28918316Swollman} 29018316Swollman 29118316Swollman 29218316Swollman/* query all of the listed hosts 29318316Swollman */ 29418316Swollmanstatic void 29518316Swollmanquery_loop(char *argv[], int argc) 29618316Swollman{ 29718316Swollman struct seen { 29818316Swollman struct seen *next; 29918316Swollman struct in_addr addr; 30018316Swollman } *seen, *sp; 30118316Swollman int answered = 0; 30218316Swollman int cc; 30318316Swollman fd_set bits; 30418316Swollman struct timeval now, delay; 30518316Swollman struct sockaddr_in from; 30618316Swollman int fromlen; 30718316Swollman 30818316Swollman 30918316Swollman OMSG.rip_cmd = (pflag) ? RIPCMD_POLL : RIPCMD_REQUEST; 31018316Swollman if (ripv2) { 31118316Swollman OMSG.rip_vers = RIPv2; 31218316Swollman } else { 31318316Swollman OMSG.rip_vers = RIPv1; 31418316Swollman OMSG.rip_nets[0].n_mask = 0; 31518316Swollman } 31618316Swollman 31718316Swollman /* ask the first (valid) host */ 31818316Swollman seen = 0; 31918316Swollman while (0 > out(*argv++)) { 32018316Swollman if (*argv == 0) 32118316Swollman exit(-1); 32218316Swollman answered++; 32318316Swollman } 32418316Swollman 32518316Swollman FD_ZERO(&bits); 32618316Swollman for (;;) { 32718316Swollman FD_SET(s, &bits); 32818316Swollman delay.tv_sec = 0; 32918316Swollman delay.tv_usec = STIME; 33018316Swollman cc = select(s+1, &bits, 0,0, &delay); 33118316Swollman if (cc > 0) { 33218316Swollman fromlen = sizeof(from); 33318316Swollman cc = recvfrom(s, imsg_buf.packet, 33418316Swollman sizeof(imsg_buf.packet), 0, 33518316Swollman (struct sockaddr *)&from, &fromlen); 33618316Swollman if (cc < 0) { 33718316Swollman perror("recvfrom"); 33818316Swollman exit(1); 33918316Swollman } 34018316Swollman /* count the distinct responding hosts. 34118316Swollman * You cannot match responding hosts with 34218316Swollman * addresses to which queries were transmitted, 34318316Swollman * because a router might respond with a 34418316Swollman * different source address. 34518316Swollman */ 34618316Swollman for (sp = seen; sp != 0; sp = sp->next) { 34718316Swollman if (sp->addr.s_addr == from.sin_addr.s_addr) 34818316Swollman break; 34918316Swollman } 35018316Swollman if (sp == 0) { 35118316Swollman sp = malloc(sizeof(*sp)); 35218316Swollman sp->addr = from.sin_addr; 35318316Swollman sp->next = seen; 35418316Swollman seen = sp; 35518316Swollman answered++; 35618316Swollman } 35718316Swollman 35818316Swollman rip_input(&from, cc); 35918316Swollman continue; 36018316Swollman } 36118316Swollman 36218316Swollman if (cc < 0) { 36318316Swollman if ( errno == EINTR) 36418316Swollman continue; 36518316Swollman perror("select"); 36618316Swollman exit(1); 36718316Swollman } 36818316Swollman 36918316Swollman /* After a pause in responses, probe another host. 37018316Swollman * This reduces the intermingling of answers. 37118316Swollman */ 37218316Swollman while (*argv != 0 && 0 > out(*argv++)) 37318316Swollman answered++; 37418316Swollman 37518316Swollman /* continue until no more packets arrive 37618316Swollman * or we have heard from all hosts 37718316Swollman */ 37818316Swollman if (answered >= argc) 37918316Swollman break; 38018316Swollman 38118316Swollman /* or until we have waited a long time 38218316Swollman */ 38318316Swollman if (gettimeofday(&now, 0) < 0) { 38418316Swollman perror("gettimeofday(now)"); 38518316Swollman exit(1); 38618316Swollman } 38718316Swollman if (sent.tv_sec + wtime <= now.tv_sec) 38818316Swollman break; 38918316Swollman } 39018316Swollman 39118316Swollman /* fail if there was no answer */ 39218316Swollman exit (answered >= argc ? 0 : 1); 39318316Swollman} 39418316Swollman 39518316Swollman 39618316Swollman/* sent do one host 39718316Swollman */ 39818316Swollmanstatic int 39918316Swollmanout(char *host) 40018316Swollman{ 40118316Swollman struct sockaddr_in router; 40218316Swollman struct hostent *hp; 40318316Swollman 40418316Swollman if (gettimeofday(&sent, 0) < 0) { 40518316Swollman perror("gettimeofday(sent)"); 40618316Swollman return -1; 40718316Swollman } 40818316Swollman 40918316Swollman bzero(&router, sizeof(router)); 41018316Swollman router.sin_family = AF_INET; 41118316Swollman#ifdef _HAVE_SIN_LEN 41218316Swollman router.sin_len = sizeof(router); 41318316Swollman#endif 41418316Swollman if (!inet_aton(host, &router.sin_addr)) { 41518316Swollman hp = gethostbyname(host); 41618316Swollman if (hp == 0) { 41718316Swollman herror(host); 41818316Swollman return -1; 41918316Swollman } 42018316Swollman bcopy(hp->h_addr, &router.sin_addr, sizeof(router.sin_addr)); 42118316Swollman } 42218316Swollman router.sin_port = htons(RIP_PORT); 42318316Swollman 42418316Swollman if (sendto(s, &omsg_buf, omsg_len, 0, 42518316Swollman (struct sockaddr *)&router, sizeof(router)) < 0) { 42618316Swollman perror(host); 42718316Swollman return -1; 42818316Swollman } 42918316Swollman 43018316Swollman return 0; 43118316Swollman} 43218316Swollman 43318316Swollman 43418316Swollman/* 43518316Swollman * Handle an incoming RIP packet. 43618316Swollman */ 43718316Swollmanstatic void 43818316Swollmanrip_input(struct sockaddr_in *from, 43918316Swollman int size) 44018316Swollman{ 44118316Swollman struct netinfo *n, *lim; 44218316Swollman struct in_addr in; 44318316Swollman char *name; 44418316Swollman char net_buf[80]; 44518316Swollman u_int mask, dmask; 44618316Swollman char *sp; 44718316Swollman int i; 44818316Swollman struct hostent *hp; 44918316Swollman struct netent *np; 45018316Swollman struct netauth *a; 45118316Swollman 45218316Swollman 45318316Swollman if (nflag) { 45418316Swollman printf("%s:", inet_ntoa(from->sin_addr)); 45518316Swollman } else { 45618316Swollman hp = gethostbyaddr((char*)&from->sin_addr, 45718316Swollman sizeof(struct in_addr), AF_INET); 45818316Swollman if (hp == 0) { 45918316Swollman printf("%s:", 46018316Swollman inet_ntoa(from->sin_addr)); 46118316Swollman } else { 46218316Swollman printf("%s (%s):", hp->h_name, 46318316Swollman inet_ntoa(from->sin_addr)); 46418316Swollman } 46518316Swollman } 46618316Swollman if (IMSG.rip_cmd != RIPCMD_RESPONSE) { 46718316Swollman printf("\n unexpected response type %d\n", IMSG.rip_cmd); 46818316Swollman return; 46918316Swollman } 47018316Swollman printf(" RIPv%d%s %d bytes\n", IMSG.rip_vers, 47118316Swollman (IMSG.rip_vers != RIPv1 && IMSG.rip_vers != RIPv2) ? " ?" : "", 47218316Swollman size); 47318316Swollman if (size > MAXPACKETSIZE) { 47418316Swollman if (size > sizeof(imsg_buf) - sizeof(*n)) { 47518316Swollman printf(" at least %d bytes too long\n", 47618316Swollman size-MAXPACKETSIZE); 47718316Swollman size = sizeof(imsg_buf) - sizeof(*n); 47818316Swollman } else { 47918316Swollman printf(" %d bytes too long\n", 48018316Swollman size-MAXPACKETSIZE); 48118316Swollman } 48218316Swollman } else if (size%sizeof(*n) != sizeof(struct rip)%sizeof(*n)) { 48318316Swollman printf(" response of bad length=%d\n", size); 48418316Swollman } 48518316Swollman 48618316Swollman n = IMSG.rip_nets; 48718316Swollman lim = (struct netinfo *)((char*)n + size) - 1; 48818316Swollman for (; n <= lim; n++) { 48918316Swollman name = ""; 49018316Swollman if (n->n_family == RIP_AF_INET) { 49118316Swollman in.s_addr = n->n_dst; 49218316Swollman (void)strcpy(net_buf, inet_ntoa(in)); 49318316Swollman 49418316Swollman mask = ntohl(n->n_mask); 49518316Swollman dmask = mask & -mask; 49618316Swollman if (mask != 0) { 49718316Swollman sp = &net_buf[strlen(net_buf)]; 49818316Swollman if (IMSG.rip_vers == RIPv1) { 49918316Swollman (void)sprintf(sp," mask=%#x ? ",mask); 50018316Swollman mask = 0; 50118316Swollman } else if (mask + dmask == 0) { 50218316Swollman for (i = 0; 50318316Swollman (i != 32 50418316Swollman && ((1<<i)&mask) == 0); 50518316Swollman i++) 50618316Swollman continue; 50718316Swollman (void)sprintf(sp, "/%d",32-i); 50818316Swollman } else { 50918316Swollman (void)sprintf(sp," (mask %#x)", mask); 51018316Swollman } 51118316Swollman } 51218316Swollman 51318316Swollman if (!nflag) { 51418316Swollman if (mask == 0) { 51518316Swollman mask = std_mask(in.s_addr); 51618316Swollman if ((ntohl(in.s_addr) & ~mask) != 0) 51718316Swollman mask = 0; 51818316Swollman } 51918316Swollman /* Without a netmask, do not worry about 52018316Swollman * whether the destination is a host or a 52118316Swollman * network. Try both and use the first name 52218316Swollman * we get. 52318316Swollman * 52418316Swollman * If we have a netmask we can make a 52518316Swollman * good guess. 52618316Swollman */ 52718316Swollman if ((in.s_addr & ~mask) == 0) { 52818316Swollman np = getnetbyaddr((long)in.s_addr, 52918316Swollman AF_INET); 53018316Swollman if (np != 0) 53118316Swollman name = np->n_name; 53218316Swollman else if (in.s_addr == 0) 53318316Swollman name = "default"; 53418316Swollman } 53518316Swollman if (name[0] == '\0' 53618316Swollman && ((in.s_addr & ~mask) != 0 53718316Swollman || mask == 0xffffffff)) { 53818316Swollman hp = gethostbyaddr((char*)&in, 53918316Swollman sizeof(in), 54018316Swollman AF_INET); 54118316Swollman if (hp != 0) 54218316Swollman name = hp->h_name; 54318316Swollman } 54418316Swollman } 54518316Swollman 54618316Swollman } else if (n->n_family == RIP_AF_AUTH) { 54718316Swollman a = (struct netauth*)n; 54818316Swollman (void)printf(" authentication type %d: ", 54918316Swollman a->a_type); 55018316Swollman for (i = 0; i < sizeof(a->au.au_pw); i++) 55118316Swollman (void)printf("%02x ", a->au.au_pw[i]); 55218316Swollman putc('\n', stdout); 55318316Swollman continue; 55418316Swollman 55518316Swollman } else { 55618316Swollman (void)sprintf(net_buf, "(af %#x) %d.%d.%d.%d", 55718316Swollman ntohs(n->n_family), 55818316Swollman (char)(n->n_dst >> 24), 55918316Swollman (char)(n->n_dst >> 16), 56018316Swollman (char)(n->n_dst >> 8), 56118316Swollman (char)n->n_dst); 56218316Swollman } 56318316Swollman 56418316Swollman (void)printf(" %-18s metric %2d %-10s", 56518316Swollman net_buf, ntohl(n->n_metric), name); 56618316Swollman 56718316Swollman if (n->n_nhop != 0) { 56818316Swollman in.s_addr = n->n_nhop; 56918316Swollman if (nflag) 57018316Swollman hp = 0; 57118316Swollman else 57218316Swollman hp = gethostbyaddr((char*)&in, sizeof(in), 57318316Swollman AF_INET); 57418316Swollman (void)printf(" nhop=%-15s%s", 57518316Swollman (hp != 0) ? hp->h_name : inet_ntoa(in), 57618316Swollman (IMSG.rip_vers == RIPv1) ? " ?" : ""); 57718316Swollman } 57818316Swollman if (n->n_tag != 0) 57918316Swollman (void)printf(" tag=%#x%s", n->n_tag, 58018316Swollman (IMSG.rip_vers == RIPv1) ? " ?" : ""); 58118316Swollman putc('\n', stdout); 58218316Swollman } 58318316Swollman} 58418316Swollman 58518316Swollman 58618316Swollman/* Return the classical netmask for an IP address. 58718316Swollman */ 58818316Swollmanstatic u_int 58918316Swollmanstd_mask(u_int addr) /* in network order */ 59018316Swollman{ 59118316Swollman NTOHL(addr); /* was a host, not a network */ 59218316Swollman 59318316Swollman if (addr == 0) /* default route has mask 0 */ 59418316Swollman return 0; 59518316Swollman if (IN_CLASSA(addr)) 59618316Swollman return IN_CLASSA_NET; 59718316Swollman if (IN_CLASSB(addr)) 59818316Swollman return IN_CLASSB_NET; 59918316Swollman return IN_CLASSC_NET; 60018316Swollman} 60118316Swollman 60218316Swollman 60318316Swollman/* get a network number as a name or a number, with an optional "/xx" 60418316Swollman * netmask. 60518316Swollman */ 60618316Swollmanstatic int /* 0=bad */ 60718316Swollmangetnet(char *name, 60818316Swollman struct netinfo *rt) 60918316Swollman{ 61018316Swollman int i; 61118316Swollman struct netent *nentp; 61218316Swollman u_int mask; 61318316Swollman struct in_addr in; 61418316Swollman char hname[MAXHOSTNAMELEN+1]; 61518316Swollman char *mname, *p; 61618316Swollman 61718316Swollman 61818316Swollman /* Detect and separate "1.2.3.4/24" 61918316Swollman */ 62018316Swollman if (0 != (mname = rindex(name,'/'))) { 62118316Swollman i = (int)(mname - name); 62218316Swollman if (i > sizeof(hname)-1) /* name too long */ 62318316Swollman return 0; 62418316Swollman bcopy(name, hname, i); 62518316Swollman hname[i] = '\0'; 62618316Swollman mname++; 62718316Swollman name = hname; 62818316Swollman } 62918316Swollman 63018316Swollman nentp = getnetbyname(name); 63118316Swollman if (nentp != 0) { 63218316Swollman in.s_addr = nentp->n_net; 63318316Swollman } else if (inet_aton(name, &in) == 1) { 63418316Swollman NTOHL(in.s_addr); 63518316Swollman } else { 63618316Swollman return 0; 63718316Swollman } 63818316Swollman 63918316Swollman if (mname == 0) { 64018316Swollman mask = std_mask(in.s_addr); 64118316Swollman if ((~mask & in.s_addr) != 0) 64218316Swollman mask = 0xffffffff; 64318316Swollman } else { 64418316Swollman mask = (u_int)strtoul(mname, &p, 0); 64518316Swollman if (*p != '\0' || mask > 32) 64618316Swollman return 0; 64718316Swollman mask = 0xffffffff << (32-mask); 64818316Swollman } 64918316Swollman 65018316Swollman rt->n_dst = htonl(in.s_addr); 65118316Swollman rt->n_family = RIP_AF_INET; 65218316Swollman rt->n_mask = htonl(mask); 65318316Swollman return 1; 65418316Swollman} 655