Skip to content

Commit 43480c8

Browse files
committed
Add support for parsing Proxy protcol v2 TLV fields
1 parent 4c9c7c6 commit 43480c8

File tree

3 files changed

+82
-10
lines changed

3 files changed

+82
-10
lines changed

include/iocore/net/ProxyProtocol.h

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828
#include <tscore/ink_inet.h>
2929
#include <swoc/TextView.h>
30+
#include <unordered_map>
31+
#include <cstdlib>
3032

3133
enum class ProxyProtocolVersion {
3234
UNDEFINED,
@@ -40,11 +42,38 @@ enum class ProxyProtocolData {
4042
DST,
4143
};
4244

43-
struct ProxyProtocol {
44-
ProxyProtocolVersion version = ProxyProtocolVersion::UNDEFINED;
45-
uint16_t ip_family = AF_UNSPEC;
46-
IpEndpoint src_addr = {};
47-
IpEndpoint dst_addr = {};
45+
constexpr uint8_t PP2_TYPE_ALPN = 0x01;
46+
constexpr uint8_t PP2_TYPE_AUTHORITY = 0x02;
47+
constexpr uint8_t PP2_TYPE_CRC32C = 0x03;
48+
constexpr uint8_t PP2_TYPE_NOOP = 0x04;
49+
constexpr uint8_t PP2_TYPE_UNIQUE_ID = 0x05;
50+
constexpr uint8_t PP2_TYPE_SSL = 0x20;
51+
constexpr uint8_t PP2_SUBTYPE_SSL_VERSION = 0x21;
52+
constexpr uint8_t PP2_SUBTYPE_SSL_CN = 0x22;
53+
constexpr uint8_t PP2_SUBTYPE_SSL_CIPHER = 0x23;
54+
constexpr uint8_t PP2_SUBTYPE_SSL_SIG_ALG = 0x24;
55+
constexpr uint8_t PP2_SUBTYPE_SSL_KEY_ALG = 0x25;
56+
constexpr uint8_t PP2_TYPE_NETNS = 0x30;
57+
58+
class ProxyProtocol
59+
{
60+
public:
61+
ProxyProtocol() {}
62+
ProxyProtocol(ProxyProtocolVersion pp_ver, uint16_t family, IpEndpoint src, IpEndpoint dst)
63+
: version(pp_ver), ip_family(family), src_addr(src), dst_addr(dst)
64+
{
65+
}
66+
~ProxyProtocol() { free(additional_data); }
67+
int set_additional_data(std::string_view data);
68+
69+
ProxyProtocolVersion version = ProxyProtocolVersion::UNDEFINED;
70+
uint16_t ip_family = AF_UNSPEC;
71+
IpEndpoint src_addr = {};
72+
IpEndpoint dst_addr = {};
73+
std::unordered_map<uint8_t, std::string_view> tlv;
74+
75+
private:
76+
char *additional_data = nullptr;
4877
};
4978

5079
const size_t PPv1_CONNECTION_HEADER_LEN_MAX = 108;

src/iocore/net/ProxyProtocol.cc

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,6 @@ proxy_protocol_v1_parse(ProxyProtocol *pp_info, swoc::TextView hdr)
216216
/**
217217
PROXY Protocol v2 Parser
218218
219-
TODO: TLVs Support
220-
221219
@return read length
222220
*/
223221
size_t
@@ -232,6 +230,7 @@ proxy_protocol_v2_parse(ProxyProtocol *pp_info, const swoc::TextView &msg)
232230
// length check
233231
const uint16_t len = ntohs(hdr_v2->len);
234232
const size_t total_len = PPv2_CONNECTION_HEADER_LEN + len;
233+
uint16_t tlv_len = 0;
235234

236235
if (msg.size() < total_len) {
237236
return 0;
@@ -256,6 +255,7 @@ proxy_protocol_v2_parse(ProxyProtocol *pp_info, const swoc::TextView &msg)
256255
if (len < PPv2_ADDR_LEN_INET) {
257256
return 0;
258257
}
258+
tlv_len = len - PPv2_ADDR_LEN_INET;
259259

260260
IpAddr src_addr(reinterpret_cast<in_addr_t>(hdr_v2->addr.ip4.src_addr));
261261
pp_info->src_addr.assign(src_addr, hdr_v2->addr.ip4.src_port);
@@ -272,6 +272,7 @@ proxy_protocol_v2_parse(ProxyProtocol *pp_info, const swoc::TextView &msg)
272272
if (len < PPv2_ADDR_LEN_INET6) {
273273
return 0;
274274
}
275+
tlv_len = len - PPv2_ADDR_LEN_INET6;
275276

276277
IpAddr src_addr(reinterpret_cast<in6_addr const &>(hdr_v2->addr.ip6.src_addr));
277278
pp_info->src_addr.assign(src_addr, hdr_v2->addr.ip6.src_port);
@@ -299,7 +300,11 @@ proxy_protocol_v2_parse(ProxyProtocol *pp_info, const swoc::TextView &msg)
299300
return 0;
300301
}
301302

302-
// TODO: Parse TLVs
303+
if (tlv_len > 0) {
304+
if (pp_info->set_additional_data(msg.substr(msg.length() - tlv_len)) < 0) {
305+
return 0;
306+
}
307+
}
303308

304309
return total_len;
305310
}
@@ -507,3 +512,38 @@ proxy_protocol_version_cast(int i)
507512
return ProxyProtocolVersion::UNDEFINED;
508513
}
509514
}
515+
516+
int
517+
ProxyProtocol::set_additional_data(std::string_view data)
518+
{
519+
uint16_t len = data.length();
520+
additional_data = static_cast<char *>(ats_malloc(len));
521+
if (additional_data == nullptr) {
522+
return -1;
523+
}
524+
data.copy(additional_data, len);
525+
526+
const char *p = additional_data;
527+
const char *end = p + len;
528+
while (p != end) {
529+
if (end - p < 3) {
530+
// The size of a TLV entry must be 3 bytes or more
531+
return -2;
532+
}
533+
534+
// Type
535+
uint8_t type = *p;
536+
p += 1;
537+
538+
// Length
539+
uint16_t length = ntohs(*reinterpret_cast<const uint16_t *>(p));
540+
p += 2;
541+
542+
// Value
543+
Dbg(dbg_ctl_proxyprotocol, "TLV: ID=%u LEN=%hu", type, length);
544+
tlv.emplace(type, std::string_view(p, length));
545+
p += length;
546+
}
547+
548+
return 0;
549+
}

