mirror of
https://github.com/brain-hackers/linux-brain.git
synced 2024-06-09 23:36:23 +09:00
2874c5fd28
Based on 1 normalized pattern(s): this program is free software you can redistribute it and or modify it under the terms of the gnu general public license as published by the free software foundation either version 2 of the license or at your option any later version extracted by the scancode license scanner the SPDX license identifier GPL-2.0-or-later has been chosen to replace the boilerplate/reference in 3029 file(s). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Allison Randal <allison@lohutok.net> Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190527070032.746973796@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
118 lines
2.9 KiB
C
118 lines
2.9 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/* Structure dynamic extension infrastructure
|
|
* Copyright (C) 2004 Rusty Russell IBM Corporation
|
|
* Copyright (C) 2007 Netfilter Core Team <coreteam@netfilter.org>
|
|
* Copyright (C) 2007 USAGI/WIDE Project <http://www.linux-ipv6.org>
|
|
*/
|
|
#include <linux/kernel.h>
|
|
#include <linux/kmemleak.h>
|
|
#include <linux/module.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/rcupdate.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/skbuff.h>
|
|
#include <net/netfilter/nf_conntrack_extend.h>
|
|
|
|
static struct nf_ct_ext_type __rcu *nf_ct_ext_types[NF_CT_EXT_NUM];
|
|
static DEFINE_MUTEX(nf_ct_ext_type_mutex);
|
|
#define NF_CT_EXT_PREALLOC 128u /* conntrack events are on by default */
|
|
|
|
void nf_ct_ext_destroy(struct nf_conn *ct)
|
|
{
|
|
unsigned int i;
|
|
struct nf_ct_ext_type *t;
|
|
|
|
for (i = 0; i < NF_CT_EXT_NUM; i++) {
|
|
rcu_read_lock();
|
|
t = rcu_dereference(nf_ct_ext_types[i]);
|
|
|
|
/* Here the nf_ct_ext_type might have been unregisterd.
|
|
* I.e., it has responsible to cleanup private
|
|
* area in all conntracks when it is unregisterd.
|
|
*/
|
|
if (t && t->destroy)
|
|
t->destroy(ct);
|
|
rcu_read_unlock();
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(nf_ct_ext_destroy);
|
|
|
|
void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
|
|
{
|
|
unsigned int newlen, newoff, oldlen, alloc;
|
|
struct nf_ct_ext *old, *new;
|
|
struct nf_ct_ext_type *t;
|
|
|
|
/* Conntrack must not be confirmed to avoid races on reallocation. */
|
|
WARN_ON(nf_ct_is_confirmed(ct));
|
|
|
|
old = ct->ext;
|
|
|
|
if (old) {
|
|
if (__nf_ct_ext_exist(old, id))
|
|
return NULL;
|
|
oldlen = old->len;
|
|
} else {
|
|
oldlen = sizeof(*new);
|
|
}
|
|
|
|
rcu_read_lock();
|
|
t = rcu_dereference(nf_ct_ext_types[id]);
|
|
if (!t) {
|
|
rcu_read_unlock();
|
|
return NULL;
|
|
}
|
|
|
|
newoff = ALIGN(oldlen, t->align);
|
|
newlen = newoff + t->len;
|
|
rcu_read_unlock();
|
|
|
|
alloc = max(newlen, NF_CT_EXT_PREALLOC);
|
|
kmemleak_not_leak(old);
|
|
new = __krealloc(old, alloc, gfp);
|
|
if (!new)
|
|
return NULL;
|
|
|
|
if (!old) {
|
|
memset(new->offset, 0, sizeof(new->offset));
|
|
ct->ext = new;
|
|
} else if (new != old) {
|
|
kfree_rcu(old, rcu);
|
|
rcu_assign_pointer(ct->ext, new);
|
|
}
|
|
|
|
new->offset[id] = newoff;
|
|
new->len = newlen;
|
|
memset((void *)new + newoff, 0, newlen - newoff);
|
|
return (void *)new + newoff;
|
|
}
|
|
EXPORT_SYMBOL(nf_ct_ext_add);
|
|
|
|
/* This MUST be called in process context. */
|
|
int nf_ct_extend_register(const struct nf_ct_ext_type *type)
|
|
{
|
|
int ret = 0;
|
|
|
|
mutex_lock(&nf_ct_ext_type_mutex);
|
|
if (nf_ct_ext_types[type->id]) {
|
|
ret = -EBUSY;
|
|
goto out;
|
|
}
|
|
|
|
rcu_assign_pointer(nf_ct_ext_types[type->id], type);
|
|
out:
|
|
mutex_unlock(&nf_ct_ext_type_mutex);
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(nf_ct_extend_register);
|
|
|
|
/* This MUST be called in process context. */
|
|
void nf_ct_extend_unregister(const struct nf_ct_ext_type *type)
|
|
{
|
|
mutex_lock(&nf_ct_ext_type_mutex);
|
|
RCU_INIT_POINTER(nf_ct_ext_types[type->id], NULL);
|
|
mutex_unlock(&nf_ct_ext_type_mutex);
|
|
synchronize_rcu();
|
|
}
|
|
EXPORT_SYMBOL_GPL(nf_ct_extend_unregister);
|