- fix ip route rejecting dotted quads as prefix
authorBernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Tue, 21 Oct 2008 12:42:45 +0000 (12:42 -0000)
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Tue, 21 Oct 2008 12:42:45 +0000 (12:42 -0000)
- adjust error message for wrong prefix not to mention address
  Previously e.g. ip route add 127.0.0.0/255.0.0.0 dev dummy0
  was rejected, saying
ip: an inet address is expected rather than "127.0.0.0/255.0.0.0"

function                                             old     new   delta
get_prefix_1                                         201     309    +108
get_prefix                                            55      73     +18
get_addr                                              55      73     +18
get_addr32                                            48      58     +10
get_addr_1                                           249     204     -45
.rodata                                           114569  114524     -45
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/2 up/down: 154/-90)            Total: 64 bytes

networking/libiproute/utils.c
networking/libiproute/utils.h

index 706710e1f3769016b66c5ecbcffc17337467abcb..cd101f176c30c66cb7a6a4b8331ed8e7f23081c8 100644 (file)
@@ -115,10 +115,6 @@ int get_s8(int8_t * val, char *arg, int base)
 
 int get_addr_1(inet_prefix * addr, char *name, int family)
 {
-       char *cp;
-       unsigned char *ap = (unsigned char *) addr->data;
-       int i;
-
        memset(addr, 0, sizeof(*addr));
 
        if (strcmp(name, bb_str_default) == 0 ||
@@ -143,24 +139,17 @@ int get_addr_1(inet_prefix * addr, char *name, int family)
        addr->family = AF_INET;
        if (family != AF_UNSPEC && family != AF_INET)
                return -1;
+       if (inet_pton(AF_INET, name, addr->data) <= 0)
+               return -1;
        addr->bytelen = 4;
        addr->bitlen = -1;
-       for (cp = name, i = 0; *cp; cp++) {
-               if (*cp <= '9' && *cp >= '0') {
-                       ap[i] = 10 * ap[i] + (*cp - '0');
-                       continue;
-               }
-               if (*cp == '.' && ++i <= 3)
-                       continue;
-               return -1;
-       }
        return 0;
 }
 
 int get_prefix_1(inet_prefix * dst, char *arg, int family)
 {
        int err;
-       int plen;
+       unsigned plen;
        char *slash;
 
        memset(dst, 0, sizeof(*dst));
@@ -177,23 +166,36 @@ int get_prefix_1(inet_prefix * dst, char *arg, int family)
                *slash = '\0';
        err = get_addr_1(dst, arg, family);
        if (err == 0) {
-               switch (dst->family) {
-               case AF_INET6:
-                       dst->bitlen = 128;
-                       break;
-               default:
-               case AF_INET:
-                       dst->bitlen = 32;
-               }
+               dst->bitlen = (dst->family == AF_INET6) ? 128 : 32;
                if (slash) {
-                       if (get_integer(&plen, slash + 1, 0) || plen > dst->bitlen) {
+                       inet_prefix netmask_pfx;
+
+                       netmask_pfx.family = AF_UNSPEC;
+                       if ((get_unsigned(&plen, slash + 1, 0) || plen > dst->bitlen)
+                               && (get_addr_1(&netmask_pfx, slash + 1, family)))
                                err = -1;
-                               goto done;
+                       else if (netmask_pfx.family == AF_INET) {
+                               /* fill in prefix length of dotted quad */
+                               uint32_t mask = ntohl(netmask_pfx.data[0]);
+                               uint32_t host = ~mask;
+
+                               /* a valid netmask must be 2^n - 1 */
+                               if (!(host & (host + 1))) {
+                                       for (plen = 0; mask; mask <<= 1)
+                                               ++plen;
+                                       if (plen >= 0 && plen <= dst->bitlen) {
+                                                       dst->bitlen = plen;
+                                                       /* dst->flags |= PREFIXLEN_SPECIFIED; */
+                                       } else
+                                               err = -1;
+                               } else
+                                       err = -1;
+                       } else {
+                               /* plain prefix */
+                               dst->bitlen = plen;
                        }
-                       dst->bitlen = plen;
                }
        }
- done:
        if (slash)
                *slash = '/';
        return err;
@@ -202,10 +204,10 @@ int get_prefix_1(inet_prefix * dst, char *arg, int family)
 int get_addr(inet_prefix * dst, char *arg, int family)
 {
        if (family == AF_PACKET) {
-               bb_error_msg_and_die("\"%s\" may be inet address, but it is not allowed in this context", arg);
+               bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg, "address");
        }
        if (get_addr_1(dst, arg, family)) {
-               bb_error_msg_and_die("an inet address is expected rather than \"%s\"", arg);
+               bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "inet", "address", arg);
        }
        return 0;
 }
@@ -213,10 +215,10 @@ int get_addr(inet_prefix * dst, char *arg, int family)
 int get_prefix(inet_prefix * dst, char *arg, int family)
 {
        if (family == AF_PACKET) {
-               bb_error_msg_and_die("\"%s\" may be inet address, but it is not allowed in this context", arg);
+               bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg, "prefix");
        }
        if (get_prefix_1(dst, arg, family)) {
-               bb_error_msg_and_die("an inet address is expected rather than \"%s\"", arg);
+               bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "inet", "prefix", arg);
        }
        return 0;
 }
@@ -226,7 +228,7 @@ uint32_t get_addr32(char *name)
        inet_prefix addr;
 
        if (get_addr_1(&addr, name, AF_INET)) {
-               bb_error_msg_and_die("an IP address is expected rather than \"%s\"", name);
+               bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "IP", "address", name);
        }
        return addr.data[0];
 }
index 607083af8797c3708f94c238a47a86d40d411326..1af39ffe11bec58b793f359cb1b79b86773ff6a1 100644 (file)
@@ -39,6 +39,8 @@ typedef struct {
        uint32_t data[4];
 } inet_prefix;
 
+#define PREFIXLEN_SPECIFIED 1
+
 #define DN_MAXADDL 20
 #ifndef AF_DECnet
 #define AF_DECnet 12