1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org> 4 * (C) 2012 by Vyatta Inc. <http://www.vyatta.com> 5 */ 6 7 #include <linux/types.h> 8 #include <linux/netfilter.h> 9 #include <linux/skbuff.h> 10 #include <linux/vmalloc.h> 11 #include <linux/stddef.h> 12 #include <linux/err.h> 13 #include <linux/percpu.h> 14 #include <linux/kernel.h> 15 #include <linux/netdevice.h> 16 #include <linux/slab.h> 17 #include <linux/export.h> 18 19 #include <net/netfilter/nf_conntrack.h> 20 #include <net/netfilter/nf_conntrack_core.h> 21 #include <net/netfilter/nf_conntrack_extend.h> 22 #include <net/netfilter/nf_conntrack_l4proto.h> 23 #include <net/netfilter/nf_conntrack_timeout.h> 24 25 const struct nf_ct_timeout_hooks __rcu *nf_ct_timeout_hook __read_mostly; 26 EXPORT_SYMBOL_GPL(nf_ct_timeout_hook); 27 28 static int untimeout(struct nf_conn *ct, void *timeout) 29 { 30 struct nf_conn_timeout *timeout_ext = nf_ct_timeout_find(ct); 31 32 if (timeout_ext) { 33 const struct nf_ct_timeout *t; 34 35 t = rcu_access_pointer(timeout_ext->timeout); 36 37 if (!timeout || t == timeout) 38 RCU_INIT_POINTER(timeout_ext->timeout, NULL); 39 } 40 41 /* We are not intended to delete this conntrack. */ 42 return 0; 43 } 44 45 void nf_ct_untimeout(struct net *net, struct nf_ct_timeout *timeout) 46 { 47 struct nf_ct_iter_data iter_data = { 48 .net = net, 49 .data = timeout, 50 }; 51 52 nf_ct_iterate_cleanup_net(untimeout, &iter_data); 53 } 54 EXPORT_SYMBOL_GPL(nf_ct_untimeout); 55 56 static void __nf_ct_timeout_put(struct nf_ct_timeout *timeout) 57 { 58 const struct nf_ct_timeout_hooks *h = rcu_dereference(nf_ct_timeout_hook); 59 60 if (h) 61 h->timeout_put(timeout); 62 } 63 64 int nf_ct_set_timeout(struct net *net, struct nf_conn *ct, 65 u8 l3num, u8 l4num, const char *timeout_name) 66 { 67 const struct nf_ct_timeout_hooks *h; 68 struct nf_ct_timeout *timeout; 69 struct nf_conn_timeout *timeout_ext; 70 const char *errmsg = NULL; 71 int ret = 0; 72 73 rcu_read_lock(); 74 h = rcu_dereference(nf_ct_timeout_hook); 75 if (!h) { 76 ret = -ENOENT; 77 errmsg = "Timeout policy base is empty"; 78 goto out; 79 } 80 81 timeout = h->timeout_find_get(net, timeout_name); 82 if (!timeout) { 83 ret = -ENOENT; 84 pr_info_ratelimited("No such timeout policy \"%s\"\n", 85 timeout_name); 86 goto out; 87 } 88 89 if (timeout->l3num != l3num) { 90 ret = -EINVAL; 91 pr_info_ratelimited("Timeout policy `%s' can only be used by " 92 "L%d protocol number %d\n", 93 timeout_name, 3, timeout->l3num); 94 goto err_put_timeout; 95 } 96 /* Make sure the timeout policy matches any existing protocol tracker, 97 * otherwise default to generic. 98 */ 99 if (timeout->l4proto->l4proto != l4num) { 100 ret = -EINVAL; 101 pr_info_ratelimited("Timeout policy `%s' can only be used by " 102 "L%d protocol number %d\n", 103 timeout_name, 4, timeout->l4proto->l4proto); 104 goto err_put_timeout; 105 } 106 timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC); 107 if (!timeout_ext) { 108 ret = -ENOMEM; 109 goto err_put_timeout; 110 } 111 112 rcu_read_unlock(); 113 return ret; 114 115 err_put_timeout: 116 __nf_ct_timeout_put(timeout); 117 out: 118 rcu_read_unlock(); 119 if (errmsg) 120 pr_info_ratelimited("%s\n", errmsg); 121 return ret; 122 } 123 EXPORT_SYMBOL_GPL(nf_ct_set_timeout); 124 125 void nf_ct_destroy_timeout(struct nf_conn *ct) 126 { 127 struct nf_conn_timeout *timeout_ext; 128 const struct nf_ct_timeout_hooks *h; 129 130 rcu_read_lock(); 131 h = rcu_dereference(nf_ct_timeout_hook); 132 133 if (h) { 134 timeout_ext = nf_ct_timeout_find(ct); 135 if (timeout_ext) { 136 struct nf_ct_timeout *t; 137 138 t = rcu_dereference(timeout_ext->timeout); 139 if (t) 140 h->timeout_put(t); 141 RCU_INIT_POINTER(timeout_ext->timeout, NULL); 142 } 143 } 144 rcu_read_unlock(); 145 } 146 EXPORT_SYMBOL_GPL(nf_ct_destroy_timeout); 147