}
}
}
+ 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))
{
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,
- struct fw3_option *opts, int n,
+fw3_parse_options(void *s, const struct fw3_option *opts,
struct uci_section *section)
{
- int i;
char *p;
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;
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))
{
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);
- fw3_pr(" %s-s %s/%u", src->invert ? "! " : "", s, src->mask);
+ inet_ntop(src->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6,
+ &src->address2.v4, s, sizeof(s));
+
+ 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);
+
+ 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);
+ fw3_pr(" %s-d %s/%u", dest->invert ? "! " : "", s, dest->mask);
+ }
}
}
}
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, ...)
{
va_list ap;