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