home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / E-zine / Magazines / crh / freebsd / rootkit / netstat / route.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-05-27  |  18.8 KB  |  883 lines

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