LCOV - code coverage report
Current view: top level - tests - test_addr_ipv6.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 758 769 98.6 %
Date: 2017-01-21 19:00:32 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.12