LCOV - code coverage report
Current view: top level - tests - test_addr_ipv6.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 946 959 98.6 %
Date: 2018-05-30 23:58:02 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.12