LCOV - code coverage report
Current view: top level - tests - test_addr_ipv4.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1551 1565 99.1 %
Date: 2018-06-10 17:49:09 Functions: 13 13 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* test_addr_ipv4.cpp
       2             :  * Copyright (c) 2011-2018  Made to Order Software Corp.  All Rights Reserved
       3             :  *
       4             :  * Project: https://snapwebsites.org/project/libaddr
       5             :  *
       6             :  * Permission is hereby granted, free of charge, to any
       7             :  * person obtaining a copy of this software and
       8             :  * associated documentation files (the "Software"), to
       9             :  * deal in the Software without restriction, including
      10             :  * without limitation the rights to use, copy, modify,
      11             :  * merge, publish, distribute, sublicense, and/or sell
      12             :  * copies of the Software, and to permit persons to whom
      13             :  * the Software is furnished to do so, subject to the
      14             :  * following conditions:
      15             :  *
      16             :  * The above copyright notice and this permission notice
      17             :  * shall be included in all copies or substantial
      18             :  * portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
      21             :  * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
      22             :  * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
      23             :  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
      24             :  * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      25             :  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
      26             :  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      27             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
      28             :  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      29             :  * SOFTWARE.
      30             :  */
      31             : 
      32             : /** \file
      33             :  * \brief Test the IPv6 interface.
      34             :  *
      35             :  * These test verify that the IPv6 side of things function as expected.
      36             :  *
      37             :  * Note that some of the tests between the IPv4 and IPv6 overlap. Here
      38             :  * you mainly find the IPv6 side of things.
      39             :  *
      40             :  * Also, the IPv6 test include a certain number of default/global
      41             :  * test because by default the addr class implements an IPv6 object.
      42             :  */
      43             : 
      44             : // self
      45             : //
      46             : #include "test_addr_main.h"
      47             : 
      48             : // addr lib
      49             : //
      50             : #include "libaddr/iface.h"
      51             : 
      52             : 
      53             : 
      54             : /** \brief Details used by the addr class implementation.
      55             :  *
      56             :  * We have a function to check whether an address is part of
      57             :  * the interfaces of your computer. This check requires the
      58             :  * use of a `struct ifaddrs` and as such it requires to
      59             :  * delete that structure. We define a deleter for that
      60             :  * strucure here.
      61             :  */
      62             : namespace
      63             : {
      64             : 
      65             : /** \brief Delete an ifaddrs structure.
      66             :  *
      67             :  * This deleter is used to make sure all the ifaddrs get released when
      68             :  * an exception occurs or the function using such exists.
      69             :  *
      70             :  * \param[in] ia  The ifaddrs structure to free.
      71             :  */
      72           4 : void socket_deleter(int * s)
      73             : {
      74           4 :     close(*s);
      75           4 : }
      76             : 
      77             : 
      78             : }
      79             : // no name namespace
      80             : 
      81             : 
      82             : 
      83          17 : TEST_CASE( "ipv4::invalid_input", "[ipv4]" )
      84             : {
      85          30 :     GIVEN("addr()")
      86             :     {
      87           1 :         addr::addr a;
      88             : 
      89           2 :         SECTION("set IPv4 with an invalid family")
      90             :         {
      91          26 :             for(int idx(0); idx < 25; ++idx)
      92             :             {
      93          25 :                 struct sockaddr_in in = sockaddr_in();
      94           0 :                 do
      95             :                 {
      96          25 :                     in.sin_family = rand();
      97             :                 }
      98          25 :                 while(in.sin_family == AF_INET);
      99          25 :                 in.sin_port = htons(rand());
     100          25 :                 in.sin_addr.s_addr = htonl(rand() ^ (rand() << 16));
     101          25 :                 REQUIRE_THROWS_AS(a.set_ipv4(in), addr::addr_invalid_argument_exception);
     102          25 :                 REQUIRE_THROWS_AS(addr::addr b(in), addr::addr_invalid_argument_exception);
     103             :             }
     104             :         }
     105             :     }
     106             : 
     107          30 :     GIVEN("addr_parser() with IPv4 settings")
     108             :     {
     109           4 :         addr::addr_parser a;
     110             : 
     111           4 :         SECTION("invalid allow flags (too small)")
     112             :         {
     113          11 :             for(int idx(0); idx < 10; ++idx)
     114             :             {
     115             :                 // test with a negative number
     116             :                 //
     117             :                 int n;
     118           0 :                 do
     119             :                 {
     120          10 :                     n = rand();
     121             :                 }
     122          10 :                 while(n == 0);
     123          10 :                 if(n > 0)
     124             :                 {
     125             :                     // all positive numbers have a corresponding negative
     126             :                     // number so this always flips the sign as expected
     127             :                     //
     128          10 :                     n = -n;
     129             :                 }
     130          10 :                 addr::addr_parser::flag_t const flag(static_cast<addr::addr_parser::flag_t>(n));
     131             : 
     132          10 :                 REQUIRE_THROWS_AS(a.set_allow(flag, true), addr::addr_invalid_argument_exception);
     133          10 :                 REQUIRE_THROWS_AS(a.set_allow(flag, false), addr::addr_invalid_argument_exception);
     134          10 :                 REQUIRE_THROWS_AS(a.get_allow(flag), addr::addr_invalid_argument_exception);
     135             :             }
     136             :         }
     137             : 
     138           4 :         SECTION("invalid allow flags (too large)")
     139             :         {
     140          11 :             for(int idx(0); idx < 10; ++idx)
     141             :             {
     142             :                 // test with a negative number
     143             :                 //
     144             :                 int n;
     145           0 :                 do
     146             :                 {
     147          10 :                     n = rand();
     148          10 :                     if(n < 0)
     149             :                     {
     150           0 :                         n = -n;
     151             :                     }
     152             :                 }
     153          10 :                 while(n < static_cast<int>(addr::addr_parser::flag_t::FLAG_max));
     154          10 :                 addr::addr_parser::flag_t const flag(static_cast<addr::addr_parser::flag_t>(n));
     155             : 
     156          10 :                 REQUIRE_THROWS_AS(a.set_allow(flag, true), addr::addr_invalid_argument_exception);
     157          10 :                 REQUIRE_THROWS_AS(a.set_allow(flag, false), addr::addr_invalid_argument_exception);
     158          10 :                 REQUIRE_THROWS_AS(a.get_allow(flag), addr::addr_invalid_argument_exception);
     159             :             }
     160             :         }
     161             :     }
     162             : 
     163          30 :     GIVEN("addr_parser() with IPv4 addresses")
     164             :     {
     165           4 :         SECTION("bad address")
     166             :         {
     167           2 :             addr::addr_parser p;
     168           2 :             addr::addr_range::vector_t ips(p.parse("{bad-ip}"));
     169           1 :             REQUIRE(p.has_errors());
     170           1 :             REQUIRE(p.error_count() == 1);
     171           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");
     172           1 :             REQUIRE(p.has_errors());
     173           1 :             p.clear_errors();
     174           1 :             REQUIRE_FALSE(p.has_errors());
     175           1 :             REQUIRE(ips.size() == 0);
     176             :         }
     177             : 
     178           4 :         SECTION("required address")
     179             :         {
     180           2 :             addr::addr_parser p;
     181           1 :             p.set_protocol(IPPROTO_TCP);
     182           1 :             p.set_allow(addr::addr_parser::flag_t::REQUIRED_ADDRESS, true);
     183           2 :             addr::addr_range::vector_t ips(p.parse(""));
     184           1 :             REQUIRE(p.has_errors());
     185           1 :             REQUIRE(p.error_count() == 1);
     186           1 :             REQUIRE(p.error_messages() == "Required address is missing.\n");
     187           1 :             REQUIRE(p.has_errors());
     188           1 :             p.clear_errors();
     189           1 :             REQUIRE_FALSE(p.has_errors());
     190           1 :             REQUIRE(ips.size() == 0);
     191             :         }
     192             :     }
     193             : 
     194          30 :     GIVEN("addr_parser() with IPv4 ports")
     195             :     {
     196           6 :         SECTION("required port")
     197             :         {
     198             :             // optional + required -> required
     199             :             {
     200           2 :                 addr::addr_parser p;
     201           1 :                 p.set_protocol(IPPROTO_TCP);
     202           1 :                 p.set_allow(addr::addr_parser::flag_t::REQUIRED_PORT, true);
     203           2 :                 addr::addr_range::vector_t ips(p.parse("1.2.3.4"));
     204           1 :                 REQUIRE(p.has_errors());
     205           1 :                 REQUIRE(p.error_count() == 1);
     206           1 :                 REQUIRE(p.error_messages() == "Required port is missing.\n");
     207           1 :                 REQUIRE(p.has_errors());
     208           1 :                 p.clear_errors();
     209           1 :                 REQUIRE_FALSE(p.has_errors());
     210           1 :                 REQUIRE(ips.size() == 0);
     211             :             }
     212             : 
     213             :             // only required -> required just the same
     214             :             {
     215           2 :                 addr::addr_parser p;
     216           1 :                 p.set_protocol(IPPROTO_TCP);
     217           1 :                 p.set_allow(addr::addr_parser::flag_t::PORT, false);
     218           1 :                 p.set_allow(addr::addr_parser::flag_t::REQUIRED_PORT, true);
     219           2 :                 addr::addr_range::vector_t ips(p.parse("1.2.3.4"));
     220           1 :                 REQUIRE(p.has_errors());
     221           1 :                 REQUIRE(p.error_count() == 1);
     222           1 :                 REQUIRE(p.error_messages() == "Required port is missing.\n");
     223           1 :                 REQUIRE(p.has_errors());
     224           1 :                 p.clear_errors();
     225           1 :                 REQUIRE_FALSE(p.has_errors());
     226           1 :                 REQUIRE(ips.size() == 0);
     227             :             }
     228             :         }
     229             : 
     230           6 :         SECTION("port not allowed")
     231             :         {
     232           2 :             addr::addr_parser p;
     233           1 :             p.set_protocol(IPPROTO_TCP);
     234           1 :             p.set_allow(addr::addr_parser::flag_t::PORT, false);
     235           1 :             REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::REQUIRED_PORT));
     236           2 :             addr::addr_range::vector_t ips(p.parse("1.2.3.4:123"));
     237           1 :             REQUIRE(p.has_errors());
     238           1 :             REQUIRE(p.error_count() == 1);
     239           1 :             REQUIRE(p.error_messages() == "Port not allowed (1.2.3.4:123).\n");
     240           1 :             REQUIRE(p.has_errors());
     241           1 :             p.clear_errors();
     242           1 :             REQUIRE_FALSE(p.has_errors());
     243           1 :             REQUIRE(ips.size() == 0);
     244             :         }
     245             : 
     246           6 :         SECTION("invalid port")
     247             :         {
     248           2 :             addr::addr_parser p;
     249             : 
     250             :             // so to a different default value
     251             :             //
     252           1 :             int const default_port(rand() & 0xFFFF);
     253           1 :             p.set_default_port(default_port);
     254             : 
     255          26 :             for(int idx(0); idx < 25; ++idx)
     256             :             {
     257             :                 int port;
     258           0 :                 do
     259             :                 {
     260          25 :                     port = rand() ^ (rand() << 16);
     261             :                 }
     262          25 :                 while(port >= -1 && port <= 65535); // -1 is valid here, it represents "no default port defined"
     263          25 :                 REQUIRE_THROWS_AS(p.set_default_port(port), addr::addr_invalid_argument_exception);
     264             : 
     265             :                 // verify port unchanged
     266             :                 //
     267          25 :                 REQUIRE(p.get_default_port() == default_port);
     268             :             }
     269             :         }
     270             :     }
     271             : 
     272          30 :     GIVEN("addr_parser() with invalid masks")
     273             :     {
     274          10 :         SECTION("really large numbers (over 1000)")
     275             :         {
     276           6 :             for(int idx(0); idx < 5; ++idx)
     277             :             {
     278           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     279           5 :                 int const port(rand() & 0xFFFF);
     280           5 :                 int const mask((rand() & 0xFF) + 1001);
     281          10 :                 addr::addr_parser p;
     282           5 :                 p.set_protocol(proto);
     283           5 :                 p.set_allow(p.flag_t::MASK, true);
     284          10 :                 addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port) + "/" + std::to_string(mask)));
     285           5 :                 REQUIRE(p.has_errors());
     286           5 :                 REQUIRE(p.error_count() == 1);
     287           5 :                 REQUIRE(p.error_messages() == "Mask number too large (" + std::to_string(mask) + ", expected a maximum of 128).\n");
     288           5 :                 REQUIRE(ips.size() == 0);
     289             :             }
     290             :         }
     291             : 
     292          10 :         SECTION("ipv4 mask is limited between 0 and 32")
     293             :         {
     294           6 :             for(int idx(0); idx < 5; ++idx)
     295             :             {
     296           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     297           5 :                 int const port(rand() & 0xFFFF);
     298           5 :                 int const mask((rand() & 0xFF) + 33);
     299          10 :                 addr::addr_parser p;
     300           5 :                 p.set_protocol(proto);
     301           5 :                 p.set_allow(p.flag_t::MASK, true);
     302          10 :                 addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port) + "/" + std::to_string(mask)));
     303           5 :                 REQUIRE(p.has_errors());
     304           5 :                 REQUIRE(p.error_count() == 1);
     305           5 :                 REQUIRE(p.error_messages() == "Unsupported mask size (" + std::to_string(mask) + ", expected 32 at the most for an IPv4).\n");
     306           5 :                 REQUIRE(ips.size() == 0);
     307             :             }
     308             :         }
     309             : 
     310          10 :         SECTION("ipv4 mask cannot use name")
     311             :         {
     312           6 :             for(int idx(0); idx < 5; ++idx)
     313             :             {
     314           5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     315           5 :                 int const port(rand() & 0xFFFF);
     316          10 :                 addr::addr_parser p;
     317           5 :                 p.set_protocol(proto);
     318           5 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
     319          10 :                 addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port) + "/localhost"));
     320           5 :                 REQUIRE(p.has_errors());
     321           5 :                 REQUIRE(p.error_count() == 1);
     322           5 :                 REQUIRE(p.error_messages() == "Invalid mask in \"/localhost\", error -2 -- Name or service not known (errno: 0 -- Success).\n");
     323           5 :                 REQUIRE(ips.size() == 0);
     324             :             }
     325             :         }
     326             : 
     327          10 :         SECTION("ipv4 mask mismatch (mask uses ipv6)")
     328             :         {
     329           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     330           1 :             int const port(rand() & 0xFFFF);
     331           2 :             addr::addr_parser p;
     332           1 :             p.set_protocol(proto);
     333           1 :             p.set_allow(addr::addr_parser::flag_t::MASK, true);
     334           2 :             addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port) + "/[1:2:3:4:5:6:7:8]"));
     335           1 :             REQUIRE(p.has_errors());
     336           1 :             REQUIRE(p.error_count() == 1);
     337           1 :             REQUIRE(p.error_messages() == "The address uses the IPv4 syntax, the mask cannot use IPv6.\n");
     338           1 :             REQUIRE(ips.size() == 0);
     339             :         }
     340             : 
     341          10 :         SECTION("ipv4 mask mismatch (mask uses ipv6 without [...])")
     342             :         {
     343           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     344           1 :             int const port(rand() & 0xFFFF);
     345           2 :             addr::addr_parser p;
     346           1 :             p.set_protocol(proto);
     347           1 :             p.set_allow(addr::addr_parser::flag_t::MASK, true);
     348           2 :             addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port) + "/1:2:3:4:5:6:7:8"));
     349           1 :             REQUIRE(p.has_errors());
     350           1 :             REQUIRE(p.error_count() == 1);
     351           1 :             REQUIRE(p.error_messages() == "Incompatible address between the address and mask address (first was an IPv4 second an IPv6).\n");
     352           1 :             REQUIRE(ips.size() == 0);
     353             :         }
     354             :     }
     355             : 
     356          30 :     GIVEN("addr_parser() with invalid protocols")
     357             :     {
     358           4 :         SECTION("invalid names")
     359             :         {
     360           2 :             addr::addr_parser p;
     361             : 
     362             :             // not changing default protocol
     363             :             //
     364           1 :             REQUIRE(p.get_protocol() == -1);
     365           1 :             REQUIRE_THROWS_AS(p.set_protocol("igmp"), addr::addr_invalid_argument_exception);
     366           1 :             REQUIRE(p.get_protocol() == -1);
     367             : 
     368             :             // change protocol to another valid value first
     369             :             //
     370           1 :             p.set_protocol("tcp");
     371           1 :             REQUIRE_THROWS_AS(p.set_protocol("icmp"), addr::addr_invalid_argument_exception);
     372           1 :             REQUIRE(p.get_protocol() == IPPROTO_TCP);
     373             :         }
     374             : 
     375           4 :         SECTION("invalid numbers")
     376             :         {
     377         101 :             for(int idx(0); idx < 100; ++idx)
     378             :             {
     379             :                 int protocol;
     380           0 :                 do
     381             :                 {
     382         100 :                     protocol = rand();
     383             :                 }
     384             :                 while(protocol == IPPROTO_IP
     385         100 :                    || protocol == IPPROTO_TCP
     386         200 :                    || protocol == IPPROTO_UDP);
     387             : 
     388         200 :                 addr::addr_parser p;
     389             : 
     390         100 :                 REQUIRE_THROWS_AS(p.set_protocol(protocol), addr::addr_invalid_argument_exception);
     391         100 :                 REQUIRE(p.get_protocol() == -1);
     392             : 
     393             :                 // change protocol to another valid value first
     394             :                 //
     395         100 :                 p.set_protocol("tcp");
     396         100 :                 REQUIRE_THROWS_AS(p.set_protocol(protocol), addr::addr_invalid_argument_exception);
     397         100 :                 REQUIRE(p.get_protocol() == IPPROTO_TCP);
     398             :             }
     399             :         }
     400             :     }
     401          15 : }
     402             : 
     403             : 
     404          11 : TEST_CASE( "ipv4::addr", "[ipv4]" )
     405             : {
     406          18 :     GIVEN("addr()")
     407             :     {
     408           9 :         addr::addr a;
     409             : 
     410          18 :         SECTION("not an IPv4")
     411             :         {
     412           1 :             REQUIRE_FALSE(a.is_ipv4());
     413             : 
     414             :             struct sockaddr_in in;
     415           1 :             REQUIRE_THROWS_AS(a.get_ipv4(in), addr::addr_invalid_state_exception);
     416           1 :             REQUIRE_THROWS_AS(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY),          addr::addr_invalid_state_exception);
     417           1 :             REQUIRE_THROWS_AS(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_BRACKETS),      addr::addr_invalid_state_exception);
     418           1 :             REQUIRE_THROWS_AS(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_PORT),          addr::addr_invalid_state_exception);
     419           1 :             REQUIRE_THROWS_AS(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_MASK),          addr::addr_invalid_state_exception);
     420           1 :             REQUIRE_THROWS_AS(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_BRACKETS_MASK), addr::addr_invalid_state_exception);
     421           1 :             REQUIRE_THROWS_AS(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL),           addr::addr_invalid_state_exception);
     422             :         }
     423             : 
     424          18 :         SECTION("default network type (0.0.0.0)")
     425             :         {
     426           1 :             REQUIRE(a.is_default());
     427           1 :             REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_ANY);
     428           1 :             REQUIRE(a.get_network_type_string() == "Any");
     429             :         }
     430             : 
     431          18 :         SECTION("IPv6 ANY")
     432             :         {
     433             :             struct sockaddr_in6 in6;
     434           1 :             a.get_ipv6(in6);
     435           1 :             REQUIRE(in6.sin6_addr.s6_addr32[0] == 0);
     436           1 :             REQUIRE(in6.sin6_addr.s6_addr32[1] == 0);
     437           1 :             REQUIRE(in6.sin6_addr.s6_addr32[2] == 0);
     438           1 :             REQUIRE(in6.sin6_addr.s6_addr32[3] == 0);
     439           1 :             REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY)          == "::");
     440           1 :             REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS)      == "[::]");
     441           1 :             REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_PORT)          == "[::]:0");
     442           1 :             REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_MASK)          == "::/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
     443           1 :             REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS_MASK) == "[::]/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
     444           1 :             REQUIRE(a.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ALL)           == "[::]:0/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
     445             :         }
     446             : 
     447          18 :         SECTION("IPv4 or IPv6 string")
     448             :         {
     449           1 :             REQUIRE(a.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY)          == "::");
     450           1 :             REQUIRE(a.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS)      == "[::]");
     451           1 :             REQUIRE(a.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_PORT)          == "[::]:0");
     452           1 :             REQUIRE(a.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_MASK)          == "::/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
     453           1 :             REQUIRE(a.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_BRACKETS_MASK) == "[::]/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
     454           1 :             REQUIRE(a.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL)           == "[::]:0/[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]");
     455             :         }
     456             : 
     457          18 :         SECTION("interface determination")
     458             :         {
     459           1 :             REQUIRE(addr::find_addr_interface(a, false) == nullptr);
     460           1 :             REQUIRE(addr::find_addr_interface(a, true) != nullptr);
     461             :         }
     462             : 
     463          18 :         SECTION("default name/service/port/protocol")
     464             :         {
     465           1 :             REQUIRE(a.get_name() == std::string());
     466           1 :             REQUIRE(a.get_service() == std::string());
     467           1 :             REQUIRE(a.get_port() == 0);
     468           1 :             REQUIRE(a.get_protocol() == IPPROTO_TCP);
     469             :         }
     470             : 
     471          18 :         SECTION("compare with self")
     472             :         {
     473           1 :             REQUIRE(a == a);
     474           1 :             REQUIRE_FALSE(a != a);
     475           1 :             REQUIRE_FALSE(a < a);
     476           1 :             REQUIRE(a <= a);
     477           1 :             REQUIRE_FALSE(a > a);
     478           1 :             REQUIRE(a >= a);
     479             :         }
     480             : 
     481          18 :         SECTION("compare with another 0.0.0.0")
     482             :         {
     483             :             {
     484           1 :                 addr::addr b;
     485             : 
     486           1 :                 REQUIRE(a == b);
     487           1 :                 REQUIRE_FALSE(a != b);
     488           1 :                 REQUIRE_FALSE(a < b);
     489           1 :                 REQUIRE(a <= b);
     490           1 :                 REQUIRE_FALSE(a > b);
     491           1 :                 REQUIRE(a >= b);
     492             :             }
     493             : 
     494             :             {
     495           1 :                 struct sockaddr_in6 in6 = sockaddr_in6();
     496           1 :                 in6.sin6_family = AF_INET6;
     497           1 :                 in6.sin6_port = htons(0);
     498           1 :                 in6.sin6_addr.s6_addr32[0] = htonl(0);
     499           1 :                 in6.sin6_addr.s6_addr32[1] = htonl(0);
     500           1 :                 in6.sin6_addr.s6_addr32[2] = htonl(0);
     501           1 :                 in6.sin6_addr.s6_addr32[3] = htonl(0);
     502           1 :                 addr::addr b(in6);
     503             : 
     504           1 :                 REQUIRE(a == b);
     505           1 :                 REQUIRE_FALSE(a != b);
     506           1 :                 REQUIRE_FALSE(a < b);
     507           1 :                 REQUIRE(a <= b);
     508           1 :                 REQUIRE_FALSE(a > b);
     509           1 :                 REQUIRE(a >= b);
     510             :             }
     511             : 
     512             :             // ANY in IPv4 != ANY in IPv6...
     513             :             // (i.e. IPv4 sets addr.sin6_addr.s6_addr16[5] == 0xFFFF)
     514             :             {
     515           1 :                 struct sockaddr_in in = sockaddr_in();
     516           1 :                 in.sin_family = AF_INET;
     517           1 :                 in.sin_port = htons(0);
     518           1 :                 in.sin_addr.s_addr = htonl(0);
     519           1 :                 addr::addr b(in);
     520             : 
     521           1 :                 REQUIRE_FALSE(a == b);
     522           1 :                 REQUIRE(a != b);
     523           1 :                 REQUIRE(a < b);
     524           1 :                 REQUIRE(a <= b);
     525           1 :                 REQUIRE_FALSE(a > b);
     526           1 :                 REQUIRE_FALSE(a >= b);
     527             :             }
     528             :         }
     529             : 
     530          18 :         SECTION("compare with IPv4 127.0.0.1")
     531             :         {
     532           1 :             struct sockaddr_in in = sockaddr_in();
     533           1 :             in.sin_family = AF_INET;
     534           1 :             in.sin_port = htons(80);
     535           1 :             in.sin_addr.s_addr = htonl((127 << 24) | 1);
     536           1 :             addr::addr b(in);
     537             : 
     538           1 :             REQUIRE_FALSE(a == b);
     539           1 :             REQUIRE(a != b);
     540           1 :             REQUIRE(a < b);
     541           1 :             REQUIRE(a <= b);
     542           1 :             REQUIRE_FALSE(a > b);
     543           1 :             REQUIRE_FALSE(a >= b);
     544             :         }
     545             :     }
     546           9 : }
     547             : 
     548             : 
     549          15 : TEST_CASE( "ipv4::address", "[ipv4]" )
     550             : {
     551          26 :     GIVEN("addr() with an IPv4")
     552             :     {
     553           3 :         addr::addr a;
     554             : 
     555           6 :         SECTION("set_ipv4() / get_ipv4()")
     556             :         {
     557          11 :             for(int idx(0); idx < 10; ++idx)
     558             :             {
     559          10 :                 struct sockaddr_in in = sockaddr_in();
     560          10 :                 in.sin_family = AF_INET;
     561          10 :                 in.sin_port = htons(rand());
     562          10 :                 in.sin_addr.s_addr = htonl(rand() ^ (rand() << 16));
     563             : 
     564             :                 // test constructor
     565             :                 //
     566          10 :                 addr::addr b(in);
     567             :                 struct sockaddr_in out;
     568          10 :                 b.get_ipv4(out);
     569          10 :                 REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
     570             : 
     571             :                 // test set
     572             :                 //
     573          10 :                 a.set_ipv4(in);
     574          10 :                 a.get_ipv4(out);
     575          10 :                 REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
     576             :             }
     577             :         }
     578             : 
     579           6 :         SECTION("set_ipv4() / to_ipv4_string()")
     580             :         {
     581          11 :             for(int idx(0); idx < 10; ++idx)
     582             :             {
     583          10 :                 struct sockaddr_in in = sockaddr_in();
     584          10 :                 in.sin_family = AF_INET;
     585          10 :                 uint16_t const port(rand());
     586          10 :                 in.sin_port = htons(port);
     587          10 :                 uint32_t const address(rand() ^ (rand() << 16));
     588          10 :                 in.sin_addr.s_addr = htonl(address);
     589             : 
     590             :                 std::string ip(
     591          20 :                           std::to_string((address >> 24) & 255)
     592          20 :                         + "."
     593          40 :                         + std::to_string((address >> 16) & 255)
     594          20 :                         + "."
     595          40 :                         + std::to_string((address >>  8) & 255)
     596          20 :                         + "."
     597          20 :                         + std::to_string((address >>  0) & 255)
     598          30 :                         );
     599          20 :                 std::string port_str(std::to_string(static_cast<int>(port)));
     600             : 
     601             :                 // check IPv4 as a string
     602             :                 //
     603          10 :                 a.set_ipv4(in);
     604          10 :                 REQUIRE(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY)          == ip);
     605          10 :                 REQUIRE(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_BRACKETS)      == ip);
     606          10 :                 REQUIRE(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_PORT)          == ip + ":" + port_str);
     607          10 :                 REQUIRE(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_MASK)          == ip + "/255.255.255.255"); // will change to 32 at some point
     608          10 :                 REQUIRE(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_BRACKETS_MASK) == ip + "/255.255.255.255");
     609          10 :                 REQUIRE(a.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL)           == ip + ":" + port_str + "/255.255.255.255");
     610             :             }
     611             :         }
     612             : 
     613           6 :         SECTION("name of various IPs")
     614             :         {
     615           1 :             struct sockaddr_in in = sockaddr_in();
     616           1 :             in.sin_family = AF_INET;
     617           1 :             in.sin_port = htons(rand());
     618           1 :             in.sin_addr.s_addr = 0;
     619             : 
     620             :             // verify network type
     621             :             //
     622           1 :             a.set_ipv4(in);
     623           1 :             REQUIRE(a.get_name() == std::string()); // no name for "any" (TCP)
     624             : 
     625           1 :             a.set_protocol(IPPROTO_UDP);
     626           1 :             REQUIRE(a.get_name() == std::string()); // no name for "any" (UDP)
     627             : 
     628           1 :             in.sin_addr.s_addr = htonl(0x7f000001);
     629           1 :             a.set_ipv4(in);
     630             :             char hostname[HOST_NAME_MAX + 1];
     631           1 :             hostname[HOST_NAME_MAX] = '\0';
     632           1 :             REQUIRE(gethostname(hostname, sizeof(hostname)) == 0);
     633           1 :             REQUIRE(hostname[0] != '\0');
     634           2 :             std::string localhost(a.get_name());
     635           1 :             bool const localhost_flag(localhost == hostname || localhost == "localhost");
     636           1 :             REQUIRE(localhost_flag);
     637             : 
     638           1 :             REQUIRE(addr::find_addr_interface(a, false) != nullptr);
     639             :         }
     640             :     }
     641             : 
     642          26 :     GIVEN("addr_parser() with IPv4 addresses")
     643             :     {
     644          14 :         SECTION("verify basics")
     645             :         {
     646           2 :             addr::addr_parser p;
     647           1 :             p.set_protocol(IPPROTO_TCP);
     648           1 :             REQUIRE(p.get_default_address4() == "");
     649           1 :             REQUIRE(p.get_default_address6() == "");
     650           1 :             REQUIRE(p.get_default_port() == -1);
     651           1 :             REQUIRE(p.get_default_mask4() == "");
     652           1 :             REQUIRE(p.get_default_mask6() == "");
     653           2 :             addr::addr_range::vector_t ips(p.parse("1.2.3.4"));
     654           1 :             REQUIRE_FALSE(p.has_errors());
     655           1 :             REQUIRE(ips.size() == 1);
     656           1 :             addr::addr_range const & r(ips[0]);
     657           1 :             REQUIRE(r.has_from());
     658           1 :             REQUIRE_FALSE(r.has_to());
     659           1 :             REQUIRE_FALSE(r.is_range());
     660           1 :             REQUIRE_FALSE(r.is_empty());
     661           1 :             addr::addr f(r.get_from());
     662           1 :             REQUIRE(f.is_ipv4());
     663           1 :             REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
     664           1 :             REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
     665           1 :             REQUIRE(f.get_port() == 0);
     666           1 :             REQUIRE(f.get_protocol() == IPPROTO_TCP);
     667           1 :             REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     668           1 :             uint8_t mask[16] = {};
     669           1 :             f.get_mask(mask);
     670          17 :             for(int idx(0); idx < 16; ++idx)
     671             :             {
     672          16 :                 REQUIRE(mask[idx] == 255);
     673             :             }
     674             :         }
     675             : 
     676          14 :         SECTION("verify default address")
     677             :         {
     678           2 :             addr::addr_parser p;
     679             : 
     680           1 :             p.set_default_address("1.5.19.200");
     681           1 :             REQUIRE(p.get_default_address4() == "1.5.19.200");
     682           1 :             REQUIRE(p.get_default_address6() == "");
     683           1 :             p.set_default_address("");
     684           1 :             REQUIRE(p.get_default_address4() == "");
     685           1 :             REQUIRE(p.get_default_address6() == "");
     686             : 
     687           1 :             p.set_default_address("1.5.19.200");
     688           1 :             REQUIRE(p.get_default_address4() == "1.5.19.200");
     689           1 :             REQUIRE(p.get_default_address6() == "");
     690           1 :             p.set_default_address("[4:5:4:5:7:8:7:8]");
     691           1 :             REQUIRE(p.get_default_address4() == "1.5.19.200");
     692           1 :             REQUIRE(p.get_default_address6() == "4:5:4:5:7:8:7:8");
     693           1 :             p.set_default_address("");
     694           1 :             REQUIRE(p.get_default_address4() == "");
     695           1 :             REQUIRE(p.get_default_address6() == "");
     696             :         }
     697             : 
     698          14 :         SECTION("verify default mask")
     699             :         {
     700           2 :             addr::addr_parser p;
     701             : 
     702           1 :             p.set_default_mask("1.5.19.200");
     703           1 :             REQUIRE(p.get_default_mask4() == "1.5.19.200");
     704           1 :             REQUIRE(p.get_default_mask6() == "");
     705           1 :             p.set_default_mask("");
     706           1 :             REQUIRE(p.get_default_mask4() == "");
     707           1 :             REQUIRE(p.get_default_mask6() == "");
     708             : 
     709           1 :             p.set_default_mask("1.5.19.200");
     710           1 :             REQUIRE(p.get_default_mask4() == "1.5.19.200");
     711           1 :             REQUIRE(p.get_default_mask6() == "");
     712           1 :             p.set_default_mask("[4:5:4:5:7:8:7:8]");
     713           1 :             REQUIRE(p.get_default_mask4() == "1.5.19.200");
     714           1 :             REQUIRE(p.get_default_mask6() == "4:5:4:5:7:8:7:8");
     715           1 :             p.set_default_mask("");
     716           1 :             REQUIRE(p.get_default_mask4() == "");
     717           1 :             REQUIRE(p.get_default_mask6() == "");
     718             :         }
     719             : 
     720          14 :         SECTION("verify default allow flags")
     721             :         {
     722           2 :             addr::addr_parser p;
     723             : 
     724          13 :             for(int idx(0); idx < static_cast<int>(addr::addr_parser::flag_t::FLAG_max); ++idx)
     725             :             {
     726          12 :                 switch(static_cast<addr::addr_parser::flag_t>(idx))
     727             :                 {
     728             :                 case addr::addr_parser::flag_t::ADDRESS:
     729             :                 case addr::addr_parser::flag_t::PORT:
     730             :                     // only the ADDRESS and PORT are true by default
     731             :                     //
     732           2 :                     REQUIRE(p.get_allow(static_cast<addr::addr_parser::flag_t>(idx)));
     733           2 :                     break;
     734             : 
     735             :                 default:
     736          10 :                     REQUIRE_FALSE(p.get_allow(static_cast<addr::addr_parser::flag_t>(idx)));
     737          10 :                     break;
     738             : 
     739             :                 }
     740             :             }
     741             :         }
     742             : 
     743          14 :         SECTION("verify contradictory flags")
     744             :         {
     745           2 :             addr::addr_parser p;
     746             : 
     747             :             // by default we start with false
     748             :             //
     749           1 :             REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
     750           1 :             REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES));
     751           1 :             REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
     752             : 
     753             :             // check setting MULTI_ADDRESSES_COMMAS to true
     754             :             //
     755           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS, true);
     756           1 :             REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
     757           1 :             REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES));
     758           1 :             REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
     759             : 
     760             :             // add MULTI_ADDRESSES_COMMAS_AND_SPACES
     761             :             //
     762           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES, true);
     763           1 :             REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
     764           1 :             REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES));
     765           1 :             REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
     766             : 
     767             :             // add MULTI_PORTS_COMMAS
     768             :             //
     769           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS, true);
     770           1 :             REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
     771           1 :             REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES));
     772           1 :             REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
     773             : 
     774             :             // add MULTI_ADDRESSES_COMMAS_AND_SPACES only
     775             :             //
     776           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES, true);
     777           1 :             REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
     778           1 :             REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES));
     779           1 :             REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
     780             : 
     781             :             // add MULTI_ADDRESSES_COMMAS second, order should not affect anything
     782             :             //
     783           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS, true);
     784           1 :             REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
     785           1 :             REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES));
     786           1 :             REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
     787             : 
     788             :             // back to MULTI_PORTS_COMMAS
     789             :             //
     790           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS, true);
     791           1 :             REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
     792           1 :             REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES));
     793           1 :             REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
     794             : 
     795             :             // add MULTI_ADDRESSES_COMMAS first now
     796             :             //
     797           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS, true);
     798           1 :             REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
     799           1 :             REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES));
     800           1 :             REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
     801             :         }
     802             : 
     803          14 :         SECTION("default address")
     804             :         {
     805           2 :             addr::addr_parser p;
     806           1 :             p.set_protocol(IPPROTO_TCP);
     807           1 :             p.set_default_address("5.5.5.5");
     808           1 :             REQUIRE(p.get_default_address4() == "5.5.5.5");
     809           1 :             REQUIRE(p.get_default_address6() == "");
     810           2 :             addr::addr_range::vector_t ips(p.parse(""));
     811           1 :             REQUIRE_FALSE(p.has_errors());
     812           1 :             REQUIRE(ips.size() == 1);
     813           1 :             addr::addr_range const & r(ips[0]);
     814           1 :             REQUIRE(r.has_from());
     815           1 :             REQUIRE_FALSE(r.has_to());
     816           1 :             REQUIRE_FALSE(r.is_range());
     817           1 :             REQUIRE_FALSE(r.is_empty());
     818           1 :             addr::addr f(r.get_from());
     819           1 :             REQUIRE(f.is_ipv4());
     820           1 :             REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.5.5.5");
     821           1 :             REQUIRE(f.get_port() == 0);
     822           1 :             REQUIRE(f.get_protocol() == IPPROTO_TCP);
     823           1 :             REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     824             :         }
     825             : 
     826          14 :         SECTION("address, not port allowed")
     827             :         {
     828             :             // specific address with a default
     829             :             {
     830           2 :                 addr::addr_parser p;
     831           1 :                 p.set_allow(addr::addr_parser::flag_t::PORT, false);
     832           1 :                 p.set_protocol(IPPROTO_TCP);
     833           1 :                 p.set_default_address("5.5.5.5");
     834           1 :                 REQUIRE(p.get_default_address4() == "5.5.5.5");
     835           1 :                 REQUIRE(p.get_default_address6() == "");
     836           2 :                 addr::addr_range::vector_t ips(p.parse("9.9.9.9"));
     837           1 :                 REQUIRE_FALSE(p.has_errors());
     838           1 :                 REQUIRE(ips.size() == 1);
     839           1 :                 addr::addr_range const & r(ips[0]);
     840           1 :                 REQUIRE(r.has_from());
     841           1 :                 REQUIRE_FALSE(r.has_to());
     842           1 :                 REQUIRE_FALSE(r.is_range());
     843           1 :                 REQUIRE_FALSE(r.is_empty());
     844           1 :                 addr::addr f(r.get_from());
     845           1 :                 REQUIRE(f.is_ipv4());
     846           1 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "9.9.9.9");
     847           1 :                 REQUIRE(f.get_port() == 0);
     848           1 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
     849           1 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     850             :             }
     851             : 
     852             :             // only a default address
     853             :             {
     854           2 :                 addr::addr_parser p;
     855           1 :                 p.set_allow(addr::addr_parser::flag_t::PORT, false);
     856           1 :                 p.set_protocol(IPPROTO_TCP);
     857           1 :                 p.set_default_address("5.5.5.5");
     858           1 :                 REQUIRE(p.get_default_address4() == "5.5.5.5");
     859           1 :                 REQUIRE(p.get_default_address6() == "");
     860           2 :                 addr::addr_range::vector_t ips(p.parse(""));
     861           1 :                 REQUIRE_FALSE(p.has_errors());
     862           1 :                 REQUIRE(ips.size() == 1);
     863           1 :                 addr::addr_range const & r(ips[0]);
     864           1 :                 REQUIRE(r.has_from());
     865           1 :                 REQUIRE_FALSE(r.has_to());
     866           1 :                 REQUIRE_FALSE(r.is_range());
     867           1 :                 REQUIRE_FALSE(r.is_empty());
     868           1 :                 addr::addr f(r.get_from());
     869           1 :                 REQUIRE(f.is_ipv4());
     870           1 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.5.5.5");
     871           1 :                 REQUIRE(f.get_port() == 0);
     872           1 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
     873           1 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     874             :             }
     875             :         }
     876             :     }
     877             : 
     878          26 :     GIVEN("addr_parser() with multiple IPv4 addresses in one string")
     879             :     {
     880           6 :         SECTION("3 IPs separated by commas")
     881             :         {
     882           2 :             addr::addr_parser p;
     883           1 :             p.set_protocol(IPPROTO_TCP);
     884           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS, true);
     885           2 :             addr::addr_range::vector_t ips(p.parse("1.2.3.4:55,5.6.7.8,,,,10.11.12.99:77"));
     886           1 :             REQUIRE_FALSE(p.has_errors());
     887           1 :             REQUIRE(ips.size() == 3);
     888             : 
     889           1 :             uint8_t mask[16] = {};
     890             : 
     891             :             // 1.2.3.4:55
     892             :             {
     893           1 :                 addr::addr_range const & r(ips[0]);
     894           1 :                 REQUIRE(r.has_from());
     895           1 :                 REQUIRE_FALSE(r.has_to());
     896           1 :                 REQUIRE_FALSE(r.is_range());
     897           1 :                 REQUIRE_FALSE(r.is_empty());
     898           1 :                 addr::addr f(r.get_from());
     899           1 :                 REQUIRE(f.is_ipv4());
     900           1 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
     901           1 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
     902           1 :                 REQUIRE(f.get_port() == 55);
     903           1 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
     904           1 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     905           1 :                 f.get_mask(mask);
     906          17 :                 for(int idx(0); idx < 16; ++idx)
     907             :                 {
     908          16 :                     REQUIRE(mask[idx] == 255);
     909             :                 }
     910             :             }
     911             : 
     912             :             // 5.6.7.8
     913             :             {
     914           1 :                 addr::addr_range const & r(ips[1]);
     915           1 :                 REQUIRE(r.has_from());
     916           1 :                 REQUIRE_FALSE(r.has_to());
     917           1 :                 REQUIRE_FALSE(r.is_range());
     918           1 :                 REQUIRE_FALSE(r.is_empty());
     919           1 :                 addr::addr f(r.get_from());
     920           1 :                 REQUIRE(f.is_ipv4());
     921           1 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
     922           1 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
     923           1 :                 REQUIRE(f.get_port() == 0);
     924           1 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
     925           1 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     926           1 :                 f.get_mask(mask);
     927          17 :                 for(int idx(0); idx < 16; ++idx)
     928             :                 {
     929          16 :                     REQUIRE(mask[idx] == 255);
     930             :                 }
     931             :             }
     932             : 
     933             :             // 10.11.12.99:77
     934             :             {
     935           1 :                 addr::addr_range const & r(ips[2]);
     936           1 :                 REQUIRE(r.has_from());
     937           1 :                 REQUIRE_FALSE(r.has_to());
     938           1 :                 REQUIRE_FALSE(r.is_range());
     939           1 :                 REQUIRE_FALSE(r.is_empty());
     940           1 :                 addr::addr f(r.get_from());
     941           1 :                 REQUIRE(f.is_ipv4());
     942           1 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
     943           1 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
     944           1 :                 REQUIRE(f.get_port() == 77);
     945           1 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
     946           1 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
     947           1 :                 f.get_mask(mask);
     948          17 :                 for(int idx(0); idx < 16; ++idx)
     949             :                 {
     950          16 :                     REQUIRE(mask[idx] == 255);
     951             :                 }
     952             :             }
     953             :         }
     954             : 
     955           6 :         SECTION("3 IPs separated by spaces")
     956             :         {
     957           2 :             addr::addr_parser p;
     958           1 :             p.set_protocol(IPPROTO_TCP);
     959           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_SPACES, true);
     960           2 :             addr::addr_range::vector_t ips(p.parse("1.2.3.4:55 5.6.7.8   10.11.12.99:77"));
     961           1 :             REQUIRE_FALSE(p.has_errors());
     962           1 :             REQUIRE(ips.size() == 3);
     963             : 
     964           1 :             uint8_t mask[16] = {};
     965             : 
     966             :             // 1.2.3.4:55
     967             :             {
     968           1 :                 addr::addr_range const & r(ips[0]);
     969           1 :                 REQUIRE(r.has_from());
     970           1 :                 REQUIRE_FALSE(r.has_to());
     971           1 :                 REQUIRE_FALSE(r.is_range());
     972           1 :                 REQUIRE_FALSE(r.is_empty());
     973           1 :                 addr::addr f(r.get_from());
     974           1 :                 REQUIRE(f.is_ipv4());
     975           1 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
     976           1 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
     977           1 :                 REQUIRE(f.get_port() == 55);
     978           1 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
     979           1 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     980           1 :                 f.get_mask(mask);
     981          17 :                 for(int idx(0); idx < 16; ++idx)
     982             :                 {
     983          16 :                     REQUIRE(mask[idx] == 255);
     984             :                 }
     985             :             }
     986             : 
     987             :             // 5.6.7.8
     988             :             {
     989           1 :                 addr::addr_range const & r(ips[1]);
     990           1 :                 REQUIRE(r.has_from());
     991           1 :                 REQUIRE_FALSE(r.has_to());
     992           1 :                 REQUIRE_FALSE(r.is_range());
     993           1 :                 REQUIRE_FALSE(r.is_empty());
     994           1 :                 addr::addr f(r.get_from());
     995           1 :                 REQUIRE(f.is_ipv4());
     996           1 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
     997           1 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
     998           1 :                 REQUIRE(f.get_port() == 0);
     999           1 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1000           1 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1001           1 :                 f.get_mask(mask);
    1002          17 :                 for(int idx(0); idx < 16; ++idx)
    1003             :                 {
    1004          16 :                     REQUIRE(mask[idx] == 255);
    1005             :                 }
    1006             :             }
    1007             : 
    1008             :             // 10.11.12.99:77
    1009             :             {
    1010           1 :                 addr::addr_range const & r(ips[2]);
    1011           1 :                 REQUIRE(r.has_from());
    1012           1 :                 REQUIRE_FALSE(r.has_to());
    1013           1 :                 REQUIRE_FALSE(r.is_range());
    1014           1 :                 REQUIRE_FALSE(r.is_empty());
    1015           1 :                 addr::addr f(r.get_from());
    1016           1 :                 REQUIRE(f.is_ipv4());
    1017           1 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
    1018           1 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
    1019           1 :                 REQUIRE(f.get_port() == 77);
    1020           1 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1021           1 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1022           1 :                 f.get_mask(mask);
    1023          17 :                 for(int idx(0); idx < 16; ++idx)
    1024             :                 {
    1025          16 :                     REQUIRE(mask[idx] == 255);
    1026             :                 }
    1027             :             }
    1028             :         }
    1029             : 
    1030           6 :         SECTION("3 IPs separated by commas and/or spaces")
    1031             :         {
    1032           2 :             addr::addr_parser p;
    1033           1 :             p.set_protocol(IPPROTO_TCP);
    1034           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS_AND_SPACES, true);
    1035           2 :             addr::addr_range::vector_t ips(p.parse(" 1.2.3.4:55,, 5.6.7.8 , 10.11.12.99:77 "));
    1036           1 :             REQUIRE_FALSE(p.has_errors());
    1037           1 :             REQUIRE(ips.size() == 3);
    1038             : 
    1039           1 :             uint8_t mask[16] = {};
    1040             : 
    1041             :             // 1.2.3.4:55
    1042             :             {
    1043           1 :                 addr::addr_range const & r(ips[0]);
    1044           1 :                 REQUIRE(r.has_from());
    1045           1 :                 REQUIRE_FALSE(r.has_to());
    1046           1 :                 REQUIRE_FALSE(r.is_range());
    1047           1 :                 REQUIRE_FALSE(r.is_empty());
    1048           1 :                 addr::addr f(r.get_from());
    1049           1 :                 REQUIRE(f.is_ipv4());
    1050           1 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
    1051           1 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
    1052           1 :                 REQUIRE(f.get_port() == 55);
    1053           1 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1054           1 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1055           1 :                 f.get_mask(mask);
    1056          17 :                 for(int idx(0); idx < 16; ++idx)
    1057             :                 {
    1058          16 :                     REQUIRE(mask[idx] == 255);
    1059             :                 }
    1060             :             }
    1061             : 
    1062             :             // 5.6.7.8
    1063             :             {
    1064           1 :                 addr::addr_range const & r(ips[1]);
    1065           1 :                 REQUIRE(r.has_from());
    1066           1 :                 REQUIRE_FALSE(r.has_to());
    1067           1 :                 REQUIRE_FALSE(r.is_range());
    1068           1 :                 REQUIRE_FALSE(r.is_empty());
    1069           1 :                 addr::addr f(r.get_from());
    1070           1 :                 REQUIRE(f.is_ipv4());
    1071           1 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
    1072           1 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
    1073           1 :                 REQUIRE(f.get_port() == 0);
    1074           1 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1075           1 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1076           1 :                 f.get_mask(mask);
    1077          17 :                 for(int idx(0); idx < 16; ++idx)
    1078             :                 {
    1079          16 :                     REQUIRE(mask[idx] == 255);
    1080             :                 }
    1081             :             }
    1082             : 
    1083             :             // 10.11.12.99:77
    1084             :             {
    1085           1 :                 addr::addr_range const & r(ips[2]);
    1086           1 :                 REQUIRE(r.has_from());
    1087           1 :                 REQUIRE_FALSE(r.has_to());
    1088           1 :                 REQUIRE_FALSE(r.is_range());
    1089           1 :                 REQUIRE_FALSE(r.is_empty());
    1090           1 :                 addr::addr f(r.get_from());
    1091           1 :                 REQUIRE(f.is_ipv4());
    1092           1 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
    1093           1 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
    1094           1 :                 REQUIRE(f.get_port() == 77);
    1095           1 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1096           1 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1097           1 :                 f.get_mask(mask);
    1098          17 :                 for(int idx(0); idx < 16; ++idx)
    1099             :                 {
    1100          16 :                     REQUIRE(mask[idx] == 255);
    1101             :                 }
    1102             :             }
    1103             :         }
    1104             :     }
    1105          13 : }
    1106             : 
    1107             : 
    1108           5 : TEST_CASE( "ipv4::ports", "[ipv4]" )
    1109             : {
    1110           6 :     GIVEN("addr_parser() with IPv4 addresses and port")
    1111             :     {
    1112           6 :         SECTION("verify port")
    1113             :         {
    1114       65537 :             for(int port(0); port < 65536; ++port)
    1115             :             {
    1116       65536 :                 int proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1117      131072 :                 addr::addr_parser p;
    1118       65536 :                 p.set_protocol(proto);
    1119      131072 :                 addr::addr_range::vector_t ips(p.parse("192.168.12.199:" + std::to_string(port)));
    1120       65536 :                 REQUIRE_FALSE(p.has_errors());
    1121       65536 :                 REQUIRE(ips.size() == 1);
    1122       65536 :                 addr::addr_range const & r(ips[0]);
    1123       65536 :                 addr::addr f(r.get_from());
    1124       65536 :                 REQUIRE(f.is_ipv4());
    1125       65536 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "192.168.12.199");
    1126       65536 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "192.168.12.199");
    1127       65536 :                 REQUIRE(f.get_port() == port);
    1128       65536 :                 REQUIRE(f.get_protocol() == proto);
    1129       65536 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1130             :             }
    1131             :         }
    1132             : 
    1133           6 :         SECTION("default address with various port")
    1134             :         {
    1135         101 :             for(int idx(0); idx < 100; ++idx)
    1136             :             {
    1137         100 :                 uint16_t const port(rand());
    1138         200 :                 addr::addr_parser p;
    1139         100 :                 p.set_protocol(IPPROTO_TCP);
    1140         100 :                 p.set_default_address("5.5.5.5");
    1141         100 :                 REQUIRE(p.get_default_address4() == "5.5.5.5");
    1142         100 :                 REQUIRE(p.get_default_address6() == "");
    1143         200 :                 addr::addr_range::vector_t ips(p.parse(":" + std::to_string(static_cast<int>(port))));
    1144         100 :                 REQUIRE_FALSE(p.has_errors());
    1145         100 :                 REQUIRE(ips.size() == 1);
    1146         100 :                 addr::addr_range const & r(ips[0]);
    1147         100 :                 REQUIRE(r.has_from());
    1148         100 :                 REQUIRE_FALSE(r.has_to());
    1149         100 :                 REQUIRE_FALSE(r.is_range());
    1150         100 :                 REQUIRE_FALSE(r.is_empty());
    1151         100 :                 addr::addr f(r.get_from());
    1152         100 :                 REQUIRE(f.is_ipv4());
    1153         100 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
    1154         100 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
    1155         100 :                 REQUIRE(f.get_port() == port);
    1156         100 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1157         100 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1158             :             }
    1159             :         }
    1160             : 
    1161           6 :         SECTION("address with default port")
    1162             :         {
    1163          26 :             for(int idx(0); idx < 25; ++idx)
    1164             :             {
    1165          25 :                 uint16_t const port(rand());
    1166          50 :                 addr::addr_parser p;
    1167          25 :                 p.set_protocol(IPPROTO_TCP);
    1168          25 :                 p.set_default_port(port);
    1169          25 :                 REQUIRE(p.get_default_port() == port);
    1170          50 :                 addr::addr_range::vector_t ips(p.parse("5.5.5.5"));
    1171          25 :                 REQUIRE_FALSE(p.has_errors());
    1172          25 :                 REQUIRE(ips.size() == 1);
    1173          25 :                 addr::addr_range const & r(ips[0]);
    1174          25 :                 REQUIRE(r.has_from());
    1175          25 :                 REQUIRE_FALSE(r.has_to());
    1176          25 :                 REQUIRE_FALSE(r.is_range());
    1177          25 :                 REQUIRE_FALSE(r.is_empty());
    1178          25 :                 addr::addr f(r.get_from());
    1179          25 :                 REQUIRE(f.is_ipv4());
    1180          25 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
    1181          25 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
    1182          25 :                 REQUIRE(f.get_port() == port);
    1183          25 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1184          25 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1185             :             }
    1186             : 
    1187          26 :             for(int idx(0); idx < 25; ++idx)
    1188             :             {
    1189          25 :                 uint16_t const port(rand());
    1190          50 :                 addr::addr_parser p;
    1191          25 :                 p.set_protocol(IPPROTO_TCP);
    1192          25 :                 p.set_default_port(port);
    1193          25 :                 REQUIRE(p.get_default_port() == port);
    1194          50 :                 addr::addr_range::vector_t ips(p.parse("5.5.5.5:"));
    1195          25 :                 REQUIRE_FALSE(p.has_errors());
    1196          25 :                 REQUIRE(ips.size() == 1);
    1197          25 :                 addr::addr_range const & r(ips[0]);
    1198          25 :                 REQUIRE(r.has_from());
    1199          25 :                 REQUIRE_FALSE(r.has_to());
    1200          25 :                 REQUIRE_FALSE(r.is_range());
    1201          25 :                 REQUIRE_FALSE(r.is_empty());
    1202          25 :                 addr::addr f(r.get_from());
    1203          25 :                 REQUIRE(f.is_ipv4());
    1204          25 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
    1205          25 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
    1206          25 :                 REQUIRE(f.get_port() == port);
    1207          25 :                 REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1208          25 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1209             :             }
    1210             :         }
    1211             :     }
    1212           3 : }
    1213             : 
    1214             : 
    1215           9 : TEST_CASE( "ipv4::masks", "[ipv4]" )
    1216             : {
    1217          14 :     GIVEN("addr_parser() of address:port/mask")
    1218             :     {
    1219          14 :         SECTION("mask allowed, but no mask")
    1220             :         {
    1221           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1222           1 :             int const port(rand() & 0xFFFF);
    1223           2 :             addr::addr_parser p;
    1224           1 :             p.set_protocol(proto);
    1225           1 :             p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1226           2 :             addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port)));
    1227           1 :             REQUIRE_FALSE(p.has_errors());
    1228           1 :             REQUIRE(ips.size() == 1);
    1229           1 :             addr::addr_range const & r(ips[0]);
    1230           1 :             addr::addr f(r.get_from());
    1231           1 :             REQUIRE(f.is_ipv4());
    1232           2 :             std::string result("172.19.6.91:" + std::to_string(port) + "/255.255.255.255");
    1233           1 :             REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1234           1 :             REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1235           1 :             REQUIRE(f.get_port() == port);
    1236           1 :             REQUIRE(f.get_protocol() == proto);
    1237           1 :             REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1238             :         }
    1239             : 
    1240          14 :         SECTION("empty mask")
    1241             :         {
    1242           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1243           1 :             int const port(rand() & 0xFFFF);
    1244           2 :             addr::addr_parser p;
    1245           1 :             p.set_protocol(proto);
    1246           1 :             p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1247           2 :             addr::addr_range::vector_t ips(p.parse("172.18.5.91:" + std::to_string(port) + "/"));
    1248           1 :             REQUIRE_FALSE(p.has_errors());
    1249           1 :             REQUIRE(ips.size() == 1);
    1250           1 :             addr::addr_range const & r(ips[0]);
    1251           1 :             addr::addr f(r.get_from());
    1252           1 :             REQUIRE(f.is_ipv4());
    1253           2 :             std::string result("172.18.5.91:" + std::to_string(port) + "/255.255.255.255");
    1254           1 :             REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1255           1 :             REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1256           1 :             REQUIRE(f.get_port() == port);
    1257           1 :             REQUIRE(f.get_protocol() == proto);
    1258           1 :             REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1259             :         }
    1260             : 
    1261          14 :         SECTION("one number masks")
    1262             :         {
    1263          34 :             for(int idx(0); idx <= 32; ++idx)
    1264             :             {
    1265          33 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1266          33 :                 int const port(rand() & 0xFFFF);
    1267          66 :                 addr::addr_parser p;
    1268          33 :                 p.set_protocol(proto);
    1269          33 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1270          66 :                 addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port) + "/" + std::to_string(idx)));
    1271          33 :                 REQUIRE_FALSE(p.has_errors());
    1272          33 :                 REQUIRE(ips.size() == 1);
    1273          33 :                 addr::addr_range const & r(ips[0]);
    1274          33 :                 addr::addr f(r.get_from());
    1275          33 :                 REQUIRE(f.is_ipv4());
    1276          33 :                 uint64_t const mask(std::numeric_limits<uint64_t>::max() << (32 - idx));
    1277             :                 std::string mask_str(
    1278          66 :                           std::to_string((mask >> 24) & 255)
    1279          66 :                         + "."
    1280         132 :                         + std::to_string((mask >> 16) & 255)
    1281          66 :                         + "."
    1282         132 :                         + std::to_string((mask >>  8) & 255)
    1283          66 :                         + "."
    1284         132 :                         + std::to_string((mask >>  0) & 255));
    1285          66 :                 std::string result("172.17.3.91:" + std::to_string(port) + "/" + mask_str);
    1286          33 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1287          33 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1288          33 :                 REQUIRE(f.get_port() == port);
    1289          33 :                 REQUIRE(f.get_protocol() == proto);
    1290          33 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1291             :             }
    1292             :         }
    1293             : 
    1294          14 :         SECTION("address like mask")
    1295             :         {
    1296          26 :             for(int idx(0); idx < 25; ++idx)
    1297             :             {
    1298          25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1299          25 :                 int const port(rand() & 0xFFFF);
    1300          50 :                 addr::addr_parser p;
    1301          25 :                 p.set_protocol(proto);
    1302          25 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1303             :                 // when specified as an IP, the mask can be absolutely anything
    1304             :                 uint8_t mask[4];
    1305         125 :                 for(int j(0); j < 4; ++j)
    1306             :                 {
    1307         100 :                     mask[j] = rand();
    1308             :                 }
    1309             :                 std::string const mask_str(
    1310          50 :                               std::to_string(static_cast<int>(mask[0]))
    1311          50 :                             + "."
    1312         100 :                             + std::to_string(static_cast<int>(mask[1]))
    1313          50 :                             + "."
    1314         100 :                             + std::to_string(static_cast<int>(mask[2]))
    1315          50 :                             + "."
    1316         100 :                             + std::to_string(static_cast<int>(mask[3])));
    1317          50 :                 addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port) + "/" + mask_str));
    1318          25 :                 REQUIRE_FALSE(p.has_errors());
    1319          25 :                 REQUIRE(ips.size() == 1);
    1320          25 :                 addr::addr_range const & r(ips[0]);
    1321          25 :                 addr::addr f(r.get_from());
    1322          25 :                 REQUIRE(f.is_ipv4());
    1323          50 :                 std::string result("172.17.3.91:" + std::to_string(port) + "/" + mask_str);
    1324          25 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1325          25 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1326          25 :                 REQUIRE(f.get_port() == port);
    1327          25 :                 REQUIRE(f.get_protocol() == proto);
    1328          25 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1329             :             }
    1330             :         }
    1331             : 
    1332          14 :         SECTION("address like default mask")
    1333             :         {
    1334          26 :             for(int idx(0); idx < 25; ++idx)
    1335             :             {
    1336          25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1337          25 :                 int const port(rand() & 0xFFFF);
    1338          50 :                 addr::addr_parser p;
    1339          25 :                 p.set_protocol(proto);
    1340          25 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1341             :                 // when specified as an IP, the mask can be absolutely anything
    1342             :                 // (here the mask is a string an it will be parsed by the
    1343             :                 // parser if required)
    1344             :                 //
    1345             :                 uint8_t mask[4];
    1346         125 :                 for(int j(0); j < 4; ++j)
    1347             :                 {
    1348         100 :                     mask[j] = rand();
    1349             :                 }
    1350             :                 std::string const mask_str(
    1351          50 :                               std::to_string(static_cast<int>(mask[0]))
    1352          50 :                             + "."
    1353         100 :                             + std::to_string(static_cast<int>(mask[1]))
    1354          50 :                             + "."
    1355         100 :                             + std::to_string(static_cast<int>(mask[2]))
    1356          50 :                             + "."
    1357         100 :                             + std::to_string(static_cast<int>(mask[3])));
    1358          25 :                 p.set_default_mask(mask_str);
    1359          50 :                 addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port)));
    1360          25 :                 REQUIRE_FALSE(p.has_errors());
    1361          25 :                 REQUIRE(ips.size() == 1);
    1362          25 :                 addr::addr_range const & r(ips[0]);
    1363          25 :                 addr::addr f(r.get_from());
    1364          25 :                 REQUIRE(f.is_ipv4());
    1365          50 :                 std::string result("172.17.3.91:" + std::to_string(port) + "/" + mask_str);
    1366          25 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1367          25 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1368          25 :                 REQUIRE(f.get_port() == port);
    1369          25 :                 REQUIRE(f.get_protocol() == proto);
    1370          25 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1371             :                 uint8_t verify_mask[16];
    1372          25 :                 f.get_mask(verify_mask);
    1373         325 :                 for(int j(0); j < 16 - 4; ++j)
    1374             :                 {
    1375         300 :                     REQUIRE(verify_mask[j] == 255);
    1376             :                 }
    1377         125 :                 for(int j(12); j < 16; ++j)
    1378             :                 {
    1379         100 :                     REQUIRE(verify_mask[j] == mask[j - 12]);
    1380             :                 }
    1381             :             }
    1382             :         }
    1383             : 
    1384          14 :         SECTION("address like mask with a default")
    1385             :         {
    1386          26 :             for(int idx(0); idx < 25; ++idx)
    1387             :             {
    1388          25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1389          25 :                 int const port(rand() & 0xFFFF);
    1390          50 :                 addr::addr_parser p;
    1391          25 :                 p.set_protocol(proto);
    1392          25 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1393             : 
    1394             :                 // here we want a default and an IP with a specific mask
    1395             :                 // to make sure that the specific mask has priority
    1396             :                 //
    1397             :                 uint8_t mask[4];
    1398         125 :                 for(int j(0); j < 4; ++j)
    1399             :                 {
    1400         100 :                     mask[j] = rand();
    1401             :                 }
    1402             :                 std::string const mask_str(
    1403          50 :                               std::to_string(static_cast<int>(mask[0]))
    1404          50 :                             + "."
    1405         100 :                             + std::to_string(static_cast<int>(mask[1]))
    1406          50 :                             + "."
    1407         100 :                             + std::to_string(static_cast<int>(mask[2]))
    1408          50 :                             + "."
    1409         100 :                             + std::to_string(static_cast<int>(mask[3])));
    1410             : 
    1411             :                 uint8_t default_mask[4];
    1412         125 :                 for(int j(0); j < 4; ++j)
    1413             :                 {
    1414         100 :                     default_mask[j] = rand();
    1415             :                 }
    1416             :                 std::string const default_mask_str(
    1417          50 :                               std::to_string(static_cast<int>(default_mask[0]))
    1418          50 :                             + "."
    1419         100 :                             + std::to_string(static_cast<int>(default_mask[1]))
    1420          50 :                             + "."
    1421         100 :                             + std::to_string(static_cast<int>(default_mask[2]))
    1422          50 :                             + "."
    1423         100 :                             + std::to_string(static_cast<int>(default_mask[3])));
    1424          25 :                 p.set_default_mask(default_mask_str);
    1425             : 
    1426          50 :                 addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port) + "/" + mask_str));
    1427          25 :                 REQUIRE_FALSE(p.has_errors());
    1428          25 :                 REQUIRE(ips.size() == 1);
    1429          25 :                 addr::addr_range const & r(ips[0]);
    1430          25 :                 addr::addr f(r.get_from());
    1431          25 :                 REQUIRE(f.is_ipv4());
    1432          50 :                 std::string result("172.17.3.91:" + std::to_string(port) + "/" + mask_str);
    1433          25 :                 REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1434          25 :                 REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1435          25 :                 REQUIRE(f.get_port() == port);
    1436          25 :                 REQUIRE(f.get_protocol() == proto);
    1437          25 :                 REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1438             :                 uint8_t verify_mask[16];
    1439          25 :                 f.get_mask(verify_mask);
    1440         325 :                 for(int j(0); j < 16 - 4; ++j)
    1441             :                 {
    1442         300 :                     REQUIRE(verify_mask[j] == 255);
    1443             :                 }
    1444         125 :                 for(int j(12); j < 16; ++j)
    1445             :                 {
    1446         100 :                     REQUIRE(verify_mask[j] == mask[j - 12]);
    1447             :                 }
    1448             :             }
    1449             :         }
    1450             : 
    1451          14 :         SECTION("two addresses and a mask for a match / no match")
    1452             :         {
    1453           1 :             int const port1(rand() & 0xFFFF);
    1454           2 :             addr::addr_parser p;
    1455           1 :             p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1456             : 
    1457             :             // parse the IP with a mask
    1458             :             //
    1459           1 :             int proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1460           1 :             p.set_protocol(proto);
    1461           2 :             addr::addr_range::vector_t ips1(p.parse("192.168.0.0:" + std::to_string(port1) + "/16"));
    1462           1 :             REQUIRE_FALSE(p.has_errors());
    1463           1 :             REQUIRE(ips1.size() == 1);
    1464           1 :             addr::addr_range const & r1(ips1[0]);
    1465           1 :             addr::addr f1(r1.get_from());
    1466           1 :             REQUIRE(f1.is_ipv4());
    1467           1 :             REQUIRE(f1.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == "192.168.0.0:" + std::to_string(port1) + "/255.255.0.0");
    1468           1 :             REQUIRE(f1.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == "192.168.0.0:" + std::to_string(port1) + "/255.255.0.0");
    1469           1 :             REQUIRE(f1.get_port() == port1);
    1470           1 :             REQUIRE(f1.get_protocol() == proto);
    1471           1 :             REQUIRE(f1.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1472             : 
    1473             :             // reuse parser
    1474             :             //
    1475           1 :             proto = rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP;
    1476           1 :             p.set_protocol(proto);
    1477           1 :             int const port2(rand() & 0xFFFF);
    1478           2 :             addr::addr_range::vector_t ips2(p.parse("192.168.5.36:" + std::to_string(port2)));
    1479           1 :             REQUIRE_FALSE(p.has_errors());
    1480           1 :             REQUIRE(ips2.size() == 1);
    1481           1 :             addr::addr_range const & r2(ips2[0]);
    1482           1 :             addr::addr f2(r2.get_from());
    1483           1 :             REQUIRE(f2.is_ipv4());
    1484           1 :             REQUIRE(f2.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == "192.168.5.36:" + std::to_string(port2) + "/255.255.255.255");
    1485           1 :             REQUIRE(f2.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == "192.168.5.36:" + std::to_string(port2) + "/255.255.255.255");
    1486           1 :             REQUIRE(f2.get_port() == port2);
    1487           1 :             REQUIRE(f2.get_protocol() == proto);
    1488           1 :             REQUIRE(f2.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1489             : 
    1490             :             // 3rd with a mask along the full IP
    1491             :             //
    1492           1 :             proto = rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP;
    1493           1 :             p.set_protocol(proto);
    1494           1 :             int const port3(rand() & 0xFFFF);
    1495           2 :             addr::addr_range::vector_t ips3(p.parse("192.168.5.36:" + std::to_string(port3) + "/16"));
    1496           1 :             REQUIRE_FALSE(p.has_errors());
    1497           1 :             REQUIRE(ips3.size() == 1);
    1498           1 :             addr::addr_range const & r3(ips3[0]);
    1499           1 :             addr::addr f3(r3.get_from());
    1500           1 :             REQUIRE(f3.is_ipv4());
    1501           1 :             REQUIRE(f3.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == "192.168.5.36:" + std::to_string(port3) + "/255.255.0.0");
    1502           1 :             REQUIRE(f3.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == "192.168.5.36:" + std::to_string(port3) + "/255.255.0.0");
    1503           1 :             REQUIRE(f3.get_port() == port3);
    1504           1 :             REQUIRE(f3.get_protocol() == proto);
    1505           1 :             REQUIRE(f3.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1506             : 
    1507             :             // just a side test
    1508             :             //
    1509           1 :             REQUIRE(f1 != f2);
    1510           1 :             REQUIRE(f1 != f3);
    1511           1 :             REQUIRE(f2 == f3);
    1512             : 
    1513             :             // check whether p1 matches p2 and vice versa
    1514             :             //
    1515           1 :             REQUIRE(f1.match(f2));          // f2 & mask1 == f1
    1516           1 :             REQUIRE(f1.match(f3));          // f3 & mask1 == f1
    1517             : 
    1518           1 :             REQUIRE_FALSE(f2.match(f1));    // f1 & mask2 != f2
    1519           1 :             REQUIRE(f2.match(f3));          // f3 & mask2 == f2  (because f2 == f3 anyway)
    1520             : 
    1521           1 :             REQUIRE(f3.match(f1));          // f1 & mask3 == f3
    1522           1 :             REQUIRE(f3.match(f2));          // f2 & mask3 == f3
    1523             : 
    1524           1 :             f3.apply_mask();
    1525             : 
    1526           1 :             REQUIRE(f1 != f2);
    1527           1 :             REQUIRE(f1 == f3);
    1528           1 :             REQUIRE(f2 != f3);
    1529             : 
    1530             :             // re-run the match() calls with f3 since it changed...
    1531             :             //
    1532           1 :             REQUIRE(f1.match(f3));          // f3 & mask1 == f1
    1533             : 
    1534           1 :             REQUIRE_FALSE(f2.match(f3));    // f3 & mask2 == f2  (because f2 != f3 anymore)
    1535             : 
    1536           1 :             REQUIRE(f3.match(f1));          // f1 & mask3 == f3
    1537           1 :             REQUIRE(f3.match(f2));          // f2 & mask3 == f3
    1538             :         }
    1539             :     }
    1540           7 : }
    1541             : 
    1542             : 
    1543           8 : TEST_CASE( "ipv4::protocol", "[ipv4]" )
    1544             : {
    1545          12 :     GIVEN("addr()")
    1546             :     {
    1547           2 :         addr::addr a;
    1548             : 
    1549           4 :         SECTION("default protocol")
    1550             :         {
    1551           1 :             REQUIRE(a.get_protocol() == IPPROTO_TCP);
    1552             :         }
    1553             : 
    1554           4 :         SECTION("set_protocol()")
    1555             :         {
    1556             :             // setup a random protocol
    1557             :             //
    1558           1 :             int const start_protocol([]()
    1559             :                 {
    1560           1 :                     switch(rand() % 3)
    1561             :                     {
    1562             :                     case 0:
    1563           0 :                         return IPPROTO_IP;
    1564             : 
    1565             :                     case 1:
    1566           0 :                         return IPPROTO_TCP;
    1567             : 
    1568             :                     //case 2:
    1569             :                     default:
    1570           1 :                         return IPPROTO_UDP;
    1571             : 
    1572             :                     }
    1573           1 :                 }());
    1574           1 :             a.set_protocol(start_protocol);
    1575             : 
    1576             :             // test 100 invalid protocols
    1577             :             //
    1578         101 :             for(int idx(0); idx < 100; ++idx)
    1579             :             {
    1580             :                 int invalid_protocol;
    1581           0 :                 do
    1582             :                 {
    1583         100 :                     invalid_protocol = rand();
    1584             :                 }
    1585             :                 while(invalid_protocol == IPPROTO_IP
    1586         100 :                    || invalid_protocol == IPPROTO_TCP
    1587         200 :                    || invalid_protocol == IPPROTO_UDP);
    1588         100 :                 REQUIRE_THROWS_AS(a.set_protocol(invalid_protocol), addr::addr_invalid_argument_exception);
    1589             : 
    1590             :                 // make sure the protocol does not change on errors
    1591         100 :                 REQUIRE(a.get_protocol() == start_protocol);
    1592             :             }
    1593             : 
    1594             :             // null string is not allowed
    1595             :             //
    1596           1 :             REQUIRE_THROWS_AS(a.set_protocol(nullptr), addr::addr_invalid_argument_exception);
    1597             : 
    1598             :             // other "invalid" (unsupported, really) string protocols
    1599             :             //
    1600           1 :             REQUIRE_THROWS_AS(a.set_protocol("icmp"), addr::addr_invalid_argument_exception);
    1601           1 :             REQUIRE_THROWS_AS(a.set_protocol("raw"), addr::addr_invalid_argument_exception);
    1602           1 :             REQUIRE_THROWS_AS(a.set_protocol("hmp"), addr::addr_invalid_argument_exception);
    1603             : 
    1604             :             // test all valid protocols (numeric)
    1605             :             //
    1606           1 :             a.set_protocol(IPPROTO_IP);
    1607           1 :             REQUIRE(a.get_protocol() == IPPROTO_IP);
    1608           1 :             a.set_protocol(IPPROTO_TCP);
    1609           1 :             REQUIRE(a.get_protocol() == IPPROTO_TCP);
    1610           1 :             a.set_protocol(IPPROTO_UDP);
    1611           1 :             REQUIRE(a.get_protocol() == IPPROTO_UDP);
    1612             : 
    1613             :             // test all valid protocols (ascii)
    1614             :             //
    1615           1 :             a.set_protocol("ip");
    1616           1 :             REQUIRE(a.get_protocol() == IPPROTO_IP);
    1617           1 :             a.set_protocol("tcp");
    1618           1 :             REQUIRE(a.get_protocol() == IPPROTO_TCP);
    1619           1 :             a.set_protocol("udp");
    1620           1 :             REQUIRE(a.get_protocol() == IPPROTO_UDP);
    1621             :         }
    1622             :     }
    1623             : 
    1624          12 :     GIVEN("addr_parser()")
    1625             :     {
    1626           6 :         addr::addr_parser p;
    1627             : 
    1628           6 :         SECTION("verify default")
    1629             :         {
    1630           1 :             REQUIRE(p.get_protocol() == -1);
    1631             :         }
    1632             : 
    1633           6 :         SECTION("test 3 allowed protocols")
    1634             :         {
    1635             :             // by string
    1636             :             //
    1637           1 :             p.set_protocol("ip");
    1638           1 :             REQUIRE(p.get_protocol() == IPPROTO_IP);
    1639           1 :             p.set_protocol("tcp");
    1640           1 :             REQUIRE(p.get_protocol() == IPPROTO_TCP);
    1641           1 :             p.set_protocol("udp");
    1642           1 :             REQUIRE(p.get_protocol() == IPPROTO_UDP);
    1643             : 
    1644             :             // numerically
    1645             :             //
    1646           1 :             p.set_protocol(IPPROTO_IP);
    1647           1 :             REQUIRE(p.get_protocol() == IPPROTO_IP);
    1648           1 :             p.set_protocol(IPPROTO_TCP);
    1649           1 :             REQUIRE(p.get_protocol() == IPPROTO_TCP);
    1650           1 :             p.set_protocol(IPPROTO_UDP);
    1651           1 :             REQUIRE(p.get_protocol() == IPPROTO_UDP);
    1652             :         }
    1653             : 
    1654           6 :         SECTION("verify clearing works")
    1655             :         {
    1656           1 :             p.set_protocol("ip");
    1657           1 :             REQUIRE(p.get_protocol() == IPPROTO_IP);
    1658           1 :             p.clear_protocol();
    1659           1 :             REQUIRE(p.get_protocol() == -1);
    1660             : 
    1661           1 :             p.set_protocol("tcp");
    1662           1 :             REQUIRE(p.get_protocol() == IPPROTO_TCP);
    1663           1 :             p.clear_protocol();
    1664           1 :             REQUIRE(p.get_protocol() == -1);
    1665             : 
    1666           1 :             p.set_protocol("udp");
    1667           1 :             REQUIRE(p.get_protocol() == IPPROTO_UDP);
    1668           1 :             p.clear_protocol();
    1669           1 :             REQUIRE(p.get_protocol() == -1);
    1670             :         }
    1671             :     }
    1672             : 
    1673          12 :     GIVEN("addr_parser with any protocol")
    1674             :     {
    1675           1 :         addr::addr a;
    1676             : 
    1677           2 :         SECTION("get address with all protocols")
    1678             :         {
    1679           2 :             addr::addr_parser p;
    1680             :             //p.set_protocol(...); -- by default we'll get all the protocols supported
    1681           2 :             addr::addr_range::vector_t ips(p.parse("127.0.0.1"));
    1682           1 :             REQUIRE_FALSE(p.has_errors());
    1683           1 :             REQUIRE(!ips.empty());
    1684           4 :             for(size_t idx(0); idx < ips.size(); ++idx)
    1685             :             {
    1686           3 :                 addr::addr_range const & r(ips[idx]);
    1687           3 :                 REQUIRE(r.has_from());
    1688           3 :                 REQUIRE_FALSE(r.has_to());
    1689           3 :                 REQUIRE_FALSE(r.is_range());
    1690           3 :                 REQUIRE_FALSE(r.is_empty());
    1691           3 :                 addr::addr f(r.get_from());
    1692           3 :                 if(f.is_ipv4())
    1693             :                 {
    1694           3 :                     REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "127.0.0.1");
    1695           3 :                     REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "127.0.0.1");
    1696           3 :                     REQUIRE(f.get_port() == 0);
    1697             :                     //REQUIRE(f.get_protocol() == ...); -- may be TCP, UDP, IP
    1698           3 :                     REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LOOPBACK);
    1699             :                 }
    1700             :                 else
    1701             :                 {
    1702           0 :                     REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::1");
    1703           0 :                     REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::1");
    1704           0 :                     REQUIRE(f.get_port() == 0);
    1705             :                     //REQUIRE(f.get_protocol() == ...); -- may be TCP, UDP, IP
    1706           0 :                     REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LOOPBACK);
    1707             :                 }
    1708             :             }
    1709             :         }
    1710             :     }
    1711           6 : }
    1712             : 
    1713             : 
    1714          10 : TEST_CASE( "ipv4::network_type", "[ipv4]" )
    1715             : {
    1716          16 :     GIVEN("addr()")
    1717             :     {
    1718           8 :         addr::addr a;
    1719             : 
    1720          16 :         SECTION("any (0.0.0.0)")
    1721             :         {
    1722           1 :             struct sockaddr_in in = sockaddr_in();
    1723           1 :             in.sin_family = AF_INET;
    1724           1 :             in.sin_port = htons(rand());
    1725           1 :             in.sin_addr.s_addr = 0;
    1726             : 
    1727             :             // verify network type
    1728             :             //
    1729           1 :             a.set_ipv4(in);
    1730             : 
    1731           1 :             REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_ANY);
    1732           1 :             REQUIRE(a.get_network_type_string() == "Any");
    1733             :         }
    1734             : 
    1735          16 :         SECTION("private address 10.x.x.x/8")
    1736             :         {
    1737          11 :             for(int idx(0); idx < 10; ++idx)
    1738             :             {
    1739          10 :                 struct sockaddr_in in = sockaddr_in();
    1740          10 :                 in.sin_family = AF_INET;
    1741          10 :                 in.sin_port = htons(rand());
    1742             :                 uint32_t address((10 << 24)
    1743          10 :                               | ((rand() & 255) << 16)
    1744          10 :                               | ((rand() & 255) << 8)
    1745          10 :                               | ((rand() & 255) << 0));
    1746          10 :                 in.sin_addr.s_addr = htonl(address);
    1747             : 
    1748             :                 // verify network type
    1749             :                 //
    1750          10 :                 a.set_ipv4(in);
    1751          10 :                 REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1752          10 :                 REQUIRE(a.get_network_type_string() == "Private");
    1753             :             }
    1754             :         }
    1755             : 
    1756          16 :         SECTION("private address 172.16.x.x/12")
    1757             :         {
    1758          11 :             for(int idx(0); idx < 10; ++idx)
    1759             :             {
    1760          10 :                 struct sockaddr_in in = sockaddr_in();
    1761          10 :                 in.sin_family = AF_INET;
    1762          10 :                 in.sin_port = htons(rand());
    1763             :                 uint32_t address((172 << 24)
    1764          10 :                               | (((rand() & 15) | 16) << 16)
    1765          10 :                               | ((rand() & 255) << 8)
    1766          10 :                               | ((rand() & 255) << 0));
    1767          10 :                 in.sin_addr.s_addr = htonl(address);
    1768             : 
    1769             :                 // verify network type
    1770             :                 //
    1771          10 :                 a.set_ipv4(in);
    1772          10 :                 REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1773          10 :                 REQUIRE(a.get_network_type_string() == "Private");
    1774             :             }
    1775             :         }
    1776             : 
    1777          16 :         SECTION("private address 192.168.x.x/16")
    1778             :         {
    1779          11 :             for(int idx(0); idx < 10; ++idx)
    1780             :             {
    1781          10 :                 struct sockaddr_in in = sockaddr_in();
    1782          10 :                 in.sin_family = AF_INET;
    1783          10 :                 in.sin_port = htons(rand());
    1784             :                 uint32_t address((192 << 24)
    1785             :                               |  (168 << 16)
    1786          10 :                               | ((rand() & 255) << 8)
    1787          10 :                               | ((rand() & 255) << 0));
    1788          10 :                 in.sin_addr.s_addr = htonl(address);
    1789             : 
    1790             :                 // verify network type
    1791             :                 //
    1792          10 :                 a.set_ipv4(in);
    1793          10 :                 REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1794          10 :                 REQUIRE(a.get_network_type_string() == "Private");
    1795             :             }
    1796             :         }
    1797             : 
    1798          16 :         SECTION("private address 100.66.x.x/10")
    1799             :         {
    1800          11 :             for(int idx(0); idx < 10; ++idx)
    1801             :             {
    1802          10 :                 struct sockaddr_in in = sockaddr_in();
    1803          10 :                 in.sin_family = AF_INET;
    1804          10 :                 in.sin_port = htons(rand());
    1805             :                 uint32_t address((100 << 24)
    1806          10 :                               | (((rand() & 63) | 64) << 16)
    1807          10 :                               | ((rand() & 255) << 8)
    1808          10 :                               | ((rand() & 255) << 0));
    1809          10 :                 in.sin_addr.s_addr = htonl(address);
    1810             : 
    1811             :                 // verify network type
    1812             :                 //
    1813          10 :                 a.set_ipv4(in);
    1814          10 :                 REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_CARRIER);
    1815          10 :                 REQUIRE(a.get_network_type_string() == "Carrier");
    1816             :             }
    1817             :         }
    1818             : 
    1819          16 :         SECTION("private address 169.254.x.x/16")
    1820             :         {
    1821          11 :             for(int idx(0); idx < 10; ++idx)
    1822             :             {
    1823          10 :                 struct sockaddr_in in = sockaddr_in();
    1824          10 :                 in.sin_family = AF_INET;
    1825          10 :                 in.sin_port = htons(rand());
    1826             :                 uint32_t address((169 << 24)
    1827             :                               |  (254 << 16)
    1828          10 :                               | ((rand() & 255) << 8)
    1829          10 :                               | ((rand() & 255) << 0));
    1830          10 :                 in.sin_addr.s_addr = htonl(address);
    1831             : 
    1832             :                 // verify network type
    1833             :                 //
    1834          10 :                 a.set_ipv4(in);
    1835          10 :                 REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LINK_LOCAL);
    1836          10 :                 REQUIRE(a.get_network_type_string() == "Local Link");
    1837             :             }
    1838             :         }
    1839             : 
    1840          16 :         SECTION("private address 224.x.x.x/4")
    1841             :         {
    1842          11 :             for(int idx(0); idx < 10; ++idx)
    1843             :             {
    1844          10 :                 struct sockaddr_in in = sockaddr_in();
    1845          10 :                 in.sin_family = AF_INET;
    1846          10 :                 in.sin_port = htons(rand());
    1847          10 :                 uint32_t address((((rand() & 15) | 224) << 24)
    1848          10 :                               | ((rand() & 255) << 16)
    1849          10 :                               | ((rand() & 255) << 8)
    1850          10 :                               | ((rand() & 255) << 0));
    1851          10 :                 in.sin_addr.s_addr = htonl(address);
    1852             : 
    1853             :                 // verify network type
    1854             :                 //
    1855          10 :                 a.set_ipv4(in);
    1856          10 :                 REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_MULTICAST);
    1857          10 :                 REQUIRE(a.get_network_type_string() == "Multicast");
    1858             : 
    1859             :                 // make sure no interface uses that IP
    1860             :                 //
    1861          10 :                 REQUIRE(addr::find_addr_interface(a, false) == nullptr);
    1862             :             }
    1863             :         }
    1864             : 
    1865          16 :         SECTION("private address 127.x.x.x/8")
    1866             :         {
    1867          11 :             for(int idx(0); idx < 10; ++idx)
    1868             :             {
    1869          10 :                 struct sockaddr_in in = sockaddr_in();
    1870          10 :                 in.sin_family = AF_INET;
    1871          10 :                 in.sin_port = htons(rand());
    1872             :                 uint32_t address((127 << 24)
    1873          10 :                               | ((rand() & 255) << 16)
    1874          10 :                               | ((rand() & 255) << 8)
    1875          10 :                               | ((rand() & 255) << 0));
    1876          10 :                 in.sin_addr.s_addr = htonl(address);
    1877             : 
    1878             :                 // verify network type
    1879             :                 //
    1880          10 :                 a.set_ipv4(in);
    1881          10 :                 REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LOOPBACK);
    1882          10 :                 REQUIRE(a.get_network_type_string() == "Loopback");
    1883             :             }
    1884             :         }
    1885             :     }
    1886           8 : }
    1887             : 
    1888             : 
    1889           8 : TEST_CASE( "ipv4::network", "[ipv4]" )
    1890             : {
    1891          12 :     GIVEN("set_from_socket()")
    1892             :     {
    1893          12 :         SECTION("invalid socket")
    1894             :         {
    1895           1 :             addr::addr a;
    1896           1 :             REQUIRE_THROWS_AS(a.set_from_socket(-1, true),  addr::addr_invalid_argument_exception);
    1897           1 :             REQUIRE_THROWS_AS(a.set_from_socket(-1, false), addr::addr_invalid_argument_exception);
    1898             :         }
    1899             : 
    1900          12 :         SECTION("non-opened file descriptor")
    1901             :         {
    1902           1 :             addr::addr a;
    1903             : 
    1904             :             // unless we have a bug, there should not be any file descriptor
    1905             :             // currently open with an ID of 1,000
    1906             :             //
    1907           1 :             REQUIRE_THROWS_AS(a.set_from_socket(1000, true),  addr::addr_io_exception);
    1908           1 :             REQUIRE_THROWS_AS(a.set_from_socket(1000, false), addr::addr_io_exception);
    1909             :         }
    1910             : 
    1911          12 :         SECTION("unknown socket type")
    1912             :         {
    1913           1 :             addr::addr a;
    1914             : 
    1915           1 :             int s(socket(AF_UNIX, SOCK_STREAM, 0));
    1916           1 :             REQUIRE(s >= 0);
    1917           2 :             std::shared_ptr<int> auto_free(&s, socket_deleter);
    1918             : 
    1919             :             // unless we have a bug, there should not be any file descriptor
    1920             :             // currently open with an ID of 1,000
    1921             :             //
    1922           1 :             REQUIRE_THROWS_AS(a.set_from_socket(s, true),  addr::addr_io_exception);
    1923           1 :             REQUIRE_THROWS_AS(a.set_from_socket(s, false), addr::addr_invalid_state_exception);
    1924             :         }
    1925             : 
    1926          12 :         SECTION("create a server, but do not test it (yet)...")
    1927             :         {
    1928           2 :             addr::addr_parser p;
    1929           2 :             addr::addr_range::vector_t ips(p.parse("127.0.0.1:49999"));
    1930           1 :             REQUIRE(ips.size() >= 1);
    1931             : 
    1932           1 :             addr::addr & a(ips[0].get_from());
    1933           1 :             int s(a.create_socket(addr::addr::SOCKET_FLAG_NONBLOCK | addr::addr::SOCKET_FLAG_CLOEXEC | addr::addr::SOCKET_FLAG_REUSE));
    1934           1 :             REQUIRE(s >= 0);
    1935           2 :             std::shared_ptr<int> auto_free(&s, socket_deleter);
    1936             : 
    1937           1 :             REQUIRE(a.bind(s) == 0);
    1938             :         }
    1939             : 
    1940          12 :         SECTION("connect with TCP to 127.0.0.1")
    1941             :         {
    1942           1 :             if(unittest::g_tcp_port != -1)
    1943             :             {
    1944           2 :                 addr::addr_parser p;
    1945           2 :                 addr::addr_range::vector_t ips(p.parse("127.0.0.1:" + std::to_string(unittest::g_tcp_port)));
    1946           1 :                 REQUIRE(ips.size() >= 1);
    1947             : 
    1948           1 :                 addr::addr & a(ips[0].get_from());
    1949           1 :                 int s(a.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC));// | addr::addr::SOCKET_FLAG_REUSE));
    1950           1 :                 REQUIRE(s >= 0);
    1951           2 :                 std::shared_ptr<int> auto_free(&s, socket_deleter);
    1952             : 
    1953           1 :                 REQUIRE(a.connect(s) == 0);
    1954             : 
    1955             :                 // get socket info from the other side (peer == true)
    1956             :                 //
    1957           1 :                 addr::addr b;
    1958           1 :                 b.set_from_socket(s, true);
    1959           1 :                 REQUIRE(b.is_ipv4());
    1960           1 :                 REQUIRE(b.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY)    == "127.0.0.1");
    1961           1 :                 REQUIRE(b.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "127.0.0.1");
    1962             : 
    1963             :                 // in this case we know what the port is since we specified
    1964             :                 // that when connecting
    1965             :                 //
    1966           1 :                 REQUIRE(b.get_port() == unittest::g_tcp_port);
    1967             : 
    1968             :                 // now try this side (peer == false)
    1969             :                 //
    1970           1 :                 addr::addr c;
    1971           1 :                 c.set_from_socket(s, false);
    1972           1 :                 REQUIRE(c.is_ipv4());
    1973           1 :                 REQUIRE(c.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY)    == "127.0.0.1");
    1974           1 :                 REQUIRE(c.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "127.0.0.1");
    1975             : 
    1976             :                 // we cannot be sure of the port, there is a range we could
    1977             :                 // test better (more constraining) but for this test is
    1978             :                 // certainly does not matter much; it has to be more than
    1979             :                 // 1023, though
    1980             :                 //
    1981           1 :                 REQUIRE(c.get_port() > 1023);
    1982             :             }
    1983             :             else
    1984             :             {
    1985           0 :                 std::cout << "connect to 127.0.0.1 test skipped as no TCP port was specified on the command line." << std::endl;
    1986             :             }
    1987             :         }
    1988             : 
    1989          12 :         SECTION("connect with UDP to 127.0.0.1")
    1990             :         {
    1991           2 :             addr::addr_parser p;
    1992           1 :             p.set_protocol("udp");
    1993           2 :             addr::addr_range::vector_t ips(p.parse("127.0.0.1:53"));
    1994           1 :             REQUIRE(ips.size() >= 1);
    1995             : 
    1996           1 :             addr::addr & a(ips[0].get_from());
    1997           1 :             int s(a.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC));// | addr::addr::SOCKET_FLAG_REUSE));
    1998           1 :             REQUIRE(s >= 0);
    1999           2 :             std::shared_ptr<int> auto_free(&s, socket_deleter);
    2000             : 
    2001           1 :             REQUIRE(a.connect(s) == -1);
    2002             : 
    2003             :             // get socket info from the other side (peer == true)
    2004             :             //
    2005           1 :             addr::addr b;
    2006           1 :             REQUIRE_THROWS_AS(b.set_from_socket(s, true), addr::addr_io_exception);
    2007           1 :             REQUIRE_FALSE(b.is_ipv4());
    2008           1 :             REQUIRE(b.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY)    == "::");
    2009           1 :             REQUIRE(b.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::");
    2010             : 
    2011             :             // in this case we know what the port is since we specified
    2012             :             // that when connecting
    2013             :             //
    2014           1 :             REQUIRE(b.get_port() == 0);
    2015             : 
    2016             :             // now try this side (peer == false)
    2017             :             //
    2018           1 :             addr::addr c;
    2019           1 :             c.set_from_socket(s, false);
    2020           1 :             REQUIRE(c.is_ipv4());
    2021           1 :             REQUIRE(c.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY)    == "0.0.0.0");
    2022           1 :             REQUIRE(c.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "0.0.0.0");
    2023             : 
    2024             :             // we cannot be sure of the port, there is a range we could
    2025             :             // test better (more constraining) but for this test is
    2026             :             // certainly does not matter much; it has to be more than
    2027             :             // 1023, though
    2028             :             //
    2029           1 :             REQUIRE(c.get_port() == 0);
    2030             :         }
    2031             :     }
    2032           6 : }
    2033             : 
    2034             : 
    2035          15 : TEST_CASE( "ipv4::string_to_addr", "[ipv4]" )
    2036             : {
    2037          26 :     GIVEN("string_to_addr() ipv4")
    2038             :     {
    2039          26 :         SECTION("empty address without defaults")
    2040             :         {
    2041           1 :             addr::addr a(addr::string_to_addr(std::string()));
    2042             : 
    2043           1 :             REQUIRE(a.is_ipv4());
    2044             : 
    2045           1 :             struct sockaddr_in in = sockaddr_in();
    2046           1 :             in.sin_family = AF_INET;
    2047           1 :             in.sin_port = 0;
    2048           1 :             in.sin_addr.s_addr = htonl((0 << 24) | (0 << 16) | (0 << 8) | (0 << 0));
    2049             : 
    2050             :             // test string_to_addr accuracy
    2051             :             //
    2052             :             struct sockaddr_in out;
    2053           1 :             a.get_ipv4(out);
    2054           1 :             REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2055             : 
    2056             :             uint8_t mask[16];
    2057           1 :             a.get_mask(mask);
    2058           1 :             REQUIRE(mask[ 0] == 0xFF);
    2059           1 :             REQUIRE(mask[ 1] == 0xFF);
    2060           1 :             REQUIRE(mask[ 2] == 0xFF);
    2061           1 :             REQUIRE(mask[ 3] == 0xFF);
    2062           1 :             REQUIRE(mask[ 4] == 0xFF);
    2063           1 :             REQUIRE(mask[ 5] == 0xFF);
    2064           1 :             REQUIRE(mask[ 6] == 0xFF);
    2065           1 :             REQUIRE(mask[ 7] == 0xFF);
    2066           1 :             REQUIRE(mask[ 8] == 0xFF);
    2067           1 :             REQUIRE(mask[ 9] == 0xFF);
    2068           1 :             REQUIRE(mask[10] == 0xFF);
    2069           1 :             REQUIRE(mask[11] == 0xFF);
    2070           1 :             REQUIRE(mask[12] == 0xFF);
    2071           1 :             REQUIRE(mask[13] == 0xFF);
    2072           1 :             REQUIRE(mask[14] == 0xFF);
    2073           1 :             REQUIRE(mask[15] == 0xFF);
    2074             :         }
    2075          26 :         SECTION("explicit defaults")
    2076             :         {
    2077           1 :             addr::addr a(addr::string_to_addr("5.14.34.111", std::string(), -1, std::string(), false));
    2078             : 
    2079           1 :             REQUIRE(a.is_ipv4());
    2080             : 
    2081           1 :             struct sockaddr_in in = sockaddr_in();
    2082           1 :             in.sin_family = AF_INET;
    2083           1 :             in.sin_port = 0;
    2084           1 :             in.sin_addr.s_addr = htonl((5 << 24) | (14 << 16) | (34 << 8) | (111 << 0));
    2085             : 
    2086             :             // test string_to_addr accuracy
    2087             :             //
    2088             :             struct sockaddr_in out;
    2089           1 :             a.get_ipv4(out);
    2090           1 :             REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2091             : 
    2092             :             uint8_t mask[16];
    2093           1 :             a.get_mask(mask);
    2094           1 :             REQUIRE(mask[ 0] == 0xFF);
    2095           1 :             REQUIRE(mask[ 1] == 0xFF);
    2096           1 :             REQUIRE(mask[ 2] == 0xFF);
    2097           1 :             REQUIRE(mask[ 3] == 0xFF);
    2098           1 :             REQUIRE(mask[ 4] == 0xFF);
    2099           1 :             REQUIRE(mask[ 5] == 0xFF);
    2100           1 :             REQUIRE(mask[ 6] == 0xFF);
    2101           1 :             REQUIRE(mask[ 7] == 0xFF);
    2102           1 :             REQUIRE(mask[ 8] == 0xFF);
    2103           1 :             REQUIRE(mask[ 9] == 0xFF);
    2104           1 :             REQUIRE(mask[10] == 0xFF);
    2105           1 :             REQUIRE(mask[11] == 0xFF);
    2106           1 :             REQUIRE(mask[12] == 0xFF);
    2107           1 :             REQUIRE(mask[13] == 0xFF);
    2108           1 :             REQUIRE(mask[14] == 0xFF);
    2109           1 :             REQUIRE(mask[15] == 0xFF);
    2110             :         }
    2111          26 :         SECTION("defaults")
    2112             :         {
    2113           1 :             addr::addr a(addr::string_to_addr("7.149.104.211"));
    2114             : 
    2115           1 :             REQUIRE(a.is_ipv4());
    2116             : 
    2117           1 :             struct sockaddr_in in = sockaddr_in();
    2118           1 :             in.sin_family = AF_INET;
    2119           1 :             in.sin_port = 0;
    2120           1 :             in.sin_addr.s_addr = htonl((7 << 24) | (149 << 16) | (104 << 8) | (211 << 0));
    2121             : 
    2122             :             // test string_to_addr accuracy
    2123             :             //
    2124             :             struct sockaddr_in out;
    2125           1 :             a.get_ipv4(out);
    2126           1 :             REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2127             : 
    2128             :             uint8_t mask[16];
    2129           1 :             a.get_mask(mask);
    2130           1 :             REQUIRE(mask[ 0] == 0xFF);
    2131           1 :             REQUIRE(mask[ 1] == 0xFF);
    2132           1 :             REQUIRE(mask[ 2] == 0xFF);
    2133           1 :             REQUIRE(mask[ 3] == 0xFF);
    2134           1 :             REQUIRE(mask[ 4] == 0xFF);
    2135           1 :             REQUIRE(mask[ 5] == 0xFF);
    2136           1 :             REQUIRE(mask[ 6] == 0xFF);
    2137           1 :             REQUIRE(mask[ 7] == 0xFF);
    2138           1 :             REQUIRE(mask[ 8] == 0xFF);
    2139           1 :             REQUIRE(mask[ 9] == 0xFF);
    2140           1 :             REQUIRE(mask[10] == 0xFF);
    2141           1 :             REQUIRE(mask[11] == 0xFF);
    2142           1 :             REQUIRE(mask[12] == 0xFF);
    2143           1 :             REQUIRE(mask[13] == 0xFF);
    2144           1 :             REQUIRE(mask[14] == 0xFF);
    2145           1 :             REQUIRE(mask[15] == 0xFF);
    2146             :         }
    2147          26 :         SECTION("addr & default addr")
    2148             :         {
    2149           1 :             addr::addr a(addr::string_to_addr("37.149.174.11", "1.205.32.11"));
    2150             : 
    2151           1 :             REQUIRE(a.is_ipv4());
    2152             : 
    2153           1 :             struct sockaddr_in in = sockaddr_in();
    2154           1 :             in.sin_family = AF_INET;
    2155           1 :             in.sin_port = 0;
    2156           1 :             in.sin_addr.s_addr = htonl((37 << 24) | (149 << 16) | (174 << 8) | (11 << 0));
    2157             : 
    2158             :             // test string_to_addr accuracy
    2159             :             //
    2160             :             struct sockaddr_in out;
    2161           1 :             a.get_ipv4(out);
    2162           1 :             REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2163             : 
    2164             :             uint8_t mask[16];
    2165           1 :             a.get_mask(mask);
    2166           1 :             REQUIRE(mask[ 0] == 0xFF);
    2167           1 :             REQUIRE(mask[ 1] == 0xFF);
    2168           1 :             REQUIRE(mask[ 2] == 0xFF);
    2169           1 :             REQUIRE(mask[ 3] == 0xFF);
    2170           1 :             REQUIRE(mask[ 4] == 0xFF);
    2171           1 :             REQUIRE(mask[ 5] == 0xFF);
    2172           1 :             REQUIRE(mask[ 6] == 0xFF);
    2173           1 :             REQUIRE(mask[ 7] == 0xFF);
    2174           1 :             REQUIRE(mask[ 8] == 0xFF);
    2175           1 :             REQUIRE(mask[ 9] == 0xFF);
    2176           1 :             REQUIRE(mask[10] == 0xFF);
    2177           1 :             REQUIRE(mask[11] == 0xFF);
    2178           1 :             REQUIRE(mask[12] == 0xFF);
    2179           1 :             REQUIRE(mask[13] == 0xFF);
    2180           1 :             REQUIRE(mask[14] == 0xFF);
    2181           1 :             REQUIRE(mask[15] == 0xFF);
    2182             :         }
    2183          26 :         SECTION("no addr, expect default addr")
    2184             :         {
    2185           1 :             addr::addr a(addr::string_to_addr("", "1.205.32.11"));
    2186             : 
    2187           1 :             REQUIRE(a.is_ipv4());
    2188             : 
    2189           1 :             struct sockaddr_in in = sockaddr_in();
    2190           1 :             in.sin_family = AF_INET;
    2191           1 :             in.sin_port = 0;
    2192           1 :             in.sin_addr.s_addr = htonl((1 << 24) | (205 << 16) | (32 << 8) | (11 << 0));
    2193             : 
    2194             :             // test string_to_addr accuracy
    2195             :             //
    2196             :             struct sockaddr_in out;
    2197           1 :             a.get_ipv4(out);
    2198           1 :             REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2199             : 
    2200             :             uint8_t mask[16];
    2201           1 :             a.get_mask(mask);
    2202           1 :             REQUIRE(mask[ 0] == 0xFF);
    2203           1 :             REQUIRE(mask[ 1] == 0xFF);
    2204           1 :             REQUIRE(mask[ 2] == 0xFF);
    2205           1 :             REQUIRE(mask[ 3] == 0xFF);
    2206           1 :             REQUIRE(mask[ 4] == 0xFF);
    2207           1 :             REQUIRE(mask[ 5] == 0xFF);
    2208           1 :             REQUIRE(mask[ 6] == 0xFF);
    2209           1 :             REQUIRE(mask[ 7] == 0xFF);
    2210           1 :             REQUIRE(mask[ 8] == 0xFF);
    2211           1 :             REQUIRE(mask[ 9] == 0xFF);
    2212           1 :             REQUIRE(mask[10] == 0xFF);
    2213           1 :             REQUIRE(mask[11] == 0xFF);
    2214           1 :             REQUIRE(mask[12] == 0xFF);
    2215           1 :             REQUIRE(mask[13] == 0xFF);
    2216           1 :             REQUIRE(mask[14] == 0xFF);
    2217           1 :             REQUIRE(mask[15] == 0xFF);
    2218             :         }
    2219          26 :         SECTION("addr and port, with a default port")
    2220             :         {
    2221           1 :             addr::addr a(addr::string_to_addr("69.109.223.17:697", "1.205.32.11", 123));
    2222             : 
    2223           1 :             REQUIRE(a.is_ipv4());
    2224             : 
    2225           1 :             struct sockaddr_in in = sockaddr_in();
    2226           1 :             in.sin_family = AF_INET;
    2227           1 :             in.sin_port = htons(697);
    2228           1 :             in.sin_addr.s_addr = htonl((69 << 24) | (109 << 16) | (223 << 8) | (17 << 0));
    2229             : 
    2230             :             // test string_to_addr accuracy
    2231             :             //
    2232             :             struct sockaddr_in out;
    2233           1 :             a.get_ipv4(out);
    2234           1 :             REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2235             : 
    2236             :             uint8_t mask[16];
    2237           1 :             a.get_mask(mask);
    2238           1 :             REQUIRE(mask[ 0] == 0xFF);
    2239           1 :             REQUIRE(mask[ 1] == 0xFF);
    2240           1 :             REQUIRE(mask[ 2] == 0xFF);
    2241           1 :             REQUIRE(mask[ 3] == 0xFF);
    2242           1 :             REQUIRE(mask[ 4] == 0xFF);
    2243           1 :             REQUIRE(mask[ 5] == 0xFF);
    2244           1 :             REQUIRE(mask[ 6] == 0xFF);
    2245           1 :             REQUIRE(mask[ 7] == 0xFF);
    2246           1 :             REQUIRE(mask[ 8] == 0xFF);
    2247           1 :             REQUIRE(mask[ 9] == 0xFF);
    2248           1 :             REQUIRE(mask[10] == 0xFF);
    2249           1 :             REQUIRE(mask[11] == 0xFF);
    2250           1 :             REQUIRE(mask[12] == 0xFF);
    2251           1 :             REQUIRE(mask[13] == 0xFF);
    2252           1 :             REQUIRE(mask[14] == 0xFF);
    2253           1 :             REQUIRE(mask[15] == 0xFF);
    2254             :         }
    2255          26 :         SECTION("addr without port, with a default port")
    2256             :         {
    2257           1 :             addr::addr a(addr::string_to_addr("169.209.23.217", "1.205.32.11", 123));
    2258             : 
    2259           1 :             REQUIRE(a.is_ipv4());
    2260             : 
    2261           1 :             struct sockaddr_in in = sockaddr_in();
    2262           1 :             in.sin_family = AF_INET;
    2263           1 :             in.sin_port = htons(123);
    2264           1 :             in.sin_addr.s_addr = htonl((169 << 24) | (209 << 16) | (23 << 8) | (217 << 0));
    2265             : 
    2266             :             // test string_to_addr accuracy
    2267             :             //
    2268             :             struct sockaddr_in out;
    2269           1 :             a.get_ipv4(out);
    2270           1 :             REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2271             : 
    2272             :             uint8_t mask[16];
    2273           1 :             a.get_mask(mask);
    2274           1 :             REQUIRE(mask[ 0] == 0xFF);
    2275           1 :             REQUIRE(mask[ 1] == 0xFF);
    2276           1 :             REQUIRE(mask[ 2] == 0xFF);
    2277           1 :             REQUIRE(mask[ 3] == 0xFF);
    2278           1 :             REQUIRE(mask[ 4] == 0xFF);
    2279           1 :             REQUIRE(mask[ 5] == 0xFF);
    2280           1 :             REQUIRE(mask[ 6] == 0xFF);
    2281           1 :             REQUIRE(mask[ 7] == 0xFF);
    2282           1 :             REQUIRE(mask[ 8] == 0xFF);
    2283           1 :             REQUIRE(mask[ 9] == 0xFF);
    2284           1 :             REQUIRE(mask[10] == 0xFF);
    2285           1 :             REQUIRE(mask[11] == 0xFF);
    2286           1 :             REQUIRE(mask[12] == 0xFF);
    2287           1 :             REQUIRE(mask[13] == 0xFF);
    2288           1 :             REQUIRE(mask[14] == 0xFF);
    2289           1 :             REQUIRE(mask[15] == 0xFF);
    2290             :         }
    2291          26 :         SECTION("addr without port but protocol")
    2292             :         {
    2293           1 :             addr::addr a(addr::string_to_addr("4.5.123.7", "1.205.32.11", 60000, "tcp"));
    2294             : 
    2295           1 :             REQUIRE(a.is_ipv4());
    2296             : 
    2297           1 :             struct sockaddr_in in = sockaddr_in();
    2298           1 :             in.sin_family = AF_INET;
    2299           1 :             in.sin_port = htons(60000);
    2300           1 :             in.sin_addr.s_addr = htonl((4 << 24) | (5 << 16) | (123 << 8) | (7 << 0));
    2301             : 
    2302             :             // test string_to_addr accuracy
    2303             :             //
    2304             :             struct sockaddr_in out;
    2305           1 :             a.get_ipv4(out);
    2306           1 :             REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2307             : 
    2308             :             uint8_t mask[16];
    2309           1 :             a.get_mask(mask);
    2310           1 :             REQUIRE(mask[ 0] == 0xFF);
    2311           1 :             REQUIRE(mask[ 1] == 0xFF);
    2312           1 :             REQUIRE(mask[ 2] == 0xFF);
    2313           1 :             REQUIRE(mask[ 3] == 0xFF);
    2314           1 :             REQUIRE(mask[ 4] == 0xFF);
    2315           1 :             REQUIRE(mask[ 5] == 0xFF);
    2316           1 :             REQUIRE(mask[ 6] == 0xFF);
    2317           1 :             REQUIRE(mask[ 7] == 0xFF);
    2318           1 :             REQUIRE(mask[ 8] == 0xFF);
    2319           1 :             REQUIRE(mask[ 9] == 0xFF);
    2320           1 :             REQUIRE(mask[10] == 0xFF);
    2321           1 :             REQUIRE(mask[11] == 0xFF);
    2322           1 :             REQUIRE(mask[12] == 0xFF);
    2323           1 :             REQUIRE(mask[13] == 0xFF);
    2324           1 :             REQUIRE(mask[14] == 0xFF);
    2325           1 :             REQUIRE(mask[15] == 0xFF);
    2326             :         }
    2327          26 :         SECTION("addr with port and protocol")
    2328             :         {
    2329           1 :             addr::addr a(addr::string_to_addr("204.105.13.9:65", "1.205.32.11", 60000, "tcp"));
    2330             : 
    2331           1 :             REQUIRE(a.is_ipv4());
    2332             : 
    2333           1 :             struct sockaddr_in in = sockaddr_in();
    2334           1 :             in.sin_family = AF_INET;
    2335           1 :             in.sin_port = htons(65);
    2336           1 :             in.sin_addr.s_addr = htonl((204 << 24) | (105 << 16) | (13 << 8) | (9 << 0));
    2337             : 
    2338             :             // test string_to_addr accuracy
    2339             :             //
    2340             :             struct sockaddr_in out;
    2341           1 :             a.get_ipv4(out);
    2342           1 :             REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2343             : 
    2344             :             uint8_t mask[16];
    2345           1 :             a.get_mask(mask);
    2346           1 :             REQUIRE(mask[ 0] == 0xFF);
    2347           1 :             REQUIRE(mask[ 1] == 0xFF);
    2348           1 :             REQUIRE(mask[ 2] == 0xFF);
    2349           1 :             REQUIRE(mask[ 3] == 0xFF);
    2350           1 :             REQUIRE(mask[ 4] == 0xFF);
    2351           1 :             REQUIRE(mask[ 5] == 0xFF);
    2352           1 :             REQUIRE(mask[ 6] == 0xFF);
    2353           1 :             REQUIRE(mask[ 7] == 0xFF);
    2354           1 :             REQUIRE(mask[ 8] == 0xFF);
    2355           1 :             REQUIRE(mask[ 9] == 0xFF);
    2356           1 :             REQUIRE(mask[10] == 0xFF);
    2357           1 :             REQUIRE(mask[11] == 0xFF);
    2358           1 :             REQUIRE(mask[12] == 0xFF);
    2359           1 :             REQUIRE(mask[13] == 0xFF);
    2360           1 :             REQUIRE(mask[14] == 0xFF);
    2361           1 :             REQUIRE(mask[15] == 0xFF);
    2362             :         }
    2363          26 :         SECTION("addr with port and protocol but no mask, albeit allowed")
    2364             :         {
    2365           1 :             addr::addr a(addr::string_to_addr("94.95.131.18:765", "11.205.32.21", 54003, "tcp", true));
    2366             : 
    2367           1 :             REQUIRE(a.is_ipv4());
    2368             : 
    2369           1 :             struct sockaddr_in in = sockaddr_in();
    2370           1 :             in.sin_family = AF_INET;
    2371           1 :             in.sin_port = htons(765);
    2372           1 :             in.sin_addr.s_addr = htonl((94 << 24) | (95 << 16) | (131 << 8) | (18 << 0));
    2373             : 
    2374             :             // test string_to_addr accuracy
    2375             :             //
    2376             :             struct sockaddr_in out;
    2377           1 :             a.get_ipv4(out);
    2378           1 :             REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2379             : 
    2380             :             uint8_t mask[16];
    2381           1 :             a.get_mask(mask);
    2382           1 :             REQUIRE(mask[ 0] == 0xFF);
    2383           1 :             REQUIRE(mask[ 1] == 0xFF);
    2384           1 :             REQUIRE(mask[ 2] == 0xFF);
    2385           1 :             REQUIRE(mask[ 3] == 0xFF);
    2386           1 :             REQUIRE(mask[ 4] == 0xFF);
    2387           1 :             REQUIRE(mask[ 5] == 0xFF);
    2388           1 :             REQUIRE(mask[ 6] == 0xFF);
    2389           1 :             REQUIRE(mask[ 7] == 0xFF);
    2390           1 :             REQUIRE(mask[ 8] == 0xFF);
    2391           1 :             REQUIRE(mask[ 9] == 0xFF);
    2392           1 :             REQUIRE(mask[10] == 0xFF);
    2393           1 :             REQUIRE(mask[11] == 0xFF);
    2394           1 :             REQUIRE(mask[12] == 0xFF);
    2395           1 :             REQUIRE(mask[13] == 0xFF);
    2396           1 :             REQUIRE(mask[14] == 0xFF);
    2397           1 :             REQUIRE(mask[15] == 0xFF);
    2398             :         }
    2399          26 :         SECTION("addr with port and protocol and mask, albeit allowed")
    2400             :         {
    2401           1 :             addr::addr a(addr::string_to_addr("44.45.141.48:765/30", "11.205.32.21", 54003, "tcp", true));
    2402             : 
    2403           1 :             REQUIRE(a.is_ipv4());
    2404             : 
    2405           1 :             struct sockaddr_in in = sockaddr_in();
    2406           1 :             in.sin_family = AF_INET;
    2407           1 :             in.sin_port = htons(765);
    2408           1 :             in.sin_addr.s_addr = htonl((44 << 24) | (45 << 16) | (141 << 8) | (48 << 0));
    2409             : 
    2410             :             // test string_to_addr accuracy
    2411             :             //
    2412             :             struct sockaddr_in out;
    2413           1 :             a.get_ipv4(out);
    2414           1 :             REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2415             : 
    2416             :             uint8_t mask[16];
    2417           1 :             a.get_mask(mask);
    2418           1 :             REQUIRE(mask[ 0] == 0xFF);
    2419           1 :             REQUIRE(mask[ 1] == 0xFF);
    2420           1 :             REQUIRE(mask[ 2] == 0xFF);
    2421           1 :             REQUIRE(mask[ 3] == 0xFF);
    2422           1 :             REQUIRE(mask[ 4] == 0xFF);
    2423           1 :             REQUIRE(mask[ 5] == 0xFF);
    2424           1 :             REQUIRE(mask[ 6] == 0xFF);
    2425           1 :             REQUIRE(mask[ 7] == 0xFF);
    2426           1 :             REQUIRE(mask[ 8] == 0xFF);
    2427           1 :             REQUIRE(mask[ 9] == 0xFF);
    2428           1 :             REQUIRE(mask[10] == 0xFF);
    2429           1 :             REQUIRE(mask[11] == 0xFF);
    2430           1 :             REQUIRE(mask[12] == 0xFF);
    2431           1 :             REQUIRE(mask[13] == 0xFF);
    2432           1 :             REQUIRE(mask[14] == 0xFF);
    2433           1 :             REQUIRE(mask[15] == 0xFC);
    2434             :         }
    2435          26 :         SECTION("addr with port and protocol and mask, albeit allowed")
    2436             :         {
    2437           1 :             addr::addr a(addr::string_to_addr("160.0.0.0:1675/4", "11.205.32.21", 14003, "udp", true));
    2438             : 
    2439           1 :             REQUIRE(a.is_ipv4());
    2440             : 
    2441           1 :             struct sockaddr_in in = sockaddr_in();
    2442           1 :             in.sin_family = AF_INET;
    2443           1 :             in.sin_port = htons(1675);
    2444           1 :             in.sin_addr.s_addr = htonl((160 << 24) | (0 << 16) | (0 << 8) | (0 << 0));
    2445             : 
    2446             :             // test string_to_addr accuracy
    2447             :             //
    2448             :             struct sockaddr_in out;
    2449           1 :             a.get_ipv4(out);
    2450           1 :             REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2451             : 
    2452             :             uint8_t mask[16];
    2453           1 :             a.get_mask(mask);
    2454           1 :             REQUIRE(mask[ 0] == 0xFF);
    2455           1 :             REQUIRE(mask[ 1] == 0xFF);
    2456           1 :             REQUIRE(mask[ 2] == 0xFF);
    2457           1 :             REQUIRE(mask[ 3] == 0xFF);
    2458           1 :             REQUIRE(mask[ 4] == 0xFF);
    2459           1 :             REQUIRE(mask[ 5] == 0xFF);
    2460           1 :             REQUIRE(mask[ 6] == 0xFF);
    2461           1 :             REQUIRE(mask[ 7] == 0xFF);
    2462           1 :             REQUIRE(mask[ 8] == 0xFF);
    2463           1 :             REQUIRE(mask[ 9] == 0xFF);
    2464           1 :             REQUIRE(mask[10] == 0xFF);
    2465           1 :             REQUIRE(mask[11] == 0xFF);
    2466           1 :             REQUIRE(mask[12] == 0xF0);
    2467           1 :             REQUIRE(mask[13] == 0x00);
    2468           1 :             REQUIRE(mask[14] == 0x00);
    2469           1 :             REQUIRE(mask[15] == 0x00);
    2470             :         }
    2471          26 :         SECTION("addr with port and invalid protocol so we get an exception")
    2472             :         {
    2473           1 :             REQUIRE_THROWS_AS(addr::string_to_addr("169.60.33.0:9322/24", std::string(), -1, "icmp", true),
    2474             :                                                                         addr::addr_invalid_argument_exception);
    2475             :         }
    2476             :     }
    2477             :     // TODO: add ipv6 tests, although at this point it's not too
    2478             :     //       important here, it may change in the future
    2479             :     //
    2480             : 
    2481             : //addr string_to_addr(
    2482             : //          std::string const & a
    2483             : //        , std::string const & default_address = std::string()
    2484             : //        , int default_port = -1
    2485             : //        , std::string const & protocol = std::string()
    2486             : //        , bool mask = false);
    2487          19 : }
    2488             : 
    2489             : 
    2490             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.12