route.c revision 17265
11558Srgrimes/* 21558Srgrimes * 31558Srgrimes * Copyright (c) 1983, 1989, 1991, 1993 41558Srgrimes * The Regents of the University of California. All rights reserved. 51558Srgrimes * 61558Srgrimes * Redistribution and use in source and binary forms, with or without 71558Srgrimes * modification, are permitted provided that the following conditions 81558Srgrimes * are met: 91558Srgrimes * 1. Redistributions of source code must retain the above copyright 101558Srgrimes * notice, this list of conditions and the following disclaimer. 111558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 121558Srgrimes * notice, this list of conditions and the following disclaimer in the 131558Srgrimes * documentation and/or other materials provided with the distribution. 141558Srgrimes * 3. All advertising materials mentioning features or use of this software 151558Srgrimes * must display the following acknowledgement: 161558Srgrimes * This product includes software developed by the University of 171558Srgrimes * California, Berkeley and its contributors. 181558Srgrimes * 4. Neither the name of the University nor the names of its contributors 191558Srgrimes * may be used to endorse or promote products derived from this software 201558Srgrimes * without specific prior written permission. 211558Srgrimes * 221558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 231558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 241558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 251558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 261558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 271558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 281558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 291558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 301558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 311558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 321558Srgrimes * SUCH DAMAGE. 331558Srgrimes */ 341558Srgrimes 351558Srgrimes#ifndef lint 3613171Swollmanstatic const char copyright[] = 371558Srgrimes"@(#) Copyright (c) 1983, 1989, 1991, 1993\n\ 381558Srgrimes The Regents of the University of California. All rights reserved.\n"; 391558Srgrimes#endif /* not lint */ 401558Srgrimes 411558Srgrimes#ifndef lint 4213171Swollman/* 431558Srgrimesstatic char sccsid[] = "@(#)route.c 8.3 (Berkeley) 3/19/94"; 4413171Swollman*/ 4513171Swollmanstatic const char rcsid[] = 4617265Sjulian "$Id: route.c,v 1.10 1996/07/23 01:18:47 julian Exp $"; 471558Srgrimes#endif /* not lint */ 481558Srgrimes 491558Srgrimes#include <sys/param.h> 501558Srgrimes#include <sys/file.h> 511558Srgrimes#include <sys/socket.h> 521558Srgrimes#include <sys/ioctl.h> 531558Srgrimes#include <sys/mbuf.h> 541558Srgrimes#include <sys/sysctl.h> 551558Srgrimes 561558Srgrimes#include <net/if.h> 571558Srgrimes#include <net/route.h> 581558Srgrimes#include <net/if_dl.h> 591558Srgrimes#include <netinet/in.h> 6017046Sjulian#include <netatalk/at.h> 6114092Swollman#ifdef NS 621558Srgrimes#include <netns/ns.h> 6314092Swollman#endif 6413940Swollman#ifdef ISO 651558Srgrimes#include <netiso/iso.h> 6613940Swollman#endif 6713940Swollman#ifdef CCITT 681558Srgrimes#include <netccitt/x25.h> 6913940Swollman#endif 701558Srgrimes#include <arpa/inet.h> 711558Srgrimes#include <netdb.h> 721558Srgrimes 731558Srgrimes#include <errno.h> 741558Srgrimes#include <unistd.h> 751558Srgrimes#include <stdio.h> 761558Srgrimes#include <ctype.h> 771558Srgrimes#include <stdlib.h> 781558Srgrimes#include <string.h> 791558Srgrimes#include <paths.h> 8013171Swollman#include <err.h> 8113171Swollman#include <sysexits.h> 821558Srgrimes 831558Srgrimesstruct keytab { 841558Srgrimes char *kt_cp; 851558Srgrimes int kt_i; 861558Srgrimes} keywords[] = { 871558Srgrimes#include "keywords.h" 881558Srgrimes {0, 0} 891558Srgrimes}; 901558Srgrimes 911558Srgrimesstruct ortentry route; 921558Srgrimesunion sockunion { 931558Srgrimes struct sockaddr sa; 941558Srgrimes struct sockaddr_in sin; 9517046Sjulian struct sockaddr_at sat; 9614092Swollman#ifdef NS 971558Srgrimes struct sockaddr_ns sns; 9814092Swollman#endif 9913940Swollman#ifdef ISO 1001558Srgrimes struct sockaddr_iso siso; 10113940Swollman#endif 1021558Srgrimes struct sockaddr_dl sdl; 10313940Swollman#ifdef CCITT 1041558Srgrimes struct sockaddr_x25 sx25; 10513940Swollman#endif 1061558Srgrimes} so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp; 1071558Srgrimes 1081558Srgrimestypedef union sockunion *sup; 1091558Srgrimesint pid, rtm_addrs, uid; 1101558Srgrimesint s; 1111558Srgrimesint forcehost, forcenet, doflush, nflag, af, qflag, tflag, keyword(); 1121558Srgrimesint iflag, verbose, aflen = sizeof (struct sockaddr_in); 1131558Srgrimesint locking, lockrest, debugonly; 1141558Srgrimesstruct rt_metrics rt_metrics; 1151558Srgrimesu_long rtm_inits; 1161558Srgrimesstruct in_addr inet_makeaddr(); 11717046Sjulianint atalk_aton __P((const char *, struct at_addr *)); 11817046Sjulianchar *atalk_ntoa __P((struct at_addr)); 1191558Srgrimeschar *routename(), *netname(); 1201558Srgrimesvoid flushroutes(), newroute(), monitor(), sockaddr(), sodump(), bprintf(); 1211558Srgrimesvoid print_getmsg(), print_rtmsg(), pmsg_common(), pmsg_addrs(), mask_addr(); 1221558Srgrimesint getaddr(), rtmsg(), x25_makemask(); 1231558Srgrimesextern char *inet_ntoa(), *iso_ntoa(), *link_ntoa(); 12413940Swollman#ifdef CCITT 12513171Swollmanextern int ccitt_addr __P((char *, struct sockaddr_x25 *)); 12613940Swollman#endif 1271558Srgrimes 12813171Swollman__dead void usage __P((const char *)) __dead2; 12913171Swollman 1301558Srgrimes__dead void 1311558Srgrimesusage(cp) 13213171Swollman const char *cp; 1331558Srgrimes{ 1341558Srgrimes if (cp) 13513171Swollman warnx("bad keyword: %s", cp); 1361558Srgrimes (void) fprintf(stderr, 1371558Srgrimes "usage: route [ -nqv ] cmd [[ -<qualifers> ] args ]\n"); 13813171Swollman exit(EX_USAGE); 1391558Srgrimes /* NOTREACHED */ 1401558Srgrimes} 1411558Srgrimes 1421558Srgrimes#define ROUNDUP(a) \ 1431558Srgrimes ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 1441558Srgrimes#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 1451558Srgrimes 1461558Srgrimesint 1471558Srgrimesmain(argc, argv) 1481558Srgrimes int argc; 1491558Srgrimes char **argv; 1501558Srgrimes{ 1511558Srgrimes extern int optind; 1521558Srgrimes int ch; 1531558Srgrimes 1541558Srgrimes if (argc < 2) 1551558Srgrimes usage((char *)NULL); 1561558Srgrimes 1571558Srgrimes while ((ch = getopt(argc, argv, "nqdtv")) != EOF) 1581558Srgrimes switch(ch) { 1591558Srgrimes case 'n': 1601558Srgrimes nflag = 1; 1611558Srgrimes break; 1621558Srgrimes case 'q': 1631558Srgrimes qflag = 1; 1641558Srgrimes break; 1651558Srgrimes case 'v': 1661558Srgrimes verbose = 1; 1671558Srgrimes break; 1681558Srgrimes case 't': 1691558Srgrimes tflag = 1; 1701558Srgrimes break; 1711558Srgrimes case 'd': 1721558Srgrimes debugonly = 1; 1731558Srgrimes break; 1741558Srgrimes case '?': 1751558Srgrimes default: 1761558Srgrimes usage((char *)NULL); 1771558Srgrimes } 1781558Srgrimes argc -= optind; 1791558Srgrimes argv += optind; 1801558Srgrimes 1811558Srgrimes pid = getpid(); 1821558Srgrimes uid = getuid(); 1831558Srgrimes if (tflag) 1841558Srgrimes s = open("/dev/null", O_WRONLY, 0); 1851558Srgrimes else 1861558Srgrimes s = socket(PF_ROUTE, SOCK_RAW, 0); 1871558Srgrimes if (s < 0) 18813171Swollman err(EX_OSERR, "socket"); 1891558Srgrimes if (*argv) 1901558Srgrimes switch (keyword(*argv)) { 1911558Srgrimes case K_GET: 1921558Srgrimes uid = 0; 1931558Srgrimes /* FALLTHROUGH */ 1941558Srgrimes 1951558Srgrimes case K_CHANGE: 1961558Srgrimes case K_ADD: 1971558Srgrimes case K_DELETE: 1981558Srgrimes newroute(argc, argv); 1991558Srgrimes exit(0); 2001558Srgrimes /* NOTREACHED */ 2011558Srgrimes 2021558Srgrimes case K_MONITOR: 2031558Srgrimes monitor(); 2041558Srgrimes /* NOTREACHED */ 2051558Srgrimes 2061558Srgrimes case K_FLUSH: 2071558Srgrimes flushroutes(argc, argv); 2081558Srgrimes exit(0); 2091558Srgrimes /* NOTREACHED */ 2101558Srgrimes } 2111558Srgrimes usage(*argv); 2121558Srgrimes /* NOTREACHED */ 2131558Srgrimes} 2141558Srgrimes 2151558Srgrimes/* 2161558Srgrimes * Purge all entries in the routing tables not 2171558Srgrimes * associated with network interfaces. 2181558Srgrimes */ 2191558Srgrimesvoid 2201558Srgrimesflushroutes(argc, argv) 2211558Srgrimes int argc; 2221558Srgrimes char *argv[]; 2231558Srgrimes{ 2241558Srgrimes size_t needed; 2251558Srgrimes int mib[6], rlen, seqno; 2261558Srgrimes char *buf, *next, *lim; 2271558Srgrimes register struct rt_msghdr *rtm; 2281558Srgrimes 2291558Srgrimes if (uid) { 23013171Swollman errx(EX_NOPERM, "must be root to alter routing table"); 2311558Srgrimes } 2321558Srgrimes shutdown(s, 0); /* Don't want to read back our messages */ 2331558Srgrimes if (argc > 1) { 2341558Srgrimes argv++; 2351558Srgrimes if (argc == 2 && **argv == '-') 2361558Srgrimes switch (keyword(*argv + 1)) { 2371558Srgrimes case K_INET: 2381558Srgrimes af = AF_INET; 2391558Srgrimes break; 24017046Sjulian case K_ATALK: 24117046Sjulian af = AF_APPLETALK; 24217046Sjulian break; 24314092Swollman#ifdef NS 2441558Srgrimes case K_XNS: 2451558Srgrimes af = AF_NS; 2461558Srgrimes break; 24714092Swollman#endif 2481558Srgrimes case K_LINK: 2491558Srgrimes af = AF_LINK; 2501558Srgrimes break; 25113940Swollman#ifdef ISO 2521558Srgrimes case K_ISO: 2531558Srgrimes case K_OSI: 2541558Srgrimes af = AF_ISO; 2551558Srgrimes break; 25613940Swollman#endif 25713940Swollman#ifdef CCITT 2581558Srgrimes case K_X25: 2591558Srgrimes af = AF_CCITT; 26013940Swollman#endif 2611558Srgrimes default: 2621558Srgrimes goto bad; 2631558Srgrimes } else 2641558Srgrimesbad: usage(*argv); 2651558Srgrimes } 2661558Srgrimes mib[0] = CTL_NET; 2671558Srgrimes mib[1] = PF_ROUTE; 2681558Srgrimes mib[2] = 0; /* protocol */ 2691558Srgrimes mib[3] = 0; /* wildcard address family */ 2701558Srgrimes mib[4] = NET_RT_DUMP; 2711558Srgrimes mib[5] = 0; /* no flags */ 2721558Srgrimes if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 27313171Swollman err(EX_OSERR, "route-sysctl-estimate"); 2741558Srgrimes if ((buf = malloc(needed)) == NULL) 27513171Swollman err(EX_OSERR, "malloc"); 2761558Srgrimes if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 27713171Swollman err(EX_OSERR, "route-sysctl-get"); 2781558Srgrimes lim = buf + needed; 2791558Srgrimes if (verbose) 2801558Srgrimes (void) printf("Examining routing table from sysctl\n"); 2811558Srgrimes seqno = 0; /* ??? */ 2821558Srgrimes for (next = buf; next < lim; next += rtm->rtm_msglen) { 2831558Srgrimes rtm = (struct rt_msghdr *)next; 2841558Srgrimes if (verbose) 2851558Srgrimes print_rtmsg(rtm, rtm->rtm_msglen); 2861558Srgrimes if ((rtm->rtm_flags & RTF_GATEWAY) == 0) 2871558Srgrimes continue; 2881558Srgrimes if (af) { 2891558Srgrimes struct sockaddr *sa = (struct sockaddr *)(rtm + 1); 2901558Srgrimes 2911558Srgrimes if (sa->sa_family != af) 2921558Srgrimes continue; 2931558Srgrimes } 2941558Srgrimes if (debugonly) 2951558Srgrimes continue; 2961558Srgrimes rtm->rtm_type = RTM_DELETE; 2971558Srgrimes rtm->rtm_seq = seqno; 2981558Srgrimes rlen = write(s, next, rtm->rtm_msglen); 2991558Srgrimes if (rlen < (int)rtm->rtm_msglen) { 30013171Swollman warn("write to routing socket"); 3011558Srgrimes (void) printf("got only %d for rlen\n", rlen); 3021558Srgrimes break; 3031558Srgrimes } 3041558Srgrimes seqno++; 3051558Srgrimes if (qflag) 3061558Srgrimes continue; 3071558Srgrimes if (verbose) 3081558Srgrimes print_rtmsg(rtm, rlen); 3091558Srgrimes else { 3101558Srgrimes struct sockaddr *sa = (struct sockaddr *)(rtm + 1); 3111558Srgrimes (void) printf("%-20.20s ", rtm->rtm_flags & RTF_HOST ? 3121558Srgrimes routename(sa) : netname(sa)); 3131558Srgrimes sa = (struct sockaddr *)(sa->sa_len + (char *)sa); 3141558Srgrimes (void) printf("%-20.20s ", routename(sa)); 3151558Srgrimes (void) printf("done\n"); 3161558Srgrimes } 3171558Srgrimes } 3181558Srgrimes} 3191558Srgrimes 3201558Srgrimeschar * 3211558Srgrimesroutename(sa) 3221558Srgrimes struct sockaddr *sa; 3231558Srgrimes{ 3241558Srgrimes register char *cp; 3251558Srgrimes static char line[50]; 3261558Srgrimes struct hostent *hp; 3271558Srgrimes static char domain[MAXHOSTNAMELEN + 1]; 3281558Srgrimes static int first = 1; 32914092Swollman#ifdef NS 3301558Srgrimes char *ns_print(); 33114092Swollman#endif 3321558Srgrimes 3331558Srgrimes if (first) { 3341558Srgrimes first = 0; 3351558Srgrimes if (gethostname(domain, MAXHOSTNAMELEN) == 0 && 3361558Srgrimes (cp = index(domain, '.'))) 3371558Srgrimes (void) strcpy(domain, cp + 1); 3381558Srgrimes else 3391558Srgrimes domain[0] = 0; 3401558Srgrimes } 3411558Srgrimes 3421558Srgrimes if (sa->sa_len == 0) 3431558Srgrimes strcpy(line, "default"); 3441558Srgrimes else switch (sa->sa_family) { 3451558Srgrimes 3461558Srgrimes case AF_INET: 3471558Srgrimes { struct in_addr in; 3481558Srgrimes in = ((struct sockaddr_in *)sa)->sin_addr; 3491558Srgrimes 3501558Srgrimes cp = 0; 3511558Srgrimes if (in.s_addr == INADDR_ANY || sa->sa_len < 4) 3521558Srgrimes cp = "default"; 3531558Srgrimes if (cp == 0 && !nflag) { 3541558Srgrimes hp = gethostbyaddr((char *)&in, sizeof (struct in_addr), 3551558Srgrimes AF_INET); 3561558Srgrimes if (hp) { 3571558Srgrimes if ((cp = index(hp->h_name, '.')) && 3581558Srgrimes !strcmp(cp + 1, domain)) 3591558Srgrimes *cp = 0; 3601558Srgrimes cp = hp->h_name; 3611558Srgrimes } 3621558Srgrimes } 3631558Srgrimes if (cp) 3641558Srgrimes strcpy(line, cp); 3651558Srgrimes else { 36613171Swollman /* XXX - why not inet_ntoa()? */ 36713171Swollman#define C(x) (unsigned)((x) & 0xff) 3681558Srgrimes in.s_addr = ntohl(in.s_addr); 3691558Srgrimes (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), 3701558Srgrimes C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); 3711558Srgrimes } 3721558Srgrimes break; 3731558Srgrimes } 3741558Srgrimes 37517046Sjulian case AF_APPLETALK: 37617046Sjulian (void) snprintf(line, sizeof(line), "atalk %s", 37717046Sjulian atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr)); 37817046Sjulian break; 37917046Sjulian 38014092Swollman#ifdef NS 3811558Srgrimes case AF_NS: 3821558Srgrimes return (ns_print((struct sockaddr_ns *)sa)); 38314092Swollman#endif 3841558Srgrimes 3851558Srgrimes case AF_LINK: 3861558Srgrimes return (link_ntoa((struct sockaddr_dl *)sa)); 3871558Srgrimes 38813940Swollman#ifdef ISO 3891558Srgrimes case AF_ISO: 3901558Srgrimes (void) sprintf(line, "iso %s", 3911558Srgrimes iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr)); 3921558Srgrimes break; 39313940Swollman#endif 3941558Srgrimes default: 3951558Srgrimes { u_short *s = (u_short *)sa; 3961558Srgrimes u_short *slim = s + ((sa->sa_len + 1) >> 1); 3971558Srgrimes char *cp = line + sprintf(line, "(%d)", sa->sa_family); 3981558Srgrimes 3991558Srgrimes while (++s < slim) /* start with sa->sa_data */ 4001558Srgrimes cp += sprintf(cp, " %x", *s); 4011558Srgrimes break; 4021558Srgrimes } 4031558Srgrimes } 4041558Srgrimes return (line); 4051558Srgrimes} 4061558Srgrimes 4071558Srgrimes/* 4081558Srgrimes * Return the name of the network whose address is given. 4091558Srgrimes * The address is assumed to be that of a net or subnet, not a host. 4101558Srgrimes */ 4111558Srgrimeschar * 4121558Srgrimesnetname(sa) 4131558Srgrimes struct sockaddr *sa; 4141558Srgrimes{ 4151558Srgrimes char *cp = 0; 4161558Srgrimes static char line[50]; 4171558Srgrimes struct netent *np = 0; 4181558Srgrimes u_long net, mask; 4191558Srgrimes register u_long i; 4201558Srgrimes int subnetshift; 42114092Swollman#ifdef NS 4221558Srgrimes char *ns_print(); 42314092Swollman#endif 4241558Srgrimes 4251558Srgrimes switch (sa->sa_family) { 4261558Srgrimes 4271558Srgrimes case AF_INET: 4281558Srgrimes { struct in_addr in; 4291558Srgrimes in = ((struct sockaddr_in *)sa)->sin_addr; 4301558Srgrimes 4311558Srgrimes i = in.s_addr = ntohl(in.s_addr); 4321558Srgrimes if (in.s_addr == 0) 4331558Srgrimes cp = "default"; 4341558Srgrimes else if (!nflag) { 4351558Srgrimes if (IN_CLASSA(i)) { 4361558Srgrimes mask = IN_CLASSA_NET; 4371558Srgrimes subnetshift = 8; 4381558Srgrimes } else if (IN_CLASSB(i)) { 4391558Srgrimes mask = IN_CLASSB_NET; 4401558Srgrimes subnetshift = 8; 4411558Srgrimes } else { 4421558Srgrimes mask = IN_CLASSC_NET; 4431558Srgrimes subnetshift = 4; 4441558Srgrimes } 4451558Srgrimes /* 4461558Srgrimes * If there are more bits than the standard mask 4471558Srgrimes * would suggest, subnets must be in use. 4481558Srgrimes * Guess at the subnet mask, assuming reasonable 4491558Srgrimes * width subnet fields. 4501558Srgrimes */ 4511558Srgrimes while (in.s_addr &~ mask) 4521558Srgrimes mask = (long)mask >> subnetshift; 4531558Srgrimes net = in.s_addr & mask; 4541558Srgrimes while ((mask & 1) == 0) 4551558Srgrimes mask >>= 1, net >>= 1; 4561558Srgrimes np = getnetbyaddr(net, AF_INET); 4571558Srgrimes if (np) 4581558Srgrimes cp = np->n_name; 4591558Srgrimes } 4601558Srgrimes if (cp) 4611558Srgrimes strcpy(line, cp); 4621558Srgrimes else if ((in.s_addr & 0xffffff) == 0) 4631558Srgrimes (void) sprintf(line, "%u", C(in.s_addr >> 24)); 4641558Srgrimes else if ((in.s_addr & 0xffff) == 0) 4651558Srgrimes (void) sprintf(line, "%u.%u", C(in.s_addr >> 24), 4661558Srgrimes C(in.s_addr >> 16)); 4671558Srgrimes else if ((in.s_addr & 0xff) == 0) 4681558Srgrimes (void) sprintf(line, "%u.%u.%u", C(in.s_addr >> 24), 4691558Srgrimes C(in.s_addr >> 16), C(in.s_addr >> 8)); 4701558Srgrimes else 4711558Srgrimes (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), 4721558Srgrimes C(in.s_addr >> 16), C(in.s_addr >> 8), 4731558Srgrimes C(in.s_addr)); 4741558Srgrimes break; 4751558Srgrimes } 4761558Srgrimes 47717046Sjulian case AF_APPLETALK: 47817046Sjulian (void) snprintf(line, sizeof(line), "atalk %s", 47917046Sjulian atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr)); 48017046Sjulian break; 48117046Sjulian 48214092Swollman#ifdef NS 4831558Srgrimes case AF_NS: 4841558Srgrimes return (ns_print((struct sockaddr_ns *)sa)); 4851558Srgrimes break; 48614092Swollman#endif 4871558Srgrimes 4881558Srgrimes case AF_LINK: 4891558Srgrimes return (link_ntoa((struct sockaddr_dl *)sa)); 4901558Srgrimes 49113940Swollman#ifdef ISO 4921558Srgrimes case AF_ISO: 4931558Srgrimes (void) sprintf(line, "iso %s", 4941558Srgrimes iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr)); 4951558Srgrimes break; 49613940Swollman#endif 4971558Srgrimes 4981558Srgrimes default: 4991558Srgrimes { u_short *s = (u_short *)sa->sa_data; 5001558Srgrimes u_short *slim = s + ((sa->sa_len + 1)>>1); 5011558Srgrimes char *cp = line + sprintf(line, "af %d:", sa->sa_family); 5021558Srgrimes 5031558Srgrimes while (s < slim) 5041558Srgrimes cp += sprintf(cp, " %x", *s++); 5051558Srgrimes break; 5061558Srgrimes } 5071558Srgrimes } 5081558Srgrimes return (line); 5091558Srgrimes} 5101558Srgrimes 5111558Srgrimesvoid 5121558Srgrimesset_metric(value, key) 5131558Srgrimes char *value; 5141558Srgrimes int key; 5151558Srgrimes{ 5161558Srgrimes int flag = 0; 5171558Srgrimes u_long noval, *valp = &noval; 5181558Srgrimes 5191558Srgrimes switch (key) { 5201558Srgrimes#define caseof(x, y, z) case x: valp = &rt_metrics.z; flag = y; break 5211558Srgrimes caseof(K_MTU, RTV_MTU, rmx_mtu); 5221558Srgrimes caseof(K_HOPCOUNT, RTV_HOPCOUNT, rmx_hopcount); 5231558Srgrimes caseof(K_EXPIRE, RTV_EXPIRE, rmx_expire); 5241558Srgrimes caseof(K_RECVPIPE, RTV_RPIPE, rmx_recvpipe); 5251558Srgrimes caseof(K_SENDPIPE, RTV_SPIPE, rmx_sendpipe); 5261558Srgrimes caseof(K_SSTHRESH, RTV_SSTHRESH, rmx_ssthresh); 5271558Srgrimes caseof(K_RTT, RTV_RTT, rmx_rtt); 5281558Srgrimes caseof(K_RTTVAR, RTV_RTTVAR, rmx_rttvar); 5291558Srgrimes } 5301558Srgrimes rtm_inits |= flag; 5311558Srgrimes if (lockrest || locking) 5321558Srgrimes rt_metrics.rmx_locks |= flag; 5331558Srgrimes if (locking) 5341558Srgrimes locking = 0; 5351558Srgrimes *valp = atoi(value); 5361558Srgrimes} 5371558Srgrimes 5381558Srgrimesvoid 5391558Srgrimesnewroute(argc, argv) 5401558Srgrimes int argc; 5411558Srgrimes register char **argv; 5421558Srgrimes{ 5431558Srgrimes char *cmd, *dest = "", *gateway = "", *err; 5441558Srgrimes int ishost = 0, ret, attempts, oerrno, flags = RTF_STATIC; 5451558Srgrimes int key; 5461558Srgrimes struct hostent *hp = 0; 5471558Srgrimes 5481558Srgrimes if (uid) { 54913171Swollman errx(EX_NOPERM, "must be root to alter routing table"); 5501558Srgrimes } 5511558Srgrimes cmd = argv[0]; 5521558Srgrimes if (*cmd != 'g') 5531558Srgrimes shutdown(s, 0); /* Don't want to read back our messages */ 5541558Srgrimes while (--argc > 0) { 5551558Srgrimes if (**(++argv)== '-') { 5561558Srgrimes switch (key = keyword(1 + *argv)) { 5571558Srgrimes case K_LINK: 5581558Srgrimes af = AF_LINK; 5591558Srgrimes aflen = sizeof(struct sockaddr_dl); 5601558Srgrimes break; 56113940Swollman#ifdef ISO 5621558Srgrimes case K_OSI: 5631558Srgrimes case K_ISO: 5641558Srgrimes af = AF_ISO; 5651558Srgrimes aflen = sizeof(struct sockaddr_iso); 5661558Srgrimes break; 56713940Swollman#endif 5681558Srgrimes case K_INET: 5691558Srgrimes af = AF_INET; 5701558Srgrimes aflen = sizeof(struct sockaddr_in); 5711558Srgrimes break; 57217046Sjulian case K_ATALK: 57317046Sjulian af = AF_APPLETALK; 57417046Sjulian aflen = sizeof(struct sockaddr_at); 57517046Sjulian break; 57613940Swollman#ifdef CCITT 5771558Srgrimes case K_X25: 5781558Srgrimes af = AF_CCITT; 5791558Srgrimes aflen = sizeof(struct sockaddr_x25); 5801558Srgrimes break; 58113940Swollman#endif 5821558Srgrimes case K_SA: 5831558Srgrimes af = PF_ROUTE; 5841558Srgrimes aflen = sizeof(union sockunion); 5851558Srgrimes break; 58614092Swollman#ifdef NS 5871558Srgrimes case K_XNS: 5881558Srgrimes af = AF_NS; 5891558Srgrimes aflen = sizeof(struct sockaddr_ns); 5901558Srgrimes break; 59114092Swollman#endif 5921558Srgrimes case K_IFACE: 5931558Srgrimes case K_INTERFACE: 5941558Srgrimes iflag++; 5952787Spst break; 5961558Srgrimes case K_NOSTATIC: 5971558Srgrimes flags &= ~RTF_STATIC; 5981558Srgrimes break; 5991558Srgrimes case K_LOCK: 6001558Srgrimes locking = 1; 6011558Srgrimes break; 6021558Srgrimes case K_LOCKREST: 6031558Srgrimes lockrest = 1; 6041558Srgrimes break; 6051558Srgrimes case K_HOST: 6061558Srgrimes forcehost++; 6071558Srgrimes break; 6081558Srgrimes case K_REJECT: 6091558Srgrimes flags |= RTF_REJECT; 6101558Srgrimes break; 6111558Srgrimes case K_BLACKHOLE: 6121558Srgrimes flags |= RTF_BLACKHOLE; 6131558Srgrimes break; 6141558Srgrimes case K_PROTO1: 6151558Srgrimes flags |= RTF_PROTO1; 6161558Srgrimes break; 6171558Srgrimes case K_PROTO2: 6181558Srgrimes flags |= RTF_PROTO2; 6191558Srgrimes break; 6201558Srgrimes case K_CLONING: 6211558Srgrimes flags |= RTF_CLONING; 6221558Srgrimes break; 6231558Srgrimes case K_XRESOLVE: 6241558Srgrimes flags |= RTF_XRESOLVE; 6251558Srgrimes break; 6261558Srgrimes case K_STATIC: 6271558Srgrimes flags |= RTF_STATIC; 6281558Srgrimes break; 6291558Srgrimes case K_IFA: 6301558Srgrimes argc--; 6311558Srgrimes (void) getaddr(RTA_IFA, *++argv, 0); 6321558Srgrimes break; 6331558Srgrimes case K_IFP: 6341558Srgrimes argc--; 6351558Srgrimes (void) getaddr(RTA_IFP, *++argv, 0); 6361558Srgrimes break; 6371558Srgrimes case K_GENMASK: 6381558Srgrimes argc--; 6391558Srgrimes (void) getaddr(RTA_GENMASK, *++argv, 0); 6401558Srgrimes break; 6411558Srgrimes case K_GATEWAY: 6421558Srgrimes argc--; 6431558Srgrimes (void) getaddr(RTA_GATEWAY, *++argv, 0); 6441558Srgrimes break; 6451558Srgrimes case K_DST: 6461558Srgrimes argc--; 6471558Srgrimes ishost = getaddr(RTA_DST, *++argv, &hp); 6481558Srgrimes dest = *argv; 6491558Srgrimes break; 6501558Srgrimes case K_NETMASK: 6511558Srgrimes argc--; 6521558Srgrimes (void) getaddr(RTA_NETMASK, *++argv, 0); 6531558Srgrimes /* FALLTHROUGH */ 6541558Srgrimes case K_NET: 6551558Srgrimes forcenet++; 6561558Srgrimes break; 6571558Srgrimes case K_MTU: 6581558Srgrimes case K_HOPCOUNT: 6591558Srgrimes case K_EXPIRE: 6601558Srgrimes case K_RECVPIPE: 6611558Srgrimes case K_SENDPIPE: 6621558Srgrimes case K_SSTHRESH: 6631558Srgrimes case K_RTT: 6641558Srgrimes case K_RTTVAR: 6651558Srgrimes argc--; 6661558Srgrimes set_metric(*++argv, key); 6671558Srgrimes break; 6681558Srgrimes default: 6691558Srgrimes usage(1+*argv); 6701558Srgrimes } 6711558Srgrimes } else { 6721558Srgrimes if ((rtm_addrs & RTA_DST) == 0) { 6731558Srgrimes dest = *argv; 6741558Srgrimes ishost = getaddr(RTA_DST, *argv, &hp); 6751558Srgrimes } else if ((rtm_addrs & RTA_GATEWAY) == 0) { 6761558Srgrimes gateway = *argv; 6771558Srgrimes (void) getaddr(RTA_GATEWAY, *argv, &hp); 6781558Srgrimes } else { 67913171Swollman#ifdef CRUFT 6801558Srgrimes int ret = atoi(*argv); 6811558Srgrimes 6821558Srgrimes if (ret == 0) { 6831558Srgrimes if (strcmp(*argv, "0") == 0) 6841558Srgrimes printf("%s,%s", 6851558Srgrimes "old usage of trailing 0", 6861558Srgrimes "assuming route to if\n"); 6871558Srgrimes else 6881558Srgrimes usage((char *)NULL); 6891558Srgrimes iflag = 1; 6901558Srgrimes continue; 6911558Srgrimes } else if (ret > 0 && ret < 10) { 6921558Srgrimes printf("old usage of trailing digit, "); 6931558Srgrimes printf("assuming route via gateway\n"); 6941558Srgrimes iflag = 0; 6951558Srgrimes continue; 6961558Srgrimes } 69713171Swollman#endif 6981558Srgrimes (void) getaddr(RTA_NETMASK, *argv, 0); 6991558Srgrimes } 7001558Srgrimes } 7011558Srgrimes } 7021558Srgrimes if (forcehost) 7031558Srgrimes ishost = 1; 7041558Srgrimes if (forcenet) 7051558Srgrimes ishost = 0; 7061558Srgrimes flags |= RTF_UP; 7071558Srgrimes if (ishost) 7081558Srgrimes flags |= RTF_HOST; 7091558Srgrimes if (iflag == 0) 7101558Srgrimes flags |= RTF_GATEWAY; 7111558Srgrimes for (attempts = 1; ; attempts++) { 7121558Srgrimes errno = 0; 7131558Srgrimes if ((ret = rtmsg(*cmd, flags)) == 0) 7141558Srgrimes break; 7151558Srgrimes if (errno != ENETUNREACH && errno != ESRCH) 7161558Srgrimes break; 7171558Srgrimes if (af == AF_INET && *gateway && hp && hp->h_addr_list[1]) { 7181558Srgrimes hp->h_addr_list++; 7191558Srgrimes bcopy(hp->h_addr_list[0], &so_gate.sin.sin_addr, 7201558Srgrimes hp->h_length); 7211558Srgrimes } else 7221558Srgrimes break; 7231558Srgrimes } 7241558Srgrimes if (*cmd == 'g') 7251558Srgrimes exit(0); 7261558Srgrimes oerrno = errno; 7271558Srgrimes (void) printf("%s %s %s", cmd, ishost? "host" : "net", dest); 7281558Srgrimes if (*gateway) { 7291558Srgrimes (void) printf(": gateway %s", gateway); 7301558Srgrimes if (attempts > 1 && ret == 0 && af == AF_INET) 7311558Srgrimes (void) printf(" (%s)", 7321558Srgrimes inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr)); 7331558Srgrimes } 7341558Srgrimes if (ret == 0) 7351558Srgrimes (void) printf("\n"); 7361558Srgrimes else { 7371558Srgrimes switch (oerrno) { 7381558Srgrimes case ESRCH: 7391558Srgrimes err = "not in table"; 7401558Srgrimes break; 7411558Srgrimes case EBUSY: 7421558Srgrimes err = "entry in use"; 7431558Srgrimes break; 7441558Srgrimes case ENOBUFS: 7451558Srgrimes err = "routing table overflow"; 7461558Srgrimes break; 7471558Srgrimes default: 7481558Srgrimes err = strerror(oerrno); 7491558Srgrimes break; 7501558Srgrimes } 7511558Srgrimes (void) printf(": %s\n", err); 7521558Srgrimes } 7531558Srgrimes} 7541558Srgrimes 7551558Srgrimesvoid 7561558Srgrimesinet_makenetandmask(net, sin) 7571558Srgrimes u_long net; 7581558Srgrimes register struct sockaddr_in *sin; 7591558Srgrimes{ 7601558Srgrimes u_long addr, mask = 0; 7611558Srgrimes register char *cp; 7621558Srgrimes 7631558Srgrimes rtm_addrs |= RTA_NETMASK; 7641558Srgrimes if (net == 0) 7651558Srgrimes mask = addr = 0; 7661558Srgrimes else if (net < 128) { 7671558Srgrimes addr = net << IN_CLASSA_NSHIFT; 7681558Srgrimes mask = IN_CLASSA_NET; 7691558Srgrimes } else if (net < 65536) { 7701558Srgrimes addr = net << IN_CLASSB_NSHIFT; 7711558Srgrimes mask = IN_CLASSB_NET; 7721558Srgrimes } else if (net < 16777216L) { 7731558Srgrimes addr = net << IN_CLASSC_NSHIFT; 7741558Srgrimes mask = IN_CLASSC_NET; 7751558Srgrimes } else { 7761558Srgrimes addr = net; 7771558Srgrimes if ((addr & IN_CLASSA_HOST) == 0) 7781558Srgrimes mask = IN_CLASSA_NET; 7791558Srgrimes else if ((addr & IN_CLASSB_HOST) == 0) 7801558Srgrimes mask = IN_CLASSB_NET; 7811558Srgrimes else if ((addr & IN_CLASSC_HOST) == 0) 7821558Srgrimes mask = IN_CLASSC_NET; 7831558Srgrimes else 7841558Srgrimes mask = -1; 7851558Srgrimes } 7861558Srgrimes sin->sin_addr.s_addr = htonl(addr); 7871558Srgrimes sin = &so_mask.sin; 7881558Srgrimes sin->sin_addr.s_addr = htonl(mask); 7891558Srgrimes sin->sin_len = 0; 7901558Srgrimes sin->sin_family = 0; 7911558Srgrimes cp = (char *)(&sin->sin_addr + 1); 7921558Srgrimes while (*--cp == 0 && cp > (char *)sin) 7931558Srgrimes ; 7941558Srgrimes sin->sin_len = 1 + cp - (char *)sin; 7951558Srgrimes} 7961558Srgrimes 7971558Srgrimes/* 7981558Srgrimes * Interpret an argument as a network address of some kind, 7991558Srgrimes * returning 1 if a host address, 0 if a network address. 8001558Srgrimes */ 8011558Srgrimesint 8021558Srgrimesgetaddr(which, s, hpp) 8031558Srgrimes int which; 8041558Srgrimes char *s; 8051558Srgrimes struct hostent **hpp; 8061558Srgrimes{ 8071558Srgrimes register sup su; 80814092Swollman#ifdef NS 8091558Srgrimes struct ns_addr ns_addr(); 81014092Swollman#endif 81113940Swollman#ifdef ISO 8121558Srgrimes struct iso_addr *iso_addr(); 81313940Swollman#endif 8141558Srgrimes struct hostent *hp; 8151558Srgrimes struct netent *np; 8161558Srgrimes u_long val; 8171558Srgrimes 8181558Srgrimes if (af == 0) { 8191558Srgrimes af = AF_INET; 8201558Srgrimes aflen = sizeof(struct sockaddr_in); 8211558Srgrimes } 8221558Srgrimes rtm_addrs |= which; 8231558Srgrimes switch (which) { 8241558Srgrimes case RTA_DST: 8251558Srgrimes su = &so_dst; 8261558Srgrimes su->sa.sa_family = af; 8271558Srgrimes break; 8281558Srgrimes case RTA_GATEWAY: 8291558Srgrimes su = &so_gate; 8301558Srgrimes su->sa.sa_family = af; 8311558Srgrimes break; 8321558Srgrimes case RTA_NETMASK: 8331558Srgrimes su = &so_mask; 8341558Srgrimes break; 8351558Srgrimes case RTA_GENMASK: 8361558Srgrimes su = &so_genmask; 8371558Srgrimes break; 8381558Srgrimes case RTA_IFP: 8391558Srgrimes su = &so_ifp; 8401558Srgrimes su->sa.sa_family = af; 8411558Srgrimes break; 8421558Srgrimes case RTA_IFA: 8431558Srgrimes su = &so_ifa; 8441558Srgrimes su->sa.sa_family = af; 8451558Srgrimes break; 8461558Srgrimes default: 8471558Srgrimes usage("Internal Error"); 8481558Srgrimes /*NOTREACHED*/ 8491558Srgrimes } 8501558Srgrimes su->sa.sa_len = aflen; 8511558Srgrimes if (strcmp(s, "default") == 0) { 8521558Srgrimes switch (which) { 8531558Srgrimes case RTA_DST: 8541558Srgrimes forcenet++; 8551558Srgrimes (void) getaddr(RTA_NETMASK, s, 0); 8561558Srgrimes break; 8571558Srgrimes case RTA_NETMASK: 8581558Srgrimes case RTA_GENMASK: 8591558Srgrimes su->sa.sa_len = 0; 8601558Srgrimes } 8611558Srgrimes return (0); 8621558Srgrimes } 8631558Srgrimes switch (af) { 86414092Swollman#ifdef NS 8651558Srgrimes case AF_NS: 8661558Srgrimes if (which == RTA_DST) { 8671558Srgrimes extern short ns_bh[3]; 8681558Srgrimes struct sockaddr_ns *sms = &(so_mask.sns); 8691558Srgrimes bzero((char *)sms, sizeof(*sms)); 8701558Srgrimes sms->sns_family = 0; 8711558Srgrimes sms->sns_len = 6; 8721558Srgrimes sms->sns_addr.x_net = *(union ns_net *)ns_bh; 8731558Srgrimes rtm_addrs |= RTA_NETMASK; 8741558Srgrimes } 8751558Srgrimes su->sns.sns_addr = ns_addr(s); 8761558Srgrimes return (!ns_nullhost(su->sns.sns_addr)); 87714092Swollman#endif 8781558Srgrimes 87913940Swollman#ifdef ISO 8801558Srgrimes case AF_OSI: 8811558Srgrimes su->siso.siso_addr = *iso_addr(s); 8821558Srgrimes if (which == RTA_NETMASK || which == RTA_GENMASK) { 8831558Srgrimes register char *cp = (char *)TSEL(&su->siso); 8841558Srgrimes su->siso.siso_nlen = 0; 8851558Srgrimes do {--cp ;} while ((cp > (char *)su) && (*cp == 0)); 8861558Srgrimes su->siso.siso_len = 1 + cp - (char *)su; 8871558Srgrimes } 8881558Srgrimes return (1); 88913940Swollman#endif 8901558Srgrimes 89117046Sjulian case AF_APPLETALK: 89217046Sjulian if (!atalk_aton(s, &su->sat.sat_addr)) 89317046Sjulian errx(EX_NOHOST, "bad address: %s", s); 89417265Sjulian rtm_addrs |= RTA_NETMASK; 89517265Sjulian return(forcehost || su->sat.sat_addr.s_node != 0); 89617046Sjulian 8971558Srgrimes case AF_LINK: 8981558Srgrimes link_addr(s, &su->sdl); 8991558Srgrimes return (1); 9001558Srgrimes 90113940Swollman#ifdef ISO 9021558Srgrimes case AF_CCITT: 9031558Srgrimes ccitt_addr(s, &su->sx25); 9041558Srgrimes return (which == RTA_DST ? x25_makemask() : 1); 90513940Swollman#endif 9061558Srgrimes 9071558Srgrimes case PF_ROUTE: 9081558Srgrimes su->sa.sa_len = sizeof(*su); 9091558Srgrimes sockaddr(s, &su->sa); 9101558Srgrimes return (1); 9111558Srgrimes 9121558Srgrimes case AF_INET: 9131558Srgrimes default: 9141558Srgrimes break; 9151558Srgrimes } 9161558Srgrimes 9171558Srgrimes if (hpp == NULL) 9181558Srgrimes hpp = &hp; 9191558Srgrimes *hpp = NULL; 92014132Smpp if (((val = inet_addr(s)) != INADDR_NONE) && 9211558Srgrimes (which != RTA_DST || forcenet == 0)) { 9221558Srgrimes su->sin.sin_addr.s_addr = val; 9231558Srgrimes if (inet_lnaof(su->sin.sin_addr) != INADDR_ANY) 9241558Srgrimes return (1); 9251558Srgrimes else { 9261558Srgrimes val = ntohl(val); 9271558Srgrimes goto netdone; 9281558Srgrimes } 9291558Srgrimes } 93014132Smpp if ((val = inet_network(s)) != INADDR_NONE || 9311558Srgrimes ((np = getnetbyname(s)) != NULL && (val = np->n_net) != 0)) { 9321558Srgrimesnetdone: 9331558Srgrimes if (which == RTA_DST) 9341558Srgrimes inet_makenetandmask(val, &su->sin); 9351558Srgrimes return (0); 9361558Srgrimes } 9371558Srgrimes hp = gethostbyname(s); 9381558Srgrimes if (hp) { 9391558Srgrimes *hpp = hp; 9401558Srgrimes su->sin.sin_family = hp->h_addrtype; 9411558Srgrimes bcopy(hp->h_addr, (char *)&su->sin.sin_addr, hp->h_length); 9421558Srgrimes return (1); 9431558Srgrimes } 94413515Smpp errx(EX_NOHOST, "bad address: %s", s); 9451558Srgrimes} 9461558Srgrimes 94713940Swollman#ifdef CCITT 9481558Srgrimesint 9491558Srgrimesx25_makemask() 9501558Srgrimes{ 9511558Srgrimes register char *cp; 9521558Srgrimes 9531558Srgrimes if ((rtm_addrs & RTA_NETMASK) == 0) { 9541558Srgrimes rtm_addrs |= RTA_NETMASK; 9551558Srgrimes for (cp = (char *)&so_mask.sx25.x25_net; 9561558Srgrimes cp < &so_mask.sx25.x25_opts.op_flags; cp++) 9571558Srgrimes *cp = -1; 9581558Srgrimes so_mask.sx25.x25_len = (u_char)&(((sup)0)->sx25.x25_opts); 9591558Srgrimes } 9601558Srgrimes return 0; 9611558Srgrimes} 96213940Swollman#endif 9631558Srgrimes 96414092Swollman#ifdef NS 9651558Srgrimesshort ns_nullh[] = {0,0,0}; 9661558Srgrimesshort ns_bh[] = {-1,-1,-1}; 9671558Srgrimes 9681558Srgrimeschar * 9691558Srgrimesns_print(sns) 9701558Srgrimes struct sockaddr_ns *sns; 9711558Srgrimes{ 9721558Srgrimes struct ns_addr work; 9731558Srgrimes union { union ns_net net_e; u_long long_e; } net; 9741558Srgrimes u_short port; 9751558Srgrimes static char mybuf[50], cport[10], chost[25]; 9761558Srgrimes char *host = ""; 9771558Srgrimes register char *p; 9781558Srgrimes register u_char *q; 9791558Srgrimes 9801558Srgrimes work = sns->sns_addr; 9811558Srgrimes port = ntohs(work.x_port); 9821558Srgrimes work.x_port = 0; 9831558Srgrimes net.net_e = work.x_net; 9841558Srgrimes if (ns_nullhost(work) && net.long_e == 0) { 9851558Srgrimes if (!port) 9861558Srgrimes return ("*.*"); 9871558Srgrimes (void) sprintf(mybuf, "*.%XH", port); 9881558Srgrimes return (mybuf); 9891558Srgrimes } 9901558Srgrimes 9911558Srgrimes if (bcmp((char *)ns_bh, (char *)work.x_host.c_host, 6) == 0) 9921558Srgrimes host = "any"; 9931558Srgrimes else if (bcmp((char *)ns_nullh, (char *)work.x_host.c_host, 6) == 0) 9941558Srgrimes host = "*"; 9951558Srgrimes else { 9961558Srgrimes q = work.x_host.c_host; 9971558Srgrimes (void) sprintf(chost, "%02X%02X%02X%02X%02X%02XH", 9981558Srgrimes q[0], q[1], q[2], q[3], q[4], q[5]); 9991558Srgrimes for (p = chost; *p == '0' && p < chost + 12; p++) 10001558Srgrimes /* void */; 10011558Srgrimes host = p; 10021558Srgrimes } 10031558Srgrimes if (port) 10041558Srgrimes (void) sprintf(cport, ".%XH", htons(port)); 10051558Srgrimes else 10061558Srgrimes *cport = 0; 10071558Srgrimes 100813171Swollman (void) sprintf(mybuf,"%lxH.%s%s", (unsigned long)ntohl(net.long_e), 100913171Swollman host, cport); 10101558Srgrimes return (mybuf); 10111558Srgrimes} 101214092Swollman#endif 10131558Srgrimes 10141558Srgrimesvoid 10151558Srgrimesinterfaces() 10161558Srgrimes{ 10171558Srgrimes size_t needed; 10181558Srgrimes int mib[6]; 10191558Srgrimes char *buf, *lim, *next; 10201558Srgrimes register struct rt_msghdr *rtm; 10211558Srgrimes 10221558Srgrimes mib[0] = CTL_NET; 10231558Srgrimes mib[1] = PF_ROUTE; 10241558Srgrimes mib[2] = 0; /* protocol */ 10251558Srgrimes mib[3] = 0; /* wildcard address family */ 10261558Srgrimes mib[4] = NET_RT_IFLIST; 10271558Srgrimes mib[5] = 0; /* no flags */ 10281558Srgrimes if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 102913171Swollman err(EX_OSERR, "route-sysctl-estimate"); 10301558Srgrimes if ((buf = malloc(needed)) == NULL) 103113171Swollman err(EX_OSERR, "malloc"); 10321558Srgrimes if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) 103313171Swollman err(EX_OSERR, "actual retrieval of interface table"); 10341558Srgrimes lim = buf + needed; 10351558Srgrimes for (next = buf; next < lim; next += rtm->rtm_msglen) { 10361558Srgrimes rtm = (struct rt_msghdr *)next; 10371558Srgrimes print_rtmsg(rtm, rtm->rtm_msglen); 10381558Srgrimes } 10391558Srgrimes} 10401558Srgrimes 10411558Srgrimesvoid 10421558Srgrimesmonitor() 10431558Srgrimes{ 10441558Srgrimes int n; 10451558Srgrimes char msg[2048]; 10461558Srgrimes 10471558Srgrimes verbose = 1; 10481558Srgrimes if (debugonly) { 10491558Srgrimes interfaces(); 10501558Srgrimes exit(0); 10511558Srgrimes } 10521558Srgrimes for(;;) { 10531558Srgrimes n = read(s, msg, 2048); 10541558Srgrimes (void) printf("got message of size %d\n", n); 10551558Srgrimes print_rtmsg((struct rt_msghdr *)msg, n); 10561558Srgrimes } 10571558Srgrimes} 10581558Srgrimes 10591558Srgrimesstruct { 10601558Srgrimes struct rt_msghdr m_rtm; 10611558Srgrimes char m_space[512]; 10621558Srgrimes} m_rtmsg; 10631558Srgrimes 10641558Srgrimesint 10651558Srgrimesrtmsg(cmd, flags) 10661558Srgrimes int cmd, flags; 10671558Srgrimes{ 10681558Srgrimes static int seq; 10691558Srgrimes int rlen; 10701558Srgrimes register char *cp = m_rtmsg.m_space; 10711558Srgrimes register int l; 10721558Srgrimes 10731558Srgrimes#define NEXTADDR(w, u) \ 10741558Srgrimes if (rtm_addrs & (w)) {\ 10751558Srgrimes l = ROUNDUP(u.sa.sa_len); bcopy((char *)&(u), cp, l); cp += l;\ 10761558Srgrimes if (verbose) sodump(&(u),"u");\ 10771558Srgrimes } 10781558Srgrimes 10791558Srgrimes errno = 0; 10801558Srgrimes bzero((char *)&m_rtmsg, sizeof(m_rtmsg)); 10811558Srgrimes if (cmd == 'a') 10821558Srgrimes cmd = RTM_ADD; 10831558Srgrimes else if (cmd == 'c') 10841558Srgrimes cmd = RTM_CHANGE; 10851558Srgrimes else if (cmd == 'g') { 10861558Srgrimes cmd = RTM_GET; 10871558Srgrimes if (so_ifp.sa.sa_family == 0) { 108813171Swollman so_ifp.sa.sa_family = AF_LINK; 108913171Swollman so_ifp.sa.sa_len = sizeof(struct sockaddr_dl); 10901558Srgrimes rtm_addrs |= RTA_IFP; 10911558Srgrimes } 10921558Srgrimes } else 10931558Srgrimes cmd = RTM_DELETE; 10941558Srgrimes#define rtm m_rtmsg.m_rtm 10951558Srgrimes rtm.rtm_type = cmd; 10961558Srgrimes rtm.rtm_flags = flags; 10971558Srgrimes rtm.rtm_version = RTM_VERSION; 10981558Srgrimes rtm.rtm_seq = ++seq; 10991558Srgrimes rtm.rtm_addrs = rtm_addrs; 11001558Srgrimes rtm.rtm_rmx = rt_metrics; 11011558Srgrimes rtm.rtm_inits = rtm_inits; 11021558Srgrimes 11031558Srgrimes if (rtm_addrs & RTA_NETMASK) 11041558Srgrimes mask_addr(); 11051558Srgrimes NEXTADDR(RTA_DST, so_dst); 11061558Srgrimes NEXTADDR(RTA_GATEWAY, so_gate); 11071558Srgrimes NEXTADDR(RTA_NETMASK, so_mask); 11081558Srgrimes NEXTADDR(RTA_GENMASK, so_genmask); 11091558Srgrimes NEXTADDR(RTA_IFP, so_ifp); 11101558Srgrimes NEXTADDR(RTA_IFA, so_ifa); 11111558Srgrimes rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; 11121558Srgrimes if (verbose) 11131558Srgrimes print_rtmsg(&rtm, l); 11141558Srgrimes if (debugonly) 11151558Srgrimes return (0); 11161558Srgrimes if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) { 11171558Srgrimes perror("writing to routing socket"); 11181558Srgrimes return (-1); 11191558Srgrimes } 11201558Srgrimes if (cmd == RTM_GET) { 11211558Srgrimes do { 11221558Srgrimes l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); 11231558Srgrimes } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid)); 11241558Srgrimes if (l < 0) 112513171Swollman warn("read from routing socket"); 11261558Srgrimes else 11271558Srgrimes print_getmsg(&rtm, l); 11281558Srgrimes } 11291558Srgrimes#undef rtm 11301558Srgrimes return (0); 11311558Srgrimes} 11321558Srgrimes 11331558Srgrimesvoid 11341558Srgrimesmask_addr() 11351558Srgrimes{ 11361558Srgrimes int olen = so_mask.sa.sa_len; 11371558Srgrimes register char *cp1 = olen + (char *)&so_mask, *cp2; 11381558Srgrimes 11391558Srgrimes for (so_mask.sa.sa_len = 0; cp1 > (char *)&so_mask; ) 11401558Srgrimes if (*--cp1 != 0) { 11411558Srgrimes so_mask.sa.sa_len = 1 + cp1 - (char *)&so_mask; 11421558Srgrimes break; 11431558Srgrimes } 11441558Srgrimes if ((rtm_addrs & RTA_DST) == 0) 11451558Srgrimes return; 11461558Srgrimes switch (so_dst.sa.sa_family) { 114714092Swollman#ifdef NS 11481558Srgrimes case AF_NS: 114914092Swollman#endif 11501558Srgrimes case AF_INET: 115117046Sjulian case AF_APPLETALK: 115213940Swollman#ifdef CCITT 11531558Srgrimes case AF_CCITT: 115413940Swollman#endif 11551558Srgrimes case 0: 11561558Srgrimes return; 115713940Swollman#ifdef ISO 11581558Srgrimes case AF_ISO: 11591558Srgrimes olen = MIN(so_dst.siso.siso_nlen, 11601558Srgrimes MAX(so_mask.sa.sa_len - 6, 0)); 11611558Srgrimes break; 116213940Swollman#endif 11631558Srgrimes } 11641558Srgrimes cp1 = so_mask.sa.sa_len + 1 + (char *)&so_dst; 11651558Srgrimes cp2 = so_dst.sa.sa_len + 1 + (char *)&so_dst; 11661558Srgrimes while (cp2 > cp1) 11671558Srgrimes *--cp2 = 0; 11681558Srgrimes cp2 = so_mask.sa.sa_len + 1 + (char *)&so_mask; 11691558Srgrimes while (cp1 > so_dst.sa.sa_data) 11701558Srgrimes *--cp1 &= *--cp2; 117113940Swollman#ifdef ISO 11721558Srgrimes switch (so_dst.sa.sa_family) { 11731558Srgrimes case AF_ISO: 11741558Srgrimes so_dst.siso.siso_nlen = olen; 11751558Srgrimes break; 11761558Srgrimes } 117713940Swollman#endif 11781558Srgrimes} 11791558Srgrimes 11801558Srgrimeschar *msgtypes[] = { 11811558Srgrimes "", 11821558Srgrimes "RTM_ADD: Add Route", 11831558Srgrimes "RTM_DELETE: Delete Route", 11841558Srgrimes "RTM_CHANGE: Change Metrics or flags", 11851558Srgrimes "RTM_GET: Report Metrics", 11861558Srgrimes "RTM_LOSING: Kernel Suspects Partitioning", 11871558Srgrimes "RTM_REDIRECT: Told to use different route", 11881558Srgrimes "RTM_MISS: Lookup failed on this address", 11891558Srgrimes "RTM_LOCK: fix specified metrics", 11901558Srgrimes "RTM_OLDADD: caused by SIOCADDRT", 11911558Srgrimes "RTM_OLDDEL: caused by SIOCDELRT", 11921558Srgrimes "RTM_RESOLVE: Route created by cloning", 11931558Srgrimes "RTM_NEWADDR: address being added to iface", 11941558Srgrimes "RTM_DELADDR: address being removed from iface", 11951558Srgrimes "RTM_IFINFO: iface status change", 11961558Srgrimes 0, 11971558Srgrimes}; 11981558Srgrimes 11991558Srgrimeschar metricnames[] = 120015690Swollman"\011pksent\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount" 120115690Swollman"\1mtu"; 12021558Srgrimeschar routeflags[] = 120315690Swollman"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT" 120415690Swollman"\011CLONING\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE\016b016" 120515690Swollman"\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3\024CHAINDELETE" 120615690Swollman"\025PINNED\026LOCAL\027BROADCAST\030MULTICAST"; 12071558Srgrimeschar ifnetflags[] = 120815690Swollman"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP" 120915690Swollman"\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1" 121015690Swollman"\017LINK2\020MULTICAST"; 12111558Srgrimeschar addrnames[] = 12121558Srgrimes"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD"; 12131558Srgrimes 12141558Srgrimesvoid 12151558Srgrimesprint_rtmsg(rtm, msglen) 12161558Srgrimes register struct rt_msghdr *rtm; 12171558Srgrimes int msglen; 12181558Srgrimes{ 12191558Srgrimes struct if_msghdr *ifm; 12201558Srgrimes struct ifa_msghdr *ifam; 12211558Srgrimes 12221558Srgrimes if (verbose == 0) 12231558Srgrimes return; 12241558Srgrimes if (rtm->rtm_version != RTM_VERSION) { 12251558Srgrimes (void) printf("routing message version %d not understood\n", 12261558Srgrimes rtm->rtm_version); 12271558Srgrimes return; 12281558Srgrimes } 12291558Srgrimes (void)printf("%s: len %d, ", msgtypes[rtm->rtm_type], rtm->rtm_msglen); 12301558Srgrimes switch (rtm->rtm_type) { 12311558Srgrimes case RTM_IFINFO: 12321558Srgrimes ifm = (struct if_msghdr *)rtm; 12331558Srgrimes (void) printf("if# %d, flags:", ifm->ifm_index); 12341558Srgrimes bprintf(stdout, ifm->ifm_flags, ifnetflags); 12351558Srgrimes pmsg_addrs((char *)(ifm + 1), ifm->ifm_addrs); 12361558Srgrimes break; 12371558Srgrimes case RTM_NEWADDR: 12381558Srgrimes case RTM_DELADDR: 12391558Srgrimes ifam = (struct ifa_msghdr *)rtm; 12401558Srgrimes (void) printf("metric %d, flags:", ifam->ifam_metric); 12411558Srgrimes bprintf(stdout, ifam->ifam_flags, routeflags); 12421558Srgrimes pmsg_addrs((char *)(ifam + 1), ifam->ifam_addrs); 12431558Srgrimes break; 12441558Srgrimes default: 124513171Swollman (void) printf("pid: %ld, seq %d, errno %d, flags:", 124613171Swollman (long)rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno); 12471558Srgrimes bprintf(stdout, rtm->rtm_flags, routeflags); 12481558Srgrimes pmsg_common(rtm); 12491558Srgrimes } 12501558Srgrimes} 12511558Srgrimes 12521558Srgrimesvoid 12531558Srgrimesprint_getmsg(rtm, msglen) 12541558Srgrimes register struct rt_msghdr *rtm; 12551558Srgrimes int msglen; 12561558Srgrimes{ 12571558Srgrimes struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL; 12581558Srgrimes struct sockaddr_dl *ifp = NULL; 12591558Srgrimes register struct sockaddr *sa; 12601558Srgrimes register char *cp; 12611558Srgrimes register int i; 12621558Srgrimes 12631558Srgrimes (void) printf(" route to: %s\n", routename(&so_dst)); 12641558Srgrimes if (rtm->rtm_version != RTM_VERSION) { 126513171Swollman warnx("routing message version %d not understood", 126613171Swollman rtm->rtm_version); 12671558Srgrimes return; 12681558Srgrimes } 12691558Srgrimes if (rtm->rtm_msglen > msglen) { 127013171Swollman warnx("message length mismatch, in packet %d, returned %d\n", 127113171Swollman rtm->rtm_msglen, msglen); 12721558Srgrimes } 12731558Srgrimes if (rtm->rtm_errno) { 127413171Swollman errno = rtm->rtm_errno; 127513171Swollman warn("message indicates error %d", errno); 12761558Srgrimes return; 12771558Srgrimes } 12781558Srgrimes cp = ((char *)(rtm + 1)); 12791558Srgrimes if (rtm->rtm_addrs) 12801558Srgrimes for (i = 1; i; i <<= 1) 12811558Srgrimes if (i & rtm->rtm_addrs) { 12821558Srgrimes sa = (struct sockaddr *)cp; 12831558Srgrimes switch (i) { 12841558Srgrimes case RTA_DST: 12851558Srgrimes dst = sa; 12861558Srgrimes break; 12871558Srgrimes case RTA_GATEWAY: 12881558Srgrimes gate = sa; 12891558Srgrimes break; 12901558Srgrimes case RTA_NETMASK: 12911558Srgrimes mask = sa; 12921558Srgrimes break; 12931558Srgrimes case RTA_IFP: 12941558Srgrimes if (sa->sa_family == AF_LINK && 12951558Srgrimes ((struct sockaddr_dl *)sa)->sdl_nlen) 12961558Srgrimes ifp = (struct sockaddr_dl *)sa; 12971558Srgrimes break; 12981558Srgrimes } 12991558Srgrimes ADVANCE(cp, sa); 13001558Srgrimes } 13011558Srgrimes if (dst && mask) 13021558Srgrimes mask->sa_family = dst->sa_family; /* XXX */ 13031558Srgrimes if (dst) 13041558Srgrimes (void)printf("destination: %s\n", routename(dst)); 13051558Srgrimes if (mask) { 13061558Srgrimes int savenflag = nflag; 13071558Srgrimes 13081558Srgrimes nflag = 1; 13091558Srgrimes (void)printf(" mask: %s\n", routename(mask)); 13101558Srgrimes nflag = savenflag; 13111558Srgrimes } 13121558Srgrimes if (gate && rtm->rtm_flags & RTF_GATEWAY) 13131558Srgrimes (void)printf(" gateway: %s\n", routename(gate)); 13141558Srgrimes if (ifp) 13151558Srgrimes (void)printf(" interface: %.*s\n", 13161558Srgrimes ifp->sdl_nlen, ifp->sdl_data); 13171558Srgrimes (void)printf(" flags: "); 13181558Srgrimes bprintf(stdout, rtm->rtm_flags, routeflags); 13191558Srgrimes 13201558Srgrimes#define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ') 13211558Srgrimes#define msec(u) (((u) + 500) / 1000) /* usec to msec */ 13221558Srgrimes 13231558Srgrimes (void) printf("\n%s\n", "\ 13241558Srgrimes recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire"); 132513171Swollman printf("%8ld%c ", rtm->rtm_rmx.rmx_recvpipe, lock(RPIPE)); 132613171Swollman printf("%8ld%c ", rtm->rtm_rmx.rmx_sendpipe, lock(SPIPE)); 132713171Swollman printf("%8ld%c ", rtm->rtm_rmx.rmx_ssthresh, lock(SSTHRESH)); 132813171Swollman printf("%8ld%c ", msec(rtm->rtm_rmx.rmx_rtt), lock(RTT)); 132913171Swollman printf("%8ld%c ", msec(rtm->rtm_rmx.rmx_rttvar), lock(RTTVAR)); 133013171Swollman printf("%8ld%c ", rtm->rtm_rmx.rmx_hopcount, lock(HOPCOUNT)); 133113171Swollman printf("%8ld%c ", rtm->rtm_rmx.rmx_mtu, lock(MTU)); 13321558Srgrimes if (rtm->rtm_rmx.rmx_expire) 13331558Srgrimes rtm->rtm_rmx.rmx_expire -= time(0); 133413171Swollman printf("%8ld%c\n", rtm->rtm_rmx.rmx_expire, lock(EXPIRE)); 13351558Srgrimes#undef lock 13361558Srgrimes#undef msec 13371558Srgrimes#define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD) 13381558Srgrimes if (verbose) 13391558Srgrimes pmsg_common(rtm); 13401558Srgrimes else if (rtm->rtm_addrs &~ RTA_IGN) { 13411558Srgrimes (void) printf("sockaddrs: "); 13421558Srgrimes bprintf(stdout, rtm->rtm_addrs, addrnames); 13431558Srgrimes putchar('\n'); 13441558Srgrimes } 13451558Srgrimes#undef RTA_IGN 13461558Srgrimes} 13471558Srgrimes 13481558Srgrimesvoid 13491558Srgrimespmsg_common(rtm) 13501558Srgrimes register struct rt_msghdr *rtm; 13511558Srgrimes{ 13521558Srgrimes (void) printf("\nlocks: "); 13531558Srgrimes bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames); 13541558Srgrimes (void) printf(" inits: "); 13551558Srgrimes bprintf(stdout, rtm->rtm_inits, metricnames); 13561558Srgrimes pmsg_addrs(((char *)(rtm + 1)), rtm->rtm_addrs); 13571558Srgrimes} 13581558Srgrimes 13591558Srgrimesvoid 13601558Srgrimespmsg_addrs(cp, addrs) 13611558Srgrimes char *cp; 13621558Srgrimes int addrs; 13631558Srgrimes{ 13641558Srgrimes register struct sockaddr *sa; 13651558Srgrimes int i; 13661558Srgrimes 13671558Srgrimes if (addrs == 0) 13681558Srgrimes return; 13691558Srgrimes (void) printf("\nsockaddrs: "); 13701558Srgrimes bprintf(stdout, addrs, addrnames); 13711558Srgrimes (void) putchar('\n'); 13721558Srgrimes for (i = 1; i; i <<= 1) 13731558Srgrimes if (i & addrs) { 13741558Srgrimes sa = (struct sockaddr *)cp; 13751558Srgrimes (void) printf(" %s", routename(sa)); 13761558Srgrimes ADVANCE(cp, sa); 13771558Srgrimes } 13781558Srgrimes (void) putchar('\n'); 13791558Srgrimes (void) fflush(stdout); 13801558Srgrimes} 13811558Srgrimes 13821558Srgrimesvoid 13831558Srgrimesbprintf(fp, b, s) 13841558Srgrimes register FILE *fp; 13851558Srgrimes register int b; 13861558Srgrimes register u_char *s; 13871558Srgrimes{ 13881558Srgrimes register int i; 13891558Srgrimes int gotsome = 0; 13901558Srgrimes 13911558Srgrimes if (b == 0) 13921558Srgrimes return; 139313171Swollman while ((i = *s++) != 0) { 13941558Srgrimes if (b & (1 << (i-1))) { 13951558Srgrimes if (gotsome == 0) 13961558Srgrimes i = '<'; 13971558Srgrimes else 13981558Srgrimes i = ','; 13991558Srgrimes (void) putc(i, fp); 14001558Srgrimes gotsome = 1; 14011558Srgrimes for (; (i = *s) > 32; s++) 14021558Srgrimes (void) putc(i, fp); 14031558Srgrimes } else 14041558Srgrimes while (*s > 32) 14051558Srgrimes s++; 14061558Srgrimes } 14071558Srgrimes if (gotsome) 14081558Srgrimes (void) putc('>', fp); 14091558Srgrimes} 14101558Srgrimes 14111558Srgrimesint 14121558Srgrimeskeyword(cp) 14131558Srgrimes char *cp; 14141558Srgrimes{ 14151558Srgrimes register struct keytab *kt = keywords; 14161558Srgrimes 14171558Srgrimes while (kt->kt_cp && strcmp(kt->kt_cp, cp)) 14181558Srgrimes kt++; 14191558Srgrimes return kt->kt_i; 14201558Srgrimes} 14211558Srgrimes 14221558Srgrimesvoid 14231558Srgrimessodump(su, which) 14241558Srgrimes register sup su; 14251558Srgrimes char *which; 14261558Srgrimes{ 14271558Srgrimes switch (su->sa.sa_family) { 14281558Srgrimes case AF_LINK: 14291558Srgrimes (void) printf("%s: link %s; ", 14301558Srgrimes which, link_ntoa(&su->sdl)); 14311558Srgrimes break; 143213940Swollman#ifdef ISO 14331558Srgrimes case AF_ISO: 14341558Srgrimes (void) printf("%s: iso %s; ", 14351558Srgrimes which, iso_ntoa(&su->siso.siso_addr)); 14361558Srgrimes break; 143713940Swollman#endif 14381558Srgrimes case AF_INET: 14391558Srgrimes (void) printf("%s: inet %s; ", 14401558Srgrimes which, inet_ntoa(su->sin.sin_addr)); 14411558Srgrimes break; 144217046Sjulian case AF_APPLETALK: 144317046Sjulian (void) printf("%s: atalk %s; ", 144417046Sjulian which, atalk_ntoa(su->sat.sat_addr)); 144517046Sjulian break; 144614092Swollman#ifdef NS 14471558Srgrimes case AF_NS: 14481558Srgrimes (void) printf("%s: xns %s; ", 14491558Srgrimes which, ns_ntoa(su->sns.sns_addr)); 14501558Srgrimes break; 145114092Swollman#endif 14521558Srgrimes } 14531558Srgrimes (void) fflush(stdout); 14541558Srgrimes} 14551558Srgrimes 14561558Srgrimes/* States*/ 14571558Srgrimes#define VIRGIN 0 14581558Srgrimes#define GOTONE 1 14591558Srgrimes#define GOTTWO 2 14601558Srgrimes/* Inputs */ 14611558Srgrimes#define DIGIT (4*0) 14621558Srgrimes#define END (4*1) 14631558Srgrimes#define DELIM (4*2) 14641558Srgrimes 14651558Srgrimesvoid 14661558Srgrimessockaddr(addr, sa) 14671558Srgrimes register char *addr; 14681558Srgrimes register struct sockaddr *sa; 14691558Srgrimes{ 14701558Srgrimes register char *cp = (char *)sa; 14711558Srgrimes int size = sa->sa_len; 14721558Srgrimes char *cplim = cp + size; 147313171Swollman register int byte = 0, state = VIRGIN, new = 0 /* foil gcc */; 14741558Srgrimes 14751558Srgrimes bzero(cp, size); 14761558Srgrimes cp++; 14771558Srgrimes do { 14781558Srgrimes if ((*addr >= '0') && (*addr <= '9')) { 14791558Srgrimes new = *addr - '0'; 14801558Srgrimes } else if ((*addr >= 'a') && (*addr <= 'f')) { 14811558Srgrimes new = *addr - 'a' + 10; 14821558Srgrimes } else if ((*addr >= 'A') && (*addr <= 'F')) { 14831558Srgrimes new = *addr - 'A' + 10; 14841558Srgrimes } else if (*addr == 0) 14851558Srgrimes state |= END; 14861558Srgrimes else 14871558Srgrimes state |= DELIM; 14881558Srgrimes addr++; 14891558Srgrimes switch (state /* | INPUT */) { 14901558Srgrimes case GOTTWO | DIGIT: 14911558Srgrimes *cp++ = byte; /*FALLTHROUGH*/ 14921558Srgrimes case VIRGIN | DIGIT: 14931558Srgrimes state = GOTONE; byte = new; continue; 14941558Srgrimes case GOTONE | DIGIT: 14951558Srgrimes state = GOTTWO; byte = new + (byte << 4); continue; 14961558Srgrimes default: /* | DELIM */ 14971558Srgrimes state = VIRGIN; *cp++ = byte; byte = 0; continue; 14981558Srgrimes case GOTONE | END: 14991558Srgrimes case GOTTWO | END: 15001558Srgrimes *cp++ = byte; /* FALLTHROUGH */ 15011558Srgrimes case VIRGIN | END: 15021558Srgrimes break; 15031558Srgrimes } 15041558Srgrimes break; 15051558Srgrimes } while (cp < cplim); 15061558Srgrimes sa->sa_len = cp - (char *)sa; 15071558Srgrimes} 150817046Sjulian 150917046Sjulianint 151017046Sjulianatalk_aton(const char *text, struct at_addr *addr) 151117046Sjulian{ 151217046Sjulian u_int net, node; 151317046Sjulian 151417046Sjulian if (sscanf(text, "%u.%u", &net, &node) != 2 151517046Sjulian || net > 0xffff || node > 0xff) 151617046Sjulian return(0); 151717254Sjulian addr->s_net = htons(net); 151817046Sjulian addr->s_node = node; 151917046Sjulian return(1); 152017046Sjulian} 152117046Sjulian 152217046Sjulianchar * 152317046Sjulianatalk_ntoa(struct at_addr at) 152417046Sjulian{ 152517046Sjulian static char buf[20]; 152617046Sjulian 152717254Sjulian (void) snprintf(buf, sizeof(buf), "%u.%u", ntohs(at.s_net), at.s_node); 152817046Sjulian return(buf); 152917046Sjulian} 1530