1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _NF_CONNTRACK_TIMEOUT_H 3 #define _NF_CONNTRACK_TIMEOUT_H 4 5 #include <net/net_namespace.h> 6 #include <linux/netfilter/nf_conntrack_common.h> 7 #include <linux/netfilter/nf_conntrack_tuple_common.h> 8 #include <linux/refcount.h> 9 #include <net/netfilter/nf_conntrack.h> 10 #include <net/netfilter/nf_conntrack_extend.h> 11 12 #define CTNL_TIMEOUT_NAME_MAX 32 13 14 struct nf_ct_timeout { 15 refcount_t refcnt; 16 __u16 l3num; 17 const struct nf_conntrack_l4proto *l4proto; 18 struct rcu_head rcu; 19 char data[]; 20 }; 21 22 struct nf_conn_timeout { 23 struct nf_ct_timeout __rcu *timeout; 24 }; 25 26 static inline void nf_ct_timeout_put(const struct nf_conn *ct) 27 { 28 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 29 struct nf_conn_timeout *timeout_ext; 30 struct nf_ct_timeout *timeout; 31 32 timeout_ext = nf_ct_ext_find(ct, NF_CT_EXT_TIMEOUT); 33 if (!timeout_ext) 34 return; 35 36 timeout = rcu_dereference(timeout_ext->timeout); 37 if (timeout && refcount_dec_and_test(&timeout->refcnt)) 38 kfree_rcu(timeout, rcu); 39 #endif 40 } 41 42 static inline unsigned int * 43 nf_ct_timeout_data(const struct nf_conn_timeout *t) 44 { 45 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 46 struct nf_ct_timeout *timeout; 47 48 timeout = rcu_dereference(t->timeout); 49 if (timeout == NULL) 50 return NULL; 51 52 return (unsigned int *)timeout->data; 53 #else 54 return NULL; 55 #endif 56 } 57 58 static inline 59 struct nf_conn_timeout *nf_ct_timeout_find(const struct nf_conn *ct) 60 { 61 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 62 return nf_ct_ext_find(ct, NF_CT_EXT_TIMEOUT); 63 #else 64 return NULL; 65 #endif 66 } 67 68 static inline 69 struct nf_conn_timeout *nf_ct_timeout_ext_add(struct nf_conn *ct, 70 struct nf_ct_timeout *timeout, 71 gfp_t gfp) 72 { 73 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 74 struct nf_conn_timeout *timeout_ext; 75 76 if (!timeout) 77 return NULL; 78 79 timeout_ext = nf_ct_ext_add(ct, NF_CT_EXT_TIMEOUT, gfp); 80 if (!timeout_ext || timeout_ext->timeout) 81 return NULL; 82 83 if (!refcount_inc_not_zero(&timeout->refcnt)) 84 return NULL; 85 86 rcu_assign_pointer(timeout_ext->timeout, timeout); 87 88 return timeout_ext; 89 #else 90 return NULL; 91 #endif 92 }; 93 94 static inline unsigned int *nf_ct_timeout_lookup(const struct nf_conn *ct) 95 { 96 unsigned int *timeouts = NULL; 97 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 98 struct nf_conn_timeout *timeout_ext; 99 100 timeout_ext = nf_ct_timeout_find(ct); 101 if (timeout_ext && rcu_access_pointer(timeout_ext->timeout)) 102 timeouts = nf_ct_timeout_data(timeout_ext); 103 #endif 104 return timeouts; 105 } 106 107 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 108 void nf_ct_untimeout(struct net *net, struct nf_ct_timeout *timeout); 109 int nf_ct_set_timeout(struct net *net, struct nf_conn *ct, u8 l3num, u8 l4num, 110 const char *timeout_name); 111 void nf_ct_destroy_timeout(struct nf_conn *ct); 112 #else 113 static inline int nf_ct_set_timeout(struct net *net, struct nf_conn *ct, 114 u8 l3num, u8 l4num, 115 const char *timeout_name) 116 { 117 return -EOPNOTSUPP; 118 } 119 120 static inline void nf_ct_destroy_timeout(struct nf_conn *ct) 121 { 122 return; 123 } 124 #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ 125 126 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 127 struct nf_ct_timeout_hooks { 128 struct nf_ct_timeout *(*timeout_find_get)(struct net *net, const char *name); 129 void (*timeout_put)(struct nf_ct_timeout *timeout); 130 }; 131 132 extern const struct nf_ct_timeout_hooks __rcu *nf_ct_timeout_hook; 133 #endif 134 135 #endif /* _NF_CONNTRACK_TIMEOUT_H */ 136