This is an automated email from the ASF dual-hosted git repository.

maskit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new ef802ccdbc Accept PROXY protocol header that carries UDP address info 
(#12011)
ef802ccdbc is described below

commit ef802ccdbc808d53da9649d2bd248934e857a763
Author: Masakazu Kitajo <[email protected]>
AuthorDate: Mon Feb 3 17:31:19 2025 -0700

    Accept PROXY protocol header that carries UDP address info (#12011)
    
    * Accept PROXY protocol header that carries UDP address info
    
    * Add tests
---
 include/iocore/net/ProxyProtocol.h              |  5 +-
 src/iocore/net/ProxyProtocol.cc                 | 60 ++++++++++++++----------
 src/iocore/net/unit_tests/test_ProxyProtocol.cc | 62 +++++++++++++++++++++++++
 3 files changed, 102 insertions(+), 25 deletions(-)

diff --git a/include/iocore/net/ProxyProtocol.h 
b/include/iocore/net/ProxyProtocol.h
index f7cbb1aa28..7ff570162a 100644
--- a/include/iocore/net/ProxyProtocol.h
+++ b/include/iocore/net/ProxyProtocol.h
@@ -64,10 +64,13 @@ public:
   {
   }
   ~ProxyProtocol() { ats_free(additional_data); }
-  int set_additional_data(std::string_view data);
+  int  set_additional_data(std::string_view data);
+  void set_ipv4_addrs(in_addr_t src_addr, uint16_t src_port, in_addr_t 
dst_addr, uint16_t dst_port);
+  void set_ipv6_addrs(const in6_addr &src_addr, uint16_t src_port, const 
in6_addr &dst_addr, uint16_t dst_port);
 
   ProxyProtocolVersion                          version   = 
ProxyProtocolVersion::UNDEFINED;
   uint16_t                                      ip_family = AF_UNSPEC;
+  int                                           type      = 0;
   IpEndpoint                                    src_addr  = {};
   IpEndpoint                                    dst_addr  = {};
   std::unordered_map<uint8_t, std::string_view> tlv;
diff --git a/src/iocore/net/ProxyProtocol.cc b/src/iocore/net/ProxyProtocol.cc
index c2c6444307..76e7a3ddef 100644
--- a/src/iocore/net/ProxyProtocol.cc
+++ b/src/iocore/net/ProxyProtocol.cc
@@ -251,44 +251,32 @@ proxy_protocol_v2_parse(ProxyProtocol *pp_info, const 
swoc::TextView &msg)
   }
   case PPv2_CMD_PROXY: {
     switch (hdr_v2->fam) {
-    case PPv2_PROTO_TCP4: {
+    case PPv2_PROTO_TCP4:
+    case PPv2_PROTO_UDP4:
       if (len < PPv2_ADDR_LEN_INET) {
         return 0;
       }
       tlv_len = len - PPv2_ADDR_LEN_INET;
 
-      IpAddr src_addr(reinterpret_cast<in_addr_t>(hdr_v2->addr.ip4.src_addr));
-      pp_info->src_addr.assign(src_addr, hdr_v2->addr.ip4.src_port);
-
-      IpAddr dst_addr(reinterpret_cast<in_addr_t>(hdr_v2->addr.ip4.dst_addr));
-      pp_info->dst_addr.assign(dst_addr, hdr_v2->addr.ip4.dst_port);
-
-      pp_info->version   = ProxyProtocolVersion::V2;
-      pp_info->ip_family = AF_INET;
+      
pp_info->set_ipv4_addrs(reinterpret_cast<in_addr_t>(hdr_v2->addr.ip4.src_addr), 
hdr_v2->addr.ip4.src_port,
+                              
reinterpret_cast<in_addr_t>(hdr_v2->addr.ip4.dst_addr), 
hdr_v2->addr.ip4.dst_port);
+      pp_info->type    = hdr_v2->fam == PPv2_PROTO_TCP4 ? SOCK_STREAM : 
SOCK_DGRAM;
+      pp_info->version = ProxyProtocolVersion::V2;
 
       break;
-    }
-    case PPv2_PROTO_TCP6: {
+    case PPv2_PROTO_TCP6:
+    case PPv2_PROTO_UDP6:
       if (len < PPv2_ADDR_LEN_INET6) {
         return 0;
       }
       tlv_len = len - PPv2_ADDR_LEN_INET6;
 
-      IpAddr src_addr(reinterpret_cast<in6_addr const 
&>(hdr_v2->addr.ip6.src_addr));
-      pp_info->src_addr.assign(src_addr, hdr_v2->addr.ip6.src_port);
-
-      IpAddr dst_addr(reinterpret_cast<in6_addr const 
&>(hdr_v2->addr.ip6.dst_addr));
-      pp_info->dst_addr.assign(dst_addr, hdr_v2->addr.ip6.dst_port);
-
-      pp_info->version   = ProxyProtocolVersion::V2;
-      pp_info->ip_family = AF_INET6;
+      pp_info->set_ipv6_addrs(reinterpret_cast<in6_addr const 
&>(hdr_v2->addr.ip6.src_addr), hdr_v2->addr.ip6.src_port,
+                              reinterpret_cast<in6_addr const 
&>(hdr_v2->addr.ip6.dst_addr), hdr_v2->addr.ip6.dst_port);
+      pp_info->type    = hdr_v2->fam == PPv2_PROTO_TCP6 ? SOCK_STREAM : 
SOCK_DGRAM;
+      pp_info->version = ProxyProtocolVersion::V2;
 
       break;
-    }
-    case PPv2_PROTO_UDP4:
-      [[fallthrough]];
-    case PPv2_PROTO_UDP6:
-      [[fallthrough]];
     case PPv2_PROTO_UNIX_STREAM:
       [[fallthrough]];
     case PPv2_PROTO_UNIX_DATAGRAM:
@@ -513,6 +501,30 @@ proxy_protocol_version_cast(int i)
   }
 }
 
+void
+ProxyProtocol::set_ipv4_addrs(in_addr_t src_addr, uint16_t src_port, in_addr_t 
dst_addr, uint16_t dst_port)
+{
+  IpAddr src(src_addr);
+  IpAddr dst(dst_addr);
+
+  this->src_addr.assign(src, src_port);
+  this->dst_addr.assign(dst, dst_port);
+
+  this->ip_family = AF_INET;
+}
+
+void
+ProxyProtocol::set_ipv6_addrs(const in6_addr &src_addr, uint16_t src_port, 
const in6_addr &dst_addr, uint16_t dst_port)
+{
+  IpAddr src(src_addr);
+  IpAddr dst(dst_addr);
+
+  this->src_addr.assign(src, src_port);
+  this->dst_addr.assign(dst, dst_port);
+
+  this->ip_family = AF_INET6;
+}
+
 int
 ProxyProtocol::set_additional_data(std::string_view data)
 {
diff --git a/src/iocore/net/unit_tests/test_ProxyProtocol.cc 
b/src/iocore/net/unit_tests/test_ProxyProtocol.cc
index 4f9c3a316d..7345f858a3 100644
--- a/src/iocore/net/unit_tests/test_ProxyProtocol.cc
+++ b/src/iocore/net/unit_tests/test_ProxyProtocol.cc
@@ -150,6 +150,7 @@ TEST_CASE("PROXY Protocol v2 Parser", 
"[ProxyProtocol][ProxyProtocolv2]")
 
     CHECK(pp_info.version == ProxyProtocolVersion::V2);
     CHECK(pp_info.ip_family == AF_INET);
+    CHECK(pp_info.type == SOCK_STREAM);
     CHECK(pp_info.src_addr == src_addr);
     CHECK(pp_info.dst_addr == dst_addr);
   }
@@ -180,6 +181,67 @@ TEST_CASE("PROXY Protocol v2 Parser", 
"[ProxyProtocol][ProxyProtocolv2]")
 
     CHECK(pp_info.version == ProxyProtocolVersion::V2);
     CHECK(pp_info.ip_family == AF_INET6);
+    CHECK(pp_info.type == SOCK_STREAM);
+    CHECK(pp_info.src_addr == src_addr);
+    CHECK(pp_info.dst_addr == dst_addr);
+  }
+
+  SECTION("UDP over IPv4 without TLVs")
+  {
+    uint8_t raw_data[] = {
+      0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, ///< preface
+      0x55, 0x49, 0x54, 0x0A,                         ///<
+      0x21,                                           ///< version & command
+      0x12,                                           ///< protocol & family
+      0x00, 0x0C,                                     ///< len
+      0xC0, 0x00, 0x02, 0x01,                         ///< src_addr
+      0xC6, 0x33, 0x64, 0x01,                         ///< dst_addr
+      0xC3, 0x50,                                     ///< src_port
+      0x01, 0xBB,                                     ///< dst_port
+    };
+
+    swoc::TextView tv(reinterpret_cast<char *>(raw_data), sizeof(raw_data));
+
+    ProxyProtocol pp_info;
+    REQUIRE(proxy_protocol_parse(&pp_info, tv) == tv.size());
+
+    REQUIRE(ats_ip_pton("192.0.2.1:50000", src_addr) == 0);
+    REQUIRE(ats_ip_pton("198.51.100.1:443", dst_addr) == 0);
+
+    CHECK(pp_info.version == ProxyProtocolVersion::V2);
+    CHECK(pp_info.ip_family == AF_INET);
+    CHECK(pp_info.type == SOCK_DGRAM);
+    CHECK(pp_info.src_addr == src_addr);
+    CHECK(pp_info.dst_addr == dst_addr);
+  }
+
+  SECTION("UDP over IPv6 without TLVs")
+  {
+    uint8_t raw_data[] = {
+      0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, ///< preface
+      0x55, 0x49, 0x54, 0x0A,                         ///<
+      0x21,                                           ///< version & command
+      0x22,                                           ///< protocol & family
+      0x00, 0x24,                                     ///< len
+      0x20, 0x01, 0x0D, 0xB8, 0x00, 0x00, 0x00, 0x01, ///< src_addr
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ///<
+      0x20, 0x01, 0x0D, 0xB8, 0x00, 0x00, 0x00, 0x02, ///< dst_addr
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ///<
+      0xC3, 0x50,                                     ///< src_port
+      0x01, 0xBB,                                     ///< dst_port
+    };
+
+    swoc::TextView tv(reinterpret_cast<char *>(raw_data), sizeof(raw_data));
+
+    ProxyProtocol pp_info;
+    REQUIRE(proxy_protocol_parse(&pp_info, tv) == tv.size());
+
+    REQUIRE(ats_ip_pton("[2001:db8:0:1::]:50000", src_addr) == 0);
+    REQUIRE(ats_ip_pton("[2001:db8:0:2::]:443", dst_addr) == 0);
+
+    CHECK(pp_info.version == ProxyProtocolVersion::V2);
+    CHECK(pp_info.ip_family == AF_INET6);
+    CHECK(pp_info.type == SOCK_DGRAM);
     CHECK(pp_info.src_addr == src_addr);
     CHECK(pp_info.dst_addr == dst_addr);
   }

Reply via email to