On Tue, Jun 09, 2020 at 08:44:42AM +0200, Remi Locherer wrote: > 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?
Why do you think the route counts are needed? You fetch all routing tables to count them in userland. The sysctl for doing that is expensive and especially on systems with full tables will make this command slow. If this is something we really want then the kernel should track and provide the count. Apart from that I think this is a good addition. > 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); > } > -- :wq Claudio