From: Remi Gacogne Date: Wed, 9 May 2018 10:53:06 +0000 (+0200) Subject: rec: Delay RPZ threads creation until the Lua config has been parsed X-Git-Tag: dnsdist-1.3.1~94^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F6588%2Fhead;p=thirdparty%2Fpdns.git rec: Delay RPZ threads creation until the Lua config has been parsed Otherwise if the parsing of the remaining Lua directives takes longer than the AXFR, our zone content will be replaced by an empty zone once the parsing finishes. --- diff --git a/pdns/rec-lua-conf.cc b/pdns/rec-lua-conf.cc index b6f8438207..eff6ecb677 100644 --- a/pdns/rec-lua-conf.cc +++ b/pdns/rec-lua-conf.cc @@ -92,6 +92,8 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly) if(!ifs) throw PDNSException("Cannot open file '"+fname+"': "+strerror(errno)); + std::vector, uint32_t, size_t, TSIGTriplet, size_t, ComboAddress, uint16_t, std::shared_ptr, std::string> > rpzMasterThreads; + auto luaconfsLocal = g_luaconfs.getLocal(); lci.generation = luaconfsLocal->generation + 1; @@ -137,7 +139,7 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly) } }); - Lua.writeFunction("rpzMaster", [&lci, checkOnly](const string& master_, const string& zoneName, const boost::optional>>& options) { + Lua.writeFunction("rpzMaster", [&lci, &rpzMasterThreads, checkOnly](const string& master_, const string& zoneName, const boost::optional>>& options) { boost::optional defpol; std::shared_ptr zone = std::make_shared(); @@ -234,20 +236,7 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly) exit(1); // FIXME proper exit code? } - try { - if (!checkOnly) { - std::thread t(RPZIXFRTracker, master, defpol, maxTTL, zoneIdx, tt, maxReceivedXFRMBytes * 1024 * 1024, localAddress, zone, axfrTimeout, sr, dumpFile, lci.generation); - t.detach(); - } - } - catch(const std::exception& e) { - g_log< > > > > argvec_t; @@ -406,6 +395,23 @@ void loadRecursorLuaConfig(const std::string& fname, bool checkOnly) try { Lua.executeCode(ifs); g_luaconfs.setState(lci); + + if (!checkOnly) { + for (const auto& rpzMaster : rpzMasterThreads) { + try { + std::thread t(RPZIXFRTracker, std::get<0>(rpzMaster), std::get<1>(rpzMaster), std::get<2>(rpzMaster), std::get<3>(rpzMaster), std::get<4>(rpzMaster), std::get<5>(rpzMaster) * 1024 * 1024, std::get<6>(rpzMaster), std::get<7>(rpzMaster), std::get<8>(rpzMaster), std::get<9>(rpzMaster), lci.generation); + t.detach(); + } + catch(const std::exception& e) { + g_log< defpol, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, std::shared_ptr zone, const uint16_t axfrTimeout, std::shared_ptr sr, std::string dumpZoneFileName, uint64_t configGeneration) +void RPZIXFRTracker(const ComboAddress& master, boost::optional defpol, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, const uint16_t axfrTimeout, std::shared_ptr sr, std::string dumpZoneFileName, uint64_t configGeneration) { bool isPreloaded = sr != nullptr; - uint32_t refresh = zone->getRefresh(); - DNSName zoneName = zone->getDomain(); - std::string polName = zone->getName() ? *(zone->getName()) : zoneName.toString(); + auto luaconfsLocal = g_luaconfs.getLocal(); + /* we can _never_ modify this zone directly, we need to do a full copy then replace the existing zone */ + std::shared_ptr oldZone = luaconfsLocal->dfe.getZone(zoneIdx); + if (!oldZone) { + g_log<getRefresh(); + DNSName zoneName = oldZone->getDomain(); + std::string polName = oldZone->getName() ? *(oldZone->getName()) : zoneName.toString(); while (!sr) { /* if we received an empty sr, the zone was not really preloaded */ - std::shared_ptr newZone = std::make_shared(*zone); + /* full copy, as promised */ + std::shared_ptr newZone = std::make_shared(*oldZone); try { sr=loadRPZFromServer(master, zoneName, newZone, defpol, maxTTL, tt, maxReceivedBytes, localAddress, axfrTimeout); if(refresh == 0) { @@ -382,7 +390,6 @@ void RPZIXFRTracker(const ComboAddress& master, boost::optional oldZone = luaconfsLocal->dfe.getZone(zoneIdx); + oldZone = luaconfsLocal->dfe.getZone(zoneIdx); /* we need to make a _full copy_ of the zone we are going to work on */ std::shared_ptr newZone = std::make_shared(*oldZone); diff --git a/pdns/rpzloader.hh b/pdns/rpzloader.hh index f3b43128c6..5faf77d8b1 100644 --- a/pdns/rpzloader.hh +++ b/pdns/rpzloader.hh @@ -29,7 +29,7 @@ extern bool g_logRPZChanges; std::shared_ptr loadRPZFromFile(const std::string& fname, std::shared_ptr zone, boost::optional defpol, uint32_t maxTTL); std::shared_ptr loadRPZFromServer(const ComboAddress& master, const DNSName& zoneName, std::shared_ptr zone, boost::optional defpol, uint32_t maxTTL, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, const uint16_t axfrTimeout); void RPZRecordToPolicy(const DNSRecord& dr, std::shared_ptr zone, bool addOrRemove, boost::optional defpol, uint32_t maxTTL); -void RPZIXFRTracker(const ComboAddress& master, boost::optional defpol, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, std::shared_ptr zone, const uint16_t axfrTimeout, shared_ptr sr, std::string dumpZoneFileName, uint64_t configGeneration); +void RPZIXFRTracker(const ComboAddress& master, boost::optional defpol, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, const uint16_t axfrTimeout, shared_ptr sr, std::string dumpZoneFileName, uint64_t configGeneration); struct rpzStats {