hi tech@,

netstat -r with -A/-M (which uses kvm(3)) was broken since in-kernel
routing table implementation was changed to ART-based.

this patch adds support for ART-based implementation in netstat.

kernel and src build ok.

by the way, is "netstat -r with -A on live system" really needed?
it needs kern.allowkmem=1.

Regards,

--
FUKAUMI Naoki

Index: regress/sys/net/rtable/Makefile.inc
===================================================================
RCS file: /cvs/src/regress/sys/net/rtable/Makefile.inc,v
retrieving revision 1.3
diff -u -p -r1.3 Makefile.inc
--- regress/sys/net/rtable/Makefile.inc 27 Jul 2017 13:34:30 -0000      1.3
+++ regress/sys/net/rtable/Makefile.inc 13 Mar 2019 07:03:52 -0000
@@ -9,6 +9,6 @@ SRCS+=          art.c
 CFLAGS+=       -DART
 .endif
 
-CPPFLAGS+=     -I${TOPDIR} -Wall
+CPPFLAGS+=     -I${TOPDIR} -Wall -Wno-macro-redefined
 
 .PATH:         ${TOPDIR} ${TOPDIR}/../../../../sys/net
Index: sys/net/art.c
===================================================================
RCS file: /cvs/src/sys/net/art.c,v
retrieving revision 1.27
diff -u -p -r1.27 art.c
--- sys/net/art.c       28 Feb 2017 09:50:13 -0000      1.27
+++ sys/net/art.c       13 Mar 2019 07:03:53 -0000
@@ -37,37 +37,6 @@
 
 #include <net/art.h>
 
-#define ISLEAF(e)      (((unsigned long)(e) & 1) == 0)
-#define SUBTABLE(e)    ((struct art_table *)((unsigned long)(e) & ~1))
-#define ASNODE(t)      ((struct art_node *)((unsigned long)(t) | 1))
-
-/*
- * Allotment Table.
- */
-struct art_table {
-       struct art_table        *at_parent;     /* Parent table */
-       uint32_t                 at_index;      /* Index in the parent table */
-       uint32_t                 at_minfringe;  /* Index that fringe begins */
-       uint32_t                 at_level;      /* Level of the table */
-       uint8_t                  at_bits;       /* Stride length of the table */
-       uint8_t                  at_offset;     /* Sum of parents' stride len */
-
-       /*
-        * Items stored in the heap are pointers to nodes, in the leaf
-        * case, or tables otherwise.  One exception is index 0 which
-        * is a route counter.
-        */
-       union {
-               struct srp               node;
-               unsigned long            count;
-       } *at_heap;                             /* Array of 2^(slen+1) items */
-};
-#define        at_refcnt       at_heap[0].count/* Refcounter (1 per different 
route) */
-#define        at_default      at_heap[1].node /* Default route (was in parent 
heap) */
-
-/* Heap size for an ART table of stride length ``slen''. */
-#define AT_HEAPSIZE(slen)      ((1 << ((slen) + 1)) * sizeof(void *))
-
 int                     art_bindex(struct art_table *, uint8_t *, int);
 void                    art_allot(struct art_table *at, int, struct art_node *,
                             struct art_node *);
Index: sys/net/art.h
===================================================================
RCS file: /cvs/src/sys/net/art.h,v
retrieving revision 1.17
diff -u -p -r1.17 art.h
--- sys/net/art.h       28 Feb 2017 09:50:13 -0000      1.17
+++ sys/net/art.h       13 Mar 2019 07:03:53 -0000
@@ -20,6 +20,7 @@
 #define _NET_ART_H_
 
 #include <sys/rwlock.h>
+#include <sys/srp.h>
 
 #define ART_MAXLVL     32      /* We currently use 32 levels for IPv6. */
 
@@ -35,6 +36,37 @@ struct art_root {
        uint8_t                  ar_off;        /* Offset of the key in bytes */
        unsigned int             ar_rtableid;   /* ID of this routing table */
 };
