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