Home | History | Annotate | Line # | Download | only in libnpftest
npf_table_test.c revision 1.10
      1 /*	$NetBSD: npf_table_test.c,v 1.10 2018/09/29 14:41:36 rmind 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 	unsigned i;
    107 
    108 	(void)verbose;
    109 
    110 	tblset = npf_tableset_create(3);
    111 	fail |= !check_ok(tblset != NULL);
    112 
    113 	/* Table ID 1, using hash table with 256 lists. */
    114 	t1 = npf_table_create(HASH_TID, 0, NPF_TABLE_HASH, NULL, 256);
    115 	fail |= !check_ok(t1 != NULL);
    116 	error = npf_tableset_insert(tblset, t1);
    117 	fail |= !check_ok(error == 0);
    118 
    119 	/* Check for double-insert. */
    120 	error = npf_tableset_insert(tblset, t1);
    121 	fail |= !check_ok(error != 0);
    122 
    123 	/* Table ID 2, using a prefix tree. */
    124 	t2 = npf_table_create(TREE_TID, 1, NPF_TABLE_TREE, NULL, 0);
    125 	fail |= !(t2 != NULL);
    126 	error = npf_tableset_insert(tblset, t2);
    127 	fail |= !check_ok(error == 0);
    128 
    129 	/* Table ID 3, using a CDB. */
    130 	t3 = npf_table_create(CDB_TID, 2, NPF_TABLE_CDB, blob, size);
    131 	fail |= !(t3 != NULL);
    132 	error = npf_tableset_insert(tblset, t3);
    133 	fail |= !check_ok(error == 0);
    134 
    135 	/* Attempt to match non-existing entries - should fail. */
    136 	addr->word32[0] = inet_addr(ip_list[0]);
    137 	alen = sizeof(struct in_addr);
    138 
    139 	t = npf_tableset_getbyname(tblset, HASH_TID);
    140 	error = npf_table_lookup(t, alen, addr);
    141 	fail |= !check_ok(error != 0);
    142 
    143 	t = npf_tableset_getbyname(tblset, TREE_TID);
    144 	error = npf_table_lookup(t, alen, addr);
    145 	fail |= !check_ok(error != 0);
    146 
    147 	/* Fill both tables with IP addresses. */
    148 	fail |= npf_table_test_fill4(tblset, addr);
    149 
    150 	/* Attempt to add duplicates - should fail. */
    151 	addr->word32[0] = inet_addr(ip_list[0]);
    152 	alen = sizeof(struct in_addr);
    153 
    154 	t = npf_tableset_getbyname(tblset, HASH_TID);
    155 	error = npf_table_insert(t, alen, addr, nm);
    156 	fail |= !check_ok(error != 0);
    157 
    158 	t = npf_tableset_getbyname(tblset, TREE_TID);
    159 	error = npf_table_insert(t, alen, addr, nm);
    160 	fail |= !check_ok(error != 0);
    161 
    162 	/* Match (validate) each IP entry. */
    163 	for (i = 0; i < __arraycount(ip_list); i++) {
    164 		addr->word32[0] = inet_addr(ip_list[i]);
    165 
    166 		t = npf_tableset_getbyname(tblset, HASH_TID);
    167 		error = npf_table_lookup(t, alen, addr);
    168 		fail |= !check_ok(error == 0);
    169 
    170 		t = npf_tableset_getbyname(tblset, TREE_TID);
    171 		error = npf_table_lookup(t, alen, addr);
    172 		fail |= !check_ok(error == 0);
    173 	}
    174 
    175 	/* IPv6 addresses. */
    176 	memcpy(addr, ip6_list[0], sizeof(ip6_list[0]));
    177 	alen = sizeof(struct in6_addr);
    178 
    179 	t = npf_tableset_getbyname(tblset, HASH_TID);
    180 	error = npf_table_insert(t, alen, addr, nm);
    181 	fail |= !check_ok(error == 0);
    182 	error = npf_table_lookup(t, alen, addr);
    183 	fail |= !check_ok(error == 0);
    184 	error = npf_table_remove(t, alen, addr, nm);
    185 	fail |= !check_ok(error == 0);
    186 
    187 	t = npf_tableset_getbyname(tblset, TREE_TID);
    188 	error = npf_table_insert(t, alen, addr, nm);
    189 	fail |= !check_ok(error == 0);
    190 	error = npf_table_lookup(t, alen, addr);
    191 	fail |= !check_ok(error == 0);
    192 	error = npf_table_remove(t, alen, addr, nm);
    193 	fail |= !check_ok(error == 0);
    194 
    195 	/*
    196 	 * Masking: 96, 32, 127.
    197 	 */
    198 
    199 	memcpy(addr, ip6_list[1], sizeof(ip6_list[1]));
    200 	error = npf_table_insert(t, alen, addr, 96);
    201 	fail |= !check_ok(error == 0);
    202 
    203 	memcpy(addr, ip6_list[0], sizeof(ip6_list[0]));
    204 	error = npf_table_lookup(t, alen, addr);
    205 	fail |= !check_ok(error == 0);
    206 
    207 	memcpy(addr, ip6_list[1], sizeof(ip6_list[1]));
    208 	error = npf_table_remove(t, alen, addr, 96);
    209 	fail |= !check_ok(error == 0);
    210 
    211 
    212 	memcpy(addr, ip6_list[2], sizeof(ip6_list[2]));
    213 	error = npf_table_insert(t, alen, addr, 32);
    214 	fail |= !check_ok(error == 0);
    215 
    216 	memcpy(addr, ip6_list[0], sizeof(ip6_list[0]));
    217 	error = npf_table_lookup(t, alen, addr);
    218 	fail |= !check_ok(error == 0);
    219 
    220 	memcpy(addr, ip6_list[2], sizeof(ip6_list[2]));
    221 	error = npf_table_remove(t, alen, addr, 32);
    222 	fail |= !check_ok(error == 0);
    223 
    224 
    225 	memcpy(addr, ip6_list[3], sizeof(ip6_list[3]));
    226 	error = npf_table_insert(t, alen, addr, 126);
    227 	fail |= !check_ok(error == 0);
    228 
    229 	memcpy(addr, ip6_list[0], sizeof(ip6_list[0]));
    230 	error = npf_table_lookup(t, alen, addr);
    231 	fail |= !check_ok(error != 0);
    232 
    233 	memcpy(addr, ip6_list[3], sizeof(ip6_list[3]));
    234 	error = npf_table_remove(t, alen, addr, 126);
    235 	fail |= !check_ok(error == 0);
    236 
    237 
    238 	alen = sizeof(struct in_addr);
    239 
    240 	/* Remove all IPv4 entries. */
    241 	for (i = 0; i < __arraycount(ip_list); i++) {
    242 		addr->word32[0] = inet_addr(ip_list[i]);
    243 
    244 		t = npf_tableset_getbyname(tblset, HASH_TID);
    245 		error = npf_table_remove(t, alen, addr, nm);
    246 		fail |= !check_ok(error == 0);
    247 
    248 		t = npf_tableset_getbyname(tblset, TREE_TID);
    249 		error = npf_table_remove(t, alen, addr, nm);
    250 		fail |= !check_ok(error == 0);
    251 	}
    252 
    253 	/* Test CDB. */
    254 	addr->word32[0] = inet_addr(ip_list[0]);
    255 	alen = sizeof(struct in_addr);
    256 	error = npf_table_lookup(t3, alen, addr);
    257 	fail |= !check_ok(error == 0);
    258 
    259 	for (i = 1; i < __arraycount(ip_list) - 1; i++) {
    260 		addr->word32[0] = inet_addr(ip_list[i]);
    261 		alen = sizeof(struct in_addr);
    262 		error = npf_table_lookup(t3, alen, addr);
    263 		fail |= !check_ok(error != 0);
    264 	}
    265 
    266 	npf_tableset_destroy(tblset);
    267 
    268 	return !fail;
    269 }
    270