LCOV - code coverage report
Current view: top level - tests - test_addr_ipv6.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 949 962 98.6 %
Date: 2018-06-08 23:44:40 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.12