This is an automated email from the ASF dual-hosted git repository. bneradt pushed a commit to branch dev-1-0-10 in repository https://gitbox.apache.org/repos/asf/trafficserver-libswoc.git
commit 9d62d2210a0919edfe7580d6439d470334dbe161 Author: Alan M. Carroll <a...@apache.org> AuthorDate: Thu Jan 30 16:01:13 2020 -0600 Fix BWF conflict between unsigned and in_addr_t. Be thorough about IP4 address stored in host order. --- swoc++/include/swoc/bwf_ip.h | 6 +----- swoc++/include/swoc/swoc_ip.h | 15 ++++++++++++--- swoc++/src/bw_ip_format.cc | 6 +++--- unit_tests/test_ip.cc | 27 +++++++++++++++++++++++---- 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/swoc++/include/swoc/bwf_ip.h b/swoc++/include/swoc/bwf_ip.h index be1fa46..2b19d7f 100644 --- a/swoc++/include/swoc/bwf_ip.h +++ b/swoc++/include/swoc/bwf_ip.h @@ -28,8 +28,8 @@ namespace swoc { // All of these expect the address to be in network order. BufferWriter &bwformat(BufferWriter &w, bwf::Spec const &spec, sockaddr const *addr); -BufferWriter &bwformat(BufferWriter &w, bwf::Spec const &spec, in_addr_t addr); BufferWriter &bwformat(BufferWriter &w, bwf::Spec const &spec, in6_addr const &addr); +BufferWriter &bwformat(BufferWriter &w, bwf::Spec const &spec, IP4Addr const &addr); BufferWriter &bwformat(BufferWriter &w, bwf::Spec const &spec, IPAddr const &addr); BufferWriter &bwformat(BufferWriter &w, bwf::Spec const &spec, sockaddr const *addr); @@ -38,8 +38,4 @@ bwformat(BufferWriter &w, bwf::Spec const &spec, IPEndpoint const &addr) { return bwformat(w, spec, &addr.sa); } -inline BufferWriter &bwformat(BufferWriter &w, bwf::Spec const &spec, IP4Addr const& addr) { - return bwformat(w, spec, addr.network_order()); -} - } // namespace swoc diff --git a/swoc++/include/swoc/swoc_ip.h b/swoc++/include/swoc/swoc_ip.h index f440caa..66213cb 100644 --- a/swoc++/include/swoc/swoc_ip.h +++ b/swoc++/include/swoc/swoc_ip.h @@ -149,7 +149,7 @@ union IPEndpoint { }; /** Storage for an IPv4 address. - Stored in network order. + Stored in host order. */ class IP4Addr { using self_type = IP4Addr; ///< Self reference type. @@ -185,6 +185,7 @@ public: sockaddr *fill(sockaddr_in *sa, in_port_t port = 0) const; in_addr_t network_order() const; + in_addr_t host_order() const; /** Parse @a text as IPv4 address. The address resulting from the parse is copied to this object if the conversion is successful, @@ -210,13 +211,17 @@ public: /// Test for loopback bool is_loopback() const; + constexpr static in_addr_t reorder(in_addr_t src) { + return ((src & 0xFF) << 24) | (((src >> 8) & 0xFF) << 16) | (((src >> 16) & 0xFF) << 8) | ((src >> 24) & 0xFF); + } + protected: friend bool operator==(self_type const &, self_type const &); friend bool operator!=(self_type const &, self_type const &); friend bool operator<(self_type const &, self_type const &); friend bool operator<=(self_type const &, self_type const &); - in_addr_t _addr = INADDR_ANY; + in_addr_t _addr = INADDR_ANY; ///< Address in host order. }; /** Storage for an IPv6 address. @@ -1002,7 +1007,7 @@ IPEndpoint::host_order_port(sockaddr const *addr) { // --- IPAddr variants --- -inline constexpr IP4Addr::IP4Addr(in_addr_t addr) : _addr(addr) {} +inline constexpr IP4Addr::IP4Addr(in_addr_t addr) : _addr(reorder(addr)) {} inline IP4Addr::IP4Addr(std::string_view const& text) { if (! this->load(text)) { @@ -1026,6 +1031,10 @@ inline in_addr_t IP4Addr::network_order() const { return htonl(_addr); } +inline in_addr_t IP4Addr::host_order() const { + return _addr; +} + inline IP4Addr::operator in_addr_t() const { return this->network_order(); } diff --git a/swoc++/src/bw_ip_format.cc b/swoc++/src/bw_ip_format.cc index 0cf041e..14f5c27 100644 --- a/swoc++/src/bw_ip_format.cc +++ b/swoc++/src/bw_ip_format.cc @@ -49,9 +49,9 @@ namespace swoc using bwf::Spec; BufferWriter & -bwformat(BufferWriter &w, Spec const &spec, in_addr_t addr) +bwformat(BufferWriter &w, Spec const &spec, IP4Addr const& addr) { - in_addr_t host { ntohl(addr) }; + in_addr_t host = addr.host_order(); Spec local_spec{spec}; // Format for address elements. bool align_p = false; @@ -253,7 +253,7 @@ bwformat(BufferWriter &w, Spec const &spec, sockaddr const *addr) bool bracket_p = false; switch (addr->sa_family) { case AF_INET: - bwformat(w, spec, reinterpret_cast<sockaddr_in const *>(addr)->sin_addr.s_addr); + bwformat(w, spec, IP4Addr{reinterpret_cast<sockaddr_in const *>(addr)->sin_addr.s_addr}); break; case AF_INET6: if (port_p) { diff --git a/unit_tests/test_ip.cc b/unit_tests/test_ip.cc index 7ad662a..285e13f 100644 --- a/unit_tests/test_ip.cc +++ b/unit_tests/test_ip.cc @@ -62,7 +62,6 @@ TEST_CASE("ink_inet", "[libswoc][ip]") { IP6Addr a6_1{"fe80:88b5:4a:20c:29ff:feae:5587:1c33"}; IP6Addr a6_2{"fe80:88b5:4a:20c:29ff:feae:5587:1c34"}; IP6Addr a6_3{"de80:88b5:4a:20c:29ff:feae:5587:1c35"}; - IP6Addr a6_4{"fe80:88b5:4a:20c:29ff:feae:5587:1c34"}; REQUIRE(a6_1 != a6_null); REQUIRE(a6_1 != a6_2); @@ -73,9 +72,29 @@ TEST_CASE("ink_inet", "[libswoc][ip]") { ++a6_1; REQUIRE(a6_1 != a6_2); REQUIRE(a6_1 > a6_2); - REQUIRE(a6_3 != a6_4); - REQUIRE(a6_3 < a6_4); - REQUIRE(a6_4 > a6_3); + + REQUIRE(a6_3 != a6_2); + REQUIRE(a6_3 < a6_2); + REQUIRE(a6_2 > a6_3); + + // Little bit of IP4 address arithmetic / comparison testing. + IP4Addr a4_null; + IP4Addr a4_1{"172.28.56.33"}; + IP4Addr a4_2{"172.28.56.34"}; + IP4Addr a4_3{"170.28.56.35"}; + + REQUIRE(a4_1 != a4_null); + REQUIRE(a4_1 != a4_2); + REQUIRE(a4_1 < a4_2); + REQUIRE(a4_2 > a4_1); + ++a4_1; + REQUIRE(a4_1 == a4_2); + ++a4_1; + REQUIRE(a4_1 != a4_2); + REQUIRE(a4_1 > a4_2); + REQUIRE(a4_3 != a4_2); + REQUIRE(a4_3 < a4_2); + REQUIRE(a4_2 > a4_3); // For this data, the bytes should be in IPv6 network order. static const std::tuple<TextView, bool, IP6Addr::raw_type> ipv6_ex[] = {