LCOV - code coverage report
Current view: top level - tests - catch_ipv4.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1637 1654 99.0 %
Date: 2022-01-30 17:24:05 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           1 :             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           1 :             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          18 : CATCH_TEST_CASE( "ipv4::address", "[ipv4]" )
     553             : {
     554          32 :     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          10 :                 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          10 :                 std::string ip(
     594          20 :                           std::to_string((address >> 24) & 255)
     595          30 :                         + "."
     596          40 :                         + std::to_string((address >> 16) & 255)
     597          30 :                         + "."
     598          40 :                         + std::to_string((address >>  8) & 255)
     599          30 :                         + "."
     600          20 :                         + std::to_string((address >>  0) & 255)
     601          40 :                         );
     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           1 :             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          32 :     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           3 :                 case addr::addr_parser::flag_t::ADDRESS:
     732             :                 case addr::addr_parser::flag_t::ADDRESS_LOOKUP:
     733             :                 case addr::addr_parser::flag_t::PORT:
     734             :                     // only these are true by default
     735             :                     //
     736           3 :                     CATCH_REQUIRE(p.get_allow(static_cast<addr::addr_parser::flag_t>(idx)));
     737           3 :                     break;
     738             : 
     739           9 :                 default:
     740           9 :                     CATCH_REQUIRE_FALSE(p.get_allow(static_cast<addr::addr_parser::flag_t>(idx)));
     741           9 :                     break;
     742             : 
     743             :                 }
     744             :             }
     745             :         }
     746             : 
     747          14 :         CATCH_SECTION("verify contradictory flags")
     748             :         {
     749           2 :             addr::addr_parser p;
     750             : 
     751             :             // by default these are set to false
     752             :             //
     753           1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
     754           1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_SPACES));
     755           1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
     756             : 
     757             :             // check setting MULTI_ADDRESSES_COMMAS to true
     758             :             //
     759           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS, true);
     760           1 :             CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
     761           1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_SPACES));
     762           1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
     763             : 
     764             :             // add MULTI_ADDRESSES_SPACES
     765             :             //
     766           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_SPACES, true);
     767           1 :             CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
     768           1 :             CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_SPACES));
     769           1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
     770             : 
     771             :             // add MULTI_PORTS_COMMAS
     772             :             //
     773           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS, true);
     774           1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
     775           1 :             CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_SPACES));
     776           1 :             CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
     777             : 
     778             :             // add MULTI_ADDRESSES_COMMAS again
     779             :             //
     780           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS, true);
     781           1 :             CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
     782           1 :             CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_SPACES));
     783           1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
     784             : 
     785             :             // remove MULTI_ADDRESSES_SPACES
     786             :             //
     787           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_SPACES, false);
     788           1 :             CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
     789           1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_SPACES));
     790           1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
     791             : 
     792             :             // back to MULTI_PORTS_COMMAS
     793             :             //
     794           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS, true);
     795           1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
     796           1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_SPACES));
     797           1 :             CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
     798             : 
     799             :             // add MULTI_ADDRESSES_COMMAS first now
     800             :             //
     801           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS, true);
     802           1 :             CATCH_REQUIRE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS));
     803           1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_SPACES));
     804           1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::addr_parser::flag_t::MULTI_PORTS_COMMAS));
     805             :         }
     806             : 
     807          14 :         CATCH_SECTION("default address")
     808             :         {
     809           2 :             addr::addr_parser p;
     810           1 :             p.set_protocol(IPPROTO_TCP);
     811           1 :             p.set_default_address("5.5.5.5");
     812           1 :             CATCH_REQUIRE(p.get_default_address4() == "5.5.5.5");
     813           1 :             CATCH_REQUIRE(p.get_default_address6() == "");
     814           2 :             addr::addr_range::vector_t ips(p.parse(""));
     815           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
     816           1 :             CATCH_REQUIRE(ips.size() == 1);
     817           1 :             addr::addr_range const & r(ips[0]);
     818           1 :             CATCH_REQUIRE(r.has_from());
     819           1 :             CATCH_REQUIRE_FALSE(r.has_to());
     820           1 :             CATCH_REQUIRE_FALSE(r.is_range());
     821           1 :             CATCH_REQUIRE_FALSE(r.is_empty());
     822           1 :             addr::addr f(r.get_from());
     823           1 :             CATCH_REQUIRE(f.is_ipv4());
     824           1 :             CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.5.5.5");
     825           1 :             CATCH_REQUIRE(f.get_port() == 0);
     826           1 :             CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
     827           1 :             CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     828             :         }
     829             : 
     830          14 :         CATCH_SECTION("address, no port allowed")
     831             :         {
     832             :             // specific address with a default
     833             :             {
     834           2 :                 addr::addr_parser p;
     835           1 :                 p.set_allow(addr::addr_parser::flag_t::PORT, false);
     836           1 :                 p.set_protocol(IPPROTO_TCP);
     837           1 :                 p.set_default_address("5.5.5.5");
     838           1 :                 CATCH_REQUIRE(p.get_default_address4() == "5.5.5.5");
     839           1 :                 CATCH_REQUIRE(p.get_default_address6() == "");
     840           2 :                 addr::addr_range::vector_t ips(p.parse("9.9.9.9"));
     841           1 :                 CATCH_REQUIRE_FALSE(p.has_errors());
     842           1 :                 CATCH_REQUIRE(ips.size() == 1);
     843           1 :                 addr::addr_range const & r(ips[0]);
     844           1 :                 CATCH_REQUIRE(r.has_from());
     845           1 :                 CATCH_REQUIRE_FALSE(r.has_to());
     846           1 :                 CATCH_REQUIRE_FALSE(r.is_range());
     847           1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
     848           1 :                 addr::addr f(r.get_from());
     849           1 :                 CATCH_REQUIRE(f.is_ipv4());
     850           1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "9.9.9.9");
     851           1 :                 CATCH_REQUIRE(f.get_port() == 0);
     852           1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
     853           1 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     854             :             }
     855             : 
     856             :             // only a default address
     857             :             {
     858           2 :                 addr::addr_parser p;
     859           1 :                 p.set_allow(addr::addr_parser::flag_t::PORT, false);
     860           1 :                 p.set_protocol(IPPROTO_TCP);
     861           1 :                 p.set_default_address("5.5.5.5");
     862           1 :                 CATCH_REQUIRE(p.get_default_address4() == "5.5.5.5");
     863           1 :                 CATCH_REQUIRE(p.get_default_address6() == "");
     864           2 :                 addr::addr_range::vector_t ips(p.parse(""));
     865           1 :                 CATCH_REQUIRE_FALSE(p.has_errors());
     866           1 :                 CATCH_REQUIRE(ips.size() == 1);
     867           1 :                 addr::addr_range const & r(ips[0]);
     868           1 :                 CATCH_REQUIRE(r.has_from());
     869           1 :                 CATCH_REQUIRE_FALSE(r.has_to());
     870           1 :                 CATCH_REQUIRE_FALSE(r.is_range());
     871           1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
     872           1 :                 addr::addr f(r.get_from());
     873           1 :                 CATCH_REQUIRE(f.is_ipv4());
     874           1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.5.5.5");
     875           1 :                 CATCH_REQUIRE(f.get_port() == 0);
     876           1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
     877           1 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     878             :             }
     879             :         }
     880             :     }
     881             : 
     882          32 :     CATCH_GIVEN("addr_parser() with multiple IPv4 addresses in one string")
     883             :     {
     884           6 :         CATCH_SECTION("3 IPs separated by commas")
     885             :         {
     886           2 :             addr::addr_parser p;
     887           1 :             p.set_protocol(IPPROTO_TCP);
     888           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS, true);
     889           2 :             addr::addr_range::vector_t ips(p.parse("1.2.3.4:55,5.6.7.8,,,,10.11.12.99:77"));
     890           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
     891           1 :             CATCH_REQUIRE(ips.size() == 3);
     892             : 
     893           1 :             uint8_t mask[16] = {};
     894             : 
     895             :             // 1.2.3.4:55
     896             :             {
     897           1 :                 addr::addr_range const & r(ips[0]);
     898           1 :                 CATCH_REQUIRE(r.has_from());
     899           1 :                 CATCH_REQUIRE_FALSE(r.has_to());
     900           1 :                 CATCH_REQUIRE_FALSE(r.is_range());
     901           1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
     902           1 :                 addr::addr f(r.get_from());
     903           1 :                 CATCH_REQUIRE(f.is_ipv4());
     904           1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
     905           1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
     906           1 :                 CATCH_REQUIRE(f.get_port() == 55);
     907           1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
     908           1 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     909           1 :                 f.get_mask(mask);
     910          17 :                 for(int idx(0); idx < 16; ++idx)
     911             :                 {
     912          16 :                     CATCH_REQUIRE(mask[idx] == 255);
     913             :                 }
     914             :             }
     915             : 
     916             :             // 5.6.7.8
     917             :             {
     918           1 :                 addr::addr_range const & r(ips[1]);
     919           1 :                 CATCH_REQUIRE(r.has_from());
     920           1 :                 CATCH_REQUIRE_FALSE(r.has_to());
     921           1 :                 CATCH_REQUIRE_FALSE(r.is_range());
     922           1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
     923           1 :                 addr::addr f(r.get_from());
     924           1 :                 CATCH_REQUIRE(f.is_ipv4());
     925           1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
     926           1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
     927           1 :                 CATCH_REQUIRE(f.get_port() == 0);
     928           1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
     929           1 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     930           1 :                 f.get_mask(mask);
     931          17 :                 for(int idx(0); idx < 16; ++idx)
     932             :                 {
     933          16 :                     CATCH_REQUIRE(mask[idx] == 255);
     934             :                 }
     935             :             }
     936             : 
     937             :             // 10.11.12.99:77
     938             :             {
     939           1 :                 addr::addr_range const & r(ips[2]);
     940           1 :                 CATCH_REQUIRE(r.has_from());
     941           1 :                 CATCH_REQUIRE_FALSE(r.has_to());
     942           1 :                 CATCH_REQUIRE_FALSE(r.is_range());
     943           1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
     944           1 :                 addr::addr f(r.get_from());
     945           1 :                 CATCH_REQUIRE(f.is_ipv4());
     946           1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
     947           1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
     948           1 :                 CATCH_REQUIRE(f.get_port() == 77);
     949           1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
     950           1 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
     951           1 :                 f.get_mask(mask);
     952          17 :                 for(int idx(0); idx < 16; ++idx)
     953             :                 {
     954          16 :                     CATCH_REQUIRE(mask[idx] == 255);
     955             :                 }
     956             :             }
     957             :         }
     958             : 
     959           6 :         CATCH_SECTION("3 IPs separated by spaces")
     960             :         {
     961           2 :             addr::addr_parser p;
     962           1 :             p.set_protocol(IPPROTO_TCP);
     963           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_SPACES, true);
     964           2 :             addr::addr_range::vector_t ips(p.parse("1.2.3.4:55 5.6.7.8   10.11.12.99:77"));
     965           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
     966           1 :             CATCH_REQUIRE(ips.size() == 3);
     967             : 
     968           1 :             uint8_t mask[16] = {};
     969             : 
     970             :             // 1.2.3.4:55
     971             :             {
     972           1 :                 addr::addr_range const & r(ips[0]);
     973           1 :                 CATCH_REQUIRE(r.has_from());
     974           1 :                 CATCH_REQUIRE_FALSE(r.has_to());
     975           1 :                 CATCH_REQUIRE_FALSE(r.is_range());
     976           1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
     977           1 :                 addr::addr f(r.get_from());
     978           1 :                 CATCH_REQUIRE(f.is_ipv4());
     979           1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
     980           1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
     981           1 :                 CATCH_REQUIRE(f.get_port() == 55);
     982           1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
     983           1 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
     984           1 :                 f.get_mask(mask);
     985          17 :                 for(int idx(0); idx < 16; ++idx)
     986             :                 {
     987          16 :                     CATCH_REQUIRE(mask[idx] == 255);
     988             :                 }
     989             :             }
     990             : 
     991             :             // 5.6.7.8
     992             :             {
     993           1 :                 addr::addr_range const & r(ips[1]);
     994           1 :                 CATCH_REQUIRE(r.has_from());
     995           1 :                 CATCH_REQUIRE_FALSE(r.has_to());
     996           1 :                 CATCH_REQUIRE_FALSE(r.is_range());
     997           1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
     998           1 :                 addr::addr f(r.get_from());
     999           1 :                 CATCH_REQUIRE(f.is_ipv4());
    1000           1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
    1001           1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
    1002           1 :                 CATCH_REQUIRE(f.get_port() == 0);
    1003           1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1004           1 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1005           1 :                 f.get_mask(mask);
    1006          17 :                 for(int idx(0); idx < 16; ++idx)
    1007             :                 {
    1008          16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1009             :                 }
    1010             :             }
    1011             : 
    1012             :             // 10.11.12.99:77
    1013             :             {
    1014           1 :                 addr::addr_range const & r(ips[2]);
    1015           1 :                 CATCH_REQUIRE(r.has_from());
    1016           1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1017           1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1018           1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1019           1 :                 addr::addr f(r.get_from());
    1020           1 :                 CATCH_REQUIRE(f.is_ipv4());
    1021           1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
    1022           1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
    1023           1 :                 CATCH_REQUIRE(f.get_port() == 77);
    1024           1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1025           1 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1026           1 :                 f.get_mask(mask);
    1027          17 :                 for(int idx(0); idx < 16; ++idx)
    1028             :                 {
    1029          16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1030             :                 }
    1031             :             }
    1032             :         }
    1033             : 
    1034           6 :         CATCH_SECTION("3 IPs separated by commas and/or spaces")
    1035             :         {
    1036           2 :             addr::addr_parser p;
    1037           1 :             p.set_protocol(IPPROTO_TCP);
    1038           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_COMMAS, true);
    1039           1 :             p.set_allow(addr::addr_parser::flag_t::MULTI_ADDRESSES_SPACES, true);
    1040           2 :             addr::addr_range::vector_t ips(p.parse(" 1.2.3.4:55,, 5.6.7.8 , 10.11.12.99:77 "));
    1041           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1042           1 :             CATCH_REQUIRE(ips.size() == 3);
    1043             : 
    1044           1 :             uint8_t mask[16] = {};
    1045             : 
    1046             :             // 1.2.3.4:55
    1047             :             {
    1048           1 :                 addr::addr_range const & r(ips[0]);
    1049           1 :                 CATCH_REQUIRE(r.has_from());
    1050           1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1051           1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1052           1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1053           1 :                 addr::addr f(r.get_from());
    1054           1 :                 CATCH_REQUIRE(f.is_ipv4());
    1055           1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
    1056           1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "1.2.3.4");
    1057           1 :                 CATCH_REQUIRE(f.get_port() == 55);
    1058           1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1059           1 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1060           1 :                 f.get_mask(mask);
    1061          17 :                 for(int idx(0); idx < 16; ++idx)
    1062             :                 {
    1063          16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1064             :                 }
    1065             :             }
    1066             : 
    1067             :             // 5.6.7.8
    1068             :             {
    1069           1 :                 addr::addr_range const & r(ips[1]);
    1070           1 :                 CATCH_REQUIRE(r.has_from());
    1071           1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1072           1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1073           1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1074           1 :                 addr::addr f(r.get_from());
    1075           1 :                 CATCH_REQUIRE(f.is_ipv4());
    1076           1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
    1077           1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "5.6.7.8");
    1078           1 :                 CATCH_REQUIRE(f.get_port() == 0);
    1079           1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1080           1 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1081           1 :                 f.get_mask(mask);
    1082          17 :                 for(int idx(0); idx < 16; ++idx)
    1083             :                 {
    1084          16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1085             :                 }
    1086             :             }
    1087             : 
    1088             :             // 10.11.12.99:77
    1089             :             {
    1090           1 :                 addr::addr_range const & r(ips[2]);
    1091           1 :                 CATCH_REQUIRE(r.has_from());
    1092           1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1093           1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1094           1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1095           1 :                 addr::addr f(r.get_from());
    1096           1 :                 CATCH_REQUIRE(f.is_ipv4());
    1097           1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
    1098           1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "10.11.12.99");
    1099           1 :                 CATCH_REQUIRE(f.get_port() == 77);
    1100           1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1101           1 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1102           1 :                 f.get_mask(mask);
    1103          17 :                 for(int idx(0); idx < 16; ++idx)
    1104             :                 {
    1105          16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1106             :                 }
    1107             :             }
    1108             :         }
    1109             :     }
    1110             : 
    1111          32 :     CATCH_GIVEN("addr_parser() with numeric only IPv4 addresses")
    1112             :     {
    1113           6 :         CATCH_SECTION("Simple numeric IPv4")
    1114             :         {
    1115           2 :             addr::addr_parser p;
    1116           1 :             p.set_protocol(IPPROTO_TCP);
    1117           1 :             p.set_allow(addr::addr_parser::flag_t::ADDRESS_LOOKUP, false);
    1118           2 :             addr::addr_range::vector_t ips(p.parse("4.3.1.2:3003"));
    1119           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1120           1 :             CATCH_REQUIRE(ips.size() == 1);
    1121             : 
    1122           1 :             addr::addr_range const & r(ips[0]);
    1123           1 :             CATCH_REQUIRE(r.has_from());
    1124           1 :             CATCH_REQUIRE_FALSE(r.has_to());
    1125           1 :             CATCH_REQUIRE_FALSE(r.is_range());
    1126           1 :             CATCH_REQUIRE_FALSE(r.is_empty());
    1127           1 :             addr::addr f(r.get_from());
    1128           1 :             CATCH_REQUIRE(f.is_ipv4());
    1129           1 :             CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "4.3.1.2");
    1130           1 :             CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "4.3.1.2");
    1131           1 :             CATCH_REQUIRE(f.get_port() == 3003);
    1132           1 :             CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1133           1 :             CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1134           1 :             uint8_t mask[16] = {};
    1135           1 :             f.get_mask(mask);
    1136          17 :             for(int idx(0); idx < 16; ++idx)
    1137             :             {
    1138          16 :                 CATCH_REQUIRE(mask[idx] == 255);
    1139             :             }
    1140             :         }
    1141             : 
    1142           6 :         CATCH_SECTION("Invalid domain name address when we only accept numeric IPs")
    1143             :         {
    1144           2 :             addr::addr_parser p;
    1145           1 :             p.set_protocol(IPPROTO_TCP);
    1146           1 :             p.set_allow(addr::addr_parser::flag_t::ADDRESS_LOOKUP, false);
    1147           2 :             addr::addr_range::vector_t ips(p.parse("www.example.com:4471"));
    1148           1 :             CATCH_REQUIRE(p.has_errors());
    1149           1 :             CATCH_REQUIRE(p.error_count() == 1);
    1150           1 :             CATCH_REQUIRE(p.error_messages() == "Unknown address in \"www.example.com\" (no DNS lookup was allowed).\n");
    1151           1 :             CATCH_REQUIRE(ips.size() == 0);
    1152             :         }
    1153             : 
    1154           6 :         CATCH_SECTION("Invalid port: service name not allowed")
    1155             :         {
    1156           2 :             addr::addr_parser p;
    1157           1 :             p.set_protocol(IPPROTO_TCP);
    1158           1 :             p.set_allow(addr::addr_parser::flag_t::ADDRESS_LOOKUP, false);
    1159           2 :             addr::addr_range::vector_t ips(p.parse("192.168.255.32:https"));
    1160           1 :             CATCH_REQUIRE(p.has_errors());
    1161           1 :             CATCH_REQUIRE(p.error_count() == 1);
    1162           1 :             CATCH_REQUIRE(p.error_messages() == "Invalid port in \"https\" (no service name lookup allowed).\n");
    1163           1 :             CATCH_REQUIRE(ips.size() == 0);
    1164             :         }
    1165             :     }
    1166          16 : }
    1167             : 
    1168             : 
    1169           5 : CATCH_TEST_CASE( "ipv4::ports", "[ipv4]" )
    1170             : {
    1171           6 :     CATCH_GIVEN("addr_parser() with IPv4 addresses and port")
    1172             :     {
    1173           6 :         CATCH_SECTION("verify port")
    1174             :         {
    1175       65537 :             for(int port(0); port < 65536; ++port)
    1176             :             {
    1177       65536 :                 int proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1178      131072 :                 addr::addr_parser p;
    1179       65536 :                 p.set_protocol(proto);
    1180      131072 :                 addr::addr_range::vector_t ips(p.parse("192.168.12.199:" + std::to_string(port)));
    1181       65536 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1182       65536 :                 CATCH_REQUIRE(ips.size() == 1);
    1183       65536 :                 addr::addr_range const & r(ips[0]);
    1184       65536 :                 addr::addr f(r.get_from());
    1185       65536 :                 CATCH_REQUIRE(f.is_ipv4());
    1186       65536 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "192.168.12.199");
    1187       65536 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "192.168.12.199");
    1188       65536 :                 CATCH_REQUIRE(f.get_port() == port);
    1189       65536 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    1190       65536 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1191             :             }
    1192             :         }
    1193             : 
    1194           6 :         CATCH_SECTION("default address with various port")
    1195             :         {
    1196         101 :             for(int idx(0); idx < 100; ++idx)
    1197             :             {
    1198         100 :                 uint16_t const port(rand());
    1199         200 :                 addr::addr_parser p;
    1200         100 :                 p.set_protocol(IPPROTO_TCP);
    1201         100 :                 p.set_default_address("5.5.5.5");
    1202         100 :                 CATCH_REQUIRE(p.get_default_address4() == "5.5.5.5");
    1203         100 :                 CATCH_REQUIRE(p.get_default_address6() == "");
    1204         200 :                 addr::addr_range::vector_t ips(p.parse(":" + std::to_string(static_cast<int>(port))));
    1205         100 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1206         100 :                 CATCH_REQUIRE(ips.size() == 1);
    1207         100 :                 addr::addr_range const & r(ips[0]);
    1208         100 :                 CATCH_REQUIRE(r.has_from());
    1209         100 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1210         100 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1211         100 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1212         100 :                 addr::addr f(r.get_from());
    1213         100 :                 CATCH_REQUIRE(f.is_ipv4());
    1214         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)));
    1215         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)));
    1216         100 :                 CATCH_REQUIRE(f.get_port() == port);
    1217         100 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1218         100 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1219             :             }
    1220             :         }
    1221             : 
    1222           6 :         CATCH_SECTION("address with default port")
    1223             :         {
    1224          26 :             for(int idx(0); idx < 25; ++idx)
    1225             :             {
    1226          25 :                 uint16_t const port(rand());
    1227          50 :                 addr::addr_parser p;
    1228          25 :                 p.set_protocol(IPPROTO_TCP);
    1229          25 :                 p.set_default_port(port);
    1230          25 :                 CATCH_REQUIRE(p.get_default_port() == port);
    1231          50 :                 addr::addr_range::vector_t ips(p.parse("5.5.5.5"));
    1232          25 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1233          25 :                 CATCH_REQUIRE(ips.size() == 1);
    1234          25 :                 addr::addr_range const & r(ips[0]);
    1235          25 :                 CATCH_REQUIRE(r.has_from());
    1236          25 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1237          25 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1238          25 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1239          25 :                 addr::addr f(r.get_from());
    1240          25 :                 CATCH_REQUIRE(f.is_ipv4());
    1241          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)));
    1242          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)));
    1243          25 :                 CATCH_REQUIRE(f.get_port() == port);
    1244          25 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1245          25 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1246             :             }
    1247             : 
    1248          26 :             for(int idx(0); idx < 25; ++idx)
    1249             :             {
    1250          25 :                 uint16_t const port(rand());
    1251          50 :                 addr::addr_parser p;
    1252          25 :                 p.set_protocol(IPPROTO_TCP);
    1253          25 :                 p.set_default_port(port);
    1254          25 :                 CATCH_REQUIRE(p.get_default_port() == port);
    1255          50 :                 addr::addr_range::vector_t ips(p.parse("5.5.5.5:"));
    1256          25 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1257          25 :                 CATCH_REQUIRE(ips.size() == 1);
    1258          25 :                 addr::addr_range const & r(ips[0]);
    1259          25 :                 CATCH_REQUIRE(r.has_from());
    1260          25 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1261          25 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1262          25 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1263          25 :                 addr::addr f(r.get_from());
    1264          25 :                 CATCH_REQUIRE(f.is_ipv4());
    1265          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)));
    1266          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)));
    1267          25 :                 CATCH_REQUIRE(f.get_port() == port);
    1268          25 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1269          25 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1270             :             }
    1271             :         }
    1272             :     }
    1273           3 : }
    1274             : 
    1275             : 
    1276           9 : CATCH_TEST_CASE( "ipv4::masks", "[ipv4]" )
    1277             : {
    1278          14 :     CATCH_GIVEN("addr_parser() of address:port/mask")
    1279             :     {
    1280          14 :         CATCH_SECTION("mask allowed, but no mask")
    1281             :         {
    1282           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1283           1 :             int const port(rand() & 0xFFFF);
    1284           2 :             addr::addr_parser p;
    1285           1 :             p.set_protocol(proto);
    1286           1 :             p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1287           2 :             addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port)));
    1288           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1289           1 :             CATCH_REQUIRE(ips.size() == 1);
    1290           1 :             addr::addr_range const & r(ips[0]);
    1291           1 :             addr::addr f(r.get_from());
    1292           1 :             CATCH_REQUIRE(f.is_ipv4());
    1293           2 :             std::string result("172.19.6.91:" + std::to_string(port) + "/255.255.255.255");
    1294           1 :             CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1295           1 :             CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1296           1 :             CATCH_REQUIRE(f.get_port() == port);
    1297           1 :             CATCH_REQUIRE(f.get_protocol() == proto);
    1298           1 :             CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1299             :         }
    1300             : 
    1301          14 :         CATCH_SECTION("empty mask")
    1302             :         {
    1303           1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1304           1 :             int const port(rand() & 0xFFFF);
    1305           2 :             addr::addr_parser p;
    1306           1 :             p.set_protocol(proto);
    1307           1 :             p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1308           2 :             addr::addr_range::vector_t ips(p.parse("172.18.5.91:" + std::to_string(port) + "/"));
    1309           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1310           1 :             CATCH_REQUIRE(ips.size() == 1);
    1311           1 :             addr::addr_range const & r(ips[0]);
    1312           1 :             addr::addr f(r.get_from());
    1313           1 :             CATCH_REQUIRE(f.is_ipv4());
    1314           2 :             std::string result("172.18.5.91:" + std::to_string(port) + "/255.255.255.255");
    1315           1 :             CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1316           1 :             CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1317           1 :             CATCH_REQUIRE(f.get_port() == port);
    1318           1 :             CATCH_REQUIRE(f.get_protocol() == proto);
    1319           1 :             CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1320             :         }
    1321             : 
    1322          14 :         CATCH_SECTION("one number masks")
    1323             :         {
    1324          34 :             for(int idx(0); idx <= 32; ++idx)
    1325             :             {
    1326          33 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1327          33 :                 int const port(rand() & 0xFFFF);
    1328          66 :                 addr::addr_parser p;
    1329          33 :                 p.set_protocol(proto);
    1330          33 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1331          66 :                 addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port) + "/" + std::to_string(idx)));
    1332          33 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1333          33 :                 CATCH_REQUIRE(ips.size() == 1);
    1334          33 :                 addr::addr_range const & r(ips[0]);
    1335          33 :                 addr::addr f(r.get_from());
    1336          33 :                 CATCH_REQUIRE(f.is_ipv4());
    1337          33 :                 uint64_t const mask(std::numeric_limits<uint64_t>::max() << (32 - idx));
    1338          33 :                 std::string mask_str(
    1339          66 :                           std::to_string((mask >> 24) & 255)
    1340          99 :                         + "."
    1341         132 :                         + std::to_string((mask >> 16) & 255)
    1342          99 :                         + "."
    1343         132 :                         + std::to_string((mask >>  8) & 255)
    1344          99 :                         + "."
    1345         132 :                         + std::to_string((mask >>  0) & 255));
    1346          66 :                 std::string result("172.17.3.91:" + std::to_string(port) + "/" + mask_str);
    1347          33 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1348          33 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1349          33 :                 CATCH_REQUIRE(f.get_port() == port);
    1350          33 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    1351          33 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1352             :             }
    1353             :         }
    1354             : 
    1355          14 :         CATCH_SECTION("address like mask")
    1356             :         {
    1357          26 :             for(int idx(0); idx < 25; ++idx)
    1358             :             {
    1359          25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1360          25 :                 int const port(rand() & 0xFFFF);
    1361          50 :                 addr::addr_parser p;
    1362          25 :                 p.set_protocol(proto);
    1363          25 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1364             :                 // when specified as an IP, the mask can be absolutely anything
    1365          25 :                 uint8_t mask[4];
    1366         125 :                 for(int j(0); j < 4; ++j)
    1367             :                 {
    1368         100 :                     mask[j] = rand();
    1369             :                 }
    1370          25 :                 std::string const mask_str(
    1371          50 :                               std::to_string(static_cast<int>(mask[0]))
    1372          75 :                             + "."
    1373         100 :                             + std::to_string(static_cast<int>(mask[1]))
    1374          75 :                             + "."
    1375         100 :                             + std::to_string(static_cast<int>(mask[2]))
    1376          75 :                             + "."
    1377         100 :                             + std::to_string(static_cast<int>(mask[3])));
    1378          50 :                 addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port) + "/" + mask_str));
    1379          25 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1380          25 :                 CATCH_REQUIRE(ips.size() == 1);
    1381          25 :                 addr::addr_range const & r(ips[0]);
    1382          25 :                 addr::addr f(r.get_from());
    1383          25 :                 CATCH_REQUIRE(f.is_ipv4());
    1384          50 :                 std::string result("172.17.3.91:" + std::to_string(port) + "/" + mask_str);
    1385          25 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1386          25 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1387          25 :                 CATCH_REQUIRE(f.get_port() == port);
    1388          25 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    1389          25 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1390             :             }
    1391             :         }
    1392             : 
    1393          14 :         CATCH_SECTION("address like default mask")
    1394             :         {
    1395          26 :             for(int idx(0); idx < 25; ++idx)
    1396             :             {
    1397          25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1398          25 :                 int const port(rand() & 0xFFFF);
    1399          50 :                 addr::addr_parser p;
    1400          25 :                 p.set_protocol(proto);
    1401          25 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1402             :                 // when specified as an IP, the mask can be absolutely anything
    1403             :                 // (here the mask is a string an it will be parsed by the
    1404             :                 // parser if required)
    1405             :                 //
    1406          25 :                 uint8_t mask[4];
    1407         125 :                 for(int j(0); j < 4; ++j)
    1408             :                 {
    1409         100 :                     mask[j] = rand();
    1410             :                 }
    1411          25 :                 std::string const mask_str(
    1412          50 :                               std::to_string(static_cast<int>(mask[0]))
    1413          75 :                             + "."
    1414         100 :                             + std::to_string(static_cast<int>(mask[1]))
    1415          75 :                             + "."
    1416         100 :                             + std::to_string(static_cast<int>(mask[2]))
    1417          75 :                             + "."
    1418         100 :                             + std::to_string(static_cast<int>(mask[3])));
    1419          25 :                 p.set_default_mask(mask_str);
    1420          50 :                 addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port)));
    1421          25 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1422          25 :                 CATCH_REQUIRE(ips.size() == 1);
    1423          25 :                 addr::addr_range const & r(ips[0]);
    1424          25 :                 addr::addr f(r.get_from());
    1425          25 :                 CATCH_REQUIRE(f.is_ipv4());
    1426          50 :                 std::string result("172.17.3.91:" + std::to_string(port) + "/" + mask_str);
    1427          25 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1428          25 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1429          25 :                 CATCH_REQUIRE(f.get_port() == port);
    1430          25 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    1431          25 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1432          25 :                 uint8_t verify_mask[16];
    1433          25 :                 f.get_mask(verify_mask);
    1434         325 :                 for(int j(0); j < 16 - 4; ++j)
    1435             :                 {
    1436         300 :                     CATCH_REQUIRE(verify_mask[j] == 255);
    1437             :                 }
    1438         125 :                 for(int j(12); j < 16; ++j)
    1439             :                 {
    1440         100 :                     CATCH_REQUIRE(verify_mask[j] == mask[j - 12]);
    1441             :                 }
    1442             :             }
    1443             :         }
    1444             : 
    1445          14 :         CATCH_SECTION("address like mask with a default")
    1446             :         {
    1447          26 :             for(int idx(0); idx < 25; ++idx)
    1448             :             {
    1449          25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1450          25 :                 int const port(rand() & 0xFFFF);
    1451          50 :                 addr::addr_parser p;
    1452          25 :                 p.set_protocol(proto);
    1453          25 :                 p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1454             : 
    1455             :                 // here we want a default and an IP with a specific mask
    1456             :                 // to make sure that the specific mask has priority
    1457             :                 //
    1458          25 :                 uint8_t mask[4];
    1459         125 :                 for(int j(0); j < 4; ++j)
    1460             :                 {
    1461         100 :                     mask[j] = rand();
    1462             :                 }
    1463          25 :                 std::string const mask_str(
    1464          50 :                               std::to_string(static_cast<int>(mask[0]))
    1465          75 :                             + "."
    1466         100 :                             + std::to_string(static_cast<int>(mask[1]))
    1467          75 :                             + "."
    1468         100 :                             + std::to_string(static_cast<int>(mask[2]))
    1469          75 :                             + "."
    1470         100 :                             + std::to_string(static_cast<int>(mask[3])));
    1471             : 
    1472          25 :                 uint8_t default_mask[4];
    1473         125 :                 for(int j(0); j < 4; ++j)
    1474             :                 {
    1475         100 :                     default_mask[j] = rand();
    1476             :                 }
    1477          25 :                 std::string const default_mask_str(
    1478          50 :                               std::to_string(static_cast<int>(default_mask[0]))
    1479          75 :                             + "."
    1480         100 :                             + std::to_string(static_cast<int>(default_mask[1]))
    1481          75 :                             + "."
    1482         100 :                             + std::to_string(static_cast<int>(default_mask[2]))
    1483          75 :                             + "."
    1484         100 :                             + std::to_string(static_cast<int>(default_mask[3])));
    1485          25 :                 p.set_default_mask(default_mask_str);
    1486             : 
    1487          50 :                 addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port) + "/" + mask_str));
    1488          25 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1489          25 :                 CATCH_REQUIRE(ips.size() == 1);
    1490          25 :                 addr::addr_range const & r(ips[0]);
    1491          25 :                 addr::addr f(r.get_from());
    1492          25 :                 CATCH_REQUIRE(f.is_ipv4());
    1493          50 :                 std::string result("172.17.3.91:" + std::to_string(port) + "/" + mask_str);
    1494          25 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1495          25 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ALL) == result);
    1496          25 :                 CATCH_REQUIRE(f.get_port() == port);
    1497          25 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    1498          25 :                 CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1499          25 :                 uint8_t verify_mask[16];
    1500          25 :                 f.get_mask(verify_mask);
    1501         325 :                 for(int j(0); j < 16 - 4; ++j)
    1502             :                 {
    1503         300 :                     CATCH_REQUIRE(verify_mask[j] == 255);
    1504             :                 }
    1505         125 :                 for(int j(12); j < 16; ++j)
    1506             :                 {
    1507         100 :                     CATCH_REQUIRE(verify_mask[j] == mask[j - 12]);
    1508             :                 }
    1509             :             }
    1510             :         }
    1511             : 
    1512          14 :         CATCH_SECTION("two addresses and a mask for a match / no match")
    1513             :         {
    1514           1 :             int const port1(rand() & 0xFFFF);
    1515           2 :             addr::addr_parser p;
    1516           1 :             p.set_allow(addr::addr_parser::flag_t::MASK, true);
    1517             : 
    1518             :             // parse the IP with a mask
    1519             :             //
    1520           1 :             int proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1521           1 :             p.set_protocol(proto);
    1522           2 :             addr::addr_range::vector_t ips1(p.parse("192.168.0.0:" + std::to_string(port1) + "/16"));
    1523           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1524           1 :             CATCH_REQUIRE(ips1.size() == 1);
    1525           1 :             addr::addr_range const & r1(ips1[0]);
    1526           1 :             addr::addr f1(r1.get_from());
    1527           1 :             CATCH_REQUIRE(f1.is_ipv4());
    1528           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");
    1529           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");
    1530           1 :             CATCH_REQUIRE(f1.get_port() == port1);
    1531           1 :             CATCH_REQUIRE(f1.get_protocol() == proto);
    1532           1 :             CATCH_REQUIRE(f1.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1533             : 
    1534             :             // reuse parser
    1535             :             //
    1536           1 :             proto = rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP;
    1537           1 :             p.set_protocol(proto);
    1538           1 :             int const port2(rand() & 0xFFFF);
    1539           2 :             addr::addr_range::vector_t ips2(p.parse("192.168.5.36:" + std::to_string(port2)));
    1540           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1541           1 :             CATCH_REQUIRE(ips2.size() == 1);
    1542           1 :             addr::addr_range const & r2(ips2[0]);
    1543           1 :             addr::addr f2(r2.get_from());
    1544           1 :             CATCH_REQUIRE(f2.is_ipv4());
    1545           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");
    1546           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");
    1547           1 :             CATCH_REQUIRE(f2.get_port() == port2);
    1548           1 :             CATCH_REQUIRE(f2.get_protocol() == proto);
    1549           1 :             CATCH_REQUIRE(f2.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1550             : 
    1551             :             // 3rd with a mask along the full IP
    1552             :             //
    1553           1 :             proto = rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP;
    1554           1 :             p.set_protocol(proto);
    1555           1 :             int const port3(rand() & 0xFFFF);
    1556           2 :             addr::addr_range::vector_t ips3(p.parse("192.168.5.36:" + std::to_string(port3) + "/16"));
    1557           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1558           1 :             CATCH_REQUIRE(ips3.size() == 1);
    1559           1 :             addr::addr_range const & r3(ips3[0]);
    1560           1 :             addr::addr f3(r3.get_from());
    1561           1 :             CATCH_REQUIRE(f3.is_ipv4());
    1562           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");
    1563           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");
    1564           1 :             CATCH_REQUIRE(f3.get_port() == port3);
    1565           1 :             CATCH_REQUIRE(f3.get_protocol() == proto);
    1566           1 :             CATCH_REQUIRE(f3.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1567             : 
    1568             :             // just a side test
    1569             :             //
    1570           1 :             CATCH_REQUIRE(f1 != f2);
    1571           1 :             CATCH_REQUIRE(f1 != f3);
    1572           1 :             CATCH_REQUIRE(f2 == f3);
    1573             : 
    1574             :             // check whether p1 matches p2 and vice versa
    1575             :             //
    1576           1 :             CATCH_REQUIRE(f1.match(f2));          // f2 & mask1 == f1
    1577           1 :             CATCH_REQUIRE(f1.match(f3));          // f3 & mask1 == f1
    1578             : 
    1579           1 :             CATCH_REQUIRE_FALSE(f2.match(f1));    // f1 & mask2 != f2
    1580           1 :             CATCH_REQUIRE(f2.match(f3));          // f3 & mask2 == f2  (because f2 == f3 anyway)
    1581             : 
    1582           1 :             CATCH_REQUIRE(f3.match(f1));          // f1 & mask3 == f3
    1583           1 :             CATCH_REQUIRE(f3.match(f2));          // f2 & mask3 == f3
    1584             : 
    1585           1 :             f3.apply_mask();
    1586             : 
    1587           1 :             CATCH_REQUIRE(f1 != f2);
    1588           1 :             CATCH_REQUIRE(f1 == f3);
    1589           1 :             CATCH_REQUIRE(f2 != f3);
    1590             : 
    1591             :             // re-run the match() calls with f3 since it changed...
    1592             :             //
    1593           1 :             CATCH_REQUIRE(f1.match(f3));          // f3 & mask1 == f1
    1594             : 
    1595           1 :             CATCH_REQUIRE_FALSE(f2.match(f3));    // f3 & mask2 == f2  (because f2 != f3 anymore)
    1596             : 
    1597           1 :             CATCH_REQUIRE(f3.match(f1));          // f1 & mask3 == f3
    1598           1 :             CATCH_REQUIRE(f3.match(f2));          // f2 & mask3 == f3
    1599             :         }
    1600             :     }
    1601           7 : }
    1602             : 
    1603             : 
    1604           8 : CATCH_TEST_CASE( "ipv4::protocol", "[ipv4]" )
    1605             : {
    1606          12 :     CATCH_GIVEN("addr()")
    1607             :     {
    1608           2 :         addr::addr a;
    1609             : 
    1610           4 :         CATCH_SECTION("default protocol")
    1611             :         {
    1612           1 :             CATCH_REQUIRE(a.get_protocol() == IPPROTO_TCP);
    1613             :         }
    1614             : 
    1615           4 :         CATCH_SECTION("set_protocol()")
    1616             :         {
    1617             :             // setup a random protocol
    1618             :             //
    1619           1 :             int const start_protocol([]()
    1620             :                 {
    1621           1 :                     switch(rand() % 3)
    1622             :                     {
    1623           1 :                     case 0:
    1624           1 :                         return IPPROTO_IP;
    1625             : 
    1626           0 :                     case 1:
    1627           0 :                         return IPPROTO_TCP;
    1628             : 
    1629             :                     //case 2:
    1630           0 :                     default:
    1631           0 :                         return IPPROTO_UDP;
    1632             : 
    1633             :                     }
    1634           1 :                 }());
    1635           1 :             a.set_protocol(start_protocol);
    1636             : 
    1637             :             // test 100 invalid protocols
    1638             :             //
    1639         101 :             for(int idx(0); idx < 100; ++idx)
    1640             :             {
    1641             :                 int invalid_protocol;
    1642           0 :                 do
    1643             :                 {
    1644         100 :                     invalid_protocol = rand();
    1645             :                 }
    1646             :                 while(invalid_protocol == IPPROTO_IP
    1647         100 :                    || invalid_protocol == IPPROTO_TCP
    1648         200 :                    || invalid_protocol == IPPROTO_UDP);
    1649         100 :                 CATCH_REQUIRE_THROWS_AS(a.set_protocol(invalid_protocol), addr::addr_invalid_argument);
    1650             : 
    1651             :                 // make sure the protocol does not change on errors
    1652         100 :                 CATCH_REQUIRE(a.get_protocol() == start_protocol);
    1653             :             }
    1654             : 
    1655             :             // null string is not allowed
    1656             :             //
    1657           1 :             CATCH_REQUIRE_THROWS_AS(a.set_protocol(nullptr), addr::addr_invalid_argument);
    1658             : 
    1659             :             // other "invalid" (unsupported, really) string protocols
    1660             :             //
    1661           1 :             CATCH_REQUIRE_THROWS_AS(a.set_protocol("icmp"), addr::addr_invalid_argument);
    1662           1 :             CATCH_REQUIRE_THROWS_AS(a.set_protocol("raw"), addr::addr_invalid_argument);
    1663           1 :             CATCH_REQUIRE_THROWS_AS(a.set_protocol("hmp"), addr::addr_invalid_argument);
    1664             : 
    1665             :             // test all valid protocols (numeric)
    1666             :             //
    1667           1 :             a.set_protocol(IPPROTO_IP);
    1668           1 :             CATCH_REQUIRE(a.get_protocol() == IPPROTO_IP);
    1669           1 :             a.set_protocol(IPPROTO_TCP);
    1670           1 :             CATCH_REQUIRE(a.get_protocol() == IPPROTO_TCP);
    1671           1 :             a.set_protocol(IPPROTO_UDP);
    1672           1 :             CATCH_REQUIRE(a.get_protocol() == IPPROTO_UDP);
    1673             : 
    1674             :             // test all valid protocols (ascii)
    1675             :             //
    1676           1 :             a.set_protocol("ip");
    1677           1 :             CATCH_REQUIRE(a.get_protocol() == IPPROTO_IP);
    1678           1 :             a.set_protocol("tcp");
    1679           1 :             CATCH_REQUIRE(a.get_protocol() == IPPROTO_TCP);
    1680           1 :             a.set_protocol("udp");
    1681           1 :             CATCH_REQUIRE(a.get_protocol() == IPPROTO_UDP);
    1682             :         }
    1683             :     }
    1684             : 
    1685          12 :     CATCH_GIVEN("addr_parser()")
    1686             :     {
    1687           6 :         addr::addr_parser p;
    1688             : 
    1689           6 :         CATCH_SECTION("verify default")
    1690             :         {
    1691           1 :             CATCH_REQUIRE(p.get_protocol() == -1);
    1692             :         }
    1693             : 
    1694           6 :         CATCH_SECTION("test 3 allowed protocols")
    1695             :         {
    1696             :             // by string
    1697             :             //
    1698           1 :             p.set_protocol("ip");
    1699           1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_IP);
    1700           1 :             p.set_protocol("tcp");
    1701           1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_TCP);
    1702           1 :             p.set_protocol("udp");
    1703           1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_UDP);
    1704             : 
    1705             :             // numerically
    1706             :             //
    1707           1 :             p.set_protocol(IPPROTO_IP);
    1708           1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_IP);
    1709           1 :             p.set_protocol(IPPROTO_TCP);
    1710           1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_TCP);
    1711           1 :             p.set_protocol(IPPROTO_UDP);
    1712           1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_UDP);
    1713             :         }
    1714             : 
    1715           6 :         CATCH_SECTION("verify clearing works")
    1716             :         {
    1717           1 :             p.set_protocol("ip");
    1718           1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_IP);
    1719           1 :             p.clear_protocol();
    1720           1 :             CATCH_REQUIRE(p.get_protocol() == -1);
    1721             : 
    1722           1 :             p.set_protocol("tcp");
    1723           1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_TCP);
    1724           1 :             p.clear_protocol();
    1725           1 :             CATCH_REQUIRE(p.get_protocol() == -1);
    1726             : 
    1727           1 :             p.set_protocol("udp");
    1728           1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_UDP);
    1729           1 :             p.clear_protocol();
    1730           1 :             CATCH_REQUIRE(p.get_protocol() == -1);
    1731             :         }
    1732             :     }
    1733             : 
    1734          12 :     CATCH_GIVEN("addr_parser with any protocol")
    1735             :     {
    1736           1 :         addr::addr a;
    1737             : 
    1738           2 :         CATCH_SECTION("get address with all protocols")
    1739             :         {
    1740           2 :             addr::addr_parser p;
    1741             :             //p.set_protocol(...); -- by default we'll get all the protocols supported
    1742           2 :             addr::addr_range::vector_t ips(p.parse("127.0.0.1"));
    1743           1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1744           1 :             CATCH_REQUIRE(!ips.empty());
    1745           4 :             for(size_t idx(0); idx < ips.size(); ++idx)
    1746             :             {
    1747           3 :                 addr::addr_range const & r(ips[idx]);
    1748           3 :                 CATCH_REQUIRE(r.has_from());
    1749           3 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1750           3 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1751           3 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1752           3 :                 addr::addr f(r.get_from());
    1753           3 :                 if(f.is_ipv4())
    1754             :                 {
    1755           3 :                     CATCH_REQUIRE(f.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "127.0.0.1");
    1756           3 :                     CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "127.0.0.1");
    1757           3 :                     CATCH_REQUIRE(f.get_port() == 0);
    1758             :                     //CATCH_REQUIRE(f.get_protocol() == ...); -- may be TCP, UDP, IP
    1759           3 :                     CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LOOPBACK);
    1760             :                 }
    1761             :                 else
    1762             :                 {
    1763           0 :                     CATCH_REQUIRE(f.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::1");
    1764           0 :                     CATCH_REQUIRE(f.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::1");
    1765           0 :                     CATCH_REQUIRE(f.get_port() == 0);
    1766             :                     //CATCH_REQUIRE(f.get_protocol() == ...); -- may be TCP, UDP, IP
    1767           0 :                     CATCH_REQUIRE(f.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LOOPBACK);
    1768             :                 }
    1769             :             }
    1770             :         }
    1771             :     }
    1772           6 : }
    1773             : 
    1774             : 
    1775          10 : CATCH_TEST_CASE( "ipv4::network_type", "[ipv4]" )
    1776             : {
    1777          16 :     CATCH_GIVEN("addr()")
    1778             :     {
    1779           8 :         addr::addr a;
    1780             : 
    1781          16 :         CATCH_SECTION("any (0.0.0.0)")
    1782             :         {
    1783           1 :             struct sockaddr_in in = sockaddr_in();
    1784           1 :             in.sin_family = AF_INET;
    1785           1 :             in.sin_port = htons(rand());
    1786           1 :             in.sin_addr.s_addr = 0;
    1787             : 
    1788             :             // verify network type
    1789             :             //
    1790           1 :             a.set_ipv4(in);
    1791             : 
    1792           1 :             CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_ANY);
    1793           1 :             CATCH_REQUIRE(a.get_network_type_string() == "Any");
    1794             :         }
    1795             : 
    1796          16 :         CATCH_SECTION("private address 10.x.x.x/8")
    1797             :         {
    1798          11 :             for(int idx(0); idx < 10; ++idx)
    1799             :             {
    1800          10 :                 struct sockaddr_in in = sockaddr_in();
    1801          10 :                 in.sin_family = AF_INET;
    1802          10 :                 in.sin_port = htons(rand());
    1803             :                 uint32_t address((10 << 24)
    1804          10 :                               | ((rand() & 255) << 16)
    1805          10 :                               | ((rand() & 255) << 8)
    1806          10 :                               | ((rand() & 255) << 0));
    1807          10 :                 in.sin_addr.s_addr = htonl(address);
    1808             : 
    1809             :                 // verify network type
    1810             :                 //
    1811          10 :                 a.set_ipv4(in);
    1812          10 :                 CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1813          10 :                 CATCH_REQUIRE(a.get_network_type_string() == "Private");
    1814             :             }
    1815             :         }
    1816             : 
    1817          16 :         CATCH_SECTION("private address 172.16.x.x/12")
    1818             :         {
    1819          11 :             for(int idx(0); idx < 10; ++idx)
    1820             :             {
    1821          10 :                 struct sockaddr_in in = sockaddr_in();
    1822          10 :                 in.sin_family = AF_INET;
    1823          10 :                 in.sin_port = htons(rand());
    1824             :                 uint32_t address((172 << 24)
    1825          10 :                               | (((rand() & 15) | 16) << 16)
    1826          10 :                               | ((rand() & 255) << 8)
    1827          10 :                               | ((rand() & 255) << 0));
    1828          10 :                 in.sin_addr.s_addr = htonl(address);
    1829             : 
    1830             :                 // verify network type
    1831             :                 //
    1832          10 :                 a.set_ipv4(in);
    1833          10 :                 CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1834          10 :                 CATCH_REQUIRE(a.get_network_type_string() == "Private");
    1835             :             }
    1836             :         }
    1837             : 
    1838          16 :         CATCH_SECTION("private address 192.168.x.x/16")
    1839             :         {
    1840          11 :             for(int idx(0); idx < 10; ++idx)
    1841             :             {
    1842          10 :                 struct sockaddr_in in = sockaddr_in();
    1843          10 :                 in.sin_family = AF_INET;
    1844          10 :                 in.sin_port = htons(rand());
    1845             :                 uint32_t address((192 << 24)
    1846             :                               |  (168 << 16)
    1847          10 :                               | ((rand() & 255) << 8)
    1848          10 :                               | ((rand() & 255) << 0));
    1849          10 :                 in.sin_addr.s_addr = htonl(address);
    1850             : 
    1851             :                 // verify network type
    1852             :                 //
    1853          10 :                 a.set_ipv4(in);
    1854          10 :                 CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1855          10 :                 CATCH_REQUIRE(a.get_network_type_string() == "Private");
    1856             :             }
    1857             :         }
    1858             : 
    1859          16 :         CATCH_SECTION("private address 100.66.x.x/10")
    1860             :         {
    1861          11 :             for(int idx(0); idx < 10; ++idx)
    1862             :             {
    1863          10 :                 struct sockaddr_in in = sockaddr_in();
    1864          10 :                 in.sin_family = AF_INET;
    1865          10 :                 in.sin_port = htons(rand());
    1866             :                 uint32_t address((100 << 24)
    1867          10 :                               | (((rand() & 63) | 64) << 16)
    1868          10 :                               | ((rand() & 255) << 8)
    1869          10 :                               | ((rand() & 255) << 0));
    1870          10 :                 in.sin_addr.s_addr = htonl(address);
    1871             : 
    1872             :                 // verify network type
    1873             :                 //
    1874          10 :                 a.set_ipv4(in);
    1875          10 :                 CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_CARRIER);
    1876          10 :                 CATCH_REQUIRE(a.get_network_type_string() == "Carrier");
    1877             :             }
    1878             :         }
    1879             : 
    1880          16 :         CATCH_SECTION("private address 169.254.x.x/16")
    1881             :         {
    1882          11 :             for(int idx(0); idx < 10; ++idx)
    1883             :             {
    1884          10 :                 struct sockaddr_in in = sockaddr_in();
    1885          10 :                 in.sin_family = AF_INET;
    1886          10 :                 in.sin_port = htons(rand());
    1887             :                 uint32_t address((169 << 24)
    1888             :                               |  (254 << 16)
    1889          10 :                               | ((rand() & 255) << 8)
    1890          10 :                               | ((rand() & 255) << 0));
    1891          10 :                 in.sin_addr.s_addr = htonl(address);
    1892             : 
    1893             :                 // verify network type
    1894             :                 //
    1895          10 :                 a.set_ipv4(in);
    1896          10 :                 CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LINK_LOCAL);
    1897          10 :                 CATCH_REQUIRE(a.get_network_type_string() == "Local Link");
    1898             :             }
    1899             :         }
    1900             : 
    1901          16 :         CATCH_SECTION("private address 224.x.x.x/4")
    1902             :         {
    1903          11 :             for(int idx(0); idx < 10; ++idx)
    1904             :             {
    1905          10 :                 struct sockaddr_in in = sockaddr_in();
    1906          10 :                 in.sin_family = AF_INET;
    1907          10 :                 in.sin_port = htons(rand());
    1908          10 :                 uint32_t address((((rand() & 15) | 224) << 24)
    1909          10 :                               | ((rand() & 255) << 16)
    1910          10 :                               | ((rand() & 255) << 8)
    1911          10 :                               | ((rand() & 255) << 0));
    1912          10 :                 in.sin_addr.s_addr = htonl(address);
    1913             : 
    1914             :                 // verify network type
    1915             :                 //
    1916          10 :                 a.set_ipv4(in);
    1917          10 :                 CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_MULTICAST);
    1918          10 :                 CATCH_REQUIRE(a.get_network_type_string() == "Multicast");
    1919             : 
    1920             :                 // make sure no interface uses that IP
    1921             :                 //
    1922          10 :                 CATCH_REQUIRE(addr::find_addr_interface(a, false) == nullptr);
    1923             :             }
    1924             :         }
    1925             : 
    1926          16 :         CATCH_SECTION("private address 127.x.x.x/8")
    1927             :         {
    1928          11 :             for(int idx(0); idx < 10; ++idx)
    1929             :             {
    1930          10 :                 struct sockaddr_in in = sockaddr_in();
    1931          10 :                 in.sin_family = AF_INET;
    1932          10 :                 in.sin_port = htons(rand());
    1933             :                 uint32_t address((127 << 24)
    1934          10 :                               | ((rand() & 255) << 16)
    1935          10 :                               | ((rand() & 255) << 8)
    1936          10 :                               | ((rand() & 255) << 0));
    1937          10 :                 in.sin_addr.s_addr = htonl(address);
    1938             : 
    1939             :                 // verify network type
    1940             :                 //
    1941          10 :                 a.set_ipv4(in);
    1942          10 :                 CATCH_REQUIRE(a.get_network_type() == addr::addr::network_type_t::NETWORK_TYPE_LOOPBACK);
    1943          10 :                 CATCH_REQUIRE(a.get_network_type_string() == "Loopback");
    1944             :             }
    1945             :         }
    1946             :     }
    1947           8 : }
    1948             : 
    1949             : 
    1950           8 : CATCH_TEST_CASE( "ipv4::network", "[ipv4]" )
    1951             : {
    1952          12 :     CATCH_GIVEN("set_from_socket()")
    1953             :     {
    1954          12 :         CATCH_SECTION("invalid socket")
    1955             :         {
    1956           1 :             addr::addr a;
    1957           1 :             CATCH_REQUIRE_THROWS_AS(a.set_from_socket(-1, true),  addr::addr_invalid_argument);
    1958           1 :             CATCH_REQUIRE_THROWS_AS(a.set_from_socket(-1, false), addr::addr_invalid_argument);
    1959             :         }
    1960             : 
    1961          12 :         CATCH_SECTION("non-opened file descriptor")
    1962             :         {
    1963           1 :             addr::addr a;
    1964             : 
    1965             :             // unless we have a bug, there should not be any file descriptor
    1966             :             // currently open with an ID of 1,000
    1967             :             //
    1968           1 :             CATCH_REQUIRE_THROWS_AS(a.set_from_socket(1000, true),  addr::addr_io_error);
    1969           1 :             CATCH_REQUIRE_THROWS_AS(a.set_from_socket(1000, false), addr::addr_io_error);
    1970             :         }
    1971             : 
    1972          12 :         CATCH_SECTION("unknown socket type")
    1973             :         {
    1974           1 :             addr::addr a;
    1975             : 
    1976           1 :             int s(socket(AF_UNIX, SOCK_STREAM, 0));
    1977           1 :             CATCH_REQUIRE(s >= 0);
    1978           2 :             std::shared_ptr<int> auto_free(&s, socket_deleter);
    1979             : 
    1980             :             // unless we have a bug, there should not be any file descriptor
    1981             :             // currently open with an ID of 1,000
    1982             :             //
    1983           1 :             CATCH_REQUIRE_THROWS_AS(a.set_from_socket(s, true),  addr::addr_io_error);
    1984           1 :             CATCH_REQUIRE_THROWS_AS(a.set_from_socket(s, false), addr::addr_invalid_state);
    1985             :         }
    1986             : 
    1987          12 :         CATCH_SECTION("create a server, but do not test it (yet)...")
    1988             :         {
    1989           2 :             addr::addr_parser p;
    1990           2 :             addr::addr_range::vector_t ips(p.parse("127.0.0.1:49999"));
    1991           1 :             CATCH_REQUIRE(ips.size() >= 1);
    1992             : 
    1993           1 :             addr::addr & a(ips[0].get_from());
    1994           1 :             int s(a.create_socket(addr::addr::SOCKET_FLAG_NONBLOCK | addr::addr::SOCKET_FLAG_CLOEXEC | addr::addr::SOCKET_FLAG_REUSE));
    1995           1 :             CATCH_REQUIRE(s >= 0);
    1996           2 :             std::shared_ptr<int> auto_free(&s, socket_deleter);
    1997             : 
    1998           1 :             CATCH_REQUIRE(a.bind(s) == 0);
    1999             :         }
    2000             : 
    2001          12 :         CATCH_SECTION("connect with TCP to 127.0.0.1")
    2002             :         {
    2003           1 :             if(SNAP_CATCH2_NAMESPACE::g_tcp_port != -1)
    2004             :             {
    2005           2 :                 addr::addr_parser p;
    2006           2 :                 addr::addr_range::vector_t ips(p.parse("127.0.0.1:" + std::to_string(SNAP_CATCH2_NAMESPACE::g_tcp_port)));
    2007           1 :                 CATCH_REQUIRE(ips.size() >= 1);
    2008             : 
    2009           1 :                 addr::addr & a(ips[0].get_from());
    2010           1 :                 int s(a.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC));// | addr::addr::SOCKET_FLAG_REUSE));
    2011           1 :                 CATCH_REQUIRE(s >= 0);
    2012           2 :                 std::shared_ptr<int> auto_free(&s, socket_deleter);
    2013             : 
    2014           1 :                 CATCH_REQUIRE(a.connect(s) == 0);
    2015             : 
    2016             :                 // get socket info from the other side (peer == true)
    2017             :                 //
    2018           1 :                 addr::addr b;
    2019           1 :                 b.set_from_socket(s, true);
    2020           1 :                 CATCH_REQUIRE(b.is_ipv4());
    2021           1 :                 CATCH_REQUIRE(b.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY)    == "127.0.0.1");
    2022           1 :                 CATCH_REQUIRE(b.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "127.0.0.1");
    2023             : 
    2024             :                 // in this case we know what the port is since we specified
    2025             :                 // that when connecting
    2026             :                 //
    2027           1 :                 CATCH_REQUIRE(b.get_port() == SNAP_CATCH2_NAMESPACE::g_tcp_port);
    2028             : 
    2029             :                 // now try this side (peer == false)
    2030             :                 //
    2031           1 :                 addr::addr c;
    2032           1 :                 c.set_from_socket(s, false);
    2033           1 :                 CATCH_REQUIRE(c.is_ipv4());
    2034           1 :                 CATCH_REQUIRE(c.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY)    == "127.0.0.1");
    2035           1 :                 CATCH_REQUIRE(c.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "127.0.0.1");
    2036             : 
    2037             :                 // we cannot be sure of the port, there is a range we could
    2038             :                 // test better (more constraining) but for this test is
    2039             :                 // certainly does not matter much; it has to be more than
    2040             :                 // 1023, though
    2041             :                 //
    2042           1 :                 CATCH_REQUIRE(c.get_port() > 1023);
    2043             :             }
    2044             :             else
    2045             :             {
    2046             :                 // avoid issue of no assertions
    2047             :                 //
    2048           0 :                 CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::g_tcp_port == -1);
    2049           0 :                 std::cout << "connect to 127.0.0.1 test skipped as no TCP port was specified on the command line." << std::endl;
    2050             :             }
    2051             :         }
    2052             : 
    2053          12 :         CATCH_SECTION("connect with UDP to 127.0.0.1")
    2054             :         {
    2055           2 :             addr::addr_parser p;
    2056           1 :             p.set_protocol("udp");
    2057           2 :             addr::addr_range::vector_t ips(p.parse("127.0.0.1:53"));
    2058           1 :             CATCH_REQUIRE(ips.size() >= 1);
    2059             : 
    2060           1 :             addr::addr & a(ips[0].get_from());
    2061           1 :             int s(a.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC));// | addr::addr::SOCKET_FLAG_REUSE));
    2062           1 :             CATCH_REQUIRE(s >= 0);
    2063           2 :             std::shared_ptr<int> auto_free(&s, socket_deleter);
    2064             : 
    2065           1 :             CATCH_REQUIRE(a.connect(s) == -1);
    2066             : 
    2067             :             // get socket info from the other side (peer == true)
    2068             :             //
    2069           1 :             addr::addr b;
    2070           1 :             CATCH_REQUIRE_THROWS_AS(b.set_from_socket(s, true), addr::addr_io_error);
    2071           1 :             CATCH_REQUIRE_FALSE(b.is_ipv4());
    2072           1 :             CATCH_REQUIRE(b.to_ipv6_string(addr::addr::string_ip_t::STRING_IP_ONLY)    == "::");
    2073           1 :             CATCH_REQUIRE(b.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "::");
    2074             : 
    2075             :             // in this case we know what the port is since we specified
    2076             :             // that when connecting
    2077             :             //
    2078           1 :             CATCH_REQUIRE(b.get_port() == 0);
    2079             : 
    2080             :             // now try this side (peer == false)
    2081             :             //
    2082           1 :             addr::addr c;
    2083           1 :             c.set_from_socket(s, false);
    2084           1 :             CATCH_REQUIRE(c.is_ipv4());
    2085           1 :             CATCH_REQUIRE(c.to_ipv4_string(addr::addr::string_ip_t::STRING_IP_ONLY)    == "0.0.0.0");
    2086           1 :             CATCH_REQUIRE(c.to_ipv4or6_string(addr::addr::string_ip_t::STRING_IP_ONLY) == "0.0.0.0");
    2087             : 
    2088             :             // we cannot be sure of the port, there is a range we could
    2089             :             // test better (more constraining) but for this test is
    2090             :             // certainly does not matter much; it has to be more than
    2091             :             // 1023, though
    2092             :             //
    2093           1 :             CATCH_REQUIRE(c.get_port() == 0);
    2094             :         }
    2095             :     }
    2096           6 : }
    2097             : 
    2098             : 
    2099          15 : CATCH_TEST_CASE( "ipv4::string_to_addr", "[ipv4]" )
    2100             : {
    2101          26 :     CATCH_GIVEN("string_to_addr() ipv4")
    2102             :     {
    2103          26 :         CATCH_SECTION("empty address without defaults")
    2104             :         {
    2105           1 :             addr::addr a(addr::string_to_addr(std::string()));
    2106             : 
    2107           1 :             CATCH_REQUIRE(a.is_ipv4());
    2108             : 
    2109           1 :             struct sockaddr_in in = sockaddr_in();
    2110           1 :             in.sin_family = AF_INET;
    2111           1 :             in.sin_port = 0;
    2112           1 :             in.sin_addr.s_addr = htonl((0 << 24) | (0 << 16) | (0 << 8) | (0 << 0));
    2113             : 
    2114             :             // test string_to_addr accuracy
    2115             :             //
    2116           1 :             struct sockaddr_in out;
    2117           1 :             a.get_ipv4(out);
    2118           1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2119             : 
    2120           1 :             uint8_t mask[16];
    2121           1 :             a.get_mask(mask);
    2122           1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    2123           1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    2124           1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    2125           1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    2126           1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    2127           1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    2128           1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    2129           1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    2130           1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    2131           1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    2132           1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    2133           1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    2134           1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    2135           1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    2136           1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    2137           1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    2138             :         }
    2139          26 :         CATCH_SECTION("explicit defaults")
    2140             :         {
    2141           1 :             addr::addr a(addr::string_to_addr("5.14.34.111", std::string(), -1, std::string(), false));
    2142             : 
    2143           1 :             CATCH_REQUIRE(a.is_ipv4());
    2144             : 
    2145           1 :             struct sockaddr_in in = sockaddr_in();
    2146           1 :             in.sin_family = AF_INET;
    2147           1 :             in.sin_port = 0;
    2148           1 :             in.sin_addr.s_addr = htonl((5 << 24) | (14 << 16) | (34 << 8) | (111 << 0));
    2149             : 
    2150             :             // test string_to_addr accuracy
    2151             :             //
    2152           1 :             struct sockaddr_in out;
    2153           1 :             a.get_ipv4(out);
    2154           1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2155             : 
    2156           1 :             uint8_t mask[16];
    2157           1 :             a.get_mask(mask);
    2158           1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    2159           1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    2160           1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    2161           1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    2162           1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    2163           1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    2164           1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    2165           1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    2166           1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    2167           1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    2168           1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    2169           1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    2170           1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    2171           1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    2172           1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    2173           1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    2174             :         }
    2175          26 :         CATCH_SECTION("defaults")
    2176             :         {
    2177           1 :             addr::addr a(addr::string_to_addr("7.149.104.211"));
    2178             : 
    2179           1 :             CATCH_REQUIRE(a.is_ipv4());
    2180             : 
    2181           1 :             struct sockaddr_in in = sockaddr_in();
    2182           1 :             in.sin_family = AF_INET;
    2183           1 :             in.sin_port = 0;
    2184           1 :             in.sin_addr.s_addr = htonl((7 << 24) | (149 << 16) | (104 << 8) | (211 << 0));
    2185             : 
    2186             :             // test string_to_addr accuracy
    2187             :             //
    2188           1 :             struct sockaddr_in out;
    2189           1 :             a.get_ipv4(out);
    2190           1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2191             : 
    2192           1 :             uint8_t mask[16];
    2193           1 :             a.get_mask(mask);
    2194           1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    2195           1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    2196           1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    2197           1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    2198           1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    2199           1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    2200           1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    2201           1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    2202           1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    2203           1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    2204           1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    2205           1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    2206           1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    2207           1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    2208           1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    2209           1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    2210             :         }
    2211          26 :         CATCH_SECTION("addr & default addr")
    2212             :         {
    2213           1 :             addr::addr a(addr::string_to_addr("37.149.174.11", "1.205.32.11"));
    2214             : 
    2215           1 :             CATCH_REQUIRE(a.is_ipv4());
    2216             : 
    2217           1 :             struct sockaddr_in in = sockaddr_in();
    2218           1 :             in.sin_family = AF_INET;
    2219           1 :             in.sin_port = 0;
    2220           1 :             in.sin_addr.s_addr = htonl((37 << 24) | (149 << 16) | (174 << 8) | (11 << 0));
    2221             : 
    2222             :             // test string_to_addr accuracy
    2223             :             //
    2224           1 :             struct sockaddr_in out;
    2225           1 :             a.get_ipv4(out);
    2226           1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2227             : 
    2228           1 :             uint8_t mask[16];
    2229           1 :             a.get_mask(mask);
    2230           1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    2231           1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    2232           1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    2233           1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    2234           1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    2235           1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    2236           1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    2237           1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    2238           1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    2239           1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    2240           1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    2241           1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    2242           1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    2243           1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    2244           1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    2245           1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    2246             :         }
    2247          26 :         CATCH_SECTION("no addr, expect default addr")
    2248             :         {
    2249           1 :             addr::addr a(addr::string_to_addr("", "1.205.32.11"));
    2250             : 
    2251           1 :             CATCH_REQUIRE(a.is_ipv4());
    2252             : 
    2253           1 :             struct sockaddr_in in = sockaddr_in();
    2254           1 :             in.sin_family = AF_INET;
    2255           1 :             in.sin_port = 0;
    2256           1 :             in.sin_addr.s_addr = htonl((1 << 24) | (205 << 16) | (32 << 8) | (11 << 0));
    2257             : 
    2258             :             // test string_to_addr accuracy
    2259             :             //
    2260           1 :             struct sockaddr_in out;
    2261           1 :             a.get_ipv4(out);
    2262           1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2263             : 
    2264           1 :             uint8_t mask[16];
    2265           1 :             a.get_mask(mask);
    2266           1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    2267           1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    2268           1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    2269           1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    2270           1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    2271           1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    2272           1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    2273           1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    2274           1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    2275           1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    2276           1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    2277           1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    2278           1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    2279           1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    2280           1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    2281           1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    2282             :         }
    2283          26 :         CATCH_SECTION("addr and port, with a default port")
    2284             :         {
    2285           1 :             addr::addr a(addr::string_to_addr("69.109.223.17:697", "1.205.32.11", 123));
    2286             : 
    2287           1 :             CATCH_REQUIRE(a.is_ipv4());
    2288             : 
    2289           1 :             struct sockaddr_in in = sockaddr_in();
    2290           1 :             in.sin_family = AF_INET;
    2291           1 :             in.sin_port = htons(697);
    2292           1 :             in.sin_addr.s_addr = htonl((69 << 24) | (109 << 16) | (223 << 8) | (17 << 0));
    2293             : 
    2294             :             // test string_to_addr accuracy
    2295             :             //
    2296           1 :             struct sockaddr_in out;
    2297           1 :             a.get_ipv4(out);
    2298           1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2299             : 
    2300           1 :             uint8_t mask[16];
    2301           1 :             a.get_mask(mask);
    2302           1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    2303           1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    2304           1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    2305           1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    2306           1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    2307           1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    2308           1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    2309           1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    2310           1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    2311           1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    2312           1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    2313           1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    2314           1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    2315           1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    2316           1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    2317           1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    2318             :         }
    2319          26 :         CATCH_SECTION("addr without port, with a default port")
    2320             :         {
    2321           1 :             addr::addr a(addr::string_to_addr("169.209.23.217", "1.205.32.11", 123));
    2322             : 
    2323           1 :             CATCH_REQUIRE(a.is_ipv4());
    2324             : 
    2325           1 :             struct sockaddr_in in = sockaddr_in();
    2326           1 :             in.sin_family = AF_INET;
    2327           1 :             in.sin_port = htons(123);
    2328           1 :             in.sin_addr.s_addr = htonl((169 << 24) | (209 << 16) | (23 << 8) | (217 << 0));
    2329             : 
    2330             :             // test string_to_addr accuracy
    2331             :             //
    2332           1 :             struct sockaddr_in out;
    2333           1 :             a.get_ipv4(out);
    2334           1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2335             : 
    2336           1 :             uint8_t mask[16];
    2337           1 :             a.get_mask(mask);
    2338           1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    2339           1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    2340           1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    2341           1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    2342           1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    2343           1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    2344           1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    2345           1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    2346           1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    2347           1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    2348           1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    2349           1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    2350           1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    2351           1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    2352           1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    2353           1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    2354             :         }
    2355          26 :         CATCH_SECTION("addr without port but protocol")
    2356             :         {
    2357           1 :             addr::addr a(addr::string_to_addr("4.5.123.7", "1.205.32.11", 60000, "tcp"));
    2358             : 
    2359           1 :             CATCH_REQUIRE(a.is_ipv4());
    2360             : 
    2361           1 :             struct sockaddr_in in = sockaddr_in();
    2362           1 :             in.sin_family = AF_INET;
    2363           1 :             in.sin_port = htons(60000);
    2364           1 :             in.sin_addr.s_addr = htonl((4 << 24) | (5 << 16) | (123 << 8) | (7 << 0));
    2365             : 
    2366             :             // test string_to_addr accuracy
    2367             :             //
    2368           1 :             struct sockaddr_in out;
    2369           1 :             a.get_ipv4(out);
    2370           1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2371             : 
    2372           1 :             uint8_t mask[16];
    2373           1 :             a.get_mask(mask);
    2374           1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    2375           1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    2376           1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    2377           1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    2378           1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    2379           1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    2380           1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    2381           1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    2382           1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    2383           1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    2384           1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    2385           1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    2386           1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    2387           1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    2388           1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    2389           1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    2390             :         }
    2391          26 :         CATCH_SECTION("addr with port and protocol")
    2392             :         {
    2393           1 :             addr::addr a(addr::string_to_addr("204.105.13.9:65", "1.205.32.11", 60000, "tcp"));
    2394             : 
    2395           1 :             CATCH_REQUIRE(a.is_ipv4());
    2396             : 
    2397           1 :             struct sockaddr_in in = sockaddr_in();
    2398           1 :             in.sin_family = AF_INET;
    2399           1 :             in.sin_port = htons(65);
    2400           1 :             in.sin_addr.s_addr = htonl((204 << 24) | (105 << 16) | (13 << 8) | (9 << 0));
    2401             : 
    2402             :             // test string_to_addr accuracy
    2403             :             //
    2404           1 :             struct sockaddr_in out;
    2405           1 :             a.get_ipv4(out);
    2406           1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2407             : 
    2408           1 :             uint8_t mask[16];
    2409           1 :             a.get_mask(mask);
    2410           1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    2411           1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    2412           1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    2413           1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    2414           1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    2415           1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    2416           1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    2417           1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    2418           1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    2419           1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    2420           1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    2421           1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    2422           1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    2423           1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    2424           1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    2425           1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    2426             :         }
    2427          26 :         CATCH_SECTION("addr with port and protocol but no mask, albeit allowed")
    2428             :         {
    2429           1 :             addr::addr a(addr::string_to_addr("94.95.131.18:765", "11.205.32.21", 54003, "tcp", true));
    2430             : 
    2431           1 :             CATCH_REQUIRE(a.is_ipv4());
    2432             : 
    2433           1 :             struct sockaddr_in in = sockaddr_in();
    2434           1 :             in.sin_family = AF_INET;
    2435           1 :             in.sin_port = htons(765);
    2436           1 :             in.sin_addr.s_addr = htonl((94 << 24) | (95 << 16) | (131 << 8) | (18 << 0));
    2437             : 
    2438             :             // test string_to_addr accuracy
    2439             :             //
    2440           1 :             struct sockaddr_in out;
    2441           1 :             a.get_ipv4(out);
    2442           1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2443             : 
    2444           1 :             uint8_t mask[16];
    2445           1 :             a.get_mask(mask);
    2446           1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    2447           1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    2448           1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    2449           1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    2450           1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    2451           1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    2452           1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    2453           1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    2454           1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    2455           1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    2456           1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    2457           1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    2458           1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    2459           1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    2460           1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    2461           1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    2462             :         }
    2463          26 :         CATCH_SECTION("addr with port and protocol and mask, albeit allowed")
    2464             :         {
    2465           1 :             addr::addr a(addr::string_to_addr("44.45.141.48:765/30", "11.205.32.21", 54003, "tcp", true));
    2466             : 
    2467           1 :             CATCH_REQUIRE(a.is_ipv4());
    2468             : 
    2469           1 :             struct sockaddr_in in = sockaddr_in();
    2470           1 :             in.sin_family = AF_INET;
    2471           1 :             in.sin_port = htons(765);
    2472           1 :             in.sin_addr.s_addr = htonl((44 << 24) | (45 << 16) | (141 << 8) | (48 << 0));
    2473             : 
    2474             :             // test string_to_addr accuracy
    2475             :             //
    2476           1 :             struct sockaddr_in out;
    2477           1 :             a.get_ipv4(out);
    2478           1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2479             : 
    2480           1 :             uint8_t mask[16];
    2481           1 :             a.get_mask(mask);
    2482           1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    2483           1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    2484           1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    2485           1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    2486           1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    2487           1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    2488           1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    2489           1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    2490           1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    2491           1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    2492           1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    2493           1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    2494           1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    2495           1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    2496           1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    2497           1 :             CATCH_REQUIRE(mask[15] == 0xFC);
    2498             :         }
    2499          26 :         CATCH_SECTION("addr with port and protocol and mask, albeit allowed")
    2500             :         {
    2501           1 :             addr::addr a(addr::string_to_addr("160.0.0.0:1675/4", "11.205.32.21", 14003, "udp", true));
    2502             : 
    2503           1 :             CATCH_REQUIRE(a.is_ipv4());
    2504             : 
    2505           1 :             struct sockaddr_in in = sockaddr_in();
    2506           1 :             in.sin_family = AF_INET;
    2507           1 :             in.sin_port = htons(1675);
    2508           1 :             in.sin_addr.s_addr = htonl((160 << 24) | (0 << 16) | (0 << 8) | (0 << 0));
    2509             : 
    2510             :             // test string_to_addr accuracy
    2511             :             //
    2512           1 :             struct sockaddr_in out;
    2513           1 :             a.get_ipv4(out);
    2514           1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    2515             : 
    2516           1 :             uint8_t mask[16];
    2517           1 :             a.get_mask(mask);
    2518           1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    2519           1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    2520           1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    2521           1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    2522           1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    2523           1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    2524           1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    2525           1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    2526           1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    2527           1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    2528           1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    2529           1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    2530           1 :             CATCH_REQUIRE(mask[12] == 0xF0);
    2531           1 :             CATCH_REQUIRE(mask[13] == 0x00);
    2532           1 :             CATCH_REQUIRE(mask[14] == 0x00);
    2533           1 :             CATCH_REQUIRE(mask[15] == 0x00);
    2534             :         }
    2535          26 :         CATCH_SECTION("addr with port and invalid protocol so we get an exception")
    2536             :         {
    2537           1 :             CATCH_REQUIRE_THROWS_AS(addr::string_to_addr("169.60.33.0:9322/24", std::string(), -1, "icmp", true),
    2538             :                                                                         addr::addr_invalid_argument);
    2539             :         }
    2540             :     }
    2541             :     // TODO: add ipv6 tests, although at this point it's not too
    2542             :     //       important here, it may change in the future
    2543             :     //
    2544             : 
    2545             : //addr string_to_addr(
    2546             : //          std::string const & a
    2547             : //        , std::string const & default_address = std::string()
    2548             : //        , int default_port = -1
    2549             : //        , std::string const & protocol = std::string()
    2550             : //        , bool mask = false);
    2551          19 : }
    2552             : 
    2553             : 
    2554             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13