From: Aki Tuomi Date: Wed, 30 Oct 2013 12:16:04 +0000 (+0200) Subject: Load AXFR-SOURCE when provided for domains X-Git-Tag: rec-3.6.0-rc1~339^2~5 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=95302209cc43d35ce471f9263057792f8096d4a3;p=pdns Load AXFR-SOURCE when provided for domains --- diff --git a/modules/tinydnsbackend/data b/modules/tinydnsbackend/data index 53daee570..357a06b6f 100644 --- a/modules/tinydnsbackend/data +++ b/modules/tinydnsbackend/data @@ -20262,3 +20262,7 @@ Zminimal.com:ns1.example.com.:ahu.example.com.:2000081501:28800:7200:604800:8640 Ztsig.com:ns1.example.com.:ahu.example.com.:2000081501:28800:7200:604800:86400:120 &tsig.com::ns1.example.com.:120 &tsig.com::ns2.example.com.:120 +#2000081501 auto axfr-get +Zstest.com:ns1.example.com.:ahu.example.com.:2000081501:28800:7200:604800:86400:120 +&stest.com::ns1.example.com.:120 +&stest.com::ns2.example.com.:120 diff --git a/modules/tinydnsbackend/data.cdb b/modules/tinydnsbackend/data.cdb index 31341c202..9b76b88f1 100644 Binary files a/modules/tinydnsbackend/data.cdb and b/modules/tinydnsbackend/data.cdb differ diff --git a/pdns/resolver.cc b/pdns/resolver.cc index e18ac2541..fbf9fae5f 100644 --- a/pdns/resolver.cc +++ b/pdns/resolver.cc @@ -88,28 +88,27 @@ int makeQuerySocket(const ComboAddress& local, bool udpOrTCP) Resolver::Resolver() try { - d_sock4 = d_sock6 = 0; - d_sock4 = makeQuerySocket(ComboAddress(::arg()["query-local-address"]), true); + locals["default4"] = makeQuerySocket(ComboAddress(::arg()["query-local-address"]), true); if(!::arg()["query-local-address6"].empty()) - d_sock6 = makeQuerySocket(ComboAddress(::arg()["query-local-address6"]), true); + locals["default6"] = makeQuerySocket(ComboAddress(::arg()["query-local-address6"]), true); else - d_sock6 = -1; + locals["default6"] = -1; } catch(...) { - if(d_sock4>=0) - close(d_sock4); + if(locals["default4"]>=0) + close(locals["default4"]); throw; } Resolver::~Resolver() { - if(d_sock4>=0) - Utility::closesocket(d_sock4); - if(d_sock6>=0) - Utility::closesocket(d_sock6); + for(std::map::iterator iter = locals.begin(); iter != locals.end(); iter++) { + close(iter->second); + } } -uint16_t Resolver::sendResolve(const ComboAddress& remote, const char *domain, int type, bool dnssecOK, +uint16_t Resolver::sendResolve(const ComboAddress& remote, const ComboAddress& local, + const char *domain, int type, bool dnssecOK, const string& tsigkeyname, const string& tsigalgorithm, const string& tsigsecret) { @@ -136,8 +135,26 @@ uint16_t Resolver::sendResolve(const ComboAddress& remote, const char *domain, i trc.d_eRcode=0; addTSIG(pw, &trc, tsigkeyname, tsigsecret, "", false); } - - int sock = remote.sin4.sin_family == AF_INET ? d_sock4 : d_sock6; + + int sock; + + // choose socket based on local + if (local.sin4.sin_family == 0) { + // up to us. + sock = remote.sin4.sin_family == AF_INET ? locals["default4"] : locals["default6"]; + } else { + std::string lstr = local.toString(); + std::map::iterator lptr; + // see if there is a local + + if ((lptr = locals.find(lstr)) != locals.end()) { + sock = lptr->second; + } else { + // try to make socket + sock = makeQuerySocket(local, true); + locals[lstr] = sock; + } + } if(sendto(sock, &packet[0], packet.size(), 0, (struct sockaddr*)(&remote), remote.getSocklen()) < 0) { throw ResolverException("Unable to ask query of "+remote.toStringWithPort()+": "+stringerror()); @@ -145,6 +162,16 @@ uint16_t Resolver::sendResolve(const ComboAddress& remote, const char *domain, i return randomid; } +uint16_t Resolver::sendResolve(const ComboAddress& remote, const char *domain, + int type, bool dnssecOK, + const string& tsigkeyname, const string& tsigalgorithm, + const string& tsigsecret) +{ + ComboAddress local; + local.sin4.sin_family = 0; + return this->sendResolve(remote, local, domain, type, dnssecOK, tsigkeyname, tsigalgorithm, tsigsecret); +} + static int parseResult(MOADNSParser& mdp, const std::string& origQname, uint16_t origQtype, uint16_t id, Resolver::res_t* result) { result->clear(); @@ -203,13 +230,34 @@ static int parseResult(MOADNSParser& mdp, const std::string& origQname, uint16_t bool Resolver::tryGetSOASerial(string* domain, uint32_t *theirSerial, uint32_t *theirInception, uint32_t *theirExpire, uint16_t* id) { - Utility::setNonBlocking( d_sock4 ); - Utility::setNonBlocking( d_sock6 ); - + struct pollfd *fds = new struct pollfd[locals.size()]; + size_t i = 0, k; int sock; - if(!waitFor2Data(d_sock4, d_sock6, 0, 250000, &sock)) // lame function, I know.. - return false; - + + for(std::map::iterator iter=locals.begin(); iter != locals.end(); iter++, i++) { + fds[i].fd = iter->second; + fds[i].events = POLLIN; + } + + if (poll(fds, i, 250) < 1) { // wait for 0.25s + delete [] fds; + return false; + } + + sock = -1; + + // determine who + for(k=0;k::iterator lptr; + // see if there is a local + + if ((lptr = locals.find(lstr)) != locals.end()) sock = lptr->second; + else throw ResolverException("sendResolve did not create socket for " + lstr); + } + int err=waitForData(sock, 0, 3000000); if(!err) { @@ -285,7 +347,11 @@ int Resolver::resolve(const string &ipport, const char *domain, int type, Resolv return -1; } - +int Resolver::resolve(const string &ipport, const char *domain, int type, Resolver::res_t* res) { + ComboAddress local; + local.sin4.sin_family = 0; + return resolve(ipport, domain, type, res, local); +} void Resolver::getSoaSerial(const string &ipport, const string &domain, uint32_t *serial) { diff --git a/pdns/resolver.hh b/pdns/resolver.hh index c917543c3..d74c03df9 100644 --- a/pdns/resolver.hh +++ b/pdns/resolver.hh @@ -56,12 +56,17 @@ public: typedef vector res_t; //! synchronously resolve domain|type at IP, store result in result, rcode in ret + int resolve(const string &ip, const char *domain, int type, res_t* result, const ComboAddress& local); + int resolve(const string &ip, const char *domain, int type, res_t* result); - + //! only send out a resolution request + uint16_t sendResolve(const ComboAddress& remote, const ComboAddress& local, const char *domain, int type, bool dnssecOk=false, + const string& tsigkeyname="", const string& tsigalgorithm="", const string& tsigsecret=""); + uint16_t sendResolve(const ComboAddress& remote, const char *domain, int type, bool dnssecOk=false, const string& tsigkeyname="", const string& tsigalgorithm="", const string& tsigsecret=""); - + //! see if we got a SOA response from our sendResolve bool tryGetSOASerial(string* theirDomain, uint32_t* theirSerial, uint32_t* theirInception, uint32_t* theirExpire, uint16_t* id); @@ -69,8 +74,8 @@ public: void getSoaSerial(const string &, const string &, uint32_t *); private: - int d_sock4, d_sock6; - + std::map locals; + uint16_t d_randomid; }; diff --git a/pdns/slavecommunicator.cc b/pdns/slavecommunicator.cc index 8223b06c0..14f0cad44 100644 --- a/pdns/slavecommunicator.cc +++ b/pdns/slavecommunicator.cc @@ -393,6 +393,7 @@ struct DomainNotificationInfo { DomainInfo di; bool dnssecOk; + ComboAddress localaddr; string tsigkeyname, tsigalgname, tsigsecret; }; } @@ -423,12 +424,21 @@ struct SlaveSenderReceiver random_shuffle(dni.di.masters.begin(), dni.di.masters.end()); try { ComboAddress remote(*dni.di.masters.begin()); - return make_pair(dni.di.zone, - d_resolver.sendResolve(ComboAddress(*dni.di.masters.begin(), 53), - dni.di.zone.c_str(), - QType::SOA, - dni.dnssecOk, dni.tsigkeyname, dni.tsigalgname, dni.tsigsecret) - ); + if (dni.localaddr.sin4.sin_family == 0) { + return make_pair(dni.di.zone, + d_resolver.sendResolve(ComboAddress(*dni.di.masters.begin(), 53), + dni.di.zone.c_str(), + QType::SOA, + dni.dnssecOk, dni.tsigkeyname, dni.tsigalgname, dni.tsigsecret) + ); + } else { + return make_pair(dni.di.zone, + d_resolver.sendResolve(ComboAddress(*dni.di.masters.begin(), 53), dni.localaddr, + dni.di.zone.c_str(), + QType::SOA, + dni.dnssecOk, dni.tsigkeyname, dni.tsigalgname, dni.tsigsecret) + ); + } } catch(PDNSException& e) { throw runtime_error("While attempting to query freshness of '"+dni.di.zone+"': "+e.reason); @@ -504,6 +514,7 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P) domains_by_name_t& nameindex=boost::multi_index::get(d_suckdomains); BOOST_FOREACH(DomainInfo& di, rdomains) { + std::vector localaddr; SuckRequest sr; sr.domain=di.zone; if(di.masters.empty()) // slave domains w/o masters are ignored @@ -522,6 +533,22 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P) B->getTSIGKey(dni.tsigkeyname, &dni.tsigalgname, &secret64); B64Decode(secret64, dni.tsigsecret); } + + localaddr.clear(); + // check for AXFR-SOURCE + if(B->getDomainMetadata(di.zone, "AXFR-SOURCE", localaddr) && !localaddr.empty()) { + try { + dni.localaddr = ComboAddress(localaddr[0]); + L<