Commit 902d6a4c authored by Subash Abhinov Kasiviswanathan's avatar Subash Abhinov Kasiviswanathan Committed by Pablo Neira Ayuso

netfilter: nf_defrag: Skip defrag if NOTRACK is set

conntrack defrag is needed only if some module like CONNTRACK or NAT
explicitly requests it. For plain forwarding scenarios, defrag is
not needed and can be skipped if NOTRACK is set in a rule.

Since conntrack defrag is currently higher priority than raw table,
setting NOTRACK is not sufficient. We need to move raw to a higher
priority for iptables only.

This is achieved by introducing a module parameter "raw_before_defrag"
which allows to change the priority of raw table to place it before
defrag. By default, the parameter is disabled and the priority of raw
table is NF_IP_PRI_RAW to support legacy behavior. If the module
parameter is enabled, then the priority of the raw table is set to
NF_IP_PRI_RAW_BEFORE_DEFRAG.
Signed-off-by: default avatarSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 5ed001ba
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
enum nf_ip_hook_priorities { enum nf_ip_hook_priorities {
NF_IP_PRI_FIRST = INT_MIN, NF_IP_PRI_FIRST = INT_MIN,
NF_IP_PRI_RAW_BEFORE_DEFRAG = -450,
NF_IP_PRI_CONNTRACK_DEFRAG = -400, NF_IP_PRI_CONNTRACK_DEFRAG = -400,
NF_IP_PRI_RAW = -300, NF_IP_PRI_RAW = -300,
NF_IP_PRI_SELINUX_FIRST = -225, NF_IP_PRI_SELINUX_FIRST = -225,
......
...@@ -62,6 +62,7 @@ ...@@ -62,6 +62,7 @@
enum nf_ip6_hook_priorities { enum nf_ip6_hook_priorities {
NF_IP6_PRI_FIRST = INT_MIN, NF_IP6_PRI_FIRST = INT_MIN,
NF_IP6_PRI_RAW_BEFORE_DEFRAG = -450,
NF_IP6_PRI_CONNTRACK_DEFRAG = -400, NF_IP6_PRI_CONNTRACK_DEFRAG = -400,
NF_IP6_PRI_RAW = -300, NF_IP6_PRI_RAW = -300,
NF_IP6_PRI_SELINUX_FIRST = -225, NF_IP6_PRI_SELINUX_FIRST = -225,
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* *
* Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h> #include <linux/module.h>
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -12,7 +13,11 @@ ...@@ -12,7 +13,11 @@
static int __net_init iptable_raw_table_init(struct net *net); static int __net_init iptable_raw_table_init(struct net *net);
static const struct xt_table packet_raw = { static bool raw_before_defrag __read_mostly;
MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag");
module_param(raw_before_defrag, bool, 0000);
static struct xt_table packet_raw = {
.name = "raw", .name = "raw",
.valid_hooks = RAW_VALID_HOOKS, .valid_hooks = RAW_VALID_HOOKS,
.me = THIS_MODULE, .me = THIS_MODULE,
...@@ -64,6 +69,12 @@ static int __init iptable_raw_init(void) ...@@ -64,6 +69,12 @@ static int __init iptable_raw_init(void)
{ {
int ret; int ret;
if (raw_before_defrag) {
packet_raw.priority = NF_IP_PRI_RAW_BEFORE_DEFRAG;
pr_info("Enabling raw table before defrag\n");
}
rawtable_ops = xt_hook_ops_alloc(&packet_raw, iptable_raw_hook); rawtable_ops = xt_hook_ops_alloc(&packet_raw, iptable_raw_hook);
if (IS_ERR(rawtable_ops)) if (IS_ERR(rawtable_ops))
return PTR_ERR(rawtable_ops); return PTR_ERR(rawtable_ops);
......
...@@ -80,7 +80,7 @@ static unsigned int ipv4_conntrack_defrag(void *priv, ...@@ -80,7 +80,7 @@ static unsigned int ipv4_conntrack_defrag(void *priv,
#endif #endif
#endif #endif
/* Gather fragments. */ /* Gather fragments. */
if (ip_is_fragment(ip_hdr(skb))) { if (skb->_nfct != IP_CT_UNTRACKED && ip_is_fragment(ip_hdr(skb))) {
enum ip_defrag_users user = enum ip_defrag_users user =
nf_ct_defrag_user(state->hook, skb); nf_ct_defrag_user(state->hook, skb);
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* *
* Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h> #include <linux/module.h>
#include <linux/netfilter_ipv6/ip6_tables.h> #include <linux/netfilter_ipv6/ip6_tables.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -11,7 +12,11 @@ ...@@ -11,7 +12,11 @@
static int __net_init ip6table_raw_table_init(struct net *net); static int __net_init ip6table_raw_table_init(struct net *net);
static const struct xt_table packet_raw = { static bool raw_before_defrag __read_mostly;
MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag");
module_param(raw_before_defrag, bool, 0000);
static struct xt_table packet_raw = {
.name = "raw", .name = "raw",
.valid_hooks = RAW_VALID_HOOKS, .valid_hooks = RAW_VALID_HOOKS,
.me = THIS_MODULE, .me = THIS_MODULE,
...@@ -63,6 +68,12 @@ static int __init ip6table_raw_init(void) ...@@ -63,6 +68,12 @@ static int __init ip6table_raw_init(void)
{ {
int ret; int ret;
if (raw_before_defrag) {
packet_raw.priority = NF_IP6_PRI_RAW_BEFORE_DEFRAG;
pr_info("Enabling raw table before defrag\n");
}
/* Register hooks */ /* Register hooks */
rawtable_ops = xt_hook_ops_alloc(&packet_raw, ip6table_raw_hook); rawtable_ops = xt_hook_ops_alloc(&packet_raw, ip6table_raw_hook);
if (IS_ERR(rawtable_ops)) if (IS_ERR(rawtable_ops))
......
...@@ -65,6 +65,9 @@ static unsigned int ipv6_defrag(void *priv, ...@@ -65,6 +65,9 @@ static unsigned int ipv6_defrag(void *priv,
return NF_ACCEPT; return NF_ACCEPT;
#endif #endif
if (skb->_nfct == IP_CT_UNTRACKED)
return NF_ACCEPT;
err = nf_ct_frag6_gather(state->net, skb, err = nf_ct_frag6_gather(state->net, skb,
nf_ct6_defrag_user(state->hook, skb)); nf_ct6_defrag_user(state->hook, skb));
/* queued */ /* queued */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment