ComboAddress localAddress;
ComboAddress master(master_, 53);
size_t zoneIdx;
+ std::string dumpFile;
std::shared_ptr<SOARecordContent> sr = nullptr;
try {
if(have.count("seedFile")) {
seedFile = boost::get<std::string>(constGet(have, "seedFile"));
}
+
+ if(have.count("dumpFile")) {
+ dumpFile = boost::get<std::string>(constGet(have, "dumpFile"));
+ }
}
if (localAddress != ComboAddress() && localAddress.sin4.sin_family != master.sin4.sin_family) {
zoneIdx = lci.dfe.addZone(zone);
if (!seedFile.empty()) {
- sr = loadRPZFromFile(seedFile, zone, defpol, maxTTL);
- if (zone->getDomain() != domain) {
- throw PDNSException("The RPZ zone " + zoneName + " loaded from the seed file (" + zone->getDomain().toString() + ") does not match the one passed in parameter (" + domain.toString() + ")");
- }
+ g_log<<Logger::Info<<"Pre-loading RPZ zone "<<zoneName<<" from seed file '"<<seedFile<<"'"<<endl;
+ try {
+ sr = loadRPZFromFile(seedFile, zone, defpol, maxTTL);
- if (sr == nullptr) {
- throw PDNSException("The RPZ zone " + zoneName + " loaded from the seed file (" + zone->getDomain().toString() + ") has no SOA record");
+ if (zone->getDomain() != domain) {
+ throw PDNSException("The RPZ zone " + zoneName + " loaded from the seed file (" + zone->getDomain().toString() + ") does not match the one passed in parameter (" + domain.toString() + ")");
+ }
+
+ if (sr == nullptr) {
+ throw PDNSException("The RPZ zone " + zoneName + " loaded from the seed file (" + zone->getDomain().toString() + ") has no SOA record");
+ }
+ }
+ catch(const std::exception& e) {
+ g_log<<Logger::Warning<<"Unable to pre-load RPZ zone "<<zoneName<<" from seed file '"<<seedFile<<"': "<<e.what()<<endl;
}
}
}
try {
if (!checkOnly) {
- std::thread t(RPZIXFRTracker, master, defpol, maxTTL, zoneIdx, tt, maxReceivedXFRMBytes * 1024 * 1024, localAddress, zone, axfrTimeout, sr, lci.generation);
+ std::thread t(RPZIXFRTracker, master, defpol, maxTTL, zoneIdx, tt, maxReceivedXFRMBytes * 1024 * 1024, localAddress, zone, axfrTimeout, sr, dumpFile, lci.generation);
t.detach();
}
}
stats->d_numberOfRecords = numberOfRecords;
}
-void RPZIXFRTracker(const ComboAddress& master, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, std::shared_ptr<DNSFilterEngine::Zone> zone, const uint16_t axfrTimeout, std::shared_ptr<SOARecordContent> sr, uint64_t configGeneration)
+static bool dumpZoneToDisk(const DNSName& zoneName, const std::shared_ptr<DNSFilterEngine::Zone>& newZone, const std::string& dumpZoneFileName)
+{
+ std::string temp = dumpZoneFileName + "XXXXXX";
+ int fd = mkstemp(&temp.at(0));
+ if (fd < 0) {
+ g_log<<Logger::Warning<<"Unable to open a file to dump the content of the RPZ zone "<<zoneName.toLogString()<<endl;
+ return false;
+ }
+
+ FILE * fp = fdopen(fd, "w+");
+ if (fp == nullptr) {
+ close(fd);
+ g_log<<Logger::Warning<<"Unable to open a file pointer to dump the content of the RPZ zone "<<zoneName.toLogString()<<endl;
+ return false;
+ }
+
+ fd = -1;
+
+ try {
+ newZone->dump(fp);
+ }
+ catch(const std::exception& e) {
+ g_log<<Logger::Warning<<"Error while dumping the content of the RPZ zone "<<zoneName.toLogString()<<": "<<e.what()<<endl;
+ fclose(fp);
+ return false;
+ }
+
+ if (fflush(fp) != 0) {
+ g_log<<Logger::Warning<<"Error while flushing the content of the RPZ zone "<<zoneName.toLogString()<<" to the dump file: "<<strerror(errno)<<endl;
+ return false;
+ }
+
+ if (fsync(fileno(fp)) != 0) {
+ g_log<<Logger::Warning<<"Error while syncing the content of the RPZ zone "<<zoneName.toLogString()<<" to the dump file: "<<strerror(errno)<<endl;
+ return false;
+ }
+
+ if (fclose(fp) != 0) {
+ g_log<<Logger::Warning<<"Error while writing the content of the RPZ zone "<<zoneName.toLogString()<<" to the dump file: "<<strerror(errno)<<endl;
+ return false;
+ }
+
+ if (rename(temp.c_str(), dumpZoneFileName.c_str()) != 0) {
+ g_log<<Logger::Warning<<"Error while moving the content of the RPZ zone "<<zoneName.toLogString()<<" to the dump file: "<<strerror(errno)<<endl;
+ return false;
+ }
+
+ return true;
+}
+
+void RPZIXFRTracker(const ComboAddress& master, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, std::shared_ptr<DNSFilterEngine::Zone> zone, const uint16_t axfrTimeout, std::shared_ptr<SOARecordContent> sr, std::string dumpZoneFileName, uint64_t configGeneration)
{
bool isPreloaded = sr != nullptr;
uint32_t refresh = zone->getRefresh();
}
zone->setSerial(sr->d_st.serial);
setRPZZoneNewState(polName, sr->d_st.serial, zone->size(), true);
+
+ if (!dumpZoneFileName.empty()) {
+ dumpZoneToDisk(zoneName, zone, dumpZoneFileName);
+ }
}
catch(const std::exception& e) {
g_log<<Logger::Warning<<"Unable to load RPZ zone '"<<zoneName<<"' from '"<<master<<"': '"<<e.what()<<"'. (Will try again in "<<(refresh > 0 ? refresh : 10)<<" seconds...)"<<endl;
g_luaconfs.modify([zoneIdx, &newZone](LuaConfigItems& lci) {
lci.dfe.setZone(zoneIdx, newZone);
});
+
+ if (!dumpZoneFileName.empty()) {
+ dumpZoneToDisk(zoneName, newZone, dumpZoneFileName);
+ }
}
}
std::shared_ptr<SOARecordContent> loadRPZFromFile(const std::string& fname, std::shared_ptr<DNSFilterEngine::Zone> zone, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL);
std::shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zoneName, std::shared_ptr<DNSFilterEngine::Zone> zone, boost::optional<DNSFilterEngine::Policy> 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<DNSFilterEngine::Zone> zone, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL);
-void RPZIXFRTracker(const ComboAddress& master, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, std::shared_ptr<DNSFilterEngine::Zone> zone, const uint16_t axfrTimeout, shared_ptr<SOARecordContent> sr, uint64_t configGeneration);
+void RPZIXFRTracker(const ComboAddress& master, boost::optional<DNSFilterEngine::Policy> defpol, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, std::shared_ptr<DNSFilterEngine::Zone> zone, const uint16_t axfrTimeout, shared_ptr<SOARecordContent> sr, std::string dumpZoneFileName, uint64_t configGeneration);
struct rpzStats
{