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