1
2
3
4
5
6#ifndef _NF_CONNTRACK_ECACHE_H
7#define _NF_CONNTRACK_ECACHE_H
8#include <net/netfilter/nf_conntrack.h>
9
10#include <net/net_namespace.h>
11#include <net/netfilter/nf_conntrack_expect.h>
12#include <linux/netfilter/nf_conntrack_common.h>
13#include <linux/netfilter/nf_conntrack_tuple_common.h>
14#include <net/netfilter/nf_conntrack_extend.h>
15
16enum nf_ct_ecache_state {
17 NFCT_ECACHE_UNKNOWN,
18 NFCT_ECACHE_DESTROY_FAIL,
19 NFCT_ECACHE_DESTROY_SENT,
20};
21
22struct nf_conntrack_ecache {
23 unsigned long cache;
24 u16 missed;
25 u16 ctmask;
26 u16 expmask;
27 enum nf_ct_ecache_state state:8;
28 u32 portid;
29};
30
31static inline struct nf_conntrack_ecache *
32nf_ct_ecache_find(const struct nf_conn *ct)
33{
34#ifdef CONFIG_NF_CONNTRACK_EVENTS
35 return nf_ct_ext_find(ct, NF_CT_EXT_ECACHE);
36#else
37 return NULL;
38#endif
39}
40
41static inline struct nf_conntrack_ecache *
42nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp)
43{
44#ifdef CONFIG_NF_CONNTRACK_EVENTS
45 struct net *net = nf_ct_net(ct);
46 struct nf_conntrack_ecache *e;
47
48 if (!ctmask && !expmask && net->ct.sysctl_events) {
49 ctmask = ~0;
50 expmask = ~0;
51 }
52 if (!ctmask && !expmask)
53 return NULL;
54
55 e = nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp);
56 if (e) {
57 e->ctmask = ctmask;
58 e->expmask = expmask;
59 }
60 return e;
61#else
62 return NULL;
63#endif
64}
65
66#ifdef CONFIG_NF_CONNTRACK_EVENTS
67
68
69struct nf_ct_event {
70 struct nf_conn *ct;
71 u32 portid;
72 int report;
73};
74
75struct nf_ct_event_notifier {
76 int (*fcn)(unsigned int events, struct nf_ct_event *item);
77};
78
79int nf_conntrack_register_notifier(struct net *net,
80 struct nf_ct_event_notifier *nb);
81void nf_conntrack_unregister_notifier(struct net *net,
82 struct nf_ct_event_notifier *nb);
83
84void nf_ct_deliver_cached_events(struct nf_conn *ct);
85int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct,
86 u32 portid, int report);
87
88#else
89
90static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct)
91{
92}
93
94static inline int nf_conntrack_eventmask_report(unsigned int eventmask,
95 struct nf_conn *ct,
96 u32 portid,
97 int report)
98{
99 return 0;
100}
101
102#endif
103
104static inline void
105nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
106{
107#ifdef CONFIG_NF_CONNTRACK_EVENTS
108 struct net *net = nf_ct_net(ct);
109 struct nf_conntrack_ecache *e;
110
111 if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
112 return;
113
114 e = nf_ct_ecache_find(ct);
115 if (e == NULL)
116 return;
117
118 set_bit(event, &e->cache);
119#endif
120}
121
122static inline int
123nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct,
124 u32 portid, int report)
125{
126#ifdef CONFIG_NF_CONNTRACK_EVENTS
127 const struct net *net = nf_ct_net(ct);
128
129 if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
130 return 0;
131
132 return nf_conntrack_eventmask_report(1 << event, ct, portid, report);
133#else
134 return 0;
135#endif
136}
137
138static inline int
139nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
140{
141#ifdef CONFIG_NF_CONNTRACK_EVENTS
142 const struct net *net = nf_ct_net(ct);
143
144 if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
145 return 0;
146
147 return nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
148#else
149 return 0;
150#endif
151}
152
153#ifdef CONFIG_NF_CONNTRACK_EVENTS
154
155struct nf_exp_event {
156 struct nf_conntrack_expect *exp;
157 u32 portid;
158 int report;
159};
160
161struct nf_exp_event_notifier {
162 int (*fcn)(unsigned int events, struct nf_exp_event *item);
163};
164
165int nf_ct_expect_register_notifier(struct net *net,
166 struct nf_exp_event_notifier *nb);
167void nf_ct_expect_unregister_notifier(struct net *net,
168 struct nf_exp_event_notifier *nb);
169
170void nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
171 struct nf_conntrack_expect *exp,
172 u32 portid, int report);
173
174void nf_conntrack_ecache_pernet_init(struct net *net);
175void nf_conntrack_ecache_pernet_fini(struct net *net);
176
177int nf_conntrack_ecache_init(void);
178void nf_conntrack_ecache_fini(void);
179
180#else
181
182static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
183 struct nf_conntrack_expect *exp,
184 u32 portid,
185 int report)
186{
187}
188
189static inline void nf_conntrack_ecache_pernet_init(struct net *net)
190{
191}
192
193static inline void nf_conntrack_ecache_pernet_fini(struct net *net)
194{
195}
196
197static inline int nf_conntrack_ecache_init(void)
198{
199 return 0;
200}
201
202static inline void nf_conntrack_ecache_fini(void)
203{
204}
205
206#endif
207
208static inline void nf_conntrack_ecache_delayed_work(struct net *net)
209{
210#ifdef CONFIG_NF_CONNTRACK_EVENTS
211 if (!delayed_work_pending(&net->ct.ecache_dwork)) {
212 schedule_delayed_work(&net->ct.ecache_dwork, HZ);
213 net->ct.ecache_dwork_pending = true;
214 }
215#endif
216}
217
218static inline void nf_conntrack_ecache_work(struct net *net)
219{
220#ifdef CONFIG_NF_CONNTRACK_EVENTS
221 if (net->ct.ecache_dwork_pending) {
222 net->ct.ecache_dwork_pending = false;
223 mod_delayed_work(system_wq, &net->ct.ecache_dwork, 0);
224 }
225#endif
226}
227
228#endif
229