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 16enum nf_ct_ecache_state { 17 NFCT_ECACHE_DESTROY_FAIL, /* tried but failed to send destroy event */ 18 NFCT_ECACHE_DESTROY_SENT, /* sent destroy event after failure */ 19}; 20 21struct nf_conntrack_ecache { 22 unsigned long cache; /* bitops want long */ 23 u16 ctmask; /* bitmask of ct events to be delivered */ 24 u16 expmask; /* bitmask of expect events to be delivered */ 25 u32 missed; /* missed events */ 26 u32 portid; /* netlink portid of destroyer */ 27}; 28 29static inline struct nf_conntrack_ecache * 30nf_ct_ecache_find(const struct nf_conn *ct) 31{ 32#ifdef CONFIG_NF_CONNTRACK_EVENTS 33 return nf_ct_ext_find(ct, NF_CT_EXT_ECACHE); 34#else 35 return NULL; 36#endif 37} 38 39static inline bool nf_ct_ecache_exist(const struct nf_conn *ct) 40{ 41#ifdef CONFIG_NF_CONNTRACK_EVENTS 42 return nf_ct_ext_exist(ct, NF_CT_EXT_ECACHE); 43#else 44 return false; 45#endif 46} 47 48#ifdef CONFIG_NF_CONNTRACK_EVENTS 49 50/* This structure is passed to event handler */ 51struct nf_ct_event { 52 struct nf_conn *ct; 53 u32 portid; 54 int report; 55}; 56 57struct nf_exp_event { 58 struct nf_conntrack_expect *exp; 59 u32 portid; 60 int report; 61}; 62 63struct nf_ct_event_notifier { 64 int (*ct_event)(unsigned int events, const struct nf_ct_event *item); 65 int (*exp_event)(unsigned int events, const struct nf_exp_event *item); 66}; 67 68void nf_conntrack_register_notifier(struct net *net, 69 const struct nf_ct_event_notifier *nb); 70void nf_conntrack_unregister_notifier(struct net *net); 71 72void nf_ct_deliver_cached_events(struct nf_conn *ct); 73int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct, 74 u32 portid, int report); 75 76bool nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp); 77#else 78 79static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) 80{ 81} 82 83static inline int nf_conntrack_eventmask_report(unsigned int eventmask, 84 struct nf_conn *ct, 85 u32 portid, 86 int report) 87{ 88 return 0; 89} 90 91static inline bool nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp) 92{ 93 return false; 94} 95#endif 96 97static inline void 98nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) 99{ 100#ifdef CONFIG_NF_CONNTRACK_EVENTS 101 struct net *net = nf_ct_net(ct); 102 struct nf_conntrack_ecache *e; 103 104 if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) 105 return; 106 107 e = nf_ct_ecache_find(ct); 108 if (e == NULL) 109 return; 110 111 set_bit(event, &e->cache); 112#endif 113} 114 115static inline int 116nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct, 117 u32 portid, int report) 118{ 119#ifdef CONFIG_NF_CONNTRACK_EVENTS 120 if (nf_ct_ecache_exist(ct)) 121 return nf_conntrack_eventmask_report(1 << event, ct, portid, report); 122#endif 123 return 0; 124} 125 126static inline int 127nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct) 128{ 129#ifdef CONFIG_NF_CONNTRACK_EVENTS 130 if (nf_ct_ecache_exist(ct)) 131 return nf_conntrack_eventmask_report(1 << event, ct, 0, 0); 132#endif 133 return 0; 134} 135 136#ifdef CONFIG_NF_CONNTRACK_EVENTS 137void nf_ct_expect_event_report(enum ip_conntrack_expect_events event, 138 struct nf_conntrack_expect *exp, 139 u32 portid, int report); 140 141void nf_conntrack_ecache_work(struct net *net, enum nf_ct_ecache_state state); 142 143void nf_conntrack_ecache_pernet_init(struct net *net); 144void nf_conntrack_ecache_pernet_fini(struct net *net); 145 146struct nf_conntrack_net_ecache *nf_conn_pernet_ecache(const struct net *net); 147 148static inline bool nf_conntrack_ecache_dwork_pending(const struct net *net) 149{ 150 return net->ct.ecache_dwork_pending; 151} 152#else /* CONFIG_NF_CONNTRACK_EVENTS */ 153 154static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e, 155 struct nf_conntrack_expect *exp, 156 u32 portid, 157 int report) 158{ 159} 160 161static inline void nf_conntrack_ecache_work(struct net *net, 162 enum nf_ct_ecache_state s) 163{ 164} 165 166static inline void nf_conntrack_ecache_pernet_init(struct net *net) 167{ 168} 169 170static inline void nf_conntrack_ecache_pernet_fini(struct net *net) 171{ 172} 173static inline bool nf_conntrack_ecache_dwork_pending(const struct net *net) { return false; } 174#endif /* CONFIG_NF_CONNTRACK_EVENTS */ 175#endif /*_NF_CONNTRACK_ECACHE_H*/ 176