Line data Source code
1 : // Copyright (c) 2011-2021 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // Project: https://snapwebsites.org/project/libaddr
4 : //
5 : // Permission is hereby granted, free of charge, to any
6 : // person obtaining a copy of this software and
7 : // associated documentation files (the "Software"), to
8 : // deal in the Software without restriction, including
9 : // without limitation the rights to use, copy, modify,
10 : // merge, publish, distribute, sublicense, and/or sell
11 : // copies of the Software, and to permit persons to whom
12 : // the Software is furnished to do so, subject to the
13 : // following conditions:
14 : //
15 : // The above copyright notice and this permission notice
16 : // shall be included in all copies or substantial
17 : // portions of the Software.
18 : //
19 : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
20 : // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
21 : // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
22 : // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
23 : // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 : // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 : // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26 : // ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 : // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 : // SOFTWARE.
29 :
30 :
31 : /** \file
32 : * \brief Test the IPv4 interface.
33 : *
34 : * These test verify that the IPv4 side of things function as expected.
35 : *
36 : * Note that some of the tests between the IPv4 and IPv6 overlap. Here
37 : * you mainly find the IPv4 side of things.
38 : */
39 :
40 : // self
41 : //
42 : #include "catch_main.h"
43 :
44 :
45 : // addr lib
46 : //
47 : #include <libaddr/iface.h>
48 :
49 :
50 : // last include
51 : //
52 : #include <snapdev/poison.h>
53 :
54 :
55 :
56 :
57 : /** \brief Details used by the addr class implementation.
58 : *
59 : * We have a function to check whether an address is part of
60 : * the interfaces of your computer. This check requires the
61 : * use of a `struct ifaddrs` and as such it requires to
62 : * delete that structure. We define a deleter for that
63 : * strucure here.
64 : */
65 : namespace
66 : {
67 :
68 : /** \brief Close a socket.
69 : *
70 : * This deleter is used to make sure all the socket we test get closed
71 : * on exit.
72 : *
73 : * \param[in] s The socket to close.
74 : */
75 4 : void socket_deleter(int * s)
76 : {
77 4 : close(*s);
78 4 : }
79 :
80 :
81 : }
82 : // no name namespace
83 :
84 :
85 :
86 17 : CATCH_TEST_CASE( "ipv4::invalid_input", "[ipv4]" )
87 : {
88 30 : CATCH_GIVEN("addr()")
89 : {
90 1 : addr::addr a;
91 :
92 2 : CATCH_SECTION("set IPv4 with an invalid family")
93 : {
94 26 : for(int idx(0); idx < 25; ++idx)
95 : {
96 25 : struct sockaddr_in in = sockaddr_in();
97 0 : do
98 : {
99 25 : in.sin_family = rand();
100 : }
101 25 : while(in.sin_family == AF_INET);
102 25 : in.sin_port = htons(rand());
103 25 : in.sin_addr.s_addr = htonl(rand() ^ (rand() << 16));
104 25 : CATCH_REQUIRE_THROWS_AS(a.set_ipv4(in), addr::addr_invalid_argument);
105 25 : CATCH_REQUIRE_THROWS_AS(addr::addr(in), addr::addr_invalid_argument);
106 : }
107 : }
108 : }
109 :
110 30 : CATCH_GIVEN("addr_parser() with IPv4 settings")
111 : {
112 4 : addr::addr_parser a;
113 :
114 4 : CATCH_SECTION("invalid allow flags (too small)")
115 : {
116 11 : for(int idx(0); idx < 10; ++idx)
117 : {
118 : // test with a negative number
119 : //
120 : int n;
121 0 : do
122 : {
123 10 : n = rand();
124 : }
125 10 : while(n == 0);
126 10 : if(n > 0)
127 : {
128 : // all positive numbers have a corresponding negative
129 : // number so this always flips the sign as expected
130 : //
131 10 : n = -n;
132 : }
133 10 : addr::addr_parser::flag_t const flag(static_cast<addr::addr_parser::flag_t>(n));
134 :
135 10 : CATCH_REQUIRE_THROWS_AS(a.set_allow(flag, true), addr::addr_invalid_argument);
136 10 : CATCH_REQUIRE_THROWS_AS(a.set_allow(flag, false), addr::addr_invalid_argument);
137 10 : CATCH_REQUIRE_THROWS_AS(a.get_allow(flag), addr::addr_invalid_argument);
138 : }
139 : }
140 :
141 4 : CATCH_SECTION("invalid allow flags (too large)")
142 : {
143 11 : for(int idx(0); idx < 10; ++idx)
144 : {
145 : // test with a negative number
146 : //
147 : int n;
148 0 : do
149 : {
150 10 : n = rand();
151 10 : if(n < 0)
152 : {
153 0 : n = -n;
154 : }
155 : }
156 10 : while(n < static_cast<int>(addr::addr_parser::flag_t::FLAG_max));
157 10 : addr::addr_parser::flag_t const flag(static_cast<addr::addr_parser::flag_t>(n));
158 :
159 10 : CATCH_REQUIRE_THROWS_AS(a.set_allow(flag, true), addr::addr_invalid_argument);
160 10 : CATCH_REQUIRE_THROWS_AS(a.set_allow(flag, false), addr::addr_invalid_argument);
161 10 : CATCH_REQUIRE_THROWS_AS(a.get_allow(flag), addr::addr_invalid_argument);
162 : }
163 : }
164 : }
165 :
166 30 : CATCH_GIVEN("addr_parser() with IPv4 addresses")
167 : {
168 4 : CATCH_SECTION("bad address")
169 : {
170 2 : addr::addr_parser p;
171 2 : addr::addr_range::vector_t ips(p.parse("{bad-ip}"));
172 1 : CATCH_REQUIRE(p.has_errors());
173 1 : CATCH_REQUIRE(p.error_count() == 1);
174 1 : CATCH_REQUIRE(p.error_messages() == "Invalid address in \"{bad-ip}\" error -2 -- Name or service not known (errno: 2 -- No such file or directory).\n");
175 1 : CATCH_REQUIRE(p.has_errors());
176 1 : p.clear_errors();
177 1 : CATCH_REQUIRE_FALSE(p.has_errors());
178 1 : CATCH_REQUIRE(ips.size() == 0);
179 : }
180 :
181 4 : CATCH_SECTION("required address")
182 : {
183 2 : addr::addr_parser p;
184 1 : p.set_protocol(IPPROTO_TCP);
185 1 : p.set_allow(addr::addr_parser::flag_t::REQUIRED_ADDRESS, true);
186 2 : addr::addr_range::vector_t ips(p.parse(""));
187 1 : CATCH_REQUIRE(p.has_errors());
188 1 : CATCH_REQUIRE(p.error_count() == 1);
189 1 : CATCH_REQUIRE(p.error_messages() == "Required address is missing.\n");
190 1 : CATCH_REQUIRE(p.has_errors());
191 1 : p.clear_errors();
192 1 : CATCH_REQUIRE_FALSE(p.has_errors());
193 1 : CATCH_REQUIRE(ips.size() == 0);
194 : }
195 : }
196 :
197 30 : CATCH_GIVEN("addr_parser() with IPv4 ports")
198 : {
199 6 : CATCH_SECTION("required port")
200 : {
201 : // optional + required -> required
202 : {
203 2 : addr::addr_parser p;
204 1 : p.set_protocol(IPPROTO_TCP);
205 1 : p.set_allow(addr::addr_parser::flag_t::REQUIRED_PORT, true);
206 2 : addr::addr_range::vector_t ips(p.parse("1.2.3.4"));
207 1 : CATCH_REQUIRE(p.has_errors());
208 1 : CATCH_REQUIRE(p.error_count() == 1);
209 1 : CATCH_REQUIRE(p.error_messages() == "Required port is missing.\n");
210 1 : CATCH_REQUIRE(p.has_errors());
211 1 : p.clear_errors();
212 1 : CATCH_REQUIRE_FALSE(p.has_errors());
213 1 : CATCH_REQUIRE(ips.size() == 0);
214 : }
215 :
216 : // only required -> required just the same
217 : {
218 2 : addr::addr_parser p;
219 1 : p.set_protocol(IPPROTO_TCP);
220 1 : p.set_allow(addr::addr_parser::flag_t::PORT, false);
221 1 : p.set_allow(addr::addr_parser::flag_t::REQUIRED_PORT, true);
222 2 : addr::addr_range::vector_t ips(p.parse("1.2.3.4"));
223 1 : CATCH_REQUIRE(p.has_errors());
224 1 : CATCH_REQUIRE(p.error_count() == 1);
225 1 : CATCH_REQUIRE(p.error_messages() == "Required port is missing.\n");
226 1 : CATCH_REQUIRE(p.has_errors());
227 1 : p.clear_errors();
228 1 : CATCH_REQUIRE_FALSE(p.has_errors());
229 1 : CATCH_REQUIRE(ips.size() == 0);
230 : }
231 : }
232 :
233 6 : CATCH_SECTION("port not allowed")
234 : {
235 2 : addr::addr_parser p;
236 1 : p.set_protocol(IPPROTO_TCP);
237 1 : p.set_allow(addr::addr_parser::flag_t::PORT, false);
238 1 : CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::REQUIRED_PORT));
239 2 : addr::addr_range::vector_t ips(p.parse("1.2.3.4:123"));
240 1 : CATCH_REQUIRE(p.has_errors());
241 1 : CATCH_REQUIRE(p.error_count() == 1);
242 1 : CATCH_REQUIRE(p.error_messages() == "Port not allowed (1.2.3.4:123).\n");
243 1 : CATCH_REQUIRE(p.has_errors());
244 1 : p.clear_errors();
245 1 : CATCH_REQUIRE_FALSE(p.has_errors());
246 1 : CATCH_REQUIRE(ips.size() == 0);
247 : }
248 :
249 6 : CATCH_SECTION("invalid port")
250 : {
251 2 : addr::addr_parser p;
252 :
253 : // so to a different default value
254 : //
255 1 : int const default_port(rand() & 0xFFFF);
256 1 : p.set_default_port(default_port);
257 :
258 26 : for(int idx(0); idx < 25; ++idx)
259 : {
260 : int port;
261 0 : do
262 : {
263 25 : port = rand() ^ (rand() << 16);
264 : }
265 25 : while(port >= -1 && port <= 65535); // -1 is valid here, it represents "no default port defined"
266 25 : CATCH_REQUIRE_THROWS_AS(p.set_default_port(port), addr::addr_invalid_argument);
267 :
268 : // verify port unchanged
269 : //
270 25 : CATCH_REQUIRE(p.get_default_port() == default_port);
271 : }
272 : }
273 : }
274 :
275 30 : CATCH_GIVEN("addr_parser() with invalid masks")
276 : {
277 10 : CATCH_SECTION("really large numbers (over 1000)")
278 : {
279 6 : for(int idx(0); idx < 5; ++idx)
280 : {
281 5 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
282 5 : int const port(rand() & 0xFFFF);
283 5 : int const mask((rand() & 0xFF) + 1001);
284 10 : addr::addr_parser p;
285 5 : p.set_protocol(proto);
286 5 : p.set_allow(p.flag_t::MASK, true);
287 10 : addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port) + "/" + std::to_string(mask)));
288 5 : CATCH_REQUIRE(p.has_errors());
289 5 : CATCH_REQUIRE(p.error_count() == 1);
290 5 : CATCH_REQUIRE(p.error_messages() == "Mask number too large (" + std::to_string(mask) + ", expected a maximum of 128).\n");
291 5 : CATCH_REQUIRE(ips.size() == 0);
292 : }
293 : }
294 :
295 10 : CATCH_SECTION("ipv4 mask is limited between 0 and 32")
296 : {
297 6 : for(int idx(0); idx < 5; ++idx)
298 : {
299 5 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
300 5 : int const port(rand() & 0xFFFF);
301 5 : int const mask((rand() & 0xFF) + 33);
302 10 : addr::addr_parser p;
303 5 : p.set_protocol(proto);
304 5 : p.set_allow(p.flag_t::MASK, true);
305 10 : addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port) + "/" + std::to_string(mask)));
306 5 : CATCH_REQUIRE(p.has_errors());
307 5 : CATCH_REQUIRE(p.error_count() == 1);
308 5 : CATCH_REQUIRE(p.error_messages() == "Unsupported mask size (" + std::to_string(mask) + ", expected 32 at the most for an IPv4).\n");
309 5 : CATCH_REQUIRE(ips.size() == 0);
310 : }
311 : }
312 :
313 10 : CATCH_SECTION("ipv4 mask cannot use name")
314 : {
315 6 : for(int idx(0); idx < 5; ++idx)
316 : {
317 5 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
318 5 : int const port(rand() & 0xFFFF);
319 10 : addr::addr_parser p;
320 5 : p.set_protocol(proto);
321 5 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
322 10 : addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port) + "/localhost"));
323 5 : CATCH_REQUIRE(p.has_errors());
324 5 : CATCH_REQUIRE(p.error_count() == 1);
325 5 : CATCH_REQUIRE(p.error_messages() == "Invalid mask in \"/localhost\", error -2 -- Name or service not known (errno: 0 -- Success).\n");
326 5 : CATCH_REQUIRE(ips.size() == 0);
327 : }
328 : }
329 :
330 10 : CATCH_SECTION("ipv4 mask mismatch (mask uses ipv6)")
331 : {
332 1 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
333 1 : int const port(rand() & 0xFFFF);
334 2 : addr::addr_parser p;
335 1 : p.set_protocol(proto);
336 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
337 2 : addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port) + "/[1:2:3:4:5:6:7:8]"));
338 1 : CATCH_REQUIRE(p.has_errors());
339 1 : CATCH_REQUIRE(p.error_count() == 1);
340 1 : CATCH_REQUIRE(p.error_messages() == "The address uses the IPv4 syntax, the mask cannot use IPv6.\n");
341 1 : CATCH_REQUIRE(ips.size() == 0);
342 : }
343 :
344 10 : CATCH_SECTION("ipv4 mask mismatch (mask uses ipv6 without [...])")
345 : {
346 1 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
347 1 : int const port(rand() & 0xFFFF);
348 2 : addr::addr_parser p;
349 1 : p.set_protocol(proto);
350 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
351 2 : addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port) + "/1:2:3:4:5:6:7:8"));
352 1 : CATCH_REQUIRE(p.has_errors());
353 1 : CATCH_REQUIRE(p.error_count() == 1);
354 1 : CATCH_REQUIRE(p.error_messages() == "Incompatible address between the address and mask address (first was an IPv4 second an IPv6).\n");
355 1 : CATCH_REQUIRE(ips.size() == 0);
356 : }
357 : }
358 :
359 30 : CATCH_GIVEN("addr_parser() with invalid protocols")
360 : {
361 4 : CATCH_SECTION("invalid names")
362 : {
363 2 : addr::addr_parser p;
364 :
365 : // not changing default protocol
366 : //
367 1 : CATCH_REQUIRE(p.get_protocol() == -1);
368 1 : CATCH_REQUIRE_THROWS_AS(p.set_protocol("igmp"), addr::addr_invalid_argument);
369 1 : CATCH_REQUIRE(p.get_protocol() == -1);
370 :
371 : // change protocol to another valid value first
372 : //
373 1 : p.set_protocol("tcp");
374 1 : CATCH_REQUIRE_THROWS_AS(p.set_protocol("icmp"), addr::addr_invalid_argument);
375 1 : CATCH_REQUIRE(p.get_protocol() == IPPROTO_TCP);
376 : }
377 :
378 4 : CATCH_SECTION("invalid numbers")
379 : {
380 101 : for(int idx(0); idx < 100; ++idx)
381 : {
382 : int protocol;
383 0 : do
384 : {
385 100 : protocol = rand();
386 : }
387 : while(protocol == IPPROTO_IP
388 100 : || protocol == IPPROTO_TCP
389 200 : || protocol == IPPROTO_UDP);
390 :
391 200 : addr::addr_parser p;
392 :
393 100 : CATCH_REQUIRE_THROWS_AS(p.set_protocol(protocol), addr::addr_invalid_argument);
394 100 : CATCH_REQUIRE(p.get_protocol() == -1);
395 :
396 : // change protocol to another valid value first
397 : //
398 100 : p.set_protocol("tcp");
399 100 : CATCH_REQUIRE_THROWS_AS(p.set_protocol(protocol), addr::addr_invalid_argument);
400 100 : CATCH_REQUIRE(p.get_protocol() == IPPROTO_TCP);
401 : }
402 : }
403 : }
404 15 : }
405 :
406 :
407 11 : CATCH_TEST_CASE( "ipv4::addr", "[ipv4]" )
408 : {
409 18 : CATCH_GIVEN("addr()")
410 : {
411 9 : addr::addr a;
412 :
413 18 : CATCH_SECTION("not an IPv4")
414 : {
415 1 : CATCH_REQUIRE_FALSE(a.is_ipv4());
416 :
417 1 : struct sockaddr_in in;
418 1 : CATCH_REQUIRE_THROWS_AS(a.get_ipv4(in), addr::addr_invalid_state);
419 1 : CATCH_REQUIRE_THROWS_AS(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY), addr::addr_invalid_state);
420 1 : CATCH_REQUIRE_THROWS_AS(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_BRACKETS), addr::addr_invalid_state);
421 1 : CATCH_REQUIRE_THROWS_AS(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_PORT), addr::addr_invalid_state);
422 1 : CATCH_REQUIRE_THROWS_AS(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_MASK), addr::addr_invalid_state);
423 1 : CATCH_REQUIRE_THROWS_AS(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_BRACKETS_MASK), addr::addr_invalid_state);
424 1 : CATCH_REQUIRE_THROWS_AS(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL), addr::addr_invalid_state);
425 : }
426 :
427 18 : CATCH_SECTION("default network type (0.0.0.0)")
428 : {
429 1 : CATCH_REQUIRE(a.is_default());
430 1 : CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_ANY);
431 1 : CATCH_REQUIRE(a.get_network_type_string() == "Any");
432 : }
433 :
434 18 : CATCH_SECTION("IPv6 ANY")
435 : {
436 1 : struct sockaddr_in6 in6;
437 1 : a.get_ipv6(in6);
438 1 : CATCH_REQUIRE(in6.sin6_addr.s6_addr32[0] == 0);
439 1 : CATCH_REQUIRE(in6.sin6_addr.s6_addr32[1] == 0);
440 1 : CATCH_REQUIRE(in6.sin6_addr.s6_addr32[2] == 0);
441 1 : CATCH_REQUIRE(in6.sin6_addr.s6_addr32[3] == 0);
442 1 : CATCH_REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::");
443 1 : CATCH_REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[::]");
444 1 : CATCH_REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_PORT) == "[::]:0");
445 1 : CATCH_REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_MASK) == "::/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
446 1 : CATCH_REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS_MASK) == "[::]/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
447 1 : CATCH_REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == "[::]:0/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
448 : }
449 :
450 18 : CATCH_SECTION("IPv4 or IPv6 string")
451 : {
452 1 : CATCH_REQUIRE(a.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::");
453 1 : CATCH_REQUIRE(a.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[::]");
454 1 : CATCH_REQUIRE(a.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_PORT) == "[::]:0");
455 1 : CATCH_REQUIRE(a.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_MASK) == "::/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
456 1 : CATCH_REQUIRE(a.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS_MASK) == "[::]/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
457 1 : CATCH_REQUIRE(a.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == "[::]:0/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
458 : }
459 :
460 18 : CATCH_SECTION("interface determination")
461 : {
462 1 : CATCH_REQUIRE(addr::find_addr_interface(a, false) == nullptr);
463 1 : CATCH_REQUIRE(addr::find_addr_interface(a, true) != nullptr);
464 : }
465 :
466 18 : CATCH_SECTION("default name/service/port/protocol")
467 : {
468 1 : CATCH_REQUIRE(a.get_name() == std::string());
469 1 : CATCH_REQUIRE(a.get_service() == std::string());
470 1 : CATCH_REQUIRE(a.get_port() == 0);
471 1 : CATCH_REQUIRE(a.get_protocol() == IPPROTO_TCP);
472 : }
473 :
474 18 : CATCH_SECTION("compare with self")
475 : {
476 1 : CATCH_REQUIRE(a == a);
477 1 : CATCH_REQUIRE_FALSE(a != a);
478 1 : CATCH_REQUIRE_FALSE(a < a);
479 1 : CATCH_REQUIRE(a <= a);
480 1 : CATCH_REQUIRE_FALSE(a > a);
481 1 : CATCH_REQUIRE(a >= a);
482 : }
483 :
484 18 : CATCH_SECTION("compare with another 0.0.0.0")
485 : {
486 : {
487 1 : addr::addr b;
488 :
489 1 : CATCH_REQUIRE(a == b);
490 1 : CATCH_REQUIRE_FALSE(a != b);
491 1 : CATCH_REQUIRE_FALSE(a < b);
492 1 : CATCH_REQUIRE(a <= b);
493 1 : CATCH_REQUIRE_FALSE(a > b);
494 1 : CATCH_REQUIRE(a >= b);
495 : }
496 :
497 : {
498 1 : struct sockaddr_in6 in6 = sockaddr_in6();
499 1 : in6.sin6_family = AF_INET6;
500 1 : in6.sin6_port = htons(0);
501 1 : in6.sin6_addr.s6_addr32[0] = htonl(0);
502 1 : in6.sin6_addr.s6_addr32[1] = htonl(0);
503 1 : in6.sin6_addr.s6_addr32[2] = htonl(0);
504 1 : in6.sin6_addr.s6_addr32[3] = htonl(0);
505 1 : addr::addr b(in6);
506 :
507 1 : CATCH_REQUIRE(a == b);
508 1 : CATCH_REQUIRE_FALSE(a != b);
509 1 : CATCH_REQUIRE_FALSE(a < b);
510 1 : CATCH_REQUIRE(a <= b);
511 1 : CATCH_REQUIRE_FALSE(a > b);
512 1 : CATCH_REQUIRE(a >= b);
513 : }
514 :
515 : // ANY in IPv4 != ANY in IPv6...
516 : // (i.e. IPv4 sets addr.sin6_addr.s6_addr16[5] == 0xFFFF)
517 : {
518 1 : struct sockaddr_in in = sockaddr_in();
519 1 : in.sin_family = AF_INET;
520 1 : in.sin_port = htons(0);
521 1 : in.sin_addr.s_addr = htonl(0);
522 1 : addr::addr b(in);
523 :
524 1 : CATCH_REQUIRE_FALSE(a == b);
525 1 : CATCH_REQUIRE(a != b);
526 1 : CATCH_REQUIRE(a < b);
527 1 : CATCH_REQUIRE(a <= b);
528 1 : CATCH_REQUIRE_FALSE(a > b);
529 1 : CATCH_REQUIRE_FALSE(a >= b);
530 : }
531 : }
532 :
533 18 : CATCH_SECTION("compare with IPv4 127.0.0.1")
534 : {
535 1 : struct sockaddr_in in = sockaddr_in();
536 1 : in.sin_family = AF_INET;
537 1 : in.sin_port = htons(80);
538 1 : in.sin_addr.s_addr = htonl((127 << 24) | 1);
539 1 : addr::addr b(in);
540 :
541 1 : CATCH_REQUIRE_FALSE(a == b);
542 1 : CATCH_REQUIRE(a != b);
543 1 : CATCH_REQUIRE(a < b);
544 1 : CATCH_REQUIRE(a <= b);
545 1 : CATCH_REQUIRE_FALSE(a > b);
546 1 : CATCH_REQUIRE_FALSE(a >= b);
547 : }
548 : }
549 9 : }
550 :
551 :
552 15 : CATCH_TEST_CASE( "ipv4::address", "[ipv4]" )
553 : {
554 26 : CATCH_GIVEN("addr() with an IPv4")
555 : {
556 3 : addr::addr a;
557 :
558 6 : CATCH_SECTION("set_ipv4() / get_ipv4()")
559 : {
560 11 : for(int idx(0); idx < 10; ++idx)
561 : {
562 10 : struct sockaddr_in in = sockaddr_in();
563 10 : in.sin_family = AF_INET;
564 10 : in.sin_port = htons(rand());
565 10 : in.sin_addr.s_addr = htonl(rand() ^ (rand() << 16));
566 :
567 : // test constructor
568 : //
569 10 : addr::addr b(in);
570 10 : struct sockaddr_in out;
571 10 : b.get_ipv4(out);
572 10 : CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
573 :
574 : // test set
575 : //
576 10 : a.set_ipv4(in);
577 10 : a.get_ipv4(out);
578 10 : CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
579 : }
580 : }
581 :
582 6 : CATCH_SECTION("set_ipv4() / to_ipv4_string()")
583 : {
584 11 : for(int idx(0); idx < 10; ++idx)
585 : {
586 10 : struct sockaddr_in in = sockaddr_in();
587 10 : in.sin_family = AF_INET;
588 10 : uint16_t const port(rand());
589 10 : in.sin_port = htons(port);
590 10 : uint32_t const address(rand() ^ (rand() << 16));
591 10 : in.sin_addr.s_addr = htonl(address);
592 :
593 10 : std::string ip(
594 20 : std::to_string((address >> 24) & 255)
595 30 : + "."
596 40 : + std::to_string((address >> 16) & 255)
597 30 : + "."
598 40 : + std::to_string((address >> 8) & 255)
599 30 : + "."
600 20 : + std::to_string((address >> 0) & 255)
601 40 : );
602 20 : std::string port_str(std::to_string(static_cast<int>(port)));
603 :
604 : // check IPv4 as a string
605 : //
606 10 : a.set_ipv4(in);
607 10 : CATCH_REQUIRE(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == ip);
608 10 : CATCH_REQUIRE(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == ip);
609 10 : CATCH_REQUIRE(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_PORT) == ip + ":" + port_str);
610 10 : CATCH_REQUIRE(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_MASK) == ip + "/255.255.255.255"); // will change to 32 at some point
611 10 : CATCH_REQUIRE(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_BRACKETS_MASK) == ip + "/255.255.255.255");
612 10 : CATCH_REQUIRE(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == ip + ":" + port_str + "/255.255.255.255");
613 : }
614 : }
615 :
616 6 : CATCH_SECTION("name of various IPs")
617 : {
618 1 : struct sockaddr_in in = sockaddr_in();
619 1 : in.sin_family = AF_INET;
620 1 : in.sin_port = htons(rand());
621 1 : in.sin_addr.s_addr = 0;
622 :
623 : // verify network type
624 : //
625 1 : a.set_ipv4(in);
626 1 : CATCH_REQUIRE(a.get_name() == std::string()); // no name for "any" (TCP)
627 :
628 1 : a.set_protocol(IPPROTO_UDP);
629 1 : CATCH_REQUIRE(a.get_name() == std::string()); // no name for "any" (UDP)
630 :
631 1 : in.sin_addr.s_addr = htonl(0x7f000001);
632 1 : a.set_ipv4(in);
633 1 : char hostname[HOST_NAME_MAX + 1];
634 1 : hostname[HOST_NAME_MAX] = '\0';
635 1 : CATCH_REQUIRE(gethostname(hostname, sizeof(hostname)) == 0);
636 1 : CATCH_REQUIRE(hostname[0] != '\0');
637 2 : std::string localhost(a.get_name());
638 1 : bool const localhost_flag(localhost == hostname || localhost == "localhost");
639 1 : CATCH_REQUIRE(localhost_flag);
640 :
641 1 : CATCH_REQUIRE(addr::find_addr_interface(a, false) != nullptr);
642 : }
643 : }
644 :
645 26 : CATCH_GIVEN("addr_parser() with IPv4 addresses")
646 : {
647 14 : CATCH_SECTION("verify basics")
648 : {
649 2 : addr::addr_parser p;
650 1 : p.set_protocol(IPPROTO_TCP);
651 1 : CATCH_REQUIRE(p.get_default_address4() == "");
652 1 : CATCH_REQUIRE(p.get_default_address6() == "");
653 1 : CATCH_REQUIRE(p.get_default_port() == -1);
654 1 : CATCH_REQUIRE(p.get_default_mask4() == "");
655 1 : CATCH_REQUIRE(p.get_default_mask6() == "");
656 2 : addr::addr_range::vector_t ips(p.parse("1.2.3.4"));
657 1 : CATCH_REQUIRE_FALSE(p.has_errors());
658 1 : CATCH_REQUIRE(ips.size() == 1);
659 1 : addr::addr_range const & r(ips[0]);
660 1 : CATCH_REQUIRE(r.has_from());
661 1 : CATCH_REQUIRE_FALSE(r.has_to());
662 1 : CATCH_REQUIRE_FALSE(r.is_range());
663 1 : CATCH_REQUIRE_FALSE(r.is_empty());
664 1 : addr::addr f(r.get_from());
665 1 : CATCH_REQUIRE(f.is_ipv4());
666 1 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
667 1 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
668 1 : CATCH_REQUIRE(f.get_port() == 0);
669 1 : CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
670 1 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
671 1 : uint8_t mask[16] = {};
672 1 : f.get_mask(mask);
673 17 : for(int idx(0); idx < 16; ++idx)
674 : {
675 16 : CATCH_REQUIRE(mask[idx] == 255);
676 : }
677 : }
678 :
679 14 : CATCH_SECTION("verify default address")
680 : {
681 2 : addr::addr_parser p;
682 :
683 1 : p.set_default_address("1.5.19.200");
684 1 : CATCH_REQUIRE(p.get_default_address4() == "1.5.19.200");
685 1 : CATCH_REQUIRE(p.get_default_address6() == "");
686 1 : p.set_default_address("");
687 1 : CATCH_REQUIRE(p.get_default_address4() == "");
688 1 : CATCH_REQUIRE(p.get_default_address6() == "");
689 :
690 1 : p.set_default_address("1.5.19.200");
691 1 : CATCH_REQUIRE(p.get_default_address4() == "1.5.19.200");
692 1 : CATCH_REQUIRE(p.get_default_address6() == "");
693 1 : p.set_default_address("[4:5:4:5:7:8:7:8]");
694 1 : CATCH_REQUIRE(p.get_default_address4() == "1.5.19.200");
695 1 : CATCH_REQUIRE(p.get_default_address6() == "4:5:4:5:7:8:7:8");
696 1 : p.set_default_address("");
697 1 : CATCH_REQUIRE(p.get_default_address4() == "");
698 1 : CATCH_REQUIRE(p.get_default_address6() == "");
699 : }
700 :
701 14 : CATCH_SECTION("verify default mask")
702 : {
703 2 : addr::addr_parser p;
704 :
705 1 : p.set_default_mask("1.5.19.200");
706 1 : CATCH_REQUIRE(p.get_default_mask4() == "1.5.19.200");
707 1 : CATCH_REQUIRE(p.get_default_mask6() == "");
708 1 : p.set_default_mask("");
709 1 : CATCH_REQUIRE(p.get_default_mask4() == "");
710 1 : CATCH_REQUIRE(p.get_default_mask6() == "");
711 :
712 1 : p.set_default_mask("1.5.19.200");
713 1 : CATCH_REQUIRE(p.get_default_mask4() == "1.5.19.200");
714 1 : CATCH_REQUIRE(p.get_default_mask6() == "");
715 1 : p.set_default_mask("[4:5:4:5:7:8:7:8]");
716 1 : CATCH_REQUIRE(p.get_default_mask4() == "1.5.19.200");
717 1 : CATCH_REQUIRE(p.get_default_mask6() == "4:5:4:5:7:8:7:8");
718 1 : p.set_default_mask("");
719 1 : CATCH_REQUIRE(p.get_default_mask4() == "");
720 1 : CATCH_REQUIRE(p.get_default_mask6() == "");
721 : }
722 :
723 14 : CATCH_SECTION("verify default allow flags")
724 : {
725 2 : addr::addr_parser p;
726 :
727 13 : for(int idx(0); idx < static_cast<int>(addr::addr_parser::flag_t::FLAG_max); ++idx)
728 : {
729 12 : switch(static_cast<addr::addr_parser::flag_t>(idx))
730 : {
731 2 : case addr::addr_parser::flag_t::ADDRESS:
732 : case addr::addr_parser::flag_t::PORT:
733 : // only the ADDRESS and PORT are true by default
734 : //
735 2 : CATCH_REQUIRE(p.get_allow(static_cast<addr::addr_parser::flag_t>(idx)));
736 2 : break;
737 :
738 10 : default:
739 10 : CATCH_REQUIRE_FALSE(p.get_allow(static_cast<addr::addr_parser::flag_t>(idx)));
740 10 : break;
741 :
742 : }
743 : }
744 : }
745 :
746 14 : CATCH_SECTION("verify contradictory flags")
747 : {
748 2 : addr::addr_parser p;
749 :
750 : // by default we start with false
751 : //
752 1 : CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
753 1 : CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES));
754 1 : CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
755 :
756 : // check setting MULTI_ADDRESSES_COMMAS to true
757 : //
758 1 : p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS, true);
759 1 : CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
760 1 : CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES));
761 1 : CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
762 :
763 : // add MULTI_ADDRESSES_COMMAS_AND_SPACES
764 : //
765 1 : p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES, true);
766 1 : CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
767 1 : CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES));
768 1 : CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
769 :
770 : // add MULTI_PORTS_COMMAS
771 : //
772 1 : p.set_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS, true);
773 1 : CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
774 1 : CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES));
775 1 : CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
776 :
777 : // add MULTI_ADDRESSES_COMMAS_AND_SPACES only
778 : //
779 1 : p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES, true);
780 1 : CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
781 1 : CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES));
782 1 : CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
783 :
784 : // add MULTI_ADDRESSES_COMMAS second, order should not affect anything
785 : //
786 1 : p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS, true);
787 1 : CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
788 1 : CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES));
789 1 : CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
790 :
791 : // back to MULTI_PORTS_COMMAS
792 : //
793 1 : p.set_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS, true);
794 1 : CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
795 1 : CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES));
796 1 : CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
797 :
798 : // add MULTI_ADDRESSES_COMMAS first now
799 : //
800 1 : p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS, true);
801 1 : CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
802 1 : CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES));
803 1 : CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
804 : }
805 :
806 14 : CATCH_SECTION("default address")
807 : {
808 2 : addr::addr_parser p;
809 1 : p.set_protocol(IPPROTO_TCP);
810 1 : p.set_default_address("5.5.5.5");
811 1 : CATCH_REQUIRE(p.get_default_address4() == "5.5.5.5");
812 1 : CATCH_REQUIRE(p.get_default_address6() == "");
813 2 : addr::addr_range::vector_t ips(p.parse(""));
814 1 : CATCH_REQUIRE_FALSE(p.has_errors());
815 1 : CATCH_REQUIRE(ips.size() == 1);
816 1 : addr::addr_range const & r(ips[0]);
817 1 : CATCH_REQUIRE(r.has_from());
818 1 : CATCH_REQUIRE_FALSE(r.has_to());
819 1 : CATCH_REQUIRE_FALSE(r.is_range());
820 1 : CATCH_REQUIRE_FALSE(r.is_empty());
821 1 : addr::addr f(r.get_from());
822 1 : CATCH_REQUIRE(f.is_ipv4());
823 1 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.5.5.5");
824 1 : CATCH_REQUIRE(f.get_port() == 0);
825 1 : CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
826 1 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
827 : }
828 :
829 14 : CATCH_SECTION("address, not port allowed")
830 : {
831 : // specific address with a default
832 : {
833 2 : addr::addr_parser p;
834 1 : p.set_allow(addr::addr_parser::flag_t::PORT, false);
835 1 : p.set_protocol(IPPROTO_TCP);
836 1 : p.set_default_address("5.5.5.5");
837 1 : CATCH_REQUIRE(p.get_default_address4() == "5.5.5.5");
838 1 : CATCH_REQUIRE(p.get_default_address6() == "");
839 2 : addr::addr_range::vector_t ips(p.parse("9.9.9.9"));
840 1 : CATCH_REQUIRE_FALSE(p.has_errors());
841 1 : CATCH_REQUIRE(ips.size() == 1);
842 1 : addr::addr_range const & r(ips[0]);
843 1 : CATCH_REQUIRE(r.has_from());
844 1 : CATCH_REQUIRE_FALSE(r.has_to());
845 1 : CATCH_REQUIRE_FALSE(r.is_range());
846 1 : CATCH_REQUIRE_FALSE(r.is_empty());
847 1 : addr::addr f(r.get_from());
848 1 : CATCH_REQUIRE(f.is_ipv4());
849 1 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "9.9.9.9");
850 1 : CATCH_REQUIRE(f.get_port() == 0);
851 1 : CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
852 1 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
853 : }
854 :
855 : // only a default address
856 : {
857 2 : addr::addr_parser p;
858 1 : p.set_allow(addr::addr_parser::flag_t::PORT, false);
859 1 : p.set_protocol(IPPROTO_TCP);
860 1 : p.set_default_address("5.5.5.5");
861 1 : CATCH_REQUIRE(p.get_default_address4() == "5.5.5.5");
862 1 : CATCH_REQUIRE(p.get_default_address6() == "");
863 2 : addr::addr_range::vector_t ips(p.parse(""));
864 1 : CATCH_REQUIRE_FALSE(p.has_errors());
865 1 : CATCH_REQUIRE(ips.size() == 1);
866 1 : addr::addr_range const & r(ips[0]);
867 1 : CATCH_REQUIRE(r.has_from());
868 1 : CATCH_REQUIRE_FALSE(r.has_to());
869 1 : CATCH_REQUIRE_FALSE(r.is_range());
870 1 : CATCH_REQUIRE_FALSE(r.is_empty());
871 1 : addr::addr f(r.get_from());
872 1 : CATCH_REQUIRE(f.is_ipv4());
873 1 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.5.5.5");
874 1 : CATCH_REQUIRE(f.get_port() == 0);
875 1 : CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
876 1 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
877 : }
878 : }
879 : }
880 :
881 26 : CATCH_GIVEN("addr_parser() with multiple IPv4 addresses in one string")
882 : {
883 6 : CATCH_SECTION("3 IPs separated by commas")
884 : {
885 2 : addr::addr_parser p;
886 1 : p.set_protocol(IPPROTO_TCP);
887 1 : p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS, true);
888 2 : addr::addr_range::vector_t ips(p.parse("1.2.3.4:55,5.6.7.8,,,,10.11.12.99:77"));
889 1 : CATCH_REQUIRE_FALSE(p.has_errors());
890 1 : CATCH_REQUIRE(ips.size() == 3);
891 :
892 1 : uint8_t mask[16] = {};
893 :
894 : // 1.2.3.4:55
895 : {
896 1 : addr::addr_range const & r(ips[0]);
897 1 : CATCH_REQUIRE(r.has_from());
898 1 : CATCH_REQUIRE_FALSE(r.has_to());
899 1 : CATCH_REQUIRE_FALSE(r.is_range());
900 1 : CATCH_REQUIRE_FALSE(r.is_empty());
901 1 : addr::addr f(r.get_from());
902 1 : CATCH_REQUIRE(f.is_ipv4());
903 1 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
904 1 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
905 1 : CATCH_REQUIRE(f.get_port() == 55);
906 1 : CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
907 1 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
908 1 : f.get_mask(mask);
909 17 : for(int idx(0); idx < 16; ++idx)
910 : {
911 16 : CATCH_REQUIRE(mask[idx] == 255);
912 : }
913 : }
914 :
915 : // 5.6.7.8
916 : {
917 1 : addr::addr_range const & r(ips[1]);
918 1 : CATCH_REQUIRE(r.has_from());
919 1 : CATCH_REQUIRE_FALSE(r.has_to());
920 1 : CATCH_REQUIRE_FALSE(r.is_range());
921 1 : CATCH_REQUIRE_FALSE(r.is_empty());
922 1 : addr::addr f(r.get_from());
923 1 : CATCH_REQUIRE(f.is_ipv4());
924 1 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
925 1 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
926 1 : CATCH_REQUIRE(f.get_port() == 0);
927 1 : CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
928 1 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
929 1 : f.get_mask(mask);
930 17 : for(int idx(0); idx < 16; ++idx)
931 : {
932 16 : CATCH_REQUIRE(mask[idx] == 255);
933 : }
934 : }
935 :
936 : // 10.11.12.99:77
937 : {
938 1 : addr::addr_range const & r(ips[2]);
939 1 : CATCH_REQUIRE(r.has_from());
940 1 : CATCH_REQUIRE_FALSE(r.has_to());
941 1 : CATCH_REQUIRE_FALSE(r.is_range());
942 1 : CATCH_REQUIRE_FALSE(r.is_empty());
943 1 : addr::addr f(r.get_from());
944 1 : CATCH_REQUIRE(f.is_ipv4());
945 1 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
946 1 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
947 1 : CATCH_REQUIRE(f.get_port() == 77);
948 1 : CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
949 1 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
950 1 : f.get_mask(mask);
951 17 : for(int idx(0); idx < 16; ++idx)
952 : {
953 16 : CATCH_REQUIRE(mask[idx] == 255);
954 : }
955 : }
956 : }
957 :
958 6 : CATCH_SECTION("3 IPs separated by spaces")
959 : {
960 2 : addr::addr_parser p;
961 1 : p.set_protocol(IPPROTO_TCP);
962 1 : p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_SPACES, true);
963 2 : addr::addr_range::vector_t ips(p.parse("1.2.3.4:55 5.6.7.8 10.11.12.99:77"));
964 1 : CATCH_REQUIRE_FALSE(p.has_errors());
965 1 : CATCH_REQUIRE(ips.size() == 3);
966 :
967 1 : uint8_t mask[16] = {};
968 :
969 : // 1.2.3.4:55
970 : {
971 1 : addr::addr_range const & r(ips[0]);
972 1 : CATCH_REQUIRE(r.has_from());
973 1 : CATCH_REQUIRE_FALSE(r.has_to());
974 1 : CATCH_REQUIRE_FALSE(r.is_range());
975 1 : CATCH_REQUIRE_FALSE(r.is_empty());
976 1 : addr::addr f(r.get_from());
977 1 : CATCH_REQUIRE(f.is_ipv4());
978 1 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
979 1 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
980 1 : CATCH_REQUIRE(f.get_port() == 55);
981 1 : CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
982 1 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
983 1 : f.get_mask(mask);
984 17 : for(int idx(0); idx < 16; ++idx)
985 : {
986 16 : CATCH_REQUIRE(mask[idx] == 255);
987 : }
988 : }
989 :
990 : // 5.6.7.8
991 : {
992 1 : addr::addr_range const & r(ips[1]);
993 1 : CATCH_REQUIRE(r.has_from());
994 1 : CATCH_REQUIRE_FALSE(r.has_to());
995 1 : CATCH_REQUIRE_FALSE(r.is_range());
996 1 : CATCH_REQUIRE_FALSE(r.is_empty());
997 1 : addr::addr f(r.get_from());
998 1 : CATCH_REQUIRE(f.is_ipv4());
999 1 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
1000 1 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
1001 1 : CATCH_REQUIRE(f.get_port() == 0);
1002 1 : CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
1003 1 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
1004 1 : f.get_mask(mask);
1005 17 : for(int idx(0); idx < 16; ++idx)
1006 : {
1007 16 : CATCH_REQUIRE(mask[idx] == 255);
1008 : }
1009 : }
1010 :
1011 : // 10.11.12.99:77
1012 : {
1013 1 : addr::addr_range const & r(ips[2]);
1014 1 : CATCH_REQUIRE(r.has_from());
1015 1 : CATCH_REQUIRE_FALSE(r.has_to());
1016 1 : CATCH_REQUIRE_FALSE(r.is_range());
1017 1 : CATCH_REQUIRE_FALSE(r.is_empty());
1018 1 : addr::addr f(r.get_from());
1019 1 : CATCH_REQUIRE(f.is_ipv4());
1020 1 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
1021 1 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
1022 1 : CATCH_REQUIRE(f.get_port() == 77);
1023 1 : CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
1024 1 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
1025 1 : f.get_mask(mask);
1026 17 : for(int idx(0); idx < 16; ++idx)
1027 : {
1028 16 : CATCH_REQUIRE(mask[idx] == 255);
1029 : }
1030 : }
1031 : }
1032 :
1033 6 : CATCH_SECTION("3 IPs separated by commas and/or spaces")
1034 : {
1035 2 : addr::addr_parser p;
1036 1 : p.set_protocol(IPPROTO_TCP);
1037 1 : p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES, true);
1038 2 : addr::addr_range::vector_t ips(p.parse(" 1.2.3.4:55,, 5.6.7.8 , 10.11.12.99:77 "));
1039 1 : CATCH_REQUIRE_FALSE(p.has_errors());
1040 1 : CATCH_REQUIRE(ips.size() == 3);
1041 :
1042 1 : uint8_t mask[16] = {};
1043 :
1044 : // 1.2.3.4:55
1045 : {
1046 1 : addr::addr_range const & r(ips[0]);
1047 1 : CATCH_REQUIRE(r.has_from());
1048 1 : CATCH_REQUIRE_FALSE(r.has_to());
1049 1 : CATCH_REQUIRE_FALSE(r.is_range());
1050 1 : CATCH_REQUIRE_FALSE(r.is_empty());
1051 1 : addr::addr f(r.get_from());
1052 1 : CATCH_REQUIRE(f.is_ipv4());
1053 1 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
1054 1 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
1055 1 : CATCH_REQUIRE(f.get_port() == 55);
1056 1 : CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
1057 1 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
1058 1 : f.get_mask(mask);
1059 17 : for(int idx(0); idx < 16; ++idx)
1060 : {
1061 16 : CATCH_REQUIRE(mask[idx] == 255);
1062 : }
1063 : }
1064 :
1065 : // 5.6.7.8
1066 : {
1067 1 : addr::addr_range const & r(ips[1]);
1068 1 : CATCH_REQUIRE(r.has_from());
1069 1 : CATCH_REQUIRE_FALSE(r.has_to());
1070 1 : CATCH_REQUIRE_FALSE(r.is_range());
1071 1 : CATCH_REQUIRE_FALSE(r.is_empty());
1072 1 : addr::addr f(r.get_from());
1073 1 : CATCH_REQUIRE(f.is_ipv4());
1074 1 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
1075 1 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
1076 1 : CATCH_REQUIRE(f.get_port() == 0);
1077 1 : CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
1078 1 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
1079 1 : f.get_mask(mask);
1080 17 : for(int idx(0); idx < 16; ++idx)
1081 : {
1082 16 : CATCH_REQUIRE(mask[idx] == 255);
1083 : }
1084 : }
1085 :
1086 : // 10.11.12.99:77
1087 : {
1088 1 : addr::addr_range const & r(ips[2]);
1089 1 : CATCH_REQUIRE(r.has_from());
1090 1 : CATCH_REQUIRE_FALSE(r.has_to());
1091 1 : CATCH_REQUIRE_FALSE(r.is_range());
1092 1 : CATCH_REQUIRE_FALSE(r.is_empty());
1093 1 : addr::addr f(r.get_from());
1094 1 : CATCH_REQUIRE(f.is_ipv4());
1095 1 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
1096 1 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
1097 1 : CATCH_REQUIRE(f.get_port() == 77);
1098 1 : CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
1099 1 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
1100 1 : f.get_mask(mask);
1101 17 : for(int idx(0); idx < 16; ++idx)
1102 : {
1103 16 : CATCH_REQUIRE(mask[idx] == 255);
1104 : }
1105 : }
1106 : }
1107 : }
1108 13 : }
1109 :
1110 :
1111 5 : CATCH_TEST_CASE( "ipv4::ports", "[ipv4]" )
1112 : {
1113 6 : CATCH_GIVEN("addr_parser() with IPv4 addresses and port")
1114 : {
1115 6 : CATCH_SECTION("verify port")
1116 : {
1117 65537 : for(int port(0); port < 65536; ++port)
1118 : {
1119 65536 : int proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
1120 131072 : addr::addr_parser p;
1121 65536 : p.set_protocol(proto);
1122 131072 : addr::addr_range::vector_t ips(p.parse("192.168.12.199:" + std::to_string(port)));
1123 65536 : CATCH_REQUIRE_FALSE(p.has_errors());
1124 65536 : CATCH_REQUIRE(ips.size() == 1);
1125 65536 : addr::addr_range const & r(ips[0]);
1126 65536 : addr::addr f(r.get_from());
1127 65536 : CATCH_REQUIRE(f.is_ipv4());
1128 65536 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "192.168.12.199");
1129 65536 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "192.168.12.199");
1130 65536 : CATCH_REQUIRE(f.get_port() == port);
1131 65536 : CATCH_REQUIRE(f.get_protocol() == proto);
1132 65536 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
1133 : }
1134 : }
1135 :
1136 6 : CATCH_SECTION("default address with various port")
1137 : {
1138 101 : for(int idx(0); idx < 100; ++idx)
1139 : {
1140 100 : uint16_t const port(rand());
1141 200 : addr::addr_parser p;
1142 100 : p.set_protocol(IPPROTO_TCP);
1143 100 : p.set_default_address("5.5.5.5");
1144 100 : CATCH_REQUIRE(p.get_default_address4() == "5.5.5.5");
1145 100 : CATCH_REQUIRE(p.get_default_address6() == "");
1146 200 : addr::addr_range::vector_t ips(p.parse(":" + std::to_string(static_cast<int>(port))));
1147 100 : CATCH_REQUIRE_FALSE(p.has_errors());
1148 100 : CATCH_REQUIRE(ips.size() == 1);
1149 100 : addr::addr_range const & r(ips[0]);
1150 100 : CATCH_REQUIRE(r.has_from());
1151 100 : CATCH_REQUIRE_FALSE(r.has_to());
1152 100 : CATCH_REQUIRE_FALSE(r.is_range());
1153 100 : CATCH_REQUIRE_FALSE(r.is_empty());
1154 100 : addr::addr f(r.get_from());
1155 100 : CATCH_REQUIRE(f.is_ipv4());
1156 100 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
1157 100 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
1158 100 : CATCH_REQUIRE(f.get_port() == port);
1159 100 : CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
1160 100 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
1161 : }
1162 : }
1163 :
1164 6 : CATCH_SECTION("address with default port")
1165 : {
1166 26 : for(int idx(0); idx < 25; ++idx)
1167 : {
1168 25 : uint16_t const port(rand());
1169 50 : addr::addr_parser p;
1170 25 : p.set_protocol(IPPROTO_TCP);
1171 25 : p.set_default_port(port);
1172 25 : CATCH_REQUIRE(p.get_default_port() == port);
1173 50 : addr::addr_range::vector_t ips(p.parse("5.5.5.5"));
1174 25 : CATCH_REQUIRE_FALSE(p.has_errors());
1175 25 : CATCH_REQUIRE(ips.size() == 1);
1176 25 : addr::addr_range const & r(ips[0]);
1177 25 : CATCH_REQUIRE(r.has_from());
1178 25 : CATCH_REQUIRE_FALSE(r.has_to());
1179 25 : CATCH_REQUIRE_FALSE(r.is_range());
1180 25 : CATCH_REQUIRE_FALSE(r.is_empty());
1181 25 : addr::addr f(r.get_from());
1182 25 : CATCH_REQUIRE(f.is_ipv4());
1183 25 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
1184 25 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
1185 25 : CATCH_REQUIRE(f.get_port() == port);
1186 25 : CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
1187 25 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
1188 : }
1189 :
1190 26 : for(int idx(0); idx < 25; ++idx)
1191 : {
1192 25 : uint16_t const port(rand());
1193 50 : addr::addr_parser p;
1194 25 : p.set_protocol(IPPROTO_TCP);
1195 25 : p.set_default_port(port);
1196 25 : CATCH_REQUIRE(p.get_default_port() == port);
1197 50 : addr::addr_range::vector_t ips(p.parse("5.5.5.5:"));
1198 25 : CATCH_REQUIRE_FALSE(p.has_errors());
1199 25 : CATCH_REQUIRE(ips.size() == 1);
1200 25 : addr::addr_range const & r(ips[0]);
1201 25 : CATCH_REQUIRE(r.has_from());
1202 25 : CATCH_REQUIRE_FALSE(r.has_to());
1203 25 : CATCH_REQUIRE_FALSE(r.is_range());
1204 25 : CATCH_REQUIRE_FALSE(r.is_empty());
1205 25 : addr::addr f(r.get_from());
1206 25 : CATCH_REQUIRE(f.is_ipv4());
1207 25 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
1208 25 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
1209 25 : CATCH_REQUIRE(f.get_port() == port);
1210 25 : CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
1211 25 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
1212 : }
1213 : }
1214 : }
1215 3 : }
1216 :
1217 :
1218 9 : CATCH_TEST_CASE( "ipv4::masks", "[ipv4]" )
1219 : {
1220 14 : CATCH_GIVEN("addr_parser() of address:port/mask")
1221 : {
1222 14 : CATCH_SECTION("mask allowed, but no mask")
1223 : {
1224 1 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
1225 1 : int const port(rand() & 0xFFFF);
1226 2 : addr::addr_parser p;
1227 1 : p.set_protocol(proto);
1228 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
1229 2 : addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port)));
1230 1 : CATCH_REQUIRE_FALSE(p.has_errors());
1231 1 : CATCH_REQUIRE(ips.size() == 1);
1232 1 : addr::addr_range const & r(ips[0]);
1233 1 : addr::addr f(r.get_from());
1234 1 : CATCH_REQUIRE(f.is_ipv4());
1235 2 : std::string result("172.19.6.91:" + std::to_string(port) + "/255.255.255.255");
1236 1 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1237 1 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1238 1 : CATCH_REQUIRE(f.get_port() == port);
1239 1 : CATCH_REQUIRE(f.get_protocol() == proto);
1240 1 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
1241 : }
1242 :
1243 14 : CATCH_SECTION("empty mask")
1244 : {
1245 1 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
1246 1 : int const port(rand() & 0xFFFF);
1247 2 : addr::addr_parser p;
1248 1 : p.set_protocol(proto);
1249 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
1250 2 : addr::addr_range::vector_t ips(p.parse("172.18.5.91:" + std::to_string(port) + "/"));
1251 1 : CATCH_REQUIRE_FALSE(p.has_errors());
1252 1 : CATCH_REQUIRE(ips.size() == 1);
1253 1 : addr::addr_range const & r(ips[0]);
1254 1 : addr::addr f(r.get_from());
1255 1 : CATCH_REQUIRE(f.is_ipv4());
1256 2 : std::string result("172.18.5.91:" + std::to_string(port) + "/255.255.255.255");
1257 1 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1258 1 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1259 1 : CATCH_REQUIRE(f.get_port() == port);
1260 1 : CATCH_REQUIRE(f.get_protocol() == proto);
1261 1 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
1262 : }
1263 :
1264 14 : CATCH_SECTION("one number masks")
1265 : {
1266 34 : for(int idx(0); idx <= 32; ++idx)
1267 : {
1268 33 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
1269 33 : int const port(rand() & 0xFFFF);
1270 66 : addr::addr_parser p;
1271 33 : p.set_protocol(proto);
1272 33 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
1273 66 : addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port) + "/" + std::to_string(idx)));
1274 33 : CATCH_REQUIRE_FALSE(p.has_errors());
1275 33 : CATCH_REQUIRE(ips.size() == 1);
1276 33 : addr::addr_range const & r(ips[0]);
1277 33 : addr::addr f(r.get_from());
1278 33 : CATCH_REQUIRE(f.is_ipv4());
1279 33 : uint64_t const mask(std::numeric_limits<uint64_t>::max() << (32 - idx));
1280 33 : std::string mask_str(
1281 66 : std::to_string((mask >> 24) & 255)
1282 99 : + "."
1283 132 : + std::to_string((mask >> 16) & 255)
1284 99 : + "."
1285 132 : + std::to_string((mask >> 8) & 255)
1286 99 : + "."
1287 132 : + std::to_string((mask >> 0) & 255));
1288 66 : std::string result("172.17.3.91:" + std::to_string(port) + "/" + mask_str);
1289 33 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1290 33 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1291 33 : CATCH_REQUIRE(f.get_port() == port);
1292 33 : CATCH_REQUIRE(f.get_protocol() == proto);
1293 33 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
1294 : }
1295 : }
1296 :
1297 14 : CATCH_SECTION("address like mask")
1298 : {
1299 26 : for(int idx(0); idx < 25; ++idx)
1300 : {
1301 25 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
1302 25 : int const port(rand() & 0xFFFF);
1303 50 : addr::addr_parser p;
1304 25 : p.set_protocol(proto);
1305 25 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
1306 : // when specified as an IP, the mask can be absolutely anything
1307 25 : uint8_t mask[4];
1308 125 : for(int j(0); j < 4; ++j)
1309 : {
1310 100 : mask[j] = rand();
1311 : }
1312 25 : std::string const mask_str(
1313 50 : std::to_string(static_cast<int>(mask[0]))
1314 75 : + "."
1315 100 : + std::to_string(static_cast<int>(mask[1]))
1316 75 : + "."
1317 100 : + std::to_string(static_cast<int>(mask[2]))
1318 75 : + "."
1319 100 : + std::to_string(static_cast<int>(mask[3])));
1320 50 : addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port) + "/" + mask_str));
1321 25 : CATCH_REQUIRE_FALSE(p.has_errors());
1322 25 : CATCH_REQUIRE(ips.size() == 1);
1323 25 : addr::addr_range const & r(ips[0]);
1324 25 : addr::addr f(r.get_from());
1325 25 : CATCH_REQUIRE(f.is_ipv4());
1326 50 : std::string result("172.17.3.91:" + std::to_string(port) + "/" + mask_str);
1327 25 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1328 25 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1329 25 : CATCH_REQUIRE(f.get_port() == port);
1330 25 : CATCH_REQUIRE(f.get_protocol() == proto);
1331 25 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
1332 : }
1333 : }
1334 :
1335 14 : CATCH_SECTION("address like default mask")
1336 : {
1337 26 : for(int idx(0); idx < 25; ++idx)
1338 : {
1339 25 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
1340 25 : int const port(rand() & 0xFFFF);
1341 50 : addr::addr_parser p;
1342 25 : p.set_protocol(proto);
1343 25 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
1344 : // when specified as an IP, the mask can be absolutely anything
1345 : // (here the mask is a string an it will be parsed by the
1346 : // parser if required)
1347 : //
1348 25 : uint8_t mask[4];
1349 125 : for(int j(0); j < 4; ++j)
1350 : {
1351 100 : mask[j] = rand();
1352 : }
1353 25 : std::string const mask_str(
1354 50 : std::to_string(static_cast<int>(mask[0]))
1355 75 : + "."
1356 100 : + std::to_string(static_cast<int>(mask[1]))
1357 75 : + "."
1358 100 : + std::to_string(static_cast<int>(mask[2]))
1359 75 : + "."
1360 100 : + std::to_string(static_cast<int>(mask[3])));
1361 25 : p.set_default_mask(mask_str);
1362 50 : addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port)));
1363 25 : CATCH_REQUIRE_FALSE(p.has_errors());
1364 25 : CATCH_REQUIRE(ips.size() == 1);
1365 25 : addr::addr_range const & r(ips[0]);
1366 25 : addr::addr f(r.get_from());
1367 25 : CATCH_REQUIRE(f.is_ipv4());
1368 50 : std::string result("172.17.3.91:" + std::to_string(port) + "/" + mask_str);
1369 25 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1370 25 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1371 25 : CATCH_REQUIRE(f.get_port() == port);
1372 25 : CATCH_REQUIRE(f.get_protocol() == proto);
1373 25 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
1374 25 : uint8_t verify_mask[16];
1375 25 : f.get_mask(verify_mask);
1376 325 : for(int j(0); j < 16 - 4; ++j)
1377 : {
1378 300 : CATCH_REQUIRE(verify_mask[j] == 255);
1379 : }
1380 125 : for(int j(12); j < 16; ++j)
1381 : {
1382 100 : CATCH_REQUIRE(verify_mask[j] == mask[j - 12]);
1383 : }
1384 : }
1385 : }
1386 :
1387 14 : CATCH_SECTION("address like mask with a default")
1388 : {
1389 26 : for(int idx(0); idx < 25; ++idx)
1390 : {
1391 25 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
1392 25 : int const port(rand() & 0xFFFF);
1393 50 : addr::addr_parser p;
1394 25 : p.set_protocol(proto);
1395 25 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
1396 :
1397 : // here we want a default and an IP with a specific mask
1398 : // to make sure that the specific mask has priority
1399 : //
1400 25 : uint8_t mask[4];
1401 125 : for(int j(0); j < 4; ++j)
1402 : {
1403 100 : mask[j] = rand();
1404 : }
1405 25 : std::string const mask_str(
1406 50 : std::to_string(static_cast<int>(mask[0]))
1407 75 : + "."
1408 100 : + std::to_string(static_cast<int>(mask[1]))
1409 75 : + "."
1410 100 : + std::to_string(static_cast<int>(mask[2]))
1411 75 : + "."
1412 100 : + std::to_string(static_cast<int>(mask[3])));
1413 :
1414 25 : uint8_t default_mask[4];
1415 125 : for(int j(0); j < 4; ++j)
1416 : {
1417 100 : default_mask[j] = rand();
1418 : }
1419 25 : std::string const default_mask_str(
1420 50 : std::to_string(static_cast<int>(default_mask[0]))
1421 75 : + "."
1422 100 : + std::to_string(static_cast<int>(default_mask[1]))
1423 75 : + "."
1424 100 : + std::to_string(static_cast<int>(default_mask[2]))
1425 75 : + "."
1426 100 : + std::to_string(static_cast<int>(default_mask[3])));
1427 25 : p.set_default_mask(default_mask_str);
1428 :
1429 50 : addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port) + "/" + mask_str));
1430 25 : CATCH_REQUIRE_FALSE(p.has_errors());
1431 25 : CATCH_REQUIRE(ips.size() == 1);
1432 25 : addr::addr_range const & r(ips[0]);
1433 25 : addr::addr f(r.get_from());
1434 25 : CATCH_REQUIRE(f.is_ipv4());
1435 50 : std::string result("172.17.3.91:" + std::to_string(port) + "/" + mask_str);
1436 25 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1437 25 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1438 25 : CATCH_REQUIRE(f.get_port() == port);
1439 25 : CATCH_REQUIRE(f.get_protocol() == proto);
1440 25 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
1441 25 : uint8_t verify_mask[16];
1442 25 : f.get_mask(verify_mask);
1443 325 : for(int j(0); j < 16 - 4; ++j)
1444 : {
1445 300 : CATCH_REQUIRE(verify_mask[j] == 255);
1446 : }
1447 125 : for(int j(12); j < 16; ++j)
1448 : {
1449 100 : CATCH_REQUIRE(verify_mask[j] == mask[j - 12]);
1450 : }
1451 : }
1452 : }
1453 :
1454 14 : CATCH_SECTION("two addresses and a mask for a match / no match")
1455 : {
1456 1 : int const port1(rand() & 0xFFFF);
1457 2 : addr::addr_parser p;
1458 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
1459 :
1460 : // parse the IP with a mask
1461 : //
1462 1 : int proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
1463 1 : p.set_protocol(proto);
1464 2 : addr::addr_range::vector_t ips1(p.parse("192.168.0.0:" + std::to_string(port1) + "/16"));
1465 1 : CATCH_REQUIRE_FALSE(p.has_errors());
1466 1 : CATCH_REQUIRE(ips1.size() == 1);
1467 1 : addr::addr_range const & r1(ips1[0]);
1468 1 : addr::addr f1(r1.get_from());
1469 1 : CATCH_REQUIRE(f1.is_ipv4());
1470 1 : CATCH_REQUIRE(f1.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == "192.168.0.0:" + std::to_string(port1) + "/255.255.0.0");
1471 1 : CATCH_REQUIRE(f1.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == "192.168.0.0:" + std::to_string(port1) + "/255.255.0.0");
1472 1 : CATCH_REQUIRE(f1.get_port() == port1);
1473 1 : CATCH_REQUIRE(f1.get_protocol() == proto);
1474 1 : CATCH_REQUIRE(f1.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
1475 :
1476 : // reuse parser
1477 : //
1478 1 : proto = rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP;
1479 1 : p.set_protocol(proto);
1480 1 : int const port2(rand() & 0xFFFF);
1481 2 : addr::addr_range::vector_t ips2(p.parse("192.168.5.36:" + std::to_string(port2)));
1482 1 : CATCH_REQUIRE_FALSE(p.has_errors());
1483 1 : CATCH_REQUIRE(ips2.size() == 1);
1484 1 : addr::addr_range const & r2(ips2[0]);
1485 1 : addr::addr f2(r2.get_from());
1486 1 : CATCH_REQUIRE(f2.is_ipv4());
1487 1 : CATCH_REQUIRE(f2.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == "192.168.5.36:" + std::to_string(port2) + "/255.255.255.255");
1488 1 : CATCH_REQUIRE(f2.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == "192.168.5.36:" + std::to_string(port2) + "/255.255.255.255");
1489 1 : CATCH_REQUIRE(f2.get_port() == port2);
1490 1 : CATCH_REQUIRE(f2.get_protocol() == proto);
1491 1 : CATCH_REQUIRE(f2.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
1492 :
1493 : // 3rd with a mask along the full IP
1494 : //
1495 1 : proto = rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP;
1496 1 : p.set_protocol(proto);
1497 1 : int const port3(rand() & 0xFFFF);
1498 2 : addr::addr_range::vector_t ips3(p.parse("192.168.5.36:" + std::to_string(port3) + "/16"));
1499 1 : CATCH_REQUIRE_FALSE(p.has_errors());
1500 1 : CATCH_REQUIRE(ips3.size() == 1);
1501 1 : addr::addr_range const & r3(ips3[0]);
1502 1 : addr::addr f3(r3.get_from());
1503 1 : CATCH_REQUIRE(f3.is_ipv4());
1504 1 : CATCH_REQUIRE(f3.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == "192.168.5.36:" + std::to_string(port3) + "/255.255.0.0");
1505 1 : CATCH_REQUIRE(f3.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == "192.168.5.36:" + std::to_string(port3) + "/255.255.0.0");
1506 1 : CATCH_REQUIRE(f3.get_port() == port3);
1507 1 : CATCH_REQUIRE(f3.get_protocol() == proto);
1508 1 : CATCH_REQUIRE(f3.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
1509 :
1510 : // just a side test
1511 : //
1512 1 : CATCH_REQUIRE(f1 != f2);
1513 1 : CATCH_REQUIRE(f1 != f3);
1514 1 : CATCH_REQUIRE(f2 == f3);
1515 :
1516 : // check whether p1 matches p2 and vice versa
1517 : //
1518 1 : CATCH_REQUIRE(f1.match(f2)); // f2 & mask1 == f1
1519 1 : CATCH_REQUIRE(f1.match(f3)); // f3 & mask1 == f1
1520 :
1521 1 : CATCH_REQUIRE_FALSE(f2.match(f1)); // f1 & mask2 != f2
1522 1 : CATCH_REQUIRE(f2.match(f3)); // f3 & mask2 == f2 (because f2 == f3 anyway)
1523 :
1524 1 : CATCH_REQUIRE(f3.match(f1)); // f1 & mask3 == f3
1525 1 : CATCH_REQUIRE(f3.match(f2)); // f2 & mask3 == f3
1526 :
1527 1 : f3.apply_mask();
1528 :
1529 1 : CATCH_REQUIRE(f1 != f2);
1530 1 : CATCH_REQUIRE(f1 == f3);
1531 1 : CATCH_REQUIRE(f2 != f3);
1532 :
1533 : // re-run the match() calls with f3 since it changed...
1534 : //
1535 1 : CATCH_REQUIRE(f1.match(f3)); // f3 & mask1 == f1
1536 :
1537 1 : CATCH_REQUIRE_FALSE(f2.match(f3)); // f3 & mask2 == f2 (because f2 != f3 anymore)
1538 :
1539 1 : CATCH_REQUIRE(f3.match(f1)); // f1 & mask3 == f3
1540 1 : CATCH_REQUIRE(f3.match(f2)); // f2 & mask3 == f3
1541 : }
1542 : }
1543 7 : }
1544 :
1545 :
1546 8 : CATCH_TEST_CASE( "ipv4::protocol", "[ipv4]" )
1547 : {
1548 12 : CATCH_GIVEN("addr()")
1549 : {
1550 2 : addr::addr a;
1551 :
1552 4 : CATCH_SECTION("default protocol")
1553 : {
1554 1 : CATCH_REQUIRE(a.get_protocol() == IPPROTO_TCP);
1555 : }
1556 :
1557 4 : CATCH_SECTION("set_protocol()")
1558 : {
1559 : // setup a random protocol
1560 : //
1561 1 : int const start_protocol([]()
1562 : {
1563 1 : switch(rand() % 3)
1564 : {
1565 1 : case 0:
1566 1 : return IPPROTO_IP;
1567 :
1568 0 : case 1:
1569 0 : return IPPROTO_TCP;
1570 :
1571 : //case 2:
1572 0 : default:
1573 0 : return IPPROTO_UDP;
1574 :
1575 : }
1576 1 : }());
1577 1 : a.set_protocol(start_protocol);
1578 :
1579 : // test 100 invalid protocols
1580 : //
1581 101 : for(int idx(0); idx < 100; ++idx)
1582 : {
1583 : int invalid_protocol;
1584 0 : do
1585 : {
1586 100 : invalid_protocol = rand();
1587 : }
1588 : while(invalid_protocol == IPPROTO_IP
1589 100 : || invalid_protocol == IPPROTO_TCP
1590 200 : || invalid_protocol == IPPROTO_UDP);
1591 100 : CATCH_REQUIRE_THROWS_AS(a.set_protocol(invalid_protocol), addr::addr_invalid_argument);
1592 :
1593 : // make sure the protocol does not change on errors
1594 100 : CATCH_REQUIRE(a.get_protocol() == start_protocol);
1595 : }
1596 :
1597 : // null string is not allowed
1598 : //
1599 1 : CATCH_REQUIRE_THROWS_AS(a.set_protocol(nullptr), addr::addr_invalid_argument);
1600 :
1601 : // other "invalid" (unsupported, really) string protocols
1602 : //
1603 1 : CATCH_REQUIRE_THROWS_AS(a.set_protocol("icmp"), addr::addr_invalid_argument);
1604 1 : CATCH_REQUIRE_THROWS_AS(a.set_protocol("raw"), addr::addr_invalid_argument);
1605 1 : CATCH_REQUIRE_THROWS_AS(a.set_protocol("hmp"), addr::addr_invalid_argument);
1606 :
1607 : // test all valid protocols (numeric)
1608 : //
1609 1 : a.set_protocol(IPPROTO_IP);
1610 1 : CATCH_REQUIRE(a.get_protocol() == IPPROTO_IP);
1611 1 : a.set_protocol(IPPROTO_TCP);
1612 1 : CATCH_REQUIRE(a.get_protocol() == IPPROTO_TCP);
1613 1 : a.set_protocol(IPPROTO_UDP);
1614 1 : CATCH_REQUIRE(a.get_protocol() == IPPROTO_UDP);
1615 :
1616 : // test all valid protocols (ascii)
1617 : //
1618 1 : a.set_protocol("ip");
1619 1 : CATCH_REQUIRE(a.get_protocol() == IPPROTO_IP);
1620 1 : a.set_protocol("tcp");
1621 1 : CATCH_REQUIRE(a.get_protocol() == IPPROTO_TCP);
1622 1 : a.set_protocol("udp");
1623 1 : CATCH_REQUIRE(a.get_protocol() == IPPROTO_UDP);
1624 : }
1625 : }
1626 :
1627 12 : CATCH_GIVEN("addr_parser()")
1628 : {
1629 6 : addr::addr_parser p;
1630 :
1631 6 : CATCH_SECTION("verify default")
1632 : {
1633 1 : CATCH_REQUIRE(p.get_protocol() == -1);
1634 : }
1635 :
1636 6 : CATCH_SECTION("test 3 allowed protocols")
1637 : {
1638 : // by string
1639 : //
1640 1 : p.set_protocol("ip");
1641 1 : CATCH_REQUIRE(p.get_protocol() == IPPROTO_IP);
1642 1 : p.set_protocol("tcp");
1643 1 : CATCH_REQUIRE(p.get_protocol() == IPPROTO_TCP);
1644 1 : p.set_protocol("udp");
1645 1 : CATCH_REQUIRE(p.get_protocol() == IPPROTO_UDP);
1646 :
1647 : // numerically
1648 : //
1649 1 : p.set_protocol(IPPROTO_IP);
1650 1 : CATCH_REQUIRE(p.get_protocol() == IPPROTO_IP);
1651 1 : p.set_protocol(IPPROTO_TCP);
1652 1 : CATCH_REQUIRE(p.get_protocol() == IPPROTO_TCP);
1653 1 : p.set_protocol(IPPROTO_UDP);
1654 1 : CATCH_REQUIRE(p.get_protocol() == IPPROTO_UDP);
1655 : }
1656 :
1657 6 : CATCH_SECTION("verify clearing works")
1658 : {
1659 1 : p.set_protocol("ip");
1660 1 : CATCH_REQUIRE(p.get_protocol() == IPPROTO_IP);
1661 1 : p.clear_protocol();
1662 1 : CATCH_REQUIRE(p.get_protocol() == -1);
1663 :
1664 1 : p.set_protocol("tcp");
1665 1 : CATCH_REQUIRE(p.get_protocol() == IPPROTO_TCP);
1666 1 : p.clear_protocol();
1667 1 : CATCH_REQUIRE(p.get_protocol() == -1);
1668 :
1669 1 : p.set_protocol("udp");
1670 1 : CATCH_REQUIRE(p.get_protocol() == IPPROTO_UDP);
1671 1 : p.clear_protocol();
1672 1 : CATCH_REQUIRE(p.get_protocol() == -1);
1673 : }
1674 : }
1675 :
1676 12 : CATCH_GIVEN("addr_parser with any protocol")
1677 : {
1678 1 : addr::addr a;
1679 :
1680 2 : CATCH_SECTION("get address with all protocols")
1681 : {
1682 2 : addr::addr_parser p;
1683 : //p.set_protocol(...); -- by default we'll get all the protocols supported
1684 2 : addr::addr_range::vector_t ips(p.parse("127.0.0.1"));
1685 1 : CATCH_REQUIRE_FALSE(p.has_errors());
1686 1 : CATCH_REQUIRE(!ips.empty());
1687 4 : for(size_t idx(0); idx < ips.size(); ++idx)
1688 : {
1689 3 : addr::addr_range const & r(ips[idx]);
1690 3 : CATCH_REQUIRE(r.has_from());
1691 3 : CATCH_REQUIRE_FALSE(r.has_to());
1692 3 : CATCH_REQUIRE_FALSE(r.is_range());
1693 3 : CATCH_REQUIRE_FALSE(r.is_empty());
1694 3 : addr::addr f(r.get_from());
1695 3 : if(f.is_ipv4())
1696 : {
1697 3 : CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "127.0.0.1");
1698 3 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "127.0.0.1");
1699 3 : CATCH_REQUIRE(f.get_port() == 0);
1700 : //CATCH_REQUIRE(f.get_protocol() == ...); -- may be TCP, UDP, IP
1701 3 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LOOPBACK);
1702 : }
1703 : else
1704 : {
1705 0 : CATCH_REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::1");
1706 0 : CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::1");
1707 0 : CATCH_REQUIRE(f.get_port() == 0);
1708 : //CATCH_REQUIRE(f.get_protocol() == ...); -- may be TCP, UDP, IP
1709 0 : CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LOOPBACK);
1710 : }
1711 : }
1712 : }
1713 : }
1714 6 : }
1715 :
1716 :
1717 10 : CATCH_TEST_CASE( "ipv4::network_type", "[ipv4]" )
1718 : {
1719 16 : CATCH_GIVEN("addr()")
1720 : {
1721 8 : addr::addr a;
1722 :
1723 16 : CATCH_SECTION("any (0.0.0.0)")
1724 : {
1725 1 : struct sockaddr_in in = sockaddr_in();
1726 1 : in.sin_family = AF_INET;
1727 1 : in.sin_port = htons(rand());
1728 1 : in.sin_addr.s_addr = 0;
1729 :
1730 : // verify network type
1731 : //
1732 1 : a.set_ipv4(in);
1733 :
1734 1 : CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_ANY);
1735 1 : CATCH_REQUIRE(a.get_network_type_string() == "Any");
1736 : }
1737 :
1738 16 : CATCH_SECTION("private address 10.x.x.x/8")
1739 : {
1740 11 : for(int idx(0); idx < 10; ++idx)
1741 : {
1742 10 : struct sockaddr_in in = sockaddr_in();
1743 10 : in.sin_family = AF_INET;
1744 10 : in.sin_port = htons(rand());
1745 : uint32_t address((10 << 24)
1746 10 : | ((rand() & 255) << 16)
1747 10 : | ((rand() & 255) << 8)
1748 10 : | ((rand() & 255) << 0));
1749 10 : in.sin_addr.s_addr = htonl(address);
1750 :
1751 : // verify network type
1752 : //
1753 10 : a.set_ipv4(in);
1754 10 : CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
1755 10 : CATCH_REQUIRE(a.get_network_type_string() == "Private");
1756 : }
1757 : }
1758 :
1759 16 : CATCH_SECTION("private address 172.16.x.x/12")
1760 : {
1761 11 : for(int idx(0); idx < 10; ++idx)
1762 : {
1763 10 : struct sockaddr_in in = sockaddr_in();
1764 10 : in.sin_family = AF_INET;
1765 10 : in.sin_port = htons(rand());
1766 : uint32_t address((172 << 24)
1767 10 : | (((rand() & 15) | 16) << 16)
1768 10 : | ((rand() & 255) << 8)
1769 10 : | ((rand() & 255) << 0));
1770 10 : in.sin_addr.s_addr = htonl(address);
1771 :
1772 : // verify network type
1773 : //
1774 10 : a.set_ipv4(in);
1775 10 : CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
1776 10 : CATCH_REQUIRE(a.get_network_type_string() == "Private");
1777 : }
1778 : }
1779 :
1780 16 : CATCH_SECTION("private address 192.168.x.x/16")
1781 : {
1782 11 : for(int idx(0); idx < 10; ++idx)
1783 : {
1784 10 : struct sockaddr_in in = sockaddr_in();
1785 10 : in.sin_family = AF_INET;
1786 10 : in.sin_port = htons(rand());
1787 : uint32_t address((192 << 24)
1788 : | (168 << 16)
1789 10 : | ((rand() & 255) << 8)
1790 10 : | ((rand() & 255) << 0));
1791 10 : in.sin_addr.s_addr = htonl(address);
1792 :
1793 : // verify network type
1794 : //
1795 10 : a.set_ipv4(in);
1796 10 : CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
1797 10 : CATCH_REQUIRE(a.get_network_type_string() == "Private");
1798 : }
1799 : }
1800 :
1801 16 : CATCH_SECTION("private address 100.66.x.x/10")
1802 : {
1803 11 : for(int idx(0); idx < 10; ++idx)
1804 : {
1805 10 : struct sockaddr_in in = sockaddr_in();
1806 10 : in.sin_family = AF_INET;
1807 10 : in.sin_port = htons(rand());
1808 : uint32_t address((100 << 24)
1809 10 : | (((rand() & 63) | 64) << 16)
1810 10 : | ((rand() & 255) << 8)
1811 10 : | ((rand() & 255) << 0));
1812 10 : in.sin_addr.s_addr = htonl(address);
1813 :
1814 : // verify network type
1815 : //
1816 10 : a.set_ipv4(in);
1817 10 : CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_CARRIER);
1818 10 : CATCH_REQUIRE(a.get_network_type_string() == "Carrier");
1819 : }
1820 : }
1821 :
1822 16 : CATCH_SECTION("private address 169.254.x.x/16")
1823 : {
1824 11 : for(int idx(0); idx < 10; ++idx)
1825 : {
1826 10 : struct sockaddr_in in = sockaddr_in();
1827 10 : in.sin_family = AF_INET;
1828 10 : in.sin_port = htons(rand());
1829 : uint32_t address((169 << 24)
1830 : | (254 << 16)
1831 10 : | ((rand() & 255) << 8)
1832 10 : | ((rand() & 255) << 0));
1833 10 : in.sin_addr.s_addr = htonl(address);
1834 :
1835 : // verify network type
1836 : //
1837 10 : a.set_ipv4(in);
1838 10 : CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LINK_LOCAL);
1839 10 : CATCH_REQUIRE(a.get_network_type_string() == "Local Link");
1840 : }
1841 : }
1842 :
1843 16 : CATCH_SECTION("private address 224.x.x.x/4")
1844 : {
1845 11 : for(int idx(0); idx < 10; ++idx)
1846 : {
1847 10 : struct sockaddr_in in = sockaddr_in();
1848 10 : in.sin_family = AF_INET;
1849 10 : in.sin_port = htons(rand());
1850 10 : uint32_t address((((rand() & 15) | 224) << 24)
1851 10 : | ((rand() & 255) << 16)
1852 10 : | ((rand() & 255) << 8)
1853 10 : | ((rand() & 255) << 0));
1854 10 : in.sin_addr.s_addr = htonl(address);
1855 :
1856 : // verify network type
1857 : //
1858 10 : a.set_ipv4(in);
1859 10 : CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_MULTICAST);
1860 10 : CATCH_REQUIRE(a.get_network_type_string() == "Multicast");
1861 :
1862 : // make sure no interface uses that IP
1863 : //
1864 10 : CATCH_REQUIRE(addr::find_addr_interface(a, false) == nullptr);
1865 : }
1866 : }
1867 :
1868 16 : CATCH_SECTION("private address 127.x.x.x/8")
1869 : {
1870 11 : for(int idx(0); idx < 10; ++idx)
1871 : {
1872 10 : struct sockaddr_in in = sockaddr_in();
1873 10 : in.sin_family = AF_INET;
1874 10 : in.sin_port = htons(rand());
1875 : uint32_t address((127 << 24)
1876 10 : | ((rand() & 255) << 16)
1877 10 : | ((rand() & 255) << 8)
1878 10 : | ((rand() & 255) << 0));
1879 10 : in.sin_addr.s_addr = htonl(address);
1880 :
1881 : // verify network type
1882 : //
1883 10 : a.set_ipv4(in);
1884 10 : CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LOOPBACK);
1885 10 : CATCH_REQUIRE(a.get_network_type_string() == "Loopback");
1886 : }
1887 : }
1888 : }
1889 8 : }
1890 :
1891 :
1892 8 : CATCH_TEST_CASE( "ipv4::network", "[ipv4]" )
1893 : {
1894 12 : CATCH_GIVEN("set_from_socket()")
1895 : {
1896 12 : CATCH_SECTION("invalid socket")
1897 : {
1898 1 : addr::addr a;
1899 1 : CATCH_REQUIRE_THROWS_AS(a.set_from_socket(-1, true), addr::addr_invalid_argument);
1900 1 : CATCH_REQUIRE_THROWS_AS(a.set_from_socket(-1, false), addr::addr_invalid_argument);
1901 : }
1902 :
1903 12 : CATCH_SECTION("non-opened file descriptor")
1904 : {
1905 1 : addr::addr a;
1906 :
1907 : // unless we have a bug, there should not be any file descriptor
1908 : // currently open with an ID of 1,000
1909 : //
1910 1 : CATCH_REQUIRE_THROWS_AS(a.set_from_socket(1000, true), addr::addr_io_error);
1911 1 : CATCH_REQUIRE_THROWS_AS(a.set_from_socket(1000, false), addr::addr_io_error);
1912 : }
1913 :
1914 12 : CATCH_SECTION("unknown socket type")
1915 : {
1916 1 : addr::addr a;
1917 :
1918 1 : int s(socket(AF_UNIX, SOCK_STREAM, 0));
1919 1 : CATCH_REQUIRE(s >= 0);
1920 2 : std::shared_ptr<int> auto_free(&s, socket_deleter);
1921 :
1922 : // unless we have a bug, there should not be any file descriptor
1923 : // currently open with an ID of 1,000
1924 : //
1925 1 : CATCH_REQUIRE_THROWS_AS(a.set_from_socket(s, true), addr::addr_io_error);
1926 1 : CATCH_REQUIRE_THROWS_AS(a.set_from_socket(s, false), addr::addr_invalid_state);
1927 : }
1928 :
1929 12 : CATCH_SECTION("create a server, but do not test it (yet)...")
1930 : {
1931 2 : addr::addr_parser p;
1932 2 : addr::addr_range::vector_t ips(p.parse("127.0.0.1:49999"));
1933 1 : CATCH_REQUIRE(ips.size() >= 1);
1934 :
1935 1 : addr::addr & a(ips[0].get_from());
1936 1 : int s(a.create_socket(addr::addr::SOCKET_FLAG_NONBLOCK | addr::addr::SOCKET_FLAG_CLOEXEC | addr::addr::SOCKET_FLAG_REUSE));
1937 1 : CATCH_REQUIRE(s >= 0);
1938 2 : std::shared_ptr<int> auto_free(&s, socket_deleter);
1939 :
1940 1 : CATCH_REQUIRE(a.bind(s) == 0);
1941 : }
1942 :
1943 12 : CATCH_SECTION("connect with TCP to 127.0.0.1")
1944 : {
1945 1 : if(SNAP_CATCH2_NAMESPACE::g_tcp_port != -1)
1946 : {
1947 2 : addr::addr_parser p;
1948 2 : addr::addr_range::vector_t ips(p.parse("127.0.0.1:" + std::to_string(SNAP_CATCH2_NAMESPACE::g_tcp_port)));
1949 1 : CATCH_REQUIRE(ips.size() >= 1);
1950 :
1951 1 : addr::addr & a(ips[0].get_from());
1952 1 : int s(a.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC));// | addr::addr::SOCKET_FLAG_REUSE));
1953 1 : CATCH_REQUIRE(s >= 0);
1954 2 : std::shared_ptr<int> auto_free(&s, socket_deleter);
1955 :
1956 1 : CATCH_REQUIRE(a.connect(s) == 0);
1957 :
1958 : // get socket info from the other side (peer == true)
1959 : //
1960 1 : addr::addr b;
1961 1 : b.set_from_socket(s, true);
1962 1 : CATCH_REQUIRE(b.is_ipv4());
1963 1 : CATCH_REQUIRE(b.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "127.0.0.1");
1964 1 : CATCH_REQUIRE(b.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "127.0.0.1");
1965 :
1966 : // in this case we know what the port is since we specified
1967 : // that when connecting
1968 : //
1969 1 : CATCH_REQUIRE(b.get_port() == SNAP_CATCH2_NAMESPACE::g_tcp_port);
1970 :
1971 : // now try this side (peer == false)
1972 : //
1973 1 : addr::addr c;
1974 1 : c.set_from_socket(s, false);
1975 1 : CATCH_REQUIRE(c.is_ipv4());
1976 1 : CATCH_REQUIRE(c.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "127.0.0.1");
1977 1 : CATCH_REQUIRE(c.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "127.0.0.1");
1978 :
1979 : // we cannot be sure of the port, there is a range we could
1980 : // test better (more constraining) but for this test is
1981 : // certainly does not matter much; it has to be more than
1982 : // 1023, though
1983 : //
1984 1 : CATCH_REQUIRE(c.get_port() > 1023);
1985 : }
1986 : else
1987 : {
1988 : // avoid issue of no assertions
1989 : //
1990 0 : CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::g_tcp_port == -1);
1991 0 : std::cout << "connect to 127.0.0.1 test skipped as no TCP port was specified on the command line." << std::endl;
1992 : }
1993 : }
1994 :
1995 12 : CATCH_SECTION("connect with UDP to 127.0.0.1")
1996 : {
1997 2 : addr::addr_parser p;
1998 1 : p.set_protocol("udp");
1999 2 : addr::addr_range::vector_t ips(p.parse("127.0.0.1:53"));
2000 1 : CATCH_REQUIRE(ips.size() >= 1);
2001 :
2002 1 : addr::addr & a(ips[0].get_from());
2003 1 : int s(a.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC));// | addr::addr::SOCKET_FLAG_REUSE));
2004 1 : CATCH_REQUIRE(s >= 0);
2005 2 : std::shared_ptr<int> auto_free(&s, socket_deleter);
2006 :
2007 1 : CATCH_REQUIRE(a.connect(s) == -1);
2008 :
2009 : // get socket info from the other side (peer == true)
2010 : //
2011 1 : addr::addr b;
2012 1 : CATCH_REQUIRE_THROWS_AS(b.set_from_socket(s, true), addr::addr_io_error);
2013 1 : CATCH_REQUIRE_FALSE(b.is_ipv4());
2014 1 : CATCH_REQUIRE(b.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::");
2015 1 : CATCH_REQUIRE(b.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::");
2016 :
2017 : // in this case we know what the port is since we specified
2018 : // that when connecting
2019 : //
2020 1 : CATCH_REQUIRE(b.get_port() == 0);
2021 :
2022 : // now try this side (peer == false)
2023 : //
2024 1 : addr::addr c;
2025 1 : c.set_from_socket(s, false);
2026 1 : CATCH_REQUIRE(c.is_ipv4());
2027 1 : CATCH_REQUIRE(c.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "0.0.0.0");
2028 1 : CATCH_REQUIRE(c.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "0.0.0.0");
2029 :
2030 : // we cannot be sure of the port, there is a range we could
2031 : // test better (more constraining) but for this test is
2032 : // certainly does not matter much; it has to be more than
2033 : // 1023, though
2034 : //
2035 1 : CATCH_REQUIRE(c.get_port() == 0);
2036 : }
2037 : }
2038 6 : }
2039 :
2040 :
2041 15 : CATCH_TEST_CASE( "ipv4::string_to_addr", "[ipv4]" )
2042 : {
2043 26 : CATCH_GIVEN("string_to_addr() ipv4")
2044 : {
2045 26 : CATCH_SECTION("empty address without defaults")
2046 : {
2047 1 : addr::addr a(addr::string_to_addr(std::string()));
2048 :
2049 1 : CATCH_REQUIRE(a.is_ipv4());
2050 :
2051 1 : struct sockaddr_in in = sockaddr_in();
2052 1 : in.sin_family = AF_INET;
2053 1 : in.sin_port = 0;
2054 1 : in.sin_addr.s_addr = htonl((0 << 24) | (0 << 16) | (0 << 8) | (0 << 0));
2055 :
2056 : // test string_to_addr accuracy
2057 : //
2058 1 : struct sockaddr_in out;
2059 1 : a.get_ipv4(out);
2060 1 : CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
2061 :
2062 1 : uint8_t mask[16];
2063 1 : a.get_mask(mask);
2064 1 : CATCH_REQUIRE(mask[ 0] == 0xFF);
2065 1 : CATCH_REQUIRE(mask[ 1] == 0xFF);
2066 1 : CATCH_REQUIRE(mask[ 2] == 0xFF);
2067 1 : CATCH_REQUIRE(mask[ 3] == 0xFF);
2068 1 : CATCH_REQUIRE(mask[ 4] == 0xFF);
2069 1 : CATCH_REQUIRE(mask[ 5] == 0xFF);
2070 1 : CATCH_REQUIRE(mask[ 6] == 0xFF);
2071 1 : CATCH_REQUIRE(mask[ 7] == 0xFF);
2072 1 : CATCH_REQUIRE(mask[ 8] == 0xFF);
2073 1 : CATCH_REQUIRE(mask[ 9] == 0xFF);
2074 1 : CATCH_REQUIRE(mask[10] == 0xFF);
2075 1 : CATCH_REQUIRE(mask[11] == 0xFF);
2076 1 : CATCH_REQUIRE(mask[12] == 0xFF);
2077 1 : CATCH_REQUIRE(mask[13] == 0xFF);
2078 1 : CATCH_REQUIRE(mask[14] == 0xFF);
2079 1 : CATCH_REQUIRE(mask[15] == 0xFF);
2080 : }
2081 26 : CATCH_SECTION("explicit defaults")
2082 : {
2083 1 : addr::addr a(addr::string_to_addr("5.14.34.111", std::string(), -1, std::string(), false));
2084 :
2085 1 : CATCH_REQUIRE(a.is_ipv4());
2086 :
2087 1 : struct sockaddr_in in = sockaddr_in();
2088 1 : in.sin_family = AF_INET;
2089 1 : in.sin_port = 0;
2090 1 : in.sin_addr.s_addr = htonl((5 << 24) | (14 << 16) | (34 << 8) | (111 << 0));
2091 :
2092 : // test string_to_addr accuracy
2093 : //
2094 1 : struct sockaddr_in out;
2095 1 : a.get_ipv4(out);
2096 1 : CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
2097 :
2098 1 : uint8_t mask[16];
2099 1 : a.get_mask(mask);
2100 1 : CATCH_REQUIRE(mask[ 0] == 0xFF);
2101 1 : CATCH_REQUIRE(mask[ 1] == 0xFF);
2102 1 : CATCH_REQUIRE(mask[ 2] == 0xFF);
2103 1 : CATCH_REQUIRE(mask[ 3] == 0xFF);
2104 1 : CATCH_REQUIRE(mask[ 4] == 0xFF);
2105 1 : CATCH_REQUIRE(mask[ 5] == 0xFF);
2106 1 : CATCH_REQUIRE(mask[ 6] == 0xFF);
2107 1 : CATCH_REQUIRE(mask[ 7] == 0xFF);
2108 1 : CATCH_REQUIRE(mask[ 8] == 0xFF);
2109 1 : CATCH_REQUIRE(mask[ 9] == 0xFF);
2110 1 : CATCH_REQUIRE(mask[10] == 0xFF);
2111 1 : CATCH_REQUIRE(mask[11] == 0xFF);
2112 1 : CATCH_REQUIRE(mask[12] == 0xFF);
2113 1 : CATCH_REQUIRE(mask[13] == 0xFF);
2114 1 : CATCH_REQUIRE(mask[14] == 0xFF);
2115 1 : CATCH_REQUIRE(mask[15] == 0xFF);
2116 : }
2117 26 : CATCH_SECTION("defaults")
2118 : {
2119 1 : addr::addr a(addr::string_to_addr("7.149.104.211"));
2120 :
2121 1 : CATCH_REQUIRE(a.is_ipv4());
2122 :
2123 1 : struct sockaddr_in in = sockaddr_in();
2124 1 : in.sin_family = AF_INET;
2125 1 : in.sin_port = 0;
2126 1 : in.sin_addr.s_addr = htonl((7 << 24) | (149 << 16) | (104 << 8) | (211 << 0));
2127 :
2128 : // test string_to_addr accuracy
2129 : //
2130 1 : struct sockaddr_in out;
2131 1 : a.get_ipv4(out);
2132 1 : CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
2133 :
2134 1 : uint8_t mask[16];
2135 1 : a.get_mask(mask);
2136 1 : CATCH_REQUIRE(mask[ 0] == 0xFF);
2137 1 : CATCH_REQUIRE(mask[ 1] == 0xFF);
2138 1 : CATCH_REQUIRE(mask[ 2] == 0xFF);
2139 1 : CATCH_REQUIRE(mask[ 3] == 0xFF);
2140 1 : CATCH_REQUIRE(mask[ 4] == 0xFF);
2141 1 : CATCH_REQUIRE(mask[ 5] == 0xFF);
2142 1 : CATCH_REQUIRE(mask[ 6] == 0xFF);
2143 1 : CATCH_REQUIRE(mask[ 7] == 0xFF);
2144 1 : CATCH_REQUIRE(mask[ 8] == 0xFF);
2145 1 : CATCH_REQUIRE(mask[ 9] == 0xFF);
2146 1 : CATCH_REQUIRE(mask[10] == 0xFF);
2147 1 : CATCH_REQUIRE(mask[11] == 0xFF);
2148 1 : CATCH_REQUIRE(mask[12] == 0xFF);
2149 1 : CATCH_REQUIRE(mask[13] == 0xFF);
2150 1 : CATCH_REQUIRE(mask[14] == 0xFF);
2151 1 : CATCH_REQUIRE(mask[15] == 0xFF);
2152 : }
2153 26 : CATCH_SECTION("addr & default addr")
2154 : {
2155 1 : addr::addr a(addr::string_to_addr("37.149.174.11", "1.205.32.11"));
2156 :
2157 1 : CATCH_REQUIRE(a.is_ipv4());
2158 :
2159 1 : struct sockaddr_in in = sockaddr_in();
2160 1 : in.sin_family = AF_INET;
2161 1 : in.sin_port = 0;
2162 1 : in.sin_addr.s_addr = htonl((37 << 24) | (149 << 16) | (174 << 8) | (11 << 0));
2163 :
2164 : // test string_to_addr accuracy
2165 : //
2166 1 : struct sockaddr_in out;
2167 1 : a.get_ipv4(out);
2168 1 : CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
2169 :
2170 1 : uint8_t mask[16];
2171 1 : a.get_mask(mask);
2172 1 : CATCH_REQUIRE(mask[ 0] == 0xFF);
2173 1 : CATCH_REQUIRE(mask[ 1] == 0xFF);
2174 1 : CATCH_REQUIRE(mask[ 2] == 0xFF);
2175 1 : CATCH_REQUIRE(mask[ 3] == 0xFF);
2176 1 : CATCH_REQUIRE(mask[ 4] == 0xFF);
2177 1 : CATCH_REQUIRE(mask[ 5] == 0xFF);
2178 1 : CATCH_REQUIRE(mask[ 6] == 0xFF);
2179 1 : CATCH_REQUIRE(mask[ 7] == 0xFF);
2180 1 : CATCH_REQUIRE(mask[ 8] == 0xFF);
2181 1 : CATCH_REQUIRE(mask[ 9] == 0xFF);
2182 1 : CATCH_REQUIRE(mask[10] == 0xFF);
2183 1 : CATCH_REQUIRE(mask[11] == 0xFF);
2184 1 : CATCH_REQUIRE(mask[12] == 0xFF);
2185 1 : CATCH_REQUIRE(mask[13] == 0xFF);
2186 1 : CATCH_REQUIRE(mask[14] == 0xFF);
2187 1 : CATCH_REQUIRE(mask[15] == 0xFF);
2188 : }
2189 26 : CATCH_SECTION("no addr, expect default addr")
2190 : {
2191 1 : addr::addr a(addr::string_to_addr("", "1.205.32.11"));
2192 :
2193 1 : CATCH_REQUIRE(a.is_ipv4());
2194 :
2195 1 : struct sockaddr_in in = sockaddr_in();
2196 1 : in.sin_family = AF_INET;
2197 1 : in.sin_port = 0;
2198 1 : in.sin_addr.s_addr = htonl((1 << 24) | (205 << 16) | (32 << 8) | (11 << 0));
2199 :
2200 : // test string_to_addr accuracy
2201 : //
2202 1 : struct sockaddr_in out;
2203 1 : a.get_ipv4(out);
2204 1 : CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
2205 :
2206 1 : uint8_t mask[16];
2207 1 : a.get_mask(mask);
2208 1 : CATCH_REQUIRE(mask[ 0] == 0xFF);
2209 1 : CATCH_REQUIRE(mask[ 1] == 0xFF);
2210 1 : CATCH_REQUIRE(mask[ 2] == 0xFF);
2211 1 : CATCH_REQUIRE(mask[ 3] == 0xFF);
2212 1 : CATCH_REQUIRE(mask[ 4] == 0xFF);
2213 1 : CATCH_REQUIRE(mask[ 5] == 0xFF);
2214 1 : CATCH_REQUIRE(mask[ 6] == 0xFF);
2215 1 : CATCH_REQUIRE(mask[ 7] == 0xFF);
2216 1 : CATCH_REQUIRE(mask[ 8] == 0xFF);
2217 1 : CATCH_REQUIRE(mask[ 9] == 0xFF);
2218 1 : CATCH_REQUIRE(mask[10] == 0xFF);
2219 1 : CATCH_REQUIRE(mask[11] == 0xFF);
2220 1 : CATCH_REQUIRE(mask[12] == 0xFF);
2221 1 : CATCH_REQUIRE(mask[13] == 0xFF);
2222 1 : CATCH_REQUIRE(mask[14] == 0xFF);
2223 1 : CATCH_REQUIRE(mask[15] == 0xFF);
2224 : }
2225 26 : CATCH_SECTION("addr and port, with a default port")
2226 : {
2227 1 : addr::addr a(addr::string_to_addr("69.109.223.17:697", "1.205.32.11", 123));
2228 :
2229 1 : CATCH_REQUIRE(a.is_ipv4());
2230 :
2231 1 : struct sockaddr_in in = sockaddr_in();
2232 1 : in.sin_family = AF_INET;
2233 1 : in.sin_port = htons(697);
2234 1 : in.sin_addr.s_addr = htonl((69 << 24) | (109 << 16) | (223 << 8) | (17 << 0));
2235 :
2236 : // test string_to_addr accuracy
2237 : //
2238 1 : struct sockaddr_in out;
2239 1 : a.get_ipv4(out);
2240 1 : CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
2241 :
2242 1 : uint8_t mask[16];
2243 1 : a.get_mask(mask);
2244 1 : CATCH_REQUIRE(mask[ 0] == 0xFF);
2245 1 : CATCH_REQUIRE(mask[ 1] == 0xFF);
2246 1 : CATCH_REQUIRE(mask[ 2] == 0xFF);
2247 1 : CATCH_REQUIRE(mask[ 3] == 0xFF);
2248 1 : CATCH_REQUIRE(mask[ 4] == 0xFF);
2249 1 : CATCH_REQUIRE(mask[ 5] == 0xFF);
2250 1 : CATCH_REQUIRE(mask[ 6] == 0xFF);
2251 1 : CATCH_REQUIRE(mask[ 7] == 0xFF);
2252 1 : CATCH_REQUIRE(mask[ 8] == 0xFF);
2253 1 : CATCH_REQUIRE(mask[ 9] == 0xFF);
2254 1 : CATCH_REQUIRE(mask[10] == 0xFF);
2255 1 : CATCH_REQUIRE(mask[11] == 0xFF);
2256 1 : CATCH_REQUIRE(mask[12] == 0xFF);
2257 1 : CATCH_REQUIRE(mask[13] == 0xFF);
2258 1 : CATCH_REQUIRE(mask[14] == 0xFF);
2259 1 : CATCH_REQUIRE(mask[15] == 0xFF);
2260 : }
2261 26 : CATCH_SECTION("addr without port, with a default port")
2262 : {
2263 1 : addr::addr a(addr::string_to_addr("169.209.23.217", "1.205.32.11", 123));
2264 :
2265 1 : CATCH_REQUIRE(a.is_ipv4());
2266 :
2267 1 : struct sockaddr_in in = sockaddr_in();
2268 1 : in.sin_family = AF_INET;
2269 1 : in.sin_port = htons(123);
2270 1 : in.sin_addr.s_addr = htonl((169 << 24) | (209 << 16) | (23 << 8) | (217 << 0));
2271 :
2272 : // test string_to_addr accuracy
2273 : //
2274 1 : struct sockaddr_in out;
2275 1 : a.get_ipv4(out);
2276 1 : CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
2277 :
2278 1 : uint8_t mask[16];
2279 1 : a.get_mask(mask);
2280 1 : CATCH_REQUIRE(mask[ 0] == 0xFF);
2281 1 : CATCH_REQUIRE(mask[ 1] == 0xFF);
2282 1 : CATCH_REQUIRE(mask[ 2] == 0xFF);
2283 1 : CATCH_REQUIRE(mask[ 3] == 0xFF);
2284 1 : CATCH_REQUIRE(mask[ 4] == 0xFF);
2285 1 : CATCH_REQUIRE(mask[ 5] == 0xFF);
2286 1 : CATCH_REQUIRE(mask[ 6] == 0xFF);
2287 1 : CATCH_REQUIRE(mask[ 7] == 0xFF);
2288 1 : CATCH_REQUIRE(mask[ 8] == 0xFF);
2289 1 : CATCH_REQUIRE(mask[ 9] == 0xFF);
2290 1 : CATCH_REQUIRE(mask[10] == 0xFF);
2291 1 : CATCH_REQUIRE(mask[11] == 0xFF);
2292 1 : CATCH_REQUIRE(mask[12] == 0xFF);
2293 1 : CATCH_REQUIRE(mask[13] == 0xFF);
2294 1 : CATCH_REQUIRE(mask[14] == 0xFF);
2295 1 : CATCH_REQUIRE(mask[15] == 0xFF);
2296 : }
2297 26 : CATCH_SECTION("addr without port but protocol")
2298 : {
2299 1 : addr::addr a(addr::string_to_addr("4.5.123.7", "1.205.32.11", 60000, "tcp"));
2300 :
2301 1 : CATCH_REQUIRE(a.is_ipv4());
2302 :
2303 1 : struct sockaddr_in in = sockaddr_in();
2304 1 : in.sin_family = AF_INET;
2305 1 : in.sin_port = htons(60000);
2306 1 : in.sin_addr.s_addr = htonl((4 << 24) | (5 << 16) | (123 << 8) | (7 << 0));
2307 :
2308 : // test string_to_addr accuracy
2309 : //
2310 1 : struct sockaddr_in out;
2311 1 : a.get_ipv4(out);
2312 1 : CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
2313 :
2314 1 : uint8_t mask[16];
2315 1 : a.get_mask(mask);
2316 1 : CATCH_REQUIRE(mask[ 0] == 0xFF);
2317 1 : CATCH_REQUIRE(mask[ 1] == 0xFF);
2318 1 : CATCH_REQUIRE(mask[ 2] == 0xFF);
2319 1 : CATCH_REQUIRE(mask[ 3] == 0xFF);
2320 1 : CATCH_REQUIRE(mask[ 4] == 0xFF);
2321 1 : CATCH_REQUIRE(mask[ 5] == 0xFF);
2322 1 : CATCH_REQUIRE(mask[ 6] == 0xFF);
2323 1 : CATCH_REQUIRE(mask[ 7] == 0xFF);
2324 1 : CATCH_REQUIRE(mask[ 8] == 0xFF);
2325 1 : CATCH_REQUIRE(mask[ 9] == 0xFF);
2326 1 : CATCH_REQUIRE(mask[10] == 0xFF);
2327 1 : CATCH_REQUIRE(mask[11] == 0xFF);
2328 1 : CATCH_REQUIRE(mask[12] == 0xFF);
2329 1 : CATCH_REQUIRE(mask[13] == 0xFF);
2330 1 : CATCH_REQUIRE(mask[14] == 0xFF);
2331 1 : CATCH_REQUIRE(mask[15] == 0xFF);
2332 : }
2333 26 : CATCH_SECTION("addr with port and protocol")
2334 : {
2335 1 : addr::addr a(addr::string_to_addr("204.105.13.9:65", "1.205.32.11", 60000, "tcp"));
2336 :
2337 1 : CATCH_REQUIRE(a.is_ipv4());
2338 :
2339 1 : struct sockaddr_in in = sockaddr_in();
2340 1 : in.sin_family = AF_INET;
2341 1 : in.sin_port = htons(65);
2342 1 : in.sin_addr.s_addr = htonl((204 << 24) | (105 << 16) | (13 << 8) | (9 << 0));
2343 :
2344 : // test string_to_addr accuracy
2345 : //
2346 1 : struct sockaddr_in out;
2347 1 : a.get_ipv4(out);
2348 1 : CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
2349 :
2350 1 : uint8_t mask[16];
2351 1 : a.get_mask(mask);
2352 1 : CATCH_REQUIRE(mask[ 0] == 0xFF);
2353 1 : CATCH_REQUIRE(mask[ 1] == 0xFF);
2354 1 : CATCH_REQUIRE(mask[ 2] == 0xFF);
2355 1 : CATCH_REQUIRE(mask[ 3] == 0xFF);
2356 1 : CATCH_REQUIRE(mask[ 4] == 0xFF);
2357 1 : CATCH_REQUIRE(mask[ 5] == 0xFF);
2358 1 : CATCH_REQUIRE(mask[ 6] == 0xFF);
2359 1 : CATCH_REQUIRE(mask[ 7] == 0xFF);
2360 1 : CATCH_REQUIRE(mask[ 8] == 0xFF);
2361 1 : CATCH_REQUIRE(mask[ 9] == 0xFF);
2362 1 : CATCH_REQUIRE(mask[10] == 0xFF);
2363 1 : CATCH_REQUIRE(mask[11] == 0xFF);
2364 1 : CATCH_REQUIRE(mask[12] == 0xFF);
2365 1 : CATCH_REQUIRE(mask[13] == 0xFF);
2366 1 : CATCH_REQUIRE(mask[14] == 0xFF);
2367 1 : CATCH_REQUIRE(mask[15] == 0xFF);
2368 : }
2369 26 : CATCH_SECTION("addr with port and protocol but no mask, albeit allowed")
2370 : {
2371 1 : addr::addr a(addr::string_to_addr("94.95.131.18:765", "11.205.32.21", 54003, "tcp", true));
2372 :
2373 1 : CATCH_REQUIRE(a.is_ipv4());
2374 :
2375 1 : struct sockaddr_in in = sockaddr_in();
2376 1 : in.sin_family = AF_INET;
2377 1 : in.sin_port = htons(765);
2378 1 : in.sin_addr.s_addr = htonl((94 << 24) | (95 << 16) | (131 << 8) | (18 << 0));
2379 :
2380 : // test string_to_addr accuracy
2381 : //
2382 1 : struct sockaddr_in out;
2383 1 : a.get_ipv4(out);
2384 1 : CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
2385 :
2386 1 : uint8_t mask[16];
2387 1 : a.get_mask(mask);
2388 1 : CATCH_REQUIRE(mask[ 0] == 0xFF);
2389 1 : CATCH_REQUIRE(mask[ 1] == 0xFF);
2390 1 : CATCH_REQUIRE(mask[ 2] == 0xFF);
2391 1 : CATCH_REQUIRE(mask[ 3] == 0xFF);
2392 1 : CATCH_REQUIRE(mask[ 4] == 0xFF);
2393 1 : CATCH_REQUIRE(mask[ 5] == 0xFF);
2394 1 : CATCH_REQUIRE(mask[ 6] == 0xFF);
2395 1 : CATCH_REQUIRE(mask[ 7] == 0xFF);
2396 1 : CATCH_REQUIRE(mask[ 8] == 0xFF);
2397 1 : CATCH_REQUIRE(mask[ 9] == 0xFF);
2398 1 : CATCH_REQUIRE(mask[10] == 0xFF);
2399 1 : CATCH_REQUIRE(mask[11] == 0xFF);
2400 1 : CATCH_REQUIRE(mask[12] == 0xFF);
2401 1 : CATCH_REQUIRE(mask[13] == 0xFF);
2402 1 : CATCH_REQUIRE(mask[14] == 0xFF);
2403 1 : CATCH_REQUIRE(mask[15] == 0xFF);
2404 : }
2405 26 : CATCH_SECTION("addr with port and protocol and mask, albeit allowed")
2406 : {
2407 1 : addr::addr a(addr::string_to_addr("44.45.141.48:765/30", "11.205.32.21", 54003, "tcp", true));
2408 :
2409 1 : CATCH_REQUIRE(a.is_ipv4());
2410 :
2411 1 : struct sockaddr_in in = sockaddr_in();
2412 1 : in.sin_family = AF_INET;
2413 1 : in.sin_port = htons(765);
2414 1 : in.sin_addr.s_addr = htonl((44 << 24) | (45 << 16) | (141 << 8) | (48 << 0));
2415 :
2416 : // test string_to_addr accuracy
2417 : //
2418 1 : struct sockaddr_in out;
2419 1 : a.get_ipv4(out);
2420 1 : CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
2421 :
2422 1 : uint8_t mask[16];
2423 1 : a.get_mask(mask);
2424 1 : CATCH_REQUIRE(mask[ 0] == 0xFF);
2425 1 : CATCH_REQUIRE(mask[ 1] == 0xFF);
2426 1 : CATCH_REQUIRE(mask[ 2] == 0xFF);
2427 1 : CATCH_REQUIRE(mask[ 3] == 0xFF);
2428 1 : CATCH_REQUIRE(mask[ 4] == 0xFF);
2429 1 : CATCH_REQUIRE(mask[ 5] == 0xFF);
2430 1 : CATCH_REQUIRE(mask[ 6] == 0xFF);
2431 1 : CATCH_REQUIRE(mask[ 7] == 0xFF);
2432 1 : CATCH_REQUIRE(mask[ 8] == 0xFF);
2433 1 : CATCH_REQUIRE(mask[ 9] == 0xFF);
2434 1 : CATCH_REQUIRE(mask[10] == 0xFF);
2435 1 : CATCH_REQUIRE(mask[11] == 0xFF);
2436 1 : CATCH_REQUIRE(mask[12] == 0xFF);
2437 1 : CATCH_REQUIRE(mask[13] == 0xFF);
2438 1 : CATCH_REQUIRE(mask[14] == 0xFF);
2439 1 : CATCH_REQUIRE(mask[15] == 0xFC);
2440 : }
2441 26 : CATCH_SECTION("addr with port and protocol and mask, albeit allowed")
2442 : {
2443 1 : addr::addr a(addr::string_to_addr("160.0.0.0:1675/4", "11.205.32.21", 14003, "udp", true));
2444 :
2445 1 : CATCH_REQUIRE(a.is_ipv4());
2446 :
2447 1 : struct sockaddr_in in = sockaddr_in();
2448 1 : in.sin_family = AF_INET;
2449 1 : in.sin_port = htons(1675);
2450 1 : in.sin_addr.s_addr = htonl((160 << 24) | (0 << 16) | (0 << 8) | (0 << 0));
2451 :
2452 : // test string_to_addr accuracy
2453 : //
2454 1 : struct sockaddr_in out;
2455 1 : a.get_ipv4(out);
2456 1 : CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
2457 :
2458 1 : uint8_t mask[16];
2459 1 : a.get_mask(mask);
2460 1 : CATCH_REQUIRE(mask[ 0] == 0xFF);
2461 1 : CATCH_REQUIRE(mask[ 1] == 0xFF);
2462 1 : CATCH_REQUIRE(mask[ 2] == 0xFF);
2463 1 : CATCH_REQUIRE(mask[ 3] == 0xFF);
2464 1 : CATCH_REQUIRE(mask[ 4] == 0xFF);
2465 1 : CATCH_REQUIRE(mask[ 5] == 0xFF);
2466 1 : CATCH_REQUIRE(mask[ 6] == 0xFF);
2467 1 : CATCH_REQUIRE(mask[ 7] == 0xFF);
2468 1 : CATCH_REQUIRE(mask[ 8] == 0xFF);
2469 1 : CATCH_REQUIRE(mask[ 9] == 0xFF);
2470 1 : CATCH_REQUIRE(mask[10] == 0xFF);
2471 1 : CATCH_REQUIRE(mask[11] == 0xFF);
2472 1 : CATCH_REQUIRE(mask[12] == 0xF0);
2473 1 : CATCH_REQUIRE(mask[13] == 0x00);
2474 1 : CATCH_REQUIRE(mask[14] == 0x00);
2475 1 : CATCH_REQUIRE(mask[15] == 0x00);
2476 : }
2477 26 : CATCH_SECTION("addr with port and invalid protocol so we get an exception")
2478 : {
2479 1 : CATCH_REQUIRE_THROWS_AS(addr::string_to_addr("169.60.33.0:9322/24", std::string(), -1, "icmp", true),
2480 : addr::addr_invalid_argument);
2481 : }
2482 : }
2483 : // TODO: add ipv6 tests, although at this point it's not too
2484 : // important here, it may change in the future
2485 : //
2486 :
2487 : //addr string_to_addr(
2488 : // std::string const & a
2489 : // , std::string const & default_address = std::string()
2490 : // , int default_port = -1
2491 : // , std::string const & protocol = std::string()
2492 : // , bool mask = false);
2493 19 : }
2494 :
2495 :
2496 : // vim: ts=4 sw=4 et
|