|
|
1.1 root 1: /*
2: * Copyright (c) 1983, 1988 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: static char sccsid[] = "@(#)route.c 5.19 (Berkeley) 6/18/90";
22: #endif /* not lint */
23:
24: #include <sys/param.h>
25: #include <sys/socket.h>
26: #include <sys/mbuf.h>
27:
28: #include <net/if.h>
29: #define KERNEL
30: #include <net/route.h>
31: #undef KERNEL
32: #include <netinet/in.h>
33:
34: #include <netns/ns.h>
35:
36: #include <netdb.h>
37: #include <sys/kinfo.h>
38:
39: #include <stdio.h>
40: #include <string.h>
41:
42: extern int nflag;
43: extern char *routename(), *netname(), *ns_print(), *plural();
44: extern char *malloc();
45: #define kget(p, d) \
46: (kvm_read((off_t)(p), (char *)&(d), sizeof (d)))
47:
48: /*
49: * Definitions for showing gateway flags.
50: */
51: struct bits {
52: short b_mask;
53: char b_val;
54: } bits[] = {
55: { RTF_UP, 'U' },
56: { RTF_GATEWAY, 'G' },
57: { RTF_HOST, 'H' },
58: { RTF_DYNAMIC, 'D' },
59: { RTF_MODIFIED, 'M' },
60: { RTF_CLONING, 'C' },
61: { RTF_XRESOLVE, 'R' },
62: { RTF_LLINFO, 'L' },
63: { 0 }
64: };
65:
66: /*
67: * Print routing tables.
68: */
69: routepr(hostaddr, netaddr, hashsizeaddr, treeaddr)
70: off_t hostaddr, netaddr, hashsizeaddr, treeaddr;
71: {
72: struct mbuf mb;
73: register struct ortentry *rt;
74: register struct mbuf *m;
75: char name[16], *flags;
76: struct mbuf **routehash;
77: int hashsize;
78: int i, doinghost = 1;
79:
80: printf("Routing tables\n");
81: printf("%-16.16s %-18.18s %-6.6s %6.6s%8.8s %s\n",
82: "Destination", "Gateway",
83: "Flags", "Refs", "Use", "Interface");
84: if (treeaddr)
85: return treestuff(treeaddr);
86: if (hostaddr == 0) {
87: printf("rthost: symbol not in namelist\n");
88: return;
89: }
90: if (netaddr == 0) {
91: printf("rtnet: symbol not in namelist\n");
92: return;
93: }
94: if (hashsizeaddr == 0) {
95: printf("rthashsize: symbol not in namelist\n");
96: return;
97: }
98: kget(hashsizeaddr, hashsize);
99: routehash = (struct mbuf **)malloc( hashsize*sizeof (struct mbuf *) );
100: kvm_read(hostaddr, (char *)routehash, hashsize*sizeof (struct mbuf *));
101: again:
102: for (i = 0; i < hashsize; i++) {
103: if (routehash[i] == 0)
104: continue;
105: m = routehash[i];
106: while (m) {
107: kget(m, mb);
108: p_rtentry((struct rtentry *)(mb.m_dat));
109: m = mb.m_next;
110: }
111: }
112: if (doinghost) {
113: kvm_read(netaddr, (char *)routehash,
114: hashsize*sizeof (struct mbuf *));
115: doinghost = 0;
116: goto again;
117: }
118: free((char *)routehash);
119: return;
120: }
121:
122: static union {
123: struct sockaddr u_sa;
124: u_short u_data[128];
125: } pt_u;
126: static struct rtentry rtentry;
127:
128: int NewTree = 0;
129: treestuff(rtree)
130: off_t rtree;
131: {
132: struct radix_node_head *rnh, head;
133:
134: if (NewTree)
135: return(ntreestuff());
136: for (kget(rtree, rnh); rnh; rnh = head.rnh_next) {
137: kget(rnh, head);
138: if (head.rnh_af == 0) {
139: printf("Netmasks:\n");
140: p_tree(head.rnh_treetop, 0);
141: } else {
142: printf("\nRoute Tree for Protocol Family %d:\n",
143: head.rnh_af);
144: p_tree(head.rnh_treetop, 1);
145: }
146: }
147: }
148:
149: struct sockaddr *
150: kgetsa(dst)
151: register struct sockaddr *dst;
152: {
153: kget(dst, pt_u.u_sa);
154: if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa)) {
155: kvm_read((off_t)dst, pt_u.u_data, pt_u.u_sa.sa_len);
156: }
157: return (&pt_u.u_sa);
158: }
159:
160: p_tree(rn, do_rtent)
161: struct radix_node *rn;
162: {
163: struct radix_node rnode;
164: register u_short *s, *slim;
165: int len;
166:
167: again:
168: kget(rn, rnode);
169: if (rnode.rn_b < 0) {
170: if (rnode.rn_flags & RNF_ROOT)
171: printf("(root node)\n");
172: else if (do_rtent) {
173: kget(rn, rtentry);
174: p_rtentry(&rtentry);
175: } else {
176: p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key),
177: 0, 44);
178: putchar('\n');
179: }
180: if (rn = rnode.rn_dupedkey)
181: goto again;
182: } else {
183: p_tree(rnode.rn_l, do_rtent);
184: p_tree(rnode.rn_r, do_rtent);
185: }
186: }
187:
188: ntreestuff()
189: {
190: int needed;
191: char *buf, *next, *lim;
192: register struct rt_msghdr *rtm;
193:
194: if ((needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0)) < 0)
195: { perror("route-getkerninfo-estimate"); exit(1);}
196: if ((buf = malloc(needed)) == 0)
197: { printf("out of space\n"); exit(1);}
198: if (getkerninfo(KINFO_RT_DUMP, buf, &needed, 0) < 0)
199: { perror("actual retrieval of routing table"); exit(1);}
200: lim = buf + needed;
201: for (next = buf; next < lim; next += rtm->rtm_msglen) {
202: rtm = (struct rt_msghdr *)next;
203: np_rtentry(rtm);
204: }
205: }
206:
207: np_rtentry(rtm)
208: register struct rt_msghdr *rtm;
209: {
210: register struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
211: static int masks_done, old_af, banner_printed;
212: int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST;
213:
214: #ifdef notdef
215: /* for the moment, netmasks are skipped over */
216: if (!banner_printed) {
217: printf("Netmasks:\n");
218: banner_printed = 1;
219: }
220: if (masks_done == 0) {
221: if (rtm->rtm_addrs != RTA_DST ) {
222: masks_done = 1;
223: af = sa->sa_family;
224: }
225: } else
226: #endif
227: af = sa->sa_family;
228: if (af != old_af) {
229: printf("\nRoute Tree for Protocol Family %d:\n", af);
230: old_af = af;
231: }
232: if (rtm->rtm_addrs == RTA_DST)
233: p_sockaddr(sa, 0, 36);
234: else {
235: p_sockaddr(sa, rtm->rtm_flags, 16);
236: if (sa->sa_len == 0)
237: sa->sa_len = sizeof(long);
238: sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
239: p_sockaddr(sa, 0, 18);
240: }
241: p_flags(rtm->rtm_flags & interesting, "%-6.6s ");
242: putchar('\n');
243: }
244:
245: p_sockaddr(sa, flags, width)
246: struct sockaddr *sa;
247: int flags, width;
248: {
249: char format[20], workbuf[128], *cp, *cplim;
250: register char *cpout;
251:
252: switch(sa->sa_family) {
253: case AF_INET:
254: {
255: register struct sockaddr_in *sin = (struct sockaddr_in *)sa;
256:
257: cp = (sin->sin_addr.s_addr == 0) ? "default" :
258: ((flags & RTF_HOST) ?
259: routename(sin->sin_addr) : netname(sin->sin_addr, 0L));
260: }
261: break;
262:
263: case AF_NS:
264: cp = ns_print((struct sockaddr_ns *)sa);
265: break;
266:
267: default:
268: {
269: register u_short *s = ((u_short *)sa->sa_data),
270: *slim = ((sa->sa_len + 1)/2) + s;
271:
272: cp = workbuf;
273: cplim = cp + sizeof(workbuf) - 6;
274: cp += sprintf(cp, "(%d)", sa->sa_family);
275: while (s < slim && cp < cplim)
276: cp += sprintf(cp, "%x ", *s++);
277: cp = workbuf;
278: }
279: }
280: if (nflag)
281: printf("%-*s ", width, cp);
282: else
283: printf("%-*.*s ", width, width, cp);
284: }
285:
286: p_flags(f, format)
287: register int f;
288: char *format;
289: {
290: char name[33], *flags;
291: register struct bits *p = bits;
292: for (flags = name; p->b_mask; p++)
293: if (p->b_mask & f)
294: *flags++ = p->b_val;
295: *flags = '\0';
296: printf(format, name);
297: }
298:
299: p_rtentry(rt)
300: register struct rtentry *rt;
301: {
302: char name[16];
303: register struct sockaddr *sa;
304: struct ifnet ifnet;
305:
306: p_sockaddr(kgetsa(rt_key(rt)), rt->rt_flags, 16);
307: p_sockaddr(kgetsa(rt->rt_gateway), 0, 18);
308: p_flags(rt->rt_flags, "%-6.6s ");
309: printf("%6d %8d ", rt->rt_refcnt, rt->rt_use);
310: if (rt->rt_ifp == 0) {
311: putchar('\n');
312: return;
313: }
314: kget(rt->rt_ifp, ifnet);
315: kvm_read((off_t)ifnet.if_name, name, 16);
316: printf(" %.15s%d\n", name, ifnet.if_unit);
317: }
318:
319: p_ortentry(rt)
320: register struct ortentry *rt;
321: {
322: char name[16], *flags;
323: register struct bits *p;
324: register struct sockaddr_in *sin;
325: struct ifnet ifnet;
326:
327: p_sockaddr(&rt->rt_dst, rt->rt_flags, 16);
328: p_sockaddr(&rt->rt_gateway, 0, 18);
329: p_flags(rt->rt_flags, "%-6.6s ");
330: printf("%6d %8d ", rt->rt_refcnt, rt->rt_use);
331: if (rt->rt_ifp == 0) {
332: putchar('\n');
333: return;
334: }
335: kget(rt->rt_ifp, ifnet);
336: kvm_read((off_t)ifnet.if_name, name, 16);
337: printf(" %.15s%d\n", name, ifnet.if_unit);
338: }
339:
340: char *
341: routename(in)
342: struct in_addr in;
343: {
344: register char *cp;
345: static char line[MAXHOSTNAMELEN + 1];
346: struct hostent *hp;
347: static char domain[MAXHOSTNAMELEN + 1];
348: static int first = 1;
349: char *index();
350:
351: if (first) {
352: first = 0;
353: if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
354: (cp = index(domain, '.')))
355: (void) strcpy(domain, cp + 1);
356: else
357: domain[0] = 0;
358: }
359: cp = 0;
360: if (!nflag) {
361: hp = gethostbyaddr((char *)&in, sizeof (struct in_addr),
362: AF_INET);
363: if (hp) {
364: if ((cp = index(hp->h_name, '.')) &&
365: !strcmp(cp + 1, domain))
366: *cp = 0;
367: cp = hp->h_name;
368: }
369: }
370: if (cp)
371: strncpy(line, cp, sizeof(line) - 1);
372: else {
373: #define C(x) ((x) & 0xff)
374: in.s_addr = ntohl(in.s_addr);
375: sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
376: C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
377: }
378: return (line);
379: }
380:
381: /*
382: * Return the name of the network whose address is given.
383: * The address is assumed to be that of a net or subnet, not a host.
384: */
385: char *
386: netname(in, mask)
387: struct in_addr in;
388: u_long mask;
389: {
390: char *cp = 0;
391: static char line[MAXHOSTNAMELEN + 1];
392: struct netent *np = 0;
393: u_long net;
394: register i;
395: int subnetshift;
396:
397: i = ntohl(in.s_addr);
398: if (!nflag && i) {
399: if (mask == 0) {
400: if (IN_CLASSA(i)) {
401: mask = IN_CLASSA_NET;
402: subnetshift = 8;
403: } else if (IN_CLASSB(i)) {
404: mask = IN_CLASSB_NET;
405: subnetshift = 8;
406: } else {
407: mask = IN_CLASSC_NET;
408: subnetshift = 4;
409: }
410: /*
411: * If there are more bits than the standard mask
412: * would suggest, subnets must be in use.
413: * Guess at the subnet mask, assuming reasonable
414: * width subnet fields.
415: */
416: while (i &~ mask)
417: mask = (long)mask >> subnetshift;
418: }
419: net = i & mask;
420: while ((mask & 1) == 0)
421: mask >>= 1, net >>= 1;
422: np = getnetbyaddr(net, AF_INET);
423: if (np)
424: cp = np->n_name;
425: }
426: if (cp)
427: strncpy(line, cp, sizeof(line) - 1);
428: else if ((i & 0xffffff) == 0)
429: sprintf(line, "%u", C(i >> 24));
430: else if ((i & 0xffff) == 0)
431: sprintf(line, "%u.%u", C(i >> 24) , C(i >> 16));
432: else if ((i & 0xff) == 0)
433: sprintf(line, "%u.%u.%u", C(i >> 24), C(i >> 16), C(i >> 8));
434: else
435: sprintf(line, "%u.%u.%u.%u", C(i >> 24),
436: C(i >> 16), C(i >> 8), C(i));
437: return (line);
438: }
439:
440: /*
441: * Print routing statistics
442: */
443: rt_stats(off)
444: off_t off;
445: {
446: struct rtstat rtstat;
447:
448: if (off == 0) {
449: printf("rtstat: symbol not in namelist\n");
450: return;
451: }
452: kvm_read(off, (char *)&rtstat, sizeof (rtstat));
453: printf("routing:\n");
454: printf("\t%u bad routing redirect%s\n",
455: rtstat.rts_badredirect, plural(rtstat.rts_badredirect));
456: printf("\t%u dynamically created route%s\n",
457: rtstat.rts_dynamic, plural(rtstat.rts_dynamic));
458: printf("\t%u new gateway%s due to redirects\n",
459: rtstat.rts_newgateway, plural(rtstat.rts_newgateway));
460: printf("\t%u destination%s found unreachable\n",
461: rtstat.rts_unreach, plural(rtstat.rts_unreach));
462: printf("\t%u use%s of a wildcard route\n",
463: rtstat.rts_wildcard, plural(rtstat.rts_wildcard));
464: }
465: short ns_nullh[] = {0,0,0};
466: short ns_bh[] = {-1,-1,-1};
467:
468: char *
469: ns_print(sns)
470: struct sockaddr_ns *sns;
471: {
472: struct ns_addr work;
473: union { union ns_net net_e; u_long long_e; } net;
474: u_short port;
475: static char mybuf[50], cport[10], chost[25];
476: char *host = "";
477: register char *p; register u_char *q;
478:
479: work = sns->sns_addr;
480: port = ntohs(work.x_port);
481: work.x_port = 0;
482: net.net_e = work.x_net;
483: if (ns_nullhost(work) && net.long_e == 0) {
484: if (port ) {
485: sprintf(mybuf, "*.%xH", port);
486: upHex(mybuf);
487: } else
488: sprintf(mybuf, "*.*");
489: return (mybuf);
490: }
491:
492: if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) {
493: host = "any";
494: } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) {
495: host = "*";
496: } else {
497: q = work.x_host.c_host;
498: sprintf(chost, "%02x%02x%02x%02x%02x%02xH",
499: q[0], q[1], q[2], q[3], q[4], q[5]);
500: for (p = chost; *p == '0' && p < chost + 12; p++);
501: host = p;
502: }
503: if (port)
504: sprintf(cport, ".%xH", htons(port));
505: else
506: *cport = 0;
507:
508: sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport);
509: upHex(mybuf);
510: return(mybuf);
511: }
512:
513: char *
514: ns_phost(sns)
515: struct sockaddr_ns *sns;
516: {
517: struct sockaddr_ns work;
518: static union ns_net ns_zeronet;
519: char *p;
520:
521: work = *sns;
522: work.sns_addr.x_port = 0;
523: work.sns_addr.x_net = ns_zeronet;
524:
525: p = ns_print(&work);
526: if (strncmp("0H.", p, 3) == 0) p += 3;
527: return(p);
528: }
529: upHex(p0)
530: char *p0;
531: {
532: register char *p = p0;
533: for (; *p; p++) switch (*p) {
534:
535: case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
536: *p += ('A' - 'a');
537: }
538: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.