cmake: Find uci.h
[project/firewall3.git] / options.c
index 25668fc..407931b 100644 (file)
--- a/options.c
+++ b/options.c
@@ -1,7 +1,7 @@
 /*
  * firewall3 - 3rd OpenWrt UCI firewall implementation
  *
- *   Copyright (C) 2013-2014 Jo-Philipp Wich <jow@openwrt.org>
+ *   Copyright (C) 2013-2014 Jo-Philipp Wich <jo@mein.io>
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -244,8 +244,8 @@ fw3_parse_address(void *ptr, const char *val, bool is_list)
        struct fw3_address addr = { };
        struct in_addr v4;
        struct in6_addr v6;
-       char *p, *s, *e;
-       int i, m = -1;
+       char *p = NULL, *m = NULL, *s, *e;
+       int bits = -1;
 
        if (*val == '!')
        {
@@ -258,71 +258,82 @@ fw3_parse_address(void *ptr, const char *val, bool is_list)
        if (!s)
                return false;
 
-       if ((p = strchr(s, '/')) != NULL)
-       {
+       if ((m = strchr(s, '/')) != NULL)
+               *m++ = 0;
+       else if ((p = strchr(s, '-')) != NULL)
                *p++ = 0;
-               m = strtoul(p, &e, 10);
 
-               if ((e == p) || (*e != 0))
+       if (inet_pton(AF_INET6, s, &v6))
+       {
+               addr.family = FW3_FAMILY_V6;
+               addr.address.v6 = v6;
+
+               if (m)
                {
-                       if (strchr(s, ':') || !inet_pton(AF_INET, p, &v4))
+                       if (!inet_pton(AF_INET6, m, &v6))
                        {
-                               free(s);
-                               return false;
-                       }
+                               bits = strtol(m, &e, 10);
 
-                       for (i = 0, m = 32; !(v4.s_addr & 1) && (i < 32); i++)
-                       {
-                               m--;
-                               v4.s_addr >>= 1;
+                               if ((*e != 0) || !fw3_bitlen2netmask(addr.family, bits, &v6))
+                                       goto fail;
                        }
-               }
-       }
-       else if ((p = strchr(s, '-')) != NULL)
-       {
-               *p++ = 0;
 
-               if (inet_pton(AF_INET6, p, &v6))
-               {
-                       addr.family = FW3_FAMILY_V6;
-                       addr.address2.v6 = v6;
-                       addr.range = true;
+                       addr.mask.v6 = v6;
                }
-               else if (inet_pton(AF_INET, p, &v4))
+               else if (p)
                {
-                       addr.family = FW3_FAMILY_V4;
-                       addr.address2.v4 = v4;
+                       if (!inet_pton(AF_INET6, p, &addr.mask.v6))
+                               goto fail;
+
                        addr.range = true;
                }
                else
                {
-                       free(s);
-                       return false;
+                       memset(addr.mask.v6.s6_addr, 0xFF, 16);
                }
        }
-
-       if (inet_pton(AF_INET6, s, &v6))
-       {
-               addr.family = FW3_FAMILY_V6;
-               addr.address.v6 = v6;
-               addr.mask = (m >= 0) ? m : 128;
-       }
        else if (inet_pton(AF_INET, s, &v4))
        {
                addr.family = FW3_FAMILY_V4;
                addr.address.v4 = v4;
-               addr.mask = (m >= 0) ? m : 32;
+
+               if (m)
+               {
+                       if (!inet_pton(AF_INET, m, &v4))
+                       {
+                               bits = strtol(m, &e, 10);
+
+                               if ((*e != 0) || !fw3_bitlen2netmask(addr.family, bits, &v4))
+                                       goto fail;
+                       }
+
+                       addr.mask.v4 = v4;
+               }
+               else if (p)
+               {
+                       if (!inet_pton(AF_INET, p, &addr.mask.v4))
+                               goto fail;
+
+                       addr.range = true;
+               }
+               else
+               {
+                       addr.mask.v4.s_addr = 0xFFFFFFFF;
+               }
        }
        else
        {
-               free(s);
-               return false;
+               goto fail;
        }
 
        free(s);
        addr.set = true;
        put_value(ptr, &addr, sizeof(addr), is_list);
        return true;
+
+fail:
+       free(s);
+       return false;
 }
 
 bool
@@ -431,7 +442,7 @@ fw3_parse_port(void *ptr, const char *val, bool is_list)
 bool
 fw3_parse_family(void *ptr, const char *val, bool is_list)
 {
-       if (!strcmp(val, "any"))
+       if (!strcmp(val, "any") || !strcmp(val, "*"))
                *((enum fw3_family *)ptr) = FW3_FAMILY_ANY;
        else if (!strcmp(val, "inet") || strrchr(val, '4'))
                *((enum fw3_family *)ptr) = FW3_FAMILY_V4;
@@ -532,7 +543,7 @@ fw3_parse_protocol(void *ptr, const char *val, bool is_list)
                while (isspace(*++val));
        }
 
-       if (!strcmp(val, "all"))
+       if (!strcmp(val, "all") || !strcmp(val, "any") || !strcmp(val, "*"))
        {
                proto.any = true;
                put_value(ptr, &proto, sizeof(proto), is_list);
@@ -970,7 +981,7 @@ fw3_parse_options(void *s, const struct fw3_option *opts,
 
 bool
 fw3_parse_blob_options(void *s, const struct fw3_option *opts,
-                  struct blob_attr *a)
+                       struct blob_attr *a, const char *name)
 {
        char *p, *v, buf[16];
        bool known;
@@ -996,7 +1007,9 @@ fw3_parse_blob_options(void *s, const struct fw3_option *opts,
                        {
                                if (!opt->elem_size)
                                {
-                                       fprintf(stderr, "%s must not be a list\n", opt->name);
+                                       fprintf(stderr, "%s: '%s' must not be a list\n",
+                                               name, opt->name);
+
                                        valid = false;
                                }
                                else
@@ -1014,7 +1027,8 @@ fw3_parse_blob_options(void *s, const struct fw3_option *opts,
 
                                                if (!opt->parse(dest, v, true))
                                                {
-                                                       fprintf(stderr, "%s has invalid value '%s'\n", opt->name, v);
+                                                       fprintf(stderr, "%s: '%s' has invalid value '%s'\n",
+                                                               name, opt->name, v);
                                                        valid = false;
                                                        continue;
                                                }
@@ -1037,7 +1051,8 @@ fw3_parse_blob_options(void *s, const struct fw3_option *opts,
                                {
                                        if (!opt->parse((char *)s + opt->offset, v, false))
                                        {
-                                               fprintf(stderr, "%s has invalid value '%s'\n", opt->name, v);
+                                               fprintf(stderr, "%s: '%s' has invalid value '%s'\n",
+                                                       name, opt->name, v);
                                                valid = false;
                                        }
                                }
@@ -1049,7 +1064,8 @@ fw3_parse_blob_options(void *s, const struct fw3_option *opts,
                                        {
                                                if (!opt->parse(dest, p, true))
                                                {
-                                                       fprintf(stderr, "%s has invalid value '%s'\n", opt->name, p);
+                                                       fprintf(stderr, "%s: '%s' has invalid value '%s'\n",
+                                                               name, opt->name, p);
                                                        valid = false;
                                                        continue;
                                                }
@@ -1061,8 +1077,8 @@ fw3_parse_blob_options(void *s, const struct fw3_option *opts,
                        break;
                }
 
-               if (!known)
-                       fprintf(stderr, "%s is unknown\n", blobmsg_name(o));
+               if (!known && strcmp(blobmsg_name(o), "type"))
+                       fprintf(stderr, "%s: '%s' is unknown\n", name, blobmsg_name(o));
        }
 
        return valid;
@@ -1070,7 +1086,7 @@ fw3_parse_blob_options(void *s, const struct fw3_option *opts,
 
 
 const char *
-fw3_address_to_string(struct fw3_address *address, bool allow_invert)
+fw3_address_to_string(struct fw3_address *address, bool allow_invert, bool as_cidr)
 {
        char *p, ip[INET6_ADDRSTRLEN];
        static char buf[INET6_ADDRSTRLEN * 2 + 2];
@@ -1088,13 +1104,21 @@ fw3_address_to_string(struct fw3_address *address, bool allow_invert)
        if (address->range)
        {
                inet_ntop(address->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6,
-                         &address->address2.v4, ip, sizeof(ip));
+                         &address->mask.v4, ip, sizeof(ip));
 
                p += sprintf(p, "-%s", ip);
        }
+       else if (!as_cidr)
+       {
+               inet_ntop(address->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6,
+                         &address->mask.v4, ip, sizeof(ip));
+
+               p += sprintf(p, "/%s", ip);
+       }
        else
        {
-               p += sprintf(p, "/%u", address->mask);
+               p += sprintf(p, "/%u", fw3_netmask2bitlen(address->family,
+                                                         &address->mask.v6));
        }
 
        return buf;