LCOV - code coverage report
Current view: top level - tests - catch_ipv4.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1554 1570 99.0 %
Date: 2021-07-21 12:51:15 Functions: 13 13 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13