src/iocore/net/unit_tests/test_ProxyProtocol.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,20 +234,20 @@ TEST_CASE("PROXY Protocol v2 Parser", "[ProxyProtocol][ProxyProtocolv2]")
234234
CHECK(pp_info.ip_family == AF_UNSPEC);
235235
}
236236

237-
// TLVs are not supported yet. Checking TLVs are skipped as expected for now.
238237
SECTION("TLVs")
239238
{
240239
uint8_t raw_data[] = {
241240
0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, ///< preface
242241
0x55, 0x49, 0x54, 0x0A, ///<
243242
0x21, ///< version & command
244243
0x11, ///< protocol & family
245-
0x00, 0x11, ///< len
244+
0x00, 0x17, ///< len
246245
0xC0, 0x00, 0x02, 0x01, ///< src_addr
247246
0xC6, 0x33, 0x64, 0x01, ///< dst_addr
248247
0xC3, 0x50, ///< src_port
249248
0x01, 0xBB, ///< dst_port
250249
0x01, 0x00, 0x02, 0x68, 0x32, /// PP2_TYPE_ALPN (h2)
250+
0x02, 0x00, 0x03, 0x61, 0x62, 0x63 /// PP2_TYPE_AUTHORITY (abc)
251251
};
252252

253253
swoc::TextView tv(reinterpret_cast<char *>(raw_data), sizeof(raw_data));
@@ -262,6 +262,9 @@ TEST_CASE("PROXY Protocol v2 Parser", "[ProxyProtocol][ProxyProtocolv2]")
262262
CHECK(pp_info.ip_family == AF_INET);
263263
CHECK(pp_info.src_addr == src_addr);
264264
CHECK(pp_info.dst_addr == dst_addr);
265+
266+
CHECK(pp_info.tlv[PP2_TYPE_ALPN] == "h2");
267+
CHECK(pp_info.tlv[PP2_TYPE_AUTHORITY] == "abc");
265268
}
266269

267270
SECTION("Malformed Headers")

0 commit comments

Comments
 (0)