new subnets, interface addressing
[unix-history] / usr / src / usr.bin / netstat / route.c
index 1cc721c..04213b8 100644 (file)
@@ -1,19 +1,20 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)route.c    4.3 82/10/06";
+static char sccsid[] = "@(#)route.c    4.10 85/06/03";
 #endif
 
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/mbuf.h>
 #endif
 
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/mbuf.h>
+
 #include <net/if.h>
 #include <net/if.h>
-#include <net/in.h>
-#define        KERNEL          /* to get routehash and RTHASHSIZ */
 #include <net/route.h>
 #include <net/route.h>
+#include <netinet/in.h>
+
 #include <netdb.h>
 
 extern int kmem;
 extern int nflag;
 #include <netdb.h>
 
 extern int kmem;
 extern int nflag;
-extern char *routename();
+extern char *routename(), *netname();
 
 /*
  * Definitions for showing gateway flags.
 
 /*
  * Definitions for showing gateway flags.
@@ -31,19 +32,18 @@ struct bits {
 /*
  * Print routing tables.
  */
 /*
  * Print routing tables.
  */
-routepr(hostaddr, netaddr)
-       off_t hostaddr, netaddr;
+routepr(hostaddr, netaddr, hashsizeaddr)
+       off_t hostaddr, netaddr, hashsizeaddr;
 {
        struct mbuf mb;
        register struct rtentry *rt;
        register struct mbuf *m;
        register struct bits *p;
 {
        struct mbuf mb;
        register struct rtentry *rt;
        register struct mbuf *m;
        register struct bits *p;
-       struct netent *np;
-       struct hostent *hp;
        char name[16], *flags;
        char name[16], *flags;
-       struct mbuf *routehash[RTHASHSIZ];
+       struct mbuf **routehash;
        struct ifnet ifnet;
        struct ifnet ifnet;
-       int first = 1, i, doinghost = 1;
+       int hashsize;
+       int i, doinghost = 1;
 
        if (hostaddr == 0) {
                printf("rthost: symbol not in namelist\n");
 
        if (hostaddr == 0) {
                printf("rthost: symbol not in namelist\n");
@@ -53,14 +53,21 @@ routepr(hostaddr, netaddr)
                printf("rtnet: symbol not in namelist\n");
                return;
        }
                printf("rtnet: symbol not in namelist\n");
                return;
        }
+       if (hashsizeaddr == 0) {
+               printf("rthashsize: symbol not in namelist\n");
+               return;
+       }
+       klseek(kmem, hashsizeaddr, 0);
+       read(kmem, &hashsize, sizeof (hashsize));
+       routehash = (struct mbuf **)malloc( hashsize*sizeof (struct mbuf *) );
        klseek(kmem, hostaddr, 0);
        klseek(kmem, hostaddr, 0);
-       read(kmem, routehash, sizeof (routehash));
+       read(kmem, routehash, hashsize*sizeof (struct mbuf *));
        printf("Routing tables\n");
        printf("%-15.15s %-15.15s %-8.8s %-6.6s %-10.10s %s\n",
                "Destination", "Gateway",
                "Flags", "Refcnt", "Use", "Interface");
 again:
        printf("Routing tables\n");
        printf("%-15.15s %-15.15s %-8.8s %-6.6s %-10.10s %s\n",
                "Destination", "Gateway",
                "Flags", "Refcnt", "Use", "Interface");
 again:
-       for (i = 0; i < RTHASHSIZ; i++) {
+       for (i = 0; i < hashsize; i++) {
                if (routehash[i] == 0)
                        continue;
                m = routehash[i];
                if (routehash[i] == 0)
                        continue;
                m = routehash[i];
@@ -71,7 +78,10 @@ again:
                        read(kmem, &mb, sizeof (mb));
                        rt = mtod(&mb, struct rtentry *);
                        sin = (struct sockaddr_in *)&rt->rt_dst;
                        read(kmem, &mb, sizeof (mb));
                        rt = mtod(&mb, struct rtentry *);
                        sin = (struct sockaddr_in *)&rt->rt_dst;
-                       printf("%-15.15s ", routename(sin->sin_addr));
+                       printf("%-15.15s ",
+                           (sin->sin_addr.s_addr == 0) ? "default" :
+                           (rt->rt_flags & RTF_HOST) ?
+                           routename(sin->sin_addr) : netname(sin->sin_addr, 0));
                        sin = (struct sockaddr_in *)&rt->rt_gateway;
                        printf("%-15.15s ", routename(sin->sin_addr));
                        for (flags = name, p = bits; p->b_mask; p++)
                        sin = (struct sockaddr_in *)&rt->rt_gateway;
                        printf("%-15.15s ", routename(sin->sin_addr));
                        for (flags = name, p = bits; p->b_mask; p++)
@@ -95,10 +105,11 @@ again:
        }
        if (doinghost) {
                klseek(kmem, netaddr, 0);
        }
        if (doinghost) {
                klseek(kmem, netaddr, 0);
-               read(kmem, routehash, sizeof (routehash));
+               read(kmem, routehash, hashsize*sizeof (struct mbuf *));
                doinghost = 0;
                goto again;
        }
                doinghost = 0;
                goto again;
        }
+       free(routehash);
 }
 
 char *
 }
 
 char *
