set<ComboAddress> masters; // A set so we can do multiple master addresses in the future
};
-// For all the listen-sockets
-FDMultiplexer* g_fdm;
-
// This contains the configuration for each domain
map<DNSName, ixfrdistdomain_t> g_domainConfigs;
using namespace boost::multi_index;
namespace po = boost::program_options;
-po::variables_map g_vm;
-string g_workdir;
bool g_exiting = false;
-#define KEEP_DEFAULT 20
-uint16_t g_keep = KEEP_DEFAULT;
-
-#define AXFRTIMEOUT_DEFAULT 20
-uint16_t g_axfrTimeout = AXFRTIMEOUT_DEFAULT;
-
NetmaskGroup g_acl;
void handleSignal(int signum) {
return rfc1982LessThan(i, j);
}
-void cleanUpDomain(const DNSName& domain) {
- string dir = g_workdir + "/" + domain.toString();
+void cleanUpDomain(const DNSName& domain, const uint16_t& keep, const string& workdir) {
+ string dir = workdir + "/" + domain.toString();
DIR *dp;
dp = opendir(dir.c_str());
if (dp == nullptr) {
zoneVersions.push_back(std::stoi(d->d_name));
}
closedir(dp);
- g_log<<Logger::Info<<"Found "<<zoneVersions.size()<<" versions of "<<domain<<", asked to keep "<<g_keep<<", ";
- if (zoneVersions.size() <= g_keep) {
+ g_log<<Logger::Info<<"Found "<<zoneVersions.size()<<" versions of "<<domain<<", asked to keep "<<keep<<", ";
+ if (zoneVersions.size() <= keep) {
g_log<<Logger::Info<<"not cleaning up"<<endl;
return;
}
- g_log<<Logger::Info<<"cleaning up the oldest "<<zoneVersions.size() - g_keep<<endl;
+ g_log<<Logger::Info<<"cleaning up the oldest "<<zoneVersions.size() - keep<<endl;
// Sort the versions
std::sort(zoneVersions.begin(), zoneVersions.end(), sortSOA);
{
// Lock to ensure no one reads this.
std::lock_guard<std::mutex> guard(g_soas_mutex);
- for (auto iter = zoneVersions.cbegin(); iter != zoneVersions.cend() - g_keep; ++iter) {
+ for (auto iter = zoneVersions.cbegin(); iter != zoneVersions.cend() - keep; ++iter) {
string fname = dir + "/" + std::to_string(*iter);
g_log<<Logger::Debug<<"Removing "<<fname<<endl;
unlink(fname.c_str());
}
}
-void updateThread() {
+void updateThread(const string& workdir, const uint16_t& keep, const uint16_t& axfrTimeout) {
std::map<DNSName, time_t> lastCheck;
// Initialize the serials we have
for (const auto &domainConfig : g_domainConfigs) {
DNSName domain = domainConfig.first;
lastCheck[domain] = 0;
- string dir = g_workdir + "/" + domain.toString();
+ string dir = workdir + "/" + domain.toString();
try {
g_log<<Logger::Info<<"Trying to initially load domain "<<domain<<" from disk"<<endl;
auto serial = getSerialsFromDir(dir);
shared_ptr<SOARecordContent> soa;
{
- string fname = g_workdir + "/" + domain.toString() + "/" + std::to_string(serial);
+ string fname = workdir + "/" + domain.toString() + "/" + std::to_string(serial);
loadSOAFromDisk(domain, fname, soa);
records_t records;
if (soa != nullptr) {
if (soa != nullptr) {
g_log<<Logger::Notice<<"Loaded zone "<<domain<<" with serial "<<soa->d_st.serial<<endl;
// Initial cleanup
- cleanUpDomain(domain);
+ cleanUpDomain(domain, keep, workdir);
}
} catch (runtime_error &e) {
// Most likely, the directory does not exist.
std::advance(it, random() % g_domainConfigs[domain].masters.size());
ComboAddress master = *it;
- string dir = g_workdir + "/" + domain.toString();
+ string dir = workdir + "/" + domain.toString();
g_log<<Logger::Info<<"Attempting to retrieve SOA Serial update for '"<<domain<<"' from '"<<master.toStringWithPort()<<"'"<<endl;
shared_ptr<SOARecordContent> sr;
try {
records_t records;
time_t t_start = time(nullptr);
time_t axfr_now = time(nullptr);
- while(axfr.getChunk(nop, &chunk, (axfr_now - t_start + g_axfrTimeout))) {
+ while(axfr.getChunk(nop, &chunk, (axfr_now - t_start + axfrTimeout))) {
for(auto& dr : chunk) {
if(dr.d_type == QType::TSIG)
continue;
}
}
axfr_now = time(nullptr);
- if (axfr_now - t_start > g_axfrTimeout) {
+ if (axfr_now - t_start > axfrTimeout) {
throw PDNSException("Total AXFR time exceeded!");
}
}
g_soas[domain].ixfrDiffs.push_back(diff);
}
// Clean up the diffs
- while (g_soas[domain].ixfrDiffs.size() > g_keep) {
+ while (g_soas[domain].ixfrDiffs.size() > keep) {
g_soas[domain].ixfrDiffs.erase(g_soas[domain].ixfrDiffs.begin());
}
g_soas[domain].latestAXFR = records;
g_log<<Logger::Warning<<"Could not save zone '"<<domain<<"' to disk: "<<e.what()<<endl;
}
// Now clean up the directory
- cleanUpDomain(domain);
+ cleanUpDomain(domain, keep, workdir);
} /* for (const auto &domain : domains) */
sleep(1);
} /* while (true) */
* good, false otherwise. Will log all issues with the config
*/
bool parseAndCheckConfig(const string& configpath, YAML::Node& config) {
- g_log<<Logger::Info<<"Loading configuration file from "<<g_vm["config"].as<string>()<<endl;
+ g_log<<Logger::Info<<"Loading configuration file from "<<configpath<<endl;
try {
config = YAML::LoadFile(configpath);
} catch (const runtime_error &e) {
- g_log<<Logger::Error<<"Unable to load configuration file '"<<g_vm["config"].as<string>()<<"': "<<e.what()<<endl;
+ g_log<<Logger::Error<<"Unable to load configuration file '"<<configpath<<"': "<<e.what()<<endl;
return false;
}
retval = false;
}
} else {
- config["keep"] = KEEP_DEFAULT;
+ config["keep"] = 20;
}
if (config["axfr-timeout"]) {
g_log<<Logger::Error<<"Unable to read 'axfr-timeout' value: "<<e.what()<<endl;
}
} else {
- config["axfr-timeout"] = AXFRTIMEOUT_DEFAULT;
+ config["axfr-timeout"] = 10;
}
if (config["tcp-in-threads"]) {
g_log.setPrefixed(true);
g_log.disableSyslog(true);
g_log.setTimestamps(false);
+ po::variables_map g_vm;
try {
po::options_description desc("IXFR distribution tool");
desc.add_options()
g_domainConfigs[domain["domain"].as<DNSName>()].masters = s;
}
- g_workdir = config["work-dir"].as<string>();
-
for (const auto &addr : config["acl"].as<vector<string>>()) {
try {
g_acl.addMask(addr);
}
g_log<<Logger::Notice<<"ACL set to "<<g_acl.toString()<<"."<<endl;
- g_fdm = FDMultiplexer::getMultiplexerSilent();
- if (g_fdm == nullptr) {
+ FDMultiplexer* fdm = FDMultiplexer::getMultiplexerSilent();
+ if (fdm == nullptr) {
g_log<<Logger::Error<<"Could not enable a multiplexer for the listen sockets!"<<endl;
return EXIT_FAILURE;
}
if (stype == SOCK_STREAM) {
SListen(s, 30); // TODO make this configurable
}
- g_fdm->addReadFD(s, stype == SOCK_DGRAM ? handleUDPRequest : handleTCPRequest);
+ fdm->addReadFD(s, stype == SOCK_DGRAM ? handleUDPRequest : handleTCPRequest);
allSockets.insert(s);
} catch(runtime_error &e) {
g_log<<Logger::Error<<e.what()<<endl;
g_log<<Logger::Notice<<"IXFR distributor starting up!"<<endl;
- std::thread ut(updateThread);
+ std::thread ut(updateThread,
+ config["work-dir"].as<string>(),
+ config["keep"].as<uint16_t>(),
+ config["axfr-timeout"].as<uint16_t>());
vector<std::thread> tcpHandlers;
tcpHandlers.reserve(config["tcp-in-threads"].as<uint16_t>());
struct timeval now;
for(;;) {
gettimeofday(&now, 0);
- g_fdm->run(&now);
+ fdm->run(&now);
if (g_exiting) {
g_log<<Logger::Notice<<"Shutting down!"<<endl;
for (const int& fd : allSockets) {