From: Peter van Dijk Date: Thu, 11 Jan 2024 11:01:24 +0000 (+0100) Subject: format dnsproxy.{cc,hh}, ednssubnet.{cc,hh}, stubresolver.cc X-Git-Tag: auth-4.9.0-alpha1^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c0ebe1da23ba271375202c86b79794ab79a222fb;p=thirdparty%2Fpdns.git format dnsproxy.{cc,hh}, ednssubnet.{cc,hh}, stubresolver.cc --- diff --git a/.not-formatted b/.not-formatted index fc8ed5abd8..efd77b72f3 100644 --- a/.not-formatted +++ b/.not-formatted @@ -111,8 +111,6 @@ ./pdns/dnspcap.hh ./pdns/dnspcap2calidns.cc ./pdns/dnspcap2protobuf.cc -./pdns/dnsproxy.cc -./pdns/dnsproxy.hh ./pdns/dnsrecords.cc ./pdns/dnsrecords.hh ./pdns/dnsreplay.cc @@ -140,8 +138,6 @@ ./pdns/ednsoptions.cc ./pdns/ednsoptions.hh ./pdns/ednspadding.cc -./pdns/ednssubnet.cc -./pdns/ednssubnet.hh ./pdns/fstrm_logger.cc ./pdns/fstrm_logger.hh ./pdns/gettime.cc @@ -236,7 +232,6 @@ ./pdns/statnode.cc ./pdns/statnode.hh ./pdns/stubquery.cc -./pdns/stubresolver.cc ./pdns/svc-records.cc ./pdns/svc-records.hh ./pdns/tcpiohandler.cc diff --git a/pdns/dnsproxy.cc b/pdns/dnsproxy.cc index 6482b67cf1..7ff8c873e5 100644 --- a/pdns/dnsproxy.cc +++ b/pdns/dnsproxy.cc @@ -42,98 +42,98 @@ extern StatBag S; -DNSProxy::DNSProxy(const string &remote): d_xor(dns_random_uint16()) +DNSProxy::DNSProxy(const string& remote) : + d_xor(dns_random_uint16()) { - d_resanswers=S.getPointer("recursing-answers"); - d_resquestions=S.getPointer("recursing-questions"); - d_udpanswers=S.getPointer("udp-answers"); + d_resanswers = S.getPointer("recursing-answers"); + d_resquestions = S.getPointer("recursing-questions"); + d_udpanswers = S.getPointer("udp-answers"); vector addresses; stringtok(addresses, remote, " ,\t"); d_remote = ComboAddress(addresses[0], 53); - if((d_sock=socket(d_remote.sin4.sin_family, SOCK_DGRAM,0))<0) { - throw PDNSException(string("socket: ")+stringerror()); + if ((d_sock = socket(d_remote.sin4.sin_family, SOCK_DGRAM, 0)) < 0) { + throw PDNSException(string("socket: ") + stringerror()); } ComboAddress local; - if(d_remote.sin4.sin_family==AF_INET) { + if (d_remote.sin4.sin_family == AF_INET) { local = ComboAddress("0.0.0.0"); } else { local = ComboAddress("::"); } - - unsigned int n=0; - for(;n<10;n++) { - local.sin4.sin_port = htons(10000+dns_random(50000)); - - if(::bind(d_sock, (struct sockaddr *)&local, local.getSocklen()) >= 0) + + unsigned int n = 0; + for (; n < 10; n++) { + local.sin4.sin_port = htons(10000 + dns_random(50000)); + + if (::bind(d_sock, (struct sockaddr*)&local, local.getSocklen()) >= 0) break; } - if(n==10) { + if (n == 10) { closesocket(d_sock); - d_sock=-1; - throw PDNSException(string("binding dnsproxy socket: ")+stringerror()); + d_sock = -1; + throw PDNSException(string("binding dnsproxy socket: ") + stringerror()); } - if(connect(d_sock, (sockaddr *)&d_remote, d_remote.getSocklen())<0) { - throw PDNSException("Unable to UDP connect to remote nameserver "+d_remote.toStringWithPort()+": "+stringerror()); + if (connect(d_sock, (sockaddr*)&d_remote, d_remote.getSocklen()) < 0) { + throw PDNSException("Unable to UDP connect to remote nameserver " + d_remote.toStringWithPort() + ": " + stringerror()); } - g_log<qtype, plonk it in the answer section of 'r' with name aname -bool DNSProxy::completePacket(std::unique_ptr& r, const DNSName& target,const DNSName& aname, const uint8_t scopeMask) +bool DNSProxy::completePacket(std::unique_ptr& r, const DNSName& target, const DNSName& aname, const uint8_t scopeMask) { string ECSOptionStr; - if (r->hasEDNSSubnet()) - { - DLOG(g_log<<"dnsproxy::completePacket: Parsed edns source: "<d_eso.source.toString()<<", scope: "<d_eso.scope.toString()<<", family = "<d_eso.scope.getNetwork().sin4.sin_family<hasEDNSSubnet()) { + DLOG(g_log << "dnsproxy::completePacket: Parsed edns source: " << r->d_eso.source.toString() << ", scope: " << r->d_eso.scope.toString() << ", family = " << r->d_eso.scope.getNetwork().sin4.sin_family << endl); ECSOptionStr = makeEDNSSubnetOptsString(r->d_eso); - DLOG(g_log<<"from dnsproxy::completePacket: Creating ECS option string "<d_tcp) { + if (r->d_tcp) { vector ips; int ret1 = 0, ret2 = 0; // rip out edns info here, pass it to the stubDoResolve - if(r->qtype == QType::A || r->qtype == QType::ANY) + if (r->qtype == QType::A || r->qtype == QType::ANY) ret1 = stubDoResolve(target, QType::A, ips, r->hasEDNSSubnet() ? &r->d_eso : nullptr); - if(r->qtype == QType::AAAA || r->qtype == QType::ANY) + if (r->qtype == QType::AAAA || r->qtype == QType::ANY) ret2 = stubDoResolve(target, QType::AAAA, ips, r->hasEDNSSubnet() ? &r->d_eso : nullptr); - if(ret1 != RCode::NoError || ret2 != RCode::NoError) { - g_log<clearRecords(); r->setRcode(RCode::ServFail); - } else { - for (auto &ip : ips) - { + } + else { + for (auto& ip : ips) { ip.dr.d_name = aname; r->addRecord(std::move(ip)); } } - uint16_t len=htons(r->getString().length()); + uint16_t len = htons(r->getString().length()); string buffer((const char*)&len, 2); buffer.append(r->getString()); - writen2WithTimeout(r->getSocket(), buffer.c_str(), buffer.length(), timeval{::arg().asNum("tcp-idle-timeout"),0}); + writen2WithTimeout(r->getSocket(), buffer.c_str(), buffer.length(), timeval{::arg().asNum("tcp-idle-timeout"), 0}); return true; } @@ -145,57 +145,53 @@ bool DNSProxy::completePacket(std::unique_ptr& r, const DNSName& targ id = getID_locked(*conntrack); ConntrackEntry ce; - ce.id = r->d.id; - ce.remote = r->d_remote; - ce.outsock = r->getSocket(); - ce.created = time( nullptr ); + ce.id = r->d.id; + ce.remote = r->d_remote; + ce.outsock = r->getSocket(); + ce.created = time(nullptr); ce.qtype = r->qtype.getCode(); ce.qname = target; ce.anyLocal = r->d_anyLocal; ce.complete = std::move(r); - ce.aname=aname; + ce.aname = aname; ce.anameScopeMask = scopeMask; - (*conntrack)[id]=std::move(ce); + (*conntrack)[id] = std::move(ce); } vector packet; DNSPacketWriter pw(packet, target, qtype); - pw.getHeader()->rd=true; - pw.getHeader()->id=id ^ d_xor; + pw.getHeader()->rd = true; + pw.getHeader()->id = id ^ d_xor; // Add EDNS Subnet if the client sent one - issue #5469 if (!ECSOptionStr.empty()) { - DLOG(g_log<<"from dnsproxy::completePacket: adding ECS option string to packet options "<second.createdsecond.created) { - g_log<second.remote.toStringWithPort()<<" with internal id "<second.complete.reset(); - S.inc("recursion-unanswered"); + else if (i->second.created < time(nullptr) - 60) { + if (i->second.created) { + g_log << Logger::Warning << "Recursive query for remote " << i->second.remote.toStringWithPort() << " with internal id " << n << " was not answered by backend within timeout, reusing id" << endl; + i->second.complete.reset(); + S.inc("recursion-unanswered"); } return n; } @@ -214,53 +210,51 @@ void DNSProxy::mainloop() cmsgbuf_aligned cbuf; ComboAddress fromaddr; - for(;;) { + for (;;) { socklen_t fromaddrSize = sizeof(fromaddr); - len=recvfrom(d_sock, buffer, sizeof(buffer),0, (struct sockaddr*) &fromaddr, &fromaddrSize); // answer from our backend - if(len<(ssize_t)sizeof(dnsheader)) { - if(len<0) - g_log<find(d.id^d_xor); - if(i==conntrack->end()) { - g_log<second.created == 0) { + g_log << Logger::Error << "Received packet from recursor backend with id " << (d.id ^ d_xor) << " which is a duplicate" << endl; continue; } - - d.id=i->second.id; - memcpy(buffer,&d,sizeof(d)); // commit spoofed id + + d.id = i->second.id; + memcpy(buffer, &d, sizeof(d)); // commit spoofed id DNSPacket p(false); - p.parse(buffer,(size_t)len); + p.parse(buffer, (size_t)len); - if(p.qtype.getCode() != i->second.qtype || p.qdomain != i->second.qname) { - g_log<second.qtype<<", "<second.qname<<")"<second.qtype || p.qdomain != i->second.qname) { + g_log << Logger::Error << "Discarding packet from recursor backend with id " << (d.id ^ d_xor) << ", qname or qtype mismatch (" << p.qtype.getCode() << " v " << i->second.qtype << ", " << p.qdomain << " v " << i->second.qname << ")" << endl; continue; } @@ -271,18 +265,18 @@ void DNSProxy::mainloop() // update the EDNS options with info from the resolver - issue #5469 // note that this relies on the ECS string encoder to use the source network, and only take the prefix length from scope i->second.complete->d_eso.scope = p.d_eso.scope; - DLOG(g_log<<"from dnsproxy::mainLoop: updated EDNS options from resolver EDNS source: "<second.complete->d_eso.source.toString()<<" EDNS scope: "<second.complete->d_eso.scope.toString()<second.complete->d_eso.source.toString() << " EDNS scope: " << i->second.complete->d_eso.scope.toString() << endl); if (mdp.d_header.rcode == RCode::NoError) { - for (const auto & answer : mdp.d_answers) { - if(answer.first.d_place == DNSResourceRecord::ANSWER || (answer.first.d_place == DNSResourceRecord::AUTHORITY && answer.first.d_type == QType::SOA)) { + for (const auto& answer : mdp.d_answers) { + if (answer.first.d_place == DNSResourceRecord::ANSWER || (answer.first.d_place == DNSResourceRecord::AUTHORITY && answer.first.d_type == QType::SOA)) { - if(answer.first.d_type == i->second.qtype || (i->second.qtype == QType::ANY && (answer.first.d_type == QType::A || answer.first.d_type == QType::AAAA))) { + if (answer.first.d_type == i->second.qtype || (i->second.qtype == QType::ANY && (answer.first.d_type == QType::A || answer.first.d_type == QType::AAAA))) { DNSZoneRecord dzr; - dzr.dr.d_name=i->second.aname; + dzr.dr.d_name = i->second.aname; dzr.dr.d_type = answer.first.d_type; - dzr.dr.d_ttl=answer.first.d_ttl; - dzr.dr.d_place= answer.first.d_place; + dzr.dr.d_ttl = answer.first.d_ttl; + dzr.dr.d_place = answer.first.d_place; dzr.dr.setContent(answer.first.getContent()); i->second.complete->addRecord(std::move(dzr)); } @@ -290,12 +284,13 @@ void DNSProxy::mainloop() } i->second.complete->setRcode(mdp.d_header.rcode); - } else { - g_log<second.aname<<" ALIAS "<second.qname<<" over UDP, "<second.qtype).toString()<<"-record query returned "<second.aname << " ALIAS " << i->second.qname << " over UDP, " << QType(i->second.qtype).toString() << "-record query returned " << RCode::to_s(mdp.d_header.rcode) << ", returning SERVFAIL" << endl; i->second.complete->clearRecords(); i->second.complete->setRcode(RCode::ServFail); } - reply=i->second.complete->getString(); + reply = i->second.complete->getString(); iov.iov_base = (void*)reply.c_str(); iov.iov_len = reply.length(); i->second.complete.reset(); @@ -303,41 +298,41 @@ void DNSProxy::mainloop() msgh.msg_iovlen = 1; msgh.msg_name = (struct sockaddr*)&i->second.remote; msgh.msg_namelen = i->second.remote.getSocklen(); - msgh.msg_control=nullptr; + msgh.msg_control = nullptr; - if(i->second.anyLocal) { + if (i->second.anyLocal) { addCMsgSrcAddr(&msgh, &cbuf, i->second.anyLocal.get_ptr(), 0); } - if(sendmsg(i->second.outsock, &msgh, 0) < 0) { + if (sendmsg(i->second.outsock, &msgh, 0) < 0) { int err = errno; - g_log<second.created=0; + i->second.created = 0; } } } - catch(PDNSException &ae) { - g_log<-1) { +DNSProxy::~DNSProxy() +{ + if (d_sock > -1) { try { closesocket(d_sock); } - catch(const PDNSException& e) { + catch (const PDNSException& e) { } } - d_sock=-1; + d_sock = -1; } diff --git a/pdns/dnsproxy.hh b/pdns/dnsproxy.hh index 1a2ff00b9a..ccf71a17f6 100644 --- a/pdns/dnsproxy.hh +++ b/pdns/dnsproxy.hh @@ -38,7 +38,7 @@ This is a thread that just throws packets around. Should handle ~1000 packets/se Consists of a thread receiving packets back from the backend and retransmitting them to the original client. -Furthermore, it provides a member function that reports the packet to the connection tracker and actually sends it out. +Furthermore, it provides a member function that reports the packet to the connection tracker and actually sends it out. The sending happens from a source port that is determined by the constructor, but IS random. Furthermore, the ID is XOR-ed with a random value to make sure outside parties can't spoof us. @@ -49,12 +49,12 @@ To fix: how to remove the stale entries that will surely accumulate class DNSProxy { public: - DNSProxy(const string &ip); //!< creates socket + DNSProxy(const string& ip); //!< creates socket ~DNSProxy(); //& r, const DNSName& target,const DNSName& aname, const uint8_t scopeMask); + bool completePacket(std::unique_ptr& r, const DNSName& target, const DNSName& aname, const uint8_t scopeMask); - void mainloop(); //!< this is the main loop that receives reply packets and sends them out again + void mainloop(); //!< this is the main loop that receives reply packets and sends them out again private: struct ConntrackEntry { @@ -70,7 +70,7 @@ private: int outsock; }; - typedef map map_t; + typedef map map_t; // Data ComboAddress d_remote; diff --git a/pdns/ednssubnet.cc b/pdns/ednssubnet.cc index a85fe02690..a174d1aed8 100644 --- a/pdns/ednssubnet.cc +++ b/pdns/ednssubnet.cc @@ -25,59 +25,61 @@ #include "ednssubnet.hh" #include "dns.hh" -namespace { - struct EDNSSubnetOptsWire - { - uint16_t family; - uint8_t sourceMask; - uint8_t scopeMask; - } GCCPACKATTRIBUTE; // BRRRRR +namespace +{ +struct EDNSSubnetOptsWire +{ + uint16_t family; + uint8_t sourceMask; + uint8_t scopeMask; +} GCCPACKATTRIBUTE; // BRRRRR } bool getEDNSSubnetOptsFromString(const string& options, EDNSSubnetOpts* eso) { - //cerr<<"options.size:"< 0 ? (((esow.sourceMask - 1)>> 3)+1) : 0; - //cerr<<"octetsin:"< 0 ? (((esow.sourceMask - 1) >> 3) + 1) : 0; + // cerr<<"octetsin:"< sizeof(address.sin4.sin_addr.s_addr)) + if (octetsin > sizeof(address.sin4.sin_addr.s_addr)) return false; address.reset(); address.sin4.sin_family = AF_INET; - if(octetsin > 0) - memcpy(&address.sin4.sin_addr.s_addr, options+sizeof(esow), octetsin); - } else if(esow.family == 2) { - if(len != sizeof(esow)+octetsin) + if (octetsin > 0) + memcpy(&address.sin4.sin_addr.s_addr, options + sizeof(esow), octetsin); + } + else if (esow.family == 2) { + if (len != sizeof(esow) + octetsin) return false; - if(octetsin > sizeof(address.sin6.sin6_addr.s6_addr)) + if (octetsin > sizeof(address.sin6.sin6_addr.s6_addr)) return false; address.reset(); address.sin4.sin_family = AF_INET6; - if(octetsin > 0) - memcpy(&address.sin6.sin6_addr.s6_addr, options+sizeof(esow), octetsin); + if (octetsin > 0) + memcpy(&address.sin6.sin6_addr.s6_addr, options + sizeof(esow), octetsin); } else return false; eso->source = Netmask(address, esow.sourceMask); /* 'address' has more bits set (potentially) than scopeMask. This leads to odd looking netmasks that promise more precision than they have. For this reason we truncate the address to scopeMask bits */ - + address.truncate(esow.scopeMask); // truncate will not throw for odd scopeMasks eso->scope = Netmask(address, esow.scopeMask); @@ -93,15 +95,14 @@ string makeEDNSSubnetOptsString(const EDNSSubnetOpts& eso) esow.sourceMask = eso.source.getBits(); esow.scopeMask = eso.scope.getBits(); ret.assign((const char*)&esow, sizeof(esow)); - int octetsout = ((esow.sourceMask - 1)>> 3)+1; + int octetsout = ((esow.sourceMask - 1) >> 3) + 1; - ComboAddress src=eso.source.getNetwork(); + ComboAddress src = eso.source.getNetwork(); src.truncate(esow.sourceMask); - if(family == htons(1)) - ret.append((const char*) &src.sin4.sin_addr.s_addr, octetsout); + if (family == htons(1)) + ret.append((const char*)&src.sin4.sin_addr.s_addr, octetsout); else - ret.append((const char*) &src.sin6.sin6_addr.s6_addr, octetsout); + ret.append((const char*)&src.sin6.sin6_addr.s6_addr, octetsout); return ret; } - diff --git a/pdns/ednssubnet.hh b/pdns/ednssubnet.hh index b0f6e485bf..19beb03186 100644 --- a/pdns/ednssubnet.hh +++ b/pdns/ednssubnet.hh @@ -26,8 +26,8 @@ struct EDNSSubnetOpts { - Netmask source; - Netmask scope; + Netmask source; + Netmask scope; }; bool getEDNSSubnetOptsFromString(const string& options, EDNSSubnetOpts* eso); diff --git a/pdns/stubresolver.cc b/pdns/stubresolver.cc index a8dc38e4a3..f6f12c6c75 100644 --- a/pdns/stubresolver.cc +++ b/pdns/stubresolver.cc @@ -39,7 +39,7 @@ static string logPrefix = "[stub-resolver] "; bool resolversDefined() { if (s_resolversForStub.read_lock()->empty()) { - g_log< now) - return ; + return; parseLocalResolvConf_locked(*(s_resolversForStub.write_lock()), now); } - /* * Fill the s_resolversForStub vector with addresses for the upstream resolvers. * First, parse the `resolver` configuration option for IP addresses to use. @@ -88,7 +87,7 @@ static void parseLocalResolvConf() */ void stubParseResolveConf() { - if(::arg().mustDo("resolver")) { + if (::arg().mustDo("resolver")) { auto resolversForStub = s_resolversForStub.write_lock(); vector parts; stringtok(parts, ::arg()["resolver"], " ,\t"); @@ -113,7 +112,7 @@ int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& r } // only check if resolvers come from local resolv.conf in the first place if (s_localResolvConfMtime != 0) { - parseLocalResolvConf(); + parseLocalResolvConf(); } if (!resolversDefined()) return RCode::ServFail; @@ -122,11 +121,10 @@ int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& r vector packet; DNSPacketWriter pw(packet, qname, qtype); - pw.getHeader()->id=dns_random_uint16(); - pw.getHeader()->rd=1; - - if (d_eso != nullptr) - { + pw.getHeader()->id = dns_random_uint16(); + pw.getHeader()->rd = 1; + + if (d_eso != nullptr) { // pass along EDNS subnet from client if given - issue #5469 string origECSOptionStr = makeEDNSSubnetOptsString(*d_eso); DNSPacketWriter::optvect_t opts; @@ -136,13 +134,13 @@ int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& r } string queryNameType = qname.toString() + "|" + QType(qtype).toString(); - string msg ="Doing stub resolving for '" + queryNameType + "', using resolvers: "; + string msg = "Doing stub resolving for '" + queryNameType + "', using resolvers: "; for (const auto& server : *resolversForStub) { msg += server.toString() + ", "; } - g_log<& r try { retry: sock.read(reply); // this calls recv - if(reply.size() > sizeof(struct dnsheader)) { + if (reply.size() > sizeof(struct dnsheader)) { struct dnsheader d; memcpy(&d, reply.c_str(), sizeof(d)); - if(d.id != pw.getHeader()->id) + if (d.id != pw.getHeader()->id) goto retry; } } - catch(...) { + catch (...) { continue; } MOADNSParser mdp(false, reply); - if(mdp.d_header.rcode == RCode::ServFail) + if (mdp.d_header.rcode == RCode::ServFail) continue; - for(const auto & answer : mdp.d_answers) { - if(answer.first.d_place == 1 && answer.first.d_type==qtype) { + for (const auto& answer : mdp.d_answers) { + if (answer.first.d_place == 1 && answer.first.d_type == qtype) { DNSZoneRecord zrr; zrr.dr = answer.first; - zrr.auth=true; + zrr.auth = true; ret.push_back(zrr); } } - g_log<& ret, const EDNSSubnetOpts* d_eso) { +int stubDoResolve(const DNSName& qname, uint16_t qtype, vector& ret, const EDNSSubnetOpts* d_eso) +{ vector ret2; int res = stubDoResolve(qname, qtype, ret2, d_eso); - for (const auto &r : ret2) { + for (const auto& r : ret2) { ret.push_back(r.dr); } return res;