| /* |
| * Run this after adding a new attribute to the nf_conntrack object |
| */ |
| |
| #include <assert.h> |
| #include <stdio.h> |
| #include <stdbool.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <sys/wait.h> |
| #include <time.h> |
| #include <errno.h> |
| |
| #include <libnetfilter_conntrack/libnetfilter_conntrack.h> |
| |
| /* |
| * this file contains a test to check the set/get/copy/cmp APIs. |
| */ |
| |
| static void eval_sigterm(int status) |
| { |
| switch(WTERMSIG(status)) { |
| case SIGSEGV: |
| printf("received SIGSEV\n"); |
| break; |
| case 0: |
| printf("OK\n"); |
| break; |
| default: |
| printf("exited with signal: %d\n", WTERMSIG(status)); |
| break; |
| } |
| } |
| |
| 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"); |
| |
| maxb = rand() & 0xffff; |
| |
| a = nfct_bitmask_new(maxb); |
| |
| assert(!nfct_bitmask_test_bit(a, maxb + 32)); |
| nfct_bitmask_set_bit(a, maxb + 32); |
| assert(!nfct_bitmask_test_bit(a, maxb + 32)); |
| |
| for (i = 0; i <= maxb; i++) |
| assert(!nfct_bitmask_test_bit(a, i)); |
| |
| for (i = 0; i <= maxb; i++) { |
| if (rand() & 1) { |
| assert(!nfct_bitmask_test_bit(a, i)); |
| continue; |
| } |
| nfct_bitmask_set_bit(a, i); |
| assert(nfct_bitmask_test_bit(a, i)); |
| } |
| |
| b = nfct_bitmask_clone(a); |
| assert(b); |
| |
| for (i = 0; i <= maxb; i++) { |
| if (nfct_bitmask_test_bit(a, i)) |
| assert(nfct_bitmask_test_bit(b, i)); |
| else |
| assert(!nfct_bitmask_test_bit(b, i)); |
| } |
| |
| nfct_bitmask_destroy(a); |
| |
| for (i = 0; i <= maxb; i++) { |
| if (rand() & 1) |
| continue; |
| nfct_bitmask_unset_bit(b, i); |
| assert(!nfct_bitmask_test_bit(b, i)); |
| } |
| |
| /* nfct_bitmask_clear() */ |
| for (i = 0; i < maxb; i++) { |
| nfct_bitmask_set_bit(b, i); |
| assert(nfct_bitmask_test_bit(b, i)); |
| nfct_bitmask_clear(b); |
| assert(!nfct_bitmask_test_bit(b, i)); |
| } |
| |
| for (i = 0; i < maxb; i++) |
| nfct_bitmask_set_bit(b, i); |
| nfct_bitmask_clear(b); |
| for (i = 0; i < maxb; i++) |
| assert(!nfct_bitmask_test_bit(b, i)); |
| |
| /* nfct_bitmask_equal() */ |
| for (i = 0; i < maxb / 32 * 32; i += 32) { |
| a = nfct_bitmask_new(i); |
| assert(!nfct_bitmask_equal(a, b)); |
| nfct_bitmask_destroy(a); |
| } |
| |
| a = nfct_bitmask_clone(b); |
| assert(nfct_bitmask_equal(a, b)); |
| for (i = 0; i < maxb; i++) { |
| if (nfct_bitmask_test_bit(a, i)) { |
| nfct_bitmask_unset_bit(a, i); |
| assert(!nfct_bitmask_equal(a, b)); |
| nfct_bitmask_set_bit(a, i); |
| } else { |
| nfct_bitmask_set_bit(a, i); |
| assert(!nfct_bitmask_equal(a, b)); |
| nfct_bitmask_unset_bit(a, i); |
| } |
| assert(nfct_bitmask_equal(a, b)); |
| } |
| |
| nfct_bitmask_destroy(a); |
| 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_IPV6: |
| case ATTR_DNAT_IPV6: |
| 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 int test_cmp_attr32(int attr, bool at1, bool at2, |
| uint32_t v1, uint32_t v2, unsigned int flags) |
| { |
| struct nf_conntrack *ct1 = nfct_new(); |
| struct nf_conntrack *ct2 = nfct_new(); |
| int ret; |
| |
| if (at1) |
| nfct_set_attr_u32(ct1, attr, v1); |
| if (at2) |
| nfct_set_attr_u32(ct2, attr, v2); |
| |
| ret = nfct_cmp(ct1, ct2, NFCT_CMP_ALL | flags); |
| |
| nfct_destroy(ct1); |
| nfct_destroy(ct2); |
| |
| return ret; |
| } |
| |
| static void test_nfct_cmp_attr(int attr) |
| { |
| unsigned int flags = 0; |
| |
| /* 0000, 1000, 1100, 0010, 1010... */ |
| /* attr at1 at2 v1 v2 */ |
| assert(test_cmp_attr32(attr, false, false, 0, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, true, false, 0, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, false, true, 0, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, true, true, 0, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, false, false, 1, 0, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, false, 1, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, false, true, 1, 0, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, true, 1, 0, flags) == 0); |
| assert(test_cmp_attr32(attr, false, false, 0, 1, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, false, 0, 1, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, false, true, 0, 1, flags) == 1); |
| assert(test_cmp_attr32(attr, true, true, 0, 1, flags) == 0); |
| assert(test_cmp_attr32(attr, false, false, 1, 1, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, false, 1, 1, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, false, true, 1, 1, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, true, 1, 1, flags) == 1); |
| |
| flags = NFCT_CMP_STRICT; |
| assert(test_cmp_attr32(attr, false, false, 0, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, true, false, 0, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, false, true, 0, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, true, true, 0, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, false, false, 1, 0, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, false, 1, 0, flags) == 0); |
| assert(test_cmp_attr32(attr, false, true, 1, 0, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, true, 1, 0, flags) == 0); |
| assert(test_cmp_attr32(attr, false, false, 0, 1, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, false, 0, 1, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, false, true, 0, 1, flags) == 0); |
| assert(test_cmp_attr32(attr, true, true, 0, 1, flags) == 0); |
| assert(test_cmp_attr32(attr, false, false, 1, 1, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, false, 1, 1, flags) == 0); /* verbose */ |
| assert(test_cmp_attr32(attr, false, true, 1, 1, flags) == 0); /* verbose */ |
| assert(test_cmp_attr32(attr, true, true, 1, 1, flags) == 1); |
| |
| flags = NFCT_CMP_MASK; |
| assert(test_cmp_attr32(attr, false, false, 0, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, true, false, 0, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, false, true, 0, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, true, true, 0, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, false, false, 1, 0, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, false, 1, 0, flags) == 0); |
| assert(test_cmp_attr32(attr, false, true, 1, 0, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, true, 1, 0, flags) == 0); |
| assert(test_cmp_attr32(attr, false, false, 0, 1, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, false, 0, 1, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, false, true, 0, 1, flags) == 1); |
| assert(test_cmp_attr32(attr, true, true, 0, 1, flags) == 0); |
| assert(test_cmp_attr32(attr, false, false, 1, 1, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, false, 1, 1, flags) == 0); /* verbose */ |
| assert(test_cmp_attr32(attr, false, true, 1, 1, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, true, 1, 1, flags) == 1); |
| |
| flags = NFCT_CMP_STRICT|NFCT_CMP_MASK; |
| assert(test_cmp_attr32(attr, false, false, 0, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, true, false, 0, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, false, true, 0, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, true, true, 0, 0, flags) == 1); |
| assert(test_cmp_attr32(attr, false, false, 1, 0, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, false, 1, 0, flags) == 0); |
| assert(test_cmp_attr32(attr, false, true, 1, 0, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, true, 1, 0, flags) == 0); |
| assert(test_cmp_attr32(attr, false, false, 0, 1, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, false, 0, 1, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, false, true, 0, 1, flags) == 0); |
| assert(test_cmp_attr32(attr, true, true, 0, 1, flags) == 0); |
| assert(test_cmp_attr32(attr, false, false, 1, 1, flags) == 1); /* verbose */ |
| assert(test_cmp_attr32(attr, true, false, 1, 1, flags) == 0); /* verbose */ |
| assert(test_cmp_attr32(attr, false, true, 1, 1, flags) == 0); /* verbose */ |
| assert(test_cmp_attr32(attr, true, true, 1, 1, flags) == 1); |
| } |
| |
| static void test_nfct_cmp_api(struct nf_conntrack *ct1, struct nf_conntrack *ct2) |
| { |
| int i; |
| |
| printf("== test cmp API ==\n"); |
| |
| test_nfct_cmp_attr(ATTR_ZONE); |
| test_nfct_cmp_attr(ATTR_ORIG_ZONE); |
| test_nfct_cmp_attr(ATTR_REPL_ZONE); |
| test_nfct_cmp_attr(ATTR_MARK); |
| |
| assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1); |
| assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_STRICT) == 0); |
| |
| nfct_copy(ct1, ct2, NFCT_CP_OVERRIDE); |
| |
| assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1); |
| assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_STRICT) == 1); |
| |
| for (i=0; i < ATTR_MAX ; i++) { |
| nfct_attr_unset(ct1, i); |
| |
| assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1); |
| assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_STRICT) == 0); |
| assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_MASK) == 1); |
| } |
| nfct_copy(ct1, ct2, NFCT_CP_OVERRIDE); |
| for (i=0; i < ATTR_MAX ; i++) { |
| nfct_attr_unset(ct2, i); |
| |
| assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1); |
| 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); |
| nfct_attr_unset(ct2, i); |
| |
| assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1); |
| assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_STRICT) == 1); |
| assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_MASK) == 1); |
| } |
| nfct_destroy(ct1); |
| nfct_destroy(ct2); |
| } |
| |
| static void test_nfexp_cmp_api(struct nf_expect *ex1, struct nf_expect *ex2) |
| { |
| int i; |
| |
| printf("== test expect cmp API ==\n"); |
| |
| /* XXX: missing nfexp_copy API. */ |
| memcpy(ex1, ex2, nfexp_maxsize()); |
| |
| assert(nfexp_cmp(ex1, ex2, 0) == 1); |
| assert(nfexp_cmp(ex1, ex2, NFCT_CMP_STRICT) == 1); |
| |
| assert(nfexp_attr_is_set(ex1, 0) == 1); |
| nfexp_attr_unset(ex1, 0); |
| assert(nfexp_attr_is_set(ex1, 0) == 0); |
| |
| memcpy(ex1, ex2, nfexp_maxsize()); |
| for (i=0; i < ATTR_EXP_MAX; i++) { |
| nfexp_attr_unset(ex1, i); |
| |
| assert(nfexp_cmp(ex1, ex2, 0) == 1); |
| assert(nfexp_cmp(ex1, ex2, NFCT_CMP_STRICT) == 0); |
| assert(nfexp_cmp(ex1, ex2, NFCT_CMP_MASK) == 1); |
| } |
| memcpy(ex1, ex2, nfexp_maxsize()); |
| for (i=0; i < ATTR_EXP_MAX; i++) { |
| nfexp_attr_unset(ex2, i); |
| |
| assert(nfexp_cmp(ex1, ex2, 0) == 1); |
| assert(nfexp_cmp(ex1, ex2, NFCT_CMP_MASK) == 0); |
| } |
| memcpy(ex1, ex2, nfexp_maxsize()); |
| for (i=0; i < ATTR_EXP_MAX; i++) { |
| nfexp_attr_unset(ex1, i); |
| nfexp_attr_unset(ex2, i); |
| |
| assert(nfexp_cmp(ex1, ex2, 0) == 1); |
| assert(nfexp_cmp(ex1, ex2, NFCT_CMP_STRICT) == 1); |
| assert(nfexp_cmp(ex1, ex2, NFCT_CMP_MASK) == 1); |
| } |
| nfexp_destroy(ex1); |
| nfexp_destroy(ex2); |
| } |
| |
| int main(void) |
| { |
| int ret, i; |
| struct nf_conntrack *ct, *ct2, *tmp; |
| struct nf_expect *exp, *tmp_exp; |
| char data[256]; |
| const char *val; |
| int status; |
| struct nfct_bitmask *b, *b2; |
| |
| srand(time(NULL)); |
| |
| /* initialize fake data for testing purposes */ |
| for (i=0; i<sizeof(data); i++) |
| data[i] = 0x01; |
| |
| ct = nfct_new(); |
| if (!ct) { |
| perror("nfct_new"); |
| return 0; |
| } |
| tmp = nfct_new(); |
| if (!tmp) { |
| perror("nfct_new"); |
| return 0; |
| } |
| |
| printf("== test set API ==\n"); |
| ret = fork(); |
| if (ret == 0) { |
| for (i=0; i<ATTR_MAX; i++) |
| nfct_set_attr(ct, i, data); |
| exit(0); |
| } else { |
| wait(&status); |
| 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++) { |
| 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); |
| break; |
| } |
| } |
| |
| printf("== test get API ==\n"); |
| ret = fork(); |
| if (ret == 0) { |
| for (i=0; i<ATTR_MAX; i++) |
| nfct_get_attr(ct, i); |
| exit(0); |
| } else { |
| wait(&status); |
| eval_sigterm(status); |
| } |
| |
| printf("== validate set API ==\n"); |
| ret = fork(); |
| if (ret == 0) { |
| for (i=0; i<ATTR_MAX; i++) { |
| 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)); |
| break; |
| case ATTR_CONNLABELS: |
| case ATTR_CONNLABELS_MASK: |
| /* already set above */ |
| break; |
| default: |
| data[0] = (uint8_t) i; |
| nfct_set_attr(ct, i, data); |
| } |
| val = nfct_get_attr(ct, i); |
| switch (i) { |
| case ATTR_CONNLABELS: |
| assert((void *) val == b); |
| continue; |
| case ATTR_CONNLABELS_MASK: |
| assert((void *) val == b2); |
| continue; |
| } |
| |
| if (val[0] != data[0]) { |
| printf("ERROR: set/get operations don't match " |
| "for attribute %d (%x != %x)\n", |
| i, val[0], data[0]); |
| } |
| } |
| exit(0); |
| } else { |
| wait(&status); |
| eval_sigterm(status); |
| } |
| |
| printf("== test copy API ==\n"); |
| ret = fork(); |
| if (ret == 0) { |
| for (i=0; i<ATTR_MAX; i++) |
| nfct_copy_attr(tmp, ct, i); |
| exit(0); |
| } else { |
| wait(&status); |
| eval_sigterm(status); |
| } |
| |
| ret = fork(); |
| if (ret == 0) { |
| test_nfct_cmp_api(tmp, ct); |
| exit(0); |
| } else { |
| wait(&status); |
| eval_sigterm(status); |
| } |
| |
| exp = nfexp_new(); |
| if (!exp) { |
| perror("nfexp_new"); |
| return 0; |
| } |
| tmp_exp = nfexp_new(); |
| if (!tmp_exp) { |
| perror("nfexp_new"); |
| return 0; |
| } |
| |
| printf("== test expect set API ==\n"); |
| ret = fork(); |
| if (ret == 0) { |
| for (i=0; i<ATTR_EXP_MAX; i++) |
| nfexp_set_attr(exp, i, data); |
| exit(0); |
| } else { |
| wait(&status); |
| eval_sigterm(status); |
| } |
| |
| for (i=0; i<ATTR_EXP_MAX; i++) |
| nfexp_set_attr(exp, i, data); |
| |
| printf("== test expect get API ==\n"); |
| ret = fork(); |
| if (ret == 0) { |
| for (i=0; i<ATTR_EXP_MAX; i++) |
| nfexp_get_attr(exp, i); |
| exit(0); |
| } else { |
| wait(&status); |
| eval_sigterm(status); |
| } |
| |
| printf("== validate expect set API ==\n"); |
| ret = fork(); |
| if (ret == 0) { |
| for (i=0; i<ATTR_EXP_MAX; i++) { |
| data[0] = (uint8_t) i; |
| nfexp_set_attr(exp, i, data); |
| val = nfexp_get_attr(exp, i); |
| if (val[0] != data[0]) { |
| printf("ERROR: set/get operations don't match " |
| "for attribute %d (%x != %x)\n", |
| i, val[0], data[0]); |
| } |
| } |
| exit(0); |
| } else { |
| wait(&status); |
| eval_sigterm(status); |
| } |
| |
| ret = fork(); |
| if (ret == 0) { |
| test_nfexp_cmp_api(tmp_exp, exp); |
| exit(0); |
| } else { |
| wait(&status); |
| eval_sigterm(status); |
| } |
| |
| ct2 = nfct_new(); |
| if (!ct2) { |
| perror("nfct_new"); |
| return 0; |
| } |
| |
| printf("== test set grp API ==\n"); |
| ret = fork(); |
| if (ret == 0) { |
| for (i=0; i<ATTR_GRP_MAX; i++) |
| nfct_set_attr_grp(ct2, i, data); |
| exit(0); |
| } else { |
| wait(&status); |
| eval_sigterm(status); |
| } |
| |
| for (i=0; i<ATTR_GRP_MAX; i++) |
| nfct_set_attr_grp(ct2, i, data); |
| |
| printf("== test get grp API ==\n"); |
| ret = fork(); |
| if (ret == 0) { |
| char buf[32]; /* IPv6 group address is 16 bytes * 2 */ |
| |
| for (i=0; i<ATTR_GRP_MAX; i++) |
| nfct_get_attr_grp(ct2, i, buf); |
| exit(0); |
| } else { |
| wait(&status); |
| eval_sigterm(status); |
| } |
| |
| printf("== validate set grp API ==\n"); |
| ret = fork(); |
| if (ret == 0) { |
| for (i=0; i<ATTR_GRP_MAX; i++) { |
| char buf[32]; /* IPv6 group address is 16 bytes */ |
| |
| data[0] = (uint8_t) i; |
| nfct_set_attr_grp(ct2, i, data); |
| nfct_get_attr_grp(ct2, i, buf); |
| /* These attributes cannot be set, ignore them. */ |
| switch(i) { |
| case ATTR_GRP_ORIG_COUNTERS: |
| case ATTR_GRP_REPL_COUNTERS: |
| case ATTR_GRP_ORIG_ADDR_SRC: |
| case ATTR_GRP_ORIG_ADDR_DST: |
| case ATTR_GRP_REPL_ADDR_SRC: |
| case ATTR_GRP_REPL_ADDR_DST: |
| continue; |
| } |
| if (buf[0] != data[0]) { |
| printf("ERROR: set/get operations don't match " |
| "for attribute %d (%x != %x)\n", |
| i, buf[0], data[0]); |
| } |
| } |
| exit(0); |
| } else { |
| wait(&status); |
| eval_sigterm(status); |
| } |
| |
| nfct_destroy(ct2); |
| printf("== destroy cloned ct entry ==\n"); |
| nfct_destroy(ct); |
| nfct_destroy(tmp); |
| nfexp_destroy(exp); |
| nfexp_destroy(tmp_exp); |
| |
| printf("OK\n"); |
| |
| test_nfct_bitmask(); |
| |
| return EXIT_SUCCESS; |
| } |