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

          Line data    Source code
       1             : /* test_addr_ipv6.cpp
       2             :  * Copyright (C) 2011-2017  Made to Order Software Corporation
       3             :  *
       4             :  * Project: http://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             : // C lib
      49             : //
      50             : //#include <string.h>
      51             : ////#include <math.h>
      52             : ////#include <time.h>
      53             : //#include <unistd.h>
      54             : //#include <limits.h>
      55             : 
      56             : 
      57             : 
      58             : 
      59             : /** \brief Details used by the addr class implementation.
      60             :  *
      61             :  * We have a function to check whether an address is part of
      62             :  * the interfaces of your computer. This check requires the
      63             :  * use of a `struct ifaddrs` and as such it requires to
      64             :  * delete that structure. We define a deleter for that
      65             :  * strucure here.
      66             :  */
      67             : namespace
      68             : {
      69             : 
      70             : /** \brief Delete an ifaddrs structure.
      71             :  *
      72             :  * This deleter is used to make sure all the ifaddrs get released when
      73             :  * an exception occurs or the function using such exists.
      74             :  *
      75             :  * \param[in] ia  The ifaddrs structure to free.
      76             :  */
      77           3 : void socket_deleter(int * s)
      78             : {
      79           3 :     close(*s);
      80           3 : }
      81             : 
      82             : 
      83             : }
      84             : // no name namespace
      85             : 
      86             : 
      87             : 
      88          16 : TEST_CASE( "ipv6::invalid_input", "ipv6" )
      89             : {
      90          28 :     GIVEN("addr()")
      91             :     {
      92           2 :         addr::addr a;
      93             : 
      94           2 :         SECTION("set IPv6 with an invalid family")
      95             :         {
      96           1 :             struct sockaddr_in6 in6 = sockaddr_in6();
      97           0 :             do
      98             :             {
      99           1 :                 in6.sin6_family = rand();
     100             :             }
     101           1 :             while(in6.sin6_family == AF_INET6);
     102           1 :             in6.sin6_port = rand();
     103           9 :             for(int idx(0); idx < 8; ++idx)
     104             :             {
     105           8 :                 in6.sin6_addr.s6_addr16[idx] = rand();
     106             :             }
     107           1 :             REQUIRE_THROWS_AS(a.set_ipv6(in6), addr::addr_invalid_argument_exception);
     108           1 :             REQUIRE_THROWS_AS(addr::addr b(in6), addr::addr_invalid_argument_exception);
     109             :         }
     110             :     }
     111             : 
     112          28 :     GIVEN("addr_parser() with IPv6 addresses")
     113             :     {
     114           6 :         SECTION("bad address")
     115             :         {
     116           2 :             addr::addr_parser p;
     117           2 :             addr::addr_range::vector_t ips(p.parse("[{bad-ip}]"));
     118           1 :             REQUIRE(p.has_errors());
     119           1 :             REQUIRE(p.error_count() == 1);
     120           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");
     121           1 :             REQUIRE(ips.size() == 0);
     122             :         }
     123             : 
     124           6 :         SECTION("missing ']'")
     125             :         {
     126           2 :             addr::addr_parser p;
     127           2 :             addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7"));
     128           1 :             REQUIRE(p.has_errors());
     129           1 :             REQUIRE(p.error_count() == 1);
     130           1 :             REQUIRE(p.error_messages() == "IPv6 is missing the ']' ([1:2:3:4:5:6:7).\n");
     131           1 :             REQUIRE(ips.size() == 0);
     132             :         }
     133             : 
     134           6 :         SECTION("required address")
     135             :         {
     136           2 :             addr::addr_parser p;
     137           1 :             p.set_protocol(IPPROTO_TCP);
     138           1 :             p.set_allow(addr::addr_parser::flag_t::REQUIRED_ADDRESS, true);
     139           2 :             addr::addr_range::vector_t ips(p.parse("[]"));
     140           1 :             REQUIRE(p.has_errors());
     141           1 :             REQUIRE(p.error_count() == 1);
     142           1 :             REQUIRE(p.error_messages() == "Required address is missing.\n");
     143           1 :             REQUIRE(ips.size() == 0);
     144             :         }
     145             :     }
     146             : 
     147          28 :     GIVEN("addr_parser() with IPv4 ports")
     148             :     {
     149           4 :         SECTION("required port")
     150             :         {
     151             :             // optional + required -> required
     152             :             {
     153           2 :                 addr::addr_parser p;
     154           1 :                 p.set_protocol(IPPROTO_TCP);
     155           1 :                 p.set_allow(addr::addr_parser::flag_t::REQUIRED_PORT, true);
     156           2 :                 addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]"));
     157           1 :                 REQUIRE(p.has_errors());
     158           1 :                 REQUIRE(p.error_count() == 1);
     159           1 :                 REQUIRE(p.error_messages() == "Required port is missing.\n");
     160           1 :                 REQUIRE(ips.size() == 0);
     161             :             }
     162             : 
     163             :             // only required -> required just the same
     164             :             {
     165           2 :                 addr::addr_parser p;
     166           1 :                 p.set_protocol(IPPROTO_TCP);
     167           1 :                 p.set_allow(addr::addr_parser::flag_t::PORT, false);
     168           1 :                 p.set_allow(addr::addr_parser::flag_t::REQUIRED_PORT, true);
     169           2 :                 addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]"));
     170           1 :                 REQUIRE(p.has_errors());
     171           1 :                 REQUIRE(p.error_count() == 1);
     172           1 :                 REQUIRE(p.error_messages() == "Required port is missing.\n");
     173           1 :                 REQUIRE(ips.size() == 0);
     174             :             }
     175             :         }
     176             : 
     177           4 :         SECTION("port not allowed")
     178             :         {
     179             :             {
     180           2 :                 addr::addr_parser p;
     181           1 :                 p.set_protocol(IPPROTO_TCP);
     182           1 :                 p.set_allow(addr::addr_parser::flag_t::PORT, false);
     183           2 :                 addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:123"));
     184           1 :                 REQUIRE(p.has_errors());
     185           1 :                 REQUIRE(p.error_count() == 1);
     186           1 :                 REQUIRE(p.error_messages() == "Port not allowed ([1:2:3:4:5:6:7:8]:123).\n");
     187           1 :                 REQUIRE(ips.size() == 0);
     188             :             }
     189             : 
     190             :             {
     191           2 :                 addr::addr_parser p;
     192           1 :                 p.set_protocol(IPPROTO_TCP);
     193           1 :                 p.set_allow(addr::addr_parser::flag_t::PORT, false);
     194           2 :                 addr::addr_range::vector_t ips(p.parse("1:2:3:4:5:6:7:8:123.5"));
     195           1 :                 REQUIRE(p.has_errors());
     196           1 :                 REQUIRE(p.error_count() == 1);
     197           1 :                 REQUIRE(p.error_messages() == "Port not allowed (1:2:3:4:5:6:7:8:123.5).\n");
     198           1 :                 REQUIRE(ips.size() == 0);
     199             :             }
     200             :         }
     201             :     }
     202             : 
     203          28 :     GIVEN("addr_parser() with invalid masks")
     204             :     {
     205          16 :         SECTION("really large numbers (over 1000)")
     206             :         {
     207           6 :             for(int idx(0); idx < 5; ++idx)
     208             :             {
     209           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     210           5 :                 int const port(rand() & 0xFFFF);
     211           5 :                 int const mask((rand() & 0xFF) + 1001);
     212          10 :                 addr::addr_parser p;
     213           5 :                 p.set_protocol(proto);
     214           5 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
     215          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)));
     216           5 :                 REQUIRE(p.has_errors());
     217           5 :                 REQUIRE(p.error_count() == 1);
     218           5 :                 REQUIRE(p.error_messages() == "Mask number too large (" + std::to_string(mask) + ", expected a maximum of 128).\n");
     219           5 :                 REQUIRE(ips.size() == 0);
     220             :             }
     221             : 
     222             :             // in case the number is between square brackets it looks like
     223             :             // an IPv4 to getaddrinfo() so we get a different error...
     224             :             // (i.e. the '[' is not a digit so we do not get the "too large"
     225             :             // error...)
     226             :             //
     227           6 :             for(int idx(0); idx < 5; ++idx)
     228             :             {
     229           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     230           5 :                 int const port(rand() & 0xFFFF);
     231           5 :                 int const mask((rand() & 0xFF) + 1001);
     232          10 :                 addr::addr_parser p;
     233           5 :                 p.set_protocol(proto);
     234           5 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
     235          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) + "]"));
     236           5 :                 REQUIRE(p.has_errors());
     237           5 :                 REQUIRE(p.error_count() == 1);
     238           5 :                 REQUIRE(p.error_messages() == "Incompatible address between the address and mask address (first was an IPv6 second an IPv4).\n");
     239           5 :                 REQUIRE(ips.size() == 0);
     240             :             }
     241             : 
     242             :             // an empty address with a mask too large gets us to another place
     243             :             //
     244           6 :             for(int idx(0); idx < 5; ++idx)
     245             :             {
     246           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     247           5 :                 int const port(rand() & 0xFFFF);
     248           5 :                 int const mask((rand() & 0xFF) + 1001);
     249          10 :                 addr::addr_parser p;
     250           5 :                 p.set_protocol(proto);
     251           5 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
     252          10 :                 addr::addr_range::vector_t ips(p.parse(":" + std::to_string(port) + "/" + std::to_string(mask)));
     253           5 :                 REQUIRE(p.has_errors());
     254           5 :                 REQUIRE(p.error_count() == 1);
     255           5 :                 REQUIRE(p.error_messages() == "Mask number too large (" + std::to_string(mask) + ", expected a maximum of 128).\n");
     256           5 :                 REQUIRE(ips.size() == 0);
     257             :             }
     258             : 
     259             :             // an empty address with a mask too large gets us to another place
     260             :             //
     261           6 :             for(int idx(0); idx < 5; ++idx)
     262             :             {
     263           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     264           5 :                 int const port(rand() & 0xFFFF);
     265           5 :                 int const mask((rand() & 0xFF));
     266          10 :                 addr::addr_parser p;
     267           5 :                 p.set_protocol(proto);
     268           5 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
     269          10 :                 addr::addr_range::vector_t ips(p.parse(":" + std::to_string(port) + "/" + std::to_string(mask) + "q"));
     270           5 :                 REQUIRE(p.has_errors());
     271           5 :                 REQUIRE(p.error_count() == 1);
     272           5 :                 REQUIRE(p.error_messages() == "Invalid mask in \"/" + std::to_string(mask) + "q\", error -2 -- Name or service not known (errno: 0 -- Success).\n");
     273           5 :                 REQUIRE(ips.size() == 0);
     274             :             }
     275             :         }
     276             : 
     277          16 :         SECTION("ipv6 mask is limited between 0 and 128")
     278             :         {
     279           6 :             for(int idx(0); idx < 5; ++idx)
     280             :             {
     281           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     282           5 :                 int const port(rand() & 0xFFFF);
     283           5 :                 int const mask((rand() & 0xFF) + 129);
     284          10 :                 addr::addr_parser p;
     285           5 :                 p.set_protocol(proto);
     286           5 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
     287          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)));
     288           5 :                 REQUIRE(p.has_errors());
     289           5 :                 REQUIRE(p.error_count() == 1);
     290           5 :                 REQUIRE(p.error_messages() == "Unsupported mask size (" + std::to_string(mask) + ", expected 128 at the most for an IPv6).\n");
     291           5 :                 REQUIRE(ips.size() == 0);
     292             :             }
     293             :         }
     294             : 
     295          16 :         SECTION("ipv6 mask cannot use name")
     296             :         {
     297           6 :             for(int idx(0); idx < 5; ++idx)
     298             :             {
     299           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     300           5 :                 int const port(rand() & 0xFFFF);
     301          10 :                 addr::addr_parser p;
     302           5 :                 p.set_protocol(proto);
     303           5 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
     304          10 :                 addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/[localhost]"));
     305           5 :                 REQUIRE(p.has_errors());
     306           5 :                 REQUIRE(p.error_count() == 1);
     307           5 :                 REQUIRE(p.error_messages() == "Invalid mask in \"/[localhost]\", error -2 -- Name or service not known (errno: 0 -- Success).\n");
     308           5 :                 REQUIRE(ips.size() == 0);
     309             :             }
     310             :         }
     311             : 
     312          16 :         SECTION("ipv6 mask must be between '[...]'")
     313             :         {
     314           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     315           1 :             int const port(rand() & 0xFFFF);
     316           2 :             addr::addr_parser p;
     317           1 :             p.set_protocol(proto);
     318           1 :             p.set_allow(addr::addr_parser::flag_t::MASK, true);
     319           2 :             addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/::3"));
     320           1 :             REQUIRE(p.has_errors());
     321           1 :             REQUIRE(p.error_count() == 1);
     322           1 :             REQUIRE(p.error_messages() == "The address uses the IPv6 syntax, the mask cannot use IPv4.\n");
     323           1 :             REQUIRE(ips.size() == 0);
     324             :         }
     325             : 
     326          16 :         SECTION("ipv6 mask missing the ']'")
     327             :         {
     328           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     329           1 :             int const port(rand() & 0xFFFF);
     330           2 :             addr::addr_parser p;
     331           1 :             p.set_protocol(proto);
     332           1 :             p.set_allow(addr::addr_parser::flag_t::MASK, true);
     333           2 :             addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]:" + std::to_string(port) + "/[::3"));
     334           1 :             REQUIRE(p.has_errors());
     335           1 :             REQUIRE(p.error_count() == 1);
     336           1 :             REQUIRE(p.error_messages() == "The IPv6 mask is missing the ']' ([::3).\n");
     337           1 :             REQUIRE(ips.size() == 0);
     338             :         }
     339             : 
     340          16 :         SECTION("ipv6 mask with an ipv4 in the '[...]'")
     341             :         {
     342           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     343           1 :             int const port(rand() & 0xFFFF);
     344           2 :             addr::addr_parser p;
     345           1 :             p.set_protocol(proto);
     346           1 :             p.set_allow(addr::addr_parser::flag_t::MASK, true);
     347           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]"));
     348           1 :             REQUIRE(p.has_errors());
     349           1 :             REQUIRE(p.error_count() == 1);
     350           1 :             REQUIRE(p.error_messages() == "Incompatible address between the address and mask address (first was an IPv6 second an IPv4).\n");
     351           1 :             REQUIRE(ips.size() == 0);
     352             :         }
     353             : 
     354          16 :         SECTION("verify default mask")
     355             :         {
     356           2 :             addr::addr_parser p;
     357             : 
     358           1 :             REQUIRE_THROWS_AS(p.set_default_address("[4:5:4:5:7:8:7:8"), addr::addr_invalid_argument_exception);
     359           1 :             REQUIRE(p.get_default_address4() == "");
     360           1 :             REQUIRE(p.get_default_address6() == "");
     361             : 
     362           1 :             p.set_default_address("[1:7:1:7:1:7:1:7]");
     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 :             REQUIRE_THROWS_AS(p.set_default_address("[9:5:9:5:9:8:9:8"), addr::addr_invalid_argument_exception);
     367           1 :             REQUIRE(p.get_default_address4() == "");
     368           1 :             REQUIRE(p.get_default_address6() == "1:7:1:7:1:7:1:7");
     369             : 
     370           1 :             p.set_default_address("12.55.1.9");
     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 :             REQUIRE_THROWS_AS(p.set_default_address("[9:f00f:9:e00e:9:d00d:9:c00c"), addr::addr_invalid_argument_exception);
     375           1 :             REQUIRE(p.get_default_address4() == "12.55.1.9");
     376           1 :             REQUIRE(p.get_default_address6() == "1:7:1:7:1:7:1:7");
     377             : 
     378           1 :             p.set_default_address("");
     379           1 :             REQUIRE(p.get_default_address4() == "");
     380           1 :             REQUIRE(p.get_default_address6() == "");
     381             :         }
     382             : 
     383          16 :         SECTION("verify default mask")
     384             :         {
     385           2 :             addr::addr_parser p;
     386             : 
     387           1 :             REQUIRE_THROWS_AS(p.set_default_mask("[4:5:4:5:7:8:7:8"), addr::addr_invalid_argument_exception);
     388           1 :             REQUIRE(p.get_default_mask4() == "");
     389           1 :             REQUIRE(p.get_default_mask6() == "");
     390             : 
     391           1 :             p.set_default_mask("[1:7:1:7:1:7:1:7]");
     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 :             REQUIRE_THROWS_AS(p.set_default_mask("[9:5:9:5:9:8:9:8"), addr::addr_invalid_argument_exception);
     396           1 :             REQUIRE(p.get_default_mask4() == "");
     397           1 :             REQUIRE(p.get_default_mask6() == "1:7:1:7:1:7:1:7");
     398             : 
     399           1 :             p.set_default_mask("12.55.1.9");
     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 :             REQUIRE_THROWS_AS(p.set_default_mask("[9:f00f:9:e00e:9:d00d:9:c00c"), addr::addr_invalid_argument_exception);
     404           1 :             REQUIRE(p.get_default_mask4() == "12.55.1.9");
     405           1 :             REQUIRE(p.get_default_mask6() == "1:7:1:7:1:7:1:7");
     406             : 
     407           1 :             p.set_default_mask("");
     408           1 :             REQUIRE(p.get_default_mask4() == "");
     409           1 :             REQUIRE(p.get_default_mask6() == "");
     410             :         }
     411             :     }
     412          14 : }
     413             : 
     414             : 
     415           8 : TEST_CASE( "ipv6::address", "ipv6" )
     416             : {
     417          12 :     GIVEN("addr() with an IPv6")
     418             :     {
     419           6 :         addr::addr a;
     420             : 
     421           6 :         SECTION("set_ipv6() / get_ipv6()")
     422             :         {
     423          11 :             for(int idx(0); idx < 10; ++idx)
     424             :             {
     425          10 :                 struct sockaddr_in6 in6 = sockaddr_in6();
     426          10 :                 in6.sin6_family = AF_INET6;
     427          10 :                 in6.sin6_port = htons(rand());
     428          10 :                 in6.sin6_addr.s6_addr16[0] = rand();
     429          10 :                 in6.sin6_addr.s6_addr16[1] = rand();
     430          10 :                 in6.sin6_addr.s6_addr16[2] = rand();
     431          10 :                 in6.sin6_addr.s6_addr16[3] = rand();
     432          10 :                 in6.sin6_addr.s6_addr16[4] = rand();
     433          10 :                 in6.sin6_addr.s6_addr16[5] = rand();
     434          10 :                 in6.sin6_addr.s6_addr16[6] = rand();
     435          10 :                 in6.sin6_addr.s6_addr16[7] = rand();
     436             : 
     437             :                 // verify network type
     438             :                 //
     439          10 :                 a.set_ipv6(in6);
     440             : 
     441             :                 // test constructor
     442             :                 //
     443          20 :                 addr::addr b(in6);
     444             :                 struct sockaddr_in6 out6;
     445          10 :                 b.get_ipv6(out6);
     446          10 :                 REQUIRE(memcmp(&out6, &in6, sizeof(struct sockaddr_in)) == 0);
     447             : 
     448             :                 // test set
     449             :                 //
     450          10 :                 a.set_ipv6(in6);
     451          10 :                 a.get_ipv6(out6);
     452          10 :                 REQUIRE(memcmp(&out6, &in6, sizeof(struct sockaddr_in)) == 0);
     453             :             }
     454             :         }
     455             : 
     456           6 :         SECTION("set_ipv6() check to_ipv6_string()")
     457             :         {
     458          11 :             for(int idx(0); idx < 10; ++idx)
     459             :             {
     460          10 :                 struct sockaddr_in6 in6 = sockaddr_in6();
     461          10 :                 in6.sin6_family = AF_INET6;
     462          10 :                 in6.sin6_port = htons(rand());
     463          90 :                 for(int j(0); j < 8; ++j)
     464             :                 {
     465             :                     // avoid any zeroes so that way we do not have
     466             :                     // to handle the "::" syntax
     467           0 :                     do
     468             :                     {
     469          80 :                         in6.sin6_addr.s6_addr16[j] = rand();
     470             :                     }
     471          80 :                     while(in6.sin6_addr.s6_addr16[j] == 0);
     472             :                 }
     473             : 
     474          20 :                 std::stringstream ip_buf;
     475          10 :                 ip_buf << std::hex
     476          20 :                        << ntohs(in6.sin6_addr.s6_addr16[0])
     477          10 :                        << ":"
     478          20 :                        << ntohs(in6.sin6_addr.s6_addr16[1])
     479          10 :                        << ":"
     480          20 :                        << ntohs(in6.sin6_addr.s6_addr16[2])
     481          10 :                        << ":"
     482          20 :                        << ntohs(in6.sin6_addr.s6_addr16[3])
     483          10 :                        << ":"
     484          20 :                        << ntohs(in6.sin6_addr.s6_addr16[4])
     485          10 :                        << ":"
     486          20 :                        << ntohs(in6.sin6_addr.s6_addr16[5])
     487          10 :                        << ":"
     488          20 :                        << ntohs(in6.sin6_addr.s6_addr16[6])
     489          10 :                        << ":"
     490          20 :                        << ntohs(in6.sin6_addr.s6_addr16[7]);
     491          20 :                 std::string const ip(ip_buf.str());
     492             : 
     493          20 :                 std::string port_str(std::to_string(static_cast<int>(htons(in6.sin6_port))));
     494             : 
     495             :                 // check IPv6 as a string
     496             :                 //
     497          10 :                 a.set_ipv6(in6);
     498          10 :                 REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY)          == ip);
     499          10 :                 REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS)      == "[" + ip + "]");
     500          10 :                 REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_PORT)          == "[" + ip + "]:" + port_str);
     501          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
     502          10 :                 REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS_MASK) == "[" + ip + "]/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
     503          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]");
     504             :             }
     505             :         }
     506             : 
     507           6 :         SECTION("name of various IPs")
     508             :         {
     509           1 :             struct sockaddr_in6 in6 = sockaddr_in6();
     510           1 :             in6.sin6_family = AF_INET6;
     511           1 :             in6.sin6_port = htons(rand());
     512             : 
     513             :             // verify network type
     514             :             //
     515           1 :             a.set_ipv6(in6);
     516           1 :             REQUIRE(a.get_name() == std::string()); // no name for "any" (TCP)
     517             : 
     518           1 :             a.set_protocol(IPPROTO_UDP);
     519           1 :             REQUIRE(a.get_name() == std::string()); // no name for "any" (UDP)
     520             : 
     521           1 :             in6 = sockaddr_in6();
     522           1 :             in6.sin6_family = AF_INET6;
     523           1 :             in6.sin6_port = htons(rand());
     524           1 :             in6.sin6_addr.s6_addr16[7] = htons(1);
     525           1 :             a.set_ipv6(in6);
     526             :             char hostname[HOST_NAME_MAX + 1];
     527           1 :             hostname[HOST_NAME_MAX] = '\0';
     528           1 :             REQUIRE(gethostname(hostname, sizeof(hostname)) == 0);
     529           1 :             REQUIRE(hostname[0] != '\0');
     530           1 :             REQUIRE(a.get_name() == hostname);
     531           1 :             REQUIRE(a.is_computer_interface_address() == addr::addr::computer_interface_address_t::COMPUTER_INTERFACE_ADDRESS_TRUE);
     532             :         }
     533             :     }
     534             : 
     535          12 :     GIVEN("addr_parser() with IPv6 addresses")
     536             :     {
     537           6 :         SECTION("verify basics")
     538             :         {
     539           2 :             addr::addr_parser p;
     540           1 :             p.set_protocol(IPPROTO_TCP);
     541           2 :             addr::addr_range::vector_t ips(p.parse("[1:2:3:4:5:6:7:8]"));
     542           1 :             REQUIRE_FALSE(p.has_errors());
     543           1 :             REQUIRE(ips.size() == 1);
     544           1 :             addr::addr_range const & r(ips[0]);
     545           1 :             REQUIRE(r.has_from());
     546           1 :             REQUIRE_FALSE(r.has_to());
     547           1 :             REQUIRE_FALSE(r.is_range());
     548           1 :             REQUIRE_FALSE(r.is_empty());
     549           2 :             addr::addr f(r.get_from());
     550           1 :             REQUIRE_FALSE(f.is_ipv4());
     551           1 :             REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1:2:3:4:5:6:7:8");
     552           1 :             REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[1:2:3:4:5:6:7:8]");
     553           1 :             REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1:2:3:4:5:6:7:8");
     554           1 :             REQUIRE(f.get_port() == 0);
     555           1 :             REQUIRE(f.get_protocol() == IPPROTO_TCP);
     556           1 :             REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     557           1 :             uint8_t mask[16] = {};
     558           1 :             f.get_mask(mask);
     559          17 :             for(int idx(0); idx < 16; ++idx)
     560             :             {
     561          16 :                 REQUIRE(mask[idx] == 255);
     562             :             }
     563             :         }
     564             : 
     565           6 :         SECTION("default address")
     566             :         {
     567           2 :             addr::addr_parser p;
     568           1 :             p.set_protocol(IPPROTO_TCP);
     569           1 :             p.set_default_address("5:5:5:5:5:5:5:5");
     570           2 :             addr::addr_range::vector_t ips(p.parse(""));
     571           1 :             REQUIRE_FALSE(p.has_errors());
     572           1 :             REQUIRE(ips.size() == 1);
     573           1 :             addr::addr_range const & r(ips[0]);
     574           1 :             REQUIRE(r.has_from());
     575           1 :             REQUIRE_FALSE(r.has_to());
     576           1 :             REQUIRE_FALSE(r.is_range());
     577           1 :             REQUIRE_FALSE(r.is_empty());
     578           2 :             addr::addr f(r.get_from());
     579           1 :             REQUIRE_FALSE(f.is_ipv4());
     580           1 :             REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5:5:5:5:5:5:5:5");
     581           1 :             REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[5:5:5:5:5:5:5:5]");
     582           1 :             REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5:5:5:5:5:5:5:5");
     583           1 :             REQUIRE(f.get_port() == 0);
     584           1 :             REQUIRE(f.get_protocol() == IPPROTO_TCP);
     585           1 :             REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     586             :         }
     587             : 
     588           6 :         SECTION("address, not port allowed")
     589             :         {
     590             :             // specific address with a default
     591             :             {
     592           2 :                 addr::addr_parser p;
     593           1 :                 p.set_allow(addr::addr_parser::flag_t::PORT, false);
     594           1 :                 p.set_protocol(IPPROTO_TCP);
     595           1 :                 p.set_default_address("8:7:6:5:4:3:2:1");
     596           2 :                 addr::addr_range::vector_t ips(p.parse("[9:9:9:9:4:3:2:1]"));
     597           1 :                 REQUIRE_FALSE(p.has_errors());
     598           1 :                 REQUIRE(ips.size() == 1);
     599           1 :                 addr::addr_range const & r(ips[0]);
     600           1 :                 REQUIRE(r.has_from());
     601           1 :                 REQUIRE_FALSE(r.has_to());
     602           1 :                 REQUIRE_FALSE(r.is_range());
     603           1 :                 REQUIRE_FALSE(r.is_empty());
     604           2 :                 addr::addr f(r.get_from());
     605           1 :                 REQUIRE_FALSE(f.is_ipv4());
     606           1 :                 REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "9:9:9:9:4:3:2:1");
     607           1 :                 REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[9:9:9:9:4:3:2:1]");
     608           1 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "9:9:9:9:4:3:2:1");
     609           1 :                 REQUIRE(f.get_port() == 0);
     610           1 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
     611           1 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     612             :             }
     613             : 
     614             :             // only a default address
     615             :             {
     616           2 :                 addr::addr_parser p;
     617           1 :                 p.set_allow(addr::addr_parser::flag_t::PORT, false);
     618           1 :                 p.set_protocol(IPPROTO_TCP);
     619           1 :                 p.set_default_address("5:1:6:2:7:3:8:4");
     620           2 :                 addr::addr_range::vector_t ips(p.parse(""));
     621           1 :                 REQUIRE_FALSE(p.has_errors());
     622           1 :                 REQUIRE(ips.size() == 1);
     623           1 :                 addr::addr_range const & r(ips[0]);
     624           1 :                 REQUIRE(r.has_from());
     625           1 :                 REQUIRE_FALSE(r.has_to());
     626           1 :                 REQUIRE_FALSE(r.is_range());
     627           1 :                 REQUIRE_FALSE(r.is_empty());
     628           2 :                 addr::addr f(r.get_from());
     629           1 :                 REQUIRE_FALSE(f.is_ipv4());
     630           1 :                 REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5:1:6:2:7:3:8:4");
     631           1 :                 REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[5:1:6:2:7:3:8:4]");
     632           1 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5:1:6:2:7:3:8:4");
     633           1 :                 REQUIRE(f.get_port() == 0);
     634           1 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
     635           1 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     636             :             }
     637             :         }
     638             :     }
     639           6 : }
     640             : 
     641             : 
     642           7 : TEST_CASE( "ipv6::ports", "ipv6" )
     643             : {
     644             :     // by default addr() is an IPv6 address so we test the basic port
     645             :     // functions here, although it could be in a common place instead...
     646             :     //
     647          10 :     GIVEN("addr()")
     648             :     {
     649           6 :         addr::addr a;
     650             : 
     651           6 :         SECTION("default port")
     652             :         {
     653           1 :             REQUIRE(a.get_port() == 0);
     654             :         }
     655             : 
     656           6 :         SECTION("set_port()")
     657             :         {
     658             :             // setup a random port to start with
     659             :             //
     660           1 :             int const start_port(rand() & 0xFFFF);
     661           1 :             a.set_port(start_port);
     662             : 
     663             :             // test 100 invalid ports
     664             :             //
     665         101 :             for(int idx(0); idx < 100; ++idx)
     666             :             {
     667             :                 // first try a negative port
     668             :                 int port_too_small;
     669           0 :                 do
     670             :                 {
     671         100 :                     port_too_small = -(rand() & 0xFFFF);
     672             :                 }
     673         100 :                 while(port_too_small == 0);
     674         100 :                 REQUIRE_THROWS_AS(a.set_port(port_too_small), addr::addr_invalid_argument_exception);
     675             : 
     676             :                 // first try a negative port
     677         100 :                 int const port_too_large = (rand() & 0xFFFF) + 65536;
     678         100 :                 REQUIRE_THROWS_AS(a.set_port(port_too_large), addr::addr_invalid_argument_exception);
     679             : 
     680             :                 // make sure port does not get modified on errors
     681         100 :                 REQUIRE(a.get_port() == start_port);
     682             :             }
     683             : 
     684             :             // test all ports
     685             :             //
     686       65537 :             for(int port(0); port < 65536; ++port)
     687             :             {
     688       65536 :                 a.set_port(port);
     689             : 
     690       65536 :                 REQUIRE(a.get_port() == port);
     691             :             }
     692             :         }
     693             : 
     694           6 :         SECTION("known ports to test get_service()")
     695             :         {
     696           1 :             a.set_port(80);
     697           1 :             REQUIRE(a.get_service() == "http");
     698             : 
     699           1 :             a.set_port(443);
     700           1 :             REQUIRE(a.get_service() == "https");
     701             : 
     702             :             // again with UDP
     703             :             // 
     704           1 :             a.set_protocol(IPPROTO_UDP);
     705             : 
     706           1 :             a.set_port(80);
     707           1 :             REQUIRE(a.get_service() == "http");
     708             : 
     709           1 :             a.set_port(443);
     710           1 :             REQUIRE(a.get_service() == "https");
     711             :         }
     712             :     }
     713             : 
     714          10 :     GIVEN("addr_parser() with IPv6 addresses and port")
     715             :     {
     716           4 :         SECTION("verify port")
     717             :         {
     718       65537 :             for(int port(0); port < 65536; ++port)
     719             :             {
     720       65536 :                 int proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     721      131072 :                 addr::addr_parser p;
     722       65536 :                 p.set_protocol(proto);
     723      131072 :                 addr::addr_range::vector_t ips(p.parse("[ff01:2f3:f041:e301:f:10:11:12]:" + std::to_string(port)));
     724       65536 :                 REQUIRE_FALSE(p.has_errors());
     725       65536 :                 REQUIRE(ips.size() == 1);
     726       65536 :                 addr::addr_range const & r(ips[0]);
     727      131072 :                 addr::addr f(r.get_from());
     728       65536 :                 REQUIRE_FALSE(f.is_ipv4());
     729       65536 :                 REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "ff01:2f3:f041:e301:f:10:11:12");
     730       65536 :                 REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS) == "[ff01:2f3:f041:e301:f:10:11:12]");
     731       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));
     732       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));
     733       65536 :                 REQUIRE(f.get_port() == port);
     734       65536 :                 REQUIRE(f.get_protocol() == proto);
     735       65536 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LOOPBACK);
     736             :             }
     737             :         }
     738             : 
     739           4 :         SECTION("default address with various port")
     740             :         {
     741         101 :             for(int idx(0); idx < 100; ++idx)
     742             :             {
     743         100 :                 uint16_t const port(rand());
     744         200 :                 addr::addr_parser p;
     745         100 :                 p.set_protocol(IPPROTO_TCP);
     746         100 :                 p.set_default_address("ff02:23:f41:e31:20:30:40:50");
     747         200 :                 addr::addr_range::vector_t ips(p.parse(":" + std::to_string(static_cast<int>(port))));
     748         100 :                 REQUIRE_FALSE(p.has_errors());
     749         100 :                 REQUIRE(ips.size() == 1);
     750         100 :                 addr::addr_range const & r(ips[0]);
     751         100 :                 REQUIRE(r.has_from());
     752         100 :                 REQUIRE_FALSE(r.has_to());
     753         100 :                 REQUIRE_FALSE(r.is_range());
     754         100 :                 REQUIRE_FALSE(r.is_empty());
     755         200 :                 addr::addr f(r.get_from());
     756         100 :                 REQUIRE_FALSE(f.is_ipv4());
     757         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)));
     758         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)));
     759         100 :                 REQUIRE(f.get_port() == port);
     760         100 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
     761         100 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LINK_LOCAL);
     762             :             }
     763             :         }
     764             :     }
     765           5 : }
     766             : 
     767             : 
     768          14 : TEST_CASE( "ipv6::masks", "ipv6" )
     769             : {
     770          24 :     GIVEN("addr()")
     771             :     {
     772             :         // technically, a default addr object represents and IPv6 so the
     773             :         // dealing with the mask without an IPv4 is done by IPv6 tests
     774             :         //
     775           6 :         addr::addr a;
     776             : 
     777           6 :         SECTION("default mask")
     778             :         {
     779           1 :             uint8_t mask[16] = {};
     780           1 :             a.get_mask(mask);
     781          17 :             for(int idx(0); idx < 16; ++idx)
     782             :             {
     783          16 :                 REQUIRE(mask[idx] == 255);
     784             :             }
     785             :         }
     786             : 
     787           6 :         SECTION("set_mask()")
     788             :         {
     789             :             uint8_t mask[16], verify_mask[16];
     790           6 :             for(int idx(0); idx < 5; ++idx)
     791             :             {
     792          85 :                 for(int j(0); j < 16; ++j)
     793             :                 {
     794          80 :                     mask[j] = rand();
     795             :                 }
     796           5 :                 a.set_mask(mask);
     797           5 :                 a.get_mask(verify_mask);
     798          85 :                 for(int j(0); j < 16; ++j)
     799             :                 {
     800          80 :                     REQUIRE(mask[j] == verify_mask[j]);
     801             :                 }
     802             : 
     803             :                 // verify that a copy does copy the mask as expected
     804             :                 //
     805          10 :                 addr::addr b(a);
     806           5 :                 b.get_mask(verify_mask);
     807          85 :                 for(int j(0); j < 16; ++j)
     808             :                 {
     809          80 :                     REQUIRE(mask[j] == verify_mask[j]);
     810             :                 }
     811             :             }
     812             :         }
     813             : 
     814           6 :         SECTION("set_mask()")
     815             :         {
     816             :             uint8_t mask[16];
     817             :             uint8_t verify_mask[16];
     818           6 :             for(int idx(0); idx < 5; ++idx)
     819             :             {
     820          85 :                 for(int j(0); j < 16; ++j)
     821             :                 {
     822          80 :                     mask[j] = rand();
     823             :                 }
     824           5 :                 a.set_mask(mask);
     825           5 :                 a.get_mask(verify_mask);
     826          85 :                 for(int j(0); j < 16; ++j)
     827             :                 {
     828          80 :                     REQUIRE(mask[j] == verify_mask[j]);
     829          80 :                     verify_mask[j] = rand();
     830             :                 }
     831             : 
     832             :                 // verify that a copy does copy the mask as expected
     833             :                 //
     834          10 :                 addr::addr b(a);
     835           5 :                 b.get_mask(verify_mask);
     836          85 :                 for(int j(0); j < 16; ++j)
     837             :                 {
     838          80 :                     REQUIRE(mask[j] == verify_mask[j]);
     839          80 :                     verify_mask[j] = rand();
     840             :                 }
     841             : 
     842             :                 // verify that copying inside a range works too
     843             :                 //
     844          10 :                 addr::addr_range r;
     845           5 :                 r.set_from(a);
     846           5 :                 r.get_from().get_mask(verify_mask);
     847          85 :                 for(int j(0); j < 16; ++j)
     848             :                 {
     849          80 :                     REQUIRE(mask[j] == verify_mask[j]);
     850          80 :                     verify_mask[j] = rand();
     851             :                 }
     852             : 
     853             :                 // then that a range copy works as expected
     854             :                 //
     855          10 :                 addr::addr_range c(r);
     856           5 :                 c.get_from().get_mask(verify_mask);
     857          85 :                 for(int j(0); j < 16; ++j)
     858             :                 {
     859          80 :                     REQUIRE(mask[j] == verify_mask[j]);
     860          80 :                     verify_mask[j] = rand();
     861             :                 }
     862             :             }
     863             :         }
     864             :     }
     865             : 
     866          24 :     GIVEN("addr_parser() of address:port/mask")
     867             :     {
     868          18 :         SECTION("mask allowed, but no mask")
     869             :         {
     870           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     871           1 :             int const port(rand() & 0xFFFF);
     872           2 :             addr::addr_parser p;
     873           1 :             p.set_protocol(proto);
     874           1 :             p.set_allow(addr::addr_parser::flag_t::MASK, true);
     875           2 :             addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port)));
     876           1 :             REQUIRE_FALSE(p.has_errors());
     877           1 :             REQUIRE(ips.size() == 1);
     878           1 :             addr::addr_range const & r(ips[0]);
     879           2 :             addr::addr f(r.get_from());
     880           1 :             REQUIRE_FALSE(f.is_ipv4());
     881           2 :             std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
     882           1 :             REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
     883           1 :             REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
     884           1 :             REQUIRE(f.get_port() == port);
     885           1 :             REQUIRE(f.get_protocol() == proto);
     886             :         }
     887             : 
     888          18 :         SECTION("empty mask")
     889             :         {
     890           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     891           1 :             int const port(rand() & 0xFFFF);
     892           2 :             addr::addr_parser p;
     893           1 :             p.set_protocol(proto);
     894           1 :             p.set_allow(addr::addr_parser::flag_t::MASK, true);
     895           2 :             addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/"));
     896           1 :             REQUIRE_FALSE(p.has_errors());
     897           1 :             REQUIRE(ips.size() == 1);
     898           1 :             addr::addr_range const & r(ips[0]);
     899           2 :             addr::addr f(r.get_from());
     900           1 :             REQUIRE_FALSE(f.is_ipv4());
     901           2 :             std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
     902           1 :             REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
     903           1 :             REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
     904           1 :             REQUIRE(f.get_port() == port);
     905           1 :             REQUIRE(f.get_protocol() == proto);
     906             :         }
     907             : 
     908          18 :         SECTION("empty mask including the '[]'")
     909             :         {
     910           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     911           1 :             int const port(rand() & 0xFFFF);
     912           2 :             addr::addr_parser p;
     913           1 :             p.set_protocol(proto);
     914           1 :             p.set_allow(addr::addr_parser::flag_t::MASK, true);
     915           2 :             addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[]"));
     916           1 :             REQUIRE_FALSE(p.has_errors());
     917           1 :             REQUIRE(ips.size() == 1);
     918           1 :             addr::addr_range const & r(ips[0]);
     919           2 :             addr::addr f(r.get_from());
     920           1 :             REQUIRE_FALSE(f.is_ipv4());
     921           2 :             std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
     922           1 :             REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
     923           1 :             REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
     924           1 :             REQUIRE(f.get_port() == port);
     925           1 :             REQUIRE(f.get_protocol() == proto);
     926             :         }
     927             : 
     928          18 :         SECTION("one number masks")
     929             :         {
     930         130 :             for(int idx(0); idx <= 128; ++idx)
     931             :             {
     932         129 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     933         129 :                 int const port(rand() & 0xFFFF);
     934         258 :                 addr::addr_parser p;
     935         129 :                 p.set_protocol(proto);
     936         129 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
     937         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)));
     938         129 :                 REQUIRE_FALSE(p.has_errors());
     939         129 :                 REQUIRE(ips.size() == 1);
     940         129 :                 addr::addr_range const & r(ips[0]);
     941         258 :                 addr::addr f(r.get_from());
     942         129 :                 REQUIRE_FALSE(f.is_ipv4());
     943         129 :                 uint8_t mask[16] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };
     944         129 :                 int j(15);
     945         129 :                 int m(128 - idx);
     946        2049 :                 for(; m > 8; m -= 8, --j)
     947             :                 {
     948         960 :                     mask[j] = 0;
     949             :                 }
     950         129 :                 if(j < 0)
     951             :                 {
     952           0 :                     throw std::logic_error("invalid j here");
     953             :                 }
     954         129 :                 mask[j] = 255 << m;
     955             :                 char buf[1024]; // really large buffer to make sure it does not get truncated
     956         129 :                 if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
     957             :                 {
     958           0 :                     throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
     959             :                 }
     960         258 :                 std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + buf + "]");
     961         129 :                 REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
     962         129 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
     963         129 :                 REQUIRE(f.get_port() == port);
     964         129 :                 REQUIRE(f.get_protocol() == proto);
     965             :             }
     966             :         }
     967             : 
     968          18 :         SECTION("address like mask")
     969             :         {
     970          26 :             for(int idx(0); idx < 25; ++idx)
     971             :             {
     972          25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     973          25 :                 int const port(rand() & 0xFFFF);
     974          50 :                 addr::addr_parser p;
     975          25 :                 p.set_protocol(proto);
     976          25 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
     977             :                 // when specified as an IP, the mask can be absolutely anything
     978             :                 uint8_t mask[16];
     979         425 :                 for(int j(0); j < 16; ++j)
     980             :                 {
     981         400 :                     mask[j] = rand();
     982             :                 }
     983          50 :                 std::stringstream smask;
     984          25 :                 smask << std::hex
     985          50 :                       << htons((mask[ 1] << 8) | mask[ 0])
     986          25 :                       << ":"                            
     987          50 :                       << htons((mask[ 3] << 8) | mask[ 2])
     988          25 :                       << ":"                            
     989          50 :                       << htons((mask[ 5] << 8) | mask[ 4])
     990          25 :                       << ":"                            
     991          50 :                       << htons((mask[ 7] << 8) | mask[ 6])
     992          25 :                       << ":"                            
     993          50 :                       << htons((mask[ 9] << 8) | mask[ 8])
     994          25 :                       << ":"                            
     995          50 :                       << htons((mask[11] << 8) | mask[10])
     996          25 :                       << ":"                            
     997          50 :                       << htons((mask[13] << 8) | mask[12])
     998          25 :                       << ":"                            
     999          50 :                       << htons((mask[15] << 8) | mask[14]);
    1000             :                 char buf[1024]; // really large buffer to make sure it does not get truncated
    1001          25 :                 if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
    1002             :                 {
    1003           0 :                     throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
    1004             :                 }
    1005          50 :                 addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + smask.str() + "]"));
    1006          25 :                 REQUIRE_FALSE(p.has_errors());
    1007          25 :                 REQUIRE(ips.size() == 1);
    1008          25 :                 addr::addr_range const & r(ips[0]);
    1009          50 :                 addr::addr f(r.get_from());
    1010          25 :                 REQUIRE_FALSE(f.is_ipv4());
    1011          50 :                 std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + buf + "]");
    1012          25 :                 REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1013          25 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1014          25 :                 REQUIRE(f.get_port() == port);
    1015          25 :                 REQUIRE(f.get_protocol() == proto);
    1016             :             }
    1017             :         }
    1018             : 
    1019          18 :         SECTION("address like default mask")
    1020             :         {
    1021          26 :             for(int idx(0); idx < 25; ++idx)
    1022             :             {
    1023          25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1024          25 :                 int const port(rand() & 0xFFFF);
    1025          50 :                 addr::addr_parser p;
    1026          25 :                 p.set_protocol(proto);
    1027          25 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1028             :                 // when specified as an IP, the mask can be absolutely anything
    1029             :                 // (here the mask is a string an it will be parsed by the
    1030             :                 // parser if required)
    1031             :                 //
    1032             :                 uint8_t mask[16];
    1033         425 :                 for(int j(0); j < 16; ++j)
    1034             :                 {
    1035         400 :                     mask[j] = rand();
    1036             :                 }
    1037          50 :                 std::stringstream smask;
    1038          25 :                 smask << std::hex
    1039          25 :                       << "["
    1040          50 :                       << htons((mask[ 1] << 8) | mask[ 0])
    1041          25 :                       << ":"                            
    1042          50 :                       << htons((mask[ 3] << 8) | mask[ 2])
    1043          25 :                       << ":"                            
    1044          50 :                       << htons((mask[ 5] << 8) | mask[ 4])
    1045          25 :                       << ":"                            
    1046          50 :                       << htons((mask[ 7] << 8) | mask[ 6])
    1047          25 :                       << ":"                            
    1048          50 :                       << htons((mask[ 9] << 8) | mask[ 8])
    1049          25 :                       << ":"                            
    1050          50 :                       << htons((mask[11] << 8) | mask[10])
    1051          25 :                       << ":"                            
    1052          50 :                       << htons((mask[13] << 8) | mask[12])
    1053          25 :                       << ":"                            
    1054          50 :                       << htons((mask[15] << 8) | mask[14])
    1055          25 :                       << "]";
    1056             :                 char buf[1024]; // really large buffer to make sure it does not get truncated
    1057          25 :                 if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
    1058             :                 {
    1059           0 :                     throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
    1060             :                 }
    1061          25 :                 p.set_default_mask(smask.str());
    1062          50 :                 addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port)));
    1063          25 :                 REQUIRE_FALSE(p.has_errors());
    1064          25 :                 REQUIRE(ips.size() == 1);
    1065          25 :                 addr::addr_range const & r(ips[0]);
    1066          50 :                 addr::addr f(r.get_from());
    1067          25 :                 REQUIRE_FALSE(f.is_ipv4());
    1068          50 :                 std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + buf + "]");
    1069          25 :                 REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1070          25 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1071          25 :                 REQUIRE(f.get_port() == port);
    1072          25 :                 REQUIRE(f.get_protocol() == proto);
    1073             :                 uint8_t verify_mask[16];
    1074          25 :                 f.get_mask(verify_mask);
    1075         425 :                 for(int j(0); j < 16; ++j)
    1076             :                 {
    1077         400 :                     REQUIRE(verify_mask[j] == mask[j]);
    1078             :                 }
    1079             :             }
    1080             :         }
    1081             : 
    1082          18 :         SECTION("address like mask with a default")
    1083             :         {
    1084          26 :             for(int idx(0); idx < 25; ++idx)
    1085             :             {
    1086          25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1087          25 :                 int const port(rand() & 0xFFFF);
    1088          50 :                 addr::addr_parser p;
    1089          25 :                 p.set_protocol(proto);
    1090          25 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1091             : 
    1092             :                 // here we want a default and an IP with a specific mask
    1093             :                 // to make sure that the specific mask has priority
    1094             :                 //
    1095             :                 uint8_t mask[16];
    1096         425 :                 for(int j(0); j < 16; ++j)
    1097             :                 {
    1098         400 :                     mask[j] = rand();
    1099             :                 }
    1100          50 :                 std::stringstream smask;
    1101          25 :                 smask << std::hex
    1102          25 :                       << "["
    1103          50 :                       << htons((mask[ 1] << 8) | mask[ 0])
    1104          25 :                       << ":"                            
    1105          50 :                       << htons((mask[ 3] << 8) | mask[ 2])
    1106          25 :                       << ":"                            
    1107          50 :                       << htons((mask[ 5] << 8) | mask[ 4])
    1108          25 :                       << ":"                            
    1109          50 :                       << htons((mask[ 7] << 8) | mask[ 6])
    1110          25 :                       << ":"                            
    1111          50 :                       << htons((mask[ 9] << 8) | mask[ 8])
    1112          25 :                       << ":"                            
    1113          50 :                       << htons((mask[11] << 8) | mask[10])
    1114          25 :                       << ":"                            
    1115          50 :                       << htons((mask[13] << 8) | mask[12])
    1116          25 :                       << ":"                            
    1117          50 :                       << htons((mask[15] << 8) | mask[14])
    1118          25 :                       << "]";
    1119             :                 char buf[1024]; // really large buffer to make sure it does not get truncated
    1120          25 :                 if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
    1121             :                 {
    1122           0 :                     throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
    1123             :                 }
    1124             : 
    1125             :                 uint8_t default_mask[16];
    1126         425 :                 for(int j(0); j < 16; ++j)
    1127             :                 {
    1128         400 :                     default_mask[j] = rand();
    1129             :                 }
    1130             :                 //std::stringstream default_smask;
    1131             :                 //default_smask << std::hex
    1132             :                 //      << "["
    1133             :                 //      << htons((default_mask[ 1] << 8) | default_mask[ 0])
    1134             :                 //      << ":"                            
    1135             :                 //      << htons((default_mask[ 3] << 8) | default_mask[ 2])
    1136             :                 //      << ":"                            
    1137             :                 //      << htons((default_mask[ 5] << 8) | default_mask[ 4])
    1138             :                 //      << ":"                            
    1139             :                 //      << htons((default_mask[ 7] << 8) | default_mask[ 6])
    1140             :                 //      << ":"                            
    1141             :                 //      << htons((default_mask[ 9] << 8) | default_mask[ 8])
    1142             :                 //      << ":"                            
    1143             :                 //      << htons((default_mask[11] << 8) | default_mask[10])
    1144             :                 //      << ":"                            
    1145             :                 //      << htons((default_mask[13] << 8) | default_mask[12])
    1146             :                 //      << ":"                            
    1147             :                 //      << htons((default_mask[15] << 8) | default_mask[14])
    1148             :                 //      << "]";
    1149             :                 char default_buf[1024]; // really large buffer to make sure it does not get truncated
    1150          25 :                 if(inet_ntop(AF_INET6, default_mask, default_buf, sizeof(buf)) == nullptr)
    1151             :                 {
    1152           0 :                     throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
    1153             :                 }
    1154          25 :                 p.set_default_mask(default_buf);
    1155             : 
    1156          50 :                 addr::addr_range::vector_t ips(p.parse("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/" + smask.str()));
    1157          25 :                 REQUIRE_FALSE(p.has_errors());
    1158          25 :                 REQUIRE(ips.size() == 1);
    1159          25 :                 addr::addr_range const & r(ips[0]);
    1160          50 :                 addr::addr f(r.get_from());
    1161          25 :                 REQUIRE_FALSE(f.is_ipv4());
    1162          50 :                 std::string result("[55:33:22:11:0:cc:bb:aa]:" + std::to_string(port) + "/[" + buf + "]");
    1163          25 :                 REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1164          25 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1165          25 :                 REQUIRE(f.get_port() == port);
    1166          25 :                 REQUIRE(f.get_protocol() == proto);
    1167             :                 uint8_t verify_mask[16];
    1168          25 :                 f.get_mask(verify_mask);
    1169         425 :                 for(int j(0); j < 16; ++j)
    1170             :                 {
    1171         400 :                     REQUIRE(verify_mask[j] == mask[j]);
    1172             :                 }
    1173             :             }
    1174             :         }
    1175             : 
    1176          18 :         SECTION("no address, but one IPv6 number masks")
    1177             :         {
    1178             :             // with just a number, the mask is considered an IPv6 mask
    1179             :             // if it is 33 or more
    1180             :             //
    1181          97 :             for(int idx(33); idx <= 128; ++idx)
    1182             :             {
    1183          96 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1184          96 :                 int const port(rand() & 0xFFFF);
    1185         192 :                 addr::addr_parser p;
    1186          96 :                 p.set_protocol(proto);
    1187          96 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1188             :                 //p.set_default_address("55:33:22:11:0:cc:bb:aa");
    1189         192 :                 addr::addr_range::vector_t ips(p.parse(":" + std::to_string(port) + "/" + std::to_string(idx)));
    1190          96 :                 REQUIRE_FALSE(p.has_errors());
    1191          96 :                 REQUIRE(ips.size() == 1);
    1192          96 :                 addr::addr_range const & r(ips[0]);
    1193         192 :                 addr::addr f(r.get_from());
    1194          96 :                 REQUIRE_FALSE(f.is_ipv4());
    1195          96 :                 uint8_t mask[16] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };
    1196          96 :                 int j(15);
    1197          96 :                 int m(128 - idx);
    1198        1130 :                 for(; m > 8; m -= 8, --j)
    1199             :                 {
    1200         517 :                     mask[j] = 0;
    1201             :                 }
    1202          96 :                 if(j < 0)
    1203             :                 {
    1204           0 :                     throw std::logic_error("invalid j here");
    1205             :                 }
    1206          96 :                 mask[j] = 255 << m;
    1207             :                 char buf[1024]; // really large buffer to make sure it does not get truncated
    1208          96 :                 if(inet_ntop(AF_INET6, mask, buf, sizeof(buf)) == nullptr)
    1209             :                 {
    1210           0 :                     throw std::logic_error("somehow we could not convert our mask to an IPv6 address.");
    1211             :                 }
    1212         192 :                 std::string result("[::]:" + std::to_string(port) + "/[" + buf + "]");
    1213          96 :                 REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1214          96 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1215          96 :                 REQUIRE(f.get_port() == port);
    1216          96 :                 REQUIRE(f.get_protocol() == proto);
    1217             :             }
    1218             :         }
    1219             : 
    1220          18 :         SECTION("no address, but one IPv6 masks")
    1221             :         {
    1222             :             // with just a number, the mask is considered an IPv6 mask
    1223             :             // if it is 33 or more
    1224             :             //
    1225           6 :             for(int idx(0); idx < 5; ++idx)
    1226             :             {
    1227           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1228           5 :                 int const port(rand() & 0xFFFF);
    1229          10 :                 addr::addr_parser p;
    1230           5 :                 p.set_protocol(proto);
    1231           5 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1232             :                 //p.set_default_address("55:33:22:11:0:cc:bb:aa");
    1233          10 :                 addr::addr_range::vector_t ips(p.parse(":" + std::to_string(port) + "/[1:2:3:4:5:6:7:8]"));
    1234           5 :                 REQUIRE_FALSE(p.has_errors());
    1235           5 :                 REQUIRE(ips.size() == 1);
    1236           5 :                 addr::addr_range const & r(ips[0]);
    1237          10 :                 addr::addr f(r.get_from());
    1238           5 :                 REQUIRE_FALSE(f.is_ipv4());
    1239          10 :                 std::string result("[::]:" + std::to_string(port) + "/[1:2:3:4:5:6:7:8]");
    1240           5 :                 REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1241           5 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1242           5 :                 REQUIRE(f.get_port() == port);
    1243           5 :                 REQUIRE(f.get_protocol() == proto);
    1244             :             }
    1245             :         }
    1246             :     }
    1247          12 : }
    1248             : 
    1249             : 
    1250           9 : TEST_CASE( "ipv6::network_type", "ipv6" )
    1251             : {
    1252          14 :     GIVEN("addr()")
    1253             :     {
    1254          14 :         addr::addr a;
    1255             : 
    1256          14 :         SECTION("any (::)")
    1257             :         {
    1258             :             {
    1259           1 :                 struct sockaddr_in6 in6 = sockaddr_in6();
    1260           1 :                 in6.sin6_family = AF_INET6;
    1261           1 :                 in6.sin6_port = htons(rand());
    1262           1 :                 in6.sin6_addr.s6_addr32[0] = 0;
    1263           1 :                 in6.sin6_addr.s6_addr32[1] = 0;
    1264           1 :                 in6.sin6_addr.s6_addr32[2] = 0;
    1265           1 :                 in6.sin6_addr.s6_addr32[3] = 0;
    1266             : 
    1267             :                 // verify network type
    1268             :                 //
    1269           1 :                 a.set_ipv6(in6);
    1270             : 
    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", "ipv4" )
    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           2 :                 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           2 :                 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           2 :             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           2 :             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