Annotation of src/usr.bin/netstat/route.c, Revision 1.29
1.29 ! deraadt 1: /* $OpenBSD: route.c,v 1.28 1999/06/26 21:21:46 ho Exp $ */
1.2 deraadt 2: /* $NetBSD: route.c,v 1.15 1996/05/07 02:55:06 thorpej Exp $ */
1.1 deraadt 3:
4: /*
5: * Copyright (c) 1983, 1988, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
38: #if 0
39: static char sccsid[] = "from: @(#)route.c 8.3 (Berkeley) 3/9/94";
40: #else
1.29 ! deraadt 41: static char *rcsid = "$OpenBSD: route.c,v 1.28 1999/06/26 21:21:46 ho Exp $";
1.1 deraadt 42: #endif
43: #endif /* not lint */
44:
45: #include <sys/param.h>
46: #include <sys/protosw.h>
47: #include <sys/socket.h>
48: #include <sys/mbuf.h>
49:
50: #include <net/if.h>
51: #include <net/if_dl.h>
52: #include <net/if_types.h>
53: #define _KERNEL
54: #include <net/route.h>
55: #undef _KERNEL
56: #include <netinet/in.h>
1.13 millert 57: #include <arpa/inet.h>
1.1 deraadt 58:
59: #include <netns/ns.h>
60:
1.5 mickey 61: #include <netipx/ipx.h>
62:
1.18 denny 63: #include <netatalk/at.h>
64:
1.1 deraadt 65: #include <sys/sysctl.h>
66:
1.15 millert 67: #include <limits.h>
1.1 deraadt 68: #include <netdb.h>
69: #include <stdio.h>
70: #include <stdlib.h>
71: #include <string.h>
72: #include <unistd.h>
1.9 angelos 73:
74: #ifndef INET
75: #define INET
76: #endif
77:
1.26 angelos 78: #include <sys/socket.h>
79: #include <netinet/ip_ipsp.h>
1.1 deraadt 80: #include "netstat.h"
81:
82: #define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d)))
83:
1.29 ! deraadt 84: /* alignment constraint for routing socket */
! 85: #define ROUNDUP(a) \
! 86: ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
! 87: #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
! 88:
1.1 deraadt 89: /*
90: * Definitions for showing gateway flags.
91: */
92: struct bits {
93: short b_mask;
94: char b_val;
95: } bits[] = {
96: { RTF_UP, 'U' },
97: { RTF_GATEWAY, 'G' },
98: { RTF_HOST, 'H' },
99: { RTF_REJECT, 'R' },
100: { RTF_DYNAMIC, 'D' },
101: { RTF_MODIFIED, 'M' },
102: { RTF_DONE, 'd' }, /* Completed -- for routing messages only */
103: { RTF_MASK, 'm' }, /* Mask Present -- for routing messages only */
104: { RTF_CLONING, 'C' },
105: { RTF_XRESOLVE, 'X' },
106: { RTF_LLINFO, 'L' },
107: { RTF_STATIC, 'S' },
108: { RTF_PROTO1, '1' },
109: { RTF_PROTO2, '2' },
110: { 0 }
111: };
112:
113: static union {
1.6 deraadt 114: struct sockaddr u_sa;
115: u_int32_t u_data[64];
1.29 ! deraadt 116: int u_dummy; /* force word-alignment */
1.1 deraadt 117: } pt_u;
118:
119: int do_rtent = 0;
120: struct rtentry rtentry;
121: struct radix_node rnode;
122: struct radix_mask rmask;
123:
124: int NewTree = 0;
125:
126: static struct sockaddr *kgetsa __P((struct sockaddr *));
127: static void p_tree __P((struct radix_node *));
128: static void p_rtnode __P(());
129: static void ntreestuff __P(());
130: static void np_rtentry __P((struct rt_msghdr *));
1.21 peter 131: static void p_sockaddr __P((struct sockaddr *, struct sockaddr *, int, int));
1.1 deraadt 132: static void p_flags __P((int, char *));
133: static void p_rtentry __P((struct rtentry *));
1.9 angelos 134: static void encap_print __P((struct rtentry *));
1.1 deraadt 135:
136: /*
137: * Print routing tables.
138: */
139: void
140: routepr(rtree)
141: u_long rtree;
142: {
143: struct radix_node_head *rnh, head;
144: int i;
145:
146: printf("Routing tables\n");
147:
148: if (Aflag == 0 && NewTree)
149: ntreestuff();
150: else {
151: if (rtree == 0) {
152: printf("rt_tables: symbol not in namelist\n");
153: return;
154: }
155:
156: kget(rtree, rt_tables);
157: for (i = 0; i <= AF_MAX; i++) {
158: if ((rnh = rt_tables[i]) == 0)
159: continue;
160: kget(rnh, head);
161: if (i == AF_UNSPEC) {
162: if (Aflag && af == 0) {
163: printf("Netmasks:\n");
164: p_tree(head.rnh_treetop);
165: }
166: } else if (af == AF_UNSPEC || af == i) {
167: pr_family(i);
168: do_rtent = 1;
1.26 angelos 169: if (i != PF_KEY)
1.10 deraadt 170: pr_rthdr();
1.9 angelos 171: else
1.10 deraadt 172: pr_encaphdr();
1.1 deraadt 173: p_tree(head.rnh_treetop);
174: }
175: }
176: }
177: }
178:
179: /*
180: * Print address family header before a section of the routing table.
181: */
182: void
183: pr_family(af)
184: int af;
185: {
186: char *afname;
187:
188: switch (af) {
189: case AF_INET:
190: afname = "Internet";
191: break;
192: case AF_NS:
193: afname = "XNS";
194: break;
1.5 mickey 195: case AF_IPX:
196: afname = "IPX";
197: break;
1.1 deraadt 198: case AF_ISO:
199: afname = "ISO";
200: break;
201: case AF_CCITT:
202: afname = "X.25";
203: break;
1.26 angelos 204: case PF_KEY:
1.10 deraadt 205: afname = "Encap";
1.9 angelos 206: break;
1.18 denny 207: case AF_APPLETALK:
208: afname = "AppleTalk";
209: break;
1.1 deraadt 210: default:
211: afname = NULL;
212: break;
213: }
214: if (afname)
215: printf("\n%s:\n", afname);
216: else
217: printf("\nProtocol Family %d:\n", af);
218: }
219:
220: /* column widths; each followed by one space */
1.19 mickey 221: #define WID_DST 18 /* width of destination column */
1.1 deraadt 222: #define WID_GW 18 /* width of gateway column */
223:
224: /*
225: * Print header for routing table columns.
226: */
227: void
228: pr_rthdr()
229: {
230:
231: if (Aflag)
1.15 millert 232: printf("%-*.*s ", PLEN, PLEN, "Address");
1.20 kstailey 233: printf("%-*.*s %-*.*s %-6.6s %6.6s %6.6s %6.6s %s\n",
1.1 deraadt 234: WID_DST, WID_DST, "Destination",
235: WID_GW, WID_GW, "Gateway",
236: "Flags", "Refs", "Use", "Mtu", "Interface");
237: }
238:
1.9 angelos 239: /*
1.26 angelos 240: * Print header for PF_KEY entries.
1.9 angelos 241: */
242: void
243: pr_encaphdr()
244: {
1.10 deraadt 245: if (Aflag)
1.15 millert 246: printf("%-*s ", PLEN, "Address");
1.28 ho 247: printf("%-18s %-5s %-18s %-5s %-5s %-22s\n",
248: "Source", "Port", "Destination",
1.16 angelos 249: "Port", "Proto", "SA(Address/SPI/Proto)");
1.9 angelos 250: }
251:
1.1 deraadt 252: static struct sockaddr *
253: kgetsa(dst)
254: register struct sockaddr *dst;
255: {
256:
257: kget(dst, pt_u.u_sa);
258: if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa))
259: kread((u_long)dst, (char *)pt_u.u_data, pt_u.u_sa.sa_len);
260: return (&pt_u.u_sa);
261: }
262:
263: static void
264: p_tree(rn)
265: struct radix_node *rn;
266: {
267:
268: again:
269: kget(rn, rnode);
270: if (rnode.rn_b < 0) {
271: if (Aflag)
1.14 millert 272: printf("%-16p ", rn);
1.1 deraadt 273: if (rnode.rn_flags & RNF_ROOT) {
274: if (Aflag)
275: printf("(root node)%s",
276: rnode.rn_dupedkey ? " =>\n" : "\n");
277: } else if (do_rtent) {
278: kget(rn, rtentry);
279: p_rtentry(&rtentry);
280: if (Aflag)
281: p_rtnode();
282: } else {
283: p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key),
1.21 peter 284: 0, 0, 44);
1.1 deraadt 285: putchar('\n');
286: }
1.13 millert 287: if ((rn = rnode.rn_dupedkey))
1.1 deraadt 288: goto again;
289: } else {
290: if (Aflag && do_rtent) {
1.14 millert 291: printf("%-16p ", rn);
1.1 deraadt 292: p_rtnode();
293: }
294: rn = rnode.rn_r;
295: p_tree(rnode.rn_l);
296: p_tree(rn);
297: }
298: }
299:
1.23 deraadt 300: char nbuf[25];
1.1 deraadt 301:
302: static void
303: p_rtnode()
304: {
305: struct radix_mask *rm = rnode.rn_mklist;
306:
307: if (rnode.rn_b < 0) {
308: if (rnode.rn_mask) {
309: printf("\t mask ");
310: p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask),
1.21 peter 311: 0, 0, -1);
1.1 deraadt 312: } else if (rm == 0)
313: return;
314: } else {
1.23 deraadt 315: snprintf(nbuf, sizeof nbuf, "(%d)", rnode.rn_b);
1.14 millert 316: printf("%6.6s %16p : %16p", nbuf, rnode.rn_l,
317: rnode.rn_r);
1.1 deraadt 318: }
319: while (rm) {
320: kget(rm, rmask);
1.23 deraadt 321: snprintf(nbuf, sizeof nbuf, " %d refs, ", rmask.rm_refs);
1.14 millert 322: printf(" mk = %16p {(%d),%s",
1.1 deraadt 323: rm, -1 - rmask.rm_b, rmask.rm_refs ? nbuf : " ");
1.21 peter 324: p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask), 0, 0, -1);
1.1 deraadt 325: putchar('}');
1.13 millert 326: if ((rm = rmask.rm_mklist))
1.1 deraadt 327: printf(" ->");
328: }
329: putchar('\n');
330: }
331:
332: static void
333: ntreestuff()
334: {
335: size_t needed;
336: int mib[6];
337: char *buf, *next, *lim;
338: register struct rt_msghdr *rtm;
339:
1.10 deraadt 340: mib[0] = CTL_NET;
341: mib[1] = PF_ROUTE;
342: mib[2] = 0;
343: mib[3] = 0;
344: mib[4] = NET_RT_DUMP;
345: mib[5] = 0;
346: if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
347: perror("route-sysctl-estimate");
348: exit(1);
349: }
350: if ((buf = malloc(needed)) == 0) {
351: printf("out of space\n");
352: exit(1);
353: }
354: if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
355: perror("sysctl of routing table");
356: exit(1);
357: }
358: lim = buf + needed;
1.1 deraadt 359: for (next = buf; next < lim; next += rtm->rtm_msglen) {
360: rtm = (struct rt_msghdr *)next;
361: np_rtentry(rtm);
362: }
363: }
364:
365: static void
366: np_rtentry(rtm)
367: register struct rt_msghdr *rtm;
368: {
369: register struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
370: #ifdef notdef
371: static int masks_done, banner_printed;
372: #endif
373: static int old_af;
374: int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST;
375:
376: #ifdef notdef
377: /* for the moment, netmasks are skipped over */
378: if (!banner_printed) {
379: printf("Netmasks:\n");
380: banner_printed = 1;
381: }
382: if (masks_done == 0) {
383: if (rtm->rtm_addrs != RTA_DST ) {
384: masks_done = 1;
385: af = sa->sa_family;
386: }
387: } else
388: #endif
389: af = sa->sa_family;
390: if (af != old_af) {
391: pr_family(af);
392: old_af = af;
393: }
394: if (rtm->rtm_addrs == RTA_DST)
1.21 peter 395: p_sockaddr(sa, 0, 0, 36);
1.1 deraadt 396: else {
1.21 peter 397: p_sockaddr(sa, 0, rtm->rtm_flags, 16);
1.29 ! deraadt 398: sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
1.21 peter 399: p_sockaddr(sa, 0, 0, 18);
1.1 deraadt 400: }
401: p_flags(rtm->rtm_flags & interesting, "%-6.6s ");
402: putchar('\n');
403: }
404:
405: static void
1.21 peter 406: p_sockaddr(sa, mask, flags, width)
407: struct sockaddr *sa, *mask;
1.1 deraadt 408: int flags, width;
409: {
410: char workbuf[128], *cplim;
411: register char *cp = workbuf;
1.25 millert 412: size_t n;
1.1 deraadt 413:
414: switch(sa->sa_family) {
415: case AF_INET:
416: {
417: register struct sockaddr_in *sin = (struct sockaddr_in *)sa;
1.21 peter 418: register struct sockaddr_in *msin = (struct sockaddr_in *)mask;
1.1 deraadt 419:
420: cp = (sin->sin_addr.s_addr == 0) ? "default" :
421: ((flags & RTF_HOST) ?
422: routename(sin->sin_addr.s_addr) :
1.21 peter 423: netname(sin->sin_addr.s_addr, msin->sin_addr.s_addr));
424:
1.1 deraadt 425: break;
426: }
427:
428: case AF_NS:
429: cp = ns_print(sa);
430: break;
431:
1.5 mickey 432: case AF_IPX:
433: cp = ipx_print(sa);
434: break;
1.9 angelos 435:
1.1 deraadt 436: case AF_LINK:
437: {
438: register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
439:
440: if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 &&
441: sdl->sdl_slen == 0)
1.23 deraadt 442: (void) snprintf(workbuf, sizeof workbuf,
443: "link#%d", sdl->sdl_index);
1.1 deraadt 444: else switch (sdl->sdl_type) {
445: case IFT_ETHER:
446: {
447: register int i;
448: register u_char *lla = (u_char *)sdl->sdl_data +
449: sdl->sdl_nlen;
450:
451: cplim = "";
452: for (i = 0; i < sdl->sdl_alen; i++, lla++) {
1.25 millert 453: n = snprintf(cp,
1.4 deraadt 454: workbuf + sizeof (workbuf) - cp,
455: "%s%x", cplim, *lla);
1.25 millert 456: if (n >= workbuf + sizeof (workbuf) - cp)
457: n = workbuf + sizeof (workbuf) - cp - 1;
458: cp += n;
1.1 deraadt 459: cplim = ":";
460: }
461: cp = workbuf;
462: break;
463: }
464: default:
465: cp = link_ntoa(sdl);
466: break;
467: }
468: break;
469: }
470:
1.18 denny 471: case AF_APPLETALK:
472: {
473: /* XXX could do better */
474: cp = atalk_print(sa,11);
475: break;
476: }
1.1 deraadt 477: default:
478: {
479: register u_char *s = (u_char *)sa->sa_data, *slim;
480:
1.10 deraadt 481: slim = sa->sa_len + (u_char *) sa;
1.1 deraadt 482: cplim = cp + sizeof(workbuf) - 6;
1.25 millert 483: n = snprintf(cp, cplim - cp, "(%d)", sa->sa_family);
484: if (n >= cplim - cp)
485: n = cplim - cp - 1;
486: cp += n;
1.1 deraadt 487: while (s < slim && cp < cplim) {
1.25 millert 488: n = snprintf(cp, workbuf + sizeof (workbuf) - cp,
1.4 deraadt 489: " %02x", *s++);
1.25 millert 490: if (n >= workbuf + sizeof (workbuf) - cp)
491: n = workbuf + sizeof (workbuf) - cp - 1;
492: cp += n;
493: if (s < slim) {
494: n = snprintf(cp,
1.4 deraadt 495: workbuf + sizeof (workbuf) - cp,
496: "%02x", *s++);
1.25 millert 497: if (n >= workbuf + sizeof (workbuf) - cp)
498: n = workbuf + sizeof (workbuf) - cp - 1;
499: cp += n;
500: }
1.1 deraadt 501: }
502: cp = workbuf;
503: }
504: }
505: if (width < 0 )
506: printf("%s ", cp);
507: else {
508: if (nflag)
509: printf("%-*s ", width, cp);
510: else
511: printf("%-*.*s ", width, width, cp);
512: }
513: }
514:
515: static void
516: p_flags(f, format)
517: register int f;
518: char *format;
519: {
520: char name[33], *flags;
521: register struct bits *p = bits;
522:
523: for (flags = name; p->b_mask; p++)
524: if (p->b_mask & f)
525: *flags++ = p->b_val;
526: *flags = '\0';
527: printf(format, name);
528: }
529:
530: static void
531: p_rtentry(rt)
532: register struct rtentry *rt;
533: {
534: static struct ifnet ifnet, *lastif;
1.21 peter 535: struct sockaddr sock1, sock2;
536: struct sockaddr *sa = &sock1, *mask = &sock2;
1.9 angelos 537:
1.21 peter 538: bcopy(kgetsa(rt_key(rt)), sa, sizeof(struct sockaddr));
539:
1.26 angelos 540: if (sa->sa_family == PF_KEY) {
1.10 deraadt 541: encap_print(rt);
542: return;
1.9 angelos 543: }
1.21 peter 544:
545: if (rt_mask(rt))
546: bcopy(kgetsa(rt_mask(rt)), mask, sizeof(struct sockaddr));
547: else
548: mask = 0;
1.9 angelos 549:
1.21 peter 550: p_sockaddr(sa, mask, rt->rt_flags, WID_DST);
551: p_sockaddr(kgetsa(rt->rt_gateway), 0, RTF_HOST, WID_GW);
1.1 deraadt 552: p_flags(rt->rt_flags, "%-6.6s ");
1.13 millert 553: printf("%6d %8ld ", rt->rt_refcnt, rt->rt_use);
1.1 deraadt 554: if (rt->rt_rmx.rmx_mtu)
1.13 millert 555: printf("%6ld ", rt->rt_rmx.rmx_mtu);
1.1 deraadt 556: else
557: printf("%6s ", "-");
558: if (rt->rt_ifp) {
559: if (rt->rt_ifp != lastif) {
560: kget(rt->rt_ifp, ifnet);
561: lastif = rt->rt_ifp;
562: }
1.2 deraadt 563: printf(" %.16s%s", ifnet.if_xname,
1.1 deraadt 564: rt->rt_nodes[0].rn_dupedkey ? " =>" : "");
565: }
566: putchar('\n');
567: }
568:
569: char *
570: routename(in)
1.13 millert 571: in_addr_t in;
1.1 deraadt 572: {
573: register char *cp;
1.24 deraadt 574: static char line[MAXHOSTNAMELEN];
1.1 deraadt 575: struct hostent *hp;
1.24 deraadt 576: static char domain[MAXHOSTNAMELEN];
1.1 deraadt 577: static int first = 1;
578:
579: if (first) {
580: first = 0;
1.24 deraadt 581: if (gethostname(domain, sizeof domain) == 0 &&
1.7 millert 582: (cp = strchr(domain, '.')))
1.1 deraadt 583: (void) strcpy(domain, cp + 1);
584: else
585: domain[0] = 0;
586: }
587: cp = 0;
588: if (!nflag) {
589: hp = gethostbyaddr((char *)&in, sizeof (struct in_addr),
590: AF_INET);
591: if (hp) {
1.7 millert 592: if ((cp = strchr(hp->h_name, '.')) &&
1.1 deraadt 593: !strcmp(cp + 1, domain))
594: *cp = 0;
595: cp = hp->h_name;
596: }
597: }
1.22 deraadt 598: if (cp) {
1.1 deraadt 599: strncpy(line, cp, sizeof(line) - 1);
1.22 deraadt 600: line[sizeof(line) - 1] = '\0';
601: } else {
1.1 deraadt 602: #define C(x) ((x) & 0xff)
603: in = ntohl(in);
1.23 deraadt 604: snprintf(line, sizeof line, "%u.%u.%u.%u",
1.1 deraadt 605: C(in >> 24), C(in >> 16), C(in >> 8), C(in));
606: }
607: return (line);
608: }
609:
610: /*
611: * Return the name of the network whose address is given.
612: * The address is assumed to be that of a net or subnet, not a host.
613: */
614: char *
615: netname(in, mask)
1.13 millert 616: in_addr_t in, mask;
1.1 deraadt 617: {
618: char *cp = 0;
1.24 deraadt 619: static char line[MAXHOSTNAMELEN];
1.1 deraadt 620: struct netent *np = 0;
1.13 millert 621: in_addr_t net, subnetshift;
1.21 peter 622: int mbits;
1.1 deraadt 623:
624: in = ntohl(in);
625: mask = ntohl(mask);
626: if (!nflag && in != INADDR_ANY) {
1.21 peter 627: if (np = getnetbyaddr(in, AF_INET))
1.1 deraadt 628: cp = np->n_name;
629: }
1.21 peter 630: mbits = mask ? 33 - ffs(mask) : 0;
1.22 deraadt 631: if (cp) {
1.1 deraadt 632: strncpy(line, cp, sizeof(line) - 1);
1.22 deraadt 633: line[sizeof(line) - 1] = '\0';
1.27 deraadt 634: } else if (mbits < 9)
1.23 deraadt 635: snprintf(line, sizeof line, "%u/%d", C(in >> 24), mbits);
1.27 deraadt 636: else if (mbits < 17)
1.23 deraadt 637: snprintf(line, sizeof line, "%u.%u/%d",
638: C(in >> 24) , C(in >> 16), mbits);
1.27 deraadt 639: else if (mbits < 25)
1.23 deraadt 640: snprintf(line, sizeof line, "%u.%u.%u/%d",
641: C(in >> 24), C(in >> 16), C(in >> 8), mbits);
1.1 deraadt 642: else
1.23 deraadt 643: snprintf(line, sizeof line, "%u.%u.%u.%u/%d", C(in >> 24),
1.21 peter 644: C(in >> 16), C(in >> 8), C(in), mbits);
1.1 deraadt 645: return (line);
646: }
647:
648: /*
649: * Print routing statistics
650: */
651: void
652: rt_stats(off)
653: u_long off;
654: {
655: struct rtstat rtstat;
656:
657: if (off == 0) {
658: printf("rtstat: symbol not in namelist\n");
659: return;
660: }
661: kread(off, (char *)&rtstat, sizeof (rtstat));
662: printf("routing:\n");
663: printf("\t%u bad routing redirect%s\n",
664: rtstat.rts_badredirect, plural(rtstat.rts_badredirect));
665: printf("\t%u dynamically created route%s\n",
666: rtstat.rts_dynamic, plural(rtstat.rts_dynamic));
667: printf("\t%u new gateway%s due to redirects\n",
668: rtstat.rts_newgateway, plural(rtstat.rts_newgateway));
669: printf("\t%u destination%s found unreachable\n",
670: rtstat.rts_unreach, plural(rtstat.rts_unreach));
671: printf("\t%u use%s of a wildcard route\n",
672: rtstat.rts_wildcard, plural(rtstat.rts_wildcard));
673: }
1.5 mickey 674:
1.1 deraadt 675: short ns_nullh[] = {0,0,0};
676: short ns_bh[] = {-1,-1,-1};
677:
678: char *
679: ns_print(sa)
680: register struct sockaddr *sa;
681: {
682: register struct sockaddr_ns *sns = (struct sockaddr_ns*)sa;
683: struct ns_addr work;
684: union { union ns_net net_e; u_long long_e; } net;
1.13 millert 685: in_port_t port;
1.1 deraadt 686: static char mybuf[50], cport[10], chost[25];
687: char *host = "";
688: register char *p; register u_char *q;
689:
690: work = sns->sns_addr;
691: port = ntohs(work.x_port);
692: work.x_port = 0;
1.10 deraadt 693: net.net_e = work.x_net;
1.1 deraadt 694: if (ns_nullhost(work) && net.long_e == 0) {
695: if (port ) {
1.23 deraadt 696: snprintf(mybuf, sizeof mybuf, "*.%xH", port);
1.1 deraadt 697: upHex(mybuf);
698: } else
1.23 deraadt 699: snprintf(mybuf, sizeof mybuf, "*.*");
1.1 deraadt 700: return (mybuf);
701: }
702:
703: if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) {
704: host = "any";
705: } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) {
706: host = "*";
707: } else {
708: q = work.x_host.c_host;
1.23 deraadt 709: snprintf(chost, sizeof chost, "%02x%02x%02x%02x%02x%02xH",
1.1 deraadt 710: q[0], q[1], q[2], q[3], q[4], q[5]);
711: for (p = chost; *p == '0' && p < chost + 12; p++)
712: continue;
713: host = p;
714: }
715: if (port)
1.23 deraadt 716: snprintf(cport, sizeof cport, ".%xH", htons(port));
1.1 deraadt 717: else
718: *cport = 0;
719:
1.23 deraadt 720: snprintf(mybuf, sizeof mybuf, "%xH.%s%s", ntohl(net.long_e),
721: host, cport);
1.1 deraadt 722: upHex(mybuf);
723: return(mybuf);
724: }
725:
726: char *
727: ns_phost(sa)
728: struct sockaddr *sa;
729: {
730: register struct sockaddr_ns *sns = (struct sockaddr_ns *)sa;
731: struct sockaddr_ns work;
732: static union ns_net ns_zeronet;
733: char *p;
734:
735: work = *sns;
736: work.sns_addr.x_port = 0;
737: work.sns_addr.x_net = ns_zeronet;
738:
739: p = ns_print((struct sockaddr *)&work);
1.5 mickey 740: if (strncmp("0H.", p, 3) == 0) p += 3;
741: return(p);
742: }
743:
744: u_short ipx_nullh[] = {0,0,0};
745: u_short ipx_bh[] = {0xffff,0xffff,0xffff};
746:
747: char *
748: ipx_print(sa)
749: register struct sockaddr *sa;
750: {
751: register struct sockaddr_ipx *sipx = (struct sockaddr_ipx*)sa;
752: struct ipx_addr work;
753: union { union ipx_net net_e; u_long long_e; } net;
1.13 millert 754: in_port_t port;
1.5 mickey 755: static char mybuf[50], cport[10], chost[25];
756: char *host = "";
1.13 millert 757: register char *q;
1.5 mickey 758:
759: work = sipx->sipx_addr;
760: port = ntohs(work.ipx_port);
761: work.ipx_port = 0;
1.10 deraadt 762: net.net_e = work.ipx_net;
1.5 mickey 763: if (ipx_nullhost(work) && net.long_e == 0) {
764: if (port != 0) {
1.23 deraadt 765: snprintf(mybuf, sizeof mybuf, "*.%xH", port);
1.5 mickey 766: upHex(mybuf);
767: } else
1.23 deraadt 768: snprintf(mybuf, sizeof mybuf, "*.*");
1.5 mickey 769: return (mybuf);
770: }
771:
772: if (bcmp(ipx_bh, work.ipx_host.c_host, 6) == 0) {
773: host = "any";
774: } else if (bcmp(ipx_nullh, work.ipx_host.c_host, 6) == 0) {
775: host = "*";
776: } else {
777: q = work.ipx_host.c_host;
1.23 deraadt 778: snprintf(chost, sizeof chost, "%02x:%02x:%02x:%02x:%02x:%02x",
779: q[0], q[1], q[2], q[3], q[4], q[5]);
1.5 mickey 780: host = chost;
781: }
782: if (port)
1.23 deraadt 783: snprintf(cport, sizeof cport, ".%xH", htons(port));
1.5 mickey 784: else
785: *cport = 0;
786:
1.23 deraadt 787: snprintf(mybuf, sizeof mybuf, "%xH.%s%s", ntohl(net.long_e),
788: host, cport);
1.5 mickey 789: upHex(mybuf);
790: return(mybuf);
791: }
792:
793: char *
794: ipx_phost(sa)
795: struct sockaddr *sa;
796: {
797: register struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)sa;
798: struct sockaddr_ipx work;
799: static union ipx_net ipx_zeronet;
800: char *p;
801:
802: work = *sipx;
803: work.sipx_addr.ipx_port = 0;
804: work.sipx_addr.ipx_net = ipx_zeronet;
805:
806: p = ipx_print((struct sockaddr *)&work);
1.1 deraadt 807: if (strncmp("0H.", p, 3) == 0) p += 3;
808: return(p);
1.9 angelos 809: }
810:
811: static void
812: encap_print(rt)
813: register struct rtentry *rt;
814: {
1.10 deraadt 815: struct sockaddr_encap sen1, sen2, sen3;
1.9 angelos 816:
817: bcopy(kgetsa(rt_key(rt)), &sen1, sizeof(sen1));
818: bcopy(kgetsa(rt_mask(rt)), &sen2, sizeof(sen2));
819: bcopy(kgetsa(rt->rt_gateway), &sen3, sizeof(sen3));
820:
1.28 ho 821: printf("%-18s %-5u ", netname(sen1.sen_ip_src.s_addr,
822: sen2.sen_ip_src.s_addr),
823: sen1.sen_sport);
824:
825: printf("%-18s %-5u %-5u ", netname(sen1.sen_ip_dst.s_addr,
826: sen2.sen_ip_dst.s_addr),
827: sen1.sen_dport, sen1.sen_proto);
828:
1.16 angelos 829: printf("%s/%08x/%-lu\n", inet_ntoa(sen3.sen_ipsp_dst),
830: ntohl(sen3.sen_ipsp_spi), sen3.sen_ipsp_sproto);
1.1 deraadt 831: }
832:
833: void
834: upHex(p0)
835: char *p0;
836: {
837: register char *p = p0;
838: for (; *p; p++) switch (*p) {
839:
840: case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
841: *p += ('A' - 'a');
842: }
843: }