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

Generated by: LCOV version 1.12