From: Remi Gacogne Date: Thu, 21 Oct 2021 08:22:12 +0000 (+0200) Subject: dnsdist: Properly format dnsdist-lua.cc once and for all (hopefully) X-Git-Tag: rec-4.6.0-beta1~39^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=69108ebb23e072b1cbd158208a2d12b7adf30fde;p=thirdparty%2Fpdns.git dnsdist: Properly format dnsdist-lua.cc once and for all (hopefully) --- diff --git a/.not-formatted b/.not-formatted index 8c3a8a86ff..af4cb444b8 100644 --- a/.not-formatted +++ b/.not-formatted @@ -68,7 +68,6 @@ ./pdns/dnsdist-lua-inspection.cc ./pdns/dnsdist-lua-rules.cc ./pdns/dnsdist-lua-vars.cc -./pdns/dnsdist-lua.cc ./pdns/dnsdist-lua.hh ./pdns/dnsdist-protobuf.cc ./pdns/dnsdist-protobuf.hh diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index 7e4b0079ca..3ce9c065e9 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -77,14 +77,14 @@ static bool g_included{false}; has done so before on this invocation, this call won't be part of delta() output */ void setLuaNoSideEffect() { - if(g_noLuaSideEffect==false) // there has been a side effect already + if (g_noLuaSideEffect == false) // there has been a side effect already return; - g_noLuaSideEffect=true; + g_noLuaSideEffect = true; } void setLuaSideEffect() { - g_noLuaSideEffect=false; + g_noLuaSideEffect = false; } bool getLuaNoSideEffect() @@ -100,7 +100,7 @@ void resetLuaSideEffect() g_noLuaSideEffect = boost::logic::indeterminate; } -typedef std::unordered_map >, std::vector >, std::map > > localbind_t; +typedef std::unordered_map>, std::vector>, std::map>> localbind_t; static void parseLocalBindVars(boost::optional vars, bool& reusePort, int& tcpFastOpenQueueSize, std::string& interface, std::set& cpus, int& tcpListenQueueSize, size_t& maxInFlightQueriesPerConnection, size_t& tcpMaxConcurrentConnections) { @@ -124,7 +124,7 @@ static void parseLocalBindVars(boost::optional vars, bool& reusePor interface = boost::get((*vars)["interface"]); } if (vars->count("cpus")) { - for (const auto& cpu : boost::get>>((*vars)["cpus"])) { + for (const auto& cpu : boost::get>>((*vars)["cpus"])) { cpus.insert(cpu.second); } } @@ -132,7 +132,7 @@ static void parseLocalBindVars(boost::optional vars, bool& reusePor } #if defined(HAVE_DNS_OVER_TLS) || defined(HAVE_DNS_OVER_HTTPS) -static bool loadTLSCertificateAndKeys(const std::string& context, std::vector>& pairs, boost::variant>> certFiles, boost::variant>> keyFiles) +static bool loadTLSCertificateAndKeys(const std::string& context, std::vector>& pairs, boost::variant>> certFiles, boost::variant>> keyFiles) { if (certFiles.type() == typeid(std::string) && keyFiles.type() == typeid(std::string)) { auto certFile = boost::get(certFiles); @@ -140,10 +140,9 @@ static bool loadTLSCertificateAndKeys(const std::string& context, std::vector>) && keyFiles.type() == typeid(std::vector>)) - { - auto certFilesVect = boost::get>>(certFiles); - auto keyFilesVect = boost::get>>(keyFiles); + else if (certFiles.type() == typeid(std::vector>) && keyFiles.type() == typeid(std::vector>)) { + auto certFilesVect = boost::get>>(certFiles); + auto keyFilesVect = boost::get>>(keyFiles); if (certFilesVect.size() == keyFilesVect.size()) { pairs.clear(); for (size_t idx = 0; idx < certFilesVect.size(); idx++) { @@ -152,13 +151,13 @@ static bool loadTLSCertificateAndKeys(const std::string& context, std::vector((*vars)["numberOfStoredSessions"]); if (value < 0) { errlog("Invalid value '%d' for %s() parameter 'numberOfStoredSessions', should be >= 0, dismissing", value, context); - g_outputBuffer="Invalid value '" + std::to_string(value) + "' for " + context + "() parameter 'numberOfStoredSessions', should be >= 0, dismissing"; + g_outputBuffer = "Invalid value '" + std::to_string(value) + "' for " + context + "() parameter 'numberOfStoredSessions', should be >= 0, dismissing"; } config.d_maxStoredSessions = value; } @@ -243,426 +242,421 @@ static void parseTLSConfig(TLSConfig& config, const std::string& context, boost: static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) { - typedef std::unordered_map >, DownstreamState::checkfunc_t > > newserver_t; + typedef std::unordered_map>, DownstreamState::checkfunc_t>> newserver_t; luaCtx.writeFunction("inClientStartup", [client]() { - return client && !g_configurationDone; + return client && !g_configurationDone; }); luaCtx.writeFunction("inConfigCheck", [configCheck]() { - return !configCheck; + return !configCheck; }); luaCtx.writeFunction("newServer", - [client, configCheck](boost::variant pvars, boost::optional qps) { - setLuaSideEffect(); - - std::shared_ptr ret = std::make_shared(ComboAddress(), ComboAddress(), 0, std::string(), 1, !(client || configCheck)); - newserver_t vars; - - ComboAddress serverAddr; - std::string serverAddressStr; - if(auto addrStr = boost::get(&pvars)) { - serverAddressStr = *addrStr; - if(qps) { - vars["qps"] = std::to_string(*qps); - } - } else { - vars = boost::get(pvars); - serverAddressStr = boost::get(vars["address"]); - } - - try { - serverAddr = ComboAddress(serverAddressStr, 53); - } - catch(const PDNSException& e) { - g_outputBuffer="Error creating new server: "+string(e.reason); - errlog("Error creating new server with address %s: %s", serverAddressStr, e.reason); - return ret; - } - catch(std::exception& e) { - g_outputBuffer="Error creating new server: "+string(e.what()); - errlog("Error creating new server with address %s: %s", serverAddressStr, e.what()); - return ret; - } - - if(IsAnyAddress(serverAddr)) { - g_outputBuffer="Error creating new server: invalid address for a downstream server."; - errlog("Error creating new server: %s is not a valid address for a downstream server", serverAddressStr); - return ret; - } - - ComboAddress sourceAddr; - std::string sourceItfName; - unsigned int sourceItf = 0; - size_t numberOfSockets = 1; - std::set cpus; - - if(vars.count("source")) { - /* handle source in the following forms: + [client, configCheck](boost::variant pvars, boost::optional qps) { + setLuaSideEffect(); + + std::shared_ptr ret = std::make_shared(ComboAddress(), ComboAddress(), 0, std::string(), 1, !(client || configCheck)); + newserver_t vars; + + ComboAddress serverAddr; + std::string serverAddressStr; + if (auto addrStr = boost::get(&pvars)) { + serverAddressStr = *addrStr; + if (qps) { + vars["qps"] = std::to_string(*qps); + } + } + else { + vars = boost::get(pvars); + serverAddressStr = boost::get(vars["address"]); + } + + try { + serverAddr = ComboAddress(serverAddressStr, 53); + } + catch (const PDNSException& e) { + g_outputBuffer = "Error creating new server: " + string(e.reason); + errlog("Error creating new server with address %s: %s", serverAddressStr, e.reason); + return ret; + } + catch (std::exception& e) { + g_outputBuffer = "Error creating new server: " + string(e.what()); + errlog("Error creating new server with address %s: %s", serverAddressStr, e.what()); + return ret; + } + + if (IsAnyAddress(serverAddr)) { + g_outputBuffer = "Error creating new server: invalid address for a downstream server."; + errlog("Error creating new server: %s is not a valid address for a downstream server", serverAddressStr); + return ret; + } + + ComboAddress sourceAddr; + std::string sourceItfName; + unsigned int sourceItf = 0; + size_t numberOfSockets = 1; + std::set cpus; + + if (vars.count("source")) { + /* handle source in the following forms: - v4 address ("192.0.2.1") - v6 address ("2001:DB8::1") - interface name ("eth0") - v4 address and interface name ("192.0.2.1@eth0") - v6 address and interface name ("2001:DB8::1@eth0") */ - const string source = boost::get(vars["source"]); - bool parsed = false; - std::string::size_type pos = source.find("@"); - if (pos == std::string::npos) { - /* no '@', try to parse that as a valid v4/v6 address */ - try { - sourceAddr = ComboAddress(source); - parsed = true; - } - catch(...) - { - } - } + const string source = boost::get(vars["source"]); + bool parsed = false; + std::string::size_type pos = source.find("@"); + if (pos == std::string::npos) { + /* no '@', try to parse that as a valid v4/v6 address */ + try { + sourceAddr = ComboAddress(source); + parsed = true; + } + catch (...) { + } + } + + if (parsed == false) { + /* try to parse as interface name, or v4/v6@itf */ + sourceItfName = source.substr(pos == std::string::npos ? 0 : pos + 1); + unsigned int itfIdx = if_nametoindex(sourceItfName.c_str()); - if (parsed == false) - { - /* try to parse as interface name, or v4/v6@itf */ - sourceItfName = source.substr(pos == std::string::npos ? 0 : pos + 1); - unsigned int itfIdx = if_nametoindex(sourceItfName.c_str()); - - if (itfIdx != 0) { - if (pos == 0 || pos == std::string::npos) { - /* "eth0" or "@eth0" */ - sourceItf = itfIdx; - } - else { - /* "192.0.2.1@eth0" */ - sourceAddr = ComboAddress(source.substr(0, pos)); - sourceItf = itfIdx; - } + if (itfIdx != 0) { + if (pos == 0 || pos == std::string::npos) { + /* "eth0" or "@eth0" */ + sourceItf = itfIdx; + } + else { + /* "192.0.2.1@eth0" */ + sourceAddr = ComboAddress(source.substr(0, pos)); + sourceItf = itfIdx; + } #ifdef SO_BINDTODEVICE - /* we need to retain CAP_NET_RAW to be able to set SO_BINDTODEVICE in the health checks */ - g_capabilitiesToRetain.insert("CAP_NET_RAW"); + /* we need to retain CAP_NET_RAW to be able to set SO_BINDTODEVICE in the health checks */ + g_capabilitiesToRetain.insert("CAP_NET_RAW"); #endif - } - else - { - warnlog("Dismissing source %s because '%s' is not a valid interface name", source, sourceItfName); - } - } - } - - if (vars.count("sockets")) { - numberOfSockets = std::stoul(boost::get(vars["sockets"])); - if (numberOfSockets == 0) { - warnlog("Dismissing invalid number of sockets '%s', using 1 instead", boost::get(vars["sockets"])); - numberOfSockets = 1; - } - } - - // create but don't connect the socket in client or check-config modes - ret=std::make_shared(serverAddr, sourceAddr, sourceItf, sourceItfName, numberOfSockets, !(client || configCheck)); - if (!(client || configCheck)) { - infolog("Added downstream server %s", serverAddr.toStringWithPort()); - } - - if(vars.count("qps")) { - int qpsVal=std::stoi(boost::get(vars["qps"])); - ret->qps=QPSLimiter(qpsVal, qpsVal); - } - - if(vars.count("order")) { - ret->order=std::stoi(boost::get(vars["order"])); - } - - if(vars.count("weight")) { - try { - int weightVal=std::stoi(boost::get(vars["weight"])); + } + else { + warnlog("Dismissing source %s because '%s' is not a valid interface name", source, sourceItfName); + } + } + } - if(weightVal < 1) { - errlog("Error creating new server: downstream weight value must be greater than 0."); - return ret; - } + if (vars.count("sockets")) { + numberOfSockets = std::stoul(boost::get(vars["sockets"])); + if (numberOfSockets == 0) { + warnlog("Dismissing invalid number of sockets '%s', using 1 instead", boost::get(vars["sockets"])); + numberOfSockets = 1; + } + } + + // create but don't connect the socket in client or check-config modes + ret = std::make_shared(serverAddr, sourceAddr, sourceItf, sourceItfName, numberOfSockets, !(client || configCheck)); + if (!(client || configCheck)) { + infolog("Added downstream server %s", serverAddr.toStringWithPort()); + } + + if (vars.count("qps")) { + int qpsVal = std::stoi(boost::get(vars["qps"])); + ret->qps = QPSLimiter(qpsVal, qpsVal); + } + + if (vars.count("order")) { + ret->order = std::stoi(boost::get(vars["order"])); + } + + if (vars.count("weight")) { + try { + int weightVal = std::stoi(boost::get(vars["weight"])); + + if (weightVal < 1) { + errlog("Error creating new server: downstream weight value must be greater than 0."); + return ret; + } - ret->setWeight(weightVal); - } - catch(std::exception& e) { - // std::stoi will throw an exception if the string isn't in a value int range - errlog("Error creating new server: downstream weight value must be between %s and %s", 1, std::numeric_limits::max()); - return ret; - } - } + ret->setWeight(weightVal); + } + catch (std::exception& e) { + // std::stoi will throw an exception if the string isn't in a value int range + errlog("Error creating new server: downstream weight value must be between %s and %s", 1, std::numeric_limits::max()); + return ret; + } + } - if(vars.count("retries")) { - ret->d_retries = std::stoi(boost::get(vars["retries"])); - } + if (vars.count("retries")) { + ret->d_retries = std::stoi(boost::get(vars["retries"])); + } - if(vars.count("checkInterval")) { - ret->checkInterval=static_cast(std::stoul(boost::get(vars["checkInterval"]))); - } + if (vars.count("checkInterval")) { + ret->checkInterval = static_cast(std::stoul(boost::get(vars["checkInterval"]))); + } - if(vars.count("tcpConnectTimeout")) { - ret->tcpConnectTimeout=std::stoi(boost::get(vars["tcpConnectTimeout"])); - } + if (vars.count("tcpConnectTimeout")) { + ret->tcpConnectTimeout = std::stoi(boost::get(vars["tcpConnectTimeout"])); + } - if(vars.count("tcpSendTimeout")) { - ret->tcpSendTimeout=std::stoi(boost::get(vars["tcpSendTimeout"])); - } + if (vars.count("tcpSendTimeout")) { + ret->tcpSendTimeout = std::stoi(boost::get(vars["tcpSendTimeout"])); + } - if(vars.count("tcpRecvTimeout")) { - ret->tcpRecvTimeout=std::stoi(boost::get(vars["tcpRecvTimeout"])); - } + if (vars.count("tcpRecvTimeout")) { + ret->tcpRecvTimeout = std::stoi(boost::get(vars["tcpRecvTimeout"])); + } - if(vars.count("tcpFastOpen")) { - bool fastOpen = boost::get(vars["tcpFastOpen"]); - if (fastOpen) { + if (vars.count("tcpFastOpen")) { + bool fastOpen = boost::get(vars["tcpFastOpen"]); + if (fastOpen) { #ifdef MSG_FASTOPEN - ret->tcpFastOpen=true; + ret->tcpFastOpen = true; #else warnlog("TCP Fast Open has been configured on downstream server %s but is not supported", boost::get(vars["address"])); #endif - } - } + } + } - if(vars.count("maxInFlight")) { - ret->d_maxInFlightQueriesPerConn = std::stoi(boost::get(vars["maxInFlight"])); - } + if (vars.count("maxInFlight")) { + ret->d_maxInFlightQueriesPerConn = std::stoi(boost::get(vars["maxInFlight"])); + } - if(vars.count("name")) { - ret->setName(boost::get(vars["name"])); - } + if (vars.count("name")) { + ret->setName(boost::get(vars["name"])); + } - if (vars.count("id")) { - ret->setId(boost::lexical_cast(boost::get(vars["id"]))); - } + if (vars.count("id")) { + ret->setId(boost::lexical_cast(boost::get(vars["id"]))); + } - if(vars.count("checkName")) { - ret->checkName=DNSName(boost::get(vars["checkName"])); - } + if (vars.count("checkName")) { + ret->checkName = DNSName(boost::get(vars["checkName"])); + } - if(vars.count("checkType")) { - ret->checkType=boost::get(vars["checkType"]); - } - - if(vars.count("checkClass")) { - ret->checkClass=std::stoi(boost::get(vars["checkClass"])); - } + if (vars.count("checkType")) { + ret->checkType = boost::get(vars["checkType"]); + } - if(vars.count("checkFunction")) { - ret->checkFunction = boost::get(vars["checkFunction"]); - } - - if(vars.count("checkTimeout")) { - ret->checkTimeout = std::stoi(boost::get(vars["checkTimeout"])); - } + if (vars.count("checkClass")) { + ret->checkClass = std::stoi(boost::get(vars["checkClass"])); + } - if (vars.count("checkTCP")) { - ret->d_tcpCheck = boost::get(vars.at("checkTCP")); - } + if (vars.count("checkFunction")) { + ret->checkFunction = boost::get(vars["checkFunction"]); + } - if(vars.count("setCD")) { - ret->setCD=boost::get(vars["setCD"]); - } + if (vars.count("checkTimeout")) { + ret->checkTimeout = std::stoi(boost::get(vars["checkTimeout"])); + } - if(vars.count("mustResolve")) { - ret->mustResolve=boost::get(vars["mustResolve"]); - } + if (vars.count("checkTCP")) { + ret->d_tcpCheck = boost::get(vars.at("checkTCP")); + } - if(vars.count("useClientSubnet")) { - ret->useECS=boost::get(vars["useClientSubnet"]); - } + if (vars.count("setCD")) { + ret->setCD = boost::get(vars["setCD"]); + } - if(vars.count("useProxyProtocol")) { - ret->useProxyProtocol = boost::get(vars["useProxyProtocol"]); - } + if (vars.count("mustResolve")) { + ret->mustResolve = boost::get(vars["mustResolve"]); + } - if(vars.count("disableZeroScope")) { - ret->disableZeroScope=boost::get(vars["disableZeroScope"]); - } + if (vars.count("useClientSubnet")) { + ret->useECS = boost::get(vars["useClientSubnet"]); + } - if(vars.count("ipBindAddrNoPort")) { - ret->ipBindAddrNoPort=boost::get(vars["ipBindAddrNoPort"]); - } + if (vars.count("useProxyProtocol")) { + ret->useProxyProtocol = boost::get(vars["useProxyProtocol"]); + } - if(vars.count("addXPF")) { - ret->xpfRRCode=std::stoi(boost::get(vars["addXPF"])); - } + if (vars.count("disableZeroScope")) { + ret->disableZeroScope = boost::get(vars["disableZeroScope"]); + } - if(vars.count("maxCheckFailures")) { - ret->maxCheckFailures=std::stoi(boost::get(vars["maxCheckFailures"])); - } + if (vars.count("ipBindAddrNoPort")) { + ret->ipBindAddrNoPort = boost::get(vars["ipBindAddrNoPort"]); + } - if(vars.count("rise")) { - ret->minRiseSuccesses=std::stoi(boost::get(vars["rise"])); - } + if (vars.count("addXPF")) { + ret->xpfRRCode = std::stoi(boost::get(vars["addXPF"])); + } - if(vars.count("reconnectOnUp")) { - ret->reconnectOnUp=boost::get(vars["reconnectOnUp"]); - } + if (vars.count("maxCheckFailures")) { + ret->maxCheckFailures = std::stoi(boost::get(vars["maxCheckFailures"])); + } - if(vars.count("cpus")) { - for (const auto& cpu : boost::get>>(vars["cpus"])) { - cpus.insert(std::stoi(cpu.second)); - } - } + if (vars.count("rise")) { + ret->minRiseSuccesses = std::stoi(boost::get(vars["rise"])); + } - if (vars.count("tcpOnly")) { - ret->d_tcpOnly = boost::get(vars.at("tcpOnly")); - } + if (vars.count("reconnectOnUp")) { + ret->reconnectOnUp = boost::get(vars["reconnectOnUp"]); + } - if (vars.count("tls")) { - TLSContextParameters tlsParams; - std::string ciphers; - std::string ciphers13; + if (vars.count("cpus")) { + for (const auto& cpu : boost::get>>(vars["cpus"])) { + cpus.insert(std::stoi(cpu.second)); + } + } - tlsParams.d_provider = boost::get(vars.at("tls")); + if (vars.count("tcpOnly")) { + ret->d_tcpOnly = boost::get(vars.at("tcpOnly")); + } - if (vars.count("ciphers")) { - tlsParams.d_ciphers = boost::get(vars.at("ciphers")); - } - if (vars.count("ciphers13")) { - tlsParams.d_ciphers13 = boost::get(vars.at("ciphers13")); - } - if (vars.count("caStore")) { - tlsParams.d_caStore = boost::get(vars.at("caStore")); - } - if (vars.count("validateCertificates")) { - tlsParams.d_validateCertificates = boost::get(vars.at("validateCertificates")); - } - if (vars.count("releaseBuffers")) { - tlsParams.d_releaseBuffers = boost::get(vars.at("releaseBuffers")); - } - if (vars.count("enableRenegotiation")) { - tlsParams.d_enableRenegotiation = boost::get(vars.at("enableRenegotiation")); - } + if (vars.count("tls")) { + TLSContextParameters tlsParams; + std::string ciphers; + std::string ciphers13; + tlsParams.d_provider = boost::get(vars.at("tls")); - if (vars.count("subjectName")) { - ret->d_tlsSubjectName = boost::get(vars.at("subjectName")); - } + if (vars.count("ciphers")) { + tlsParams.d_ciphers = boost::get(vars.at("ciphers")); + } + if (vars.count("ciphers13")) { + tlsParams.d_ciphers13 = boost::get(vars.at("ciphers13")); + } + if (vars.count("caStore")) { + tlsParams.d_caStore = boost::get(vars.at("caStore")); + } + if (vars.count("validateCertificates")) { + tlsParams.d_validateCertificates = boost::get(vars.at("validateCertificates")); + } + if (vars.count("releaseBuffers")) { + tlsParams.d_releaseBuffers = boost::get(vars.at("releaseBuffers")); + } + if (vars.count("enableRenegotiation")) { + tlsParams.d_enableRenegotiation = boost::get(vars.at("enableRenegotiation")); + } + if (vars.count("subjectName")) { + ret->d_tlsSubjectName = boost::get(vars.at("subjectName")); + } - ret->d_tlsCtx = getTLSContext(tlsParams); + ret->d_tlsCtx = getTLSContext(tlsParams); - if (vars.count("dohPath")) { + if (vars.count("dohPath")) { #ifdef HAVE_NGHTTP2 - ret->d_dohPath = boost::get(vars.at("dohPath")); - if (ret->d_tlsCtx) { - setupDoHClientProtocolNegotiation(ret->d_tlsCtx); - } + ret->d_dohPath = boost::get(vars.at("dohPath")); + if (ret->d_tlsCtx) { + setupDoHClientProtocolNegotiation(ret->d_tlsCtx); + } - if (g_configurationDone && g_outgoingDoHWorkerThreads && *g_outgoingDoHWorkerThreads == 0) { - throw std::runtime_error("Error: setOutgoingDoHWorkerThreads() is set to 0 so no outgoing DoH worker thread is available to serve queries"); - } + if (g_configurationDone && g_outgoingDoHWorkerThreads && *g_outgoingDoHWorkerThreads == 0) { + throw std::runtime_error("Error: setOutgoingDoHWorkerThreads() is set to 0 so no outgoing DoH worker thread is available to serve queries"); + } - if (!g_outgoingDoHWorkerThreads || *g_outgoingDoHWorkerThreads == 0) { - g_outgoingDoHWorkerThreads = 1; - } + if (!g_outgoingDoHWorkerThreads || *g_outgoingDoHWorkerThreads == 0) { + g_outgoingDoHWorkerThreads = 1; + } - if (vars.count("addXForwardedHeaders")) { - ret->d_addXForwardedHeaders = boost::get(vars.at("addXForwardedHeaders")); - } + if (vars.count("addXForwardedHeaders")) { + ret->d_addXForwardedHeaders = boost::get(vars.at("addXForwardedHeaders")); + } #else /* HAVE_NGHTTP2 */ throw std::runtime_error("Outgoing DNS over HTTPS support requested (via 'dohPath' on newServer()) but nghttp2 support is not available"); #endif /* HAVE_NGHTTP2 */ - } - else { - setupDoTProtocolNegotiation(ret->d_tlsCtx); - } - } - - if (ret->isTCPOnly()) { - /* no need to keep the UDP states, then */ - ret->idStates.clear(); - } - - /* this needs to be done _AFTER_ the order has been set, - since the server are kept ordered inside the pool */ - auto localPools = g_pools.getCopy(); - if(vars.count("pool")) { - if(auto* pool = boost::get(&vars["pool"])) { - ret->pools.insert(*pool); - } - else { - auto pools = boost::get > >(vars["pool"]); - for(auto& p : pools) { - ret->pools.insert(p.second); - } - } - for(const auto& poolName: ret->pools) { - addServerToPool(localPools, poolName, ret); - } - } - else { - addServerToPool(localPools, "", ret); - } - g_pools.setState(localPools); - - if (ret->connected) { - ret->threadStarted.test_and_set(); - - if (g_launchWork) { - g_launchWork->push_back([ret,cpus]() { - ret->tid = thread(responderThread, ret); - if (!cpus.empty()) { - mapThreadToCPUList(ret->tid.native_handle(), cpus); - } - }); - } - else { - ret->tid = thread(responderThread, ret); - if (!cpus.empty()) { - mapThreadToCPUList(ret->tid.native_handle(), cpus); - } - } - } + } + else { + setupDoTProtocolNegotiation(ret->d_tlsCtx); + } + } + + if (ret->isTCPOnly()) { + /* no need to keep the UDP states, then */ + ret->idStates.clear(); + } + + /* this needs to be done _AFTER_ the order has been set, + since the server are kept ordered inside the pool */ + auto localPools = g_pools.getCopy(); + if (vars.count("pool")) { + if (auto* pool = boost::get(&vars["pool"])) { + ret->pools.insert(*pool); + } + else { + auto pools = boost::get>>(vars["pool"]); + for (auto& p : pools) { + ret->pools.insert(p.second); + } + } + for (const auto& poolName : ret->pools) { + addServerToPool(localPools, poolName, ret); + } + } + else { + addServerToPool(localPools, "", ret); + } + g_pools.setState(localPools); + + if (ret->connected) { + ret->threadStarted.test_and_set(); + + if (g_launchWork) { + g_launchWork->push_back([ret, cpus]() { + ret->tid = thread(responderThread, ret); + if (!cpus.empty()) { + mapThreadToCPUList(ret->tid.native_handle(), cpus); + } + }); + } + else { + ret->tid = thread(responderThread, ret); + if (!cpus.empty()) { + mapThreadToCPUList(ret->tid.native_handle(), cpus); + } + } + } - auto states = g_dstates.getCopy(); - states.push_back(ret); - std::stable_sort(states.begin(), states.end(), [](const decltype(ret)& a, const decltype(ret)& b) { - return a->order < b->order; - }); - g_dstates.setState(states); - return ret; - } ); + auto states = g_dstates.getCopy(); + states.push_back(ret); + std::stable_sort(states.begin(), states.end(), [](const decltype(ret)& a, const decltype(ret)& b) { + return a->order < b->order; + }); + g_dstates.setState(states); + return ret; + }); luaCtx.writeFunction("rmServer", - [](boost::variant, int, std::string> var) - { - setLuaSideEffect(); - shared_ptr server = nullptr; - auto states = g_dstates.getCopy(); - if (auto* rem = boost::get>(&var)) { - server = *rem; - } - else if (auto str = boost::get(&var)) { - const auto uuid = getUniqueID(*str); - for (auto& state : states) { - if (state->id == uuid) { - server = state; - } - } - } - else { - int idx = boost::get(var); - server = states.at(idx); - } - if (!server) { - throw std::runtime_error("unable to locate the requested server"); - } - auto localPools = g_pools.getCopy(); - for (const string& poolName : server->pools) { - removeServerFromPool(localPools, poolName, server); - } - /* the server might also be in the default pool */ - removeServerFromPool(localPools, "", server); - g_pools.setState(localPools); - states.erase(remove(states.begin(), states.end(), server), states.end()); - g_dstates.setState(states); - server->stop(); - } ); + [](boost::variant, int, std::string> var) { + setLuaSideEffect(); + shared_ptr server = nullptr; + auto states = g_dstates.getCopy(); + if (auto* rem = boost::get>(&var)) { + server = *rem; + } + else if (auto str = boost::get(&var)) { + const auto uuid = getUniqueID(*str); + for (auto& state : states) { + if (state->id == uuid) { + server = state; + } + } + } + else { + int idx = boost::get(var); + server = states.at(idx); + } + if (!server) { + throw std::runtime_error("unable to locate the requested server"); + } + auto localPools = g_pools.getCopy(); + for (const string& poolName : server->pools) { + removeServerFromPool(localPools, poolName, server); + } + /* the server might also be in the default pool */ + removeServerFromPool(localPools, "", server); + g_pools.setState(localPools); + states.erase(remove(states.begin(), states.end(), server), states.end()); + g_dstates.setState(states); + server->stop(); + }); luaCtx.writeFunction("truncateTC", [](bool tc) { setLuaSideEffect(); g_truncateTC=tc; }); luaCtx.writeFunction("fixupCase", [](bool fu) { setLuaSideEffect(); g_fixupCase=fu; }); luaCtx.writeFunction("addACL", [](const std::string& domain) { - setLuaSideEffect(); - g_ACL.modify([domain](NetmaskGroup& nmg) { nmg.addMask(domain); }); - }); + setLuaSideEffect(); + g_ACL.modify([domain](NetmaskGroup& nmg) { nmg.addMask(domain); }); + }); luaCtx.writeFunction("rmACL", [](const std::string& netmask) { setLuaSideEffect(); @@ -670,146 +664,146 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) }); luaCtx.writeFunction("setLocal", [client](const std::string& addr, boost::optional vars) { - setLuaSideEffect(); - if(client) - return; - if (g_configurationDone) { - g_outputBuffer="setLocal cannot be used at runtime!\n"; - return; - } - bool reusePort = false; - int tcpFastOpenQueueSize = 0; - int tcpListenQueueSize = 0; - size_t maxInFlightQueriesPerConn = 0; - size_t tcpMaxConcurrentConnections = 0; - std::string interface; - std::set cpus; + setLuaSideEffect(); + if (client) + return; + if (g_configurationDone) { + g_outputBuffer = "setLocal cannot be used at runtime!\n"; + return; + } + bool reusePort = false; + int tcpFastOpenQueueSize = 0; + int tcpListenQueueSize = 0; + size_t maxInFlightQueriesPerConn = 0; + size_t tcpMaxConcurrentConnections = 0; + std::string interface; + std::set cpus; - parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus, tcpListenQueueSize, maxInFlightQueriesPerConn, tcpMaxConcurrentConnections); + parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus, tcpListenQueueSize, maxInFlightQueriesPerConn, tcpMaxConcurrentConnections); - try { - ComboAddress loc(addr, 53); - for (auto it = g_frontends.begin(); it != g_frontends.end(); ) { - /* DoH, DoT and DNSCrypt frontends are separate */ - if ((*it)->tlsFrontend == nullptr && (*it)->dnscryptCtx == nullptr && (*it)->dohFrontend == nullptr) { - it = g_frontends.erase(it); - } - else { - ++it; - } - } - - // only works pre-startup, so no sync necessary - g_frontends.push_back(std::make_unique(loc, false, reusePort, tcpFastOpenQueueSize, interface, cpus)); - auto tcpCS = std::make_unique(loc, true, reusePort, tcpFastOpenQueueSize, interface, cpus); - if (tcpListenQueueSize > 0) { - tcpCS->tcpListenQueueSize = tcpListenQueueSize; - } - if (maxInFlightQueriesPerConn > 0) { - tcpCS->d_maxInFlightQueriesPerConn = maxInFlightQueriesPerConn; + try { + ComboAddress loc(addr, 53); + for (auto it = g_frontends.begin(); it != g_frontends.end();) { + /* DoH, DoT and DNSCrypt frontends are separate */ + if ((*it)->tlsFrontend == nullptr && (*it)->dnscryptCtx == nullptr && (*it)->dohFrontend == nullptr) { + it = g_frontends.erase(it); } - if (tcpMaxConcurrentConnections > 0) { - tcpCS->d_tcpConcurrentConnectionsLimit = tcpMaxConcurrentConnections; + else { + ++it; } + } - g_frontends.push_back(std::move(tcpCS)); + // only works pre-startup, so no sync necessary + g_frontends.push_back(std::make_unique(loc, false, reusePort, tcpFastOpenQueueSize, interface, cpus)); + auto tcpCS = std::make_unique(loc, true, reusePort, tcpFastOpenQueueSize, interface, cpus); + if (tcpListenQueueSize > 0) { + tcpCS->tcpListenQueueSize = tcpListenQueueSize; } - catch(const std::exception& e) { - g_outputBuffer="Error: "+string(e.what())+"\n"; + if (maxInFlightQueriesPerConn > 0) { + tcpCS->d_maxInFlightQueriesPerConn = maxInFlightQueriesPerConn; } - }); + if (tcpMaxConcurrentConnections > 0) { + tcpCS->d_tcpConcurrentConnectionsLimit = tcpMaxConcurrentConnections; + } + + g_frontends.push_back(std::move(tcpCS)); + } + catch (const std::exception& e) { + g_outputBuffer = "Error: " + string(e.what()) + "\n"; + } + }); luaCtx.writeFunction("addLocal", [client](const std::string& addr, boost::optional vars) { - setLuaSideEffect(); - if(client) - return; - if (g_configurationDone) { - g_outputBuffer="addLocal cannot be used at runtime!\n"; - return; - } - bool reusePort = false; - int tcpFastOpenQueueSize = 0; - int tcpListenQueueSize = 0; - size_t maxInFlightQueriesPerConn = 0; - size_t tcpMaxConcurrentConnections = 0; - std::string interface; - std::set cpus; + setLuaSideEffect(); + if (client) + return; + if (g_configurationDone) { + g_outputBuffer = "addLocal cannot be used at runtime!\n"; + return; + } + bool reusePort = false; + int tcpFastOpenQueueSize = 0; + int tcpListenQueueSize = 0; + size_t maxInFlightQueriesPerConn = 0; + size_t tcpMaxConcurrentConnections = 0; + std::string interface; + std::set cpus; - parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus, tcpListenQueueSize, maxInFlightQueriesPerConn, tcpMaxConcurrentConnections); + parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus, tcpListenQueueSize, maxInFlightQueriesPerConn, tcpMaxConcurrentConnections); - try { - ComboAddress loc(addr, 53); - // only works pre-startup, so no sync necessary - g_frontends.push_back(std::make_unique(loc, false, reusePort, tcpFastOpenQueueSize, interface, cpus)); - auto tcpCS = std::make_unique(loc, true, reusePort, tcpFastOpenQueueSize, interface, cpus); - if (tcpListenQueueSize > 0) { - tcpCS->tcpListenQueueSize = tcpListenQueueSize; - } - if (maxInFlightQueriesPerConn > 0) { - tcpCS->d_maxInFlightQueriesPerConn = maxInFlightQueriesPerConn; - } - if (tcpMaxConcurrentConnections > 0) { - tcpCS->d_tcpConcurrentConnectionsLimit = tcpMaxConcurrentConnections; - } - g_frontends.push_back(std::move(tcpCS)); + try { + ComboAddress loc(addr, 53); + // only works pre-startup, so no sync necessary + g_frontends.push_back(std::make_unique(loc, false, reusePort, tcpFastOpenQueueSize, interface, cpus)); + auto tcpCS = std::make_unique(loc, true, reusePort, tcpFastOpenQueueSize, interface, cpus); + if (tcpListenQueueSize > 0) { + tcpCS->tcpListenQueueSize = tcpListenQueueSize; } - catch(std::exception& e) { - g_outputBuffer="Error: "+string(e.what())+"\n"; - errlog("Error while trying to listen on %s: %s\n", addr, string(e.what())); + if (maxInFlightQueriesPerConn > 0) { + tcpCS->d_maxInFlightQueriesPerConn = maxInFlightQueriesPerConn; } - }); - - luaCtx.writeFunction("setACL", [](boost::variant>> inp) { - setLuaSideEffect(); - NetmaskGroup nmg; - if(auto str = boost::get(&inp)) { - nmg.addMask(*str); + if (tcpMaxConcurrentConnections > 0) { + tcpCS->d_tcpConcurrentConnectionsLimit = tcpMaxConcurrentConnections; } - else for(const auto& p : boost::get>>(inp)) { - nmg.addMask(p.second); + g_frontends.push_back(std::move(tcpCS)); + } + catch (std::exception& e) { + g_outputBuffer = "Error: " + string(e.what()) + "\n"; + errlog("Error while trying to listen on %s: %s\n", addr, string(e.what())); + } + }); + + luaCtx.writeFunction("setACL", [](boost::variant>> inp) { + setLuaSideEffect(); + NetmaskGroup nmg; + if (auto str = boost::get(&inp)) { + nmg.addMask(*str); + } + else + for (const auto& p : boost::get>>(inp)) { + nmg.addMask(p.second); } - g_ACL.setState(nmg); + g_ACL.setState(nmg); }); luaCtx.writeFunction("setACLFromFile", [](const std::string& file) { - setLuaSideEffect(); - NetmaskGroup nmg; - - ifstream ifs(file); - if(!ifs) { - throw std::runtime_error("Could not open '"+file+"': "+stringerror()); - } - - string::size_type pos; - string line; - while(getline(ifs,line)) { - pos=line.find('#'); - if(pos!=string::npos) - line.resize(pos); - boost::trim(line); - if(line.empty()) - continue; + setLuaSideEffect(); + NetmaskGroup nmg; - nmg.addMask(line); - } + ifstream ifs(file); + if (!ifs) { + throw std::runtime_error("Could not open '" + file + "': " + stringerror()); + } + + string::size_type pos; + string line; + while (getline(ifs, line)) { + pos = line.find('#'); + if (pos != string::npos) + line.resize(pos); + boost::trim(line); + if (line.empty()) + continue; + + nmg.addMask(line); + } - g_ACL.setState(nmg); + g_ACL.setState(nmg); }); luaCtx.writeFunction("showACL", []() { - setLuaNoSideEffect(); - vector vec; - - g_ACL.getLocal()->toStringVector(&vec); + setLuaNoSideEffect(); + vector vec; - for(const auto& s : vec) - g_outputBuffer+=s+"\n"; + g_ACL.getLocal()->toStringVector(&vec); - }); + for (const auto& s : vec) + g_outputBuffer += s + "\n"; + }); luaCtx.writeFunction("shutdown", []() { #ifdef HAVE_SYSTEMD - sd_notify(0, "STOPPING=1"); + sd_notify(0, "STOPPING=1"); #endif /* HAVE_SYSTEMD */ #if 0 // Useful for debugging leaks, but might lead to race under load @@ -819,240 +813,235 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) } g_tlslocals.clear(); #endif /* 0 */ - _exit(0); - } ); + _exit(0); + }); - typedef std::unordered_map > showserversopts_t; + typedef std::unordered_map> showserversopts_t; luaCtx.writeFunction("showServers", [](boost::optional vars) { - setLuaNoSideEffect(); - bool showUUIDs = false; - if (vars) { - if (vars->count("showUUIDs")) { - showUUIDs = boost::get((*vars)["showUUIDs"]); - } + setLuaNoSideEffect(); + bool showUUIDs = false; + if (vars) { + if (vars->count("showUUIDs")) { + showUUIDs = boost::get((*vars)["showUUIDs"]); + } + } + try { + ostringstream ret; + boost::format fmt; + if (showUUIDs) { + fmt = boost::format("%1$-3d %15$-36s %2$-20.20s %|62t|%3% %|92t|%4$5s %|88t|%5$7.1f %|103t|%6$7d %|106t|%7$3d %|115t|%8$2d %|117t|%9$10d %|123t|%10$7d %|128t|%11$5.1f %|146t|%12$5.1f %|152t|%13$11d %14%"); + // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + ret << (fmt % "#" % "Name" % "Address" % "State" % "Qps" % "Qlim" % "Ord" % "Wt" % "Queries" % "Drops" % "Drate" % "Lat" % "Outstanding" % "Pools" % "UUID") << endl; + } + else { + fmt = boost::format("%1$-3d %2$-20.20s %|25t|%3% %|55t|%4$5s %|51t|%5$7.1f %|66t|%6$7d %|69t|%7$3d %|78t|%8$2d %|80t|%9$10d %|86t|%10$7d %|91t|%11$5.1f %|109t|%12$5.1f %|115t|%13$11d %14%"); + ret << (fmt % "#" % "Name" % "Address" % "State" % "Qps" % "Qlim" % "Ord" % "Wt" % "Queries" % "Drops" % "Drate" % "Lat" % "Outstanding" % "Pools") << endl; } - try { - ostringstream ret; - boost::format fmt; - if (showUUIDs) { - fmt = boost::format("%1$-3d %15$-36s %2$-20.20s %|62t|%3% %|92t|%4$5s %|88t|%5$7.1f %|103t|%6$7d %|106t|%7$3d %|115t|%8$2d %|117t|%9$10d %|123t|%10$7d %|128t|%11$5.1f %|146t|%12$5.1f %|152t|%13$11d %14%" ); - // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - ret << (fmt % "#" % "Name" % "Address" % "State" % "Qps" % "Qlim" % "Ord" % "Wt" % "Queries" % "Drops" % "Drate" % "Lat" % "Outstanding" % "Pools" % "UUID") << endl; - } else { - fmt = boost::format("%1$-3d %2$-20.20s %|25t|%3% %|55t|%4$5s %|51t|%5$7.1f %|66t|%6$7d %|69t|%7$3d %|78t|%8$2d %|80t|%9$10d %|86t|%10$7d %|91t|%11$5.1f %|109t|%12$5.1f %|115t|%13$11d %14%" ); - ret << (fmt % "#" % "Name" % "Address" % "State" % "Qps" % "Qlim" % "Ord" % "Wt" % "Queries" % "Drops" % "Drate" % "Lat" % "Outstanding" % "Pools") << endl; - } - uint64_t totQPS{0}, totQueries{0}, totDrops{0}; - int counter=0; - auto states = g_dstates.getLocal(); - for(const auto& s : *states) { - string status = s->getStatus(); - string pools; - for(auto& p : s->pools) { - if(!pools.empty()) - pools+=" "; - pools+=p; - } - if (showUUIDs) { - ret << (fmt % counter % s->getName() % s->remote.toStringWithPort() % - status % - s->queryLoad % s->qps.getRate() % s->order % s->weight % s->queries.load() % s->reuseds.load() % (s->dropRate) % (s->latencyUsec/1000.0) % s->outstanding.load() % pools % s->id) << endl; - } else { - ret << (fmt % counter % s->getName() % s->remote.toStringWithPort() % - status % - s->queryLoad % s->qps.getRate() % s->order % s->weight % s->queries.load() % s->reuseds.load() % (s->dropRate) % (s->latencyUsec/1000.0) % s->outstanding.load() % pools) << endl; - } - totQPS += s->queryLoad; - totQueries += s->queries.load(); - totDrops += s->reuseds.load(); - ++counter; + uint64_t totQPS{0}, totQueries{0}, totDrops{0}; + int counter = 0; + auto states = g_dstates.getLocal(); + for (const auto& s : *states) { + string status = s->getStatus(); + string pools; + for (auto& p : s->pools) { + if (!pools.empty()) + pools += " "; + pools += p; } if (showUUIDs) { - ret<< (fmt % "All" % "" % "" % "" - % - (double)totQPS % "" % "" % "" % totQueries % totDrops % "" % "" % "" % "" % "" ) << endl; - } else { - ret<< (fmt % "All" % "" % "" % "" - % - (double)totQPS % "" % "" % "" % totQueries % totDrops % "" % "" % "" % "" ) << endl; + ret << (fmt % counter % s->getName() % s->remote.toStringWithPort() % status % s->queryLoad % s->qps.getRate() % s->order % s->weight % s->queries.load() % s->reuseds.load() % (s->dropRate) % (s->latencyUsec / 1000.0) % s->outstanding.load() % pools % s->id) << endl; } - - g_outputBuffer=ret.str(); - } catch(std::exception& e) { - g_outputBuffer=e.what(); - throw; + else { + ret << (fmt % counter % s->getName() % s->remote.toStringWithPort() % status % s->queryLoad % s->qps.getRate() % s->order % s->weight % s->queries.load() % s->reuseds.load() % (s->dropRate) % (s->latencyUsec / 1000.0) % s->outstanding.load() % pools) << endl; + } + totQPS += s->queryLoad; + totQueries += s->queries.load(); + totDrops += s->reuseds.load(); + ++counter; } - }); + if (showUUIDs) { + ret << (fmt % "All" % "" % "" % "" + % (double)totQPS % "" % "" % "" % totQueries % totDrops % "" % "" % "" % "" % "") + << endl; + } + else { + ret << (fmt % "All" % "" % "" % "" + % (double)totQPS % "" % "" % "" % totQueries % totDrops % "" % "" % "" % "") + << endl; + } + + g_outputBuffer = ret.str(); + } + catch (std::exception& e) { + g_outputBuffer = e.what(); + throw; + } + }); luaCtx.writeFunction("getServers", []() { - setLuaNoSideEffect(); - vector > > ret; - int count=1; - for(const auto& s : g_dstates.getCopy()) { - ret.emplace_back(count++, s); - } - return ret; - }); + setLuaNoSideEffect(); + vector>> ret; + int count = 1; + for (const auto& s : g_dstates.getCopy()) { + ret.push_back(make_pair(count++, s)); + } + return ret; + }); luaCtx.writeFunction("getPoolServers", [](string pool) { - const auto poolServers = getDownstreamCandidates(g_pools.getCopy(), pool); - return *poolServers; - }); + const auto poolServers = getDownstreamCandidates(g_pools.getCopy(), pool); + return *poolServers; + }); luaCtx.writeFunction("getServer", [client](boost::variant i) { - if (client) { - return std::make_shared(ComboAddress(), ComboAddress(), 0, std::string(), 1, false); - } - auto states = g_dstates.getCopy(); - if (auto str = boost::get(&i)) { - const auto uuid = getUniqueID(*str); - for (auto& state : states) { - if (state->id == uuid) { - return state; - } + if (client) { + return std::make_shared(ComboAddress(), ComboAddress(), 0, std::string(), 1, false); + } + auto states = g_dstates.getCopy(); + if (auto str = boost::get(&i)) { + const auto uuid = getUniqueID(*str); + for (auto& state : states) { + if (state->id == uuid) { + return state; } } - else if (auto pos = boost::get(&i)) { - return states.at(*pos); - } + } + else if (auto pos = boost::get(&i)) { + return states.at(*pos); + } - g_outputBuffer = "Error: no rule matched\n"; - return std::shared_ptr(nullptr); - }); + g_outputBuffer = "Error: no rule matched\n"; + return std::shared_ptr(nullptr); + }); - luaCtx.writeFunction("carbonServer", [](const std::string& address, boost::optional ourName, - boost::optional interval, boost::optional namespace_name, - boost::optional instance_name) { - setLuaSideEffect(); - auto ours = g_carbon.getCopy(); - ours.push_back({ - ComboAddress(address, 2003), - (namespace_name && !namespace_name->empty()) ? *namespace_name : "dnsdist", - ourName ? *ourName : "", - (instance_name && !instance_name->empty()) ? *instance_name : "main" , - interval ? *interval : 30 - }); - g_carbon.setState(ours); - }); - - luaCtx.writeFunction("webserver", [client,configCheck](const std::string& address, boost::optional password, boost::optional apiKey, const boost::optional > customHeaders, const boost::optional acl) { - setLuaSideEffect(); - ComboAddress local; - try { - local = ComboAddress(address); - } - catch (const PDNSException& e) { - throw std::runtime_error(std::string("Error parsing the bind address for the webserver: ") + e.reason); - } + luaCtx.writeFunction("carbonServer", [](const std::string& address, boost::optional ourName, boost::optional interval, boost::optional namespace_name, boost::optional instance_name) { + setLuaSideEffect(); + auto ours = g_carbon.getCopy(); + ours.push_back({ComboAddress(address, 2003), + (namespace_name && !namespace_name->empty()) ? *namespace_name : "dnsdist", + ourName ? *ourName : "", + (instance_name && !instance_name->empty()) ? *instance_name : "main", + interval ? *interval : 30}); + g_carbon.setState(ours); + }); - if (client || configCheck) { - return; - } + luaCtx.writeFunction("webserver", [client, configCheck](const std::string& address, boost::optional password, boost::optional apiKey, const boost::optional> customHeaders, const boost::optional acl) { + setLuaSideEffect(); + ComboAddress local; + try { + local = ComboAddress(address); + } + catch (const PDNSException& e) { + throw std::runtime_error(std::string("Error parsing the bind address for the webserver: ") + e.reason); + } - if (password || apiKey || customHeaders || acl) { - warnlog("Passing additional parameters to 'webserver()' is deprecated, please use 'setWebserverConfig()' instead."); - } + if (client || configCheck) { + return; + } - try { - int sock = SSocket(local.sin4.sin_family, SOCK_STREAM, 0); - SSetsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 1); - SBind(sock, local); - SListen(sock, 5); - auto launch=[sock, local, password, apiKey, customHeaders, acl]() { - if (password) { - auto holder = make_unique(std::string(*password), false); - if (!holder->wasHashed() && holder->isHashingAvailable()) { - infolog("Passing a plain-text password to 'webserver()' is deprecated, please use 'setWebserverConfig()' instead and consider generating a hashed password using 'hashPassword()'."); - } - - setWebserverPassword(std::move(holder)); - } + if (password || apiKey || customHeaders || acl) { + warnlog("Passing additional parameters to 'webserver()' is deprecated, please use 'setWebserverConfig()' instead."); + } - if (apiKey) { - auto holder = make_unique(std::string(*apiKey), false); - setWebserverAPIKey(std::move(holder)); + try { + int sock = SSocket(local.sin4.sin_family, SOCK_STREAM, 0); + SSetsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 1); + SBind(sock, local); + SListen(sock, 5); + auto launch = [sock, local, password, apiKey, customHeaders, acl]() { + if (password) { + auto holder = make_unique(std::string(*password), false); + if (!holder->wasHashed() && holder->isHashingAvailable()) { + infolog("Passing a plain-text password to 'webserver()' is deprecated, please use 'setWebserverConfig()' instead and consider generating a hashed password using 'hashPassword()'."); } - if (customHeaders) { - setWebserverCustomHeaders(customHeaders); - } + setWebserverPassword(std::move(holder)); + } - if (acl) { - setWebserverACL(*acl); - } - thread t(dnsdistWebserverThread, sock, local); - t.detach(); - }; - if (g_launchWork) { - g_launchWork->push_back(launch); + if (apiKey) { + auto holder = make_unique(std::string(*apiKey), false); + setWebserverAPIKey(std::move(holder)); } - else { - launch(); + + if (customHeaders) { + setWebserverCustomHeaders(customHeaders); + } + + if (acl) { + setWebserverACL(*acl); } + thread t(dnsdistWebserverThread, sock, local); + t.detach(); + }; + if (g_launchWork) { + g_launchWork->push_back(launch); } - catch (const std::exception& e) { - g_outputBuffer="Unable to bind to webserver socket on " + local.toStringWithPort() + ": " + e.what(); - errlog("Unable to bind to webserver socket on %s: %s", local.toStringWithPort(), e.what()); + else { + launch(); } + } + catch (const std::exception& e) { + g_outputBuffer = "Unable to bind to webserver socket on " + local.toStringWithPort() + ": " + e.what(); + errlog("Unable to bind to webserver socket on %s: %s", local.toStringWithPort(), e.what()); + } + }); - }); - - typedef std::unordered_map> > webserveropts_t; + typedef std::unordered_map>> webserveropts_t; luaCtx.writeFunction("setWebserverConfig", [](boost::optional vars) { - setLuaSideEffect(); - - if (!vars) { - return ; - } + setLuaSideEffect(); - bool hashPlaintextCredentials = false; - if (vars->count("hashPlaintextCredentials")) { - hashPlaintextCredentials = boost::get(vars->at("hashPlaintextCredentials")); - } + if (!vars) { + return; + } - if (vars->count("password")) { - std::string password = boost::get(vars->at("password")); - auto holder = make_unique(std::move(password), hashPlaintextCredentials); - if (!holder->wasHashed() && holder->isHashingAvailable()) { - infolog("Passing a plain-text password via the 'password' parameter to 'setWebserverConfig()' is not advised, please consider generating a hashed one using 'hashPassword()' instead."); - } + bool hashPlaintextCredentials = false; + if (vars->count("hashPlaintextCredentials")) { + hashPlaintextCredentials = boost::get(vars->at("hashPlaintextCredentials")); + } - setWebserverPassword(std::move(holder)); + if (vars->count("password")) { + std::string password = boost::get(vars->at("password")); + auto holder = make_unique(std::move(password), hashPlaintextCredentials); + if (!holder->wasHashed() && holder->isHashingAvailable()) { + infolog("Passing a plain-text password via the 'password' parameter to 'setWebserverConfig()' is not advised, please consider generating a hashed one using 'hashPassword()' instead."); } - if (vars->count("apiKey")) { - std::string apiKey = boost::get(vars->at("apiKey")); - auto holder = make_unique(std::move(apiKey), hashPlaintextCredentials); - if (!holder->wasHashed() && holder->isHashingAvailable()) { - infolog("Passing a plain-text API key via the 'apiKey' parameter to 'setWebserverConfig()' is not advised, please consider generating a hashed one using 'hashPassword()' instead."); - } + setWebserverPassword(std::move(holder)); + } - setWebserverAPIKey(std::move(holder)); + if (vars->count("apiKey")) { + std::string apiKey = boost::get(vars->at("apiKey")); + auto holder = make_unique(std::move(apiKey), hashPlaintextCredentials); + if (!holder->wasHashed() && holder->isHashingAvailable()) { + infolog("Passing a plain-text API key via the 'apiKey' parameter to 'setWebserverConfig()' is not advised, please consider generating a hashed one using 'hashPassword()' instead."); } - if (vars->count("acl")) { - const std::string acl = boost::get(vars->at("acl")); + setWebserverAPIKey(std::move(holder)); + } - setWebserverACL(acl); - } + if (vars->count("acl")) { + const std::string acl = boost::get(vars->at("acl")); - if (vars->count("customHeaders")) { - const boost::optional > headers = boost::get >(vars->at("customHeaders")); + setWebserverACL(acl); + } - setWebserverCustomHeaders(headers); - } + if (vars->count("customHeaders")) { + const boost::optional> headers = boost::get>(vars->at("customHeaders")); - if (vars->count("statsRequireAuthentication")) { - setWebserverStatsRequireAuthentication(boost::get(vars->at("statsRequireAuthentication"))); - } + setWebserverCustomHeaders(headers); + } - if (vars->count("maxConcurrentConnections")) { - setWebserverMaxConcurrentConnections(std::stoi(boost::get(vars->at("maxConcurrentConnections")))); - } - }); + if (vars->count("statsRequireAuthentication")) { + setWebserverStatsRequireAuthentication(boost::get(vars->at("statsRequireAuthentication"))); + } + + if (vars->count("maxConcurrentConnections")) { + setWebserverMaxConcurrentConnections(std::stoi(boost::get(vars->at("maxConcurrentConnections")))); + } + }); luaCtx.writeFunction("hashPassword", [](const std::string& password, boost::optional workFactor) { if (workFactor) { @@ -1061,257 +1050,264 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) return hashPassword(password); }); - luaCtx.writeFunction("controlSocket", [client,configCheck](const std::string& str) { - setLuaSideEffect(); - ComboAddress local(str, 5199); + luaCtx.writeFunction("controlSocket", [client, configCheck](const std::string& str) { + setLuaSideEffect(); + ComboAddress local(str, 5199); - if(client || configCheck) { - g_serverControl = local; - return; - } + if (client || configCheck) { + g_serverControl = local; + return; + } - g_consoleEnabled = true; + g_consoleEnabled = true; #ifdef HAVE_LIBSODIUM - if (g_configurationDone && g_consoleKey.empty()) { - warnlog("Warning, the console has been enabled via 'controlSocket()' but no key has been set with 'setKey()' so all connections will fail until a key has been set"); - } + if (g_configurationDone && g_consoleKey.empty()) { + warnlog("Warning, the console has been enabled via 'controlSocket()' but no key has been set with 'setKey()' so all connections will fail until a key has been set"); + } #endif - try { - int sock = SSocket(local.sin4.sin_family, SOCK_STREAM, 0); - SSetsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 1); - SBind(sock, local); - SListen(sock, 5); - auto launch=[sock, local]() { - thread t(controlThread, sock, local); - t.detach(); - }; - if (g_launchWork) { - g_launchWork->push_back(launch); - } - else { - launch(); - } + try { + int sock = SSocket(local.sin4.sin_family, SOCK_STREAM, 0); + SSetsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 1); + SBind(sock, local); + SListen(sock, 5); + auto launch = [sock, local]() { + thread t(controlThread, sock, local); + t.detach(); + }; + if (g_launchWork) { + g_launchWork->push_back(launch); } - catch(std::exception& e) { - g_outputBuffer="Unable to bind to control socket on " + local.toStringWithPort() + ": " + e.what(); - errlog("Unable to bind to control socket on %s: %s", local.toStringWithPort(), e.what()); + else { + launch(); } - }); + } + catch (std::exception& e) { + g_outputBuffer = "Unable to bind to control socket on " + local.toStringWithPort() + ": " + e.what(); + errlog("Unable to bind to control socket on %s: %s", local.toStringWithPort(), e.what()); + } + }); luaCtx.writeFunction("addConsoleACL", [](const std::string& netmask) { - setLuaSideEffect(); + setLuaSideEffect(); #ifndef HAVE_LIBSODIUM - warnlog("Allowing remote access to the console while libsodium support has not been enabled is not secure, and will result in cleartext communications"); + warnlog("Allowing remote access to the console while libsodium support has not been enabled is not secure, and will result in cleartext communications"); #endif - g_consoleACL.modify([netmask](NetmaskGroup& nmg) { nmg.addMask(netmask); }); - }); + g_consoleACL.modify([netmask](NetmaskGroup& nmg) { nmg.addMask(netmask); }); + }); - luaCtx.writeFunction("setConsoleACL", [](boost::variant>> inp) { - setLuaSideEffect(); + luaCtx.writeFunction("setConsoleACL", [](boost::variant>> inp) { + setLuaSideEffect(); #ifndef HAVE_LIBSODIUM - warnlog("Allowing remote access to the console while libsodium support has not been enabled is not secure, and will result in cleartext communications"); + warnlog("Allowing remote access to the console while libsodium support has not been enabled is not secure, and will result in cleartext communications"); #endif - NetmaskGroup nmg; - if(auto str = boost::get(&inp)) { - nmg.addMask(*str); - } - else for(const auto& p : boost::get>>(inp)) { - nmg.addMask(p.second); + NetmaskGroup nmg; + if (auto str = boost::get(&inp)) { + nmg.addMask(*str); + } + else + for (const auto& p : boost::get>>(inp)) { + nmg.addMask(p.second); } - g_consoleACL.setState(nmg); + g_consoleACL.setState(nmg); }); luaCtx.writeFunction("showConsoleACL", []() { - setLuaNoSideEffect(); + setLuaNoSideEffect(); #ifndef HAVE_LIBSODIUM - warnlog("Allowing remote access to the console while libsodium support has not been enabled is not secure, and will result in cleartext communications"); + warnlog("Allowing remote access to the console while libsodium support has not been enabled is not secure, and will result in cleartext communications"); #endif - vector vec; - g_consoleACL.getLocal()->toStringVector(&vec); + vector vec; + g_consoleACL.getLocal()->toStringVector(&vec); - for(const auto& s : vec) { - g_outputBuffer += s + "\n"; - } - }); + for (const auto& s : vec) { + g_outputBuffer += s + "\n"; + } + }); luaCtx.writeFunction("setConsoleMaximumConcurrentConnections", [](size_t max) { - setLuaSideEffect(); - setConsoleMaximumConcurrentConnections(max); + setLuaSideEffect(); + setConsoleMaximumConcurrentConnections(max); }); luaCtx.writeFunction("clearQueryCounters", []() { - unsigned int size{0}; - { - auto records = g_qcount.records.write_lock(); - size = records->size(); - records->clear(); - } + unsigned int size{0}; + { + auto records = g_qcount.records.write_lock(); + size = records->size(); + records->clear(); + } - boost::format fmt("%d records cleared from query counter buffer\n"); - g_outputBuffer = (fmt % size).str(); - }); + boost::format fmt("%d records cleared from query counter buffer\n"); + g_outputBuffer = (fmt % size).str(); + }); luaCtx.writeFunction("getQueryCounters", [](boost::optional optMax) { - setLuaNoSideEffect(); - auto records = g_qcount.records.read_lock(); - g_outputBuffer = "query counting is currently: "; - g_outputBuffer+= g_qcount.enabled ? "enabled" : "disabled"; - g_outputBuffer+= (boost::format(" (%d records in buffer)\n") % records->size()).str(); - - boost::format fmt("%-3d %s: %d request(s)\n"); - unsigned int max = optMax ? *optMax : 10; - unsigned int index{1}; - for (auto it = records->begin(); it != records->end() && index <= max; ++it, ++index) { - g_outputBuffer += (fmt % index % it->first % it->second).str(); - } - }); + setLuaNoSideEffect(); + auto records = g_qcount.records.read_lock(); + g_outputBuffer = "query counting is currently: "; + g_outputBuffer += g_qcount.enabled ? "enabled" : "disabled"; + g_outputBuffer += (boost::format(" (%d records in buffer)\n") % records->size()).str(); + + boost::format fmt("%-3d %s: %d request(s)\n"); + unsigned int max = optMax ? *optMax : 10; + unsigned int index{1}; + for (auto it = records->begin(); it != records->end() && index <= max; ++it, ++index) { + g_outputBuffer += (fmt % index % it->first % it->second).str(); + } + }); - luaCtx.writeFunction("setQueryCount", [](bool enabled) { g_qcount.enabled=enabled; }); + luaCtx.writeFunction("setQueryCount", [](bool enabled) { g_qcount.enabled = enabled; }); luaCtx.writeFunction("setQueryCountFilter", [](QueryCountFilter func) { - g_qcount.filter = func; - }); + g_qcount.filter = func; + }); luaCtx.writeFunction("makeKey", []() { - setLuaNoSideEffect(); - g_outputBuffer="setKey("+newKey()+")\n"; - }); + setLuaNoSideEffect(); + g_outputBuffer = "setKey(" + newKey() + ")\n"; + }); luaCtx.writeFunction("setKey", [](const std::string& key) { - if(!g_configurationDone && ! g_consoleKey.empty()) { // this makes sure the commandline -k key prevails over dnsdist.conf - return; // but later setKeys() trump the -k value again - } + if (!g_configurationDone && !g_consoleKey.empty()) { // this makes sure the commandline -k key prevails over dnsdist.conf + return; // but later setKeys() trump the -k value again + } #ifndef HAVE_LIBSODIUM - warnlog("Calling setKey() while libsodium support has not been enabled is not secure, and will result in cleartext communications"); + warnlog("Calling setKey() while libsodium support has not been enabled is not secure, and will result in cleartext communications"); #endif - setLuaSideEffect(); - string newkey; - if(B64Decode(key, newkey) < 0) { - g_outputBuffer=string("Unable to decode ")+key+" as Base64"; - errlog("%s", g_outputBuffer); - } - else - g_consoleKey=newkey; - }); + setLuaSideEffect(); + string newkey; + if (B64Decode(key, newkey) < 0) { + g_outputBuffer = string("Unable to decode ") + key + " as Base64"; + errlog("%s", g_outputBuffer); + } + else + g_consoleKey = newkey; + }); luaCtx.writeFunction("clearConsoleHistory", []() { - clearConsoleHistory(); - }); + clearConsoleHistory(); + }); - luaCtx.writeFunction("testCrypto", [](boost::optional optTestMsg) - { - setLuaNoSideEffect(); + luaCtx.writeFunction("testCrypto", [](boost::optional optTestMsg) { + setLuaNoSideEffect(); #ifdef HAVE_LIBSODIUM - try { - string testmsg; - - if (optTestMsg) { - testmsg = *optTestMsg; - } - else { - testmsg = "testStringForCryptoTests"; - } - - SodiumNonce sn, sn2; - sn.init(); - sn2=sn; - string encrypted = sodEncryptSym(testmsg, g_consoleKey, sn); - string decrypted = sodDecryptSym(encrypted, g_consoleKey, sn2); - - sn.increment(); - sn2.increment(); - - encrypted = sodEncryptSym(testmsg, g_consoleKey, sn); - decrypted = sodDecryptSym(encrypted, g_consoleKey, sn2); - - if(testmsg == decrypted) - g_outputBuffer="Everything is ok!\n"; - else - g_outputBuffer="Crypto failed.. (the decoded value does not match the cleartext one)\n"; - } - catch(const std::exception& e) { - g_outputBuffer="Crypto failed: "+std::string(e.what())+"\n"; - } - catch(...) { - g_outputBuffer="Crypto failed..\n"; - } + try { + string testmsg; + + if (optTestMsg) { + testmsg = *optTestMsg; + } + else { + testmsg = "testStringForCryptoTests"; + } + + SodiumNonce sn, sn2; + sn.init(); + sn2 = sn; + string encrypted = sodEncryptSym(testmsg, g_consoleKey, sn); + string decrypted = sodDecryptSym(encrypted, g_consoleKey, sn2); + + sn.increment(); + sn2.increment(); + + encrypted = sodEncryptSym(testmsg, g_consoleKey, sn); + decrypted = sodDecryptSym(encrypted, g_consoleKey, sn2); + + if (testmsg == decrypted) + g_outputBuffer = "Everything is ok!\n"; + else + g_outputBuffer = "Crypto failed.. (the decoded value does not match the cleartext one)\n"; + } + catch (const std::exception& e) { + g_outputBuffer = "Crypto failed: " + std::string(e.what()) + "\n"; + } + catch (...) { + g_outputBuffer = "Crypto failed..\n"; + } #else - g_outputBuffer="Crypto not available.\n"; + g_outputBuffer = "Crypto not available.\n"; #endif - }); + }); - luaCtx.writeFunction("setTCPRecvTimeout", [](int timeout) { g_tcpRecvTimeout=timeout; }); + luaCtx.writeFunction("setTCPRecvTimeout", [](int timeout) { g_tcpRecvTimeout = timeout; }); - luaCtx.writeFunction("setTCPSendTimeout", [](int timeout) { g_tcpSendTimeout=timeout; }); + luaCtx.writeFunction("setTCPSendTimeout", [](int timeout) { g_tcpSendTimeout = timeout; }); - luaCtx.writeFunction("setUDPTimeout", [](int timeout) { g_udpTimeout=timeout; }); + luaCtx.writeFunction("setUDPTimeout", [](int timeout) { g_udpTimeout = timeout; }); luaCtx.writeFunction("setMaxUDPOutstanding", [](uint16_t max) { - if (!g_configurationDone) { - g_maxOutstanding = max; - } else { - g_outputBuffer="Max UDP outstanding cannot be altered at runtime!\n"; - } - }); + if (!g_configurationDone) { + g_maxOutstanding = max; + } + else { + g_outputBuffer = "Max UDP outstanding cannot be altered at runtime!\n"; + } + }); luaCtx.writeFunction("setMaxTCPClientThreads", [](uint64_t max) { - if (!g_configurationDone) { - g_maxTCPClientThreads = max; - } else { - g_outputBuffer="Maximum TCP client threads count cannot be altered at runtime!\n"; - } - }); + if (!g_configurationDone) { + g_maxTCPClientThreads = max; + } + else { + g_outputBuffer = "Maximum TCP client threads count cannot be altered at runtime!\n"; + } + }); luaCtx.writeFunction("setMaxTCPQueuedConnections", [](uint64_t max) { - if (!g_configurationDone) { - g_maxTCPQueuedConnections = max; - } else { - g_outputBuffer="The maximum number of queued TCP connections cannot be altered at runtime!\n"; - } - }); + if (!g_configurationDone) { + g_maxTCPQueuedConnections = max; + } + else { + g_outputBuffer = "The maximum number of queued TCP connections cannot be altered at runtime!\n"; + } + }); luaCtx.writeFunction("setMaxTCPQueriesPerConnection", [](size_t max) { - if (!g_configurationDone) { - g_maxTCPQueriesPerConn = max; - } else { - g_outputBuffer="The maximum number of queries per TCP connection cannot be altered at runtime!\n"; - } - }); + if (!g_configurationDone) { + g_maxTCPQueriesPerConn = max; + } + else { + g_outputBuffer = "The maximum number of queries per TCP connection cannot be altered at runtime!\n"; + } + }); luaCtx.writeFunction("setMaxTCPConnectionsPerClient", [](size_t max) { - if (!g_configurationDone) { - g_maxTCPConnectionsPerClient = max; - } else { - g_outputBuffer="The maximum number of TCP connection per client cannot be altered at runtime!\n"; - } - }); + if (!g_configurationDone) { + g_maxTCPConnectionsPerClient = max; + } + else { + g_outputBuffer = "The maximum number of TCP connection per client cannot be altered at runtime!\n"; + } + }); luaCtx.writeFunction("setMaxTCPConnectionDuration", [](size_t max) { - if (!g_configurationDone) { - g_maxTCPConnectionDuration = max; - } else { - g_outputBuffer="The maximum duration of a TCP connection cannot be altered at runtime!\n"; - } - }); + if (!g_configurationDone) { + g_maxTCPConnectionDuration = max; + } + else { + g_outputBuffer = "The maximum duration of a TCP connection cannot be altered at runtime!\n"; + } + }); luaCtx.writeFunction("setMaxCachedTCPConnectionsPerDownstream", [](size_t max) { setMaxCachedTCPConnectionsPerDownstream(max); - }); + }); luaCtx.writeFunction("setOutgoingDoHWorkerThreads", [](uint64_t workers) { - if (!g_configurationDone) { - g_outgoingDoHWorkerThreads = workers; - } else { - g_outputBuffer="The amount of outgoing DoH worker threads cannot be altered at runtime!\n"; - } - }); + if (!g_configurationDone) { + g_outgoingDoHWorkerThreads = workers; + } + else { + g_outputBuffer = "The amount of outgoing DoH worker threads cannot be altered at runtime!\n"; + } + }); luaCtx.writeFunction("setOutgoingTLSSessionsCacheMaxTicketsPerBackend", [](uint16_t max) { if (g_configurationDone) { @@ -1341,772 +1337,783 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) luaCtx.writeFunction("setCacheCleaningPercentage", [](uint16_t percentage) { if (percentage < 100) g_cacheCleaningPercentage = percentage; else g_cacheCleaningPercentage = 100; }); - luaCtx.writeFunction("setECSSourcePrefixV4", [](uint16_t prefix) { g_ECSSourcePrefixV4=prefix; }); + luaCtx.writeFunction("setECSSourcePrefixV4", [](uint16_t prefix) { g_ECSSourcePrefixV4 = prefix; }); - luaCtx.writeFunction("setECSSourcePrefixV6", [](uint16_t prefix) { g_ECSSourcePrefixV6=prefix; }); + luaCtx.writeFunction("setECSSourcePrefixV6", [](uint16_t prefix) { g_ECSSourcePrefixV6 = prefix; }); - luaCtx.writeFunction("setECSOverride", [](bool override) { g_ECSOverride=override; }); - - luaCtx.writeFunction("showDynBlocks", []() { - setLuaNoSideEffect(); - auto slow = g_dynblockNMG.getCopy(); - struct timespec now; - gettime(&now); - boost::format fmt("%-24s %8d %8d %-10s %-20s %s\n"); - g_outputBuffer = (fmt % "What" % "Seconds" % "Blocks" % "Warning" % "Action" % "Reason").str(); - for(const auto& e: slow) { - if (now < e.second.until) { - uint64_t counter = e.second.blocks; - if (g_defaultBPFFilter && e.second.bpf) { - counter += g_defaultBPFFilter->getHits(e.first.getNetwork()); - } - g_outputBuffer+= (fmt % e.first.toString() % (e.second.until.tv_sec - now.tv_sec) % counter % (e.second.warning ? "true" : "false") % DNSAction::typeToString(e.second.action != DNSAction::Action::None ? e.second.action : g_dynBlockAction) % e.second.reason).str(); - } - } - auto slow2 = g_dynblockSMT.getCopy(); - slow2.visit([&now, &fmt](const SuffixMatchTree& node) { - if(now getHits(e.first.getNetwork()); + } + g_outputBuffer += (fmt % e.first.toString() % (e.second.until.tv_sec - now.tv_sec) % counter % (e.second.warning ? "true" : "false") % DNSAction::typeToString(e.second.action != DNSAction::Action::None ? e.second.action : g_dynBlockAction) % e.second.reason).str(); + } + } + auto slow2 = g_dynblockSMT.getCopy(); + slow2.visit([&now, &fmt](const SuffixMatchTree& node) { + if (now < node.d_value.until) { + string dom("empty"); + if (!node.d_value.domain.empty()) + dom = node.d_value.domain.toString(); + g_outputBuffer += (fmt % dom % (node.d_value.until.tv_sec - now.tv_sec) % node.d_value.blocks % (node.d_value.warning ? "true" : "false") % DNSAction::typeToString(node.d_value.action != DNSAction::Action::None ? node.d_value.action : g_dynBlockAction) % node.d_value.reason).str(); + } }); + }); luaCtx.writeFunction("clearDynBlocks", []() { - setLuaSideEffect(); - nmts_t nmg; - g_dynblockNMG.setState(nmg); - SuffixMatchTree smt; - g_dynblockSMT.setState(smt); - }); + setLuaSideEffect(); + nmts_t nmg; + g_dynblockNMG.setState(nmg); + SuffixMatchTree smt; + g_dynblockSMT.setState(smt); + }); luaCtx.writeFunction("addDynBlocks", - [](const std::unordered_map& m, const std::string& msg, boost::optional seconds, boost::optional action) { - if (m.empty()) { - return; - } - setLuaSideEffect(); - auto slow = g_dynblockNMG.getCopy(); - struct timespec until, now; - gettime(&now); - until = now; - int actualSeconds = seconds ? *seconds : 10; - until.tv_sec += actualSeconds; - for (const auto& capair : m) { - unsigned int count = 0; - AddressAndPortRange requestor(capair.first, capair.first.isIPv4() ? 32 : 128, 0); - auto got = slow.lookup(requestor); - bool expired = false; - if (got) { - if (until < got->second.until) { - // had a longer policy - continue; - } - if (now < got->second.until) { - // only inherit count on fresh query we are extending - count = got->second.blocks; - } - else { - expired = true; - } - } - DynBlock db{msg, until, DNSName(), (action ? *action : DNSAction::Action::None)}; - db.blocks = count; - if (!got || expired) { - warnlog("Inserting dynamic block for %s for %d seconds: %s", capair.first.toString(), actualSeconds, msg); + [](const std::unordered_map& m, const std::string& msg, boost::optional seconds, boost::optional action) { + if (m.empty()) { + return; + } + setLuaSideEffect(); + auto slow = g_dynblockNMG.getCopy(); + struct timespec until, now; + gettime(&now); + until = now; + int actualSeconds = seconds ? *seconds : 10; + until.tv_sec += actualSeconds; + for (const auto& capair : m) { + unsigned int count = 0; + AddressAndPortRange requestor(capair.first, capair.first.isIPv4() ? 32 : 128, 0); + auto got = slow.lookup(requestor); + bool expired = false; + if (got) { + if (until < got->second.until) { + // had a longer policy + continue; + } + if (now < got->second.until) { + // only inherit count on fresh query we are extending + count = got->second.blocks; } - slow.insert(requestor).second = db; - } - g_dynblockNMG.setState(slow); - }); + else { + expired = true; + } + } + DynBlock db{msg, until, DNSName(), (action ? *action : DNSAction::Action::None)}; + db.blocks = count; + if (!got || expired) { + warnlog("Inserting dynamic block for %s for %d seconds: %s", capair.first.toString(), actualSeconds, msg); + } + slow.insert(requestor).second = db; + } + g_dynblockNMG.setState(slow); + }); luaCtx.writeFunction("addDynBlockSMT", - [](const vector >&names, const std::string& msg, boost::optional seconds, boost::optional action) { - if (names.empty()) { - return; + [](const vector>& names, const std::string& msg, boost::optional seconds, boost::optional action) { + if (names.empty()) { + return; + } + setLuaSideEffect(); + auto slow = g_dynblockSMT.getCopy(); + struct timespec until, now; + gettime(&now); + until = now; + int actualSeconds = seconds ? *seconds : 10; + until.tv_sec += actualSeconds; + + for (const auto& capair : names) { + unsigned int count = 0; + DNSName domain(capair.second); + domain.makeUsLowerCase(); + auto got = slow.lookup(domain); + bool expired = false; + if (got) { + if (until < got->until) // had a longer policy + continue; + if (now < got->until) // only inherit count on fresh query we are extending + count = got->blocks; + else + expired = true; } - setLuaSideEffect(); - auto slow = g_dynblockSMT.getCopy(); - struct timespec until, now; - gettime(&now); - until=now; - int actualSeconds = seconds ? *seconds : 10; - until.tv_sec += actualSeconds; - - for(const auto& capair : names) { - unsigned int count = 0; - DNSName domain(capair.second); - domain.makeUsLowerCase(); - auto got = slow.lookup(domain); - bool expired=false; - if(got) { - if(until < got->until) // had a longer policy - continue; - if(now < got->until) // only inherit count on fresh query we are extending - count=got->blocks; - else - expired=true; - } - - DynBlock db{msg,until,domain,(action ? *action : DNSAction::Action::None)}; - db.blocks=count; - if(!got || expired) - warnlog("Inserting dynamic block for %s for %d seconds: %s", domain, actualSeconds, msg); - slow.add(domain, std::move(db)); - } - g_dynblockSMT.setState(slow); - }); + + DynBlock db{msg, until, domain, (action ? *action : DNSAction::Action::None)}; + db.blocks = count; + if (!got || expired) + warnlog("Inserting dynamic block for %s for %d seconds: %s", domain, actualSeconds, msg); + slow.add(domain, std::move(db)); + } + g_dynblockSMT.setState(slow); + }); luaCtx.writeFunction("setDynBlocksAction", [](DNSAction::Action action) { - if (!g_configurationDone) { - if (action == DNSAction::Action::Drop || action == DNSAction::Action::NoOp || action == DNSAction::Action::Nxdomain || action == DNSAction::Action::Refused || action == DNSAction::Action::Truncate || action == DNSAction::Action::NoRecurse) { - g_dynBlockAction = action; - } - else { - errlog("Dynamic blocks action can only be Drop, NoOp, NXDomain, Refused, Truncate or NoRecurse!"); - g_outputBuffer="Dynamic blocks action can only be Drop, NoOp, NXDomain, Refused, Truncate or NoRecurse!\n"; - } - } else { - g_outputBuffer="Dynamic blocks action cannot be altered at runtime!\n"; + if (!g_configurationDone) { + if (action == DNSAction::Action::Drop || action == DNSAction::Action::NoOp || action == DNSAction::Action::Nxdomain || action == DNSAction::Action::Refused || action == DNSAction::Action::Truncate || action == DNSAction::Action::NoRecurse) { + g_dynBlockAction = action; } - }); + else { + errlog("Dynamic blocks action can only be Drop, NoOp, NXDomain, Refused, Truncate or NoRecurse!"); + g_outputBuffer = "Dynamic blocks action can only be Drop, NoOp, NXDomain, Refused, Truncate or NoRecurse!\n"; + } + } + else { + g_outputBuffer = "Dynamic blocks action cannot be altered at runtime!\n"; + } + }); luaCtx.writeFunction("setDynBlocksPurgeInterval", [](unsigned int interval) { DynBlockMaintenance::s_expiredDynBlocksPurgeInterval = interval; }); luaCtx.writeFunction("addDNSCryptBind", [](const std::string& addr, const std::string& providerName, boost::variant>> certFiles, boost::variant>> keyFiles, boost::optional vars) { - if (g_configurationDone) { - g_outputBuffer="addDNSCryptBind cannot be used at runtime!\n"; - return; - } + if (g_configurationDone) { + g_outputBuffer = "addDNSCryptBind cannot be used at runtime!\n"; + return; + } #ifdef HAVE_DNSCRYPT - bool reusePort = false; - int tcpFastOpenQueueSize = 0; - int tcpListenQueueSize = 0; - size_t maxInFlightQueriesPerConn = 0; - size_t tcpMaxConcurrentConnections = 0; - std::string interface; - std::set cpus; - std::vector certKeys; + bool reusePort = false; + int tcpFastOpenQueueSize = 0; + int tcpListenQueueSize = 0; + size_t maxInFlightQueriesPerConn = 0; + size_t tcpMaxConcurrentConnections = 0; + std::string interface; + std::set cpus; + std::vector certKeys; - parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus, tcpListenQueueSize, maxInFlightQueriesPerConn, tcpMaxConcurrentConnections); + parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus, tcpListenQueueSize, maxInFlightQueriesPerConn, tcpMaxConcurrentConnections); - if (certFiles.type() == typeid(std::string) && keyFiles.type() == typeid(std::string)) { - auto certFile = boost::get(certFiles); - auto keyFile = boost::get(keyFiles); - certKeys.push_back({certFile, keyFile}); - } - else if (certFiles.type() == typeid(std::vector>) && keyFiles.type() == typeid(std::vector>)) { - auto certFilesVect = boost::get>>(certFiles); - auto keyFilesVect = boost::get>>(keyFiles); - if (certFilesVect.size() == keyFilesVect.size()) { - for (size_t idx = 0; idx < certFilesVect.size(); idx++) { - certKeys.push_back({certFilesVect.at(idx).second, keyFilesVect.at(idx).second}); - } - } - else { - errlog("Error, mismatching number of certificates and keys in call to addDNSCryptBind!"); - g_outputBuffer="Error, mismatching number of certificates and keys in call to addDNSCryptBind()!"; - return; + if (certFiles.type() == typeid(std::string) && keyFiles.type() == typeid(std::string)) { + auto certFile = boost::get(certFiles); + auto keyFile = boost::get(keyFiles); + certKeys.push_back({certFile, keyFile}); + } + else if (certFiles.type() == typeid(std::vector>) && keyFiles.type() == typeid(std::vector>)) { + auto certFilesVect = boost::get>>(certFiles); + auto keyFilesVect = boost::get>>(keyFiles); + if (certFilesVect.size() == keyFilesVect.size()) { + for (size_t idx = 0; idx < certFilesVect.size(); idx++) { + certKeys.push_back({certFilesVect.at(idx).second, keyFilesVect.at(idx).second}); } } else { - errlog("Error, mismatching number of certificates and keys in call to addDNSCryptBind()!"); - g_outputBuffer="Error, mismatching number of certificates and keys in call to addDNSCryptBind()!"; + errlog("Error, mismatching number of certificates and keys in call to addDNSCryptBind!"); + g_outputBuffer = "Error, mismatching number of certificates and keys in call to addDNSCryptBind()!"; return; } + } + else { + errlog("Error, mismatching number of certificates and keys in call to addDNSCryptBind()!"); + g_outputBuffer = "Error, mismatching number of certificates and keys in call to addDNSCryptBind()!"; + return; + } - try { - auto ctx = std::make_shared(providerName, certKeys); - - /* UDP */ - auto cs = std::make_unique(ComboAddress(addr, 443), false, reusePort, tcpFastOpenQueueSize, interface, cpus); - cs->dnscryptCtx = ctx; - g_dnsCryptLocals.push_back(ctx); - g_frontends.push_back(std::move(cs)); - - /* TCP */ - cs = std::make_unique(ComboAddress(addr, 443), true, reusePort, tcpFastOpenQueueSize, interface, cpus); - cs->dnscryptCtx = ctx; - if (tcpListenQueueSize > 0) { - cs->tcpListenQueueSize = tcpListenQueueSize; - } - if (maxInFlightQueriesPerConn > 0) { - cs->d_maxInFlightQueriesPerConn = maxInFlightQueriesPerConn; - } - if (tcpMaxConcurrentConnections > 0) { - cs->d_tcpConcurrentConnectionsLimit = tcpMaxConcurrentConnections; - } + try { + auto ctx = std::make_shared(providerName, certKeys); + + /* UDP */ + auto cs = std::make_unique(ComboAddress(addr, 443), false, reusePort, tcpFastOpenQueueSize, interface, cpus); + cs->dnscryptCtx = ctx; + g_dnsCryptLocals.push_back(ctx); + g_frontends.push_back(std::move(cs)); - g_frontends.push_back(std::move(cs)); + /* TCP */ + cs = std::make_unique(ComboAddress(addr, 443), true, reusePort, tcpFastOpenQueueSize, interface, cpus); + cs->dnscryptCtx = ctx; + if (tcpListenQueueSize > 0) { + cs->tcpListenQueueSize = tcpListenQueueSize; } - catch(std::exception& e) { - errlog(e.what()); - g_outputBuffer="Error: "+string(e.what())+"\n"; + if (maxInFlightQueriesPerConn > 0) { + cs->d_maxInFlightQueriesPerConn = maxInFlightQueriesPerConn; } + if (tcpMaxConcurrentConnections > 0) { + cs->d_tcpConcurrentConnectionsLimit = tcpMaxConcurrentConnections; + } + + g_frontends.push_back(std::move(cs)); + } + catch (std::exception& e) { + errlog(e.what()); + g_outputBuffer = "Error: " + string(e.what()) + "\n"; + } #else - g_outputBuffer="Error: DNSCrypt support is not enabled.\n"; + g_outputBuffer = "Error: DNSCrypt support is not enabled.\n"; #endif - - }); + }); luaCtx.writeFunction("showDNSCryptBinds", []() { - setLuaNoSideEffect(); + setLuaNoSideEffect(); #ifdef HAVE_DNSCRYPT - ostringstream ret; - boost::format fmt("%1$-3d %2% %|25t|%3$-20.20s"); - ret << (fmt % "#" % "Address" % "Provider Name") << endl; - size_t idx = 0; - - std::unordered_set> contexts; - for (const auto& frontend : g_frontends) { - const std::shared_ptr ctx = frontend->dnscryptCtx; - if (!ctx || contexts.count(ctx) != 0) { - continue; - } - contexts.insert(ctx); - ret<< (fmt % idx % frontend->local.toStringWithPort() % ctx->getProviderName()) << endl; - idx++; - } + ostringstream ret; + boost::format fmt("%1$-3d %2% %|25t|%3$-20.20s"); + ret << (fmt % "#" % "Address" % "Provider Name") << endl; + size_t idx = 0; + + std::unordered_set> contexts; + for (const auto& frontend : g_frontends) { + const std::shared_ptr ctx = frontend->dnscryptCtx; + if (!ctx || contexts.count(ctx) != 0) { + continue; + } + contexts.insert(ctx); + ret << (fmt % idx % frontend->local.toStringWithPort() % ctx->getProviderName()) << endl; + idx++; + } - g_outputBuffer=ret.str(); + g_outputBuffer = ret.str(); #else - g_outputBuffer="Error: DNSCrypt support is not enabled.\n"; + g_outputBuffer = "Error: DNSCrypt support is not enabled.\n"; #endif - }); + }); luaCtx.writeFunction("getDNSCryptBind", [](size_t idx) { - setLuaNoSideEffect(); + setLuaNoSideEffect(); #ifdef HAVE_DNSCRYPT - std::shared_ptr ret = nullptr; - if (idx < g_dnsCryptLocals.size()) { - ret = g_dnsCryptLocals.at(idx); - } - return ret; + std::shared_ptr ret = nullptr; + if (idx < g_dnsCryptLocals.size()) { + ret = g_dnsCryptLocals.at(idx); + } + return ret; #else - g_outputBuffer="Error: DNSCrypt support is not enabled.\n"; + g_outputBuffer = "Error: DNSCrypt support is not enabled.\n"; #endif - }); + }); luaCtx.writeFunction("getDNSCryptBindCount", []() { - setLuaNoSideEffect(); - return g_dnsCryptLocals.size(); - }); + setLuaNoSideEffect(); + return g_dnsCryptLocals.size(); + }); luaCtx.writeFunction("generateDNSCryptProviderKeys", [client](const std::string& publicKeyFile, const std::string privateKeyFile) { - setLuaNoSideEffect(); + setLuaNoSideEffect(); #ifdef HAVE_DNSCRYPT - if (client) { - return; - } - unsigned char publicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE]; - unsigned char privateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE]; - sodium_mlock(privateKey, sizeof(privateKey)); + if (client) { + return; + } + unsigned char publicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE]; + unsigned char privateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE]; + sodium_mlock(privateKey, sizeof(privateKey)); - try { - DNSCryptContext::generateProviderKeys(publicKey, privateKey); + try { + DNSCryptContext::generateProviderKeys(publicKey, privateKey); - ofstream pubKStream(publicKeyFile); - pubKStream.write((char*) publicKey, sizeof(publicKey)); - pubKStream.close(); + ofstream pubKStream(publicKeyFile); + pubKStream.write((char*)publicKey, sizeof(publicKey)); + pubKStream.close(); - ofstream privKStream(privateKeyFile); - privKStream.write((char*) privateKey, sizeof(privateKey)); - privKStream.close(); + ofstream privKStream(privateKeyFile); + privKStream.write((char*)privateKey, sizeof(privateKey)); + privKStream.close(); - g_outputBuffer="Provider fingerprint is: " + DNSCryptContext::getProviderFingerprint(publicKey) + "\n"; - } - catch(std::exception& e) { - errlog(e.what()); - g_outputBuffer="Error: "+string(e.what())+"\n"; - } + g_outputBuffer = "Provider fingerprint is: " + DNSCryptContext::getProviderFingerprint(publicKey) + "\n"; + } + catch (std::exception& e) { + errlog(e.what()); + g_outputBuffer = "Error: " + string(e.what()) + "\n"; + } - sodium_memzero(privateKey, sizeof(privateKey)); - sodium_munlock(privateKey, sizeof(privateKey)); + sodium_memzero(privateKey, sizeof(privateKey)); + sodium_munlock(privateKey, sizeof(privateKey)); #else - g_outputBuffer="Error: DNSCrypt support is not enabled.\n"; + g_outputBuffer = "Error: DNSCrypt support is not enabled.\n"; #endif - }); + }); luaCtx.writeFunction("printDNSCryptProviderFingerprint", [](const std::string& publicKeyFile) { - setLuaNoSideEffect(); + setLuaNoSideEffect(); #ifdef HAVE_DNSCRYPT - unsigned char publicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE]; + unsigned char publicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE]; - try { - ifstream file(publicKeyFile); - file.read((char *) &publicKey, sizeof(publicKey)); + try { + ifstream file(publicKeyFile); + file.read((char*)&publicKey, sizeof(publicKey)); - if (file.fail()) - throw std::runtime_error("Invalid dnscrypt provider public key file " + publicKeyFile); + if (file.fail()) + throw std::runtime_error("Invalid dnscrypt provider public key file " + publicKeyFile); - file.close(); - g_outputBuffer="Provider fingerprint is: " + DNSCryptContext::getProviderFingerprint(publicKey) + "\n"; - } - catch(std::exception& e) { - errlog(e.what()); - g_outputBuffer="Error: "+string(e.what())+"\n"; - } + file.close(); + g_outputBuffer = "Provider fingerprint is: " + DNSCryptContext::getProviderFingerprint(publicKey) + "\n"; + } + catch (std::exception& e) { + errlog(e.what()); + g_outputBuffer = "Error: " + string(e.what()) + "\n"; + } #else - g_outputBuffer="Error: DNSCrypt support is not enabled.\n"; + g_outputBuffer = "Error: DNSCrypt support is not enabled.\n"; #endif - }); + }); #ifdef HAVE_DNSCRYPT luaCtx.writeFunction("generateDNSCryptCertificate", [client](const std::string& providerPrivateKeyFile, const std::string& certificateFile, const std::string privateKeyFile, uint32_t serial, time_t begin, time_t end, boost::optional version) { - setLuaNoSideEffect(); - if (client) { - return; - } - DNSCryptPrivateKey privateKey; - DNSCryptCert cert; + setLuaNoSideEffect(); + if (client) { + return; + } + DNSCryptPrivateKey privateKey; + DNSCryptCert cert; - try { - if (generateDNSCryptCertificate(providerPrivateKeyFile, serial, begin, end, version ? *version : DNSCryptExchangeVersion::VERSION1, cert, privateKey)) { - privateKey.saveToFile(privateKeyFile); - DNSCryptContext::saveCertFromFile(cert, certificateFile); - } + try { + if (generateDNSCryptCertificate(providerPrivateKeyFile, serial, begin, end, version ? *version : DNSCryptExchangeVersion::VERSION1, cert, privateKey)) { + privateKey.saveToFile(privateKeyFile); + DNSCryptContext::saveCertFromFile(cert, certificateFile); } - catch(const std::exception& e) { - errlog(e.what()); - g_outputBuffer="Error: "+string(e.what())+"\n"; - } - }); + } + catch (const std::exception& e) { + errlog(e.what()); + g_outputBuffer = "Error: " + string(e.what()) + "\n"; + } + }); #endif luaCtx.writeFunction("showPools", []() { - setLuaNoSideEffect(); - try { - ostringstream ret; - boost::format fmt("%1$-20.20s %|25t|%2$20s %|25t|%3$20s %|50t|%4%" ); - // 1 2 3 4 - ret << (fmt % "Name" % "Cache" % "ServerPolicy" % "Servers" ) << endl; - - const auto localPools = g_pools.getCopy(); - for (const auto& entry : localPools) { - const string& name = entry.first; - const std::shared_ptr pool = entry.second; - string cache = pool->packetCache != nullptr ? pool->packetCache->toString() : ""; - string policy = g_policy.getLocal()->getName(); - if (pool->policy != nullptr) { - policy = pool->policy->getName(); + setLuaNoSideEffect(); + try { + ostringstream ret; + boost::format fmt("%1$-20.20s %|25t|%2$20s %|25t|%3$20s %|50t|%4%"); + // 1 2 3 4 + ret << (fmt % "Name" % "Cache" % "ServerPolicy" % "Servers") << endl; + + const auto localPools = g_pools.getCopy(); + for (const auto& entry : localPools) { + const string& name = entry.first; + const std::shared_ptr pool = entry.second; + string cache = pool->packetCache != nullptr ? pool->packetCache->toString() : ""; + string policy = g_policy.getLocal()->getName(); + if (pool->policy != nullptr) { + policy = pool->policy->getName(); + } + string servers; + + const auto poolServers = pool->getServers(); + for (const auto& server : *poolServers) { + if (!servers.empty()) { + servers += ", "; } - string servers; - - const auto poolServers = pool->getServers(); - for (const auto& server: *poolServers) { - if (!servers.empty()) { - servers += ", "; - } - if (!server.second->getName().empty()) { - servers += server.second->getName(); - servers += " "; - } - servers += server.second->remote.toStringWithPort(); + if (!server.second->getName().empty()) { + servers += server.second->getName(); + servers += " "; } - - ret << (fmt % name % cache % policy % servers) << endl; + servers += server.second->remote.toStringWithPort(); } - g_outputBuffer=ret.str(); - }catch(std::exception& e) { g_outputBuffer=e.what(); throw; } - }); - luaCtx.writeFunction("getPool", [client](const string& poolName) { - if (client) { - return std::make_shared(); + ret << (fmt % name % cache % policy % servers) << endl; } - auto localPools = g_pools.getCopy(); - std::shared_ptr pool = createPoolIfNotExists(localPools, poolName); - g_pools.setState(localPools); - return pool; - }); + g_outputBuffer = ret.str(); + } + catch (std::exception& e) { + g_outputBuffer = e.what(); + throw; + } + }); + + luaCtx.writeFunction("getPool", [client](const string& poolName) { + if (client) { + return std::make_shared(); + } + auto localPools = g_pools.getCopy(); + std::shared_ptr pool = createPoolIfNotExists(localPools, poolName); + g_pools.setState(localPools); + return pool; + }); - luaCtx.writeFunction("setVerboseHealthChecks", [](bool verbose) { g_verboseHealthChecks=verbose; }); + luaCtx.writeFunction("setVerboseHealthChecks", [](bool verbose) { g_verboseHealthChecks = verbose; }); luaCtx.writeFunction("setStaleCacheEntriesTTL", [](uint32_t ttl) { g_staleCacheEntriesTTL = ttl; }); luaCtx.writeFunction("showBinds", []() { - setLuaNoSideEffect(); - try { - ostringstream ret; - boost::format fmt("%1$-3d %2$-20.20s %|35t|%3$-20.20s %|57t|%4%" ); - // 1 2 3 4 - ret << (fmt % "#" % "Address" % "Protocol" % "Queries" ) << endl; - - size_t counter = 0; - for (const auto& front : g_frontends) { - ret << (fmt % counter % front->local.toStringWithPort() % front->getType() % front->queries) << endl; - counter++; - } - g_outputBuffer=ret.str(); - }catch(std::exception& e) { g_outputBuffer=e.what(); throw; } - }); + setLuaNoSideEffect(); + try { + ostringstream ret; + boost::format fmt("%1$-3d %2$-20.20s %|35t|%3$-20.20s %|57t|%4%"); + // 1 2 3 4 + ret << (fmt % "#" % "Address" % "Protocol" % "Queries") << endl; - luaCtx.writeFunction("getBind", [](size_t num) { - setLuaNoSideEffect(); - ClientState* ret = nullptr; - if(num < g_frontends.size()) { - ret=g_frontends[num].get(); + size_t counter = 0; + for (const auto& front : g_frontends) { + ret << (fmt % counter % front->local.toStringWithPort() % front->getType() % front->queries) << endl; + counter++; } - return ret; - }); + g_outputBuffer = ret.str(); + } + catch (std::exception& e) { + g_outputBuffer = e.what(); + throw; + } + }); + + luaCtx.writeFunction("getBind", [](size_t num) { + setLuaNoSideEffect(); + ClientState* ret = nullptr; + if (num < g_frontends.size()) { + ret = g_frontends[num].get(); + } + return ret; + }); luaCtx.writeFunction("getBindCount", []() { - setLuaNoSideEffect(); - return g_frontends.size(); - }); + setLuaNoSideEffect(); + return g_frontends.size(); + }); luaCtx.writeFunction("help", [](boost::optional command) { - setLuaNoSideEffect(); - g_outputBuffer = ""; - for (const auto& keyword : g_consoleKeywords) { - if (!command) { - g_outputBuffer += keyword.toString() + "\n"; - } - else if (keyword.name == command) { - g_outputBuffer = keyword.toString() + "\n"; - return; - } - } - if (command) { - g_outputBuffer = "Nothing found for " + *command + "\n"; + setLuaNoSideEffect(); + g_outputBuffer = ""; + for (const auto& keyword : g_consoleKeywords) { + if (!command) { + g_outputBuffer += keyword.toString() + "\n"; + } + else if (keyword.name == command) { + g_outputBuffer = keyword.toString() + "\n"; + return; } - }); + } + if (command) { + g_outputBuffer = "Nothing found for " + *command + "\n"; + } + }); luaCtx.writeFunction("showVersion", []() { - setLuaNoSideEffect(); - g_outputBuffer = "dnsdist " + std::string(VERSION) + "\n"; - }); + setLuaNoSideEffect(); + g_outputBuffer = "dnsdist " + std::string(VERSION) + "\n"; + }); luaCtx.writeFunction("showSecurityStatus", []() { - setLuaNoSideEffect(); - g_outputBuffer = std::to_string(g_stats.securityStatus) + "\n"; - }); + setLuaNoSideEffect(); + g_outputBuffer = std::to_string(g_stats.securityStatus) + "\n"; + }); #ifdef HAVE_EBPF luaCtx.writeFunction("setDefaultBPFFilter", [](std::shared_ptr bpf) { - if (g_configurationDone) { - g_outputBuffer="setDefaultBPFFilter() cannot be used at runtime!\n"; - return; - } - g_defaultBPFFilter = bpf; - }); + if (g_configurationDone) { + g_outputBuffer = "setDefaultBPFFilter() cannot be used at runtime!\n"; + return; + } + g_defaultBPFFilter = bpf; + }); luaCtx.writeFunction("registerDynBPFFilter", [](std::shared_ptr dbpf) { - if (dbpf) { - g_dynBPFFilters.push_back(dbpf); - } - }); + if (dbpf) { + g_dynBPFFilters.push_back(dbpf); + } + }); luaCtx.writeFunction("unregisterDynBPFFilter", [](std::shared_ptr dbpf) { - if (dbpf) { - for (auto it = g_dynBPFFilters.begin(); it != g_dynBPFFilters.end(); it++) { - if (*it == dbpf) { - g_dynBPFFilters.erase(it); - break; - } + if (dbpf) { + for (auto it = g_dynBPFFilters.begin(); it != g_dynBPFFilters.end(); it++) { + if (*it == dbpf) { + g_dynBPFFilters.erase(it); + break; } } - }); + } + }); - luaCtx.writeFunction("addBPFFilterDynBlocks", [](const std::unordered_map& m, std::shared_ptr dynbpf, boost::optional seconds, boost::optional msg) { - if (!dynbpf) { - return; - } - setLuaSideEffect(); - struct timespec until, now; - clock_gettime(CLOCK_MONOTONIC, &now); - until=now; - int actualSeconds = seconds ? *seconds : 10; - until.tv_sec += actualSeconds; - for(const auto& capair : m) { - if (dynbpf->block(capair.first, until)) { - warnlog("Inserting eBPF dynamic block for %s for %d seconds: %s", capair.first.toString(), actualSeconds, msg ? *msg : ""); - } + luaCtx.writeFunction("addBPFFilterDynBlocks", [](const std::unordered_map& m, std::shared_ptr dynbpf, boost::optional seconds, boost::optional msg) { + if (!dynbpf) { + return; + } + setLuaSideEffect(); + struct timespec until, now; + clock_gettime(CLOCK_MONOTONIC, &now); + until = now; + int actualSeconds = seconds ? *seconds : 10; + until.tv_sec += actualSeconds; + for (const auto& capair : m) { + if (dynbpf->block(capair.first, until)) { + warnlog("Inserting eBPF dynamic block for %s for %d seconds: %s", capair.first.toString(), actualSeconds, msg ? *msg : ""); } - }); + } + }); #endif /* HAVE_EBPF */ - luaCtx.writeFunction()>("getStatisticsCounters", []() { - setLuaNoSideEffect(); - std::unordered_map res; - for(const auto& entry : g_stats.entries) { - if(const auto& val = boost::get(&entry.second)) - res[entry.first] = (*val)->load(); - } - return res; - }); + luaCtx.writeFunction()>("getStatisticsCounters", []() { + setLuaNoSideEffect(); + std::unordered_map res; + for (const auto& entry : g_stats.entries) { + if (const auto& val = boost::get(&entry.second)) + res[entry.first] = (*val)->load(); + } + return res; + }); luaCtx.writeFunction("includeDirectory", [&luaCtx](const std::string& dirname) { - if (g_configurationDone) { - errlog("includeDirectory() cannot be used at runtime!"); - g_outputBuffer="includeDirectory() cannot be used at runtime!\n"; - return; - } + if (g_configurationDone) { + errlog("includeDirectory() cannot be used at runtime!"); + g_outputBuffer = "includeDirectory() cannot be used at runtime!\n"; + return; + } - if (g_included) { - errlog("includeDirectory() cannot be used recursively!"); - g_outputBuffer="includeDirectory() cannot be used recursively!\n"; - return; - } + if (g_included) { + errlog("includeDirectory() cannot be used recursively!"); + g_outputBuffer = "includeDirectory() cannot be used recursively!\n"; + return; + } - struct stat st; - if (stat(dirname.c_str(), &st)) { - errlog("The included directory %s does not exist!", dirname.c_str()); - g_outputBuffer="The included directory " + dirname + " does not exist!"; - return; - } + struct stat st; + if (stat(dirname.c_str(), &st)) { + errlog("The included directory %s does not exist!", dirname.c_str()); + g_outputBuffer = "The included directory " + dirname + " does not exist!"; + return; + } - if (!S_ISDIR(st.st_mode)) { - errlog("The included directory %s is not a directory!", dirname.c_str()); - g_outputBuffer="The included directory " + dirname + " is not a directory!"; - return; - } + if (!S_ISDIR(st.st_mode)) { + errlog("The included directory %s is not a directory!", dirname.c_str()); + g_outputBuffer = "The included directory " + dirname + " is not a directory!"; + return; + } - DIR *dirp; - struct dirent *ent; - std::list files; - if (!(dirp = opendir(dirname.c_str()))) { - errlog("Error opening the included directory %s!", dirname.c_str()); - g_outputBuffer="Error opening the included directory " + dirname + "!"; - return; + DIR* dirp; + struct dirent* ent; + std::list files; + if (!(dirp = opendir(dirname.c_str()))) { + errlog("Error opening the included directory %s!", dirname.c_str()); + g_outputBuffer = "Error opening the included directory " + dirname + "!"; + return; + } + + while ((ent = readdir(dirp)) != NULL) { + if (ent->d_name[0] == '.') { + continue; } - while((ent = readdir(dirp)) != NULL) { - if (ent->d_name[0] == '.') { + if (boost::ends_with(ent->d_name, ".conf")) { + std::ostringstream namebuf; + namebuf << dirname.c_str() << "/" << ent->d_name; + + if (stat(namebuf.str().c_str(), &st) || !S_ISREG(st.st_mode)) { continue; } - if (boost::ends_with(ent->d_name, ".conf")) { - std::ostringstream namebuf; - namebuf << dirname.c_str() << "/" << ent->d_name; - - if (stat(namebuf.str().c_str(), &st) || !S_ISREG(st.st_mode)) { - continue; - } - - files.push_back(namebuf.str()); - } + files.push_back(namebuf.str()); } + } - closedir(dirp); - files.sort(); + closedir(dirp); + files.sort(); - g_included = true; + g_included = true; - for (auto file = files.begin(); file != files.end(); ++file) { - std::ifstream ifs(*file); - if (!ifs) { - warnlog("Unable to read configuration from '%s'", *file); - } else { - vinfolog("Read configuration from '%s'", *file); - } + for (auto file = files.begin(); file != files.end(); ++file) { + std::ifstream ifs(*file); + if (!ifs) { + warnlog("Unable to read configuration from '%s'", *file); + } + else { + vinfolog("Read configuration from '%s'", *file); + } - try { - luaCtx.executeCode(ifs); - } - catch (...) { - g_included = false; - throw; - } + try { + luaCtx.executeCode(ifs); + } + catch (...) { + g_included = false; + throw; } - g_included = false; - }); + luaCtx.executeCode(ifs); + } + + g_included = false; + }); luaCtx.writeFunction("setAPIWritable", [](bool writable, boost::optional apiConfigDir) { - setLuaSideEffect(); - g_apiReadWrite = writable; - if (apiConfigDir) { - if (!(*apiConfigDir).empty()) { - g_apiConfigDirectory = *apiConfigDir; - } - else { - errlog("The API configuration directory value cannot be empty!"); - g_outputBuffer="The API configuration directory value cannot be empty!"; - } + setLuaSideEffect(); + g_apiReadWrite = writable; + if (apiConfigDir) { + if (!(*apiConfigDir).empty()) { + g_apiConfigDirectory = *apiConfigDir; } - }); + else { + errlog("The API configuration directory value cannot be empty!"); + g_outputBuffer = "The API configuration directory value cannot be empty!"; + } + } + }); luaCtx.writeFunction("setServFailWhenNoServer", [](bool servfail) { - setLuaSideEffect(); - g_servFailOnNoPolicy = servfail; - }); + setLuaSideEffect(); + g_servFailOnNoPolicy = servfail; + }); luaCtx.writeFunction("setRoundRobinFailOnNoServer", [](bool fail) { - setLuaSideEffect(); - g_roundrobinFailOnNoServer = fail; - }); + setLuaSideEffect(); + g_roundrobinFailOnNoServer = fail; + }); luaCtx.writeFunction("setConsistentHashingBalancingFactor", [](double factor) { - setLuaSideEffect(); - if (factor >= 1.0) { - g_consistentHashBalancingFactor = factor; - } - else { - errlog("Invalid value passed to setConsistentHashingBalancingFactor()!"); - g_outputBuffer="Invalid value passed to setConsistentHashingBalancingFactor()!\n"; - return; - } - }); + setLuaSideEffect(); + if (factor >= 1.0) { + g_consistentHashBalancingFactor = factor; + } + else { + errlog("Invalid value passed to setConsistentHashingBalancingFactor()!"); + g_outputBuffer = "Invalid value passed to setConsistentHashingBalancingFactor()!\n"; + return; + } + }); luaCtx.writeFunction("setWeightedBalancingFactor", [](double factor) { - setLuaSideEffect(); - if (factor >= 1.0) { - g_weightedBalancingFactor = factor; - } - else { - errlog("Invalid value passed to setWeightedBalancingFactor()!"); - g_outputBuffer="Invalid value passed to setWeightedBalancingFactor()!\n"; - return; - } - }); + setLuaSideEffect(); + if (factor >= 1.0) { + g_weightedBalancingFactor = factor; + } + else { + errlog("Invalid value passed to setWeightedBalancingFactor()!"); + g_outputBuffer = "Invalid value passed to setWeightedBalancingFactor()!\n"; + return; + } + }); luaCtx.writeFunction("setRingBuffersSize", [client](size_t capacity, boost::optional numberOfShards) { - setLuaSideEffect(); - if (g_configurationDone) { - errlog("setRingBuffersSize() cannot be used at runtime!"); - g_outputBuffer="setRingBuffersSize() cannot be used at runtime!\n"; - return; - } - if (!client) { - g_rings.setCapacity(capacity, numberOfShards ? *numberOfShards : 10); - } - else { - g_rings.setCapacity(0, 1); - } - }); + setLuaSideEffect(); + if (g_configurationDone) { + errlog("setRingBuffersSize() cannot be used at runtime!"); + g_outputBuffer = "setRingBuffersSize() cannot be used at runtime!\n"; + return; + } + if (!client) { + g_rings.setCapacity(capacity, numberOfShards ? *numberOfShards : 10); + } + else { + g_rings.setCapacity(0, 1); + } + }); luaCtx.writeFunction("setRingBuffersLockRetries", [](size_t retries) { - setLuaSideEffect(); - g_rings.setNumberOfLockRetries(retries); - }); + setLuaSideEffect(); + g_rings.setNumberOfLockRetries(retries); + }); luaCtx.writeFunction("setWHashedPertubation", [](uint32_t pertub) { - setLuaSideEffect(); - g_hashperturb = pertub; - }); + setLuaSideEffect(); + g_hashperturb = pertub; + }); luaCtx.writeFunction("setTCPInternalPipeBufferSize", [](size_t size) { g_tcpInternalPipeBufferSize = size; }); - luaCtx.writeFunction("snmpAgent", [client,configCheck](bool enableTraps, boost::optional daemonSocket) { - if(client || configCheck) - return; + luaCtx.writeFunction("snmpAgent", [client, configCheck](bool enableTraps, boost::optional daemonSocket) { + if (client || configCheck) + return; #ifdef HAVE_NET_SNMP - if (g_configurationDone) { - errlog("snmpAgent() cannot be used at runtime!"); - g_outputBuffer="snmpAgent() cannot be used at runtime!\n"; - return; - } + if (g_configurationDone) { + errlog("snmpAgent() cannot be used at runtime!"); + g_outputBuffer = "snmpAgent() cannot be used at runtime!\n"; + return; + } - if (g_snmpEnabled) { - errlog("snmpAgent() cannot be used twice!"); - g_outputBuffer="snmpAgent() cannot be used twice!\n"; - return; - } + if (g_snmpEnabled) { + errlog("snmpAgent() cannot be used twice!"); + g_outputBuffer = "snmpAgent() cannot be used twice!\n"; + return; + } - g_snmpEnabled = true; - g_snmpTrapsEnabled = enableTraps; - g_snmpAgent = new DNSDistSNMPAgent("dnsdist", daemonSocket ? *daemonSocket : std::string()); + g_snmpEnabled = true; + g_snmpTrapsEnabled = enableTraps; + g_snmpAgent = new DNSDistSNMPAgent("dnsdist", daemonSocket ? *daemonSocket : std::string()); #else errlog("NET SNMP support is required to use snmpAgent()"); - g_outputBuffer="NET SNMP support is required to use snmpAgent()\n"; + g_outputBuffer = "NET SNMP support is required to use snmpAgent()\n"; #endif /* HAVE_NET_SNMP */ - }); + }); luaCtx.writeFunction("sendCustomTrap", [](const std::string& str) { - if (g_snmpAgent && g_snmpTrapsEnabled) { - g_snmpAgent->sendCustomTrap(str); - } - }); + if (g_snmpAgent && g_snmpTrapsEnabled) { + g_snmpAgent->sendCustomTrap(str); + } + }); luaCtx.writeFunction("setServerPolicy", [](const ServerPolicy& policy) { - setLuaSideEffect(); - g_policy.setState(policy); - }); + setLuaSideEffect(); + g_policy.setState(policy); + }); luaCtx.writeFunction("setServerPolicyLua", [](string name, ServerPolicy::policyfunc_t policy) { - setLuaSideEffect(); - g_policy.setState(ServerPolicy{name, policy, true}); - }); + setLuaSideEffect(); + g_policy.setState(ServerPolicy{name, policy, true}); + }); luaCtx.writeFunction("setServerPolicyLuaFFI", [](string name, ServerPolicy::ffipolicyfunc_t policy) { - setLuaSideEffect(); - auto pol = ServerPolicy(name, policy); - g_policy.setState(std::move(pol)); - }); + setLuaSideEffect(); + auto pol = ServerPolicy(name, policy); + g_policy.setState(std::move(pol)); + }); luaCtx.writeFunction("setServerPolicyLuaFFIPerThread", [](string name, const std::string& policyCode) { - setLuaSideEffect(); - auto pol = ServerPolicy(name, policyCode); - g_policy.setState(std::move(pol)); - }); + setLuaSideEffect(); + auto pol = ServerPolicy(name, policyCode); + g_policy.setState(std::move(pol)); + }); luaCtx.writeFunction("showServerPolicy", []() { - setLuaSideEffect(); - g_outputBuffer=g_policy.getLocal()->getName()+"\n"; - }); + setLuaSideEffect(); + g_outputBuffer = g_policy.getLocal()->getName() + "\n"; + }); luaCtx.writeFunction("setPoolServerPolicy", [](ServerPolicy policy, string pool) { - setLuaSideEffect(); - auto localPools = g_pools.getCopy(); - setPoolPolicy(localPools, pool, std::make_shared(policy)); - g_pools.setState(localPools); - }); + setLuaSideEffect(); + auto localPools = g_pools.getCopy(); + setPoolPolicy(localPools, pool, std::make_shared(policy)); + g_pools.setState(localPools); + }); luaCtx.writeFunction("setPoolServerPolicyLua", [](string name, ServerPolicy::policyfunc_t policy, string pool) { - setLuaSideEffect(); - auto localPools = g_pools.getCopy(); - setPoolPolicy(localPools, pool, std::make_shared(ServerPolicy{name, policy, true})); - g_pools.setState(localPools); - }); + setLuaSideEffect(); + auto localPools = g_pools.getCopy(); + setPoolPolicy(localPools, pool, std::make_shared(ServerPolicy{name, policy, true})); + g_pools.setState(localPools); + }); luaCtx.writeFunction("setPoolServerPolicyLuaFFI", [](string name, ServerPolicy::ffipolicyfunc_t policy, string pool) { - setLuaSideEffect(); - auto localPools = g_pools.getCopy(); - setPoolPolicy(localPools, pool, std::make_shared(ServerPolicy{name, policy})); - g_pools.setState(localPools); - }); + setLuaSideEffect(); + auto localPools = g_pools.getCopy(); + setPoolPolicy(localPools, pool, std::make_shared(ServerPolicy{name, policy})); + g_pools.setState(localPools); + }); luaCtx.writeFunction("setPoolServerPolicyLuaFFIPerThread", [](string name, const std::string& policyCode, string pool) { - setLuaSideEffect(); - auto localPools = g_pools.getCopy(); - setPoolPolicy(localPools, pool, std::make_shared(ServerPolicy{name, policyCode})); - g_pools.setState(localPools); - }); + setLuaSideEffect(); + auto localPools = g_pools.getCopy(); + setPoolPolicy(localPools, pool, std::make_shared(ServerPolicy{name, policyCode})); + g_pools.setState(localPools); + }); luaCtx.writeFunction("showPoolServerPolicy", [](string pool) { - setLuaSideEffect(); - auto localPools = g_pools.getCopy(); - auto poolObj = getPool(localPools, pool); - if (poolObj->policy == nullptr) { - g_outputBuffer=g_policy.getLocal()->getName()+"\n"; - } else { - g_outputBuffer=poolObj->policy->getName()+"\n"; - } - }); + setLuaSideEffect(); + auto localPools = g_pools.getCopy(); + auto poolObj = getPool(localPools, pool); + if (poolObj->policy == nullptr) { + g_outputBuffer = g_policy.getLocal()->getName() + "\n"; + } + else { + g_outputBuffer = poolObj->policy->getName() + "\n"; + } + }); luaCtx.writeFunction("setTCPDownstreamCleanupInterval", [](uint16_t interval) { - setLuaSideEffect(); - DownstreamConnectionsManager::setCleanupInterval(interval); - }); + setLuaSideEffect(); + DownstreamConnectionsManager::setCleanupInterval(interval); + }); luaCtx.writeFunction("setConsoleConnectionsLogging", [](bool enabled) { - g_logConsoleConnections = enabled; - }); + g_logConsoleConnections = enabled; + }); luaCtx.writeFunction("setConsoleOutputMaxMsgSize", [](uint32_t size) { - g_consoleOutputMsgMaxSize = size; - }); + g_consoleOutputMsgMaxSize = size; + }); - luaCtx.writeFunction("setProxyProtocolACL", [](boost::variant>> inp) { + luaCtx.writeFunction("setProxyProtocolACL", [](boost::variant>> inp) { if (g_configurationDone) { errlog("setProxyProtocolACL() cannot be used at runtime!"); - g_outputBuffer="setProxyProtocolACL() cannot be used at runtime!\n"; + g_outputBuffer = "setProxyProtocolACL() cannot be used at runtime!\n"; return; } setLuaSideEffect(); @@ -2115,8 +2122,8 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) nmg.addMask(*str); } else { - for(const auto& p : boost::get>>(inp)) { - nmg.addMask(p.second); + for (const auto& p : boost::get>>(inp)) { + nmg.addMask(p.second); } } g_proxyProtocolACL = std::move(nmg); @@ -2125,7 +2132,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) luaCtx.writeFunction("setProxyProtocolApplyACLToProxiedClients", [](bool apply) { if (g_configurationDone) { errlog("setProxyProtocolApplyACLToProxiedClients() cannot be used at runtime!"); - g_outputBuffer="setProxyProtocolApplyACLToProxiedClients() cannot be used at runtime!\n"; + g_outputBuffer = "setProxyProtocolApplyACLToProxiedClients() cannot be used at runtime!\n"; return; } setLuaSideEffect(); @@ -2135,7 +2142,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) luaCtx.writeFunction("setProxyProtocolMaximumPayloadSize", [](size_t size) { if (g_configurationDone) { errlog("setProxyProtocolMaximumPayloadSize() cannot be used at runtime!"); - g_outputBuffer="setProxyProtocolMaximumPayloadSize() cannot be used at runtime!\n"; + g_outputBuffer = "setProxyProtocolMaximumPayloadSize() cannot be used at runtime!\n"; return; } setLuaSideEffect(); @@ -2143,112 +2150,111 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) }); luaCtx.writeFunction("setUDPMultipleMessagesVectorSize", [](size_t vSize) { - if (g_configurationDone) { - errlog("setUDPMultipleMessagesVectorSize() cannot be used at runtime!"); - g_outputBuffer="setUDPMultipleMessagesVectorSize() cannot be used at runtime!\n"; - return; - } + if (g_configurationDone) { + errlog("setUDPMultipleMessagesVectorSize() cannot be used at runtime!"); + g_outputBuffer = "setUDPMultipleMessagesVectorSize() cannot be used at runtime!\n"; + return; + } #if defined(HAVE_RECVMMSG) && defined(HAVE_SENDMMSG) && defined(MSG_WAITFORONE) - setLuaSideEffect(); - g_udpVectorSize = vSize; + setLuaSideEffect(); + g_udpVectorSize = vSize; #else errlog("recvmmsg() support is not available!"); - g_outputBuffer="recvmmsg support is not available!\n"; + g_outputBuffer = "recvmmsg support is not available!\n"; #endif - }); + }); luaCtx.writeFunction("setAddEDNSToSelfGeneratedResponses", [](bool add) { - g_addEDNSToSelfGeneratedResponses = add; + g_addEDNSToSelfGeneratedResponses = add; }); luaCtx.writeFunction("setPayloadSizeOnSelfGeneratedAnswers", [](uint16_t payloadSize) { - if (payloadSize < 512) { - warnlog("setPayloadSizeOnSelfGeneratedAnswers() is set too low, using 512 instead!"); - g_outputBuffer="setPayloadSizeOnSelfGeneratedAnswers() is set too low, using 512 instead!"; - payloadSize = 512; - } - if (payloadSize > s_udpIncomingBufferSize) { - warnlog("setPayloadSizeOnSelfGeneratedAnswers() is set too high, capping to %d instead!", s_udpIncomingBufferSize); - g_outputBuffer="setPayloadSizeOnSelfGeneratedAnswers() is set too high, capping to " + std::to_string(s_udpIncomingBufferSize) + " instead"; - payloadSize = s_udpIncomingBufferSize; - } - g_PayloadSizeSelfGenAnswers = payloadSize; + if (payloadSize < 512) { + warnlog("setPayloadSizeOnSelfGeneratedAnswers() is set too low, using 512 instead!"); + g_outputBuffer = "setPayloadSizeOnSelfGeneratedAnswers() is set too low, using 512 instead!"; + payloadSize = 512; + } + if (payloadSize > s_udpIncomingBufferSize) { + warnlog("setPayloadSizeOnSelfGeneratedAnswers() is set too high, capping to %d instead!", s_udpIncomingBufferSize); + g_outputBuffer = "setPayloadSizeOnSelfGeneratedAnswers() is set too high, capping to " + std::to_string(s_udpIncomingBufferSize) + " instead"; + payloadSize = s_udpIncomingBufferSize; + } + g_PayloadSizeSelfGenAnswers = payloadSize; }); luaCtx.writeFunction("setSecurityPollSuffix", [](const std::string& suffix) { - if (g_configurationDone) { - g_outputBuffer="setSecurityPollSuffix() cannot be used at runtime!\n"; - return; - } + if (g_configurationDone) { + g_outputBuffer = "setSecurityPollSuffix() cannot be used at runtime!\n"; + return; + } - g_secPollSuffix = suffix; + g_secPollSuffix = suffix; }); luaCtx.writeFunction("setSecurityPollInterval", [](time_t newInterval) { - if (newInterval <= 0) { - warnlog("setSecurityPollInterval() should be > 0, skipping"); - g_outputBuffer="setSecurityPollInterval() should be > 0, skipping"; - } + if (newInterval <= 0) { + warnlog("setSecurityPollInterval() should be > 0, skipping"); + g_outputBuffer = "setSecurityPollInterval() should be > 0, skipping"; + } - g_secPollInterval = newInterval; + g_secPollInterval = newInterval; }); - luaCtx.writeFunction("setSyslogFacility", [](boost::variant facility) { + luaCtx.writeFunction("setSyslogFacility", [](boost::variant facility) { setLuaSideEffect(); if (g_configurationDone) { - g_outputBuffer="setSyslogFacility cannot be used at runtime!\n"; + g_outputBuffer = "setSyslogFacility cannot be used at runtime!\n"; return; } if (facility.type() == typeid(std::string)) { static std::map const facilities = { - { "local0", LOG_LOCAL0 }, - { "log_local0", LOG_LOCAL0 }, - { "local1", LOG_LOCAL1 }, - { "log_local1", LOG_LOCAL1 }, - { "local2", LOG_LOCAL2 }, - { "log_local2", LOG_LOCAL2 }, - { "local3", LOG_LOCAL3 }, - { "log_local3", LOG_LOCAL3 }, - { "local4", LOG_LOCAL4 }, - { "log_local4", LOG_LOCAL4 }, - { "local5", LOG_LOCAL5 }, - { "log_local5", LOG_LOCAL5 }, - { "local6", LOG_LOCAL6 }, - { "log_local6", LOG_LOCAL6 }, - { "local7", LOG_LOCAL7 }, - { "log_local7", LOG_LOCAL7 }, + {"local0", LOG_LOCAL0}, + {"log_local0", LOG_LOCAL0}, + {"local1", LOG_LOCAL1}, + {"log_local1", LOG_LOCAL1}, + {"local2", LOG_LOCAL2}, + {"log_local2", LOG_LOCAL2}, + {"local3", LOG_LOCAL3}, + {"log_local3", LOG_LOCAL3}, + {"local4", LOG_LOCAL4}, + {"log_local4", LOG_LOCAL4}, + {"local5", LOG_LOCAL5}, + {"log_local5", LOG_LOCAL5}, + {"local6", LOG_LOCAL6}, + {"log_local6", LOG_LOCAL6}, + {"local7", LOG_LOCAL7}, + {"log_local7", LOG_LOCAL7}, /* most of these likely make very little sense for dnsdist, but why not? */ - { "kern", LOG_KERN }, - { "log_kern", LOG_KERN }, - { "user", LOG_USER }, - { "log_user", LOG_USER }, - { "mail", LOG_MAIL }, - { "log_mail", LOG_MAIL }, - { "daemon", LOG_DAEMON }, - { "log_daemon", LOG_DAEMON }, - { "auth", LOG_AUTH }, - { "log_auth", LOG_AUTH }, - { "syslog", LOG_SYSLOG }, - { "log_syslog", LOG_SYSLOG }, - { "lpr", LOG_LPR }, - { "log_lpr", LOG_LPR }, - { "news", LOG_NEWS }, - { "log_news", LOG_NEWS }, - { "uucp", LOG_UUCP }, - { "log_uucp", LOG_UUCP }, - { "cron", LOG_CRON }, - { "log_cron", LOG_CRON }, - { "authpriv", LOG_AUTHPRIV }, - { "log_authpriv", LOG_AUTHPRIV }, - { "ftp", LOG_FTP }, - { "log_ftp", LOG_FTP } - }; + {"kern", LOG_KERN}, + {"log_kern", LOG_KERN}, + {"user", LOG_USER}, + {"log_user", LOG_USER}, + {"mail", LOG_MAIL}, + {"log_mail", LOG_MAIL}, + {"daemon", LOG_DAEMON}, + {"log_daemon", LOG_DAEMON}, + {"auth", LOG_AUTH}, + {"log_auth", LOG_AUTH}, + {"syslog", LOG_SYSLOG}, + {"log_syslog", LOG_SYSLOG}, + {"lpr", LOG_LPR}, + {"log_lpr", LOG_LPR}, + {"news", LOG_NEWS}, + {"log_news", LOG_NEWS}, + {"uucp", LOG_UUCP}, + {"log_uucp", LOG_UUCP}, + {"cron", LOG_CRON}, + {"log_cron", LOG_CRON}, + {"authpriv", LOG_AUTHPRIV}, + {"log_authpriv", LOG_AUTHPRIV}, + {"ftp", LOG_FTP}, + {"log_ftp", LOG_FTP}}; auto facilityStr = boost::get(facility); toLowerInPlace(facilityStr); auto it = facilities.find(facilityStr); if (it == facilities.end()) { - g_outputBuffer="Unknown facility '" + facilityStr + "' passed to setSyslogFacility()!\n"; + g_outputBuffer = "Unknown facility '" + facilityStr + "' passed to setSyslogFacility()!\n"; return; } setSyslogFacility(it->second); @@ -2258,14 +2264,14 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) } }); - luaCtx.writeFunction("addDOHLocal", [client](const std::string& addr, boost::optional>>> certFiles, boost::optional>>> keyFiles, boost::optional > > > urls, boost::optional vars) { + luaCtx.writeFunction("addDOHLocal", [client](const std::string& addr, boost::optional>>> certFiles, boost::optional>>> keyFiles, boost::optional>>> urls, boost::optional vars) { if (client) { return; } #ifdef HAVE_DNS_OVER_HTTPS setLuaSideEffect(); if (g_configurationDone) { - g_outputBuffer="addDOHLocal cannot be used at runtime!\n"; + g_outputBuffer = "addDOHLocal cannot be used at runtime!\n"; return; } auto frontend = std::make_shared(); @@ -2286,9 +2292,9 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) if (urls->type() == typeid(std::string)) { frontend->d_urls.push_back(boost::get(*urls)); } - else if (urls->type() == typeid(std::vector>)) { - auto urlsVect = boost::get>>(*urls); - for(const auto& p : urlsVect) { + else if (urls->type() == typeid(std::vector>)) { + auto urlsVect = boost::get>>(*urls); + for (const auto& p : urlsVect) { frontend->d_urls.push_back(p.second); } } @@ -2317,7 +2323,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) } if (vars->count("customResponseHeaders")) { - for (auto const& headerMap : boost::get>((*vars)["customResponseHeaders"])) { + for (auto const& headerMap : boost::get>((*vars).at("customResponseHeaders"))) { frontend->d_customResponseHeaders.emplace_back(boost::to_lower_copy(headerMap.first), headerMap.second); } } @@ -2351,372 +2357,371 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) } g_frontends.push_back(std::move(cs)); #else - throw std::runtime_error("addDOHLocal() called but DNS over HTTPS support is not present!"); + throw std::runtime_error("addDOHLocal() called but DNS over HTTPS support is not present!"); #endif }); luaCtx.writeFunction("showDOHFrontends", []() { #ifdef HAVE_DNS_OVER_HTTPS - setLuaNoSideEffect(); - try { - ostringstream ret; - boost::format fmt("%-3d %-20.20s %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d"); - ret << (fmt % "#" % "Address" % "HTTP" % "HTTP/1" % "HTTP/2" % "GET" % "POST" % "Bad" % "Errors" % "Redirects" % "Valid" % "# ticket keys" % "Rotation delay" % "Next rotation") << endl; - size_t counter = 0; - for (const auto& ctx : g_dohlocals) { - ret << (fmt % counter % ctx->d_local.toStringWithPort() % ctx->d_httpconnects % ctx->d_http1Stats.d_nbQueries % ctx->d_http2Stats.d_nbQueries % ctx->d_getqueries % ctx->d_postqueries % ctx->d_badrequests % ctx->d_errorresponses % ctx->d_redirectresponses % ctx->d_validresponses % ctx->getTicketsKeysCount() % ctx->getTicketsKeyRotationDelay() % ctx->getNextTicketsKeyRotation()) << endl; - counter++; - } - g_outputBuffer = ret.str(); - } - catch(const std::exception& e) { - g_outputBuffer = e.what(); - throw; - } + setLuaNoSideEffect(); + try { + ostringstream ret; + boost::format fmt("%-3d %-20.20s %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d %-15d"); + ret << (fmt % "#" % "Address" % "HTTP" % "HTTP/1" % "HTTP/2" % "GET" % "POST" % "Bad" % "Errors" % "Redirects" % "Valid" % "# ticket keys" % "Rotation delay" % "Next rotation") << endl; + size_t counter = 0; + for (const auto& ctx : g_dohlocals) { + ret << (fmt % counter % ctx->d_local.toStringWithPort() % ctx->d_httpconnects % ctx->d_http1Stats.d_nbQueries % ctx->d_http2Stats.d_nbQueries % ctx->d_getqueries % ctx->d_postqueries % ctx->d_badrequests % ctx->d_errorresponses % ctx->d_redirectresponses % ctx->d_validresponses % ctx->getTicketsKeysCount() % ctx->getTicketsKeyRotationDelay() % ctx->getNextTicketsKeyRotation()) << endl; + counter++; + } + g_outputBuffer = ret.str(); + } + catch (const std::exception& e) { + g_outputBuffer = e.what(); + throw; + } #else - g_outputBuffer="DNS over HTTPS support is not present!\n"; + g_outputBuffer = "DNS over HTTPS support is not present!\n"; #endif - }); + }); - luaCtx.writeFunction("showDOHResponseCodes", []() { + luaCtx.writeFunction("showDOHResponseCodes", []() { #ifdef HAVE_DNS_OVER_HTTPS - setLuaNoSideEffect(); - try { - ostringstream ret; - boost::format fmt("%-3d %-20.20s %-15d %-15d %-15d %-15d %-15d %-15d"); - g_outputBuffer = "\n- HTTP/1:\n\n"; - ret << (fmt % "#" % "Address" % "200" % "400" % "403" % "500" % "502" % "Others" ) << endl; - size_t counter = 0; - for (const auto& ctx : g_dohlocals) { - ret << (fmt % counter % ctx->d_local.toStringWithPort() % ctx->d_http1Stats.d_nb200Responses % ctx->d_http1Stats.d_nb400Responses % ctx->d_http1Stats.d_nb403Responses % ctx->d_http1Stats.d_nb500Responses % ctx->d_http1Stats.d_nb502Responses % ctx->d_http1Stats.d_nbOtherResponses) << endl; - counter++; - } - g_outputBuffer += ret.str(); - ret.str(""); - - g_outputBuffer += "\n- HTTP/2:\n\n"; - ret << (fmt % "#" % "Address" % "200" % "400" % "403" % "500" % "502" % "Others" ) << endl; - counter = 0; - for (const auto& ctx : g_dohlocals) { - ret << (fmt % counter % ctx->d_local.toStringWithPort() % ctx->d_http2Stats.d_nb200Responses % ctx->d_http2Stats.d_nb400Responses % ctx->d_http2Stats.d_nb403Responses % ctx->d_http2Stats.d_nb500Responses % ctx->d_http2Stats.d_nb502Responses % ctx->d_http2Stats.d_nbOtherResponses) << endl; - counter++; - } - g_outputBuffer += ret.str(); - } - catch(const std::exception& e) { - g_outputBuffer = e.what(); - throw; - } + setLuaNoSideEffect(); + try { + ostringstream ret; + boost::format fmt("%-3d %-20.20s %-15d %-15d %-15d %-15d %-15d %-15d"); + g_outputBuffer = "\n- HTTP/1:\n\n"; + ret << (fmt % "#" % "Address" % "200" % "400" % "403" % "500" % "502" % "Others") << endl; + size_t counter = 0; + for (const auto& ctx : g_dohlocals) { + ret << (fmt % counter % ctx->d_local.toStringWithPort() % ctx->d_http1Stats.d_nb200Responses % ctx->d_http1Stats.d_nb400Responses % ctx->d_http1Stats.d_nb403Responses % ctx->d_http1Stats.d_nb500Responses % ctx->d_http1Stats.d_nb502Responses % ctx->d_http1Stats.d_nbOtherResponses) << endl; + counter++; + } + g_outputBuffer += ret.str(); + ret.str(""); + + g_outputBuffer += "\n- HTTP/2:\n\n"; + ret << (fmt % "#" % "Address" % "200" % "400" % "403" % "500" % "502" % "Others") << endl; + counter = 0; + for (const auto& ctx : g_dohlocals) { + ret << (fmt % counter % ctx->d_local.toStringWithPort() % ctx->d_http2Stats.d_nb200Responses % ctx->d_http2Stats.d_nb400Responses % ctx->d_http2Stats.d_nb403Responses % ctx->d_http2Stats.d_nb500Responses % ctx->d_http2Stats.d_nb502Responses % ctx->d_http2Stats.d_nbOtherResponses) << endl; + counter++; + } + g_outputBuffer += ret.str(); + } + catch (const std::exception& e) { + g_outputBuffer = e.what(); + throw; + } #else - g_outputBuffer="DNS over HTTPS support is not present!\n"; + g_outputBuffer = "DNS over HTTPS support is not present!\n"; #endif - }); + }); - luaCtx.writeFunction("getDOHFrontend", [client](size_t index) { - std::shared_ptr result = nullptr; - if (client) { - return result; - } + luaCtx.writeFunction("getDOHFrontend", [client](size_t index) { + std::shared_ptr result = nullptr; + if (client) { + return result; + } #ifdef HAVE_DNS_OVER_HTTPS - setLuaNoSideEffect(); - try { - if (index < g_dohlocals.size()) { - result = g_dohlocals.at(index); - } - else { - errlog("Error: trying to get DOH frontend with index %zu but we only have %zu frontend(s)\n", index, g_dohlocals.size()); - g_outputBuffer="Error: trying to get DOH frontend with index " + std::to_string(index) + " but we only have " + std::to_string(g_dohlocals.size()) + " frontend(s)\n"; - } - } - catch(const std::exception& e) { - g_outputBuffer="Error while trying to get DOH frontend with index " + std::to_string(index) + ": "+string(e.what())+"\n"; - errlog("Error while trying to get DOH frontend with index %zu: %s\n", index, string(e.what())); - } + setLuaNoSideEffect(); + try { + if (index < g_dohlocals.size()) { + result = g_dohlocals.at(index); + } + else { + errlog("Error: trying to get DOH frontend with index %zu but we only have %zu frontend(s)\n", index, g_dohlocals.size()); + g_outputBuffer = "Error: trying to get DOH frontend with index " + std::to_string(index) + " but we only have " + std::to_string(g_dohlocals.size()) + " frontend(s)\n"; + } + } + catch (const std::exception& e) { + g_outputBuffer = "Error while trying to get DOH frontend with index " + std::to_string(index) + ": " + string(e.what()) + "\n"; + errlog("Error while trying to get DOH frontend with index %zu: %s\n", index, string(e.what())); + } #else g_outputBuffer="DNS over HTTPS support is not present!\n"; #endif - return result; - }); + return result; + }); - luaCtx.writeFunction("getDOHFrontendCount", []() { - setLuaNoSideEffect(); - return g_dohlocals.size(); - }); + luaCtx.writeFunction("getDOHFrontendCount", []() { + setLuaNoSideEffect(); + return g_dohlocals.size(); + }); - luaCtx.registerFunction::*)()>("reloadCertificates", [](std::shared_ptr frontend) { - if (frontend != nullptr) { - frontend->reloadCertificates(); - } - }); + luaCtx.registerFunction::*)()>("reloadCertificates", [](std::shared_ptr frontend) { + if (frontend != nullptr) { + frontend->reloadCertificates(); + } + }); - luaCtx.registerFunction::*)(boost::variant>> certFiles, boost::variant>> keyFiles)>("loadNewCertificatesAndKeys", [](std::shared_ptr frontend, boost::variant>> certFiles, boost::variant>> keyFiles) { + luaCtx.registerFunction::*)(boost::variant>> certFiles, boost::variant>> keyFiles)>("loadNewCertificatesAndKeys", [](std::shared_ptr frontend, boost::variant>> certFiles, boost::variant>> keyFiles) { #ifdef HAVE_DNS_OVER_HTTPS - if (frontend != nullptr) { - if (loadTLSCertificateAndKeys("DOHFrontend::loadNewCertificatesAndKeys", frontend->d_tlsConfig.d_certKeyPairs, certFiles, keyFiles)) { - frontend->reloadCertificates(); - } - } + if (frontend != nullptr) { + if (loadTLSCertificateAndKeys("DOHFrontend::loadNewCertificatesAndKeys", frontend->d_tlsConfig.d_certKeyPairs, certFiles, keyFiles)) { + frontend->reloadCertificates(); + } + } #endif - }); + }); - luaCtx.registerFunction::*)()>("rotateTicketsKey", [](std::shared_ptr frontend) { - if (frontend != nullptr) { - frontend->rotateTicketsKey(time(nullptr)); - } - }); + luaCtx.registerFunction::*)()>("rotateTicketsKey", [](std::shared_ptr frontend) { + if (frontend != nullptr) { + frontend->rotateTicketsKey(time(nullptr)); + } + }); - luaCtx.registerFunction::*)(const std::string&)>("loadTicketsKeys", [](std::shared_ptr frontend, const std::string& file) { - if (frontend != nullptr) { - frontend->loadTicketsKeys(file); - } - }); + luaCtx.registerFunction::*)(const std::string&)>("loadTicketsKeys", [](std::shared_ptr frontend, const std::string& file) { + if (frontend != nullptr) { + frontend->loadTicketsKeys(file); + } + }); - luaCtx.registerFunction::*)(const std::map>&)>("setResponsesMap", [](std::shared_ptr frontend, const std::map>& map) { - if (frontend != nullptr) { - auto newMap = std::make_shared>>(); - newMap->reserve(map.size()); + luaCtx.registerFunction::*)(const std::map>&)>("setResponsesMap", [](std::shared_ptr frontend, const std::map>& map) { + if (frontend != nullptr) { + auto newMap = std::make_shared>>(); + newMap->reserve(map.size()); - for (const auto& entry : map) { - newMap->push_back(entry.second); - } + for (const auto& entry : map) { + newMap->push_back(entry.second); + } - frontend->d_responsesMap = std::move(newMap); - } - }); + frontend->d_responsesMap = std::move(newMap); + } + }); - luaCtx.writeFunction("addTLSLocal", [client](const std::string& addr, boost::variant>> certFiles, boost::variant>> keyFiles, boost::optional vars) { - if (client) { - return; - } + luaCtx.writeFunction("addTLSLocal", [client](const std::string& addr, boost::variant>> certFiles, boost::variant>> keyFiles, boost::optional vars) { + if (client) { + return; + } #ifdef HAVE_DNS_OVER_TLS - setLuaSideEffect(); - if (g_configurationDone) { - g_outputBuffer="addTLSLocal cannot be used at runtime!\n"; - return; - } - shared_ptr frontend = std::make_shared(); + setLuaSideEffect(); + if (g_configurationDone) { + g_outputBuffer = "addTLSLocal cannot be used at runtime!\n"; + return; + } + shared_ptr frontend = std::make_shared(); - if (!loadTLSCertificateAndKeys("addTLSLocal", frontend->d_tlsConfig.d_certKeyPairs, certFiles, keyFiles)) { - return; - } + if (!loadTLSCertificateAndKeys("addTLSLocal", frontend->d_tlsConfig.d_certKeyPairs, certFiles, keyFiles)) { + return; + } - bool reusePort = false; - int tcpFastOpenQueueSize = 0; - int tcpListenQueueSize = 0; - size_t maxInFlightQueriesPerConn = 0; - size_t tcpMaxConcurrentConns = 0; - std::string interface; - std::set cpus; + bool reusePort = false; + int tcpFastOpenQueueSize = 0; + int tcpListenQueueSize = 0; + size_t maxInFlightQueriesPerConn = 0; + size_t tcpMaxConcurrentConns = 0; + std::string interface; + std::set cpus; - if (vars) { - parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus, tcpListenQueueSize, maxInFlightQueriesPerConn, tcpMaxConcurrentConns); + if (vars) { + parseLocalBindVars(vars, reusePort, tcpFastOpenQueueSize, interface, cpus, tcpListenQueueSize, maxInFlightQueriesPerConn, tcpMaxConcurrentConns); - if (vars->count("provider")) { - frontend->d_provider = boost::get((*vars)["provider"]); - boost::algorithm::to_lower(frontend->d_provider); - } + if (vars->count("provider")) { + frontend->d_provider = boost::get((*vars)["provider"]); + boost::algorithm::to_lower(frontend->d_provider); + } - parseTLSConfig(frontend->d_tlsConfig, "addTLSLocal", vars); - } + parseTLSConfig(frontend->d_tlsConfig, "addTLSLocal", vars); + } - try { - frontend->d_addr = ComboAddress(addr, 853); - if (!frontend->d_provider.empty()) { - vinfolog("Loading TLS provider '%s'", frontend->d_provider); - } - else { + try { + frontend->d_addr = ComboAddress(addr, 853); + if (!frontend->d_provider.empty()) { + vinfolog("Loading TLS provider '%s'", frontend->d_provider); + } + else { #ifdef HAVE_LIBSSL - vinfolog("Loading default TLS provider 'openssl'"); + vinfolog("Loading default TLS provider 'openssl'"); #else - vinfolog("Loading default TLS provider 'gnutls'"); + vinfolog("Loading default TLS provider 'gnutls'"); #endif - } - // only works pre-startup, so no sync necessary - auto cs = std::make_unique(frontend->d_addr, true, reusePort, tcpFastOpenQueueSize, interface, cpus); - cs->tlsFrontend = frontend; - if (tcpListenQueueSize > 0) { - cs->tcpListenQueueSize = tcpListenQueueSize; - } - if (maxInFlightQueriesPerConn > 0) { - cs->d_maxInFlightQueriesPerConn = maxInFlightQueriesPerConn; - } - if (tcpMaxConcurrentConns > 0) { - cs->d_tcpConcurrentConnectionsLimit = tcpMaxConcurrentConns; - } + } + // only works pre-startup, so no sync necessary + auto cs = std::make_unique(frontend->d_addr, true, reusePort, tcpFastOpenQueueSize, interface, cpus); + cs->tlsFrontend = frontend; + if (tcpListenQueueSize > 0) { + cs->tcpListenQueueSize = tcpListenQueueSize; + } + if (maxInFlightQueriesPerConn > 0) { + cs->d_maxInFlightQueriesPerConn = maxInFlightQueriesPerConn; + } + if (tcpMaxConcurrentConns > 0) { + cs->d_tcpConcurrentConnectionsLimit = tcpMaxConcurrentConns; + } - g_tlslocals.push_back(cs->tlsFrontend); - g_frontends.push_back(std::move(cs)); - } - catch(const std::exception& e) { - g_outputBuffer="Error: "+string(e.what())+"\n"; - } + g_tlslocals.push_back(cs->tlsFrontend); + g_frontends.push_back(std::move(cs)); + } + catch (const std::exception& e) { + g_outputBuffer = "Error: " + string(e.what()) + "\n"; + } #else - throw std::runtime_error("addTLSLocal() called but DNS over TLS support is not present!"); + throw std::runtime_error("addTLSLocal() called but DNS over TLS support is not present!"); #endif - }); + }); - luaCtx.writeFunction("showTLSContexts", []() { + luaCtx.writeFunction("showTLSContexts", []() { #ifdef HAVE_DNS_OVER_TLS - setLuaNoSideEffect(); - try { - ostringstream ret; - boost::format fmt("%1$-3d %2$-20.20s %|25t|%3$-14d %|40t|%4$-14d %|54t|%5$-21.21s"); - // 1 2 3 4 5 - ret << (fmt % "#" % "Address" % "# ticket keys" % "Rotation delay" % "Next rotation" ) << endl; - size_t counter = 0; - for (const auto& ctx : g_tlslocals) { - ret << (fmt % counter % ctx->d_addr.toStringWithPort() % ctx->getTicketsKeysCount() % ctx->getTicketsKeyRotationDelay() % ctx->getNextTicketsKeyRotation()) << endl; - counter++; - } - g_outputBuffer = ret.str(); - } - catch(const std::exception& e) { - g_outputBuffer = e.what(); - throw; - } + setLuaNoSideEffect(); + try { + ostringstream ret; + boost::format fmt("%1$-3d %2$-20.20s %|25t|%3$-14d %|40t|%4$-14d %|54t|%5$-21.21s"); + // 1 2 3 4 5 + ret << (fmt % "#" % "Address" % "# ticket keys" % "Rotation delay" % "Next rotation") << endl; + size_t counter = 0; + for (const auto& ctx : g_tlslocals) { + ret << (fmt % counter % ctx->d_addr.toStringWithPort() % ctx->getTicketsKeysCount() % ctx->getTicketsKeyRotationDelay() % ctx->getNextTicketsKeyRotation()) << endl; + counter++; + } + g_outputBuffer = ret.str(); + } + catch (const std::exception& e) { + g_outputBuffer = e.what(); + throw; + } #else - g_outputBuffer="DNS over TLS support is not present!\n"; + g_outputBuffer = "DNS over TLS support is not present!\n"; #endif - }); + }); - luaCtx.writeFunction("getTLSContext", [](size_t index) { - std::shared_ptr result = nullptr; + luaCtx.writeFunction("getTLSContext", [](size_t index) { + std::shared_ptr result = nullptr; #ifdef HAVE_DNS_OVER_TLS - setLuaNoSideEffect(); - try { - if (index < g_tlslocals.size()) { - result = g_tlslocals.at(index)->getContext(); - } - else { - errlog("Error: trying to get TLS context with index %zu but we only have %zu context(s)\n", index, g_tlslocals.size()); - g_outputBuffer="Error: trying to get TLS context with index " + std::to_string(index) + " but we only have " + std::to_string(g_tlslocals.size()) + " context(s)\n"; - } - } - catch(const std::exception& e) { - g_outputBuffer="Error while trying to get TLS context with index " + std::to_string(index) + ": "+string(e.what())+"\n"; - errlog("Error while trying to get TLS context with index %zu: %s\n", index, string(e.what())); - } + setLuaNoSideEffect(); + try { + if (index < g_tlslocals.size()) { + result = g_tlslocals.at(index)->getContext(); + } + else { + errlog("Error: trying to get TLS context with index %zu but we only have %zu context(s)\n", index, g_tlslocals.size()); + g_outputBuffer = "Error: trying to get TLS context with index " + std::to_string(index) + " but we only have " + std::to_string(g_tlslocals.size()) + " context(s)\n"; + } + } + catch (const std::exception& e) { + g_outputBuffer = "Error while trying to get TLS context with index " + std::to_string(index) + ": " + string(e.what()) + "\n"; + errlog("Error while trying to get TLS context with index %zu: %s\n", index, string(e.what())); + } #else g_outputBuffer="DNS over TLS support is not present!\n"; #endif - return result; - }); + return result; + }); - luaCtx.writeFunction("getTLSFrontend", [](size_t index) { - std::shared_ptr result = nullptr; + luaCtx.writeFunction("getTLSFrontend", [](size_t index) { + std::shared_ptr result = nullptr; #ifdef HAVE_DNS_OVER_TLS - setLuaNoSideEffect(); - try { - if (index < g_tlslocals.size()) { - result = g_tlslocals.at(index); - } - else { - errlog("Error: trying to get TLS frontend with index %zu but we only have %zu frontends\n", index, g_tlslocals.size()); - g_outputBuffer="Error: trying to get TLS frontend with index " + std::to_string(index) + " but we only have " + std::to_string(g_tlslocals.size()) + " frontend(s)\n"; - } - } - catch(const std::exception& e) { - g_outputBuffer="Error while trying to get TLS frontend with index " + std::to_string(index) + ": "+string(e.what())+"\n"; - errlog("Error while trying to get TLS frontend with index %zu: %s\n", index, string(e.what())); - } + setLuaNoSideEffect(); + try { + if (index < g_tlslocals.size()) { + result = g_tlslocals.at(index); + } + else { + errlog("Error: trying to get TLS frontend with index %zu but we only have %zu frontends\n", index, g_tlslocals.size()); + g_outputBuffer = "Error: trying to get TLS frontend with index " + std::to_string(index) + " but we only have " + std::to_string(g_tlslocals.size()) + " frontend(s)\n"; + } + } + catch (const std::exception& e) { + g_outputBuffer = "Error while trying to get TLS frontend with index " + std::to_string(index) + ": " + string(e.what()) + "\n"; + errlog("Error while trying to get TLS frontend with index %zu: %s\n", index, string(e.what())); + } #else g_outputBuffer="DNS over TLS support is not present!\n"; #endif - return result; - }); + return result; + }); - luaCtx.writeFunction("getTLSFrontendCount", []() { - setLuaNoSideEffect(); - return g_tlslocals.size(); - }); + luaCtx.writeFunction("getTLSFrontendCount", []() { + setLuaNoSideEffect(); + return g_tlslocals.size(); + }); - luaCtx.registerFunction::*)()>("rotateTicketsKey", [](std::shared_ptr& ctx) { - if (ctx != nullptr) { - ctx->rotateTicketsKey(time(nullptr)); - } - }); + luaCtx.registerFunction::*)()>("rotateTicketsKey", [](std::shared_ptr& ctx) { + if (ctx != nullptr) { + ctx->rotateTicketsKey(time(nullptr)); + } + }); - luaCtx.registerFunction::*)(const std::string&)>("loadTicketsKeys", [](std::shared_ptr& ctx, const std::string& file) { - if (ctx != nullptr) { - ctx->loadTicketsKeys(file); - } - }); + luaCtx.registerFunction::*)(const std::string&)>("loadTicketsKeys", [](std::shared_ptr& ctx, const std::string& file) { + if (ctx != nullptr) { + ctx->loadTicketsKeys(file); + } + }); - luaCtx.registerFunction::*)()>("rotateTicketsKey", [](std::shared_ptr& frontend) { - if (frontend == nullptr) { - return; - } - auto ctx = frontend->getContext(); - if (ctx) { - ctx->rotateTicketsKey(time(nullptr)); - } - }); + luaCtx.registerFunction::*)()>("rotateTicketsKey", [](std::shared_ptr& frontend) { + if (frontend == nullptr) { + return; + } + auto ctx = frontend->getContext(); + if (ctx) { + ctx->rotateTicketsKey(time(nullptr)); + } + }); - luaCtx.registerFunction::*)(const std::string&)>("loadTicketsKeys", [](std::shared_ptr& frontend, const std::string& file) { - if (frontend == nullptr) { - return; - } - auto ctx = frontend->getContext(); - if (ctx) { - ctx->loadTicketsKeys(file); - } - }); + luaCtx.registerFunction::*)(const std::string&)>("loadTicketsKeys", [](std::shared_ptr& frontend, const std::string& file) { + if (frontend == nullptr) { + return; + } + auto ctx = frontend->getContext(); + if (ctx) { + ctx->loadTicketsKeys(file); + } + }); - luaCtx.registerFunction::*)()>("reloadCertificates", [](std::shared_ptr& frontend) { - if (frontend == nullptr) { - return; - } - frontend->setupTLS(); - }); + luaCtx.registerFunction::*)()>("reloadCertificates", [](std::shared_ptr& frontend) { + if (frontend == nullptr) { + return; + } + frontend->setupTLS(); + }); - luaCtx.registerFunction::*)(boost::variant>> certFiles, boost::variant>> keyFiles)>("loadNewCertificatesAndKeys", [](std::shared_ptr& frontend, boost::variant>> certFiles, boost::variant>> keyFiles) { + luaCtx.registerFunction::*)(boost::variant>> certFiles, boost::variant>> keyFiles)>("loadNewCertificatesAndKeys", [](std::shared_ptr& frontend, boost::variant>> certFiles, boost::variant>> keyFiles) { #ifdef HAVE_DNS_OVER_TLS - if (loadTLSCertificateAndKeys("TLSFrontend::loadNewCertificatesAndKeys", frontend->d_tlsConfig.d_certKeyPairs, certFiles, keyFiles)) { - frontend->setupTLS(); - } + if (loadTLSCertificateAndKeys("TLSFrontend::loadNewCertificatesAndKeys", frontend->d_tlsConfig.d_certKeyPairs, certFiles, keyFiles)) { + frontend->setupTLS(); + } #endif - }); + }); - luaCtx.writeFunction("reloadAllCertificates", []() { - for (auto& frontend : g_frontends) { - if (!frontend) { - continue; - } - try { + luaCtx.writeFunction("reloadAllCertificates", []() { + for (auto& frontend : g_frontends) { + if (!frontend) { + continue; + } + try { #ifdef HAVE_DNSCRYPT - if (frontend->dnscryptCtx) { - frontend->dnscryptCtx->reloadCertificates(); - } + if (frontend->dnscryptCtx) { + frontend->dnscryptCtx->reloadCertificates(); + } #endif /* HAVE_DNSCRYPT */ #ifdef HAVE_DNS_OVER_TLS - if (frontend->tlsFrontend) { - frontend->tlsFrontend->setupTLS(); - } + if (frontend->tlsFrontend) { + frontend->tlsFrontend->setupTLS(); + } #endif /* HAVE_DNS_OVER_TLS */ #ifdef HAVE_DNS_OVER_HTTPS - if (frontend->dohFrontend) { - frontend->dohFrontend->reloadCertificates(); - } -#endif /* HAVE_DNS_OVER_HTTPS */ - } - catch(const std::exception& e) { - errlog("Error reloading certificates for frontend %s: %s", frontend->local.toStringWithPort(), e.what()); - } + if (frontend->dohFrontend) { + frontend->dohFrontend->reloadCertificates(); } - }); +#endif /* HAVE_DNS_OVER_HTTPS */ + } + catch (const std::exception& e) { + errlog("Error reloading certificates for frontend %s: %s", frontend->local.toStringWithPort(), e.what()); + } + } + }); - luaCtx.writeFunction("setAllowEmptyResponse", [](bool allow) { g_allowEmptyResponse=allow; }); - luaCtx.writeFunction("setDropEmptyQueries", [](bool drop) { extern bool g_dropEmptyQueries; g_dropEmptyQueries = drop; }); + luaCtx.writeFunction("setAllowEmptyResponse", [](bool allow) { g_allowEmptyResponse = allow; }); + luaCtx.writeFunction("setDropEmptyQueries", [](bool drop) { extern bool g_dropEmptyQueries; g_dropEmptyQueries = drop; }); #if defined(HAVE_LIBSSL) && defined(HAVE_OCSP_BASIC_SIGN) - luaCtx.writeFunction("generateOCSPResponse", [client](const std::string& certFile, const std::string& caCert, const std::string& caKey, const std::string& outFile, int ndays, int nmin) { - if (client) { - return; - } + luaCtx.writeFunction("generateOCSPResponse", [client](const std::string& certFile, const std::string& caCert, const std::string& caKey, const std::string& outFile, int ndays, int nmin) { + if (client) { + return; + } - libssl_generate_ocsp_response(certFile, caCert, caKey, outFile, ndays, nmin); - }); + libssl_generate_ocsp_response(certFile, caCert, caKey, outFile, ndays, nmin); + }); #endif /* HAVE_LIBSSL && HAVE_OCSP_BASIC_SIGN*/ } @@ -2744,7 +2749,7 @@ vector> setupLua(LuaContext& luaCtx, bool client, bool #endif std::ifstream ifs(config); - if(!ifs) + if (!ifs) warnlog("Unable to read configuration from '%s'", config); else vinfolog("Read configuration from '%s'", config);