Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
0004  * (C) 2012 by Vyatta Inc. <http://www.vyatta.com>
0005  */
0006 
0007 #include <linux/types.h>
0008 #include <linux/netfilter.h>
0009 #include <linux/skbuff.h>
0010 #include <linux/vmalloc.h>
0011 #include <linux/stddef.h>
0012 #include <linux/err.h>
0013 #include <linux/percpu.h>
0014 #include <linux/kernel.h>
0015 #include <linux/netdevice.h>
0016 #include <linux/slab.h>
0017 #include <linux/export.h>
0018 
0019 #include <net/netfilter/nf_conntrack.h>
0020 #include <net/netfilter/nf_conntrack_core.h>
0021 #include <net/netfilter/nf_conntrack_extend.h>
0022 #include <net/netfilter/nf_conntrack_l4proto.h>
0023 #include <net/netfilter/nf_conntrack_timeout.h>
0024 
0025 const struct nf_ct_timeout_hooks __rcu *nf_ct_timeout_hook __read_mostly;
0026 EXPORT_SYMBOL_GPL(nf_ct_timeout_hook);
0027 
0028 static int untimeout(struct nf_conn *ct, void *timeout)
0029 {
0030     struct nf_conn_timeout *timeout_ext = nf_ct_timeout_find(ct);
0031 
0032     if (timeout_ext) {
0033         const struct nf_ct_timeout *t;
0034 
0035         t = rcu_access_pointer(timeout_ext->timeout);
0036 
0037         if (!timeout || t == timeout)
0038             RCU_INIT_POINTER(timeout_ext->timeout, NULL);
0039     }
0040 
0041     /* We are not intended to delete this conntrack. */
0042     return 0;
0043 }
0044 
0045 void nf_ct_untimeout(struct net *net, struct nf_ct_timeout *timeout)
0046 {
0047     struct nf_ct_iter_data iter_data = {
0048         .net    = net,
0049         .data   = timeout,
0050     };
0051 
0052     nf_ct_iterate_cleanup_net(untimeout, &iter_data);
0053 }
0054 EXPORT_SYMBOL_GPL(nf_ct_untimeout);
0055 
0056 static void __nf_ct_timeout_put(struct nf_ct_timeout *timeout)
0057 {
0058     const struct nf_ct_timeout_hooks *h = rcu_dereference(nf_ct_timeout_hook);
0059 
0060     if (h)
0061         h->timeout_put(timeout);
0062 }
0063 
0064 int nf_ct_set_timeout(struct net *net, struct nf_conn *ct,
0065               u8 l3num, u8 l4num, const char *timeout_name)
0066 {
0067     const struct nf_ct_timeout_hooks *h;
0068     struct nf_ct_timeout *timeout;
0069     struct nf_conn_timeout *timeout_ext;
0070     const char *errmsg = NULL;
0071     int ret = 0;
0072 
0073     rcu_read_lock();
0074     h = rcu_dereference(nf_ct_timeout_hook);
0075     if (!h) {
0076         ret = -ENOENT;
0077         errmsg = "Timeout policy base is empty";
0078         goto out;
0079     }
0080 
0081     timeout = h->timeout_find_get(net, timeout_name);
0082     if (!timeout) {
0083         ret = -ENOENT;
0084         pr_info_ratelimited("No such timeout policy \"%s\"\n",
0085                     timeout_name);
0086         goto out;
0087     }
0088 
0089     if (timeout->l3num != l3num) {
0090         ret = -EINVAL;
0091         pr_info_ratelimited("Timeout policy `%s' can only be used by "
0092                     "L%d protocol number %d\n",
0093                     timeout_name, 3, timeout->l3num);
0094         goto err_put_timeout;
0095     }
0096     /* Make sure the timeout policy matches any existing protocol tracker,
0097      * otherwise default to generic.
0098      */
0099     if (timeout->l4proto->l4proto != l4num) {
0100         ret = -EINVAL;
0101         pr_info_ratelimited("Timeout policy `%s' can only be used by "
0102                     "L%d protocol number %d\n",
0103                     timeout_name, 4, timeout->l4proto->l4proto);
0104         goto err_put_timeout;
0105     }
0106     timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC);
0107     if (!timeout_ext) {
0108         ret = -ENOMEM;
0109         goto err_put_timeout;
0110     }
0111 
0112     rcu_read_unlock();
0113     return ret;
0114 
0115 err_put_timeout:
0116     __nf_ct_timeout_put(timeout);
0117 out:
0118     rcu_read_unlock();
0119     if (errmsg)
0120         pr_info_ratelimited("%s\n", errmsg);
0121     return ret;
0122 }
0123 EXPORT_SYMBOL_GPL(nf_ct_set_timeout);
0124 
0125 void nf_ct_destroy_timeout(struct nf_conn *ct)
0126 {
0127     struct nf_conn_timeout *timeout_ext;
0128     const struct nf_ct_timeout_hooks *h;
0129 
0130     rcu_read_lock();
0131     h = rcu_dereference(nf_ct_timeout_hook);
0132 
0133     if (h) {
0134         timeout_ext = nf_ct_timeout_find(ct);
0135         if (timeout_ext) {
0136             struct nf_ct_timeout *t;
0137 
0138             t = rcu_dereference(timeout_ext->timeout);
0139             if (t)
0140                 h->timeout_put(t);
0141             RCU_INIT_POINTER(timeout_ext->timeout, NULL);
0142         }
0143     }
0144     rcu_read_unlock();
0145 }
0146 EXPORT_SYMBOL_GPL(nf_ct_destroy_timeout);