Hi,

to my knowledge there is no easy way to list all active rdomains or
routing tables. Other platforms have "show vrf" or similar commands
for an overview.

Here is my attempt at such a view for OpenBSD:

twister ..in/netstat$ obj/netstat -R
Rdomain   0
  Interfaces: lo0 iwm0 re0 enc0 pflog0
  Routing tables:
      0: Internet       8, Internet6      43, MPLS       0
      3: Internet       1, Internet6       0, MPLS       0
      7: Internet  130309, Internet6   10000, MPLS       0

Rdomain  77
  Interfaces: vether77 lo77
  Routing tables:
     77: Internet       0, Internet6       0, MPLS       0

Rdomain 122
  Interfaces: vether122 lo122 pair122 vether1122 vether1123 vether1124 
vether1125 vether1126 vether1127
  Routing tables:
    122: Internet      24, Internet6       0, MPLS       0

Rdomain 255
  Interfaces: vether255 lo255
  Routing tables:
    255: Internet       3, Internet6       0, MPLS       0

twister ..in/netstat$

Comments? OKs?

Remi


Index: main.c
===================================================================
RCS file: /cvs/src/usr.bin/netstat/main.c,v
retrieving revision 1.116
diff -u -p -r1.116 main.c
--- main.c      28 Apr 2019 17:59:51 -0000      1.116
+++ main.c      30 May 2020 17:59:33 -0000
@@ -127,7 +127,7 @@ main(int argc, char *argv[])
        tableid = getrtable();
 
        while ((ch = getopt(argc, argv,
-           "AaBbc:deFf:ghI:iLlM:mN:np:P:qrsT:tuvW:w:")) != -1)
+           "AaBbc:deFf:ghI:iLlM:mN:np:P:qRrsT:tuvW:w:")) != -1)
                switch (ch) {
                case 'A':
                        Aflag = 1;
@@ -225,6 +225,9 @@ main(int argc, char *argv[])
                case 'q':
                        qflag = 1;
                        break;
+               case 'R':
+                       Rflag = 1;
+                       break;
                case 'r':
                        rflag = 1;
                        break;
@@ -318,6 +321,11 @@ main(int argc, char *argv[])
                        mroutepr();
                if (af == AF_INET6 || af == AF_UNSPEC)
                        mroute6pr();
+               exit(0);
+       }
+
+       if (Rflag) {
+               rdomainpr();
                exit(0);
        }
 
Index: netstat.1
===================================================================
RCS file: /cvs/src/usr.bin/netstat/netstat.1,v
retrieving revision 1.86
diff -u -p -r1.86 netstat.1
--- netstat.1   17 Apr 2019 20:34:21 -0000      1.86
+++ netstat.1   8 Jun 2020 19:21:26 -0000
@@ -74,6 +74,8 @@
 .Op Fl i | I Ar interface
 .Nm
 .Op Fl W Ar interface
+.Nm
+.Op Fl R
 .Sh DESCRIPTION
 The
 .Nm
@@ -267,6 +269,9 @@ Otherwise the states of the matching soc
 Only show interfaces that have seen packets (or bytes if
 .Fl b
 is specified).
+.It Fl R
+Show all rdomains and list associated interfaces and routing tables
+with number of entries.
 .It Fl r
 Show the routing tables.
 The output is explained in more detail below.
Index: netstat.h
===================================================================
RCS file: /cvs/src/usr.bin/netstat/netstat.h,v
retrieving revision 1.74
diff -u -p -r1.74 netstat.h
--- netstat.h   28 Apr 2019 17:59:51 -0000      1.74
+++ netstat.h   7 Jun 2020 22:03:10 -0000
@@ -57,6 +57,7 @@ int   pflag;          /* show given protocol */
 int    Pflag;          /* show given PCB */
 int    qflag;          /* only display non-zero values for output */
 int    rflag;          /* show routing tables (or routing stats) */
+int    Rflag;          /* show rdomain and rtable summary */
 int    sflag;          /* show protocol statistics */
 int    tflag;          /* show i/f watchdog timers */
 int    vflag;          /* be verbose */
@@ -112,6 +113,9 @@ void        rt_stats(void);
 void   pr_rthdr(int, int);
 void   pr_encaphdr(void);
 void   pr_family(int);
+
+void   rdomainpr(void);
+void   rttsummarypr(int);
 
 void   ip6_stats(char *);
 void   icmp6_stats(char *);
