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