X-Git-Url: http://git.archive.openwrt.org/?p=project%2Ffirewall3.git;a=blobdiff_plain;f=options.c;h=d990cada687277c12a92efb26817785b21001975;hp=d88d3ba09b50b6f17173af7fbac5071a692fe440;hb=f50a524847a0ac74ef8cc74011d3cc46e9269c6b;hpb=18f4c6fda6afb912f53ded3112b1f270ddf5ff6c diff --git a/options.c b/options.c index d88d3ba..d990cad 100644 --- a/options.c +++ b/options.c @@ -75,6 +75,7 @@ const char *fw3_flag_names[__FW3_FLAG_MAX] = { "REJECT", "DROP", "NOTRACK", + "HELPER", "MARK", "DNAT", "SNAT", @@ -342,19 +343,31 @@ fw3_parse_network(void *ptr, const char *val, bool is_list) 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); @@ -885,13 +898,35 @@ fw3_parse_direction(void *ptr, const char *val, bool is_list) return valid; } +bool +fw3_parse_cthelper(void *ptr, const char *val, bool is_list) +{ + struct fw3_cthelpermatch m = { }; + + if (*val == '!') + { + m.invert = true; + while (isspace(*++val)); + } + + if (*val) + { + m.set = true; + strncpy(m.name, val, sizeof(m.name) - 1); + put_value(ptr, &m, sizeof(m), is_list); + return true; + } + + return false; +} + bool fw3_parse_options(void *s, const struct fw3_option *opts, 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; @@ -953,10 +988,30 @@ fw3_parse_options(void *s, const struct fw3_option *opts, } 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); @@ -964,6 +1019,14 @@ fw3_parse_options(void *s, const struct fw3_option *opts, 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; + } } }