diff --git a/pdns/dnsrecords.cc b/pdns/dnsrecords.cc index 475f12cfa50e..e2212e36cd69 100644 --- a/pdns/dnsrecords.cc +++ b/pdns/dnsrecords.cc @@ -341,7 +341,7 @@ boilerplate_conv(SVCB, conv.xfr16BitInt(d_priority); conv.xfrName(d_target, false, true); if (d_priority != 0) { - conv.xfrSvcParamKeyVals(*d_params.lock()); + conv.xfrSvcParamKeyVals(d_params); } ) @@ -349,7 +349,7 @@ boilerplate_conv(HTTPS, conv.xfr16BitInt(d_priority); conv.xfrName(d_target, false, true); if (d_priority != 0) { - conv.xfrSvcParamKeyVals(*d_params.lock()); + conv.xfrSvcParamKeyVals(d_params); } ) @@ -747,29 +747,28 @@ string APLRecordContent::getZoneRepresentation(bool /* noDot */) const { /* APL end */ /* SVCB start */ -bool SVCBBaseRecordContent::autoHint(const SvcParam::SvcParamKey &key) { - auto params = d_params.lock(); - auto p = getParamIt(key, *params); - if (p == params->end()) { +bool SVCBBaseRecordContent::autoHint(const SvcParam::SvcParamKey &key) const { + auto p = getParamIt(key); + if (p == d_params.end()) { return false; } return p->getAutoHint(); } void SVCBBaseRecordContent::setHints(const SvcParam::SvcParamKey &key, const std::vector &addresses) { + auto p = getParamIt(key); + if (p == d_params.end()) { + return; + } + std::vector h; h.reserve(h.size() + addresses.size()); h.insert(h.end(), addresses.begin(), addresses.end()); - auto params = d_params.lock(); - auto p = getParamIt(key, *params); - if (p == params->end()) { - return; - } try { auto newParam = SvcParam(key, std::move(h)); - params->erase(p); - params->insert(newParam); + d_params.erase(p); + d_params.insert(newParam); } catch (...) { // XXX maybe we should SERVFAIL instead? return; @@ -777,40 +776,47 @@ void SVCBBaseRecordContent::setHints(const SvcParam::SvcParamKey &key, const std } void SVCBBaseRecordContent::removeParam(const SvcParam::SvcParamKey &key) { - auto params = d_params.lock(); - auto p = getParamIt(key, *params); - if (p == params->end()) { + auto p = getParamIt(key); + if (p == d_params.end()) { return; } - params->erase(p); + d_params.erase(p); } -bool SVCBBaseRecordContent::hasParams() { - return !d_params.lock()->empty(); +bool SVCBBaseRecordContent::hasParams() const { + return !d_params.empty(); } -bool SVCBBaseRecordContent::hasParam(const SvcParam::SvcParamKey &key) { - auto params = d_params.lock(); - return getParamIt(key, *params) != params->end(); +bool SVCBBaseRecordContent::hasParam(const SvcParam::SvcParamKey &key) const { + return getParamIt(key) != d_params.end(); } -SvcParam SVCBBaseRecordContent::getParam(const SvcParam::SvcParamKey &key) { - auto params = d_params.lock(); - auto p = getParamIt(key, *params); - if (p == params->end()) { +SvcParam SVCBBaseRecordContent::getParam(const SvcParam::SvcParamKey &key) const { + auto p = getParamIt(key); + if (p == d_params.end()) { throw std::out_of_range("No param with key " + SvcParam::keyToString(key)); } return *p; } -set::const_iterator SVCBBaseRecordContent::getParamIt(const SvcParam::SvcParamKey &key, std::set& params) { - auto p = std::find_if(params.begin(), params.end(), +set::const_iterator SVCBBaseRecordContent::getParamIt(const SvcParam::SvcParamKey &key) const { + auto p = std::find_if(d_params.begin(), d_params.end(), [&key](const SvcParam ¶m) { return param.getKey() == key; }); return p; } +std::shared_ptr SVCBRecordContent::clone() const +{ + return std::shared_ptr(std::make_shared(*this)); +} + +std::shared_ptr HTTPSRecordContent::clone() const +{ + return std::shared_ptr(std::make_shared(*this)); +} + /* SVCB end */ boilerplate_conv(TKEY, diff --git a/pdns/dnsrecords.hh b/pdns/dnsrecords.hh index 245d8e8d4e40..1d3b45c5a487 100644 --- a/pdns/dnsrecords.hh +++ b/pdns/dnsrecords.hh @@ -517,37 +517,40 @@ class SVCBBaseRecordContent : public DNSRecordContent const DNSName& getTarget() const {return d_target;} uint16_t getPriority() const {return d_priority;} // Returns true if a value for |key| was set to 'auto' - bool autoHint(const SvcParam::SvcParamKey &key); + 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); // Whether or not there are any parameter - bool hasParams(); + bool hasParams() const; // Whether or not the param of |key| exists - bool hasParam(const SvcParam::SvcParamKey &key); + bool hasParam(const SvcParam::SvcParamKey &key) const; // Get the parameter with |key|, will throw out_of_range if param isn't there - SvcParam getParam(const SvcParam::SvcParamKey &key); + SvcParam getParam(const SvcParam::SvcParamKey &key) const; + virtual std::shared_ptr clone() const = 0; protected: - LockGuarded> d_params; + std::set d_params; DNSName d_target; uint16_t d_priority; // Get the iterator to parameter with |key|, return value can be d_params::end - static set::const_iterator getParamIt(const SvcParam::SvcParamKey &key, set& params); + std::set::const_iterator getParamIt(const SvcParam::SvcParamKey &key) const; }; class SVCBRecordContent : public SVCBBaseRecordContent { public: includeboilerplate(SVCB) + std::shared_ptr clone() const override; }; class HTTPSRecordContent : public SVCBBaseRecordContent { public: includeboilerplate(HTTPS) + std::shared_ptr clone() const override; }; class RRSIGRecordContent : public DNSRecordContent diff --git a/pdns/packethandler.cc b/pdns/packethandler.cc index a1e3c71afe04..81d157dcb620 100644 --- a/pdns/packethandler.cc +++ b/pdns/packethandler.cc @@ -549,6 +549,12 @@ void PacketHandler::doAdditionalProcessing(DNSPacket& p, std::unique_ptrgetTarget().isRoot() ? rec->dr.d_name : rrc->getTarget(); if (rrc->hasParam(SvcParam::ipv4hint) && rrc->autoHint(SvcParam::ipv4hint)) { + auto newRRC = rrc->clone(); + if (!newRRC) { + continue; + } + rrc = newRRC; + rec->dr.d_content = newRRC; if (s_SVCAutohints) { auto hints = getIPAddressFor(target, QType::A); if (hints.size() == 0) { @@ -562,6 +568,12 @@ void PacketHandler::doAdditionalProcessing(DNSPacket& p, std::unique_ptrhasParam(SvcParam::ipv6hint) && rrc->autoHint(SvcParam::ipv6hint)) { + auto newRRC = rrc->clone(); + if (!newRRC) { + continue; + } + rrc = newRRC; + rec->dr.d_content = newRRC; if (s_SVCAutohints) { auto hints = getIPAddressFor(target, QType::AAAA); if (hints.size() == 0) {