From fe3ecee341da8542aa25b962dcb8bcc628fcdd1e Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Thu, 21 Feb 2013 22:42:01 +0100 Subject: [PATCH] add time match support --- options.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++++++++ options.h | 27 +++++- redirects.c | 45 ++++++---- rules.c | 41 ++++++---- 4 files changed, 311 insertions(+), 34 deletions(-) diff --git a/options.c b/options.c index c605260..9870e91 100644 --- a/options.c +++ b/options.c @@ -518,6 +518,160 @@ fw3_parse_ipset_datatype(void *ptr, const char *val) return false; } +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) + { + *((struct tm *)ptr) = tm; + return true; + } + +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; + char *p; + + if (*val == '!') + { + setbit(*(uint8_t *)ptr, 0); + while (isspace(*++val)); + } + + for (p = strtok((char *)val, " \t"); p; p = strtok(NULL, " \t")) + { + if (!strncasecmp(p, "monday", strlen(p))) + w = 1; + else if (!strncasecmp(p, "tuesday", strlen(p))) + w = 2; + else if (!strncasecmp(p, "wednesday", strlen(p))) + w = 3; + else if (!strncasecmp(p, "thursday", strlen(p))) + w = 4; + else if (!strncasecmp(p, "friday", strlen(p))) + w = 5; + else if (!strncasecmp(p, "saturday", strlen(p))) + w = 6; + else if (!strncasecmp(p, "sunday", strlen(p))) + w = 7; + else + { + w = strtoul(p, &p, 10); + + if (*p || w < 1 || w > 7) + return false; + } + + setbit(*(uint8_t *)ptr, w); + } + + return true; +} + +bool +fw3_parse_monthdays(void *ptr, const char *val) +{ + unsigned int d; + char *p; + + if (*val == '!') + { + setbit(*(uint32_t *)ptr, 0); + while (isspace(*++val)); + } + + for (p = strtok((char *)val, " \t"); p; p = strtok(NULL, " \t")) + { + d = strtoul(p, &p, 10); + + if (*p || d < 1 || d > 31) + return false; + + setbit(*(uint32_t *)ptr, d); + } + + return true; +} + void fw3_parse_options(void *s, const struct fw3_option *opts, @@ -809,6 +963,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", (time->monthdays & 1) ? "! " : ""); + + 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", (time->weekdays & 1) ? "! " : ""); + + 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, ...) { diff --git a/options.h b/options.h index 2209cbe..fe9816e 100644 --- a/options.h +++ b/options.h @@ -35,6 +35,8 @@ #include #include +#include + #include #include @@ -196,6 +198,17 @@ struct fw3_limit enum fw3_limit_unit unit; }; +struct fw3_time +{ + bool utc; + struct tm datestart; + struct tm datestop; + uint32_t timestart; + uint32_t timestop; + uint32_t monthdays; /* bit 0 is invert + 1 .. 31 */ + uint8_t weekdays; /* bit 0 is invert + 1 .. 7 */ +}; + struct fw3_defaults { enum fw3_target policy_input; @@ -286,9 +299,10 @@ struct fw3_rule struct list_head icmp_type; - enum fw3_target target; - struct fw3_limit limit; + struct fw3_time time; + + enum fw3_target target; const char *extra; }; @@ -322,6 +336,8 @@ struct fw3_redirect struct fw3_address ip_redir; struct fw3_port port_redir; + struct fw3_time time; + enum fw3_target target; const char *extra; @@ -416,9 +432,15 @@ bool fw3_parse_port(void *ptr, const char *val); bool fw3_parse_family(void *ptr, const char *val); bool fw3_parse_icmptype(void *ptr, const char *val); bool fw3_parse_protocol(void *ptr, const char *val); + bool fw3_parse_ipset_method(void *ptr, const char *val); bool fw3_parse_ipset_datatype(void *ptr, const char *val); +bool fw3_parse_date(void *ptr, const char *val); +bool fw3_parse_time(void *ptr, const char *val); +bool fw3_parse_weekdays(void *ptr, const char *val); +bool fw3_parse_monthdays(void *ptr, const char *val); + void fw3_parse_options(void *s, const struct fw3_option *opts, struct uci_section *section); @@ -430,6 +452,7 @@ void fw3_format_protocol(struct fw3_protocol *proto, enum fw3_family family); void fw3_format_icmptype(struct fw3_icmptype *icmp, enum fw3_family family); void fw3_format_limit(struct fw3_limit *limit); void fw3_format_ipset(struct fw3_ipset *ipset, bool invert); +void fw3_format_time(struct fw3_time *time); void __fw3_format_comment(const char *comment, ...); #define fw3_format_comment(...) __fw3_format_comment(__VA_ARGS__, NULL) diff --git a/redirects.c b/redirects.c index 51c764f..2aa6664 100644 --- a/redirects.c +++ b/redirects.c @@ -20,31 +20,39 @@ const struct fw3_option fw3_redirect_opts[] = { - FW3_OPT("name", string, redirect, name), - FW3_OPT("family", family, redirect, family), + FW3_OPT("name", string, redirect, name), + FW3_OPT("family", family, redirect, family), - FW3_OPT("src", device, redirect, src), - FW3_OPT("dest", device, redirect, dest), + FW3_OPT("src", device, redirect, src), + FW3_OPT("dest", device, redirect, dest), - FW3_OPT("ipset", device, redirect, ipset), + FW3_OPT("ipset", device, redirect, ipset), - FW3_LIST("proto", protocol, redirect, proto), + FW3_LIST("proto", protocol, redirect, proto), - FW3_OPT("src_ip", address, redirect, ip_src), - FW3_LIST("src_mac", mac, redirect, mac_src), - FW3_OPT("src_port", port, redirect, port_src), + FW3_OPT("src_ip", address, redirect, ip_src), + FW3_LIST("src_mac", mac, redirect, mac_src), + FW3_OPT("src_port", port, redirect, port_src), - FW3_OPT("src_dip", address, redirect, ip_dest), - FW3_OPT("src_dport", port, redirect, port_dest), + FW3_OPT("src_dip", address, redirect, ip_dest), + FW3_OPT("src_dport", port, redirect, port_dest), - FW3_OPT("dest_ip", address, redirect, ip_redir), - FW3_OPT("dest_port", port, redirect, port_redir), + FW3_OPT("dest_ip", address, redirect, ip_redir), + FW3_OPT("dest_port", port, redirect, port_redir), - FW3_OPT("extra", string, redirect, extra), + FW3_OPT("extra", string, redirect, extra), - FW3_OPT("reflection", bool, redirect, reflection), + FW3_OPT("utc_time", bool, redirect, time.utc), + FW3_OPT("start_date", date, redirect, time.datestart), + FW3_OPT("stop_date", date, redirect, time.datestop), + FW3_OPT("start_time", time, redirect, time.timestart), + FW3_OPT("stop_time", time, redirect, time.timestop), + FW3_OPT("weekdays", weekdays, redirect, time.weekdays), + FW3_OPT("monthdays", monthdays, redirect, time.monthdays), - FW3_OPT("target", target, redirect, target), + FW3_OPT("reflection", bool, redirect, reflection), + + FW3_OPT("target", target, redirect, target), { } }; @@ -364,6 +372,7 @@ print_redirect(enum fw3_table table, enum fw3_family family, } fw3_format_mac(mac); + fw3_format_time(&redir->time); fw3_format_extra(redir->extra); fw3_format_comment(redir->name); print_target_nat(redir); @@ -376,6 +385,7 @@ print_redirect(enum fw3_table table, enum fw3_family family, fw3_format_src_dest(&redir->ip_src, &redir->ip_redir); fw3_format_sport_dport(&redir->port_src, &redir->port_redir); fw3_format_mac(mac); + fw3_format_time(&redir->time); fw3_format_extra(redir->extra); fw3_format_comment(redir->name); print_target_filter(redir); @@ -422,6 +432,7 @@ print_redirect(enum fw3_table table, enum fw3_family family, fw3_format_protocol(proto, family); fw3_format_src_dest(int_addr, ext_addr); fw3_format_sport_dport(NULL, &redir->port_dest); + fw3_format_time(&redir->time); fw3_format_comment(redir->name, " (reflection)"); print_snat_dnat(FW3_TARGET_DNAT, &redir->ip_redir, &redir->port_redir); @@ -430,6 +441,7 @@ print_redirect(enum fw3_table table, enum fw3_family family, fw3_format_protocol(proto, family); fw3_format_src_dest(int_addr, &redir->ip_redir); fw3_format_sport_dport(NULL, &redir->port_redir); + fw3_format_time(&redir->time); fw3_format_comment(redir->name, " (reflection)"); print_snat_dnat(FW3_TARGET_SNAT, ext_addr, NULL); } @@ -439,6 +451,7 @@ print_redirect(enum fw3_table table, enum fw3_family family, fw3_format_protocol(proto, family); fw3_format_src_dest(int_addr, &redir->ip_redir); fw3_format_sport_dport(NULL, &redir->port_redir); + fw3_format_time(&redir->time); fw3_format_comment(redir->name, " (reflection)"); fw3_pr(" -j zone_%s_dest_ACCEPT\n", redir->dest.name); } diff --git a/rules.c b/rules.c index ab094bb..e733cd9 100644 --- a/rules.c +++ b/rules.c @@ -20,30 +20,38 @@ const struct fw3_option fw3_rule_opts[] = { - FW3_OPT("name", string, rule, name), - FW3_OPT("family", family, rule, family), + FW3_OPT("name", string, rule, name), + FW3_OPT("family", family, rule, family), - FW3_OPT("src", device, rule, src), - FW3_OPT("dest", device, rule, dest), + FW3_OPT("src", device, rule, src), + FW3_OPT("dest", device, rule, dest), - FW3_OPT("ipset", device, rule, ipset), + FW3_OPT("ipset", device, rule, ipset), - FW3_LIST("proto", protocol, rule, proto), + FW3_LIST("proto", protocol, rule, proto), - FW3_LIST("src_ip", address, rule, ip_src), - FW3_LIST("src_mac", mac, rule, mac_src), - FW3_LIST("src_port", port, rule, port_src), + FW3_LIST("src_ip", address, rule, ip_src), + FW3_LIST("src_mac", mac, rule, mac_src), + FW3_LIST("src_port", port, rule, port_src), - FW3_LIST("dest_ip", address, rule, ip_dest), - FW3_LIST("dest_port", port, rule, port_dest), + FW3_LIST("dest_ip", address, rule, ip_dest), + FW3_LIST("dest_port", port, rule, port_dest), - FW3_LIST("icmp_type", icmptype, rule, icmp_type), - FW3_OPT("extra", string, rule, extra), + FW3_LIST("icmp_type", icmptype, rule, icmp_type), + FW3_OPT("extra", string, rule, extra), - FW3_OPT("limit", limit, rule, limit), - FW3_OPT("limit_burst", int, rule, limit.burst), + FW3_OPT("limit", limit, rule, limit), + FW3_OPT("limit_burst", int, rule, limit.burst), - FW3_OPT("target", target, rule, target), + FW3_OPT("utc_time", bool, rule, time.utc), + FW3_OPT("start_date", date, rule, time.datestart), + FW3_OPT("stop_date", date, rule, time.datestop), + FW3_OPT("start_time", time, rule, time.timestart), + FW3_OPT("stop_time", time, rule, time.timestop), + FW3_OPT("weekdays", weekdays, rule, time.weekdays), + FW3_OPT("monthdays", monthdays, rule, time.monthdays), + + FW3_OPT("target", target, rule, target), { } }; @@ -242,6 +250,7 @@ print_rule(enum fw3_table table, enum fw3_family family, fw3_format_icmptype(icmptype, family); fw3_format_mac(mac); fw3_format_limit(&rule->limit); + fw3_format_time(&rule->time); fw3_format_extra(rule->extra); fw3_format_comment(rule->name); print_target(rule); -- 2.25.1