aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2010-02-03 07:51:51 -0500
committerPatrick McHardy <kaber@trash.net>2010-02-03 07:51:51 -0500
commit0cebe4b4163b6373c9d24c1a192939777bc27e55 (patch)
tree6a091112f27c17b7bbe8d2adcdbf45564312bba4
parent858b31330054a9ad259feceea0ad1ce5385c47f0 (diff)
netfilter: ctnetlink: support selective event delivery
Add two masks for conntrack end expectation events to struct nf_conntrack_ecache and use them to filter events. Their default value is "all events" when the event sysctl is on and "no events" when it is off. A following patch will add specific initializations. Expectation events depend on the ecache struct of their master conntrack. Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--include/linux/netfilter/nf_conntrack_common.h18
-rw-r--r--include/net/netfilter/nf_conntrack_ecache.h59
-rw-r--r--net/netfilter/nf_conntrack_core.c2
-rw-r--r--net/netfilter/nf_conntrack_netlink.c2
4 files changed, 48 insertions, 33 deletions
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
index a374787ed9b0..ebfed90733f7 100644
--- a/include/linux/netfilter/nf_conntrack_common.h
+++ b/include/linux/netfilter/nf_conntrack_common.h
@@ -74,6 +74,24 @@ enum ip_conntrack_status {
74 IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT), 74 IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
75}; 75};
76 76
77/* Connection tracking event types */
78enum ip_conntrack_events {
79 IPCT_NEW, /* new conntrack */
80 IPCT_RELATED, /* related conntrack */
81 IPCT_DESTROY, /* destroyed conntrack */
82 IPCT_REPLY, /* connection has seen two-way traffic */
83 IPCT_ASSURED, /* connection status has changed to assured */
84 IPCT_PROTOINFO, /* protocol information has changed */
85 IPCT_HELPER, /* new helper has been set */
86 IPCT_MARK, /* new mark has been set */
87 IPCT_NATSEQADJ, /* NAT is doing sequence adjustment */
88 IPCT_SECMARK, /* new security mark has been set */
89};
90
91enum ip_conntrack_expect_events {
92 IPEXP_NEW, /* new expectation */
93};
94
77#ifdef __KERNEL__ 95#ifdef __KERNEL__
78struct ip_conntrack_stat { 96struct ip_conntrack_stat {
79 unsigned int searched; 97 unsigned int searched;
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 5e05fb883ab1..96ba5f7dcab6 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -12,28 +12,12 @@
12#include <linux/netfilter/nf_conntrack_tuple_common.h> 12#include <linux/netfilter/nf_conntrack_tuple_common.h>
13#include <net/netfilter/nf_conntrack_extend.h> 13#include <net/netfilter/nf_conntrack_extend.h>
14 14
15/* Connection tracking event types */
16enum ip_conntrack_events {
17 IPCT_NEW, /* new conntrack */
18 IPCT_RELATED, /* related conntrack */
19 IPCT_DESTROY, /* destroyed conntrack */
20 IPCT_REPLY, /* connection has seen two-way traffic */
21 IPCT_ASSURED, /* connection status has changed to assured */
22 IPCT_PROTOINFO, /* protocol information has changed */
23 IPCT_HELPER, /* new helper has been set */
24 IPCT_MARK, /* new mark has been set */
25 IPCT_NATSEQADJ, /* NAT is doing sequence adjustment */
26 IPCT_SECMARK, /* new security mark has been set */
27};
28
29enum ip_conntrack_expect_events {
30 IPEXP_NEW, /* new expectation */
31};
32
33struct nf_conntrack_ecache { 15struct nf_conntrack_ecache {
34 unsigned long cache; /* bitops want long */ 16 unsigned long cache; /* bitops want long */
35 unsigned long missed; /* missed events */ 17 unsigned long missed; /* missed events */
36 u32 pid; /* netlink pid of destroyer */ 18 u16 ctmask; /* bitmask of ct events to be delivered */
19 u16 expmask; /* bitmask of expect events to be delivered */
20 u32 pid; /* netlink pid of destroyer */
37}; 21};
38 22
39static inline struct nf_conntrack_ecache * 23static inline struct nf_conntrack_ecache *
@@ -43,14 +27,24 @@ nf_ct_ecache_find(const struct nf_conn *ct)
43} 27}
44 28
45static inline struct nf_conntrack_ecache * 29static inline struct nf_conntrack_ecache *
46nf_ct_ecache_ext_add(struct nf_conn *ct, gfp_t gfp) 30nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp)
47{ 31{
48 struct net *net = nf_ct_net(ct); 32 struct net *net = nf_ct_net(ct);
33 struct nf_conntrack_ecache *e;
49 34
50 if (!net->ct.sysctl_events) 35 if (!ctmask && !expmask && net->ct.sysctl_events) {
36 ctmask = ~0;
37 expmask = ~0;
38 }
39 if (!ctmask && !expmask)
51 return NULL; 40 return NULL;
52 41
53 return nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp); 42 e = nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp);
43 if (e) {
44 e->ctmask = ctmask;
45 e->expmask = expmask;
46 }
47 return e;
54}; 48};
55 49
56#ifdef CONFIG_NF_CONNTRACK_EVENTS 50#ifdef CONFIG_NF_CONNTRACK_EVENTS
@@ -83,6 +77,9 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
83 if (e == NULL) 77 if (e == NULL)
84 return; 78 return;
85 79
80 if (!(e->ctmask & (1 << event)))
81 return;
82
86 set_bit(event, &e->cache); 83 set_bit(event, &e->cache);
87} 84}
88 85
@@ -93,7 +90,6 @@ nf_conntrack_eventmask_report(unsigned int eventmask,
93 int report) 90 int report)
94{ 91{
95 int ret = 0; 92 int ret = 0;
96 struct net *net = nf_ct_net(ct);
97 struct nf_ct_event_notifier *notify; 93 struct nf_ct_event_notifier *notify;
98 struct nf_conntrack_ecache *e; 94 struct nf_conntrack_ecache *e;
99 95
@@ -102,9 +98,6 @@ nf_conntrack_eventmask_report(unsigned int eventmask,
102 if (notify == NULL) 98 if (notify == NULL)
103 goto out_unlock; 99 goto out_unlock;
104 100
105 if (!net->ct.sysctl_events)
106 goto out_unlock;
107
108 e = nf_ct_ecache_find(ct); 101 e = nf_ct_ecache_find(ct);
109 if (e == NULL) 102 if (e == NULL)
110 goto out_unlock; 103 goto out_unlock;
@@ -118,6 +111,9 @@ nf_conntrack_eventmask_report(unsigned int eventmask,
118 /* This is a resent of a destroy event? If so, skip missed */ 111 /* This is a resent of a destroy event? If so, skip missed */
119 unsigned long missed = e->pid ? 0 : e->missed; 112 unsigned long missed = e->pid ? 0 : e->missed;
120 113
114 if (!((eventmask | missed) & e->ctmask))
115 goto out_unlock;
116
121 ret = notify->fcn(eventmask | missed, &item); 117 ret = notify->fcn(eventmask | missed, &item);
122 if (unlikely(ret < 0 || missed)) { 118 if (unlikely(ret < 0 || missed)) {
123 spin_lock_bh(&ct->lock); 119 spin_lock_bh(&ct->lock);
@@ -173,18 +169,19 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
173 u32 pid, 169 u32 pid,
174 int report) 170 int report)
175{ 171{
176 struct net *net = nf_ct_exp_net(exp);
177 struct nf_exp_event_notifier *notify; 172 struct nf_exp_event_notifier *notify;
173 struct nf_conntrack_ecache *e;
178 174
179 rcu_read_lock(); 175 rcu_read_lock();
180 notify = rcu_dereference(nf_expect_event_cb); 176 notify = rcu_dereference(nf_expect_event_cb);
181 if (notify == NULL) 177 if (notify == NULL)
182 goto out_unlock; 178 goto out_unlock;
183 179
184 if (!net->ct.sysctl_events) 180 e = nf_ct_ecache_find(exp->master);
181 if (e == NULL)
185 goto out_unlock; 182 goto out_unlock;
186 183
187 { 184 if (e->expmask & (1 << event)) {
188 struct nf_exp_event item = { 185 struct nf_exp_event item = {
189 .exp = exp, 186 .exp = exp,
190 .pid = pid, 187 .pid = pid,
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 091ff770eb7b..53b8da6ad6b7 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -648,7 +648,7 @@ init_conntrack(struct net *net,
648 } 648 }
649 649
650 nf_ct_acct_ext_add(ct, GFP_ATOMIC); 650 nf_ct_acct_ext_add(ct, GFP_ATOMIC);
651 nf_ct_ecache_ext_add(ct, GFP_ATOMIC); 651 nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
652 652
653 spin_lock_bh(&nf_conntrack_lock); 653 spin_lock_bh(&nf_conntrack_lock);
654 exp = nf_ct_find_expectation(net, tuple); 654 exp = nf_ct_find_expectation(net, tuple);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index ff594eb138c1..f5c0b09e12f1 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1281,7 +1281,7 @@ ctnetlink_create_conntrack(struct net *net,
1281 } 1281 }
1282 1282
1283 nf_ct_acct_ext_add(ct, GFP_ATOMIC); 1283 nf_ct_acct_ext_add(ct, GFP_ATOMIC);
1284 nf_ct_ecache_ext_add(ct, GFP_ATOMIC); 1284 nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
1285 1285
1286#if defined(CONFIG_NF_CONNTRACK_MARK) 1286#if defined(CONFIG_NF_CONNTRACK_MARK)
1287 if (cda[CTA_MARK]) 1287 if (cda[CTA_MARK])