Author: hrs
Date: Sat Nov 17 19:54:23 2012
New Revision: 243185
URL: http://svnweb.freebsd.org/changeset/base/243185

Log:
  Add -fib modifier to specify FIB number.  The FIB number can be in a
  comma-separated list and/or range specification:
  
   # route add -inet 192.0.2.0/24 198.51.100.1 -fib 1,3-5,6
  
  Although all of the subcommands supports the modifier, "monitor" does not
  support the list or range specification at this moment.
  
  Reviewed by:  bz

Modified:
  head/sbin/route/keywords
  head/sbin/route/route.8
  head/sbin/route/route.c

Modified: head/sbin/route/keywords
==============================================================================
--- head/sbin/route/keywords    Sat Nov 17 18:11:10 2012        (r243184)
+++ head/sbin/route/keywords    Sat Nov 17 19:54:23 2012        (r243185)
@@ -10,6 +10,7 @@ del
 delete
 dst
 expire
+fib
 flush
 gateway
 genmask

Modified: head/sbin/route/route.8
==============================================================================
--- head/sbin/route/route.8     Sat Nov 17 18:11:10 2012        (r243184)
+++ head/sbin/route/route.8     Sat Nov 17 19:54:23 2012        (r243185)
@@ -28,7 +28,7 @@
 .\"     @(#)route.8    8.3 (Berkeley) 3/19/94
 .\" $FreeBSD$
 .\"
-.Dd March 24, 2012
+.Dd November 17, 2012
 .Dt ROUTE 8
 .Os
 .Sh NAME
@@ -118,16 +118,14 @@ The monitor command has the syntax:
 .Bd -ragged -offset indent -compact
 .Nm
 .Op Fl n
-.Cm monitor
+.Cm monitor Op Fl fib Ar number
 .Ed
 .Pp
 The flush command has the syntax:
 .Pp
 .Bd -ragged -offset indent -compact
 .Nm
-.Op Fl n
-.Cm flush
-.Op Ar family
+.Oo Fl n Cm flush Oc Oo Ar family Oc Op Fl fib Ar number
 .Ed
 .Pp
 If the
@@ -144,6 +142,11 @@ or
 .Fl inet
 modifiers, only routes having destinations with addresses in the
 delineated family will be deleted.
+When a
+.Fl fib
+option is specified, the operation will be applied to
+the specified FIB
+.Pq routing table .
 .Pp
 The other commands have the following syntax:
 .Pp
@@ -154,6 +157,7 @@ The other commands have the following sy
 .Op Fl net No \&| Fl host
 .Ar destination gateway
 .Op Ar netmask
+.Op Fl fib Ar number
 .Ed
 .Pp
 where
@@ -210,9 +214,15 @@ A
 .Ar destination
 of
 .Ar default
-is a synonym for
-.Fl net Li 0.0.0.0 ,
-which is the default route.
+is a synonym for the default route.
+For
+.Li IPv4
+it is
+.Fl net Fl inet Li 0.0.0.0 ,
+and for
+.Li IPv6
+it is
+.Fl net Fl inet6 Li :: .
 .Pp
 If the destination is directly reachable
 via an interface requiring
@@ -314,6 +324,33 @@ specify that all ensuing metrics may be 
 .Fl lockrest
 meta-modifier.
 .Pp
+The optional modifier
+.Fl fib Ar number
+specifies that the command will be applied to a non-default FIB.
+The
+.Ar number
+must be smaller than the
+.Va net.fibs
+.Xr sysctl 8
+MIB.
+When this modifier is not specified,
+or a negative number is specified,
+the default FIB shown in the
+.Va net.my_fibnum
+.Xr sysctl 8
+MIB will be used.
+.Pp
+The
+.Ar number
+allows multiple FIBs by a comma-separeted list and/or range
+specification.
+The
+.Qq Fl fib Li 2,4,6
+means the FIB number 2, 4, and 6.
+The
+.Qq Fl fib Li 1,3-5,6
+means the 1, 3, 4, 5, and 6.
+.Pp
 In a
 .Cm change
 or

