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 
eval_sigterm(int status)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 
test_nfct_bitmask(void)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. */
attr_is_readonly(int attr)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 
test_nfct_cmp_api_single(struct nf_conntrack * ct1,struct nf_conntrack * ct2,int attr)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 
test_cmp_attr32(int attr,bool at1,bool at2,uint32_t v1,uint32_t v2,unsigned int flags)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 
test_nfct_cmp_attr(int attr)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 
test_nfct_cmp_api(struct nf_conntrack * ct1,struct nf_conntrack * ct2)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 
test_nfexp_cmp_api(struct nf_expect * ex1,struct nf_expect * ex2)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 
main(void)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