netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] conntrack: nfct_cmp: also compare labels
@ 2013-06-05 20:30 Florian Westphal
  2013-06-05 20:30 ` [PATCH 2/2] qa: nfct_cmp: verify individual attr comparision Florian Westphal
  0 siblings, 1 reply; 2+ messages in thread
From: Florian Westphal @ 2013-06-05 20:30 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

As nfct_cmp fails if the ctmark is different, it should compare labels, too.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
YET another missing bit of the connlabel patchset.
Followup patch extends qa/test_api to check for these
kinds of errors.

diff --git a/src/conntrack/compare.c b/src/conntrack/compare.c
index 97c25cb..f4a194a 100644
--- a/src/conntrack/compare.c
+++ b/src/conntrack/compare.c
@@ -370,6 +370,51 @@ cmp_secctx(const struct nf_conntrack *ct1,
 	return strcmp(ct1->secctx, ct2->secctx) == 0;
 }
 
+static int __cmp_clabel(const struct nfct_bitmask *a,
+			const struct nfct_bitmask *b)
+{
+	unsigned int len, max;
+	const uint32_t *bits;
+
+	if (a == NULL || b == NULL)
+		return a == b;
+
+	if (a->words < b->words) {
+		bits = b->bits;
+		max = b->words;
+		len = a->words;
+	} else {
+		bits = a->bits;
+		max = a->words;
+		len = b->words;
+	}
+
+	while (max > len) {
+		if (bits[--max])
+			return 0;
+	}
+	/* bitmask sizes are equal or extra bits are not set */
+	return memcmp(a->bits, b->bits, len * sizeof(a->bits[0])) == 0;
+}
+
+static int cmp_clabel(const struct nf_conntrack *ct1,
+		      const struct nf_conntrack *ct2,
+		      unsigned int flags)
+{
+	return __cmp_clabel(nfct_get_attr(ct1, ATTR_CONNLABELS),
+			    nfct_get_attr(ct2, ATTR_CONNLABELS));
+
+}
+
+static int cmp_clabel_mask(const struct nf_conntrack *ct1,
+		      const struct nf_conntrack *ct2,
+		      unsigned int flags)
+{
+	return __cmp_clabel(nfct_get_attr(ct1, ATTR_CONNLABELS_MASK),
+			    nfct_get_attr(ct2, ATTR_CONNLABELS_MASK));
+
+}
+
 static int cmp_meta(const struct nf_conntrack *ct1,
 		    const struct nf_conntrack *ct2,
 		    unsigned int flags)
@@ -392,6 +437,10 @@ static int cmp_meta(const struct nf_conntrack *ct1,
 		return 0;
 	if (!__cmp(ATTR_SECCTX, ct1, ct2, flags, cmp_secctx))
 		return 0;
+	if (!__cmp(ATTR_CONNLABELS, ct1, ct2, flags, cmp_clabel))
+		return 0;
+	if (!__cmp(ATTR_CONNLABELS_MASK, ct1, ct2, flags, cmp_clabel_mask))
+		return 0;
 
 	return 1;
 }
-- 
1.8.1.5


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [PATCH 2/2] qa: nfct_cmp: verify individual attr comparision
  2013-06-05 20:30 [PATCH 1/2] conntrack: nfct_cmp: also compare labels Florian Westphal
@ 2013-06-05 20:30 ` Florian Westphal
  0 siblings, 0 replies; 2+ messages in thread
From: Florian Westphal @ 2013-06-05 20:30 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

