Annotation of 43BSDReno/usr.bin/netstat/route.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.