X-Git-Url: http://git.archive.openwrt.org/?p=project%2Ffirewall3.git;a=blobdiff_plain;f=options.c;h=5c529b30f2b512d1de903836a13f670779bec420;hp=1f10050bb14d1117c7c50ef15230c5a42157c141;hb=ff9d5e13c9150c62fe698e4bc5541e6f92b241d0;hpb=23741a3279981c5e0ce3ca9e00e368d4f0b142b6 diff --git a/options.c b/options.c index 1f10050..5c529b3 100644 --- a/options.c +++ b/options.c @@ -18,7 +18,29 @@ #include "options.h" -const char *fw3_flag_names[FW3_DEFAULT_DROP_INVALID + 1] = { + +static bool +parse_enum(void *ptr, const char *val, const char **values, int min, int max) +{ + int i, l = strlen(val); + + if (l > 0) + { + for (i = 0; i <= (max - min); i++) + { + if (!strncasecmp(val, values[i], l)) + { + *((int *)ptr) = min + i; + return true; + } + } + } + + return false; +} + + +const char *fw3_flag_names[__FW3_FLAG_MAX] = { "filter", "nat", "mangle", @@ -33,8 +55,54 @@ const char *fw3_flag_names[FW3_DEFAULT_DROP_INVALID + 1] = { "NOTRACK", "DNAT", "SNAT", + + "ACCEPT", + "REJECT", + "DROP", +}; + +static const char *limit_units[] = { + "second", + "minute", + "hour", + "day", +}; + +static const char *ipset_methods[] = { + "bitmap", + "hash", + "list", +}; + +static const char *ipset_types[] = { + "ip", + "port", + "mac", + "net", + "set", +}; + +static const char *weekdays[] = { + "monday", + "tuesday", + "wednesday", + "thursday", + "friday", + "saturday", + "sunday", }; +static const char *include_types[] = { + "script", + "restore", +}; + +static const char *reflection_sources[] = { + "internal", + "external", +}; + + bool fw3_parse_bool(void *ptr, const char *val) { @@ -69,38 +137,8 @@ fw3_parse_string(void *ptr, const char *val) bool fw3_parse_target(void *ptr, const char *val) { - if (!strcmp(val, "ACCEPT")) - { - *((enum fw3_target *)ptr) = FW3_TARGET_ACCEPT; - return true; - } - else if (!strcmp(val, "REJECT")) - { - *((enum fw3_target *)ptr) = FW3_TARGET_REJECT; - return true; - } - else if (!strcmp(val, "DROP")) - { - *((enum fw3_target *)ptr) = FW3_TARGET_DROP; - return true; - } - else if (!strcmp(val, "NOTRACK")) - { - *((enum fw3_target *)ptr) = FW3_TARGET_NOTRACK; - return true; - } - else if (!strcmp(val, "DNAT")) - { - *((enum fw3_target *)ptr) = FW3_TARGET_DNAT; - return true; - } - else if (!strcmp(val, "SNAT")) - { - *((enum fw3_target *)ptr) = FW3_TARGET_SNAT; - return true; - } - - return false; + return parse_enum(ptr, val, &fw3_flag_names[FW3_FLAG_ACCEPT], + FW3_FLAG_ACCEPT, FW3_FLAG_SNAT); } bool @@ -128,15 +166,7 @@ fw3_parse_limit(void *ptr, const char *val) if (!strlen(e)) return false; - if (!strncmp(e, "second", strlen(e))) - u = FW3_LIMIT_UNIT_SECOND; - else if (!strncmp(e, "minute", strlen(e))) - u = FW3_LIMIT_UNIT_MINUTE; - else if (!strncmp(e, "hour", strlen(e))) - u = FW3_LIMIT_UNIT_HOUR; - else if (!strncmp(e, "day", strlen(e))) - u = FW3_LIMIT_UNIT_DAY; - else + if (!parse_enum(&u, e, limit_units, 0, FW3_LIMIT_UNIT_DAY)) return false; limit->rate = n; @@ -212,6 +242,28 @@ fw3_parse_address(void *ptr, const char *val) } } } + else if ((p = strchr(s, '-')) != NULL) + { + *p++ = 0; + + if (inet_pton(AF_INET6, p, &v6)) + { + addr->family = FW3_FAMILY_V6; + addr->address2.v6 = v6; + addr->range = true; + } + else if (inet_pton(AF_INET, p, &v4)) + { + addr->family = FW3_FAMILY_V4; + addr->address2.v4 = v4; + addr->range = true; + } + else + { + free(s); + return false; + } + } if (inet_pton(AF_INET6, s, &v6)) { @@ -427,23 +479,8 @@ fw3_parse_protocol(void *ptr, const char *val) bool fw3_parse_ipset_method(void *ptr, const char *val) { - if (!strncmp(val, "bitmap", strlen(val))) - { - *((enum fw3_ipset_method *)ptr) = FW3_IPSET_METHOD_BITMAP; - return true; - } - else if (!strncmp(val, "hash", strlen(val))) - { - *((enum fw3_ipset_method *)ptr) = FW3_IPSET_METHOD_HASH; - return true; - } - else if (!strncmp(val, "list", strlen(val))) - { - *((enum fw3_ipset_method *)ptr) = FW3_IPSET_METHOD_LIST; - return true; - } - - return false; + return parse_enum(ptr, val, ipset_methods, + FW3_IPSET_METHOD_BITMAP, FW3_IPSET_METHOD_LIST); } bool @@ -467,47 +504,188 @@ fw3_parse_ipset_datatype(void *ptr, const char *val) type->dest = false; } - if (!strncmp(val, "ip", strlen(val))) + return parse_enum(&type->type, val, ipset_types, + FW3_IPSET_TYPE_IP, FW3_IPSET_TYPE_SET); +} + +bool +fw3_parse_date(void *ptr, const char *val) +{ + unsigned int year = 1970, mon = 1, day = 1, hour = 0, min = 0, sec = 0; + struct tm tm = { 0 }; + char *p; + + year = strtoul(val, &p, 10); + if ((*p != '-' && *p) || year < 1970 || year > 2038) + goto fail; + else if (!*p) + goto ret; + + mon = strtoul(++p, &p, 10); + if ((*p != '-' && *p) || mon > 12) + goto fail; + else if (!*p) + goto ret; + + day = strtoul(++p, &p, 10); + if ((*p != 'T' && *p) || day > 31) + goto fail; + else if (!*p) + goto ret; + + hour = strtoul(++p, &p, 10); + if ((*p != ':' && *p) || hour > 23) + goto fail; + else if (!*p) + goto ret; + + min = strtoul(++p, &p, 10); + if ((*p != ':' && *p) || min > 59) + goto fail; + else if (!*p) + goto ret; + + sec = strtoul(++p, &p, 10); + if (*p || sec > 59) + goto fail; + +ret: + tm.tm_year = year - 1900; + tm.tm_mon = mon - 1; + tm.tm_mday = day; + tm.tm_hour = hour; + tm.tm_min = min; + tm.tm_sec = sec; + + if (mktime(&tm) >= 0) { - type->type = FW3_IPSET_TYPE_IP; + *((struct tm *)ptr) = tm; return true; } - else if (!strncmp(val, "port", strlen(val))) + +fail: + return false; +} + +bool +fw3_parse_time(void *ptr, const char *val) +{ + unsigned int hour = 0, min = 0, sec = 0; + char *p; + + hour = strtoul(val, &p, 10); + if (*p != ':' || hour > 23) + goto fail; + + min = strtoul(++p, &p, 10); + if ((*p != ':' && *p) || min > 59) + goto fail; + else if (!*p) + goto ret; + + sec = strtoul(++p, &p, 10); + if (*p || sec > 59) + goto fail; + +ret: + *((int *)ptr) = 60 * 60 * hour + 60 * min + sec; + return true; + +fail: + return false; +} + +bool +fw3_parse_weekdays(void *ptr, const char *val) +{ + unsigned int w = 0; + char *p, *s; + + if (*val == '!') { - type->type = FW3_IPSET_TYPE_PORT; - return true; + setbit(*(uint8_t *)ptr, 0); + while (isspace(*++val)); } - else if (!strncmp(val, "mac", strlen(val))) + + if (!(s = strdup(val))) + return false; + + for (p = strtok(s, " \t"); p; p = strtok(NULL, " \t")) { - type->type = FW3_IPSET_TYPE_MAC; - return true; + if (!parse_enum(&w, p, weekdays, 1, 7)) + { + w = strtoul(p, &p, 10); + + if (*p || w < 1 || w > 7) + { + free(s); + return false; + } + } + + setbit(*(uint8_t *)ptr, w); } - else if (!strncmp(val, "net", strlen(val))) + + free(s); + return true; +} + +bool +fw3_parse_monthdays(void *ptr, const char *val) +{ + unsigned int d; + char *p, *s; + + if (*val == '!') { - type->type = FW3_IPSET_TYPE_NET; - return true; + setbit(*(uint32_t *)ptr, 0); + while (isspace(*++val)); } - else if (!strncmp(val, "set", strlen(val))) + + if (!(s = strdup(val))) + return false; + + for (p = strtok(s, " \t"); p; p = strtok(NULL, " \t")) { - type->type = FW3_IPSET_TYPE_SET; - return true; + d = strtoul(p, &p, 10); + + if (*p || d < 1 || d > 31) + { + free(s); + return false; + } + + setbit(*(uint32_t *)ptr, d); } - return false; + free(s); + return true; +} + +bool +fw3_parse_include_type(void *ptr, const char *val) +{ + return parse_enum(ptr, val, include_types, + FW3_INC_TYPE_SCRIPT, FW3_INC_TYPE_RESTORE); +} + +bool +fw3_parse_reflection_source(void *ptr, const char *val) +{ + return parse_enum(ptr, val, reflection_sources, + FW3_REFLECTION_INTERNAL, FW3_REFLECTION_EXTERNAL); } void -fw3_parse_options(void *s, - struct fw3_option *opts, int n, +fw3_parse_options(void *s, const struct fw3_option *opts, struct uci_section *section) { - int i; - char *p; + char *p, *v; bool known; struct uci_element *e, *l; struct uci_option *o; - struct fw3_option *opt; + const struct fw3_option *opt; struct list_head *item; struct list_head *dest; @@ -516,11 +694,9 @@ fw3_parse_options(void *s, o = uci_to_option(e); known = false; - for (i = 0; i < n; i++) + for (opt = opts; opt->name; opt++) { - opt = &opts[i]; - - if (!opt->parse || !opt->name) + if (!opt->parse) continue; if (strcmp(opt->name, e->name)) @@ -560,9 +736,15 @@ fw3_parse_options(void *s, } else { - if (!o->v.string) + v = o->v.string; + + if (!v) continue; + /* protocol "tcpudp" compatibility hack */ + if (opt->parse == fw3_parse_protocol && !strcmp(v, "tcpudp")) + v = strdup("tcp udp"); + if (!opt->elem_size) { if (!opt->parse((char *)s + opt->offset, o->v.string)) @@ -570,9 +752,7 @@ fw3_parse_options(void *s, } else { - for (p = strtok(o->v.string, " \t"); - p != NULL; - p = strtok(NULL, " \t")) + for (p = strtok(v, " \t"); p != NULL; p = strtok(NULL, " \t")) { item = malloc(opt->elem_size); @@ -592,6 +772,9 @@ fw3_parse_options(void *s, list_add_tail(item, dest); } } + + if (v != o->v.string) + free(v); } known = true; @@ -619,20 +802,53 @@ fw3_format_src_dest(struct fw3_address *src, struct fw3_address *dest) { char s[INET6_ADDRSTRLEN]; + if ((src && src->range) || (dest && dest->range)) + fw3_pr(" -m iprange"); + if (src && src->set) { - inet_ntop(src->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, - &src->address.v4, s, sizeof(s)); + if (src->range) + { + inet_ntop(src->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, + &src->address.v4, s, sizeof(s)); + + fw3_pr(" %s--src-range %s", src->invert ? "! " : "", s); + + inet_ntop(src->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, + &src->address2.v4, s, sizeof(s)); - fw3_pr(" %s-s %s/%u", src->invert ? "! " : "", s, src->mask); + fw3_pr("-%s", s); + } + else + { + inet_ntop(src->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, + &src->address.v4, s, sizeof(s)); + + fw3_pr(" %s-s %s/%u", src->invert ? "! " : "", s, src->mask); + } } if (dest && dest->set) { - inet_ntop(dest->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, - &dest->address.v4, s, sizeof(s)); + if (dest->range) + { + inet_ntop(dest->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, + &dest->address.v4, s, sizeof(s)); + + fw3_pr(" %s--dst-range %s", dest->invert ? "! " : "", s); - fw3_pr(" %s-d %s/%u", dest->invert ? "! " : "", s, dest->mask); + inet_ntop(dest->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, + &dest->address2.v4, s, sizeof(s)); + + fw3_pr("-%s", s); + } + else + { + inet_ntop(dest->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, + &dest->address.v4, s, sizeof(s)); + + fw3_pr(" %s-d %s/%u", dest->invert ? "! " : "", s, dest->mask); + } } } @@ -717,17 +933,11 @@ fw3_format_limit(struct fw3_limit *limit) if (!limit) return; - const char *units[] = { - [FW3_LIMIT_UNIT_SECOND] = "second", - [FW3_LIMIT_UNIT_MINUTE] = "minute", - [FW3_LIMIT_UNIT_HOUR] = "hour", - [FW3_LIMIT_UNIT_DAY] = "day", - }; - if (limit->rate > 0) { fw3_pr(" -m limit %s--limit %u/%s", - limit->invert ? "! " : "", limit->rate, units[limit->unit]); + limit->invert ? "! " : "", + limit->rate, limit_units[limit->unit]); if (limit->burst > 0) fw3_pr(" --limit-burst %u", limit->burst); @@ -759,6 +969,84 @@ fw3_format_ipset(struct fw3_ipset *ipset, bool invert) } void +fw3_format_time(struct fw3_time *time) +{ + int i; + struct tm empty = { 0 }; + char buf[sizeof("9999-99-99T23:59:59\0")]; + bool d1 = memcmp(&time->datestart, &empty, sizeof(empty)); + bool d2 = memcmp(&time->datestop, &empty, sizeof(empty)); + bool first; + + if (!d1 && !d2 && !time->timestart && !time->timestop && + !(time->monthdays & 0xFFFFFFFE) && !(time->weekdays & 0xFE)) + { + return; + } + + fw3_pr(" -m time"); + + if (time->utc) + fw3_pr(" --utc"); + + if (d1) + { + strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &time->datestart); + fw3_pr(" --datestart %s", buf); + } + + if (d2) + { + strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &time->datestop); + fw3_pr(" --datestop %s", buf); + } + + if (time->timestart) + { + fw3_pr(" --timestart %02d:%02d:%02d", + time->timestart / 3600, + time->timestart % 3600 / 60, + time->timestart % 60); + } + + if (time->timestop) + { + fw3_pr(" --timestop %02d:%02d:%02d", + time->timestop / 3600, + time->timestop % 3600 / 60, + time->timestop % 60); + } + + if (time->monthdays & 0xFFFFFFFE) + { + fw3_pr(" %s--monthdays", hasbit(time->monthdays, 0) ? "! " : ""); + + for (i = 1, first = true; i < 32; i++) + { + if (hasbit(time->monthdays, i)) + { + fw3_pr("%c%u", first ? ' ' : ',', i); + first = false; + } + } + } + + if (time->weekdays & 0xFE) + { + fw3_pr(" %s--weekdays", hasbit(time->weekdays, 0) ? "! " : ""); + + for (i = 1, first = true; i < 8; i++) + { + if (hasbit(time->weekdays, i)) + { + fw3_pr("%c%u", first ? ' ' : ',', i); + first = false; + } + } + } +} + +void __fw3_format_comment(const char *comment, ...) { va_list ap;