]>
git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blob - net/netfilter/nf_conntrack_extend.c
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>
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>
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 */
20 void nf_ct_ext_destroy(struct nf_conn
*ct
)
23 struct nf_ct_ext_type
*t
;
25 for (i
= 0; i
< NF_CT_EXT_NUM
; i
++) {
27 t
= rcu_dereference(nf_ct_ext_types
[i
]);
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.
41 void *nf_ct_ext_add(struct nf_conn
*ct
, enum nf_ct_ext_id id
, gfp_t gfp
)
43 unsigned int newlen
, newoff
, oldlen
, alloc
;
44 struct nf_ct_ext_type
*t
;
45 struct nf_ct_ext
*new;
47 /* Conntrack must not be confirmed to avoid races on reallocation. */
48 WARN_ON(nf_ct_is_confirmed(ct
));
52 const struct nf_ct_ext
*old
= ct
->ext
;
54 if (__nf_ct_ext_exist(old
, id
))
58 oldlen
= sizeof(*new);
62 t
= rcu_dereference(nf_ct_ext_types
[id
]);
68 newoff
= ALIGN(oldlen
, t
->align
);
69 newlen
= newoff
+ t
->len
;
72 alloc
= max(newlen
, NF_CT_EXT_PREALLOC
);
73 new = krealloc(ct
->ext
, alloc
, gfp
);
78 memset(new->offset
, 0, sizeof(new->offset
));
80 new->offset
[id
] = newoff
;
82 memset((void *)new + newoff
, 0, newlen
- newoff
);
85 return (void *)new + newoff
;
87 EXPORT_SYMBOL(nf_ct_ext_add
);
89 /* This MUST be called in process context. */
90 int nf_ct_extend_register(const struct nf_ct_ext_type
*type
)
94 mutex_lock(&nf_ct_ext_type_mutex
);
95 if (nf_ct_ext_types
[type
->id
]) {
100 rcu_assign_pointer(nf_ct_ext_types
[type
->id
], type
);
102 mutex_unlock(&nf_ct_ext_type_mutex
);
105 EXPORT_SYMBOL_GPL(nf_ct_extend_register
);
107 /* This MUST be called in process context. */
108 void nf_ct_extend_unregister(const struct nf_ct_ext_type
*type
)
110 mutex_lock(&nf_ct_ext_type_mutex
);
111 RCU_INIT_POINTER(nf_ct_ext_types
[type
->id
], NULL
);
112 mutex_unlock(&nf_ct_ext_type_mutex
);
115 EXPORT_SYMBOL_GPL(nf_ct_extend_unregister
);