For each attribute:
 - copy ct2 attrs to ct1 (so they're the same)
 - change value of attr
 - call nfct_cmp to check of cmp now fails

Unfortunately, most attributes fail this test at this time, thus
added a TODO exclusion list to make the test pass for now.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
It would be nice if others could have a look at the
FIXME switch in the patch below, and perhaps add
comments for those attributes that are intentionally
omitted from comparisions.

diff --git a/qa/test_api.c b/qa/test_api.c
index aea4bc0..583feb8 100644
--- a/qa/test_api.c
+++ b/qa/test_api.c
@@ -36,6 +36,7 @@ static void test_nfct_bitmask(void)
 {
 	struct nfct_bitmask *a, *b;
 	unsigned short int maxb, i;
+	struct nf_conntrack *ct1, *ct2;
 
 	printf("== test nfct_bitmask_* API ==\n");
 
@@ -79,9 +80,168 @@ static void test_nfct_bitmask(void)
 	}
 
 	nfct_bitmask_destroy(b);
+
+	ct1 = nfct_new();
+	ct2 = nfct_new();
+
+	maxb = rand() & 0xff;
+	maxb += 128;
+	maxb /= 2;
+	a = nfct_bitmask_new(maxb * 2);
+	b = nfct_bitmask_new(maxb);
+	nfct_set_attr(ct1, ATTR_CONNLABELS, a);
+	nfct_set_attr(ct2, ATTR_CONNLABELS, b);
+
+	assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1);
+
+	nfct_bitmask_set_bit(a, maxb);
+	nfct_bitmask_set_bit(b, maxb);
+	assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1);
+
+	nfct_bitmask_set_bit(a, maxb * 2);
+	assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 0);
+	nfct_destroy(ct1);
+	nfct_destroy(ct2);
 	printf("OK\n");
 }
 
+/* These attributes cannot be set, ignore them. */
+static int attr_is_readonly(int attr)
+{
+	switch (attr) {
+	case ATTR_ORIG_COUNTER_PACKETS:
+	case ATTR_REPL_COUNTER_PACKETS:
+	case ATTR_ORIG_COUNTER_BYTES:
+	case ATTR_REPL_COUNTER_BYTES:
+	case ATTR_USE:
+	case ATTR_SECCTX:
+	case ATTR_TIMESTAMP_START:
+	case ATTR_TIMESTAMP_STOP:
+		return 1;
+	}
+	return 0;
+}
+
+
+static int test_nfct_cmp_api_single(struct nf_conntrack *ct1,
+				struct nf_conntrack *ct2, int attr)
+{
+	char data[256];
+	struct nfct_bitmask *b;
+	int bit;
+
+	if (attr_is_readonly(attr))
+		return 0;
+
+	switch (attr) {
+	case ATTR_SECMARK: /* obsolete */
+		return 0;
+
+	/* FIXME: not implemented comparators: */
+	case ATTR_SNAT_IPV4:
+	case ATTR_DNAT_IPV4:
+	case ATTR_SNAT_PORT:
+	case ATTR_DNAT_PORT:
+
+	case ATTR_TCP_FLAGS_ORIG:
+	case ATTR_TCP_FLAGS_REPL:
+	case ATTR_TCP_MASK_ORIG:
+	case ATTR_TCP_MASK_REPL:
+
+	case ATTR_MASTER_IPV4_SRC:
+	case ATTR_MASTER_IPV4_DST:
+	case ATTR_MASTER_IPV6_SRC:
+	case ATTR_MASTER_IPV6_DST:
+	case ATTR_MASTER_PORT_SRC:
+	case ATTR_MASTER_PORT_DST:
+	case ATTR_MASTER_L3PROTO:
+	case ATTR_MASTER_L4PROTO:
+
+	case ATTR_ORIG_NAT_SEQ_CORRECTION_POS:
+	case ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE:
+	case ATTR_ORIG_NAT_SEQ_OFFSET_AFTER:
+	case ATTR_REPL_NAT_SEQ_CORRECTION_POS:
+	case ATTR_REPL_NAT_SEQ_OFFSET_BEFORE:
+	case ATTR_REPL_NAT_SEQ_OFFSET_AFTER:
+
+	case ATTR_SCTP_VTAG_ORIG:
+	case ATTR_SCTP_VTAG_REPL:
+
+	case ATTR_HELPER_NAME:
+
+	case ATTR_DCCP_ROLE:
+	case ATTR_DCCP_HANDSHAKE_SEQ:
+
+	case ATTR_TCP_WSCALE_ORIG:
+	case ATTR_TCP_WSCALE_REPL:
+
+	case ATTR_HELPER_INFO:
+		return 0; /* XXX */
+
+	default:
+		break;
+	}
+
+	if (attr >= ATTR_SCTP_STATE) {
+		nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_SCTP);
+		nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_SCTP);
+	} else if (attr >= ATTR_TCP_FLAGS_ORIG) {
+		nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_TCP);
+		nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_TCP);
+	} else if (attr >= ATTR_ICMP_CODE) {
+		nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_ICMP);
+		nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_ICMP);
+	} else if (attr >= ATTR_ORIG_PORT_SRC) {
+		nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_TCP);
+		nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_TCP);
+	}
+
+	nfct_copy(ct2, ct1, NFCT_CP_OVERRIDE);
+	memset(data, 42, sizeof(data));
+
+	assert(nfct_attr_is_set(ct1, attr));
+	assert(nfct_attr_is_set(ct2, attr));
+
+	switch (attr) {
+	case ATTR_CONNLABELS:
+	case ATTR_CONNLABELS_MASK:
+		b = (void *) nfct_get_attr(ct1, attr);
+		assert(b);
+		b = nfct_bitmask_clone(b);
+		assert(b);
+		bit = nfct_bitmask_maxbit(b);
+		if (nfct_bitmask_test_bit(b, bit)) {
+			nfct_bitmask_unset_bit(b, bit);
+			assert(!nfct_bitmask_test_bit(b, bit));
+		} else {
+			nfct_bitmask_set_bit(b, bit);
+			assert(nfct_bitmask_test_bit(b, bit));
+		}
+		assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1);
+		nfct_set_attr(ct2, attr, b);
+		break;
+	case ATTR_HELPER_INFO:
+		nfct_set_attr_l(ct2, attr, "test", 4);
+		break;
+	default:
+		nfct_set_attr(ct2, attr, data);
+		break;
+	}
+
+	if (nfct_cmp(ct1, ct2, NFCT_CMP_ALL) != 0) {
+		fprintf(stderr, "nfct_cmp assert failure for attr %d\n", attr);
+		fprintf(stderr, "%p, %p, %x, %x\n", nfct_get_attr(ct1, attr),
+				nfct_get_attr(ct2, attr),
+				nfct_get_attr_u32(ct1, attr), nfct_get_attr_u32(ct2, attr));
+		return -1;
+	}
+	if (nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_STRICT) != 0) {
+		fprintf(stderr, "nfct_cmp strict assert failure for attr %d\n", attr);
+		return -1;
+	}
+	return 0;
+}
+
 static void test_nfct_cmp_api(struct nf_conntrack *ct1, struct nf_conntrack *ct2)
 {
 	int i;
@@ -111,6 +271,10 @@ static void test_nfct_cmp_api(struct nf_conntrack *ct1, struct nf_conntrack *ct2
 		assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_STRICT) == 0);
 		assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_MASK) == 0);
 	}
