{
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;
{
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;
{
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;
}
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));
}
}
-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;
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;
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