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