1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * connection tracking event cache. 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 16 enum nf_ct_ecache_state { 17 NFCT_ECACHE_UNKNOWN, /* destroy event not sent */ 18 NFCT_ECACHE_DESTROY_FAIL, /* tried but failed to send destroy event */ 19 NFCT_ECACHE_DESTROY_SENT, /* sent destroy event after failure */ 20 }; 21 22 struct nf_conntrack_ecache { 23 unsigned long cache; /* bitops want long */ 24 u16 missed; /* missed events */ 25 u16 ctmask; /* bitmask of ct events to be delivered */ 26 u16 expmask; /* bitmask of expect events to be delivered */ 27 enum nf_ct_ecache_state state:8;/* ecache state */ 28 u32 portid; /* netlink portid of destroyer */ 29 }; 30 31 static inline struct nf_conntrack_ecache * 32 nf_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 41 static inline struct nf_conntrack_ecache * 42 nf_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 /* This structure is passed to event handler */ 69 struct nf_ct_event { 70 struct nf_conn *ct; 71 u32 portid; 72 int report; 73 }; 74 75 struct nf_ct_event_notifier { 76 int (*fcn)(unsigned int events, struct nf_ct_event *item); 77 }; 78 79 int nf_conntrack_register_notifier(struct net *net, 80 struct nf_ct_event_notifier *nb); 81 void nf_conntrack_unregister_notifier(struct net *net, 82 struct nf_ct_event_notifier *nb); 83 84 void nf_ct_deliver_cached_events(struct nf_conn *ct); 85 int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct, 86 u32 portid, int report); 87 88 #else 89 90 static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) 91 { 92 } 93 94 static 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 104 static inline void 105 nf_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 122 static inline int 123 nf_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 138 static inline int 139 nf_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 155 struct nf_exp_event { 156 struct nf_conntrack_expect *exp; 157 u32 portid; 158 int report; 159 }; 160 161 struct nf_exp_event_notifier { 162 int (*fcn)(unsigned int events, struct nf_exp_event *item); 163 }; 164 165 int nf_ct_expect_register_notifier(struct net *net, 166 struct nf_exp_event_notifier *nb); 167 void nf_ct_expect_unregister_notifier(struct net *net, 168 struct nf_exp_event_notifier *nb); 169 170 void nf_ct_expect_event_report(enum ip_conntrack_expect_events event, 171 struct nf_conntrack_expect *exp, 172 u32 portid, int report); 173 174 void nf_conntrack_ecache_pernet_init(struct net *net); 175 void nf_conntrack_ecache_pernet_fini(struct net *net); 176 177 int nf_conntrack_ecache_init(void); 178 void nf_conntrack_ecache_fini(void); 179 180 #else /* CONFIG_NF_CONNTRACK_EVENTS */ 181 182 static 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 189 static inline void nf_conntrack_ecache_pernet_init(struct net *net) 190 { 191 } 192 193 static inline void nf_conntrack_ecache_pernet_fini(struct net *net) 194 { 195 } 196 197 static inline int nf_conntrack_ecache_init(void) 198 { 199 return 0; 200 } 201 202 static inline void nf_conntrack_ecache_fini(void) 203 { 204 } 205 206 #endif /* CONFIG_NF_CONNTRACK_EVENTS */ 207 208 static 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 218 static 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 /*_NF_CONNTRACK_ECACHE_H*/ 229