Line data Source code
1 : /* test_addr_ipv6.cpp
2 : * Copyright (C) 2011-2017 Made to Order Software Corporation
3 : *
4 : * Project: http://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 : // C lib
49 : //
50 : //#include <string.h>
51 : ////#include <math.h>
52 : ////#include <time.h>
53 : //#include <unistd.h>
54 : //#include <limits.h>
55 :
56 :
57 :
58 :
59 : /** \brief Details used by the addr class implementation.
60 : *
61 : * We have a function to check whether an address is part of
62 : * the interfaces of your computer. This check requires the
63 : * use of a `struct ifaddrs` and as such it requires to
64 : * delete that structure. We define a deleter for that
65 : * strucure here.
66 : */
67 : namespace
68 : {
69 :
70 : /** \brief Delete an ifaddrs structure.
71 : *
72 : * This deleter is used to make sure all the ifaddrs get released when
73 : * an exception occurs or the function using such exists.
74 : *
75 : * \param[in] ia The ifaddrs structure to free.
76 : */
77 3 : void socket_deleter(int * s)
78 : {
79 3 : close(*s);
80 3 : }
81 :
82 :
83 : }
84 : // no name namespace
85 :
86 :
87 :
88 16 : TEST_CASE( "ipv6::invalid_input", "ipv6" )
89 : {
90 28 : GIVEN("addr()")
91 : {
92 2 : addr::addr a;
93 :
94 2 : SECTION("set IPv6 with an invalid family")
95 : {
96 1 : struct sockaddr_in6 in6 = sockaddr_in6();
97 0 : do
98 : {
99 1 : in6.sin6_family = rand();
100 : }
101 1 : while(in6.sin6_family == AF_INET6);
102 1 : in6.sin6_port = rand();
103 9 : for(int idx(0); idx < 8; ++idx)
104 : {
105 8 : in6.sin6_addr.s6_addr16[idx] = rand();
106 : }
107 1 : REQUIRE_THROWS_AS(a.set_ipv6(in6), addr::addr_invalid_argument_exception);
108 1 : REQUIRE_THROWS_AS(addr::addr b(in6), addr::addr_invalid_argument_exception);
109 : }
110 : }
111 :
112 28 : GIVEN("addr_parser() with IPv6 addresses")
113 : {
114 6 : SECTION("bad address")
115 : {
116 2 : addr::addr_parser p;
117 2 : addr::addr_range::vector_t ips(p.parse("[{bad-ip}]"));
118 1 : REQUIRE(p.has_errors());
119 1 : REQUIRE(p.error_count() == 1);
120 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");
121 1 : REQUIRE(ips.size() == 0);
122 : }
123 :
124 6 : SECTION("missing ']'")
125 : {
126 2 : addr::addr_parser p;
127 2 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7"));
128 1 : REQUIRE(p.has_errors());
129 1 : REQUIRE(p.error_count() == 1);
130 1 : REQUIRE(p.error_messages() == "IPv6 is missing the ']' ([1:2:3:4:5:6:7).\n");
131 1 : REQUIRE(ips.size() == 0);
132 : }
133 :
134 6 : SECTION("required address")
135 : {
136 2 : addr::addr_parser p;
137 1 : p.set_protocol(IPPROTO_TCP);
138 1 : p.set_allow(addr::addr_parser::flag_t::REQUIRED_ADDRESS, true);
139 2 : addr::addr_range::vector_t ips(p.parse("[]"));
140 1 : REQUIRE(p.has_errors());
141 1 : REQUIRE(p.error_count() == 1);
142 1 : REQUIRE(p.error_messages() == "Required address is missing.\n");
143 1 : REQUIRE(ips.size() == 0);
144 : }
145 : }
146 :
147 28 : GIVEN("addr_parser() with IPv4 ports")
148 : {
149 4 : SECTION("required port")
150 : {
151 : // optional + required -> required
152 : {
153 2 : addr::addr_parser p;
154 1 : p.set_protocol(IPPROTO_TCP);
155 1 : p.set_allow(addr::addr_parser::flag_t::REQUIRED_PORT, true);
156 2 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]"));
157 1 : REQUIRE(p.has_errors());
158 1 : REQUIRE(p.error_count() == 1);
159 1 : REQUIRE(p.error_messages() == "Required port is missing.\n");
160 1 : REQUIRE(ips.size() == 0);
161 : }
162 :
163 : // only required -> required just the same
164 : {
165 2 : addr::addr_parser p;
166 1 : p.set_protocol(IPPROTO_TCP);
167 1 : p.set_allow(addr::addr_parser::flag_t::PORT, false);
168 1 : p.set_allow(addr::addr_parser::flag_t::REQUIRED_PORT, true);
169 2 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]"));
170 1 : REQUIRE(p.has_errors());
171 1 : REQUIRE(p.error_count() == 1);
172 1 : REQUIRE(p.error_messages() == "Required port is missing.\n");
173 1 : REQUIRE(ips.size() == 0);
174 : }
175 : }
176 :
177 4 : SECTION("port not allowed")
178 : {
179 : {
180 2 : addr::addr_parser p;
181 1 : p.set_protocol(IPPROTO_TCP);
182 1 : p.set_allow(addr::addr_parser::flag_t::PORT, false);
183 2 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:123"));
184 1 : REQUIRE(p.has_errors());
185 1 : REQUIRE(p.error_count() == 1);
186 1 : REQUIRE(p.error_messages() == "Port not allowed ([1:2:3:4:5:6:7:8]:123).\n");
187 1 : REQUIRE(ips.size() == 0);
188 : }
189 :
190 : {
191 2 : addr::addr_parser p;
192 1 : p.set_protocol(IPPROTO_TCP);
193 1 : p.set_allow(addr::addr_parser::flag_t::PORT, false);
194 2 : addr::addr_range::vector_t ips(p.parse("1:2:3:4:5:6:7:8:123.5"));
195 1 : REQUIRE(p.has_errors());
196 1 : REQUIRE(p.error_count() == 1);
197 1 : REQUIRE(p.error_messages() == "Port not allowed (1:2:3:4:5:6:7:8:123.5).\n");
198 1 : REQUIRE(ips.size() == 0);
199 : }
200 : }
201 : }
202 :
203 28 : GIVEN("addr_parser() with invalid masks")
204 : {
205 16 : SECTION("really large numbers (over 1000)")
206 : {
207 6 : for(int idx(0); idx < 5; ++idx)
208 : {
209 5 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
210 5 : int const port(rand() & 0xFFFF);
211 5 : int const mask((rand() & 0xFF) + 1001);
212 10 : addr::addr_parser p;
213 5 : p.set_protocol(proto);
214 5 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
215 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)));
216 5 : REQUIRE(p.has_errors());
217 5 : REQUIRE(p.error_count() == 1);
218 5 : REQUIRE(p.error_messages() == "Mask number too large (" + std::to_string(mask) + ", expected a maximum of 128).\n");
219 5 : REQUIRE(ips.size() == 0);
220 : }
221 :
222 : // in case the number is between square brackets it looks like
223 : // an IPv4 to getaddrinfo() so we get a different error...
224 : // (i.e. the '[' is not a digit so we do not get the "too large"
225 : // error...)
226 : //
227 6 : for(int idx(0); idx < 5; ++idx)
228 : {
229 5 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
230 5 : int const port(rand() & 0xFFFF);
231 5 : int const mask((rand() & 0xFF) + 1001);
232 10 : addr::addr_parser p;
233 5 : p.set_protocol(proto);
234 5 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
235 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) + "]"));
236 5 : REQUIRE(p.has_errors());
237 5 : REQUIRE(p.error_count() == 1);
238 5 : REQUIRE(p.error_messages() == "Incompatible address between the address and mask address (first was an IPv6 second an IPv4).\n");
239 5 : REQUIRE(ips.size() == 0);
240 : }
241 :
242 : // an empty address with a mask too large gets us to another place
243 : //
244 6 : for(int idx(0); idx < 5; ++idx)
245 : {
246 5 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
247 5 : int const port(rand() & 0xFFFF);
248 5 : int const mask((rand() & 0xFF) + 1001);
249 10 : addr::addr_parser p;
250 5 : p.set_protocol(proto);
251 5 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
252 10 : addr::addr_range::vector_t ips(p.parse(":" + std::to_string(port) + "/" + std::to_string(mask)));
253 5 : REQUIRE(p.has_errors());
254 5 : REQUIRE(p.error_count() == 1);
255 5 : REQUIRE(p.error_messages() == "Mask number too large (" + std::to_string(mask) + ", expected a maximum of 128).\n");
256 5 : REQUIRE(ips.size() == 0);
257 : }
258 :
259 : // an empty address with a mask too large gets us to another place
260 : //
261 6 : for(int idx(0); idx < 5; ++idx)
262 : {
263 5 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
264 5 : int const port(rand() & 0xFFFF);
265 5 : int const mask((rand() & 0xFF));
266 10 : addr::addr_parser p;
267 5 : p.set_protocol(proto);
268 5 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
269 10 : addr::addr_range::vector_t ips(p.parse(":" + std::to_string(port) + "/" + std::to_string(mask) + "q"));
270 5 : REQUIRE(p.has_errors());
271 5 : REQUIRE(p.error_count() == 1);
272 5 : REQUIRE(p.error_messages() == "Invalid mask in \"/" + std::to_string(mask) + "q\", error -2 -- Name or service not known (errno: 0 -- Success).\n");
273 5 : REQUIRE(ips.size() == 0);
274 : }
275 : }
276 :
277 16 : SECTION("ipv6 mask is limited between 0 and 128")
278 : {
279 6 : for(int idx(0); idx < 5; ++idx)
280 : {
281 5 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
282 5 : int const port(rand() & 0xFFFF);
283 5 : int const mask((rand() & 0xFF) + 129);
284 10 : addr::addr_parser p;
285 5 : p.set_protocol(proto);
286 5 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
287 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)));
288 5 : REQUIRE(p.has_errors());
289 5 : REQUIRE(p.error_count() == 1);
290 5 : REQUIRE(p.error_messages() == "Unsupported mask size (" + std::to_string(mask) + ", expected 128 at the most for an IPv6).\n");
291 5 : REQUIRE(ips.size() == 0);
292 : }
293 : }
294 :
295 16 : SECTION("ipv6 mask cannot use name")
296 : {
297 6 : for(int idx(0); idx < 5; ++idx)
298 : {
299 5 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
300 5 : int const port(rand() & 0xFFFF);
301 10 : addr::addr_parser p;
302 5 : p.set_protocol(proto);
303 5 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
304 10 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/[localhost]"));
305 5 : REQUIRE(p.has_errors());
306 5 : REQUIRE(p.error_count() == 1);
307 5 : REQUIRE(p.error_messages() == "Invalid mask in \"/[localhost]\", error -2 -- Name or service not known (errno: 0 -- Success).\n");
308 5 : REQUIRE(ips.size() == 0);
309 : }
310 : }
311 :
312 16 : SECTION("ipv6 mask must be between '[...]'")
313 : {
314 1 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
315 1 : int const port(rand() & 0xFFFF);
316 2 : addr::addr_parser p;
317 1 : p.set_protocol(proto);
318 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
319 2 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/::3"));
320 1 : REQUIRE(p.has_errors());
321 1 : REQUIRE(p.error_count() == 1);
322 1 : REQUIRE(p.error_messages() == "The address uses the IPv6 syntax, the mask cannot use IPv4.\n");
323 1 : REQUIRE(ips.size() == 0);
324 : }
325 :
326 16 : SECTION("ipv6 mask missing the ']'")
327 : {
328 1 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
329 1 : int const port(rand() & 0xFFFF);
330 2 : addr::addr_parser p;
331 1 : p.set_protocol(proto);
332 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
333 2 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/[::3"));
334 1 : REQUIRE(p.has_errors());
335 1 : REQUIRE(p.error_count() == 1);
336 1 : REQUIRE(p.error_messages() == "The IPv6 mask is missing the ']' ([::3).\n");
337 1 : REQUIRE(ips.size() == 0);
338 : }
339 :
340 16 : SECTION("ipv6 mask with an ipv4 in the '[...]'")
341 : {
342 1 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
343 1 : int const port(rand() & 0xFFFF);
344 2 : addr::addr_parser p;
345 1 : p.set_protocol(proto);
346 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
347 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]"));
348 1 : REQUIRE(p.has_errors());
349 1 : REQUIRE(p.error_count() == 1);
350 1 : REQUIRE(p.error_messages() == "Incompatible address between the address and mask address (first was an IPv6 second an IPv4).\n");
351 1 : REQUIRE(ips.size() == 0);
352 : }
353 :
354 16 : SECTION("verify default mask")
355 : {
356 2 : addr::addr_parser p;
357 :
358 1 : REQUIRE_THROWS_AS(p.set_default_address("[4:5:4:5:7:8:7:8"), addr::addr_invalid_argument_exception);
359 1 : REQUIRE(p.get_default_address4() == "");
360 1 : REQUIRE(p.get_default_address6() == "");
361 :
362 1 : p.set_default_address("[1:7:1:7:1:7:1:7]");
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 : REQUIRE_THROWS_AS(p.set_default_address("[9:5:9:5:9:8:9:8"), addr::addr_invalid_argument_exception);
367 1 : REQUIRE(p.get_default_address4() == "");
368 1 : REQUIRE(p.get_default_address6() == "1:7:1:7:1:7:1:7");
369 :
370 1 : p.set_default_address("12.55.1.9");
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 : REQUIRE_THROWS_AS(p.set_default_address("[9:f00f:9:e00e:9:d00d:9:c00c"), addr::addr_invalid_argument_exception);
375 1 : REQUIRE(p.get_default_address4() == "12.55.1.9");
376 1 : REQUIRE(p.get_default_address6() == "1:7:1:7:1:7:1:7");
377 :
378 1 : p.set_default_address("");
379 1 : REQUIRE(p.get_default_address4() == "");
380 1 : REQUIRE(p.get_default_address6() == "");
381 : }
382 :
383 16 : SECTION("verify default mask")
384 : {
385 2 : addr::addr_parser p;
386 :
387 1 : REQUIRE_THROWS_AS(p.set_default_mask("[4:5:4:5:7:8:7:8"), addr::addr_invalid_argument_exception);
388 1 : REQUIRE(p.get_default_mask4() == "");
389 1 : REQUIRE(p.get_default_mask6() == "");
390 :
391 1 : p.set_default_mask("[1:7:1:7:1:7:1:7]");
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 : REQUIRE_THROWS_AS(p.set_default_mask("[9:5:9:5:9:8:9:8"), addr::addr_invalid_argument_exception);
396 1 : REQUIRE(p.get_default_mask4() == "");
397 1 : REQUIRE(p.get_default_mask6() == "1:7:1:7:1:7:1:7");
398 :
399 1 : p.set_default_mask("12.55.1.9");
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 : REQUIRE_THROWS_AS(p.set_default_mask("[9:f00f:9:e00e:9:d00d:9:c00c"), addr::addr_invalid_argument_exception);
404 1 : REQUIRE(p.get_default_mask4() == "12.55.1.9");
405 1 : REQUIRE(p.get_default_mask6() == "1:7:1:7:1:7:1:7");
406 :
407 1 : p.set_default_mask("");
408 1 : REQUIRE(p.get_default_mask4() == "");
409 1 : REQUIRE(p.get_default_mask6() == "");
410 : }
411 : }
412 14 : }
413 :
414 :
415 8 : TEST_CASE( "ipv6::address", "ipv6" )
416 : {
417 12 : GIVEN("addr() with an IPv6")
418 : {
419 6 : addr::addr a;
420 :
421 6 : SECTION("set_ipv6() / get_ipv6()")
422 : {
423 11 : for(int idx(0); idx < 10; ++idx)
424 : {
425 10 : struct sockaddr_in6 in6 = sockaddr_in6();
426 10 : in6.sin6_family = AF_INET6;
427 10 : in6.sin6_port = htons(rand());
428 10 : in6.sin6_addr.s6_addr16[0] = rand();
429 10 : in6.sin6_addr.s6_addr16[1] = rand();
430 10 : in6.sin6_addr.s6_addr16[2] = rand();
431 10 : in6.sin6_addr.s6_addr16[3] = rand();
432 10 : in6.sin6_addr.s6_addr16[4] = rand();
433 10 : in6.sin6_addr.s6_addr16[5] = rand();
434 10 : in6.sin6_addr.s6_addr16[6] = rand();
435 10 : in6.sin6_addr.s6_addr16[7] = rand();
436 :
437 : // verify network type
438 : //
439 10 : a.set_ipv6(in6);
440 :
441 : // test constructor
442 : //
443 20 : addr::addr b(in6);
444 : struct sockaddr_in6 out6;
445 10 : b.get_ipv6(out6);
446 10 : REQUIRE(memcmp(&out6, &in6, sizeof(struct sockaddr_in)) == 0);
447 :
448 : // test set
449 : //
450 10 : a.set_ipv6(in6);
451 10 : a.get_ipv6(out6);
452 10 : REQUIRE(memcmp(&out6, &in6, sizeof(struct sockaddr_in)) == 0);
453 : }
454 : }
455 :
456 6 : SECTION("set_ipv6() check to_ipv6_string()")
457 : {
458 11 : for(int idx(0); idx < 10; ++idx)
459 : {
460 10 : struct sockaddr_in6 in6 = sockaddr_in6();
461 10 : in6.sin6_family = AF_INET6;
462 10 : in6.sin6_port = htons(rand());
463 90 : for(int j(0); j < 8; ++j)
464 : {
465 : // avoid any zeroes so that way we do not have
466 : // to handle the "::" syntax
467 0 : do
468 : {
469 80 : in6.sin6_addr.s6_addr16[j] = rand();
470 : }
471 80 : while(in6.sin6_addr.s6_addr16[j] == 0);
472 : }
473 :
474 20 : std::stringstream ip_buf;
475 10 : ip_buf << std::hex
476 20 : << ntohs(in6.sin6_addr.s6_addr16[0])
477 10 : << ":"
478 20 : << ntohs(in6.sin6_addr.s6_addr16[1])
479 10 : << ":"
480 20 : << ntohs(in6.sin6_addr.s6_addr16[2])
481 10 : << ":"
482 20 : << ntohs(in6.sin6_addr.s6_addr16[3])
483 10 : << ":"
484 20 : << ntohs(in6.sin6_addr.s6_addr16[4])
485 10 : << ":"
486 20 : << ntohs(in6.sin6_addr.s6_addr16[5])
487 10 : << ":"
488 20 : << ntohs(in6.sin6_addr.s6_addr16[6])
489 10 : << ":"
490 20 : << ntohs(in6.sin6_addr.s6_addr16[7]);
491 20 : std::string const ip(ip_buf.str());
492 :
493 20 : std::string port_str(std::to_string(static_cast<int>(htons(in6.sin6_port))));
494 :
495 : // check IPv6 as a string
496 : //
497 10 : a.set_ipv6(in6);
498 10 : REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == ip);
499 10 : REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[" + ip + "]");
500 10 : REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_PORT) == "[" + ip + "]:" + port_str);
501 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
502 10 : REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS_MASK) == "[" + ip + "]/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
503 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]");
504 : }
505 : }
506 :
507 6 : SECTION("name of various IPs")
508 : {
509 1 : struct sockaddr_in6 in6 = sockaddr_in6();
510 1 : in6.sin6_family = AF_INET6;
511 1 : in6.sin6_port = htons(rand());
512 :
513 : // verify network type
514 : //
515 1 : a.set_ipv6(in6);
516 1 : REQUIRE(a.get_name() == std::string()); // no name for "any" (TCP)
517 :
518 1 : a.set_protocol(IPPROTO_UDP);
519 1 : REQUIRE(a.get_name() == std::string()); // no name for "any" (UDP)
520 :
521 1 : in6 = sockaddr_in6();
522 1 : in6.sin6_family = AF_INET6;
523 1 : in6.sin6_port = htons(rand());
524 1 : in6.sin6_addr.s6_addr16[7] = htons(1);
525 1 : a.set_ipv6(in6);
526 : char hostname[HOST_NAME_MAX + 1];
527 1 : hostname[HOST_NAME_MAX] = '\0';
528 1 : REQUIRE(gethostname(hostname, sizeof(hostname)) == 0);
529 1 : REQUIRE(hostname[0] != '\0');
530 1 : REQUIRE(a.get_name() == hostname);
531 1 : REQUIRE(a.is_computer_interface_address() == addr::addr::computer_interface_address_t::COMPUTER_INTERFACE_ADDRESS_TRUE);
532 : }
533 : }
534 :
535 12 : GIVEN("addr_parser() with IPv6 addresses")
536 : {
537 6 : SECTION("verify basics")
538 : {
539 2 : addr::addr_parser p;
540 1 : p.set_protocol(IPPROTO_TCP);
541 2 : addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]"));
542 1 : REQUIRE_FALSE(p.has_errors());
543 1 : REQUIRE(ips.size() == 1);
544 1 : addr::addr_range const & r(ips[0]);
545 1 : REQUIRE(r.has_from());
546 1 : REQUIRE_FALSE(r.has_to());
547 1 : REQUIRE_FALSE(r.is_range());
548 1 : REQUIRE_FALSE(r.is_empty());
549 2 : addr::addr f(r.get_from());
550 1 : REQUIRE_FALSE(f.is_ipv4());
551 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1:2:3:4:5:6:7:8");
552 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[1:2:3:4:5:6:7:8]");
553 1 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1:2:3:4:5:6:7:8");
554 1 : REQUIRE(f.get_port() == 0);
555 1 : REQUIRE(f.get_protocol() == IPPROTO_TCP);
556 1 : REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
557 1 : uint8_t mask[16] = {};
558 1 : f.get_mask(mask);
559 17 : for(int idx(0); idx < 16; ++idx)
560 : {
561 16 : REQUIRE(mask[idx] == 255);
562 : }
563 : }
564 :
565 6 : SECTION("default address")
566 : {
567 2 : addr::addr_parser p;
568 1 : p.set_protocol(IPPROTO_TCP);
569 1 : p.set_default_address("5:5:5:5:5:5:5:5");
570 2 : addr::addr_range::vector_t ips(p.parse(""));
571 1 : REQUIRE_FALSE(p.has_errors());
572 1 : REQUIRE(ips.size() == 1);
573 1 : addr::addr_range const & r(ips[0]);
574 1 : REQUIRE(r.has_from());
575 1 : REQUIRE_FALSE(r.has_to());
576 1 : REQUIRE_FALSE(r.is_range());
577 1 : REQUIRE_FALSE(r.is_empty());
578 2 : addr::addr f(r.get_from());
579 1 : REQUIRE_FALSE(f.is_ipv4());
580 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5:5:5:5:5:5:5:5");
581 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[5:5:5:5:5:5:5:5]");
582 1 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5:5:5:5:5:5:5:5");
583 1 : REQUIRE(f.get_port() == 0);
584 1 : REQUIRE(f.get_protocol() == IPPROTO_TCP);
585 1 : REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
586 : }
587 :
588 6 : SECTION("address, not port allowed")
589 : {
590 : // specific address with a default
591 : {
592 2 : addr::addr_parser p;
593 1 : p.set_allow(addr::addr_parser::flag_t::PORT, false);
594 1 : p.set_protocol(IPPROTO_TCP);
595 1 : p.set_default_address("8:7:6:5:4:3:2:1");
596 2 : addr::addr_range::vector_t ips(p.parse("[9:9:9:9:4:3:2:1]"));
597 1 : REQUIRE_FALSE(p.has_errors());
598 1 : REQUIRE(ips.size() == 1);
599 1 : addr::addr_range const & r(ips[0]);
600 1 : REQUIRE(r.has_from());
601 1 : REQUIRE_FALSE(r.has_to());
602 1 : REQUIRE_FALSE(r.is_range());
603 1 : REQUIRE_FALSE(r.is_empty());
604 2 : addr::addr f(r.get_from());
605 1 : REQUIRE_FALSE(f.is_ipv4());
606 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "9:9:9:9:4:3:2:1");
607 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[9:9:9:9:4:3:2:1]");
608 1 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "9:9:9:9:4:3:2:1");
609 1 : REQUIRE(f.get_port() == 0);
610 1 : REQUIRE(f.get_protocol() == IPPROTO_TCP);
611 1 : REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
612 : }
613 :
614 : // only a default address
615 : {
616 2 : addr::addr_parser p;
617 1 : p.set_allow(addr::addr_parser::flag_t::PORT, false);
618 1 : p.set_protocol(IPPROTO_TCP);
619 1 : p.set_default_address("5:1:6:2:7:3:8:4");
620 2 : addr::addr_range::vector_t ips(p.parse(""));
621 1 : REQUIRE_FALSE(p.has_errors());
622 1 : REQUIRE(ips.size() == 1);
623 1 : addr::addr_range const & r(ips[0]);
624 1 : REQUIRE(r.has_from());
625 1 : REQUIRE_FALSE(r.has_to());
626 1 : REQUIRE_FALSE(r.is_range());
627 1 : REQUIRE_FALSE(r.is_empty());
628 2 : addr::addr f(r.get_from());
629 1 : REQUIRE_FALSE(f.is_ipv4());
630 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5:1:6:2:7:3:8:4");
631 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[5:1:6:2:7:3:8:4]");
632 1 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5:1:6:2:7:3:8:4");
633 1 : REQUIRE(f.get_port() == 0);
634 1 : REQUIRE(f.get_protocol() == IPPROTO_TCP);
635 1 : REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
636 : }
637 : }
638 : }
639 6 : }
640 :
641 :
642 7 : TEST_CASE( "ipv6::ports", "ipv6" )
643 : {
644 : // by default addr() is an IPv6 address so we test the basic port
645 : // functions here, although it could be in a common place instead...
646 : //
647 10 : GIVEN("addr()")
648 : {
649 6 : addr::addr a;
650 :
651 6 : SECTION("default port")
652 : {
653 1 : REQUIRE(a.get_port() == 0);
654 : }
655 :
656 6 : SECTION("set_port()")
657 : {
658 : // setup a random port to start with
659 : //
660 1 : int const start_port(rand() & 0xFFFF);
661 1 : a.set_port(start_port);
662 :
663 : // test 100 invalid ports
664 : //
665 101 : for(int idx(0); idx < 100; ++idx)
666 : {
667 : // first try a negative port
668 : int port_too_small;
669 0 : do
670 : {
671 100 : port_too_small = -(rand() & 0xFFFF);
672 : }
673 100 : while(port_too_small == 0);
674 100 : REQUIRE_THROWS_AS(a.set_port(port_too_small), addr::addr_invalid_argument_exception);
675 :
676 : // first try a negative port
677 100 : int const port_too_large = (rand() & 0xFFFF) + 65536;
678 100 : REQUIRE_THROWS_AS(a.set_port(port_too_large), addr::addr_invalid_argument_exception);
679 :
680 : // make sure port does not get modified on errors
681 100 : REQUIRE(a.get_port() == start_port);
682 : }
683 :
684 : // test all ports
685 : //
686 65537 : for(int port(0); port < 65536; ++port)
687 : {
688 65536 : a.set_port(port);
689 :
690 65536 : REQUIRE(a.get_port() == port);
691 : }
692 : }
693 :
694 6 : SECTION("known ports to test get_service()")
695 : {
696 1 : a.set_port(80);
697 1 : REQUIRE(a.get_service() == "http");
698 :
699 1 : a.set_port(443);
700 1 : REQUIRE(a.get_service() == "https");
701 :
702 : // again with UDP
703 : //
704 1 : a.set_protocol(IPPROTO_UDP);
705 :
706 1 : a.set_port(80);
707 1 : REQUIRE(a.get_service() == "http");
708 :
709 1 : a.set_port(443);
710 1 : REQUIRE(a.get_service() == "https");
711 : }
712 : }
713 :
714 10 : GIVEN("addr_parser() with IPv6 addresses and port")
715 : {
716 4 : SECTION("verify port")
717 : {
718 65537 : for(int port(0); port < 65536; ++port)
719 : {
720 65536 : int proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
721 131072 : addr::addr_parser p;
722 65536 : p.set_protocol(proto);
723 131072 : addr::addr_range::vector_t ips(p.parse("[ff01:2f3:f041:e301:f:10:11:12]:" + std::to_string(port)));
724 65536 : REQUIRE_FALSE(p.has_errors());
725 65536 : REQUIRE(ips.size() == 1);
726 65536 : addr::addr_range const & r(ips[0]);
727 131072 : addr::addr f(r.get_from());
728 65536 : REQUIRE_FALSE(f.is_ipv4());
729 65536 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "ff01:2f3:f041:e301:f:10:11:12");
730 65536 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[ff01:2f3:f041:e301:f:10:11:12]");
731 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));
732 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));
733 65536 : REQUIRE(f.get_port() == port);
734 65536 : REQUIRE(f.get_protocol() == proto);
735 65536 : REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LOOPBACK);
736 : }
737 : }
738 :
739 4 : SECTION("default address with various port")
740 : {
741 101 : for(int idx(0); idx < 100; ++idx)
742 : {
743 100 : uint16_t const port(rand());
744 200 : addr::addr_parser p;
745 100 : p.set_protocol(IPPROTO_TCP);
746 100 : p.set_default_address("ff02:23:f41:e31:20:30:40:50");
747 200 : addr::addr_range::vector_t ips(p.parse(":" + std::to_string(static_cast<int>(port))));
748 100 : REQUIRE_FALSE(p.has_errors());
749 100 : REQUIRE(ips.size() == 1);
750 100 : addr::addr_range const & r(ips[0]);
751 100 : REQUIRE(r.has_from());
752 100 : REQUIRE_FALSE(r.has_to());
753 100 : REQUIRE_FALSE(r.is_range());
754 100 : REQUIRE_FALSE(r.is_empty());
755 200 : addr::addr f(r.get_from());
756 100 : REQUIRE_FALSE(f.is_ipv4());
757 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)));
758 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)));
759 100 : REQUIRE(f.get_port() == port);
760 100 : REQUIRE(f.get_protocol() == IPPROTO_TCP);
761 100 : REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LINK_LOCAL);
762 : }
763 : }
764 : }
765 5 : }
766 :
767 :
768 14 : TEST_CASE( "ipv6::masks", "ipv6" )
769 : {
770 24 : GIVEN("addr()")
771 : {
772 : // technically, a default addr object represents and IPv6 so the
773 : // dealing with the mask without an IPv4 is done by IPv6 tests
774 : //
775 6 : addr::addr a;
776 :
777 6 : SECTION("default mask")
778 : {
779 1 : uint8_t mask[16] = {};
780 1 : a.get_mask(mask);
781 17 : for(int idx(0); idx < 16; ++idx)
782 : {
783 16 : REQUIRE(mask[idx] == 255);
784 : }
785 : }
786 :
787 6 : SECTION("set_mask()")
788 : {
789 : uint8_t mask[16], verify_mask[16];
790 6 : for(int idx(0); idx < 5; ++idx)
791 : {
792 85 : for(int j(0); j < 16; ++j)
793 : {
794 80 : mask[j] = rand();
795 : }
796 5 : a.set_mask(mask);
797 5 : a.get_mask(verify_mask);
798 85 : for(int j(0); j < 16; ++j)
799 : {
800 80 : REQUIRE(mask[j] == verify_mask[j]);
801 : }
802 :
803 : // verify that a copy does copy the mask as expected
804 : //
805 10 : addr::addr b(a);
806 5 : b.get_mask(verify_mask);
807 85 : for(int j(0); j < 16; ++j)
808 : {
809 80 : REQUIRE(mask[j] == verify_mask[j]);
810 : }
811 : }
812 : }
813 :
814 6 : SECTION("set_mask()")
815 : {
816 : uint8_t mask[16];
817 : uint8_t verify_mask[16];
818 6 : for(int idx(0); idx < 5; ++idx)
819 : {
820 85 : for(int j(0); j < 16; ++j)
821 : {
822 80 : mask[j] = rand();
823 : }
824 5 : a.set_mask(mask);
825 5 : a.get_mask(verify_mask);
826 85 : for(int j(0); j < 16; ++j)
827 : {
828 80 : REQUIRE(mask[j] == verify_mask[j]);
829 80 : verify_mask[j] = rand();
830 : }
831 :
832 : // verify that a copy does copy the mask as expected
833 : //
834 10 : addr::addr b(a);
835 5 : b.get_mask(verify_mask);
836 85 : for(int j(0); j < 16; ++j)
837 : {
838 80 : REQUIRE(mask[j] == verify_mask[j]);
839 80 : verify_mask[j] = rand();
840 : }
841 :
842 : // verify that copying inside a range works too
843 : //
844 10 : addr::addr_range r;
845 5 : r.set_from(a);
846 5 : r.get_from().get_mask(verify_mask);
847 85 : for(int j(0); j < 16; ++j)
848 : {
849 80 : REQUIRE(mask[j] == verify_mask[j]);
850 80 : verify_mask[j] = rand();
851 : }
852 :
853 : // then that a range copy works as expected
854 : //
855 10 : addr::addr_range c(r);
856 5 : c.get_from().get_mask(verify_mask);
857 85 : for(int j(0); j < 16; ++j)
858 : {
859 80 : REQUIRE(mask[j] == verify_mask[j]);
860 80 : verify_mask[j] = rand();
861 : }
862 : }
863 : }
864 : }
865 :
866 24 : GIVEN("addr_parser() of address:port/mask")
867 : {
868 18 : SECTION("mask allowed, but no mask")
869 : {
870 1 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
871 1 : int const port(rand() & 0xFFFF);
872 2 : addr::addr_parser p;
873 1 : p.set_protocol(proto);
874 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
875 2 : addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port)));
876 1 : REQUIRE_FALSE(p.has_errors());
877 1 : REQUIRE(ips.size() == 1);
878 1 : addr::addr_range const & r(ips[0]);
879 2 : addr::addr f(r.get_from());
880 1 : REQUIRE_FALSE(f.is_ipv4());
881 2 : std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
882 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
883 1 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
884 1 : REQUIRE(f.get_port() == port);
885 1 : REQUIRE(f.get_protocol() == proto);
886 : }
887 :
888 18 : SECTION("empty mask")
889 : {
890 1 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
891 1 : int const port(rand() & 0xFFFF);
892 2 : addr::addr_parser p;
893 1 : p.set_protocol(proto);
894 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
895 2 : addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/"));
896 1 : REQUIRE_FALSE(p.has_errors());
897 1 : REQUIRE(ips.size() == 1);
898 1 : addr::addr_range const & r(ips[0]);
899 2 : addr::addr f(r.get_from());
900 1 : REQUIRE_FALSE(f.is_ipv4());
901 2 : std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
902 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
903 1 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
904 1 : REQUIRE(f.get_port() == port);
905 1 : REQUIRE(f.get_protocol() == proto);
906 : }
907 :
908 18 : SECTION("empty mask including the '[]'")
909 : {
910 1 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
911 1 : int const port(rand() & 0xFFFF);
912 2 : addr::addr_parser p;
913 1 : p.set_protocol(proto);
914 1 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
915 2 : addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[]"));
916 1 : REQUIRE_FALSE(p.has_errors());
917 1 : REQUIRE(ips.size() == 1);
918 1 : addr::addr_range const & r(ips[0]);
919 2 : addr::addr f(r.get_from());
920 1 : REQUIRE_FALSE(f.is_ipv4());
921 2 : std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
922 1 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
923 1 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
924 1 : REQUIRE(f.get_port() == port);
925 1 : REQUIRE(f.get_protocol() == proto);
926 : }
927 :
928 18 : SECTION("one number masks")
929 : {
930 130 : for(int idx(0); idx <= 128; ++idx)
931 : {
932 129 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
933 129 : int const port(rand() & 0xFFFF);
934 258 : addr::addr_parser p;
935 129 : p.set_protocol(proto);
936 129 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
937 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)));
938 129 : REQUIRE_FALSE(p.has_errors());
939 129 : REQUIRE(ips.size() == 1);
940 129 : addr::addr_range const & r(ips[0]);
941 258 : addr::addr f(r.get_from());
942 129 : REQUIRE_FALSE(f.is_ipv4());
943 129 : uint8_t mask[16] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };
944 129 : int j(15);
945 129 : int m(128 - idx);
946 2049 : for(; m > 8; m -= 8, --j)
947 : {
948 960 : mask[j] = 0;
949 : }
950 129 : if(j < 0)
951 : {
952 0 : throw std::logic_error("invalid j here");
953 : }
954 129 : mask[j] = 255 << m;
955 : char buf[1024]; // really large buffer to make sure it does not get truncated
956 129 : if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
957 : {
958 0 : throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
959 : }
960 258 : std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + buf + "]");
961 129 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
962 129 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
963 129 : REQUIRE(f.get_port() == port);
964 129 : REQUIRE(f.get_protocol() == proto);
965 : }
966 : }
967 :
968 18 : SECTION("address like mask")
969 : {
970 26 : for(int idx(0); idx < 25; ++idx)
971 : {
972 25 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
973 25 : int const port(rand() & 0xFFFF);
974 50 : addr::addr_parser p;
975 25 : p.set_protocol(proto);
976 25 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
977 : // when specified as an IP, the mask can be absolutely anything
978 : uint8_t mask[16];
979 425 : for(int j(0); j < 16; ++j)
980 : {
981 400 : mask[j] = rand();
982 : }
983 50 : std::stringstream smask;
984 25 : smask << std::hex
985 50 : << htons((mask[ 1] << 8) | mask[ 0])
986 25 : << ":"
987 50 : << htons((mask[ 3] << 8) | mask[ 2])
988 25 : << ":"
989 50 : << htons((mask[ 5] << 8) | mask[ 4])
990 25 : << ":"
991 50 : << htons((mask[ 7] << 8) | mask[ 6])
992 25 : << ":"
993 50 : << htons((mask[ 9] << 8) | mask[ 8])
994 25 : << ":"
995 50 : << htons((mask[11] << 8) | mask[10])
996 25 : << ":"
997 50 : << htons((mask[13] << 8) | mask[12])
998 25 : << ":"
999 50 : << htons((mask[15] << 8) | mask[14]);
1000 : char buf[1024]; // really large buffer to make sure it does not get truncated
1001 25 : if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
1002 : {
1003 0 : throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
1004 : }
1005 50 : addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + smask.str() + "]"));
1006 25 : REQUIRE_FALSE(p.has_errors());
1007 25 : REQUIRE(ips.size() == 1);
1008 25 : addr::addr_range const & r(ips[0]);
1009 50 : addr::addr f(r.get_from());
1010 25 : REQUIRE_FALSE(f.is_ipv4());
1011 50 : std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + buf + "]");
1012 25 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1013 25 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1014 25 : REQUIRE(f.get_port() == port);
1015 25 : REQUIRE(f.get_protocol() == proto);
1016 : }
1017 : }
1018 :
1019 18 : SECTION("address like default mask")
1020 : {
1021 26 : for(int idx(0); idx < 25; ++idx)
1022 : {
1023 25 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
1024 25 : int const port(rand() & 0xFFFF);
1025 50 : addr::addr_parser p;
1026 25 : p.set_protocol(proto);
1027 25 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
1028 : // when specified as an IP, the mask can be absolutely anything
1029 : // (here the mask is a string an it will be parsed by the
1030 : // parser if required)
1031 : //
1032 : uint8_t mask[16];
1033 425 : for(int j(0); j < 16; ++j)
1034 : {
1035 400 : mask[j] = rand();
1036 : }
1037 50 : std::stringstream smask;
1038 25 : smask << std::hex
1039 25 : << "["
1040 50 : << htons((mask[ 1] << 8) | mask[ 0])
1041 25 : << ":"
1042 50 : << htons((mask[ 3] << 8) | mask[ 2])
1043 25 : << ":"
1044 50 : << htons((mask[ 5] << 8) | mask[ 4])
1045 25 : << ":"
1046 50 : << htons((mask[ 7] << 8) | mask[ 6])
1047 25 : << ":"
1048 50 : << htons((mask[ 9] << 8) | mask[ 8])
1049 25 : << ":"
1050 50 : << htons((mask[11] << 8) | mask[10])
1051 25 : << ":"
1052 50 : << htons((mask[13] << 8) | mask[12])
1053 25 : << ":"
1054 50 : << htons((mask[15] << 8) | mask[14])
1055 25 : << "]";
1056 : char buf[1024]; // really large buffer to make sure it does not get truncated
1057 25 : if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
1058 : {
1059 0 : throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
1060 : }
1061 25 : p.set_default_mask(smask.str());
1062 50 : addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port)));
1063 25 : REQUIRE_FALSE(p.has_errors());
1064 25 : REQUIRE(ips.size() == 1);
1065 25 : addr::addr_range const & r(ips[0]);
1066 50 : addr::addr f(r.get_from());
1067 25 : REQUIRE_FALSE(f.is_ipv4());
1068 50 : std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + buf + "]");
1069 25 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1070 25 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1071 25 : REQUIRE(f.get_port() == port);
1072 25 : REQUIRE(f.get_protocol() == proto);
1073 : uint8_t verify_mask[16];
1074 25 : f.get_mask(verify_mask);
1075 425 : for(int j(0); j < 16; ++j)
1076 : {
1077 400 : REQUIRE(verify_mask[j] == mask[j]);
1078 : }
1079 : }
1080 : }
1081 :
1082 18 : SECTION("address like mask with a default")
1083 : {
1084 26 : for(int idx(0); idx < 25; ++idx)
1085 : {
1086 25 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
1087 25 : int const port(rand() & 0xFFFF);
1088 50 : addr::addr_parser p;
1089 25 : p.set_protocol(proto);
1090 25 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
1091 :
1092 : // here we want a default and an IP with a specific mask
1093 : // to make sure that the specific mask has priority
1094 : //
1095 : uint8_t mask[16];
1096 425 : for(int j(0); j < 16; ++j)
1097 : {
1098 400 : mask[j] = rand();
1099 : }
1100 50 : std::stringstream smask;
1101 25 : smask << std::hex
1102 25 : << "["
1103 50 : << htons((mask[ 1] << 8) | mask[ 0])
1104 25 : << ":"
1105 50 : << htons((mask[ 3] << 8) | mask[ 2])
1106 25 : << ":"
1107 50 : << htons((mask[ 5] << 8) | mask[ 4])
1108 25 : << ":"
1109 50 : << htons((mask[ 7] << 8) | mask[ 6])
1110 25 : << ":"
1111 50 : << htons((mask[ 9] << 8) | mask[ 8])
1112 25 : << ":"
1113 50 : << htons((mask[11] << 8) | mask[10])
1114 25 : << ":"
1115 50 : << htons((mask[13] << 8) | mask[12])
1116 25 : << ":"
1117 50 : << htons((mask[15] << 8) | mask[14])
1118 25 : << "]";
1119 : char buf[1024]; // really large buffer to make sure it does not get truncated
1120 25 : if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
1121 : {
1122 0 : throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
1123 : }
1124 :
1125 : uint8_t default_mask[16];
1126 425 : for(int j(0); j < 16; ++j)
1127 : {
1128 400 : default_mask[j] = rand();
1129 : }
1130 : //std::stringstream default_smask;
1131 : //default_smask << std::hex
1132 : // << "["
1133 : // << htons((default_mask[ 1] << 8) | default_mask[ 0])
1134 : // << ":"
1135 : // << htons((default_mask[ 3] << 8) | default_mask[ 2])
1136 : // << ":"
1137 : // << htons((default_mask[ 5] << 8) | default_mask[ 4])
1138 : // << ":"
1139 : // << htons((default_mask[ 7] << 8) | default_mask[ 6])
1140 : // << ":"
1141 : // << htons((default_mask[ 9] << 8) | default_mask[ 8])
1142 : // << ":"
1143 : // << htons((default_mask[11] << 8) | default_mask[10])
1144 : // << ":"
1145 : // << htons((default_mask[13] << 8) | default_mask[12])
1146 : // << ":"
1147 : // << htons((default_mask[15] << 8) | default_mask[14])
1148 : // << "]";
1149 : char default_buf[1024]; // really large buffer to make sure it does not get truncated
1150 25 : if(inet_ntop(AF_INET6, default_mask, default_buf, sizeof(buf)) == nullptr)
1151 : {
1152 0 : throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
1153 : }
1154 25 : p.set_default_mask(default_buf);
1155 :
1156 50 : addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/" + smask.str()));
1157 25 : REQUIRE_FALSE(p.has_errors());
1158 25 : REQUIRE(ips.size() == 1);
1159 25 : addr::addr_range const & r(ips[0]);
1160 50 : addr::addr f(r.get_from());
1161 25 : REQUIRE_FALSE(f.is_ipv4());
1162 50 : std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + buf + "]");
1163 25 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1164 25 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1165 25 : REQUIRE(f.get_port() == port);
1166 25 : REQUIRE(f.get_protocol() == proto);
1167 : uint8_t verify_mask[16];
1168 25 : f.get_mask(verify_mask);
1169 425 : for(int j(0); j < 16; ++j)
1170 : {
1171 400 : REQUIRE(verify_mask[j] == mask[j]);
1172 : }
1173 : }
1174 : }
1175 :
1176 18 : SECTION("no address, but one IPv6 number masks")
1177 : {
1178 : // with just a number, the mask is considered an IPv6 mask
1179 : // if it is 33 or more
1180 : //
1181 97 : for(int idx(33); idx <= 128; ++idx)
1182 : {
1183 96 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
1184 96 : int const port(rand() & 0xFFFF);
1185 192 : addr::addr_parser p;
1186 96 : p.set_protocol(proto);
1187 96 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
1188 : //p.set_default_address("55:33:22:11:0:cc:bb:aa");
1189 192 : addr::addr_range::vector_t ips(p.parse(":" + std::to_string(port) + "/" + std::to_string(idx)));
1190 96 : REQUIRE_FALSE(p.has_errors());
1191 96 : REQUIRE(ips.size() == 1);
1192 96 : addr::addr_range const & r(ips[0]);
1193 192 : addr::addr f(r.get_from());
1194 96 : REQUIRE_FALSE(f.is_ipv4());
1195 96 : uint8_t mask[16] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };
1196 96 : int j(15);
1197 96 : int m(128 - idx);
1198 1130 : for(; m > 8; m -= 8, --j)
1199 : {
1200 517 : mask[j] = 0;
1201 : }
1202 96 : if(j < 0)
1203 : {
1204 0 : throw std::logic_error("invalid j here");
1205 : }
1206 96 : mask[j] = 255 << m;
1207 : char buf[1024]; // really large buffer to make sure it does not get truncated
1208 96 : if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
1209 : {
1210 0 : throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
1211 : }
1212 192 : std::string result("[::]:" + std::to_string(port) + "/[" + buf + "]");
1213 96 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1214 96 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1215 96 : REQUIRE(f.get_port() == port);
1216 96 : REQUIRE(f.get_protocol() == proto);
1217 : }
1218 : }
1219 :
1220 18 : SECTION("no address, but one IPv6 masks")
1221 : {
1222 : // with just a number, the mask is considered an IPv6 mask
1223 : // if it is 33 or more
1224 : //
1225 6 : for(int idx(0); idx < 5; ++idx)
1226 : {
1227 5 : int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
1228 5 : int const port(rand() & 0xFFFF);
1229 10 : addr::addr_parser p;
1230 5 : p.set_protocol(proto);
1231 5 : p.set_allow(addr::addr_parser::flag_t::MASK, true);
1232 : //p.set_default_address("55:33:22:11:0:cc:bb:aa");
1233 10 : addr::addr_range::vector_t ips(p.parse(":" + std::to_string(port) + "/[1:2:3:4:5:6:7:8]"));
1234 5 : REQUIRE_FALSE(p.has_errors());
1235 5 : REQUIRE(ips.size() == 1);
1236 5 : addr::addr_range const & r(ips[0]);
1237 10 : addr::addr f(r.get_from());
1238 5 : REQUIRE_FALSE(f.is_ipv4());
1239 10 : std::string result("[::]:" + std::to_string(port) + "/[1:2:3:4:5:6:7:8]");
1240 5 : REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1241 5 : REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
1242 5 : REQUIRE(f.get_port() == port);
1243 5 : REQUIRE(f.get_protocol() == proto);
1244 : }
1245 : }
1246 : }
1247 12 : }
1248 :
1249 :
1250 9 : TEST_CASE( "ipv6::network_type", "ipv6" )
1251 : {
1252 14 : GIVEN("addr()")
1253 : {
1254 14 : addr::addr a;
1255 :
1256 14 : SECTION("any (::)")
1257 : {
1258 : {
1259 1 : struct sockaddr_in6 in6 = sockaddr_in6();
1260 1 : in6.sin6_family = AF_INET6;
1261 1 : in6.sin6_port = htons(rand());
1262 1 : in6.sin6_addr.s6_addr32[0] = 0;
1263 1 : in6.sin6_addr.s6_addr32[1] = 0;
1264 1 : in6.sin6_addr.s6_addr32[2] = 0;
1265 1 : in6.sin6_addr.s6_addr32[3] = 0;
1266 :
1267 : // verify network type
1268 : //
1269 1 : a.set_ipv6(in6);
1270 :
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", "ipv4" )
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 2 : 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 2 : 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 2 : 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 2 : 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
|