blob: b96ecf7241ceba9beaeb54b911f10aaf0a899e4c [file] [log] [blame]
/*
* 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;
}