LCOV - code coverage report
Current view: top level - tests - catch_ipv4.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 98.6 % 2727 2689
Test Date: 2025-04-18 08:03:11 Functions: 100.0 % 15 15
Legend: Lines: hit not hit

            Line data    Source code
       1              : // Copyright (c) 2011-2025  Made to Order Software Corp.  All Rights Reserved
       2              : //
       3              : // https://snapwebsites.org/project/libaddr
       4              : // contact@m2osw.com
       5              : //
       6              : // Permission is hereby granted, free of charge, to any
       7              : // person obtaining a copy of this software and
       8              : // associated documentation files (the "Software"), to
       9              : // deal in the Software without restriction, including
      10              : // without limitation the rights to use, copy, modify,
      11              : // merge, publish, distribute, sublicense, and/or sell
      12              : // copies of the Software, and to permit persons to whom
      13              : // the Software is furnished to do so, subject to the
      14              : // following conditions:
      15              : //
      16              : // The above copyright notice and this permission notice
      17              : // shall be included in all copies or substantial
      18              : // portions of the Software.
      19              : //
      20              : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
      21              : // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
      22              : // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
      23              : // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
      24              : // EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      25              : // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
      26              : // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      27              : // ARISING FROM, OUT OF OR IN CONNECTION WITH THE
      28              : // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      29              : // SOFTWARE.
      30              : 
      31              : 
      32              : /** \file
      33              :  * \brief Test the IPv4 interface.
      34              :  *
      35              :  * These test verify that the IPv4 side of things function as expected.
      36              :  *
      37              :  * Note that some of the tests between the IPv4 and IPv6 overlap. Here
      38              :  * you mainly find the IPv4 side of things.
      39              :  */
      40              : 
      41              : // addr
      42              : //
      43              : #include    <libaddr/iface.h>
      44              : 
      45              : 
      46              : // self
      47              : //
      48              : #include    "catch_main.h"
      49              : 
      50              : 
      51              : // last include
      52              : //
      53              : #include    <snapdev/poison.h>
      54              : 
      55              : 
      56              : 
      57              : 
      58              : /** \brief Details used by the addr class implementation.
      59              :  *
      60              :  * We have a function to check whether an address is part of
      61              :  * the interfaces of your computer. This check requires the
      62              :  * use of a `struct ifaddrs` and as such it requires to
      63              :  * delete that structure. We define a deleter for that
      64              :  * structure here.
      65              :  */
      66              : namespace
      67              : {
      68              : 
      69              : /** \brief Close a socket.
      70              :  *
      71              :  * This deleter is used to make sure all the socket we test get closed
      72              :  * on exit.
      73              :  *
      74              :  * \param[in] s  The socket to close.
      75              :  */
      76            5 : void socket_deleter(int * s)
      77              : {
      78            5 :     close(*s);
      79            5 : }
      80              : 
      81              : 
      82              : }
      83              : // no name namespace
      84              : 
      85              : 
      86              : 
      87           15 : CATCH_TEST_CASE("ipv4::invalid_input", "[ipv4]")
      88              : {
      89           15 :     CATCH_GIVEN("addr()")
      90              :     {
      91            1 :         addr::addr a;
      92              : 
      93            1 :         CATCH_START_SECTION("ipv4::invalid_input: set IPv4 with an invalid family")
      94              :         {
      95           26 :             for(int idx(0); idx < 25; ++idx)
      96              :             {
      97           25 :                 struct sockaddr_in in = sockaddr_in();
      98              :                 do
      99              :                 {
     100           25 :                     in.sin_family = rand();
     101              :                 }
     102           25 :                 while(in.sin_family == AF_INET);
     103           25 :                 in.sin_port = htons(rand());
     104           25 :                 in.sin_addr.s_addr = htonl(rand() ^ (rand() << 16));
     105           25 :                 CATCH_REQUIRE_THROWS_AS(a.set_ipv4(in), addr::addr_invalid_argument);
     106           50 :                 CATCH_REQUIRE_THROWS_AS(addr::addr(in), addr::addr_invalid_argument);
     107              :             }
     108              :         }
     109            1 :         CATCH_END_SECTION()
     110           16 :     }
     111              : 
     112           15 :     CATCH_GIVEN("addr_parser() with IPv4 settings")
     113              :     {
     114            2 :         addr::addr_parser a;
     115              : 
     116            2 :         CATCH_START_SECTION("ipv4::addr_parser(): invalid allow flags (too small)")
     117              :         {
     118           11 :             for(int idx(0); idx < 10; ++idx)
     119              :             {
     120              :                 // test with a negative number
     121              :                 //
     122              :                 int n;
     123              :                 do
     124              :                 {
     125           10 :                     n = rand();
     126              :                 }
     127           10 :                 while(n == 0);
     128           10 :                 if(n > 0)
     129              :                 {
     130              :                     // all positive numbers have a corresponding negative
     131              :                     // number so this always flips the sign as expected
     132              :                     //
     133           10 :                     n = -n;
     134              :                 }
     135           10 :                 addr::allow_t const flag(static_cast<addr::allow_t>(n));
     136              : 
     137           10 :                 CATCH_REQUIRE_THROWS_AS(a.set_allow(flag, true), addr::addr_invalid_argument);
     138           10 :                 CATCH_REQUIRE_THROWS_AS(a.set_allow(flag, false), addr::addr_invalid_argument);
     139           10 :                 CATCH_REQUIRE_THROWS_AS(a.get_allow(flag), addr::addr_invalid_argument);
     140              :             }
     141              :         }
     142            2 :         CATCH_END_SECTION()
     143              : 
     144            2 :         CATCH_START_SECTION("ipv4::addr_parser(): invalid allow flags (too large)")
     145              :         {
     146           11 :             for(int idx(0); idx < 10; ++idx)
     147              :             {
     148              :                 // test with a negative number
     149              :                 //
     150              :                 int n;
     151              :                 do
     152              :                 {
     153           10 :                     n = rand();
     154           10 :                     if(n < 0)
     155              :                     {
     156            0 :                         n = -n;
     157              :                     }
     158              :                 }
     159           10 :                 while(n < static_cast<int>(addr::allow_t::ALLOW_max));
     160           10 :                 addr::allow_t const flag(static_cast<addr::allow_t>(n));
     161              : 
     162           10 :                 CATCH_REQUIRE_THROWS_AS(a.set_allow(flag, true), addr::addr_invalid_argument);
     163           10 :                 CATCH_REQUIRE_THROWS_AS(a.set_allow(flag, false), addr::addr_invalid_argument);
     164           10 :                 CATCH_REQUIRE_THROWS_AS(a.get_allow(flag), addr::addr_invalid_argument);
     165              :             }
     166              :         }
     167            2 :         CATCH_END_SECTION()
     168           17 :     }
     169              : 
     170           15 :     CATCH_GIVEN("addr_parser() with IPv4 addresses")
     171              :     {
     172            2 :         CATCH_START_SECTION("ipv4::addr_parser(): bad address")
     173              :         {
     174            1 :             addr::addr_parser p;
     175            3 :             addr::addr_range::vector_t ips(p.parse("{bad-ip}"));
     176            1 :             CATCH_REQUIRE(p.has_errors());
     177            1 :             CATCH_REQUIRE(p.error_count() == 1);
     178            1 :             CATCH_REQUIRE(p.error_messages() == "Invalid address in \"{bad-ip}\" error -2 -- Name or service not known (errno: 22 -- Invalid argument).\n");
     179            1 :             CATCH_REQUIRE(p.has_errors());
     180            1 :             p.clear_errors();
     181            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
     182            1 :             CATCH_REQUIRE(ips.size() == 0);
     183            1 :         }
     184            2 :         CATCH_END_SECTION()
     185              : 
     186            2 :         CATCH_START_SECTION("ipv4::addr_parser(): required address")
     187              :         {
     188            1 :             addr::addr_parser p;
     189            1 :             p.set_protocol(IPPROTO_TCP);
     190            1 :             p.set_allow(addr::allow_t::ALLOW_REQUIRED_ADDRESS, true);
     191            3 :             addr::addr_range::vector_t ips(p.parse(""));
     192            1 :             CATCH_REQUIRE(p.has_errors());
     193            1 :             CATCH_REQUIRE(p.error_count() == 1);
     194            1 :             CATCH_REQUIRE(p.error_messages() == "Required address is missing.\n");
     195            1 :             CATCH_REQUIRE(p.has_errors());
     196            1 :             p.clear_errors();
     197            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
     198            1 :             CATCH_REQUIRE(ips.size() == 0);
     199            1 :         }
     200            2 :         CATCH_END_SECTION()
     201           15 :     }
     202              : 
     203           15 :     CATCH_GIVEN("addr_parser() with IPv4 ports")
     204              :     {
     205            3 :         CATCH_START_SECTION("ipv4::addr_parser(): required port")
     206              :         {
     207              :             // optional + required -> required
     208              :             {
     209            1 :                 addr::addr_parser p;
     210            1 :                 p.set_protocol(IPPROTO_TCP);
     211            1 :                 p.set_allow(addr::allow_t::ALLOW_REQUIRED_PORT, true);
     212            3 :                 addr::addr_range::vector_t ips(p.parse("1.2.3.4"));
     213            1 :                 CATCH_REQUIRE(p.has_errors());
     214            1 :                 CATCH_REQUIRE(p.error_count() == 1);
     215            1 :                 CATCH_REQUIRE(p.error_messages() == "Required port is missing.\n");
     216            1 :                 CATCH_REQUIRE(p.has_errors());
     217            1 :                 p.clear_errors();
     218            1 :                 CATCH_REQUIRE_FALSE(p.has_errors());
     219            1 :                 CATCH_REQUIRE(ips.size() == 0);
     220            1 :             }
     221              : 
     222              :             // only required -> required just the same
     223              :             {
     224            1 :                 addr::addr_parser p;
     225            1 :                 p.set_protocol(IPPROTO_TCP);
     226            1 :                 p.set_allow(addr::allow_t::ALLOW_PORT, false);
     227            1 :                 p.set_allow(addr::allow_t::ALLOW_REQUIRED_PORT, true);
     228            3 :                 addr::addr_range::vector_t ips(p.parse("1.2.3.4"));
     229            1 :                 CATCH_REQUIRE(p.has_errors());
     230            1 :                 CATCH_REQUIRE(p.error_count() == 1);
     231            1 :                 CATCH_REQUIRE(p.error_messages() == "Required port is missing.\n");
     232            1 :                 CATCH_REQUIRE(p.has_errors());
     233            1 :                 p.clear_errors();
     234            1 :                 CATCH_REQUIRE_FALSE(p.has_errors());
     235            1 :                 CATCH_REQUIRE(ips.size() == 0);
     236            1 :             }
     237              :         }
     238            3 :         CATCH_END_SECTION()
     239              : 
     240            3 :         CATCH_START_SECTION("ipv4::addr_parser(): port not allowed")
     241              :         {
     242            1 :             addr::addr_parser p;
     243            1 :             p.set_protocol(IPPROTO_TCP);
     244            1 :             p.set_allow(addr::allow_t::ALLOW_PORT, false);
     245            1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::allow_t::ALLOW_REQUIRED_PORT));
     246            3 :             addr::addr_range::vector_t ips(p.parse("1.2.3.4:123"));
     247            1 :             CATCH_REQUIRE(p.has_errors());
     248            1 :             CATCH_REQUIRE(p.error_count() == 1);
     249            1 :             CATCH_REQUIRE(p.error_messages() == "Port not allowed (1.2.3.4:123).\n");
     250            1 :             CATCH_REQUIRE(p.has_errors());
     251            1 :             p.clear_errors();
     252            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
     253            1 :             CATCH_REQUIRE(ips.size() == 0);
     254            1 :         }
     255            3 :         CATCH_END_SECTION()
     256              : 
     257            3 :         CATCH_START_SECTION("ipv4::addr_parser(): invalid port")
     258              :         {
     259            1 :             addr::addr_parser p;
     260              : 
     261              :             // so to a different default value
     262              :             //
     263            1 :             int const default_port(rand() & 0xFFFF);
     264            1 :             p.set_default_port(default_port);
     265              : 
     266           26 :             for(int idx(0); idx < 25; ++idx)
     267              :             {
     268           25 :                 int port(0);
     269              :                 do
     270              :                 {
     271           25 :                     port = rand() ^ (rand() << 16);
     272              :                 }
     273           25 :                 while(port >= -1 && port <= 65535); // -1 is valid here, it represents "no default port defined"
     274           25 :                 CATCH_REQUIRE_THROWS_AS(p.set_default_port(port), addr::addr_invalid_argument);
     275              : 
     276           25 :                 std::string const port_str(std::to_string(port));
     277           25 :                 CATCH_REQUIRE_THROWS_AS(p.set_default_port(port_str), addr::addr_invalid_argument);
     278              : 
     279              :                 // verify port unchanged
     280              :                 //
     281           25 :                 CATCH_REQUIRE(p.get_default_port() == default_port);
     282           25 :             }
     283              : 
     284            5 :             CATCH_REQUIRE_THROWS_AS(p.set_default_port("not-a-number"), addr::addr_invalid_argument);
     285            1 :         }
     286            3 :         CATCH_END_SECTION()
     287           15 :     }
     288              : 
     289           15 :     CATCH_GIVEN("addr_parser() with invalid masks")
     290              :     {
     291            5 :         CATCH_START_SECTION("ipv4::addr_parser(): really large numbers (over 1000)")
     292              :         {
     293            6 :             for(int idx(0); idx < 5; ++idx)
     294              :             {
     295            5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     296            5 :                 int const port(rand() & 0xFFFF);
     297            5 :                 int const mask((rand() & 0xFF) + 10001);
     298            5 :                 addr::addr_parser p;
     299            5 :                 p.set_protocol(proto);
     300            5 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
     301            5 :                 addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port) + "/" + std::to_string(mask)));
     302            5 :                 CATCH_REQUIRE(p.has_errors());
     303            5 :                 CATCH_REQUIRE(p.error_count() == 1);
     304            5 :                 CATCH_REQUIRE(p.error_messages() == "Mask size too large (" + std::to_string(mask) + ", expected a maximum of 128).\n");
     305            5 :                 CATCH_REQUIRE(ips.size() == 0);
     306            5 :             }
     307              :         }
     308            5 :         CATCH_END_SECTION()
     309              : 
     310            5 :         CATCH_START_SECTION("ipv4::addr_parser(): ipv4 mask is limited between 0 and 32")
     311              :         {
     312            6 :             for(int idx(0); idx < 5; ++idx)
     313              :             {
     314            5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     315            5 :                 int const port(rand() & 0xFFFF);
     316            5 :                 int const mask((rand() & 0xFF) + 33);
     317            5 :                 addr::addr_parser p;
     318            5 :                 p.set_protocol(proto);
     319            5 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
     320            5 :                 addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port) + "/" + std::to_string(mask)));
     321            5 :                 CATCH_REQUIRE(p.has_errors());
     322            5 :                 CATCH_REQUIRE(p.error_count() == 1);
     323            5 :                 CATCH_REQUIRE(p.error_messages() == "Unsupported mask size (" + std::to_string(mask) + ", expected 32 at the most for an IPv4).\n");
     324            5 :                 CATCH_REQUIRE(ips.size() == 0);
     325            5 :             }
     326              :         }
     327            5 :         CATCH_END_SECTION()
     328              : 
     329            5 :         CATCH_START_SECTION("ipv4::addr_parser(): ipv4 mask cannot use name")
     330              :         {
     331            6 :             for(int idx(0); idx < 5; ++idx)
     332              :             {
     333            5 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     334            5 :                 int const port(rand() & 0xFFFF);
     335            5 :                 addr::addr_parser p;
     336            5 :                 p.set_protocol(proto);
     337            5 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
     338            5 :                 p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
     339            5 :                 addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port) + "/localhost"));
     340            5 :                 CATCH_REQUIRE(p.has_errors());
     341            5 :                 CATCH_REQUIRE(p.error_count() == 1);
     342            5 :                 CATCH_REQUIRE(p.error_messages() == "Invalid mask in \"/localhost\", error -2 -- Name or service not known (errno: 0 -- Success).\n");
     343            5 :                 CATCH_REQUIRE(ips.size() == 0);
     344            5 :             }
     345              :         }
     346            5 :         CATCH_END_SECTION()
     347              : 
     348            5 :         CATCH_START_SECTION("ipv4::addr_parser(): ipv4 mask mismatch (mask uses ipv6)")
     349              :         {
     350            1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     351            1 :             int const port(rand() & 0xFFFF);
     352            1 :             addr::addr_parser p;
     353            1 :             p.set_protocol(proto);
     354            1 :             p.set_allow(addr::allow_t::ALLOW_MASK, true);
     355            1 :             p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
     356            1 :             addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port) + "/[1:2:3:4:5:6:7:8]"));
     357            1 :             CATCH_REQUIRE(p.has_errors());
     358            1 :             CATCH_REQUIRE(p.error_count() == 1);
     359            1 :             CATCH_REQUIRE(p.error_messages() == "The address uses the IPv4 syntax, the mask cannot use IPv6.\n");
     360            1 :             CATCH_REQUIRE(ips.size() == 0);
     361            1 :         }
     362            5 :         CATCH_END_SECTION()
     363              : 
     364            5 :         CATCH_START_SECTION("ipv4::addr_parser(): ipv4 mask mismatch (mask uses ipv6 without [...])")
     365              :         {
     366            1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
     367            1 :             int const port(rand() & 0xFFFF);
     368            1 :             addr::addr_parser p;
     369            1 :             p.set_protocol(proto);
     370            1 :             p.set_allow(addr::allow_t::ALLOW_MASK, true);
     371            1 :             p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
     372            1 :             addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port) + "/1:2:3:4:5:6:7:8"));
     373            1 :             CATCH_REQUIRE(p.has_errors());
     374            1 :             CATCH_REQUIRE(p.error_count() == 1);
     375            1 :             CATCH_REQUIRE(p.error_messages() == "Incompatible address between the address and mask address (first was an IPv4 second an IPv6).\n");
     376            1 :             CATCH_REQUIRE(ips.size() == 0);
     377            1 :         }
     378            5 :         CATCH_END_SECTION()
     379           15 :     }
     380              : 
     381           15 :     CATCH_GIVEN("addr_parser() with invalid protocols")
     382              :     {
     383            2 :         CATCH_START_SECTION("ipv4::addr_parser(): invalid names")
     384              :         {
     385            1 :             addr::addr_parser p;
     386              : 
     387              :             // not changing default protocol
     388              :             //
     389            1 :             CATCH_REQUIRE(p.get_protocol() == -1);
     390            5 :             CATCH_REQUIRE_THROWS_AS(p.set_protocol("unknown"), addr::addr_invalid_argument);
     391            1 :             CATCH_REQUIRE(p.get_protocol() == -1);
     392              : 
     393              :             // change protocol to another valid value first
     394              :             //
     395            3 :             p.set_protocol("tcp");
     396            5 :             CATCH_REQUIRE_THROWS_AS(p.set_protocol("another"), addr::addr_invalid_argument);
     397            1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_TCP);
     398            1 :         }
     399            2 :         CATCH_END_SECTION()
     400              : 
     401            2 :         CATCH_START_SECTION("ipv4::addr_parser(): invalid numbers")
     402              :         {
     403          101 :             for(int idx(0); idx < 100; ++idx)
     404              :             {
     405              :                 int protocol;
     406              :                 do
     407              :                 {
     408          100 :                     protocol = rand();
     409              :                 }
     410              :                 while(protocol == IPPROTO_IP
     411          100 :                    || protocol == IPPROTO_TCP
     412          200 :                    || protocol == IPPROTO_UDP);
     413              : 
     414          100 :                 addr::addr_parser p;
     415              : 
     416          100 :                 CATCH_REQUIRE_THROWS_AS(p.set_protocol(protocol), addr::addr_invalid_argument);
     417          100 :                 CATCH_REQUIRE(p.get_protocol() == -1);
     418              : 
     419              :                 // change protocol to another valid value first
     420              :                 //
     421          300 :                 p.set_protocol("tcp");
     422          100 :                 CATCH_REQUIRE_THROWS_AS(p.set_protocol(protocol), addr::addr_invalid_argument);
     423          100 :                 CATCH_REQUIRE(p.get_protocol() == IPPROTO_TCP);
     424          100 :             }
     425              :         }
     426            2 :         CATCH_END_SECTION()
     427           15 :     }
     428           15 : }
     429              : 
     430              : 
     431            9 : CATCH_TEST_CASE("ipv4::address_defaults", "[ipv4][ipv6]")
     432              : {
     433            9 :     CATCH_GIVEN("addr()")
     434              :     {
     435            9 :         addr::addr a;
     436              : 
     437            9 :         CATCH_START_SECTION("ipv4::addr: by default (all zeroes) IP is not an IPv4")
     438              :         {
     439            1 :             CATCH_REQUIRE_FALSE(a.is_ipv4());
     440            1 :             CATCH_REQUIRE_FALSE(a.get_family() == AF_INET);
     441            1 :             CATCH_REQUIRE(a.get_family() == AF_INET6);
     442            1 :             CATCH_REQUIRE(a.get_hostname() == std::string());
     443            1 :             CATCH_REQUIRE(a.is_hostname_an_ip());
     444            1 :             CATCH_REQUIRE(a.get_interface() == std::string());
     445              : 
     446            1 :             struct sockaddr_in in;
     447            1 :             CATCH_REQUIRE_THROWS_AS(a.get_ipv4(in), addr::addr_invalid_state);
     448            2 :             CATCH_REQUIRE_THROWS_AS(a.to_ipv4_string(addr::STRING_IP_ADDRESS),                                                               addr::addr_invalid_state);
     449            2 :             CATCH_REQUIRE_THROWS_AS(a.to_ipv4_string(addr::STRING_IP_BRACKET_ADDRESS),                                                       addr::addr_invalid_state);
     450            2 :             CATCH_REQUIRE_THROWS_AS(a.to_ipv4_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT),                                addr::addr_invalid_state);
     451            2 :             CATCH_REQUIRE_THROWS_AS(a.to_ipv4_string(addr::STRING_IP_ADDRESS | addr::STRING_IP_PORT | addr::STRING_IP_MASK),                 addr::addr_invalid_state);
     452            2 :             CATCH_REQUIRE_THROWS_AS(a.to_ipv4_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT | addr::STRING_IP_BRACKET_MASK), addr::addr_invalid_state);
     453            2 :             CATCH_REQUIRE_THROWS_AS(a.to_ipv4_string(addr::STRING_IP_ALL),                                                                   addr::addr_invalid_state);
     454              :         }
     455            9 :         CATCH_END_SECTION()
     456              : 
     457            9 :         CATCH_START_SECTION("ipv4::addr: default network type (:: and 0.0.0.0)")
     458              :         {
     459            1 :             a.set_port(80);
     460              : 
     461              :             // at first this is still an IPv6
     462              :             //
     463            1 :             CATCH_REQUIRE(a.is_default());
     464            1 :             CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_ANY);
     465            3 :             CATCH_REQUIRE(std::string(a.get_network_type_string()) == "Any");
     466            1 :             CATCH_REQUIRE_FALSE(a.is_lan());
     467            1 :             CATCH_REQUIRE_FALSE(a.is_lan(true));
     468            1 :             CATCH_REQUIRE_FALSE(a.is_lan(false));
     469            1 :             CATCH_REQUIRE(a.get_port() == 80);
     470            1 :             CATCH_REQUIRE(a.get_protocol() == IPPROTO_TCP);
     471            1 :             CATCH_REQUIRE(a.is_wan());
     472            1 :             CATCH_REQUIRE(a.is_wan(true));
     473            1 :             CATCH_REQUIRE_FALSE(a.is_wan(false));
     474            1 :             CATCH_REQUIRE(a.is_valid());
     475            1 :             CATCH_REQUIRE(a.to_ipv6_string(addr::STRING_IP_ADDRESS | addr::STRING_IP_DEFAULT_AS_ASTERISK) == "*");
     476            1 :             CATCH_REQUIRE(a.to_ipv6_string(addr::STRING_IP_ADDRESS | addr::STRING_IP_DEFAULT_AS_ASTERISK | addr::STRING_IP_PORT) == "[*]:80");
     477            1 :             CATCH_REQUIRE(a.to_ipv6_string(addr::STRING_IP_ADDRESS | addr::STRING_IP_DEFAULT_AS_ASTERISK | addr::STRING_IP_PORT_NAME) == "[*]:http");
     478            1 :             CATCH_REQUIRE(a.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_DEFAULT_AS_ASTERISK) == "[*]");
     479            1 :             CATCH_REQUIRE(a.to_ipv6_string(addr::STRING_IP_ADDRESS) == "::");
     480            1 :             CATCH_REQUIRE(a.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS) == "[::]");
     481            1 :             CATCH_REQUIRE(a.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_DEFAULT_AS_IPV4) == "0.0.0.0");
     482            1 :             CATCH_REQUIRE(a.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_DEFAULT_AS_IPV4 | addr::STRING_IP_PORT) == "0.0.0.0:80");
     483            1 :             CATCH_REQUIRE(a.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_DEFAULT_AS_IPV4 | addr::STRING_IP_PORT_NAME) == "0.0.0.0:http");
     484              : 
     485              :             // make it an IPv4 and try again
     486              :             //
     487            1 :             struct sockaddr_in in = sockaddr_in();
     488            1 :             in.sin_family = AF_INET;
     489            1 :             in.sin_port = htons(80);
     490            1 :             a.set_ipv4(in);
     491              : 
     492            1 :             CATCH_REQUIRE(a.is_default());
     493            1 :             CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_ANY);
     494            3 :             CATCH_REQUIRE(std::string(a.get_network_type_string()) == "Any");
     495            1 :             CATCH_REQUIRE_FALSE(a.is_lan());
     496            1 :             CATCH_REQUIRE_FALSE(a.is_lan(true));
     497            1 :             CATCH_REQUIRE_FALSE(a.is_lan(false));
     498            1 :             CATCH_REQUIRE(a.is_wan());
     499            1 :             CATCH_REQUIRE(a.is_wan(true));
     500            1 :             CATCH_REQUIRE_FALSE(a.is_wan(false));
     501            1 :             CATCH_REQUIRE(a.is_valid());
     502            1 :             CATCH_REQUIRE(a.to_ipv4_string(addr::STRING_IP_ADDRESS | addr::STRING_IP_DEFAULT_AS_ASTERISK) == "*");
     503            1 :             CATCH_REQUIRE(a.to_ipv4_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_DEFAULT_AS_ASTERISK) == "*");
     504            1 :             CATCH_REQUIRE(a.to_ipv4_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_DEFAULT_AS_ASTERISK | addr::STRING_IP_PORT) == "*:80");
     505            1 :             CATCH_REQUIRE(a.to_ipv4_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_DEFAULT_AS_ASTERISK | addr::STRING_IP_PORT_NAME) == "*:http");
     506            1 :             CATCH_REQUIRE(a.to_ipv4_string(addr::STRING_IP_BRACKET_ADDRESS) == "0.0.0.0");
     507            1 :             CATCH_REQUIRE(a.to_ipv4_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT) == "0.0.0.0:80");
     508            1 :             CATCH_REQUIRE(a.to_ipv4_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT_NAME) == "0.0.0.0:http");
     509              :         }
     510            9 :         CATCH_END_SECTION()
     511              : 
     512            9 :         CATCH_START_SECTION("ipv4::addr: IPv6 ANY")
     513              :         {
     514            1 :             struct sockaddr_in6 in6;
     515            1 :             a.get_ipv6(in6);
     516            1 :             CATCH_REQUIRE(in6.sin6_addr.s6_addr32[0] == 0);
     517            1 :             CATCH_REQUIRE(in6.sin6_addr.s6_addr32[1] == 0);
     518            1 :             CATCH_REQUIRE(in6.sin6_addr.s6_addr32[2] == 0);
     519            1 :             CATCH_REQUIRE(in6.sin6_addr.s6_addr32[3] == 0);
     520            1 :             CATCH_REQUIRE(a.to_ipv6_string(addr::STRING_IP_ADDRESS)                                         == "::");
     521            1 :             CATCH_REQUIRE(a.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS)                                 == "[::]");
     522            1 :             CATCH_REQUIRE(a.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT)          == "[::]:0");
     523            1 :             CATCH_REQUIRE(a.to_ipv6_string(addr::STRING_IP_ADDRESS | addr::STRING_IP_MASK)                  == "::/128");
     524            1 :             CATCH_REQUIRE(a.to_ipv6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_BRACKET_MASK)  == "[::]/128");
     525            1 :             CATCH_REQUIRE(a.to_ipv6_string(addr::STRING_IP_ALL)                                             == "[::]:0/128");
     526              :         }
     527            9 :         CATCH_END_SECTION()
     528              : 
     529            9 :         CATCH_START_SECTION("ipv4::addr: IPv4 or IPv6 string")
     530              :         {
     531            1 :             CATCH_REQUIRE(a.to_ipv4or6_string(addr::STRING_IP_ADDRESS)                                          == "::");
     532            1 :             CATCH_REQUIRE(a.to_ipv4or6_string(addr::STRING_IP_BRACKET_ADDRESS)                                  == "[::]");
     533            1 :             CATCH_REQUIRE(a.to_ipv4or6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT)           == "[::]:0");
     534            1 :             CATCH_REQUIRE(a.to_ipv4or6_string(addr::STRING_IP_ADDRESS | addr::STRING_IP_MASK)                   == "::/128");
     535            1 :             CATCH_REQUIRE(a.to_ipv4or6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_BRACKET_MASK)   == "[::]/128");
     536            1 :             CATCH_REQUIRE(a.to_ipv4or6_string(addr::STRING_IP_ALL)                                              == "[::]:0/128");
     537              :         }
     538            9 :         CATCH_END_SECTION()
     539              : 
     540            9 :         CATCH_START_SECTION("ipv4::addr: interface determination")
     541              :         {
     542            1 :             CATCH_REQUIRE(addr::find_addr_interface(a, false) == nullptr);
     543            1 :             CATCH_REQUIRE(addr::find_addr_interface(a, true) != nullptr);
     544              :         }
     545            9 :         CATCH_END_SECTION()
     546              : 
     547            9 :         CATCH_START_SECTION("ipv4::addr: default name/service/port/protocol")
     548              :         {
     549            1 :             CATCH_REQUIRE(a.get_name() == std::string());
     550            1 :             CATCH_REQUIRE(a.get_service() == std::string());
     551            1 :             CATCH_REQUIRE(a.get_port() == 0);
     552            1 :             CATCH_REQUIRE(a.get_protocol() == IPPROTO_TCP);
     553              :         }
     554            9 :         CATCH_END_SECTION()
     555              : 
     556            9 :         CATCH_START_SECTION("ipv4::addr: compare with self")
     557              :         {
     558            1 :             CATCH_REQUIRE(a == a);
     559            1 :             CATCH_REQUIRE_FALSE(a != a);
     560            1 :             CATCH_REQUIRE_FALSE(a < a);
     561            1 :             CATCH_REQUIRE(a <= a);
     562            1 :             CATCH_REQUIRE_FALSE(a > a);
     563            1 :             CATCH_REQUIRE(a >= a);
     564              :         }
     565            9 :         CATCH_END_SECTION()
     566              : 
     567            9 :         CATCH_START_SECTION("ipv4::addr: compare with another 0.0.0.0")
     568              :         {
     569              :             {
     570            1 :                 addr::addr b;
     571              : 
     572            1 :                 CATCH_REQUIRE(a == b);
     573            1 :                 CATCH_REQUIRE_FALSE(a != b);
     574            1 :                 CATCH_REQUIRE_FALSE(a < b);
     575            1 :                 CATCH_REQUIRE(a <= b);
     576            1 :                 CATCH_REQUIRE_FALSE(a > b);
     577            1 :                 CATCH_REQUIRE(a >= b);
     578            1 :             }
     579              : 
     580              :             {
     581            1 :                 struct sockaddr_in6 in6 = sockaddr_in6();
     582            1 :                 in6.sin6_family = AF_INET6;
     583            1 :                 in6.sin6_port = htons(0);
     584            1 :                 in6.sin6_addr.s6_addr32[0] = htonl(0);
     585            1 :                 in6.sin6_addr.s6_addr32[1] = htonl(0);
     586            1 :                 in6.sin6_addr.s6_addr32[2] = htonl(0);
     587            1 :                 in6.sin6_addr.s6_addr32[3] = htonl(0);
     588            1 :                 addr::addr b(in6);
     589              : 
     590            1 :                 CATCH_REQUIRE(a == b);
     591            1 :                 CATCH_REQUIRE_FALSE(a != b);
     592            1 :                 CATCH_REQUIRE_FALSE(a < b);
     593            1 :                 CATCH_REQUIRE(a <= b);
     594            1 :                 CATCH_REQUIRE_FALSE(a > b);
     595            1 :                 CATCH_REQUIRE(a >= b);
     596            1 :             }
     597              : 
     598              :             // ANY in IPv4 != ANY in IPv6...
     599              :             // (i.e. IPv4 sets addr.sin6_addr.s6_addr16[5] == 0xFFFF)
     600              :             {
     601            1 :                 struct sockaddr_in in = sockaddr_in();
     602            1 :                 in.sin_family = AF_INET;
     603            1 :                 in.sin_port = htons(0);
     604            1 :                 in.sin_addr.s_addr = htonl(0);
     605            1 :                 addr::addr b(in);
     606              : 
     607            1 :                 CATCH_REQUIRE_FALSE(a == b);
     608            1 :                 CATCH_REQUIRE(a != b);
     609            1 :                 CATCH_REQUIRE(a < b);
     610            1 :                 CATCH_REQUIRE(a <= b);
     611            1 :                 CATCH_REQUIRE_FALSE(a > b);
     612            1 :                 CATCH_REQUIRE_FALSE(a >= b);
     613            1 :             }
     614              :         }
     615            9 :         CATCH_END_SECTION()
     616              : 
     617            9 :         CATCH_START_SECTION("ipv4::addr: compare with IPv4 127.0.0.1")
     618              :         {
     619            1 :             struct sockaddr_in in = sockaddr_in();
     620            1 :             in.sin_family = AF_INET;
     621            1 :             in.sin_port = htons(80);
     622            1 :             in.sin_addr.s_addr = htonl((127 << 24) | 1);
     623            1 :             addr::addr b(in);
     624              : 
     625            1 :             CATCH_REQUIRE_FALSE(a == b);
     626            1 :             CATCH_REQUIRE(a != b);
     627            1 :             CATCH_REQUIRE(a < b);
     628            1 :             CATCH_REQUIRE(a <= b);
     629            1 :             CATCH_REQUIRE_FALSE(a > b);
     630            1 :             CATCH_REQUIRE_FALSE(a >= b);
     631            1 :         }
     632            9 :         CATCH_END_SECTION()
     633           18 :     }
     634            9 : }
     635              : 
     636              : 
     637           21 : CATCH_TEST_CASE("ipv4::address", "[ipv4]")
     638              : {
     639           21 :     CATCH_GIVEN("addr() with an IPv4")
     640              :     {
     641            3 :         addr::addr a;
     642              : 
     643            3 :         CATCH_START_SECTION("ipv4::addr: set_ipv4() / get_ipv4()")
     644              :         {
     645           11 :             for(int idx(0); idx < 10; ++idx)
     646              :             {
     647           10 :                 struct sockaddr_in in = sockaddr_in();
     648           10 :                 in.sin_family = AF_INET;
     649           10 :                 in.sin_port = htons(rand());
     650           10 :                 in.sin_addr.s_addr = htonl(rand() ^ (rand() << 16));
     651              : 
     652              :                 // test constructor
     653              :                 //
     654           10 :                 addr::addr b(in);
     655           10 :                 struct sockaddr_in out;
     656           10 :                 b.get_ipv4(out);
     657           10 :                 CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
     658              : 
     659              :                 // test set
     660              :                 //
     661           10 :                 a.set_ipv4(in);
     662           10 :                 a.get_ipv4(out);
     663           10 :                 CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
     664           10 :             }
     665              :         }
     666            3 :         CATCH_END_SECTION()
     667              : 
     668            3 :         CATCH_START_SECTION("ipv4::addr: set_ipv4() / to_ipv4_string()")
     669              :         {
     670           11 :             for(int idx(0); idx < 10; ++idx)
     671              :             {
     672           10 :                 struct sockaddr_in in = sockaddr_in();
     673           10 :                 in.sin_family = AF_INET;
     674           10 :                 uint16_t const port(rand());
     675           10 :                 in.sin_port = htons(port);
     676           10 :                 uint32_t const address(rand() ^ (rand() << 16));
     677           10 :                 in.sin_addr.s_addr = htonl(address);
     678              : 
     679           10 :                 std::string ip(
     680           20 :                           std::to_string((address >> 24) & 255)
     681           40 :                         + "."
     682           40 :                         + std::to_string((address >> 16) & 255)
     683           40 :                         + "."
     684           40 :                         + std::to_string((address >>  8) & 255)
     685           40 :                         + "."
     686           20 :                         + std::to_string((address >>  0) & 255)
     687           30 :                         );
     688           10 :                 std::string port_str(std::to_string(static_cast<int>(port)));
     689              : 
     690              :                 // check IPv4 as a string
     691              :                 //
     692           10 :                 a.set_ipv4(in);
     693           10 :                 CATCH_REQUIRE(a.to_ipv4_string(addr::STRING_IP_ADDRESS)                                         == ip);
     694           10 :                 CATCH_REQUIRE(a.to_ipv4_string(addr::STRING_IP_BRACKET_ADDRESS)                                 == ip);
     695           10 :                 CATCH_REQUIRE(a.to_ipv4_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT)          == ip + ":" + port_str);
     696           10 :                 CATCH_REQUIRE(a.to_ipv4_string(addr::STRING_IP_ADDRESS | addr::STRING_IP_MASK)                  == ip + "/32");
     697           10 :                 CATCH_REQUIRE(a.to_ipv4_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_BRACKET_MASK)  == ip + "/32");
     698           10 :                 CATCH_REQUIRE(a.to_ipv4_string(addr::STRING_IP_ALL)                                             == ip + ":" + port_str + "/32");
     699              : 
     700              :                 // if the mask is not a valid IPv4 mask, then we get an exception
     701              :                 //
     702           10 :                 std::uint8_t invalid_mask[16] = { 255, 255 };
     703           10 :                 a.set_mask(invalid_mask);
     704           20 :                 CATCH_REQUIRE_THROWS_AS(a.to_ipv4_string(addr::STRING_IP_ALL), addr::addr_unexpected_mask);
     705           10 :                 invalid_mask[3] = 255;
     706           10 :                 a.set_mask(invalid_mask);
     707           20 :                 CATCH_REQUIRE_THROWS_AS(a.to_ipv4_string(addr::STRING_IP_ALL), addr::addr_unexpected_mask);
     708           10 :                 std::uint8_t const valid_mask[16] = {
     709              :                            255,    255,    255,    255,
     710              :                            255,    255,    255,    255,
     711              :                            255,    255,    255,    255,
     712           10 :                         static_cast<std::uint8_t>(rand()),
     713           10 :                         static_cast<std::uint8_t>(rand()),
     714           10 :                         static_cast<std::uint8_t>(rand()),
     715           10 :                         static_cast<std::uint8_t>(rand()),
     716           10 :                     };
     717           10 :                 a.set_mask(valid_mask);
     718           10 :                 a.set_mask_count(128);
     719           10 :             }
     720              :         }
     721            3 :         CATCH_END_SECTION()
     722              : 
     723            3 :         CATCH_START_SECTION("ipv4::addr: name of various IPs")
     724              :         {
     725            1 :             struct sockaddr_in in = sockaddr_in();
     726            1 :             in.sin_family = AF_INET;
     727            1 :             in.sin_port = htons(rand());
     728            1 :             in.sin_addr.s_addr = 0;
     729              : 
     730              :             // verify network type
     731              :             //
     732            1 :             a.set_ipv4(in);
     733            1 :             CATCH_REQUIRE(a.get_name() == std::string()); // no name for "any" (TCP)
     734              : 
     735            1 :             a.set_protocol(IPPROTO_UDP);
     736            1 :             CATCH_REQUIRE(a.get_name() == std::string()); // no name for "any" (UDP)
     737              : 
     738            1 :             in.sin_addr.s_addr = htonl(0x7f000001);
     739            1 :             a.set_ipv4(in);
     740            1 :             char hostname[HOST_NAME_MAX + 1];
     741            1 :             hostname[HOST_NAME_MAX] = '\0';
     742            1 :             CATCH_REQUIRE(gethostname(hostname, sizeof(hostname)) == 0);
     743            1 :             CATCH_REQUIRE(hostname[0] != '\0');
     744            1 :             std::string localhost(a.get_name());
     745            1 :             bool const localhost_flag(localhost == hostname || localhost == "localhost");
     746            1 :             CATCH_REQUIRE(localhost_flag);
     747              : 
     748            1 :             CATCH_REQUIRE(addr::find_addr_interface(a, false) != nullptr);
     749            1 :         }
     750            3 :         CATCH_END_SECTION()
     751           24 :     }
     752              : 
     753           21 :     CATCH_GIVEN("addr_parser() with IPv4 addresses")
     754              :     {
     755            7 :         CATCH_START_SECTION("ipv4::addr: verify basics")
     756              :         {
     757            1 :             addr::addr_parser p;
     758            1 :             p.set_protocol(IPPROTO_TCP);
     759            1 :             CATCH_REQUIRE(p.get_default_address4() == "");
     760            1 :             CATCH_REQUIRE(p.get_default_address6() == "");
     761            1 :             CATCH_REQUIRE(p.get_default_port() == -1);
     762            1 :             CATCH_REQUIRE(p.get_default_mask4() == "");
     763            1 :             CATCH_REQUIRE(p.get_default_mask6() == "");
     764            3 :             addr::addr_range::vector_t ips(p.parse("1.2.3.4"));
     765            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
     766            1 :             CATCH_REQUIRE(ips.size() == 1);
     767            1 :             addr::addr_range const & r(ips[0]);
     768            1 :             CATCH_REQUIRE(r.has_from());
     769            1 :             CATCH_REQUIRE_FALSE(r.has_to());
     770            1 :             CATCH_REQUIRE_FALSE(r.is_range());
     771            1 :             CATCH_REQUIRE_FALSE(r.is_empty());
     772            1 :             addr::addr f(r.get_from());
     773            1 :             CATCH_REQUIRE(f.is_ipv4());
     774            1 :             CATCH_REQUIRE(f.get_family() == AF_INET);
     775            1 :             CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
     776            1 :             CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "1.2.3.4");
     777            1 :             CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "1.2.3.4");
     778            1 :             CATCH_REQUIRE(f.get_port() == 0);
     779            1 :             CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
     780            1 :             CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
     781            1 :             CATCH_REQUIRE_FALSE(f.is_lan());
     782            1 :             CATCH_REQUIRE_FALSE(f.is_lan(true));
     783            1 :             CATCH_REQUIRE_FALSE(f.is_lan(false));
     784            1 :             CATCH_REQUIRE(f.is_wan());
     785            1 :             CATCH_REQUIRE(f.is_wan(true));
     786            1 :             CATCH_REQUIRE(f.is_wan(false));
     787            1 :             uint8_t mask[16] = {};
     788            1 :             f.get_mask(mask);
     789           17 :             for(int idx(0); idx < 16; ++idx)
     790              :             {
     791           16 :                 CATCH_REQUIRE(mask[idx] == 255);
     792              :             }
     793            1 :         }
     794            7 :         CATCH_END_SECTION()
     795              : 
     796            7 :         CATCH_START_SECTION("ipv4::addr: verify default address")
     797              :         {
     798            1 :             addr::addr_parser p;
     799              : 
     800            3 :             p.set_default_address("1.5.19.200");
     801            1 :             CATCH_REQUIRE(p.get_default_address4() == "1.5.19.200");
     802            1 :             CATCH_REQUIRE(p.get_default_address6() == "");
     803            3 :             p.set_default_address("");
     804            1 :             CATCH_REQUIRE(p.get_default_address4() == "");
     805            1 :             CATCH_REQUIRE(p.get_default_address6() == "");
     806              : 
     807            3 :             p.set_default_address("1.5.19.200");
     808            1 :             CATCH_REQUIRE(p.get_default_address4() == "1.5.19.200");
     809            1 :             CATCH_REQUIRE(p.get_default_address6() == "");
     810            3 :             p.set_default_address("[4:5:4:5:7:8:7:8]");
     811            1 :             CATCH_REQUIRE(p.get_default_address4() == "1.5.19.200");
     812            1 :             CATCH_REQUIRE(p.get_default_address6() == "4:5:4:5:7:8:7:8");
     813            3 :             p.set_default_address("");
     814            1 :             CATCH_REQUIRE(p.get_default_address4() == "");
     815            1 :             CATCH_REQUIRE(p.get_default_address6() == "");
     816            1 :         }
     817            7 :         CATCH_END_SECTION()
     818              : 
     819            7 :         CATCH_START_SECTION("ipv4::addr: verify default mask")
     820              :         {
     821            1 :             addr::addr_parser p;
     822              : 
     823            3 :             p.set_default_mask("1.5.19.200");
     824            1 :             CATCH_REQUIRE(p.get_default_mask4() == "1.5.19.200");
     825            1 :             CATCH_REQUIRE(p.get_default_mask6() == "");
     826            3 :             p.set_default_mask("");
     827            1 :             CATCH_REQUIRE(p.get_default_mask4() == "");
     828            1 :             CATCH_REQUIRE(p.get_default_mask6() == "");
     829              : 
     830            3 :             p.set_default_mask("1.5.19.200");
     831            1 :             CATCH_REQUIRE(p.get_default_mask4() == "1.5.19.200");
     832            1 :             CATCH_REQUIRE(p.get_default_mask6() == "");
     833            3 :             p.set_default_mask("[4:5:4:5:7:8:7:8]");
     834            1 :             CATCH_REQUIRE(p.get_default_mask4() == "1.5.19.200");
     835            1 :             CATCH_REQUIRE(p.get_default_mask6() == "4:5:4:5:7:8:7:8");
     836            3 :             p.set_default_mask("");
     837            1 :             CATCH_REQUIRE(p.get_default_mask4() == "");
     838            1 :             CATCH_REQUIRE(p.get_default_mask6() == "");
     839            1 :         }
     840            7 :         CATCH_END_SECTION()
     841              : 
     842            7 :         CATCH_START_SECTION("ipv4::addr: verify default allow flags")
     843              :         {
     844            1 :             addr::addr_parser p;
     845              : 
     846           17 :             for(int idx(0); idx < static_cast<int>(addr::allow_t::ALLOW_max); ++idx)
     847              :             {
     848           16 :                 switch(static_cast<addr::allow_t>(idx))
     849              :                 {
     850            3 :                 case addr::allow_t::ALLOW_ADDRESS:
     851              :                 case addr::allow_t::ALLOW_ADDRESS_LOOKUP:
     852              :                 case addr::allow_t::ALLOW_PORT:
     853              :                     // only these are true by default
     854              :                     //
     855            3 :                     CATCH_REQUIRE(p.get_allow(static_cast<addr::allow_t>(idx)));
     856            3 :                     break;
     857              : 
     858           13 :                 default:
     859           13 :                     CATCH_REQUIRE_FALSE(p.get_allow(static_cast<addr::allow_t>(idx)));
     860           13 :                     break;
     861              : 
     862              :                 }
     863              :             }
     864            1 :         }
     865            7 :         CATCH_END_SECTION()
     866              : 
     867            7 :         CATCH_START_SECTION("ipv4::addr: verify contradictory flags")
     868              :         {
     869            1 :             addr::addr_parser p;
     870              : 
     871              :             // by default these are set to false
     872              :             //
     873            1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS));
     874            1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_SPACES));
     875            1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::allow_t::ALLOW_MULTI_PORTS_COMMAS));
     876              : 
     877              :             // check setting MULTI_ADDRESSES_COMMAS to true
     878              :             //
     879            1 :             p.set_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS, true);
     880            1 :             CATCH_REQUIRE(p.get_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS));
     881            1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_SPACES));
     882            1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::allow_t::ALLOW_MULTI_PORTS_COMMAS));
     883              : 
     884              :             // add MULTI_ADDRESSES_SPACES
     885              :             //
     886            1 :             p.set_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_SPACES, true);
     887            1 :             CATCH_REQUIRE(p.get_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS));
     888            1 :             CATCH_REQUIRE(p.get_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_SPACES));
     889            1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::allow_t::ALLOW_MULTI_PORTS_COMMAS));
     890              : 
     891              :             // add MULTI_PORTS_COMMAS
     892              :             //
     893            1 :             p.set_allow(addr::allow_t::ALLOW_MULTI_PORTS_COMMAS, true);
     894            1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS));
     895            1 :             CATCH_REQUIRE(p.get_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_SPACES));
     896            1 :             CATCH_REQUIRE(p.get_allow(addr::allow_t::ALLOW_MULTI_PORTS_COMMAS));
     897              : 
     898              :             // add MULTI_ADDRESSES_COMMAS again
     899              :             //
     900            1 :             p.set_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS, true);
     901            1 :             CATCH_REQUIRE(p.get_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS));
     902            1 :             CATCH_REQUIRE(p.get_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_SPACES));
     903            1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::allow_t::ALLOW_MULTI_PORTS_COMMAS));
     904              : 
     905              :             // remove MULTI_ADDRESSES_SPACES
     906              :             //
     907            1 :             p.set_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_SPACES, false);
     908            1 :             CATCH_REQUIRE(p.get_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS));
     909            1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_SPACES));
     910            1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::allow_t::ALLOW_MULTI_PORTS_COMMAS));
     911              : 
     912              :             // back to MULTI_PORTS_COMMAS
     913              :             //
     914            1 :             p.set_allow(addr::allow_t::ALLOW_MULTI_PORTS_COMMAS, true);
     915            1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS));
     916            1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_SPACES));
     917            1 :             CATCH_REQUIRE(p.get_allow(addr::allow_t::ALLOW_MULTI_PORTS_COMMAS));
     918              : 
     919              :             // add MULTI_ADDRESSES_COMMAS first now
     920              :             //
     921            1 :             p.set_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS, true);
     922            1 :             CATCH_REQUIRE(p.get_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS));
     923            1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_SPACES));
     924            1 :             CATCH_REQUIRE_FALSE(p.get_allow(addr::allow_t::ALLOW_MULTI_PORTS_COMMAS));
     925            1 :         }
     926            7 :         CATCH_END_SECTION()
     927              : 
     928            7 :         CATCH_START_SECTION("ipv4::addr: default address")
     929              :         {
     930            1 :             addr::addr_parser p;
     931            1 :             p.set_protocol(IPPROTO_TCP);
     932            3 :             p.set_default_address("5.5.5.5");
     933            1 :             CATCH_REQUIRE(p.get_default_address4() == "5.5.5.5");
     934            1 :             CATCH_REQUIRE(p.get_default_address6() == "");
     935            3 :             addr::addr_range::vector_t ips(p.parse(""));
     936            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
     937            1 :             CATCH_REQUIRE(ips.size() == 1);
     938            1 :             addr::addr_range const & r(ips[0]);
     939            1 :             CATCH_REQUIRE(r.has_from());
     940            1 :             CATCH_REQUIRE_FALSE(r.has_to());
     941            1 :             CATCH_REQUIRE_FALSE(r.is_range());
     942            1 :             CATCH_REQUIRE_FALSE(r.is_empty());
     943            1 :             addr::addr f(r.get_from());
     944            1 :             CATCH_REQUIRE(f.is_ipv4());
     945            1 :             CATCH_REQUIRE(f.get_family() == AF_INET);
     946            1 :             CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
     947            1 :             CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "5.5.5.5");
     948            1 :             CATCH_REQUIRE(f.get_port() == 0);
     949            1 :             CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
     950            1 :             CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
     951            1 :             CATCH_REQUIRE_FALSE(f.is_lan());
     952            1 :             CATCH_REQUIRE_FALSE(f.is_lan(true));
     953            1 :             CATCH_REQUIRE_FALSE(f.is_lan(false));
     954            1 :             CATCH_REQUIRE(f.is_wan());
     955            1 :             CATCH_REQUIRE(f.is_wan(true));
     956            1 :             CATCH_REQUIRE(f.is_wan(false));
     957            1 :         }
     958            7 :         CATCH_END_SECTION()
     959              : 
     960            7 :         CATCH_START_SECTION("ipv4::addr: address, no port allowed")
     961              :         {
     962              :             // specific address with a default
     963              :             {
     964            1 :                 addr::addr_parser p;
     965            1 :                 p.set_allow(addr::allow_t::ALLOW_PORT, false);
     966            1 :                 p.set_protocol(IPPROTO_TCP);
     967            3 :                 p.set_default_address("5.5.5.5");
     968            1 :                 CATCH_REQUIRE(p.get_default_address4() == "5.5.5.5");
     969            1 :                 CATCH_REQUIRE(p.get_default_address6() == "");
     970            3 :                 addr::addr_range::vector_t ips(p.parse("9.9.9.9"));
     971            1 :                 CATCH_REQUIRE_FALSE(p.has_errors());
     972            1 :                 CATCH_REQUIRE(ips.size() == 1);
     973            1 :                 addr::addr_range const & r(ips[0]);
     974            1 :                 CATCH_REQUIRE(r.has_from());
     975            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
     976            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
     977            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
     978            1 :                 addr::addr f(r.get_from());
     979            1 :                 CATCH_REQUIRE(f.is_ipv4());
     980            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
     981            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
     982            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "9.9.9.9");
     983            1 :                 CATCH_REQUIRE(f.get_port() == 0);
     984            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
     985            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
     986            1 :                 CATCH_REQUIRE_FALSE(f.is_lan());
     987            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
     988            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
     989            1 :                 CATCH_REQUIRE(f.is_wan());
     990            1 :                 CATCH_REQUIRE(f.is_wan(true));
     991            1 :                 CATCH_REQUIRE(f.is_wan(false));
     992            1 :             }
     993              : 
     994              :             // only a default address
     995              :             {
     996            1 :                 addr::addr_parser p;
     997            1 :                 p.set_allow(addr::allow_t::ALLOW_PORT, false);
     998            1 :                 p.set_protocol(IPPROTO_TCP);
     999            3 :                 p.set_default_address("5.5.5.5");
    1000            1 :                 CATCH_REQUIRE(p.get_default_address4() == "5.5.5.5");
    1001            1 :                 CATCH_REQUIRE(p.get_default_address6() == "");
    1002            3 :                 addr::addr_range::vector_t ips(p.parse(""));
    1003            1 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1004            1 :                 CATCH_REQUIRE(ips.size() == 1);
    1005            1 :                 addr::addr_range const & r(ips[0]);
    1006            1 :                 CATCH_REQUIRE(r.has_from());
    1007            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1008            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1009            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1010            1 :                 addr::addr f(r.get_from());
    1011            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1012            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1013            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1014            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "5.5.5.5");
    1015            1 :                 CATCH_REQUIRE(f.get_port() == 0);
    1016            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1017            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1018            1 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1019            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1020            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1021            1 :                 CATCH_REQUIRE(f.is_wan());
    1022            1 :                 CATCH_REQUIRE(f.is_wan(true));
    1023            1 :                 CATCH_REQUIRE(f.is_wan(false));
    1024            1 :             }
    1025              :         }
    1026            7 :         CATCH_END_SECTION()
    1027           21 :     }
    1028              : 
    1029           21 :     CATCH_GIVEN("addr_parser() with multiple IPv4 addresses in one string")
    1030              :     {
    1031            6 :         CATCH_START_SECTION("ipv4::addr: 3 IPs separated by commas")
    1032              :         {
    1033            1 :             addr::addr_parser p;
    1034            1 :             p.set_protocol(IPPROTO_TCP);
    1035            1 :             p.set_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS, true);
    1036            3 :             addr::addr_range::vector_t ips(p.parse("1.2.3.4:55,5.6.7.8,,,,10.11.12.99:77"));
    1037            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1038            1 :             CATCH_REQUIRE(ips.size() == 3);
    1039              : 
    1040            1 :             uint8_t mask[16] = {};
    1041              : 
    1042              :             // 1.2.3.4:55
    1043              :             {
    1044            1 :                 addr::addr_range const & r(ips[0]);
    1045            1 :                 CATCH_REQUIRE(r.has_from());
    1046            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1047            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1048            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1049            1 :                 addr::addr f(r.get_from());
    1050            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1051            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1052            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1053            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "1.2.3.4");
    1054            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "1.2.3.4");
    1055            1 :                 CATCH_REQUIRE(f.get_port() == 55);
    1056            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1057            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1058            1 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1059            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1060            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1061            1 :                 CATCH_REQUIRE(f.is_wan());
    1062            1 :                 CATCH_REQUIRE(f.is_wan(true));
    1063            1 :                 CATCH_REQUIRE(f.is_wan(false));
    1064            1 :                 f.get_mask(mask);
    1065           17 :                 for(int idx(0); idx < 16; ++idx)
    1066              :                 {
    1067           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1068              :                 }
    1069            1 :             }
    1070              : 
    1071              :             // 5.6.7.8
    1072              :             {
    1073            1 :                 addr::addr_range const & r(ips[1]);
    1074            1 :                 CATCH_REQUIRE(r.has_from());
    1075            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1076            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1077            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1078            1 :                 addr::addr f(r.get_from());
    1079            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1080            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1081            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1082            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "5.6.7.8");
    1083            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "5.6.7.8");
    1084            1 :                 CATCH_REQUIRE(f.get_port() == 0);
    1085            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1086            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1087            1 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1088            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1089            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1090            1 :                 CATCH_REQUIRE(f.is_wan());
    1091            1 :                 CATCH_REQUIRE(f.is_wan(true));
    1092            1 :                 CATCH_REQUIRE(f.is_wan(false));
    1093            1 :                 f.get_mask(mask);
    1094           17 :                 for(int idx(0); idx < 16; ++idx)
    1095              :                 {
    1096           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1097              :                 }
    1098            1 :             }
    1099              : 
    1100              :             // 10.11.12.99:77
    1101              :             {
    1102            1 :                 addr::addr_range const & r(ips[2]);
    1103            1 :                 CATCH_REQUIRE(r.has_from());
    1104            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1105            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1106            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1107            1 :                 addr::addr f(r.get_from());
    1108            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1109            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1110            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1111            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.11.12.99");
    1112            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "10.11.12.99");
    1113            1 :                 CATCH_REQUIRE(f.get_port() == 77);
    1114            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1115            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1116            1 :                 CATCH_REQUIRE(f.is_lan());
    1117            1 :                 CATCH_REQUIRE(f.is_lan(true));
    1118            1 :                 CATCH_REQUIRE(f.is_lan(false));
    1119            1 :                 CATCH_REQUIRE_FALSE(f.is_wan());
    1120            1 :                 CATCH_REQUIRE_FALSE(f.is_wan(true));
    1121            1 :                 CATCH_REQUIRE_FALSE(f.is_wan(false));
    1122            1 :                 f.get_mask(mask);
    1123           17 :                 for(int idx(0); idx < 16; ++idx)
    1124              :                 {
    1125           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1126              :                 }
    1127            1 :             }
    1128            1 :         }
    1129            6 :         CATCH_END_SECTION()
    1130              : 
    1131            6 :         CATCH_START_SECTION("ipv4::addr: 3 IPs separated by spaces")
    1132              :         {
    1133            1 :             addr::addr_parser p;
    1134            1 :             p.set_protocol(IPPROTO_TCP);
    1135            1 :             p.set_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_SPACES, true);
    1136            3 :             addr::addr_range::vector_t ips(p.parse("1.2.3.4:55 5.6.7.8   10.11.12.99:77"));
    1137            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1138            1 :             CATCH_REQUIRE(ips.size() == 3);
    1139              : 
    1140            1 :             uint8_t mask[16] = {};
    1141              : 
    1142              :             // 1.2.3.4:55
    1143              :             {
    1144            1 :                 addr::addr_range const & r(ips[0]);
    1145            1 :                 CATCH_REQUIRE(r.has_from());
    1146            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1147            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1148            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1149            1 :                 addr::addr f(r.get_from());
    1150            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1151            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1152            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1153            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "1.2.3.4");
    1154            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "1.2.3.4");
    1155            1 :                 CATCH_REQUIRE(f.get_port() == 55);
    1156            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1157            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1158            1 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1159            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1160            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1161            1 :                 CATCH_REQUIRE(f.is_wan());
    1162            1 :                 CATCH_REQUIRE(f.is_wan(true));
    1163            1 :                 CATCH_REQUIRE(f.is_wan(false));
    1164            1 :                 f.get_mask(mask);
    1165           17 :                 for(int idx(0); idx < 16; ++idx)
    1166              :                 {
    1167           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1168              :                 }
    1169            1 :             }
    1170              : 
    1171              :             // 5.6.7.8
    1172              :             {
    1173            1 :                 addr::addr_range const & r(ips[1]);
    1174            1 :                 CATCH_REQUIRE(r.has_from());
    1175            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1176            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1177            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1178            1 :                 addr::addr f(r.get_from());
    1179            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1180            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1181            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1182            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "5.6.7.8");
    1183            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "5.6.7.8");
    1184            1 :                 CATCH_REQUIRE(f.get_port() == 0);
    1185            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1186            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1187            1 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1188            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1189            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1190            1 :                 CATCH_REQUIRE(f.is_wan());
    1191            1 :                 CATCH_REQUIRE(f.is_wan(true));
    1192            1 :                 CATCH_REQUIRE(f.is_wan(false));
    1193            1 :                 f.get_mask(mask);
    1194           17 :                 for(int idx(0); idx < 16; ++idx)
    1195              :                 {
    1196           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1197              :                 }
    1198            1 :             }
    1199              : 
    1200              :             // 10.11.12.99:77
    1201              :             {
    1202            1 :                 addr::addr_range const & r(ips[2]);
    1203            1 :                 CATCH_REQUIRE(r.has_from());
    1204            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1205            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1206            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1207            1 :                 addr::addr f(r.get_from());
    1208            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1209            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1210            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1211            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.11.12.99");
    1212            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "10.11.12.99");
    1213            1 :                 CATCH_REQUIRE(f.get_port() == 77);
    1214            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1215            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1216            1 :                 CATCH_REQUIRE(f.is_lan());
    1217            1 :                 CATCH_REQUIRE(f.is_lan(true));
    1218            1 :                 CATCH_REQUIRE(f.is_lan(false));
    1219            1 :                 CATCH_REQUIRE_FALSE(f.is_wan());
    1220            1 :                 CATCH_REQUIRE_FALSE(f.is_wan(true));
    1221            1 :                 CATCH_REQUIRE_FALSE(f.is_wan(false));
    1222            1 :                 f.get_mask(mask);
    1223           17 :                 for(int idx(0); idx < 16; ++idx)
    1224              :                 {
    1225           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1226              :                 }
    1227            1 :             }
    1228            1 :         }
    1229            6 :         CATCH_END_SECTION()
    1230              : 
    1231            6 :         CATCH_START_SECTION("ipv4::addr: 3 IPs separated by commas and/or spaces")
    1232              :         {
    1233            1 :             addr::addr_parser p;
    1234            1 :             p.set_protocol(IPPROTO_TCP);
    1235            1 :             p.set_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS, true);
    1236            1 :             p.set_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_SPACES, true);
    1237            3 :             addr::addr_range::vector_t ips(p.parse(" 1.2.3.4:55,, 5.6.7.8 , 10.11.12.99:77 "));
    1238            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1239            1 :             CATCH_REQUIRE(ips.size() == 3);
    1240              : 
    1241            1 :             uint8_t mask[16] = {};
    1242              : 
    1243              :             // 1.2.3.4:55
    1244              :             {
    1245            1 :                 addr::addr_range const & r(ips[0]);
    1246            1 :                 CATCH_REQUIRE(r.has_from());
    1247            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1248            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1249            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1250            1 :                 addr::addr f(r.get_from());
    1251            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1252            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1253            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1254            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "1.2.3.4");
    1255            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "1.2.3.4");
    1256            1 :                 CATCH_REQUIRE(f.get_port() == 55);
    1257            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1258            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1259            1 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1260            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1261            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1262            1 :                 CATCH_REQUIRE(f.is_wan());
    1263            1 :                 CATCH_REQUIRE(f.is_wan(true));
    1264            1 :                 CATCH_REQUIRE(f.is_wan(false));
    1265            1 :                 f.get_mask(mask);
    1266           17 :                 for(int idx(0); idx < 16; ++idx)
    1267              :                 {
    1268           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1269              :                 }
    1270            1 :             }
    1271              : 
    1272              :             // 5.6.7.8
    1273              :             {
    1274            1 :                 addr::addr_range const & r(ips[1]);
    1275            1 :                 CATCH_REQUIRE(r.has_from());
    1276            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1277            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1278            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1279            1 :                 addr::addr f(r.get_from());
    1280            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1281            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1282            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1283            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "5.6.7.8");
    1284            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "5.6.7.8");
    1285            1 :                 CATCH_REQUIRE(f.get_port() == 0);
    1286            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1287            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1288            1 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1289            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1290            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1291            1 :                 CATCH_REQUIRE(f.is_wan());
    1292            1 :                 CATCH_REQUIRE(f.is_wan(true));
    1293            1 :                 CATCH_REQUIRE(f.is_wan(false));
    1294            1 :                 f.get_mask(mask);
    1295           17 :                 for(int idx(0); idx < 16; ++idx)
    1296              :                 {
    1297           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1298              :                 }
    1299            1 :             }
    1300              : 
    1301              :             // 10.11.12.99:77
    1302              :             {
    1303            1 :                 addr::addr_range const & r(ips[2]);
    1304            1 :                 CATCH_REQUIRE(r.has_from());
    1305            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1306            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1307            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1308            1 :                 addr::addr f(r.get_from());
    1309            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1310            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1311            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1312            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.11.12.99");
    1313            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "10.11.12.99");
    1314            1 :                 CATCH_REQUIRE(f.get_port() == 77);
    1315            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1316            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1317            1 :                 CATCH_REQUIRE(f.is_lan());
    1318            1 :                 CATCH_REQUIRE(f.is_lan(true));
    1319            1 :                 CATCH_REQUIRE(f.is_lan(false));
    1320            1 :                 CATCH_REQUIRE_FALSE(f.is_wan());
    1321            1 :                 CATCH_REQUIRE_FALSE(f.is_wan(true));
    1322            1 :                 CATCH_REQUIRE_FALSE(f.is_wan(false));
    1323            1 :                 f.get_mask(mask);
    1324           17 :                 for(int idx(0); idx < 16; ++idx)
    1325              :                 {
    1326           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1327              :                 }
    1328            1 :             }
    1329            1 :         }
    1330            6 :         CATCH_END_SECTION()
    1331              : 
    1332            6 :         CATCH_START_SECTION("ipv4::addr: 3 IPs with hash (#) comments")
    1333              :         {
    1334            1 :             addr::addr_parser p;
    1335            1 :             p.set_protocol(IPPROTO_TCP);
    1336            1 :             p.set_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS, true);
    1337            1 :             p.set_allow(addr::allow_t::ALLOW_COMMENT_HASH, true);
    1338            3 :             addr::addr_range::vector_t ips(p.parse("1.2.3.4:55#first,5.6.7.8#second,10.11.12.99:77#third"));
    1339            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1340            1 :             CATCH_REQUIRE(ips.size() == 3);
    1341              : 
    1342            1 :             uint8_t mask[16] = {};
    1343              : 
    1344              :             // 1.2.3.4:55
    1345              :             {
    1346            1 :                 addr::addr_range const & r(ips[0]);
    1347            1 :                 CATCH_REQUIRE(r.has_from());
    1348            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1349            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1350            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1351            1 :                 addr::addr f(r.get_from());
    1352            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1353            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1354            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1355            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "1.2.3.4");
    1356            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "1.2.3.4");
    1357            1 :                 CATCH_REQUIRE(f.get_port() == 55);
    1358            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1359            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1360            1 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1361            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1362            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1363            1 :                 CATCH_REQUIRE(f.is_wan());
    1364            1 :                 CATCH_REQUIRE(f.is_wan(true));
    1365            1 :                 CATCH_REQUIRE(f.is_wan(false));
    1366            1 :                 f.get_mask(mask);
    1367           17 :                 for(int idx(0); idx < 16; ++idx)
    1368              :                 {
    1369           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1370              :                 }
    1371            1 :             }
    1372              : 
    1373              :             // 5.6.7.8
    1374              :             {
    1375            1 :                 addr::addr_range const & r(ips[1]);
    1376            1 :                 CATCH_REQUIRE(r.has_from());
    1377            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1378            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1379            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1380            1 :                 addr::addr f(r.get_from());
    1381            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1382            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1383            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1384            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "5.6.7.8");
    1385            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "5.6.7.8");
    1386            1 :                 CATCH_REQUIRE(f.get_port() == 0);
    1387            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1388            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1389            1 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1390            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1391            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1392            1 :                 CATCH_REQUIRE(f.is_wan());
    1393            1 :                 CATCH_REQUIRE(f.is_wan(true));
    1394            1 :                 CATCH_REQUIRE(f.is_wan(false));
    1395            1 :                 f.get_mask(mask);
    1396           17 :                 for(int idx(0); idx < 16; ++idx)
    1397              :                 {
    1398           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1399              :                 }
    1400            1 :             }
    1401              : 
    1402              :             // 10.11.12.99:77
    1403              :             {
    1404            1 :                 addr::addr_range const & r(ips[2]);
    1405            1 :                 CATCH_REQUIRE(r.has_from());
    1406            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1407            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1408            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1409            1 :                 addr::addr f(r.get_from());
    1410            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1411            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1412            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1413            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.11.12.99");
    1414            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "10.11.12.99");
    1415            1 :                 CATCH_REQUIRE(f.get_port() == 77);
    1416            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1417            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1418            1 :                 CATCH_REQUIRE(f.is_lan());
    1419            1 :                 CATCH_REQUIRE(f.is_lan(true));
    1420            1 :                 CATCH_REQUIRE(f.is_lan(false));
    1421            1 :                 CATCH_REQUIRE_FALSE(f.is_wan());
    1422            1 :                 CATCH_REQUIRE_FALSE(f.is_wan(true));
    1423            1 :                 CATCH_REQUIRE_FALSE(f.is_wan(false));
    1424            1 :                 f.get_mask(mask);
    1425           17 :                 for(int idx(0); idx < 16; ++idx)
    1426              :                 {
    1427           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1428              :                 }
    1429            1 :             }
    1430            1 :         }
    1431            6 :         CATCH_END_SECTION()
    1432              : 
    1433            6 :         CATCH_START_SECTION("ipv4::addr: 3 IPs with semicolon (;) comments")
    1434              :         {
    1435            1 :             addr::addr_parser p;
    1436            1 :             p.set_protocol(IPPROTO_TCP);
    1437            1 :             p.set_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS, true);
    1438            1 :             p.set_allow(addr::allow_t::ALLOW_COMMENT_SEMICOLON, true);
    1439            3 :             addr::addr_range::vector_t ips(p.parse("1.2.3.4:55;first,5.6.7.8;second,10.11.12.99:77;third"));
    1440            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1441            1 :             CATCH_REQUIRE(ips.size() == 3);
    1442              : 
    1443            1 :             uint8_t mask[16] = {};
    1444              : 
    1445              :             // 1.2.3.4:55
    1446              :             {
    1447            1 :                 addr::addr_range const & r(ips[0]);
    1448            1 :                 CATCH_REQUIRE(r.has_from());
    1449            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1450            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1451            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1452            1 :                 addr::addr f(r.get_from());
    1453            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1454            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1455            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1456            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "1.2.3.4");
    1457            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "1.2.3.4");
    1458            1 :                 CATCH_REQUIRE(f.get_port() == 55);
    1459            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1460            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1461            1 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1462            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1463            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1464            1 :                 CATCH_REQUIRE(f.is_wan());
    1465            1 :                 CATCH_REQUIRE(f.is_wan(true));
    1466            1 :                 CATCH_REQUIRE(f.is_wan(false));
    1467            1 :                 f.get_mask(mask);
    1468           17 :                 for(int idx(0); idx < 16; ++idx)
    1469              :                 {
    1470           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1471              :                 }
    1472            1 :             }
    1473              : 
    1474              :             // 5.6.7.8
    1475              :             {
    1476            1 :                 addr::addr_range const & r(ips[1]);
    1477            1 :                 CATCH_REQUIRE(r.has_from());
    1478            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1479            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1480            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1481            1 :                 addr::addr f(r.get_from());
    1482            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1483            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1484            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1485            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "5.6.7.8");
    1486            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "5.6.7.8");
    1487            1 :                 CATCH_REQUIRE(f.get_port() == 0);
    1488            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1489            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1490            1 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1491            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1492            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1493            1 :                 CATCH_REQUIRE(f.is_wan());
    1494            1 :                 CATCH_REQUIRE(f.is_wan(true));
    1495            1 :                 CATCH_REQUIRE(f.is_wan(false));
    1496            1 :                 f.get_mask(mask);
    1497           17 :                 for(int idx(0); idx < 16; ++idx)
    1498              :                 {
    1499           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1500              :                 }
    1501            1 :             }
    1502              : 
    1503              :             // 10.11.12.99:77
    1504              :             {
    1505            1 :                 addr::addr_range const & r(ips[2]);
    1506            1 :                 CATCH_REQUIRE(r.has_from());
    1507            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1508            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1509            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1510            1 :                 addr::addr f(r.get_from());
    1511            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1512            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1513            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1514            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.11.12.99");
    1515            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "10.11.12.99");
    1516            1 :                 CATCH_REQUIRE(f.get_port() == 77);
    1517            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1518            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1519            1 :                 CATCH_REQUIRE(f.is_lan());
    1520            1 :                 CATCH_REQUIRE(f.is_lan(true));
    1521            1 :                 CATCH_REQUIRE(f.is_lan(false));
    1522            1 :                 CATCH_REQUIRE_FALSE(f.is_wan());
    1523            1 :                 CATCH_REQUIRE_FALSE(f.is_wan(true));
    1524            1 :                 CATCH_REQUIRE_FALSE(f.is_wan(false));
    1525            1 :                 f.get_mask(mask);
    1526           17 :                 for(int idx(0); idx < 16; ++idx)
    1527              :                 {
    1528           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1529              :                 }
    1530            1 :             }
    1531            1 :         }
    1532            6 :         CATCH_END_SECTION()
    1533              : 
    1534            6 :         CATCH_START_SECTION("ipv4::addr: 3 IPs with hash (#) and semicolon (;) comments")
    1535              :         {
    1536            1 :             addr::addr_parser p;
    1537            1 :             p.set_protocol(IPPROTO_TCP);
    1538            1 :             p.set_allow(addr::allow_t::ALLOW_MULTI_ADDRESSES_COMMAS, true);
    1539            1 :             p.set_allow(addr::allow_t::ALLOW_COMMENT_HASH, true);
    1540            1 :             p.set_allow(addr::allow_t::ALLOW_COMMENT_SEMICOLON, true);
    1541            3 :             addr::addr_range::vector_t ips(p.parse("1.2.3.4:55;first,5.6.7.8#second,10.11.12.99:77;third"));
    1542            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1543            1 :             CATCH_REQUIRE(ips.size() == 3);
    1544              : 
    1545            1 :             uint8_t mask[16] = {};
    1546              : 
    1547              :             // 1.2.3.4:55
    1548              :             {
    1549            1 :                 addr::addr_range const & r(ips[0]);
    1550            1 :                 CATCH_REQUIRE(r.has_from());
    1551            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1552            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1553            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1554            1 :                 addr::addr f(r.get_from());
    1555            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1556            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1557            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1558            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "1.2.3.4");
    1559            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "1.2.3.4");
    1560            1 :                 CATCH_REQUIRE(f.get_port() == 55);
    1561            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1562            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1563            1 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1564            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1565            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1566            1 :                 CATCH_REQUIRE(f.is_wan());
    1567            1 :                 CATCH_REQUIRE(f.is_wan(true));
    1568            1 :                 CATCH_REQUIRE(f.is_wan(false));
    1569            1 :                 f.get_mask(mask);
    1570           17 :                 for(int idx(0); idx < 16; ++idx)
    1571              :                 {
    1572           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1573              :                 }
    1574            1 :             }
    1575              : 
    1576              :             // 5.6.7.8
    1577              :             {
    1578            1 :                 addr::addr_range const & r(ips[1]);
    1579            1 :                 CATCH_REQUIRE(r.has_from());
    1580            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1581            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1582            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1583            1 :                 addr::addr f(r.get_from());
    1584            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1585            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1586            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1587            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "5.6.7.8");
    1588            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "5.6.7.8");
    1589            1 :                 CATCH_REQUIRE(f.get_port() == 0);
    1590            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1591            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1592            1 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1593            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1594            1 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1595            1 :                 CATCH_REQUIRE(f.is_wan());
    1596            1 :                 CATCH_REQUIRE(f.is_wan(true));
    1597            1 :                 CATCH_REQUIRE(f.is_wan(false));
    1598            1 :                 f.get_mask(mask);
    1599           17 :                 for(int idx(0); idx < 16; ++idx)
    1600              :                 {
    1601           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1602              :                 }
    1603            1 :             }
    1604              : 
    1605              :             // 10.11.12.99:77
    1606              :             {
    1607            1 :                 addr::addr_range const & r(ips[2]);
    1608            1 :                 CATCH_REQUIRE(r.has_from());
    1609            1 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1610            1 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1611            1 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1612            1 :                 addr::addr f(r.get_from());
    1613            1 :                 CATCH_REQUIRE(f.is_ipv4());
    1614            1 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1615            1 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1616            1 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "10.11.12.99");
    1617            1 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "10.11.12.99");
    1618            1 :                 CATCH_REQUIRE(f.get_port() == 77);
    1619            1 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1620            1 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1621            1 :                 CATCH_REQUIRE(f.is_lan());
    1622            1 :                 CATCH_REQUIRE(f.is_lan(true));
    1623            1 :                 CATCH_REQUIRE(f.is_lan(false));
    1624            1 :                 CATCH_REQUIRE_FALSE(f.is_wan());
    1625            1 :                 CATCH_REQUIRE_FALSE(f.is_wan(true));
    1626            1 :                 CATCH_REQUIRE_FALSE(f.is_wan(false));
    1627            1 :                 f.get_mask(mask);
    1628           17 :                 for(int idx(0); idx < 16; ++idx)
    1629              :                 {
    1630           16 :                     CATCH_REQUIRE(mask[idx] == 255);
    1631              :                 }
    1632            1 :             }
    1633            1 :         }
    1634            6 :         CATCH_END_SECTION()
    1635           21 :     }
    1636              : 
    1637           21 :     CATCH_GIVEN("addr_parser() with numeric only IPv4 addresses")
    1638              :     {
    1639            3 :         CATCH_START_SECTION("ipv4::addr: simple numeric IPv4")
    1640              :         {
    1641            1 :             addr::addr_parser p;
    1642            1 :             p.set_protocol(IPPROTO_TCP);
    1643            1 :             p.set_allow(addr::allow_t::ALLOW_ADDRESS_LOOKUP, false);
    1644            3 :             addr::addr_range::vector_t ips(p.parse("4.3.1.2:3003"));
    1645            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1646            1 :             CATCH_REQUIRE(ips.size() == 1);
    1647              : 
    1648            1 :             addr::addr_range const & r(ips[0]);
    1649            1 :             CATCH_REQUIRE(r.has_from());
    1650            1 :             CATCH_REQUIRE_FALSE(r.has_to());
    1651            1 :             CATCH_REQUIRE_FALSE(r.is_range());
    1652            1 :             CATCH_REQUIRE_FALSE(r.is_empty());
    1653            1 :             addr::addr f(r.get_from());
    1654            1 :             CATCH_REQUIRE(f.is_ipv4());
    1655            1 :             CATCH_REQUIRE(f.get_family() == AF_INET);
    1656            1 :             CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1657            1 :             CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "4.3.1.2");
    1658            1 :             CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "4.3.1.2");
    1659            1 :             CATCH_REQUIRE(f.get_port() == 3003);
    1660            1 :             CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1661            1 :             CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1662            1 :             CATCH_REQUIRE_FALSE(f.is_lan());
    1663            1 :             CATCH_REQUIRE_FALSE(f.is_lan(true));
    1664            1 :             CATCH_REQUIRE_FALSE(f.is_lan(false));
    1665            1 :             CATCH_REQUIRE(f.is_wan());
    1666            1 :             CATCH_REQUIRE(f.is_wan(true));
    1667            1 :             CATCH_REQUIRE(f.is_wan(false));
    1668            1 :             uint8_t mask[16] = {};
    1669            1 :             f.get_mask(mask);
    1670           17 :             for(int idx(0); idx < 16; ++idx)
    1671              :             {
    1672           16 :                 CATCH_REQUIRE(mask[idx] == 255);
    1673              :             }
    1674            1 :         }
    1675            3 :         CATCH_END_SECTION()
    1676              : 
    1677            3 :         CATCH_START_SECTION("ipv4::addr: invalid domain name address when we only accept numeric IPs")
    1678              :         {
    1679            1 :             addr::addr_parser p;
    1680            1 :             p.set_protocol(IPPROTO_TCP);
    1681            1 :             p.set_allow(addr::allow_t::ALLOW_ADDRESS_LOOKUP, false);
    1682            3 :             addr::addr_range::vector_t ips(p.parse("www.example.com:4471"));
    1683            1 :             CATCH_REQUIRE(p.has_errors());
    1684            1 :             CATCH_REQUIRE(p.error_count() == 1);
    1685            1 :             CATCH_REQUIRE(p.error_messages() == "Unknown address in \"www.example.com\" (no DNS lookup was allowed).\n");
    1686            1 :             CATCH_REQUIRE(ips.size() == 0);
    1687            1 :         }
    1688            3 :         CATCH_END_SECTION()
    1689              : 
    1690            3 :         CATCH_START_SECTION("ipv4::addr: invalid port: service name not allowed")
    1691              :         {
    1692            1 :             addr::addr_parser p;
    1693            1 :             p.set_protocol(IPPROTO_TCP);
    1694            1 :             p.set_allow(addr::allow_t::ALLOW_ADDRESS_LOOKUP, false);
    1695            3 :             addr::addr_range::vector_t ips(p.parse("192.168.255.32:https"));
    1696            1 :             CATCH_REQUIRE(p.has_errors());
    1697            1 :             CATCH_REQUIRE(p.error_count() == 1);
    1698            1 :             CATCH_REQUIRE(p.error_messages() == "invalid port in \"https\" (no service name lookup allowed).\n");
    1699            1 :             CATCH_REQUIRE(ips.size() == 0);
    1700            1 :         }
    1701            3 :         CATCH_END_SECTION()
    1702           21 :     }
    1703              : 
    1704           21 :     CATCH_START_SECTION("ipv4::addr: IP as hostname")
    1705              :     {
    1706           11 :         for(int idx(0); idx < 10; ++idx)
    1707              :         {
    1708           10 :             struct sockaddr_in in = sockaddr_in();
    1709           10 :             in.sin_family = AF_INET;
    1710           10 :             in.sin_port = htons(rand());
    1711           10 :             in.sin_addr.s_addr = htonl(rand() ^ (rand() << 16));
    1712           10 :             addr::addr a(in);
    1713           10 :             struct sockaddr_in out;
    1714           10 :             a.get_ipv4(out);
    1715           10 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    1716           10 :             CATCH_REQUIRE(a.get_hostname().empty());
    1717           10 :             std::string const ip(a.to_ipv4or6_string(addr::STRING_IP_ADDRESS));
    1718           10 :             a.set_hostname(ip);
    1719           10 :             CATCH_REQUIRE(a.get_hostname() == ip);
    1720           10 :             CATCH_REQUIRE(a.is_hostname_an_ip());
    1721           30 :             a.set_hostname("no.an.ip");
    1722           10 :             CATCH_REQUIRE(a.get_hostname() == "no.an.ip");
    1723           10 :             CATCH_REQUIRE_FALSE(a.is_hostname_an_ip());
    1724           10 :         }
    1725              :     }
    1726           21 :     CATCH_END_SECTION()
    1727              : 
    1728           21 :     CATCH_START_SECTION("ipv4::addr: set interface")
    1729              :     {
    1730            1 :         addr::addr a;
    1731            1 :         CATCH_REQUIRE(a.get_interface().empty());
    1732            3 :         a.set_interface("eth0");
    1733            1 :         CATCH_REQUIRE(a.get_interface() == "eth0");
    1734            3 :         a.set_interface("epn3");
    1735            1 :         CATCH_REQUIRE(a.get_interface() == "epn3");
    1736            1 :         a.set_interface(std::string());
    1737            1 :         CATCH_REQUIRE(a.get_interface().empty());
    1738            1 :     }
    1739           21 :     CATCH_END_SECTION()
    1740           21 : }
    1741              : 
    1742              : 
    1743            5 : CATCH_TEST_CASE("ipv4::ports", "[ipv4]")
    1744              : {
    1745            5 :     CATCH_START_SECTION("ipv4::addr: verify port names")
    1746              :     {
    1747              :         // test a few ports that we know are and are not defined in /etc/services
    1748              :         //
    1749            1 :         addr::addr a;
    1750              : 
    1751            1 :         struct sockaddr_in in = sockaddr_in();
    1752            1 :         in.sin_family = AF_INET;
    1753            1 :         in.sin_port = htons(rand());
    1754            1 :         SNAP_CATCH2_NAMESPACE::random(in.sin_addr.s_addr);
    1755              : 
    1756              :         // verify network type
    1757              :         //
    1758            1 :         a.set_ipv4(in);
    1759            1 :         CATCH_REQUIRE(a.is_ipv4());
    1760              : 
    1761              :         struct port_name_t
    1762              :         {
    1763              :             int             f_port = 0;
    1764              :             char const *    f_name = nullptr;
    1765              :         };
    1766            1 :         port_name_t names[] = {
    1767              :             { 21, "ftp" },
    1768              :             { 22, "ssh" },
    1769              :             { 23, "telnet" },
    1770              :             { 80, "http" },
    1771              :             { 443, "https" },
    1772              :             { 4004, "" },
    1773              :         };
    1774              : 
    1775            7 :         for(auto n : names)
    1776              :         {
    1777            6 :             a.set_port(n.f_port);
    1778            6 :             CATCH_REQUIRE(a.get_port_name() == n.f_name);
    1779              :         }
    1780            1 :     }
    1781            5 :     CATCH_END_SECTION()
    1782              : 
    1783            5 :     CATCH_START_SECTION("ipv4::addr: verify protocol names")
    1784              :     {
    1785              :         // test a few ports that we know are and are not defined in /etc/services
    1786              :         //
    1787            1 :         addr::addr a;
    1788              : 
    1789            1 :         struct sockaddr_in6 in6 = sockaddr_in6();
    1790            1 :         in6.sin6_family = AF_INET6;
    1791            1 :         in6.sin6_port = htons(rand());
    1792              :         do
    1793              :         {
    1794            1 :             SNAP_CATCH2_NAMESPACE::random(in6.sin6_addr.s6_addr32[0]);
    1795            1 :             SNAP_CATCH2_NAMESPACE::random(in6.sin6_addr.s6_addr32[1]);
    1796            1 :             SNAP_CATCH2_NAMESPACE::random(in6.sin6_addr.s6_addr32[2]);
    1797            1 :             SNAP_CATCH2_NAMESPACE::random(in6.sin6_addr.s6_addr32[3]);
    1798            1 :             a.set_ipv6(in6);
    1799              :         }
    1800            1 :         while(!a.is_valid() || a.is_ipv4());
    1801            1 :         CATCH_REQUIRE(!a.is_ipv4());
    1802              : 
    1803              :         struct protocol_name_t
    1804              :         {
    1805              :             int             f_protocol = 0;
    1806              :             char const *    f_name = nullptr;
    1807              :         };
    1808            1 :         protocol_name_t names[] = {
    1809              :             { 0, "ip" },
    1810              :             { 6, "tcp" },
    1811              :             { 17, "udp" },
    1812              :         };
    1813              : 
    1814            4 :         for(auto n : names)
    1815              :         {
    1816            3 :             a.set_protocol(n.f_protocol);
    1817            3 :             CATCH_REQUIRE(a.get_protocol_name() == n.f_name);
    1818              :         }
    1819              : 
    1820            4 :         for(auto n : names)
    1821              :         {
    1822            3 :             a.set_protocol(n.f_name);
    1823            3 :             CATCH_REQUIRE(a.get_protocol() == n.f_protocol);
    1824            3 :             CATCH_REQUIRE(a.get_protocol_name() == n.f_name);
    1825              :         }
    1826            1 :     }
    1827            5 :     CATCH_END_SECTION()
    1828              : 
    1829            5 :     CATCH_GIVEN("addr_parser() with IPv4 addresses and port")
    1830              :     {
    1831            3 :         CATCH_START_SECTION("ipv4::addr: verify port")
    1832              :         {
    1833        65537 :             for(int port(0); port < 65536; ++port)
    1834              :             {
    1835        65536 :                 int proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1836        65536 :                 addr::addr_parser p;
    1837        65536 :                 p.set_protocol(proto);
    1838        65536 :                 addr::addr_range::vector_t ips(p.parse("192.168.12.199:" + std::to_string(port)));
    1839        65536 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1840        65536 :                 CATCH_REQUIRE(ips.size() == 1);
    1841        65536 :                 addr::addr_range const & r(ips[0]);
    1842        65536 :                 addr::addr f(r.get_from());
    1843        65536 :                 CATCH_REQUIRE(f.is_ipv4());
    1844        65536 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1845        65536 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1846        65536 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "192.168.12.199");
    1847        65536 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "192.168.12.199");
    1848        65536 :                 CATCH_REQUIRE(f.get_port() == port);
    1849        65536 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    1850        65536 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    1851        65536 :                 CATCH_REQUIRE(f.is_lan());
    1852        65536 :                 CATCH_REQUIRE(f.is_lan(true));
    1853        65536 :                 CATCH_REQUIRE(f.is_lan(false));
    1854        65536 :                 CATCH_REQUIRE_FALSE(f.is_wan());
    1855        65536 :                 CATCH_REQUIRE_FALSE(f.is_wan(true));
    1856        65536 :                 CATCH_REQUIRE_FALSE(f.is_wan(false));
    1857        65536 :             }
    1858              :         }
    1859            3 :         CATCH_END_SECTION()
    1860              : 
    1861            3 :         CATCH_START_SECTION("ipv4::addr: default address with various port")
    1862              :         {
    1863          101 :             for(int idx(0); idx < 100; ++idx)
    1864              :             {
    1865          100 :                 uint16_t const port(rand());
    1866          100 :                 addr::addr_parser p;
    1867          100 :                 p.set_protocol(IPPROTO_TCP);
    1868          300 :                 p.set_default_address("5.5.5.5");
    1869          100 :                 CATCH_REQUIRE(p.get_default_address4() == "5.5.5.5");
    1870          100 :                 CATCH_REQUIRE(p.get_default_address6() == "");
    1871          100 :                 addr::addr_range::vector_t ips(p.parse(":" + std::to_string(static_cast<int>(port))));
    1872          100 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1873          100 :                 CATCH_REQUIRE(ips.size() == 1);
    1874          100 :                 addr::addr_range const & r(ips[0]);
    1875          100 :                 CATCH_REQUIRE(r.has_from());
    1876          100 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1877          100 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1878          100 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1879          100 :                 addr::addr f(r.get_from());
    1880          100 :                 CATCH_REQUIRE(f.is_ipv4());
    1881          100 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1882          100 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1883          100 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
    1884          100 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
    1885          100 :                 CATCH_REQUIRE(f.get_port() == port);
    1886          100 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1887          100 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1888          100 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1889          100 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1890          100 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1891          100 :                 CATCH_REQUIRE(f.is_wan());
    1892          100 :                 CATCH_REQUIRE(f.is_wan(true));
    1893          100 :                 CATCH_REQUIRE(f.is_wan(false));
    1894          100 :             }
    1895              :         }
    1896            3 :         CATCH_END_SECTION()
    1897              : 
    1898            3 :         CATCH_START_SECTION("ipv4::addr: address with default port")
    1899              :         {
    1900           26 :             for(int idx(0); idx < 25; ++idx)
    1901              :             {
    1902           25 :                 std::uint16_t const port(rand());
    1903           25 :                 addr::addr_parser p;
    1904           25 :                 p.set_protocol(IPPROTO_TCP);
    1905           25 :                 if((rand() & 1) == 0)
    1906              :                 {
    1907           11 :                     p.set_default_port(port);
    1908              :                 }
    1909              :                 else
    1910              :                 {
    1911           14 :                     std::string const port_str(std::to_string(static_cast<int>(port)));
    1912           14 :                     p.set_default_port(port_str);
    1913           14 :                 }
    1914           25 :                 CATCH_REQUIRE(p.get_default_port() == port);
    1915           75 :                 addr::addr_range::vector_t ips(p.parse("5.5.5.5"));
    1916           25 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1917           25 :                 CATCH_REQUIRE(ips.size() == 1);
    1918           25 :                 addr::addr_range const & r(ips[0]);
    1919           25 :                 CATCH_REQUIRE(r.has_from());
    1920           25 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1921           25 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1922           25 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1923           25 :                 addr::addr f(r.get_from());
    1924           25 :                 CATCH_REQUIRE(f.is_ipv4());
    1925           25 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1926           25 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1927           25 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
    1928           25 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
    1929           25 :                 CATCH_REQUIRE(f.get_port() == port);
    1930           25 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1931           25 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1932           25 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1933           25 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1934           25 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1935           25 :                 CATCH_REQUIRE(f.is_wan());
    1936           25 :                 CATCH_REQUIRE(f.is_wan(true));
    1937           25 :                 CATCH_REQUIRE(f.is_wan(false));
    1938           25 :             }
    1939              : 
    1940           26 :             for(int idx(0); idx < 25; ++idx)
    1941              :             {
    1942           25 :                 std::uint16_t const port(rand());
    1943           25 :                 addr::addr_parser p;
    1944           25 :                 p.set_protocol(IPPROTO_TCP);
    1945           25 :                 if((rand() & 1) == 0)
    1946              :                 {
    1947           13 :                     p.set_default_port(port);
    1948              :                 }
    1949              :                 else
    1950              :                 {
    1951           12 :                     std::string const port_str(std::to_string(static_cast<int>(port)));
    1952           12 :                     p.set_default_port(port_str);
    1953           12 :                 }
    1954           25 :                 CATCH_REQUIRE(p.get_default_port() == port);
    1955           75 :                 addr::addr_range::vector_t ips(p.parse("5.5.5.5:"));
    1956           25 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    1957           25 :                 CATCH_REQUIRE(ips.size() == 1);
    1958           25 :                 addr::addr_range const & r(ips[0]);
    1959           25 :                 CATCH_REQUIRE(r.has_from());
    1960           25 :                 CATCH_REQUIRE_FALSE(r.has_to());
    1961           25 :                 CATCH_REQUIRE_FALSE(r.is_range());
    1962           25 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    1963           25 :                 addr::addr f(r.get_from());
    1964           25 :                 CATCH_REQUIRE(f.is_ipv4());
    1965           25 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    1966           25 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    1967           25 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
    1968           25 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_BRACKET_ADDRESS | addr::STRING_IP_PORT) == "5.5.5.5:" + std::to_string(static_cast<int>(port)));
    1969           25 :                 CATCH_REQUIRE(f.get_port() == port);
    1970           25 :                 CATCH_REQUIRE(f.get_protocol() == IPPROTO_TCP);
    1971           25 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PUBLIC);
    1972           25 :                 CATCH_REQUIRE_FALSE(f.is_lan());
    1973           25 :                 CATCH_REQUIRE_FALSE(f.is_lan(true));
    1974           25 :                 CATCH_REQUIRE_FALSE(f.is_lan(false));
    1975           25 :                 CATCH_REQUIRE(f.is_wan());
    1976           25 :                 CATCH_REQUIRE(f.is_wan(true));
    1977           25 :                 CATCH_REQUIRE(f.is_wan(false));
    1978           25 :             }
    1979              :         }
    1980            3 :         CATCH_END_SECTION()
    1981            5 :     }
    1982            5 : }
    1983              : 
    1984              : 
    1985            9 : CATCH_TEST_CASE("ipv4::masks", "[ipv4]")
    1986              : {
    1987            9 :     CATCH_GIVEN("addr_parser() of address:port/mask")
    1988              :     {
    1989            9 :         CATCH_START_SECTION("ipv4::addr: mask allowed, but no mask")
    1990              :         {
    1991            1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    1992            1 :             int const port(rand() & 0xFFFF);
    1993            1 :             addr::addr_parser p;
    1994            1 :             p.set_protocol(proto);
    1995            1 :             p.set_allow(addr::allow_t::ALLOW_MASK, true);
    1996            1 :             addr::addr_range::vector_t ips(p.parse("172.19.6.91:" + std::to_string(port)));
    1997            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    1998            1 :             CATCH_REQUIRE(ips.size() == 1);
    1999            1 :             addr::addr_range const & r(ips[0]);
    2000            1 :             addr::addr f(r.get_from());
    2001            1 :             CATCH_REQUIRE(f.is_ipv4());
    2002            1 :             CATCH_REQUIRE(f.get_family() == AF_INET);
    2003            1 :             CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    2004            1 :             std::string result("172.19.6.91:" + std::to_string(port) + "/32");
    2005            1 :             CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ALL) == result);
    2006            1 :             CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ALL) == result);
    2007            1 :             CATCH_REQUIRE(f.get_port() == port);
    2008            1 :             CATCH_REQUIRE(f.get_protocol() == proto);
    2009            1 :             CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    2010            1 :             CATCH_REQUIRE(f.is_lan());
    2011            1 :             CATCH_REQUIRE(f.is_lan(true));
    2012            1 :             CATCH_REQUIRE(f.is_lan(false));
    2013            1 :             CATCH_REQUIRE_FALSE(f.is_wan());
    2014            1 :             CATCH_REQUIRE_FALSE(f.is_wan(true));
    2015            1 :             CATCH_REQUIRE_FALSE(f.is_wan(false));
    2016            1 :             CATCH_REQUIRE(f.get_mask_size() == 128);
    2017            1 :         }
    2018            9 :         CATCH_END_SECTION()
    2019              : 
    2020            9 :         CATCH_START_SECTION("ipv4::addr: empty mask")
    2021              :         {
    2022            1 :             int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    2023            1 :             int const port(rand() & 0xFFFF);
    2024            1 :             addr::addr_parser p;
    2025            1 :             p.set_protocol(proto);
    2026            1 :             p.set_allow(addr::allow_t::ALLOW_MASK, true);
    2027            1 :             addr::addr_range::vector_t ips(p.parse("172.18.5.91:" + std::to_string(port) + "/"));
    2028            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    2029            1 :             CATCH_REQUIRE(ips.size() == 1);
    2030            1 :             addr::addr_range const & r(ips[0]);
    2031            1 :             addr::addr f(r.get_from());
    2032            1 :             CATCH_REQUIRE(f.is_ipv4());
    2033            1 :             CATCH_REQUIRE(f.get_family() == AF_INET);
    2034            1 :             CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    2035            1 :             std::string result("172.18.5.91:" + std::to_string(port) + "/32");
    2036            1 :             CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ALL) == result);
    2037            1 :             CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ALL) == result);
    2038            1 :             CATCH_REQUIRE(f.get_port() == port);
    2039            1 :             CATCH_REQUIRE(f.get_protocol() == proto);
    2040            1 :             CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    2041            1 :             CATCH_REQUIRE(f.is_lan());
    2042            1 :             CATCH_REQUIRE(f.is_lan(true));
    2043            1 :             CATCH_REQUIRE(f.is_lan(false));
    2044            1 :             CATCH_REQUIRE_FALSE(f.is_wan());
    2045            1 :             CATCH_REQUIRE_FALSE(f.is_wan(true));
    2046            1 :             CATCH_REQUIRE_FALSE(f.is_wan(false));
    2047            1 :             CATCH_REQUIRE(f.get_mask_size() == 128);
    2048            1 :         }
    2049            9 :         CATCH_END_SECTION()
    2050              : 
    2051            9 :         CATCH_START_SECTION("ipv4::addr: one number masks")
    2052              :         {
    2053           34 :             for(int idx(0); idx <= 32; ++idx)
    2054              :             {
    2055           33 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    2056           33 :                 int const port(rand() & 0xFFFF);
    2057           33 :                 addr::addr_parser p;
    2058           33 :                 p.set_protocol(proto);
    2059           33 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
    2060           33 :                 addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port) + "/" + std::to_string(idx)));
    2061           33 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    2062           33 :                 CATCH_REQUIRE(ips.size() == 1);
    2063           33 :                 addr::addr_range const & r(ips[0]);
    2064           33 :                 addr::addr f(r.get_from());
    2065           33 :                 CATCH_REQUIRE(f.is_ipv4());
    2066           33 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    2067           33 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    2068              :                 //uint64_t const mask(std::numeric_limits<uint64_t>::max() << (32 - idx));
    2069              :                 //std::string mask_str(
    2070              :                 //          std::to_string((mask >> 24) & 255)
    2071              :                 //        + "."
    2072              :                 //        + std::to_string((mask >> 16) & 255)
    2073              :                 //        + "."
    2074              :                 //        + std::to_string((mask >>  8) & 255)
    2075              :                 //        + "."
    2076              :                 //        + std::to_string((mask >>  0) & 255));
    2077           33 :                 std::string result("172.17.3.91:" + std::to_string(port) + "/" + std::to_string(idx));
    2078           33 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ALL) == result);
    2079           33 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ALL) == result);
    2080           33 :                 CATCH_REQUIRE(f.get_port() == port);
    2081           33 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    2082           33 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    2083           33 :                 CATCH_REQUIRE(f.is_lan());
    2084           33 :                 CATCH_REQUIRE(f.is_lan(true));
    2085           33 :                 CATCH_REQUIRE(f.is_lan(false));
    2086           33 :                 CATCH_REQUIRE_FALSE(f.is_wan());
    2087           33 :                 CATCH_REQUIRE_FALSE(f.is_wan(true));
    2088           33 :                 CATCH_REQUIRE_FALSE(f.is_wan(false));
    2089           33 :                 CATCH_REQUIRE(f.get_mask_size() == 96 + idx);
    2090           33 :             }
    2091              :         }
    2092            9 :         CATCH_END_SECTION()
    2093              : 
    2094            9 :         CATCH_START_SECTION("ipv4::addr: address like mask")
    2095              :         {
    2096           26 :             for(int idx(0); idx < 25; ++idx)
    2097              :             {
    2098           25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    2099           25 :                 int const port(rand() & 0xFFFF);
    2100           25 :                 addr::addr_parser p;
    2101           25 :                 p.set_protocol(proto);
    2102           25 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
    2103           25 :                 p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
    2104              :                 // when specified as an IP, the mask can be absolutely anything
    2105           25 :                 uint8_t mask[4];
    2106              :                 do
    2107              :                 {
    2108          125 :                     for(int j(0); j < 4; ++j)
    2109              :                     {
    2110          100 :                         mask[j] = rand();
    2111              :                     }
    2112              :                 }
    2113           25 :                 while(mask[0] == 0      // make sure the mask is no just a number
    2114            0 :                    && mask[1] == 0
    2115            0 :                    && mask[2] == 0
    2116           25 :                    && mask[3] == 0);
    2117           25 :                 switch(mask[0])
    2118              :                 {
    2119            2 :                 case 0xFF:
    2120            2 :                     mask[0] &= ~(1 << (rand() & 7));
    2121            2 :                     break;
    2122              : 
    2123            0 :                 case 0xFE:
    2124              :                 case 0xFC:
    2125              :                 case 0xF8:
    2126              :                 case 0xF0:
    2127              :                 case 0xE0:
    2128              :                 case 0xC0:
    2129            0 :                     mask[0] &= 0x7F;
    2130            0 :                     break;
    2131              : 
    2132            1 :                 case 0x80:
    2133            1 :                     mask[0] |= 1 << (rand() % 6);
    2134            1 :                     break;
    2135              : 
    2136              :                 }
    2137           25 :                 std::string const mask_str(
    2138           50 :                               std::to_string(static_cast<int>(mask[0]))
    2139          100 :                             + "."
    2140          100 :                             + std::to_string(static_cast<int>(mask[1]))
    2141          100 :                             + "."
    2142          100 :                             + std::to_string(static_cast<int>(mask[2]))
    2143          100 :                             + "."
    2144          100 :                             + std::to_string(static_cast<int>(mask[3])));
    2145           50 :                 addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port) + "/" + mask_str));
    2146           25 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    2147           25 :                 CATCH_REQUIRE(ips.size() == 1);
    2148           25 :                 addr::addr_range const & r(ips[0]);
    2149           50 :                 addr::addr f(r.get_from());
    2150           25 :                 CATCH_REQUIRE(f.is_ipv4());
    2151           25 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    2152           25 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    2153           50 :                 std::string result("172.17.3.91:" + std::to_string(port) + "/" + mask_str);
    2154           25 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ALL) == result);
    2155           25 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ALL) == result);
    2156           25 :                 CATCH_REQUIRE(f.get_port() == port);
    2157           25 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    2158           25 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    2159           25 :                 CATCH_REQUIRE(f.is_lan());
    2160           25 :                 CATCH_REQUIRE(f.is_lan(true));
    2161           25 :                 CATCH_REQUIRE(f.is_lan(false));
    2162           25 :                 CATCH_REQUIRE_FALSE(f.is_wan());
    2163           25 :                 CATCH_REQUIRE_FALSE(f.is_wan(true));
    2164           25 :                 CATCH_REQUIRE_FALSE(f.is_wan(false));
    2165              : 
    2166              :                 // above we made sure that the mask was not just a number so
    2167              :                 // here we should always get -1
    2168              :                 //
    2169           25 :                 CATCH_REQUIRE(f.get_mask_size() == -1);
    2170           25 :             }
    2171              :         }
    2172            9 :         CATCH_END_SECTION()
    2173              : 
    2174            9 :         CATCH_START_SECTION("ipv4::addr: address like mask when not allowed")
    2175              :         {
    2176           26 :             for(int idx(0); idx < 25; ++idx)
    2177              :             {
    2178           25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    2179           25 :                 int const port(rand() & 0xFFFF);
    2180           25 :                 addr::addr_parser p;
    2181           25 :                 p.set_protocol(proto);
    2182           25 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
    2183           25 :                 p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, false);
    2184              :                 // when specified as an IP, the mask can be absolutely anything
    2185           25 :                 uint8_t mask[4];
    2186              :                 do
    2187              :                 {
    2188          125 :                     for(int j(0); j < 4; ++j)
    2189              :                     {
    2190          100 :                         mask[j] = rand();
    2191              :                     }
    2192              :                 }
    2193           25 :                 while(mask[0] == 0      // make sure the mask is no just a number
    2194            0 :                    && mask[1] == 0
    2195            0 :                    && mask[2] == 0
    2196           25 :                    && mask[3] == 0);
    2197           25 :                 switch(mask[0])
    2198              :                 {
    2199            0 :                 case 0xFF:
    2200            0 :                     mask[0] &= ~(1 << (rand() & 7));
    2201            0 :                     break;
    2202              : 
    2203            0 :                 case 0xFE:
    2204              :                 case 0xFC:
    2205              :                 case 0xF8:
    2206              :                 case 0xF0:
    2207              :                 case 0xE0:
    2208              :                 case 0xC0:
    2209            0 :                     mask[0] &= 0x7F;
    2210            0 :                     break;
    2211              : 
    2212            1 :                 case 0x80:
    2213            1 :                     mask[0] |= 1 << (rand() % 6);
    2214            1 :                     break;
    2215              : 
    2216              :                 }
    2217           25 :                 std::string const mask_str(
    2218           50 :                               std::to_string(static_cast<int>(mask[0]))
    2219          100 :                             + "."
    2220          100 :                             + std::to_string(static_cast<int>(mask[1]))
    2221          100 :                             + "."
    2222          100 :                             + std::to_string(static_cast<int>(mask[2]))
    2223          100 :                             + "."
    2224          100 :                             + std::to_string(static_cast<int>(mask[3])));
    2225           50 :                 addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port) + "/" + mask_str));
    2226           25 :                 CATCH_REQUIRE(p.has_errors());
    2227           25 :                 CATCH_REQUIRE(ips.size() == 0);
    2228           25 :             }
    2229              :         }
    2230            9 :         CATCH_END_SECTION()
    2231              : 
    2232            9 :         CATCH_START_SECTION("ipv4::addr: address like default mask")
    2233              :         {
    2234           26 :             for(int idx(0); idx < 25; ++idx)
    2235              :             {
    2236           25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    2237           25 :                 int const port(rand() & 0xFFFF);
    2238           25 :                 addr::addr_parser p;
    2239           25 :                 p.set_protocol(proto);
    2240           25 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
    2241           25 :                 p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
    2242              :                 // when specified as an IP, the mask can be absolutely anything
    2243              :                 // (here the mask is a string an it will be parsed by the
    2244              :                 // parser if required)
    2245              :                 //
    2246           25 :                 uint8_t mask[4];
    2247          125 :                 for(int j(0); j < 4; ++j)
    2248              :                 {
    2249          100 :                     mask[j] = rand();
    2250              :                 }
    2251           25 :                 std::string const mask_str(
    2252           50 :                               std::to_string(static_cast<int>(mask[0]))
    2253          100 :                             + "."
    2254          100 :                             + std::to_string(static_cast<int>(mask[1]))
    2255          100 :                             + "."
    2256          100 :                             + std::to_string(static_cast<int>(mask[2]))
    2257          100 :                             + "."
    2258           75 :                             + std::to_string(static_cast<int>(mask[3])));
    2259           25 :                 p.set_default_mask(mask_str);
    2260           25 :                 addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port)));
    2261           25 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    2262           25 :                 CATCH_REQUIRE(ips.size() == 1);
    2263           25 :                 addr::addr_range const & r(ips[0]);
    2264           25 :                 addr::addr f(r.get_from());
    2265           25 :                 CATCH_REQUIRE(f.is_ipv4());
    2266           25 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    2267           25 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    2268           25 :                 std::string result("172.17.3.91:" + std::to_string(port) + "/" + mask_str);
    2269           25 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ALL) == result);
    2270           25 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ALL) == result);
    2271           25 :                 CATCH_REQUIRE(f.get_port() == port);
    2272           25 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    2273           25 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    2274           25 :                 CATCH_REQUIRE(f.is_lan());
    2275           25 :                 CATCH_REQUIRE(f.is_lan(true));
    2276           25 :                 CATCH_REQUIRE(f.is_lan(false));
    2277           25 :                 CATCH_REQUIRE_FALSE(f.is_wan());
    2278           25 :                 CATCH_REQUIRE_FALSE(f.is_wan(true));
    2279           25 :                 CATCH_REQUIRE_FALSE(f.is_wan(false));
    2280           25 :                 uint8_t verify_mask[16];
    2281           25 :                 f.get_mask(verify_mask);
    2282          325 :                 for(int j(0); j < 16 - 4; ++j)
    2283              :                 {
    2284          300 :                     CATCH_REQUIRE(verify_mask[j] == 255);
    2285              :                 }
    2286          125 :                 for(int j(12); j < 16; ++j)
    2287              :                 {
    2288          100 :                     CATCH_REQUIRE(verify_mask[j] == mask[j - 12]);
    2289              :                 }
    2290           25 :             }
    2291              :         }
    2292            9 :         CATCH_END_SECTION()
    2293              : 
    2294            9 :         CATCH_START_SECTION("ipv4::addr: address like mask with a default")
    2295              :         {
    2296           26 :             for(int idx(0); idx < 25; ++idx)
    2297              :             {
    2298           25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    2299           25 :                 int const port(rand() & 0xFFFF);
    2300           25 :                 addr::addr_parser p;
    2301           25 :                 p.set_protocol(proto);
    2302           25 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
    2303           25 :                 p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true);
    2304              : 
    2305              :                 // here we want a default and an IP with a specific mask
    2306              :                 // to make sure that the specific mask has priority
    2307              :                 //
    2308           25 :                 uint8_t mask[4];
    2309          125 :                 for(int j(0); j < 4; ++j)
    2310              :                 {
    2311          100 :                     mask[j] = rand();
    2312              :                 }
    2313           25 :                 std::string const mask_str(
    2314           50 :                               std::to_string(static_cast<int>(mask[0]))
    2315          100 :                             + "."
    2316          100 :                             + std::to_string(static_cast<int>(mask[1]))
    2317          100 :                             + "."
    2318          100 :                             + std::to_string(static_cast<int>(mask[2]))
    2319          100 :                             + "."
    2320           75 :                             + std::to_string(static_cast<int>(mask[3])));
    2321              : 
    2322           25 :                 uint8_t default_mask[4];
    2323          125 :                 for(int j(0); j < 4; ++j)
    2324              :                 {
    2325          100 :                     default_mask[j] = rand();
    2326              :                 }
    2327           25 :                 std::string const default_mask_str(
    2328           50 :                               std::to_string(static_cast<int>(default_mask[0]))
    2329          100 :                             + "."
    2330          100 :                             + std::to_string(static_cast<int>(default_mask[1]))
    2331          100 :                             + "."
    2332          100 :                             + std::to_string(static_cast<int>(default_mask[2]))
    2333          100 :                             + "."
    2334           75 :                             + std::to_string(static_cast<int>(default_mask[3])));
    2335           25 :                 p.set_default_mask(default_mask_str);
    2336              : 
    2337           25 :                 addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port) + "/" + mask_str));
    2338           25 :                 CATCH_REQUIRE_FALSE(p.has_errors());
    2339           25 :                 CATCH_REQUIRE(ips.size() == 1);
    2340           25 :                 addr::addr_range const & r(ips[0]);
    2341           25 :                 addr::addr f(r.get_from());
    2342           25 :                 CATCH_REQUIRE(f.is_ipv4());
    2343           25 :                 CATCH_REQUIRE(f.get_family() == AF_INET);
    2344           25 :                 CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    2345           25 :                 std::string result("172.17.3.91:" + std::to_string(port) + "/" + mask_str);
    2346           25 :                 CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ALL) == result);
    2347           25 :                 CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ALL) == result);
    2348           25 :                 CATCH_REQUIRE(f.get_port() == port);
    2349           25 :                 CATCH_REQUIRE(f.get_protocol() == proto);
    2350           25 :                 CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    2351           25 :                 CATCH_REQUIRE(f.is_lan());
    2352           25 :                 CATCH_REQUIRE(f.is_lan(true));
    2353           25 :                 CATCH_REQUIRE(f.is_lan(false));
    2354           25 :                 CATCH_REQUIRE_FALSE(f.is_wan());
    2355           25 :                 CATCH_REQUIRE_FALSE(f.is_wan(true));
    2356           25 :                 CATCH_REQUIRE_FALSE(f.is_wan(false));
    2357           25 :                 uint8_t verify_mask[16];
    2358           25 :                 f.get_mask(verify_mask);
    2359          325 :                 for(int j(0); j < 16 - 4; ++j)
    2360              :                 {
    2361          300 :                     CATCH_REQUIRE(verify_mask[j] == 255);
    2362              :                 }
    2363          125 :                 for(int j(12); j < 16; ++j)
    2364              :                 {
    2365          100 :                     CATCH_REQUIRE(verify_mask[j] == mask[j - 12]);
    2366              :                 }
    2367           25 :             }
    2368              :         }
    2369            9 :         CATCH_END_SECTION()
    2370              : 
    2371            9 :         CATCH_START_SECTION("ipv4::addr: address like default mask")
    2372              :         {
    2373           26 :             for(int idx(0); idx < 25; ++idx)
    2374              :             {
    2375           25 :                 int const proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    2376           25 :                 int const port(rand() & 0xFFFF);
    2377           25 :                 addr::addr_parser p;
    2378           25 :                 p.set_protocol(proto);
    2379           25 :                 p.set_allow(addr::allow_t::ALLOW_MASK, true);
    2380              : 
    2381              :                 //p.set_allow(addr::allow_t::ALLOW_ADDRESS_MASK, true); -- if we forget this one, the parsing fails with an error
    2382              : 
    2383              :                 // when specified as an IP, the mask can be absolutely anything
    2384              :                 // (here the mask is a string an it will be parsed by the
    2385              :                 // parser if required)
    2386              :                 //
    2387           25 :                 uint8_t mask[4];
    2388          125 :                 for(int j(0); j < 4; ++j)
    2389              :                 {
    2390          100 :                     mask[j] = rand();
    2391              :                 }
    2392           25 :                 std::string const mask_str(
    2393           50 :                               std::to_string(static_cast<int>(mask[0]))
    2394          100 :                             + "."
    2395          100 :                             + std::to_string(static_cast<int>(mask[1]))
    2396          100 :                             + "."
    2397          100 :                             + std::to_string(static_cast<int>(mask[2]))
    2398          100 :                             + "."
    2399           75 :                             + std::to_string(static_cast<int>(mask[3])));
    2400           25 :                 p.set_default_mask(mask_str);
    2401           25 :                 addr::addr_range::vector_t ips(p.parse("172.17.3.91:" + std::to_string(port)));
    2402           25 :                 CATCH_REQUIRE(p.has_errors());
    2403           25 :                 CATCH_REQUIRE(ips.size() == 0);
    2404           25 :             }
    2405              :         }
    2406            9 :         CATCH_END_SECTION()
    2407              : 
    2408            9 :         CATCH_START_SECTION("ipv4::addr: two addresses and a mask for a match / no match")
    2409              :         {
    2410            1 :             int const port1(rand() & 0xFFFF);
    2411            1 :             addr::addr_parser p;
    2412            1 :             p.set_allow(addr::allow_t::ALLOW_MASK, true);
    2413              : 
    2414              :             // parse the IP with a mask
    2415              :             //
    2416            1 :             int proto(rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP);
    2417            1 :             p.set_protocol(proto);
    2418            1 :             addr::addr_range::vector_t ips1(p.parse("192.168.0.0:" + std::to_string(port1) + "/16"));
    2419            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    2420            1 :             CATCH_REQUIRE(ips1.size() == 1);
    2421            1 :             addr::addr_range const & r1(ips1[0]);
    2422            1 :             addr::addr f1(r1.get_from());
    2423            1 :             CATCH_REQUIRE(f1.is_ipv4());
    2424            1 :             CATCH_REQUIRE(f1.get_family() == AF_INET);
    2425            1 :             CATCH_REQUIRE_FALSE(f1.get_family() == AF_INET6);
    2426            1 :             CATCH_REQUIRE(f1.to_ipv4_string(addr::STRING_IP_ALL) == "192.168.0.0:" + std::to_string(port1) + "/16");
    2427            1 :             CATCH_REQUIRE(f1.to_ipv4or6_string(addr::STRING_IP_ALL) == "192.168.0.0:" + std::to_string(port1) + "/16");
    2428            1 :             CATCH_REQUIRE(f1.get_port() == port1);
    2429            1 :             CATCH_REQUIRE(f1.get_protocol() == proto);
    2430            1 :             CATCH_REQUIRE(f1.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    2431            1 :             CATCH_REQUIRE(f1.is_lan());
    2432            1 :             CATCH_REQUIRE(f1.is_lan(true));
    2433            1 :             CATCH_REQUIRE(f1.is_lan(false));
    2434            1 :             CATCH_REQUIRE_FALSE(f1.is_wan());
    2435            1 :             CATCH_REQUIRE_FALSE(f1.is_wan(true));
    2436            1 :             CATCH_REQUIRE_FALSE(f1.is_wan(false));
    2437              : 
    2438              :             // reuse parser
    2439              :             //
    2440            1 :             proto = rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP;
    2441            1 :             p.set_protocol(proto);
    2442            1 :             int const port2(rand() & 0xFFFF);
    2443            1 :             addr::addr_range::vector_t ips2(p.parse("192.168.5.36:" + std::to_string(port2)));
    2444            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    2445            1 :             CATCH_REQUIRE(ips2.size() == 1);
    2446            1 :             addr::addr_range const & r2(ips2[0]);
    2447            1 :             addr::addr f2(r2.get_from());
    2448            1 :             CATCH_REQUIRE(f2.is_ipv4());
    2449            1 :             CATCH_REQUIRE(f2.get_family() == AF_INET);
    2450            1 :             CATCH_REQUIRE_FALSE(f2.get_family() == AF_INET6);
    2451            1 :             CATCH_REQUIRE(f2.to_ipv4_string(addr::STRING_IP_ALL) == "192.168.5.36:" + std::to_string(port2) + "/32");
    2452            1 :             CATCH_REQUIRE(f2.to_ipv4or6_string(addr::STRING_IP_ALL) == "192.168.5.36:" + std::to_string(port2) + "/32");
    2453            1 :             CATCH_REQUIRE(f2.get_port() == port2);
    2454            1 :             CATCH_REQUIRE(f2.get_protocol() == proto);
    2455            1 :             CATCH_REQUIRE(f2.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    2456            1 :             CATCH_REQUIRE(f2.is_lan());
    2457            1 :             CATCH_REQUIRE(f2.is_lan(true));
    2458            1 :             CATCH_REQUIRE(f2.is_lan(false));
    2459            1 :             CATCH_REQUIRE_FALSE(f2.is_wan());
    2460            1 :             CATCH_REQUIRE_FALSE(f2.is_wan(true));
    2461            1 :             CATCH_REQUIRE_FALSE(f2.is_wan(false));
    2462              : 
    2463              :             // 3rd with a mask along the full IP
    2464              :             //
    2465            1 :             proto = rand() & 1 ? IPPROTO_TCP : IPPROTO_UDP;
    2466            1 :             p.set_protocol(proto);
    2467            1 :             int const port3(rand() & 0xFFFF);
    2468            1 :             addr::addr_range::vector_t ips3(p.parse("192.168.5.36:" + std::to_string(port3) + "/16"));
    2469            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    2470            1 :             CATCH_REQUIRE(ips3.size() == 1);
    2471            1 :             addr::addr_range const & r3(ips3[0]);
    2472            1 :             addr::addr f3(r3.get_from());
    2473            1 :             CATCH_REQUIRE(f3.is_ipv4());
    2474            1 :             CATCH_REQUIRE(f3.get_family() == AF_INET);
    2475            1 :             CATCH_REQUIRE_FALSE(f3.get_family() == AF_INET6);
    2476            1 :             CATCH_REQUIRE(f3.to_ipv4_string(addr::STRING_IP_ALL) == "192.168.5.36:" + std::to_string(port3) + "/16");
    2477            1 :             CATCH_REQUIRE(f3.to_ipv4or6_string(addr::STRING_IP_ALL) == "192.168.5.36:" + std::to_string(port3) + "/16");
    2478            1 :             CATCH_REQUIRE(f3.get_port() == port3);
    2479            1 :             CATCH_REQUIRE(f3.get_protocol() == proto);
    2480            1 :             CATCH_REQUIRE(f3.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    2481            1 :             CATCH_REQUIRE(f3.is_lan());
    2482            1 :             CATCH_REQUIRE(f3.is_lan(true));
    2483            1 :             CATCH_REQUIRE(f3.is_lan(false));
    2484            1 :             CATCH_REQUIRE_FALSE(f3.is_wan());
    2485            1 :             CATCH_REQUIRE_FALSE(f3.is_wan(true));
    2486            1 :             CATCH_REQUIRE_FALSE(f3.is_wan(false));
    2487              : 
    2488              :             // just a side test
    2489              :             //
    2490            1 :             CATCH_REQUIRE(f1 != f2);
    2491            1 :             CATCH_REQUIRE(f1 != f3);
    2492            1 :             CATCH_REQUIRE(f2 == f3);
    2493              : 
    2494              :             // check whether p1 matches p2 and vice versa
    2495              :             //
    2496            1 :             CATCH_REQUIRE(f1.match(f2));          // f2 & mask1 == f1 & mask1
    2497            1 :             CATCH_REQUIRE(f1.match(f3));          // f3 & mask1 == f1 & mask1
    2498              : 
    2499            1 :             CATCH_REQUIRE_FALSE(f2.match(f1));    // f1 & mask2 != f2 & mask2
    2500            1 :             CATCH_REQUIRE(f2.match(f3));          // f3 & mask2 == f2 & mask2  (because f2 == f3 anyway)
    2501              : 
    2502            1 :             CATCH_REQUIRE(f3.match(f1));          // f1 & mask3 == f3 & mask3
    2503            1 :             CATCH_REQUIRE(f3.match(f2));          // f2 & mask3 == f3 & mask3
    2504              : 
    2505            1 :             f3.apply_mask();
    2506              : 
    2507            1 :             CATCH_REQUIRE(f1 != f2);
    2508            1 :             CATCH_REQUIRE(f1 == f3);
    2509            1 :             CATCH_REQUIRE(f2 != f3);
    2510              : 
    2511              :             // re-run the match() calls with f3 since it changed...
    2512              :             //
    2513            1 :             CATCH_REQUIRE(f1.match(f3));          // f3 & mask1 == f1 & mask1
    2514              : 
    2515            1 :             CATCH_REQUIRE_FALSE(f2.match(f3));    // f3 & mask2 == f2 & mask2  (because f2 != f3 anymore)
    2516              : 
    2517            1 :             CATCH_REQUIRE(f3.match(f1));          // f1 & mask3 == f3 & mask3
    2518            1 :             CATCH_REQUIRE(f3.match(f2));          // f2 & mask3 == f3 & mask3
    2519              : 
    2520            1 :             addr::addr fa; // by default an address is ANY and it matches everything
    2521            1 :             CATCH_REQUIRE(fa.match(f1, true));
    2522            1 :             CATCH_REQUIRE(fa.match(f2, true));
    2523            1 :             CATCH_REQUIRE(fa.match(f3, true));
    2524            1 :             std::uint8_t const verify_match[16] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };
    2525            1 :             std::uint8_t any_mask[16] = {};
    2526            1 :             fa.get_mask(any_mask);
    2527            1 :             CATCH_REQUIRE(memcmp(verify_match, any_mask, 16) == 0);
    2528            1 :         }
    2529            9 :         CATCH_END_SECTION()
    2530            9 :     }
    2531            9 : }
    2532              : 
    2533              : 
    2534            6 : CATCH_TEST_CASE("ipv4::protocol", "[ipv4]")
    2535              : {
    2536            6 :     CATCH_GIVEN("addr()")
    2537              :     {
    2538            2 :         addr::addr a;
    2539              : 
    2540            2 :         CATCH_START_SECTION("ipv4::addr: default protocol")
    2541              :         {
    2542            1 :             CATCH_REQUIRE(a.get_protocol() == IPPROTO_TCP);
    2543              :         }
    2544            2 :         CATCH_END_SECTION()
    2545              : 
    2546            2 :         CATCH_START_SECTION("ipv4::addr: set_protocol()")
    2547              :         {
    2548              :             // setup a random protocol
    2549              :             //
    2550            2 :             int const start_protocol([]()
    2551              :                 {
    2552            1 :                     switch(rand() % 3)
    2553              :                     {
    2554            1 :                     case 0:
    2555            1 :                         return IPPROTO_IP;
    2556              : 
    2557            0 :                     case 1:
    2558            0 :                         return IPPROTO_TCP;
    2559              : 
    2560              :                     //case 2:
    2561            0 :                     default:
    2562            0 :                         return IPPROTO_UDP;
    2563              : 
    2564              :                     }
    2565            1 :                 }());
    2566            1 :             a.set_protocol(start_protocol);
    2567              : 
    2568              :             // test 100 invalid protocols
    2569              :             //
    2570          101 :             for(int idx(0); idx < 100; ++idx)
    2571              :             {
    2572              :                 int invalid_protocol;
    2573              :                 do
    2574              :                 {
    2575          100 :                     invalid_protocol = rand();
    2576              :                 }
    2577              :                 while(invalid_protocol == IPPROTO_IP
    2578          100 :                    || invalid_protocol == IPPROTO_TCP
    2579          200 :                    || invalid_protocol == IPPROTO_UDP);
    2580          100 :                 CATCH_REQUIRE_THROWS_AS(a.set_protocol(invalid_protocol), addr::addr_invalid_argument);
    2581              : 
    2582              :                 // make sure the protocol does not change on errors
    2583          100 :                 CATCH_REQUIRE(a.get_protocol() == start_protocol);
    2584              :             }
    2585              : 
    2586              :             // null string is not allowed
    2587              :             //
    2588            1 :             CATCH_REQUIRE_THROWS_AS(a.set_protocol(nullptr), addr::addr_invalid_argument);
    2589              : 
    2590              :             // other "invalid" (unsupported, really) string protocols
    2591              :             //
    2592            1 :             CATCH_REQUIRE_THROWS_AS(a.set_protocol("unknown"), addr::addr_invalid_argument);
    2593            1 :             CATCH_REQUIRE_THROWS_AS(a.set_protocol("invalid"), addr::addr_invalid_argument);
    2594            1 :             CATCH_REQUIRE_THROWS_AS(a.set_protocol("other"), addr::addr_invalid_argument);
    2595              : 
    2596              :             // test all valid protocols (numeric)
    2597              :             //
    2598            1 :             a.set_protocol(IPPROTO_IP);
    2599            1 :             CATCH_REQUIRE(a.get_protocol() == IPPROTO_IP);
    2600            1 :             a.set_protocol(IPPROTO_TCP);
    2601            1 :             CATCH_REQUIRE(a.get_protocol() == IPPROTO_TCP);
    2602            1 :             a.set_protocol(IPPROTO_UDP);
    2603            1 :             CATCH_REQUIRE(a.get_protocol() == IPPROTO_UDP);
    2604              : 
    2605              :             // test all valid protocols (ascii)
    2606              :             //
    2607            1 :             a.set_protocol("ip");
    2608            1 :             CATCH_REQUIRE(a.get_protocol() == IPPROTO_IP);
    2609            1 :             a.set_protocol("tcp");
    2610            1 :             CATCH_REQUIRE(a.get_protocol() == IPPROTO_TCP);
    2611            1 :             a.set_protocol("udp");
    2612            1 :             CATCH_REQUIRE(a.get_protocol() == IPPROTO_UDP);
    2613              :         }
    2614            2 :         CATCH_END_SECTION()
    2615            8 :     }
    2616              : 
    2617            6 :     CATCH_GIVEN("addr_parser()")
    2618              :     {
    2619            3 :         addr::addr_parser p;
    2620              : 
    2621            3 :         CATCH_START_SECTION("ipv4::addr: verify default")
    2622              :         {
    2623            1 :             CATCH_REQUIRE(p.get_protocol() == -1);
    2624              :         }
    2625            3 :         CATCH_END_SECTION()
    2626              : 
    2627            3 :         CATCH_START_SECTION("ipv4::addr: test 3 allowed protocols")
    2628              :         {
    2629              :             // by string
    2630              :             //
    2631            3 :             p.set_protocol("ip");
    2632            1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_IP);
    2633            3 :             p.set_protocol("tcp");
    2634            1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_TCP);
    2635            3 :             p.set_protocol("udp");
    2636            1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_UDP);
    2637              : 
    2638              :             // numerically
    2639              :             //
    2640            1 :             p.set_protocol(IPPROTO_IP);
    2641            1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_IP);
    2642            1 :             p.set_protocol(IPPROTO_TCP);
    2643            1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_TCP);
    2644            1 :             p.set_protocol(IPPROTO_UDP);
    2645            1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_UDP);
    2646              :         }
    2647            3 :         CATCH_END_SECTION()
    2648              : 
    2649            3 :         CATCH_START_SECTION("ipv4::addr: verify clearing works")
    2650              :         {
    2651            3 :             p.set_protocol("ip");
    2652            1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_IP);
    2653            1 :             p.clear_protocol();
    2654            1 :             CATCH_REQUIRE(p.get_protocol() == -1);
    2655              : 
    2656            3 :             p.set_protocol("tcp");
    2657            1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_TCP);
    2658            1 :             p.clear_protocol();
    2659            1 :             CATCH_REQUIRE(p.get_protocol() == -1);
    2660              : 
    2661            3 :             p.set_protocol("udp");
    2662            1 :             CATCH_REQUIRE(p.get_protocol() == IPPROTO_UDP);
    2663            1 :             p.clear_protocol();
    2664            1 :             CATCH_REQUIRE(p.get_protocol() == -1);
    2665              :         }
    2666            3 :         CATCH_END_SECTION()
    2667            9 :     }
    2668              : 
    2669            6 :     CATCH_GIVEN("addr_parser with any protocol")
    2670              :     {
    2671            1 :         addr::addr a;
    2672              : 
    2673            1 :         CATCH_START_SECTION("ipv4::addr: get address with all protocols")
    2674              :         {
    2675            1 :             addr::addr_parser p;
    2676              :             //p.set_protocol(...); -- by default we'll get all the protocols supported
    2677            3 :             addr::addr_range::vector_t ips(p.parse("127.0.0.1"));
    2678            1 :             CATCH_REQUIRE_FALSE(p.has_errors());
    2679            1 :             CATCH_REQUIRE(!ips.empty());
    2680            4 :             for(size_t idx(0); idx < ips.size(); ++idx)
    2681              :             {
    2682            3 :                 addr::addr_range const & r(ips[idx]);
    2683            3 :                 CATCH_REQUIRE(r.has_from());
    2684            3 :                 CATCH_REQUIRE_FALSE(r.has_to());
    2685            3 :                 CATCH_REQUIRE_FALSE(r.is_range());
    2686            3 :                 CATCH_REQUIRE_FALSE(r.is_empty());
    2687            3 :                 addr::addr f(r.get_from());
    2688            3 :                 if(f.is_ipv4())
    2689              :                 {
    2690            3 :                     CATCH_REQUIRE(f.get_family() == AF_INET);
    2691            3 :                     CATCH_REQUIRE_FALSE(f.get_family() == AF_INET6);
    2692            3 :                     CATCH_REQUIRE(f.to_ipv4_string(addr::STRING_IP_ADDRESS) == "127.0.0.1");
    2693            3 :                     CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "127.0.0.1");
    2694            3 :                     CATCH_REQUIRE(f.get_port() == 0);
    2695              :                     //CATCH_REQUIRE(f.get_protocol() == ...); -- may be TCP, UDP, IP
    2696            3 :                     CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_LOOPBACK);
    2697            3 :                     CATCH_REQUIRE(f.is_lan());
    2698            3 :                     CATCH_REQUIRE(f.is_lan(true));
    2699            3 :                     CATCH_REQUIRE(f.is_lan(false));
    2700            3 :                     CATCH_REQUIRE_FALSE(f.is_wan());
    2701            3 :                     CATCH_REQUIRE_FALSE(f.is_wan(true));
    2702            3 :                     CATCH_REQUIRE_FALSE(f.is_wan(false));
    2703              :                 }
    2704              :                 else
    2705              :                 {
    2706            0 :                     CATCH_REQUIRE_FALSE(f.get_family() == AF_INET);
    2707            0 :                     CATCH_REQUIRE(f.get_family() == AF_INET6);
    2708            0 :                     CATCH_REQUIRE(f.to_ipv6_string(addr::STRING_IP_ADDRESS) == "::1");
    2709            0 :                     CATCH_REQUIRE(f.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "::1");
    2710            0 :                     CATCH_REQUIRE(f.get_port() == 0);
    2711              :                     //CATCH_REQUIRE(f.get_protocol() == ...); -- may be TCP, UDP, IP
    2712            0 :                     CATCH_REQUIRE(f.get_network_type() == addr::network_type_t::NETWORK_TYPE_LOOPBACK);
    2713            0 :                     CATCH_REQUIRE(f.is_lan());
    2714            0 :                     CATCH_REQUIRE(f.is_lan(true));
    2715            0 :                     CATCH_REQUIRE(f.is_lan(false));
    2716            0 :                     CATCH_REQUIRE_FALSE(f.is_wan());
    2717            0 :                     CATCH_REQUIRE_FALSE(f.is_wan(true));
    2718            0 :                     CATCH_REQUIRE_FALSE(f.is_wan(false));
    2719              :                 }
    2720            3 :             }
    2721            1 :         }
    2722            1 :         CATCH_END_SECTION()
    2723            7 :     }
    2724            6 : }
    2725              : 
    2726              : 
    2727            8 : CATCH_TEST_CASE("ipv4::network_type", "[ipv4]")
    2728              : {
    2729            8 :     CATCH_GIVEN("addr()")
    2730              :     {
    2731            8 :         addr::addr a;
    2732              : 
    2733            8 :         CATCH_START_SECTION("ipv4::addr: any (0.0.0.0)")
    2734              :         {
    2735            1 :             struct sockaddr_in in = sockaddr_in();
    2736            1 :             in.sin_family = AF_INET;
    2737            1 :             in.sin_port = htons(rand());
    2738            1 :             in.sin_addr.s_addr = 0;
    2739              : 
    2740              :             // verify network type
    2741              :             //
    2742            1 :             a.set_ipv4(in);
    2743              : 
    2744            1 :             CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_ANY);
    2745            3 :             CATCH_REQUIRE(std::string(a.get_network_type_string()) == "Any");
    2746            1 :             CATCH_REQUIRE_FALSE(a.is_lan());
    2747            1 :             CATCH_REQUIRE_FALSE(a.is_lan(true));
    2748            1 :             CATCH_REQUIRE_FALSE(a.is_lan(false));
    2749            1 :             CATCH_REQUIRE(a.is_wan());
    2750            1 :             CATCH_REQUIRE(a.is_wan(true));
    2751            1 :             CATCH_REQUIRE_FALSE(a.is_wan(false));
    2752              :         }
    2753            8 :         CATCH_END_SECTION()
    2754              : 
    2755            8 :         CATCH_START_SECTION("ipv4::addr: private address 10.x.x.x/8")
    2756              :         {
    2757           11 :             for(int idx(0); idx < 10; ++idx)
    2758              :             {
    2759           10 :                 struct sockaddr_in in = sockaddr_in();
    2760           10 :                 in.sin_family = AF_INET;
    2761           10 :                 in.sin_port = htons(rand());
    2762              :                 uint32_t address((10 << 24)
    2763           10 :                               | ((rand() & 255) << 16)
    2764           10 :                               | ((rand() & 255) << 8)
    2765           10 :                               | ((rand() & 255) << 0));
    2766           10 :                 in.sin_addr.s_addr = htonl(address);
    2767              : 
    2768              :                 // verify network type
    2769              :                 //
    2770           10 :                 a.set_ipv4(in);
    2771           10 :                 CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    2772           30 :                 CATCH_REQUIRE(std::string(a.get_network_type_string()) == "Private");
    2773           10 :                 CATCH_REQUIRE(a.is_lan());
    2774           10 :                 CATCH_REQUIRE(a.is_lan(true));
    2775           10 :                 CATCH_REQUIRE(a.is_lan(false));
    2776           10 :                 CATCH_REQUIRE_FALSE(a.is_wan());
    2777           10 :                 CATCH_REQUIRE_FALSE(a.is_wan(true));
    2778           10 :                 CATCH_REQUIRE_FALSE(a.is_wan(false));
    2779              :             }
    2780              :         }
    2781            8 :         CATCH_END_SECTION()
    2782              : 
    2783            8 :         CATCH_START_SECTION("ipv4::addr: private address 172.16.x.x/12")
    2784              :         {
    2785           11 :             for(int idx(0); idx < 10; ++idx)
    2786              :             {
    2787           10 :                 struct sockaddr_in in = sockaddr_in();
    2788           10 :                 in.sin_family = AF_INET;
    2789           10 :                 in.sin_port = htons(rand());
    2790              :                 uint32_t address((172 << 24)
    2791           10 :                               | (((rand() & 15) | 16) << 16)
    2792           10 :                               | ((rand() & 255) << 8)
    2793           10 :                               | ((rand() & 255) << 0));
    2794           10 :                 in.sin_addr.s_addr = htonl(address);
    2795              : 
    2796              :                 // verify network type
    2797              :                 //
    2798           10 :                 a.set_ipv4(in);
    2799           10 :                 CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    2800           30 :                 CATCH_REQUIRE(std::string(a.get_network_type_string()) == "Private");
    2801           10 :                 CATCH_REQUIRE(a.is_lan());
    2802           10 :                 CATCH_REQUIRE(a.is_lan(true));
    2803           10 :                 CATCH_REQUIRE(a.is_lan(false));
    2804           10 :                 CATCH_REQUIRE_FALSE(a.is_wan());
    2805           10 :                 CATCH_REQUIRE_FALSE(a.is_wan(true));
    2806           10 :                 CATCH_REQUIRE_FALSE(a.is_wan(false));
    2807              :             }
    2808              :         }
    2809            8 :         CATCH_END_SECTION()
    2810              : 
    2811            8 :         CATCH_START_SECTION("ipv4::addr: private address 192.168.x.x/16")
    2812              :         {
    2813           11 :             for(int idx(0); idx < 10; ++idx)
    2814              :             {
    2815           10 :                 struct sockaddr_in in = sockaddr_in();
    2816           10 :                 in.sin_family = AF_INET;
    2817           10 :                 in.sin_port = htons(rand());
    2818              :                 uint32_t address((192 << 24)
    2819              :                               |  (168 << 16)
    2820           10 :                               | ((rand() & 255) << 8)
    2821           10 :                               | ((rand() & 255) << 0));
    2822           10 :                 in.sin_addr.s_addr = htonl(address);
    2823              : 
    2824              :                 // verify network type
    2825              :                 //
    2826           10 :                 a.set_ipv4(in);
    2827           10 :                 CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_PRIVATE);
    2828           30 :                 CATCH_REQUIRE(std::string(a.get_network_type_string()) == "Private");
    2829           10 :                 CATCH_REQUIRE(a.is_lan());
    2830           10 :                 CATCH_REQUIRE(a.is_lan(true));
    2831           10 :                 CATCH_REQUIRE(a.is_lan(false));
    2832           10 :                 CATCH_REQUIRE_FALSE(a.is_wan());
    2833           10 :                 CATCH_REQUIRE_FALSE(a.is_wan(true));
    2834           10 :                 CATCH_REQUIRE_FALSE(a.is_wan(false));
    2835              :             }
    2836              :         }
    2837            8 :         CATCH_END_SECTION()
    2838              : 
    2839            8 :         CATCH_START_SECTION("ipv4::addr: private address 100.66.x.x/10")
    2840              :         {
    2841           11 :             for(int idx(0); idx < 10; ++idx)
    2842              :             {
    2843           10 :                 struct sockaddr_in in = sockaddr_in();
    2844           10 :                 in.sin_family = AF_INET;
    2845           10 :                 in.sin_port = htons(rand());
    2846              :                 uint32_t address((100 << 24)
    2847           10 :                               | (((rand() & 63) | 64) << 16)
    2848           10 :                               | ((rand() & 255) << 8)
    2849           10 :                               | ((rand() & 255) << 0));
    2850           10 :                 in.sin_addr.s_addr = htonl(address);
    2851              : 
    2852              :                 // verify network type
    2853              :                 //
    2854           10 :                 a.set_ipv4(in);
    2855           10 :                 CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_CARRIER);
    2856           30 :                 CATCH_REQUIRE(std::string(a.get_network_type_string()) == "Carrier");
    2857           10 :                 CATCH_REQUIRE_FALSE(a.is_lan());
    2858           10 :                 CATCH_REQUIRE(a.is_lan(true));
    2859           10 :                 CATCH_REQUIRE_FALSE(a.is_lan(false));
    2860           10 :                 CATCH_REQUIRE_FALSE(a.is_wan());
    2861           10 :                 CATCH_REQUIRE_FALSE(a.is_wan(true));
    2862           10 :                 CATCH_REQUIRE_FALSE(a.is_wan(false));
    2863              :             }
    2864              :         }
    2865            8 :         CATCH_END_SECTION()
    2866              : 
    2867            8 :         CATCH_START_SECTION("ipv4::addr: private address 169.254.x.x/16")
    2868              :         {
    2869           11 :             for(int idx(0); idx < 10; ++idx)
    2870              :             {
    2871           10 :                 struct sockaddr_in in = sockaddr_in();
    2872           10 :                 in.sin_family = AF_INET;
    2873           10 :                 in.sin_port = htons(rand());
    2874              :                 uint32_t address((169 << 24)
    2875              :                               |  (254 << 16)
    2876           10 :                               | ((rand() & 255) << 8)
    2877           10 :                               | ((rand() & 255) << 0));
    2878           10 :                 in.sin_addr.s_addr = htonl(address);
    2879              : 
    2880              :                 // verify network type
    2881              :                 //
    2882           10 :                 a.set_ipv4(in);
    2883           10 :                 CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_LINK_LOCAL);
    2884           30 :                 CATCH_REQUIRE(std::string(a.get_network_type_string()) == "Local Link");
    2885           10 :                 CATCH_REQUIRE_FALSE(a.is_lan());
    2886           10 :                 CATCH_REQUIRE(a.is_lan(true));
    2887           10 :                 CATCH_REQUIRE_FALSE(a.is_lan(false));
    2888           10 :                 CATCH_REQUIRE_FALSE(a.is_wan());
    2889           10 :                 CATCH_REQUIRE_FALSE(a.is_wan(true));
    2890           10 :                 CATCH_REQUIRE_FALSE(a.is_wan(false));
    2891              :             }
    2892              :         }
    2893            8 :         CATCH_END_SECTION()
    2894              : 
    2895            8 :         CATCH_START_SECTION("ipv4::addr: private address 224.x.x.x/4")
    2896              :         {
    2897           11 :             for(int idx(0); idx < 10; ++idx)
    2898              :             {
    2899           10 :                 struct sockaddr_in in = sockaddr_in();
    2900           10 :                 in.sin_family = AF_INET;
    2901           10 :                 in.sin_port = htons(rand());
    2902           10 :                 uint32_t address((((rand() & 15) | 224) << 24)
    2903           10 :                               | ((rand() & 255) << 16)
    2904           10 :                               | ((rand() & 255) << 8)
    2905           10 :                               | ((rand() & 255) << 0));
    2906           10 :                 in.sin_addr.s_addr = htonl(address);
    2907              : 
    2908              :                 // verify network type
    2909              :                 //
    2910           10 :                 a.set_ipv4(in);
    2911           10 :                 CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_MULTICAST);
    2912           30 :                 CATCH_REQUIRE(std::string(a.get_network_type_string()) == "Multicast");
    2913           10 :                 CATCH_REQUIRE_FALSE(a.is_lan());
    2914           10 :                 CATCH_REQUIRE(a.is_lan(true));
    2915           10 :                 CATCH_REQUIRE_FALSE(a.is_lan(false));
    2916           10 :                 CATCH_REQUIRE_FALSE(a.is_wan());
    2917           10 :                 CATCH_REQUIRE_FALSE(a.is_wan(true));
    2918           10 :                 CATCH_REQUIRE_FALSE(a.is_wan(false));
    2919              : 
    2920              :                 // make sure no interface uses that IP
    2921              :                 //
    2922           10 :                 CATCH_REQUIRE(addr::find_addr_interface(a, false) == nullptr);
    2923              :             }
    2924              :         }
    2925            8 :         CATCH_END_SECTION()
    2926              : 
    2927            8 :         CATCH_START_SECTION("ipv4::addr: private address 127.x.x.x/8")
    2928              :         {
    2929           11 :             for(int idx(0); idx < 10; ++idx)
    2930              :             {
    2931           10 :                 struct sockaddr_in in = sockaddr_in();
    2932           10 :                 in.sin_family = AF_INET;
    2933           10 :                 in.sin_port = htons(rand());
    2934              :                 uint32_t address((127 << 24)
    2935           10 :                               | ((rand() & 255) << 16)
    2936           10 :                               | ((rand() & 255) << 8)
    2937           10 :                               | ((rand() & 255) << 0));
    2938           10 :                 in.sin_addr.s_addr = htonl(address);
    2939              : 
    2940              :                 // verify network type
    2941              :                 //
    2942           10 :                 a.set_ipv4(in);
    2943           10 :                 CATCH_REQUIRE(a.get_network_type() == addr::network_type_t::NETWORK_TYPE_LOOPBACK);
    2944           30 :                 CATCH_REQUIRE(std::string(a.get_network_type_string()) == "Loopback");
    2945           10 :                 CATCH_REQUIRE(a.is_lan());
    2946           10 :                 CATCH_REQUIRE(a.is_lan(true));
    2947           10 :                 CATCH_REQUIRE(a.is_lan(false));
    2948           10 :                 CATCH_REQUIRE_FALSE(a.is_wan());
    2949           10 :                 CATCH_REQUIRE_FALSE(a.is_wan(true));
    2950           10 :                 CATCH_REQUIRE_FALSE(a.is_wan(false));
    2951              :             }
    2952              :         }
    2953            8 :         CATCH_END_SECTION()
    2954           16 :     }
    2955            8 : }
    2956              : 
    2957              : 
    2958            7 : CATCH_TEST_CASE("ipv4::network", "[ipv4]")
    2959              : {
    2960            7 :     CATCH_GIVEN("set_from_socket()")
    2961              :     {
    2962            7 :         CATCH_START_SECTION("ipv4::addr: invalid socket")
    2963              :         {
    2964            1 :             addr::addr a;
    2965            1 :             CATCH_REQUIRE_THROWS_AS(a.set_from_socket(-1, true),  addr::addr_invalid_argument);
    2966            1 :             CATCH_REQUIRE_THROWS_AS(a.set_from_socket(-1, false), addr::addr_invalid_argument);
    2967            1 :         }
    2968            7 :         CATCH_END_SECTION()
    2969              : 
    2970            7 :         CATCH_START_SECTION("ipv4::addr: non-opened file descriptor")
    2971              :         {
    2972            1 :             addr::addr a;
    2973              : 
    2974              :             // unless we have a bug, there should not be any file descriptor
    2975              :             // currently open with an ID of 1,000
    2976              :             //
    2977            1 :             CATCH_REQUIRE_THROWS_AS(a.set_from_socket(1000, true),  addr::addr_io_error);
    2978            1 :             CATCH_REQUIRE_THROWS_AS(a.set_from_socket(1000, false), addr::addr_io_error);
    2979            1 :         }
    2980            7 :         CATCH_END_SECTION()
    2981              : 
    2982            7 :         CATCH_START_SECTION("ipv4::addr: unknown socket type")
    2983              :         {
    2984            1 :             addr::addr a;
    2985              : 
    2986            1 :             int s(socket(AF_UNIX, SOCK_STREAM, 0));
    2987            1 :             CATCH_REQUIRE(s >= 0);
    2988            1 :             std::shared_ptr<int> auto_free(&s, socket_deleter);
    2989              : 
    2990              :             // unless we have a bug, there should not be any file descriptor
    2991              :             // currently open with an ID of 1,000
    2992              :             //
    2993            1 :             CATCH_REQUIRE_THROWS_AS(a.set_from_socket(s, true),  addr::addr_io_error);
    2994            1 :             CATCH_REQUIRE_THROWS_AS(a.set_from_socket(s, false), addr::addr_invalid_state);
    2995            1 :         }
    2996            7 :         CATCH_END_SECTION()
    2997              : 
    2998            7 :         CATCH_START_SECTION("ipv4::addr/addr_parser: create a server (bind), but do not test it (yet)...")
    2999              :         {
    3000            1 :             addr::addr_parser p;
    3001            3 :             addr::addr_range::vector_t ips(p.parse("127.0.0.1:49999"));
    3002            1 :             CATCH_REQUIRE(ips.size() >= 1);
    3003              : 
    3004            1 :             addr::addr & a(ips[0].get_from());
    3005            1 :             int s(a.create_socket(addr::addr::SOCKET_FLAG_NONBLOCK | addr::addr::SOCKET_FLAG_CLOEXEC | addr::addr::SOCKET_FLAG_REUSE));
    3006            1 :             CATCH_REQUIRE(s >= 0);
    3007            1 :             std::shared_ptr<int> auto_free(&s, socket_deleter);
    3008              : 
    3009            1 :             CATCH_REQUIRE(a.bind(s) == 0);
    3010            1 :         }
    3011            7 :         CATCH_END_SECTION()
    3012              : 
    3013            7 :         CATCH_START_SECTION("ipv4::addr/addr_parser: connect() with TCP to 127.0.0.1")
    3014              :         {
    3015            1 :             if(SNAP_CATCH2_NAMESPACE::g_tcp_port != -1)
    3016              :             {
    3017            1 :                 addr::addr_parser p;
    3018            1 :                 addr::addr_range::vector_t ips(p.parse("127.0.0.1:" + std::to_string(SNAP_CATCH2_NAMESPACE::g_tcp_port)));
    3019            1 :                 CATCH_REQUIRE(ips.size() >= 1);
    3020              : 
    3021            1 :                 addr::addr & a(ips[0].get_from());
    3022            1 :                 int s(a.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC));// | addr::addr::SOCKET_FLAG_REUSE));
    3023            1 :                 CATCH_REQUIRE(s >= 0);
    3024            1 :                 std::shared_ptr<int> auto_free(&s, socket_deleter);
    3025              : 
    3026            1 :                 CATCH_REQUIRE(a.connect(s) == 0);
    3027              : 
    3028              :                 // get socket info from the other side (peer == true)
    3029              :                 //
    3030            1 :                 addr::addr b;
    3031            1 :                 b.set_from_socket(s, true);
    3032            1 :                 CATCH_REQUIRE(b.is_ipv4());
    3033            1 :                 CATCH_REQUIRE(b.get_family() == AF_INET);
    3034            1 :                 CATCH_REQUIRE_FALSE(b.get_family() == AF_INET6);
    3035            1 :                 CATCH_REQUIRE(b.to_ipv4_string(addr::STRING_IP_ADDRESS)    == "127.0.0.1");
    3036            1 :                 CATCH_REQUIRE(b.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "127.0.0.1");
    3037              : 
    3038              :                 // in this case we know what the port is since we specified
    3039              :                 // that when connecting
    3040              :                 //
    3041            1 :                 CATCH_REQUIRE(b.get_port() == SNAP_CATCH2_NAMESPACE::g_tcp_port);
    3042              : 
    3043              :                 // now try this side (peer == false)
    3044              :                 //
    3045            1 :                 addr::addr c;
    3046            1 :                 c.set_from_socket(s, false);
    3047            1 :                 CATCH_REQUIRE(c.is_ipv4());
    3048            1 :                 CATCH_REQUIRE(c.get_family() == AF_INET);
    3049            1 :                 CATCH_REQUIRE_FALSE(c.get_family() == AF_INET6);
    3050            1 :                 CATCH_REQUIRE(c.to_ipv4_string(addr::STRING_IP_ADDRESS)    == "127.0.0.1");
    3051            1 :                 CATCH_REQUIRE(c.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "127.0.0.1");
    3052              : 
    3053              :                 // we cannot be sure of the port, there is a range we could
    3054              :                 // test better (more constraining) but for this test is
    3055              :                 // certainly does not matter much; it has to be more than
    3056              :                 // 1023, though
    3057              :                 //
    3058            1 :                 CATCH_REQUIRE(c.get_port() > 1023);
    3059            1 :             }
    3060              :             else
    3061              :             {
    3062              :                 // avoid issue of no assertions
    3063              :                 //
    3064            0 :                 CATCH_REQUIRE(SNAP_CATCH2_NAMESPACE::g_tcp_port == -1);
    3065            0 :                 std::cout << "connect to 127.0.0.1 test skipped as no TCP port was specified on the command line." << std::endl;
    3066              :             }
    3067              :         }
    3068            7 :         CATCH_END_SECTION()
    3069              : 
    3070            7 :         CATCH_START_SECTION("ipv4::addr/addr_parser: connect() with UDP to 127.0.0.1:53 which fails")
    3071              :         {
    3072            1 :             addr::addr_parser p;
    3073            3 :             p.set_protocol("udp");
    3074            3 :             addr::addr_range::vector_t ips(p.parse("127.0.0.1:53"));
    3075            1 :             CATCH_REQUIRE(ips.size() >= 1);
    3076              : 
    3077            1 :             addr::addr & a(ips[0].get_from());
    3078            1 :             int s(a.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC));// | addr::addr::SOCKET_FLAG_REUSE));
    3079            1 :             CATCH_REQUIRE(s >= 0);
    3080            1 :             std::shared_ptr<int> auto_free(&s, socket_deleter);
    3081              : 
    3082              :             // addr::connect() does not support UDP
    3083              :             //
    3084            1 :             CATCH_REQUIRE(a.connect(s) == -1);
    3085              : 
    3086            1 :             addr::addr b;
    3087            1 :             CATCH_REQUIRE_THROWS_AS(b.set_from_socket(s, true), addr::addr_io_error);
    3088            1 :             CATCH_REQUIRE_FALSE(b.is_ipv4());
    3089            1 :             CATCH_REQUIRE_FALSE(b.get_family() == AF_INET);
    3090            1 :             CATCH_REQUIRE(b.get_family() == AF_INET6);
    3091            1 :             CATCH_REQUIRE(b.to_ipv6_string(addr::STRING_IP_ADDRESS)    == "::");
    3092            1 :             CATCH_REQUIRE(b.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "::");
    3093            1 :             CATCH_REQUIRE(b.get_port() == 0);
    3094              : 
    3095            1 :             addr::addr c;
    3096            1 :             c.set_from_socket(s, false);
    3097            1 :             CATCH_REQUIRE(c.is_ipv4());
    3098            1 :             CATCH_REQUIRE(c.get_family() == AF_INET);
    3099            1 :             CATCH_REQUIRE_FALSE(c.get_family() == AF_INET6);
    3100            1 :             CATCH_REQUIRE(c.to_ipv4_string(addr::STRING_IP_ADDRESS)    == "0.0.0.0");
    3101            1 :             CATCH_REQUIRE(c.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "0.0.0.0");
    3102            1 :             CATCH_REQUIRE(c.get_port() == 0);
    3103            1 :         }
    3104            7 :         CATCH_END_SECTION()
    3105              : 
    3106            7 :         CATCH_START_SECTION("ipv4::addr/addr_parser: bind() with UDP to 127.0.0.1:<auto> (as a \"client\") which works")
    3107              :         {
    3108            1 :             addr::addr_parser p;
    3109            3 :             p.set_protocol("udp");
    3110            3 :             addr::addr_range::vector_t ips(p.parse("127.0.0.1"));
    3111            1 :             CATCH_REQUIRE(ips.size() >= 1);
    3112              : 
    3113            1 :             addr::addr & a(ips[0].get_from());
    3114            1 :             int s(a.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC));// | addr::addr::SOCKET_FLAG_REUSE));
    3115            1 :             CATCH_REQUIRE(s >= 0);
    3116            1 :             std::shared_ptr<int> auto_free(&s, socket_deleter);
    3117              : 
    3118              :             // succeeds, but the port is not known
    3119              :             //
    3120            1 :             CATCH_REQUIRE(a.bind(s) == 0);
    3121              : 
    3122              :             // this is a UDP socket, there is no other side so we get ANY
    3123              :             //
    3124            1 :             addr::addr b;
    3125            1 :             CATCH_REQUIRE_THROWS_AS(b.set_from_socket(s, true), addr::addr_io_error);
    3126            1 :             CATCH_REQUIRE_FALSE(b.is_ipv4());
    3127            1 :             CATCH_REQUIRE_FALSE(b.get_family() == AF_INET);
    3128            1 :             CATCH_REQUIRE(b.get_family() == AF_INET6);
    3129            1 :             CATCH_REQUIRE(b.to_ipv6_string(addr::STRING_IP_ADDRESS)    == "::");
    3130            1 :             CATCH_REQUIRE(b.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "::");
    3131            1 :             CATCH_REQUIRE(b.get_port() == 0);
    3132              : 
    3133              :             // now try this side (peer == false) and again it is "any"
    3134              :             // since it failed connecting
    3135              :             //
    3136            1 :             addr::addr c;
    3137            1 :             c.set_from_socket(s, false);
    3138            1 :             CATCH_REQUIRE(c.is_ipv4());
    3139            1 :             CATCH_REQUIRE(c.get_family() == AF_INET);
    3140            1 :             CATCH_REQUIRE_FALSE(c.get_family() == AF_INET6);
    3141            1 :             CATCH_REQUIRE(c.to_ipv4_string(addr::STRING_IP_ADDRESS)    == "127.0.0.1");
    3142            1 :             CATCH_REQUIRE(c.to_ipv4or6_string(addr::STRING_IP_ADDRESS) == "127.0.0.1");
    3143              : 
    3144              :             // if this worked, the port is > 1023 (it was auto-allocated)
    3145              :             //
    3146            1 :             CATCH_REQUIRE(c.get_port() > 1023);
    3147              : 
    3148              :             // since the a.bind() is expected to read that port, it should
    3149              :             // equal the one in `a`
    3150              :             //
    3151            1 :             CATCH_REQUIRE(a.get_port() == c.get_port());
    3152            1 :         }
    3153            7 :         CATCH_END_SECTION()
    3154            7 :     }
    3155            7 : }
    3156              : 
    3157              : 
    3158           14 : CATCH_TEST_CASE("ipv4::string_to_addr", "[ipv4]")
    3159              : {
    3160           14 :     CATCH_GIVEN("string_to_addr() ipv4")
    3161              :     {
    3162           14 :         CATCH_START_SECTION("ipv4::string_to_addr: empty address without defaults")
    3163              :         {
    3164            1 :             addr::addr a(addr::string_to_addr(std::string()));
    3165              : 
    3166            1 :             CATCH_REQUIRE(a.is_ipv4());
    3167            1 :             CATCH_REQUIRE(a.get_family() == AF_INET);
    3168            1 :             CATCH_REQUIRE_FALSE(a.get_family() == AF_INET6);
    3169              : 
    3170            1 :             struct sockaddr_in in = sockaddr_in();
    3171            1 :             in.sin_family = AF_INET;
    3172            1 :             in.sin_port = 0;
    3173            1 :             in.sin_addr.s_addr = htonl((0 << 24) | (0 << 16) | (0 << 8) | (0 << 0));
    3174              : 
    3175              :             // test string_to_addr accuracy
    3176              :             //
    3177            1 :             struct sockaddr_in out;
    3178            1 :             a.get_ipv4(out);
    3179            1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    3180              : 
    3181            1 :             uint8_t mask[16];
    3182            1 :             a.get_mask(mask);
    3183            1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    3184            1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    3185            1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    3186            1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    3187            1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    3188            1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    3189            1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    3190            1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    3191            1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    3192            1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    3193            1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    3194            1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    3195            1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    3196            1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    3197            1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    3198            1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    3199            1 :         }
    3200           14 :         CATCH_END_SECTION()
    3201              : 
    3202           14 :         CATCH_START_SECTION("ipv4::string_to_addr: explicit defaults")
    3203              :         {
    3204            3 :             addr::addr a(addr::string_to_addr("5.14.34.111", std::string(), -1, std::string(), false));
    3205              : 
    3206            1 :             CATCH_REQUIRE(a.is_ipv4());
    3207            1 :             CATCH_REQUIRE(a.get_family() == AF_INET);
    3208            1 :             CATCH_REQUIRE_FALSE(a.get_family() == AF_INET6);
    3209              : 
    3210            1 :             struct sockaddr_in in = sockaddr_in();
    3211            1 :             in.sin_family = AF_INET;
    3212            1 :             in.sin_port = 0;
    3213            1 :             in.sin_addr.s_addr = htonl((5 << 24) | (14 << 16) | (34 << 8) | (111 << 0));
    3214              : 
    3215              :             // test string_to_addr accuracy
    3216              :             //
    3217            1 :             struct sockaddr_in out;
    3218            1 :             a.get_ipv4(out);
    3219            1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    3220              : 
    3221            1 :             uint8_t mask[16];
    3222            1 :             a.get_mask(mask);
    3223            1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    3224            1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    3225            1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    3226            1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    3227            1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    3228            1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    3229            1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    3230            1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    3231            1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    3232            1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    3233            1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    3234            1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    3235            1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    3236            1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    3237            1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    3238            1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    3239            1 :         }
    3240           14 :         CATCH_END_SECTION()
    3241              : 
    3242           14 :         CATCH_START_SECTION("ipv4::string_to_addr: defaults")
    3243              :         {
    3244            3 :             addr::addr a(addr::string_to_addr("7.149.104.211"));
    3245              : 
    3246            1 :             CATCH_REQUIRE(a.is_ipv4());
    3247            1 :             CATCH_REQUIRE(a.get_family() == AF_INET);
    3248            1 :             CATCH_REQUIRE_FALSE(a.get_family() == AF_INET6);
    3249              : 
    3250            1 :             struct sockaddr_in in = sockaddr_in();
    3251            1 :             in.sin_family = AF_INET;
    3252            1 :             in.sin_port = 0;
    3253            1 :             in.sin_addr.s_addr = htonl((7 << 24) | (149 << 16) | (104 << 8) | (211 << 0));
    3254              : 
    3255              :             // test string_to_addr accuracy
    3256              :             //
    3257            1 :             struct sockaddr_in out;
    3258            1 :             a.get_ipv4(out);
    3259            1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    3260              : 
    3261            1 :             uint8_t mask[16];
    3262            1 :             a.get_mask(mask);
    3263            1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    3264            1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    3265            1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    3266            1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    3267            1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    3268            1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    3269            1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    3270            1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    3271            1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    3272            1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    3273            1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    3274            1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    3275            1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    3276            1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    3277            1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    3278            1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    3279            1 :         }
    3280           14 :         CATCH_END_SECTION()
    3281              : 
    3282           14 :         CATCH_START_SECTION("ipv4::string_to_addr: addr & default addr")
    3283              :         {
    3284            5 :             addr::addr a(addr::string_to_addr("37.149.174.11", "1.205.32.11"));
    3285              : 
    3286            1 :             CATCH_REQUIRE(a.is_ipv4());
    3287            1 :             CATCH_REQUIRE(a.get_family() == AF_INET);
    3288            1 :             CATCH_REQUIRE_FALSE(a.get_family() == AF_INET6);
    3289              : 
    3290            1 :             struct sockaddr_in in = sockaddr_in();
    3291            1 :             in.sin_family = AF_INET;
    3292            1 :             in.sin_port = 0;
    3293            1 :             in.sin_addr.s_addr = htonl((37 << 24) | (149 << 16) | (174 << 8) | (11 << 0));
    3294              : 
    3295              :             // test string_to_addr accuracy
    3296              :             //
    3297            1 :             struct sockaddr_in out;
    3298            1 :             a.get_ipv4(out);
    3299            1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    3300              : 
    3301            1 :             uint8_t mask[16];
    3302            1 :             a.get_mask(mask);
    3303            1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    3304            1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    3305            1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    3306            1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    3307            1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    3308            1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    3309            1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    3310            1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    3311            1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    3312            1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    3313            1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    3314            1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    3315            1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    3316            1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    3317            1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    3318            1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    3319            1 :         }
    3320           14 :         CATCH_END_SECTION()
    3321              : 
    3322           14 :         CATCH_START_SECTION("ipv4::string_to_addr: no addr, expect default addr")
    3323              :         {
    3324            5 :             addr::addr a(addr::string_to_addr("", "1.205.32.11"));
    3325              : 
    3326            1 :             CATCH_REQUIRE(a.is_ipv4());
    3327            1 :             CATCH_REQUIRE(a.get_family() == AF_INET);
    3328            1 :             CATCH_REQUIRE_FALSE(a.get_family() == AF_INET6);
    3329              : 
    3330            1 :             struct sockaddr_in in = sockaddr_in();
    3331            1 :             in.sin_family = AF_INET;
    3332            1 :             in.sin_port = 0;
    3333            1 :             in.sin_addr.s_addr = htonl((1 << 24) | (205 << 16) | (32 << 8) | (11 << 0));
    3334              : 
    3335              :             // test string_to_addr accuracy
    3336              :             //
    3337            1 :             struct sockaddr_in out;
    3338            1 :             a.get_ipv4(out);
    3339            1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    3340              : 
    3341            1 :             uint8_t mask[16];
    3342            1 :             a.get_mask(mask);
    3343            1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    3344            1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    3345            1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    3346            1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    3347            1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    3348            1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    3349            1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    3350            1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    3351            1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    3352            1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    3353            1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    3354            1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    3355            1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    3356            1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    3357            1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    3358            1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    3359            1 :         }
    3360           14 :         CATCH_END_SECTION()
    3361              : 
    3362           14 :         CATCH_START_SECTION("ipv4::string_to_addr: addr and port, with a default port")
    3363              :         {
    3364            5 :             addr::addr a(addr::string_to_addr("69.109.223.17:697", "1.205.32.11", 123));
    3365              : 
    3366            1 :             CATCH_REQUIRE(a.is_ipv4());
    3367            1 :             CATCH_REQUIRE(a.get_family() == AF_INET);
    3368            1 :             CATCH_REQUIRE_FALSE(a.get_family() == AF_INET6);
    3369              : 
    3370            1 :             struct sockaddr_in in = sockaddr_in();
    3371            1 :             in.sin_family = AF_INET;
    3372            1 :             in.sin_port = htons(697);
    3373            1 :             in.sin_addr.s_addr = htonl((69 << 24) | (109 << 16) | (223 << 8) | (17 << 0));
    3374              : 
    3375              :             // test string_to_addr accuracy
    3376              :             //
    3377            1 :             struct sockaddr_in out;
    3378            1 :             a.get_ipv4(out);
    3379            1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    3380              : 
    3381            1 :             uint8_t mask[16];
    3382            1 :             a.get_mask(mask);
    3383            1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    3384            1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    3385            1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    3386            1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    3387            1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    3388            1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    3389            1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    3390            1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    3391            1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    3392            1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    3393            1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    3394            1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    3395            1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    3396            1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    3397            1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    3398            1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    3399            1 :         }
    3400           14 :         CATCH_END_SECTION()
    3401              : 
    3402           14 :         CATCH_START_SECTION("ipv4::string_to_addr: addr without port, with a default port")
    3403              :         {
    3404            5 :             addr::addr a(addr::string_to_addr("169.209.23.217", "1.205.32.11", 123));
    3405              : 
    3406            1 :             CATCH_REQUIRE(a.is_ipv4());
    3407            1 :             CATCH_REQUIRE(a.get_family() == AF_INET);
    3408            1 :             CATCH_REQUIRE_FALSE(a.get_family() == AF_INET6);
    3409              : 
    3410            1 :             struct sockaddr_in in = sockaddr_in();
    3411            1 :             in.sin_family = AF_INET;
    3412            1 :             in.sin_port = htons(123);
    3413            1 :             in.sin_addr.s_addr = htonl((169 << 24) | (209 << 16) | (23 << 8) | (217 << 0));
    3414              : 
    3415              :             // test string_to_addr accuracy
    3416              :             //
    3417            1 :             struct sockaddr_in out;
    3418            1 :             a.get_ipv4(out);
    3419            1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    3420              : 
    3421            1 :             uint8_t mask[16];
    3422            1 :             a.get_mask(mask);
    3423            1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    3424            1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    3425            1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    3426            1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    3427            1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    3428            1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    3429            1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    3430            1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    3431            1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    3432            1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    3433            1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    3434            1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    3435            1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    3436            1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    3437            1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    3438            1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    3439            1 :         }
    3440           14 :         CATCH_END_SECTION()
    3441              : 
    3442           14 :         CATCH_START_SECTION("ipv4::string_to_addr: addr without port but protocol")
    3443              :         {
    3444            7 :             addr::addr a(addr::string_to_addr("4.5.123.7", "1.205.32.11", 60000, "tcp"));
    3445              : 
    3446            1 :             CATCH_REQUIRE(a.is_ipv4());
    3447            1 :             CATCH_REQUIRE(a.get_family() == AF_INET);
    3448            1 :             CATCH_REQUIRE_FALSE(a.get_family() == AF_INET6);
    3449              : 
    3450            1 :             struct sockaddr_in in = sockaddr_in();
    3451            1 :             in.sin_family = AF_INET;
    3452            1 :             in.sin_port = htons(60000);
    3453            1 :             in.sin_addr.s_addr = htonl((4 << 24) | (5 << 16) | (123 << 8) | (7 << 0));
    3454              : 
    3455              :             // test string_to_addr accuracy
    3456              :             //
    3457            1 :             struct sockaddr_in out;
    3458            1 :             a.get_ipv4(out);
    3459            1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    3460              : 
    3461            1 :             uint8_t mask[16];
    3462            1 :             a.get_mask(mask);
    3463            1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    3464            1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    3465            1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    3466            1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    3467            1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    3468            1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    3469            1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    3470            1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    3471            1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    3472            1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    3473            1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    3474            1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    3475            1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    3476            1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    3477            1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    3478            1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    3479            1 :         }
    3480           14 :         CATCH_END_SECTION()
    3481              : 
    3482           14 :         CATCH_START_SECTION("ipv4::string_to_addr: addr with port and protocol")
    3483              :         {
    3484            7 :             addr::addr a(addr::string_to_addr("204.105.13.9:65", "1.205.32.11", 60000, "tcp"));
    3485              : 
    3486            1 :             CATCH_REQUIRE(a.is_ipv4());
    3487            1 :             CATCH_REQUIRE(a.get_family() == AF_INET);
    3488            1 :             CATCH_REQUIRE_FALSE(a.get_family() == AF_INET6);
    3489              : 
    3490            1 :             struct sockaddr_in in = sockaddr_in();
    3491            1 :             in.sin_family = AF_INET;
    3492            1 :             in.sin_port = htons(65);
    3493            1 :             in.sin_addr.s_addr = htonl((204 << 24) | (105 << 16) | (13 << 8) | (9 << 0));
    3494              : 
    3495              :             // test string_to_addr accuracy
    3496              :             //
    3497            1 :             struct sockaddr_in out;
    3498            1 :             a.get_ipv4(out);
    3499            1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    3500              : 
    3501            1 :             uint8_t mask[16];
    3502            1 :             a.get_mask(mask);
    3503            1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    3504            1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    3505            1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    3506            1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    3507            1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    3508            1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    3509            1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    3510            1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    3511            1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    3512            1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    3513            1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    3514            1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    3515            1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    3516            1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    3517            1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    3518            1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    3519            1 :         }
    3520           14 :         CATCH_END_SECTION()
    3521              : 
    3522           14 :         CATCH_START_SECTION("ipv4::string_to_addr: addr with port and protocol but no mask, albeit allowed")
    3523              :         {
    3524            7 :             addr::addr a(addr::string_to_addr("94.95.131.18:765", "11.205.32.21", 54003, "tcp", true));
    3525              : 
    3526            1 :             CATCH_REQUIRE(a.is_ipv4());
    3527            1 :             CATCH_REQUIRE(a.get_family() == AF_INET);
    3528            1 :             CATCH_REQUIRE_FALSE(a.get_family() == AF_INET6);
    3529              : 
    3530            1 :             struct sockaddr_in in = sockaddr_in();
    3531            1 :             in.sin_family = AF_INET;
    3532            1 :             in.sin_port = htons(765);
    3533            1 :             in.sin_addr.s_addr = htonl((94 << 24) | (95 << 16) | (131 << 8) | (18 << 0));
    3534              : 
    3535              :             // test string_to_addr accuracy
    3536              :             //
    3537            1 :             struct sockaddr_in out;
    3538            1 :             a.get_ipv4(out);
    3539            1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    3540              : 
    3541            1 :             uint8_t mask[16];
    3542            1 :             a.get_mask(mask);
    3543            1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    3544            1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    3545            1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    3546            1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    3547            1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    3548            1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    3549            1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    3550            1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    3551            1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    3552            1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    3553            1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    3554            1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    3555            1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    3556            1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    3557            1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    3558            1 :             CATCH_REQUIRE(mask[15] == 0xFF);
    3559            1 :         }
    3560           14 :         CATCH_END_SECTION()
    3561              : 
    3562           14 :         CATCH_START_SECTION("ipv4::string_to_addr: addr with port and protocol and mask, albeit allowed")
    3563              :         {
    3564            7 :             addr::addr a(addr::string_to_addr("44.45.141.48:765/30", "11.205.32.21", 54003, "tcp", true));
    3565              : 
    3566            1 :             CATCH_REQUIRE(a.is_ipv4());
    3567            1 :             CATCH_REQUIRE(a.get_family() == AF_INET);
    3568            1 :             CATCH_REQUIRE_FALSE(a.get_family() == AF_INET6);
    3569              : 
    3570            1 :             struct sockaddr_in in = sockaddr_in();
    3571            1 :             in.sin_family = AF_INET;
    3572            1 :             in.sin_port = htons(765);
    3573            1 :             in.sin_addr.s_addr = htonl((44 << 24) | (45 << 16) | (141 << 8) | (48 << 0));
    3574              : 
    3575              :             // test string_to_addr accuracy
    3576              :             //
    3577            1 :             struct sockaddr_in out;
    3578            1 :             a.get_ipv4(out);
    3579            1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    3580              : 
    3581            1 :             uint8_t mask[16];
    3582            1 :             a.get_mask(mask);
    3583            1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    3584            1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    3585            1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    3586            1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    3587            1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    3588            1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    3589            1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    3590            1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    3591            1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    3592            1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    3593            1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    3594            1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    3595            1 :             CATCH_REQUIRE(mask[12] == 0xFF);
    3596            1 :             CATCH_REQUIRE(mask[13] == 0xFF);
    3597            1 :             CATCH_REQUIRE(mask[14] == 0xFF);
    3598            1 :             CATCH_REQUIRE(mask[15] == 0xFC);
    3599            1 :         }
    3600           14 :         CATCH_END_SECTION()
    3601              : 
    3602           14 :         CATCH_START_SECTION("ipv4::string_to_addr: addr with port and protocol and mask, albeit allowed")
    3603              :         {
    3604            7 :             addr::addr a(addr::string_to_addr("160.0.0.0:1675/4", "11.205.32.21", 14003, "udp", true));
    3605              : 
    3606            1 :             CATCH_REQUIRE(a.is_ipv4());
    3607            1 :             CATCH_REQUIRE(a.get_family() == AF_INET);
    3608            1 :             CATCH_REQUIRE_FALSE(a.get_family() == AF_INET6);
    3609              : 
    3610            1 :             struct sockaddr_in in = sockaddr_in();
    3611            1 :             in.sin_family = AF_INET;
    3612            1 :             in.sin_port = htons(1675);
    3613            1 :             in.sin_addr.s_addr = htonl((160 << 24) | (0 << 16) | (0 << 8) | (0 << 0));
    3614              : 
    3615              :             // test string_to_addr accuracy
    3616              :             //
    3617            1 :             struct sockaddr_in out;
    3618            1 :             a.get_ipv4(out);
    3619            1 :             CATCH_REQUIRE(memcmp(&out, &in, sizeof(struct sockaddr_in)) == 0);
    3620              : 
    3621            1 :             uint8_t mask[16];
    3622            1 :             a.get_mask(mask);
    3623            1 :             CATCH_REQUIRE(mask[ 0] == 0xFF);
    3624            1 :             CATCH_REQUIRE(mask[ 1] == 0xFF);
    3625            1 :             CATCH_REQUIRE(mask[ 2] == 0xFF);
    3626            1 :             CATCH_REQUIRE(mask[ 3] == 0xFF);
    3627            1 :             CATCH_REQUIRE(mask[ 4] == 0xFF);
    3628            1 :             CATCH_REQUIRE(mask[ 5] == 0xFF);
    3629            1 :             CATCH_REQUIRE(mask[ 6] == 0xFF);
    3630            1 :             CATCH_REQUIRE(mask[ 7] == 0xFF);
    3631            1 :             CATCH_REQUIRE(mask[ 8] == 0xFF);
    3632            1 :             CATCH_REQUIRE(mask[ 9] == 0xFF);
    3633            1 :             CATCH_REQUIRE(mask[10] == 0xFF);
    3634            1 :             CATCH_REQUIRE(mask[11] == 0xFF);
    3635            1 :             CATCH_REQUIRE(mask[12] == 0xF0);
    3636            1 :             CATCH_REQUIRE(mask[13] == 0x00);
    3637            1 :             CATCH_REQUIRE(mask[14] == 0x00);
    3638            1 :             CATCH_REQUIRE(mask[15] == 0x00);
    3639            1 :         }
    3640           14 :         CATCH_END_SECTION()
    3641              : 
    3642           14 :         CATCH_START_SECTION("ipv4::string_to_addr: addr with port and invalid protocol so we get an exception")
    3643              :         {
    3644           12 :             CATCH_REQUIRE_THROWS_AS(addr::string_to_addr("169.60.33.0:9322/24", std::string(), -1, "icmp", true),
    3645              :                                                                         addr::addr_invalid_argument);
    3646              :         }
    3647           14 :         CATCH_END_SECTION()
    3648              : 
    3649           14 :         CATCH_START_SECTION("ipv4::string_to_addr: definitely not a valid address")
    3650              :         {
    3651           12 :             CATCH_REQUIRE_THROWS_MATCHES(
    3652              :                   addr::string_to_addr("not an address")
    3653              :                 , addr::addr_invalid_argument
    3654              :                 , Catch::Matchers::ExceptionMessage("addr_error: the address \"not an address\" could not be converted to a single address in string_to_addr(), found 0 entries instead."));
    3655              :         }
    3656           14 :         CATCH_END_SECTION()
    3657           14 :     }
    3658           14 : }
    3659              : 
    3660              : 
    3661            3 : CATCH_TEST_CASE("ipv4::udp", "[ipv4]")
    3662              : {
    3663            3 :     constexpr int const TEST_PORT(4004);
    3664            3 :     constexpr int const TEST_PROTOCOL(IPPROTO_UDP);
    3665            3 :     constexpr int const TEST_COUNT(10);
    3666              : 
    3667            3 :     CATCH_START_SECTION("ipv4::udp: sendto() and recvfrom()")
    3668              :     {
    3669              :         class sr
    3670              :         {
    3671              :         public:
    3672            1 :             sr()
    3673            1 :             {
    3674            1 :                 f_a.set_protocol(TEST_PROTOCOL);
    3675            1 :                 f_a.set_ipv4_loopback();
    3676            1 :                 f_a.set_port(TEST_PORT);
    3677            1 :                 f_sa = f_a.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC | addr::addr::SOCKET_FLAG_REUSE);
    3678            1 :                 CATCH_REQUIRE(f_sa != -1);
    3679              : 
    3680            1 :                 f_b.set_protocol(TEST_PROTOCOL);
    3681            1 :                 f_b.set_ipv4_loopback();
    3682            1 :                 f_b.set_port(TEST_PORT);
    3683            1 :                 f_sb = f_b.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC | addr::addr::SOCKET_FLAG_REUSE);
    3684            1 :                 CATCH_REQUIRE(f_sb != -1);
    3685            1 :                 f_b.bind(f_sb); // the receive has to be bound
    3686              : 
    3687           11 :                 for(int i(0); i < TEST_COUNT; ++i)
    3688              :                 {
    3689           10 :                     std::size_t const size(rand() % 350 + 50);
    3690           10 :                     f_buf[i].resize(size);
    3691         2264 :                     for(std::size_t idx(0); idx < size; ++idx)
    3692              :                     {
    3693         2254 :                         f_buf[i][idx] = rand();
    3694              :                     }
    3695              :                 }
    3696            1 :             }
    3697              : 
    3698            1 :             void run()
    3699              :             {
    3700            1 :                 int client_port(-1);
    3701           11 :                 for(int i(0); i < TEST_COUNT; ++i)
    3702              :                 {
    3703           10 :                     sendto(i);
    3704              : 
    3705           30 :                     std::vector<std::uint8_t> bb(f_buf[i].size());
    3706           10 :                     int const r(f_b.recvfrom(f_sb, reinterpret_cast<char *>(bb.data()), bb.size()));
    3707           10 :                     if(r == -1)
    3708              :                     {
    3709            0 :                         int const e(errno);
    3710            0 :                         std::cerr << "--- recvfrom() returned an error: " << strerror(e) << std::endl;
    3711            0 :                         return;
    3712              :                     }
    3713              : 
    3714           10 :                     CATCH_REQUIRE(r == static_cast<int>(f_buf[i].size()));
    3715           10 :                     CATCH_REQUIRE(f_buf[i] == bb);
    3716           10 :                     CATCH_REQUIRE(f_b.is_ipv4());
    3717           10 :                     if(client_port == -1)
    3718              :                     {
    3719            1 :                         client_port = f_b.get_port();
    3720              :                     }
    3721              :                     else
    3722              :                     {
    3723              :                         // the ephemeral port does not change once we sent
    3724              :                         // the first packet
    3725              :                         //
    3726            9 :                         CATCH_REQUIRE(f_b.get_port() == client_port);
    3727              :                     }
    3728           10 :                     CATCH_REQUIRE(f_b.get_network_type() == addr::network_type_t::NETWORK_TYPE_LOOPBACK);
    3729           10 :                 }
    3730              :             }
    3731              : 
    3732           10 :             void sendto(int idx)
    3733              :             {
    3734           10 :                 int const r(f_a.sendto(f_sa, reinterpret_cast<char const *>(f_buf[idx].data()), f_buf[idx].size()));
    3735           10 :                 if(r == -1)
    3736              :                 {
    3737            0 :                     int const e(errno);
    3738            0 :                     std::cerr << "--- sendto() returned an error: " << strerror(e) << std::endl;
    3739            0 :                     return;
    3740              :                 }
    3741           10 :                 CATCH_REQUIRE(r == static_cast<int>(f_buf[idx].size()));
    3742              :             }
    3743              : 
    3744              :             addr::addr                  f_a = addr::addr();
    3745              :             addr::addr                  f_b = addr::addr();
    3746              :             int                         f_sa = -1;
    3747              :             int                         f_sb = -1;
    3748              :             std::vector<std::uint8_t>   f_buf[TEST_COUNT] = {};
    3749              :         };
    3750              : 
    3751            1 :         sr run;
    3752            1 :         run.run();
    3753            1 :     }
    3754            3 :     CATCH_END_SECTION()
    3755              : 
    3756            3 :     CATCH_START_SECTION("ipv4::udp: sendto() with wrong protocol")
    3757              :     {
    3758            1 :         addr::addr a;
    3759            1 :         a.set_protocol(IPPROTO_TCP);
    3760            1 :         a.set_ipv4_loopback();
    3761            1 :         a.set_port(TEST_PORT);
    3762            1 :         int sa(a.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC | addr::addr::SOCKET_FLAG_REUSE));
    3763            1 :         CATCH_REQUIRE(sa != -1);
    3764              : 
    3765            1 :         char buf[256];
    3766            1 :         int const r(a.sendto(sa, buf, sizeof(buf)));
    3767            1 :         int const e(errno);
    3768            1 :         CATCH_REQUIRE(r == -1);
    3769            1 :         CATCH_REQUIRE(e == EINVAL);
    3770              : 
    3771            1 :         close(sa);
    3772            1 :     }
    3773            3 :     CATCH_END_SECTION()
    3774              : 
    3775            3 :     CATCH_START_SECTION("ipv4::udp: recvfrom() with wrong protocol")
    3776              :     {
    3777            1 :         addr::addr a;
    3778            1 :         a.set_protocol(IPPROTO_TCP);
    3779            1 :         a.set_ipv4_loopback();
    3780            1 :         a.set_port(TEST_PORT);
    3781            1 :         int sa(a.create_socket(addr::addr::SOCKET_FLAG_CLOEXEC | addr::addr::SOCKET_FLAG_REUSE));
    3782            1 :         CATCH_REQUIRE(sa != -1);
    3783            1 :         a.bind(sa); // the receive has to be bound
    3784              : 
    3785            1 :         char buf[256];
    3786            1 :         int const r(a.recvfrom(sa, buf, sizeof(buf)));
    3787            1 :         int const e(errno);
    3788            1 :         CATCH_REQUIRE(r == -1);
    3789            1 :         CATCH_REQUIRE(e == EINVAL);
    3790              : 
    3791            1 :         close(sa);
    3792            1 :     }
    3793            3 :     CATCH_END_SECTION()
    3794            3 : }
    3795              : 
    3796              : 
    3797              : // vim: ts=4 sw=4 et
        

Generated by: LCOV version 2.0-1

Snap C++ | List of projects | List of versions