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);
}