+
+#define ISLEAF(e)      (((unsigned long)(e) & 1) == 0)
+#define SUBTABLE(e)    ((struct art_table *)((unsigned long)(e) & ~1))
+#define ASNODE(t)      ((struct art_node *)((unsigned long)(t) | 1))
+
+/*
+ * Allotment Table.
+ */
+struct art_table {
+       struct art_table        *at_parent;     /* Parent table */
+       uint32_t                 at_index;      /* Index in the parent table */
+       uint32_t                 at_minfringe;  /* Index that fringe begins */
+       uint32_t                 at_level;      /* Level of the table */
+       uint8_t                  at_bits;       /* Stride length of the table */
+       uint8_t                  at_offset;     /* Sum of parents' stride len */
+
+       /*
+        * Items stored in the heap are pointers to nodes, in the leaf
+        * case, or tables otherwise.  One exception is index 0 which
+        * is a route counter.
+        */
+       union {
+               struct srp               node;
+               unsigned long            count;
+       } *at_heap;                             /* Array of 2^(slen+1) items */
+};
+#define        at_refcnt       at_heap[0].count/* Refcounter (1 per different 
route) */
+#define        at_default      at_heap[1].node /* Default route (was in parent 
heap) */
+
+/* Heap size for an ART table of stride length ``slen''. */
+#define AT_HEAPSIZE(slen)      ((1 << ((slen) + 1)) * sizeof(void *))
 
 /*
  * Forward declaration needed for the list of mpath routes
Index: sys/net/route.h
===================================================================
RCS file: /cvs/src/sys/net/route.h,v
retrieving revision 1.174
diff -u -p -r1.174 route.h
--- sys/net/route.h     13 Feb 2019 23:47:42 -0000      1.174
+++ sys/net/route.h     13 Mar 2019 07:03:54 -0000
@@ -93,12 +93,8 @@ struct rt_metrics {
  */
 
 struct rtentry {
-#if !defined(_KERNEL) && !defined(ART)
-       struct  radix_node rt_nodes[2]; /* tree glue, and other values */
-#else
        struct sockaddr *rt_dest;       /* destination */
        SRPL_ENTRY(rtentry) rt_next;    /* Next multipath entry to our dst. */
-#endif
        struct sockaddr *rt_gateway;    /* value */
        struct ifaddr   *rt_ifa;        /* the answer: interface addr to use */
        caddr_t          rt_llinfo;     /* pointer to link level info cache or
@@ -115,9 +111,7 @@ struct rtentry {
        unsigned int     rt_ifidx;      /* the answer: interface to use */
        unsigned int     rt_flags;      /* up/down?, host/net */
        int              rt_refcnt;     /* # held references */
-#if defined(_KERNEL) || defined(ART)
        int              rt_plen;       /* prefix length */
-#endif
        uint16_t         rt_labelid;    /* route label ID */
        uint8_t          rt_priority;   /* routing priority to use */
 };
Index: sys/net/rtable.h
===================================================================
RCS file: /cvs/src/sys/net/rtable.h,v
retrieving revision 1.22
diff -u -p -r1.22 rtable.h
--- sys/net/rtable.h    23 Nov 2018 16:24:11 -0000      1.22
+++ sys/net/rtable.h    13 Mar 2019 07:03:54 -0000
@@ -19,20 +19,6 @@
 #ifndef        _NET_RTABLE_H_
 #define        _NET_RTABLE_H_
 
-#if !defined(_KERNEL) && !defined(ART)
-
-/*
- * Traditional BSD routing table implementation based on a radix tree.
- */
-#include <net/radix.h>
-
-#define        rt_key(rt)      (((struct sockaddr *)(rt)->rt_nodes[0].rn_key))
-#define        rt_mask(rt)     (((struct sockaddr *)(rt)->rt_nodes[0].rn_mask))
-#define        rt_plen(rt)     (rtable_satoplen(rt_key(rt)->sa_family, 
rt_mask(rt)))
-#define        RT_ROOT(rt)     ((rt)->rt_nodes[0].rn_flags & RNF_ROOT)
-
-#else /* defined(_KERNEL) || defined(ART) */
-
 /*
  * Newer routing table implementation based on ART (Allotment Routing
  * Table).
@@ -42,8 +28,6 @@
 #define        rt_key(rt)      ((rt)->rt_dest)
 #define        rt_plen(rt)     ((rt)->rt_plen)
 #define        RT_ROOT(rt)     (0)
-
-#endif /* defined(_KERNEL) || defined(ART) */
 
 int             rtable_satoplen(sa_family_t, struct sockaddr *);
 
