make fw3_ubus_address take a list_head * argument instead of allocating & returning one
authorFelix Fietkau <nbd@openwrt.org>
Mon, 30 Jun 2014 17:17:53 +0000 (19:17 +0200)
committerFelix Fietkau <nbd@openwrt.org>
Mon, 30 Jun 2014 18:52:21 +0000 (20:52 +0200)
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
options.c
redirects.c
ubus.c
ubus.h
zones.c

index 80e5542a420385a3e393164b2ac1f120982cc31c..e864db7ca3c3a12c9edeb0a87cf1ff5af60036c4 100644 (file)
--- a/options.c
+++ b/options.c
@@ -330,28 +330,20 @@ fw3_parse_network(void *ptr, const char *val, bool is_list)
 {
        struct fw3_device dev = { };
        struct fw3_address *addr;
-       struct list_head *addr_list;
+       LIST_HEAD(addr_list);
 
        if (!fw3_parse_address(ptr, val, is_list))
        {
                if (!fw3_parse_device(&dev, val, false))
                        return false;
 
-               addr_list = fw3_ubus_address(dev.name);
-
-               if (addr_list)
+               fw3_ubus_address(&addr_list, dev.name);
+               list_for_each_entry(addr, &addr_list, list)
                {
-                       list_for_each_entry(addr, addr_list, list)
-                       {
-                               addr->invert = dev.invert;
-                               addr->resolved = true;
-
-                               if (!put_value(ptr, addr, sizeof(*addr), is_list))
-                                       break;
-                       }
-
-                       fw3_free_list(addr_list);
+                       addr->invert = dev.invert;
+                       addr->resolved = true;
                }
+               list_splice_tail(&addr_list, ptr);
        }
 
        return true;
index f1fa1f431a79d8bb11daeaec5a7be9854933fc6d..080e2c17d49fc1117d1467260ab81cda0eb9b8d6 100644 (file)
@@ -171,8 +171,7 @@ check_local(struct uci_element *e, struct fw3_redirect *redir,
 {
        struct fw3_zone *zone;
        struct fw3_device *net;
-       struct fw3_address *addr;
-       struct list_head *addrs;
+       struct fw3_address *addr, *tmp;
 
        if (redir->target != FW3_FLAG_DNAT)
                return false;
@@ -187,25 +186,23 @@ check_local(struct uci_element *e, struct fw3_redirect *redir,
        {
                list_for_each_entry(net, &zone->networks, list)
                {
-                       addrs = fw3_ubus_address(net->name);
-
-                       if (!addrs)
-                               continue;
+                       LIST_HEAD(addrs);
 
-                       list_for_each_entry(addr, addrs, list)
+                       fw3_ubus_address(&addrs, net->name);
+                       list_for_each_entry_safe(addr, tmp, &addrs, list)
                        {
-                               if (!compare_addr(&redir->ip_redir, addr))
-                                       continue;
+                               if (compare_addr(&redir->ip_redir, addr)) {
+                                       warn_elem(e, "refers to a destination address on this router, "
+                                                    "assuming port redirection");
 
-                               warn_elem(e, "refers to a destination address on this router, "
-                                            "assuming port redirection");
+                                       redir->local = true;
+                                       continue;
+                               }
 
-                               redir->local = true;
-                               break;
+                               list_del(&addr->list);
+                               free(addr);
                        }
 
-                       fw3_free_list(addrs);
-
                        if (redir->local)
                                return true;
                }
diff --git a/ubus.c b/ubus.c
index 34e21b8d5b1e1bb8cbb659231d0818bbdfa68c58..a5f3a65a9d7c5b8ebe175ea32a77d481c9712abb 100644 (file)
--- a/ubus.c
+++ b/ubus.c
@@ -90,12 +90,16 @@ parse_subnet(enum fw3_family family, struct blob_attr *dict, int rem)
 
 static void
 parse_subnets(struct list_head *head, enum fw3_family family,
-              struct blob_attr *list, int rem)
+              struct blob_attr *list)
 {
        struct blob_attr *cur;
        struct fw3_address *addr;
+       int rem;
 
-       __blob_for_each_attr(cur, list, rem)
+       if (!list)
+               return;
+
+       blob_for_each_attr(cur, list, rem)
        {
                addr = parse_subnet(family, blobmsg_data(cur), blobmsg_data_len(cur));
 
@@ -104,11 +108,10 @@ parse_subnets(struct list_head *head, enum fw3_family family,
        }
 }
 
-static void *
-invoke_common(const char *net, bool device)
+struct fw3_device *
+fw3_ubus_device(const char *net)
 {
        struct fw3_device *dev = NULL;
-       struct list_head *addr = NULL;
        struct blob_attr *c, *cur;
        unsigned r, rem;
        char *data;
@@ -117,16 +120,9 @@ invoke_common(const char *net, bool device)
        if (!net || !interfaces)
                return NULL;
 
-       if (device)
-               dev = calloc(1, sizeof(*dev));
-       else
-               addr = malloc(sizeof(*addr));
-
-       if ((device && !dev) || (!device && !addr))
-               goto fail;
-
-       if (!device)
-               INIT_LIST_HEAD(addr);
+       dev = calloc(1, sizeof(*dev));
+       if (!dev)
+               return NULL;
 
        blobmsg_for_each_attr(c, interfaces, r) {
                matched = false;
@@ -140,47 +136,53 @@ invoke_common(const char *net, bool device)
                blobmsg_for_each_attr(cur, c, rem) {
                        data = blobmsg_data(cur);
 
-                       if (dev && !strcmp(blobmsg_name(cur), "device") && !dev->name[0])
+                       if (!strcmp(blobmsg_name(cur), "device") && !dev->name[0])
                                snprintf(dev->name, sizeof(dev->name), "%s", data);
-                       else if (dev && !strcmp(blobmsg_name(cur), "l3_device"))
+                       else if (!strcmp(blobmsg_name(cur), "l3_device"))
                                snprintf(dev->name, sizeof(dev->name), "%s", data);
-                       else if (!dev && !strcmp(blobmsg_name(cur), "ipv4-address"))
-                               parse_subnets(addr, FW3_FAMILY_V4,
-                                             blobmsg_data(cur), blobmsg_data_len(cur));
-                       else if (!dev && (!strcmp(blobmsg_name(cur), "ipv6-address") ||
-                                         !strcmp(blobmsg_name(cur), "ipv6-prefix-assignment")))
-                               parse_subnets(addr, FW3_FAMILY_V6,
-                                             blobmsg_data(cur), blobmsg_data_len(cur));
                }
 
-               if (dev)
-                       dev->set = !!dev->name[0];
-
-               break;
-       }
-
-       if (device && dev->set)
+               dev->set = !!dev->name[0];
                return dev;
-       else if (!device && !list_empty(addr))
-               return addr;
-
-fail:
-       free(dev);
-       free(addr);
+       }
 
        return NULL;
 }
 
-struct fw3_device *
-fw3_ubus_device(const char *net)
+void
+fw3_ubus_address(struct list_head *list, const char *net)
 {
-       return invoke_common(net, true);
-}
+       enum {
+               ADDR_INTERFACE,
+               ADDR_IPV4,
+               ADDR_IPV6,
+               ADDR_IPV6_PREFIX,
+               __ADDR_MAX
+       };
+       static const struct blobmsg_policy policy[__ADDR_MAX] = {
+               [ADDR_INTERFACE] = { "interface", BLOBMSG_TYPE_STRING },
+               [ADDR_IPV4] = { "ipv4-address", BLOBMSG_TYPE_ARRAY },
+               [ADDR_IPV6] = { "ipv6-address", BLOBMSG_TYPE_ARRAY },
+               [ADDR_IPV6_PREFIX] = { "ipv6-prefix-assignment", BLOBMSG_TYPE_ARRAY },
+       };
+       struct blob_attr *tb[__ADDR_MAX];
+       struct blob_attr *cur;
+       int rem;
 
-struct list_head *
-fw3_ubus_address(const char *net)
-{
-       return invoke_common(net, false);
+       if (!net || !interfaces)
+               return;
+
+       blobmsg_for_each_attr(cur, interfaces, rem) {
+               blobmsg_parse(policy, __ADDR_MAX, tb, blobmsg_data(cur), blobmsg_len(cur));
+
+               if (!tb[ADDR_INTERFACE] ||
+                   strcmp(blobmsg_data(tb[ADDR_INTERFACE]), net) != 0)
+                       continue;
+
+               parse_subnets(list, FW3_FAMILY_V4, tb[ADDR_IPV4]);
+               parse_subnets(list, FW3_FAMILY_V6, tb[ADDR_IPV6]);
+               parse_subnets(list, FW3_FAMILY_V6, tb[ADDR_IPV6_PREFIX]);
+       }
 }
 
 void
diff --git a/ubus.h b/ubus.h
index 35eac906d130fa40ceb476877e963f36e3160f99..58e598cbc2d7d438f5627109440398734c1cccbf 100644 (file)
--- a/ubus.h
+++ b/ubus.h
@@ -30,7 +30,7 @@ void fw3_ubus_disconnect(void);
 
 struct fw3_device * fw3_ubus_device(const char *net);
 
-struct list_head * fw3_ubus_address(const char *net);
+void fw3_ubus_address(struct list_head *list, const char *net);
 
 void fw3_ubus_zone_devices(struct fw3_zone *zone);
 
diff --git a/zones.c b/zones.c
index 53c62461b927b2ae61dca04fe47335ba32870b33..6ab3d12176e49c6c7a85dc8f4050280ed2bc538a 100644 (file)
--- a/zones.c
+++ b/zones.c
@@ -678,7 +678,7 @@ fw3_resolve_zone_addresses(struct fw3_zone *zone)
 {
        struct fw3_device *net;
        struct fw3_address *addr, *tmp;
-       struct list_head *addrs, *all;
+       struct list_head *all;
 
        all = calloc(1, sizeof(*all));
        if (!all)
@@ -687,20 +687,7 @@ fw3_resolve_zone_addresses(struct fw3_zone *zone)
        INIT_LIST_HEAD(all);
 
        list_for_each_entry(net, &zone->networks, list)
-       {
-               addrs = fw3_ubus_address(net->name);
-
-               if (!addrs)
-                       continue;
-
-               list_for_each_entry_safe(addr, tmp, addrs, list)
-               {
-                       list_del(&addr->list);
-                       list_add_tail(&addr->list, all);
-               }
-
-               free(addrs);
-       }
+               fw3_ubus_address(all, net->name);
 
        list_for_each_entry(addr, &zone->subnets, list)
        {