blob: 12d967b587264af71c84d62faca95a4e7ace096f [file] [log] [blame]
Martin Josefssonf6180122006-11-29 02:35:01 +01001/*
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
Alexey Dobriyan6058fa62008-10-08 11:35:07 +02009#include <net/net_namespace.h>
Martin Josefssonf6180122006-11-29 02:35:01 +010010#include <net/netfilter/nf_conntrack_expect.h>
Pablo Neira Ayusoa0891aa2009-06-13 12:26:29 +020011#include <linux/netfilter/nf_conntrack_common.h>
12#include <linux/netfilter/nf_conntrack_tuple_common.h>
13#include <net/netfilter/nf_conntrack_extend.h>
Martin Josefssonf6180122006-11-29 02:35:01 +010014
Florian Westphal616b14b2016-08-25 15:33:30 +020015enum nf_ct_ecache_state {
16 NFCT_ECACHE_UNKNOWN, /* destroy event not sent */
17 NFCT_ECACHE_DESTROY_FAIL, /* tried but failed to send destroy event */
18 NFCT_ECACHE_DESTROY_SENT, /* sent destroy event after failure */
19};
20
Pablo Neira Ayusoa0891aa2009-06-13 12:26:29 +020021struct nf_conntrack_ecache {
Florian Westphal616b14b2016-08-25 15:33:30 +020022 unsigned long cache; /* bitops want long */
23 unsigned long missed; /* missed events */
24 u16 ctmask; /* bitmask of ct events to be delivered */
25 u16 expmask; /* bitmask of expect events to be delivered */
26 u32 portid; /* netlink portid of destroyer */
27 enum nf_ct_ecache_state state; /* ecache state */
Pablo Neira Ayusoa0891aa2009-06-13 12:26:29 +020028};
29
30static inline struct nf_conntrack_ecache *
31nf_ct_ecache_find(const struct nf_conn *ct)
32{
Changli Gaoe0e76c82010-11-15 12:23:24 +010033#ifdef CONFIG_NF_CONNTRACK_EVENTS
Pablo Neira Ayusoa0891aa2009-06-13 12:26:29 +020034 return nf_ct_ext_find(ct, NF_CT_EXT_ECACHE);
Changli Gaoe0e76c82010-11-15 12:23:24 +010035#else
36 return NULL;
37#endif
Pablo Neira Ayusoa0891aa2009-06-13 12:26:29 +020038}
39
40static inline struct nf_conntrack_ecache *
Patrick McHardy0cebe4b2010-02-03 13:51:51 +010041nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp)
Pablo Neira Ayusoa0891aa2009-06-13 12:26:29 +020042{
Changli Gaoe0e76c82010-11-15 12:23:24 +010043#ifdef CONFIG_NF_CONNTRACK_EVENTS
Pablo Neira Ayusoa0891aa2009-06-13 12:26:29 +020044 struct net *net = nf_ct_net(ct);
Patrick McHardy0cebe4b2010-02-03 13:51:51 +010045 struct nf_conntrack_ecache *e;
Pablo Neira Ayusoa0891aa2009-06-13 12:26:29 +020046
Patrick McHardy0cebe4b2010-02-03 13:51:51 +010047 if (!ctmask && !expmask && net->ct.sysctl_events) {
48 ctmask = ~0;
49 expmask = ~0;
50 }
51 if (!ctmask && !expmask)
Pablo Neira Ayusoa0891aa2009-06-13 12:26:29 +020052 return NULL;
53
Patrick McHardy0cebe4b2010-02-03 13:51:51 +010054 e = nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp);
55 if (e) {
56 e->ctmask = ctmask;
57 e->expmask = expmask;
58 }
59 return e;
Changli Gaoe0e76c82010-11-15 12:23:24 +010060#else
61 return NULL;
62#endif
Pablo Neira Ayuso6bfea192009-06-02 20:08:44 +020063};
64
Martin Josefssonf6180122006-11-29 02:35:01 +010065#ifdef CONFIG_NF_CONNTRACK_EVENTS
Pablo Neira Ayuso19abb7b2008-11-18 11:56:20 +010066/* This structure is passed to event handler */
67struct nf_ct_event {
68 struct nf_conn *ct;
Eric W. Biederman15e47302012-09-07 20:12:54 +000069 u32 portid;
Pablo Neira Ayuso19abb7b2008-11-18 11:56:20 +010070 int report;
71};
72
Pablo Neira Ayusoe34d5c12009-06-03 10:32:06 +020073struct nf_ct_event_notifier {
74 int (*fcn)(unsigned int events, struct nf_ct_event *item);
75};
76
Joe Perches4e77be42013-09-23 11:37:48 -070077int nf_conntrack_register_notifier(struct net *net,
78 struct nf_ct_event_notifier *nb);
79void nf_conntrack_unregister_notifier(struct net *net,
80 struct nf_ct_event_notifier *nb);
Martin Josefssonf6180122006-11-29 02:35:01 +010081
Joe Perches4e77be42013-09-23 11:37:48 -070082void nf_ct_deliver_cached_events(struct nf_conn *ct);
Florian Westphal3c435e22016-04-11 21:52:35 +020083int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct,
84 u32 portid, int report);
Martin Josefssonf6180122006-11-29 02:35:01 +010085
86static inline void
Alexey Dobriyana71996f2008-10-08 11:35:07 +020087nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
Martin Josefssonf6180122006-11-29 02:35:01 +010088{
Pablo Neira Ayuso70e99422011-11-22 00:16:51 +010089 struct net *net = nf_ct_net(ct);
Pablo Neira Ayusoa0891aa2009-06-13 12:26:29 +020090 struct nf_conntrack_ecache *e;
Martin Josefssonf6180122006-11-29 02:35:01 +010091
Pablo Neira Ayuso6bd04052012-07-05 15:42:10 +020092 if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
Pablo Neira Ayusoa0891aa2009-06-13 12:26:29 +020093 return;
94
95 e = nf_ct_ecache_find(ct);
96 if (e == NULL)
97 return;
98
99 set_bit(event, &e->cache);
Martin Josefssonf6180122006-11-29 02:35:01 +0100100}
101
Pablo Neira Ayusodd7669a2009-06-13 12:30:52 +0200102static inline int
Pablo Neira Ayusoa0891aa2009-06-13 12:26:29 +0200103nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct,
Eric W. Biederman15e47302012-09-07 20:12:54 +0000104 u32 portid, int report)
Pablo Neira Ayusoa0891aa2009-06-13 12:26:29 +0200105{
Florian Westphal3c435e22016-04-11 21:52:35 +0200106 const struct net *net = nf_ct_net(ct);
107
108 if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
109 return 0;
110
Eric W. Biederman15e47302012-09-07 20:12:54 +0000111 return nf_conntrack_eventmask_report(1 << event, ct, portid, report);
Pablo Neira Ayusoa0891aa2009-06-13 12:26:29 +0200112}
113
Pablo Neira Ayusodd7669a2009-06-13 12:30:52 +0200114static inline int
Pablo Neira Ayuso19abb7b2008-11-18 11:56:20 +0100115nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
116{
Florian Westphal3c435e22016-04-11 21:52:35 +0200117 const struct net *net = nf_ct_net(ct);
118
119 if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
120 return 0;
121
Pablo Neira Ayusodd7669a2009-06-13 12:30:52 +0200122 return nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
Pablo Neira Ayuso19abb7b2008-11-18 11:56:20 +0100123}
124
125struct nf_exp_event {
126 struct nf_conntrack_expect *exp;
Eric W. Biederman15e47302012-09-07 20:12:54 +0000127 u32 portid;
Pablo Neira Ayuso19abb7b2008-11-18 11:56:20 +0100128 int report;
129};
130
Pablo Neira Ayusoe34d5c12009-06-03 10:32:06 +0200131struct nf_exp_event_notifier {
132 int (*fcn)(unsigned int events, struct nf_exp_event *item);
133};
134
Joe Perches4e77be42013-09-23 11:37:48 -0700135int nf_ct_expect_register_notifier(struct net *net,
136 struct nf_exp_event_notifier *nb);
137void nf_ct_expect_unregister_notifier(struct net *net,
138 struct nf_exp_event_notifier *nb);
Patrick McHardy010c7d62007-03-14 16:40:10 -0700139
Florian Westphalecdfb482016-04-11 21:52:36 +0200140void nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
141 struct nf_conntrack_expect *exp,
142 u32 portid, int report);
Martin Josefssonf6180122006-11-29 02:35:01 +0100143
Joe Perches4e77be42013-09-23 11:37:48 -0700144int nf_conntrack_ecache_pernet_init(struct net *net);
145void nf_conntrack_ecache_pernet_fini(struct net *net);
Alexey Dobriyan6058fa62008-10-08 11:35:07 +0200146
Joe Perches4e77be42013-09-23 11:37:48 -0700147int nf_conntrack_ecache_init(void);
148void nf_conntrack_ecache_fini(void);
Martin Josefssonf6180122006-11-29 02:35:01 +0100149
Florian Westphal95005072014-06-10 23:12:56 +0200150static inline void nf_conntrack_ecache_delayed_work(struct net *net)
151{
152 if (!delayed_work_pending(&net->ct.ecache_dwork)) {
153 schedule_delayed_work(&net->ct.ecache_dwork, HZ);
154 net->ct.ecache_dwork_pending = true;
155 }
156}
157
158static inline void nf_conntrack_ecache_work(struct net *net)
159{
160 if (net->ct.ecache_dwork_pending) {
161 net->ct.ecache_dwork_pending = false;
162 mod_delayed_work(system_wq, &net->ct.ecache_dwork, 0);
163 }
164}
165#else /* CONFIG_NF_CONNTRACK_EVENTS */
Martin Josefssonf6180122006-11-29 02:35:01 +0100166static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
Linus Torvalds64f1b6532008-10-11 09:46:24 -0700167 struct nf_conn *ct) {}
Pablo Neira Ayusodd7669a2009-06-13 12:30:52 +0200168static inline int nf_conntrack_eventmask_report(unsigned int eventmask,
169 struct nf_conn *ct,
Eric W. Biederman15e47302012-09-07 20:12:54 +0000170 u32 portid,
Pablo Neira Ayusodd7669a2009-06-13 12:30:52 +0200171 int report) { return 0; }
172static inline int nf_conntrack_event(enum ip_conntrack_events event,
173 struct nf_conn *ct) { return 0; }
174static inline int nf_conntrack_event_report(enum ip_conntrack_events event,
175 struct nf_conn *ct,
Eric W. Biederman15e47302012-09-07 20:12:54 +0000176 u32 portid,
Pablo Neira Ayusodd7669a2009-06-13 12:30:52 +0200177 int report) { return 0; }
Martin Josefssonf6180122006-11-29 02:35:01 +0100178static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
Pablo Neira Ayuso19abb7b2008-11-18 11:56:20 +0100179static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
180 struct nf_conntrack_expect *exp,
Eric W. Biederman15e47302012-09-07 20:12:54 +0000181 u32 portid,
Pablo Neira Ayuso19abb7b2008-11-18 11:56:20 +0100182 int report) {}
Alexey Dobriyan6058fa62008-10-08 11:35:07 +0200183
Gao feng3fe0f942013-01-21 22:10:28 +0000184static inline int nf_conntrack_ecache_pernet_init(struct net *net)
Alexey Dobriyan6058fa62008-10-08 11:35:07 +0200185{
186 return 0;
Guo-Fu Tsengbb21c952008-10-09 21:10:36 -0700187}
Alexey Dobriyan6058fa62008-10-08 11:35:07 +0200188
Gao feng3fe0f942013-01-21 22:10:28 +0000189static inline void nf_conntrack_ecache_pernet_fini(struct net *net)
190{
191}
192
193static inline int nf_conntrack_ecache_init(void)
194{
195 return 0;
196}
197
198static inline void nf_conntrack_ecache_fini(void)
Alexey Dobriyan6058fa62008-10-08 11:35:07 +0200199{
200}
Florian Westphal95005072014-06-10 23:12:56 +0200201
202static inline void nf_conntrack_ecache_delayed_work(struct net *net)
203{
204}
205
206static inline void nf_conntrack_ecache_work(struct net *net)
207{
208}
Martin Josefssonf6180122006-11-29 02:35:01 +0100209#endif /* CONFIG_NF_CONNTRACK_EVENTS */
210
211#endif /*_NF_CONNTRACK_ECACHE_H*/
212