Index: route.c
===================================================================
RCS file: /cvs/src/usr.bin/netstat/route.c,v
retrieving revision 1.104
diff -u -p -r1.104 route.c
--- route.c     28 Jun 2019 13:35:02 -0000      1.104
+++ route.c     8 Jun 2020 19:29:58 -0000
@@ -51,6 +51,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <ifaddrs.h>
 
 #include "netstat.h"
 
@@ -346,4 +347,117 @@ rt_stats(void)
            rtstat.rts_unreach, plural(rtstat.rts_unreach));
        printf("\t%u use%s of a wildcard route\n",
            rtstat.rts_wildcard, plural(rtstat.rts_wildcard));
+}
+
+/*
+ * Print rdomain and rtable summary
+ */
+
+void
+rdomainpr(void)
+{
+       struct if_data           *ifd;
+       struct ifaddrs           *ifap, *ifa;
+       struct rt_tableinfo       info;
+
+       int      rtt_dom[RT_TABLEID_MAX+1];
+       int      mib[6], rdom, rtt;
+       size_t   len;
+       char    *old, *rdom_if[RT_TABLEID_MAX+1] = { };
+
+       getifaddrs(&ifap);
+       for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+               if (ifa->ifa_addr->sa_family != AF_LINK)
+                       continue;
+               ifd = ifa->ifa_data;
+               if (rdom_if[ifd->ifi_rdomain] == NULL) {
+                       if (asprintf(&rdom_if[ifd->ifi_rdomain], "%s",
+                           ifa->ifa_name) == -1)
+                               exit(1);
+               } else {
+                       old = rdom_if[ifd->ifi_rdomain];
+                       if (asprintf(&rdom_if[ifd->ifi_rdomain], "%s %s",
+                           old, ifa->ifa_name) == -1)
+                               exit(1);
+                       free(old);
+               }
+       }
+       freeifaddrs(ifap);
+
+       mib[0] = CTL_NET;
+       mib[1] = PF_ROUTE;
+       mib[2] = 0;
+       mib[3] = 0;
+       mib[4] = NET_RT_TABLE;
+
+       len = sizeof(info);
+       for (rtt = 0; rtt <= RT_TABLEID_MAX; rtt++) {
+               mib[5] = rtt;
+               if (sysctl(mib, 6, &info, &len, NULL, 0) == -1)
+                       rtt_dom[rtt] = -1;
+               else
+                       rtt_dom[rtt] = info.rti_domainid;
+       }
+
+       for (rdom = 0; rdom <= RT_TABLEID_MAX; rdom++) {
+               if (rdom_if[rdom] == NULL)
+                       continue;
+               printf("Rdomain %3i\n", rdom);
+               printf("  Interfaces: %s\n", rdom_if[rdom]);
+               printf("  Routing tables:\n");
+               for (rtt = 0; rtt <= RT_TABLEID_MAX; rtt++) {
+                       if (rtt_dom[rtt] == rdom)
+                               rttsummarypr(rtt);
+               }
+               printf("\n");
+               free(rdom_if[rdom]);
+       }
+}
+
+void
+rttsummarypr(int tableid)
+{
+       struct rt_msghdr        *rtm;
+       struct sockaddr         *sa;
+       char    *buf = NULL, *next, *lim = NULL;
+       size_t   needed;
+       int      mib[7], mcnt;
+       int      inet = 0, inet6 = 0, mpls = 0;
+
+       mib[0] = CTL_NET;
+       mib[1] = PF_ROUTE;
+       mib[2] = 0;
+       mib[3] = af;
+       mib[4] = NET_RT_DUMP;
+       mib[5] = 0;
+       mib[6] = tableid;
+       mcnt = 7;
+
+       needed = get_sysctl(mib, mcnt, &buf);
+       lim = buf + needed;
+
+       if (buf) {
+               for (next = buf; next < lim; next += rtm->rtm_msglen) {
+                       rtm = (struct rt_msghdr *)next;
+                       if (rtm->rtm_version != RTM_VERSION)
+                               continue;
+
+                       sa = (struct sockaddr *)((char *)rtm + rtm->rtm_hdrlen);
+                       switch(sa->sa_family) {
+                       case AF_INET:
+                               inet++;
+                               break;
+                       case AF_INET6:
+                               inet6++;
+                               break;
+                       case AF_MPLS:
+                               mpls++;
+                               break;
+                       }
+               }
+       }
+       free(buf);
+
+       printf("    %3i: Internet %7i, Internet6 %7i, MPLS %7i\n", tableid,
+           inet, inet6, mpls);
 }

Reply via email to