LCOV - code coverage report
Current view: top level - tests - catch_ipv6.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1887 1916 98.5 %
Date: 2024-06-02 17:59:01 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2011-2023  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/libaddr
       4             : // contact@m2osw.com
       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 tests include a certain number of default/global
      41             :  * tests because internally the addr class implements an IPv6 object.
      42             :  */
      43             : 
      44             : // addr
      45             : //
      46             : #include    <libaddr/iface.h>
      47             : 
      48             : 
      49             : // self
      50             : //
      51             : #include    "catch_main.h"
      52             : 
      53             : 
      54             : // snapdev
      55             : //
      56             : #include    <snapdev/int128_literal.h>
      57             : #include    <snapdev/ostream_int128.h>
      58             : #include    <snapdev/string_replace_many.h>
      59             : 
      60             : 
      61             : // last include
      62             : //
      63             : #include    <snapdev/poison.h>
      64             : 
      65             : 
      66             : using namespace snapdev::literals;
      67             : 
      68             : 
      69             : 
      70             : /** \brief Details used by the addr class implementation.
      71             :  *
      72             :  * We have a function to check whether an address is part of
      73             :  * the interfaces of your computer. This check requires the
      74             :  * use of a `struct ifaddrs` and as such it requires to
      75             :  * delete that structure. We define a deleter for that
      76             :  * strucure here.
      77             :  */
      78             : namespace
      79             : {
      80             : 
      81             : /** \brief Close a socket.
      82             :  *
      83             :  * This deleter is used to make sure all the sockets get closed on exit.
      84             :  *
      85             :  * \param[in] s  The socket to close.
      86             :  */
      87           3 : void socket_deleter(int * s)
      88             : {
      89           3 :     close(*s);
      90           3 : }
      91             : 
      92             : 
      93             : }
      94             : // no name namespace
      95             : 
      96             : 
      97             : 
      98          14 : CATCH_TEST_CASE("ipv6::invalid_input", "[ipv6]")
      99             : {
     100          14 :     CATCH_GIVEN("addr()")
     101             :     {
     102           1 :         addr::addr a;
     103             : 
     104           1 :         CATCH_START_SECTION("ipv6::invalid_input: set IPv6 with an invalid family")
     105             :         {
     106           1 :             struct sockaddr_in6 in6 = sockaddr_in6();
     107             :             do
     108             :             {
     109           1 :                 in6.sin6_family = rand();
     110             :             }
     111           1 :             while(in6.sin6_family == AF_INET6);
     112           1 :             in6.sin6_port = rand();
     113           9 :             for(int idx(0); idx < 8; ++idx)
     114             :             {
     115           8 :                 in6.sin6_addr.s6_addr16[idx] = rand();
     116             :             }
     117           1 :             CATCH_REQUIRE_THROWS_AS(a.set_ipv6(in6), addr::addr_invalid_argument);
     118           1 :             CATCH_REQUIRE_THROWS_AS(addr::addr(in6), addr::addr_invalid_argument);
     119             :         }
     120           1 :         CATCH_END_SECTION()
     121          15 :     }
     122             : 
     123          14 :     CATCH_GIVEN("addr_parser() with IPv6 addresses")
     124             :     {
     125           3 :         CATCH_START_SECTION("ipv6::invalid_input: bad address")
     126             :         {
     127           1 :             addr::addr_parser p;
     128           3 :             addr::addr_range::vector_t ips(p.parse("[{bad-ip}]"));
     129           1 :             CATCH_REQUIRE(p.has_errors());
     130           1 :             CATCH_REQUIRE(p.error_count() == 1);
     131           1 :             CATCH_REQUIRE(p.error_messages() == "Invalid address in \"{bad-ip}\" error -2 -- Name or service not known (errno: 22 -- Invalid argument).\n");
     132           1 :             CATCH_REQUIRE(ips.size() == 0);
     133           1 :         }
     134           3 :         CATCH_END_SECTION()
     135             : 
     136           3 :         CATCH_START_SECTION("ipv6::invalid_input: missing ']'")
     137             :         {
     138           1 :             addr::addr_parser p;
     139           3 :             addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7"));
     140           1 :             CATCH_REQUIRE(p.has_errors());
     141           1 :             CATCH_REQUIRE(p.error_count() == 1);
     142           1 :             CATCH_REQUIRE(p.error_messages() == "IPv6 is missing the ']' ([1:2:3:4:5:6:7).\n");
     143           1 :             CATCH_REQUIRE(ips.size() == 0);
     144           1 :         }
     145           3 :         CATCH_END_SECTION()
     146             : 
     147           3 :         CATCH_START_SECTION("ipv6::invalid_input: required address")
     148             :         {
     149           1 :             addr::addr_parser p;
     150           1 :             p.set_protocol(IPPROTO_TCP);
     151           1 :             p.set_allow(addr::allow_t::ALLOW_REQUIRED_ADDRESS, true);
     152           3 :             addr::addr_range::vector_t ips(p.parse("[]"));
     153           1 :             CATCH_REQUIRE(p.has_errors());
     154           1 :             CATCH_REQUIRE(p.error_count() == 1);
     155           1 :             CATCH_REQUIRE(p.error_messages() == "Required address is missing.\n");
     156           1 :             CATCH_REQUIRE(ips.size() == 0);
     157           1 :         }
     158           3 :         CATCH_END_SECTION()
     159          14 :     }
     160             : 
     161          14 :     CATCH_GIVEN("addr_parser() with IPv4 ports")
     162             :     {
     163           2 :         CATCH_START_SECTION("ipv6::invalid_input: required port")
     164             :         {
     165             :             // optional + required -> required
     166             :             {
     167           1 :                 addr::addr_parser p;
     168           1 :                 p.set_protocol(IPPROTO_TCP);
     169           1 :                 p.set_allow(addr::allow_t::ALLOW_REQUIRED_PORT, true);
     170           3 :                 addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]"));
     171           1 :                 CATCH_REQUIRE(p.has_errors());
     172           1 :                 CATCH_REQUIRE(p.error_count() == 1);
     173           1 :                 CATCH_REQUIRE(p.error_messages() == "Required port is missing.\n");
     174           1 :                 CATCH_REQUIRE(ips.size() == 0);
     175           1 :             }
     176             : 
     177             :             // only required -> required just the same
     178             :             {
     179           1 :                 addr::addr_parser p;
     180           1 :                 p.set_protocol(IPPROTO_TCP);
     181           1 :                 p.set_allow(addr::allow_t::ALLOW_PORT, false);
     182           1 :                 p.set_allow(addr::allow_t::ALLOW_REQUIRED_PORT, true);
     183           3 :                 addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]"));
     184           1 :                 CATCH_REQUIRE(p.has_errors());
     185           1 :                 CATCH_REQUIRE(p.error_count() == 1);
     186           1 :                 CATCH_REQUIRE(p.error_messages() == "Required port is missing.\n");
     187           1 :                 CATCH_REQUIRE(ips.size() == 0);
     188           1 :             }
     189             :         }
     190           2 :         CATCH_END_SECTION()
     191             : 
     192           2 :         CATCH_START_SECTION("ipv6::invalid_input: port not allowed")
     193             :         {
     194             :             {
     195           1 :                 addr::addr_parser p;
     196           1 :                 p.set_protocol(IPPROTO_TCP);
     197           1 :                 p.set_allow(addr::allow_t::ALLOW_PORT, false);
     198           3 :                 addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:123"));
     199           1 :                 CATCH_REQUIRE(p.has_errors());
     200           1 :                 CATCH_REQUIRE(p.error_count() == 1);
     201           1 :                 CATCH_REQUIRE(p.error_messages() == "Port not allowed ([1:2:3:4:5:6:7:8]:123).\n");
     202           1 :                 CATCH_REQUIRE(ips.size() == 0);
     203           1 :             }
     204             : 
     205             :             {
     206           1 :                 addr::addr_parser p;
     207           1 :                 p.set_protocol(IPPROTO_TCP);
     208           1 :                 p.set_allow(addr::allow_t::ALLOW_PORT, false);
     209           3 :                 addr::addr_range::vector_t ips(p.parse("1:2:3:4:5:6:7:8:123.5"));
     210           1 :                 CATCH_REQUIRE(p.has_errors());
     211           1 :                 CATCH_REQUIRE(p.error_count() == 1);
     212           1 :                 CATCH_REQUIRE(p.error_messages() == "Invalid address in \"1:2:3:4:5:6:7:8:123.5\" error -2 -- Name or service not known (errno: 22 -- Invalid argument).\n");
     213           1 :                 CATCH_REQUIRE(ips.size() == 0);
     214           1 :             }
     215             :         }
     216           2 :         CATCH_END_SECTION()
     217          14 :     }
     218             : 
     219          14 :     CATCH_GIVEN("addr_parser() with invalid masks")
     220             :     {
     221           8 :         CATCH_START_SECTION("ipv6::invalid_input: really large numbers (over 1000)")
     222             :         {
     223           6 :             for(int idx(0); idx < 5; ++idx)
     224             :             {
     225           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     226           5 :                 int const port(rand() & 0xFFFF);
     227           5 :                 int const mask((rand() & 0xFF) + 10001);
     228           5 :                 addr::addr_parser p;
     229           5 :                 p.set_protocol(proto);
     230           5 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
     231          30 :                 addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/" + std::to_string(mask)));
     232           5 :                 CATCH_REQUIRE(p.has_errors());
     233           5 :                 CATCH_REQUIRE(p.error_count() == 1);
     234           5 :                 CATCH_REQUIRE(p.error_messages() == "Mask size too large (" + std::to_string(mask) + ", expected a maximum of 128).\n");
     235           5 :                 CATCH_REQUIRE(ips.size() == 0);
     236           5 :             }
     237             : 
     238             :             // in case the number is between square brackets it looks like
     239             :             // an IPv4 to getaddrinfo() so we get a different error...
     240             :             // (i.e. the '[' is not a digit so we do not get the "too large"
     241             :             // error...)
     242             :             //
     243           6 :             for(int idx(0); idx < 5; ++idx)
     244             :             {
     245           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     246           5 :                 int const port(rand() & 0xFFFF);
     247           5 :                 int const mask((rand() & 0xFF) + 10001);
     248           5 :                 addr::addr_parser p;
     249           5 :                 p.set_protocol(proto);
     250           5 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
     251           5 :                 p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
     252          35 :                 addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/[" + std::to_string(mask) + "]"));
     253           5 :                 CATCH_REQUIRE(p.has_errors());
     254           5 :                 CATCH_REQUIRE(p.error_count() == 1);
     255           5 :                 CATCH_REQUIRE(p.error_messages() == "Mask size too large ([" + std::to_string(mask) + "], expected a maximum of 128).\n");
     256           5 :                 CATCH_REQUIRE(ips.size() == 0);
     257           5 :             }
     258             : 
     259             :             // an empty address with a mask too large gets us to another place
     260             :             //
     261           6 :             for(int idx(0); idx < 5; ++idx)
     262             :             {
     263           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     264           5 :                 int const port(rand() & 0xFFFF);
     265           5 :                 int const mask((rand() & 0xFF) + 10001);
     266           5 :                 addr::addr_parser p;
     267           5 :                 p.set_protocol(proto);
     268           5 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
     269          30 :                 addr::addr_range::vector_t ips(p.parse(":" + std::to_string(port) + "/" + std::to_string(mask)));
     270           5 :                 CATCH_REQUIRE(p.has_errors());
     271           5 :                 CATCH_REQUIRE(p.error_count() == 1);
     272           5 :                 CATCH_REQUIRE(p.error_messages() == "Mask size too large (" + std::to_string(mask) + ", expected a maximum of 128).\n");
     273           5 :                 CATCH_REQUIRE(ips.size() == 0);
     274           5 :             }
     275             : 
     276             :             // an empty address with a mask too large gets us to another place
     277             :             //
     278           6 :             for(int idx(0); idx < 5; ++idx)
     279             :             {
     280           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     281           5 :                 int const port(rand() & 0xFFFF);
     282           5 :                 int const mask((rand() & 0xFF));
     283           5 :                 addr::addr_parser p;
     284           5 :                 p.set_protocol(proto);
     285           5 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
     286           5 :                 p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
     287          35 :                 addr::addr_range::vector_t ips(p.parse(":" + std::to_string(port) + "/" + std::to_string(mask) + "q"));
     288           5 :                 CATCH_REQUIRE(p.has_errors());
     289           5 :                 CATCH_REQUIRE(p.error_count() == 1);
     290           5 :                 CATCH_REQUIRE(p.error_messages() == "Invalid mask in \"/" + std::to_string(mask) + "q\", error -2 -- Name or service not known (errno: 0 -- Success).\n");
     291           5 :                 CATCH_REQUIRE(ips.size() == 0);
     292           5 :             }
     293             :         }
     294           8 :         CATCH_END_SECTION()
     295             : 
     296           8 :         CATCH_START_SECTION("ipv6::invalid_input: ipv6 mask is limited between 0 and 128")
     297             :         {
     298           6 :             for(int idx(0); idx < 5; ++idx)
     299             :             {
     300           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     301           5 :                 int const port(rand() & 0xFFFF);
     302           5 :                 int const mask((rand() & 0xFF) + 129);
     303           5 :                 addr::addr_parser p;
     304           5 :                 p.set_protocol(proto);
     305           5 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
     306          30 :                 addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/" + std::to_string(mask)));
     307           5 :                 CATCH_REQUIRE(p.has_errors());
     308           5 :                 CATCH_REQUIRE(p.error_count() == 1);
     309           5 :                 CATCH_REQUIRE(p.error_messages() == "Unsupported mask size (" + std::to_string(mask) + ", expected 128 at the most for an IPv6).\n");
     310           5 :                 CATCH_REQUIRE(ips.size() == 0);
     311           5 :             }
     312             :         }
     313           8 :         CATCH_END_SECTION()
     314             : 
     315           8 :         CATCH_START_SECTION("ipv6::invalid_input: ipv6 mask cannot use name")
     316             :         {
     317           6 :             for(int idx(0); idx < 5; ++idx)
     318             :             {
     319           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     320           5 :                 int const port(rand() & 0xFFFF);
     321           5 :                 addr::addr_parser p;
     322           5 :                 p.set_protocol(proto);
     323           5 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
     324           5 :                 p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
     325          20 :                 addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/[localhost]"));
     326           5 :                 CATCH_REQUIRE(p.has_errors());
     327           5 :                 CATCH_REQUIRE(p.error_count() == 1);
     328           5 :                 CATCH_REQUIRE(p.error_messages() == "Invalid mask in \"/[localhost]\", error -2 -- Name or service not known (errno: 0 -- Success).\n");
     329           5 :                 CATCH_REQUIRE(ips.size() == 0);
     330           5 :             }
     331             :         }
     332           8 :         CATCH_END_SECTION()
     333             : 
     334           8 :         CATCH_START_SECTION("ipv6::invalid_input: ipv6 mask must be between '[...]'")
     335             :         {
     336           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     337           1 :             int const port(rand() & 0xFFFF);
     338           1 :             addr::addr_parser p;
     339           1 :             p.set_protocol(proto);
     340           1 :             p.set_allow(addr::allow_t::ALLOW_MASK, true);
     341           1 :             p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
     342           4 :             addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/::3"));
     343           1 :             CATCH_REQUIRE(p.has_errors());
     344           1 :             CATCH_REQUIRE(p.error_count() == 1);
     345           1 :             CATCH_REQUIRE(p.error_messages() == "The address uses the IPv6 syntax, the mask cannot use IPv4.\n");
     346           1 :             CATCH_REQUIRE(ips.size() == 0);
     347           1 :         }
     348           8 :         CATCH_END_SECTION()
     349             : 
     350           8 :         CATCH_START_SECTION("ipv6::invalid_input: ipv6 mask missing the ']'")
     351             :         {
     352           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     353           1 :             int const port(rand() & 0xFFFF);
     354           1 :             addr::addr_parser p;
     355           1 :             p.set_protocol(proto);
     356           1 :             p.set_allow(addr::allow_t::ALLOW_MASK, true);
     357           1 :             p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
     358           4 :             addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/[::3"));
     359           1 :             CATCH_REQUIRE(p.has_errors());
     360           1 :             CATCH_REQUIRE(p.error_count() == 1);
     361           1 :             CATCH_REQUIRE(p.error_messages() == "The IPv6 mask is missing the ']' ([::3).\n");
     362           1 :             CATCH_REQUIRE(ips.size() == 0);
     363           1 :         }
     364           8 :         CATCH_END_SECTION()
     365             : 
     366           8 :         CATCH_START_SECTION("ipv6::invalid_input: ipv6 mask with an ipv4 in the '[...]'")
     367             :         {
     368           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     369           1 :             int const port(rand() & 0xFFFF);
     370           1 :             addr::addr_parser p;
     371           1 :             p.set_protocol(proto);
     372           1 :             p.set_allow(addr::allow_t::ALLOW_MASK, true);
     373           1 :             p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
     374           4 :             addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/[1.2.3.4]"));
     375           1 :             CATCH_REQUIRE(p.has_errors());
     376           1 :             CATCH_REQUIRE(p.error_count() == 1);
     377           1 :             CATCH_REQUIRE(p.error_messages() == "Incompatible address between the address and mask address (first was an IPv6 second an IPv4).\n");
     378           1 :             CATCH_REQUIRE(ips.size() == 0);
     379           1 :         }
     380           8 :         CATCH_END_SECTION()
     381             : 
     382           8 :         CATCH_START_SECTION("ipv6::invalid_input: verify default address")
     383             :         {
     384           1 :             addr::addr_parser p;
     385             : 
     386           5 :             CATCH_REQUIRE_THROWS_AS(p.set_default_address("[4:5:4:5:7:8:7:8"), addr::addr_invalid_argument);
     387           1 :             CATCH_REQUIRE(p.get_default_address4() == "");
     388           1 :             CATCH_REQUIRE(p.get_default_address6() == "");
     389             : 
     390           1 :             p.set_default_address("[1:7:1:7:1:7:1:7]");
     391           1 :             CATCH_REQUIRE(p.get_default_address4() == "");
     392           1 :             CATCH_REQUIRE(p.get_default_address6() == "1:7:1:7:1:7:1:7");
     393             : 
     394           5 :             CATCH_REQUIRE_THROWS_AS(p.set_default_address("[9:5:9:5:9:8:9:8"), addr::addr_invalid_argument);
     395           1 :             CATCH_REQUIRE(p.get_default_address4() == "");
     396           1 :             CATCH_REQUIRE(p.get_default_address6() == "1:7:1:7:1:7:1:7");
     397             : 
     398           1 :             p.set_default_address("12.55.1.9");
     399           1 :             CATCH_REQUIRE(p.get_default_address4() == "12.55.1.9");
     400           1 :             CATCH_REQUIRE(p.get_default_address6() == "1:7:1:7:1:7:1:7");
     401             : 
     402           5 :             CATCH_REQUIRE_THROWS_AS(p.set_default_address("[9:f00f:9:e00e:9:d00d:9:c00c"), addr::addr_invalid_argument);
     403           1 :             CATCH_REQUIRE(p.get_default_address4() == "12.55.1.9");
     404           1 :             CATCH_REQUIRE(p.get_default_address6() == "1:7:1:7:1:7:1:7");
     405             : 
     406           1 :             p.set_default_address("");
     407           1 :             CATCH_REQUIRE(p.get_default_address4() == "");
     408           1 :             CATCH_REQUIRE(p.get_default_address6() == "");
     409           1 :         }
     410           8 :         CATCH_END_SECTION()
     411             : 
     412           8 :         CATCH_START_SECTION("ipv6::invalid_input: verify default mask")
     413             :         {
     414           1 :             addr::addr_parser p;
     415             : 
     416           5 :             CATCH_REQUIRE_THROWS_AS(p.set_default_mask("[4:5:4:5:7:8:7:8"), addr::addr_invalid_argument);
     417           1 :             CATCH_REQUIRE(p.get_default_mask4() == "");
     418           1 :             CATCH_REQUIRE(p.get_default_mask6() == "");
     419             : 
     420           1 :             p.set_default_mask("[1:7:1:7:1:7:1:7]");
     421           1 :             CATCH_REQUIRE(p.get_default_mask4() == "");
     422           1 :             CATCH_REQUIRE(p.get_default_mask6() == "1:7:1:7:1:7:1:7");
     423             : 
     424           5 :             CATCH_REQUIRE_THROWS_AS(p.set_default_mask("[9:5:9:5:9:8:9:8"), addr::addr_invalid_argument);
     425           1 :             CATCH_REQUIRE(p.get_default_mask4() == "");
     426           1 :             CATCH_REQUIRE(p.get_default_mask6() == "1:7:1:7:1:7:1:7");
     427             : 
     428           1 :             p.set_default_mask("12.55.1.9");
     429           1 :             CATCH_REQUIRE(p.get_default_mask4() == "12.55.1.9");
     430           1 :             CATCH_REQUIRE(p.get_default_mask6() == "1:7:1:7:1:7:1:7");
     431             : 
     432           5 :             CATCH_REQUIRE_THROWS_AS(p.set_default_mask("[9:f00f:9:e00e:9:d00d:9:c00c"), addr::addr_invalid_argument);
     433           1 :             CATCH_REQUIRE(p.get_default_mask4() == "12.55.1.9");
     434           1 :             CATCH_REQUIRE(p.get_default_mask6() == "1:7:1:7:1:7:1:7");
     435             : 
     436           1 :             p.set_default_mask("55");
     437           1 :             CATCH_REQUIRE(p.get_default_mask4() == "12.55.1.9");
     438           1 :             CATCH_REQUIRE(p.get_default_mask6() == "55");
     439             : 
     440           1 :             p.set_default_mask("16");
     441           1 :             CATCH_REQUIRE(p.get_default_mask4() == "16");
     442           1 :             CATCH_REQUIRE(p.get_default_mask6() == "55");
     443             : 
     444           1 :             p.set_default_mask("");
     445           1 :             CATCH_REQUIRE(p.get_default_mask4() == "");
     446           1 :             CATCH_REQUIRE(p.get_default_mask6() == "");
     447             : 
     448          11 :             for(int idx(-10); idx < 0; ++idx)
     449             :             {
     450          30 :                 CATCH_REQUIRE_THROWS_MATCHES(
     451             :                           p.set_default_mask(std::to_string(idx))
     452             :                         , addr::addr_invalid_argument
     453             :                         , Catch::Matchers::ExceptionMessage(
     454             :                                   "addr_error: a mask number must be between 0 and 128."));
     455             :             }
     456             : 
     457           8 :             for(int idx(129); idx <= 135; ++idx)
     458             :             {
     459          21 :                 CATCH_REQUIRE_THROWS_MATCHES(
     460             :                           p.set_default_mask(std::to_string(idx))
     461             :                         , addr::addr_invalid_argument
     462             :                         , Catch::Matchers::ExceptionMessage(
     463             :                                   "addr_error: a mask number must be between 0 and 128."));
     464             :             }
     465           1 :         }
     466           8 :         CATCH_END_SECTION()
     467          14 :     }
     468          14 : }
     469             : 
     470             : 
     471          26 : CATCH_TEST_CASE("ipv6::address", "[ipv6]")
     472             : {
     473          26 :     CATCH_GIVEN("addr() with an IPv6")
     474             :     {
     475           6 :         addr::addr a;
     476             : 
     477           6 :         CATCH_START_SECTION("ipv6::address: default is 128 bit set to zero")
     478             :         {
     479           1 :             CATCH_REQUIRE(a.ip_to_uint128() == 0_uint128);
     480             : 
     481             :             // any address is not the next/previous of itself, even 0
     482           1 :             CATCH_REQUIRE_FALSE(a.is_next(a));
     483           1 :             CATCH_REQUIRE_FALSE(a.is_previous(a));
     484             : 
     485             :             // first address -N is still the first address
     486             :             //
     487           1 :             addr::addr b(a);
     488           1 :             CATCH_REQUIRE(a == b);
     489           1 :             b--;
     490           1 :             CATCH_REQUIRE(a == b);
     491           1 :             --b;
     492           1 :             CATCH_REQUIRE(a == b);
     493          11 :             for(int idx(0); idx < 10; ++idx)
     494             :             {
     495          10 :                 b -= rand() % 0xFFFF;
     496          10 :                 CATCH_REQUIRE(a == b);
     497             : 
     498          10 :                 addr::addr c(b - rand() % 0xFFFF);
     499          10 :                 CATCH_REQUIRE(a == c);
     500          10 :             }
     501             : 
     502           1 :             __int128 diff(a - b);
     503           1 :             CATCH_REQUIRE(diff == 0_int128);
     504           1 :         }
     505           6 :         CATCH_END_SECTION();
     506             : 
     507           6 :         CATCH_START_SECTION("ipv6::address: parse the default IPv6 address \"[::]\" and \"::\"")
     508             :         {
     509           1 :             int proto[] = { IPPROTO_TCP, IPPROTO_UDP, IPPROTO_IP };
     510             : 
     511           1 :             CATCH_REQUIRE(a.ip_to_uint128() == 0_uint128);
     512             : 
     513             :             {
     514             :                 // we do not specify the protocol so we receive one response
     515             :                 // per protocol (TCP, UDP, and IP)
     516             :                 //
     517           1 :                 addr::addr_parser p;
     518           3 :                 addr::addr_range::vector_t ips(p.parse("[::]"));
     519           1 :                 CATCH_REQUIRE(ips.size() == std::size(proto));
     520             : 
     521             :                 // the IP address itself is ANY
     522             :                 // the protocol varies, however
     523             :                 //
     524           4 :                 for(std::size_t idx(0); idx < std::size(proto); ++idx)
     525             :                 {
     526           3 :                     CATCH_REQUIRE(ips[idx].has_from());
     527           3 :                     CATCH_REQUIRE_FALSE(ips[idx].has_to());
     528           3 :                     CATCH_REQUIRE(ips[idx].get_from() == a);
     529           3 :                     CATCH_REQUIRE(ips[idx].get_from().get_protocol() == proto[idx]);
     530             :                 }
     531           1 :             }
     532             : 
     533             :             {
     534           1 :                 addr::addr_parser p;
     535           3 :                 addr::addr_range::vector_t ips(p.parse("::"));
     536           1 :                 CATCH_REQUIRE(ips.size() == std::size(proto));
     537             : 
     538             :                 // the IP address itself is ANY
     539             :                 // the protocol varies, however
     540             :                 //
     541           4 :                 for(std::size_t idx(0); idx < std::size(proto); ++idx)
     542             :                 {
     543           3 :                     CATCH_REQUIRE(ips[idx].has_from());
     544           3 :                     CATCH_REQUIRE_FALSE(ips[idx].has_to());
     545           3 :                     CATCH_REQUIRE(ips[idx].get_from() == a);
     546           3 :                     CATCH_REQUIRE(ips[idx].get_from().get_protocol() == proto[idx]);
     547             :                 }
     548           1 :             }
     549             :         }
     550           6 :         CATCH_END_SECTION();
     551             : 
     552             : #pragma GCC diagnostic push
     553             : #pragma GCC diagnostic ignored "-Wpedantic"
     554           6 :         CATCH_START_SECTION("ipv6::address: verify last IPv6 address")
     555             :         {
     556           1 :             CATCH_REQUIRE(a.ip_to_uint128() == 0_uint128);
     557             : 
     558           1 :             struct sockaddr_in6 in6 = sockaddr_in6();
     559           1 :             in6.sin6_family = AF_INET6;
     560           1 :             in6.sin6_port = htons(rand());
     561           1 :             in6.sin6_addr.s6_addr32[0] = 0xFFFFFFFF;
     562           1 :             in6.sin6_addr.s6_addr32[1] = 0xFFFFFFFF;
     563           1 :             in6.sin6_addr.s6_addr32[2] = 0xFFFFFFFF;
     564           1 :             in6.sin6_addr.s6_addr32[3] = 0xFFFFFFFF;
     565           1 :             a.set_ipv6(in6);
     566             : 
     567             :             // any address is not the next/previous of itself, even "-1"
     568           1 :             CATCH_REQUIRE_FALSE(a.is_next(a));
     569           1 :             CATCH_REQUIRE_FALSE(a.is_previous(a));
     570             : 
     571             :             // last address +N is still the last address
     572             :             //
     573           1 :             addr::addr b(a);
     574           1 :             CATCH_REQUIRE(a == b);
     575           1 :             b++;
     576           1 :             CATCH_REQUIRE(a == b);
     577           1 :             ++b;
     578           1 :             CATCH_REQUIRE(a == b);
     579          11 :             for(int idx(0); idx < 10; ++idx)
     580             :             {
     581          10 :                 b += rand() % 0xFFFF;
     582          10 :                 CATCH_REQUIRE(a == b);
     583             : 
     584          10 :                 addr::addr c(b + rand() % 0xFFFF);
     585          10 :                 CATCH_REQUIRE(a == c);
     586          10 :             }
     587             : 
     588           1 :             __int128 diff(a - b);
     589           1 :             CATCH_REQUIRE(diff == 0_int128);
     590           1 :         }
     591           6 :         CATCH_END_SECTION();
     592             : #pragma GCC diagnostic pop
     593             : 
     594             : #pragma GCC diagnostic push
     595             : #pragma GCC diagnostic ignored "-Wpedantic"
     596           6 :         CATCH_START_SECTION("ipv6::address: set_ipv6() / get_ipv6()")
     597             :         {
     598          11 :             for(int idx(0); idx < 10; ++idx)
     599             :             {
     600          10 :                 struct sockaddr_in6 in6 = sockaddr_in6();
     601          10 :                 in6.sin6_family = AF_INET6;
     602          10 :                 in6.sin6_port = htons(rand());
     603          10 :                 in6.sin6_addr.s6_addr16[0] = rand();
     604          10 :                 in6.sin6_addr.s6_addr16[1] = rand();
     605          10 :                 in6.sin6_addr.s6_addr16[2] = rand();
     606          10 :                 in6.sin6_addr.s6_addr16[3] = rand();
     607          10 :                 in6.sin6_addr.s6_addr16[4] = rand();
     608          10 :                 in6.sin6_addr.s6_addr16[5] = rand();
     609          10 :                 in6.sin6_addr.s6_addr16[6] = rand();
     610          10 :                 in6.sin6_addr.s6_addr16[7] = rand();
     611             : 
     612          10 :                 unsigned __int128 address(0_uint128);
     613          10 :                 address |= static_cast<unsigned __int128>(in6.sin6_addr.s6_addr[ 0]) << 120;
     614          10 :                 address |= static_cast<unsigned __int128>(in6.sin6_addr.s6_addr[ 1]) << 112;
     615          10 :                 address |= static_cast<unsigned __int128>(in6.sin6_addr.s6_addr[ 2]) << 104;
     616          10 :                 address |= static_cast<unsigned __int128>(in6.sin6_addr.s6_addr[ 3]) <<  96;
     617          10 :                 address |= static_cast<unsigned __int128>(in6.sin6_addr.s6_addr[ 4]) <<  88;
     618          10 :                 address |= static_cast<unsigned __int128>(in6.sin6_addr.s6_addr[ 5]) <<  80;
     619          10 :                 address |= static_cast<unsigned __int128>(in6.sin6_addr.s6_addr[ 6]) <<  72;
     620          10 :                 address |= static_cast<unsigned __int128>(in6.sin6_addr.s6_addr[ 7]) <<  64;
     621          10 :                 address |= static_cast<unsigned __int128>(in6.sin6_addr.s6_addr[ 8]) <<  56;
     622          10 :                 address |= static_cast<unsigned __int128>(in6.sin6_addr.s6_addr[ 9]) <<  48;
     623          10 :                 address |= static_cast<unsigned __int128>(in6.sin6_addr.s6_addr[10]) <<  40;
     624          10 :                 address |= static_cast<unsigned __int128>(in6.sin6_addr.s6_addr[11]) <<  32;
     625          10 :                 address |= static_cast<unsigned __int128>(in6.sin6_addr.s6_addr[12]) <<  24;
     626          10 :                 address |= static_cast<unsigned __int128>(in6.sin6_addr.s6_addr[13]) <<  16;
     627          10 :                 address |= static_cast<unsigned __int128>(in6.sin6_addr.s6_addr[14]) <<   8;
     628          10 :                 address |= static_cast<unsigned __int128>(in6.sin6_addr.s6_addr[15]) <<   0;
     629             : 
     630             :                 // set the address
     631             :                 //
     632          10 :                 a.set_ipv6(in6);
     633          10 :                 CATCH_REQUIRE(a.ip_to_uint128() == address);
     634             : 
     635             :                 // test constructor
     636             :                 //
     637          10 :                 addr::addr b(in6);
     638          10 :                 struct sockaddr_in6 out6;
     639          10 :                 b.get_ipv6(out6);
     640          10 :                 CATCH_REQUIRE(memcmp(&out6, &in6, sizeof(struct sockaddr_in)) == 0);
     641             : 
     642             :                 // test set
     643             :                 //
     644          10 :                 a.set_ipv6(in6);
     645          10 :                 a.get_ipv6(out6);
     646          10 :                 CATCH_REQUIRE(memcmp(&out6, &in6, sizeof(struct sockaddr_in)) == 0);
     647          10 :                 CATCH_REQUIRE(a.ip_to_uint128() == address);
     648             : 
     649          10 :                 struct sockaddr_in6 in6b = sockaddr_in6();
     650          10 :                 in6b.sin6_family = AF_INET6;
     651          10 :                 in6b.sin6_port = htons(rand());
     652          10 :                 in6b.sin6_addr.s6_addr16[0] = rand();
     653          10 :                 in6b.sin6_addr.s6_addr16[1] = rand();
     654          10 :                 in6b.sin6_addr.s6_addr16[2] = rand();
     655          10 :                 in6b.sin6_addr.s6_addr16[3] = rand();
     656          10 :                 in6b.sin6_addr.s6_addr16[4] = rand();
     657          10 :                 in6b.sin6_addr.s6_addr16[5] = rand();
     658          10 :                 in6b.sin6_addr.s6_addr16[6] = rand();
     659          10 :                 in6b.sin6_addr.s6_addr16[7] = rand();
     660             : 
     661          10 :                 unsigned __int128 new_address(0_uint128);
     662          10 :                 new_address |= static_cast<unsigned __int128>(in6b.sin6_addr.s6_addr[ 0]) << 120;
     663          10 :                 new_address |= static_cast<unsigned __int128>(in6b.sin6_addr.s6_addr[ 1]) << 112;
     664          10 :                 new_address |= static_cast<unsigned __int128>(in6b.sin6_addr.s6_addr[ 2]) << 104;
     665          10 :                 new_address |= static_cast<unsigned __int128>(in6b.sin6_addr.s6_addr[ 3]) <<  96;
     666          10 :                 new_address |= static_cast<unsigned __int128>(in6b.sin6_addr.s6_addr[ 4]) <<  88;
     667          10 :                 new_address |= static_cast<unsigned __int128>(in6b.sin6_addr.s6_addr[ 5]) <<  80;
     668          10 :                 new_address |= static_cast<unsigned __int128>(in6b.sin6_addr.s6_addr[ 6]) <<  72;
     669          10 :                 new_address |= static_cast<unsigned __int128>(in6b.sin6_addr.s6_addr[ 7]) <<  64;
     670          10 :                 new_address |= static_cast<unsigned __int128>(in6b.sin6_addr.s6_addr[ 8]) <<  56;
     671          10 :                 new_address |= static_cast<unsigned __int128>(in6b.sin6_addr.s6_addr[ 9]) <<  48;
     672          10 :                 new_address |= static_cast<unsigned __int128>(in6b.sin6_addr.s6_addr[10]) <<  40;
     673          10 :                 new_address |= static_cast<unsigned __int128>(in6b.sin6_addr.s6_addr[11]) <<  32;
     674          10 :                 new_address |= static_cast<unsigned __int128>(in6b.sin6_addr.s6_addr[12]) <<  24;
     675          10 :                 new_address |= static_cast<unsigned __int128>(in6b.sin6_addr.s6_addr[13]) <<  16;
     676          10 :                 new_address |= static_cast<unsigned __int128>(in6b.sin6_addr.s6_addr[14]) <<   8;
     677          10 :                 new_address |= static_cast<unsigned __int128>(in6b.sin6_addr.s6_addr[15]) <<   0;
     678             : 
     679          10 :                 a.ip_from_uint128(new_address);
     680          10 :                 CATCH_REQUIRE(a.ip_to_uint128() == new_address);
     681             : 
     682          10 :                 if(new_address >= 10)
     683             :                 {
     684          10 :                     addr::addr const e(a + -10);
     685          10 :                     CATCH_REQUIRE(e.ip_to_uint128() == new_address - 10);
     686             : 
     687          10 :                     addr::addr f(a);
     688          10 :                     f += -10;
     689          10 :                     CATCH_REQUIRE(e.ip_to_uint128() == new_address - 10);
     690          10 :                 }
     691          10 :                 if(new_address <= 0xffffffffffffffffffffffffffffffff_uint128 - 10)
     692             :                 {
     693          10 :                     addr::addr const e(a - -10);
     694          10 :                     CATCH_REQUIRE(e.ip_to_uint128() == new_address + 10);
     695             : 
     696          10 :                     addr::addr f(a);
     697          10 :                     f -= -10;
     698          10 :                     CATCH_REQUIRE(e.ip_to_uint128() == new_address + 10);
     699          10 :                 }
     700             : 
     701          10 :                 struct sockaddr_in6 in6c(in6b);
     702          10 :                 for(int p(16); p > 0; )
     703             :                 {
     704          10 :                     --p;
     705          10 :                     ++in6c.sin6_addr.s6_addr[p];
     706          10 :                     if(in6c.sin6_addr.s6_addr[p] != 0)
     707             :                     {
     708          10 :                         break;
     709             :                     }
     710             :                 }
     711             : 
     712          10 :                 addr::addr const c(in6c);
     713          10 :                 CATCH_REQUIRE(a.is_next(c));
     714             : 
     715          10 :                 struct sockaddr_in6 in6d(in6b);
     716          10 :                 for(int p(16); p > 0; )
     717             :                 {
     718          10 :                     --p;
     719          10 :                     --in6d.sin6_addr.s6_addr[p];
     720          10 :                     if(in6d.sin6_addr.s6_addr[p] != 0xFF)
     721             :                     {
     722          10 :                         break;
     723             :                     }
     724             :                 }
     725             : 
     726          10 :                 addr::addr const d(in6d);
     727          10 :                 CATCH_REQUIRE(a.is_previous(d));
     728          10 :             }
     729             :         }
     730           6 :         CATCH_END_SECTION()
     731             : #pragma GCC diagnostic pop
     732             : 
     733           6 :         CATCH_START_SECTION("ipv6::address: set_ipv6() check to_ipv6_string()")
     734             :         {
     735           1 :             std::vector<char const *> locales = {
     736             :                 "en_US.utf8",
     737             :                 "fr_FR.utf8",
     738             :                 "ja_JP.utf8",
     739             :                 "zh_SG.utf8",
     740           2 :             };
     741           5 :             for(auto const & l : locales)
     742             :             {
     743           4 :                 std::locale const loc(l);
     744             : 
     745           4 :                 std::map<addr::string_ip_t, std::string> addr_vec;
     746           4 :                 addr::addr::vector_t addresses;
     747          44 :                 for(int idx(0); idx < 10; ++idx)
     748             :                 {
     749          40 :                     struct sockaddr_in6 in6 = sockaddr_in6();
     750          40 :                     in6.sin6_family = AF_INET6;
     751          40 :                     in6.sin6_port = htons(rand());
     752         360 :                     for(int j(0); j < 8; ++j)
     753             :                     {
     754             :                         // avoid any zeroes so that way we do not have
     755             :                         // to handle the "::" syntax
     756             :                         do
     757             :                         {
     758         320 :                             in6.sin6_addr.s6_addr16[j] = rand();
     759             :                         }
     760         320 :                         while(in6.sin6_addr.s6_addr16[j] == 0);
     761             :                     }
     762             : 
     763          40 :                     std::stringstream ip_buf;
     764          40 :                     ip_buf << std::hex
     765          40 :                            << ntohs(in6.sin6_addr.s6_addr16[0])
     766          40 :                            << ":"
     767          40 :                            << ntohs(in6.sin6_addr.s6_addr16[1])
     768          40 :                            << ":"
     769          40 :                            << ntohs(in6.sin6_addr.s6_addr16[2])
     770          40 :                            << ":"
     771          40 :                            << ntohs(in6.sin6_addr.s6_addr16[3])
     772          40 :                            << ":"
     773          40 :                            << ntohs(in6.sin6_addr.s6_addr16[4])
     774          40 :                            << ":"
     775          40 :                            << ntohs(in6.sin6_addr.s6_addr16[5])
     776          40 :                            << ":"
     777          40 :                            << ntohs(in6.sin6_addr.s6_addr16[6])
     778          40 :                            << ":"
     779          40 :                            << ntohs(in6.sin6_addr.s6_addr16[7]);
     780          40 :                     std::string const ip(ip_buf.str());
     781             : 
     782          40 :                     std::string port_str(std::to_string(static_cast<int>(htons(in6.sin6_port))));
     783             : 
     784             :                     // check IPv6 as a string
     785             :                     //
     786          40 :                     a.set_ipv6(in6);
     787          40 :                     addresses.push_back(a);
     788          40 :                     CATCH_REQUIRE(a.get_str_port() == port_str);
     789             :                     {
     790          40 :                         std::string const str(a.to_ipv6_string(addr::STRING_IP_ADDRESS));
     791          40 :                         if(addr_vec[addr::STRING_IP_ADDRESS] != std::string())
     792             :                         {
     793          36 :                             addr_vec[addr::STRING_IP_ADDRESS] += ",";
     794             :                         }
     795          40 :                         addr_vec[addr::STRING_IP_ADDRESS] += str;
     796          40 :                         CATCH_REQUIRE(str == ip);
     797          40 :                     }
     798             :                     {
     799          40 :                         std::string const str(a.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS));
     800          40 :                         if(addr_vec[addr::STRING_IP_BRACKET_ADDRESS] != std::string())
     801             :                         {
     802          36 :                             addr_vec[addr::STRING_IP_BRACKET_ADDRESS] += ",";
     803             :                         }
     804          40 :                         addr_vec[addr::STRING_IP_BRACKET_ADDRESS] += str;
     805          40 :                         CATCH_REQUIRE(str == "[" + ip + "]");
     806          40 :                     }
     807             :                     {
     808          40 :                         std::string const str(a.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT));
     809          40 :                         if(addr_vec[addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT] != std::string())
     810             :                         {
     811          36 :                             addr_vec[addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT] += ",";
     812             :                         }
     813          40 :                         addr_vec[addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT] += str;
     814          40 :                         CATCH_REQUIRE(str == "[" + ip + "]:" + port_str);
     815          40 :                     }
     816             :                     {
     817          40 :                         std::string const str(a.to_ipv6_string(addr::STRING_IP_ADDRESS | addr::STRING_IP_MASK));
     818          40 :                         if(addr_vec[addr::STRING_IP_ADDRESS | addr::STRING_IP_MASK] != std::string())
     819             :                         {
     820          36 :                             addr_vec[addr::STRING_IP_ADDRESS | addr::STRING_IP_MASK] += ",";
     821             :                         }
     822          40 :                         addr_vec[addr::STRING_IP_ADDRESS | addr::STRING_IP_MASK] += str;
     823          40 :                         CATCH_REQUIRE(str == ip + "/128");
     824          40 :                     }
     825             :                     {
     826          40 :                         std::string const str(a.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_BRACKET_MASK));
     827          40 :                         if(addr_vec[addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_BRACKET_MASK] != std::string())
     828             :                         {
     829          36 :                             addr_vec[addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_BRACKET_MASK] += ",";
     830             :                         }
     831          40 :                         addr_vec[addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_BRACKET_MASK] += str;
     832          40 :                         CATCH_REQUIRE(str == "[" + ip + "]/128");
     833          40 :                     }
     834             :                     {
     835          40 :                         std::string const str(a.to_ipv6_string(addr::STRING_IP_ALL));
     836          40 :                         if(addr_vec[addr::STRING_IP_ALL] != std::string())
     837             :                         {
     838          36 :                             addr_vec[addr::STRING_IP_ALL] += ",";
     839             :                         }
     840          40 :                         addr_vec[addr::STRING_IP_ALL] += str;
     841          40 :                         CATCH_REQUIRE(str == "[" + ip + "]:" + port_str + "/128");
     842          40 :                     }
     843             : 
     844             :                     // the ostream functions
     845             :                     {
     846          40 :                         std::stringstream ss;
     847          40 :                         ss << a; // mode defaults to ALL
     848          40 :                         CATCH_REQUIRE(ss.str() == "[" + ip + "]:" + port_str + "/128");
     849          40 :                     }
     850             :                     {
     851          40 :                         std::stringstream ss;
     852          40 :                         ss << addr::setaddrmode(addr::STRING_IP_ADDRESS) << a;
     853          40 :                         CATCH_REQUIRE(ss.str() == ip);
     854          40 :                     }
     855             :                     {
     856          40 :                         std::stringstream ss;
     857          40 :                         ss << addr::setaddrmode(addr::STRING_IP_BRACKET_ADDRESS) << a;
     858          40 :                         CATCH_REQUIRE(ss.str() == "[" + ip + "]");
     859          40 :                     }
     860             :                     {
     861          40 :                         std::stringstream ss;
     862          40 :                         ss << addr::setaddrmode(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT) << a;
     863          40 :                         CATCH_REQUIRE(ss.str() == "[" + ip + "]:" + port_str);
     864          40 :                     }
     865             :                     {
     866          40 :                         std::stringstream ss;
     867          40 :                         ss << addr::setaddrmode(addr::STRING_IP_ADDRESS | addr::STRING_IP_MASK) << a;
     868          40 :                         CATCH_REQUIRE(ss.str() == ip + "/128");
     869          40 :                     }
     870             :                     {
     871          40 :                         std::stringstream ss;
     872          40 :                         ss << addr::setaddrmode(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_BRACKET_MASK) << a;
     873          40 :                         CATCH_REQUIRE(ss.str() == "[" + ip + "]/128");
     874          40 :                     }
     875             :                     {
     876          40 :                         std::stringstream ss;
     877          40 :                         ss << addr::setaddrmode(addr::STRING_IP_ALL) << a;
     878          40 :                         CATCH_REQUIRE(ss.str() == "[" + ip + "]:" + port_str + "/128");
     879          40 :                     }
     880             :                     {
     881          40 :                         std::stringstream ss;
     882          40 :                         ss << addr::setaddrmode(addr::STRING_IP_PORT);
     883          40 :                         ss.copyfmt(std::cout); // we did not change the mode of std::cout so here we expect STRING_IP_ALL after the copy
     884          40 :                         ss << a;
     885          40 :                         CATCH_REQUIRE(ss.str() == "[" + ip + "]:" + port_str + "/128");
     886          40 :                     }
     887             :                     {
     888          40 :                         std::stringstream sss;
     889          40 :                         std::stringstream ssd;
     890          40 :                         sss << addr::setaddrmode(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT);
     891          40 :                         ssd << addr::setaddrmode(addr::STRING_IP_BRACKET_ADDRESS);
     892          40 :                         ssd.copyfmt(sss);
     893          40 :                         ssd << a;
     894          40 :                         CATCH_REQUIRE(ssd.str() == "[" + ip + "]:" + port_str);
     895          40 :                     }
     896          40 :                 }
     897             : 
     898             :                 {
     899           4 :                     std::stringstream ss;
     900           4 :                     ss << addresses;
     901           4 :                     ss.imbue(loc);
     902           4 :                     CATCH_REQUIRE(ss.str() == addr_vec[addr::STRING_IP_ALL]);
     903           4 :                 }
     904             :                 {
     905           4 :                     std::stringstream ss;
     906           4 :                     ss.imbue(loc);
     907           4 :                     ss << addr::setaddrsep(" ");
     908           4 :                     ss.imbue(loc);
     909           4 :                     ss << addresses;
     910          20 :                     std::string const expected(snapdev::string_replace_many(addr_vec[addr::STRING_IP_ALL], {{",", " "}}));
     911           4 :                     CATCH_REQUIRE(ss.str() == expected);
     912           4 :                 }
     913             :                 {
     914           4 :                     std::stringstream ss;
     915           4 :                     ss << addr::setaddrmode(addr::STRING_IP_ADDRESS);
     916           4 :                     ss.imbue(loc);
     917           4 :                     ss << addresses;
     918           4 :                     CATCH_REQUIRE(ss.str() == addr_vec[addr::STRING_IP_ADDRESS]);
     919           4 :                 }
     920             :                 {
     921           4 :                     std::stringstream ss;
     922           4 :                     ss << addr::setaddrsep("|") << addr::setaddrmode(addr::STRING_IP_ADDRESS) << addresses;
     923          20 :                     std::string const expected(snapdev::string_replace_many(addr_vec[addr::STRING_IP_ADDRESS], {{",", "|"}}));
     924           4 :                     CATCH_REQUIRE(ss.str() == expected);
     925           4 :                 }
     926             :                 {
     927           4 :                     std::stringstream ss;
     928           4 :                     ss << addr::setaddrmode(addr::STRING_IP_BRACKET_ADDRESS) << addresses;
     929           4 :                     CATCH_REQUIRE(ss.str() == addr_vec[addr::STRING_IP_BRACKET_ADDRESS]);
     930           4 :                 }
     931             :                 {
     932           4 :                     std::stringstream ss;
     933           4 :                     ss << addr::setaddrsep(";") << addr::setaddrmode(addr::STRING_IP_BRACKET_ADDRESS) << addresses;
     934          20 :                     std::string const expected(snapdev::string_replace_many(addr_vec[addr::STRING_IP_BRACKET_ADDRESS], {{",", ";"}}));
     935           4 :                     CATCH_REQUIRE(ss.str() == expected);
     936           4 :                 }
     937             :                 {
     938           4 :                     std::stringstream ss;
     939           4 :                     ss << addr::setaddrmode(addr::STRING_IP_ADDRESS | addr::STRING_IP_PORT) << addresses;
     940           4 :                     CATCH_REQUIRE(ss.str() == addr_vec[addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT]);
     941           4 :                 }
     942             :                 {
     943           4 :                     std::stringstream ss;
     944           4 :                     ss << addr::setaddrsep("+") << addr::setaddrmode(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT);
     945           4 :                     ss.imbue(loc);
     946           4 :                     ss << addresses;
     947          20 :                     std::string const expected(snapdev::string_replace_many(addr_vec[addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT], {{",", "+"}}));
     948           4 :                     CATCH_REQUIRE(ss.str() == expected);
     949           4 :                 }
     950             :                 {
     951           4 :                     std::stringstream ss;
     952           4 :                     ss.imbue(loc);
     953           4 :                     ss << addr::setaddrmode(addr::STRING_IP_ADDRESS | addr::STRING_IP_MASK) << addresses;
     954           4 :                     CATCH_REQUIRE(ss.str() == addr_vec[addr::STRING_IP_ADDRESS | addr::STRING_IP_MASK]);
     955           4 :                 }
     956             :                 {
     957           4 :                     std::stringstream ss;
     958           4 :                     ss << addr::setaddrsep(", ") << addr::setaddrmode(addr::STRING_IP_ADDRESS | addr::STRING_IP_MASK) << addresses;
     959          20 :                     std::string const expected(snapdev::string_replace_many(addr_vec[addr::STRING_IP_ADDRESS | addr::STRING_IP_MASK], {{",", ", "}}));
     960           4 :                     CATCH_REQUIRE(ss.str() == expected);
     961           4 :                 }
     962             :                 {
     963           4 :                     std::stringstream ss;
     964           4 :                     ss << addr::setaddrmode(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_BRACKET_MASK) << addresses;
     965           4 :                     CATCH_REQUIRE(ss.str() == addr_vec[addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_BRACKET_MASK]);
     966           4 :                 }
     967             :                 {
     968           4 :                     std::stringstream ss;
     969           4 :                     ss << addr::setaddrsep("$") << addr::setaddrmode(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_BRACKET_MASK) << addresses;
     970          20 :                     std::string const expected(snapdev::string_replace_many(addr_vec[addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_BRACKET_MASK], {{",", "$"}}));
     971           4 :                     CATCH_REQUIRE(ss.str() == expected);
     972           4 :                 }
     973             :                 {
     974           4 :                     std::stringstream ss;
     975           4 :                     ss << addr::setaddrmode(addr::STRING_IP_ALL);
     976           4 :                     ss.imbue(loc);
     977           4 :                     ss << addresses;
     978           4 :                     CATCH_REQUIRE(ss.str() == addr_vec[addr::STRING_IP_ALL]);
     979           4 :                 }
     980             :                 {
     981           4 :                     std::stringstream ss;
     982           4 :                     ss.imbue(loc);
     983           4 :                     ss << addr::setaddrsep("\n") << addr::setaddrmode(addr::STRING_IP_ALL) << addresses;
     984          20 :                     std::string const expected(snapdev::string_replace_many(addr_vec[addr::STRING_IP_ALL], {{",", "\n"}}));
     985           4 :                     CATCH_REQUIRE(ss.str() == expected);
     986           4 :                 }
     987           4 :             }
     988           1 :         }
     989           6 :         CATCH_END_SECTION()
     990             : 
     991           6 :         CATCH_START_SECTION("ipv6::address: name of various IPs")
     992             :         {
     993           1 :             struct sockaddr_in6 in6 = sockaddr_in6();
     994           1 :             in6.sin6_family = AF_INET6;
     995           1 :             in6.sin6_port = htons(rand());
     996             : 
     997             :             // verify network type
     998             :             //
     999           1 :             a.set_ipv6(in6);
    1000           1 :             CATCH_REQUIRE(a.get_name() == std::string()); // no name for "any" (TCP)
    1001             : 
    1002           1 :             a.set_protocol(IPPROTO_UDP);
    1003           1 :             CATCH_REQUIRE(a.get_name() == std::string()); // no name for "any" (UDP)
    1004             : 
    1005           1 :             in6 = sockaddr_in6();
    1006           1 :             in6.sin6_family = AF_INET6;
    1007           1 :             in6.sin6_port = htons(rand());
    1008           1 :             in6.sin6_addr.s6_addr16[7] = htons(1);
    1009           1 :             a.set_ipv6(in6);
    1010           1 :             char hostname[HOST_NAME_MAX + 1];
    1011           1 :             hostname[HOST_NAME_MAX] = '\0';
    1012           1 :             CATCH_REQUIRE(gethostname(hostname, sizeof(hostname)) == 0);
    1013           1 :             CATCH_REQUIRE(hostname[0] != '\0');
    1014           1 :             std::string localhost(a.get_name());
    1015           1 :             bool const localhost_flag(localhost == hostname || localhost == "ip6-localhost");
    1016           1 :             CATCH_REQUIRE(localhost_flag);
    1017             : 
    1018           1 :             CATCH_REQUIRE(addr::find_addr_interface(a, false) != nullptr);
    1019           1 :         }
    1020           6 :         CATCH_END_SECTION()
    1021          32 :     }
    1022             : 
    1023          26 :     CATCH_GIVEN("addr_parser() with IPv6 addresses")
    1024             :     {
    1025           3 :         CATCH_START_SECTION("ipv6::address: verify basics")
    1026             :         {
    1027           1 :             addr::addr_parser p;
    1028           1 :             p.set_protocol(IPPROTO_TCP);
    1029           3 :             addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]"));
    1030           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1031           1 :             CATCH_REQUIRE(ips.size() == 1);
    1032           1 :             addr::addr_range const & r(ips[0]);
    1033           1 :             CATCH_REQUIRE(r.has_from());
    1034           1 :             CATCH_REQUIRE_FALSE(r.has_to());
    1035           1 :             CATCH_REQUIRE_FALSE(r.is_range());
    1036           1 :             CATCH_REQUIRE_FALSE(r.is_empty());
    1037           1 :             addr::addr f(r.get_from());
    1038           1 :             CATCH_REQUIRE_FALSE(f.is_ipv4());
    1039           1 :             CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    1040           1 :             CATCH_REQUIRE(f.get_family() == AF_INET6);
    1041           1 :             CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_ADDRESS) == "1:2:3:4:5:6:7:8");
    1042           1 :             CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS) == "[1:2:3:4:5:6:7:8]");
    1043           1 :             CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "1:2:3:4:5:6:7:8");
    1044           1 :             CATCH_REQUIRE(f.get_port() == 0);
    1045           1 :             CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1046           1 :             CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1047           1 :             CATCH_REQUIRE_FALSE(f.is_lan());
    1048           1 :             CATCH_REQUIRE_FALSE(f.is_lan(true));
    1049           1 :             CATCH_REQUIRE_FALSE(f.is_lan(false));
    1050           1 :             CATCH_REQUIRE(f.is_wan());
    1051           1 :             CATCH_REQUIRE(f.is_wan(true));
    1052           1 :             CATCH_REQUIRE(f.is_wan(false));
    1053           1 :             uint8_t mask[16] = {};
    1054           1 :             f.get_mask(mask);
    1055          17 :             for(int idx(0); idx < 16; ++idx)
    1056             :             {
    1057          16 :                 CATCH_REQUIRE(mask[idx] == 255);
    1058             :             }
    1059           1 :             CATCH_REQUIRE(f.get_mask_size() == 128);
    1060           1 :         }
    1061           3 :         CATCH_END_SECTION()
    1062             : 
    1063           3 :         CATCH_START_SECTION("ipv6::address: default address")
    1064             :         {
    1065           1 :             addr::addr_parser p;
    1066           1 :             p.set_protocol(IPPROTO_TCP);
    1067           1 :             p.set_default_address("5:5:5:5:5:5:5:5");
    1068           3 :             addr::addr_range::vector_t ips(p.parse(""));
    1069           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1070           1 :             CATCH_REQUIRE(ips.size() == 1);
    1071           1 :             addr::addr_range const & r(ips[0]);
    1072           1 :             CATCH_REQUIRE(r.has_from());
    1073           1 :             CATCH_REQUIRE_FALSE(r.has_to());
    1074           1 :             CATCH_REQUIRE_FALSE(r.is_range());
    1075           1 :             CATCH_REQUIRE_FALSE(r.is_empty());
    1076           1 :             addr::addr f(r.get_from());
    1077           1 :             CATCH_REQUIRE_FALSE(f.is_ipv4());
    1078           1 :             CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    1079           1 :             CATCH_REQUIRE(f.get_family() == AF_INET6);
    1080           1 :             CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_ADDRESS) == "5:5:5:5:5:5:5:5");
    1081           1 :             CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS) == "[5:5:5:5:5:5:5:5]");
    1082           1 :             CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "5:5:5:5:5:5:5:5");
    1083           1 :             CATCH_REQUIRE(f.get_port() == 0);
    1084           1 :             CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1085           1 :             CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1086           1 :             CATCH_REQUIRE_FALSE(f.is_lan());
    1087           1 :             CATCH_REQUIRE_FALSE(f.is_lan(true));
    1088           1 :             CATCH_REQUIRE_FALSE(f.is_lan(false));
    1089           1 :             CATCH_REQUIRE(f.is_wan());
    1090           1 :             CATCH_REQUIRE(f.is_wan(true));
    1091           1 :             CATCH_REQUIRE(f.is_wan(false));
    1092           1 :         }
    1093           3 :         CATCH_END_SECTION()
    1094             : 
    1095           3 :         CATCH_START_SECTION("ipv6::address: address, no port allowed")
    1096             :         {
    1097             :             // specific address with a default
    1098             :             {
    1099           1 :                 addr::addr_parser p;
    1100           1 :                 p.set_allow(addr::allow_t::ALLOW_PORT, false);
    1101           1 :                 p.set_protocol(IPPROTO_TCP);
    1102           1 :                 p.set_default_address("8:7:6:5:4:3:2:1");
    1103           3 :                 addr::addr_range::vector_t ips(p.parse("[9:9:9:9:4:3:2:1]"));
    1104           1 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1105           1 :                 CATCH_REQUIRE(ips.size() == 1);
    1106           1 :                 addr::addr_range const & r(ips[0]);
    1107           1 :                 CATCH_REQUIRE(r.has_from());
    1108           1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1109           1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1110           1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1111           1 :                 addr::addr f(r.get_from());
    1112           1 :                 CATCH_REQUIRE_FALSE(f.is_ipv4());
    1113           1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    1114           1 :                 CATCH_REQUIRE(f.get_family() == AF_INET6);
    1115           1 :                 CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_ADDRESS) == "9:9:9:9:4:3:2:1");
    1116           1 :                 CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS) == "[9:9:9:9:4:3:2:1]");
    1117           1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "9:9:9:9:4:3:2:1");
    1118           1 :                 CATCH_REQUIRE(f.get_port() == 0);
    1119           1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1120           1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1121           1 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1122           1 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1123           1 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1124           1 :                 CATCH_REQUIRE(f.is_wan());
    1125           1 :                 CATCH_REQUIRE(f.is_wan(true));
    1126           1 :                 CATCH_REQUIRE(f.is_wan(false));
    1127           1 :             }
    1128             : 
    1129             :             // only a default address
    1130             :             {
    1131           1 :                 addr::addr_parser p;
    1132           1 :                 p.set_allow(addr::allow_t::ALLOW_PORT, false);
    1133           1 :                 p.set_protocol(IPPROTO_TCP);
    1134           1 :                 p.set_default_address("5:1:6:2:7:3:8:4");
    1135           3 :                 addr::addr_range::vector_t ips(p.parse(""));
    1136           1 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1137           1 :                 CATCH_REQUIRE(ips.size() == 1);
    1138           1 :                 addr::addr_range const & r(ips[0]);
    1139           1 :                 CATCH_REQUIRE(r.has_from());
    1140           1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1141           1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1142           1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1143           1 :                 addr::addr f(r.get_from());
    1144           1 :                 CATCH_REQUIRE_FALSE(f.is_ipv4());
    1145           1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    1146           1 :                 CATCH_REQUIRE(f.get_family() == AF_INET6);
    1147           1 :                 CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_ADDRESS) == "5:1:6:2:7:3:8:4");
    1148           1 :                 CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS) == "[5:1:6:2:7:3:8:4]");
    1149           1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "5:1:6:2:7:3:8:4");
    1150           1 :                 CATCH_REQUIRE(f.get_port() == 0);
    1151           1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1152           1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1153           1 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1154           1 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1155           1 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1156           1 :                 CATCH_REQUIRE(f.is_wan());
    1157           1 :                 CATCH_REQUIRE(f.is_wan(true));
    1158           1 :                 CATCH_REQUIRE(f.is_wan(false));
    1159           1 :             }
    1160             :         }
    1161           3 :         CATCH_END_SECTION()
    1162          26 :     }
    1163             : 
    1164          26 :     CATCH_GIVEN("addr_parser() with numeric only IPv6 addresses")
    1165             :     {
    1166           3 :         CATCH_START_SECTION("ipv6::address: simple numeric IPv6")
    1167             :         {
    1168           1 :             addr::addr_parser p;
    1169           1 :             p.set_protocol(IPPROTO_TCP);
    1170           1 :             p.set_allow(addr::allow_t::ALLOW_ADDRESS_LOOKUP, false);
    1171           3 :             addr::addr_range::vector_t ips(p.parse("[4::f003:3001:20af]:5093"));
    1172           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1173           1 :             CATCH_REQUIRE(ips.size() == 1);
    1174             : 
    1175           1 :             addr::addr_range const & r(ips[0]);
    1176           1 :             CATCH_REQUIRE(r.has_from());
    1177           1 :             CATCH_REQUIRE_FALSE(r.has_to());
    1178           1 :             CATCH_REQUIRE_FALSE(r.is_range());
    1179           1 :             CATCH_REQUIRE_FALSE(r.is_empty());
    1180           1 :             addr::addr f(r.get_from());
    1181           1 :             CATCH_REQUIRE_FALSE(f.is_ipv4());
    1182           1 :             CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    1183           1 :             CATCH_REQUIRE(f.get_family() == AF_INET6);
    1184             :             // getting an IPv4 would throw, which is checked somewhere else
    1185             :             //CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "");
    1186           1 :             CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "4::f003:3001:20af");
    1187           1 :             CATCH_REQUIRE(f.get_port() == 5093);
    1188           1 :             CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1189           1 :             CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1190           1 :             CATCH_REQUIRE_FALSE(f.is_lan());
    1191           1 :             CATCH_REQUIRE_FALSE(f.is_lan(true));
    1192           1 :             CATCH_REQUIRE_FALSE(f.is_lan(false));
    1193           1 :             CATCH_REQUIRE(f.is_wan());
    1194           1 :             CATCH_REQUIRE(f.is_wan(true));
    1195           1 :             CATCH_REQUIRE(f.is_wan(false));
    1196           1 :             uint8_t mask[16] = {};
    1197           1 :             f.get_mask(mask);
    1198          17 :             for(int idx(0); idx < 16; ++idx)
    1199             :             {
    1200          16 :                 CATCH_REQUIRE(mask[idx] == 255);
    1201             :             }
    1202           1 :             CATCH_REQUIRE(f.get_mask_size() == 128);
    1203           1 :         }
    1204           3 :         CATCH_END_SECTION()
    1205             : 
    1206           3 :         CATCH_START_SECTION("ipv6::address: invalid IPv6 domain name address when we only accept numeric IPs")
    1207             :         {
    1208             :             // this is exactly the same path as the IPv4 test...
    1209             :             // if we have a named domain then IPv4 fails, IPv6 fails, then we err on it
    1210             :             //
    1211           1 :             addr::addr_parser p;
    1212           1 :             p.set_protocol(IPPROTO_TCP);
    1213           1 :             p.set_allow(addr::allow_t::ALLOW_ADDRESS_LOOKUP, false);
    1214           3 :             addr::addr_range::vector_t const ips(p.parse("ipv6.example.com:4471"));
    1215           1 :             CATCH_REQUIRE(p.has_errors());
    1216           1 :             CATCH_REQUIRE(p.error_count() == 1);
    1217           1 :             CATCH_REQUIRE(p.error_messages() == "Unknown address in \"ipv6.example.com\" (no DNS lookup was allowed).\n");
    1218           1 :             CATCH_REQUIRE(ips.size() == 0);
    1219           1 :         }
    1220           3 :         CATCH_END_SECTION()
    1221             : 
    1222           3 :         CATCH_START_SECTION("ipv6::address: invalid IPv6 domain name address when we only accept numeric IPs")
    1223             :         {
    1224             :             // this is exactly the same path as the IPv4 test...
    1225             :             // if we have a named domain then IPv4 fails, IPv6 fails, then we err on it
    1226             :             //
    1227           1 :             addr::addr_parser p;
    1228           1 :             p.set_protocol(IPPROTO_TCP);
    1229           1 :             p.set_allow(addr::allow_t::ALLOW_ADDRESS_LOOKUP, false);
    1230           1 :             p.set_allow(addr::allow_t::ALLOW_PORT, false);
    1231           1 :             p.set_default_port(4471);
    1232           3 :             addr::addr_range::vector_t const ips(p.parse("[f801::31]"));
    1233           1 :             CATCH_REQUIRE(p.has_errors());
    1234           1 :             CATCH_REQUIRE(p.error_count() == 1);
    1235           1 :             CATCH_REQUIRE(p.error_messages() == "Found a port (\"4471\") when it is not allowed.\n");
    1236           1 :             CATCH_REQUIRE(ips.size() == 0);
    1237           1 :         }
    1238           3 :         CATCH_END_SECTION()
    1239          26 :     }
    1240             : 
    1241          26 :     CATCH_GIVEN("ipv6::address: a set of IPs and a sort")
    1242             :     {
    1243          18 :         std::string const ip_list("7::-3::,10.0.0.32,192.168.2.15-192.168.2.23,::,5.8.9.11,f801::5553,192.168.2.1-192.168.2.14,::3000-::2000");
    1244           9 :         addr::addr_parser p;
    1245           9 :         p.set_protocol(IPPROTO_TCP);
    1246           9 :         p.set_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS, true);
    1247           9 :         p.set_allow(addr::allow_t::ALLOW_ADDRESS_RANGE, true);
    1248           9 :         CATCH_REQUIRE(p.get_sort_order() == addr::SORT_NO);
    1249             : 
    1250           9 :         CATCH_START_SECTION("ipv6::address: parse and no sort")
    1251             :         {
    1252           1 :             addr::addr_range::vector_t const ips(p.parse(ip_list));
    1253             : 
    1254           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1255           1 :             CATCH_REQUIRE(ips.size() == 8);
    1256           1 :             CATCH_REQUIRE(ips[0].to_string(addr::STRING_IP_ADDRESS) == "<empty address range>");
    1257           1 :             CATCH_REQUIRE(ips[1].to_string(addr::STRING_IP_ADDRESS) == "10.0.0.32");
    1258           1 :             CATCH_REQUIRE(ips[2].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.15-192.168.2.23");
    1259           1 :             CATCH_REQUIRE(ips[3].to_string(addr::STRING_IP_ADDRESS) == "::");
    1260           1 :             CATCH_REQUIRE(ips[4].to_string(addr::STRING_IP_ADDRESS) == "5.8.9.11");
    1261           1 :             CATCH_REQUIRE(ips[5].to_string(addr::STRING_IP_ADDRESS) == "f801::5553");
    1262           1 :             CATCH_REQUIRE(ips[6].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.1-192.168.2.14");
    1263           1 :             CATCH_REQUIRE(ips[7].to_string(addr::STRING_IP_ADDRESS) == "<empty address range>");
    1264           1 :         }
    1265           9 :         CATCH_END_SECTION()
    1266             : 
    1267           9 :         CATCH_START_SECTION("ipv6::address: parse and ignore empty")
    1268             :         {
    1269           1 :             addr::sort_t const order(addr::SORT_NO_EMPTY);
    1270           1 :             p.set_sort_order(order);
    1271           1 :             CATCH_REQUIRE(p.get_sort_order() == order);
    1272           1 :             addr::addr_range::vector_t const ips(p.parse(ip_list));
    1273             : 
    1274           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1275           1 :             CATCH_REQUIRE(ips.size() == 6);
    1276           1 :             CATCH_REQUIRE(ips[0].to_string(addr::STRING_IP_ADDRESS) == "10.0.0.32");
    1277           1 :             CATCH_REQUIRE(ips[1].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.15-192.168.2.23");
    1278           1 :             CATCH_REQUIRE(ips[2].to_string(addr::STRING_IP_ADDRESS) == "::");
    1279           1 :             CATCH_REQUIRE(ips[3].to_string(addr::STRING_IP_ADDRESS) == "5.8.9.11");
    1280           1 :             CATCH_REQUIRE(ips[4].to_string(addr::STRING_IP_ADDRESS) == "f801::5553");
    1281           1 :             CATCH_REQUIRE(ips[5].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.1-192.168.2.14");
    1282           1 :         }
    1283           9 :         CATCH_END_SECTION()
    1284             : 
    1285           9 :         CATCH_START_SECTION("ipv6::address: parse and full sort")
    1286             :         {
    1287           1 :             addr::sort_t const order(addr::SORT_FULL);
    1288           1 :             p.set_sort_order(order);
    1289           1 :             CATCH_REQUIRE(p.get_sort_order() == order);
    1290           1 :             addr::addr_range::vector_t const ips(p.parse(ip_list));
    1291             : 
    1292           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1293           1 :             CATCH_REQUIRE(ips.size() == 8);
    1294           1 :             CATCH_REQUIRE(ips[0].to_string(addr::STRING_IP_ADDRESS) == "::");
    1295           1 :             CATCH_REQUIRE(ips[1].to_string(addr::STRING_IP_ADDRESS) == "5.8.9.11");
    1296           1 :             CATCH_REQUIRE(ips[2].to_string(addr::STRING_IP_ADDRESS) == "10.0.0.32");
    1297           1 :             CATCH_REQUIRE(ips[3].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.1-192.168.2.14");
    1298           1 :             CATCH_REQUIRE(ips[4].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.15-192.168.2.23");
    1299           1 :             CATCH_REQUIRE(ips[5].to_string(addr::STRING_IP_ADDRESS) == "f801::5553");
    1300           1 :             CATCH_REQUIRE(ips[6].to_string(addr::STRING_IP_ADDRESS) == "<empty address range>");
    1301           1 :             CATCH_REQUIRE(ips[7].to_string(addr::STRING_IP_ADDRESS) == "<empty address range>");
    1302           1 :         }
    1303           9 :         CATCH_END_SECTION()
    1304             : 
    1305           9 :         CATCH_START_SECTION("ipv6::address: parse and put IPv6 addresses first")
    1306             :         {
    1307           1 :             addr::sort_t const order(addr::SORT_IPV6_FIRST);
    1308           1 :             p.set_sort_order(order);
    1309           1 :             CATCH_REQUIRE(p.get_sort_order() == order);
    1310           1 :             addr::addr_range::vector_t const ips(p.parse(ip_list));
    1311             : 
    1312           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1313           1 :             CATCH_REQUIRE(ips.size() == 8);
    1314           1 :             CATCH_REQUIRE(ips[0].to_string(addr::STRING_IP_ADDRESS) == "::");
    1315           1 :             CATCH_REQUIRE(ips[1].to_string(addr::STRING_IP_ADDRESS) == "f801::5553");
    1316           1 :             CATCH_REQUIRE(ips[2].to_string(addr::STRING_IP_ADDRESS) == "10.0.0.32");
    1317           1 :             CATCH_REQUIRE(ips[3].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.15-192.168.2.23");
    1318           1 :             CATCH_REQUIRE(ips[4].to_string(addr::STRING_IP_ADDRESS) == "5.8.9.11");
    1319           1 :             CATCH_REQUIRE(ips[5].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.1-192.168.2.14");
    1320           1 :             CATCH_REQUIRE(ips[6].to_string(addr::STRING_IP_ADDRESS) == "<empty address range>");
    1321           1 :             CATCH_REQUIRE(ips[7].to_string(addr::STRING_IP_ADDRESS) == "<empty address range>");
    1322           1 :         }
    1323           9 :         CATCH_END_SECTION()
    1324             : 
    1325           9 :         CATCH_START_SECTION("ipv6::address: parse and put IPv4 addresses first")
    1326             :         {
    1327           1 :             addr::sort_t const order(addr::SORT_IPV4_FIRST);
    1328           1 :             p.set_sort_order(order);
    1329           1 :             CATCH_REQUIRE(p.get_sort_order() == order);
    1330           1 :             addr::addr_range::vector_t const ips(p.parse(ip_list));
    1331             : 
    1332           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1333           1 :             CATCH_REQUIRE(ips.size() == 8);
    1334           1 :             CATCH_REQUIRE(ips[0].to_string(addr::STRING_IP_ADDRESS) == "10.0.0.32");
    1335           1 :             CATCH_REQUIRE(ips[1].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.15-192.168.2.23");
    1336           1 :             CATCH_REQUIRE(ips[2].to_string(addr::STRING_IP_ADDRESS) == "5.8.9.11");
    1337           1 :             CATCH_REQUIRE(ips[3].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.1-192.168.2.14");
    1338           1 :             CATCH_REQUIRE(ips[4].to_string(addr::STRING_IP_ADDRESS) == "::");
    1339           1 :             CATCH_REQUIRE(ips[5].to_string(addr::STRING_IP_ADDRESS) == "f801::5553");
    1340           1 :             CATCH_REQUIRE(ips[6].to_string(addr::STRING_IP_ADDRESS) == "<empty address range>");
    1341           1 :             CATCH_REQUIRE(ips[7].to_string(addr::STRING_IP_ADDRESS) == "<empty address range>");
    1342           1 :         }
    1343           9 :         CATCH_END_SECTION()
    1344             : 
    1345           9 :         CATCH_START_SECTION("ipv6::address: parse, sort, and merge")
    1346             :         {
    1347           1 :             addr::sort_t const order(addr::SORT_MERGE);
    1348           1 :             p.set_sort_order(order);
    1349           1 :             CATCH_REQUIRE(p.get_sort_order() == order);
    1350           1 :             addr::addr_range::vector_t const ips(p.parse(ip_list));
    1351             : 
    1352           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1353           1 :             CATCH_REQUIRE(ips.size() == 7);
    1354           1 :             CATCH_REQUIRE(ips[0].to_string(addr::STRING_IP_ADDRESS) == "::");
    1355           1 :             CATCH_REQUIRE(ips[1].to_string(addr::STRING_IP_ADDRESS) == "5.8.9.11");
    1356           1 :             CATCH_REQUIRE(ips[2].to_string(addr::STRING_IP_ADDRESS) == "10.0.0.32");
    1357           1 :             CATCH_REQUIRE(ips[3].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.1-192.168.2.23");
    1358           1 :             CATCH_REQUIRE(ips[4].to_string(addr::STRING_IP_ADDRESS) == "f801::5553");
    1359           1 :             CATCH_REQUIRE(ips[5].to_string(addr::STRING_IP_ADDRESS) == "<empty address range>");
    1360           1 :             CATCH_REQUIRE(ips[6].to_string(addr::STRING_IP_ADDRESS) == "<empty address range>");
    1361           1 :         }
    1362           9 :         CATCH_END_SECTION()
    1363             : 
    1364           9 :         CATCH_START_SECTION("ipv6::address: parse, sort, merge, and put IPv4 first")
    1365             :         {
    1366           1 :             addr::sort_t const order(addr::SORT_MERGE | addr::SORT_IPV4_FIRST);
    1367           1 :             p.set_sort_order(order);
    1368           1 :             CATCH_REQUIRE(p.get_sort_order() == order);
    1369           1 :             addr::addr_range::vector_t const ips(p.parse(ip_list));
    1370             : 
    1371           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1372           1 :             CATCH_REQUIRE(ips.size() == 7);
    1373           1 :             CATCH_REQUIRE(ips[0].to_string(addr::STRING_IP_ADDRESS) == "5.8.9.11");
    1374           1 :             CATCH_REQUIRE(ips[1].to_string(addr::STRING_IP_ADDRESS) == "10.0.0.32");
    1375           1 :             CATCH_REQUIRE(ips[2].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.1-192.168.2.23");
    1376           1 :             CATCH_REQUIRE(ips[3].to_string(addr::STRING_IP_ADDRESS) == "::");
    1377           1 :             CATCH_REQUIRE(ips[4].to_string(addr::STRING_IP_ADDRESS) == "f801::5553");
    1378           1 :             CATCH_REQUIRE(ips[5].to_string(addr::STRING_IP_ADDRESS) == "<empty address range>");
    1379           1 :             CATCH_REQUIRE(ips[6].to_string(addr::STRING_IP_ADDRESS) == "<empty address range>");
    1380           1 :         }
    1381           9 :         CATCH_END_SECTION()
    1382             : 
    1383           9 :         CATCH_START_SECTION("ipv6::address: parse, sort, merge, and put IPv6 first")
    1384             :         {
    1385           1 :             addr::sort_t const order(addr::SORT_MERGE | addr::SORT_IPV6_FIRST);
    1386           1 :             p.set_sort_order(order);
    1387           1 :             CATCH_REQUIRE(p.get_sort_order() == order);
    1388           1 :             addr::addr_range::vector_t const ips(p.parse(ip_list));
    1389             : 
    1390           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1391           1 :             CATCH_REQUIRE(ips.size() == 7);
    1392           1 :             CATCH_REQUIRE(ips[0].to_string(addr::STRING_IP_ADDRESS) == "::");
    1393           1 :             CATCH_REQUIRE(ips[1].to_string(addr::STRING_IP_ADDRESS) == "f801::5553");
    1394           1 :             CATCH_REQUIRE(ips[2].to_string(addr::STRING_IP_ADDRESS) == "5.8.9.11");
    1395           1 :             CATCH_REQUIRE(ips[3].to_string(addr::STRING_IP_ADDRESS) == "10.0.0.32");
    1396           1 :             CATCH_REQUIRE(ips[4].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.1-192.168.2.23");
    1397           1 :             CATCH_REQUIRE(ips[5].to_string(addr::STRING_IP_ADDRESS) == "<empty address range>");
    1398           1 :             CATCH_REQUIRE(ips[6].to_string(addr::STRING_IP_ADDRESS) == "<empty address range>");
    1399           1 :         }
    1400           9 :         CATCH_END_SECTION()
    1401             : 
    1402           9 :         CATCH_START_SECTION("ipv6::address: parse, sort, merge, and put IPv6 first")
    1403             :         {
    1404             :             // this is the one we expect most users to make use of to
    1405             :             //   1. ignore empty entries (useless)
    1406             :             //   2. merge when possible to reduce the number of items
    1407             :             //   3. handle IPv6 first, then try IPv4 is any available
    1408             :             //
    1409           1 :             addr::sort_t const order(addr::SORT_NO_EMPTY | addr::SORT_MERGE | addr::SORT_IPV6_FIRST);
    1410           1 :             p.set_sort_order(order);
    1411           1 :             CATCH_REQUIRE(p.get_sort_order() == order);
    1412           1 :             addr::addr_range::vector_t const ips(p.parse(ip_list));
    1413             : 
    1414           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1415           1 :             CATCH_REQUIRE(ips.size() == 5);
    1416           1 :             CATCH_REQUIRE(ips[0].to_string(addr::STRING_IP_ADDRESS) == "::");
    1417           1 :             CATCH_REQUIRE(ips[1].to_string(addr::STRING_IP_ADDRESS) == "f801::5553");
    1418           1 :             CATCH_REQUIRE(ips[2].to_string(addr::STRING_IP_ADDRESS) == "5.8.9.11");
    1419           1 :             CATCH_REQUIRE(ips[3].to_string(addr::STRING_IP_ADDRESS) == "10.0.0.32");
    1420           1 :             CATCH_REQUIRE(ips[4].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.1-192.168.2.23");
    1421           1 :         }
    1422           9 :         CATCH_END_SECTION()
    1423          35 :     }
    1424             : 
    1425          26 :     CATCH_START_SECTION("ipv6::address: one side ranges")
    1426             :     {
    1427           1 :         addr::addr_parser p;
    1428           1 :         p.set_protocol(IPPROTO_TCP);
    1429           1 :         p.set_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS, true);
    1430           1 :         p.set_allow(addr::allow_t::ALLOW_ADDRESS_RANGE, true);
    1431             : 
    1432           2 :         std::string const ip_list("-::1,-10.0.0.32,f801::5553-,192.168.2.1-");
    1433           1 :         addr::addr_range::vector_t const ips(p.parse(ip_list));
    1434             : 
    1435           1 :         CATCH_REQUIRE_FALSE(p.has_errors());
    1436           1 :         CATCH_REQUIRE(ips.size() == 4);
    1437           1 :         CATCH_REQUIRE(ips[0].to_string(addr::STRING_IP_ADDRESS) == "-::1");
    1438           1 :         CATCH_REQUIRE(ips[1].to_string(addr::STRING_IP_ADDRESS) == "-10.0.0.32");
    1439           1 :         CATCH_REQUIRE(ips[2].to_string(addr::STRING_IP_ADDRESS) == "f801::5553");
    1440           1 :         CATCH_REQUIRE(ips[3].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.1");
    1441           1 :     }
    1442          26 :     CATCH_END_SECTION()
    1443             : 
    1444          26 :     CATCH_START_SECTION("ipv6::address: test invalid sort (IPv4 vs IPv6)")
    1445             :     {
    1446           1 :         addr::addr_parser p;
    1447             : 
    1448             :         // set something valid
    1449             :         //
    1450           1 :         addr::sort_t const order(addr::SORT_NO_EMPTY);
    1451           1 :         p.set_sort_order(order);
    1452           1 :         CATCH_REQUIRE(p.get_sort_order() == order);
    1453             : 
    1454             :         // try to set something invalid
    1455             :         //
    1456           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    1457             :                   p.set_sort_order(addr::SORT_IPV6_FIRST | addr::SORT_IPV4_FIRST)
    1458             :                 , addr::addr_invalid_argument
    1459             :                 , Catch::Matchers::ExceptionMessage(
    1460             :                           "addr_error: addr_parser::set_sort_order(): flags SORT_IPV6_FIRST and SORT_IPV4_FIRST are mutually exclusive."));
    1461             : 
    1462             :         // verify that the invalid attempt did not change anything
    1463             :         //
    1464           1 :         CATCH_REQUIRE(p.get_sort_order() == order);
    1465           1 :     }
    1466          26 :     CATCH_END_SECTION()
    1467             : 
    1468          26 :     CATCH_START_SECTION("ipv6::address: parse & sort multi-address separated by '\\n' with '#' comments")
    1469             :     {
    1470           1 :         addr::addr_parser p;
    1471           1 :         p.set_protocol(IPPROTO_TCP);
    1472           1 :         p.set_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_NEWLINES, true);
    1473           1 :         p.set_allow(addr::allow_t::ALLOW_ADDRESS_RANGE, true);
    1474           1 :         p.set_allow(addr::allow_t::ALLOW_COMMENT_HASH, true);
    1475             : 
    1476           1 :         CATCH_REQUIRE(p.get_sort_order() == addr::SORT_NO); // verify default
    1477           1 :         addr::sort_t const order(addr::SORT_NO_EMPTY | addr::SORT_MERGE | addr::SORT_IPV6_FIRST);
    1478           1 :         p.set_sort_order(order);
    1479           1 :         CATCH_REQUIRE(p.get_sort_order() == order);
    1480             : 
    1481           1 :         std::string const ip_list(
    1482             :                 "9::-a::\n"
    1483             :                 "10.1.0.32\n"
    1484             :                 "192.168.2.23-192.168.2.18\n"
    1485             :                 "#0:0:300f:f00f:3355::3\n"  // commented
    1486             :                 "::1\n"
    1487             :                 "25.8.9.11\n\n"             // extra empty line
    1488             :                 "f801::3332\n"
    1489             :                 "192.168.2.1-192.168.2.14\n"
    1490             :                 "-:45\n"                    // for a range, at least one IP is required
    1491             :                 "a::1-b::3\n\n"             // extra empty line at the end too
    1492           2 :                 "# an actual comment\n");
    1493           1 :         addr::addr_range::vector_t const ips(p.parse(ip_list));
    1494             : 
    1495             :         // note that even though we had errors, the valid IP entries
    1496             :         // appear in the ips vector and we can test them
    1497             :         //
    1498           1 :         CATCH_REQUIRE(p.has_errors());
    1499           1 :         CATCH_REQUIRE(p.error_messages() == "An address range requires at least one of the \"from\" or \"to\" addresses.\n");
    1500             : 
    1501           1 :         CATCH_REQUIRE(ips.size() == 6);
    1502           1 :         CATCH_REQUIRE(ips[0].to_string(addr::STRING_IP_ADDRESS) == "::1");
    1503           1 :         CATCH_REQUIRE(ips[1].to_string(addr::STRING_IP_ADDRESS) == "9::-b::3");
    1504           1 :         CATCH_REQUIRE(ips[2].to_string(addr::STRING_IP_ADDRESS) == "f801::3332");
    1505           1 :         CATCH_REQUIRE(ips[3].to_string(addr::STRING_IP_ADDRESS) == "10.1.0.32");
    1506           1 :         CATCH_REQUIRE(ips[4].to_string(addr::STRING_IP_ADDRESS) == "25.8.9.11");
    1507           1 :         CATCH_REQUIRE(ips[5].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.1-192.168.2.14");
    1508           1 :     }
    1509          26 :     CATCH_END_SECTION()
    1510             : 
    1511          26 :     CATCH_START_SECTION("ipv6::address: parse & sort multi-address separated by '\\n' with ';' comments")
    1512             :     {
    1513           1 :         addr::addr_parser p;
    1514           1 :         p.set_protocol(IPPROTO_TCP);
    1515           1 :         p.set_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_NEWLINES, true);
    1516           1 :         p.set_allow(addr::allow_t::ALLOW_ADDRESS_RANGE, true);
    1517           1 :         p.set_allow(addr::allow_t::ALLOW_COMMENT_SEMICOLON, true);
    1518             : 
    1519           1 :         CATCH_REQUIRE(p.get_sort_order() == addr::SORT_NO); // verify default
    1520           1 :         addr::sort_t const order(addr::SORT_NO_EMPTY | addr::SORT_MERGE | addr::SORT_IPV6_FIRST);
    1521           1 :         p.set_sort_order(order);
    1522           1 :         CATCH_REQUIRE(p.get_sort_order() == order);
    1523             : 
    1524           1 :         std::string const ip_list(
    1525             :                 "; list of IPs\n"
    1526             :                 "9::-a::\n"
    1527             :                 "10.1.0.32\n"
    1528             :                 "192.168.2.23-192.168.2.18\n"
    1529             :                 ";0:0:300f:f00f:3355::3\n"  // commented
    1530             :                 "::1\n"
    1531             :                 "25.8.9.11\n\n"             // extra empty line
    1532             :                 "f801::3332\n"
    1533             :                 "192.168.2.1-192.168.2.14\n"
    1534             :                 "-:45\n"                    // for a range, at least one IP is required
    1535           2 :                 "a::1-b::3\n\n");           // extra empty line at the end too
    1536           1 :         addr::addr_range::vector_t const ips(p.parse(ip_list));
    1537             : 
    1538             :         // note that even though we had errors, the valid IP entries
    1539             :         // appear in the ips vector and we can test them
    1540             :         //
    1541           1 :         CATCH_REQUIRE(p.has_errors());
    1542           1 :         CATCH_REQUIRE(p.error_messages() == "An address range requires at least one of the \"from\" or \"to\" addresses.\n");
    1543             : 
    1544           1 :         CATCH_REQUIRE(ips.size() == 6);
    1545           1 :         CATCH_REQUIRE(ips[0].to_string(addr::STRING_IP_ADDRESS) == "::1");
    1546           1 :         CATCH_REQUIRE(ips[1].to_string(addr::STRING_IP_ADDRESS) == "9::-b::3");
    1547           1 :         CATCH_REQUIRE(ips[2].to_string(addr::STRING_IP_ADDRESS) == "f801::3332");
    1548           1 :         CATCH_REQUIRE(ips[3].to_string(addr::STRING_IP_ADDRESS) == "10.1.0.32");
    1549           1 :         CATCH_REQUIRE(ips[4].to_string(addr::STRING_IP_ADDRESS) == "25.8.9.11");
    1550           1 :         CATCH_REQUIRE(ips[5].to_string(addr::STRING_IP_ADDRESS) == "192.168.2.1-192.168.2.14");
    1551           1 :     }
    1552          26 :     CATCH_END_SECTION()
    1553             : 
    1554          26 :     CATCH_START_SECTION("ipv6::address: parse invalid range (IP which becomes multiple entries)")
    1555             :     {
    1556           1 :         addr::addr_parser p;
    1557           1 :         p.set_protocol(IPPROTO_TCP);
    1558           1 :         p.set_allow(addr::allow_t::ALLOW_ADDRESS_RANGE, true);
    1559           3 :         addr::addr_range::vector_t const ips1(p.parse("localhost-:45"));
    1560             : 
    1561           1 :         CATCH_REQUIRE(p.has_errors());
    1562           1 :         CATCH_REQUIRE(p.error_messages() == "The \"from\" of an address range must be exactly one address.\n");
    1563             : 
    1564           1 :         CATCH_REQUIRE(ips1.empty());
    1565             : 
    1566           1 :         p.clear_errors();
    1567           3 :         addr::addr_range::vector_t const ips2(p.parse("-localhost:45"));
    1568             : 
    1569           1 :         CATCH_REQUIRE(p.has_errors());
    1570           1 :         CATCH_REQUIRE(p.error_messages() == "The \"to\" of an address range must be exactly one address.\n");
    1571             : 
    1572           1 :         CATCH_REQUIRE(ips2.empty());
    1573             : 
    1574           1 :         p.clear_errors();
    1575           3 :         addr::addr_range::vector_t const ips3(p.parse("invalid.from-:45"));
    1576             : 
    1577           1 :         CATCH_REQUIRE(p.has_errors());
    1578           1 :         CATCH_REQUIRE(p.error_messages() == "Invalid address in \"invalid.from:45\" error -2 -- Name or service not known (errno: 22 -- Invalid argument).\n");
    1579             : 
    1580           1 :         CATCH_REQUIRE(ips3.empty());
    1581             : 
    1582             :         // .to is a valid TLD (Tonga) so here I use .tom instead
    1583             :         //
    1584           1 :         p.clear_errors();
    1585           3 :         addr::addr_range::vector_t const ips4(p.parse("-invalid.tom:45"));
    1586             : 
    1587           1 :         CATCH_REQUIRE(p.has_errors());
    1588           1 :         CATCH_REQUIRE(p.error_messages() == "Invalid address in \"invalid.tom:45\" error -2 -- Name or service not known (errno: 22 -- Invalid argument).\n");
    1589             : 
    1590           1 :         CATCH_REQUIRE(ips4.empty());
    1591           1 :     }
    1592          26 :     CATCH_END_SECTION()
    1593          26 : }
    1594             : 
    1595             : 
    1596           7 : CATCH_TEST_CASE("ipv6::ports", "[ipv6]")
    1597             : {
    1598             :     // by default addr() is an IPv6 address so we test the basic port
    1599             :     // functions here, although it could be in a common place instead...
    1600             :     //
    1601           7 :     CATCH_GIVEN("addr()")
    1602             :     {
    1603           3 :         addr::addr a;
    1604             : 
    1605           3 :         CATCH_START_SECTION("ipv6::ports: default port")
    1606             :         {
    1607           1 :             CATCH_REQUIRE(a.get_port() == 0);
    1608             :         }
    1609           3 :         CATCH_END_SECTION()
    1610             : 
    1611           3 :         CATCH_START_SECTION("ipv6::ports: set_port()")
    1612             :         {
    1613             :             // setup a random port to start with
    1614             :             //
    1615           1 :             int const start_port(rand() & 0xFFFF);
    1616           1 :             a.set_port(start_port);
    1617             : 
    1618             :             // test 100 invalid ports
    1619             :             //
    1620         101 :             for(int idx(0); idx < 100; ++idx)
    1621             :             {
    1622             :                 // first try a negative port
    1623             :                 int port_too_small;
    1624             :                 do
    1625             :                 {
    1626         100 :                     port_too_small = -(rand() & 0xFFFF);
    1627             :                 }
    1628         100 :                 while(port_too_small == 0);
    1629         100 :                 CATCH_REQUIRE_THROWS_AS(a.set_port(port_too_small), addr::addr_invalid_argument);
    1630             : 
    1631             :                 // first try a negative port
    1632         100 :                 int const port_too_large = (rand() & 0xFFFF) + 65536;
    1633         100 :                 CATCH_REQUIRE_THROWS_AS(a.set_port(port_too_large), addr::addr_invalid_argument);
    1634             : 
    1635             :                 // make sure port does not get modified on errors
    1636         100 :                 CATCH_REQUIRE(a.get_port() == start_port);
    1637             :             }
    1638             : 
    1639             :             // test all ports
    1640             :             //
    1641       65537 :             for(int port(0); port < 65536; ++port)
    1642             :             {
    1643       65536 :                 a.set_port(port);
    1644             : 
    1645       65536 :                 CATCH_REQUIRE(a.get_port() == port);
    1646             :             }
    1647             :         }
    1648           3 :         CATCH_END_SECTION()
    1649             : 
    1650           3 :         CATCH_START_SECTION("ipv6::ports: known ports to test get_service()")
    1651             :         {
    1652           1 :             a.set_port(80);
    1653           1 :             CATCH_REQUIRE(a.get_service() == "http");
    1654             : 
    1655           1 :             a.set_port(443);
    1656           1 :             CATCH_REQUIRE(a.get_service() == "https");
    1657             : 
    1658             :             // again with UDP
    1659             :             // 
    1660           1 :             a.set_protocol(IPPROTO_UDP);
    1661             : 
    1662           1 :             a.set_port(80);
    1663           1 :             std::string service(a.get_service());
    1664           1 :             CATCH_REQUIRE((service == "http" || service == "80"));
    1665             : 
    1666           1 :             a.set_port(443);
    1667           1 :             service = a.get_service();
    1668           1 :             CATCH_REQUIRE((service == "https"|| service == "443"));
    1669           1 :         }
    1670           3 :         CATCH_END_SECTION()
    1671          10 :     }
    1672             : 
    1673           7 :     CATCH_GIVEN("addr_parser() with IPv6 addresses and port")
    1674             :     {
    1675           4 :         CATCH_START_SECTION("ipv6::ports: verify port by parser")
    1676             :         {
    1677       65537 :             for(int port(0); port < 65536; ++port)
    1678             :             {
    1679       65536 :                 int proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1680       65536 :                 addr::addr_parser p;
    1681       65536 :                 p.set_protocol(proto);
    1682      196608 :                 addr::addr_range::vector_t ips(p.parse("[ff01:2f3:f041:e301:f:10:11:12]:" + std::to_string(port)));
    1683       65536 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1684       65536 :                 CATCH_REQUIRE(ips.size() == 1);
    1685       65536 :                 addr::addr_range const & r(ips[0]);
    1686       65536 :                 addr::addr f(r.get_from());
    1687       65536 :                 CATCH_REQUIRE_FALSE(f.is_ipv4());
    1688       65536 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    1689       65536 :                 CATCH_REQUIRE(f.get_family() == AF_INET6);
    1690       65536 :                 CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_ADDRESS) == "ff01:2f3:f041:e301:f:10:11:12");
    1691       65536 :                 CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS) == "[ff01:2f3:f041:e301:f:10:11:12]");
    1692       65536 :                 CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT) == "[ff01:2f3:f041:e301:f:10:11:12]:" + std::to_string(port));
    1693       65536 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT) == "[ff01:2f3:f041:e301:f:10:11:12]:" + std::to_string(port));
    1694       65536 :                 CATCH_REQUIRE(f.get_port() == port);
    1695       65536 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    1696       65536 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_LOOPBACK);
    1697       65536 :                 CATCH_REQUIRE(f.is_lan());
    1698       65536 :                 CATCH_REQUIRE(f.is_lan(true));
    1699       65536 :                 CATCH_REQUIRE(f.is_lan(false));
    1700       65536 :                 CATCH_REQUIRE_FALSE(f.is_wan());
    1701       65536 :                 CATCH_REQUIRE_FALSE(f.is_wan(true));
    1702       65536 :                 CATCH_REQUIRE_FALSE(f.is_wan(false));
    1703       65536 :             }
    1704             :         }
    1705           4 :         CATCH_END_SECTION()
    1706             : 
    1707           4 :         CATCH_START_SECTION("ipv6::port: default address with various port")
    1708             :         {
    1709         101 :             for(int idx(0); idx < 100; ++idx)
    1710             :             {
    1711         100 :                 uint16_t const port(rand());
    1712         100 :                 addr::addr_parser p;
    1713         100 :                 p.set_protocol(IPPROTO_TCP);
    1714         100 :                 p.set_default_address("ff02:23:f41:e31:20:30:40:50");
    1715         300 :                 addr::addr_range::vector_t ips(p.parse(":" + std::to_string(static_cast<int>(port))));
    1716         100 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1717         100 :                 CATCH_REQUIRE(ips.size() == 1);
    1718         100 :                 addr::addr_range const & r(ips[0]);
    1719         100 :                 CATCH_REQUIRE(r.has_from());
    1720         100 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1721         100 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1722         100 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1723         100 :                 addr::addr f(r.get_from());
    1724         100 :                 CATCH_REQUIRE_FALSE(f.is_ipv4());
    1725         100 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    1726         100 :                 CATCH_REQUIRE(f.get_family() == AF_INET6);
    1727         100 :                 CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT) == "[ff02:23:f41:e31:20:30:40:50]:" + std::to_string(static_cast<int>(port)));
    1728         100 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT) == "[ff02:23:f41:e31:20:30:40:50]:" + std::to_string(static_cast<int>(port)));
    1729         100 :                 CATCH_REQUIRE(f.get_port() == port);
    1730         100 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1731         100 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_LINK_LOCAL);
    1732         100 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1733         100 :                 CATCH_REQUIRE(f.is_lan(true));
    1734         100 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1735         100 :                 CATCH_REQUIRE_FALSE(f.is_wan());
    1736         100 :                 CATCH_REQUIRE_FALSE(f.is_wan(true));
    1737         100 :                 CATCH_REQUIRE_FALSE(f.is_wan(false));
    1738         100 :             }
    1739             :         }
    1740           4 :         CATCH_END_SECTION()
    1741             : 
    1742           4 :         CATCH_START_SECTION("ipv6::port: port when not allowed check as IPv6")
    1743             :         {
    1744           1 :             addr::addr_parser p;
    1745           1 :             p.set_allow(addr::allow_t::ALLOW_PORT, false);
    1746           3 :             addr::addr_range::vector_t ips(p.parse("localhost:33.5"));
    1747           1 :             CATCH_REQUIRE(p.has_errors());
    1748           1 :             CATCH_REQUIRE(p.error_count() == 1);
    1749           1 :             CATCH_REQUIRE(p.error_messages() == "Invalid address in \"localhost:33.5\" error -2 -- Name or service not known\n");
    1750           1 :             CATCH_REQUIRE(p.has_errors());
    1751           1 :             p.clear_errors();
    1752           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1753           1 :             CATCH_REQUIRE(ips.size() == 0);
    1754           1 :         }
    1755           4 :         CATCH_END_SECTION()
    1756             : 
    1757           4 :         CATCH_START_SECTION("ipv6::port: space before port")
    1758             :         {
    1759           1 :             addr::addr_parser p;
    1760           3 :             addr::addr_range::vector_t ips(p.parse("[fafa:fefe:ffaa:ffee::3] :456"));
    1761           1 :             CATCH_REQUIRE(p.has_errors());
    1762           1 :             CATCH_REQUIRE(p.error_count() == 1);
    1763           1 :             CATCH_REQUIRE(p.error_messages() == "The IPv6 address \"[fafa:fefe:ffaa:ffee::3] :456\" is followed by unknown data.\n");
    1764           1 :             CATCH_REQUIRE(p.has_errors());
    1765           1 :             p.clear_errors();
    1766           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1767           1 :             CATCH_REQUIRE(ips.size() == 0);
    1768           1 :         }
    1769           4 :         CATCH_END_SECTION()
    1770           7 :     }
    1771           7 : }
    1772             : 
    1773             : 
    1774          14 : CATCH_TEST_CASE( "ipv6::masks", "[ipv6]" )
    1775             : {
    1776          14 :     CATCH_GIVEN("addr()")
    1777             :     {
    1778             :         // technically, a default addr object represents and IPv6 so the
    1779             :         // dealing with the mask without an IPv4 is done by IPv6 tests
    1780             :         //
    1781           4 :         addr::addr a;
    1782             : 
    1783           4 :         CATCH_START_SECTION("ipv6::masks: default mask")
    1784             :         {
    1785           1 :             uint8_t mask[16] = {};
    1786           1 :             a.get_mask(mask);
    1787          17 :             for(int idx(0); idx < 16; ++idx)
    1788             :             {
    1789          16 :                 CATCH_REQUIRE(mask[idx] == 255);
    1790             :             }
    1791           1 :             CATCH_REQUIRE(a.get_mask_size() == 128);
    1792             :         }
    1793           4 :         CATCH_END_SECTION()
    1794             : 
    1795           4 :         CATCH_START_SECTION("ipv6::masks: set_mask_count()")
    1796             :         {
    1797         130 :             for(int idx(0); idx <= 128; ++idx)
    1798             :             {
    1799         129 :                 a.set_mask_count(idx);
    1800         129 :                 CATCH_REQUIRE(a.get_mask_size() == idx);
    1801             :             }
    1802             : 
    1803          11 :             for(int idx(-10); idx < 0; ++idx)
    1804             :             {
    1805          10 :                 CATCH_REQUIRE_THROWS_MATCHES(
    1806             :                           a.set_mask_count(idx)
    1807             :                         , addr::out_of_range
    1808             :                         , Catch::Matchers::ExceptionMessage(
    1809             :                                   "out_of_range: the mask size " + std::to_string(idx) + " is out of range."));
    1810             :             }
    1811             : 
    1812           3 :             for(int idx(129); idx <= 130; ++idx)
    1813             :             {
    1814           2 :                 CATCH_REQUIRE_THROWS_MATCHES(
    1815             :                           a.set_mask_count(idx)
    1816             :                         , addr::out_of_range
    1817             :                         , Catch::Matchers::ExceptionMessage(
    1818             :                                   "out_of_range: the mask size " + std::to_string(idx) + " is out of range."));
    1819             :             }
    1820             :         }
    1821           4 :         CATCH_END_SECTION()
    1822             : 
    1823           4 :         CATCH_START_SECTION("ipv6::masks: set_mask()")
    1824             :         {
    1825           1 :             uint8_t mask[16], verify_mask[16];
    1826           6 :             for(int idx(0); idx < 5; ++idx)
    1827             :             {
    1828          85 :                 for(int j(0); j < 16; ++j)
    1829             :                 {
    1830          80 :                     mask[j] = rand();
    1831             :                 }
    1832           5 :                 a.set_mask(mask);
    1833           5 :                 a.get_mask(verify_mask);
    1834          85 :                 for(int j(0); j < 16; ++j)
    1835             :                 {
    1836          80 :                     CATCH_REQUIRE(mask[j] == verify_mask[j]);
    1837             :                 }
    1838             : 
    1839             :                 // verify that a copy does copy the mask as expected
    1840             :                 //
    1841           5 :                 addr::addr b(a);
    1842           5 :                 b.get_mask(verify_mask);
    1843          85 :                 for(int j(0); j < 16; ++j)
    1844             :                 {
    1845          80 :                     CATCH_REQUIRE(mask[j] == verify_mask[j]);
    1846             :                 }
    1847             : 
    1848             :                 // since it's completely random, it should be -1 but it could
    1849             :                 // also be a number, in any event a and b have the same mask
    1850             :                 // so the function has to return the same value
    1851             :                 //
    1852           5 :                 CATCH_REQUIRE(a.get_mask_size() == b.get_mask_size());
    1853           5 :             }
    1854             :         }
    1855           4 :         CATCH_END_SECTION()
    1856             : 
    1857           4 :         CATCH_START_SECTION("ipv6::masks: set_mask()")
    1858             :         {
    1859           1 :             uint8_t mask[16];
    1860           1 :             uint8_t verify_mask[16];
    1861           6 :             for(int idx(0); idx < 5; ++idx)
    1862             :             {
    1863          85 :                 for(int j(0); j < 16; ++j)
    1864             :                 {
    1865          80 :                     mask[j] = rand();
    1866             :                 }
    1867           5 :                 a.set_mask(mask);
    1868           5 :                 a.get_mask(verify_mask);
    1869          85 :                 for(int j(0); j < 16; ++j)
    1870             :                 {
    1871          80 :                     CATCH_REQUIRE(mask[j] == verify_mask[j]);
    1872          80 :                     verify_mask[j] = rand();
    1873             :                 }
    1874             : 
    1875             :                 // verify that a copy does copy the mask as expected
    1876             :                 //
    1877           5 :                 addr::addr b(a);
    1878           5 :                 b.get_mask(verify_mask);
    1879          85 :                 for(int j(0); j < 16; ++j)
    1880             :                 {
    1881          80 :                     CATCH_REQUIRE(mask[j] == verify_mask[j]);
    1882          80 :                     verify_mask[j] = rand();
    1883             :                 }
    1884             : 
    1885             :                 // verify that copying inside a range works too
    1886             :                 //
    1887           5 :                 addr::addr_range r;
    1888           5 :                 r.set_from(a);
    1889           5 :                 r.get_from().get_mask(verify_mask);
    1890          85 :                 for(int j(0); j < 16; ++j)
    1891             :                 {
    1892          80 :                     CATCH_REQUIRE(mask[j] == verify_mask[j]);
    1893          80 :                     verify_mask[j] = rand();
    1894             :                 }
    1895             : 
    1896             :                 // then that a range copy works as expected
    1897             :                 //
    1898           5 :                 addr::addr_range c(r);
    1899           5 :                 c.get_from().get_mask(verify_mask);
    1900          85 :                 for(int j(0); j < 16; ++j)
    1901             :                 {
    1902          80 :                     CATCH_REQUIRE(mask[j] == verify_mask[j]);
    1903          80 :                     verify_mask[j] = rand();
    1904             :                 }
    1905           5 :             }
    1906             :         }
    1907           4 :         CATCH_END_SECTION()
    1908          18 :     }
    1909             : 
    1910          14 :     CATCH_GIVEN("addr_parser() of address:port/mask")
    1911             :     {
    1912          10 :         CATCH_START_SECTION("ipv6::masks: mask allowed, but no mask")
    1913             :         {
    1914           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1915           1 :             int const port(rand() & 0xFFFF);
    1916           1 :             addr::addr_parser p;
    1917           1 :             p.set_protocol(proto);
    1918           1 :             p.set_allow(addr::allow_t::ALLOW_MASK, true);
    1919           3 :             addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port)));
    1920           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1921           1 :             CATCH_REQUIRE(ips.size() == 1);
    1922           1 :             addr::addr_range const & r(ips[0]);
    1923           1 :             addr::addr f(r.get_from());
    1924           1 :             CATCH_REQUIRE_FALSE(f.is_ipv4());
    1925           1 :             CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    1926           1 :             CATCH_REQUIRE(f.get_family() == AF_INET6);
    1927           3 :             std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/128");
    1928           1 :             CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_ALL) == result);
    1929           1 :             CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ALL) == result);
    1930           1 :             CATCH_REQUIRE(f.get_port() == port);
    1931           1 :             CATCH_REQUIRE(f.get_protocol() == proto);
    1932           1 :             CATCH_REQUIRE(f.get_mask_size() == 128);
    1933           1 :         }
    1934          10 :         CATCH_END_SECTION()
    1935             : 
    1936          10 :         CATCH_START_SECTION("ipv6::masks: empty mask")
    1937             :         {
    1938           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1939           1 :             int const port(rand() & 0xFFFF);
    1940           1 :             addr::addr_parser p;
    1941           1 :             p.set_protocol(proto);
    1942           1 :             p.set_allow(addr::allow_t::ALLOW_MASK, true);
    1943           4 :             addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/"));
    1944           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1945           1 :             CATCH_REQUIRE(ips.size() == 1);
    1946           1 :             addr::addr_range const & r(ips[0]);
    1947           1 :             addr::addr f(r.get_from());
    1948           1 :             CATCH_REQUIRE_FALSE(f.is_ipv4());
    1949           1 :             CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    1950           1 :             CATCH_REQUIRE(f.get_family() == AF_INET6);
    1951           3 :             std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/128");
    1952           1 :             CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_ALL) == result);
    1953           1 :             CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ALL) == result);
    1954           1 :             CATCH_REQUIRE(f.get_port() == port);
    1955           1 :             CATCH_REQUIRE(f.get_protocol() == proto);
    1956           1 :             CATCH_REQUIRE(f.get_mask_size() == 128);
    1957           1 :         }
    1958          10 :         CATCH_END_SECTION()
    1959             : 
    1960          10 :         CATCH_START_SECTION("ipv6::masks: empty mask including the '[]'")
    1961             :         {
    1962           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1963           1 :             int const port(rand() & 0xFFFF);
    1964           1 :             addr::addr_parser p;
    1965           1 :             p.set_protocol(proto);
    1966           1 :             p.set_allow(addr::allow_t::ALLOW_MASK, true);
    1967           1 :             p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
    1968           4 :             addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[]"));
    1969           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1970           1 :             CATCH_REQUIRE(ips.size() == 1);
    1971           1 :             addr::addr_range const & r(ips[0]);
    1972           1 :             addr::addr f(r.get_from());
    1973           1 :             CATCH_REQUIRE_FALSE(f.is_ipv4());
    1974           1 :             CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    1975           1 :             CATCH_REQUIRE(f.get_family() == AF_INET6);
    1976           3 :             std::string const result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/128");
    1977           1 :             CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_ALL) == result);
    1978           1 :             CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ALL) == result);
    1979           1 :             CATCH_REQUIRE(f.get_port() == port);
    1980           1 :             CATCH_REQUIRE(f.get_protocol() == proto);
    1981           1 :             CATCH_REQUIRE(f.get_mask_size() == 128);
    1982           1 :         }
    1983          10 :         CATCH_END_SECTION()
    1984             : 
    1985          10 :         CATCH_START_SECTION("ipv6::masks: empty mask '[]' with address mask not allowed")
    1986             :         {
    1987           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1988           1 :             int const port(rand() & 0xFFFF);
    1989           1 :             addr::addr_parser p;
    1990           1 :             p.set_protocol(proto);
    1991           1 :             p.set_allow(addr::allow_t::ALLOW_MASK, true);
    1992           4 :             addr::addr_range::vector_t ips(p.parse("[66:33:cc:11:7:11:bb:dd]:" + std::to_string(port) + "/[]"));
    1993           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1994           1 :             CATCH_REQUIRE(ips.size() == 1);
    1995           3 :             std::string const result("[66:33:cc:11:7:11:bb:dd]:" + std::to_string(port) + "/128");
    1996           1 :             CATCH_REQUIRE(ips[0].get_from().to_ipv4or6_string(addr::STRING_IP_ALL) == result);
    1997           1 :         }
    1998          10 :         CATCH_END_SECTION()
    1999             : 
    2000          10 :         CATCH_START_SECTION("ipv6::masks: one number masks")
    2001             :         {
    2002         130 :             for(int idx(0); idx <= 128; ++idx)
    2003             :             {
    2004         129 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    2005         129 :                 int const port(rand() & 0xFFFF);
    2006         129 :                 addr::addr_parser p;
    2007         129 :                 p.set_protocol(proto);
    2008         129 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
    2009         774 :                 addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/" + std::to_string(idx)));
    2010         129 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    2011         129 :                 CATCH_REQUIRE(ips.size() == 1);
    2012         129 :                 addr::addr_range const & r(ips[0]);
    2013         129 :                 addr::addr f(r.get_from());
    2014         129 :                 CATCH_REQUIRE_FALSE(f.is_ipv4());
    2015         129 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    2016         129 :                 CATCH_REQUIRE(f.get_family() == AF_INET6);
    2017         129 :                 uint8_t mask[16] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };
    2018         129 :                 int j(15);
    2019         129 :                 int m(128 - idx);
    2020        1089 :                 for(; m > 8; m -= 8, --j)
    2021             :                 {
    2022         960 :                     mask[j] = 0;
    2023             :                 }
    2024         129 :                 if(j < 0)
    2025             :                 {
    2026           0 :                     throw std::logic_error("invalid j here");
    2027             :                 }
    2028         129 :                 mask[j] = 255 << m;
    2029         129 :                 char buf[1024]; // really large buffer to make sure it does not get truncated
    2030         129 :                 if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
    2031             :                 {
    2032           0 :                     throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
    2033             :                 }
    2034         645 :                 std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/" + std::to_string(idx));
    2035         129 :                 CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_ALL) == result);
    2036         129 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ALL) == result);
    2037         129 :                 CATCH_REQUIRE(f.get_port() == port);
    2038         129 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    2039         129 :                 CATCH_REQUIRE(f.get_mask_size() == idx);
    2040         129 :             }
    2041             :         }
    2042          10 :         CATCH_END_SECTION()
    2043             : 
    2044          10 :         CATCH_START_SECTION("ipv6::masks: address like mask")
    2045             :         {
    2046          26 :             for(int idx(0); idx < 25; ++idx)
    2047             :             {
    2048          25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    2049          25 :                 int const port(rand() & 0xFFFF);
    2050          25 :                 addr::addr_parser p;
    2051          25 :                 p.set_protocol(proto);
    2052          25 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
    2053          25 :                 p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
    2054             :                 // when specified as an IP, the mask can be absolutely anything
    2055          25 :                 uint8_t mask[16];
    2056         425 :                 for(int j(0); j < 16; ++j)
    2057             :                 {
    2058         400 :                     mask[j] = rand();
    2059             :                 }
    2060          25 :                 std::stringstream smask;
    2061          25 :                 smask << std::hex
    2062          25 :                       << htons((mask[ 1] << 8) | mask[ 0])
    2063          25 :                       << ":"                            
    2064          25 :                       << htons((mask[ 3] << 8) | mask[ 2])
    2065          25 :                       << ":"                            
    2066          25 :                       << htons((mask[ 5] << 8) | mask[ 4])
    2067          25 :                       << ":"                            
    2068          25 :                       << htons((mask[ 7] << 8) | mask[ 6])
    2069          25 :                       << ":"                            
    2070          25 :                       << htons((mask[ 9] << 8) | mask[ 8])
    2071          25 :                       << ":"                            
    2072          25 :                       << htons((mask[11] << 8) | mask[10])
    2073          25 :                       << ":"                            
    2074          25 :                       << htons((mask[13] << 8) | mask[12])
    2075          25 :                       << ":"                            
    2076          25 :                       << htons((mask[15] << 8) | mask[14]);
    2077          25 :                 char buf[1024]; // really large buffer to make sure it does not get truncated
    2078          25 :                 if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
    2079             :                 {
    2080           0 :                     throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
    2081             :                 }
    2082         175 :                 addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + smask.str() + "]"));
    2083          25 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    2084          25 :                 CATCH_REQUIRE(ips.size() == 1);
    2085          25 :                 addr::addr_range const & r(ips[0]);
    2086          25 :                 addr::addr f(r.get_from());
    2087          25 :                 CATCH_REQUIRE_FALSE(f.is_ipv4());
    2088          25 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    2089          25 :                 CATCH_REQUIRE(f.get_family() == AF_INET6);
    2090         125 :                 std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + buf + "]");
    2091          25 :                 CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_ALL) == result);
    2092          25 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ALL) == result);
    2093          25 :                 CATCH_REQUIRE(f.get_port() == port);
    2094          25 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    2095          25 :             }
    2096             :         }
    2097          10 :         CATCH_END_SECTION()
    2098             : 
    2099          10 :         CATCH_START_SECTION("ipv6::masks: address like default mask")
    2100             :         {
    2101          26 :             for(int idx(0); idx < 25; ++idx)
    2102             :             {
    2103          25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    2104          25 :                 int const port(rand() & 0xFFFF);
    2105          25 :                 addr::addr_parser p;
    2106          25 :                 p.set_protocol(proto);
    2107          25 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
    2108          25 :                 p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
    2109             :                 // when specified as an IP, the mask can be absolutely anything
    2110             :                 // (here the mask is a string an it will be parsed by the
    2111             :                 // parser if required)
    2112             :                 //
    2113          25 :                 uint8_t mask[16];
    2114         425 :                 for(int j(0); j < 16; ++j)
    2115             :                 {
    2116         400 :                     mask[j] = rand();
    2117             :                 }
    2118          25 :                 std::stringstream smask;
    2119          25 :                 smask << std::hex
    2120          25 :                       << "["
    2121          25 :                       << htons((mask[ 1] << 8) | mask[ 0])
    2122          25 :                       << ":"                            
    2123          25 :                       << htons((mask[ 3] << 8) | mask[ 2])
    2124          25 :                       << ":"                            
    2125          25 :                       << htons((mask[ 5] << 8) | mask[ 4])
    2126          25 :                       << ":"                            
    2127          25 :                       << htons((mask[ 7] << 8) | mask[ 6])
    2128          25 :                       << ":"                            
    2129          25 :                       << htons((mask[ 9] << 8) | mask[ 8])
    2130          25 :                       << ":"                            
    2131          25 :                       << htons((mask[11] << 8) | mask[10])
    2132          25 :                       << ":"                            
    2133          25 :                       << htons((mask[13] << 8) | mask[12])
    2134          25 :                       << ":"                            
    2135          25 :                       << htons((mask[15] << 8) | mask[14])
    2136          25 :                       << "]";
    2137          25 :                 char buf[1024]; // really large buffer to make sure it does not get truncated
    2138          25 :                 if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
    2139             :                 {
    2140           0 :                     throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
    2141             :                 }
    2142          25 :                 p.set_default_mask(smask.str());
    2143          75 :                 addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port)));
    2144          25 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    2145          25 :                 CATCH_REQUIRE(ips.size() == 1);
    2146          25 :                 addr::addr_range const & r(ips[0]);
    2147          25 :                 addr::addr f(r.get_from());
    2148          25 :                 CATCH_REQUIRE_FALSE(f.is_ipv4());
    2149          25 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    2150          25 :                 CATCH_REQUIRE(f.get_family() == AF_INET6);
    2151         125 :                 std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + buf + "]");
    2152          25 :                 CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_ALL) == result);
    2153          25 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ALL) == result);
    2154          25 :                 CATCH_REQUIRE(f.get_port() == port);
    2155          25 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    2156          25 :                 uint8_t verify_mask[16];
    2157          25 :                 f.get_mask(verify_mask);
    2158         425 :                 for(int j(0); j < 16; ++j)
    2159             :                 {
    2160         400 :                     CATCH_REQUIRE(verify_mask[j] == mask[j]);
    2161             :                 }
    2162          25 :             }
    2163             :         }
    2164          10 :         CATCH_END_SECTION()
    2165             : 
    2166          10 :         CATCH_START_SECTION("ipv6::masks: address like mask with a default")
    2167             :         {
    2168          26 :             for(int idx(0); idx < 25; ++idx)
    2169             :             {
    2170          25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    2171          25 :                 int const port(rand() & 0xFFFF);
    2172          25 :                 addr::addr_parser p;
    2173          25 :                 p.set_protocol(proto);
    2174          25 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
    2175          25 :                 p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
    2176             : 
    2177             :                 // here we want a default and an IP with a specific mask
    2178             :                 // to make sure that the specific mask has priority
    2179             :                 //
    2180          25 :                 uint8_t mask[16];
    2181         425 :                 for(int j(0); j < 16; ++j)
    2182             :                 {
    2183         400 :                     mask[j] = rand();
    2184             :                 }
    2185          25 :                 std::stringstream smask;
    2186          25 :                 smask << std::hex
    2187          25 :                       << "["
    2188          25 :                       << htons((mask[ 1] << 8) | mask[ 0])
    2189          25 :                       << ":"                            
    2190          25 :                       << htons((mask[ 3] << 8) | mask[ 2])
    2191          25 :                       << ":"                            
    2192          25 :                       << htons((mask[ 5] << 8) | mask[ 4])
    2193          25 :                       << ":"                            
    2194          25 :                       << htons((mask[ 7] << 8) | mask[ 6])
    2195          25 :                       << ":"                            
    2196          25 :                       << htons((mask[ 9] << 8) | mask[ 8])
    2197          25 :                       << ":"                            
    2198          25 :                       << htons((mask[11] << 8) | mask[10])
    2199          25 :                       << ":"                            
    2200          25 :                       << htons((mask[13] << 8) | mask[12])
    2201          25 :                       << ":"                            
    2202          25 :                       << htons((mask[15] << 8) | mask[14])
    2203          25 :                       << "]";
    2204          25 :                 char buf[1024]; // really large buffer to make sure it does not get truncated
    2205          25 :                 if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
    2206             :                 {
    2207           0 :                     throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
    2208             :                 }
    2209             : 
    2210          25 :                 uint8_t default_mask[16];
    2211         425 :                 for(int j(0); j < 16; ++j)
    2212             :                 {
    2213         400 :                     default_mask[j] = rand();
    2214             :                 }
    2215             :                 //std::stringstream default_smask;
    2216             :                 //default_smask << std::hex
    2217             :                 //      << "["
    2218             :                 //      << htons((default_mask[ 1] << 8) | default_mask[ 0])
    2219             :                 //      << ":"                            
    2220             :                 //      << htons((default_mask[ 3] << 8) | default_mask[ 2])
    2221             :                 //      << ":"                            
    2222             :                 //      << htons((default_mask[ 5] << 8) | default_mask[ 4])
    2223             :                 //      << ":"                            
    2224             :                 //      << htons((default_mask[ 7] << 8) | default_mask[ 6])
    2225             :                 //      << ":"                            
    2226             :                 //      << htons((default_mask[ 9] << 8) | default_mask[ 8])
    2227             :                 //      << ":"                            
    2228             :                 //      << htons((default_mask[11] << 8) | default_mask[10])
    2229             :                 //      << ":"                            
    2230             :                 //      << htons((default_mask[13] << 8) | default_mask[12])
    2231             :                 //      << ":"                            
    2232             :                 //      << htons((default_mask[15] << 8) | default_mask[14])
    2233             :                 //      << "]";
    2234          25 :                 char default_buf[1024]; // really large buffer to make sure it does not get truncated
    2235          25 :                 if(inet_ntop(AF_INET6, default_mask, default_buf, sizeof(buf)) == nullptr)
    2236             :                 {
    2237           0 :                     throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
    2238             :                 }
    2239          25 :                 p.set_default_mask(default_buf);
    2240             : 
    2241         150 :                 addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/" + smask.str()));
    2242          25 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    2243          25 :                 CATCH_REQUIRE(ips.size() == 1);
    2244          25 :                 addr::addr_range const & r(ips[0]);
    2245          25 :                 addr::addr f(r.get_from());
    2246          25 :                 CATCH_REQUIRE_FALSE(f.is_ipv4());
    2247          25 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    2248          25 :                 CATCH_REQUIRE(f.get_family() == AF_INET6);
    2249         125 :                 std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + buf + "]");
    2250          25 :                 CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_ALL) == result);
    2251          25 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ALL) == result);
    2252          25 :                 CATCH_REQUIRE(f.get_port() == port);
    2253          25 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    2254          25 :                 uint8_t verify_mask[16];
    2255          25 :                 f.get_mask(verify_mask);
    2256         425 :                 for(int j(0); j < 16; ++j)
    2257             :                 {
    2258         400 :                     CATCH_REQUIRE(verify_mask[j] == mask[j]);
    2259             :                 }
    2260          25 :             }
    2261             :         }
    2262          10 :         CATCH_END_SECTION()
    2263             : 
    2264          10 :         CATCH_START_SECTION("ipv6::masks: no address, but one IPv6 number masks")
    2265             :         {
    2266             :             // with just a number, the mask is considered an IPv6 mask
    2267             :             // if it is 33 or more
    2268             :             //
    2269          97 :             for(int idx(33); idx <= 128; ++idx)
    2270             :             {
    2271          96 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    2272          96 :                 int const port(rand() & 0xFFFF);
    2273          96 :                 addr::addr_parser p;
    2274          96 :                 p.set_protocol(proto);
    2275          96 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
    2276             :                 //p.set_default_address("55:33:22:11:0:cc:bb:aa");
    2277         576 :                 addr::addr_range::vector_t ips(p.parse(":" + std::to_string(port) + "/" + std::to_string(idx)));
    2278          96 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    2279          96 :                 CATCH_REQUIRE(ips.size() == 1);
    2280          96 :                 addr::addr_range const & r(ips[0]);
    2281          96 :                 addr::addr f(r.get_from());
    2282          96 :                 CATCH_REQUIRE_FALSE(f.is_ipv4());
    2283          96 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    2284          96 :                 CATCH_REQUIRE(f.get_family() == AF_INET6);
    2285          96 :                 uint8_t mask[16] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };
    2286          96 :                 int j(15);
    2287          96 :                 int m(128 - idx);
    2288         613 :                 for(; m > 8; m -= 8, --j)
    2289             :                 {
    2290         517 :                     mask[j] = 0;
    2291             :                 }
    2292          96 :                 if(j < 0)
    2293             :                 {
    2294           0 :                     throw std::logic_error("invalid j here");
    2295             :                 }
    2296          96 :                 mask[j] = 255 << m;
    2297          96 :                 char buf[1024]; // really large buffer to make sure it does not get truncated
    2298          96 :                 if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
    2299             :                 {
    2300           0 :                     throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
    2301             :                 }
    2302         480 :                 std::string result("[::]:" + std::to_string(port) + "/" + std::to_string(idx));
    2303          96 :                 CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_ALL) == result);
    2304          96 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ALL) == result);
    2305          96 :                 CATCH_REQUIRE(f.get_port() == port);
    2306          96 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    2307          96 :                 CATCH_REQUIRE(f.get_mask_size() == idx);
    2308          96 :             }
    2309             :         }
    2310          10 :         CATCH_END_SECTION()
    2311             : 
    2312          10 :         CATCH_START_SECTION("ipv6::masks: no address, but one IPv6 masks")
    2313             :         {
    2314             :             // with just a number, the mask is considered an IPv6 mask
    2315             :             // if it is 33 or more
    2316             :             //
    2317           6 :             for(int idx(0); idx < 5; ++idx)
    2318             :             {
    2319           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    2320           5 :                 int const port(rand() & 0xFFFF);
    2321           5 :                 addr::addr_parser p;
    2322           5 :                 p.set_protocol(proto);
    2323           5 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
    2324           5 :                 p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
    2325             :                 //p.set_default_address("55:33:22:11:0:cc:bb:aa");
    2326          20 :                 addr::addr_range::vector_t ips(p.parse(":" + std::to_string(port) + "/[1:2:3:4:5:6:7:8]"));
    2327           5 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    2328           5 :                 CATCH_REQUIRE(ips.size() == 1);
    2329           5 :                 addr::addr_range const & r(ips[0]);
    2330           5 :                 addr::addr f(r.get_from());
    2331           5 :                 CATCH_REQUIRE_FALSE(f.is_ipv4());
    2332           5 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    2333           5 :                 CATCH_REQUIRE(f.get_family() == AF_INET6);
    2334          15 :                 std::string result("[::]:" + std::to_string(port) + "/[1:2:3:4:5:6:7:8]");
    2335           5 :                 CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_ALL) == result);
    2336           5 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ALL) == result);
    2337           5 :                 CATCH_REQUIRE(f.get_port() == port);
    2338           5 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    2339           5 :             }
    2340             :         }
    2341          10 :         CATCH_END_SECTION()
    2342          14 :     }
    2343          14 : }
    2344             : 
    2345             : 
    2346           7 : CATCH_TEST_CASE("ipv6::network_type", "[ipv6]")
    2347             : {
    2348           7 :     CATCH_GIVEN("addr()")
    2349             :     {
    2350           7 :         addr::addr a;
    2351             : 
    2352           7 :         CATCH_START_SECTION("ipv6::network_type: any (::)")
    2353             :         {
    2354             :             {
    2355           1 :                 struct sockaddr_in6 in6 = sockaddr_in6();
    2356           1 :                 in6.sin6_family = AF_INET6;
    2357           1 :                 in6.sin6_port = htons(rand());
    2358           1 :                 in6.sin6_addr.s6_addr32[0] = 0;
    2359           1 :                 in6.sin6_addr.s6_addr32[1] = 0;
    2360           1 :                 in6.sin6_addr.s6_addr32[2] = 0;
    2361           1 :                 in6.sin6_addr.s6_addr32[3] = 0;
    2362             : 
    2363             :                 // verify network type
    2364             :                 //
    2365           1 :                 a.set_ipv6(in6);
    2366             : 
    2367           1 :                 CATCH_REQUIRE(a.is_default());
    2368           1 :                 CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_ANY);
    2369           1 :                 CATCH_REQUIRE(a.get_network_type_string() == "Any");
    2370           1 :                 CATCH_REQUIRE_FALSE(a.is_lan());
    2371           1 :                 CATCH_REQUIRE_FALSE(a.is_lan(true));
    2372           1 :                 CATCH_REQUIRE_FALSE(a.is_lan(false));
    2373           1 :                 CATCH_REQUIRE(a.is_wan());
    2374           1 :                 CATCH_REQUIRE(a.is_wan(true));
    2375           1 :                 CATCH_REQUIRE_FALSE(a.is_wan(false));
    2376             :             }
    2377             : 
    2378             :             // make sure that if any byte is set to non-zero it is not
    2379             :             // viewed as the ANY address
    2380             :             //
    2381          17 :             for(int idx(0); idx < 16; ++idx)
    2382             :             {
    2383          16 :                 struct sockaddr_in6 in6 = sockaddr_in6();
    2384          16 :                 in6.sin6_family = AF_INET6;
    2385          16 :                 in6.sin6_port = htons(rand());
    2386          16 :                 in6.sin6_addr.s6_addr32[0] = 0;
    2387          16 :                 in6.sin6_addr.s6_addr32[1] = 0;
    2388          16 :                 in6.sin6_addr.s6_addr32[2] = 0;
    2389          16 :                 in6.sin6_addr.s6_addr32[3] = 0;
    2390             : 
    2391             :                 // change one byte only
    2392             :                 //
    2393             :                 do
    2394             :                 {
    2395          16 :                     in6.sin6_addr.s6_addr[idx] = rand();
    2396             :                 }
    2397          16 :                 while(in6.sin6_addr.s6_addr[idx] == 0);
    2398             : 
    2399             :                 // verify network type
    2400             :                 //
    2401          16 :                 a.set_ipv6(in6);
    2402             : 
    2403          16 :                 CATCH_REQUIRE(a.get_network_type_string() != "Any");
    2404             : 
    2405             :                 // addresses that start with 0xFD are private
    2406             :                 //
    2407             :                 // note that the test algorithm prevents IPv4 addresses so
    2408             :                 // not need to bother with those
    2409             :                 //
    2410          16 :                 switch(a.get_network_type())
    2411             :                 {
    2412           0 :                 case addr::network_type_t::NETWORK_TYPE_UNDEFINED:
    2413             :                 case addr::network_type_t::NETWORK_TYPE_ANY:
    2414             :                     // the address is always defined
    2415             :                     // the address is never all zeroes
    2416             :                     //
    2417           0 :                     CATCH_REQUIRE(false);
    2418           0 :                     break;
    2419             : 
    2420           0 :                 case addr::network_type_t::NETWORK_TYPE_PRIVATE:
    2421             :                 case addr::network_type_t::NETWORK_TYPE_LOOPBACK:
    2422           0 :                     CATCH_REQUIRE(a.is_lan());
    2423           0 :                     CATCH_REQUIRE(a.is_lan(true));
    2424           0 :                     CATCH_REQUIRE(a.is_lan(false));
    2425           0 :                     CATCH_REQUIRE_FALSE(a.is_wan());
    2426           0 :                     CATCH_REQUIRE_FALSE(a.is_wan(true));
    2427           0 :                     CATCH_REQUIRE_FALSE(a.is_wan(false));
    2428           0 :                     break;
    2429             : 
    2430           0 :                 case addr::network_type_t::NETWORK_TYPE_CARRIER:
    2431             :                 case addr::network_type_t::NETWORK_TYPE_LINK_LOCAL:
    2432             :                 case addr::network_type_t::NETWORK_TYPE_MULTICAST:
    2433           0 :                     CATCH_REQUIRE_FALSE(a.is_lan());
    2434           0 :                     CATCH_REQUIRE(a.is_lan(true));
    2435           0 :                     CATCH_REQUIRE_FALSE(a.is_lan(false));
    2436           0 :                     CATCH_REQUIRE_FALSE(a.is_wan());
    2437           0 :                     CATCH_REQUIRE_FALSE(a.is_wan(true));
    2438           0 :                     CATCH_REQUIRE_FALSE(a.is_wan(false));
    2439           0 :                     break;
    2440             : 
    2441          16 :                 case addr::network_type_t::NETWORK_TYPE_PUBLIC:
    2442          16 :                     CATCH_REQUIRE_FALSE(a.is_lan());
    2443          16 :                     CATCH_REQUIRE_FALSE(a.is_lan(true));
    2444          16 :                     CATCH_REQUIRE_FALSE(a.is_lan(false));
    2445          16 :                     CATCH_REQUIRE(a.is_wan());
    2446          16 :                     CATCH_REQUIRE(a.is_wan(true));
    2447          16 :                     CATCH_REQUIRE(a.is_wan(false));
    2448          16 :                     break;
    2449             : 
    2450             :                 }
    2451             :             }
    2452             :         }
    2453           7 :         CATCH_END_SECTION()
    2454             : 
    2455           7 :         CATCH_START_SECTION("ipv6::network_type: private address fd00::/8")
    2456             :         {
    2457          11 :             for(int idx(0); idx < 10; ++idx)
    2458             :             {
    2459          10 :                 struct sockaddr_in6 in6 = sockaddr_in6();
    2460          10 :                 in6.sin6_family = AF_INET6;
    2461          10 :                 in6.sin6_port = htons(rand());
    2462          10 :                 in6.sin6_addr.s6_addr16[0] = htons(0xFD00 | (rand() & 255));
    2463          10 :                 in6.sin6_addr.s6_addr16[1] = rand();
    2464          10 :                 in6.sin6_addr.s6_addr16[2] = rand();
    2465          10 :                 in6.sin6_addr.s6_addr16[3] = rand();
    2466          10 :                 in6.sin6_addr.s6_addr16[4] = rand();
    2467          10 :                 in6.sin6_addr.s6_addr16[5] = rand();
    2468          10 :                 in6.sin6_addr.s6_addr16[6] = rand();
    2469          10 :                 in6.sin6_addr.s6_addr16[7] = rand();
    2470             : 
    2471             :                 // verify network type
    2472             :                 //
    2473          10 :                 a.set_ipv6(in6);
    2474          10 :                 CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    2475          10 :                 CATCH_REQUIRE(a.get_network_type_string() == "Private");
    2476          10 :                 CATCH_REQUIRE(a.is_lan());
    2477          10 :                 CATCH_REQUIRE(a.is_lan(true));
    2478          10 :                 CATCH_REQUIRE(a.is_lan(false));
    2479          10 :                 CATCH_REQUIRE_FALSE(a.is_wan());
    2480          10 :                 CATCH_REQUIRE_FALSE(a.is_wan(true));
    2481          10 :                 CATCH_REQUIRE_FALSE(a.is_wan(false));
    2482             :             }
    2483             :         }
    2484           7 :         CATCH_END_SECTION()
    2485             : 
    2486           7 :         CATCH_START_SECTION("ipv6::network_type: private address fe80::/10")
    2487             :         {
    2488          11 :             for(int idx(0); idx < 10; ++idx)
    2489             :             {
    2490          10 :                 struct sockaddr_in6 in6 = sockaddr_in6();
    2491          10 :                 in6.sin6_family = AF_INET6;
    2492          10 :                 in6.sin6_port = htons(rand());
    2493          10 :                 in6.sin6_addr.s6_addr16[0] = htons(0xFE80 | (rand() & 63));
    2494          10 :                 in6.sin6_addr.s6_addr16[1] = rand();
    2495          10 :                 in6.sin6_addr.s6_addr16[2] = rand();
    2496          10 :                 in6.sin6_addr.s6_addr16[3] = rand();
    2497          10 :                 in6.sin6_addr.s6_addr16[4] = rand();
    2498          10 :                 in6.sin6_addr.s6_addr16[5] = rand();
    2499          10 :                 in6.sin6_addr.s6_addr16[6] = rand();
    2500          10 :                 in6.sin6_addr.s6_addr16[7] = rand();
    2501             : 
    2502             :                 // verify network type
    2503             :                 //
    2504          10 :                 a.set_ipv6(in6);
    2505          10 :                 CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_LINK_LOCAL);
    2506          10 :                 CATCH_REQUIRE(a.get_network_type_string() == "Local Link");
    2507          10 :                 CATCH_REQUIRE_FALSE(a.is_lan());
    2508          10 :                 CATCH_REQUIRE(a.is_lan(true));
    2509          10 :                 CATCH_REQUIRE_FALSE(a.is_lan(false));
    2510          10 :                 CATCH_REQUIRE_FALSE(a.is_wan());
    2511          10 :                 CATCH_REQUIRE_FALSE(a.is_wan(true));
    2512          10 :                 CATCH_REQUIRE_FALSE(a.is_wan(false));
    2513             :             }
    2514             :         }
    2515           7 :         CATCH_END_SECTION()
    2516             : 
    2517           7 :         CATCH_START_SECTION("ipv6::network_type: private address ff02::/16")
    2518             :         {
    2519          11 :             for(int idx(0); idx < 10; ++idx)
    2520             :             {
    2521          10 :                 struct sockaddr_in6 in6 = sockaddr_in6();
    2522          10 :                 in6.sin6_family = AF_INET6;
    2523          10 :                 in6.sin6_port = htons(rand());
    2524          10 :                 in6.sin6_addr.s6_addr16[0] = htons(0xFF02);
    2525          10 :                 in6.sin6_addr.s6_addr16[1] = rand();
    2526          10 :                 in6.sin6_addr.s6_addr16[2] = rand();
    2527          10 :                 in6.sin6_addr.s6_addr16[3] = rand();
    2528          10 :                 in6.sin6_addr.s6_addr16[4] = rand();
    2529          10 :                 in6.sin6_addr.s6_addr16[5] = rand();
    2530          10 :                 in6.sin6_addr.s6_addr16[6] = rand();
    2531          10 :                 in6.sin6_addr.s6_addr16[7] = rand();
    2532             : 
    2533             :                 // verify network type
    2534             :                 //
    2535          10 :                 a.set_ipv6(in6);
    2536          10 :                 CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_LINK_LOCAL);
    2537          10 :                 CATCH_REQUIRE(a.get_network_type_string() == "Local Link");
    2538          10 :                 CATCH_REQUIRE_FALSE(a.is_lan());
    2539          10 :                 CATCH_REQUIRE(a.is_lan(true));
    2540          10 :                 CATCH_REQUIRE_FALSE(a.is_lan(false));
    2541          10 :                 CATCH_REQUIRE_FALSE(a.is_wan());
    2542          10 :                 CATCH_REQUIRE_FALSE(a.is_wan(true));
    2543          10 :                 CATCH_REQUIRE_FALSE(a.is_wan(false));
    2544             :             }
    2545             :         }
    2546           7 :         CATCH_END_SECTION()
    2547             : 
    2548           7 :         CATCH_START_SECTION("ipv6::network_type: private address ff00::/8")
    2549             :         {
    2550          11 :             for(int idx(0); idx < 10; ++idx)
    2551             :             {
    2552          10 :                 struct sockaddr_in6 in6 = sockaddr_in6();
    2553          10 :                 in6.sin6_family = AF_INET6;
    2554          10 :                 in6.sin6_port = htons(rand());
    2555             :                 do
    2556             :                 {
    2557          13 :                     in6.sin6_addr.s6_addr16[0] = htons(0xFF00 | (rand() & 255));
    2558             :                 }
    2559          13 :                 while((in6.sin6_addr.s6_addr16[0] & htons(0xFF0F)) == htons(0xFF01)       // ffx1::/16
    2560          11 :                    || (in6.sin6_addr.s6_addr16[0] & htons(0xFF0F)) == htons(0xFF02)       // ffx2::/16
    2561          10 :                    || (in6.sin6_addr.s6_addr16[0] & htons(0xFFC0)) == htons(0xFE80)       // fe80::/10
    2562          23 :                    || (in6.sin6_addr.s6_addr16[0] & htons(0xFF00)) == htons(0xFD00));     // fd00::/8
    2563          10 :                 in6.sin6_addr.s6_addr16[1] = rand();
    2564          10 :                 in6.sin6_addr.s6_addr16[2] = rand();
    2565          10 :                 in6.sin6_addr.s6_addr16[3] = rand();
    2566          10 :                 in6.sin6_addr.s6_addr16[4] = rand();
    2567          10 :                 in6.sin6_addr.s6_addr16[5] = rand();
    2568          10 :                 in6.sin6_addr.s6_addr16[6] = rand();
    2569          10 :                 in6.sin6_addr.s6_addr16[7] = rand();
    2570             : 
    2571             :                 // verify network type
    2572             :                 //
    2573          10 :                 a.set_ipv6(in6);
    2574          10 :                 CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_MULTICAST);
    2575          10 :                 CATCH_REQUIRE(a.get_network_type_string() == "Multicast");
    2576          10 :                 CATCH_REQUIRE_FALSE(a.is_lan());
    2577          10 :                 CATCH_REQUIRE(a.is_lan(true));
    2578          10 :                 CATCH_REQUIRE_FALSE(a.is_lan(false));
    2579          10 :                 CATCH_REQUIRE_FALSE(a.is_wan());
    2580          10 :                 CATCH_REQUIRE_FALSE(a.is_wan(true));
    2581          10 :                 CATCH_REQUIRE_FALSE(a.is_wan(false));
    2582             :             }
    2583             :         }
    2584           7 :         CATCH_END_SECTION()
    2585             : 
    2586           7 :         CATCH_START_SECTION("ipv6::network_type: private address ffx1::/8")
    2587             :         {
    2588          11 :             for(int idx(0); idx < 10; ++idx)
    2589             :             {
    2590          10 :                 struct sockaddr_in6 in6 = sockaddr_in6();
    2591          10 :                 in6.sin6_family = AF_INET6;
    2592          10 :                 in6.sin6_port = htons(rand());
    2593          10 :                 in6.sin6_addr.s6_addr16[0] = htons(0xFF01 | ((rand() & 15) << 4));
    2594          10 :                 in6.sin6_addr.s6_addr16[1] = rand();
    2595          10 :                 in6.sin6_addr.s6_addr16[2] = rand();
    2596          10 :                 in6.sin6_addr.s6_addr16[3] = rand();
    2597          10 :                 in6.sin6_addr.s6_addr16[4] = rand();
    2598          10 :                 in6.sin6_addr.s6_addr16[5] = rand();
    2599          10 :                 in6.sin6_addr.s6_addr16[6] = rand();
    2600          10 :                 in6.sin6_addr.s6_addr16[7] = rand();
    2601             : 
    2602             :                 // verify network type
    2603             :                 //
    2604          10 :                 a.set_ipv6(in6);
    2605          10 :                 CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_LOOPBACK);
    2606          10 :                 CATCH_REQUIRE(a.get_network_type_string() == "Loopback");
    2607          10 :                 CATCH_REQUIRE(a.is_lan());
    2608          10 :                 CATCH_REQUIRE(a.is_lan(true));
    2609          10 :                 CATCH_REQUIRE(a.is_lan(false));
    2610          10 :                 CATCH_REQUIRE_FALSE(a.is_wan());
    2611          10 :                 CATCH_REQUIRE_FALSE(a.is_wan(true));
    2612          10 :                 CATCH_REQUIRE_FALSE(a.is_wan(false));
    2613             :             }
    2614             :         }
    2615           7 :         CATCH_END_SECTION()
    2616             : 
    2617           7 :         CATCH_START_SECTION("ipv6::network_type: private address ::1")
    2618             :         {
    2619          11 :             for(int idx(0); idx < 10; ++idx)
    2620             :             {
    2621          10 :                 struct sockaddr_in6 in6 = sockaddr_in6();
    2622          10 :                 in6.sin6_family = AF_INET6;
    2623          10 :                 in6.sin6_port = htons(rand());
    2624          10 :                 in6.sin6_addr.s6_addr16[0] = 0;
    2625          10 :                 in6.sin6_addr.s6_addr16[1] = 0;
    2626          10 :                 in6.sin6_addr.s6_addr16[2] = 0;
    2627          10 :                 in6.sin6_addr.s6_addr16[3] = 0;
    2628          10 :                 in6.sin6_addr.s6_addr16[4] = 0;
    2629          10 :                 in6.sin6_addr.s6_addr16[5] = 0;
    2630          10 :                 in6.sin6_addr.s6_addr16[6] = 0;
    2631          10 :                 in6.sin6_addr.s6_addr16[7] = htons(1);
    2632             : 
    2633             :                 // verify network type
    2634             :                 //
    2635          10 :                 a.set_ipv6(in6);
    2636          10 :                 CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_LOOPBACK);
    2637          10 :                 CATCH_REQUIRE(a.get_network_type_string() == "Loopback");
    2638          10 :                 CATCH_REQUIRE(a.is_lan());
    2639          10 :                 CATCH_REQUIRE(a.is_lan(true));
    2640          10 :                 CATCH_REQUIRE(a.is_lan(false));
    2641          10 :                 CATCH_REQUIRE_FALSE(a.is_wan());
    2642          10 :                 CATCH_REQUIRE_FALSE(a.is_wan(true));
    2643          10 :                 CATCH_REQUIRE_FALSE(a.is_wan(false));
    2644             : 
    2645             :                 // try again from a string to confirm
    2646             :                 //
    2647          10 :                 struct addrinfo * addrlist(nullptr);
    2648          10 :                 int const port(rand() & 65535);
    2649          10 :                 int const r(getaddrinfo("::1", std::to_string(port).c_str(), nullptr, &addrlist));
    2650          10 :                 CATCH_REQUIRE(r == 0);
    2651          10 :                 CATCH_REQUIRE(addrlist != nullptr);
    2652          10 :                 CATCH_REQUIRE(addrlist->ai_family == AF_INET6);
    2653          10 :                 CATCH_REQUIRE(addrlist->ai_addrlen == sizeof(struct sockaddr_in6));
    2654          10 :                 a.set_ipv6(*reinterpret_cast<sockaddr_in6 *>(addrlist->ai_addr));
    2655          10 :                 CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_LOOPBACK);
    2656          10 :                 CATCH_REQUIRE(a.get_network_type_string() == "Loopback");
    2657          10 :                 CATCH_REQUIRE(a.is_lan());
    2658          10 :                 CATCH_REQUIRE(a.is_lan(true));
    2659          10 :                 CATCH_REQUIRE(a.is_lan(false));
    2660          10 :                 CATCH_REQUIRE_FALSE(a.is_wan());
    2661          10 :                 CATCH_REQUIRE_FALSE(a.is_wan(true));
    2662          10 :                 CATCH_REQUIRE_FALSE(a.is_wan(false));
    2663          10 :                 freeaddrinfo(addrlist);
    2664             :             }
    2665             :         }
    2666           7 :         CATCH_END_SECTION()
    2667          14 :     }
    2668           7 : }
    2669             : 
    2670             : 
    2671           3 : CATCH_TEST_CASE("ipv6::network", "[ipv6]")
    2672             : {
    2673           3 :     CATCH_GIVEN("set_from_socket()")
    2674             :     {
    2675           3 :         CATCH_START_SECTION("ipv6::network: create a server, but do not test it (yet)...")
    2676             :         {
    2677           1 :             addr::addr_parser p;
    2678           3 :             addr::addr_range::vector_t ips(p.parse("[::1]:49999"));
    2679           1 :             CATCH_REQUIRE(ips.size() >= 1);
    2680             : 
    2681           1 :             addr::addr & a(ips[0].get_from());
    2682           1 :             int s(a.create_socket(addr::addr::SOCKET_FLAG_NONBLOCK | addr::addr::SOCKET_FLAG_CLOEXEC | addr::addr::SOCKET_FLAG_REUSE));
    2683           1 :             CATCH_REQUIRE(s >= 0);
    2684           1 :             std::shared_ptr<int> auto_free(&s, socket_deleter);
    2685             : 
    2686           1 :             CATCH_REQUIRE(a.bind(s) == 0);
    2687           1 :         }
    2688           3 :         CATCH_END_SECTION()
    2689             : 
    2690           3 :         CATCH_START_SECTION("ipv6::network: connect with TCP to [::1]")
    2691             :         {
    2692           1 :             if(SNAP_CATCH2_NAMESPACE::g_tcp_port != -1)
    2693             :             {
    2694           1 :                 addr::addr_parser p;
    2695           3 :                 addr::addr_range::vector_t ips(p.parse("[::1]:" + std::to_string(SNAP_CATCH2_NAMESPACE::g_tcp_port)));
    2696           1 :                 CATCH_REQUIRE(ips.size() >= 1);
    2697             : 
    2698           1 :                 addr::addr & a(ips[0].get_from());
    2699           1 :                 int s(a.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC));// | addr::addr::SOCKET_FLAG_REUSE));
    2700           1 :                 CATCH_REQUIRE(s >= 0);
    2701           1 :                 std::shared_ptr<int> auto_free(&s, socket_deleter);
    2702             : 
    2703           1 :                 CATCH_REQUIRE(a.connect(s) == 0);
    2704             : 
    2705             :                 // get socket info from the other side (peer == true)
    2706             :                 //
    2707           1 :                 addr::addr b;
    2708           1 :                 b.set_from_socket(s, true);
    2709           1 :                 CATCH_REQUIRE_FALSE(b.is_ipv4());
    2710           1 :                 CATCH_REQUIRE_FALSE(b.get_family() == AF_INET);
    2711           1 :                 CATCH_REQUIRE(b.get_family() == AF_INET6);
    2712           1 :                 CATCH_REQUIRE(b.to_ipv6_string(addr::STRING_IP_ADDRESS)    == "::1");
    2713           1 :                 CATCH_REQUIRE(b.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "::1");
    2714             : 
    2715             :                 // in this case we know what the port is since we specified
    2716             :                 // that when connecting
    2717             :                 //
    2718           1 :                 CATCH_REQUIRE(b.get_port() == SNAP_CATCH2_NAMESPACE::g_tcp_port);
    2719             : 
    2720             :                 // now try this side (peer == false)
    2721             :                 //
    2722           1 :                 addr::addr c;
    2723           1 :                 c.set_from_socket(s, false);
    2724           1 :                 CATCH_REQUIRE_FALSE(c.is_ipv4());
    2725           1 :                 CATCH_REQUIRE_FALSE(c.get_family() == AF_INET);
    2726           1 :                 CATCH_REQUIRE(c.get_family() == AF_INET6);
    2727           1 :                 CATCH_REQUIRE(c.to_ipv6_string(addr::STRING_IP_ADDRESS)    == "::1");
    2728           1 :                 CATCH_REQUIRE(c.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "::1");
    2729             : 
    2730             :                 // we cannot be sure of the port, there is a range we could
    2731             :                 // test better (more constraining) but for this test is
    2732             :                 // certainly does not matter much; it has to be more than
    2733             :                 // 1023, though
    2734             :                 //
    2735           1 :                 CATCH_REQUIRE(c.get_port() > 1023);
    2736           1 :             }
    2737             :             else
    2738             :             {
    2739             :                 // avoid issue of no assertions
    2740             :                 //
    2741           0 :                 CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::g_tcp_port == -1);
    2742           0 :                 std::cout << "connect to [::1] test skipped as no TCP port was specified on the command line." << std::endl;
    2743             :             }
    2744             :         }
    2745           3 :         CATCH_END_SECTION()
    2746             : 
    2747           3 :         CATCH_START_SECTION("ipv6::network: connect with UDP to [::1]")
    2748             :         {
    2749           1 :             addr::addr_parser p;
    2750           1 :             p.set_protocol("udp");
    2751           3 :             addr::addr_range::vector_t ips(p.parse("[::1]:53"));
    2752           1 :             CATCH_REQUIRE(ips.size() >= 1);
    2753             : 
    2754           1 :             addr::addr & a(ips[0].get_from());
    2755           1 :             int s(a.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC));// | addr::addr::SOCKET_FLAG_REUSE));
    2756           1 :             CATCH_REQUIRE(s >= 0);
    2757           1 :             std::shared_ptr<int> auto_free(&s, socket_deleter);
    2758             : 
    2759           1 :             CATCH_REQUIRE(a.connect(s) == -1);
    2760             : 
    2761             :             // get socket info from the other side (peer == true)
    2762             :             //
    2763           1 :             addr::addr b;
    2764           1 :             CATCH_REQUIRE_THROWS_AS(b.set_from_socket(s, true), addr::addr_io_error);
    2765           1 :             CATCH_REQUIRE_FALSE(b.is_ipv4());
    2766           1 :             CATCH_REQUIRE_FALSE(b.get_family() == AF_INET);
    2767           1 :             CATCH_REQUIRE(b.get_family() == AF_INET6);
    2768           1 :             CATCH_REQUIRE(b.to_ipv6_string(addr::STRING_IP_ADDRESS)    == "::");
    2769           1 :             CATCH_REQUIRE(b.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "::");
    2770             : 
    2771             :             // in this case we know what the port is since we specified
    2772             :             // that when connecting
    2773             :             //
    2774           1 :             CATCH_REQUIRE(b.get_port() == 0);
    2775             : 
    2776             :             // now try this side (peer == false)
    2777             :             //
    2778           1 :             addr::addr c;
    2779           1 :             c.set_from_socket(s, false);
    2780           1 :             CATCH_REQUIRE_FALSE(c.is_ipv4());
    2781           1 :             CATCH_REQUIRE_FALSE(c.get_family() == AF_INET);
    2782           1 :             CATCH_REQUIRE(c.get_family() == AF_INET6);
    2783           1 :             CATCH_REQUIRE(c.to_ipv6_string(addr::STRING_IP_ADDRESS)    == "::");
    2784           1 :             CATCH_REQUIRE(c.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "::");
    2785             : 
    2786             :             // we cannot be sure of the port, there is a range we could
    2787             :             // test better (more constraining) but for this test is
    2788             :             // certainly does not matter much; it has to be more than
    2789             :             // 1023, though
    2790             :             //
    2791           1 :             CATCH_REQUIRE(c.get_port() == 0);
    2792           1 :         }
    2793           3 :         CATCH_END_SECTION()
    2794           3 :     }
    2795           3 : }
    2796             : 
    2797             : 
    2798             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14

Snap C++ | List of projects | List of versions