route.c revision 47668
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1983, 1989, 1991, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 3. All advertising materials mentioning features or use of this software 141558Srgrimes * must display the following acknowledgement: 151558Srgrimes * This product includes software developed by the University of 161558Srgrimes * California, Berkeley and its contributors. 171558Srgrimes * 4. Neither the name of the University nor the names of its contributors 181558Srgrimes * may be used to endorse or promote products derived from this software 191558Srgrimes * without specific prior written permission. 201558Srgrimes * 211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311558Srgrimes * SUCH DAMAGE. 321558Srgrimes */ 331558Srgrimes 341558Srgrimes#ifndef lint 3513171Swollmanstatic const char copyright[] = 361558Srgrimes"@(#) Copyright (c) 1983, 1989, 1991, 1993\n\ 371558Srgrimes The Regents of the University of California. All rights reserved.\n"; 381558Srgrimes#endif /* not lint */ 391558Srgrimes 401558Srgrimes#ifndef lint 4137907Scharnier#if 0 421558Srgrimesstatic char sccsid[] = "@(#)route.c 8.3 (Berkeley) 3/19/94"; 4337907Scharnier#endif 4413171Swollmanstatic const char rcsid[] = 4547668Sru "$Id: route.c,v 1.29 1998/07/28 06:25:35 charnier Exp $"; 461558Srgrimes#endif /* not lint */ 471558Srgrimes 481558Srgrimes#include <sys/param.h> 491558Srgrimes#include <sys/file.h> 501558Srgrimes#include <sys/socket.h> 511558Srgrimes#include <sys/ioctl.h> 521558Srgrimes#include <sys/sysctl.h> 531558Srgrimes 541558Srgrimes#include <net/if.h> 551558Srgrimes#include <net/route.h> 561558Srgrimes#include <net/if_dl.h> 571558Srgrimes#include <netinet/in.h> 5817046Sjulian#include <netatalk/at.h> 5914092Swollman#ifdef NS 601558Srgrimes#include <netns/ns.h> 6114092Swollman#endif 621558Srgrimes#include <arpa/inet.h> 631558Srgrimes#include <netdb.h> 641558Srgrimes 6520287Swollman#include <ctype.h> 6620287Swollman#include <err.h> 671558Srgrimes#include <errno.h> 681558Srgrimes#include <stdio.h> 691558Srgrimes#include <stdlib.h> 701558Srgrimes#include <string.h> 7113171Swollman#include <sysexits.h> 7220287Swollman#include <unistd.h> 731558Srgrimes 741558Srgrimesstruct keytab { 751558Srgrimes char *kt_cp; 761558Srgrimes int kt_i; 771558Srgrimes} keywords[] = { 781558Srgrimes#include "keywords.h" 791558Srgrimes {0, 0} 801558Srgrimes}; 811558Srgrimes 821558Srgrimesstruct ortentry route; 831558Srgrimesunion sockunion { 841558Srgrimes struct sockaddr sa; 851558Srgrimes struct sockaddr_in sin; 8617046Sjulian struct sockaddr_at sat; 8714092Swollman#ifdef NS 881558Srgrimes struct sockaddr_ns sns; 8914092Swollman#endif 901558Srgrimes struct sockaddr_dl sdl; 911558Srgrimes} so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp; 921558Srgrimes 931558Srgrimestypedef union sockunion *sup; 941558Srgrimesint pid, rtm_addrs, uid; 951558Srgrimesint s; 961558Srgrimesint forcehost, forcenet, doflush, nflag, af, qflag, tflag, keyword(); 971558Srgrimesint iflag, verbose, aflen = sizeof (struct sockaddr_in); 981558Srgrimesint locking, lockrest, debugonly; 991558Srgrimesstruct rt_metrics rt_metrics; 1001558Srgrimesu_long rtm_inits; 1011558Srgrimesstruct in_addr inet_makeaddr(); 10217046Sjulianint atalk_aton __P((const char *, struct at_addr *)); 10317046Sjulianchar *atalk_ntoa __P((struct at_addr)); 1041558Srgrimeschar *routename(), *netname(); 1051558Srgrimesvoid flushroutes(), newroute(), monitor(), sockaddr(), sodump(), bprintf(); 1061558Srgrimesvoid print_getmsg(), print_rtmsg(), pmsg_common(), pmsg_addrs(), mask_addr(); 1071558Srgrimesint getaddr(), rtmsg(), x25_makemask(); 1081558Srgrimesextern char *inet_ntoa(), *iso_ntoa(), *link_ntoa(); 1091558Srgrimes 11018286Sbdevoid usage __P((const char *)) __dead2; 11113171Swollman 11218286Sbdevoid 1131558Srgrimesusage(cp) 11413171Swollman const char *cp; 1151558Srgrimes{ 1161558Srgrimes if (cp) 11713171Swollman warnx("bad keyword: %s", cp); 1181558Srgrimes (void) fprintf(stderr, 11937907Scharnier "usage: route [-dnqtv] command [[modifiers] args]\n"); 12013171Swollman exit(EX_USAGE); 1211558Srgrimes /* NOTREACHED */ 1221558Srgrimes} 1231558Srgrimes 1241558Srgrimes#define ROUNDUP(a) \ 1251558Srgrimes ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 1261558Srgrimes#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 1271558Srgrimes 1281558Srgrimesint 1291558Srgrimesmain(argc, argv) 1301558Srgrimes int argc; 1311558Srgrimes char **argv; 1321558Srgrimes{ 1331558Srgrimes int ch; 1341558Srgrimes 1351558Srgrimes if (argc < 2) 1361558Srgrimes usage((char *)NULL); 1371558Srgrimes 13837907Scharnier while ((ch = getopt(argc, argv, "nqdtv")) != -1) 1391558Srgrimes switch(ch) { 1401558Srgrimes case 'n': 1411558Srgrimes nflag = 1; 1421558Srgrimes break; 1431558Srgrimes case 'q': 1441558Srgrimes qflag = 1; 1451558Srgrimes break; 1461558Srgrimes case 'v': 1471558Srgrimes verbose = 1; 1481558Srgrimes break; 1491558Srgrimes case 't': 1501558Srgrimes tflag = 1; 1511558Srgrimes break; 1521558Srgrimes case 'd': 1531558Srgrimes debugonly = 1; 1541558Srgrimes break; 1551558Srgrimes case '?': 1561558Srgrimes default: 1571558Srgrimes usage((char *)NULL); 1581558Srgrimes } 1591558Srgrimes argc -= optind; 1601558Srgrimes argv += optind; 1611558Srgrimes 1621558Srgrimes pid = getpid(); 1631558Srgrimes uid = getuid(); 1641558Srgrimes if (tflag) 1651558Srgrimes s = open("/dev/null", O_WRONLY, 0); 1661558Srgrimes else 1671558Srgrimes s = socket(PF_ROUTE, SOCK_RAW, 0); 1681558Srgrimes if (s < 0) 16913171Swollman err(EX_OSERR, "socket"); 17019209Sfenner setuid(uid); 1711558Srgrimes if (*argv) 1721558Srgrimes switch (keyword(*argv)) { 1731558Srgrimes case K_GET: 1741558Srgrimes uid = 0; 1751558Srgrimes /* FALLTHROUGH */ 1761558Srgrimes 1771558Srgrimes case K_CHANGE: 1781558Srgrimes case K_ADD: 1791558Srgrimes case K_DELETE: 1801558Srgrimes newroute(argc, argv); 1811558Srgrimes exit(0); 1821558Srgrimes /* NOTREACHED */ 1831558Srgrimes 1841558Srgrimes case K_MONITOR: 1851558Srgrimes monitor(); 1861558Srgrimes /* NOTREACHED */ 1871558Srgrimes 1881558Srgrimes case K_FLUSH: 1891558Srgrimes flushroutes(argc, argv); 1901558Srgrimes exit(0); 1911558Srgrimes /* NOTREACHED */ 1921558Srgrimes } 1931558Srgrimes usage(*argv); 1941558Srgrimes /* NOTREACHED */ 1951558Srgrimes} 1961558Srgrimes 1971558Srgrimes/* 1981558Srgrimes * Purge all entries in the routing tables not 1991558Srgrimes * associated with network interfaces. 2001558Srgrimes */ 2011558Srgrimesvoid 2021558Srgrimesflushroutes(argc, argv) 2031558Srgrimes int argc; 2041558Srgrimes char *argv[]; 2051558Srgrimes{ 2061558Srgrimes size_t needed; 2071558Srgrimes int mib[6], rlen, seqno; 2081558Srgrimes char *buf, *next, *lim; 2091558Srgrimes register struct rt_msghdr *rtm; 2101558Srgrimes 2111558Srgrimes if (uid) { 21213171Swollman errx(EX_NOPERM, "must be root to alter routing table"); 2131558Srgrimes } 2141558Srgrimes shutdown(s, 0); /* Don't want to read back our messages */ 2151558Srgrimes if (argc > 1) { 2161558Srgrimes argv++; 2171558Srgrimes if (argc == 2 && **argv == '-') 2181558Srgrimes switch (keyword(*argv + 1)) { 2191558Srgrimes case K_INET: 2201558Srgrimes af = AF_INET; 2211558Srgrimes break; 22217046Sjulian case K_ATALK: 22317046Sjulian af = AF_APPLETALK; 22417046Sjulian break; 22514092Swollman#ifdef NS 2261558Srgrimes case K_XNS: 2271558Srgrimes af = AF_NS; 2281558Srgrimes break; 22914092Swollman#endif 2301558Srgrimes case K_LINK: 2311558Srgrimes af = AF_LINK; 2321558Srgrimes break; 2331558Srgrimes default: 2341558Srgrimes goto bad; 2351558Srgrimes } else 2361558Srgrimesbad: usage(*argv); 2371558Srgrimes } 2381558Srgrimes mib[0] = CTL_NET; 2391558Srgrimes mib[1] = PF_ROUTE; 2401558Srgrimes mib[2] = 0; /* protocol */ 2411558Srgrimes mib[3] = 0; /* wildcard address family */ 2421558Srgrimes mib[4] = NET_RT_DUMP; 2431558Srgrimes mib[5] = 0; /* no flags */ 2441558Srgrimes if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 24513171Swollman err(EX_OSERR, "route-sysctl-estimate"); 2461558Srgrimes if ((buf = malloc(needed)) == NULL) 24737907Scharnier errx(EX_OSERR, "malloc failed"); 2481558Srgrimes if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 24913171Swollman err(EX_OSERR, "route-sysctl-get"); 2501558Srgrimes lim = buf + needed; 2511558Srgrimes if (verbose) 2521558Srgrimes (void) printf("Examining routing table from sysctl\n"); 2531558Srgrimes seqno = 0; /* ??? */ 2541558Srgrimes for (next = buf; next < lim; next += rtm->rtm_msglen) { 2551558Srgrimes rtm = (struct rt_msghdr *)next; 2561558Srgrimes if (verbose) 2571558Srgrimes print_rtmsg(rtm, rtm->rtm_msglen); 2581558Srgrimes if ((rtm->rtm_flags & RTF_GATEWAY) == 0) 2591558Srgrimes continue; 2601558Srgrimes if (af) { 2611558Srgrimes struct sockaddr *sa = (struct sockaddr *)(rtm + 1); 2621558Srgrimes 2631558Srgrimes if (sa->sa_family != af) 2641558Srgrimes continue; 2651558Srgrimes } 2661558Srgrimes if (debugonly) 2671558Srgrimes continue; 2681558Srgrimes rtm->rtm_type = RTM_DELETE; 2691558Srgrimes rtm->rtm_seq = seqno; 2701558Srgrimes rlen = write(s, next, rtm->rtm_msglen); 2711558Srgrimes if (rlen < (int)rtm->rtm_msglen) { 27213171Swollman warn("write to routing socket"); 2731558Srgrimes (void) printf("got only %d for rlen\n", rlen); 2741558Srgrimes break; 2751558Srgrimes } 2761558Srgrimes seqno++; 2771558Srgrimes if (qflag) 2781558Srgrimes continue; 2791558Srgrimes if (verbose) 2801558Srgrimes print_rtmsg(rtm, rlen); 2811558Srgrimes else { 2821558Srgrimes struct sockaddr *sa = (struct sockaddr *)(rtm + 1); 2831558Srgrimes (void) printf("%-20.20s ", rtm->rtm_flags & RTF_HOST ? 2841558Srgrimes routename(sa) : netname(sa)); 2851558Srgrimes sa = (struct sockaddr *)(sa->sa_len + (char *)sa); 2861558Srgrimes (void) printf("%-20.20s ", routename(sa)); 2871558Srgrimes (void) printf("done\n"); 2881558Srgrimes } 2891558Srgrimes } 2901558Srgrimes} 2911558Srgrimes 2921558Srgrimeschar * 2931558Srgrimesroutename(sa) 2941558Srgrimes struct sockaddr *sa; 2951558Srgrimes{ 2961558Srgrimes register char *cp; 29719209Sfenner static char line[MAXHOSTNAMELEN + 1]; 2981558Srgrimes struct hostent *hp; 2991558Srgrimes static char domain[MAXHOSTNAMELEN + 1]; 3001558Srgrimes static int first = 1; 30114092Swollman#ifdef NS 3021558Srgrimes char *ns_print(); 30314092Swollman#endif 3041558Srgrimes 3051558Srgrimes if (first) { 3061558Srgrimes first = 0; 3071558Srgrimes if (gethostname(domain, MAXHOSTNAMELEN) == 0 && 30819209Sfenner (cp = index(domain, '.'))) { 30919209Sfenner domain[MAXHOSTNAMELEN] = '\0'; 3101558Srgrimes (void) strcpy(domain, cp + 1); 31119209Sfenner } else 3121558Srgrimes domain[0] = 0; 3131558Srgrimes } 3141558Srgrimes 3151558Srgrimes if (sa->sa_len == 0) 3161558Srgrimes strcpy(line, "default"); 3171558Srgrimes else switch (sa->sa_family) { 3181558Srgrimes 3191558Srgrimes case AF_INET: 3201558Srgrimes { struct in_addr in; 3211558Srgrimes in = ((struct sockaddr_in *)sa)->sin_addr; 3221558Srgrimes 3231558Srgrimes cp = 0; 3241558Srgrimes if (in.s_addr == INADDR_ANY || sa->sa_len < 4) 3251558Srgrimes cp = "default"; 3261558Srgrimes if (cp == 0 && !nflag) { 3271558Srgrimes hp = gethostbyaddr((char *)&in, sizeof (struct in_addr), 3281558Srgrimes AF_INET); 3291558Srgrimes if (hp) { 3301558Srgrimes if ((cp = index(hp->h_name, '.')) && 3311558Srgrimes !strcmp(cp + 1, domain)) 3321558Srgrimes *cp = 0; 3331558Srgrimes cp = hp->h_name; 3341558Srgrimes } 3351558Srgrimes } 33631958Simp if (cp) { 33731958Simp strncpy(line, cp, sizeof(line) - 1); 33831958Simp line[sizeof(line) - 1] = '\0'; 33931958Simp } else { 34013171Swollman /* XXX - why not inet_ntoa()? */ 34113171Swollman#define C(x) (unsigned)((x) & 0xff) 3421558Srgrimes in.s_addr = ntohl(in.s_addr); 3431558Srgrimes (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), 3441558Srgrimes C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); 3451558Srgrimes } 3461558Srgrimes break; 3471558Srgrimes } 3481558Srgrimes 34917046Sjulian case AF_APPLETALK: 35017046Sjulian (void) snprintf(line, sizeof(line), "atalk %s", 35117046Sjulian atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr)); 35217046Sjulian break; 35317046Sjulian 35414092Swollman#ifdef NS 3551558Srgrimes case AF_NS: 3561558Srgrimes return (ns_print((struct sockaddr_ns *)sa)); 35714092Swollman#endif 3581558Srgrimes 3591558Srgrimes case AF_LINK: 3601558Srgrimes return (link_ntoa((struct sockaddr_dl *)sa)); 3611558Srgrimes 3621558Srgrimes default: 3631558Srgrimes { u_short *s = (u_short *)sa; 3641558Srgrimes u_short *slim = s + ((sa->sa_len + 1) >> 1); 3651558Srgrimes char *cp = line + sprintf(line, "(%d)", sa->sa_family); 36619209Sfenner char *cpe = line + sizeof(line); 3671558Srgrimes 36819209Sfenner while (++s < slim && cp < cpe) /* start with sa->sa_data */ 36919209Sfenner cp += snprintf(cp, cpe - cp, " %x", *s); 3701558Srgrimes break; 3711558Srgrimes } 3721558Srgrimes } 3731558Srgrimes return (line); 3741558Srgrimes} 3751558Srgrimes 3761558Srgrimes/* 3771558Srgrimes * Return the name of the network whose address is given. 3781558Srgrimes * The address is assumed to be that of a net or subnet, not a host. 3791558Srgrimes */ 3801558Srgrimeschar * 3811558Srgrimesnetname(sa) 3821558Srgrimes struct sockaddr *sa; 3831558Srgrimes{ 3841558Srgrimes char *cp = 0; 38519209Sfenner static char line[MAXHOSTNAMELEN + 1]; 3861558Srgrimes struct netent *np = 0; 3871558Srgrimes u_long net, mask; 3881558Srgrimes register u_long i; 3891558Srgrimes int subnetshift; 39014092Swollman#ifdef NS 3911558Srgrimes char *ns_print(); 39214092Swollman#endif 3931558Srgrimes 3941558Srgrimes switch (sa->sa_family) { 3951558Srgrimes 3961558Srgrimes case AF_INET: 3971558Srgrimes { struct in_addr in; 3981558Srgrimes in = ((struct sockaddr_in *)sa)->sin_addr; 3991558Srgrimes 4001558Srgrimes i = in.s_addr = ntohl(in.s_addr); 4011558Srgrimes if (in.s_addr == 0) 4021558Srgrimes cp = "default"; 4031558Srgrimes else if (!nflag) { 4041558Srgrimes if (IN_CLASSA(i)) { 4051558Srgrimes mask = IN_CLASSA_NET; 4061558Srgrimes subnetshift = 8; 4071558Srgrimes } else if (IN_CLASSB(i)) { 4081558Srgrimes mask = IN_CLASSB_NET; 4091558Srgrimes subnetshift = 8; 4101558Srgrimes } else { 4111558Srgrimes mask = IN_CLASSC_NET; 4121558Srgrimes subnetshift = 4; 4131558Srgrimes } 4141558Srgrimes /* 4151558Srgrimes * If there are more bits than the standard mask 4161558Srgrimes * would suggest, subnets must be in use. 4171558Srgrimes * Guess at the subnet mask, assuming reasonable 4181558Srgrimes * width subnet fields. 4191558Srgrimes */ 4201558Srgrimes while (in.s_addr &~ mask) 4211558Srgrimes mask = (long)mask >> subnetshift; 4221558Srgrimes net = in.s_addr & mask; 4231558Srgrimes while ((mask & 1) == 0) 4241558Srgrimes mask >>= 1, net >>= 1; 4251558Srgrimes np = getnetbyaddr(net, AF_INET); 4261558Srgrimes if (np) 4271558Srgrimes cp = np->n_name; 4281558Srgrimes } 4291558Srgrimes if (cp) 43019209Sfenner strncpy(line, cp, sizeof(line)); 4311558Srgrimes else if ((in.s_addr & 0xffffff) == 0) 4321558Srgrimes (void) sprintf(line, "%u", C(in.s_addr >> 24)); 4331558Srgrimes else if ((in.s_addr & 0xffff) == 0) 4341558Srgrimes (void) sprintf(line, "%u.%u", C(in.s_addr >> 24), 4351558Srgrimes C(in.s_addr >> 16)); 4361558Srgrimes else if ((in.s_addr & 0xff) == 0) 4371558Srgrimes (void) sprintf(line, "%u.%u.%u", C(in.s_addr >> 24), 4381558Srgrimes C(in.s_addr >> 16), C(in.s_addr >> 8)); 4391558Srgrimes else 4401558Srgrimes (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), 4411558Srgrimes C(in.s_addr >> 16), C(in.s_addr >> 8), 4421558Srgrimes C(in.s_addr)); 4431558Srgrimes break; 4441558Srgrimes } 4451558Srgrimes 44617046Sjulian case AF_APPLETALK: 44717046Sjulian (void) snprintf(line, sizeof(line), "atalk %s", 44817046Sjulian atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr)); 44917046Sjulian break; 45017046Sjulian 45114092Swollman#ifdef NS 4521558Srgrimes case AF_NS: 4531558Srgrimes return (ns_print((struct sockaddr_ns *)sa)); 4541558Srgrimes break; 45514092Swollman#endif 4561558Srgrimes 4571558Srgrimes case AF_LINK: 4581558Srgrimes return (link_ntoa((struct sockaddr_dl *)sa)); 4591558Srgrimes 4601558Srgrimes 4611558Srgrimes default: 4621558Srgrimes { u_short *s = (u_short *)sa->sa_data; 4631558Srgrimes u_short *slim = s + ((sa->sa_len + 1)>>1); 4641558Srgrimes char *cp = line + sprintf(line, "af %d:", sa->sa_family); 46519209Sfenner char *cpe = line + sizeof(line); 4661558Srgrimes 46719209Sfenner while (s < slim && cp < cpe) 46819209Sfenner cp += snprintf(cp, cpe - cp, " %x", *s++); 4691558Srgrimes break; 4701558Srgrimes } 4711558Srgrimes } 4721558Srgrimes return (line); 4731558Srgrimes} 4741558Srgrimes 4751558Srgrimesvoid 4761558Srgrimesset_metric(value, key) 4771558Srgrimes char *value; 4781558Srgrimes int key; 4791558Srgrimes{ 4801558Srgrimes int flag = 0; 4811558Srgrimes u_long noval, *valp = &noval; 4821558Srgrimes 4831558Srgrimes switch (key) { 4841558Srgrimes#define caseof(x, y, z) case x: valp = &rt_metrics.z; flag = y; break 4851558Srgrimes caseof(K_MTU, RTV_MTU, rmx_mtu); 4861558Srgrimes caseof(K_HOPCOUNT, RTV_HOPCOUNT, rmx_hopcount); 4871558Srgrimes caseof(K_EXPIRE, RTV_EXPIRE, rmx_expire); 4881558Srgrimes caseof(K_RECVPIPE, RTV_RPIPE, rmx_recvpipe); 4891558Srgrimes caseof(K_SENDPIPE, RTV_SPIPE, rmx_sendpipe); 4901558Srgrimes caseof(K_SSTHRESH, RTV_SSTHRESH, rmx_ssthresh); 4911558Srgrimes caseof(K_RTT, RTV_RTT, rmx_rtt); 4921558Srgrimes caseof(K_RTTVAR, RTV_RTTVAR, rmx_rttvar); 4931558Srgrimes } 4941558Srgrimes rtm_inits |= flag; 4951558Srgrimes if (lockrest || locking) 4961558Srgrimes rt_metrics.rmx_locks |= flag; 4971558Srgrimes if (locking) 4981558Srgrimes locking = 0; 4991558Srgrimes *valp = atoi(value); 5001558Srgrimes} 5011558Srgrimes 5021558Srgrimesvoid 5031558Srgrimesnewroute(argc, argv) 5041558Srgrimes int argc; 5051558Srgrimes register char **argv; 5061558Srgrimes{ 5071558Srgrimes char *cmd, *dest = "", *gateway = "", *err; 5081558Srgrimes int ishost = 0, ret, attempts, oerrno, flags = RTF_STATIC; 5091558Srgrimes int key; 5101558Srgrimes struct hostent *hp = 0; 5111558Srgrimes 5121558Srgrimes if (uid) { 51313171Swollman errx(EX_NOPERM, "must be root to alter routing table"); 5141558Srgrimes } 5151558Srgrimes cmd = argv[0]; 5161558Srgrimes if (*cmd != 'g') 5171558Srgrimes shutdown(s, 0); /* Don't want to read back our messages */ 5181558Srgrimes while (--argc > 0) { 5191558Srgrimes if (**(++argv)== '-') { 5201558Srgrimes switch (key = keyword(1 + *argv)) { 5211558Srgrimes case K_LINK: 5221558Srgrimes af = AF_LINK; 5231558Srgrimes aflen = sizeof(struct sockaddr_dl); 5241558Srgrimes break; 5251558Srgrimes case K_INET: 5261558Srgrimes af = AF_INET; 5271558Srgrimes aflen = sizeof(struct sockaddr_in); 5281558Srgrimes break; 52917046Sjulian case K_ATALK: 53017046Sjulian af = AF_APPLETALK; 53117046Sjulian aflen = sizeof(struct sockaddr_at); 53217046Sjulian break; 5331558Srgrimes case K_SA: 5341558Srgrimes af = PF_ROUTE; 5351558Srgrimes aflen = sizeof(union sockunion); 5361558Srgrimes break; 53714092Swollman#ifdef NS 5381558Srgrimes case K_XNS: 5391558Srgrimes af = AF_NS; 5401558Srgrimes aflen = sizeof(struct sockaddr_ns); 5411558Srgrimes break; 54214092Swollman#endif 5431558Srgrimes case K_IFACE: 5441558Srgrimes case K_INTERFACE: 5451558Srgrimes iflag++; 5462787Spst break; 5471558Srgrimes case K_NOSTATIC: 5481558Srgrimes flags &= ~RTF_STATIC; 5491558Srgrimes break; 55017591Sjulian case K_LLINFO: 55117591Sjulian flags |= RTF_LLINFO; 55217591Sjulian break; 5531558Srgrimes case K_LOCK: 5541558Srgrimes locking = 1; 5551558Srgrimes break; 5561558Srgrimes case K_LOCKREST: 5571558Srgrimes lockrest = 1; 5581558Srgrimes break; 5591558Srgrimes case K_HOST: 5601558Srgrimes forcehost++; 5611558Srgrimes break; 5621558Srgrimes case K_REJECT: 5631558Srgrimes flags |= RTF_REJECT; 5641558Srgrimes break; 5651558Srgrimes case K_BLACKHOLE: 5661558Srgrimes flags |= RTF_BLACKHOLE; 5671558Srgrimes break; 5681558Srgrimes case K_PROTO1: 5691558Srgrimes flags |= RTF_PROTO1; 5701558Srgrimes break; 5711558Srgrimes case K_PROTO2: 5721558Srgrimes flags |= RTF_PROTO2; 5731558Srgrimes break; 5741558Srgrimes case K_CLONING: 5751558Srgrimes flags |= RTF_CLONING; 5761558Srgrimes break; 5771558Srgrimes case K_XRESOLVE: 5781558Srgrimes flags |= RTF_XRESOLVE; 5791558Srgrimes break; 5801558Srgrimes case K_STATIC: 5811558Srgrimes flags |= RTF_STATIC; 5821558Srgrimes break; 5831558Srgrimes case K_IFA: 58447668Sru if (!--argc) 58547668Sru usage((char *)NULL); 5861558Srgrimes (void) getaddr(RTA_IFA, *++argv, 0); 5871558Srgrimes break; 5881558Srgrimes case K_IFP: 58947668Sru if (!--argc) 59047668Sru usage((char *)NULL); 5911558Srgrimes (void) getaddr(RTA_IFP, *++argv, 0); 5921558Srgrimes break; 5931558Srgrimes case K_GENMASK: 59447668Sru if (!--argc) 59547668Sru usage((char *)NULL); 5961558Srgrimes (void) getaddr(RTA_GENMASK, *++argv, 0); 5971558Srgrimes break; 5981558Srgrimes case K_GATEWAY: 59947668Sru if (!--argc) 60047668Sru usage((char *)NULL); 6011558Srgrimes (void) getaddr(RTA_GATEWAY, *++argv, 0); 6021558Srgrimes break; 6031558Srgrimes case K_DST: 60447668Sru if (!--argc) 60547668Sru usage((char *)NULL); 6061558Srgrimes ishost = getaddr(RTA_DST, *++argv, &hp); 6071558Srgrimes dest = *argv; 6081558Srgrimes break; 6091558Srgrimes case K_NETMASK: 61047668Sru if (!--argc) 61147668Sru usage((char *)NULL); 6121558Srgrimes (void) getaddr(RTA_NETMASK, *++argv, 0); 6131558Srgrimes /* FALLTHROUGH */ 6141558Srgrimes case K_NET: 6151558Srgrimes forcenet++; 6161558Srgrimes break; 6171558Srgrimes case K_MTU: 6181558Srgrimes case K_HOPCOUNT: 6191558Srgrimes case K_EXPIRE: 6201558Srgrimes case K_RECVPIPE: 6211558Srgrimes case K_SENDPIPE: 6221558Srgrimes case K_SSTHRESH: 6231558Srgrimes case K_RTT: 6241558Srgrimes case K_RTTVAR: 62547668Sru if (!--argc) 62647668Sru usage((char *)NULL); 6271558Srgrimes set_metric(*++argv, key); 6281558Srgrimes break; 6291558Srgrimes default: 6301558Srgrimes usage(1+*argv); 6311558Srgrimes } 6321558Srgrimes } else { 6331558Srgrimes if ((rtm_addrs & RTA_DST) == 0) { 6341558Srgrimes dest = *argv; 6351558Srgrimes ishost = getaddr(RTA_DST, *argv, &hp); 6361558Srgrimes } else if ((rtm_addrs & RTA_GATEWAY) == 0) { 6371558Srgrimes gateway = *argv; 6381558Srgrimes (void) getaddr(RTA_GATEWAY, *argv, &hp); 6391558Srgrimes } else { 6401558Srgrimes (void) getaddr(RTA_NETMASK, *argv, 0); 6411558Srgrimes } 6421558Srgrimes } 6431558Srgrimes } 6441558Srgrimes if (forcehost) 6451558Srgrimes ishost = 1; 6461558Srgrimes if (forcenet) 6471558Srgrimes ishost = 0; 6481558Srgrimes flags |= RTF_UP; 6491558Srgrimes if (ishost) 6501558Srgrimes flags |= RTF_HOST; 6511558Srgrimes if (iflag == 0) 6521558Srgrimes flags |= RTF_GATEWAY; 6531558Srgrimes for (attempts = 1; ; attempts++) { 6541558Srgrimes errno = 0; 6551558Srgrimes if ((ret = rtmsg(*cmd, flags)) == 0) 6561558Srgrimes break; 6571558Srgrimes if (errno != ENETUNREACH && errno != ESRCH) 6581558Srgrimes break; 6591558Srgrimes if (af == AF_INET && *gateway && hp && hp->h_addr_list[1]) { 6601558Srgrimes hp->h_addr_list++; 6611558Srgrimes bcopy(hp->h_addr_list[0], &so_gate.sin.sin_addr, 66231958Simp MIN(hp->h_length, sizeof(so_gate.sin.sin_addr))); 6631558Srgrimes } else 6641558Srgrimes break; 6651558Srgrimes } 6661558Srgrimes if (*cmd == 'g') 6671558Srgrimes exit(0); 6681558Srgrimes oerrno = errno; 6691558Srgrimes (void) printf("%s %s %s", cmd, ishost? "host" : "net", dest); 6701558Srgrimes if (*gateway) { 6711558Srgrimes (void) printf(": gateway %s", gateway); 6721558Srgrimes if (attempts > 1 && ret == 0 && af == AF_INET) 6731558Srgrimes (void) printf(" (%s)", 6741558Srgrimes inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr)); 6751558Srgrimes } 6761558Srgrimes if (ret == 0) 6771558Srgrimes (void) printf("\n"); 6781558Srgrimes else { 6791558Srgrimes switch (oerrno) { 6801558Srgrimes case ESRCH: 6811558Srgrimes err = "not in table"; 6821558Srgrimes break; 6831558Srgrimes case EBUSY: 6841558Srgrimes err = "entry in use"; 6851558Srgrimes break; 6861558Srgrimes case ENOBUFS: 6871558Srgrimes err = "routing table overflow"; 6881558Srgrimes break; 6891558Srgrimes default: 6901558Srgrimes err = strerror(oerrno); 6911558Srgrimes break; 6921558Srgrimes } 6931558Srgrimes (void) printf(": %s\n", err); 6941558Srgrimes } 6951558Srgrimes} 6961558Srgrimes 6971558Srgrimesvoid 69824558Sphkinet_makenetandmask(net, sin, bits) 69924558Sphk u_long net, bits; 7001558Srgrimes register struct sockaddr_in *sin; 7011558Srgrimes{ 7021558Srgrimes u_long addr, mask = 0; 7031558Srgrimes register char *cp; 7041558Srgrimes 7051558Srgrimes rtm_addrs |= RTA_NETMASK; 7061558Srgrimes if (net == 0) 7071558Srgrimes mask = addr = 0; 70824558Sphk else if (bits) { 70924558Sphk addr = net; 71024558Sphk mask = 0xffffffff << (32 - bits); 71124558Sphk } else if (net < 128) { 7121558Srgrimes addr = net << IN_CLASSA_NSHIFT; 7131558Srgrimes mask = IN_CLASSA_NET; 7141558Srgrimes } else if (net < 65536) { 7151558Srgrimes addr = net << IN_CLASSB_NSHIFT; 7161558Srgrimes mask = IN_CLASSB_NET; 7171558Srgrimes } else if (net < 16777216L) { 7181558Srgrimes addr = net << IN_CLASSC_NSHIFT; 7191558Srgrimes mask = IN_CLASSC_NET; 7201558Srgrimes } else { 7211558Srgrimes addr = net; 7221558Srgrimes if ((addr & IN_CLASSA_HOST) == 0) 7231558Srgrimes mask = IN_CLASSA_NET; 7241558Srgrimes else if ((addr & IN_CLASSB_HOST) == 0) 7251558Srgrimes mask = IN_CLASSB_NET; 7261558Srgrimes else if ((addr & IN_CLASSC_HOST) == 0) 7271558Srgrimes mask = IN_CLASSC_NET; 7281558Srgrimes else 7291558Srgrimes mask = -1; 7301558Srgrimes } 7311558Srgrimes sin->sin_addr.s_addr = htonl(addr); 7321558Srgrimes sin = &so_mask.sin; 7331558Srgrimes sin->sin_addr.s_addr = htonl(mask); 7341558Srgrimes sin->sin_len = 0; 7351558Srgrimes sin->sin_family = 0; 7361558Srgrimes cp = (char *)(&sin->sin_addr + 1); 7371558Srgrimes while (*--cp == 0 && cp > (char *)sin) 7381558Srgrimes ; 7391558Srgrimes sin->sin_len = 1 + cp - (char *)sin; 7401558Srgrimes} 7411558Srgrimes 7421558Srgrimes/* 7431558Srgrimes * Interpret an argument as a network address of some kind, 7441558Srgrimes * returning 1 if a host address, 0 if a network address. 7451558Srgrimes */ 7461558Srgrimesint 7471558Srgrimesgetaddr(which, s, hpp) 7481558Srgrimes int which; 7491558Srgrimes char *s; 7501558Srgrimes struct hostent **hpp; 7511558Srgrimes{ 7521558Srgrimes register sup su; 75314092Swollman#ifdef NS 7541558Srgrimes struct ns_addr ns_addr(); 75514092Swollman#endif 7561558Srgrimes struct hostent *hp; 7571558Srgrimes struct netent *np; 7581558Srgrimes u_long val; 75924558Sphk char *q,qs; 7601558Srgrimes 7611558Srgrimes if (af == 0) { 7621558Srgrimes af = AF_INET; 7631558Srgrimes aflen = sizeof(struct sockaddr_in); 7641558Srgrimes } 7651558Srgrimes rtm_addrs |= which; 7661558Srgrimes switch (which) { 7671558Srgrimes case RTA_DST: 7681558Srgrimes su = &so_dst; 7691558Srgrimes break; 7701558Srgrimes case RTA_GATEWAY: 7711558Srgrimes su = &so_gate; 77217486Sjulian if (iflag) { 77317486Sjulian #define MAX_IFACES 400 77417486Sjulian int sock; 77517486Sjulian struct ifreq iflist[MAX_IFACES]; 77617486Sjulian struct ifconf ifconf; 77717486Sjulian struct ifreq *ifr, *ifr_end; 77817486Sjulian struct sockaddr_dl *dl, *sdl = NULL; 77917486Sjulian 78017486Sjulian /* Get socket */ 78117486Sjulian if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) 78217486Sjulian err(1, "socket"); 78317486Sjulian 78417486Sjulian /* Get interface list */ 78517486Sjulian ifconf.ifc_req = iflist; 78617486Sjulian ifconf.ifc_len = sizeof(iflist); 78717486Sjulian if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0) 78817486Sjulian err(1, "ioctl(SIOCGIFCONF)"); 78917486Sjulian close(sock); 79017486Sjulian 79117486Sjulian /* Look for this interface in the list */ 79217486Sjulian for (ifr = ifconf.ifc_req, 79317486Sjulian ifr_end = (struct ifreq *) 79417486Sjulian (ifconf.ifc_buf + ifconf.ifc_len); 79517486Sjulian ifr < ifr_end; 79617486Sjulian ifr = (struct ifreq *) ((char *) &ifr->ifr_addr 79717486Sjulian + ifr->ifr_addr.sa_len)) { 79817486Sjulian dl = (struct sockaddr_dl *)&ifr->ifr_addr; 79917486Sjulian if (ifr->ifr_addr.sa_family == AF_LINK 80017486Sjulian && (ifr->ifr_flags & IFF_POINTOPOINT) 80117486Sjulian && !strncmp(s, dl->sdl_data, dl->sdl_nlen) 80217486Sjulian && s[dl->sdl_nlen] == 0) { 80317486Sjulian sdl = dl; 80417486Sjulian break; 80517486Sjulian } 80617486Sjulian } 80717486Sjulian 80817486Sjulian /* If we found it, then use it */ 80917486Sjulian if (sdl) { 81017486Sjulian su->sdl = *sdl; 81117486Sjulian return(1); 81217486Sjulian } 81317486Sjulian } 8141558Srgrimes break; 8151558Srgrimes case RTA_NETMASK: 8161558Srgrimes su = &so_mask; 8171558Srgrimes break; 8181558Srgrimes case RTA_GENMASK: 8191558Srgrimes su = &so_genmask; 8201558Srgrimes break; 8211558Srgrimes case RTA_IFP: 8221558Srgrimes su = &so_ifp; 8231558Srgrimes break; 8241558Srgrimes case RTA_IFA: 8251558Srgrimes su = &so_ifa; 8261558Srgrimes break; 8271558Srgrimes default: 82837907Scharnier usage("internal error"); 8291558Srgrimes /*NOTREACHED*/ 8301558Srgrimes } 8311558Srgrimes su->sa.sa_len = aflen; 83227500Sjulian su->sa.sa_family = af; /* cases that don't want it have left already */ 8331558Srgrimes if (strcmp(s, "default") == 0) { 83427500Sjulian /* 83527500Sjulian * Default is net 0.0.0.0/0 83627500Sjulian */ 8371558Srgrimes switch (which) { 8381558Srgrimes case RTA_DST: 8391558Srgrimes forcenet++; 84027500Sjulian /* bzero(su, sizeof(*su)); *//* for readability */ 8411558Srgrimes (void) getaddr(RTA_NETMASK, s, 0); 8421558Srgrimes break; 8431558Srgrimes case RTA_NETMASK: 8441558Srgrimes case RTA_GENMASK: 84527500Sjulian /* bzero(su, sizeof(*su)); *//* for readability */ 8461558Srgrimes } 8471558Srgrimes return (0); 8481558Srgrimes } 8491558Srgrimes switch (af) { 85014092Swollman#ifdef NS 8511558Srgrimes case AF_NS: 8521558Srgrimes if (which == RTA_DST) { 8531558Srgrimes extern short ns_bh[3]; 8541558Srgrimes struct sockaddr_ns *sms = &(so_mask.sns); 8551558Srgrimes bzero((char *)sms, sizeof(*sms)); 8561558Srgrimes sms->sns_family = 0; 8571558Srgrimes sms->sns_len = 6; 8581558Srgrimes sms->sns_addr.x_net = *(union ns_net *)ns_bh; 8591558Srgrimes rtm_addrs |= RTA_NETMASK; 8601558Srgrimes } 8611558Srgrimes su->sns.sns_addr = ns_addr(s); 8621558Srgrimes return (!ns_nullhost(su->sns.sns_addr)); 86314092Swollman#endif 8641558Srgrimes 8651558Srgrimes 86617046Sjulian case AF_APPLETALK: 86717046Sjulian if (!atalk_aton(s, &su->sat.sat_addr)) 86817046Sjulian errx(EX_NOHOST, "bad address: %s", s); 86917265Sjulian rtm_addrs |= RTA_NETMASK; 87017265Sjulian return(forcehost || su->sat.sat_addr.s_node != 0); 87117046Sjulian 8721558Srgrimes case AF_LINK: 8731558Srgrimes link_addr(s, &su->sdl); 8741558Srgrimes return (1); 8751558Srgrimes 8761558Srgrimes 8771558Srgrimes case PF_ROUTE: 8781558Srgrimes su->sa.sa_len = sizeof(*su); 8791558Srgrimes sockaddr(s, &su->sa); 8801558Srgrimes return (1); 8811558Srgrimes 8821558Srgrimes case AF_INET: 8831558Srgrimes default: 8841558Srgrimes break; 8851558Srgrimes } 8861558Srgrimes 8871558Srgrimes if (hpp == NULL) 8881558Srgrimes hpp = &hp; 8891558Srgrimes *hpp = NULL; 89024558Sphk 89124558Sphk q = strchr(s,'/'); 89224558Sphk if (q && which == RTA_DST) { 89324558Sphk qs = *q; 89424558Sphk *q = '\0'; 89524558Sphk if (((val = inet_addr(s)) != INADDR_NONE)) { 89624558Sphk inet_makenetandmask( 89724558Sphk htonl(val), &su->sin, strtoul(q+1, 0, 0)); 89824558Sphk return (0); 89924558Sphk } 90024558Sphk *q =qs; 90124558Sphk } 90214132Smpp if (((val = inet_addr(s)) != INADDR_NONE) && 9031558Srgrimes (which != RTA_DST || forcenet == 0)) { 9041558Srgrimes su->sin.sin_addr.s_addr = val; 9051558Srgrimes if (inet_lnaof(su->sin.sin_addr) != INADDR_ANY) 9061558Srgrimes return (1); 9071558Srgrimes else { 9081558Srgrimes val = ntohl(val); 9091558Srgrimes goto netdone; 9101558Srgrimes } 9111558Srgrimes } 91214132Smpp if ((val = inet_network(s)) != INADDR_NONE || 91319209Sfenner (forcehost == 0 && (np = getnetbyname(s)) != NULL && 91419209Sfenner (val = np->n_net) != 0)) { 9151558Srgrimesnetdone: 9161558Srgrimes if (which == RTA_DST) 91724558Sphk inet_makenetandmask(val, &su->sin, 0); 9181558Srgrimes return (0); 9191558Srgrimes } 9201558Srgrimes hp = gethostbyname(s); 9211558Srgrimes if (hp) { 9221558Srgrimes *hpp = hp; 9231558Srgrimes su->sin.sin_family = hp->h_addrtype; 92431958Simp bcopy(hp->h_addr, (char *)&su->sin.sin_addr, 92532008Simp MIN(hp->h_length, sizeof(su->sin.sin_addr))); 9261558Srgrimes return (1); 9271558Srgrimes } 92813515Smpp errx(EX_NOHOST, "bad address: %s", s); 9291558Srgrimes} 9301558Srgrimes 9311558Srgrimes 93214092Swollman#ifdef NS 9331558Srgrimesshort ns_nullh[] = {0,0,0}; 9341558Srgrimesshort ns_bh[] = {-1,-1,-1}; 9351558Srgrimes 9361558Srgrimeschar * 9371558Srgrimesns_print(sns) 9381558Srgrimes struct sockaddr_ns *sns; 9391558Srgrimes{ 9401558Srgrimes struct ns_addr work; 9411558Srgrimes union { union ns_net net_e; u_long long_e; } net; 9421558Srgrimes u_short port; 94322953Sroberto static char mybuf[50+MAXHOSTNAMELEN], cport[10], chost[25]; 9441558Srgrimes char *host = ""; 9451558Srgrimes register char *p; 9461558Srgrimes register u_char *q; 9471558Srgrimes 9481558Srgrimes work = sns->sns_addr; 9491558Srgrimes port = ntohs(work.x_port); 9501558Srgrimes work.x_port = 0; 9511558Srgrimes net.net_e = work.x_net; 9521558Srgrimes if (ns_nullhost(work) && net.long_e == 0) { 9531558Srgrimes if (!port) 9541558Srgrimes return ("*.*"); 9551558Srgrimes (void) sprintf(mybuf, "*.%XH", port); 9561558Srgrimes return (mybuf); 9571558Srgrimes } 9581558Srgrimes 9591558Srgrimes if (bcmp((char *)ns_bh, (char *)work.x_host.c_host, 6) == 0) 9601558Srgrimes host = "any"; 9611558Srgrimes else if (bcmp((char *)ns_nullh, (char *)work.x_host.c_host, 6) == 0) 9621558Srgrimes host = "*"; 9631558Srgrimes else { 9641558Srgrimes q = work.x_host.c_host; 9651558Srgrimes (void) sprintf(chost, "%02X%02X%02X%02X%02X%02XH", 9661558Srgrimes q[0], q[1], q[2], q[3], q[4], q[5]); 9671558Srgrimes for (p = chost; *p == '0' && p < chost + 12; p++) 9681558Srgrimes /* void */; 9691558Srgrimes host = p; 9701558Srgrimes } 9711558Srgrimes if (port) 9721558Srgrimes (void) sprintf(cport, ".%XH", htons(port)); 9731558Srgrimes else 9741558Srgrimes *cport = 0; 9751558Srgrimes 97622953Sroberto (void) snprintf(mybuf, sizeof(mybuf), "%lxH.%s%s", 97722953Sroberto (unsigned long)ntohl(net.long_e), 97813171Swollman host, cport); 9791558Srgrimes return (mybuf); 9801558Srgrimes} 98114092Swollman#endif 9821558Srgrimes 9831558Srgrimesvoid 9841558Srgrimesinterfaces() 9851558Srgrimes{ 9861558Srgrimes size_t needed; 9871558Srgrimes int mib[6]; 9881558Srgrimes char *buf, *lim, *next; 9891558Srgrimes register struct rt_msghdr *rtm; 9901558Srgrimes 9911558Srgrimes mib[0] = CTL_NET; 9921558Srgrimes mib[1] = PF_ROUTE; 9931558Srgrimes mib[2] = 0; /* protocol */ 9941558Srgrimes mib[3] = 0; /* wildcard address family */ 9951558Srgrimes mib[4] = NET_RT_IFLIST; 9961558Srgrimes mib[5] = 0; /* no flags */ 9971558Srgrimes if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 99813171Swollman err(EX_OSERR, "route-sysctl-estimate"); 9991558Srgrimes if ((buf = malloc(needed)) == NULL) 100037907Scharnier errx(EX_OSERR, "malloc failed"); 10011558Srgrimes if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 100213171Swollman err(EX_OSERR, "actual retrieval of interface table"); 10031558Srgrimes lim = buf + needed; 10041558Srgrimes for (next = buf; next < lim; next += rtm->rtm_msglen) { 10051558Srgrimes rtm = (struct rt_msghdr *)next; 10061558Srgrimes print_rtmsg(rtm, rtm->rtm_msglen); 10071558Srgrimes } 10081558Srgrimes} 10091558Srgrimes 10101558Srgrimesvoid 10111558Srgrimesmonitor() 10121558Srgrimes{ 10131558Srgrimes int n; 10141558Srgrimes char msg[2048]; 10151558Srgrimes 10161558Srgrimes verbose = 1; 10171558Srgrimes if (debugonly) { 10181558Srgrimes interfaces(); 10191558Srgrimes exit(0); 10201558Srgrimes } 10211558Srgrimes for(;;) { 10221558Srgrimes n = read(s, msg, 2048); 10231558Srgrimes (void) printf("got message of size %d\n", n); 10241558Srgrimes print_rtmsg((struct rt_msghdr *)msg, n); 10251558Srgrimes } 10261558Srgrimes} 10271558Srgrimes 10281558Srgrimesstruct { 10291558Srgrimes struct rt_msghdr m_rtm; 10301558Srgrimes char m_space[512]; 10311558Srgrimes} m_rtmsg; 10321558Srgrimes 10331558Srgrimesint 10341558Srgrimesrtmsg(cmd, flags) 10351558Srgrimes int cmd, flags; 10361558Srgrimes{ 10371558Srgrimes static int seq; 10381558Srgrimes int rlen; 10391558Srgrimes register char *cp = m_rtmsg.m_space; 10401558Srgrimes register int l; 10411558Srgrimes 10421558Srgrimes#define NEXTADDR(w, u) \ 10431558Srgrimes if (rtm_addrs & (w)) {\ 10441558Srgrimes l = ROUNDUP(u.sa.sa_len); bcopy((char *)&(u), cp, l); cp += l;\ 10451558Srgrimes if (verbose) sodump(&(u),"u");\ 10461558Srgrimes } 10471558Srgrimes 10481558Srgrimes errno = 0; 10491558Srgrimes bzero((char *)&m_rtmsg, sizeof(m_rtmsg)); 10501558Srgrimes if (cmd == 'a') 10511558Srgrimes cmd = RTM_ADD; 10521558Srgrimes else if (cmd == 'c') 10531558Srgrimes cmd = RTM_CHANGE; 10541558Srgrimes else if (cmd == 'g') { 10551558Srgrimes cmd = RTM_GET; 10561558Srgrimes if (so_ifp.sa.sa_family == 0) { 105713171Swollman so_ifp.sa.sa_family = AF_LINK; 105813171Swollman so_ifp.sa.sa_len = sizeof(struct sockaddr_dl); 10591558Srgrimes rtm_addrs |= RTA_IFP; 10601558Srgrimes } 10611558Srgrimes } else 10621558Srgrimes cmd = RTM_DELETE; 10631558Srgrimes#define rtm m_rtmsg.m_rtm 10641558Srgrimes rtm.rtm_type = cmd; 10651558Srgrimes rtm.rtm_flags = flags; 10661558Srgrimes rtm.rtm_version = RTM_VERSION; 10671558Srgrimes rtm.rtm_seq = ++seq; 10681558Srgrimes rtm.rtm_addrs = rtm_addrs; 10691558Srgrimes rtm.rtm_rmx = rt_metrics; 10701558Srgrimes rtm.rtm_inits = rtm_inits; 10711558Srgrimes 10721558Srgrimes if (rtm_addrs & RTA_NETMASK) 10731558Srgrimes mask_addr(); 10741558Srgrimes NEXTADDR(RTA_DST, so_dst); 10751558Srgrimes NEXTADDR(RTA_GATEWAY, so_gate); 10761558Srgrimes NEXTADDR(RTA_NETMASK, so_mask); 10771558Srgrimes NEXTADDR(RTA_GENMASK, so_genmask); 10781558Srgrimes NEXTADDR(RTA_IFP, so_ifp); 10791558Srgrimes NEXTADDR(RTA_IFA, so_ifa); 10801558Srgrimes rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; 10811558Srgrimes if (verbose) 10821558Srgrimes print_rtmsg(&rtm, l); 10831558Srgrimes if (debugonly) 10841558Srgrimes return (0); 10851558Srgrimes if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) { 108637907Scharnier warn("writing to routing socket"); 10871558Srgrimes return (-1); 10881558Srgrimes } 10891558Srgrimes if (cmd == RTM_GET) { 10901558Srgrimes do { 10911558Srgrimes l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); 10921558Srgrimes } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid)); 10931558Srgrimes if (l < 0) 109413171Swollman warn("read from routing socket"); 10951558Srgrimes else 10961558Srgrimes print_getmsg(&rtm, l); 10971558Srgrimes } 10981558Srgrimes#undef rtm 10991558Srgrimes return (0); 11001558Srgrimes} 11011558Srgrimes 11021558Srgrimesvoid 11031558Srgrimesmask_addr() 11041558Srgrimes{ 11051558Srgrimes int olen = so_mask.sa.sa_len; 11061558Srgrimes register char *cp1 = olen + (char *)&so_mask, *cp2; 11071558Srgrimes 11081558Srgrimes for (so_mask.sa.sa_len = 0; cp1 > (char *)&so_mask; ) 11091558Srgrimes if (*--cp1 != 0) { 11101558Srgrimes so_mask.sa.sa_len = 1 + cp1 - (char *)&so_mask; 11111558Srgrimes break; 11121558Srgrimes } 11131558Srgrimes if ((rtm_addrs & RTA_DST) == 0) 11141558Srgrimes return; 11151558Srgrimes switch (so_dst.sa.sa_family) { 111614092Swollman#ifdef NS 11171558Srgrimes case AF_NS: 111814092Swollman#endif 11191558Srgrimes case AF_INET: 112017046Sjulian case AF_APPLETALK: 11211558Srgrimes case 0: 11221558Srgrimes return; 11231558Srgrimes } 11241558Srgrimes cp1 = so_mask.sa.sa_len + 1 + (char *)&so_dst; 11251558Srgrimes cp2 = so_dst.sa.sa_len + 1 + (char *)&so_dst; 11261558Srgrimes while (cp2 > cp1) 11271558Srgrimes *--cp2 = 0; 11281558Srgrimes cp2 = so_mask.sa.sa_len + 1 + (char *)&so_mask; 11291558Srgrimes while (cp1 > so_dst.sa.sa_data) 11301558Srgrimes *--cp1 &= *--cp2; 11311558Srgrimes} 11321558Srgrimes 11331558Srgrimeschar *msgtypes[] = { 11341558Srgrimes "", 11351558Srgrimes "RTM_ADD: Add Route", 11361558Srgrimes "RTM_DELETE: Delete Route", 11371558Srgrimes "RTM_CHANGE: Change Metrics or flags", 11381558Srgrimes "RTM_GET: Report Metrics", 11391558Srgrimes "RTM_LOSING: Kernel Suspects Partitioning", 11401558Srgrimes "RTM_REDIRECT: Told to use different route", 11411558Srgrimes "RTM_MISS: Lookup failed on this address", 11421558Srgrimes "RTM_LOCK: fix specified metrics", 11431558Srgrimes "RTM_OLDADD: caused by SIOCADDRT", 11441558Srgrimes "RTM_OLDDEL: caused by SIOCDELRT", 11451558Srgrimes "RTM_RESOLVE: Route created by cloning", 11461558Srgrimes "RTM_NEWADDR: address being added to iface", 11471558Srgrimes "RTM_DELADDR: address being removed from iface", 11481558Srgrimes "RTM_IFINFO: iface status change", 114921465Swollman "RTM_NEWMADDR: new multicast group membership on iface", 115021465Swollman "RTM_DELMADDR: multicast group membership removed from iface", 11511558Srgrimes 0, 11521558Srgrimes}; 11531558Srgrimes 11541558Srgrimeschar metricnames[] = 115515690Swollman"\011pksent\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount" 115615690Swollman"\1mtu"; 11571558Srgrimeschar routeflags[] = 115815690Swollman"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT" 115915690Swollman"\011CLONING\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE\016b016" 116015690Swollman"\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3\024CHAINDELETE" 116115690Swollman"\025PINNED\026LOCAL\027BROADCAST\030MULTICAST"; 11621558Srgrimeschar ifnetflags[] = 116315690Swollman"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP" 116415690Swollman"\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1" 116515690Swollman"\017LINK2\020MULTICAST"; 11661558Srgrimeschar addrnames[] = 11671558Srgrimes"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD"; 11681558Srgrimes 11691558Srgrimesvoid 11701558Srgrimesprint_rtmsg(rtm, msglen) 11711558Srgrimes register struct rt_msghdr *rtm; 11721558Srgrimes int msglen; 11731558Srgrimes{ 11741558Srgrimes struct if_msghdr *ifm; 11751558Srgrimes struct ifa_msghdr *ifam; 117621465Swollman#ifdef RTM_NEWMADDR 117721465Swollman struct ifma_msghdr *ifmam; 117821465Swollman#endif 11791558Srgrimes 11801558Srgrimes if (verbose == 0) 11811558Srgrimes return; 11821558Srgrimes if (rtm->rtm_version != RTM_VERSION) { 11831558Srgrimes (void) printf("routing message version %d not understood\n", 11841558Srgrimes rtm->rtm_version); 11851558Srgrimes return; 11861558Srgrimes } 11871558Srgrimes (void)printf("%s: len %d, ", msgtypes[rtm->rtm_type], rtm->rtm_msglen); 11881558Srgrimes switch (rtm->rtm_type) { 11891558Srgrimes case RTM_IFINFO: 11901558Srgrimes ifm = (struct if_msghdr *)rtm; 11911558Srgrimes (void) printf("if# %d, flags:", ifm->ifm_index); 11921558Srgrimes bprintf(stdout, ifm->ifm_flags, ifnetflags); 11931558Srgrimes pmsg_addrs((char *)(ifm + 1), ifm->ifm_addrs); 11941558Srgrimes break; 11951558Srgrimes case RTM_NEWADDR: 11961558Srgrimes case RTM_DELADDR: 11971558Srgrimes ifam = (struct ifa_msghdr *)rtm; 11981558Srgrimes (void) printf("metric %d, flags:", ifam->ifam_metric); 11991558Srgrimes bprintf(stdout, ifam->ifam_flags, routeflags); 12001558Srgrimes pmsg_addrs((char *)(ifam + 1), ifam->ifam_addrs); 12011558Srgrimes break; 120221465Swollman#ifdef RTM_NEWMADDR 120321465Swollman case RTM_NEWMADDR: 120421465Swollman case RTM_DELMADDR: 120521465Swollman ifmam = (struct ifma_msghdr *)rtm; 120621465Swollman pmsg_addrs((char *)(ifmam + 1), ifmam->ifmam_addrs); 120721465Swollman break; 120821465Swollman#endif 12091558Srgrimes default: 121013171Swollman (void) printf("pid: %ld, seq %d, errno %d, flags:", 121113171Swollman (long)rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno); 12121558Srgrimes bprintf(stdout, rtm->rtm_flags, routeflags); 12131558Srgrimes pmsg_common(rtm); 12141558Srgrimes } 12151558Srgrimes} 12161558Srgrimes 12171558Srgrimesvoid 12181558Srgrimesprint_getmsg(rtm, msglen) 12191558Srgrimes register struct rt_msghdr *rtm; 12201558Srgrimes int msglen; 12211558Srgrimes{ 12221558Srgrimes struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL; 12231558Srgrimes struct sockaddr_dl *ifp = NULL; 12241558Srgrimes register struct sockaddr *sa; 12251558Srgrimes register char *cp; 12261558Srgrimes register int i; 12271558Srgrimes 12281558Srgrimes (void) printf(" route to: %s\n", routename(&so_dst)); 12291558Srgrimes if (rtm->rtm_version != RTM_VERSION) { 123013171Swollman warnx("routing message version %d not understood", 123113171Swollman rtm->rtm_version); 12321558Srgrimes return; 12331558Srgrimes } 12341558Srgrimes if (rtm->rtm_msglen > msglen) { 123537907Scharnier warnx("message length mismatch, in packet %d, returned %d", 123613171Swollman rtm->rtm_msglen, msglen); 12371558Srgrimes } 12381558Srgrimes if (rtm->rtm_errno) { 123913171Swollman errno = rtm->rtm_errno; 124013171Swollman warn("message indicates error %d", errno); 12411558Srgrimes return; 12421558Srgrimes } 12431558Srgrimes cp = ((char *)(rtm + 1)); 12441558Srgrimes if (rtm->rtm_addrs) 12451558Srgrimes for (i = 1; i; i <<= 1) 12461558Srgrimes if (i & rtm->rtm_addrs) { 12471558Srgrimes sa = (struct sockaddr *)cp; 12481558Srgrimes switch (i) { 12491558Srgrimes case RTA_DST: 12501558Srgrimes dst = sa; 12511558Srgrimes break; 12521558Srgrimes case RTA_GATEWAY: 12531558Srgrimes gate = sa; 12541558Srgrimes break; 12551558Srgrimes case RTA_NETMASK: 12561558Srgrimes mask = sa; 12571558Srgrimes break; 12581558Srgrimes case RTA_IFP: 12591558Srgrimes if (sa->sa_family == AF_LINK && 12601558Srgrimes ((struct sockaddr_dl *)sa)->sdl_nlen) 12611558Srgrimes ifp = (struct sockaddr_dl *)sa; 12621558Srgrimes break; 12631558Srgrimes } 12641558Srgrimes ADVANCE(cp, sa); 12651558Srgrimes } 12661558Srgrimes if (dst && mask) 12671558Srgrimes mask->sa_family = dst->sa_family; /* XXX */ 12681558Srgrimes if (dst) 12691558Srgrimes (void)printf("destination: %s\n", routename(dst)); 12701558Srgrimes if (mask) { 12711558Srgrimes int savenflag = nflag; 12721558Srgrimes 12731558Srgrimes nflag = 1; 12741558Srgrimes (void)printf(" mask: %s\n", routename(mask)); 12751558Srgrimes nflag = savenflag; 12761558Srgrimes } 12771558Srgrimes if (gate && rtm->rtm_flags & RTF_GATEWAY) 12781558Srgrimes (void)printf(" gateway: %s\n", routename(gate)); 12791558Srgrimes if (ifp) 12801558Srgrimes (void)printf(" interface: %.*s\n", 12811558Srgrimes ifp->sdl_nlen, ifp->sdl_data); 12821558Srgrimes (void)printf(" flags: "); 12831558Srgrimes bprintf(stdout, rtm->rtm_flags, routeflags); 12841558Srgrimes 12851558Srgrimes#define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ') 12861558Srgrimes#define msec(u) (((u) + 500) / 1000) /* usec to msec */ 12871558Srgrimes 12881558Srgrimes (void) printf("\n%s\n", "\ 12891558Srgrimes recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire"); 129013171Swollman printf("%8ld%c ", rtm->rtm_rmx.rmx_recvpipe, lock(RPIPE)); 129113171Swollman printf("%8ld%c ", rtm->rtm_rmx.rmx_sendpipe, lock(SPIPE)); 129213171Swollman printf("%8ld%c ", rtm->rtm_rmx.rmx_ssthresh, lock(SSTHRESH)); 129313171Swollman printf("%8ld%c ", msec(rtm->rtm_rmx.rmx_rtt), lock(RTT)); 129413171Swollman printf("%8ld%c ", msec(rtm->rtm_rmx.rmx_rttvar), lock(RTTVAR)); 129513171Swollman printf("%8ld%c ", rtm->rtm_rmx.rmx_hopcount, lock(HOPCOUNT)); 129613171Swollman printf("%8ld%c ", rtm->rtm_rmx.rmx_mtu, lock(MTU)); 12971558Srgrimes if (rtm->rtm_rmx.rmx_expire) 12981558Srgrimes rtm->rtm_rmx.rmx_expire -= time(0); 129913171Swollman printf("%8ld%c\n", rtm->rtm_rmx.rmx_expire, lock(EXPIRE)); 13001558Srgrimes#undef lock 13011558Srgrimes#undef msec 13021558Srgrimes#define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD) 13031558Srgrimes if (verbose) 13041558Srgrimes pmsg_common(rtm); 13051558Srgrimes else if (rtm->rtm_addrs &~ RTA_IGN) { 13061558Srgrimes (void) printf("sockaddrs: "); 13071558Srgrimes bprintf(stdout, rtm->rtm_addrs, addrnames); 13081558Srgrimes putchar('\n'); 13091558Srgrimes } 13101558Srgrimes#undef RTA_IGN 13111558Srgrimes} 13121558Srgrimes 13131558Srgrimesvoid 13141558Srgrimespmsg_common(rtm) 13151558Srgrimes register struct rt_msghdr *rtm; 13161558Srgrimes{ 13171558Srgrimes (void) printf("\nlocks: "); 13181558Srgrimes bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames); 13191558Srgrimes (void) printf(" inits: "); 13201558Srgrimes bprintf(stdout, rtm->rtm_inits, metricnames); 13211558Srgrimes pmsg_addrs(((char *)(rtm + 1)), rtm->rtm_addrs); 13221558Srgrimes} 13231558Srgrimes 13241558Srgrimesvoid 13251558Srgrimespmsg_addrs(cp, addrs) 13261558Srgrimes char *cp; 13271558Srgrimes int addrs; 13281558Srgrimes{ 13291558Srgrimes register struct sockaddr *sa; 13301558Srgrimes int i; 13311558Srgrimes 13321558Srgrimes if (addrs == 0) 13331558Srgrimes return; 13341558Srgrimes (void) printf("\nsockaddrs: "); 13351558Srgrimes bprintf(stdout, addrs, addrnames); 13361558Srgrimes (void) putchar('\n'); 13371558Srgrimes for (i = 1; i; i <<= 1) 13381558Srgrimes if (i & addrs) { 13391558Srgrimes sa = (struct sockaddr *)cp; 13401558Srgrimes (void) printf(" %s", routename(sa)); 13411558Srgrimes ADVANCE(cp, sa); 13421558Srgrimes } 13431558Srgrimes (void) putchar('\n'); 13441558Srgrimes (void) fflush(stdout); 13451558Srgrimes} 13461558Srgrimes 13471558Srgrimesvoid 13481558Srgrimesbprintf(fp, b, s) 13491558Srgrimes register FILE *fp; 13501558Srgrimes register int b; 13511558Srgrimes register u_char *s; 13521558Srgrimes{ 13531558Srgrimes register int i; 13541558Srgrimes int gotsome = 0; 13551558Srgrimes 13561558Srgrimes if (b == 0) 13571558Srgrimes return; 135813171Swollman while ((i = *s++) != 0) { 13591558Srgrimes if (b & (1 << (i-1))) { 13601558Srgrimes if (gotsome == 0) 13611558Srgrimes i = '<'; 13621558Srgrimes else 13631558Srgrimes i = ','; 13641558Srgrimes (void) putc(i, fp); 13651558Srgrimes gotsome = 1; 13661558Srgrimes for (; (i = *s) > 32; s++) 13671558Srgrimes (void) putc(i, fp); 13681558Srgrimes } else 13691558Srgrimes while (*s > 32) 13701558Srgrimes s++; 13711558Srgrimes } 13721558Srgrimes if (gotsome) 13731558Srgrimes (void) putc('>', fp); 13741558Srgrimes} 13751558Srgrimes 13761558Srgrimesint 13771558Srgrimeskeyword(cp) 13781558Srgrimes char *cp; 13791558Srgrimes{ 13801558Srgrimes register struct keytab *kt = keywords; 13811558Srgrimes 13821558Srgrimes while (kt->kt_cp && strcmp(kt->kt_cp, cp)) 13831558Srgrimes kt++; 13841558Srgrimes return kt->kt_i; 13851558Srgrimes} 13861558Srgrimes 13871558Srgrimesvoid 13881558Srgrimessodump(su, which) 13891558Srgrimes register sup su; 13901558Srgrimes char *which; 13911558Srgrimes{ 13921558Srgrimes switch (su->sa.sa_family) { 13931558Srgrimes case AF_LINK: 13941558Srgrimes (void) printf("%s: link %s; ", 13951558Srgrimes which, link_ntoa(&su->sdl)); 13961558Srgrimes break; 13971558Srgrimes case AF_INET: 13981558Srgrimes (void) printf("%s: inet %s; ", 13991558Srgrimes which, inet_ntoa(su->sin.sin_addr)); 14001558Srgrimes break; 140117046Sjulian case AF_APPLETALK: 140217046Sjulian (void) printf("%s: atalk %s; ", 140317046Sjulian which, atalk_ntoa(su->sat.sat_addr)); 140417046Sjulian break; 140514092Swollman#ifdef NS 14061558Srgrimes case AF_NS: 14071558Srgrimes (void) printf("%s: xns %s; ", 14081558Srgrimes which, ns_ntoa(su->sns.sns_addr)); 14091558Srgrimes break; 141014092Swollman#endif 14111558Srgrimes } 14121558Srgrimes (void) fflush(stdout); 14131558Srgrimes} 14141558Srgrimes 14151558Srgrimes/* States*/ 14161558Srgrimes#define VIRGIN 0 14171558Srgrimes#define GOTONE 1 14181558Srgrimes#define GOTTWO 2 14191558Srgrimes/* Inputs */ 14201558Srgrimes#define DIGIT (4*0) 14211558Srgrimes#define END (4*1) 14221558Srgrimes#define DELIM (4*2) 14231558Srgrimes 14241558Srgrimesvoid 14251558Srgrimessockaddr(addr, sa) 14261558Srgrimes register char *addr; 14271558Srgrimes register struct sockaddr *sa; 14281558Srgrimes{ 14291558Srgrimes register char *cp = (char *)sa; 14301558Srgrimes int size = sa->sa_len; 14311558Srgrimes char *cplim = cp + size; 143213171Swollman register int byte = 0, state = VIRGIN, new = 0 /* foil gcc */; 14331558Srgrimes 14341558Srgrimes bzero(cp, size); 14351558Srgrimes cp++; 14361558Srgrimes do { 14371558Srgrimes if ((*addr >= '0') && (*addr <= '9')) { 14381558Srgrimes new = *addr - '0'; 14391558Srgrimes } else if ((*addr >= 'a') && (*addr <= 'f')) { 14401558Srgrimes new = *addr - 'a' + 10; 14411558Srgrimes } else if ((*addr >= 'A') && (*addr <= 'F')) { 14421558Srgrimes new = *addr - 'A' + 10; 14431558Srgrimes } else if (*addr == 0) 14441558Srgrimes state |= END; 14451558Srgrimes else 14461558Srgrimes state |= DELIM; 14471558Srgrimes addr++; 14481558Srgrimes switch (state /* | INPUT */) { 14491558Srgrimes case GOTTWO | DIGIT: 14501558Srgrimes *cp++ = byte; /*FALLTHROUGH*/ 14511558Srgrimes case VIRGIN | DIGIT: 14521558Srgrimes state = GOTONE; byte = new; continue; 14531558Srgrimes case GOTONE | DIGIT: 14541558Srgrimes state = GOTTWO; byte = new + (byte << 4); continue; 14551558Srgrimes default: /* | DELIM */ 14561558Srgrimes state = VIRGIN; *cp++ = byte; byte = 0; continue; 14571558Srgrimes case GOTONE | END: 14581558Srgrimes case GOTTWO | END: 14591558Srgrimes *cp++ = byte; /* FALLTHROUGH */ 14601558Srgrimes case VIRGIN | END: 14611558Srgrimes break; 14621558Srgrimes } 14631558Srgrimes break; 14641558Srgrimes } while (cp < cplim); 14651558Srgrimes sa->sa_len = cp - (char *)sa; 14661558Srgrimes} 146717046Sjulian 146817046Sjulianint 146917046Sjulianatalk_aton(const char *text, struct at_addr *addr) 147017046Sjulian{ 147117046Sjulian u_int net, node; 147217046Sjulian 147317046Sjulian if (sscanf(text, "%u.%u", &net, &node) != 2 147417046Sjulian || net > 0xffff || node > 0xff) 147517046Sjulian return(0); 147617254Sjulian addr->s_net = htons(net); 147717046Sjulian addr->s_node = node; 147817046Sjulian return(1); 147917046Sjulian} 148017046Sjulian 148117046Sjulianchar * 148217046Sjulianatalk_ntoa(struct at_addr at) 148317046Sjulian{ 148417046Sjulian static char buf[20]; 148517046Sjulian 148617254Sjulian (void) snprintf(buf, sizeof(buf), "%u.%u", ntohs(at.s_net), at.s_node); 148717046Sjulian return(buf); 148817046Sjulian} 1489