Module Name: src
Committed By: kefren
Date: Tue Jun 21 14:33:14 UTC 2011
Modified Files:
src/sbin/route: route.c
Log Message:
Alloc dynamically sockunions in sou.
Teach route(8) about multiple tags. E.G.: -tag 100,20,33
XXX: needs documentation
To generate a diff of this commit:
cvs rdiff -u -r1.128 -r1.129 src/sbin/route/route.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sbin/route/route.c
diff -u src/sbin/route/route.c:1.128 src/sbin/route/route.c:1.129
--- src/sbin/route/route.c:1.128 Tue Feb 1 01:39:19 2011
+++ src/sbin/route/route.c Tue Jun 21 14:33:14 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: route.c,v 1.128 2011/02/01 01:39:19 matt Exp $ */
+/* $NetBSD: route.c,v 1.129 2011/06/21 14:33:14 kefren Exp $ */
/*
* Copyright (c) 1983, 1989, 1991, 1993
@@ -39,7 +39,7 @@
#if 0
static char sccsid[] = "@(#)route.c 8.6 (Berkeley) 4/28/95";
#else
-__RCSID("$NetBSD: route.c,v 1.128 2011/02/01 01:39:19 matt Exp $");
+__RCSID("$NetBSD: route.c,v 1.129 2011/06/21 14:33:14 kefren Exp $");
#endif
#endif /* not lint */
@@ -97,7 +97,8 @@
typedef union sockunion *sup;
struct sou {
- union sockunion so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp, so_mpls;
+ union sockunion *so_dst, *so_gate, *so_mask, *so_genmask, *so_ifa,
+ *so_ifp, *so_mpls;
};
static char *any_ntoa(const struct sockaddr *);
@@ -116,6 +117,8 @@
static void monitor(void);
static int print_getmsg(struct rt_msghdr *, int, struct sou *);
static const char *linkstate(struct if_msghdr *);
+static sup readtag(sup, const char *);
+static void addtag(sup, const char *, int);
#endif /* SMALL */
static int rtmsg(int, int, struct sou *);
static void mask_addr(struct sou *);
@@ -588,11 +591,21 @@
case AF_MPLS:
{
union mpls_shim ms;
+ const union mpls_shim *pms;
+ int psize = sizeof(struct sockaddr_mpls);
ms.s_addr =((const struct sockaddr_mpls*)sa)->smpls_addr.s_addr;
ms.s_addr = ntohl(ms.s_addr);
snprintf(line, sizeof(line), "%u", ms.shim.label);
+ pms = &((const struct sockaddr_mpls*)sa)->smpls_addr;
+ while(psize < sa->sa_len) {
+ pms++;
+ ms.s_addr = ntohl(pms->s_addr);
+ snprintf(line, sizeof(line), "%s %u", line,
+ ms.shim.label);
+ psize += sizeof(ms);
+ }
break;
}
#endif /* SMALL */
@@ -795,7 +808,18 @@
struct hostent *hp = 0;
struct sou sou, *soup = &sou;
- memset(&sou, 0, sizeof(sou));
+ sou.so_dst = calloc(1, sizeof(union sockunion));
+ sou.so_gate = calloc(1, sizeof(union sockunion));
+ sou.so_mask = calloc(1, sizeof(union sockunion));
+ sou.so_genmask = calloc(1, sizeof(union sockunion));
+ sou.so_ifa = calloc(1, sizeof(union sockunion));
+ sou.so_ifp = calloc(1, sizeof(union sockunion));
+ sou.so_mpls = calloc(1, sizeof(union sockunion));
+
+ if (sou.so_dst == NULL || sou.so_gate == NULL || sou.so_mask == NULL ||
+ sou.so_genmask == NULL || sou.so_ifa == NULL || sou.so_ifp == NULL ||
+ sou.so_mpls == NULL)
+ errx(EXIT_FAILURE, "Cannot allocate memory");
cmd = argv[0];
af = AF_UNSPEC;
@@ -849,6 +873,7 @@
case K_TAG:
if (!--argc)
usage(1+*argv);
+ af = AF_MPLS;
aflen = sizeof(struct sockaddr_mpls);
(void)getaddr(RTA_TAG, *++argv, 0, soup);
break;
@@ -1016,7 +1041,7 @@
break;
if (af == AF_INET && *gateway && hp && hp->h_addr_list[1]) {
hp->h_addr_list++;
- memmove(&soup->so_gate.sin.sin_addr, hp->h_addr_list[0],
+ memmove(&soup->so_gate->sin.sin_addr, hp->h_addr_list[0],
hp->h_length);
} else
break;
@@ -1030,13 +1055,21 @@
(void)printf(": gateway %s", gateway);
if (attempts > 1 && ret == 0 && af == AF_INET)
(void)printf(" (%s)",
- inet_ntoa(soup->so_gate.sin.sin_addr));
+ inet_ntoa(soup->so_gate->sin.sin_addr));
}
if (ret == 0)
(void)printf("\n");
else
(void)printf(": %s\n", route_strerror(oerrno));
}
+ free(sou.so_dst);
+ free(sou.so_gate);
+ free(sou.so_mask);
+ free(sou.so_genmask);
+ free(sou.so_ifa);
+ free(sou.so_ifp);
+ free(sou.so_mpls);
+
return ret != 0;
}
@@ -1090,7 +1123,7 @@
mask = -1;
}
isin->sin_addr.s_addr = htonl(addr);
- sin = &soup->so_mask.sin;
+ sin = &soup->so_mask->sin;
sin->sin_addr.s_addr = htonl(mask);
sin->sin_len = 0;
sin->sin_family = 0;
@@ -1154,28 +1187,28 @@
rtm_addrs |= which;
switch (which) {
case RTA_DST:
- su = &soup->so_dst;
+ su = soup->so_dst;
break;
case RTA_GATEWAY:
- su = &soup->so_gate;
+ su = soup->so_gate;
break;
case RTA_NETMASK:
- su = &soup->so_mask;
+ su = soup->so_mask;
break;
case RTA_GENMASK:
- su = &soup->so_genmask;
+ su = soup->so_genmask;
break;
case RTA_IFP:
- su = &soup->so_ifp;
+ su = soup->so_ifp;
afamily = AF_LINK;
break;
case RTA_IFA:
- su = &soup->so_ifa;
+ su = soup->so_ifa;
su->sa.sa_family = af;
break;
#ifndef SMALL
case RTA_TAG:
- su = &soup->so_mpls;
+ su = soup->so_mpls;
afamily = AF_MPLS;
break;
#endif
@@ -1285,15 +1318,13 @@
rtm_addrs |= RTA_NETMASK;
return(forcehost || su->sat.sat_addr.s_node != 0);
case AF_MPLS:
- /* Tag should be a positive value, limited to 20 bits */
- if (atoi(s) < 0 || atoi(s) >= (1 << 20))
- errx(1, "bad tag: %s", s);
- su->smpls.smpls_addr.s_addr = 0;
- su->smpls.smpls_addr.shim.label = atoi(s);
- su->smpls.smpls_addr.s_addr =
- htonl(su->smpls.smpls_addr.s_addr);
-
- /* We don't have netmasks for tags */
+ if (which == RTA_DST)
+ soup->so_dst = readtag(su, s);
+ else if (which == RTA_TAG)
+ soup->so_mpls = readtag(su, s);
+ else
+ errx(EXIT_FAILURE, "MPLS can be used only as "
+ "DST or TAG");
return 1;
#endif
@@ -1353,6 +1384,56 @@
/*NOTREACHED*/
}
+static sup
+readtag(sup su, const char *s)
+{
+ char *p, *n, *norig;
+ int mplssize = 0;
+ sup retsu = su;
+
+ n = (char*)malloc(strlen(s) + 1);
+ if (n == NULL)
+ errx(EXIT_FAILURE, "%s: Cannot allocate memory", s);
+ norig = n;
+ strlcpy(n, s, strlen(s) + 1);
+ for (uint i = 0; i < strlen(n); i++)
+ if(n[i] == ',')
+ mplssize++;
+
+#define MPLS_NEW_SIZE (sizeof(struct sockaddr_mpls) + \
+ mplssize * sizeof(union mpls_shim))
+
+ if (mplssize != 0 && sizeof(union sockunion) < MPLS_NEW_SIZE) {
+ free(su);
+ retsu = malloc(MPLS_NEW_SIZE);
+ retsu->smpls.smpls_family = AF_MPLS;
+ }
+ retsu->smpls.smpls_len = MPLS_NEW_SIZE;
+ mplssize = 0;
+ while ((p = strchr(n, ',')) != NULL) {
+ p[0] = '\0';
+ addtag(retsu, n, mplssize);
+ n = p + 1;
+ mplssize++;
+ }
+ addtag(retsu, n, mplssize);
+
+ free(norig);
+ return retsu;
+}
+
+static void
+addtag(sup su, const char *s, int where)
+{
+ union mpls_shim *ms = &su->smpls.smpls_addr;
+
+ if (atoi(s) < 0 || atoi(s) >= (1 << 20))
+ errx(EXIT_FAILURE, "%s: Bad tag", s);
+ ms[where].s_addr = 0;
+ ms[where].shim.label = atoi(s);
+ ms[where].s_addr = htonl(ms[where].s_addr);
+}
+
int
prefixlen(const char *s, struct sou *soup)
{
@@ -1381,22 +1462,22 @@
r = len & 7;
switch (af) {
case AF_INET:
- memset(&soup->so_mask, 0, sizeof(soup->so_mask));
- soup->so_mask.sin.sin_family = AF_INET;
- soup->so_mask.sin.sin_len = sizeof(struct sockaddr_in);
- soup->so_mask.sin.sin_addr.s_addr = (len == 0 ? 0
+ memset(soup->so_mask, 0, sizeof(soup->so_mask));
+ soup->so_mask->sin.sin_family = AF_INET;
+ soup->so_mask->sin.sin_len = sizeof(struct sockaddr_in);
+ soup->so_mask->sin.sin_addr.s_addr = (len == 0 ? 0
: htonl(0xffffffff << (32 - len)));
break;
#ifdef INET6
case AF_INET6:
- soup->so_mask.sin6.sin6_family = AF_INET6;
- soup->so_mask.sin6.sin6_len = sizeof(struct sockaddr_in6);
- memset(&soup->so_mask.sin6.sin6_addr, 0,
- sizeof(soup->so_mask.sin6.sin6_addr));
+ soup->so_mask->sin6.sin6_family = AF_INET6;
+ soup->so_mask->sin6.sin6_len = sizeof(struct sockaddr_in6);
+ memset(&soup->so_mask->sin6.sin6_addr, 0,
+ sizeof(soup->so_mask->sin6.sin6_addr));
if (q > 0)
- memset(&soup->so_mask.sin6.sin6_addr, 0xff, q);
+ memset(&soup->so_mask->sin6.sin6_addr, 0xff, q);
if (r > 0)
- *((u_char *)&soup->so_mask.sin6.sin6_addr + q) =
+ *((u_char *)&soup->so_mask->sin6.sin6_addr + q) =
(0xff00 >> r) & 0xff;
break;
#endif
@@ -1478,8 +1559,8 @@
#define NEXTADDR(w, u) \
if (rtm_addrs & (w)) {\
- l = RT_ROUNDUP(u.sa.sa_len); memmove(cp, &(u), l); cp += l;\
- if (verbose && ! shortoutput) sodump(&(u),#u);\
+ l = RT_ROUNDUP(u->sa.sa_len); memmove(cp, u, l); cp += l;\
+ if (verbose && ! shortoutput) sodump(u,#u);\
}
errno = 0;
@@ -1493,9 +1574,9 @@
return -1;
#else /* SMALL */
cmd = RTM_GET;
- if (soup->so_ifp.sa.sa_family == AF_UNSPEC) {
- soup->so_ifp.sa.sa_family = AF_LINK;
- soup->so_ifp.sa.sa_len = sizeof(struct sockaddr_dl);
+ if (soup->so_ifp->sa.sa_family == AF_UNSPEC) {
+ soup->so_ifp->sa.sa_family = AF_LINK;
+ soup->so_ifp->sa.sa_len = sizeof(struct sockaddr_dl);
rtm_addrs |= RTA_IFP;
}
#endif /* SMALL */
@@ -1556,17 +1637,17 @@
static void
mask_addr(struct sou *soup)
{
- int olen = soup->so_mask.sa.sa_len;
+ int olen = soup->so_mask->sa.sa_len;
char *cp1 = olen + (char *)&soup->so_mask, *cp2;
- for (soup->so_mask.sa.sa_len = 0; cp1 > (char *)&soup->so_mask; )
+ for (soup->so_mask->sa.sa_len = 0; cp1 > (char *)&soup->so_mask; )
if (*--cp1 != 0) {
- soup->so_mask.sa.sa_len = 1 + cp1 - (char *)&soup->so_mask;
+ soup->so_mask->sa.sa_len = 1 + cp1 - (char *)&soup->so_mask;
break;
}
if ((rtm_addrs & RTA_DST) == 0)
return;
- switch (soup->so_dst.sa.sa_family) {
+ switch (soup->so_dst->sa.sa_family) {
case AF_INET:
#ifdef INET6
case AF_INET6:
@@ -1578,22 +1659,22 @@
return;
#ifndef SMALL
case AF_ISO:
- olen = MIN(soup->so_dst.siso.siso_nlen,
- MAX(soup->so_mask.sa.sa_len - 6, 0));
+ olen = MIN(soup->so_dst->siso.siso_nlen,
+ MAX(soup->so_mask->sa.sa_len - 6, 0));
break;
#endif /* SMALL */
}
- cp1 = soup->so_mask.sa.sa_len + 1 + (char *)&soup->so_dst;
- cp2 = soup->so_dst.sa.sa_len + 1 + (char *)&soup->so_dst;
+ cp1 = soup->so_mask->sa.sa_len + 1 + (char *)&soup->so_dst;
+ cp2 = soup->so_dst->sa.sa_len + 1 + (char *)&soup->so_dst;
while (cp2 > cp1)
*--cp2 = 0;
- cp2 = soup->so_mask.sa.sa_len + 1 + (char *)&soup->so_mask;
- while (cp1 > soup->so_dst.sa.sa_data)
+ cp2 = soup->so_mask->sa.sa_len + 1 + (char *)&soup->so_mask;
+ while (cp1 > soup->so_dst->sa.sa_data)
*--cp1 &= *--cp2;
#ifndef SMALL
- switch (soup->so_dst.sa.sa_family) {
+ switch (soup->so_dst->sa.sa_family) {
case AF_ISO:
- soup->so_dst.siso.siso_nlen = olen;
+ soup->so_dst->siso.siso_nlen = olen;
break;
}
#endif /* SMALL */
@@ -1802,7 +1883,7 @@
if (! shortoutput) {
(void)printf(" route to: %s\n",
- routename(&soup->so_dst.sa, NULL, RTF_HOST));
+ routename(&soup->so_dst->sa, NULL, RTF_HOST));
}
if (rtm->rtm_version != RTM_VERSION) {
warnx("routing message version %d not understood",
@@ -2059,13 +2140,24 @@
which, iso_ntoa(&su->siso.siso_addr));
break;
case AF_MPLS:
- {
+ {
union mpls_shim ms;
+ const union mpls_shim *pms;
+ int psize = sizeof(struct sockaddr_mpls);
+
ms.s_addr = ntohl(su->smpls.smpls_addr.s_addr);
printf("%s: mpls %u; ",
which, ms.shim.label);
+
+ pms = &su->smpls.smpls_addr;
+ while(psize < su->smpls.smpls_len) {
+ pms++;
+ ms.s_addr = ntohl(pms->s_addr);
+ printf("%u; ", ms.shim.label);
+ psize += sizeof(ms);
}
break;
+ }
#endif /* SMALL */
default:
(void)printf("%s: (%d) %s; ",