template ProxyMappingStats_t broadcastAccFunction(const std::function<ProxyMappingStats_t*()>& fun);
template RemoteLoggerStats_t broadcastAccFunction(const std::function<RemoteLoggerStats_t*()>& fun);
-static int serviceMain(Logr::log_t log)
+static int initNet(Logr::log_t log)
{
- g_log.setName(g_programname);
- g_log.disableSyslog(::arg().mustDo("disable-syslog"));
- g_log.setTimestamps(::arg().mustDo("log-timestamp"));
- g_regressionTestMode = ::arg().mustDo("devonly-regression-test-mode");
-
- if (!::arg()["logging-facility"].empty()) {
- int val = logFacilityToLOG(::arg().asNum("logging-facility"));
- if (val >= 0) {
- g_log.setFacility(val);
- } else {
- SLOG(g_log << Logger::Error << "Unknown logging facility " << ::arg().asNum("logging-facility") << endl,
- log->info(Logr::Error, "Unknown logging facility", "facility", Logging::Loggable(::arg().asNum("logging-facility"))));
- }
- }
-
- showProductVersion();
-
- g_disthashseed = dns_random(0xffffffff);
-
checkLinuxIPv6Limits(log);
try {
pdns::parseQueryLocalAddress(::arg()["query-local-address"]);
log->info(Logr::Error, "No outgoing addresses configured! Can not continue"));
return 99;
}
+ return 0;
+}
- // keep this ABOVE loadRecursorLuaConfig!
+static int initDNSSEC(Logr::log_t log)
+{
if (::arg()["dnssec"] == "off") {
g_dnssecmode = DNSSECMode::Off;
} else if (::arg()["dnssec"] == "process-no-validate") {
g_dnssecLogBogus = ::arg().mustDo("dnssec-log-bogus");
g_maxNSEC3Iterations = ::arg().asNum("nsec3-max-iterations");
+ return 0;
+}
- g_maxCacheEntries = ::arg().asNum("max-cache-entries");
-
- luaConfigDelayedThreads delayedLuaThreads;
- try {
- ProxyMapping proxyMapping;
- loadRecursorLuaConfig(::arg()["lua-config-file"], delayedLuaThreads, proxyMapping);
- // Initial proxy mapping
- g_proxyMapping = proxyMapping.empty() ? nullptr : std::make_unique<ProxyMapping>(proxyMapping);
- }
- catch (PDNSException& e) {
- SLOG(g_log << Logger::Error << "Cannot load Lua configuration: " << e.reason << endl,
- log->error(Logr::Error, e.reason, "Cannot load Lua configuration"));
- return 1;
- }
-
- parseACLs();
- initPublicSuffixList(::arg()["public-suffix-list-file"]);
-
+static void initDontQuery(Logr::log_t log)
+{
if (!::arg()["dont-query"].empty()) {
vector<string> ips;
stringtok(ips, ::arg()["dont-query"], ", ");
log->info(Logr::Notice, "Will not send queries to", "addresses", Logging::IterLoggable(ips.begin(), ips.end()));
}
}
+}
- /* this needs to be done before parseACLs(), which call broadcastFunction() */
- RecThreadInfo::setWeDistributeQueries(::arg().mustDo("pdns-distributes-queries"));
- if (RecThreadInfo::weDistributeQueries()) {
- SLOG(g_log << Logger::Warning << "PowerDNS Recursor itself will distribute queries over threads" << endl,
- log->info(Logr::Notice, "PowerDNS Recursor itself will distribute queries over threads"));
- }
-
- g_outgoingEDNSBufsize = ::arg().asNum("edns-outgoing-bufsize");
-
- if (::arg()["trace"] == "fail") {
- SyncRes::setDefaultLogMode(SyncRes::Store);
- }
- else if (::arg().mustDo("trace")) {
- SyncRes::setDefaultLogMode(SyncRes::Log);
- ::arg().set("quiet") = "no";
- g_quiet = false;
- }
- auto myHostname = getHostname();
- if (!myHostname.has_value()) {
- SLOG(g_log << Logger::Warning << "Unable to get the hostname, NSID and id.server values will be empty" << endl,
- log->info(Logr::Warning, "Unable to get the hostname, NSID and id.server values will be empty"));
- }
-
+static int initSyncRes(Logr::log_t log, const std::optional<std::string>& myHostname)
+{
SyncRes::s_minimumTTL = ::arg().asNum("minimum-ttl-override");
SyncRes::s_minimumECSTTL = ::arg().asNum("ecs-minimum-ttl-override");
SyncRes::s_maxnegttl = ::arg().asNum("max-negative-ttl");
SyncRes::parseEDNSSubnetAllowlist(::arg()["edns-subnet-allow-list"]);
SyncRes::parseEDNSSubnetAddFor(::arg()["ecs-add-for"]);
g_useIncomingECS = ::arg().mustDo("use-incoming-edns-subnet");
+ return 0;
+}
- g_proxyProtocolACL.toMasks(::arg()["proxy-protocol-from"]);
- g_proxyProtocolMaximumSize = ::arg().asNum("proxy-protocol-maximum-size");
-
- if (!::arg()["dns64-prefix"].empty()) {
- try {
- auto dns64Prefix = Netmask(::arg()["dns64-prefix"]);
- if (dns64Prefix.getBits() != 96) {
- SLOG(g_log << Logger::Error << "Invalid prefix for 'dns64-prefix', the current implementation only supports /96 prefixes: " << ::arg()["dns64-prefix"] << endl,
- log->info(Logr::Error, "Invalid prefix for 'dns64-prefix', the current implementation only supports /96 prefixes", "prefix", Logging::Loggable(::arg()["dns64-prefix"])));
- return 1;
- }
- g_dns64Prefix = dns64Prefix.getNetwork();
- g_dns64PrefixReverse = reverseNameFromIP(*g_dns64Prefix);
- /* /96 is 24 nibbles + 2 for "ip6.arpa." */
- while (g_dns64PrefixReverse.countLabels() > 26) {
- g_dns64PrefixReverse.chopOff();
- }
- }
- catch (const NetmaskException& ne) {
- SLOG(g_log << Logger::Error << "Invalid prefix '" << ::arg()["dns64-prefix"] << "' for 'dns64-prefix': " << ne.reason << endl,
- log->info(Logr::Error, "Invalid prefix", "dns64-prefix", Logging::Loggable(::arg()["dns64-prefix"])));
- return 1;
- }
- }
-
- g_networkTimeoutMsec = ::arg().asNum("network-timeout");
-
- std::tie(g_initialDomainMap, g_initialAllowNotifyFor) = parseZoneConfiguration();
-
- g_latencyStatSize = ::arg().asNum("latency-statistic-size");
-
- g_logCommonErrors = ::arg().mustDo("log-common-errors");
- g_logRPZChanges = ::arg().mustDo("log-rpz-changes");
-
- g_anyToTcp = ::arg().mustDo("any-to-tcp");
- g_udpTruncationThreshold = ::arg().asNum("udp-truncation-threshold");
-
- g_lowercaseOutgoing = ::arg().mustDo("lowercase-outgoing");
-
- g_paddingFrom.toMasks(::arg()["edns-padding-from"]);
- if (::arg()["edns-padding-mode"] == "always") {
- g_paddingMode = PaddingMode::Always;
- }
- else if (::arg()["edns-padding-mode"] == "padded-queries-only") {
- g_paddingMode = PaddingMode::PaddedQueries;
- }
- else {
- SLOG(g_log << Logger::Error << "Unknown edns-padding-mode: " << ::arg()["edns-padding-mode"] << endl,
- log->info(Logr::Error, "Unknown edns-padding-mode", "edns-padding-mode", Logging::Loggable(::arg()["edns-padding-mode"])));
- return 1;
- }
- g_paddingTag = ::arg().asNum("edns-padding-tag");
- g_paddingOutgoing = ::arg().mustDo("edns-padding-out");
-
- RecThreadInfo::setNumDistributorThreads(::arg().asNum("distributor-threads"));
- RecThreadInfo::setNumWorkerThreads(::arg().asNum("threads"));
- if (RecThreadInfo::numWorkers() < 1) {
- SLOG(g_log << Logger::Warning << "Asked to run with 0 threads, raising to 1 instead" << endl,
- log->info(Logr::Warning, "Asked to run with 0 threads, raising to 1 instead"));
- RecThreadInfo::setNumWorkerThreads(1);
- }
-
- g_maxMThreads = ::arg().asNum("max-mthreads");
-
- int64_t maxInFlight = ::arg().asNum("max-concurrent-requests-per-tcp-connection");
- if (maxInFlight < 1 || maxInFlight > USHRT_MAX || maxInFlight >= g_maxMThreads) {
- SLOG(g_log << Logger::Warning << "Asked to run with illegal max-concurrent-requests-per-tcp-connection, setting to default (10)" << endl,
- log->info(Logr::Warning, "Asked to run with illegal max-concurrent-requests-per-tcp-connection, setting to default (10)"));
- TCPConnection::s_maxInFlight = 10;
- }
- else {
- TCPConnection::s_maxInFlight = maxInFlight;
- }
-
- int64_t millis = ::arg().asNum("tcp-out-max-idle-ms");
- TCPOutConnectionManager::s_maxIdleTime = timeval{millis / 1000, (static_cast<suseconds_t>(millis) % 1000) * 1000};
- TCPOutConnectionManager::s_maxIdlePerAuth = ::arg().asNum("tcp-out-max-idle-per-auth");
- TCPOutConnectionManager::s_maxQueries = ::arg().asNum("tcp-out-max-queries");
- TCPOutConnectionManager::s_maxIdlePerThread = ::arg().asNum("tcp-out-max-idle-per-thread");
-
- g_gettagNeedsEDNSOptions = ::arg().mustDo("gettag-needs-edns-options");
-
- s_statisticsInterval = ::arg().asNum("statistics-interval");
-
- SyncRes::s_addExtendedResolutionDNSErrors = ::arg().mustDo("extended-resolution-errors");
-
- if (::arg().asNum("aggressive-nsec-cache-size") > 0) {
- if (g_dnssecmode == DNSSECMode::ValidateAll || g_dnssecmode == DNSSECMode::ValidateForLog || g_dnssecmode == DNSSECMode::Process) {
- g_aggressiveNSECCache = make_unique<AggressiveNSECCache>(::arg().asNum("aggressive-nsec-cache-size"));
- }
- else {
- SLOG(g_log << Logger::Warning << "Aggressive NSEC/NSEC3 caching is enabled but DNSSEC validation is not set to 'validate', 'log-fail' or 'process', ignoring" << endl,
- log->info(Logr::Warning, "Aggressive NSEC/NSEC3 caching is enabled but DNSSEC validation is not set to 'validate', 'log-fail' or 'process', ignoring"));
- }
- }
-
- AggressiveNSECCache::s_maxNSEC3CommonPrefix = static_cast<uint8_t>(std::round(std::log2(::arg().asNum("aggressive-cache-min-nsec3-hit-ratio"))));
- SLOG(g_log << Logger::Debug << "NSEC3 aggressive cache tuning: aggressive-cache-min-nsec3-hit-ratio: " << ::arg().asNum("aggressive-cache-min-nsec3-hit-ratio") << " max common prefix bits: " << std::to_string(AggressiveNSECCache::s_maxNSEC3CommonPrefix) << endl,
- log->info(Logr::Debug, "NSEC3 aggressive cache tuning", "aggressive-cache-min-nsec3-hit-ratio", Logging::Loggable(::arg().asNum("aggressive-cache-min-nsec3-hit-ratio")), "maxCommonPrefixBits", Logging::Loggable(AggressiveNSECCache::s_maxNSEC3CommonPrefix)));
-
- {
- SuffixMatchNode dontThrottleNames;
- vector<string> parts;
- stringtok(parts, ::arg()["dont-throttle-names"], " ,");
- for (const auto& part : parts) {
- dontThrottleNames.add(DNSName(part));
- }
- g_dontThrottleNames.setState(std::move(dontThrottleNames));
-
- parts.clear();
- NetmaskGroup dontThrottleNetmasks;
- stringtok(parts, ::arg()["dont-throttle-netmasks"], " ,");
- for (const auto& part : parts) {
- dontThrottleNetmasks.addMask(Netmask(part));
- }
- g_dontThrottleNetmasks.setState(std::move(dontThrottleNetmasks));
- }
-
- {
- SuffixMatchNode xdnssecNames;
- vector<string> parts;
- stringtok(parts, ::arg()["x-dnssec-names"], " ,");
- for (const auto& part : parts) {
- xdnssecNames.add(DNSName(part));
- }
- g_xdnssec.setState(std::move(xdnssecNames));
- }
-
- {
- SuffixMatchNode dotauthNames;
- vector<string> parts;
- stringtok(parts, ::arg()["dot-to-auth-names"], " ,");
-#ifndef HAVE_DNS_OVER_TLS
- if (parts.size()) {
- SLOG(g_log << Logger::Error << "dot-to-auth-names setting contains names, but Recursor was built without DNS over TLS support. Setting will be ignored." << endl,
- log->info(Logr::Error, "dot-to-auth-names setting contains names, but Recursor was built without DNS over TLS support. Setting will be ignored"));
- }
-#endif
- for (const auto& part : parts) {
- dotauthNames.add(DNSName(part));
- }
- g_DoTToAuthNames.setState(std::move(dotauthNames));
- }
-
- {
- CarbonConfig config;
- stringtok(config.servers, arg()["carbon-server"], ", ");
- config.hostname = arg()["carbon-ourname"];
- config.instance_name = arg()["carbon-instance"];
- config.namespace_name = arg()["carbon-namespace"];
- g_carbonConfig.setState(std::move(config));
- }
-
+static void initDistribution(Logr::log_t log)
+{
g_balancingFactor = ::arg().asDouble("distribution-load-factor");
if (g_balancingFactor != 0.0 && g_balancingFactor < 1.0) {
g_balancingFactor = 0.0;
}
}
}
+}
-#ifdef NOD_ENABLED
- // Setup newly observed domain globals
- setupNODGlobal();
-#endif /* NOD_ENABLED */
-
+static int initForks(Logr::log_t log)
+{
int forks = 0;
for (; forks < ::arg().asNum("processes") - 1; ++forks) {
- if (fork() == 0) // we are child
+ if (fork() == 0) { // we are child
break;
+ }
}
if (::arg().mustDo("daemon")) {
g_log.toConsole(Logger::Critical);
daemonize(log);
}
+
if (Utility::getpid() == 1) {
/* We are running as pid 1, register sigterm and sigint handler
signal(SIGUSR1, usr1Handler);
signal(SIGUSR2, usr2Handler);
signal(SIGPIPE, SIG_IGN); // NOLINT: Posix API
+ return forks;
+}
- checkOrFixFDS(log);
-
-#ifdef HAVE_LIBSODIUM
- if (sodium_init() == -1) {
- SLOG(g_log << Logger::Error << "Unable to initialize sodium crypto library" << endl,
- log->info(Logr::Error, "Unable to initialize sodium crypto library"));
- return 99;
+static int initPorts(Logr::log_t log)
+{
+ int port = ::arg().asNum("udp-source-port-min");
+ if (port < 1024 || port > 65535) {
+ SLOG(g_log << Logger::Error << "Unable to launch, udp-source-port-min is not a valid port number" << endl,
+ log->info(Logr::Error, "Unable to launch, udp-source-port-min is not a valid port number"));
+ return 99; // this isn't going to fix itself either
}
-#endif
-
- openssl_thread_setup();
- openssl_seed();
- /* setup rng before chroot */
- dns_random_init();
-
- if (::arg()["server-id"].empty()) {
- ::arg().set("server-id") = myHostname.has_value() ? *myHostname : "";
+ g_minUdpSourcePort = port;
+ port = ::arg().asNum("udp-source-port-max");
+ if (port < 1024 || port > 65535 || port < g_minUdpSourcePort) {
+ SLOG(g_log << Logger::Error << "Unable to launch, udp-source-port-max is not a valid port number or is smaller than udp-source-port-min" << endl,
+ log->info(Logr::Error, "Unable to launch, udp-source-port-max is not a valid port number or is smaller than udp-source-port-min"));
+ return 99; // this isn't going to fix itself either
}
-
- gid_t newgid = 0;
- if (!::arg()["setgid"].empty()) {
- newgid = strToGID(::arg()["setgid"]);
- }
- uid_t newuid = 0;
- if (!::arg()["setuid"].empty()) {
- newuid = strToUID(::arg()["setuid"]);
+ g_maxUdpSourcePort = port;
+ std::vector<string> parts{};
+ stringtok(parts, ::arg()["udp-source-port-avoid"], ", ");
+ for (const auto& part : parts) {
+ port = std::stoi(part);
+ if (port < 1024 || port > 65535) {
+ SLOG(g_log << Logger::Error << "Unable to launch, udp-source-port-avoid contains an invalid port number: " << part << endl,
+ log->info(Logr::Error, "Unable to launch, udp-source-port-avoid contains an invalid port number", "port", Logging::Loggable(part)));
+ return 99; // this isn't going to fix itself either
+ }
+ g_avoidUdpSourcePorts.insert(port);
}
+ return 0;
+}
- Utility::dropGroupPrivs(newuid, newgid);
+static void initSNMP([[maybe_unused]] Logr::log_t log)
+{
+ if (::arg().mustDo("snmp-agent")) {
+#ifdef HAVE_NET_SNMP
+ string setting = ::arg()["snmp-daemon-socket"];
+ if (setting.empty()) {
+ setting = ::arg()["snmp-master-socket"];
+ }
+ g_snmpAgent = std::make_shared<RecursorSNMPAgent>("recursor", setting);
+ g_snmpAgent->run();
+#else
+ const std::string msg = "snmp-agent set but SNMP support not compiled in";
+ SLOG(g_log << Logger::Error << msg << endl,
+ log->info(Logr::Error, msg));
+#endif // HAVE_NET_SNMP
+ }
+}
+static int initControl(Logr::log_t log, uid_t newuid, int forks) // NOLINT(bugprone-easily-swappable-parameter*)
+{
if (!::arg()["chroot"].empty()) {
#ifdef HAVE_SYSTEMD
char* ns;
SLOG(g_log << Logger::Warning << e.what() << endl,
log->error(Logr::Warning, e.what(), "Could not drop capabilities"));
}
+ return 0;
+}
+
+static void initSuffixMatchNodes()
+{
+ {
+ SuffixMatchNode dontThrottleNames;
+ vector<string> parts;
+ stringtok(parts, ::arg()["dont-throttle-names"], " ,");
+ for (const auto& part : parts) {
+ dontThrottleNames.add(DNSName(part));
+ }
+ g_dontThrottleNames.setState(std::move(dontThrottleNames));
+
+ parts.clear();
+ NetmaskGroup dontThrottleNetmasks;
+ stringtok(parts, ::arg()["dont-throttle-netmasks"], " ,");
+ for (const auto& part : parts) {
+ dontThrottleNetmasks.addMask(Netmask(part));
+ }
+ g_dontThrottleNetmasks.setState(std::move(dontThrottleNetmasks));
+ }
+
+ {
+ SuffixMatchNode xdnssecNames;
+ vector<string> parts;
+ stringtok(parts, ::arg()["x-dnssec-names"], " ,");
+ for (const auto& part : parts) {
+ xdnssecNames.add(DNSName(part));
+ }
+ g_xdnssec.setState(std::move(xdnssecNames));
+ }
+
+ {
+ SuffixMatchNode dotauthNames;
+ vector<string> parts;
+ stringtok(parts, ::arg()["dot-to-auth-names"], " ,");
+#ifndef HAVE_DNS_OVER_TLS
+ if (parts.size()) {
+ SLOG(g_log << Logger::Error << "dot-to-auth-names setting contains names, but Recursor was built without DNS over TLS support. Setting will be ignored." << endl,
+ log->info(Logr::Error, "dot-to-auth-names setting contains names, but Recursor was built without DNS over TLS support. Setting will be ignored"));
+ }
+#endif
+ for (const auto& part : parts) {
+ dotauthNames.add(DNSName(part));
+ }
+ g_DoTToAuthNames.setState(std::move(dotauthNames));
+ }
+}
+
+static void initCarbon()
+{
+ CarbonConfig config;
+ stringtok(config.servers, arg()["carbon-server"], ", ");
+ config.hostname = arg()["carbon-ourname"];
+ config.instance_name = arg()["carbon-instance"];
+ config.namespace_name = arg()["carbon-namespace"];
+ g_carbonConfig.setState(std::move(config));
+}
+
+static int initDNS64(Logr::log_t log)
+{
+ if (!::arg()["dns64-prefix"].empty()) {
+ try {
+ auto dns64Prefix = Netmask(::arg()["dns64-prefix"]);
+ if (dns64Prefix.getBits() != 96) {
+ SLOG(g_log << Logger::Error << "Invalid prefix for 'dns64-prefix', the current implementation only supports /96 prefixes: " << ::arg()["dns64-prefix"] << endl,
+ log->info(Logr::Error, "Invalid prefix for 'dns64-prefix', the current implementation only supports /96 prefixes", "prefix", Logging::Loggable(::arg()["dns64-prefix"])));
+ return 1;
+ }
+ g_dns64Prefix = dns64Prefix.getNetwork();
+ g_dns64PrefixReverse = reverseNameFromIP(*g_dns64Prefix);
+ /* /96 is 24 nibbles + 2 for "ip6.arpa." */
+ while (g_dns64PrefixReverse.countLabels() > 26) {
+ g_dns64PrefixReverse.chopOff();
+ }
+ }
+ catch (const NetmaskException& ne) {
+ SLOG(g_log << Logger::Error << "Invalid prefix '" << ::arg()["dns64-prefix"] << "' for 'dns64-prefix': " << ne.reason << endl,
+ log->info(Logr::Error, "Invalid prefix", "dns64-prefix", Logging::Loggable(::arg()["dns64-prefix"])));
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int serviceMain(Logr::log_t log)
+{
+ g_log.setName(g_programname);
+ g_log.disableSyslog(::arg().mustDo("disable-syslog"));
+ g_log.setTimestamps(::arg().mustDo("log-timestamp"));
+ g_regressionTestMode = ::arg().mustDo("devonly-regression-test-mode");
+
+ if (!::arg()["logging-facility"].empty()) {
+ int val = logFacilityToLOG(::arg().asNum("logging-facility"));
+ if (val >= 0) {
+ g_log.setFacility(val);
+ } else {
+ SLOG(g_log << Logger::Error << "Unknown logging facility " << ::arg().asNum("logging-facility") << endl,
+ log->info(Logr::Error, "Unknown logging facility", "facility", Logging::Loggable(::arg().asNum("logging-facility"))));
+ }
+ }
+
+ showProductVersion();
+
+ g_disthashseed = dns_random(0xffffffff);
+
+ int ret = initNet(log);
+ if (ret != 0) {
+ return ret;
+ }
+ // keep this ABOVE loadRecursorLuaConfig!
+ ret = initDNSSEC(log);
+ if (ret != 0) {
+ return ret;
+ }
+ g_maxCacheEntries = ::arg().asNum("max-cache-entries");
+
+ luaConfigDelayedThreads delayedLuaThreads;
+ try {
+ ProxyMapping proxyMapping;
+ loadRecursorLuaConfig(::arg()["lua-config-file"], delayedLuaThreads, proxyMapping);
+ // Initial proxy mapping
+ g_proxyMapping = proxyMapping.empty() ? nullptr : std::make_unique<ProxyMapping>(proxyMapping);
+ }
+ catch (PDNSException& e) {
+ SLOG(g_log << Logger::Error << "Cannot load Lua configuration: " << e.reason << endl,
+ log->error(Logr::Error, e.reason, "Cannot load Lua configuration"));
+ return 1;
+ }
+
+ parseACLs();
+ initPublicSuffixList(::arg()["public-suffix-list-file"]);
+
+ initDontQuery(log);
+
+ /* this needs to be done before parseACLs(), which call broadcastFunction() */
+ RecThreadInfo::setWeDistributeQueries(::arg().mustDo("pdns-distributes-queries"));
+ if (RecThreadInfo::weDistributeQueries()) {
+ SLOG(g_log << Logger::Warning << "PowerDNS Recursor itself will distribute queries over threads" << endl,
+ log->info(Logr::Notice, "PowerDNS Recursor itself will distribute queries over threads"));
+ }
+
+ g_outgoingEDNSBufsize = ::arg().asNum("edns-outgoing-bufsize");
+
+ if (::arg()["trace"] == "fail") {
+ SyncRes::setDefaultLogMode(SyncRes::Store);
+ }
+ else if (::arg().mustDo("trace")) {
+ SyncRes::setDefaultLogMode(SyncRes::Log);
+ ::arg().set("quiet") = "no";
+ g_quiet = false;
+ }
+ auto myHostname = getHostname();
+ if (!myHostname.has_value()) {
+ SLOG(g_log << Logger::Warning << "Unable to get the hostname, NSID and id.server values will be empty" << endl,
+ log->info(Logr::Warning, "Unable to get the hostname, NSID and id.server values will be empty"));
+ }
+
+ ret = initSyncRes(log, myHostname);
+ if (ret != 0) {
+ return ret;
+ }
+
+ g_proxyProtocolACL.toMasks(::arg()["proxy-protocol-from"]);
+ g_proxyProtocolMaximumSize = ::arg().asNum("proxy-protocol-maximum-size");
+
+ ret = initDNS64(log);
+ if (ret != 0) {
+ return ret;
+ }
+ g_networkTimeoutMsec = ::arg().asNum("network-timeout");
+
+ std::tie(g_initialDomainMap, g_initialAllowNotifyFor) = parseZoneConfiguration();
+
+ g_latencyStatSize = ::arg().asNum("latency-statistic-size");
+
+ g_logCommonErrors = ::arg().mustDo("log-common-errors");
+ g_logRPZChanges = ::arg().mustDo("log-rpz-changes");
+
+ g_anyToTcp = ::arg().mustDo("any-to-tcp");
+ g_udpTruncationThreshold = ::arg().asNum("udp-truncation-threshold");
+
+ g_lowercaseOutgoing = ::arg().mustDo("lowercase-outgoing");
+
+ g_paddingFrom.toMasks(::arg()["edns-padding-from"]);
+ if (::arg()["edns-padding-mode"] == "always") {
+ g_paddingMode = PaddingMode::Always;
+ }
+ else if (::arg()["edns-padding-mode"] == "padded-queries-only") {
+ g_paddingMode = PaddingMode::PaddedQueries;
+ }
+ else {
+ SLOG(g_log << Logger::Error << "Unknown edns-padding-mode: " << ::arg()["edns-padding-mode"] << endl,
+ log->info(Logr::Error, "Unknown edns-padding-mode", "edns-padding-mode", Logging::Loggable(::arg()["edns-padding-mode"])));
+ return 1;
+ }
+ g_paddingTag = ::arg().asNum("edns-padding-tag");
+ g_paddingOutgoing = ::arg().mustDo("edns-padding-out");
+
+ RecThreadInfo::setNumDistributorThreads(::arg().asNum("distributor-threads"));
+ RecThreadInfo::setNumWorkerThreads(::arg().asNum("threads"));
+ if (RecThreadInfo::numWorkers() < 1) {
+ SLOG(g_log << Logger::Warning << "Asked to run with 0 threads, raising to 1 instead" << endl,
+ log->info(Logr::Warning, "Asked to run with 0 threads, raising to 1 instead"));
+ RecThreadInfo::setNumWorkerThreads(1);
+ }
+
+ g_maxMThreads = ::arg().asNum("max-mthreads");
+
+ int64_t maxInFlight = ::arg().asNum("max-concurrent-requests-per-tcp-connection");
+ if (maxInFlight < 1 || maxInFlight > USHRT_MAX || maxInFlight >= g_maxMThreads) {
+ SLOG(g_log << Logger::Warning << "Asked to run with illegal max-concurrent-requests-per-tcp-connection, setting to default (10)" << endl,
+ log->info(Logr::Warning, "Asked to run with illegal max-concurrent-requests-per-tcp-connection, setting to default (10)"));
+ TCPConnection::s_maxInFlight = 10;
+ }
+ else {
+ TCPConnection::s_maxInFlight = maxInFlight;
+ }
+
+ int64_t millis = ::arg().asNum("tcp-out-max-idle-ms");
+ TCPOutConnectionManager::s_maxIdleTime = timeval{millis / 1000, (static_cast<suseconds_t>(millis) % 1000) * 1000};
+ TCPOutConnectionManager::s_maxIdlePerAuth = ::arg().asNum("tcp-out-max-idle-per-auth");
+ TCPOutConnectionManager::s_maxQueries = ::arg().asNum("tcp-out-max-queries");
+ TCPOutConnectionManager::s_maxIdlePerThread = ::arg().asNum("tcp-out-max-idle-per-thread");
+
+ g_gettagNeedsEDNSOptions = ::arg().mustDo("gettag-needs-edns-options");
+
+ s_statisticsInterval = ::arg().asNum("statistics-interval");
+
+ SyncRes::s_addExtendedResolutionDNSErrors = ::arg().mustDo("extended-resolution-errors");
+
+ if (::arg().asNum("aggressive-nsec-cache-size") > 0) {
+ if (g_dnssecmode == DNSSECMode::ValidateAll || g_dnssecmode == DNSSECMode::ValidateForLog || g_dnssecmode == DNSSECMode::Process) {
+ g_aggressiveNSECCache = make_unique<AggressiveNSECCache>(::arg().asNum("aggressive-nsec-cache-size"));
+ }
+ else {
+ SLOG(g_log << Logger::Warning << "Aggressive NSEC/NSEC3 caching is enabled but DNSSEC validation is not set to 'validate', 'log-fail' or 'process', ignoring" << endl,
+ log->info(Logr::Warning, "Aggressive NSEC/NSEC3 caching is enabled but DNSSEC validation is not set to 'validate', 'log-fail' or 'process', ignoring"));
+ }
+ }
+
+ AggressiveNSECCache::s_maxNSEC3CommonPrefix = static_cast<uint8_t>(std::round(std::log2(::arg().asNum("aggressive-cache-min-nsec3-hit-ratio"))));
+ SLOG(g_log << Logger::Debug << "NSEC3 aggressive cache tuning: aggressive-cache-min-nsec3-hit-ratio: " << ::arg().asNum("aggressive-cache-min-nsec3-hit-ratio") << " max common prefix bits: " << std::to_string(AggressiveNSECCache::s_maxNSEC3CommonPrefix) << endl,
+ log->info(Logr::Debug, "NSEC3 aggressive cache tuning", "aggressive-cache-min-nsec3-hit-ratio", Logging::Loggable(::arg().asNum("aggressive-cache-min-nsec3-hit-ratio")), "maxCommonPrefixBits", Logging::Loggable(AggressiveNSECCache::s_maxNSEC3CommonPrefix)));
+
+ initSuffixMatchNodes();
+ initCarbon();
+ initDistribution(log);
+
+#ifdef NOD_ENABLED
+ // Setup newly observed domain globals
+ setupNODGlobal();
+#endif /* NOD_ENABLED */
+
+ auto forks = initForks(log);
+
+ checkOrFixFDS(log);
+
+#ifdef HAVE_LIBSODIUM
+ if (sodium_init() == -1) {
+ SLOG(g_log << Logger::Error << "Unable to initialize sodium crypto library" << endl,
+ log->info(Logr::Error, "Unable to initialize sodium crypto library"));
+ return 99;
+ }
+#endif
+
+ openssl_thread_setup();
+ openssl_seed();
+ /* setup rng before chroot */
+ dns_random_init();
+
+ if (::arg()["server-id"].empty()) {
+ ::arg().set("server-id") = myHostname.has_value() ? *myHostname : "";
+ }
+
+ gid_t newgid = 0;
+ if (!::arg()["setgid"].empty()) {
+ newgid = strToGID(::arg()["setgid"]);
+ }
+ uid_t newuid = 0;
+ if (!::arg()["setuid"].empty()) {
+ newuid = strToUID(::arg()["setuid"]);
+ }
+
+ Utility::dropGroupPrivs(newuid, newgid);
+
+ ret = initControl(log, newuid, forks);
+ if (ret != 0) {
+ return ret;
+ }
startLuaConfigDelayedThreads(delayedLuaThreads, g_luaconfs.getCopy().generation);
delayedLuaThreads.rpzPrimaryThreads.clear(); // no longer needed
// Run before any thread doing stats related things
registerAllStats();
- if (::arg().mustDo("snmp-agent")) {
-#ifdef HAVE_NET_SNMP
- string setting = ::arg()["snmp-daemon-socket"];
- if (setting.empty()) {
- setting = ::arg()["snmp-master-socket"];
- }
- g_snmpAgent = std::make_shared<RecursorSNMPAgent>("recursor", setting);
- g_snmpAgent->run();
-#else
- const std::string msg = "snmp-agent set but SNMP support not compiled in";
- SLOG(g_log << Logger::Error << msg << endl,
- log->info(Logr::Error, msg));
-#endif // HAVE_NET_SNMP
- }
+ initSNMP(log);
- int port = ::arg().asNum("udp-source-port-min");
- if (port < 1024 || port > 65535) {
- SLOG(g_log << Logger::Error << "Unable to launch, udp-source-port-min is not a valid port number" << endl,
- log->info(Logr::Error, "Unable to launch, udp-source-port-min is not a valid port number"));
- return 99; // this isn't going to fix itself either
- }
- g_minUdpSourcePort = port;
- port = ::arg().asNum("udp-source-port-max");
- if (port < 1024 || port > 65535 || port < g_minUdpSourcePort) {
- SLOG(g_log << Logger::Error << "Unable to launch, udp-source-port-max is not a valid port number or is smaller than udp-source-port-min" << endl,
- log->info(Logr::Error, "Unable to launch, udp-source-port-max is not a valid port number or is smaller than udp-source-port-min"));
- return 99; // this isn't going to fix itself either
- }
- g_maxUdpSourcePort = port;
- std::vector<string> parts{};
- stringtok(parts, ::arg()["udp-source-port-avoid"], ", ");
- for (const auto& part : parts) {
- port = std::stoi(part);
- if (port < 1024 || port > 65535) {
- SLOG(g_log << Logger::Error << "Unable to launch, udp-source-port-avoid contains an invalid port number: " << part << endl,
- log->info(Logr::Error, "Unable to launch, udp-source-port-avoid contains an invalid port number", "port", Logging::Loggable(part)));
- return 99; // this isn't going to fix itself either
- }
- g_avoidUdpSourcePorts.insert(port);
+ ret = initPorts(log);
+ if (ret != 0) {
+ return ret;
}
return RecThreadInfo::runThreads(log);