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
This commit is contained in:
parent
571b26027e
commit
9ba63ff592
@ -10,6 +10,7 @@ del
|
||||
delete
|
||||
dst
|
||||
expire
|
||||
fib
|
||||
flush
|
||||
gateway
|
||||
genmask
|
||||
|
@ -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 syntax:
|
||||
.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 locked by the
|
||||
.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
|
||||
|
@ -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 sockaddr_in6 *, const char *);
|
||||
#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 (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;
|
||||
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");
|
||||
}
|
||||
|
||||
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 msglen)
|
||||
}
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user