Annotation of 43BSDReno/usr.bin/netstat/route.c, revision 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.