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