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 #include <asm/local64.h> 16 17 enum nf_ct_ecache_state { 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 #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP 25 local64_t timestamp; /* event timestamp, in nanoseconds */ 26 #endif 27 u16 ctmask; /* bitmask of ct events to be delivered */ 28 u16 expmask; /* bitmask of expect events to be delivered */ 29 u32 missed; /* missed events */ 30 u32 portid; /* netlink portid of destroyer */ 31 }; 32 33 static inline struct nf_conntrack_ecache * 34 nf_ct_ecache_find(const struct nf_conn *ct) 35 { 36 #ifdef CONFIG_NF_CONNTRACK_EVENTS 37 return nf_ct_ext_find(ct, NF_CT_EXT_ECACHE); 38 #else 39 return NULL; 40 #endif 41 } 42 43 static inline bool nf_ct_ecache_exist(const struct nf_conn *ct) 44 { 45 #ifdef CONFIG_NF_CONNTRACK_EVENTS 46 return nf_ct_ext_exist(ct, NF_CT_EXT_ECACHE); 47 #else 48 return false; 49 #endif 50 } 51 52 #ifdef CONFIG_NF_CONNTRACK_EVENTS 53 54 /* This structure is passed to event handler */ 55 struct nf_ct_event { 56 struct nf_conn *ct; 57 u32 portid; 58 int report; 59 }; 60 61 struct nf_exp_event { 62 struct nf_conntrack_expect *exp; 63 u32 portid; 64 int report; 65 }; 66 67 struct nf_ct_event_notifier { 68 int (*ct_event)(unsigned int events, const struct nf_ct_event *item); 69 int (*exp_event)(unsigned int events, const struct nf_exp_event *item); 70 }; 71 72 void nf_conntrack_register_notifier(struct net *net, 73 const struct nf_ct_event_notifier *nb); 74 void nf_conntrack_unregister_notifier(struct net *net); 75 76 void nf_ct_deliver_cached_events(struct nf_conn *ct); 77 int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct, 78 u32 portid, int report); 79 80 bool nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp); 81 #else 82 83 static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) 84 { 85 } 86 87 static inline int nf_conntrack_eventmask_report(unsigned int eventmask, 88 struct nf_conn *ct, 89 u32 portid, 90 int report) 91 { 92 return 0; 93 } 94 95 static inline bool nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp) 96 { 97 return false; 98 } 99 #endif 100 101 static inline void 102 nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) 103 { 104 #ifdef CONFIG_NF_CONNTRACK_EVENTS 105 struct net *net = nf_ct_net(ct); 106 struct nf_conntrack_ecache *e; 107 108 if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) 109 return; 110 111 e = nf_ct_ecache_find(ct); 112 if (e == NULL) 113 return; 114 115 #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP 116 /* renew only if this is the first cached event, so that the 117 * timestamp reflects the first, not the last, generated event. 118 */ 119 if (local64_read(&e->timestamp) && READ_ONCE(e->cache) == 0) 120 local64_set(&e->timestamp, ktime_get_real_ns()); 121 #endif 122 123 set_bit(event, &e->cache); 124 #endif 125 } 126 127 static inline int 128 nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct, 129 u32 portid, int report) 130 { 131 #ifdef CONFIG_NF_CONNTRACK_EVENTS 132 if (nf_ct_ecache_exist(ct)) 133 return nf_conntrack_eventmask_report(1 << event, ct, portid, report); 134 #endif 135 return 0; 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 if (nf_ct_ecache_exist(ct)) 143 return nf_conntrack_eventmask_report(1 << event, ct, 0, 0); 144 #endif 145 return 0; 146 } 147 148 #ifdef CONFIG_NF_CONNTRACK_EVENTS 149 void nf_ct_expect_event_report(enum ip_conntrack_expect_events event, 150 struct nf_conntrack_expect *exp, 151 u32 portid, int report); 152 153 void nf_conntrack_ecache_work(struct net *net, enum nf_ct_ecache_state state); 154 155 void nf_conntrack_ecache_pernet_init(struct net *net); 156 void nf_conntrack_ecache_pernet_fini(struct net *net); 157 158 struct nf_conntrack_net_ecache *nf_conn_pernet_ecache(const struct net *net); 159 160 static inline bool nf_conntrack_ecache_dwork_pending(const struct net *net) 161 { 162 return net->ct.ecache_dwork_pending; 163 } 164 #else /* CONFIG_NF_CONNTRACK_EVENTS */ 165 166 static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e, 167 struct nf_conntrack_expect *exp, 168 u32 portid, 169 int report) 170 { 171 } 172 173 static inline void nf_conntrack_ecache_work(struct net *net, 174 enum nf_ct_ecache_state s) 175 { 176 } 177 178 static inline void nf_conntrack_ecache_pernet_init(struct net *net) 179 { 180 } 181 182 static inline void nf_conntrack_ecache_pernet_fini(struct net *net) 183 { 184 } 185 static inline bool nf_conntrack_ecache_dwork_pending(const struct net *net) { return false; } 186 #endif /* CONFIG_NF_CONNTRACK_EVENTS */ 187 #endif /*_NF_CONNTRACK_ECACHE_H*/ 188