NetBSD/usr.sbin/npf/npftest/libnpftest/npf_table_test.c
2014-02-06 02:51:28 +00:00

253 lines
6.3 KiB
C

/* $NetBSD: npf_table_test.c,v 1.8 2014/02/06 02:51:28 rmind Exp $ */
/*
* NPF tableset test.
*
* Public Domain.
*/
#include <sys/types.h>
#include <sys/malloc.h>
#include "npf_impl.h"
#include "npf_test.h"
static const char *ip_list[] = {
"192.168.1.1",
"10.0.0.1",
"192.168.2.1",
"10.1.0.1",
"192.168.100.253",
"10.0.5.1",
"192.168.128.127",
"10.0.0.2",
};
static const uint16_t ip6_list[][8] = {
{
htons(0xfe80), 0x0, 0x0, 0x0,
htons(0x2a0), htons(0xc0ff), htons(0xfe10), htons(0x1234)
},
{
htons(0xfe80), 0x0, 0x0, 0x0,
htons(0x2a0), htons(0xc0ff), 0x00, 0x0
},
{
htons(0xfe80), 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0
},
{
htons(0xfe80), 0x0, 0x0, 0x0,
htons(0x2a0), htons(0xc0ff), htons(0xfe10), htons(0x1230)
}
};
#define HASH_TID "hash-table"
#define TREE_TID "tree-table"
#define CDB_TID "cdb-table"
static bool
npf_table_test_fill4(npf_tableset_t *tblset, npf_addr_t *addr)
{
const int alen = sizeof(struct in_addr);
const int nm = NPF_NO_NETMASK;
bool fail = false;
/* Fill both tables with IP addresses. */
for (unsigned i = 0; i < __arraycount(ip_list); i++) {
npf_table_t *t;
int error;
addr->s6_addr32[0] = inet_addr(ip_list[i]);
t = npf_tableset_getbyname(tblset, HASH_TID);
error = npf_table_insert(t, alen, addr, nm);
fail |= !(error == 0);
error = npf_table_insert(t, alen, addr, nm);
fail |= !(error != 0);
t = npf_tableset_getbyname(tblset, TREE_TID);
error = npf_table_insert(t, alen, addr, nm);
fail |= !(error == 0);
error = npf_table_insert(t, alen, addr, nm);
fail |= !(error != 0);
}
return fail;
}
bool
npf_table_test(bool verbose, void *blob, size_t size)
{
npf_addr_t addr_storage, *addr = &addr_storage;
const int nm = NPF_NO_NETMASK;
npf_table_t *t, *t1, *t2, *t3;
npf_tableset_t *tblset;
int error, alen;
bool fail = false;
void *cdb;
u_int i;
tblset = npf_tableset_create(3);
fail |= !(tblset != NULL);
/* Table ID 1, using hash table with 256 lists. */
t1 = npf_table_create(HASH_TID, 0, NPF_TABLE_HASH, NULL, 256);
fail |= !(t1 != NULL);
error = npf_tableset_insert(tblset, t1);
fail |= !(error == 0);
/* Check for double-insert. */
error = npf_tableset_insert(tblset, t1);
fail |= !(error != 0);
/* Table ID 2, using a prefix tree. */
t2 = npf_table_create(TREE_TID, 1, NPF_TABLE_TREE, NULL, 0);
fail |= !(t2 != NULL);
error = npf_tableset_insert(tblset, t2);
fail |= !(error == 0);
/* Table ID 3, using a CDB. */
cdb = malloc(size, M_TEMP, M_WAITOK);
memcpy(cdb, blob, size);
t3 = npf_table_create(CDB_TID, 2, NPF_TABLE_CDB, cdb, size);
fail |= !(t3 != NULL);
error = npf_tableset_insert(tblset, t3);
fail |= !(error == 0);
/* Attempt to match non-existing entries - should fail. */
addr->s6_addr32[0] = inet_addr(ip_list[0]);
alen = sizeof(struct in_addr);
t = npf_tableset_getbyname(tblset, HASH_TID);
error = npf_table_lookup(t, alen, addr);
fail |= !(error != 0);
t = npf_tableset_getbyname(tblset, TREE_TID);
error = npf_table_lookup(t, alen, addr);
fail |= !(error != 0);
/* Fill both tables with IP addresses. */
fail |= npf_table_test_fill4(tblset, addr);
/* Attempt to add duplicates - should fail. */
addr->s6_addr32[0] = inet_addr(ip_list[0]);
alen = sizeof(struct in_addr);
t = npf_tableset_getbyname(tblset, HASH_TID);
error = npf_table_insert(t, alen, addr, nm);
fail |= !(error != 0);
t = npf_tableset_getbyname(tblset, TREE_TID);
error = npf_table_insert(t, alen, addr, nm);
fail |= !(error != 0);
/* Match (validate) each IP entry. */
for (i = 0; i < __arraycount(ip_list); i++) {
addr->s6_addr32[0] = inet_addr(ip_list[i]);
t = npf_tableset_getbyname(tblset, HASH_TID);
error = npf_table_lookup(t, alen, addr);
fail |= !(error == 0);
t = npf_tableset_getbyname(tblset, TREE_TID);
error = npf_table_lookup(t, alen, addr);
fail |= !(error == 0);
}
/* IPv6 addresses. */
memcpy(addr, ip6_list[0], sizeof(ip6_list[0]));
alen = sizeof(struct in6_addr);
t = npf_tableset_getbyname(tblset, HASH_TID);
error = npf_table_insert(t, alen, addr, nm);
fail |= !(error == 0);
error = npf_table_lookup(t, alen, addr);
fail |= !(error == 0);
error = npf_table_remove(t, alen, addr, nm);
fail |= !(error == 0);
t = npf_tableset_getbyname(tblset, TREE_TID);
error = npf_table_insert(t, alen, addr, nm);
fail |= !(error == 0);
error = npf_table_lookup(t, alen, addr);
fail |= !(error == 0);
error = npf_table_remove(t, alen, addr, nm);
fail |= !(error == 0);
/*
* Masking: 96, 32, 127.
*/
memcpy(addr, ip6_list[1], sizeof(ip6_list[1]));
error = npf_table_insert(t, alen, addr, 96);
fail |= !(error == 0);
memcpy(addr, ip6_list[0], sizeof(ip6_list[0]));
error = npf_table_lookup(t, alen, addr);
fail |= !(error == 0);
memcpy(addr, ip6_list[1], sizeof(ip6_list[1]));
error = npf_table_remove(t, alen, addr, 96);
fail |= !(error == 0);
memcpy(addr, ip6_list[2], sizeof(ip6_list[2]));
error = npf_table_insert(t, alen, addr, 32);
fail |= !(error == 0);
memcpy(addr, ip6_list[0], sizeof(ip6_list[0]));
error = npf_table_lookup(t, alen, addr);
fail |= !(error == 0);
memcpy(addr, ip6_list[2], sizeof(ip6_list[2]));
error = npf_table_remove(t, alen, addr, 32);
fail |= !(error == 0);
memcpy(addr, ip6_list[3], sizeof(ip6_list[3]));
error = npf_table_insert(t, alen, addr, 126);
fail |= !(error == 0);
memcpy(addr, ip6_list[0], sizeof(ip6_list[0]));
error = npf_table_lookup(t, alen, addr);
fail |= !(error != 0);
memcpy(addr, ip6_list[3], sizeof(ip6_list[3]));
error = npf_table_remove(t, alen, addr, 126);
fail |= !(error == 0);
alen = sizeof(struct in_addr);
/* Remove all IPv4 entries. */
for (i = 0; i < __arraycount(ip_list); i++) {
addr->s6_addr32[0] = inet_addr(ip_list[i]);
t = npf_tableset_getbyname(tblset, HASH_TID);
error = npf_table_remove(t, alen, addr, nm);
fail |= !(error == 0);
t = npf_tableset_getbyname(tblset, TREE_TID);
error = npf_table_remove(t, alen, addr, nm);
fail |= !(error == 0);
}
/* Test CDB. */
addr->s6_addr32[0] = inet_addr(ip_list[0]);
alen = sizeof(struct in_addr);
error = npf_table_lookup(t3, alen, addr);
fail |= !(error == 0);
for (i = 1; i < __arraycount(ip_list) - 1; i++) {
addr->s6_addr32[0] = inet_addr(ip_list[i]);
alen = sizeof(struct in_addr);
error = npf_table_lookup(t3, alen, addr);
fail |= !(error != 0);
}
npf_tableset_destroy(tblset);
return !fail;
}