Line data Source code
1 : /* test_addr_range.cpp
2 : * Copyright (C) 2011-2017 Made to Order Software Corporation
3 : *
4 : * Project: http://snapwebsites.org/project/libaddr
5 : *
6 : * Permission is hereby granted, free of charge, to any
7 : * person obtaining a copy of this software and
8 : * associated documentation files (the "Software"), to
9 : * deal in the Software without restriction, including
10 : * without limitation the rights to use, copy, modify,
11 : * merge, publish, distribute, sublicense, and/or sell
12 : * copies of the Software, and to permit persons to whom
13 : * the Software is furnished to do so, subject to the
14 : * following conditions:
15 : *
16 : * The above copyright notice and this permission notice
17 : * shall be included in all copies or substantial
18 : * portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
21 : * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
22 : * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
23 : * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
24 : * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 : * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 : * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 : * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 : * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 : * SOFTWARE.
30 : */
31 :
32 : #include "test_addr_main.h"
33 : #include "libaddr/addr.h"
34 :
35 : #include <sstream>
36 : #include <fstream>
37 :
38 : #include <string.h>
39 : #include <unistd.h>
40 : #include <limits.h>
41 :
42 :
43 :
44 7 : TEST_CASE( "ipv4::range", "ipv4" )
45 : {
46 10 : GIVEN("addr_range()")
47 : {
48 6 : addr::addr_range range;
49 :
50 6 : SECTION("verify defaults")
51 : {
52 2 : addr::addr a;
53 :
54 1 : REQUIRE_FALSE(range.has_from());
55 1 : REQUIRE_FALSE(range.has_to());
56 1 : REQUIRE_FALSE(range.is_range());
57 1 : REQUIRE_FALSE(range.is_empty());
58 : //std::cerr << "++++++++++++++++++ " << a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_PORT) << "\n";
59 : //std::cerr << "++++++++++++++++++ " << range.get_from().to_ipv6_string(addr::addr::string_ip_t::STRING_IP_PORT) << "\n";
60 : //
61 : //struct sockaddr_in6 in6_a;
62 : //a.get_ipv6(in6_a);
63 : //std::cerr << "++++++++++++++++++ in6 --" << std::hex;
64 : //for(size_t idx(0); idx < sizeof(in6_a); ++idx)
65 : // std::cerr << " " << static_cast<int>(reinterpret_cast<char *>(&in6_a)[idx]);
66 : //std::cerr << "\n";
67 : //
68 : //struct sockaddr_in6 in6_b;
69 : //range.get_from().get_ipv6(in6_b);
70 : //std::cerr << "++++++++++++++++++ in6 --" << std::hex;
71 : //for(size_t idx(0); idx < sizeof(in6_b); ++idx)
72 : // std::cerr << " " << static_cast<int>(reinterpret_cast<char *>(&in6_b)[idx]);
73 : //std::cerr << "\n";
74 1 : REQUIRE(range.get_from() == a);
75 1 : REQUIRE(range.get_to() == a);
76 :
77 : // to use the const version of the get_from/to() functions
78 : // we have to define a const refence to range
79 : //
80 1 : auto const & r(range);
81 1 : REQUIRE(r.get_from() == a);
82 1 : REQUIRE(r.get_to() == a);
83 :
84 2 : addr::addr other;
85 1 : REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state_exception);
86 1 : REQUIRE_THROWS_AS(r.is_in(other), addr::addr_invalid_state_exception);
87 : }
88 :
89 6 : SECTION("test normal range (from <= to)")
90 : {
91 2 : addr::addr a;
92 2 : addr::addr other;
93 :
94 : // from is set to 10.0.0.1
95 1 : struct sockaddr_in fin = sockaddr_in();
96 1 : fin.sin_family = AF_INET;
97 1 : fin.sin_port = htons(rand());
98 : uint32_t faddress((10 << 24)
99 : | (0 << 16)
100 : | (0 << 8)
101 1 : | 1);
102 1 : fin.sin_addr.s_addr = htonl(faddress);
103 2 : addr::addr f;
104 1 : f.set_ipv4(fin);
105 :
106 : // from is set to 10.0.0.254
107 1 : struct sockaddr_in tin = sockaddr_in();
108 1 : tin.sin_family = AF_INET;
109 1 : tin.sin_port = htons(rand());
110 : uint32_t taddress((10 << 24)
111 : | (0 << 16)
112 : | (0 << 8)
113 1 : | 254);
114 1 : tin.sin_addr.s_addr = htonl(taddress);
115 2 : addr::addr t;
116 1 : t.set_ipv4(tin);
117 :
118 : // test defaults first
119 : //
120 1 : REQUIRE_FALSE(range.has_from());
121 1 : REQUIRE_FALSE(range.has_to());
122 1 : REQUIRE_FALSE(range.is_range());
123 1 : REQUIRE_FALSE(range.is_empty());
124 1 : REQUIRE(range.get_from() == a);
125 1 : REQUIRE(range.get_to() == a);
126 1 : auto const & r1(range);
127 1 : REQUIRE(r1.get_from() == a);
128 1 : REQUIRE(r1.get_to() == a);
129 1 : REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state_exception);
130 1 : REQUIRE_THROWS_AS(r1.is_in(other), addr::addr_invalid_state_exception);
131 :
132 1 : range.set_from(f);
133 :
134 : // defined "from", test the results
135 : //
136 1 : REQUIRE(range.has_from());
137 1 : REQUIRE_FALSE(range.has_to());
138 1 : REQUIRE_FALSE(range.is_range());
139 1 : REQUIRE_FALSE(range.is_empty());
140 1 : REQUIRE(range.get_from() == f);
141 1 : REQUIRE(range.get_to() == a);
142 1 : auto const & r2(range);
143 1 : REQUIRE(r2.get_from() == f);
144 1 : REQUIRE(r2.get_to() == a);
145 1 : REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state_exception);
146 1 : REQUIRE_THROWS_AS(r2.is_in(other), addr::addr_invalid_state_exception);
147 :
148 1 : range.set_to(t);
149 :
150 : // defined "to", test the results
151 : //
152 1 : REQUIRE(range.has_from());
153 1 : REQUIRE(range.has_to());
154 1 : REQUIRE(range.is_range());
155 1 : REQUIRE_FALSE(range.is_empty());
156 1 : REQUIRE(range.get_from() == f);
157 1 : REQUIRE(range.get_to() == t);
158 1 : auto const & r3(range);
159 1 : REQUIRE(r3.get_from() == f);
160 1 : REQUIRE(r3.get_to() == t);
161 :
162 : // IP before range
163 : {
164 1 : struct sockaddr_in bin = sockaddr_in();
165 1 : bin.sin_family = AF_INET;
166 1 : bin.sin_port = htons(rand());
167 : uint32_t baddress((10 << 24)
168 : | (0 << 16)
169 : | (0 << 8)
170 1 : | 0);
171 1 : bin.sin_addr.s_addr = htonl(baddress);
172 2 : addr::addr b;
173 1 : b.set_ipv4(bin);
174 :
175 1 : REQUIRE_FALSE(range.is_in(b));
176 : }
177 :
178 11 : for(int idx(0); idx < 10; ++idx)
179 : {
180 10 : struct sockaddr_in bin = sockaddr_in();
181 10 : bin.sin_family = AF_INET;
182 10 : bin.sin_port = htons(rand());
183 10 : uint32_t baddress(((rand() % 10) << 24)
184 10 : | ((rand() & 255) << 16)
185 10 : | ((rand() & 255) << 8)
186 10 : | (rand() & 255));
187 10 : bin.sin_addr.s_addr = htonl(baddress);
188 20 : addr::addr b;
189 10 : b.set_ipv4(bin);
190 :
191 10 : REQUIRE_FALSE(range.is_in(b));
192 : }
193 :
194 : // IP after range
195 : {
196 1 : struct sockaddr_in ain = sockaddr_in();
197 1 : ain.sin_family = AF_INET;
198 1 : ain.sin_port = htons(rand());
199 : uint32_t aaddress((10 << 24)
200 : | (0 << 16)
201 : | (0 << 8)
202 1 : | 255);
203 1 : ain.sin_addr.s_addr = htonl(aaddress);
204 2 : addr::addr after;
205 1 : after.set_ipv4(ain);
206 :
207 1 : REQUIRE_FALSE(range.is_in(after));
208 : }
209 :
210 11 : for(int idx(0); idx < 10; ++idx)
211 : {
212 10 : struct sockaddr_in ain = sockaddr_in();
213 10 : ain.sin_family = AF_INET;
214 10 : ain.sin_port = htons(rand());
215 10 : uint32_t aaddress(((rand() % (256 - 11) + 11) << 24)
216 10 : | ((rand() & 255) << 16)
217 10 : | ((rand() & 255) << 8)
218 10 : | (rand() & 255));
219 10 : ain.sin_addr.s_addr = htonl(aaddress);
220 20 : addr::addr after;
221 10 : after.set_ipv4(ain);
222 :
223 10 : REQUIRE_FALSE(range.is_in(after));
224 : }
225 :
226 : // IP in range
227 : //
228 255 : for(int idx(1); idx < 255; ++idx)
229 : {
230 254 : struct sockaddr_in iin = sockaddr_in();
231 254 : iin.sin_family = AF_INET;
232 254 : iin.sin_port = htons(rand());
233 : uint32_t iaddress((10 << 24)
234 : | (0 << 16)
235 : | (0 << 8)
236 254 : | idx);
237 254 : iin.sin_addr.s_addr = htonl(iaddress);
238 508 : addr::addr i;
239 254 : i.set_ipv4(iin);
240 :
241 254 : REQUIRE(range.is_in(i));
242 : }
243 : }
244 :
245 6 : SECTION("test empty range (from > to)")
246 : {
247 2 : addr::addr a;
248 2 : addr::addr other;
249 :
250 : // from is set to 10.0.0.254
251 1 : struct sockaddr_in fin = sockaddr_in();
252 1 : fin.sin_family = AF_INET;
253 1 : fin.sin_port = htons(rand());
254 : uint32_t faddress((10 << 24)
255 : | (0 << 16)
256 : | (0 << 8)
257 1 : | 254);
258 1 : fin.sin_addr.s_addr = htonl(faddress);
259 2 : addr::addr f;
260 1 : f.set_ipv4(fin);
261 :
262 : // from is set to 10.0.0.1
263 1 : struct sockaddr_in tin = sockaddr_in();
264 1 : tin.sin_family = AF_INET;
265 1 : tin.sin_port = htons(rand());
266 : uint32_t taddress((10 << 24)
267 : | (0 << 16)
268 : | (0 << 8)
269 1 : | 1);
270 1 : tin.sin_addr.s_addr = htonl(taddress);
271 2 : addr::addr t;
272 1 : t.set_ipv4(tin);
273 :
274 : // test defaults first
275 : //
276 1 : REQUIRE_FALSE(range.has_from());
277 1 : REQUIRE_FALSE(range.has_to());
278 1 : REQUIRE_FALSE(range.is_range());
279 1 : REQUIRE_FALSE(range.is_empty());
280 1 : REQUIRE(range.get_from() == a);
281 1 : REQUIRE(range.get_to() == a);
282 1 : auto const & r1(range);
283 1 : REQUIRE(r1.get_from() == a);
284 1 : REQUIRE(r1.get_to() == a);
285 1 : REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state_exception);
286 1 : REQUIRE_THROWS_AS(r1.is_in(other), addr::addr_invalid_state_exception);
287 :
288 1 : range.set_from(f);
289 :
290 : // defined "from", test the results
291 : //
292 1 : REQUIRE(range.has_from());
293 1 : REQUIRE_FALSE(range.has_to());
294 1 : REQUIRE_FALSE(range.is_range());
295 1 : REQUIRE_FALSE(range.is_empty());
296 1 : REQUIRE(range.get_from() == f);
297 1 : REQUIRE(range.get_to() == a);
298 1 : auto const & r2(range);
299 1 : REQUIRE(r2.get_from() == f);
300 1 : REQUIRE(r2.get_to() == a);
301 1 : REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state_exception);
302 1 : REQUIRE_THROWS_AS(r2.is_in(other), addr::addr_invalid_state_exception);
303 :
304 1 : range.set_to(t);
305 :
306 : // defined "to", test the results
307 : //
308 1 : REQUIRE(range.has_from());
309 1 : REQUIRE(range.has_to());
310 1 : REQUIRE(range.is_range());
311 1 : REQUIRE(range.is_empty());
312 1 : REQUIRE(range.get_from() == f);
313 1 : REQUIRE(range.get_to() == t);
314 1 : auto const & r3(range);
315 1 : REQUIRE(r3.get_from() == f);
316 1 : REQUIRE(r3.get_to() == t);
317 :
318 : // IP before range
319 : {
320 1 : struct sockaddr_in bin = sockaddr_in();
321 1 : bin.sin_family = AF_INET;
322 1 : bin.sin_port = htons(rand());
323 : uint32_t baddress((10 << 24)
324 : | (0 << 16)
325 : | (0 << 8)
326 1 : | 0);
327 1 : bin.sin_addr.s_addr = htonl(baddress);
328 2 : addr::addr b;
329 1 : b.set_ipv4(bin);
330 :
331 1 : REQUIRE_FALSE(range.is_in(b));
332 : }
333 :
334 11 : for(int idx(0); idx < 10; ++idx)
335 : {
336 10 : struct sockaddr_in bin = sockaddr_in();
337 10 : bin.sin_family = AF_INET;
338 10 : bin.sin_port = htons(rand());
339 10 : uint32_t baddress(((rand() % 10) << 24)
340 10 : | ((rand() & 255) << 16)
341 10 : | ((rand() & 255) << 8)
342 10 : | (rand() & 255));
343 10 : bin.sin_addr.s_addr = htonl(baddress);
344 20 : addr::addr b;
345 10 : b.set_ipv4(bin);
346 :
347 10 : REQUIRE_FALSE(range.is_in(b));
348 : }
349 :
350 : // IP after range
351 : {
352 1 : struct sockaddr_in ain = sockaddr_in();
353 1 : ain.sin_family = AF_INET;
354 1 : ain.sin_port = htons(rand());
355 : uint32_t aaddress((10 << 24)
356 : | (0 << 16)
357 : | (0 << 8)
358 1 : | 255);
359 1 : ain.sin_addr.s_addr = htonl(aaddress);
360 2 : addr::addr after;
361 1 : after.set_ipv4(ain);
362 :
363 1 : REQUIRE_FALSE(range.is_in(after));
364 : }
365 :
366 11 : for(int idx(0); idx < 10; ++idx)
367 : {
368 10 : struct sockaddr_in ain = sockaddr_in();
369 10 : ain.sin_family = AF_INET;
370 10 : ain.sin_port = htons(rand());
371 10 : uint32_t aaddress(((rand() % (256 - 11) + 11) << 24)
372 10 : | ((rand() & 255) << 16)
373 10 : | ((rand() & 255) << 8)
374 10 : | (rand() & 255));
375 10 : ain.sin_addr.s_addr = htonl(aaddress);
376 20 : addr::addr after;
377 10 : after.set_ipv4(ain);
378 :
379 10 : REQUIRE_FALSE(range.is_in(after));
380 : }
381 :
382 : // IP in range
383 : //
384 101 : for(int idx(0); idx < 100; ++idx)
385 : {
386 100 : struct sockaddr_in iin = sockaddr_in();
387 100 : iin.sin_family = AF_INET;
388 100 : iin.sin_port = htons(rand());
389 : uint32_t iaddress((10 << 24)
390 : | (0 << 16)
391 : | (0 << 8)
392 100 : | ((rand() & 253) + 1));
393 100 : iin.sin_addr.s_addr = htonl(iaddress);
394 200 : addr::addr i;
395 100 : i.set_ipv4(iin);
396 :
397 100 : REQUIRE_FALSE(range.is_in(i));
398 : }
399 : }
400 : }
401 :
402 10 : GIVEN("compute intersection of two ranges")
403 : {
404 4 : SECTION("two ranges that overlap")
405 : {
406 : // from is set to 10.1.0.0
407 1 : struct sockaddr_in f1in = sockaddr_in();
408 1 : f1in.sin_family = AF_INET;
409 1 : f1in.sin_port = htons(rand());
410 : uint32_t f1address((10 << 24)
411 : | (1 << 16)
412 : | (0 << 8)
413 1 : | 0);
414 1 : f1in.sin_addr.s_addr = htonl(f1address);
415 2 : addr::addr f1;
416 1 : f1.set_ipv4(f1in);
417 :
418 : // from is set to 10.5.255.255
419 1 : struct sockaddr_in t1in = sockaddr_in();
420 1 : t1in.sin_family = AF_INET;
421 1 : t1in.sin_port = htons(rand());
422 : uint32_t t1address((10 << 24)
423 : | (5 << 16)
424 : | (255 << 8)
425 1 : | 255);
426 1 : t1in.sin_addr.s_addr = htonl(t1address);
427 2 : addr::addr t1;
428 1 : t1.set_ipv4(t1in);
429 :
430 : // from is set to 10.2.0.0
431 1 : struct sockaddr_in f2in = sockaddr_in();
432 1 : f2in.sin_family = AF_INET;
433 1 : f2in.sin_port = htons(rand());
434 : uint32_t f2address((10 << 24)
435 : | (2 << 16)
436 : | (0 << 8)
437 1 : | 0);
438 1 : f2in.sin_addr.s_addr = htonl(f2address);
439 2 : addr::addr f2;
440 1 : f2.set_ipv4(f2in);
441 :
442 : // from is set to 10.10.255.255
443 1 : struct sockaddr_in t2in = sockaddr_in();
444 1 : t2in.sin_family = AF_INET;
445 1 : t2in.sin_port = htons(rand());
446 : uint32_t t2address((10 << 24)
447 : | (10 << 16)
448 : | (255 << 8)
449 1 : | 255);
450 1 : t2in.sin_addr.s_addr = htonl(t2address);
451 2 : addr::addr t2;
452 1 : t2.set_ipv4(t2in);
453 :
454 2 : addr::addr_range range1;
455 1 : range1.set_from(f1);
456 1 : range1.set_to(t1);
457 :
458 2 : addr::addr_range range2;
459 1 : range2.set_from(f2);
460 1 : range2.set_to(t2);
461 :
462 1 : REQUIRE(range1.is_range());
463 1 : REQUIRE_FALSE(range1.is_empty());
464 1 : REQUIRE(range2.is_range());
465 1 : REQUIRE_FALSE(range2.is_empty());
466 :
467 2 : addr::addr_range range3(range1.intersection(range2));
468 :
469 1 : REQUIRE(range3.is_range());
470 1 : REQUIRE_FALSE(range3.is_empty());
471 :
472 1 : REQUIRE(range3.get_from().to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.2.0.0");
473 1 : REQUIRE(range3.get_to().to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.5.255.255");
474 : }
475 :
476 4 : SECTION("two ranges that do not overlap")
477 : {
478 : // from is set to 10.1.0.0
479 1 : struct sockaddr_in f1in = sockaddr_in();
480 1 : f1in.sin_family = AF_INET;
481 1 : f1in.sin_port = htons(rand());
482 : uint32_t f1address((10 << 24)
483 : | (1 << 16)
484 : | (0 << 8)
485 1 : | 0);
486 1 : f1in.sin_addr.s_addr = htonl(f1address);
487 2 : addr::addr f1;
488 1 : f1.set_ipv4(f1in);
489 :
490 : // from is set to 10.5.255.255
491 1 : struct sockaddr_in t1in = sockaddr_in();
492 1 : t1in.sin_family = AF_INET;
493 1 : t1in.sin_port = htons(rand());
494 : uint32_t t1address((10 << 24)
495 : | (5 << 16)
496 : | (255 << 8)
497 1 : | 255);
498 1 : t1in.sin_addr.s_addr = htonl(t1address);
499 2 : addr::addr t1;
500 1 : t1.set_ipv4(t1in);
501 :
502 : // from is set to 10.10.0.0
503 1 : struct sockaddr_in f2in = sockaddr_in();
504 1 : f2in.sin_family = AF_INET;
505 1 : f2in.sin_port = htons(rand());
506 : uint32_t f2address((10 << 24)
507 : | (10 << 16)
508 : | (0 << 8)
509 1 : | 0);
510 1 : f2in.sin_addr.s_addr = htonl(f2address);
511 2 : addr::addr f2;
512 1 : f2.set_ipv4(f2in);
513 :
514 : // from is set to 10.20.255.255
515 1 : struct sockaddr_in t2in = sockaddr_in();
516 1 : t2in.sin_family = AF_INET;
517 1 : t2in.sin_port = htons(rand());
518 : uint32_t t2address((10 << 24)
519 : | (20 << 16)
520 : | (255 << 8)
521 1 : | 255);
522 1 : t2in.sin_addr.s_addr = htonl(t2address);
523 2 : addr::addr t2;
524 1 : t2.set_ipv4(t2in);
525 :
526 2 : addr::addr_range range1;
527 1 : range1.set_from(f1);
528 1 : range1.set_to(t1);
529 :
530 2 : addr::addr_range range2;
531 1 : range2.set_from(f2);
532 1 : range2.set_to(t2);
533 :
534 1 : REQUIRE(range1.is_range());
535 1 : REQUIRE_FALSE(range1.is_empty());
536 1 : REQUIRE(range2.is_range());
537 1 : REQUIRE_FALSE(range2.is_empty());
538 :
539 2 : addr::addr_range range3(range1.intersection(range2));
540 :
541 1 : REQUIRE(range3.is_range());
542 1 : REQUIRE(range3.is_empty());
543 :
544 : // although it is "empty" we know the IPs and can test them
545 : //
546 1 : REQUIRE(range3.get_from().to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.10.0.0");
547 1 : REQUIRE(range3.get_to().to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.5.255.255");
548 : }
549 : }
550 11 : }
551 :
552 :
553 :
554 :
555 :
556 : // vim: ts=4 sw=4 et
|