17b6ab19dSGarrett Wollman /*- 27b6ab19dSGarrett Wollman * Copyright (c) 1982, 1986, 1993 37b6ab19dSGarrett Wollman * The Regents of the University of California. All rights reserved. 47b6ab19dSGarrett Wollman * 57b6ab19dSGarrett Wollman * Redistribution and use in source and binary forms, with or without 67b6ab19dSGarrett Wollman * modification, are permitted provided that the following conditions 77b6ab19dSGarrett Wollman * are met: 87b6ab19dSGarrett Wollman * 1. Redistributions of source code must retain the above copyright 97b6ab19dSGarrett Wollman * notice, this list of conditions and the following disclaimer. 107b6ab19dSGarrett Wollman * 2. Redistributions in binary form must reproduce the above copyright 117b6ab19dSGarrett Wollman * notice, this list of conditions and the following disclaimer in the 127b6ab19dSGarrett Wollman * documentation and/or other materials provided with the distribution. 137b6ab19dSGarrett Wollman * 3. All advertising materials mentioning features or use of this software 147b6ab19dSGarrett Wollman * must display the following acknowledgement: 157b6ab19dSGarrett Wollman * This product includes software developed by the University of 167b6ab19dSGarrett Wollman * California, Berkeley and its contributors. 177b6ab19dSGarrett Wollman * 4. Neither the name of the University nor the names of its contributors 187b6ab19dSGarrett Wollman * may be used to endorse or promote products derived from this software 197b6ab19dSGarrett Wollman * without specific prior written permission. 207b6ab19dSGarrett Wollman * 217b6ab19dSGarrett Wollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 227b6ab19dSGarrett Wollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 237b6ab19dSGarrett Wollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 247b6ab19dSGarrett Wollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 257b6ab19dSGarrett Wollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 267b6ab19dSGarrett Wollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 277b6ab19dSGarrett Wollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 287b6ab19dSGarrett Wollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 297b6ab19dSGarrett Wollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 307b6ab19dSGarrett Wollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 317b6ab19dSGarrett Wollman * SUCH DAMAGE. 327b6ab19dSGarrett Wollman */ 337b6ab19dSGarrett Wollman 347b6ab19dSGarrett Wollman char copyright[] = 357b6ab19dSGarrett Wollman "@(#) Copyright (c) 1982, 1986, 1993\n\ 367b6ab19dSGarrett Wollman The Regents of the University of California. All rights reserved.\n"; 377b6ab19dSGarrett Wollman 387b6ab19dSGarrett Wollman #if !defined(lint) && !defined(sgi) && !defined(__NetBSD__) 397b6ab19dSGarrett Wollman static char sccsid[] = "@(#)query.c 8.1 (Berkeley) 6/5/93"; 407b6ab19dSGarrett Wollman #elif defined(__NetBSD__) 417b6ab19dSGarrett Wollman static char rcsid[] = "$NetBSD$"; 427b6ab19dSGarrett Wollman #endif 437b6ab19dSGarrett Wollman 447b6ab19dSGarrett Wollman #include <sys/param.h> 457b6ab19dSGarrett Wollman #include <sys/protosw.h> 467b6ab19dSGarrett Wollman #include <sys/socket.h> 477b6ab19dSGarrett Wollman #include <sys/time.h> 487b6ab19dSGarrett Wollman #include <netinet/in.h> 497b6ab19dSGarrett Wollman #define RIPVERSION RIPv2 507b6ab19dSGarrett Wollman #include <protocols/routed.h> 517b6ab19dSGarrett Wollman #include <arpa/inet.h> 527b6ab19dSGarrett Wollman #include <netdb.h> 537b6ab19dSGarrett Wollman #include <errno.h> 547b6ab19dSGarrett Wollman #include <unistd.h> 557b6ab19dSGarrett Wollman #include <stdio.h> 567b6ab19dSGarrett Wollman #include <stdlib.h> 577b6ab19dSGarrett Wollman #include <string.h> 587b6ab19dSGarrett Wollman #ifdef sgi 597b6ab19dSGarrett Wollman #include <strings.h> 607b6ab19dSGarrett Wollman #include <bstring.h> 617b6ab19dSGarrett Wollman #endif 627b6ab19dSGarrett Wollman 637b6ab19dSGarrett Wollman #ifndef sgi 647b6ab19dSGarrett Wollman #define _HAVE_SIN_LEN 657b6ab19dSGarrett Wollman #endif 667b6ab19dSGarrett Wollman 6752ad6021SGarrett Wollman #include <md5.h> 687b6ab19dSGarrett Wollman #define WTIME 15 /* Time to wait for all responses */ 697b6ab19dSGarrett Wollman #define STIME (250*1000) /* usec to wait for another response */ 707b6ab19dSGarrett Wollman 717b6ab19dSGarrett Wollman int s; 727b6ab19dSGarrett Wollman 737b6ab19dSGarrett Wollman char *pgmname; 747b6ab19dSGarrett Wollman 757b6ab19dSGarrett Wollman union { 767b6ab19dSGarrett Wollman struct rip rip; 777b6ab19dSGarrett Wollman char packet[MAXPACKETSIZE+MAXPATHLEN]; 787b6ab19dSGarrett Wollman } omsg_buf; 797b6ab19dSGarrett Wollman #define OMSG omsg_buf.rip 807b6ab19dSGarrett Wollman int omsg_len = sizeof(struct rip); 817b6ab19dSGarrett Wollman 827b6ab19dSGarrett Wollman union { 837b6ab19dSGarrett Wollman struct rip rip; 847b6ab19dSGarrett Wollman char packet[MAXPACKETSIZE+1024]; 857b6ab19dSGarrett Wollman } imsg_buf; 867b6ab19dSGarrett Wollman #define IMSG imsg_buf.rip 877b6ab19dSGarrett Wollman 887b6ab19dSGarrett Wollman int nflag; /* numbers, no names */ 897b6ab19dSGarrett Wollman int pflag; /* play the `gated` game */ 907b6ab19dSGarrett Wollman int ripv2 = 1; /* use RIP version 2 */ 917b6ab19dSGarrett Wollman int wtime = WTIME; 927b6ab19dSGarrett Wollman int rflag; /* 1=ask about a particular route */ 93d5b718b3SGarrett Wollman int trace, not_trace; /* send trace command or not */ 94d5b718b3SGarrett Wollman int auth_type = RIP_AUTH_NONE; 95d5b718b3SGarrett Wollman char passwd[RIP_AUTH_PW_LEN]; 96d5b718b3SGarrett Wollman u_long keyid; 977b6ab19dSGarrett Wollman 987b6ab19dSGarrett Wollman struct timeval sent; /* when query sent */ 997b6ab19dSGarrett Wollman 1007b6ab19dSGarrett Wollman static void rip_input(struct sockaddr_in*, int); 1017b6ab19dSGarrett Wollman static int out(char *); 1027b6ab19dSGarrett Wollman static void trace_loop(char *argv[]); 1037b6ab19dSGarrett Wollman static void query_loop(char *argv[], int); 1047b6ab19dSGarrett Wollman static int getnet(char *, struct netinfo *); 1057b6ab19dSGarrett Wollman static u_int std_mask(u_int); 106d5b718b3SGarrett Wollman static int parse_quote(char **, char *, char *, char *, int); 1077b6ab19dSGarrett Wollman 1087b6ab19dSGarrett Wollman 109b8186907SGarrett Wollman void 1107b6ab19dSGarrett Wollman main(int argc, 1117b6ab19dSGarrett Wollman char *argv[]) 1127b6ab19dSGarrett Wollman { 1137b6ab19dSGarrett Wollman int ch, bsize; 114d5b718b3SGarrett Wollman char *p, *options, *value, delim; 1157b6ab19dSGarrett Wollman 1167b6ab19dSGarrett Wollman OMSG.rip_nets[0].n_dst = RIP_DEFAULT; 1177b6ab19dSGarrett Wollman OMSG.rip_nets[0].n_family = RIP_AF_UNSPEC; 1187b6ab19dSGarrett Wollman OMSG.rip_nets[0].n_metric = htonl(HOPCNT_INFINITY); 1197b6ab19dSGarrett Wollman 1207b6ab19dSGarrett Wollman pgmname = argv[0]; 1218d64695cSWarner Losh while ((ch = getopt(argc, argv, "np1w:r:t:a:")) != -1) 1227b6ab19dSGarrett Wollman switch (ch) { 1237b6ab19dSGarrett Wollman case 'n': 1247b6ab19dSGarrett Wollman not_trace = 1; 1257b6ab19dSGarrett Wollman nflag = 1; 1267b6ab19dSGarrett Wollman break; 1277b6ab19dSGarrett Wollman 1287b6ab19dSGarrett Wollman case 'p': 1297b6ab19dSGarrett Wollman not_trace = 1; 1307b6ab19dSGarrett Wollman pflag = 1; 1317b6ab19dSGarrett Wollman break; 1327b6ab19dSGarrett Wollman 1337b6ab19dSGarrett Wollman case '1': 1347b6ab19dSGarrett Wollman ripv2 = 0; 1357b6ab19dSGarrett Wollman break; 1367b6ab19dSGarrett Wollman 1377b6ab19dSGarrett Wollman case 'w': 1387b6ab19dSGarrett Wollman not_trace = 1; 1397b6ab19dSGarrett Wollman wtime = (int)strtoul(optarg, &p, 0); 1407b6ab19dSGarrett Wollman if (*p != '\0' 1417b6ab19dSGarrett Wollman || wtime <= 0) 1427b6ab19dSGarrett Wollman goto usage; 1437b6ab19dSGarrett Wollman break; 1447b6ab19dSGarrett Wollman 1457b6ab19dSGarrett Wollman case 'r': 1467b6ab19dSGarrett Wollman not_trace = 1; 1477b6ab19dSGarrett Wollman if (rflag) 1487b6ab19dSGarrett Wollman goto usage; 1497b6ab19dSGarrett Wollman rflag = getnet(optarg, &OMSG.rip_nets[0]); 1507b6ab19dSGarrett Wollman if (!rflag) { 1517b6ab19dSGarrett Wollman struct hostent *hp = gethostbyname(optarg); 1527b6ab19dSGarrett Wollman if (hp == 0) { 1537b6ab19dSGarrett Wollman fprintf(stderr, "%s: %s:", 1547b6ab19dSGarrett Wollman pgmname, optarg); 1557b6ab19dSGarrett Wollman herror(0); 1567b6ab19dSGarrett Wollman exit(1); 1577b6ab19dSGarrett Wollman } 1587b6ab19dSGarrett Wollman bcopy(hp->h_addr, &OMSG.rip_nets[0].n_dst, 1597b6ab19dSGarrett Wollman sizeof(OMSG.rip_nets[0].n_dst)); 1607b6ab19dSGarrett Wollman OMSG.rip_nets[0].n_family = RIP_AF_INET; 1617b6ab19dSGarrett Wollman OMSG.rip_nets[0].n_mask = -1; 1627b6ab19dSGarrett Wollman rflag = 1; 1637b6ab19dSGarrett Wollman } 1647b6ab19dSGarrett Wollman break; 1657b6ab19dSGarrett Wollman 1667b6ab19dSGarrett Wollman case 't': 1677b6ab19dSGarrett Wollman trace = 1; 1687b6ab19dSGarrett Wollman options = optarg; 1697b6ab19dSGarrett Wollman while (*options != '\0') { 1707b6ab19dSGarrett Wollman char *traceopts[] = { 1717b6ab19dSGarrett Wollman # define TRACE_ON 0 1727b6ab19dSGarrett Wollman "on", 1737b6ab19dSGarrett Wollman # define TRACE_MORE 1 1747b6ab19dSGarrett Wollman "more", 1757b6ab19dSGarrett Wollman # define TRACE_OFF 2 1767b6ab19dSGarrett Wollman "off", 1777b6ab19dSGarrett Wollman # define TRACE_DUMP 3 1787b6ab19dSGarrett Wollman "dump", 1797b6ab19dSGarrett Wollman 0 1807b6ab19dSGarrett Wollman }; 1817b6ab19dSGarrett Wollman switch (getsubopt(&options,traceopts,&value)) { 1827b6ab19dSGarrett Wollman case TRACE_ON: 1837b6ab19dSGarrett Wollman OMSG.rip_cmd = RIPCMD_TRACEON; 1847b6ab19dSGarrett Wollman if (!value 1857b6ab19dSGarrett Wollman || strlen(value) > MAXPATHLEN) 1867b6ab19dSGarrett Wollman goto usage; 1877b6ab19dSGarrett Wollman break; 1887b6ab19dSGarrett Wollman case TRACE_MORE: 1897b6ab19dSGarrett Wollman if (value) 1907b6ab19dSGarrett Wollman goto usage; 1917b6ab19dSGarrett Wollman OMSG.rip_cmd = RIPCMD_TRACEON; 1927b6ab19dSGarrett Wollman value = ""; 1937b6ab19dSGarrett Wollman break; 1947b6ab19dSGarrett Wollman case TRACE_OFF: 1957b6ab19dSGarrett Wollman if (value) 1967b6ab19dSGarrett Wollman goto usage; 1977b6ab19dSGarrett Wollman OMSG.rip_cmd = RIPCMD_TRACEOFF; 1987b6ab19dSGarrett Wollman value = ""; 1997b6ab19dSGarrett Wollman break; 2007b6ab19dSGarrett Wollman case TRACE_DUMP: 2017b6ab19dSGarrett Wollman if (value) 2027b6ab19dSGarrett Wollman goto usage; 2037b6ab19dSGarrett Wollman OMSG.rip_cmd = RIPCMD_TRACEON; 2047b6ab19dSGarrett Wollman value = "dump/../table"; 2057b6ab19dSGarrett Wollman break; 2067b6ab19dSGarrett Wollman default: 2077b6ab19dSGarrett Wollman goto usage; 2087b6ab19dSGarrett Wollman } 2097b6ab19dSGarrett Wollman strcpy((char*)OMSG.rip_tracefile, value); 2107b6ab19dSGarrett Wollman omsg_len += strlen(value) - sizeof(OMSG.ripun); 2117b6ab19dSGarrett Wollman } 2127b6ab19dSGarrett Wollman break; 2137b6ab19dSGarrett Wollman 214d5b718b3SGarrett Wollman case 'a': 215d5b718b3SGarrett Wollman not_trace = 1; 216d5b718b3SGarrett Wollman p = strchr(optarg,'='); 217d5b718b3SGarrett Wollman if (!p) 218d5b718b3SGarrett Wollman goto usage; 219d5b718b3SGarrett Wollman *p++ = '\0'; 220d5b718b3SGarrett Wollman if (!strcasecmp("passwd",optarg)) 221d5b718b3SGarrett Wollman auth_type = RIP_AUTH_PW; 222d5b718b3SGarrett Wollman else if (!strcasecmp("md5_passwd",optarg)) 223d5b718b3SGarrett Wollman auth_type = RIP_AUTH_MD5; 224d5b718b3SGarrett Wollman else 225d5b718b3SGarrett Wollman goto usage; 226d5b718b3SGarrett Wollman if (0 > parse_quote(&p,"|",&delim, 227d5b718b3SGarrett Wollman passwd,sizeof(passwd))) 228d5b718b3SGarrett Wollman goto usage; 229d5b718b3SGarrett Wollman if (auth_type == RIP_AUTH_MD5 230d5b718b3SGarrett Wollman && delim == '|') { 231d5b718b3SGarrett Wollman keyid = strtoul(p+1,&p,0); 232d5b718b3SGarrett Wollman if (keyid > 255 || *p != '\0') 233d5b718b3SGarrett Wollman goto usage; 234d5b718b3SGarrett Wollman } else if (delim != '\0') { 235d5b718b3SGarrett Wollman goto usage; 236d5b718b3SGarrett Wollman } 237d5b718b3SGarrett Wollman break; 238d5b718b3SGarrett Wollman 2397b6ab19dSGarrett Wollman default: 2407b6ab19dSGarrett Wollman goto usage; 2417b6ab19dSGarrett Wollman } 2427b6ab19dSGarrett Wollman argv += optind; 2437b6ab19dSGarrett Wollman argc -= optind; 2447b6ab19dSGarrett Wollman if ((not_trace && trace) || argc == 0) { 2457b6ab19dSGarrett Wollman usage: fprintf(stderr, "%s: [-np1v] [-r tgt_rt] [-w wtime]" 246d5b718b3SGarrett Wollman " [-a type=passwd] host1 [host2 ...]\n" 247b8186907SGarrett Wollman "or\t-t {on=filename|more|off|dump}" 248d5b718b3SGarrett Wollman " host1 [host2 ...]\n", 2497b6ab19dSGarrett Wollman pgmname); 2507b6ab19dSGarrett Wollman exit(1); 2517b6ab19dSGarrett Wollman } 2527b6ab19dSGarrett Wollman 2537b6ab19dSGarrett Wollman s = socket(AF_INET, SOCK_DGRAM, 0); 2547b6ab19dSGarrett Wollman if (s < 0) { 2557b6ab19dSGarrett Wollman perror("socket"); 2567b6ab19dSGarrett Wollman exit(2); 2577b6ab19dSGarrett Wollman } 2587b6ab19dSGarrett Wollman 2597b6ab19dSGarrett Wollman /* be prepared to receive a lot of routes */ 2607b6ab19dSGarrett Wollman for (bsize = 127*1024; ; bsize -= 1024) { 2617b6ab19dSGarrett Wollman if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, 2627b6ab19dSGarrett Wollman &bsize, sizeof(bsize)) == 0) 2637b6ab19dSGarrett Wollman break; 2647b6ab19dSGarrett Wollman if (bsize <= 4*1024) { 2657b6ab19dSGarrett Wollman perror("setsockopt SO_RCVBUF"); 2667b6ab19dSGarrett Wollman break; 2677b6ab19dSGarrett Wollman } 2687b6ab19dSGarrett Wollman } 2697b6ab19dSGarrett Wollman 2707b6ab19dSGarrett Wollman if (trace) 2717b6ab19dSGarrett Wollman trace_loop(argv); 2727b6ab19dSGarrett Wollman else 2737b6ab19dSGarrett Wollman query_loop(argv, argc); 2747b6ab19dSGarrett Wollman /* NOTREACHED */ 2757b6ab19dSGarrett Wollman } 2767b6ab19dSGarrett Wollman 2777b6ab19dSGarrett Wollman 2787b6ab19dSGarrett Wollman /* tell the target hosts about tracing 2797b6ab19dSGarrett Wollman */ 2807b6ab19dSGarrett Wollman static void 2817b6ab19dSGarrett Wollman trace_loop(char *argv[]) 2827b6ab19dSGarrett Wollman { 2837b6ab19dSGarrett Wollman struct sockaddr_in myaddr; 2847b6ab19dSGarrett Wollman int res; 2857b6ab19dSGarrett Wollman 2867b6ab19dSGarrett Wollman if (geteuid() != 0) { 2877b6ab19dSGarrett Wollman (void)fprintf(stderr, "-t requires UID 0\n"); 2887b6ab19dSGarrett Wollman exit(1); 2897b6ab19dSGarrett Wollman } 2907b6ab19dSGarrett Wollman 2917b6ab19dSGarrett Wollman if (ripv2) { 2927b6ab19dSGarrett Wollman OMSG.rip_vers = RIPv2; 2937b6ab19dSGarrett Wollman } else { 2947b6ab19dSGarrett Wollman OMSG.rip_vers = RIPv1; 2957b6ab19dSGarrett Wollman } 2967b6ab19dSGarrett Wollman 2977b6ab19dSGarrett Wollman bzero(&myaddr, sizeof(myaddr)); 2987b6ab19dSGarrett Wollman myaddr.sin_family = AF_INET; 2997b6ab19dSGarrett Wollman #ifdef _HAVE_SIN_LEN 3007b6ab19dSGarrett Wollman myaddr.sin_len = sizeof(myaddr); 3017b6ab19dSGarrett Wollman #endif 3027b6ab19dSGarrett Wollman myaddr.sin_port = htons(IPPORT_RESERVED-1); 3037b6ab19dSGarrett Wollman while (bind(s, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { 3047b6ab19dSGarrett Wollman if (errno != EADDRINUSE 3057b6ab19dSGarrett Wollman || myaddr.sin_port == 0) { 3067b6ab19dSGarrett Wollman perror("bind"); 3077b6ab19dSGarrett Wollman exit(2); 3087b6ab19dSGarrett Wollman } 3097b6ab19dSGarrett Wollman myaddr.sin_port = htons(ntohs(myaddr.sin_port)-1); 3107b6ab19dSGarrett Wollman } 3117b6ab19dSGarrett Wollman 3127b6ab19dSGarrett Wollman res = 1; 3137b6ab19dSGarrett Wollman while (*argv != 0) { 3147b6ab19dSGarrett Wollman if (out(*argv++) <= 0) 3157b6ab19dSGarrett Wollman res = 0; 3167b6ab19dSGarrett Wollman } 3177b6ab19dSGarrett Wollman exit(res); 3187b6ab19dSGarrett Wollman } 3197b6ab19dSGarrett Wollman 3207b6ab19dSGarrett Wollman 3217b6ab19dSGarrett Wollman /* query all of the listed hosts 3227b6ab19dSGarrett Wollman */ 3237b6ab19dSGarrett Wollman static void 3247b6ab19dSGarrett Wollman query_loop(char *argv[], int argc) 3257b6ab19dSGarrett Wollman { 326d5b718b3SGarrett Wollman # define NA0 (OMSG.rip_auths[0]) 327d5b718b3SGarrett Wollman # define NA2 (OMSG.rip_auths[2]) 3287b6ab19dSGarrett Wollman struct seen { 3297b6ab19dSGarrett Wollman struct seen *next; 3307b6ab19dSGarrett Wollman struct in_addr addr; 3317b6ab19dSGarrett Wollman } *seen, *sp; 3327b6ab19dSGarrett Wollman int answered = 0; 3337b6ab19dSGarrett Wollman int cc; 3347b6ab19dSGarrett Wollman fd_set bits; 3357b6ab19dSGarrett Wollman struct timeval now, delay; 3367b6ab19dSGarrett Wollman struct sockaddr_in from; 3377b6ab19dSGarrett Wollman int fromlen; 338d5b718b3SGarrett Wollman MD5_CTX md5_ctx; 3397b6ab19dSGarrett Wollman 3407b6ab19dSGarrett Wollman 3417b6ab19dSGarrett Wollman OMSG.rip_cmd = (pflag) ? RIPCMD_POLL : RIPCMD_REQUEST; 3427b6ab19dSGarrett Wollman if (ripv2) { 3437b6ab19dSGarrett Wollman OMSG.rip_vers = RIPv2; 344d5b718b3SGarrett Wollman if (auth_type == RIP_AUTH_PW) { 345d5b718b3SGarrett Wollman OMSG.rip_nets[1] = OMSG.rip_nets[0]; 346d5b718b3SGarrett Wollman NA0.a_family = RIP_AF_AUTH; 347d5b718b3SGarrett Wollman NA0.a_type = RIP_AUTH_PW; 348d5b718b3SGarrett Wollman bcopy(passwd, NA0.au.au_pw, 349d5b718b3SGarrett Wollman RIP_AUTH_PW_LEN); 350d5b718b3SGarrett Wollman omsg_len += sizeof(OMSG.rip_nets[0]); 351d5b718b3SGarrett Wollman 352d5b718b3SGarrett Wollman } else if (auth_type == RIP_AUTH_MD5) { 353d5b718b3SGarrett Wollman OMSG.rip_nets[1] = OMSG.rip_nets[0]; 354d5b718b3SGarrett Wollman NA0.a_family = RIP_AF_AUTH; 355d5b718b3SGarrett Wollman NA0.a_type = RIP_AUTH_MD5; 356d5b718b3SGarrett Wollman NA0.au.a_md5.md5_keyid = (int8_t)keyid; 357d5b718b3SGarrett Wollman NA0.au.a_md5.md5_auth_len = RIP_AUTH_PW_LEN; 358d5b718b3SGarrett Wollman NA0.au.a_md5.md5_seqno = 0; 359d5b718b3SGarrett Wollman NA0.au.a_md5.md5_pkt_len = sizeof(OMSG.rip_nets[1]); 360d5b718b3SGarrett Wollman NA2.a_family = RIP_AF_AUTH; 361d5b718b3SGarrett Wollman NA2.a_type = 1; 362d5b718b3SGarrett Wollman bcopy(passwd, NA2.au.au_pw, sizeof(NA2.au.au_pw)); 363d5b718b3SGarrett Wollman MD5Init(&md5_ctx); 364d5b718b3SGarrett Wollman MD5Update(&md5_ctx, (u_char *)&NA0, 365d5b718b3SGarrett Wollman (char *)(&NA2+1) - (char *)&NA0); 366d5b718b3SGarrett Wollman MD5Final(NA2.au.au_pw, &md5_ctx); 367d5b718b3SGarrett Wollman omsg_len += 2*sizeof(OMSG.rip_nets[0]); 368d5b718b3SGarrett Wollman } 369d5b718b3SGarrett Wollman 3707b6ab19dSGarrett Wollman } else { 3717b6ab19dSGarrett Wollman OMSG.rip_vers = RIPv1; 3727b6ab19dSGarrett Wollman OMSG.rip_nets[0].n_mask = 0; 3737b6ab19dSGarrett Wollman } 3747b6ab19dSGarrett Wollman 3757b6ab19dSGarrett Wollman /* ask the first (valid) host */ 3767b6ab19dSGarrett Wollman seen = 0; 3777b6ab19dSGarrett Wollman while (0 > out(*argv++)) { 3787b6ab19dSGarrett Wollman if (*argv == 0) 3797b6ab19dSGarrett Wollman exit(-1); 3807b6ab19dSGarrett Wollman answered++; 3817b6ab19dSGarrett Wollman } 3827b6ab19dSGarrett Wollman 3837b6ab19dSGarrett Wollman FD_ZERO(&bits); 3847b6ab19dSGarrett Wollman for (;;) { 3857b6ab19dSGarrett Wollman FD_SET(s, &bits); 3867b6ab19dSGarrett Wollman delay.tv_sec = 0; 3877b6ab19dSGarrett Wollman delay.tv_usec = STIME; 3887b6ab19dSGarrett Wollman cc = select(s+1, &bits, 0,0, &delay); 3897b6ab19dSGarrett Wollman if (cc > 0) { 3907b6ab19dSGarrett Wollman fromlen = sizeof(from); 3917b6ab19dSGarrett Wollman cc = recvfrom(s, imsg_buf.packet, 3927b6ab19dSGarrett Wollman sizeof(imsg_buf.packet), 0, 3937b6ab19dSGarrett Wollman (struct sockaddr *)&from, &fromlen); 3947b6ab19dSGarrett Wollman if (cc < 0) { 3957b6ab19dSGarrett Wollman perror("recvfrom"); 3967b6ab19dSGarrett Wollman exit(1); 3977b6ab19dSGarrett Wollman } 3987b6ab19dSGarrett Wollman /* count the distinct responding hosts. 3997b6ab19dSGarrett Wollman * You cannot match responding hosts with 4007b6ab19dSGarrett Wollman * addresses to which queries were transmitted, 4017b6ab19dSGarrett Wollman * because a router might respond with a 4027b6ab19dSGarrett Wollman * different source address. 4037b6ab19dSGarrett Wollman */ 4047b6ab19dSGarrett Wollman for (sp = seen; sp != 0; sp = sp->next) { 4057b6ab19dSGarrett Wollman if (sp->addr.s_addr == from.sin_addr.s_addr) 4067b6ab19dSGarrett Wollman break; 4077b6ab19dSGarrett Wollman } 4087b6ab19dSGarrett Wollman if (sp == 0) { 4097b6ab19dSGarrett Wollman sp = malloc(sizeof(*sp)); 4107b6ab19dSGarrett Wollman sp->addr = from.sin_addr; 4117b6ab19dSGarrett Wollman sp->next = seen; 4127b6ab19dSGarrett Wollman seen = sp; 4137b6ab19dSGarrett Wollman answered++; 4147b6ab19dSGarrett Wollman } 4157b6ab19dSGarrett Wollman 4167b6ab19dSGarrett Wollman rip_input(&from, cc); 4177b6ab19dSGarrett Wollman continue; 4187b6ab19dSGarrett Wollman } 4197b6ab19dSGarrett Wollman 4207b6ab19dSGarrett Wollman if (cc < 0) { 4217b6ab19dSGarrett Wollman if ( errno == EINTR) 4227b6ab19dSGarrett Wollman continue; 4237b6ab19dSGarrett Wollman perror("select"); 4247b6ab19dSGarrett Wollman exit(1); 4257b6ab19dSGarrett Wollman } 4267b6ab19dSGarrett Wollman 4277b6ab19dSGarrett Wollman /* After a pause in responses, probe another host. 4287b6ab19dSGarrett Wollman * This reduces the intermingling of answers. 4297b6ab19dSGarrett Wollman */ 4307b6ab19dSGarrett Wollman while (*argv != 0 && 0 > out(*argv++)) 4317b6ab19dSGarrett Wollman answered++; 4327b6ab19dSGarrett Wollman 4337b6ab19dSGarrett Wollman /* continue until no more packets arrive 4347b6ab19dSGarrett Wollman * or we have heard from all hosts 4357b6ab19dSGarrett Wollman */ 4367b6ab19dSGarrett Wollman if (answered >= argc) 4377b6ab19dSGarrett Wollman break; 4387b6ab19dSGarrett Wollman 4397b6ab19dSGarrett Wollman /* or until we have waited a long time 4407b6ab19dSGarrett Wollman */ 4417b6ab19dSGarrett Wollman if (gettimeofday(&now, 0) < 0) { 4427b6ab19dSGarrett Wollman perror("gettimeofday(now)"); 4437b6ab19dSGarrett Wollman exit(1); 4447b6ab19dSGarrett Wollman } 4457b6ab19dSGarrett Wollman if (sent.tv_sec + wtime <= now.tv_sec) 4467b6ab19dSGarrett Wollman break; 4477b6ab19dSGarrett Wollman } 4487b6ab19dSGarrett Wollman 4497b6ab19dSGarrett Wollman /* fail if there was no answer */ 4507b6ab19dSGarrett Wollman exit (answered >= argc ? 0 : 1); 4517b6ab19dSGarrett Wollman } 4527b6ab19dSGarrett Wollman 4537b6ab19dSGarrett Wollman 454d5b718b3SGarrett Wollman /* send to one host 4557b6ab19dSGarrett Wollman */ 4567b6ab19dSGarrett Wollman static int 4577b6ab19dSGarrett Wollman out(char *host) 4587b6ab19dSGarrett Wollman { 4597b6ab19dSGarrett Wollman struct sockaddr_in router; 4607b6ab19dSGarrett Wollman struct hostent *hp; 4617b6ab19dSGarrett Wollman 4627b6ab19dSGarrett Wollman if (gettimeofday(&sent, 0) < 0) { 4637b6ab19dSGarrett Wollman perror("gettimeofday(sent)"); 4647b6ab19dSGarrett Wollman return -1; 4657b6ab19dSGarrett Wollman } 4667b6ab19dSGarrett Wollman 4677b6ab19dSGarrett Wollman bzero(&router, sizeof(router)); 4687b6ab19dSGarrett Wollman router.sin_family = AF_INET; 4697b6ab19dSGarrett Wollman #ifdef _HAVE_SIN_LEN 4707b6ab19dSGarrett Wollman router.sin_len = sizeof(router); 4717b6ab19dSGarrett Wollman #endif 4727b6ab19dSGarrett Wollman if (!inet_aton(host, &router.sin_addr)) { 4737b6ab19dSGarrett Wollman hp = gethostbyname(host); 4747b6ab19dSGarrett Wollman if (hp == 0) { 4757b6ab19dSGarrett Wollman herror(host); 4767b6ab19dSGarrett Wollman return -1; 4777b6ab19dSGarrett Wollman } 4787b6ab19dSGarrett Wollman bcopy(hp->h_addr, &router.sin_addr, sizeof(router.sin_addr)); 4797b6ab19dSGarrett Wollman } 4807b6ab19dSGarrett Wollman router.sin_port = htons(RIP_PORT); 4817b6ab19dSGarrett Wollman 4827b6ab19dSGarrett Wollman if (sendto(s, &omsg_buf, omsg_len, 0, 4837b6ab19dSGarrett Wollman (struct sockaddr *)&router, sizeof(router)) < 0) { 4847b6ab19dSGarrett Wollman perror(host); 4857b6ab19dSGarrett Wollman return -1; 4867b6ab19dSGarrett Wollman } 4877b6ab19dSGarrett Wollman 4887b6ab19dSGarrett Wollman return 0; 4897b6ab19dSGarrett Wollman } 4907b6ab19dSGarrett Wollman 4917b6ab19dSGarrett Wollman 4927b6ab19dSGarrett Wollman /* 493d5b718b3SGarrett Wollman * Convert string to printable characters 494d5b718b3SGarrett Wollman */ 495d5b718b3SGarrett Wollman static char * 496d5b718b3SGarrett Wollman qstring(u_char *s, int len) 497d5b718b3SGarrett Wollman { 498d5b718b3SGarrett Wollman static char buf[8*20+1]; 499d5b718b3SGarrett Wollman char *p; 500d5b718b3SGarrett Wollman u_char *s2, c; 501d5b718b3SGarrett Wollman 502d5b718b3SGarrett Wollman 503d5b718b3SGarrett Wollman for (p = buf; len != 0 && p < &buf[sizeof(buf)-1]; len--) { 504d5b718b3SGarrett Wollman c = *s++; 505d5b718b3SGarrett Wollman if (c == '\0') { 506d5b718b3SGarrett Wollman for (s2 = s+1; s2 < &s[len]; s2++) { 507d5b718b3SGarrett Wollman if (*s2 != '\0') 508d5b718b3SGarrett Wollman break; 509d5b718b3SGarrett Wollman } 510d5b718b3SGarrett Wollman if (s2 >= &s[len]) 511d5b718b3SGarrett Wollman goto exit; 512d5b718b3SGarrett Wollman } 513d5b718b3SGarrett Wollman 514d5b718b3SGarrett Wollman if (c >= ' ' && c < 0x7f && c != '\\') { 515d5b718b3SGarrett Wollman *p++ = c; 516d5b718b3SGarrett Wollman continue; 517d5b718b3SGarrett Wollman } 518d5b718b3SGarrett Wollman *p++ = '\\'; 519d5b718b3SGarrett Wollman switch (c) { 520d5b718b3SGarrett Wollman case '\\': 521d5b718b3SGarrett Wollman *p++ = '\\'; 522d5b718b3SGarrett Wollman break; 523d5b718b3SGarrett Wollman case '\n': 524d5b718b3SGarrett Wollman *p++= 'n'; 525d5b718b3SGarrett Wollman break; 526d5b718b3SGarrett Wollman case '\r': 527d5b718b3SGarrett Wollman *p++= 'r'; 528d5b718b3SGarrett Wollman break; 529d5b718b3SGarrett Wollman case '\t': 530d5b718b3SGarrett Wollman *p++ = 't'; 531d5b718b3SGarrett Wollman break; 532d5b718b3SGarrett Wollman case '\b': 533d5b718b3SGarrett Wollman *p++ = 'b'; 534d5b718b3SGarrett Wollman break; 535d5b718b3SGarrett Wollman default: 536d5b718b3SGarrett Wollman p += sprintf(p,"%o",c); 537d5b718b3SGarrett Wollman break; 538d5b718b3SGarrett Wollman } 539d5b718b3SGarrett Wollman } 540d5b718b3SGarrett Wollman exit: 541d5b718b3SGarrett Wollman *p = '\0'; 542d5b718b3SGarrett Wollman return buf; 543d5b718b3SGarrett Wollman } 544d5b718b3SGarrett Wollman 545d5b718b3SGarrett Wollman 546d5b718b3SGarrett Wollman /* 5477b6ab19dSGarrett Wollman * Handle an incoming RIP packet. 5487b6ab19dSGarrett Wollman */ 5497b6ab19dSGarrett Wollman static void 5507b6ab19dSGarrett Wollman rip_input(struct sockaddr_in *from, 5517b6ab19dSGarrett Wollman int size) 5527b6ab19dSGarrett Wollman { 5537b6ab19dSGarrett Wollman struct netinfo *n, *lim; 5547b6ab19dSGarrett Wollman struct in_addr in; 5557b6ab19dSGarrett Wollman char *name; 5567b6ab19dSGarrett Wollman char net_buf[80]; 5577b6ab19dSGarrett Wollman u_int mask, dmask; 5587b6ab19dSGarrett Wollman char *sp; 5597b6ab19dSGarrett Wollman int i; 5607b6ab19dSGarrett Wollman struct hostent *hp; 5617b6ab19dSGarrett Wollman struct netent *np; 562d5b718b3SGarrett Wollman struct netauth *na; 5637b6ab19dSGarrett Wollman 5647b6ab19dSGarrett Wollman 5657b6ab19dSGarrett Wollman if (nflag) { 5667b6ab19dSGarrett Wollman printf("%s:", inet_ntoa(from->sin_addr)); 5677b6ab19dSGarrett Wollman } else { 5687b6ab19dSGarrett Wollman hp = gethostbyaddr((char*)&from->sin_addr, 5697b6ab19dSGarrett Wollman sizeof(struct in_addr), AF_INET); 5707b6ab19dSGarrett Wollman if (hp == 0) { 5717b6ab19dSGarrett Wollman printf("%s:", 5727b6ab19dSGarrett Wollman inet_ntoa(from->sin_addr)); 5737b6ab19dSGarrett Wollman } else { 5747b6ab19dSGarrett Wollman printf("%s (%s):", hp->h_name, 5757b6ab19dSGarrett Wollman inet_ntoa(from->sin_addr)); 5767b6ab19dSGarrett Wollman } 5777b6ab19dSGarrett Wollman } 5787b6ab19dSGarrett Wollman if (IMSG.rip_cmd != RIPCMD_RESPONSE) { 5797b6ab19dSGarrett Wollman printf("\n unexpected response type %d\n", IMSG.rip_cmd); 5807b6ab19dSGarrett Wollman return; 5817b6ab19dSGarrett Wollman } 5827b6ab19dSGarrett Wollman printf(" RIPv%d%s %d bytes\n", IMSG.rip_vers, 5837b6ab19dSGarrett Wollman (IMSG.rip_vers != RIPv1 && IMSG.rip_vers != RIPv2) ? " ?" : "", 5847b6ab19dSGarrett Wollman size); 5857b6ab19dSGarrett Wollman if (size > MAXPACKETSIZE) { 5867b6ab19dSGarrett Wollman if (size > sizeof(imsg_buf) - sizeof(*n)) { 5877b6ab19dSGarrett Wollman printf(" at least %d bytes too long\n", 5887b6ab19dSGarrett Wollman size-MAXPACKETSIZE); 5897b6ab19dSGarrett Wollman size = sizeof(imsg_buf) - sizeof(*n); 5907b6ab19dSGarrett Wollman } else { 5917b6ab19dSGarrett Wollman printf(" %d bytes too long\n", 5927b6ab19dSGarrett Wollman size-MAXPACKETSIZE); 5937b6ab19dSGarrett Wollman } 5947b6ab19dSGarrett Wollman } else if (size%sizeof(*n) != sizeof(struct rip)%sizeof(*n)) { 5957b6ab19dSGarrett Wollman printf(" response of bad length=%d\n", size); 5967b6ab19dSGarrett Wollman } 5977b6ab19dSGarrett Wollman 5987b6ab19dSGarrett Wollman n = IMSG.rip_nets; 5997b6ab19dSGarrett Wollman lim = (struct netinfo *)((char*)n + size) - 1; 6007b6ab19dSGarrett Wollman for (; n <= lim; n++) { 6017b6ab19dSGarrett Wollman name = ""; 6027b6ab19dSGarrett Wollman if (n->n_family == RIP_AF_INET) { 6037b6ab19dSGarrett Wollman in.s_addr = n->n_dst; 6047b6ab19dSGarrett Wollman (void)strcpy(net_buf, inet_ntoa(in)); 6057b6ab19dSGarrett Wollman 6067b6ab19dSGarrett Wollman mask = ntohl(n->n_mask); 6077b6ab19dSGarrett Wollman dmask = mask & -mask; 6087b6ab19dSGarrett Wollman if (mask != 0) { 6097b6ab19dSGarrett Wollman sp = &net_buf[strlen(net_buf)]; 6107b6ab19dSGarrett Wollman if (IMSG.rip_vers == RIPv1) { 6117b6ab19dSGarrett Wollman (void)sprintf(sp," mask=%#x ? ",mask); 6127b6ab19dSGarrett Wollman mask = 0; 6137b6ab19dSGarrett Wollman } else if (mask + dmask == 0) { 6147b6ab19dSGarrett Wollman for (i = 0; 6157b6ab19dSGarrett Wollman (i != 32 6167b6ab19dSGarrett Wollman && ((1<<i)&mask) == 0); 6177b6ab19dSGarrett Wollman i++) 6187b6ab19dSGarrett Wollman continue; 6197b6ab19dSGarrett Wollman (void)sprintf(sp, "/%d",32-i); 6207b6ab19dSGarrett Wollman } else { 6217b6ab19dSGarrett Wollman (void)sprintf(sp," (mask %#x)", mask); 6227b6ab19dSGarrett Wollman } 6237b6ab19dSGarrett Wollman } 6247b6ab19dSGarrett Wollman 6257b6ab19dSGarrett Wollman if (!nflag) { 6267b6ab19dSGarrett Wollman if (mask == 0) { 6277b6ab19dSGarrett Wollman mask = std_mask(in.s_addr); 6287b6ab19dSGarrett Wollman if ((ntohl(in.s_addr) & ~mask) != 0) 6297b6ab19dSGarrett Wollman mask = 0; 6307b6ab19dSGarrett Wollman } 6317b6ab19dSGarrett Wollman /* Without a netmask, do not worry about 6327b6ab19dSGarrett Wollman * whether the destination is a host or a 6337b6ab19dSGarrett Wollman * network. Try both and use the first name 6347b6ab19dSGarrett Wollman * we get. 6357b6ab19dSGarrett Wollman * 6367b6ab19dSGarrett Wollman * If we have a netmask we can make a 6377b6ab19dSGarrett Wollman * good guess. 6387b6ab19dSGarrett Wollman */ 6397b6ab19dSGarrett Wollman if ((in.s_addr & ~mask) == 0) { 6407b6ab19dSGarrett Wollman np = getnetbyaddr((long)in.s_addr, 6417b6ab19dSGarrett Wollman AF_INET); 6427b6ab19dSGarrett Wollman if (np != 0) 6437b6ab19dSGarrett Wollman name = np->n_name; 6447b6ab19dSGarrett Wollman else if (in.s_addr == 0) 6457b6ab19dSGarrett Wollman name = "default"; 6467b6ab19dSGarrett Wollman } 6477b6ab19dSGarrett Wollman if (name[0] == '\0' 6487b6ab19dSGarrett Wollman && ((in.s_addr & ~mask) != 0 6497b6ab19dSGarrett Wollman || mask == 0xffffffff)) { 6507b6ab19dSGarrett Wollman hp = gethostbyaddr((char*)&in, 6517b6ab19dSGarrett Wollman sizeof(in), 6527b6ab19dSGarrett Wollman AF_INET); 6537b6ab19dSGarrett Wollman if (hp != 0) 6547b6ab19dSGarrett Wollman name = hp->h_name; 6557b6ab19dSGarrett Wollman } 6567b6ab19dSGarrett Wollman } 6577b6ab19dSGarrett Wollman 6587b6ab19dSGarrett Wollman } else if (n->n_family == RIP_AF_AUTH) { 659d5b718b3SGarrett Wollman na = (struct netauth*)n; 660d5b718b3SGarrett Wollman if (na->a_type == RIP_AUTH_PW 661d5b718b3SGarrett Wollman && n == IMSG.rip_nets) { 662d5b718b3SGarrett Wollman (void)printf(" Password Authentication:" 663d5b718b3SGarrett Wollman " \"%s\"\n", 664d5b718b3SGarrett Wollman qstring(na->au.au_pw, 665d5b718b3SGarrett Wollman RIP_AUTH_PW_LEN)); 666d5b718b3SGarrett Wollman continue; 667d5b718b3SGarrett Wollman } 668d5b718b3SGarrett Wollman 669d5b718b3SGarrett Wollman if (na->a_type == RIP_AUTH_MD5 670d5b718b3SGarrett Wollman && n == IMSG.rip_nets) { 671d5b718b3SGarrett Wollman (void)printf(" MD5 Authentication" 672d5b718b3SGarrett Wollman " len=%d KeyID=%d" 673d5b718b3SGarrett Wollman " seqno=%d" 674d5b718b3SGarrett Wollman " rsvd=%#x,%#x\n", 675d5b718b3SGarrett Wollman na->au.a_md5.md5_pkt_len, 676d5b718b3SGarrett Wollman na->au.a_md5.md5_keyid, 677d5b718b3SGarrett Wollman na->au.a_md5.md5_seqno, 678d5b718b3SGarrett Wollman na->au.a_md5.rsvd[0], 679d5b718b3SGarrett Wollman na->au.a_md5.rsvd[1]); 680d5b718b3SGarrett Wollman continue; 681d5b718b3SGarrett Wollman } 682d5b718b3SGarrett Wollman (void)printf(" Authentication type %d: ", 683d5b718b3SGarrett Wollman ntohs(na->a_type)); 684d5b718b3SGarrett Wollman for (i = 0; i < sizeof(na->au.au_pw); i++) 685d5b718b3SGarrett Wollman (void)printf("%02x ", na->au.au_pw[i]); 6867b6ab19dSGarrett Wollman putc('\n', stdout); 6877b6ab19dSGarrett Wollman continue; 6887b6ab19dSGarrett Wollman 6897b6ab19dSGarrett Wollman } else { 6907b6ab19dSGarrett Wollman (void)sprintf(net_buf, "(af %#x) %d.%d.%d.%d", 6917b6ab19dSGarrett Wollman ntohs(n->n_family), 6927b6ab19dSGarrett Wollman (char)(n->n_dst >> 24), 6937b6ab19dSGarrett Wollman (char)(n->n_dst >> 16), 6947b6ab19dSGarrett Wollman (char)(n->n_dst >> 8), 6957b6ab19dSGarrett Wollman (char)n->n_dst); 6967b6ab19dSGarrett Wollman } 6977b6ab19dSGarrett Wollman 6987b6ab19dSGarrett Wollman (void)printf(" %-18s metric %2d %-10s", 6997b6ab19dSGarrett Wollman net_buf, ntohl(n->n_metric), name); 7007b6ab19dSGarrett Wollman 7017b6ab19dSGarrett Wollman if (n->n_nhop != 0) { 7027b6ab19dSGarrett Wollman in.s_addr = n->n_nhop; 7037b6ab19dSGarrett Wollman if (nflag) 7047b6ab19dSGarrett Wollman hp = 0; 7057b6ab19dSGarrett Wollman else 7067b6ab19dSGarrett Wollman hp = gethostbyaddr((char*)&in, sizeof(in), 7077b6ab19dSGarrett Wollman AF_INET); 7087b6ab19dSGarrett Wollman (void)printf(" nhop=%-15s%s", 7097b6ab19dSGarrett Wollman (hp != 0) ? hp->h_name : inet_ntoa(in), 7107b6ab19dSGarrett Wollman (IMSG.rip_vers == RIPv1) ? " ?" : ""); 7117b6ab19dSGarrett Wollman } 7127b6ab19dSGarrett Wollman if (n->n_tag != 0) 7137b6ab19dSGarrett Wollman (void)printf(" tag=%#x%s", n->n_tag, 7147b6ab19dSGarrett Wollman (IMSG.rip_vers == RIPv1) ? " ?" : ""); 7157b6ab19dSGarrett Wollman putc('\n', stdout); 7167b6ab19dSGarrett Wollman } 7177b6ab19dSGarrett Wollman } 7187b6ab19dSGarrett Wollman 7197b6ab19dSGarrett Wollman 7207b6ab19dSGarrett Wollman /* Return the classical netmask for an IP address. 7217b6ab19dSGarrett Wollman */ 7227b6ab19dSGarrett Wollman static u_int 7237b6ab19dSGarrett Wollman std_mask(u_int addr) /* in network order */ 7247b6ab19dSGarrett Wollman { 7257b6ab19dSGarrett Wollman NTOHL(addr); /* was a host, not a network */ 7267b6ab19dSGarrett Wollman 7277b6ab19dSGarrett Wollman if (addr == 0) /* default route has mask 0 */ 7287b6ab19dSGarrett Wollman return 0; 7297b6ab19dSGarrett Wollman if (IN_CLASSA(addr)) 7307b6ab19dSGarrett Wollman return IN_CLASSA_NET; 7317b6ab19dSGarrett Wollman if (IN_CLASSB(addr)) 7327b6ab19dSGarrett Wollman return IN_CLASSB_NET; 7337b6ab19dSGarrett Wollman return IN_CLASSC_NET; 7347b6ab19dSGarrett Wollman } 7357b6ab19dSGarrett Wollman 7367b6ab19dSGarrett Wollman 7377b6ab19dSGarrett Wollman /* get a network number as a name or a number, with an optional "/xx" 7387b6ab19dSGarrett Wollman * netmask. 7397b6ab19dSGarrett Wollman */ 7407b6ab19dSGarrett Wollman static int /* 0=bad */ 7417b6ab19dSGarrett Wollman getnet(char *name, 7427b6ab19dSGarrett Wollman struct netinfo *rt) 7437b6ab19dSGarrett Wollman { 7447b6ab19dSGarrett Wollman int i; 7457b6ab19dSGarrett Wollman struct netent *nentp; 7467b6ab19dSGarrett Wollman u_int mask; 7477b6ab19dSGarrett Wollman struct in_addr in; 7487b6ab19dSGarrett Wollman char hname[MAXHOSTNAMELEN+1]; 7497b6ab19dSGarrett Wollman char *mname, *p; 7507b6ab19dSGarrett Wollman 7517b6ab19dSGarrett Wollman 7527b6ab19dSGarrett Wollman /* Detect and separate "1.2.3.4/24" 7537b6ab19dSGarrett Wollman */ 7547b6ab19dSGarrett Wollman if (0 != (mname = rindex(name,'/'))) { 7557b6ab19dSGarrett Wollman i = (int)(mname - name); 7567b6ab19dSGarrett Wollman if (i > sizeof(hname)-1) /* name too long */ 7577b6ab19dSGarrett Wollman return 0; 7587b6ab19dSGarrett Wollman bcopy(name, hname, i); 7597b6ab19dSGarrett Wollman hname[i] = '\0'; 7607b6ab19dSGarrett Wollman mname++; 7617b6ab19dSGarrett Wollman name = hname; 7627b6ab19dSGarrett Wollman } 7637b6ab19dSGarrett Wollman 7647b6ab19dSGarrett Wollman nentp = getnetbyname(name); 7657b6ab19dSGarrett Wollman if (nentp != 0) { 7667b6ab19dSGarrett Wollman in.s_addr = nentp->n_net; 7677b6ab19dSGarrett Wollman } else if (inet_aton(name, &in) == 1) { 7687b6ab19dSGarrett Wollman NTOHL(in.s_addr); 7697b6ab19dSGarrett Wollman } else { 7707b6ab19dSGarrett Wollman return 0; 7717b6ab19dSGarrett Wollman } 7727b6ab19dSGarrett Wollman 7737b6ab19dSGarrett Wollman if (mname == 0) { 7747b6ab19dSGarrett Wollman mask = std_mask(in.s_addr); 7757b6ab19dSGarrett Wollman if ((~mask & in.s_addr) != 0) 7767b6ab19dSGarrett Wollman mask = 0xffffffff; 7777b6ab19dSGarrett Wollman } else { 7787b6ab19dSGarrett Wollman mask = (u_int)strtoul(mname, &p, 0); 7797b6ab19dSGarrett Wollman if (*p != '\0' || mask > 32) 7807b6ab19dSGarrett Wollman return 0; 7817b6ab19dSGarrett Wollman mask = 0xffffffff << (32-mask); 7827b6ab19dSGarrett Wollman } 7837b6ab19dSGarrett Wollman 7847b6ab19dSGarrett Wollman rt->n_dst = htonl(in.s_addr); 7857b6ab19dSGarrett Wollman rt->n_family = RIP_AF_INET; 7867b6ab19dSGarrett Wollman rt->n_mask = htonl(mask); 7877b6ab19dSGarrett Wollman return 1; 7887b6ab19dSGarrett Wollman } 789d5b718b3SGarrett Wollman 790d5b718b3SGarrett Wollman 791d5b718b3SGarrett Wollman /* strtok(), but honoring backslash 792d5b718b3SGarrett Wollman */ 793d5b718b3SGarrett Wollman static int /* -1=bad */ 794d5b718b3SGarrett Wollman parse_quote(char **linep, 795d5b718b3SGarrett Wollman char *delims, 796d5b718b3SGarrett Wollman char *delimp, 797d5b718b3SGarrett Wollman char *buf, 798d5b718b3SGarrett Wollman int lim) 799d5b718b3SGarrett Wollman { 800d5b718b3SGarrett Wollman char c, *pc, *p; 801d5b718b3SGarrett Wollman 802d5b718b3SGarrett Wollman 803d5b718b3SGarrett Wollman pc = *linep; 804d5b718b3SGarrett Wollman if (*pc == '\0') 805d5b718b3SGarrett Wollman return -1; 806d5b718b3SGarrett Wollman 807d5b718b3SGarrett Wollman for (;;) { 808d5b718b3SGarrett Wollman if (lim == 0) 809d5b718b3SGarrett Wollman return -1; 810d5b718b3SGarrett Wollman c = *pc++; 811d5b718b3SGarrett Wollman if (c == '\0') 812d5b718b3SGarrett Wollman break; 813d5b718b3SGarrett Wollman 814d5b718b3SGarrett Wollman if (c == '\\' && pc != '\0') { 815d5b718b3SGarrett Wollman if ((c = *pc++) == 'n') { 816d5b718b3SGarrett Wollman c = '\n'; 817d5b718b3SGarrett Wollman } else if (c == 'r') { 818d5b718b3SGarrett Wollman c = '\r'; 819d5b718b3SGarrett Wollman } else if (c == 't') { 820d5b718b3SGarrett Wollman c = '\t'; 821d5b718b3SGarrett Wollman } else if (c == 'b') { 822d5b718b3SGarrett Wollman c = '\b'; 823d5b718b3SGarrett Wollman } else if (c >= '0' && c <= '7') { 824d5b718b3SGarrett Wollman c -= '0'; 825d5b718b3SGarrett Wollman if (*pc >= '0' && *pc <= '7') { 826d5b718b3SGarrett Wollman c = (c<<3)+(*pc++ - '0'); 827d5b718b3SGarrett Wollman if (*pc >= '0' && *pc <= '7') 828d5b718b3SGarrett Wollman c = (c<<3)+(*pc++ - '0'); 829d5b718b3SGarrett Wollman } 830d5b718b3SGarrett Wollman } 831d5b718b3SGarrett Wollman 832d5b718b3SGarrett Wollman } else { 833d5b718b3SGarrett Wollman for (p = delims; *p != '\0'; ++p) { 834d5b718b3SGarrett Wollman if (*p == c) 835d5b718b3SGarrett Wollman goto exit; 836d5b718b3SGarrett Wollman } 837d5b718b3SGarrett Wollman } 838d5b718b3SGarrett Wollman 839d5b718b3SGarrett Wollman *buf++ = c; 840d5b718b3SGarrett Wollman --lim; 841d5b718b3SGarrett Wollman } 842d5b718b3SGarrett Wollman exit: 843d5b718b3SGarrett Wollman if (delimp != 0) 844d5b718b3SGarrett Wollman *delimp = c; 845d5b718b3SGarrett Wollman *linep = pc-1; 846d5b718b3SGarrett Wollman if (lim != 0) 847d5b718b3SGarrett Wollman *buf = '\0'; 848d5b718b3SGarrett Wollman return 0; 849d5b718b3SGarrett Wollman } 850