PROXY Protocol v2 Parser @return read length */
| 223 | @return read length |
| 224 | */ |
| 225 | size_t |
| 226 | proxy_protocol_v2_parse(ProxyProtocol *pp_info, const swoc::TextView &msg) |
| 227 | { |
| 228 | ink_release_assert(msg.size() >= PPv2_CONNECTION_HEADER_LEN); |
| 229 | |
| 230 | const PPv2Hdr *hdr_v2 = reinterpret_cast<const PPv2Hdr *>(msg.data()); |
| 231 | |
| 232 | // Assuming PREFACE check is done |
| 233 | |
| 234 | // length check |
| 235 | const uint16_t len = ntohs(hdr_v2->len); |
| 236 | const size_t total_len = PPv2_CONNECTION_HEADER_LEN + len; |
| 237 | uint16_t tlv_len = 0; |
| 238 | |
| 239 | if (msg.size() < total_len) { |
| 240 | Dbg(dbg_ctl_proxyprotocol_v2, "The amount of available data is smaller than the expected size"); |
| 241 | return 0; |
| 242 | } |
| 243 | |
| 244 | // protocol version and command |
| 245 | switch (hdr_v2->ver_cmd) { |
| 246 | case PPv2_CMD_LOCAL: { |
| 247 | // protocol byte should be UNSPEC (\x00) with LOCAL command |
| 248 | if (hdr_v2->fam != PPv2_PROTO_UNSPEC) { |
| 249 | Dbg(dbg_ctl_proxyprotocol_v2, "UNSPEC is unexpected"); |
| 250 | return 0; |
| 251 | } |
| 252 | |
| 253 | pp_info->version = ProxyProtocolVersion::V2; |
| 254 | pp_info->ip_family = AF_UNSPEC; |
| 255 | |
| 256 | return total_len; |
| 257 | } |
| 258 | case PPv2_CMD_PROXY: { |
| 259 | switch (hdr_v2->fam) { |
| 260 | case PPv2_PROTO_TCP4: |
| 261 | case PPv2_PROTO_UDP4: |
| 262 | if (len < PPv2_ADDR_LEN_INET) { |
| 263 | Dbg(dbg_ctl_proxyprotocol_v2, "There is not enough data left for IPv4 info"); |
| 264 | return 0; |
| 265 | } |
| 266 | tlv_len = len - PPv2_ADDR_LEN_INET; |
| 267 | |
| 268 | pp_info->set_ipv4_addrs(reinterpret_cast<in_addr_t>(hdr_v2->addr.ip4.src_addr), hdr_v2->addr.ip4.src_port, |
| 269 | reinterpret_cast<in_addr_t>(hdr_v2->addr.ip4.dst_addr), hdr_v2->addr.ip4.dst_port); |
| 270 | pp_info->type = hdr_v2->fam == PPv2_PROTO_TCP4 ? SOCK_STREAM : SOCK_DGRAM; |
| 271 | pp_info->version = ProxyProtocolVersion::V2; |
| 272 | |
| 273 | break; |
| 274 | case PPv2_PROTO_TCP6: |
| 275 | case PPv2_PROTO_UDP6: |
| 276 | if (len < PPv2_ADDR_LEN_INET6) { |
| 277 | Dbg(dbg_ctl_proxyprotocol_v2, "There is not enough data left for IPv6 info"); |
| 278 | return 0; |
| 279 | } |
| 280 | tlv_len = len - PPv2_ADDR_LEN_INET6; |
| 281 | |
| 282 | pp_info->set_ipv6_addrs(reinterpret_cast<in6_addr const &>(hdr_v2->addr.ip6.src_addr), hdr_v2->addr.ip6.src_port, |
no test coverage detected