diff options
author | Patrick McHardy <kaber@trash.net> | 2010-02-03 07:51:51 -0500 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2010-02-03 07:51:51 -0500 |
commit | 0cebe4b4163b6373c9d24c1a192939777bc27e55 (patch) | |
tree | 6a091112f27c17b7bbe8d2adcdbf45564312bba4 /include/net | |
parent | 858b31330054a9ad259feceea0ad1ce5385c47f0 (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>
Diffstat (limited to 'include/net')
-rw-r--r-- | include/net/netfilter/nf_conntrack_ecache.h | 59 |
1 files changed, 28 insertions, 31 deletions
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 */ | ||
16 | enum 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 | |||
29 | enum ip_conntrack_expect_events { | ||
30 | IPEXP_NEW, /* new expectation */ | ||
31 | }; | ||
32 | |||
33 | struct nf_conntrack_ecache { | 15 | struct 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 | ||
39 | static inline struct nf_conntrack_ecache * | 23 | static inline struct nf_conntrack_ecache * |
@@ -43,14 +27,24 @@ nf_ct_ecache_find(const struct nf_conn *ct) | |||
43 | } | 27 | } |
44 | 28 | ||
45 | static inline struct nf_conntrack_ecache * | 29 | static inline struct nf_conntrack_ecache * |
46 | nf_ct_ecache_ext_add(struct nf_conn *ct, gfp_t gfp) | 30 | nf_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, |