* [PATCH nf-next v2 01/10] netfilter: make /proc/net/netfilter pernet
@ 2013-03-25 9:50 Gao feng
2013-03-25 9:50 ` [PATCH nf-next v2 02/10] netfilter: nf_log: prepar net namespace support for nf_log Gao feng
` (9 more replies)
0 siblings, 10 replies; 24+ messages in thread
From: Gao feng @ 2013-03-25 9:50 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo, Gao feng
Now,only init net has directroy /proc/net/netfilter,
this patch makes this proc dentry pernet.
Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
---
include/net/net_namespace.h | 2 ++
include/net/netns/netfilter.h | 11 +++++++++++
net/netfilter/core.c | 36 +++++++++++++++++++++++++++++++-----
3 files changed, 44 insertions(+), 5 deletions(-)
create mode 100644 include/net/netns/netfilter.h
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index de644bc..b176978 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -17,6 +17,7 @@
#include <net/netns/ipv6.h>
#include <net/netns/sctp.h>
#include <net/netns/dccp.h>
+#include <net/netns/netfilter.h>
#include <net/netns/x_tables.h>
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
#include <net/netns/conntrack.h>
@@ -94,6 +95,7 @@ struct net {
struct netns_dccp dccp;
#endif
#ifdef CONFIG_NETFILTER
+ struct netns_nf nf;
struct netns_xt xt;
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
struct netns_ct ct;
diff --git a/include/net/netns/netfilter.h b/include/net/netns/netfilter.h
new file mode 100644
index 0000000..248ca1c
--- /dev/null
+++ b/include/net/netns/netfilter.h
@@ -0,0 +1,11 @@
+#ifndef __NETNS_NETFILTER_H
+#define __NETNS_NETFILTER_H
+
+#include <linux/proc_fs.h>
+
+struct netns_nf {
+#if defined CONFIG_PROC_FS
+ struct proc_dir_entry *proc_netfilter;
+#endif
+};
+#endif
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index a9c488b..e054799 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -281,6 +281,35 @@ struct proc_dir_entry *proc_net_netfilter;
EXPORT_SYMBOL(proc_net_netfilter);
#endif
+static int __net_init netfilter_net_init(struct net *net)
+{
+#ifdef CONFIG_PROC_FS
+ net->nf.proc_netfilter = proc_net_mkdir(net,
+ "netfilter",
+ net->proc_net);
+ if (net_eq(net, &init_net)) {
+ if (!net->nf.proc_netfilter)
+ panic("cannot create netfilter proc entry");
+ else
+ proc_net_netfilter = net->nf.proc_netfilter;
+ } else if (!net->nf.proc_netfilter) {
+ pr_err("cannot create netfilter proc entry");
+ return -ENOMEM;
+ }
+#endif
+ return 0;
+}
+
+static void __net_exit netfilter_net_exit(struct net *net)
+{
+ remove_proc_entry("netfilter", net->proc_net);
+}
+
+static struct pernet_operations netfilter_net_ops = {
+ .init = netfilter_net_init,
+ .exit = netfilter_net_exit,
+};
+
void __init netfilter_init(void)
{
int i, h;
@@ -289,11 +318,8 @@ void __init netfilter_init(void)
INIT_LIST_HEAD(&nf_hooks[i][h]);
}
-#ifdef CONFIG_PROC_FS
- proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net);
- if (!proc_net_netfilter)
- panic("cannot create netfilter proc entry");
-#endif
+ if (register_pernet_subsys(&netfilter_net_ops) < 0)
+ return;
if (netfilter_log_init() < 0)
panic("cannot initialize nf_log");
--
1.7.11.7
^ permalink raw reply related [flat|nested] 24+ messages in thread* [PATCH nf-next v2 02/10] netfilter: nf_log: prepar net namespace support for nf_log 2013-03-25 9:50 [PATCH nf-next v2 01/10] netfilter: make /proc/net/netfilter pernet Gao feng @ 2013-03-25 9:50 ` Gao feng 2013-04-05 18:30 ` Pablo Neira Ayuso 2013-03-25 9:50 ` [PATCH nf-next v2 03/10] netfilter: ebt_log: add net namespace support for ebt_log Gao feng ` (8 subsequent siblings) 9 siblings, 1 reply; 24+ messages in thread From: Gao feng @ 2013-03-25 9:50 UTC (permalink / raw) To: netfilter-devel; +Cc: pablo, Gao feng This patch adds netns support for nf_log,contains four major changes. 1,nf_log_register is split to two functions: nf_log_register and nf_log_set. The new nf_log_register is used only for register nf_logger, nf_log_set is used for setting pernet nf_loggers. Because the moudules that use the nf_log_register should be changed to use these new functions, and in order not to change the behavior. only allow to set the nf_loggers of init net. 2,Add net as a parameter of nf_log_bind_pf,only allow init net to bind the nflogger to the proto family. 3,Some l4proto such as tcp,udp... use nf_log_packet to log the invalid packets, we need pass proper netns to the nf_log_packet. Since other netns except init net has no nflogger binding to the proto, we only allow nf_log_packet handle the log request which comes from init net. 4,Make the sysctl net/netfilter/nf_log pernet. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- include/net/netfilter/nf_log.h | 14 +- include/net/netns/netfilter.h | 7 + net/bridge/netfilter/ebt_log.c | 7 +- net/bridge/netfilter/ebt_nflog.c | 5 +- net/ipv4/netfilter/ip_tables.c | 3 +- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 8 +- net/ipv6/netfilter/ip6_tables.c | 3 +- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 7 +- net/netfilter/nf_conntrack_helper.c | 2 +- net/netfilter/nf_conntrack_proto_dccp.c | 9 +- net/netfilter/nf_conntrack_proto_tcp.c | 18 +- net/netfilter/nf_conntrack_proto_udp.c | 6 +- net/netfilter/nf_conntrack_proto_udplite.c | 8 +- net/netfilter/nf_log.c | 223 ++++++++++++++++++------- net/netfilter/nfnetlink_log.c | 5 +- net/netfilter/xt_osf.c | 6 +- 16 files changed, 231 insertions(+), 100 deletions(-) diff --git a/include/net/netfilter/nf_log.h b/include/net/netfilter/nf_log.h index e991bd0..31f1fb9 100644 --- a/include/net/netfilter/nf_log.h +++ b/include/net/netfilter/nf_log.h @@ -49,12 +49,18 @@ struct nf_logger { int nf_log_register(u_int8_t pf, struct nf_logger *logger); void nf_log_unregister(struct nf_logger *logger); -int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger); -void nf_log_unbind_pf(u_int8_t pf); +void nf_log_set(struct net *net, u_int8_t pf, + const struct nf_logger *logger); +void nf_log_unset(struct net *net, const struct nf_logger *logger); + +int nf_log_bind_pf(struct net *net, u_int8_t pf, + const struct nf_logger *logger); +void nf_log_unbind_pf(struct net *net, u_int8_t pf); /* Calls the registered backend logging function */ -__printf(7, 8) -void nf_log_packet(u_int8_t pf, +__printf(8, 9) +void nf_log_packet(struct net *net, + u_int8_t pf, unsigned int hooknum, const struct sk_buff *skb, const struct net_device *in, diff --git a/include/net/netns/netfilter.h b/include/net/netns/netfilter.h index 248ca1c..8874002 100644 --- a/include/net/netns/netfilter.h +++ b/include/net/netns/netfilter.h @@ -2,10 +2,17 @@ #define __NETNS_NETFILTER_H #include <linux/proc_fs.h> +#include <linux/netfilter.h> + +struct nf_logger; struct netns_nf { #if defined CONFIG_PROC_FS struct proc_dir_entry *proc_netfilter; #endif + const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO]; +#ifdef CONFIG_SYSCTL + struct ctl_table_header *nf_log_dir_header; +#endif }; #endif diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 92de5e5..08e5ea5 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -176,17 +176,18 @@ ebt_log_tg(struct sk_buff *skb, const struct xt_action_param *par) { const struct ebt_log_info *info = par->targinfo; struct nf_loginfo li; + struct net *net = dev_net(par->in ? par->in : par->out); li.type = NF_LOG_TYPE_LOG; li.u.log.level = info->loglevel; li.u.log.logflags = info->bitmask; if (info->bitmask & EBT_LOG_NFLOG) - nf_log_packet(NFPROTO_BRIDGE, par->hooknum, skb, par->in, - par->out, &li, "%s", info->prefix); + nf_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb, + par->in, par->out, &li, "%s", info->prefix); else ebt_log_packet(NFPROTO_BRIDGE, par->hooknum, skb, par->in, - par->out, &li, info->prefix); + par->out, &li, info->prefix); return EBT_CONTINUE; } diff --git a/net/bridge/netfilter/ebt_nflog.c b/net/bridge/netfilter/ebt_nflog.c index 5be68bb..59ac795 100644 --- a/net/bridge/netfilter/ebt_nflog.c +++ b/net/bridge/netfilter/ebt_nflog.c @@ -24,14 +24,15 @@ ebt_nflog_tg(struct sk_buff *skb, const struct xt_action_param *par) { const struct ebt_nflog_info *info = par->targinfo; struct nf_loginfo li; + struct net *net = dev_net(par->in ? par->in : par->out); li.type = NF_LOG_TYPE_ULOG; li.u.ulog.copy_len = info->len; li.u.ulog.group = info->group; li.u.ulog.qthreshold = info->threshold; - nf_log_packet(PF_BRIDGE, par->hooknum, skb, par->in, par->out, - &li, "%s", info->prefix); + nf_log_packet(net, PF_BRIDGE, par->hooknum, skb, par->in, + par->out, &li, "%s", info->prefix); return EBT_CONTINUE; } diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 3efcf87..b371593 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -259,6 +259,7 @@ static void trace_packet(const struct sk_buff *skb, const char *hookname, *chainname, *comment; const struct ipt_entry *iter; unsigned int rulenum = 0; + struct net *net = dev_net(in ? in : out); table_base = private->entries[smp_processor_id()]; root = get_entry(table_base, private->hook_entry[hook]); @@ -271,7 +272,7 @@ static void trace_packet(const struct sk_buff *skb, &chainname, &comment, &rulenum) != 0) break; - nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo, + nf_log_packet(net, AF_INET, hook, skb, in, out, &trace_loginfo, "TRACE: %s:%s:%s:%u ", tablename, chainname, comment, rulenum); } diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 5241d99..c2cd63d 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -187,8 +187,8 @@ icmp_error(struct net *net, struct nf_conn *tmpl, icmph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_ih), &_ih); if (icmph == NULL) { if (LOG_INVALID(net, IPPROTO_ICMP)) - nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, - "nf_ct_icmp: short packet "); + nf_log_packet(net, PF_INET, 0, skb, NULL, NULL, + NULL, "nf_ct_icmp: short packet "); return -NF_ACCEPT; } @@ -196,7 +196,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl, if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && nf_ip_checksum(skb, hooknum, dataoff, 0)) { if (LOG_INVALID(net, IPPROTO_ICMP)) - nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, PF_INET, 0, skb, NULL, NULL, NULL, "nf_ct_icmp: bad HW ICMP checksum "); return -NF_ACCEPT; } @@ -209,7 +209,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl, */ if (icmph->type > NR_ICMP_TYPES) { if (LOG_INVALID(net, IPPROTO_ICMP)) - nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, PF_INET, 0, skb, NULL, NULL, NULL, "nf_ct_icmp: invalid ICMP type "); return -NF_ACCEPT; } diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 341b54a..8861b1e 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -284,6 +284,7 @@ static void trace_packet(const struct sk_buff *skb, const char *hookname, *chainname, *comment; const struct ip6t_entry *iter; unsigned int rulenum = 0; + struct net *net = dev_net(in ? in : out); table_base = private->entries[smp_processor_id()]; root = get_entry(table_base, private->hook_entry[hook]); @@ -296,7 +297,7 @@ static void trace_packet(const struct sk_buff *skb, &chainname, &comment, &rulenum) != 0) break; - nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo, + nf_log_packet(net, AF_INET6, hook, skb, in, out, &trace_loginfo, "TRACE: %s:%s:%s:%u ", tablename, chainname, comment, rulenum); } diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 24df3dd..b3807c5 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -131,7 +131,8 @@ static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, type + 128); nf_ct_dump_tuple_ipv6(&ct->tuplehash[0].tuple); if (LOG_INVALID(nf_ct_net(ct), IPPROTO_ICMPV6)) - nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, + nf_log_packet(nf_ct_net(ct), PF_INET6, 0, skb, NULL, + NULL, NULL, "nf_ct_icmpv6: invalid new with type %d ", type + 128); return false; @@ -203,7 +204,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl, icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih); if (icmp6h == NULL) { if (LOG_INVALID(net, IPPROTO_ICMPV6)) - nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL, "nf_ct_icmpv6: short packet "); return -NF_ACCEPT; } @@ -211,7 +212,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl, if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) { if (LOG_INVALID(net, IPPROTO_ICMPV6)) - nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL, "nf_ct_icmpv6: ICMPv6 checksum failed "); return -NF_ACCEPT; } diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 94b4b98..a0b1c5c 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -353,7 +353,7 @@ void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct, /* rcu_read_lock()ed by nf_hook_slow */ helper = rcu_dereference(help->helper); - nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, + nf_log_packet(nf_ct_net(ct), nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, "nf_ct_%s: dropping packet: %pV ", helper->name, &vaf); va_end(args); diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index 432f957..7358dc3 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c @@ -456,7 +456,8 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, out_invalid: if (LOG_INVALID(net, IPPROTO_DCCP)) - nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, msg); + nf_log_packet(net, nf_ct_l3num(ct), 0, skb, NULL, NULL, + NULL, msg); return false; } @@ -542,13 +543,13 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, spin_unlock_bh(&ct->lock); if (LOG_INVALID(net, IPPROTO_DCCP)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "nf_ct_dccp: invalid packet ignored "); return NF_ACCEPT; case CT_DCCP_INVALID: spin_unlock_bh(&ct->lock); if (LOG_INVALID(net, IPPROTO_DCCP)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "nf_ct_dccp: invalid state transition "); return -NF_ACCEPT; } @@ -613,7 +614,7 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl, out_invalid: if (LOG_INVALID(net, IPPROTO_DCCP)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, msg); + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, msg); return -NF_ACCEPT; } diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 83876e9..f021a20 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -720,7 +720,7 @@ static bool tcp_in_window(const struct nf_conn *ct, tn->tcp_be_liberal) res = true; if (!res && LOG_INVALID(net, IPPROTO_TCP)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "nf_ct_tcp: %s ", before(seq, sender->td_maxend + 1) ? after(end, sender->td_end - receiver->td_maxwin - 1) ? @@ -772,7 +772,7 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl, th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph); if (th == NULL) { if (LOG_INVALID(net, IPPROTO_TCP)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "nf_ct_tcp: short packet "); return -NF_ACCEPT; } @@ -780,7 +780,7 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl, /* Not whole TCP header or malformed packet */ if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) { if (LOG_INVALID(net, IPPROTO_TCP)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "nf_ct_tcp: truncated/malformed packet "); return -NF_ACCEPT; } @@ -793,7 +793,7 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl, if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) { if (LOG_INVALID(net, IPPROTO_TCP)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "nf_ct_tcp: bad TCP checksum "); return -NF_ACCEPT; } @@ -802,7 +802,7 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl, tcpflags = (tcp_flag_byte(th) & ~(TCPHDR_ECE|TCPHDR_CWR|TCPHDR_PSH)); if (!tcp_valid_flags[tcpflags]) { if (LOG_INVALID(net, IPPROTO_TCP)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "nf_ct_tcp: invalid TCP flag combination "); return -NF_ACCEPT; } @@ -949,7 +949,7 @@ static int tcp_packet(struct nf_conn *ct, } spin_unlock_bh(&ct->lock); if (LOG_INVALID(net, IPPROTO_TCP)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "nf_ct_tcp: invalid packet ignored in " "state %s ", tcp_conntrack_names[old_state]); return NF_ACCEPT; @@ -959,7 +959,7 @@ static int tcp_packet(struct nf_conn *ct, dir, get_conntrack_index(th), old_state); spin_unlock_bh(&ct->lock); if (LOG_INVALID(net, IPPROTO_TCP)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "nf_ct_tcp: invalid state "); return -NF_ACCEPT; case TCP_CONNTRACK_CLOSE: @@ -969,8 +969,8 @@ static int tcp_packet(struct nf_conn *ct, /* Invalid RST */ spin_unlock_bh(&ct->lock); if (LOG_INVALID(net, IPPROTO_TCP)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, - "nf_ct_tcp: invalid RST "); + nf_log_packet(net, pf, 0, skb, NULL, NULL, + NULL, "nf_ct_tcp: invalid RST "); return -NF_ACCEPT; } if (index == TCP_RST_SET diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index 59623cc..fee4322 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -119,7 +119,7 @@ static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); if (hdr == NULL) { if (LOG_INVALID(net, IPPROTO_UDP)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "nf_ct_udp: short packet "); return -NF_ACCEPT; } @@ -127,7 +127,7 @@ static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, /* Truncated/malformed packets */ if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) { if (LOG_INVALID(net, IPPROTO_UDP)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "nf_ct_udp: truncated/malformed packet "); return -NF_ACCEPT; } @@ -143,7 +143,7 @@ static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) { if (LOG_INVALID(net, IPPROTO_UDP)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "nf_ct_udp: bad UDP checksum "); return -NF_ACCEPT; } diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c index 1574895..c29d359 100644 --- a/net/netfilter/nf_conntrack_proto_udplite.c +++ b/net/netfilter/nf_conntrack_proto_udplite.c @@ -131,7 +131,7 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl, hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); if (hdr == NULL) { if (LOG_INVALID(net, IPPROTO_UDPLITE)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "nf_ct_udplite: short packet "); return -NF_ACCEPT; } @@ -141,7 +141,7 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl, cscov = udplen; else if (cscov < sizeof(*hdr) || cscov > udplen) { if (LOG_INVALID(net, IPPROTO_UDPLITE)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "nf_ct_udplite: invalid checksum coverage "); return -NF_ACCEPT; } @@ -149,7 +149,7 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl, /* UDPLITE mandates checksums */ if (!hdr->check) { if (LOG_INVALID(net, IPPROTO_UDPLITE)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "nf_ct_udplite: checksum missing "); return -NF_ACCEPT; } @@ -159,7 +159,7 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl, nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_UDP, pf)) { if (LOG_INVALID(net, IPPROTO_UDPLITE)) - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "nf_ct_udplite: bad UDPLite checksum "); return -NF_ACCEPT; } diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 9e31269..2aa1fc1 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -16,7 +16,6 @@ #define NF_LOG_PREFIXLEN 128 #define NFLOGGER_NAME_LEN 64 -static const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO] __read_mostly; static struct list_head nf_loggers_l[NFPROTO_NUMPROTO] __read_mostly; static DEFINE_MUTEX(nf_log_mutex); @@ -32,13 +31,50 @@ static struct nf_logger *__find_logger(int pf, const char *str_logger) return NULL; } +void nf_log_set(struct net *net, u_int8_t pf, const struct nf_logger *logger) +{ + if (!net_eq(net, &init_net)) + return; + + if (pf != NFPROTO_UNSPEC) { + const struct nf_logger *log; + mutex_lock(&nf_log_mutex); + log = rcu_dereference_protected(net->nf.nf_loggers[pf], + lockdep_is_held(&nf_log_mutex)); + if (log == NULL) + rcu_assign_pointer(net->nf.nf_loggers[pf], logger); + + mutex_unlock(&nf_log_mutex); + } +} +EXPORT_SYMBOL(nf_log_set); + +void nf_log_unset(struct net *net, const struct nf_logger *logger) +{ + int i; + const struct nf_logger *log; + + if (!net_eq(net, &init_net)) + return; + + mutex_lock(&nf_log_mutex); + for (i = 0; i < NFPROTO_NUMPROTO; i++) { + log = rcu_dereference_protected(net->nf.nf_loggers[i], + lockdep_is_held(&nf_log_mutex)); + if (log == logger) + RCU_INIT_POINTER(net->nf.nf_loggers[i], NULL); + } + mutex_unlock(&nf_log_mutex); + synchronize_rcu(); +} +EXPORT_SYMBOL(nf_log_unset); + /* return EEXIST if the same logger is registered, 0 on success. */ int nf_log_register(u_int8_t pf, struct nf_logger *logger) { - const struct nf_logger *llog; int i; - if (pf >= ARRAY_SIZE(nf_loggers)) + if (pf >= ARRAY_SIZE(init_net.nf.nf_loggers)) return -EINVAL; for (i = 0; i < ARRAY_SIZE(logger->list); i++) @@ -52,63 +88,62 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger) } else { /* register at end of list to honor first register win */ list_add_tail(&logger->list[pf], &nf_loggers_l[pf]); - llog = rcu_dereference_protected(nf_loggers[pf], - lockdep_is_held(&nf_log_mutex)); - if (llog == NULL) - rcu_assign_pointer(nf_loggers[pf], logger); } mutex_unlock(&nf_log_mutex); + nf_log_set(&init_net, pf, logger); return 0; } EXPORT_SYMBOL(nf_log_register); void nf_log_unregister(struct nf_logger *logger) { - const struct nf_logger *c_logger; int i; mutex_lock(&nf_log_mutex); - for (i = 0; i < ARRAY_SIZE(nf_loggers); i++) { - c_logger = rcu_dereference_protected(nf_loggers[i], - lockdep_is_held(&nf_log_mutex)); - if (c_logger == logger) - RCU_INIT_POINTER(nf_loggers[i], NULL); + for (i = 0; i < NFPROTO_NUMPROTO; i++) list_del(&logger->list[i]); - } mutex_unlock(&nf_log_mutex); - synchronize_rcu(); + nf_log_unset(&init_net, logger); } EXPORT_SYMBOL(nf_log_unregister); -int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger) +int nf_log_bind_pf(struct net *net, u_int8_t pf, + const struct nf_logger *logger) { - if (pf >= ARRAY_SIZE(nf_loggers)) + if (!net_eq(net, &init_net)) + return 0; + + if (pf >= ARRAY_SIZE(net->nf.nf_loggers)) return -EINVAL; mutex_lock(&nf_log_mutex); if (__find_logger(pf, logger->name) == NULL) { mutex_unlock(&nf_log_mutex); return -ENOENT; } - rcu_assign_pointer(nf_loggers[pf], logger); + rcu_assign_pointer(net->nf.nf_loggers[pf], logger); mutex_unlock(&nf_log_mutex); return 0; } EXPORT_SYMBOL(nf_log_bind_pf); -void nf_log_unbind_pf(u_int8_t pf) +void nf_log_unbind_pf(struct net *net, u_int8_t pf) { - if (pf >= ARRAY_SIZE(nf_loggers)) + if (!net_eq(net, &init_net)) + return; + + if (pf >= ARRAY_SIZE(net->nf.nf_loggers)) return; mutex_lock(&nf_log_mutex); - RCU_INIT_POINTER(nf_loggers[pf], NULL); + RCU_INIT_POINTER(net->nf.nf_loggers[pf], NULL); mutex_unlock(&nf_log_mutex); } EXPORT_SYMBOL(nf_log_unbind_pf); -void nf_log_packet(u_int8_t pf, +void nf_log_packet(struct net *net, + u_int8_t pf, unsigned int hooknum, const struct sk_buff *skb, const struct net_device *in, @@ -120,8 +155,11 @@ void nf_log_packet(u_int8_t pf, char prefix[NF_LOG_PREFIXLEN]; const struct nf_logger *logger; + if (!net_eq(net, &init_net)) + return; + rcu_read_lock(); - logger = rcu_dereference(nf_loggers[pf]); + logger = rcu_dereference(net->nf.nf_loggers[pf]); if (logger) { va_start(args, fmt); vsnprintf(prefix, sizeof(prefix), fmt, args); @@ -135,9 +173,11 @@ EXPORT_SYMBOL(nf_log_packet); #ifdef CONFIG_PROC_FS static void *seq_start(struct seq_file *seq, loff_t *pos) { + struct net *net = seq_file_net(seq); + mutex_lock(&nf_log_mutex); - if (*pos >= ARRAY_SIZE(nf_loggers)) + if (*pos >= ARRAY_SIZE(net->nf.nf_loggers)) return NULL; return pos; @@ -145,9 +185,11 @@ static void *seq_start(struct seq_file *seq, loff_t *pos) static void *seq_next(struct seq_file *s, void *v, loff_t *pos) { + struct net *net = seq_file_net(s); + (*pos)++; - if (*pos >= ARRAY_SIZE(nf_loggers)) + if (*pos >= ARRAY_SIZE(net->nf.nf_loggers)) return NULL; return pos; @@ -164,8 +206,9 @@ static int seq_show(struct seq_file *s, void *v) const struct nf_logger *logger; struct nf_logger *t; int ret; + struct net *net = seq_file_net(s); - logger = rcu_dereference_protected(nf_loggers[*pos], + logger = rcu_dereference_protected(net->nf.nf_loggers[*pos], lockdep_is_held(&nf_log_mutex)); if (!logger) @@ -199,7 +242,8 @@ static const struct seq_operations nflog_seq_ops = { static int nflog_open(struct inode *inode, struct file *file) { - return seq_open(file, &nflog_seq_ops); + return seq_open_net(inode, file, &nflog_seq_ops, + sizeof(struct seq_net_private)); } static const struct file_operations nflog_file_ops = { @@ -207,7 +251,7 @@ static const struct file_operations nflog_file_ops = { .open = nflog_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = seq_release_net, }; @@ -216,7 +260,6 @@ static const struct file_operations nflog_file_ops = { #ifdef CONFIG_SYSCTL static char nf_log_sysctl_fnames[NFPROTO_NUMPROTO-NFPROTO_UNSPEC][3]; static struct ctl_table nf_log_sysctl_table[NFPROTO_NUMPROTO+1]; -static struct ctl_table_header *nf_log_dir_header; static int nf_log_proc_dostring(ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) @@ -226,15 +269,19 @@ static int nf_log_proc_dostring(ctl_table *table, int write, size_t size = *lenp; int r = 0; int tindex = (unsigned long)table->extra1; + struct net *net = current->nsproxy->net_ns; if (write) { + if (!net_eq(net, &init_net)) + return -EPERM; + if (size > sizeof(buf)) size = sizeof(buf); if (copy_from_user(buf, buffer, size)) return -EFAULT; if (!strcmp(buf, "NONE")) { - nf_log_unbind_pf(tindex); + nf_log_unbind_pf(net, tindex); return 0; } mutex_lock(&nf_log_mutex); @@ -243,11 +290,11 @@ static int nf_log_proc_dostring(ctl_table *table, int write, mutex_unlock(&nf_log_mutex); return -ENOENT; } - rcu_assign_pointer(nf_loggers[tindex], logger); + rcu_assign_pointer(net->nf.nf_loggers[tindex], logger); mutex_unlock(&nf_log_mutex); } else { mutex_lock(&nf_log_mutex); - logger = rcu_dereference_protected(nf_loggers[tindex], + logger = rcu_dereference_protected(net->nf.nf_loggers[tindex], lockdep_is_held(&nf_log_mutex)); if (!logger) table->data = "NONE"; @@ -260,49 +307,111 @@ static int nf_log_proc_dostring(ctl_table *table, int write, return r; } -static __init int netfilter_log_sysctl_init(void) +static int netfilter_log_sysctl_init(struct net *net) { int i; - - for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) { - snprintf(nf_log_sysctl_fnames[i-NFPROTO_UNSPEC], 3, "%d", i); - nf_log_sysctl_table[i].procname = - nf_log_sysctl_fnames[i-NFPROTO_UNSPEC]; - nf_log_sysctl_table[i].data = NULL; - nf_log_sysctl_table[i].maxlen = - NFLOGGER_NAME_LEN * sizeof(char); - nf_log_sysctl_table[i].mode = 0644; - nf_log_sysctl_table[i].proc_handler = nf_log_proc_dostring; - nf_log_sysctl_table[i].extra1 = (void *)(unsigned long) i; + struct ctl_table *table; + + table = nf_log_sysctl_table; + if (!net_eq(net, &init_net)) { + table = kmemdup(nf_log_sysctl_table, + sizeof(nf_log_sysctl_table), + GFP_KERNEL); + if (!table) + goto err_alloc; + } else { + for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) { + snprintf(nf_log_sysctl_fnames[i-NFPROTO_UNSPEC], + 3, "%d", i); + nf_log_sysctl_table[i].procname = + nf_log_sysctl_fnames[i-NFPROTO_UNSPEC]; + nf_log_sysctl_table[i].data = NULL; + nf_log_sysctl_table[i].maxlen = + NFLOGGER_NAME_LEN * sizeof(char); + nf_log_sysctl_table[i].mode = 0644; + nf_log_sysctl_table[i].proc_handler = + nf_log_proc_dostring; + nf_log_sysctl_table[i].extra1 = + (void *)(unsigned long) i; + } } - nf_log_dir_header = register_net_sysctl(&init_net, "net/netfilter/nf_log", - nf_log_sysctl_table); - if (!nf_log_dir_header) - return -ENOMEM; + net->nf.nf_log_dir_header = register_net_sysctl(net, + "net/netfilter/nf_log", + table); + if (!net->nf.nf_log_dir_header) + goto err_reg; return 0; +err_reg: + if (!net_eq(net, &init_net)) + kfree(table); +err_alloc: + return -ENOMEM; +} + +static void netfilter_log_sysctl_exit(struct net *net) +{ + struct ctl_table *table; + + table = net->nf.nf_log_dir_header->ctl_table_arg; + unregister_net_sysctl_table(net->nf.nf_log_dir_header); + if (!net_eq(net, &init_net)) + kfree(table); } #else -static __init int netfilter_log_sysctl_init(void) +static int netfilter_log_sysctl_init(struct net *net) { return 0; } + +static void netfilter_log_sysctl_exit(struct net *net) +{ +} #endif /* CONFIG_SYSCTL */ -int __init netfilter_log_init(void) +static int __net_init nf_log_net_init(struct net *net) { - int i, r; + int ret = -ENOMEM; #ifdef CONFIG_PROC_FS if (!proc_create("nf_log", S_IRUGO, - proc_net_netfilter, &nflog_file_ops)) - return -1; + net->nf.proc_netfilter, &nflog_file_ops)) + goto out_proc; #endif + ret = netfilter_log_sysctl_init(net); + if (ret < 0) + goto out_sysctl; + return 0; +out_sysctl: +#ifdef CONFIG_PROC_FS + /* + * For init net, Erros will trigger panic, + * unrool on error is unnecessary, + */ + if (!net_eq(net, &init_net)) + remove_proc_entry("nf_log", net->nf.proc_netfilter); +out_proc: +#endif + return ret; +} + +static void __net_exit nf_log_net_exit(struct net *net) +{ + netfilter_log_sysctl_exit(net); + remove_proc_entry("nf_log", net->nf.proc_netfilter); +} - /* Errors will trigger panic, unroll on error is unnecessary. */ - r = netfilter_log_sysctl_init(); - if (r < 0) - return r; +static struct pernet_operations nf_log_net_ops = { + .init = nf_log_net_init, + .exit = nf_log_net_exit, +}; + +int __init netfilter_log_init(void) +{ + int i, ret; + ret = register_pernet_subsys(&nf_log_net_ops); + if (ret < 0) + return ret; for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) INIT_LIST_HEAD(&(nf_loggers_l[i])); diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index f248db5..b593fd1 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -767,6 +767,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, u_int16_t group_num = ntohs(nfmsg->res_id); struct nfulnl_instance *inst; struct nfulnl_msg_config_cmd *cmd = NULL; + struct net *net = sock_net(ctnl); int ret = 0; if (nfula[NFULA_CFG_CMD]) { @@ -776,9 +777,9 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, /* Commands without queue context */ switch (cmd->command) { case NFULNL_CFG_CMD_PF_BIND: - return nf_log_bind_pf(pf, &nfulnl_logger); + return nf_log_bind_pf(net, pf, &nfulnl_logger); case NFULNL_CFG_CMD_PF_UNBIND: - nf_log_unbind_pf(pf); + nf_log_unbind_pf(net, pf); return 0; } } diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c index a5e673d..647d989 100644 --- a/net/netfilter/xt_osf.c +++ b/net/netfilter/xt_osf.c @@ -201,6 +201,7 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p) unsigned char opts[MAX_IPOPTLEN]; const struct xt_osf_finger *kf; const struct xt_osf_user_finger *f; + struct net *net = dev_net(p->in ? p->in : p->out); if (!info) return false; @@ -325,7 +326,7 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p) fcount++; if (info->flags & XT_OSF_LOG) - nf_log_packet(p->family, p->hooknum, skb, + nf_log_packet(net, p->family, p->hooknum, skb, p->in, p->out, NULL, "%s [%s:%s] : %pI4:%d -> %pI4:%d hops=%d\n", f->genre, f->version, f->subtype, @@ -341,7 +342,8 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p) rcu_read_unlock(); if (!fcount && (info->flags & XT_OSF_LOG)) - nf_log_packet(p->family, p->hooknum, skb, p->in, p->out, NULL, + nf_log_packet(net, p->family, p->hooknum, skb, p->in, + p->out, NULL, "Remote OS is not known: %pI4:%u -> %pI4:%u\n", &ip->saddr, ntohs(tcp->source), &ip->daddr, ntohs(tcp->dest)); -- 1.7.11.7 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH nf-next v2 02/10] netfilter: nf_log: prepar net namespace support for nf_log 2013-03-25 9:50 ` [PATCH nf-next v2 02/10] netfilter: nf_log: prepar net namespace support for nf_log Gao feng @ 2013-04-05 18:30 ` Pablo Neira Ayuso 2013-04-08 2:46 ` Gao feng 0 siblings, 1 reply; 24+ messages in thread From: Pablo Neira Ayuso @ 2013-04-05 18:30 UTC (permalink / raw) To: Gao feng; +Cc: netfilter-devel On Mon, Mar 25, 2013 at 05:50:40PM +0800, Gao feng wrote: > This patch adds netns support for nf_log,contains > four major changes. > > 1,nf_log_register is split to two functions: > nf_log_register and nf_log_set. > The new nf_log_register is used only for register nf_logger, > nf_log_set is used for setting pernet nf_loggers. > > Because the moudules that use the nf_log_register should be > changed to use these new functions, and in order not to > change the behavior. only allow to set the nf_loggers of > init net. > > 2,Add net as a parameter of nf_log_bind_pf,only allow init net > to bind the nflogger to the proto family. > > 3,Some l4proto such as tcp,udp... use nf_log_packet to log > the invalid packets, we need pass proper netns to the > nf_log_packet. Since other netns except init net has > no nflogger binding to the proto, we only allow nf_log_packet > handle the log request which comes from init net. > > 4,Make the sysctl net/netfilter/nf_log pernet. Applied with some changes (see below), thanks. > Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> > --- > include/net/netfilter/nf_log.h | 14 +- > include/net/netns/netfilter.h | 7 + > net/bridge/netfilter/ebt_log.c | 7 +- > net/bridge/netfilter/ebt_nflog.c | 5 +- > net/ipv4/netfilter/ip_tables.c | 3 +- > net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 8 +- > net/ipv6/netfilter/ip6_tables.c | 3 +- > net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 7 +- > net/netfilter/nf_conntrack_helper.c | 2 +- > net/netfilter/nf_conntrack_proto_dccp.c | 9 +- > net/netfilter/nf_conntrack_proto_tcp.c | 18 +- > net/netfilter/nf_conntrack_proto_udp.c | 6 +- > net/netfilter/nf_conntrack_proto_udplite.c | 8 +- > net/netfilter/nf_log.c | 223 ++++++++++++++++++------- > net/netfilter/nfnetlink_log.c | 5 +- > net/netfilter/xt_osf.c | 6 +- > 16 files changed, 231 insertions(+), 100 deletions(-) > > diff --git a/include/net/netfilter/nf_log.h b/include/net/netfilter/nf_log.h > index e991bd0..31f1fb9 100644 > --- a/include/net/netfilter/nf_log.h > +++ b/include/net/netfilter/nf_log.h > @@ -49,12 +49,18 @@ struct nf_logger { > int nf_log_register(u_int8_t pf, struct nf_logger *logger); > void nf_log_unregister(struct nf_logger *logger); > > -int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger); > -void nf_log_unbind_pf(u_int8_t pf); > +void nf_log_set(struct net *net, u_int8_t pf, > + const struct nf_logger *logger); > +void nf_log_unset(struct net *net, const struct nf_logger *logger); > + > +int nf_log_bind_pf(struct net *net, u_int8_t pf, > + const struct nf_logger *logger); > +void nf_log_unbind_pf(struct net *net, u_int8_t pf); > > /* Calls the registered backend logging function */ > -__printf(7, 8) > -void nf_log_packet(u_int8_t pf, > +__printf(8, 9) > +void nf_log_packet(struct net *net, > + u_int8_t pf, > unsigned int hooknum, > const struct sk_buff *skb, > const struct net_device *in, > diff --git a/include/net/netns/netfilter.h b/include/net/netns/netfilter.h > index 248ca1c..8874002 100644 > --- a/include/net/netns/netfilter.h > +++ b/include/net/netns/netfilter.h > @@ -2,10 +2,17 @@ > #define __NETNS_NETFILTER_H > > #include <linux/proc_fs.h> > +#include <linux/netfilter.h> > + > +struct nf_logger; > > struct netns_nf { > #if defined CONFIG_PROC_FS > struct proc_dir_entry *proc_netfilter; > #endif > + const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO]; > +#ifdef CONFIG_SYSCTL > + struct ctl_table_header *nf_log_dir_header; > +#endif > }; > #endif > diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c > index 92de5e5..08e5ea5 100644 > --- a/net/bridge/netfilter/ebt_log.c > +++ b/net/bridge/netfilter/ebt_log.c > @@ -176,17 +176,18 @@ ebt_log_tg(struct sk_buff *skb, const struct xt_action_param *par) > { > const struct ebt_log_info *info = par->targinfo; > struct nf_loginfo li; > + struct net *net = dev_net(par->in ? par->in : par->out); > > li.type = NF_LOG_TYPE_LOG; > li.u.log.level = info->loglevel; > li.u.log.logflags = info->bitmask; > > if (info->bitmask & EBT_LOG_NFLOG) > - nf_log_packet(NFPROTO_BRIDGE, par->hooknum, skb, par->in, > - par->out, &li, "%s", info->prefix); > + nf_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb, > + par->in, par->out, &li, "%s", info->prefix); > else > ebt_log_packet(NFPROTO_BRIDGE, par->hooknum, skb, par->in, > - par->out, &li, info->prefix); > + par->out, &li, info->prefix); > return EBT_CONTINUE; > } > > diff --git a/net/bridge/netfilter/ebt_nflog.c b/net/bridge/netfilter/ebt_nflog.c > index 5be68bb..59ac795 100644 > --- a/net/bridge/netfilter/ebt_nflog.c > +++ b/net/bridge/netfilter/ebt_nflog.c > @@ -24,14 +24,15 @@ ebt_nflog_tg(struct sk_buff *skb, const struct xt_action_param *par) > { > const struct ebt_nflog_info *info = par->targinfo; > struct nf_loginfo li; > + struct net *net = dev_net(par->in ? par->in : par->out); > > li.type = NF_LOG_TYPE_ULOG; > li.u.ulog.copy_len = info->len; > li.u.ulog.group = info->group; > li.u.ulog.qthreshold = info->threshold; > > - nf_log_packet(PF_BRIDGE, par->hooknum, skb, par->in, par->out, > - &li, "%s", info->prefix); > + nf_log_packet(net, PF_BRIDGE, par->hooknum, skb, par->in, > + par->out, &li, "%s", info->prefix); > return EBT_CONTINUE; > } > > diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c > index 3efcf87..b371593 100644 > --- a/net/ipv4/netfilter/ip_tables.c > +++ b/net/ipv4/netfilter/ip_tables.c > @@ -259,6 +259,7 @@ static void trace_packet(const struct sk_buff *skb, > const char *hookname, *chainname, *comment; > const struct ipt_entry *iter; > unsigned int rulenum = 0; > + struct net *net = dev_net(in ? in : out); > > table_base = private->entries[smp_processor_id()]; > root = get_entry(table_base, private->hook_entry[hook]); > @@ -271,7 +272,7 @@ static void trace_packet(const struct sk_buff *skb, > &chainname, &comment, &rulenum) != 0) > break; > > - nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo, > + nf_log_packet(net, AF_INET, hook, skb, in, out, &trace_loginfo, > "TRACE: %s:%s:%s:%u ", > tablename, chainname, comment, rulenum); > } > diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c > index 5241d99..c2cd63d 100644 > --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c > +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c > @@ -187,8 +187,8 @@ icmp_error(struct net *net, struct nf_conn *tmpl, > icmph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_ih), &_ih); > if (icmph == NULL) { > if (LOG_INVALID(net, IPPROTO_ICMP)) > - nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, > - "nf_ct_icmp: short packet "); > + nf_log_packet(net, PF_INET, 0, skb, NULL, NULL, > + NULL, "nf_ct_icmp: short packet "); > return -NF_ACCEPT; > } > > @@ -196,7 +196,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl, > if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && > nf_ip_checksum(skb, hooknum, dataoff, 0)) { > if (LOG_INVALID(net, IPPROTO_ICMP)) > - nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, PF_INET, 0, skb, NULL, NULL, NULL, > "nf_ct_icmp: bad HW ICMP checksum "); > return -NF_ACCEPT; > } > @@ -209,7 +209,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl, > */ > if (icmph->type > NR_ICMP_TYPES) { > if (LOG_INVALID(net, IPPROTO_ICMP)) > - nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, PF_INET, 0, skb, NULL, NULL, NULL, > "nf_ct_icmp: invalid ICMP type "); > return -NF_ACCEPT; > } > diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c > index 341b54a..8861b1e 100644 > --- a/net/ipv6/netfilter/ip6_tables.c > +++ b/net/ipv6/netfilter/ip6_tables.c > @@ -284,6 +284,7 @@ static void trace_packet(const struct sk_buff *skb, > const char *hookname, *chainname, *comment; > const struct ip6t_entry *iter; > unsigned int rulenum = 0; > + struct net *net = dev_net(in ? in : out); > > table_base = private->entries[smp_processor_id()]; > root = get_entry(table_base, private->hook_entry[hook]); > @@ -296,7 +297,7 @@ static void trace_packet(const struct sk_buff *skb, > &chainname, &comment, &rulenum) != 0) > break; > > - nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo, > + nf_log_packet(net, AF_INET6, hook, skb, in, out, &trace_loginfo, > "TRACE: %s:%s:%s:%u ", > tablename, chainname, comment, rulenum); > } > diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c > index 24df3dd..b3807c5 100644 > --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c > +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c > @@ -131,7 +131,8 @@ static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, > type + 128); > nf_ct_dump_tuple_ipv6(&ct->tuplehash[0].tuple); > if (LOG_INVALID(nf_ct_net(ct), IPPROTO_ICMPV6)) > - nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, > + nf_log_packet(nf_ct_net(ct), PF_INET6, 0, skb, NULL, > + NULL, NULL, > "nf_ct_icmpv6: invalid new with type %d ", > type + 128); > return false; > @@ -203,7 +204,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl, > icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih); > if (icmp6h == NULL) { > if (LOG_INVALID(net, IPPROTO_ICMPV6)) > - nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL, > "nf_ct_icmpv6: short packet "); > return -NF_ACCEPT; > } > @@ -211,7 +212,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl, > if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && > nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) { > if (LOG_INVALID(net, IPPROTO_ICMPV6)) > - nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL, > "nf_ct_icmpv6: ICMPv6 checksum failed "); > return -NF_ACCEPT; > } > diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c > index 94b4b98..a0b1c5c 100644 > --- a/net/netfilter/nf_conntrack_helper.c > +++ b/net/netfilter/nf_conntrack_helper.c > @@ -353,7 +353,7 @@ void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct, > /* rcu_read_lock()ed by nf_hook_slow */ > helper = rcu_dereference(help->helper); > > - nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, > + nf_log_packet(nf_ct_net(ct), nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, > "nf_ct_%s: dropping packet: %pV ", helper->name, &vaf); > > va_end(args); > diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c > index 432f957..7358dc3 100644 > --- a/net/netfilter/nf_conntrack_proto_dccp.c > +++ b/net/netfilter/nf_conntrack_proto_dccp.c > @@ -456,7 +456,8 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, > > out_invalid: > if (LOG_INVALID(net, IPPROTO_DCCP)) > - nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, msg); > + nf_log_packet(net, nf_ct_l3num(ct), 0, skb, NULL, NULL, > + NULL, msg); > return false; > } > > @@ -542,13 +543,13 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, > > spin_unlock_bh(&ct->lock); > if (LOG_INVALID(net, IPPROTO_DCCP)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, > "nf_ct_dccp: invalid packet ignored "); > return NF_ACCEPT; > case CT_DCCP_INVALID: > spin_unlock_bh(&ct->lock); > if (LOG_INVALID(net, IPPROTO_DCCP)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, > "nf_ct_dccp: invalid state transition "); > return -NF_ACCEPT; > } > @@ -613,7 +614,7 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl, > > out_invalid: > if (LOG_INVALID(net, IPPROTO_DCCP)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, msg); > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, msg); > return -NF_ACCEPT; > } > > diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c > index 83876e9..f021a20 100644 > --- a/net/netfilter/nf_conntrack_proto_tcp.c > +++ b/net/netfilter/nf_conntrack_proto_tcp.c > @@ -720,7 +720,7 @@ static bool tcp_in_window(const struct nf_conn *ct, > tn->tcp_be_liberal) > res = true; > if (!res && LOG_INVALID(net, IPPROTO_TCP)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, > "nf_ct_tcp: %s ", > before(seq, sender->td_maxend + 1) ? > after(end, sender->td_end - receiver->td_maxwin - 1) ? > @@ -772,7 +772,7 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl, > th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph); > if (th == NULL) { > if (LOG_INVALID(net, IPPROTO_TCP)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, > "nf_ct_tcp: short packet "); > return -NF_ACCEPT; > } > @@ -780,7 +780,7 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl, > /* Not whole TCP header or malformed packet */ > if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) { > if (LOG_INVALID(net, IPPROTO_TCP)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, > "nf_ct_tcp: truncated/malformed packet "); > return -NF_ACCEPT; > } > @@ -793,7 +793,7 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl, > if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && > nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) { > if (LOG_INVALID(net, IPPROTO_TCP)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, > "nf_ct_tcp: bad TCP checksum "); > return -NF_ACCEPT; > } > @@ -802,7 +802,7 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl, > tcpflags = (tcp_flag_byte(th) & ~(TCPHDR_ECE|TCPHDR_CWR|TCPHDR_PSH)); > if (!tcp_valid_flags[tcpflags]) { > if (LOG_INVALID(net, IPPROTO_TCP)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, > "nf_ct_tcp: invalid TCP flag combination "); > return -NF_ACCEPT; > } > @@ -949,7 +949,7 @@ static int tcp_packet(struct nf_conn *ct, > } > spin_unlock_bh(&ct->lock); > if (LOG_INVALID(net, IPPROTO_TCP)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, > "nf_ct_tcp: invalid packet ignored in " > "state %s ", tcp_conntrack_names[old_state]); > return NF_ACCEPT; > @@ -959,7 +959,7 @@ static int tcp_packet(struct nf_conn *ct, > dir, get_conntrack_index(th), old_state); > spin_unlock_bh(&ct->lock); > if (LOG_INVALID(net, IPPROTO_TCP)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, > "nf_ct_tcp: invalid state "); > return -NF_ACCEPT; > case TCP_CONNTRACK_CLOSE: > @@ -969,8 +969,8 @@ static int tcp_packet(struct nf_conn *ct, > /* Invalid RST */ > spin_unlock_bh(&ct->lock); > if (LOG_INVALID(net, IPPROTO_TCP)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > - "nf_ct_tcp: invalid RST "); > + nf_log_packet(net, pf, 0, skb, NULL, NULL, > + NULL, "nf_ct_tcp: invalid RST "); > return -NF_ACCEPT; > } > if (index == TCP_RST_SET > diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c > index 59623cc..fee4322 100644 > --- a/net/netfilter/nf_conntrack_proto_udp.c > +++ b/net/netfilter/nf_conntrack_proto_udp.c > @@ -119,7 +119,7 @@ static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, > hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); > if (hdr == NULL) { > if (LOG_INVALID(net, IPPROTO_UDP)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, > "nf_ct_udp: short packet "); > return -NF_ACCEPT; > } > @@ -127,7 +127,7 @@ static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, > /* Truncated/malformed packets */ > if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) { > if (LOG_INVALID(net, IPPROTO_UDP)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, > "nf_ct_udp: truncated/malformed packet "); > return -NF_ACCEPT; > } > @@ -143,7 +143,7 @@ static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, > if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && > nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) { > if (LOG_INVALID(net, IPPROTO_UDP)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, > "nf_ct_udp: bad UDP checksum "); > return -NF_ACCEPT; > } > diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c > index 1574895..c29d359 100644 > --- a/net/netfilter/nf_conntrack_proto_udplite.c > +++ b/net/netfilter/nf_conntrack_proto_udplite.c > @@ -131,7 +131,7 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl, > hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); > if (hdr == NULL) { > if (LOG_INVALID(net, IPPROTO_UDPLITE)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, > "nf_ct_udplite: short packet "); > return -NF_ACCEPT; > } > @@ -141,7 +141,7 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl, > cscov = udplen; > else if (cscov < sizeof(*hdr) || cscov > udplen) { > if (LOG_INVALID(net, IPPROTO_UDPLITE)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, > "nf_ct_udplite: invalid checksum coverage "); > return -NF_ACCEPT; > } > @@ -149,7 +149,7 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl, > /* UDPLITE mandates checksums */ > if (!hdr->check) { > if (LOG_INVALID(net, IPPROTO_UDPLITE)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, > "nf_ct_udplite: checksum missing "); > return -NF_ACCEPT; > } > @@ -159,7 +159,7 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl, > nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_UDP, > pf)) { > if (LOG_INVALID(net, IPPROTO_UDPLITE)) > - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, > + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, > "nf_ct_udplite: bad UDPLite checksum "); > return -NF_ACCEPT; > } > diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c > index 9e31269..2aa1fc1 100644 > --- a/net/netfilter/nf_log.c > +++ b/net/netfilter/nf_log.c > @@ -16,7 +16,6 @@ > #define NF_LOG_PREFIXLEN 128 > #define NFLOGGER_NAME_LEN 64 > > -static const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO] __read_mostly; > static struct list_head nf_loggers_l[NFPROTO_NUMPROTO] __read_mostly; > static DEFINE_MUTEX(nf_log_mutex); > > @@ -32,13 +31,50 @@ static struct nf_logger *__find_logger(int pf, const char *str_logger) > return NULL; > } > > +void nf_log_set(struct net *net, u_int8_t pf, const struct nf_logger *logger) > +{ > + if (!net_eq(net, &init_net)) > + return; > + > + if (pf != NFPROTO_UNSPEC) { > + const struct nf_logger *log; > + mutex_lock(&nf_log_mutex); > + log = rcu_dereference_protected(net->nf.nf_loggers[pf], > + lockdep_is_held(&nf_log_mutex)); > + if (log == NULL) > + rcu_assign_pointer(net->nf.nf_loggers[pf], logger); > + > + mutex_unlock(&nf_log_mutex); > + } > +} > +EXPORT_SYMBOL(nf_log_set); > + > +void nf_log_unset(struct net *net, const struct nf_logger *logger) > +{ > + int i; > + const struct nf_logger *log; > + > + if (!net_eq(net, &init_net)) > + return; > + > + mutex_lock(&nf_log_mutex); > + for (i = 0; i < NFPROTO_NUMPROTO; i++) { > + log = rcu_dereference_protected(net->nf.nf_loggers[i], > + lockdep_is_held(&nf_log_mutex)); > + if (log == logger) > + RCU_INIT_POINTER(net->nf.nf_loggers[i], NULL); > + } > + mutex_unlock(&nf_log_mutex); > + synchronize_rcu(); > +} > +EXPORT_SYMBOL(nf_log_unset); > + > /* return EEXIST if the same logger is registered, 0 on success. */ > int nf_log_register(u_int8_t pf, struct nf_logger *logger) > { > - const struct nf_logger *llog; > int i; > > - if (pf >= ARRAY_SIZE(nf_loggers)) > + if (pf >= ARRAY_SIZE(init_net.nf.nf_loggers)) > return -EINVAL; > > for (i = 0; i < ARRAY_SIZE(logger->list); i++) > @@ -52,63 +88,62 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger) > } else { > /* register at end of list to honor first register win */ > list_add_tail(&logger->list[pf], &nf_loggers_l[pf]); > - llog = rcu_dereference_protected(nf_loggers[pf], > - lockdep_is_held(&nf_log_mutex)); > - if (llog == NULL) > - rcu_assign_pointer(nf_loggers[pf], logger); > } > > mutex_unlock(&nf_log_mutex); > > + nf_log_set(&init_net, pf, logger); > return 0; > } > EXPORT_SYMBOL(nf_log_register); > > void nf_log_unregister(struct nf_logger *logger) > { > - const struct nf_logger *c_logger; > int i; > > mutex_lock(&nf_log_mutex); > - for (i = 0; i < ARRAY_SIZE(nf_loggers); i++) { > - c_logger = rcu_dereference_protected(nf_loggers[i], > - lockdep_is_held(&nf_log_mutex)); > - if (c_logger == logger) > - RCU_INIT_POINTER(nf_loggers[i], NULL); > + for (i = 0; i < NFPROTO_NUMPROTO; i++) > list_del(&logger->list[i]); > - } > mutex_unlock(&nf_log_mutex); > > - synchronize_rcu(); > + nf_log_unset(&init_net, logger); > } > EXPORT_SYMBOL(nf_log_unregister); > > -int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger) > +int nf_log_bind_pf(struct net *net, u_int8_t pf, > + const struct nf_logger *logger) > { > - if (pf >= ARRAY_SIZE(nf_loggers)) > + if (!net_eq(net, &init_net)) > + return 0; > + > + if (pf >= ARRAY_SIZE(net->nf.nf_loggers)) > return -EINVAL; > mutex_lock(&nf_log_mutex); > if (__find_logger(pf, logger->name) == NULL) { > mutex_unlock(&nf_log_mutex); > return -ENOENT; > } > - rcu_assign_pointer(nf_loggers[pf], logger); > + rcu_assign_pointer(net->nf.nf_loggers[pf], logger); > mutex_unlock(&nf_log_mutex); > return 0; > } > EXPORT_SYMBOL(nf_log_bind_pf); > > -void nf_log_unbind_pf(u_int8_t pf) > +void nf_log_unbind_pf(struct net *net, u_int8_t pf) > { > - if (pf >= ARRAY_SIZE(nf_loggers)) > + if (!net_eq(net, &init_net)) > + return; > + > + if (pf >= ARRAY_SIZE(net->nf.nf_loggers)) > return; > mutex_lock(&nf_log_mutex); > - RCU_INIT_POINTER(nf_loggers[pf], NULL); > + RCU_INIT_POINTER(net->nf.nf_loggers[pf], NULL); > mutex_unlock(&nf_log_mutex); > } > EXPORT_SYMBOL(nf_log_unbind_pf); > > -void nf_log_packet(u_int8_t pf, > +void nf_log_packet(struct net *net, > + u_int8_t pf, > unsigned int hooknum, > const struct sk_buff *skb, > const struct net_device *in, > @@ -120,8 +155,11 @@ void nf_log_packet(u_int8_t pf, > char prefix[NF_LOG_PREFIXLEN]; > const struct nf_logger *logger; > > + if (!net_eq(net, &init_net)) > + return; > + > rcu_read_lock(); > - logger = rcu_dereference(nf_loggers[pf]); > + logger = rcu_dereference(net->nf.nf_loggers[pf]); > if (logger) { > va_start(args, fmt); > vsnprintf(prefix, sizeof(prefix), fmt, args); > @@ -135,9 +173,11 @@ EXPORT_SYMBOL(nf_log_packet); > #ifdef CONFIG_PROC_FS > static void *seq_start(struct seq_file *seq, loff_t *pos) > { > + struct net *net = seq_file_net(seq); > + > mutex_lock(&nf_log_mutex); > > - if (*pos >= ARRAY_SIZE(nf_loggers)) > + if (*pos >= ARRAY_SIZE(net->nf.nf_loggers)) > return NULL; > > return pos; > @@ -145,9 +185,11 @@ static void *seq_start(struct seq_file *seq, loff_t *pos) > > static void *seq_next(struct seq_file *s, void *v, loff_t *pos) > { > + struct net *net = seq_file_net(s); > + > (*pos)++; > > - if (*pos >= ARRAY_SIZE(nf_loggers)) > + if (*pos >= ARRAY_SIZE(net->nf.nf_loggers)) > return NULL; > > return pos; > @@ -164,8 +206,9 @@ static int seq_show(struct seq_file *s, void *v) > const struct nf_logger *logger; > struct nf_logger *t; > int ret; > + struct net *net = seq_file_net(s); > > - logger = rcu_dereference_protected(nf_loggers[*pos], > + logger = rcu_dereference_protected(net->nf.nf_loggers[*pos], > lockdep_is_held(&nf_log_mutex)); > > if (!logger) > @@ -199,7 +242,8 @@ static const struct seq_operations nflog_seq_ops = { > > static int nflog_open(struct inode *inode, struct file *file) > { > - return seq_open(file, &nflog_seq_ops); > + return seq_open_net(inode, file, &nflog_seq_ops, > + sizeof(struct seq_net_private)); > } > > static const struct file_operations nflog_file_ops = { > @@ -207,7 +251,7 @@ static const struct file_operations nflog_file_ops = { > .open = nflog_open, > .read = seq_read, > .llseek = seq_lseek, > - .release = seq_release, > + .release = seq_release_net, > }; > > > @@ -216,7 +260,6 @@ static const struct file_operations nflog_file_ops = { > #ifdef CONFIG_SYSCTL > static char nf_log_sysctl_fnames[NFPROTO_NUMPROTO-NFPROTO_UNSPEC][3]; > static struct ctl_table nf_log_sysctl_table[NFPROTO_NUMPROTO+1]; > -static struct ctl_table_header *nf_log_dir_header; > > static int nf_log_proc_dostring(ctl_table *table, int write, > void __user *buffer, size_t *lenp, loff_t *ppos) > @@ -226,15 +269,19 @@ static int nf_log_proc_dostring(ctl_table *table, int write, > size_t size = *lenp; > int r = 0; > int tindex = (unsigned long)table->extra1; > + struct net *net = current->nsproxy->net_ns; > > if (write) { > + if (!net_eq(net, &init_net)) > + return -EPERM; > + > if (size > sizeof(buf)) > size = sizeof(buf); > if (copy_from_user(buf, buffer, size)) > return -EFAULT; > > if (!strcmp(buf, "NONE")) { > - nf_log_unbind_pf(tindex); > + nf_log_unbind_pf(net, tindex); > return 0; > } > mutex_lock(&nf_log_mutex); > @@ -243,11 +290,11 @@ static int nf_log_proc_dostring(ctl_table *table, int write, > mutex_unlock(&nf_log_mutex); > return -ENOENT; > } > - rcu_assign_pointer(nf_loggers[tindex], logger); > + rcu_assign_pointer(net->nf.nf_loggers[tindex], logger); > mutex_unlock(&nf_log_mutex); > } else { > mutex_lock(&nf_log_mutex); > - logger = rcu_dereference_protected(nf_loggers[tindex], > + logger = rcu_dereference_protected(net->nf.nf_loggers[tindex], > lockdep_is_held(&nf_log_mutex)); > if (!logger) > table->data = "NONE"; > @@ -260,49 +307,111 @@ static int nf_log_proc_dostring(ctl_table *table, int write, > return r; > } > > -static __init int netfilter_log_sysctl_init(void) > +static int netfilter_log_sysctl_init(struct net *net) > { > int i; > - > - for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) { > - snprintf(nf_log_sysctl_fnames[i-NFPROTO_UNSPEC], 3, "%d", i); > - nf_log_sysctl_table[i].procname = > - nf_log_sysctl_fnames[i-NFPROTO_UNSPEC]; > - nf_log_sysctl_table[i].data = NULL; > - nf_log_sysctl_table[i].maxlen = > - NFLOGGER_NAME_LEN * sizeof(char); > - nf_log_sysctl_table[i].mode = 0644; > - nf_log_sysctl_table[i].proc_handler = nf_log_proc_dostring; > - nf_log_sysctl_table[i].extra1 = (void *)(unsigned long) i; > + struct ctl_table *table; > + > + table = nf_log_sysctl_table; > + if (!net_eq(net, &init_net)) { > + table = kmemdup(nf_log_sysctl_table, > + sizeof(nf_log_sysctl_table), > + GFP_KERNEL); > + if (!table) > + goto err_alloc; > + } else { > + for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) { > + snprintf(nf_log_sysctl_fnames[i-NFPROTO_UNSPEC], > + 3, "%d", i); This is not your fault actually. While at it, I have removed -NFPROTO_UNSPEC (it's zero, so that substraction provides nothing). > + nf_log_sysctl_table[i].procname = > + nf_log_sysctl_fnames[i-NFPROTO_UNSPEC]; > + nf_log_sysctl_table[i].data = NULL; > + nf_log_sysctl_table[i].maxlen = > + NFLOGGER_NAME_LEN * sizeof(char); > + nf_log_sysctl_table[i].mode = 0644; > + nf_log_sysctl_table[i].proc_handler = > + nf_log_proc_dostring; > + nf_log_sysctl_table[i].extra1 = > + (void *)(unsigned long) i; > + } > } > > - nf_log_dir_header = register_net_sysctl(&init_net, "net/netfilter/nf_log", > - nf_log_sysctl_table); > - if (!nf_log_dir_header) > - return -ENOMEM; > + net->nf.nf_log_dir_header = register_net_sysctl(net, > + "net/netfilter/nf_log", > + table); > + if (!net->nf.nf_log_dir_header) > + goto err_reg; > > return 0; > +err_reg: > + if (!net_eq(net, &init_net)) > + kfree(table); > +err_alloc: > + return -ENOMEM; > +} > + > +static void netfilter_log_sysctl_exit(struct net *net) > +{ > + struct ctl_table *table; > + > + table = net->nf.nf_log_dir_header->ctl_table_arg; > + unregister_net_sysctl_table(net->nf.nf_log_dir_header); > + if (!net_eq(net, &init_net)) > + kfree(table); > } > #else > -static __init int netfilter_log_sysctl_init(void) > +static int netfilter_log_sysctl_init(struct net *net) > { > return 0; > } > + > +static void netfilter_log_sysctl_exit(struct net *net) > +{ > +} > #endif /* CONFIG_SYSCTL */ > > -int __init netfilter_log_init(void) > +static int __net_init nf_log_net_init(struct net *net) > { > - int i, r; > + int ret = -ENOMEM; > #ifdef CONFIG_PROC_FS > if (!proc_create("nf_log", S_IRUGO, > - proc_net_netfilter, &nflog_file_ops)) > - return -1; > + net->nf.proc_netfilter, &nflog_file_ops)) > + goto out_proc; > #endif > + ret = netfilter_log_sysctl_init(net); > + if (ret < 0) > + goto out_sysctl; > + return 0; > +out_sysctl: > +#ifdef CONFIG_PROC_FS removed this ifdef. The function remove_proc_entry already defines an empty function if CONFIG_PROC_FS is not set. > + /* > + * For init net, Erros will trigger panic, > + * unrool on error is unnecessary, > + */ Fixed English typos in this sentence. > + if (!net_eq(net, &init_net)) > + remove_proc_entry("nf_log", net->nf.proc_netfilter); > +out_proc: > +#endif > + return ret; > +} > + > +static void __net_exit nf_log_net_exit(struct net *net) > +{ > + netfilter_log_sysctl_exit(net); > + remove_proc_entry("nf_log", net->nf.proc_netfilter); > +} > > - /* Errors will trigger panic, unroll on error is unnecessary. */ > - r = netfilter_log_sysctl_init(); > - if (r < 0) > - return r; > +static struct pernet_operations nf_log_net_ops = { > + .init = nf_log_net_init, > + .exit = nf_log_net_exit, > +}; > + > +int __init netfilter_log_init(void) > +{ > + int i, ret; Please, add empty line after variable declaration next time. > + ret = register_pernet_subsys(&nf_log_net_ops); > + if (ret < 0) > + return ret; > > for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) > INIT_LIST_HEAD(&(nf_loggers_l[i])); > diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c > index f248db5..b593fd1 100644 > --- a/net/netfilter/nfnetlink_log.c > +++ b/net/netfilter/nfnetlink_log.c > @@ -767,6 +767,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, > u_int16_t group_num = ntohs(nfmsg->res_id); > struct nfulnl_instance *inst; > struct nfulnl_msg_config_cmd *cmd = NULL; > + struct net *net = sock_net(ctnl); > int ret = 0; > > if (nfula[NFULA_CFG_CMD]) { > @@ -776,9 +777,9 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, > /* Commands without queue context */ > switch (cmd->command) { > case NFULNL_CFG_CMD_PF_BIND: > - return nf_log_bind_pf(pf, &nfulnl_logger); > + return nf_log_bind_pf(net, pf, &nfulnl_logger); > case NFULNL_CFG_CMD_PF_UNBIND: > - nf_log_unbind_pf(pf); > + nf_log_unbind_pf(net, pf); > return 0; > } > } > diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c > index a5e673d..647d989 100644 > --- a/net/netfilter/xt_osf.c > +++ b/net/netfilter/xt_osf.c > @@ -201,6 +201,7 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p) > unsigned char opts[MAX_IPOPTLEN]; > const struct xt_osf_finger *kf; > const struct xt_osf_user_finger *f; > + struct net *net = dev_net(p->in ? p->in : p->out); > > if (!info) > return false; > @@ -325,7 +326,7 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p) > fcount++; > > if (info->flags & XT_OSF_LOG) > - nf_log_packet(p->family, p->hooknum, skb, > + nf_log_packet(net, p->family, p->hooknum, skb, > p->in, p->out, NULL, > "%s [%s:%s] : %pI4:%d -> %pI4:%d hops=%d\n", > f->genre, f->version, f->subtype, > @@ -341,7 +342,8 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p) > rcu_read_unlock(); > > if (!fcount && (info->flags & XT_OSF_LOG)) > - nf_log_packet(p->family, p->hooknum, skb, p->in, p->out, NULL, > + nf_log_packet(net, p->family, p->hooknum, skb, p->in, > + p->out, NULL, > "Remote OS is not known: %pI4:%u -> %pI4:%u\n", > &ip->saddr, ntohs(tcp->source), > &ip->daddr, ntohs(tcp->dest)); > -- > 1.7.11.7 > > -- > 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 [flat|nested] 24+ messages in thread
* Re: [PATCH nf-next v2 02/10] netfilter: nf_log: prepar net namespace support for nf_log 2013-04-05 18:30 ` Pablo Neira Ayuso @ 2013-04-08 2:46 ` Gao feng 0 siblings, 0 replies; 24+ messages in thread From: Gao feng @ 2013-04-08 2:46 UTC (permalink / raw) To: Pablo Neira Ayuso; +Cc: netfilter-devel On 2013/04/06 02:30, Pablo Neira Ayuso wrote: > On Mon, Mar 25, 2013 at 05:50:40PM +0800, Gao feng wrote: >> This patch adds netns support for nf_log,contains >> four major changes. >> >> 1,nf_log_register is split to two functions: >> nf_log_register and nf_log_set. >> The new nf_log_register is used only for register nf_logger, >> nf_log_set is used for setting pernet nf_loggers. >> >> Because the moudules that use the nf_log_register should be >> changed to use these new functions, and in order not to >> change the behavior. only allow to set the nf_loggers of >> init net. >> >> 2,Add net as a parameter of nf_log_bind_pf,only allow init net >> to bind the nflogger to the proto family. >> >> 3,Some l4proto such as tcp,udp... use nf_log_packet to log >> the invalid packets, we need pass proper netns to the >> nf_log_packet. Since other netns except init net has >> no nflogger binding to the proto, we only allow nf_log_packet >> handle the log request which comes from init net. >> >> 4,Make the sysctl net/netfilter/nf_log pernet. > > Applied with some changes (see below), thanks. > >> Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> >> --- >> include/net/netfilter/nf_log.h | 14 +- >> include/net/netns/netfilter.h | 7 + >> net/bridge/netfilter/ebt_log.c | 7 +- >> net/bridge/netfilter/ebt_nflog.c | 5 +- >> net/ipv4/netfilter/ip_tables.c | 3 +- >> net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 8 +- >> net/ipv6/netfilter/ip6_tables.c | 3 +- >> net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 7 +- >> net/netfilter/nf_conntrack_helper.c | 2 +- >> net/netfilter/nf_conntrack_proto_dccp.c | 9 +- >> net/netfilter/nf_conntrack_proto_tcp.c | 18 +- >> net/netfilter/nf_conntrack_proto_udp.c | 6 +- >> net/netfilter/nf_conntrack_proto_udplite.c | 8 +- >> net/netfilter/nf_log.c | 223 ++++++++++++++++++------- >> net/netfilter/nfnetlink_log.c | 5 +- >> net/netfilter/xt_osf.c | 6 +- >> 16 files changed, 231 insertions(+), 100 deletions(-) >> >> diff --git a/include/net/netfilter/nf_log.h b/include/net/netfilter/nf_log.h >> index e991bd0..31f1fb9 100644 >> --- a/include/net/netfilter/nf_log.h >> +++ b/include/net/netfilter/nf_log.h >> @@ -49,12 +49,18 @@ struct nf_logger { >> int nf_log_register(u_int8_t pf, struct nf_logger *logger); >> void nf_log_unregister(struct nf_logger *logger); >> >> -int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger); >> -void nf_log_unbind_pf(u_int8_t pf); >> +void nf_log_set(struct net *net, u_int8_t pf, >> + const struct nf_logger *logger); >> +void nf_log_unset(struct net *net, const struct nf_logger *logger); >> + >> +int nf_log_bind_pf(struct net *net, u_int8_t pf, >> + const struct nf_logger *logger); >> +void nf_log_unbind_pf(struct net *net, u_int8_t pf); >> >> /* Calls the registered backend logging function */ >> -__printf(7, 8) >> -void nf_log_packet(u_int8_t pf, >> +__printf(8, 9) >> +void nf_log_packet(struct net *net, >> + u_int8_t pf, >> unsigned int hooknum, >> const struct sk_buff *skb, >> const struct net_device *in, >> diff --git a/include/net/netns/netfilter.h b/include/net/netns/netfilter.h >> index 248ca1c..8874002 100644 >> --- a/include/net/netns/netfilter.h >> +++ b/include/net/netns/netfilter.h >> @@ -2,10 +2,17 @@ >> #define __NETNS_NETFILTER_H >> >> #include <linux/proc_fs.h> >> +#include <linux/netfilter.h> >> + >> +struct nf_logger; >> >> struct netns_nf { >> #if defined CONFIG_PROC_FS >> struct proc_dir_entry *proc_netfilter; >> #endif >> + const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO]; >> +#ifdef CONFIG_SYSCTL >> + struct ctl_table_header *nf_log_dir_header; >> +#endif >> }; >> #endif >> diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c >> index 92de5e5..08e5ea5 100644 >> --- a/net/bridge/netfilter/ebt_log.c >> +++ b/net/bridge/netfilter/ebt_log.c >> @@ -176,17 +176,18 @@ ebt_log_tg(struct sk_buff *skb, const struct xt_action_param *par) >> { >> const struct ebt_log_info *info = par->targinfo; >> struct nf_loginfo li; >> + struct net *net = dev_net(par->in ? par->in : par->out); >> >> li.type = NF_LOG_TYPE_LOG; >> li.u.log.level = info->loglevel; >> li.u.log.logflags = info->bitmask; >> >> if (info->bitmask & EBT_LOG_NFLOG) >> - nf_log_packet(NFPROTO_BRIDGE, par->hooknum, skb, par->in, >> - par->out, &li, "%s", info->prefix); >> + nf_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb, >> + par->in, par->out, &li, "%s", info->prefix); >> else >> ebt_log_packet(NFPROTO_BRIDGE, par->hooknum, skb, par->in, >> - par->out, &li, info->prefix); >> + par->out, &li, info->prefix); >> return EBT_CONTINUE; >> } >> >> diff --git a/net/bridge/netfilter/ebt_nflog.c b/net/bridge/netfilter/ebt_nflog.c >> index 5be68bb..59ac795 100644 >> --- a/net/bridge/netfilter/ebt_nflog.c >> +++ b/net/bridge/netfilter/ebt_nflog.c >> @@ -24,14 +24,15 @@ ebt_nflog_tg(struct sk_buff *skb, const struct xt_action_param *par) >> { >> const struct ebt_nflog_info *info = par->targinfo; >> struct nf_loginfo li; >> + struct net *net = dev_net(par->in ? par->in : par->out); >> >> li.type = NF_LOG_TYPE_ULOG; >> li.u.ulog.copy_len = info->len; >> li.u.ulog.group = info->group; >> li.u.ulog.qthreshold = info->threshold; >> >> - nf_log_packet(PF_BRIDGE, par->hooknum, skb, par->in, par->out, >> - &li, "%s", info->prefix); >> + nf_log_packet(net, PF_BRIDGE, par->hooknum, skb, par->in, >> + par->out, &li, "%s", info->prefix); >> return EBT_CONTINUE; >> } >> >> diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c >> index 3efcf87..b371593 100644 >> --- a/net/ipv4/netfilter/ip_tables.c >> +++ b/net/ipv4/netfilter/ip_tables.c >> @@ -259,6 +259,7 @@ static void trace_packet(const struct sk_buff *skb, >> const char *hookname, *chainname, *comment; >> const struct ipt_entry *iter; >> unsigned int rulenum = 0; >> + struct net *net = dev_net(in ? in : out); >> >> table_base = private->entries[smp_processor_id()]; >> root = get_entry(table_base, private->hook_entry[hook]); >> @@ -271,7 +272,7 @@ static void trace_packet(const struct sk_buff *skb, >> &chainname, &comment, &rulenum) != 0) >> break; >> >> - nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo, >> + nf_log_packet(net, AF_INET, hook, skb, in, out, &trace_loginfo, >> "TRACE: %s:%s:%s:%u ", >> tablename, chainname, comment, rulenum); >> } >> diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c >> index 5241d99..c2cd63d 100644 >> --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c >> +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c >> @@ -187,8 +187,8 @@ icmp_error(struct net *net, struct nf_conn *tmpl, >> icmph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_ih), &_ih); >> if (icmph == NULL) { >> if (LOG_INVALID(net, IPPROTO_ICMP)) >> - nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, >> - "nf_ct_icmp: short packet "); >> + nf_log_packet(net, PF_INET, 0, skb, NULL, NULL, >> + NULL, "nf_ct_icmp: short packet "); >> return -NF_ACCEPT; >> } >> >> @@ -196,7 +196,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl, >> if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && >> nf_ip_checksum(skb, hooknum, dataoff, 0)) { >> if (LOG_INVALID(net, IPPROTO_ICMP)) >> - nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, PF_INET, 0, skb, NULL, NULL, NULL, >> "nf_ct_icmp: bad HW ICMP checksum "); >> return -NF_ACCEPT; >> } >> @@ -209,7 +209,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl, >> */ >> if (icmph->type > NR_ICMP_TYPES) { >> if (LOG_INVALID(net, IPPROTO_ICMP)) >> - nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, PF_INET, 0, skb, NULL, NULL, NULL, >> "nf_ct_icmp: invalid ICMP type "); >> return -NF_ACCEPT; >> } >> diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c >> index 341b54a..8861b1e 100644 >> --- a/net/ipv6/netfilter/ip6_tables.c >> +++ b/net/ipv6/netfilter/ip6_tables.c >> @@ -284,6 +284,7 @@ static void trace_packet(const struct sk_buff *skb, >> const char *hookname, *chainname, *comment; >> const struct ip6t_entry *iter; >> unsigned int rulenum = 0; >> + struct net *net = dev_net(in ? in : out); >> >> table_base = private->entries[smp_processor_id()]; >> root = get_entry(table_base, private->hook_entry[hook]); >> @@ -296,7 +297,7 @@ static void trace_packet(const struct sk_buff *skb, >> &chainname, &comment, &rulenum) != 0) >> break; >> >> - nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo, >> + nf_log_packet(net, AF_INET6, hook, skb, in, out, &trace_loginfo, >> "TRACE: %s:%s:%s:%u ", >> tablename, chainname, comment, rulenum); >> } >> diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c >> index 24df3dd..b3807c5 100644 >> --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c >> +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c >> @@ -131,7 +131,8 @@ static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, >> type + 128); >> nf_ct_dump_tuple_ipv6(&ct->tuplehash[0].tuple); >> if (LOG_INVALID(nf_ct_net(ct), IPPROTO_ICMPV6)) >> - nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(nf_ct_net(ct), PF_INET6, 0, skb, NULL, >> + NULL, NULL, >> "nf_ct_icmpv6: invalid new with type %d ", >> type + 128); >> return false; >> @@ -203,7 +204,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl, >> icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih); >> if (icmp6h == NULL) { >> if (LOG_INVALID(net, IPPROTO_ICMPV6)) >> - nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL, >> "nf_ct_icmpv6: short packet "); >> return -NF_ACCEPT; >> } >> @@ -211,7 +212,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl, >> if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && >> nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) { >> if (LOG_INVALID(net, IPPROTO_ICMPV6)) >> - nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, PF_INET6, 0, skb, NULL, NULL, NULL, >> "nf_ct_icmpv6: ICMPv6 checksum failed "); >> return -NF_ACCEPT; >> } >> diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c >> index 94b4b98..a0b1c5c 100644 >> --- a/net/netfilter/nf_conntrack_helper.c >> +++ b/net/netfilter/nf_conntrack_helper.c >> @@ -353,7 +353,7 @@ void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct, >> /* rcu_read_lock()ed by nf_hook_slow */ >> helper = rcu_dereference(help->helper); >> >> - nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, >> + nf_log_packet(nf_ct_net(ct), nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, >> "nf_ct_%s: dropping packet: %pV ", helper->name, &vaf); >> >> va_end(args); >> diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c >> index 432f957..7358dc3 100644 >> --- a/net/netfilter/nf_conntrack_proto_dccp.c >> +++ b/net/netfilter/nf_conntrack_proto_dccp.c >> @@ -456,7 +456,8 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, >> >> out_invalid: >> if (LOG_INVALID(net, IPPROTO_DCCP)) >> - nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, msg); >> + nf_log_packet(net, nf_ct_l3num(ct), 0, skb, NULL, NULL, >> + NULL, msg); >> return false; >> } >> >> @@ -542,13 +543,13 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, >> >> spin_unlock_bh(&ct->lock); >> if (LOG_INVALID(net, IPPROTO_DCCP)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, >> "nf_ct_dccp: invalid packet ignored "); >> return NF_ACCEPT; >> case CT_DCCP_INVALID: >> spin_unlock_bh(&ct->lock); >> if (LOG_INVALID(net, IPPROTO_DCCP)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, >> "nf_ct_dccp: invalid state transition "); >> return -NF_ACCEPT; >> } >> @@ -613,7 +614,7 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl, >> >> out_invalid: >> if (LOG_INVALID(net, IPPROTO_DCCP)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, msg); >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, msg); >> return -NF_ACCEPT; >> } >> >> diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c >> index 83876e9..f021a20 100644 >> --- a/net/netfilter/nf_conntrack_proto_tcp.c >> +++ b/net/netfilter/nf_conntrack_proto_tcp.c >> @@ -720,7 +720,7 @@ static bool tcp_in_window(const struct nf_conn *ct, >> tn->tcp_be_liberal) >> res = true; >> if (!res && LOG_INVALID(net, IPPROTO_TCP)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, >> "nf_ct_tcp: %s ", >> before(seq, sender->td_maxend + 1) ? >> after(end, sender->td_end - receiver->td_maxwin - 1) ? >> @@ -772,7 +772,7 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl, >> th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph); >> if (th == NULL) { >> if (LOG_INVALID(net, IPPROTO_TCP)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, >> "nf_ct_tcp: short packet "); >> return -NF_ACCEPT; >> } >> @@ -780,7 +780,7 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl, >> /* Not whole TCP header or malformed packet */ >> if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) { >> if (LOG_INVALID(net, IPPROTO_TCP)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, >> "nf_ct_tcp: truncated/malformed packet "); >> return -NF_ACCEPT; >> } >> @@ -793,7 +793,7 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl, >> if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && >> nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) { >> if (LOG_INVALID(net, IPPROTO_TCP)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, >> "nf_ct_tcp: bad TCP checksum "); >> return -NF_ACCEPT; >> } >> @@ -802,7 +802,7 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl, >> tcpflags = (tcp_flag_byte(th) & ~(TCPHDR_ECE|TCPHDR_CWR|TCPHDR_PSH)); >> if (!tcp_valid_flags[tcpflags]) { >> if (LOG_INVALID(net, IPPROTO_TCP)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, >> "nf_ct_tcp: invalid TCP flag combination "); >> return -NF_ACCEPT; >> } >> @@ -949,7 +949,7 @@ static int tcp_packet(struct nf_conn *ct, >> } >> spin_unlock_bh(&ct->lock); >> if (LOG_INVALID(net, IPPROTO_TCP)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, >> "nf_ct_tcp: invalid packet ignored in " >> "state %s ", tcp_conntrack_names[old_state]); >> return NF_ACCEPT; >> @@ -959,7 +959,7 @@ static int tcp_packet(struct nf_conn *ct, >> dir, get_conntrack_index(th), old_state); >> spin_unlock_bh(&ct->lock); >> if (LOG_INVALID(net, IPPROTO_TCP)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, >> "nf_ct_tcp: invalid state "); >> return -NF_ACCEPT; >> case TCP_CONNTRACK_CLOSE: >> @@ -969,8 +969,8 @@ static int tcp_packet(struct nf_conn *ct, >> /* Invalid RST */ >> spin_unlock_bh(&ct->lock); >> if (LOG_INVALID(net, IPPROTO_TCP)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> - "nf_ct_tcp: invalid RST "); >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, >> + NULL, "nf_ct_tcp: invalid RST "); >> return -NF_ACCEPT; >> } >> if (index == TCP_RST_SET >> diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c >> index 59623cc..fee4322 100644 >> --- a/net/netfilter/nf_conntrack_proto_udp.c >> +++ b/net/netfilter/nf_conntrack_proto_udp.c >> @@ -119,7 +119,7 @@ static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, >> hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); >> if (hdr == NULL) { >> if (LOG_INVALID(net, IPPROTO_UDP)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, >> "nf_ct_udp: short packet "); >> return -NF_ACCEPT; >> } >> @@ -127,7 +127,7 @@ static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, >> /* Truncated/malformed packets */ >> if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) { >> if (LOG_INVALID(net, IPPROTO_UDP)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, >> "nf_ct_udp: truncated/malformed packet "); >> return -NF_ACCEPT; >> } >> @@ -143,7 +143,7 @@ static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, >> if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING && >> nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) { >> if (LOG_INVALID(net, IPPROTO_UDP)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, >> "nf_ct_udp: bad UDP checksum "); >> return -NF_ACCEPT; >> } >> diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c >> index 1574895..c29d359 100644 >> --- a/net/netfilter/nf_conntrack_proto_udplite.c >> +++ b/net/netfilter/nf_conntrack_proto_udplite.c >> @@ -131,7 +131,7 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl, >> hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); >> if (hdr == NULL) { >> if (LOG_INVALID(net, IPPROTO_UDPLITE)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, >> "nf_ct_udplite: short packet "); >> return -NF_ACCEPT; >> } >> @@ -141,7 +141,7 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl, >> cscov = udplen; >> else if (cscov < sizeof(*hdr) || cscov > udplen) { >> if (LOG_INVALID(net, IPPROTO_UDPLITE)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, >> "nf_ct_udplite: invalid checksum coverage "); >> return -NF_ACCEPT; >> } >> @@ -149,7 +149,7 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl, >> /* UDPLITE mandates checksums */ >> if (!hdr->check) { >> if (LOG_INVALID(net, IPPROTO_UDPLITE)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, >> "nf_ct_udplite: checksum missing "); >> return -NF_ACCEPT; >> } >> @@ -159,7 +159,7 @@ static int udplite_error(struct net *net, struct nf_conn *tmpl, >> nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_UDP, >> pf)) { >> if (LOG_INVALID(net, IPPROTO_UDPLITE)) >> - nf_log_packet(pf, 0, skb, NULL, NULL, NULL, >> + nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, >> "nf_ct_udplite: bad UDPLite checksum "); >> return -NF_ACCEPT; >> } >> diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c >> index 9e31269..2aa1fc1 100644 >> --- a/net/netfilter/nf_log.c >> +++ b/net/netfilter/nf_log.c >> @@ -16,7 +16,6 @@ >> #define NF_LOG_PREFIXLEN 128 >> #define NFLOGGER_NAME_LEN 64 >> >> -static const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO] __read_mostly; >> static struct list_head nf_loggers_l[NFPROTO_NUMPROTO] __read_mostly; >> static DEFINE_MUTEX(nf_log_mutex); >> >> @@ -32,13 +31,50 @@ static struct nf_logger *__find_logger(int pf, const char *str_logger) >> return NULL; >> } >> >> +void nf_log_set(struct net *net, u_int8_t pf, const struct nf_logger *logger) >> +{ >> + if (!net_eq(net, &init_net)) >> + return; >> + >> + if (pf != NFPROTO_UNSPEC) { >> + const struct nf_logger *log; >> + mutex_lock(&nf_log_mutex); >> + log = rcu_dereference_protected(net->nf.nf_loggers[pf], >> + lockdep_is_held(&nf_log_mutex)); >> + if (log == NULL) >> + rcu_assign_pointer(net->nf.nf_loggers[pf], logger); >> + >> + mutex_unlock(&nf_log_mutex); >> + } >> +} >> +EXPORT_SYMBOL(nf_log_set); >> + >> +void nf_log_unset(struct net *net, const struct nf_logger *logger) >> +{ >> + int i; >> + const struct nf_logger *log; >> + >> + if (!net_eq(net, &init_net)) >> + return; >> + >> + mutex_lock(&nf_log_mutex); >> + for (i = 0; i < NFPROTO_NUMPROTO; i++) { >> + log = rcu_dereference_protected(net->nf.nf_loggers[i], >> + lockdep_is_held(&nf_log_mutex)); >> + if (log == logger) >> + RCU_INIT_POINTER(net->nf.nf_loggers[i], NULL); >> + } >> + mutex_unlock(&nf_log_mutex); >> + synchronize_rcu(); >> +} >> +EXPORT_SYMBOL(nf_log_unset); >> + >> /* return EEXIST if the same logger is registered, 0 on success. */ >> int nf_log_register(u_int8_t pf, struct nf_logger *logger) >> { >> - const struct nf_logger *llog; >> int i; >> >> - if (pf >= ARRAY_SIZE(nf_loggers)) >> + if (pf >= ARRAY_SIZE(init_net.nf.nf_loggers)) >> return -EINVAL; >> >> for (i = 0; i < ARRAY_SIZE(logger->list); i++) >> @@ -52,63 +88,62 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger) >> } else { >> /* register at end of list to honor first register win */ >> list_add_tail(&logger->list[pf], &nf_loggers_l[pf]); >> - llog = rcu_dereference_protected(nf_loggers[pf], >> - lockdep_is_held(&nf_log_mutex)); >> - if (llog == NULL) >> - rcu_assign_pointer(nf_loggers[pf], logger); >> } >> >> mutex_unlock(&nf_log_mutex); >> >> + nf_log_set(&init_net, pf, logger); >> return 0; >> } >> EXPORT_SYMBOL(nf_log_register); >> >> void nf_log_unregister(struct nf_logger *logger) >> { >> - const struct nf_logger *c_logger; >> int i; >> >> mutex_lock(&nf_log_mutex); >> - for (i = 0; i < ARRAY_SIZE(nf_loggers); i++) { >> - c_logger = rcu_dereference_protected(nf_loggers[i], >> - lockdep_is_held(&nf_log_mutex)); >> - if (c_logger == logger) >> - RCU_INIT_POINTER(nf_loggers[i], NULL); >> + for (i = 0; i < NFPROTO_NUMPROTO; i++) >> list_del(&logger->list[i]); >> - } >> mutex_unlock(&nf_log_mutex); >> >> - synchronize_rcu(); >> + nf_log_unset(&init_net, logger); >> } >> EXPORT_SYMBOL(nf_log_unregister); >> >> -int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger) >> +int nf_log_bind_pf(struct net *net, u_int8_t pf, >> + const struct nf_logger *logger) >> { >> - if (pf >= ARRAY_SIZE(nf_loggers)) >> + if (!net_eq(net, &init_net)) >> + return 0; >> + >> + if (pf >= ARRAY_SIZE(net->nf.nf_loggers)) >> return -EINVAL; >> mutex_lock(&nf_log_mutex); >> if (__find_logger(pf, logger->name) == NULL) { >> mutex_unlock(&nf_log_mutex); >> return -ENOENT; >> } >> - rcu_assign_pointer(nf_loggers[pf], logger); >> + rcu_assign_pointer(net->nf.nf_loggers[pf], logger); >> mutex_unlock(&nf_log_mutex); >> return 0; >> } >> EXPORT_SYMBOL(nf_log_bind_pf); >> >> -void nf_log_unbind_pf(u_int8_t pf) >> +void nf_log_unbind_pf(struct net *net, u_int8_t pf) >> { >> - if (pf >= ARRAY_SIZE(nf_loggers)) >> + if (!net_eq(net, &init_net)) >> + return; >> + >> + if (pf >= ARRAY_SIZE(net->nf.nf_loggers)) >> return; >> mutex_lock(&nf_log_mutex); >> - RCU_INIT_POINTER(nf_loggers[pf], NULL); >> + RCU_INIT_POINTER(net->nf.nf_loggers[pf], NULL); >> mutex_unlock(&nf_log_mutex); >> } >> EXPORT_SYMBOL(nf_log_unbind_pf); >> >> -void nf_log_packet(u_int8_t pf, >> +void nf_log_packet(struct net *net, >> + u_int8_t pf, >> unsigned int hooknum, >> const struct sk_buff *skb, >> const struct net_device *in, >> @@ -120,8 +155,11 @@ void nf_log_packet(u_int8_t pf, >> char prefix[NF_LOG_PREFIXLEN]; >> const struct nf_logger *logger; >> >> + if (!net_eq(net, &init_net)) >> + return; >> + >> rcu_read_lock(); >> - logger = rcu_dereference(nf_loggers[pf]); >> + logger = rcu_dereference(net->nf.nf_loggers[pf]); >> if (logger) { >> va_start(args, fmt); >> vsnprintf(prefix, sizeof(prefix), fmt, args); >> @@ -135,9 +173,11 @@ EXPORT_SYMBOL(nf_log_packet); >> #ifdef CONFIG_PROC_FS >> static void *seq_start(struct seq_file *seq, loff_t *pos) >> { >> + struct net *net = seq_file_net(seq); >> + >> mutex_lock(&nf_log_mutex); >> >> - if (*pos >= ARRAY_SIZE(nf_loggers)) >> + if (*pos >= ARRAY_SIZE(net->nf.nf_loggers)) >> return NULL; >> >> return pos; >> @@ -145,9 +185,11 @@ static void *seq_start(struct seq_file *seq, loff_t *pos) >> >> static void *seq_next(struct seq_file *s, void *v, loff_t *pos) >> { >> + struct net *net = seq_file_net(s); >> + >> (*pos)++; >> >> - if (*pos >= ARRAY_SIZE(nf_loggers)) >> + if (*pos >= ARRAY_SIZE(net->nf.nf_loggers)) >> return NULL; >> >> return pos; >> @@ -164,8 +206,9 @@ static int seq_show(struct seq_file *s, void *v) >> const struct nf_logger *logger; >> struct nf_logger *t; >> int ret; >> + struct net *net = seq_file_net(s); >> >> - logger = rcu_dereference_protected(nf_loggers[*pos], >> + logger = rcu_dereference_protected(net->nf.nf_loggers[*pos], >> lockdep_is_held(&nf_log_mutex)); >> >> if (!logger) >> @@ -199,7 +242,8 @@ static const struct seq_operations nflog_seq_ops = { >> >> static int nflog_open(struct inode *inode, struct file *file) >> { >> - return seq_open(file, &nflog_seq_ops); >> + return seq_open_net(inode, file, &nflog_seq_ops, >> + sizeof(struct seq_net_private)); >> } >> >> static const struct file_operations nflog_file_ops = { >> @@ -207,7 +251,7 @@ static const struct file_operations nflog_file_ops = { >> .open = nflog_open, >> .read = seq_read, >> .llseek = seq_lseek, >> - .release = seq_release, >> + .release = seq_release_net, >> }; >> >> >> @@ -216,7 +260,6 @@ static const struct file_operations nflog_file_ops = { >> #ifdef CONFIG_SYSCTL >> static char nf_log_sysctl_fnames[NFPROTO_NUMPROTO-NFPROTO_UNSPEC][3]; >> static struct ctl_table nf_log_sysctl_table[NFPROTO_NUMPROTO+1]; >> -static struct ctl_table_header *nf_log_dir_header; >> >> static int nf_log_proc_dostring(ctl_table *table, int write, >> void __user *buffer, size_t *lenp, loff_t *ppos) >> @@ -226,15 +269,19 @@ static int nf_log_proc_dostring(ctl_table *table, int write, >> size_t size = *lenp; >> int r = 0; >> int tindex = (unsigned long)table->extra1; >> + struct net *net = current->nsproxy->net_ns; >> >> if (write) { >> + if (!net_eq(net, &init_net)) >> + return -EPERM; >> + >> if (size > sizeof(buf)) >> size = sizeof(buf); >> if (copy_from_user(buf, buffer, size)) >> return -EFAULT; >> >> if (!strcmp(buf, "NONE")) { >> - nf_log_unbind_pf(tindex); >> + nf_log_unbind_pf(net, tindex); >> return 0; >> } >> mutex_lock(&nf_log_mutex); >> @@ -243,11 +290,11 @@ static int nf_log_proc_dostring(ctl_table *table, int write, >> mutex_unlock(&nf_log_mutex); >> return -ENOENT; >> } >> - rcu_assign_pointer(nf_loggers[tindex], logger); >> + rcu_assign_pointer(net->nf.nf_loggers[tindex], logger); >> mutex_unlock(&nf_log_mutex); >> } else { >> mutex_lock(&nf_log_mutex); >> - logger = rcu_dereference_protected(nf_loggers[tindex], >> + logger = rcu_dereference_protected(net->nf.nf_loggers[tindex], >> lockdep_is_held(&nf_log_mutex)); >> if (!logger) >> table->data = "NONE"; >> @@ -260,49 +307,111 @@ static int nf_log_proc_dostring(ctl_table *table, int write, >> return r; >> } >> >> -static __init int netfilter_log_sysctl_init(void) >> +static int netfilter_log_sysctl_init(struct net *net) >> { >> int i; >> - >> - for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) { >> - snprintf(nf_log_sysctl_fnames[i-NFPROTO_UNSPEC], 3, "%d", i); >> - nf_log_sysctl_table[i].procname = >> - nf_log_sysctl_fnames[i-NFPROTO_UNSPEC]; >> - nf_log_sysctl_table[i].data = NULL; >> - nf_log_sysctl_table[i].maxlen = >> - NFLOGGER_NAME_LEN * sizeof(char); >> - nf_log_sysctl_table[i].mode = 0644; >> - nf_log_sysctl_table[i].proc_handler = nf_log_proc_dostring; >> - nf_log_sysctl_table[i].extra1 = (void *)(unsigned long) i; >> + struct ctl_table *table; >> + >> + table = nf_log_sysctl_table; >> + if (!net_eq(net, &init_net)) { >> + table = kmemdup(nf_log_sysctl_table, >> + sizeof(nf_log_sysctl_table), >> + GFP_KERNEL); >> + if (!table) >> + goto err_alloc; >> + } else { >> + for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) { >> + snprintf(nf_log_sysctl_fnames[i-NFPROTO_UNSPEC], >> + 3, "%d", i); > > This is not your fault actually. While at it, I have removed > -NFPROTO_UNSPEC (it's zero, so that substraction provides nothing). > Ok,thanks for your work :) >> + nf_log_sysctl_table[i].procname = >> + nf_log_sysctl_fnames[i-NFPROTO_UNSPEC]; >> + nf_log_sysctl_table[i].data = NULL; >> + nf_log_sysctl_table[i].maxlen = >> + NFLOGGER_NAME_LEN * sizeof(char); >> + nf_log_sysctl_table[i].mode = 0644; >> + nf_log_sysctl_table[i].proc_handler = >> + nf_log_proc_dostring; >> + nf_log_sysctl_table[i].extra1 = >> + (void *)(unsigned long) i; >> + } >> } >> >> - nf_log_dir_header = register_net_sysctl(&init_net, "net/netfilter/nf_log", >> - nf_log_sysctl_table); >> - if (!nf_log_dir_header) >> - return -ENOMEM; >> + net->nf.nf_log_dir_header = register_net_sysctl(net, >> + "net/netfilter/nf_log", >> + table); >> + if (!net->nf.nf_log_dir_header) >> + goto err_reg; >> >> return 0; >> +err_reg: >> + if (!net_eq(net, &init_net)) >> + kfree(table); >> +err_alloc: >> + return -ENOMEM; >> +} >> + >> +static void netfilter_log_sysctl_exit(struct net *net) >> +{ >> + struct ctl_table *table; >> + >> + table = net->nf.nf_log_dir_header->ctl_table_arg; >> + unregister_net_sysctl_table(net->nf.nf_log_dir_header); >> + if (!net_eq(net, &init_net)) >> + kfree(table); >> } >> #else >> -static __init int netfilter_log_sysctl_init(void) >> +static int netfilter_log_sysctl_init(struct net *net) >> { >> return 0; >> } >> + >> +static void netfilter_log_sysctl_exit(struct net *net) >> +{ >> +} >> #endif /* CONFIG_SYSCTL */ >> >> -int __init netfilter_log_init(void) >> +static int __net_init nf_log_net_init(struct net *net) >> { >> - int i, r; >> + int ret = -ENOMEM; >> #ifdef CONFIG_PROC_FS >> if (!proc_create("nf_log", S_IRUGO, >> - proc_net_netfilter, &nflog_file_ops)) >> - return -1; >> + net->nf.proc_netfilter, &nflog_file_ops)) >> + goto out_proc; >> #endif >> + ret = netfilter_log_sysctl_init(net); >> + if (ret < 0) >> + goto out_sysctl; >> + return 0; >> +out_sysctl: >> +#ifdef CONFIG_PROC_FS > > removed this ifdef. The function remove_proc_entry already defines an > empty function if CONFIG_PROC_FS is not set. > Thanks for the hand. >> + /* >> + * For init net, Erros will trigger panic, >> + * unrool on error is unnecessary, >> + */ > > Fixed English typos in this sentence. > >> + if (!net_eq(net, &init_net)) >> + remove_proc_entry("nf_log", net->nf.proc_netfilter); >> +out_proc: >> +#endif >> + return ret; >> +} >> + >> +static void __net_exit nf_log_net_exit(struct net *net) >> +{ >> + netfilter_log_sysctl_exit(net); >> + remove_proc_entry("nf_log", net->nf.proc_netfilter); >> +} >> >> - /* Errors will trigger panic, unroll on error is unnecessary. */ >> - r = netfilter_log_sysctl_init(); >> - if (r < 0) >> - return r; >> +static struct pernet_operations nf_log_net_ops = { >> + .init = nf_log_net_init, >> + .exit = nf_log_net_exit, >> +}; >> + >> +int __init netfilter_log_init(void) >> +{ >> + int i, ret; > > Please, add empty line after variable declaration next time. > Thanks again, I must miss this place... Thanks! ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH nf-next v2 03/10] netfilter: ebt_log: add net namespace support for ebt_log 2013-03-25 9:50 [PATCH nf-next v2 01/10] netfilter: make /proc/net/netfilter pernet Gao feng 2013-03-25 9:50 ` [PATCH nf-next v2 02/10] netfilter: nf_log: prepar net namespace support for nf_log Gao feng @ 2013-03-25 9:50 ` Gao feng 2013-04-05 18:32 ` Pablo Neira Ayuso 2013-03-25 9:50 ` [PATCH nf-next v2 04/10] netfilter: xt_LOG: add net namespace support for xt_LOG Gao feng ` (7 subsequent siblings) 9 siblings, 1 reply; 24+ messages in thread From: Gao feng @ 2013-03-25 9:50 UTC (permalink / raw) To: netfilter-devel; +Cc: pablo, Gao feng Add pernet_operations for ebt_log, in pernet_ops, we call nf_log_set/unset to set/unset nf_loggers of per net. Because the syslog ns has not been implemented, we don't want the container DDOS the host's syslog. so only enable ebt_log in init_net and wait for syslog ns. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- net/bridge/netfilter/ebt_log.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 08e5ea5..cd465d1 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -78,6 +78,10 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum, const char *prefix) { unsigned int bitmask; + struct net *net = dev_net(in ? in : out); + + if (!net_eq(net, &init_net)) + return; spin_lock_bh(&ebt_log_lock); printk(KERN_SOH "%c%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x", @@ -207,6 +211,22 @@ static struct nf_logger ebt_log_logger __read_mostly = { .me = THIS_MODULE, }; +static int __net_init ebt_log_net_init(struct net *net) +{ + nf_log_set(net, NFPROTO_BRIDGE, &ebt_log_logger); + return 0; +} + +static void __net_exit ebt_log_net_fini(struct net *net) +{ + nf_log_unset(net, &ebt_log_logger); +} + +static struct pernet_operations ebt_log_net_ops = { + .init = ebt_log_net_init, + .exit = ebt_log_net_fini, +}; + static int __init ebt_log_init(void) { int ret; @@ -214,12 +234,14 @@ static int __init ebt_log_init(void) ret = xt_register_target(&ebt_log_tg_reg); if (ret < 0) return ret; + nf_log_register(NFPROTO_BRIDGE, &ebt_log_logger); - return 0; + return register_pernet_subsys(&ebt_log_net_ops); } static void __exit ebt_log_fini(void) { + unregister_pernet_subsys(&ebt_log_net_ops); nf_log_unregister(&ebt_log_logger); xt_unregister_target(&ebt_log_tg_reg); } -- 1.7.11.7 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH nf-next v2 03/10] netfilter: ebt_log: add net namespace support for ebt_log 2013-03-25 9:50 ` [PATCH nf-next v2 03/10] netfilter: ebt_log: add net namespace support for ebt_log Gao feng @ 2013-04-05 18:32 ` Pablo Neira Ayuso 2013-04-08 2:50 ` Gao feng 0 siblings, 1 reply; 24+ messages in thread From: Pablo Neira Ayuso @ 2013-04-05 18:32 UTC (permalink / raw) To: Gao feng; +Cc: netfilter-devel On Mon, Mar 25, 2013 at 05:50:41PM +0800, Gao feng wrote: > Add pernet_operations for ebt_log, in pernet_ops, > we call nf_log_set/unset to set/unset nf_loggers > of per net. > > Because the syslog ns has not been implemented, > we don't want the container DDOS the host's syslog. > so only enable ebt_log in init_net and wait for > syslog ns. Applied with change. > Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> > --- > net/bridge/netfilter/ebt_log.c | 24 +++++++++++++++++++++++- > 1 file changed, 23 insertions(+), 1 deletion(-) > > diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c > index 08e5ea5..cd465d1 100644 > --- a/net/bridge/netfilter/ebt_log.c > +++ b/net/bridge/netfilter/ebt_log.c > @@ -78,6 +78,10 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum, > const char *prefix) > { > unsigned int bitmask; > + struct net *net = dev_net(in ? in : out); > + Added a comment here to explicitly recall that we depend on syslog ns support to remove these two lines below. > + if (!net_eq(net, &init_net)) > + return; > > spin_lock_bh(&ebt_log_lock); > printk(KERN_SOH "%c%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x", > @@ -207,6 +211,22 @@ static struct nf_logger ebt_log_logger __read_mostly = { > .me = THIS_MODULE, > }; > > +static int __net_init ebt_log_net_init(struct net *net) > +{ > + nf_log_set(net, NFPROTO_BRIDGE, &ebt_log_logger); > + return 0; > +} > + > +static void __net_exit ebt_log_net_fini(struct net *net) > +{ > + nf_log_unset(net, &ebt_log_logger); > +} > + > +static struct pernet_operations ebt_log_net_ops = { > + .init = ebt_log_net_init, > + .exit = ebt_log_net_fini, > +}; > + > static int __init ebt_log_init(void) > { > int ret; > @@ -214,12 +234,14 @@ static int __init ebt_log_init(void) > ret = xt_register_target(&ebt_log_tg_reg); > if (ret < 0) > return ret; > + > nf_log_register(NFPROTO_BRIDGE, &ebt_log_logger); > - return 0; > + return register_pernet_subsys(&ebt_log_net_ops); You have to unroll in case register_pernet_subsys, I fixed this. > } > > static void __exit ebt_log_fini(void) > { > + unregister_pernet_subsys(&ebt_log_net_ops); > nf_log_unregister(&ebt_log_logger); > xt_unregister_target(&ebt_log_tg_reg); > } > -- > 1.7.11.7 > ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH nf-next v2 03/10] netfilter: ebt_log: add net namespace support for ebt_log 2013-04-05 18:32 ` Pablo Neira Ayuso @ 2013-04-08 2:50 ` Gao feng 0 siblings, 0 replies; 24+ messages in thread From: Gao feng @ 2013-04-08 2:50 UTC (permalink / raw) To: Pablo Neira Ayuso; +Cc: netfilter-devel On 2013/04/06 02:32, Pablo Neira Ayuso wrote: > On Mon, Mar 25, 2013 at 05:50:41PM +0800, Gao feng wrote: >> Add pernet_operations for ebt_log, in pernet_ops, >> we call nf_log_set/unset to set/unset nf_loggers >> of per net. >> >> Because the syslog ns has not been implemented, >> we don't want the container DDOS the host's syslog. >> so only enable ebt_log in init_net and wait for >> syslog ns. > > Applied with change. > >> Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> >> --- >> net/bridge/netfilter/ebt_log.c | 24 +++++++++++++++++++++++- >> 1 file changed, 23 insertions(+), 1 deletion(-) >> >> diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c >> index 08e5ea5..cd465d1 100644 >> --- a/net/bridge/netfilter/ebt_log.c >> +++ b/net/bridge/netfilter/ebt_log.c >> @@ -78,6 +78,10 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum, >> const char *prefix) >> { >> unsigned int bitmask; >> + struct net *net = dev_net(in ? in : out); >> + > > Added a comment here to explicitly recall that we depend on syslog ns > support to remove these two lines below. > This is good, and I will note this too. >> + if (!net_eq(net, &init_net)) >> + return; >> >> spin_lock_bh(&ebt_log_lock); >> printk(KERN_SOH "%c%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x", >> @@ -207,6 +211,22 @@ static struct nf_logger ebt_log_logger __read_mostly = { >> .me = THIS_MODULE, >> }; >> >> +static int __net_init ebt_log_net_init(struct net *net) >> +{ >> + nf_log_set(net, NFPROTO_BRIDGE, &ebt_log_logger); >> + return 0; >> +} >> + >> +static void __net_exit ebt_log_net_fini(struct net *net) >> +{ >> + nf_log_unset(net, &ebt_log_logger); >> +} >> + >> +static struct pernet_operations ebt_log_net_ops = { >> + .init = ebt_log_net_init, >> + .exit = ebt_log_net_fini, >> +}; >> + >> static int __init ebt_log_init(void) >> { >> int ret; >> @@ -214,12 +234,14 @@ static int __init ebt_log_init(void) >> ret = xt_register_target(&ebt_log_tg_reg); >> if (ret < 0) >> return ret; >> + >> nf_log_register(NFPROTO_BRIDGE, &ebt_log_logger); >> - return 0; >> + return register_pernet_subsys(&ebt_log_net_ops); > > You have to unroll in case register_pernet_subsys, I fixed this. > This is my mistake,thanks for your fix :) ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH nf-next v2 04/10] netfilter: xt_LOG: add net namespace support for xt_LOG 2013-03-25 9:50 [PATCH nf-next v2 01/10] netfilter: make /proc/net/netfilter pernet Gao feng 2013-03-25 9:50 ` [PATCH nf-next v2 02/10] netfilter: nf_log: prepar net namespace support for nf_log Gao feng 2013-03-25 9:50 ` [PATCH nf-next v2 03/10] netfilter: ebt_log: add net namespace support for ebt_log Gao feng @ 2013-03-25 9:50 ` Gao feng 2013-04-05 18:33 ` Pablo Neira Ayuso 2013-03-25 9:50 ` [PATCH nf-next v2 05/10] netfilter: ebt_ulog: add net namesapce support for ebt_ulog Gao feng ` (6 subsequent siblings) 9 siblings, 1 reply; 24+ messages in thread From: Gao feng @ 2013-03-25 9:50 UTC (permalink / raw) To: netfilter-devel; +Cc: pablo, Gao feng Add pernet_operations for xt_LOG, in pernet_ops, we call nf_log_set/unset to set/unset nf_loggers of per net. Because the syslog ns has not been implemented, we don't want the container DDOS the host's syslog. so only enable ebt_log in init_net and wait for syslog ns. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- net/netfilter/xt_LOG.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c index fa40096..d396600 100644 --- a/net/netfilter/xt_LOG.c +++ b/net/netfilter/xt_LOG.c @@ -474,7 +474,13 @@ ipt_log_packet(u_int8_t pf, const struct nf_loginfo *loginfo, const char *prefix) { - struct sbuff *m = sb_open(); + struct sbuff *m; + struct net *net = dev_net(in ? in : out); + + if (!net_eq(net, &init_net)) + return; + + m = sb_open(); if (!loginfo) loginfo = &default_loginfo; @@ -798,7 +804,13 @@ ip6t_log_packet(u_int8_t pf, const struct nf_loginfo *loginfo, const char *prefix) { - struct sbuff *m = sb_open(); + struct sbuff *m; + struct net *net = dev_net(in ? in : out); + + if (!net_eq(net, &init_net)) + return; + + m = sb_open(); if (!loginfo) loginfo = &default_loginfo; @@ -893,6 +905,28 @@ static struct nf_logger ip6t_log_logger __read_mostly = { }; #endif +static int __net_init log_net_init(struct net *net) +{ + nf_log_set(net, NFPROTO_IPV4, &ipt_log_logger); +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) + nf_log_set(net, NFPROTO_IPV6, &ip6t_log_logger); +#endif + return 0; +} + +static void __net_exit log_net_exit(struct net *net) +{ + nf_log_unset(net, &ipt_log_logger); +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) + nf_log_unset(net, &ip6t_log_logger); +#endif +} + +static struct pernet_operations log_net_ops = { + .init = log_net_init, + .exit = log_net_exit, +}; + static int __init log_tg_init(void) { int ret; @@ -905,11 +939,12 @@ static int __init log_tg_init(void) #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) nf_log_register(NFPROTO_IPV6, &ip6t_log_logger); #endif - return 0; + return register_pernet_subsys(&log_net_ops); } static void __exit log_tg_exit(void) { + unregister_pernet_subsys(&log_net_ops); nf_log_unregister(&ipt_log_logger); #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) nf_log_unregister(&ip6t_log_logger); -- 1.7.11.7 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH nf-next v2 04/10] netfilter: xt_LOG: add net namespace support for xt_LOG 2013-03-25 9:50 ` [PATCH nf-next v2 04/10] netfilter: xt_LOG: add net namespace support for xt_LOG Gao feng @ 2013-04-05 18:33 ` Pablo Neira Ayuso 2013-04-08 2:50 ` Gao feng 0 siblings, 1 reply; 24+ messages in thread From: Pablo Neira Ayuso @ 2013-04-05 18:33 UTC (permalink / raw) To: Gao feng; +Cc: netfilter-devel On Mon, Mar 25, 2013 at 05:50:42PM +0800, Gao feng wrote: > Add pernet_operations for xt_LOG, in pernet_ops, > we call nf_log_set/unset to set/unset nf_loggers > of per net. > > Because the syslog ns has not been implemented, > we don't want the container DDOS the host's syslog. > so only enable ebt_log in init_net and wait for > syslog ns. Applied with change. > Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> > --- > net/netfilter/xt_LOG.c | 41 ++++++++++++++++++++++++++++++++++++++--- > 1 file changed, 38 insertions(+), 3 deletions(-) > > diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c > index fa40096..d396600 100644 > --- a/net/netfilter/xt_LOG.c > +++ b/net/netfilter/xt_LOG.c > @@ -474,7 +474,13 @@ ipt_log_packet(u_int8_t pf, > const struct nf_loginfo *loginfo, > const char *prefix) > { > - struct sbuff *m = sb_open(); > + struct sbuff *m; > + struct net *net = dev_net(in ? in : out); > + > + if (!net_eq(net, &init_net)) > + return; > + > + m = sb_open(); > > if (!loginfo) > loginfo = &default_loginfo; > @@ -798,7 +804,13 @@ ip6t_log_packet(u_int8_t pf, > const struct nf_loginfo *loginfo, > const char *prefix) > { > - struct sbuff *m = sb_open(); > + struct sbuff *m; > + struct net *net = dev_net(in ? in : out); > + Added comment here, as in ebt_log. > + if (!net_eq(net, &init_net)) > + return; > + > + m = sb_open(); > > if (!loginfo) > loginfo = &default_loginfo; > @@ -893,6 +905,28 @@ static struct nf_logger ip6t_log_logger __read_mostly = { > }; > #endif > > +static int __net_init log_net_init(struct net *net) > +{ > + nf_log_set(net, NFPROTO_IPV4, &ipt_log_logger); > +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) > + nf_log_set(net, NFPROTO_IPV6, &ip6t_log_logger); > +#endif > + return 0; > +} > + > +static void __net_exit log_net_exit(struct net *net) > +{ > + nf_log_unset(net, &ipt_log_logger); > +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) > + nf_log_unset(net, &ip6t_log_logger); > +#endif > +} > + > +static struct pernet_operations log_net_ops = { > + .init = log_net_init, > + .exit = log_net_exit, > +}; > + > static int __init log_tg_init(void) > { > int ret; > @@ -905,11 +939,12 @@ static int __init log_tg_init(void) > #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) > nf_log_register(NFPROTO_IPV6, &ip6t_log_logger); > #endif > - return 0; > + return register_pernet_subsys(&log_net_ops); You have to unroll if this fails. > } > > static void __exit log_tg_exit(void) > { > + unregister_pernet_subsys(&log_net_ops); > nf_log_unregister(&ipt_log_logger); > #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) > nf_log_unregister(&ip6t_log_logger); > -- > 1.7.11.7 > > -- > 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 [flat|nested] 24+ messages in thread
* Re: [PATCH nf-next v2 04/10] netfilter: xt_LOG: add net namespace support for xt_LOG 2013-04-05 18:33 ` Pablo Neira Ayuso @ 2013-04-08 2:50 ` Gao feng 0 siblings, 0 replies; 24+ messages in thread From: Gao feng @ 2013-04-08 2:50 UTC (permalink / raw) To: Pablo Neira Ayuso; +Cc: netfilter-devel On 2013/04/06 02:33, Pablo Neira Ayuso wrote: > On Mon, Mar 25, 2013 at 05:50:42PM +0800, Gao feng wrote: >> Add pernet_operations for xt_LOG, in pernet_ops, >> we call nf_log_set/unset to set/unset nf_loggers >> of per net. >> >> Because the syslog ns has not been implemented, >> we don't want the container DDOS the host's syslog. >> so only enable ebt_log in init_net and wait for >> syslog ns. > > Applied with change. > >> Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> >> --- >> net/netfilter/xt_LOG.c | 41 ++++++++++++++++++++++++++++++++++++++--- >> 1 file changed, 38 insertions(+), 3 deletions(-) >> >> diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c >> index fa40096..d396600 100644 >> --- a/net/netfilter/xt_LOG.c >> +++ b/net/netfilter/xt_LOG.c >> @@ -474,7 +474,13 @@ ipt_log_packet(u_int8_t pf, >> const struct nf_loginfo *loginfo, >> const char *prefix) >> { >> - struct sbuff *m = sb_open(); >> + struct sbuff *m; >> + struct net *net = dev_net(in ? in : out); >> + >> + if (!net_eq(net, &init_net)) >> + return; >> + >> + m = sb_open(); >> >> if (!loginfo) >> loginfo = &default_loginfo; >> @@ -798,7 +804,13 @@ ip6t_log_packet(u_int8_t pf, >> const struct nf_loginfo *loginfo, >> const char *prefix) >> { >> - struct sbuff *m = sb_open(); >> + struct sbuff *m; >> + struct net *net = dev_net(in ? in : out); >> + > > Added comment here, as in ebt_log. > >> + if (!net_eq(net, &init_net)) >> + return; >> + >> + m = sb_open(); >> >> if (!loginfo) >> loginfo = &default_loginfo; >> @@ -893,6 +905,28 @@ static struct nf_logger ip6t_log_logger __read_mostly = { >> }; >> #endif >> >> +static int __net_init log_net_init(struct net *net) >> +{ >> + nf_log_set(net, NFPROTO_IPV4, &ipt_log_logger); >> +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) >> + nf_log_set(net, NFPROTO_IPV6, &ip6t_log_logger); >> +#endif >> + return 0; >> +} >> + >> +static void __net_exit log_net_exit(struct net *net) >> +{ >> + nf_log_unset(net, &ipt_log_logger); >> +#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) >> + nf_log_unset(net, &ip6t_log_logger); >> +#endif >> +} >> + >> +static struct pernet_operations log_net_ops = { >> + .init = log_net_init, >> + .exit = log_net_exit, >> +}; >> + >> static int __init log_tg_init(void) >> { >> int ret; >> @@ -905,11 +939,12 @@ static int __init log_tg_init(void) >> #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) >> nf_log_register(NFPROTO_IPV6, &ip6t_log_logger); >> #endif >> - return 0; >> + return register_pernet_subsys(&log_net_ops); > > You have to unroll if this fails. > Thanks again :) ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH nf-next v2 05/10] netfilter: ebt_ulog: add net namesapce support for ebt_ulog 2013-03-25 9:50 [PATCH nf-next v2 01/10] netfilter: make /proc/net/netfilter pernet Gao feng ` (2 preceding siblings ...) 2013-03-25 9:50 ` [PATCH nf-next v2 04/10] netfilter: xt_LOG: add net namespace support for xt_LOG Gao feng @ 2013-03-25 9:50 ` Gao feng 2013-04-05 18:34 ` Pablo Neira Ayuso 2013-03-25 9:50 ` [PATCH nf-next v2 06/10] netfilter: ipt_ulog: add net namespace support for ipt_ulog Gao feng ` (5 subsequent siblings) 9 siblings, 1 reply; 24+ messages in thread From: Gao feng @ 2013-03-25 9:50 UTC (permalink / raw) To: netfilter-devel; +Cc: pablo, Gao feng Add pernet_operations for ebt_ulog, in pernet_ops, we call nf_log_set/unset to set/unset nf_loggers of per net. This patch also make ulog_buffers and netlink socket ebtulognl per netns. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- net/bridge/netfilter/ebt_ulog.c | 125 ++++++++++++++++++++++++++++------------ 1 file changed, 88 insertions(+), 37 deletions(-) diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index 442b032..0ddd612 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -41,6 +41,7 @@ #include <linux/netfilter_bridge/ebtables.h> #include <linux/netfilter_bridge/ebt_ulog.h> #include <net/netfilter/nf_log.h> +#include <net/netns/generic.h> #include <net/sock.h> #include "../br_private.h" @@ -62,13 +63,22 @@ typedef struct { spinlock_t lock; /* the per-queue lock */ } ebt_ulog_buff_t; -static ebt_ulog_buff_t ulog_buffers[EBT_ULOG_MAXNLGROUPS]; -static struct sock *ebtulognl; +static int ebt_ulog_net_id __read_mostly; +struct ebt_ulog_net { + unsigned int nlgroup[EBT_ULOG_MAXNLGROUPS]; + ebt_ulog_buff_t ulog_buffers[EBT_ULOG_MAXNLGROUPS]; + struct sock *ebtulognl; +}; + +static struct ebt_ulog_net *ebt_ulog_pernet(struct net *net) +{ + return net_generic(net, ebt_ulog_net_id); +} /* send one ulog_buff_t to userspace */ -static void ulog_send(unsigned int nlgroup) +static void ulog_send(struct ebt_ulog_net *ebt, unsigned int nlgroup) { - ebt_ulog_buff_t *ub = &ulog_buffers[nlgroup]; + ebt_ulog_buff_t *ub = &ebt->ulog_buffers[nlgroup]; del_timer(&ub->timer); @@ -80,7 +90,7 @@ static void ulog_send(unsigned int nlgroup) ub->lastnlh->nlmsg_type = NLMSG_DONE; NETLINK_CB(ub->skb).dst_group = nlgroup + 1; - netlink_broadcast(ebtulognl, ub->skb, 0, nlgroup + 1, GFP_ATOMIC); + netlink_broadcast(ebt->ebtulognl, ub->skb, 0, nlgroup + 1, GFP_ATOMIC); ub->qlen = 0; ub->skb = NULL; @@ -89,10 +99,15 @@ static void ulog_send(unsigned int nlgroup) /* timer function to flush queue in flushtimeout time */ static void ulog_timer(unsigned long data) { - spin_lock_bh(&ulog_buffers[data].lock); - if (ulog_buffers[data].skb) - ulog_send(data); - spin_unlock_bh(&ulog_buffers[data].lock); + struct ebt_ulog_net *ebt = container_of((void *)data, + struct ebt_ulog_net, + nlgroup[*(unsigned int *)data]); + + ebt_ulog_buff_t *ub = &ebt->ulog_buffers[*(unsigned int *)data]; + spin_lock_bh(&ub->lock); + if (ub->skb) + ulog_send(ebt, *(unsigned int *)data); + spin_unlock_bh(&ub->lock); } static struct sk_buff *ulog_alloc_skb(unsigned int size) @@ -123,8 +138,10 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb, ebt_ulog_packet_msg_t *pm; size_t size, copy_len; struct nlmsghdr *nlh; + struct net *net = dev_net(in ? in : out); + struct ebt_ulog_net *ebt = ebt_ulog_pernet(net); unsigned int group = uloginfo->nlgroup; - ebt_ulog_buff_t *ub = &ulog_buffers[group]; + ebt_ulog_buff_t *ub = &ebt->ulog_buffers[group]; spinlock_t *lock = &ub->lock; ktime_t kt; @@ -146,7 +163,7 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb, if (!(ub->skb = ulog_alloc_skb(size))) goto unlock; } else if (size > skb_tailroom(ub->skb)) { - ulog_send(group); + ulog_send(ebt, group); if (!(ub->skb = ulog_alloc_skb(size))) goto unlock; @@ -205,7 +222,7 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb, ub->lastnlh = nlh; if (ub->qlen >= uloginfo->qthreshold) - ulog_send(group); + ulog_send(ebt, group); else if (!timer_pending(&ub->timer)) { ub->timer.expires = jiffies + flushtimeout * HZ / 100; add_timer(&ub->timer); @@ -277,47 +294,39 @@ static struct nf_logger ebt_ulog_logger __read_mostly = { .me = THIS_MODULE, }; -static int __init ebt_ulog_init(void) +static int __net_init ebt_ulog_net_init(struct net *net) { - int ret; int i; + struct ebt_ulog_net *ebt = ebt_ulog_pernet(net); + struct netlink_kernel_cfg cfg = { .groups = EBT_ULOG_MAXNLGROUPS, }; - if (nlbufsiz >= 128*1024) { - pr_warning("Netlink buffer has to be <= 128kB," - " please try a smaller nlbufsiz parameter.\n"); - return -EINVAL; - } - /* initialize ulog_buffers */ for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { - setup_timer(&ulog_buffers[i].timer, ulog_timer, i); - spin_lock_init(&ulog_buffers[i].lock); + ebt->nlgroup[i] = i; + setup_timer(&ebt->ulog_buffers[i].timer, ulog_timer, + (unsigned long)&ebt->nlgroup[i]); + spin_lock_init(&ebt->ulog_buffers[i].lock); } - ebtulognl = netlink_kernel_create(&init_net, NETLINK_NFLOG, &cfg); - if (!ebtulognl) - ret = -ENOMEM; - else if ((ret = xt_register_target(&ebt_ulog_tg_reg)) != 0) - netlink_kernel_release(ebtulognl); + ebt->ebtulognl = netlink_kernel_create(net, NETLINK_NFLOG, &cfg); + if (!ebt->ebtulognl) + return -ENOMEM; - if (ret == 0) - nf_log_register(NFPROTO_BRIDGE, &ebt_ulog_logger); - - return ret; + nf_log_set(net, NFPROTO_BRIDGE, &ebt_ulog_logger); + return 0; } -static void __exit ebt_ulog_fini(void) +static void __net_exit ebt_ulog_net_fini(struct net *net) { - ebt_ulog_buff_t *ub; int i; + struct ebt_ulog_net *ebt = ebt_ulog_pernet(net); - nf_log_unregister(&ebt_ulog_logger); - xt_unregister_target(&ebt_ulog_tg_reg); + nf_log_unset(net, &ebt_ulog_logger); for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { - ub = &ulog_buffers[i]; + ebt_ulog_buff_t *ub = &ebt->ulog_buffers[i]; del_timer(&ub->timer); if (ub->skb) { @@ -325,7 +334,49 @@ static void __exit ebt_ulog_fini(void) ub->skb = NULL; } } - netlink_kernel_release(ebtulognl); + netlink_kernel_release(ebt->ebtulognl); +} + +static struct pernet_operations ebt_ulog_net_ops = { + .init = ebt_ulog_net_init, + .exit = ebt_ulog_net_fini, + .id = &ebt_ulog_net_id, + .size = sizeof(struct ebt_ulog_net), +}; + +static int __init ebt_ulog_init(void) +{ + int ret; + + if (nlbufsiz >= 128*1024) { + pr_warn("Netlink buffer has to be <= 128kB," + "please try a smaller nlbufsiz parameter.\n"); + return -EINVAL; + } + + ret = register_pernet_subsys(&ebt_ulog_net_ops); + if (ret) + goto out_pernet; + + ret = xt_register_target(&ebt_ulog_tg_reg); + if (ret) + goto out_target; + + nf_log_register(NFPROTO_BRIDGE, &ebt_ulog_logger); + + return 0; + +out_target: + unregister_pernet_subsys(&ebt_ulog_net_ops); +out_pernet: + return ret; +} + +static void __exit ebt_ulog_fini(void) +{ + nf_log_unregister(&ebt_ulog_logger); + xt_unregister_target(&ebt_ulog_tg_reg); + unregister_pernet_subsys(&ebt_ulog_net_ops); } module_init(ebt_ulog_init); -- 1.7.11.7 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH nf-next v2 05/10] netfilter: ebt_ulog: add net namesapce support for ebt_ulog 2013-03-25 9:50 ` [PATCH nf-next v2 05/10] netfilter: ebt_ulog: add net namesapce support for ebt_ulog Gao feng @ 2013-04-05 18:34 ` Pablo Neira Ayuso 0 siblings, 0 replies; 24+ messages in thread From: Pablo Neira Ayuso @ 2013-04-05 18:34 UTC (permalink / raw) To: Gao feng; +Cc: netfilter-devel On Mon, Mar 25, 2013 at 05:50:43PM +0800, Gao feng wrote: > Add pernet_operations for ebt_ulog, in pernet_ops, > we call nf_log_set/unset to set/unset nf_loggers > of per net. > > This patch also make ulog_buffers and netlink socket > ebtulognl per netns. Applied, thanks. In this patch the unroll in case register_pernet_subsys is fine. ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH nf-next v2 06/10] netfilter: ipt_ulog: add net namespace support for ipt_ulog 2013-03-25 9:50 [PATCH nf-next v2 01/10] netfilter: make /proc/net/netfilter pernet Gao feng ` (3 preceding siblings ...) 2013-03-25 9:50 ` [PATCH nf-next v2 05/10] netfilter: ebt_ulog: add net namesapce support for ebt_ulog Gao feng @ 2013-03-25 9:50 ` Gao feng 2013-04-05 18:35 ` Pablo Neira Ayuso 2013-03-25 9:50 ` [PATCH nf-next v2 07/10] netfilter: nfnetlink_log: add net namespace support for nfnetlink_log Gao feng ` (4 subsequent siblings) 9 siblings, 1 reply; 24+ messages in thread From: Gao feng @ 2013-03-25 9:50 UTC (permalink / raw) To: netfilter-devel; +Cc: pablo, Gao feng Add pernet_operations for ipt_ulog, in pernet_ops, we call nf_log_set/unset to set/unset nf_loggers of per net. This patch also make ulog_buffers and netlink socket nflognl per netns. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- net/ipv4/netfilter/ipt_ULOG.c | 130 +++++++++++++++++++++++++++++------------- 1 file changed, 89 insertions(+), 41 deletions(-) diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 7d168dc..745fdc6 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c @@ -45,6 +45,7 @@ #include <linux/netfilter/x_tables.h> #include <linux/netfilter_ipv4/ipt_ULOG.h> #include <net/netfilter/nf_log.h> +#include <net/netns/generic.h> #include <net/sock.h> #include <linux/bitops.h> #include <asm/unaligned.h> @@ -78,15 +79,23 @@ typedef struct { struct timer_list timer; /* the timer function */ } ulog_buff_t; -static ulog_buff_t ulog_buffers[ULOG_MAXNLGROUPS]; /* array of buffers */ +static int ulog_net_id __read_mostly; +struct ulog_net { + unsigned int nlgroup[ULOG_MAXNLGROUPS]; + ulog_buff_t ulog_buffers[ULOG_MAXNLGROUPS]; + struct sock *nflognl; + spinlock_t lock; +}; -static struct sock *nflognl; /* our socket */ -static DEFINE_SPINLOCK(ulog_lock); /* spinlock */ +static struct ulog_net *ulog_pernet(struct net *net) +{ + return net_generic(net, ulog_net_id); +} /* send one ulog_buff_t to userspace */ -static void ulog_send(unsigned int nlgroupnum) +static void ulog_send(struct ulog_net *ulog, unsigned int nlgroupnum) { - ulog_buff_t *ub = &ulog_buffers[nlgroupnum]; + ulog_buff_t *ub = &ulog->ulog_buffers[nlgroupnum]; pr_debug("ulog_send: timer is deleting\n"); del_timer(&ub->timer); @@ -103,7 +112,8 @@ static void ulog_send(unsigned int nlgroupnum) NETLINK_CB(ub->skb).dst_group = nlgroupnum + 1; pr_debug("throwing %d packets to netlink group %u\n", ub->qlen, nlgroupnum + 1); - netlink_broadcast(nflognl, ub->skb, 0, nlgroupnum + 1, GFP_ATOMIC); + netlink_broadcast(ulog->nflognl, ub->skb, 0, nlgroupnum + 1, + GFP_ATOMIC); ub->qlen = 0; ub->skb = NULL; @@ -114,13 +124,16 @@ static void ulog_send(unsigned int nlgroupnum) /* timer function to flush queue in flushtimeout time */ static void ulog_timer(unsigned long data) { + struct ulog_net *ulog = container_of((void *)data, + struct ulog_net, + nlgroup[*(unsigned int *)data]); pr_debug("timer function called, calling ulog_send\n"); /* lock to protect against somebody modifying our structure * from ipt_ulog_target at the same time */ - spin_lock_bh(&ulog_lock); - ulog_send(data); - spin_unlock_bh(&ulog_lock); + spin_lock_bh(&ulog->lock); + ulog_send(ulog, data); + spin_unlock_bh(&ulog->lock); } static struct sk_buff *ulog_alloc_skb(unsigned int size) @@ -160,6 +173,8 @@ static void ipt_ulog_packet(unsigned int hooknum, size_t size, copy_len; struct nlmsghdr *nlh; struct timeval tv; + struct net *net = dev_net(in ? in : out); + struct ulog_net *ulog = ulog_pernet(net); /* ffs == find first bit set, necessary because userspace * is already shifting groupnumber, but we need unshifted. @@ -174,9 +189,9 @@ static void ipt_ulog_packet(unsigned int hooknum, size = NLMSG_SPACE(sizeof(*pm) + copy_len); - ub = &ulog_buffers[groupnum]; + ub = &ulog->ulog_buffers[groupnum]; - spin_lock_bh(&ulog_lock); + spin_lock_bh(&ulog->lock); if (!ub->skb) { if (!(ub->skb = ulog_alloc_skb(size))) @@ -186,7 +201,7 @@ static void ipt_ulog_packet(unsigned int hooknum, /* either the queue len is too high or we don't have * enough room in nlskb left. send it to userspace. */ - ulog_send(groupnum); + ulog_send(ulog, groupnum); if (!(ub->skb = ulog_alloc_skb(size))) goto alloc_failure; @@ -260,16 +275,16 @@ static void ipt_ulog_packet(unsigned int hooknum, if (ub->qlen >= loginfo->qthreshold) { if (loginfo->qthreshold > 1) nlh->nlmsg_type = NLMSG_DONE; - ulog_send(groupnum); + ulog_send(ulog, groupnum); } out_unlock: - spin_unlock_bh(&ulog_lock); + spin_unlock_bh(&ulog->lock); return; alloc_failure: pr_debug("Error building netlink message\n"); - spin_unlock_bh(&ulog_lock); + spin_unlock_bh(&ulog->lock); } static unsigned int @@ -376,54 +391,43 @@ static struct nf_logger ipt_ulog_logger __read_mostly = { .me = THIS_MODULE, }; -static int __init ulog_tg_init(void) +static int __net_init ulog_tg_net_init(struct net *net) { - int ret, i; + int i; + struct ulog_net *ulog = ulog_pernet(net); + struct netlink_kernel_cfg cfg = { .groups = ULOG_MAXNLGROUPS, }; - pr_debug("init module\n"); - - if (nlbufsiz > 128*1024) { - pr_warning("Netlink buffer has to be <= 128kB\n"); - return -EINVAL; - } - + spin_lock_init(&ulog->lock); /* initialize ulog_buffers */ for (i = 0; i < ULOG_MAXNLGROUPS; i++) - setup_timer(&ulog_buffers[i].timer, ulog_timer, i); + setup_timer(&ulog->ulog_buffers[i].timer, ulog_timer, i); - nflognl = netlink_kernel_create(&init_net, NETLINK_NFLOG, &cfg); - if (!nflognl) + ulog->nflognl = netlink_kernel_create(net, NETLINK_NFLOG, &cfg); + if (!ulog->nflognl) return -ENOMEM; - ret = xt_register_target(&ulog_tg_reg); - if (ret < 0) { - netlink_kernel_release(nflognl); - return ret; - } if (nflog) - nf_log_register(NFPROTO_IPV4, &ipt_ulog_logger); - + nf_log_set(net, NFPROTO_IPV4, &ipt_ulog_logger); return 0; } -static void __exit ulog_tg_exit(void) +static void __net_exit ulog_tg_net_exit(struct net *net) { ulog_buff_t *ub; int i; - - pr_debug("cleanup_module\n"); + struct ulog_net *ulog = ulog_pernet(net); if (nflog) - nf_log_unregister(&ipt_ulog_logger); - xt_unregister_target(&ulog_tg_reg); - netlink_kernel_release(nflognl); + nf_log_unset(net, &ipt_ulog_logger); + + netlink_kernel_release(ulog->nflognl); /* remove pending timers and free allocated skb's */ for (i = 0; i < ULOG_MAXNLGROUPS; i++) { - ub = &ulog_buffers[i]; + ub = &ulog->ulog_buffers[i]; pr_debug("timer is deleting\n"); del_timer(&ub->timer); @@ -434,5 +438,49 @@ static void __exit ulog_tg_exit(void) } } +static struct pernet_operations ulog_tg_net_ops = { + .init = ulog_tg_net_init, + .exit = ulog_tg_net_exit, + .id = &ulog_net_id, + .size = sizeof(struct ulog_net), +}; + +static int __init ulog_tg_init(void) +{ + int ret; + pr_debug("init module\n"); + + if (nlbufsiz > 128*1024) { + pr_warn("Netlink buffer has to be <= 128kB\n"); + return -EINVAL; + } + + ret = register_pernet_subsys(&ulog_tg_net_ops); + if (ret) + goto out_pernet; + + ret = xt_register_target(&ulog_tg_reg); + if (ret < 0) + goto out_target; + + if (nflog) + nf_log_register(NFPROTO_IPV4, &ipt_ulog_logger); + + return 0; +out_target: + unregister_pernet_subsys(&ulog_tg_net_ops); +out_pernet: + return ret; +} + +static void __exit ulog_tg_exit(void) +{ + pr_debug("cleanup_module\n"); + if (nflog) + nf_log_unregister(&ipt_ulog_logger); + xt_unregister_target(&ulog_tg_reg); + unregister_pernet_subsys(&ulog_tg_net_ops); +} + module_init(ulog_tg_init); module_exit(ulog_tg_exit); -- 1.7.11.7 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH nf-next v2 06/10] netfilter: ipt_ulog: add net namespace support for ipt_ulog 2013-03-25 9:50 ` [PATCH nf-next v2 06/10] netfilter: ipt_ulog: add net namespace support for ipt_ulog Gao feng @ 2013-04-05 18:35 ` Pablo Neira Ayuso 0 siblings, 0 replies; 24+ messages in thread From: Pablo Neira Ayuso @ 2013-04-05 18:35 UTC (permalink / raw) To: Gao feng; +Cc: netfilter-devel On Mon, Mar 25, 2013 at 05:50:44PM +0800, Gao feng wrote: > Add pernet_operations for ipt_ulog, in pernet_ops, > we call nf_log_set/unset to set/unset nf_loggers > of per net. > > This patch also make ulog_buffers and netlink socket > nflognl per netns. Applied, thanks. ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH nf-next v2 07/10] netfilter: nfnetlink_log: add net namespace support for nfnetlink_log 2013-03-25 9:50 [PATCH nf-next v2 01/10] netfilter: make /proc/net/netfilter pernet Gao feng ` (4 preceding siblings ...) 2013-03-25 9:50 ` [PATCH nf-next v2 06/10] netfilter: ipt_ulog: add net namespace support for ipt_ulog Gao feng @ 2013-03-25 9:50 ` Gao feng 2013-04-05 18:38 ` Pablo Neira Ayuso 2013-03-25 9:50 ` [PATCH nf-next v2 08/10] netfilter: nf_log: enable nflog in un-init net namespace Gao feng ` (3 subsequent siblings) 9 siblings, 1 reply; 24+ messages in thread From: Gao feng @ 2013-03-25 9:50 UTC (permalink / raw) To: netfilter-devel; +Cc: pablo, Gao feng This patch makes /proc/net/netfilter/nfnetlink_log pernet, and netns has it's own instance table and lock. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- net/netfilter/nfnetlink_log.c | 176 +++++++++++++++++++++++++++--------------- 1 file changed, 114 insertions(+), 62 deletions(-) diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index b593fd1..75a8244 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -32,6 +32,7 @@ #include <linux/slab.h> #include <net/sock.h> #include <net/netfilter/nf_log.h> +#include <net/netns/generic.h> #include <net/netfilter/nfnetlink_log.h> #include <linux/atomic.h> @@ -56,6 +57,7 @@ struct nfulnl_instance { unsigned int qlen; /* number of nlmsgs in skb */ struct sk_buff *skb; /* pre-allocatd skb */ struct timer_list timer; + struct net *net; struct user_namespace *peer_user_ns; /* User namespace of the peer process */ int peer_portid; /* PORTID of the peer process */ @@ -71,25 +73,33 @@ struct nfulnl_instance { struct rcu_head rcu; }; -static DEFINE_SPINLOCK(instances_lock); -static atomic_t global_seq; - #define INSTANCE_BUCKETS 16 -static struct hlist_head instance_table[INSTANCE_BUCKETS]; static unsigned int hash_init; +static int nfnl_log_net_id __read_mostly; +struct nfnl_log_net { + spinlock_t instances_lock; + struct hlist_head instance_table[INSTANCE_BUCKETS]; + atomic_t global_seq; +}; + +static struct nfnl_log_net *nfnl_log_pernet(struct net *net) +{ + return net_generic(net, nfnl_log_net_id); +} + static inline u_int8_t instance_hashfn(u_int16_t group_num) { return ((group_num & 0xff) % INSTANCE_BUCKETS); } static struct nfulnl_instance * -__instance_lookup(u_int16_t group_num) +__instance_lookup(struct nfnl_log_net *log, u_int16_t group_num) { struct hlist_head *head; struct nfulnl_instance *inst; - head = &instance_table[instance_hashfn(group_num)]; + head = &log->instance_table[instance_hashfn(group_num)]; hlist_for_each_entry_rcu(inst, head, hlist) { if (inst->group_num == group_num) return inst; @@ -104,12 +114,12 @@ instance_get(struct nfulnl_instance *inst) } static struct nfulnl_instance * -instance_lookup_get(u_int16_t group_num) +instance_lookup_get(struct nfnl_log_net *log, u_int16_t group_num) { struct nfulnl_instance *inst; rcu_read_lock_bh(); - inst = __instance_lookup(group_num); + inst = __instance_lookup(log, group_num); if (inst && !atomic_inc_not_zero(&inst->use)) inst = NULL; rcu_read_unlock_bh(); @@ -119,7 +129,11 @@ instance_lookup_get(u_int16_t group_num) static void nfulnl_instance_free_rcu(struct rcu_head *head) { - kfree(container_of(head, struct nfulnl_instance, rcu)); + struct nfulnl_instance *inst; + inst = container_of(head, struct nfulnl_instance, rcu); + + put_net(inst->net); + kfree(inst); module_put(THIS_MODULE); } @@ -133,13 +147,15 @@ instance_put(struct nfulnl_instance *inst) static void nfulnl_timer(unsigned long data); static struct nfulnl_instance * -instance_create(u_int16_t group_num, int portid, struct user_namespace *user_ns) +instance_create(struct net *net, u_int16_t group_num, + int portid, struct user_namespace *user_ns) { struct nfulnl_instance *inst; + struct nfnl_log_net *log = nfnl_log_pernet(net); int err; - spin_lock_bh(&instances_lock); - if (__instance_lookup(group_num)) { + spin_lock_bh(&log->instances_lock); + if (__instance_lookup(log, group_num)) { err = -EEXIST; goto out_unlock; } @@ -162,7 +178,7 @@ instance_create(u_int16_t group_num, int portid, struct user_namespace *user_ns) atomic_set(&inst->use, 2); setup_timer(&inst->timer, nfulnl_timer, (unsigned long)inst); - + inst->net = get_net(net); inst->peer_user_ns = user_ns; inst->peer_portid = portid; inst->group_num = group_num; @@ -174,14 +190,15 @@ instance_create(u_int16_t group_num, int portid, struct user_namespace *user_ns) inst->copy_range = NFULNL_COPY_RANGE_MAX; hlist_add_head_rcu(&inst->hlist, - &instance_table[instance_hashfn(group_num)]); + &log->instance_table[instance_hashfn(group_num)]); - spin_unlock_bh(&instances_lock); + + spin_unlock_bh(&log->instances_lock); return inst; out_unlock: - spin_unlock_bh(&instances_lock); + spin_unlock_bh(&log->instances_lock); return ERR_PTR(err); } @@ -210,11 +227,12 @@ __instance_destroy(struct nfulnl_instance *inst) } static inline void -instance_destroy(struct nfulnl_instance *inst) +instance_destroy(struct nfnl_log_net *log, + struct nfulnl_instance *inst) { - spin_lock_bh(&instances_lock); + spin_lock_bh(&log->instances_lock); __instance_destroy(inst); - spin_unlock_bh(&instances_lock); + spin_unlock_bh(&log->instances_lock); } static int @@ -336,7 +354,7 @@ __nfulnl_send(struct nfulnl_instance *inst) if (!nlh) goto out; } - status = nfnetlink_unicast(inst->skb, &init_net, inst->peer_portid, + status = nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid, MSG_DONTWAIT); inst->qlen = 0; @@ -370,7 +388,8 @@ nfulnl_timer(unsigned long data) /* This is an inline function, we don't really care about a long * list of arguments */ static inline int -__build_packet_message(struct nfulnl_instance *inst, +__build_packet_message(struct nfnl_log_net *log, + struct nfulnl_instance *inst, const struct sk_buff *skb, unsigned int data_len, u_int8_t pf, @@ -536,7 +555,7 @@ __build_packet_message(struct nfulnl_instance *inst, /* global sequence number */ if ((inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) && nla_put_be32(inst->skb, NFULA_SEQ_GLOBAL, - htonl(atomic_inc_return(&global_seq)))) + htonl(atomic_inc_return(&log->global_seq)))) goto nla_put_failure; if (data_len) { @@ -592,13 +611,15 @@ nfulnl_log_packet(u_int8_t pf, const struct nf_loginfo *li; unsigned int qthreshold; unsigned int plen; + struct net *net = dev_net(in ? in : out); + struct nfnl_log_net *log = nfnl_log_pernet(net); if (li_user && li_user->type == NF_LOG_TYPE_ULOG) li = li_user; else li = &default_loginfo; - inst = instance_lookup_get(li->u.ulog.group); + inst = instance_lookup_get(log, li->u.ulog.group); if (!inst) return; @@ -680,7 +701,7 @@ nfulnl_log_packet(u_int8_t pf, inst->qlen++; - __build_packet_message(inst, skb, data_len, pf, + __build_packet_message(log, inst, skb, data_len, pf, hooknum, in, out, prefix, plen); if (inst->qlen >= qthreshold) @@ -709,24 +730,24 @@ nfulnl_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr) { struct netlink_notify *n = ptr; + struct nfnl_log_net *log = nfnl_log_pernet(n->net); if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) { int i; /* destroy all instances for this portid */ - spin_lock_bh(&instances_lock); + spin_lock_bh(&log->instances_lock); for (i = 0; i < INSTANCE_BUCKETS; i++) { struct hlist_node *t2; struct nfulnl_instance *inst; - struct hlist_head *head = &instance_table[i]; + struct hlist_head *head = &log->instance_table[i]; hlist_for_each_entry_safe(inst, t2, head, hlist) { - if ((net_eq(n->net, &init_net)) && - (n->portid == inst->peer_portid)) + if (n->portid == inst->peer_portid) __instance_destroy(inst); } } - spin_unlock_bh(&instances_lock); + spin_unlock_bh(&log->instances_lock); } return NOTIFY_DONE; } @@ -768,6 +789,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, struct nfulnl_instance *inst; struct nfulnl_msg_config_cmd *cmd = NULL; struct net *net = sock_net(ctnl); + struct nfnl_log_net *log = nfnl_log_pernet(net); int ret = 0; if (nfula[NFULA_CFG_CMD]) { @@ -784,7 +806,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, } } - inst = instance_lookup_get(group_num); + inst = instance_lookup_get(log, group_num); if (inst && inst->peer_portid != NETLINK_CB(skb).portid) { ret = -EPERM; goto out_put; @@ -798,7 +820,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, goto out_put; } - inst = instance_create(group_num, + inst = instance_create(net, group_num, NETLINK_CB(skb).portid, sk_user_ns(NETLINK_CB(skb).ssk)); if (IS_ERR(inst)) { @@ -812,7 +834,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, goto out; } - instance_destroy(inst); + instance_destroy(log, inst); goto out_put; default: ret = -ENOTSUPP; @@ -895,55 +917,66 @@ static const struct nfnetlink_subsystem nfulnl_subsys = { #ifdef CONFIG_PROC_FS struct iter_state { + struct seq_net_private p; unsigned int bucket; }; -static struct hlist_node *get_first(struct iter_state *st) +static struct hlist_node *get_first(struct net *net, struct iter_state *st) { + struct nfnl_log_net *log; if (!st) return NULL; + log = nfnl_log_pernet(net); + for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { - if (!hlist_empty(&instance_table[st->bucket])) - return rcu_dereference_bh(hlist_first_rcu(&instance_table[st->bucket])); + struct hlist_head *head = &log->instance_table[st->bucket]; + if (!hlist_empty(head)) + return rcu_dereference_bh(hlist_first_rcu(head)); } return NULL; } -static struct hlist_node *get_next(struct iter_state *st, struct hlist_node *h) +static struct hlist_node *get_next(struct net *net, struct iter_state *st, + struct hlist_node *h) { h = rcu_dereference_bh(hlist_next_rcu(h)); while (!h) { + struct nfnl_log_net *log; + struct hlist_head *head; if (++st->bucket >= INSTANCE_BUCKETS) return NULL; - h = rcu_dereference_bh(hlist_first_rcu(&instance_table[st->bucket])); + log = nfnl_log_pernet(net); + head = &log->instance_table[st->bucket]; + h = rcu_dereference_bh(hlist_first_rcu(head)); } return h; } -static struct hlist_node *get_idx(struct iter_state *st, loff_t pos) +static struct hlist_node *get_idx(struct net *net, struct iter_state *st, + loff_t pos) { struct hlist_node *head; - head = get_first(st); + head = get_first(net, st); if (head) - while (pos && (head = get_next(st, head))) + while (pos && (head = get_next(net, st, head))) pos--; return pos ? NULL : head; } -static void *seq_start(struct seq_file *seq, loff_t *pos) +static void *seq_start(struct seq_file *s, loff_t *pos) __acquires(rcu_bh) { rcu_read_lock_bh(); - return get_idx(seq->private, *pos); + return get_idx(seq_file_net(s), s->private, *pos); } static void *seq_next(struct seq_file *s, void *v, loff_t *pos) { (*pos)++; - return get_next(s->private, v); + return get_next(seq_file_net(s), s->private, v); } static void seq_stop(struct seq_file *s, void *v) @@ -972,8 +1005,8 @@ static const struct seq_operations nful_seq_ops = { static int nful_open(struct inode *inode, struct file *file) { - return seq_open_private(file, &nful_seq_ops, - sizeof(struct iter_state)); + return seq_open_net(inode, file, &nful_seq_ops, + sizeof(struct iter_state)); } static const struct file_operations nful_file_ops = { @@ -981,17 +1014,42 @@ static const struct file_operations nful_file_ops = { .open = nful_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release_private, + .release = seq_release_net, }; #endif /* PROC_FS */ -static int __init nfnetlink_log_init(void) +static int __net_init nfnl_log_net_init(struct net *net) { - int i, status = -ENOMEM; - + unsigned int i; + struct nfnl_log_net *log = nfnl_log_pernet(net); for (i = 0; i < INSTANCE_BUCKETS; i++) - INIT_HLIST_HEAD(&instance_table[i]); + INIT_HLIST_HEAD(&log->instance_table[i]); + spin_lock_init(&log->instances_lock); + +#ifdef CONFIG_PROC_FS + if (!proc_create("nfnetlink_log", 0440, + net->nf.proc_netfilter, &nful_file_ops)) + return -ENOMEM; +#endif + return 0; +} + +static void __net_exit nfnl_log_net_exit(struct net *net) +{ + remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter); +} + +static struct pernet_operations nfnl_log_net_ops = { + .init = nfnl_log_net_init, + .exit = nfnl_log_net_exit, + .id = &nfnl_log_net_id, + .size = sizeof(struct nfnl_log_net), +}; + +static int __init nfnetlink_log_init(void) +{ + int status = -ENOMEM; /* it's not really all that important to have a random value, so * we can do this from the init function, even if there hasn't @@ -1001,29 +1059,25 @@ static int __init nfnetlink_log_init(void) netlink_register_notifier(&nfulnl_rtnl_notifier); status = nfnetlink_subsys_register(&nfulnl_subsys); if (status < 0) { - printk(KERN_ERR "log: failed to create netlink socket\n"); + pr_err("log: failed to create netlink socket\n"); goto cleanup_netlink_notifier; } status = nf_log_register(NFPROTO_UNSPEC, &nfulnl_logger); if (status < 0) { - printk(KERN_ERR "log: failed to register logger\n"); + pr_err("log: failed to register logger\n"); goto cleanup_subsys; } -#ifdef CONFIG_PROC_FS - if (!proc_create("nfnetlink_log", 0440, - proc_net_netfilter, &nful_file_ops)) { - status = -ENOMEM; + status = register_pernet_subsys(&nfnl_log_net_ops); + if (status < 0) { + pr_err("log: failed to register pernet ops\n"); goto cleanup_logger; } -#endif return status; -#ifdef CONFIG_PROC_FS cleanup_logger: nf_log_unregister(&nfulnl_logger); -#endif cleanup_subsys: nfnetlink_subsys_unregister(&nfulnl_subsys); cleanup_netlink_notifier: @@ -1033,10 +1087,8 @@ cleanup_netlink_notifier: static void __exit nfnetlink_log_fini(void) { + unregister_pernet_subsys(&nfnl_log_net_ops); nf_log_unregister(&nfulnl_logger); -#ifdef CONFIG_PROC_FS - remove_proc_entry("nfnetlink_log", proc_net_netfilter); -#endif nfnetlink_subsys_unregister(&nfulnl_subsys); netlink_unregister_notifier(&nfulnl_rtnl_notifier); } -- 1.7.11.7 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH nf-next v2 07/10] netfilter: nfnetlink_log: add net namespace support for nfnetlink_log 2013-03-25 9:50 ` [PATCH nf-next v2 07/10] netfilter: nfnetlink_log: add net namespace support for nfnetlink_log Gao feng @ 2013-04-05 18:38 ` Pablo Neira Ayuso 0 siblings, 0 replies; 24+ messages in thread From: Pablo Neira Ayuso @ 2013-04-05 18:38 UTC (permalink / raw) To: Gao feng; +Cc: netfilter-devel On Mon, Mar 25, 2013 at 05:50:45PM +0800, Gao feng wrote: > This patch makes /proc/net/netfilter/nfnetlink_log pernet, > and netns has it's own instance table and lock. Applied, thanks. ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH nf-next v2 08/10] netfilter: nf_log: enable nflog in un-init net namespace 2013-03-25 9:50 [PATCH nf-next v2 01/10] netfilter: make /proc/net/netfilter pernet Gao feng ` (5 preceding siblings ...) 2013-03-25 9:50 ` [PATCH nf-next v2 07/10] netfilter: nfnetlink_log: add net namespace support for nfnetlink_log Gao feng @ 2013-03-25 9:50 ` Gao feng 2013-04-05 18:38 ` Pablo Neira Ayuso 2013-03-25 9:50 ` [PATCH nf-next v2 09/10] netfilter: nfnetlink_queue: add net namespace support for nfnetlink_queue Gao feng ` (2 subsequent siblings) 9 siblings, 1 reply; 24+ messages in thread From: Gao feng @ 2013-03-25 9:50 UTC (permalink / raw) To: netfilter-devel; +Cc: pablo, Gao feng Now all nf_loggers are support net namespace, we can allow all net namespace to enable the nflog. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- net/netfilter/nf_log.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 2aa1fc1..5f6182d 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -33,9 +33,6 @@ static struct nf_logger *__find_logger(int pf, const char *str_logger) void nf_log_set(struct net *net, u_int8_t pf, const struct nf_logger *logger) { - if (!net_eq(net, &init_net)) - return; - if (pf != NFPROTO_UNSPEC) { const struct nf_logger *log; mutex_lock(&nf_log_mutex); @@ -54,9 +51,6 @@ void nf_log_unset(struct net *net, const struct nf_logger *logger) int i; const struct nf_logger *log; - if (!net_eq(net, &init_net)) - return; - mutex_lock(&nf_log_mutex); for (i = 0; i < NFPROTO_NUMPROTO; i++) { log = rcu_dereference_protected(net->nf.nf_loggers[i], @@ -92,7 +86,6 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger) mutex_unlock(&nf_log_mutex); - nf_log_set(&init_net, pf, logger); return 0; } EXPORT_SYMBOL(nf_log_register); @@ -105,17 +98,12 @@ void nf_log_unregister(struct nf_logger *logger) for (i = 0; i < NFPROTO_NUMPROTO; i++) list_del(&logger->list[i]); mutex_unlock(&nf_log_mutex); - - nf_log_unset(&init_net, logger); } EXPORT_SYMBOL(nf_log_unregister); int nf_log_bind_pf(struct net *net, u_int8_t pf, const struct nf_logger *logger) { - if (!net_eq(net, &init_net)) - return 0; - if (pf >= ARRAY_SIZE(net->nf.nf_loggers)) return -EINVAL; mutex_lock(&nf_log_mutex); @@ -131,9 +119,6 @@ EXPORT_SYMBOL(nf_log_bind_pf); void nf_log_unbind_pf(struct net *net, u_int8_t pf) { - if (!net_eq(net, &init_net)) - return; - if (pf >= ARRAY_SIZE(net->nf.nf_loggers)) return; mutex_lock(&nf_log_mutex); @@ -155,9 +140,6 @@ void nf_log_packet(struct net *net, char prefix[NF_LOG_PREFIXLEN]; const struct nf_logger *logger; - if (!net_eq(net, &init_net)) - return; - rcu_read_lock(); logger = rcu_dereference(net->nf.nf_loggers[pf]); if (logger) { @@ -272,9 +254,6 @@ static int nf_log_proc_dostring(ctl_table *table, int write, struct net *net = current->nsproxy->net_ns; if (write) { - if (!net_eq(net, &init_net)) - return -EPERM; - if (size > sizeof(buf)) size = sizeof(buf); if (copy_from_user(buf, buffer, size)) -- 1.7.11.7 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH nf-next v2 08/10] netfilter: nf_log: enable nflog in un-init net namespace 2013-03-25 9:50 ` [PATCH nf-next v2 08/10] netfilter: nf_log: enable nflog in un-init net namespace Gao feng @ 2013-04-05 18:38 ` Pablo Neira Ayuso 0 siblings, 0 replies; 24+ messages in thread From: Pablo Neira Ayuso @ 2013-04-05 18:38 UTC (permalink / raw) To: Gao feng; +Cc: netfilter-devel On Mon, Mar 25, 2013 at 05:50:46PM +0800, Gao feng wrote: > Now all nf_loggers are support net namespace, we > can allow all net namespace to enable the nflog. Applied, thanks. ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH nf-next v2 09/10] netfilter: nfnetlink_queue: add net namespace support for nfnetlink_queue 2013-03-25 9:50 [PATCH nf-next v2 01/10] netfilter: make /proc/net/netfilter pernet Gao feng ` (6 preceding siblings ...) 2013-03-25 9:50 ` [PATCH nf-next v2 08/10] netfilter: nf_log: enable nflog in un-init net namespace Gao feng @ 2013-03-25 9:50 ` Gao feng 2013-04-05 18:40 ` Pablo Neira Ayuso 2013-03-25 9:50 ` [PATCH nf-next v2 10/10] netfilter: remove useless variable proc_net_netfilter Gao feng 2013-04-05 17:44 ` [PATCH nf-next v2 01/10] netfilter: make /proc/net/netfilter pernet Pablo Neira Ayuso 9 siblings, 1 reply; 24+ messages in thread From: Gao feng @ 2013-03-25 9:50 UTC (permalink / raw) To: netfilter-devel; +Cc: pablo, Gao feng This patch makes /proc/net/netfilter/nfnetlink_queue pernet, and netns has it's own instance table and lock. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- net/netfilter/nfnetlink_queue_core.c | 190 +++++++++++++++++++++++------------ 1 file changed, 123 insertions(+), 67 deletions(-) diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index da91b86..975350e 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c @@ -30,6 +30,7 @@ #include <linux/list.h> #include <net/sock.h> #include <net/netfilter/nf_queue.h> +#include <net/netns/generic.h> #include <net/netfilter/nfnetlink_queue.h> #include <linux/atomic.h> @@ -66,10 +67,18 @@ struct nfqnl_instance { typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long); -static DEFINE_SPINLOCK(instances_lock); +static int nfnl_queue_net_id __read_mostly; #define INSTANCE_BUCKETS 16 -static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly; +struct nfnl_queue_net { + spinlock_t instances_lock; + struct hlist_head instance_table[INSTANCE_BUCKETS]; +}; + +static struct nfnl_queue_net *nfnl_queue_pernet(struct net *net) +{ + return net_generic(net, nfnl_queue_net_id); +} static inline u_int8_t instance_hashfn(u_int16_t queue_num) { @@ -77,12 +86,12 @@ static inline u_int8_t instance_hashfn(u_int16_t queue_num) } static struct nfqnl_instance * -instance_lookup(u_int16_t queue_num) +instance_lookup(struct nfnl_queue_net *q, u_int16_t queue_num) { struct hlist_head *head; struct nfqnl_instance *inst; - head = &instance_table[instance_hashfn(queue_num)]; + head = &q->instance_table[instance_hashfn(queue_num)]; hlist_for_each_entry_rcu(inst, head, hlist) { if (inst->queue_num == queue_num) return inst; @@ -91,14 +100,15 @@ instance_lookup(u_int16_t queue_num) } static struct nfqnl_instance * -instance_create(u_int16_t queue_num, int portid) +instance_create(struct nfnl_queue_net *q, u_int16_t queue_num, + int portid) { struct nfqnl_instance *inst; unsigned int h; int err; - spin_lock(&instances_lock); - if (instance_lookup(queue_num)) { + spin_lock(&q->instances_lock); + if (instance_lookup(q, queue_num)) { err = -EEXIST; goto out_unlock; } @@ -123,16 +133,16 @@ instance_create(u_int16_t queue_num, int portid) } h = instance_hashfn(queue_num); - hlist_add_head_rcu(&inst->hlist, &instance_table[h]); + hlist_add_head_rcu(&inst->hlist, &q->instance_table[h]); - spin_unlock(&instances_lock); + spin_unlock(&q->instances_lock); return inst; out_free: kfree(inst); out_unlock: - spin_unlock(&instances_lock); + spin_unlock(&q->instances_lock); return ERR_PTR(err); } @@ -158,11 +168,11 @@ __instance_destroy(struct nfqnl_instance *inst) } static void -instance_destroy(struct nfqnl_instance *inst) +instance_destroy(struct nfnl_queue_net *q, struct nfqnl_instance *inst) { - spin_lock(&instances_lock); + spin_lock(&q->instances_lock); __instance_destroy(inst); - spin_unlock(&instances_lock); + spin_unlock(&q->instances_lock); } static inline void @@ -473,9 +483,12 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) int err = -ENOBUFS; __be32 *packet_id_ptr; int failopen = 0; + struct net *net = dev_net(entry->indev ? + entry->indev : entry->outdev); + struct nfnl_queue_net *q = nfnl_queue_pernet(net); /* rcu_read_lock()ed by nf_hook_slow() */ - queue = instance_lookup(queuenum); + queue = instance_lookup(q, queuenum); if (!queue) { err = -ESRCH; goto err_out; @@ -512,7 +525,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) *packet_id_ptr = htonl(entry->id); /* nfnetlink_unicast will either free the nskb or add it to a socket */ - err = nfnetlink_unicast(nskb, &init_net, queue->peer_portid, MSG_DONTWAIT); + err = nfnetlink_unicast(nskb, net, queue->peer_portid, MSG_DONTWAIT); if (err < 0) { queue->queue_user_dropped++; goto err_out_unlock; @@ -625,15 +638,16 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) /* drop all packets with either indev or outdev == ifindex from all queue * instances */ static void -nfqnl_dev_drop(int ifindex) +nfqnl_dev_drop(struct net *net, int ifindex) { int i; + struct nfnl_queue_net *q = nfnl_queue_pernet(net); rcu_read_lock(); for (i = 0; i < INSTANCE_BUCKETS; i++) { struct nfqnl_instance *inst; - struct hlist_head *head = &instance_table[i]; + struct hlist_head *head = &q->instance_table[i]; hlist_for_each_entry_rcu(inst, head, hlist) nfqnl_flush(inst, dev_cmp, ifindex); @@ -650,12 +664,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this, { struct net_device *dev = ptr; - if (!net_eq(dev_net(dev), &init_net)) - return NOTIFY_DONE; - /* Drop any packets associated with the downed device */ if (event == NETDEV_DOWN) - nfqnl_dev_drop(dev->ifindex); + nfqnl_dev_drop(dev_net(dev), dev->ifindex); return NOTIFY_DONE; } @@ -668,24 +679,24 @@ nfqnl_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr) { struct netlink_notify *n = ptr; + struct nfnl_queue_net *q = nfnl_queue_pernet(n->net); if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) { int i; /* destroy all instances for this portid */ - spin_lock(&instances_lock); + spin_lock(&q->instances_lock); for (i = 0; i < INSTANCE_BUCKETS; i++) { struct hlist_node *t2; struct nfqnl_instance *inst; - struct hlist_head *head = &instance_table[i]; + struct hlist_head *head = &q->instance_table[i]; hlist_for_each_entry_safe(inst, t2, head, hlist) { - if ((n->net == &init_net) && - (n->portid == inst->peer_portid)) + if (n->portid == inst->peer_portid) __instance_destroy(inst); } } - spin_unlock(&instances_lock); + spin_unlock(&q->instances_lock); } return NOTIFY_DONE; } @@ -706,11 +717,13 @@ static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = { [NFQA_MARK] = { .type = NLA_U32 }, }; -static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlportid) +static struct nfqnl_instance * +verdict_instance_lookup(struct nfnl_queue_net *q, + u16 queue_num, int nlportid) { struct nfqnl_instance *queue; - queue = instance_lookup(queue_num); + queue = instance_lookup(q, queue_num); if (!queue) return ERR_PTR(-ENODEV); @@ -754,7 +767,11 @@ nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb, LIST_HEAD(batch_list); u16 queue_num = ntohs(nfmsg->res_id); - queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).portid); + struct net *net = sock_net(ctnl); + struct nfnl_queue_net *q = nfnl_queue_pernet(net); + + queue = verdict_instance_lookup(q, queue_num, + NETLINK_CB(skb).portid); if (IS_ERR(queue)) return PTR_ERR(queue); @@ -802,10 +819,13 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, enum ip_conntrack_info uninitialized_var(ctinfo); struct nf_conn *ct = NULL; - queue = instance_lookup(queue_num); - if (!queue) + struct net *net = sock_net(ctnl); + struct nfnl_queue_net *q = nfnl_queue_pernet(net); - queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).portid); + queue = instance_lookup(q, queue_num); + if (!queue) + queue = verdict_instance_lookup(q, queue_num, + NETLINK_CB(skb).portid); if (IS_ERR(queue)) return PTR_ERR(queue); @@ -869,6 +889,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, u_int16_t queue_num = ntohs(nfmsg->res_id); struct nfqnl_instance *queue; struct nfqnl_msg_config_cmd *cmd = NULL; + struct net *net = sock_net(ctnl); + struct nfnl_queue_net *q = nfnl_queue_pernet(net); int ret = 0; if (nfqa[NFQA_CFG_CMD]) { @@ -882,7 +904,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, } rcu_read_lock(); - queue = instance_lookup(queue_num); + queue = instance_lookup(q, queue_num); if (queue && queue->peer_portid != NETLINK_CB(skb).portid) { ret = -EPERM; goto err_out_unlock; @@ -895,7 +917,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, ret = -EBUSY; goto err_out_unlock; } - queue = instance_create(queue_num, NETLINK_CB(skb).portid); + queue = instance_create(q, queue_num, + NETLINK_CB(skb).portid); if (IS_ERR(queue)) { ret = PTR_ERR(queue); goto err_out_unlock; @@ -906,7 +929,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, ret = -ENODEV; goto err_out_unlock; } - instance_destroy(queue); + instance_destroy(q, queue); break; case NFQNL_CFG_CMD_PF_BIND: case NFQNL_CFG_CMD_PF_UNBIND: @@ -1000,53 +1023,63 @@ static const struct nfnetlink_subsystem nfqnl_subsys = { #ifdef CONFIG_PROC_FS struct iter_state { + struct seq_net_private p; unsigned int bucket; }; -static struct hlist_node *get_first(struct seq_file *seq) +static struct hlist_node *get_first(struct seq_file *s) { - struct iter_state *st = seq->private; + struct iter_state *st = s->private; + struct net *net; + struct nfnl_queue_net *q; if (!st) return NULL; + net = seq_file_net(s); + q = nfnl_queue_pernet(net); for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { - if (!hlist_empty(&instance_table[st->bucket])) - return instance_table[st->bucket].first; + if (!hlist_empty(&q->instance_table[st->bucket])) + return q->instance_table[st->bucket].first; } return NULL; } -static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h) +static struct hlist_node *get_next(struct seq_file *s, + struct hlist_node *h) { - struct iter_state *st = seq->private; + struct iter_state *st = s->private; + struct net *net = seq_file_net(s); h = h->next; while (!h) { + struct nfnl_queue_net *q; + if (++st->bucket >= INSTANCE_BUCKETS) return NULL; - h = instance_table[st->bucket].first; + q = nfnl_queue_pernet(net); + h = q->instance_table[st->bucket].first; } return h; } -static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) +static struct hlist_node *get_idx(struct seq_file *s, loff_t pos) { struct hlist_node *head; - head = get_first(seq); + head = get_first(s); if (head) - while (pos && (head = get_next(seq, head))) + while (pos && (head = get_next(s, head))) pos--; return pos ? NULL : head; } -static void *seq_start(struct seq_file *seq, loff_t *pos) - __acquires(instances_lock) +static void *seq_start(struct seq_file *s, loff_t *pos) + __acquires(nfnl_queue_pernet(seq_file_net(s))->instances_lock) { - spin_lock(&instances_lock); - return get_idx(seq, *pos); + spin_lock(&nfnl_queue_pernet(seq_file_net(s))->instances_lock); + return get_idx(s, *pos); } static void *seq_next(struct seq_file *s, void *v, loff_t *pos) @@ -1056,9 +1089,9 @@ static void *seq_next(struct seq_file *s, void *v, loff_t *pos) } static void seq_stop(struct seq_file *s, void *v) - __releases(instances_lock) + __releases(nfnl_queue_pernet(seq_file_net(s))->instances_lock) { - spin_unlock(&instances_lock); + spin_unlock(&nfnl_queue_pernet(seq_file_net(s))->instances_lock); } static int seq_show(struct seq_file *s, void *v) @@ -1082,7 +1115,7 @@ static const struct seq_operations nfqnl_seq_ops = { static int nfqnl_open(struct inode *inode, struct file *file) { - return seq_open_private(file, &nfqnl_seq_ops, + return seq_open_net(inode, file, &nfqnl_seq_ops, sizeof(struct iter_state)); } @@ -1091,39 +1124,64 @@ static const struct file_operations nfqnl_file_ops = { .open = nfqnl_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release_private, + .release = seq_release_net, }; #endif /* PROC_FS */ -static int __init nfnetlink_queue_init(void) +static int __net_init nfnl_queue_net_init(struct net *net) { - int i, status = -ENOMEM; + unsigned int i; + struct nfnl_queue_net *q = nfnl_queue_pernet(net); for (i = 0; i < INSTANCE_BUCKETS; i++) - INIT_HLIST_HEAD(&instance_table[i]); + INIT_HLIST_HEAD(&q->instance_table[i]); + spin_lock_init(&q->instances_lock); + +#ifdef CONFIG_PROC_FS + if (!proc_create("nfnetlink_queue", 0440, + net->nf.proc_netfilter, &nfqnl_file_ops)) + return -ENOMEM; +#endif + return 0; +} + +static void __net_exit nfnl_queue_net_exit(struct net *net) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("nfnetlink_queue", net->nf.proc_netfilter); +#endif +} + +static struct pernet_operations nfnl_queue_net_ops = { + .init = nfnl_queue_net_init, + .exit = nfnl_queue_net_exit, + .id = &nfnl_queue_net_id, + .size = sizeof(struct nfnl_queue_net), +}; + +static int __init nfnetlink_queue_init(void) +{ + int status = -ENOMEM; netlink_register_notifier(&nfqnl_rtnl_notifier); status = nfnetlink_subsys_register(&nfqnl_subsys); if (status < 0) { - printk(KERN_ERR "nf_queue: failed to create netlink socket\n"); + pr_err("nf_queue: failed to create netlink socket\n"); goto cleanup_netlink_notifier; } -#ifdef CONFIG_PROC_FS - if (!proc_create("nfnetlink_queue", 0440, - proc_net_netfilter, &nfqnl_file_ops)) + status = register_pernet_subsys(&nfnl_queue_net_ops); + if (status < 0) { + pr_err("nf_queue: failed to register pernet ops\n"); goto cleanup_subsys; -#endif - + } register_netdevice_notifier(&nfqnl_dev_notifier); nf_register_queue_handler(&nfqh); return status; -#ifdef CONFIG_PROC_FS cleanup_subsys: nfnetlink_subsys_unregister(&nfqnl_subsys); -#endif cleanup_netlink_notifier: netlink_unregister_notifier(&nfqnl_rtnl_notifier); return status; @@ -1133,9 +1191,7 @@ static void __exit nfnetlink_queue_fini(void) { nf_unregister_queue_handler(); unregister_netdevice_notifier(&nfqnl_dev_notifier); -#ifdef CONFIG_PROC_FS - remove_proc_entry("nfnetlink_queue", proc_net_netfilter); -#endif + unregister_pernet_subsys(&nfnl_queue_net_ops); nfnetlink_subsys_unregister(&nfqnl_subsys); netlink_unregister_notifier(&nfqnl_rtnl_notifier); -- 1.7.11.7 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH nf-next v2 09/10] netfilter: nfnetlink_queue: add net namespace support for nfnetlink_queue 2013-03-25 9:50 ` [PATCH nf-next v2 09/10] netfilter: nfnetlink_queue: add net namespace support for nfnetlink_queue Gao feng @ 2013-04-05 18:40 ` Pablo Neira Ayuso 0 siblings, 0 replies; 24+ messages in thread From: Pablo Neira Ayuso @ 2013-04-05 18:40 UTC (permalink / raw) To: Gao feng; +Cc: netfilter-devel On Mon, Mar 25, 2013 at 05:50:47PM +0800, Gao feng wrote: > This patch makes /proc/net/netfilter/nfnetlink_queue pernet, > and netns has it's own instance table and lock. Applied, thanks. ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH nf-next v2 10/10] netfilter: remove useless variable proc_net_netfilter 2013-03-25 9:50 [PATCH nf-next v2 01/10] netfilter: make /proc/net/netfilter pernet Gao feng ` (7 preceding siblings ...) 2013-03-25 9:50 ` [PATCH nf-next v2 09/10] netfilter: nfnetlink_queue: add net namespace support for nfnetlink_queue Gao feng @ 2013-03-25 9:50 ` Gao feng 2013-04-05 18:45 ` Pablo Neira Ayuso 2013-04-05 17:44 ` [PATCH nf-next v2 01/10] netfilter: make /proc/net/netfilter pernet Pablo Neira Ayuso 9 siblings, 1 reply; 24+ messages in thread From: Gao feng @ 2013-03-25 9:50 UTC (permalink / raw) To: netfilter-devel; +Cc: pablo, Gao feng After we add net namespace support for nflog and nfqueue, the var proc_net_netfilter has no use,just remove it. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- include/linux/netfilter.h | 1 - net/netfilter/core.c | 7 ------- 2 files changed, 8 deletions(-) diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index ee14284..b9d401c 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -291,7 +291,6 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) #ifdef CONFIG_PROC_FS #include <linux/proc_fs.h> -extern struct proc_dir_entry *proc_net_netfilter; #endif #else /* !CONFIG_NETFILTER */ diff --git a/net/netfilter/core.c b/net/netfilter/core.c index e054799..3117ce8 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -276,11 +276,6 @@ void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *); EXPORT_SYMBOL(nf_nat_decode_session_hook); #endif -#ifdef CONFIG_PROC_FS -struct proc_dir_entry *proc_net_netfilter; -EXPORT_SYMBOL(proc_net_netfilter); -#endif - static int __net_init netfilter_net_init(struct net *net) { #ifdef CONFIG_PROC_FS @@ -290,8 +285,6 @@ static int __net_init netfilter_net_init(struct net *net) if (net_eq(net, &init_net)) { if (!net->nf.proc_netfilter) panic("cannot create netfilter proc entry"); - else - proc_net_netfilter = net->nf.proc_netfilter; } else if (!net->nf.proc_netfilter) { pr_err("cannot create netfilter proc entry"); return -ENOMEM; -- 1.7.11.7 ^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH nf-next v2 10/10] netfilter: remove useless variable proc_net_netfilter 2013-03-25 9:50 ` [PATCH nf-next v2 10/10] netfilter: remove useless variable proc_net_netfilter Gao feng @ 2013-04-05 18:45 ` Pablo Neira Ayuso 2013-04-08 2:56 ` Gao feng 0 siblings, 1 reply; 24+ messages in thread From: Pablo Neira Ayuso @ 2013-04-05 18:45 UTC (permalink / raw) To: Gao feng; +Cc: netfilter-devel On Mon, Mar 25, 2013 at 05:50:48PM +0800, Gao feng wrote: > After we add net namespace support for nflog and nfqueue, > the var proc_net_netfilter has no use,just remove it. Applied a different patch based on yours. > Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> > --- > include/linux/netfilter.h | 1 - > net/netfilter/core.c | 7 ------- > 2 files changed, 8 deletions(-) > > diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h > index ee14284..b9d401c 100644 > --- a/include/linux/netfilter.h > +++ b/include/linux/netfilter.h > @@ -291,7 +291,6 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) > > #ifdef CONFIG_PROC_FS > #include <linux/proc_fs.h> Removed also these two lines above. > -extern struct proc_dir_entry *proc_net_netfilter; > #endif > > #else /* !CONFIG_NETFILTER */ > diff --git a/net/netfilter/core.c b/net/netfilter/core.c > index e054799..3117ce8 100644 > --- a/net/netfilter/core.c > +++ b/net/netfilter/core.c > @@ -276,11 +276,6 @@ void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *); > EXPORT_SYMBOL(nf_nat_decode_session_hook); > #endif > > -#ifdef CONFIG_PROC_FS > -struct proc_dir_entry *proc_net_netfilter; > -EXPORT_SYMBOL(proc_net_netfilter); > -#endif > - > static int __net_init netfilter_net_init(struct net *net) > { > #ifdef CONFIG_PROC_FS > @@ -290,8 +285,6 @@ static int __net_init netfilter_net_init(struct net *net) > if (net_eq(net, &init_net)) { > if (!net->nf.proc_netfilter) > panic("cannot create netfilter proc entry"); > - else > - proc_net_netfilter = net->nf.proc_netfilter; > } else if (!net->nf.proc_netfilter) { > pr_err("cannot create netfilter proc entry"); > return -ENOMEM; Refactors this code to handle error path like: if (!net->nf.proc_netfilter) { if (!net_eq(net, &init_net)) pr_err("cannot create netfilter proc entry"); return -ENOMEM; } So this spots an error only if netns fails. This still panics for the init_net case. ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH nf-next v2 10/10] netfilter: remove useless variable proc_net_netfilter 2013-04-05 18:45 ` Pablo Neira Ayuso @ 2013-04-08 2:56 ` Gao feng 0 siblings, 0 replies; 24+ messages in thread From: Gao feng @ 2013-04-08 2:56 UTC (permalink / raw) To: Pablo Neira Ayuso; +Cc: netfilter-devel On 2013/04/06 02:45, Pablo Neira Ayuso wrote: > On Mon, Mar 25, 2013 at 05:50:48PM +0800, Gao feng wrote: >> After we add net namespace support for nflog and nfqueue, >> the var proc_net_netfilter has no use,just remove it. > > Applied a different patch based on yours. > >> Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> >> --- >> include/linux/netfilter.h | 1 - >> net/netfilter/core.c | 7 ------- >> 2 files changed, 8 deletions(-) >> >> diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h >> index ee14284..b9d401c 100644 >> --- a/include/linux/netfilter.h >> +++ b/include/linux/netfilter.h >> @@ -291,7 +291,6 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) >> >> #ifdef CONFIG_PROC_FS >> #include <linux/proc_fs.h> > > Removed also these two lines above. > >> -extern struct proc_dir_entry *proc_net_netfilter; >> #endif >> >> #else /* !CONFIG_NETFILTER */ >> diff --git a/net/netfilter/core.c b/net/netfilter/core.c >> index e054799..3117ce8 100644 >> --- a/net/netfilter/core.c >> +++ b/net/netfilter/core.c >> @@ -276,11 +276,6 @@ void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *); >> EXPORT_SYMBOL(nf_nat_decode_session_hook); >> #endif >> >> -#ifdef CONFIG_PROC_FS >> -struct proc_dir_entry *proc_net_netfilter; >> -EXPORT_SYMBOL(proc_net_netfilter); >> -#endif >> - >> static int __net_init netfilter_net_init(struct net *net) >> { >> #ifdef CONFIG_PROC_FS >> @@ -290,8 +285,6 @@ static int __net_init netfilter_net_init(struct net *net) >> if (net_eq(net, &init_net)) { >> if (!net->nf.proc_netfilter) >> panic("cannot create netfilter proc entry"); >> - else >> - proc_net_netfilter = net->nf.proc_netfilter; >> } else if (!net->nf.proc_netfilter) { >> pr_err("cannot create netfilter proc entry"); >> return -ENOMEM; > > Refactors this code to handle error path like: > > if (!net->nf.proc_netfilter) { > if (!net_eq(net, &init_net)) > pr_err("cannot create netfilter proc entry"); > > return -ENOMEM; > } > > So this spots an error only if netns fails. This still panics for the > init_net case. > Thanks for your hand, looks good to me. ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH nf-next v2 01/10] netfilter: make /proc/net/netfilter pernet 2013-03-25 9:50 [PATCH nf-next v2 01/10] netfilter: make /proc/net/netfilter pernet Gao feng ` (8 preceding siblings ...) 2013-03-25 9:50 ` [PATCH nf-next v2 10/10] netfilter: remove useless variable proc_net_netfilter Gao feng @ 2013-04-05 17:44 ` Pablo Neira Ayuso 9 siblings, 0 replies; 24+ messages in thread From: Pablo Neira Ayuso @ 2013-04-05 17:44 UTC (permalink / raw) To: Gao feng; +Cc: netfilter-devel On Mon, Mar 25, 2013 at 05:50:39PM +0800, Gao feng wrote: > Now,only init net has directroy /proc/net/netfilter, > this patch makes this proc dentry pernet. Applied with minor glitch, see below: > Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> > --- > include/net/net_namespace.h | 2 ++ > include/net/netns/netfilter.h | 11 +++++++++++ > net/netfilter/core.c | 36 +++++++++++++++++++++++++++++++----- > 3 files changed, 44 insertions(+), 5 deletions(-) > create mode 100644 include/net/netns/netfilter.h > > diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h > index de644bc..b176978 100644 > --- a/include/net/net_namespace.h > +++ b/include/net/net_namespace.h > @@ -17,6 +17,7 @@ > #include <net/netns/ipv6.h> > #include <net/netns/sctp.h> > #include <net/netns/dccp.h> > +#include <net/netns/netfilter.h> > #include <net/netns/x_tables.h> > #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) > #include <net/netns/conntrack.h> > @@ -94,6 +95,7 @@ struct net { > struct netns_dccp dccp; > #endif > #ifdef CONFIG_NETFILTER > + struct netns_nf nf; > struct netns_xt xt; > #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) > struct netns_ct ct; > diff --git a/include/net/netns/netfilter.h b/include/net/netns/netfilter.h > new file mode 100644 > index 0000000..248ca1c > --- /dev/null > +++ b/include/net/netns/netfilter.h > @@ -0,0 +1,11 @@ > +#ifndef __NETNS_NETFILTER_H > +#define __NETNS_NETFILTER_H > + > +#include <linux/proc_fs.h> > + > +struct netns_nf { > +#if defined CONFIG_PROC_FS > + struct proc_dir_entry *proc_netfilter; > +#endif > +}; > +#endif > diff --git a/net/netfilter/core.c b/net/netfilter/core.c > index a9c488b..e054799 100644 > --- a/net/netfilter/core.c > +++ b/net/netfilter/core.c > @@ -281,6 +281,35 @@ struct proc_dir_entry *proc_net_netfilter; > EXPORT_SYMBOL(proc_net_netfilter); > #endif > > +static int __net_init netfilter_net_init(struct net *net) > +{ > +#ifdef CONFIG_PROC_FS > + net->nf.proc_netfilter = proc_net_mkdir(net, > + "netfilter", > + net->proc_net); > + if (net_eq(net, &init_net)) { > + if (!net->nf.proc_netfilter) > + panic("cannot create netfilter proc entry"); Moved this panic() to netfilter_init and it just returns -ENOMEM. > + else > + proc_net_netfilter = net->nf.proc_netfilter; > + } else if (!net->nf.proc_netfilter) { > + pr_err("cannot create netfilter proc entry"); > + return -ENOMEM; > + } > +#endif > + return 0; > +} > + > +static void __net_exit netfilter_net_exit(struct net *net) > +{ > + remove_proc_entry("netfilter", net->proc_net); > +} > + > +static struct pernet_operations netfilter_net_ops = { > + .init = netfilter_net_init, > + .exit = netfilter_net_exit, > +}; > + > void __init netfilter_init(void) > { > int i, h; > @@ -289,11 +318,8 @@ void __init netfilter_init(void) > INIT_LIST_HEAD(&nf_hooks[i][h]); > } > > -#ifdef CONFIG_PROC_FS > - proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net); > - if (!proc_net_netfilter) > - panic("cannot create netfilter proc entry"); > -#endif > + if (register_pernet_subsys(&netfilter_net_ops) < 0) > + return; > > if (netfilter_log_init() < 0) > panic("cannot initialize nf_log"); > -- > 1.7.11.7 > > -- > 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 [flat|nested] 24+ messages in thread
end of thread, other threads:[~2013-04-08 2:55 UTC | newest] Thread overview: 24+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-03-25 9:50 [PATCH nf-next v2 01/10] netfilter: make /proc/net/netfilter pernet Gao feng 2013-03-25 9:50 ` [PATCH nf-next v2 02/10] netfilter: nf_log: prepar net namespace support for nf_log Gao feng 2013-04-05 18:30 ` Pablo Neira Ayuso 2013-04-08 2:46 ` Gao feng 2013-03-25 9:50 ` [PATCH nf-next v2 03/10] netfilter: ebt_log: add net namespace support for ebt_log Gao feng 2013-04-05 18:32 ` Pablo Neira Ayuso 2013-04-08 2:50 ` Gao feng 2013-03-25 9:50 ` [PATCH nf-next v2 04/10] netfilter: xt_LOG: add net namespace support for xt_LOG Gao feng 2013-04-05 18:33 ` Pablo Neira Ayuso 2013-04-08 2:50 ` Gao feng 2013-03-25 9:50 ` [PATCH nf-next v2 05/10] netfilter: ebt_ulog: add net namesapce support for ebt_ulog Gao feng 2013-04-05 18:34 ` Pablo Neira Ayuso 2013-03-25 9:50 ` [PATCH nf-next v2 06/10] netfilter: ipt_ulog: add net namespace support for ipt_ulog Gao feng 2013-04-05 18:35 ` Pablo Neira Ayuso 2013-03-25 9:50 ` [PATCH nf-next v2 07/10] netfilter: nfnetlink_log: add net namespace support for nfnetlink_log Gao feng 2013-04-05 18:38 ` Pablo Neira Ayuso 2013-03-25 9:50 ` [PATCH nf-next v2 08/10] netfilter: nf_log: enable nflog in un-init net namespace Gao feng 2013-04-05 18:38 ` Pablo Neira Ayuso 2013-03-25 9:50 ` [PATCH nf-next v2 09/10] netfilter: nfnetlink_queue: add net namespace support for nfnetlink_queue Gao feng 2013-04-05 18:40 ` Pablo Neira Ayuso 2013-03-25 9:50 ` [PATCH nf-next v2 10/10] netfilter: remove useless variable proc_net_netfilter Gao feng 2013-04-05 18:45 ` Pablo Neira Ayuso 2013-04-08 2:56 ` Gao feng 2013-04-05 17:44 ` [PATCH nf-next v2 01/10] netfilter: make /proc/net/netfilter pernet 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.