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