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