summaryrefslogtreecommitdiff
path: root/sbin/route/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/route/route.c')
-rw-r--r--sbin/route/route.c126
1 files changed, 89 insertions, 37 deletions
diff --git a/sbin/route/route.c b/sbin/route/route.c
index 9f0f0740f44..649dd964b14 100644
--- a/sbin/route/route.c
+++ b/sbin/route/route.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.c,v 1.66 2004/05/15 07:43:34 claudio Exp $ */
+/* $OpenBSD: route.c,v 1.67 2004/06/06 17:08:23 cedric Exp $ */
/* $NetBSD: route.c,v 1.16 1996/04/15 18:27:05 cgd Exp $ */
/*
@@ -40,7 +40,7 @@ static const char copyright[] =
#if 0
static const char sccsid[] = "@(#)route.c 8.3 (Berkeley) 3/19/94";
#else
-static const char rcsid[] = "$OpenBSD: route.c,v 1.66 2004/05/15 07:43:34 claudio Exp $";
+static const char rcsid[] = "$OpenBSD: route.c,v 1.67 2004/06/06 17:08:23 cedric Exp $";
#endif
#endif /* not lint */
@@ -83,13 +83,14 @@ union sockunion {
struct sockaddr_iso siso;
struct sockaddr_dl sdl;
struct sockaddr_x25 sx25;
-} so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp;
+ struct sockaddr_rtin rtin;
+} so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp, so_src, so_srcmask;
typedef union sockunion *sup;
pid_t pid;
int rtm_addrs, s;
int forcehost, forcenet, doflush, nflag, af, qflag, tflag, keyword(char *);
-int iflag, verbose, aflen = sizeof (struct sockaddr_in);
+int Sflag, iflag, verbose, aflen = sizeof (struct sockaddr_in);
int locking, lockrest, debugonly;
struct rt_metrics rt_metrics;
u_long rtm_inits;
@@ -108,7 +109,7 @@ void print_rtmsg(struct rt_msghdr *, int);
void pmsg_common(struct rt_msghdr *);
void pmsg_addrs(char *, int);
void bprintf(FILE *, int, u_char *);
-void mask_addr(void);
+void mask_addr(union sockunion *, union sockunion *, int which);
#ifdef INET6
static int inet6_makenetandmask(struct sockaddr_in6 *);
#endif
@@ -119,7 +120,8 @@ __dead void usage(char *cp);
void quit(char *s);
char *any_ntoa(const struct sockaddr *sa);
void set_metric(char *value, int key);
-void inet_makenetandmask(u_int32_t net, struct sockaddr_in *sin, int bits);
+void inet_makenetandmask(u_int32_t net, struct sockaddr_in *sin, int bits,
+ int which);
char *ns_print(struct sockaddr_ns *sns);
char *ipx_print(struct sockaddr_ipx *sipx);
void interfaces(void);
@@ -132,7 +134,7 @@ usage(char *cp)
if (cp)
(void) fprintf(stderr, "route: botched keyword: %s\n", cp);
(void) fprintf(stderr,
- "usage: route [ -nqv ] cmd [[ -<modifiers> ] args ]\n");
+ "usage: route [ -nqSv ] cmd [[ -<modifiers> ] args ]\n");
(void) fprintf(stderr,
"keywords: get, add, change, delete, show, flush, monitor.\n");
exit(1);
@@ -165,7 +167,7 @@ main(int argc, char **argv)
if (argc < 2)
usage(NULL);
- while ((ch = getopt(argc, argv, "nqdtv")) != -1)
+ while ((ch = getopt(argc, argv, "nqdtvS")) != -1)
switch(ch) {
case 'n':
nflag = 1;
@@ -182,6 +184,9 @@ main(int argc, char **argv)
case 'd':
debugonly = 1;
break;
+ case 'S':
+ Sflag = 1;
+ break;
default:
usage(NULL);
}
@@ -601,7 +606,7 @@ set_metric(char *value, int key)
int
newroute(int argc, char **argv)
{
- char *cmd, *dest = "", *gateway = "", *err;
+ char *cmd, *dest = "", *source = "", *gateway = "", *err;
int ishost = 0, ret = 0, attempts, oerrno, flags = RTF_STATIC;
int key;
struct hostent *hp = 0;
@@ -718,6 +723,17 @@ newroute(int argc, char **argv)
ishost = getaddr(RTA_DST, *++argv, &hp);
dest = *argv;
break;
+ case K_SRC:
+ if (!--argc)
+ usage(1+*argv);
+ (void) getaddr(RTA_SRC, *++argv, 0);
+ source = *argv;
+ break;
+ case K_SRCMASK:
+ if (!--argc)
+ usage(1+*argv);
+ (void) getaddr(RTA_SRCMASK, *++argv, 0);
+ break;
case K_NETMASK:
if (!--argc)
usage(1+*argv);
@@ -747,7 +763,7 @@ newroute(int argc, char **argv)
usage(1+*argv);
}
} else {
- if ((rtm_addrs & RTA_DST) == 0) {
+ if ((rtm_addrs & (RTA_DST|RTA_SRC)) == 0) {
dest = *argv;
ishost = getaddr(RTA_DST, *argv, &hp);
} else if ((rtm_addrs & RTA_GATEWAY) == 0) {
@@ -786,6 +802,11 @@ newroute(int argc, char **argv)
flags |= RTF_HOST;
if (iflag == 0)
flags |= RTF_GATEWAY;
+ if (rtm_addrs & (RTA_SRC|RTA_SRCMASK)) {
+ if (!(rtm_addrs & RTA_DST))
+ getaddr(RTA_DST, "default", &hp);
+ flags |= RTF_SOURCE;
+ }
for (attempts = 1; ; attempts++) {
errno = 0;
if ((ret = rtmsg(*cmd, flags)) == 0)
@@ -804,6 +825,8 @@ newroute(int argc, char **argv)
oerrno = errno;
if (!qflag) {
(void) printf("%s %s %s", cmd, ishost? "host" : "net", dest);
+ if (*source)
+ (void) printf(": source %s", source);
if (*gateway) {
(void) printf(": gateway %s", gateway);
if (attempts > 1 && ret == 0 && af == AF_INET)
@@ -834,12 +857,12 @@ newroute(int argc, char **argv)
}
void
-inet_makenetandmask(u_int32_t net, struct sockaddr_in *sin, int bits)
+inet_makenetandmask(u_int32_t net, struct sockaddr_in *sin, int bits, int which)
{
u_int32_t addr, mask = 0;
char *cp;
- rtm_addrs |= RTA_NETMASK;
+ rtm_addrs |= (which == RTA_DST) ? RTA_NETMASK : RTA_SRCMASK;
if (net == 0)
mask = addr = 0;
else if (bits) {
@@ -866,7 +889,7 @@ inet_makenetandmask(u_int32_t net, struct sockaddr_in *sin, int bits)
mask = -1;
}
sin->sin_addr.s_addr = htonl(addr);
- sin = &so_mask.sin;
+ sin = (which == RTA_DST) ? &so_mask.sin : &so_srcmask.sin;
sin->sin_addr.s_addr = htonl(mask);
sin->sin_len = 0;
sin->sin_family = 0;
@@ -948,6 +971,12 @@ getaddr(int which, char *s, struct hostent **hpp)
su = &so_ifa;
su->sa.sa_family = af;
break;
+ case RTA_SRC:
+ su = &so_src;
+ break;
+ case RTA_SRCMASK:
+ su = &so_srcmask;
+ break;
default:
usage("Internal Error");
/*NOTREACHED*/
@@ -1073,19 +1102,19 @@ getaddr(int which, char *s, struct hostent **hpp)
*hpp = NULL;
q = strchr(s,'/');
- if (q && which == RTA_DST) {
+ if (q && (which == RTA_DST || which == RTA_SRC)) {
qs = *q;
*q = '\0';
val = inet_addr(s);
if (val != INADDR_NONE) {
inet_makenetandmask(htonl(val), &su->sin,
- strtoul(q+1, 0, 0));
+ strtoul(q+1, 0, 0), which);
return (0);
}
*q =qs;
}
if (((val = inet_addr(s)) != INADDR_NONE) &&
- (which != RTA_DST || forcenet == 0)) {
+ ((which != RTA_DST && which != RTA_SRC) || forcenet == 0)) {
su->sin.sin_addr.s_addr = val;
if (inet_lnaof(su->sin.sin_addr) != INADDR_ANY)
return (1);
@@ -1098,8 +1127,8 @@ getaddr(int which, char *s, struct hostent **hpp)
(forcehost == 0 && (np = getnetbyname(s)) != NULL &&
(val = np->n_net) != 0)) {
netdone:
- if (which == RTA_DST)
- inet_makenetandmask(val, &su->sin, 0);
+ if (which == RTA_DST || which == RTA_SRC)
+ inet_makenetandmask(val, &su->sin, 0, which);
return (0);
}
hp = gethostbyname(s);
@@ -1367,13 +1396,17 @@ rtmsg(int cmd, int flags)
rtm.rtm_inits = rtm_inits;
if (rtm_addrs & RTA_NETMASK)
- mask_addr();
+ mask_addr(&so_dst, &so_mask, RTA_DST);
+ if (rtm_addrs & RTA_SRCMASK)
+ mask_addr(&so_src, &so_srcmask, RTA_SRC);
NEXTADDR(RTA_DST, so_dst);
NEXTADDR(RTA_GATEWAY, so_gate);
NEXTADDR(RTA_NETMASK, so_mask);
NEXTADDR(RTA_GENMASK, so_genmask);
NEXTADDR(RTA_IFP, so_ifp);
NEXTADDR(RTA_IFA, so_ifa);
+ NEXTADDR(RTA_SRC, so_src);
+ NEXTADDR(RTA_SRCMASK, so_srcmask);
rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
if (verbose)
print_rtmsg(&rtm, l);
@@ -1400,19 +1433,19 @@ rtmsg(int cmd, int flags)
}
void
-mask_addr(void)
+mask_addr(union sockunion *addr, union sockunion *mask, int which)
{
- int olen = so_mask.sa.sa_len;
- char *cp1 = olen + (char *)&so_mask, *cp2;
+ int olen = mask->sa.sa_len;
+ char *cp1 = olen + (char *)mask, *cp2;
- for (so_mask.sa.sa_len = 0; cp1 > (char *)&so_mask; )
+ for (mask->sa.sa_len = 0; cp1 > (char *)mask; )
if (*--cp1 != 0) {
- so_mask.sa.sa_len = 1 + cp1 - (char *)&so_mask;
+ mask->sa.sa_len = 1 + cp1 - (char *)mask;
break;
}
- if ((rtm_addrs & RTA_DST) == 0)
+ if ((rtm_addrs & which) == 0)
return;
- switch (so_dst.sa.sa_family) {
+ switch (addr->sa.sa_family) {
case AF_NS:
case AF_IPX:
case AF_INET:
@@ -1423,20 +1456,20 @@ mask_addr(void)
case 0:
return;
case AF_ISO:
- olen = MIN(so_dst.siso.siso_nlen,
- MAX(so_mask.sa.sa_len - 6, 0));
+ olen = MIN(addr->siso.siso_nlen,
+ MAX(mask->sa.sa_len - 6, 0));
break;
}
- cp1 = so_mask.sa.sa_len + 1 + (char *)&so_dst;
- cp2 = so_dst.sa.sa_len + 1 + (char *)&so_dst;
+ cp1 = mask->sa.sa_len + 1 + (char *)addr;
+ cp2 = addr->sa.sa_len + 1 + (char *)addr;
while (cp2 > cp1)
*--cp2 = 0;
- cp2 = so_mask.sa.sa_len + 1 + (char *)&so_mask;
- while (cp1 > so_dst.sa.sa_data)
+ cp2 = mask->sa.sa_len + 1 + (char *)mask;
+ while (cp1 > addr->sa.sa_data)
*--cp1 &= *--cp2;
- switch (so_dst.sa.sa_family) {
+ switch (addr->sa.sa_family) {
case AF_ISO:
- so_dst.siso.siso_nlen = olen;
+ addr->siso.siso_nlen = olen;
break;
}
}
@@ -1464,11 +1497,11 @@ char *msgtypes[] = {
char metricnames[] =
"\011pksent\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount\1mtu";
char routeflags[] =
-"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT\011CLONING\012XRESOLVE\013LLINFO\014STATIC\017PROTO2\020PROTO1\040CLONED";
+"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT\011CLONING\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE\016PROTO3\017PROTO2\020PROTO1\021CLONED\022SOURCE";
char ifnetflags[] =
"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6NOTRAILERS\7RUNNING\010NOARP\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1\017LINK2\020MULTICAST";
char addrnames[] =
-"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD";
+"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD\011SRC\012SRCMASK";
void
print_rtmsg(struct rt_msghdr *rtm, int msglen)
@@ -1538,6 +1571,7 @@ void
print_getmsg(struct rt_msghdr *rtm, int msglen)
{
struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL;
+ struct sockaddr *src = NULL, *srcmask = NULL;
struct sockaddr_dl *ifp = NULL;
struct sockaddr *sa;
char *cp;
@@ -1575,6 +1609,12 @@ print_getmsg(struct rt_msghdr *rtm, int msglen)
case RTA_NETMASK:
mask = sa;
break;
+ case RTA_SRC:
+ src = sa;
+ break;
+ case RTA_SRCMASK:
+ srcmask = sa;
+ break;
case RTA_IFP:
if (sa->sa_family == AF_LINK &&
((struct sockaddr_dl *)sa)->sdl_nlen)
@@ -1594,6 +1634,17 @@ print_getmsg(struct rt_msghdr *rtm, int msglen)
(void)printf(" mask: %s\n", routename(mask));
nflag = savenflag;
}
+ if (src && srcmask)
+ srcmask->sa_family = src->sa_family; /* XXX */
+ if (src)
+ (void)printf(" source: %s\n", routename(src));
+ if (srcmask) {
+ int savenflag = nflag;
+
+ nflag = 1;
+ (void)printf(" mask: %s\n", routename(mask));
+ nflag = savenflag;
+ }
if (gate && rtm->rtm_flags & RTF_GATEWAY)
(void)printf(" gateway: %s\n", routename(gate));
if (ifp)
@@ -1619,7 +1670,8 @@ print_getmsg(struct rt_msghdr *rtm, int msglen)
printf("%8d%c\n", (int)rtm->rtm_rmx.rmx_expire, lock(EXPIRE));
#undef lock
#undef msec
-#define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD)
+#define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_SRC|RTA_SRCMASK| \
+ RTA_IFP|RTA_IFA|RTA_BRD)
if (verbose)
pmsg_common(rtm);
else if (rtm->rtm_addrs &~ RTA_IGN) {