summaryrefslogtreecommitdiffstats
path: root/dnsdist-lua-bindings.cc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dnsdist-lua-bindings.cc206
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();
+ });
}