Lua.writeFunction("zoneToCache", [&delayedThreads](const string& zoneName, const string& method, const boost::variant<string, std::vector<std::pair<int, string>>>& srcs, boost::optional<zoneToCacheOptions_t> options) {
try {
RecZoneToCache::Config conf;
+ DNSName validZoneName(zoneName);
conf.d_zone = zoneName;
+ const set<string> methods = {"axfr", "url", "file"};
+ if (methods.count(method) == 0) {
+ throw std::runtime_error("unknwon method '" + method + "'");
+ }
conf.d_method = method;
if (srcs.type() == typeid(std::string)) {
conf.d_sources.push_back(boost::get<std::string>(srcs));
conf.d_sources.push_back(src.second);
}
}
+ if (conf.d_sources.size() == 0) {
+ throw std::runtime_error("at least one source required");
+ }
if (options) {
auto& have = *options;
if (have.count("timeout")) {
- conf.d_timeout = boost::get<uint32_t>(have["timeout"]);
+ conf.d_timeout = boost::get<uint32_t>(have.at("timeout"));
}
if (have.count("tsigname")) {
- conf.d_tt.name = DNSName(toLower(boost::get<string>(have["tsigname"])));
- conf.d_tt.algo = DNSName(toLower(boost::get<string>(have[ "tsigalgo"])));
- if (B64Decode(boost::get<string>(have[ "tsigsecret"]), conf.d_tt.secret)) {
+ conf.d_tt.name = DNSName(toLower(boost::get<string>(have.at("tsigname"))));
+ conf.d_tt.algo = DNSName(toLower(boost::get<string>(have.at("tsigalgo"))));
+ if (B64Decode(boost::get<string>(have.at("tsigsecret")), conf.d_tt.secret)) {
throw std::runtime_error("TSIG secret is not valid Base-64 encoded");
}
}
if (have.count("maxReceivedMBytes")) {
- conf.d_maxReceivedBytes = static_cast<size_t>(boost::get<uint32_t>(have["maxReceivedMBytes"]));
+ conf.d_maxReceivedBytes = static_cast<size_t>(boost::get<uint32_t>(have.at("maxReceivedMBytes")));
conf.d_maxReceivedBytes *= 1024 * 1024;
}
if (have.count("localAddress")) {
- conf.d_local = ComboAddress(boost::get<string>(have["localAddress"]));
+ conf.d_local = ComboAddress(boost::get<string>(have.at("localAddress")));
}
if (have.count("refreshPeriod")) {
- conf.d_refreshPeriod = boost::get<uint32_t>(have["refreshPeriod"]);
+ conf.d_refreshPeriod = boost::get<uint32_t>(have.at("refreshPeriod"));
}
if (have.count("retryOnErrorPeriod")) {
- conf.d_retryOnError = boost::get<uint32_t>(have["retryOnErrorPeriod"]);
+ conf.d_retryOnError = boost::get<uint32_t>(have.at("retryOnErrorPeriod"));
}
}
delayedThreads.ztcConfigs.push_back(conf);
}
- catch (const std::exception&e ) {
- g_log<<Logger::Error<<"Problem configuring zoneToCache: "<<e.what()<<endl;
+ catch (const std::exception& e) {
+ g_log<<Logger::Error<<"Problem configuring zoneToCache for zone '" << zoneName << "': " << e.what() << endl;
}
});
-
+
typedef vector<pair<int,boost::variant<string, vector<pair<int, string> > > > > argvec_t;
Lua.writeFunction("addSortList",
[&lci](const std::string& formask_,
DNSName d_zone;
shared_ptr<Logr::Logger>& d_log;
- bool isRRSetAuth(const DNSName& qname, QType qtype);
+ bool isRRSetAuth(const DNSName& qname, QType qtype) const;
void parseDRForCache(DNSRecord& dr);
void getByAXFR(const RecZoneToCache::Config&);
- void ZoneToCache(const RecZoneToCache::Config& config);
+ void ZoneToCache(const RecZoneToCache::Config& config, uint64_t gen);
};
-bool ZoneData::isRRSetAuth(const DNSName& qname, QType qtype)
+bool ZoneData::isRRSetAuth(const DNSName& qname, QType qtype) const
{
DNSName delegatedZone(qname);
if (qtype == QType::DS) {
}
axfrNow = time(nullptr);
if (axfrNow < axfrStart || axfrNow - axfrStart > axfrTimeout) {
- throw PDNSException("Total AXFR time for zoneToCache exceeded!");
+ throw std::runtime_error("Total AXFR time for zoneToCache exceeded!");
}
}
}
-static std::vector<std::string> getLinesFromFile(const RecZoneToCache::Config& config)
+static std::vector<std::string> getLinesFromFile(const std::string& file)
{
std::vector<std::string> lines;
- std::ifstream stream(config.d_sources.at(0));
+ std::ifstream stream(file);
if (!stream) {
- throw PDNSException("Cannot read file: " + config.d_sources.at(0));
+ throw std::runtime_error("Cannot read file: " + file);
}
std::string line;
while (std::getline(stream, line)) {
std::string reply = mc.getURL(config.d_sources.at(0), nullptr, local == ComboAddress() ? nullptr : &local, config.d_timeout, false, true);
if (config.d_maxReceivedBytes > 0 && reply.size() > config.d_maxReceivedBytes) {
// We should actually detect this *during* the GET
- throw PDNSException("Retrieved data exceeds maxReceivedBytes");
+ throw std::runtime_error("Retrieved data exceeds maxReceivedBytes");
}
std::istringstream stream(reply);
string line;
return lines;
}
-void ZoneData::ZoneToCache(const RecZoneToCache::Config& config)
+void ZoneData::ZoneToCache(const RecZoneToCache::Config& config, uint64_t configGeneration)
{
if (config.d_sources.size() > 1) {
d_log->info("Multiple sources not yet supported, using first");
}
else if (config.d_method == "file") {
d_log->info("Getting zone from file");
- lines = getLinesFromFile(config);
+ lines = getLinesFromFile(config.d_sources.at(0));
}
DNSResourceRecord drr;
ZoneParserTNG zpt(lines, d_zone);
- zpt.setMaxGenerateSteps(0);
+ zpt.setMaxGenerateSteps(1);
while (zpt.get(drr)) {
DNSRecord dr(drr);
}
}
+ // Extra check before we are touching the cache
+ auto luaconfsLocal = g_luaconfs.getLocal();
+ if (luaconfsLocal->generation != configGeneration) {
+ return;
+ }
+
// Rerun, now inserting the rrsets into the cache with associated sigs
d_now = time(nullptr);
for (const auto& [key, v] : d_all) {
vector<shared_ptr<RRSIGRecordContent>> sigsrr;
auto it = d_sigs.find(key);
if (it != d_sigs.end()) {
- for (const auto& sig : it->second) {
- sigsrr.push_back(sig);
- }
+ sigsrr = it->second;
}
bool auth = isRRSetAuth(qname, qtype);
// Same decision as updateCacheFromRecords() (we do not test for NSEC since we skip those completely)
time_t refresh = config.d_retryOnError;
try {
ZoneData data(log);
- data.ZoneToCache(config);
+ data.ZoneToCache(config, configGeneration);
+ if (luaconfsLocal->generation != configGeneration) {
+ log->info("A more recent configuration has been found, stopping the old update thread");
+ return;
+ }
refresh = config.d_refreshPeriod;
log->info("Loaded zone into cache", "refresh", Logging::Loggable(refresh));
}