C(V4, NAT, CUSTOM_CHAINS, "postrouting_rule"),
C(ANY, MANGLE, UNSPEC, "mssfix"),
+ C(ANY, MANGLE, UNSPEC, "fwmark"),
+
C(ANY, RAW, UNSPEC, "notrack"),
{ }
C(V4, NAT, UNSPEC, "POSTROUTING -j delegate_postrouting"),
C(ANY, MANGLE, UNSPEC, "FORWARD -j mssfix"),
+ C(ANY, MANGLE, UNSPEC, "PREROUTING -j fwmark"),
+
C(ANY, RAW, UNSPEC, "PREROUTING -j notrack"),
{ }
"REJECT",
"DROP",
"NOTRACK",
+ "MARK",
"DNAT",
"SNAT",
FW3_REFLECTION_INTERNAL, FW3_REFLECTION_EXTERNAL);
}
+bool
+fw3_parse_mark(void *ptr, const char *val, bool is_list)
+{
+ uint32_t n;
+ char *s, *e;
+ struct fw3_mark *m = ptr;
+
+ if (*val == '!')
+ {
+ m->invert = true;
+ while (isspace(*++val));
+ }
+
+ if ((s = strchr(val, '/')) != NULL)
+ *s++ = 0;
+
+ n = strtoul(val, &e, 0);
+
+ if (e == val || *e)
+ return false;
+
+ m->mark = n;
+ m->mask = 0xFFFFFFFF;
+
+ if (s)
+ {
+ n = strtoul(s, &e, 0);
+
+ if (e == s || *e)
+ return false;
+
+ m->mask = n;
+ }
+
+ m->set = true;
+ return true;
+}
+
void
fw3_parse_options(void *s, const struct fw3_option *opts,
}
}
+void
+fw3_format_mark(struct fw3_mark *mark)
+{
+ if (!mark->set)
+ return;
+
+ fw3_pr(" -m mark %s--mark 0x%x", mark->invert ? "! " : "", mark->mark);
+
+ if (mark->mask < 0xFFFFFFFF)
+ fw3_pr("/0x%x", mark->mask);
+}
+
void
__fw3_format_comment(const char *comment, ...)
{
FW3_FLAG_REJECT = 7,
FW3_FLAG_DROP = 8,
FW3_FLAG_NOTRACK = 9,
- FW3_FLAG_DNAT = 10,
- FW3_FLAG_SNAT = 11,
- FW3_FLAG_SRC_ACCEPT = 12,
- FW3_FLAG_SRC_REJECT = 13,
- FW3_FLAG_SRC_DROP = 14,
- FW3_FLAG_CUSTOM_CHAINS = 15,
- FW3_FLAG_SYN_FLOOD = 16,
- FW3_FLAG_MTU_FIX = 17,
- FW3_FLAG_DROP_INVALID = 18,
- FW3_FLAG_HOTPLUG = 19,
- FW3_FLAG_DELETED = 20,
+ FW3_FLAG_MARK = 10,
+ FW3_FLAG_DNAT = 11,
+ FW3_FLAG_SNAT = 12,
+ FW3_FLAG_SRC_ACCEPT = 13,
+ FW3_FLAG_SRC_REJECT = 14,
+ FW3_FLAG_SRC_DROP = 15,
+ FW3_FLAG_CUSTOM_CHAINS = 16,
+ FW3_FLAG_SYN_FLOOD = 17,
+ FW3_FLAG_MTU_FIX = 18,
+ FW3_FLAG_DROP_INVALID = 19,
+ FW3_FLAG_HOTPLUG = 20,
+ FW3_FLAG_DELETED = 21,
__FW3_FLAG_MAX
};
uint8_t weekdays; /* bit 0 is invert + 1 .. 7 */
};
+struct fw3_mark
+{
+ bool set;
+ bool invert;
+ uint32_t mark;
+ uint32_t mask;
+};
+
struct fw3_defaults
{
enum fw3_flag policy_input;
struct fw3_limit limit;
struct fw3_time time;
+ struct fw3_mark mark;
enum fw3_flag target;
+ struct fw3_mark set_mark;
+ struct fw3_mark set_xmark;
const char *extra;
};
struct fw3_port port_redir;
struct fw3_time time;
+ struct fw3_mark mark;
enum fw3_flag target;
bool fw3_parse_time(void *ptr, const char *val, bool is_list);
bool fw3_parse_weekdays(void *ptr, const char *val, bool is_list);
bool fw3_parse_monthdays(void *ptr, const char *val, bool is_list);
+bool fw3_parse_mark(void *ptr, const char *val, bool is_list);
void fw3_parse_options(void *s, const struct fw3_option *opts,
struct uci_section *section);
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_mark(struct fw3_mark *mark);
void __fw3_format_comment(const char *comment, ...);
#define fw3_format_comment(...) __fw3_format_comment(__VA_ARGS__, NULL)
FW3_OPT("weekdays", weekdays, redirect, time.weekdays),
FW3_OPT("monthdays", monthdays, redirect, time.monthdays),
+ FW3_OPT("mark", mark, redirect, mark),
+
FW3_OPT("reflection", bool, redirect, reflection),
FW3_OPT("reflection_src", reflection_source,
redirect, reflection_src),
fw3_format_mac(mac);
fw3_format_time(&redir->time);
+ fw3_format_mark(&redir->mark);
fw3_format_extra(redir->extra);
fw3_format_comment(redir->name);
print_target_nat(redir);
fw3_format_sport_dport(&redir->port_src, &redir->port_redir);
fw3_format_mac(mac);
fw3_format_time(&redir->time);
+ fw3_format_mark(&redir->mark);
fw3_format_extra(redir->extra);
fw3_format_comment(redir->name);
print_target_filter(redir);
FW3_OPT("weekdays", weekdays, rule, time.weekdays),
FW3_OPT("monthdays", monthdays, rule, time.monthdays),
+ FW3_OPT("mark", mark, rule, mark),
+ FW3_OPT("set_mark", mark, rule, set_mark),
+ FW3_OPT("set_xmark", mark, rule, set_xmark),
+
FW3_OPT("target", target, rule, target),
{ }
continue;
}
+ if (!rule->set_mark.set && !rule->set_xmark.set &&
+ rule->target == FW3_FLAG_MARK)
+ {
+ warn_elem(e, "is set to target MARK but specifies neither "
+ "'set_mark' nor 'set_xmark' option");
+ fw3_free_rule(rule);
+ continue;
+ }
+
+ if (rule->_dest && rule->target == FW3_FLAG_MARK)
+ {
+ warn_elem(e, "must not specify 'dest' for MARK target");
+ fw3_free_rule(rule);
+ continue;
+ }
+
+ if (rule->set_mark.invert || rule->set_xmark.invert)
+ {
+ warn_elem(e, "must not have inverted 'set_mark' or 'set_xmark'");
+ fw3_free_rule(rule);
+ continue;
+ }
+
if (!rule->_src && !rule->_dest && !rule->src.any && !rule->dest.any)
{
warn_elem(e, "has neither a source nor a destination zone assigned "
warn_elem(e, "has no target specified, defaulting to REJECT");
rule->target = FW3_FLAG_REJECT;
}
- else if (rule->target > FW3_FLAG_NOTRACK)
+ else if (rule->target > FW3_FLAG_MARK)
{
warn_elem(e, "has invalid target specified, defaulting to REJECT");
rule->target = FW3_FLAG_REJECT;
{
sprintf(chain, "zone_%s_notrack", rule->src.name);
}
+ else if (rule->target == FW3_FLAG_MARK)
+ {
+ sprintf(chain, "fwmark");
+ }
else
{
if (rule->src.set)
switch(rule->target)
{
+ case FW3_FLAG_MARK:
+ if (rule->set_mark.set)
+ fw3_pr(" -j MARK --set-mark 0x%x/0x%x\n",
+ rule->set_mark.mark, rule->set_mark.mask);
+ else
+ fw3_pr(" -j MARK --set-xmark 0x%x/0x%x\n",
+ rule->set_xmark.mark, rule->set_xmark.mask);
+ return;
+
case FW3_FLAG_ACCEPT:
case FW3_FLAG_DROP:
case FW3_FLAG_NOTRACK:
fw3_format_mac(mac);
fw3_format_limit(&rule->limit);
fw3_format_time(&rule->time);
+ fw3_format_mark(&rule->mark);
fw3_format_extra(rule->extra);
fw3_format_comment(rule->name);
print_target(rule);
if (!fw3_is_family(rule, family))
return;
- if ((table == FW3_TABLE_RAW && rule->target != FW3_FLAG_NOTRACK) ||
- (table != FW3_TABLE_FILTER))
+ if ((rule->target == FW3_FLAG_NOTRACK && table != FW3_TABLE_RAW) ||
+ (rule->target == FW3_FLAG_MARK && table != FW3_TABLE_MANGLE) ||
+ (rule->target < FW3_FLAG_NOTRACK && table != FW3_TABLE_FILTER))
return;
if (rule->name)