From b1bea54a70d751e1c7c020dcf7c58b2bc45f8353 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Thu, 22 Sep 2022 17:41:07 +0200 Subject: [PATCH] dnsdist: Add Lua bindings for the ring entries --- pdns/dnsdist-lua.cc | 1 + pdns/dnsdist-lua.hh | 1 + pdns/dnsdistdist/Makefile.am | 1 + .../dnsdistdist/dnsdist-lua-bindings-rings.cc | 141 ++++++++++++++++++ pdns/dnsdistdist/docs/reference/config.rst | 76 ++++++++++ 5 files changed, 220 insertions(+) create mode 100644 pdns/dnsdistdist/dnsdist-lua-bindings-rings.cc diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index dfd4b4d4b0..e3ad014020 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -3021,6 +3021,7 @@ vector> setupLua(LuaContext& luaCtx, bool client, bool setupLuaBindingsKVS(luaCtx, client); setupLuaBindingsPacketCache(luaCtx, client); setupLuaBindingsProtoBuf(luaCtx, client, configCheck); + setupLuaBindingsRings(luaCtx, client); setupLuaInspection(luaCtx); setupLuaRules(luaCtx); setupLuaVars(luaCtx); diff --git a/pdns/dnsdist-lua.hh b/pdns/dnsdist-lua.hh index cf22e9163a..6f71e9816c 100644 --- a/pdns/dnsdist-lua.hh +++ b/pdns/dnsdist-lua.hh @@ -149,6 +149,7 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx); void setupLuaBindingsKVS(LuaContext& luaCtx, bool client); void setupLuaBindingsPacketCache(LuaContext& luaCtx, bool client); void setupLuaBindingsProtoBuf(LuaContext& luaCtx, bool client, bool configCheck); +void setupLuaBindingsRings(LuaContext& luaCtx, bool client); void setupLuaRules(LuaContext& luaCtx); void setupLuaInspection(LuaContext& luaCtx); void setupLuaVars(LuaContext& luaCtx); diff --git a/pdns/dnsdistdist/Makefile.am b/pdns/dnsdistdist/Makefile.am index 68fc61d9a5..bdd92416c2 100644 --- a/pdns/dnsdistdist/Makefile.am +++ b/pdns/dnsdistdist/Makefile.am @@ -154,6 +154,7 @@ dnsdist_SOURCES = \ dnsdist-lua-bindings-kvs.cc \ dnsdist-lua-bindings-packetcache.cc \ dnsdist-lua-bindings-protobuf.cc \ + dnsdist-lua-bindings-rings.cc \ dnsdist-lua-bindings.cc \ dnsdist-lua-ffi-interface.h dnsdist-lua-ffi-interface.inc \ dnsdist-lua-ffi.cc dnsdist-lua-ffi.hh \ diff --git a/pdns/dnsdistdist/dnsdist-lua-bindings-rings.cc b/pdns/dnsdistdist/dnsdist-lua-bindings-rings.cc new file mode 100644 index 0000000000..4bf83a51bc --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-lua-bindings-rings.cc @@ -0,0 +1,141 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "dnsdist.hh" +#include "dnsdist-rings.hh" +#include "dnsdist-lua.hh" + +#ifndef DISABLE_LUA_BINDINGS_RINGS +struct LuaRingEntry +{ + DNSName qname; + ComboAddress requestor; + ComboAddress ds; + struct timespec when; + std::string macAddr; + struct dnsheader dh; + unsigned int usec; + unsigned int size; + uint16_t qtype; + dnsdist::Protocol protocol; + bool isResponse; +}; + +template +static void addRingEntryToList(LuaArray& list, const T& entry) +{ + constexpr bool response = std::is_same_v; + if constexpr (!response) { +#if defined(DNSDIST_RINGS_WITH_MACADDRESS) + list.emplace_back(list.size() + 1, LuaRingEntry{entry.name, entry.requestor, ComboAddress(), entry.when, entry.hasmac ? std::string(reinterpret_cast(entry.macaddress.data()), entry.macaddress.size()) : std::string(), entry.dh, 0U, entry.size, entry.qtype, entry.protocol, false}); +#else + list.emplace_back(list.size() + 1, LuaRingEntry{entry.name, entry.requestor, ComboAddress(), entry.when, std::string(), entry.dh, 0U, entry.size, entry.qtype, entry.protocol, false}); +#endif + } + else { + list.emplace_back(list.size() + 1, LuaRingEntry{entry.name, entry.requestor, entry.ds, entry.when, std::string(), entry.dh, entry.usec, entry.size, entry.qtype, entry.protocol, true}); + } +} + +#endif /* DISABLE_LUA_BINDINGS_RINGS */ + +void setupLuaBindingsRings(LuaContext& luaCtx, bool client) +{ +#ifndef DISABLE_LUA_BINDINGS_RINGS + luaCtx.writeFunction("getRingEntries", [client]() { + LuaArray results; + + if (client) { + return results; + } + + for (const auto& shard : g_rings.d_shards) { + { + auto ql = shard->queryRing.lock(); + for (const auto& entry : *ql) { + addRingEntryToList(results, entry); + } + } + { + auto rl = shard->respRing.lock(); + for (const auto& entry : *rl) { + addRingEntryToList(results, entry); + } + } + } + + return results; + }); + + luaCtx.registerMember(std::string("qname"), [](const LuaRingEntry& entry) { + return entry.qname; + }); + + luaCtx.registerMember(std::string("requestor"), [](const LuaRingEntry& entry) { + return entry.requestor; + }); + + luaCtx.registerMember(std::string("backend"), [](const LuaRingEntry& entry) { + return entry.ds; + }); + + luaCtx.registerMember(std::string("when"), [](const LuaRingEntry& entry) { + return entry.when; + }); + + luaCtx.registerMember(std::string("macAddress"), [](const LuaRingEntry& entry) { + return entry.macAddr; + }); + + luaCtx.registerMember(std::string("dnsheader"), [](const LuaRingEntry& entry) { + return entry.dh; + }); + + luaCtx.registerMember(std::string("usec"), [](const LuaRingEntry& entry) { + return entry.usec; + }); + + luaCtx.registerMember(std::string("size"), [](const LuaRingEntry& entry) { + return entry.size; + }); + + luaCtx.registerMember(std::string("qtype"), [](const LuaRingEntry& entry) { + return entry.qtype; + }); + + luaCtx.registerMember(std::string("protocol"), [](const LuaRingEntry& entry) { + return entry.protocol.toString(); + }); + + luaCtx.registerMember(std::string("isResponse"), [](const LuaRingEntry& entry) { + return entry.isResponse; + }); + + luaCtx.registerMember(std::string("tv_sec"), [](const timespec& ts) { + return ts.tv_sec; + }); + + luaCtx.registerMember(std::string("tv_nsec"), [](const timespec& ts) { + return ts.tv_nsec; + }); + +#endif /* DISABLE_LUA_BINDINGS_RINGS */ +} diff --git a/pdns/dnsdistdist/docs/reference/config.rst b/pdns/dnsdistdist/docs/reference/config.rst index 767604da95..fa9cd483ba 100644 --- a/pdns/dnsdistdist/docs/reference/config.rst +++ b/pdns/dnsdistdist/docs/reference/config.rst @@ -1762,6 +1762,12 @@ Other functions :param int numberOfDaysOfValidity: Number of days this OCSP response should be valid. :param int numberOfMinutesOfValidity: Number of minutes this OCSP response should be valid, in addition to the number of days. +.. function:: getRingEntries() + + .. versionadded:: 1.8.0 + + Return a list of all the entries, queries and responses alike, that are present in the in-memory ring buffers, as :class:`LuaRingEntry` objects. + .. function:: loadTLSEngine(engineName [, defaultString]) .. versionadded:: 1.8.0 @@ -1853,6 +1859,76 @@ DOHFrontend :param str content: The content of the HTTP response, or a URL if the status is a redirection (3xx). :param table of headers: The custom headers to set for the HTTP response, if any. The default is to use the value of the ``customResponseHeaders`` parameter passed to :func:`addDOHLocal`. +LuaRingEntry +~~~~~~~~~~~~ + +.. class:: LuaRingEntry + + .. versionadded:: 1.8.0 + + This object represents an entry from the in-memory ring buffers, query or response. + + .. attribute:: LuaRingEntry.backend + + If this entry is a response, the backend from which it has been received as a :ref:`ComboAddress`. + +.. attribute:: LuaRingEntry.dnsheader + + The :ref:`DNSHeader` of this entry. + + .. attribute:: LuaRingEntry.isResponse + + Whether this entry is a response (true) or a request (false). + + .. attribute:: LuaRingEntry.macAddress + + The MAC address of the client as a string, if available. + + .. attribute:: LuaRingEntry.protocol + + The protocol (Do53 UDP, Do53 TCP, DoT, DoH, ...) over which this entry was received, as a string. + + .. attribute:: LuaRingEntry.qname + + The qname of this entry as a :ref:`DNSName`. + + .. attribute:: LuaRingEntry.qtype + + The qtype of this entry as an integer. + + .. attribute:: LuaRingEntry.requestor + + The requestor (client IP) of this entry as a :ref:`ComboAddress`. + + .. attribute:: LuaRingEntry.size + + The size of the DNS payload of that entry, in bytes. + +.. attribute:: LuaRingEntry.usec + + The response time (elapsed time between the request was received and the response sent) in milliseconds. + +.. attribute:: LuaRingEntry.when + + The timestamp of this entry, as a :ref:`timespec`. + +timespec +~~~~~~~~ + +.. class:: timespec + + .. versionadded:: 1.8.0 + + This object represents a timestamp in the timespec format. + + .. attribute:: timespec.tv_sec + + Number of seconds elapsed since Unix epoch. + + .. attribute:: timespec.tv_nsec + + Number of remaining nanoseconds elapsed since Unix epoch after subtracting the seconds from the `tv_sec` field. + TLSContext ~~~~~~~~~~ -- 2.47.2