Line data Source code
1 : // Copyright (c) 2011-2022 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/libaddr
4 : // contact@m2osw.com
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 : /** \file
33 : * \brief Check the addr_range class basics.
34 : *
35 : * This set of unit tests do basic verification of the range class.
36 : *
37 : * The point here is to test the range functionality and not the
38 : * addr_parser class.
39 : */
40 :
41 :
42 : // self
43 : //
44 : #include "catch_main.h"
45 :
46 :
47 : // snapdev
48 : //
49 : #include <snapdev/int128_literal.h>
50 : #include <snapdev/ostream_int128.h>
51 :
52 :
53 : // last include
54 : //
55 : #include <snapdev/poison.h>
56 :
57 :
58 : using namespace snapdev::literals;
59 :
60 :
61 :
62 16 : CATCH_TEST_CASE("ipv4::range", "[ipv4]")
63 : {
64 28 : CATCH_GIVEN("addr_range()")
65 : {
66 18 : addr::addr_range range;
67 :
68 18 : CATCH_START_SECTION("addr_range: verify defaults")
69 : {
70 2 : addr::addr a;
71 :
72 1 : CATCH_REQUIRE_FALSE(range.has_from());
73 1 : CATCH_REQUIRE_FALSE(range.has_to());
74 1 : CATCH_REQUIRE_FALSE(range.is_range());
75 1 : CATCH_REQUIRE_FALSE(range.is_empty());
76 1 : CATCH_REQUIRE(range.get_from() == a);
77 1 : CATCH_REQUIRE(range.get_to() == a);
78 :
79 : // to use the const version of the get_from/to() functions
80 : // we have to define a const refence to range
81 : //
82 1 : auto const & r(range);
83 1 : CATCH_REQUIRE(r.get_from() == a);
84 1 : CATCH_REQUIRE(r.get_to() == a);
85 :
86 2 : addr::addr other;
87 1 : CATCH_REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state);
88 1 : CATCH_REQUIRE_THROWS_AS(r.is_in(other), addr::addr_invalid_state);
89 : }
90 : CATCH_END_SECTION()
91 :
92 18 : CATCH_START_SECTION("addr_range: test normal range (from <= to)")
93 : {
94 2 : addr::addr a;
95 2 : addr::addr other;
96 :
97 : // from 10.0.0.1
98 1 : struct sockaddr_in fin = sockaddr_in();
99 1 : fin.sin_family = AF_INET;
100 1 : int const fport(rand() & 0xFFFF);
101 1 : fin.sin_port = htons(fport);
102 1 : uint32_t const faddress((10 << 24)
103 : | (0 << 16)
104 : | (0 << 8)
105 : | 1);
106 1 : fin.sin_addr.s_addr = htonl(faddress);
107 2 : addr::addr f;
108 1 : f.set_ipv4(fin);
109 :
110 : // to 10.0.0.254
111 1 : struct sockaddr_in tin = sockaddr_in();
112 1 : tin.sin_family = AF_INET;
113 1 : int const tport(rand() & 0xFFFF);
114 1 : tin.sin_port = htons(tport);
115 1 : uint32_t const taddress((10 << 24)
116 : | (0 << 16)
117 : | (0 << 8)
118 : | 254);
119 1 : tin.sin_addr.s_addr = htonl(taddress);
120 2 : addr::addr t;
121 1 : t.set_ipv4(tin);
122 :
123 : // test defaults first
124 : //
125 1 : CATCH_REQUIRE_FALSE(range.has_from());
126 1 : CATCH_REQUIRE_FALSE(range.has_to());
127 1 : CATCH_REQUIRE_FALSE(range.is_range());
128 1 : CATCH_REQUIRE_FALSE(range.is_empty());
129 1 : CATCH_REQUIRE_FALSE(range.is_ipv4());
130 1 : CATCH_REQUIRE(range.get_from() == a);
131 1 : CATCH_REQUIRE(range.get_to() == a);
132 1 : CATCH_REQUIRE(range.size() == 0);
133 1 : auto const & r1(range);
134 1 : CATCH_REQUIRE(r1.get_from() == a);
135 1 : CATCH_REQUIRE(r1.get_to() == a);
136 1 : CATCH_REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state);
137 1 : CATCH_REQUIRE_THROWS_AS(r1.is_in(other), addr::addr_invalid_state);
138 1 : CATCH_REQUIRE(r1.size() == 0);
139 1 : CATCH_REQUIRE(range.match(a));
140 1 : CATCH_REQUIRE_FALSE(range.match(f));
141 1 : CATCH_REQUIRE_FALSE(range.match(t));
142 :
143 1 : range.set_from(f);
144 :
145 : // defined "from", test the results
146 : //
147 1 : CATCH_REQUIRE(range.has_from());
148 1 : CATCH_REQUIRE_FALSE(range.has_to());
149 1 : CATCH_REQUIRE_FALSE(range.is_range());
150 1 : CATCH_REQUIRE_FALSE(range.is_empty());
151 1 : CATCH_REQUIRE(range.is_ipv4());
152 1 : CATCH_REQUIRE(range.get_from() == f);
153 1 : CATCH_REQUIRE(range.get_to() == a);
154 1 : CATCH_REQUIRE(range.size() == 1);
155 1 : auto const & r2(range);
156 1 : CATCH_REQUIRE(r2.get_from() == f);
157 1 : CATCH_REQUIRE(r2.get_to() == a);
158 1 : CATCH_REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state);
159 1 : CATCH_REQUIRE_THROWS_AS(r2.is_in(other), addr::addr_invalid_state);
160 1 : CATCH_REQUIRE(r2.size() == 1);
161 1 : CATCH_REQUIRE_FALSE(range.match(a));
162 1 : CATCH_REQUIRE(range.match(f));
163 1 : CATCH_REQUIRE_FALSE(range.match(t));
164 :
165 : {
166 2 : std::stringstream ss;
167 1 : ss << range;
168 1 : CATCH_REQUIRE(ss.str() == "10.0.0.1:" + std::to_string(fport) + "/32");
169 :
170 2 : addr::addr::vector_t from_vec(range.to_addresses(1000));
171 1 : CATCH_REQUIRE(from_vec.size() == 1);
172 1 : CATCH_REQUIRE(from_vec[0] == f);
173 : }
174 :
175 1 : range.swap_from_to();
176 :
177 : // swaped "from" & "to", test the results
178 : //
179 1 : CATCH_REQUIRE_FALSE(range.has_from());
180 1 : CATCH_REQUIRE(range.has_to());
181 1 : CATCH_REQUIRE_FALSE(range.is_range());
182 1 : CATCH_REQUIRE_FALSE(range.is_empty());
183 1 : CATCH_REQUIRE(range.is_ipv4());
184 1 : CATCH_REQUIRE(range.get_from() == a);
185 1 : CATCH_REQUIRE(range.get_to() == f);
186 1 : CATCH_REQUIRE(range.size() == 1);
187 1 : auto const & r2b(range);
188 1 : CATCH_REQUIRE(r2b.get_from() == a);
189 1 : CATCH_REQUIRE(r2b.get_to() == f);
190 1 : CATCH_REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state);
191 1 : CATCH_REQUIRE_THROWS_AS(r2b.is_in(other), addr::addr_invalid_state);
192 1 : CATCH_REQUIRE(r2b.size() == 1);
193 1 : CATCH_REQUIRE_FALSE(range.match(a));
194 1 : CATCH_REQUIRE(range.match(f));
195 1 : CATCH_REQUIRE_FALSE(range.match(t));
196 :
197 : {
198 2 : std::stringstream ss1;
199 1 : ss1 << range;
200 1 : CATCH_REQUIRE(ss1.str() == "-10.0.0.1:" + std::to_string(fport) + "/32");
201 :
202 2 : std::stringstream ss2;
203 1 : ss2 << addr::setaddrmode(addr::string_ip_t::STRING_IP_ONLY) << range;
204 1 : CATCH_REQUIRE(ss2.str() == "-10.0.0.1");
205 :
206 2 : addr::addr::vector_t from_vec(range.to_addresses(1000));
207 1 : CATCH_REQUIRE(from_vec.size() == 1);
208 1 : CATCH_REQUIRE(from_vec[0] == f);
209 : }
210 :
211 1 : range.swap_from_to(); // restore before we go on
212 1 : CATCH_REQUIRE(range.get_from() == f);
213 1 : CATCH_REQUIRE(range.get_to() == a);
214 :
215 1 : range.set_to(t);
216 :
217 : // defined "to", test the results
218 : //
219 1 : CATCH_REQUIRE(range.has_from());
220 1 : CATCH_REQUIRE(range.has_to());
221 1 : CATCH_REQUIRE(range.is_range());
222 1 : CATCH_REQUIRE_FALSE(range.is_empty());
223 1 : CATCH_REQUIRE(range.is_ipv4());
224 1 : CATCH_REQUIRE(range.get_from() == f);
225 1 : CATCH_REQUIRE(range.get_to() == t);
226 1 : CATCH_REQUIRE(range.size() == 254); // all but .0 and .255, that's 254 addresses
227 1 : auto const & r3(range);
228 1 : CATCH_REQUIRE(r3.get_from() == f);
229 1 : CATCH_REQUIRE(r3.get_to() == t);
230 1 : CATCH_REQUIRE(r3.size() == 254);
231 1 : CATCH_REQUIRE_FALSE(range.match(a));
232 1 : CATCH_REQUIRE(range.match(f));
233 1 : CATCH_REQUIRE(range.match(t));
234 :
235 : {
236 2 : std::stringstream ss;
237 1 : ss << range;
238 1 : CATCH_REQUIRE(ss.str() == "10.0.0.1-10.0.0.254:" + std::to_string(tport) + "/32");
239 : }
240 :
241 2 : addr::addr_range to_range; // to-only range
242 1 : to_range.set_to(t);
243 :
244 : // defined "to", but not from
245 : //
246 1 : CATCH_REQUIRE_FALSE(to_range.has_from());
247 1 : CATCH_REQUIRE(to_range.has_to());
248 1 : CATCH_REQUIRE_FALSE(to_range.is_range());
249 1 : CATCH_REQUIRE_FALSE(to_range.is_empty());
250 1 : CATCH_REQUIRE(to_range.is_ipv4());
251 1 : CATCH_REQUIRE(to_range.get_from() == a);
252 1 : CATCH_REQUIRE(to_range.get_to() == t);
253 1 : CATCH_REQUIRE(to_range.size() == 1);
254 1 : auto const & r4(to_range);
255 1 : CATCH_REQUIRE(r4.get_from() == a);
256 1 : CATCH_REQUIRE(r4.get_to() == t);
257 1 : CATCH_REQUIRE(r4.size() == 1);
258 1 : CATCH_REQUIRE_FALSE(to_range.match(a));
259 1 : CATCH_REQUIRE_FALSE(to_range.match(f));
260 1 : CATCH_REQUIRE(to_range.match(t));
261 :
262 : {
263 2 : std::stringstream ss;
264 1 : ss << to_range;
265 1 : CATCH_REQUIRE(ss.str() == "-10.0.0.254:" + std::to_string(tport) + "/32");
266 :
267 2 : addr::addr::vector_t to_vec(to_range.to_addresses(1000));
268 1 : CATCH_REQUIRE(to_vec.size() == 1);
269 1 : CATCH_REQUIRE(to_vec[0] == t);
270 : }
271 :
272 : // IP before range
273 : {
274 1 : struct sockaddr_in bin = sockaddr_in();
275 1 : bin.sin_family = AF_INET;
276 1 : bin.sin_port = htons(rand());
277 1 : uint32_t baddress((10 << 24)
278 : | (0 << 16)
279 : | (0 << 8)
280 : | 0);
281 1 : bin.sin_addr.s_addr = htonl(baddress);
282 2 : addr::addr b;
283 1 : b.set_ipv4(bin);
284 1 : CATCH_REQUIRE(f.is_previous(b));
285 1 : CATCH_REQUIRE(b.is_next(f));
286 :
287 1 : CATCH_REQUIRE_FALSE(range.is_in(b));
288 : }
289 :
290 11 : for(int idx(0); idx < 10; ++idx)
291 : {
292 10 : struct sockaddr_in bin = sockaddr_in();
293 10 : bin.sin_family = AF_INET;
294 10 : bin.sin_port = htons(rand());
295 10 : uint32_t baddress(((rand() % 10) << 24)
296 10 : | ((rand() & 255) << 16)
297 10 : | ((rand() & 255) << 8)
298 10 : | (rand() & 255));
299 10 : bin.sin_addr.s_addr = htonl(baddress);
300 20 : addr::addr b;
301 10 : b.set_ipv4(bin);
302 :
303 10 : CATCH_REQUIRE_FALSE(range.is_in(b));
304 : }
305 :
306 : // IP after range
307 : {
308 1 : struct sockaddr_in ain = sockaddr_in();
309 1 : ain.sin_family = AF_INET;
310 1 : ain.sin_port = htons(rand());
311 1 : uint32_t aaddress((10 << 24)
312 : | (0 << 16)
313 : | (0 << 8)
314 : | 255);
315 1 : ain.sin_addr.s_addr = htonl(aaddress);
316 2 : addr::addr after;
317 1 : after.set_ipv4(ain);
318 1 : CATCH_REQUIRE(after.is_previous(t));
319 1 : CATCH_REQUIRE(t.is_next(after));
320 :
321 1 : CATCH_REQUIRE_FALSE(range.is_in(after));
322 : }
323 :
324 11 : for(int idx(0); idx < 10; ++idx)
325 : {
326 10 : struct sockaddr_in ain = sockaddr_in();
327 10 : ain.sin_family = AF_INET;
328 10 : ain.sin_port = htons(rand());
329 10 : uint32_t aaddress(((rand() % (256 - 11) + 11) << 24)
330 10 : | ((rand() & 255) << 16)
331 10 : | ((rand() & 255) << 8)
332 10 : | (rand() & 255));
333 10 : ain.sin_addr.s_addr = htonl(aaddress);
334 20 : addr::addr after;
335 10 : after.set_ipv4(ain);
336 :
337 10 : CATCH_REQUIRE_FALSE(range.is_in(after));
338 : }
339 :
340 : // IP in range
341 : //
342 255 : for(int idx(1); idx < 255; ++idx)
343 : {
344 254 : struct sockaddr_in iin = sockaddr_in();
345 254 : iin.sin_family = AF_INET;
346 254 : iin.sin_port = htons(rand());
347 254 : uint32_t iaddress((10 << 24)
348 : | (0 << 16)
349 : | (0 << 8)
350 254 : | idx);
351 254 : iin.sin_addr.s_addr = htonl(iaddress);
352 508 : addr::addr i;
353 254 : i.set_ipv4(iin);
354 :
355 254 : CATCH_REQUIRE(range.is_in(i));
356 : }
357 :
358 : // range to vector of IPs addresses
359 : //
360 2 : addr::addr::vector_t vec(range.to_addresses(1000));
361 255 : for(int idx(1); idx <= 254; ++idx)
362 : {
363 254 : struct sockaddr_in ein = sockaddr_in();
364 254 : ein.sin_family = AF_INET;
365 254 : int const eport(rand() & 0xFFFF);
366 254 : ein.sin_port = htons(eport);
367 254 : uint32_t const eaddress((10 << 24)
368 : | (0 << 16)
369 : | (0 << 8)
370 254 : | idx);
371 254 : ein.sin_addr.s_addr = htonl(eaddress);
372 508 : addr::addr e;
373 254 : e.set_ipv4(ein);
374 254 : CATCH_REQUIRE(vec.front() == e);
375 254 : vec.erase(vec.begin());
376 : }
377 : // same, but use a limit so we get only the first 10 IPs
378 1 : CATCH_REQUIRE_THROWS_MATCHES(
379 : range.to_addresses(10)
380 : , addr::out_of_range
381 : , Catch::Matchers::ExceptionMessage(
382 : "out_of_range: too many addresses in this range: 254 > 10"));
383 : }
384 : CATCH_END_SECTION()
385 :
386 18 : CATCH_START_SECTION("addr_range: test empty range (from > to)")
387 : {
388 2 : addr::addr a;
389 2 : addr::addr other;
390 :
391 : // from is set to 10.0.0.254
392 1 : struct sockaddr_in fin = sockaddr_in();
393 1 : fin.sin_family = AF_INET;
394 1 : int const fport(rand() & 0xFFFF);
395 1 : fin.sin_port = htons(fport);
396 1 : uint32_t const faddress((10 << 24)
397 : | (0 << 16)
398 : | (0 << 8)
399 : | 254);
400 1 : fin.sin_addr.s_addr = htonl(faddress);
401 2 : addr::addr f;
402 1 : f.set_ipv4(fin);
403 :
404 : // from is set to 10.0.0.1
405 1 : struct sockaddr_in tin = sockaddr_in();
406 1 : tin.sin_family = AF_INET;
407 1 : int const tport(rand() & 0xFFFF);
408 1 : tin.sin_port = htons(tport);
409 1 : uint32_t const taddress((10 << 24)
410 : | (0 << 16)
411 : | (0 << 8)
412 : | 1);
413 1 : tin.sin_addr.s_addr = htonl(taddress);
414 2 : addr::addr t;
415 1 : t.set_ipv4(tin);
416 :
417 : // test defaults first
418 : //
419 1 : CATCH_REQUIRE_FALSE(range.has_from());
420 1 : CATCH_REQUIRE_FALSE(range.has_to());
421 1 : CATCH_REQUIRE_FALSE(range.is_range());
422 1 : CATCH_REQUIRE_FALSE(range.is_empty());
423 1 : CATCH_REQUIRE(range.get_from() == a);
424 1 : CATCH_REQUIRE(range.get_to() == a);
425 1 : auto const & r1(range);
426 1 : CATCH_REQUIRE(r1.get_from() == a);
427 1 : CATCH_REQUIRE(r1.get_to() == a);
428 1 : CATCH_REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state);
429 1 : CATCH_REQUIRE_THROWS_AS(r1.is_in(other), addr::addr_invalid_state);
430 1 : CATCH_REQUIRE(range.match(a));
431 1 : CATCH_REQUIRE_FALSE(range.match(f));
432 1 : CATCH_REQUIRE_FALSE(range.match(t));
433 :
434 1 : range.set_from(f);
435 :
436 : // defined "from", test the results
437 : //
438 1 : CATCH_REQUIRE(range.has_from());
439 1 : CATCH_REQUIRE_FALSE(range.has_to());
440 1 : CATCH_REQUIRE_FALSE(range.is_range());
441 1 : CATCH_REQUIRE_FALSE(range.is_empty());
442 1 : CATCH_REQUIRE(range.get_from() == f);
443 1 : CATCH_REQUIRE(range.get_to() == a);
444 1 : auto const & r2(range);
445 1 : CATCH_REQUIRE(r2.get_from() == f);
446 1 : CATCH_REQUIRE(r2.get_to() == a);
447 1 : CATCH_REQUIRE_THROWS_AS(range.is_in(other), addr::addr_invalid_state);
448 1 : CATCH_REQUIRE_THROWS_AS(r2.is_in(other), addr::addr_invalid_state);
449 1 : CATCH_REQUIRE_FALSE(range.match(a));
450 1 : CATCH_REQUIRE(range.match(f));
451 1 : CATCH_REQUIRE_FALSE(range.match(t));
452 :
453 : {
454 2 : std::stringstream ss;
455 1 : ss << range;
456 1 : CATCH_REQUIRE(ss.str() == "10.0.0.254:" + std::to_string(fport) + "/32");
457 : }
458 :
459 1 : range.set_to(t);
460 :
461 : // defined "to", test the results
462 : //
463 1 : CATCH_REQUIRE(range.has_from());
464 1 : CATCH_REQUIRE(range.has_to());
465 1 : CATCH_REQUIRE(range.is_range());
466 1 : CATCH_REQUIRE(range.is_empty());
467 1 : CATCH_REQUIRE(range.get_from() == f);
468 1 : CATCH_REQUIRE(range.get_to() == t);
469 1 : auto const & r3(range);
470 1 : CATCH_REQUIRE(r3.get_from() == f);
471 1 : CATCH_REQUIRE(r3.get_to() == t);
472 1 : CATCH_REQUIRE_FALSE(range.match(a));
473 1 : CATCH_REQUIRE_FALSE(range.match(f));
474 1 : CATCH_REQUIRE_FALSE(range.match(t));
475 :
476 : {
477 2 : std::stringstream ss;
478 1 : ss << range;
479 1 : CATCH_REQUIRE(ss.str() == "<empty address range>");
480 : }
481 :
482 : // IP before range
483 : {
484 1 : struct sockaddr_in bin = sockaddr_in();
485 1 : bin.sin_family = AF_INET;
486 1 : bin.sin_port = htons(rand());
487 1 : uint32_t baddress((10 << 24)
488 : | (0 << 16)
489 : | (0 << 8)
490 : | 0);
491 1 : bin.sin_addr.s_addr = htonl(baddress);
492 2 : addr::addr b;
493 1 : b.set_ipv4(bin);
494 :
495 1 : CATCH_REQUIRE_FALSE(range.is_in(b));
496 : }
497 :
498 11 : for(int idx(0); idx < 10; ++idx)
499 : {
500 10 : struct sockaddr_in bin = sockaddr_in();
501 10 : bin.sin_family = AF_INET;
502 10 : bin.sin_port = htons(rand());
503 10 : uint32_t baddress(((rand() % 10) << 24)
504 10 : | ((rand() & 255) << 16)
505 10 : | ((rand() & 255) << 8)
506 10 : | (rand() & 255));
507 10 : bin.sin_addr.s_addr = htonl(baddress);
508 20 : addr::addr b;
509 10 : b.set_ipv4(bin);
510 :
511 10 : CATCH_REQUIRE_FALSE(range.is_in(b));
512 : }
513 :
514 : // IP after range
515 : {
516 1 : struct sockaddr_in ain = sockaddr_in();
517 1 : ain.sin_family = AF_INET;
518 1 : ain.sin_port = htons(rand());
519 1 : uint32_t aaddress((10 << 24)
520 : | (0 << 16)
521 : | (0 << 8)
522 : | 255);
523 1 : ain.sin_addr.s_addr = htonl(aaddress);
524 2 : addr::addr after;
525 1 : after.set_ipv4(ain);
526 :
527 1 : CATCH_REQUIRE_FALSE(range.is_in(after));
528 : }
529 :
530 11 : for(int idx(0); idx < 10; ++idx)
531 : {
532 10 : struct sockaddr_in ain = sockaddr_in();
533 10 : ain.sin_family = AF_INET;
534 10 : ain.sin_port = htons(rand());
535 10 : uint32_t aaddress(((rand() % (256 - 11) + 11) << 24)
536 10 : | ((rand() & 255) << 16)
537 10 : | ((rand() & 255) << 8)
538 10 : | (rand() & 255));
539 10 : ain.sin_addr.s_addr = htonl(aaddress);
540 20 : addr::addr after;
541 10 : after.set_ipv4(ain);
542 :
543 10 : CATCH_REQUIRE_FALSE(range.is_in(after));
544 : }
545 :
546 : // IP in range
547 : //
548 101 : for(int idx(0); idx < 100; ++idx)
549 : {
550 100 : struct sockaddr_in iin = sockaddr_in();
551 100 : iin.sin_family = AF_INET;
552 100 : iin.sin_port = htons(rand());
553 : uint32_t iaddress((10 << 24)
554 : | (0 << 16)
555 : | (0 << 8)
556 100 : | ((rand() & 253) + 1));
557 100 : iin.sin_addr.s_addr = htonl(iaddress);
558 200 : addr::addr i;
559 100 : i.set_ipv4(iin);
560 :
561 100 : CATCH_REQUIRE_FALSE(range.is_in(i));
562 : }
563 : }
564 : CATCH_END_SECTION()
565 :
566 18 : CATCH_START_SECTION("addr_range: compare \"from\" ranges against each other")
567 : {
568 2 : addr::addr a;
569 2 : addr::addr_range other;
570 :
571 1 : CATCH_REQUIRE(range.compare(range) == addr::compare_t::COMPARE_UNORDERED);
572 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_UNORDERED);
573 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_UNORDERED);
574 :
575 1 : struct sockaddr_in in = sockaddr_in();
576 1 : in.sin_family = AF_INET;
577 1 : in.sin_port = htons(rand());
578 : uint32_t address((10 << 24)
579 1 : | ((rand() & 255) << 16)
580 1 : | ((rand() & 255) << 8)
581 1 : | (rand() & 255));
582 1 : in.sin_addr.s_addr = htonl(address);
583 1 : a.set_ipv4(in);
584 1 : range.set_from(a);
585 :
586 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_UNORDERED);
587 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_UNORDERED);
588 1 : CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_UNORDERED);
589 :
590 1 : address = (20 << 24)
591 1 : | ((rand() & 255) << 16)
592 1 : | ((rand() & 255) << 8)
593 1 : | (rand() & 255);
594 1 : in.sin_addr.s_addr = htonl(address);
595 1 : a.set_ipv4(in);
596 1 : other.set_from(a);
597 :
598 1 : CATCH_REQUIRE(range.compare(range) == addr::compare_t::COMPARE_EQUAL);
599 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_SMALLER);
600 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_LARGER);
601 1 : CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_EQUAL);
602 :
603 1 : a = range.get_from();
604 1 : other.set_from(a + 1);
605 :
606 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_PRECEDES);
607 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_FOLLOWS);
608 : }
609 : CATCH_END_SECTION()
610 :
611 18 : CATCH_START_SECTION("addr_range: compare \"to\" ranges against each other")
612 : {
613 2 : addr::addr a;
614 2 : addr::addr_range other;
615 :
616 1 : CATCH_REQUIRE(range.compare(range) == addr::compare_t::COMPARE_UNORDERED);
617 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_UNORDERED);
618 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_UNORDERED);
619 :
620 1 : struct sockaddr_in in = sockaddr_in();
621 1 : in.sin_family = AF_INET;
622 1 : in.sin_port = htons(rand());
623 : uint32_t address((10 << 24)
624 1 : | ((rand() & 255) << 16)
625 1 : | ((rand() & 255) << 8)
626 1 : | (rand() & 255));
627 1 : in.sin_addr.s_addr = htonl(address);
628 1 : a.set_ipv4(in);
629 1 : range.set_to(a);
630 :
631 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_UNORDERED);
632 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_UNORDERED);
633 1 : CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_UNORDERED);
634 :
635 1 : address = (20 << 24)
636 1 : | ((rand() & 255) << 16)
637 1 : | ((rand() & 255) << 8)
638 1 : | (rand() & 255);
639 1 : in.sin_addr.s_addr = htonl(address);
640 1 : a.set_ipv4(in);
641 1 : other.set_to(a);
642 :
643 1 : CATCH_REQUIRE(range.compare(range) == addr::compare_t::COMPARE_EQUAL);
644 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_SMALLER);
645 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_LARGER);
646 1 : CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_EQUAL);
647 :
648 1 : a = range.get_to();
649 1 : other.set_to(a + 1);
650 :
651 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_PRECEDES);
652 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_FOLLOWS);
653 : }
654 : CATCH_END_SECTION()
655 :
656 18 : CATCH_START_SECTION("addr_range: compare \"from\" against \"to\" ranges")
657 : {
658 2 : addr::addr a;
659 2 : addr::addr_range other;
660 :
661 1 : CATCH_REQUIRE(range.compare(range) == addr::compare_t::COMPARE_UNORDERED);
662 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_UNORDERED);
663 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_UNORDERED);
664 :
665 1 : struct sockaddr_in in = sockaddr_in();
666 1 : in.sin_family = AF_INET;
667 1 : in.sin_port = htons(rand());
668 : uint32_t address((10 << 24)
669 1 : | ((rand() & 255) << 16)
670 1 : | ((rand() & 255) << 8)
671 1 : | (rand() & 255));
672 1 : in.sin_addr.s_addr = htonl(address);
673 1 : a.set_ipv4(in);
674 1 : range.set_from(a);
675 :
676 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_UNORDERED);
677 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_UNORDERED);
678 1 : CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_UNORDERED);
679 :
680 1 : address = (20 << 24)
681 1 : | ((rand() & 255) << 16)
682 1 : | ((rand() & 255) << 8)
683 1 : | (rand() & 255);
684 1 : in.sin_addr.s_addr = htonl(address);
685 1 : a.set_ipv4(in);
686 1 : other.set_to(a);
687 :
688 1 : CATCH_REQUIRE(range.compare(range) == addr::compare_t::COMPARE_EQUAL);
689 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_SMALLER);
690 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_LARGER);
691 1 : CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_EQUAL);
692 :
693 1 : a = range.get_from();
694 1 : other.set_to(a + 1);
695 :
696 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_PRECEDES);
697 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_FOLLOWS);
698 : }
699 : CATCH_END_SECTION()
700 :
701 18 : CATCH_START_SECTION("addr_range: compare full ranges (\"from\" and \"to\" defined)")
702 : {
703 2 : addr::addr a;
704 2 : addr::addr_range other;
705 :
706 1 : struct sockaddr_in in = sockaddr_in();
707 1 : in.sin_family = AF_INET;
708 1 : in.sin_port = htons(rand());
709 1 : uint32_t address((10 << 24)
710 : | (5 << 16)
711 : | (7 << 8)
712 : | (32 << 0));
713 1 : in.sin_addr.s_addr = htonl(address);
714 1 : a.set_ipv4(in);
715 1 : range.set_from(a);
716 :
717 1 : address = (10 << 24)
718 : | (5 << 16)
719 : | (7 << 8)
720 : | (37 << 0);
721 1 : in.sin_addr.s_addr = htonl(address);
722 1 : a.set_ipv4(in);
723 1 : range.set_to(a);
724 :
725 1 : CATCH_REQUIRE(range.compare(range) == addr::compare_t::COMPARE_EQUAL);
726 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_UNORDERED);
727 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_UNORDERED);
728 1 : CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_UNORDERED);
729 :
730 1 : address = (20 << 24)
731 : | (5 << 16)
732 : | (7 << 8)
733 : | (32 << 0);
734 1 : in.sin_addr.s_addr = htonl(address);
735 1 : a.set_ipv4(in);
736 1 : other.set_from(a);
737 :
738 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_SMALLER);
739 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_LARGER);
740 1 : CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_EQUAL);
741 :
742 1 : other.swap_from_to();
743 :
744 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_SMALLER);
745 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_LARGER);
746 1 : CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_EQUAL);
747 :
748 1 : address = (20 << 24)
749 : | (5 << 16)
750 : | (7 << 8)
751 : | (22 << 0);
752 1 : in.sin_addr.s_addr = htonl(address);
753 1 : a.set_ipv4(in);
754 1 : other.set_from(a); // it was swapped, so set from again
755 :
756 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_SMALLER);
757 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_LARGER);
758 1 : CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_EQUAL);
759 :
760 1 : other.swap_from_to();
761 :
762 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_FIRST);
763 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_LAST);
764 1 : CATCH_REQUIRE(other.compare(other) == addr::compare_t::COMPARE_UNORDERED);
765 :
766 1 : other.swap_from_to();
767 :
768 1 : a = range.get_to();
769 1 : other.set_from(a + 1);
770 :
771 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_PRECEDES);
772 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_FOLLOWS);
773 :
774 1 : other.set_from(a);
775 :
776 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_OVERLAP_SMALL_VS_LARGE);
777 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_OVERLAP_LARGE_VS_SMALL);
778 : }
779 : CATCH_END_SECTION()
780 :
781 18 : CATCH_START_SECTION("addr_range: compare mixed IPs")
782 : {
783 2 : addr::addr a;
784 2 : addr::addr_range other;
785 :
786 1 : struct sockaddr_in in4 = sockaddr_in();
787 1 : in4.sin_family = AF_INET;
788 1 : in4.sin_port = htons(rand());
789 1 : uint32_t address((10 << 24)
790 : | (5 << 16)
791 : | (7 << 8)
792 : | (32 << 0));
793 1 : in4.sin_addr.s_addr = htonl(address);
794 1 : a.set_ipv4(in4);
795 1 : range.set_from(a);
796 :
797 1 : struct sockaddr_in6 in6 = sockaddr_in6();
798 1 : in6.sin6_family = AF_INET6;
799 1 : in6.sin6_port = htons(rand());
800 1 : in6.sin6_addr.s6_addr[0] = 0xF8;
801 1 : a.set_ipv6(in6);
802 1 : other.set_from(a);
803 :
804 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_IPV4_VS_IPV6);
805 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_IPV6_VS_IPV4);
806 :
807 1 : CATCH_REQUIRE(range.compare(other, true) == addr::compare_t::COMPARE_SMALLER);
808 1 : CATCH_REQUIRE(other.compare(range, true) == addr::compare_t::COMPARE_LARGER);
809 :
810 1 : in6.sin6_addr.s6_addr[0] = 0;
811 1 : in6.sin6_addr.s6_addr[15] = 1;
812 1 : a.set_ipv6(in6);
813 1 : other.set_from(a);
814 :
815 1 : CATCH_REQUIRE(range.compare(other) == addr::compare_t::COMPARE_IPV4_VS_IPV6);
816 1 : CATCH_REQUIRE(other.compare(range) == addr::compare_t::COMPARE_IPV6_VS_IPV4);
817 :
818 1 : CATCH_REQUIRE(range.compare(other, true) == addr::compare_t::COMPARE_LARGER);
819 1 : CATCH_REQUIRE(other.compare(range, true) == addr::compare_t::COMPARE_SMALLER);
820 : }
821 : CATCH_END_SECTION()
822 :
823 18 : CATCH_START_SECTION("addr_range: create range from CIDR")
824 : {
825 2 : addr::addr a;
826 :
827 : // from is set to 10.x.x.x
828 1 : struct sockaddr_in fin = sockaddr_in();
829 1 : fin.sin_family = AF_INET;
830 1 : fin.sin_port = htons(rand());
831 : uint32_t faddress((10 << 24)
832 1 : | ((rand() & 255) << 16)
833 1 : | ((rand() & 255) << 8)
834 1 : | (rand() & 255));
835 1 : fin.sin_addr.s_addr = htonl(faddress);
836 1 : a.set_ipv4(fin);
837 :
838 : // no mask defined, that means the range will be [a..a]
839 1 : range.from_cidr(a);
840 :
841 1 : CATCH_REQUIRE(range.has_from());
842 1 : CATCH_REQUIRE(range.has_to());
843 1 : CATCH_REQUIRE(range.is_range());
844 1 : CATCH_REQUIRE_FALSE(range.is_empty());
845 1 : CATCH_REQUIRE(range.is_ipv4());
846 1 : CATCH_REQUIRE(range.get_from() == a);
847 1 : CATCH_REQUIRE(range.get_to() == a);
848 1 : CATCH_REQUIRE(range.size() == 1);
849 :
850 : #pragma GCC diagnostic push
851 : #pragma GCC diagnostic ignored "-Wpedantic"
852 34 : for(int size(96); size <= 128; ++size)
853 : {
854 33 : a.set_mask_count(size);
855 33 : range.from_cidr(a);
856 :
857 33 : CATCH_REQUIRE(range.has_from());
858 33 : CATCH_REQUIRE(range.has_to());
859 33 : CATCH_REQUIRE(range.is_range());
860 33 : CATCH_REQUIRE_FALSE(range.is_empty());
861 33 : CATCH_REQUIRE(range.is_ipv4());
862 33 : unsigned __int128 mask(0xffffffffffffffffffffffffffffffff_uint128);
863 33 : mask <<= 128 - size;
864 33 : addr::addr const & f(range.get_from());
865 33 : addr::addr const & t(range.get_to());
866 33 : unsigned __int128 aa(a.ip_to_uint128());
867 33 : unsigned __int128 fa(f.ip_to_uint128());
868 33 : unsigned __int128 ta(t.ip_to_uint128());
869 33 : unsigned __int128 fm(aa & mask);
870 33 : unsigned __int128 tm(aa | ~mask);
871 33 : CATCH_REQUIRE(fa == fm);
872 33 : CATCH_REQUIRE(ta == tm);
873 33 : CATCH_REQUIRE(range.size() == 1ULL << (128 - size));
874 : }
875 : #pragma GCC diagnostic pop
876 :
877 : // create an invalid mask as far as from_cidr() is concerned
878 : //
879 1 : uint8_t invalid_mask[16] = {};
880 17 : for(int i(0); i < 16; ++i)
881 : {
882 1 : do
883 : {
884 17 : invalid_mask[i] = rand();
885 : }
886 17 : while(invalid_mask[i] == 0 || invalid_mask[i] == 0xFF);
887 : }
888 1 : a.set_mask(invalid_mask);
889 1 : CATCH_REQUIRE_THROWS_MATCHES(
890 : range.from_cidr(a)
891 : , addr::addr_unsupported_as_range
892 : , Catch::Matchers::ExceptionMessage(
893 : "addr_error: unsupported mask for a range"));
894 : }
895 : CATCH_END_SECTION()
896 : }
897 :
898 28 : CATCH_GIVEN("compute intersection of two ranges")
899 : {
900 4 : CATCH_START_SECTION("addr_range: intersection of two ranges that overlap")
901 : {
902 : // from is set to 10.1.0.0
903 1 : struct sockaddr_in f1in = sockaddr_in();
904 1 : f1in.sin_family = AF_INET;
905 1 : f1in.sin_port = htons(rand());
906 1 : uint32_t f1address((10 << 24)
907 : | (1 << 16)
908 : | (0 << 8)
909 : | 0);
910 1 : f1in.sin_addr.s_addr = htonl(f1address);
911 2 : addr::addr f1;
912 1 : f1.set_ipv4(f1in);
913 :
914 : // to is set to 10.5.255.255
915 1 : struct sockaddr_in t1in = sockaddr_in();
916 1 : t1in.sin_family = AF_INET;
917 1 : t1in.sin_port = htons(rand());
918 1 : uint32_t t1address((10 << 24)
919 : | (5 << 16)
920 : | (255 << 8)
921 : | 255);
922 1 : t1in.sin_addr.s_addr = htonl(t1address);
923 2 : addr::addr t1;
924 1 : t1.set_ipv4(t1in);
925 :
926 : // from is set to 10.2.0.0
927 1 : struct sockaddr_in f2in = sockaddr_in();
928 1 : f2in.sin_family = AF_INET;
929 1 : f2in.sin_port = htons(rand());
930 1 : uint32_t f2address((10 << 24)
931 : | (2 << 16)
932 : | (0 << 8)
933 : | 0);
934 1 : f2in.sin_addr.s_addr = htonl(f2address);
935 2 : addr::addr f2;
936 1 : f2.set_ipv4(f2in);
937 :
938 : // to is set to 10.10.255.255
939 1 : struct sockaddr_in t2in = sockaddr_in();
940 1 : t2in.sin_family = AF_INET;
941 1 : t2in.sin_port = htons(rand());
942 1 : uint32_t t2address((10 << 24)
943 : | (10 << 16)
944 : | (255 << 8)
945 : | 255);
946 1 : t2in.sin_addr.s_addr = htonl(t2address);
947 2 : addr::addr t2;
948 1 : t2.set_ipv4(t2in);
949 :
950 2 : addr::addr_range range1;
951 1 : range1.set_from(f1);
952 1 : range1.set_to(t1);
953 :
954 2 : addr::addr_range range2;
955 1 : range2.set_from(f2);
956 1 : range2.set_to(t2);
957 :
958 1 : CATCH_REQUIRE(range1.is_range());
959 1 : CATCH_REQUIRE_FALSE(range1.is_empty());
960 1 : CATCH_REQUIRE(range2.is_range());
961 1 : CATCH_REQUIRE_FALSE(range2.is_empty());
962 :
963 2 : addr::addr_range const range3(range1.intersection(range2));
964 :
965 1 : CATCH_REQUIRE(range3.is_range());
966 1 : CATCH_REQUIRE_FALSE(range3.is_empty());
967 :
968 1 : CATCH_REQUIRE(range3.get_from().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.2.0.0");
969 1 : CATCH_REQUIRE(range3.get_to().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.5.255.255");
970 : }
971 : CATCH_END_SECTION()
972 :
973 4 : CATCH_START_SECTION("addr_range: intersection of two ranges that do not overlap")
974 : {
975 : // from is set to 10.1.0.0
976 1 : struct sockaddr_in f1in = sockaddr_in();
977 1 : f1in.sin_family = AF_INET;
978 1 : f1in.sin_port = htons(rand());
979 1 : uint32_t f1address((10 << 24)
980 : | (1 << 16)
981 : | (0 << 8)
982 : | 0);
983 1 : f1in.sin_addr.s_addr = htonl(f1address);
984 2 : addr::addr f1;
985 1 : f1.set_ipv4(f1in);
986 :
987 : // to is set to 10.5.255.255
988 1 : struct sockaddr_in t1in = sockaddr_in();
989 1 : t1in.sin_family = AF_INET;
990 1 : t1in.sin_port = htons(rand());
991 1 : uint32_t t1address((10 << 24)
992 : | (5 << 16)
993 : | (255 << 8)
994 : | 255);
995 1 : t1in.sin_addr.s_addr = htonl(t1address);
996 2 : addr::addr t1;
997 1 : t1.set_ipv4(t1in);
998 :
999 : // from is set to 10.10.0.0
1000 1 : struct sockaddr_in f2in = sockaddr_in();
1001 1 : f2in.sin_family = AF_INET;
1002 1 : f2in.sin_port = htons(rand());
1003 1 : uint32_t f2address((10 << 24)
1004 : | (10 << 16)
1005 : | (0 << 8)
1006 : | 0);
1007 1 : f2in.sin_addr.s_addr = htonl(f2address);
1008 2 : addr::addr f2;
1009 1 : f2.set_ipv4(f2in);
1010 :
1011 : // to is set to 10.20.255.255
1012 1 : struct sockaddr_in t2in = sockaddr_in();
1013 1 : t2in.sin_family = AF_INET;
1014 1 : t2in.sin_port = htons(rand());
1015 1 : uint32_t t2address((10 << 24)
1016 : | (20 << 16)
1017 : | (255 << 8)
1018 : | 255);
1019 1 : t2in.sin_addr.s_addr = htonl(t2address);
1020 2 : addr::addr t2;
1021 1 : t2.set_ipv4(t2in);
1022 :
1023 2 : addr::addr_range range1;
1024 1 : range1.set_from(f1);
1025 1 : range1.set_to(t1);
1026 :
1027 2 : addr::addr_range range2;
1028 1 : range2.set_from(f2);
1029 1 : range2.set_to(t2);
1030 :
1031 1 : CATCH_REQUIRE(range1.is_range());
1032 1 : CATCH_REQUIRE_FALSE(range1.is_empty());
1033 1 : CATCH_REQUIRE(range2.is_range());
1034 1 : CATCH_REQUIRE_FALSE(range2.is_empty());
1035 :
1036 2 : addr::addr_range const range3(range1.intersection(range2));
1037 :
1038 1 : CATCH_REQUIRE(range3.is_range());
1039 1 : CATCH_REQUIRE(range3.is_empty());
1040 :
1041 : // although it is "empty" we know the IPs and can test them
1042 : //
1043 1 : CATCH_REQUIRE(range3.get_from().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.10.0.0");
1044 1 : CATCH_REQUIRE(range3.get_to().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.5.255.255");
1045 :
1046 2 : addr::addr_range::vector_t rlist;
1047 1 : rlist.push_back(range1);
1048 1 : rlist.push_back(range2);
1049 1 : CATCH_REQUIRE(addr::address_match_ranges(rlist, f1));
1050 1 : CATCH_REQUIRE(addr::address_match_ranges(rlist, f2));
1051 1 : CATCH_REQUIRE(addr::address_match_ranges(rlist, t1));
1052 1 : CATCH_REQUIRE(addr::address_match_ranges(rlist, t2));
1053 : }
1054 : CATCH_END_SECTION()
1055 : }
1056 :
1057 28 : CATCH_GIVEN("check for union of two ranges")
1058 : {
1059 6 : CATCH_START_SECTION("addr_range: union of two ranges that overlap")
1060 : {
1061 : // from 10.1.0.0
1062 1 : struct sockaddr_in f1in = sockaddr_in();
1063 1 : f1in.sin_family = AF_INET;
1064 1 : f1in.sin_port = htons(rand());
1065 1 : uint32_t f1address((10 << 24)
1066 : | (1 << 16)
1067 : | (0 << 8)
1068 : | 0);
1069 1 : f1in.sin_addr.s_addr = htonl(f1address);
1070 2 : addr::addr f1;
1071 1 : f1.set_ipv4(f1in);
1072 :
1073 : // to 10.5.255.255
1074 1 : struct sockaddr_in t1in = sockaddr_in();
1075 1 : t1in.sin_family = AF_INET;
1076 1 : t1in.sin_port = htons(rand());
1077 1 : uint32_t t1address((10 << 24)
1078 : | (5 << 16)
1079 : | (255 << 8)
1080 : | 255);
1081 1 : t1in.sin_addr.s_addr = htonl(t1address);
1082 2 : addr::addr t1;
1083 1 : t1.set_ipv4(t1in);
1084 :
1085 : // from is set to 10.2.0.0
1086 1 : struct sockaddr_in f2in = sockaddr_in();
1087 1 : f2in.sin_family = AF_INET;
1088 1 : f2in.sin_port = htons(rand());
1089 1 : uint32_t f2address((10 << 24)
1090 : | (2 << 16)
1091 : | (0 << 8)
1092 : | 0);
1093 1 : f2in.sin_addr.s_addr = htonl(f2address);
1094 2 : addr::addr f2;
1095 1 : f2.set_ipv4(f2in);
1096 :
1097 : // from is set to 10.10.255.255
1098 1 : struct sockaddr_in t2in = sockaddr_in();
1099 1 : t2in.sin_family = AF_INET;
1100 1 : t2in.sin_port = htons(rand());
1101 1 : uint32_t t2address((10 << 24)
1102 : | (10 << 16)
1103 : | (255 << 8)
1104 : | 255);
1105 1 : t2in.sin_addr.s_addr = htonl(t2address);
1106 2 : addr::addr t2;
1107 1 : t2.set_ipv4(t2in);
1108 :
1109 2 : addr::addr_range range1;
1110 2 : addr::addr_range range2;
1111 :
1112 : {
1113 2 : addr::addr_range const r(range1.union_if_possible(range2));
1114 1 : CATCH_REQUIRE_FALSE(r.is_defined());
1115 : }
1116 : {
1117 2 : addr::addr_range const r(range2.union_if_possible(range1));
1118 1 : CATCH_REQUIRE_FALSE(r.is_defined());
1119 : }
1120 :
1121 1 : range1.set_from(f1);
1122 :
1123 : {
1124 2 : addr::addr_range const r(range1.union_if_possible(range2));
1125 1 : CATCH_REQUIRE_FALSE(r.is_defined());
1126 : }
1127 : {
1128 2 : addr::addr_range const r(range2.union_if_possible(range1));
1129 1 : CATCH_REQUIRE_FALSE(r.is_defined());
1130 : }
1131 : {
1132 2 : addr::addr_range const r(range1.union_if_possible(range1));
1133 1 : CATCH_REQUIRE(r.is_defined());
1134 1 : CATCH_REQUIRE_FALSE(r.is_range());
1135 1 : CATCH_REQUIRE_FALSE(r.is_empty());
1136 1 : CATCH_REQUIRE(r.has_from());
1137 1 : CATCH_REQUIRE_FALSE(r.has_to());
1138 1 : CATCH_REQUIRE(r.get_from().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.1.0.0");
1139 : }
1140 :
1141 1 : range2.set_from(f2);
1142 :
1143 : {
1144 2 : addr::addr_range const r(range1.union_if_possible(range2));
1145 1 : CATCH_REQUIRE_FALSE(r.is_defined());
1146 1 : CATCH_REQUIRE_FALSE(r.is_range());
1147 1 : CATCH_REQUIRE_FALSE(r.is_empty());
1148 1 : CATCH_REQUIRE_FALSE(r.has_from());
1149 1 : CATCH_REQUIRE_FALSE(r.has_to());
1150 : }
1151 : {
1152 2 : addr::addr_range const r(range2.union_if_possible(range1));
1153 1 : CATCH_REQUIRE_FALSE(r.is_defined());
1154 1 : CATCH_REQUIRE_FALSE(r.is_range());
1155 1 : CATCH_REQUIRE_FALSE(r.is_empty());
1156 1 : CATCH_REQUIRE_FALSE(r.has_from());
1157 1 : CATCH_REQUIRE_FALSE(r.has_to());
1158 : }
1159 :
1160 1 : range1.set_to(t1);
1161 :
1162 : {
1163 2 : addr::addr_range const r(range1.union_if_possible(range2));
1164 1 : CATCH_REQUIRE(r.is_defined());
1165 1 : CATCH_REQUIRE(r.is_range());
1166 1 : CATCH_REQUIRE_FALSE(r.is_empty());
1167 1 : CATCH_REQUIRE(r.has_from());
1168 1 : CATCH_REQUIRE(r.has_to());
1169 1 : CATCH_REQUIRE(r.get_from().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.1.0.0");
1170 1 : CATCH_REQUIRE(r.get_to().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.5.255.255");
1171 : }
1172 : {
1173 2 : addr::addr_range const r(range2.union_if_possible(range1));
1174 1 : CATCH_REQUIRE(r.is_defined());
1175 1 : CATCH_REQUIRE(r.is_range());
1176 1 : CATCH_REQUIRE_FALSE(r.is_empty());
1177 1 : CATCH_REQUIRE(r.has_from());
1178 1 : CATCH_REQUIRE(r.has_to());
1179 1 : CATCH_REQUIRE(r.get_from().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.1.0.0");
1180 1 : CATCH_REQUIRE(r.get_to().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.5.255.255");
1181 : }
1182 :
1183 1 : range2.set_to(t2);
1184 :
1185 1 : CATCH_REQUIRE(range1.compare(range2) == addr::compare_t::COMPARE_OVERLAP_SMALL_VS_LARGE);
1186 1 : CATCH_REQUIRE(range2.compare(range1) == addr::compare_t::COMPARE_OVERLAP_LARGE_VS_SMALL);
1187 :
1188 1 : CATCH_REQUIRE(range1.is_range());
1189 1 : CATCH_REQUIRE_FALSE(range1.is_empty());
1190 1 : CATCH_REQUIRE(range2.is_range());
1191 1 : CATCH_REQUIRE_FALSE(range2.is_empty());
1192 :
1193 : {
1194 2 : addr::addr_range const r(range1.union_if_possible(range2));
1195 1 : CATCH_REQUIRE(r.is_defined());
1196 1 : CATCH_REQUIRE(r.is_range());
1197 1 : CATCH_REQUIRE_FALSE(r.is_empty());
1198 1 : CATCH_REQUIRE(r.has_from());
1199 1 : CATCH_REQUIRE(r.has_to());
1200 1 : CATCH_REQUIRE(r.get_from().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.1.0.0");
1201 1 : CATCH_REQUIRE(r.get_to().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.10.255.255");
1202 :
1203 1 : CATCH_REQUIRE(range1.compare(r) == addr::compare_t::COMPARE_INCLUDES);
1204 1 : CATCH_REQUIRE(r.compare(range1) == addr::compare_t::COMPARE_INCLUDED);
1205 1 : CATCH_REQUIRE(range2.compare(r) == addr::compare_t::COMPARE_INCLUDES);
1206 1 : CATCH_REQUIRE(r.compare(range2) == addr::compare_t::COMPARE_INCLUDED);
1207 : }
1208 : }
1209 : CATCH_END_SECTION()
1210 :
1211 6 : CATCH_START_SECTION("addr_range: union of two ranges that touch")
1212 : {
1213 : // from 10.1.0.0
1214 1 : struct sockaddr_in f1in = sockaddr_in();
1215 1 : f1in.sin_family = AF_INET;
1216 1 : f1in.sin_port = htons(rand());
1217 1 : uint32_t f1address((10 << 24)
1218 : | (1 << 16)
1219 : | (0 << 8)
1220 : | 0);
1221 1 : f1in.sin_addr.s_addr = htonl(f1address);
1222 2 : addr::addr f1;
1223 1 : f1.set_ipv4(f1in);
1224 :
1225 : // to 10.5.32.21
1226 1 : struct sockaddr_in t1in = sockaddr_in();
1227 1 : t1in.sin_family = AF_INET;
1228 1 : t1in.sin_port = htons(rand());
1229 1 : uint32_t t1address((10 << 24)
1230 : | (5 << 16)
1231 : | (32 << 8)
1232 : | 21);
1233 1 : t1in.sin_addr.s_addr = htonl(t1address);
1234 2 : addr::addr t1;
1235 1 : t1.set_ipv4(t1in);
1236 :
1237 : // from is set to 10.5.32.22
1238 1 : struct sockaddr_in f2in = sockaddr_in();
1239 1 : f2in.sin_family = AF_INET;
1240 1 : f2in.sin_port = htons(rand());
1241 1 : uint32_t f2address((10 << 24)
1242 : | (5 << 16)
1243 : | (32 << 8)
1244 : | 22);
1245 1 : f2in.sin_addr.s_addr = htonl(f2address);
1246 2 : addr::addr f2;
1247 1 : f2.set_ipv4(f2in);
1248 :
1249 : // from is set to 10.11.255.255
1250 1 : struct sockaddr_in t2in = sockaddr_in();
1251 1 : t2in.sin_family = AF_INET;
1252 1 : t2in.sin_port = htons(rand());
1253 1 : uint32_t t2address((10 << 24)
1254 : | (11 << 16)
1255 : | (255 << 8)
1256 : | 255);
1257 1 : t2in.sin_addr.s_addr = htonl(t2address);
1258 2 : addr::addr t2;
1259 1 : t2.set_ipv4(t2in);
1260 :
1261 2 : addr::addr_range range1;
1262 1 : range1.set_from(f1);
1263 1 : range1.set_to(t1);
1264 :
1265 2 : addr::addr_range range2;
1266 1 : range2.set_from(f2);
1267 1 : range2.set_to(t2);
1268 :
1269 1 : CATCH_REQUIRE(range1.is_range());
1270 1 : CATCH_REQUIRE_FALSE(range1.is_empty());
1271 1 : CATCH_REQUIRE(range2.is_range());
1272 1 : CATCH_REQUIRE_FALSE(range2.is_empty());
1273 :
1274 : // the intersection is going to be empty (nothing overlaps)
1275 : //
1276 2 : addr::addr_range const range3(range1.intersection(range2));
1277 :
1278 1 : CATCH_REQUIRE(range3.is_range());
1279 1 : CATCH_REQUIRE(range3.is_empty());
1280 :
1281 : // the union works as expected
1282 : //
1283 2 : addr::addr_range const range4(range1.union_if_possible(range2));
1284 :
1285 1 : CATCH_REQUIRE(range4.is_range());
1286 1 : CATCH_REQUIRE_FALSE(range4.is_empty());
1287 :
1288 1 : CATCH_REQUIRE(range4.get_from().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.1.0.0");
1289 1 : CATCH_REQUIRE(range4.get_to().to_ipv4_string(addr::string_ip_t::STRING_IP_ONLY) == "10.11.255.255");
1290 : }
1291 : CATCH_END_SECTION()
1292 :
1293 6 : CATCH_START_SECTION("addr_range: union two ranges that do not overlap")
1294 : {
1295 : // from 10.1.0.0
1296 1 : struct sockaddr_in f1in = sockaddr_in();
1297 1 : f1in.sin_family = AF_INET;
1298 1 : int const f1port(rand() & 0xFFFF);
1299 1 : f1in.sin_port = htons(f1port);
1300 1 : uint32_t const f1address((10 << 24)
1301 : | (1 << 16)
1302 : | (0 << 8)
1303 : | 0);
1304 1 : f1in.sin_addr.s_addr = htonl(f1address);
1305 2 : addr::addr f1;
1306 1 : f1.set_ipv4(f1in);
1307 :
1308 : // to 10.1.0.255
1309 1 : struct sockaddr_in t1in = sockaddr_in();
1310 1 : t1in.sin_family = AF_INET;
1311 1 : int const t1port(rand() & 0xFFFF);
1312 1 : t1in.sin_port = htons(t1port);
1313 1 : uint32_t const t1address((10 << 24)
1314 : | (1 << 16)
1315 : | (0 << 8)
1316 : | 255);
1317 1 : t1in.sin_addr.s_addr = htonl(t1address);
1318 2 : addr::addr t1;
1319 1 : t1.set_ipv4(t1in);
1320 :
1321 : // from 10.10.0.0
1322 1 : struct sockaddr_in f2in = sockaddr_in();
1323 1 : f2in.sin_family = AF_INET;
1324 1 : int const f2port(rand() & 0xFFFF);
1325 1 : f2in.sin_port = htons(f2port);
1326 1 : uint32_t const f2address((10 << 24)
1327 : | (10 << 16)
1328 : | (0 << 8)
1329 : | 0);
1330 1 : f2in.sin_addr.s_addr = htonl(f2address);
1331 2 : addr::addr f2;
1332 1 : f2.set_ipv4(f2in);
1333 :
1334 : // to 10.10.1.255
1335 1 : struct sockaddr_in t2in = sockaddr_in();
1336 1 : t2in.sin_family = AF_INET;
1337 1 : int const t2port(rand() & 0xFFFF);
1338 1 : t2in.sin_port = htons(t2port);
1339 1 : uint32_t const t2address((10 << 24)
1340 : | (10 << 16)
1341 : | (1 << 8)
1342 : | 255);
1343 1 : t2in.sin_addr.s_addr = htonl(t2address);
1344 2 : addr::addr t2;
1345 1 : t2.set_ipv4(t2in);
1346 :
1347 2 : addr::addr_range range1;
1348 1 : range1.set_from(f1);
1349 1 : range1.set_to(t1);
1350 :
1351 2 : addr::addr_range range2;
1352 1 : range2.set_from(f2);
1353 1 : range2.set_to(t2);
1354 :
1355 1 : CATCH_REQUIRE(range1.is_range());
1356 1 : CATCH_REQUIRE_FALSE(range1.is_empty());
1357 1 : CATCH_REQUIRE(range2.is_range());
1358 1 : CATCH_REQUIRE_FALSE(range2.is_empty());
1359 :
1360 2 : addr::addr_range const range3(range1.union_if_possible(range2));
1361 :
1362 1 : CATCH_REQUIRE_FALSE(range3.is_range());
1363 1 : CATCH_REQUIRE_FALSE(range3.is_empty());
1364 :
1365 2 : std::string vec_result;
1366 2 : std::string vec_result_ip_only;
1367 : {
1368 2 : std::stringstream ss;
1369 1 : ss << range1;
1370 2 : std::string const range1_result("10.1.0.0-10.1.0.255:" + std::to_string(t1port) + "/32");
1371 1 : CATCH_REQUIRE(ss.str() == range1_result);
1372 1 : vec_result += range1_result;
1373 1 : vec_result_ip_only += "10.1.0.0-10.1.0.255";
1374 : }
1375 : {
1376 2 : std::stringstream ss;
1377 1 : ss << range2;
1378 2 : std::string const range2_result("10.10.0.0-10.10.1.255:" + std::to_string(t2port) + "/32");
1379 1 : CATCH_REQUIRE(ss.str() == range2_result);
1380 1 : vec_result += ',';
1381 1 : vec_result += range2_result;
1382 1 : vec_result_ip_only += ',';
1383 1 : vec_result_ip_only += "10.10.0.0-10.10.1.255";
1384 : }
1385 : {
1386 2 : std::stringstream ss;
1387 1 : ss << addr::setaddrmode(addr::string_ip_t::STRING_IP_MASK) << range3;
1388 2 : std::string const range3_result("<empty address range>");
1389 1 : CATCH_REQUIRE(ss.str() == range3_result);
1390 1 : vec_result += ',';
1391 1 : vec_result += range3_result;
1392 1 : vec_result_ip_only += ',';
1393 1 : vec_result_ip_only += "<empty address range>";
1394 : }
1395 : {
1396 2 : addr::addr_range::vector_t vec{ range1, range2, range3 };
1397 2 : std::stringstream ss;
1398 1 : ss << vec;
1399 1 : CATCH_REQUIRE(ss.str() == vec_result);
1400 :
1401 2 : std::stringstream sm;
1402 1 : sm << addr::setaddrmode(addr::string_ip_t::STRING_IP_ONLY) << vec;
1403 1 : CATCH_REQUIRE(sm.str() == vec_result_ip_only);
1404 :
1405 2 : addr::addr::vector_t all_addresses(addr::addr_range::to_addresses(vec, 1000));
1406 :
1407 : // the first 256 are 10.1.0.0 to 10.1.0.255
1408 : //
1409 257 : for(int idx(0); idx < 256; ++idx)
1410 : {
1411 256 : struct sockaddr_in v1in = sockaddr_in();
1412 256 : v1in.sin_family = AF_INET;
1413 256 : int const v1port(rand() & 0xFFFF);
1414 256 : v1in.sin_port = htons(v1port);
1415 256 : uint32_t const v1address((10 << 24)
1416 : | (1 << 16)
1417 : | (0 << 8)
1418 256 : | idx);
1419 256 : v1in.sin_addr.s_addr = htonl(v1address);
1420 512 : addr::addr v1;
1421 256 : v1.set_ipv4(v1in);
1422 :
1423 256 : CATCH_REQUIRE(all_addresses[idx] == v1);
1424 : }
1425 :
1426 : // the following 512 are 10.10.0.0 to 10.10.1.255
1427 : //
1428 513 : for(int idx(0); idx < 512; ++idx)
1429 : {
1430 512 : struct sockaddr_in v2in = sockaddr_in();
1431 512 : v2in.sin_family = AF_INET;
1432 512 : int const v2port(rand() & 0xFFFF);
1433 512 : v2in.sin_port = htons(v2port);
1434 512 : uint32_t const v2address((10 << 24)
1435 : | (10 << 16)
1436 : | (0 << 8)
1437 512 : | idx); // this one leaks in the next as expected
1438 512 : v2in.sin_addr.s_addr = htonl(v2address);
1439 1024 : addr::addr v2;
1440 512 : v2.set_ipv4(v2in);
1441 :
1442 512 : CATCH_REQUIRE(all_addresses[idx + 256] == v2);
1443 : }
1444 :
1445 1 : CATCH_REQUIRE_THROWS_MATCHES(
1446 : addr::addr_range::to_addresses(vec, 256 + 512 - 1)
1447 : , addr::out_of_range
1448 : , Catch::Matchers::ExceptionMessage(
1449 : "out_of_range: too many addresses in this range: 768 > 767"));
1450 : }
1451 : }
1452 : CATCH_END_SECTION()
1453 : }
1454 20 : }
1455 :
1456 :
1457 :
1458 : // vim: ts=4 sw=4 et
|