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,
}
}
+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, ...)
{
#include <netinet/in.h>
#include <netinet/ether.h>
+#include <time.h>
+
#include <uci.h>
#include <libubox/list.h>
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;
struct list_head icmp_type;
- enum fw3_target target;
-
struct fw3_limit limit;
+ struct fw3_time time;
+
+ enum fw3_target target;
const char *extra;
};
struct fw3_address ip_redir;
struct fw3_port port_redir;
+ struct fw3_time time;
+
enum fw3_target target;
const char *extra;
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);
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)
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),
{ }
};
}
fw3_format_mac(mac);
+ fw3_format_time(&redir->time);
fw3_format_extra(redir->extra);
fw3_format_comment(redir->name);
print_target_nat(redir);
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);
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);
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);
}
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);
}
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),
{ }
};
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);