Index: sys/sys/srp.h
===================================================================
RCS file: /cvs/src/sys/sys/srp.h,v
retrieving revision 1.13
diff -u -p -r1.13 srp.h
--- sys/sys/srp.h       20 Nov 2016 11:40:58 -0000      1.13
+++ sys/sys/srp.h       13 Mar 2019 07:03:54 -0000
@@ -70,6 +70,13 @@ struct srpl {
        struct srp              sl_head;
 };
 
+#define SRPL_HEAD(name, type)          struct srpl
+
+#define SRPL_ENTRY(type)                                               \
+struct {                                                               \
+       struct srp              se_next;                                \
+}
+
 #ifdef _KERNEL
 
 void            srp_startup(void);
@@ -102,13 +109,6 @@ void               srpl_rc_init(struct srpl_rc *, voi
                    void (*)(void *, void *), void *);
 
 #define SRPL_INIT(_sl)                 srp_init(&(_sl)->sl_head)
-
-#define SRPL_HEAD(name, type)          struct srpl
-
-#define SRPL_ENTRY(type)                                               \
-struct {                                                               \
-       struct srp              se_next;                                \
-}
 
 #define SRPL_FIRST(_sr, _sl)           srp_enter((_sr), &(_sl)->sl_head)
 #define SRPL_NEXT(_sr, _e, _ENTRY)     srp_enter((_sr), &(_e)->_ENTRY.se_next)
Index: usr.bin/netstat/main.c
===================================================================
RCS file: /cvs/src/usr.bin/netstat/main.c,v
retrieving revision 1.115
diff -u -p -r1.115 main.c
--- usr.bin/netstat/main.c      5 Mar 2019 06:47:12 -0000       1.115
+++ usr.bin/netstat/main.c      13 Mar 2019 07:03:54 -0000
@@ -54,14 +54,12 @@
 #include "netstat.h"
 
 struct nlist nl[] = {
-#define N_RTREE                0
-       { "_rt_tables"},
-#define N_RTMASK       1
-       { "_mask_rnhead" },
-#define N_AF2RTAFIDX   2
-       { "_af2rtafidx" },
-#define N_RTBLIDMAX    3
-       { "_rtbl_id_max" },
+#define N_AFMAP                0
+       { "_afmap"},
+#define N_AF2IDX       1
+       { "_af2idx" },
+#define N_AF2IDXMAX    2
+       { "_af2idx_max" },
 
        { "" }
 };
