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: 2019-09-02 12:15:29 Functions: 13 13 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.12