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