diff options
author | Jo-Philipp Wich <jo@mein.io> | 2017-05-26 18:42:05 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2017-05-26 18:52:28 +0200 |
commit | 3d2c18a91bb7cd5f3c0dec7fecf3008934de170b (patch) | |
tree | 3dcf10fa98db75b3c0d6febf8e32a3d449da2bd2 | |
parent | 0e5dd73076c3dc23a6971784640dd7e36f99b6d5 (diff) | |
download | firewall3-3d2c18a91bb7cd5f3c0dec7fecf3008934de170b.tar.gz |
options: improve handling of negations when parsing space separated values
Improve the space separated list parser to interprete "val1 ! val2"
as ("val1", "!val2") instead of ("val1", "!", "val2").
This corrects parsing of sections like ...
config rule
option sec_ip '! 1.1.1.0/24'
... which previously errored out with:
Warning: Option @rule[0].src_ip has invalid value '!'
Fixes FS#806.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r-- | options.c | 31 |
1 files changed, 30 insertions, 1 deletions
@@ -891,7 +891,7 @@ 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 +953,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 +984,15 @@ 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; + continue; + } } } |