@@ -104,7 +102,7 @@ struct protox *protoprotox[] = {
 static void usage(void);
 static struct protox *name2protox(char *);
 static struct protox *knownname(char *);
-u_int gettable(const char *);
+void gettable(u_int);
 
 kvm_t *kvmd;
 
@@ -168,8 +166,6 @@ main(int argc, char *argv[])
                                af = AF_UNIX;
                        else if (strcmp(optarg, "mpls") == 0)
                                af = AF_MPLS;
-                       else if (strcmp(optarg, "mask") == 0)
-                               af = 0xff;
                        else {
                                (void)fprintf(stderr,
                                    "%s: %s: unknown address family\n",
@@ -236,8 +232,10 @@ main(int argc, char *argv[])
                        ++sflag;
                        break;
                case 'T':
+                       tableid = strtonum(optarg, 0, RT_TABLEID_MAX, &errstr);
+                       if (errstr)
+                               errx(1, "invalid table id: %s", errstr);
                        Tflag = 1;
-                       tableid = gettable(optarg);
                        break;
                case 't':
                        tflag = 1;
@@ -341,11 +339,13 @@ main(int argc, char *argv[])
                        errx(1, "no namelist");
        }
 
+       if (!need_nlist && Tflag)
+               gettable(tableid);
+
        if (rflag) {
                if (Aflag || nlistf != NULL || memf != NULL)
-                       routepr(nl[N_RTREE].n_value, nl[N_RTMASK].n_value,
-                           nl[N_AF2RTAFIDX].n_value, nl[N_RTBLIDMAX].n_value,
-                           tableid);
+                       routepr(nl[N_AFMAP].n_value, nl[N_AF2IDX].n_value,
+                           nl[N_AF2IDXMAX].n_value, tableid);
                else
                        p_rttables(af, tableid);
                exit(0);
@@ -458,18 +458,12 @@ usage(void)
        exit(1);
 }
 
-u_int
-gettable(const char *s)
+void
+gettable(u_int tableid)
 {
-       const char *errstr;
        struct rt_tableinfo info;
        int mib[6];
        size_t len;
-       u_int tableid;
-
-       tableid = strtonum(s, 0, RT_TABLEID_MAX, &errstr);
-       if (errstr)
-               errx(1, "invalid table id: %s", errstr);
 
        mib[0] = CTL_NET;
        mib[1] = PF_ROUTE;
@@ -481,6 +475,4 @@ gettable(const char *s)
        len = sizeof(info);
        if (sysctl(mib, 6, &info, &len, NULL, 0) == -1)
                err(1, "routing table %d", tableid);
-
-       return (tableid);
 }
Index: usr.bin/netstat/netstat.h
===================================================================
RCS file: /cvs/src/usr.bin/netstat/netstat.h,v
retrieving revision 1.73
diff -u -p -r1.73 netstat.h
--- usr.bin/netstat/netstat.h   4 Mar 2019 21:32:26 -0000       1.73
+++ usr.bin/netstat/netstat.h   13 Mar 2019 07:03:54 -0000
@@ -138,7 +138,7 @@ char        *routename4(in_addr_t);
 char   *netname(struct sockaddr *, struct sockaddr *);
 char   *netname4(in_addr_t, in_addr_t);
 char   *mpls_op(u_int32_t);
-void   routepr(u_long, u_long, u_long, u_long, u_int);
+void   routepr(u_long, u_long, u_long, u_int);
 
 void   nsprotopr(u_long, char *);
 
Index: usr.bin/netstat/route.c
===================================================================
RCS file: /cvs/src/usr.bin/netstat/route.c,v
retrieving revision 1.101
diff -u -p -r1.101 route.c
--- usr.bin/netstat/route.c     15 Sep 2016 01:01:07 -0000      1.101
+++ usr.bin/netstat/route.c     13 Mar 2019 07:03:54 -0000
@@ -55,95 +55,90 @@
 
 #include "netstat.h"
 
-/* alignment constraint for routing socket */
-#define ROUNDUP(a) \
-       ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
-#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
-
-struct radix_node_head ***rt_head;
-struct radix_node_head ***rnt;
-struct radix_node_head *rt_tables[AF_MAX+1];   /* provides enough space */
-u_int8_t                 af2rtafidx[AF_MAX+1];
-
 static union {
        struct          sockaddr u_sa;
        u_int32_t       u_data[64];
        int             u_dummy;        /* force word-alignment */
 } pt_u;
 
-int    do_rtent = 0;
 struct rtentry rtentry;
-struct radix_node rnode;
-struct radix_mask rmask;
 
 static struct sockaddr *kgetsa(struct sockaddr *);
-static void p_tree(struct radix_node *);
-static void p_rtnode(void);
-static void p_rtflags(u_char);
+static struct sockaddr *plentosa(sa_family_t, int, struct sockaddr *);
+static struct art_node *getdefault(struct art_table *);
+static void p_table(struct art_table *);
+static void p_artnode(struct art_node *);
 static void p_krtentry(struct rtentry *);
 
 /*
  * Print routing tables.
  */
 void
-routepr(u_long rtree, u_long mtree, u_long af2idx, u_long rtbl_id_max,
-    u_int tableid)
+routepr(u_long afmap, u_long af2idx, u_long af2idx_max, u_int tableid)
 {
-       struct radix_node_head *rnh, head;
-       int i, idxmax = 0;
-       u_int rtidxmax;
+       struct art_root ar;
+       struct art_node *node;
+       struct srp *afm_head, *afm;
+       struct {
+               unsigned int    limit;
+               void          **tbl;
+       } map;
+       void **tbl;
+       int i;
+       uint8_t af2i[AF_MAX+1];
+       uint8_t af2i_max;
 
        printf("Routing tables\n");
 
-       if (rtree == 0 || af2idx == 0) {
-               printf("rt_tables: symbol not in namelist\n");
+       if (afmap == 0 || af2idx == 0 || af2idx_max == 0) {
+               printf("symbol not in namelist\n");
                return;
        }
 
-       kread((u_long)rtree, &rt_head, sizeof(rt_head));
-       kread((u_long)rtbl_id_max, &rtidxmax, sizeof(rtidxmax));
-       kread((long)af2idx, &af2rtafidx, sizeof(af2rtafidx));
-
-       for (i = 0; i <= AF_MAX; i++) {
-               if (af2rtafidx[i] > idxmax)
-                       idxmax = af2rtafidx[i];
-       }
+       kread(afmap, &afm_head, sizeof(afm_head));
+       kread(af2idx, af2i, sizeof(af2i));
+       kread(af2idx_max, &af2i_max, sizeof(af2i_max));
 
-       if ((rnt = calloc(rtidxmax + 1, sizeof(struct radix_node_head **))) ==
-           NULL)
+       if ((afm = calloc(af2i_max + 1, sizeof(*afm))) == NULL)
                err(1, NULL);
 
-       kread((u_long)rt_head, rnt, (rtidxmax + 1) *
-           sizeof(struct radix_node_head **));
-       if (tableid > rtidxmax || rnt[tableid] == NULL) {
-               printf("Bad table %u\n", tableid);
-               return;
-       }
-       kread((u_long)rnt[tableid], rt_tables, (idxmax + 1) * sizeof(rnh));
+       kread((u_long)afm_head, afm, (af2i_max + 1) * sizeof(*afm));
 
-       for (i = 0; i <= AF_MAX; i++) {
-               if (i == AF_UNSPEC) {
-                       if (Aflag && (af == AF_UNSPEC || af == 0xff)) {
-                               kread(mtree, &rnh, sizeof(rnh));
-                               kread((u_long)rnh, &head, sizeof(head));
-                               printf("Netmasks:\n");
-                               p_tree(head.rnh_treetop);
-                       }
+       for (i = 1; i <= AF_MAX; i++) {
+               if (af != AF_UNSPEC && af != i)
                        continue;
-               }
-               if (af2rtafidx[i] == 0)
-                       /* no table for this AF */
+               if (af2i[i] == 0 || afm[af2i[i]].ref == NULL)
                        continue;
-               if ((rnh = rt_tables[af2rtafidx[i]]) == NULL)
+
+               kread((u_long)afm[af2i[i]].ref, &map, sizeof(map));
+               if (tableid >= map.limit)
                        continue;
-               kread((u_long)rnh, &head, sizeof(head));
-               if (af == AF_UNSPEC || af == i) {
-                       pr_family(i);
-                       do_rtent = 1;
-                       pr_rthdr(i, Aflag);
-                       p_tree(head.rnh_treetop);
-               }
+
+               if ((tbl = calloc(map.limit, sizeof(*tbl))) == NULL)
+                       err(1, NULL);
+
+               kread((u_long)map.tbl, tbl, map.limit * sizeof(*tbl));
+               if (tbl[tableid] == NULL)
+                       continue;
+
+               kread((u_long)tbl[tableid], &ar, sizeof(ar));
+
+               free(tbl);
+
+               if (ar.ar_root.ref == NULL)
+                       continue;
+
+               pr_family(i);
+               pr_rthdr(i, Aflag);
+
+               node = getdefault(ar.ar_root.ref);
+               if (node != NULL)
+                       p_artnode(node);
+
+               p_table(ar.ar_root.ref);
        }
+
+       free(afm);
 }
 
 static struct sockaddr *
@@ -156,106 +151,128 @@ kgetsa(struct sockaddr *dst)
        return (&pt_u.u_sa);
 }
 
-static void
-p_tree(struct radix_node *rn)
+static struct sockaddr *
+plentosa(sa_family_t af, int plen, struct sockaddr *sa_mask)
 {
+       struct sockaddr_in *sin = (struct sockaddr_in *)sa_mask;
+       struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa_mask;
+       uint8_t *p;
+       int i;
+
+       if (plen < 0)
+               return (NULL);
+
+       memset(sa_mask, 0, sizeof(struct sockaddr_storage));
+
+       switch (af) {
+       case AF_INET:
+               if (plen > 32)
+                       return (NULL);
+               sin->sin_family = AF_INET;
+               sin->sin_len = sizeof(struct sockaddr_in);
+               memset(&sin->sin_addr, 0, sizeof(sin->sin_addr));
+               p = (uint8_t *)&sin->sin_addr;
+               break;
+       case AF_INET6:
+               if (plen > 128)
+                       return (NULL);
+               sin6->sin6_family = AF_INET6;
+               sin6->sin6_len = sizeof(struct sockaddr_in6);
+               memset(&sin6->sin6_addr.s6_addr, 0, 
sizeof(sin6->sin6_addr.s6_addr));
+               p = sin6->sin6_addr.s6_addr;
+               break;
+       default:
+               return (NULL);
+       }
+
+       for (i = 0; i < plen / 8; i++)
+               p[i] = 0xff;
+       if (plen % 8)
+               p[i] = (0xff00 >> (plen % 8)) & 0xff;
 
-again:
-       kread((u_long)rn, &rnode, sizeof(rnode));
-       if (rnode.rn_b < 0) {
-               if (Aflag)
-                       printf("%-16p ", rn);
-               if (rnode.rn_flags & RNF_ROOT) {
-                       if (Aflag)
-                               printf("(root node)%s",
-                                   rnode.rn_dupedkey ? " =>\n" : "\n");
-               } else if (do_rtent) {
-                       kread((u_long)rn, &rtentry, sizeof(rtentry));
-                       p_krtentry(&rtentry);
-                       if (Aflag)
-                               p_rtnode();
-               } else {
-                       p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key),
-                           0, 0, 44);
-                       putchar('\n');
-               }
-               if ((rn = rnode.rn_dupedkey))
-                       goto again;
-       } else {
-               if (Aflag && do_rtent) {
-                       printf("%-16p ", rn);
-                       p_rtnode();
-               }
-               rn = rnode.rn_r;
-               p_tree(rnode.rn_l);
-               p_tree(rn);
-       }
+       return (sa_mask);
 }
 
-static void
-p_rtflags(u_char flags)
+static struct art_node *
+getdefault(struct art_table *at)
 {
-       putchar('<');
-       if (flags & RNF_NORMAL)
-               putchar('N');
-       if (flags & RNF_ROOT)
-               putchar('R');
-       if (flags & RNF_ACTIVE)
-               putchar('A');
-       if (flags & ~(RNF_NORMAL | RNF_ROOT | RNF_ACTIVE))
-               printf("/0x%02x", flags);
-       putchar('>');
-}
+       struct art_node *node;
+       struct art_table table;
+       union {
+               struct srp               node;
+               unsigned long            count;
+       } *heap;
+
+       kread((u_long)at, &table, sizeof(table));
+       heap = calloc(1, AT_HEAPSIZE(table.at_bits));
+       kread((u_long)table.at_heap, heap, AT_HEAPSIZE(table.at_bits));
+
+       node = heap[1].node.ref;
 
-char   nbuf[25];
+       free(heap);
+
+       return (node);
+}
 
 static void
