FW3_OPT("output", target, defaults, policy_output),
FW3_OPT("drop_invalid", bool, defaults, drop_invalid),
+ FW3_OPT("tcp_reject_code", reject_code, defaults, tcp_reject_code),
+ FW3_OPT("any_reject_code", reject_code, defaults, any_reject_code),
FW3_OPT("syn_flood", bool, defaults, syn_flood),
FW3_OPT("synflood_protect", bool, defaults, syn_flood),
FW3_OPT("custom_chains", bool, defaults, custom_chains),
FW3_OPT("disable_ipv6", bool, defaults, disable_ipv6),
FW3_OPT("flow_offloading", bool, defaults, flow_offloading),
+ FW3_OPT("flow_offloading_hw", bool, defaults, flow_offloading_hw),
FW3_OPT("__flags_v4", int, defaults, flags[0]),
FW3_OPT("__flags_v6", int, defaults, flags[1]),
}
static void
-check_offloading(struct uci_element *e, bool *offloading)
+check_target(struct uci_element *e, bool *available, const char *target, const bool ipv6)
{
- FILE *f;
-
- if (!*offloading)
- return;
-
- f = fopen("/sys/module/xt_FLOWOFFLOAD/refcnt", "r");
-
- if (f)
+ const bool b = fw3_has_target(ipv6, target);
+ if (!b)
{
- fclose(f);
- return;
+ warn_elem(e, "requires unavailable target extension %s, disabling", target);
+ *available = false;
+ }
+}
+
+static void
+check_any_reject_code(struct uci_element *e, enum fw3_reject_code *any_reject_code)
+{
+ if (*any_reject_code == FW3_REJECT_CODE_TCP_RESET) {
+ warn_elem(e, "tcp-reset not valid for any_reject_code, defaulting to port-unreach");
+ *any_reject_code = FW3_REJECT_CODE_PORT_UNREACH;
}
+}
- warn_elem(e, "enables offloading but missing kernel support, disabling");
- *offloading = false;
+static const char*
+get_reject_code(enum fw3_family family, enum fw3_reject_code reject_code)
+{
+ switch (reject_code) {
+ case FW3_REJECT_CODE_TCP_RESET:
+ return "tcp-reset";
+ case FW3_REJECT_CODE_PORT_UNREACH:
+ return "port-unreach";
+ case FW3_REJECT_CODE_ADM_PROHIBITED:
+ return family == FW3_FAMILY_V6 ? "adm-prohibited": "admin-prohib";
+ default:
+ return "unknown";
+ }
}
void
bool seen = false;
+ defs->tcp_reject_code = FW3_REJECT_CODE_TCP_RESET;
+ defs->any_reject_code = FW3_REJECT_CODE_PORT_UNREACH;
defs->syn_flood_rate.rate = 25;
defs->syn_flood_rate.burst = 50;
defs->tcp_syncookies = true;
continue;
}
+ seen = true;
+
if(!fw3_parse_options(&state->defaults, fw3_flag_opts, s))
warn_elem(e, "has invalid options");
check_policy(e, &defs->policy_output, "output");
check_policy(e, &defs->policy_forward, "forward");
- check_offloading(e, &defs->flow_offloading);
+ check_any_reject_code(e, &defs->any_reject_code);
+
+ /* exists in both ipv4 and ipv6, if at all, so only check ipv4 */
+ check_target(e, &defs->flow_offloading, "FLOWOFFLOAD", false);
}
}
for (c = default_chains; c->format; c++)
{
- /* don't touch user chains on selective stop */
- if (reload && c->flag == FW3_FLAG_CUSTOM_CHAINS)
- continue;
-
if (!fw3_is_family(c, handle->family))
continue;
!fw3_hasbit(defs->flags[handle->family == FW3_FAMILY_V6], c->flag))
continue;
- fw3_ipt_create_chain(handle, c->format);
+ fw3_ipt_create_chain(handle, reload, c->format);
}
set(defs->flags, handle->family, handle->table);
{
int i;
struct fw3_defaults *defs = &state->defaults;
- struct fw3_device lodev = { .set = true };
+ struct fw3_device lodev = { .set = true, .name = "lo" };
struct fw3_protocol tcp = { .protocol = 6 };
struct fw3_ipt_rule *r;
{
case FW3_TABLE_FILTER:
- sprintf(lodev.name, "lo");
-
r = fw3_ipt_rule_create(handle, NULL, &lodev, NULL, NULL, NULL);
fw3_ipt_rule_target(r, "ACCEPT");
fw3_ipt_rule_append(r, "INPUT");
for (i = 0; i < ARRAY_SIZE(chains); i += 2)
{
r = fw3_ipt_rule_new(handle);
- fw3_ipt_rule_comment(r, "user chain for %s", chains[i+1]);
+ fw3_ipt_rule_comment(r, "Custom %s rule chain", chains[i+1]);
fw3_ipt_rule_target(r, "%s_rule", chains[i+1]);
fw3_ipt_rule_append(r, chains[i]);
}
if (defs->flow_offloading)
{
r = fw3_ipt_rule_new(handle);
+ fw3_ipt_rule_comment(r, "Traffic offloading");
fw3_ipt_rule_extra(r, "-m conntrack --ctstate RELATED,ESTABLISHED");
fw3_ipt_rule_target(r, "FLOWOFFLOAD");
+ if (defs->flow_offloading_hw)
+ fw3_ipt_rule_addarg(r, false, "--hw", NULL);
fw3_ipt_rule_append(r, "FORWARD");
}
r = fw3_ipt_rule_create(handle, &tcp, NULL, NULL, NULL, NULL);
fw3_ipt_rule_target(r, "REJECT");
- fw3_ipt_rule_addarg(r, false, "--reject-with", "tcp-reset");
+ fw3_ipt_rule_addarg(r, false, "--reject-with", get_reject_code(handle->family, defs->tcp_reject_code));
fw3_ipt_rule_append(r, "reject");
r = fw3_ipt_rule_new(handle);
fw3_ipt_rule_target(r, "REJECT");
- fw3_ipt_rule_addarg(r, false, "--reject-with", "port-unreach");
+ fw3_ipt_rule_addarg(r, false, "--reject-with", get_reject_code(handle->family, defs->any_reject_code));
fw3_ipt_rule_append(r, "reject");
break;
if (defs->custom_chains)
{
r = fw3_ipt_rule_new(handle);
- fw3_ipt_rule_comment(r, "user chain for prerouting");
+ fw3_ipt_rule_comment(r, "Custom prerouting rule chain");
fw3_ipt_rule_target(r, "prerouting_rule");
fw3_ipt_rule_append(r, "PREROUTING");
r = fw3_ipt_rule_new(handle);
- fw3_ipt_rule_comment(r, "user chain for postrouting");
+ fw3_ipt_rule_comment(r, "Custom postrouting rule chain");
fw3_ipt_rule_target(r, "postrouting_rule");
fw3_ipt_rule_append(r, "POSTROUTING");
}
set_default(const char *name, int set)
{
FILE *f;
- char path[sizeof("/proc/sys/net/ipv4/tcp_window_scaling\0")];
+ char path[sizeof("/proc/sys/net/ipv4/tcp_window_scaling")];
snprintf(path, sizeof(path), "/proc/sys/net/ipv4/tcp_%s", name);
- info(" * Set tcp_%s to %s", name, set ? "on" : "off", name);
+ info(" * Set tcp_%s to %s", name, set ? "on" : "off");
if (!(f = fopen(path, "w")))
{
fw3_ipt_delete_id_rules(handle, "PREROUTING");
fw3_ipt_delete_id_rules(handle, "POSTROUTING");
+ /* first flush all the rules ... */
for (c = default_chains; c->format; c++)
{
/* don't touch user chains on selective stop */
continue;
fw3_ipt_flush_chain(handle, c->format);
+ }
+
+ /* ... then remove the chains */
+ for (c = default_chains; c->format; c++)
+ {
+ if (!fw3_is_family(c, handle->family))
+ continue;
- /* keep certain basic chains that do not depend on any settings to
- avoid purging unrelated user rules pointing to them */
- if (reload && !c->flag)
+ if (c->table != handle->table)
+ continue;
+
+ if (c->flag && !has(defs->flags, handle->family, c->flag))
continue;
- fw3_ipt_delete_chain(handle, c->format);
+ fw3_ipt_delete_chain(handle, reload, c->format);
}
del(defs->flags, handle->family, handle->table);