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 ctmask; /* bitmask of ct events to be delivered */ 25 u16 expmask; /* bitmask of expect events to be delivered */ 26 enum nf_ct_ecache_state state:8;/* ecache state */ 27 u32 missed; /* missed events */ 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_exp_event { 76 struct nf_conntrack_expect *exp; 77 u32 portid; 78 int report; 79 }; 80 81 struct nf_ct_event_notifier { 82 int (*ct_event)(unsigned int events, const struct nf_ct_event *item); 83 int (*exp_event)(unsigned int events, const struct nf_exp_event *item); 84 }; 85 86 void nf_conntrack_register_notifier(struct net *net, 87 const struct nf_ct_event_notifier *nb); 88 void nf_conntrack_unregister_notifier(struct net *net); 89 90 void nf_ct_deliver_cached_events(struct nf_conn *ct); 91 int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct, 92 u32 portid, int report); 93 94 #else 95 96 static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) 97 { 98 } 99 100 static inline int nf_conntrack_eventmask_report(unsigned int eventmask, 101 struct nf_conn *ct, 102 u32 portid, 103 int report) 104 { 105 return 0; 106 } 107 108 #endif 109 110 static inline void 111 nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) 112 { 113 #ifdef CONFIG_NF_CONNTRACK_EVENTS 114 struct net *net = nf_ct_net(ct); 115 struct nf_conntrack_ecache *e; 116 117 if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) 118 return; 119 120 e = nf_ct_ecache_find(ct); 121 if (e == NULL) 122 return; 123 124 set_bit(event, &e->cache); 125 #endif 126 } 127 128 static inline int 129 nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct, 130 u32 portid, int report) 131 { 132 #ifdef CONFIG_NF_CONNTRACK_EVENTS 133 const struct net *net = nf_ct_net(ct); 134 135 if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) 136 return 0; 137 138 return nf_conntrack_eventmask_report(1 << event, ct, portid, report); 139 #else 140 return 0; 141 #endif 142 } 143 144 static inline int 145 nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) 146 { 147 #ifdef CONFIG_NF_CONNTRACK_EVENTS 148 const struct net *net = nf_ct_net(ct); 149 150 if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) 151 return 0; 152 153 return nf_conntrack_eventmask_report(1 << event, ct, 0, 0); 154 #else 155 return 0; 156 #endif 157 } 158 159 #ifdef CONFIG_NF_CONNTRACK_EVENTS 160 void nf_ct_expect_event_report(enum ip_conntrack_expect_events event, 161 struct nf_conntrack_expect *exp, 162 u32 portid, int report); 163 164 void nf_conntrack_ecache_work(struct net *net, enum nf_ct_ecache_state state); 165 166 void nf_conntrack_ecache_pernet_init(struct net *net); 167 void nf_conntrack_ecache_pernet_fini(struct net *net); 168 169 static inline bool nf_conntrack_ecache_dwork_pending(const struct net *net) 170 { 171 return net->ct.ecache_dwork_pending; 172 } 173 #else /* CONFIG_NF_CONNTRACK_EVENTS */ 174 175 static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e, 176 struct nf_conntrack_expect *exp, 177 u32 portid, 178 int report) 179 { 180 } 181 182 static inline void nf_conntrack_ecache_work(struct net *net, 183 enum nf_ct_ecache_state s) 184 { 185 } 186 187 static inline void nf_conntrack_ecache_pernet_init(struct net *net) 188 { 189 } 190 191 static inline void nf_conntrack_ecache_pernet_fini(struct net *net) 192 { 193 } 194 static inline bool nf_conntrack_ecache_dwork_pending(const struct net *net) { return false; } 195 #endif /* CONFIG_NF_CONNTRACK_EVENTS */ 196 #endif /*_NF_CONNTRACK_ECACHE_H*/ 197