Line data Source code
1 : /* test_addr_ipv6.cpp
2 : * Copyright (c) 2011-2018 Made to Order Software Corp. All Rights Reserved
3 : *
4 : * Project: https://snapwebsites.org/project/libaddr
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 test include a certain number of default/global
41 : * test because by default the addr class implements an IPv6 object.
42 : */
43 :
44 : // self
45 : //
46 : #include "test_addr_main.h"
47 :
48 : // addr lib
49 : //
50 : #include "libaddr/iface.h"
51 :
52 :
53 :
54 :
55 : /** \brief Details used by the addr class implementation.
56 : *
57 : * We have a function to check whether an address is part of
58 : * the interfaces of your computer. This check requires the
59 : * use of a `struct ifaddrs` and as such it requires to
60 : * delete that structure. We define a deleter for that
61 : * strucure here.
62 : */
63 : namespace
64 : {
65 :
66 : /** \brief Delete an ifaddrs structure.
67 : *
68 : * This deleter is used to make sure all the ifaddrs get released when
69 : * an exception occurs or the function using such exists.
70 : *
71 : * \param[in] ia The ifaddrs structure to free.
72 : */
73 3 : void socket_deleter(int * s)
74 : {
75 3 : close(*s);
76 3 : }
77 :
78 :
79 : }
80 : // no name namespace
81 :
82 :
83 :
84 16 : TEST_CASE( "ipv6::invalid_input", "[ipv6]" )
85 : {
86 28 : GIVEN("addr()")
87 : {
88 1 : addr::addr a;
89 :
90 2 : SECTION("set IPv6 with an invalid family")
91 : {
92 1 : struct sockaddr_in6 in6 = sockaddr_in6();
93 0 : do
94 : {
95 1 : in6.sin6_family = rand();
96 : }
97 1 : while(in6.sin6_family == AF_INET6);
98 1 : in6.sin6_port = rand();
99 9 : for(int idx(0); idx < 8; ++idx)
100 : {
101 8 : in6.sin6_addr.s6_addr16[idx] = rand();
102 : }
103 1 : REQUIRE_THROWS_AS(a.set_ipv6(in6), addr::addr_invalid_argument_exception);
104 1 : REQUIRE_THROWS_AS(addr::addr b(in6), addr::addr_invalid_argument_exception);
105 : }
106 : }
107 :
108 28 : GIVEN("addr_parser() with IPv6 addresses")
109 : {
110 6 : SECTION("bad address")
111 : {
112 2 : addr::addr_parser p;
113 2 : addr::addr_range::vector_t ips(p.parse("[{bad-ip}]"));
114 1 : REQUIRE(p.has_errors());
115 1 : REQUIRE(p.error_count() == 1);
116 1 : REQUIRE(p.error_messages() == "Invalid address in \"{bad-ip}\" error -2 -- Name or service not known (errno: 2 -- No such file or directory).\n");
117 1 : REQUIRE(ips.size() == 0);
118 : }
119 :
120 6 : SECTION("missing ']'")
121 : {
122 2 : addr::addr_parser p;
123 2 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7"));
124 1 : REQUIRE(p.has_errors());
125 1 : REQUIRE(p.error_count() == 1);
126 1 : REQUIRE(p.error_messages() == "IPv6 is missing the ']' ([1:2:3:4:5:6:7).\n");
127 1 : REQUIRE(ips.size() == 0);
128 : }
129 :
130 6 : SECTION("required address")
131 : {
132 2 : addr::addr_parser p;
133 1 : p.set_protocol(IPPROTO_TCP);
134 1 : p.set_allow(addr::addr_parser::flag_t::REQUIRED_ADDRESS, true);
135 2 : addr::addr_range::vector_t ips(p.parse("[]"));
136 1 : REQUIRE(p.has_errors());
137 1 : REQUIRE(p.error_count() == 1);
138 1 : REQUIRE(p.error_messages() == "Required address is missing.\n");
139 1 : REQUIRE(ips.size() == 0);
140 : }
141 : }
142 :
143 28 : GIVEN("addr_parser() with IPv4 ports")
144 : {
145 4 : SECTION("required port")
146 : {
147 : // optional + required -> required
148 : {
149 2 : addr::addr_parser p;
150 1 : p.set_protocol(IPPROTO_TCP);
151 1 : p.set_allow(addr::addr_parser::flag_t::REQUIRED_PORT, true);
152 2 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]"));
153 1 : REQUIRE(p.has_errors());
154 1 : REQUIRE(p.error_count() == 1);
155 1 : REQUIRE(p.error_messages() == "Required port is missing.\n");
156 1 : REQUIRE(ips.size() == 0);
157 : }
158 :
159 : // only required -> required just the same
160 : {
161 2 : addr::addr_parser p;
162 1 : p.set_protocol(IPPROTO_TCP);
163 1 : p.set_allow(addr::addr_parser::flag_t::PORT, false);
164 1 : p.set_allow(addr::addr_parser::flag_t::REQUIRED_PORT, true);
165 2 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]"));
166 1 : REQUIRE(p.has_errors());
167 1 : REQUIRE(p.error_count() == 1);
168 1 : REQUIRE(p.error_messages() == "Required port is missing.\n");
169 1 : REQUIRE(ips.size() == 0);
170 : }
171 : }
172 :
173 4 : SECTION("port not allowed")
174 : {
175 : {
176 2 : addr::addr_parser p;
177 1 : p.set_protocol(IPPROTO_TCP);
178 1 : p.set_allow(addr::addr_parser::flag_t::PORT, false);
179 2 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:123"));
180 1 : REQUIRE(p.has_errors());
181 1 : REQUIRE(p.error_count() == 1);
182 1 : REQUIRE(p.error_messages() == "Port not allowed ([1:2:3:4:5:6:7:8]:123).\n");
183 1 : REQUIRE(ips.size() == 0);
184 : }
185 :
186 : {
187 2 : addr::addr_parser p;
188 1 : p.set_protocol(IPPROTO_TCP);
189 1 : p.set_allow(addr::addr_parser::flag_t::PORT, false);
190 2 : addr::addr_range::vector_t ips(p.parse("1:2:3:4:5:6:7:8:123.5"));
191 1 : REQUIRE(p.has_errors());
192 1 : REQUIRE(p.error_count() == 1);
193 1 : REQUIRE(p.error_messages() == "Port not allowed (1:2:3:4:5:6:7:8:123.5).\n");
194 1 : REQUIRE(ips.size() == 0);
195 : }
196 : }
197 : }
198 :
199 28 : GIVEN("addr_parser() with invalid masks")
200 : {
201 16 : SECTION("really large numbers (over 1000)")
202 : {
203 6 : for(int idx(0); idx < 5; ++idx)
204 : {
205 5 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
206 5 : int const port(rand() & 0xFFFF);
207 5 : int const mask((rand() & 0xFF) + 1001);
208 10 : addr::addr_parser p;
209 5 : p.set_protocol(proto);
210 5 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
211 10 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/" + std::to_string(mask)));
212 5 : REQUIRE(p.has_errors());
213 5 : REQUIRE(p.error_count() == 1);
214 5 : REQUIRE(p.error_messages() == "Mask number too large (" + std::to_string(mask) + ", expected a maximum of 128).\n");
215 5 : REQUIRE(ips.size() == 0);
216 : }
217 :
218 : // in case the number is between square brackets it looks like
219 : // an IPv4 to getaddrinfo() so we get a different error...
220 : // (i.e. the '[' is not a digit so we do not get the "too large"
221 : // error...)
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) + 1001);
228 10 : addr::addr_parser p;
229 5 : p.set_protocol(proto);
230 5 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
231 10 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/[" + std::to_string(mask) + "]"));
232 5 : REQUIRE(p.has_errors());
233 5 : REQUIRE(p.error_count() == 1);
234 5 : REQUIRE(p.error_messages() == "Incompatible address between the address and mask address (first was an IPv6 second an IPv4).\n");
235 5 : REQUIRE(ips.size() == 0);
236 : }
237 :
238 : // an empty address with a mask too large gets us to another place
239 : //
240 6 : for(int idx(0); idx < 5; ++idx)
241 : {
242 5 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
243 5 : int const port(rand() & 0xFFFF);
244 5 : int const mask((rand() & 0xFF) + 1001);
245 10 : addr::addr_parser p;
246 5 : p.set_protocol(proto);
247 5 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
248 10 : addr::addr_range::vector_t ips(p.parse(":" + std::to_string(port) + "/" + std::to_string(mask)));
249 5 : REQUIRE(p.has_errors());
250 5 : REQUIRE(p.error_count() == 1);
251 5 : REQUIRE(p.error_messages() == "Mask number too large (" + std::to_string(mask) + ", expected a maximum of 128).\n");
252 5 : REQUIRE(ips.size() == 0);
253 : }
254 :
255 : // an empty address with a mask too large gets us to another place
256 : //
257 6 : for(int idx(0); idx < 5; ++idx)
258 : {
259 5 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
260 5 : int const port(rand() & 0xFFFF);
261 5 : int const mask((rand() & 0xFF));
262 10 : addr::addr_parser p;
263 5 : p.set_protocol(proto);
264 5 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
265 10 : addr::addr_range::vector_t ips(p.parse(":" + std::to_string(port) + "/" + std::to_string(mask) + "q"));
266 5 : REQUIRE(p.has_errors());
267 5 : REQUIRE(p.error_count() == 1);
268 5 : REQUIRE(p.error_messages() == "Invalid mask in \"/" + std::to_string(mask) + "q\", error -2 -- Name or service not known (errno: 0 -- Success).\n");
269 5 : REQUIRE(ips.size() == 0);
270 : }
271 : }
272 :
273 16 : SECTION("ipv6 mask is limited between 0 and 128")
274 : {
275 6 : for(int idx(0); idx < 5; ++idx)
276 : {
277 5 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
278 5 : int const port(rand() & 0xFFFF);
279 5 : int const mask((rand() & 0xFF) + 129);
280 10 : addr::addr_parser p;
281 5 : p.set_protocol(proto);
282 5 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
283 10 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/" + std::to_string(mask)));
284 5 : REQUIRE(p.has_errors());
285 5 : REQUIRE(p.error_count() == 1);
286 5 : REQUIRE(p.error_messages() == "Unsupported mask size (" + std::to_string(mask) + ", expected 128 at the most for an IPv6).\n");
287 5 : REQUIRE(ips.size() == 0);
288 : }
289 : }
290 :
291 16 : SECTION("ipv6 mask cannot use name")
292 : {
293 6 : for(int idx(0); idx < 5; ++idx)
294 : {
295 5 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
296 5 : int const port(rand() & 0xFFFF);
297 10 : addr::addr_parser p;
298 5 : p.set_protocol(proto);
299 5 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
300 10 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/[localhost]"));
301 5 : REQUIRE(p.has_errors());
302 5 : REQUIRE(p.error_count() == 1);
303 5 : REQUIRE(p.error_messages() == "Invalid mask in \"/[localhost]\", error -2 -- Name or service not known (errno: 0 -- Success).\n");
304 5 : REQUIRE(ips.size() == 0);
305 : }
306 : }
307 :
308 16 : SECTION("ipv6 mask must be between '[...]'")
309 : {
310 1 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
311 1 : int const port(rand() & 0xFFFF);
312 2 : addr::addr_parser p;
313 1 : p.set_protocol(proto);
314 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
315 2 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/::3"));
316 1 : REQUIRE(p.has_errors());
317 1 : REQUIRE(p.error_count() == 1);
318 1 : REQUIRE(p.error_messages() == "The address uses the IPv6 syntax, the mask cannot use IPv4.\n");
319 1 : REQUIRE(ips.size() == 0);
320 : }
321 :
322 16 : SECTION("ipv6 mask missing the ']'")
323 : {
324 1 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
325 1 : int const port(rand() & 0xFFFF);
326 2 : addr::addr_parser p;
327 1 : p.set_protocol(proto);
328 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
329 2 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/[::3"));
330 1 : REQUIRE(p.has_errors());
331 1 : REQUIRE(p.error_count() == 1);
332 1 : REQUIRE(p.error_messages() == "The IPv6 mask is missing the ']' ([::3).\n");
333 1 : REQUIRE(ips.size() == 0);
334 : }
335 :
336 16 : SECTION("ipv6 mask with an ipv4 in the '[...]'")
337 : {
338 1 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
339 1 : int const port(rand() & 0xFFFF);
340 2 : addr::addr_parser p;
341 1 : p.set_protocol(proto);
342 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
343 2 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/[1.2.3.4]"));
344 1 : REQUIRE(p.has_errors());
345 1 : REQUIRE(p.error_count() == 1);
346 1 : REQUIRE(p.error_messages() == "Incompatible address between the address and mask address (first was an IPv6 second an IPv4).\n");
347 1 : REQUIRE(ips.size() == 0);
348 : }
349 :
350 16 : SECTION("verify default mask")
351 : {
352 2 : addr::addr_parser p;
353 :
354 1 : REQUIRE_THROWS_AS(p.set_default_address("[4:5:4:5:7:8:7:8"), addr::addr_invalid_argument_exception);
355 1 : REQUIRE(p.get_default_address4() == "");
356 1 : REQUIRE(p.get_default_address6() == "");
357 :
358 1 : p.set_default_address("[1:7:1:7:1:7:1:7]");
359 1 : REQUIRE(p.get_default_address4() == "");
360 1 : REQUIRE(p.get_default_address6() == "1:7:1:7:1:7:1:7");
361 :
362 1 : REQUIRE_THROWS_AS(p.set_default_address("[9:5:9:5:9:8:9:8"), addr::addr_invalid_argument_exception);
363 1 : REQUIRE(p.get_default_address4() == "");
364 1 : REQUIRE(p.get_default_address6() == "1:7:1:7:1:7:1:7");
365 :
366 1 : p.set_default_address("12.55.1.9");
367 1 : REQUIRE(p.get_default_address4() == "12.55.1.9");
368 1 : REQUIRE(p.get_default_address6() == "1:7:1:7:1:7:1:7");
369 :
370 1 : REQUIRE_THROWS_AS(p.set_default_address("[9:f00f:9:e00e:9:d00d:9:c00c"), addr::addr_invalid_argument_exception);
371 1 : REQUIRE(p.get_default_address4() == "12.55.1.9");
372 1 : REQUIRE(p.get_default_address6() == "1:7:1:7:1:7:1:7");
373 :
374 1 : p.set_default_address("");
375 1 : REQUIRE(p.get_default_address4() == "");
376 1 : REQUIRE(p.get_default_address6() == "");
377 : }
378 :
379 16 : SECTION("verify default mask")
380 : {
381 2 : addr::addr_parser p;
382 :
383 1 : REQUIRE_THROWS_AS(p.set_default_mask("[4:5:4:5:7:8:7:8"), addr::addr_invalid_argument_exception);
384 1 : REQUIRE(p.get_default_mask4() == "");
385 1 : REQUIRE(p.get_default_mask6() == "");
386 :
387 1 : p.set_default_mask("[1:7:1:7:1:7:1:7]");
388 1 : REQUIRE(p.get_default_mask4() == "");
389 1 : REQUIRE(p.get_default_mask6() == "1:7:1:7:1:7:1:7");
390 :
391 1 : REQUIRE_THROWS_AS(p.set_default_mask("[9:5:9:5:9:8:9:8"), addr::addr_invalid_argument_exception);
392 1 : REQUIRE(p.get_default_mask4() == "");
393 1 : REQUIRE(p.get_default_mask6() == "1:7:1:7:1:7:1:7");
394 :
395 1 : p.set_default_mask("12.55.1.9");
396 1 : REQUIRE(p.get_default_mask4() == "12.55.1.9");
397 1 : REQUIRE(p.get_default_mask6() == "1:7:1:7:1:7:1:7");
398 :
399 1 : REQUIRE_THROWS_AS(p.set_default_mask("[9:f00f:9:e00e:9:d00d:9:c00c"), addr::addr_invalid_argument_exception);
400 1 : REQUIRE(p.get_default_mask4() == "12.55.1.9");
401 1 : REQUIRE(p.get_default_mask6() == "1:7:1:7:1:7:1:7");
402 :
403 1 : p.set_default_mask("");
404 1 : REQUIRE(p.get_default_mask4() == "");
405 1 : REQUIRE(p.get_default_mask6() == "");
406 : }
407 : }
408 14 : }
409 :
410 :
411 8 : TEST_CASE( "ipv6::address", "[ipv6]" )
412 : {
413 12 : GIVEN("addr() with an IPv6")
414 : {
415 3 : addr::addr a;
416 :
417 6 : SECTION("set_ipv6() / get_ipv6()")
418 : {
419 11 : for(int idx(0); idx < 10; ++idx)
420 : {
421 10 : struct sockaddr_in6 in6 = sockaddr_in6();
422 10 : in6.sin6_family = AF_INET6;
423 10 : in6.sin6_port = htons(rand());
424 10 : in6.sin6_addr.s6_addr16[0] = rand();
425 10 : in6.sin6_addr.s6_addr16[1] = rand();
426 10 : in6.sin6_addr.s6_addr16[2] = rand();
427 10 : in6.sin6_addr.s6_addr16[3] = rand();
428 10 : in6.sin6_addr.s6_addr16[4] = rand();
429 10 : in6.sin6_addr.s6_addr16[5] = rand();
430 10 : in6.sin6_addr.s6_addr16[6] = rand();
431 10 : in6.sin6_addr.s6_addr16[7] = rand();
432 :
433 : // verify network type
434 : //
435 10 : a.set_ipv6(in6);
436 :
437 : // test constructor
438 : //
439 10 : addr::addr b(in6);
440 : struct sockaddr_in6 out6;
441 10 : b.get_ipv6(out6);
442 10 : REQUIRE(memcmp(&out6, &in6, sizeof(struct sockaddr_in)) == 0);
443 :
444 : // test set
445 : //
446 10 : a.set_ipv6(in6);
447 10 : a.get_ipv6(out6);
448 10 : REQUIRE(memcmp(&out6, &in6, sizeof(struct sockaddr_in)) == 0);
449 : }
450 : }
451 :
452 6 : SECTION("set_ipv6() check to_ipv6_string()")
453 : {
454 11 : for(int idx(0); idx < 10; ++idx)
455 : {
456 10 : struct sockaddr_in6 in6 = sockaddr_in6();
457 10 : in6.sin6_family = AF_INET6;
458 10 : in6.sin6_port = htons(rand());
459 90 : for(int j(0); j < 8; ++j)
460 : {
461 : // avoid any zeroes so that way we do not have
462 : // to handle the "::" syntax
463 0 : do
464 : {
465 80 : in6.sin6_addr.s6_addr16[j] = rand();
466 : }
467 80 : while(in6.sin6_addr.s6_addr16[j] == 0);
468 : }
469 :
470 20 : std::stringstream ip_buf;
471 10 : ip_buf << std::hex
472 20 : << ntohs(in6.sin6_addr.s6_addr16[0])
473 10 : << ":"
474 20 : << ntohs(in6.sin6_addr.s6_addr16[1])
475 10 : << ":"
476 20 : << ntohs(in6.sin6_addr.s6_addr16[2])
477 10 : << ":"
478 20 : << ntohs(in6.sin6_addr.s6_addr16[3])
479 10 : << ":"
480 20 : << ntohs(in6.sin6_addr.s6_addr16[4])
481 10 : << ":"
482 20 : << ntohs(in6.sin6_addr.s6_addr16[5])
483 10 : << ":"
484 20 : << ntohs(in6.sin6_addr.s6_addr16[6])
485 10 : << ":"
486 20 : << ntohs(in6.sin6_addr.s6_addr16[7]);
487 20 : std::string const ip(ip_buf.str());
488 :
489 20 : std::string port_str(std::to_string(static_cast<int>(htons(in6.sin6_port))));
490 :
491 : // check IPv6 as a string
492 : //
493 10 : a.set_ipv6(in6);
494 10 : REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == ip);
495 10 : REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[" + ip + "]");
496 10 : REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_PORT) == "[" + ip + "]:" + port_str);
497 10 : REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_MASK) == ip + "/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); // will change to 128 at some point
498 10 : REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS_MASK) == "[" + ip + "]/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
499 10 : REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == "[" + ip + "]:" + port_str + "/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
500 : }
501 : }
502 :
503 6 : SECTION("name of various IPs")
504 : {
505 1 : struct sockaddr_in6 in6 = sockaddr_in6();
506 1 : in6.sin6_family = AF_INET6;
507 1 : in6.sin6_port = htons(rand());
508 :
509 : // verify network type
510 : //
511 1 : a.set_ipv6(in6);
512 1 : REQUIRE(a.get_name() == std::string()); // no name for "any" (TCP)
513 :
514 1 : a.set_protocol(IPPROTO_UDP);
515 1 : REQUIRE(a.get_name() == std::string()); // no name for "any" (UDP)
516 :
517 1 : in6 = sockaddr_in6();
518 1 : in6.sin6_family = AF_INET6;
519 1 : in6.sin6_port = htons(rand());
520 1 : in6.sin6_addr.s6_addr16[7] = htons(1);
521 1 : a.set_ipv6(in6);
522 : char hostname[HOST_NAME_MAX + 1];
523 1 : hostname[HOST_NAME_MAX] = '\0';
524 1 : REQUIRE(gethostname(hostname, sizeof(hostname)) == 0);
525 1 : REQUIRE(hostname[0] != '\0');
526 2 : std::string localhost(a.get_name());
527 1 : bool const localhost_flag(localhost == hostname || localhost == "ip6-localhost");
528 1 : REQUIRE(localhost_flag);
529 :
530 1 : REQUIRE(addr::find_addr_interface(a, false) != nullptr);
531 : }
532 : }
533 :
534 12 : GIVEN("addr_parser() with IPv6 addresses")
535 : {
536 6 : SECTION("verify basics")
537 : {
538 2 : addr::addr_parser p;
539 1 : p.set_protocol(IPPROTO_TCP);
540 2 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]"));
541 1 : REQUIRE_FALSE(p.has_errors());
542 1 : REQUIRE(ips.size() == 1);
543 1 : addr::addr_range const & r(ips[0]);
544 1 : REQUIRE(r.has_from());
545 1 : REQUIRE_FALSE(r.has_to());
546 1 : REQUIRE_FALSE(r.is_range());
547 1 : REQUIRE_FALSE(r.is_empty());
548 1 : addr::addr f(r.get_from());
549 1 : REQUIRE_FALSE(f.is_ipv4());
550 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1:2:3:4:5:6:7:8");
551 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[1:2:3:4:5:6:7:8]");
552 1 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1:2:3:4:5:6:7:8");
553 1 : REQUIRE(f.get_port() == 0);
554 1 : REQUIRE(f.get_protocol() == IPPROTO_TCP);
555 1 : REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
556 1 : uint8_t mask[16] = {};
557 1 : f.get_mask(mask);
558 17 : for(int idx(0); idx < 16; ++idx)
559 : {
560 16 : REQUIRE(mask[idx] == 255);
561 : }
562 : }
563 :
564 6 : SECTION("default address")
565 : {
566 2 : addr::addr_parser p;
567 1 : p.set_protocol(IPPROTO_TCP);
568 1 : p.set_default_address("5:5:5:5:5:5:5:5");
569 2 : addr::addr_range::vector_t ips(p.parse(""));
570 1 : REQUIRE_FALSE(p.has_errors());
571 1 : REQUIRE(ips.size() == 1);
572 1 : addr::addr_range const & r(ips[0]);
573 1 : REQUIRE(r.has_from());
574 1 : REQUIRE_FALSE(r.has_to());
575 1 : REQUIRE_FALSE(r.is_range());
576 1 : REQUIRE_FALSE(r.is_empty());
577 1 : addr::addr f(r.get_from());
578 1 : REQUIRE_FALSE(f.is_ipv4());
579 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5:5:5:5:5:5:5:5");
580 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[5:5:5:5:5:5:5:5]");
581 1 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5:5:5:5:5:5:5:5");
582 1 : REQUIRE(f.get_port() == 0);
583 1 : REQUIRE(f.get_protocol() == IPPROTO_TCP);
584 1 : REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
585 : }
586 :
587 6 : SECTION("address, not port allowed")
588 : {
589 : // specific address with a default
590 : {
591 2 : addr::addr_parser p;
592 1 : p.set_allow(addr::addr_parser::flag_t::PORT, false);
593 1 : p.set_protocol(IPPROTO_TCP);
594 1 : p.set_default_address("8:7:6:5:4:3:2:1");
595 2 : addr::addr_range::vector_t ips(p.parse("[9:9:9:9:4:3:2:1]"));
596 1 : REQUIRE_FALSE(p.has_errors());
597 1 : REQUIRE(ips.size() == 1);
598 1 : addr::addr_range const & r(ips[0]);
599 1 : REQUIRE(r.has_from());
600 1 : REQUIRE_FALSE(r.has_to());
601 1 : REQUIRE_FALSE(r.is_range());
602 1 : REQUIRE_FALSE(r.is_empty());
603 1 : addr::addr f(r.get_from());
604 1 : REQUIRE_FALSE(f.is_ipv4());
605 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "9:9:9:9:4:3:2:1");
606 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[9:9:9:9:4:3:2:1]");
607 1 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "9:9:9:9:4:3:2:1");
608 1 : REQUIRE(f.get_port() == 0);
609 1 : REQUIRE(f.get_protocol() == IPPROTO_TCP);
610 1 : REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
611 : }
612 :
613 : // only a default address
614 : {
615 2 : addr::addr_parser p;
616 1 : p.set_allow(addr::addr_parser::flag_t::PORT, false);
617 1 : p.set_protocol(IPPROTO_TCP);
618 1 : p.set_default_address("5:1:6:2:7:3:8:4");
619 2 : addr::addr_range::vector_t ips(p.parse(""));
620 1 : REQUIRE_FALSE(p.has_errors());
621 1 : REQUIRE(ips.size() == 1);
622 1 : addr::addr_range const & r(ips[0]);
623 1 : REQUIRE(r.has_from());
624 1 : REQUIRE_FALSE(r.has_to());
625 1 : REQUIRE_FALSE(r.is_range());
626 1 : REQUIRE_FALSE(r.is_empty());
627 1 : addr::addr f(r.get_from());
628 1 : REQUIRE_FALSE(f.is_ipv4());
629 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5:1:6:2:7:3:8:4");
630 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[5:1:6:2:7:3:8:4]");
631 1 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5:1:6:2:7:3:8:4");
632 1 : REQUIRE(f.get_port() == 0);
633 1 : REQUIRE(f.get_protocol() == IPPROTO_TCP);
634 1 : REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
635 : }
636 : }
637 : }
638 6 : }
639 :
640 :
641 7 : TEST_CASE( "ipv6::ports", "[ipv6]" )
642 : {
643 : // by default addr() is an IPv6 address so we test the basic port
644 : // functions here, although it could be in a common place instead...
645 : //
646 10 : GIVEN("addr()")
647 : {
648 3 : addr::addr a;
649 :
650 6 : SECTION("default port")
651 : {
652 1 : REQUIRE(a.get_port() == 0);
653 : }
654 :
655 6 : SECTION("set_port()")
656 : {
657 : // setup a random port to start with
658 : //
659 1 : int const start_port(rand() & 0xFFFF);
660 1 : a.set_port(start_port);
661 :
662 : // test 100 invalid ports
663 : //
664 101 : for(int idx(0); idx < 100; ++idx)
665 : {
666 : // first try a negative port
667 : int port_too_small;
668 0 : do
669 : {
670 100 : port_too_small = -(rand() & 0xFFFF);
671 : }
672 100 : while(port_too_small == 0);
673 100 : REQUIRE_THROWS_AS(a.set_port(port_too_small), addr::addr_invalid_argument_exception);
674 :
675 : // first try a negative port
676 100 : int const port_too_large = (rand() & 0xFFFF) + 65536;
677 100 : REQUIRE_THROWS_AS(a.set_port(port_too_large), addr::addr_invalid_argument_exception);
678 :
679 : // make sure port does not get modified on errors
680 100 : REQUIRE(a.get_port() == start_port);
681 : }
682 :
683 : // test all ports
684 : //
685 65537 : for(int port(0); port < 65536; ++port)
686 : {
687 65536 : a.set_port(port);
688 :
689 65536 : REQUIRE(a.get_port() == port);
690 : }
691 : }
692 :
693 6 : SECTION("known ports to test get_service()")
694 : {
695 1 : a.set_port(80);
696 1 : REQUIRE(a.get_service() == "http");
697 :
698 1 : a.set_port(443);
699 1 : REQUIRE(a.get_service() == "https");
700 :
701 : // again with UDP
702 : //
703 1 : a.set_protocol(IPPROTO_UDP);
704 :
705 1 : a.set_port(80);
706 1 : REQUIRE(a.get_service() == "http");
707 :
708 1 : a.set_port(443);
709 1 : REQUIRE(a.get_service() == "https");
710 : }
711 : }
712 :
713 10 : GIVEN("addr_parser() with IPv6 addresses and port")
714 : {
715 4 : SECTION("verify port")
716 : {
717 65537 : for(int port(0); port < 65536; ++port)
718 : {
719 65536 : int proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
720 131072 : addr::addr_parser p;
721 65536 : p.set_protocol(proto);
722 131072 : addr::addr_range::vector_t ips(p.parse("[ff01:2f3:f041:e301:f:10:11:12]:" + std::to_string(port)));
723 65536 : REQUIRE_FALSE(p.has_errors());
724 65536 : REQUIRE(ips.size() == 1);
725 65536 : addr::addr_range const & r(ips[0]);
726 65536 : addr::addr f(r.get_from());
727 65536 : REQUIRE_FALSE(f.is_ipv4());
728 65536 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "ff01:2f3:f041:e301:f:10:11:12");
729 65536 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[ff01:2f3:f041:e301:f:10:11:12]");
730 65536 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_PORT) == "[ff01:2f3:f041:e301:f:10:11:12]:" + std::to_string(port));
731 65536 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_PORT) == "[ff01:2f3:f041:e301:f:10:11:12]:" + std::to_string(port));
732 65536 : REQUIRE(f.get_port() == port);
733 65536 : REQUIRE(f.get_protocol() == proto);
734 65536 : REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LOOPBACK);
735 : }
736 : }
737 :
738 4 : SECTION("default address with various port")
739 : {
740 101 : for(int idx(0); idx < 100; ++idx)
741 : {
742 100 : uint16_t const port(rand());
743 200 : addr::addr_parser p;
744 100 : p.set_protocol(IPPROTO_TCP);
745 100 : p.set_default_address("ff02:23:f41:e31:20:30:40:50");
746 200 : addr::addr_range::vector_t ips(p.parse(":" + std::to_string(static_cast<int>(port))));
747 100 : REQUIRE_FALSE(p.has_errors());
748 100 : REQUIRE(ips.size() == 1);
749 100 : addr::addr_range const & r(ips[0]);
750 100 : REQUIRE(r.has_from());
751 100 : REQUIRE_FALSE(r.has_to());
752 100 : REQUIRE_FALSE(r.is_range());
753 100 : REQUIRE_FALSE(r.is_empty());
754 100 : addr::addr f(r.get_from());
755 100 : REQUIRE_FALSE(f.is_ipv4());
756 100 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_PORT) == "[ff02:23:f41:e31:20:30:40:50]:" + std::to_string(static_cast<int>(port)));
757 100 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_PORT) == "[ff02:23:f41:e31:20:30:40:50]:" + std::to_string(static_cast<int>(port)));
758 100 : REQUIRE(f.get_port() == port);
759 100 : REQUIRE(f.get_protocol() == IPPROTO_TCP);
760 100 : REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LINK_LOCAL);
761 : }
762 : }
763 : }
764 5 : }
765 :
766 :
767 14 : TEST_CASE( "ipv6::masks", "[ipv6]" )
768 : {
769 24 : GIVEN("addr()")
770 : {
771 : // technically, a default addr object represents and IPv6 so the
772 : // dealing with the mask without an IPv4 is done by IPv6 tests
773 : //
774 3 : addr::addr a;
775 :
776 6 : SECTION("default mask")
777 : {
778 1 : uint8_t mask[16] = {};
779 1 : a.get_mask(mask);
780 17 : for(int idx(0); idx < 16; ++idx)
781 : {
782 16 : REQUIRE(mask[idx] == 255);
783 : }
784 : }
785 :
786 6 : SECTION("set_mask()")
787 : {
788 : uint8_t mask[16], verify_mask[16];
789 6 : for(int idx(0); idx < 5; ++idx)
790 : {
791 85 : for(int j(0); j < 16; ++j)
792 : {
793 80 : mask[j] = rand();
794 : }
795 5 : a.set_mask(mask);
796 5 : a.get_mask(verify_mask);
797 85 : for(int j(0); j < 16; ++j)
798 : {
799 80 : REQUIRE(mask[j] == verify_mask[j]);
800 : }
801 :
802 : // verify that a copy does copy the mask as expected
803 : //
804 5 : addr::addr b(a);
805 5 : b.get_mask(verify_mask);
806 85 : for(int j(0); j < 16; ++j)
807 : {
808 80 : REQUIRE(mask[j] == verify_mask[j]);
809 : }
810 : }
811 : }
812 :
813 6 : SECTION("set_mask()")
814 : {
815 : uint8_t mask[16];
816 : uint8_t verify_mask[16];
817 6 : for(int idx(0); idx < 5; ++idx)
818 : {
819 85 : for(int j(0); j < 16; ++j)
820 : {
821 80 : mask[j] = rand();
822 : }
823 5 : a.set_mask(mask);
824 5 : a.get_mask(verify_mask);
825 85 : for(int j(0); j < 16; ++j)
826 : {
827 80 : REQUIRE(mask[j] == verify_mask[j]);
828 80 : verify_mask[j] = rand();
829 : }
830 :
831 : // verify that a copy does copy the mask as expected
832 : //
833 5 : addr::addr b(a);
834 5 : b.get_mask(verify_mask);
835 85 : for(int j(0); j < 16; ++j)
836 : {
837 80 : REQUIRE(mask[j] == verify_mask[j]);
838 80 : verify_mask[j] = rand();
839 : }
840 :
841 : // verify that copying inside a range works too
842 : //
843 5 : addr::addr_range r;
844 5 : r.set_from(a);
845 5 : r.get_from().get_mask(verify_mask);
846 85 : for(int j(0); j < 16; ++j)
847 : {
848 80 : REQUIRE(mask[j] == verify_mask[j]);
849 80 : verify_mask[j] = rand();
850 : }
851 :
852 : // then that a range copy works as expected
853 : //
854 5 : addr::addr_range c(r);
855 5 : c.get_from().get_mask(verify_mask);
856 85 : for(int j(0); j < 16; ++j)
857 : {
858 80 : REQUIRE(mask[j] == verify_mask[j]);
859 80 : verify_mask[j] = rand();
860 : }
861 : }
862 : }
863 : }
864 :
865 24 : GIVEN("addr_parser() of address:port/mask")
866 : {
867 18 : SECTION("mask allowed, but no mask")
868 : {
869 1 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
870 1 : int const port(rand() & 0xFFFF);
871 2 : addr::addr_parser p;
872 1 : p.set_protocol(proto);
873 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
874 2 : addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port)));
875 1 : REQUIRE_FALSE(p.has_errors());
876 1 : REQUIRE(ips.size() == 1);
877 1 : addr::addr_range const & r(ips[0]);
878 1 : addr::addr f(r.get_from());
879 1 : REQUIRE_FALSE(f.is_ipv4());
880 2 : std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
881 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
882 1 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
883 1 : REQUIRE(f.get_port() == port);
884 1 : REQUIRE(f.get_protocol() == proto);
885 : }
886 :
887 18 : SECTION("empty mask")
888 : {
889 1 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
890 1 : int const port(rand() & 0xFFFF);
891 2 : addr::addr_parser p;
892 1 : p.set_protocol(proto);
893 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
894 2 : addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/"));
895 1 : REQUIRE_FALSE(p.has_errors());
896 1 : REQUIRE(ips.size() == 1);
897 1 : addr::addr_range const & r(ips[0]);
898 1 : addr::addr f(r.get_from());
899 1 : REQUIRE_FALSE(f.is_ipv4());
900 2 : std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
901 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
902 1 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
903 1 : REQUIRE(f.get_port() == port);
904 1 : REQUIRE(f.get_protocol() == proto);
905 : }
906 :
907 18 : SECTION("empty mask including the '[]'")
908 : {
909 1 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
910 1 : int const port(rand() & 0xFFFF);
911 2 : addr::addr_parser p;
912 1 : p.set_protocol(proto);
913 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
914 2 : addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[]"));
915 1 : REQUIRE_FALSE(p.has_errors());
916 1 : REQUIRE(ips.size() == 1);
917 1 : addr::addr_range const & r(ips[0]);
918 1 : addr::addr f(r.get_from());
919 1 : REQUIRE_FALSE(f.is_ipv4());
920 2 : std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
921 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
922 1 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
923 1 : REQUIRE(f.get_port() == port);
924 1 : REQUIRE(f.get_protocol() == proto);
925 : }
926 :
927 18 : SECTION("one number masks")
928 : {
929 130 : for(int idx(0); idx <= 128; ++idx)
930 : {
931 129 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
932 129 : int const port(rand() & 0xFFFF);
933 258 : addr::addr_parser p;
934 129 : p.set_protocol(proto);
935 129 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
936 258 : addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/" + std::to_string(idx)));
937 129 : REQUIRE_FALSE(p.has_errors());
938 129 : REQUIRE(ips.size() == 1);
939 129 : addr::addr_range const & r(ips[0]);
940 129 : addr::addr f(r.get_from());
941 129 : REQUIRE_FALSE(f.is_ipv4());
942 129 : uint8_t mask[16] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };
943 129 : int j(15);
944 129 : int m(128 - idx);
945 2049 : for(; m > 8; m -= 8, --j)
946 : {
947 960 : mask[j] = 0;
948 : }
949 129 : if(j < 0)
950 : {
951 0 : throw std::logic_error("invalid j here");
952 : }
953 129 : mask[j] = 255 << m;
954 : char buf[1024]; // really large buffer to make sure it does not get truncated
955 129 : if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
956 : {
957 0 : throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
958 : }
959 258 : std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + buf + "]");
960 129 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
961 129 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
962 129 : REQUIRE(f.get_port() == port);
963 129 : REQUIRE(f.get_protocol() == proto);
964 : }
965 : }
966 :
967 18 : SECTION("address like mask")
968 : {
969 26 : for(int idx(0); idx < 25; ++idx)
970 : {
971 25 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
972 25 : int const port(rand() & 0xFFFF);
973 50 : addr::addr_parser p;
974 25 : p.set_protocol(proto);
975 25 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
976 : // when specified as an IP, the mask can be absolutely anything
977 : uint8_t mask[16];
978 425 : for(int j(0); j < 16; ++j)
979 : {
980 400 : mask[j] = rand();
981 : }
982 50 : std::stringstream smask;
983 25 : smask << std::hex
984 50 : << htons((mask[ 1] << 8) | mask[ 0])
985 25 : << ":"
986 50 : << htons((mask[ 3] << 8) | mask[ 2])
987 25 : << ":"
988 50 : << htons((mask[ 5] << 8) | mask[ 4])
989 25 : << ":"
990 50 : << htons((mask[ 7] << 8) | mask[ 6])
991 25 : << ":"
992 50 : << htons((mask[ 9] << 8) | mask[ 8])
993 25 : << ":"
994 50 : << htons((mask[11] << 8) | mask[10])
995 25 : << ":"
996 50 : << htons((mask[13] << 8) | mask[12])
997 25 : << ":"
998 50 : << htons((mask[15] << 8) | mask[14]);
999 : char buf[1024]; // really large buffer to make sure it does not get truncated
1000 25 : if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
1001 : {
1002 0 : throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
1003 : }
1004 50 : addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + smask.str() + "]"));
1005 25 : REQUIRE_FALSE(p.has_errors());
1006 25 : REQUIRE(ips.size() == 1);
1007 25 : addr::addr_range const & r(ips[0]);
1008 25 : addr::addr f(r.get_from());
1009 25 : REQUIRE_FALSE(f.is_ipv4());
1010 50 : std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + buf + "]");
1011 25 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1012 25 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1013 25 : REQUIRE(f.get_port() == port);
1014 25 : REQUIRE(f.get_protocol() == proto);
1015 : }
1016 : }
1017 :
1018 18 : SECTION("address like default mask")
1019 : {
1020 26 : for(int idx(0); idx < 25; ++idx)
1021 : {
1022 25 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
1023 25 : int const port(rand() & 0xFFFF);
1024 50 : addr::addr_parser p;
1025 25 : p.set_protocol(proto);
1026 25 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
1027 : // when specified as an IP, the mask can be absolutely anything
1028 : // (here the mask is a string an it will be parsed by the
1029 : // parser if required)
1030 : //
1031 : uint8_t mask[16];
1032 425 : for(int j(0); j < 16; ++j)
1033 : {
1034 400 : mask[j] = rand();
1035 : }
1036 50 : std::stringstream smask;
1037 25 : smask << std::hex
1038 25 : << "["
1039 50 : << htons((mask[ 1] << 8) | mask[ 0])
1040 25 : << ":"
1041 50 : << htons((mask[ 3] << 8) | mask[ 2])
1042 25 : << ":"
1043 50 : << htons((mask[ 5] << 8) | mask[ 4])
1044 25 : << ":"
1045 50 : << htons((mask[ 7] << 8) | mask[ 6])
1046 25 : << ":"
1047 50 : << htons((mask[ 9] << 8) | mask[ 8])
1048 25 : << ":"
1049 50 : << htons((mask[11] << 8) | mask[10])
1050 25 : << ":"
1051 50 : << htons((mask[13] << 8) | mask[12])
1052 25 : << ":"
1053 50 : << htons((mask[15] << 8) | mask[14])
1054 25 : << "]";
1055 : char buf[1024]; // really large buffer to make sure it does not get truncated
1056 25 : if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
1057 : {
1058 0 : throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
1059 : }
1060 25 : p.set_default_mask(smask.str());
1061 50 : addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port)));
1062 25 : REQUIRE_FALSE(p.has_errors());
1063 25 : REQUIRE(ips.size() == 1);
1064 25 : addr::addr_range const & r(ips[0]);
1065 25 : addr::addr f(r.get_from());
1066 25 : REQUIRE_FALSE(f.is_ipv4());
1067 50 : std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + buf + "]");
1068 25 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1069 25 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1070 25 : REQUIRE(f.get_port() == port);
1071 25 : REQUIRE(f.get_protocol() == proto);
1072 : uint8_t verify_mask[16];
1073 25 : f.get_mask(verify_mask);
1074 425 : for(int j(0); j < 16; ++j)
1075 : {
1076 400 : REQUIRE(verify_mask[j] == mask[j]);
1077 : }
1078 : }
1079 : }
1080 :
1081 18 : SECTION("address like mask with a default")
1082 : {
1083 26 : for(int idx(0); idx < 25; ++idx)
1084 : {
1085 25 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
1086 25 : int const port(rand() & 0xFFFF);
1087 50 : addr::addr_parser p;
1088 25 : p.set_protocol(proto);
1089 25 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
1090 :
1091 : // here we want a default and an IP with a specific mask
1092 : // to make sure that the specific mask has priority
1093 : //
1094 : uint8_t mask[16];
1095 425 : for(int j(0); j < 16; ++j)
1096 : {
1097 400 : mask[j] = rand();
1098 : }
1099 50 : std::stringstream smask;
1100 25 : smask << std::hex
1101 25 : << "["
1102 50 : << htons((mask[ 1] << 8) | mask[ 0])
1103 25 : << ":"
1104 50 : << htons((mask[ 3] << 8) | mask[ 2])
1105 25 : << ":"
1106 50 : << htons((mask[ 5] << 8) | mask[ 4])
1107 25 : << ":"
1108 50 : << htons((mask[ 7] << 8) | mask[ 6])
1109 25 : << ":"
1110 50 : << htons((mask[ 9] << 8) | mask[ 8])
1111 25 : << ":"
1112 50 : << htons((mask[11] << 8) | mask[10])
1113 25 : << ":"
1114 50 : << htons((mask[13] << 8) | mask[12])
1115 25 : << ":"
1116 50 : << htons((mask[15] << 8) | mask[14])
1117 25 : << "]";
1118 : char buf[1024]; // really large buffer to make sure it does not get truncated
1119 25 : if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
1120 : {
1121 0 : throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
1122 : }
1123 :
1124 : uint8_t default_mask[16];
1125 425 : for(int j(0); j < 16; ++j)
1126 : {
1127 400 : default_mask[j] = rand();
1128 : }
1129 : //std::stringstream default_smask;
1130 : //default_smask << std::hex
1131 : // << "["
1132 : // << htons((default_mask[ 1] << 8) | default_mask[ 0])
1133 : // << ":"
1134 : // << htons((default_mask[ 3] << 8) | default_mask[ 2])
1135 : // << ":"
1136 : // << htons((default_mask[ 5] << 8) | default_mask[ 4])
1137 : // << ":"
1138 : // << htons((default_mask[ 7] << 8) | default_mask[ 6])
1139 : // << ":"
1140 : // << htons((default_mask[ 9] << 8) | default_mask[ 8])
1141 : // << ":"
1142 : // << htons((default_mask[11] << 8) | default_mask[10])
1143 : // << ":"
1144 : // << htons((default_mask[13] << 8) | default_mask[12])
1145 : // << ":"
1146 : // << htons((default_mask[15] << 8) | default_mask[14])
1147 : // << "]";
1148 : char default_buf[1024]; // really large buffer to make sure it does not get truncated
1149 25 : if(inet_ntop(AF_INET6, default_mask, default_buf, sizeof(buf)) == nullptr)
1150 : {
1151 0 : throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
1152 : }
1153 25 : p.set_default_mask(default_buf);
1154 :
1155 50 : addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/" + smask.str()));
1156 25 : REQUIRE_FALSE(p.has_errors());
1157 25 : REQUIRE(ips.size() == 1);
1158 25 : addr::addr_range const & r(ips[0]);
1159 25 : addr::addr f(r.get_from());
1160 25 : REQUIRE_FALSE(f.is_ipv4());
1161 50 : std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + buf + "]");
1162 25 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1163 25 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1164 25 : REQUIRE(f.get_port() == port);
1165 25 : REQUIRE(f.get_protocol() == proto);
1166 : uint8_t verify_mask[16];
1167 25 : f.get_mask(verify_mask);
1168 425 : for(int j(0); j < 16; ++j)
1169 : {
1170 400 : REQUIRE(verify_mask[j] == mask[j]);
1171 : }
1172 : }
1173 : }
1174 :
1175 18 : SECTION("no address, but one IPv6 number masks")
1176 : {
1177 : // with just a number, the mask is considered an IPv6 mask
1178 : // if it is 33 or more
1179 : //
1180 97 : for(int idx(33); idx <= 128; ++idx)
1181 : {
1182 96 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
1183 96 : int const port(rand() & 0xFFFF);
1184 192 : addr::addr_parser p;
1185 96 : p.set_protocol(proto);
1186 96 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
1187 : //p.set_default_address("55:33:22:11:0:cc:bb:aa");
1188 192 : addr::addr_range::vector_t ips(p.parse(":" + std::to_string(port) + "/" + std::to_string(idx)));
1189 96 : REQUIRE_FALSE(p.has_errors());
1190 96 : REQUIRE(ips.size() == 1);
1191 96 : addr::addr_range const & r(ips[0]);
1192 96 : addr::addr f(r.get_from());
1193 96 : REQUIRE_FALSE(f.is_ipv4());
1194 96 : uint8_t mask[16] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };
1195 96 : int j(15);
1196 96 : int m(128 - idx);
1197 1130 : for(; m > 8; m -= 8, --j)
1198 : {
1199 517 : mask[j] = 0;
1200 : }
1201 96 : if(j < 0)
1202 : {
1203 0 : throw std::logic_error("invalid j here");
1204 : }
1205 96 : mask[j] = 255 << m;
1206 : char buf[1024]; // really large buffer to make sure it does not get truncated
1207 96 : if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
1208 : {
1209 0 : throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
1210 : }
1211 192 : std::string result("[::]:" + std::to_string(port) + "/[" + buf + "]");
1212 96 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1213 96 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1214 96 : REQUIRE(f.get_port() == port);
1215 96 : REQUIRE(f.get_protocol() == proto);
1216 : }
1217 : }
1218 :
1219 18 : SECTION("no address, but one IPv6 masks")
1220 : {
1221 : // with just a number, the mask is considered an IPv6 mask
1222 : // if it is 33 or more
1223 : //
1224 6 : for(int idx(0); idx < 5; ++idx)
1225 : {
1226 5 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
1227 5 : int const port(rand() & 0xFFFF);
1228 10 : addr::addr_parser p;
1229 5 : p.set_protocol(proto);
1230 5 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
1231 : //p.set_default_address("55:33:22:11:0:cc:bb:aa");
1232 10 : addr::addr_range::vector_t ips(p.parse(":" + std::to_string(port) + "/[1:2:3:4:5:6:7:8]"));
1233 5 : REQUIRE_FALSE(p.has_errors());
1234 5 : REQUIRE(ips.size() == 1);
1235 5 : addr::addr_range const & r(ips[0]);
1236 5 : addr::addr f(r.get_from());
1237 5 : REQUIRE_FALSE(f.is_ipv4());
1238 10 : std::string result("[::]:" + std::to_string(port) + "/[1:2:3:4:5:6:7:8]");
1239 5 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1240 5 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1241 5 : REQUIRE(f.get_port() == port);
1242 5 : REQUIRE(f.get_protocol() == proto);
1243 : }
1244 : }
1245 : }
1246 12 : }
1247 :
1248 :
1249 9 : TEST_CASE( "ipv6::network_type", "[ipv6]" )
1250 : {
1251 14 : GIVEN("addr()")
1252 : {
1253 7 : addr::addr a;
1254 :
1255 14 : SECTION("any (::)")
1256 : {
1257 : {
1258 1 : struct sockaddr_in6 in6 = sockaddr_in6();
1259 1 : in6.sin6_family = AF_INET6;
1260 1 : in6.sin6_port = htons(rand());
1261 1 : in6.sin6_addr.s6_addr32[0] = 0;
1262 1 : in6.sin6_addr.s6_addr32[1] = 0;
1263 1 : in6.sin6_addr.s6_addr32[2] = 0;
1264 1 : in6.sin6_addr.s6_addr32[3] = 0;
1265 :
1266 : // verify network type
1267 : //
1268 1 : a.set_ipv6(in6);
1269 :
1270 1 : REQUIRE(a.is_default());
1271 1 : REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_ANY);
1272 1 : REQUIRE(a.get_network_type_string() == "Any");
1273 : }
1274 :
1275 : // make sure that if any byte is set to non-zero it is not
1276 : // viewed as the ANY address
1277 : //
1278 17 : for(int idx(0); idx < 16; ++idx)
1279 : {
1280 16 : struct sockaddr_in6 in6 = sockaddr_in6();
1281 16 : in6.sin6_family = AF_INET6;
1282 16 : in6.sin6_port = htons(rand());
1283 16 : in6.sin6_addr.s6_addr32[0] = 0;
1284 16 : in6.sin6_addr.s6_addr32[1] = 0;
1285 16 : in6.sin6_addr.s6_addr32[2] = 0;
1286 16 : in6.sin6_addr.s6_addr32[3] = 0;
1287 :
1288 : // change one byte only
1289 : //
1290 0 : do
1291 : {
1292 16 : in6.sin6_addr.s6_addr[idx] = rand();
1293 : }
1294 16 : while(in6.sin6_addr.s6_addr[idx] == 0);
1295 :
1296 : // verify network type
1297 : //
1298 16 : a.set_ipv6(in6);
1299 :
1300 16 : REQUIRE(a.get_network_type() != addr::addr::network_type_t::NETWORK_TYPE_ANY);
1301 16 : REQUIRE(a.get_network_type_string() != "Any");
1302 : }
1303 : }
1304 :
1305 14 : SECTION("private address fd00::/8")
1306 : {
1307 11 : for(int idx(0); idx < 10; ++idx)
1308 : {
1309 10 : struct sockaddr_in6 in6 = sockaddr_in6();
1310 10 : in6.sin6_family = AF_INET6;
1311 10 : in6.sin6_port = htons(rand());
1312 10 : in6.sin6_addr.s6_addr16[0] = htons(0xFD00 | (rand() & 255));
1313 10 : in6.sin6_addr.s6_addr16[1] = rand();
1314 10 : in6.sin6_addr.s6_addr16[2] = rand();
1315 10 : in6.sin6_addr.s6_addr16[3] = rand();
1316 10 : in6.sin6_addr.s6_addr16[4] = rand();
1317 10 : in6.sin6_addr.s6_addr16[5] = rand();
1318 10 : in6.sin6_addr.s6_addr16[6] = rand();
1319 10 : in6.sin6_addr.s6_addr16[7] = rand();
1320 :
1321 : // verify network type
1322 : //
1323 10 : a.set_ipv6(in6);
1324 10 : REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
1325 10 : REQUIRE(a.get_network_type_string() == "Private");
1326 : }
1327 : }
1328 :
1329 14 : SECTION("private address fe80::/10")
1330 : {
1331 11 : for(int idx(0); idx < 10; ++idx)
1332 : {
1333 10 : struct sockaddr_in6 in6 = sockaddr_in6();
1334 10 : in6.sin6_family = AF_INET6;
1335 10 : in6.sin6_port = htons(rand());
1336 10 : in6.sin6_addr.s6_addr16[0] = htons(0xFE80 | (rand() & 63));
1337 10 : in6.sin6_addr.s6_addr16[1] = rand();
1338 10 : in6.sin6_addr.s6_addr16[2] = rand();
1339 10 : in6.sin6_addr.s6_addr16[3] = rand();
1340 10 : in6.sin6_addr.s6_addr16[4] = rand();
1341 10 : in6.sin6_addr.s6_addr16[5] = rand();
1342 10 : in6.sin6_addr.s6_addr16[6] = rand();
1343 10 : in6.sin6_addr.s6_addr16[7] = rand();
1344 :
1345 : // verify network type
1346 : //
1347 10 : a.set_ipv6(in6);
1348 10 : REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LINK_LOCAL);
1349 10 : REQUIRE(a.get_network_type_string() == "Local Link");
1350 : }
1351 : }
1352 :
1353 14 : SECTION("private address ff02::/16")
1354 : {
1355 11 : for(int idx(0); idx < 10; ++idx)
1356 : {
1357 10 : struct sockaddr_in6 in6 = sockaddr_in6();
1358 10 : in6.sin6_family = AF_INET6;
1359 10 : in6.sin6_port = htons(rand());
1360 10 : in6.sin6_addr.s6_addr16[0] = htons(0xFF02);
1361 10 : in6.sin6_addr.s6_addr16[1] = rand();
1362 10 : in6.sin6_addr.s6_addr16[2] = rand();
1363 10 : in6.sin6_addr.s6_addr16[3] = rand();
1364 10 : in6.sin6_addr.s6_addr16[4] = rand();
1365 10 : in6.sin6_addr.s6_addr16[5] = rand();
1366 10 : in6.sin6_addr.s6_addr16[6] = rand();
1367 10 : in6.sin6_addr.s6_addr16[7] = rand();
1368 :
1369 : // verify network type
1370 : //
1371 10 : a.set_ipv6(in6);
1372 10 : REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LINK_LOCAL);
1373 10 : REQUIRE(a.get_network_type_string() == "Local Link");
1374 : }
1375 : }
1376 :
1377 14 : SECTION("private address ff00::/8")
1378 : {
1379 11 : for(int idx(0); idx < 10; ++idx)
1380 : {
1381 10 : struct sockaddr_in6 in6 = sockaddr_in6();
1382 10 : in6.sin6_family = AF_INET6;
1383 10 : in6.sin6_port = htons(rand());
1384 3 : do
1385 : {
1386 13 : in6.sin6_addr.s6_addr16[0] = htons(0xFF00 | (rand() & 255));
1387 : }
1388 13 : while((in6.sin6_addr.s6_addr16[0] & htons(0xFF0F)) == htons(0xFF01) // ffx1::/16
1389 12 : || (in6.sin6_addr.s6_addr16[0] & htons(0xFF0F)) == htons(0xFF02) // ffx2::/16
1390 10 : || (in6.sin6_addr.s6_addr16[0] & htons(0xFFC0)) == htons(0xFE80) // fe80::/10
1391 23 : || (in6.sin6_addr.s6_addr16[0] & htons(0xFF00)) == htons(0xFD00)); // fd00::/8
1392 10 : in6.sin6_addr.s6_addr16[1] = rand();
1393 10 : in6.sin6_addr.s6_addr16[2] = rand();
1394 10 : in6.sin6_addr.s6_addr16[3] = rand();
1395 10 : in6.sin6_addr.s6_addr16[4] = rand();
1396 10 : in6.sin6_addr.s6_addr16[5] = rand();
1397 10 : in6.sin6_addr.s6_addr16[6] = rand();
1398 10 : in6.sin6_addr.s6_addr16[7] = rand();
1399 :
1400 : // verify network type
1401 : //
1402 10 : a.set_ipv6(in6);
1403 10 : REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_MULTICAST);
1404 10 : REQUIRE(a.get_network_type_string() == "Multicast");
1405 : }
1406 : }
1407 :
1408 14 : SECTION("private address ffx1::/8")
1409 : {
1410 11 : for(int idx(0); idx < 10; ++idx)
1411 : {
1412 10 : struct sockaddr_in6 in6 = sockaddr_in6();
1413 10 : in6.sin6_family = AF_INET6;
1414 10 : in6.sin6_port = htons(rand());
1415 10 : in6.sin6_addr.s6_addr16[0] = htons(0xFF01 | ((rand() & 15) << 4));
1416 10 : in6.sin6_addr.s6_addr16[1] = rand();
1417 10 : in6.sin6_addr.s6_addr16[2] = rand();
1418 10 : in6.sin6_addr.s6_addr16[3] = rand();
1419 10 : in6.sin6_addr.s6_addr16[4] = rand();
1420 10 : in6.sin6_addr.s6_addr16[5] = rand();
1421 10 : in6.sin6_addr.s6_addr16[6] = rand();
1422 10 : in6.sin6_addr.s6_addr16[7] = rand();
1423 :
1424 : // verify network type
1425 : //
1426 10 : a.set_ipv6(in6);
1427 10 : REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LOOPBACK);
1428 10 : REQUIRE(a.get_network_type_string() == "Loopback");
1429 : }
1430 : }
1431 :
1432 14 : SECTION("private address ::1")
1433 : {
1434 11 : for(int idx(0); idx < 10; ++idx)
1435 : {
1436 10 : struct sockaddr_in6 in6 = sockaddr_in6();
1437 10 : in6.sin6_family = AF_INET6;
1438 10 : in6.sin6_port = htons(rand());
1439 10 : in6.sin6_addr.s6_addr16[0] = 0;
1440 10 : in6.sin6_addr.s6_addr16[1] = 0;
1441 10 : in6.sin6_addr.s6_addr16[2] = 0;
1442 10 : in6.sin6_addr.s6_addr16[3] = 0;
1443 10 : in6.sin6_addr.s6_addr16[4] = 0;
1444 10 : in6.sin6_addr.s6_addr16[5] = 0;
1445 10 : in6.sin6_addr.s6_addr16[6] = 0;
1446 10 : in6.sin6_addr.s6_addr16[7] = htons(1);
1447 :
1448 : // verify network type
1449 : //
1450 10 : a.set_ipv6(in6);
1451 10 : REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LOOPBACK);
1452 10 : REQUIRE(a.get_network_type_string() == "Loopback");
1453 :
1454 : // try again from a string to confirm
1455 : //
1456 10 : struct addrinfo * addrlist(nullptr);
1457 10 : int const port(rand() & 65535);
1458 10 : int const r(getaddrinfo("::1", std::to_string(port).c_str(), nullptr, &addrlist));
1459 10 : REQUIRE(r == 0);
1460 10 : REQUIRE(addrlist != nullptr);
1461 10 : REQUIRE(addrlist->ai_family == AF_INET6);
1462 10 : REQUIRE(addrlist->ai_addrlen == sizeof(struct sockaddr_in6));
1463 10 : a.set_ipv6(*reinterpret_cast<sockaddr_in6 *>(addrlist->ai_addr));
1464 10 : REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LOOPBACK);
1465 10 : REQUIRE(a.get_network_type_string() == "Loopback");
1466 : }
1467 : }
1468 : }
1469 7 : }
1470 :
1471 :
1472 5 : TEST_CASE( "ipv6::network", "[ipv6]" )
1473 : {
1474 6 : GIVEN("set_from_socket()")
1475 : {
1476 6 : SECTION("create a server, but do not test it (yet)...")
1477 : {
1478 2 : addr::addr_parser p;
1479 2 : addr::addr_range::vector_t ips(p.parse("[::1]:49999"));
1480 1 : REQUIRE(ips.size() >= 1);
1481 :
1482 1 : addr::addr & a(ips[0].get_from());
1483 1 : int s(a.create_socket(addr::addr::SOCKET_FLAG_NONBLOCK | addr::addr::SOCKET_FLAG_CLOEXEC | addr::addr::SOCKET_FLAG_REUSE));
1484 1 : REQUIRE(s >= 0);
1485 2 : std::shared_ptr<int> auto_free(&s, socket_deleter);
1486 :
1487 1 : REQUIRE(a.bind(s) == 0);
1488 : }
1489 :
1490 6 : SECTION("connect with TCP to [::1]")
1491 : {
1492 1 : if(unittest::g_tcp_port != -1)
1493 : {
1494 2 : addr::addr_parser p;
1495 2 : addr::addr_range::vector_t ips(p.parse("[::1]:" + std::to_string(unittest::g_tcp_port)));
1496 1 : REQUIRE(ips.size() >= 1);
1497 :
1498 1 : addr::addr & a(ips[0].get_from());
1499 1 : int s(a.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC));// | addr::addr::SOCKET_FLAG_REUSE));
1500 1 : REQUIRE(s >= 0);
1501 2 : std::shared_ptr<int> auto_free(&s, socket_deleter);
1502 :
1503 1 : REQUIRE(a.connect(s) == 0);
1504 :
1505 : // get socket info from the other side (peer == true)
1506 : //
1507 1 : addr::addr b;
1508 1 : b.set_from_socket(s, true);
1509 1 : REQUIRE_FALSE(b.is_ipv4());
1510 1 : REQUIRE(b.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::1");
1511 1 : REQUIRE(b.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::1");
1512 :
1513 : // in this case we know what the port is since we specified
1514 : // that when connecting
1515 : //
1516 1 : REQUIRE(b.get_port() == unittest::g_tcp_port);
1517 :
1518 : // now try this side (peer == false)
1519 : //
1520 1 : addr::addr c;
1521 1 : c.set_from_socket(s, false);
1522 1 : REQUIRE_FALSE(c.is_ipv4());
1523 1 : REQUIRE(c.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::1");
1524 1 : REQUIRE(c.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::1");
1525 :
1526 : // we cannot be sure of the port, there is a range we could
1527 : // test better (more constraining) but for this test is
1528 : // certainly does not matter much; it has to be more than
1529 : // 1023, though
1530 : //
1531 1 : REQUIRE(c.get_port() > 1023);
1532 : }
1533 : else
1534 : {
1535 0 : std::cout << "connect to [::1] test skipped as no TCP port was specified on the command line." << std::endl;
1536 : }
1537 : }
1538 :
1539 6 : SECTION("connect with UDP to [::1]")
1540 : {
1541 2 : addr::addr_parser p;
1542 1 : p.set_protocol("udp");
1543 2 : addr::addr_range::vector_t ips(p.parse("[::1]:53"));
1544 1 : REQUIRE(ips.size() >= 1);
1545 :
1546 1 : addr::addr & a(ips[0].get_from());
1547 1 : int s(a.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC));// | addr::addr::SOCKET_FLAG_REUSE));
1548 1 : REQUIRE(s >= 0);
1549 2 : std::shared_ptr<int> auto_free(&s, socket_deleter);
1550 :
1551 1 : REQUIRE(a.connect(s) == -1);
1552 :
1553 : // get socket info from the other side (peer == true)
1554 : //
1555 1 : addr::addr b;
1556 1 : REQUIRE_THROWS_AS(b.set_from_socket(s, true), addr::addr_io_exception);
1557 1 : REQUIRE_FALSE(b.is_ipv4());
1558 1 : REQUIRE(b.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::");
1559 1 : REQUIRE(b.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::");
1560 :
1561 : // in this case we know what the port is since we specified
1562 : // that when connecting
1563 : //
1564 1 : REQUIRE(b.get_port() == 0);
1565 :
1566 : // now try this side (peer == false)
1567 : //
1568 1 : addr::addr c;
1569 1 : c.set_from_socket(s, false);
1570 1 : REQUIRE_FALSE(c.is_ipv4());
1571 1 : REQUIRE(c.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::");
1572 1 : REQUIRE(c.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::");
1573 :
1574 : // we cannot be sure of the port, there is a range we could
1575 : // test better (more constraining) but for this test is
1576 : // certainly does not matter much; it has to be more than
1577 : // 1023, though
1578 : //
1579 1 : REQUIRE(c.get_port() == 0);
1580 : }
1581 : }
1582 9 : }
1583 :
1584 :
1585 : // vim: ts=4 sw=4 et
|