summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/nfct-mnl-set-label.c8
-rw-r--r--include/internal/object.h1
-rw-r--r--include/libnetfilter_conntrack/libnetfilter_conntrack.h1
-rw-r--r--include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h1
-rw-r--r--qa/test_api.c25
-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
11 files changed, 70 insertions, 11 deletions
diff --git a/examples/nfct-mnl-set-label.c b/examples/nfct-mnl-set-label.c
index 9e7fbf6..c52b267 100644
--- a/examples/nfct-mnl-set-label.c
+++ b/examples/nfct-mnl-set-label.c
@@ -35,6 +35,14 @@ static void set_label(struct nf_conntrack *ct, struct callback_args *cbargs)
nfct_bitmask_set_bit(b, bit);
nfct_set_attr(ct, ATTR_CONNLABELS, b);
+ if (bit >= 0) {
+ b = nfct_bitmask_new(bit);
+ if (b) {
+ nfct_bitmask_set_bit(b, bit);
+ nfct_set_attr(ct, ATTR_CONNLABELS_MASK, b);
+ }
+ }
+
cbargs->seq++;
nlh = mnl_nlmsg_put_header(buf);
diff --git a/include/internal/object.h b/include/internal/object.h
index bbb038a..540ad0d 100644
--- a/include/internal/object.h
+++ b/include/internal/object.h
@@ -191,6 +191,7 @@ struct nf_conntrack {
size_t helper_info_len;
struct nfct_bitmask *connlabels;
+ struct nfct_bitmask *connlabels_mask;
};
/*
diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack.h b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
index c209184..39dc24c 100644
--- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h
+++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
@@ -134,6 +134,7 @@ enum nf_conntrack_attr {
ATTR_TIMESTAMP_STOP = 64, /* u64 bits, linux >= 2.6.38 */
ATTR_HELPER_INFO, /* variable length */
ATTR_CONNLABELS, /* variable length */
+ ATTR_CONNLABELS_MASK, /* variable length */
ATTR_MAX
};
diff --git a/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h b/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h
index 3c69ba9..5812595 100644
--- a/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h
+++ b/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h
@@ -54,6 +54,7 @@ enum ctattr_type {
CTA_TIMESTAMP,
CTA_MARK_MASK,
CTA_LABELS,
+ CTA_LABELS_MASK,
__CTA_MAX
};
#define CTA_MAX (__CTA_MAX - 1)
diff --git a/qa/test_api.c b/qa/test_api.c
index 399afdc..499d01f 100644
--- a/qa/test_api.c
+++ b/qa/test_api.c
@@ -91,7 +91,7 @@ int main(void)
char data[256];
const char *val;
int status;
- struct nfct_bitmask *b;
+ struct nfct_bitmask *b, *b2;
srand(time(NULL));
@@ -121,14 +121,23 @@ int main(void)
eval_sigterm(status);
}
+ b = nfct_bitmask_new(rand() & 0xffff);
+ assert(b);
+ b2 = nfct_bitmask_new(rand() & 0xffff);
+ assert(b2);
+
for (i=0; i<ATTR_MAX; i++) {
- if (i != ATTR_CONNLABELS) {
+ switch (i) {
+ case ATTR_CONNLABELS:
+ nfct_set_attr(ct, i, b);
+ break;
+ case ATTR_CONNLABELS_MASK:
+ nfct_set_attr(ct, i, b2);
+ break;
+ default:
nfct_set_attr(ct, i, data);
- continue;
+ break;
}
- b = nfct_bitmask_new(rand() & 0xffff);
- assert(b);
- nfct_set_attr(ct, i, b);
}
printf("== test get API ==\n");
@@ -162,6 +171,7 @@ int main(void)
nfct_set_attr_l(ct, i, data, sizeof(data));
break;
case ATTR_CONNLABELS:
+ case ATTR_CONNLABELS_MASK:
/* already set above */
break;
default:
@@ -173,6 +183,9 @@ int main(void)
case ATTR_CONNLABELS:
assert((void *) val == b);
continue;
+ case ATTR_CONNLABELS_MASK:
+ assert((void *) val == b2);
+ continue;
}
if (val[0] != data[0]) {
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,
};