From: Miod Vallat Date: Fri, 4 Apr 2025 06:16:09 +0000 (+0200) Subject: Split handling of Query opcode, step 1/2. X-Git-Tag: dnsdist-2.0.0-alpha2~69^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0773897af567ce058cc4c4fb85dffaf6699ed4d2;p=thirdparty%2Fpdns.git Split handling of Query opcode, step 1/2. Gets rid of the "sendit" goto label. --- diff --git a/pdns/packethandler.cc b/pdns/packethandler.cc index 1415968aef..2c3b28f048 100644 --- a/pdns/packethandler.cc +++ b/pdns/packethandler.cc @@ -1497,16 +1497,14 @@ std::unique_ptr PacketHandler::doQuestion(DNSPacket& p) } } -std::unique_ptr PacketHandler::opcodeQuery(DNSPacket& p, bool noCache) +bool PacketHandler::opcodeQueryInner(DNSPacket& p, queryState &state) { - std::unique_ptr r{nullptr}; DNSZoneRecord rr; int retargetcount=0; - set authSet; vector rrset; - bool weDone=false, weRedirected=false, weHaveUnauth=false, doSigs=false; + bool weDone=false, weRedirected=false, weHaveUnauth=false; DNSName haveAlias; uint8_t aliasScopeMask; @@ -1514,125 +1512,125 @@ std::unique_ptr PacketHandler::opcodeQuery(DNSPacket& p, bool noCache bool doLua=g_doLuaRecord; #endif - r=p.replyPacket(); // generate an empty reply packet, possibly with TSIG details inside + state.r=p.replyPacket(); // generate an empty reply packet, possibly with TSIG details inside // g_log<setRcode(RCode::Refused); - return r; + state.r->setRcode(RCode::Refused); + return false; } DNSName target=p.qdomain; // catch chaos qclass requests if(p.qclass == QClass::CHAOS) { - if (doChaosRequest(p,r,target)) - goto sendit; - else - return r; + if (!doChaosRequest(p,state.r,target)) { + return false; + } + return true; } // we only know about qclass IN (and ANY), send Refused for everything else. if(p.qclass != QClass::IN && p.qclass!=QClass::ANY) { - r->setRcode(RCode::Refused); - return r; + state.r->setRcode(RCode::Refused); + return false; } // send TC for udp ANY query if any-to-tcp is enabled. if(p.qtype.getCode() == QType::ANY && !p.d_tcp && g_anyToTcp) { - r->d.tc = 1; - r->commitD(); - return r; + state.r->d.tc = 1; + state.r->commitD(); + return false; } // for qclass ANY the response should never be authoritative unless the response covers all classes. if(p.qclass==QClass::ANY) - r->setA(false); + state.r->setA(false); retargeted:; if(retargetcount > 10) { // XXX FIXME, retargetcount++? g_log<setRcode(RCode::ServFail); - return r; + state.r=p.replyPacket(); + state.r->setRcode(RCode::ServFail); + return false; } - if (retargetcount > 0 && !d_doResolveAcrossZones && !target.isPartOf(r->qdomainzone)) { + if (retargetcount > 0 && !d_doResolveAcrossZones && !target.isPartOf(state.r->qdomainzone)) { // We are following a retarget outside the initial zone (and do not need to check getAuth to know this). Config asked us not to do that. // This is a performance optimization, the generic case is checked after getAuth below. - goto sendit; // NOLINT(cppcoreguidelines-avoid-goto) + return true; } if(!B.getAuth(target, p.qtype, &d_sd)) { DLOG(g_log<setA(false); // drop AA if we never had a SOA in the first place - r->setRcode(RCode::Refused); // send REFUSED - but only on empty 'no idea' + state.r->setA(false); // drop AA if we never had a SOA in the first place + state.r->setRcode(RCode::Refused); // send REFUSED - but only on empty 'no idea' } - goto sendit; + return true; } DLOG(g_log<setRcode(RCode::Refused); - goto sendit; + state.r->setRcode(RCode::Refused); + return true; } DLOG(g_log<<"Checking for referrals first, unless this is a DS query"< PacketHandler::opcodeQuery(DNSPacket& p, bool noCache continue; } if(rec->d_type == QType::CNAME || rec->d_type == p.qtype.getCode() || (p.qtype.getCode() == QType::ANY && rec->d_type != QType::RRSIG)) { - noCache=true; + state.noCache=true; try { auto recvec=luaSynth(rec->getCode(), target, rr, d_sd.qname, p, rec->d_type, s_LUA); if(!recvec.empty()) { @@ -1680,9 +1678,9 @@ std::unique_ptr PacketHandler::opcodeQuery(DNSPacket& p, bool noCache catch(std::exception &e) { B.lookupEnd(); // don't leave DB handle in bad state - r=p.replyPacket(); - r->setRcode(RCode::ServFail); - return r; + state.r=p.replyPacket(); + state.r->setRcode(RCode::ServFail); + return false; } } } @@ -1728,14 +1726,15 @@ std::unique_ptr PacketHandler::opcodeQuery(DNSPacket& p, bool noCache DLOG(g_log<<"After first ANY query for '"<completePacket(r, haveAlias, target, aliasScopeMask); - return nullptr; + DP->completePacket(state.r, haveAlias, target, aliasScopeMask); + state.r = nullptr; + return false; } // referral for DS query @@ -1764,10 +1763,10 @@ std::unique_ptr PacketHandler::opcodeQuery(DNSPacket& p, bool noCache } if(doReferral) { DLOG(g_log<<"DS query found no direct result, trying referral now"< PacketHandler::opcodeQuery(DNSPacket& p, bool noCache DLOG(g_log<qdomainwild=wildcard; + if(!retargetcount) state.r->qdomainwild=wildcard; retargetcount++; goto retargeted; } if(nodata) - makeNOError(p, r, target, wildcard, 2); + makeNOError(p, state.r, target, wildcard, 2); - goto sendit; + return true; } try { - if (tryDNAME(p, r, target)) { + if (tryDNAME(p, state.r, target)) { retargetcount++; goto retargeted; } } catch (const std::range_error &e) { // We couldn't make a CNAME..... - r->setRcode(RCode::YXDomain); - goto sendit; + state.r->setRcode(RCode::YXDomain); + return true; } if (!(((p.qtype.getCode() == QType::CNAME) || (p.qtype.getCode() == QType::ANY)) && retargetcount > 0)) - makeNXDomain(p, r, target, wildcard); + makeNXDomain(p, state.r, target, wildcard); - goto sendit; + return true; } if(weRedirected) { for(auto& loopRR: rrset) { if(loopRR.dr.d_type == QType::CNAME) { - r->addRecord(DNSZoneRecord(loopRR)); + state.r->addRecord(DNSZoneRecord(loopRR)); target = getRR(loopRR.dr)->getTarget(); retargetcount++; goto retargeted; @@ -1830,24 +1829,24 @@ std::unique_ptr PacketHandler::opcodeQuery(DNSPacket& p, bool noCache } #endif if ((p.qtype.getCode() == QType::ANY || loopRR.dr.d_type == p.qtype.getCode()) && loopRR.auth) { - r->addRecord(DNSZoneRecord(loopRR)); + state.r->addRecord(DNSZoneRecord(loopRR)); haveRecords = true; } } if (haveRecords) { if(d_dnssec && p.qtype.getCode() == QType::ANY) - completeANYRecords(p, r, target); + completeANYRecords(p, state.r, target); } else - makeNOError(p, r, target, DNSName(), 0); + makeNOError(p, state.r, target, DNSName(), 0); - goto sendit; + return true; } else if(weHaveUnauth) { DLOG(g_log<<"Have unauth data, so need to hunt for best NS records"< PacketHandler::opcodeQuery(DNSPacket& p, bool noCache } else { DLOG(g_log<<"Have some data, but not the right data"< PacketHandler::opcodeQuery(DNSPacket& p, bool noCache) +{ + queryState state; + state.noCache = noCache; - for(const auto& loopRR: r->getRRS()) { - if(loopRR.scopeMask) { - noCache=true; - break; + if (opcodeQueryInner(p, state)) { + doAdditionalProcessing(p, state.r); + + for(const auto& loopRR: state.r->getRRS()) { + if(loopRR.scopeMask) { + state.noCache=true; + break; + } } - } - if(doSigs) - addRRSigs(d_dk, B, authSet, r->getRRS(), &p); + if(state.doSigs) + addRRSigs(d_dk, B, state.authSet, state.r->getRRS(), &p); - if(PC.enabled() && !noCache && p.couldBeCached()) - PC.insert(p, *r, r->getMinTTL()); // in the packet cache + if(PC.enabled() && !state.noCache && p.couldBeCached()) + PC.insert(p, *state.r, state.r->getMinTTL()); // in the packet cache + } - return r; + return std::move(state.r); } std::unique_ptr PacketHandler::opcodeNotify(DNSPacket& p, bool /* noCache */) diff --git a/pdns/packethandler.hh b/pdns/packethandler.hh index 429e67c8ac..a3a95bdd5c 100644 --- a/pdns/packethandler.hh +++ b/pdns/packethandler.hh @@ -109,6 +109,13 @@ private: void tkeyHandler(const DNSPacket& p, std::unique_ptr& r); // r{nullptr}; + set authSet; + bool doSigs{false}; + bool noCache{false}; + }; + bool opcodeQueryInner(DNSPacket&, queryState&); std::unique_ptr opcodeQuery(DNSPacket&, bool); std::unique_ptr opcodeNotify(DNSPacket&, bool); std::unique_ptr opcodeUpdate(DNSPacket&, bool);