+
+	for (i=0; i < ATTR_MAX ; i++)
+		assert(test_nfct_cmp_api_single(ct1, ct2, i) == 0);
+
 	nfct_copy(ct2, ct1, NFCT_CP_OVERRIDE);
 	for (i=0; i < ATTR_MAX ; i++) {
 		nfct_attr_unset(ct1, i);
@@ -240,17 +404,9 @@ int main(void)
 	ret = fork();
 	if (ret == 0) {
 		for (i=0; i<ATTR_MAX; i++) {
-			/* These attributes cannot be set, ignore them. */
-			switch(i) {
-			case ATTR_ORIG_COUNTER_PACKETS:
-			case ATTR_REPL_COUNTER_PACKETS:
-			case ATTR_ORIG_COUNTER_BYTES:
-			case ATTR_REPL_COUNTER_BYTES:
-			case ATTR_USE:
-			case ATTR_SECCTX:
-			case ATTR_TIMESTAMP_START:
-			case ATTR_TIMESTAMP_STOP:
+			if (attr_is_readonly(i))
 				continue;
+			switch(i) {
 			/* These attributes require special handling */
 			case ATTR_HELPER_INFO:
 				nfct_set_attr_l(ct, i, data, sizeof(data));
-- 
1.8.1.5


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2013-06-05 20:32 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-05 20:30 [PATCH 1/2] conntrack: nfct_cmp: also compare labels Florian Westphal
2013-06-05 20:30 ` [PATCH 2/2] qa: nfct_cmp: verify individual attr comparision Florian Westphal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).