Modified: head/sbin/route/route.c
==============================================================================
--- head/sbin/route/route.c     Sat Nov 17 18:11:10 2012        (r243184)
+++ head/sbin/route/route.c     Sat Nov 17 19:54:23 2012        (r243185)
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/ioctl.h>
 #include <sys/sysctl.h>
 #include <sys/types.h>
+#include <sys/queue.h>
 
 #include <net/if.h>
 #include <net/route.h>
@@ -77,7 +78,6 @@ struct keytab {
        {0, 0}
 };
 
-struct ortentry route;
 union  sockunion {
        struct  sockaddr sa;
        struct  sockaddr_in sin;
@@ -99,11 +99,14 @@ int locking, lockrest, debugonly;
 struct rt_metrics rt_metrics;
 u_long  rtm_inits;
 uid_t  uid;
+static int     defaultfib;
+static int     numfibs;
 
 static int     atalk_aton(const char *, struct at_addr *);
 static char    *atalk_ntoa(struct at_addr);
 static void    bprintf(FILE *, int, u_char *);
 static void    flushroutes(int argc, char *argv[]);
+static int     flushroutes_fib(int);
 static int     getaddr(int, char *, struct hostent **);
 static int     keyword(const char *);
 static void    inet_makenetandmask(u_long, struct sockaddr_in *, u_long);
@@ -112,21 +115,36 @@ static int inet6_makenetandmask(struct s
 #endif
 static void    interfaces(void);
 static void    mask_addr(void);
-static void    monitor(void);
+static void    monitor(int, char*[]);
 static const char      *netname(struct sockaddr *);
 static void    newroute(int, char **);
+static int     newroute_fib(int, char *, int);
 static void    pmsg_addrs(char *, int, size_t);
 static void    pmsg_common(struct rt_msghdr *, size_t);
 static int     prefixlen(const char *);
-static void    print_getmsg(struct rt_msghdr *, int);
+static void    print_getmsg(struct rt_msghdr *, int, int);
 static void    print_rtmsg(struct rt_msghdr *, size_t);
 static const char      *routename(struct sockaddr *);
-static int     rtmsg(int, int);
+static int     rtmsg(int, int, int);
 static void    set_metric(char *, int);
+static int     set_sofib(int);
+static int     set_procfib(int);
 static void    sockaddr(char *, struct sockaddr *);
 static void    sodump(sup, const char *);
 extern char *iso_ntoa(void);
 
+struct fibl {
+       TAILQ_ENTRY(fibl)       fl_next;
+
+       int     fl_num;
+       int     fl_error;
+       int     fl_errno;
+};
+TAILQ_HEAD(fibl_head_t, fibl) fibl_head;
+
+static int     fiboptlist_csv(const char *, struct fibl_head_t *);
+static int     fiboptlist_range(const char *, struct fibl_head_t *);
+
 static void usage(const char *) __dead2;
 
 void
@@ -144,6 +162,7 @@ int
 main(int argc, char **argv)
 {
        int ch;
+       size_t len;
 
        if (argc < 2)
                usage(NULL);
@@ -180,6 +199,17 @@ main(int argc, char **argv)
                s = socket(PF_ROUTE, SOCK_RAW, 0);
        if (s < 0)
                err(EX_OSERR, "socket");
+
+       len = sizeof(numfibs);
+       if (sysctlbyname("net.fibs", (void *)&numfibs, &len, NULL, 0) == -1)
+               numfibs = -1;
+
+       len = sizeof(defaultfib);
+       if (numfibs != -1 &&
+           sysctlbyname("net.my_fibnum", (void *)&defaultfib, &len, NULL,
+               0) == -1)
+               defaultfib = -1;
+
        if (*argv != NULL)
                switch (keyword(*argv)) {
                case K_GET:
@@ -195,7 +225,7 @@ main(int argc, char **argv)
                        /* NOTREACHED */
 
                case K_MONITOR:
-                       monitor();
+                       monitor(argc, argv);
                        /* NOTREACHED */
 
                case K_FLUSH:
@@ -207,6 +237,124 @@ main(int argc, char **argv)
        /* NOTREACHED */
 }
 
+static int
+set_sofib(int fib)
+{
+
+       if (fib < 0)
+               return (0);
+       return (setsockopt(s, SOL_SOCKET, SO_SETFIB, (void *)&fib,
+           sizeof(fib)));
+}
+
+static int
+set_procfib(int fib)
+{
+       
+       if (fib < 0)
+               return (0);
+       return (setfib(fib));
+}
+
+static int
+fiboptlist_range(const char *arg, struct fibl_head_t *flh)
+{
+       struct fibl *fl;
+       char *str, *token, *endptr;
+       int fib[2], i, error;
+
+       str = strdup(arg);
+       error = 0;
+       i = 0;
+       while ((token = strsep(&str, "-")) != NULL) {
+               switch (i) {
+               case 0:
+               case 1:
+                       fib[i] = strtol(token, &endptr, 0);
+                       if (*endptr != '\0' || (fib[i] == 0 &&
+                           (errno == EINVAL || errno == ERANGE)))
+                               error = 1;
+                       break;
+               default:
+                       error = 1;
+               }
+               if (error)
+                       goto fiboptlist_range_ret;
+               i++;
+       }
+       if (fib[0] >= fib[1]) {
+               error = 1;
+               goto fiboptlist_range_ret;
+       }
+       for (i = fib[0]; i <= fib[1]; i++) {
+               fl = calloc(1, sizeof(*fl));
+               if (fl == NULL) {
+                       error = 1;
+                       goto fiboptlist_range_ret;
+               }
+               fl->fl_num = i;
+               TAILQ_INSERT_TAIL(flh, fl, fl_next);
+       }
+fiboptlist_range_ret:
+       free(str);
+       return (error);
+}
+
+#define        ALLSTRLEN       64
+static int
+fiboptlist_csv(const char *arg, struct fibl_head_t *flh)
+{
+       struct fibl *fl;
+       char *str, *token, *endptr;
+       int fib, error;
+
+       if (strcmp("all", arg) == 0) {
+               str = calloc(1, ALLSTRLEN);
+               if (str == NULL) {
+                       error = 1;
+                       goto fiboptlist_csv_ret;
+               }
+               if (numfibs > 1)
+                       snprintf(str, ALLSTRLEN - 1, "%d-%d", 0, numfibs - 1);
+               else
+                       snprintf(str, ALLSTRLEN - 1, "%d", 0);
+       } else if (strcmp("default", arg) == 0) {
+               str = calloc(1, ALLSTRLEN);
+               if (str == NULL) {
+                       error = 1;
+                       goto fiboptlist_csv_ret;
+               }
+               snprintf(str, ALLSTRLEN - 1, "%d", defaultfib);
+       } else
+               str = strdup(arg);
+
+       error = 0;
+       while ((token = strsep(&str, ",")) != NULL) {
+               if (*token != '-' && strchr(token, '-') != NULL) {
+                       error = fiboptlist_range(token, flh);
+                       if (error)
+                               goto fiboptlist_csv_ret;
+               } else {
+                       fib = strtol(token, &endptr, 0);
+                       if (*endptr != '\0' || (fib == 0 &&
+                           (errno == EINVAL || errno == ERANGE))) {
+                               error = 1;
+                               goto fiboptlist_csv_ret;
+                       }
+                       fl = calloc(1, sizeof(*fl));
+                       if (fl == NULL) {
+                               error = 1;
+                               goto fiboptlist_csv_ret;
+                       }
+                       fl->fl_num = fib;
+                       TAILQ_INSERT_TAIL(flh, fl, fl_next);
+               }
+       }
+fiboptlist_csv_ret:
+       free(str);
+       return (error);
+}
+
 /*
  * Purge all entries in the routing tables not
  * associated with network interfaces.
@@ -214,38 +362,71 @@ main(int argc, char **argv)
 static void
 flushroutes(int argc, char *argv[])
 {
-       size_t needed;
-       int mib[6], rlen, seqno, count = 0;
-       char *buf, *next, *lim;
-       struct rt_msghdr *rtm;
+       struct fibl *fl;
+       int error;
 
        if (uid != 0 && !debugonly) {
                errx(EX_NOPERM, "must be root to alter routing table");
        }
        shutdown(s, SHUT_RD); /* Don't want to read back our messages */
-       if (argc > 1) {
+
+       TAILQ_INIT(&fibl_head);
+       while (argc > 1) {
+               argc--;
                argv++;
-               if (argc == 2 && **argv == '-')
-                   switch (keyword(*argv + 1)) {
-                       case K_INET:
-                               af = AF_INET;
-                               break;
+               if (**argv != '-')
+                       usage(*argv);
+               switch (keyword(*argv + 1)) {
+               case K_INET:
+                       af = AF_INET;
+                       break;
 #ifdef INET6
-                       case K_INET6:
-                               af = AF_INET6;
-                               break;
+               case K_INET6:
+                       af = AF_INET6;
+                       break;
 #endif
-                       case K_ATALK:
-                               af = AF_APPLETALK;
-                               break;
-                       case K_LINK:
-                               af = AF_LINK;
-                               break;
-                       default:
-                               goto bad;
-               } else
-bad:                   usage(*argv);
+               case K_ATALK:
+                       af = AF_APPLETALK;
+                       break;
+               case K_LINK:
+                       af = AF_LINK;
+                       break;
+               case K_FIB:
+                       if (!--argc)
+                               usage(*argv);
+                       error = fiboptlist_csv(*++argv, &fibl_head);
+                       if (error)
+                               usage(*argv);
+                       break;
+               default:
+                       usage(*argv);
+               }
+       }
+       if (TAILQ_EMPTY(&fibl_head)) {
+               error = fiboptlist_csv("default", &fibl_head);
+               if (error)
+                       errx(EX_OSERR, "fiboptlist_csv failed.");
        }
+       TAILQ_FOREACH(fl, &fibl_head, fl_next)
+               flushroutes_fib(fl->fl_num);
+}
+
+static int
+flushroutes_fib(int fib)
+{
+       struct rt_msghdr *rtm;
+       size_t needed;
+       char *buf, *next, *lim;
+       int mib[6], rlen, seqno, count = 0;
+       int error;
+
+       error = set_sofib(fib);
+       error += set_procfib(fib);
+       if (error) {
+               warn("fib number %d is ignored", fib);
+               return (error);
+       }
+
 retry:
        mib[0] = CTL_NET;
        mib[1] = PF_ROUTE;
@@ -303,13 +484,17 @@ retry:
                        print_rtmsg(rtm, rlen);
                else {
                        struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
-                       (void) printf("%-20.20s ", rtm->rtm_flags & RTF_HOST ?
+
+                       printf("%-20.20s ", rtm->rtm_flags & RTF_HOST ?
                            routename(sa) : netname(sa));
                        sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa);
-                       (void) printf("%-20.20s ", routename(sa));
-                       (void) printf("done\n");
+                       printf("%-20.20s ", routename(sa));
+                       if (fib >= 0)
+                               printf("-fib %-3d ", fib);
+                       printf("done\n");
                }
        }
+       return (error);
 }
 
 const char *
@@ -551,18 +736,32 @@ set_metric(char *value, int key)
        *valp = atoi(value);
 }
 
+#define        F_ISHOST        0x01
+#define        F_FORCENET      0x02
+#define        F_FORCEHOST     0x04
+#define        F_PROXY         0x08
+#define        F_INTERFACE     0x10
+
 static void
 newroute(int argc, char **argv)
 {
+       struct hostent *hp;
+       struct fibl *fl;
        char *cmd;
-       const char *dest = "", *gateway = "", *errmsg;
-       int ishost = 0, proxy = 0, ret, attempts, oerrno, flags = RTF_STATIC;
-       int key;
-       struct hostent *hp = 0;
+       const char *dest, *gateway, *errmsg;
+       int key, error, flags, nrflags, fibnum;
 
        if (uid != 0) {
                errx(EX_NOPERM, "must be root to alter routing table");
        }
+
+       dest = NULL;
+       gateway = NULL;
+       flags = RTF_STATIC;
+       nrflags = 0;
+       hp = NULL;
+       TAILQ_INIT(&fibl_head);
+
        cmd = argv[0];
        if (*cmd != 'g' && *cmd != 's')
                shutdown(s, SHUT_RD); /* Don't want to read back our messages */
@@ -594,7 +793,7 @@ newroute(int argc, char **argv)
                                break;
                        case K_IFACE:
                        case K_INTERFACE:
-                               iflag++;
+                               nrflags |= F_INTERFACE;
                                break;
                        case K_NOSTATIC:
                                flags &= ~RTF_STATIC;
@@ -606,7 +805,7 @@ newroute(int argc, char **argv)
                                lockrest = 1;
                                break;
                        case K_HOST:
-                               forcehost++;
+                               nrflags |= F_FORCEHOST;
                                break;
                        case K_REJECT:
                                flags |= RTF_REJECT;
@@ -621,7 +820,7 @@ newroute(int argc, char **argv)
                                flags |= RTF_PROTO2;
                                break;
                        case K_PROXY:
-                               proxy = 1;
+                               nrflags |= F_PROXY;
                                break;
                        case K_XRESOLVE:
                                flags |= RTF_XRESOLVE;
@@ -635,6 +834,13 @@ newroute(int argc, char **argv)
                        case K_NOSTICK:
                                flags &= ~RTF_STICKY;
                                break;
+                       case K_FIB:
+                               if (!--argc)
+                                       usage(NULL);
+                               error = fiboptlist_csv(*++argv, &fibl_head);
+                               if (error)
+                                       usage(NULL);
+                               break;
                        case K_IFA:
                                if (!--argc)
                                        usage(NULL);
@@ -658,7 +864,8 @@ newroute(int argc, char **argv)
                        case K_DST:
                                if (!--argc)
                                        usage(NULL);
-                               ishost = getaddr(RTA_DST, *++argv, &hp);
+                               if (getaddr(RTA_DST, *++argv, &hp))
+                                       nrflags |= F_ISHOST;
                                dest = *argv;
                                break;
                        case K_NETMASK:
@@ -667,17 +874,17 @@ newroute(int argc, char **argv)
                                (void) getaddr(RTA_NETMASK, *++argv, 0);
                                /* FALLTHROUGH */
                        case K_NET:
-                               forcenet++;
+                               nrflags |= F_FORCENET;
                                break;
                        case K_PREFIXLEN:
                                if (!--argc)
                                        usage(NULL);
                                if (prefixlen(*++argv) == -1) {
-                                       forcenet = 0;
-                                       ishost = 1;
+                                       nrflags &= ~F_FORCENET;
+                                       nrflags |= F_ISHOST;
                                } else {
-                                       forcenet = 1;
-                                       ishost = 0;
+                                       nrflags |= F_FORCENET;
+                                       nrflags &= ~F_ISHOST;
                                }
                                break;
                        case K_MTU:
@@ -699,18 +906,20 @@ newroute(int argc, char **argv)
                } else {
                        if ((rtm_addrs & RTA_DST) == 0) {
                                dest = *argv;
-                               ishost = getaddr(RTA_DST, *argv, &hp);
+                               if (getaddr(RTA_DST, *argv, &hp))
+                                       nrflags |= F_ISHOST;
                        } else if ((rtm_addrs & RTA_GATEWAY) == 0) {
                                gateway = *argv;
                                (void) getaddr(RTA_GATEWAY, *argv, &hp);
                        } else {
                                (void) getaddr(RTA_NETMASK, *argv, 0);
-                               forcenet = 1;
+                               nrflags |= F_FORCENET;
                        }
                }
        }
