From: Charles-Henri Bruyand Date: Tue, 13 Mar 2018 18:08:22 +0000 (+0000) Subject: Auth: Reload /etc/resolv.conf when modified. Fix #6263 X-Git-Tag: dnsdist-1.3.0~40^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9cc98a196692860769de0bc3eee5fb520c95563f;p=thirdparty%2Fpdns.git Auth: Reload /etc/resolv.conf when modified. Fix #6263 --- diff --git a/pdns/stubresolver.cc b/pdns/stubresolver.cc index ab15434b2d..c07cd746af 100644 --- a/pdns/stubresolver.cc +++ b/pdns/stubresolver.cc @@ -1,3 +1,5 @@ +#include + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -14,9 +16,15 @@ #include "statbag.hh" #include "stubresolver.hh" +#define LOCAL_RESOLV_CONF_PATH "/etc/resolv.conf" + // s_resolversForStub contains the ComboAddresses that are used by // stubDoResolve static vector s_resolversForStub; +static pthread_mutex_t s_resolversForStubLock = PTHREAD_MUTEX_INITIALIZER; + +// /etc/resolv.conf last modification time +static auto s_localResolvConfMtime = 0; /* * Returns false if no resolvers are configured, while emitting a warning about this @@ -30,6 +38,47 @@ bool resolversDefined() return true; } +/* + * Parse /etc/resolv.conf and add those nameservers to s_resolversForStub + */ +static void parseLocalResolvConf() +{ + ifstream ifs(LOCAL_RESOLV_CONF_PATH); + struct stat st; + string line; + + if(!ifs) + return; + if (stat(LOCAL_RESOLV_CONF_PATH, &st) == -1) + return ; + s_localResolvConfMtime = st.st_mtime; + + pthread_mutex_lock(&s_resolversForStubLock); + s_resolversForStub.clear(); + while(std::getline(ifs, line)) { + boost::trim_right_if(line, is_any_of(" \r\n\x1a")); + boost::trim_left(line); // leading spaces, let's be nice + + string::size_type tpos = line.find_first_of(";#"); + if(tpos != string::npos) + line.resize(tpos); + + if(boost::starts_with(line, "nameserver ") || boost::starts_with(line, "nameserver\t")) { + vector parts; + stringtok(parts, line, " \t,"); // be REALLY nice + for(vector::const_iterator iter = parts.begin()+1; iter != parts.end(); ++iter) { + try { + s_resolversForStub.push_back(ComboAddress(*iter, 53)); + } + catch(...) + { + } + } + } + } + pthread_mutex_unlock(&s_resolversForStubLock); +} + /* * Fill the s_resolversForStub vector with addresses for the upstream resolvers. * First, parse the `resolver` configuration option for IP addresses to use. @@ -46,32 +95,7 @@ void stubParseResolveConf() } if (s_resolversForStub.empty()) { - ifstream ifs("/etc/resolv.conf"); - if(!ifs) - return; - - string line; - while(std::getline(ifs, line)) { - boost::trim_right_if(line, is_any_of(" \r\n\x1a")); - boost::trim_left(line); // leading spaces, let's be nice - - string::size_type tpos = line.find_first_of(";#"); - if(tpos != string::npos) - line.resize(tpos); - - if(boost::starts_with(line, "nameserver ") || boost::starts_with(line, "nameserver\t")) { - vector parts; - stringtok(parts, line, " \t,"); // be REALLY nice - for(vector::const_iterator iter = parts.begin()+1; iter != parts.end(); ++iter) { - try { - s_resolversForStub.push_back(ComboAddress(*iter, 53)); - } - catch(...) - { - } - } - } - } + parseLocalResolvConf(); } // Emit a warning if there are no stubs. resolversDefined(); @@ -80,6 +104,16 @@ void stubParseResolveConf() // s_resolversForStub contains the ComboAddresses that are used to resolve the int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& ret) { + // only check if resolvers come from he local resolv.conf in the first place + if (s_localResolvConfMtime != 0) { + struct stat st; + + if (stat(LOCAL_RESOLV_CONF_PATH, &st) != -1) { + if (st.st_mtime > s_localResolvConfMtime) { + parseLocalResolvConf(); + } + } + } if (!resolversDefined()) return RCode::ServFail;