@@ -107,34 +118,99 @@ routename(in)
 {
        char *cp = 0;
        static char line[50];
 {
        char *cp = 0;
        static char line[50];
-       int lna, net;
+       struct hostent *hp;
 
 
-       net = in_netof(in);
-       lna = in_lnaof(in);
        if (!nflag) {
        if (!nflag) {
-               if (lna == INADDR_ANY) {
-                       struct netent *np = getnetbyaddr(net, AF_INET);
+               hp = gethostbyaddr(&in, sizeof (struct in_addr),
+                       AF_INET);
+               if (hp)
+                       cp = hp->h_name;
+       }
+       if (cp)
+               strcpy(line, cp);
+       else {
+#define C(x)   ((x) & 0xff)
+               in.s_addr = ntohl(in.s_addr);
+               sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
+                       C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
+       }
+       return (line);
+}
 
 
-                       if (np)
-                               cp = np->n_name;
-               } else {
-                       struct hostent *hp;
+/*
+ * Return the name of the network whose address is given.
+ * The address is assumed to be that of a net or subnet, not a host.
+ */
+char *
+netname(in, mask)
+       struct in_addr in;
+       u_long mask;
+{
+       char *cp = 0;
+       static char line[50];
+       struct netent *np = 0;
+       u_long net;
+       register i;
 
 
-                       hp = gethostbyaddr(&in, sizeof (struct in_addr),
-                               AF_INET);
-                       if (hp)
-                               cp = hp->h_name;
+       in.s_addr = ntohl(in.s_addr);
+       if (!nflag && in.s_addr) {
+               if (mask) {
+                       net = in.s_addr & mask;
+                       while ((mask & 1) == 0)
+                               mask >>= 1, net >>= 1;
+                       np = getnetbyaddr(net, AF_INET);
+               }
+               if (np == 0) {
+                       /*
+                        * Try for subnet addresses.
+                        */
+                       for (i = 0; ((0xf<<i) & in.s_addr) == 0; i += 4)
+                               ;
+                       for ( ; i; i -= 4)
+                           if (np = getnetbyaddr((unsigned)in.s_addr >> i,
+                                   AF_INET))
+                                       break;
                }
                }
+               if (np)
+                       cp = np->n_name;
        }
        if (cp)
                strcpy(line, cp);
        }
        if (cp)
                strcpy(line, cp);
-       else {
-               u_char *ucp = (u_char *)&in;
-               if (lna == INADDR_ANY)
-                       sprintf(line, "%u.%u.%u", ucp[0], ucp[1], ucp[2]);
-               else
-                       sprintf(line, "%u.%u.%u.%u", ucp[0], ucp[1],
-                               ucp[2], ucp[3]);
-       }
+       else if ((in.s_addr & 0xffffff) == 0)
+               sprintf(line, "%u", C(in.s_addr >> 24));
+       else if ((in.s_addr & 0xffff) == 0)
+               sprintf(line, "%u.%u", C(in.s_addr >> 24) , C(in.s_addr >> 16));
+       else if ((in.s_addr & 0xff) == 0)
+               sprintf(line, "%u.%u.%u", C(in.s_addr >> 24),
+                       C(in.s_addr >> 16), C(in.s_addr >> 8));
+       else
+               sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
+                       C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
        return (line);
 }
        return (line);
 }
+/*
+ * Print routing statistics
+ */
+rt_stats(off)
+       off_t off;
+{
+       struct rtstat rtstat;
+
+       if (off == 0) {
+               printf("rtstat: symbol not in namelist\n");
+               return;
+       }
+       klseek(kmem, off, 0);
+       read(kmem, (char *)&rtstat, sizeof (rtstat));
+       printf("routing:\n");
+       printf("\t%d bad routing redirect%s\n",
+               rtstat.rts_badredirect, plural(rtstat.rts_badredirect));
+       printf("\t%d dynamically created route%s\n",
+               rtstat.rts_dynamic, plural(rtstat.rts_dynamic));
+       printf("\t%d new gateway%s due to redirects\n",
+               rtstat.rts_newgateway, plural(rtstat.rts_newgateway));
+       printf("\t%d destination%s found unreachable\n",
+               rtstat.rts_unreach, plural(rtstat.rts_unreach));
+       printf("\t%d use%s of a wildcard route\n",
+               rtstat.rts_wildcard, plural(rtstat.rts_wildcard));
+}