-       if (forcehost) {
-               ishost = 1;
+
+       if (nrflags & F_FORCEHOST) {
+               nrflags |= F_ISHOST;
 #ifdef INET6
                if (af == AF_INET6) {
                        rtm_addrs &= ~RTA_NETMASK;
@@ -718,71 +927,125 @@ newroute(int argc, char **argv)
                }
 #endif
        }
-       if (forcenet)
-               ishost = 0;
+       if (nrflags & F_FORCENET)
+               nrflags &= ~F_ISHOST;
        flags |= RTF_UP;
-       if (ishost)
+       if (nrflags & F_ISHOST)
                flags |= RTF_HOST;
-       if (iflag == 0)
+       if ((nrflags & F_INTERFACE) == 0)
                flags |= RTF_GATEWAY;
-       if (proxy) {
+       if (nrflags & F_PROXY) {
                so_dst.sinarp.sin_other = SIN_PROXY;
                flags |= RTF_ANNOUNCE;
        }
-       for (attempts = 1; ; attempts++) {
-               errno = 0;
-               if ((ret = rtmsg(*cmd, flags)) == 0)
-                       break;
-               if (errno != ENETUNREACH && errno != ESRCH)
-                       break;
-               if (af == AF_INET && *gateway != '\0' &&
-                   hp != NULL && hp->h_addr_list[1] != NULL) {
-                       hp->h_addr_list++;
-                       memmove(&so_gate.sin.sin_addr, hp->h_addr_list[0],
-                           MIN((size_t)hp->h_length,
-                           sizeof(so_gate.sin.sin_addr)));
-               } else
-                       break;
+       if (dest == NULL)
+               dest = "";
+       if (gateway == NULL)
+               gateway = "";
+
+       if (TAILQ_EMPTY(&fibl_head)) {
+               error = fiboptlist_csv("default", &fibl_head);
+               if (error)
+                       errx(EX_OSERR, "fiboptlist_csv failed.");
+       }
+       error = 0;
+       TAILQ_FOREACH(fl, &fibl_head, fl_next) {
+               fl->fl_error = newroute_fib(fl->fl_num, cmd, flags);
+               if (fl->fl_error)
+                       fl->fl_errno = errno;
+               error += fl->fl_error;
        }
        if (*cmd == 'g' || *cmd == 's')
-               exit(ret != 0);
+               exit(error);
+
+       error = 0;
        if (!qflag) {
-               oerrno = errno;
-               (void) printf("%s %s %s", cmd, ishost? "host" : "net", dest);
-               if (*gateway) {
-                       (void) printf(": gateway %s", gateway);
-                       if (attempts > 1 && ret == 0 && af == AF_INET)
-                           (void) printf(" (%s)",
-                               inet_ntoa(((struct sockaddr_in 
*)&route.rt_gateway)->sin_addr));
+               fibnum = 0;
+               TAILQ_FOREACH(fl, &fibl_head, fl_next) {
+                       if (fl->fl_error == 0)
+                               fibnum++;
+               }
+               if (fibnum > 0) {
+                       int firstfib = 1;
+
+                       printf("%s %s %s", cmd,
+                           (nrflags & F_ISHOST) ? "host" : "net", dest);
+                       if (*gateway)
+                               printf(": gateway %s", gateway);
+
+                       if (numfibs > 1) {
+                               TAILQ_FOREACH(fl, &fibl_head, fl_next) {
+                                       if (fl->fl_error == 0
+                                           && fl->fl_num >= 0) {
+                                               if (firstfib) {
+                                                       printf(" fib ");
+                                                       firstfib = 0;
+                                               }
+                                               printf("%d", fl->fl_num);
+                                               if (fibnum-- > 1)
+                                                       printf(",");
+                                       }
+                               }
+                       }
+                       printf("\n");
                }
-               if (ret == 0) {
-                       (void) printf("\n");
-               } else {
-                       switch (oerrno) {
-                       case ESRCH:
-                               errmsg = "not in table";
-                               break;
-                       case EBUSY:
-                               errmsg = "entry in use";
-                               break;
-                       case ENOBUFS:
-                               errmsg = "not enough memory";
-                               break;
-                       case EADDRINUSE:
-                               /* handle recursion avoidance in rt_setgate() */
-                               errmsg = "gateway uses the same route";
-                               break;
-                       case EEXIST:
-                               errmsg = "route already in table";
-                               break;
-                       default:
-                               errmsg = strerror(oerrno);
-                               break;
+
+               fibnum = 0;
+               TAILQ_FOREACH(fl, &fibl_head, fl_next) {
+                       if (fl->fl_error != 0) {
+                               printf("%s %s %s", cmd, (nrflags & F_ISHOST)
+                                   ? "host" : "net", dest);
+                               if (*gateway)
+                                       printf(": gateway %s", gateway);
+
+                               if (fl->fl_num >= 0)
+                                       printf(" fib %d", fl->fl_num);
+
+                               switch (fl->fl_errno) {
+                               case ESRCH:
+                                       errmsg = "not in table";
+                                       break;
+                               case EBUSY:
+                                       errmsg = "entry in use";
+                                       break;
+                               case ENOBUFS:
+                                       errmsg = "not enough memory";
+                                       break;
+                               case EADDRINUSE:
+                                       /*
+                                        * handle recursion avoidance
+                                        * in rt_setgate()
+                                        */
+                                       errmsg = "gateway uses the same route";
+                                       break;
+                               case EEXIST:
+                                       errmsg = "route already in table";
+                                       break;
+                               default:
+                                       errmsg = strerror(fl->fl_errno);
+                                       break;
+                               }
+                               printf(": %s\n", errmsg);
+                               error = 1;
                        }
-                       (void) printf(": %s\n", errmsg);
                }
        }
-       exit(ret != 0);
+       exit(error);
+}
+
+static int
+newroute_fib(int fib, char *cmd, int flags)
+{
+       int error;
+
+       error = set_sofib(fib);
+       if (error) {
+               warn("fib number %d is ignored", fib);
+               return (error);
+       }
+
+       error = rtmsg(*cmd, flags, fib);
+       return (error);
 }
 
 static void
@@ -1132,10 +1395,33 @@ retry2:
 }
 
 static void
-monitor(void)
+monitor(int argc, char *argv[])
 {
-       int n;
-       char msg[2048];
+       int n, fib, error;
+       char msg[2048], *endptr;
+
+       fib = defaultfib;
+       while (argc > 1) {
+               argc--;
+               argv++;
+               if (**argv != '-')
+                       usage(*argv);
+               switch (keyword(*argv + 1)) {
+               case K_FIB:
+                       if (!--argc)
+                               usage(*argv);
+                       fib = strtol(*++argv, &endptr, 0);
+                       if (*endptr != '\0' || (fib == 0 &&
+                           (errno == EINVAL || errno == ERANGE)))
+                               usage(*argv);
+                       break;
+               default:
+                       usage(*argv);
+               }
+       }
+       error = set_sofib(fib);
+       if (error)
+               errx(EX_USAGE, "invalid fib number: %d", fib);
 
        verbose = 1;
        if (debugonly) {
@@ -1157,7 +1443,7 @@ struct {
 } m_rtmsg;
 
 static int
-rtmsg(int cmd, int flags)
+rtmsg(int cmd, int flags, int fib)
 {
        static int seq;
        int rlen;
@@ -1220,7 +1506,7 @@ rtmsg(int cmd, int flags)
                if (l < 0)
                        warn("read from routing socket");
                else
-                       print_getmsg(&rtm, l);
+                       print_getmsg(&rtm, l, fib);
        }
 #undef rtm
        return (0);
@@ -1397,7 +1683,7 @@ badlen:
 }
 
 static void
-print_getmsg(struct rt_msghdr *rtm, int msglen)
+print_getmsg(struct rt_msghdr *rtm, int msglen, int fib)
 {
        struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL;
        struct sockaddr_dl *ifp = NULL;
@@ -1457,6 +1743,8 @@ print_getmsg(struct rt_msghdr *rtm, int 
        }
        if (gate && rtm->rtm_flags & RTF_GATEWAY)
                (void)printf("    gateway: %s\n", routename(gate));
+       if (fib >= 0)
+               (void)printf("        fib: %u\n", (unsigned int)fib);
        if (ifp)
                (void)printf("  interface: %.*s\n",
                    ifp->sdl_nlen, ifp->sdl_data);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to