"Fossies" - the Fresh Open Source Software Archive

Member "pdns-auth-4.2.0/pdns/stubresolver.cc" (27 Aug 2019, 4751 Bytes) of package /linux/misc/dns/pdns-auth-4.2.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "stubresolver.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.1.13_vs_4.2.0.

    1 #include <sys/stat.h>
    2 
    3 #ifdef HAVE_CONFIG_H
    4 #include "config.h"
    5 #endif
    6 
    7 #include "logger.hh"
    8 #include "arguments.hh"
    9 #include "version.hh"
   10 #include "misc.hh"
   11 
   12 #include "sstuff.hh"
   13 #include "dnswriter.hh"
   14 #include "dns_random.hh"
   15 #include "namespaces.hh"
   16 #include "statbag.hh"
   17 #include "stubresolver.hh"
   18 
   19 #define LOCAL_RESOLV_CONF_PATH "/etc/resolv.conf"
   20 // don't stat() for local resolv.conf more than once every INTERVAL secs.
   21 #define LOCAL_RESOLV_CONF_MAX_CHECK_INTERVAL 60
   22 
   23 // s_resolversForStub contains the ComboAddresses that are used by
   24 // stubDoResolve
   25 static vector<ComboAddress> s_resolversForStub;
   26 static pthread_rwlock_t s_resolversForStubLock = PTHREAD_RWLOCK_INITIALIZER;
   27 static bool s_stubResolvConfigured = false;
   28 
   29 // /etc/resolv.conf last modification time
   30 static time_t s_localResolvConfMtime = 0;
   31 static time_t s_localResolvConfLastCheck = 0;
   32 
   33 /*
   34  * Returns false if no resolvers are configured, while emitting a warning about this
   35  */
   36 bool resolversDefined()
   37 {
   38   ReadLock l(&s_resolversForStubLock);
   39   if (s_resolversForStub.empty()) {
   40     g_log<<Logger::Warning<<"No upstream resolvers configured, stub resolving (including secpoll and ALIAS) impossible."<<endl;
   41     return false;
   42   }
   43   return true;
   44 }
   45 
   46 /*
   47  * Parse /etc/resolv.conf and add those nameservers to s_resolversForStub
   48  */
   49 static void parseLocalResolvConf_locked(const time_t& now)
   50 {
   51   struct stat st;
   52   s_localResolvConfLastCheck = now;
   53 
   54   if (stat(LOCAL_RESOLV_CONF_PATH, &st) != -1) {
   55     if (st.st_mtime != s_localResolvConfMtime) {
   56       std::vector<ComboAddress> resolvers = getResolvers(LOCAL_RESOLV_CONF_PATH);
   57 
   58       s_localResolvConfMtime = st.st_mtime;
   59 
   60       if (resolvers.empty()) {
   61         return;
   62       }
   63 
   64       s_resolversForStub = std::move(resolvers);
   65     }
   66   }
   67 }
   68 
   69 static void parseLocalResolvConf()
   70 {
   71   const time_t now = time(nullptr);
   72   if ((s_localResolvConfLastCheck + LOCAL_RESOLV_CONF_MAX_CHECK_INTERVAL) > now)
   73     return ;
   74 
   75   WriteLock wl(&s_resolversForStubLock);
   76   parseLocalResolvConf_locked(now);
   77 }
   78 
   79 
   80 /*
   81  * Fill the s_resolversForStub vector with addresses for the upstream resolvers.
   82  * First, parse the `resolver` configuration option for IP addresses to use.
   83  * If that doesn't work, parse /etc/resolv.conf and add those nameservers to
   84  * s_resolversForStub.
   85  *
   86  * mainthread() calls this so you don't have to.
   87  */
   88 void stubParseResolveConf()
   89 {
   90   if(::arg().mustDo("resolver")) {
   91     WriteLock wl(&s_resolversForStubLock);
   92     vector<string> parts;
   93     stringtok(parts, ::arg()["resolver"], " ,\t");
   94     for (const auto& addr : parts)
   95       s_resolversForStub.push_back(ComboAddress(addr, 53));
   96   }
   97 
   98   if (s_resolversForStub.empty()) {
   99     parseLocalResolvConf();
  100   }
  101   // Emit a warning if there are no stubs.
  102   resolversDefined();
  103   s_stubResolvConfigured = true;
  104 }
  105 
  106 // s_resolversForStub contains the ComboAddresses that are used to resolve the
  107 int stubDoResolve(const DNSName& qname, uint16_t qtype, vector<DNSZoneRecord>& ret)
  108 {
  109   // ensure resolver gets always configured
  110   if (!s_stubResolvConfigured) {
  111     stubParseResolveConf();
  112   }
  113   // only check if resolvers come from local resolv.conf in the first place
  114   if (s_localResolvConfMtime != 0) {
  115         parseLocalResolvConf();
  116   }
  117   if (!resolversDefined())
  118     return RCode::ServFail;
  119 
  120   ReadLock l(&s_resolversForStubLock);
  121   vector<uint8_t> packet;
  122 
  123   DNSPacketWriter pw(packet, qname, qtype);
  124   pw.getHeader()->id=dns_random(0xffff);
  125   pw.getHeader()->rd=1;
  126 
  127   string msg ="Doing stub resolving, using resolvers: ";
  128   for (const auto& server : s_resolversForStub) {
  129     msg += server.toString() + ", ";
  130   }
  131   g_log<<Logger::Debug<<msg.substr(0, msg.length() - 2)<<endl;
  132 
  133   for(const ComboAddress& dest :  s_resolversForStub) {
  134     Socket sock(dest.sin4.sin_family, SOCK_DGRAM);
  135     sock.setNonBlocking();
  136     sock.connect(dest);
  137     sock.send(string(packet.begin(), packet.end()));
  138 
  139     string reply;
  140 
  141     waitForData(sock.getHandle(), 2, 0);
  142     try {
  143     retry:
  144       sock.read(reply); // this calls recv
  145       if(reply.size() > sizeof(struct dnsheader)) {
  146         struct dnsheader d;
  147         memcpy(&d, reply.c_str(), sizeof(d));
  148         if(d.id != pw.getHeader()->id)
  149           goto retry;
  150       }
  151     }
  152     catch(...) {
  153       continue;
  154     }
  155     MOADNSParser mdp(false, reply);
  156     if(mdp.d_header.rcode == RCode::ServFail)
  157       continue;
  158 
  159     for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
  160       if(i->first.d_place == 1 && i->first.d_type==qtype) {
  161         DNSZoneRecord zrr;
  162         zrr.dr = i->first;
  163         zrr.auth=true;
  164         ret.push_back(zrr);
  165       }
  166     }
  167     g_log<<Logger::Debug<<"Question got answered by "<<dest.toString()<<endl;
  168     return mdp.d_header.rcode;
  169   }
  170   return RCode::ServFail;
  171 }