- 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"
No binary (build failed)
—
(log yok)
| @@ -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]; | |
| } | |
| @@ -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 | |