From: Remi Gacogne Date: Thu, 27 Aug 2020 09:00:06 +0000 (+0200) Subject: dnsdist: Add per-thread Lua FFI load-balancing policies X-Git-Tag: rec-4.5.0-alpha0~23^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fd51c832b280fa57f749b1fdd6d4b9428bc10806;p=thirdparty%2Fpdns.git dnsdist: Add per-thread Lua FFI load-balancing policies This allows Lua FFI load-balancing policies that don't need access to the global, shared Lua state to be lock-less, avoiding lock contention. --- diff --git a/pdns/dnsdist-console.cc b/pdns/dnsdist-console.cc index 177837f522..130e4cc628 100644 --- a/pdns/dnsdist-console.cc +++ b/pdns/dnsdist-console.cc @@ -528,7 +528,9 @@ const std::vector g_consoleKeywords{ { "SetNegativeAndSOAAction", true, "nxd, zone, ttl, mname, rname, serial, refresh, retry, expire, minimum [, options]", "Turn a query into a NXDomain or NoData answer and sets a SOA record in the additional section" }, { "setPayloadSizeOnSelfGeneratedAnswers", true, "payloadSize", "set the UDP payload size advertised via EDNS on self-generated responses" }, { "setPoolServerPolicy", true, "policy, pool", "set the server selection policy for this pool to that policy" }, - { "setPoolServerPolicyLua", true, "name, func, pool", "set the server selection policy for this pool to one named 'name' and provided by 'function'" }, + { "setPoolServerPolicyLua", true, "name, function, pool", "set the server selection policy for this pool to one named 'name' and provided by 'function'" }, + { "setPoolServerPolicyLuaFFI", true, "name, function, pool", "set the server selection policy for this pool to one named 'name' and provided by 'function'" }, + { "setPoolServerPolicyLuaFFIPerThread", true, "name, code", "set server selection policy for this pool to one named 'name' and returned by the Lua FFI code passed in 'code'" }, { "setPreserveTrailingData", true, "bool", "set whether trailing data should be preserved while adding ECS or XPF records to incoming queries" }, { "setQueryCount", true, "bool", "set whether queries should be counted" }, { "setQueryCountFilter", true, "func", "filter queries that would be counted, where `func` is a function with parameter `dq` which decides whether a query should and how it should be counted" }, @@ -541,6 +543,7 @@ const std::vector g_consoleKeywords{ { "setServerPolicy", true, "policy", "set server selection policy to that policy" }, { "setServerPolicyLua", true, "name, function", "set server selection policy to one named 'name' and provided by 'function'" }, { "setServerPolicyLuaFFI", true, "name, function", "set server selection policy to one named 'name' and provided by the Lua FFI 'function'" }, + { "setServerPolicyLuaFFIPerThread", true, "name, code", "set server selection policy to one named 'name' and returned by the Lua FFI code passed in 'code'" }, { "setServFailWhenNoServer", true, "bool", "if set, return a ServFail when no servers are available, instead of the default behaviour of dropping the query" }, { "setStaleCacheEntriesTTL", true, "n", "allows using cache entries expired for at most n seconds when there is no backend available to answer for a query" }, { "setSyslogFacility", true, "facility", "set the syslog logging facility to 'facility'. Defaults to LOG_DAEMON" }, diff --git a/pdns/dnsdist-lbpolicies.hh b/pdns/dnsdist-lbpolicies.hh index 7ad5f25cff..395deec2b5 100644 --- a/pdns/dnsdist-lbpolicies.hh +++ b/pdns/dnsdist-lbpolicies.hh @@ -27,37 +27,69 @@ struct dnsdist_ffi_dnsquestion_t; struct DownstreamState; -struct ServerPolicy +struct PerThreadPoliciesState; + +class ServerPolicy { +public: template using NumberedVector = std::vector >; using NumberedServerVector = NumberedVector>; typedef std::function(const NumberedServerVector& servers, const DNSQuestion*)> policyfunc_t; typedef std::function ffipolicyfunc_t; - ServerPolicy(const std::string& name_, policyfunc_t policy_, bool isLua_): name(name_), policy(policy_), isLua(isLua_) + ServerPolicy(const std::string& name_, policyfunc_t policy_, bool isLua_): d_name(name_), d_policy(policy_), d_isLua(isLua_) { } - ServerPolicy(const std::string& name_, ffipolicyfunc_t policy_): name(name_), ffipolicy(policy_), isLua(true), isFFI(true) + + ServerPolicy(const std::string& name_, ffipolicyfunc_t policy_): d_name(name_), d_ffipolicy(policy_), d_isLua(true), d_isFFI(true) { } + + /* create a per-thread FFI policy */ + ServerPolicy(const std::string& name_, const std::string& code); + ServerPolicy() { } - string name; - policyfunc_t policy; - ffipolicyfunc_t ffipolicy; - bool isLua{false}; - bool isFFI{false}; + std::shared_ptr getSelectedBackend(const ServerPolicy::NumberedServerVector& servers, DNSQuestion& dq) const; + + const std::string& getName() const + { + return d_name; + } std::string toString() const { - return string("ServerPolicy") + (isLua ? " (Lua)" : "") + " \"" + name + "\""; + return string("ServerPolicy") + (d_isLua ? " (Lua)" : "") + " \"" + d_name + "\""; } + +private: + struct PerThreadState + { + LuaContext d_luaContext; + std::unordered_map d_policies; + bool d_initialized{false}; + }; + + const ffipolicyfunc_t& getPerThreadPolicy() const; + static thread_local PerThreadState t_perThreadState; + + +public: + std::string d_name; + std::string d_perThreadPolicyCode; + + policyfunc_t d_policy; + ffipolicyfunc_t d_ffipolicy; + + bool d_isLua{false}; + bool d_isFFI{false}; + bool d_isPerThread{false}; }; struct ServerPool; -using pools_t=map>; +using pools_t = map>; std::shared_ptr getPool(const pools_t& pools, const std::string& poolName); std::shared_ptr createPoolIfNotExists(pools_t& pools, const string& poolName); void setPoolPolicy(pools_t& pools, const string& poolName, std::shared_ptr policy); @@ -75,7 +107,6 @@ std::shared_ptr whashedFromHash(const ServerPolicy::NumberedSer std::shared_ptr chashed(const ServerPolicy::NumberedServerVector& servers, const DNSQuestion* dq); std::shared_ptr chashedFromHash(const ServerPolicy::NumberedServerVector& servers, size_t hash); std::shared_ptr roundrobin(const ServerPolicy::NumberedServerVector& servers, const DNSQuestion* dq); -std::shared_ptr getSelectedBackendFromPolicy(const ServerPolicy& policy, const ServerPolicy::NumberedServerVector& servers, DNSQuestion& dq); extern double g_consistentHashBalancingFactor; extern double g_weightedBalancingFactor; diff --git a/pdns/dnsdist-lua-actions.cc b/pdns/dnsdist-lua-actions.cc index ef47d25165..dbbcaadfda 100644 --- a/pdns/dnsdist-lua-actions.cc +++ b/pdns/dnsdist-lua-actions.cc @@ -1505,9 +1505,9 @@ void setResponseHeadersFromConfig(dnsheader& dh, const ResponseConfig& config) } } -void setupLuaActions() +void setupLuaActions(LuaContext& luaCtx) { - g_lua.writeFunction("newRuleAction", [](luadnsrule_t dnsrule, std::shared_ptr action, boost::optional params) { + luaCtx.writeFunction("newRuleAction", [](luadnsrule_t dnsrule, std::shared_ptr action, boost::optional params) { boost::uuids::uuid uuid; uint64_t creationOrder; parseRuleParams(params, uuid, creationOrder); @@ -1517,7 +1517,7 @@ void setupLuaActions() return std::make_shared(ra); }); - g_lua.writeFunction("addAction", [](luadnsrule_t var, boost::variant, std::shared_ptr > era, boost::optional params) { + luaCtx.writeFunction("addAction", [](luadnsrule_t var, boost::variant, std::shared_ptr > era, boost::optional params) { if (era.type() != typeid(std::shared_ptr)) { throw std::runtime_error("addAction() can only be called with query-related actions, not response-related ones. Are you looking for addResponseAction()?"); } @@ -1525,7 +1525,7 @@ void setupLuaActions() addAction(&g_rulactions, var, boost::get >(era), params); }); - g_lua.writeFunction("addResponseAction", [](luadnsrule_t var, boost::variant, std::shared_ptr > era, boost::optional params) { + luaCtx.writeFunction("addResponseAction", [](luadnsrule_t var, boost::variant, std::shared_ptr > era, boost::optional params) { if (era.type() != typeid(std::shared_ptr)) { throw std::runtime_error("addResponseAction() can only be called with response-related actions, not query-related ones. Are you looking for addAction()?"); } @@ -1533,7 +1533,7 @@ void setupLuaActions() addAction(&g_resprulactions, var, boost::get >(era), params); }); - g_lua.writeFunction("addCacheHitResponseAction", [](luadnsrule_t var, boost::variant, std::shared_ptr> era, boost::optional params) { + luaCtx.writeFunction("addCacheHitResponseAction", [](luadnsrule_t var, boost::variant, std::shared_ptr> era, boost::optional params) { if (era.type() != typeid(std::shared_ptr)) { throw std::runtime_error("addCacheHitResponseAction() can only be called with response-related actions, not query-related ones. Are you looking for addAction()?"); } @@ -1541,7 +1541,7 @@ void setupLuaActions() addAction(&g_cachehitresprulactions, var, boost::get >(era), params); }); - g_lua.writeFunction("addSelfAnsweredResponseAction", [](luadnsrule_t var, boost::variant, std::shared_ptr> era, boost::optional params) { + luaCtx.writeFunction("addSelfAnsweredResponseAction", [](luadnsrule_t var, boost::variant, std::shared_ptr> era, boost::optional params) { if (era.type() != typeid(std::shared_ptr)) { throw std::runtime_error("addSelfAnsweredResponseAction() can only be called with response-related actions, not query-related ones. Are you looking for addAction()?"); } @@ -1549,7 +1549,7 @@ void setupLuaActions() addAction(&g_selfansweredresprulactions, var, boost::get >(era), params); }); - g_lua.registerFunction("printStats", [](const DNSAction& ta) { + luaCtx.registerFunction("printStats", [](const DNSAction& ta) { setLuaNoSideEffect(); auto stats = ta.getStats(); for(const auto& s : stats) { @@ -1561,7 +1561,7 @@ void setupLuaActions() } }); - g_lua.writeFunction("getAction", [](unsigned int num) { + luaCtx.writeFunction("getAction", [](unsigned int num) { setLuaNoSideEffect(); boost::optional> ret; auto rulactions = g_rulactions.getCopy(); @@ -1570,39 +1570,39 @@ void setupLuaActions() return ret; }); - g_lua.registerFunction("getStats", &DNSAction::getStats); + luaCtx.registerFunction("getStats", &DNSAction::getStats); - g_lua.writeFunction("LuaAction", [](LuaAction::func_t func) { + luaCtx.writeFunction("LuaAction", [](LuaAction::func_t func) { setLuaSideEffect(); return std::shared_ptr(new LuaAction(func)); }); - g_lua.writeFunction("LuaFFIAction", [](LuaFFIAction::func_t func) { + luaCtx.writeFunction("LuaFFIAction", [](LuaFFIAction::func_t func) { setLuaSideEffect(); return std::shared_ptr(new LuaFFIAction(func)); }); - g_lua.writeFunction("NoRecurseAction", []() { + luaCtx.writeFunction("NoRecurseAction", []() { return std::shared_ptr(new NoRecurseAction); }); - g_lua.writeFunction("MacAddrAction", [](int code) { + luaCtx.writeFunction("MacAddrAction", [](int code) { return std::shared_ptr(new MacAddrAction(code)); }); - g_lua.writeFunction("PoolAction", [](const std::string& a) { + luaCtx.writeFunction("PoolAction", [](const std::string& a) { return std::shared_ptr(new PoolAction(a)); }); - g_lua.writeFunction("QPSAction", [](int limit) { + luaCtx.writeFunction("QPSAction", [](int limit) { return std::shared_ptr(new QPSAction(limit)); }); - g_lua.writeFunction("QPSPoolAction", [](int limit, const std::string& a) { + luaCtx.writeFunction("QPSPoolAction", [](int limit, const std::string& a) { return std::shared_ptr(new QPSPoolAction(limit, a)); }); - g_lua.writeFunction("SpoofAction", [](boost::variant>> inp, boost::optional b, boost::optional vars) { + luaCtx.writeFunction("SpoofAction", [](boost::variant>> inp, boost::optional b, boost::optional vars) { vector addrs; if(auto s = boost::get(&inp)) addrs.push_back(ComboAddress(*s)); @@ -1621,97 +1621,97 @@ void setupLuaActions() return ret; }); - g_lua.writeFunction("SpoofCNAMEAction", [](const std::string& a, boost::optional vars) { + luaCtx.writeFunction("SpoofCNAMEAction", [](const std::string& a, boost::optional vars) { auto ret = std::shared_ptr(new SpoofAction(DNSName(a))); auto sa = std::dynamic_pointer_cast(ret); parseResponseConfig(vars, sa->d_responseConfig); return ret; }); - g_lua.writeFunction("SpoofRawAction", [](const std::string& raw, boost::optional vars) { + luaCtx.writeFunction("SpoofRawAction", [](const std::string& raw, boost::optional vars) { auto ret = std::shared_ptr(new SpoofAction(raw)); auto sa = std::dynamic_pointer_cast(ret); parseResponseConfig(vars, sa->d_responseConfig); return ret; }); - g_lua.writeFunction("DropAction", []() { + luaCtx.writeFunction("DropAction", []() { return std::shared_ptr(new DropAction); }); - g_lua.writeFunction("AllowAction", []() { + luaCtx.writeFunction("AllowAction", []() { return std::shared_ptr(new AllowAction); }); - g_lua.writeFunction("NoneAction", []() { + luaCtx.writeFunction("NoneAction", []() { return std::shared_ptr(new NoneAction); }); - g_lua.writeFunction("DelayAction", [](int msec) { + luaCtx.writeFunction("DelayAction", [](int msec) { return std::shared_ptr(new DelayAction(msec)); }); - g_lua.writeFunction("TCAction", []() { + luaCtx.writeFunction("TCAction", []() { return std::shared_ptr(new TCAction); }); - g_lua.writeFunction("DisableValidationAction", []() { + luaCtx.writeFunction("DisableValidationAction", []() { return std::shared_ptr(new DisableValidationAction); }); - g_lua.writeFunction("LogAction", [](boost::optional fname, boost::optional binary, boost::optional append, boost::optional buffered, boost::optional verboseOnly, boost::optional includeTimestamp) { + luaCtx.writeFunction("LogAction", [](boost::optional fname, boost::optional binary, boost::optional append, boost::optional buffered, boost::optional verboseOnly, boost::optional includeTimestamp) { return std::shared_ptr(new LogAction(fname ? *fname : "", binary ? *binary : true, append ? *append : false, buffered ? *buffered : false, verboseOnly ? *verboseOnly : true, includeTimestamp ? *includeTimestamp : false)); }); - g_lua.writeFunction("LogResponseAction", [](boost::optional fname, boost::optional append, boost::optional buffered, boost::optional verboseOnly, boost::optional includeTimestamp) { + luaCtx.writeFunction("LogResponseAction", [](boost::optional fname, boost::optional append, boost::optional buffered, boost::optional verboseOnly, boost::optional includeTimestamp) { return std::shared_ptr(new LogResponseAction(fname ? *fname : "", append ? *append : false, buffered ? *buffered : false, verboseOnly ? *verboseOnly : true, includeTimestamp ? *includeTimestamp : false)); }); - g_lua.writeFunction("RCodeAction", [](uint8_t rcode, boost::optional vars) { + luaCtx.writeFunction("RCodeAction", [](uint8_t rcode, boost::optional vars) { auto ret = std::shared_ptr(new RCodeAction(rcode)); auto rca = std::dynamic_pointer_cast(ret); parseResponseConfig(vars, rca->d_responseConfig); return ret; }); - g_lua.writeFunction("ERCodeAction", [](uint8_t rcode, boost::optional vars) { + luaCtx.writeFunction("ERCodeAction", [](uint8_t rcode, boost::optional vars) { auto ret = std::shared_ptr(new ERCodeAction(rcode)); auto erca = std::dynamic_pointer_cast(ret); parseResponseConfig(vars, erca->d_responseConfig); return ret; }); - g_lua.writeFunction("SkipCacheAction", []() { + luaCtx.writeFunction("SkipCacheAction", []() { return std::shared_ptr(new SkipCacheAction); }); - g_lua.writeFunction("TempFailureCacheTTLAction", [](int maxTTL) { + luaCtx.writeFunction("TempFailureCacheTTLAction", [](int maxTTL) { return std::shared_ptr(new TempFailureCacheTTLAction(maxTTL)); }); - g_lua.writeFunction("DropResponseAction", []() { + luaCtx.writeFunction("DropResponseAction", []() { return std::shared_ptr(new DropResponseAction); }); - g_lua.writeFunction("AllowResponseAction", []() { + luaCtx.writeFunction("AllowResponseAction", []() { return std::shared_ptr(new AllowResponseAction); }); - g_lua.writeFunction("DelayResponseAction", [](int msec) { + luaCtx.writeFunction("DelayResponseAction", [](int msec) { return std::shared_ptr(new DelayResponseAction(msec)); }); - g_lua.writeFunction("LuaResponseAction", [](LuaResponseAction::func_t func) { + luaCtx.writeFunction("LuaResponseAction", [](LuaResponseAction::func_t func) { setLuaSideEffect(); return std::shared_ptr(new LuaResponseAction(func)); }); - g_lua.writeFunction("LuaFFIResponseAction", [](LuaFFIResponseAction::func_t func) { + luaCtx.writeFunction("LuaFFIResponseAction", [](LuaFFIResponseAction::func_t func) { setLuaSideEffect(); return std::shared_ptr(new LuaFFIResponseAction(func)); }); - g_lua.writeFunction("RemoteLogAction", [](std::shared_ptr logger, boost::optional > alterFunc, boost::optional> vars) { + luaCtx.writeFunction("RemoteLogAction", [](std::shared_ptr logger, boost::optional > alterFunc, boost::optional> vars) { if (logger) { // avoids potentially-evaluated-expression warning with clang. RemoteLoggerInterface& rl = *logger.get(); @@ -1739,7 +1739,7 @@ void setupLuaActions() #endif }); - g_lua.writeFunction("RemoteLogResponseAction", [](std::shared_ptr logger, boost::optional > alterFunc, boost::optional includeCNAME, boost::optional> vars) { + luaCtx.writeFunction("RemoteLogResponseAction", [](std::shared_ptr logger, boost::optional > alterFunc, boost::optional includeCNAME, boost::optional> vars) { if (logger) { // avoids potentially-evaluated-expression warning with clang. RemoteLoggerInterface& rl = *logger.get(); @@ -1767,7 +1767,7 @@ void setupLuaActions() #endif }); - g_lua.writeFunction("DnstapLogAction", [](const std::string& identity, std::shared_ptr logger, boost::optional > alterFunc) { + luaCtx.writeFunction("DnstapLogAction", [](const std::string& identity, std::shared_ptr logger, boost::optional > alterFunc) { #ifdef HAVE_PROTOBUF return std::shared_ptr(new DnstapLogAction(identity, logger, alterFunc)); #else @@ -1775,7 +1775,7 @@ void setupLuaActions() #endif }); - g_lua.writeFunction("DnstapLogResponseAction", [](const std::string& identity, std::shared_ptr logger, boost::optional > alterFunc) { + luaCtx.writeFunction("DnstapLogResponseAction", [](const std::string& identity, std::shared_ptr logger, boost::optional > alterFunc) { #ifdef HAVE_PROTOBUF return std::shared_ptr(new DnstapLogResponseAction(identity, logger, alterFunc)); #else @@ -1783,30 +1783,30 @@ void setupLuaActions() #endif }); - g_lua.writeFunction("TeeAction", [](const std::string& remote, boost::optional addECS) { + luaCtx.writeFunction("TeeAction", [](const std::string& remote, boost::optional addECS) { return std::shared_ptr(new TeeAction(ComboAddress(remote, 53), addECS ? *addECS : false)); }); - g_lua.writeFunction("ECSPrefixLengthAction", [](uint16_t v4PrefixLength, uint16_t v6PrefixLength) { + luaCtx.writeFunction("ECSPrefixLengthAction", [](uint16_t v4PrefixLength, uint16_t v6PrefixLength) { return std::shared_ptr(new ECSPrefixLengthAction(v4PrefixLength, v6PrefixLength)); }); - g_lua.writeFunction("ECSOverrideAction", [](bool ecsOverride) { + luaCtx.writeFunction("ECSOverrideAction", [](bool ecsOverride) { return std::shared_ptr(new ECSOverrideAction(ecsOverride)); }); - g_lua.writeFunction("DisableECSAction", []() { + luaCtx.writeFunction("DisableECSAction", []() { return std::shared_ptr(new DisableECSAction()); }); - g_lua.writeFunction("SetECSAction", [](const std::string v4, boost::optional v6) { + luaCtx.writeFunction("SetECSAction", [](const std::string v4, boost::optional v6) { if (v6) { return std::shared_ptr(new SetECSAction(Netmask(v4), Netmask(*v6))); } return std::shared_ptr(new SetECSAction(Netmask(v4))); }); - g_lua.writeFunction("SNMPTrapAction", [](boost::optional reason) { + luaCtx.writeFunction("SNMPTrapAction", [](boost::optional reason) { #ifdef HAVE_NET_SNMP return std::shared_ptr(new SNMPTrapAction(reason ? *reason : "")); #else @@ -1814,7 +1814,7 @@ void setupLuaActions() #endif /* HAVE_NET_SNMP */ }); - g_lua.writeFunction("SNMPTrapResponseAction", [](boost::optional reason) { + luaCtx.writeFunction("SNMPTrapResponseAction", [](boost::optional reason) { #ifdef HAVE_NET_SNMP return std::shared_ptr(new SNMPTrapResponseAction(reason ? *reason : "")); #else @@ -1822,20 +1822,20 @@ void setupLuaActions() #endif /* HAVE_NET_SNMP */ }); - g_lua.writeFunction("TagAction", [](std::string tag, std::string value) { + luaCtx.writeFunction("TagAction", [](std::string tag, std::string value) { return std::shared_ptr(new TagAction(tag, value)); }); - g_lua.writeFunction("TagResponseAction", [](std::string tag, std::string value) { + luaCtx.writeFunction("TagResponseAction", [](std::string tag, std::string value) { return std::shared_ptr(new TagResponseAction(tag, value)); }); - g_lua.writeFunction("ContinueAction", [](std::shared_ptr action) { + luaCtx.writeFunction("ContinueAction", [](std::shared_ptr action) { return std::shared_ptr(new ContinueAction(action)); }); #ifdef HAVE_DNS_OVER_HTTPS - g_lua.writeFunction("HTTPStatusAction", [](uint16_t status, std::string body, boost::optional contentType, boost::optional vars) { + luaCtx.writeFunction("HTTPStatusAction", [](uint16_t status, std::string body, boost::optional contentType, boost::optional vars) { auto ret = std::shared_ptr(new HTTPStatusAction(status, body, contentType ? *contentType : "")); auto hsa = std::dynamic_pointer_cast(ret); parseResponseConfig(vars, hsa->d_responseConfig); @@ -1843,18 +1843,18 @@ void setupLuaActions() }); #endif /* HAVE_DNS_OVER_HTTPS */ - g_lua.writeFunction("KeyValueStoreLookupAction", [](std::shared_ptr& kvs, std::shared_ptr& lookupKey, const std::string& destinationTag) { + luaCtx.writeFunction("KeyValueStoreLookupAction", [](std::shared_ptr& kvs, std::shared_ptr& lookupKey, const std::string& destinationTag) { return std::shared_ptr(new KeyValueStoreLookupAction(kvs, lookupKey, destinationTag)); }); - g_lua.writeFunction("SetNegativeAndSOAAction", [](bool nxd, const std::string& zone, uint32_t ttl, const std::string& mname, const std::string& rname, uint32_t serial, uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum, boost::optional vars) { + luaCtx.writeFunction("SetNegativeAndSOAAction", [](bool nxd, const std::string& zone, uint32_t ttl, const std::string& mname, const std::string& rname, uint32_t serial, uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum, boost::optional vars) { auto ret = std::shared_ptr(new SetNegativeAndSOAAction(nxd, DNSName(zone), ttl, DNSName(mname), DNSName(rname), serial, refresh, retry, expire, minimum)); auto action = std::dynamic_pointer_cast(ret); parseResponseConfig(vars, action->d_responseConfig); return ret; }); - g_lua.writeFunction("SetProxyProtocolValuesAction", [](const std::vector>& values) { + luaCtx.writeFunction("SetProxyProtocolValuesAction", [](const std::vector>& values) { return std::shared_ptr(new SetProxyProtocolValuesAction(values)); }); } diff --git a/pdns/dnsdist-lua-bindings-dnsquestion.cc b/pdns/dnsdist-lua-bindings-dnsquestion.cc index 9c87d129c8..eaa1ef31bc 100644 --- a/pdns/dnsdist-lua-bindings-dnsquestion.cc +++ b/pdns/dnsdist-lua-bindings-dnsquestion.cc @@ -24,27 +24,27 @@ #include "dnsdist-lua.hh" #include "dnsparser.hh" -void setupLuaBindingsDNSQuestion() +void setupLuaBindingsDNSQuestion(LuaContext& luaCtx) { /* DNSQuestion */ /* PowerDNS DNSQuestion compat */ - g_lua.registerMember("localaddr", [](const DNSQuestion& dq) -> const ComboAddress { return *dq.local; }, [](DNSQuestion& dq, const ComboAddress newLocal) { (void) newLocal; }); - g_lua.registerMember("qname", [](const DNSQuestion& dq) -> const DNSName { return *dq.qname; }, [](DNSQuestion& dq, const DNSName newName) { (void) newName; }); - g_lua.registerMember("qtype", [](const DNSQuestion& dq) -> uint16_t { return dq.qtype; }, [](DNSQuestion& dq, uint16_t newType) { (void) newType; }); - g_lua.registerMember("qclass", [](const DNSQuestion& dq) -> uint16_t { return dq.qclass; }, [](DNSQuestion& dq, uint16_t newClass) { (void) newClass; }); - g_lua.registerMember("rcode", [](const DNSQuestion& dq) -> int { return dq.dh->rcode; }, [](DNSQuestion& dq, int newRCode) { dq.dh->rcode = newRCode; }); - g_lua.registerMember("remoteaddr", [](const DNSQuestion& dq) -> const ComboAddress { return *dq.remote; }, [](DNSQuestion& dq, const ComboAddress newRemote) { (void) newRemote; }); + luaCtx.registerMember("localaddr", [](const DNSQuestion& dq) -> const ComboAddress { return *dq.local; }, [](DNSQuestion& dq, const ComboAddress newLocal) { (void) newLocal; }); + luaCtx.registerMember("qname", [](const DNSQuestion& dq) -> const DNSName { return *dq.qname; }, [](DNSQuestion& dq, const DNSName newName) { (void) newName; }); + luaCtx.registerMember("qtype", [](const DNSQuestion& dq) -> uint16_t { return dq.qtype; }, [](DNSQuestion& dq, uint16_t newType) { (void) newType; }); + luaCtx.registerMember("qclass", [](const DNSQuestion& dq) -> uint16_t { return dq.qclass; }, [](DNSQuestion& dq, uint16_t newClass) { (void) newClass; }); + luaCtx.registerMember("rcode", [](const DNSQuestion& dq) -> int { return dq.dh->rcode; }, [](DNSQuestion& dq, int newRCode) { dq.dh->rcode = newRCode; }); + luaCtx.registerMember("remoteaddr", [](const DNSQuestion& dq) -> const ComboAddress { return *dq.remote; }, [](DNSQuestion& dq, const ComboAddress newRemote) { (void) newRemote; }); /* DNSDist DNSQuestion */ - g_lua.registerMember("dh", &DNSQuestion::dh); - g_lua.registerMember("len", [](const DNSQuestion& dq) -> uint16_t { return dq.len; }, [](DNSQuestion& dq, uint16_t newlen) { dq.len = newlen; }); - g_lua.registerMember("opcode", [](const DNSQuestion& dq) -> uint8_t { return dq.dh->opcode; }, [](DNSQuestion& dq, uint8_t newOpcode) { (void) newOpcode; }); - g_lua.registerMember("size", [](const DNSQuestion& dq) -> size_t { return dq.size; }, [](DNSQuestion& dq, size_t newSize) { (void) newSize; }); - g_lua.registerMember("tcp", [](const DNSQuestion& dq) -> bool { return dq.tcp; }, [](DNSQuestion& dq, bool newTcp) { (void) newTcp; }); - g_lua.registerMember("skipCache", [](const DNSQuestion& dq) -> bool { return dq.skipCache; }, [](DNSQuestion& dq, bool newSkipCache) { dq.skipCache = newSkipCache; }); - g_lua.registerMember("useECS", [](const DNSQuestion& dq) -> bool { return dq.useECS; }, [](DNSQuestion& dq, bool useECS) { dq.useECS = useECS; }); - g_lua.registerMember("ecsOverride", [](const DNSQuestion& dq) -> bool { return dq.ecsOverride; }, [](DNSQuestion& dq, bool ecsOverride) { dq.ecsOverride = ecsOverride; }); - g_lua.registerMember("ecsPrefixLength", [](const DNSQuestion& dq) -> uint16_t { return dq.ecsPrefixLength; }, [](DNSQuestion& dq, uint16_t newPrefixLength) { dq.ecsPrefixLength = newPrefixLength; }); - g_lua.registerMember (DNSQuestion::*)>("tempFailureTTL", + luaCtx.registerMember("dh", &DNSQuestion::dh); + luaCtx.registerMember("len", [](const DNSQuestion& dq) -> uint16_t { return dq.len; }, [](DNSQuestion& dq, uint16_t newlen) { dq.len = newlen; }); + luaCtx.registerMember("opcode", [](const DNSQuestion& dq) -> uint8_t { return dq.dh->opcode; }, [](DNSQuestion& dq, uint8_t newOpcode) { (void) newOpcode; }); + luaCtx.registerMember("size", [](const DNSQuestion& dq) -> size_t { return dq.size; }, [](DNSQuestion& dq, size_t newSize) { (void) newSize; }); + luaCtx.registerMember("tcp", [](const DNSQuestion& dq) -> bool { return dq.tcp; }, [](DNSQuestion& dq, bool newTcp) { (void) newTcp; }); + luaCtx.registerMember("skipCache", [](const DNSQuestion& dq) -> bool { return dq.skipCache; }, [](DNSQuestion& dq, bool newSkipCache) { dq.skipCache = newSkipCache; }); + luaCtx.registerMember("useECS", [](const DNSQuestion& dq) -> bool { return dq.useECS; }, [](DNSQuestion& dq, bool useECS) { dq.useECS = useECS; }); + luaCtx.registerMember("ecsOverride", [](const DNSQuestion& dq) -> bool { return dq.ecsOverride; }, [](DNSQuestion& dq, bool ecsOverride) { dq.ecsOverride = ecsOverride; }); + luaCtx.registerMember("ecsPrefixLength", [](const DNSQuestion& dq) -> uint16_t { return dq.ecsPrefixLength; }, [](DNSQuestion& dq, uint16_t newPrefixLength) { dq.ecsPrefixLength = newPrefixLength; }); + luaCtx.registerMember (DNSQuestion::*)>("tempFailureTTL", [](const DNSQuestion& dq) -> boost::optional { return dq.tempFailureTTL; }, @@ -52,29 +52,29 @@ void setupLuaBindingsDNSQuestion() dq.tempFailureTTL = newValue; } ); - g_lua.registerFunction("getDO", [](const DNSQuestion& dq) { + luaCtx.registerFunction("getDO", [](const DNSQuestion& dq) { return getEDNSZ(dq) & EDNS_HEADER_FLAG_DO; }); - g_lua.registerFunction(DNSQuestion::*)()>("getEDNSOptions", [](DNSQuestion& dq) { + luaCtx.registerFunction(DNSQuestion::*)()>("getEDNSOptions", [](DNSQuestion& dq) { if (dq.ednsOptions == nullptr) { parseEDNSOptions(dq); } return *dq.ednsOptions; }); - g_lua.registerFunction("getTrailingData", [](const DNSQuestion& dq) { + luaCtx.registerFunction("getTrailingData", [](const DNSQuestion& dq) { return dq.getTrailingData(); }); - g_lua.registerFunction("setTrailingData", [](DNSQuestion& dq, const std::string& tail) { + luaCtx.registerFunction("setTrailingData", [](DNSQuestion& dq, const std::string& tail) { return dq.setTrailingData(tail); }); - g_lua.registerFunction("getServerNameIndication", [](const DNSQuestion& dq) { + luaCtx.registerFunction("getServerNameIndication", [](const DNSQuestion& dq) { return dq.sni; }); - g_lua.registerFunction("sendTrap", [](const DNSQuestion& dq, boost::optional reason) { + luaCtx.registerFunction("sendTrap", [](const DNSQuestion& dq, boost::optional reason) { #ifdef HAVE_NET_SNMP if (g_snmpAgent && g_snmpTrapsEnabled) { g_snmpAgent->sendDNSTrap(dq, reason ? *reason : ""); @@ -82,13 +82,13 @@ void setupLuaBindingsDNSQuestion() #endif /* HAVE_NET_SNMP */ }); - g_lua.registerFunction("setTag", [](DNSQuestion& dq, const std::string& strLabel, const std::string& strValue) { + luaCtx.registerFunction("setTag", [](DNSQuestion& dq, const std::string& strLabel, const std::string& strValue) { if(dq.qTag == nullptr) { dq.qTag = std::make_shared(); } dq.qTag->insert({strLabel, strValue}); }); - g_lua.registerFunction>)>("setTagArray", [](DNSQuestion& dq, const vector>&tags) { + luaCtx.registerFunction>)>("setTagArray", [](DNSQuestion& dq, const vector>&tags) { if (!dq.qTag) { dq.qTag = std::make_shared(); } @@ -97,7 +97,7 @@ void setupLuaBindingsDNSQuestion() dq.qTag->insert({tag.first, tag.second}); } }); - g_lua.registerFunction("getTag", [](const DNSQuestion& dq, const std::string& strLabel) { + luaCtx.registerFunction("getTag", [](const DNSQuestion& dq, const std::string& strLabel) { if (!dq.qTag) { return string(); } @@ -109,7 +109,7 @@ void setupLuaBindingsDNSQuestion() } return it->second; }); - g_lua.registerFunction("getTagArray", [](const DNSQuestion& dq) { + luaCtx.registerFunction("getTagArray", [](const DNSQuestion& dq) { if (!dq.qTag) { QTag empty; return empty; @@ -118,7 +118,7 @@ void setupLuaBindingsDNSQuestion() return *dq.qTag; }); - g_lua.registerFunction>)>("setProxyProtocolValues", [](DNSQuestion& dq, const std::vector>& values) { + luaCtx.registerFunction>)>("setProxyProtocolValues", [](DNSQuestion& dq, const std::vector>& values) { if (!dq.proxyProtocolValues) { dq.proxyProtocolValues = make_unique>(); } @@ -131,36 +131,36 @@ void setupLuaBindingsDNSQuestion() }); /* LuaWrapper doesn't support inheritance */ - g_lua.registerMember("localaddr", [](const DNSResponse& dq) -> const ComboAddress { return *dq.local; }, [](DNSResponse& dq, const ComboAddress newLocal) { (void) newLocal; }); - g_lua.registerMember("qname", [](const DNSResponse& dq) -> const DNSName { return *dq.qname; }, [](DNSResponse& dq, const DNSName newName) { (void) newName; }); - g_lua.registerMember("qtype", [](const DNSResponse& dq) -> uint16_t { return dq.qtype; }, [](DNSResponse& dq, uint16_t newType) { (void) newType; }); - g_lua.registerMember("qclass", [](const DNSResponse& dq) -> uint16_t { return dq.qclass; }, [](DNSResponse& dq, uint16_t newClass) { (void) newClass; }); - g_lua.registerMember("rcode", [](const DNSResponse& dq) -> int { return dq.dh->rcode; }, [](DNSResponse& dq, int newRCode) { dq.dh->rcode = newRCode; }); - g_lua.registerMember("remoteaddr", [](const DNSResponse& dq) -> const ComboAddress { return *dq.remote; }, [](DNSResponse& dq, const ComboAddress newRemote) { (void) newRemote; }); - g_lua.registerMember("dh", [](const DNSResponse& dr) -> dnsheader* { return dr.dh; }, [](DNSResponse& dr, dnsheader * newdh) { dr.dh = newdh; }); - g_lua.registerMember("len", [](const DNSResponse& dq) -> uint16_t { return dq.len; }, [](DNSResponse& dq, uint16_t newlen) { dq.len = newlen; }); - g_lua.registerMember("opcode", [](const DNSResponse& dq) -> uint8_t { return dq.dh->opcode; }, [](DNSResponse& dq, uint8_t newOpcode) { (void) newOpcode; }); - g_lua.registerMember("size", [](const DNSResponse& dq) -> size_t { return dq.size; }, [](DNSResponse& dq, size_t newSize) { (void) newSize; }); - g_lua.registerMember("tcp", [](const DNSResponse& dq) -> bool { return dq.tcp; }, [](DNSResponse& dq, bool newTcp) { (void) newTcp; }); - g_lua.registerMember("skipCache", [](const DNSResponse& dq) -> bool { return dq.skipCache; }, [](DNSResponse& dq, bool newSkipCache) { dq.skipCache = newSkipCache; }); - g_lua.registerFunction editFunc)>("editTTLs", [](const DNSResponse& dr, std::function editFunc) { + luaCtx.registerMember("localaddr", [](const DNSResponse& dq) -> const ComboAddress { return *dq.local; }, [](DNSResponse& dq, const ComboAddress newLocal) { (void) newLocal; }); + luaCtx.registerMember("qname", [](const DNSResponse& dq) -> const DNSName { return *dq.qname; }, [](DNSResponse& dq, const DNSName newName) { (void) newName; }); + luaCtx.registerMember("qtype", [](const DNSResponse& dq) -> uint16_t { return dq.qtype; }, [](DNSResponse& dq, uint16_t newType) { (void) newType; }); + luaCtx.registerMember("qclass", [](const DNSResponse& dq) -> uint16_t { return dq.qclass; }, [](DNSResponse& dq, uint16_t newClass) { (void) newClass; }); + luaCtx.registerMember("rcode", [](const DNSResponse& dq) -> int { return dq.dh->rcode; }, [](DNSResponse& dq, int newRCode) { dq.dh->rcode = newRCode; }); + luaCtx.registerMember("remoteaddr", [](const DNSResponse& dq) -> const ComboAddress { return *dq.remote; }, [](DNSResponse& dq, const ComboAddress newRemote) { (void) newRemote; }); + luaCtx.registerMember("dh", [](const DNSResponse& dr) -> dnsheader* { return dr.dh; }, [](DNSResponse& dr, dnsheader * newdh) { dr.dh = newdh; }); + luaCtx.registerMember("len", [](const DNSResponse& dq) -> uint16_t { return dq.len; }, [](DNSResponse& dq, uint16_t newlen) { dq.len = newlen; }); + luaCtx.registerMember("opcode", [](const DNSResponse& dq) -> uint8_t { return dq.dh->opcode; }, [](DNSResponse& dq, uint8_t newOpcode) { (void) newOpcode; }); + luaCtx.registerMember("size", [](const DNSResponse& dq) -> size_t { return dq.size; }, [](DNSResponse& dq, size_t newSize) { (void) newSize; }); + luaCtx.registerMember("tcp", [](const DNSResponse& dq) -> bool { return dq.tcp; }, [](DNSResponse& dq, bool newTcp) { (void) newTcp; }); + luaCtx.registerMember("skipCache", [](const DNSResponse& dq) -> bool { return dq.skipCache; }, [](DNSResponse& dq, bool newSkipCache) { dq.skipCache = newSkipCache; }); + luaCtx.registerFunction editFunc)>("editTTLs", [](const DNSResponse& dr, std::function editFunc) { editDNSPacketTTL((char*) dr.dh, dr.len, editFunc); }); - g_lua.registerFunction("getTrailingData", [](const DNSResponse& dq) { + luaCtx.registerFunction("getTrailingData", [](const DNSResponse& dq) { return dq.getTrailingData(); }); - g_lua.registerFunction("setTrailingData", [](DNSResponse& dq, const std::string& tail) { + luaCtx.registerFunction("setTrailingData", [](DNSResponse& dq, const std::string& tail) { return dq.setTrailingData(tail); }); - g_lua.registerFunction("setTag", [](DNSResponse& dr, const std::string& strLabel, const std::string& strValue) { + luaCtx.registerFunction("setTag", [](DNSResponse& dr, const std::string& strLabel, const std::string& strValue) { if(dr.qTag == nullptr) { dr.qTag = std::make_shared(); } dr.qTag->insert({strLabel, strValue}); }); - g_lua.registerFunction>)>("setTagArray", [](DNSResponse& dr, const vector>&tags) { + luaCtx.registerFunction>)>("setTagArray", [](DNSResponse& dr, const vector>&tags) { if (!dr.qTag) { dr.qTag = std::make_shared(); } @@ -169,7 +169,7 @@ void setupLuaBindingsDNSQuestion() dr.qTag->insert({tag.first, tag.second}); } }); - g_lua.registerFunction("getTag", [](const DNSResponse& dr, const std::string& strLabel) { + luaCtx.registerFunction("getTag", [](const DNSResponse& dr, const std::string& strLabel) { if (!dr.qTag) { return string(); } @@ -181,7 +181,7 @@ void setupLuaBindingsDNSQuestion() } return it->second; }); - g_lua.registerFunction("getTagArray", [](const DNSResponse& dr) { + luaCtx.registerFunction("getTagArray", [](const DNSResponse& dr) { if (!dr.qTag) { QTag empty; return empty; @@ -190,7 +190,7 @@ void setupLuaBindingsDNSQuestion() return *dr.qTag; }); - g_lua.registerFunction("sendTrap", [](const DNSResponse& dr, boost::optional reason) { + luaCtx.registerFunction("sendTrap", [](const DNSResponse& dr, boost::optional reason) { #ifdef HAVE_NET_SNMP if (g_snmpAgent && g_snmpTrapsEnabled) { g_snmpAgent->sendDNSTrap(dr, reason ? *reason : ""); @@ -199,42 +199,42 @@ void setupLuaBindingsDNSQuestion() }); #ifdef HAVE_DNS_OVER_HTTPS - g_lua.registerFunction("getHTTPPath", [](const DNSQuestion& dq) { + luaCtx.registerFunction("getHTTPPath", [](const DNSQuestion& dq) { if (dq.du == nullptr) { return std::string(); } return dq.du->getHTTPPath(); }); - g_lua.registerFunction("getHTTPQueryString", [](const DNSQuestion& dq) { + luaCtx.registerFunction("getHTTPQueryString", [](const DNSQuestion& dq) { if (dq.du == nullptr) { return std::string(); } return dq.du->getHTTPQueryString(); }); - g_lua.registerFunction("getHTTPHost", [](const DNSQuestion& dq) { + luaCtx.registerFunction("getHTTPHost", [](const DNSQuestion& dq) { if (dq.du == nullptr) { return std::string(); } return dq.du->getHTTPHost(); }); - g_lua.registerFunction("getHTTPScheme", [](const DNSQuestion& dq) { + luaCtx.registerFunction("getHTTPScheme", [](const DNSQuestion& dq) { if (dq.du == nullptr) { return std::string(); } return dq.du->getHTTPScheme(); }); - g_lua.registerFunction(DNSQuestion::*)(void)>("getHTTPHeaders", [](const DNSQuestion& dq) { + luaCtx.registerFunction(DNSQuestion::*)(void)>("getHTTPHeaders", [](const DNSQuestion& dq) { if (dq.du == nullptr) { return std::unordered_map(); } return dq.du->getHTTPHeaders(); }); - g_lua.registerFunction contentType)>("setHTTPResponse", [](DNSQuestion& dq, uint16_t statusCode, const std::string& body, const boost::optional contentType) { + luaCtx.registerFunction contentType)>("setHTTPResponse", [](DNSQuestion& dq, uint16_t statusCode, const std::string& body, const boost::optional contentType) { if (dq.du == nullptr) { return; } @@ -242,7 +242,7 @@ void setupLuaBindingsDNSQuestion() }); #endif /* HAVE_DNS_OVER_HTTPS */ - g_lua.registerFunction("setNegativeAndAdditionalSOA", [](DNSQuestion& dq, bool nxd, const std::string& zone, uint32_t ttl, const std::string& mname, const std::string& rname, uint32_t serial, uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum) { + luaCtx.registerFunction("setNegativeAndAdditionalSOA", [](DNSQuestion& dq, bool nxd, const std::string& zone, uint32_t ttl, const std::string& mname, const std::string& rname, uint32_t serial, uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum) { return setNegativeAndAdditionalSOA(dq, nxd, DNSName(zone), ttl, DNSName(mname), DNSName(rname), serial, refresh, retry, expire, minimum); }); } diff --git a/pdns/dnsdist-lua-bindings.cc b/pdns/dnsdist-lua-bindings.cc index ba4cf9eac4..62c679336b 100644 --- a/pdns/dnsdist-lua-bindings.cc +++ b/pdns/dnsdist-lua-bindings.cc @@ -25,24 +25,24 @@ #include "dolog.hh" -void setupLuaBindings(bool client) +void setupLuaBindings(LuaContext& luaCtx, bool client) { - g_lua.writeFunction("infolog", [](const string& arg) { + luaCtx.writeFunction("infolog", [](const string& arg) { infolog("%s", arg); }); - g_lua.writeFunction("errlog", [](const string& arg) { + luaCtx.writeFunction("errlog", [](const string& arg) { errlog("%s", arg); }); - g_lua.writeFunction("warnlog", [](const string& arg) { + luaCtx.writeFunction("warnlog", [](const string& arg) { warnlog("%s", arg); }); - g_lua.writeFunction("show", [](const string& arg) { + luaCtx.writeFunction("show", [](const string& arg) { g_outputBuffer+=arg; g_outputBuffer+="\n"; }); /* Exceptions */ - g_lua.registerFunction("__tostring", [](const std::exception_ptr& eptr) { + luaCtx.registerFunction("__tostring", [](const std::exception_ptr& eptr) { try { if (eptr) { std::rethrow_exception(eptr); @@ -57,125 +57,126 @@ void setupLuaBindings(bool client) return string("No exception"); }); /* ServerPolicy */ - g_lua.writeFunction("newServerPolicy", [](string name, ServerPolicy::policyfunc_t policy) { return std::make_shared(name, policy, true);}); - g_lua.registerMember("name", &ServerPolicy::name); - g_lua.registerMember("policy", &ServerPolicy::policy); - g_lua.registerMember("ffipolicy", &ServerPolicy::ffipolicy); - g_lua.registerMember("isLua", &ServerPolicy::isLua); - g_lua.registerMember("isFFI", &ServerPolicy::isFFI); - g_lua.registerFunction("toString", &ServerPolicy::toString); - - g_lua.writeVariable("firstAvailable", ServerPolicy{"firstAvailable", firstAvailable, false}); - g_lua.writeVariable("roundrobin", ServerPolicy{"roundrobin", roundrobin, false}); - g_lua.writeVariable("wrandom", ServerPolicy{"wrandom", wrandom, false}); - g_lua.writeVariable("whashed", ServerPolicy{"whashed", whashed, false}); - g_lua.writeVariable("chashed", ServerPolicy{"chashed", chashed, false}); - g_lua.writeVariable("leastOutstanding", ServerPolicy{"leastOutstanding", leastOutstanding, false}); + luaCtx.writeFunction("newServerPolicy", [](string name, ServerPolicy::policyfunc_t policy) { return std::make_shared(name, policy, true);}); + luaCtx.registerMember("name", &ServerPolicy::d_name); + luaCtx.registerMember("policy", &ServerPolicy::d_policy); + luaCtx.registerMember("ffipolicy", &ServerPolicy::d_ffipolicy); + luaCtx.registerMember("isLua", &ServerPolicy::d_isLua); + luaCtx.registerMember("isFFI", &ServerPolicy::d_isFFI); + luaCtx.registerMember("isPerThread", &ServerPolicy::d_isPerThread); + luaCtx.registerFunction("toString", &ServerPolicy::toString); + + luaCtx.writeVariable("firstAvailable", ServerPolicy{"firstAvailable", firstAvailable, false}); + luaCtx.writeVariable("roundrobin", ServerPolicy{"roundrobin", roundrobin, false}); + luaCtx.writeVariable("wrandom", ServerPolicy{"wrandom", wrandom, false}); + luaCtx.writeVariable("whashed", ServerPolicy{"whashed", whashed, false}); + luaCtx.writeVariable("chashed", ServerPolicy{"chashed", chashed, false}); + luaCtx.writeVariable("leastOutstanding", ServerPolicy{"leastOutstanding", leastOutstanding, false}); /* ServerPool */ - g_lua.registerFunction::*)(std::shared_ptr)>("setCache", [](std::shared_ptr pool, std::shared_ptr cache) { + luaCtx.registerFunction::*)(std::shared_ptr)>("setCache", [](std::shared_ptr pool, std::shared_ptr cache) { if (pool) { pool->packetCache = cache; } }); - g_lua.registerFunction("getCache", &ServerPool::getCache); - g_lua.registerFunction::*)()>("unsetCache", [](std::shared_ptr pool) { + luaCtx.registerFunction("getCache", &ServerPool::getCache); + luaCtx.registerFunction::*)()>("unsetCache", [](std::shared_ptr pool) { if (pool) { pool->packetCache = nullptr; } }); - g_lua.registerFunction("getECS", &ServerPool::getECS); - g_lua.registerFunction("setECS", &ServerPool::setECS); + luaCtx.registerFunction("getECS", &ServerPool::getECS); + luaCtx.registerFunction("setECS", &ServerPool::setECS); /* DownstreamState */ - g_lua.registerFunction("setQPS", [](DownstreamState& s, int lim) { s.qps = lim ? QPSLimiter(lim, lim) : QPSLimiter(); }); - g_lua.registerFunction::*)(string)>("addPool", [](std::shared_ptr s, string pool) { + luaCtx.registerFunction("setQPS", [](DownstreamState& s, int lim) { s.qps = lim ? QPSLimiter(lim, lim) : QPSLimiter(); }); + luaCtx.registerFunction::*)(string)>("addPool", [](std::shared_ptr s, string pool) { auto localPools = g_pools.getCopy(); addServerToPool(localPools, pool, s); g_pools.setState(localPools); s->pools.insert(pool); }); - g_lua.registerFunction::*)(string)>("rmPool", [](std::shared_ptr s, string pool) { + luaCtx.registerFunction::*)(string)>("rmPool", [](std::shared_ptr s, string pool) { auto localPools = g_pools.getCopy(); removeServerFromPool(localPools, pool, s); g_pools.setState(localPools); s->pools.erase(pool); }); - g_lua.registerFunction("getOutstanding", [](const DownstreamState& s) { return s.outstanding.load(); }); - g_lua.registerFunction("getLatency", [](const DownstreamState& s) { return s.latencyUsec; }); - g_lua.registerFunction("isUp", &DownstreamState::isUp); - g_lua.registerFunction("setDown", &DownstreamState::setDown); - g_lua.registerFunction("setUp", &DownstreamState::setUp); - g_lua.registerFunction newStatus)>("setAuto", [](DownstreamState& s, boost::optional newStatus) { + luaCtx.registerFunction("getOutstanding", [](const DownstreamState& s) { return s.outstanding.load(); }); + luaCtx.registerFunction("getLatency", [](const DownstreamState& s) { return s.latencyUsec; }); + luaCtx.registerFunction("isUp", &DownstreamState::isUp); + luaCtx.registerFunction("setDown", &DownstreamState::setDown); + luaCtx.registerFunction("setUp", &DownstreamState::setUp); + luaCtx.registerFunction newStatus)>("setAuto", [](DownstreamState& s, boost::optional newStatus) { if (newStatus) { s.upStatus = *newStatus; } s.setAuto(); }); - g_lua.registerFunction("getName", [](const DownstreamState& s) { return s.getName(); }); - g_lua.registerFunction("getNameWithAddr", [](const DownstreamState& s) { return s.getNameWithAddr(); }); - g_lua.registerMember("upStatus", &DownstreamState::upStatus); - g_lua.registerMember("weight", + luaCtx.registerFunction("getName", [](const DownstreamState& s) { return s.getName(); }); + luaCtx.registerFunction("getNameWithAddr", [](const DownstreamState& s) { return s.getNameWithAddr(); }); + luaCtx.registerMember("upStatus", &DownstreamState::upStatus); + luaCtx.registerMember("weight", [](const DownstreamState& s) -> int {return s.weight;}, [](DownstreamState& s, int newWeight) {s.setWeight(newWeight);} ); - g_lua.registerMember("order", &DownstreamState::order); - g_lua.registerMember("name", [](const DownstreamState& backend) -> const std::string { return backend.getName(); }, [](DownstreamState& backend, const std::string& newName) { backend.setName(newName); }); - g_lua.registerFunction("getID", [](const DownstreamState& s) { return boost::uuids::to_string(s.id); }); + luaCtx.registerMember("order", &DownstreamState::order); + luaCtx.registerMember("name", [](const DownstreamState& backend) -> const std::string { return backend.getName(); }, [](DownstreamState& backend, const std::string& newName) { backend.setName(newName); }); + luaCtx.registerFunction("getID", [](const DownstreamState& s) { return boost::uuids::to_string(s.id); }); /* dnsheader */ - g_lua.registerFunction("setRD", [](dnsheader& dh, bool v) { + luaCtx.registerFunction("setRD", [](dnsheader& dh, bool v) { dh.rd=v; }); - g_lua.registerFunction("getRD", [](dnsheader& dh) { + luaCtx.registerFunction("getRD", [](dnsheader& dh) { return (bool)dh.rd; }); - g_lua.registerFunction("setRA", [](dnsheader& dh, bool v) { + luaCtx.registerFunction("setRA", [](dnsheader& dh, bool v) { dh.ra=v; }); - g_lua.registerFunction("getRA", [](dnsheader& dh) { + luaCtx.registerFunction("getRA", [](dnsheader& dh) { return (bool)dh.ra; }); - g_lua.registerFunction("setAD", [](dnsheader& dh, bool v) { + luaCtx.registerFunction("setAD", [](dnsheader& dh, bool v) { dh.ad=v; }); - g_lua.registerFunction("getAD", [](dnsheader& dh) { + luaCtx.registerFunction("getAD", [](dnsheader& dh) { return (bool)dh.ad; }); - g_lua.registerFunction("setAA", [](dnsheader& dh, bool v) { + luaCtx.registerFunction("setAA", [](dnsheader& dh, bool v) { dh.aa=v; }); - g_lua.registerFunction("getAA", [](dnsheader& dh) { + luaCtx.registerFunction("getAA", [](dnsheader& dh) { return (bool)dh.aa; }); - g_lua.registerFunction("setCD", [](dnsheader& dh, bool v) { + luaCtx.registerFunction("setCD", [](dnsheader& dh, bool v) { dh.cd=v; }); - g_lua.registerFunction("getCD", [](dnsheader& dh) { + luaCtx.registerFunction("getCD", [](dnsheader& dh) { return (bool)dh.cd; }); - g_lua.registerFunction("setTC", [](dnsheader& dh, bool v) { + luaCtx.registerFunction("setTC", [](dnsheader& dh, bool v) { dh.tc=v; if(v) dh.ra = dh.rd; // you'll always need this, otherwise TC=1 gets ignored }); - g_lua.registerFunction("setQR", [](dnsheader& dh, bool v) { + luaCtx.registerFunction("setQR", [](dnsheader& dh, bool v) { dh.qr=v; }); /* ComboAddress */ - g_lua.writeFunction("newCA", [](const std::string& name) { return ComboAddress(name); }); - g_lua.writeFunction("newCAFromRaw", [](const std::string& raw, boost::optional port) { + luaCtx.writeFunction("newCA", [](const std::string& name) { return ComboAddress(name); }); + luaCtx.writeFunction("newCAFromRaw", [](const std::string& raw, boost::optional port) { if (raw.size() == 4) { struct sockaddr_in sin4; memset(&sin4, 0, sizeof(sin4)); @@ -198,42 +199,42 @@ void setupLuaBindings(bool client) } return ComboAddress(); }); - g_lua.registerFunction("tostring", [](const ComboAddress& ca) { return ca.toString(); }); - g_lua.registerFunction("tostringWithPort", [](const ComboAddress& ca) { return ca.toStringWithPort(); }); - g_lua.registerFunction("toString", [](const ComboAddress& ca) { return ca.toString(); }); - g_lua.registerFunction("toStringWithPort", [](const ComboAddress& ca) { return ca.toStringWithPort(); }); - g_lua.registerFunction("getPort", [](const ComboAddress& ca) { return ntohs(ca.sin4.sin_port); } ); - g_lua.registerFunction("truncate", [](ComboAddress& ca, unsigned int bits) { ca.truncate(bits); }); - g_lua.registerFunction("isIPv4", [](const ComboAddress& ca) { return ca.sin4.sin_family == AF_INET; }); - g_lua.registerFunction("isIPv6", [](const ComboAddress& ca) { return ca.sin4.sin_family == AF_INET6; }); - g_lua.registerFunction("isMappedIPv4", [](const ComboAddress& ca) { return ca.isMappedIPv4(); }); - g_lua.registerFunction("mapToIPv4", [](const ComboAddress& ca) { return ca.mapToIPv4(); }); - g_lua.registerFunction("match", [](nmts_t& s, const ComboAddress& ca) { return s.match(ca); }); + luaCtx.registerFunction("tostring", [](const ComboAddress& ca) { return ca.toString(); }); + luaCtx.registerFunction("tostringWithPort", [](const ComboAddress& ca) { return ca.toStringWithPort(); }); + luaCtx.registerFunction("toString", [](const ComboAddress& ca) { return ca.toString(); }); + luaCtx.registerFunction("toStringWithPort", [](const ComboAddress& ca) { return ca.toStringWithPort(); }); + luaCtx.registerFunction("getPort", [](const ComboAddress& ca) { return ntohs(ca.sin4.sin_port); } ); + luaCtx.registerFunction("truncate", [](ComboAddress& ca, unsigned int bits) { ca.truncate(bits); }); + luaCtx.registerFunction("isIPv4", [](const ComboAddress& ca) { return ca.sin4.sin_family == AF_INET; }); + luaCtx.registerFunction("isIPv6", [](const ComboAddress& ca) { return ca.sin4.sin_family == AF_INET6; }); + luaCtx.registerFunction("isMappedIPv4", [](const ComboAddress& ca) { return ca.isMappedIPv4(); }); + luaCtx.registerFunction("mapToIPv4", [](const ComboAddress& ca) { return ca.mapToIPv4(); }); + luaCtx.registerFunction("match", [](nmts_t& s, const ComboAddress& ca) { return s.match(ca); }); /* DNSName */ - g_lua.registerFunction("isPartOf", &DNSName::isPartOf); - g_lua.registerFunction("chopOff", [](DNSName&dn ) { return dn.chopOff(); }); - g_lua.registerFunction("countLabels", [](const DNSName& name) { return name.countLabels(); }); - g_lua.registerFunction("hash", [](const DNSName& name) { return name.hash(); }); - g_lua.registerFunction("wirelength", [](const DNSName& name) { return name.wirelength(); }); - g_lua.registerFunction("tostring", [](const DNSName&dn ) { return dn.toString(); }); - g_lua.registerFunction("toString", [](const DNSName&dn ) { return dn.toString(); }); - g_lua.writeFunction("newDNSName", [](const std::string& name) { return DNSName(name); }); - g_lua.writeFunction("newDNSNameFromRaw", [](const std::string& name) { return DNSName(name.c_str(), name.size(), 0, false); }); - g_lua.writeFunction("newSuffixMatchNode", []() { return SuffixMatchNode(); }); - g_lua.writeFunction("newDNSNameSet", []() { return DNSNameSet(); }); + luaCtx.registerFunction("isPartOf", &DNSName::isPartOf); + luaCtx.registerFunction("chopOff", [](DNSName&dn ) { return dn.chopOff(); }); + luaCtx.registerFunction("countLabels", [](const DNSName& name) { return name.countLabels(); }); + luaCtx.registerFunction("hash", [](const DNSName& name) { return name.hash(); }); + luaCtx.registerFunction("wirelength", [](const DNSName& name) { return name.wirelength(); }); + luaCtx.registerFunction("tostring", [](const DNSName&dn ) { return dn.toString(); }); + luaCtx.registerFunction("toString", [](const DNSName&dn ) { return dn.toString(); }); + luaCtx.writeFunction("newDNSName", [](const std::string& name) { return DNSName(name); }); + luaCtx.writeFunction("newDNSNameFromRaw", [](const std::string& name) { return DNSName(name.c_str(), name.size(), 0, false); }); + luaCtx.writeFunction("newSuffixMatchNode", []() { return SuffixMatchNode(); }); + luaCtx.writeFunction("newDNSNameSet", []() { return DNSNameSet(); }); /* DNSNameSet */ - g_lua.registerFunction("toString", [](const DNSNameSet&dns ) { return dns.toString(); }); - g_lua.registerFunction("add", [](DNSNameSet& dns, DNSName& dn) { dns.insert(dn); }); - g_lua.registerFunction("check", [](DNSNameSet& dns, DNSName& dn) { return dns.find(dn) != dns.end(); }); - g_lua.registerFunction("delete",(size_t (DNSNameSet::*)(const DNSName&)) &DNSNameSet::erase); - g_lua.registerFunction("size",(size_t (DNSNameSet::*)() const) &DNSNameSet::size); - g_lua.registerFunction("clear",(void (DNSNameSet::*)()) &DNSNameSet::clear); - g_lua.registerFunction("empty",(bool (DNSNameSet::*)()) &DNSNameSet::empty); + luaCtx.registerFunction("toString", [](const DNSNameSet&dns ) { return dns.toString(); }); + luaCtx.registerFunction("add", [](DNSNameSet& dns, DNSName& dn) { dns.insert(dn); }); + luaCtx.registerFunction("check", [](DNSNameSet& dns, DNSName& dn) { return dns.find(dn) != dns.end(); }); + luaCtx.registerFunction("delete",(size_t (DNSNameSet::*)(const DNSName&)) &DNSNameSet::erase); + luaCtx.registerFunction("size",(size_t (DNSNameSet::*)() const) &DNSNameSet::size); + luaCtx.registerFunction("clear",(void (DNSNameSet::*)()) &DNSNameSet::clear); + luaCtx.registerFunction("empty",(bool (DNSNameSet::*)()) &DNSNameSet::empty); /* SuffixMatchNode */ - g_lua.registerFunction>, vector>> &name)>("add", [](SuffixMatchNode &smn, const boost::variant>, vector>> &name) { + luaCtx.registerFunction>, vector>> &name)>("add", [](SuffixMatchNode &smn, const boost::variant>, vector>> &name) { if (name.type() == typeid(DNSName)) { auto n = boost::get(name); smn.add(n); @@ -259,7 +260,7 @@ void setupLuaBindings(bool client) return; } }); - g_lua.registerFunction>, vector>> &name)>("remove", [](SuffixMatchNode &smn, const boost::variant>, vector>> &name) { + luaCtx.registerFunction>, vector>> &name)>("remove", [](SuffixMatchNode &smn, const boost::variant>, vector>> &name) { if (name.type() == typeid(DNSName)) { auto n = boost::get(name); smn.remove(n); @@ -288,10 +289,10 @@ void setupLuaBindings(bool client) } }); - g_lua.registerFunction("check",(bool (SuffixMatchNode::*)(const DNSName&) const) &SuffixMatchNode::check); + luaCtx.registerFunction("check",(bool (SuffixMatchNode::*)(const DNSName&) const) &SuffixMatchNode::check); /* Netmask */ - g_lua.writeFunction("newNetmask", [](boost::variant s, boost::optional bits) { + luaCtx.writeFunction("newNetmask", [](boost::variant s, boost::optional bits) { if (s.type() == typeid(ComboAddress)) { auto ca = boost::get(s); if (bits) { @@ -305,92 +306,92 @@ void setupLuaBindings(bool client) } throw std::runtime_error("Invalid parameter passed to 'newNetmask()'"); }); - g_lua.registerFunction("empty", &Netmask::empty); - g_lua.registerFunction("getBits", &Netmask::getBits); - g_lua.registerFunction("getNetwork", [](const Netmask& nm) { return nm.getNetwork(); } ); // const reference makes this necessary - g_lua.registerFunction("getMaskedNetwork", [](const Netmask& nm) { return nm.getMaskedNetwork(); } ); - g_lua.registerFunction("isIpv4", &Netmask::isIPv4); - g_lua.registerFunction("isIPv4", &Netmask::isIPv4); - g_lua.registerFunction("isIpv6", &Netmask::isIPv6); - g_lua.registerFunction("isIPv6", &Netmask::isIPv6); - g_lua.registerFunction("match", (bool (Netmask::*)(const string&) const)&Netmask::match); - g_lua.registerFunction("toString", &Netmask::toString); - g_lua.registerEqFunction(&Netmask::operator==); - g_lua.registerToStringFunction(&Netmask::toString); + luaCtx.registerFunction("empty", &Netmask::empty); + luaCtx.registerFunction("getBits", &Netmask::getBits); + luaCtx.registerFunction("getNetwork", [](const Netmask& nm) { return nm.getNetwork(); } ); // const reference makes this necessary + luaCtx.registerFunction("getMaskedNetwork", [](const Netmask& nm) { return nm.getMaskedNetwork(); } ); + luaCtx.registerFunction("isIpv4", &Netmask::isIPv4); + luaCtx.registerFunction("isIPv4", &Netmask::isIPv4); + luaCtx.registerFunction("isIpv6", &Netmask::isIPv6); + luaCtx.registerFunction("isIPv6", &Netmask::isIPv6); + luaCtx.registerFunction("match", (bool (Netmask::*)(const string&) const)&Netmask::match); + luaCtx.registerFunction("toString", &Netmask::toString); + luaCtx.registerEqFunction(&Netmask::operator==); + luaCtx.registerToStringFunction(&Netmask::toString); /* NetmaskGroup */ - g_lua.writeFunction("newNMG", []() { return NetmaskGroup(); }); - g_lua.registerFunction("addMask", [](NetmaskGroup&nmg, const std::string& mask) + luaCtx.writeFunction("newNMG", []() { return NetmaskGroup(); }); + luaCtx.registerFunction("addMask", [](NetmaskGroup&nmg, const std::string& mask) { nmg.addMask(mask); }); - g_lua.registerFunction& map)>("addMasks", [](NetmaskGroup&nmg, const std::map& map) + luaCtx.registerFunction& map)>("addMasks", [](NetmaskGroup&nmg, const std::map& map) { for (const auto& entry : map) { nmg.addMask(Netmask(entry.first)); } }); - g_lua.registerFunction("match", (bool (NetmaskGroup::*)(const ComboAddress&) const)&NetmaskGroup::match); - g_lua.registerFunction("size", &NetmaskGroup::size); - g_lua.registerFunction("clear", &NetmaskGroup::clear); - g_lua.registerFunction("toString", [](const NetmaskGroup& nmg ) { return "NetmaskGroup " + nmg.toString(); }); + luaCtx.registerFunction("match", (bool (NetmaskGroup::*)(const ComboAddress&) const)&NetmaskGroup::match); + luaCtx.registerFunction("size", &NetmaskGroup::size); + luaCtx.registerFunction("clear", &NetmaskGroup::clear); + luaCtx.registerFunction("toString", [](const NetmaskGroup& nmg ) { return "NetmaskGroup " + nmg.toString(); }); /* QPSLimiter */ - g_lua.writeFunction("newQPSLimiter", [](int rate, int burst) { return QPSLimiter(rate, burst); }); - g_lua.registerFunction("check", &QPSLimiter::check); + luaCtx.writeFunction("newQPSLimiter", [](int rate, int burst) { return QPSLimiter(rate, burst); }); + luaCtx.registerFunction("check", &QPSLimiter::check); /* ClientState */ - g_lua.registerFunction("toString", [](const ClientState& fe) { + luaCtx.registerFunction("toString", [](const ClientState& fe) { setLuaNoSideEffect(); return fe.local.toStringWithPort(); }); - g_lua.registerMember("muted", &ClientState::muted); + luaCtx.registerMember("muted", &ClientState::muted); #ifdef HAVE_EBPF - g_lua.registerFunction)>("attachFilter", [](ClientState& frontend, std::shared_ptr bpf) { + luaCtx.registerFunction)>("attachFilter", [](ClientState& frontend, std::shared_ptr bpf) { if (bpf) { frontend.attachFilter(bpf); } }); - g_lua.registerFunction("detachFilter", [](ClientState& frontend) { + luaCtx.registerFunction("detachFilter", [](ClientState& frontend) { frontend.detachFilter(); }); #endif /* HAVE_EBPF */ /* BPF Filter */ #ifdef HAVE_EBPF - g_lua.writeFunction("newBPFFilter", [client](uint32_t maxV4, uint32_t maxV6, uint32_t maxQNames) { + luaCtx.writeFunction("newBPFFilter", [client](uint32_t maxV4, uint32_t maxV6, uint32_t maxQNames) { if (client) { return std::shared_ptr(nullptr); } return std::make_shared(maxV4, maxV6, maxQNames); }); - g_lua.registerFunction::*)(const ComboAddress& ca)>("block", [](std::shared_ptr bpf, const ComboAddress& ca) { + luaCtx.registerFunction::*)(const ComboAddress& ca)>("block", [](std::shared_ptr bpf, const ComboAddress& ca) { if (bpf) { return bpf->block(ca); } }); - g_lua.registerFunction::*)(const DNSName& qname, boost::optional qtype)>("blockQName", [](std::shared_ptr bpf, const DNSName& qname, boost::optional qtype) { + luaCtx.registerFunction::*)(const DNSName& qname, boost::optional qtype)>("blockQName", [](std::shared_ptr bpf, const DNSName& qname, boost::optional qtype) { if (bpf) { return bpf->block(qname, qtype ? *qtype : 255); } }); - g_lua.registerFunction::*)(const ComboAddress& ca)>("unblock", [](std::shared_ptr bpf, const ComboAddress& ca) { + luaCtx.registerFunction::*)(const ComboAddress& ca)>("unblock", [](std::shared_ptr bpf, const ComboAddress& ca) { if (bpf) { return bpf->unblock(ca); } }); - g_lua.registerFunction::*)(const DNSName& qname, boost::optional qtype)>("unblockQName", [](std::shared_ptr bpf, const DNSName& qname, boost::optional qtype) { + luaCtx.registerFunction::*)(const DNSName& qname, boost::optional qtype)>("unblockQName", [](std::shared_ptr bpf, const DNSName& qname, boost::optional qtype) { if (bpf) { return bpf->unblock(qname, qtype ? *qtype : 255); } }); - g_lua.registerFunction::*)()>("getStats", [](const std::shared_ptr bpf) { + luaCtx.registerFunction::*)()>("getStats", [](const std::shared_ptr bpf) { setLuaNoSideEffect(); std::string res; if (bpf) { @@ -411,7 +412,7 @@ void setupLuaBindings(bool client) return res; }); - g_lua.registerFunction::*)()>("attachToAllBinds", [](std::shared_ptr bpf) { + luaCtx.registerFunction::*)()>("attachToAllBinds", [](std::shared_ptr bpf) { std::string res; if (bpf) { for (const auto& frontend : g_frontends) { @@ -420,14 +421,14 @@ void setupLuaBindings(bool client) } }); - g_lua.writeFunction("newDynBPFFilter", [client](std::shared_ptr bpf) { + luaCtx.writeFunction("newDynBPFFilter", [client](std::shared_ptr bpf) { if (client) { return std::shared_ptr(nullptr); } return std::make_shared(bpf); }); - g_lua.registerFunction::*)(const ComboAddress& addr, boost::optional seconds)>("block", [](std::shared_ptr dbpf, const ComboAddress& addr, boost::optional seconds) { + luaCtx.registerFunction::*)(const ComboAddress& addr, boost::optional seconds)>("block", [](std::shared_ptr dbpf, const ComboAddress& addr, boost::optional seconds) { if (dbpf) { struct timespec until; clock_gettime(CLOCK_MONOTONIC, &until); @@ -436,7 +437,7 @@ void setupLuaBindings(bool client) } }); - g_lua.registerFunction::*)()>("purgeExpired", [](std::shared_ptr dbpf) { + luaCtx.registerFunction::*)()>("purgeExpired", [](std::shared_ptr dbpf) { if (dbpf) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -444,7 +445,7 @@ void setupLuaBindings(bool client) } }); - g_lua.registerFunction::*)(boost::variant>>)>("excludeRange", [](std::shared_ptr dbpf, boost::variant>> ranges) { + luaCtx.registerFunction::*)(boost::variant>>)>("excludeRange", [](std::shared_ptr dbpf, boost::variant>> ranges) { if (ranges.type() == typeid(std::vector>)) { for (const auto& range : *boost::get>>(&ranges)) { dbpf->excludeRange(Netmask(range.second)); @@ -455,7 +456,7 @@ void setupLuaBindings(bool client) } }); - g_lua.registerFunction::*)(boost::variant>>)>("includeRange", [](std::shared_ptr dbpf, boost::variant>> ranges) { + luaCtx.registerFunction::*)(boost::variant>>)>("includeRange", [](std::shared_ptr dbpf, boost::variant>> ranges) { if (ranges.type() == typeid(std::vector>)) { for (const auto& range : *boost::get>>(&ranges)) { dbpf->includeRange(Netmask(range.second)); @@ -468,10 +469,10 @@ void setupLuaBindings(bool client) #endif /* HAVE_EBPF */ /* EDNSOptionView */ - g_lua.registerFunction("count", [](const EDNSOptionView& option) { + luaCtx.registerFunction("count", [](const EDNSOptionView& option) { return option.values.size(); }); - g_lua.registerFunction(EDNSOptionView::*)()>("getValues", [] (const EDNSOptionView& option) { + luaCtx.registerFunction(EDNSOptionView::*)()>("getValues", [] (const EDNSOptionView& option) { std::vector values; for (const auto& value : option.values) { values.push_back(std::string(value.content, value.size)); @@ -479,7 +480,7 @@ void setupLuaBindings(bool client) return values; }); - g_lua.writeFunction("newDOHResponseMapEntry", [](const std::string& regex, uint16_t status, const std::string& content, boost::optional> customHeaders) { + luaCtx.writeFunction("newDOHResponseMapEntry", [](const std::string& regex, uint16_t status, const std::string& content, boost::optional> customHeaders) { boost::optional>> headers{boost::none}; if (customHeaders) { headers = std::vector>(); diff --git a/pdns/dnsdist-lua-inspection.cc b/pdns/dnsdist-lua-inspection.cc index 180e6555a7..14028e0d47 100644 --- a/pdns/dnsdist-lua-inspection.cc +++ b/pdns/dnsdist-lua-inspection.cc @@ -223,9 +223,9 @@ static counts_t exceedRespByterate(unsigned int rate, int seconds) }); } -void setupLuaInspection() +void setupLuaInspection(LuaContext& luaCtx) { - g_lua.writeFunction("topClients", [](boost::optional top_) { + luaCtx.writeFunction("topClients", [](boost::optional top_) { setLuaNoSideEffect(); auto top = top_.get_value_or(10); map counts; @@ -259,7 +259,7 @@ void setupLuaInspection() g_outputBuffer += (fmt % (count) % "Rest" % rest % (total > 0 ? 100.0*rest/total : 100.0)).str(); }); - g_lua.writeFunction("getTopQueries", [](unsigned int top, boost::optional labels) { + luaCtx.writeFunction("getTopQueries", [](unsigned int top, boost::optional labels) { setLuaNoSideEffect(); map counts; unsigned int total=0; @@ -307,9 +307,9 @@ void setupLuaInspection() }); - g_lua.executeCode(R"(function topQueries(top, labels) top = top or 10; for k,v in ipairs(getTopQueries(top,labels)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2], v[3])) end end)"); + luaCtx.executeCode(R"(function topQueries(top, labels) top = top or 10; for k,v in ipairs(getTopQueries(top,labels)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2], v[3])) end end)"); - g_lua.writeFunction("getResponseRing", []() { + luaCtx.writeFunction("getResponseRing", []() { setLuaNoSideEffect(); size_t totalEntries = 0; std::vector> rings; @@ -336,28 +336,28 @@ void setupLuaInspection() return ret; }); - g_lua.writeFunction("getTopResponses", [](unsigned int top, unsigned int kind, boost::optional labels) { + luaCtx.writeFunction("getTopResponses", [](unsigned int top, unsigned int kind, boost::optional labels) { return getGenResponses(top, labels, [kind](const Rings::Response& r) { return r.dh.rcode == kind; }); }); - g_lua.executeCode(R"(function topResponses(top, kind, labels) top = top or 10; kind = kind or 0; for k,v in ipairs(getTopResponses(top, kind, labels)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2],v[3])) end end)"); + luaCtx.executeCode(R"(function topResponses(top, kind, labels) top = top or 10; kind = kind or 0; for k,v in ipairs(getTopResponses(top, kind, labels)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2],v[3])) end end)"); - g_lua.writeFunction("getSlowResponses", [](unsigned int top, unsigned int msec, boost::optional labels) { + luaCtx.writeFunction("getSlowResponses", [](unsigned int top, unsigned int msec, boost::optional labels) { return getGenResponses(top, labels, [msec](const Rings::Response& r) { return r.usec > msec*1000; }); }); - g_lua.executeCode(R"(function topSlow(top, msec, labels) top = top or 10; msec = msec or 500; for k,v in ipairs(getSlowResponses(top, msec, labels)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2],v[3])) end end)"); + luaCtx.executeCode(R"(function topSlow(top, msec, labels) top = top or 10; msec = msec or 500; for k,v in ipairs(getSlowResponses(top, msec, labels)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2],v[3])) end end)"); - g_lua.writeFunction("getTopBandwidth", [](unsigned int top) { + luaCtx.writeFunction("getTopBandwidth", [](unsigned int top) { setLuaNoSideEffect(); return g_rings.getTopBandwidth(top); }); - g_lua.executeCode(R"(function topBandwidth(top) top = top or 10; for k,v in ipairs(getTopBandwidth(top)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2],v[3])) end end)"); + luaCtx.executeCode(R"(function topBandwidth(top) top = top or 10; for k,v in ipairs(getTopBandwidth(top)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2],v[3])) end end)"); - g_lua.writeFunction("delta", []() { + luaCtx.writeFunction("delta", []() { setLuaNoSideEffect(); // we hold the lua lock already! for(const auto& d : g_confDelta) { @@ -370,7 +370,7 @@ void setupLuaInspection() } }); - g_lua.writeFunction("grepq", [](boost::variant > > inp, boost::optional limit) { + luaCtx.writeFunction("grepq", [](boost::variant > > inp, boost::optional limit) { setLuaNoSideEffect(); boost::optional nm; boost::optional dn; @@ -517,7 +517,7 @@ void setupLuaInspection() } }); - g_lua.writeFunction("showResponseLatency", []() { + luaCtx.writeFunction("showResponseLatency", []() { setLuaNoSideEffect(); map histo; double bin=100; @@ -575,7 +575,7 @@ void setupLuaInspection() } }); - g_lua.writeFunction("showTCPStats", [] { + luaCtx.writeFunction("showTCPStats", [] { setLuaNoSideEffect(); ostringstream ret; boost::format fmt("%-12d %-12d %-12d %-12d"); @@ -611,7 +611,7 @@ void setupLuaInspection() g_outputBuffer=ret.str(); }); - g_lua.writeFunction("showTLSErrorCounters", [] { + luaCtx.writeFunction("showTLSErrorCounters", [] { setLuaNoSideEffect(); ostringstream ret; boost::format fmt("%-3d %-20.20s %-23d %-23d %-23d %-23d %-23d %-23d %-23d %-23d"); @@ -642,7 +642,7 @@ void setupLuaInspection() g_outputBuffer=ret.str(); }); - g_lua.writeFunction("dumpStats", [] { + luaCtx.writeFunction("dumpStats", [] { setLuaNoSideEffect(); vector leftcolumn, rightcolumn; @@ -686,21 +686,21 @@ void setupLuaInspection() } }); - g_lua.writeFunction("exceedServFails", [](unsigned int rate, int seconds) { + luaCtx.writeFunction("exceedServFails", [](unsigned int rate, int seconds) { setLuaNoSideEffect(); return exceedRCode(rate, seconds, RCode::ServFail); }); - g_lua.writeFunction("exceedNXDOMAINs", [](unsigned int rate, int seconds) { + luaCtx.writeFunction("exceedNXDOMAINs", [](unsigned int rate, int seconds) { setLuaNoSideEffect(); return exceedRCode(rate, seconds, RCode::NXDomain); }); - g_lua.writeFunction("exceedRespByterate", [](unsigned int rate, int seconds) { + luaCtx.writeFunction("exceedRespByterate", [](unsigned int rate, int seconds) { setLuaNoSideEffect(); return exceedRespByterate(rate, seconds); }); - g_lua.writeFunction("exceedQTypeRate", [](uint16_t type, unsigned int rate, int seconds) { + luaCtx.writeFunction("exceedQTypeRate", [](uint16_t type, unsigned int rate, int seconds) { setLuaNoSideEffect(); return exceedQueryGen(rate, seconds, [type](counts_t& counts, const Rings::Query& q) { if(q.qtype==type) @@ -708,71 +708,71 @@ void setupLuaInspection() }); }); - g_lua.writeFunction("exceedQRate", [](unsigned int rate, int seconds) { + luaCtx.writeFunction("exceedQRate", [](unsigned int rate, int seconds) { setLuaNoSideEffect(); return exceedQueryGen(rate, seconds, [](counts_t& counts, const Rings::Query& q) { counts[q.requestor]++; }); }); - g_lua.writeFunction("getRespRing", getRespRing); + luaCtx.writeFunction("getRespRing", getRespRing); /* StatNode */ - g_lua.registerFunction("numChildren", + luaCtx.registerFunction("numChildren", [](StatNode& sn) -> unsigned int { return sn.children.size(); } ); - g_lua.registerMember("fullname", &StatNode::fullname); - g_lua.registerMember("labelsCount", &StatNode::labelsCount); - g_lua.registerMember("servfails", &StatNode::Stat::servfails); - g_lua.registerMember("nxdomains", &StatNode::Stat::nxdomains); - g_lua.registerMember("queries", &StatNode::Stat::queries); - g_lua.registerMember("noerrors", &StatNode::Stat::noerrors); - g_lua.registerMember("drops", &StatNode::Stat::drops); - g_lua.registerMember("bytes", &StatNode::Stat::bytes); - - g_lua.writeFunction("statNodeRespRing", [](statvisitor_t visitor, boost::optional seconds) { + luaCtx.registerMember("fullname", &StatNode::fullname); + luaCtx.registerMember("labelsCount", &StatNode::labelsCount); + luaCtx.registerMember("servfails", &StatNode::Stat::servfails); + luaCtx.registerMember("nxdomains", &StatNode::Stat::nxdomains); + luaCtx.registerMember("queries", &StatNode::Stat::queries); + luaCtx.registerMember("noerrors", &StatNode::Stat::noerrors); + luaCtx.registerMember("drops", &StatNode::Stat::drops); + luaCtx.registerMember("bytes", &StatNode::Stat::bytes); + + luaCtx.writeFunction("statNodeRespRing", [](statvisitor_t visitor, boost::optional seconds) { statNodeRespRing(visitor, seconds ? *seconds : 0); }); /* DynBlockRulesGroup */ - g_lua.writeFunction("dynBlockRulesGroup", []() { return std::make_shared(); }); - g_lua.registerFunction::*)(unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setQueryRate", [](std::shared_ptr& group, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { + luaCtx.writeFunction("dynBlockRulesGroup", []() { return std::make_shared(); }); + luaCtx.registerFunction::*)(unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setQueryRate", [](std::shared_ptr& group, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { if (group) { group->setQueryRate(rate, warningRate ? *warningRate : 0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None); } }); - g_lua.registerFunction::*)(unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setResponseByteRate", [](std::shared_ptr& group, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { + luaCtx.registerFunction::*)(unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setResponseByteRate", [](std::shared_ptr& group, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { if (group) { group->setResponseByteRate(rate, warningRate ? *warningRate : 0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None); } }); - g_lua.registerFunction::*)(unsigned int, const std::string&, unsigned int, boost::optional, DynBlockRulesGroup::smtVisitor_t)>("setSuffixMatchRule", [](std::shared_ptr& group, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, DynBlockRulesGroup::smtVisitor_t visitor) { + luaCtx.registerFunction::*)(unsigned int, const std::string&, unsigned int, boost::optional, DynBlockRulesGroup::smtVisitor_t)>("setSuffixMatchRule", [](std::shared_ptr& group, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, DynBlockRulesGroup::smtVisitor_t visitor) { if (group) { group->setSuffixMatchRule(seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, visitor); } }); - g_lua.registerFunction::*)(unsigned int, const std::string&, unsigned int, boost::optional, dnsdist_ffi_stat_node_visitor_t)>("setSuffixMatchRuleFFI", [](std::shared_ptr& group, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, dnsdist_ffi_stat_node_visitor_t visitor) { + luaCtx.registerFunction::*)(unsigned int, const std::string&, unsigned int, boost::optional, dnsdist_ffi_stat_node_visitor_t)>("setSuffixMatchRuleFFI", [](std::shared_ptr& group, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, dnsdist_ffi_stat_node_visitor_t visitor) { if (group) { group->setSuffixMatchRuleFFI(seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, visitor); } }); - g_lua.registerFunction::*)(uint8_t, unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setRCodeRate", [](std::shared_ptr& group, uint8_t rcode, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { + luaCtx.registerFunction::*)(uint8_t, unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setRCodeRate", [](std::shared_ptr& group, uint8_t rcode, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { if (group) { group->setRCodeRate(rcode, rate, warningRate ? *warningRate : 0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None); } }); - g_lua.registerFunction::*)(uint8_t, double, unsigned int, const std::string&, unsigned int, size_t, boost::optional, boost::optional)>("setRCodeRatio", [](std::shared_ptr& group, uint8_t rcode, double ratio, unsigned int seconds, const std::string& reason, unsigned int blockDuration, size_t minimumNumberOfResponses, boost::optional action, boost::optional warningRatio) { + luaCtx.registerFunction::*)(uint8_t, double, unsigned int, const std::string&, unsigned int, size_t, boost::optional, boost::optional)>("setRCodeRatio", [](std::shared_ptr& group, uint8_t rcode, double ratio, unsigned int seconds, const std::string& reason, unsigned int blockDuration, size_t minimumNumberOfResponses, boost::optional action, boost::optional warningRatio) { if (group) { group->setRCodeRatio(rcode, ratio, warningRatio ? *warningRatio : 0.0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None, minimumNumberOfResponses); } }); - g_lua.registerFunction::*)(uint16_t, unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setQTypeRate", [](std::shared_ptr& group, uint16_t qtype, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { + luaCtx.registerFunction::*)(uint16_t, unsigned int, unsigned int, const std::string&, unsigned int, boost::optional, boost::optional)>("setQTypeRate", [](std::shared_ptr& group, uint16_t qtype, unsigned int rate, unsigned int seconds, const std::string& reason, unsigned int blockDuration, boost::optional action, boost::optional warningRate) { if (group) { group->setQTypeRate(qtype, rate, warningRate ? *warningRate : 0, seconds, reason, blockDuration, action ? *action : DNSAction::Action::None); } }); - g_lua.registerFunction::*)(boost::variant>>)>("excludeRange", [](std::shared_ptr& group, boost::variant>> ranges) { + luaCtx.registerFunction::*)(boost::variant>>)>("excludeRange", [](std::shared_ptr& group, boost::variant>> ranges) { if (ranges.type() == typeid(std::vector>)) { for (const auto& range : *boost::get>>(&ranges)) { group->excludeRange(Netmask(range.second)); @@ -782,7 +782,7 @@ void setupLuaInspection() group->excludeRange(Netmask(*boost::get(&ranges))); } }); - g_lua.registerFunction::*)(boost::variant>>)>("includeRange", [](std::shared_ptr& group, boost::variant>> ranges) { + luaCtx.registerFunction::*)(boost::variant>>)>("includeRange", [](std::shared_ptr& group, boost::variant>> ranges) { if (ranges.type() == typeid(std::vector>)) { for (const auto& range : *boost::get>>(&ranges)) { group->includeRange(Netmask(range.second)); @@ -792,7 +792,7 @@ void setupLuaInspection() group->includeRange(Netmask(*boost::get(&ranges))); } }); - g_lua.registerFunction::*)(boost::variant>>)>("excludeDomains", [](std::shared_ptr& group, boost::variant>> domains) { + luaCtx.registerFunction::*)(boost::variant>>)>("excludeDomains", [](std::shared_ptr& group, boost::variant>> domains) { if (domains.type() == typeid(std::vector>)) { for (const auto& range : *boost::get>>(&domains)) { group->excludeDomain(DNSName(range.second)); @@ -802,9 +802,9 @@ void setupLuaInspection() group->excludeDomain(DNSName(*boost::get(&domains))); } }); - g_lua.registerFunction::*)()>("apply", [](std::shared_ptr& group) { + luaCtx.registerFunction::*)()>("apply", [](std::shared_ptr& group) { group->apply(); }); - g_lua.registerFunction("setQuiet", &DynBlockRulesGroup::setQuiet); - g_lua.registerFunction("toString", &DynBlockRulesGroup::toString); + luaCtx.registerFunction("setQuiet", &DynBlockRulesGroup::setQuiet); + luaCtx.registerFunction("toString", &DynBlockRulesGroup::toString); } diff --git a/pdns/dnsdist-lua-rules.cc b/pdns/dnsdist-lua-rules.cc index c33af0d7f1..4307b0d131 100644 --- a/pdns/dnsdist-lua-rules.cc +++ b/pdns/dnsdist-lua-rules.cc @@ -178,80 +178,80 @@ static void mvRule(GlobalStateHolder > *someRespRulActions, unsigned i someRespRulActions->setState(std::move(rules)); } -void setupLuaRules() +void setupLuaRules(LuaContext& luaCtx) { - g_lua.writeFunction("makeRule", makeRule); + luaCtx.writeFunction("makeRule", makeRule); - g_lua.registerFunction::*)()>("toString", [](const std::shared_ptr& rule) { return rule->toString(); }); + luaCtx.registerFunction::*)()>("toString", [](const std::shared_ptr& rule) { return rule->toString(); }); - g_lua.writeFunction("showResponseRules", [](boost::optional vars) { + luaCtx.writeFunction("showResponseRules", [](boost::optional vars) { showRules(&g_resprulactions, vars); }); - g_lua.writeFunction("rmResponseRule", [](boost::variant id) { + luaCtx.writeFunction("rmResponseRule", [](boost::variant id) { rmRule(&g_resprulactions, id); }); - g_lua.writeFunction("topResponseRule", []() { + luaCtx.writeFunction("topResponseRule", []() { topRule(&g_resprulactions); }); - g_lua.writeFunction("mvResponseRule", [](unsigned int from, unsigned int to) { + luaCtx.writeFunction("mvResponseRule", [](unsigned int from, unsigned int to) { mvRule(&g_resprulactions, from, to); }); - g_lua.writeFunction("showCacheHitResponseRules", [](boost::optional vars) { + luaCtx.writeFunction("showCacheHitResponseRules", [](boost::optional vars) { showRules(&g_cachehitresprulactions, vars); }); - g_lua.writeFunction("rmCacheHitResponseRule", [](boost::variant id) { + luaCtx.writeFunction("rmCacheHitResponseRule", [](boost::variant id) { rmRule(&g_cachehitresprulactions, id); }); - g_lua.writeFunction("topCacheHitResponseRule", []() { + luaCtx.writeFunction("topCacheHitResponseRule", []() { topRule(&g_cachehitresprulactions); }); - g_lua.writeFunction("mvCacheHitResponseRule", [](unsigned int from, unsigned int to) { + luaCtx.writeFunction("mvCacheHitResponseRule", [](unsigned int from, unsigned int to) { mvRule(&g_cachehitresprulactions, from, to); }); - g_lua.writeFunction("showSelfAnsweredResponseRules", [](boost::optional vars) { + luaCtx.writeFunction("showSelfAnsweredResponseRules", [](boost::optional vars) { showRules(&g_selfansweredresprulactions, vars); }); - g_lua.writeFunction("rmSelfAnsweredResponseRule", [](boost::variant id) { + luaCtx.writeFunction("rmSelfAnsweredResponseRule", [](boost::variant id) { rmRule(&g_selfansweredresprulactions, id); }); - g_lua.writeFunction("topSelfAnsweredResponseRule", []() { + luaCtx.writeFunction("topSelfAnsweredResponseRule", []() { topRule(&g_selfansweredresprulactions); }); - g_lua.writeFunction("mvSelfAnsweredResponseRule", [](unsigned int from, unsigned int to) { + luaCtx.writeFunction("mvSelfAnsweredResponseRule", [](unsigned int from, unsigned int to) { mvRule(&g_selfansweredresprulactions, from, to); }); - g_lua.writeFunction("rmRule", [](boost::variant id) { + luaCtx.writeFunction("rmRule", [](boost::variant id) { rmRule(&g_rulactions, id); }); - g_lua.writeFunction("topRule", []() { + luaCtx.writeFunction("topRule", []() { topRule(&g_rulactions); }); - g_lua.writeFunction("mvRule", [](unsigned int from, unsigned int to) { + luaCtx.writeFunction("mvRule", [](unsigned int from, unsigned int to) { mvRule(&g_rulactions, from, to); }); - g_lua.writeFunction("clearRules", []() { + luaCtx.writeFunction("clearRules", []() { setLuaSideEffect(); g_rulactions.modify([](decltype(g_rulactions)::value_type& rulactions) { rulactions.clear(); }); }); - g_lua.writeFunction("setRules", [](const std::vector>>& newruleactions) { + luaCtx.writeFunction("setRules", [](const std::vector>>& newruleactions) { setLuaSideEffect(); g_rulactions.modify([newruleactions](decltype(g_rulactions)::value_type& gruleactions) { gruleactions.clear(); @@ -265,52 +265,52 @@ void setupLuaRules() }); }); - g_lua.writeFunction("MaxQPSIPRule", [](unsigned int qps, boost::optional ipv4trunc, boost::optional ipv6trunc, boost::optional burst, boost::optional expiration, boost::optional cleanupDelay, boost::optional scanFraction) { + luaCtx.writeFunction("MaxQPSIPRule", [](unsigned int qps, boost::optional ipv4trunc, boost::optional ipv6trunc, boost::optional burst, boost::optional expiration, boost::optional cleanupDelay, boost::optional scanFraction) { return std::shared_ptr(new MaxQPSIPRule(qps, burst.get_value_or(qps), ipv4trunc.get_value_or(32), ipv6trunc.get_value_or(64), expiration.get_value_or(300), cleanupDelay.get_value_or(60), scanFraction.get_value_or(10))); }); - g_lua.writeFunction("MaxQPSRule", [](unsigned int qps, boost::optional burst) { + luaCtx.writeFunction("MaxQPSRule", [](unsigned int qps, boost::optional burst) { if(!burst) return std::shared_ptr(new MaxQPSRule(qps)); else return std::shared_ptr(new MaxQPSRule(qps, *burst)); }); - g_lua.writeFunction("RegexRule", [](const std::string& str) { + luaCtx.writeFunction("RegexRule", [](const std::string& str) { return std::shared_ptr(new RegexRule(str)); }); #ifdef HAVE_DNS_OVER_HTTPS - g_lua.writeFunction("HTTPHeaderRule", [](const std::string& header, const std::string& regex) { + luaCtx.writeFunction("HTTPHeaderRule", [](const std::string& header, const std::string& regex) { return std::shared_ptr(new HTTPHeaderRule(header, regex)); }); - g_lua.writeFunction("HTTPPathRule", [](const std::string& path) { + luaCtx.writeFunction("HTTPPathRule", [](const std::string& path) { return std::shared_ptr(new HTTPPathRule(path)); }); - g_lua.writeFunction("HTTPPathRegexRule", [](const std::string& regex) { + luaCtx.writeFunction("HTTPPathRegexRule", [](const std::string& regex) { return std::shared_ptr(new HTTPPathRegexRule(regex)); }); #endif #ifdef HAVE_RE2 - g_lua.writeFunction("RE2Rule", [](const std::string& str) { + luaCtx.writeFunction("RE2Rule", [](const std::string& str) { return std::shared_ptr(new RE2Rule(str)); }); #endif - g_lua.writeFunction("SNIRule", [](const std::string& name) { + luaCtx.writeFunction("SNIRule", [](const std::string& name) { return std::shared_ptr(new SNIRule(name)); }); - g_lua.writeFunction("SuffixMatchNodeRule", [](const SuffixMatchNode& smn, boost::optional quiet) { + luaCtx.writeFunction("SuffixMatchNodeRule", [](const SuffixMatchNode& smn, boost::optional quiet) { return std::shared_ptr(new SuffixMatchNodeRule(smn, quiet ? *quiet : false)); }); - g_lua.writeFunction("NetmaskGroupRule", [](const NetmaskGroup& nmg, boost::optional src, boost::optional quiet) { + luaCtx.writeFunction("NetmaskGroupRule", [](const NetmaskGroup& nmg, boost::optional src, boost::optional quiet) { return std::shared_ptr(new NetmaskGroupRule(nmg, src ? *src : true, quiet ? *quiet : false)); }); - g_lua.writeFunction("benchRule", [](std::shared_ptr rule, boost::optional times_, boost::optional suffix_) { + luaCtx.writeFunction("benchRule", [](std::shared_ptr rule, boost::optional times_, boost::optional suffix_) { setLuaNoSideEffect(); int times = times_.get_value_or(100000); DNSName suffix(suffix_.get_value_or("powerdns.com")); @@ -349,19 +349,19 @@ void setupLuaRules() }); - g_lua.writeFunction("AllRule", []() { + luaCtx.writeFunction("AllRule", []() { return std::shared_ptr(new AllRule()); }); - g_lua.writeFunction("ProbaRule", [](double proba) { + luaCtx.writeFunction("ProbaRule", [](double proba) { return std::shared_ptr(new ProbaRule(proba)); }); - g_lua.writeFunction("QNameRule", [](const std::string& qname) { + luaCtx.writeFunction("QNameRule", [](const std::string& qname) { return std::shared_ptr(new QNameRule(DNSName(qname))); }); - g_lua.writeFunction("QTypeRule", [](boost::variant str) { + luaCtx.writeFunction("QTypeRule", [](boost::variant str) { uint16_t qtype; if(auto dir = boost::get(&str)) { qtype = *dir; @@ -375,123 +375,123 @@ void setupLuaRules() return std::shared_ptr(new QTypeRule(qtype)); }); - g_lua.writeFunction("QClassRule", [](int c) { + luaCtx.writeFunction("QClassRule", [](int c) { return std::shared_ptr(new QClassRule(c)); }); - g_lua.writeFunction("OpcodeRule", [](uint8_t code) { + luaCtx.writeFunction("OpcodeRule", [](uint8_t code) { return std::shared_ptr(new OpcodeRule(code)); }); - g_lua.writeFunction("AndRule", [](vector > >a) { + luaCtx.writeFunction("AndRule", [](vector > >a) { return std::shared_ptr(new AndRule(a)); }); - g_lua.writeFunction("OrRule", [](vector > >a) { + luaCtx.writeFunction("OrRule", [](vector > >a) { return std::shared_ptr(new OrRule(a)); }); - g_lua.writeFunction("DSTPortRule", [](uint16_t port) { + luaCtx.writeFunction("DSTPortRule", [](uint16_t port) { return std::shared_ptr(new DSTPortRule(port)); }); - g_lua.writeFunction("TCPRule", [](bool tcp) { + luaCtx.writeFunction("TCPRule", [](bool tcp) { return std::shared_ptr(new TCPRule(tcp)); }); - g_lua.writeFunction("DNSSECRule", []() { + luaCtx.writeFunction("DNSSECRule", []() { return std::shared_ptr(new DNSSECRule()); }); - g_lua.writeFunction("NotRule", [](std::shared_ptrrule) { + luaCtx.writeFunction("NotRule", [](std::shared_ptrrule) { return std::shared_ptr(new NotRule(rule)); }); - g_lua.writeFunction("RecordsCountRule", [](uint8_t section, uint16_t minCount, uint16_t maxCount) { + luaCtx.writeFunction("RecordsCountRule", [](uint8_t section, uint16_t minCount, uint16_t maxCount) { return std::shared_ptr(new RecordsCountRule(section, minCount, maxCount)); }); - g_lua.writeFunction("RecordsTypeCountRule", [](uint8_t section, uint16_t type, uint16_t minCount, uint16_t maxCount) { + luaCtx.writeFunction("RecordsTypeCountRule", [](uint8_t section, uint16_t type, uint16_t minCount, uint16_t maxCount) { return std::shared_ptr(new RecordsTypeCountRule(section, type, minCount, maxCount)); }); - g_lua.writeFunction("TrailingDataRule", []() { + luaCtx.writeFunction("TrailingDataRule", []() { return std::shared_ptr(new TrailingDataRule()); }); - g_lua.writeFunction("QNameLabelsCountRule", [](unsigned int minLabelsCount, unsigned int maxLabelsCount) { + luaCtx.writeFunction("QNameLabelsCountRule", [](unsigned int minLabelsCount, unsigned int maxLabelsCount) { return std::shared_ptr(new QNameLabelsCountRule(minLabelsCount, maxLabelsCount)); }); - g_lua.writeFunction("QNameWireLengthRule", [](size_t min, size_t max) { + luaCtx.writeFunction("QNameWireLengthRule", [](size_t min, size_t max) { return std::shared_ptr(new QNameWireLengthRule(min, max)); }); - g_lua.writeFunction("RCodeRule", [](uint8_t rcode) { + luaCtx.writeFunction("RCodeRule", [](uint8_t rcode) { return std::shared_ptr(new RCodeRule(rcode)); }); - g_lua.writeFunction("ERCodeRule", [](uint8_t rcode) { + luaCtx.writeFunction("ERCodeRule", [](uint8_t rcode) { return std::shared_ptr(new ERCodeRule(rcode)); }); - g_lua.writeFunction("EDNSVersionRule", [](uint8_t version) { + luaCtx.writeFunction("EDNSVersionRule", [](uint8_t version) { return std::shared_ptr(new EDNSVersionRule(version)); }); - g_lua.writeFunction("EDNSOptionRule", [](uint16_t optcode) { + luaCtx.writeFunction("EDNSOptionRule", [](uint16_t optcode) { return std::shared_ptr(new EDNSOptionRule(optcode)); }); - g_lua.writeFunction("showRules", [](boost::optional vars) { + luaCtx.writeFunction("showRules", [](boost::optional vars) { showRules(&g_rulactions, vars); }); - g_lua.writeFunction("RDRule", []() { + luaCtx.writeFunction("RDRule", []() { return std::shared_ptr(new RDRule()); }); - g_lua.writeFunction("TagRule", [](std::string tag, boost::optional value) { + luaCtx.writeFunction("TagRule", [](std::string tag, boost::optional value) { return std::shared_ptr(new TagRule(tag, value)); }); - g_lua.writeFunction("TimedIPSetRule", []() { + luaCtx.writeFunction("TimedIPSetRule", []() { return std::shared_ptr(new TimedIPSetRule()); }); - g_lua.writeFunction("PoolAvailableRule", [](std::string poolname) { + luaCtx.writeFunction("PoolAvailableRule", [](std::string poolname) { return std::shared_ptr(new PoolAvailableRule(poolname)); }); - g_lua.registerFunction::*)()>("clear", [](std::shared_ptr tisr) { + luaCtx.registerFunction::*)()>("clear", [](std::shared_ptr tisr) { tisr->clear(); }); - g_lua.registerFunction::*)()>("cleanup", [](std::shared_ptr tisr) { + luaCtx.registerFunction::*)()>("cleanup", [](std::shared_ptr tisr) { tisr->cleanup(); }); - g_lua.registerFunction::*)(const ComboAddress& ca, int t)>("add", [](std::shared_ptr tisr, const ComboAddress& ca, int t) { + luaCtx.registerFunction::*)(const ComboAddress& ca, int t)>("add", [](std::shared_ptr tisr, const ComboAddress& ca, int t) { tisr->add(ca, time(0)+t); }); - g_lua.registerFunction(std::shared_ptr::*)()>("slice", [](std::shared_ptr tisr) { + luaCtx.registerFunction(std::shared_ptr::*)()>("slice", [](std::shared_ptr tisr) { return std::dynamic_pointer_cast(tisr); }); - g_lua.writeFunction("QNameSetRule", [](const DNSNameSet& names) { + luaCtx.writeFunction("QNameSetRule", [](const DNSNameSet& names) { return std::shared_ptr(new QNameSetRule(names)); }); - g_lua.writeFunction("KeyValueStoreLookupRule", [](std::shared_ptr& kvs, std::shared_ptr& lookupKey) { + luaCtx.writeFunction("KeyValueStoreLookupRule", [](std::shared_ptr& kvs, std::shared_ptr& lookupKey) { return std::shared_ptr(new KeyValueStoreLookupRule(kvs, lookupKey)); }); - g_lua.writeFunction("LuaRule", [](LuaRule::func_t func) { + luaCtx.writeFunction("LuaRule", [](LuaRule::func_t func) { return std::shared_ptr(new LuaRule(func)); }); - g_lua.writeFunction("LuaFFIRule", [](LuaFFIRule::func_t func) { + luaCtx.writeFunction("LuaFFIRule", [](LuaFFIRule::func_t func) { return std::shared_ptr(new LuaFFIRule(func)); }); } diff --git a/pdns/dnsdist-lua-vars.cc b/pdns/dnsdist-lua-vars.cc index 7058deab3d..9e263f7d7a 100644 --- a/pdns/dnsdist-lua-vars.cc +++ b/pdns/dnsdist-lua-vars.cc @@ -25,9 +25,9 @@ #undef BADSIG // signal.h SIG_ERR -void setupLuaVars() +void setupLuaVars(LuaContext& luaCtx) { - g_lua.writeVariable("DNSAction", std::unordered_map{ + luaCtx.writeVariable("DNSAction", std::unordered_map{ {"Drop", (int)DNSAction::Action::Drop}, {"Nxdomain", (int)DNSAction::Action::Nxdomain}, {"Refused", (int)DNSAction::Action::Refused}, @@ -44,7 +44,7 @@ void setupLuaVars() {"NoRecurse", (int)DNSAction::Action::NoRecurse} }); - g_lua.writeVariable("DNSResponseAction", std::unordered_map{ + luaCtx.writeVariable("DNSResponseAction", std::unordered_map{ {"Allow", (int)DNSResponseAction::Action::Allow }, {"Delay", (int)DNSResponseAction::Action::Delay }, {"Drop", (int)DNSResponseAction::Action::Drop }, @@ -53,14 +53,14 @@ void setupLuaVars() {"None", (int)DNSResponseAction::Action::None } }); - g_lua.writeVariable("DNSClass", std::unordered_map{ + luaCtx.writeVariable("DNSClass", std::unordered_map{ {"IN", QClass::IN }, {"CHAOS", QClass::CHAOS }, {"NONE", QClass::NONE }, {"ANY", QClass::ANY } }); - g_lua.writeVariable("DNSOpcode", std::unordered_map{ + luaCtx.writeVariable("DNSOpcode", std::unordered_map{ {"Query", Opcode::Query }, {"IQuery", Opcode::IQuery }, {"Status", Opcode::Status }, @@ -68,14 +68,14 @@ void setupLuaVars() {"Update", Opcode::Update } }); - g_lua.writeVariable("DNSSection", std::unordered_map{ + luaCtx.writeVariable("DNSSection", std::unordered_map{ {"Question", 0 }, {"Answer", 1 }, {"Authority", 2 }, {"Additional",3 } }); - g_lua.writeVariable("EDNSOptionCode", std::unordered_map{ + luaCtx.writeVariable("EDNSOptionCode", std::unordered_map{ {"NSID", EDNSOptionCode::NSID }, {"DAU", EDNSOptionCode::DAU }, {"DHU", EDNSOptionCode::DHU }, @@ -89,7 +89,7 @@ void setupLuaVars() {"KEYTAG", EDNSOptionCode::KEYTAG } }); - g_lua.writeVariable("DNSRCode", std::unordered_map{ + luaCtx.writeVariable("DNSRCode", std::unordered_map{ {"NOERROR", RCode::NoError }, {"FORMERR", RCode::FormErr }, {"SERVFAIL", RCode::ServFail }, @@ -115,9 +115,9 @@ void setupLuaVars() vector > dd; for(const auto& n : QType::names) dd.push_back({n.first, n.second}); - g_lua.writeVariable("DNSQType", dd); + luaCtx.writeVariable("DNSQType", dd); - g_lua.executeCode(R"LUA( + luaCtx.executeCode(R"LUA( local tables = { DNSQType = DNSQType, DNSRCode = DNSRCode @@ -139,7 +139,7 @@ void setupLuaVars() ); #ifdef HAVE_DNSCRYPT - g_lua.writeVariable("DNSCryptExchangeVersion", std::unordered_map{ + luaCtx.writeVariable("DNSCryptExchangeVersion", std::unordered_map{ { "VERSION1", DNSCryptExchangeVersion::VERSION1 }, { "VERSION2", DNSCryptExchangeVersion::VERSION2 }, }); diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index 3dacbc83f6..b16d466c87 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -63,7 +63,7 @@ using std::thread; -static vector>* g_launchWork = nullptr; +static boost::optional>> g_launchWork = boost::none; boost::tribool g_noLuaSideEffect; static bool g_included{false}; @@ -223,18 +223,18 @@ static void parseTLSConfig(TLSConfig& config, const std::string& context, boost: #endif // defined(HAVE_DNS_OVER_TLS) || defined(HAVE_DNS_OVER_HTTPS) -static void setupLuaConfig(bool client, bool configCheck) +static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) { typedef std::unordered_map >, DownstreamState::checkfunc_t > > newserver_t; - g_lua.writeFunction("inClientStartup", [client]() { + luaCtx.writeFunction("inClientStartup", [client]() { return client && !g_configurationDone; }); - g_lua.writeFunction("inConfigCheck", [configCheck]() { + luaCtx.writeFunction("inConfigCheck", [configCheck]() { return !configCheck; }); - g_lua.writeFunction("newServer", + luaCtx.writeFunction("newServer", [client, configCheck](boost::variant pvars, boost::optional qps) { setLuaSideEffect(); @@ -500,7 +500,7 @@ static void setupLuaConfig(bool client, bool configCheck) if (ret->connected) { ret->threadStarted.test_and_set(); - if(g_launchWork) { + if (g_launchWork) { g_launchWork->push_back([ret,cpus]() { ret->tid = thread(responderThread, ret); if (!cpus.empty()) { @@ -525,7 +525,7 @@ static void setupLuaConfig(bool client, bool configCheck) return ret; } ); - g_lua.writeFunction("rmServer", + luaCtx.writeFunction("rmServer", [](boost::variant, int, std::string> var) { setLuaSideEffect(); @@ -561,20 +561,20 @@ static void setupLuaConfig(bool client, bool configCheck) server->stop(); } ); - g_lua.writeFunction("truncateTC", [](bool tc) { setLuaSideEffect(); g_truncateTC=tc; }); - g_lua.writeFunction("fixupCase", [](bool fu) { setLuaSideEffect(); g_fixupCase=fu; }); + luaCtx.writeFunction("truncateTC", [](bool tc) { setLuaSideEffect(); g_truncateTC=tc; }); + luaCtx.writeFunction("fixupCase", [](bool fu) { setLuaSideEffect(); g_fixupCase=fu; }); - g_lua.writeFunction("addACL", [](const std::string& domain) { + luaCtx.writeFunction("addACL", [](const std::string& domain) { setLuaSideEffect(); g_ACL.modify([domain](NetmaskGroup& nmg) { nmg.addMask(domain); }); }); - g_lua.writeFunction("rmACL", [](const std::string& netmask) { + luaCtx.writeFunction("rmACL", [](const std::string& netmask) { setLuaSideEffect(); g_ACL.modify([netmask](NetmaskGroup& nmg) { nmg.deleteMask(netmask); }); }); - g_lua.writeFunction("setLocal", [client](const std::string& addr, boost::optional vars) { + luaCtx.writeFunction("setLocal", [client](const std::string& addr, boost::optional vars) { setLuaSideEffect(); if(client) return; @@ -615,7 +615,7 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("addLocal", [client](const std::string& addr, boost::optional vars) { + luaCtx.writeFunction("addLocal", [client](const std::string& addr, boost::optional vars) { setLuaSideEffect(); if(client) return; @@ -647,7 +647,7 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("setACL", [](boost::variant>> inp) { + luaCtx.writeFunction("setACL", [](boost::variant>> inp) { setLuaSideEffect(); NetmaskGroup nmg; if(auto str = boost::get(&inp)) { @@ -659,7 +659,7 @@ static void setupLuaConfig(bool client, bool configCheck) g_ACL.setState(nmg); }); - g_lua.writeFunction("showACL", []() { + luaCtx.writeFunction("showACL", []() { setLuaNoSideEffect(); vector vec; @@ -670,7 +670,7 @@ static void setupLuaConfig(bool client, bool configCheck) }); - g_lua.writeFunction("shutdown", []() { + luaCtx.writeFunction("shutdown", []() { #ifdef HAVE_SYSTEMD sd_notify(0, "STOPPING=1"); #endif /* HAVE_SYSTEMD */ @@ -690,7 +690,7 @@ static void setupLuaConfig(bool client, bool configCheck) typedef std::unordered_map > showserversopts_t; - g_lua.writeFunction("showServers", [](boost::optional vars) { + luaCtx.writeFunction("showServers", [](boost::optional vars) { setLuaNoSideEffect(); bool showUUIDs = false; if (vars) { @@ -752,7 +752,7 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("getServers", []() { + luaCtx.writeFunction("getServers", []() { setLuaNoSideEffect(); vector > > ret; int count=1; @@ -762,12 +762,12 @@ static void setupLuaConfig(bool client, bool configCheck) return ret; }); - g_lua.writeFunction("getPoolServers", [](string pool) { + luaCtx.writeFunction("getPoolServers", [](string pool) { const auto poolServers = getDownstreamCandidates(g_pools.getCopy(), pool); return *poolServers; }); - g_lua.writeFunction("getServer", [client](boost::variant i) { + luaCtx.writeFunction("getServer", [client](boost::variant i) { if (client) { return std::make_shared(ComboAddress()); } @@ -788,7 +788,7 @@ static void setupLuaConfig(bool client, bool configCheck) return std::shared_ptr(nullptr); }); - g_lua.writeFunction("carbonServer", [](const std::string& address, boost::optional ourName, + luaCtx.writeFunction("carbonServer", [](const std::string& address, boost::optional ourName, boost::optional interval, boost::optional namespace_name, boost::optional instance_name) { setLuaSideEffect(); @@ -803,7 +803,7 @@ static void setupLuaConfig(bool client, bool configCheck) g_carbon.setState(ours); }); - g_lua.writeFunction("webserver", [client,configCheck](const std::string& address, const std::string& password, const boost::optional apiKey, const boost::optional > customHeaders, const boost::optional acl) { + luaCtx.writeFunction("webserver", [client,configCheck](const std::string& address, const std::string& password, const boost::optional apiKey, const boost::optional > customHeaders, const boost::optional acl) { setLuaSideEffect(); ComboAddress local; try { @@ -832,10 +832,12 @@ static void setupLuaConfig(bool client, bool configCheck) thread t(dnsdistWebserverThread, sock, local); t.detach(); }; - if(g_launchWork) + if (g_launchWork) { g_launchWork->push_back(launch); - else + } + else { launch(); + } } catch(std::exception& e) { g_outputBuffer="Unable to bind to webserver socket on " + local.toStringWithPort() + ": " + e.what(); @@ -846,7 +848,7 @@ static void setupLuaConfig(bool client, bool configCheck) typedef std::unordered_map> > webserveropts_t; - g_lua.writeFunction("setWebserverConfig", [](boost::optional vars) { + luaCtx.writeFunction("setWebserverConfig", [](boost::optional vars) { setLuaSideEffect(); if (!vars) { @@ -874,7 +876,7 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("controlSocket", [client,configCheck](const std::string& str) { + luaCtx.writeFunction("controlSocket", [client,configCheck](const std::string& str) { setLuaSideEffect(); ComboAddress local(str, 5199); @@ -899,11 +901,12 @@ static void setupLuaConfig(bool client, bool configCheck) thread t(controlThread, sock, local); t.detach(); }; - if(g_launchWork) + if (g_launchWork) { g_launchWork->push_back(launch); - else + } + else { launch(); - + } } catch(std::exception& e) { g_outputBuffer="Unable to bind to control socket on " + local.toStringWithPort() + ": " + e.what(); @@ -911,7 +914,7 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("addConsoleACL", [](const std::string& netmask) { + luaCtx.writeFunction("addConsoleACL", [](const std::string& netmask) { 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"); @@ -920,7 +923,7 @@ static void setupLuaConfig(bool client, bool configCheck) g_consoleACL.modify([netmask](NetmaskGroup& nmg) { nmg.addMask(netmask); }); }); - g_lua.writeFunction("setConsoleACL", [](boost::variant>> inp) { + luaCtx.writeFunction("setConsoleACL", [](boost::variant>> inp) { setLuaSideEffect(); #ifndef HAVE_LIBSODIUM @@ -937,7 +940,7 @@ static void setupLuaConfig(bool client, bool configCheck) g_consoleACL.setState(nmg); }); - g_lua.writeFunction("showConsoleACL", []() { + luaCtx.writeFunction("showConsoleACL", []() { setLuaNoSideEffect(); #ifndef HAVE_LIBSODIUM @@ -952,7 +955,7 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("clearQueryCounters", []() { + luaCtx.writeFunction("clearQueryCounters", []() { unsigned int size{0}; { WriteLock wl(&g_qcount.queryLock); @@ -964,7 +967,7 @@ static void setupLuaConfig(bool client, bool configCheck) g_outputBuffer = (fmt % size).str(); }); - g_lua.writeFunction("getQueryCounters", [](boost::optional optMax) { + luaCtx.writeFunction("getQueryCounters", [](boost::optional optMax) { setLuaNoSideEffect(); ReadLock rl(&g_qcount.queryLock); g_outputBuffer = "query counting is currently: "; @@ -980,18 +983,18 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("setQueryCount", [](bool enabled) { g_qcount.enabled=enabled; }); + luaCtx.writeFunction("setQueryCount", [](bool enabled) { g_qcount.enabled=enabled; }); - g_lua.writeFunction("setQueryCountFilter", [](QueryCountFilter func) { + luaCtx.writeFunction("setQueryCountFilter", [](QueryCountFilter func) { g_qcount.filter = func; }); - g_lua.writeFunction("makeKey", []() { + luaCtx.writeFunction("makeKey", []() { setLuaNoSideEffect(); g_outputBuffer="setKey("+newKey()+")\n"; }); - g_lua.writeFunction("setKey", [](const std::string& key) { + 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 } @@ -1009,11 +1012,11 @@ static void setupLuaConfig(bool client, bool configCheck) g_consoleKey=newkey; }); - g_lua.writeFunction("clearConsoleHistory", []() { + luaCtx.writeFunction("clearConsoleHistory", []() { clearConsoleHistory(); }); - g_lua.writeFunction("testCrypto", [](boost::optional optTestMsg) + luaCtx.writeFunction("testCrypto", [](boost::optional optTestMsg) { setLuaNoSideEffect(); #ifdef HAVE_LIBSODIUM @@ -1055,13 +1058,13 @@ static void setupLuaConfig(bool client, bool configCheck) #endif }); - g_lua.writeFunction("setTCPRecvTimeout", [](int timeout) { g_tcpRecvTimeout=timeout; }); + luaCtx.writeFunction("setTCPRecvTimeout", [](int timeout) { g_tcpRecvTimeout=timeout; }); - g_lua.writeFunction("setTCPSendTimeout", [](int timeout) { g_tcpSendTimeout=timeout; }); + luaCtx.writeFunction("setTCPSendTimeout", [](int timeout) { g_tcpSendTimeout=timeout; }); - g_lua.writeFunction("setUDPTimeout", [](int timeout) { g_udpTimeout=timeout; }); + luaCtx.writeFunction("setUDPTimeout", [](int timeout) { g_udpTimeout=timeout; }); - g_lua.writeFunction("setMaxUDPOutstanding", [](uint16_t max) { + luaCtx.writeFunction("setMaxUDPOutstanding", [](uint16_t max) { if (!g_configurationDone) { g_maxOutstanding = max; } else { @@ -1069,7 +1072,7 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("setMaxTCPClientThreads", [](uint64_t max) { + luaCtx.writeFunction("setMaxTCPClientThreads", [](uint64_t max) { if (!g_configurationDone) { g_maxTCPClientThreads = max; } else { @@ -1077,7 +1080,7 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("setMaxTCPQueuedConnections", [](uint64_t max) { + luaCtx.writeFunction("setMaxTCPQueuedConnections", [](uint64_t max) { if (!g_configurationDone) { g_maxTCPQueuedConnections = max; } else { @@ -1085,7 +1088,7 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("setMaxTCPQueriesPerConnection", [](size_t max) { + luaCtx.writeFunction("setMaxTCPQueriesPerConnection", [](size_t max) { if (!g_configurationDone) { g_maxTCPQueriesPerConn = max; } else { @@ -1093,7 +1096,7 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("setMaxTCPConnectionsPerClient", [](size_t max) { + luaCtx.writeFunction("setMaxTCPConnectionsPerClient", [](size_t max) { if (!g_configurationDone) { g_maxTCPConnectionsPerClient = max; } else { @@ -1101,7 +1104,7 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("setMaxTCPConnectionDuration", [](size_t max) { + luaCtx.writeFunction("setMaxTCPConnectionDuration", [](size_t max) { if (!g_configurationDone) { g_maxTCPConnectionDuration = max; } else { @@ -1109,19 +1112,19 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("setCacheCleaningDelay", [](uint32_t delay) { g_cacheCleaningDelay = delay; }); + luaCtx.writeFunction("setCacheCleaningDelay", [](uint32_t delay) { g_cacheCleaningDelay = delay; }); - g_lua.writeFunction("setCacheCleaningPercentage", [](uint16_t percentage) { if (percentage < 100) g_cacheCleaningPercentage = percentage; else g_cacheCleaningPercentage = 100; }); + luaCtx.writeFunction("setCacheCleaningPercentage", [](uint16_t percentage) { if (percentage < 100) g_cacheCleaningPercentage = percentage; else g_cacheCleaningPercentage = 100; }); - g_lua.writeFunction("setECSSourcePrefixV4", [](uint16_t prefix) { g_ECSSourcePrefixV4=prefix; }); + luaCtx.writeFunction("setECSSourcePrefixV4", [](uint16_t prefix) { g_ECSSourcePrefixV4=prefix; }); - g_lua.writeFunction("setECSSourcePrefixV6", [](uint16_t prefix) { g_ECSSourcePrefixV6=prefix; }); + luaCtx.writeFunction("setECSSourcePrefixV6", [](uint16_t prefix) { g_ECSSourcePrefixV6=prefix; }); - g_lua.writeFunction("setECSOverride", [](bool override) { g_ECSOverride=override; }); + luaCtx.writeFunction("setECSOverride", [](bool override) { g_ECSOverride=override; }); - g_lua.writeFunction("setPreserveTrailingData", [](bool preserve) { g_preserveTrailingData = preserve; }); + luaCtx.writeFunction("setPreserveTrailingData", [](bool preserve) { g_preserveTrailingData = preserve; }); - g_lua.writeFunction("showDynBlocks", []() { + luaCtx.writeFunction("showDynBlocks", []() { setLuaNoSideEffect(); auto slow = g_dynblockNMG.getCopy(); struct timespec now; @@ -1144,7 +1147,7 @@ static void setupLuaConfig(bool client, bool configCheck) }); - g_lua.writeFunction("clearDynBlocks", []() { + luaCtx.writeFunction("clearDynBlocks", []() { setLuaSideEffect(); nmts_t nmg; g_dynblockNMG.setState(nmg); @@ -1152,7 +1155,7 @@ static void setupLuaConfig(bool client, bool configCheck) g_dynblockSMT.setState(smt); }); - g_lua.writeFunction("addDynBlocks", + luaCtx.writeFunction("addDynBlocks", [](const std::unordered_map& m, const std::string& msg, boost::optional seconds, boost::optional action) { if (m.empty()) { return; @@ -1185,7 +1188,7 @@ static void setupLuaConfig(bool client, bool configCheck) g_dynblockNMG.setState(slow); }); - g_lua.writeFunction("addDynBlockSMT", + luaCtx.writeFunction("addDynBlockSMT", [](const vector >&names, const std::string& msg, boost::optional seconds, boost::optional action) { if (names.empty()) { return; @@ -1222,7 +1225,7 @@ static void setupLuaConfig(bool client, bool configCheck) g_dynblockSMT.setState(slow); }); - g_lua.writeFunction("setDynBlocksAction", [](DNSAction::Action action) { + 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; @@ -1236,7 +1239,7 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("addDNSCryptBind", [](const std::string& addr, const std::string& providerName, boost::variant>> certFiles, boost::variant>> keyFiles, boost::optional vars) { + 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; @@ -1304,7 +1307,7 @@ static void setupLuaConfig(bool client, bool configCheck) }); - g_lua.writeFunction("showDNSCryptBinds", []() { + luaCtx.writeFunction("showDNSCryptBinds", []() { setLuaNoSideEffect(); #ifdef HAVE_DNSCRYPT ostringstream ret; @@ -1329,7 +1332,7 @@ static void setupLuaConfig(bool client, bool configCheck) #endif }); - g_lua.writeFunction("getDNSCryptBind", [](size_t idx) { + luaCtx.writeFunction("getDNSCryptBind", [](size_t idx) { setLuaNoSideEffect(); #ifdef HAVE_DNSCRYPT std::shared_ptr ret = nullptr; @@ -1342,12 +1345,12 @@ static void setupLuaConfig(bool client, bool configCheck) #endif }); - g_lua.writeFunction("getDNSCryptBindCount", []() { + luaCtx.writeFunction("getDNSCryptBindCount", []() { setLuaNoSideEffect(); return g_dnsCryptLocals.size(); }); - g_lua.writeFunction("generateDNSCryptProviderKeys", [client](const std::string& publicKeyFile, const std::string privateKeyFile) { + luaCtx.writeFunction("generateDNSCryptProviderKeys", [client](const std::string& publicKeyFile, const std::string privateKeyFile) { setLuaNoSideEffect(); #ifdef HAVE_DNSCRYPT if (client) { @@ -1382,7 +1385,7 @@ static void setupLuaConfig(bool client, bool configCheck) #endif }); - g_lua.writeFunction("printDNSCryptProviderFingerprint", [](const std::string& publicKeyFile) { + luaCtx.writeFunction("printDNSCryptProviderFingerprint", [](const std::string& publicKeyFile) { setLuaNoSideEffect(); #ifdef HAVE_DNSCRYPT unsigned char publicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE]; @@ -1407,7 +1410,7 @@ static void setupLuaConfig(bool client, bool configCheck) }); #ifdef HAVE_DNSCRYPT - g_lua.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) { + 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; @@ -1428,7 +1431,7 @@ static void setupLuaConfig(bool client, bool configCheck) }); #endif - g_lua.writeFunction("showPools", []() { + luaCtx.writeFunction("showPools", []() { setLuaNoSideEffect(); try { ostringstream ret; @@ -1441,9 +1444,9 @@ static void setupLuaConfig(bool client, bool configCheck) 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()->name; + string policy = g_policy.getLocal()->getName(); if (pool->policy != nullptr) { - policy = pool->policy->name; + policy = pool->policy->getName(); } string servers; @@ -1465,7 +1468,7 @@ static void setupLuaConfig(bool client, bool configCheck) }catch(std::exception& e) { g_outputBuffer=e.what(); throw; } }); - g_lua.writeFunction("getPool", [client](const string& poolName) { + luaCtx.writeFunction("getPool", [client](const string& poolName) { if (client) { return std::make_shared(); } @@ -1475,10 +1478,10 @@ static void setupLuaConfig(bool client, bool configCheck) return pool; }); - g_lua.writeFunction("setVerboseHealthChecks", [](bool verbose) { g_verboseHealthChecks=verbose; }); - g_lua.writeFunction("setStaleCacheEntriesTTL", [](uint32_t ttl) { g_staleCacheEntriesTTL = ttl; }); + luaCtx.writeFunction("setVerboseHealthChecks", [](bool verbose) { g_verboseHealthChecks=verbose; }); + luaCtx.writeFunction("setStaleCacheEntriesTTL", [](uint32_t ttl) { g_staleCacheEntriesTTL = ttl; }); - g_lua.writeFunction("showBinds", []() { + luaCtx.writeFunction("showBinds", []() { setLuaNoSideEffect(); try { ostringstream ret; @@ -1495,7 +1498,7 @@ static void setupLuaConfig(bool client, bool configCheck) }catch(std::exception& e) { g_outputBuffer=e.what(); throw; } }); - g_lua.writeFunction("getBind", [](size_t num) { + luaCtx.writeFunction("getBind", [](size_t num) { setLuaNoSideEffect(); ClientState* ret = nullptr; if(num < g_frontends.size()) { @@ -1504,12 +1507,12 @@ static void setupLuaConfig(bool client, bool configCheck) return ret; }); - g_lua.writeFunction("getBindCount", []() { + luaCtx.writeFunction("getBindCount", []() { setLuaNoSideEffect(); return g_frontends.size(); }); - g_lua.writeFunction("help", [](boost::optional command) { + luaCtx.writeFunction("help", [](boost::optional command) { setLuaNoSideEffect(); g_outputBuffer = ""; for (const auto& keyword : g_consoleKeywords) { @@ -1526,18 +1529,18 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("showVersion", []() { + luaCtx.writeFunction("showVersion", []() { setLuaNoSideEffect(); g_outputBuffer = "dnsdist " + std::string(VERSION) + "\n"; }); - g_lua.writeFunction("showSecurityStatus", []() { + luaCtx.writeFunction("showSecurityStatus", []() { setLuaNoSideEffect(); g_outputBuffer = std::to_string(g_stats.securityStatus) + "\n"; }); #ifdef HAVE_EBPF - g_lua.writeFunction("setDefaultBPFFilter", [](std::shared_ptr bpf) { + luaCtx.writeFunction("setDefaultBPFFilter", [](std::shared_ptr bpf) { if (g_configurationDone) { g_outputBuffer="setDefaultBPFFilter() cannot be used at runtime!\n"; return; @@ -1545,13 +1548,13 @@ static void setupLuaConfig(bool client, bool configCheck) g_defaultBPFFilter = bpf; }); - g_lua.writeFunction("registerDynBPFFilter", [](std::shared_ptr dbpf) { + luaCtx.writeFunction("registerDynBPFFilter", [](std::shared_ptr dbpf) { if (dbpf) { g_dynBPFFilters.push_back(dbpf); } }); - g_lua.writeFunction("unregisterDynBPFFilter", [](std::shared_ptr dbpf) { + luaCtx.writeFunction("unregisterDynBPFFilter", [](std::shared_ptr dbpf) { if (dbpf) { for (auto it = g_dynBPFFilters.begin(); it != g_dynBPFFilters.end(); it++) { if (*it == dbpf) { @@ -1562,7 +1565,7 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("addBPFFilterDynBlocks", [](const std::unordered_map& m, std::shared_ptr dynbpf, boost::optional seconds, boost::optional msg) { + luaCtx.writeFunction("addBPFFilterDynBlocks", [](const std::unordered_map& m, std::shared_ptr dynbpf, boost::optional seconds, boost::optional msg) { setLuaSideEffect(); struct timespec until, now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -1578,7 +1581,7 @@ static void setupLuaConfig(bool client, bool configCheck) #endif /* HAVE_EBPF */ - g_lua.writeFunction()>("getStatisticsCounters", []() { + luaCtx.writeFunction()>("getStatisticsCounters", []() { setLuaNoSideEffect(); std::unordered_map res; for(const auto& entry : g_stats.entries) { @@ -1588,7 +1591,7 @@ static void setupLuaConfig(bool client, bool configCheck) return res; }); - g_lua.writeFunction("includeDirectory", [](const std::string& dirname) { + 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"; @@ -1652,13 +1655,13 @@ static void setupLuaConfig(bool client, bool configCheck) vinfolog("Read configuration from '%s'", *file); } - g_lua.executeCode(ifs); + luaCtx.executeCode(ifs); } g_included = false; }); - g_lua.writeFunction("setAPIWritable", [](bool writable, boost::optional apiConfigDir) { + luaCtx.writeFunction("setAPIWritable", [](bool writable, boost::optional apiConfigDir) { setLuaSideEffect(); g_apiReadWrite = writable; if (apiConfigDir) { @@ -1672,17 +1675,17 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("setServFailWhenNoServer", [](bool servfail) { + luaCtx.writeFunction("setServFailWhenNoServer", [](bool servfail) { setLuaSideEffect(); g_servFailOnNoPolicy = servfail; }); - g_lua.writeFunction("setRoundRobinFailOnNoServer", [](bool fail) { + luaCtx.writeFunction("setRoundRobinFailOnNoServer", [](bool fail) { setLuaSideEffect(); g_roundrobinFailOnNoServer = fail; }); - g_lua.writeFunction("setConsistentHashingBalancingFactor", [](double factor) { + luaCtx.writeFunction("setConsistentHashingBalancingFactor", [](double factor) { setLuaSideEffect(); if (factor >= 1.0) { g_consistentHashBalancingFactor = factor; @@ -1694,7 +1697,7 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("setWeightedBalancingFactor", [](double factor) { + luaCtx.writeFunction("setWeightedBalancingFactor", [](double factor) { setLuaSideEffect(); if (factor >= 1.0) { g_weightedBalancingFactor = factor; @@ -1706,7 +1709,7 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("setRingBuffersSize", [](size_t capacity, boost::optional numberOfShards) { + luaCtx.writeFunction("setRingBuffersSize", [](size_t capacity, boost::optional numberOfShards) { setLuaSideEffect(); if (g_configurationDone) { errlog("setRingBuffersSize() cannot be used at runtime!"); @@ -1716,17 +1719,17 @@ static void setupLuaConfig(bool client, bool configCheck) g_rings.setCapacity(capacity, numberOfShards ? *numberOfShards : 1); }); - g_lua.writeFunction("setRingBuffersLockRetries", [](size_t retries) { + luaCtx.writeFunction("setRingBuffersLockRetries", [](size_t retries) { setLuaSideEffect(); g_rings.setNumberOfLockRetries(retries); }); - g_lua.writeFunction("setWHashedPertubation", [](uint32_t pertub) { + luaCtx.writeFunction("setWHashedPertubation", [](uint32_t pertub) { setLuaSideEffect(); g_hashperturb = pertub; }); - g_lua.writeFunction("setTCPUseSinglePipe", [](bool flag) { + luaCtx.writeFunction("setTCPUseSinglePipe", [](bool flag) { if (g_configurationDone) { g_outputBuffer="setTCPUseSinglePipe() cannot be used at runtime!\n"; return; @@ -1735,7 +1738,7 @@ static void setupLuaConfig(bool client, bool configCheck) g_useTCPSinglePipe = flag; }); - g_lua.writeFunction("snmpAgent", [client,configCheck](bool enableTraps, boost::optional masterSocket) { + luaCtx.writeFunction("snmpAgent", [client,configCheck](bool enableTraps, boost::optional masterSocket) { if(client || configCheck) return; #ifdef HAVE_NET_SNMP @@ -1760,72 +1763,92 @@ static void setupLuaConfig(bool client, bool configCheck) #endif /* HAVE_NET_SNMP */ }); - g_lua.writeFunction("sendCustomTrap", [](const std::string& str) { + luaCtx.writeFunction("sendCustomTrap", [](const std::string& str) { if (g_snmpAgent && g_snmpTrapsEnabled) { g_snmpAgent->sendCustomTrap(str); } }); - g_lua.writeFunction("setServerPolicy", [](ServerPolicy policy) { + luaCtx.writeFunction("setServerPolicy", [](ServerPolicy policy) { setLuaSideEffect(); g_policy.setState(policy); }); - g_lua.writeFunction("setServerPolicyLua", [](string name, ServerPolicy::policyfunc_t policy) { + luaCtx.writeFunction("setServerPolicyLua", [](string name, ServerPolicy::policyfunc_t policy) { setLuaSideEffect(); g_policy.setState(ServerPolicy{name, policy, true}); }); - g_lua.writeFunction("setServerPolicyLuaFFI", [](string name, ServerPolicy::ffipolicyfunc_t policy) { + luaCtx.writeFunction("setServerPolicyLuaFFI", [](string name, ServerPolicy::ffipolicyfunc_t policy) { setLuaSideEffect(); auto pol = ServerPolicy(name, policy); g_policy.setState(std::move(pol)); }); - g_lua.writeFunction("showServerPolicy", []() { + luaCtx.writeFunction("setServerPolicyLuaFFIPerThread", [](string name, const std::string& policyCode) { setLuaSideEffect(); - g_outputBuffer=g_policy.getLocal()->name+"\n"; + auto pol = ServerPolicy(name, policyCode); + g_policy.setState(std::move(pol)); }); - g_lua.writeFunction("setPoolServerPolicy", [](ServerPolicy policy, string pool) { + luaCtx.writeFunction("showServerPolicy", []() { + 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); }); - g_lua.writeFunction("setPoolServerPolicyLua", [](string name, ServerPolicy::policyfunc_t policy, string pool) { + 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); }); - g_lua.writeFunction("showPoolServerPolicy", [](string pool) { + 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); + }); + + 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); + }); + + 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()->name+"\n"; + g_outputBuffer=g_policy.getLocal()->getName()+"\n"; } else { - g_outputBuffer=poolObj->policy->name+"\n"; + g_outputBuffer=poolObj->policy->getName()+"\n"; } }); - g_lua.writeFunction("setTCPDownstreamCleanupInterval", [](uint16_t interval) { + luaCtx.writeFunction("setTCPDownstreamCleanupInterval", [](uint16_t interval) { setLuaSideEffect(); g_downstreamTCPCleanupInterval = interval; }); - g_lua.writeFunction("setConsoleConnectionsLogging", [](bool enabled) { + luaCtx.writeFunction("setConsoleConnectionsLogging", [](bool enabled) { g_logConsoleConnections = enabled; }); - g_lua.writeFunction("setConsoleOutputMaxMsgSize", [](uint32_t size) { + luaCtx.writeFunction("setConsoleOutputMaxMsgSize", [](uint32_t size) { g_consoleOutputMsgMaxSize = size; }); - g_lua.writeFunction("setUDPMultipleMessagesVectorSize", [](size_t vSize) { + 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"; @@ -1840,11 +1863,11 @@ static void setupLuaConfig(bool client, bool configCheck) #endif }); - g_lua.writeFunction("setAddEDNSToSelfGeneratedResponses", [](bool add) { + luaCtx.writeFunction("setAddEDNSToSelfGeneratedResponses", [](bool add) { g_addEDNSToSelfGeneratedResponses = add; }); - g_lua.writeFunction("setPayloadSizeOnSelfGeneratedAnswers", [](uint16_t payloadSize) { + 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!"; @@ -1858,7 +1881,7 @@ static void setupLuaConfig(bool client, bool configCheck) g_PayloadSizeSelfGenAnswers = payloadSize; }); - g_lua.writeFunction("setSecurityPollSuffix", [](const std::string& suffix) { + luaCtx.writeFunction("setSecurityPollSuffix", [](const std::string& suffix) { if (g_configurationDone) { g_outputBuffer="setSecurityPollSuffix() cannot be used at runtime!\n"; return; @@ -1867,7 +1890,7 @@ static void setupLuaConfig(bool client, bool configCheck) g_secPollSuffix = suffix; }); - g_lua.writeFunction("setSecurityPollInterval", [](time_t newInterval) { + luaCtx.writeFunction("setSecurityPollInterval", [](time_t newInterval) { if (newInterval <= 0) { warnlog("setSecurityPollInterval() should be > 0, skipping"); g_outputBuffer="setSecurityPollInterval() should be > 0, skipping"; @@ -1876,7 +1899,7 @@ static void setupLuaConfig(bool client, bool configCheck) g_secPollInterval = newInterval; }); - g_lua.writeFunction("setSyslogFacility", [](int facility) { + luaCtx.writeFunction("setSyslogFacility", [](int facility) { setLuaSideEffect(); if (g_configurationDone) { g_outputBuffer="setSyslogFacility cannot be used at runtime!\n"; @@ -1885,7 +1908,7 @@ static void setupLuaConfig(bool client, bool configCheck) setSyslogFacility(facility); }); - g_lua.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; } @@ -1975,7 +1998,7 @@ static void setupLuaConfig(bool client, bool configCheck) #endif }); - g_lua.writeFunction("showDOHFrontends", []() { + luaCtx.writeFunction("showDOHFrontends", []() { #ifdef HAVE_DNS_OVER_HTTPS setLuaNoSideEffect(); try { @@ -1998,7 +2021,7 @@ static void setupLuaConfig(bool client, bool configCheck) #endif }); - g_lua.writeFunction("showDOHResponseCodes", []() { + luaCtx.writeFunction("showDOHResponseCodes", []() { #ifdef HAVE_DNS_OVER_HTTPS setLuaNoSideEffect(); try { @@ -2032,7 +2055,7 @@ static void setupLuaConfig(bool client, bool configCheck) #endif }); - g_lua.writeFunction("getDOHFrontend", [client](size_t index) { + luaCtx.writeFunction("getDOHFrontend", [client](size_t index) { std::shared_ptr result = nullptr; if (client) { return result; @@ -2058,30 +2081,30 @@ static void setupLuaConfig(bool client, bool configCheck) return result; }); - g_lua.writeFunction("getDOHFrontendCount", []() { + luaCtx.writeFunction("getDOHFrontendCount", []() { setLuaNoSideEffect(); return g_dohlocals.size(); }); - g_lua.registerFunction::*)()>("reloadCertificates", [](std::shared_ptr frontend) { + luaCtx.registerFunction::*)()>("reloadCertificates", [](std::shared_ptr frontend) { if (frontend != nullptr) { frontend->reloadCertificates(); } }); - g_lua.registerFunction::*)()>("rotateTicketsKey", [](std::shared_ptr frontend) { + luaCtx.registerFunction::*)()>("rotateTicketsKey", [](std::shared_ptr frontend) { if (frontend != nullptr) { frontend->rotateTicketsKey(time(nullptr)); } }); - g_lua.registerFunction::*)(const std::string&)>("loadTicketsKeys", [](std::shared_ptr frontend, const std::string& file) { + luaCtx.registerFunction::*)(const std::string&)>("loadTicketsKeys", [](std::shared_ptr frontend, const std::string& file) { if (frontend != nullptr) { frontend->loadTicketsKeys(file); } }); - g_lua.registerFunction::*)(const std::map>&)>("setResponsesMap", [](std::shared_ptr frontend, const std::map>& map) { + luaCtx.registerFunction::*)(const std::map>&)>("setResponsesMap", [](std::shared_ptr frontend, const std::map>& map) { if (frontend != nullptr) { std::vector> newMap; newMap.reserve(map.size()); @@ -2094,7 +2117,7 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("addTLSLocal", [client](const std::string& addr, boost::variant>> certFiles, boost::variant>> keyFiles, boost::optional vars) { + luaCtx.writeFunction("addTLSLocal", [client](const std::string& addr, boost::variant>> certFiles, boost::variant>> keyFiles, boost::optional vars) { if (client) { return; } @@ -2156,7 +2179,7 @@ static void setupLuaConfig(bool client, bool configCheck) #endif }); - g_lua.writeFunction("showTLSContexts", []() { + luaCtx.writeFunction("showTLSContexts", []() { #ifdef HAVE_DNS_OVER_TLS setLuaNoSideEffect(); try { @@ -2180,7 +2203,7 @@ static void setupLuaConfig(bool client, bool configCheck) #endif }); - g_lua.writeFunction("getTLSContext", [](size_t index) { + luaCtx.writeFunction("getTLSContext", [](size_t index) { std::shared_ptr result = nullptr; #ifdef HAVE_DNS_OVER_TLS setLuaNoSideEffect(); @@ -2203,7 +2226,7 @@ static void setupLuaConfig(bool client, bool configCheck) return result; }); - g_lua.writeFunction("getTLSFrontend", [](size_t index) { + luaCtx.writeFunction("getTLSFrontend", [](size_t index) { std::shared_ptr result = nullptr; #ifdef HAVE_DNS_OVER_TLS setLuaNoSideEffect(); @@ -2226,24 +2249,24 @@ static void setupLuaConfig(bool client, bool configCheck) return result; }); - g_lua.writeFunction("getTLSFrontendCount", []() { + luaCtx.writeFunction("getTLSFrontendCount", []() { setLuaNoSideEffect(); return g_tlslocals.size(); }); - g_lua.registerFunction::*)()>("rotateTicketsKey", [](std::shared_ptr ctx) { + luaCtx.registerFunction::*)()>("rotateTicketsKey", [](std::shared_ptr ctx) { if (ctx != nullptr) { ctx->rotateTicketsKey(time(nullptr)); } }); - g_lua.registerFunction::*)(const std::string&)>("loadTicketsKeys", [](std::shared_ptr ctx, const std::string& file) { + luaCtx.registerFunction::*)(const std::string&)>("loadTicketsKeys", [](std::shared_ptr ctx, const std::string& file) { if (ctx != nullptr) { ctx->loadTicketsKeys(file); } }); - g_lua.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("loadNewCertificatesAndKeys", frontend->d_tlsConfig.d_certKeyPairs, certFiles, keyFiles)) { frontend->setupTLS(); @@ -2251,7 +2274,7 @@ static void setupLuaConfig(bool client, bool configCheck) #endif }); - g_lua.writeFunction("reloadAllCertificates", []() { + luaCtx.writeFunction("reloadAllCertificates", []() { for (auto& frontend : g_frontends) { if (!frontend) { continue; @@ -2279,10 +2302,10 @@ static void setupLuaConfig(bool client, bool configCheck) } }); - g_lua.writeFunction("setAllowEmptyResponse", [](bool allow) { g_allowEmptyResponse=allow; }); + luaCtx.writeFunction("setAllowEmptyResponse", [](bool allow) { g_allowEmptyResponse=allow; }); #if defined(HAVE_LIBSSL) && defined(HAVE_OCSP_BASIC_SIGN) - g_lua.writeFunction("generateOCSPResponse", [client](const std::string& certFile, const std::string& caCert, const std::string& caKey, const std::string& outFile, int ndays, int nmin) { + 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; } @@ -2292,24 +2315,26 @@ static void setupLuaConfig(bool client, bool configCheck) #endif /* HAVE_LIBSSL && HAVE_OCSP_BASIC_SIGN*/ } -vector> setupLua(bool client, bool configCheck, const std::string& config) +vector> setupLua(LuaContext& luaCtx, bool client, bool configCheck, const std::string& config) { - g_launchWork= new vector>(); - - setupLuaActions(); - setupLuaConfig(client, configCheck); - setupLuaBindings(client); - setupLuaBindingsDNSCrypt(); - setupLuaBindingsDNSQuestion(); - setupLuaBindingsKVS(client); - setupLuaBindingsPacketCache(); - setupLuaBindingsProtoBuf(client, configCheck); - setupLuaInspection(); - setupLuaRules(); - setupLuaVars(); + // this needs to exist only during the parsing of the configuration + // and cannot be captured by lambdas + g_launchWork = std::vector>(); + + setupLuaActions(luaCtx); + setupLuaConfig(luaCtx, client, configCheck); + setupLuaBindings(luaCtx, client); + setupLuaBindingsDNSCrypt(luaCtx); + setupLuaBindingsDNSQuestion(luaCtx); + setupLuaBindingsKVS(luaCtx, client); + setupLuaBindingsPacketCache(luaCtx); + setupLuaBindingsProtoBuf(luaCtx, client, configCheck); + setupLuaInspection(luaCtx); + setupLuaRules(luaCtx); + setupLuaVars(luaCtx); #ifdef LUAJIT_VERSION - g_lua.executeCode(getLuaFFIWrappers()); + luaCtx.executeCode(getLuaFFIWrappers()); #endif std::ifstream ifs(config); @@ -2318,10 +2343,9 @@ vector> setupLua(bool client, bool configCheck, const else vinfolog("Read configuration from '%s'", config); - g_lua.executeCode(ifs); + luaCtx.executeCode(ifs); auto ret = *g_launchWork; - delete g_launchWork; - g_launchWork = nullptr; + g_launchWork = boost::none; return ret; } diff --git a/pdns/dnsdist-lua.hh b/pdns/dnsdist-lua.hh index b25be8840f..4818345e65 100644 --- a/pdns/dnsdist-lua.hh +++ b/pdns/dnsdist-lua.hh @@ -94,14 +94,15 @@ void parseRuleParams(boost::optional params, boost::uuids::uuid typedef NetmaskTree nmts_t; -vector> setupLua(bool client, bool configCheck, const std::string& config); -void setupLuaActions(); -void setupLuaBindings(bool client); -void setupLuaBindingsDNSCrypt(); -void setupLuaBindingsDNSQuestion(); -void setupLuaBindingsKVS(bool client); -void setupLuaBindingsPacketCache(); -void setupLuaBindingsProtoBuf(bool client, bool configCheck); -void setupLuaRules(); -void setupLuaInspection(); -void setupLuaVars(); +vector> setupLua(LuaContext& luaCtx, bool client, bool configCheck, const std::string& config); +void setupLuaActions(LuaContext& luaCtx); +void setupLuaBindings(LuaContext& luaCtx, bool client); +void setupLuaBindingsDNSCrypt(LuaContext& luaCtx); +void setupLuaBindingsDNSQuestion(LuaContext& luaCtx); +void setupLuaBindingsKVS(LuaContext& luaCtx, bool client); +void setupLuaBindingsPacketCache(LuaContext& luaCtx); +void setupLuaBindingsProtoBuf(LuaContext& luaCtx, bool client, bool configCheck); +void setupLuaRules(LuaContext& luaCtx); +void setupLuaInspection(LuaContext& luaCtx); +void setupLuaVars(LuaContext& luaCtx); +void setupLuaLoadBalancingContext(LuaContext& luaCtx); diff --git a/pdns/dnsdist-tcp.cc b/pdns/dnsdist-tcp.cc index 854c996e34..71c669202f 100644 --- a/pdns/dnsdist-tcp.cc +++ b/pdns/dnsdist-tcp.cc @@ -1405,10 +1405,10 @@ void tcpClientThread(int pipefd) /* spawn as many of these as required, they call Accept on a socket on which they will accept queries, and they will hand off to worker threads & spawn more of them if required */ -void tcpAcceptorThread(void* p) +void tcpAcceptorThread(ClientState* cs) { setThreadName("dnsdist/tcpAcce"); - ClientState* cs = (ClientState*) p; + bool tcpClientCountIncremented = false; ComboAddress remote; remote.sin4.sin_family = cs->local.sin4.sin_family; diff --git a/pdns/dnsdist-web.cc b/pdns/dnsdist-web.cc index 0c0389848d..00da6abe1f 100644 --- a/pdns/dnsdist-web.cc +++ b/pdns/dnsdist-web.cc @@ -381,7 +381,7 @@ static void connectionThread(int sock, ComboAddress remote) { "packetcache-misses", 0}, { "over-capacity-drops", 0 }, { "too-old-drops", 0 }, - { "server-policy", g_policy.getLocal()->name} + { "server-policy", g_policy.getLocal()->getName()} }; for(const auto& e : g_stats.entries) { @@ -1083,7 +1083,7 @@ static void connectionThread(int sock, ComboAddress remote) { "ecs-source-prefix-v6", (double) g_ECSSourcePrefixV6 }, { "fixup-case", g_fixupCase }, { "max-outstanding", (double) g_maxOutstanding }, - { "server-policy", g_policy.getLocal()->name }, + { "server-policy", g_policy.getLocal()->getName() }, { "stale-cache-entries-ttl", (double) g_staleCacheEntriesTTL }, { "tcp-recv-timeout", (double) g_tcpRecvTimeout }, { "tcp-send-timeout", (double) g_tcpSendTimeout }, diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index 4e62293526..ac24be4c58 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -1199,7 +1199,7 @@ ProcessQueryResult processQuery(DNSQuestion& dq, ClientState& cs, LocalHolders& policy = *(serverPool->policy); } const auto servers = serverPool->getServers(); - selectedBackend = getSelectedBackendFromPolicy(policy, *servers, dq); + selectedBackend = policy.getSelectedBackend(*servers, dq); uint16_t cachedResponseSize = dq.size; uint32_t allowExpired = selectedBackend ? 0 : g_staleCacheEntriesTTL; @@ -2168,7 +2168,7 @@ try g_policy.setState(leastOutstandingPol); if(g_cmdLine.beClient || !g_cmdLine.command.empty()) { - setupLua(true, false, g_cmdLine.config); + setupLua(g_lua, true, false, g_cmdLine.config); if (clientAddress != ComboAddress()) g_serverControl = clientAddress; doClient(g_serverControl, g_cmdLine.command); @@ -2189,22 +2189,22 @@ try g_consoleACL.setState(consoleACL); if (g_cmdLine.checkConfig) { - setupLua(false, true, g_cmdLine.config); + setupLua(g_lua, false, true, g_cmdLine.config); // No exception was thrown infolog("Configuration '%s' OK!", g_cmdLine.config); _exit(EXIT_SUCCESS); } - auto todo=setupLua(false, false, g_cmdLine.config); + auto todo = setupLua(g_lua, false, false, g_cmdLine.config); auto localPools = g_pools.getCopy(); { bool precompute = false; - if (g_policy.getLocal()->name == "chashed") { + if (g_policy.getLocal()->getName() == "chashed") { precompute = true; } else { for (const auto& entry: localPools) { - if (entry.second->policy != nullptr && entry.second->policy->name == "chashed") { + if (entry.second->policy != nullptr && entry.second->policy->getName() == "chashed") { precompute = true; break ; } diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index 9c6dcd16c0..55c0868647 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -1107,7 +1107,7 @@ struct dnsheader; vector> setupLua(bool client, const std::string& config); -void tcpAcceptorThread(void* p); +void tcpAcceptorThread(ClientState* p); #ifdef HAVE_DNS_OVER_HTTPS void dohThread(ClientState* cs); #endif /* HAVE_DNS_OVER_HTTPS */ diff --git a/pdns/dnsdistdist/Makefile.am b/pdns/dnsdistdist/Makefile.am index b0ca67ad42..828af5ec5d 100644 --- a/pdns/dnsdistdist/Makefile.am +++ b/pdns/dnsdistdist/Makefile.am @@ -219,17 +219,23 @@ testrunner_SOURCES = \ test-iputils_hh.cc \ test-mplexer.cc \ test-proxy_protocol_cc.cc \ + bpf-filter.cc bpf-filter.hh \ cachecleaner.hh \ circular_buffer.hh \ dnsdist.hh \ dnsdist-backend.cc \ dnsdist-cache.cc dnsdist-cache.hh \ dnsdist-dynblocks.cc dnsdist-dynblocks.hh \ + dnsdist-dynbpf.cc dnsdist-dynbpf.hh \ dnsdist-ecs.cc dnsdist-ecs.hh \ dnsdist-kvs.cc dnsdist-kvs.hh \ dnsdist-lbpolicies.cc dnsdist-lbpolicies.hh \ + dnsdist-lua-bindings.cc \ + dnsdist-lua-bindings-dnsquestion.cc \ + dnsdist-lua-bindings-kvs.cc \ dnsdist-lua-ffi.cc dnsdist-lua-ffi.hh \ dnsdist-lua-ffi-interface.h dnsdist-lua-ffi-interface.inc \ + dnsdist-lua-vars.cc \ dnsdist-rings.hh \ dnsdist-xpf.cc dnsdist-xpf.hh \ dnscrypt.cc dnscrypt.hh \ diff --git a/pdns/dnsdistdist/dnsdist-lbpolicies.cc b/pdns/dnsdistdist/dnsdist-lbpolicies.cc index b4268364f7..1d75ca0600 100644 --- a/pdns/dnsdistdist/dnsdist-lbpolicies.cc +++ b/pdns/dnsdistdist/dnsdist-lbpolicies.cc @@ -22,6 +22,7 @@ #include "dnsdist.hh" #include "dnsdist-lbpolicies.hh" +#include "dnsdist-lua.hh" #include "dnsdist-lua-ffi.hh" #include "dolog.hh" @@ -251,9 +252,9 @@ void setPoolPolicy(pools_t& pools, const string& poolName, std::shared_ptr pool = createPoolIfNotExists(pools, poolName); if (!poolName.empty()) { - vinfolog("Setting pool %s server selection policy to %s", poolName, policy->name); + vinfolog("Setting pool %s server selection policy to %s", poolName, policy->getName()); } else { - vinfolog("Setting default pool server selection policy to %s", policy->name); + vinfolog("Setting default pool server selection policy to %s", policy->getName()); } pool->policy = policy; } @@ -294,28 +295,61 @@ std::shared_ptr getPool(const pools_t& pools, const std::string& poo return it->second; } -std::shared_ptr getSelectedBackendFromPolicy(const ServerPolicy& policy, const ServerPolicy::NumberedServerVector& servers, DNSQuestion& dq) +ServerPolicy::ServerPolicy(const std::string& name_, const std::string& code): d_name(name_), d_perThreadPolicyCode(code), d_isLua(true), d_isFFI(true), d_isPerThread(true) +{ + LuaContext tmpContext; + setupLuaLoadBalancingContext(tmpContext); + auto ret = tmpContext.executeCode(code); +} + +thread_local ServerPolicy::PerThreadState ServerPolicy::t_perThreadState; + +const ServerPolicy::ffipolicyfunc_t& ServerPolicy::getPerThreadPolicy() const +{ + auto& state = t_perThreadState; + if (!state.d_initialized) { + setupLuaLoadBalancingContext(state.d_luaContext); + state.d_initialized = true; + } + + const auto& it = state.d_policies.find(d_name); + if (it != state.d_policies.end()) { + return it->second; + } + + auto newPolicy = state.d_luaContext.executeCode(d_perThreadPolicyCode); + state.d_policies[d_name] = std::move(newPolicy); + return state.d_policies.at(d_name); +} + +std::shared_ptr ServerPolicy::getSelectedBackend(const ServerPolicy::NumberedServerVector& servers, DNSQuestion& dq) const { std::shared_ptr selectedBackend{nullptr}; - if (policy.isLua) { - if (!policy.isFFI) { + if (d_isLua) { + if (!d_isFFI) { std::lock_guard lock(g_luamutex); - selectedBackend = policy.policy(servers, &dq); + selectedBackend = d_policy(servers, &dq); } else { dnsdist_ffi_dnsquestion_t dnsq(&dq); dnsdist_ffi_servers_list_t serversList(servers); unsigned int selected = 0; - { + + if (!d_isPerThread) { std::lock_guard lock(g_luamutex); - selected = policy.ffipolicy(&serversList, &dnsq); + selected = d_ffipolicy(&serversList, &dnsq); + } + else { + const auto& policy = getPerThreadPolicy(); + selected = policy(&serversList, &dnsq); } + selectedBackend = servers.at(selected).second; } } else { - selectedBackend = policy.policy(servers, &dq); + selectedBackend = d_policy(servers, &dq); } return selectedBackend; diff --git a/pdns/dnsdistdist/dnsdist-lua-bindings-dnscrypt.cc b/pdns/dnsdistdist/dnsdist-lua-bindings-dnscrypt.cc index 6a25dcf852..ff2a13ee15 100644 --- a/pdns/dnsdistdist/dnsdist-lua-bindings-dnscrypt.cc +++ b/pdns/dnsdistdist/dnsdist-lua-bindings-dnscrypt.cc @@ -26,15 +26,15 @@ #include "dolog.hh" -void setupLuaBindingsDNSCrypt() +void setupLuaBindingsDNSCrypt(LuaContext& luaCtx) { #ifdef HAVE_DNSCRYPT /* DNSCryptContext bindings */ - g_lua.registerFunction("getProviderName", [](const DNSCryptContext& ctx) { return ctx.getProviderName().toStringNoDot(); }); - g_lua.registerFunction("markActive", &DNSCryptContext::markActive); - g_lua.registerFunction("markInactive", &DNSCryptContext::markInactive); - g_lua.registerFunction("removeInactiveCertificate", &DNSCryptContext::removeInactiveCertificate); - g_lua.registerFunction::*)(const std::string& certFile, const std::string& keyFile, boost::optional active)>("loadNewCertificate", [](std::shared_ptr ctx, const std::string& certFile, const std::string& keyFile, boost::optional active) { + luaCtx.registerFunction("getProviderName", [](const DNSCryptContext& ctx) { return ctx.getProviderName().toStringNoDot(); }); + luaCtx.registerFunction("markActive", &DNSCryptContext::markActive); + luaCtx.registerFunction("markInactive", &DNSCryptContext::markInactive); + luaCtx.registerFunction("removeInactiveCertificate", &DNSCryptContext::removeInactiveCertificate); + luaCtx.registerFunction::*)(const std::string& certFile, const std::string& keyFile, boost::optional active)>("loadNewCertificate", [](std::shared_ptr ctx, const std::string& certFile, const std::string& keyFile, boost::optional active) { if (ctx == nullptr) { throw std::runtime_error("DNSCryptContext::loadNewCertificate() called on a nil value"); @@ -42,7 +42,7 @@ void setupLuaBindingsDNSCrypt() ctx->loadNewCertificate(certFile, keyFile, active ? *active : true); }); - g_lua.registerFunction::*)(const DNSCryptCert& newCert, const DNSCryptPrivateKey& newKey, boost::optional active)>("addNewCertificate", [](std::shared_ptr ctx, const DNSCryptCert& newCert, const DNSCryptPrivateKey& newKey, boost::optional active) { + luaCtx.registerFunction::*)(const DNSCryptCert& newCert, const DNSCryptPrivateKey& newKey, boost::optional active)>("addNewCertificate", [](std::shared_ptr ctx, const DNSCryptCert& newCert, const DNSCryptPrivateKey& newKey, boost::optional active) { if (ctx == nullptr) { throw std::runtime_error("DNSCryptContext::addNewCertificate() called on a nil value"); @@ -50,7 +50,7 @@ void setupLuaBindingsDNSCrypt() ctx->addNewCertificate(newCert, newKey, active ? *active : true); }); - g_lua.registerFunction>(std::shared_ptr::*)()>("getCertificatePairs", [](std::shared_ptr ctx) { + luaCtx.registerFunction>(std::shared_ptr::*)()>("getCertificatePairs", [](std::shared_ptr ctx) { std::map> result; if (ctx != nullptr) { @@ -63,7 +63,7 @@ void setupLuaBindingsDNSCrypt() return result; }); - g_lua.registerFunction(std::shared_ptr::*)(size_t idx)>("getCertificatePair", [](std::shared_ptr ctx, size_t idx) { + luaCtx.registerFunction(std::shared_ptr::*)(size_t idx)>("getCertificatePair", [](std::shared_ptr ctx, size_t idx) { if (ctx == nullptr) { throw std::runtime_error("DNSCryptContext::getCertificatePair() called on a nil value"); @@ -78,7 +78,7 @@ void setupLuaBindingsDNSCrypt() return result; }); - g_lua.registerFunction::*)(size_t idx)>("getCertificate", [](std::shared_ptr ctx, size_t idx) { + luaCtx.registerFunction::*)(size_t idx)>("getCertificate", [](std::shared_ptr ctx, size_t idx) { if (ctx == nullptr) { throw std::runtime_error("DNSCryptContext::getCertificate() called on a nil value"); @@ -92,7 +92,7 @@ void setupLuaBindingsDNSCrypt() throw std::runtime_error("This DNSCrypt context has no certificate at index " + std::to_string(idx)); }); - g_lua.registerFunction::*)()>("printCertificates", [](const std::shared_ptr ctx) { + luaCtx.registerFunction::*)()>("printCertificates", [](const std::shared_ptr ctx) { ostringstream ret; if (ctx != nullptr) { @@ -111,7 +111,7 @@ void setupLuaBindingsDNSCrypt() return ret.str(); }); - g_lua.registerFunction version)>("generateAndLoadInMemoryCertificate", [](DNSCryptContext& ctx, const std::string& providerPrivateKeyFile, uint32_t serial, time_t begin, time_t end, boost::optional version) { + luaCtx.registerFunction version)>("generateAndLoadInMemoryCertificate", [](DNSCryptContext& ctx, const std::string& providerPrivateKeyFile, uint32_t serial, time_t begin, time_t end, boost::optional version) { DNSCryptPrivateKey privateKey; DNSCryptCert cert; @@ -127,13 +127,13 @@ void setupLuaBindingsDNSCrypt() }); /* DNSCryptCertificatePair */ - g_lua.registerFunction::*)()>("getCertificate", [](const std::shared_ptr pair) { + luaCtx.registerFunction::*)()>("getCertificate", [](const std::shared_ptr pair) { if (pair == nullptr) { throw std::runtime_error("DNSCryptCertificatePair::getCertificate() called on a nil value"); } return pair->cert; }); - g_lua.registerFunction::*)()>("isActive", [](const std::shared_ptr pair) { + luaCtx.registerFunction::*)()>("isActive", [](const std::shared_ptr pair) { if (pair == nullptr) { throw std::runtime_error("DNSCryptCertificatePair::isActive() called on a nil value"); } @@ -141,14 +141,14 @@ void setupLuaBindingsDNSCrypt() }); /* DNSCryptCert */ - g_lua.registerFunction("getMagic", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast(cert.magic), sizeof(cert.magic)); }); - g_lua.registerFunction("getEsVersion", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast(cert.esVersion), sizeof(cert.esVersion)); }); - g_lua.registerFunction("getProtocolMinorVersion", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast(cert.protocolMinorVersion), sizeof(cert.protocolMinorVersion)); }); - g_lua.registerFunction("getSignature", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast(cert.signature), sizeof(cert.signature)); }); - g_lua.registerFunction("getResolverPublicKey", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast(cert.signedData.resolverPK), sizeof(cert.signedData.resolverPK)); }); - g_lua.registerFunction("getClientMagic", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast(cert.signedData.clientMagic), sizeof(cert.signedData.clientMagic)); }); - g_lua.registerFunction("getSerial", [](const DNSCryptCert& cert) { return cert.getSerial(); }); - g_lua.registerFunction("getTSStart", [](const DNSCryptCert& cert) { return ntohl(cert.getTSStart()); }); - g_lua.registerFunction("getTSEnd", [](const DNSCryptCert& cert) { return ntohl(cert.getTSEnd()); }); + luaCtx.registerFunction("getMagic", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast(cert.magic), sizeof(cert.magic)); }); + luaCtx.registerFunction("getEsVersion", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast(cert.esVersion), sizeof(cert.esVersion)); }); + luaCtx.registerFunction("getProtocolMinorVersion", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast(cert.protocolMinorVersion), sizeof(cert.protocolMinorVersion)); }); + luaCtx.registerFunction("getSignature", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast(cert.signature), sizeof(cert.signature)); }); + luaCtx.registerFunction("getResolverPublicKey", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast(cert.signedData.resolverPK), sizeof(cert.signedData.resolverPK)); }); + luaCtx.registerFunction("getClientMagic", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast(cert.signedData.clientMagic), sizeof(cert.signedData.clientMagic)); }); + luaCtx.registerFunction("getSerial", [](const DNSCryptCert& cert) { return cert.getSerial(); }); + luaCtx.registerFunction("getTSStart", [](const DNSCryptCert& cert) { return ntohl(cert.getTSStart()); }); + luaCtx.registerFunction("getTSEnd", [](const DNSCryptCert& cert) { return ntohl(cert.getTSEnd()); }); #endif } diff --git a/pdns/dnsdistdist/dnsdist-lua-bindings-kvs.cc b/pdns/dnsdistdist/dnsdist-lua-bindings-kvs.cc index 3bc185056e..bf26914bc7 100644 --- a/pdns/dnsdistdist/dnsdist-lua-bindings-kvs.cc +++ b/pdns/dnsdistdist/dnsdist-lua-bindings-kvs.cc @@ -23,24 +23,24 @@ #include "dnsdist-kvs.hh" #include "dnsdist-lua.hh" -void setupLuaBindingsKVS(bool client) +void setupLuaBindingsKVS(LuaContext& luaCtx, bool client) { /* Key Value Store objects */ - g_lua.writeFunction("KeyValueLookupKeySourceIP", [](boost::optional v4Mask, boost::optional v6Mask) { + luaCtx.writeFunction("KeyValueLookupKeySourceIP", [](boost::optional v4Mask, boost::optional v6Mask) { return std::shared_ptr(new KeyValueLookupKeySourceIP(v4Mask.get_value_or(32), v6Mask.get_value_or(128))); }); - g_lua.writeFunction("KeyValueLookupKeyQName", [](boost::optional wireFormat) { + luaCtx.writeFunction("KeyValueLookupKeyQName", [](boost::optional wireFormat) { return std::shared_ptr(new KeyValueLookupKeyQName(wireFormat ? *wireFormat : true)); }); - g_lua.writeFunction("KeyValueLookupKeySuffix", [](boost::optional minLabels, boost::optional wireFormat) { + luaCtx.writeFunction("KeyValueLookupKeySuffix", [](boost::optional minLabels, boost::optional wireFormat) { return std::shared_ptr(new KeyValueLookupKeySuffix(minLabels ? *minLabels : 0, wireFormat ? *wireFormat : true)); }); - g_lua.writeFunction("KeyValueLookupKeyTag", [](const std::string& tag) { + luaCtx.writeFunction("KeyValueLookupKeyTag", [](const std::string& tag) { return std::shared_ptr(new KeyValueLookupKeyTag(tag)); }); #ifdef HAVE_LMDB - g_lua.writeFunction("newLMDBKVStore", [client](const std::string& fname, const std::string& dbName) { + luaCtx.writeFunction("newLMDBKVStore", [client](const std::string& fname, const std::string& dbName) { if (client) { return std::shared_ptr(nullptr); } @@ -49,7 +49,7 @@ void setupLuaBindingsKVS(bool client) #endif /* HAVE_LMDB */ #ifdef HAVE_CDB - g_lua.writeFunction("newCDBKVStore", [client](const std::string& fname, time_t refreshDelay) { + luaCtx.writeFunction("newCDBKVStore", [client](const std::string& fname, time_t refreshDelay) { if (client) { return std::shared_ptr(nullptr); } @@ -57,7 +57,7 @@ void setupLuaBindingsKVS(bool client) }); #endif /* HAVE_CDB */ - g_lua.registerFunction::*)(const boost::variant, boost::optional wireFormat)>("lookup", [](std::shared_ptr& kvs, const boost::variant keyVar, boost::optional wireFormat) { + luaCtx.registerFunction::*)(const boost::variant, boost::optional wireFormat)>("lookup", [](std::shared_ptr& kvs, const boost::variant keyVar, boost::optional wireFormat) { std::string result; if (!kvs) { return result; @@ -89,7 +89,7 @@ void setupLuaBindingsKVS(bool client) return result; }); - g_lua.registerFunction::*)(const DNSName&, boost::optional minLabels, boost::optional wireFormat)>("lookupSuffix", [](std::shared_ptr& kvs, const DNSName& dn, boost::optional minLabels, boost::optional wireFormat) { + luaCtx.registerFunction::*)(const DNSName&, boost::optional minLabels, boost::optional wireFormat)>("lookupSuffix", [](std::shared_ptr& kvs, const DNSName& dn, boost::optional minLabels, boost::optional wireFormat) { std::string result; if (!kvs) { return result; @@ -105,7 +105,7 @@ void setupLuaBindingsKVS(bool client) return result; }); - g_lua.registerFunction::*)()>("reload", [](std::shared_ptr& kvs) { + luaCtx.registerFunction::*)()>("reload", [](std::shared_ptr& kvs) { if (!kvs) { return false; } diff --git a/pdns/dnsdistdist/dnsdist-lua-bindings-packetcache.cc b/pdns/dnsdistdist/dnsdist-lua-bindings-packetcache.cc index b6d687a759..c3aed7465f 100644 --- a/pdns/dnsdistdist/dnsdist-lua-bindings-packetcache.cc +++ b/pdns/dnsdistdist/dnsdist-lua-bindings-packetcache.cc @@ -27,10 +27,10 @@ #include "dnsdist.hh" #include "dnsdist-lua.hh" -void setupLuaBindingsPacketCache() +void setupLuaBindingsPacketCache(LuaContext& luaCtx) { /* PacketCache */ - g_lua.writeFunction("newPacketCache", [](size_t maxEntries, boost::optional>> vars) { + luaCtx.writeFunction("newPacketCache", [](size_t maxEntries, boost::optional>> vars) { bool keepStaleData = false; size_t maxTTL = 86400; @@ -92,31 +92,31 @@ void setupLuaBindingsPacketCache() return res; }); - g_lua.registerFunction::*)()>("toString", [](const std::shared_ptr& cache) { + luaCtx.registerFunction::*)()>("toString", [](const std::shared_ptr& cache) { if (cache) { return cache->toString(); } return std::string(); }); - g_lua.registerFunction::*)()>("isFull", [](const std::shared_ptr& cache) { + luaCtx.registerFunction::*)()>("isFull", [](const std::shared_ptr& cache) { if (cache) { return cache->isFull(); } return false; }); - g_lua.registerFunction::*)(size_t)>("purgeExpired", [](std::shared_ptr& cache, size_t upTo) { + luaCtx.registerFunction::*)(size_t)>("purgeExpired", [](std::shared_ptr& cache, size_t upTo) { if (cache) { return cache->purgeExpired(upTo); } return static_cast(0); }); - g_lua.registerFunction::*)(size_t)>("expunge", [](std::shared_ptr& cache, size_t upTo) { + luaCtx.registerFunction::*)(size_t)>("expunge", [](std::shared_ptr& cache, size_t upTo) { if (cache) { return cache->expunge(upTo); } return static_cast(0); }); - g_lua.registerFunction::*)(const boost::variant& dname, boost::optional qtype, boost::optional suffixMatch)>("expungeByName", []( + luaCtx.registerFunction::*)(const boost::variant& dname, boost::optional qtype, boost::optional suffixMatch)>("expungeByName", []( std::shared_ptr& cache, const boost::variant& dname, boost::optional qtype, @@ -132,7 +132,7 @@ void setupLuaBindingsPacketCache() g_outputBuffer="Expunged " + std::to_string(cache->expungeByName(qname, qtype ? *qtype : QType(QType::ANY).getCode(), suffixMatch ? *suffixMatch : false)) + " records\n"; } }); - g_lua.registerFunction::*)()>("printStats", [](const std::shared_ptr& cache) { + luaCtx.registerFunction::*)()>("printStats", [](const std::shared_ptr& cache) { if (cache) { g_outputBuffer="Entries: " + std::to_string(cache->getEntriesCount()) + "/" + std::to_string(cache->getMaxEntries()) + "\n"; g_outputBuffer+="Hits: " + std::to_string(cache->getHits()) + "\n"; @@ -144,7 +144,7 @@ void setupLuaBindingsPacketCache() g_outputBuffer+="TTL Too Shorts: " + std::to_string(cache->getTTLTooShorts()) + "\n"; } }); - g_lua.registerFunction(std::shared_ptr::*)()>("getStats", [](const std::shared_ptr& cache) { + luaCtx.registerFunction(std::shared_ptr::*)()>("getStats", [](const std::shared_ptr& cache) { std::unordered_map stats; if (cache) { stats["entries"] = cache->getEntriesCount(); @@ -159,7 +159,7 @@ void setupLuaBindingsPacketCache() } return stats; }); - g_lua.registerFunction::*)(const std::string& fname)>("dump", [](const std::shared_ptr& cache, const std::string& fname) { + luaCtx.registerFunction::*)(const std::string& fname)>("dump", [](const std::shared_ptr& cache, const std::string& fname) { if (cache) { int fd = open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660); diff --git a/pdns/dnsdistdist/dnsdist-lua-bindings-protobuf.cc b/pdns/dnsdistdist/dnsdist-lua-bindings-protobuf.cc index 1f96d7168a..c8aade0aff 100644 --- a/pdns/dnsdistdist/dnsdist-lua-bindings-protobuf.cc +++ b/pdns/dnsdistdist/dnsdist-lua-bindings-protobuf.cc @@ -49,88 +49,88 @@ static void parseFSTRMOptions(const boost::optional("ipencrypt", [](const ComboAddress& ca, const std::string& key) { + luaCtx.registerFunction("ipencrypt", [](const ComboAddress& ca, const std::string& key) { return encryptCA(ca, key); }); - g_lua.registerFunction("ipdecrypt", [](const ComboAddress& ca, const std::string& key) { + luaCtx.registerFunction("ipdecrypt", [](const ComboAddress& ca, const std::string& key) { return decryptCA(ca, key); }); - g_lua.writeFunction("makeIPCipherKey", [](const std::string& password) { + luaCtx.writeFunction("makeIPCipherKey", [](const std::string& password) { return makeIPCipherKey(password); }); #endif /* HAVE_LIBCRYPTO */ /* ProtobufMessage */ - g_lua.registerFunction("setTag", [](DNSDistProtoBufMessage& message, const std::string& strValue) { + luaCtx.registerFunction("setTag", [](DNSDistProtoBufMessage& message, const std::string& strValue) { message.addTag(strValue); }); - g_lua.registerFunction>)>("setTagArray", [](DNSDistProtoBufMessage& message, const vector>&tags) { + luaCtx.registerFunction>)>("setTagArray", [](DNSDistProtoBufMessage& message, const vector>&tags) { for (const auto& tag : tags) { message.addTag(tag.second); } }); - g_lua.registerFunction sec, boost::optional uSec)>("setProtobufResponseType", + luaCtx.registerFunction sec, boost::optional uSec)>("setProtobufResponseType", [](DNSDistProtoBufMessage& message, boost::optional sec, boost::optional uSec) { message.setType(DNSProtoBufMessage::Response); message.setQueryTime(sec?*sec:0, uSec?*uSec:0); }); - g_lua.registerFunction("addResponseRR", [](DNSDistProtoBufMessage& message, + luaCtx.registerFunction("addResponseRR", [](DNSDistProtoBufMessage& message, const std::string& strQueryName, uint16_t uType, uint16_t uClass, uint32_t uTTL, const std::string& strBlob) { message.addRR(DNSName(strQueryName), uType, uClass, uTTL, strBlob); }); - g_lua.registerFunction("setEDNSSubnet", [](DNSDistProtoBufMessage& message, const Netmask& subnet) { message.setEDNSSubnet(subnet); }); - g_lua.registerFunction("setQuestion", [](DNSDistProtoBufMessage& message, const DNSName& qname, uint16_t qtype, uint16_t qclass) { message.setQuestion(qname, qtype, qclass); }); - g_lua.registerFunction("setBytes", [](DNSDistProtoBufMessage& message, size_t bytes) { message.setBytes(bytes); }); - g_lua.registerFunction("setTime", [](DNSDistProtoBufMessage& message, time_t sec, uint32_t usec) { message.setTime(sec, usec); }); - g_lua.registerFunction("setQueryTime", [](DNSDistProtoBufMessage& message, time_t sec, uint32_t usec) { message.setQueryTime(sec, usec); }); - g_lua.registerFunction("setResponseCode", [](DNSDistProtoBufMessage& message, uint8_t rcode) { message.setResponseCode(rcode); }); - g_lua.registerFunction("toDebugString", [](const DNSDistProtoBufMessage& message) { return message.toDebugString(); }); - g_lua.registerFunction)>("setRequestor", [](DNSDistProtoBufMessage& message, const ComboAddress& addr, boost::optional port) { + luaCtx.registerFunction("setEDNSSubnet", [](DNSDistProtoBufMessage& message, const Netmask& subnet) { message.setEDNSSubnet(subnet); }); + luaCtx.registerFunction("setQuestion", [](DNSDistProtoBufMessage& message, const DNSName& qname, uint16_t qtype, uint16_t qclass) { message.setQuestion(qname, qtype, qclass); }); + luaCtx.registerFunction("setBytes", [](DNSDistProtoBufMessage& message, size_t bytes) { message.setBytes(bytes); }); + luaCtx.registerFunction("setTime", [](DNSDistProtoBufMessage& message, time_t sec, uint32_t usec) { message.setTime(sec, usec); }); + luaCtx.registerFunction("setQueryTime", [](DNSDistProtoBufMessage& message, time_t sec, uint32_t usec) { message.setQueryTime(sec, usec); }); + luaCtx.registerFunction("setResponseCode", [](DNSDistProtoBufMessage& message, uint8_t rcode) { message.setResponseCode(rcode); }); + luaCtx.registerFunction("toDebugString", [](const DNSDistProtoBufMessage& message) { return message.toDebugString(); }); + luaCtx.registerFunction)>("setRequestor", [](DNSDistProtoBufMessage& message, const ComboAddress& addr, boost::optional port) { message.setRequestor(addr); if (port) { message.setRequestorPort(*port); } }); - g_lua.registerFunction)>("setRequestorFromString", [](DNSDistProtoBufMessage& message, const std::string& str, boost::optional port) { + luaCtx.registerFunction)>("setRequestorFromString", [](DNSDistProtoBufMessage& message, const std::string& str, boost::optional port) { message.setRequestor(str); if (port) { message.setRequestorPort(*port); } }); - g_lua.registerFunction)>("setResponder", [](DNSDistProtoBufMessage& message, const ComboAddress& addr, boost::optional port) { + luaCtx.registerFunction)>("setResponder", [](DNSDistProtoBufMessage& message, const ComboAddress& addr, boost::optional port) { message.setResponder(addr); if (port) { message.setResponderPort(*port); } }); - g_lua.registerFunction)>("setResponderFromString", [](DNSDistProtoBufMessage& message, const std::string& str, boost::optional port) { + luaCtx.registerFunction)>("setResponderFromString", [](DNSDistProtoBufMessage& message, const std::string& str, boost::optional port) { message.setResponder(str); if (port) { message.setResponderPort(*port); } }); - g_lua.registerFunction("setServerIdentity", [](DNSDistProtoBufMessage& message, const std::string& str) { + luaCtx.registerFunction("setServerIdentity", [](DNSDistProtoBufMessage& message, const std::string& str) { message.setServerIdentity(str); }); - g_lua.registerFunction("toDebugString", [](const DnstapMessage& message) { return message.toDebugString(); }); - g_lua.registerFunction("setExtra", [](DnstapMessage& message, const std::string& str) { + luaCtx.registerFunction("toDebugString", [](const DnstapMessage& message) { return message.toDebugString(); }); + luaCtx.registerFunction("setExtra", [](DnstapMessage& message, const std::string& str) { message.setExtra(str); }); /* RemoteLogger */ - g_lua.writeFunction("newRemoteLogger", [client,configCheck](const std::string& remote, boost::optional timeout, boost::optional maxQueuedEntries, boost::optional reconnectWaitTime) { + luaCtx.writeFunction("newRemoteLogger", [client,configCheck](const std::string& remote, boost::optional timeout, boost::optional maxQueuedEntries, boost::optional reconnectWaitTime) { if (client || configCheck) { return std::shared_ptr(nullptr); } return std::shared_ptr(new RemoteLogger(ComboAddress(remote), timeout ? *timeout : 2, maxQueuedEntries ? (*maxQueuedEntries*100) : 10000, reconnectWaitTime ? *reconnectWaitTime : 1, client)); }); - g_lua.writeFunction("newFrameStreamUnixLogger", [client,configCheck](const std::string& address, boost::optional> params) { + luaCtx.writeFunction("newFrameStreamUnixLogger", [client,configCheck](const std::string& address, boost::optional> params) { #ifdef HAVE_FSTRM if (client || configCheck) { return std::shared_ptr(nullptr); @@ -144,7 +144,7 @@ void setupLuaBindingsProtoBuf(bool client, bool configCheck) #endif /* HAVE_FSTRM */ }); - g_lua.writeFunction("newFrameStreamTcpLogger", [client,configCheck](const std::string& address, boost::optional> params) { + luaCtx.writeFunction("newFrameStreamTcpLogger", [client,configCheck](const std::string& address, boost::optional> params) { #if defined(HAVE_FSTRM) && defined(HAVE_FSTRM_TCP_WRITER_INIT) if (client || configCheck) { return std::shared_ptr(nullptr); @@ -158,7 +158,7 @@ void setupLuaBindingsProtoBuf(bool client, bool configCheck) #endif /* HAVE_FSTRM */ }); - g_lua.registerFunction::*)()>("toString", [](const std::shared_ptr& logger) { + luaCtx.registerFunction::*)()>("toString", [](const std::shared_ptr& logger) { if (logger) { return logger->toString(); } diff --git a/pdns/dnsdistdist/dnsdist-lua-ffi.cc b/pdns/dnsdistdist/dnsdist-lua-ffi.cc index a40a4ab196..1cc6cf2cbc 100644 --- a/pdns/dnsdistdist/dnsdist-lua-ffi.cc +++ b/pdns/dnsdistdist/dnsdist-lua-ffi.cc @@ -21,6 +21,7 @@ */ #include "dnsdist-lua-ffi.hh" +#include "dnsdist-lua.hh" #include "dnsdist-ecs.hh" uint16_t dnsdist_ffi_dnsquestion_get_qtype(const dnsdist_ffi_dnsquestion_t* dq) @@ -504,3 +505,15 @@ const std::string& getLuaFFIWrappers() )FFICodeContent"; return code; } + +void setupLuaLoadBalancingContext(LuaContext& luaCtx) +{ + setupLuaBindings(luaCtx, true); + setupLuaBindingsDNSQuestion(luaCtx); + setupLuaBindingsKVS(luaCtx, true); + setupLuaVars(luaCtx); + +#ifdef LUAJIT_VERSION + luaCtx.executeCode(getLuaFFIWrappers()); +#endif +} diff --git a/pdns/dnsdistdist/docs/advanced/tuning.rst b/pdns/dnsdistdist/docs/advanced/tuning.rst index 46f846c68c..d50becb7f7 100644 --- a/pdns/dnsdistdist/docs/advanced/tuning.rst +++ b/pdns/dnsdistdist/docs/advanced/tuning.rst @@ -31,7 +31,7 @@ Large installations are advised to increase the default value at the cost of a s Most of the query processing is done in C++ for maximum performance, but some operations are executed in Lua for maximum flexibility: * Rules added by :func:`addLuaAction` - * Server selection policies defined via :func:`setServerPolicyLua`, :func:`setServerPolicyLuaFFI` or :func:`newServerPolicy` + * Server selection policies defined via :func:`setServerPolicyLua`, :func:`setServerPolicyLuaFFI`, :func:`setServerPolicyLuaFFIPerThread` or :func:`newServerPolicy` While Lua is fast, its use should be restricted to the strict necessary in order to achieve maximum performance, it might be worth considering using LuaJIT instead of Lua. When Lua inspection is needed, the best course of action is to restrict the queries sent to Lua inspection by using :func:`addLuaAction` with a selector. diff --git a/pdns/dnsdistdist/docs/guides/serverselection.rst b/pdns/dnsdistdist/docs/guides/serverselection.rst index 7e8ad323c2..66aa68ac03 100644 --- a/pdns/dnsdistdist/docs/guides/serverselection.rst +++ b/pdns/dnsdistdist/docs/guides/serverselection.rst @@ -112,6 +112,24 @@ Or:: setServerPolicyLua("splitsetup", splitSetup) +For performance reasons, 1.6.0 introduced per-thread Lua FFI policies that are run in a lock-free per-thread Lua context instead of the global one. +This reduces contention between threads at the cost of preventing sharing data between threads for these policies. Since the policy needs to be recompiled +in the context of each thread instead of the global one, Lua code that returns a function should be passed to the function as a string instead of directly +passing the name of a function: + +.. code-block:: lua + + setServerPolicyLuaFFIPerThread("luaffiroundrobin", [[ + local ffi = require("ffi") + local C = ffi.C + + local counter = 0 + return function(servers_list, dq) + counter = counter + 1 + return (counter % tonumber(C.dnsdist_ffi_servers_list_get_count(servers_list))) + end + ]]) + ServerPolicy Objects -------------------- @@ -143,6 +161,12 @@ ServerPolicy Objects Whether this policy is a native (C++) policy or a Lua-based one. + .. attribute:: ServerPolicy.isPerThread + + .. versionadded: 1.6.0 + + Whether a FFI Lua-based policy is executed in a lock-free per-thread context instead of running in the global Lua context. + .. attribute:: ServerPolicy.name The name of the policy. @@ -197,6 +221,16 @@ Functions :param string name: name for this policy :param string function: name of the FFI function +.. function:: setServerPolicyLuaFFIPerThread(name, code) + + .. versionadded:: 1.6.0 + + Set server selection policy to one named ``name`` and the Lua FFI function returned by the Lua code passed in ``code``. + The resulting policy will be executed in a lock-free per-thread context, instead of running in the global Lua context. + + :param string name: name for this policy + :param string code: Lua FFI code returning the function to execute as a server selection policy + .. function:: setServFailWhenNoServer(value) If set, return a ServFail when no servers are available, instead of the default behaviour of dropping the query. diff --git a/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc b/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc index 6c85b6243b..4e21675def 100644 --- a/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc +++ b/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc @@ -27,6 +27,9 @@ GlobalStateHolder> g_dynblockNMG; GlobalStateHolder> g_dynblockSMT; #endif /* BENCH_POLICIES */ +GlobalStateHolder g_pools; +std::vector> g_frontends; + /* add stub implementations, we don't want to include the corresponding object files and their dependencies */ @@ -76,6 +79,12 @@ bool DNSDistSNMPAgent::sendDNSTrap(const DNSQuestion& dq, const std::string& rea return false; } +void setLuaNoSideEffect() +{ +} + +string g_outputBuffer; + static DNSQuestion getDQ(const DNSName* providedName = nullptr) { static const DNSName qname("powerdns.com."); @@ -122,7 +131,7 @@ static void benchPolicy(const ServerPolicy& pol) for (size_t idx = 0; idx < 1000; idx++) { for (const auto& name : names) { auto dq = getDQ(&name); - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); } } cerr<(ComboAddress("192.0.2.1:53")) }); /* servers start as 'down' */ - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); BOOST_CHECK(server == nullptr); /* mark the server as 'up' */ servers.at(0).second->setUp(); - server = getSelectedBackendFromPolicy(pol, servers, dq); + server = pol.getSelectedBackend(servers, dq); BOOST_CHECK(server != nullptr); /* add a second server, we should still get the first one */ servers.push_back({ 2, std::make_shared(ComboAddress("192.0.2.2:53")) }); - server = getSelectedBackendFromPolicy(pol, servers, dq); + server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(server != nullptr); BOOST_CHECK(server == servers.at(0).second); /* mark the first server as 'down', second as 'up' */ servers.at(0).second->setDown(); servers.at(1).second->setUp(); - server = getSelectedBackendFromPolicy(pol, servers, dq); + server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(server != nullptr); BOOST_CHECK(server == servers.at(1).second); @@ -181,38 +190,38 @@ BOOST_AUTO_TEST_CASE(test_roundRobin) { /* selecting a server on an empty server list */ g_roundrobinFailOnNoServer = false; - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); BOOST_CHECK(server == nullptr); servers.push_back({ 1, std::make_shared(ComboAddress("192.0.2.1:53")) }); /* servers start as 'down' but the RR policy returns a server unless g_roundrobinFailOnNoServer is set */ g_roundrobinFailOnNoServer = true; - server = getSelectedBackendFromPolicy(pol, servers, dq); + server = pol.getSelectedBackend(servers, dq); BOOST_CHECK(server == nullptr); g_roundrobinFailOnNoServer = false; - server = getSelectedBackendFromPolicy(pol, servers, dq); + server = pol.getSelectedBackend(servers, dq); BOOST_CHECK(server != nullptr); /* mark the server as 'up' */ servers.at(0).second->setUp(); - server = getSelectedBackendFromPolicy(pol, servers, dq); + server = pol.getSelectedBackend(servers, dq); BOOST_CHECK(server != nullptr); /* add a second server, we should get the first one then the second one */ servers.push_back({ 2, std::make_shared(ComboAddress("192.0.2.2:53")) }); servers.at(1).second->setUp(); - server = getSelectedBackendFromPolicy(pol, servers, dq); + server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(server != nullptr); BOOST_CHECK(server == servers.at(0).second); - server = getSelectedBackendFromPolicy(pol, servers, dq); + server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(server != nullptr); BOOST_CHECK(server == servers.at(1).second); /* mark the first server as 'down', second as 'up' */ servers.at(0).second->setDown(); servers.at(1).second->setUp(); - server = getSelectedBackendFromPolicy(pol, servers, dq); + server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(server != nullptr); BOOST_CHECK(server == servers.at(1).second); @@ -224,7 +233,7 @@ BOOST_AUTO_TEST_CASE(test_roundRobin) { } for (size_t idx = 0; idx < 1000; idx++) { - server = getSelectedBackendFromPolicy(pol, servers, dq); + server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(serversMap.count(server) == 1); ++serversMap[server]; } @@ -246,24 +255,24 @@ BOOST_AUTO_TEST_CASE(test_leastOutstanding) { servers.push_back({ 1, std::make_shared(ComboAddress("192.0.2.1:53")) }); /* servers start as 'down' */ - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); BOOST_CHECK(server == nullptr); /* mark the server as 'up' */ servers.at(0).second->setUp(); - server = getSelectedBackendFromPolicy(pol, servers, dq); + server = pol.getSelectedBackend(servers, dq); BOOST_CHECK(server != nullptr); /* add a second server, we should still get the first one */ servers.push_back({ 2, std::make_shared(ComboAddress("192.0.2.2:53")) }); - server = getSelectedBackendFromPolicy(pol, servers, dq); + server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(server != nullptr); BOOST_CHECK(server == servers.at(0).second); /* mark the first server as 'down', second as 'up' */ servers.at(0).second->setDown(); servers.at(1).second->setUp(); - server = getSelectedBackendFromPolicy(pol, servers, dq); + server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(server != nullptr); BOOST_CHECK(server == servers.at(1).second); @@ -271,7 +280,7 @@ BOOST_AUTO_TEST_CASE(test_leastOutstanding) { servers.at(0).second->setUp(); servers.at(0).second->outstanding = 42; servers.at(1).second->setUp(); - server = getSelectedBackendFromPolicy(pol, servers, dq); + server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(server != nullptr); BOOST_CHECK(server == servers.at(1).second); @@ -293,7 +302,7 @@ BOOST_AUTO_TEST_CASE(test_wrandom) { benchPolicy(pol); for (size_t idx = 0; idx < 1000; idx++) { - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(serversMap.count(server) == 1); ++serversMap[server]; } @@ -321,7 +330,7 @@ BOOST_AUTO_TEST_CASE(test_wrandom) { servers.at(servers.size()-1).second->weight = 100; for (size_t idx = 0; idx < 1000; idx++) { - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(serversMap.count(server) == 1); ++serversMap[server]; } @@ -360,7 +369,7 @@ BOOST_AUTO_TEST_CASE(test_whashed) { for (const auto& name : names) { auto dq = getDQ(&name); - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(serversMap.count(server) == 1); ++serversMap[server]; } @@ -383,9 +392,9 @@ BOOST_AUTO_TEST_CASE(test_whashed) { /* request 1000 times the same name, we should go to the same server every time */ { auto dq = getDQ(&names.at(0)); - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); for (size_t idx = 0; idx < 1000; idx++) { - BOOST_CHECK(getSelectedBackendFromPolicy(pol, servers, dq) == server); + BOOST_CHECK(pol.getSelectedBackend(servers, dq) == server); } } @@ -399,7 +408,7 @@ BOOST_AUTO_TEST_CASE(test_whashed) { for (const auto& name : names) { auto dq = getDQ(&name); - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(serversMap.count(server) == 1); ++serversMap[server]; } @@ -445,7 +454,7 @@ BOOST_AUTO_TEST_CASE(test_chashed) { for (const auto& name : names) { auto dq = getDQ(&name); - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(serversMap.count(server) == 1); ++serversMap[server]; } @@ -468,9 +477,9 @@ BOOST_AUTO_TEST_CASE(test_chashed) { /* request 1000 times the same name, we should go to the same server every time */ { auto dq = getDQ(&names.at(0)); - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); for (size_t idx = 0; idx < 1000; idx++) { - BOOST_CHECK(getSelectedBackendFromPolicy(pol, servers, dq) == server); + BOOST_CHECK(pol.getSelectedBackend(servers, dq) == server); } } @@ -484,7 +493,7 @@ BOOST_AUTO_TEST_CASE(test_chashed) { for (const auto& name : names) { auto dq = getDQ(&name); - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(serversMap.count(server) == 1); ++serversMap[server]; } @@ -540,7 +549,7 @@ BOOST_AUTO_TEST_CASE(test_lua) { for (const auto& name : names) { auto dq = getDQ(&name); - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(serversMap.count(server) == 1); ++serversMap[server]; } @@ -600,7 +609,7 @@ BOOST_AUTO_TEST_CASE(test_lua_ffi_rr) { for (const auto& name : names) { auto dq = getDQ(&name); - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(serversMap.count(server) == 1); ++serversMap[server]; } @@ -657,7 +666,7 @@ BOOST_AUTO_TEST_CASE(test_lua_ffi_hashed) { for (const auto& name : names) { auto dq = getDQ(&name); - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(serversMap.count(server) == 1); ++serversMap[server]; } @@ -712,7 +721,7 @@ BOOST_AUTO_TEST_CASE(test_lua_ffi_whashed) { for (const auto& name : names) { auto dq = getDQ(&name); - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(serversMap.count(server) == 1); ++serversMap[server]; } @@ -774,7 +783,7 @@ BOOST_AUTO_TEST_CASE(test_lua_ffi_chashed) { for (const auto& name : names) { auto dq = getDQ(&name); - auto server = getSelectedBackendFromPolicy(pol, servers, dq); + auto server = pol.getSelectedBackend(servers, dq); BOOST_REQUIRE(serversMap.count(server) == 1); ++serversMap[server]; } diff --git a/regression-tests.dnsdist/test_Routing.py b/regression-tests.dnsdist/test_Routing.py index 70deba8f3c..8aabad85fa 100644 --- a/regression-tests.dnsdist/test_Routing.py +++ b/regression-tests.dnsdist/test_Routing.py @@ -253,6 +253,82 @@ class TestRoutingRoundRobinLBAllDown(DNSDistTest): (_, receivedResponse) = sender(query, response=None, useQueue=False) self.assertEquals(receivedResponse, None) +class TestRoutingLuaFFIPerThreadRoundRobinLB(DNSDistTest): + + _testServer2Port = 5351 + _config_params = ['_testServerPort', '_testServer2Port'] + _config_template = """ + setServerPolicyLuaFFIPerThread("luaffiroundrobin", [[ + local ffi = require("ffi") + local C = ffi.C + + local counter = 0 + return function(servers_list, dq) + counter = counter + 1 + return (counter %% tonumber(C.dnsdist_ffi_servers_list_get_count(servers_list))) + end + ]]) + + s1 = newServer{address="127.0.0.1:%s"} + s1:setUp() + s2 = newServer{address="127.0.0.1:%s"} + s2:setUp() + """ + + @classmethod + def startResponders(cls): + print("Launching responders..") + cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue]) + cls._UDPResponder.setDaemon(True) + cls._UDPResponder.start() + cls._UDPResponder2 = threading.Thread(name='UDP Responder 2', target=cls.UDPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue]) + cls._UDPResponder2.setDaemon(True) + cls._UDPResponder2.start() + + cls._TCPResponder = threading.Thread(name='TCP Responder', target=cls.TCPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue]) + cls._TCPResponder.setDaemon(True) + cls._TCPResponder.start() + + cls._TCPResponder2 = threading.Thread(name='TCP Responder 2', target=cls.TCPResponder, args=[cls._testServer2Port, cls._toResponderQueue, cls._fromResponderQueue]) + cls._TCPResponder2.setDaemon(True) + cls._TCPResponder2.start() + + def testRR(self): + """ + Routing: Round Robin + + Send 10 A queries to "rr.routing.tests.powerdns.com.", + check that dnsdist routes half of it to each backend. + """ + numberOfQueries = 10 + name = 'rr.routing.tests.powerdns.com.' + query = dns.message.make_query(name, 'A', 'IN') + response = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 60, + dns.rdataclass.IN, + dns.rdatatype.A, + '192.0.2.1') + response.answer.append(rrset) + + # the round robin counter is shared for UDP and TCP, + # so we need to do UDP then TCP to have a clean count + for _ in range(numberOfQueries): + (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) + receivedQuery.id = query.id + self.assertEquals(query, receivedQuery) + self.assertEquals(response, receivedResponse) + + for _ in range(numberOfQueries): + (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) + receivedQuery.id = query.id + self.assertEquals(query, receivedQuery) + self.assertEquals(response, receivedResponse) + + for key in self._responsesCounter: + value = self._responsesCounter[key] + self.assertEquals(value, numberOfQueries / 2) + class TestRoutingOrder(DNSDistTest): _testServer2Port = 5351