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