root/net/netfilter/nf_conntrack_extend.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nf_ct_ext_destroy
  2. nf_ct_ext_add
  3. nf_ct_extend_register
  4. nf_ct_extend_unregister

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /* Structure dynamic extension infrastructure
   3  * Copyright (C) 2004 Rusty Russell IBM Corporation
   4  * Copyright (C) 2007 Netfilter Core Team <coreteam@netfilter.org>
   5  * Copyright (C) 2007 USAGI/WIDE Project <http://www.linux-ipv6.org>
   6  */
   7 #include <linux/kernel.h>
   8 #include <linux/kmemleak.h>
   9 #include <linux/module.h>
  10 #include <linux/mutex.h>
  11 #include <linux/rcupdate.h>
  12 #include <linux/slab.h>
  13 #include <linux/skbuff.h>
  14 #include <net/netfilter/nf_conntrack_extend.h>
  15 
  16 static struct nf_ct_ext_type __rcu *nf_ct_ext_types[NF_CT_EXT_NUM];
  17 static DEFINE_MUTEX(nf_ct_ext_type_mutex);
  18 #define NF_CT_EXT_PREALLOC      128u /* conntrack events are on by default */
  19 
  20 void nf_ct_ext_destroy(struct nf_conn *ct)
  21 {
  22         unsigned int i;
  23         struct nf_ct_ext_type *t;
  24 
  25         for (i = 0; i < NF_CT_EXT_NUM; i++) {
  26                 rcu_read_lock();
  27                 t = rcu_dereference(nf_ct_ext_types[i]);
  28 
  29                 /* Here the nf_ct_ext_type might have been unregisterd.
  30                  * I.e., it has responsible to cleanup private
  31                  * area in all conntracks when it is unregisterd.
  32                  */
  33                 if (t && t->destroy)
  34                         t->destroy(ct);
  35                 rcu_read_unlock();
  36         }
  37 }
  38 EXPORT_SYMBOL(nf_ct_ext_destroy);
  39 
  40 void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
  41 {
  42         unsigned int newlen, newoff, oldlen, alloc;
  43         struct nf_ct_ext *old, *new;
  44         struct nf_ct_ext_type *t;
  45 
  46         /* Conntrack must not be confirmed to avoid races on reallocation. */
  47         WARN_ON(nf_ct_is_confirmed(ct));
  48 
  49         old = ct->ext;
  50 
  51         if (old) {
  52                 if (__nf_ct_ext_exist(old, id))
  53                         return NULL;
  54                 oldlen = old->len;
  55         } else {
  56                 oldlen = sizeof(*new);
  57         }
  58 
  59         rcu_read_lock();
  60         t = rcu_dereference(nf_ct_ext_types[id]);
  61         if (!t) {
  62                 rcu_read_unlock();
  63                 return NULL;
  64         }
  65 
  66         newoff = ALIGN(oldlen, t->align);
  67         newlen = newoff + t->len;
  68         rcu_read_unlock();
  69 
  70         alloc = max(newlen, NF_CT_EXT_PREALLOC);
  71         kmemleak_not_leak(old);
  72         new = __krealloc(old, alloc, gfp);
  73         if (!new)
  74                 return NULL;
  75 
  76         if (!old) {
  77                 memset(new->offset, 0, sizeof(new->offset));
  78                 ct->ext = new;
  79         } else if (new != old) {
  80                 kfree_rcu(old, rcu);
  81                 rcu_assign_pointer(ct->ext, new);
  82         }
  83 
  84         new->offset[id] = newoff;
  85         new->len = newlen;
  86         memset((void *)new + newoff, 0, newlen - newoff);
  87         return (void *)new + newoff;
  88 }
  89 EXPORT_SYMBOL(nf_ct_ext_add);
  90 
  91 /* This MUST be called in process context. */
  92 int nf_ct_extend_register(const struct nf_ct_ext_type *type)
  93 {
  94         int ret = 0;
  95 
  96         mutex_lock(&nf_ct_ext_type_mutex);
  97         if (nf_ct_ext_types[type->id]) {
  98                 ret = -EBUSY;
  99                 goto out;
 100         }
 101 
 102         rcu_assign_pointer(nf_ct_ext_types[type->id], type);
 103 out:
 104         mutex_unlock(&nf_ct_ext_type_mutex);
 105         return ret;
 106 }
 107 EXPORT_SYMBOL_GPL(nf_ct_extend_register);
 108 
 109 /* This MUST be called in process context. */
 110 void nf_ct_extend_unregister(const struct nf_ct_ext_type *type)
 111 {
 112         mutex_lock(&nf_ct_ext_type_mutex);
 113         RCU_INIT_POINTER(nf_ct_ext_types[type->id], NULL);
 114         mutex_unlock(&nf_ct_ext_type_mutex);
 115         synchronize_rcu();
 116 }
 117 EXPORT_SYMBOL_GPL(nf_ct_extend_unregister);

/* [<][>][^][v][top][bottom][index][help] */