summaryrefslogtreecommitdiffstats
path: root/src/conntrack
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2012-12-14 12:42:48 +0100
committerFlorian Westphal <fw@strlen.de>2013-05-06 21:34:35 +0200
commit22c8af6991eab12a87fec4f06559e1d7ea3826f1 (patch)
tree56bd05aa44b7273770a471e0bee2677282de45eb /src/conntrack
parentd5e1f43e14bff7072e5a7a232bb2b04fcd710d52 (diff)
api: add CTA_LABEL_MASK attribute handling
allows to set/clear only a subset of the in-kernel label set, e.g. "set bit 1 and do not change any others". Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'src/conntrack')
-rw-r--r--src/conntrack/api.c2
-rw-r--r--src/conntrack/build_mnl.c6
-rw-r--r--src/conntrack/copy.c9
-rw-r--r--src/conntrack/getter.c6
-rw-r--r--src/conntrack/parse_mnl.c1
-rw-r--r--src/conntrack/setter.c21
6 files changed, 40 insertions, 5 deletions
diff --git a/src/conntrack/api.c b/src/conntrack/api.c
index 072bb09..b6c453f 100644
--- a/src/conntrack/api.c
+++ b/src/conntrack/api.c
@@ -97,6 +97,8 @@ void nfct_destroy(struct nf_conntrack *ct)
free(ct->helper_info);
if (ct->connlabels)
nfct_bitmask_destroy(ct->connlabels);
+ if (ct->connlabels_mask)
+ nfct_bitmask_destroy(ct->connlabels_mask);
free(ct);
ct = NULL; /* bugtrap */
}
diff --git a/src/conntrack/build_mnl.c b/src/conntrack/build_mnl.c
index a666e01..a37bd73 100644
--- a/src/conntrack/build_mnl.c
+++ b/src/conntrack/build_mnl.c
@@ -386,6 +386,12 @@ nfct_build_labels(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
struct nfct_bitmask *b = ct->connlabels;
unsigned int size = b->words * sizeof(b->bits[0]);
mnl_attr_put(nlh, CTA_LABELS, size, b->bits);
+
+ if (test_bit(ATTR_CONNLABELS_MASK, ct->head.set)) {
+ b = ct->connlabels_mask;
+ if (size == (b->words * sizeof(b->bits[0])))
+ mnl_attr_put(nlh, CTA_LABELS_MASK, size, b->bits);
+ }
}
int
diff --git a/src/conntrack/copy.c b/src/conntrack/copy.c
index 9cb567c..5915c16 100644
--- a/src/conntrack/copy.c
+++ b/src/conntrack/copy.c
@@ -466,6 +466,12 @@ static void copy_attr_connlabels(struct nf_conntrack *dest,
dest->connlabels = do_copy_attr_connlabels(dest->connlabels, orig->connlabels);
}
+static void copy_attr_connlabels_mask(struct nf_conntrack *dest,
+ const struct nf_conntrack *orig)
+{
+ dest->connlabels_mask = do_copy_attr_connlabels(dest->connlabels_mask, orig->connlabels_mask);
+}
+
const copy_attr copy_attr_array[ATTR_MAX] = {
[ATTR_ORIG_IPV4_SRC] = copy_attr_orig_ipv4_src,
[ATTR_ORIG_IPV4_DST] = copy_attr_orig_ipv4_dst,
@@ -534,6 +540,7 @@ const copy_attr copy_attr_array[ATTR_MAX] = {
[ATTR_TIMESTAMP_STOP] = copy_attr_timestamp_stop,
[ATTR_HELPER_INFO] = copy_attr_help_info,
[ATTR_CONNLABELS] = copy_attr_connlabels,
+ [ATTR_CONNLABELS_MASK] = copy_attr_connlabels_mask,
};
/* this is used by nfct_copy() with the NFCT_CP_OVERRIDE flag set. */
@@ -544,8 +551,10 @@ void __copy_fast(struct nf_conntrack *ct1, const struct nf_conntrack *ct2)
ct1->secctx = NULL;
ct1->helper_info = NULL;
ct1->connlabels = NULL;
+ ct1->connlabels_mask = NULL;
copy_attr_secctx(ct1, ct2);
copy_attr_help_info(ct1, ct2);
copy_attr_connlabels(ct1, ct2);
+ copy_attr_connlabels_mask(ct1, ct2);
}
diff --git a/src/conntrack/getter.c b/src/conntrack/getter.c
index 53c9e0e..ae546ee 100644
--- a/src/conntrack/getter.c
+++ b/src/conntrack/getter.c
@@ -344,6 +344,11 @@ static const void *get_attr_connlabels(const struct nf_conntrack *ct)
return ct->connlabels;
}
+static const void *get_attr_connlabels_mask(const struct nf_conntrack *ct)
+{
+ return ct->connlabels_mask;
+}
+
const get_attr get_attr_array[ATTR_MAX] = {
[ATTR_ORIG_IPV4_SRC] = get_attr_orig_ipv4_src,
[ATTR_ORIG_IPV4_DST] = get_attr_orig_ipv4_dst,
@@ -412,4 +417,5 @@ const get_attr get_attr_array[ATTR_MAX] = {
[ATTR_TIMESTAMP_STOP] = get_attr_timestamp_stop,
[ATTR_HELPER_INFO] = get_attr_helper_info,
[ATTR_CONNLABELS] = get_attr_connlabels,
+ [ATTR_CONNLABELS_MASK] = get_attr_connlabels_mask,
};
diff --git a/src/conntrack/parse_mnl.c b/src/conntrack/parse_mnl.c
index a4272f9..6984e78 100644
--- a/src/conntrack/parse_mnl.c
+++ b/src/conntrack/parse_mnl.c
@@ -958,6 +958,7 @@ nfct_payload_parse(const void *payload, size_t payload_len,
if (nfct_parse_labels(tb[CTA_LABELS], ct) < 0)
return -1;
}
+ /* CTA_LABELS_MASK: never sent by kernel */
return 0;
}
diff --git a/src/conntrack/setter.c b/src/conntrack/setter.c
index 8879f02..4dda6c9 100644
--- a/src/conntrack/setter.c
+++ b/src/conntrack/setter.c
@@ -421,17 +421,27 @@ retry:
}
static void
-set_attr_connlabels(struct nf_conntrack *ct, const void *value, size_t len)
+do_set_attr_connlabels(struct nfct_bitmask *current, const void *value)
{
- if (ct->connlabels == value)
- return;
+ if (current && current != value)
+ nfct_bitmask_destroy(current);
+}
- if (ct->connlabels)
- nfct_bitmask_destroy(ct->connlabels);
+static void
+set_attr_connlabels(struct nf_conntrack *ct, const void *value, size_t len)
+{
+ do_set_attr_connlabels(ct->connlabels, value);
ct->connlabels = (void *) value;
}
static void
+set_attr_connlabels_mask(struct nf_conntrack *ct, const void *value, size_t len)
+{
+ do_set_attr_connlabels(ct->connlabels_mask, value);
+ ct->connlabels_mask = (void *) value;
+}
+
+static void
set_attr_do_nothing(struct nf_conntrack *ct, const void *value, size_t len) {}
const set_attr set_attr_array[ATTR_MAX] = {
@@ -502,4 +512,5 @@ const set_attr set_attr_array[ATTR_MAX] = {
[ATTR_TIMESTAMP_STOP] = set_attr_do_nothing,
[ATTR_HELPER_INFO] = set_attr_helper_info,
[ATTR_CONNLABELS] = set_attr_connlabels,
+ [ATTR_CONNLABELS_MASK] = set_attr_connlabels_mask,
};