Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sbin/route Alloc dynamically sockunions in sou.



details:   https://anonhg.NetBSD.org/src/rev/5cd09b92733c
branches:  trunk
changeset: 766395:5cd09b92733c
user:      kefren <kefren%NetBSD.org@localhost>
date:      Tue Jun 21 14:33:14 2011 +0000

description:
Alloc dynamically sockunions in sou.
Teach route(8) about multiple tags. E.G.: -tag 100,20,33
XXX: needs documentation

diffstat:

 sbin/route/route.c |  196 ++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 144 insertions(+), 52 deletions(-)

diffs (truncated from 389 to 300 lines):

diff -r 400b37b2685e -r 5cd09b92733c sbin/route/route.c
--- a/sbin/route/route.c        Tue Jun 21 14:30:19 2011 +0000
+++ b/sbin/route/route.c        Tue Jun 21 14:33:14 2011 +0000
@@ -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;
                }



Home | Main Index | Thread Index | Old Index