PROXY Protocol v1 Parser @return read length */
| 101 | @return read length |
| 102 | */ |
| 103 | size_t |
| 104 | proxy_protocol_v1_parse(ProxyProtocol *pp_info, swoc::TextView hdr) |
| 105 | { |
| 106 | ink_release_assert(hdr.size() >= PPv1_CONNECTION_HEADER_LEN_MIN); |
| 107 | |
| 108 | // Find the terminating newline |
| 109 | swoc::TextView::size_type pos = hdr.find('\n'); |
| 110 | if (pos == hdr.npos) { |
| 111 | Dbg(dbg_ctl_proxyprotocol_v1, "ssl_has_proxy_v1: LF not found"); |
| 112 | return 0; |
| 113 | } |
| 114 | |
| 115 | if (hdr[pos - 1] != '\r') { |
| 116 | Dbg(dbg_ctl_proxyprotocol_v1, "ssl_has_proxy_v1: CR not found"); |
| 117 | return 0; |
| 118 | } |
| 119 | |
| 120 | swoc::TextView token; |
| 121 | |
| 122 | // All the cases are special and sequence, might as well unroll them. |
| 123 | |
| 124 | // The header should begin with the PROXY preface |
| 125 | token = hdr.split_prefix_at(' '); |
| 126 | if (0 == token.size() || token != PPv1_CONNECTION_PREFACE) { |
| 127 | Dbg(dbg_ctl_proxyprotocol_v1, "proxy_protov1_parse: header [%.*s] does not start with preface [%.*s]", |
| 128 | static_cast<int>(hdr.size()), hdr.data(), static_cast<int>(PPv1_CONNECTION_PREFACE.size()), PPv1_CONNECTION_PREFACE.data()); |
| 129 | return 0; |
| 130 | } |
| 131 | Dbg(dbg_ctl_proxyprotocol_v1, "proxy_protov1_parse: [%.*s] = PREFACE", static_cast<int>(token.size()), token.data()); |
| 132 | |
| 133 | // The INET protocol family - TCP4, TCP6 or UNKNOWN |
| 134 | if (hdr.starts_with(PPv1_PROTO_UNKNOWN)) { |
| 135 | Dbg(dbg_ctl_proxyprotocol_v1, "proxy_protov1_parse: [UNKNOWN] = INET Family"); |
| 136 | |
| 137 | // Ignore anything presented before the CRLF |
| 138 | pp_info->version = ProxyProtocolVersion::V1; |
| 139 | |
| 140 | return pos + 1; |
| 141 | } else if (hdr.starts_with(PPv1_PROTO_TCP4)) { |
| 142 | token = hdr.split_prefix_at(' '); |
| 143 | if (0 == token.size()) { |
| 144 | return 0; |
| 145 | } |
| 146 | |
| 147 | pp_info->ip_family = AF_INET; |
| 148 | pp_info->type = SOCK_STREAM; |
| 149 | } else if (hdr.starts_with(PPv1_PROTO_TCP6)) { |
| 150 | token = hdr.split_prefix_at(' '); |
| 151 | if (0 == token.size()) { |
| 152 | return 0; |
| 153 | } |
| 154 | |
| 155 | pp_info->ip_family = AF_INET6; |
| 156 | pp_info->type = SOCK_STREAM; |
| 157 | } else { |
| 158 | return 0; |
| 159 | } |
| 160 | Dbg(dbg_ctl_proxyprotocol_v1, "proxy_protov1_parse: [%.*s] = INET Family", static_cast<int>(token.size()), token.data()); |
no test coverage detected