hush: remove superfluous assignment
[oweals/busybox.git] / networking / libiproute / utils.c
index 591c8933a390bf53d263eaec36e813ee580f7015..85034c0f66298e39e8eb4127a09511ebf671e2cd 100644 (file)
  */
 
 #include "libbb.h"
-
-#include <string.h>
-#include <unistd.h>
-
 #include "utils.h"
 #include "inet_common.h"
 
-int get_integer(int *val, char *arg, int base)
-{
-       long res;
-       char *ptr;
-
-       if (!arg || !*arg)
-               return -1;
-       res = strtol(arg, &ptr, base);
-       if (!ptr || ptr == arg || *ptr || res > INT_MAX || res < INT_MIN)
-               return -1;
-       *val = res;
-       return 0;
-}
-
-int get_unsigned(unsigned *val, char *arg, int base)
-{
-       unsigned long res;
-       char *ptr;
-
-       if (!arg || !*arg)
-               return -1;
-       res = strtoul(arg, &ptr, base);
-       if (!ptr || ptr == arg || *ptr || res > UINT_MAX)
-               return -1;
-       *val = res;
-       return 0;
-}
-
-int get_u32(uint32_t * val, char *arg, int base)
+unsigned get_unsigned(char *arg, const char *errmsg)
 {
        unsigned long res;
        char *ptr;
 
-       if (!arg || !*arg)
-               return -1;
-       res = strtoul(arg, &ptr, base);
-       if (!ptr || ptr == arg || *ptr || res > 0xFFFFFFFFUL)
-               return -1;
-       *val = res;
-       return 0;
+       if (*arg) {
+               res = strtoul(arg, &ptr, 0);
+//FIXME: "" will be accepted too, is it correct?!
+               if (!*ptr && res <= UINT_MAX) {
+                       return res;
+               }
+       }
+       invarg(arg, errmsg); /* does not return */
 }
 
-int get_u16(uint16_t * val, char *arg, int base)
+uint32_t get_u32(char *arg, const char *errmsg)
 {
        unsigned long res;
        char *ptr;
 
-       if (!arg || !*arg)
-               return -1;
-       res = strtoul(arg, &ptr, base);
-       if (!ptr || ptr == arg || *ptr || res > 0xFFFF)
-               return -1;
-       *val = res;
-       return 0;
+       if (*arg) {
+               res = strtoul(arg, &ptr, 0);
+//FIXME: "" will be accepted too, is it correct?!
+               if (!*ptr && res <= 0xFFFFFFFFUL) {
+                       return res;
+               }
+       }
+       invarg(arg, errmsg); /* does not return */
 }
 
-int get_u8(uint8_t * val, char *arg, int base)
+uint16_t get_u16(char *arg, const char *errmsg)
 {
        unsigned long res;
        char *ptr;
 
-       if (!arg || !*arg)
-               return -1;
-       res = strtoul(arg, &ptr, base);
-       if (!ptr || ptr == arg || *ptr || res > 0xFF)
-               return -1;
-       *val = res;
-       return 0;
-}
-
-int get_s16(int16_t * val, char *arg, int base)
-{
-       long res;
-       char *ptr;
-
-       if (!arg || !*arg)
-               return -1;
-       res = strtol(arg, &ptr, base);
-       if (!ptr || ptr == arg || *ptr || res > 0x7FFF || res < -0x8000)
-               return -1;
-       *val = res;
-       return 0;
-}
-
-int get_s8(int8_t * val, char *arg, int base)
-{
-       long res;
-       char *ptr;
-
-       if (!arg || !*arg)
-               return -1;
-       res = strtol(arg, &ptr, base);
-       if (!ptr || ptr == arg || *ptr || res > 0x7F || res < -0x80)
-               return -1;
-       *val = res;
-       return 0;
+       if (*arg) {
+               res = strtoul(arg, &ptr, 0);
+//FIXME: "" will be accepted too, is it correct?!
+               if (!*ptr && res <= 0xFFFF) {
+                       return res;
+               }
+       }
+       invarg(arg, errmsg); /* does not return */
 }
 
