fix bug in not converting gateway if -net specified.
[unix-history] / usr / src / sbin / route / route.c
CommitLineData
5ff67f98 1/*
7b3729cc 2 * Copyright (c) 1983, 1989 The Regents of the University of California.
fca7493d
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
5ff67f98
DF
16 */
17
18#ifndef lint
19char copyright[] =
7d5f817b 20"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
5ff67f98 21 All rights reserved.\n";
fca7493d 22#endif /* not lint */
5ff67f98 23
4bec325f 24#ifndef lint
caf9a58c 25static char sccsid[] = "@(#)route.c 5.21 (Berkeley) %G%";
fca7493d 26#endif /* not lint */
4bec325f 27
7d5f817b 28#include <paths.h>
a2280e64 29#include <sys/param.h>
4bec325f
BJ
30#include <sys/socket.h>
31#include <sys/ioctl.h>
5c7868a2 32#include <sys/file.h>
63c817da 33#include <sys/mbuf.h>
9eb5d442 34#include <sys/kinfo.h>
94a2d2a7 35
4bec325f 36#include <net/route.h>
31bd2db6 37#include <net/if_dl.h>
94a2d2a7 38#include <netinet/in.h>
eac76d14 39#include <netns/ns.h>
7d5f817b 40#include <netiso/iso.h>
94a2d2a7 41
5c7868a2 42#include <netdb.h>
94a2d2a7 43#include <stdio.h>
4bec325f
BJ
44#include <errno.h>
45#include <ctype.h>
46
31bd2db6
KS
47struct keytab {
48 char *kt_cp;
49 int kt_i;
50} keywords[] = {
51#include "keywords.h"
52{0, 0}
53};
54
57cacc90 55struct ortentry route;
31bd2db6 56union sockunion {
7d5f817b
KS
57 struct sockaddr sa;
58 struct sockaddr_in sin;
59 struct sockaddr_ns sns;
60 struct sockaddr_iso siso;
31bd2db6
KS
61 struct sockaddr_dl sdl;
62} so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp, *so_addrs[] =
63{ &so_dst, &so_gate, &so_mask, &so_genmask, &so_ifa, &so_ifp, 0};
64typedef union sockunion *sup;
65int pid, rtm_addrs;
4bec325f 66int s;
31bd2db6
KS
67int forcehost, forcenet, doflush, nflag, af, qflag, Cflag, keyword();
68int iflag, verbose;
b268b889 69struct sockaddr_in sin = { sizeof(sin), AF_INET };
379dcc38 70struct in_addr inet_makeaddr();
31bd2db6
KS
71char *malloc(), *routename(), *netname();
72extern char *iso_ntoa(), *link_ntoa();
b268b889
MK
73#define kget(p, d) \
74 (lseek(kmem, (off_t)(p), 0), read(kmem, (char *)&(d), sizeof (d)))
4bec325f 75
31bd2db6
KS
76usage(cp)
77char *cp;
78{
79 fprintf(stderr,
80 "usage: route [ -nqCv ] cmd [[ -<qualifers> ] args ]\n");
81 if (cp) fprintf(stderr, "(botched keyword: %s)\n", cp);
82
83 exit(1);
84}
4bec325f
BJ
85main(argc, argv)
86 int argc;
87 char *argv[];
88{
89
b268b889 90 char *argvp;
4bec325f 91 if (argc < 2)
31bd2db6 92 usage((char *)0);
4bec325f 93 argc--, argv++;
b3933da8 94 for (; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
b268b889 95 for (argvp = argv[0]++; *argvp; argvp++)
b3933da8 96 switch (*argv[0]) {
b3933da8 97 case 'n':
a2280e64 98 nflag++;
b3933da8 99 break;
ae578a19
KS
100 case 'q':
101 qflag++;
102 break;
5c7868a2
KS
103 case 'C':
104 Cflag++; /* Use old ioctls */
57cacc90 105 break;
7d5f817b
KS
106 case 'v':
107 verbose++;
b3933da8
MK
108 }
109 }
5c7868a2
KS
110 pid = getpid();
111 if (Cflag)
57cacc90 112 s = socket(AF_INET, SOCK_RAW, 0);
5c7868a2
KS
113 else
114 s = socket(PF_ROUTE, SOCK_RAW, 0);
57cacc90
KS
115 if (s < 0) {
116 perror("route: socket");
117 exit(1);
118 }
31bd2db6
KS
119 if (argc > 0) switch (keyword(*argv)) {
120 case K_ADD:
121 case K_CHANGE:
122 case K_DELETE:
63c817da 123 newroute(argc, argv);
31bd2db6 124 case K_MONITOR:
5c7868a2 125 monitor();
31bd2db6
KS
126 case K_FLUSH:
127 flushroutes(argc, argv);
128 }
129 usage(*argv);
63c817da
SL
130}
131
132/*
133 * Purge all entries in the routing tables not
134 * associated with network interfaces.
135 */
31bd2db6
KS
136flushroutes(argc, argv)
137char *argv[];
b268b889 138{
9eb5d442
KS
139 int bufsize, needed, seqno, rlen;
140 char *buf, *next, *lim;
141 register struct rt_msghdr *rtm;
142 struct {
143 struct rt_msghdr m_rtm;
144 union {
145 char u_saddrs[200];
146 struct sockaddr u_sa;
147 } m_u;
148 } m;
149
31bd2db6
KS
150 if (argc > 1) {
151 argv++;
152 if (argc == 1 && **argv == '-') switch (keyword(1 + *argv)) {
153 case K_INET: af = AF_INET; break;
154 case K_XNS: af = AF_NS; break;
155 case K_LINK: af = AF_LINK; break;
156 case K_OSI: af = AF_ISO; break;
157 default: goto bad;
158 } else
159 bad: usage(*argv);
160 }
9eb5d442
KS
161 if ((needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0)) < 0)
162 { perror("route-getkerninfo-estimate"); exit(1);}
163 if ((buf = malloc(needed)) == 0)
164 { printf("out of space\n");; exit(1);}
165 if ((rlen = getkerninfo(KINFO_RT_DUMP, buf, &needed, 0)) < 0)
166 { perror("actual retrieval of routing table"); exit(1);}
167 lim = buf + rlen;
168 for (next = buf; next < lim; next += rtm->rtm_msglen) {
169 rtm = (struct rt_msghdr *)next;
170 if ((rtm->rtm_flags & (RTF_GATEWAY|RTF_HOST)) == 0)
171 continue;
31bd2db6
KS
172 if (af) {
173 struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
174 if (sa->sa_family != af)
175 continue;
176 }
9eb5d442
KS
177 rtm->rtm_type = RTM_DELETE;
178 rtm->rtm_seq = seqno;
179 if ((rlen = write(s, next, rtm->rtm_msglen)) < 0) {
180 perror("writing to routing socket");
181 printf("got only %d for rlen\n", rlen);
31bd2db6 182 break;
b268b889 183 }
9eb5d442
KS
184 again:
185 if ((rlen = read(s, (char *)&m, sizeof (m))) < 0) {
186 perror("reading from routing socket");
187 printf("got only %d for rlen\n", rlen);
31bd2db6 188 break;
9eb5d442
KS
189 }
190 if ((m.m_rtm.rtm_pid != pid) || (m.m_rtm.rtm_seq != seqno)) {
191 printf("Got response for somebody else's request");
192 goto again;
193 }
194 seqno++;
195 if (qflag)
196 continue;
197 if (verbose) {
31bd2db6 198 print_rtmsg(rtm, rlen);
9eb5d442
KS
199 } else {
200 struct sockaddr *sa = &m.m_u.u_sa;
201 printf("%-20.20s ", (rtm->rtm_flags & RTF_HOST) ?
202 routename(sa) : netname(sa));
203 sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
204 printf("%-20.20s ", routename(sa));
205 printf("done\n");
57cacc90
KS
206 }
207 }
31bd2db6 208 exit(0);
57cacc90 209}
9eb5d442 210
63c817da 211char *
eac76d14
MK
212routename(sa)
213 struct sockaddr *sa;
63c817da 214{
a2280e64 215 register char *cp;
63c817da 216 static char line[50];
6edb1941 217 struct hostent *hp;
a2280e64
MK
218 static char domain[MAXHOSTNAMELEN + 1];
219 static int first = 1;
220 char *index();
eac76d14 221 char *ns_print();
63c817da 222
a2280e64
MK
223 if (first) {
224 first = 0;
225 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
226 (cp = index(domain, '.')))
227 (void) strcpy(domain, cp + 1);
228 else
229 domain[0] = 0;
230 }
eac76d14
MK
231 switch (sa->sa_family) {
232
233 case AF_INET:
234 { struct in_addr in;
235 in = ((struct sockaddr_in *)sa)->sin_addr;
236
237 cp = 0;
238 if (in.s_addr == INADDR_ANY)
239 cp = "default";
240 if (cp == 0 && !nflag) {
241 hp = gethostbyaddr(&in, sizeof (struct in_addr),
242 AF_INET);
243 if (hp) {
244 if ((cp = index(hp->h_name, '.')) &&
245 !strcmp(cp + 1, domain))
246 *cp = 0;
247 cp = hp->h_name;
248 }
a2280e64 249 }
eac76d14
MK
250 if (cp)
251 strcpy(line, cp);
252 else {
a2280e64 253#define C(x) ((x) & 0xff)
eac76d14 254 in.s_addr = ntohl(in.s_addr);
9bd38ba8 255 (void)sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
eac76d14
MK
256 C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
257 }
258 break;
259 }
260
261 case AF_NS:
262 return (ns_print((struct sockaddr_ns *)sa));
263
31bd2db6
KS
264 case AF_LINK:
265 return (link_ntoa((struct sockaddr_dl *)sa));
266
267 case AF_ISO:
268 (void) sprintf(line, "iso %s",
269 iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr));
270 break;
271
eac76d14
MK
272 default:
273 { u_short *s = (u_short *)sa->sa_data;
31bd2db6
KS
274 u_short *slim = s + ((sa->sa_len + 1)>>1);
275 char *cp = line + sprintf(line, "(%d)", sa->sa_family);
276 int n;
eac76d14 277
31bd2db6
KS
278 while (s < slim) {
279 n = sprintf(cp, " %x", *s);
280 s++; cp += n;
281 }
eac76d14
MK
282 break;
283 }
a2280e64
MK
284 }
285 return (line);
286}
287
288/*
289 * Return the name of the network whose address is given.
290 * The address is assumed to be that of a net or subnet, not a host.
291 */
292char *
eac76d14
MK
293netname(sa)
294 struct sockaddr *sa;
a2280e64
MK
295{
296 char *cp = 0;
297 static char line[50];
298 struct netent *np = 0;
299 u_long net, mask;
e2fe1192 300 register u_long i;
a2280e64 301 int subnetshift;
a48a48cc 302 char *ns_print();
a2280e64 303
eac76d14
MK
304 switch (sa->sa_family) {
305
306 case AF_INET:
307 { struct in_addr in;
308 in = ((struct sockaddr_in *)sa)->sin_addr;
309
e2fe1192 310 i = in.s_addr = ntohl(in.s_addr);
eac76d14
MK
311 if (in.s_addr == 0)
312 cp = "default";
313 else if (!nflag) {
314 if (IN_CLASSA(i)) {
315 mask = IN_CLASSA_NET;
316 subnetshift = 8;
317 } else if (IN_CLASSB(i)) {
318 mask = IN_CLASSB_NET;
319 subnetshift = 8;
320 } else {
321 mask = IN_CLASSC_NET;
322 subnetshift = 4;
323 }
324 /*
325 * If there are more bits than the standard mask
326 * would suggest, subnets must be in use.
327 * Guess at the subnet mask, assuming reasonable
328 * width subnet fields.
329 */
330 while (in.s_addr &~ mask)
331 mask = (long)mask >> subnetshift;
332 net = in.s_addr & mask;
333 while ((mask & 1) == 0)
334 mask >>= 1, net >>= 1;
335 np = getnetbyaddr(net, AF_INET);
336 if (np)
337 cp = np->n_name;
a2280e64 338 }
eac76d14
MK
339 if (cp)
340 strcpy(line, cp);
341 else if ((in.s_addr & 0xffffff) == 0)
9bd38ba8 342 (void)sprintf(line, "%u", C(in.s_addr >> 24));
eac76d14 343 else if ((in.s_addr & 0xffff) == 0)
9bd38ba8 344 (void)sprintf(line, "%u.%u", C(in.s_addr >> 24),
eac76d14
MK
345 C(in.s_addr >> 16));
346 else if ((in.s_addr & 0xff) == 0)
9bd38ba8 347 (void)sprintf(line, "%u.%u.%u", C(in.s_addr >> 24),
eac76d14
MK
348 C(in.s_addr >> 16), C(in.s_addr >> 8));
349 else
9bd38ba8 350 (void)sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
eac76d14
MK
351 C(in.s_addr >> 16), C(in.s_addr >> 8),
352 C(in.s_addr));
353 break;
354 }
355
356 case AF_NS:
357 return (ns_print((struct sockaddr_ns *)sa));
358 break;
359
31bd2db6
KS
360 case AF_LINK:
361 return (link_ntoa((struct sockaddr_dl *)sa));
362
363 case AF_ISO:
364 (void) sprintf(line, "iso %s",
365 iso_ntoa(&((struct sockaddr_iso *)sa)->siso_addr));
366 break;
367
eac76d14
MK
368 default:
369 { u_short *s = (u_short *)sa->sa_data;
31bd2db6
KS
370 u_short *slim = s + ((sa->sa_len + 1)>>1);
371 char *cp = line + sprintf(line, "af %d:", sa->sa_family);
372 int n;
eac76d14 373
31bd2db6
KS
374 while (s < slim) {
375 n = sprintf(cp, " %x", *s);
376 s++; cp += n;
377 }
eac76d14
MK
378 break;
379 }
63c817da
SL
380 }
381 return (line);
4bec325f
BJ
382}
383
384newroute(argc, argv)
385 int argc;
31bd2db6 386 register char **argv;
4bec325f
BJ
387{
388 struct sockaddr_in *sin;
57cacc90 389 char *cmd, *dest, *gateway, *mask;
31bd2db6
KS
390 int ishost, metric = 0, ret, attempts, oerrno, flags = 0, next;
391 struct hostent *hp = 0;
792b0612 392 extern int errno;
4bec325f 393
183ef13b 394 cmd = argv[0];
31bd2db6
KS
395 while (--argc > 0) {
396 if (**(++argv)== '-') {
397 switch(keyword(1 + *argv)) {
398 case K_LINK:
399 af = AF_LINK;
400 break;
401 case K_OSI:
402 af = AF_ISO;
403 break;
404 case K_INET:
405 af = AF_INET;
406 break;
407 case K_XNS:
408 af = AF_NS;
409 break;
410 case K_IFACE:
411 iflag++;
412 break;
413 case K_HOST:
414 forcehost++;
415 break;
416 case K_NET:
417 forcenet++;
418 break;
419 case K_NETMASK:
420 argc--;
421 (void) getaddr(RTA_NETMASK, *++argv, 0);
422 break;
423 case K_GENMASK:
424 argc--;
425 (void) getaddr(RTA_GENMASK, *++argv, 0);
426 break;
427 default:
428 usage(1+*argv);
429 }
430 } else {
431 if ((rtm_addrs & RTA_DST) == 0) {
432 dest = *argv;
433 ishost = getaddr(RTA_DST, *argv, &hp);
434 } else if ((rtm_addrs & RTA_GATEWAY) == 0) {
435 gateway = *argv;
436 (void) getaddr(RTA_GATEWAY, *argv, &hp);
437 } else {
438 int ret = atoi(*argv);
439 if (ret == 0) {
440 printf("%s,%s", "old usage of trailing 0",
441 "assuming route to if\n");
442 iflag = 1;
443 continue;
444 } else if (ret > 0 && ret < 10) {
445 printf("old usage of trailing digit, ");
446 printf("assuming route via gateway\n");
447 iflag = 0;
448 continue;
449 }
450 (void) getaddr(RTA_NETMASK, *argv, 0);
451 }
452 }
453 }
b3933da8
MK
454 if (forcehost)
455 ishost = 1;
456 if (forcenet)
457 ishost = 0;
7d5f817b 458 flags = RTF_UP;
6edb1941 459 if (ishost)
7d5f817b 460 flags |= RTF_HOST;
57cacc90 461 if (iflag == 0)
7d5f817b 462 flags |= RTF_GATEWAY;
792b0612
MK
463 for (attempts = 1; ; attempts++) {
464 errno = 0;
31bd2db6 465 if (Cflag && (af == AF_INET || af == AF_NS)) {
7d5f817b
KS
466 route.rt_flags = flags;
467 route.rt_dst = so_dst.sa;
468 route.rt_gateway = so_gate.sa;
57cacc90
KS
469 if ((ret = ioctl(s, *cmd == 'a' ? SIOCADDRT : SIOCDELRT,
470 (caddr_t)&route)) == 0)
471 break;
472 } else {
31bd2db6 473 if ((ret = rtmsg(*cmd, flags)) == 0);
57cacc90
KS
474 break;
475 }
792b0612
MK
476 if (errno != ENETUNREACH && errno != ESRCH)
477 break;
478 if (hp && hp->h_addr_list[1]) {
479 hp->h_addr_list++;
7d5f817b 480 bcopy(hp->h_addr_list[0], (caddr_t)&so_dst.sin.sin_addr,
792b0612
MK
481 hp->h_length);
482 } else
483 break;
484 }
485 oerrno = errno;
486 printf("%s %s %s: gateway %s", cmd, ishost? "host" : "net",
487 dest, gateway);
488 if (attempts > 1 && ret == 0)
489 printf(" (%s)",
490 inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr));
491 if (ret == 0)
492 printf("\n");
493 else {
494 printf(": ");
495 fflush(stdout);
496 errno = oerrno;
31bd2db6 497 error("");
792b0612 498 }
31bd2db6 499 exit(0);
4bec325f
BJ
500}
501
502error(cmd)
503 char *cmd;
504{
a48a48cc 505 extern int errno;
4bec325f 506
a48a48cc
KB
507 switch(errno) {
508 case ESRCH:
ae578a19 509 printf("not in table\n");
a48a48cc
KB
510 break;
511 case EBUSY:
ae578a19 512 printf("entry in use\n");
a48a48cc
KB
513 break;
514 case ENOBUFS:
ae578a19 515 printf("routing table overflow\n");
a48a48cc
KB
516 break;
517 default:
57cacc90 518 printf("ioctl returns %d\n", errno);
4bec325f 519 perror(cmd);
a48a48cc 520 }
ae578a19
KS
521 fflush(stdout);
522 errno = 0;
4bec325f
BJ
523}
524
55e026df
MK
525char *
526savestr(s)
527 char *s;
528{
529 char *sav;
530
531 sav = malloc(strlen(s) + 1);
532 if (sav == NULL) {
533 fprintf("route: out of memory\n");
534 exit(1);
535 }
536 strcpy(sav, s);
537 return (sav);
538}
539
31bd2db6 540inet_makenetandmask(net, sin)
5c7868a2 541u_long net;
31bd2db6 542register struct sockaddr_in *sin;
57cacc90
KS
543{
544 u_long addr;
5c7868a2 545 u_long mask = 0;
31bd2db6 546 register char *cp;
57cacc90 547
31bd2db6 548 rtm_addrs |= RTA_NETMASK;
57cacc90 549 if (net == 0)
5c7868a2 550 mask = addr = 0;
57cacc90
KS
551 else if (net < 128) {
552 addr = net << IN_CLASSA_NSHIFT;
5c7868a2 553 mask = IN_CLASSA_NET;
57cacc90
KS
554 } else if (net < 65536) {
555 addr = net << IN_CLASSB_NSHIFT;
5c7868a2 556 mask = IN_CLASSB_NET;
57cacc90
KS
557 } else if (net < 16777216L) {
558 addr = net << IN_CLASSC_NSHIFT;
5c7868a2 559 mask = IN_CLASSC_NET;
57cacc90
KS
560 } else {
561 addr = net;
562 if ((addr & IN_CLASSA_HOST) == 0)
5c7868a2 563 mask = IN_CLASSA_NET;
57cacc90 564 else if ((addr & IN_CLASSB_HOST) == 0)
5c7868a2 565 mask = IN_CLASSB_NET;
57cacc90 566 else if ((addr & IN_CLASSC_HOST) == 0)
5c7868a2 567 mask = IN_CLASSC_NET;
57cacc90 568 else
5c7868a2
KS
569 mask = -1;
570 }
31bd2db6
KS
571 sin->sin_addr.s_addr = htonl(addr);
572 sin = &so_mask.sin;
573 sin->sin_addr.s_addr = htonl(mask);
574 sin->sin_len = 0;
575 sin->sin_family = 0;
576 cp = (char *)(1 + &(sin->sin_addr));
577 while (*--cp == 0 && cp > (char *)sin)
578 ;
579 sin->sin_len = 1 + cp - (char *)sin;
57cacc90
KS
580}
581
6edb1941
MK
582/*
583 * Interpret an argument as a network address of some kind,
584 * returning 1 if a host address, 0 if a network address.
585 */
31bd2db6 586getaddr(which, s, hpp)
4bec325f 587 char *s;
792b0612 588 struct hostent **hpp;
4bec325f 589{
31bd2db6 590 register union sockunion *su;
b268b889 591 struct ns_addr ns_addr();
31bd2db6 592 struct iso_addr iso_addr();
accbc2e3 593 struct hostent *hp;
379dcc38 594 struct netent *np;
31bd2db6 595 u_long val;
accbc2e3 596
31bd2db6
KS
597 if (af == 0)
598 af = AF_INET;
599 switch (which) {
600 case RTA_DST: su = so_addrs[0]; break;
601 case RTA_GATEWAY: su = so_addrs[1]; break;
602 case RTA_NETMASK: su = so_addrs[2]; break;
603 case RTA_GENMASK: su = so_addrs[3]; break;
604 default: usage("Internal Error"); /*NOTREACHED*/
605 }
606 rtm_addrs |= which;
607 su->sa.sa_family = af;
7d5f817b 608 if (strcmp(s, "default") == 0) {
31bd2db6
KS
609 su->sa.sa_len = 0;
610 if (which == RTA_DST)
611 getaddr(RTA_NETMASK, s, 0);
612 return 0;
7d5f817b 613 }
31bd2db6 614 if (af == AF_NS)
b268b889 615 goto do_xns;
31bd2db6 616 if (af == AF_OSI)
7d5f817b 617 goto do_osi;
31bd2db6
KS
618 if (af == AF_LINK)
619 goto do_link;
620 su->sin.sin_len = sizeof(su->sin);
621 if (hpp == 0) hpp = &hp;
7d5f817b 622 *hpp = 0;
31bd2db6
KS
623 if (forcenet == 0 && (val = inet_addr(s)) != -1) {
624 su->sin.sin_addr.s_addr = val;
625 if (inet_lnaof(su->sin.sin_addr) != INADDR_ANY)
626 return (1);
627 else {
628 val = ntohl(val);
629 out: if (which == RTA_DST)
630 inet_makenetandmask(val, &su->sin);
631 return (0);
a2280e64 632 }
792b0612
MK
633 }
634 val = inet_network(s);
635 if (val != -1) {
5c7868a2 636 goto out;
792b0612 637 }
379dcc38
SL
638 np = getnetbyname(s);
639 if (np) {
5c7868a2 640 val = np->n_net;
5c7868a2 641 goto out;
379dcc38 642 }
78160c55
MK
643 hp = gethostbyname(s);
644 if (hp) {
792b0612 645 *hpp = hp;
31bd2db6
KS
646 su->sin.sin_family = hp->h_addrtype;
647 bcopy(hp->h_addr, &su->sin.sin_addr, hp->h_length);
57cacc90 648 return (1);
78160c55 649 }
379dcc38
SL
650 fprintf(stderr, "%s: bad value\n", s);
651 exit(1);
b268b889 652do_xns:
31bd2db6 653 su->sns.sns_len = sizeof (su->sns);
7d5f817b
KS
654 if (val == 0)
655 return(0);
31bd2db6 656 if (which == RTA_DST) {
57cacc90 657 extern short ns_bh[3];
31bd2db6
KS
658 struct sockaddr_ns *sms = &(so_mask.sns);
659 bzero((char *)sms, sizeof(*sms));
57cacc90
KS
660 sms->sns_family = 0;
661 sms->sns_len = 6;
662 sms->sns_addr.x_net = *(union ns_net *)ns_bh;
31bd2db6 663 rtm_addrs |= RTA_NETMASK;
57cacc90 664 }
31bd2db6
KS
665 su->sns.sns_addr = ns_addr(s);
666 return (!ns_nullhost(su->sns.sns_addr));
7d5f817b 667do_osi:
31bd2db6
KS
668 su->siso.siso_len = sizeof(su->siso);
669 su->siso.siso_addr = iso_addr(s);
670 return (1);
671do_link:
672 su->sdl.sdl_len = sizeof(su->sdl);
673 link_addr(s, &su->sdl);
7d5f817b 674 return (1);
183ef13b 675}
eac76d14
MK
676
677short ns_nullh[] = {0,0,0};
678short ns_bh[] = {-1,-1,-1};
679
680char *
681ns_print(sns)
682struct sockaddr_ns *sns;
683{
684 struct ns_addr work;
685 union { union ns_net net_e; u_long long_e; } net;
686 u_short port;
687 static char mybuf[50], cport[10], chost[25];
688 char *host = "";
689 register char *p; register u_char *q; u_char *q_lim;
690
691 work = sns->sns_addr;
692 port = ntohs(work.x_port);
693 work.x_port = 0;
694 net.net_e = work.x_net;
695 if (ns_nullhost(work) && net.long_e == 0) {
696 if (port ) {
9bd38ba8 697 (void)sprintf(mybuf, "*.%xH", port);
eac76d14
MK
698 upHex(mybuf);
699 } else
9bd38ba8 700 (void)sprintf(mybuf, "*.*");
eac76d14
MK
701 return (mybuf);
702 }
703
704 if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) {
705 host = "any";
706 } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) {
707 host = "*";
708 } else {
709 q = work.x_host.c_host;
9bd38ba8 710 (void)sprintf(chost, "%02x%02x%02x%02x%02x%02xH",
eac76d14
MK
711 q[0], q[1], q[2], q[3], q[4], q[5]);
712 for (p = chost; *p == '0' && p < chost + 12; p++);
713 host = p;
714 }
715 if (port)
9bd38ba8 716 (void)sprintf(cport, ".%xH", htons(port));
eac76d14
MK
717 else
718 *cport = 0;
719
9bd38ba8 720 (void)sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport);
eac76d14
MK
721 upHex(mybuf);
722 return(mybuf);
723}
724
725upHex(p0)
726char *p0;
727{
728 register char *p = p0;
729 for (; *p; p++) switch (*p) {
730
731 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
732 *p += ('A' - 'a');
733 }
734}
57cacc90
KS
735
736monitor()
737{
738 int n;
739 char msg[2048];
9eb5d442 740 verbose = 1;
57cacc90
KS
741 for(;;) {
742 n = read(s, msg, 2048);
743 printf("got message of size %d\n", n);
31bd2db6 744 print_rtmsg((struct rt_msghdr *)msg);
57cacc90
KS
745 }
746}
747
748struct {
749 struct rt_msghdr m_rtm;
31bd2db6 750 char m_space[512];
57cacc90
KS
751} m_rtmsg;
752
31bd2db6 753rtmsg(cmd, flags)
57cacc90
KS
754{
755 static int seq;
756 int len = sizeof(m_rtmsg), rlen;
757 extern int errno;
31bd2db6
KS
758 register char *cp = m_rtmsg.m_space;
759 register int l;
57cacc90
KS
760
761 errno = 0;
762 bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
763 if (cmd == 'a')
764 cmd = RTM_ADD;
765 else if (cmd == 'c')
766 cmd = RTM_CHANGE;
767 else
768 cmd = RTM_DELETE;
769 m_rtmsg.m_rtm.rtm_flags = flags;
a387100b 770 m_rtmsg.m_rtm.rtm_version = RTM_VERSION;
57cacc90 771 m_rtmsg.m_rtm.rtm_seq = ++seq;
31bd2db6
KS
772 m_rtmsg.m_rtm.rtm_addrs = rtm_addrs;
773
774#define ROUND(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
775#define NEXTADDR(w, u) { if (rtm_addrs & (w)) {l = (u).sa.sa_len;\
776 if(verbose)sodump(&(u),"u");if(l == 0) l = sizeof(int); l = ROUND(l);\
777 bcopy((char *)&(u), cp, l); cp += l;}}
778
779 NEXTADDR(RTA_DST, so_dst);
780 NEXTADDR(RTA_GATEWAY, so_gate);
781 NEXTADDR(RTA_NETMASK, so_mask);
782 NEXTADDR(RTA_GENMASK, so_genmask);
783 m_rtmsg.m_rtm.rtm_msglen = cp - (char *)&m_rtmsg;
57cacc90 784 m_rtmsg.m_rtm.rtm_type = cmd;
31bd2db6
KS
785 if (verbose)
786 print_rtmsg(&m_rtmsg.m_rtm, len);
57cacc90
KS
787 if ((rlen = write(s, (char *)&m_rtmsg, len)) < 0) {
788 perror("writing to routing socket");
789 printf("got only %d for rlen\n", rlen);
7d5f817b 790 return (-1);
57cacc90
KS
791 }
792again:
793 if ((rlen = read(s, (char *)&m_rtmsg, len)) < 0) {
794 perror("reading from routing socket");
795 printf("got only %d for rlen\n", rlen);
7d5f817b 796 return (-1);
57cacc90
KS
797 }
798 if ((m_rtmsg.m_rtm.rtm_pid != pid) ||
799 (m_rtmsg.m_rtm.rtm_seq != seq)) {
800 printf("Got response for somebody else's request");
801 goto again;
802 }
803 if (qflag == 0)
804 print_rtmsg( &m_rtmsg.m_rtm, rlen);
805 if ((m_rtmsg.m_rtm.rtm_flags & RTF_DONE) == 0) {
806 errno = m_rtmsg.m_rtm.rtm_errno;
807 perror("response from routing socket turned down");
808 return (-1);
809 }
810 return (0);
811}
812
813char *msgtypes[] = {
814"",
815"RTM_ADD: Add Route",
816"RTM_DELETE: Delete Route",
817"RTM_CHANGE: Change Metrics or flags",
818"RTM_GET: Report Metrics",
819"RTM_LOSING: Kernel Suspects Partitioning",
820"RTM_REDIRECT: Told to use different route",
821"RTM_MISS: Lookup failed on this address",
822"RTM_LOCK: fix specified metrics",
823"RTM_OLDADD: caused by SIOCADDRT",
824"RTM_OLDDEL: caused by SIOCDELRT",
8250, };
826
827char metricnames[] =
828"\010rttvar\7rtt\6ssthresh\7sendpipe\4recvpipe\3expire\2hopcount\1mtu";
829
830#define ROUNDUP(a) ((char *)(1 + (((((int)a)) - 1) | (sizeof(long) - 1))))
831
832print_rtmsg(rtm, n)
833register struct rt_msghdr *rtm;
834{
835 char *cp;
836 register struct sockaddr *sa;
a387100b 837 int i;
57cacc90 838
7d5f817b
KS
839 if (verbose == 0)
840 return;
a387100b 841 if (rtm->rtm_version != RTM_VERSION) {
5c7868a2 842 printf("routing message version %d not understood\n",
57cacc90 843 rtm->rtm_version);
5c7868a2
KS
844 } else {
845 printf("%s\npid: %d, len %d, seq %d, errno %d, flags:",
846 msgtypes[rtm->rtm_type], rtm->rtm_pid, rtm->rtm_msglen,
847 rtm->rtm_seq, rtm->rtm_errno);
848 bprintf(stdout, rtm->rtm_flags,
849 "\1UP\2GATEWAY\3HOST\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT");
a387100b 850 printf("\nlocks: "); bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames);
5c7868a2 851 printf(" inits: "); bprintf(stdout, rtm->rtm_inits, metricnames);
31bd2db6 852 printf("\nsockaddrs: ");
a387100b
KS
853 bprintf(stdout, rtm->rtm_addrs,
854 "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR");
855 putchar('\n');
5c7868a2 856 cp = ((char *)(rtm + 1));
a387100b
KS
857 if (rtm->rtm_addrs)
858 for (i = 1; i; i <<= 1)
859 if (i & rtm->rtm_addrs) {
860 sa = (struct sockaddr *)cp;
861 printf(" %s", routename(sa));
862 cp = ROUNDUP(cp + sa->sa_len);
863 }
5c7868a2 864 putchar('\n');
57cacc90 865 }
57cacc90
KS
866 fflush(stdout);
867}
868
869bprintf(fp, b, s)
870register FILE *fp;
871register int b;
872register u_char *s;
873{
874 register int i;
875 int gotsome = 0;
876
877 if (b == 0)
878 return;
879 while (i = *s++) {
880 if (b & (1 << (i-1))) {
881 if (gotsome == 0) i = '<'; else i = ',';
882 putc(i, fp);
883 gotsome = 1;
884 for (; (i = *s) > 32; s++)
885 putc(i, fp);
886 } else
887 while (*s > 32)
888 s++;
889 }
890 if (gotsome)
891 putc('>', fp);
892}
31bd2db6
KS
893int
894keyword(cp)
895char *cp;
896{
897 register struct keytab *kt = keywords;
898 while (kt->kt_cp && strcmp(kt->kt_cp, cp))
899 kt++;
900 return kt->kt_i;
901}
902
903sodump(su, which)
904register union sockunion *su;
905char *which;
906{
907 switch (su->sa.sa_family) {
908 case AF_LINK:
909 printf("%s: link %s; ", which, link_ntoa(&su->sdl));
910 break;
911 case AF_ISO:
912 printf("%s: iso %s; ", which, iso_ntoa(&su->siso.siso_addr));
913 break;
914 case AF_INET:
915 printf("%s: inet %s; ", which, inet_ntoa(su->sin.sin_addr));
916 break;
917 case AF_NS:
918 printf("%s: xns %s; ", which, ns_ntoa(&su->sns.sns_addr));
919 break;
920 }
921 fflush(stdout);
922}
923
924/*
925 * Copyright (c) 1990 Regents of the University of California.
926 * All rights reserved.
927 *
928 * Redistribution and use in source and binary forms are permitted
929 * provided that the above copyright notice and this paragraph are
930 * duplicated in all such forms and that any documentation,
931 * advertising materials, and other materials related to such
932 * distribution and use acknowledge that the software was developed
933 * by the University of California, Berkeley. The name of the
934 * University may not be used to endorse or promote products derived
935 * from this software without specific prior written permission.
936 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
937 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
938 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
939 */
940
941#if defined(LIBC_SCCS) && !defined(lint)
942static char sccsid[] = "@(#)linkaddr.c 5.1 (Berkeley) 4/1/90";
943#endif /* LIBC_SCCS and not lint */
944
945#ifndef AF_LINK
946#include <sys/param.h>
947#include <sys/socket.h>
948#include <net/if_dl.h>
949#endif
950/* States*/
951#define NAMING 0
952#define GOTONE 1
953#define GOTTWO 2
954#define RESET 3
955/* Inputs */
956#define DIGIT (4*0)
957#define END (4*1)
958#define DELIM (4*2)
959#define LETTER (4*3)
960
961link_addr(addr, sdl)
962register char *addr;
963register struct sockaddr_dl *sdl;
964{
965 register char *cp = sdl->sdl_data;
966 char *cplim = sdl->sdl_len + (char *)sdl;
967 register int byte = 0, state = NAMING, new;
968
969 bzero((char *)&sdl->sdl_family, sdl->sdl_len - 1);
970 sdl->sdl_family = AF_LINK;
971 do {
972 state &= ~LETTER;
973 if ((*addr >= '0') && (*addr <= '9')) {
974 new = *addr - '0';
975 } else if ((*addr >= 'a') && (*addr <= 'f')) {
976 new = *addr - 'a' + 10;
977 } else if ((*addr >= 'A') && (*addr <= 'F')) {
978 new = *addr - 'A' + 10;
979 } else if (*addr == 0) {
980 state |= END;
981 } else if (state == NAMING &&
982 (((*addr >= 'A') && (*addr <= 'Z')) ||
983 ((*addr >= 'a') && (*addr <= 'z'))))
984 state |= LETTER;
985 else
986 state |= DELIM;
987 addr++;
988 switch (state /* | INPUT */) {
989 case NAMING | DIGIT:
990 case NAMING | LETTER:
991 *cp++ = addr[-1]; continue;
992 case NAMING | DELIM:
993 state = RESET; sdl->sdl_nlen = cp - sdl->sdl_data; continue;
994 case GOTTWO | DIGIT:
995 *cp++ = byte; /*FALLTHROUGH*/
996 case RESET | DIGIT:
997 state = GOTONE; byte = new; continue;
998 case GOTONE | DIGIT:
999 state = GOTTWO; byte = new + (byte << 4); continue;
1000 default: /* | DELIM */
1001 state = RESET; *cp++ = byte; byte = 0; continue;
1002 case GOTONE | END:
1003 case GOTTWO | END:
1004 *cp++ = byte; /* FALLTHROUGH */
1005 case RESET | END:
1006 break;
1007 }
1008 break;
1009 } while (cp < cplim);
1010 sdl->sdl_alen = cp - LLADDR(sdl);
1011 new = cp - (char *)sdl;
1012 if (new > sizeof(*sdl))
1013 sdl->sdl_len = new;
1014 return;
1015}
1016static char hexlist[] = "0123456789abcdef";
1017
1018char *
1019link_ntoa(sdl)
1020register struct sockaddr_dl *sdl;
1021{
1022 static char obuf[64];
1023 register char *out = obuf;
1024 register int i;
1025 register u_char *in = (u_char *)LLADDR(sdl);
1026 u_char *inlim = in + sdl->sdl_nlen;
1027 int firsttime = 1;
1028
1029 if (sdl->sdl_nlen) {
1030 bcopy(sdl->sdl_data, obuf, sdl->sdl_nlen);
1031 out += sdl->sdl_nlen;
1032 *out++ = ':';
1033 }
1034 while (in < inlim) {
1035 if (firsttime) firsttime = 0; else *out++ = '.';
1036 i = *in++;
1037 if (i > 0xf) {
1038 out[1] = hexlist[i & 0xf];
1039 i >>= 4;
1040 out[0] = hexlist[i];
1041 out += 2;
1042 } else
1043 *out++ = hexlist[i];
1044 }
1045 *out = 0;
1046 return(obuf);
1047}