incorporate fix from dkhusema
[unix-history] / usr / src / sbin / route / route.c
CommitLineData
5ff67f98 1/*
d19a4594 2 * Copyright (c) 1983, 1989, 1991 The Regents of the University of California.
fca7493d
KB
3 * All rights reserved.
4 *
70ab3c27 5 * %sccs.include.redist.c%
5ff67f98
DF
6 */
7
8#ifndef lint
9char copyright[] =
d19a4594 10"@(#) Copyright (c) 1983, 1989, 1991 The Regents of the University of California.\n\
5ff67f98 11 All rights reserved.\n";
fca7493d 12#endif /* not lint */
5ff67f98 13
4bec325f 14#ifndef lint
c70cd151 15static char sccsid[] = "@(#)route.c 5.41 (Berkeley) %G%";
fca7493d 16#endif /* not lint */
4bec325f 17
a2280e64 18#include <sys/param.h>
79394449 19#include <sys/file.h>
4bec325f
BJ
20#include <sys/socket.h>
21#include <sys/ioctl.h>
63c817da 22#include <sys/mbuf.h>
9eb5d442 23#include <sys/kinfo.h>
94a2d2a7 24
4bec325f 25#include <net/route.h>
31bd2db6 26#include <net/if_dl.h>
94a2d2a7 27#include <netinet/in.h>
eac76d14 28#include <netns/ns.h>
7d5f817b 29#include <netiso/iso.h>
79394449 30#include <netccitt/x25.h>
789bb287 31#include <arpa/inet.h>
5c7868a2 32#include <netdb.h>
789bb287 33
4bec325f 34#include <errno.h>
789bb287 35#include <unistd.h>
9494af5d 36#include <stdio.h>
789bb287 37#include <ctype.h>
9494af5d
CT
38#include <stdlib.h>
39#include <string.h>
505837c5 40#include <paths.h>
4bec325f 41
31bd2db6
KS
42struct keytab {
43 char *kt_cp;
44 int kt_i;
45} keywords[] = {
46#include "keywords.h"
6a01ae04 47 {0, 0}
31bd2db6
KS
48};
49
57cacc90 50struct ortentry route;
31bd2db6 51union sockunion {
7d5f817b
KS
52 struct sockaddr sa;
53 struct sockaddr_in sin;
54 struct sockaddr_ns sns;
55 struct sockaddr_iso siso;
31bd2db6 56 struct sockaddr_dl sdl;
79394449 57 struct sockaddr_x25 sx25;
789bb287
MK
58} so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp;
59
31bd2db6 60typedef union sockunion *sup;
c64fbe35 61int pid, rtm_addrs, uid;
4bec325f 62int s;
d19a4594 63int forcehost, forcenet, doflush, nflag, af, qflag, tflag, keyword();
eb03b231 64int iflag, verbose, aflen = sizeof (struct sockaddr_in);
7cd60aa5 65int locking, lockrest, debugonly;
b268b889 66struct sockaddr_in sin = { sizeof(sin), AF_INET };
7cd60aa5 67struct rt_metrics rt_metrics;
7d8dd943 68u_long rtm_inits;
379dcc38 69struct in_addr inet_makeaddr();
9494af5d 70char *routename(), *netname();
79394449 71void flushroutes(), newroute(), monitor(), sockaddr();
9494af5d 72void print_getmsg(), print_rtmsg(), pmsg_common(), sodump(), bprintf();
c70cd151 73int getaddr(), rtmsg(), x25_makemask();
9494af5d 74extern char *inet_ntoa(), *iso_ntoa(), *link_ntoa();
4bec325f 75
9494af5d 76void
31bd2db6 77usage(cp)
9494af5d
CT
78 char *cp;
79{
9494af5d 80 if (cp)
e6a1ded8
KB
81 (void) fprintf(stderr, "route: botched keyword: %s\n", cp);
82 (void) fprintf(stderr,
d19a4594 83 "usage: route [ -nqv ] cmd [[ -<qualifers> ] args ]\n");
9494af5d
CT
84 exit(1);
85 /* NOTREACHED */
86}
87
88void
89quit(s)
90 char *s;
31bd2db6 91{
9494af5d 92 int sverrno = errno;
31bd2db6 93
9494af5d
CT
94 (void) fprintf(stderr, "route: ");
95 if (s)
96 (void) fprintf(stderr, "%s: ", s);
97 (void) fprintf(stderr, "%s\n", strerror(sverrno));
31bd2db6 98 exit(1);
9494af5d 99 /* NOTREACHED */
31bd2db6 100}
7d8dd943 101
c64fbe35
KS
102#define ROUNDUP(a) \
103 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
104#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
105
4bec325f
BJ
106main(argc, argv)
107 int argc;
e6a1ded8 108 char **argv;
4bec325f 109{
e6a1ded8
KB
110 extern int optind;
111 int ch;
b268b889 112 char *argvp;
9494af5d 113
4bec325f 114 if (argc < 2)
9494af5d 115 usage((char *)NULL);
e6a1ded8 116
d19a4594 117 while ((ch = getopt(argc, argv, "nqtv")) != EOF)
e6a1ded8 118 switch(ch) {
e6a1ded8
KB
119 case 'n':
120 nflag = 1;
121 break;
122 case 'q':
123 qflag = 1;
124 break;
125 case 'v':
126 verbose = 1;
127 break;
79394449
KS
128 case 't':
129 tflag = 1;
130 break;
e6a1ded8
KB
131 case '?':
132 default:
133 usage();
134 }
135 argc -= optind;
136 argv += optind;
137
5c7868a2 138 pid = getpid();
c64fbe35 139 uid = getuid();
79394449
KS
140 if (tflag)
141 s = open("/dev/null", O_WRONLY, 0);
5c7868a2
KS
142 else
143 s = socket(PF_ROUTE, SOCK_RAW, 0);
9494af5d
CT
144 if (s < 0)
145 quit("socket");
e6a1ded8 146 if (*argv)
789bb287 147 switch (keyword(*argv)) {
ac62fbdc 148 case K_GET:
c64fbe35
KS
149 uid = 0;
150 /* FALLTHROUGH */
789bb287 151
31bd2db6 152 case K_CHANGE:
c64fbe35 153 case K_ADD:
31bd2db6 154 case K_DELETE:
63c817da 155 newroute(argc, argv);
789bb287
MK
156 exit(0);
157 /* NOTREACHED */
158
31bd2db6 159 case K_MONITOR:
5c7868a2 160 monitor();
789bb287
MK
161 /* NOTREACHED */
162
31bd2db6
KS
163 case K_FLUSH:
164 flushroutes(argc, argv);
789bb287
MK
165 exit(0);
166 /* NOTREACHED */
e6a1ded8 167 }
31bd2db6 168 usage(*argv);
9494af5d 169 /* NOTREACHED */
63c817da
SL
170}
171
172/*
173 * Purge all entries in the routing tables not
174 * associated with network interfaces.
175 */
9494af5d 176void
31bd2db6 177flushroutes(argc, argv)
9494af5d
CT
178 int argc;
179 char *argv[];
b268b889 180{
9494af5d 181 int needed, seqno, rlen;
9eb5d442
KS
182 char *buf, *next, *lim;
183 register struct rt_msghdr *rtm;
9eb5d442 184
c64fbe35 185 if (uid)
789bb287 186 quit("must be root to alter routing table");
104e26d6 187 shutdown(s, 0); /* Don't want to read back our messages */
31bd2db6
KS
188 if (argc > 1) {
189 argv++;
789bb287
MK
190 if (argc == 2 && **argv == '-')
191 switch (keyword(*argv + 1)) {
192 case K_INET:
193 af = AF_INET;
194 break;
195 case K_XNS:
196 af = AF_NS;
197 break;
198 case K_LINK:
199 af = AF_LINK;
200 break;
201 case K_ISO:
202 case K_OSI:
203 af = AF_ISO;
204 break;
79394449
KS
205 case K_X25:
206 af = AF_CCITT;
789bb287
MK
207 default:
208 goto bad;
31bd2db6 209 } else
789bb287 210bad: usage(*argv);
31bd2db6 211 }
9eb5d442 212 if ((needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0)) < 0)
9494af5d
CT
213 quit("route-getkerninfo-estimate");
214 if ((buf = malloc(needed)) == NULL)
215 quit("malloc");
9eb5d442 216 if ((rlen = getkerninfo(KINFO_RT_DUMP, buf, &needed, 0)) < 0)
9494af5d 217 quit("actual retrieval of routing table");
9eb5d442 218 lim = buf + rlen;
9494af5d 219 seqno = 0; /* ??? */
9eb5d442
KS
220 for (next = buf; next < lim; next += rtm->rtm_msglen) {
221 rtm = (struct rt_msghdr *)next;
eb03b231 222 if ((rtm->rtm_flags & RTF_GATEWAY) == 0)
9eb5d442 223 continue;
31bd2db6
KS
224 if (af) {
225 struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
789bb287 226
31bd2db6
KS
227 if (sa->sa_family != af)
228 continue;
229 }
9eb5d442
KS
230 rtm->rtm_type = RTM_DELETE;
231 rtm->rtm_seq = seqno;
ac62fbdc
KS
232 rlen = write(s, next, rtm->rtm_msglen);
233 if (rlen < (int)rtm->rtm_msglen) {
9494af5d
CT
234 (void) fprintf(stderr,
235 "route: write to routing socket: %s\n",
236 strerror(errno));
237 (void) printf("got only %d for rlen\n", rlen);
31bd2db6 238 break;
b268b889 239 }
9eb5d442
KS
240 seqno++;
241 if (qflag)
242 continue;
9494af5d 243 if (verbose)
31bd2db6 244 print_rtmsg(rtm, rlen);
9494af5d 245 else {
039256d2 246 struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
9494af5d 247 (void) printf("%-20.20s ", rtm->rtm_flags & RTF_HOST ?
9eb5d442
KS
248 routename(sa) : netname(sa));
249 sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
9494af5d
CT
250 (void) printf("%-20.20s ", routename(sa));
251 (void) printf("done\n");
57cacc90
KS
252 }
253 }
57cacc90 254}
9eb5d442 255
63c817da 256char *
eac76d14
MK
257routename(sa)
258 struct sockaddr *sa;
63c817da 259{
a2280e64 260 register char *cp;
63c817da 261 static char line[50];
6edb1941 262 struct hostent *hp;
a2280e64
MK
263 static char domain[MAXHOSTNAMELEN + 1];
264 static int first = 1;
eac76d14 265 char *ns_print();
63c817da 266
a2280e64
MK
267 if (first) {
268 first = 0;
269 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
270 (cp = index(domain, '.')))
271 (void) strcpy(domain, cp + 1);
272 else
273 domain[0] = 0;
274 }
b762b60d
KS
275
276 if (sa->sa_len == 0)
277 strcpy(line, "default");
278 else switch (sa->sa_family) {
eac76d14
MK
279
280 case AF_INET:
281 { struct in_addr in;
282 in = ((struct sockaddr_in *)sa)->sin_addr;
283
284 cp = 0;
b762b60d 285 if (in.s_addr == INADDR_ANY || sa->sa_len < 4)
eac76d14
MK
286 cp = "default";
287 if (cp == 0 && !nflag) {
789bb287 288 hp = gethostbyaddr((char *)&in, sizeof (struct in_addr),
eac76d14
MK
289 AF_INET);
290 if (hp) {
291 if ((cp = index(hp->h_name, '.')) &&
292 !strcmp(cp + 1, domain))
293 *cp = 0;
294 cp = hp->h_name;
295 }
a2280e64 296 }
eac76d14
MK
297 if (cp)
298 strcpy(line, cp);
299 else {
a2280e64 300#define C(x) ((x) & 0xff)
eac76d14 301 in.s_addr = ntohl(in.s_addr);
9494af5d 302 (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
eac76d14
MK
303 C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
304 }
305 break;
306 }
307
308 case AF_NS:
309 return (ns_print((struct sockaddr_ns *)sa));
310
31bd2db6
KS
311 case AF_LINK:
312 return (link_ntoa((struct sockaddr_dl *)sa));
313
314 case AF_ISO:
315 (void) sprintf(line, "iso %s",
316 iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr));
317 break;
318
eac76d14
MK
319 default:
320 { u_short *s = (u_short *)sa->sa_data;
9494af5d 321 u_short *slim = s + ((sa->sa_len + 1) >> 1);
31bd2db6 322 char *cp = line + sprintf(line, "(%d)", sa->sa_family);
eac76d14 323
9494af5d
CT
324 while (s < slim)
325 cp += sprintf(cp, " %x", *s++);
eac76d14
MK
326 break;
327 }
a2280e64
MK
328 }
329 return (line);
330}
331
332/*
333 * Return the name of the network whose address is given.
334 * The address is assumed to be that of a net or subnet, not a host.
335 */
336char *
eac76d14
MK
337netname(sa)
338 struct sockaddr *sa;
a2280e64
MK
339{
340 char *cp = 0;
341 static char line[50];
342 struct netent *np = 0;
343 u_long net, mask;
e2fe1192 344 register u_long i;
a2280e64 345 int subnetshift;
a48a48cc 346 char *ns_print();
a2280e64 347
eac76d14
MK
348 switch (sa->sa_family) {
349
350 case AF_INET:
351 { struct in_addr in;
352 in = ((struct sockaddr_in *)sa)->sin_addr;
353
e2fe1192 354 i = in.s_addr = ntohl(in.s_addr);
eac76d14
MK
355 if (in.s_addr == 0)
356 cp = "default";
357 else if (!nflag) {
358 if (IN_CLASSA(i)) {
359 mask = IN_CLASSA_NET;
360 subnetshift = 8;
361 } else if (IN_CLASSB(i)) {
362 mask = IN_CLASSB_NET;
363 subnetshift = 8;
364 } else {
365 mask = IN_CLASSC_NET;
366 subnetshift = 4;
367 }
368 /*
369 * If there are more bits than the standard mask
370 * would suggest, subnets must be in use.
371 * Guess at the subnet mask, assuming reasonable
372 * width subnet fields.
373 */
374 while (in.s_addr &~ mask)
375 mask = (long)mask >> subnetshift;
376 net = in.s_addr & mask;
377 while ((mask & 1) == 0)
378 mask >>= 1, net >>= 1;
379 np = getnetbyaddr(net, AF_INET);
380 if (np)
381 cp = np->n_name;
a2280e64 382 }
eac76d14
MK
383 if (cp)
384 strcpy(line, cp);
385 else if ((in.s_addr & 0xffffff) == 0)
9494af5d 386 (void) sprintf(line, "%u", C(in.s_addr >> 24));
eac76d14 387 else if ((in.s_addr & 0xffff) == 0)
9494af5d 388 (void) sprintf(line, "%u.%u", C(in.s_addr >> 24),
eac76d14
MK
389 C(in.s_addr >> 16));
390 else if ((in.s_addr & 0xff) == 0)
9494af5d 391 (void) sprintf(line, "%u.%u.%u", C(in.s_addr >> 24),
eac76d14
MK
392 C(in.s_addr >> 16), C(in.s_addr >> 8));
393 else
9494af5d 394 (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
eac76d14
MK
395 C(in.s_addr >> 16), C(in.s_addr >> 8),
396 C(in.s_addr));
397 break;
398 }
399
400 case AF_NS:
401 return (ns_print((struct sockaddr_ns *)sa));
402 break;
403
31bd2db6
KS
404 case AF_LINK:
405 return (link_ntoa((struct sockaddr_dl *)sa));
406
407 case AF_ISO:
408 (void) sprintf(line, "iso %s",
409 iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr));
410 break;
411
eac76d14
MK
412 default:
413 { u_short *s = (u_short *)sa->sa_data;
31bd2db6
KS
414 u_short *slim = s + ((sa->sa_len + 1)>>1);
415 char *cp = line + sprintf(line, "af %d:", sa->sa_family);
eac76d14 416
9494af5d
CT
417 while (s < slim)
418 cp += sprintf(cp, " %x", *s++);
eac76d14
MK
419 break;
420 }
63c817da
SL
421 }
422 return (line);
4bec325f
BJ
423}
424
9494af5d 425void
7cd60aa5 426set_metric(value, key)
9494af5d
CT
427 char *value;
428 int key;
7cd60aa5
KS
429{
430 int flag = 0;
431 u_long noval, *valp = &noval;
432
433 switch (key) {
434#define caseof(x, y, z) case x: valp = &rt_metrics.z; flag = y; break
435 caseof(K_MTU, RTV_MTU, rmx_mtu);
436 caseof(K_HOPCOUNT, RTV_HOPCOUNT, rmx_hopcount);
437 caseof(K_EXPIRE, RTV_EXPIRE, rmx_expire);
438 caseof(K_RECVPIPE, RTV_RPIPE, rmx_recvpipe);
439 caseof(K_SENDPIPE, RTV_SPIPE, rmx_sendpipe);
440 caseof(K_SSTHRESH, RTV_SSTHRESH, rmx_ssthresh);
441 caseof(K_RTT, RTV_RTT, rmx_rtt);
442 caseof(K_RTTVAR, RTV_RTTVAR, rmx_rttvar);
443 }
7d8dd943 444 rtm_inits |= flag;
7cd60aa5
KS
445 if (lockrest || locking)
446 rt_metrics.rmx_locks |= flag;
447 if (locking)
448 locking = 0;
449 *valp = atoi(value);
450}
451
9494af5d 452void
4bec325f
BJ
453newroute(argc, argv)
454 int argc;
31bd2db6 455 register char **argv;
4bec325f 456{
9494af5d 457 char *cmd, *dest = "", *gateway = "", *err;
b762b60d 458 int ishost = 0, ret, attempts, oerrno, flags = RTF_STATIC;
7cd60aa5 459 int key;
31bd2db6 460 struct hostent *hp = 0;
4bec325f 461
c64fbe35 462 if (uid)
789bb287 463 quit("must be root to alter routing table");
183ef13b 464 cmd = argv[0];
ac62fbdc
KS
465 if (*cmd != 'g')
466 shutdown(s, 0); /* Don't want to read back our messages */
31bd2db6
KS
467 while (--argc > 0) {
468 if (**(++argv)== '-') {
9494af5d 469 switch (key = keyword(1 + *argv)) {
31bd2db6
KS
470 case K_LINK:
471 af = AF_LINK;
eb03b231 472 aflen = sizeof(struct sockaddr_dl);
31bd2db6
KS
473 break;
474 case K_OSI:
eb03b231 475 case K_ISO:
31bd2db6 476 af = AF_ISO;
eb03b231 477 aflen = sizeof(struct sockaddr_iso);
31bd2db6
KS
478 break;
479 case K_INET:
480 af = AF_INET;
eb03b231 481 aflen = sizeof(struct sockaddr_in);
31bd2db6 482 break;
79394449
KS
483 case K_X25:
484 af = AF_CCITT;
485 aflen = sizeof(struct sockaddr_x25);
486 break;
487 case K_SA:
83929a15 488 af = PF_ROUTE;
79394449
KS
489 aflen = sizeof(union sockunion);
490 break;
31bd2db6
KS
491 case K_XNS:
492 af = AF_NS;
eb03b231 493 aflen = sizeof(struct sockaddr_ns);
31bd2db6
KS
494 break;
495 case K_IFACE:
7cd60aa5 496 case K_INTERFACE:
31bd2db6 497 iflag++;
b762b60d
KS
498 case K_NOSTATIC:
499 flags &= ~RTF_STATIC;
31bd2db6 500 break;
7cd60aa5
KS
501 case K_LOCK:
502 locking = 1;
503 break;
504 case K_LOCKREST:
505 lockrest = 1;
506 break;
31bd2db6
KS
507 case K_HOST:
508 forcehost++;
509 break;
039256d2
KS
510 case K_REJECT:
511 flags |= RTF_REJECT;
512 break;
67506849
KS
513 case K_PROTO1:
514 flags |= RTF_PROTO1;
515 break;
516 case K_PROTO2:
517 flags |= RTF_PROTO2;
518 break;
7cd60aa5
KS
519 case K_CLONING:
520 flags |= RTF_CLONING;
521 break;
522 case K_XRESOLVE:
523 flags |= RTF_XRESOLVE;
524 break;
b762b60d
KS
525 case K_STATIC:
526 flags |= RTF_STATIC;
527 break;
ac62fbdc
KS
528 case K_IFA:
529 argc--;
530 (void) getaddr(RTA_IFA, *++argv, 0);
531 break;
532 case K_IFP:
533 argc--;
534 (void) getaddr(RTA_IFP, *++argv, 0);
535 break;
31bd2db6
KS
536 case K_GENMASK:
537 argc--;
538 (void) getaddr(RTA_GENMASK, *++argv, 0);
539 break;
ac62fbdc
KS
540 case K_GATEWAY:
541 argc--;
542 (void) getaddr(RTA_GATEWAY, *++argv, 0);
543 break;
544 case K_DST:
545 argc--;
546 ishost = getaddr(RTA_DST, *++argv, &hp);
547 dest = *argv;
548 break;
549 case K_NETMASK:
550 argc--;
551 (void) getaddr(RTA_NETMASK, *++argv, 0);
552 /* FALLTHROUGH */
553 case K_NET:
554 forcenet++;
555 break;
7cd60aa5
KS
556 case K_MTU:
557 case K_HOPCOUNT:
558 case K_EXPIRE:
559 case K_RECVPIPE:
560 case K_SENDPIPE:
561 case K_SSTHRESH:
562 case K_RTT:
563 case K_RTTVAR:
564 argc--;
565 set_metric(*++argv, key);
566 break;
31bd2db6
KS
567 default:
568 usage(1+*argv);
569 }
570 } else {
571 if ((rtm_addrs & RTA_DST) == 0) {
572 dest = *argv;
573 ishost = getaddr(RTA_DST, *argv, &hp);
574 } else if ((rtm_addrs & RTA_GATEWAY) == 0) {
575 gateway = *argv;
576 (void) getaddr(RTA_GATEWAY, *argv, &hp);
577 } else {
578 int ret = atoi(*argv);
d19a4594 579
31bd2db6 580 if (ret == 0) {
d19a4594
MK
581 if (strcmp(*argv, "0") == 0)
582 printf("%s,%s",
583 "old usage of trailing 0",
584 "assuming route to if\n");
585 else
586 usage(NULL);
31bd2db6
KS
587 iflag = 1;
588 continue;
589 } else if (ret > 0 && ret < 10) {
590 printf("old usage of trailing digit, ");
591 printf("assuming route via gateway\n");
592 iflag = 0;
593 continue;
594 }
595 (void) getaddr(RTA_NETMASK, *argv, 0);
596 }
597 }
598 }
b3933da8
MK
599 if (forcehost)
600 ishost = 1;
601 if (forcenet)
602 ishost = 0;
7cd60aa5 603 flags |= RTF_UP;
6edb1941 604 if (ishost)
7d5f817b 605 flags |= RTF_HOST;
57cacc90 606 if (iflag == 0)
7d5f817b 607 flags |= RTF_GATEWAY;
792b0612
MK
608 for (attempts = 1; ; attempts++) {
609 errno = 0;
d19a4594
MK
610 if ((ret = rtmsg(*cmd, flags)) == 0)
611 break;
792b0612
MK
612 if (errno != ENETUNREACH && errno != ESRCH)
613 break;
d19a4594 614 if (af == AF_INET && *gateway && hp && hp->h_addr_list[1]) {
792b0612 615 hp->h_addr_list++;
d19a4594 616 bcopy(hp->h_addr_list[0], &so_gate.sin.sin_addr,
792b0612
MK
617 hp->h_length);
618 } else
619 break;
620 }
ac62fbdc
KS
621 if (*cmd == 'g')
622 exit(0);
792b0612 623 oerrno = errno;
d19a4594
MK
624 (void) printf("%s %s %s", cmd, ishost? "host" : "net", dest);
625 if (*gateway) {
626 (void) printf(": gateway %s", gateway);
627 if (attempts > 1 && ret == 0 && af == AF_INET)
628 (void) printf(" (%s)",
629 inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr));
630 }
792b0612 631 if (ret == 0)
9494af5d 632 (void) printf("\n");
792b0612 633 else {
9494af5d
CT
634 switch (oerrno) {
635 case ESRCH:
636 err = "not in table";
637 break;
638 case EBUSY:
639 err = "entry in use";
640 break;
641 case ENOBUFS:
642 err = "routing table overflow";
643 break;
644 default:
645 err = strerror(oerrno);
646 break;
647 }
648 (void) printf(": %s\n", err);
792b0612 649 }
4bec325f
BJ
650}
651
9494af5d 652void
31bd2db6 653inet_makenetandmask(net, sin)
9494af5d
CT
654 u_long net;
655 register struct sockaddr_in *sin;
57cacc90 656{
9494af5d 657 u_long addr, mask = 0;
31bd2db6 658 register char *cp;
57cacc90 659
31bd2db6 660 rtm_addrs |= RTA_NETMASK;
57cacc90 661 if (net == 0)
5c7868a2 662 mask = addr = 0;
57cacc90
KS
663 else if (net < 128) {
664 addr = net << IN_CLASSA_NSHIFT;
5c7868a2 665 mask = IN_CLASSA_NET;
57cacc90
KS
666 } else if (net < 65536) {
667 addr = net << IN_CLASSB_NSHIFT;
5c7868a2 668 mask = IN_CLASSB_NET;
57cacc90
KS
669 } else if (net < 16777216L) {
670 addr = net << IN_CLASSC_NSHIFT;
5c7868a2 671 mask = IN_CLASSC_NET;
57cacc90
KS
672 } else {
673 addr = net;
674 if ((addr & IN_CLASSA_HOST) == 0)
5c7868a2 675 mask = IN_CLASSA_NET;
57cacc90 676 else if ((addr & IN_CLASSB_HOST) == 0)
5c7868a2 677 mask = IN_CLASSB_NET;
57cacc90 678 else if ((addr & IN_CLASSC_HOST) == 0)
5c7868a2 679 mask = IN_CLASSC_NET;
57cacc90 680 else
5c7868a2
KS
681 mask = -1;
682 }
31bd2db6
KS
683 sin->sin_addr.s_addr = htonl(addr);
684 sin = &so_mask.sin;
685 sin->sin_addr.s_addr = htonl(mask);
686 sin->sin_len = 0;
687 sin->sin_family = 0;
9494af5d 688 cp = (char *)(&sin->sin_addr + 1);
31bd2db6
KS
689 while (*--cp == 0 && cp > (char *)sin)
690 ;
691 sin->sin_len = 1 + cp - (char *)sin;
57cacc90
KS
692}
693
6edb1941
MK
694/*
695 * Interpret an argument as a network address of some kind,
696 * returning 1 if a host address, 0 if a network address.
697 */
9494af5d 698int
31bd2db6 699getaddr(which, s, hpp)
9494af5d 700 int which;
4bec325f 701 char *s;
792b0612 702 struct hostent **hpp;
4bec325f 703{
ac62fbdc 704 register sup su;
9494af5d 705 struct ns_addr ns_addr();
eb03b231 706 struct iso_addr *iso_addr();
accbc2e3 707 struct hostent *hp;
379dcc38 708 struct netent *np;
31bd2db6 709 u_long val;
accbc2e3 710
eb03b231 711 if (af == 0) {
31bd2db6 712 af = AF_INET;
eb03b231
KS
713 aflen = sizeof(struct sockaddr_in);
714 }
715 rtm_addrs |= which;
31bd2db6 716 switch (which) {
6a01ae04
MK
717 case RTA_DST:
718 su = &so_dst;
719 su->sa.sa_family = af;
720 break;
721 case RTA_GATEWAY:
722 su = &so_gate;
723 su->sa.sa_family = af;
724 break;
725 case RTA_NETMASK:
726 su = &so_mask;
727 break;
728 case RTA_GENMASK:
729 su = &so_genmask;
730 break;
731 case RTA_IFP:
732 su = &so_ifp;
733 su->sa.sa_family = af;
734 break;
735 case RTA_IFA:
736 su = &so_ifa;
737 su->sa.sa_family = af;
738 break;
739 default:
740 usage("Internal Error");
741 /*NOTREACHED*/
31bd2db6 742 }
eb03b231 743 su->sa.sa_len = aflen;
7d5f817b 744 if (strcmp(s, "default") == 0) {
eb03b231
KS
745 switch (which) {
746 case RTA_DST:
747 forcenet++;
9494af5d 748 (void) getaddr(RTA_NETMASK, s, 0);
eb03b231
KS
749 break;
750 case RTA_NETMASK:
751 case RTA_GENMASK:
752 su->sa.sa_len = 0;
753 }
6a01ae04
MK
754 return (0);
755 }
756 switch (af) {
757 case AF_NS:
758 if (which == RTA_DST) {
759 extern short ns_bh[3];
760 struct sockaddr_ns *sms = &(so_mask.sns);
761 bzero((char *)sms, sizeof(*sms));
762 sms->sns_family = 0;
763 sms->sns_len = 6;
764 sms->sns_addr.x_net = *(union ns_net *)ns_bh;
765 rtm_addrs |= RTA_NETMASK;
766 }
767 su->sns.sns_addr = ns_addr(s);
768 return (!ns_nullhost(su->sns.sns_addr));
769
770 case AF_OSI:
771 su->siso.siso_addr = *iso_addr(s);
772 if (which == RTA_NETMASK || which == RTA_GENMASK) {
773 register char *cp = (char *)TSEL(&su->siso);
774 su->siso.siso_nlen = 0;
775 do {--cp ;} while ((cp > (char *)su) && (*cp == 0));
776 su->siso.siso_len = 1 + cp - (char *)su;
777 }
778 return (1);
779
780 case AF_LINK:
781 link_addr(s, &su->sdl);
782 return (1);
783
784 case AF_CCITT:
785 ccitt_addr(s, &su->sx25);
c70cd151 786 return (which == RTA_DST ? x25_makemask() : 1);
6a01ae04
MK
787
788 case PF_ROUTE:
789 su->sa.sa_len = sizeof(*su);
790 sockaddr(s, &su->sa);
791 return (1);
792
793 case AF_INET:
794 default:
795 break;
7d5f817b 796 }
6a01ae04 797
9494af5d
CT
798 if (hpp == NULL)
799 hpp = &hp;
800 *hpp = NULL;
85e467b1
KS
801 if (((val = inet_addr(s)) != -1) &&
802 (which != RTA_DST || forcenet == 0)) {
31bd2db6
KS
803 su->sin.sin_addr.s_addr = val;
804 if (inet_lnaof(su->sin.sin_addr) != INADDR_ANY)
805 return (1);
806 else {
807 val = ntohl(val);
6a01ae04 808 goto netdone;
a2280e64 809 }
792b0612 810 }
c70cd151
KS
811 if ((val = inet_network(s)) != -1 ||
812 ((np = getnetbyname(s)) != NULL && (val = np->n_net) != 0)) {
6a01ae04
MK
813netdone:
814 if (which == RTA_DST)
815 inet_makenetandmask(val, &su->sin);
816 return (0);
379dcc38 817 }
78160c55
MK
818 hp = gethostbyname(s);
819 if (hp) {
792b0612 820 *hpp = hp;
31bd2db6 821 su->sin.sin_family = hp->h_addrtype;
9494af5d 822 bcopy(hp->h_addr, (char *)&su->sin.sin_addr, hp->h_length);
57cacc90 823 return (1);
78160c55 824 }
9494af5d 825 (void) fprintf(stderr, "%s: bad value\n", s);
379dcc38 826 exit(1);
183ef13b 827}
eac76d14 828
c70cd151
KS
829x25_makemask()
830{
831 register char *cp;
832
833 if ((rtm_addrs & RTA_NETMASK) == 0) {
834 rtm_addrs |= RTA_NETMASK;
835 for (cp = (char *)&so_mask.sx25.x25_net;
836 cp < &so_mask.sx25.x25_opts.op_flags; cp++)
837 *cp = -1;
838 so_mask.sx25.x25_len = (u_char)&(((sup)0)->sx25.x25_opts);
839 }
840 return 0;
841}
842
eac76d14
MK
843short ns_nullh[] = {0,0,0};
844short ns_bh[] = {-1,-1,-1};
845
846char *
847ns_print(sns)
9494af5d 848 struct sockaddr_ns *sns;
eac76d14
MK
849{
850 struct ns_addr work;
851 union { union ns_net net_e; u_long long_e; } net;
852 u_short port;
853 static char mybuf[50], cport[10], chost[25];
854 char *host = "";
9494af5d
CT
855 register char *p;
856 register u_char *q;
eac76d14
MK
857
858 work = sns->sns_addr;
859 port = ntohs(work.x_port);
860 work.x_port = 0;
861 net.net_e = work.x_net;
862 if (ns_nullhost(work) && net.long_e == 0) {
9494af5d
CT
863 if (!port)
864 return ("*.*");
865 (void) sprintf(mybuf, "*.%XH", port);
eac76d14
MK
866 return (mybuf);
867 }
868
9494af5d 869 if (bcmp((char *)ns_bh, (char *)work.x_host.c_host, 6) == 0)
eac76d14 870 host = "any";
9494af5d 871 else if (bcmp((char *)ns_nullh, (char *)work.x_host.c_host, 6) == 0)
eac76d14 872 host = "*";
9494af5d 873 else {
eac76d14 874 q = work.x_host.c_host;
9494af5d 875 (void) sprintf(chost, "%02X%02X%02X%02X%02X%02XH",
eac76d14 876 q[0], q[1], q[2], q[3], q[4], q[5]);
9494af5d
CT
877 for (p = chost; *p == '0' && p < chost + 12; p++)
878 /* void */;
eac76d14
MK
879 host = p;
880 }
881 if (port)
9494af5d 882 (void) sprintf(cport, ".%XH", htons(port));
eac76d14
MK
883 else
884 *cport = 0;
885
9494af5d
CT
886 (void) sprintf(mybuf,"%XH.%s%s", ntohl(net.long_e), host, cport);
887 return (mybuf);
eac76d14 888}
57cacc90 889
9494af5d 890void
57cacc90
KS
891monitor()
892{
893 int n;
894 char msg[2048];
9494af5d 895
9eb5d442 896 verbose = 1;
57cacc90
KS
897 for(;;) {
898 n = read(s, msg, 2048);
9494af5d 899 (void) printf("got message of size %d\n", n);
31bd2db6 900 print_rtmsg((struct rt_msghdr *)msg);
57cacc90
KS
901 }
902}
903
904struct {
905 struct rt_msghdr m_rtm;
9494af5d 906 char m_space[512];
57cacc90
KS
907} m_rtmsg;
908
9494af5d 909int
31bd2db6 910rtmsg(cmd, flags)
9494af5d 911 int cmd, flags;
57cacc90
KS
912{
913 static int seq;
85e467b1 914 int rlen;
31bd2db6
KS
915 register char *cp = m_rtmsg.m_space;
916 register int l;
57cacc90 917
c64fbe35
KS
918#define NEXTADDR(w, u) \
919 if (rtm_addrs & (w)) {\
920 l = ROUNDUP(u.sa.sa_len); bcopy((char *)&(u), cp, l); cp += l;\
921 if (verbose) sodump(&(u),"u");\
922 }
ac62fbdc 923
57cacc90
KS
924 errno = 0;
925 bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
926 if (cmd == 'a')
927 cmd = RTM_ADD;
928 else if (cmd == 'c')
929 cmd = RTM_CHANGE;
6a01ae04 930 else if (cmd == 'g') {
ac62fbdc 931 cmd = RTM_GET;
6a01ae04
MK
932 if (so_ifp.sa.sa_family == 0) {
933 so_ifp.sa.sa_family == AF_LINK;
934 so_ifp.sa.sa_len == sizeof(struct sockaddr_dl);
935 rtm_addrs |= RTA_IFP;
936 }
937 } else
57cacc90 938 cmd = RTM_DELETE;
ac62fbdc
KS
939#define rtm m_rtmsg.m_rtm
940 rtm.rtm_type = cmd;
941 rtm.rtm_flags = flags;
942 rtm.rtm_version = RTM_VERSION;
943 rtm.rtm_seq = ++seq;
944 rtm.rtm_addrs = rtm_addrs;
945 rtm.rtm_rmx = rt_metrics;
946 rtm.rtm_inits = rtm_inits;
31bd2db6 947
79394449
KS
948 if (rtm_addrs & RTA_NETMASK)
949 mask_addr();
31bd2db6
KS
950 NEXTADDR(RTA_DST, so_dst);
951 NEXTADDR(RTA_GATEWAY, so_gate);
952 NEXTADDR(RTA_NETMASK, so_mask);
953 NEXTADDR(RTA_GENMASK, so_genmask);
ac62fbdc
KS
954 NEXTADDR(RTA_IFP, so_ifp);
955 NEXTADDR(RTA_IFA, so_ifa);
956 rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
31bd2db6 957 if (verbose)
ac62fbdc 958 print_rtmsg(&rtm, l);
7cd60aa5 959 if (debugonly)
d19a4594 960 return (0);
85e467b1 961 if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
57cacc90 962 perror("writing to routing socket");
7d5f817b 963 return (-1);
57cacc90 964 }
ac62fbdc
KS
965 if (cmd == RTM_GET) {
966 do {
967 l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
968 } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
969 if (l < 0)
9494af5d
CT
970 (void) fprintf(stderr,
971 "route: read from routing socket: %s\n",
972 strerror(errno));
ac62fbdc
KS
973 else
974 print_getmsg(&rtm, l);
975 }
976#undef rtm
57cacc90
KS
977 return (0);
978}
979
d19a4594
MK
980mask_addr()
981{
b762b60d
KS
982 int olen = so_mask.sa.sa_len;
983 register char *cp1 = olen + (char *)&so_mask, *cp2;
79394449 984
b762b60d
KS
985 for (so_mask.sa.sa_len = 0; cp1 > (char *)&so_mask; )
986 if (*--cp1 != 0) {
987 so_mask.sa.sa_len = 1 + cp1 - (char *)&so_mask;
988 break;
989 }
79394449
KS
990 if ((rtm_addrs & RTA_DST) == 0)
991 return;
d19a4594
MK
992 switch (so_dst.sa.sa_family) {
993 case AF_NS:
994 case AF_INET:
b762b60d 995 case AF_CCITT:
d19a4594 996 case 0:
79394449
KS
997 return;
998 case AF_ISO:
999 olen = MIN(so_dst.siso.siso_nlen, so_mask.sa.sa_len - 6);
d19a4594 1000 break;
79394449
KS
1001 }
1002 cp1 = so_mask.sa.sa_len + 1 + (char *)&so_dst;
1003 cp2 = so_dst.sa.sa_len + 1 + (char *)&so_dst;
1004 while (cp2 > cp1)
1005 *--cp2 = 0;
1006 cp2 = so_mask.sa.sa_len + 1 + (char *)&so_mask;
1007 while (cp1 > so_dst.sa.sa_data)
1008 *--cp1 &= *--cp2;
d19a4594 1009 switch (so_dst.sa.sa_family) {
79394449
KS
1010 case AF_ISO:
1011 so_dst.siso.siso_nlen = olen;
d19a4594 1012 break;
79394449
KS
1013 }
1014}
1015
57cacc90 1016char *msgtypes[] = {
9494af5d
CT
1017 "",
1018 "RTM_ADD: Add Route",
1019 "RTM_DELETE: Delete Route",
1020 "RTM_CHANGE: Change Metrics or flags",
1021 "RTM_GET: Report Metrics",
1022 "RTM_LOSING: Kernel Suspects Partitioning",
1023 "RTM_REDIRECT: Told to use different route",
1024 "RTM_MISS: Lookup failed on this address",
1025 "RTM_LOCK: fix specified metrics",
1026 "RTM_OLDADD: caused by SIOCADDRT",
1027 "RTM_OLDDEL: caused by SIOCDELRT",
1028 0,
1029};
57cacc90
KS
1030
1031char metricnames[] =
7cd60aa5
KS
1032"\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount\1mtu";
1033char routeflags[] =
b762b60d 1034"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT\011CLONING\012XRESOLVE\013LLINFO\014STATIC\017PROTO2\020PROTO1";
57cacc90 1035
57cacc90 1036
9494af5d 1037void
ac62fbdc 1038print_rtmsg(rtm, msglen)
9494af5d
CT
1039 register struct rt_msghdr *rtm;
1040 int msglen;
57cacc90 1041{
7d5f817b
KS
1042 if (verbose == 0)
1043 return;
a387100b 1044 if (rtm->rtm_version != RTM_VERSION) {
9494af5d
CT
1045 (void) printf("routing message version %d not understood\n",
1046 rtm->rtm_version);
1047 return;
57cacc90 1048 }
9494af5d 1049 (void) printf("%s\npid: %d, len %d, seq %d, errno %d, flags:",
ac62fbdc
KS
1050 msgtypes[rtm->rtm_type], rtm->rtm_pid, rtm->rtm_msglen,
1051 rtm->rtm_seq, rtm->rtm_errno);
1052 bprintf(stdout, rtm->rtm_flags, routeflags);
1053 pmsg_common(rtm);
1054}
1055
9494af5d 1056void
ac62fbdc 1057print_getmsg(rtm, msglen)
9494af5d
CT
1058 register struct rt_msghdr *rtm;
1059 int msglen;
ac62fbdc 1060{
d19a4594 1061 struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL;
6a01ae04 1062 struct sockaddr_dl *ifp = NULL;
d19a4594
MK
1063 register struct sockaddr *sa;
1064 register char *cp;
1065 register int i;
1066
7f0cc49c 1067 (void) printf(" route to: %s\n", routename(&so_dst));
ac62fbdc 1068 if (rtm->rtm_version != RTM_VERSION) {
d19a4594
MK
1069 (void)fprintf(stderr,
1070 "routing message version %d not understood\n",
9494af5d 1071 rtm->rtm_version);
ac62fbdc
KS
1072 return;
1073 }
c64fbe35 1074 if (rtm->rtm_msglen > msglen) {
d19a4594
MK
1075 (void)fprintf(stderr,
1076 "message length mismatch, in packet %d, returned %d\n",
9494af5d 1077 rtm->rtm_msglen, msglen);
ac62fbdc 1078 }
d19a4594
MK
1079 if (rtm->rtm_errno) {
1080 (void) fprintf(stderr, "RTM_GET: %s (errno %d)\n",
1081 strerror(rtm->rtm_errno), rtm->rtm_errno);
1082 return;
1083 }
1084 cp = ((char *)(rtm + 1));
1085 if (rtm->rtm_addrs)
1086 for (i = 1; i; i <<= 1)
1087 if (i & rtm->rtm_addrs) {
1088 sa = (struct sockaddr *)cp;
1089 switch (i) {
1090 case RTA_DST:
1091 dst = sa;
1092 break;
1093 case RTA_GATEWAY:
1094 gate = sa;
1095 break;
1096 case RTA_NETMASK:
1097 mask = sa;
1098 break;
6a01ae04
MK
1099 case RTA_IFP:
1100 if (sa->sa_family == AF_LINK &&
1101 ((struct sockaddr_dl *)sa)->sdl_nlen)
1102 ifp = (struct sockaddr_dl *)sa;
1103 break;
d19a4594
MK
1104 }
1105 ADVANCE(cp, sa);
1106 }
1107 if (dst && mask)
1108 mask->sa_family = dst->sa_family; /* XXX */
1109 if (dst)
1110 (void)printf("destination: %s\n", routename(dst));
1111 if (mask) {
1112 int savenflag = nflag;
1113
1114 nflag = 1;
1115 (void)printf(" mask: %s\n", routename(mask));
1116 nflag = savenflag;
1117 }
1118 if (gate && rtm->rtm_flags & RTF_GATEWAY)
1119 (void)printf(" gateway: %s\n", routename(gate));
6a01ae04
MK
1120 if (ifp)
1121 (void)printf(" interface: %.*s\n",
1122 ifp->sdl_nlen, ifp->sdl_data);
d19a4594 1123 (void)printf(" flags: ");
ac62fbdc 1124 bprintf(stdout, rtm->rtm_flags, routeflags);
d19a4594
MK
1125
1126#define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ')
1127#define msec(u) (((u) + 500) / 1000) /* usec to msec */
1128
1129 (void) printf("\n%s\n", "\
1130 recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire");
1131 printf("%8d%c ", rtm->rtm_rmx.rmx_recvpipe, lock(RPIPE));
1132 printf("%8d%c ", rtm->rtm_rmx.rmx_sendpipe, lock(SPIPE));
1133 printf("%8d%c ", rtm->rtm_rmx.rmx_ssthresh, lock(SSTHRESH));
1134 printf("%8d%c ", msec(rtm->rtm_rmx.rmx_rtt), lock(RTT));
1135 printf("%8d%c ", msec(rtm->rtm_rmx.rmx_rttvar), lock(RTTVAR));
1136 printf("%8d%c ", rtm->rtm_rmx.rmx_hopcount, lock(HOPCOUNT));
1137 printf("%8d%c ", rtm->rtm_rmx.rmx_mtu, lock(MTU));
1138 if (rtm->rtm_rmx.rmx_expire)
1139 rtm->rtm_rmx.rmx_expire -= time(0);
1140 printf("%8d%c\n", rtm->rtm_rmx.rmx_expire, lock(EXPIRE));
1141#undef lock
1142#undef msec
6a01ae04 1143#define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA)
d19a4594
MK
1144 if (verbose)
1145 pmsg_common(rtm);
6a01ae04 1146 else if (rtm->rtm_addrs &~ RTA_IGN) {
d19a4594
MK
1147 (void) printf("sockaddrs: ");
1148 bprintf(stdout, rtm->rtm_addrs,
1149 "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR");
6a01ae04 1150 putchar('\n');
d19a4594 1151 }
6a01ae04 1152#undef RTA_IGN
ac62fbdc
KS
1153}
1154
9494af5d 1155void
ac62fbdc 1156pmsg_common(rtm)
9494af5d 1157 register struct rt_msghdr *rtm;
ac62fbdc
KS
1158{
1159 char *cp;
1160 register struct sockaddr *sa;
1161 int i;
1162
9494af5d
CT
1163 (void) printf("\nlocks: ");
1164 bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames);
1165 (void) printf(" inits: ");
1166 bprintf(stdout, rtm->rtm_inits, metricnames);
1167 (void) printf("\nsockaddrs: ");
ac62fbdc
KS
1168 bprintf(stdout, rtm->rtm_addrs,
1169 "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR");
9494af5d 1170 (void) putchar('\n');
ac62fbdc
KS
1171 cp = ((char *)(rtm + 1));
1172 if (rtm->rtm_addrs)
9494af5d
CT
1173 for (i = 1; i; i <<= 1)
1174 if (i & rtm->rtm_addrs) {
1175 sa = (struct sockaddr *)cp;
1176 (void) printf(" %s", routename(sa));
1177 ADVANCE(cp, sa);
1178 }
1179 (void) putchar('\n');
1180 (void) fflush(stdout);
57cacc90
KS
1181}
1182
9494af5d 1183void
57cacc90 1184bprintf(fp, b, s)
9494af5d
CT
1185 register FILE *fp;
1186 register int b;
1187 register u_char *s;
57cacc90
KS
1188{
1189 register int i;
1190 int gotsome = 0;
1191
1192 if (b == 0)
1193 return;
1194 while (i = *s++) {
1195 if (b & (1 << (i-1))) {
9494af5d
CT
1196 if (gotsome == 0)
1197 i = '<';
1198 else
1199 i = ',';
1200 (void) putc(i, fp);
57cacc90
KS
1201 gotsome = 1;
1202 for (; (i = *s) > 32; s++)
9494af5d 1203 (void) putc(i, fp);
57cacc90
KS
1204 } else
1205 while (*s > 32)
1206 s++;
1207 }
1208 if (gotsome)
9494af5d 1209 (void) putc('>', fp);
57cacc90 1210}
9494af5d 1211
31bd2db6
KS
1212int
1213keyword(cp)
9494af5d 1214 char *cp;
31bd2db6
KS
1215{
1216 register struct keytab *kt = keywords;
9494af5d 1217
31bd2db6
KS
1218 while (kt->kt_cp && strcmp(kt->kt_cp, cp))
1219 kt++;
1220 return kt->kt_i;
1221}
1222
9494af5d 1223void
31bd2db6 1224sodump(su, which)
9494af5d
CT
1225 register sup su;
1226 char *which;
31bd2db6
KS
1227{
1228 switch (su->sa.sa_family) {
1229 case AF_LINK:
9494af5d
CT
1230 (void) printf("%s: link %s; ",
1231 which, link_ntoa(&su->sdl));
31bd2db6
KS
1232 break;
1233 case AF_ISO:
9494af5d
CT
1234 (void) printf("%s: iso %s; ",
1235 which, iso_ntoa(&su->siso.siso_addr));
31bd2db6
KS
1236 break;
1237 case AF_INET:
9494af5d
CT
1238 (void) printf("%s: inet %s; ",
1239 which, inet_ntoa(su->sin.sin_addr));
31bd2db6
KS
1240 break;
1241 case AF_NS:
9494af5d
CT
1242 (void) printf("%s: xns %s; ",
1243 which, ns_ntoa(su->sns.sns_addr));
31bd2db6
KS
1244 break;
1245 }
9494af5d 1246 (void) fflush(stdout);
31bd2db6 1247}
d19a4594 1248
79394449
KS
1249/* States*/
1250#define VIRGIN 0
1251#define GOTONE 1
1252#define GOTTWO 2
1253/* Inputs */
1254#define DIGIT (4*0)
1255#define END (4*1)
1256#define DELIM (4*2)
1257
1258void
1259sockaddr(addr, sa)
d19a4594
MK
1260 register char *addr;
1261 register struct sockaddr *sa;
79394449
KS
1262{
1263 register char *cp = (char *)sa;
1264 int size = sa->sa_len;
1265 char *cplim = cp + size;
1266 register int byte = 0, state = VIRGIN, new;
1267
1268 bzero(cp, size);
83929a15 1269 cp++;
79394449
KS
1270 do {
1271 if ((*addr >= '0') && (*addr <= '9')) {
1272 new = *addr - '0';
1273 } else if ((*addr >= 'a') && (*addr <= 'f')) {
1274 new = *addr - 'a' + 10;
1275 } else if ((*addr >= 'A') && (*addr <= 'F')) {
1276 new = *addr - 'A' + 10;
1277 } else if (*addr == 0)
1278 state |= END;
1279 else
1280 state |= DELIM;
1281 addr++;
1282 switch (state /* | INPUT */) {
1283 case GOTTWO | DIGIT:
1284 *cp++ = byte; /*FALLTHROUGH*/
1285 case VIRGIN | DIGIT:
1286 state = GOTONE; byte = new; continue;
1287 case GOTONE | DIGIT:
1288 state = GOTTWO; byte = new + (byte << 4); continue;
1289 default: /* | DELIM */
1290 state = VIRGIN; *cp++ = byte; byte = 0; continue;
1291 case GOTONE | END:
1292 case GOTTWO | END:
1293 *cp++ = byte; /* FALLTHROUGH */
1294 case VIRGIN | END:
1295 break;
1296 }
1297 break;
1298 } while (cp < cplim);
1299 sa->sa_len = cp - (char *)sa;
1300}