|
@@ -14,6 +14,8 @@
|
|
|
#include <net/netfilter/nf_conntrack_ecache.h>
|
|
|
#include <net/netfilter/nf_conntrack_labels.h>
|
|
|
|
|
|
+static spinlock_t nf_connlabels_lock;
|
|
|
+
|
|
|
static unsigned int label_bits(const struct nf_conn_labels *l)
|
|
|
{
|
|
|
unsigned int longs = l->words;
|
|
@@ -89,6 +91,35 @@ int nf_connlabels_replace(struct nf_conn *ct,
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(nf_connlabels_replace);
|
|
|
|
|
|
+int nf_connlabels_get(struct net *net, unsigned int n_bits)
|
|
|
+{
|
|
|
+ size_t words;
|
|
|
+
|
|
|
+ if (n_bits > (NF_CT_LABELS_MAX_SIZE * BITS_PER_BYTE))
|
|
|
+ return -ERANGE;
|
|
|
+
|
|
|
+ words = BITS_TO_LONGS(n_bits);
|
|
|
+
|
|
|
+ spin_lock(&nf_connlabels_lock);
|
|
|
+ net->ct.labels_used++;
|
|
|
+ if (words > net->ct.label_words)
|
|
|
+ net->ct.label_words = words;
|
|
|
+ spin_unlock(&nf_connlabels_lock);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(nf_connlabels_get);
|
|
|
+
|
|
|
+void nf_connlabels_put(struct net *net)
|
|
|
+{
|
|
|
+ spin_lock(&nf_connlabels_lock);
|
|
|
+ net->ct.labels_used--;
|
|
|
+ if (net->ct.labels_used == 0)
|
|
|
+ net->ct.label_words = 0;
|
|
|
+ spin_unlock(&nf_connlabels_lock);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(nf_connlabels_put);
|
|
|
+
|
|
|
static struct nf_ct_ext_type labels_extend __read_mostly = {
|
|
|
.len = sizeof(struct nf_conn_labels),
|
|
|
.align = __alignof__(struct nf_conn_labels),
|
|
@@ -97,6 +128,7 @@ static struct nf_ct_ext_type labels_extend __read_mostly = {
|
|
|
|
|
|
int nf_conntrack_labels_init(void)
|
|
|
{
|
|
|
+ spin_lock_init(&nf_connlabels_lock);
|
|
|
return nf_ct_extend_register(&labels_extend);
|
|
|
}
|
|
|
|