121990Sdist /*
262145Sbostic * Copyright (c) 1983, 1988, 1993
362145Sbostic * The Regents of the University of California. All rights reserved.
433451Skarels *
542945Ssklower * %sccs.include.redist.c%
621990Sdist */
721990Sdist
87909Ssam #ifndef lint
9*69077Ssklower static char sccsid[] = "@(#)route.c 8.6 (Berkeley) 04/28/95";
1034902Sbostic #endif /* not lint */
117909Ssam
1224914Skarels #include <sys/param.h>
1353698Ssklower #include <sys/protosw.h>
147909Ssam #include <sys/socket.h>
157909Ssam #include <sys/mbuf.h>
169205Ssam
177909Ssam #include <net/if.h>
1850682Skarels #include <net/if_dl.h>
1950682Skarels #include <net/if_types.h>
2036308Skarels #define KERNEL
217909Ssam #include <net/route.h>
2236308Skarels #undef KERNEL
239205Ssam #include <netinet/in.h>
249205Ssam
2523499Ssklower #include <netns/ns.h>
2623499Ssklower
2758931Smckusick #include <sys/sysctl.h>
287909Ssam
2953698Ssklower #include <netdb.h>
3042945Ssklower #include <stdio.h>
3153698Ssklower #include <stdlib.h>
3242945Ssklower #include <string.h>
3354721Ssklower #include <unistd.h>
3453698Ssklower #include "netstat.h"
3542945Ssklower
3654761Ssklower #define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d)))
377909Ssam
387909Ssam /*
397909Ssam * Definitions for showing gateway flags.
407909Ssam */
417909Ssam struct bits {
427909Ssam short b_mask;
437909Ssam char b_val;
447909Ssam } bits[] = {
457909Ssam { RTF_UP, 'U' },
467909Ssam { RTF_GATEWAY, 'G' },
477909Ssam { RTF_HOST, 'H' },
4854721Ssklower { RTF_REJECT, 'R' },
4924914Skarels { RTF_DYNAMIC, 'D' },
5030452Skarels { RTF_MODIFIED, 'M' },
5154721Ssklower { RTF_DONE, 'd' }, /* Completed -- for routing messages only */
5254721Ssklower { RTF_MASK, 'm' }, /* Mask Present -- for routing messages only */
5343248Ssklower { RTF_CLONING, 'C' },
5445664Ssklower { RTF_XRESOLVE, 'X' },
5543248Ssklower { RTF_LLINFO, 'L' },
5650883Ssklower { RTF_STATIC, 'S' },
5754721Ssklower { RTF_PROTO1, '1' },
5854721Ssklower { RTF_PROTO2, '2' },
597909Ssam { 0 }
607909Ssam };
617909Ssam
6250682Skarels static union {
6350682Skarels struct sockaddr u_sa;
6450682Skarels u_short u_data[128];
6550682Skarels } pt_u;
6650682Skarels
6750682Skarels int do_rtent = 0;
6850682Skarels struct rtentry rtentry;
6950682Skarels struct radix_node rnode;
7050682Skarels struct radix_mask rmask;
7150682Skarels
7250682Skarels int NewTree = 0;
7350682Skarels
7453698Ssklower static struct sockaddr *kgetsa __P((struct sockaddr *));
7553698Ssklower static void p_tree __P((struct radix_node *));
7653698Ssklower static void p_rtnode __P(());
7753698Ssklower static void ntreestuff __P(());
7853698Ssklower static void np_rtentry __P((struct rt_msghdr *));
79*69077Ssklower static void p_sockaddr __P((struct sockaddr *, struct sockaddr *, int, int));
8053698Ssklower static void p_flags __P((int, char *));
8153698Ssklower static void p_rtentry __P((struct rtentry *));
8253698Ssklower
837909Ssam /*
847909Ssam * Print routing tables.
857909Ssam */
8653698Ssklower void
routepr(rtree)8750682Skarels routepr(rtree)
8854761Ssklower u_long rtree;
897909Ssam {
9050682Skarels struct radix_node_head *rnh, head;
9150883Ssklower int i;
927909Ssam
9336308Skarels printf("Routing tables\n");
9450682Skarels
9550682Skarels if (Aflag == 0 && NewTree)
9650682Skarels ntreestuff();
9750682Skarels else {
9850682Skarels if (rtree == 0) {
9950883Ssklower printf("rt_tables: symbol not in namelist\n");
10050682Skarels return;
1017909Ssam }
10250682Skarels
10350883Ssklower kget(rtree, rt_tables);
10450883Ssklower for (i = 0; i <= AF_MAX; i++) {
10550883Ssklower if ((rnh = rt_tables[i]) == 0)
10650883Ssklower continue;
10750682Skarels kget(rnh, head);
10850883Ssklower if (i == AF_UNSPEC) {
10953698Ssklower if (Aflag && af == 0) {
11050682Skarels printf("Netmasks:\n");
11150682Skarels p_tree(head.rnh_treetop);
11250682Skarels }
11350883Ssklower } else if (af == AF_UNSPEC || af == i) {
11450883Ssklower pr_family(i);
11550682Skarels do_rtent = 1;
11650682Skarels pr_rthdr();
11750682Skarels p_tree(head.rnh_treetop);
11850682Skarels }
11950682Skarels }
1207909Ssam }
12150682Skarels }
12250682Skarels
12350682Skarels /*
12450682Skarels * Print address family header before a section of the routing table.
12550682Skarels */
12653698Ssklower void
pr_family(af)12750682Skarels pr_family(af)
12850682Skarels int af;
12950682Skarels {
13050682Skarels char *afname;
13150682Skarels
13250682Skarels switch (af) {
13350682Skarels case AF_INET:
13450682Skarels afname = "Internet";
13550682Skarels break;
13650682Skarels case AF_NS:
13750682Skarels afname = "XNS";
13850682Skarels break;
13950682Skarels case AF_ISO:
14050682Skarels afname = "ISO";
14150682Skarels break;
14250883Ssklower case AF_CCITT:
14350883Ssklower afname = "X.25";
14450883Ssklower break;
14550682Skarels default:
14650682Skarels afname = NULL;
14750682Skarels break;
1487909Ssam }
14950682Skarels if (afname)
15050682Skarels printf("\n%s:\n", afname);
15150682Skarels else
15250682Skarels printf("\nProtocol Family %d:\n", af);
1537909Ssam }
1547909Ssam
15550682Skarels /* column widths; each followed by one space */
15650682Skarels #define WID_DST 16 /* width of destination column */
15750682Skarels #define WID_GW 18 /* width of gateway column */
15836308Skarels
15950682Skarels /*
16050682Skarels * Print header for routing table columns.
16150682Skarels */
16253698Ssklower void
pr_rthdr()16350682Skarels pr_rthdr()
16436308Skarels {
16543248Ssklower
16650682Skarels if (Aflag)
16750682Skarels printf("%-8.8s ","Address");
16850682Skarels printf("%-*.*s %-*.*s %-6.6s %6.6s%8.8s %s\n",
16950682Skarels WID_DST, WID_DST, "Destination",
17050682Skarels WID_GW, WID_GW, "Gateway",
17150682Skarels "Flags", "Refs", "Use", "Interface");
17236308Skarels }
17336308Skarels
17453698Ssklower static struct sockaddr *
kgetsa(dst)17540837Ssklower kgetsa(dst)
17650682Skarels register struct sockaddr *dst;
17740837Ssklower {
17850682Skarels
17940837Ssklower kget(dst, pt_u.u_sa);
18050682Skarels if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa))
18154761Ssklower kread((u_long)dst, (char *)pt_u.u_data, pt_u.u_sa.sa_len);
18240837Ssklower return (&pt_u.u_sa);
18340837Ssklower }
18440837Ssklower
18553698Ssklower static void
p_tree(rn)18645664Ssklower p_tree(rn)
18750682Skarels struct radix_node *rn;
18836308Skarels {
18936308Skarels
19036308Skarels again:
19136308Skarels kget(rn, rnode);
19236308Skarels if (rnode.rn_b < 0) {
19345664Ssklower if (Aflag)
19445664Ssklower printf("%-8.8x ", rn);
19550682Skarels if (rnode.rn_flags & RNF_ROOT) {
19650682Skarels if (Aflag)
19750682Skarels printf("(root node)%s",
19845664Ssklower rnode.rn_dupedkey ? " =>\n" : "\n");
19950682Skarels } else if (do_rtent) {
20036308Skarels kget(rn, rtentry);
20136308Skarels p_rtentry(&rtentry);
20245664Ssklower if (Aflag)
20345664Ssklower p_rtnode();
20436308Skarels } else {
20540837Ssklower p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key),
206*69077Ssklower NULL, 0, 44);
20736308Skarels putchar('\n');
20836308Skarels }
20936308Skarels if (rn = rnode.rn_dupedkey)
21036308Skarels goto again;
21136308Skarels } else {
21245664Ssklower if (Aflag && do_rtent) {
21345664Ssklower printf("%-8.8x ", rn);
21445664Ssklower p_rtnode();
21545664Ssklower }
21645664Ssklower rn = rnode.rn_r;
21745664Ssklower p_tree(rnode.rn_l);
21845664Ssklower p_tree(rn);
21936308Skarels }
22036308Skarels }
22136308Skarels
22250682Skarels char nbuf[20];
22350682Skarels
22453698Ssklower static void
p_rtnode()22545664Ssklower p_rtnode()
22645664Ssklower {
22750682Skarels struct radix_mask *rm = rnode.rn_mklist;
22845664Ssklower
22945664Ssklower if (rnode.rn_b < 0) {
23045664Ssklower if (rnode.rn_mask) {
23145664Ssklower printf("\t mask ");
23245664Ssklower p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask),
233*69077Ssklower NULL, 0, -1);
23445664Ssklower } else if (rm == 0)
23545664Ssklower return;
23645664Ssklower } else {
23745664Ssklower sprintf(nbuf, "(%d)", rnode.rn_b);
23845664Ssklower printf("%6.6s %8.8x : %8.8x", nbuf, rnode.rn_l, rnode.rn_r);
23945664Ssklower }
24045664Ssklower while (rm) {
24145664Ssklower kget(rm, rmask);
24245664Ssklower sprintf(nbuf, " %d refs, ", rmask.rm_refs);
24345664Ssklower printf(" mk = %8.8x {(%d),%s",
24445664Ssklower rm, -1 - rmask.rm_b, rmask.rm_refs ? nbuf : " ");
24567874Ssklower if (rmask.rm_flags & RNF_NORMAL) {
24667874Ssklower struct radix_node rnode_aux;
24767897Ssklower printf(" <normal>, ");
24867874Ssklower kget(rmask.rm_leaf, rnode_aux);
249*69077Ssklower p_sockaddr(kgetsa((struct sockaddr *)rnode_aux.rn_mask),
250*69077Ssklower NULL, 0, -1);
25167874Ssklower } else
252*69077Ssklower p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask),
253*69077Ssklower NULL, 0, -1);
25445664Ssklower putchar('}');
25545664Ssklower if (rm = rmask.rm_mklist)
25645664Ssklower printf(" ->");
25745664Ssklower }
25845664Ssklower putchar('\n');
25945664Ssklower }
26045664Ssklower
26153698Ssklower static void
ntreestuff()26240837Ssklower ntreestuff()
26336308Skarels {
26458931Smckusick size_t needed;
26558931Smckusick int mib[6];
26640837Ssklower char *buf, *next, *lim;
26740837Ssklower register struct rt_msghdr *rtm;
26840837Ssklower
26958931Smckusick mib[0] = CTL_NET;
27058931Smckusick mib[1] = PF_ROUTE;
27158931Smckusick mib[2] = 0;
27258931Smckusick mib[3] = 0;
27358931Smckusick mib[4] = NET_RT_DUMP;
27458931Smckusick mib[5] = 0;
27558931Smckusick if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
27658931Smckusick { perror("route-sysctl-estimate"); exit(1);}
27740837Ssklower if ((buf = malloc(needed)) == 0)
27843248Ssklower { printf("out of space\n"); exit(1);}
27958931Smckusick if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
28058931Smckusick { perror("sysctl of routing table"); exit(1);}
28140837Ssklower lim = buf + needed;
28240837Ssklower for (next = buf; next < lim; next += rtm->rtm_msglen) {
28340837Ssklower rtm = (struct rt_msghdr *)next;
28440837Ssklower np_rtentry(rtm);
28536308Skarels }
28636308Skarels }
28736308Skarels
28853698Ssklower static void
np_rtentry(rtm)28940837Ssklower np_rtentry(rtm)
29050682Skarels register struct rt_msghdr *rtm;
29136308Skarels {
29240837Ssklower register struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
29353698Ssklower #ifdef notdef
29453698Ssklower static int masks_done, banner_printed;
29553698Ssklower #endif
29653698Ssklower static int old_af;
29740837Ssklower int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST;
29836308Skarels
29940837Ssklower #ifdef notdef
30040837Ssklower /* for the moment, netmasks are skipped over */
30140837Ssklower if (!banner_printed) {
30240837Ssklower printf("Netmasks:\n");
30340837Ssklower banner_printed = 1;
30440837Ssklower }
30540837Ssklower if (masks_done == 0) {
30640837Ssklower if (rtm->rtm_addrs != RTA_DST ) {
30740837Ssklower masks_done = 1;
30840837Ssklower af = sa->sa_family;
30940837Ssklower }
31040837Ssklower } else
31140837Ssklower #endif
31240837Ssklower af = sa->sa_family;
31340837Ssklower if (af != old_af) {
31450682Skarels pr_family(af);
31540837Ssklower old_af = af;
31640837Ssklower }
31740837Ssklower if (rtm->rtm_addrs == RTA_DST)
318*69077Ssklower p_sockaddr(sa, NULL, 0, 36);
31940837Ssklower else {
320*69077Ssklower p_sockaddr(sa, NULL, rtm->rtm_flags, 16);
32140837Ssklower if (sa->sa_len == 0)
32240837Ssklower sa->sa_len = sizeof(long);
32340837Ssklower sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
324*69077Ssklower p_sockaddr(sa, NULL, 0, 18);
32540837Ssklower }
32640837Ssklower p_flags(rtm->rtm_flags & interesting, "%-6.6s ");
32740837Ssklower putchar('\n');
32840837Ssklower }
32940837Ssklower
33053698Ssklower static void
p_sockaddr(sa,mask,flags,width)331*69077Ssklower p_sockaddr(sa, mask, flags, width)
332*69077Ssklower struct sockaddr *sa, *mask;
33350682Skarels int flags, width;
33440837Ssklower {
33553698Ssklower char workbuf[128], *cplim;
33650682Skarels register char *cp = workbuf;
33740837Ssklower
33840837Ssklower switch(sa->sa_family) {
33936308Skarels case AF_INET:
34040837Ssklower {
34140837Ssklower register struct sockaddr_in *sin = (struct sockaddr_in *)sa;
34240837Ssklower
343*69077Ssklower if (sin->sin_addr.s_addr == INADDR_ANY)
344*69077Ssklower cp = "default";
345*69077Ssklower else if (flags & RTF_HOST)
346*69077Ssklower cp = routename(sin->sin_addr.s_addr);
347*69077Ssklower else if (mask)
348*69077Ssklower cp = netname(sin->sin_addr.s_addr,
349*69077Ssklower ntohl(((struct sockaddr_in *)mask)
350*69077Ssklower ->sin_addr.s_addr));
351*69077Ssklower else
352*69077Ssklower cp = netname(sin->sin_addr.s_addr, 0L);
35350682Skarels break;
35440837Ssklower }
35540837Ssklower
35636308Skarels case AF_NS:
35753698Ssklower cp = ns_print(sa);
35836308Skarels break;
35940837Ssklower
36050682Skarels case AF_LINK:
36150682Skarels {
36250682Skarels register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
36350682Skarels
36450682Skarels if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 &&
36550682Skarels sdl->sdl_slen == 0)
36650682Skarels (void) sprintf(workbuf, "link#%d", sdl->sdl_index);
36750682Skarels else switch (sdl->sdl_type) {
36850682Skarels case IFT_ETHER:
36950682Skarels {
37050682Skarels register int i;
37150682Skarels register u_char *lla = (u_char *)sdl->sdl_data +
37250682Skarels sdl->sdl_nlen;
37350682Skarels
37450682Skarels cplim = "";
37550682Skarels for (i = 0; i < sdl->sdl_alen; i++, lla++) {
37650682Skarels cp += sprintf(cp, "%s%x", cplim, *lla);
37750682Skarels cplim = ":";
37850682Skarels }
37950682Skarels cp = workbuf;
38050682Skarels break;
38150682Skarels }
38250682Skarels default:
38350682Skarels cp = link_ntoa(sdl);
38450682Skarels break;
38550682Skarels }
38650682Skarels break;
38750682Skarels }
38850682Skarels
38936308Skarels default:
39040837Ssklower {
39166331Ssklower register u_char *s = (u_char *)sa->sa_data, *slim;
39240837Ssklower
39366320Ssklower slim = sa->sa_len + (u_char *) sa;
39440837Ssklower cplim = cp + sizeof(workbuf) - 6;
39540837Ssklower cp += sprintf(cp, "(%d)", sa->sa_family);
39666320Ssklower while (s < slim && cp < cplim) {
39766320Ssklower cp += sprintf(cp, " %02x", *s++);
39866320Ssklower if (s < slim)
39966320Ssklower cp += sprintf(cp, "%02x", *s++);
40066320Ssklower }
40140837Ssklower cp = workbuf;
40240837Ssklower }
40336308Skarels }
40445664Ssklower if (width < 0 )
40545664Ssklower printf("%s ", cp);
40645664Ssklower else {
40745664Ssklower if (nflag)
40845664Ssklower printf("%-*s ", width, cp);
40945664Ssklower else
41045664Ssklower printf("%-*.*s ", width, width, cp);
41145664Ssklower }
41240837Ssklower }
41340837Ssklower
41453698Ssklower static void
p_flags(f,format)41540837Ssklower p_flags(f, format)
41650682Skarels register int f;
41750682Skarels char *format;
41840837Ssklower {
41940837Ssklower char name[33], *flags;
42040837Ssklower register struct bits *p = bits;
42150682Skarels
42240837Ssklower for (flags = name; p->b_mask; p++)
42340837Ssklower if (p->b_mask & f)
42436308Skarels *flags++ = p->b_val;
42536308Skarels *flags = '\0';
42640837Ssklower printf(format, name);
42740837Ssklower }
42840837Ssklower
42953698Ssklower static void
p_rtentry(rt)43040837Ssklower p_rtentry(rt)
43153698Ssklower register struct rtentry *rt;
43240837Ssklower {
43350682Skarels static struct ifnet ifnet, *lastif;
43450682Skarels static char name[16];
435*69077Ssklower register struct sockaddr *sa;
436*69077Ssklower struct sockaddr addr, mask;
43740837Ssklower
438*69077Ssklower if (!(sa = kgetsa(rt_key(rt))))
439*69077Ssklower bzero(&addr, sizeof addr);
440*69077Ssklower else
441*69077Ssklower addr = *sa;
442*69077Ssklower if (!rt_mask(rt) || !(sa = kgetsa(rt_mask(rt))))
443*69077Ssklower bzero(&mask, sizeof mask);
444*69077Ssklower else
445*69077Ssklower mask = *sa;
446*69077Ssklower p_sockaddr(&addr, &mask, rt->rt_flags, WID_DST);
447*69077Ssklower p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, WID_GW);
44840837Ssklower p_flags(rt->rt_flags, "%-6.6s ");
44940837Ssklower printf("%6d %8d ", rt->rt_refcnt, rt->rt_use);
45050682Skarels if (rt->rt_ifp) {
45150682Skarels if (rt->rt_ifp != lastif) {
45250682Skarels kget(rt->rt_ifp, ifnet);
45354761Ssklower kread((u_long)ifnet.if_name, name, 16);
45450682Skarels lastif = rt->rt_ifp;
45550682Skarels }
45650682Skarels printf(" %.15s%d%s", name, ifnet.if_unit,
45750682Skarels rt->rt_nodes[0].rn_dupedkey ? " =>" : "");
45836308Skarels }
45950682Skarels putchar('\n');
46036308Skarels }
46136308Skarels
4627909Ssam char *
routename(in)4637909Ssam routename(in)
46453698Ssklower u_long in;
4657909Ssam {
46624918Skarels register char *cp;
46733023Skarels static char line[MAXHOSTNAMELEN + 1];
46816463Skarels struct hostent *hp;
46924914Skarels static char domain[MAXHOSTNAMELEN + 1];
47024914Skarels static int first = 1;
4717909Ssam
47224914Skarels if (first) {
47324914Skarels first = 0;
47424914Skarels if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
47524914Skarels (cp = index(domain, '.')))
47624914Skarels (void) strcpy(domain, cp + 1);
47724914Skarels else
47824914Skarels domain[0] = 0;
47924914Skarels }
48024918Skarels cp = 0;
4817909Ssam if (!nflag) {
48229749Skupfer hp = gethostbyaddr((char *)&in, sizeof (struct in_addr),
48321908Skarels AF_INET);
48424914Skarels if (hp) {
48524914Skarels if ((cp = index(hp->h_name, '.')) &&
48624914Skarels !strcmp(cp + 1, domain))
48724914Skarels *cp = 0;
48821908Skarels cp = hp->h_name;
48924914Skarels }
4907909Ssam }
4917909Ssam if (cp)
49233023Skarels strncpy(line, cp, sizeof(line) - 1);
4937909Ssam else {
49421908Skarels #define C(x) ((x) & 0xff)
49553698Ssklower in = ntohl(in);
49653698Ssklower sprintf(line, "%u.%u.%u.%u",
49753698Ssklower C(in >> 24), C(in >> 16), C(in >> 8), C(in));
4987909Ssam }
4997909Ssam return (line);
5007909Ssam }
50121908Skarels
502*69077Ssklower static u_long
forgemask(a)503*69077Ssklower forgemask(a)
504*69077Ssklower u_long a;
505*69077Ssklower {
506*69077Ssklower u_long m;
507*69077Ssklower
508*69077Ssklower if (IN_CLASSA(a))
509*69077Ssklower m = IN_CLASSA_NET;
510*69077Ssklower else if (IN_CLASSB(a))
511*69077Ssklower m = IN_CLASSB_NET;
512*69077Ssklower else
513*69077Ssklower m = IN_CLASSC_NET;
514*69077Ssklower return (m);
515*69077Ssklower }
516*69077Ssklower
517*69077Ssklower static void
domask(dst,addr,mask)518*69077Ssklower domask(dst, addr, mask)
519*69077Ssklower char *dst;
520*69077Ssklower u_long addr, mask;
521*69077Ssklower {
522*69077Ssklower register int b, i;
523*69077Ssklower
524*69077Ssklower if (!mask || (forgemask(addr) == mask)) {
525*69077Ssklower *dst = '\0';
526*69077Ssklower return;
527*69077Ssklower }
528*69077Ssklower i = 0;
529*69077Ssklower for (b = 0; b < 32; b++)
530*69077Ssklower if (mask & (1 << b)) {
531*69077Ssklower register int bb;
532*69077Ssklower
533*69077Ssklower i = b;
534*69077Ssklower for (bb = b+1; bb < 32; bb++)
535*69077Ssklower if (!(mask & (1 << bb))) {
536*69077Ssklower i = -1; /* noncontig */
537*69077Ssklower break;
538*69077Ssklower }
539*69077Ssklower break;
540*69077Ssklower }
541*69077Ssklower if (i == -1)
542*69077Ssklower sprintf(dst, "&0x%lx", mask);
543*69077Ssklower else
544*69077Ssklower sprintf(dst, "/%d", 32-i);
545*69077Ssklower }
546*69077Ssklower
54712839Ssam /*
54821908Skarels * Return the name of the network whose address is given.
54921908Skarels * The address is assumed to be that of a net or subnet, not a host.
55021908Skarels */
55121908Skarels char *
netname(in,mask)55221908Skarels netname(in, mask)
55353698Ssklower u_long in, mask;
55421908Skarels {
55521908Skarels char *cp = 0;
55633023Skarels static char line[MAXHOSTNAMELEN + 1];
55721908Skarels struct netent *np = 0;
558*69077Ssklower u_long net, omask;
559*69077Ssklower register u_long i;
56024914Skarels int subnetshift;
56121908Skarels
56253698Ssklower i = ntohl(in);
563*69077Ssklower omask = mask;
56430973Skarels if (!nflag && i) {
56524914Skarels if (mask == 0) {
566*69077Ssklower switch (mask = forgemask(i)) {
567*69077Ssklower case IN_CLASSA_NET:
56824914Skarels subnetshift = 8;
569*69077Ssklower break;
570*69077Ssklower case IN_CLASSB_NET:
57124914Skarels subnetshift = 8;
572*69077Ssklower break;
573*69077Ssklower case IN_CLASSC_NET:
57424914Skarels subnetshift = 4;
575*69077Ssklower break;
576*69077Ssklower default:
577*69077Ssklower abort();
57824914Skarels }
57921908Skarels /*
58024914Skarels * If there are more bits than the standard mask
58124914Skarels * would suggest, subnets must be in use.
58224914Skarels * Guess at the subnet mask, assuming reasonable
58324914Skarels * width subnet fields.
58421908Skarels */
58530973Skarels while (i &~ mask)
58624914Skarels mask = (long)mask >> subnetshift;
58721908Skarels }
58830973Skarels net = i & mask;
58924914Skarels while ((mask & 1) == 0)
59024914Skarels mask >>= 1, net >>= 1;
59124914Skarels np = getnetbyaddr(net, AF_INET);
59221908Skarels if (np)
59321908Skarels cp = np->n_name;
59453698Ssklower }
59521908Skarels if (cp)
59633023Skarels strncpy(line, cp, sizeof(line) - 1);
59730973Skarels else if ((i & 0xffffff) == 0)
59830973Skarels sprintf(line, "%u", C(i >> 24));
59930973Skarels else if ((i & 0xffff) == 0)
60030973Skarels sprintf(line, "%u.%u", C(i >> 24) , C(i >> 16));
60130973Skarels else if ((i & 0xff) == 0)
60230973Skarels sprintf(line, "%u.%u.%u", C(i >> 24), C(i >> 16), C(i >> 8));
60321908Skarels else
60430973Skarels sprintf(line, "%u.%u.%u.%u", C(i >> 24),
60530973Skarels C(i >> 16), C(i >> 8), C(i));
606*69077Ssklower domask(line+strlen(line), i, omask);
60721908Skarels return (line);
60821908Skarels }
60924914Skarels
61021908Skarels /*
61112839Ssam * Print routing statistics
61212839Ssam */
61353698Ssklower void
rt_stats(off)61412839Ssam rt_stats(off)
61554761Ssklower u_long off;
61612839Ssam {
61712839Ssam struct rtstat rtstat;
61812839Ssam
61912839Ssam if (off == 0) {
62012839Ssam printf("rtstat: symbol not in namelist\n");
62112839Ssam return;
62212839Ssam }
62353698Ssklower kread(off, (char *)&rtstat, sizeof (rtstat));
62412839Ssam printf("routing:\n");
62530292Ssam printf("\t%u bad routing redirect%s\n",
62612839Ssam rtstat.rts_badredirect, plural(rtstat.rts_badredirect));
62730292Ssam printf("\t%u dynamically created route%s\n",
62812839Ssam rtstat.rts_dynamic, plural(rtstat.rts_dynamic));
62930292Ssam printf("\t%u new gateway%s due to redirects\n",
63012839Ssam rtstat.rts_newgateway, plural(rtstat.rts_newgateway));
63130292Ssam printf("\t%u destination%s found unreachable\n",
63212839Ssam rtstat.rts_unreach, plural(rtstat.rts_unreach));
63330292Ssam printf("\t%u use%s of a wildcard route\n",
63412839Ssam rtstat.rts_wildcard, plural(rtstat.rts_wildcard));
63512839Ssam }
63627265Skarels short ns_nullh[] = {0,0,0};
63723499Ssklower short ns_bh[] = {-1,-1,-1};
63823499Ssklower
63923499Ssklower char *
ns_print(sa)64053698Ssklower ns_print(sa)
64153698Ssklower register struct sockaddr *sa;
64223499Ssklower {
64353698Ssklower register struct sockaddr_ns *sns = (struct sockaddr_ns*)sa;
64427265Skarels struct ns_addr work;
64527265Skarels union { union ns_net net_e; u_long long_e; } net;
64627265Skarels u_short port;
64727265Skarels static char mybuf[50], cport[10], chost[25];
64827265Skarels char *host = "";
64929749Skupfer register char *p; register u_char *q;
65023499Ssklower
65127265Skarels work = sns->sns_addr;
65227265Skarels port = ntohs(work.x_port);
65327265Skarels work.x_port = 0;
65427265Skarels net.net_e = work.x_net;
65527265Skarels if (ns_nullhost(work) && net.long_e == 0) {
65627265Skarels if (port ) {
65727265Skarels sprintf(mybuf, "*.%xH", port);
65827265Skarels upHex(mybuf);
65927265Skarels } else
66027265Skarels sprintf(mybuf, "*.*");
66127265Skarels return (mybuf);
66227265Skarels }
66323499Ssklower
66443248Ssklower if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) {
66527265Skarels host = "any";
66627265Skarels } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) {
66727265Skarels host = "*";
66827265Skarels } else {
66927265Skarels q = work.x_host.c_host;
67027265Skarels sprintf(chost, "%02x%02x%02x%02x%02x%02xH",
67127265Skarels q[0], q[1], q[2], q[3], q[4], q[5]);
67253698Ssklower for (p = chost; *p == '0' && p < chost + 12; p++)
67353698Ssklower continue;
67427265Skarels host = p;
67527265Skarels }
67627265Skarels if (port)
67727265Skarels sprintf(cport, ".%xH", htons(port));
67827265Skarels else
67927265Skarels *cport = 0;
68023499Ssklower
68127265Skarels sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport);
68227265Skarels upHex(mybuf);
68323499Ssklower return(mybuf);
68423499Ssklower }
68527265Skarels
68623499Ssklower char *
ns_phost(sa)68753698Ssklower ns_phost(sa)
68853698Ssklower struct sockaddr *sa;
68923499Ssklower {
69053698Ssklower register struct sockaddr_ns *sns = (struct sockaddr_ns *)sa;
69127265Skarels struct sockaddr_ns work;
69227265Skarels static union ns_net ns_zeronet;
69327265Skarels char *p;
69453698Ssklower
69527265Skarels work = *sns;
69627265Skarels work.sns_addr.x_port = 0;
69727265Skarels work.sns_addr.x_net = ns_zeronet;
69827265Skarels
69953698Ssklower p = ns_print((struct sockaddr *)&work);
70027265Skarels if (strncmp("0H.", p, 3) == 0) p += 3;
70127265Skarels return(p);
70223499Ssklower }
70353698Ssklower
70453698Ssklower void
upHex(p0)70527265Skarels upHex(p0)
70653698Ssklower char *p0;
70727265Skarels {
70827265Skarels register char *p = p0;
70927265Skarels for (; *p; p++) switch (*p) {
71027265Skarels
71127265Skarels case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
71227265Skarels *p += ('A' - 'a');
71327265Skarels }
71427265Skarels }
715