From: Remi Gacogne Date: Fri, 16 Sep 2016 15:10:25 +0000 (+0200) Subject: Don't parse spurious RRs in queries when we don't need them X-Git-Tag: rec-4.0.4~1^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=28e152dd6fa8495b5e1cafda837acb3cf1e7ae75;p=pdns Don't parse spurious RRs in queries when we don't need them --- diff --git a/pdns/comfun.cc b/pdns/comfun.cc index ee6d7dd2c..aacab3cc7 100644 --- a/pdns/comfun.cc +++ b/pdns/comfun.cc @@ -120,7 +120,7 @@ struct SendReceive } // parse packet, set 'id', fill out 'ip' - MOADNSParser mdp(string(buf, len)); + MOADNSParser mdp(false, string(buf, len)); if(!g_quiet) { cout<<"Reply to question for qname='"<rd || dh->qr) continue; - MOADNSParser mdp((const char*)pr.d_payload, pr.d_len); + MOADNSParser mdp(false, (const char*)pr.d_payload, pr.d_len); entry.ip = pr.getSource(); entry.port = pr.d_udp->uh_sport; diff --git a/pdns/dnsgram.cc b/pdns/dnsgram.cc index 32458dbd7..17a5f990b 100644 --- a/pdns/dnsgram.cc +++ b/pdns/dnsgram.cc @@ -157,7 +157,7 @@ try ntohs(pr.d_udp->uh_dport)==53 || ntohs(pr.d_udp->uh_sport)==53) && pr.d_len > 12) { try { - MOADNSParser mdp((const char*)pr.d_payload, pr.d_len); + MOADNSParser mdp(false, (const char*)pr.d_payload, pr.d_len); if(lastreport.tv_sec == 0) { lastreport = pr.d_pheader.ts; diff --git a/pdns/dnspacket.cc b/pdns/dnspacket.cc index b2d3b1c02..0862f8081 100644 --- a/pdns/dnspacket.cc +++ b/pdns/dnspacket.cc @@ -51,7 +51,7 @@ bool DNSPacket::s_doEDNSSubnetProcessing; uint16_t DNSPacket::s_udpTruncationThreshold; -DNSPacket::DNSPacket() +DNSPacket::DNSPacket(bool isQuery) { d_wrapped=false; d_compress=true; @@ -69,6 +69,7 @@ DNSPacket::DNSPacket() d_maxreplylen = 0; d_tsigtimersonly = false; d_haveednssection = false; + d_isQuery = isQuery; } const string& DNSPacket::getString() @@ -390,7 +391,7 @@ void DNSPacket::setQuestion(int op, const DNSName &qd, int newqtype) /** convenience function for creating a reply packet from a question packet. Do not forget to delete it after use! */ DNSPacket *DNSPacket::replyPacket() const { - DNSPacket *r=new DNSPacket; + DNSPacket *r=new DNSPacket(false); r->setSocket(d_socket); r->d_anyLocal=d_anyLocal; r->setRemote(&d_remote); @@ -471,7 +472,7 @@ void DNSPacket::setTSIGDetails(const TSIGRecordContent& tr, const DNSName& keyna bool DNSPacket::getTSIGDetails(TSIGRecordContent* trc, DNSName* keyname, string* message) const { - MOADNSParser mdp(d_rawpacket); + MOADNSParser mdp(d_isQuery, d_rawpacket); if(!mdp.getTSIGPos()) return false; @@ -500,7 +501,7 @@ bool DNSPacket::getTSIGDetails(TSIGRecordContent* trc, DNSName* keyname, string* bool DNSPacket::getTKEYRecord(TKEYRecordContent *tr, DNSName *keyname) const { - MOADNSParser mdp(d_rawpacket); + MOADNSParser mdp(d_isQuery, d_rawpacket); bool gotit=false; for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) { @@ -540,7 +541,7 @@ try return -1; } - MOADNSParser mdp(d_rawpacket); + MOADNSParser mdp(d_isQuery, d_rawpacket); EDNSOpts edo; // ANY OPTION WHICH *MIGHT* BE SET DOWN BELOW SHOULD BE CLEARED FIRST! diff --git a/pdns/dnspacket.hh b/pdns/dnspacket.hh index 7230ea6ac..ce37d35d3 100644 --- a/pdns/dnspacket.hh +++ b/pdns/dnspacket.hh @@ -64,7 +64,7 @@ class DNSSECKeeper; class DNSPacket { public: - DNSPacket(); + DNSPacket(bool isQuery); DNSPacket(const DNSPacket &orig); int noparse(const char *mesg, size_t len); //!< just suck the data inward @@ -192,6 +192,7 @@ private: bool d_wantsnsid; bool d_haveednssubnet; bool d_haveednssection; + bool d_isQuery; }; diff --git a/pdns/dnsparser.cc b/pdns/dnsparser.cc index ebdcf0a06..d60bcd847 100644 --- a/pdns/dnsparser.cc +++ b/pdns/dnsparser.cc @@ -116,7 +116,7 @@ shared_ptr DNSRecordContent::unserialize(const DNSName& qname, memcpy(&packet[pos], &drh, sizeof(drh)); pos+=sizeof(drh); memcpy(&packet[pos], serialized.c_str(), serialized.size()); pos+=(uint16_t)serialized.size(); - MOADNSParser mdp((char*)&*packet.begin(), (unsigned int)packet.size()); + MOADNSParser mdp(false, (char*)&*packet.begin(), (unsigned int)packet.size()); shared_ptr ret= mdp.d_answers.begin()->first.d_content; return ret; } @@ -211,7 +211,7 @@ DNSRecord::DNSRecord(const DNSResourceRecord& rr) d_content = std::shared_ptr(DNSRecordContent::mastermake(d_type, rr.qclass, rr.content)); } -void MOADNSParser::init(const char *packet, unsigned int len) +void MOADNSParser::init(bool query, const char *packet, unsigned int len) { if(len < sizeof(dnsheader)) throw MOADNSException("Packet shorter than minimal header"); @@ -225,7 +225,10 @@ void MOADNSParser::init(const char *packet, unsigned int len) d_header.ancount=ntohs(d_header.ancount); d_header.nscount=ntohs(d_header.nscount); d_header.arcount=ntohs(d_header.arcount); - + + if (query && (d_header.qdcount > 1)) + throw MOADNSException("Query with QD > 1 ("+std::to_string(d_header.qdcount)+")"); + uint16_t contentlen=len-sizeof(dnsheader); d_content.resize(contentlen); @@ -270,7 +273,15 @@ void MOADNSParser::init(const char *packet, unsigned int len) dr.d_name=name; dr.d_clen=ah.d_clen; - dr.d_content=std::shared_ptr(DNSRecordContent::mastermake(dr, pr, d_header.opcode)); + if (query && (dr.d_place == DNSResourceRecord::ANSWER || dr.d_place == DNSResourceRecord::AUTHORITY || (dr.d_type != QType::OPT && dr.d_type != QType::TSIG && dr.d_type != QType::SIG && dr.d_type != QType::TKEY) || ((dr.d_type == QType::TSIG || dr.d_type == QType::SIG || dr.d_type == QType::TKEY) && dr.d_class != QClass::ANY))) { +// cerr<<"discarding RR, query is "<(new UnknownRecordContent(dr, pr)); + } + else { +// cerr<<"parsing RR, query is "<(DNSRecordContent::mastermake(dr, pr, d_header.opcode)); + } + d_answers.push_back(make_pair(dr, pr.d_pos)); if(dr.d_type == QType::TSIG && dr.d_class == 0xff) diff --git a/pdns/dnsparser.hh b/pdns/dnsparser.hh index 8f00c49e7..e70064fbb 100644 --- a/pdns/dnsparser.hh +++ b/pdns/dnsparser.hh @@ -337,15 +337,15 @@ class MOADNSParser : public boost::noncopyable { public: //! Parse from a string - MOADNSParser(const string& buffer) : d_tsigPos(0) + MOADNSParser(bool query, const string& buffer) : d_tsigPos(0) { - init(buffer.c_str(), (unsigned int)buffer.size()); + init(query, buffer.c_str(), (unsigned int)buffer.size()); } //! Parse from a pointer and length - MOADNSParser(const char *packet, unsigned int len) : d_tsigPos(0) + MOADNSParser(bool query, const char *packet, unsigned int len) : d_tsigPos(0) { - init(packet, len); + init(query, packet, len); } DNSName d_qname; @@ -371,7 +371,7 @@ public: } private: void getDnsrecordheader(struct dnsrecordheader &ah); - void init(const char *packet, unsigned int len); + void init(bool query, const char *packet, unsigned int len); vector d_content; uint16_t d_tsigPos; }; diff --git a/pdns/dnsproxy.cc b/pdns/dnsproxy.cc index f7061c098..3f6342386 100644 --- a/pdns/dnsproxy.cc +++ b/pdns/dnsproxy.cc @@ -228,7 +228,7 @@ void DNSProxy::mainloop(void) d.id=i->second.id; memcpy(buffer,&d,sizeof(d)); // commit spoofed id - DNSPacket p,q; + DNSPacket p(false),q(false); p.parse(buffer,(size_t)len); q.parse(buffer,(size_t)len); @@ -243,7 +243,7 @@ void DNSProxy::mainloop(void) string reply; // needs to be alive at time of sendmsg! if(i->second.complete) { - MOADNSParser mdp(p.getString()); + MOADNSParser mdp(false, p.getString()); // cerr<<"Got completion, "<first.d_place-1<<" "<first.d_label<<" " << DNSRecordContent::NumberToType(j->first.d_type)<<" "<first.d_content->getZoneRepresentation()<recvFromAsync(packet, remote)) { try { s_weanswers++; - MOADNSParser mdp(packet.c_str(), packet.length()); + MOADNSParser mdp(false, packet.c_str(), packet.length()); if(!mdp.d_header.qr) { cout<<"Received a question from our reference nameserver!"<id=tmp; } - MOADNSParser mdp((const char*)pr.d_payload, pr.d_len); + MOADNSParser mdp(false, (const char*)pr.d_payload, pr.d_len); QuestionIdentifier qi=QuestionIdentifier::create(pr.getSource(), pr.getDest(), mdp); if(!mdp.d_header.qr) { diff --git a/pdns/dnsscan.cc b/pdns/dnsscan.cc index 7127e1b74..2fb712e2f 100644 --- a/pdns/dnsscan.cc +++ b/pdns/dnsscan.cc @@ -87,7 +87,7 @@ try while(pr.getUDPPacket()) { try { - MOADNSParser mdp((const char*)pr.d_payload, pr.d_len); + MOADNSParser mdp(false, (const char*)pr.d_payload, pr.d_len); if(mdp.d_qtype < 256) counts[mdp.d_qtype]++; diff --git a/pdns/dnsscope.cc b/pdns/dnsscope.cc index 78e2cd0a3..4ad9976a8 100644 --- a/pdns/dnsscope.cc +++ b/pdns/dnsscope.cc @@ -217,7 +217,7 @@ try continue; } } - MOADNSParser mdp((const char*)pr.d_payload, pr.d_len); + MOADNSParser mdp(false, (const char*)pr.d_payload, pr.d_len); if(haveRDFilter && mdp.d_header.rd != rdFilter) { rdFilterMismatch++; continue; diff --git a/pdns/dnstcpbench.cc b/pdns/dnstcpbench.cc index e64f533eb..fbeba1ba5 100644 --- a/pdns/dnstcpbench.cc +++ b/pdns/dnstcpbench.cc @@ -98,7 +98,7 @@ try q->udpUsec = makeUsec(now - tv); tv=now; - MOADNSParser mdp(reply); + MOADNSParser mdp(false, reply); if(!mdp.d_header.tc) return; g_truncates++; @@ -148,7 +148,7 @@ try q->tcpUsec = makeUsec(now - tv); q->answerSecond = now.tv_sec; - MOADNSParser mdp(reply); + MOADNSParser mdp(false, reply); // cout<<"Had correct TCP/IP response, "<d_records.clear(); try { lwr->d_tcbit=0; - MOADNSParser mdp((const char*)buf.get(), len); + MOADNSParser mdp(false, (const char*)buf.get(), len); lwr->d_aabit=mdp.d_header.aa; lwr->d_tcbit=mdp.d_header.tc; lwr->d_rcode=mdp.d_header.rcode; diff --git a/pdns/mastercommunicator.cc b/pdns/mastercommunicator.cc index 5d1c27cb2..82b0dbd0d 100644 --- a/pdns/mastercommunicator.cc +++ b/pdns/mastercommunicator.cc @@ -167,7 +167,7 @@ time_t CommunicatorClass::doNotifications() size=recvfrom(sock,buffer,sizeof(buffer),0,(struct sockaddr *)&from,&fromlen); if(size < 0) break; - DNSPacket p; + DNSPacket p(true); p.setRemote(&from); diff --git a/pdns/nameserver.cc b/pdns/nameserver.cc index a806adb30..b8cb88385 100644 --- a/pdns/nameserver.cc +++ b/pdns/nameserver.cc @@ -360,7 +360,7 @@ DNSPacket *UDPNameserver::receive(DNSPacket *prefilled) if(prefilled) // they gave us a preallocated packet packet=prefilled; else - packet=new DNSPacket; // don't forget to free it! + packet=new DNSPacket(true); // don't forget to free it! packet->setSocket(sock); packet->setRemote(&remote); diff --git a/pdns/notify.cc b/pdns/notify.cc index 8243f49fd..b421fa204 100644 --- a/pdns/notify.cc +++ b/pdns/notify.cc @@ -106,7 +106,7 @@ try throw runtime_error("Unable to receive notification response from PowerDNS: "+stringerror()); string packet(buffer, len); - MOADNSParser mdp(packet); + MOADNSParser mdp(false, packet); cerr<<"Received notification response with error: "<* records) // d_receivedBytes += (uint16_t) len; - MOADNSParser mdp(d_buf.get(), len); + MOADNSParser mdp(false, d_buf.get(), len); int err; if(!records) diff --git a/pdns/rfc2136handler.cc b/pdns/rfc2136handler.cc index e37357d35..0a4ec7928 100644 --- a/pdns/rfc2136handler.cc +++ b/pdns/rfc2136handler.cc @@ -652,7 +652,7 @@ int PacketHandler::forwardPacket(const string &msgPrefix, DNSPacket *p, DomainIn closesocket(sock); try { - MOADNSParser mdp(buf, recvRes); + MOADNSParser mdp(false, buf, recvRes); L<getString()); + MOADNSParser mdp(false, p->getString()); if (mdp.d_header.qdcount != 1) { L<, set, TCacheComp > tcache_t; tcache_t tcache; @@ -503,7 +503,7 @@ struct ParsePacketBareTest void operator()() const { - MOADNSParser mdp((const char*)&*d_packet.begin(), d_packet.size()); + MOADNSParser mdp(false, (const char*)&*d_packet.begin(), d_packet.size()); } const vector& d_packet; std::string d_name; diff --git a/pdns/stubresolver.cc b/pdns/stubresolver.cc index 87505e05c..e1a8935f9 100644 --- a/pdns/stubresolver.cc +++ b/pdns/stubresolver.cc @@ -99,7 +99,7 @@ int stubDoResolve(const string& qname, uint16_t qtype, vector catch(...) { continue; } - MOADNSParser mdp(reply); + MOADNSParser mdp(false, reply); if(mdp.d_header.rcode == RCode::ServFail) continue; diff --git a/pdns/tcpreceiver.cc b/pdns/tcpreceiver.cc index c18c1f75a..dfcc45406 100644 --- a/pdns/tcpreceiver.cc +++ b/pdns/tcpreceiver.cc @@ -297,7 +297,7 @@ void *TCPNameserver::doConnection(void *data) else S.inc("tcp4-queries"); - packet=shared_ptr(new DNSPacket); + packet=shared_ptr(new DNSPacket(true)); packet->setRemote(&remote); packet->d_tcp=true; packet->setSocket(fd); @@ -317,7 +317,7 @@ void *TCPNameserver::doConnection(void *data) } shared_ptr reply; - shared_ptr cached= shared_ptr(new DNSPacket); + shared_ptr cached= shared_ptr(new DNSPacket(false)); if(logDNSQueries) { string remote; if(packet->hasEDNSSubnet()) @@ -1034,7 +1034,7 @@ int TCPNameserver::doIXFR(shared_ptr q, int outsock) outpacket->d_dnssecOk=true; // RFC 5936, 2.2.5 'SHOULD' uint32_t serial = 0; - MOADNSParser mdp(q->getString()); + MOADNSParser mdp(false, q->getString()); for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i != mdp.d_answers.end(); ++i) { const DNSRecord *rr = &i->first; if (rr->d_type == QType::SOA && rr->d_place == DNSResourceRecord::AUTHORITY) { diff --git a/pdns/test-distributor_hh.cc b/pdns/test-distributor_hh.cc index a1cd677bc..63ae49d3a 100644 --- a/pdns/test-distributor_hh.cc +++ b/pdns/test-distributor_hh.cc @@ -19,7 +19,7 @@ struct Question DNSName qdomain; DNSPacket* replyPacket() { - return new DNSPacket(); + return new DNSPacket(false); } }; @@ -27,7 +27,7 @@ struct Backend { DNSPacket* question(Question*) { - return new DNSPacket(); + return new DNSPacket(true); } }; @@ -62,7 +62,7 @@ struct BackendSlow DNSPacket* question(Question*) { sleep(1); - return new DNSPacket(); + return new DNSPacket(true); } }; @@ -96,7 +96,7 @@ struct BackendDies // cerr<<"Going.. down!"< s_count; int d_count{0}; diff --git a/pdns/test-dnscrypt_cc.cc b/pdns/test-dnscrypt_cc.cc index 804727934..cbc32454d 100644 --- a/pdns/test-dnscrypt_cc.cc +++ b/pdns/test-dnscrypt_cc.cc @@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(DNSCryptPlaintextQuery) { ctx.getCertificateResponse(query, response); - MOADNSParser mdp((char*) response.data(), response.size()); + MOADNSParser mdp(false, (char*) response.data(), response.size()); BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1); BOOST_CHECK_EQUAL(mdp.d_header.ancount, 1); @@ -177,7 +177,7 @@ BOOST_AUTO_TEST_CASE(DNSCryptEncryptedQueryValid) { BOOST_CHECK_EQUAL(query->valid, true); BOOST_CHECK_EQUAL(query->encrypted, true); - MOADNSParser mdp((char*) plainQuery.data(), decryptedLen); + MOADNSParser mdp(true, (char*) plainQuery.data(), decryptedLen); BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1); BOOST_CHECK_EQUAL(mdp.d_header.ancount, 0); @@ -269,7 +269,7 @@ BOOST_AUTO_TEST_CASE(DNSCryptEncryptedQueryValidWithOldKey) { BOOST_CHECK_EQUAL(query->valid, true); BOOST_CHECK_EQUAL(query->encrypted, true); - MOADNSParser mdp((char*) plainQuery.data(), decryptedLen); + MOADNSParser mdp(true, (char*) plainQuery.data(), decryptedLen); BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1); BOOST_CHECK_EQUAL(mdp.d_header.ancount, 0); diff --git a/pdns/test-dnsdist_cc.cc b/pdns/test-dnsdist_cc.cc index fe8a8ff36..1a52dec77 100644 --- a/pdns/test-dnsdist_cc.cc +++ b/pdns/test-dnsdist_cc.cc @@ -45,7 +45,7 @@ bool g_verbose{true}; static void validateQuery(const char * packet, size_t packetSize) { - MOADNSParser mdp(packet, packetSize); + MOADNSParser mdp(true, packet, packetSize); BOOST_CHECK_EQUAL(mdp.d_qname.toString(), "www.powerdns.com."); @@ -57,7 +57,7 @@ static void validateQuery(const char * packet, size_t packetSize) static void validateResponse(const char * packet, size_t packetSize, bool hasEdns, uint8_t additionalCount=0) { - MOADNSParser mdp(packet, packetSize); + MOADNSParser mdp(false, packet, packetSize); BOOST_CHECK_EQUAL(mdp.d_qname.toString(), "www.powerdns.com."); diff --git a/pdns/test-dnsrecords_cc.cc b/pdns/test-dnsrecords_cc.cc index f8da82f04..576c42d5d 100644 --- a/pdns/test-dnsrecords_cc.cc +++ b/pdns/test-dnsrecords_cc.cc @@ -284,14 +284,15 @@ BOOST_AUTO_TEST_CASE(test_opt_record_in) { std::string packet("\xf0\x01\x01\x00\x00\x01\x00\x01\x00\x00\x00\x01\x03www\x08powerdns\x03""com\x00\x00\x01\x00\x01\x03www\x08powerdns\x03""com\x00\x00\x01\x00\x01\x00\x00\x00\x10\x00\x04\x7f\x00\x00\x01\x00\x00\x29\x05\x00\x00\x00\x00\x00\x00\x0c\x00\x03\x00\x08powerdns",89); OPTRecordContent::report(); - MOADNSParser mdp((char*)&*packet.begin(), (unsigned int)packet.size()); + MOADNSParser mdp(true, (char*)&*packet.begin(), (unsigned int)packet.size()); - getEDNSOpts(mdp, &eo); + BOOST_CHECK_EQUAL(getEDNSOpts(mdp, &eo), true); // this should contain NSID now BOOST_CHECK_EQUAL(eo.d_packetsize, 1280); // it should contain NSID option with value 'powerdns', and nothing else + BOOST_CHECK_EQUAL(eo.d_options.size(), 1); BOOST_CHECK_EQUAL(eo.d_options[0].first, 3); // nsid BOOST_CHECK_EQUAL(eo.d_options[0].second, "powerdns"); } diff --git a/pdns/test-packetcache_cc.cc b/pdns/test-packetcache_cc.cc index ad6353cb1..eaecb27c1 100644 --- a/pdns/test-packetcache_cc.cc +++ b/pdns/test-packetcache_cc.cc @@ -197,7 +197,7 @@ BOOST_AUTO_TEST_CASE(test_PacketCachePacket) { vector > opts; DNSPacketWriter pw(pak, DNSName("www.powerdns.com"), QType::A); - DNSPacket q, r, r2; + DNSPacket q(true), r(false), r2(false); q.parse((char*)&pak[0], pak.size()); pak.clear(); diff --git a/pdns/toysdig.cc b/pdns/toysdig.cc index 4992b0574..eca198f87 100644 --- a/pdns/toysdig.cc +++ b/pdns/toysdig.cc @@ -86,7 +86,7 @@ public: { TCPResolver tr(d_dest); string resp=tr.query(qname, qtype); - MOADNSParser mdp(resp); + MOADNSParser mdp(false, resp); vector ret; ret.reserve(mdp.d_answers.size()); for(const auto& a : mdp.d_answers) { diff --git a/pdns/tsig-tests.cc b/pdns/tsig-tests.cc index 1c54284bf..b0306b593 100644 --- a/pdns/tsig-tests.cc +++ b/pdns/tsig-tests.cc @@ -65,7 +65,7 @@ try string reply; sock.recvFrom(reply, dest); - MOADNSParser mdp(reply); + MOADNSParser mdp(false, reply); cout<<"Reply to question for qname='"<& new_ptrs) { for(const DNSResourceRecord& rr : new_ptrs) { - DNSPacket fakePacket; + DNSPacket fakePacket(false); SOAData sd; sd.db = (DNSBackend *)-1; // getAuth() cache bypass fakePacket.qtype = QType::PTR;