From: Remi Gacogne Date: Thu, 16 Nov 2023 16:16:14 +0000 (+0100) Subject: dnsdist: Add `NetmaskGroup:addNMG()` to merge Netmask groups X-Git-Tag: rec-5.1.0-alpha0~1^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=25b3e633fdea9dd63c182972dd86fbf6dcc02334;p=thirdparty%2Fpdns.git dnsdist: Add `NetmaskGroup:addNMG()` to merge Netmask groups --- diff --git a/pdns/dnsdist-lua-bindings.cc b/pdns/dnsdist-lua-bindings.cc index c0339deaba..5d9fe9a3c6 100644 --- a/pdns/dnsdist-lua-bindings.cc +++ b/pdns/dnsdist-lua-bindings.cc @@ -382,10 +382,17 @@ void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck) /* NetmaskGroup */ luaCtx.writeFunction("newNMG", []() { return NetmaskGroup(); }); - luaCtx.registerFunction("addMask", [](NetmaskGroup&nmg, const std::string& mask) + luaCtx.registerFunction("addMask", [](NetmaskGroup&nmg, const std::string& mask) { nmg.addMask(mask); }); + luaCtx.registerFunction("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& map)>("addMasks", [](NetmaskGroup&nmg, const std::map& map) { for (const auto& entry : map) { diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index a943f2b9d3..5bca935b2d 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -840,12 +840,11 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) luaCtx.writeFunction("showACL", []() { setLuaNoSideEffect(); - vector vec; + auto aclEntries = g_ACL.getLocal()->toStringVector(); - g_ACL.getLocal()->toStringVector(&vec); - - for (const auto& s : vec) - g_outputBuffer += s + "\n"; + for (const auto& entry : aclEntries) { + g_outputBuffer += entry + "\n"; + } }); luaCtx.writeFunction("shutdown", []() { @@ -1164,11 +1163,10 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck) warnlog("Allowing remote access to the console while libsodium support has not been enabled is not secure, and will result in cleartext communications"); #endif - vector vec; - g_consoleACL.getLocal()->toStringVector(&vec); + auto aclEntries = g_consoleACL.getLocal()->toStringVector(); - for (const auto& s : vec) { - g_outputBuffer += s + "\n"; + for (const auto& entry : aclEntries) { + g_outputBuffer += entry + "\n"; } }); diff --git a/pdns/dnsdist-web.cc b/pdns/dnsdist-web.cc index d0890b5462..066b5c177f 100644 --- a/pdns/dnsdist-web.cc +++ b/pdns/dnsdist-web.cc @@ -253,15 +253,14 @@ static bool apiWriteConfigFile(const string& filebasename, const string& content static void apiSaveACL(const NetmaskGroup& nmg) { - vector vec; - nmg.toStringVector(&vec); + auto aclEntries = nmg.toStringVector(); string acl; - for(const auto& s : vec) { + for (const auto& entry : aclEntries) { if (!acl.empty()) { acl += ", "; } - acl += "\"" + s + "\""; + acl += "\"" + entry + "\""; } string content = "setACL({" + acl + "})"; @@ -1284,14 +1283,13 @@ static void handleStats(const YaHTTP::Request& req, YaHTTP::Response& resp) string acl; { - vector vec; - g_ACL.getLocal()->toStringVector(&vec); + auto aclEntries = g_ACL.getLocal()->toStringVector(); - for (const auto& s : vec) { + for (const auto& entry : aclEntries) { if (!acl.empty()) { acl += ", "; } - acl += s; + acl += entry; } } @@ -1526,18 +1524,12 @@ static void handleAllowFrom(const YaHTTP::Request& req, YaHTTP::Response& resp) } } if (resp.status == 200) { - Json::array acl; - vector vec; - g_ACL.getLocal()->toStringVector(&vec); - - for(const auto& s : vec) { - acl.push_back(s); - } + auto aclEntries = g_ACL.getLocal()->toStringVector(); Json::object obj{ { "type", "ConfigSetting" }, { "name", "allow-from" }, - { "value", acl } + { "value", aclEntries } }; Json my_json = obj; resp.body = my_json.dump(); diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index b5f8cc0f3f..bfaa81bd9f 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -2948,26 +2948,28 @@ int main(int argc, char** argv) } } - vector vec; - std::string acls; - g_ACL.getLocal()->toStringVector(&vec); - for (const auto& aclEntry : vec) { - if (!acls.empty()) { - acls += ", "; - } - acls += aclEntry; - } - infolog("ACL allowing queries from: %s", acls); - vec.clear(); - acls.clear(); - g_consoleACL.getLocal()->toStringVector(&vec); - for (const auto& entry : vec) { - if (!acls.empty()) { - acls += ", "; - } - acls += entry; - } - infolog("Console ACL allowing connections from: %s", acls.c_str()); + { + std::string acls; + auto aclEntries = g_ACL.getLocal()->toStringVector(); + for (const auto& aclEntry : aclEntries) { + if (!acls.empty()) { + acls += ", "; + } + acls += aclEntry; + } + infolog("ACL allowing queries from: %s", acls); + } + { + std::string acls; + auto aclEntries = g_consoleACL.getLocal()->toStringVector(); + for (const auto& entry : aclEntries) { + if (!acls.empty()) { + acls += ", "; + } + acls += entry; + } + infolog("Console ACL allowing connections from: %s", acls.c_str()); + } #ifdef HAVE_LIBSODIUM if (g_consoleEnabled && g_consoleKey.empty()) { diff --git a/pdns/dnsdistdist/docs/reference/netmaskgroup.rst b/pdns/dnsdistdist/docs/reference/netmaskgroup.rst index b6d19b97ac..568bb95b6a 100644 --- a/pdns/dnsdistdist/docs/reference/netmaskgroup.rst +++ b/pdns/dnsdistdist/docs/reference/netmaskgroup.rst @@ -17,6 +17,14 @@ NetmaskGroup :param string mask: Add this mask, prefix with `!` to exclude this mask from matching. :param table masks: Adds the keys of the table to the :class:`NetmaskGroup`. It should be a table whose keys are :class:`ComboAddress` objects and whose values are integers. The integer values of the table entries are ignored. The table is of the same type as the table returned by the `exceed*` functions. + .. method:: NetmaskGroup:addNMG(otherNMG) + + .. versionadded:: 1.9.0 + + Add one or more masks from an existing to this NMG. + + :param NetmaskGroup otherNMG: Add the masks from a :class:`NetmaskGroup` to this one. + .. method:: NetmaskGroup:match(address) -> bool Checks if ``address`` is matched by this NetmaskGroup. diff --git a/pdns/iputils.hh b/pdns/iputils.hh index 47ca071a47..18c15bcc53 100644 --- a/pdns/iputils.hh +++ b/pdns/iputils.hh @@ -1462,11 +1462,14 @@ public: return str.str(); } - void toStringVector(vector* vec) const + std::vector toStringVector() const { - for(auto iter = tree.begin(); iter != tree.end(); ++iter) { - vec->push_back((iter->second ? "" : "!") + iter->first.toString()); + std::vector out; + out.reserve(tree.size()); + for (const auto& entry : tree) { + out.push_back((entry.second ? "" : "!") + entry.first.toString()); } + return out; } void toMasks(const string &ips) diff --git a/pdns/recursordist/ws-recursor.cc b/pdns/recursordist/ws-recursor.cc index 5214c57e32..34313fa493 100644 --- a/pdns/recursordist/ws-recursor.cc +++ b/pdns/recursordist/ws-recursor.cc @@ -151,10 +151,10 @@ static void apiServerConfigACL(const std::string& aclType, HttpRequest* req, Htt // Return currently configured ACLs vector entries; if (t_allowFrom && aclType == "allow-from") { - t_allowFrom->toStringVector(&entries); + entries = t_allowFrom->toStringVector(); } else if (t_allowNotifyFrom && aclType == "allow-notify-from") { - t_allowNotifyFrom->toStringVector(&entries); + entries = t_allowNotifyFrom->toStringVector(); } resp->setJsonBody(Json::object{ diff --git a/regression-tests.dnsdist/test_RulesActions.py b/regression-tests.dnsdist/test_RulesActions.py index 4ce1178649..14f64d9218 100644 --- a/regression-tests.dnsdist/test_RulesActions.py +++ b/regression-tests.dnsdist/test_RulesActions.py @@ -751,6 +751,37 @@ class TestAdvancedNMGRule(DNSDistTest): (_, receivedResponse) = sender(query, response=None, useQueue=False) self.assertEqual(receivedResponse, expectedResponse) +class TestAdvancedNMGAddNMG(DNSDistTest): + _config_template = """ + oneNMG = newNMG() + anotherNMG = newNMG() + anotherNMG:addMask('127.0.0.1/32') + oneNMG:addNMG(anotherNMG) + addAction(NotRule(NetmaskGroupRule(oneNMG)), DropAction()) + addAction(AllRule(), SpoofAction('192.0.2.1')) + newServer{address="127.0.0.1:%s"} + """ + + def testAdvancedNMGRuleAddNMG(self): + """ + Advanced: NMGRule:addNMG() + """ + name = 'nmgrule-addnmg.advanced.tests.powerdns.com.' + query = dns.message.make_query(name, 'A', 'IN') + query.flags &= ~dns.flags.RD + expectedResponse = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 60, + dns.rdataclass.IN, + dns.rdatatype.A, + '192.0.2.1') + expectedResponse.answer.append(rrset) + + for method in ("sendUDPQuery", "sendTCPQuery"): + sender = getattr(self, method) + (_,receivedResponse) = sender(query, response=expectedResponse, useQueue=False) + self.assertEqual(receivedResponse, expectedResponse) + class TestDSTPortRule(DNSDistTest): _config_params = ['_dnsDistPort', '_testServerPort']