• Bug#1109845: unblock: pdns-recursor/5.2.4-2 [pre-approval] (2/2)

    From Chris =?utf-8?Q?Hofst=C3=A4dtler?=@21:1/5 to All on Fri Jul 25 03:20:02 2025
    [continued from previous message]

    + settings.outgoing.edns_subnet_harden = arg().mustDo("edns-subnet-harden");
    settings.recursor.etc_hosts_file = arg()["etc-hosts-file"];
    settings.recursor.event_trace_enabled = static_cast<uint64_t>(arg().asNum("event-trace-enabled"));
    settings.recursor.export_etc_hosts = arg().mustDo("export-etc-hosts");
    @@ -864,6 +866,13 @@
    to_yaml(rustvalue.vec_string_val, value);
    return true;
    }
    + if (key == "edns-subnet-harden") {
    + section = "outgoing";
    + fieldname = "edns_subnet_harden";
    + type_name = "bool";
    + to_yaml(rustvalue.bool_val, value);
    + return true;
    + }
    if (key == "etc-hosts-file") {
    section = "recursor";
    fieldname = "etc_hosts_file";
    @@ -2010,6 +2019,7 @@
    ::arg().set("edns-padding-out") = to_arg(settings.outgoing.edns_padding);
    ::arg().set("edns-padding-tag") = to_arg(settings.incoming.edns_padding_tag);
    ::arg().set("edns-subnet-allow-list") = to_arg(settings.outgoing.edns_subnet_allow_list);
    + ::arg().set("edns-subnet-harden") = to_arg(settings.outgoing.edns_subnet_harden);
    ::arg().set("etc-hosts-file") = to_arg(settings.recursor.etc_hosts_file);
    ::arg().set("event-trace-enabled") = to_arg(settings.recursor.event_trace_enabled);
    ::arg().set("export-etc-hosts") = to_arg(settings.recursor.export_etc_hosts);
    diff -Nru pdns-recursor-5.2.2/settings/rust/src/lib.rs pdns-recursor-5.2.4/settings/rust/src/lib.rs
    --- pdns-recursor-5.2.2/settings/rust/src/lib.rs 2025-04-08 12:42:42.000000000 +0200
    +++ pdns-recursor-5.2.4/settings/rust/src/lib.rs 2025-07-17 14:22:44.000000000 +0200
    @@ -925,6 +925,9 @@
    edns_subnet_allow_list: Vec<String>,

    #[serde(default, skip_serializing_if = "crate::is_default")]
    + edns_subnet_harden: bool,
    +
    + #[serde(default, skip_serializing_if = "crate::is_default")]
    lowercase: bool,

    #[serde(default, skip_serializing_if = "crate::is_default")]
    @@ -2048,6 +2051,9 @@
    }
    merge_vec(&mut self.edns_subnet_allow_list, &mut rhs.edns_subnet_allow_list);
    }
    + if m.contains_key("edns_subnet_harden") {
    + rhs.edns_subnet_harden.clone_into(&mut self.edns_subnet_harden);
    + }
    if m.contains_key("lowercase") {
    rhs.lowercase.clone_into(&mut self.lowercase);
    }
    diff -Nru pdns-recursor-5.2.2/settings/table.py pdns-recursor-5
  • From Sebastian Ramacher@21:1/5 to All on Sat Jul 26 09:30:01 2025
    [continued from previous message]

    }
    STATUS current
    DESCRIPTION "Objects conformance group for PowerDNS Recursor"
    diff -Nru pdns-recursor-5.2.2/settings/cxxsettings-generated.cc pdns-recursor-5.2.4/settings/cxxsettings-generated.cc
    --- pdns-recursor-5.2.2/settings/cxxsettings-generated.cc 2025-04-08 12:42:42.000000000 +0200
    +++ pdns-recursor-5.2.4/settings/cxxsettings-generated.cc 2025-07-17 14:22:44.000000000 +0200
    @@ -64,6 +64,7 @@
    ::arg().set("edns-padding-tag", "Packetcache tag associated to responses sent with EDNS padding, to prevent sending these to clients for which padding is not enabled.") = "7830";
    ::arg().set("edns-subnet-whitelist", "List of netmasks and domains that we should enable EDNS subnet for (deprecated)") = "";
    ::arg().set("edns-subnet-allow-list", "List of netmasks and domains that we should enable EDNS subnet for") = "";
    + ::arg().setSwitch("edns-subnet-harden", "Do more strict checking or EDNS Client Subnet information returned by authoritative servers") = "no";
    ::arg().setSwitch("enable-old-settings", "Enable (deprecated) parsing of old-style settings") = "no";
    ::arg().set("entropy-source", "If set, read entropy from this file") = "/dev/urandom";
    ::arg().set("etc-hosts-file", "Path to 'hosts' file") = "/etc/hosts";
    @@ -310,6 +311,7 @@
    settings.outgoing.edns_padding = arg().mustDo("edns-padding-out");
    settings.incoming.edns_padding_tag = static_cast<uint64_t>(arg().asNum("edns-padding-tag"));
    settings.outgoing.edns_subnet_allow_list = getStrings("edns-subnet-allow-list");
    + settings.outgoing.edns_subnet_harden = arg().mustDo("edns-subnet-harden");
    settings.recursor.etc_hosts_file = arg()["etc-hosts-file"];
    settings.recursor.event_trace_enabled = static_cast<uint64_t>(arg().asNum("event-trace-enabled"));
    settings.recursor.export_etc_hosts = arg().mustDo("export-etc-hosts");
    @@ -864,6 +866,13 @@
    to_yaml(rustvalue.vec_string_val, value);
    return true;
    }
    + if (key == "edns-subnet-harden") {
    + section = "outgoing";
    + fieldname = "edns_subnet_harden";
    + type_name = "bool";
    + to_yaml(rustvalue.bool_val, value);
    + return true;
    + }
    if (key == "etc-hosts-file") {
    section = "recursor";
    fieldname = "etc_hosts_file";
    @@ -2010,6 +2019,7 @@
    ::arg().set("edns-padding-out") = to_arg(settings.outgoing.edns_padding);
    ::arg().set("edns-padding-tag") = to_arg(settings.incoming.edns_padding_tag);
    ::arg().set("edns-subnet-allow-list") = to_arg(settings.outgoing.edns_subnet_allow_list);
    + ::arg().set("edns-subnet-harden") = to_arg(settings.outgoing.edns_subnet_harden);
    ::arg().set("etc-hosts-file") = to_arg(settings.recursor.etc_hosts_file);
    ::arg().set("event-trace-enabled") = to_arg(settings.recursor.event_trace_enabled);
    ::arg().set("export-etc-hosts") = to_arg(settings.recursor.export_etc_hosts);
    diff -Nru pdns-recursor-5.2.2/settings/rust/src/lib.rs pdns-recursor-5.2.4/settings/rust/src/lib.rs
    --- pdns-recursor-5.2.2/settings/rust/src/lib.rs 2025-04-08 12:42:42.000000000 +0200
    +++ pdns-recursor-5.2.4/settings/rust/src/lib.rs 2025-07-17 14:22:44.000000000 +0200
    @@ -925,6 +925,9 @@
    edns_subnet_allow_list: Vec<String>,

    #[serde(default, skip_serializing_if = "crate::is_default")]
    + edns_subnet_harden: bool,
    +
    + #[serde(default, skip_serializing_if = "crate::is_default")]
    lowercase: bool,

    #[serde(default, skip_serializing_if = "crate::is_default")]
    @@ -2048,6 +2051,9 @@
    }
    merge_vec(&mut self.edns_subnet_allow_list, &mut rhs.edns_subnet_allow_list);
    }
    + if m.contains_key("edns_subnet_harden") {
    + rhs.edns_subnet_harden.clone_into(&mut self.edns_subnet_harden);
    + }
    if m.contains_key("lowercase") {
    rhs.lowercase.clone_into(&mut self.lowercase);
    }
    diff -Nru pdns-recursor-5.2.2/settings/table.py pdns-recursor-5.2.4/settings/table.py
    --- pdns-recursor-5.2.2/settings/table.py 2025-04-08 12:40:39.000000000 +0200
    +++ pdns-recursor-5.2.4/settings/table.py 2025-07-17 14:20:08.000000000 +0200
    @@ -952,6 +952,18 @@
    'versionadded': '4.5.0'
    },
    {
    + 'name' : 'edns_subnet_harden',
    + 'section' : 'outgoing',
    + 'type' : LType.Bool,
    + 'default' : 'false',
    + 'help' : 'Do more strict checking or EDNS Client Subnet information returned by authoritative servers',
    + 'doc' : '''
    +Do more strict checking or EDNS Client Subnet information returned by authoritative servers.
    +Answers missing ECS information will be ignored and followed up by an ECS-less query.
    + ''',
    + 'versionadded': ['5.2.x', '5.1.x', '5.0.x']
    + },
    + {
    'name' : 'enable_old_settings',
    'section' : 'recursor',
    'type' : LType.Bool,
    diff -Nru pdns-recursor-5.2.2/syncres.cc pdns-recursor-5.2.4/syncres.cc
    --- pdns-recursor-5.2.2/syncres.cc 2025-04-08 12:40:39.000000000 +0200
    +++ pdns-recursor-5.2.4/syncres.cc 2025-07-17 14:20:08.000000000 +0200
    @@ -5490,19 +5490,24 @@
    }
    }

    -bool SyncRes::doResolveAtThisIP(const std::string& prefix, const DNSName& qname, const QType qtype, LWResult& lwr, boost::optional<Netmask>& ednsmask, const DNSName& auth, bool const sendRDQuery, const bool wasForwarded, const DNSName& nsName, const
    ComboAddress& remoteIP, bool doTCP, bool doDoT, bool& truncated, bool& spoofed, boost::optional<EDNSExtendedError>& extendedError, bool dontThrottle)
    +void SyncRes::checkTotalTime(const DNSName& qname, QType qtype, boost::optional<EDNSExtendedError>& extendedError) const
    {
    - bool chained = false;
    - LWResult::Result resolveret = LWResult::Result::Success;
    -
    if (s_maxtotusec != 0 && d_totUsec > s_maxtotusec) {
    if (s_addExtendedResolutionDNSErrors) {
    extendedError = EDNSExtendedError{static_cast<uint16_t>(EDNSExtendedError::code::NoReachableAuthority), "Timeout waiting for answer(s)"};
    }
    throw ImmediateServFailException("Too much time waiting for " + qname.toLogString() + "|" + qtype.toString() + ", timeouts: " + std::to_string(d_timeouts) + ", throttles: " + std::to_string(d_throttledqueries) + ", queries: " + std::to_string(d_
    outqueries) + ", " + std::to_string(d_totUsec / 1000) + " ms");
    }
    +}
    +
    +bool SyncRes::doResolveAtThisIP(const std::string& prefix, const DNSName& qname, const QType qtype, LWResult& lwr, boost::optional<Netmask>& ednsmask, const DNSName& auth, bool const sendRDQuery, const bool wasForwarded, const DNSName& nsName, const
    ComboAddress& remoteIP, bool doTCP, bool doDoT, bool& truncated, bool& spoofed, boost::optional<EDNSExtendedError>& extendedError, bool dontThrottle)
    +{
    + checkTotalTime(qname, qtype, extendedError);

    + bool chained = false;
    + LWResult::Result resolveret = LWResult::Result::Success;
    int preOutQueryRet = RCode::NoError;
    +
    if (d_pdl && d_pdl->preoutquery(remoteIP, d_requestor, qname, qtype, doTCP, lwr.d_records, preOutQueryRet, d_eventTrace, timeval{0, 0})) {
    LOG(prefix << qname << ": Query handled by Lua" << endl);
    }
    @@ -5516,6 +5521,13 @@
    resolveret = asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, auth, qtype.getCode(),
    doTCP, sendRDQuery, &d_now, ednsmask, &lwr, &chained, nsName); // <- we go out on the wire!
    ednsStats(ednsmask, qname, prefix);
    + if (resolveret == LWResult::Result::ECSMissing) {
    + ednsmask = boost::none;
    + LOG(prefix << qname << ": Answer has no ECS, trying again without EDNS Client Subnet Mask" << endl);
    + updateQueryCounts(prefix, qname, remoteIP, doTCP, doDoT);
    + resolveret = asyncresolveWrapper(remoteIP, d_doDNSSEC, qname, auth, qtype.getCode(),
    + doTCP, sendRDQuery, &d_now, ednsmask, &lwr, &chained, nsName);
    + }
    }

    /* preoutquery killed the query by setting dq.rcode to -3 */
    diff -Nru pdns-recursor-5.2.2/syncres.hh pdns-recursor-5.2.4/syncres.hh
    --- pdns-recursor-5.2.2/syncres.hh 2025-04-08 12:40:39.000000000 +0200
    +++ pdns-recursor-5.2.4/syncres.hh 2025-07-17 14:20:08.000000000 +0200
    @@ -634,6 +634,7 @@
    std::map<DNSName, std::vector<ComboAddress>>* fallback);
    void ednsStats(boost::optional<Netmask>& ednsmask, const DNSName& qname, const string& prefix);
    void incTimeoutStats(const ComboAddress& remoteIP);
    + void checkTotalTime(const DNSName& qname, QType qtype, boost::optional<EDNSExtendedError>& extendedError) const;
    bool doResolveAtThisIP(const std::string& prefix, const DNSName& qname, QType qtype, LWResult& lwr, boost::optional<Netmask>& ednsmask, const DNSName& auth, bool sendRDQuery, bool wasForwarded, const DNSName& nsName, const ComboAddress& remoteIP,
    bool doTCP, bool doDoT, bool& truncated, bool& spoofed, boost::optional<EDNSExtendedError>& extendedError, bool dontThrottle = false);
    bool processAnswer(unsigned int depth, const string& prefix, LWResult& lwr, const DNSName& qname, QType qtype, DNSName& auth, bool wasForwarded, const boost::optional<Netmask>& ednsmask, bool sendRDQuery, NsSet& nameservers, std::vector<DNSRecord>&
    ret, const DNSFilterEngine& dfe, bool* gotNewServers, int* rcode, vState& state, const ComboAddress& remoteIP);

    @@ -781,6 +782,7 @@
    mutable chain_t authReqChain;
    shared_ptr<TCPIOHandler> tcphandler{nullptr};
    timeval creationTime{};
    + std::optional<Netmask> ecsSubnet;
    string::size_type inPos{0}; // how far are we along in the inMSG
    size_t inWanted{0}; // if this is set, we'll read until inWanted bytes are read
    string::size_type outPos{0}; // how far we are along in the outMSG
    @@ -803,7 +805,7 @@

    inline ostream& operator<<(ostream& ostr, const PacketID& pid)
    {
    - return ostr << "PacketID(id=" << pid.id << ",remote=" << pid.remote.toString() << ",type=" << pid.type << ",tcpsock=" << pid.tcpsock << ",fd=" << pid.fd << ',' << pid.domain << ')';
    + return ostr << "PacketID(id=" << pid.id << ",remote=" << pid.remote.toString() << ",type=" << pid.type << ",tcpsock=" << pid.tcpsock << ",fd=" << pid.fd << ",name=" << pid.domain << ",ecs=" << (pid.ecsSubnet ? pid.ecsSubnet->toString() : "") << ')';
    }

    inline ostream& operator<<(ostream& ostr, const shared_ptr<PacketID>& pid)


    --
    Sebastian Ramacher

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)