From: Pieter Lexis Date: Wed, 17 Jan 2018 18:36:30 +0000 (+0100) Subject: ixfrdist: working UDP and TCP SOA queries and update thread X-Git-Tag: dnsdist-1.3.0~111^2~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=772cdea3e522cfdc3f0f9d4b04b191c2281fc178;p=thirdparty%2Fpdns.git ixfrdist: working UDP and TCP SOA queries and update thread --- diff --git a/pdns/ixfrdist.cc b/pdns/ixfrdist.cc index 30e9a12e43..dda8829d19 100644 --- a/pdns/ixfrdist.cc +++ b/pdns/ixfrdist.cc @@ -24,6 +24,7 @@ #endif #include #include +#include #include "ixfr.hh" #include "ixfrutils.hh" #include "resolver.hh" @@ -31,6 +32,7 @@ #include "sstuff.hh" #include "mplexer.hh" + /* BEGIN Needed because of deeper dependencies */ #include "arguments.hh" #include "statbag.hh" @@ -50,12 +52,17 @@ SelectFDMultiplexer g_fdm; // The domains we support set g_domains; +// Map domains to SOA Records and have a mutex to update it. +std::map> g_soas; +std::mutex g_soas_mutex; + using namespace boost::multi_index; namespace po = boost::program_options; po::variables_map g_vm; string g_workdir; ComboAddress g_master; + bool g_verbose = false; bool g_debug = false; @@ -64,8 +71,7 @@ void usage(po::options_description &desc) { cerr << desc << "\n"; } -void updateThread() { - std::map serials; +void* updateThread(void*) { std::map lastCheck; // Initialize the serials we have @@ -73,45 +79,55 @@ void updateThread() { lastCheck[domain] = 0; string dir = g_workdir + "/" + domain.toString(); try { - serials[domain] = getSerialsFromDir(dir); + auto serial = getSerialsFromDir(dir); + shared_ptr soa; + { + loadSOAFromDisk(domain, g_workdir + "/" + domain.toString() + "/" + std::to_string(serial), soa); + std::lock_guard guard(g_soas_mutex); + if (soa != nullptr) { + g_soas[domain] = soa; + } + } } catch (runtime_error &e) { // Most likely, the directory does not exist. cerr<<"[INFO] "< sr; + try { + auto newSerial = getSerialFromMaster(g_master, domain, sr); // TODO TSIG + if(g_soas.find(domain) != g_soas.end() && g_verbose) { + cerr<<"[INFO] Got SOA Serial: "<< newSerial<<", had Serial: "<d_st.serial< sr; - try { - auto newSerial = getSerialFromMaster(g_master, domain, sr); // TODO TSIG + if (g_soas.find(domain) != g_soas.end() && newSerial == g_soas[domain]->d_st.serial) { if (g_verbose) { - cerr<<"[INFO] Got SOA Serial: "<< newSerial<<", had Serial: "< soa; try { AXFRRetriever axfr(g_master, domain, tt, &local); unsigned int nrecords=0; @@ -132,77 +149,198 @@ void updateThread() { dr.d_name.makeUsRelative(domain); records.insert(dr); nrecords++; + if (dr.d_type == QType::SOA) { + soa = getRR(dr); + } } } if (g_verbose) { - cerr<<"[INFO] Done! Received "< guard(g_soas_mutex); + if (soa != nullptr) { + g_soas[domain] = soa; + } + } } /* for (const auto &domain : domains) */ sleep(10); } /* while (true) */ } /* updateThread */ +bool checkQuery(const MOADNSParser& mdp, const ComboAddress& saddr, const bool udp = true) { + vector info_msg; + + if (g_debug) { + cerr<<"[DEBUG] Had "< makeSOAPacket(const MOADNSParser& mdp) { + vector packet; + DNSPacketWriter pw(packet, mdp.d_qname, mdp.d_qtype); + pw.getHeader()->id = mdp.d_header.id; + pw.getHeader()->rd = mdp.d_header.rd; + pw.getHeader()->qr = 1; + + pw.startRecord(mdp.d_qname, QType::SOA); + g_soas[mdp.d_qname]->toPacket(pw); + pw.commit(); + + return packet; +} + + void handleUDPRequest(int fd, boost::any&) { // TODO make the buffer-size configurable char buf[4096]; - struct sockaddr saddr; + ComboAddress saddr; socklen_t fromlen; - int res = recvfrom(fd, buf, sizeof(buf), 0, &saddr, &fromlen); - ComboAddress from(&saddr, fromlen); + int res = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr*) &saddr, &fromlen); if (res == 0) { - cerr<<"[Warning] Got an empty message from "< info_msg; + if (!checkQuery(mdp, saddr)) { + return; + } - if (g_debug) { - cerr<<"[Debug] Had "< packet; + if (mdp.d_qtype == QType::SOA) { + packet = makeSOAPacket(mdp); + } + + char buf[2]; + buf[0]=packet.size()/256; + buf[1]=packet.size()%256; + + int send = writen2(cfd, buf, 2); + send += writen2(cfd, &packet[0], packet.size()); + shutdown(cfd, 2); + } catch (MOADNSException &e) { + cerr<<"[WARNING] Could not parse DNS packet from "<(), 53); } catch(PDNSException &e) { - cerr<<"[Error] server-address '"<()<<"' is not an IP address: "<()<<"' is not an IP address: "<& soa) +{ + ZoneParserTNG zpt(fname, zone); + DNSResourceRecord rr; + + while(zpt.get(rr)) { + if (rr.qtype == QType::SOA) { + soa = getRR(DNSRecord(rr)); + return; + } + } +} diff --git a/pdns/ixfrutils.hh b/pdns/ixfrutils.hh index 201089cba6..f787f6dde4 100644 --- a/pdns/ixfrutils.hh +++ b/pdns/ixfrutils.hh @@ -54,3 +54,4 @@ uint32_t getSerialsFromDir(const std::string& dir); uint32_t getSerialFromRecords(const records_t& records, DNSRecord& soaret); void writeZoneToDisk(const records_t& records, const DNSName& zone, const std::string& directory); void loadZoneFromDisk(records_t& records, const string& fname, const DNSName& zone); +void loadSOAFromDisk(const DNSName& zone, const string& fname, shared_ptr& soa);