-p_rtnode(void)
+p_table(struct art_table *at)
 {
-       struct radix_mask *rm = rnode.rn_mklist;
-
-       if (rnode.rn_b < 0) {
-               snprintf(nbuf, sizeof nbuf, " => %p", rnode.rn_dupedkey);
-               printf("\t  (%p)%s", rnode.rn_p, rnode.rn_dupedkey ? nbuf : "");
-               if (rnode.rn_mask) {
-                       printf(" mask ");
-                       p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask),
-                           0, 0, -1);
-               } else if (rm == NULL) {
-                       putchar('\n');
-                       return;
+       struct art_node *next, *node;
+       struct art_table *nat, table;
+       union {
+               struct srp               node;
+               unsigned long            count;
+       } *heap;
+       int i, j;
+
+       kread((u_long)at, &table, sizeof(table));
+       heap = calloc(1, AT_HEAPSIZE(table.at_bits));
+       kread((u_long)table.at_heap, heap, AT_HEAPSIZE(table.at_bits));
+
+       for (j = 1; j < table.at_minfringe; j += 2) {
+               for (i = (j > 2) ? j : 2; i < table.at_minfringe; i <<= 1) {
+                       next = heap[i >> 1].node.ref;
+                       node = heap[i].node.ref;
+                       if (node != NULL && node != next)
+                               p_artnode(node);
                }
-       } else {
-               snprintf(nbuf, sizeof nbuf, "(%d)", rnode.rn_b);
-               printf("%6.6s (%p) %16p : %16p", nbuf,
-                   rnode.rn_p, rnode.rn_l, rnode.rn_r);
-       }
-
-       putchar(' ');
-       p_rtflags(rnode.rn_flags);
-
-       while (rm) {
-               kread((u_long)rm, &rmask, sizeof(rmask));
-               snprintf(nbuf, sizeof nbuf, " %d refs, ", rmask.rm_refs);
-               printf("\n\tmk = %p {(%d),%s", rm, -1 - rmask.rm_b,
-                   rmask.rm_refs ? nbuf : " ");
-               p_rtflags(rmask.rm_flags);
-               printf(", ");
-               if (rmask.rm_flags & RNF_NORMAL) {
-                       struct radix_node rnode_aux;
-
-                       printf("leaf = %p ", rmask.rm_leaf);
-                       kread((u_long)rmask.rm_leaf, &rnode_aux, 
sizeof(rnode_aux));
-                       p_sockaddr(kgetsa((struct sockaddr *)rnode_aux.rn_mask),
-                           0, 0, -1);
+       }
+
+       for (i = table.at_minfringe; i < table.at_minfringe << 1; i++) {
+               next = heap[i >> 1].node.ref;
+               node = heap[i].node.ref;
+               if (!ISLEAF(node)) {
+                       nat = SUBTABLE(node);
+                       node = getdefault(nat);
                } else
-                       p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask),
-                           0, 0, -1);
-               putchar('}');
-               if ((rm = rmask.rm_mklist))
-                       printf(" ->");
+                       nat = NULL;
+
+               if (node != NULL && node != next)
+                       p_artnode(node);
+
+               if (nat != NULL)
+                       p_table(nat);
+       }
+
+       free(heap);
+}
+
+static void
+p_artnode(struct art_node *an)
+{
+       struct art_node node;
+       struct rtentry *rt;
+
+       kread((u_long)an, &node, sizeof(node));
+       rt = node.an_rtlist.sl_head.ref;
+
+       while (rt != NULL) {
+               kread((u_long)rt, &rtentry, sizeof(rtentry));
+               if (Aflag)
+                       printf("%-16p ", rt);
+               p_krtentry(&rtentry);
+               rt = rtentry.rt_next.se_next.ref;
        }
-       putchar('\n');
 }
 
 static void
