1 /* -*- coding: utf-8 -*-
2 * ----------------------------------------------------------------------
3 * Copyright © 2009-2012, RedJack, LLC.
4 * All rights reserved.
5 *
6 * Please see the LICENSE.txt file in this distribution for license
7 * details.
8 * ----------------------------------------------------------------------
9 */
10
11 #include <stdlib.h>
12
13 #include <check.h>
14 #include <libcork/core.h>
15
16 #include "ipset/ipset.h"
17
18
19 #define IPV4_BIT_SIZE 32
20 #define IPV6_BIT_SIZE 128
21
22
23 /*-----------------------------------------------------------------------
24 * Iterators
25 */
26
START_TEST(test_iterate_empty)27 START_TEST(test_iterate_empty)
28 {
29 struct ip_set set;
30 ipset_init(&set);
31 struct ipset_iterator *it = ipset_iterate(&set, true);
32 fail_if(it == NULL,
33 "IP set iterator is NULL");
34 fail_unless(it->finished,
35 "IP set should be empty");
36 ipset_iterator_free(it);
37 ipset_done(&set);
38 }
39 END_TEST
40
41
START_TEST(test_ipv4_iterate_01)42 START_TEST(test_ipv4_iterate_01)
43 {
44 struct ip_set set;
45 ipset_init(&set);
46
47 struct cork_ip ip1;
48 cork_ip_init(&ip1, "192.168.0.1");
49
50 fail_if(ipset_ip_add(&set, &ip1),
51 "Element should not be present");
52
53 struct ipset_iterator *it = ipset_iterate(&set, true);
54 fail_if(it == NULL,
55 "IP set iterator is NULL");
56
57 fail_if(it->finished,
58 "IP set shouldn't be empty");
59 fail_unless(cork_ip_equal(&ip1, &it->addr),
60 "IP address 0 doesn't match");
61 fail_unless(it->cidr_prefix == IPV4_BIT_SIZE,
62 "IP CIDR prefix 0 doesn't match");
63
64 ipset_iterator_advance(it);
65 fail_unless(it->finished,
66 "IP set should contain 1 element");
67
68 ipset_iterator_free(it);
69
70 ipset_done(&set);
71 }
72 END_TEST
73
74
START_TEST(test_ipv4_iterate_network_01)75 START_TEST(test_ipv4_iterate_network_01)
76 {
77 struct ip_set set;
78 ipset_init(&set);
79
80 struct cork_ip ip1;
81 cork_ip_init(&ip1, "192.168.0.0");
82
83 fail_if(ipset_ip_add_network(&set, &ip1, 31),
84 "Element should not be present");
85
86 struct ipset_iterator *it = ipset_iterate_networks(&set, true);
87 fail_if(it == NULL,
88 "IP set iterator is NULL");
89
90 fail_if(it->finished,
91 "IP set shouldn't be empty");
92 fail_unless(cork_ip_equal(&ip1, &it->addr),
93 "IP address 0 doesn't match");
94 fail_unless(it->cidr_prefix == 31,
95 "IP CIDR prefix 0 doesn't match");
96
97 ipset_iterator_advance(it);
98 fail_unless(it->finished,
99 "IP set should contain 1 elements");
100
101 ipset_iterator_free(it);
102
103 ipset_done(&set);
104 }
105 END_TEST
106
107
START_TEST(test_ipv4_iterate_network_02)108 START_TEST(test_ipv4_iterate_network_02)
109 {
110 struct ip_set set;
111 ipset_init(&set);
112
113 struct cork_ip ip1;
114 cork_ip_init(&ip1, "192.168.0.0");
115
116 fail_if(ipset_ip_add_network(&set, &ip1, 16),
117 "Element should not be present");
118
119 struct ipset_iterator *it = ipset_iterate_networks(&set, true);
120 fail_if(it == NULL,
121 "IP set iterator is NULL");
122
123 fail_if(it->finished,
124 "IP set shouldn't be empty");
125 fail_unless(cork_ip_equal(&ip1, &it->addr),
126 "IP address 0 doesn't match");
127 fail_unless(it->cidr_prefix == 16,
128 "IP CIDR prefix 0 doesn't match");
129
130 ipset_iterator_advance(it);
131 fail_unless(it->finished,
132 "IP set should contain 1 elements");
133
134 ipset_iterator_free(it);
135
136 ipset_done(&set);
137 }
138 END_TEST
139
140
START_TEST(test_ipv4_iterate_network_03)141 START_TEST(test_ipv4_iterate_network_03)
142 {
143 struct ip_set set;
144 ipset_init(&set);
145
146 /*
147 * If we add all of the IP addresses in a network individually, we
148 * should still get the network as a whole from the iterator.
149 */
150
151 struct cork_ip ip1;
152 cork_ip_init(&ip1, "192.168.0.0");
153
154 struct cork_ip ip2;
155 cork_ip_init(&ip2, "192.168.0.1");
156
157 fail_if(ipset_ip_add(&set, &ip1),
158 "Element should not be present");
159
160 fail_if(ipset_ip_add(&set, &ip2),
161 "Element should not be present");
162
163 struct ipset_iterator *it = ipset_iterate_networks(&set, true);
164 fail_if(it == NULL,
165 "IP set iterator is NULL");
166
167 fail_if(it->finished,
168 "IP set shouldn't be empty");
169 fail_unless(cork_ip_equal(&ip1, &it->addr),
170 "IP address 0 doesn't match");
171 fail_unless(it->cidr_prefix == 31,
172 "IP CIDR prefix 0 doesn't match");
173
174 ipset_iterator_advance(it);
175 fail_unless(it->finished,
176 "IP set should contain 1 elements");
177
178 ipset_iterator_free(it);
179
180 ipset_done(&set);
181 }
182 END_TEST
183
184
START_TEST(test_ipv6_iterate_01)185 START_TEST(test_ipv6_iterate_01)
186 {
187 struct ip_set set;
188 ipset_init(&set);
189
190 struct cork_ip ip1;
191 cork_ip_init(&ip1, "fe80::1");
192
193 fail_if(ipset_ip_add(&set, &ip1),
194 "Element should not be present");
195
196 struct ipset_iterator *it = ipset_iterate(&set, true);
197 fail_if(it == NULL,
198 "IP set iterator is NULL");
199
200 fail_if(it->finished,
201 "IP set shouldn't be empty");
202 fail_unless(cork_ip_equal(&ip1, &it->addr),
203 "IP address 0 doesn't match");
204 fail_unless(it->cidr_prefix == IPV6_BIT_SIZE,
205 "IP CIDR prefix 0 doesn't match");
206
207 ipset_iterator_advance(it);
208 fail_unless(it->finished,
209 "IP set should contain 1 element");
210
211 ipset_iterator_free(it);
212
213 ipset_done(&set);
214 }
215 END_TEST
216
217
START_TEST(test_ipv6_iterate_network_01)218 START_TEST(test_ipv6_iterate_network_01)
219 {
220 struct ip_set set;
221 ipset_init(&set);
222
223 struct cork_ip ip1;
224 cork_ip_init(&ip1, "fe80::");
225
226 fail_if(ipset_ip_add_network(&set, &ip1, 127),
227 "Element should not be present");
228
229 struct ipset_iterator *it = ipset_iterate_networks(&set, true);
230 fail_if(it == NULL,
231 "IP set iterator is NULL");
232
233 fail_if(it->finished,
234 "IP set shouldn't be empty");
235 fail_unless(cork_ip_equal(&ip1, &it->addr),
236 "IP address 0 doesn't match");
237 fail_unless(it->cidr_prefix == 127,
238 "IP CIDR prefix 0 doesn't match (%u)", it->cidr_prefix);
239
240 ipset_iterator_advance(it);
241 fail_unless(it->finished,
242 "IP set should contain 1 element");
243
244 ipset_iterator_free(it);
245
246 ipset_done(&set);
247 }
248 END_TEST
249
250
START_TEST(test_ipv6_iterate_network_02)251 START_TEST(test_ipv6_iterate_network_02)
252 {
253 struct ip_set set;
254 ipset_init(&set);
255
256 struct cork_ip ip1;
257 cork_ip_init(&ip1, "fe80::");
258
259 fail_if(ipset_ip_add_network(&set, &ip1, 16),
260 "Element should not be present");
261
262 struct ipset_iterator *it = ipset_iterate_networks(&set, true);
263 fail_if(it == NULL,
264 "IP set iterator is NULL");
265
266 fail_if(it->finished,
267 "IP set shouldn't be empty");
268 fail_unless(cork_ip_equal(&ip1, &it->addr),
269 "IP address 0 doesn't match");
270 fail_unless(it->cidr_prefix == 16,
271 "IP CIDR prefix 0 doesn't match (%u)", it->cidr_prefix);
272
273 ipset_iterator_advance(it);
274 fail_unless(it->finished,
275 "IP set should contain 1 element");
276
277 ipset_iterator_free(it);
278
279 ipset_done(&set);
280 }
281 END_TEST
282
283
START_TEST(test_ipv6_iterate_network_03)284 START_TEST(test_ipv6_iterate_network_03)
285 {
286 struct ip_set set;
287 ipset_init(&set);
288
289 /*
290 * If we add all of the IP addresses in a network individually, we
291 * should still get the network as a whole from the iterator.
292 */
293
294 struct cork_ip ip1;
295 cork_ip_init(&ip1, "fe80::");
296
297 struct cork_ip ip2;
298 cork_ip_init(&ip2, "fe80::1");
299
300 fail_if(ipset_ip_add(&set, &ip1),
301 "Element should not be present");
302
303 fail_if(ipset_ip_add(&set, &ip2),
304 "Element should not be present");
305
306 struct ipset_iterator *it = ipset_iterate_networks(&set, true);
307 fail_if(it == NULL,
308 "IP set iterator is NULL");
309
310 fail_if(it->finished,
311 "IP set shouldn't be empty");
312 fail_unless(cork_ip_equal(&ip1, &it->addr),
313 "IP address 0 doesn't match");
314 fail_unless(it->cidr_prefix == 127,
315 "IP CIDR prefix 0 doesn't match");
316
317 ipset_iterator_advance(it);
318 fail_unless(it->finished,
319 "IP set should contain 1 elements");
320
321 ipset_iterator_free(it);
322
323 ipset_done(&set);
324 }
325 END_TEST
326
327
START_TEST(test_generic_ip_iterate_01)328 START_TEST(test_generic_ip_iterate_01)
329 {
330 struct ip_set set;
331 ipset_init(&set);
332
333 struct cork_ip ip1;
334 cork_ip_init(&ip1, "0.0.0.0");
335
336 struct cork_ip ip2;
337 cork_ip_init(&ip2, "::");
338
339 struct ipset_iterator *it = ipset_iterate_networks(&set, false);
340 fail_if(it == NULL,
341 "IP set iterator is NULL");
342
343 fail_if(it->finished,
344 "IP set shouldn't be empty");
345 fail_unless(cork_ip_equal(&ip1, &it->addr),
346 "IP address 0 doesn't match");
347 fail_unless(it->cidr_prefix == 0,
348 "IP CIDR prefix 0 doesn't match");
349
350 ipset_iterator_advance(it);
351 fail_if(it->finished,
352 "IP set should have more than 1 element");
353 fail_unless(cork_ip_equal(&ip2, &it->addr),
354 "IP address 1 doesn't match");
355 fail_unless(it->cidr_prefix == 0,
356 "IP CIDR prefix 1 doesn't match");
357
358 ipset_iterator_advance(it);
359 fail_unless(it->finished,
360 "IP set should contain 2 elements");
361
362 ipset_iterator_free(it);
363
364 ipset_done(&set);
365 }
366 END_TEST
367
368
START_TEST(test_generic_ip_iterate_02)369 START_TEST(test_generic_ip_iterate_02)
370 {
371 struct ip_set set;
372 ipset_init(&set);
373
374 /*
375 * These addresses are carefully constructed so that the same BDD
376 * variable assignments are used to store both, apart from the
377 * IPv4/v6 discriminator variable. The goal is get a BDD that has
378 * EITHER in the assignment for variable 0, but isn't simply the
379 * empty or full set.
380 */
381
382 struct cork_ip ip1;
383 cork_ip_init(&ip1, "192.168.0.1"); /* 0xc0a80001 */
384
385 struct cork_ip ip2;
386 cork_ip_init(&ip2, "c0a8:0001::");
387
388 fail_if(ipset_ip_add(&set, &ip1),
389 "Element should not be present");
390 fail_if(ipset_ip_add_network(&set, &ip2, 32),
391 "Element should not be present");
392
393 struct ipset_iterator *it = ipset_iterate_networks(&set, true);
394 fail_if(it == NULL,
395 "IP set iterator is NULL");
396
397 fail_if(it->finished,
398 "IP set shouldn't be empty");
399 fail_unless(cork_ip_equal(&ip1, &it->addr),
400 "IP address 0 doesn't match");
401 fail_unless(it->cidr_prefix == 32,
402 "IP CIDR prefix 0 doesn't match");
403
404 ipset_iterator_advance(it);
405 fail_if(it->finished,
406 "IP set should have more than 1 element");
407 fail_unless(cork_ip_equal(&ip2, &it->addr),
408 "IP address 1 doesn't match");
409 fail_unless(it->cidr_prefix == 32,
410 "IP CIDR prefix 1 doesn't match");
411
412 ipset_iterator_advance(it);
413 fail_unless(it->finished,
414 "IP set should contain 2 elements");
415
416 ipset_iterator_free(it);
417
418 ipset_done(&set);
419 }
420 END_TEST
421
422
423 /*-----------------------------------------------------------------------
424 * Testing harness
425 */
426
427 Suite *
ipset_suite()428 ipset_suite()
429 {
430 Suite *s = suite_create("ipset");
431
432 TCase *tc_iterator = tcase_create("iterator");
433 tcase_add_test(tc_iterator, test_iterate_empty);
434 tcase_add_test(tc_iterator, test_ipv4_iterate_01);
435 tcase_add_test(tc_iterator, test_ipv4_iterate_network_01);
436 tcase_add_test(tc_iterator, test_ipv4_iterate_network_02);
437 tcase_add_test(tc_iterator, test_ipv4_iterate_network_03);
438 tcase_add_test(tc_iterator, test_ipv6_iterate_01);
439 tcase_add_test(tc_iterator, test_ipv6_iterate_network_01);
440 tcase_add_test(tc_iterator, test_ipv6_iterate_network_02);
441 tcase_add_test(tc_iterator, test_ipv6_iterate_network_03);
442 tcase_add_test(tc_iterator, test_generic_ip_iterate_01);
443 tcase_add_test(tc_iterator, test_generic_ip_iterate_02);
444 suite_add_tcase(s, tc_iterator);
445
446 return s;
447 }
448
449
450 int
main(int argc,const char ** argv)451 main(int argc, const char **argv)
452 {
453 int number_failed;
454 Suite *suite = ipset_suite();
455 SRunner *runner = srunner_create(suite);
456
457 ipset_init_library();
458
459 srunner_run_all(runner, CK_NORMAL);
460 number_failed = srunner_ntests_failed(runner);
461 srunner_free(runner);
462
463 return (number_failed == 0)? EXIT_SUCCESS: EXIT_FAILURE;
464 }
465