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

Generated by: LCOV version 1.14

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