Merge tag 'timer' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
[deliverable/linux.git] / include / net / netfilter / nf_conntrack_ecache.h
CommitLineData
f6180121
MJ
1/*
2 * connection tracking event cache.
3 */
4
5#ifndef _NF_CONNTRACK_ECACHE_H
6#define _NF_CONNTRACK_ECACHE_H
7#include <net/netfilter/nf_conntrack.h>
8
6058fa6b 9#include <net/net_namespace.h>
f6180121 10#include <net/netfilter/nf_conntrack_expect.h>
a0891aa6
PNA
11#include <linux/netfilter/nf_conntrack_common.h>
12#include <linux/netfilter/nf_conntrack_tuple_common.h>
13#include <net/netfilter/nf_conntrack_extend.h>
f6180121 14
a0891aa6 15struct nf_conntrack_ecache {
0cebe4b4
PM
16 unsigned long cache; /* bitops want long */
17 unsigned long missed; /* missed events */
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 */
a0891aa6 21};
6bfea198 22
a0891aa6
PNA
23static inline struct nf_conntrack_ecache *
24nf_ct_ecache_find(const struct nf_conn *ct)
25{
e0e76c83 26#ifdef CONFIG_NF_CONNTRACK_EVENTS
a0891aa6 27 return nf_ct_ext_find(ct, NF_CT_EXT_ECACHE);
e0e76c83
CG
28#else
29 return NULL;
30#endif
a0891aa6 31}
6bfea198 32
a0891aa6 33static inline struct nf_conntrack_ecache *
0cebe4b4 34nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp)
a0891aa6 35{
e0e76c83 36#ifdef CONFIG_NF_CONNTRACK_EVENTS
a0891aa6 37 struct net *net = nf_ct_net(ct);
0cebe4b4 38 struct nf_conntrack_ecache *e;
6bfea198 39
0cebe4b4
PM
40 if (!ctmask && !expmask && net->ct.sysctl_events) {
41 ctmask = ~0;
42 expmask = ~0;
43 }
44 if (!ctmask && !expmask)
a0891aa6 45 return NULL;
6bfea198 46
0cebe4b4
PM
47 e = nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp);
48 if (e) {
49 e->ctmask = ctmask;
50 e->expmask = expmask;
51 }
52 return e;
e0e76c83
CG
53#else
54 return NULL;
55#endif
6bfea198
PNA
56};
57
f6180121 58#ifdef CONFIG_NF_CONNTRACK_EVENTS
19abb7b0
PNA
59/* This structure is passed to event handler */
60struct nf_ct_event {
61 struct nf_conn *ct;
62 u32 pid;
63 int report;
64};
65
e34d5c1a
PNA
66struct nf_ct_event_notifier {
67 int (*fcn)(unsigned int events, struct nf_ct_event *item);
68};
69
70e9942f
PNA
70extern int nf_conntrack_register_notifier(struct net *net, struct nf_ct_event_notifier *nb);
71extern void nf_conntrack_unregister_notifier(struct net *net, struct nf_ct_event_notifier *nb);
f6180121 72
a0891aa6 73extern void nf_ct_deliver_cached_events(struct nf_conn *ct);
f6180121
MJ
74
75static inline void
a71996fc 76nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
f6180121 77{
70e9942f 78 struct net *net = nf_ct_net(ct);
a0891aa6
PNA
79 struct nf_conntrack_ecache *e;
80
6bd0405b 81 if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
a0891aa6
PNA
82 return;
83
84 e = nf_ct_ecache_find(ct);
85 if (e == NULL)
86 return;
87
88 set_bit(event, &e->cache);
f6180121
MJ
89}
90
dd7669a9 91static inline int
a0891aa6
PNA
92nf_conntrack_eventmask_report(unsigned int eventmask,
93 struct nf_conn *ct,
94 u32 pid,
95 int report)
f6180121 96{
dd7669a9 97 int ret = 0;
70e9942f 98 struct net *net = nf_ct_net(ct);
e34d5c1a 99 struct nf_ct_event_notifier *notify;
dd7669a9 100 struct nf_conntrack_ecache *e;
e34d5c1a
PNA
101
102 rcu_read_lock();
70e9942f 103 notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
e34d5c1a
PNA
104 if (notify == NULL)
105 goto out_unlock;
106
dd7669a9
PNA
107 e = nf_ct_ecache_find(ct);
108 if (e == NULL)
109 goto out_unlock;
110
e34d5c1a
PNA
111 if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) {
112 struct nf_ct_event item = {
113 .ct = ct,
dd7669a9 114 .pid = e->pid ? e->pid : pid,
e34d5c1a
PNA
115 .report = report
116 };
dd7669a9
PNA
117 /* This is a resent of a destroy event? If so, skip missed */
118 unsigned long missed = e->pid ? 0 : e->missed;
119
0cebe4b4
PM
120 if (!((eventmask | missed) & e->ctmask))
121 goto out_unlock;
122
dd7669a9
PNA
123 ret = notify->fcn(eventmask | missed, &item);
124 if (unlikely(ret < 0 || missed)) {
125 spin_lock_bh(&ct->lock);
126 if (ret < 0) {
127 /* This is a destroy event that has been
128 * triggered by a process, we store the PID
129 * to include it in the retransmission. */
130 if (eventmask & (1 << IPCT_DESTROY) &&
131 e->pid == 0 && pid != 0)
132 e->pid = pid;
133 else
134 e->missed |= eventmask;
135 } else
136 e->missed &= ~missed;
137 spin_unlock_bh(&ct->lock);
138 }
e34d5c1a
PNA
139 }
140out_unlock:
141 rcu_read_unlock();
dd7669a9 142 return ret;
f6180121
MJ
143}
144
dd7669a9 145static inline int
a0891aa6
PNA
146nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct,
147 u32 pid, int report)
148{
dd7669a9 149 return nf_conntrack_eventmask_report(1 << event, ct, pid, report);
a0891aa6
PNA
150}
151
dd7669a9 152static inline int
19abb7b0
PNA
153nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
154{
dd7669a9 155 return nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
19abb7b0
PNA
156}
157
158struct nf_exp_event {
159 struct nf_conntrack_expect *exp;
160 u32 pid;
161 int report;
162};
163
e34d5c1a
PNA
164struct nf_exp_event_notifier {
165 int (*fcn)(unsigned int events, struct nf_exp_event *item);
166};
167
70e9942f
PNA
168extern int nf_ct_expect_register_notifier(struct net *net, struct nf_exp_event_notifier *nb);
169extern void nf_ct_expect_unregister_notifier(struct net *net, struct nf_exp_event_notifier *nb);
010c7d6f 170
19abb7b0
PNA
171static inline void
172nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
173 struct nf_conntrack_expect *exp,
174 u32 pid,
175 int report)
176{
70e9942f 177 struct net *net = nf_ct_exp_net(exp);
e34d5c1a 178 struct nf_exp_event_notifier *notify;
0cebe4b4 179 struct nf_conntrack_ecache *e;
e34d5c1a
PNA
180
181 rcu_read_lock();
70e9942f 182 notify = rcu_dereference(net->ct.nf_expect_event_cb);
e34d5c1a
PNA
183 if (notify == NULL)
184 goto out_unlock;
185
0cebe4b4
PM
186 e = nf_ct_ecache_find(exp->master);
187 if (e == NULL)
a0891aa6
PNA
188 goto out_unlock;
189
0cebe4b4 190 if (e->expmask & (1 << event)) {
e34d5c1a
PNA
191 struct nf_exp_event item = {
192 .exp = exp,
193 .pid = pid,
194 .report = report
195 };
a0891aa6 196 notify->fcn(1 << event, &item);
e34d5c1a
PNA
197 }
198out_unlock:
199 rcu_read_unlock();
19abb7b0
PNA
200}
201
f6180121 202static inline void
6823645d
PM
203nf_ct_expect_event(enum ip_conntrack_expect_events event,
204 struct nf_conntrack_expect *exp)
f6180121 205{
19abb7b0 206 nf_ct_expect_event_report(event, exp, 0, 0);
f6180121
MJ
207}
208
6058fa6b
AD
209extern int nf_conntrack_ecache_init(struct net *net);
210extern void nf_conntrack_ecache_fini(struct net *net);
211
f6180121
MJ
212#else /* CONFIG_NF_CONNTRACK_EVENTS */
213
214static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
64f1b653 215 struct nf_conn *ct) {}
dd7669a9
PNA
216static inline int nf_conntrack_eventmask_report(unsigned int eventmask,
217 struct nf_conn *ct,
218 u32 pid,
219 int report) { return 0; }
220static inline int nf_conntrack_event(enum ip_conntrack_events event,
221 struct nf_conn *ct) { return 0; }
222static inline int nf_conntrack_event_report(enum ip_conntrack_events event,
223 struct nf_conn *ct,
224 u32 pid,
225 int report) { return 0; }
f6180121 226static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
6823645d
PM
227static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event,
228 struct nf_conntrack_expect *exp) {}
19abb7b0
PNA
229static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
230 struct nf_conntrack_expect *exp,
231 u32 pid,
232 int report) {}
6058fa6b
AD
233
234static inline int nf_conntrack_ecache_init(struct net *net)
235{
236 return 0;
bb21c95e 237}
6058fa6b
AD
238
239static inline void nf_conntrack_ecache_fini(struct net *net)
240{
241}
f6180121
MJ
242#endif /* CONFIG_NF_CONNTRACK_EVENTS */
243
244#endif /*_NF_CONNTRACK_ECACHE_H*/
245
This page took 0.468939 seconds and 5 git commands to generate.