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