From: Pieter Lexis Date: Tue, 9 Feb 2021 16:08:44 +0000 (+0100) Subject: SVCB: Lookup IP auto hints on response and XFR X-Git-Tag: dnsdist-1.6.0-rc1~33^2~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bdbee3776b1637caf7026e6c011d272a03d77c1a;p=thirdparty%2Fpdns.git SVCB: Lookup IP auto hints on response and XFR --- diff --git a/pdns/dnspacket.cc b/pdns/dnspacket.cc index d1707aa990..705956c2f5 100644 --- a/pdns/dnspacket.cc +++ b/pdns/dnspacket.cc @@ -160,6 +160,19 @@ vector DNSPacket::getAPRecords() return arrs; } +vector DNSPacket::getServiceRecords() +{ + vector arrs; + + for(auto & i : d_rrs) { + if (i.dr.d_type==QType::SVCB || + i.dr.d_type==QType::HTTPS) { + arrs.push_back(&i); + } + } + return arrs; +} + vector DNSPacket::getAnswerRecords() { vector arrs; diff --git a/pdns/dnspacket.hh b/pdns/dnspacket.hh index 86ef68b731..4456847d6d 100644 --- a/pdns/dnspacket.hh +++ b/pdns/dnspacket.hh @@ -109,6 +109,7 @@ public: vector getAPRecords(); //!< get a vector with DNSZoneRecords that need additional processing vector getAnswerRecords(); //!< get a vector with DNSZoneRecords that are answers + vector getServiceRecords(); //!< Get a vector with all Service-style (SVCB) records void setCompress(bool compress); std::unique_ptr replyPacket() const; //!< convenience function that creates a virgin answer packet to this question diff --git a/pdns/dnsrecords.cc b/pdns/dnsrecords.cc index fa267e4b33..995aef5fdd 100644 --- a/pdns/dnsrecords.cc +++ b/pdns/dnsrecords.cc @@ -749,6 +749,17 @@ void SVCBBaseRecordContent::setHints(const SvcParam::SvcParamKey &key, const std } } +void SVCBBaseRecordContent::removeParam(const SvcParam::SvcParamKey &key) { + auto p = std::find_if(d_params.begin(), d_params.end(), + [&key](const SvcParam ¶m) { + return param.getKey() == key; + }); + if (p == d_params.end()) { + return; + } + d_params.erase(p); +} + /* SVCB end */ boilerplate_conv(TKEY, diff --git a/pdns/dnsrecords.hh b/pdns/dnsrecords.hh index bafe372989..963663d5e6 100644 --- a/pdns/dnsrecords.hh +++ b/pdns/dnsrecords.hh @@ -506,6 +506,8 @@ class SVCBBaseRecordContent : public DNSRecordContent bool autoHint(const SvcParam::SvcParamKey &key) const; // Sets the |addresses| to the existing hints for |key| void setHints(const SvcParam::SvcParamKey &key, const std::vector &addresses); + // Removes the parameter for |key| from d_params + void removeParam(const SvcParam::SvcParamKey &key); protected: uint16_t d_priority; diff --git a/pdns/packethandler.cc b/pdns/packethandler.cc index ee45ff65be..00f8900b1c 100644 --- a/pdns/packethandler.cc +++ b/pdns/packethandler.cc @@ -522,6 +522,41 @@ void PacketHandler::doAdditionalProcessing(DNSPacket& p, std::unique_ptrgetServiceRecords()) { + // Process auto hints + auto rrc = getRR(rec->dr); + DNSName target = rrc->getTarget().isRoot() ? rec->dr.d_name : rrc->getTarget(); + if (rrc->autoHint(SvcParam::ipv4hint)) { + B.lookup(QType::A, target, d_sd.domain_id); + vector hints; + DNSZoneRecord rr; + while (B.get(rr)) { + auto arrc = getRR(rr.dr); + hints.push_back(arrc->getCA()); + } + if (hints.size() == 0) { + rrc->removeParam(SvcParam::ipv4hint); + } else { + rrc->setHints(SvcParam::ipv4hint, hints); + } + } + + if (rrc->autoHint(SvcParam::ipv6hint)) { + B.lookup(QType::AAAA, target, d_sd.domain_id); + vector hints; + DNSZoneRecord rr; + while (B.get(rr)) { + auto arrc = getRR(rr.dr); + hints.push_back(arrc->getCA()); + } + if (hints.size() == 0) { + rrc->removeParam(SvcParam::ipv6hint); + } else { + rrc->setHints(SvcParam::ipv6hint, hints); + } + } + } DNSZoneRecord dzr; for(const auto& name : lookup) { diff --git a/pdns/tcpreceiver.cc b/pdns/tcpreceiver.cc index 3fefed1413..7110f5b135 100644 --- a/pdns/tcpreceiver.cc +++ b/pdns/tcpreceiver.cc @@ -726,6 +726,47 @@ int TCPNameserver::doAXFR(const DNSName &target, std::unique_ptr& q, } } + for (auto loopRR : zrrs) { + if ((loopRR.dr.d_type == QType::SVCB || loopRR.dr.d_type == QType::HTTPS)) { + // Process auto hints + // TODO this is an almost copy of the code in the packethandler + auto rrc = getRR(loopRR.dr); + if (rrc == nullptr) { + continue; + } + DNSName svcTarget = rrc->getTarget().isRoot() ? loopRR.dr.d_name : rrc->getTarget(); + if (rrc->autoHint(SvcParam::ipv4hint)) { + sd.db->lookup(QType::A, svcTarget, sd.domain_id); + vector hints; + DNSZoneRecord rr; + while (sd.db->get(rr)) { + auto arrc = getRR(rr.dr); + hints.push_back(arrc->getCA()); + } + if (hints.size() == 0) { + rrc->removeParam(SvcParam::ipv4hint); + } else { + rrc->setHints(SvcParam::ipv4hint, hints); + } + } + + if (rrc->autoHint(SvcParam::ipv6hint)) { + sd.db->lookup(QType::AAAA, svcTarget, sd.domain_id); + vector hints; + DNSZoneRecord rr; + while (sd.db->get(rr)) { + auto arrc = getRR(rr.dr); + hints.push_back(arrc->getCA()); + } + if (hints.size() == 0) { + rrc->removeParam(SvcParam::ipv6hint); + } else { + rrc->setHints(SvcParam::ipv6hint, hints); + } + } + } + } + // Group records by name and type, signpipe stumbles over interrupted rrsets if(securedZone && !presignedZone) { sort(zrrs.begin(), zrrs.end(), [](const DNSZoneRecord& a, const DNSZoneRecord& b) {