@@ -274,28 +291,21 @@ p_krtentry(struct rtentry *rt)
                return;
        }
 
-       if (rt_mask(rt)) {
-               bcopy(kgetsa(rt_mask(rt)), mask, sizeof(struct sockaddr));
-               if (sa->sa_len > sizeof(struct sockaddr))
-                       bcopy(kgetsa(rt_mask(rt)), mask, sa->sa_len);
-       } else
-               mask = 0;
+       mask = plentosa(sa->sa_family, rt_plen(rt), mask);
 
        p_addr(sa, mask, rt->rt_flags);
        p_gwaddr(kgetsa(rt->rt_gateway), sa->sa_family);
        p_flags(rt->rt_flags, "%-6.6s ");
-       printf("%5u %8lld ", rt->rt_refcnt, rt->rt_use);
+       printf("%5u %8lld ", rt->rt_refcnt - 1, rt->rt_use);
        if (rt->rt_rmx.rmx_mtu)
                printf("%5u ", rt->rt_rmx.rmx_mtu);
        else
                printf("%5s ", "-");
        putchar((rt->rt_rmx.rmx_locks & RTV_MTU) ? 'L' : ' ');
-       printf("  %2d", rt->rt_priority);
+       printf("  %2d", rt->rt_priority & RTP_MASK);
 
-       if (rt->rt_ifidx != 0) {
-               printf(" if%d%s", rt->rt_ifidx,
-                   rt->rt_nodes[0].rn_dupedkey ? " =>" : "");
-       }
+       if (rt->rt_ifidx != 0)
+               printf(" if%d", rt->rt_ifidx);
        putchar('\n');
        if (vflag)
                printf("\texpire   %10lld%c\n",

Reply via email to