diff options
Diffstat (limited to '')
-rw-r--r-- | dnsdist-lua-bindings.cc | 206 |
1 files changed, 139 insertions, 67 deletions
diff --git a/dnsdist-lua-bindings.cc b/dnsdist-lua-bindings.cc index ef5f29f..3f5d6e2 100644 --- a/dnsdist-lua-bindings.cc +++ b/dnsdist-lua-bindings.cc @@ -22,12 +22,17 @@ #include "bpf-filter.hh" #include "config.h" #include "dnsdist.hh" +#include "dnsdist-async.hh" #include "dnsdist-lua.hh" +#include "dnsdist-resolver.hh" #include "dnsdist-svc.hh" +#include "dnsdist-xsk.hh" #include "dolog.hh" +#include "xsk.hh" -void setupLuaBindings(LuaContext& luaCtx, bool client) +// NOLINTNEXTLINE(readability-function-cognitive-complexity): this function declares Lua bindings, even with a good refactoring it will likely blow up the threshold +void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) { luaCtx.writeFunction("vinfolog", [](const string& arg) { vinfolog("%s", arg); @@ -47,7 +52,7 @@ void setupLuaBindings(LuaContext& luaCtx, bool client) }); /* Exceptions */ - luaCtx.registerFunction<string(std::exception_ptr::*)()const>("__tostring", [](const std::exception_ptr& eptr) { + luaCtx.registerFunction<string(std::exception_ptr::*)()const>("__tostring", [](const std::exception_ptr& eptr) -> std::string { try { if (eptr) { std::rethrow_exception(eptr); @@ -73,16 +78,16 @@ void setupLuaBindings(LuaContext& luaCtx, bool client) luaCtx.registerFunction("toString", &ServerPolicy::toString); luaCtx.registerFunction("__tostring", &ServerPolicy::toString); - ServerPolicy policies[] = { - ServerPolicy{"firstAvailable", firstAvailable, false}, - ServerPolicy{"roundrobin", roundrobin, false}, - ServerPolicy{"wrandom", wrandom, false}, - ServerPolicy{"whashed", whashed, false}, - ServerPolicy{"chashed", chashed, false}, - ServerPolicy{"leastOutstanding", leastOutstanding, false} + const std::array<std::shared_ptr<ServerPolicy>, 6> policies = { + std::make_shared<ServerPolicy>("firstAvailable", firstAvailable, false), + std::make_shared<ServerPolicy>("roundrobin", roundrobin, false), + std::make_shared<ServerPolicy>("wrandom", wrandom, false), + std::make_shared<ServerPolicy>("whashed", whashed, false), + std::make_shared<ServerPolicy>("chashed", chashed, false), + std::make_shared<ServerPolicy>("leastOutstanding", leastOutstanding, false) }; - for (auto& policy : policies) { - luaCtx.writeVariable(policy.d_name, policy); + for (const auto& policy : policies) { + luaCtx.writeVariable(policy->d_name, policy); } #endif /* DISABLE_POLICIES_BINDINGS */ @@ -90,7 +95,7 @@ void setupLuaBindings(LuaContext& luaCtx, bool client) /* ServerPool */ luaCtx.registerFunction<void(std::shared_ptr<ServerPool>::*)(std::shared_ptr<DNSDistPacketCache>)>("setCache", [](std::shared_ptr<ServerPool> pool, std::shared_ptr<DNSDistPacketCache> cache) { if (pool) { - pool->packetCache = cache; + pool->packetCache = std::move(cache); } }); luaCtx.registerFunction("getCache", &ServerPool::getCache); @@ -104,50 +109,50 @@ void setupLuaBindings(LuaContext& luaCtx, bool client) #ifndef DISABLE_DOWNSTREAM_BINDINGS /* DownstreamState */ - luaCtx.registerFunction<void(DownstreamState::*)(int)>("setQPS", [](DownstreamState& s, int lim) { s.qps = lim ? QPSLimiter(lim, lim) : QPSLimiter(); }); - luaCtx.registerFunction<void(std::shared_ptr<DownstreamState>::*)(string)>("addPool", [](std::shared_ptr<DownstreamState> s, string pool) { + luaCtx.registerFunction<void(DownstreamState::*)(int)>("setQPS", [](DownstreamState& state, int lim) { state.qps = lim > 0 ? QPSLimiter(lim, lim) : QPSLimiter(); }); + luaCtx.registerFunction<void(std::shared_ptr<DownstreamState>::*)(string)>("addPool", [](const std::shared_ptr<DownstreamState>& state, const string& pool) { auto localPools = g_pools.getCopy(); - addServerToPool(localPools, pool, s); + addServerToPool(localPools, pool, state); g_pools.setState(localPools); - s->d_config.pools.insert(pool); + state->d_config.pools.insert(pool); }); - luaCtx.registerFunction<void(std::shared_ptr<DownstreamState>::*)(string)>("rmPool", [](std::shared_ptr<DownstreamState> s, string pool) { + luaCtx.registerFunction<void(std::shared_ptr<DownstreamState>::*)(string)>("rmPool", [](const std::shared_ptr<DownstreamState>& state, const string& pool) { auto localPools = g_pools.getCopy(); - removeServerFromPool(localPools, pool, s); + removeServerFromPool(localPools, pool, state); g_pools.setState(localPools); - s->d_config.pools.erase(pool); + state->d_config.pools.erase(pool); }); - luaCtx.registerFunction<uint64_t(DownstreamState::*)()const>("getOutstanding", [](const DownstreamState& s) { return s.outstanding.load(); }); - luaCtx.registerFunction<uint64_t(DownstreamState::*)()const>("getDrops", [](const DownstreamState& s) { return s.reuseds.load(); }); - luaCtx.registerFunction<double(DownstreamState::*)()const>("getLatency", [](const DownstreamState& s) { return s.getRelevantLatencyUsec(); }); + luaCtx.registerFunction<uint64_t(DownstreamState::*)()const>("getOutstanding", [](const DownstreamState& state) { return state.outstanding.load(); }); + luaCtx.registerFunction<uint64_t(DownstreamState::*)()const>("getDrops", [](const DownstreamState& state) { return state.reuseds.load(); }); + luaCtx.registerFunction<double(DownstreamState::*)()const>("getLatency", [](const DownstreamState& state) { return state.getRelevantLatencyUsec(); }); luaCtx.registerFunction("isUp", &DownstreamState::isUp); luaCtx.registerFunction("setDown", &DownstreamState::setDown); luaCtx.registerFunction("setUp", &DownstreamState::setUp); - luaCtx.registerFunction<void(DownstreamState::*)(boost::optional<bool> newStatus)>("setAuto", [](DownstreamState& s, boost::optional<bool> newStatus) { + luaCtx.registerFunction<void(DownstreamState::*)(boost::optional<bool> newStatus)>("setAuto", [](DownstreamState& state, boost::optional<bool> newStatus) { if (newStatus) { - s.setUpStatus(*newStatus); + state.setUpStatus(*newStatus); } - s.setAuto(); + state.setAuto(); }); - luaCtx.registerFunction<void(DownstreamState::*)(boost::optional<bool> newStatus)>("setLazyAuto", [](DownstreamState& s, boost::optional<bool> newStatus) { + luaCtx.registerFunction<void(DownstreamState::*)(boost::optional<bool> newStatus)>("setLazyAuto", [](DownstreamState& state, boost::optional<bool> newStatus) { if (newStatus) { - s.setUpStatus(*newStatus); + state.setUpStatus(*newStatus); } - s.setLazyAuto(); + state.setLazyAuto(); }); - luaCtx.registerFunction<std::string(DownstreamState::*)()const>("getName", [](const DownstreamState& s) { return s.getName(); }); - luaCtx.registerFunction<std::string(DownstreamState::*)()const>("getNameWithAddr", [](const DownstreamState& s) { return s.getNameWithAddr(); }); + luaCtx.registerFunction<std::string(DownstreamState::*)()const>("getName", [](const DownstreamState& state) -> const std::string& { return state.getName(); }); + luaCtx.registerFunction<std::string(DownstreamState::*)()const>("getNameWithAddr", [](const DownstreamState& state) -> const std::string& { return state.getNameWithAddr(); }); luaCtx.registerMember("upStatus", &DownstreamState::upStatus); luaCtx.registerMember<int (DownstreamState::*)>("weight", - [](const DownstreamState& s) -> int {return s.d_config.d_weight;}, - [](DownstreamState& s, int newWeight) { s.setWeight(newWeight); } + [](const DownstreamState& state) -> int {return state.d_config.d_weight;}, + [](DownstreamState& state, int newWeight) { state.setWeight(newWeight); } ); luaCtx.registerMember<int (DownstreamState::*)>("order", - [](const DownstreamState& s) -> int {return s.d_config.order; }, - [](DownstreamState& s, int newOrder) { s.d_config.order = newOrder; } + [](const DownstreamState& state) -> int {return state.d_config.order; }, + [](DownstreamState& state, int newOrder) { state.d_config.order = newOrder; } ); luaCtx.registerMember<const std::string(DownstreamState::*)>("name", [](const DownstreamState& backend) -> const std::string { return backend.getName(); }, [](DownstreamState& backend, const std::string& newName) { backend.setName(newName); }); - luaCtx.registerFunction<std::string(DownstreamState::*)()const>("getID", [](const DownstreamState& s) { return boost::uuids::to_string(*s.d_config.id); }); + luaCtx.registerFunction<std::string(DownstreamState::*)()const>("getID", [](const DownstreamState& state) { return boost::uuids::to_string(*state.d_config.id); }); #endif /* DISABLE_DOWNSTREAM_BINDINGS */ #ifndef DISABLE_DNSHEADER_BINDINGS @@ -283,54 +288,54 @@ void setupLuaBindings(LuaContext& luaCtx, bool client) /* SuffixMatchNode */ luaCtx.registerFunction<void (SuffixMatchNode::*)(const boost::variant<DNSName, std::string, LuaArray<DNSName>, LuaArray<std::string>> &name)>("add", [](SuffixMatchNode &smn, const boost::variant<DNSName, std::string, LuaArray<DNSName>, LuaArray<std::string>> &name) { if (name.type() == typeid(DNSName)) { - auto n = boost::get<DNSName>(name); - smn.add(n); + const auto& actualName = boost::get<DNSName>(name); + smn.add(actualName); return; } if (name.type() == typeid(std::string)) { - auto n = boost::get<std::string>(name); - smn.add(n); + const auto& actualName = boost::get<std::string>(name); + smn.add(actualName); return; } if (name.type() == typeid(LuaArray<DNSName>)) { - auto names = boost::get<LuaArray<DNSName>>(name); - for (const auto& n : names) { - smn.add(n.second); + const auto& names = boost::get<LuaArray<DNSName>>(name); + for (const auto& actualName : names) { + smn.add(actualName.second); } return; } if (name.type() == typeid(LuaArray<std::string>)) { - auto names = boost::get<LuaArray<string>>(name); - for (const auto& n : names) { - smn.add(n.second); + const auto& names = boost::get<LuaArray<string>>(name); + for (const auto& actualName : names) { + smn.add(actualName.second); } return; } }); luaCtx.registerFunction<void (SuffixMatchNode::*)(const boost::variant<DNSName, string, LuaArray<DNSName>, LuaArray<std::string>> &name)>("remove", [](SuffixMatchNode &smn, const boost::variant<DNSName, string, LuaArray<DNSName>, LuaArray<std::string>> &name) { if (name.type() == typeid(DNSName)) { - auto n = boost::get<DNSName>(name); - smn.remove(n); + const auto& actualName = boost::get<DNSName>(name); + smn.remove(actualName); return; } if (name.type() == typeid(string)) { - auto n = boost::get<string>(name); - DNSName d(n); - smn.remove(d); + const auto& actualName = boost::get<string>(name); + DNSName dnsName(actualName); + smn.remove(dnsName); return; } if (name.type() == typeid(LuaArray<DNSName>)) { - auto names = boost::get<LuaArray<DNSName>>(name); - for (const auto& n : names) { - smn.remove(n.second); + const auto& names = boost::get<LuaArray<DNSName>>(name); + for (const auto& actualName : names) { + smn.remove(actualName.second); } return; } if (name.type() == typeid(LuaArray<std::string>)) { - auto names = boost::get<LuaArray<std::string>>(name); - for (const auto& n : names) { - DNSName d(n.second); - smn.remove(d); + const auto& names = boost::get<LuaArray<std::string>>(name); + for (const auto& actualName : names) { + DNSName dnsName(actualName.second); + smn.remove(dnsName); } return; } @@ -349,16 +354,16 @@ void setupLuaBindings(LuaContext& luaCtx, bool client) #ifndef DISABLE_NETMASK_BINDINGS /* Netmask */ - luaCtx.writeFunction("newNetmask", [](boost::variant<std::string,ComboAddress> s, boost::optional<uint8_t> bits) { - if (s.type() == typeid(ComboAddress)) { - auto ca = boost::get<ComboAddress>(s); + luaCtx.writeFunction("newNetmask", [](boost::variant<std::string,ComboAddress> addrOrStr, boost::optional<uint8_t> bits) { + if (addrOrStr.type() == typeid(ComboAddress)) { + const auto& comboAddr = boost::get<ComboAddress>(addrOrStr); if (bits) { - return Netmask(ca, *bits); + return Netmask(comboAddr, *bits); } - return Netmask(ca); + return Netmask(comboAddr); } - else if (s.type() == typeid(std::string)) { - auto str = boost::get<std::string>(s); + if (addrOrStr.type() == typeid(std::string)) { + const auto& str = boost::get<std::string>(addrOrStr); return Netmask(str); } throw std::runtime_error("Invalid parameter passed to 'newNetmask()'"); @@ -379,10 +384,17 @@ void setupLuaBindings(LuaContext& luaCtx, bool client) /* NetmaskGroup */ luaCtx.writeFunction("newNMG", []() { return NetmaskGroup(); }); - luaCtx.registerFunction<void(NetmaskGroup::*)(const std::string&mask)>("addMask", [](NetmaskGroup&nmg, const std::string& mask) + luaCtx.registerFunction<void(NetmaskGroup::*)(const std::string& mask)>("addMask", [](NetmaskGroup& nmg, const std::string& mask) { nmg.addMask(mask); }); + luaCtx.registerFunction<void(NetmaskGroup::*)(const NetmaskGroup& otherNMG)>("addNMG", [](NetmaskGroup& nmg, const NetmaskGroup& otherNMG) { + /* this is not going to be very efficient, sorry */ + auto entries = otherNMG.toStringVector(); + for (const auto& entry : entries) { + nmg.addMask(entry); + } + }); luaCtx.registerFunction<void(NetmaskGroup::*)(const std::map<ComboAddress,int>& map)>("addMasks", [](NetmaskGroup&nmg, const std::map<ComboAddress,int>& map) { for (const auto& entry : map) { @@ -479,7 +491,7 @@ void setupLuaBindings(LuaContext& luaCtx, bool client) auto& params = boost::get<string>(tmp); config.d_pinnedPath = std::move(params); } - mapsConfig[name] = config; + mapsConfig[name] = std::move(config); }; convertParamsToConfig("ipv4", BPFFilter::MapType::IPv4); @@ -705,7 +717,48 @@ void setupLuaBindings(LuaContext& luaCtx, bool client) } }); #endif /* HAVE_EBPF */ - +#ifdef HAVE_XSK + using xskopt_t = LuaAssociativeTable<boost::variant<uint32_t, std::string>>; + luaCtx.writeFunction("newXsk", [client](xskopt_t opts) { + if (g_configurationDone) { + throw std::runtime_error("newXsk() only can be used at configuration time!"); + } + if (client) { + return std::shared_ptr<XskSocket>(nullptr); + } + uint32_t queue_id; + uint32_t frameNums{65536}; + std::string ifName; + std::string path("/sys/fs/bpf/dnsdist/xskmap"); + if (opts.count("ifName") == 1) { + ifName = boost::get<std::string>(opts.at("ifName")); + } + else { + throw std::runtime_error("ifName field is required!"); + } + if (opts.count("NIC_queue_id") == 1) { + queue_id = boost::get<uint32_t>(opts.at("NIC_queue_id")); + } + else { + throw std::runtime_error("NIC_queue_id field is required!"); + } + if (opts.count("frameNums") == 1) { + frameNums = boost::get<uint32_t>(opts.at("frameNums")); + } + if (opts.count("xskMapPath") == 1) { + path = boost::get<std::string>(opts.at("xskMapPath")); + } + auto socket = std::make_shared<XskSocket>(frameNums, ifName, queue_id, path); + dnsdist::xsk::g_xsk.push_back(socket); + return socket; + }); + luaCtx.registerFunction<std::string(std::shared_ptr<XskSocket>::*)()const>("getMetrics", [](const std::shared_ptr<XskSocket>& xsk) -> std::string { + if (!xsk) { + return {}; + } + return xsk->getMetrics(); + }); +#endif /* HAVE_XSK */ /* EDNSOptionView */ luaCtx.registerFunction<size_t(EDNSOptionView::*)()const>("count", [](const EDNSOptionView& option) { return option.values.size(); @@ -784,4 +837,23 @@ void setupLuaBindings(LuaContext& luaCtx, bool client) } return now; }); + + luaCtx.writeFunction("getAddressInfo", [client, configCheck](std::string hostname, std::function<void(const std::string& hostname, const LuaArray<ComboAddress>& ips)> callback) { + if (client || configCheck) { + return; + } + std::thread newThread(dnsdist::resolver::asynchronousResolver, std::move(hostname), [callback=std::move(callback)](const std::string& resolvedHostname, std::vector<ComboAddress>& ips) { + LuaArray<ComboAddress> result; + result.reserve(ips.size()); + for (const auto& entry : ips) { + result.emplace_back(result.size() + 1, entry); + } + { + auto lua = g_lua.lock(); + callback(resolvedHostname, result); + dnsdist::handleQueuedAsynchronousEvents(); + } + }); + newThread.detach(); + }); } |