-int get_addr_1(inet_prefix * addr, char *name, int family)
+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 ||
-               strcmp(name, "all") == 0 || strcmp(name, "any") == 0) {
+       if (strcmp(name, bb_str_default) == 0
+        || strcmp(name, "all") == 0
+        || strcmp(name, "any") == 0
+       ) {
                addr->family = family;
                addr->bytelen = (family == AF_INET6 ? 16 : 4);
                addr->bitlen = -1;
@@ -147,32 +88,28 @@ 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)
+static int get_prefix_1(inet_prefix *dst, char *arg, int family)
 {
        int err;
-       int plen;
+       unsigned plen;
        char *slash;
 
        memset(dst, 0, sizeof(*dst));
 
-       if (strcmp(arg, bb_str_default) == 0 || strcmp(arg, "any") == 0) {
+       if (strcmp(arg, bb_str_default) == 0
+        || strcmp(arg, "all") == 0
+        || strcmp(arg, "any") == 0
+       ) {
                dst->family = family;
-               dst->bytelen = 0;
-               dst->bitlen = 0;
+               /*dst->bytelen = 0; - done by memset */
+               /*dst->bitlen = 0;*/
                return 0;
        }
 
@@ -181,46 +118,60 @@ 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;
+                       plen = bb_strtou(slash + 1, NULL, 0);
+                       if ((errno || 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 <= 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;
 }
 
-int get_addr(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;
 }
 
-int get_prefix(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;
 }
@@ -230,7 +181,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];
 }
@@ -255,18 +206,11 @@ void duparg2(const char *key, const char *arg)
        bb_error_msg_and_die("either \"%s\" is duplicate, or \"%s\" is garbage", key, arg);
 }
 
-int matches(const char *cmd, const char *pattern)
-{
-       int len = strlen(cmd);
-
-       return strncmp(pattern, cmd, len);
-}
-
-int inet_addr_match(inet_prefix * a, inet_prefix * b, int bits)
+int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits)
 {
        uint32_t *a1 = a->data;
        uint32_t *a2 = b->data;
-       int words = bits >> 0x05;
+       int words = bits >> 5;
 
        bits &= 0x1f;
 
@@ -290,7 +234,7 @@ int inet_addr_match(inet_prefix * a, inet_prefix * b, int bits)
        return 0;
 }
 
-const char *rt_addr_n2a(int af, int ATTRIBUTE_UNUSED len,
+const char *rt_addr_n2a(int af,
                void *addr, char *buf, int buflen)
 {
        switch (af) {
@@ -302,10 +246,9 @@ const char *rt_addr_n2a(int af, int ATTRIBUTE_UNUSED len,
        }
 }
 
-
+#ifdef RESOLVE_HOSTNAMES
 const char *format_host(int af, int len, void *addr, char *buf, int buflen)
 {
-#ifdef RESOLVE_HOSTNAMES
        if (resolve_hosts) {
                struct hostent *h_ent;
 
@@ -320,11 +263,14 @@ const char *format_host(int af, int len, void *addr, char *buf, int buflen)
                        default:;
                        }
                }
-               if (len > 0 && (h_ent = gethostbyaddr(addr, len, af)) != NULL) {
-                       snprintf(buf, buflen - 1, "%s", h_ent->h_name);
-                       return buf;
+               if (len > 0) {
+                       h_ent = gethostbyaddr(addr, len, af);
+                       if (h_ent != NULL) {
+                               safe_strncpy(buf, h_ent->h_name, buflen);
+                               return buf;
+                       }
                }
        }
-#endif
-       return rt_addr_n2a(af, len, addr, buf, buflen);
+       return rt_addr_n2a(af, addr, buf, buflen);
 }
+#endif