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