Commit | Line | Data |
---|---|---|
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 | 15 | struct 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 */ | |
15e47304 | 20 | u32 portid; /* netlink portid of destroyer */ |
a0891aa6 | 21 | }; |
6bfea198 | 22 | |
a0891aa6 PNA |
23 | static inline struct nf_conntrack_ecache * |
24 | nf_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 | 33 | static inline struct nf_conntrack_ecache * |
0cebe4b4 | 34 | nf_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 */ |
60 | struct nf_ct_event { | |
61 | struct nf_conn *ct; | |
15e47304 | 62 | u32 portid; |
19abb7b0 PNA |
63 | int report; |
64 | }; | |
65 | ||
e34d5c1a PNA |
66 | struct nf_ct_event_notifier { |
67 | int (*fcn)(unsigned int events, struct nf_ct_event *item); | |
68 | }; | |
69 | ||
4e77be46 JP |
70 | int nf_conntrack_register_notifier(struct net *net, |
71 | struct nf_ct_event_notifier *nb); | |
72 | void nf_conntrack_unregister_notifier(struct net *net, | |
73 | struct nf_ct_event_notifier *nb); | |
f6180121 | 74 | |
4e77be46 | 75 | void nf_ct_deliver_cached_events(struct nf_conn *ct); |
3c435e2e FW |
76 | int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct, |
77 | u32 portid, int report); | |
f6180121 MJ |
78 | |
79 | static inline void | |
a71996fc | 80 | nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) |
f6180121 | 81 | { |
70e9942f | 82 | struct net *net = nf_ct_net(ct); |
a0891aa6 PNA |
83 | struct nf_conntrack_ecache *e; |
84 | ||
6bd0405b | 85 | if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) |
a0891aa6 PNA |
86 | return; |
87 | ||
88 | e = nf_ct_ecache_find(ct); | |
89 | if (e == NULL) | |
90 | return; | |
91 | ||
92 | set_bit(event, &e->cache); | |
f6180121 MJ |
93 | } |
94 | ||
dd7669a9 | 95 | static inline int |
a0891aa6 | 96 | nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct, |
15e47304 | 97 | u32 portid, int report) |
a0891aa6 | 98 | { |
3c435e2e FW |
99 | const struct net *net = nf_ct_net(ct); |
100 | ||
101 | if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) | |
102 | return 0; | |
103 | ||
15e47304 | 104 | return nf_conntrack_eventmask_report(1 << event, ct, portid, report); |
a0891aa6 PNA |
105 | } |
106 | ||
dd7669a9 | 107 | static inline int |
19abb7b0 PNA |
108 | nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) |
109 | { | |
3c435e2e FW |
110 | const struct net *net = nf_ct_net(ct); |
111 | ||
112 | if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) | |
113 | return 0; | |
114 | ||
dd7669a9 | 115 | return nf_conntrack_eventmask_report(1 << event, ct, 0, 0); |
19abb7b0 PNA |
116 | } |
117 | ||
118 | struct nf_exp_event { | |
119 | struct nf_conntrack_expect *exp; | |
15e47304 | 120 | u32 portid; |
19abb7b0 PNA |
121 | int report; |
122 | }; | |
123 | ||
e34d5c1a PNA |
124 | struct nf_exp_event_notifier { |
125 | int (*fcn)(unsigned int events, struct nf_exp_event *item); | |
126 | }; | |
127 | ||
4e77be46 JP |
128 | int nf_ct_expect_register_notifier(struct net *net, |
129 | struct nf_exp_event_notifier *nb); | |
130 | void nf_ct_expect_unregister_notifier(struct net *net, | |
131 | struct nf_exp_event_notifier *nb); | |
010c7d6f | 132 | |
ecdfb48c FW |
133 | void nf_ct_expect_event_report(enum ip_conntrack_expect_events event, |
134 | struct nf_conntrack_expect *exp, | |
135 | u32 portid, int report); | |
f6180121 | 136 | |
4e77be46 JP |
137 | int nf_conntrack_ecache_pernet_init(struct net *net); |
138 | void nf_conntrack_ecache_pernet_fini(struct net *net); | |
6058fa6b | 139 | |
4e77be46 JP |
140 | int nf_conntrack_ecache_init(void); |
141 | void nf_conntrack_ecache_fini(void); | |
f6180121 | 142 | |
9500507c FW |
143 | static inline void nf_conntrack_ecache_delayed_work(struct net *net) |
144 | { | |
145 | if (!delayed_work_pending(&net->ct.ecache_dwork)) { | |
146 | schedule_delayed_work(&net->ct.ecache_dwork, HZ); | |
147 | net->ct.ecache_dwork_pending = true; | |
148 | } | |
149 | } | |
150 | ||
151 | static inline void nf_conntrack_ecache_work(struct net *net) | |
152 | { | |
153 | if (net->ct.ecache_dwork_pending) { | |
154 | net->ct.ecache_dwork_pending = false; | |
155 | mod_delayed_work(system_wq, &net->ct.ecache_dwork, 0); | |
156 | } | |
157 | } | |
158 | #else /* CONFIG_NF_CONNTRACK_EVENTS */ | |
f6180121 | 159 | static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, |
64f1b653 | 160 | struct nf_conn *ct) {} |
dd7669a9 PNA |
161 | static inline int nf_conntrack_eventmask_report(unsigned int eventmask, |
162 | struct nf_conn *ct, | |
15e47304 | 163 | u32 portid, |
dd7669a9 PNA |
164 | int report) { return 0; } |
165 | static inline int nf_conntrack_event(enum ip_conntrack_events event, | |
166 | struct nf_conn *ct) { return 0; } | |
167 | static inline int nf_conntrack_event_report(enum ip_conntrack_events event, | |
168 | struct nf_conn *ct, | |
15e47304 | 169 | u32 portid, |
dd7669a9 | 170 | int report) { return 0; } |
f6180121 | 171 | static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {} |
19abb7b0 PNA |
172 | static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e, |
173 | struct nf_conntrack_expect *exp, | |
15e47304 | 174 | u32 portid, |
19abb7b0 | 175 | int report) {} |
6058fa6b | 176 | |
3fe0f943 | 177 | static inline int nf_conntrack_ecache_pernet_init(struct net *net) |
6058fa6b AD |
178 | { |
179 | return 0; | |
bb21c95e | 180 | } |
6058fa6b | 181 | |
3fe0f943 G |
182 | static inline void nf_conntrack_ecache_pernet_fini(struct net *net) |
183 | { | |
184 | } | |
185 | ||
186 | static inline int nf_conntrack_ecache_init(void) | |
187 | { | |
188 | return 0; | |
189 | } | |
190 | ||
191 | static inline void nf_conntrack_ecache_fini(void) | |
6058fa6b AD |
192 | { |
193 | } | |
9500507c FW |
194 | |
195 | static inline void nf_conntrack_ecache_delayed_work(struct net *net) | |
196 | { | |
197 | } | |
198 | ||
199 | static inline void nf_conntrack_ecache_work(struct net *net) | |
200 | { | |
201 | } | |
f6180121 MJ |
202 | #endif /* CONFIG_NF_CONNTRACK_EVENTS */ |
203 | ||
204 | #endif /*_NF_CONNTRACK_ECACHE_H*/ | |
205 |