Home | History | Annotate | Download | only in qa
      1 /*
      2  * Run this after adding a new attribute to the nf_conntrack object
      3  */
      4 
      5 #include <assert.h>
      6 #include <stdio.h>
      7 #include <stdbool.h>
      8 #include <stdlib.h>
      9 #include <unistd.h>
     10 #include <string.h>
     11 #include <sys/wait.h>
     12 #include <time.h>
     13 #include <errno.h>
     14 
     15 #include <libnetfilter_conntrack/libnetfilter_conntrack.h>
     16 
     17 /*
     18  * this file contains a test to check the set/get/copy/cmp APIs.
     19  */
     20 
     21 static void eval_sigterm(int status)
     22 {
     23 	switch(WTERMSIG(status)) {
     24 	case SIGSEGV:
     25 		printf("received SIGSEV\n");
     26 		break;
     27 	case 0:
     28 		printf("OK\n");
     29 		break;
     30 	default:
     31 		printf("exited with signal: %d\n", WTERMSIG(status));
     32 		break;
     33 	}
     34 }
     35 
     36 static void test_nfct_bitmask(void)
     37 {
     38 	struct nfct_bitmask *a, *b;
     39 	unsigned short int maxb, i;
     40 	struct nf_conntrack *ct1, *ct2;
     41 
     42 	printf("== test nfct_bitmask_* API ==\n");
     43 
     44 	maxb = rand() & 0xffff;
     45 
     46 	a = nfct_bitmask_new(maxb);
     47 
     48 	assert(!nfct_bitmask_test_bit(a, maxb + 32));
     49 	nfct_bitmask_set_bit(a, maxb + 32);
     50 	assert(!nfct_bitmask_test_bit(a, maxb + 32));
     51 
     52 	for (i = 0; i <= maxb; i++)
     53 		assert(!nfct_bitmask_test_bit(a, i));
     54 
     55 	for (i = 0; i <= maxb; i++) {
     56 		if (rand() & 1) {
     57 			assert(!nfct_bitmask_test_bit(a, i));
     58 			continue;
     59 		}
     60 		nfct_bitmask_set_bit(a, i);
     61 		assert(nfct_bitmask_test_bit(a, i));
     62 	}
     63 
     64 	b = nfct_bitmask_clone(a);
     65 	assert(b);
     66 
     67 	for (i = 0; i <= maxb; i++) {
     68 		if (nfct_bitmask_test_bit(a, i))
     69 			assert(nfct_bitmask_test_bit(b, i));
     70 		else
     71 			assert(!nfct_bitmask_test_bit(b, i));
     72 	}
     73 
     74 	nfct_bitmask_destroy(a);
     75 
     76 	for (i = 0; i <= maxb; i++) {
     77 		if (rand() & 1)
     78 			continue;
     79 		nfct_bitmask_unset_bit(b, i);
     80 		assert(!nfct_bitmask_test_bit(b, i));
     81 	}
     82 
     83 	/* nfct_bitmask_clear() */
     84 	for (i = 0; i < maxb; i++) {
     85 		nfct_bitmask_set_bit(b, i);
     86 		assert(nfct_bitmask_test_bit(b, i));
     87 		nfct_bitmask_clear(b);
     88 		assert(!nfct_bitmask_test_bit(b, i));
     89 	}
     90 
     91 	for (i = 0; i < maxb; i++)
     92 		nfct_bitmask_set_bit(b, i);
     93 	nfct_bitmask_clear(b);
     94 	for (i = 0; i < maxb; i++)
     95 		assert(!nfct_bitmask_test_bit(b, i));
     96 
     97 	/* nfct_bitmask_equal() */
     98 	for (i = 0; i < maxb / 32 * 32; i += 32) {
     99 		a = nfct_bitmask_new(i);
    100 		assert(!nfct_bitmask_equal(a, b));
    101 		nfct_bitmask_destroy(a);
    102 	}
    103 
    104 	a = nfct_bitmask_clone(b);
    105 	assert(nfct_bitmask_equal(a, b));
    106 	for (i = 0; i < maxb; i++) {
    107 		if (nfct_bitmask_test_bit(a, i)) {
    108 			nfct_bitmask_unset_bit(a, i);
    109 			assert(!nfct_bitmask_equal(a, b));
    110 			nfct_bitmask_set_bit(a, i);
    111 		} else {
    112 			nfct_bitmask_set_bit(a, i);
    113 			assert(!nfct_bitmask_equal(a, b));
    114 			nfct_bitmask_unset_bit(a, i);
    115 		}
    116 		assert(nfct_bitmask_equal(a, b));
    117 	}
    118 
    119 	nfct_bitmask_destroy(a);
    120 	nfct_bitmask_destroy(b);
    121 
    122 	ct1 = nfct_new();
    123 	ct2 = nfct_new();
    124 
    125 	maxb = rand() & 0xff;
    126 	maxb += 128;
    127 	maxb /= 2;
    128 	a = nfct_bitmask_new(maxb * 2);
    129 	b = nfct_bitmask_new(maxb);
    130 	nfct_set_attr(ct1, ATTR_CONNLABELS, a);
    131 	nfct_set_attr(ct2, ATTR_CONNLABELS, b);
    132 
    133 	assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1);
    134 
    135 	nfct_bitmask_set_bit(a, maxb);
    136 	nfct_bitmask_set_bit(b, maxb);
    137 	assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1);
    138 
    139 	nfct_bitmask_set_bit(a, maxb * 2);
    140 	assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 0);
    141 	nfct_destroy(ct1);
    142 	nfct_destroy(ct2);
    143 	printf("OK\n");
    144 }
    145 
    146 /* These attributes cannot be set, ignore them. */
    147 static int attr_is_readonly(int attr)
    148 {
    149 	switch (attr) {
    150 	case ATTR_ORIG_COUNTER_PACKETS:
    151 	case ATTR_REPL_COUNTER_PACKETS:
    152 	case ATTR_ORIG_COUNTER_BYTES:
    153 	case ATTR_REPL_COUNTER_BYTES:
    154 	case ATTR_USE:
    155 	case ATTR_SECCTX:
    156 	case ATTR_TIMESTAMP_START:
    157 	case ATTR_TIMESTAMP_STOP:
    158 		return 1;
    159 	}
    160 	return 0;
    161 }
    162 
    163 
    164 static int test_nfct_cmp_api_single(struct nf_conntrack *ct1,
    165 				struct nf_conntrack *ct2, int attr)
    166 {
    167 	char data[256];
    168 	struct nfct_bitmask *b;
    169 	int bit;
    170 
    171 	if (attr_is_readonly(attr))
    172 		return 0;
    173 
    174 	switch (attr) {
    175 	case ATTR_SECMARK: /* obsolete */
    176 		return 0;
    177 
    178 	/* FIXME: not implemented comparators: */
    179 	case ATTR_SNAT_IPV4:
    180 	case ATTR_DNAT_IPV4:
    181 	case ATTR_SNAT_IPV6:
    182 	case ATTR_DNAT_IPV6:
    183 	case ATTR_SNAT_PORT:
    184 	case ATTR_DNAT_PORT:
    185 
    186 	case ATTR_TCP_FLAGS_ORIG:
    187 	case ATTR_TCP_FLAGS_REPL:
    188 	case ATTR_TCP_MASK_ORIG:
    189 	case ATTR_TCP_MASK_REPL:
    190 
    191 	case ATTR_MASTER_IPV4_SRC:
    192 	case ATTR_MASTER_IPV4_DST:
    193 	case ATTR_MASTER_IPV6_SRC:
    194 	case ATTR_MASTER_IPV6_DST:
    195 	case ATTR_MASTER_PORT_SRC:
    196 	case ATTR_MASTER_PORT_DST:
    197 	case ATTR_MASTER_L3PROTO:
    198 	case ATTR_MASTER_L4PROTO:
    199 
    200 	case ATTR_ORIG_NAT_SEQ_CORRECTION_POS:
    201 	case ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE:
    202 	case ATTR_ORIG_NAT_SEQ_OFFSET_AFTER:
    203 	case ATTR_REPL_NAT_SEQ_CORRECTION_POS:
    204 	case ATTR_REPL_NAT_SEQ_OFFSET_BEFORE:
    205 	case ATTR_REPL_NAT_SEQ_OFFSET_AFTER:
    206 
    207 	case ATTR_SCTP_VTAG_ORIG:
    208 	case ATTR_SCTP_VTAG_REPL:
    209 
    210 	case ATTR_HELPER_NAME:
    211 
    212 	case ATTR_DCCP_ROLE:
    213 	case ATTR_DCCP_HANDSHAKE_SEQ:
    214 
    215 	case ATTR_TCP_WSCALE_ORIG:
    216 	case ATTR_TCP_WSCALE_REPL:
    217 
    218 	case ATTR_HELPER_INFO:
    219 		return 0; /* XXX */
    220 
    221 	default:
    222 		break;
    223 	}
    224 
    225 	if (attr >= ATTR_SCTP_STATE) {
    226 		nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_SCTP);
    227 		nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_SCTP);
    228 	} else if (attr >= ATTR_TCP_FLAGS_ORIG) {
    229 		nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_TCP);
    230 		nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_TCP);
    231 	} else if (attr >= ATTR_ICMP_CODE) {
    232 		nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_ICMP);
    233 		nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_ICMP);
    234 	} else if (attr >= ATTR_ORIG_PORT_SRC) {
    235 		nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_TCP);
    236 		nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_TCP);
    237 	}
    238 
    239 	nfct_copy(ct2, ct1, NFCT_CP_OVERRIDE);
    240 	memset(data, 42, sizeof(data));
    241 
    242 	assert(nfct_attr_is_set(ct1, attr));
    243 	assert(nfct_attr_is_set(ct2, attr));
    244 
    245 	switch (attr) {
    246 	case ATTR_CONNLABELS:
    247 	case ATTR_CONNLABELS_MASK:
    248 		b = (void *) nfct_get_attr(ct1, attr);
    249 		assert(b);
    250 		b = nfct_bitmask_clone(b);
    251 		assert(b);
    252 		bit = nfct_bitmask_maxbit(b);
    253 		if (nfct_bitmask_test_bit(b, bit)) {
    254 			nfct_bitmask_unset_bit(b, bit);
    255 			assert(!nfct_bitmask_test_bit(b, bit));
    256 		} else {
    257 			nfct_bitmask_set_bit(b, bit);
    258 			assert(nfct_bitmask_test_bit(b, bit));
    259 		}
    260 		assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1);
    261 		nfct_set_attr(ct2, attr, b);
    262 		break;
    263 	case ATTR_HELPER_INFO:
    264 		nfct_set_attr_l(ct2, attr, "test", 4);
    265 		break;
    266 	default:
    267 		nfct_set_attr(ct2, attr, data);
    268 		break;
    269 	}
    270 
    271 	if (nfct_cmp(ct1, ct2, NFCT_CMP_ALL) != 0) {
    272 		fprintf(stderr, "nfct_cmp assert failure for attr %d\n", attr);
    273 		fprintf(stderr, "%p, %p, %x, %x\n", nfct_get_attr(ct1, attr),
    274 				nfct_get_attr(ct2, attr),
    275 				nfct_get_attr_u32(ct1, attr), nfct_get_attr_u32(ct2, attr));
    276 		return -1;
    277 	}
    278 	if (nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_STRICT) != 0) {
    279 		fprintf(stderr, "nfct_cmp strict assert failure for attr %d\n", attr);
    280 		return -1;
    281 	}
    282 	return 0;
    283 }
    284 
    285 static int test_cmp_attr32(int attr, bool at1, bool at2,
    286 			   uint32_t v1, uint32_t v2, unsigned int flags)
    287 {
    288 	struct nf_conntrack *ct1 = nfct_new();
    289 	struct nf_conntrack *ct2 = nfct_new();
    290 	int ret;
    291 
    292 	if (at1)
    293 		nfct_set_attr_u32(ct1, attr, v1);
    294 	if (at2)
    295 		nfct_set_attr_u32(ct2, attr, v2);
    296 
    297 	ret = nfct_cmp(ct1, ct2, NFCT_CMP_ALL | flags);
    298 
    299 	nfct_destroy(ct1);
    300 	nfct_destroy(ct2);
    301 
    302 	return ret;
    303 }
    304 
    305 static void test_nfct_cmp_attr(int attr)
    306 {
    307 	unsigned int flags = 0;
    308 
    309 	/* 0000, 1000, 1100, 0010, 1010... */
    310 	/*		       attr       at1    at2    v1	v2 */
    311 	assert(test_cmp_attr32(attr, false, false,	0,	0,	flags) == 1);
    312 	assert(test_cmp_attr32(attr, true,  false,	0,	0,	flags) == 1);
    313 	assert(test_cmp_attr32(attr, false, true,	0,	0,	flags) == 1);
    314 	assert(test_cmp_attr32(attr, true,  true,	0,	0,	flags) == 1);
    315 	assert(test_cmp_attr32(attr, false, false,	1,	0,	flags) == 1); /* verbose */
    316 	assert(test_cmp_attr32(attr, true,  false,	1,	0,	flags) == 1);
    317 	assert(test_cmp_attr32(attr, false, true,	1,	0,	flags) == 1); /* verbose */
    318 	assert(test_cmp_attr32(attr, true,  true,	1,	0,	flags) == 0);
    319 	assert(test_cmp_attr32(attr, false, false,	0,	1,	flags) == 1); /* verbose */
    320 	assert(test_cmp_attr32(attr, true,  false,	0,	1,	flags) == 1); /* verbose */
    321 	assert(test_cmp_attr32(attr, false, true,	0,	1,	flags) == 1);
    322 	assert(test_cmp_attr32(attr, true,  true,	0,	1,	flags) == 0);
    323 	assert(test_cmp_attr32(attr, false, false,	1,	1,	flags) == 1); /* verbose */
    324 	assert(test_cmp_attr32(attr, true,  false,	1,	1,	flags) == 1); /* verbose */
    325 	assert(test_cmp_attr32(attr, false, true,	1,	1,	flags) == 1); /* verbose */
    326 	assert(test_cmp_attr32(attr, true,  true,	1,	1,	flags) == 1);
    327 
    328 	flags = NFCT_CMP_STRICT;
    329 	assert(test_cmp_attr32(attr, false, false,	0,	0,	flags) == 1);
    330 	assert(test_cmp_attr32(attr, true,  false,	0,	0,	flags) == 1);
    331 	assert(test_cmp_attr32(attr, false, true,	0,	0,	flags) == 1);
    332 	assert(test_cmp_attr32(attr, true,  true,	0,	0,	flags) == 1);
    333 	assert(test_cmp_attr32(attr, false, false,	1,	0,	flags) == 1); /* verbose */
    334 	assert(test_cmp_attr32(attr, true,  false,	1,	0,	flags) == 0);
    335 	assert(test_cmp_attr32(attr, false, true,	1,	0,	flags) == 1); /* verbose */
    336 	assert(test_cmp_attr32(attr, true,  true,	1,	0,	flags) == 0);
    337 	assert(test_cmp_attr32(attr, false, false,	0,	1,	flags) == 1); /* verbose */
    338 	assert(test_cmp_attr32(attr, true,  false,	0,	1,	flags) == 1); /* verbose */
    339 	assert(test_cmp_attr32(attr, false, true,	0,	1,	flags) == 0);
    340 	assert(test_cmp_attr32(attr, true,  true,	0,	1,	flags) == 0);
    341 	assert(test_cmp_attr32(attr, false, false,	1,	1,	flags) == 1); /* verbose */
    342 	assert(test_cmp_attr32(attr, true,  false,	1,	1,	flags) == 0); /* verbose */
    343 	assert(test_cmp_attr32(attr, false, true,	1,	1,	flags) == 0); /* verbose */
    344 	assert(test_cmp_attr32(attr, true,  true,	1,	1,	flags) == 1);
    345 
    346 	flags = NFCT_CMP_MASK;
    347 	assert(test_cmp_attr32(attr, false, false,	0,	0,	flags) == 1);
    348 	assert(test_cmp_attr32(attr, true,  false,	0,	0,	flags) == 1);
    349 	assert(test_cmp_attr32(attr, false, true,	0,	0,	flags) == 1);
    350 	assert(test_cmp_attr32(attr, true,  true,	0,	0,	flags) == 1);
    351 	assert(test_cmp_attr32(attr, false, false,	1,	0,	flags) == 1); /* verbose */
    352 	assert(test_cmp_attr32(attr, true,  false,	1,	0,	flags) == 0);
    353 	assert(test_cmp_attr32(attr, false, true,	1,	0,	flags) == 1); /* verbose */
    354 	assert(test_cmp_attr32(attr, true,  true,	1,	0,	flags) == 0);
    355 	assert(test_cmp_attr32(attr, false, false,	0,	1,	flags) == 1); /* verbose */
    356 	assert(test_cmp_attr32(attr, true,  false,	0,	1,	flags) == 1); /* verbose */
    357 	assert(test_cmp_attr32(attr, false, true,	0,	1,	flags) == 1);
    358 	assert(test_cmp_attr32(attr, true,  true,	0,	1,	flags) == 0);
    359 	assert(test_cmp_attr32(attr, false, false,	1,	1,	flags) == 1); /* verbose */
    360 	assert(test_cmp_attr32(attr, true,  false,	1,	1,	flags) == 0); /* verbose */
    361 	assert(test_cmp_attr32(attr, false, true,	1,	1,	flags) == 1); /* verbose */
    362 	assert(test_cmp_attr32(attr, true,  true,	1,	1,	flags) == 1);
    363 
    364 	flags = NFCT_CMP_STRICT|NFCT_CMP_MASK;
    365 	assert(test_cmp_attr32(attr, false, false,	0,	0,	flags) == 1);
    366 	assert(test_cmp_attr32(attr, true,  false,	0,	0,	flags) == 1);
    367 	assert(test_cmp_attr32(attr, false, true,	0,	0,	flags) == 1);
    368 	assert(test_cmp_attr32(attr, true,  true,	0,	0,	flags) == 1);
    369 	assert(test_cmp_attr32(attr, false, false,	1,	0,	flags) == 1); /* verbose */
    370 	assert(test_cmp_attr32(attr, true,  false,	1,	0,	flags) == 0);
    371 	assert(test_cmp_attr32(attr, false, true,	1,	0,	flags) == 1); /* verbose */
    372 	assert(test_cmp_attr32(attr, true,  true,	1,	0,	flags) == 0);
    373 	assert(test_cmp_attr32(attr, false, false,	0,	1,	flags) == 1); /* verbose */
    374 	assert(test_cmp_attr32(attr, true,  false,	0,	1,	flags) == 1); /* verbose */
    375 	assert(test_cmp_attr32(attr, false, true,	0,	1,	flags) == 0);
    376 	assert(test_cmp_attr32(attr, true,  true,	0,	1,	flags) == 0);
    377 	assert(test_cmp_attr32(attr, false, false,	1,	1,	flags) == 1); /* verbose */
    378 	assert(test_cmp_attr32(attr, true,  false,	1,	1,	flags) == 0); /* verbose */
    379 	assert(test_cmp_attr32(attr, false, true,	1,	1,	flags) == 0); /* verbose */
    380 	assert(test_cmp_attr32(attr, true,  true,	1,	1,	flags) == 1);
    381 }
    382 
    383 static void test_nfct_cmp_api(struct nf_conntrack *ct1, struct nf_conntrack *ct2)
    384 {
    385 	int i;
    386 
    387 	printf("== test cmp API ==\n");
    388 
    389 	test_nfct_cmp_attr(ATTR_ZONE);
    390 	test_nfct_cmp_attr(ATTR_ORIG_ZONE);
    391 	test_nfct_cmp_attr(ATTR_REPL_ZONE);
    392 	test_nfct_cmp_attr(ATTR_MARK);
    393 
    394 	assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1);
    395 	assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_STRICT) == 0);
    396 
    397 	nfct_copy(ct1, ct2, NFCT_CP_OVERRIDE);
    398 
    399 	assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1);
    400 	assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_STRICT) == 1);
    401 
    402 	for (i=0; i < ATTR_MAX ; i++) {
    403 		nfct_attr_unset(ct1, i);
    404 
    405 		assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1);
    406 		assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_STRICT) == 0);
    407 		assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_MASK) == 1);
    408 	}
    409 	nfct_copy(ct1, ct2, NFCT_CP_OVERRIDE);
    410 	for (i=0; i < ATTR_MAX ; i++) {
    411 		nfct_attr_unset(ct2, i);
    412 
    413 		assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1);
    414 		assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_STRICT) == 0);
    415 		assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_MASK) == 0);
    416 	}
    417 
    418 	for (i=0; i < ATTR_MAX ; i++)
    419 		assert(test_nfct_cmp_api_single(ct1, ct2, i) == 0);
    420 
    421 	nfct_copy(ct2, ct1, NFCT_CP_OVERRIDE);
    422 	for (i=0; i < ATTR_MAX ; i++) {
    423 		nfct_attr_unset(ct1, i);
    424 		nfct_attr_unset(ct2, i);
    425 
    426 		assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1);
    427 		assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_STRICT) == 1);
    428 		assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_MASK) == 1);
    429 	}
    430 	nfct_destroy(ct1);
    431 	nfct_destroy(ct2);
    432 }
    433 
    434 static void test_nfexp_cmp_api(struct nf_expect *ex1, struct nf_expect *ex2)
    435 {
    436 	int i;
    437 
    438 	printf("== test expect cmp API ==\n");
    439 
    440 	/* XXX: missing nfexp_copy API. */
    441 	memcpy(ex1, ex2, nfexp_maxsize());
    442 
    443 	assert(nfexp_cmp(ex1, ex2, 0) == 1);
    444 	assert(nfexp_cmp(ex1, ex2, NFCT_CMP_STRICT) == 1);
    445 
    446 	assert(nfexp_attr_is_set(ex1, 0) == 1);
    447 	nfexp_attr_unset(ex1, 0);
    448 	assert(nfexp_attr_is_set(ex1, 0) == 0);
    449 
    450 	memcpy(ex1, ex2, nfexp_maxsize());
    451 	for (i=0; i < ATTR_EXP_MAX; i++) {
    452 		nfexp_attr_unset(ex1, i);
    453 
    454 		assert(nfexp_cmp(ex1, ex2, 0) == 1);
    455 		assert(nfexp_cmp(ex1, ex2, NFCT_CMP_STRICT) == 0);
    456 		assert(nfexp_cmp(ex1, ex2, NFCT_CMP_MASK) == 1);
    457 	}
    458 	memcpy(ex1, ex2, nfexp_maxsize());
    459 	for (i=0; i < ATTR_EXP_MAX; i++) {
    460 		nfexp_attr_unset(ex2, i);
    461 
    462 		assert(nfexp_cmp(ex1, ex2, 0) == 1);
    463 		assert(nfexp_cmp(ex1, ex2, NFCT_CMP_MASK) == 0);
    464 	}
    465 	memcpy(ex1, ex2, nfexp_maxsize());
    466 	for (i=0; i < ATTR_EXP_MAX; i++) {
    467 		nfexp_attr_unset(ex1, i);
    468 		nfexp_attr_unset(ex2, i);
    469 
    470 		assert(nfexp_cmp(ex1, ex2, 0) == 1);
    471 		assert(nfexp_cmp(ex1, ex2, NFCT_CMP_STRICT) == 1);
    472 		assert(nfexp_cmp(ex1, ex2, NFCT_CMP_MASK) == 1);
    473 	}
    474 	nfexp_destroy(ex1);
    475 	nfexp_destroy(ex2);
    476 }
    477 
    478 int main(void)
    479 {
    480 	int ret, i;
    481 	struct nf_conntrack *ct, *ct2, *tmp;
    482 	struct nf_expect *exp, *tmp_exp;
    483 	char data[256];
    484 	const char *val;
    485 	int status;
    486 	struct nfct_bitmask *b, *b2;
    487 
    488 	srand(time(NULL));
    489 
    490 	/* initialize fake data for testing purposes */
    491 	for (i=0; i<sizeof(data); i++)
    492 		data[i] = 0x01;
    493 
    494 	ct = nfct_new();
    495 	if (!ct) {
    496 		perror("nfct_new");
    497 		return 0;
    498 	}
    499 	tmp = nfct_new();
    500 	if (!tmp) {
    501 		perror("nfct_new");
    502 		return 0;
    503 	}
    504 
    505 	printf("== test set API ==\n");
    506 	ret = fork();
    507 	if (ret == 0) {
    508 		for (i=0; i<ATTR_MAX; i++)
    509 			nfct_set_attr(ct, i, data);
    510 		exit(0);
    511 	} else {
    512 		wait(&status);
    513 		eval_sigterm(status);
    514 	}
    515 
    516 	b = nfct_bitmask_new(rand() & 0xffff);
    517 	assert(b);
    518 	b2 = nfct_bitmask_new(rand() & 0xffff);
    519 	assert(b2);
    520 
    521 	for (i=0; i<ATTR_MAX; i++) {
    522 		switch (i) {
    523 		case ATTR_CONNLABELS:
    524 			nfct_set_attr(ct, i, b);
    525 			break;
    526 		case ATTR_CONNLABELS_MASK:
    527 			nfct_set_attr(ct, i, b2);
    528 			break;
    529 		default:
    530 			nfct_set_attr(ct, i, data);
    531 			break;
    532 		}
    533 	}
    534 
    535 	printf("== test get API ==\n");
    536 	ret = fork();
    537 	if (ret == 0) {
    538 		for (i=0; i<ATTR_MAX; i++)
    539 			nfct_get_attr(ct, i);
    540 		exit(0);
    541 	} else {
    542 		wait(&status);
    543 		eval_sigterm(status);
    544 	}
    545 
    546 	printf("== validate set API ==\n");
    547 	ret = fork();
    548 	if (ret == 0) {
    549 		for (i=0; i<ATTR_MAX; i++) {
    550 			if (attr_is_readonly(i))
    551 				continue;
    552 			switch(i) {
    553 			/* These attributes require special handling */
    554 			case ATTR_HELPER_INFO:
    555 				nfct_set_attr_l(ct, i, data, sizeof(data));
    556 				break;
    557 			case ATTR_CONNLABELS:
    558 			case ATTR_CONNLABELS_MASK:
    559 				/* already set above */
    560 				break;
    561 			default:
    562 				data[0] = (uint8_t) i;
    563 				nfct_set_attr(ct, i, data);
    564 			}
    565 			val = nfct_get_attr(ct, i);
    566 			switch (i) {
    567 			case ATTR_CONNLABELS:
    568 				assert((void *) val == b);
    569 				continue;
    570 			case ATTR_CONNLABELS_MASK:
    571 				assert((void *) val == b2);
    572 				continue;
    573 			}
    574 
    575 			if (val[0] != data[0]) {
    576 				printf("ERROR: set/get operations don't match "
    577 				       "for attribute %d (%x != %x)\n",
    578 					i, val[0], data[0]);
    579 			}
    580 		}
    581 		exit(0);
    582 	} else {
    583 		wait(&status);
    584 		eval_sigterm(status);
    585 	}
    586 
    587 	printf("== test copy API ==\n");
    588 	ret = fork();
    589 	if (ret == 0) {
    590 		for (i=0; i<ATTR_MAX; i++)
    591 			nfct_copy_attr(tmp, ct, i);
    592 		exit(0);
    593 	} else {
    594 		wait(&status);
    595 		eval_sigterm(status);
    596 	}
    597 
    598 	ret = fork();
    599 	if (ret == 0) {
    600 		test_nfct_cmp_api(tmp, ct);
    601 		exit(0);
    602 	} else {
    603 		wait(&status);
    604 		eval_sigterm(status);
    605 	}
    606 
    607 	exp = nfexp_new();
    608 	if (!exp) {
    609 		perror("nfexp_new");
    610 		return 0;
    611 	}
    612 	tmp_exp = nfexp_new();
    613 	if (!tmp_exp) {
    614 		perror("nfexp_new");
    615 		return 0;
    616 	}
    617 
    618 	printf("== test expect set API ==\n");
    619 	ret = fork();
    620 	if (ret == 0) {
    621 		for (i=0; i<ATTR_EXP_MAX; i++)
    622 			nfexp_set_attr(exp, i, data);
    623 		exit(0);
    624 	} else {
    625 		wait(&status);
    626 		eval_sigterm(status);
    627 	}
    628 
    629 	for (i=0; i<ATTR_EXP_MAX; i++)
    630 		nfexp_set_attr(exp, i, data);
    631 
    632 	printf("== test expect get API ==\n");
    633 	ret = fork();
    634 	if (ret == 0) {
    635 		for (i=0; i<ATTR_EXP_MAX; i++)
    636 			nfexp_get_attr(exp, i);
    637 		exit(0);
    638 	} else {
    639 		wait(&status);
    640 		eval_sigterm(status);
    641 	}
    642 
    643 	printf("== validate expect set API ==\n");
    644 	ret = fork();
    645 	if (ret == 0) {
    646 		for (i=0; i<ATTR_EXP_MAX; i++) {
    647 			data[0] = (uint8_t) i;
    648 			nfexp_set_attr(exp, i, data);
    649 			val = nfexp_get_attr(exp, i);
    650 			if (val[0] != data[0]) {
    651 				printf("ERROR: set/get operations don't match "
    652 				       "for attribute %d (%x != %x)\n",
    653 					i, val[0], data[0]);
    654 			}
    655 		}
    656 		exit(0);
    657 	} else {
    658 		wait(&status);
    659 		eval_sigterm(status);
    660 	}
    661 
    662 	ret = fork();
    663 	if (ret == 0) {
    664 		test_nfexp_cmp_api(tmp_exp, exp);
    665 		exit(0);
    666 	} else {
    667 		wait(&status);
    668 		eval_sigterm(status);
    669 	}
    670 
    671 	ct2 = nfct_new();
    672 	if (!ct2) {
    673 		perror("nfct_new");
    674 		return 0;
    675 	}
    676 
    677 	printf("== test set grp API ==\n");
    678 	ret = fork();
    679 	if (ret == 0) {
    680 		for (i=0; i<ATTR_GRP_MAX; i++)
    681 			nfct_set_attr_grp(ct2, i, data);
    682 		exit(0);
    683 	} else {
    684 		wait(&status);
    685 		eval_sigterm(status);
    686 	}
    687 
    688 	for (i=0; i<ATTR_GRP_MAX; i++)
    689 		nfct_set_attr_grp(ct2, i, data);
    690 
    691 	printf("== test get grp API ==\n");
    692 	ret = fork();
    693 	if (ret == 0) {
    694 		char buf[32]; /* IPv6 group address is 16 bytes * 2 */
    695 
    696 		for (i=0; i<ATTR_GRP_MAX; i++)
    697 			nfct_get_attr_grp(ct2, i, buf);
    698 		exit(0);
    699 	} else {
    700 		wait(&status);
    701 		eval_sigterm(status);
    702 	}
    703 
    704 	printf("== validate set grp API ==\n");
    705 	ret = fork();
    706 	if (ret == 0) {
    707 		for (i=0; i<ATTR_GRP_MAX; i++) {
    708 			char buf[32]; /* IPv6 group address is 16 bytes */
    709 
    710 			data[0] = (uint8_t) i;
    711 			nfct_set_attr_grp(ct2, i, data);
    712 			nfct_get_attr_grp(ct2, i, buf);
    713 			/* These attributes cannot be set, ignore them. */
    714 			switch(i) {
    715 			case ATTR_GRP_ORIG_COUNTERS:
    716 			case ATTR_GRP_REPL_COUNTERS:
    717 			case ATTR_GRP_ORIG_ADDR_SRC:
    718 			case ATTR_GRP_ORIG_ADDR_DST:
    719 			case ATTR_GRP_REPL_ADDR_SRC:
    720 			case ATTR_GRP_REPL_ADDR_DST:
    721 				continue;
    722 			}
    723 			if (buf[0] != data[0]) {
    724 				printf("ERROR: set/get operations don't match "
    725 				       "for attribute %d (%x != %x)\n",
    726 					i, buf[0], data[0]);
    727 			}
    728 		}
    729 		exit(0);
    730 	} else {
    731 		wait(&status);
    732 		eval_sigterm(status);
    733 	}
    734 
    735 	nfct_destroy(ct2);
    736 	printf("== destroy cloned ct entry ==\n");
    737 	nfct_destroy(ct);
    738 	nfct_destroy(tmp);
    739 	nfexp_destroy(exp);
    740 	nfexp_destroy(tmp_exp);
    741 
    742 	printf("OK\n");
    743 
    744 	test_nfct_bitmask();
    745 
    746 	return EXIT_SUCCESS;
    747 }
    748