Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: Export nf_ct_{set,destroy}_timeout()

This patch exports nf_ct_set_timeout() and nf_ct_destroy_timeout().
The two functions are derived from xt_ct_destroy_timeout() and
xt_ct_set_timeout() in xt_CT.c, and moved to nf_conntrack_timeout.c
without any functional change.
It would be useful for other users (i.e. OVS) that utilizes the
finer-grain conntrack timeout feature.

CC: Pablo Neira Ayuso <pablo@netfilter.org>
CC: Pravin Shelar <pshelar@ovn.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Yi-Hung Wei and committed by
David S. Miller
717700d1 c63d11ba

+110 -87
+15
include/net/netfilter/nf_conntrack_timeout.h
··· 88 88 int nf_conntrack_timeout_init(void); 89 89 void nf_conntrack_timeout_fini(void); 90 90 void nf_ct_untimeout(struct net *net, struct nf_ct_timeout *timeout); 91 + int nf_ct_set_timeout(struct net *net, struct nf_conn *ct, u8 l3num, u8 l4num, 92 + const char *timeout_name); 93 + void nf_ct_destroy_timeout(struct nf_conn *ct); 91 94 #else 92 95 static inline int nf_conntrack_timeout_init(void) 93 96 { ··· 100 97 static inline void nf_conntrack_timeout_fini(void) 101 98 { 102 99 return; 100 + } 101 + 102 + static inline int nf_ct_set_timeout(struct net *net, struct nf_conn *ct, 103 + u8 l3num, u8 l4num, 104 + const char *timeout_name) 105 + { 106 + return -EOPNOTSUPP; 107 + } 108 + 109 + static inline void nf_ct_destroy_timeout(struct nf_conn *ct) 110 + { 111 + return; 103 112 } 104 113 #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ 105 114
+89
net/netfilter/nf_conntrack_timeout.c
··· 48 48 } 49 49 EXPORT_SYMBOL_GPL(nf_ct_untimeout); 50 50 51 + static void __nf_ct_timeout_put(struct nf_ct_timeout *timeout) 52 + { 53 + typeof(nf_ct_timeout_put_hook) timeout_put; 54 + 55 + timeout_put = rcu_dereference(nf_ct_timeout_put_hook); 56 + if (timeout_put) 57 + timeout_put(timeout); 58 + } 59 + 60 + int nf_ct_set_timeout(struct net *net, struct nf_conn *ct, 61 + u8 l3num, u8 l4num, const char *timeout_name) 62 + { 63 + typeof(nf_ct_timeout_find_get_hook) timeout_find_get; 64 + struct nf_ct_timeout *timeout; 65 + struct nf_conn_timeout *timeout_ext; 66 + const char *errmsg = NULL; 67 + int ret = 0; 68 + 69 + rcu_read_lock(); 70 + timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook); 71 + if (!timeout_find_get) { 72 + ret = -ENOENT; 73 + errmsg = "Timeout policy base is empty"; 74 + goto out; 75 + } 76 + 77 + timeout = timeout_find_get(net, timeout_name); 78 + if (!timeout) { 79 + ret = -ENOENT; 80 + pr_info_ratelimited("No such timeout policy \"%s\"\n", 81 + timeout_name); 82 + goto out; 83 + } 84 + 85 + if (timeout->l3num != l3num) { 86 + ret = -EINVAL; 87 + pr_info_ratelimited("Timeout policy `%s' can only be used by " 88 + "L%d protocol number %d\n", 89 + timeout_name, 3, timeout->l3num); 90 + goto err_put_timeout; 91 + } 92 + /* Make sure the timeout policy matches any existing protocol tracker, 93 + * otherwise default to generic. 94 + */ 95 + if (timeout->l4proto->l4proto != l4num) { 96 + ret = -EINVAL; 97 + pr_info_ratelimited("Timeout policy `%s' can only be used by " 98 + "L%d protocol number %d\n", 99 + timeout_name, 4, timeout->l4proto->l4proto); 100 + goto err_put_timeout; 101 + } 102 + timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC); 103 + if (!timeout_ext) { 104 + ret = -ENOMEM; 105 + goto err_put_timeout; 106 + } 107 + 108 + rcu_read_unlock(); 109 + return ret; 110 + 111 + err_put_timeout: 112 + __nf_ct_timeout_put(timeout); 113 + out: 114 + rcu_read_unlock(); 115 + if (errmsg) 116 + pr_info_ratelimited("%s\n", errmsg); 117 + return ret; 118 + } 119 + EXPORT_SYMBOL_GPL(nf_ct_set_timeout); 120 + 121 + void nf_ct_destroy_timeout(struct nf_conn *ct) 122 + { 123 + struct nf_conn_timeout *timeout_ext; 124 + typeof(nf_ct_timeout_put_hook) timeout_put; 125 + 126 + rcu_read_lock(); 127 + timeout_put = rcu_dereference(nf_ct_timeout_put_hook); 128 + 129 + if (timeout_put) { 130 + timeout_ext = nf_ct_timeout_find(ct); 131 + if (timeout_ext) { 132 + timeout_put(timeout_ext->timeout); 133 + RCU_INIT_POINTER(timeout_ext->timeout, NULL); 134 + } 135 + } 136 + rcu_read_unlock(); 137 + } 138 + EXPORT_SYMBOL_GPL(nf_ct_destroy_timeout); 139 + 51 140 static const struct nf_ct_ext_type timeout_extend = { 52 141 .len = sizeof(struct nf_conn_timeout), 53 142 .align = __alignof__(struct nf_conn_timeout),
+6 -87
net/netfilter/xt_CT.c
··· 103 103 return 0; 104 104 } 105 105 106 - #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 107 - static void __xt_ct_tg_timeout_put(struct nf_ct_timeout *timeout) 108 - { 109 - typeof(nf_ct_timeout_put_hook) timeout_put; 110 - 111 - timeout_put = rcu_dereference(nf_ct_timeout_put_hook); 112 - if (timeout_put) 113 - timeout_put(timeout); 114 - } 115 - #endif 116 - 117 106 static int 118 107 xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, 119 108 const char *timeout_name) 120 109 { 121 110 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 122 - typeof(nf_ct_timeout_find_get_hook) timeout_find_get; 123 111 const struct nf_conntrack_l4proto *l4proto; 124 - struct nf_ct_timeout *timeout; 125 - struct nf_conn_timeout *timeout_ext; 126 - const char *errmsg = NULL; 127 - int ret = 0; 128 112 u8 proto; 129 - 130 - rcu_read_lock(); 131 - timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook); 132 - if (timeout_find_get == NULL) { 133 - ret = -ENOENT; 134 - errmsg = "Timeout policy base is empty"; 135 - goto out; 136 - } 137 113 138 114 proto = xt_ct_find_proto(par); 139 115 if (!proto) { 140 - ret = -EINVAL; 141 - errmsg = "You must specify a L4 protocol and not use inversions on it"; 142 - goto out; 116 + pr_info_ratelimited("You must specify a L4 protocol and not " 117 + "use inversions on it"); 118 + return -EINVAL; 143 119 } 144 - 145 - timeout = timeout_find_get(par->net, timeout_name); 146 - if (timeout == NULL) { 147 - ret = -ENOENT; 148 - pr_info_ratelimited("No such timeout policy \"%s\"\n", 149 - timeout_name); 150 - goto out; 151 - } 152 - 153 - if (timeout->l3num != par->family) { 154 - ret = -EINVAL; 155 - pr_info_ratelimited("Timeout policy `%s' can only be used by L%d protocol number %d\n", 156 - timeout_name, 3, timeout->l3num); 157 - goto err_put_timeout; 158 - } 159 - /* Make sure the timeout policy matches any existing protocol tracker, 160 - * otherwise default to generic. 161 - */ 162 120 l4proto = nf_ct_l4proto_find(proto); 163 - if (timeout->l4proto->l4proto != l4proto->l4proto) { 164 - ret = -EINVAL; 165 - pr_info_ratelimited("Timeout policy `%s' can only be used by L%d protocol number %d\n", 166 - timeout_name, 4, timeout->l4proto->l4proto); 167 - goto err_put_timeout; 168 - } 169 - timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC); 170 - if (!timeout_ext) { 171 - ret = -ENOMEM; 172 - goto err_put_timeout; 173 - } 121 + return nf_ct_set_timeout(par->net, ct, par->family, l4proto->l4proto, 122 + timeout_name); 174 123 175 - rcu_read_unlock(); 176 - return ret; 177 - 178 - err_put_timeout: 179 - __xt_ct_tg_timeout_put(timeout); 180 - out: 181 - rcu_read_unlock(); 182 - if (errmsg) 183 - pr_info_ratelimited("%s\n", errmsg); 184 - return ret; 185 124 #else 186 125 return -EOPNOTSUPP; 187 126 #endif ··· 267 328 return xt_ct_tg_check(par, par->targinfo); 268 329 } 269 330 270 - static void xt_ct_destroy_timeout(struct nf_conn *ct) 271 - { 272 - #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 273 - struct nf_conn_timeout *timeout_ext; 274 - typeof(nf_ct_timeout_put_hook) timeout_put; 275 - 276 - rcu_read_lock(); 277 - timeout_put = rcu_dereference(nf_ct_timeout_put_hook); 278 - 279 - if (timeout_put) { 280 - timeout_ext = nf_ct_timeout_find(ct); 281 - if (timeout_ext) { 282 - timeout_put(timeout_ext->timeout); 283 - RCU_INIT_POINTER(timeout_ext->timeout, NULL); 284 - } 285 - } 286 - rcu_read_unlock(); 287 - #endif 288 - } 289 - 290 331 static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par, 291 332 struct xt_ct_target_info_v1 *info) 292 333 { ··· 280 361 281 362 nf_ct_netns_put(par->net, par->family); 282 363 283 - xt_ct_destroy_timeout(ct); 364 + nf_ct_destroy_timeout(ct); 284 365 nf_ct_put(info->ct); 285 366 } 286 367 }