12c593315Sopenharmony_ci/* 22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library 32c593315Sopenharmony_ci * 42c593315Sopenharmony_ci * Copyright (c) 2012 Tatsuhiro Tsujikawa 52c593315Sopenharmony_ci * 62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining 72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the 82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to 112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 122c593315Sopenharmony_ci * the following conditions: 132c593315Sopenharmony_ci * 142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be 152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software. 162c593315Sopenharmony_ci * 172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 242c593315Sopenharmony_ci */ 252c593315Sopenharmony_ci#include "shrpx_config.h" 262c593315Sopenharmony_ci 272c593315Sopenharmony_ci#ifdef HAVE_PWD_H 282c593315Sopenharmony_ci# include <pwd.h> 292c593315Sopenharmony_ci#endif // HAVE_PWD_H 302c593315Sopenharmony_ci#ifdef HAVE_NETDB_H 312c593315Sopenharmony_ci# include <netdb.h> 322c593315Sopenharmony_ci#endif // HAVE_NETDB_H 332c593315Sopenharmony_ci#ifdef HAVE_SYSLOG_H 342c593315Sopenharmony_ci# include <syslog.h> 352c593315Sopenharmony_ci#endif // HAVE_SYSLOG_H 362c593315Sopenharmony_ci#include <sys/types.h> 372c593315Sopenharmony_ci#include <sys/stat.h> 382c593315Sopenharmony_ci#ifdef HAVE_FCNTL_H 392c593315Sopenharmony_ci# include <fcntl.h> 402c593315Sopenharmony_ci#endif // HAVE_FCNTL_H 412c593315Sopenharmony_ci#ifdef HAVE_UNISTD_H 422c593315Sopenharmony_ci# include <unistd.h> 432c593315Sopenharmony_ci#endif // HAVE_UNISTD_H 442c593315Sopenharmony_ci#include <dirent.h> 452c593315Sopenharmony_ci 462c593315Sopenharmony_ci#include <cstring> 472c593315Sopenharmony_ci#include <cerrno> 482c593315Sopenharmony_ci#include <limits> 492c593315Sopenharmony_ci#include <fstream> 502c593315Sopenharmony_ci#include <unordered_map> 512c593315Sopenharmony_ci 522c593315Sopenharmony_ci#include <nghttp2/nghttp2.h> 532c593315Sopenharmony_ci 542c593315Sopenharmony_ci#include "url-parser/url_parser.h" 552c593315Sopenharmony_ci 562c593315Sopenharmony_ci#include "shrpx_log.h" 572c593315Sopenharmony_ci#include "shrpx_tls.h" 582c593315Sopenharmony_ci#include "shrpx_http.h" 592c593315Sopenharmony_ci#ifdef HAVE_MRUBY 602c593315Sopenharmony_ci# include "shrpx_mruby.h" 612c593315Sopenharmony_ci#endif // HAVE_MRUBY 622c593315Sopenharmony_ci#include "util.h" 632c593315Sopenharmony_ci#include "base64.h" 642c593315Sopenharmony_ci#include "ssl_compat.h" 652c593315Sopenharmony_ci#include "xsi_strerror.h" 662c593315Sopenharmony_ci 672c593315Sopenharmony_cinamespace shrpx { 682c593315Sopenharmony_ci 692c593315Sopenharmony_cinamespace { 702c593315Sopenharmony_ciConfig *config; 712c593315Sopenharmony_ci} // namespace 722c593315Sopenharmony_ci 732c593315Sopenharmony_ciconstexpr auto SHRPX_UNIX_PATH_PREFIX = StringRef::from_lit("unix:"); 742c593315Sopenharmony_ci 752c593315Sopenharmony_ciconst Config *get_config() { return config; } 762c593315Sopenharmony_ci 772c593315Sopenharmony_ciConfig *mod_config() { return config; } 782c593315Sopenharmony_ci 792c593315Sopenharmony_cistd::unique_ptr<Config> replace_config(std::unique_ptr<Config> another) { 802c593315Sopenharmony_ci auto p = config; 812c593315Sopenharmony_ci config = another.release(); 822c593315Sopenharmony_ci return std::unique_ptr<Config>(p); 832c593315Sopenharmony_ci} 842c593315Sopenharmony_ci 852c593315Sopenharmony_civoid create_config() { config = new Config(); } 862c593315Sopenharmony_ci 872c593315Sopenharmony_ciConfig::~Config() { 882c593315Sopenharmony_ci auto &upstreamconf = http2.upstream; 892c593315Sopenharmony_ci 902c593315Sopenharmony_ci nghttp2_option_del(upstreamconf.option); 912c593315Sopenharmony_ci nghttp2_option_del(upstreamconf.alt_mode_option); 922c593315Sopenharmony_ci nghttp2_session_callbacks_del(upstreamconf.callbacks); 932c593315Sopenharmony_ci 942c593315Sopenharmony_ci auto &downstreamconf = http2.downstream; 952c593315Sopenharmony_ci 962c593315Sopenharmony_ci nghttp2_option_del(downstreamconf.option); 972c593315Sopenharmony_ci nghttp2_session_callbacks_del(downstreamconf.callbacks); 982c593315Sopenharmony_ci 992c593315Sopenharmony_ci auto &dumpconf = http2.upstream.debug.dump; 1002c593315Sopenharmony_ci 1012c593315Sopenharmony_ci if (dumpconf.request_header) { 1022c593315Sopenharmony_ci fclose(dumpconf.request_header); 1032c593315Sopenharmony_ci } 1042c593315Sopenharmony_ci 1052c593315Sopenharmony_ci if (dumpconf.response_header) { 1062c593315Sopenharmony_ci fclose(dumpconf.response_header); 1072c593315Sopenharmony_ci } 1082c593315Sopenharmony_ci} 1092c593315Sopenharmony_ci 1102c593315Sopenharmony_ciTicketKeys::~TicketKeys() { 1112c593315Sopenharmony_ci /* Erase keys from memory */ 1122c593315Sopenharmony_ci for (auto &key : keys) { 1132c593315Sopenharmony_ci memset(&key, 0, sizeof(key)); 1142c593315Sopenharmony_ci } 1152c593315Sopenharmony_ci} 1162c593315Sopenharmony_ci 1172c593315Sopenharmony_cinamespace { 1182c593315Sopenharmony_ciint split_host_port(char *host, size_t hostlen, uint16_t *port_ptr, 1192c593315Sopenharmony_ci const StringRef &hostport, const StringRef &opt) { 1202c593315Sopenharmony_ci // host and port in |hostport| is separated by single ','. 1212c593315Sopenharmony_ci auto sep = std::find(std::begin(hostport), std::end(hostport), ','); 1222c593315Sopenharmony_ci if (sep == std::end(hostport)) { 1232c593315Sopenharmony_ci LOG(ERROR) << opt << ": Invalid host, port: " << hostport; 1242c593315Sopenharmony_ci return -1; 1252c593315Sopenharmony_ci } 1262c593315Sopenharmony_ci size_t len = sep - std::begin(hostport); 1272c593315Sopenharmony_ci if (hostlen < len + 1) { 1282c593315Sopenharmony_ci LOG(ERROR) << opt << ": Hostname too long: " << hostport; 1292c593315Sopenharmony_ci return -1; 1302c593315Sopenharmony_ci } 1312c593315Sopenharmony_ci std::copy(std::begin(hostport), sep, host); 1322c593315Sopenharmony_ci host[len] = '\0'; 1332c593315Sopenharmony_ci 1342c593315Sopenharmony_ci auto portstr = StringRef{sep + 1, std::end(hostport)}; 1352c593315Sopenharmony_ci auto d = util::parse_uint(portstr); 1362c593315Sopenharmony_ci if (1 <= d && d <= std::numeric_limits<uint16_t>::max()) { 1372c593315Sopenharmony_ci *port_ptr = d; 1382c593315Sopenharmony_ci return 0; 1392c593315Sopenharmony_ci } 1402c593315Sopenharmony_ci 1412c593315Sopenharmony_ci LOG(ERROR) << opt << ": Port is invalid: " << portstr; 1422c593315Sopenharmony_ci return -1; 1432c593315Sopenharmony_ci} 1442c593315Sopenharmony_ci} // namespace 1452c593315Sopenharmony_ci 1462c593315Sopenharmony_cinamespace { 1472c593315Sopenharmony_cibool is_secure(const StringRef &filename) { 1482c593315Sopenharmony_ci struct stat buf; 1492c593315Sopenharmony_ci int rv = stat(filename.c_str(), &buf); 1502c593315Sopenharmony_ci if (rv == 0) { 1512c593315Sopenharmony_ci if ((buf.st_mode & S_IRWXU) && !(buf.st_mode & S_IRWXG) && 1522c593315Sopenharmony_ci !(buf.st_mode & S_IRWXO)) { 1532c593315Sopenharmony_ci return true; 1542c593315Sopenharmony_ci } 1552c593315Sopenharmony_ci } 1562c593315Sopenharmony_ci 1572c593315Sopenharmony_ci return false; 1582c593315Sopenharmony_ci} 1592c593315Sopenharmony_ci} // namespace 1602c593315Sopenharmony_ci 1612c593315Sopenharmony_cistd::unique_ptr<TicketKeys> 1622c593315Sopenharmony_ciread_tls_ticket_key_file(const std::vector<StringRef> &files, 1632c593315Sopenharmony_ci const EVP_CIPHER *cipher, const EVP_MD *hmac) { 1642c593315Sopenharmony_ci auto ticket_keys = std::make_unique<TicketKeys>(); 1652c593315Sopenharmony_ci auto &keys = ticket_keys->keys; 1662c593315Sopenharmony_ci keys.resize(files.size()); 1672c593315Sopenharmony_ci auto enc_keylen = EVP_CIPHER_key_length(cipher); 1682c593315Sopenharmony_ci auto hmac_keylen = EVP_MD_size(hmac); 1692c593315Sopenharmony_ci if (cipher == EVP_aes_128_cbc()) { 1702c593315Sopenharmony_ci // backward compatibility, as a legacy of using same file format 1712c593315Sopenharmony_ci // with nginx and apache. 1722c593315Sopenharmony_ci hmac_keylen = 16; 1732c593315Sopenharmony_ci } 1742c593315Sopenharmony_ci auto expectedlen = keys[0].data.name.size() + enc_keylen + hmac_keylen; 1752c593315Sopenharmony_ci char buf[256]; 1762c593315Sopenharmony_ci assert(sizeof(buf) >= expectedlen); 1772c593315Sopenharmony_ci 1782c593315Sopenharmony_ci size_t i = 0; 1792c593315Sopenharmony_ci for (auto &file : files) { 1802c593315Sopenharmony_ci struct stat fst {}; 1812c593315Sopenharmony_ci 1822c593315Sopenharmony_ci if (stat(file.c_str(), &fst) == -1) { 1832c593315Sopenharmony_ci auto error = errno; 1842c593315Sopenharmony_ci LOG(ERROR) << "tls-ticket-key-file: could not stat file " << file 1852c593315Sopenharmony_ci << ", errno=" << error; 1862c593315Sopenharmony_ci return nullptr; 1872c593315Sopenharmony_ci } 1882c593315Sopenharmony_ci 1892c593315Sopenharmony_ci if (static_cast<size_t>(fst.st_size) != expectedlen) { 1902c593315Sopenharmony_ci LOG(ERROR) << "tls-ticket-key-file: the expected file size is " 1912c593315Sopenharmony_ci << expectedlen << ", the actual file size is " << fst.st_size; 1922c593315Sopenharmony_ci return nullptr; 1932c593315Sopenharmony_ci } 1942c593315Sopenharmony_ci 1952c593315Sopenharmony_ci std::ifstream f(file.c_str()); 1962c593315Sopenharmony_ci if (!f) { 1972c593315Sopenharmony_ci LOG(ERROR) << "tls-ticket-key-file: could not open file " << file; 1982c593315Sopenharmony_ci return nullptr; 1992c593315Sopenharmony_ci } 2002c593315Sopenharmony_ci 2012c593315Sopenharmony_ci f.read(buf, expectedlen); 2022c593315Sopenharmony_ci if (static_cast<size_t>(f.gcount()) != expectedlen) { 2032c593315Sopenharmony_ci LOG(ERROR) << "tls-ticket-key-file: want to read " << expectedlen 2042c593315Sopenharmony_ci << " bytes but only read " << f.gcount() << " bytes from " 2052c593315Sopenharmony_ci << file; 2062c593315Sopenharmony_ci return nullptr; 2072c593315Sopenharmony_ci } 2082c593315Sopenharmony_ci 2092c593315Sopenharmony_ci auto &key = keys[i++]; 2102c593315Sopenharmony_ci key.cipher = cipher; 2112c593315Sopenharmony_ci key.hmac = hmac; 2122c593315Sopenharmony_ci key.hmac_keylen = hmac_keylen; 2132c593315Sopenharmony_ci 2142c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 2152c593315Sopenharmony_ci LOG(INFO) << "enc_keylen=" << enc_keylen 2162c593315Sopenharmony_ci << ", hmac_keylen=" << key.hmac_keylen; 2172c593315Sopenharmony_ci } 2182c593315Sopenharmony_ci 2192c593315Sopenharmony_ci auto p = buf; 2202c593315Sopenharmony_ci std::copy_n(p, key.data.name.size(), std::begin(key.data.name)); 2212c593315Sopenharmony_ci p += key.data.name.size(); 2222c593315Sopenharmony_ci std::copy_n(p, enc_keylen, std::begin(key.data.enc_key)); 2232c593315Sopenharmony_ci p += enc_keylen; 2242c593315Sopenharmony_ci std::copy_n(p, hmac_keylen, std::begin(key.data.hmac_key)); 2252c593315Sopenharmony_ci 2262c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 2272c593315Sopenharmony_ci LOG(INFO) << "session ticket key: " << util::format_hex(key.data.name); 2282c593315Sopenharmony_ci } 2292c593315Sopenharmony_ci } 2302c593315Sopenharmony_ci return ticket_keys; 2312c593315Sopenharmony_ci} 2322c593315Sopenharmony_ci 2332c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 2342c593315Sopenharmony_cistd::shared_ptr<QUICKeyingMaterials> 2352c593315Sopenharmony_ciread_quic_secret_file(const StringRef &path) { 2362c593315Sopenharmony_ci constexpr size_t expectedlen = 2372c593315Sopenharmony_ci SHRPX_QUIC_SECRET_RESERVEDLEN + SHRPX_QUIC_SECRETLEN + SHRPX_QUIC_SALTLEN; 2382c593315Sopenharmony_ci 2392c593315Sopenharmony_ci auto qkms = std::make_shared<QUICKeyingMaterials>(); 2402c593315Sopenharmony_ci auto &kms = qkms->keying_materials; 2412c593315Sopenharmony_ci 2422c593315Sopenharmony_ci std::ifstream f(path.c_str()); 2432c593315Sopenharmony_ci if (!f) { 2442c593315Sopenharmony_ci LOG(ERROR) << "frontend-quic-secret-file: could not open file " << path; 2452c593315Sopenharmony_ci return nullptr; 2462c593315Sopenharmony_ci } 2472c593315Sopenharmony_ci 2482c593315Sopenharmony_ci std::array<char, 4096> buf; 2492c593315Sopenharmony_ci 2502c593315Sopenharmony_ci while (f.getline(buf.data(), buf.size())) { 2512c593315Sopenharmony_ci auto len = strlen(buf.data()); 2522c593315Sopenharmony_ci if (len == 0 || buf[0] == '#') { 2532c593315Sopenharmony_ci continue; 2542c593315Sopenharmony_ci } 2552c593315Sopenharmony_ci 2562c593315Sopenharmony_ci auto s = StringRef{std::begin(buf), std::begin(buf) + len}; 2572c593315Sopenharmony_ci if (s.size() != expectedlen * 2 || !util::is_hex_string(s)) { 2582c593315Sopenharmony_ci LOG(ERROR) << "frontend-quic-secret-file: each line must be a " 2592c593315Sopenharmony_ci << expectedlen * 2 << " bytes hex encoded string"; 2602c593315Sopenharmony_ci return nullptr; 2612c593315Sopenharmony_ci } 2622c593315Sopenharmony_ci 2632c593315Sopenharmony_ci kms.emplace_back(); 2642c593315Sopenharmony_ci auto &qkm = kms.back(); 2652c593315Sopenharmony_ci 2662c593315Sopenharmony_ci auto p = std::begin(s); 2672c593315Sopenharmony_ci 2682c593315Sopenharmony_ci util::decode_hex(std::begin(qkm.reserved), 2692c593315Sopenharmony_ci StringRef{p, p + qkm.reserved.size()}); 2702c593315Sopenharmony_ci p += qkm.reserved.size() * 2; 2712c593315Sopenharmony_ci util::decode_hex(std::begin(qkm.secret), 2722c593315Sopenharmony_ci StringRef{p, p + qkm.secret.size()}); 2732c593315Sopenharmony_ci p += qkm.secret.size() * 2; 2742c593315Sopenharmony_ci util::decode_hex(std::begin(qkm.salt), StringRef{p, p + qkm.salt.size()}); 2752c593315Sopenharmony_ci p += qkm.salt.size() * 2; 2762c593315Sopenharmony_ci 2772c593315Sopenharmony_ci assert(static_cast<size_t>(p - std::begin(s)) == expectedlen * 2); 2782c593315Sopenharmony_ci 2792c593315Sopenharmony_ci qkm.id = qkm.reserved[0] & 0xc0; 2802c593315Sopenharmony_ci 2812c593315Sopenharmony_ci if (kms.size() == 4) { 2822c593315Sopenharmony_ci break; 2832c593315Sopenharmony_ci } 2842c593315Sopenharmony_ci } 2852c593315Sopenharmony_ci 2862c593315Sopenharmony_ci if (f.bad() || (!f.eof() && f.fail())) { 2872c593315Sopenharmony_ci LOG(ERROR) 2882c593315Sopenharmony_ci << "frontend-quic-secret-file: error occurred while reading file " 2892c593315Sopenharmony_ci << path; 2902c593315Sopenharmony_ci return nullptr; 2912c593315Sopenharmony_ci } 2922c593315Sopenharmony_ci 2932c593315Sopenharmony_ci if (kms.empty()) { 2942c593315Sopenharmony_ci LOG(WARN) 2952c593315Sopenharmony_ci << "frontend-quic-secret-file: no keying materials are present in file " 2962c593315Sopenharmony_ci << path; 2972c593315Sopenharmony_ci return nullptr; 2982c593315Sopenharmony_ci } 2992c593315Sopenharmony_ci 3002c593315Sopenharmony_ci return qkms; 3012c593315Sopenharmony_ci} 3022c593315Sopenharmony_ci#endif // ENABLE_HTTP3 3032c593315Sopenharmony_ci 3042c593315Sopenharmony_ciFILE *open_file_for_write(const char *filename) { 3052c593315Sopenharmony_ci std::array<char, STRERROR_BUFSIZE> errbuf; 3062c593315Sopenharmony_ci 3072c593315Sopenharmony_ci#ifdef O_CLOEXEC 3082c593315Sopenharmony_ci auto fd = open(filename, O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC, 3092c593315Sopenharmony_ci S_IRUSR | S_IWUSR); 3102c593315Sopenharmony_ci#else 3112c593315Sopenharmony_ci auto fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 3122c593315Sopenharmony_ci 3132c593315Sopenharmony_ci // We get race condition if execve is called at the same time. 3142c593315Sopenharmony_ci if (fd != -1) { 3152c593315Sopenharmony_ci util::make_socket_closeonexec(fd); 3162c593315Sopenharmony_ci } 3172c593315Sopenharmony_ci#endif 3182c593315Sopenharmony_ci if (fd == -1) { 3192c593315Sopenharmony_ci auto error = errno; 3202c593315Sopenharmony_ci LOG(ERROR) << "Failed to open " << filename << " for writing. Cause: " 3212c593315Sopenharmony_ci << xsi_strerror(error, errbuf.data(), errbuf.size()); 3222c593315Sopenharmony_ci return nullptr; 3232c593315Sopenharmony_ci } 3242c593315Sopenharmony_ci auto f = fdopen(fd, "wb"); 3252c593315Sopenharmony_ci if (f == nullptr) { 3262c593315Sopenharmony_ci auto error = errno; 3272c593315Sopenharmony_ci LOG(ERROR) << "Failed to open " << filename << " for writing. Cause: " 3282c593315Sopenharmony_ci << xsi_strerror(error, errbuf.data(), errbuf.size()); 3292c593315Sopenharmony_ci return nullptr; 3302c593315Sopenharmony_ci } 3312c593315Sopenharmony_ci 3322c593315Sopenharmony_ci return f; 3332c593315Sopenharmony_ci} 3342c593315Sopenharmony_ci 3352c593315Sopenharmony_cinamespace { 3362c593315Sopenharmony_ci// Read passwd from |filename| 3372c593315Sopenharmony_cistd::string read_passwd_from_file(const StringRef &opt, 3382c593315Sopenharmony_ci const StringRef &filename) { 3392c593315Sopenharmony_ci std::string line; 3402c593315Sopenharmony_ci 3412c593315Sopenharmony_ci if (!is_secure(filename)) { 3422c593315Sopenharmony_ci LOG(ERROR) << opt << ": Private key passwd file " << filename 3432c593315Sopenharmony_ci << " has insecure mode."; 3442c593315Sopenharmony_ci return line; 3452c593315Sopenharmony_ci } 3462c593315Sopenharmony_ci 3472c593315Sopenharmony_ci std::ifstream in(filename.c_str(), std::ios::binary); 3482c593315Sopenharmony_ci if (!in) { 3492c593315Sopenharmony_ci LOG(ERROR) << opt << ": Could not open key passwd file " << filename; 3502c593315Sopenharmony_ci return line; 3512c593315Sopenharmony_ci } 3522c593315Sopenharmony_ci 3532c593315Sopenharmony_ci std::getline(in, line); 3542c593315Sopenharmony_ci return line; 3552c593315Sopenharmony_ci} 3562c593315Sopenharmony_ci} // namespace 3572c593315Sopenharmony_ci 3582c593315Sopenharmony_ciHeaderRefs::value_type parse_header(BlockAllocator &balloc, 3592c593315Sopenharmony_ci const StringRef &optarg) { 3602c593315Sopenharmony_ci auto colon = std::find(std::begin(optarg), std::end(optarg), ':'); 3612c593315Sopenharmony_ci 3622c593315Sopenharmony_ci if (colon == std::end(optarg) || colon == std::begin(optarg)) { 3632c593315Sopenharmony_ci return {}; 3642c593315Sopenharmony_ci } 3652c593315Sopenharmony_ci 3662c593315Sopenharmony_ci auto value = colon + 1; 3672c593315Sopenharmony_ci for (; *value == '\t' || *value == ' '; ++value) 3682c593315Sopenharmony_ci ; 3692c593315Sopenharmony_ci 3702c593315Sopenharmony_ci auto name_iov = 3712c593315Sopenharmony_ci make_byte_ref(balloc, std::distance(std::begin(optarg), colon) + 1); 3722c593315Sopenharmony_ci auto p = name_iov.base; 3732c593315Sopenharmony_ci p = std::copy(std::begin(optarg), colon, p); 3742c593315Sopenharmony_ci util::inp_strlower(name_iov.base, p); 3752c593315Sopenharmony_ci *p = '\0'; 3762c593315Sopenharmony_ci 3772c593315Sopenharmony_ci auto nv = 3782c593315Sopenharmony_ci HeaderRef(StringRef{name_iov.base, p}, 3792c593315Sopenharmony_ci make_string_ref(balloc, StringRef{value, std::end(optarg)})); 3802c593315Sopenharmony_ci 3812c593315Sopenharmony_ci if (!nghttp2_check_header_name(nv.name.byte(), nv.name.size()) || 3822c593315Sopenharmony_ci !nghttp2_check_header_value_rfc9113(nv.value.byte(), nv.value.size())) { 3832c593315Sopenharmony_ci return {}; 3842c593315Sopenharmony_ci } 3852c593315Sopenharmony_ci 3862c593315Sopenharmony_ci return nv; 3872c593315Sopenharmony_ci} 3882c593315Sopenharmony_ci 3892c593315Sopenharmony_citemplate <typename T> 3902c593315Sopenharmony_ciint parse_uint(T *dest, const StringRef &opt, const StringRef &optarg) { 3912c593315Sopenharmony_ci auto val = util::parse_uint(optarg); 3922c593315Sopenharmony_ci if (val == -1) { 3932c593315Sopenharmony_ci LOG(ERROR) << opt << ": bad value. Specify an integer >= 0."; 3942c593315Sopenharmony_ci return -1; 3952c593315Sopenharmony_ci } 3962c593315Sopenharmony_ci 3972c593315Sopenharmony_ci *dest = val; 3982c593315Sopenharmony_ci 3992c593315Sopenharmony_ci return 0; 4002c593315Sopenharmony_ci} 4012c593315Sopenharmony_ci 4022c593315Sopenharmony_cinamespace { 4032c593315Sopenharmony_citemplate <typename T> 4042c593315Sopenharmony_ciint parse_uint_with_unit(T *dest, const StringRef &opt, 4052c593315Sopenharmony_ci const StringRef &optarg) { 4062c593315Sopenharmony_ci auto n = util::parse_uint_with_unit(optarg); 4072c593315Sopenharmony_ci if (n == -1) { 4082c593315Sopenharmony_ci LOG(ERROR) << opt << ": bad value: '" << optarg << "'"; 4092c593315Sopenharmony_ci return -1; 4102c593315Sopenharmony_ci } 4112c593315Sopenharmony_ci 4122c593315Sopenharmony_ci if (static_cast<uint64_t>(std::numeric_limits<T>::max()) < 4132c593315Sopenharmony_ci static_cast<uint64_t>(n)) { 4142c593315Sopenharmony_ci LOG(ERROR) << opt 4152c593315Sopenharmony_ci << ": too large. The value should be less than or equal to " 4162c593315Sopenharmony_ci << std::numeric_limits<T>::max(); 4172c593315Sopenharmony_ci return -1; 4182c593315Sopenharmony_ci } 4192c593315Sopenharmony_ci 4202c593315Sopenharmony_ci *dest = n; 4212c593315Sopenharmony_ci 4222c593315Sopenharmony_ci return 0; 4232c593315Sopenharmony_ci} 4242c593315Sopenharmony_ci} // namespace 4252c593315Sopenharmony_ci 4262c593315Sopenharmony_cinamespace { 4272c593315Sopenharmony_ciint parse_altsvc(AltSvc &altsvc, const StringRef &opt, 4282c593315Sopenharmony_ci const StringRef &optarg) { 4292c593315Sopenharmony_ci // PROTOID, PORT, HOST, ORIGIN, PARAMS. 4302c593315Sopenharmony_ci auto tokens = util::split_str(optarg, ',', 5); 4312c593315Sopenharmony_ci 4322c593315Sopenharmony_ci if (tokens.size() < 2) { 4332c593315Sopenharmony_ci // Requires at least protocol_id and port 4342c593315Sopenharmony_ci LOG(ERROR) << opt << ": too few parameters: " << optarg; 4352c593315Sopenharmony_ci return -1; 4362c593315Sopenharmony_ci } 4372c593315Sopenharmony_ci 4382c593315Sopenharmony_ci int port; 4392c593315Sopenharmony_ci 4402c593315Sopenharmony_ci if (parse_uint(&port, opt, tokens[1]) != 0) { 4412c593315Sopenharmony_ci return -1; 4422c593315Sopenharmony_ci } 4432c593315Sopenharmony_ci 4442c593315Sopenharmony_ci if (port < 1 || 4452c593315Sopenharmony_ci port > static_cast<int>(std::numeric_limits<uint16_t>::max())) { 4462c593315Sopenharmony_ci LOG(ERROR) << opt << ": port is invalid: " << tokens[1]; 4472c593315Sopenharmony_ci return -1; 4482c593315Sopenharmony_ci } 4492c593315Sopenharmony_ci 4502c593315Sopenharmony_ci altsvc.protocol_id = make_string_ref(config->balloc, tokens[0]); 4512c593315Sopenharmony_ci 4522c593315Sopenharmony_ci altsvc.port = port; 4532c593315Sopenharmony_ci altsvc.service = make_string_ref(config->balloc, tokens[1]); 4542c593315Sopenharmony_ci 4552c593315Sopenharmony_ci if (tokens.size() > 2) { 4562c593315Sopenharmony_ci if (!tokens[2].empty()) { 4572c593315Sopenharmony_ci altsvc.host = make_string_ref(config->balloc, tokens[2]); 4582c593315Sopenharmony_ci } 4592c593315Sopenharmony_ci 4602c593315Sopenharmony_ci if (tokens.size() > 3) { 4612c593315Sopenharmony_ci if (!tokens[3].empty()) { 4622c593315Sopenharmony_ci altsvc.origin = make_string_ref(config->balloc, tokens[3]); 4632c593315Sopenharmony_ci } 4642c593315Sopenharmony_ci 4652c593315Sopenharmony_ci if (tokens.size() > 4) { 4662c593315Sopenharmony_ci if (!tokens[4].empty()) { 4672c593315Sopenharmony_ci altsvc.params = make_string_ref(config->balloc, tokens[4]); 4682c593315Sopenharmony_ci } 4692c593315Sopenharmony_ci } 4702c593315Sopenharmony_ci } 4712c593315Sopenharmony_ci } 4722c593315Sopenharmony_ci 4732c593315Sopenharmony_ci return 0; 4742c593315Sopenharmony_ci} 4752c593315Sopenharmony_ci} // namespace 4762c593315Sopenharmony_ci 4772c593315Sopenharmony_cinamespace { 4782c593315Sopenharmony_ci// generated by gennghttpxfun.py 4792c593315Sopenharmony_ciLogFragmentType log_var_lookup_token(const char *name, size_t namelen) { 4802c593315Sopenharmony_ci switch (namelen) { 4812c593315Sopenharmony_ci case 3: 4822c593315Sopenharmony_ci switch (name[2]) { 4832c593315Sopenharmony_ci case 'd': 4842c593315Sopenharmony_ci if (util::strieq_l("pi", name, 2)) { 4852c593315Sopenharmony_ci return LogFragmentType::PID; 4862c593315Sopenharmony_ci } 4872c593315Sopenharmony_ci break; 4882c593315Sopenharmony_ci } 4892c593315Sopenharmony_ci break; 4902c593315Sopenharmony_ci case 4: 4912c593315Sopenharmony_ci switch (name[3]) { 4922c593315Sopenharmony_ci case 'h': 4932c593315Sopenharmony_ci if (util::strieq_l("pat", name, 3)) { 4942c593315Sopenharmony_ci return LogFragmentType::PATH; 4952c593315Sopenharmony_ci } 4962c593315Sopenharmony_ci break; 4972c593315Sopenharmony_ci case 'n': 4982c593315Sopenharmony_ci if (util::strieq_l("alp", name, 3)) { 4992c593315Sopenharmony_ci return LogFragmentType::ALPN; 5002c593315Sopenharmony_ci } 5012c593315Sopenharmony_ci break; 5022c593315Sopenharmony_ci } 5032c593315Sopenharmony_ci break; 5042c593315Sopenharmony_ci case 6: 5052c593315Sopenharmony_ci switch (name[5]) { 5062c593315Sopenharmony_ci case 'd': 5072c593315Sopenharmony_ci if (util::strieq_l("metho", name, 5)) { 5082c593315Sopenharmony_ci return LogFragmentType::METHOD; 5092c593315Sopenharmony_ci } 5102c593315Sopenharmony_ci break; 5112c593315Sopenharmony_ci case 's': 5122c593315Sopenharmony_ci if (util::strieq_l("statu", name, 5)) { 5132c593315Sopenharmony_ci return LogFragmentType::STATUS; 5142c593315Sopenharmony_ci } 5152c593315Sopenharmony_ci break; 5162c593315Sopenharmony_ci } 5172c593315Sopenharmony_ci break; 5182c593315Sopenharmony_ci case 7: 5192c593315Sopenharmony_ci switch (name[6]) { 5202c593315Sopenharmony_ci case 'i': 5212c593315Sopenharmony_ci if (util::strieq_l("tls_sn", name, 6)) { 5222c593315Sopenharmony_ci return LogFragmentType::TLS_SNI; 5232c593315Sopenharmony_ci } 5242c593315Sopenharmony_ci break; 5252c593315Sopenharmony_ci case 't': 5262c593315Sopenharmony_ci if (util::strieq_l("reques", name, 6)) { 5272c593315Sopenharmony_ci return LogFragmentType::REQUEST; 5282c593315Sopenharmony_ci } 5292c593315Sopenharmony_ci break; 5302c593315Sopenharmony_ci } 5312c593315Sopenharmony_ci break; 5322c593315Sopenharmony_ci case 10: 5332c593315Sopenharmony_ci switch (name[9]) { 5342c593315Sopenharmony_ci case 'l': 5352c593315Sopenharmony_ci if (util::strieq_l("time_loca", name, 9)) { 5362c593315Sopenharmony_ci return LogFragmentType::TIME_LOCAL; 5372c593315Sopenharmony_ci } 5382c593315Sopenharmony_ci break; 5392c593315Sopenharmony_ci case 'r': 5402c593315Sopenharmony_ci if (util::strieq_l("ssl_ciphe", name, 9)) { 5412c593315Sopenharmony_ci return LogFragmentType::SSL_CIPHER; 5422c593315Sopenharmony_ci } 5432c593315Sopenharmony_ci if (util::strieq_l("tls_ciphe", name, 9)) { 5442c593315Sopenharmony_ci return LogFragmentType::TLS_CIPHER; 5452c593315Sopenharmony_ci } 5462c593315Sopenharmony_ci break; 5472c593315Sopenharmony_ci } 5482c593315Sopenharmony_ci break; 5492c593315Sopenharmony_ci case 11: 5502c593315Sopenharmony_ci switch (name[10]) { 5512c593315Sopenharmony_ci case 'r': 5522c593315Sopenharmony_ci if (util::strieq_l("remote_add", name, 10)) { 5532c593315Sopenharmony_ci return LogFragmentType::REMOTE_ADDR; 5542c593315Sopenharmony_ci } 5552c593315Sopenharmony_ci break; 5562c593315Sopenharmony_ci case 't': 5572c593315Sopenharmony_ci if (util::strieq_l("remote_por", name, 10)) { 5582c593315Sopenharmony_ci return LogFragmentType::REMOTE_PORT; 5592c593315Sopenharmony_ci } 5602c593315Sopenharmony_ci if (util::strieq_l("server_por", name, 10)) { 5612c593315Sopenharmony_ci return LogFragmentType::SERVER_PORT; 5622c593315Sopenharmony_ci } 5632c593315Sopenharmony_ci break; 5642c593315Sopenharmony_ci } 5652c593315Sopenharmony_ci break; 5662c593315Sopenharmony_ci case 12: 5672c593315Sopenharmony_ci switch (name[11]) { 5682c593315Sopenharmony_ci case '1': 5692c593315Sopenharmony_ci if (util::strieq_l("time_iso860", name, 11)) { 5702c593315Sopenharmony_ci return LogFragmentType::TIME_ISO8601; 5712c593315Sopenharmony_ci } 5722c593315Sopenharmony_ci break; 5732c593315Sopenharmony_ci case 'e': 5742c593315Sopenharmony_ci if (util::strieq_l("request_tim", name, 11)) { 5752c593315Sopenharmony_ci return LogFragmentType::REQUEST_TIME; 5762c593315Sopenharmony_ci } 5772c593315Sopenharmony_ci break; 5782c593315Sopenharmony_ci case 'l': 5792c593315Sopenharmony_ci if (util::strieq_l("ssl_protoco", name, 11)) { 5802c593315Sopenharmony_ci return LogFragmentType::SSL_PROTOCOL; 5812c593315Sopenharmony_ci } 5822c593315Sopenharmony_ci if (util::strieq_l("tls_protoco", name, 11)) { 5832c593315Sopenharmony_ci return LogFragmentType::TLS_PROTOCOL; 5842c593315Sopenharmony_ci } 5852c593315Sopenharmony_ci break; 5862c593315Sopenharmony_ci case 't': 5872c593315Sopenharmony_ci if (util::strieq_l("backend_hos", name, 11)) { 5882c593315Sopenharmony_ci return LogFragmentType::BACKEND_HOST; 5892c593315Sopenharmony_ci } 5902c593315Sopenharmony_ci if (util::strieq_l("backend_por", name, 11)) { 5912c593315Sopenharmony_ci return LogFragmentType::BACKEND_PORT; 5922c593315Sopenharmony_ci } 5932c593315Sopenharmony_ci break; 5942c593315Sopenharmony_ci } 5952c593315Sopenharmony_ci break; 5962c593315Sopenharmony_ci case 14: 5972c593315Sopenharmony_ci switch (name[13]) { 5982c593315Sopenharmony_ci case 'd': 5992c593315Sopenharmony_ci if (util::strieq_l("ssl_session_i", name, 13)) { 6002c593315Sopenharmony_ci return LogFragmentType::SSL_SESSION_ID; 6012c593315Sopenharmony_ci } 6022c593315Sopenharmony_ci if (util::strieq_l("tls_session_i", name, 13)) { 6032c593315Sopenharmony_ci return LogFragmentType::TLS_SESSION_ID; 6042c593315Sopenharmony_ci } 6052c593315Sopenharmony_ci break; 6062c593315Sopenharmony_ci } 6072c593315Sopenharmony_ci break; 6082c593315Sopenharmony_ci case 15: 6092c593315Sopenharmony_ci switch (name[14]) { 6102c593315Sopenharmony_ci case 't': 6112c593315Sopenharmony_ci if (util::strieq_l("body_bytes_sen", name, 14)) { 6122c593315Sopenharmony_ci return LogFragmentType::BODY_BYTES_SENT; 6132c593315Sopenharmony_ci } 6142c593315Sopenharmony_ci break; 6152c593315Sopenharmony_ci } 6162c593315Sopenharmony_ci break; 6172c593315Sopenharmony_ci case 16: 6182c593315Sopenharmony_ci switch (name[15]) { 6192c593315Sopenharmony_ci case 'n': 6202c593315Sopenharmony_ci if (util::strieq_l("protocol_versio", name, 15)) { 6212c593315Sopenharmony_ci return LogFragmentType::PROTOCOL_VERSION; 6222c593315Sopenharmony_ci } 6232c593315Sopenharmony_ci break; 6242c593315Sopenharmony_ci } 6252c593315Sopenharmony_ci break; 6262c593315Sopenharmony_ci case 17: 6272c593315Sopenharmony_ci switch (name[16]) { 6282c593315Sopenharmony_ci case 'l': 6292c593315Sopenharmony_ci if (util::strieq_l("tls_client_seria", name, 16)) { 6302c593315Sopenharmony_ci return LogFragmentType::TLS_CLIENT_SERIAL; 6312c593315Sopenharmony_ci } 6322c593315Sopenharmony_ci break; 6332c593315Sopenharmony_ci } 6342c593315Sopenharmony_ci break; 6352c593315Sopenharmony_ci case 18: 6362c593315Sopenharmony_ci switch (name[17]) { 6372c593315Sopenharmony_ci case 'd': 6382c593315Sopenharmony_ci if (util::strieq_l("ssl_session_reuse", name, 17)) { 6392c593315Sopenharmony_ci return LogFragmentType::SSL_SESSION_REUSED; 6402c593315Sopenharmony_ci } 6412c593315Sopenharmony_ci if (util::strieq_l("tls_session_reuse", name, 17)) { 6422c593315Sopenharmony_ci return LogFragmentType::TLS_SESSION_REUSED; 6432c593315Sopenharmony_ci } 6442c593315Sopenharmony_ci break; 6452c593315Sopenharmony_ci case 'y': 6462c593315Sopenharmony_ci if (util::strieq_l("path_without_quer", name, 17)) { 6472c593315Sopenharmony_ci return LogFragmentType::PATH_WITHOUT_QUERY; 6482c593315Sopenharmony_ci } 6492c593315Sopenharmony_ci break; 6502c593315Sopenharmony_ci } 6512c593315Sopenharmony_ci break; 6522c593315Sopenharmony_ci case 22: 6532c593315Sopenharmony_ci switch (name[21]) { 6542c593315Sopenharmony_ci case 'e': 6552c593315Sopenharmony_ci if (util::strieq_l("tls_client_issuer_nam", name, 21)) { 6562c593315Sopenharmony_ci return LogFragmentType::TLS_CLIENT_ISSUER_NAME; 6572c593315Sopenharmony_ci } 6582c593315Sopenharmony_ci break; 6592c593315Sopenharmony_ci } 6602c593315Sopenharmony_ci break; 6612c593315Sopenharmony_ci case 23: 6622c593315Sopenharmony_ci switch (name[22]) { 6632c593315Sopenharmony_ci case 'e': 6642c593315Sopenharmony_ci if (util::strieq_l("tls_client_subject_nam", name, 22)) { 6652c593315Sopenharmony_ci return LogFragmentType::TLS_CLIENT_SUBJECT_NAME; 6662c593315Sopenharmony_ci } 6672c593315Sopenharmony_ci break; 6682c593315Sopenharmony_ci } 6692c593315Sopenharmony_ci break; 6702c593315Sopenharmony_ci case 27: 6712c593315Sopenharmony_ci switch (name[26]) { 6722c593315Sopenharmony_ci case '1': 6732c593315Sopenharmony_ci if (util::strieq_l("tls_client_fingerprint_sha", name, 26)) { 6742c593315Sopenharmony_ci return LogFragmentType::TLS_CLIENT_FINGERPRINT_SHA1; 6752c593315Sopenharmony_ci } 6762c593315Sopenharmony_ci break; 6772c593315Sopenharmony_ci } 6782c593315Sopenharmony_ci break; 6792c593315Sopenharmony_ci case 29: 6802c593315Sopenharmony_ci switch (name[28]) { 6812c593315Sopenharmony_ci case '6': 6822c593315Sopenharmony_ci if (util::strieq_l("tls_client_fingerprint_sha25", name, 28)) { 6832c593315Sopenharmony_ci return LogFragmentType::TLS_CLIENT_FINGERPRINT_SHA256; 6842c593315Sopenharmony_ci } 6852c593315Sopenharmony_ci break; 6862c593315Sopenharmony_ci } 6872c593315Sopenharmony_ci break; 6882c593315Sopenharmony_ci } 6892c593315Sopenharmony_ci return LogFragmentType::NONE; 6902c593315Sopenharmony_ci} 6912c593315Sopenharmony_ci} // namespace 6922c593315Sopenharmony_ci 6932c593315Sopenharmony_cinamespace { 6942c593315Sopenharmony_cibool var_token(char c) { 6952c593315Sopenharmony_ci return util::is_alpha(c) || util::is_digit(c) || c == '_'; 6962c593315Sopenharmony_ci} 6972c593315Sopenharmony_ci} // namespace 6982c593315Sopenharmony_ci 6992c593315Sopenharmony_cistd::vector<LogFragment> parse_log_format(BlockAllocator &balloc, 7002c593315Sopenharmony_ci const StringRef &optarg) { 7012c593315Sopenharmony_ci auto literal_start = std::begin(optarg); 7022c593315Sopenharmony_ci auto p = literal_start; 7032c593315Sopenharmony_ci auto eop = std::end(optarg); 7042c593315Sopenharmony_ci 7052c593315Sopenharmony_ci auto res = std::vector<LogFragment>(); 7062c593315Sopenharmony_ci 7072c593315Sopenharmony_ci for (; p != eop;) { 7082c593315Sopenharmony_ci if (*p != '$') { 7092c593315Sopenharmony_ci ++p; 7102c593315Sopenharmony_ci continue; 7112c593315Sopenharmony_ci } 7122c593315Sopenharmony_ci 7132c593315Sopenharmony_ci auto var_start = p; 7142c593315Sopenharmony_ci 7152c593315Sopenharmony_ci ++p; 7162c593315Sopenharmony_ci 7172c593315Sopenharmony_ci const char *var_name; 7182c593315Sopenharmony_ci size_t var_namelen; 7192c593315Sopenharmony_ci if (p != eop && *p == '{') { 7202c593315Sopenharmony_ci var_name = ++p; 7212c593315Sopenharmony_ci for (; p != eop && var_token(*p); ++p) 7222c593315Sopenharmony_ci ; 7232c593315Sopenharmony_ci 7242c593315Sopenharmony_ci if (p == eop || *p != '}') { 7252c593315Sopenharmony_ci LOG(WARN) << "Missing '}' after " << StringRef{var_start, p}; 7262c593315Sopenharmony_ci continue; 7272c593315Sopenharmony_ci } 7282c593315Sopenharmony_ci 7292c593315Sopenharmony_ci var_namelen = p - var_name; 7302c593315Sopenharmony_ci ++p; 7312c593315Sopenharmony_ci } else { 7322c593315Sopenharmony_ci var_name = p; 7332c593315Sopenharmony_ci for (; p != eop && var_token(*p); ++p) 7342c593315Sopenharmony_ci ; 7352c593315Sopenharmony_ci 7362c593315Sopenharmony_ci var_namelen = p - var_name; 7372c593315Sopenharmony_ci } 7382c593315Sopenharmony_ci 7392c593315Sopenharmony_ci const char *value = nullptr; 7402c593315Sopenharmony_ci 7412c593315Sopenharmony_ci auto type = log_var_lookup_token(var_name, var_namelen); 7422c593315Sopenharmony_ci 7432c593315Sopenharmony_ci if (type == LogFragmentType::NONE) { 7442c593315Sopenharmony_ci if (util::istarts_with_l(StringRef{var_name, var_namelen}, "http_")) { 7452c593315Sopenharmony_ci if (util::streq_l("host", StringRef{var_name + str_size("http_"), 7462c593315Sopenharmony_ci var_namelen - str_size("http_")})) { 7472c593315Sopenharmony_ci // Special handling of host header field. We will use 7482c593315Sopenharmony_ci // :authority header field if host header is missing. This 7492c593315Sopenharmony_ci // is a typical case in HTTP/2. 7502c593315Sopenharmony_ci type = LogFragmentType::AUTHORITY; 7512c593315Sopenharmony_ci } else { 7522c593315Sopenharmony_ci type = LogFragmentType::HTTP; 7532c593315Sopenharmony_ci value = var_name + str_size("http_"); 7542c593315Sopenharmony_ci } 7552c593315Sopenharmony_ci } else { 7562c593315Sopenharmony_ci LOG(WARN) << "Unrecognized log format variable: " 7572c593315Sopenharmony_ci << StringRef{var_name, var_namelen}; 7582c593315Sopenharmony_ci continue; 7592c593315Sopenharmony_ci } 7602c593315Sopenharmony_ci } 7612c593315Sopenharmony_ci 7622c593315Sopenharmony_ci if (literal_start < var_start) { 7632c593315Sopenharmony_ci res.emplace_back( 7642c593315Sopenharmony_ci LogFragmentType::LITERAL, 7652c593315Sopenharmony_ci make_string_ref(balloc, StringRef{literal_start, var_start})); 7662c593315Sopenharmony_ci } 7672c593315Sopenharmony_ci 7682c593315Sopenharmony_ci literal_start = p; 7692c593315Sopenharmony_ci 7702c593315Sopenharmony_ci if (value == nullptr) { 7712c593315Sopenharmony_ci res.emplace_back(type); 7722c593315Sopenharmony_ci continue; 7732c593315Sopenharmony_ci } 7742c593315Sopenharmony_ci 7752c593315Sopenharmony_ci { 7762c593315Sopenharmony_ci auto iov = make_byte_ref( 7772c593315Sopenharmony_ci balloc, std::distance(value, var_name + var_namelen) + 1); 7782c593315Sopenharmony_ci auto p = iov.base; 7792c593315Sopenharmony_ci p = std::copy(value, var_name + var_namelen, p); 7802c593315Sopenharmony_ci for (auto cp = iov.base; cp != p; ++cp) { 7812c593315Sopenharmony_ci if (*cp == '_') { 7822c593315Sopenharmony_ci *cp = '-'; 7832c593315Sopenharmony_ci } 7842c593315Sopenharmony_ci } 7852c593315Sopenharmony_ci *p = '\0'; 7862c593315Sopenharmony_ci res.emplace_back(type, StringRef{iov.base, p}); 7872c593315Sopenharmony_ci } 7882c593315Sopenharmony_ci } 7892c593315Sopenharmony_ci 7902c593315Sopenharmony_ci if (literal_start != eop) { 7912c593315Sopenharmony_ci res.emplace_back(LogFragmentType::LITERAL, 7922c593315Sopenharmony_ci make_string_ref(balloc, StringRef{literal_start, eop})); 7932c593315Sopenharmony_ci } 7942c593315Sopenharmony_ci 7952c593315Sopenharmony_ci return res; 7962c593315Sopenharmony_ci} 7972c593315Sopenharmony_ci 7982c593315Sopenharmony_cinamespace { 7992c593315Sopenharmony_ciint parse_address_family(int *dest, const StringRef &opt, 8002c593315Sopenharmony_ci const StringRef &optarg) { 8012c593315Sopenharmony_ci if (util::strieq_l("auto", optarg)) { 8022c593315Sopenharmony_ci *dest = AF_UNSPEC; 8032c593315Sopenharmony_ci return 0; 8042c593315Sopenharmony_ci } 8052c593315Sopenharmony_ci if (util::strieq_l("IPv4", optarg)) { 8062c593315Sopenharmony_ci *dest = AF_INET; 8072c593315Sopenharmony_ci return 0; 8082c593315Sopenharmony_ci } 8092c593315Sopenharmony_ci if (util::strieq_l("IPv6", optarg)) { 8102c593315Sopenharmony_ci *dest = AF_INET6; 8112c593315Sopenharmony_ci return 0; 8122c593315Sopenharmony_ci } 8132c593315Sopenharmony_ci 8142c593315Sopenharmony_ci LOG(ERROR) << opt << ": bad value: '" << optarg << "'"; 8152c593315Sopenharmony_ci return -1; 8162c593315Sopenharmony_ci} 8172c593315Sopenharmony_ci} // namespace 8182c593315Sopenharmony_ci 8192c593315Sopenharmony_cinamespace { 8202c593315Sopenharmony_ciint parse_duration(ev_tstamp *dest, const StringRef &opt, 8212c593315Sopenharmony_ci const StringRef &optarg) { 8222c593315Sopenharmony_ci auto t = util::parse_duration_with_unit(optarg); 8232c593315Sopenharmony_ci if (t == std::numeric_limits<double>::infinity()) { 8242c593315Sopenharmony_ci LOG(ERROR) << opt << ": bad value: '" << optarg << "'"; 8252c593315Sopenharmony_ci return -1; 8262c593315Sopenharmony_ci } 8272c593315Sopenharmony_ci 8282c593315Sopenharmony_ci *dest = t; 8292c593315Sopenharmony_ci 8302c593315Sopenharmony_ci return 0; 8312c593315Sopenharmony_ci} 8322c593315Sopenharmony_ci} // namespace 8332c593315Sopenharmony_ci 8342c593315Sopenharmony_cinamespace { 8352c593315Sopenharmony_ciint parse_tls_proto_version(int &dest, const StringRef &opt, 8362c593315Sopenharmony_ci const StringRef &optarg) { 8372c593315Sopenharmony_ci auto v = tls::proto_version_from_string(optarg); 8382c593315Sopenharmony_ci if (v == -1) { 8392c593315Sopenharmony_ci LOG(ERROR) << opt << ": invalid TLS protocol version: " << optarg; 8402c593315Sopenharmony_ci return -1; 8412c593315Sopenharmony_ci } 8422c593315Sopenharmony_ci 8432c593315Sopenharmony_ci dest = v; 8442c593315Sopenharmony_ci 8452c593315Sopenharmony_ci return 0; 8462c593315Sopenharmony_ci} 8472c593315Sopenharmony_ci} // namespace 8482c593315Sopenharmony_ci 8492c593315Sopenharmony_cistruct MemcachedConnectionParams { 8502c593315Sopenharmony_ci bool tls; 8512c593315Sopenharmony_ci}; 8522c593315Sopenharmony_ci 8532c593315Sopenharmony_cinamespace { 8542c593315Sopenharmony_ci// Parses memcached connection configuration parameter |src_params|, 8552c593315Sopenharmony_ci// and stores parsed results into |out|. This function returns 0 if 8562c593315Sopenharmony_ci// it succeeds, or -1. 8572c593315Sopenharmony_ciint parse_memcached_connection_params(MemcachedConnectionParams &out, 8582c593315Sopenharmony_ci const StringRef &src_params, 8592c593315Sopenharmony_ci const StringRef &opt) { 8602c593315Sopenharmony_ci auto last = std::end(src_params); 8612c593315Sopenharmony_ci for (auto first = std::begin(src_params); first != last;) { 8622c593315Sopenharmony_ci auto end = std::find(first, last, ';'); 8632c593315Sopenharmony_ci auto param = StringRef{first, end}; 8642c593315Sopenharmony_ci 8652c593315Sopenharmony_ci if (util::strieq_l("tls", param)) { 8662c593315Sopenharmony_ci out.tls = true; 8672c593315Sopenharmony_ci } else if (util::strieq_l("no-tls", param)) { 8682c593315Sopenharmony_ci out.tls = false; 8692c593315Sopenharmony_ci } else if (!param.empty()) { 8702c593315Sopenharmony_ci LOG(ERROR) << opt << ": " << param << ": unknown keyword"; 8712c593315Sopenharmony_ci return -1; 8722c593315Sopenharmony_ci } 8732c593315Sopenharmony_ci 8742c593315Sopenharmony_ci if (end == last) { 8752c593315Sopenharmony_ci break; 8762c593315Sopenharmony_ci } 8772c593315Sopenharmony_ci 8782c593315Sopenharmony_ci first = end + 1; 8792c593315Sopenharmony_ci } 8802c593315Sopenharmony_ci 8812c593315Sopenharmony_ci return 0; 8822c593315Sopenharmony_ci} 8832c593315Sopenharmony_ci} // namespace 8842c593315Sopenharmony_ci 8852c593315Sopenharmony_cistruct UpstreamParams { 8862c593315Sopenharmony_ci UpstreamAltMode alt_mode; 8872c593315Sopenharmony_ci bool tls; 8882c593315Sopenharmony_ci bool sni_fwd; 8892c593315Sopenharmony_ci bool proxyproto; 8902c593315Sopenharmony_ci bool quic; 8912c593315Sopenharmony_ci}; 8922c593315Sopenharmony_ci 8932c593315Sopenharmony_cinamespace { 8942c593315Sopenharmony_ci// Parses upstream configuration parameter |src_params|, and stores 8952c593315Sopenharmony_ci// parsed results into |out|. This function returns 0 if it succeeds, 8962c593315Sopenharmony_ci// or -1. 8972c593315Sopenharmony_ciint parse_upstream_params(UpstreamParams &out, const StringRef &src_params) { 8982c593315Sopenharmony_ci auto last = std::end(src_params); 8992c593315Sopenharmony_ci for (auto first = std::begin(src_params); first != last;) { 9002c593315Sopenharmony_ci auto end = std::find(first, last, ';'); 9012c593315Sopenharmony_ci auto param = StringRef{first, end}; 9022c593315Sopenharmony_ci 9032c593315Sopenharmony_ci if (util::strieq_l("tls", param)) { 9042c593315Sopenharmony_ci out.tls = true; 9052c593315Sopenharmony_ci } else if (util::strieq_l("sni-fwd", param)) { 9062c593315Sopenharmony_ci out.sni_fwd = true; 9072c593315Sopenharmony_ci } else if (util::strieq_l("no-tls", param)) { 9082c593315Sopenharmony_ci out.tls = false; 9092c593315Sopenharmony_ci } else if (util::strieq_l("api", param)) { 9102c593315Sopenharmony_ci if (out.alt_mode != UpstreamAltMode::NONE && 9112c593315Sopenharmony_ci out.alt_mode != UpstreamAltMode::API) { 9122c593315Sopenharmony_ci LOG(ERROR) << "frontend: api and healthmon are mutually exclusive"; 9132c593315Sopenharmony_ci return -1; 9142c593315Sopenharmony_ci } 9152c593315Sopenharmony_ci out.alt_mode = UpstreamAltMode::API; 9162c593315Sopenharmony_ci } else if (util::strieq_l("healthmon", param)) { 9172c593315Sopenharmony_ci if (out.alt_mode != UpstreamAltMode::NONE && 9182c593315Sopenharmony_ci out.alt_mode != UpstreamAltMode::HEALTHMON) { 9192c593315Sopenharmony_ci LOG(ERROR) << "frontend: api and healthmon are mutually exclusive"; 9202c593315Sopenharmony_ci return -1; 9212c593315Sopenharmony_ci } 9222c593315Sopenharmony_ci out.alt_mode = UpstreamAltMode::HEALTHMON; 9232c593315Sopenharmony_ci } else if (util::strieq_l("proxyproto", param)) { 9242c593315Sopenharmony_ci out.proxyproto = true; 9252c593315Sopenharmony_ci } else if (util::strieq_l("quic", param)) { 9262c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 9272c593315Sopenharmony_ci out.quic = true; 9282c593315Sopenharmony_ci#else // !ENABLE_HTTP3 9292c593315Sopenharmony_ci LOG(ERROR) << "quic: QUIC is disabled at compile time"; 9302c593315Sopenharmony_ci return -1; 9312c593315Sopenharmony_ci#endif // !ENABLE_HTTP3 9322c593315Sopenharmony_ci } else if (!param.empty()) { 9332c593315Sopenharmony_ci LOG(ERROR) << "frontend: " << param << ": unknown keyword"; 9342c593315Sopenharmony_ci return -1; 9352c593315Sopenharmony_ci } 9362c593315Sopenharmony_ci 9372c593315Sopenharmony_ci if (end == last) { 9382c593315Sopenharmony_ci break; 9392c593315Sopenharmony_ci } 9402c593315Sopenharmony_ci 9412c593315Sopenharmony_ci first = end + 1; 9422c593315Sopenharmony_ci } 9432c593315Sopenharmony_ci 9442c593315Sopenharmony_ci return 0; 9452c593315Sopenharmony_ci} 9462c593315Sopenharmony_ci} // namespace 9472c593315Sopenharmony_ci 9482c593315Sopenharmony_cistruct DownstreamParams { 9492c593315Sopenharmony_ci StringRef sni; 9502c593315Sopenharmony_ci StringRef mruby; 9512c593315Sopenharmony_ci StringRef group; 9522c593315Sopenharmony_ci AffinityConfig affinity; 9532c593315Sopenharmony_ci ev_tstamp read_timeout; 9542c593315Sopenharmony_ci ev_tstamp write_timeout; 9552c593315Sopenharmony_ci size_t fall; 9562c593315Sopenharmony_ci size_t rise; 9572c593315Sopenharmony_ci uint32_t weight; 9582c593315Sopenharmony_ci uint32_t group_weight; 9592c593315Sopenharmony_ci Proto proto; 9602c593315Sopenharmony_ci bool tls; 9612c593315Sopenharmony_ci bool dns; 9622c593315Sopenharmony_ci bool redirect_if_not_tls; 9632c593315Sopenharmony_ci bool upgrade_scheme; 9642c593315Sopenharmony_ci bool dnf; 9652c593315Sopenharmony_ci}; 9662c593315Sopenharmony_ci 9672c593315Sopenharmony_cinamespace { 9682c593315Sopenharmony_ci// Parses |value| of parameter named |name| as duration. This 9692c593315Sopenharmony_ci// function returns 0 if it succeeds and the parsed value is assigned 9702c593315Sopenharmony_ci// to |dest|, or -1. 9712c593315Sopenharmony_ciint parse_downstream_param_duration(ev_tstamp &dest, const StringRef &name, 9722c593315Sopenharmony_ci const StringRef &value) { 9732c593315Sopenharmony_ci auto t = util::parse_duration_with_unit(value); 9742c593315Sopenharmony_ci if (t == std::numeric_limits<double>::infinity()) { 9752c593315Sopenharmony_ci LOG(ERROR) << "backend: " << name << ": bad value: '" << value << "'"; 9762c593315Sopenharmony_ci return -1; 9772c593315Sopenharmony_ci } 9782c593315Sopenharmony_ci dest = t; 9792c593315Sopenharmony_ci return 0; 9802c593315Sopenharmony_ci} 9812c593315Sopenharmony_ci} // namespace 9822c593315Sopenharmony_ci 9832c593315Sopenharmony_cinamespace { 9842c593315Sopenharmony_ci// Parses downstream configuration parameter |src_params|, and stores 9852c593315Sopenharmony_ci// parsed results into |out|. This function returns 0 if it succeeds, 9862c593315Sopenharmony_ci// or -1. 9872c593315Sopenharmony_ciint parse_downstream_params(DownstreamParams &out, 9882c593315Sopenharmony_ci const StringRef &src_params) { 9892c593315Sopenharmony_ci auto last = std::end(src_params); 9902c593315Sopenharmony_ci for (auto first = std::begin(src_params); first != last;) { 9912c593315Sopenharmony_ci auto end = std::find(first, last, ';'); 9922c593315Sopenharmony_ci auto param = StringRef{first, end}; 9932c593315Sopenharmony_ci 9942c593315Sopenharmony_ci if (util::istarts_with_l(param, "proto=")) { 9952c593315Sopenharmony_ci auto protostr = StringRef{first + str_size("proto="), end}; 9962c593315Sopenharmony_ci if (protostr.empty()) { 9972c593315Sopenharmony_ci LOG(ERROR) << "backend: proto: protocol is empty"; 9982c593315Sopenharmony_ci return -1; 9992c593315Sopenharmony_ci } 10002c593315Sopenharmony_ci 10012c593315Sopenharmony_ci if (util::streq_l("h2", std::begin(protostr), protostr.size())) { 10022c593315Sopenharmony_ci out.proto = Proto::HTTP2; 10032c593315Sopenharmony_ci } else if (util::streq_l("http/1.1", std::begin(protostr), 10042c593315Sopenharmony_ci protostr.size())) { 10052c593315Sopenharmony_ci out.proto = Proto::HTTP1; 10062c593315Sopenharmony_ci } else { 10072c593315Sopenharmony_ci LOG(ERROR) << "backend: proto: unknown protocol " << protostr; 10082c593315Sopenharmony_ci return -1; 10092c593315Sopenharmony_ci } 10102c593315Sopenharmony_ci } else if (util::istarts_with_l(param, "fall=")) { 10112c593315Sopenharmony_ci auto valstr = StringRef{first + str_size("fall="), end}; 10122c593315Sopenharmony_ci if (valstr.empty()) { 10132c593315Sopenharmony_ci LOG(ERROR) << "backend: fall: non-negative integer is expected"; 10142c593315Sopenharmony_ci return -1; 10152c593315Sopenharmony_ci } 10162c593315Sopenharmony_ci 10172c593315Sopenharmony_ci auto n = util::parse_uint(valstr); 10182c593315Sopenharmony_ci if (n == -1) { 10192c593315Sopenharmony_ci LOG(ERROR) << "backend: fall: non-negative integer is expected"; 10202c593315Sopenharmony_ci return -1; 10212c593315Sopenharmony_ci } 10222c593315Sopenharmony_ci 10232c593315Sopenharmony_ci out.fall = n; 10242c593315Sopenharmony_ci } else if (util::istarts_with_l(param, "rise=")) { 10252c593315Sopenharmony_ci auto valstr = StringRef{first + str_size("rise="), end}; 10262c593315Sopenharmony_ci if (valstr.empty()) { 10272c593315Sopenharmony_ci LOG(ERROR) << "backend: rise: non-negative integer is expected"; 10282c593315Sopenharmony_ci return -1; 10292c593315Sopenharmony_ci } 10302c593315Sopenharmony_ci 10312c593315Sopenharmony_ci auto n = util::parse_uint(valstr); 10322c593315Sopenharmony_ci if (n == -1) { 10332c593315Sopenharmony_ci LOG(ERROR) << "backend: rise: non-negative integer is expected"; 10342c593315Sopenharmony_ci return -1; 10352c593315Sopenharmony_ci } 10362c593315Sopenharmony_ci 10372c593315Sopenharmony_ci out.rise = n; 10382c593315Sopenharmony_ci } else if (util::strieq_l("tls", param)) { 10392c593315Sopenharmony_ci out.tls = true; 10402c593315Sopenharmony_ci } else if (util::strieq_l("no-tls", param)) { 10412c593315Sopenharmony_ci out.tls = false; 10422c593315Sopenharmony_ci } else if (util::istarts_with_l(param, "sni=")) { 10432c593315Sopenharmony_ci out.sni = StringRef{first + str_size("sni="), end}; 10442c593315Sopenharmony_ci } else if (util::istarts_with_l(param, "affinity=")) { 10452c593315Sopenharmony_ci auto valstr = StringRef{first + str_size("affinity="), end}; 10462c593315Sopenharmony_ci if (util::strieq_l("none", valstr)) { 10472c593315Sopenharmony_ci out.affinity.type = SessionAffinity::NONE; 10482c593315Sopenharmony_ci } else if (util::strieq_l("ip", valstr)) { 10492c593315Sopenharmony_ci out.affinity.type = SessionAffinity::IP; 10502c593315Sopenharmony_ci } else if (util::strieq_l("cookie", valstr)) { 10512c593315Sopenharmony_ci out.affinity.type = SessionAffinity::COOKIE; 10522c593315Sopenharmony_ci } else { 10532c593315Sopenharmony_ci LOG(ERROR) 10542c593315Sopenharmony_ci << "backend: affinity: value must be one of none, ip, and cookie"; 10552c593315Sopenharmony_ci return -1; 10562c593315Sopenharmony_ci } 10572c593315Sopenharmony_ci } else if (util::istarts_with_l(param, "affinity-cookie-name=")) { 10582c593315Sopenharmony_ci auto val = StringRef{first + str_size("affinity-cookie-name="), end}; 10592c593315Sopenharmony_ci if (val.empty()) { 10602c593315Sopenharmony_ci LOG(ERROR) 10612c593315Sopenharmony_ci << "backend: affinity-cookie-name: non empty string is expected"; 10622c593315Sopenharmony_ci return -1; 10632c593315Sopenharmony_ci } 10642c593315Sopenharmony_ci out.affinity.cookie.name = val; 10652c593315Sopenharmony_ci } else if (util::istarts_with_l(param, "affinity-cookie-path=")) { 10662c593315Sopenharmony_ci out.affinity.cookie.path = 10672c593315Sopenharmony_ci StringRef{first + str_size("affinity-cookie-path="), end}; 10682c593315Sopenharmony_ci } else if (util::istarts_with_l(param, "affinity-cookie-secure=")) { 10692c593315Sopenharmony_ci auto valstr = StringRef{first + str_size("affinity-cookie-secure="), end}; 10702c593315Sopenharmony_ci if (util::strieq_l("auto", valstr)) { 10712c593315Sopenharmony_ci out.affinity.cookie.secure = SessionAffinityCookieSecure::AUTO; 10722c593315Sopenharmony_ci } else if (util::strieq_l("yes", valstr)) { 10732c593315Sopenharmony_ci out.affinity.cookie.secure = SessionAffinityCookieSecure::YES; 10742c593315Sopenharmony_ci } else if (util::strieq_l("no", valstr)) { 10752c593315Sopenharmony_ci out.affinity.cookie.secure = SessionAffinityCookieSecure::NO; 10762c593315Sopenharmony_ci } else { 10772c593315Sopenharmony_ci LOG(ERROR) << "backend: affinity-cookie-secure: value must be one of " 10782c593315Sopenharmony_ci "auto, yes, and no"; 10792c593315Sopenharmony_ci return -1; 10802c593315Sopenharmony_ci } 10812c593315Sopenharmony_ci } else if (util::istarts_with_l(param, "affinity-cookie-stickiness=")) { 10822c593315Sopenharmony_ci auto valstr = 10832c593315Sopenharmony_ci StringRef{first + str_size("affinity-cookie-stickiness="), end}; 10842c593315Sopenharmony_ci if (util::strieq_l("loose", valstr)) { 10852c593315Sopenharmony_ci out.affinity.cookie.stickiness = SessionAffinityCookieStickiness::LOOSE; 10862c593315Sopenharmony_ci } else if (util::strieq_l("strict", valstr)) { 10872c593315Sopenharmony_ci out.affinity.cookie.stickiness = 10882c593315Sopenharmony_ci SessionAffinityCookieStickiness::STRICT; 10892c593315Sopenharmony_ci } else { 10902c593315Sopenharmony_ci LOG(ERROR) << "backend: affinity-cookie-stickiness: value must be " 10912c593315Sopenharmony_ci "either loose or strict"; 10922c593315Sopenharmony_ci return -1; 10932c593315Sopenharmony_ci } 10942c593315Sopenharmony_ci } else if (util::strieq_l("dns", param)) { 10952c593315Sopenharmony_ci out.dns = true; 10962c593315Sopenharmony_ci } else if (util::strieq_l("redirect-if-not-tls", param)) { 10972c593315Sopenharmony_ci out.redirect_if_not_tls = true; 10982c593315Sopenharmony_ci } else if (util::strieq_l("upgrade-scheme", param)) { 10992c593315Sopenharmony_ci out.upgrade_scheme = true; 11002c593315Sopenharmony_ci } else if (util::istarts_with_l(param, "mruby=")) { 11012c593315Sopenharmony_ci auto valstr = StringRef{first + str_size("mruby="), end}; 11022c593315Sopenharmony_ci out.mruby = valstr; 11032c593315Sopenharmony_ci } else if (util::istarts_with_l(param, "read-timeout=")) { 11042c593315Sopenharmony_ci if (parse_downstream_param_duration( 11052c593315Sopenharmony_ci out.read_timeout, StringRef::from_lit("read-timeout"), 11062c593315Sopenharmony_ci StringRef{first + str_size("read-timeout="), end}) == -1) { 11072c593315Sopenharmony_ci return -1; 11082c593315Sopenharmony_ci } 11092c593315Sopenharmony_ci } else if (util::istarts_with_l(param, "write-timeout=")) { 11102c593315Sopenharmony_ci if (parse_downstream_param_duration( 11112c593315Sopenharmony_ci out.write_timeout, StringRef::from_lit("write-timeout"), 11122c593315Sopenharmony_ci StringRef{first + str_size("write-timeout="), end}) == -1) { 11132c593315Sopenharmony_ci return -1; 11142c593315Sopenharmony_ci } 11152c593315Sopenharmony_ci } else if (util::istarts_with_l(param, "weight=")) { 11162c593315Sopenharmony_ci auto valstr = StringRef{first + str_size("weight="), end}; 11172c593315Sopenharmony_ci if (valstr.empty()) { 11182c593315Sopenharmony_ci LOG(ERROR) 11192c593315Sopenharmony_ci << "backend: weight: non-negative integer [1, 256] is expected"; 11202c593315Sopenharmony_ci return -1; 11212c593315Sopenharmony_ci } 11222c593315Sopenharmony_ci 11232c593315Sopenharmony_ci auto n = util::parse_uint(valstr); 11242c593315Sopenharmony_ci if (n < 1 || n > 256) { 11252c593315Sopenharmony_ci LOG(ERROR) 11262c593315Sopenharmony_ci << "backend: weight: non-negative integer [1, 256] is expected"; 11272c593315Sopenharmony_ci return -1; 11282c593315Sopenharmony_ci } 11292c593315Sopenharmony_ci out.weight = n; 11302c593315Sopenharmony_ci } else if (util::istarts_with_l(param, "group=")) { 11312c593315Sopenharmony_ci auto valstr = StringRef{first + str_size("group="), end}; 11322c593315Sopenharmony_ci if (valstr.empty()) { 11332c593315Sopenharmony_ci LOG(ERROR) << "backend: group: empty string is not allowed"; 11342c593315Sopenharmony_ci return -1; 11352c593315Sopenharmony_ci } 11362c593315Sopenharmony_ci out.group = valstr; 11372c593315Sopenharmony_ci } else if (util::istarts_with_l(param, "group-weight=")) { 11382c593315Sopenharmony_ci auto valstr = StringRef{first + str_size("group-weight="), end}; 11392c593315Sopenharmony_ci if (valstr.empty()) { 11402c593315Sopenharmony_ci LOG(ERROR) << "backend: group-weight: non-negative integer [1, 256] is " 11412c593315Sopenharmony_ci "expected"; 11422c593315Sopenharmony_ci return -1; 11432c593315Sopenharmony_ci } 11442c593315Sopenharmony_ci 11452c593315Sopenharmony_ci auto n = util::parse_uint(valstr); 11462c593315Sopenharmony_ci if (n < 1 || n > 256) { 11472c593315Sopenharmony_ci LOG(ERROR) << "backend: group-weight: non-negative integer [1, 256] is " 11482c593315Sopenharmony_ci "expected"; 11492c593315Sopenharmony_ci return -1; 11502c593315Sopenharmony_ci } 11512c593315Sopenharmony_ci out.group_weight = n; 11522c593315Sopenharmony_ci } else if (util::strieq_l("dnf", param)) { 11532c593315Sopenharmony_ci out.dnf = true; 11542c593315Sopenharmony_ci } else if (!param.empty()) { 11552c593315Sopenharmony_ci LOG(ERROR) << "backend: " << param << ": unknown keyword"; 11562c593315Sopenharmony_ci return -1; 11572c593315Sopenharmony_ci } 11582c593315Sopenharmony_ci 11592c593315Sopenharmony_ci if (end == last) { 11602c593315Sopenharmony_ci break; 11612c593315Sopenharmony_ci } 11622c593315Sopenharmony_ci 11632c593315Sopenharmony_ci first = end + 1; 11642c593315Sopenharmony_ci } 11652c593315Sopenharmony_ci 11662c593315Sopenharmony_ci return 0; 11672c593315Sopenharmony_ci} 11682c593315Sopenharmony_ci} // namespace 11692c593315Sopenharmony_ci 11702c593315Sopenharmony_cinamespace { 11712c593315Sopenharmony_ci// Parses host-path mapping patterns in |src_pattern|, and stores 11722c593315Sopenharmony_ci// mappings in config. We will store each host-path pattern found in 11732c593315Sopenharmony_ci// |src| with |addr|. |addr| will be copied accordingly. Also we 11742c593315Sopenharmony_ci// make a group based on the pattern. The "/" pattern is considered 11752c593315Sopenharmony_ci// as catch-all. We also parse protocol specified in |src_proto|. 11762c593315Sopenharmony_ci// 11772c593315Sopenharmony_ci// This function returns 0 if it succeeds, or -1. 11782c593315Sopenharmony_ciint parse_mapping(Config *config, DownstreamAddrConfig &addr, 11792c593315Sopenharmony_ci std::map<StringRef, size_t> &pattern_addr_indexer, 11802c593315Sopenharmony_ci const StringRef &src_pattern, const StringRef &src_params) { 11812c593315Sopenharmony_ci // This returns at least 1 element (it could be empty string). We 11822c593315Sopenharmony_ci // will append '/' to all patterns, so it becomes catch-all pattern. 11832c593315Sopenharmony_ci auto mapping = util::split_str(src_pattern, ':'); 11842c593315Sopenharmony_ci assert(!mapping.empty()); 11852c593315Sopenharmony_ci auto &downstreamconf = *config->conn.downstream; 11862c593315Sopenharmony_ci auto &addr_groups = downstreamconf.addr_groups; 11872c593315Sopenharmony_ci 11882c593315Sopenharmony_ci DownstreamParams params{}; 11892c593315Sopenharmony_ci params.proto = Proto::HTTP1; 11902c593315Sopenharmony_ci params.weight = 1; 11912c593315Sopenharmony_ci 11922c593315Sopenharmony_ci if (parse_downstream_params(params, src_params) != 0) { 11932c593315Sopenharmony_ci return -1; 11942c593315Sopenharmony_ci } 11952c593315Sopenharmony_ci 11962c593315Sopenharmony_ci if (addr.host_unix && params.dns) { 11972c593315Sopenharmony_ci LOG(ERROR) << "backend: dns: cannot be used for UNIX domain socket"; 11982c593315Sopenharmony_ci return -1; 11992c593315Sopenharmony_ci } 12002c593315Sopenharmony_ci 12012c593315Sopenharmony_ci if (params.affinity.type == SessionAffinity::COOKIE && 12022c593315Sopenharmony_ci params.affinity.cookie.name.empty()) { 12032c593315Sopenharmony_ci LOG(ERROR) << "backend: affinity-cookie-name is mandatory if " 12042c593315Sopenharmony_ci "affinity=cookie is specified"; 12052c593315Sopenharmony_ci return -1; 12062c593315Sopenharmony_ci } 12072c593315Sopenharmony_ci 12082c593315Sopenharmony_ci addr.fall = params.fall; 12092c593315Sopenharmony_ci addr.rise = params.rise; 12102c593315Sopenharmony_ci addr.weight = params.weight; 12112c593315Sopenharmony_ci addr.group = make_string_ref(downstreamconf.balloc, params.group); 12122c593315Sopenharmony_ci addr.group_weight = params.group_weight; 12132c593315Sopenharmony_ci addr.proto = params.proto; 12142c593315Sopenharmony_ci addr.tls = params.tls; 12152c593315Sopenharmony_ci addr.sni = make_string_ref(downstreamconf.balloc, params.sni); 12162c593315Sopenharmony_ci addr.dns = params.dns; 12172c593315Sopenharmony_ci addr.upgrade_scheme = params.upgrade_scheme; 12182c593315Sopenharmony_ci addr.dnf = params.dnf; 12192c593315Sopenharmony_ci 12202c593315Sopenharmony_ci auto &routerconf = downstreamconf.router; 12212c593315Sopenharmony_ci auto &router = routerconf.router; 12222c593315Sopenharmony_ci auto &rw_router = routerconf.rev_wildcard_router; 12232c593315Sopenharmony_ci auto &wildcard_patterns = routerconf.wildcard_patterns; 12242c593315Sopenharmony_ci 12252c593315Sopenharmony_ci for (const auto &raw_pattern : mapping) { 12262c593315Sopenharmony_ci StringRef pattern; 12272c593315Sopenharmony_ci auto slash = std::find(std::begin(raw_pattern), std::end(raw_pattern), '/'); 12282c593315Sopenharmony_ci if (slash == std::end(raw_pattern)) { 12292c593315Sopenharmony_ci // This effectively makes empty pattern to "/". 2 for '/' and 12302c593315Sopenharmony_ci // terminal NULL character. 12312c593315Sopenharmony_ci auto iov = make_byte_ref(downstreamconf.balloc, raw_pattern.size() + 2); 12322c593315Sopenharmony_ci auto p = iov.base; 12332c593315Sopenharmony_ci p = std::copy(std::begin(raw_pattern), std::end(raw_pattern), p); 12342c593315Sopenharmony_ci util::inp_strlower(iov.base, p); 12352c593315Sopenharmony_ci *p++ = '/'; 12362c593315Sopenharmony_ci *p = '\0'; 12372c593315Sopenharmony_ci pattern = StringRef{iov.base, p}; 12382c593315Sopenharmony_ci } else { 12392c593315Sopenharmony_ci auto path = http2::normalize_path_colon( 12402c593315Sopenharmony_ci downstreamconf.balloc, StringRef{slash, std::end(raw_pattern)}, 12412c593315Sopenharmony_ci StringRef{}); 12422c593315Sopenharmony_ci auto iov = make_byte_ref(downstreamconf.balloc, 12432c593315Sopenharmony_ci std::distance(std::begin(raw_pattern), slash) + 12442c593315Sopenharmony_ci path.size() + 1); 12452c593315Sopenharmony_ci auto p = iov.base; 12462c593315Sopenharmony_ci p = std::copy(std::begin(raw_pattern), slash, p); 12472c593315Sopenharmony_ci util::inp_strlower(iov.base, p); 12482c593315Sopenharmony_ci p = std::copy(std::begin(path), std::end(path), p); 12492c593315Sopenharmony_ci *p = '\0'; 12502c593315Sopenharmony_ci pattern = StringRef{iov.base, p}; 12512c593315Sopenharmony_ci } 12522c593315Sopenharmony_ci auto it = pattern_addr_indexer.find(pattern); 12532c593315Sopenharmony_ci if (it != std::end(pattern_addr_indexer)) { 12542c593315Sopenharmony_ci auto &g = addr_groups[(*it).second]; 12552c593315Sopenharmony_ci // Last value wins if we have multiple different affinity 12562c593315Sopenharmony_ci // value under one group. 12572c593315Sopenharmony_ci if (params.affinity.type != SessionAffinity::NONE) { 12582c593315Sopenharmony_ci if (g.affinity.type == SessionAffinity::NONE) { 12592c593315Sopenharmony_ci g.affinity.type = params.affinity.type; 12602c593315Sopenharmony_ci if (params.affinity.type == SessionAffinity::COOKIE) { 12612c593315Sopenharmony_ci g.affinity.cookie.name = make_string_ref( 12622c593315Sopenharmony_ci downstreamconf.balloc, params.affinity.cookie.name); 12632c593315Sopenharmony_ci if (!params.affinity.cookie.path.empty()) { 12642c593315Sopenharmony_ci g.affinity.cookie.path = make_string_ref( 12652c593315Sopenharmony_ci downstreamconf.balloc, params.affinity.cookie.path); 12662c593315Sopenharmony_ci } 12672c593315Sopenharmony_ci g.affinity.cookie.secure = params.affinity.cookie.secure; 12682c593315Sopenharmony_ci g.affinity.cookie.stickiness = params.affinity.cookie.stickiness; 12692c593315Sopenharmony_ci } 12702c593315Sopenharmony_ci } else if (g.affinity.type != params.affinity.type || 12712c593315Sopenharmony_ci g.affinity.cookie.name != params.affinity.cookie.name || 12722c593315Sopenharmony_ci g.affinity.cookie.path != params.affinity.cookie.path || 12732c593315Sopenharmony_ci g.affinity.cookie.secure != params.affinity.cookie.secure || 12742c593315Sopenharmony_ci g.affinity.cookie.stickiness != 12752c593315Sopenharmony_ci params.affinity.cookie.stickiness) { 12762c593315Sopenharmony_ci LOG(ERROR) << "backend: affinity: multiple different affinity " 12772c593315Sopenharmony_ci "configurations found in a single group"; 12782c593315Sopenharmony_ci return -1; 12792c593315Sopenharmony_ci } 12802c593315Sopenharmony_ci } 12812c593315Sopenharmony_ci // If at least one backend requires frontend TLS connection, 12822c593315Sopenharmony_ci // enable it for all backends sharing the same pattern. 12832c593315Sopenharmony_ci if (params.redirect_if_not_tls) { 12842c593315Sopenharmony_ci g.redirect_if_not_tls = true; 12852c593315Sopenharmony_ci } 12862c593315Sopenharmony_ci // All backends in the same group must have the same mruby path. 12872c593315Sopenharmony_ci // If some backends do not specify mruby file, and there is at 12882c593315Sopenharmony_ci // least one backend with mruby file, it is used for all 12892c593315Sopenharmony_ci // backends in the group. 12902c593315Sopenharmony_ci if (!params.mruby.empty()) { 12912c593315Sopenharmony_ci if (g.mruby_file.empty()) { 12922c593315Sopenharmony_ci g.mruby_file = make_string_ref(downstreamconf.balloc, params.mruby); 12932c593315Sopenharmony_ci } else if (g.mruby_file != params.mruby) { 12942c593315Sopenharmony_ci LOG(ERROR) << "backend: mruby: multiple different mruby file found " 12952c593315Sopenharmony_ci "in a single group"; 12962c593315Sopenharmony_ci return -1; 12972c593315Sopenharmony_ci } 12982c593315Sopenharmony_ci } 12992c593315Sopenharmony_ci // All backends in the same group must have the same read/write 13002c593315Sopenharmony_ci // timeout. If some backends do not specify read/write timeout, 13012c593315Sopenharmony_ci // and there is at least one backend with read/write timeout, it 13022c593315Sopenharmony_ci // is used for all backends in the group. 13032c593315Sopenharmony_ci if (params.read_timeout > 1e-9) { 13042c593315Sopenharmony_ci if (g.timeout.read < 1e-9) { 13052c593315Sopenharmony_ci g.timeout.read = params.read_timeout; 13062c593315Sopenharmony_ci } else if (fabs(g.timeout.read - params.read_timeout) > 1e-9) { 13072c593315Sopenharmony_ci LOG(ERROR) 13082c593315Sopenharmony_ci << "backend: read-timeout: multiple different read-timeout " 13092c593315Sopenharmony_ci "found in a single group"; 13102c593315Sopenharmony_ci return -1; 13112c593315Sopenharmony_ci } 13122c593315Sopenharmony_ci } 13132c593315Sopenharmony_ci if (params.write_timeout > 1e-9) { 13142c593315Sopenharmony_ci if (g.timeout.write < 1e-9) { 13152c593315Sopenharmony_ci g.timeout.write = params.write_timeout; 13162c593315Sopenharmony_ci } else if (fabs(g.timeout.write - params.write_timeout) > 1e-9) { 13172c593315Sopenharmony_ci LOG(ERROR) << "backend: write-timeout: multiple different " 13182c593315Sopenharmony_ci "write-timeout found in a single group"; 13192c593315Sopenharmony_ci return -1; 13202c593315Sopenharmony_ci } 13212c593315Sopenharmony_ci } 13222c593315Sopenharmony_ci // All backends in the same group must have the same dnf 13232c593315Sopenharmony_ci // setting. If some backends do not specify dnf, and there is 13242c593315Sopenharmony_ci // at least one backend with dnf, it is used for all backends in 13252c593315Sopenharmony_ci // the group. In general, multiple backends are not necessary 13262c593315Sopenharmony_ci // for dnf because there is no need for load balancing. 13272c593315Sopenharmony_ci if (params.dnf) { 13282c593315Sopenharmony_ci g.dnf = true; 13292c593315Sopenharmony_ci } 13302c593315Sopenharmony_ci 13312c593315Sopenharmony_ci g.addrs.push_back(addr); 13322c593315Sopenharmony_ci continue; 13332c593315Sopenharmony_ci } 13342c593315Sopenharmony_ci 13352c593315Sopenharmony_ci auto idx = addr_groups.size(); 13362c593315Sopenharmony_ci pattern_addr_indexer.emplace(pattern, idx); 13372c593315Sopenharmony_ci addr_groups.emplace_back(pattern); 13382c593315Sopenharmony_ci auto &g = addr_groups.back(); 13392c593315Sopenharmony_ci g.addrs.push_back(addr); 13402c593315Sopenharmony_ci g.affinity.type = params.affinity.type; 13412c593315Sopenharmony_ci if (params.affinity.type == SessionAffinity::COOKIE) { 13422c593315Sopenharmony_ci g.affinity.cookie.name = 13432c593315Sopenharmony_ci make_string_ref(downstreamconf.balloc, params.affinity.cookie.name); 13442c593315Sopenharmony_ci if (!params.affinity.cookie.path.empty()) { 13452c593315Sopenharmony_ci g.affinity.cookie.path = 13462c593315Sopenharmony_ci make_string_ref(downstreamconf.balloc, params.affinity.cookie.path); 13472c593315Sopenharmony_ci } 13482c593315Sopenharmony_ci g.affinity.cookie.secure = params.affinity.cookie.secure; 13492c593315Sopenharmony_ci g.affinity.cookie.stickiness = params.affinity.cookie.stickiness; 13502c593315Sopenharmony_ci } 13512c593315Sopenharmony_ci g.redirect_if_not_tls = params.redirect_if_not_tls; 13522c593315Sopenharmony_ci g.mruby_file = make_string_ref(downstreamconf.balloc, params.mruby); 13532c593315Sopenharmony_ci g.timeout.read = params.read_timeout; 13542c593315Sopenharmony_ci g.timeout.write = params.write_timeout; 13552c593315Sopenharmony_ci g.dnf = params.dnf; 13562c593315Sopenharmony_ci 13572c593315Sopenharmony_ci if (pattern[0] == '*') { 13582c593315Sopenharmony_ci // wildcard pattern 13592c593315Sopenharmony_ci auto path_first = 13602c593315Sopenharmony_ci std::find(std::begin(g.pattern), std::end(g.pattern), '/'); 13612c593315Sopenharmony_ci 13622c593315Sopenharmony_ci auto host = StringRef{std::begin(g.pattern) + 1, path_first}; 13632c593315Sopenharmony_ci auto path = StringRef{path_first, std::end(g.pattern)}; 13642c593315Sopenharmony_ci 13652c593315Sopenharmony_ci auto path_is_wildcard = false; 13662c593315Sopenharmony_ci if (path[path.size() - 1] == '*') { 13672c593315Sopenharmony_ci path = StringRef{std::begin(path), std::begin(path) + path.size() - 1}; 13682c593315Sopenharmony_ci path_is_wildcard = true; 13692c593315Sopenharmony_ci } 13702c593315Sopenharmony_ci 13712c593315Sopenharmony_ci auto it = std::find_if( 13722c593315Sopenharmony_ci std::begin(wildcard_patterns), std::end(wildcard_patterns), 13732c593315Sopenharmony_ci [&host](const WildcardPattern &wp) { return wp.host == host; }); 13742c593315Sopenharmony_ci 13752c593315Sopenharmony_ci if (it == std::end(wildcard_patterns)) { 13762c593315Sopenharmony_ci wildcard_patterns.emplace_back(host); 13772c593315Sopenharmony_ci 13782c593315Sopenharmony_ci auto &router = wildcard_patterns.back().router; 13792c593315Sopenharmony_ci router.add_route(path, idx, path_is_wildcard); 13802c593315Sopenharmony_ci 13812c593315Sopenharmony_ci auto iov = make_byte_ref(downstreamconf.balloc, host.size() + 1); 13822c593315Sopenharmony_ci auto p = iov.base; 13832c593315Sopenharmony_ci p = std::reverse_copy(std::begin(host), std::end(host), p); 13842c593315Sopenharmony_ci *p = '\0'; 13852c593315Sopenharmony_ci auto rev_host = StringRef{iov.base, p}; 13862c593315Sopenharmony_ci 13872c593315Sopenharmony_ci rw_router.add_route(rev_host, wildcard_patterns.size() - 1); 13882c593315Sopenharmony_ci } else { 13892c593315Sopenharmony_ci (*it).router.add_route(path, idx, path_is_wildcard); 13902c593315Sopenharmony_ci } 13912c593315Sopenharmony_ci 13922c593315Sopenharmony_ci continue; 13932c593315Sopenharmony_ci } 13942c593315Sopenharmony_ci 13952c593315Sopenharmony_ci auto path_is_wildcard = false; 13962c593315Sopenharmony_ci if (pattern[pattern.size() - 1] == '*') { 13972c593315Sopenharmony_ci pattern = StringRef{std::begin(pattern), 13982c593315Sopenharmony_ci std::begin(pattern) + pattern.size() - 1}; 13992c593315Sopenharmony_ci path_is_wildcard = true; 14002c593315Sopenharmony_ci } 14012c593315Sopenharmony_ci 14022c593315Sopenharmony_ci router.add_route(pattern, idx, path_is_wildcard); 14032c593315Sopenharmony_ci } 14042c593315Sopenharmony_ci return 0; 14052c593315Sopenharmony_ci} 14062c593315Sopenharmony_ci} // namespace 14072c593315Sopenharmony_ci 14082c593315Sopenharmony_cinamespace { 14092c593315Sopenharmony_ciForwardedNode parse_forwarded_node_type(const StringRef &optarg) { 14102c593315Sopenharmony_ci if (util::strieq_l("obfuscated", optarg)) { 14112c593315Sopenharmony_ci return ForwardedNode::OBFUSCATED; 14122c593315Sopenharmony_ci } 14132c593315Sopenharmony_ci 14142c593315Sopenharmony_ci if (util::strieq_l("ip", optarg)) { 14152c593315Sopenharmony_ci return ForwardedNode::IP; 14162c593315Sopenharmony_ci } 14172c593315Sopenharmony_ci 14182c593315Sopenharmony_ci if (optarg.size() < 2 || optarg[0] != '_') { 14192c593315Sopenharmony_ci return static_cast<ForwardedNode>(-1); 14202c593315Sopenharmony_ci } 14212c593315Sopenharmony_ci 14222c593315Sopenharmony_ci if (std::find_if_not(std::begin(optarg), std::end(optarg), [](char c) { 14232c593315Sopenharmony_ci return util::is_alpha(c) || util::is_digit(c) || c == '.' || c == '_' || 14242c593315Sopenharmony_ci c == '-'; 14252c593315Sopenharmony_ci }) != std::end(optarg)) { 14262c593315Sopenharmony_ci return static_cast<ForwardedNode>(-1); 14272c593315Sopenharmony_ci } 14282c593315Sopenharmony_ci 14292c593315Sopenharmony_ci return ForwardedNode::OBFUSCATED; 14302c593315Sopenharmony_ci} 14312c593315Sopenharmony_ci} // namespace 14322c593315Sopenharmony_ci 14332c593315Sopenharmony_cinamespace { 14342c593315Sopenharmony_ciint parse_error_page(std::vector<ErrorPage> &error_pages, const StringRef &opt, 14352c593315Sopenharmony_ci const StringRef &optarg) { 14362c593315Sopenharmony_ci std::array<char, STRERROR_BUFSIZE> errbuf; 14372c593315Sopenharmony_ci 14382c593315Sopenharmony_ci auto eq = std::find(std::begin(optarg), std::end(optarg), '='); 14392c593315Sopenharmony_ci if (eq == std::end(optarg) || eq + 1 == std::end(optarg)) { 14402c593315Sopenharmony_ci LOG(ERROR) << opt << ": bad value: '" << optarg << "'"; 14412c593315Sopenharmony_ci return -1; 14422c593315Sopenharmony_ci } 14432c593315Sopenharmony_ci 14442c593315Sopenharmony_ci auto codestr = StringRef{std::begin(optarg), eq}; 14452c593315Sopenharmony_ci unsigned int code; 14462c593315Sopenharmony_ci 14472c593315Sopenharmony_ci if (codestr == StringRef::from_lit("*")) { 14482c593315Sopenharmony_ci code = 0; 14492c593315Sopenharmony_ci } else { 14502c593315Sopenharmony_ci auto n = util::parse_uint(codestr); 14512c593315Sopenharmony_ci 14522c593315Sopenharmony_ci if (n == -1 || n < 400 || n > 599) { 14532c593315Sopenharmony_ci LOG(ERROR) << opt << ": bad code: '" << codestr << "'"; 14542c593315Sopenharmony_ci return -1; 14552c593315Sopenharmony_ci } 14562c593315Sopenharmony_ci 14572c593315Sopenharmony_ci code = static_cast<unsigned int>(n); 14582c593315Sopenharmony_ci } 14592c593315Sopenharmony_ci 14602c593315Sopenharmony_ci auto path = StringRef{eq + 1, std::end(optarg)}; 14612c593315Sopenharmony_ci 14622c593315Sopenharmony_ci std::vector<uint8_t> content; 14632c593315Sopenharmony_ci auto fd = open(path.c_str(), O_RDONLY); 14642c593315Sopenharmony_ci if (fd == -1) { 14652c593315Sopenharmony_ci auto error = errno; 14662c593315Sopenharmony_ci LOG(ERROR) << opt << ": " << optarg << ": " 14672c593315Sopenharmony_ci << xsi_strerror(error, errbuf.data(), errbuf.size()); 14682c593315Sopenharmony_ci return -1; 14692c593315Sopenharmony_ci } 14702c593315Sopenharmony_ci 14712c593315Sopenharmony_ci auto fd_closer = defer(close, fd); 14722c593315Sopenharmony_ci 14732c593315Sopenharmony_ci std::array<uint8_t, 4096> buf; 14742c593315Sopenharmony_ci for (;;) { 14752c593315Sopenharmony_ci auto n = read(fd, buf.data(), buf.size()); 14762c593315Sopenharmony_ci if (n == -1) { 14772c593315Sopenharmony_ci auto error = errno; 14782c593315Sopenharmony_ci LOG(ERROR) << opt << ": " << optarg << ": " 14792c593315Sopenharmony_ci << xsi_strerror(error, errbuf.data(), errbuf.size()); 14802c593315Sopenharmony_ci return -1; 14812c593315Sopenharmony_ci } 14822c593315Sopenharmony_ci if (n == 0) { 14832c593315Sopenharmony_ci break; 14842c593315Sopenharmony_ci } 14852c593315Sopenharmony_ci content.insert(std::end(content), std::begin(buf), std::begin(buf) + n); 14862c593315Sopenharmony_ci } 14872c593315Sopenharmony_ci 14882c593315Sopenharmony_ci error_pages.push_back(ErrorPage{std::move(content), code}); 14892c593315Sopenharmony_ci 14902c593315Sopenharmony_ci return 0; 14912c593315Sopenharmony_ci} 14922c593315Sopenharmony_ci} // namespace 14932c593315Sopenharmony_ci 14942c593315Sopenharmony_cinamespace { 14952c593315Sopenharmony_ci// Maximum size of SCT extension payload length. 14962c593315Sopenharmony_ciconstexpr size_t MAX_SCT_EXT_LEN = 16_k; 14972c593315Sopenharmony_ci} // namespace 14982c593315Sopenharmony_ci 14992c593315Sopenharmony_cistruct SubcertParams { 15002c593315Sopenharmony_ci StringRef sct_dir; 15012c593315Sopenharmony_ci}; 15022c593315Sopenharmony_ci 15032c593315Sopenharmony_cinamespace { 15042c593315Sopenharmony_ci// Parses subcert parameter |src_params|, and stores parsed results 15052c593315Sopenharmony_ci// into |out|. This function returns 0 if it succeeds, or -1. 15062c593315Sopenharmony_ciint parse_subcert_params(SubcertParams &out, const StringRef &src_params) { 15072c593315Sopenharmony_ci auto last = std::end(src_params); 15082c593315Sopenharmony_ci for (auto first = std::begin(src_params); first != last;) { 15092c593315Sopenharmony_ci auto end = std::find(first, last, ';'); 15102c593315Sopenharmony_ci auto param = StringRef{first, end}; 15112c593315Sopenharmony_ci 15122c593315Sopenharmony_ci if (util::istarts_with_l(param, "sct-dir=")) { 15132c593315Sopenharmony_ci#if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L 15142c593315Sopenharmony_ci auto sct_dir = 15152c593315Sopenharmony_ci StringRef{std::begin(param) + str_size("sct-dir="), std::end(param)}; 15162c593315Sopenharmony_ci if (sct_dir.empty()) { 15172c593315Sopenharmony_ci LOG(ERROR) << "subcert: " << param << ": empty sct-dir"; 15182c593315Sopenharmony_ci return -1; 15192c593315Sopenharmony_ci } 15202c593315Sopenharmony_ci out.sct_dir = sct_dir; 15212c593315Sopenharmony_ci#else // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L) 15222c593315Sopenharmony_ci LOG(WARN) << "subcert: sct-dir requires OpenSSL >= 1.0.2"; 15232c593315Sopenharmony_ci#endif // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L) 15242c593315Sopenharmony_ci } else if (!param.empty()) { 15252c593315Sopenharmony_ci LOG(ERROR) << "subcert: " << param << ": unknown keyword"; 15262c593315Sopenharmony_ci return -1; 15272c593315Sopenharmony_ci } 15282c593315Sopenharmony_ci 15292c593315Sopenharmony_ci if (end == last) { 15302c593315Sopenharmony_ci break; 15312c593315Sopenharmony_ci } 15322c593315Sopenharmony_ci 15332c593315Sopenharmony_ci first = end + 1; 15342c593315Sopenharmony_ci } 15352c593315Sopenharmony_ci 15362c593315Sopenharmony_ci return 0; 15372c593315Sopenharmony_ci} 15382c593315Sopenharmony_ci} // namespace 15392c593315Sopenharmony_ci 15402c593315Sopenharmony_cinamespace { 15412c593315Sopenharmony_ci// Reads *.sct files from directory denoted by |dir_path|. |dir_path| 15422c593315Sopenharmony_ci// must be NULL-terminated string. 15432c593315Sopenharmony_ciint read_tls_sct_from_dir(std::vector<uint8_t> &dst, const StringRef &opt, 15442c593315Sopenharmony_ci const StringRef &dir_path) { 15452c593315Sopenharmony_ci std::array<char, STRERROR_BUFSIZE> errbuf; 15462c593315Sopenharmony_ci 15472c593315Sopenharmony_ci auto dir = opendir(dir_path.c_str()); 15482c593315Sopenharmony_ci if (dir == nullptr) { 15492c593315Sopenharmony_ci auto error = errno; 15502c593315Sopenharmony_ci LOG(ERROR) << opt << ": " << dir_path << ": " 15512c593315Sopenharmony_ci << xsi_strerror(error, errbuf.data(), errbuf.size()); 15522c593315Sopenharmony_ci return -1; 15532c593315Sopenharmony_ci } 15542c593315Sopenharmony_ci 15552c593315Sopenharmony_ci auto closer = defer(closedir, dir); 15562c593315Sopenharmony_ci 15572c593315Sopenharmony_ci // 2 bytes total length field 15582c593315Sopenharmony_ci auto len_idx = std::distance(std::begin(dst), std::end(dst)); 15592c593315Sopenharmony_ci dst.insert(std::end(dst), 2, 0); 15602c593315Sopenharmony_ci 15612c593315Sopenharmony_ci for (;;) { 15622c593315Sopenharmony_ci errno = 0; 15632c593315Sopenharmony_ci auto ent = readdir(dir); 15642c593315Sopenharmony_ci if (ent == nullptr) { 15652c593315Sopenharmony_ci if (errno != 0) { 15662c593315Sopenharmony_ci auto error = errno; 15672c593315Sopenharmony_ci LOG(ERROR) << opt << ": failed to read directory " << dir_path << ": " 15682c593315Sopenharmony_ci << xsi_strerror(error, errbuf.data(), errbuf.size()); 15692c593315Sopenharmony_ci return -1; 15702c593315Sopenharmony_ci } 15712c593315Sopenharmony_ci break; 15722c593315Sopenharmony_ci } 15732c593315Sopenharmony_ci 15742c593315Sopenharmony_ci auto name = StringRef{ent->d_name}; 15752c593315Sopenharmony_ci 15762c593315Sopenharmony_ci if (name[0] == '.' || !util::iends_with_l(name, ".sct")) { 15772c593315Sopenharmony_ci continue; 15782c593315Sopenharmony_ci } 15792c593315Sopenharmony_ci 15802c593315Sopenharmony_ci std::string path; 15812c593315Sopenharmony_ci path.resize(dir_path.size() + 1 + name.size()); 15822c593315Sopenharmony_ci { 15832c593315Sopenharmony_ci auto p = std::begin(path); 15842c593315Sopenharmony_ci p = std::copy(std::begin(dir_path), std::end(dir_path), p); 15852c593315Sopenharmony_ci *p++ = '/'; 15862c593315Sopenharmony_ci std::copy(std::begin(name), std::end(name), p); 15872c593315Sopenharmony_ci } 15882c593315Sopenharmony_ci 15892c593315Sopenharmony_ci auto fd = open(path.c_str(), O_RDONLY); 15902c593315Sopenharmony_ci if (fd == -1) { 15912c593315Sopenharmony_ci auto error = errno; 15922c593315Sopenharmony_ci LOG(ERROR) << opt << ": failed to read SCT from " << path << ": " 15932c593315Sopenharmony_ci << xsi_strerror(error, errbuf.data(), errbuf.size()); 15942c593315Sopenharmony_ci return -1; 15952c593315Sopenharmony_ci } 15962c593315Sopenharmony_ci 15972c593315Sopenharmony_ci auto closer = defer(close, fd); 15982c593315Sopenharmony_ci 15992c593315Sopenharmony_ci // 2 bytes length field for this SCT. 16002c593315Sopenharmony_ci auto len_idx = std::distance(std::begin(dst), std::end(dst)); 16012c593315Sopenharmony_ci dst.insert(std::end(dst), 2, 0); 16022c593315Sopenharmony_ci 16032c593315Sopenharmony_ci // *.sct file tends to be small; around 110+ bytes. 16042c593315Sopenharmony_ci std::array<char, 256> buf; 16052c593315Sopenharmony_ci for (;;) { 16062c593315Sopenharmony_ci ssize_t nread; 16072c593315Sopenharmony_ci while ((nread = read(fd, buf.data(), buf.size())) == -1 && errno == EINTR) 16082c593315Sopenharmony_ci ; 16092c593315Sopenharmony_ci 16102c593315Sopenharmony_ci if (nread == -1) { 16112c593315Sopenharmony_ci auto error = errno; 16122c593315Sopenharmony_ci LOG(ERROR) << opt << ": failed to read SCT data from " << path << ": " 16132c593315Sopenharmony_ci << xsi_strerror(error, errbuf.data(), errbuf.size()); 16142c593315Sopenharmony_ci return -1; 16152c593315Sopenharmony_ci } 16162c593315Sopenharmony_ci 16172c593315Sopenharmony_ci if (nread == 0) { 16182c593315Sopenharmony_ci break; 16192c593315Sopenharmony_ci } 16202c593315Sopenharmony_ci 16212c593315Sopenharmony_ci dst.insert(std::end(dst), std::begin(buf), std::begin(buf) + nread); 16222c593315Sopenharmony_ci 16232c593315Sopenharmony_ci if (dst.size() > MAX_SCT_EXT_LEN) { 16242c593315Sopenharmony_ci LOG(ERROR) << opt << ": the concatenated SCT data from " << dir_path 16252c593315Sopenharmony_ci << " is too large. Max " << MAX_SCT_EXT_LEN; 16262c593315Sopenharmony_ci return -1; 16272c593315Sopenharmony_ci } 16282c593315Sopenharmony_ci } 16292c593315Sopenharmony_ci 16302c593315Sopenharmony_ci auto len = dst.size() - len_idx - 2; 16312c593315Sopenharmony_ci 16322c593315Sopenharmony_ci if (len == 0) { 16332c593315Sopenharmony_ci dst.resize(dst.size() - 2); 16342c593315Sopenharmony_ci continue; 16352c593315Sopenharmony_ci } 16362c593315Sopenharmony_ci 16372c593315Sopenharmony_ci dst[len_idx] = len >> 8; 16382c593315Sopenharmony_ci dst[len_idx + 1] = len; 16392c593315Sopenharmony_ci } 16402c593315Sopenharmony_ci 16412c593315Sopenharmony_ci auto len = dst.size() - len_idx - 2; 16422c593315Sopenharmony_ci 16432c593315Sopenharmony_ci if (len == 0) { 16442c593315Sopenharmony_ci dst.resize(dst.size() - 2); 16452c593315Sopenharmony_ci return 0; 16462c593315Sopenharmony_ci } 16472c593315Sopenharmony_ci 16482c593315Sopenharmony_ci dst[len_idx] = len >> 8; 16492c593315Sopenharmony_ci dst[len_idx + 1] = len; 16502c593315Sopenharmony_ci 16512c593315Sopenharmony_ci return 0; 16522c593315Sopenharmony_ci} 16532c593315Sopenharmony_ci} // namespace 16542c593315Sopenharmony_ci 16552c593315Sopenharmony_ci#if !LIBRESSL_LEGACY_API 16562c593315Sopenharmony_cinamespace { 16572c593315Sopenharmony_ci// Reads PSK secrets from path, and parses each line. The result is 16582c593315Sopenharmony_ci// directly stored into config->tls.psk_secrets. This function 16592c593315Sopenharmony_ci// returns 0 if it succeeds, or -1. 16602c593315Sopenharmony_ciint parse_psk_secrets(Config *config, const StringRef &path) { 16612c593315Sopenharmony_ci auto &tlsconf = config->tls; 16622c593315Sopenharmony_ci 16632c593315Sopenharmony_ci std::ifstream f(path.c_str(), std::ios::binary); 16642c593315Sopenharmony_ci if (!f) { 16652c593315Sopenharmony_ci LOG(ERROR) << SHRPX_OPT_PSK_SECRETS << ": could not open file " << path; 16662c593315Sopenharmony_ci return -1; 16672c593315Sopenharmony_ci } 16682c593315Sopenharmony_ci 16692c593315Sopenharmony_ci size_t lineno = 0; 16702c593315Sopenharmony_ci std::string line; 16712c593315Sopenharmony_ci while (std::getline(f, line)) { 16722c593315Sopenharmony_ci ++lineno; 16732c593315Sopenharmony_ci if (line.empty() || line[0] == '#') { 16742c593315Sopenharmony_ci continue; 16752c593315Sopenharmony_ci } 16762c593315Sopenharmony_ci 16772c593315Sopenharmony_ci auto sep_it = std::find(std::begin(line), std::end(line), ':'); 16782c593315Sopenharmony_ci if (sep_it == std::end(line)) { 16792c593315Sopenharmony_ci LOG(ERROR) << SHRPX_OPT_PSK_SECRETS 16802c593315Sopenharmony_ci << ": could not fine separator at line " << lineno; 16812c593315Sopenharmony_ci return -1; 16822c593315Sopenharmony_ci } 16832c593315Sopenharmony_ci 16842c593315Sopenharmony_ci if (sep_it == std::begin(line)) { 16852c593315Sopenharmony_ci LOG(ERROR) << SHRPX_OPT_PSK_SECRETS << ": empty identity at line " 16862c593315Sopenharmony_ci << lineno; 16872c593315Sopenharmony_ci return -1; 16882c593315Sopenharmony_ci } 16892c593315Sopenharmony_ci 16902c593315Sopenharmony_ci if (sep_it + 1 == std::end(line)) { 16912c593315Sopenharmony_ci LOG(ERROR) << SHRPX_OPT_PSK_SECRETS << ": empty secret at line " 16922c593315Sopenharmony_ci << lineno; 16932c593315Sopenharmony_ci return -1; 16942c593315Sopenharmony_ci } 16952c593315Sopenharmony_ci 16962c593315Sopenharmony_ci if (!util::is_hex_string(StringRef{sep_it + 1, std::end(line)})) { 16972c593315Sopenharmony_ci LOG(ERROR) << SHRPX_OPT_PSK_SECRETS 16982c593315Sopenharmony_ci << ": secret must be hex string at line " << lineno; 16992c593315Sopenharmony_ci return -1; 17002c593315Sopenharmony_ci } 17012c593315Sopenharmony_ci 17022c593315Sopenharmony_ci auto identity = 17032c593315Sopenharmony_ci make_string_ref(config->balloc, StringRef{std::begin(line), sep_it}); 17042c593315Sopenharmony_ci 17052c593315Sopenharmony_ci auto secret = 17062c593315Sopenharmony_ci util::decode_hex(config->balloc, StringRef{sep_it + 1, std::end(line)}); 17072c593315Sopenharmony_ci 17082c593315Sopenharmony_ci auto rv = tlsconf.psk_secrets.emplace(identity, secret); 17092c593315Sopenharmony_ci if (!rv.second) { 17102c593315Sopenharmony_ci LOG(ERROR) << SHRPX_OPT_PSK_SECRETS 17112c593315Sopenharmony_ci << ": identity has already been registered at line " << lineno; 17122c593315Sopenharmony_ci return -1; 17132c593315Sopenharmony_ci } 17142c593315Sopenharmony_ci } 17152c593315Sopenharmony_ci 17162c593315Sopenharmony_ci return 0; 17172c593315Sopenharmony_ci} 17182c593315Sopenharmony_ci} // namespace 17192c593315Sopenharmony_ci#endif // !LIBRESSL_LEGACY_API 17202c593315Sopenharmony_ci 17212c593315Sopenharmony_ci#if !LIBRESSL_LEGACY_API 17222c593315Sopenharmony_cinamespace { 17232c593315Sopenharmony_ci// Reads PSK secrets from path, and parses each line. The result is 17242c593315Sopenharmony_ci// directly stored into config->tls.client.psk. This function returns 17252c593315Sopenharmony_ci// 0 if it succeeds, or -1. 17262c593315Sopenharmony_ciint parse_client_psk_secrets(Config *config, const StringRef &path) { 17272c593315Sopenharmony_ci auto &tlsconf = config->tls; 17282c593315Sopenharmony_ci 17292c593315Sopenharmony_ci std::ifstream f(path.c_str(), std::ios::binary); 17302c593315Sopenharmony_ci if (!f) { 17312c593315Sopenharmony_ci LOG(ERROR) << SHRPX_OPT_CLIENT_PSK_SECRETS << ": could not open file " 17322c593315Sopenharmony_ci << path; 17332c593315Sopenharmony_ci return -1; 17342c593315Sopenharmony_ci } 17352c593315Sopenharmony_ci 17362c593315Sopenharmony_ci size_t lineno = 0; 17372c593315Sopenharmony_ci std::string line; 17382c593315Sopenharmony_ci while (std::getline(f, line)) { 17392c593315Sopenharmony_ci ++lineno; 17402c593315Sopenharmony_ci if (line.empty() || line[0] == '#') { 17412c593315Sopenharmony_ci continue; 17422c593315Sopenharmony_ci } 17432c593315Sopenharmony_ci 17442c593315Sopenharmony_ci auto sep_it = std::find(std::begin(line), std::end(line), ':'); 17452c593315Sopenharmony_ci if (sep_it == std::end(line)) { 17462c593315Sopenharmony_ci LOG(ERROR) << SHRPX_OPT_CLIENT_PSK_SECRETS 17472c593315Sopenharmony_ci << ": could not find separator at line " << lineno; 17482c593315Sopenharmony_ci return -1; 17492c593315Sopenharmony_ci } 17502c593315Sopenharmony_ci 17512c593315Sopenharmony_ci if (sep_it == std::begin(line)) { 17522c593315Sopenharmony_ci LOG(ERROR) << SHRPX_OPT_CLIENT_PSK_SECRETS << ": empty identity at line " 17532c593315Sopenharmony_ci << lineno; 17542c593315Sopenharmony_ci return -1; 17552c593315Sopenharmony_ci } 17562c593315Sopenharmony_ci 17572c593315Sopenharmony_ci if (sep_it + 1 == std::end(line)) { 17582c593315Sopenharmony_ci LOG(ERROR) << SHRPX_OPT_CLIENT_PSK_SECRETS << ": empty secret at line " 17592c593315Sopenharmony_ci << lineno; 17602c593315Sopenharmony_ci return -1; 17612c593315Sopenharmony_ci } 17622c593315Sopenharmony_ci 17632c593315Sopenharmony_ci if (!util::is_hex_string(StringRef{sep_it + 1, std::end(line)})) { 17642c593315Sopenharmony_ci LOG(ERROR) << SHRPX_OPT_CLIENT_PSK_SECRETS 17652c593315Sopenharmony_ci << ": secret must be hex string at line " << lineno; 17662c593315Sopenharmony_ci return -1; 17672c593315Sopenharmony_ci } 17682c593315Sopenharmony_ci 17692c593315Sopenharmony_ci tlsconf.client.psk.identity = 17702c593315Sopenharmony_ci make_string_ref(config->balloc, StringRef{std::begin(line), sep_it}); 17712c593315Sopenharmony_ci 17722c593315Sopenharmony_ci tlsconf.client.psk.secret = 17732c593315Sopenharmony_ci util::decode_hex(config->balloc, StringRef{sep_it + 1, std::end(line)}); 17742c593315Sopenharmony_ci 17752c593315Sopenharmony_ci return 0; 17762c593315Sopenharmony_ci } 17772c593315Sopenharmony_ci 17782c593315Sopenharmony_ci return 0; 17792c593315Sopenharmony_ci} 17802c593315Sopenharmony_ci} // namespace 17812c593315Sopenharmony_ci#endif // !LIBRESSL_LEGACY_API 17822c593315Sopenharmony_ci 17832c593315Sopenharmony_ci// generated by gennghttpxfun.py 17842c593315Sopenharmony_ciint option_lookup_token(const char *name, size_t namelen) { 17852c593315Sopenharmony_ci switch (namelen) { 17862c593315Sopenharmony_ci case 4: 17872c593315Sopenharmony_ci switch (name[3]) { 17882c593315Sopenharmony_ci case 'f': 17892c593315Sopenharmony_ci if (util::strieq_l("con", name, 3)) { 17902c593315Sopenharmony_ci return SHRPX_OPTID_CONF; 17912c593315Sopenharmony_ci } 17922c593315Sopenharmony_ci break; 17932c593315Sopenharmony_ci case 'r': 17942c593315Sopenharmony_ci if (util::strieq_l("use", name, 3)) { 17952c593315Sopenharmony_ci return SHRPX_OPTID_USER; 17962c593315Sopenharmony_ci } 17972c593315Sopenharmony_ci break; 17982c593315Sopenharmony_ci } 17992c593315Sopenharmony_ci break; 18002c593315Sopenharmony_ci case 6: 18012c593315Sopenharmony_ci switch (name[5]) { 18022c593315Sopenharmony_ci case 'a': 18032c593315Sopenharmony_ci if (util::strieq_l("no-vi", name, 5)) { 18042c593315Sopenharmony_ci return SHRPX_OPTID_NO_VIA; 18052c593315Sopenharmony_ci } 18062c593315Sopenharmony_ci break; 18072c593315Sopenharmony_ci case 'c': 18082c593315Sopenharmony_ci if (util::strieq_l("altsv", name, 5)) { 18092c593315Sopenharmony_ci return SHRPX_OPTID_ALTSVC; 18102c593315Sopenharmony_ci } 18112c593315Sopenharmony_ci break; 18122c593315Sopenharmony_ci case 'n': 18132c593315Sopenharmony_ci if (util::strieq_l("daemo", name, 5)) { 18142c593315Sopenharmony_ci return SHRPX_OPTID_DAEMON; 18152c593315Sopenharmony_ci } 18162c593315Sopenharmony_ci break; 18172c593315Sopenharmony_ci case 't': 18182c593315Sopenharmony_ci if (util::strieq_l("cacer", name, 5)) { 18192c593315Sopenharmony_ci return SHRPX_OPTID_CACERT; 18202c593315Sopenharmony_ci } 18212c593315Sopenharmony_ci if (util::strieq_l("clien", name, 5)) { 18222c593315Sopenharmony_ci return SHRPX_OPTID_CLIENT; 18232c593315Sopenharmony_ci } 18242c593315Sopenharmony_ci break; 18252c593315Sopenharmony_ci } 18262c593315Sopenharmony_ci break; 18272c593315Sopenharmony_ci case 7: 18282c593315Sopenharmony_ci switch (name[6]) { 18292c593315Sopenharmony_ci case 'd': 18302c593315Sopenharmony_ci if (util::strieq_l("backen", name, 6)) { 18312c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND; 18322c593315Sopenharmony_ci } 18332c593315Sopenharmony_ci break; 18342c593315Sopenharmony_ci case 'e': 18352c593315Sopenharmony_ci if (util::strieq_l("includ", name, 6)) { 18362c593315Sopenharmony_ci return SHRPX_OPTID_INCLUDE; 18372c593315Sopenharmony_ci } 18382c593315Sopenharmony_ci break; 18392c593315Sopenharmony_ci case 'g': 18402c593315Sopenharmony_ci if (util::strieq_l("backlo", name, 6)) { 18412c593315Sopenharmony_ci return SHRPX_OPTID_BACKLOG; 18422c593315Sopenharmony_ci } 18432c593315Sopenharmony_ci if (util::strieq_l("paddin", name, 6)) { 18442c593315Sopenharmony_ci return SHRPX_OPTID_PADDING; 18452c593315Sopenharmony_ci } 18462c593315Sopenharmony_ci break; 18472c593315Sopenharmony_ci case 'p': 18482c593315Sopenharmony_ci if (util::strieq_l("no-ocs", name, 6)) { 18492c593315Sopenharmony_ci return SHRPX_OPTID_NO_OCSP; 18502c593315Sopenharmony_ci } 18512c593315Sopenharmony_ci break; 18522c593315Sopenharmony_ci case 's': 18532c593315Sopenharmony_ci if (util::strieq_l("cipher", name, 6)) { 18542c593315Sopenharmony_ci return SHRPX_OPTID_CIPHERS; 18552c593315Sopenharmony_ci } 18562c593315Sopenharmony_ci if (util::strieq_l("worker", name, 6)) { 18572c593315Sopenharmony_ci return SHRPX_OPTID_WORKERS; 18582c593315Sopenharmony_ci } 18592c593315Sopenharmony_ci break; 18602c593315Sopenharmony_ci case 't': 18612c593315Sopenharmony_ci if (util::strieq_l("subcer", name, 6)) { 18622c593315Sopenharmony_ci return SHRPX_OPTID_SUBCERT; 18632c593315Sopenharmony_ci } 18642c593315Sopenharmony_ci break; 18652c593315Sopenharmony_ci } 18662c593315Sopenharmony_ci break; 18672c593315Sopenharmony_ci case 8: 18682c593315Sopenharmony_ci switch (name[7]) { 18692c593315Sopenharmony_ci case 'd': 18702c593315Sopenharmony_ci if (util::strieq_l("fronten", name, 7)) { 18712c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND; 18722c593315Sopenharmony_ci } 18732c593315Sopenharmony_ci break; 18742c593315Sopenharmony_ci case 'e': 18752c593315Sopenharmony_ci if (util::strieq_l("insecur", name, 7)) { 18762c593315Sopenharmony_ci return SHRPX_OPTID_INSECURE; 18772c593315Sopenharmony_ci } 18782c593315Sopenharmony_ci if (util::strieq_l("pid-fil", name, 7)) { 18792c593315Sopenharmony_ci return SHRPX_OPTID_PID_FILE; 18802c593315Sopenharmony_ci } 18812c593315Sopenharmony_ci break; 18822c593315Sopenharmony_ci case 'n': 18832c593315Sopenharmony_ci if (util::strieq_l("fastope", name, 7)) { 18842c593315Sopenharmony_ci return SHRPX_OPTID_FASTOPEN; 18852c593315Sopenharmony_ci } 18862c593315Sopenharmony_ci break; 18872c593315Sopenharmony_ci case 's': 18882c593315Sopenharmony_ci if (util::strieq_l("tls-ktl", name, 7)) { 18892c593315Sopenharmony_ci return SHRPX_OPTID_TLS_KTLS; 18902c593315Sopenharmony_ci } 18912c593315Sopenharmony_ci break; 18922c593315Sopenharmony_ci case 't': 18932c593315Sopenharmony_ci if (util::strieq_l("npn-lis", name, 7)) { 18942c593315Sopenharmony_ci return SHRPX_OPTID_NPN_LIST; 18952c593315Sopenharmony_ci } 18962c593315Sopenharmony_ci break; 18972c593315Sopenharmony_ci } 18982c593315Sopenharmony_ci break; 18992c593315Sopenharmony_ci case 9: 19002c593315Sopenharmony_ci switch (name[8]) { 19012c593315Sopenharmony_ci case 'e': 19022c593315Sopenharmony_ci if (util::strieq_l("no-kqueu", name, 8)) { 19032c593315Sopenharmony_ci return SHRPX_OPTID_NO_KQUEUE; 19042c593315Sopenharmony_ci } 19052c593315Sopenharmony_ci if (util::strieq_l("read-rat", name, 8)) { 19062c593315Sopenharmony_ci return SHRPX_OPTID_READ_RATE; 19072c593315Sopenharmony_ci } 19082c593315Sopenharmony_ci break; 19092c593315Sopenharmony_ci case 'l': 19102c593315Sopenharmony_ci if (util::strieq_l("log-leve", name, 8)) { 19112c593315Sopenharmony_ci return SHRPX_OPTID_LOG_LEVEL; 19122c593315Sopenharmony_ci } 19132c593315Sopenharmony_ci break; 19142c593315Sopenharmony_ci } 19152c593315Sopenharmony_ci break; 19162c593315Sopenharmony_ci case 10: 19172c593315Sopenharmony_ci switch (name[9]) { 19182c593315Sopenharmony_ci case 'e': 19192c593315Sopenharmony_ci if (util::strieq_l("error-pag", name, 9)) { 19202c593315Sopenharmony_ci return SHRPX_OPTID_ERROR_PAGE; 19212c593315Sopenharmony_ci } 19222c593315Sopenharmony_ci if (util::strieq_l("mruby-fil", name, 9)) { 19232c593315Sopenharmony_ci return SHRPX_OPTID_MRUBY_FILE; 19242c593315Sopenharmony_ci } 19252c593315Sopenharmony_ci if (util::strieq_l("write-rat", name, 9)) { 19262c593315Sopenharmony_ci return SHRPX_OPTID_WRITE_RATE; 19272c593315Sopenharmony_ci } 19282c593315Sopenharmony_ci break; 19292c593315Sopenharmony_ci case 't': 19302c593315Sopenharmony_ci if (util::strieq_l("read-burs", name, 9)) { 19312c593315Sopenharmony_ci return SHRPX_OPTID_READ_BURST; 19322c593315Sopenharmony_ci } 19332c593315Sopenharmony_ci break; 19342c593315Sopenharmony_ci } 19352c593315Sopenharmony_ci break; 19362c593315Sopenharmony_ci case 11: 19372c593315Sopenharmony_ci switch (name[10]) { 19382c593315Sopenharmony_ci case 'e': 19392c593315Sopenharmony_ci if (util::strieq_l("server-nam", name, 10)) { 19402c593315Sopenharmony_ci return SHRPX_OPTID_SERVER_NAME; 19412c593315Sopenharmony_ci } 19422c593315Sopenharmony_ci break; 19432c593315Sopenharmony_ci case 'f': 19442c593315Sopenharmony_ci if (util::strieq_l("no-quic-bp", name, 10)) { 19452c593315Sopenharmony_ci return SHRPX_OPTID_NO_QUIC_BPF; 19462c593315Sopenharmony_ci } 19472c593315Sopenharmony_ci break; 19482c593315Sopenharmony_ci case 'r': 19492c593315Sopenharmony_ci if (util::strieq_l("tls-sct-di", name, 10)) { 19502c593315Sopenharmony_ci return SHRPX_OPTID_TLS_SCT_DIR; 19512c593315Sopenharmony_ci } 19522c593315Sopenharmony_ci break; 19532c593315Sopenharmony_ci case 's': 19542c593315Sopenharmony_ci if (util::strieq_l("backend-tl", name, 10)) { 19552c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_TLS; 19562c593315Sopenharmony_ci } 19572c593315Sopenharmony_ci if (util::strieq_l("ecdh-curve", name, 10)) { 19582c593315Sopenharmony_ci return SHRPX_OPTID_ECDH_CURVES; 19592c593315Sopenharmony_ci } 19602c593315Sopenharmony_ci if (util::strieq_l("psk-secret", name, 10)) { 19612c593315Sopenharmony_ci return SHRPX_OPTID_PSK_SECRETS; 19622c593315Sopenharmony_ci } 19632c593315Sopenharmony_ci break; 19642c593315Sopenharmony_ci case 't': 19652c593315Sopenharmony_ci if (util::strieq_l("write-burs", name, 10)) { 19662c593315Sopenharmony_ci return SHRPX_OPTID_WRITE_BURST; 19672c593315Sopenharmony_ci } 19682c593315Sopenharmony_ci break; 19692c593315Sopenharmony_ci case 'y': 19702c593315Sopenharmony_ci if (util::strieq_l("dns-max-tr", name, 10)) { 19712c593315Sopenharmony_ci return SHRPX_OPTID_DNS_MAX_TRY; 19722c593315Sopenharmony_ci } 19732c593315Sopenharmony_ci if (util::strieq_l("http2-prox", name, 10)) { 19742c593315Sopenharmony_ci return SHRPX_OPTID_HTTP2_PROXY; 19752c593315Sopenharmony_ci } 19762c593315Sopenharmony_ci break; 19772c593315Sopenharmony_ci } 19782c593315Sopenharmony_ci break; 19792c593315Sopenharmony_ci case 12: 19802c593315Sopenharmony_ci switch (name[11]) { 19812c593315Sopenharmony_ci case '4': 19822c593315Sopenharmony_ci if (util::strieq_l("backend-ipv", name, 11)) { 19832c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_IPV4; 19842c593315Sopenharmony_ci } 19852c593315Sopenharmony_ci break; 19862c593315Sopenharmony_ci case '6': 19872c593315Sopenharmony_ci if (util::strieq_l("backend-ipv", name, 11)) { 19882c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_IPV6; 19892c593315Sopenharmony_ci } 19902c593315Sopenharmony_ci break; 19912c593315Sopenharmony_ci case 'c': 19922c593315Sopenharmony_ci if (util::strieq_l("http2-altsv", name, 11)) { 19932c593315Sopenharmony_ci return SHRPX_OPTID_HTTP2_ALTSVC; 19942c593315Sopenharmony_ci } 19952c593315Sopenharmony_ci break; 19962c593315Sopenharmony_ci case 'e': 19972c593315Sopenharmony_ci if (util::strieq_l("host-rewrit", name, 11)) { 19982c593315Sopenharmony_ci return SHRPX_OPTID_HOST_REWRITE; 19992c593315Sopenharmony_ci } 20002c593315Sopenharmony_ci if (util::strieq_l("http2-bridg", name, 11)) { 20012c593315Sopenharmony_ci return SHRPX_OPTID_HTTP2_BRIDGE; 20022c593315Sopenharmony_ci } 20032c593315Sopenharmony_ci break; 20042c593315Sopenharmony_ci case 'p': 20052c593315Sopenharmony_ci if (util::strieq_l("ocsp-startu", name, 11)) { 20062c593315Sopenharmony_ci return SHRPX_OPTID_OCSP_STARTUP; 20072c593315Sopenharmony_ci } 20082c593315Sopenharmony_ci break; 20092c593315Sopenharmony_ci case 'y': 20102c593315Sopenharmony_ci if (util::strieq_l("client-prox", name, 11)) { 20112c593315Sopenharmony_ci return SHRPX_OPTID_CLIENT_PROXY; 20122c593315Sopenharmony_ci } 20132c593315Sopenharmony_ci if (util::strieq_l("forwarded-b", name, 11)) { 20142c593315Sopenharmony_ci return SHRPX_OPTID_FORWARDED_BY; 20152c593315Sopenharmony_ci } 20162c593315Sopenharmony_ci break; 20172c593315Sopenharmony_ci } 20182c593315Sopenharmony_ci break; 20192c593315Sopenharmony_ci case 13: 20202c593315Sopenharmony_ci switch (name[12]) { 20212c593315Sopenharmony_ci case 'd': 20222c593315Sopenharmony_ci if (util::strieq_l("add-forwarde", name, 12)) { 20232c593315Sopenharmony_ci return SHRPX_OPTID_ADD_FORWARDED; 20242c593315Sopenharmony_ci } 20252c593315Sopenharmony_ci if (util::strieq_l("single-threa", name, 12)) { 20262c593315Sopenharmony_ci return SHRPX_OPTID_SINGLE_THREAD; 20272c593315Sopenharmony_ci } 20282c593315Sopenharmony_ci break; 20292c593315Sopenharmony_ci case 'e': 20302c593315Sopenharmony_ci if (util::strieq_l("dh-param-fil", name, 12)) { 20312c593315Sopenharmony_ci return SHRPX_OPTID_DH_PARAM_FILE; 20322c593315Sopenharmony_ci } 20332c593315Sopenharmony_ci if (util::strieq_l("errorlog-fil", name, 12)) { 20342c593315Sopenharmony_ci return SHRPX_OPTID_ERRORLOG_FILE; 20352c593315Sopenharmony_ci } 20362c593315Sopenharmony_ci if (util::strieq_l("rlimit-nofil", name, 12)) { 20372c593315Sopenharmony_ci return SHRPX_OPTID_RLIMIT_NOFILE; 20382c593315Sopenharmony_ci } 20392c593315Sopenharmony_ci break; 20402c593315Sopenharmony_ci case 'r': 20412c593315Sopenharmony_ci if (util::strieq_l("forwarded-fo", name, 12)) { 20422c593315Sopenharmony_ci return SHRPX_OPTID_FORWARDED_FOR; 20432c593315Sopenharmony_ci } 20442c593315Sopenharmony_ci break; 20452c593315Sopenharmony_ci case 's': 20462c593315Sopenharmony_ci if (util::strieq_l("tls13-cipher", name, 12)) { 20472c593315Sopenharmony_ci return SHRPX_OPTID_TLS13_CIPHERS; 20482c593315Sopenharmony_ci } 20492c593315Sopenharmony_ci break; 20502c593315Sopenharmony_ci case 't': 20512c593315Sopenharmony_ci if (util::strieq_l("verify-clien", name, 12)) { 20522c593315Sopenharmony_ci return SHRPX_OPTID_VERIFY_CLIENT; 20532c593315Sopenharmony_ci } 20542c593315Sopenharmony_ci break; 20552c593315Sopenharmony_ci } 20562c593315Sopenharmony_ci break; 20572c593315Sopenharmony_ci case 14: 20582c593315Sopenharmony_ci switch (name[13]) { 20592c593315Sopenharmony_ci case 'd': 20602c593315Sopenharmony_ci if (util::strieq_l("quic-server-i", name, 13)) { 20612c593315Sopenharmony_ci return SHRPX_OPTID_QUIC_SERVER_ID; 20622c593315Sopenharmony_ci } 20632c593315Sopenharmony_ci break; 20642c593315Sopenharmony_ci case 'e': 20652c593315Sopenharmony_ci if (util::strieq_l("accesslog-fil", name, 13)) { 20662c593315Sopenharmony_ci return SHRPX_OPTID_ACCESSLOG_FILE; 20672c593315Sopenharmony_ci } 20682c593315Sopenharmony_ci break; 20692c593315Sopenharmony_ci case 'h': 20702c593315Sopenharmony_ci if (util::strieq_l("no-server-pus", name, 13)) { 20712c593315Sopenharmony_ci return SHRPX_OPTID_NO_SERVER_PUSH; 20722c593315Sopenharmony_ci } 20732c593315Sopenharmony_ci break; 20742c593315Sopenharmony_ci case 'k': 20752c593315Sopenharmony_ci if (util::strieq_l("rlimit-memloc", name, 13)) { 20762c593315Sopenharmony_ci return SHRPX_OPTID_RLIMIT_MEMLOCK; 20772c593315Sopenharmony_ci } 20782c593315Sopenharmony_ci break; 20792c593315Sopenharmony_ci case 'p': 20802c593315Sopenharmony_ci if (util::strieq_l("no-verify-ocs", name, 13)) { 20812c593315Sopenharmony_ci return SHRPX_OPTID_NO_VERIFY_OCSP; 20822c593315Sopenharmony_ci } 20832c593315Sopenharmony_ci break; 20842c593315Sopenharmony_ci case 's': 20852c593315Sopenharmony_ci if (util::strieq_l("backend-no-tl", name, 13)) { 20862c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_NO_TLS; 20872c593315Sopenharmony_ci } 20882c593315Sopenharmony_ci if (util::strieq_l("client-cipher", name, 13)) { 20892c593315Sopenharmony_ci return SHRPX_OPTID_CLIENT_CIPHERS; 20902c593315Sopenharmony_ci } 20912c593315Sopenharmony_ci if (util::strieq_l("single-proces", name, 13)) { 20922c593315Sopenharmony_ci return SHRPX_OPTID_SINGLE_PROCESS; 20932c593315Sopenharmony_ci } 20942c593315Sopenharmony_ci break; 20952c593315Sopenharmony_ci case 't': 20962c593315Sopenharmony_ci if (util::strieq_l("tls-proto-lis", name, 13)) { 20972c593315Sopenharmony_ci return SHRPX_OPTID_TLS_PROTO_LIST; 20982c593315Sopenharmony_ci } 20992c593315Sopenharmony_ci break; 21002c593315Sopenharmony_ci } 21012c593315Sopenharmony_ci break; 21022c593315Sopenharmony_ci case 15: 21032c593315Sopenharmony_ci switch (name[14]) { 21042c593315Sopenharmony_ci case 'e': 21052c593315Sopenharmony_ci if (util::strieq_l("no-host-rewrit", name, 14)) { 21062c593315Sopenharmony_ci return SHRPX_OPTID_NO_HOST_REWRITE; 21072c593315Sopenharmony_ci } 21082c593315Sopenharmony_ci break; 21092c593315Sopenharmony_ci case 'g': 21102c593315Sopenharmony_ci if (util::strieq_l("errorlog-syslo", name, 14)) { 21112c593315Sopenharmony_ci return SHRPX_OPTID_ERRORLOG_SYSLOG; 21122c593315Sopenharmony_ci } 21132c593315Sopenharmony_ci break; 21142c593315Sopenharmony_ci case 's': 21152c593315Sopenharmony_ci if (util::strieq_l("frontend-no-tl", name, 14)) { 21162c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_NO_TLS; 21172c593315Sopenharmony_ci } 21182c593315Sopenharmony_ci break; 21192c593315Sopenharmony_ci case 'y': 21202c593315Sopenharmony_ci if (util::strieq_l("syslog-facilit", name, 14)) { 21212c593315Sopenharmony_ci return SHRPX_OPTID_SYSLOG_FACILITY; 21222c593315Sopenharmony_ci } 21232c593315Sopenharmony_ci break; 21242c593315Sopenharmony_ci } 21252c593315Sopenharmony_ci break; 21262c593315Sopenharmony_ci case 16: 21272c593315Sopenharmony_ci switch (name[15]) { 21282c593315Sopenharmony_ci case 'e': 21292c593315Sopenharmony_ci if (util::strieq_l("certificate-fil", name, 15)) { 21302c593315Sopenharmony_ci return SHRPX_OPTID_CERTIFICATE_FILE; 21312c593315Sopenharmony_ci } 21322c593315Sopenharmony_ci if (util::strieq_l("client-cert-fil", name, 15)) { 21332c593315Sopenharmony_ci return SHRPX_OPTID_CLIENT_CERT_FILE; 21342c593315Sopenharmony_ci } 21352c593315Sopenharmony_ci if (util::strieq_l("private-key-fil", name, 15)) { 21362c593315Sopenharmony_ci return SHRPX_OPTID_PRIVATE_KEY_FILE; 21372c593315Sopenharmony_ci } 21382c593315Sopenharmony_ci if (util::strieq_l("worker-read-rat", name, 15)) { 21392c593315Sopenharmony_ci return SHRPX_OPTID_WORKER_READ_RATE; 21402c593315Sopenharmony_ci } 21412c593315Sopenharmony_ci break; 21422c593315Sopenharmony_ci case 'g': 21432c593315Sopenharmony_ci if (util::strieq_l("accesslog-syslo", name, 15)) { 21442c593315Sopenharmony_ci return SHRPX_OPTID_ACCESSLOG_SYSLOG; 21452c593315Sopenharmony_ci } 21462c593315Sopenharmony_ci break; 21472c593315Sopenharmony_ci case 't': 21482c593315Sopenharmony_ci if (util::strieq_l("accesslog-forma", name, 15)) { 21492c593315Sopenharmony_ci return SHRPX_OPTID_ACCESSLOG_FORMAT; 21502c593315Sopenharmony_ci } 21512c593315Sopenharmony_ci break; 21522c593315Sopenharmony_ci } 21532c593315Sopenharmony_ci break; 21542c593315Sopenharmony_ci case 17: 21552c593315Sopenharmony_ci switch (name[16]) { 21562c593315Sopenharmony_ci case 'e': 21572c593315Sopenharmony_ci if (util::strieq_l("no-server-rewrit", name, 16)) { 21582c593315Sopenharmony_ci return SHRPX_OPTID_NO_SERVER_REWRITE; 21592c593315Sopenharmony_ci } 21602c593315Sopenharmony_ci if (util::strieq_l("worker-write-rat", name, 16)) { 21612c593315Sopenharmony_ci return SHRPX_OPTID_WORKER_WRITE_RATE; 21622c593315Sopenharmony_ci } 21632c593315Sopenharmony_ci break; 21642c593315Sopenharmony_ci case 's': 21652c593315Sopenharmony_ci if (util::strieq_l("backend-http1-tl", name, 16)) { 21662c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_HTTP1_TLS; 21672c593315Sopenharmony_ci } 21682c593315Sopenharmony_ci if (util::strieq_l("max-header-field", name, 16)) { 21692c593315Sopenharmony_ci return SHRPX_OPTID_MAX_HEADER_FIELDS; 21702c593315Sopenharmony_ci } 21712c593315Sopenharmony_ci break; 21722c593315Sopenharmony_ci case 't': 21732c593315Sopenharmony_ci if (util::strieq_l("dns-cache-timeou", name, 16)) { 21742c593315Sopenharmony_ci return SHRPX_OPTID_DNS_CACHE_TIMEOUT; 21752c593315Sopenharmony_ci } 21762c593315Sopenharmony_ci if (util::strieq_l("worker-read-burs", name, 16)) { 21772c593315Sopenharmony_ci return SHRPX_OPTID_WORKER_READ_BURST; 21782c593315Sopenharmony_ci } 21792c593315Sopenharmony_ci break; 21802c593315Sopenharmony_ci } 21812c593315Sopenharmony_ci break; 21822c593315Sopenharmony_ci case 18: 21832c593315Sopenharmony_ci switch (name[17]) { 21842c593315Sopenharmony_ci case 'a': 21852c593315Sopenharmony_ci if (util::strieq_l("tls-max-early-dat", name, 17)) { 21862c593315Sopenharmony_ci return SHRPX_OPTID_TLS_MAX_EARLY_DATA; 21872c593315Sopenharmony_ci } 21882c593315Sopenharmony_ci break; 21892c593315Sopenharmony_ci case 'r': 21902c593315Sopenharmony_ci if (util::strieq_l("add-request-heade", name, 17)) { 21912c593315Sopenharmony_ci return SHRPX_OPTID_ADD_REQUEST_HEADER; 21922c593315Sopenharmony_ci } 21932c593315Sopenharmony_ci break; 21942c593315Sopenharmony_ci case 's': 21952c593315Sopenharmony_ci if (util::strieq_l("client-psk-secret", name, 17)) { 21962c593315Sopenharmony_ci return SHRPX_OPTID_CLIENT_PSK_SECRETS; 21972c593315Sopenharmony_ci } 21982c593315Sopenharmony_ci break; 21992c593315Sopenharmony_ci case 't': 22002c593315Sopenharmony_ci if (util::strieq_l("dns-lookup-timeou", name, 17)) { 22012c593315Sopenharmony_ci return SHRPX_OPTID_DNS_LOOKUP_TIMEOUT; 22022c593315Sopenharmony_ci } 22032c593315Sopenharmony_ci if (util::strieq_l("worker-write-burs", name, 17)) { 22042c593315Sopenharmony_ci return SHRPX_OPTID_WORKER_WRITE_BURST; 22052c593315Sopenharmony_ci } 22062c593315Sopenharmony_ci break; 22072c593315Sopenharmony_ci } 22082c593315Sopenharmony_ci break; 22092c593315Sopenharmony_ci case 19: 22102c593315Sopenharmony_ci switch (name[18]) { 22112c593315Sopenharmony_ci case 'e': 22122c593315Sopenharmony_ci if (util::strieq_l("no-location-rewrit", name, 18)) { 22132c593315Sopenharmony_ci return SHRPX_OPTID_NO_LOCATION_REWRITE; 22142c593315Sopenharmony_ci } 22152c593315Sopenharmony_ci if (util::strieq_l("require-http-schem", name, 18)) { 22162c593315Sopenharmony_ci return SHRPX_OPTID_REQUIRE_HTTP_SCHEME; 22172c593315Sopenharmony_ci } 22182c593315Sopenharmony_ci if (util::strieq_l("tls-ticket-key-fil", name, 18)) { 22192c593315Sopenharmony_ci return SHRPX_OPTID_TLS_TICKET_KEY_FILE; 22202c593315Sopenharmony_ci } 22212c593315Sopenharmony_ci break; 22222c593315Sopenharmony_ci case 'f': 22232c593315Sopenharmony_ci if (util::strieq_l("backend-max-backof", name, 18)) { 22242c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_MAX_BACKOFF; 22252c593315Sopenharmony_ci } 22262c593315Sopenharmony_ci break; 22272c593315Sopenharmony_ci case 'r': 22282c593315Sopenharmony_ci if (util::strieq_l("add-response-heade", name, 18)) { 22292c593315Sopenharmony_ci return SHRPX_OPTID_ADD_RESPONSE_HEADER; 22302c593315Sopenharmony_ci } 22312c593315Sopenharmony_ci if (util::strieq_l("add-x-forwarded-fo", name, 18)) { 22322c593315Sopenharmony_ci return SHRPX_OPTID_ADD_X_FORWARDED_FOR; 22332c593315Sopenharmony_ci } 22342c593315Sopenharmony_ci if (util::strieq_l("header-field-buffe", name, 18)) { 22352c593315Sopenharmony_ci return SHRPX_OPTID_HEADER_FIELD_BUFFER; 22362c593315Sopenharmony_ci } 22372c593315Sopenharmony_ci break; 22382c593315Sopenharmony_ci case 't': 22392c593315Sopenharmony_ci if (util::strieq_l("redirect-https-por", name, 18)) { 22402c593315Sopenharmony_ci return SHRPX_OPTID_REDIRECT_HTTPS_PORT; 22412c593315Sopenharmony_ci } 22422c593315Sopenharmony_ci if (util::strieq_l("stream-read-timeou", name, 18)) { 22432c593315Sopenharmony_ci return SHRPX_OPTID_STREAM_READ_TIMEOUT; 22442c593315Sopenharmony_ci } 22452c593315Sopenharmony_ci break; 22462c593315Sopenharmony_ci } 22472c593315Sopenharmony_ci break; 22482c593315Sopenharmony_ci case 20: 22492c593315Sopenharmony_ci switch (name[19]) { 22502c593315Sopenharmony_ci case 'g': 22512c593315Sopenharmony_ci if (util::strieq_l("frontend-frame-debu", name, 19)) { 22522c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_FRAME_DEBUG; 22532c593315Sopenharmony_ci } 22542c593315Sopenharmony_ci break; 22552c593315Sopenharmony_ci case 'l': 22562c593315Sopenharmony_ci if (util::strieq_l("ocsp-update-interva", name, 19)) { 22572c593315Sopenharmony_ci return SHRPX_OPTID_OCSP_UPDATE_INTERVAL; 22582c593315Sopenharmony_ci } 22592c593315Sopenharmony_ci break; 22602c593315Sopenharmony_ci case 's': 22612c593315Sopenharmony_ci if (util::strieq_l("max-worker-processe", name, 19)) { 22622c593315Sopenharmony_ci return SHRPX_OPTID_MAX_WORKER_PROCESSES; 22632c593315Sopenharmony_ci } 22642c593315Sopenharmony_ci if (util::strieq_l("tls13-client-cipher", name, 19)) { 22652c593315Sopenharmony_ci return SHRPX_OPTID_TLS13_CLIENT_CIPHERS; 22662c593315Sopenharmony_ci } 22672c593315Sopenharmony_ci break; 22682c593315Sopenharmony_ci case 't': 22692c593315Sopenharmony_ci if (util::strieq_l("backend-read-timeou", name, 19)) { 22702c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_READ_TIMEOUT; 22712c593315Sopenharmony_ci } 22722c593315Sopenharmony_ci if (util::strieq_l("stream-write-timeou", name, 19)) { 22732c593315Sopenharmony_ci return SHRPX_OPTID_STREAM_WRITE_TIMEOUT; 22742c593315Sopenharmony_ci } 22752c593315Sopenharmony_ci if (util::strieq_l("verify-client-cacer", name, 19)) { 22762c593315Sopenharmony_ci return SHRPX_OPTID_VERIFY_CLIENT_CACERT; 22772c593315Sopenharmony_ci } 22782c593315Sopenharmony_ci break; 22792c593315Sopenharmony_ci case 'y': 22802c593315Sopenharmony_ci if (util::strieq_l("api-max-request-bod", name, 19)) { 22812c593315Sopenharmony_ci return SHRPX_OPTID_API_MAX_REQUEST_BODY; 22822c593315Sopenharmony_ci } 22832c593315Sopenharmony_ci break; 22842c593315Sopenharmony_ci } 22852c593315Sopenharmony_ci break; 22862c593315Sopenharmony_ci case 21: 22872c593315Sopenharmony_ci switch (name[20]) { 22882c593315Sopenharmony_ci case 'd': 22892c593315Sopenharmony_ci if (util::strieq_l("backend-tls-sni-fiel", name, 20)) { 22902c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_TLS_SNI_FIELD; 22912c593315Sopenharmony_ci } 22922c593315Sopenharmony_ci break; 22932c593315Sopenharmony_ci case 'e': 22942c593315Sopenharmony_ci if (util::strieq_l("quic-bpf-program-fil", name, 20)) { 22952c593315Sopenharmony_ci return SHRPX_OPTID_QUIC_BPF_PROGRAM_FILE; 22962c593315Sopenharmony_ci } 22972c593315Sopenharmony_ci break; 22982c593315Sopenharmony_ci case 'l': 22992c593315Sopenharmony_ci if (util::strieq_l("accept-proxy-protoco", name, 20)) { 23002c593315Sopenharmony_ci return SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL; 23012c593315Sopenharmony_ci } 23022c593315Sopenharmony_ci break; 23032c593315Sopenharmony_ci case 'n': 23042c593315Sopenharmony_ci if (util::strieq_l("tls-max-proto-versio", name, 20)) { 23052c593315Sopenharmony_ci return SHRPX_OPTID_TLS_MAX_PROTO_VERSION; 23062c593315Sopenharmony_ci } 23072c593315Sopenharmony_ci if (util::strieq_l("tls-min-proto-versio", name, 20)) { 23082c593315Sopenharmony_ci return SHRPX_OPTID_TLS_MIN_PROTO_VERSION; 23092c593315Sopenharmony_ci } 23102c593315Sopenharmony_ci break; 23112c593315Sopenharmony_ci case 'r': 23122c593315Sopenharmony_ci if (util::strieq_l("tls-ticket-key-ciphe", name, 20)) { 23132c593315Sopenharmony_ci return SHRPX_OPTID_TLS_TICKET_KEY_CIPHER; 23142c593315Sopenharmony_ci } 23152c593315Sopenharmony_ci break; 23162c593315Sopenharmony_ci case 's': 23172c593315Sopenharmony_ci if (util::strieq_l("frontend-max-request", name, 20)) { 23182c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_MAX_REQUESTS; 23192c593315Sopenharmony_ci } 23202c593315Sopenharmony_ci break; 23212c593315Sopenharmony_ci case 't': 23222c593315Sopenharmony_ci if (util::strieq_l("backend-write-timeou", name, 20)) { 23232c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_WRITE_TIMEOUT; 23242c593315Sopenharmony_ci } 23252c593315Sopenharmony_ci if (util::strieq_l("frontend-read-timeou", name, 20)) { 23262c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_READ_TIMEOUT; 23272c593315Sopenharmony_ci } 23282c593315Sopenharmony_ci break; 23292c593315Sopenharmony_ci case 'y': 23302c593315Sopenharmony_ci if (util::strieq_l("accesslog-write-earl", name, 20)) { 23312c593315Sopenharmony_ci return SHRPX_OPTID_ACCESSLOG_WRITE_EARLY; 23322c593315Sopenharmony_ci } 23332c593315Sopenharmony_ci break; 23342c593315Sopenharmony_ci } 23352c593315Sopenharmony_ci break; 23362c593315Sopenharmony_ci case 22: 23372c593315Sopenharmony_ci switch (name[21]) { 23382c593315Sopenharmony_ci case 'i': 23392c593315Sopenharmony_ci if (util::strieq_l("backend-http-proxy-ur", name, 21)) { 23402c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_HTTP_PROXY_URI; 23412c593315Sopenharmony_ci } 23422c593315Sopenharmony_ci break; 23432c593315Sopenharmony_ci case 'r': 23442c593315Sopenharmony_ci if (util::strieq_l("backend-request-buffe", name, 21)) { 23452c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_REQUEST_BUFFER; 23462c593315Sopenharmony_ci } 23472c593315Sopenharmony_ci if (util::strieq_l("frontend-quic-qlog-di", name, 21)) { 23482c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_QUIC_QLOG_DIR; 23492c593315Sopenharmony_ci } 23502c593315Sopenharmony_ci break; 23512c593315Sopenharmony_ci case 't': 23522c593315Sopenharmony_ci if (util::strieq_l("frontend-write-timeou", name, 21)) { 23532c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_WRITE_TIMEOUT; 23542c593315Sopenharmony_ci } 23552c593315Sopenharmony_ci break; 23562c593315Sopenharmony_ci case 'y': 23572c593315Sopenharmony_ci if (util::strieq_l("backend-address-famil", name, 21)) { 23582c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_ADDRESS_FAMILY; 23592c593315Sopenharmony_ci } 23602c593315Sopenharmony_ci break; 23612c593315Sopenharmony_ci } 23622c593315Sopenharmony_ci break; 23632c593315Sopenharmony_ci case 23: 23642c593315Sopenharmony_ci switch (name[22]) { 23652c593315Sopenharmony_ci case 'e': 23662c593315Sopenharmony_ci if (util::strieq_l("client-private-key-fil", name, 22)) { 23672c593315Sopenharmony_ci return SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE; 23682c593315Sopenharmony_ci } 23692c593315Sopenharmony_ci if (util::strieq_l("private-key-passwd-fil", name, 22)) { 23702c593315Sopenharmony_ci return SHRPX_OPTID_PRIVATE_KEY_PASSWD_FILE; 23712c593315Sopenharmony_ci } 23722c593315Sopenharmony_ci break; 23732c593315Sopenharmony_ci case 'g': 23742c593315Sopenharmony_ci if (util::strieq_l("frontend-quic-debug-lo", name, 22)) { 23752c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_QUIC_DEBUG_LOG; 23762c593315Sopenharmony_ci } 23772c593315Sopenharmony_ci break; 23782c593315Sopenharmony_ci case 'r': 23792c593315Sopenharmony_ci if (util::strieq_l("backend-response-buffe", name, 22)) { 23802c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_RESPONSE_BUFFER; 23812c593315Sopenharmony_ci } 23822c593315Sopenharmony_ci break; 23832c593315Sopenharmony_ci case 't': 23842c593315Sopenharmony_ci if (util::strieq_l("backend-connect-timeou", name, 22)) { 23852c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_CONNECT_TIMEOUT; 23862c593315Sopenharmony_ci } 23872c593315Sopenharmony_ci break; 23882c593315Sopenharmony_ci } 23892c593315Sopenharmony_ci break; 23902c593315Sopenharmony_ci case 24: 23912c593315Sopenharmony_ci switch (name[23]) { 23922c593315Sopenharmony_ci case 'a': 23932c593315Sopenharmony_ci if (util::strieq_l("frontend-quic-early-dat", name, 23)) { 23942c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_QUIC_EARLY_DATA; 23952c593315Sopenharmony_ci } 23962c593315Sopenharmony_ci break; 23972c593315Sopenharmony_ci case 'd': 23982c593315Sopenharmony_ci if (util::strieq_l("strip-incoming-forwarde", name, 23)) { 23992c593315Sopenharmony_ci return SHRPX_OPTID_STRIP_INCOMING_FORWARDED; 24002c593315Sopenharmony_ci } 24012c593315Sopenharmony_ci if (util::strieq_l("tls-ticket-key-memcache", name, 23)) { 24022c593315Sopenharmony_ci return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED; 24032c593315Sopenharmony_ci } 24042c593315Sopenharmony_ci break; 24052c593315Sopenharmony_ci case 'e': 24062c593315Sopenharmony_ci if (util::strieq_l("fetch-ocsp-response-fil", name, 23)) { 24072c593315Sopenharmony_ci return SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE; 24082c593315Sopenharmony_ci } 24092c593315Sopenharmony_ci break; 24102c593315Sopenharmony_ci case 'o': 24112c593315Sopenharmony_ci if (util::strieq_l("no-add-x-forwarded-prot", name, 23)) { 24122c593315Sopenharmony_ci return SHRPX_OPTID_NO_ADD_X_FORWARDED_PROTO; 24132c593315Sopenharmony_ci } 24142c593315Sopenharmony_ci break; 24152c593315Sopenharmony_ci case 't': 24162c593315Sopenharmony_ci if (util::strieq_l("listener-disable-timeou", name, 23)) { 24172c593315Sopenharmony_ci return SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT; 24182c593315Sopenharmony_ci } 24192c593315Sopenharmony_ci if (util::strieq_l("tls-dyn-rec-idle-timeou", name, 23)) { 24202c593315Sopenharmony_ci return SHRPX_OPTID_TLS_DYN_REC_IDLE_TIMEOUT; 24212c593315Sopenharmony_ci } 24222c593315Sopenharmony_ci break; 24232c593315Sopenharmony_ci } 24242c593315Sopenharmony_ci break; 24252c593315Sopenharmony_ci case 25: 24262c593315Sopenharmony_ci switch (name[24]) { 24272c593315Sopenharmony_ci case 'e': 24282c593315Sopenharmony_ci if (util::strieq_l("backend-http2-window-siz", name, 24)) { 24292c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_HTTP2_WINDOW_SIZE; 24302c593315Sopenharmony_ci } 24312c593315Sopenharmony_ci if (util::strieq_l("frontend-quic-secret-fil", name, 24)) { 24322c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_QUIC_SECRET_FILE; 24332c593315Sopenharmony_ci } 24342c593315Sopenharmony_ci break; 24352c593315Sopenharmony_ci case 'g': 24362c593315Sopenharmony_ci if (util::strieq_l("http2-no-cookie-crumblin", name, 24)) { 24372c593315Sopenharmony_ci return SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING; 24382c593315Sopenharmony_ci } 24392c593315Sopenharmony_ci break; 24402c593315Sopenharmony_ci case 's': 24412c593315Sopenharmony_ci if (util::strieq_l("backend-http2-window-bit", name, 24)) { 24422c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_HTTP2_WINDOW_BITS; 24432c593315Sopenharmony_ci } 24442c593315Sopenharmony_ci if (util::strieq_l("max-request-header-field", name, 24)) { 24452c593315Sopenharmony_ci return SHRPX_OPTID_MAX_REQUEST_HEADER_FIELDS; 24462c593315Sopenharmony_ci } 24472c593315Sopenharmony_ci break; 24482c593315Sopenharmony_ci case 't': 24492c593315Sopenharmony_ci if (util::strieq_l("frontend-quic-initial-rt", name, 24)) { 24502c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_QUIC_INITIAL_RTT; 24512c593315Sopenharmony_ci } 24522c593315Sopenharmony_ci break; 24532c593315Sopenharmony_ci } 24542c593315Sopenharmony_ci break; 24552c593315Sopenharmony_ci case 26: 24562c593315Sopenharmony_ci switch (name[25]) { 24572c593315Sopenharmony_ci case 'a': 24582c593315Sopenharmony_ci if (util::strieq_l("tls-no-postpone-early-dat", name, 25)) { 24592c593315Sopenharmony_ci return SHRPX_OPTID_TLS_NO_POSTPONE_EARLY_DATA; 24602c593315Sopenharmony_ci } 24612c593315Sopenharmony_ci break; 24622c593315Sopenharmony_ci case 'e': 24632c593315Sopenharmony_ci if (util::strieq_l("frontend-http2-window-siz", name, 25)) { 24642c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_SIZE; 24652c593315Sopenharmony_ci } 24662c593315Sopenharmony_ci if (util::strieq_l("frontend-http3-window-siz", name, 25)) { 24672c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP3_WINDOW_SIZE; 24682c593315Sopenharmony_ci } 24692c593315Sopenharmony_ci break; 24702c593315Sopenharmony_ci case 's': 24712c593315Sopenharmony_ci if (util::strieq_l("frontend-http2-window-bit", name, 25)) { 24722c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS; 24732c593315Sopenharmony_ci } 24742c593315Sopenharmony_ci if (util::strieq_l("max-response-header-field", name, 25)) { 24752c593315Sopenharmony_ci return SHRPX_OPTID_MAX_RESPONSE_HEADER_FIELDS; 24762c593315Sopenharmony_ci } 24772c593315Sopenharmony_ci break; 24782c593315Sopenharmony_ci case 't': 24792c593315Sopenharmony_ci if (util::strieq_l("backend-keep-alive-timeou", name, 25)) { 24802c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT; 24812c593315Sopenharmony_ci } 24822c593315Sopenharmony_ci if (util::strieq_l("frontend-quic-idle-timeou", name, 25)) { 24832c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_QUIC_IDLE_TIMEOUT; 24842c593315Sopenharmony_ci } 24852c593315Sopenharmony_ci if (util::strieq_l("no-http2-cipher-black-lis", name, 25)) { 24862c593315Sopenharmony_ci return SHRPX_OPTID_NO_HTTP2_CIPHER_BLACK_LIST; 24872c593315Sopenharmony_ci } 24882c593315Sopenharmony_ci if (util::strieq_l("no-http2-cipher-block-lis", name, 25)) { 24892c593315Sopenharmony_ci return SHRPX_OPTID_NO_HTTP2_CIPHER_BLOCK_LIST; 24902c593315Sopenharmony_ci } 24912c593315Sopenharmony_ci break; 24922c593315Sopenharmony_ci } 24932c593315Sopenharmony_ci break; 24942c593315Sopenharmony_ci case 27: 24952c593315Sopenharmony_ci switch (name[26]) { 24962c593315Sopenharmony_ci case 'd': 24972c593315Sopenharmony_ci if (util::strieq_l("tls-session-cache-memcache", name, 26)) { 24982c593315Sopenharmony_ci return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED; 24992c593315Sopenharmony_ci } 25002c593315Sopenharmony_ci break; 25012c593315Sopenharmony_ci case 'n': 25022c593315Sopenharmony_ci if (util::strieq_l("frontend-quic-require-toke", name, 26)) { 25032c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_QUIC_REQUIRE_TOKEN; 25042c593315Sopenharmony_ci } 25052c593315Sopenharmony_ci break; 25062c593315Sopenharmony_ci case 'r': 25072c593315Sopenharmony_ci if (util::strieq_l("request-header-field-buffe", name, 26)) { 25082c593315Sopenharmony_ci return SHRPX_OPTID_REQUEST_HEADER_FIELD_BUFFER; 25092c593315Sopenharmony_ci } 25102c593315Sopenharmony_ci break; 25112c593315Sopenharmony_ci case 's': 25122c593315Sopenharmony_ci if (util::strieq_l("worker-frontend-connection", name, 26)) { 25132c593315Sopenharmony_ci return SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS; 25142c593315Sopenharmony_ci } 25152c593315Sopenharmony_ci break; 25162c593315Sopenharmony_ci case 't': 25172c593315Sopenharmony_ci if (util::strieq_l("frontend-http2-read-timeou", name, 26)) { 25182c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT; 25192c593315Sopenharmony_ci } 25202c593315Sopenharmony_ci if (util::strieq_l("frontend-http3-read-timeou", name, 26)) { 25212c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP3_READ_TIMEOUT; 25222c593315Sopenharmony_ci } 25232c593315Sopenharmony_ci if (util::strieq_l("frontend-keep-alive-timeou", name, 26)) { 25242c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_KEEP_ALIVE_TIMEOUT; 25252c593315Sopenharmony_ci } 25262c593315Sopenharmony_ci break; 25272c593315Sopenharmony_ci } 25282c593315Sopenharmony_ci break; 25292c593315Sopenharmony_ci case 28: 25302c593315Sopenharmony_ci switch (name[27]) { 25312c593315Sopenharmony_ci case 'a': 25322c593315Sopenharmony_ci if (util::strieq_l("no-strip-incoming-early-dat", name, 27)) { 25332c593315Sopenharmony_ci return SHRPX_OPTID_NO_STRIP_INCOMING_EARLY_DATA; 25342c593315Sopenharmony_ci } 25352c593315Sopenharmony_ci break; 25362c593315Sopenharmony_ci case 'd': 25372c593315Sopenharmony_ci if (util::strieq_l("tls-dyn-rec-warmup-threshol", name, 27)) { 25382c593315Sopenharmony_ci return SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD; 25392c593315Sopenharmony_ci } 25402c593315Sopenharmony_ci break; 25412c593315Sopenharmony_ci case 'r': 25422c593315Sopenharmony_ci if (util::strieq_l("response-header-field-buffe", name, 27)) { 25432c593315Sopenharmony_ci return SHRPX_OPTID_RESPONSE_HEADER_FIELD_BUFFER; 25442c593315Sopenharmony_ci } 25452c593315Sopenharmony_ci break; 25462c593315Sopenharmony_ci case 's': 25472c593315Sopenharmony_ci if (util::strieq_l("http2-max-concurrent-stream", name, 27)) { 25482c593315Sopenharmony_ci return SHRPX_OPTID_HTTP2_MAX_CONCURRENT_STREAMS; 25492c593315Sopenharmony_ci } 25502c593315Sopenharmony_ci if (util::strieq_l("tls-ticket-key-memcached-tl", name, 27)) { 25512c593315Sopenharmony_ci return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_TLS; 25522c593315Sopenharmony_ci } 25532c593315Sopenharmony_ci break; 25542c593315Sopenharmony_ci case 't': 25552c593315Sopenharmony_ci if (util::strieq_l("backend-connections-per-hos", name, 27)) { 25562c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_CONNECTIONS_PER_HOST; 25572c593315Sopenharmony_ci } 25582c593315Sopenharmony_ci break; 25592c593315Sopenharmony_ci } 25602c593315Sopenharmony_ci break; 25612c593315Sopenharmony_ci case 30: 25622c593315Sopenharmony_ci switch (name[29]) { 25632c593315Sopenharmony_ci case 'd': 25642c593315Sopenharmony_ci if (util::strieq_l("verify-client-tolerate-expire", name, 29)) { 25652c593315Sopenharmony_ci return SHRPX_OPTID_VERIFY_CLIENT_TOLERATE_EXPIRED; 25662c593315Sopenharmony_ci } 25672c593315Sopenharmony_ci break; 25682c593315Sopenharmony_ci case 'e': 25692c593315Sopenharmony_ci if (util::strieq_l("frontend-http3-max-window-siz", name, 29)) { 25702c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP3_MAX_WINDOW_SIZE; 25712c593315Sopenharmony_ci } 25722c593315Sopenharmony_ci break; 25732c593315Sopenharmony_ci case 'r': 25742c593315Sopenharmony_ci if (util::strieq_l("ignore-per-pattern-mruby-erro", name, 29)) { 25752c593315Sopenharmony_ci return SHRPX_OPTID_IGNORE_PER_PATTERN_MRUBY_ERROR; 25762c593315Sopenharmony_ci } 25772c593315Sopenharmony_ci if (util::strieq_l("strip-incoming-x-forwarded-fo", name, 29)) { 25782c593315Sopenharmony_ci return SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR; 25792c593315Sopenharmony_ci } 25802c593315Sopenharmony_ci break; 25812c593315Sopenharmony_ci case 't': 25822c593315Sopenharmony_ci if (util::strieq_l("backend-http2-settings-timeou", name, 29)) { 25832c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_HTTP2_SETTINGS_TIMEOUT; 25842c593315Sopenharmony_ci } 25852c593315Sopenharmony_ci break; 25862c593315Sopenharmony_ci } 25872c593315Sopenharmony_ci break; 25882c593315Sopenharmony_ci case 31: 25892c593315Sopenharmony_ci switch (name[30]) { 25902c593315Sopenharmony_ci case 's': 25912c593315Sopenharmony_ci if (util::strieq_l("tls-session-cache-memcached-tl", name, 30)) { 25922c593315Sopenharmony_ci return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_TLS; 25932c593315Sopenharmony_ci } 25942c593315Sopenharmony_ci break; 25952c593315Sopenharmony_ci case 't': 25962c593315Sopenharmony_ci if (util::strieq_l("frontend-http2-settings-timeou", name, 30)) { 25972c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP2_SETTINGS_TIMEOUT; 25982c593315Sopenharmony_ci } 25992c593315Sopenharmony_ci break; 26002c593315Sopenharmony_ci } 26012c593315Sopenharmony_ci break; 26022c593315Sopenharmony_ci case 32: 26032c593315Sopenharmony_ci switch (name[31]) { 26042c593315Sopenharmony_ci case 'd': 26052c593315Sopenharmony_ci if (util::strieq_l("backend-connections-per-fronten", name, 31)) { 26062c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_CONNECTIONS_PER_FRONTEND; 26072c593315Sopenharmony_ci } 26082c593315Sopenharmony_ci break; 26092c593315Sopenharmony_ci } 26102c593315Sopenharmony_ci break; 26112c593315Sopenharmony_ci case 33: 26122c593315Sopenharmony_ci switch (name[32]) { 26132c593315Sopenharmony_ci case 'l': 26142c593315Sopenharmony_ci if (util::strieq_l("tls-ticket-key-memcached-interva", name, 32)) { 26152c593315Sopenharmony_ci return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_INTERVAL; 26162c593315Sopenharmony_ci } 26172c593315Sopenharmony_ci if (util::strieq_l("tls-ticket-key-memcached-max-fai", name, 32)) { 26182c593315Sopenharmony_ci return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL; 26192c593315Sopenharmony_ci } 26202c593315Sopenharmony_ci break; 26212c593315Sopenharmony_ci case 't': 26222c593315Sopenharmony_ci if (util::strieq_l("client-no-http2-cipher-black-lis", name, 32)) { 26232c593315Sopenharmony_ci return SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST; 26242c593315Sopenharmony_ci } 26252c593315Sopenharmony_ci if (util::strieq_l("client-no-http2-cipher-block-lis", name, 32)) { 26262c593315Sopenharmony_ci return SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLOCK_LIST; 26272c593315Sopenharmony_ci } 26282c593315Sopenharmony_ci break; 26292c593315Sopenharmony_ci } 26302c593315Sopenharmony_ci break; 26312c593315Sopenharmony_ci case 34: 26322c593315Sopenharmony_ci switch (name[33]) { 26332c593315Sopenharmony_ci case 'e': 26342c593315Sopenharmony_ci if (util::strieq_l("tls-ticket-key-memcached-cert-fil", name, 33)) { 26352c593315Sopenharmony_ci return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_CERT_FILE; 26362c593315Sopenharmony_ci } 26372c593315Sopenharmony_ci break; 26382c593315Sopenharmony_ci case 'r': 26392c593315Sopenharmony_ci if (util::strieq_l("frontend-http2-dump-request-heade", name, 33)) { 26402c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER; 26412c593315Sopenharmony_ci } 26422c593315Sopenharmony_ci break; 26432c593315Sopenharmony_ci case 't': 26442c593315Sopenharmony_ci if (util::strieq_l("backend-http1-connections-per-hos", name, 33)) { 26452c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_HOST; 26462c593315Sopenharmony_ci } 26472c593315Sopenharmony_ci break; 26482c593315Sopenharmony_ci case 'y': 26492c593315Sopenharmony_ci if (util::strieq_l("tls-ticket-key-memcached-max-retr", name, 33)) { 26502c593315Sopenharmony_ci return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY; 26512c593315Sopenharmony_ci } 26522c593315Sopenharmony_ci break; 26532c593315Sopenharmony_ci } 26542c593315Sopenharmony_ci break; 26552c593315Sopenharmony_ci case 35: 26562c593315Sopenharmony_ci switch (name[34]) { 26572c593315Sopenharmony_ci case 'e': 26582c593315Sopenharmony_ci if (util::strieq_l("frontend-http2-optimize-window-siz", name, 34)) { 26592c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE; 26602c593315Sopenharmony_ci } 26612c593315Sopenharmony_ci break; 26622c593315Sopenharmony_ci case 'o': 26632c593315Sopenharmony_ci if (util::strieq_l("no-strip-incoming-x-forwarded-prot", name, 34)) { 26642c593315Sopenharmony_ci return SHRPX_OPTID_NO_STRIP_INCOMING_X_FORWARDED_PROTO; 26652c593315Sopenharmony_ci } 26662c593315Sopenharmony_ci break; 26672c593315Sopenharmony_ci case 'r': 26682c593315Sopenharmony_ci if (util::strieq_l("frontend-http2-dump-response-heade", name, 34)) { 26692c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER; 26702c593315Sopenharmony_ci } 26712c593315Sopenharmony_ci if (util::strieq_l("frontend-quic-congestion-controlle", name, 34)) { 26722c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_QUIC_CONGESTION_CONTROLLER; 26732c593315Sopenharmony_ci } 26742c593315Sopenharmony_ci break; 26752c593315Sopenharmony_ci } 26762c593315Sopenharmony_ci break; 26772c593315Sopenharmony_ci case 36: 26782c593315Sopenharmony_ci switch (name[35]) { 26792c593315Sopenharmony_ci case 'd': 26802c593315Sopenharmony_ci if (util::strieq_l("worker-process-grace-shutdown-perio", name, 35)) { 26812c593315Sopenharmony_ci return SHRPX_OPTID_WORKER_PROCESS_GRACE_SHUTDOWN_PERIOD; 26822c593315Sopenharmony_ci } 26832c593315Sopenharmony_ci break; 26842c593315Sopenharmony_ci case 'e': 26852c593315Sopenharmony_ci if (util::strieq_l("backend-http2-connection-window-siz", name, 35)) { 26862c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE; 26872c593315Sopenharmony_ci } 26882c593315Sopenharmony_ci break; 26892c593315Sopenharmony_ci case 'r': 26902c593315Sopenharmony_ci if (util::strieq_l("backend-http2-connections-per-worke", name, 35)) { 26912c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER; 26922c593315Sopenharmony_ci } 26932c593315Sopenharmony_ci break; 26942c593315Sopenharmony_ci case 's': 26952c593315Sopenharmony_ci if (util::strieq_l("backend-http2-connection-window-bit", name, 35)) { 26962c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_BITS; 26972c593315Sopenharmony_ci } 26982c593315Sopenharmony_ci if (util::strieq_l("backend-http2-max-concurrent-stream", name, 35)) { 26992c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS; 27002c593315Sopenharmony_ci } 27012c593315Sopenharmony_ci break; 27022c593315Sopenharmony_ci } 27032c593315Sopenharmony_ci break; 27042c593315Sopenharmony_ci case 37: 27052c593315Sopenharmony_ci switch (name[36]) { 27062c593315Sopenharmony_ci case 'e': 27072c593315Sopenharmony_ci if (util::strieq_l("frontend-http2-connection-window-siz", name, 36)) { 27082c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE; 27092c593315Sopenharmony_ci } 27102c593315Sopenharmony_ci if (util::strieq_l("frontend-http3-connection-window-siz", name, 36)) { 27112c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP3_CONNECTION_WINDOW_SIZE; 27122c593315Sopenharmony_ci } 27132c593315Sopenharmony_ci if (util::strieq_l("tls-session-cache-memcached-cert-fil", name, 36)) { 27142c593315Sopenharmony_ci return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE; 27152c593315Sopenharmony_ci } 27162c593315Sopenharmony_ci break; 27172c593315Sopenharmony_ci case 's': 27182c593315Sopenharmony_ci if (util::strieq_l("frontend-http2-connection-window-bit", name, 36)) { 27192c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS; 27202c593315Sopenharmony_ci } 27212c593315Sopenharmony_ci if (util::strieq_l("frontend-http2-max-concurrent-stream", name, 36)) { 27222c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS; 27232c593315Sopenharmony_ci } 27242c593315Sopenharmony_ci if (util::strieq_l("frontend-http3-max-concurrent-stream", name, 36)) { 27252c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP3_MAX_CONCURRENT_STREAMS; 27262c593315Sopenharmony_ci } 27272c593315Sopenharmony_ci break; 27282c593315Sopenharmony_ci } 27292c593315Sopenharmony_ci break; 27302c593315Sopenharmony_ci case 38: 27312c593315Sopenharmony_ci switch (name[37]) { 27322c593315Sopenharmony_ci case 'd': 27332c593315Sopenharmony_ci if (util::strieq_l("backend-http1-connections-per-fronten", name, 37)) { 27342c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND; 27352c593315Sopenharmony_ci } 27362c593315Sopenharmony_ci break; 27372c593315Sopenharmony_ci } 27382c593315Sopenharmony_ci break; 27392c593315Sopenharmony_ci case 39: 27402c593315Sopenharmony_ci switch (name[38]) { 27412c593315Sopenharmony_ci case 'y': 27422c593315Sopenharmony_ci if (util::strieq_l("tls-ticket-key-memcached-address-famil", name, 38)) { 27432c593315Sopenharmony_ci return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY; 27442c593315Sopenharmony_ci } 27452c593315Sopenharmony_ci break; 27462c593315Sopenharmony_ci } 27472c593315Sopenharmony_ci break; 27482c593315Sopenharmony_ci case 40: 27492c593315Sopenharmony_ci switch (name[39]) { 27502c593315Sopenharmony_ci case 'e': 27512c593315Sopenharmony_ci if (util::strieq_l("backend-http2-decoder-dynamic-table-siz", name, 39)) { 27522c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE; 27532c593315Sopenharmony_ci } 27542c593315Sopenharmony_ci if (util::strieq_l("backend-http2-encoder-dynamic-table-siz", name, 39)) { 27552c593315Sopenharmony_ci return SHRPX_OPTID_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE; 27562c593315Sopenharmony_ci } 27572c593315Sopenharmony_ci break; 27582c593315Sopenharmony_ci } 27592c593315Sopenharmony_ci break; 27602c593315Sopenharmony_ci case 41: 27612c593315Sopenharmony_ci switch (name[40]) { 27622c593315Sopenharmony_ci case 'e': 27632c593315Sopenharmony_ci if (util::strieq_l("frontend-http2-decoder-dynamic-table-siz", name, 27642c593315Sopenharmony_ci 40)) { 27652c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE; 27662c593315Sopenharmony_ci } 27672c593315Sopenharmony_ci if (util::strieq_l("frontend-http2-encoder-dynamic-table-siz", name, 27682c593315Sopenharmony_ci 40)) { 27692c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE; 27702c593315Sopenharmony_ci } 27712c593315Sopenharmony_ci if (util::strieq_l("frontend-http2-optimize-write-buffer-siz", name, 27722c593315Sopenharmony_ci 40)) { 27732c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE; 27742c593315Sopenharmony_ci } 27752c593315Sopenharmony_ci if (util::strieq_l("frontend-http3-max-connection-window-siz", name, 27762c593315Sopenharmony_ci 40)) { 27772c593315Sopenharmony_ci return SHRPX_OPTID_FRONTEND_HTTP3_MAX_CONNECTION_WINDOW_SIZE; 27782c593315Sopenharmony_ci } 27792c593315Sopenharmony_ci if (util::strieq_l("tls-ticket-key-memcached-private-key-fil", name, 27802c593315Sopenharmony_ci 40)) { 27812c593315Sopenharmony_ci return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE; 27822c593315Sopenharmony_ci } 27832c593315Sopenharmony_ci break; 27842c593315Sopenharmony_ci } 27852c593315Sopenharmony_ci break; 27862c593315Sopenharmony_ci case 42: 27872c593315Sopenharmony_ci switch (name[41]) { 27882c593315Sopenharmony_ci case 'y': 27892c593315Sopenharmony_ci if (util::strieq_l("tls-session-cache-memcached-address-famil", name, 27902c593315Sopenharmony_ci 41)) { 27912c593315Sopenharmony_ci return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY; 27922c593315Sopenharmony_ci } 27932c593315Sopenharmony_ci break; 27942c593315Sopenharmony_ci } 27952c593315Sopenharmony_ci break; 27962c593315Sopenharmony_ci case 44: 27972c593315Sopenharmony_ci switch (name[43]) { 27982c593315Sopenharmony_ci case 'e': 27992c593315Sopenharmony_ci if (util::strieq_l("tls-session-cache-memcached-private-key-fil", name, 28002c593315Sopenharmony_ci 43)) { 28012c593315Sopenharmony_ci return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE; 28022c593315Sopenharmony_ci } 28032c593315Sopenharmony_ci break; 28042c593315Sopenharmony_ci } 28052c593315Sopenharmony_ci break; 28062c593315Sopenharmony_ci } 28072c593315Sopenharmony_ci return -1; 28082c593315Sopenharmony_ci} 28092c593315Sopenharmony_ci 28102c593315Sopenharmony_ciint parse_config(Config *config, const StringRef &opt, const StringRef &optarg, 28112c593315Sopenharmony_ci std::set<StringRef> &included_set, 28122c593315Sopenharmony_ci std::map<StringRef, size_t> &pattern_addr_indexer) { 28132c593315Sopenharmony_ci auto optid = option_lookup_token(opt.c_str(), opt.size()); 28142c593315Sopenharmony_ci return parse_config(config, optid, opt, optarg, included_set, 28152c593315Sopenharmony_ci pattern_addr_indexer); 28162c593315Sopenharmony_ci} 28172c593315Sopenharmony_ci 28182c593315Sopenharmony_ciint parse_config(Config *config, int optid, const StringRef &opt, 28192c593315Sopenharmony_ci const StringRef &optarg, std::set<StringRef> &included_set, 28202c593315Sopenharmony_ci std::map<StringRef, size_t> &pattern_addr_indexer) { 28212c593315Sopenharmony_ci std::array<char, STRERROR_BUFSIZE> errbuf; 28222c593315Sopenharmony_ci char host[NI_MAXHOST]; 28232c593315Sopenharmony_ci uint16_t port; 28242c593315Sopenharmony_ci 28252c593315Sopenharmony_ci switch (optid) { 28262c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND: { 28272c593315Sopenharmony_ci auto &downstreamconf = *config->conn.downstream; 28282c593315Sopenharmony_ci auto addr_end = std::find(std::begin(optarg), std::end(optarg), ';'); 28292c593315Sopenharmony_ci 28302c593315Sopenharmony_ci DownstreamAddrConfig addr{}; 28312c593315Sopenharmony_ci if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) { 28322c593315Sopenharmony_ci auto path = std::begin(optarg) + SHRPX_UNIX_PATH_PREFIX.size(); 28332c593315Sopenharmony_ci addr.host = 28342c593315Sopenharmony_ci make_string_ref(downstreamconf.balloc, StringRef{path, addr_end}); 28352c593315Sopenharmony_ci addr.host_unix = true; 28362c593315Sopenharmony_ci } else { 28372c593315Sopenharmony_ci if (split_host_port(host, sizeof(host), &port, 28382c593315Sopenharmony_ci StringRef{std::begin(optarg), addr_end}, opt) == -1) { 28392c593315Sopenharmony_ci return -1; 28402c593315Sopenharmony_ci } 28412c593315Sopenharmony_ci 28422c593315Sopenharmony_ci addr.host = make_string_ref(downstreamconf.balloc, StringRef{host}); 28432c593315Sopenharmony_ci addr.port = port; 28442c593315Sopenharmony_ci } 28452c593315Sopenharmony_ci 28462c593315Sopenharmony_ci auto mapping = addr_end == std::end(optarg) ? addr_end : addr_end + 1; 28472c593315Sopenharmony_ci auto mapping_end = std::find(mapping, std::end(optarg), ';'); 28482c593315Sopenharmony_ci 28492c593315Sopenharmony_ci auto params = 28502c593315Sopenharmony_ci mapping_end == std::end(optarg) ? mapping_end : mapping_end + 1; 28512c593315Sopenharmony_ci 28522c593315Sopenharmony_ci if (parse_mapping(config, addr, pattern_addr_indexer, 28532c593315Sopenharmony_ci StringRef{mapping, mapping_end}, 28542c593315Sopenharmony_ci StringRef{params, std::end(optarg)}) != 0) { 28552c593315Sopenharmony_ci return -1; 28562c593315Sopenharmony_ci } 28572c593315Sopenharmony_ci 28582c593315Sopenharmony_ci return 0; 28592c593315Sopenharmony_ci } 28602c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND: { 28612c593315Sopenharmony_ci auto &apiconf = config->api; 28622c593315Sopenharmony_ci 28632c593315Sopenharmony_ci auto addr_end = std::find(std::begin(optarg), std::end(optarg), ';'); 28642c593315Sopenharmony_ci auto src_params = StringRef{addr_end, std::end(optarg)}; 28652c593315Sopenharmony_ci 28662c593315Sopenharmony_ci UpstreamParams params{}; 28672c593315Sopenharmony_ci params.tls = true; 28682c593315Sopenharmony_ci 28692c593315Sopenharmony_ci if (parse_upstream_params(params, src_params) != 0) { 28702c593315Sopenharmony_ci return -1; 28712c593315Sopenharmony_ci } 28722c593315Sopenharmony_ci 28732c593315Sopenharmony_ci if (params.sni_fwd && !params.tls) { 28742c593315Sopenharmony_ci LOG(ERROR) << "frontend: sni_fwd requires tls"; 28752c593315Sopenharmony_ci return -1; 28762c593315Sopenharmony_ci } 28772c593315Sopenharmony_ci 28782c593315Sopenharmony_ci if (params.quic) { 28792c593315Sopenharmony_ci if (params.alt_mode != UpstreamAltMode::NONE) { 28802c593315Sopenharmony_ci LOG(ERROR) << "frontend: api or healthmon cannot be used with quic"; 28812c593315Sopenharmony_ci return -1; 28822c593315Sopenharmony_ci } 28832c593315Sopenharmony_ci 28842c593315Sopenharmony_ci if (!params.tls) { 28852c593315Sopenharmony_ci LOG(ERROR) << "frontend: quic requires TLS"; 28862c593315Sopenharmony_ci return -1; 28872c593315Sopenharmony_ci } 28882c593315Sopenharmony_ci } 28892c593315Sopenharmony_ci 28902c593315Sopenharmony_ci UpstreamAddr addr{}; 28912c593315Sopenharmony_ci addr.fd = -1; 28922c593315Sopenharmony_ci addr.tls = params.tls; 28932c593315Sopenharmony_ci addr.sni_fwd = params.sni_fwd; 28942c593315Sopenharmony_ci addr.alt_mode = params.alt_mode; 28952c593315Sopenharmony_ci addr.accept_proxy_protocol = params.proxyproto; 28962c593315Sopenharmony_ci addr.quic = params.quic; 28972c593315Sopenharmony_ci 28982c593315Sopenharmony_ci if (addr.alt_mode == UpstreamAltMode::API) { 28992c593315Sopenharmony_ci apiconf.enabled = true; 29002c593315Sopenharmony_ci } 29012c593315Sopenharmony_ci 29022c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 29032c593315Sopenharmony_ci auto &addrs = params.quic ? config->conn.quic_listener.addrs 29042c593315Sopenharmony_ci : config->conn.listener.addrs; 29052c593315Sopenharmony_ci#else // !ENABLE_HTTP3 29062c593315Sopenharmony_ci auto &addrs = config->conn.listener.addrs; 29072c593315Sopenharmony_ci#endif // !ENABLE_HTTP3 29082c593315Sopenharmony_ci 29092c593315Sopenharmony_ci if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) { 29102c593315Sopenharmony_ci if (addr.quic) { 29112c593315Sopenharmony_ci LOG(ERROR) << "frontend: quic cannot be used on UNIX domain socket"; 29122c593315Sopenharmony_ci return -1; 29132c593315Sopenharmony_ci } 29142c593315Sopenharmony_ci 29152c593315Sopenharmony_ci auto path = std::begin(optarg) + SHRPX_UNIX_PATH_PREFIX.size(); 29162c593315Sopenharmony_ci addr.host = make_string_ref(config->balloc, StringRef{path, addr_end}); 29172c593315Sopenharmony_ci addr.host_unix = true; 29182c593315Sopenharmony_ci addr.index = addrs.size(); 29192c593315Sopenharmony_ci 29202c593315Sopenharmony_ci addrs.push_back(std::move(addr)); 29212c593315Sopenharmony_ci 29222c593315Sopenharmony_ci return 0; 29232c593315Sopenharmony_ci } 29242c593315Sopenharmony_ci 29252c593315Sopenharmony_ci if (split_host_port(host, sizeof(host), &port, 29262c593315Sopenharmony_ci StringRef{std::begin(optarg), addr_end}, opt) == -1) { 29272c593315Sopenharmony_ci return -1; 29282c593315Sopenharmony_ci } 29292c593315Sopenharmony_ci 29302c593315Sopenharmony_ci addr.host = make_string_ref(config->balloc, StringRef{host}); 29312c593315Sopenharmony_ci addr.port = port; 29322c593315Sopenharmony_ci 29332c593315Sopenharmony_ci if (util::numeric_host(host, AF_INET)) { 29342c593315Sopenharmony_ci addr.family = AF_INET; 29352c593315Sopenharmony_ci addr.index = addrs.size(); 29362c593315Sopenharmony_ci addrs.push_back(std::move(addr)); 29372c593315Sopenharmony_ci return 0; 29382c593315Sopenharmony_ci } 29392c593315Sopenharmony_ci 29402c593315Sopenharmony_ci if (util::numeric_host(host, AF_INET6)) { 29412c593315Sopenharmony_ci addr.family = AF_INET6; 29422c593315Sopenharmony_ci addr.index = addrs.size(); 29432c593315Sopenharmony_ci addrs.push_back(std::move(addr)); 29442c593315Sopenharmony_ci return 0; 29452c593315Sopenharmony_ci } 29462c593315Sopenharmony_ci 29472c593315Sopenharmony_ci addr.family = AF_INET; 29482c593315Sopenharmony_ci addr.index = addrs.size(); 29492c593315Sopenharmony_ci addrs.push_back(addr); 29502c593315Sopenharmony_ci 29512c593315Sopenharmony_ci addr.family = AF_INET6; 29522c593315Sopenharmony_ci addr.index = addrs.size(); 29532c593315Sopenharmony_ci addrs.push_back(std::move(addr)); 29542c593315Sopenharmony_ci 29552c593315Sopenharmony_ci return 0; 29562c593315Sopenharmony_ci } 29572c593315Sopenharmony_ci case SHRPX_OPTID_WORKERS: 29582c593315Sopenharmony_ci#ifdef NOTHREADS 29592c593315Sopenharmony_ci LOG(WARN) << "Threading disabled at build time, no threads created."; 29602c593315Sopenharmony_ci return 0; 29612c593315Sopenharmony_ci#else // !NOTHREADS 29622c593315Sopenharmony_ci return parse_uint(&config->num_worker, opt, optarg); 29632c593315Sopenharmony_ci#endif // !NOTHREADS 29642c593315Sopenharmony_ci case SHRPX_OPTID_HTTP2_MAX_CONCURRENT_STREAMS: { 29652c593315Sopenharmony_ci LOG(WARN) << opt << ": deprecated. Use " 29662c593315Sopenharmony_ci << SHRPX_OPT_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS << " and " 29672c593315Sopenharmony_ci << SHRPX_OPT_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS << " instead."; 29682c593315Sopenharmony_ci size_t n; 29692c593315Sopenharmony_ci if (parse_uint(&n, opt, optarg) != 0) { 29702c593315Sopenharmony_ci return -1; 29712c593315Sopenharmony_ci } 29722c593315Sopenharmony_ci auto &http2conf = config->http2; 29732c593315Sopenharmony_ci http2conf.upstream.max_concurrent_streams = n; 29742c593315Sopenharmony_ci http2conf.downstream.max_concurrent_streams = n; 29752c593315Sopenharmony_ci 29762c593315Sopenharmony_ci return 0; 29772c593315Sopenharmony_ci } 29782c593315Sopenharmony_ci case SHRPX_OPTID_LOG_LEVEL: { 29792c593315Sopenharmony_ci auto level = Log::get_severity_level_by_name(optarg); 29802c593315Sopenharmony_ci if (level == -1) { 29812c593315Sopenharmony_ci LOG(ERROR) << opt << ": Invalid severity level: " << optarg; 29822c593315Sopenharmony_ci return -1; 29832c593315Sopenharmony_ci } 29842c593315Sopenharmony_ci config->logging.severity = level; 29852c593315Sopenharmony_ci 29862c593315Sopenharmony_ci return 0; 29872c593315Sopenharmony_ci } 29882c593315Sopenharmony_ci case SHRPX_OPTID_DAEMON: 29892c593315Sopenharmony_ci config->daemon = util::strieq_l("yes", optarg); 29902c593315Sopenharmony_ci 29912c593315Sopenharmony_ci return 0; 29922c593315Sopenharmony_ci case SHRPX_OPTID_HTTP2_PROXY: 29932c593315Sopenharmony_ci config->http2_proxy = util::strieq_l("yes", optarg); 29942c593315Sopenharmony_ci 29952c593315Sopenharmony_ci return 0; 29962c593315Sopenharmony_ci case SHRPX_OPTID_HTTP2_BRIDGE: 29972c593315Sopenharmony_ci LOG(ERROR) << opt 29982c593315Sopenharmony_ci << ": deprecated. Use backend=<addr>,<port>;;proto=h2;tls"; 29992c593315Sopenharmony_ci return -1; 30002c593315Sopenharmony_ci case SHRPX_OPTID_CLIENT_PROXY: 30012c593315Sopenharmony_ci LOG(ERROR) 30022c593315Sopenharmony_ci << opt 30032c593315Sopenharmony_ci << ": deprecated. Use http2-proxy, frontend=<addr>,<port>;no-tls " 30042c593315Sopenharmony_ci "and backend=<addr>,<port>;;proto=h2;tls"; 30052c593315Sopenharmony_ci return -1; 30062c593315Sopenharmony_ci case SHRPX_OPTID_ADD_X_FORWARDED_FOR: 30072c593315Sopenharmony_ci config->http.xff.add = util::strieq_l("yes", optarg); 30082c593315Sopenharmony_ci 30092c593315Sopenharmony_ci return 0; 30102c593315Sopenharmony_ci case SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR: 30112c593315Sopenharmony_ci config->http.xff.strip_incoming = util::strieq_l("yes", optarg); 30122c593315Sopenharmony_ci 30132c593315Sopenharmony_ci return 0; 30142c593315Sopenharmony_ci case SHRPX_OPTID_NO_VIA: 30152c593315Sopenharmony_ci config->http.no_via = util::strieq_l("yes", optarg); 30162c593315Sopenharmony_ci 30172c593315Sopenharmony_ci return 0; 30182c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT: 30192c593315Sopenharmony_ci return parse_duration(&config->conn.upstream.timeout.http2_read, opt, 30202c593315Sopenharmony_ci optarg); 30212c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_READ_TIMEOUT: 30222c593315Sopenharmony_ci return parse_duration(&config->conn.upstream.timeout.read, opt, optarg); 30232c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_WRITE_TIMEOUT: 30242c593315Sopenharmony_ci return parse_duration(&config->conn.upstream.timeout.write, opt, optarg); 30252c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_READ_TIMEOUT: 30262c593315Sopenharmony_ci return parse_duration(&config->conn.downstream->timeout.read, opt, optarg); 30272c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_WRITE_TIMEOUT: 30282c593315Sopenharmony_ci return parse_duration(&config->conn.downstream->timeout.write, opt, optarg); 30292c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_CONNECT_TIMEOUT: 30302c593315Sopenharmony_ci return parse_duration(&config->conn.downstream->timeout.connect, opt, 30312c593315Sopenharmony_ci optarg); 30322c593315Sopenharmony_ci case SHRPX_OPTID_STREAM_READ_TIMEOUT: 30332c593315Sopenharmony_ci return parse_duration(&config->http2.timeout.stream_read, opt, optarg); 30342c593315Sopenharmony_ci case SHRPX_OPTID_STREAM_WRITE_TIMEOUT: 30352c593315Sopenharmony_ci return parse_duration(&config->http2.timeout.stream_write, opt, optarg); 30362c593315Sopenharmony_ci case SHRPX_OPTID_ACCESSLOG_FILE: 30372c593315Sopenharmony_ci config->logging.access.file = make_string_ref(config->balloc, optarg); 30382c593315Sopenharmony_ci 30392c593315Sopenharmony_ci return 0; 30402c593315Sopenharmony_ci case SHRPX_OPTID_ACCESSLOG_SYSLOG: 30412c593315Sopenharmony_ci config->logging.access.syslog = util::strieq_l("yes", optarg); 30422c593315Sopenharmony_ci 30432c593315Sopenharmony_ci return 0; 30442c593315Sopenharmony_ci case SHRPX_OPTID_ACCESSLOG_FORMAT: 30452c593315Sopenharmony_ci config->logging.access.format = parse_log_format(config->balloc, optarg); 30462c593315Sopenharmony_ci 30472c593315Sopenharmony_ci return 0; 30482c593315Sopenharmony_ci case SHRPX_OPTID_ERRORLOG_FILE: 30492c593315Sopenharmony_ci config->logging.error.file = make_string_ref(config->balloc, optarg); 30502c593315Sopenharmony_ci 30512c593315Sopenharmony_ci return 0; 30522c593315Sopenharmony_ci case SHRPX_OPTID_ERRORLOG_SYSLOG: 30532c593315Sopenharmony_ci config->logging.error.syslog = util::strieq_l("yes", optarg); 30542c593315Sopenharmony_ci 30552c593315Sopenharmony_ci return 0; 30562c593315Sopenharmony_ci case SHRPX_OPTID_FASTOPEN: 30572c593315Sopenharmony_ci return parse_uint(&config->conn.listener.fastopen, opt, optarg); 30582c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT: 30592c593315Sopenharmony_ci return parse_duration(&config->conn.downstream->timeout.idle_read, opt, 30602c593315Sopenharmony_ci optarg); 30612c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS: 30622c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_HTTP2_WINDOW_BITS: { 30632c593315Sopenharmony_ci LOG(WARN) << opt << ": deprecated. Use " 30642c593315Sopenharmony_ci << (optid == SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS 30652c593315Sopenharmony_ci ? SHRPX_OPT_FRONTEND_HTTP2_WINDOW_SIZE 30662c593315Sopenharmony_ci : SHRPX_OPT_BACKEND_HTTP2_WINDOW_SIZE); 30672c593315Sopenharmony_ci int32_t *resp; 30682c593315Sopenharmony_ci 30692c593315Sopenharmony_ci if (optid == SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS) { 30702c593315Sopenharmony_ci resp = &config->http2.upstream.window_size; 30712c593315Sopenharmony_ci } else { 30722c593315Sopenharmony_ci resp = &config->http2.downstream.window_size; 30732c593315Sopenharmony_ci } 30742c593315Sopenharmony_ci 30752c593315Sopenharmony_ci errno = 0; 30762c593315Sopenharmony_ci 30772c593315Sopenharmony_ci int n; 30782c593315Sopenharmony_ci 30792c593315Sopenharmony_ci if (parse_uint(&n, opt, optarg) != 0) { 30802c593315Sopenharmony_ci return -1; 30812c593315Sopenharmony_ci } 30822c593315Sopenharmony_ci 30832c593315Sopenharmony_ci if (n >= 31) { 30842c593315Sopenharmony_ci LOG(ERROR) << opt 30852c593315Sopenharmony_ci << ": specify the integer in the range [0, 30], inclusive"; 30862c593315Sopenharmony_ci return -1; 30872c593315Sopenharmony_ci } 30882c593315Sopenharmony_ci 30892c593315Sopenharmony_ci // Make 16 bits to the HTTP/2 default 64KiB - 1. This is the same 30902c593315Sopenharmony_ci // behaviour of previous code. 30912c593315Sopenharmony_ci *resp = (1 << n) - 1; 30922c593315Sopenharmony_ci 30932c593315Sopenharmony_ci return 0; 30942c593315Sopenharmony_ci } 30952c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS: 30962c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_BITS: { 30972c593315Sopenharmony_ci LOG(WARN) << opt << ": deprecated. Use " 30982c593315Sopenharmony_ci << (optid == SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS 30992c593315Sopenharmony_ci ? SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE 31002c593315Sopenharmony_ci : SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE); 31012c593315Sopenharmony_ci int32_t *resp; 31022c593315Sopenharmony_ci 31032c593315Sopenharmony_ci if (optid == SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS) { 31042c593315Sopenharmony_ci resp = &config->http2.upstream.connection_window_size; 31052c593315Sopenharmony_ci } else { 31062c593315Sopenharmony_ci resp = &config->http2.downstream.connection_window_size; 31072c593315Sopenharmony_ci } 31082c593315Sopenharmony_ci 31092c593315Sopenharmony_ci errno = 0; 31102c593315Sopenharmony_ci 31112c593315Sopenharmony_ci int n; 31122c593315Sopenharmony_ci 31132c593315Sopenharmony_ci if (parse_uint(&n, opt, optarg) != 0) { 31142c593315Sopenharmony_ci return -1; 31152c593315Sopenharmony_ci } 31162c593315Sopenharmony_ci 31172c593315Sopenharmony_ci if (n < 16 || n >= 31) { 31182c593315Sopenharmony_ci LOG(ERROR) << opt 31192c593315Sopenharmony_ci << ": specify the integer in the range [16, 30], inclusive"; 31202c593315Sopenharmony_ci return -1; 31212c593315Sopenharmony_ci } 31222c593315Sopenharmony_ci 31232c593315Sopenharmony_ci *resp = (1 << n) - 1; 31242c593315Sopenharmony_ci 31252c593315Sopenharmony_ci return 0; 31262c593315Sopenharmony_ci } 31272c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_NO_TLS: 31282c593315Sopenharmony_ci LOG(WARN) << opt << ": deprecated. Use no-tls keyword in " 31292c593315Sopenharmony_ci << SHRPX_OPT_FRONTEND; 31302c593315Sopenharmony_ci return 0; 31312c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_NO_TLS: 31322c593315Sopenharmony_ci LOG(WARN) << opt 31332c593315Sopenharmony_ci << ": deprecated. backend connection is not encrypted by " 31342c593315Sopenharmony_ci "default. See also " 31352c593315Sopenharmony_ci << SHRPX_OPT_BACKEND_TLS; 31362c593315Sopenharmony_ci return 0; 31372c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_TLS_SNI_FIELD: 31382c593315Sopenharmony_ci LOG(WARN) << opt 31392c593315Sopenharmony_ci << ": deprecated. Use sni keyword in --backend option. " 31402c593315Sopenharmony_ci "For now, all sni values of all backends are " 31412c593315Sopenharmony_ci "overridden by the given value " 31422c593315Sopenharmony_ci << optarg; 31432c593315Sopenharmony_ci config->tls.backend_sni_name = make_string_ref(config->balloc, optarg); 31442c593315Sopenharmony_ci 31452c593315Sopenharmony_ci return 0; 31462c593315Sopenharmony_ci case SHRPX_OPTID_PID_FILE: 31472c593315Sopenharmony_ci config->pid_file = make_string_ref(config->balloc, optarg); 31482c593315Sopenharmony_ci 31492c593315Sopenharmony_ci return 0; 31502c593315Sopenharmony_ci case SHRPX_OPTID_USER: { 31512c593315Sopenharmony_ci auto pwd = getpwnam(optarg.c_str()); 31522c593315Sopenharmony_ci if (!pwd) { 31532c593315Sopenharmony_ci LOG(ERROR) << opt << ": failed to get uid from " << optarg << ": " 31542c593315Sopenharmony_ci << xsi_strerror(errno, errbuf.data(), errbuf.size()); 31552c593315Sopenharmony_ci return -1; 31562c593315Sopenharmony_ci } 31572c593315Sopenharmony_ci config->user = make_string_ref(config->balloc, StringRef{pwd->pw_name}); 31582c593315Sopenharmony_ci config->uid = pwd->pw_uid; 31592c593315Sopenharmony_ci config->gid = pwd->pw_gid; 31602c593315Sopenharmony_ci 31612c593315Sopenharmony_ci return 0; 31622c593315Sopenharmony_ci } 31632c593315Sopenharmony_ci case SHRPX_OPTID_PRIVATE_KEY_FILE: 31642c593315Sopenharmony_ci config->tls.private_key_file = make_string_ref(config->balloc, optarg); 31652c593315Sopenharmony_ci 31662c593315Sopenharmony_ci return 0; 31672c593315Sopenharmony_ci case SHRPX_OPTID_PRIVATE_KEY_PASSWD_FILE: { 31682c593315Sopenharmony_ci auto passwd = read_passwd_from_file(opt, optarg); 31692c593315Sopenharmony_ci if (passwd.empty()) { 31702c593315Sopenharmony_ci LOG(ERROR) << opt << ": Couldn't read key file's passwd from " << optarg; 31712c593315Sopenharmony_ci return -1; 31722c593315Sopenharmony_ci } 31732c593315Sopenharmony_ci config->tls.private_key_passwd = 31742c593315Sopenharmony_ci make_string_ref(config->balloc, StringRef{passwd}); 31752c593315Sopenharmony_ci 31762c593315Sopenharmony_ci return 0; 31772c593315Sopenharmony_ci } 31782c593315Sopenharmony_ci case SHRPX_OPTID_CERTIFICATE_FILE: 31792c593315Sopenharmony_ci config->tls.cert_file = make_string_ref(config->balloc, optarg); 31802c593315Sopenharmony_ci 31812c593315Sopenharmony_ci return 0; 31822c593315Sopenharmony_ci case SHRPX_OPTID_DH_PARAM_FILE: 31832c593315Sopenharmony_ci config->tls.dh_param_file = make_string_ref(config->balloc, optarg); 31842c593315Sopenharmony_ci 31852c593315Sopenharmony_ci return 0; 31862c593315Sopenharmony_ci case SHRPX_OPTID_SUBCERT: { 31872c593315Sopenharmony_ci auto end_keys = std::find(std::begin(optarg), std::end(optarg), ';'); 31882c593315Sopenharmony_ci auto src_params = StringRef{end_keys, std::end(optarg)}; 31892c593315Sopenharmony_ci 31902c593315Sopenharmony_ci SubcertParams params; 31912c593315Sopenharmony_ci if (parse_subcert_params(params, src_params) != 0) { 31922c593315Sopenharmony_ci return -1; 31932c593315Sopenharmony_ci } 31942c593315Sopenharmony_ci 31952c593315Sopenharmony_ci std::vector<uint8_t> sct_data; 31962c593315Sopenharmony_ci 31972c593315Sopenharmony_ci if (!params.sct_dir.empty()) { 31982c593315Sopenharmony_ci // Make sure that dir_path is NULL terminated string. 31992c593315Sopenharmony_ci if (read_tls_sct_from_dir(sct_data, opt, 32002c593315Sopenharmony_ci StringRef{params.sct_dir.str()}) != 0) { 32012c593315Sopenharmony_ci return -1; 32022c593315Sopenharmony_ci } 32032c593315Sopenharmony_ci } 32042c593315Sopenharmony_ci 32052c593315Sopenharmony_ci // Private Key file and certificate file separated by ':'. 32062c593315Sopenharmony_ci auto sp = std::find(std::begin(optarg), end_keys, ':'); 32072c593315Sopenharmony_ci if (sp == end_keys) { 32082c593315Sopenharmony_ci LOG(ERROR) << opt << ": missing ':' in " 32092c593315Sopenharmony_ci << StringRef{std::begin(optarg), end_keys}; 32102c593315Sopenharmony_ci return -1; 32112c593315Sopenharmony_ci } 32122c593315Sopenharmony_ci 32132c593315Sopenharmony_ci auto private_key_file = StringRef{std::begin(optarg), sp}; 32142c593315Sopenharmony_ci 32152c593315Sopenharmony_ci if (private_key_file.empty()) { 32162c593315Sopenharmony_ci LOG(ERROR) << opt << ": missing private key file: " 32172c593315Sopenharmony_ci << StringRef{std::begin(optarg), end_keys}; 32182c593315Sopenharmony_ci return -1; 32192c593315Sopenharmony_ci } 32202c593315Sopenharmony_ci 32212c593315Sopenharmony_ci auto cert_file = StringRef{sp + 1, end_keys}; 32222c593315Sopenharmony_ci 32232c593315Sopenharmony_ci if (cert_file.empty()) { 32242c593315Sopenharmony_ci LOG(ERROR) << opt << ": missing certificate file: " 32252c593315Sopenharmony_ci << StringRef{std::begin(optarg), end_keys}; 32262c593315Sopenharmony_ci return -1; 32272c593315Sopenharmony_ci } 32282c593315Sopenharmony_ci 32292c593315Sopenharmony_ci config->tls.subcerts.emplace_back( 32302c593315Sopenharmony_ci make_string_ref(config->balloc, private_key_file), 32312c593315Sopenharmony_ci make_string_ref(config->balloc, cert_file), std::move(sct_data)); 32322c593315Sopenharmony_ci 32332c593315Sopenharmony_ci return 0; 32342c593315Sopenharmony_ci } 32352c593315Sopenharmony_ci case SHRPX_OPTID_SYSLOG_FACILITY: { 32362c593315Sopenharmony_ci int facility = int_syslog_facility(optarg); 32372c593315Sopenharmony_ci if (facility == -1) { 32382c593315Sopenharmony_ci LOG(ERROR) << opt << ": Unknown syslog facility: " << optarg; 32392c593315Sopenharmony_ci return -1; 32402c593315Sopenharmony_ci } 32412c593315Sopenharmony_ci config->logging.syslog_facility = facility; 32422c593315Sopenharmony_ci 32432c593315Sopenharmony_ci return 0; 32442c593315Sopenharmony_ci } 32452c593315Sopenharmony_ci case SHRPX_OPTID_BACKLOG: 32462c593315Sopenharmony_ci return parse_uint(&config->conn.listener.backlog, opt, optarg); 32472c593315Sopenharmony_ci case SHRPX_OPTID_CIPHERS: 32482c593315Sopenharmony_ci config->tls.ciphers = make_string_ref(config->balloc, optarg); 32492c593315Sopenharmony_ci 32502c593315Sopenharmony_ci return 0; 32512c593315Sopenharmony_ci case SHRPX_OPTID_TLS13_CIPHERS: 32522c593315Sopenharmony_ci config->tls.tls13_ciphers = make_string_ref(config->balloc, optarg); 32532c593315Sopenharmony_ci 32542c593315Sopenharmony_ci return 0; 32552c593315Sopenharmony_ci case SHRPX_OPTID_CLIENT: 32562c593315Sopenharmony_ci LOG(ERROR) << opt 32572c593315Sopenharmony_ci << ": deprecated. Use frontend=<addr>,<port>;no-tls, " 32582c593315Sopenharmony_ci "backend=<addr>,<port>;;proto=h2;tls"; 32592c593315Sopenharmony_ci return -1; 32602c593315Sopenharmony_ci case SHRPX_OPTID_INSECURE: 32612c593315Sopenharmony_ci config->tls.insecure = util::strieq_l("yes", optarg); 32622c593315Sopenharmony_ci 32632c593315Sopenharmony_ci return 0; 32642c593315Sopenharmony_ci case SHRPX_OPTID_CACERT: 32652c593315Sopenharmony_ci config->tls.cacert = make_string_ref(config->balloc, optarg); 32662c593315Sopenharmony_ci 32672c593315Sopenharmony_ci return 0; 32682c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_IPV4: 32692c593315Sopenharmony_ci LOG(WARN) << opt 32702c593315Sopenharmony_ci << ": deprecated. Use backend-address-family=IPv4 instead."; 32712c593315Sopenharmony_ci 32722c593315Sopenharmony_ci config->conn.downstream->family = AF_INET; 32732c593315Sopenharmony_ci 32742c593315Sopenharmony_ci return 0; 32752c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_IPV6: 32762c593315Sopenharmony_ci LOG(WARN) << opt 32772c593315Sopenharmony_ci << ": deprecated. Use backend-address-family=IPv6 instead."; 32782c593315Sopenharmony_ci 32792c593315Sopenharmony_ci config->conn.downstream->family = AF_INET6; 32802c593315Sopenharmony_ci 32812c593315Sopenharmony_ci return 0; 32822c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_HTTP_PROXY_URI: { 32832c593315Sopenharmony_ci auto &proxy = config->downstream_http_proxy; 32842c593315Sopenharmony_ci // Reset here so that multiple option occurrence does not merge 32852c593315Sopenharmony_ci // the results. 32862c593315Sopenharmony_ci proxy = {}; 32872c593315Sopenharmony_ci // parse URI and get hostname, port and optionally userinfo. 32882c593315Sopenharmony_ci http_parser_url u{}; 32892c593315Sopenharmony_ci int rv = http_parser_parse_url(optarg.c_str(), optarg.size(), 0, &u); 32902c593315Sopenharmony_ci if (rv == 0) { 32912c593315Sopenharmony_ci if (u.field_set & UF_USERINFO) { 32922c593315Sopenharmony_ci auto uf = util::get_uri_field(optarg.c_str(), u, UF_USERINFO); 32932c593315Sopenharmony_ci // Surprisingly, u.field_set & UF_USERINFO is nonzero even if 32942c593315Sopenharmony_ci // userinfo component is empty string. 32952c593315Sopenharmony_ci if (!uf.empty()) { 32962c593315Sopenharmony_ci proxy.userinfo = util::percent_decode(config->balloc, uf); 32972c593315Sopenharmony_ci } 32982c593315Sopenharmony_ci } 32992c593315Sopenharmony_ci if (u.field_set & UF_HOST) { 33002c593315Sopenharmony_ci proxy.host = make_string_ref( 33012c593315Sopenharmony_ci config->balloc, util::get_uri_field(optarg.c_str(), u, UF_HOST)); 33022c593315Sopenharmony_ci } else { 33032c593315Sopenharmony_ci LOG(ERROR) << opt << ": no hostname specified"; 33042c593315Sopenharmony_ci return -1; 33052c593315Sopenharmony_ci } 33062c593315Sopenharmony_ci if (u.field_set & UF_PORT) { 33072c593315Sopenharmony_ci proxy.port = u.port; 33082c593315Sopenharmony_ci } else { 33092c593315Sopenharmony_ci LOG(ERROR) << opt << ": no port specified"; 33102c593315Sopenharmony_ci return -1; 33112c593315Sopenharmony_ci } 33122c593315Sopenharmony_ci } else { 33132c593315Sopenharmony_ci LOG(ERROR) << opt << ": parse error"; 33142c593315Sopenharmony_ci return -1; 33152c593315Sopenharmony_ci } 33162c593315Sopenharmony_ci 33172c593315Sopenharmony_ci return 0; 33182c593315Sopenharmony_ci } 33192c593315Sopenharmony_ci case SHRPX_OPTID_READ_RATE: 33202c593315Sopenharmony_ci return parse_uint_with_unit(&config->conn.upstream.ratelimit.read.rate, opt, 33212c593315Sopenharmony_ci optarg); 33222c593315Sopenharmony_ci case SHRPX_OPTID_READ_BURST: 33232c593315Sopenharmony_ci return parse_uint_with_unit(&config->conn.upstream.ratelimit.read.burst, 33242c593315Sopenharmony_ci opt, optarg); 33252c593315Sopenharmony_ci case SHRPX_OPTID_WRITE_RATE: 33262c593315Sopenharmony_ci return parse_uint_with_unit(&config->conn.upstream.ratelimit.write.rate, 33272c593315Sopenharmony_ci opt, optarg); 33282c593315Sopenharmony_ci case SHRPX_OPTID_WRITE_BURST: 33292c593315Sopenharmony_ci return parse_uint_with_unit(&config->conn.upstream.ratelimit.write.burst, 33302c593315Sopenharmony_ci opt, optarg); 33312c593315Sopenharmony_ci case SHRPX_OPTID_WORKER_READ_RATE: 33322c593315Sopenharmony_ci LOG(WARN) << opt << ": not implemented yet"; 33332c593315Sopenharmony_ci return 0; 33342c593315Sopenharmony_ci case SHRPX_OPTID_WORKER_READ_BURST: 33352c593315Sopenharmony_ci LOG(WARN) << opt << ": not implemented yet"; 33362c593315Sopenharmony_ci return 0; 33372c593315Sopenharmony_ci case SHRPX_OPTID_WORKER_WRITE_RATE: 33382c593315Sopenharmony_ci LOG(WARN) << opt << ": not implemented yet"; 33392c593315Sopenharmony_ci return 0; 33402c593315Sopenharmony_ci case SHRPX_OPTID_WORKER_WRITE_BURST: 33412c593315Sopenharmony_ci LOG(WARN) << opt << ": not implemented yet"; 33422c593315Sopenharmony_ci return 0; 33432c593315Sopenharmony_ci case SHRPX_OPTID_NPN_LIST: { 33442c593315Sopenharmony_ci auto list = util::split_str(optarg, ','); 33452c593315Sopenharmony_ci config->tls.npn_list.resize(list.size()); 33462c593315Sopenharmony_ci for (size_t i = 0; i < list.size(); ++i) { 33472c593315Sopenharmony_ci config->tls.npn_list[i] = make_string_ref(config->balloc, list[i]); 33482c593315Sopenharmony_ci } 33492c593315Sopenharmony_ci 33502c593315Sopenharmony_ci return 0; 33512c593315Sopenharmony_ci } 33522c593315Sopenharmony_ci case SHRPX_OPTID_TLS_PROTO_LIST: { 33532c593315Sopenharmony_ci LOG(WARN) << opt 33542c593315Sopenharmony_ci << ": deprecated. Use tls-min-proto-version and " 33552c593315Sopenharmony_ci "tls-max-proto-version instead."; 33562c593315Sopenharmony_ci auto list = util::split_str(optarg, ','); 33572c593315Sopenharmony_ci config->tls.tls_proto_list.resize(list.size()); 33582c593315Sopenharmony_ci for (size_t i = 0; i < list.size(); ++i) { 33592c593315Sopenharmony_ci config->tls.tls_proto_list[i] = make_string_ref(config->balloc, list[i]); 33602c593315Sopenharmony_ci } 33612c593315Sopenharmony_ci 33622c593315Sopenharmony_ci return 0; 33632c593315Sopenharmony_ci } 33642c593315Sopenharmony_ci case SHRPX_OPTID_VERIFY_CLIENT: 33652c593315Sopenharmony_ci config->tls.client_verify.enabled = util::strieq_l("yes", optarg); 33662c593315Sopenharmony_ci 33672c593315Sopenharmony_ci return 0; 33682c593315Sopenharmony_ci case SHRPX_OPTID_VERIFY_CLIENT_CACERT: 33692c593315Sopenharmony_ci config->tls.client_verify.cacert = make_string_ref(config->balloc, optarg); 33702c593315Sopenharmony_ci 33712c593315Sopenharmony_ci return 0; 33722c593315Sopenharmony_ci case SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE: 33732c593315Sopenharmony_ci config->tls.client.private_key_file = 33742c593315Sopenharmony_ci make_string_ref(config->balloc, optarg); 33752c593315Sopenharmony_ci 33762c593315Sopenharmony_ci return 0; 33772c593315Sopenharmony_ci case SHRPX_OPTID_CLIENT_CERT_FILE: 33782c593315Sopenharmony_ci config->tls.client.cert_file = make_string_ref(config->balloc, optarg); 33792c593315Sopenharmony_ci 33802c593315Sopenharmony_ci return 0; 33812c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER: 33822c593315Sopenharmony_ci config->http2.upstream.debug.dump.request_header_file = 33832c593315Sopenharmony_ci make_string_ref(config->balloc, optarg); 33842c593315Sopenharmony_ci 33852c593315Sopenharmony_ci return 0; 33862c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER: 33872c593315Sopenharmony_ci config->http2.upstream.debug.dump.response_header_file = 33882c593315Sopenharmony_ci make_string_ref(config->balloc, optarg); 33892c593315Sopenharmony_ci 33902c593315Sopenharmony_ci return 0; 33912c593315Sopenharmony_ci case SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING: 33922c593315Sopenharmony_ci config->http2.no_cookie_crumbling = util::strieq_l("yes", optarg); 33932c593315Sopenharmony_ci 33942c593315Sopenharmony_ci return 0; 33952c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_FRAME_DEBUG: 33962c593315Sopenharmony_ci config->http2.upstream.debug.frame_debug = util::strieq_l("yes", optarg); 33972c593315Sopenharmony_ci 33982c593315Sopenharmony_ci return 0; 33992c593315Sopenharmony_ci case SHRPX_OPTID_PADDING: 34002c593315Sopenharmony_ci return parse_uint(&config->padding, opt, optarg); 34012c593315Sopenharmony_ci case SHRPX_OPTID_ALTSVC: { 34022c593315Sopenharmony_ci AltSvc altsvc{}; 34032c593315Sopenharmony_ci 34042c593315Sopenharmony_ci if (parse_altsvc(altsvc, opt, optarg) != 0) { 34052c593315Sopenharmony_ci return -1; 34062c593315Sopenharmony_ci } 34072c593315Sopenharmony_ci 34082c593315Sopenharmony_ci config->http.altsvcs.push_back(std::move(altsvc)); 34092c593315Sopenharmony_ci 34102c593315Sopenharmony_ci return 0; 34112c593315Sopenharmony_ci } 34122c593315Sopenharmony_ci case SHRPX_OPTID_ADD_REQUEST_HEADER: 34132c593315Sopenharmony_ci case SHRPX_OPTID_ADD_RESPONSE_HEADER: { 34142c593315Sopenharmony_ci auto p = parse_header(config->balloc, optarg); 34152c593315Sopenharmony_ci if (p.name.empty()) { 34162c593315Sopenharmony_ci LOG(ERROR) << opt << ": invalid header field: " << optarg; 34172c593315Sopenharmony_ci return -1; 34182c593315Sopenharmony_ci } 34192c593315Sopenharmony_ci if (optid == SHRPX_OPTID_ADD_REQUEST_HEADER) { 34202c593315Sopenharmony_ci config->http.add_request_headers.push_back(std::move(p)); 34212c593315Sopenharmony_ci } else { 34222c593315Sopenharmony_ci config->http.add_response_headers.push_back(std::move(p)); 34232c593315Sopenharmony_ci } 34242c593315Sopenharmony_ci return 0; 34252c593315Sopenharmony_ci } 34262c593315Sopenharmony_ci case SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS: 34272c593315Sopenharmony_ci return parse_uint(&config->conn.upstream.worker_connections, opt, optarg); 34282c593315Sopenharmony_ci case SHRPX_OPTID_NO_LOCATION_REWRITE: 34292c593315Sopenharmony_ci config->http.no_location_rewrite = util::strieq_l("yes", optarg); 34302c593315Sopenharmony_ci 34312c593315Sopenharmony_ci return 0; 34322c593315Sopenharmony_ci case SHRPX_OPTID_NO_HOST_REWRITE: 34332c593315Sopenharmony_ci LOG(WARN) << SHRPX_OPT_NO_HOST_REWRITE 34342c593315Sopenharmony_ci << ": deprecated. :authority and host header fields are NOT " 34352c593315Sopenharmony_ci "altered by default. To rewrite these headers, use " 34362c593315Sopenharmony_ci "--host-rewrite option."; 34372c593315Sopenharmony_ci 34382c593315Sopenharmony_ci return 0; 34392c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_HOST: 34402c593315Sopenharmony_ci LOG(WARN) << opt 34412c593315Sopenharmony_ci << ": deprecated. Use backend-connections-per-host instead."; 34422c593315Sopenharmony_ci // fall through 34432c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_CONNECTIONS_PER_HOST: { 34442c593315Sopenharmony_ci int n; 34452c593315Sopenharmony_ci 34462c593315Sopenharmony_ci if (parse_uint(&n, opt, optarg) != 0) { 34472c593315Sopenharmony_ci return -1; 34482c593315Sopenharmony_ci } 34492c593315Sopenharmony_ci 34502c593315Sopenharmony_ci if (n == 0) { 34512c593315Sopenharmony_ci LOG(ERROR) << opt << ": specify an integer strictly more than 0"; 34522c593315Sopenharmony_ci 34532c593315Sopenharmony_ci return -1; 34542c593315Sopenharmony_ci } 34552c593315Sopenharmony_ci 34562c593315Sopenharmony_ci config->conn.downstream->connections_per_host = n; 34572c593315Sopenharmony_ci 34582c593315Sopenharmony_ci return 0; 34592c593315Sopenharmony_ci } 34602c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND: 34612c593315Sopenharmony_ci LOG(WARN) << opt << ": deprecated. Use " 34622c593315Sopenharmony_ci << SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND << " instead."; 34632c593315Sopenharmony_ci // fall through 34642c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_CONNECTIONS_PER_FRONTEND: 34652c593315Sopenharmony_ci return parse_uint(&config->conn.downstream->connections_per_frontend, opt, 34662c593315Sopenharmony_ci optarg); 34672c593315Sopenharmony_ci case SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT: 34682c593315Sopenharmony_ci return parse_duration(&config->conn.listener.timeout.sleep, opt, optarg); 34692c593315Sopenharmony_ci case SHRPX_OPTID_TLS_TICKET_KEY_FILE: 34702c593315Sopenharmony_ci config->tls.ticket.files.emplace_back( 34712c593315Sopenharmony_ci make_string_ref(config->balloc, optarg)); 34722c593315Sopenharmony_ci return 0; 34732c593315Sopenharmony_ci case SHRPX_OPTID_RLIMIT_NOFILE: { 34742c593315Sopenharmony_ci int n; 34752c593315Sopenharmony_ci 34762c593315Sopenharmony_ci if (parse_uint(&n, opt, optarg) != 0) { 34772c593315Sopenharmony_ci return -1; 34782c593315Sopenharmony_ci } 34792c593315Sopenharmony_ci 34802c593315Sopenharmony_ci if (n < 0) { 34812c593315Sopenharmony_ci LOG(ERROR) << opt << ": specify the integer more than or equal to 0"; 34822c593315Sopenharmony_ci 34832c593315Sopenharmony_ci return -1; 34842c593315Sopenharmony_ci } 34852c593315Sopenharmony_ci 34862c593315Sopenharmony_ci config->rlimit_nofile = n; 34872c593315Sopenharmony_ci 34882c593315Sopenharmony_ci return 0; 34892c593315Sopenharmony_ci } 34902c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_REQUEST_BUFFER: 34912c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_RESPONSE_BUFFER: { 34922c593315Sopenharmony_ci size_t n; 34932c593315Sopenharmony_ci if (parse_uint_with_unit(&n, opt, optarg) != 0) { 34942c593315Sopenharmony_ci return -1; 34952c593315Sopenharmony_ci } 34962c593315Sopenharmony_ci 34972c593315Sopenharmony_ci if (n == 0) { 34982c593315Sopenharmony_ci LOG(ERROR) << opt << ": specify an integer strictly more than 0"; 34992c593315Sopenharmony_ci 35002c593315Sopenharmony_ci return -1; 35012c593315Sopenharmony_ci } 35022c593315Sopenharmony_ci 35032c593315Sopenharmony_ci if (optid == SHRPX_OPTID_BACKEND_REQUEST_BUFFER) { 35042c593315Sopenharmony_ci config->conn.downstream->request_buffer_size = n; 35052c593315Sopenharmony_ci } else { 35062c593315Sopenharmony_ci config->conn.downstream->response_buffer_size = n; 35072c593315Sopenharmony_ci } 35082c593315Sopenharmony_ci 35092c593315Sopenharmony_ci return 0; 35102c593315Sopenharmony_ci } 35112c593315Sopenharmony_ci 35122c593315Sopenharmony_ci case SHRPX_OPTID_NO_SERVER_PUSH: 35132c593315Sopenharmony_ci config->http2.no_server_push = util::strieq_l("yes", optarg); 35142c593315Sopenharmony_ci 35152c593315Sopenharmony_ci return 0; 35162c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER: 35172c593315Sopenharmony_ci LOG(WARN) << opt << ": deprecated."; 35182c593315Sopenharmony_ci return 0; 35192c593315Sopenharmony_ci case SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE: 35202c593315Sopenharmony_ci config->tls.ocsp.fetch_ocsp_response_file = 35212c593315Sopenharmony_ci make_string_ref(config->balloc, optarg); 35222c593315Sopenharmony_ci 35232c593315Sopenharmony_ci return 0; 35242c593315Sopenharmony_ci case SHRPX_OPTID_OCSP_UPDATE_INTERVAL: 35252c593315Sopenharmony_ci return parse_duration(&config->tls.ocsp.update_interval, opt, optarg); 35262c593315Sopenharmony_ci case SHRPX_OPTID_NO_OCSP: 35272c593315Sopenharmony_ci config->tls.ocsp.disabled = util::strieq_l("yes", optarg); 35282c593315Sopenharmony_ci 35292c593315Sopenharmony_ci return 0; 35302c593315Sopenharmony_ci case SHRPX_OPTID_HEADER_FIELD_BUFFER: 35312c593315Sopenharmony_ci LOG(WARN) << opt 35322c593315Sopenharmony_ci << ": deprecated. Use request-header-field-buffer instead."; 35332c593315Sopenharmony_ci // fall through 35342c593315Sopenharmony_ci case SHRPX_OPTID_REQUEST_HEADER_FIELD_BUFFER: 35352c593315Sopenharmony_ci return parse_uint_with_unit(&config->http.request_header_field_buffer, opt, 35362c593315Sopenharmony_ci optarg); 35372c593315Sopenharmony_ci case SHRPX_OPTID_MAX_HEADER_FIELDS: 35382c593315Sopenharmony_ci LOG(WARN) << opt << ": deprecated. Use max-request-header-fields instead."; 35392c593315Sopenharmony_ci // fall through 35402c593315Sopenharmony_ci case SHRPX_OPTID_MAX_REQUEST_HEADER_FIELDS: 35412c593315Sopenharmony_ci return parse_uint(&config->http.max_request_header_fields, opt, optarg); 35422c593315Sopenharmony_ci case SHRPX_OPTID_RESPONSE_HEADER_FIELD_BUFFER: 35432c593315Sopenharmony_ci return parse_uint_with_unit(&config->http.response_header_field_buffer, opt, 35442c593315Sopenharmony_ci optarg); 35452c593315Sopenharmony_ci case SHRPX_OPTID_MAX_RESPONSE_HEADER_FIELDS: 35462c593315Sopenharmony_ci return parse_uint(&config->http.max_response_header_fields, opt, optarg); 35472c593315Sopenharmony_ci case SHRPX_OPTID_INCLUDE: { 35482c593315Sopenharmony_ci if (included_set.count(optarg)) { 35492c593315Sopenharmony_ci LOG(ERROR) << opt << ": " << optarg << " has already been included"; 35502c593315Sopenharmony_ci return -1; 35512c593315Sopenharmony_ci } 35522c593315Sopenharmony_ci 35532c593315Sopenharmony_ci included_set.insert(optarg); 35542c593315Sopenharmony_ci auto rv = 35552c593315Sopenharmony_ci load_config(config, optarg.c_str(), included_set, pattern_addr_indexer); 35562c593315Sopenharmony_ci included_set.erase(optarg); 35572c593315Sopenharmony_ci 35582c593315Sopenharmony_ci if (rv != 0) { 35592c593315Sopenharmony_ci return -1; 35602c593315Sopenharmony_ci } 35612c593315Sopenharmony_ci 35622c593315Sopenharmony_ci return 0; 35632c593315Sopenharmony_ci } 35642c593315Sopenharmony_ci case SHRPX_OPTID_TLS_TICKET_KEY_CIPHER: 35652c593315Sopenharmony_ci if (util::strieq_l("aes-128-cbc", optarg)) { 35662c593315Sopenharmony_ci config->tls.ticket.cipher = EVP_aes_128_cbc(); 35672c593315Sopenharmony_ci } else if (util::strieq_l("aes-256-cbc", optarg)) { 35682c593315Sopenharmony_ci config->tls.ticket.cipher = EVP_aes_256_cbc(); 35692c593315Sopenharmony_ci } else { 35702c593315Sopenharmony_ci LOG(ERROR) << opt 35712c593315Sopenharmony_ci << ": unsupported cipher for ticket encryption: " << optarg; 35722c593315Sopenharmony_ci return -1; 35732c593315Sopenharmony_ci } 35742c593315Sopenharmony_ci config->tls.ticket.cipher_given = true; 35752c593315Sopenharmony_ci 35762c593315Sopenharmony_ci return 0; 35772c593315Sopenharmony_ci case SHRPX_OPTID_HOST_REWRITE: 35782c593315Sopenharmony_ci config->http.no_host_rewrite = !util::strieq_l("yes", optarg); 35792c593315Sopenharmony_ci 35802c593315Sopenharmony_ci return 0; 35812c593315Sopenharmony_ci case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: 35822c593315Sopenharmony_ci case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED: { 35832c593315Sopenharmony_ci auto addr_end = std::find(std::begin(optarg), std::end(optarg), ';'); 35842c593315Sopenharmony_ci auto src_params = StringRef{addr_end, std::end(optarg)}; 35852c593315Sopenharmony_ci 35862c593315Sopenharmony_ci MemcachedConnectionParams params{}; 35872c593315Sopenharmony_ci if (parse_memcached_connection_params(params, src_params, StringRef{opt}) != 35882c593315Sopenharmony_ci 0) { 35892c593315Sopenharmony_ci return -1; 35902c593315Sopenharmony_ci } 35912c593315Sopenharmony_ci 35922c593315Sopenharmony_ci if (split_host_port(host, sizeof(host), &port, 35932c593315Sopenharmony_ci StringRef{std::begin(optarg), addr_end}, opt) == -1) { 35942c593315Sopenharmony_ci return -1; 35952c593315Sopenharmony_ci } 35962c593315Sopenharmony_ci 35972c593315Sopenharmony_ci switch (optid) { 35982c593315Sopenharmony_ci case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: { 35992c593315Sopenharmony_ci auto &memcachedconf = config->tls.session_cache.memcached; 36002c593315Sopenharmony_ci memcachedconf.host = make_string_ref(config->balloc, StringRef{host}); 36012c593315Sopenharmony_ci memcachedconf.port = port; 36022c593315Sopenharmony_ci memcachedconf.tls = params.tls; 36032c593315Sopenharmony_ci break; 36042c593315Sopenharmony_ci } 36052c593315Sopenharmony_ci case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED: { 36062c593315Sopenharmony_ci auto &memcachedconf = config->tls.ticket.memcached; 36072c593315Sopenharmony_ci memcachedconf.host = make_string_ref(config->balloc, StringRef{host}); 36082c593315Sopenharmony_ci memcachedconf.port = port; 36092c593315Sopenharmony_ci memcachedconf.tls = params.tls; 36102c593315Sopenharmony_ci break; 36112c593315Sopenharmony_ci } 36122c593315Sopenharmony_ci }; 36132c593315Sopenharmony_ci 36142c593315Sopenharmony_ci return 0; 36152c593315Sopenharmony_ci } 36162c593315Sopenharmony_ci case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_INTERVAL: 36172c593315Sopenharmony_ci return parse_duration(&config->tls.ticket.memcached.interval, opt, optarg); 36182c593315Sopenharmony_ci case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY: { 36192c593315Sopenharmony_ci int n; 36202c593315Sopenharmony_ci if (parse_uint(&n, opt, optarg) != 0) { 36212c593315Sopenharmony_ci return -1; 36222c593315Sopenharmony_ci } 36232c593315Sopenharmony_ci 36242c593315Sopenharmony_ci if (n > 30) { 36252c593315Sopenharmony_ci LOG(ERROR) << opt << ": must be smaller than or equal to 30"; 36262c593315Sopenharmony_ci return -1; 36272c593315Sopenharmony_ci } 36282c593315Sopenharmony_ci 36292c593315Sopenharmony_ci config->tls.ticket.memcached.max_retry = n; 36302c593315Sopenharmony_ci return 0; 36312c593315Sopenharmony_ci } 36322c593315Sopenharmony_ci case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL: 36332c593315Sopenharmony_ci return parse_uint(&config->tls.ticket.memcached.max_fail, opt, optarg); 36342c593315Sopenharmony_ci case SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD: { 36352c593315Sopenharmony_ci size_t n; 36362c593315Sopenharmony_ci if (parse_uint_with_unit(&n, opt, optarg) != 0) { 36372c593315Sopenharmony_ci return -1; 36382c593315Sopenharmony_ci } 36392c593315Sopenharmony_ci 36402c593315Sopenharmony_ci config->tls.dyn_rec.warmup_threshold = n; 36412c593315Sopenharmony_ci 36422c593315Sopenharmony_ci return 0; 36432c593315Sopenharmony_ci } 36442c593315Sopenharmony_ci 36452c593315Sopenharmony_ci case SHRPX_OPTID_TLS_DYN_REC_IDLE_TIMEOUT: 36462c593315Sopenharmony_ci return parse_duration(&config->tls.dyn_rec.idle_timeout, opt, optarg); 36472c593315Sopenharmony_ci 36482c593315Sopenharmony_ci case SHRPX_OPTID_MRUBY_FILE: 36492c593315Sopenharmony_ci#ifdef HAVE_MRUBY 36502c593315Sopenharmony_ci config->mruby_file = make_string_ref(config->balloc, optarg); 36512c593315Sopenharmony_ci#else // !HAVE_MRUBY 36522c593315Sopenharmony_ci LOG(WARN) << opt 36532c593315Sopenharmony_ci << ": ignored because mruby support is disabled at build time."; 36542c593315Sopenharmony_ci#endif // !HAVE_MRUBY 36552c593315Sopenharmony_ci return 0; 36562c593315Sopenharmony_ci case SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL: 36572c593315Sopenharmony_ci LOG(WARN) << opt << ": deprecated. Use proxyproto keyword in " 36582c593315Sopenharmony_ci << SHRPX_OPT_FRONTEND << " instead."; 36592c593315Sopenharmony_ci config->conn.upstream.accept_proxy_protocol = util::strieq_l("yes", optarg); 36602c593315Sopenharmony_ci 36612c593315Sopenharmony_ci return 0; 36622c593315Sopenharmony_ci case SHRPX_OPTID_ADD_FORWARDED: { 36632c593315Sopenharmony_ci auto &fwdconf = config->http.forwarded; 36642c593315Sopenharmony_ci fwdconf.params = FORWARDED_NONE; 36652c593315Sopenharmony_ci for (const auto ¶m : util::split_str(optarg, ',')) { 36662c593315Sopenharmony_ci if (util::strieq_l("by", param)) { 36672c593315Sopenharmony_ci fwdconf.params |= FORWARDED_BY; 36682c593315Sopenharmony_ci continue; 36692c593315Sopenharmony_ci } 36702c593315Sopenharmony_ci if (util::strieq_l("for", param)) { 36712c593315Sopenharmony_ci fwdconf.params |= FORWARDED_FOR; 36722c593315Sopenharmony_ci continue; 36732c593315Sopenharmony_ci } 36742c593315Sopenharmony_ci if (util::strieq_l("host", param)) { 36752c593315Sopenharmony_ci fwdconf.params |= FORWARDED_HOST; 36762c593315Sopenharmony_ci continue; 36772c593315Sopenharmony_ci } 36782c593315Sopenharmony_ci if (util::strieq_l("proto", param)) { 36792c593315Sopenharmony_ci fwdconf.params |= FORWARDED_PROTO; 36802c593315Sopenharmony_ci continue; 36812c593315Sopenharmony_ci } 36822c593315Sopenharmony_ci 36832c593315Sopenharmony_ci LOG(ERROR) << opt << ": unknown parameter " << optarg; 36842c593315Sopenharmony_ci 36852c593315Sopenharmony_ci return -1; 36862c593315Sopenharmony_ci } 36872c593315Sopenharmony_ci 36882c593315Sopenharmony_ci return 0; 36892c593315Sopenharmony_ci } 36902c593315Sopenharmony_ci case SHRPX_OPTID_STRIP_INCOMING_FORWARDED: 36912c593315Sopenharmony_ci config->http.forwarded.strip_incoming = util::strieq_l("yes", optarg); 36922c593315Sopenharmony_ci 36932c593315Sopenharmony_ci return 0; 36942c593315Sopenharmony_ci case SHRPX_OPTID_FORWARDED_BY: 36952c593315Sopenharmony_ci case SHRPX_OPTID_FORWARDED_FOR: { 36962c593315Sopenharmony_ci auto type = parse_forwarded_node_type(optarg); 36972c593315Sopenharmony_ci 36982c593315Sopenharmony_ci if (type == static_cast<ForwardedNode>(-1) || 36992c593315Sopenharmony_ci (optid == SHRPX_OPTID_FORWARDED_FOR && optarg[0] == '_')) { 37002c593315Sopenharmony_ci LOG(ERROR) << opt << ": unknown node type or illegal obfuscated string " 37012c593315Sopenharmony_ci << optarg; 37022c593315Sopenharmony_ci return -1; 37032c593315Sopenharmony_ci } 37042c593315Sopenharmony_ci 37052c593315Sopenharmony_ci auto &fwdconf = config->http.forwarded; 37062c593315Sopenharmony_ci 37072c593315Sopenharmony_ci switch (optid) { 37082c593315Sopenharmony_ci case SHRPX_OPTID_FORWARDED_BY: 37092c593315Sopenharmony_ci fwdconf.by_node_type = type; 37102c593315Sopenharmony_ci if (optarg[0] == '_') { 37112c593315Sopenharmony_ci fwdconf.by_obfuscated = make_string_ref(config->balloc, optarg); 37122c593315Sopenharmony_ci } else { 37132c593315Sopenharmony_ci fwdconf.by_obfuscated = StringRef::from_lit(""); 37142c593315Sopenharmony_ci } 37152c593315Sopenharmony_ci break; 37162c593315Sopenharmony_ci case SHRPX_OPTID_FORWARDED_FOR: 37172c593315Sopenharmony_ci fwdconf.for_node_type = type; 37182c593315Sopenharmony_ci break; 37192c593315Sopenharmony_ci } 37202c593315Sopenharmony_ci 37212c593315Sopenharmony_ci return 0; 37222c593315Sopenharmony_ci } 37232c593315Sopenharmony_ci case SHRPX_OPTID_NO_HTTP2_CIPHER_BLACK_LIST: 37242c593315Sopenharmony_ci LOG(WARN) << opt << ": deprecated. Use " 37252c593315Sopenharmony_ci << SHRPX_OPT_NO_HTTP2_CIPHER_BLOCK_LIST << " instead."; 37262c593315Sopenharmony_ci // fall through 37272c593315Sopenharmony_ci case SHRPX_OPTID_NO_HTTP2_CIPHER_BLOCK_LIST: 37282c593315Sopenharmony_ci config->tls.no_http2_cipher_block_list = util::strieq_l("yes", optarg); 37292c593315Sopenharmony_ci return 0; 37302c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_HTTP1_TLS: 37312c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_TLS: 37322c593315Sopenharmony_ci LOG(WARN) << opt << ": deprecated. Use tls keyword in " 37332c593315Sopenharmony_ci << SHRPX_OPT_BACKEND << " instead."; 37342c593315Sopenharmony_ci return 0; 37352c593315Sopenharmony_ci case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_TLS: 37362c593315Sopenharmony_ci LOG(WARN) << opt << ": deprecated. Use tls keyword in " 37372c593315Sopenharmony_ci << SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED; 37382c593315Sopenharmony_ci return 0; 37392c593315Sopenharmony_ci case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE: 37402c593315Sopenharmony_ci config->tls.session_cache.memcached.cert_file = 37412c593315Sopenharmony_ci make_string_ref(config->balloc, optarg); 37422c593315Sopenharmony_ci 37432c593315Sopenharmony_ci return 0; 37442c593315Sopenharmony_ci case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE: 37452c593315Sopenharmony_ci config->tls.session_cache.memcached.private_key_file = 37462c593315Sopenharmony_ci make_string_ref(config->balloc, optarg); 37472c593315Sopenharmony_ci 37482c593315Sopenharmony_ci return 0; 37492c593315Sopenharmony_ci case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_TLS: 37502c593315Sopenharmony_ci LOG(WARN) << opt << ": deprecated. Use tls keyword in " 37512c593315Sopenharmony_ci << SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED; 37522c593315Sopenharmony_ci return 0; 37532c593315Sopenharmony_ci case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_CERT_FILE: 37542c593315Sopenharmony_ci config->tls.ticket.memcached.cert_file = 37552c593315Sopenharmony_ci make_string_ref(config->balloc, optarg); 37562c593315Sopenharmony_ci 37572c593315Sopenharmony_ci return 0; 37582c593315Sopenharmony_ci case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE: 37592c593315Sopenharmony_ci config->tls.ticket.memcached.private_key_file = 37602c593315Sopenharmony_ci make_string_ref(config->balloc, optarg); 37612c593315Sopenharmony_ci 37622c593315Sopenharmony_ci return 0; 37632c593315Sopenharmony_ci case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY: 37642c593315Sopenharmony_ci return parse_address_family(&config->tls.ticket.memcached.family, opt, 37652c593315Sopenharmony_ci optarg); 37662c593315Sopenharmony_ci case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY: 37672c593315Sopenharmony_ci return parse_address_family(&config->tls.session_cache.memcached.family, 37682c593315Sopenharmony_ci opt, optarg); 37692c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_ADDRESS_FAMILY: 37702c593315Sopenharmony_ci return parse_address_family(&config->conn.downstream->family, opt, optarg); 37712c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS: 37722c593315Sopenharmony_ci return parse_uint(&config->http2.upstream.max_concurrent_streams, opt, 37732c593315Sopenharmony_ci optarg); 37742c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS: 37752c593315Sopenharmony_ci return parse_uint(&config->http2.downstream.max_concurrent_streams, opt, 37762c593315Sopenharmony_ci optarg); 37772c593315Sopenharmony_ci case SHRPX_OPTID_ERROR_PAGE: 37782c593315Sopenharmony_ci return parse_error_page(config->http.error_pages, opt, optarg); 37792c593315Sopenharmony_ci case SHRPX_OPTID_NO_KQUEUE: 37802c593315Sopenharmony_ci if ((ev_supported_backends() & EVBACKEND_KQUEUE) == 0) { 37812c593315Sopenharmony_ci LOG(WARN) << opt << ": kqueue is not supported on this platform"; 37822c593315Sopenharmony_ci return 0; 37832c593315Sopenharmony_ci } 37842c593315Sopenharmony_ci 37852c593315Sopenharmony_ci config->ev_loop_flags = ev_recommended_backends() & ~EVBACKEND_KQUEUE; 37862c593315Sopenharmony_ci 37872c593315Sopenharmony_ci return 0; 37882c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP2_SETTINGS_TIMEOUT: 37892c593315Sopenharmony_ci return parse_duration(&config->http2.upstream.timeout.settings, opt, 37902c593315Sopenharmony_ci optarg); 37912c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_HTTP2_SETTINGS_TIMEOUT: 37922c593315Sopenharmony_ci return parse_duration(&config->http2.downstream.timeout.settings, opt, 37932c593315Sopenharmony_ci optarg); 37942c593315Sopenharmony_ci case SHRPX_OPTID_API_MAX_REQUEST_BODY: 37952c593315Sopenharmony_ci return parse_uint_with_unit(&config->api.max_request_body, opt, optarg); 37962c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_MAX_BACKOFF: 37972c593315Sopenharmony_ci return parse_duration(&config->conn.downstream->timeout.max_backoff, opt, 37982c593315Sopenharmony_ci optarg); 37992c593315Sopenharmony_ci case SHRPX_OPTID_SERVER_NAME: 38002c593315Sopenharmony_ci config->http.server_name = make_string_ref(config->balloc, optarg); 38012c593315Sopenharmony_ci 38022c593315Sopenharmony_ci return 0; 38032c593315Sopenharmony_ci case SHRPX_OPTID_NO_SERVER_REWRITE: 38042c593315Sopenharmony_ci config->http.no_server_rewrite = util::strieq_l("yes", optarg); 38052c593315Sopenharmony_ci 38062c593315Sopenharmony_ci return 0; 38072c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE: 38082c593315Sopenharmony_ci config->http2.upstream.optimize_write_buffer_size = 38092c593315Sopenharmony_ci util::strieq_l("yes", optarg); 38102c593315Sopenharmony_ci 38112c593315Sopenharmony_ci return 0; 38122c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE: 38132c593315Sopenharmony_ci config->http2.upstream.optimize_window_size = util::strieq_l("yes", optarg); 38142c593315Sopenharmony_ci 38152c593315Sopenharmony_ci return 0; 38162c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_SIZE: 38172c593315Sopenharmony_ci if (parse_uint_with_unit(&config->http2.upstream.window_size, opt, 38182c593315Sopenharmony_ci optarg) != 0) { 38192c593315Sopenharmony_ci return -1; 38202c593315Sopenharmony_ci } 38212c593315Sopenharmony_ci 38222c593315Sopenharmony_ci return 0; 38232c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE: 38242c593315Sopenharmony_ci if (parse_uint_with_unit(&config->http2.upstream.connection_window_size, 38252c593315Sopenharmony_ci opt, optarg) != 0) { 38262c593315Sopenharmony_ci return -1; 38272c593315Sopenharmony_ci } 38282c593315Sopenharmony_ci 38292c593315Sopenharmony_ci return 0; 38302c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_HTTP2_WINDOW_SIZE: 38312c593315Sopenharmony_ci if (parse_uint_with_unit(&config->http2.downstream.window_size, opt, 38322c593315Sopenharmony_ci optarg) != 0) { 38332c593315Sopenharmony_ci return -1; 38342c593315Sopenharmony_ci } 38352c593315Sopenharmony_ci 38362c593315Sopenharmony_ci return 0; 38372c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE: 38382c593315Sopenharmony_ci if (parse_uint_with_unit(&config->http2.downstream.connection_window_size, 38392c593315Sopenharmony_ci opt, optarg) != 0) { 38402c593315Sopenharmony_ci return -1; 38412c593315Sopenharmony_ci } 38422c593315Sopenharmony_ci 38432c593315Sopenharmony_ci return 0; 38442c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE: 38452c593315Sopenharmony_ci if (parse_uint_with_unit(&config->http2.upstream.encoder_dynamic_table_size, 38462c593315Sopenharmony_ci opt, optarg) != 0) { 38472c593315Sopenharmony_ci return -1; 38482c593315Sopenharmony_ci } 38492c593315Sopenharmony_ci 38502c593315Sopenharmony_ci nghttp2_option_set_max_deflate_dynamic_table_size( 38512c593315Sopenharmony_ci config->http2.upstream.option, 38522c593315Sopenharmony_ci config->http2.upstream.encoder_dynamic_table_size); 38532c593315Sopenharmony_ci nghttp2_option_set_max_deflate_dynamic_table_size( 38542c593315Sopenharmony_ci config->http2.upstream.alt_mode_option, 38552c593315Sopenharmony_ci config->http2.upstream.encoder_dynamic_table_size); 38562c593315Sopenharmony_ci 38572c593315Sopenharmony_ci return 0; 38582c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE: 38592c593315Sopenharmony_ci return parse_uint_with_unit( 38602c593315Sopenharmony_ci &config->http2.upstream.decoder_dynamic_table_size, opt, optarg); 38612c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE: 38622c593315Sopenharmony_ci if (parse_uint_with_unit( 38632c593315Sopenharmony_ci &config->http2.downstream.encoder_dynamic_table_size, opt, 38642c593315Sopenharmony_ci optarg) != 0) { 38652c593315Sopenharmony_ci return -1; 38662c593315Sopenharmony_ci } 38672c593315Sopenharmony_ci 38682c593315Sopenharmony_ci nghttp2_option_set_max_deflate_dynamic_table_size( 38692c593315Sopenharmony_ci config->http2.downstream.option, 38702c593315Sopenharmony_ci config->http2.downstream.encoder_dynamic_table_size); 38712c593315Sopenharmony_ci 38722c593315Sopenharmony_ci return 0; 38732c593315Sopenharmony_ci case SHRPX_OPTID_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE: 38742c593315Sopenharmony_ci return parse_uint_with_unit( 38752c593315Sopenharmony_ci &config->http2.downstream.decoder_dynamic_table_size, opt, optarg); 38762c593315Sopenharmony_ci case SHRPX_OPTID_ECDH_CURVES: 38772c593315Sopenharmony_ci#if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L 38782c593315Sopenharmony_ci config->tls.ecdh_curves = make_string_ref(config->balloc, optarg); 38792c593315Sopenharmony_ci#else // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L) 38802c593315Sopenharmony_ci LOG(WARN) << opt << ": This option requires OpenSSL >= 1.0.2"; 38812c593315Sopenharmony_ci#endif // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L) 38822c593315Sopenharmony_ci return 0; 38832c593315Sopenharmony_ci case SHRPX_OPTID_TLS_SCT_DIR: 38842c593315Sopenharmony_ci#if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L 38852c593315Sopenharmony_ci return read_tls_sct_from_dir(config->tls.sct_data, opt, optarg); 38862c593315Sopenharmony_ci#else // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L) 38872c593315Sopenharmony_ci LOG(WARN) << opt << ": This option requires OpenSSL >= 1.0.2"; 38882c593315Sopenharmony_ci return 0; 38892c593315Sopenharmony_ci#endif // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L) 38902c593315Sopenharmony_ci case SHRPX_OPTID_DNS_CACHE_TIMEOUT: 38912c593315Sopenharmony_ci return parse_duration(&config->dns.timeout.cache, opt, optarg); 38922c593315Sopenharmony_ci case SHRPX_OPTID_DNS_LOOKUP_TIMEOUT: 38932c593315Sopenharmony_ci return parse_duration(&config->dns.timeout.lookup, opt, optarg); 38942c593315Sopenharmony_ci case SHRPX_OPTID_DNS_MAX_TRY: { 38952c593315Sopenharmony_ci int n; 38962c593315Sopenharmony_ci if (parse_uint(&n, opt, optarg) != 0) { 38972c593315Sopenharmony_ci return -1; 38982c593315Sopenharmony_ci } 38992c593315Sopenharmony_ci 39002c593315Sopenharmony_ci if (n > 5) { 39012c593315Sopenharmony_ci LOG(ERROR) << opt << ": must be smaller than or equal to 5"; 39022c593315Sopenharmony_ci return -1; 39032c593315Sopenharmony_ci } 39042c593315Sopenharmony_ci 39052c593315Sopenharmony_ci config->dns.max_try = n; 39062c593315Sopenharmony_ci return 0; 39072c593315Sopenharmony_ci } 39082c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_KEEP_ALIVE_TIMEOUT: 39092c593315Sopenharmony_ci return parse_duration(&config->conn.upstream.timeout.idle_read, opt, 39102c593315Sopenharmony_ci optarg); 39112c593315Sopenharmony_ci case SHRPX_OPTID_PSK_SECRETS: 39122c593315Sopenharmony_ci#if !LIBRESSL_LEGACY_API 39132c593315Sopenharmony_ci return parse_psk_secrets(config, optarg); 39142c593315Sopenharmony_ci#else // LIBRESSL_LEGACY_API 39152c593315Sopenharmony_ci LOG(WARN) 39162c593315Sopenharmony_ci << opt 39172c593315Sopenharmony_ci << ": ignored because underlying TLS library does not support PSK"; 39182c593315Sopenharmony_ci return 0; 39192c593315Sopenharmony_ci#endif // LIBRESSL_LEGACY_API 39202c593315Sopenharmony_ci case SHRPX_OPTID_CLIENT_PSK_SECRETS: 39212c593315Sopenharmony_ci#if !LIBRESSL_LEGACY_API 39222c593315Sopenharmony_ci return parse_client_psk_secrets(config, optarg); 39232c593315Sopenharmony_ci#else // LIBRESSL_LEGACY_API 39242c593315Sopenharmony_ci LOG(WARN) 39252c593315Sopenharmony_ci << opt 39262c593315Sopenharmony_ci << ": ignored because underlying TLS library does not support PSK"; 39272c593315Sopenharmony_ci return 0; 39282c593315Sopenharmony_ci#endif // LIBRESSL_LEGACY_API 39292c593315Sopenharmony_ci case SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST: 39302c593315Sopenharmony_ci LOG(WARN) << opt << ": deprecated. Use " 39312c593315Sopenharmony_ci << SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLOCK_LIST << " instead."; 39322c593315Sopenharmony_ci // fall through 39332c593315Sopenharmony_ci case SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLOCK_LIST: 39342c593315Sopenharmony_ci config->tls.client.no_http2_cipher_block_list = 39352c593315Sopenharmony_ci util::strieq_l("yes", optarg); 39362c593315Sopenharmony_ci 39372c593315Sopenharmony_ci return 0; 39382c593315Sopenharmony_ci case SHRPX_OPTID_CLIENT_CIPHERS: 39392c593315Sopenharmony_ci config->tls.client.ciphers = make_string_ref(config->balloc, optarg); 39402c593315Sopenharmony_ci 39412c593315Sopenharmony_ci return 0; 39422c593315Sopenharmony_ci case SHRPX_OPTID_TLS13_CLIENT_CIPHERS: 39432c593315Sopenharmony_ci config->tls.client.tls13_ciphers = make_string_ref(config->balloc, optarg); 39442c593315Sopenharmony_ci 39452c593315Sopenharmony_ci return 0; 39462c593315Sopenharmony_ci case SHRPX_OPTID_ACCESSLOG_WRITE_EARLY: 39472c593315Sopenharmony_ci config->logging.access.write_early = util::strieq_l("yes", optarg); 39482c593315Sopenharmony_ci 39492c593315Sopenharmony_ci return 0; 39502c593315Sopenharmony_ci case SHRPX_OPTID_TLS_MIN_PROTO_VERSION: 39512c593315Sopenharmony_ci return parse_tls_proto_version(config->tls.min_proto_version, opt, optarg); 39522c593315Sopenharmony_ci case SHRPX_OPTID_TLS_MAX_PROTO_VERSION: 39532c593315Sopenharmony_ci return parse_tls_proto_version(config->tls.max_proto_version, opt, optarg); 39542c593315Sopenharmony_ci case SHRPX_OPTID_REDIRECT_HTTPS_PORT: { 39552c593315Sopenharmony_ci auto n = util::parse_uint(optarg); 39562c593315Sopenharmony_ci if (n == -1 || n < 0 || n > 65535) { 39572c593315Sopenharmony_ci LOG(ERROR) << opt 39582c593315Sopenharmony_ci << ": bad value. Specify an integer in the range [0, " 39592c593315Sopenharmony_ci "65535], inclusive"; 39602c593315Sopenharmony_ci return -1; 39612c593315Sopenharmony_ci } 39622c593315Sopenharmony_ci config->http.redirect_https_port = make_string_ref(config->balloc, optarg); 39632c593315Sopenharmony_ci return 0; 39642c593315Sopenharmony_ci } 39652c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_MAX_REQUESTS: 39662c593315Sopenharmony_ci return parse_uint(&config->http.max_requests, opt, optarg); 39672c593315Sopenharmony_ci case SHRPX_OPTID_SINGLE_THREAD: 39682c593315Sopenharmony_ci config->single_thread = util::strieq_l("yes", optarg); 39692c593315Sopenharmony_ci 39702c593315Sopenharmony_ci return 0; 39712c593315Sopenharmony_ci case SHRPX_OPTID_SINGLE_PROCESS: 39722c593315Sopenharmony_ci config->single_process = util::strieq_l("yes", optarg); 39732c593315Sopenharmony_ci 39742c593315Sopenharmony_ci return 0; 39752c593315Sopenharmony_ci case SHRPX_OPTID_NO_ADD_X_FORWARDED_PROTO: 39762c593315Sopenharmony_ci config->http.xfp.add = !util::strieq_l("yes", optarg); 39772c593315Sopenharmony_ci 39782c593315Sopenharmony_ci return 0; 39792c593315Sopenharmony_ci case SHRPX_OPTID_NO_STRIP_INCOMING_X_FORWARDED_PROTO: 39802c593315Sopenharmony_ci config->http.xfp.strip_incoming = !util::strieq_l("yes", optarg); 39812c593315Sopenharmony_ci 39822c593315Sopenharmony_ci return 0; 39832c593315Sopenharmony_ci case SHRPX_OPTID_OCSP_STARTUP: 39842c593315Sopenharmony_ci config->tls.ocsp.startup = util::strieq_l("yes", optarg); 39852c593315Sopenharmony_ci 39862c593315Sopenharmony_ci return 0; 39872c593315Sopenharmony_ci case SHRPX_OPTID_NO_VERIFY_OCSP: 39882c593315Sopenharmony_ci config->tls.ocsp.no_verify = util::strieq_l("yes", optarg); 39892c593315Sopenharmony_ci 39902c593315Sopenharmony_ci return 0; 39912c593315Sopenharmony_ci case SHRPX_OPTID_VERIFY_CLIENT_TOLERATE_EXPIRED: 39922c593315Sopenharmony_ci config->tls.client_verify.tolerate_expired = util::strieq_l("yes", optarg); 39932c593315Sopenharmony_ci 39942c593315Sopenharmony_ci return 0; 39952c593315Sopenharmony_ci case SHRPX_OPTID_IGNORE_PER_PATTERN_MRUBY_ERROR: 39962c593315Sopenharmony_ci config->ignore_per_pattern_mruby_error = util::strieq_l("yes", optarg); 39972c593315Sopenharmony_ci 39982c593315Sopenharmony_ci return 0; 39992c593315Sopenharmony_ci case SHRPX_OPTID_TLS_NO_POSTPONE_EARLY_DATA: 40002c593315Sopenharmony_ci config->tls.no_postpone_early_data = util::strieq_l("yes", optarg); 40012c593315Sopenharmony_ci 40022c593315Sopenharmony_ci return 0; 40032c593315Sopenharmony_ci case SHRPX_OPTID_TLS_MAX_EARLY_DATA: { 40042c593315Sopenharmony_ci return parse_uint_with_unit(&config->tls.max_early_data, opt, optarg); 40052c593315Sopenharmony_ci } 40062c593315Sopenharmony_ci case SHRPX_OPTID_NO_STRIP_INCOMING_EARLY_DATA: 40072c593315Sopenharmony_ci config->http.early_data.strip_incoming = !util::strieq_l("yes", optarg); 40082c593315Sopenharmony_ci 40092c593315Sopenharmony_ci return 0; 40102c593315Sopenharmony_ci case SHRPX_OPTID_QUIC_BPF_PROGRAM_FILE: 40112c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 40122c593315Sopenharmony_ci config->quic.bpf.prog_file = make_string_ref(config->balloc, optarg); 40132c593315Sopenharmony_ci#endif // ENABLE_HTTP3 40142c593315Sopenharmony_ci 40152c593315Sopenharmony_ci return 0; 40162c593315Sopenharmony_ci case SHRPX_OPTID_NO_QUIC_BPF: 40172c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 40182c593315Sopenharmony_ci config->quic.bpf.disabled = util::strieq_l("yes", optarg); 40192c593315Sopenharmony_ci#endif // ENABLE_HTTP3 40202c593315Sopenharmony_ci 40212c593315Sopenharmony_ci return 0; 40222c593315Sopenharmony_ci case SHRPX_OPTID_HTTP2_ALTSVC: { 40232c593315Sopenharmony_ci AltSvc altsvc{}; 40242c593315Sopenharmony_ci 40252c593315Sopenharmony_ci if (parse_altsvc(altsvc, opt, optarg) != 0) { 40262c593315Sopenharmony_ci return -1; 40272c593315Sopenharmony_ci } 40282c593315Sopenharmony_ci 40292c593315Sopenharmony_ci config->http.http2_altsvcs.push_back(std::move(altsvc)); 40302c593315Sopenharmony_ci 40312c593315Sopenharmony_ci return 0; 40322c593315Sopenharmony_ci } 40332c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP3_READ_TIMEOUT: 40342c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 40352c593315Sopenharmony_ci return parse_duration(&config->conn.upstream.timeout.http3_read, opt, 40362c593315Sopenharmony_ci optarg); 40372c593315Sopenharmony_ci#else // !ENABLE_HTTP3 40382c593315Sopenharmony_ci return 0; 40392c593315Sopenharmony_ci#endif // !ENABLE_HTTP3 40402c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_QUIC_IDLE_TIMEOUT: 40412c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 40422c593315Sopenharmony_ci return parse_duration(&config->quic.upstream.timeout.idle, opt, optarg); 40432c593315Sopenharmony_ci#else // !ENABLE_HTTP3 40442c593315Sopenharmony_ci return 0; 40452c593315Sopenharmony_ci#endif // !ENABLE_HTTP3 40462c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_QUIC_DEBUG_LOG: 40472c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 40482c593315Sopenharmony_ci config->quic.upstream.debug.log = util::strieq_l("yes", optarg); 40492c593315Sopenharmony_ci#endif // ENABLE_HTTP3 40502c593315Sopenharmony_ci 40512c593315Sopenharmony_ci return 0; 40522c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP3_WINDOW_SIZE: 40532c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 40542c593315Sopenharmony_ci if (parse_uint_with_unit(&config->http3.upstream.window_size, opt, 40552c593315Sopenharmony_ci optarg) != 0) { 40562c593315Sopenharmony_ci return -1; 40572c593315Sopenharmony_ci } 40582c593315Sopenharmony_ci#endif // ENABLE_HTTP3 40592c593315Sopenharmony_ci 40602c593315Sopenharmony_ci return 0; 40612c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP3_CONNECTION_WINDOW_SIZE: 40622c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 40632c593315Sopenharmony_ci if (parse_uint_with_unit(&config->http3.upstream.connection_window_size, 40642c593315Sopenharmony_ci opt, optarg) != 0) { 40652c593315Sopenharmony_ci return -1; 40662c593315Sopenharmony_ci } 40672c593315Sopenharmony_ci#endif // ENABLE_HTTP3 40682c593315Sopenharmony_ci 40692c593315Sopenharmony_ci return 0; 40702c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP3_MAX_WINDOW_SIZE: 40712c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 40722c593315Sopenharmony_ci if (parse_uint_with_unit(&config->http3.upstream.max_window_size, opt, 40732c593315Sopenharmony_ci optarg) != 0) { 40742c593315Sopenharmony_ci return -1; 40752c593315Sopenharmony_ci } 40762c593315Sopenharmony_ci#endif // ENABLE_HTTP3 40772c593315Sopenharmony_ci 40782c593315Sopenharmony_ci return 0; 40792c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP3_MAX_CONNECTION_WINDOW_SIZE: 40802c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 40812c593315Sopenharmony_ci if (parse_uint_with_unit(&config->http3.upstream.max_connection_window_size, 40822c593315Sopenharmony_ci opt, optarg) != 0) { 40832c593315Sopenharmony_ci return -1; 40842c593315Sopenharmony_ci } 40852c593315Sopenharmony_ci#endif // ENABLE_HTTP3 40862c593315Sopenharmony_ci 40872c593315Sopenharmony_ci return 0; 40882c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_HTTP3_MAX_CONCURRENT_STREAMS: 40892c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 40902c593315Sopenharmony_ci return parse_uint(&config->http3.upstream.max_concurrent_streams, opt, 40912c593315Sopenharmony_ci optarg); 40922c593315Sopenharmony_ci#else // !ENABLE_HTTP3 40932c593315Sopenharmony_ci return 0; 40942c593315Sopenharmony_ci#endif // !ENABLE_HTTP3 40952c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_QUIC_EARLY_DATA: 40962c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 40972c593315Sopenharmony_ci config->quic.upstream.early_data = util::strieq_l("yes", optarg); 40982c593315Sopenharmony_ci#endif // ENABLE_HTTP3 40992c593315Sopenharmony_ci 41002c593315Sopenharmony_ci return 0; 41012c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_QUIC_QLOG_DIR: 41022c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 41032c593315Sopenharmony_ci config->quic.upstream.qlog.dir = make_string_ref(config->balloc, optarg); 41042c593315Sopenharmony_ci#endif // ENABLE_HTTP3 41052c593315Sopenharmony_ci 41062c593315Sopenharmony_ci return 0; 41072c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_QUIC_REQUIRE_TOKEN: 41082c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 41092c593315Sopenharmony_ci config->quic.upstream.require_token = util::strieq_l("yes", optarg); 41102c593315Sopenharmony_ci#endif // ENABLE_HTTP3 41112c593315Sopenharmony_ci 41122c593315Sopenharmony_ci return 0; 41132c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_QUIC_CONGESTION_CONTROLLER: 41142c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 41152c593315Sopenharmony_ci if (util::strieq_l("cubic", optarg)) { 41162c593315Sopenharmony_ci config->quic.upstream.congestion_controller = NGTCP2_CC_ALGO_CUBIC; 41172c593315Sopenharmony_ci } else if (util::strieq_l("bbr", optarg)) { 41182c593315Sopenharmony_ci config->quic.upstream.congestion_controller = NGTCP2_CC_ALGO_BBR; 41192c593315Sopenharmony_ci } else { 41202c593315Sopenharmony_ci LOG(ERROR) << opt << ": must be either cubic or bbr"; 41212c593315Sopenharmony_ci return -1; 41222c593315Sopenharmony_ci } 41232c593315Sopenharmony_ci#endif // ENABLE_HTTP3 41242c593315Sopenharmony_ci 41252c593315Sopenharmony_ci return 0; 41262c593315Sopenharmony_ci case SHRPX_OPTID_QUIC_SERVER_ID: 41272c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 41282c593315Sopenharmony_ci if (optarg.size() != config->quic.server_id.size() * 2 || 41292c593315Sopenharmony_ci !util::is_hex_string(optarg)) { 41302c593315Sopenharmony_ci LOG(ERROR) << opt << ": must be a hex-string"; 41312c593315Sopenharmony_ci return -1; 41322c593315Sopenharmony_ci } 41332c593315Sopenharmony_ci util::decode_hex(std::begin(config->quic.server_id), optarg); 41342c593315Sopenharmony_ci#endif // ENABLE_HTTP3 41352c593315Sopenharmony_ci 41362c593315Sopenharmony_ci return 0; 41372c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_QUIC_SECRET_FILE: 41382c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 41392c593315Sopenharmony_ci config->quic.upstream.secret_file = make_string_ref(config->balloc, optarg); 41402c593315Sopenharmony_ci#endif // ENABLE_HTTP3 41412c593315Sopenharmony_ci 41422c593315Sopenharmony_ci return 0; 41432c593315Sopenharmony_ci case SHRPX_OPTID_RLIMIT_MEMLOCK: { 41442c593315Sopenharmony_ci int n; 41452c593315Sopenharmony_ci 41462c593315Sopenharmony_ci if (parse_uint(&n, opt, optarg) != 0) { 41472c593315Sopenharmony_ci return -1; 41482c593315Sopenharmony_ci } 41492c593315Sopenharmony_ci 41502c593315Sopenharmony_ci if (n < 0) { 41512c593315Sopenharmony_ci LOG(ERROR) << opt << ": specify the integer more than or equal to 0"; 41522c593315Sopenharmony_ci 41532c593315Sopenharmony_ci return -1; 41542c593315Sopenharmony_ci } 41552c593315Sopenharmony_ci 41562c593315Sopenharmony_ci config->rlimit_memlock = n; 41572c593315Sopenharmony_ci 41582c593315Sopenharmony_ci return 0; 41592c593315Sopenharmony_ci } 41602c593315Sopenharmony_ci case SHRPX_OPTID_MAX_WORKER_PROCESSES: 41612c593315Sopenharmony_ci return parse_uint(&config->max_worker_processes, opt, optarg); 41622c593315Sopenharmony_ci case SHRPX_OPTID_WORKER_PROCESS_GRACE_SHUTDOWN_PERIOD: 41632c593315Sopenharmony_ci return parse_duration(&config->worker_process_grace_shutdown_period, opt, 41642c593315Sopenharmony_ci optarg); 41652c593315Sopenharmony_ci case SHRPX_OPTID_FRONTEND_QUIC_INITIAL_RTT: { 41662c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 41672c593315Sopenharmony_ci return parse_duration(&config->quic.upstream.initial_rtt, opt, optarg); 41682c593315Sopenharmony_ci#endif // ENABLE_HTTP3 41692c593315Sopenharmony_ci 41702c593315Sopenharmony_ci return 0; 41712c593315Sopenharmony_ci } 41722c593315Sopenharmony_ci case SHRPX_OPTID_REQUIRE_HTTP_SCHEME: 41732c593315Sopenharmony_ci config->http.require_http_scheme = util::strieq_l("yes", optarg); 41742c593315Sopenharmony_ci return 0; 41752c593315Sopenharmony_ci case SHRPX_OPTID_TLS_KTLS: 41762c593315Sopenharmony_ci config->tls.ktls = util::strieq_l("yes", optarg); 41772c593315Sopenharmony_ci return 0; 41782c593315Sopenharmony_ci case SHRPX_OPTID_CONF: 41792c593315Sopenharmony_ci LOG(WARN) << "conf: ignored"; 41802c593315Sopenharmony_ci 41812c593315Sopenharmony_ci return 0; 41822c593315Sopenharmony_ci } 41832c593315Sopenharmony_ci 41842c593315Sopenharmony_ci LOG(ERROR) << "Unknown option: " << opt; 41852c593315Sopenharmony_ci 41862c593315Sopenharmony_ci return -1; 41872c593315Sopenharmony_ci} 41882c593315Sopenharmony_ci 41892c593315Sopenharmony_ciint load_config(Config *config, const char *filename, 41902c593315Sopenharmony_ci std::set<StringRef> &include_set, 41912c593315Sopenharmony_ci std::map<StringRef, size_t> &pattern_addr_indexer) { 41922c593315Sopenharmony_ci std::ifstream in(filename, std::ios::binary); 41932c593315Sopenharmony_ci if (!in) { 41942c593315Sopenharmony_ci LOG(ERROR) << "Could not open config file " << filename; 41952c593315Sopenharmony_ci return -1; 41962c593315Sopenharmony_ci } 41972c593315Sopenharmony_ci std::string line; 41982c593315Sopenharmony_ci int linenum = 0; 41992c593315Sopenharmony_ci while (std::getline(in, line)) { 42002c593315Sopenharmony_ci ++linenum; 42012c593315Sopenharmony_ci if (line.empty() || line[0] == '#') { 42022c593315Sopenharmony_ci continue; 42032c593315Sopenharmony_ci } 42042c593315Sopenharmony_ci auto eq = std::find(std::begin(line), std::end(line), '='); 42052c593315Sopenharmony_ci if (eq == std::end(line)) { 42062c593315Sopenharmony_ci LOG(ERROR) << "Bad configuration format in " << filename << " at line " 42072c593315Sopenharmony_ci << linenum; 42082c593315Sopenharmony_ci return -1; 42092c593315Sopenharmony_ci } 42102c593315Sopenharmony_ci *eq = '\0'; 42112c593315Sopenharmony_ci 42122c593315Sopenharmony_ci if (parse_config(config, StringRef{std::begin(line), eq}, 42132c593315Sopenharmony_ci StringRef{eq + 1, std::end(line)}, include_set, 42142c593315Sopenharmony_ci pattern_addr_indexer) != 0) { 42152c593315Sopenharmony_ci return -1; 42162c593315Sopenharmony_ci } 42172c593315Sopenharmony_ci } 42182c593315Sopenharmony_ci return 0; 42192c593315Sopenharmony_ci} 42202c593315Sopenharmony_ci 42212c593315Sopenharmony_ciStringRef str_syslog_facility(int facility) { 42222c593315Sopenharmony_ci switch (facility) { 42232c593315Sopenharmony_ci case (LOG_AUTH): 42242c593315Sopenharmony_ci return StringRef::from_lit("auth"); 42252c593315Sopenharmony_ci#ifdef LOG_AUTHPRIV 42262c593315Sopenharmony_ci case (LOG_AUTHPRIV): 42272c593315Sopenharmony_ci return StringRef::from_lit("authpriv"); 42282c593315Sopenharmony_ci#endif // LOG_AUTHPRIV 42292c593315Sopenharmony_ci case (LOG_CRON): 42302c593315Sopenharmony_ci return StringRef::from_lit("cron"); 42312c593315Sopenharmony_ci case (LOG_DAEMON): 42322c593315Sopenharmony_ci return StringRef::from_lit("daemon"); 42332c593315Sopenharmony_ci#ifdef LOG_FTP 42342c593315Sopenharmony_ci case (LOG_FTP): 42352c593315Sopenharmony_ci return StringRef::from_lit("ftp"); 42362c593315Sopenharmony_ci#endif // LOG_FTP 42372c593315Sopenharmony_ci case (LOG_KERN): 42382c593315Sopenharmony_ci return StringRef::from_lit("kern"); 42392c593315Sopenharmony_ci case (LOG_LOCAL0): 42402c593315Sopenharmony_ci return StringRef::from_lit("local0"); 42412c593315Sopenharmony_ci case (LOG_LOCAL1): 42422c593315Sopenharmony_ci return StringRef::from_lit("local1"); 42432c593315Sopenharmony_ci case (LOG_LOCAL2): 42442c593315Sopenharmony_ci return StringRef::from_lit("local2"); 42452c593315Sopenharmony_ci case (LOG_LOCAL3): 42462c593315Sopenharmony_ci return StringRef::from_lit("local3"); 42472c593315Sopenharmony_ci case (LOG_LOCAL4): 42482c593315Sopenharmony_ci return StringRef::from_lit("local4"); 42492c593315Sopenharmony_ci case (LOG_LOCAL5): 42502c593315Sopenharmony_ci return StringRef::from_lit("local5"); 42512c593315Sopenharmony_ci case (LOG_LOCAL6): 42522c593315Sopenharmony_ci return StringRef::from_lit("local6"); 42532c593315Sopenharmony_ci case (LOG_LOCAL7): 42542c593315Sopenharmony_ci return StringRef::from_lit("local7"); 42552c593315Sopenharmony_ci case (LOG_LPR): 42562c593315Sopenharmony_ci return StringRef::from_lit("lpr"); 42572c593315Sopenharmony_ci case (LOG_MAIL): 42582c593315Sopenharmony_ci return StringRef::from_lit("mail"); 42592c593315Sopenharmony_ci case (LOG_SYSLOG): 42602c593315Sopenharmony_ci return StringRef::from_lit("syslog"); 42612c593315Sopenharmony_ci case (LOG_USER): 42622c593315Sopenharmony_ci return StringRef::from_lit("user"); 42632c593315Sopenharmony_ci case (LOG_UUCP): 42642c593315Sopenharmony_ci return StringRef::from_lit("uucp"); 42652c593315Sopenharmony_ci default: 42662c593315Sopenharmony_ci return StringRef::from_lit("(unknown)"); 42672c593315Sopenharmony_ci } 42682c593315Sopenharmony_ci} 42692c593315Sopenharmony_ci 42702c593315Sopenharmony_ciint int_syslog_facility(const StringRef &strfacility) { 42712c593315Sopenharmony_ci if (util::strieq_l("auth", strfacility)) { 42722c593315Sopenharmony_ci return LOG_AUTH; 42732c593315Sopenharmony_ci } 42742c593315Sopenharmony_ci 42752c593315Sopenharmony_ci#ifdef LOG_AUTHPRIV 42762c593315Sopenharmony_ci if (util::strieq_l("authpriv", strfacility)) { 42772c593315Sopenharmony_ci return LOG_AUTHPRIV; 42782c593315Sopenharmony_ci } 42792c593315Sopenharmony_ci#endif // LOG_AUTHPRIV 42802c593315Sopenharmony_ci 42812c593315Sopenharmony_ci if (util::strieq_l("cron", strfacility)) { 42822c593315Sopenharmony_ci return LOG_CRON; 42832c593315Sopenharmony_ci } 42842c593315Sopenharmony_ci 42852c593315Sopenharmony_ci if (util::strieq_l("daemon", strfacility)) { 42862c593315Sopenharmony_ci return LOG_DAEMON; 42872c593315Sopenharmony_ci } 42882c593315Sopenharmony_ci 42892c593315Sopenharmony_ci#ifdef LOG_FTP 42902c593315Sopenharmony_ci if (util::strieq_l("ftp", strfacility)) { 42912c593315Sopenharmony_ci return LOG_FTP; 42922c593315Sopenharmony_ci } 42932c593315Sopenharmony_ci#endif // LOG_FTP 42942c593315Sopenharmony_ci 42952c593315Sopenharmony_ci if (util::strieq_l("kern", strfacility)) { 42962c593315Sopenharmony_ci return LOG_KERN; 42972c593315Sopenharmony_ci } 42982c593315Sopenharmony_ci 42992c593315Sopenharmony_ci if (util::strieq_l("local0", strfacility)) { 43002c593315Sopenharmony_ci return LOG_LOCAL0; 43012c593315Sopenharmony_ci } 43022c593315Sopenharmony_ci 43032c593315Sopenharmony_ci if (util::strieq_l("local1", strfacility)) { 43042c593315Sopenharmony_ci return LOG_LOCAL1; 43052c593315Sopenharmony_ci } 43062c593315Sopenharmony_ci 43072c593315Sopenharmony_ci if (util::strieq_l("local2", strfacility)) { 43082c593315Sopenharmony_ci return LOG_LOCAL2; 43092c593315Sopenharmony_ci } 43102c593315Sopenharmony_ci 43112c593315Sopenharmony_ci if (util::strieq_l("local3", strfacility)) { 43122c593315Sopenharmony_ci return LOG_LOCAL3; 43132c593315Sopenharmony_ci } 43142c593315Sopenharmony_ci 43152c593315Sopenharmony_ci if (util::strieq_l("local4", strfacility)) { 43162c593315Sopenharmony_ci return LOG_LOCAL4; 43172c593315Sopenharmony_ci } 43182c593315Sopenharmony_ci 43192c593315Sopenharmony_ci if (util::strieq_l("local5", strfacility)) { 43202c593315Sopenharmony_ci return LOG_LOCAL5; 43212c593315Sopenharmony_ci } 43222c593315Sopenharmony_ci 43232c593315Sopenharmony_ci if (util::strieq_l("local6", strfacility)) { 43242c593315Sopenharmony_ci return LOG_LOCAL6; 43252c593315Sopenharmony_ci } 43262c593315Sopenharmony_ci 43272c593315Sopenharmony_ci if (util::strieq_l("local7", strfacility)) { 43282c593315Sopenharmony_ci return LOG_LOCAL7; 43292c593315Sopenharmony_ci } 43302c593315Sopenharmony_ci 43312c593315Sopenharmony_ci if (util::strieq_l("lpr", strfacility)) { 43322c593315Sopenharmony_ci return LOG_LPR; 43332c593315Sopenharmony_ci } 43342c593315Sopenharmony_ci 43352c593315Sopenharmony_ci if (util::strieq_l("mail", strfacility)) { 43362c593315Sopenharmony_ci return LOG_MAIL; 43372c593315Sopenharmony_ci } 43382c593315Sopenharmony_ci 43392c593315Sopenharmony_ci if (util::strieq_l("news", strfacility)) { 43402c593315Sopenharmony_ci return LOG_NEWS; 43412c593315Sopenharmony_ci } 43422c593315Sopenharmony_ci 43432c593315Sopenharmony_ci if (util::strieq_l("syslog", strfacility)) { 43442c593315Sopenharmony_ci return LOG_SYSLOG; 43452c593315Sopenharmony_ci } 43462c593315Sopenharmony_ci 43472c593315Sopenharmony_ci if (util::strieq_l("user", strfacility)) { 43482c593315Sopenharmony_ci return LOG_USER; 43492c593315Sopenharmony_ci } 43502c593315Sopenharmony_ci 43512c593315Sopenharmony_ci if (util::strieq_l("uucp", strfacility)) { 43522c593315Sopenharmony_ci return LOG_UUCP; 43532c593315Sopenharmony_ci } 43542c593315Sopenharmony_ci 43552c593315Sopenharmony_ci return -1; 43562c593315Sopenharmony_ci} 43572c593315Sopenharmony_ci 43582c593315Sopenharmony_ciStringRef strproto(Proto proto) { 43592c593315Sopenharmony_ci switch (proto) { 43602c593315Sopenharmony_ci case Proto::NONE: 43612c593315Sopenharmony_ci return StringRef::from_lit("none"); 43622c593315Sopenharmony_ci case Proto::HTTP1: 43632c593315Sopenharmony_ci return StringRef::from_lit("http/1.1"); 43642c593315Sopenharmony_ci case Proto::HTTP2: 43652c593315Sopenharmony_ci return StringRef::from_lit("h2"); 43662c593315Sopenharmony_ci case Proto::HTTP3: 43672c593315Sopenharmony_ci return StringRef::from_lit("h3"); 43682c593315Sopenharmony_ci case Proto::MEMCACHED: 43692c593315Sopenharmony_ci return StringRef::from_lit("memcached"); 43702c593315Sopenharmony_ci } 43712c593315Sopenharmony_ci 43722c593315Sopenharmony_ci // gcc needs this. 43732c593315Sopenharmony_ci assert(0); 43742c593315Sopenharmony_ci abort(); 43752c593315Sopenharmony_ci} 43762c593315Sopenharmony_ci 43772c593315Sopenharmony_cinamespace { 43782c593315Sopenharmony_ci// Consistent hashing method described in 43792c593315Sopenharmony_ci// https://github.com/RJ/ketama. Generate 160 32-bit hashes per |s|, 43802c593315Sopenharmony_ci// which is usually backend address. The each hash is associated to 43812c593315Sopenharmony_ci// index of backend address. When all hashes for every backend 43822c593315Sopenharmony_ci// address are calculated, sort it in ascending order of hash. To 43832c593315Sopenharmony_ci// choose the index, compute 32-bit hash based on client IP address, 43842c593315Sopenharmony_ci// and do lower bound search in the array. The returned index is the 43852c593315Sopenharmony_ci// backend to use. 43862c593315Sopenharmony_ciint compute_affinity_hash(std::vector<AffinityHash> &res, size_t idx, 43872c593315Sopenharmony_ci const StringRef &s) { 43882c593315Sopenharmony_ci int rv; 43892c593315Sopenharmony_ci std::array<uint8_t, 32> buf; 43902c593315Sopenharmony_ci 43912c593315Sopenharmony_ci for (auto i = 0; i < 20; ++i) { 43922c593315Sopenharmony_ci auto t = s.str(); 43932c593315Sopenharmony_ci t += i; 43942c593315Sopenharmony_ci 43952c593315Sopenharmony_ci rv = util::sha256(buf.data(), StringRef{t}); 43962c593315Sopenharmony_ci if (rv != 0) { 43972c593315Sopenharmony_ci return -1; 43982c593315Sopenharmony_ci } 43992c593315Sopenharmony_ci 44002c593315Sopenharmony_ci for (int i = 0; i < 8; ++i) { 44012c593315Sopenharmony_ci auto h = (static_cast<uint32_t>(buf[4 * i]) << 24) | 44022c593315Sopenharmony_ci (static_cast<uint32_t>(buf[4 * i + 1]) << 16) | 44032c593315Sopenharmony_ci (static_cast<uint32_t>(buf[4 * i + 2]) << 8) | 44042c593315Sopenharmony_ci static_cast<uint32_t>(buf[4 * i + 3]); 44052c593315Sopenharmony_ci 44062c593315Sopenharmony_ci res.emplace_back(idx, h); 44072c593315Sopenharmony_ci } 44082c593315Sopenharmony_ci } 44092c593315Sopenharmony_ci 44102c593315Sopenharmony_ci return 0; 44112c593315Sopenharmony_ci} 44122c593315Sopenharmony_ci} // namespace 44132c593315Sopenharmony_ci 44142c593315Sopenharmony_ci// Configures the following member in |config|: 44152c593315Sopenharmony_ci// conn.downstream_router, conn.downstream.addr_groups, 44162c593315Sopenharmony_ci// conn.downstream.addr_group_catch_all. 44172c593315Sopenharmony_ciint configure_downstream_group(Config *config, bool http2_proxy, 44182c593315Sopenharmony_ci bool numeric_addr_only, 44192c593315Sopenharmony_ci const TLSConfig &tlsconf) { 44202c593315Sopenharmony_ci int rv; 44212c593315Sopenharmony_ci 44222c593315Sopenharmony_ci auto &downstreamconf = *config->conn.downstream; 44232c593315Sopenharmony_ci auto &addr_groups = downstreamconf.addr_groups; 44242c593315Sopenharmony_ci auto &routerconf = downstreamconf.router; 44252c593315Sopenharmony_ci auto &router = routerconf.router; 44262c593315Sopenharmony_ci 44272c593315Sopenharmony_ci if (addr_groups.empty()) { 44282c593315Sopenharmony_ci DownstreamAddrConfig addr{}; 44292c593315Sopenharmony_ci addr.host = StringRef::from_lit(DEFAULT_DOWNSTREAM_HOST); 44302c593315Sopenharmony_ci addr.port = DEFAULT_DOWNSTREAM_PORT; 44312c593315Sopenharmony_ci addr.proto = Proto::HTTP1; 44322c593315Sopenharmony_ci addr.weight = 1; 44332c593315Sopenharmony_ci addr.group_weight = 1; 44342c593315Sopenharmony_ci 44352c593315Sopenharmony_ci DownstreamAddrGroupConfig g(StringRef::from_lit("/")); 44362c593315Sopenharmony_ci g.addrs.push_back(std::move(addr)); 44372c593315Sopenharmony_ci router.add_route(g.pattern, addr_groups.size()); 44382c593315Sopenharmony_ci addr_groups.push_back(std::move(g)); 44392c593315Sopenharmony_ci } 44402c593315Sopenharmony_ci 44412c593315Sopenharmony_ci // backward compatibility: override all SNI fields with the option 44422c593315Sopenharmony_ci // value --backend-tls-sni-field 44432c593315Sopenharmony_ci if (!tlsconf.backend_sni_name.empty()) { 44442c593315Sopenharmony_ci auto &sni = tlsconf.backend_sni_name; 44452c593315Sopenharmony_ci for (auto &addr_group : addr_groups) { 44462c593315Sopenharmony_ci for (auto &addr : addr_group.addrs) { 44472c593315Sopenharmony_ci addr.sni = sni; 44482c593315Sopenharmony_ci } 44492c593315Sopenharmony_ci } 44502c593315Sopenharmony_ci } 44512c593315Sopenharmony_ci 44522c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 44532c593315Sopenharmony_ci LOG(INFO) << "Resolving backend address"; 44542c593315Sopenharmony_ci } 44552c593315Sopenharmony_ci 44562c593315Sopenharmony_ci ssize_t catch_all_group = -1; 44572c593315Sopenharmony_ci for (size_t i = 0; i < addr_groups.size(); ++i) { 44582c593315Sopenharmony_ci auto &g = addr_groups[i]; 44592c593315Sopenharmony_ci if (g.pattern == StringRef::from_lit("/")) { 44602c593315Sopenharmony_ci catch_all_group = i; 44612c593315Sopenharmony_ci } 44622c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 44632c593315Sopenharmony_ci LOG(INFO) << "Host-path pattern: group " << i << ": '" << g.pattern 44642c593315Sopenharmony_ci << "'"; 44652c593315Sopenharmony_ci for (auto &addr : g.addrs) { 44662c593315Sopenharmony_ci LOG(INFO) << "group " << i << " -> " << addr.host.c_str() 44672c593315Sopenharmony_ci << (addr.host_unix ? "" : ":" + util::utos(addr.port)) 44682c593315Sopenharmony_ci << ", proto=" << strproto(addr.proto) 44692c593315Sopenharmony_ci << (addr.tls ? ", tls" : ""); 44702c593315Sopenharmony_ci } 44712c593315Sopenharmony_ci } 44722c593315Sopenharmony_ci#ifdef HAVE_MRUBY 44732c593315Sopenharmony_ci // Try compile mruby script and catch compile error early. 44742c593315Sopenharmony_ci if (!g.mruby_file.empty()) { 44752c593315Sopenharmony_ci if (mruby::create_mruby_context(g.mruby_file) == nullptr) { 44762c593315Sopenharmony_ci LOG(config->ignore_per_pattern_mruby_error ? ERROR : FATAL) 44772c593315Sopenharmony_ci << "backend: Could not compile mruby file for pattern " 44782c593315Sopenharmony_ci << g.pattern; 44792c593315Sopenharmony_ci if (!config->ignore_per_pattern_mruby_error) { 44802c593315Sopenharmony_ci return -1; 44812c593315Sopenharmony_ci } 44822c593315Sopenharmony_ci g.mruby_file = StringRef{}; 44832c593315Sopenharmony_ci } 44842c593315Sopenharmony_ci } 44852c593315Sopenharmony_ci#endif // HAVE_MRUBY 44862c593315Sopenharmony_ci } 44872c593315Sopenharmony_ci 44882c593315Sopenharmony_ci#ifdef HAVE_MRUBY 44892c593315Sopenharmony_ci // Try compile mruby script (--mruby-file) here to catch compile 44902c593315Sopenharmony_ci // error early. 44912c593315Sopenharmony_ci if (!config->mruby_file.empty()) { 44922c593315Sopenharmony_ci if (mruby::create_mruby_context(config->mruby_file) == nullptr) { 44932c593315Sopenharmony_ci LOG(FATAL) << "mruby-file: Could not compile mruby file"; 44942c593315Sopenharmony_ci return -1; 44952c593315Sopenharmony_ci } 44962c593315Sopenharmony_ci } 44972c593315Sopenharmony_ci#endif // HAVE_MRUBY 44982c593315Sopenharmony_ci 44992c593315Sopenharmony_ci if (catch_all_group == -1) { 45002c593315Sopenharmony_ci LOG(FATAL) << "backend: No catch-all backend address is configured"; 45012c593315Sopenharmony_ci return -1; 45022c593315Sopenharmony_ci } 45032c593315Sopenharmony_ci 45042c593315Sopenharmony_ci downstreamconf.addr_group_catch_all = catch_all_group; 45052c593315Sopenharmony_ci 45062c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 45072c593315Sopenharmony_ci LOG(INFO) << "Catch-all pattern is group " << catch_all_group; 45082c593315Sopenharmony_ci } 45092c593315Sopenharmony_ci 45102c593315Sopenharmony_ci auto resolve_flags = numeric_addr_only ? AI_NUMERICHOST | AI_NUMERICSERV : 0; 45112c593315Sopenharmony_ci 45122c593315Sopenharmony_ci std::array<char, util::max_hostport> hostport_buf; 45132c593315Sopenharmony_ci 45142c593315Sopenharmony_ci for (auto &g : addr_groups) { 45152c593315Sopenharmony_ci std::unordered_map<StringRef, uint32_t> wgchk; 45162c593315Sopenharmony_ci for (auto &addr : g.addrs) { 45172c593315Sopenharmony_ci if (addr.group_weight) { 45182c593315Sopenharmony_ci auto it = wgchk.find(addr.group); 45192c593315Sopenharmony_ci if (it == std::end(wgchk)) { 45202c593315Sopenharmony_ci wgchk.emplace(addr.group, addr.group_weight); 45212c593315Sopenharmony_ci } else if ((*it).second != addr.group_weight) { 45222c593315Sopenharmony_ci LOG(FATAL) << "backend: inconsistent group-weight for a single group"; 45232c593315Sopenharmony_ci return -1; 45242c593315Sopenharmony_ci } 45252c593315Sopenharmony_ci } 45262c593315Sopenharmony_ci 45272c593315Sopenharmony_ci if (addr.host_unix) { 45282c593315Sopenharmony_ci // for AF_UNIX socket, we use "localhost" as host for backend 45292c593315Sopenharmony_ci // hostport. This is used as Host header field to backend and 45302c593315Sopenharmony_ci // not going to be passed to any syscalls. 45312c593315Sopenharmony_ci addr.hostport = StringRef::from_lit("localhost"); 45322c593315Sopenharmony_ci 45332c593315Sopenharmony_ci auto path = addr.host.c_str(); 45342c593315Sopenharmony_ci auto pathlen = addr.host.size(); 45352c593315Sopenharmony_ci 45362c593315Sopenharmony_ci if (pathlen + 1 > sizeof(addr.addr.su.un.sun_path)) { 45372c593315Sopenharmony_ci LOG(FATAL) << "UNIX domain socket path " << path << " is too long > " 45382c593315Sopenharmony_ci << sizeof(addr.addr.su.un.sun_path); 45392c593315Sopenharmony_ci return -1; 45402c593315Sopenharmony_ci } 45412c593315Sopenharmony_ci 45422c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 45432c593315Sopenharmony_ci LOG(INFO) << "Use UNIX domain socket path " << path 45442c593315Sopenharmony_ci << " for backend connection"; 45452c593315Sopenharmony_ci } 45462c593315Sopenharmony_ci 45472c593315Sopenharmony_ci addr.addr.su.un.sun_family = AF_UNIX; 45482c593315Sopenharmony_ci // copy path including terminal NULL 45492c593315Sopenharmony_ci std::copy_n(path, pathlen + 1, addr.addr.su.un.sun_path); 45502c593315Sopenharmony_ci addr.addr.len = sizeof(addr.addr.su.un); 45512c593315Sopenharmony_ci 45522c593315Sopenharmony_ci continue; 45532c593315Sopenharmony_ci } 45542c593315Sopenharmony_ci 45552c593315Sopenharmony_ci addr.hostport = 45562c593315Sopenharmony_ci util::make_http_hostport(downstreamconf.balloc, addr.host, addr.port); 45572c593315Sopenharmony_ci 45582c593315Sopenharmony_ci auto hostport = 45592c593315Sopenharmony_ci util::make_hostport(std::begin(hostport_buf), addr.host, addr.port); 45602c593315Sopenharmony_ci 45612c593315Sopenharmony_ci if (!addr.dns) { 45622c593315Sopenharmony_ci if (resolve_hostname(&addr.addr, addr.host.c_str(), addr.port, 45632c593315Sopenharmony_ci downstreamconf.family, resolve_flags) == -1) { 45642c593315Sopenharmony_ci LOG(FATAL) << "Resolving backend address failed: " << hostport; 45652c593315Sopenharmony_ci return -1; 45662c593315Sopenharmony_ci } 45672c593315Sopenharmony_ci 45682c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 45692c593315Sopenharmony_ci LOG(INFO) << "Resolved backend address: " << hostport << " -> " 45702c593315Sopenharmony_ci << util::to_numeric_addr(&addr.addr); 45712c593315Sopenharmony_ci } 45722c593315Sopenharmony_ci } else { 45732c593315Sopenharmony_ci LOG(INFO) << "Resolving backend address " << hostport 45742c593315Sopenharmony_ci << " takes place dynamically"; 45752c593315Sopenharmony_ci } 45762c593315Sopenharmony_ci } 45772c593315Sopenharmony_ci 45782c593315Sopenharmony_ci for (auto &addr : g.addrs) { 45792c593315Sopenharmony_ci if (addr.group_weight == 0) { 45802c593315Sopenharmony_ci auto it = wgchk.find(addr.group); 45812c593315Sopenharmony_ci if (it == std::end(wgchk)) { 45822c593315Sopenharmony_ci addr.group_weight = 1; 45832c593315Sopenharmony_ci } else { 45842c593315Sopenharmony_ci addr.group_weight = (*it).second; 45852c593315Sopenharmony_ci } 45862c593315Sopenharmony_ci } 45872c593315Sopenharmony_ci } 45882c593315Sopenharmony_ci 45892c593315Sopenharmony_ci if (g.affinity.type != SessionAffinity::NONE) { 45902c593315Sopenharmony_ci size_t idx = 0; 45912c593315Sopenharmony_ci for (auto &addr : g.addrs) { 45922c593315Sopenharmony_ci StringRef key; 45932c593315Sopenharmony_ci if (addr.dns) { 45942c593315Sopenharmony_ci if (addr.host_unix) { 45952c593315Sopenharmony_ci key = addr.host; 45962c593315Sopenharmony_ci } else { 45972c593315Sopenharmony_ci key = addr.hostport; 45982c593315Sopenharmony_ci } 45992c593315Sopenharmony_ci } else { 46002c593315Sopenharmony_ci auto p = reinterpret_cast<uint8_t *>(&addr.addr.su); 46012c593315Sopenharmony_ci key = StringRef{p, addr.addr.len}; 46022c593315Sopenharmony_ci } 46032c593315Sopenharmony_ci rv = compute_affinity_hash(g.affinity_hash, idx, key); 46042c593315Sopenharmony_ci if (rv != 0) { 46052c593315Sopenharmony_ci return -1; 46062c593315Sopenharmony_ci } 46072c593315Sopenharmony_ci 46082c593315Sopenharmony_ci if (g.affinity.cookie.stickiness == 46092c593315Sopenharmony_ci SessionAffinityCookieStickiness::STRICT) { 46102c593315Sopenharmony_ci addr.affinity_hash = util::hash32(key); 46112c593315Sopenharmony_ci g.affinity_hash_map.emplace(addr.affinity_hash, idx); 46122c593315Sopenharmony_ci } 46132c593315Sopenharmony_ci 46142c593315Sopenharmony_ci ++idx; 46152c593315Sopenharmony_ci } 46162c593315Sopenharmony_ci 46172c593315Sopenharmony_ci std::sort(std::begin(g.affinity_hash), std::end(g.affinity_hash), 46182c593315Sopenharmony_ci [](const AffinityHash &lhs, const AffinityHash &rhs) { 46192c593315Sopenharmony_ci return lhs.hash < rhs.hash; 46202c593315Sopenharmony_ci }); 46212c593315Sopenharmony_ci } 46222c593315Sopenharmony_ci 46232c593315Sopenharmony_ci auto &timeout = g.timeout; 46242c593315Sopenharmony_ci if (timeout.read < 1e-9) { 46252c593315Sopenharmony_ci timeout.read = downstreamconf.timeout.read; 46262c593315Sopenharmony_ci } 46272c593315Sopenharmony_ci if (timeout.write < 1e-9) { 46282c593315Sopenharmony_ci timeout.write = downstreamconf.timeout.write; 46292c593315Sopenharmony_ci } 46302c593315Sopenharmony_ci } 46312c593315Sopenharmony_ci 46322c593315Sopenharmony_ci return 0; 46332c593315Sopenharmony_ci} 46342c593315Sopenharmony_ci 46352c593315Sopenharmony_ciint resolve_hostname(Address *addr, const char *hostname, uint16_t port, 46362c593315Sopenharmony_ci int family, int additional_flags) { 46372c593315Sopenharmony_ci int rv; 46382c593315Sopenharmony_ci 46392c593315Sopenharmony_ci auto service = util::utos(port); 46402c593315Sopenharmony_ci 46412c593315Sopenharmony_ci addrinfo hints{}; 46422c593315Sopenharmony_ci hints.ai_family = family; 46432c593315Sopenharmony_ci hints.ai_socktype = SOCK_STREAM; 46442c593315Sopenharmony_ci hints.ai_flags |= additional_flags; 46452c593315Sopenharmony_ci#ifdef AI_ADDRCONFIG 46462c593315Sopenharmony_ci hints.ai_flags |= AI_ADDRCONFIG; 46472c593315Sopenharmony_ci#endif // AI_ADDRCONFIG 46482c593315Sopenharmony_ci addrinfo *res; 46492c593315Sopenharmony_ci 46502c593315Sopenharmony_ci rv = getaddrinfo(hostname, service.c_str(), &hints, &res); 46512c593315Sopenharmony_ci#ifdef AI_ADDRCONFIG 46522c593315Sopenharmony_ci if (rv != 0) { 46532c593315Sopenharmony_ci // Retry without AI_ADDRCONFIG 46542c593315Sopenharmony_ci hints.ai_flags &= ~AI_ADDRCONFIG; 46552c593315Sopenharmony_ci rv = getaddrinfo(hostname, service.c_str(), &hints, &res); 46562c593315Sopenharmony_ci } 46572c593315Sopenharmony_ci#endif // AI_ADDRCONFIG 46582c593315Sopenharmony_ci if (rv != 0) { 46592c593315Sopenharmony_ci LOG(FATAL) << "Unable to resolve address for " << hostname << ": " 46602c593315Sopenharmony_ci << gai_strerror(rv); 46612c593315Sopenharmony_ci return -1; 46622c593315Sopenharmony_ci } 46632c593315Sopenharmony_ci 46642c593315Sopenharmony_ci auto res_d = defer(freeaddrinfo, res); 46652c593315Sopenharmony_ci 46662c593315Sopenharmony_ci char host[NI_MAXHOST]; 46672c593315Sopenharmony_ci rv = getnameinfo(res->ai_addr, res->ai_addrlen, host, sizeof(host), nullptr, 46682c593315Sopenharmony_ci 0, NI_NUMERICHOST); 46692c593315Sopenharmony_ci if (rv != 0) { 46702c593315Sopenharmony_ci LOG(FATAL) << "Address resolution for " << hostname 46712c593315Sopenharmony_ci << " failed: " << gai_strerror(rv); 46722c593315Sopenharmony_ci 46732c593315Sopenharmony_ci return -1; 46742c593315Sopenharmony_ci } 46752c593315Sopenharmony_ci 46762c593315Sopenharmony_ci if (LOG_ENABLED(INFO)) { 46772c593315Sopenharmony_ci LOG(INFO) << "Address resolution for " << hostname 46782c593315Sopenharmony_ci << " succeeded: " << host; 46792c593315Sopenharmony_ci } 46802c593315Sopenharmony_ci 46812c593315Sopenharmony_ci memcpy(&addr->su, res->ai_addr, res->ai_addrlen); 46822c593315Sopenharmony_ci addr->len = res->ai_addrlen; 46832c593315Sopenharmony_ci 46842c593315Sopenharmony_ci return 0; 46852c593315Sopenharmony_ci} 46862c593315Sopenharmony_ci 46872c593315Sopenharmony_ci} // namespace shrpx 4688