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 3469036300SPhilippe Charnier #ifndef lint 3569036300SPhilippe Charnier static const char copyright[] = 367b6ab19dSGarrett Wollman "@(#) Copyright (c) 1982, 1986, 1993\n\ 377b6ab19dSGarrett Wollman The Regents of the University of California. All rights reserved.\n"; 3869036300SPhilippe Charnier #endif /* not lint */ 397b6ab19dSGarrett Wollman 4069036300SPhilippe Charnier #ifndef lint 4169036300SPhilippe Charnier #if 0 427b6ab19dSGarrett Wollman static char sccsid[] = "@(#)query.c 8.1 (Berkeley) 6/5/93"; 437b6ab19dSGarrett Wollman #endif 4469036300SPhilippe Charnier static const char rcsid[] = 456f48600eSPoul-Henning Kamp "$Id: rtquery.c,v 1.7 1998/01/14 07:17:12 charnier Exp $"; 4669036300SPhilippe Charnier #endif /* not lint */ 477b6ab19dSGarrett Wollman 487b6ab19dSGarrett Wollman #include <sys/param.h> 497b6ab19dSGarrett Wollman #include <sys/socket.h> 507b6ab19dSGarrett Wollman #include <sys/time.h> 517b6ab19dSGarrett Wollman #include <netinet/in.h> 527b6ab19dSGarrett Wollman #define RIPVERSION RIPv2 537b6ab19dSGarrett Wollman #include <protocols/routed.h> 547b6ab19dSGarrett Wollman #include <arpa/inet.h> 5569036300SPhilippe Charnier #include <err.h> 567b6ab19dSGarrett Wollman #include <errno.h> 5769036300SPhilippe Charnier #include <netdb.h> 587b6ab19dSGarrett Wollman #include <stdio.h> 597b6ab19dSGarrett Wollman #include <stdlib.h> 607b6ab19dSGarrett Wollman #include <string.h> 6169036300SPhilippe Charnier #include <unistd.h> 627b6ab19dSGarrett Wollman #ifdef sgi 637b6ab19dSGarrett Wollman #include <strings.h> 647b6ab19dSGarrett Wollman #include <bstring.h> 657b6ab19dSGarrett Wollman #endif 667b6ab19dSGarrett Wollman 677b6ab19dSGarrett Wollman #ifndef sgi 687b6ab19dSGarrett Wollman #define _HAVE_SIN_LEN 697b6ab19dSGarrett Wollman #endif 707b6ab19dSGarrett Wollman 7152ad6021SGarrett Wollman #include <md5.h> 727b6ab19dSGarrett Wollman #define WTIME 15 /* Time to wait for all responses */ 737b6ab19dSGarrett Wollman #define STIME (250*1000) /* usec to wait for another response */ 747b6ab19dSGarrett Wollman 757b6ab19dSGarrett Wollman int s; 767b6ab19dSGarrett Wollman 777b6ab19dSGarrett Wollman union { 787b6ab19dSGarrett Wollman struct rip rip; 797b6ab19dSGarrett Wollman char packet[MAXPACKETSIZE+MAXPATHLEN]; 807b6ab19dSGarrett Wollman } omsg_buf; 817b6ab19dSGarrett Wollman #define OMSG omsg_buf.rip 827b6ab19dSGarrett Wollman int omsg_len = sizeof(struct rip); 837b6ab19dSGarrett Wollman 847b6ab19dSGarrett Wollman union { 857b6ab19dSGarrett Wollman struct rip rip; 867b6ab19dSGarrett Wollman char packet[MAXPACKETSIZE+1024]; 877b6ab19dSGarrett Wollman } imsg_buf; 887b6ab19dSGarrett Wollman #define IMSG imsg_buf.rip 897b6ab19dSGarrett Wollman 907b6ab19dSGarrett Wollman int nflag; /* numbers, no names */ 917b6ab19dSGarrett Wollman int pflag; /* play the `gated` game */ 927b6ab19dSGarrett Wollman int ripv2 = 1; /* use RIP version 2 */ 937b6ab19dSGarrett Wollman int wtime = WTIME; 947b6ab19dSGarrett Wollman int rflag; /* 1=ask about a particular route */ 95d5b718b3SGarrett Wollman int trace, not_trace; /* send trace command or not */ 96d5b718b3SGarrett Wollman int auth_type = RIP_AUTH_NONE; 97d5b718b3SGarrett Wollman char passwd[RIP_AUTH_PW_LEN]; 98d5b718b3SGarrett Wollman u_long keyid; 997b6ab19dSGarrett Wollman 1007b6ab19dSGarrett Wollman struct timeval sent; /* when query sent */ 1017b6ab19dSGarrett Wollman 1027b6ab19dSGarrett Wollman static void rip_input(struct sockaddr_in*, int); 1037b6ab19dSGarrett Wollman static int out(char *); 1047b6ab19dSGarrett Wollman static void trace_loop(char *argv[]); 1057b6ab19dSGarrett Wollman static void query_loop(char *argv[], int); 1067b6ab19dSGarrett Wollman static int getnet(char *, struct netinfo *); 1077b6ab19dSGarrett Wollman static u_int std_mask(u_int); 108d5b718b3SGarrett Wollman static int parse_quote(char **, char *, char *, char *, int); 1097b6ab19dSGarrett Wollman 1107b6ab19dSGarrett Wollman 111b8186907SGarrett Wollman void 1127b6ab19dSGarrett Wollman main(int argc, 1137b6ab19dSGarrett Wollman char *argv[]) 1147b6ab19dSGarrett Wollman { 1157b6ab19dSGarrett Wollman int ch, bsize; 116d5b718b3SGarrett Wollman char *p, *options, *value, delim; 1177b6ab19dSGarrett Wollman 1187b6ab19dSGarrett Wollman OMSG.rip_nets[0].n_dst = RIP_DEFAULT; 1197b6ab19dSGarrett Wollman OMSG.rip_nets[0].n_family = RIP_AF_UNSPEC; 1207b6ab19dSGarrett Wollman OMSG.rip_nets[0].n_metric = htonl(HOPCNT_INFINITY); 1217b6ab19dSGarrett Wollman 1228d64695cSWarner Losh while ((ch = getopt(argc, argv, "np1w:r:t:a:")) != -1) 1237b6ab19dSGarrett Wollman switch (ch) { 1247b6ab19dSGarrett Wollman case 'n': 1257b6ab19dSGarrett Wollman not_trace = 1; 1267b6ab19dSGarrett Wollman nflag = 1; 1277b6ab19dSGarrett Wollman break; 1287b6ab19dSGarrett Wollman 1297b6ab19dSGarrett Wollman case 'p': 1307b6ab19dSGarrett Wollman not_trace = 1; 1317b6ab19dSGarrett Wollman pflag = 1; 1327b6ab19dSGarrett Wollman break; 1337b6ab19dSGarrett Wollman 1347b6ab19dSGarrett Wollman case '1': 1357b6ab19dSGarrett Wollman ripv2 = 0; 1367b6ab19dSGarrett Wollman break; 1377b6ab19dSGarrett Wollman 1387b6ab19dSGarrett Wollman case 'w': 1397b6ab19dSGarrett Wollman not_trace = 1; 1407b6ab19dSGarrett Wollman wtime = (int)strtoul(optarg, &p, 0); 1417b6ab19dSGarrett Wollman if (*p != '\0' 1427b6ab19dSGarrett Wollman || wtime <= 0) 1437b6ab19dSGarrett Wollman goto usage; 1447b6ab19dSGarrett Wollman break; 1457b6ab19dSGarrett Wollman 1467b6ab19dSGarrett Wollman case 'r': 1477b6ab19dSGarrett Wollman not_trace = 1; 1487b6ab19dSGarrett Wollman if (rflag) 1497b6ab19dSGarrett Wollman goto usage; 1507b6ab19dSGarrett Wollman rflag = getnet(optarg, &OMSG.rip_nets[0]); 1517b6ab19dSGarrett Wollman if (!rflag) { 1527b6ab19dSGarrett Wollman struct hostent *hp = gethostbyname(optarg); 1537b6ab19dSGarrett Wollman if (hp == 0) { 1547766b145SPhilippe Charnier fprintf(stderr, "rtquery: %s:", 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) { 2457766b145SPhilippe Charnier usage: fprintf(stderr, "%s\n%s\n", 2467766b145SPhilippe Charnier "usage: rtquery [-np1v] [-r addr] [-w timeout] [-a secret] host ...", 2477766b145SPhilippe Charnier " rtquery [-t op] host ..."); 2487b6ab19dSGarrett Wollman exit(1); 2497b6ab19dSGarrett Wollman } 2507b6ab19dSGarrett Wollman 2517b6ab19dSGarrett Wollman s = socket(AF_INET, SOCK_DGRAM, 0); 25269036300SPhilippe Charnier if (s < 0) 25369036300SPhilippe Charnier err(2, "socket"); 2547b6ab19dSGarrett Wollman 2557b6ab19dSGarrett Wollman /* be prepared to receive a lot of routes */ 2567b6ab19dSGarrett Wollman for (bsize = 127*1024; ; bsize -= 1024) { 2577b6ab19dSGarrett Wollman if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, 2587b6ab19dSGarrett Wollman &bsize, sizeof(bsize)) == 0) 2597b6ab19dSGarrett Wollman break; 2607b6ab19dSGarrett Wollman if (bsize <= 4*1024) { 26169036300SPhilippe Charnier warn("setsockopt SO_RCVBUF"); 2627b6ab19dSGarrett Wollman break; 2637b6ab19dSGarrett Wollman } 2647b6ab19dSGarrett Wollman } 2657b6ab19dSGarrett Wollman 2667b6ab19dSGarrett Wollman if (trace) 2677b6ab19dSGarrett Wollman trace_loop(argv); 2687b6ab19dSGarrett Wollman else 2697b6ab19dSGarrett Wollman query_loop(argv, argc); 2707b6ab19dSGarrett Wollman /* NOTREACHED */ 2717b6ab19dSGarrett Wollman } 2727b6ab19dSGarrett Wollman 2737b6ab19dSGarrett Wollman 2747b6ab19dSGarrett Wollman /* tell the target hosts about tracing 2757b6ab19dSGarrett Wollman */ 2767b6ab19dSGarrett Wollman static void 2777b6ab19dSGarrett Wollman trace_loop(char *argv[]) 2787b6ab19dSGarrett Wollman { 2797b6ab19dSGarrett Wollman struct sockaddr_in myaddr; 2807b6ab19dSGarrett Wollman int res; 2817b6ab19dSGarrett Wollman 28269036300SPhilippe Charnier if (geteuid() != 0) 28369036300SPhilippe Charnier errx(1, "-t requires UID 0"); 2847b6ab19dSGarrett Wollman 2857b6ab19dSGarrett Wollman if (ripv2) { 2867b6ab19dSGarrett Wollman OMSG.rip_vers = RIPv2; 2877b6ab19dSGarrett Wollman } else { 2887b6ab19dSGarrett Wollman OMSG.rip_vers = RIPv1; 2897b6ab19dSGarrett Wollman } 2907b6ab19dSGarrett Wollman 2917b6ab19dSGarrett Wollman bzero(&myaddr, sizeof(myaddr)); 2927b6ab19dSGarrett Wollman myaddr.sin_family = AF_INET; 2937b6ab19dSGarrett Wollman #ifdef _HAVE_SIN_LEN 2947b6ab19dSGarrett Wollman myaddr.sin_len = sizeof(myaddr); 2957b6ab19dSGarrett Wollman #endif 2967b6ab19dSGarrett Wollman myaddr.sin_port = htons(IPPORT_RESERVED-1); 2977b6ab19dSGarrett Wollman while (bind(s, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) { 29869036300SPhilippe Charnier if (errno != EADDRINUSE || myaddr.sin_port == 0) 29969036300SPhilippe Charnier err(2, "bind"); 3007b6ab19dSGarrett Wollman myaddr.sin_port = htons(ntohs(myaddr.sin_port)-1); 3017b6ab19dSGarrett Wollman } 3027b6ab19dSGarrett Wollman 3037b6ab19dSGarrett Wollman res = 1; 3047b6ab19dSGarrett Wollman while (*argv != 0) { 3057b6ab19dSGarrett Wollman if (out(*argv++) <= 0) 3067b6ab19dSGarrett Wollman res = 0; 3077b6ab19dSGarrett Wollman } 3087b6ab19dSGarrett Wollman exit(res); 3097b6ab19dSGarrett Wollman } 3107b6ab19dSGarrett Wollman 3117b6ab19dSGarrett Wollman 3127b6ab19dSGarrett Wollman /* query all of the listed hosts 3137b6ab19dSGarrett Wollman */ 3147b6ab19dSGarrett Wollman static void 3157b6ab19dSGarrett Wollman query_loop(char *argv[], int argc) 3167b6ab19dSGarrett Wollman { 317d5b718b3SGarrett Wollman # define NA0 (OMSG.rip_auths[0]) 318d5b718b3SGarrett Wollman # define NA2 (OMSG.rip_auths[2]) 3197b6ab19dSGarrett Wollman struct seen { 3207b6ab19dSGarrett Wollman struct seen *next; 3217b6ab19dSGarrett Wollman struct in_addr addr; 3227b6ab19dSGarrett Wollman } *seen, *sp; 3237b6ab19dSGarrett Wollman int answered = 0; 3247b6ab19dSGarrett Wollman int cc; 3257b6ab19dSGarrett Wollman fd_set bits; 3267b6ab19dSGarrett Wollman struct timeval now, delay; 3277b6ab19dSGarrett Wollman struct sockaddr_in from; 3287b6ab19dSGarrett Wollman int fromlen; 329d5b718b3SGarrett Wollman MD5_CTX md5_ctx; 3307b6ab19dSGarrett Wollman 3317b6ab19dSGarrett Wollman 3327b6ab19dSGarrett Wollman OMSG.rip_cmd = (pflag) ? RIPCMD_POLL : RIPCMD_REQUEST; 3337b6ab19dSGarrett Wollman if (ripv2) { 3347b6ab19dSGarrett Wollman OMSG.rip_vers = RIPv2; 335d5b718b3SGarrett Wollman if (auth_type == RIP_AUTH_PW) { 336d5b718b3SGarrett Wollman OMSG.rip_nets[1] = OMSG.rip_nets[0]; 337d5b718b3SGarrett Wollman NA0.a_family = RIP_AF_AUTH; 338d5b718b3SGarrett Wollman NA0.a_type = RIP_AUTH_PW; 339d5b718b3SGarrett Wollman bcopy(passwd, NA0.au.au_pw, 340d5b718b3SGarrett Wollman RIP_AUTH_PW_LEN); 341d5b718b3SGarrett Wollman omsg_len += sizeof(OMSG.rip_nets[0]); 342d5b718b3SGarrett Wollman 343d5b718b3SGarrett Wollman } else if (auth_type == RIP_AUTH_MD5) { 344d5b718b3SGarrett Wollman OMSG.rip_nets[1] = OMSG.rip_nets[0]; 345d5b718b3SGarrett Wollman NA0.a_family = RIP_AF_AUTH; 346d5b718b3SGarrett Wollman NA0.a_type = RIP_AUTH_MD5; 347d5b718b3SGarrett Wollman NA0.au.a_md5.md5_keyid = (int8_t)keyid; 348d5b718b3SGarrett Wollman NA0.au.a_md5.md5_auth_len = RIP_AUTH_PW_LEN; 349d5b718b3SGarrett Wollman NA0.au.a_md5.md5_seqno = 0; 350d5b718b3SGarrett Wollman NA0.au.a_md5.md5_pkt_len = sizeof(OMSG.rip_nets[1]); 351d5b718b3SGarrett Wollman NA2.a_family = RIP_AF_AUTH; 352d5b718b3SGarrett Wollman NA2.a_type = 1; 353d5b718b3SGarrett Wollman bcopy(passwd, NA2.au.au_pw, sizeof(NA2.au.au_pw)); 354d5b718b3SGarrett Wollman MD5Init(&md5_ctx); 355d5b718b3SGarrett Wollman MD5Update(&md5_ctx, (u_char *)&NA0, 356d5b718b3SGarrett Wollman (char *)(&NA2+1) - (char *)&NA0); 357d5b718b3SGarrett Wollman MD5Final(NA2.au.au_pw, &md5_ctx); 358d5b718b3SGarrett Wollman omsg_len += 2*sizeof(OMSG.rip_nets[0]); 359d5b718b3SGarrett Wollman } 360d5b718b3SGarrett Wollman 3617b6ab19dSGarrett Wollman } else { 3627b6ab19dSGarrett Wollman OMSG.rip_vers = RIPv1; 3637b6ab19dSGarrett Wollman OMSG.rip_nets[0].n_mask = 0; 3647b6ab19dSGarrett Wollman } 3657b6ab19dSGarrett Wollman 3667b6ab19dSGarrett Wollman /* ask the first (valid) host */ 3677b6ab19dSGarrett Wollman seen = 0; 3687b6ab19dSGarrett Wollman while (0 > out(*argv++)) { 3697b6ab19dSGarrett Wollman if (*argv == 0) 37069036300SPhilippe Charnier exit(1); 3717b6ab19dSGarrett Wollman answered++; 3727b6ab19dSGarrett Wollman } 3737b6ab19dSGarrett Wollman 3747b6ab19dSGarrett Wollman FD_ZERO(&bits); 3757b6ab19dSGarrett Wollman for (;;) { 3767b6ab19dSGarrett Wollman FD_SET(s, &bits); 3777b6ab19dSGarrett Wollman delay.tv_sec = 0; 3787b6ab19dSGarrett Wollman delay.tv_usec = STIME; 3797b6ab19dSGarrett Wollman cc = select(s+1, &bits, 0,0, &delay); 3807b6ab19dSGarrett Wollman if (cc > 0) { 3817b6ab19dSGarrett Wollman fromlen = sizeof(from); 3827b6ab19dSGarrett Wollman cc = recvfrom(s, imsg_buf.packet, 3837b6ab19dSGarrett Wollman sizeof(imsg_buf.packet), 0, 3847b6ab19dSGarrett Wollman (struct sockaddr *)&from, &fromlen); 38569036300SPhilippe Charnier if (cc < 0) 38669036300SPhilippe Charnier err(1, "recvfrom"); 3877b6ab19dSGarrett Wollman /* count the distinct responding hosts. 3887b6ab19dSGarrett Wollman * You cannot match responding hosts with 3897b6ab19dSGarrett Wollman * addresses to which queries were transmitted, 3907b6ab19dSGarrett Wollman * because a router might respond with a 3917b6ab19dSGarrett Wollman * different source address. 3927b6ab19dSGarrett Wollman */ 3937b6ab19dSGarrett Wollman for (sp = seen; sp != 0; sp = sp->next) { 3947b6ab19dSGarrett Wollman if (sp->addr.s_addr == from.sin_addr.s_addr) 3957b6ab19dSGarrett Wollman break; 3967b6ab19dSGarrett Wollman } 3977b6ab19dSGarrett Wollman if (sp == 0) { 3987b6ab19dSGarrett Wollman sp = malloc(sizeof(*sp)); 3997b6ab19dSGarrett Wollman sp->addr = from.sin_addr; 4007b6ab19dSGarrett Wollman sp->next = seen; 4017b6ab19dSGarrett Wollman seen = sp; 4027b6ab19dSGarrett Wollman answered++; 4037b6ab19dSGarrett Wollman } 4047b6ab19dSGarrett Wollman 4057b6ab19dSGarrett Wollman rip_input(&from, cc); 4067b6ab19dSGarrett Wollman continue; 4077b6ab19dSGarrett Wollman } 4087b6ab19dSGarrett Wollman 4097b6ab19dSGarrett Wollman if (cc < 0) { 4107b6ab19dSGarrett Wollman if (errno == EINTR) 4117b6ab19dSGarrett Wollman continue; 41269036300SPhilippe Charnier err(1, "select"); 4137b6ab19dSGarrett Wollman } 4147b6ab19dSGarrett Wollman 4157b6ab19dSGarrett Wollman /* After a pause in responses, probe another host. 4167b6ab19dSGarrett Wollman * This reduces the intermingling of answers. 4177b6ab19dSGarrett Wollman */ 4187b6ab19dSGarrett Wollman while (*argv != 0 && 0 > out(*argv++)) 4197b6ab19dSGarrett Wollman answered++; 4207b6ab19dSGarrett Wollman 4217b6ab19dSGarrett Wollman /* continue until no more packets arrive 4227b6ab19dSGarrett Wollman * or we have heard from all hosts 4237b6ab19dSGarrett Wollman */ 4247b6ab19dSGarrett Wollman if (answered >= argc) 4257b6ab19dSGarrett Wollman break; 4267b6ab19dSGarrett Wollman 4277b6ab19dSGarrett Wollman /* or until we have waited a long time 4287b6ab19dSGarrett Wollman */ 42969036300SPhilippe Charnier if (gettimeofday(&now, 0) < 0) 43069036300SPhilippe Charnier err(1, "gettimeofday(now)"); 4317b6ab19dSGarrett Wollman if (sent.tv_sec + wtime <= now.tv_sec) 4327b6ab19dSGarrett Wollman break; 4337b6ab19dSGarrett Wollman } 4347b6ab19dSGarrett Wollman 4357b6ab19dSGarrett Wollman /* fail if there was no answer */ 4367b6ab19dSGarrett Wollman exit (answered >= argc ? 0 : 1); 4377b6ab19dSGarrett Wollman } 4387b6ab19dSGarrett Wollman 4397b6ab19dSGarrett Wollman 440d5b718b3SGarrett Wollman /* send to one host 4417b6ab19dSGarrett Wollman */ 4427b6ab19dSGarrett Wollman static int 4437b6ab19dSGarrett Wollman out(char *host) 4447b6ab19dSGarrett Wollman { 4457b6ab19dSGarrett Wollman struct sockaddr_in router; 4467b6ab19dSGarrett Wollman struct hostent *hp; 4477b6ab19dSGarrett Wollman 4487b6ab19dSGarrett Wollman if (gettimeofday(&sent, 0) < 0) { 44969036300SPhilippe Charnier warn("gettimeofday(sent)"); 4507b6ab19dSGarrett Wollman return -1; 4517b6ab19dSGarrett Wollman } 4527b6ab19dSGarrett Wollman 4537b6ab19dSGarrett Wollman bzero(&router, sizeof(router)); 4547b6ab19dSGarrett Wollman router.sin_family = AF_INET; 4557b6ab19dSGarrett Wollman #ifdef _HAVE_SIN_LEN 4567b6ab19dSGarrett Wollman router.sin_len = sizeof(router); 4577b6ab19dSGarrett Wollman #endif 4587b6ab19dSGarrett Wollman if (!inet_aton(host, &router.sin_addr)) { 4597b6ab19dSGarrett Wollman hp = gethostbyname(host); 4607b6ab19dSGarrett Wollman if (hp == 0) { 4617b6ab19dSGarrett Wollman herror(host); 4627b6ab19dSGarrett Wollman return -1; 4637b6ab19dSGarrett Wollman } 4647b6ab19dSGarrett Wollman bcopy(hp->h_addr, &router.sin_addr, sizeof(router.sin_addr)); 4657b6ab19dSGarrett Wollman } 4667b6ab19dSGarrett Wollman router.sin_port = htons(RIP_PORT); 4677b6ab19dSGarrett Wollman 4687b6ab19dSGarrett Wollman if (sendto(s, &omsg_buf, omsg_len, 0, 4697b6ab19dSGarrett Wollman (struct sockaddr *)&router, sizeof(router)) < 0) { 47069036300SPhilippe Charnier warn("%s", host); 4717b6ab19dSGarrett Wollman return -1; 4727b6ab19dSGarrett Wollman } 4737b6ab19dSGarrett Wollman 4747b6ab19dSGarrett Wollman return 0; 4757b6ab19dSGarrett Wollman } 4767b6ab19dSGarrett Wollman 4777b6ab19dSGarrett Wollman 4787b6ab19dSGarrett Wollman /* 479d5b718b3SGarrett Wollman * Convert string to printable characters 480d5b718b3SGarrett Wollman */ 481d5b718b3SGarrett Wollman static char * 482d5b718b3SGarrett Wollman qstring(u_char *s, int len) 483d5b718b3SGarrett Wollman { 484d5b718b3SGarrett Wollman static char buf[8*20+1]; 485d5b718b3SGarrett Wollman char *p; 486d5b718b3SGarrett Wollman u_char *s2, c; 487d5b718b3SGarrett Wollman 488d5b718b3SGarrett Wollman 489d5b718b3SGarrett Wollman for (p = buf; len != 0 && p < &buf[sizeof(buf)-1]; len--) { 490d5b718b3SGarrett Wollman c = *s++; 491d5b718b3SGarrett Wollman if (c == '\0') { 492d5b718b3SGarrett Wollman for (s2 = s+1; s2 < &s[len]; s2++) { 493d5b718b3SGarrett Wollman if (*s2 != '\0') 494d5b718b3SGarrett Wollman break; 495d5b718b3SGarrett Wollman } 496d5b718b3SGarrett Wollman if (s2 >= &s[len]) 497d5b718b3SGarrett Wollman goto exit; 498d5b718b3SGarrett Wollman } 499d5b718b3SGarrett Wollman 500d5b718b3SGarrett Wollman if (c >= ' ' && c < 0x7f && c != '\\') { 501d5b718b3SGarrett Wollman *p++ = c; 502d5b718b3SGarrett Wollman continue; 503d5b718b3SGarrett Wollman } 504d5b718b3SGarrett Wollman *p++ = '\\'; 505d5b718b3SGarrett Wollman switch (c) { 506d5b718b3SGarrett Wollman case '\\': 507d5b718b3SGarrett Wollman *p++ = '\\'; 508d5b718b3SGarrett Wollman break; 509d5b718b3SGarrett Wollman case '\n': 510d5b718b3SGarrett Wollman *p++= 'n'; 511d5b718b3SGarrett Wollman break; 512d5b718b3SGarrett Wollman case '\r': 513d5b718b3SGarrett Wollman *p++= 'r'; 514d5b718b3SGarrett Wollman break; 515d5b718b3SGarrett Wollman case '\t': 516d5b718b3SGarrett Wollman *p++ = 't'; 517d5b718b3SGarrett Wollman break; 518d5b718b3SGarrett Wollman case '\b': 519d5b718b3SGarrett Wollman *p++ = 'b'; 520d5b718b3SGarrett Wollman break; 521d5b718b3SGarrett Wollman default: 522d5b718b3SGarrett Wollman p += sprintf(p,"%o",c); 523d5b718b3SGarrett Wollman break; 524d5b718b3SGarrett Wollman } 525d5b718b3SGarrett Wollman } 526d5b718b3SGarrett Wollman exit: 527d5b718b3SGarrett Wollman *p = '\0'; 528d5b718b3SGarrett Wollman return buf; 529d5b718b3SGarrett Wollman } 530d5b718b3SGarrett Wollman 531d5b718b3SGarrett Wollman 532d5b718b3SGarrett Wollman /* 5337b6ab19dSGarrett Wollman * Handle an incoming RIP packet. 5347b6ab19dSGarrett Wollman */ 5357b6ab19dSGarrett Wollman static void 5367b6ab19dSGarrett Wollman rip_input(struct sockaddr_in *from, 5377b6ab19dSGarrett Wollman int size) 5387b6ab19dSGarrett Wollman { 5397b6ab19dSGarrett Wollman struct netinfo *n, *lim; 5407b6ab19dSGarrett Wollman struct in_addr in; 5417b6ab19dSGarrett Wollman char *name; 5427b6ab19dSGarrett Wollman char net_buf[80]; 5437b6ab19dSGarrett Wollman u_int mask, dmask; 5447b6ab19dSGarrett Wollman char *sp; 5457b6ab19dSGarrett Wollman int i; 5467b6ab19dSGarrett Wollman struct hostent *hp; 5477b6ab19dSGarrett Wollman struct netent *np; 548d5b718b3SGarrett Wollman struct netauth *na; 5497b6ab19dSGarrett Wollman 5507b6ab19dSGarrett Wollman 5517b6ab19dSGarrett Wollman if (nflag) { 5527b6ab19dSGarrett Wollman printf("%s:", inet_ntoa(from->sin_addr)); 5537b6ab19dSGarrett Wollman } else { 5547b6ab19dSGarrett Wollman hp = gethostbyaddr((char*)&from->sin_addr, 5557b6ab19dSGarrett Wollman sizeof(struct in_addr), AF_INET); 5567b6ab19dSGarrett Wollman if (hp == 0) { 5577b6ab19dSGarrett Wollman printf("%s:", 5587b6ab19dSGarrett Wollman inet_ntoa(from->sin_addr)); 5597b6ab19dSGarrett Wollman } else { 5607b6ab19dSGarrett Wollman printf("%s (%s):", hp->h_name, 5617b6ab19dSGarrett Wollman inet_ntoa(from->sin_addr)); 5627b6ab19dSGarrett Wollman } 5637b6ab19dSGarrett Wollman } 5647b6ab19dSGarrett Wollman if (IMSG.rip_cmd != RIPCMD_RESPONSE) { 5657b6ab19dSGarrett Wollman printf("\n unexpected response type %d\n", IMSG.rip_cmd); 5667b6ab19dSGarrett Wollman return; 5677b6ab19dSGarrett Wollman } 5687b6ab19dSGarrett Wollman printf(" RIPv%d%s %d bytes\n", IMSG.rip_vers, 5697b6ab19dSGarrett Wollman (IMSG.rip_vers != RIPv1 && IMSG.rip_vers != RIPv2) ? " ?" : "", 5707b6ab19dSGarrett Wollman size); 5717b6ab19dSGarrett Wollman if (size > MAXPACKETSIZE) { 5727b6ab19dSGarrett Wollman if (size > sizeof(imsg_buf) - sizeof(*n)) { 5737b6ab19dSGarrett Wollman printf(" at least %d bytes too long\n", 5747b6ab19dSGarrett Wollman size-MAXPACKETSIZE); 5757b6ab19dSGarrett Wollman size = sizeof(imsg_buf) - sizeof(*n); 5767b6ab19dSGarrett Wollman } else { 5777b6ab19dSGarrett Wollman printf(" %d bytes too long\n", 5787b6ab19dSGarrett Wollman size-MAXPACKETSIZE); 5797b6ab19dSGarrett Wollman } 5807b6ab19dSGarrett Wollman } else if (size%sizeof(*n) != sizeof(struct rip)%sizeof(*n)) { 5817b6ab19dSGarrett Wollman printf(" response of bad length=%d\n", size); 5827b6ab19dSGarrett Wollman } 5837b6ab19dSGarrett Wollman 5847b6ab19dSGarrett Wollman n = IMSG.rip_nets; 5857b6ab19dSGarrett Wollman lim = (struct netinfo *)((char*)n + size) - 1; 5867b6ab19dSGarrett Wollman for (; n <= lim; n++) { 5877b6ab19dSGarrett Wollman name = ""; 5887b6ab19dSGarrett Wollman if (n->n_family == RIP_AF_INET) { 5897b6ab19dSGarrett Wollman in.s_addr = n->n_dst; 5907b6ab19dSGarrett Wollman (void)strcpy(net_buf, inet_ntoa(in)); 5917b6ab19dSGarrett Wollman 5927b6ab19dSGarrett Wollman mask = ntohl(n->n_mask); 5937b6ab19dSGarrett Wollman dmask = mask & -mask; 5947b6ab19dSGarrett Wollman if (mask != 0) { 5957b6ab19dSGarrett Wollman sp = &net_buf[strlen(net_buf)]; 5967b6ab19dSGarrett Wollman if (IMSG.rip_vers == RIPv1) { 5977b6ab19dSGarrett Wollman (void)sprintf(sp," mask=%#x ? ",mask); 5987b6ab19dSGarrett Wollman mask = 0; 5997b6ab19dSGarrett Wollman } else if (mask + dmask == 0) { 6007b6ab19dSGarrett Wollman for (i = 0; 6017b6ab19dSGarrett Wollman (i != 32 6027b6ab19dSGarrett Wollman && ((1<<i)&mask) == 0); 6037b6ab19dSGarrett Wollman i++) 6047b6ab19dSGarrett Wollman continue; 6057b6ab19dSGarrett Wollman (void)sprintf(sp, "/%d",32-i); 6067b6ab19dSGarrett Wollman } else { 6077b6ab19dSGarrett Wollman (void)sprintf(sp," (mask %#x)", mask); 6087b6ab19dSGarrett Wollman } 6097b6ab19dSGarrett Wollman } 6107b6ab19dSGarrett Wollman 6117b6ab19dSGarrett Wollman if (!nflag) { 6127b6ab19dSGarrett Wollman if (mask == 0) { 6137b6ab19dSGarrett Wollman mask = std_mask(in.s_addr); 6147b6ab19dSGarrett Wollman if ((ntohl(in.s_addr) & ~mask) != 0) 6157b6ab19dSGarrett Wollman mask = 0; 6167b6ab19dSGarrett Wollman } 6177b6ab19dSGarrett Wollman /* Without a netmask, do not worry about 6187b6ab19dSGarrett Wollman * whether the destination is a host or a 6197b6ab19dSGarrett Wollman * network. Try both and use the first name 6207b6ab19dSGarrett Wollman * we get. 6217b6ab19dSGarrett Wollman * 6227b6ab19dSGarrett Wollman * If we have a netmask we can make a 6237b6ab19dSGarrett Wollman * good guess. 6247b6ab19dSGarrett Wollman */ 6257b6ab19dSGarrett Wollman if ((in.s_addr & ~mask) == 0) { 6267b6ab19dSGarrett Wollman np = getnetbyaddr((long)in.s_addr, 6277b6ab19dSGarrett Wollman AF_INET); 6287b6ab19dSGarrett Wollman if (np != 0) 6297b6ab19dSGarrett Wollman name = np->n_name; 6307b6ab19dSGarrett Wollman else if (in.s_addr == 0) 6317b6ab19dSGarrett Wollman name = "default"; 6327b6ab19dSGarrett Wollman } 6337b6ab19dSGarrett Wollman if (name[0] == '\0' 6347b6ab19dSGarrett Wollman && ((in.s_addr & ~mask) != 0 6357b6ab19dSGarrett Wollman || mask == 0xffffffff)) { 6367b6ab19dSGarrett Wollman hp = gethostbyaddr((char*)&in, 6377b6ab19dSGarrett Wollman sizeof(in), 6387b6ab19dSGarrett Wollman AF_INET); 6397b6ab19dSGarrett Wollman if (hp != 0) 6407b6ab19dSGarrett Wollman name = hp->h_name; 6417b6ab19dSGarrett Wollman } 6427b6ab19dSGarrett Wollman } 6437b6ab19dSGarrett Wollman 6447b6ab19dSGarrett Wollman } else if (n->n_family == RIP_AF_AUTH) { 645d5b718b3SGarrett Wollman na = (struct netauth*)n; 646d5b718b3SGarrett Wollman if (na->a_type == RIP_AUTH_PW 647d5b718b3SGarrett Wollman && n == IMSG.rip_nets) { 648d5b718b3SGarrett Wollman (void)printf(" Password Authentication:" 649d5b718b3SGarrett Wollman " \"%s\"\n", 650d5b718b3SGarrett Wollman qstring(na->au.au_pw, 651d5b718b3SGarrett Wollman RIP_AUTH_PW_LEN)); 652d5b718b3SGarrett Wollman continue; 653d5b718b3SGarrett Wollman } 654d5b718b3SGarrett Wollman 655d5b718b3SGarrett Wollman if (na->a_type == RIP_AUTH_MD5 656d5b718b3SGarrett Wollman && n == IMSG.rip_nets) { 657d5b718b3SGarrett Wollman (void)printf(" MD5 Authentication" 658d5b718b3SGarrett Wollman " len=%d KeyID=%d" 659d5b718b3SGarrett Wollman " seqno=%d" 660d5b718b3SGarrett Wollman " rsvd=%#x,%#x\n", 661d5b718b3SGarrett Wollman na->au.a_md5.md5_pkt_len, 662d5b718b3SGarrett Wollman na->au.a_md5.md5_keyid, 663d5b718b3SGarrett Wollman na->au.a_md5.md5_seqno, 664d5b718b3SGarrett Wollman na->au.a_md5.rsvd[0], 665d5b718b3SGarrett Wollman na->au.a_md5.rsvd[1]); 666d5b718b3SGarrett Wollman continue; 667d5b718b3SGarrett Wollman } 668d5b718b3SGarrett Wollman (void)printf(" Authentication type %d: ", 669d5b718b3SGarrett Wollman ntohs(na->a_type)); 670d5b718b3SGarrett Wollman for (i = 0; i < sizeof(na->au.au_pw); i++) 671d5b718b3SGarrett Wollman (void)printf("%02x ", na->au.au_pw[i]); 6727b6ab19dSGarrett Wollman putc('\n', stdout); 6737b6ab19dSGarrett Wollman continue; 6747b6ab19dSGarrett Wollman 6757b6ab19dSGarrett Wollman } else { 6767b6ab19dSGarrett Wollman (void)sprintf(net_buf, "(af %#x) %d.%d.%d.%d", 6777b6ab19dSGarrett Wollman ntohs(n->n_family), 6787b6ab19dSGarrett Wollman (char)(n->n_dst >> 24), 6797b6ab19dSGarrett Wollman (char)(n->n_dst >> 16), 6807b6ab19dSGarrett Wollman (char)(n->n_dst >> 8), 6817b6ab19dSGarrett Wollman (char)n->n_dst); 6827b6ab19dSGarrett Wollman } 6837b6ab19dSGarrett Wollman 6847b6ab19dSGarrett Wollman (void)printf(" %-18s metric %2d %-10s", 6857b6ab19dSGarrett Wollman net_buf, ntohl(n->n_metric), name); 6867b6ab19dSGarrett Wollman 6877b6ab19dSGarrett Wollman if (n->n_nhop != 0) { 6887b6ab19dSGarrett Wollman in.s_addr = n->n_nhop; 6897b6ab19dSGarrett Wollman if (nflag) 6907b6ab19dSGarrett Wollman hp = 0; 6917b6ab19dSGarrett Wollman else 6927b6ab19dSGarrett Wollman hp = gethostbyaddr((char*)&in, sizeof(in), 6937b6ab19dSGarrett Wollman AF_INET); 6947b6ab19dSGarrett Wollman (void)printf(" nhop=%-15s%s", 6957b6ab19dSGarrett Wollman (hp != 0) ? hp->h_name : inet_ntoa(in), 6967b6ab19dSGarrett Wollman (IMSG.rip_vers == RIPv1) ? " ?" : ""); 6977b6ab19dSGarrett Wollman } 6987b6ab19dSGarrett Wollman if (n->n_tag != 0) 6997b6ab19dSGarrett Wollman (void)printf(" tag=%#x%s", n->n_tag, 7007b6ab19dSGarrett Wollman (IMSG.rip_vers == RIPv1) ? " ?" : ""); 7017b6ab19dSGarrett Wollman putc('\n', stdout); 7027b6ab19dSGarrett Wollman } 7037b6ab19dSGarrett Wollman } 7047b6ab19dSGarrett Wollman 7057b6ab19dSGarrett Wollman 7067b6ab19dSGarrett Wollman /* Return the classical netmask for an IP address. 7077b6ab19dSGarrett Wollman */ 7087b6ab19dSGarrett Wollman static u_int 7097b6ab19dSGarrett Wollman std_mask(u_int addr) /* in network order */ 7107b6ab19dSGarrett Wollman { 7117b6ab19dSGarrett Wollman NTOHL(addr); /* was a host, not a network */ 7127b6ab19dSGarrett Wollman 7137b6ab19dSGarrett Wollman if (addr == 0) /* default route has mask 0 */ 7147b6ab19dSGarrett Wollman return 0; 7157b6ab19dSGarrett Wollman if (IN_CLASSA(addr)) 7167b6ab19dSGarrett Wollman return IN_CLASSA_NET; 7177b6ab19dSGarrett Wollman if (IN_CLASSB(addr)) 7187b6ab19dSGarrett Wollman return IN_CLASSB_NET; 7197b6ab19dSGarrett Wollman return IN_CLASSC_NET; 7207b6ab19dSGarrett Wollman } 7217b6ab19dSGarrett Wollman 7227b6ab19dSGarrett Wollman 7237b6ab19dSGarrett Wollman /* get a network number as a name or a number, with an optional "/xx" 7247b6ab19dSGarrett Wollman * netmask. 7257b6ab19dSGarrett Wollman */ 7267b6ab19dSGarrett Wollman static int /* 0=bad */ 7277b6ab19dSGarrett Wollman getnet(char *name, 7287b6ab19dSGarrett Wollman struct netinfo *rt) 7297b6ab19dSGarrett Wollman { 7307b6ab19dSGarrett Wollman int i; 7317b6ab19dSGarrett Wollman struct netent *nentp; 7327b6ab19dSGarrett Wollman u_int mask; 7337b6ab19dSGarrett Wollman struct in_addr in; 7347b6ab19dSGarrett Wollman char hname[MAXHOSTNAMELEN+1]; 7357b6ab19dSGarrett Wollman char *mname, *p; 7367b6ab19dSGarrett Wollman 7377b6ab19dSGarrett Wollman 7387b6ab19dSGarrett Wollman /* Detect and separate "1.2.3.4/24" 7397b6ab19dSGarrett Wollman */ 7407b6ab19dSGarrett Wollman if (0 != (mname = rindex(name,'/'))) { 7417b6ab19dSGarrett Wollman i = (int)(mname - name); 7427b6ab19dSGarrett Wollman if (i > sizeof(hname)-1) /* name too long */ 7437b6ab19dSGarrett Wollman return 0; 7447b6ab19dSGarrett Wollman bcopy(name, hname, i); 7457b6ab19dSGarrett Wollman hname[i] = '\0'; 7467b6ab19dSGarrett Wollman mname++; 7477b6ab19dSGarrett Wollman name = hname; 7487b6ab19dSGarrett Wollman } 7497b6ab19dSGarrett Wollman 7507b6ab19dSGarrett Wollman nentp = getnetbyname(name); 7517b6ab19dSGarrett Wollman if (nentp != 0) { 7527b6ab19dSGarrett Wollman in.s_addr = nentp->n_net; 7537b6ab19dSGarrett Wollman } else if (inet_aton(name, &in) == 1) { 7547b6ab19dSGarrett Wollman NTOHL(in.s_addr); 7557b6ab19dSGarrett Wollman } else { 7567b6ab19dSGarrett Wollman return 0; 7577b6ab19dSGarrett Wollman } 7587b6ab19dSGarrett Wollman 7597b6ab19dSGarrett Wollman if (mname == 0) { 7607b6ab19dSGarrett Wollman mask = std_mask(in.s_addr); 7617b6ab19dSGarrett Wollman if ((~mask & in.s_addr) != 0) 7627b6ab19dSGarrett Wollman mask = 0xffffffff; 7637b6ab19dSGarrett Wollman } else { 7647b6ab19dSGarrett Wollman mask = (u_int)strtoul(mname, &p, 0); 7657b6ab19dSGarrett Wollman if (*p != '\0' || mask > 32) 7667b6ab19dSGarrett Wollman return 0; 7677b6ab19dSGarrett Wollman mask = 0xffffffff << (32-mask); 7687b6ab19dSGarrett Wollman } 7697b6ab19dSGarrett Wollman 7707b6ab19dSGarrett Wollman rt->n_dst = htonl(in.s_addr); 7717b6ab19dSGarrett Wollman rt->n_family = RIP_AF_INET; 7727b6ab19dSGarrett Wollman rt->n_mask = htonl(mask); 7737b6ab19dSGarrett Wollman return 1; 7747b6ab19dSGarrett Wollman } 775d5b718b3SGarrett Wollman 776d5b718b3SGarrett Wollman 777d5b718b3SGarrett Wollman /* strtok(), but honoring backslash 778d5b718b3SGarrett Wollman */ 779d5b718b3SGarrett Wollman static int /* -1=bad */ 780d5b718b3SGarrett Wollman parse_quote(char **linep, 781d5b718b3SGarrett Wollman char *delims, 782d5b718b3SGarrett Wollman char *delimp, 783d5b718b3SGarrett Wollman char *buf, 784d5b718b3SGarrett Wollman int lim) 785d5b718b3SGarrett Wollman { 786d5b718b3SGarrett Wollman char c, *pc, *p; 787d5b718b3SGarrett Wollman 788d5b718b3SGarrett Wollman 789d5b718b3SGarrett Wollman pc = *linep; 790d5b718b3SGarrett Wollman if (*pc == '\0') 791d5b718b3SGarrett Wollman return -1; 792d5b718b3SGarrett Wollman 793d5b718b3SGarrett Wollman for (;;) { 794d5b718b3SGarrett Wollman if (lim == 0) 795d5b718b3SGarrett Wollman return -1; 796d5b718b3SGarrett Wollman c = *pc++; 797d5b718b3SGarrett Wollman if (c == '\0') 798d5b718b3SGarrett Wollman break; 799d5b718b3SGarrett Wollman 8006f48600eSPoul-Henning Kamp if (c == '\\' && *pc != '\0') { 801d5b718b3SGarrett Wollman if ((c = *pc++) == 'n') { 802d5b718b3SGarrett Wollman c = '\n'; 803d5b718b3SGarrett Wollman } else if (c == 'r') { 804d5b718b3SGarrett Wollman c = '\r'; 805d5b718b3SGarrett Wollman } else if (c == 't') { 806d5b718b3SGarrett Wollman c = '\t'; 807d5b718b3SGarrett Wollman } else if (c == 'b') { 808d5b718b3SGarrett Wollman c = '\b'; 809d5b718b3SGarrett Wollman } else if (c >= '0' && c <= '7') { 810d5b718b3SGarrett Wollman c -= '0'; 811d5b718b3SGarrett Wollman if (*pc >= '0' && *pc <= '7') { 812d5b718b3SGarrett Wollman c = (c<<3)+(*pc++ - '0'); 813d5b718b3SGarrett Wollman if (*pc >= '0' && *pc <= '7') 814d5b718b3SGarrett Wollman c = (c<<3)+(*pc++ - '0'); 815d5b718b3SGarrett Wollman } 816d5b718b3SGarrett Wollman } 817d5b718b3SGarrett Wollman 818d5b718b3SGarrett Wollman } else { 819d5b718b3SGarrett Wollman for (p = delims; *p != '\0'; ++p) { 820d5b718b3SGarrett Wollman if (*p == c) 821d5b718b3SGarrett Wollman goto exit; 822d5b718b3SGarrett Wollman } 823d5b718b3SGarrett Wollman } 824d5b718b3SGarrett Wollman 825d5b718b3SGarrett Wollman *buf++ = c; 826d5b718b3SGarrett Wollman --lim; 827d5b718b3SGarrett Wollman } 828d5b718b3SGarrett Wollman exit: 829d5b718b3SGarrett Wollman if (delimp != 0) 830d5b718b3SGarrett Wollman *delimp = c; 831d5b718b3SGarrett Wollman *linep = pc-1; 832d5b718b3SGarrett Wollman if (lim != 0) 833d5b718b3SGarrett Wollman *buf = '\0'; 834d5b718b3SGarrett Wollman return 0; 835d5b718b3SGarrett Wollman } 836