LCOV - code coverage report
Current view: top level - tests - catch_ipv6.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1679 1713 98.0 %
Date: 2022-06-26 14:27:46 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13