* [PATCH RFC 00/15] Netfilter pernet hook support
@ 2015-06-15 15:46 Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 01/15] net: include missing headers in net/net_namespace.h Pablo Neira Ayuso
` (14 more replies)
0 siblings, 15 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2015-06-15 15:46 UTC (permalink / raw
To: netfilter-devel; +Cc: ebiederm, aschultz, kaber
Hi,
This is a first version RFC patchset to add pernet hook support to Netfilter,
with basically almost no testing here so far.
The initial three patches try to address a problem in the existing netfilter
netns header files. Basically, it's not a good idea to include
linux/netfilter.h from net/netns/netfilter.h. This is pulling quite a lot of
definitions from everything that includes net/net_namespace.h that are not
required.
It follows the initial patch to introduce of the pernet support for
nf_register_hook(). Initially, all callers are converted to use init_net.
Unlike Eric Bierderman's approach, there is no new parameter struct net from
any of the NF_HOOK(), NF_HOOK_COND() and nf_hook() but I prefer his approach
since we can avoid the dev_net(indev) ? ... branch.
Then, you get the bunch converted to use the pernet hooks by introducing the
boiler plate code to duplicate the existing nf_hooks_ops struct and register
it.
Pablo Neira Ayuso (15):
net: include missing headers in net/net_namespace.h
netfilter: use forward declaration instead of including linux/proc_fs.h
netfilter: don't pull include/linux/netfilter.h from netns headers
netfilter: add pernet hook support
netfilter: ipt_CLUSTERIP: adapt it to support pernet hooks
netfilter: x_tables: adapt xt_hook_link() to support pernet hooks
netfilter: x_tables: adapt tables to pernet hooks
netfilter: nf_conntrack: adapt IPv4 and IPv6 trackers to pernet hooks
netfilter: synproxy: adapt IPv4 and IPv6 targets to pernet hooks
netfilter: defrag: add pernet hook support
ipvs: adapt it to pernet hooks
netfilter: ebtables: adapt the filter and nat table to pernet hooks
netfilter: nf_tables: adapt it to pernet hooks
security: adapt it to pernet hooks
netfilter: bridge: adapt it to pernet hooks
include/linux/netfilter.h | 33 +++--
include/linux/netfilter/x_tables.h | 5 +-
include/linux/netfilter_arp/arp_tables.h | 3 +-
include/linux/netfilter_defs.h | 9 ++
include/linux/netfilter_ingress.h | 6 +-
include/linux/netfilter_ipv4/ip_tables.h | 8 +-
include/linux/netfilter_ipv6/ip6_tables.h | 8 +-
include/net/ip_vs.h | 3 +
include/net/net_namespace.h | 2 +
include/net/netfilter/br_netfilter.h | 52 +++++++
include/net/netns/conntrack.h | 4 +
include/net/netns/netfilter.h | 27 +++-
include/net/netns/x_tables.h | 4 +-
include/uapi/linux/netfilter.h | 3 +-
net/bridge/br_netfilter.c | 171 ++++++++++++++----------
net/bridge/netfilter/ebtable_filter.c | 41 ++++--
net/bridge/netfilter/ebtable_nat.c | 41 ++++--
net/core/dev.c | 6 +-
net/decnet/netfilter/dn_rtmsg.c | 2 +-
net/ipv4/netfilter/arp_tables.c | 15 ++-
net/ipv4/netfilter/arptable_filter.c | 25 +---
net/ipv4/netfilter/ip_tables.c | 46 ++++++-
net/ipv4/netfilter/ipt_CLUSTERIP.c | 31 +++--
net/ipv4/netfilter/ipt_SYNPROXY.c | 51 ++++++-
net/ipv4/netfilter/iptable_filter.c | 21 +--
net/ipv4/netfilter/iptable_mangle.c | 21 +--
net/ipv4/netfilter/iptable_nat.c | 54 +++++---
net/ipv4/netfilter/iptable_raw.c | 20 +--
net/ipv4/netfilter/iptable_security.c | 24 +---
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 36 +++--
net/ipv4/netfilter/nf_defrag_ipv4.c | 37 ++++-
net/ipv6/netfilter/ip6_tables.c | 42 +++++-
net/ipv6/netfilter/ip6t_SYNPROXY.c | 52 ++++++-
net/ipv6/netfilter/ip6table_filter.c | 25 +---
net/ipv6/netfilter/ip6table_mangle.c | 24 +---
net/ipv6/netfilter/ip6table_nat.c | 54 +++++---
net/ipv6/netfilter/ip6table_raw.c | 24 +---
net/ipv6/netfilter/ip6table_security.c | 24 +---
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 45 ++++---
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 40 +++++-
net/ipv6/output_core.c | 1 +
net/netfilter/core.c | 26 ++--
net/netfilter/ipvs/ip_vs_core.c | 42 ++++--
net/netfilter/nf_queue.c | 2 +-
net/netfilter/nf_synproxy_core.c | 1 +
net/netfilter/nf_tables_api.c | 12 +-
net/netfilter/x_tables.c | 5 +-
security/selinux/hooks.c | 41 +++++-
security/smack/smack_netfilter.c | 3 +-
49 files changed, 845 insertions(+), 427 deletions(-)
create mode 100644 include/linux/netfilter_defs.h
--
1.7.10.4
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH RFC 01/15] net: include missing headers in net/net_namespace.h
2015-06-15 15:46 [PATCH RFC 00/15] Netfilter pernet hook support Pablo Neira Ayuso
@ 2015-06-15 15:46 ` Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 02/15] netfilter: use forward declaration instead of including linux/proc_fs.h Pablo Neira Ayuso
` (13 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2015-06-15 15:46 UTC (permalink / raw
To: netfilter-devel; +Cc: ebiederm, aschultz, kaber
Include linux/idr.h and linux/skbuff.h since they are required by objects that
are declared in the net structure.
struct net {
...
struct idr netns_ids;
...
struct sk_buff_head wext_nlevents;
...
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/net_namespace.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 72eb237..e951453 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -28,6 +28,8 @@
#include <net/netns/xfrm.h>
#include <net/netns/mpls.h>
#include <linux/ns_common.h>
+#include <linux/idr.h>
+#include <linux/skbuff.h>
struct user_namespace;
struct proc_dir_entry;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH RFC 02/15] netfilter: use forward declaration instead of including linux/proc_fs.h
2015-06-15 15:46 [PATCH RFC 00/15] Netfilter pernet hook support Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 01/15] net: include missing headers in net/net_namespace.h Pablo Neira Ayuso
@ 2015-06-15 15:46 ` Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 03/15] netfilter: don't pull include/linux/netfilter.h from netns headers Pablo Neira Ayuso
` (12 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2015-06-15 15:46 UTC (permalink / raw
To: netfilter-devel; +Cc: ebiederm, aschultz, kaber
We don't need to pull the full definitions in that file, a simple forward
declaration is enough.
Moreover, include linux/procfs.h from nf_synproxy_core, otherwise this hits a
compilation error due to missing declarations, ie.
net/netfilter/nf_synproxy_core.c: In function ‘synproxy_proc_init’:
net/netfilter/nf_synproxy_core.c:326:2: error: implicit declaration of function ‘proc_create’ [-Werror=implicit-function-declaration]
if (!proc_create("synproxy", S_IRUGO, net->proc_net_stat,
^
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netns/netfilter.h | 2 +-
net/netfilter/nf_synproxy_core.c | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/net/netns/netfilter.h b/include/net/netns/netfilter.h
index 8874002..cf25b5e 100644
--- a/include/net/netns/netfilter.h
+++ b/include/net/netns/netfilter.h
@@ -1,9 +1,9 @@
#ifndef __NETNS_NETFILTER_H
#define __NETNS_NETFILTER_H
-#include <linux/proc_fs.h>
#include <linux/netfilter.h>
+struct proc_dir_entry;
struct nf_logger;
struct netns_nf {
diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
index 52e20c9..789feea 100644
--- a/net/netfilter/nf_synproxy_core.c
+++ b/net/netfilter/nf_synproxy_core.c
@@ -11,6 +11,7 @@
#include <asm/unaligned.h>
#include <net/tcp.h>
#include <net/netns/generic.h>
+#include <linux/proc_fs.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter/x_tables.h>
--
1.7.10.4
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH RFC 03/15] netfilter: don't pull include/linux/netfilter.h from netns headers
2015-06-15 15:46 [PATCH RFC 00/15] Netfilter pernet hook support Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 01/15] net: include missing headers in net/net_namespace.h Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 02/15] netfilter: use forward declaration instead of including linux/proc_fs.h Pablo Neira Ayuso
@ 2015-06-15 15:46 ` Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 04/15] netfilter: add pernet hook support Pablo Neira Ayuso
` (11 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2015-06-15 15:46 UTC (permalink / raw
To: netfilter-devel; +Cc: ebiederm, aschultz, kaber
This pulls the full hook netfilter definitions from all those that include
net_namespace.h.
Instead let's just include the bare minimum required in the new
linux/netfilter_defs.h file, and use it from the netfilter netns header files.
I also needed to include in.h and in6.h from linux/netfilter.h otherwise we hit
this compilation error:
In file included from include/linux/netfilter_defs.h:4:0,
from include/net/netns/netfilter.h:4,
from include/net/net_namespace.h:22,
from include/linux/netdevice.h:43,
from net/netfilter/nfnetlink_queue_core.c:23:
include/uapi/linux/netfilter.h:76:17: error: field ‘in’ has incomplete type struct in_addr in;
And also explicit include linux/netfilter.h in several spots.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/linux/netfilter.h | 6 ++----
include/linux/netfilter_defs.h | 9 +++++++++
include/net/netns/netfilter.h | 2 +-
include/net/netns/x_tables.h | 2 +-
include/uapi/linux/netfilter.h | 3 ++-
net/ipv6/output_core.c | 1 +
6 files changed, 16 insertions(+), 7 deletions(-)
create mode 100644 include/linux/netfilter_defs.h
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index f5ff5d1..00050df 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -10,7 +10,8 @@
#include <linux/wait.h>
#include <linux/list.h>
#include <linux/static_key.h>
-#include <uapi/linux/netfilter.h>
+#include <linux/netfilter_defs.h>
+
#ifdef CONFIG_NETFILTER
static inline int NF_DROP_GETERR(int verdict)
{
@@ -38,9 +39,6 @@ static inline void nf_inet_addr_mask(const union nf_inet_addr *a1,
int netfilter_init(void);
-/* Largest hook number + 1 */
-#define NF_MAX_HOOKS 8
-
struct sk_buff;
struct nf_hook_ops;
diff --git a/include/linux/netfilter_defs.h b/include/linux/netfilter_defs.h
new file mode 100644
index 0000000..d3a7f85
--- /dev/null
+++ b/include/linux/netfilter_defs.h
@@ -0,0 +1,9 @@
+#ifndef __LINUX_NETFILTER_CORE_H_
+#define __LINUX_NETFILTER_CORE_H_
+
+#include <uapi/linux/netfilter.h>
+
+/* Largest hook number + 1, see uapi/linux/netfilter_decnet.h */
+#define NF_MAX_HOOKS 8
+
+#endif
diff --git a/include/net/netns/netfilter.h b/include/net/netns/netfilter.h
index cf25b5e..532e4ba 100644
--- a/include/net/netns/netfilter.h
+++ b/include/net/netns/netfilter.h
@@ -1,7 +1,7 @@
#ifndef __NETNS_NETFILTER_H
#define __NETNS_NETFILTER_H
-#include <linux/netfilter.h>
+#include <linux/netfilter_defs.h>
struct proc_dir_entry;
struct nf_logger;
diff --git a/include/net/netns/x_tables.h b/include/net/netns/x_tables.h
index 4d6597a..c8a7681 100644
--- a/include/net/netns/x_tables.h
+++ b/include/net/netns/x_tables.h
@@ -2,7 +2,7 @@
#define __NETNS_X_TABLES_H
#include <linux/list.h>
-#include <linux/netfilter.h>
+#include <linux/netfilter_defs.h>
struct ebt_table;
diff --git a/include/uapi/linux/netfilter.h b/include/uapi/linux/netfilter.h
index 177027c..d93f949 100644
--- a/include/uapi/linux/netfilter.h
+++ b/include/uapi/linux/netfilter.h
@@ -4,7 +4,8 @@
#include <linux/types.h>
#include <linux/compiler.h>
#include <linux/sysctl.h>
-
+#include <linux/in.h>
+#include <linux/in6.h>
/* Responses from hook functions. */
#define NF_DROP 0
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
index 21678ac..928a0fb 100644
--- a/net/ipv6/output_core.c
+++ b/net/ipv6/output_core.c
@@ -8,6 +8,7 @@
#include <net/ip6_fib.h>
#include <net/addrconf.h>
#include <net/secure_seq.h>
+#include <linux/netfilter.h>
static u32 __ipv6_select_ident(struct net *net, u32 hashrnd,
const struct in6_addr *dst,
--
1.7.10.4
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH RFC 04/15] netfilter: add pernet hook support
2015-06-15 15:46 [PATCH RFC 00/15] Netfilter pernet hook support Pablo Neira Ayuso
` (2 preceding siblings ...)
2015-06-15 15:46 ` [PATCH RFC 03/15] netfilter: don't pull include/linux/netfilter.h from netns headers Pablo Neira Ayuso
@ 2015-06-15 15:46 ` Pablo Neira Ayuso
2015-06-16 1:01 ` Eric W. Biederman
2015-06-15 15:46 ` [PATCH RFC 05/15] netfilter: ipt_CLUSTERIP: adapt it to support pernet hooks Pablo Neira Ayuso
` (10 subsequent siblings)
14 siblings, 1 reply; 17+ messages in thread
From: Pablo Neira Ayuso @ 2015-06-15 15:46 UTC (permalink / raw
To: netfilter-devel; +Cc: ebiederm, aschultz, kaber
This patch modifies the nf_register_hook() and nf_register_hooks() interfaces
to allow to register hooks at a pernet level.
This starts using init_net for all the existing callers though, so the full
conversion of existing netfilter hook clients to comes in follow up patches.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/linux/netfilter.h | 27 +++++++++++++++---------
include/linux/netfilter_ingress.h | 6 +++---
include/net/netns/netfilter.h | 1 +
net/bridge/br_netfilter.c | 2 +-
net/bridge/netfilter/ebtable_filter.c | 3 ++-
net/bridge/netfilter/ebtable_nat.c | 3 ++-
net/core/dev.c | 6 ++++--
net/decnet/netfilter/dn_rtmsg.c | 2 +-
net/ipv4/netfilter/ipt_CLUSTERIP.c | 2 +-
net/ipv4/netfilter/ipt_SYNPROXY.c | 2 +-
net/ipv4/netfilter/iptable_nat.c | 3 ++-
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 2 +-
net/ipv4/netfilter/nf_defrag_ipv4.c | 3 ++-
net/ipv6/netfilter/ip6t_SYNPROXY.c | 2 +-
net/ipv6/netfilter/ip6table_nat.c | 3 ++-
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 2 +-
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 3 ++-
net/netfilter/core.c | 26 +++++++++++------------
net/netfilter/ipvs/ip_vs_core.c | 2 +-
net/netfilter/nf_queue.c | 2 +-
net/netfilter/nf_tables_api.c | 6 ++++--
net/netfilter/x_tables.c | 2 +-
security/selinux/hooks.c | 6 ++++--
security/smack/smack_netfilter.c | 3 ++-
24 files changed, 70 insertions(+), 49 deletions(-)
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 00050df..f3c1c21 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -52,11 +52,13 @@ struct nf_hook_state {
struct net_device *in;
struct net_device *out;
struct sock *sk;
+ struct net *net;
struct list_head *hook_list;
int (*okfn)(struct sock *, struct sk_buff *);
};
static inline void nf_hook_state_init(struct nf_hook_state *p,
+ struct net *net,
struct list_head *hook_list,
unsigned int hook,
int thresh, u_int8_t pf,
@@ -65,6 +67,7 @@ static inline void nf_hook_state_init(struct nf_hook_state *p,
struct sock *sk,
int (*okfn)(struct sock *, struct sk_buff *))
{
+ p->net = net;
p->hook = hook;
p->thresh = thresh;
p->pf = pf;
@@ -118,9 +121,9 @@ struct nf_sockopt_ops {
};
/* Function to register/unregister hook points. */
-int nf_register_hook(struct nf_hook_ops *reg);
+int nf_register_hook(struct net *net, struct nf_hook_ops *reg);
void nf_unregister_hook(struct nf_hook_ops *reg);
-int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n);
+int nf_register_hooks(struct net *net, struct nf_hook_ops *reg, unsigned int n);
void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n);
/* Functions to register get/setsockopt ranges (non-inclusive). You
@@ -128,8 +131,6 @@ void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n);
int nf_register_sockopt(struct nf_sockopt_ops *reg);
void nf_unregister_sockopt(struct nf_sockopt_ops *reg);
-extern struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
-
#ifdef HAVE_JUMP_LABEL
extern struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
@@ -150,9 +151,12 @@ static inline bool nf_hook_list_active(struct list_head *nf_hook_list,
}
#endif
-static inline bool nf_hooks_active(u_int8_t pf, unsigned int hook)
+#include <linux/netdevice.h>
+
+static inline bool nf_hooks_active(struct net *net, u_int8_t pf,
+ unsigned int hook)
{
- return nf_hook_list_active(&nf_hooks[pf][hook], pf, hook);
+ return nf_hook_list_active(&net->nf.hooks[pf][hook], pf, hook);
}
int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state);
@@ -172,11 +176,13 @@ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
int (*okfn)(struct sock *, struct sk_buff *),
int thresh)
{
- if (nf_hooks_active(pf, hook)) {
+ struct net *net = indev ? dev_net(indev) : dev_net(outdev);
+
+ if (nf_hooks_active(net, pf, hook)) {
struct nf_hook_state state;
- nf_hook_state_init(&state, &nf_hooks[pf][hook], hook, thresh,
- pf, indev, outdev, sk, okfn);
+ nf_hook_state_init(&state, net, &net->nf.hooks[pf][hook], hook,
+ thresh, pf, indev, outdev, sk, okfn);
return nf_hook_slow(skb, &state);
}
return 1;
@@ -339,7 +345,8 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
#else /* !CONFIG_NETFILTER */
#define NF_HOOK(pf, hook, sk, skb, indev, outdev, okfn) (okfn)(sk, skb)
#define NF_HOOK_COND(pf, hook, sk, skb, indev, outdev, okfn, cond) (okfn)(sk, skb)
-static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
+static inline int nf_hook_thresh(struct net *net,
+ u_int8_t pf, unsigned int hook,
struct sock *sk,
struct sk_buff *skb,
struct net_device *indev,
diff --git a/include/linux/netfilter_ingress.h b/include/linux/netfilter_ingress.h
index cb0727f..99a78e9 100644
--- a/include/linux/netfilter_ingress.h
+++ b/include/linux/netfilter_ingress.h
@@ -5,17 +5,17 @@
#include <linux/netdevice.h>
#ifdef CONFIG_NETFILTER_INGRESS
-static inline int nf_hook_ingress_active(struct sk_buff *skb)
+static inline int nf_hook_ingress_active(struct net *net, struct sk_buff *skb)
{
return nf_hook_list_active(&skb->dev->nf_hooks_ingress,
NFPROTO_NETDEV, NF_NETDEV_INGRESS);
}
-static inline int nf_hook_ingress(struct sk_buff *skb)
+static inline int nf_hook_ingress(struct net *net, struct sk_buff *skb)
{
struct nf_hook_state state;
- nf_hook_state_init(&state, &skb->dev->nf_hooks_ingress,
+ nf_hook_state_init(&state, net, &skb->dev->nf_hooks_ingress,
NF_NETDEV_INGRESS, INT_MIN, NFPROTO_NETDEV, NULL,
skb->dev, NULL, NULL);
return nf_hook_slow(skb, &state);
diff --git a/include/net/netns/netfilter.h b/include/net/netns/netfilter.h
index 532e4ba..38aa498 100644
--- a/include/net/netns/netfilter.h
+++ b/include/net/netns/netfilter.h
@@ -14,5 +14,6 @@ struct netns_nf {
#ifdef CONFIG_SYSCTL
struct ctl_table_header *nf_log_dir_header;
#endif
+ struct list_head hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
};
#endif
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index e4e5f2f..af14ef1 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -1246,7 +1246,7 @@ static int __init br_netfilter_init(void)
{
int ret;
- ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
+ ret = nf_register_hooks(&init_net, br_nf_ops, ARRAY_SIZE(br_nf_ops));
if (ret < 0)
return ret;
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index 8a3f63b..9a5a798 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -119,7 +119,8 @@ static int __init ebtable_filter_init(void)
ret = register_pernet_subsys(&frame_filter_net_ops);
if (ret < 0)
return ret;
- ret = nf_register_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
+ ret = nf_register_hooks(&init_net, ebt_ops_filter,
+ ARRAY_SIZE(ebt_ops_filter));
if (ret < 0)
unregister_pernet_subsys(&frame_filter_net_ops);
return ret;
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index c5ef5b1..3d2759d 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -119,7 +119,8 @@ static int __init ebtable_nat_init(void)
ret = register_pernet_subsys(&frame_nat_net_ops);
if (ret < 0)
return ret;
- ret = nf_register_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat));
+ ret = nf_register_hooks(&init_net, ebt_ops_nat,
+ ARRAY_SIZE(ebt_ops_nat));
if (ret < 0)
unregister_pernet_subsys(&frame_nat_net_ops);
return ret;
diff --git a/net/core/dev.c b/net/core/dev.c
index 6778a99..a176606 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3741,13 +3741,15 @@ static inline int nf_ingress(struct sk_buff *skb, struct packet_type **pt_prev,
int *ret, struct net_device *orig_dev)
{
#ifdef CONFIG_NETFILTER_INGRESS
- if (nf_hook_ingress_active(skb)) {
+ struct net *net = dev_net(orig_dev);
+
+ if (nf_hook_ingress_active(net, skb)) {
if (*pt_prev) {
*ret = deliver_skb(skb, *pt_prev, orig_dev);
*pt_prev = NULL;
}
- return nf_hook_ingress(skb);
+ return nf_hook_ingress(net, skb);
}
#endif /* CONFIG_NETFILTER_INGRESS */
return 0;
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index af34fc9..ba02eac 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -134,7 +134,7 @@ static int __init dn_rtmsg_init(void)
return -ENOMEM;
}
- rv = nf_register_hook(&dnrmg_ops);
+ rv = nf_register_hook(&init_net, &dnrmg_ops);
if (rv) {
netlink_kernel_release(dnrmg);
}
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 45cb16a..cf23858 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -767,7 +767,7 @@ static int __init clusterip_tg_init(void)
if (ret < 0)
goto cleanup_subsys;
- ret = nf_register_hook(&cip_arp_ops);
+ ret = nf_register_hook(&init_net, &cip_arp_ops);
if (ret < 0)
goto cleanup_target;
diff --git a/net/ipv4/netfilter/ipt_SYNPROXY.c b/net/ipv4/netfilter/ipt_SYNPROXY.c
index fe8cc18..a57d3d1 100644
--- a/net/ipv4/netfilter/ipt_SYNPROXY.c
+++ b/net/ipv4/netfilter/ipt_SYNPROXY.c
@@ -450,7 +450,7 @@ static int __init synproxy_tg4_init(void)
{
int err;
- err = nf_register_hooks(ipv4_synproxy_ops,
+ err = nf_register_hooks(&init_net, ipv4_synproxy_ops,
ARRAY_SIZE(ipv4_synproxy_ops));
if (err < 0)
goto err1;
diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c
index 0d4d9cd..5ef83d3 100644
--- a/net/ipv4/netfilter/iptable_nat.c
+++ b/net/ipv4/netfilter/iptable_nat.c
@@ -131,7 +131,8 @@ static int __init iptable_nat_init(void)
if (err < 0)
goto err1;
- err = nf_register_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops));
+ err = nf_register_hooks(&init_net, nf_nat_ipv4_ops,
+ ARRAY_SIZE(nf_nat_ipv4_ops));
if (err < 0)
goto err2;
return 0;
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 30ad955..2384975 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -467,7 +467,7 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
goto cleanup_sockopt;
}
- ret = nf_register_hooks(ipv4_conntrack_ops,
+ ret = nf_register_hooks(&init_net, ipv4_conntrack_ops,
ARRAY_SIZE(ipv4_conntrack_ops));
if (ret < 0) {
pr_err("nf_conntrack_ipv4: can't register hooks.\n");
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
index c88b7d4..ad74929 100644
--- a/net/ipv4/netfilter/nf_defrag_ipv4.c
+++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
@@ -110,7 +110,8 @@ static struct nf_hook_ops ipv4_defrag_ops[] = {
static int __init nf_defrag_init(void)
{
- return nf_register_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));
+ return nf_register_hooks(&init_net, ipv4_defrag_ops,
+ ARRAY_SIZE(ipv4_defrag_ops));
}
static void __exit nf_defrag_fini(void)
diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c
index 6edb7b1..ed5d4a6 100644
--- a/net/ipv6/netfilter/ip6t_SYNPROXY.c
+++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c
@@ -473,7 +473,7 @@ static int __init synproxy_tg6_init(void)
{
int err;
- err = nf_register_hooks(ipv6_synproxy_ops,
+ err = nf_register_hooks(&init_net, ipv6_synproxy_ops,
ARRAY_SIZE(ipv6_synproxy_ops));
if (err < 0)
goto err1;
diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c
index c3a7f7a..ecb0511 100644
--- a/net/ipv6/netfilter/ip6table_nat.c
+++ b/net/ipv6/netfilter/ip6table_nat.c
@@ -133,7 +133,8 @@ static int __init ip6table_nat_init(void)
if (err < 0)
goto err1;
- err = nf_register_hooks(nf_nat_ipv6_ops, ARRAY_SIZE(nf_nat_ipv6_ops));
+ err = nf_register_hooks(&init_net, nf_nat_ipv6_ops,
+ ARRAY_SIZE(nf_nat_ipv6_ops));
if (err < 0)
goto err2;
return 0;
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 4ba0c34..8bcf625 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -407,7 +407,7 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
if (ret < 0)
goto cleanup_sockopt;
- ret = nf_register_hooks(ipv6_conntrack_ops,
+ ret = nf_register_hooks(&init_net, ipv6_conntrack_ops,
ARRAY_SIZE(ipv6_conntrack_ops));
if (ret < 0) {
pr_err("nf_conntrack_ipv6: can't register pre-routing defrag "
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
index a45db0b..7bc330f 100644
--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
+++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
@@ -108,7 +108,8 @@ static int __init nf_defrag_init(void)
pr_err("nf_defrag_ipv6: can't initialize frag6.\n");
return ret;
}
- ret = nf_register_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops));
+ ret = nf_register_hooks(&init_net, ipv6_defrag_ops,
+ ARRAY_SIZE(ipv6_defrag_ops));
if (ret < 0) {
pr_err("nf_defrag_ipv6: can't register hooks\n");
goto cleanup_frag6;
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 653e32e..73c8ecb 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -52,9 +52,6 @@ void nf_unregister_afinfo(const struct nf_afinfo *afinfo)
}
EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
-struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS] __read_mostly;
-EXPORT_SYMBOL(nf_hooks);
-
#ifdef HAVE_JUMP_LABEL
struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
EXPORT_SYMBOL(nf_hooks_needed);
@@ -62,7 +59,7 @@ EXPORT_SYMBOL(nf_hooks_needed);
static DEFINE_MUTEX(nf_hook_mutex);
-int nf_register_hook(struct nf_hook_ops *reg)
+int nf_register_hook(struct net *net, struct nf_hook_ops *reg)
{
struct list_head *nf_hook_list;
struct nf_hook_ops *elem;
@@ -80,7 +77,7 @@ int nf_register_hook(struct nf_hook_ops *reg)
#endif
/* Fall through. */
default:
- nf_hook_list = &nf_hooks[reg->pf][reg->hooknum];
+ nf_hook_list = &net->nf.hooks[reg->pf][reg->hooknum];
break;
}
@@ -121,13 +118,13 @@ void nf_unregister_hook(struct nf_hook_ops *reg)
}
EXPORT_SYMBOL(nf_unregister_hook);
-int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n)
+int nf_register_hooks(struct net *net, struct nf_hook_ops *reg, unsigned int n)
{
unsigned int i;
int err = 0;
for (i = 0; i < n; i++) {
- err = nf_register_hook(®[i]);
+ err = nf_register_hook(net, ®[i]);
if (err)
goto err;
}
@@ -296,6 +293,13 @@ EXPORT_SYMBOL(nf_nat_decode_session_hook);
static int __net_init netfilter_net_init(struct net *net)
{
+ int i, h;
+
+ for (i = 0; i < NFPROTO_NUMPROTO; i++) {
+ for (h = 0; h < NF_MAX_HOOKS; h++)
+ INIT_LIST_HEAD(&net->nf.hooks[i][h]);
+ }
+
#ifdef CONFIG_PROC_FS
net->nf.proc_netfilter = proc_net_mkdir(net, "netfilter",
net->proc_net);
@@ -306,6 +310,7 @@ static int __net_init netfilter_net_init(struct net *net)
return -ENOMEM;
}
#endif
+
return 0;
}
@@ -321,12 +326,7 @@ static struct pernet_operations netfilter_net_ops = {
int __init netfilter_init(void)
{
- int i, h, ret;
-
- for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) {
- for (h = 0; h < NF_MAX_HOOKS; h++)
- INIT_LIST_HEAD(&nf_hooks[i][h]);
- }
+ int ret;
ret = register_pernet_subsys(&netfilter_net_ops);
if (ret < 0)
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 5d2b806..2751d5a 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -2088,7 +2088,7 @@ static int __init ip_vs_init(void)
if (ret < 0)
goto cleanup_sub;
- ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
+ ret = nf_register_hooks(&init_net, ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
if (ret < 0) {
pr_err("can't register hooks.\n");
goto cleanup_dev;
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 2e88032..ab077fe 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -196,7 +196,7 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
if (verdict == NF_ACCEPT) {
next_hook:
- verdict = nf_iterate(&nf_hooks[entry->state.pf][entry->state.hook],
+ verdict = nf_iterate(entry->state.hook_list,
skb, &entry->state, &elem);
}
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 4528f12..a8d4044 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -566,7 +566,8 @@ static int nf_tables_table_enable(const struct nft_af_info *afi,
if (!(chain->flags & NFT_BASE_CHAIN))
continue;
- err = nf_register_hooks(nft_base_chain(chain)->ops, afi->nops);
+ err = nf_register_hooks(&init_net, nft_base_chain(chain)->ops,
+ afi->nops);
if (err < 0)
goto err;
@@ -1418,7 +1419,8 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
if (!(table->flags & NFT_TABLE_F_DORMANT) &&
chain->flags & NFT_BASE_CHAIN) {
- err = nf_register_hooks(nft_base_chain(chain)->ops, afi->nops);
+ err = nf_register_hooks(&init_net, nft_base_chain(chain)->ops,
+ afi->nops);
if (err < 0)
goto err1;
}
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 6062ce3..0891564 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -1201,7 +1201,7 @@ struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn)
++i;
}
- ret = nf_register_hooks(ops, num_hooks);
+ ret = nf_register_hooks(&init_net, ops, num_hooks);
if (ret < 0) {
kfree(ops);
return ERR_PTR(ret);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 7dade28..7246654 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6156,7 +6156,8 @@ static int __init selinux_nf_ip_init(void)
printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
- err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
+ err = nf_register_hooks(&init_net, selinux_nf_ops,
+ ARRAY_SIZE(selinux_nf_ops));
if (err)
panic("SELinux: nf_register_hooks: error %d\n", err);
@@ -6170,7 +6171,8 @@ static void selinux_nf_ip_exit(void)
{
printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
- nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
+ nf_unregister_hooks(&init_net, selinux_nf_ops,
+ ARRAY_SIZE(selinux_nf_ops));
}
#endif
diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
index a455cfc..e39f79e 100644
--- a/security/smack/smack_netfilter.c
+++ b/security/smack/smack_netfilter.c
@@ -82,7 +82,8 @@ static int __init smack_nf_ip_init(void)
printk(KERN_DEBUG "Smack: Registering netfilter hooks\n");
- err = nf_register_hooks(smack_nf_ops, ARRAY_SIZE(smack_nf_ops));
+ err = nf_register_hooks(&init_net, smack_nf_ops,
+ ARRAY_SIZE(smack_nf_ops));
if (err)
pr_info("Smack: nf_register_hooks: error %d\n", err);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH RFC 05/15] netfilter: ipt_CLUSTERIP: adapt it to support pernet hooks
2015-06-15 15:46 [PATCH RFC 00/15] Netfilter pernet hook support Pablo Neira Ayuso
` (3 preceding siblings ...)
2015-06-15 15:46 ` [PATCH RFC 04/15] netfilter: add pernet hook support Pablo Neira Ayuso
@ 2015-06-15 15:46 ` Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 06/15] netfilter: x_tables: adapt xt_hook_link() " Pablo Neira Ayuso
` (9 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2015-06-15 15:46 UTC (permalink / raw
To: netfilter-devel; +Cc: ebiederm, aschultz, kaber
This target is deprecated, but let's adapt this so it doesn't break existing
users.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/ipv4/netfilter/ipt_CLUSTERIP.c | 31 +++++++++++++++++++++++--------
1 file changed, 23 insertions(+), 8 deletions(-)
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index cf23858..0baa7f9 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -69,6 +69,8 @@ struct clusterip_net {
/* lock protects the configs list */
spinlock_t lock;
+ struct nf_hook_ops *ops;
+
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *procdir;
#endif
@@ -724,6 +726,7 @@ static const struct file_operations clusterip_proc_fops = {
static int clusterip_net_init(struct net *net)
{
struct clusterip_net *cn = net_generic(net, clusterip_net_id);
+ int err;
INIT_LIST_HEAD(&cn->configs);
@@ -737,13 +740,32 @@ static int clusterip_net_init(struct net *net)
}
#endif /* CONFIG_PROC_FS */
+ err = -ENOMEM;
+ cn->ops = kmemdup(&cip_arp_ops, sizeof(cip_arp_ops), GFP_KERNEL);
+ if (cn->ops == NULL)
+ goto err1;
+
+ err = nf_register_hook(net, cn->ops);
+ if (err < 0)
+ goto err2;
+
return 0;
+err2:
+ kfree(cn->ops);
+err1:
+ proc_remove(cn->procdir);
+
+ return err;
}
static void clusterip_net_exit(struct net *net)
{
-#ifdef CONFIG_PROC_FS
struct clusterip_net *cn = net_generic(net, clusterip_net_id);
+
+ nf_unregister_hook(cn->ops);
+ kfree(cn->ops);
+
+#ifdef CONFIG_PROC_FS
proc_remove(cn->procdir);
#endif
}
@@ -767,17 +789,11 @@ static int __init clusterip_tg_init(void)
if (ret < 0)
goto cleanup_subsys;
- ret = nf_register_hook(&init_net, &cip_arp_ops);
- if (ret < 0)
- goto cleanup_target;
-
pr_info("ClusterIP Version %s loaded successfully\n",
CLUSTERIP_VERSION);
return 0;
-cleanup_target:
- xt_unregister_target(&clusterip_tg_reg);
cleanup_subsys:
unregister_pernet_subsys(&clusterip_net_ops);
return ret;
@@ -787,7 +803,6 @@ static void __exit clusterip_tg_exit(void)
{
pr_info("ClusterIP Version %s unloading\n", CLUSTERIP_VERSION);
- nf_unregister_hook(&cip_arp_ops);
xt_unregister_target(&clusterip_tg_reg);
unregister_pernet_subsys(&clusterip_net_ops);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH RFC 06/15] netfilter: x_tables: adapt xt_hook_link() to support pernet hooks
2015-06-15 15:46 [PATCH RFC 00/15] Netfilter pernet hook support Pablo Neira Ayuso
` (4 preceding siblings ...)
2015-06-15 15:46 ` [PATCH RFC 05/15] netfilter: ipt_CLUSTERIP: adapt it to support pernet hooks Pablo Neira Ayuso
@ 2015-06-15 15:46 ` Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 07/15] netfilter: x_tables: adapt tables to " Pablo Neira Ayuso
` (8 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2015-06-15 15:46 UTC (permalink / raw
To: netfilter-devel; +Cc: ebiederm, aschultz, kaber
This prepares the port of the existing tables to the pernet hooks.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/linux/netfilter/x_tables.h | 3 ++-
net/ipv4/netfilter/arptable_filter.c | 3 ++-
net/ipv4/netfilter/iptable_filter.c | 3 ++-
net/ipv4/netfilter/iptable_mangle.c | 3 ++-
net/ipv4/netfilter/iptable_raw.c | 2 +-
net/ipv4/netfilter/iptable_security.c | 3 ++-
net/ipv6/netfilter/ip6table_filter.c | 3 ++-
net/ipv6/netfilter/ip6table_mangle.c | 3 ++-
net/ipv6/netfilter/ip6table_raw.c | 2 +-
net/ipv6/netfilter/ip6table_security.c | 3 ++-
net/netfilter/x_tables.c | 5 +++--
11 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 9969d79..8344092 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -402,7 +402,8 @@ xt_get_per_cpu_counter(struct xt_counters *cnt, unsigned int cpu)
return cnt;
}
-struct nf_hook_ops *xt_hook_link(const struct xt_table *, nf_hookfn *);
+struct nf_hook_ops *xt_hook_link(struct net *net, const struct xt_table *,
+ nf_hookfn *);
void xt_hook_unlink(const struct xt_table *, struct nf_hook_ops *);
#ifdef CONFIG_COMPAT
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 93876d0..c7a7729 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -69,7 +69,8 @@ static int __init arptable_filter_init(void)
if (ret < 0)
return ret;
- arpfilter_ops = xt_hook_link(&packet_filter, arptable_filter_hook);
+ arpfilter_ops = xt_hook_link(&init_net, &packet_filter,
+ arptable_filter_hook);
if (IS_ERR(arpfilter_ops)) {
ret = PTR_ERR(arpfilter_ops);
goto cleanup_table;
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index a0f3bec..f0faa27 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -90,7 +90,8 @@ static int __init iptable_filter_init(void)
return ret;
/* Register hooks */
- filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook);
+ filter_ops = xt_hook_link(&init_net, &packet_filter,
+ iptable_filter_hook);
if (IS_ERR(filter_ops)) {
ret = PTR_ERR(filter_ops);
unregister_pernet_subsys(&iptable_filter_net_ops);
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 62cbb8c..bd294b4 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -128,7 +128,8 @@ static int __init iptable_mangle_init(void)
return ret;
/* Register hooks */
- mangle_ops = xt_hook_link(&packet_mangler, iptable_mangle_hook);
+ mangle_ops = xt_hook_link(&init_net, &packet_mangler,
+ iptable_mangle_hook);
if (IS_ERR(mangle_ops)) {
ret = PTR_ERR(mangle_ops);
unregister_pernet_subsys(&iptable_mangle_net_ops);
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 0356e6d..2541383 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -69,7 +69,7 @@ static int __init iptable_raw_init(void)
return ret;
/* Register hooks */
- rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook);
+ rawtable_ops = xt_hook_link(&init_net, &packet_raw, iptable_raw_hook);
if (IS_ERR(rawtable_ops)) {
ret = PTR_ERR(rawtable_ops);
unregister_pernet_subsys(&iptable_raw_net_ops);
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c
index 4bce398..0a0ddc7 100644
--- a/net/ipv4/netfilter/iptable_security.c
+++ b/net/ipv4/netfilter/iptable_security.c
@@ -86,7 +86,8 @@ static int __init iptable_security_init(void)
if (ret < 0)
return ret;
- sectbl_ops = xt_hook_link(&security_table, iptable_security_hook);
+ sectbl_ops = xt_hook_link(&init_net, &security_table,
+ iptable_security_hook);
if (IS_ERR(sectbl_ops)) {
ret = PTR_ERR(sectbl_ops);
goto cleanup_table;
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 5c33d8a..fe0bf52 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -82,7 +82,8 @@ static int __init ip6table_filter_init(void)
return ret;
/* Register hooks */
- filter_ops = xt_hook_link(&packet_filter, ip6table_filter_hook);
+ filter_ops = xt_hook_link(&init_net, &packet_filter,
+ ip6table_filter_hook);
if (IS_ERR(filter_ops)) {
ret = PTR_ERR(filter_ops);
goto cleanup_table;
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index b551f5b..50fea9e 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -122,7 +122,8 @@ static int __init ip6table_mangle_init(void)
return ret;
/* Register hooks */
- mangle_ops = xt_hook_link(&packet_mangler, ip6table_mangle_hook);
+ mangle_ops = xt_hook_link(&init_net, &packet_mangler,
+ ip6table_mangle_hook);
if (IS_ERR(mangle_ops)) {
ret = PTR_ERR(mangle_ops);
goto cleanup_table;
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 0b33caa..141604f 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -61,7 +61,7 @@ static int __init ip6table_raw_init(void)
return ret;
/* Register hooks */
- rawtable_ops = xt_hook_link(&packet_raw, ip6table_raw_hook);
+ rawtable_ops = xt_hook_link(&init_net, &packet_raw, ip6table_raw_hook);
if (IS_ERR(rawtable_ops)) {
ret = PTR_ERR(rawtable_ops);
goto cleanup_table;
diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c
index fcef83c..8d252f8 100644
--- a/net/ipv6/netfilter/ip6table_security.c
+++ b/net/ipv6/netfilter/ip6table_security.c
@@ -78,7 +78,8 @@ static int __init ip6table_security_init(void)
if (ret < 0)
return ret;
- sectbl_ops = xt_hook_link(&security_table, ip6table_security_hook);
+ sectbl_ops = xt_hook_link(&init_net, &security_table,
+ ip6table_security_hook);
if (IS_ERR(sectbl_ops)) {
ret = PTR_ERR(sectbl_ops);
goto cleanup_table;
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 0891564..fb846d6 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -1177,7 +1177,8 @@ static const struct file_operations xt_target_ops = {
* This function will take care of creating and registering the necessary
* Netfilter hooks for XT tables.
*/
-struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn)
+struct nf_hook_ops *xt_hook_link(struct net *net, const struct xt_table *table,
+ nf_hookfn *fn)
{
unsigned int hook_mask = table->valid_hooks;
uint8_t i, num_hooks = hweight32(hook_mask);
@@ -1201,7 +1202,7 @@ struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn)
++i;
}
- ret = nf_register_hooks(&init_net, ops, num_hooks);
+ ret = nf_register_hooks(net, ops, num_hooks);
if (ret < 0) {
kfree(ops);
return ERR_PTR(ret);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH RFC 07/15] netfilter: x_tables: adapt tables to pernet hooks
2015-06-15 15:46 [PATCH RFC 00/15] Netfilter pernet hook support Pablo Neira Ayuso
` (5 preceding siblings ...)
2015-06-15 15:46 ` [PATCH RFC 06/15] netfilter: x_tables: adapt xt_hook_link() " Pablo Neira Ayuso
@ 2015-06-15 15:46 ` Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 08/15] netfilter: nf_conntrack: adapt IPv4 and IPv6 trackers " Pablo Neira Ayuso
` (7 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2015-06-15 15:46 UTC (permalink / raw
To: netfilter-devel; +Cc: ebiederm, aschultz, kaber
To achieve this, this patch moves struct nf_hook_ops to the xt_table struct.
This has a nice side effect since this simplifies the boiler plate code that
registers a table.
There is one exception though, since NAT tables are special given that
their hooks have different priorities. To address this, they use the new
__ip{6}t_register_table() and __ip{6}_unregister_table() that don't call
xt_hook_link(). Then, these table manually register the hooks and attach
the nf_hooks_ops to the new xt_table field.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/linux/netfilter/x_tables.h | 2 ++
include/linux/netfilter_arp/arp_tables.h | 3 +-
include/linux/netfilter_ipv4/ip_tables.h | 8 ++++-
include/linux/netfilter_ipv6/ip6_tables.h | 8 ++++-
net/ipv4/netfilter/arp_tables.c | 15 +++++++-
net/ipv4/netfilter/arptable_filter.c | 26 +++-----------
net/ipv4/netfilter/ip_tables.c | 46 +++++++++++++++++++++---
net/ipv4/netfilter/iptable_filter.c | 22 ++----------
net/ipv4/netfilter/iptable_mangle.c | 22 ++----------
net/ipv4/netfilter/iptable_nat.c | 55 ++++++++++++++++++-----------
net/ipv4/netfilter/iptable_raw.c | 20 ++---------
net/ipv4/netfilter/iptable_security.c | 25 ++-----------
net/ipv6/netfilter/ip6_tables.c | 42 ++++++++++++++++++++--
net/ipv6/netfilter/ip6table_filter.c | 26 ++------------
net/ipv6/netfilter/ip6table_mangle.c | 25 ++-----------
net/ipv6/netfilter/ip6table_nat.c | 55 ++++++++++++++++++-----------
net/ipv6/netfilter/ip6table_raw.c | 24 ++-----------
net/ipv6/netfilter/ip6table_security.c | 25 ++-----------
18 files changed, 210 insertions(+), 239 deletions(-)
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 8344092..7d6c808 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -192,6 +192,8 @@ struct xt_table {
/* Man behind the curtain... */
struct xt_table_info *private;
+ struct nf_hook_ops *ops;
+
/* Set this to THIS_MODULE if you are a module, otherwise NULL */
struct module *me;
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index c22a7fb..9d8d25d 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -50,7 +50,8 @@ struct arpt_error {
extern void *arpt_alloc_initial_table(const struct xt_table *);
extern struct xt_table *arpt_register_table(struct net *net,
const struct xt_table *table,
- const struct arpt_replace *repl);
+ const struct arpt_replace *repl,
+ nf_hookfn *hookfn);
extern void arpt_unregister_table(struct xt_table *table);
extern unsigned int arpt_do_table(struct sk_buff *skb,
unsigned int hook,
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 4073510..aae5b92 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -26,9 +26,15 @@ extern void ipt_init(void) __init;
extern struct xt_table *ipt_register_table(struct net *net,
const struct xt_table *table,
- const struct ipt_replace *repl);
+ const struct ipt_replace *repl,
+ nf_hookfn *hookfn);
extern void ipt_unregister_table(struct net *net, struct xt_table *table);
+extern struct xt_table *__ipt_register_table(struct net *net,
+ const struct xt_table *table,
+ const struct ipt_replace *repl);
+extern void __ipt_unregister_table(struct net *net, struct xt_table *table);
+
/* Standard entry. */
struct ipt_standard {
struct ipt_entry entry;
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index b40d2b6..2fdabe2 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -27,8 +27,14 @@ extern void ip6t_init(void) __init;
extern void *ip6t_alloc_initial_table(const struct xt_table *);
extern struct xt_table *ip6t_register_table(struct net *net,
const struct xt_table *table,
- const struct ip6t_replace *repl);
+ const struct ip6t_replace *repl,
+ nf_hookfn *hookfn);
extern void ip6t_unregister_table(struct net *net, struct xt_table *table);
+extern struct xt_table *__ip6t_register_table(struct net *net,
+ const struct xt_table *table,
+ const struct ip6t_replace *repl);
+extern void __ip6t_unregister_table(struct net *net, struct xt_table *table);
+
extern unsigned int ip6t_do_table(struct sk_buff *skb,
unsigned int hook,
const struct nf_hook_state *state,
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index d75c139..7d1f327 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -1779,13 +1779,15 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
struct xt_table *arpt_register_table(struct net *net,
const struct xt_table *table,
- const struct arpt_replace *repl)
+ const struct arpt_replace *repl,
+ nf_hookfn *hookfn)
{
int ret;
struct xt_table_info *newinfo;
struct xt_table_info bootstrap = {0};
void *loc_cpu_entry;
struct xt_table *new_table;
+ struct nf_hook_ops *ops;
newinfo = xt_alloc_table_info(repl->size);
if (!newinfo) {
@@ -1806,8 +1808,17 @@ struct xt_table *arpt_register_table(struct net *net,
ret = PTR_ERR(new_table);
goto out_free;
}
+
+ ops = xt_hook_link(net, table, hookfn);
+ if (IS_ERR(ops)) {
+ ret = PTR_ERR(ops);
+ goto out_unregister_table;
+ }
+
return new_table;
+out_unregister_table:
+ xt_unregister_table(new_table);
out_free:
xt_free_table_info(newinfo);
out:
@@ -1821,6 +1832,8 @@ void arpt_unregister_table(struct xt_table *table)
struct module *table_owner = table->me;
struct arpt_entry *iter;
+ xt_hook_unlink(table, table->ops);
+
private = xt_unregister_table(table);
/* Decrease module usage counts and free resources */
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index c7a7729..eb2c514 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -36,17 +36,16 @@ arptable_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
net->ipv4.arptable_filter);
}
-static struct nf_hook_ops *arpfilter_ops __read_mostly;
-
static int __net_init arptable_filter_net_init(struct net *net)
{
struct arpt_replace *repl;
-
+
repl = arpt_alloc_initial_table(&packet_filter);
if (repl == NULL)
return -ENOMEM;
net->ipv4.arptable_filter =
- arpt_register_table(net, &packet_filter, repl);
+ arpt_register_table(net, &packet_filter, repl,
+ arptable_filter_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv4.arptable_filter);
}
@@ -63,28 +62,11 @@ static struct pernet_operations arptable_filter_net_ops = {
static int __init arptable_filter_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&arptable_filter_net_ops);
- if (ret < 0)
- return ret;
-
- arpfilter_ops = xt_hook_link(&init_net, &packet_filter,
- arptable_filter_hook);
- if (IS_ERR(arpfilter_ops)) {
- ret = PTR_ERR(arpfilter_ops);
- goto cleanup_table;
- }
- return ret;
-
-cleanup_table:
- unregister_pernet_subsys(&arptable_filter_net_ops);
- return ret;
+ return register_pernet_subsys(&arptable_filter_net_ops);
}
static void __exit arptable_filter_fini(void)
{
- xt_hook_unlink(&packet_filter, arpfilter_ops);
unregister_pernet_subsys(&arptable_filter_net_ops);
}
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 6151500..3a3048e 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -2057,9 +2057,10 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
return ret;
}
-struct xt_table *ipt_register_table(struct net *net,
- const struct xt_table *table,
- const struct ipt_replace *repl)
+/* Just like ipt_register_table() but no hook in registered. */
+struct xt_table *__ipt_register_table(struct net *net,
+ const struct xt_table *table,
+ const struct ipt_replace *repl)
{
int ret;
struct xt_table_info *newinfo;
@@ -2093,8 +2094,38 @@ out_free:
out:
return ERR_PTR(ret);
}
+EXPORT_SYMBOL_GPL(__ipt_register_table);
-void ipt_unregister_table(struct net *net, struct xt_table *table)
+struct xt_table *ipt_register_table(struct net *net,
+ const struct xt_table *table,
+ const struct ipt_replace *repl,
+ nf_hookfn *hookfn)
+{
+ struct xt_table *new_table;
+ struct nf_hook_ops *ops;
+ int ret;
+
+ new_table = __ipt_register_table(net, table, repl);
+ if (IS_ERR(new_table)) {
+ ret = PTR_ERR(new_table);
+ goto out;
+ }
+
+ ops = xt_hook_link(net, table, hookfn);
+ if (IS_ERR(ops)) {
+ ret = PTR_ERR(ops);
+ goto out_free;
+ }
+
+ return new_table;
+out_free:
+ __ipt_unregister_table(net, new_table);
+out:
+ return ERR_PTR(ret);
+}
+
+/* Just like ipt_unregister_table() but no hook in unregistered. */
+void __ipt_unregister_table(struct net *net, struct xt_table *table)
{
struct xt_table_info *private;
void *loc_cpu_entry;
@@ -2111,6 +2142,13 @@ void ipt_unregister_table(struct net *net, struct xt_table *table)
module_put(table_owner);
xt_free_table_info(private);
}
+EXPORT_SYMBOL_GPL(__ipt_unregister_table);
+
+void ipt_unregister_table(struct net *net, struct xt_table *table)
+{
+ xt_hook_unlink(table, table->ops);
+ __ipt_unregister_table(net, table);
+}
/* Returns 1 if the type and code is matched by the range, 0 otherwise */
static inline bool
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index f0faa27..4cddbd7 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -48,8 +48,6 @@ iptable_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
return ipt_do_table(skb, ops->hooknum, state, net->ipv4.iptable_filter);
}
-static struct nf_hook_ops *filter_ops __read_mostly;
-
/* Default to forward because I got too much mail already. */
static bool forward = true;
module_param(forward, bool, 0000);
@@ -66,7 +64,8 @@ static int __net_init iptable_filter_net_init(struct net *net)
forward ? -NF_ACCEPT - 1 : -NF_DROP - 1;
net->ipv4.iptable_filter =
- ipt_register_table(net, &packet_filter, repl);
+ ipt_register_table(net, &packet_filter, repl,
+ iptable_filter_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv4.iptable_filter);
}
@@ -83,26 +82,11 @@ static struct pernet_operations iptable_filter_net_ops = {
static int __init iptable_filter_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&iptable_filter_net_ops);
- if (ret < 0)
- return ret;
-
- /* Register hooks */
- filter_ops = xt_hook_link(&init_net, &packet_filter,
- iptable_filter_hook);
- if (IS_ERR(filter_ops)) {
- ret = PTR_ERR(filter_ops);
- unregister_pernet_subsys(&iptable_filter_net_ops);
- }
-
- return ret;
+ return register_pernet_subsys(&iptable_filter_net_ops);
}
static void __exit iptable_filter_fini(void)
{
- xt_hook_unlink(&packet_filter, filter_ops);
unregister_pernet_subsys(&iptable_filter_net_ops);
}
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index bd294b4..f97a86b 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -94,8 +94,6 @@ iptable_mangle_hook(const struct nf_hook_ops *ops,
dev_net(state->in)->ipv4.iptable_mangle);
}
-static struct nf_hook_ops *mangle_ops __read_mostly;
-
static int __net_init iptable_mangle_net_init(struct net *net)
{
struct ipt_replace *repl;
@@ -104,7 +102,8 @@ static int __net_init iptable_mangle_net_init(struct net *net)
if (repl == NULL)
return -ENOMEM;
net->ipv4.iptable_mangle =
- ipt_register_table(net, &packet_mangler, repl);
+ ipt_register_table(net, &packet_mangler, repl,
+ iptable_mangle_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv4.iptable_mangle);
}
@@ -121,26 +120,11 @@ static struct pernet_operations iptable_mangle_net_ops = {
static int __init iptable_mangle_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&iptable_mangle_net_ops);
- if (ret < 0)
- return ret;
-
- /* Register hooks */
- mangle_ops = xt_hook_link(&init_net, &packet_mangler,
- iptable_mangle_hook);
- if (IS_ERR(mangle_ops)) {
- ret = PTR_ERR(mangle_ops);
- unregister_pernet_subsys(&iptable_mangle_net_ops);
- }
-
- return ret;
+ return register_pernet_subsys(&iptable_mangle_net_ops);
}
static void __exit iptable_mangle_fini(void)
{
- xt_hook_unlink(&packet_mangler, mangle_ops);
unregister_pernet_subsys(&iptable_mangle_net_ops);
}
diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c
index 5ef83d3..0bb164e 100644
--- a/net/ipv4/netfilter/iptable_nat.c
+++ b/net/ipv4/netfilter/iptable_nat.c
@@ -104,18 +104,49 @@ static struct nf_hook_ops nf_nat_ipv4_ops[] __read_mostly = {
static int __net_init iptable_nat_net_init(struct net *net)
{
struct ipt_replace *repl;
+ int err;
repl = ipt_alloc_initial_table(&nf_nat_ipv4_table);
if (repl == NULL)
return -ENOMEM;
- net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl);
+
+ net->ipv4.nat_table = __ipt_register_table(net, &nf_nat_ipv4_table,
+ repl);
+ if (IS_ERR(net->ipv4.nat_table)) {
+ err = PTR_ERR(net->ipv4.nat_table);
+ goto err1;
+ }
kfree(repl);
- return PTR_ERR_OR_ZERO(net->ipv4.nat_table);
+
+ net->ipv4.nat_table->ops = kmemdup(nf_nat_ipv4_ops,
+ sizeof(nf_nat_ipv4_ops), GFP_KERNEL);
+ if (net->ipv4.nat_table->ops == NULL) {
+ err = -ENOMEM;
+ goto err2;
+ }
+
+ err = nf_register_hooks(net, net->ipv4.nat_table->ops,
+ ARRAY_SIZE(nf_nat_ipv4_ops));
+ if (err < 0)
+ goto err3;
+
+ return 0;
+err3:
+ kfree(net->ipv4.nat_table->ops);
+err2:
+ __ipt_unregister_table(net, net->ipv4.nat_table);
+err1:
+ kfree(repl);
+
+ return err;
}
static void __net_exit iptable_nat_net_exit(struct net *net)
{
- ipt_unregister_table(net, net->ipv4.nat_table);
+ nf_unregister_hooks(net->ipv4.nat_table->ops,
+ ARRAY_SIZE(nf_nat_ipv4_ops));
+ kfree(net->ipv4.nat_table->ops);
+ __ipt_unregister_table(net, net->ipv4.nat_table);
}
static struct pernet_operations iptable_nat_net_ops = {
@@ -125,27 +156,11 @@ static struct pernet_operations iptable_nat_net_ops = {
static int __init iptable_nat_init(void)
{
- int err;
-
- err = register_pernet_subsys(&iptable_nat_net_ops);
- if (err < 0)
- goto err1;
-
- err = nf_register_hooks(&init_net, nf_nat_ipv4_ops,
- ARRAY_SIZE(nf_nat_ipv4_ops));
- if (err < 0)
- goto err2;
- return 0;
-
-err2:
- unregister_pernet_subsys(&iptable_nat_net_ops);
-err1:
- return err;
+ return register_pernet_subsys(&iptable_nat_net_ops);
}
static void __exit iptable_nat_exit(void)
{
- nf_unregister_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops));
unregister_pernet_subsys(&iptable_nat_net_ops);
}
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 2541383..908f34c 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -35,8 +35,6 @@ iptable_raw_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
return ipt_do_table(skb, ops->hooknum, state, net->ipv4.iptable_raw);
}
-static struct nf_hook_ops *rawtable_ops __read_mostly;
-
static int __net_init iptable_raw_net_init(struct net *net)
{
struct ipt_replace *repl;
@@ -45,7 +43,7 @@ static int __net_init iptable_raw_net_init(struct net *net)
if (repl == NULL)
return -ENOMEM;
net->ipv4.iptable_raw =
- ipt_register_table(net, &packet_raw, repl);
+ ipt_register_table(net, &packet_raw, repl, iptable_raw_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv4.iptable_raw);
}
@@ -62,25 +60,11 @@ static struct pernet_operations iptable_raw_net_ops = {
static int __init iptable_raw_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&iptable_raw_net_ops);
- if (ret < 0)
- return ret;
-
- /* Register hooks */
- rawtable_ops = xt_hook_link(&init_net, &packet_raw, iptable_raw_hook);
- if (IS_ERR(rawtable_ops)) {
- ret = PTR_ERR(rawtable_ops);
- unregister_pernet_subsys(&iptable_raw_net_ops);
- }
-
- return ret;
+ return register_pernet_subsys(&iptable_raw_net_ops);
}
static void __exit iptable_raw_fini(void)
{
- xt_hook_unlink(&packet_raw, rawtable_ops);
unregister_pernet_subsys(&iptable_raw_net_ops);
}
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c
index 0a0ddc7..d4c8729 100644
--- a/net/ipv4/netfilter/iptable_security.c
+++ b/net/ipv4/netfilter/iptable_security.c
@@ -53,8 +53,6 @@ iptable_security_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
net->ipv4.iptable_security);
}
-static struct nf_hook_ops *sectbl_ops __read_mostly;
-
static int __net_init iptable_security_net_init(struct net *net)
{
struct ipt_replace *repl;
@@ -63,7 +61,8 @@ static int __net_init iptable_security_net_init(struct net *net)
if (repl == NULL)
return -ENOMEM;
net->ipv4.iptable_security =
- ipt_register_table(net, &security_table, repl);
+ ipt_register_table(net, &security_table, repl,
+ iptable_security_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv4.iptable_security);
}
@@ -80,29 +79,11 @@ static struct pernet_operations iptable_security_net_ops = {
static int __init iptable_security_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&iptable_security_net_ops);
- if (ret < 0)
- return ret;
-
- sectbl_ops = xt_hook_link(&init_net, &security_table,
- iptable_security_hook);
- if (IS_ERR(sectbl_ops)) {
- ret = PTR_ERR(sectbl_ops);
- goto cleanup_table;
- }
-
- return ret;
-
-cleanup_table:
- unregister_pernet_subsys(&iptable_security_net_ops);
- return ret;
+ return register_pernet_subsys(&iptable_security_net_ops);
}
static void __exit iptable_security_fini(void)
{
- xt_hook_unlink(&security_table, sectbl_ops);
unregister_pernet_subsys(&iptable_security_net_ops);
}
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 80a7f0d..3cbc37d 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -2067,7 +2067,8 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
return ret;
}
-struct xt_table *ip6t_register_table(struct net *net,
+/* Just like ip6t_register_table() but no hook is registered. */
+struct xt_table *__ip6t_register_table(struct net *net,
const struct xt_table *table,
const struct ip6t_replace *repl)
{
@@ -2102,8 +2103,38 @@ out_free:
out:
return ERR_PTR(ret);
}
+EXPORT_SYMBOL_GPL(__ip6t_register_table);
-void ip6t_unregister_table(struct net *net, struct xt_table *table)
+struct xt_table *ip6t_register_table(struct net *net,
+ const struct xt_table *table,
+ const struct ip6t_replace *repl,
+ nf_hookfn *hookfn)
+{
+ struct xt_table *new_table;
+ struct nf_hook_ops *ops;
+ int err;
+
+ new_table = __ip6t_register_table(net, table, repl);
+ if (IS_ERR(new_table)) {
+ err = PTR_ERR(new_table);
+ goto err1;
+ }
+
+ ops = xt_hook_link(net, table, hookfn);
+ if (IS_ERR(ops)) {
+ err = PTR_ERR(ops);
+ goto err2;
+ }
+
+ return 0;
+err2:
+ __ip6t_unregister_table(net, new_table);
+err1:
+ return ERR_PTR(err);
+}
+
+/* Just like ip6t_unregister_table() but no hook is unregistered. */
+void __ip6t_unregister_table(struct net *net, struct xt_table *table)
{
struct xt_table_info *private;
void *loc_cpu_entry;
@@ -2120,6 +2151,13 @@ void ip6t_unregister_table(struct net *net, struct xt_table *table)
module_put(table_owner);
xt_free_table_info(private);
}
+EXPORT_SYMBOL_GPL(__ip6t_unregister_table);
+
+void ip6t_unregister_table(struct net *net, struct xt_table *table)
+{
+ __ip6t_unregister_table(net, table);
+ xt_hook_unlink(table, table->ops);
+}
/* Returns 1 if the type and code is matched by the range, 0 otherwise */
static inline bool
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index fe0bf52..77d237b 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -40,8 +40,6 @@ ip6table_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
return ip6t_do_table(skb, ops->hooknum, state, net->ipv6.ip6table_filter);
}
-static struct nf_hook_ops *filter_ops __read_mostly;
-
/* Default to forward because I got too much mail already. */
static bool forward = true;
module_param(forward, bool, 0000);
@@ -58,7 +56,8 @@ static int __net_init ip6table_filter_net_init(struct net *net)
forward ? -NF_ACCEPT - 1 : -NF_DROP - 1;
net->ipv6.ip6table_filter =
- ip6t_register_table(net, &packet_filter, repl);
+ ip6t_register_table(net, &packet_filter, repl,
+ ip6table_filter_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv6.ip6table_filter);
}
@@ -75,30 +74,11 @@ static struct pernet_operations ip6table_filter_net_ops = {
static int __init ip6table_filter_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&ip6table_filter_net_ops);
- if (ret < 0)
- return ret;
-
- /* Register hooks */
- filter_ops = xt_hook_link(&init_net, &packet_filter,
- ip6table_filter_hook);
- if (IS_ERR(filter_ops)) {
- ret = PTR_ERR(filter_ops);
- goto cleanup_table;
- }
-
- return ret;
-
- cleanup_table:
- unregister_pernet_subsys(&ip6table_filter_net_ops);
- return ret;
+ return register_pernet_subsys(&ip6table_filter_net_ops);
}
static void __exit ip6table_filter_fini(void)
{
- xt_hook_unlink(&packet_filter, filter_ops);
unregister_pernet_subsys(&ip6table_filter_net_ops);
}
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 50fea9e..f2d7355 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -89,7 +89,6 @@ ip6table_mangle_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
dev_net(state->in)->ipv6.ip6table_mangle);
}
-static struct nf_hook_ops *mangle_ops __read_mostly;
static int __net_init ip6table_mangle_net_init(struct net *net)
{
struct ip6t_replace *repl;
@@ -98,7 +97,8 @@ static int __net_init ip6table_mangle_net_init(struct net *net)
if (repl == NULL)
return -ENOMEM;
net->ipv6.ip6table_mangle =
- ip6t_register_table(net, &packet_mangler, repl);
+ ip6t_register_table(net, &packet_mangler, repl,
+ ip6table_mangle_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv6.ip6table_mangle);
}
@@ -115,30 +115,11 @@ static struct pernet_operations ip6table_mangle_net_ops = {
static int __init ip6table_mangle_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&ip6table_mangle_net_ops);
- if (ret < 0)
- return ret;
-
- /* Register hooks */
- mangle_ops = xt_hook_link(&init_net, &packet_mangler,
- ip6table_mangle_hook);
- if (IS_ERR(mangle_ops)) {
- ret = PTR_ERR(mangle_ops);
- goto cleanup_table;
- }
-
- return ret;
-
- cleanup_table:
- unregister_pernet_subsys(&ip6table_mangle_net_ops);
- return ret;
+ return register_pernet_subsys(&ip6table_mangle_net_ops);
}
static void __exit ip6table_mangle_fini(void)
{
- xt_hook_unlink(&packet_mangler, mangle_ops);
unregister_pernet_subsys(&ip6table_mangle_net_ops);
}
diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c
index ecb0511..44e755a 100644
--- a/net/ipv6/netfilter/ip6table_nat.c
+++ b/net/ipv6/netfilter/ip6table_nat.c
@@ -106,18 +106,49 @@ static struct nf_hook_ops nf_nat_ipv6_ops[] __read_mostly = {
static int __net_init ip6table_nat_net_init(struct net *net)
{
struct ip6t_replace *repl;
+ int err;
repl = ip6t_alloc_initial_table(&nf_nat_ipv6_table);
if (repl == NULL)
return -ENOMEM;
- net->ipv6.ip6table_nat = ip6t_register_table(net, &nf_nat_ipv6_table, repl);
+
+ net->ipv6.ip6table_nat =
+ __ip6t_register_table(net, &nf_nat_ipv6_table, repl);
+ if (IS_ERR(net->ipv6.ip6table_nat)) {
+ err = PTR_ERR(net->ipv6.ip6table_nat);
+ goto err1;
+ }
kfree(repl);
- return PTR_ERR_OR_ZERO(net->ipv6.ip6table_nat);
+
+ net->ipv6.ip6table_nat->ops =
+ kmemdup(nf_nat_ipv6_ops, sizeof(nf_nat_ipv6_ops), GFP_KERNEL);
+ if (net->ipv6.ip6table_nat->ops == NULL) {
+ err = -ENOMEM;
+ goto err2;
+ }
+
+ err = nf_register_hooks(net, net->ipv6.ip6table_nat->ops,
+ ARRAY_SIZE(nf_nat_ipv6_ops));
+ if (err < 0)
+ goto err3;
+
+ return 0;
+err3:
+ kfree(net->ipv6.ip6table_nat->ops);
+err2:
+ __ip6t_unregister_table(net, net->ipv6.ip6table_nat);
+err1:
+ kfree(repl);
+
+ return err;
}
static void __net_exit ip6table_nat_net_exit(struct net *net)
{
- ip6t_unregister_table(net, net->ipv6.ip6table_nat);
+ nf_unregister_hooks(net->ipv6.ip6table_nat->ops,
+ ARRAY_SIZE(nf_nat_ipv6_ops));
+ kfree(net->ipv6.ip6table_nat->ops);
+ __ip6t_unregister_table(net, net->ipv6.ip6table_nat);
}
static struct pernet_operations ip6table_nat_net_ops = {
@@ -127,27 +158,11 @@ static struct pernet_operations ip6table_nat_net_ops = {
static int __init ip6table_nat_init(void)
{
- int err;
-
- err = register_pernet_subsys(&ip6table_nat_net_ops);
- if (err < 0)
- goto err1;
-
- err = nf_register_hooks(&init_net, nf_nat_ipv6_ops,
- ARRAY_SIZE(nf_nat_ipv6_ops));
- if (err < 0)
- goto err2;
- return 0;
-
-err2:
- unregister_pernet_subsys(&ip6table_nat_net_ops);
-err1:
- return err;
+ return register_pernet_subsys(&ip6table_nat_net_ops);
}
static void __exit ip6table_nat_exit(void)
{
- nf_unregister_hooks(nf_nat_ipv6_ops, ARRAY_SIZE(nf_nat_ipv6_ops));
unregister_pernet_subsys(&ip6table_nat_net_ops);
}
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 141604f..4c7e496 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -27,8 +27,6 @@ ip6table_raw_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
return ip6t_do_table(skb, ops->hooknum, state, net->ipv6.ip6table_raw);
}
-static struct nf_hook_ops *rawtable_ops __read_mostly;
-
static int __net_init ip6table_raw_net_init(struct net *net)
{
struct ip6t_replace *repl;
@@ -37,7 +35,7 @@ static int __net_init ip6table_raw_net_init(struct net *net)
if (repl == NULL)
return -ENOMEM;
net->ipv6.ip6table_raw =
- ip6t_register_table(net, &packet_raw, repl);
+ ip6t_register_table(net, &packet_raw, repl, ip6table_raw_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv6.ip6table_raw);
}
@@ -54,29 +52,11 @@ static struct pernet_operations ip6table_raw_net_ops = {
static int __init ip6table_raw_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&ip6table_raw_net_ops);
- if (ret < 0)
- return ret;
-
- /* Register hooks */
- rawtable_ops = xt_hook_link(&init_net, &packet_raw, ip6table_raw_hook);
- if (IS_ERR(rawtable_ops)) {
- ret = PTR_ERR(rawtable_ops);
- goto cleanup_table;
- }
-
- return ret;
-
- cleanup_table:
- unregister_pernet_subsys(&ip6table_raw_net_ops);
- return ret;
+ return register_pernet_subsys(&ip6table_raw_net_ops);
}
static void __exit ip6table_raw_fini(void)
{
- xt_hook_unlink(&packet_raw, rawtable_ops);
unregister_pernet_subsys(&ip6table_raw_net_ops);
}
diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c
index 8d252f8..8a224ca 100644
--- a/net/ipv6/netfilter/ip6table_security.c
+++ b/net/ipv6/netfilter/ip6table_security.c
@@ -45,8 +45,6 @@ ip6table_security_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
net->ipv6.ip6table_security);
}
-static struct nf_hook_ops *sectbl_ops __read_mostly;
-
static int __net_init ip6table_security_net_init(struct net *net)
{
struct ip6t_replace *repl;
@@ -55,7 +53,8 @@ static int __net_init ip6table_security_net_init(struct net *net)
if (repl == NULL)
return -ENOMEM;
net->ipv6.ip6table_security =
- ip6t_register_table(net, &security_table, repl);
+ ip6t_register_table(net, &security_table, repl,
+ ip6table_security_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv6.ip6table_security);
}
@@ -72,29 +71,11 @@ static struct pernet_operations ip6table_security_net_ops = {
static int __init ip6table_security_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&ip6table_security_net_ops);
- if (ret < 0)
- return ret;
-
- sectbl_ops = xt_hook_link(&init_net, &security_table,
- ip6table_security_hook);
- if (IS_ERR(sectbl_ops)) {
- ret = PTR_ERR(sectbl_ops);
- goto cleanup_table;
- }
-
- return ret;
-
-cleanup_table:
- unregister_pernet_subsys(&ip6table_security_net_ops);
- return ret;
+ return register_pernet_subsys(&ip6table_security_net_ops);
}
static void __exit ip6table_security_fini(void)
{
- xt_hook_unlink(&security_table, sectbl_ops);
unregister_pernet_subsys(&ip6table_security_net_ops);
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH RFC 08/15] netfilter: nf_conntrack: adapt IPv4 and IPv6 trackers to pernet hooks
2015-06-15 15:46 [PATCH RFC 00/15] Netfilter pernet hook support Pablo Neira Ayuso
` (6 preceding siblings ...)
2015-06-15 15:46 ` [PATCH RFC 07/15] netfilter: x_tables: adapt tables to " Pablo Neira Ayuso
@ 2015-06-15 15:46 ` Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 09/15] netfilter: synproxy: adapt IPv4 and IPv6 targets " Pablo Neira Ayuso
` (6 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2015-06-15 15:46 UTC (permalink / raw
To: netfilter-devel; +Cc: ebiederm, aschultz, kaber
Since pernet hooks, we need to register the hook for each netnamespace space.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netns/conntrack.h | 4 +++
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 36 +++++++++++++------
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 45 ++++++++++++++++--------
3 files changed, 59 insertions(+), 26 deletions(-)
diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h
index 29d6a94..b175886 100644
--- a/include/net/netns/conntrack.h
+++ b/include/net/netns/conntrack.h
@@ -104,6 +104,10 @@ struct netns_ct {
struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb;
struct nf_exp_event_notifier __rcu *nf_expect_event_cb;
struct nf_ip_net nf_ct_proto;
+
+ struct nf_hook_ops *ipv4_conntrack_ops;
+ struct nf_hook_ops *ipv6_conntrack_ops;
+
#if defined(CONFIG_NF_CONNTRACK_LABELS)
unsigned int labels_used;
u8 label_words;
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 2384975..ba96348 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -424,7 +424,28 @@ static int ipv4_net_init(struct net *net)
pr_err("nf_conntrack_ipv4: pernet registration failed\n");
goto out_ipv4;
}
+
+ net->ct.ipv4_conntrack_ops =
+ kmemdup(&ipv4_conntrack_ops, sizeof(ipv4_conntrack_ops),
+ GFP_KERNEL);
+ if (net->ct.ipv4_conntrack_ops == NULL) {
+ ret = -ENOMEM;
+ goto out_kmemdup;
+ }
+
+ ret = nf_register_hooks(net, net->ct.ipv4_conntrack_ops,
+ ARRAY_SIZE(ipv4_conntrack_ops));
+ if (ret < 0) {
+ pr_err("nf_conntrack_ipv4: can't register hooks.\n");
+ goto out_hook;
+ }
+
return 0;
+
+out_hook:
+ kfree(net->ct.ipv4_conntrack_ops);
+out_kmemdup:
+ nf_ct_l3proto_pernet_unregister(net, &nf_conntrack_l3proto_ipv4);
out_ipv4:
nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_icmp);
out_icmp:
@@ -437,6 +458,9 @@ out_tcp:
static void ipv4_net_exit(struct net *net)
{
+ nf_unregister_hooks(net->ct.ipv4_conntrack_ops,
+ ARRAY_SIZE(ipv4_conntrack_ops));
+ kfree(net->ct.ipv4_conntrack_ops);
nf_ct_l3proto_pernet_unregister(net, &nf_conntrack_l3proto_ipv4);
nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_icmp);
nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udp4);
@@ -467,17 +491,10 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
goto cleanup_sockopt;
}
- ret = nf_register_hooks(&init_net, ipv4_conntrack_ops,
- ARRAY_SIZE(ipv4_conntrack_ops));
- if (ret < 0) {
- pr_err("nf_conntrack_ipv4: can't register hooks.\n");
- goto cleanup_pernet;
- }
-
ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_tcp4);
if (ret < 0) {
pr_err("nf_conntrack_ipv4: can't register tcp4 proto.\n");
- goto cleanup_hooks;
+ goto cleanup_pernet;
}
ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_udp4);
@@ -514,8 +531,6 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udp4);
cleanup_tcp4:
nf_ct_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
- cleanup_hooks:
- nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
cleanup_pernet:
unregister_pernet_subsys(&ipv4_net_ops);
cleanup_sockopt:
@@ -533,7 +548,6 @@ static void __exit nf_conntrack_l3proto_ipv4_fini(void)
nf_ct_l4proto_unregister(&nf_conntrack_l4proto_icmp);
nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udp4);
nf_ct_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
- nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
unregister_pernet_subsys(&ipv4_net_ops);
nf_unregister_sockopt(&so_getorigdst);
}
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 8bcf625..47a5862 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -366,19 +366,43 @@ static int ipv6_net_init(struct net *net)
pr_err("nf_conntrack_ipv6: pernet registration failed.\n");
goto cleanup_icmpv6;
}
+
+ net->ct.ipv6_conntrack_ops =
+ kmemdup(&ipv6_conntrack_ops, sizeof(ipv6_conntrack_ops),
+ GFP_KERNEL);
+ if (net->ct.ipv6_conntrack_ops == NULL) {
+ ret = -ENOMEM;
+ goto cleanup_ipv6;
+ }
+
+ ret = nf_register_hooks(net, net->ct.ipv6_conntrack_ops,
+ ARRAY_SIZE(ipv6_conntrack_ops));
+ if (ret < 0) {
+ pr_err("nf_conntrack_ipv6: can't register pre-routing defrag hook.\n");
+ goto cleanup_kmemdup;
+ }
+
return 0;
- cleanup_icmpv6:
+
+cleanup_kmemdup:
+ kfree(net->ct.ipv6_conntrack_ops);
+cleanup_ipv6:
+ nf_ct_l3proto_pernet_unregister(net, &nf_conntrack_l3proto_ipv6);
+cleanup_icmpv6:
nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_icmpv6);
- cleanup_udp6:
+cleanup_udp6:
nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udp6);
- cleanup_tcp6:
+cleanup_tcp6:
nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_tcp6);
- out:
+out:
return ret;
}
static void ipv6_net_exit(struct net *net)
{
+ nf_unregister_hooks(net->ct.ipv6_conntrack_ops,
+ ARRAY_SIZE(ipv6_conntrack_ops));
+ kfree(net->ct.ipv6_conntrack_ops);
nf_ct_l3proto_pernet_unregister(net, &nf_conntrack_l3proto_ipv6);
nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_icmpv6);
nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_udp6);
@@ -407,18 +431,10 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
if (ret < 0)
goto cleanup_sockopt;
- ret = nf_register_hooks(&init_net, ipv6_conntrack_ops,
- ARRAY_SIZE(ipv6_conntrack_ops));
- if (ret < 0) {
- pr_err("nf_conntrack_ipv6: can't register pre-routing defrag "
- "hook.\n");
- goto cleanup_pernet;
- }
-
ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_tcp6);
if (ret < 0) {
pr_err("nf_conntrack_ipv6: can't register tcp6 proto.\n");
- goto cleanup_hooks;
+ goto cleanup_pernet;
}
ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_udp6);
@@ -438,6 +454,7 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
pr_err("nf_conntrack_ipv6: can't register ipv6 proto.\n");
goto cleanup_icmpv6;
}
+
return ret;
cleanup_icmpv6:
@@ -446,8 +463,6 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udp6);
cleanup_tcp6:
nf_ct_l4proto_unregister(&nf_conntrack_l4proto_tcp6);
- cleanup_hooks:
- nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
cleanup_pernet:
unregister_pernet_subsys(&ipv6_net_ops);
cleanup_sockopt:
--
1.7.10.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH RFC 09/15] netfilter: synproxy: adapt IPv4 and IPv6 targets to pernet hooks
2015-06-15 15:46 [PATCH RFC 00/15] Netfilter pernet hook support Pablo Neira Ayuso
` (7 preceding siblings ...)
2015-06-15 15:46 ` [PATCH RFC 08/15] netfilter: nf_conntrack: adapt IPv4 and IPv6 trackers " Pablo Neira Ayuso
@ 2015-06-15 15:46 ` Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 10/15] netfilter: defrag: add pernet hook support Pablo Neira Ayuso
` (5 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2015-06-15 15:46 UTC (permalink / raw
To: netfilter-devel; +Cc: ebiederm, aschultz, kaber
Since pernet hooks, we need to register the hook for each netnamespace space.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/ipv4/netfilter/ipt_SYNPROXY.c | 51 ++++++++++++++++++++++++++++++++---
net/ipv6/netfilter/ip6t_SYNPROXY.c | 52 +++++++++++++++++++++++++++++++++---
2 files changed, 95 insertions(+), 8 deletions(-)
diff --git a/net/ipv4/netfilter/ipt_SYNPROXY.c b/net/ipv4/netfilter/ipt_SYNPROXY.c
index a57d3d1..f38276f 100644
--- a/net/ipv4/netfilter/ipt_SYNPROXY.c
+++ b/net/ipv4/netfilter/ipt_SYNPROXY.c
@@ -446,15 +446,58 @@ static struct nf_hook_ops ipv4_synproxy_ops[] __read_mostly = {
},
};
-static int __init synproxy_tg4_init(void)
+struct synproxy_tg4_net {
+ struct nf_hook_ops *ipv4_synproxy_ops;
+};
+
+static int synproxy_tg4_net_id __read_mostly;
+
+static int synproxy_tg4_net_init(struct net *net)
{
+ struct synproxy_tg4_net *sn = net_generic(net, synproxy_tg4_net_id);
int err;
- err = nf_register_hooks(&init_net, ipv4_synproxy_ops,
+ sn->ipv4_synproxy_ops =
+ kmemdup(ipv4_synproxy_ops, sizeof(ipv4_synproxy_ops),
+ GFP_KERNEL);
+ if (sn->ipv4_synproxy_ops == NULL)
+ return -ENOMEM;
+
+ err = nf_register_hooks(net, sn->ipv4_synproxy_ops,
ARRAY_SIZE(ipv4_synproxy_ops));
if (err < 0)
goto err1;
+err1:
+ kfree(sn->ipv4_synproxy_ops);
+
+ return err;
+}
+
+static void synproxy_tg4_net_exit(struct net *net)
+{
+ struct synproxy_tg4_net *sn = net_generic(net, synproxy_tg4_net_id);
+
+ nf_unregister_hooks(sn->ipv4_synproxy_ops,
+ ARRAY_SIZE(ipv4_synproxy_ops));
+ kfree(sn->ipv4_synproxy_ops);
+}
+
+static struct pernet_operations synproxy_tg4_net_ops = {
+ .init = synproxy_tg4_net_init,
+ .exit = synproxy_tg4_net_exit,
+ .id = &synproxy_tg4_net_id,
+ .size = sizeof(struct synproxy_tg4_net),
+};
+
+static int __init synproxy_tg4_init(void)
+{
+ int err;
+
+ err = register_pernet_subsys(&synproxy_tg4_net_ops);
+ if (err < 0)
+ goto err1;
+
err = xt_register_target(&synproxy_tg4_reg);
if (err < 0)
goto err2;
@@ -462,7 +505,7 @@ static int __init synproxy_tg4_init(void)
return 0;
err2:
- nf_unregister_hooks(ipv4_synproxy_ops, ARRAY_SIZE(ipv4_synproxy_ops));
+ unregister_pernet_subsys(&synproxy_tg4_net_ops);
err1:
return err;
}
@@ -470,7 +513,7 @@ err1:
static void __exit synproxy_tg4_exit(void)
{
xt_unregister_target(&synproxy_tg4_reg);
- nf_unregister_hooks(ipv4_synproxy_ops, ARRAY_SIZE(ipv4_synproxy_ops));
+ unregister_pernet_subsys(&synproxy_tg4_net_ops);
}
module_init(synproxy_tg4_init);
diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c
index ed5d4a6..57fbd44 100644
--- a/net/ipv6/netfilter/ip6t_SYNPROXY.c
+++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c
@@ -469,15 +469,59 @@ static struct nf_hook_ops ipv6_synproxy_ops[] __read_mostly = {
},
};
-static int __init synproxy_tg6_init(void)
+struct synproxy_tg6_net {
+ struct nf_hook_ops *ipv6_synproxy_ops;
+};
+
+static int synproxy_tg6_net_id __read_mostly;
+
+static int synproxy_tg6_net_init(struct net *net)
{
+ struct synproxy_tg6_net *sn = net_generic(net, synproxy_tg6_net_id);
int err;
- err = nf_register_hooks(&init_net, ipv6_synproxy_ops,
+ sn->ipv6_synproxy_ops =
+ kmemdup(ipv6_synproxy_ops, sizeof(ipv6_synproxy_ops),
+ GFP_KERNEL);
+ if (sn->ipv6_synproxy_ops == NULL)
+ return -ENOMEM;
+
+ err = nf_register_hooks(net, sn->ipv6_synproxy_ops,
ARRAY_SIZE(ipv6_synproxy_ops));
if (err < 0)
goto err1;
+ return 0;
+err1:
+ kfree(sn->ipv6_synproxy_ops);
+
+ return err;
+}
+
+static void synproxy_tg6_net_exit(struct net *net)
+{
+ struct synproxy_tg6_net *sn = net_generic(net, synproxy_tg6_net_id);
+
+ nf_unregister_hooks(sn->ipv6_synproxy_ops,
+ ARRAY_SIZE(ipv6_synproxy_ops));
+ kfree(sn->ipv6_synproxy_ops);
+}
+
+static struct pernet_operations synproxy_tg6_net_ops = {
+ .init = synproxy_tg6_net_init,
+ .exit = synproxy_tg6_net_exit,
+ .id = &synproxy_tg6_net_id,
+ .size = sizeof(struct synproxy_tg6_net),
+};
+
+static int __init synproxy_tg6_init(void)
+{
+ int err;
+
+ err = register_pernet_subsys(&synproxy_tg6_net_ops);
+ if (err < 0)
+ goto err1;
+
err = xt_register_target(&synproxy_tg6_reg);
if (err < 0)
goto err2;
@@ -485,7 +529,7 @@ static int __init synproxy_tg6_init(void)
return 0;
err2:
- nf_unregister_hooks(ipv6_synproxy_ops, ARRAY_SIZE(ipv6_synproxy_ops));
+ unregister_pernet_subsys(&synproxy_tg6_net_ops);
err1:
return err;
}
@@ -493,7 +537,7 @@ err1:
static void __exit synproxy_tg6_exit(void)
{
xt_unregister_target(&synproxy_tg6_reg);
- nf_unregister_hooks(ipv6_synproxy_ops, ARRAY_SIZE(ipv6_synproxy_ops));
+ unregister_pernet_subsys(&synproxy_tg6_net_ops);
}
module_init(synproxy_tg6_init);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH RFC 10/15] netfilter: defrag: add pernet hook support
2015-06-15 15:46 [PATCH RFC 00/15] Netfilter pernet hook support Pablo Neira Ayuso
` (8 preceding siblings ...)
2015-06-15 15:46 ` [PATCH RFC 09/15] netfilter: synproxy: adapt IPv4 and IPv6 targets " Pablo Neira Ayuso
@ 2015-06-15 15:46 ` Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 11/15] ipvs: adapt it to pernet hooks Pablo Neira Ayuso
` (4 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2015-06-15 15:46 UTC (permalink / raw
To: netfilter-devel; +Cc: ebiederm, aschultz, kaber
Since pernet hooks, we need to register the hook for each netnamespace space.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netns/netfilter.h | 6 +++++
net/ipv4/netfilter/nf_defrag_ipv4.c | 38 +++++++++++++++++++++++---
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 41 ++++++++++++++++++++++++++---
3 files changed, 78 insertions(+), 7 deletions(-)
diff --git a/include/net/netns/netfilter.h b/include/net/netns/netfilter.h
index 38aa498..f2b513d 100644
--- a/include/net/netns/netfilter.h
+++ b/include/net/netns/netfilter.h
@@ -15,5 +15,11 @@ struct netns_nf {
struct ctl_table_header *nf_log_dir_header;
#endif
struct list_head hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
+#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4)
+ struct nf_hook_ops *ipv4_defrag_ops;
+#endif
+#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
+ struct nf_hook_ops *ipv6_defrag_ops;
+#endif
};
#endif
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
index ad74929..084a995 100644
--- a/net/ipv4/netfilter/nf_defrag_ipv4.c
+++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
@@ -108,15 +108,47 @@ static struct nf_hook_ops ipv4_defrag_ops[] = {
},
};
+static int ipv4_defrag_net_init(struct net *net)
+{
+ int err;
+
+ net->nf.ipv4_defrag_ops =
+ kmemdup(ipv4_defrag_ops, sizeof(ipv4_defrag_ops), GFP_KERNEL);
+ if (net->nf.ipv4_defrag_ops == NULL)
+ return -ENOMEM;
+
+ err = nf_register_hooks(net, net->nf.ipv4_defrag_ops,
+ ARRAY_SIZE(ipv4_defrag_ops));
+ if (err < 0)
+ goto err1;
+
+ return 0;
+err1:
+ kfree(net->nf.ipv4_defrag_ops);
+
+ return err;
+}
+
+static void ipv4_defrag_net_exit(struct net *net)
+{
+ nf_unregister_hooks(net->nf.ipv4_defrag_ops,
+ ARRAY_SIZE(ipv4_defrag_ops));
+ kfree(net->nf.ipv4_defrag_ops);
+}
+
+static struct pernet_operations ipv4_defrag_net_ops = {
+ .init = ipv4_defrag_net_init,
+ .exit = ipv4_defrag_net_exit,
+};
+
static int __init nf_defrag_init(void)
{
- return nf_register_hooks(&init_net, ipv4_defrag_ops,
- ARRAY_SIZE(ipv4_defrag_ops));
+ return register_pernet_subsys(&ipv4_defrag_net_ops);
}
static void __exit nf_defrag_fini(void)
{
- nf_unregister_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));
+ unregister_pernet_subsys(&ipv4_defrag_net_ops);
}
void nf_defrag_ipv4_enable(void)
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
index 7bc330f..2745f9c 100644
--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
+++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
@@ -99,6 +99,39 @@ static struct nf_hook_ops ipv6_defrag_ops[] = {
},
};
+static int ipv6_defrag_net_init(struct net *net)
+{
+ int err;
+
+ net->nf.ipv6_defrag_ops =
+ kmemdup(ipv6_defrag_ops, sizeof(ipv6_defrag_ops), GFP_KERNEL);
+ if (net->nf.ipv6_defrag_ops == NULL)
+ return -ENOMEM;
+
+ err = nf_register_hooks(net, net->nf.ipv6_defrag_ops,
+ ARRAY_SIZE(ipv6_defrag_ops));
+ if (err < 0)
+ goto err1;
+
+ return 0;
+err1:
+ kfree(net->nf.ipv6_defrag_ops);
+
+ return err;
+}
+
+static void ipv6_defrag_net_exit(struct net *net)
+{
+ nf_unregister_hooks(net->nf.ipv6_defrag_ops,
+ ARRAY_SIZE(ipv6_defrag_ops));
+ kfree(net->nf.ipv6_defrag_ops);
+}
+
+static struct pernet_operations ipv6_defrag_net_ops = {
+ .init = ipv6_defrag_net_init,
+ .exit = ipv6_defrag_net_exit,
+};
+
static int __init nf_defrag_init(void)
{
int ret = 0;
@@ -108,10 +141,10 @@ static int __init nf_defrag_init(void)
pr_err("nf_defrag_ipv6: can't initialize frag6.\n");
return ret;
}
- ret = nf_register_hooks(&init_net, ipv6_defrag_ops,
- ARRAY_SIZE(ipv6_defrag_ops));
+
+ ret = register_pernet_subsys(&ipv6_defrag_net_ops);
if (ret < 0) {
- pr_err("nf_defrag_ipv6: can't register hooks\n");
+ pr_err("nf_defrag_ipv6: can't register pernet\n");
goto cleanup_frag6;
}
return ret;
@@ -124,7 +157,7 @@ cleanup_frag6:
static void __exit nf_defrag_fini(void)
{
- nf_unregister_hooks(ipv6_defrag_ops, ARRAY_SIZE(ipv6_defrag_ops));
+ unregister_pernet_subsys(&ipv6_defrag_net_ops);
nf_ct_frag6_cleanup();
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH RFC 11/15] ipvs: adapt it to pernet hooks
2015-06-15 15:46 [PATCH RFC 00/15] Netfilter pernet hook support Pablo Neira Ayuso
` (9 preceding siblings ...)
2015-06-15 15:46 ` [PATCH RFC 10/15] netfilter: defrag: add pernet hook support Pablo Neira Ayuso
@ 2015-06-15 15:46 ` Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 12/15] netfilter: ebtables: adapt the filter and nat table " Pablo Neira Ayuso
` (3 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2015-06-15 15:46 UTC (permalink / raw
To: netfilter-devel; +Cc: ebiederm, aschultz, kaber
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/ip_vs.h | 3 +++
net/netfilter/ipvs/ip_vs_core.c | 42 +++++++++++++++++++++++++++++----------
2 files changed, 35 insertions(+), 10 deletions(-)
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 4e3731e..406dbe3 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -850,6 +850,9 @@ struct ipvs_master_sync_state {
struct netns_ipvs {
int gen; /* Generation */
int enable; /* enable like nf_hooks do */
+
+ struct nf_hook_ops *ip_vs_ops;
+
/* Hash table: for real service lookups */
#define IP_VS_RTAB_BITS 4
#define IP_VS_RTAB_SIZE (1 << IP_VS_RTAB_BITS)
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 2751d5a..65cd930 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -2039,9 +2039,39 @@ static void __net_exit __ip_vs_cleanup(struct net *net)
net->ipvs = NULL;
}
+static int ip_vs_dev_init(struct net *net)
+{
+ struct netns_ipvs *ipvs_net = net_ipvs(net);
+ int err;
+
+ ipvs_net->ip_vs_ops =
+ kmemdup(ip_vs_ops, sizeof(ip_vs_ops), GFP_KERNEL);
+ if (ipvs_net->ip_vs_ops == NULL) {
+ err = -ENOMEM;
+ goto err1;
+ }
+
+ err = nf_register_hooks(net, ipvs_net->ip_vs_ops,
+ ARRAY_SIZE(ip_vs_ops));
+ if (err < 0) {
+ pr_err("can't register hooks.\n");
+ goto err2;
+ }
+
+ return 0;
+err2:
+ kfree(ipvs_net->ip_vs_ops);
+err1:
+ return err;
+}
+
static void __net_exit __ip_vs_dev_cleanup(struct net *net)
{
+ struct netns_ipvs *ipvs_net = net_ipvs(net);
+
EnterFunction(2);
+ nf_unregister_hooks(ipvs_net->ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
+ kfree(ipvs_net->ip_vs_ops);
net_ipvs(net)->enable = 0; /* Disable packet reception */
smp_wmb();
ip_vs_sync_net_cleanup(net);
@@ -2056,6 +2086,7 @@ static struct pernet_operations ipvs_core_ops = {
};
static struct pernet_operations ipvs_core_dev_ops = {
+ .init = ip_vs_dev_init,
.exit = __ip_vs_dev_cleanup,
};
@@ -2088,24 +2119,16 @@ static int __init ip_vs_init(void)
if (ret < 0)
goto cleanup_sub;
- ret = nf_register_hooks(&init_net, ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
- if (ret < 0) {
- pr_err("can't register hooks.\n");
- goto cleanup_dev;
- }
-
ret = ip_vs_register_nl_ioctl();
if (ret < 0) {
pr_err("can't register netlink/ioctl.\n");
- goto cleanup_hooks;
+ goto cleanup_dev;
}
pr_info("ipvs loaded.\n");
return ret;
-cleanup_hooks:
- nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
cleanup_dev:
unregister_pernet_device(&ipvs_core_dev_ops);
cleanup_sub:
@@ -2122,7 +2145,6 @@ exit:
static void __exit ip_vs_cleanup(void)
{
ip_vs_unregister_nl_ioctl();
- nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
unregister_pernet_device(&ipvs_core_dev_ops);
unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
ip_vs_conn_cleanup();
--
1.7.10.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH RFC 12/15] netfilter: ebtables: adapt the filter and nat table to pernet hooks
2015-06-15 15:46 [PATCH RFC 00/15] Netfilter pernet hook support Pablo Neira Ayuso
` (10 preceding siblings ...)
2015-06-15 15:46 ` [PATCH RFC 11/15] ipvs: adapt it to pernet hooks Pablo Neira Ayuso
@ 2015-06-15 15:46 ` Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 13/15] netfilter: nf_tables: adapt it " Pablo Neira Ayuso
` (2 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2015-06-15 15:46 UTC (permalink / raw
To: netfilter-devel; +Cc: ebiederm, aschultz, kaber
This adapts the filter and nat tables to register the hooks for each
netnamespace.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netns/x_tables.h | 2 ++
net/bridge/netfilter/ebtable_filter.c | 42 +++++++++++++++++++++++----------
net/bridge/netfilter/ebtable_nat.c | 42 +++++++++++++++++++++++----------
3 files changed, 62 insertions(+), 24 deletions(-)
diff --git a/include/net/netns/x_tables.h b/include/net/netns/x_tables.h
index c8a7681..831af42 100644
--- a/include/net/netns/x_tables.h
+++ b/include/net/netns/x_tables.h
@@ -14,7 +14,9 @@ struct netns_xt {
defined(CONFIG_BRIDGE_NF_EBTABLES_MODULE)
struct ebt_table *broute_table;
struct ebt_table *frame_filter;
+ struct nf_hook_ops *frame_filter_ops;
struct ebt_table *frame_nat;
+ struct nf_hook_ops *frame_nat_ops;
#endif
};
#endif
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index 9a5a798..2ee938c 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -98,12 +98,40 @@ static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
static int __net_init frame_filter_net_init(struct net *net)
{
+ int err;
+
net->xt.frame_filter = ebt_register_table(net, &frame_filter);
- return PTR_ERR_OR_ZERO(net->xt.frame_filter);
+ if (IS_ERR(net->xt.frame_filter)) {
+ err = PTR_ERR(net->xt.frame_filter);
+ goto err1;
+ }
+
+ net->xt.frame_filter_ops =
+ kmemdup(ebt_ops_filter, sizeof(ebt_ops_filter), GFP_KERNEL);
+ if (net->xt.frame_filter_ops == NULL) {
+ err = -ENOMEM;
+ goto err2;
+ }
+
+ err = nf_register_hooks(net, net->xt.frame_filter_ops,
+ ARRAY_SIZE(ebt_ops_filter));
+ if (err < 0)
+ goto err3;
+
+ return 0;
+err3:
+ kfree(net->xt.frame_filter_ops);
+err2:
+ ebt_unregister_table(net, net->xt.frame_filter);
+err1:
+ return err;
}
static void __net_exit frame_filter_net_exit(struct net *net)
{
+ nf_unregister_hooks(net->xt.frame_filter_ops,
+ ARRAY_SIZE(ebt_ops_filter));
+ kfree(net->xt.frame_filter_ops);
ebt_unregister_table(net, net->xt.frame_filter);
}
@@ -114,21 +142,11 @@ static struct pernet_operations frame_filter_net_ops = {
static int __init ebtable_filter_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&frame_filter_net_ops);
- if (ret < 0)
- return ret;
- ret = nf_register_hooks(&init_net, ebt_ops_filter,
- ARRAY_SIZE(ebt_ops_filter));
- if (ret < 0)
- unregister_pernet_subsys(&frame_filter_net_ops);
- return ret;
+ return register_pernet_subsys(&frame_filter_net_ops);
}
static void __exit ebtable_filter_fini(void)
{
- nf_unregister_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
unregister_pernet_subsys(&frame_filter_net_ops);
}
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index 3d2759d..a787126 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -98,12 +98,40 @@ static struct nf_hook_ops ebt_ops_nat[] __read_mostly = {
static int __net_init frame_nat_net_init(struct net *net)
{
+ int err;
+
net->xt.frame_nat = ebt_register_table(net, &frame_nat);
- return PTR_ERR_OR_ZERO(net->xt.frame_nat);
+ if (IS_ERR(net->xt.frame_nat)) {
+ err = PTR_ERR(net->xt.frame_nat);
+ goto err1;
+ }
+
+ net->xt.frame_nat_ops =
+ kmemdup(ebt_ops_nat, sizeof(ebt_ops_nat), GFP_KERNEL);
+ if (net->xt.frame_nat_ops == NULL) {
+ err = -ENOMEM;
+ goto err2;
+ }
+
+ err = nf_register_hooks(net, net->xt.frame_nat_ops,
+ ARRAY_SIZE(ebt_ops_nat));
+ if (err < 0)
+ goto err3;
+
+ return 0;
+err3:
+ kfree(net->xt.frame_nat_ops);
+err2:
+ ebt_unregister_table(net, net->xt.frame_nat);
+err1:
+ return err;
}
static void __net_exit frame_nat_net_exit(struct net *net)
{
+ nf_unregister_hooks(net->xt.frame_nat_ops,
+ ARRAY_SIZE(ebt_ops_nat));
+ kfree(net->xt.frame_nat_ops);
ebt_unregister_table(net, net->xt.frame_nat);
}
@@ -114,21 +142,11 @@ static struct pernet_operations frame_nat_net_ops = {
static int __init ebtable_nat_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&frame_nat_net_ops);
- if (ret < 0)
- return ret;
- ret = nf_register_hooks(&init_net, ebt_ops_nat,
- ARRAY_SIZE(ebt_ops_nat));
- if (ret < 0)
- unregister_pernet_subsys(&frame_nat_net_ops);
- return ret;
+ return register_pernet_subsys(&frame_nat_net_ops);
}
static void __exit ebtable_nat_fini(void)
{
- nf_unregister_hooks(ebt_ops_nat, ARRAY_SIZE(ebt_ops_nat));
unregister_pernet_subsys(&frame_nat_net_ops);
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH RFC 13/15] netfilter: nf_tables: adapt it to pernet hooks
2015-06-15 15:46 [PATCH RFC 00/15] Netfilter pernet hook support Pablo Neira Ayuso
` (11 preceding siblings ...)
2015-06-15 15:46 ` [PATCH RFC 12/15] netfilter: ebtables: adapt the filter and nat table " Pablo Neira Ayuso
@ 2015-06-15 15:46 ` Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 14/15] security: " Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 15/15] netfilter: bridge: " Pablo Neira Ayuso
14 siblings, 0 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2015-06-15 15:46 UTC (permalink / raw
To: netfilter-devel; +Cc: ebiederm, aschultz, kaber
Since pernet hooks, we need to register the hook for each netnamespace space.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_tables_api.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index a8d4044..48c4844 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -556,7 +556,7 @@ err:
return err;
}
-static int nf_tables_table_enable(const struct nft_af_info *afi,
+static int nf_tables_table_enable(const struct nft_ctx *ctx,
struct nft_table *table)
{
struct nft_chain *chain;
@@ -566,8 +566,8 @@ static int nf_tables_table_enable(const struct nft_af_info *afi,
if (!(chain->flags & NFT_BASE_CHAIN))
continue;
- err = nf_register_hooks(&init_net, nft_base_chain(chain)->ops,
- afi->nops);
+ err = nf_register_hooks(ctx->net, nft_base_chain(chain)->ops,
+ ctx->afi->nops);
if (err < 0)
goto err;
@@ -582,7 +582,7 @@ err:
if (i-- <= 0)
break;
- nf_unregister_hooks(nft_base_chain(chain)->ops, afi->nops);
+ nf_unregister_hooks(nft_base_chain(chain)->ops, ctx->afi->nops);
}
return err;
}
@@ -630,7 +630,7 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
nft_trans_table_enable(trans) = false;
} else if (!(flags & NFT_TABLE_F_DORMANT) &&
ctx->table->flags & NFT_TABLE_F_DORMANT) {
- ret = nf_tables_table_enable(ctx->afi, ctx->table);
+ ret = nf_tables_table_enable(ctx, ctx->table);
if (ret >= 0) {
ctx->table->flags &= ~NFT_TABLE_F_DORMANT;
nft_trans_table_enable(trans) = true;
@@ -1419,7 +1419,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
if (!(table->flags & NFT_TABLE_F_DORMANT) &&
chain->flags & NFT_BASE_CHAIN) {
- err = nf_register_hooks(&init_net, nft_base_chain(chain)->ops,
+ err = nf_register_hooks(net, nft_base_chain(chain)->ops,
afi->nops);
if (err < 0)
goto err1;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH RFC 14/15] security: adapt it to pernet hooks
2015-06-15 15:46 [PATCH RFC 00/15] Netfilter pernet hook support Pablo Neira Ayuso
` (12 preceding siblings ...)
2015-06-15 15:46 ` [PATCH RFC 13/15] netfilter: nf_tables: adapt it " Pablo Neira Ayuso
@ 2015-06-15 15:46 ` Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 15/15] netfilter: bridge: " Pablo Neira Ayuso
14 siblings, 0 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2015-06-15 15:46 UTC (permalink / raw
To: netfilter-devel; +Cc: ebiederm, aschultz, kaber
Since pernet hooks, we need to register the hook for each netnamespace space.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netns/netfilter.h | 3 +++
security/selinux/hooks.c | 43 +++++++++++++++++++++++++++++++++++------
2 files changed, 40 insertions(+), 6 deletions(-)
diff --git a/include/net/netns/netfilter.h b/include/net/netns/netfilter.h
index f2b513d..89925e3 100644
--- a/include/net/netns/netfilter.h
+++ b/include/net/netns/netfilter.h
@@ -21,5 +21,8 @@ struct netns_nf {
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
struct nf_hook_ops *ipv6_defrag_ops;
#endif
+#ifdef CONFIG_SECURITY
+ struct nf_hook_ops *selinux_ops;
+#endif
};
#endif
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 7246654..c10a5b1 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6147,6 +6147,40 @@ static struct nf_hook_ops selinux_nf_ops[] = {
#endif /* IPV6 */
};
+static int selinux_net_init(struct net *net)
+{
+ int err;
+
+ net->nf.selinux_ops =
+ kmemdup(selinux_nf_ops, sizeof(selinux_nf_ops), GFP_KERNEL);
+ if (net->nf.selinux_ops == NULL) {
+ err = -ENOMEM;
+ goto err1;
+ }
+
+ err = nf_register_hooks(net, net->nf.selinux_ops,
+ ARRAY_SIZE(selinux_nf_ops));
+ if (err < 0)
+ goto err2;
+
+ return 0;
+err2:
+ kfree(net->nf.selinux_ops);
+err1:
+ return err;
+}
+
+static void selinux_net_exit(struct net *net)
+{
+ nf_unregister_hooks(net->nf.selinux_ops, ARRAY_SIZE(selinux_nf_ops));
+ kfree(net->nf.selinux_ops);
+}
+
+static struct pernet_operations selinux_net_ops = {
+ .init = selinux_net_init,
+ .exit = selinux_net_exit,
+};
+
static int __init selinux_nf_ip_init(void)
{
int err;
@@ -6156,9 +6190,8 @@ static int __init selinux_nf_ip_init(void)
printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
- err = nf_register_hooks(&init_net, selinux_nf_ops,
- ARRAY_SIZE(selinux_nf_ops));
- if (err)
+ err = register_pernet_subsys(&selinux_net_ops);
+ if (err < 0)
panic("SELinux: nf_register_hooks: error %d\n", err);
return 0;
@@ -6170,9 +6203,7 @@ __initcall(selinux_nf_ip_init);
static void selinux_nf_ip_exit(void)
{
printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
-
- nf_unregister_hooks(&init_net, selinux_nf_ops,
- ARRAY_SIZE(selinux_nf_ops));
+ unregister_pernet_subsys(&selinux_net_ops);
}
#endif
--
1.7.10.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH RFC 15/15] netfilter: bridge: adapt it to pernet hooks
2015-06-15 15:46 [PATCH RFC 00/15] Netfilter pernet hook support Pablo Neira Ayuso
` (13 preceding siblings ...)
2015-06-15 15:46 ` [PATCH RFC 14/15] security: " Pablo Neira Ayuso
@ 2015-06-15 15:46 ` Pablo Neira Ayuso
14 siblings, 0 replies; 17+ messages in thread
From: Pablo Neira Ayuso @ 2015-06-15 15:46 UTC (permalink / raw
To: netfilter-devel; +Cc: ebiederm, aschultz, kaber
This patch replaces the global brnf_call_* variables to make them per
netnamespace. Moreover, this registers hooks at pernet level too.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netfilter/br_netfilter.h | 52 +++++++++++
include/net/netns/netfilter.h | 13 +++
net/bridge/br_netfilter.c | 171 +++++++++++++++++++++-------------
3 files changed, 169 insertions(+), 67 deletions(-)
diff --git a/include/net/netfilter/br_netfilter.h b/include/net/netfilter/br_netfilter.h
index 2aa6048..26b3591 100644
--- a/include/net/netfilter/br_netfilter.h
+++ b/include/net/netfilter/br_netfilter.h
@@ -3,4 +3,56 @@
void br_netfilter_enable(void);
+#ifdef CONFIG_SYSCTL
+static inline bool brnf_call_iptables(struct net_device *dev)
+{
+ return dev_net(dev)->nf.brnf_call_iptables;
+}
+static inline bool brnf_call_ip6tables(struct net_device *dev)
+{
+ return dev_net(dev)->nf.brnf_call_ip6tables;
+}
+static inline bool brnf_call_arptables(struct net_device *dev)
+{
+ return dev_net(dev)->nf.brnf_call_arptables;
+}
+static inline bool brnf_filter_vlan_tagged(struct net_device *dev)
+{
+ return dev_net(dev)->nf.brnf_filter_vlan_tagged;
+}
+static inline bool brnf_filter_pppoe_tagged(struct net_device *dev)
+{
+ return dev_net(dev)->nf.brnf_filter_pppoe_tagged;
+}
+static inline bool brnf_pass_vlan_indev(struct net_device *dev)
+{
+ return dev_net(dev)->nf.brnf_pass_vlan_indev;
+}
+#else
+static inline bool brnf_call_iptables(void)
+{
+ return true;
+}
+static inline bool brnf_call_ip6tables(void)
+{
+ return true;
+}
+static inline bool brnf_call_arptables(void)
+{
+ return true;
+}
+static inline bool brnf_filter_vlan_tagged(void)
+{
+ return false;
+}
+static inline bool brnf_filter_pppoe_tagged(void)
+{
+ return false;
+}
+static inline bool brnf_pass_vlan_indev(void)
+{
+ return false;
+}
+#endif /* CONFIG_SYSCTL */
+
#endif /* _BR_NETFILTER_H_ */
diff --git a/include/net/netns/netfilter.h b/include/net/netns/netfilter.h
index 89925e3..604b8f0 100644
--- a/include/net/netns/netfilter.h
+++ b/include/net/netns/netfilter.h
@@ -24,5 +24,18 @@ struct netns_nf {
#ifdef CONFIG_SECURITY
struct nf_hook_ops *selinux_ops;
#endif
+#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+#ifdef CONFIG_SYSCTL
+ struct ctl_table *brnf_table;
+ struct ctl_table_header *brnf_sysctl_header;
+ int brnf_call_iptables;
+ int brnf_call_ip6tables;
+ int brnf_call_arptables;
+ int brnf_filter_vlan_tagged;
+ int brnf_filter_pppoe_tagged;
+ int brnf_pass_vlan_indev;
+#endif
+ struct nf_hook_ops *brnf_ops;
+#endif
};
#endif
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index af14ef1..af47cfe 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -44,23 +44,6 @@
#include <linux/sysctl.h>
#endif
-#ifdef CONFIG_SYSCTL
-static struct ctl_table_header *brnf_sysctl_header;
-static int brnf_call_iptables __read_mostly = 1;
-static int brnf_call_ip6tables __read_mostly = 1;
-static int brnf_call_arptables __read_mostly = 1;
-static int brnf_filter_vlan_tagged __read_mostly = 0;
-static int brnf_filter_pppoe_tagged __read_mostly = 0;
-static int brnf_pass_vlan_indev __read_mostly = 0;
-#else
-#define brnf_call_iptables 1
-#define brnf_call_ip6tables 1
-#define brnf_call_arptables 1
-#define brnf_filter_vlan_tagged 0
-#define brnf_filter_pppoe_tagged 0
-#define brnf_pass_vlan_indev 0
-#endif
-
#define IS_IP(skb) \
(!skb_vlan_tag_present(skb) && skb->protocol == htons(ETH_P_IP))
@@ -80,17 +63,17 @@ static inline __be16 vlan_proto(const struct sk_buff *skb)
return 0;
}
-#define IS_VLAN_IP(skb) \
+#define IS_VLAN_IP(skb, dev) \
(vlan_proto(skb) == htons(ETH_P_IP) && \
- brnf_filter_vlan_tagged)
+ brnf_filter_vlan_tagged(dev))
-#define IS_VLAN_IPV6(skb) \
+#define IS_VLAN_IPV6(skb, dev) \
(vlan_proto(skb) == htons(ETH_P_IPV6) && \
- brnf_filter_vlan_tagged)
+ brnf_filter_vlan_tagged(dev))
-#define IS_VLAN_ARP(skb) \
+#define IS_VLAN_ARP(skb, dev) \
(vlan_proto(skb) == htons(ETH_P_ARP) && \
- brnf_filter_vlan_tagged)
+ brnf_filter_vlan_tagged(dev))
static inline __be16 pppoe_proto(const struct sk_buff *skb)
{
@@ -98,15 +81,15 @@ static inline __be16 pppoe_proto(const struct sk_buff *skb)
sizeof(struct pppoe_hdr)));
}
-#define IS_PPPOE_IP(skb) \
+#define IS_PPPOE_IP(skb, dev) \
(skb->protocol == htons(ETH_P_PPP_SES) && \
pppoe_proto(skb) == htons(PPP_IP) && \
- brnf_filter_pppoe_tagged)
+ brnf_filter_pppoe_tagged(dev))
-#define IS_PPPOE_IPV6(skb) \
+#define IS_PPPOE_IPV6(skb, dev) \
(skb->protocol == htons(ETH_P_PPP_SES) && \
pppoe_proto(skb) == htons(PPP_IPV6) && \
- brnf_filter_pppoe_tagged)
+ brnf_filter_pppoe_tagged(dev))
/* largest possible L2 header, see br_nf_dev_queue_xmit() */
#define NF_BRIDGE_MAX_MAC_HEADER_LENGTH (PPPOE_SES_HLEN + ETH_HLEN)
@@ -626,7 +609,8 @@ static struct net_device *brnf_get_logical_dev(struct sk_buff *skb, const struct
struct net_device *vlan, *br;
br = bridge_parent(dev);
- if (brnf_pass_vlan_indev == 0 || !skb_vlan_tag_present(skb))
+ if (dev_net(dev)->nf.brnf_pass_vlan_indev == 0 ||
+ !skb_vlan_tag_present(skb))
return br;
vlan = __vlan_find_dev_deep_rcu(br, skb->vlan_proto,
@@ -711,18 +695,22 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops,
return NF_DROP;
br = p->br;
- if (IS_IPV6(skb) || IS_VLAN_IPV6(skb) || IS_PPPOE_IPV6(skb)) {
- if (!brnf_call_ip6tables && !br->nf_call_ip6tables)
+ if (IS_IPV6(skb) ||
+ IS_VLAN_IPV6(skb, state->in) ||
+ IS_PPPOE_IPV6(skb, state->in)) {
+ if (!brnf_call_ip6tables(state->in) && !br->nf_call_ip6tables)
return NF_ACCEPT;
nf_bridge_pull_encap_header_rcsum(skb);
return br_nf_pre_routing_ipv6(ops, skb, state);
}
- if (!brnf_call_iptables && !br->nf_call_iptables)
+ if (!brnf_call_iptables(state->in) && !br->nf_call_iptables)
return NF_ACCEPT;
- if (!IS_IP(skb) && !IS_VLAN_IP(skb) && !IS_PPPOE_IP(skb))
+ if (!IS_IP(skb) &&
+ !IS_VLAN_IP(skb, state->in) &&
+ !IS_PPPOE_IP(skb, state->in))
return NF_ACCEPT;
nf_bridge_pull_encap_header_rcsum(skb);
@@ -770,8 +758,7 @@ static int br_nf_forward_finish(struct sock *sk, struct sk_buff *skb)
struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
struct net_device *in;
- if (!IS_ARP(skb) && !IS_VLAN_ARP(skb)) {
-
+ if (!IS_ARP(skb) && !IS_VLAN_ARP(skb, skb->dev)) {
if (skb->protocol == htons(ETH_P_IP))
nf_bridge->frag_max_size = IPCB(skb)->frag_max_size;
@@ -824,9 +811,13 @@ static unsigned int br_nf_forward_ip(const struct nf_hook_ops *ops,
if (!parent)
return NF_DROP;
- if (IS_IP(skb) || IS_VLAN_IP(skb) || IS_PPPOE_IP(skb))
+ if (IS_IP(skb) ||
+ IS_VLAN_IP(skb, state->out) ||
+ IS_PPPOE_IP(skb, state->out))
pf = NFPROTO_IPV4;
- else if (IS_IPV6(skb) || IS_VLAN_IPV6(skb) || IS_PPPOE_IPV6(skb))
+ else if (IS_IPV6(skb) ||
+ IS_VLAN_IPV6(skb, state->out) ||
+ IS_PPPOE_IPV6(skb, state->out))
pf = NFPROTO_IPV6;
else
return NF_ACCEPT;
@@ -876,17 +867,17 @@ static unsigned int br_nf_forward_arp(const struct nf_hook_ops *ops,
return NF_ACCEPT;
br = p->br;
- if (!brnf_call_arptables && !br->nf_call_arptables)
+ if (!brnf_call_arptables(state->out) && !br->nf_call_arptables)
return NF_ACCEPT;
if (!IS_ARP(skb)) {
- if (!IS_VLAN_ARP(skb))
+ if (!IS_VLAN_ARP(skb, state->out))
return NF_ACCEPT;
nf_bridge_pull_encap_header(skb);
}
if (arp_hdr(skb)->ar_pln != 4) {
- if (IS_VLAN_ARP(skb))
+ if (IS_VLAN_ARP(skb, state->out))
nf_bridge_push_encap_header(skb);
return NF_ACCEPT;
}
@@ -1040,9 +1031,13 @@ static unsigned int br_nf_post_routing(const struct nf_hook_ops *ops,
if (!realoutdev)
return NF_DROP;
- if (IS_IP(skb) || IS_VLAN_IP(skb) || IS_PPPOE_IP(skb))
+ if (IS_IP(skb) ||
+ IS_VLAN_IP(skb, state->out) ||
+ IS_PPPOE_IP(skb, state->out))
pf = NFPROTO_IPV4;
- else if (IS_IPV6(skb) || IS_VLAN_IPV6(skb) || IS_PPPOE_IPV6(skb))
+ else if (IS_IPV6(skb) ||
+ IS_VLAN_IPV6(skb, state->out) ||
+ IS_PPPOE_IPV6(skb, state->out))
pf = NFPROTO_IPV6;
else
return NF_ACCEPT;
@@ -1196,44 +1191,38 @@ int brnf_sysctl_call_tables(struct ctl_table *ctl, int write,
}
static struct ctl_table brnf_table[] = {
- {
+ [0] = {
.procname = "bridge-nf-call-arptables",
- .data = &brnf_call_arptables,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = brnf_sysctl_call_tables,
},
- {
+ [1] = {
.procname = "bridge-nf-call-iptables",
- .data = &brnf_call_iptables,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = brnf_sysctl_call_tables,
},
- {
+ [2] = {
.procname = "bridge-nf-call-ip6tables",
- .data = &brnf_call_ip6tables,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = brnf_sysctl_call_tables,
},
- {
+ [3] = {
.procname = "bridge-nf-filter-vlan-tagged",
- .data = &brnf_filter_vlan_tagged,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = brnf_sysctl_call_tables,
},
- {
+ [4] = {
.procname = "bridge-nf-filter-pppoe-tagged",
- .data = &brnf_filter_pppoe_tagged,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = brnf_sysctl_call_tables,
},
- {
+ [5] = {
.procname = "bridge-nf-pass-vlan-input-dev",
- .data = &brnf_pass_vlan_indev,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = brnf_sysctl_call_tables,
@@ -1242,23 +1231,75 @@ static struct ctl_table brnf_table[] = {
};
#endif
+static int __net_init br_nf_net_init(struct net *net)
+{
+ int err = -ENOMEM;
+#ifdef CONFIG_SYSCTL
+ struct ctl_table *brnf_table_net;
+
+ net->nf.brnf_call_arptables = 1;
+ net->nf.brnf_call_iptables = 1;
+ net->nf.brnf_call_ip6tables = 1;
+
+ brnf_table_net = kmemdup(brnf_table, sizeof(brnf_table), GFP_KERNEL);
+ if (brnf_table_net == NULL)
+ return -ENOMEM;
+
+ net->nf.brnf_table[0].data = &net->nf.brnf_call_arptables;
+ net->nf.brnf_table[1].data = &net->nf.brnf_call_iptables;
+ net->nf.brnf_table[2].data = &net->nf.brnf_call_ip6tables;
+ net->nf.brnf_table[3].data = &net->nf.brnf_filter_vlan_tagged;
+ net->nf.brnf_table[4].data = &net->nf.brnf_filter_pppoe_tagged;
+ net->nf.brnf_table[5].data = &net->nf.brnf_pass_vlan_indev;
+
+ net->nf.brnf_sysctl_header =
+ register_net_sysctl(net, "net/bridge", brnf_table_net);
+ if (net->nf.brnf_sysctl_header == NULL)
+ goto err1;
+#endif
+
+ net->nf.brnf_ops = kmemdup(br_nf_ops, sizeof(br_nf_ops), GFP_KERNEL);
+ if (net->nf.brnf_ops == NULL)
+ goto err2;
+
+ err = nf_register_hooks(net, net->nf.brnf_ops, ARRAY_SIZE(br_nf_ops));
+ if (err < 0)
+ goto err3;
+
+ return 0;
+err3:
+ kfree(net->nf.brnf_ops);
+err2:
+ unregister_net_sysctl_table(net->nf.brnf_sysctl_header);
+#ifdef CONFIG_SYSCTL
+err1:
+ kfree(brnf_table_net);
+#endif
+ return err;
+}
+
+static void __net_exit br_nf_net_exit(struct net *net)
+{
+#ifdef CONFIG_SYSCTL
+ unregister_net_sysctl_table(net->nf.brnf_sysctl_header);
+#endif
+ nf_unregister_hooks(net->nf.brnf_ops, ARRAY_SIZE(br_nf_ops));
+ kfree(net->nf.brnf_ops);
+}
+
+static struct pernet_operations br_nf_net_ops = {
+ .init = br_nf_net_init,
+ .exit = br_nf_net_exit,
+};
+
static int __init br_netfilter_init(void)
{
int ret;
- ret = nf_register_hooks(&init_net, br_nf_ops, ARRAY_SIZE(br_nf_ops));
+ ret = register_pernet_subsys(&br_nf_net_ops);
if (ret < 0)
return ret;
-#ifdef CONFIG_SYSCTL
- brnf_sysctl_header = register_net_sysctl(&init_net, "net/bridge", brnf_table);
- if (brnf_sysctl_header == NULL) {
- printk(KERN_WARNING
- "br_netfilter: can't register to sysctl.\n");
- nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
- return -ENOMEM;
- }
-#endif
RCU_INIT_POINTER(nf_br_ops, &br_ops);
printk(KERN_NOTICE "Bridge firewalling registered\n");
return 0;
@@ -1267,10 +1308,6 @@ static int __init br_netfilter_init(void)
static void __exit br_netfilter_fini(void)
{
RCU_INIT_POINTER(nf_br_ops, NULL);
- nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
-#ifdef CONFIG_SYSCTL
- unregister_net_sysctl_table(brnf_sysctl_header);
-#endif
}
module_init(br_netfilter_init);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH RFC 04/15] netfilter: add pernet hook support
2015-06-15 15:46 ` [PATCH RFC 04/15] netfilter: add pernet hook support Pablo Neira Ayuso
@ 2015-06-16 1:01 ` Eric W. Biederman
0 siblings, 0 replies; 17+ messages in thread
From: Eric W. Biederman @ 2015-06-16 1:01 UTC (permalink / raw
To: Pablo Neira Ayuso; +Cc: netfilter-devel, aschultz, kaber
Pablo Neira Ayuso <pablo@netfilter.org> writes:
> This patch modifies the nf_register_hook() and nf_register_hooks() interfaces
> to allow to register hooks at a pernet level.
>
> This starts using init_net for all the existing callers though, so the full
> conversion of existing netfilter hook clients to comes in follow up
> patches.
There is one issue with the approach this takes to per net network
namespace hooks.
nf_unregister_hook calls syncrhonize_net().
Which depending on which netfilter modules are loaded is going
to result in a nasty reduction in connections per second of vsftp,
because of the serialized nature of network namespace cleanup.
That should be something we can solve on top of the patches,
but I want to bring it up now so that other people are aware of it.
Eric
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2015-06-16 1:06 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-06-15 15:46 [PATCH RFC 00/15] Netfilter pernet hook support Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 01/15] net: include missing headers in net/net_namespace.h Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 02/15] netfilter: use forward declaration instead of including linux/proc_fs.h Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 03/15] netfilter: don't pull include/linux/netfilter.h from netns headers Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 04/15] netfilter: add pernet hook support Pablo Neira Ayuso
2015-06-16 1:01 ` Eric W. Biederman
2015-06-15 15:46 ` [PATCH RFC 05/15] netfilter: ipt_CLUSTERIP: adapt it to support pernet hooks Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 06/15] netfilter: x_tables: adapt xt_hook_link() " Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 07/15] netfilter: x_tables: adapt tables to " Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 08/15] netfilter: nf_conntrack: adapt IPv4 and IPv6 trackers " Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 09/15] netfilter: synproxy: adapt IPv4 and IPv6 targets " Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 10/15] netfilter: defrag: add pernet hook support Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 11/15] ipvs: adapt it to pernet hooks Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 12/15] netfilter: ebtables: adapt the filter and nat table " Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 13/15] netfilter: nf_tables: adapt it " Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 14/15] security: " Pablo Neira Ayuso
2015-06-15 15:46 ` [PATCH RFC 15/15] netfilter: bridge: " Pablo Neira Ayuso
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.