From 92281eb747b56e748b7c3d754055919c23befdd4 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 30 Jun 2014 19:17:53 +0200 Subject: [PATCH] make fw3_ubus_address take a list_head * argument instead of allocating & returning one Signed-off-by: Felix Fietkau --- options.c | 20 ++++-------- redirects.c | 27 +++++++--------- ubus.c | 92 +++++++++++++++++++++++++++-------------------------- ubus.h | 2 +- zones.c | 17 ++-------- 5 files changed, 68 insertions(+), 90 deletions(-) diff --git a/options.c b/options.c index 80e5542..e864db7 100644 --- 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; diff --git a/redirects.c b/redirects.c index f1fa1f4..080e2c1 100644 --- a/redirects.c +++ b/redirects.c @@ -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 34e21b8..a5f3a65 100644 --- 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 35eac90..58e598c 100644 --- 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 53c6246..6ab3d12 100644 --- 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) { -- 2.25.1