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_work(struct net *net, enum nf_ct_ecache_state state);
175
176void nf_conntrack_ecache_pernet_init(struct net *net);
177void nf_conntrack_ecache_pernet_fini(struct net *net);
178
179int nf_conntrack_ecache_init(void);
180void nf_conntrack_ecache_fini(void);
181
182static inline bool nf_conntrack_ecache_dwork_pending(const struct net *net)
183{
184 return net->ct.ecache_dwork_pending;
185}
186#else
187
188static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
189 struct nf_conntrack_expect *exp,
190 u32 portid,
191 int report)
192{
193}
194
195static inline void nf_conntrack_ecache_work(struct net *net,
196 enum nf_ct_ecache_state s)
197{
198}
199
200static inline void nf_conntrack_ecache_pernet_init(struct net *net)
201{
202}
203
204static inline void nf_conntrack_ecache_pernet_fini(struct net *net)
205{
206}
207
208static inline int nf_conntrack_ecache_init(void)
209{
210 return 0;
211}
212
213static inline void nf_conntrack_ecache_fini(void)
214{
215}
216
217static inline bool nf_conntrack_ecache_dwork_pending(const struct net *net) { return false; }
218#endif
219#endif
220