/*
|
* 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;
|
}
|