X-Git-Url: http://git.archive.openwrt.org/?p=project%2Ffirewall3.git;a=blobdiff_plain;f=options.c;h=087aa630469afa8eea81238a4fb9c6accc44d414;hp=f41153c693f35e509a3c531e2a7afa437ae67ddf;hb=0e77bf296648c5db92c269c678d27f6846de4e9f;hpb=50e97c52e75bdfd325cf20d43b32d294ff84d92f diff --git a/options.c b/options.c index f41153c..087aa63 100644 --- a/options.c +++ b/options.c @@ -1,7 +1,7 @@ /* * firewall3 - 3rd OpenWrt UCI firewall implementation * - * Copyright (C) 2013-2014 Jo-Philipp Wich + * Copyright (C) 2013-2014 Jo-Philipp Wich * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -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); @@ -628,6 +641,7 @@ fw3_parse_date(void *ptr, const char *val, bool is_list) { unsigned int year = 1970, mon = 1, day = 1, hour = 0, min = 0, sec = 0; struct tm tm = { 0 }; + time_t ts; char *p; year = strtoul(val, &p, 10); @@ -672,9 +686,11 @@ ret: tm.tm_min = min; tm.tm_sec = sec; - if (mktime(&tm) >= 0) + ts = mktime(&tm) - timezone; + + if (ts >= 0) { - *((struct tm *)ptr) = tm; + gmtime_r(&ts, (struct tm *)ptr); return true; } @@ -718,7 +734,7 @@ fw3_parse_weekdays(void *ptr, const char *val, bool is_list) if (*val == '!') { - setbit(*(uint8_t *)ptr, 0); + fw3_setbit(*(uint8_t *)ptr, 0); while (isspace(*++val)); } @@ -738,7 +754,7 @@ fw3_parse_weekdays(void *ptr, const char *val, bool is_list) } } - setbit(*(uint8_t *)ptr, w); + fw3_setbit(*(uint8_t *)ptr, w); } free(s); @@ -753,7 +769,7 @@ fw3_parse_monthdays(void *ptr, const char *val, bool is_list) if (*val == '!') { - setbit(*(uint32_t *)ptr, 0); + fw3_setbit(*(uint32_t *)ptr, 0); while (isspace(*++val)); } @@ -770,7 +786,7 @@ fw3_parse_monthdays(void *ptr, const char *val, bool is_list) return false; } - setbit(*(uint32_t *)ptr, d); + fw3_setbit(*(uint32_t *)ptr, d); } free(s); @@ -885,13 +901,46 @@ 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_setentry(void *ptr, const char *val, bool is_list) +{ + struct fw3_setentry e = { }; + + e.value = val; + put_value(ptr, &e, sizeof(e), is_list); + + return true; +} + 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 +1002,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 +1033,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; + } } } @@ -981,7 +1058,7 @@ fw3_parse_options(void *s, const struct fw3_option *opts, bool fw3_parse_blob_options(void *s, const struct fw3_option *opts, - struct blob_attr *a) + struct blob_attr *a, const char *name) { char *p, *v, buf[16]; bool known; @@ -1007,7 +1084,9 @@ fw3_parse_blob_options(void *s, const struct fw3_option *opts, { if (!opt->elem_size) { - fprintf(stderr, "%s must not be a list\n", opt->name); + fprintf(stderr, "%s: '%s' must not be a list\n", + name, opt->name); + valid = false; } else @@ -1025,7 +1104,8 @@ fw3_parse_blob_options(void *s, const struct fw3_option *opts, if (!opt->parse(dest, v, true)) { - fprintf(stderr, "%s has invalid value '%s'\n", opt->name, v); + fprintf(stderr, "%s: '%s' has invalid value '%s'\n", + name, opt->name, v); valid = false; continue; } @@ -1048,7 +1128,8 @@ fw3_parse_blob_options(void *s, const struct fw3_option *opts, { if (!opt->parse((char *)s + opt->offset, v, false)) { - fprintf(stderr, "%s has invalid value '%s'\n", opt->name, v); + fprintf(stderr, "%s: '%s' has invalid value '%s'\n", + name, opt->name, v); valid = false; } } @@ -1060,7 +1141,8 @@ fw3_parse_blob_options(void *s, const struct fw3_option *opts, { if (!opt->parse(dest, p, true)) { - fprintf(stderr, "%s has invalid value '%s'\n", opt->name, p); + fprintf(stderr, "%s: '%s' has invalid value '%s'\n", + name, opt->name, p); valid = false; continue; } @@ -1072,8 +1154,8 @@ fw3_parse_blob_options(void *s, const struct fw3_option *opts, break; } - if (!known) - fprintf(stderr, "%s is unknown\n", blobmsg_name(o)); + if (!known && strcmp(blobmsg_name(o), "type")) + fprintf(stderr, "%s: '%s' is unknown\n", name, blobmsg_name(o)); } return valid;