From 8fbd8ac8ddad83f7ea724f12a1f5e6bf4af50f88 Mon Sep 17 00:00:00 2001 From: Bernhard Reutner-Fischer Date: Tue, 21 Oct 2008 12:42:45 +0000 Subject: [PATCH] - fix ip route rejecting dotted quads as prefix - 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 | 64 ++++++++++++++++++----------------- networking/libiproute/utils.h | 2 ++ 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/networking/libiproute/utils.c b/networking/libiproute/utils.c index 706710e1f..cd101f176 100644 --- a/networking/libiproute/utils.c +++ b/networking/libiproute/utils.c @@ -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]; } diff --git a/networking/libiproute/utils.h b/networking/libiproute/utils.h index 607083af8..1af39ffe1 100644 --- a/networking/libiproute/utils.h +++ b/networking/libiproute/utils.h @@ -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