/*
* 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
struct fw3_device dev = { };
struct fw3_address *addr, *tmp;
LIST_HEAD(addr_list);
+ int n_addrs;
if (!fw3_parse_address(ptr, val, is_list))
{
if (!fw3_parse_device(&dev, val, false))
return false;
- fw3_ubus_address(&addr_list, dev.name);
+ n_addrs = fw3_ubus_address(&addr_list, dev.name);
+
list_for_each_entry(addr, &addr_list, list)
{
addr->invert = dev.invert;
addr->resolved = true;
}
+ /* add an empty address member with .set = false, .resolved = true
+ * to signal resolving failure to callers */
+ if (n_addrs == 0)
+ {
+ tmp = fw3_alloc(sizeof(*tmp));
+ tmp->resolved = true;
+
+ list_add_tail(&tmp->list, &addr_list);
+ }
+
if (is_list)
{
list_splice_tail(&addr_list, ptr);
if (*val == '!')
{
- setbit(*(uint8_t *)ptr, 0);
+ fw3_setbit(*(uint8_t *)ptr, 0);
while (isspace(*++val));
}
}
}
- setbit(*(uint8_t *)ptr, w);
+ fw3_setbit(*(uint8_t *)ptr, w);
}
free(s);
if (*val == '!')
{
- setbit(*(uint32_t *)ptr, 0);
+ fw3_setbit(*(uint32_t *)ptr, 0);
while (isspace(*++val));
}
return false;
}
- setbit(*(uint32_t *)ptr, d);
+ fw3_setbit(*(uint32_t *)ptr, d);
}
free(s);
struct uci_section *section)
{
char *p, *v;
- bool known;
+ bool known, inv;
struct uci_element *e, *l;
struct uci_option *o;
const struct fw3_option *opt;
}
else
{
+ inv = false;
dest = (struct list_head *)((char *)s + opt->offset);
for (p = strtok(v, " \t"); p != NULL; p = strtok(NULL, " \t"))
{
+ /* If we encounter a sole "!" token, assume that it
+ * is meant to be part of the next token, so silently
+ * skip it and remember the state... */
+ if (!strcmp(p, "!"))
+ {
+ inv = true;
+ continue;
+ }
+
+ /* The previous token was a sole "!", rewind pointer
+ * back by one byte to precede the value with an
+ * exclamation mark which effectively turns
+ * ("!", "foo") into ("!foo") */
+ if (inv)
+ {
+ *--p = '!';
+ inv = false;
+ }
+
if (!opt->parse(dest, p, true))
{
warn_elem(e, "has invalid value '%s'", p);
continue;
}
}
+
+ /* The last token was a sole "!" without any subsequent
+ * text, so pass it to the option parser as-is. */
+ if (inv && !opt->parse(dest, "!", true))
+ {
+ warn_elem(e, "has invalid value '%s'", p);
+ valid = false;
+ }
}
}