Author: glebius
Date: Wed Mar 19 09:36:29 2014
New Revision: 263335
URL: http://svnweb.freebsd.org/changeset/base/263335

Log:
  Merge r259562,r259566,r259638,r259645,r260124 by melifaro:
  
    Switch netstat -rn to use standard API for retrieving list
    of routes instead of peeking inside in-kernel radix via kget.

Modified:
  stable/10/usr.bin/netstat/if.c
  stable/10/usr.bin/netstat/main.c
  stable/10/usr.bin/netstat/mroute.c
  stable/10/usr.bin/netstat/mroute6.c
  stable/10/usr.bin/netstat/netgraph.c
  stable/10/usr.bin/netstat/netstat.h
  stable/10/usr.bin/netstat/route.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/usr.bin/netstat/if.c
==============================================================================
--- stable/10/usr.bin/netstat/if.c      Wed Mar 19 09:23:58 2014        
(r263334)
+++ stable/10/usr.bin/netstat/if.c      Wed Mar 19 09:36:29 2014        
(r263335)
@@ -224,7 +224,7 @@ next_ifma(struct ifmaddrs *ifma, const c
  * Print a description of the network interfaces.
  */
 void
-intpr(int interval, void (*pfunc)(char *))
+intpr(int interval, void (*pfunc)(char *), int af)
 {
        struct ifaddrs *ifap, *ifa;
        struct ifmaddrs *ifmap, *ifma;

Modified: stable/10/usr.bin/netstat/main.c
==============================================================================
--- stable/10/usr.bin/netstat/main.c    Wed Mar 19 09:23:58 2014        
(r263334)
+++ stable/10/usr.bin/netstat/main.c    Wed Mar 19 09:36:29 2014        
(r263335)
@@ -552,41 +552,41 @@ main(int argc, char *argv[])
         * used for the queries, which is slower.
         */
 #endif
-       kread(0, NULL, 0);
        if (iflag && !sflag) {
-               intpr(interval, NULL);
+               intpr(interval, NULL, af);
                exit(0);
        }
        if (rflag) {
                if (sflag) {
-                       rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
+                       rt_stats();
                        flowtable_stats();
                } else
-                       routepr(nl[N_RTREE].n_value, fib);
+                       routepr(fib, af);
                exit(0);
        }
+
        if (gflag) {
                if (sflag) {
                        if (af == AF_INET || af == AF_UNSPEC)
-                               mrt_stats(nl[N_MRTSTAT].n_value);
+                               mrt_stats();
 #ifdef INET6
                        if (af == AF_INET6 || af == AF_UNSPEC)
-                               mrt6_stats(nl[N_MRT6STAT].n_value);
+                               mrt6_stats();
 #endif
                } else {
                        if (af == AF_INET || af == AF_UNSPEC)
-                               mroutepr(nl[N_MFCHASHTBL].n_value,
-                                        nl[N_MFCTABLESIZE].n_value,
-                                        nl[N_VIFTABLE].n_value);
+                               mroutepr();
 #ifdef INET6
                        if (af == AF_INET6 || af == AF_UNSPEC)
-                               mroute6pr(nl[N_MF6CTABLE].n_value,
-                                         nl[N_MIF6TABLE].n_value);
+                               mroute6pr();
 #endif
                }
                exit(0);
        }
 
+       /* Load all necessary kvm symbols */
+       kresolve_list(nl);
+
        if (tp) {
                printproto(tp, tp->pr_name);
                exit(0);
@@ -639,7 +639,7 @@ printproto(struct protox *tp, const char
        if (sflag) {
                if (iflag) {
                        if (tp->pr_istats)
-                               intpr(interval, tp->pr_istats);
+                               intpr(interval, tp->pr_istats, af);
                        else if (pflag)
                                printf("%s: no per-interface stats routine\n",
                                    tp->pr_name);
@@ -702,7 +702,23 @@ kvmd_init(void)
                return (-1);
        }
 
-       if (kvm_nlist(kvmd, nl) < 0) {
+       return (0);
+}
+
+/*
+ * Resolve symbol list, return 0 on success.
+ */
+int
+kresolve_list(struct nlist *_nl)
+{
+
+       if ((kvmd == NULL) && (kvmd_init() != 0))
+               return (-1);
+
+       if (_nl[0].n_type != 0)
+               return (0);
+
+       if (kvm_nlist(kvmd, _nl) < 0) {
                if (nlistf)
                        errx(1, "%s: kvm_nlist: %s", nlistf,
                             kvm_geterr(kvmd));
@@ -710,13 +726,6 @@ kvmd_init(void)
                        errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
        }
 
-       if (nl[0].n_type == 0) {
-               if (nlistf)
-                       errx(1, "%s: no namelist", nlistf);
-               else
-                       errx(1, "no namelist");
-       }
-
        return (0);
 }
 

Modified: stable/10/usr.bin/netstat/mroute.c
==============================================================================
--- stable/10/usr.bin/netstat/mroute.c  Wed Mar 19 09:23:58 2014        
(r263334)
+++ stable/10/usr.bin/netstat/mroute.c  Wed Mar 19 09:36:29 2014        
(r263335)
@@ -65,11 +65,26 @@ __FBSDID("$FreeBSD$");
 #undef _KERNEL
 
 #include <err.h>
+#include <nlist.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include "netstat.h"
 
+/*
+ * kvm(3) bindings for every needed symbol
+ */
+static struct nlist mrl[] = {
+#define        N_MRTSTAT       0
+       { .n_name = "_mrtstat" },
+#define        N_MFCHASHTBL    1
+       { .n_name = "_mfchashtbl" },
+#define        N_VIFTABLE      2
+       { .n_name = "_viftable" },
+#define        N_MFCTABLESIZE  3
+       { .n_name = "_mfctablesize" },
+       { .n_name = NULL },
+};
 
 static void    print_bw_meter(struct bw_meter *, int *);
 static void    print_mfc(struct mfc *, int, int *);
@@ -193,11 +208,12 @@ print_mfc(struct mfc *m, int maxvif, int
 }
 
 void
-mroutepr(u_long pmfchashtbl, u_long pmfctablesize, u_long pviftbl)
+mroutepr()
 {
        struct vif viftable[MAXVIFS];
        struct vif *v;
        struct mfc *m;
+       u_long pmfchashtbl, pmfctablesize, pviftbl;
        int banner_printed;
        int saved_numeric_addr;
        size_t len;
@@ -221,6 +237,16 @@ mroutepr(u_long pmfchashtbl, u_long pmfc
         */
        maxvif = 0;
 
+       kresolve_list(mrl);
+       pmfchashtbl = mrl[N_MFCHASHTBL].n_value;
+       pmfctablesize = mrl[N_MFCTABLESIZE].n_value;
+       pviftbl = mrl[N_VIFTABLE].n_value;
+
+       if (pmfchashtbl == 0 || pmfctablesize == 0 || pviftbl == 0) {
+               fprintf(stderr, "No IPv4 MROUTING kernel support.\n");
+               return;
+       }
+
        len = sizeof(viftable);
        if (live) {
                if (sysctlbyname("net.inet.ip.viftable", viftable, &len, NULL,
@@ -338,15 +364,24 @@ mroutepr(u_long pmfchashtbl, u_long pmfc
 }
 
 void
-mrt_stats(u_long mstaddr)
+mrt_stats()
 {
        struct mrtstat mrtstat;
-       size_t len = sizeof mrtstat;
+       u_long mstaddr;
+       size_t len = sizeof(mrtstat);
+
+       kresolve_list(mrl);
+       mstaddr = mrl[N_MRTSTAT].n_value;
+
+       if (mstaddr == 0) {
+               fprintf(stderr, "No IPv4 MROUTING kernel support.\n");
+               return;
+       }
 
        if (live) {
                if (sysctlbyname("net.inet.ip.mrtstat", &mrtstat, &len, NULL,
                    0) < 0) {
-                       warn("sysctl: net.inet.ip.mrtstat");
+                       warn("sysctl: net.inet.ip.mrtstat failed.");
                        return;
                }
        } else

Modified: stable/10/usr.bin/netstat/mroute6.c
==============================================================================
--- stable/10/usr.bin/netstat/mroute6.c Wed Mar 19 09:23:58 2014        
(r263334)
+++ stable/10/usr.bin/netstat/mroute6.c Wed Mar 19 09:36:29 2014        
(r263335)
@@ -85,6 +85,7 @@ __FBSDID("$FreeBSD$");
 #include <netinet/in.h>
 
 #include <err.h>
+#include <nlist.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -95,17 +96,32 @@ __FBSDID("$FreeBSD$");
 
 #include "netstat.h"
 
+/*
+ * kvm(3) bindings for every needed symbol
+ */
+static struct nlist mrl[] = {
+#define        N_MF6CTABLE     0
+       { .n_name = "_mf6ctable" },
+#define        N_MIF6TABLE     1
+       { .n_name = "_mif6table" },
+#define        N_MRT6STAT      2
+       { .n_name = "_mrt6stat" },
+       { .n_name = NULL },
+};
+
+
 #define        WID_ORG (Wflag ? 39 : (numeric_addr ? 29 : 18)) /* width of 
origin column */
 #define        WID_GRP (Wflag ? 18 : (numeric_addr ? 16 : 18)) /* width of 
group column */
 
 void
-mroute6pr(u_long mfcaddr, u_long mifaddr)
+mroute6pr()
 {
        struct mf6c *mf6ctable[MF6CTBLSIZ], *mfcp;
        struct mif6 mif6table[MAXMIFS];
        struct mf6c mfc;
        struct rtdetq rte, *rtep;
        struct mif6 *mifp;
+       u_long mfcaddr, mifaddr;
        mifi_t mifi;
        int i;
        int banner_printed;
@@ -114,6 +130,15 @@ mroute6pr(u_long mfcaddr, u_long mifaddr
        long int waitings;
        size_t len;
 
+       kresolve_list(mrl);
+       mfcaddr = mrl[N_MF6CTABLE].n_value;
+       mifaddr = mrl[N_MIF6TABLE].n_value;
+
+       if (mfcaddr == 0 || mifaddr == 0) {
+               fprintf(stderr, "No IPv6 MROUTING kernel support.\n");
+               return;
+       }
+
        len = sizeof(mif6table);
        if (live) {
                if (sysctlbyname("net.inet6.ip6.mif6table", mif6table, &len,
@@ -217,11 +242,20 @@ mroute6pr(u_long mfcaddr, u_long mifaddr
 }
 
 void
-mrt6_stats(u_long mstaddr)
+mrt6_stats()
 {
        struct mrt6stat mrtstat;
+       u_long mstaddr;
        size_t len = sizeof mrtstat;
 
+       kresolve_list(mrl);
+       mstaddr = mrl[N_MRT6STAT].n_value;
+
+       if (mstaddr == 0) {
+               fprintf(stderr, "No IPv6 MROUTING kernel support.\n");
+               return;
+       }
+
        if (live) {
                if (sysctlbyname("net.inet6.ip6.mrt6stat", &mrtstat, &len,
                    NULL, 0) < 0) {

Modified: stable/10/usr.bin/netstat/netgraph.c
==============================================================================
--- stable/10/usr.bin/netstat/netgraph.c        Wed Mar 19 09:23:58 2014        
(r263334)
+++ stable/10/usr.bin/netstat/netgraph.c        Wed Mar 19 09:36:29 2014        
(r263335)
@@ -72,53 +72,10 @@ netgraphprotopr(u_long off, const char *
 
        /* If symbol not found, try looking in the KLD module */
        if (off == 0) {
-               const char *const modname = "ng_socket.ko";
-/* XXX We should get "mpath" from "sysctl kern.module_path" */
-               const char *mpath[] = { "/", "/boot/", "/modules/", NULL };
-               struct nlist sym[] = { { .n_name = "_ngsocklist" },
-                                      { .n_name = NULL } };
-               const char **pre;
-               struct kld_file_stat ks;
-               int fileid;
-
-               /* Can't do this for core dumps. */
-               if (!live)
-                       return;
-
-               /* See if module is loaded */
-               if ((fileid = kldfind(modname)) < 0) {
-                       if (debug)
-                               warn("kldfind(%s)", modname);
-                       return;
-               }
-
-               /* Get module info */
-               memset(&ks, 0, sizeof(ks));
-               ks.version = sizeof(struct kld_file_stat);
-               if (kldstat(fileid, &ks) < 0) {
-                       if (debug)
-                               warn("kldstat(%d)", fileid);
-                       return;
-               }
-
-               /* Get symbol table from module file */
-               for (pre = mpath; *pre; pre++) {
-                       char path[MAXPATHLEN];
-
-                       snprintf(path, sizeof(path), "%s%s", *pre, modname);
-                       if (nlist(path, sym) == 0)
-                               break;
-               }
-
-               /* Did we find it? */
-               if (sym[0].n_value == 0) {
-                       if (debug)
-                               warnx("%s not found", modname);
-                       return;
-               }
-
-               /* Symbol found at load address plus symbol offset */
-               off = (u_long) ks.address + sym[0].n_value;
+               if (debug)
+                       fprintf(stderr,
+                           "Error reading symbols from ng_socket.ko");
+               return;
        }
 
        /* Get pointer to first socket */

Modified: stable/10/usr.bin/netstat/netstat.h
==============================================================================
--- stable/10/usr.bin/netstat/netstat.h Wed Mar 19 09:23:58 2014        
(r263334)
+++ stable/10/usr.bin/netstat/netstat.h Wed Mar 19 09:36:29 2014        
(r263335)
@@ -56,11 +56,12 @@ extern int  interval; /* repeat interval 
 extern char    *interface; /* desired i/f for stats, or NULL for all i/fs */
 extern int     unit;   /* unit number for above */
 
-extern int     af;     /* address family */
 extern int     live;   /* true if we are examining a live system */
 
+struct nlist;
 int    kread(u_long addr, void *buf, size_t size);
 int    kread_counters(u_long addr, void *buf, size_t size);
+int    kresolve_list(struct nlist *);
 const char *plural(uintmax_t);
 const char *plurales(uintmax_t);
 const char *pluralies(uintmax_t);
@@ -97,8 +98,8 @@ void  icmp6_stats(u_long, const char *, i
 void   icmp6_ifstats(char *);
 void   pim6_stats(u_long, const char *, int, int);
 void   rip6_stats(u_long, const char *, int, int);
-void   mroute6pr(u_long, u_long);
-void   mrt6_stats(u_long);
+void   mroute6pr(void);
+void   mrt6_stats(void);
 
 struct sockaddr_in6;
 struct in6_addr;
@@ -119,11 +120,11 @@ void      netisr_stats(void *);
 void   hostpr(u_long, u_long);
 void   impstats(u_long, u_long);
 
-void   intpr(int, void (*)(char *));
+void   intpr(int, void (*)(char *), int);
 
 void   pr_rthdr(int);
 void   pr_family(int);
-void   rt_stats(u_long, u_long);
+void   rt_stats(void);
 void   flowtable_stats(void);
 char   *ipx_pnet(struct sockaddr *);
 char   *ipx_phost(struct sockaddr *);
@@ -136,7 +137,7 @@ char        *atalk_print(struct sockaddr *, int
 char   *atalk_print2(struct sockaddr *, struct sockaddr *, int);
 char   *ipx_print(struct sockaddr *);
 char   *ns_print(struct sockaddr *);
-void   routepr(u_long, int);
+void   routepr(int, int);
 
 void   ipxprotopr(u_long, const char *, int, int);
 void   spx_stats(u_long, const char *, int, int);
@@ -166,6 +167,6 @@ void        tp_protopr(u_long, const char *, in
 void   tp_inproto(u_long);
 void   tp_stats(caddr_t, caddr_t);
 
-void   mroutepr(u_long, u_long, u_long);
-void   mrt_stats(u_long);
+void   mroutepr(void);
+void   mrt_stats(void);
 void   bpf_stats(char *);

Modified: stable/10/usr.bin/netstat/route.c
==============================================================================
--- stable/10/usr.bin/netstat/route.c   Wed Mar 19 09:23:58 2014        
(r263334)
+++ stable/10/usr.bin/netstat/route.c   Wed Mar 19 09:36:29 2014        
(r263335)
@@ -58,8 +58,10 @@ __FBSDID("$FreeBSD$");
 #include <sys/sysctl.h>
 
 #include <arpa/inet.h>
+#include <ifaddrs.h>
 #include <libutil.h>
 #include <netdb.h>
+#include <nlist.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -105,6 +107,19 @@ struct bits {
        { 0 , 0 }
 };
 
+/*
+ * kvm(3) bindings for every needed symbol
+ */
+static struct nlist rl[] = {
+#define        N_RTSTAT        0
+       { .n_name = "_rtstat" },
+#define        N_RTREE         1
+       { .n_name = "_rt_tables"},
+#define        N_RTTRASH       2
+       { .n_name = "_rttrash" },
+       { .n_name = NULL },
+};
+
 typedef union {
        long    dummy;          /* Helps align structure. */
        struct  sockaddr u_sa;
@@ -113,13 +128,19 @@ typedef union {
 
 static sa_u pt_u;
 
+struct ifmap_entry {
+       char ifname[IFNAMSIZ];
+};
+
+static struct ifmap_entry *ifmap;
+static int ifmap_size;
+
 int    do_rtent = 0;
 struct rtentry rtentry;
 struct radix_node rnode;
 struct radix_mask rmask;
-struct radix_node_head **rt_tables;
 
-int    NewTree = 0;
+int    NewTree = 1;
 
 struct timespec uptime;
 
@@ -127,27 +148,27 @@ static struct sockaddr *kgetsa(struct so
 static void size_cols(int ef, struct radix_node *rn);
 static void size_cols_tree(struct radix_node *rn);
 static void size_cols_rtentry(struct rtentry *rt);
-static void p_tree(struct radix_node *);
-static void p_rtnode(void);
-static void ntreestuff(void);
-static void np_rtentry(struct rt_msghdr *);
+static void p_rtnode_kvm(void);
+static void p_rtable_sysctl(int, int);
+static void p_rtable_kvm(int, int );
+static void p_rtree_kvm(struct radix_node *);
+static void p_rtentry_sysctl(struct rt_msghdr *);
 static void p_sockaddr(struct sockaddr *, struct sockaddr *, int, int);
 static const char *fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask,
     int flags);
 static void p_flags(int, const char *);
 static const char *fmt_flags(int f);
-static void p_rtentry(struct rtentry *);
+static void p_rtentry_kvm(struct rtentry *);
 static void domask(char *, in_addr_t, u_long);
 
 /*
  * Print routing tables.
  */
 void
-routepr(u_long rtree, int fibnum)
+routepr(int fibnum, int af)
 {
-       struct radix_node_head **rnhp, *rnh, head;
        size_t intsize;
-       int fam, numfibs;
+       int numfibs;
 
        intsize = sizeof(int);
        if (fibnum == -1 &&
@@ -157,10 +178,6 @@ routepr(u_long rtree, int fibnum)
                numfibs = 1;
        if (fibnum < 0 || fibnum > numfibs - 1)
                errx(EX_USAGE, "%d: invalid fib", fibnum);
-       rt_tables = calloc(numfibs * (AF_MAX+1),
-           sizeof(struct radix_node_head *));
-       if (rt_tables == NULL)
-               err(EX_OSERR, "memory allocation failed");
        /*
         * Since kernel & userland use different timebase
         * (time_uptime vs time_second) and we are reading kernel memory
@@ -174,55 +191,13 @@ routepr(u_long rtree, int fibnum)
                printf(" (fib: %d)", fibnum);
        printf("\n");
 
-       if (Aflag == 0 && NewTree)
-               ntreestuff();
-       else {
-               if (rtree == 0) {
-                       printf("rt_tables: symbol not in namelist\n");
-                       return;
-               }
-
-               if (kread((u_long)(rtree), (char *)(rt_tables), (numfibs *
-                   (AF_MAX+1) * sizeof(struct radix_node_head *))) != 0)
-                       return;
-               for (fam = 0; fam <= AF_MAX; fam++) {
-                       int tmpfib;
-
-                       switch (fam) {
-                       case AF_INET6:
-                       case AF_INET:
-                               tmpfib = fibnum;
-                               break;
-                       default:
-                               tmpfib = 0;
-                       }
-                       rnhp = (struct radix_node_head **)*rt_tables;
-                       /* Calculate the in-kernel address. */
-                       rnhp += tmpfib * (AF_MAX+1) + fam;
-                       /* Read the in kernel rhn pointer. */
-                       if (kget(rnhp, rnh) != 0)
-                               continue;
-                       if (rnh == NULL)
-                               continue;
-                       /* Read the rnh data. */
-                       if (kget(rnh, head) != 0)
-                               continue;
-                       if (fam == AF_UNSPEC) {
-                               if (Aflag && af == 0) {
-                                       printf("Netmasks:\n");
-                                       p_tree(head.rnh_treetop);
-                               }
-                       } else if (af == AF_UNSPEC || af == fam) {
-                               size_cols(fam, head.rnh_treetop);
-                               pr_family(fam);
-                               do_rtent = 1;
-                               pr_rthdr(fam);
-                               p_tree(head.rnh_treetop);
-                       }
-               }
-       }
+       if (Aflag == 0 && live != 0 && NewTree)
+               p_rtable_sysctl(fibnum, af);
+       else
+               p_rtable_kvm(fibnum, af);
 }
 
+
 /*
  * Print address family header before a section of the routing table.
  */
@@ -288,7 +263,7 @@ static int wid_if;
 static int wid_expire;
 
 static void
-size_cols(int ef __unused, struct radix_node *rn)
+size_cols(int ef, struct radix_node *rn)
 {
        wid_dst = WID_DST_DEFAULT(ef);
        wid_gw = WID_GW_DEFAULT(ef);
@@ -299,7 +274,7 @@ size_cols(int ef __unused, struct radix_
        wid_if = WID_IF_DEFAULT(ef);
        wid_expire = 6;
 
-       if (Wflag)
+       if (Wflag && rn != NULL)
                size_cols_tree(rn);
 }
 
@@ -397,27 +372,14 @@ pr_rthdr(int af1)
 
        if (Aflag)
                printf("%-8.8s ","Address");
-       if (af1 == AF_INET || Wflag) {
-               if (Wflag) {
-                       printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*.*s 
%*s\n",
-                               wid_dst,        wid_dst,        "Destination",
-                               wid_gw,         wid_gw,         "Gateway",
-                               wid_flags,      wid_flags,      "Flags",
-                               wid_refs,       wid_refs,       "Refs",
-                               wid_use,        wid_use,        "Use",
-                               wid_mtu,        wid_mtu,        "Mtu",
-                               wid_if,         wid_if,         "Netif",
-                               wid_expire,                     "Expire");
-               } else {
-                       printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*s\n",
-                               wid_dst,        wid_dst,        "Destination",
-                               wid_gw,         wid_gw,         "Gateway",
-                               wid_flags,      wid_flags,      "Flags",
-                               wid_refs,       wid_refs,       "Refs",
-                               wid_use,        wid_use,        "Use",
-                               wid_if,         wid_if,         "Netif",
-                               wid_expire,                     "Expire");
-               }
+       if (Wflag) {
+               printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*s\n",
+                       wid_dst,        wid_dst,        "Destination",
+                       wid_gw,         wid_gw,         "Gateway",
+                       wid_flags,      wid_flags,      "Flags",
+                       wid_mtu,        wid_mtu,        "Mtu",
+                       wid_if,         wid_if,         "Netif",
+                       wid_expire,                     "Expire");
        } else {
                printf("%-*.*s %-*.*s %-*.*s  %*.*s %*s\n",
                        wid_dst,        wid_dst,        "Destination",
@@ -439,8 +401,77 @@ kgetsa(struct sockaddr *dst)
        return (&pt_u.u_sa);
 }
 
+/*
+ * Print kernel routing tables for given fib
+ * using debugging kvm(3) interface.
+ */
+static void
+p_rtable_kvm(int fibnum, int af)
+{
+       struct radix_node_head **rnhp, *rnh, head;
+       struct radix_node_head **rt_tables;
+       u_long rtree;
+       int fam, af_size;
+
+       kresolve_list(rl);
+       if ((rtree = rl[N_RTREE].n_value) == 0) {
+               printf("rt_tables: symbol not in namelist\n");
+               return;
+       }
+
+       af_size = (AF_MAX + 1) * sizeof(struct radix_node_head *);
+       rt_tables = calloc(1, af_size);
+       if (rt_tables == NULL)
+               err(EX_OSERR, "memory allocation failed");
+
+       if (kread((u_long)(rtree), (char *)(rt_tables) + fibnum * af_size,
+           af_size) != 0)
+               err(EX_OSERR, "error retrieving radix pointers");
+       for (fam = 0; fam <= AF_MAX; fam++) {
+               int tmpfib;
+
+               switch (fam) {
+               case AF_INET6:
+               case AF_INET:
+                       tmpfib = fibnum;
+                       break;
+               default:
+                       tmpfib = 0;
+               }
+               rnhp = (struct radix_node_head **)*rt_tables;
+               /* Calculate the in-kernel address. */
+               rnhp += tmpfib * (AF_MAX + 1) + fam;
+               /* Read the in kernel rhn pointer. */
+               if (kget(rnhp, rnh) != 0)
+                       continue;
+               if (rnh == NULL)
+                       continue;
+               /* Read the rnh data. */
+               if (kget(rnh, head) != 0)
+                       continue;
+               if (fam == AF_UNSPEC) {
+                       if (Aflag && af == 0) {
+                               printf("Netmasks:\n");
+                               p_rtree_kvm(head.rnh_treetop);
+                       }
+               } else if (af == AF_UNSPEC || af == fam) {
+                       size_cols(fam, head.rnh_treetop);
+                       pr_family(fam);
+                       do_rtent = 1;
+                       pr_rthdr(fam);
+                       p_rtree_kvm(head.rnh_treetop);
+               }
+       }
+
+       free(rt_tables);
+}
+
+/*
+ * Print given kernel radix tree using
+ * debugging kvm(3) interface.
+ */
 static void
-p_tree(struct radix_node *rn)
+p_rtree_kvm(struct radix_node *rn)
 {
 
 again:
@@ -457,9 +488,9 @@ again:
                                    rnode.rn_dupedkey ? " =>\n" : "\n");
                } else if (do_rtent) {
                        if (kget(rn, rtentry) == 0) {
-                               p_rtentry(&rtentry);
+                               p_rtentry_kvm(&rtentry);
                                if (Aflag)
-                                       p_rtnode();
+                                       p_rtnode_kvm();
                        }
                } else {
                        p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key),
@@ -471,18 +502,18 @@ again:
        } else {
                if (Aflag && do_rtent) {
                        printf("%-8.8lx ", (u_long)rn);
-                       p_rtnode();
+                       p_rtnode_kvm();
                }
                rn = rnode.rn_right;
-               p_tree(rnode.rn_left);
-               p_tree(rn);
+               p_rtree_kvm(rnode.rn_left);
+               p_rtree_kvm(rn);
        }
 }
 
 char   nbuf[20];
 
 static void
-p_rtnode(void)
+p_rtnode_kvm(void)
 {
        struct radix_mask *rm = rnode.rn_mklist;
 
@@ -522,72 +553,137 @@ p_rtnode(void)
 }
 
 static void
-ntreestuff(void)
+p_rtable_sysctl(int fibnum, int af)
 {
        size_t needed;
-       int mib[6];
+       int mib[7];
        char *buf, *next, *lim;
        struct rt_msghdr *rtm;
+       struct sockaddr *sa;
+       int fam = 0, ifindex = 0, size;
+
+       struct ifaddrs *ifap, *ifa;
+       struct sockaddr_dl *sdl;
+
+       /*
+        * Retrieve interface list at first
+        * since we need #ifindex -> if_xname match
+        */
+       if (getifaddrs(&ifap) != 0)
+               err(EX_OSERR, "getifaddrs");
+
+       for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+               
+               if (ifa->ifa_addr->sa_family != AF_LINK)
+                       continue;
+
+               sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+               ifindex = sdl->sdl_index;
+
+               if (ifindex >= ifmap_size) {
+                       size = roundup(ifindex + 1, 32) *
+                           sizeof(struct ifmap_entry);
+                       if ((ifmap = realloc(ifmap, size)) == NULL)
+                               errx(2, "realloc(%d) failed", size);
+                       memset(&ifmap[ifmap_size], 0,
+                           size - ifmap_size *
+                            sizeof(struct ifmap_entry));
+
+                       ifmap_size = roundup(ifindex + 1, 32);
+               }
+
+               if (*ifmap[ifindex].ifname != '\0')
+                       continue;
+
+               strlcpy(ifmap[ifindex].ifname, ifa->ifa_name, IFNAMSIZ);
+       }
+
+       freeifaddrs(ifap);
 
        mib[0] = CTL_NET;
        mib[1] = PF_ROUTE;
        mib[2] = 0;
-       mib[3] = 0;
+       mib[3] = af;
        mib[4] = NET_RT_DUMP;
        mib[5] = 0;
-       if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
-               err(1, "sysctl: net.route.0.0.dump estimate");
+       mib[6] = fibnum;
+       if (sysctl(mib, 7, NULL, &needed, NULL, 0) < 0) {
+               err(1, "sysctl: net.route.0.%d.dump.%d estimate", af, fibnum);
        }
 
        if ((buf = malloc(needed)) == 0) {
                errx(2, "malloc(%lu)", (unsigned long)needed);
        }
        if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
-               err(1, "sysctl: net.route.0.0.dump");
+               err(1, "sysctl: net.route.0.%d.dump.%d", af, fibnum);
        }
        lim  = buf + needed;
        for (next = buf; next < lim; next += rtm->rtm_msglen) {
                rtm = (struct rt_msghdr *)next;
-               np_rtentry(rtm);
+               /*
+                * Peek inside header to determine AF
+                */
+               sa = (struct sockaddr *)(rtm + 1);
+               if (fam != sa->sa_family) {
+                       fam = sa->sa_family;
+                       size_cols(fam, NULL);
+                       pr_family(fam);
+                       pr_rthdr(fam);
+               }
+               p_rtentry_sysctl(rtm);
        }
 }
 
 static void
-np_rtentry(struct rt_msghdr *rtm)
+p_rtentry_sysctl(struct rt_msghdr *rtm)
 {
        struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
-#ifdef notdef
-       static int masks_done, banner_printed;
-#endif
-       static int old_af;
-       int af1 = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST;
+       char buffer[128];
+       char prettyname[128];
+       sa_u addr, mask, gw;
+       unsigned int l;
+
+#define        GETSA(_s, _f)   { \
+       bzero(&(_s), sizeof(_s)); \
+       if (rtm->rtm_addrs & _f) { \
+               l = roundup(sa->sa_len, sizeof(long)); \
+               memcpy(&(_s), sa, (l > sizeof(_s)) ? sizeof(_s) : l); \
+               sa = (struct sockaddr *)((char *)sa + l); \
+       } \
+}
+
+       GETSA(addr, RTA_DST);
+       GETSA(gw, RTA_GATEWAY);
+       GETSA(mask, RTA_NETMASK);
+       p_sockaddr(&addr.u_sa, &mask.u_sa, rtm->rtm_flags, wid_dst);
+       p_sockaddr(&gw.u_sa, NULL, RTF_HOST, wid_gw);
 
-#ifdef notdef
-       /* for the moment, netmasks are skipped over */
-       if (!banner_printed) {
-               printf("Netmasks:\n");
-               banner_printed = 1;
-       }
-       if (masks_done == 0) {
-               if (rtm->rtm_addrs != RTA_DST ) {
-                       masks_done = 1;
-                       af1 = sa->sa_family;
-               }
-       } else
-#endif
-               af1 = sa->sa_family;
-       if (af1 != old_af) {
-               pr_family(af1);
-               old_af = af1;
+       snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags);
+       p_flags(rtm->rtm_flags, buffer);
+       if (Wflag) {
+               if (rtm->rtm_rmx.rmx_mtu != 0)
+                       printf("%*lu ", wid_mtu, rtm->rtm_rmx.rmx_mtu);
+               else
+                       printf("%*s ", wid_mtu, "");
        }
-       if (rtm->rtm_addrs == RTA_DST)
-               p_sockaddr(sa, NULL, 0, 36);
-       else {
-               p_sockaddr(sa, NULL, rtm->rtm_flags, 16);
-               sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa);
-               p_sockaddr(sa, NULL, 0, 18);
+
+       memset(prettyname, 0, sizeof(prettyname));
+       if (rtm->rtm_index < ifmap_size) {
+               strlcpy(prettyname, ifmap[rtm->rtm_index].ifname,
+                   sizeof(prettyname));
+               if (*prettyname == '\0')
+                       strlcpy(prettyname, "---", sizeof(prettyname));
        }
-       p_flags(rtm->rtm_flags & interesting, "%-6.6s ");
+
+       printf("%*.*s", wid_if, wid_if, prettyname);
+       if (rtm->rtm_rmx.rmx_expire) {
+               time_t expire_time;
+
+               if ((expire_time =
+                   rtm->rtm_rmx.rmx_expire - uptime.tv_sec) > 0)
+                       printf(" %*d", wid_expire, (int)expire_time);
+       }
+
        putchar('\n');
 }
 
@@ -756,7 +852,7 @@ fmt_flags(int f)
 }
 
 static void
-p_rtentry(struct rtentry *rt)
+p_rtentry_kvm(struct rtentry *rt)
 {
        static struct ifnet ifnet, *lastif;
        static char buffer[128];
@@ -775,8 +871,10 @@ p_rtentry(struct rtentry *rt)
        snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags);
        p_flags(rt->rt_flags, buffer);
        if (addr.u_sa.sa_family == AF_INET || Wflag) {
+#if 0
                printf("%*d %*lu ", wid_refs, rt->rt_refcnt,
                                     wid_use, rt->rt_use);
+#endif
                if (Wflag) {
                        if (rt->rt_rmx.rmx_mtu != 0)
                                printf("%*lu ", wid_mtu, rt->rt_rmx.rmx_mtu);
@@ -1009,16 +1107,19 @@ routename6(struct sockaddr_in6 *sa6)
  * Print routing statistics
  */
 void
-rt_stats(u_long rtsaddr, u_long rttaddr)
+rt_stats(void)
 {
        struct rtstat rtstat;
+       u_long rtsaddr, rttaddr;
        int rttrash;
 
-       if (rtsaddr == 0) {
+       kresolve_list(rl);
+
+       if ((rtsaddr = rl[N_RTSTAT].n_value) == 0) {
                printf("rtstat: symbol not in namelist\n");
                return;
        }
-       if (rttaddr == 0) {
+       if ((rttaddr = rl[N_RTTRASH].n_value) == 0) {
                printf("rttrash: symbol not in namelist\n");
                return;
        }
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to