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[] = {

Reply via email to