Home | History | Annotate | Line # | Download | only in libnpftest
npf_table_test.c revision 1.8.8.1
      1 /*	$NetBSD: npf_table_test.c,v 1.8.8.1 2017/01/07 08:57:00 pgoyette Exp $	*/
      2 
      3 /*
      4  * NPF tableset test.
      5  *
      6  * Public Domain.
      7  */
      8 
      9 #ifdef _KERNEL
     10 #include <sys/types.h>
     11 #include <sys/malloc.h>
     12 #endif
     13 
     14 #ifdef __linux__
     15 #include <endian.h>
     16 #else
     17 #include <sys/endian.h>
     18 #endif
     19 
     20 #include "npf_impl.h"
     21 #include "npf_test.h"
     22 
     23 static const char *ip_list[] = {
     24 	"192.168.1.1",
     25 	"10.0.0.1",
     26 	"192.168.2.1",
     27 	"10.1.0.1",
     28 	"192.168.100.253",
     29 	"10.0.5.1",
     30 	"192.168.128.127",
     31 	"10.0.0.2",
     32 };
     33 
     34 #if __BYTE_ORDER == __LITTLE_ENDIAN
     35 #define	U16_TO_LE(x)	((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
     36 #else
     37 #define	U16_TO_LE(x)	(x)
     38 #endif
     39 
     40 static const uint16_t ip6_list[][8] = {
     41 	{
     42 	    U16_TO_LE(0xfe80), 0x0, 0x0, 0x0,
     43 	    U16_TO_LE(0x2a0), U16_TO_LE(0xc0ff),
     44 	    U16_TO_LE(0xfe10), U16_TO_LE(0x1234)
     45 	},
     46 	{
     47 	    U16_TO_LE(0xfe80), 0x0, 0x0, 0x0,
     48 	    U16_TO_LE(0x2a0), U16_TO_LE(0xc0ff), 0x00, 0x0
     49 	},
     50 	{
     51 	    U16_TO_LE(0xfe80), 0x0, 0x0, 0x0,
     52 	    0x0, 0x0, 0x0, 0x0
     53 	},
     54 	{
     55 	    U16_TO_LE(0xfe80), 0x0, 0x0, 0x0,
     56 	    U16_TO_LE(0x2a0), U16_TO_LE(0xc0ff),
     57 	    U16_TO_LE(0xfe10), U16_TO_LE(0x1230)
     58 	}
     59 };
     60 
     61 #define	check_ok(x)	\
     62     ((x) ? true : (printf("fail at line %d\n", __LINE__), false))
     63 
     64 #define	HASH_TID		"hash-table"
     65 #define	TREE_TID		"tree-table"
     66 #define	CDB_TID			"cdb-table"
     67 
     68 static bool
     69 npf_table_test_fill4(npf_tableset_t *tblset, npf_addr_t *addr)
     70 {
     71 	const int alen = sizeof(struct in_addr);
     72 	const int nm = NPF_NO_NETMASK;
     73 	bool fail = false;
     74 
     75 	/* Fill both tables with IP addresses. */
     76 	for (unsigned i = 0; i < __arraycount(ip_list); i++) {
     77 		npf_table_t *t;
     78 		int error;
     79 
     80 		addr->word32[0] = inet_addr(ip_list[i]);
     81 
     82 		t = npf_tableset_getbyname(tblset, HASH_TID);
     83 		error = npf_table_insert(t, alen, addr, nm);
     84 		fail |= !check_ok(error == 0);
     85 		error = npf_table_insert(t, alen, addr, nm);
     86 		fail |= !check_ok(error != 0);
     87 
     88 		t = npf_tableset_getbyname(tblset, TREE_TID);
     89 		error = npf_table_insert(t, alen, addr, nm);
     90 		fail |= !check_ok(error == 0);
     91 		error = npf_table_insert(t, alen, addr, nm);
     92 		fail |= !check_ok(error != 0);
     93 	}
     94 	return fail;
     95 }
     96 
     97 bool
     98 npf_table_test(bool verbose, void *blob, size_t size)
     99 {
    100 	npf_addr_t addr_storage, *addr = &addr_storage;
    101 	const int nm = NPF_NO_NETMASK;
    102 	npf_table_t *t, *t1, *t2, *t3;
    103 	npf_tableset_t *tblset;
    104 	int error, alen;
    105 	bool fail = false;
    106 	void *cdb;
    107 	u_int i;
    108 
    109 	tblset = npf_tableset_create(3);
    110 	fail |= !check_ok(tblset != NULL);
    111 
    112 	/* Table ID 1, using hash table with 256 lists. */
    113 	t1 = npf_table_create(HASH_TID, 0, NPF_TABLE_HASH, NULL, 256);
    114 	fail |= !check_ok(t1 != NULL);
    115 	error = npf_tableset_insert(tblset, t1);
    116 	fail |= !check_ok(error == 0);
    117 
    118 	/* Check for double-insert. */
    119 	error = npf_tableset_insert(tblset, t1);
    120 	fail |= !check_ok(error != 0);
    121 
    122 	/* Table ID 2, using a prefix tree. */
    123 	t2 = npf_table_create(TREE_TID, 1, NPF_TABLE_TREE, NULL, 0);
    124 	fail |= !(t2 != NULL);
    125 	error = npf_tableset_insert(tblset, t2);
    126 	fail |= !check_ok(error == 0);
    127 
    128 	/* Table ID 3, using a CDB. */
    129 	cdb = malloc(size, M_TEMP, M_WAITOK);
    130 	memcpy(cdb, blob, size);
    131 
    132 	t3 = npf_table_create(CDB_TID, 2, NPF_TABLE_CDB, cdb, size);
    133 	fail |= !(t3 != NULL);
    134 	error = npf_tableset_insert(tblset, t3);
    135 	fail |= !check_ok(error == 0);
    136 
    137 	/* Attempt to match non-existing entries - should fail. */
    138 	addr->word32[0] = inet_addr(ip_list[0]);
    139 	alen = sizeof(struct in_addr);
    140 
    141 	t = npf_tableset_getbyname(tblset, HASH_TID);
    142 	error = npf_table_lookup(t, alen, addr);
    143 	fail |= !check_ok(error != 0);
    144 
    145 	t = npf_tableset_getbyname(tblset, TREE_TID);
    146 	error = npf_table_lookup(t, alen, addr);
    147 	fail |= !check_ok(error != 0);
    148 
    149 	/* Fill both tables with IP addresses. */
    150 	fail |= npf_table_test_fill4(tblset, addr);
    151 
    152 	/* Attempt to add duplicates - should fail. */
    153 	addr->word32[0] = inet_addr(ip_list[0]);
    154 	alen = sizeof(struct in_addr);
    155 
    156 	t = npf_tableset_getbyname(tblset, HASH_TID);
    157 	error = npf_table_insert(t, alen, addr, nm);
    158 	fail |= !check_ok(error != 0);
    159 
    160 	t = npf_tableset_getbyname(tblset, TREE_TID);
    161 	error = npf_table_insert(t, alen, addr, nm);
    162 	fail |= !check_ok(error != 0);
    163 
    164 	/* Match (validate) each IP entry. */
    165 	for (i = 0; i < __arraycount(ip_list); i++) {
    166 		addr->word32[0] = inet_addr(ip_list[i]);
    167 
    168 		t = npf_tableset_getbyname(tblset, HASH_TID);
    169 		error = npf_table_lookup(t, alen, addr);
    170 		fail |= !check_ok(error == 0);
    171 
    172 		t = npf_tableset_getbyname(tblset, TREE_TID);
    173 		error = npf_table_lookup(t, alen, addr);
    174 		fail |= !check_ok(error == 0);
    175 	}
    176 
    177 	/* IPv6 addresses. */
    178 	memcpy(addr, ip6_list[0], sizeof(ip6_list[0]));
    179 	alen = sizeof(struct in6_addr);
    180 
    181 	t = npf_tableset_getbyname(tblset, HASH_TID);
    182 	error = npf_table_insert(t, alen, addr, nm);
    183 	fail |= !check_ok(error == 0);
    184 	error = npf_table_lookup(t, alen, addr);
    185 	fail |= !check_ok(error == 0);
    186 	error = npf_table_remove(t, alen, addr, nm);
    187 	fail |= !check_ok(error == 0);
    188 
    189 	t = npf_tableset_getbyname(tblset, TREE_TID);
    190 	error = npf_table_insert(t, alen, addr, nm);
    191 	fail |= !check_ok(error == 0);
    192 	error = npf_table_lookup(t, alen, addr);
    193 	fail |= !check_ok(error == 0);
    194 	error = npf_table_remove(t, alen, addr, nm);
    195 	fail |= !check_ok(error == 0);
    196 
    197 	/*
    198 	 * Masking: 96, 32, 127.
    199 	 */
    200 
    201 	memcpy(addr, ip6_list[1], sizeof(ip6_list[1]));
    202 	error = npf_table_insert(t, alen, addr, 96);
    203 	fail |= !check_ok(error == 0);
    204 
    205 	memcpy(addr, ip6_list[0], sizeof(ip6_list[0]));
    206 	error = npf_table_lookup(t, alen, addr);
    207 	fail |= !check_ok(error == 0);
    208 
    209 	memcpy(addr, ip6_list[1], sizeof(ip6_list[1]));
    210 	error = npf_table_remove(t, alen, addr, 96);
    211 	fail |= !check_ok(error == 0);
    212 
    213 
    214 	memcpy(addr, ip6_list[2], sizeof(ip6_list[2]));
    215 	error = npf_table_insert(t, alen, addr, 32);
    216 	fail |= !check_ok(error == 0);
    217 
    218 	memcpy(addr, ip6_list[0], sizeof(ip6_list[0]));
    219 	error = npf_table_lookup(t, alen, addr);
    220 	fail |= !check_ok(error == 0);
    221 
    222 	memcpy(addr, ip6_list[2], sizeof(ip6_list[2]));
    223 	error = npf_table_remove(t, alen, addr, 32);
    224 	fail |= !check_ok(error == 0);
    225 
    226 
    227 	memcpy(addr, ip6_list[3], sizeof(ip6_list[3]));
    228 	error = npf_table_insert(t, alen, addr, 126);
    229 	fail |= !check_ok(error == 0);
    230 
    231 	memcpy(addr, ip6_list[0], sizeof(ip6_list[0]));
    232 	error = npf_table_lookup(t, alen, addr);
    233 	fail |= !check_ok(error != 0);
    234 
    235 	memcpy(addr, ip6_list[3], sizeof(ip6_list[3]));
    236 	error = npf_table_remove(t, alen, addr, 126);
    237 	fail |= !check_ok(error == 0);
    238 
    239 
    240 	alen = sizeof(struct in_addr);
    241 
    242 	/* Remove all IPv4 entries. */
    243 	for (i = 0; i < __arraycount(ip_list); i++) {
    244 		addr->word32[0] = inet_addr(ip_list[i]);
    245 
    246 		t = npf_tableset_getbyname(tblset, HASH_TID);
    247 		error = npf_table_remove(t, alen, addr, nm);
    248 		fail |= !check_ok(error == 0);
    249 
    250 		t = npf_tableset_getbyname(tblset, TREE_TID);
    251 		error = npf_table_remove(t, alen, addr, nm);
    252 		fail |= !check_ok(error == 0);
    253 	}
    254 
    255 	/* Test CDB. */
    256 	addr->word32[0] = inet_addr(ip_list[0]);
    257 	alen = sizeof(struct in_addr);
    258 	error = npf_table_lookup(t3, alen, addr);
    259 	fail |= !check_ok(error == 0);
    260 
    261 	for (i = 1; i < __arraycount(ip_list) - 1; i++) {
    262 		addr->word32[0] = inet_addr(ip_list[i]);
    263 		alen = sizeof(struct in_addr);
    264 		error = npf_table_lookup(t3, alen, addr);
    265 		fail |= !check_ok(error != 0);
    266 	}
    267 
    268 	npf_tableset_destroy(tblset);
    269 
    270 	return !fail;
    271 }
    272