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 /* This structure is passed to event handler */ 68 struct nf_ct_event { 69 struct nf_conn *ct; 70 u32 portid; 71 int report; 72 }; 73 74 struct nf_ct_event_notifier { 75 int (*fcn)(unsigned int events, struct nf_ct_event *item); 76 }; 77 78 int nf_conntrack_register_notifier(struct net *net, 79 struct nf_ct_event_notifier *nb); 80 void nf_conntrack_unregister_notifier(struct net *net, 81 struct nf_ct_event_notifier *nb); 82 83 void nf_ct_deliver_cached_events(struct nf_conn *ct); 84 int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct, 85 u32 portid, int report); 86 87 static inline void 88 nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) 89 { 90 struct net *net = nf_ct_net(ct); 91 struct nf_conntrack_ecache *e; 92 93 if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) 94 return; 95 96 e = nf_ct_ecache_find(ct); 97 if (e == NULL) 98 return; 99 100 set_bit(event, &e->cache); 101 } 102 103 static inline int 104 nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct, 105 u32 portid, int report) 106 { 107 const struct net *net = nf_ct_net(ct); 108 109 if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) 110 return 0; 111 112 return nf_conntrack_eventmask_report(1 << event, ct, portid, report); 113 } 114 115 static inline int 116 nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) 117 { 118 const struct net *net = nf_ct_net(ct); 119 120 if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) 121 return 0; 122 123 return nf_conntrack_eventmask_report(1 << event, ct, 0, 0); 124 } 125 126 struct nf_exp_event { 127 struct nf_conntrack_expect *exp; 128 u32 portid; 129 int report; 130 }; 131 132 struct nf_exp_event_notifier { 133 int (*fcn)(unsigned int events, struct nf_exp_event *item); 134 }; 135 136 int nf_ct_expect_register_notifier(struct net *net, 137 struct nf_exp_event_notifier *nb); 138 void nf_ct_expect_unregister_notifier(struct net *net, 139 struct nf_exp_event_notifier *nb); 140 141 void nf_ct_expect_event_report(enum ip_conntrack_expect_events event, 142 struct nf_conntrack_expect *exp, 143 u32 portid, int report); 144 145 void nf_conntrack_ecache_pernet_init(struct net *net); 146 void nf_conntrack_ecache_pernet_fini(struct net *net); 147 148 int nf_conntrack_ecache_init(void); 149 void nf_conntrack_ecache_fini(void); 150 151 static inline void nf_conntrack_ecache_delayed_work(struct net *net) 152 { 153 if (!delayed_work_pending(&net->ct.ecache_dwork)) { 154 schedule_delayed_work(&net->ct.ecache_dwork, HZ); 155 net->ct.ecache_dwork_pending = true; 156 } 157 } 158 159 static inline void nf_conntrack_ecache_work(struct net *net) 160 { 161 if (net->ct.ecache_dwork_pending) { 162 net->ct.ecache_dwork_pending = false; 163 mod_delayed_work(system_wq, &net->ct.ecache_dwork, 0); 164 } 165 } 166 #else /* CONFIG_NF_CONNTRACK_EVENTS */ 167 static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, 168 struct nf_conn *ct) {} 169 static inline int nf_conntrack_eventmask_report(unsigned int eventmask, 170 struct nf_conn *ct, 171 u32 portid, 172 int report) { return 0; } 173 static inline int nf_conntrack_event(enum ip_conntrack_events event, 174 struct nf_conn *ct) { return 0; } 175 static inline int nf_conntrack_event_report(enum ip_conntrack_events event, 176 struct nf_conn *ct, 177 u32 portid, 178 int report) { return 0; } 179 static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {} 180 static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e, 181 struct nf_conntrack_expect *exp, 182 u32 portid, 183 int report) {} 184 185 static inline void nf_conntrack_ecache_pernet_init(struct net *net) {} 186 187 static inline void nf_conntrack_ecache_pernet_fini(struct net *net) 188 { 189 } 190 191 static inline int nf_conntrack_ecache_init(void) 192 { 193 return 0; 194 } 195 196 static inline void nf_conntrack_ecache_fini(void) 197 { 198 } 199 200 static inline void nf_conntrack_ecache_delayed_work(struct net *net) 201 { 202 } 203 204 static inline void nf_conntrack_ecache_work(struct net *net) 205 { 206 } 207 #endif /* CONFIG_NF_CONNTRACK_EVENTS */ 208 209 #endif /*_NF_CONNTRACK_ECACHE_H*/ 210 211