On Mon, Jun 08, 2020 at 10:10:17PM +0200, Remi Locherer wrote:
> 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:

Updated diff with small changes:
- Print inet instead of Internet (input deraadt)
- Removed padding before rdomain id.
- Changed man page wording.

twister ..in/netstat$ obj/netstat -R
Rdomain 0
  Interfaces: lo0 iwm0 re0 enc0 pflog0 mpe0
  Routing tables:
      0: inet       8, inet6      45, mpls       1
      3: inet       1, inet6       0, mpls       0
      7: inet  130309, inet6   10000, mpls       0

Rdomain 77
  Interfaces: vether77 lo77
  Routing tables:
     77: inet       0, inet6       0, mpls       0

Rdomain 122
  Interfaces: vether122 lo122 pair122 vether1122 vether1123 vether1124 
vether1125 vether1126 vether1127
  Routing tables:
    122: inet      24, inet6       0, mpls       0

Rdomain 255
  Interfaces: vether255 lo255
  Routing tables:
    255: inet       3, inet6       0, mpls       0

twister ..in/netstat$

OK?


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 20:42:46 -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,8 @@ Otherwise the states of the matching soc
 Only show interfaces that have seen packets (or bytes if
 .Fl b
 is specified).
+.It Fl R
+List all rdomains with associated interfaces and routing tables.
 .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     9 Jun 2020 06:36:29 -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 %i\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: inet %7i, inet6 %7i, mpls %7i\n", tableid,
+           inet, inet6, mpls);
 }

Reply via email to