[Pdns-users] CNAME confusion?!
Andreas Mimz
dnsadmin at kos2.de
Tue Jan 25 10:46:15 UTC 2005
Ouch... looks like I haven't tested enough! I needed to revert to the
official version because now there is another Bug ;-)
It's no longer possible to perform ANY queries, so "dig kos2.de ANY
@ns4.skcserver.de" (ns4 is the one which is running with the replaced
file), where "dig kos2.de ANY @ns2.skcserver.de" (official 2.9.17)
works! With this new bug it's no longer possible to delegate new domains
to the nameservers :-(
Any Ideas?
Andreas Mimz wrote:
> So after a couple of days I have to say that the replaced file works
> perfectly :-) No more wrong CNAME mappings (even with AAAA-Questions)!
> No other problems occured so far... (or atleast I didn't notice ;-))
>
> Thank you very much!
>
>
> bert hubert wrote:
>
>> Ok, that probably won't work (patch issues, subversion migration
>> leftover),
>> and a thinko.
>>
>> Try replacing packethandler.cc in pdns 2.9.17 by the attached version.
>>
>>
>> On Sat, Jan 15, 2005 at 03:08:11PM +0100, bert hubert wrote:
>>
>>
>>> Can you try this patch? It is entirely untested, but it might solve the
>>> problem. Wiebren, your problem too I think.
>>>
>>>
>>
>>
>> ------------------------------------------------------------------------
>>
>> /*
>> PowerDNS Versatile Database Driven Nameserver
>> Copyright (C) 2005 PowerDNS.COM BV
>>
>> This program is free software; you can redistribute it and/or modify
>> it under the terms of the GNU General Public License as published by
>> the Free Software Foundation; either version 2 of the License, or
>> (at your option) any later version.
>>
>> This program is distributed in the hope that it will be useful,
>> but WITHOUT ANY WARRANTY; without even the implied warranty of
>> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> GNU General Public License for more details.
>>
>> You should have received a copy of the GNU General Public License
>> along with this program; if not, write to the Free Software
>> Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
>> 02111-1307 USA
>> */
>> #include "utility.hh"
>> #include <string>
>> #include <sys/types.h>
>>
>> #include "dns.hh"
>> #include "dnsbackend.hh"
>> #include "ueberbackend.hh"
>> #include "dnspacket.hh"
>> #include "nameserver.hh"
>> #include "distributor.hh"
>> #include "logger.hh"
>> #include "arguments.hh"
>> #include "packethandler.hh"
>> #include "statbag.hh"
>> #include "resolver.hh"
>> #include "communicator.hh"
>> #include "dnsproxy.hh"
>>
>> extern StatBag S;
>> extern PacketCache PC; extern CommunicatorClass Communicator;
>> extern DNSProxy *DP;
>>
>> int PacketHandler::s_count;
>> extern string s_programname;
>>
>> PacketHandler::PacketHandler():B(s_programname)
>> {
>> s_count++;
>> d_doFancyRecords = (arg()["fancy-records"]!="no");
>> d_doWildcards = (arg()["wildcards"]!="no");
>> d_doCNAME = (arg()["skip-cname"]=="no");
>> d_doRecursion= arg().mustDo("recursor");
>> d_logDNSDetails= arg().mustDo("log-dns-details");
>> d_doIPv6AdditionalProcessing =
>> arg().mustDo("do-ipv6-additional-processing");
>> }
>>
>> DNSBackend *PacketHandler::getBackend()
>> {
>> return &B;
>> }
>>
>> PacketHandler::~PacketHandler()
>> {
>> --s_count;
>> DLOG(L<<Logger::Error<<"PacketHandler destructor called -
>> "<<s_count<<" left"<<endl);
>> }
>>
>>
>> int PacketHandler::findMboxFW(DNSPacket *p, DNSPacket *r, string
>> &target)
>> {
>> DNSResourceRecord rr;
>> bool wedoforward=false;
>>
>> SOAData sd;
>> int zoneId;
>> if(!getAuth(p, &sd, target, &zoneId))
>> return false;
>>
>> B.lookup("MBOXFW",string("%@")+target,p, zoneId);
>> while(B.get(rr))
>> wedoforward=true;
>>
>> if(wedoforward) {
>> rr.content=arg()["smtpredirector"];
>> rr.priority=25;
>> rr.ttl=7200;
>> rr.qtype=QType::MX;
>> rr.qname=target;
>> r->addRecord(rr);
>> }
>>
>> return wedoforward;
>> }
>>
>> int PacketHandler::findUrl(DNSPacket *p, DNSPacket *r, string &target)
>> {
>> DNSResourceRecord rr;
>>
>> bool found=false;
>> B.lookup("URL",target,p); // search for a URL before we search
>> for an A
>> while(B.get(rr)) {
>> found=true;
>> DLOG(L << "Found a URL!" << endl);
>> rr.content=arg()["urlredirector"];
>> rr.qtype=QType::A; rr.qname=target;
>> r->addRecord(rr);
>> }
>> if(found)
>> return 1;
>> // now try CURL
>>
>> B.lookup("CURL",target,p); // search for a URL before we search for
>> an A
>> while(B.get(rr)) {
>> found=true;
>> DLOG(L << "Found a CURL!" << endl);
>> rr.content=arg()["urlredirector"];
>> rr.qtype=1; // A
>> rr.qname=target;
>> rr.ttl=300;
>> r->addRecord(rr);
>> }
>> if(found)
>> return found;
>> return 0;
>> }
>>
>> /** Returns 0 if nothing was found, -1 if an error occured or 1 if
>> the search
>> was satisfied */
>> int PacketHandler::doFancyRecords(DNSPacket *p, DNSPacket *r, string
>> &target)
>> {
>> DNSResourceRecord rr;
>>
>> if(p->qtype.getCode()==QType::MX) // check if this domain has smtp
>> service from us
>> return findMboxFW(p,r,target);
>>
>> if(p->qtype.getCode()==QType::A) // search for a URL record for an A
>> return findUrl(p,r,target);
>>
>> return 0;
>> }
>>
>> int PacketHandler::doDNSCheckRequest(DNSPacket *p, DNSPacket *r,
>> string &target)
>> {
>> int result = 0;
>> DNSResourceRecord rr;
>>
>> if (p->qclass == 3 && p->qtype.getName() == "HINFO") {
>> rr.content = "PowerDNS $Id: packethandler.cc 266 2005-01-11
>> 19:41:11Z ahu $";
>> rr.ttl = 5;
>> rr.qname=target;
>> rr.qtype=13; // hinfo
>> r->addRecord(rr);
>> result = 1;
>> }
>>
>> return result;
>> }
>>
>> /** This catches version requests. Returns 1 if it was handled, 0 if
>> it wasn't */
>> int PacketHandler::doVersionRequest(DNSPacket *p, DNSPacket *r,
>> string &target)
>> {
>> DNSResourceRecord rr;
>>
>> // modes: anonymous, powerdns only, full, spoofed
>> const string mode=arg()["version-string"];
>> if(p->qtype.getCode()==QType::TXT && target=="version.bind") {// TXT
>> if(mode.empty() || mode=="full") rr.content="Served by
>> POWERDNS "VERSION" $Id: packethandler.cc 266 2005-01-11 19:41:11Z ahu
>> $";
>> else if(mode=="anonymous") {
>> r->setRcode(RCode::ServFail);
>> return 1;
>> }
>> else if(mode=="powerdns")
>> rr.content="Served by PowerDNS - http://www.powerdns.com";
>> else rr.content=mode;
>>
>> rr.ttl=5;
>> rr.qname=target;
>> rr.qtype=QType::TXT; // TXT
>> r->addRecord(rr);
>> return 1;
>> }
>> return 0;
>> }
>>
>> /** Determines if we are authoritative for a zone, and at what level */
>> bool PacketHandler::getAuth(DNSPacket *p, SOAData *sd, const string
>> &target, int *zoneId)
>> {
>> string subdomain(target);
>> do {
>> if( B.getSOA( subdomain, *sd ) ) {
>> sd->qname = subdomain;
>> *zoneId = sd->domain_id;
>> return true;
>> }
>> }
>> while( chopOff( subdomain ) ); // 'www.powerdns.org' ->
>> 'powerdns.org' -> 'org' -> ''
>> return false;
>> }
>>
>> /** returns 1 in case of a straight match, 2 in case of a wildcard
>> CNAME (groan), 0 in case of no hit */
>> int PacketHandler::doWildcardRecords(DNSPacket *p, DNSPacket *r,
>> string &target)
>> {
>> DNSResourceRecord rr;
>> bool found=false, retargeted=false;
>>
>> // try chopping off domains and look for wildcard matches
>>
>> // *.pietje.nl IN A 1.2.3.4
>> // pietje.nl should now NOT match, but www.pietje.nl should
>>
>> string subdomain=target;
>> string::size_type pos;
>> while((pos=subdomain.find("."))!=string::npos) {
>> subdomain=subdomain.substr(pos+1);
>> // DLOG();
>>
>> string searchstr=string("*.")+subdomain;
>>
>> B.lookup(QType(QType::ANY), searchstr,p); // start our search at
>> the backend
>>
>> while(B.get(rr)) { // read results
>> found=true;
>> if((p->qtype.getCode()==QType::ANY || rr.qtype==p->qtype) ||
>> rr.qtype.getCode()==QType::CNAME) {
>> rr.qname=target;
>> r->addRecord(rr); // and add
>> if(rr.qtype.getCode()==QType::CNAME) {
>> if(target==rr.content) {
>> L<<Logger::Error<<"Ignoring wildcard CNAME '"<<rr.qname<<"'
>> pointing at itself"<<endl;
>> r->setRcode(RCode::ServFail);
>> continue;
>> }
>> DLOG(L<<Logger::Error<<"Retargeting because of wildcard
>> cname, from "<<target<<" to "<<rr.content<<endl);
>> target=rr.content; // retarget retargeted=true;
>> }
>> }
>> else if(d_doFancyRecords && arg().mustDo("wildcard-url") &&
>> p->qtype.getCode()==QType::A && rr.qtype.getName()=="URL") {
>> rr.content=arg()["urlredirector"];
>> rr.qtype=QType::A; rr.qname=target;
>>
>> r->addRecord(rr);
>> }
>> }
>> if(found) {
>> DLOG(L<<"Wildcard match on '"<<string("*.")+subdomain<<"'"<<endl);
>> return retargeted ? 2 : 1;
>> }
>> }
>> return 0;
>> }
>>
>> /** dangling is declared true if we were unable to resolve everything */
>> int PacketHandler::doAdditionalProcessingAndDropAA(DNSPacket *p,
>> DNSPacket *r)
>> {
>> DNSResourceRecord rr;
>> SOAData sd;
>>
>> if(p->qtype.getCode()!=QType::AXFR && r->needAP()) { // this packet
>> needs additional processing
>> DLOG(L<<Logger::Warning<<"This packet needs additional
>> processing!"<<endl);
>>
>> vector<DNSResourceRecord *> arrs=r->getAPRecords();
>> vector<DNSResourceRecord> crrs;
>>
>> for(vector<DNSResourceRecord *>::const_iterator i=arrs.begin();
>> i!=arrs.end(); ++i) crrs.push_back(**i);
>>
>> // we now have a copy, push_back on packet might reallocate!
>>
>> for(vector<DNSResourceRecord>::const_iterator i=crrs.begin();
>> i!=crrs.end();
>> ++i) {
>> if(i->qtype.getCode()==QType::NS && !B.getSOA(i->qname,sd))
>> { // drop AA in case of non-SOA-level NS answer
>> r->d.aa=false;
>> // i->d_place=DNSResourceRecord::AUTHORITY; // XXX FIXME
>> }
>>
>> QType qtypes[2];
>> qtypes[0]="A"; qtypes[1]="AAAA";
>> for(int n=0;n < d_doIPv6AdditionalProcessing + 1; ++n) {
>> B.lookup(qtypes[n],i->content,p); bool foundOne=false;
>> while(B.get(rr)) {
>> foundOne=true;
>> if(rr.domain_id!=i->domain_id &&
>> arg()["out-of-zone-additional-processing"]=="no") {
>> DLOG(L<<Logger::Warning<<"Not including out-of-zone
>> additional processing of "<<i->qname<<" ("<<rr.qname<<")"<<endl);
>> continue; // not adding out-of-zone additional data
>> }
>> rr.d_place=DNSResourceRecord::ADDITIONAL;
>> r->addRecord(rr);
>> }
>> if(!foundOne) {
>> if(d_doRecursion && DP->recurseFor(p)) {
>> try {
>> Resolver resolver;
>>
>> resolver.resolve(arg()["recursor"],i->content.c_str(),QType::A);
>> Resolver::res_t res=resolver.result();
>> for(Resolver::res_t::const_iterator
>> j=res.begin();j!=res.end();++j) {
>> if(j->d_place==DNSResourceRecord::ANSWER) {
>> rr=*j;
>> rr.d_place=DNSResourceRecord::ADDITIONAL;
>> r->addRecord(rr);
>> }
>> }
>> }
>> catch(ResolverException& re) {
>> // L<<Logger::Error<<"Trying to do additional processing
>> for answer to '"<<p->qdomain<<"' query: "<<re.reason<<endl;
>> }
>> }
>> }
>> }
>> }
>> }
>> return 1;
>> }
>>
>> /* returns 1 if everything is done & ready, 0 if the search should
>> continue */
>> int PacketHandler::makeCanonic(DNSPacket *p, DNSPacket *r, string
>> &target)
>> {
>> DNSResourceRecord rr;
>>
>> bool found=false, rfound=false;
>>
>> if(p->qtype.getCode()!=QType::CNAME && !d_doCNAME)
>> return 0;
>>
>> // Traverse a CNAME chain if needed
>> for(int numloops=0;;numloops++) {
>> if(numloops==10) {
>> L<<Logger::Error<<"Detected a CNAME loop involving "<<target<<",
>> sending SERVFAIL"<<endl;
>> r->setRcode(2);
>> return 1;
>> }
>>
>> B.lookup(QType(QType::ANY),target,p);
>> bool shortcut=p->qtype.getCode()!=QType::SOA &&
>> p->qtype.getCode()!=QType::ANY;
>> unsigned hits=0;
>> while(B.get(rr)) {
>> hits++;
>> if(!rfound && rr.qtype.getCode()==QType::CNAME) {
>> found=true;
>> r->addRecord(rr);
>> target=rr.content; // for retargeting
>> }
>> if(shortcut && !found && rr.qtype==p->qtype) {
>> rfound=true;
>> r->addRecord(rr);
>> }
>> }
>> if( (p->qtype.getCode()!=QType::SOA && hits) || rfound)
>> return 1; // ANY lookup found the right answer immediately
>>
>> if(found) {
>> if(p->qtype.getCode()==QType::CNAME) // they really wanted a CNAME!
>> return 1;
>> DLOG(L<<"Looping because of a CNAME to "<<target<<endl);
>> found=false;
>> }
>> else break;
>> }
>>
>> // we now have what we really search for ready in 'target'
>> return 0;
>> }
>>
>> /* Semantics:
>> - only one backend owns the SOA of a zone
>> - only one AXFR per zone at a time - double startTransaction should fail
>> - backends need to implement transaction semantics
>>
>>
>> How BindBackend would implement this:
>> startTransaction makes a file feedRecord sends everything to that
>> file commitTransaction moves that file atomically over the regular
>> file, and triggers a reload
>> rollbackTransaction removes the file
>>
>>
>> How PostgreSQLBackend would implement this:
>> startTransaction starts a sql transaction, which also deletes all
>> records
>> feedRecord is an insert statement
>> commitTransaction commits the transaction
>> rollbackTransaction aborts it
>>
>> How MySQLBackend would implement this:
>> (good question!)
>> */
>> int PacketHandler::trySuperMaster(DNSPacket *p)
>> {
>> Resolver::res_t nsset;
>> try {
>> Resolver resolver;
>> u_int32_t theirserial;
>> int res=resolver.getSoaSerial(p->getRemote(),p->qdomain,
>> &theirserial); if(res<=0) {
>> L<<Logger::Error<<"Unable to determine SOA serial for
>> "<<p->qdomain<<" at potential supermaster "<<p->getRemote()<<endl;
>> return RCode::ServFail;
>> }
>>
>> resolver.resolve(p->getRemote(),p->qdomain.c_str(), QType::NS);
>>
>> nsset=resolver.result();
>> }
>> catch(ResolverException &re) {
>> L<<Logger::Error<<"Error resolving SOA or NS for
>> '"<<p->qdomain<<"' at "<<p->getRemote()<<endl;
>> return RCode::ServFail;
>> }
>>
>> string account;
>> DNSBackend *db;
>> if(!B.superMasterBackend(p->getRemote(), p->qdomain, nsset,
>> &account, &db)) {
>> L<<Logger::Error<<"Unable to find backend willing to host
>> "<<p->qdomain<<" for potential supermaster "<<p->getRemote()<<endl;
>> return RCode::Refused;
>> }
>> db->createSlaveDomain(p->getRemote(),p->qdomain,account);
>> Communicator.addSuckRequest(p->qdomain, p->getRemote());
>> L<<Logger::Warning<<"Created new slave zone '"<<p->qdomain<<"' from
>> supermaster "<<p->getRemote()<<", queued axfr"<<endl;
>> return RCode::NoError;
>> }
>>
>> int PacketHandler::processNotify(DNSPacket *p)
>> {
>> /* now what? was this notification from an approved address?
>> We determine our internal SOA id (via UeberBackend)
>> We determine the SOA at our (known) master
>> if master is higher -> do stuff
>> */
>> if(!arg().mustDo("slave")) {
>> L<<Logger::Error<<"Received NOTIFY for "<<p->qdomain<<" from
>> "<<p->getRemote()<<" but slave support is disabled in the
>> configuration"<<endl;
>> return RCode::NotImp;
>> }
>> DNSBackend *db=0;
>> DomainInfo di;
>> if(!B.getDomainInfo(p->qdomain,di) || !(db=di.backend)) {
>> L<<Logger::Error<<"Received NOTIFY for "<<p->qdomain<<" from
>> "<<p->getRemote()<<" for which we are not authoritative"<<endl;
>> return trySuperMaster(p);
>> }
>> if(!db->isMaster(p->qdomain, p->getRemote())) {
>> L<<Logger::Error<<"Received NOTIFY for "<<p->qdomain<<" from
>> "<<p->getRemote()<<" which is not a master"<<endl;
>> return RCode::Refused;
>> }
>>
>> u_int32_t theirserial=0;
>>
>> /* to quote Rusty Russell - this code is so bad that you can
>> actually hear it suck */
>> /* this is an instant DoS, just spoof notifications from the address
>> of the master and we block */
>>
>> Resolver resolver;
>> int res=resolver.getSoaSerial(p->getRemote(),p->qdomain, &theirserial);
>> if(res<=0) {
>> L<<Logger::Error<<"Unable to determine SOA serial for
>> "<<p->qdomain<<" at "<<p->getRemote()<<endl;
>> return RCode::ServFail;
>> }
>>
>>
>> if(theirserial<=di.serial) {
>> L<<Logger::Error<<"Received NOTIFY for "<<p->qdomain<<" from
>> master "<<p->getRemote()<<", we are up to date: "<<
>> theirserial<<"<="<<di.serial<<endl;
>> return RCode::NoError;
>> }
>> else {
>> L<<Logger::Error<<"Received valid NOTIFY for "<<p->qdomain<<"
>> (id="<<di.id<<") from master "<<p->getRemote()<<": "<<
>> theirserial<<" > "<<di.serial<<endl;
>>
>> Communicator.addSuckRequest(p->qdomain, p->getRemote(),true); //
>> priority
>> }
>> return -1; }
>>
>>
>> //! Called by the Distributor to ask a question. Returns 0 in case of
>> an error
>> DNSPacket *PacketHandler::question(DNSPacket *p)
>> {
>> DNSResourceRecord rr;
>> SOAData sd;
>> sd.db=0;
>>
>> string subdomain="";
>> string soa;
>> int retargetcount=0;
>> bool noSameLevelNS;
>>
>> DNSPacket *r=0;
>> try { DLOG(L << Logger::Notice<<"Remote "<<inet_ntoa(
>> reinterpret_cast< struct sockaddr_in * >( &( p->remote ))->sin_addr
>> )<<" wants a type " << p->qtype.getName() << "
>> ("<<p->qtype.getCode()<<") about '"<<p->qdomain << "'" << endl);
>>
>> // XXX FIXME Find out why this isn't working!
>> #ifndef WIN32
>> if(p->d.qr) { // QR bit from dns packet (thanks RA from N)
>> L<<Logger::Error<<"Received an answer (non-query) packet from
>> "<<p->getRemote()<<", dropping"<<endl;
>> S.inc("corrupt-packets");
>> return 0;
>> }
>> #endif // WIN32
>>
>> // XXX FIXME do this in DNSPacket::parse ?
>>
>> if(!p->qdomain.empty() &&
>> p->qdomain.find_first_of("%|")!=string::npos) {
>> L<<Logger::Error<<"Received a malformed qdomain from
>> "<<p->getRemote()<<", '"<<p->qdomain<<"': dropping"<<endl;
>> S.inc("corrupt-packets");
>> return 0;
>> }
>> if(p->d.opcode) { // non-zero opcode (again thanks RA!)
>> if(p->d.opcode==Opcode::Update) {
>> if(arg().mustDo("log-failed-updates"))
>> L<<Logger::Notice<<"Received an UPDATE opcode from
>> "<<p->getRemote()<<" for "<<p->qdomain<<", sending NOTIMP"<<endl;
>> r=p->replyPacket(); r->setRcode(RCode::NotImp); // notimp;
>> return r; }
>> else if(p->d.opcode==Opcode::Notify) {
>> int res=processNotify(p);
>> if(res>=0) {
>> DNSPacket *r=p->replyPacket();
>> r->setRcode(res);
>> return r;
>> }
>> return 0;
>> }
>> L<<Logger::Error<<"Received an unknown opcode
>> "<<p->d.opcode<<" from "<<p->getRemote()<<" for "<<p->qdomain<<endl;
>>
>> r=p->replyPacket(); r->setRcode(RCode::NotImp); return
>> r; }
>> r=p->replyPacket(); // generate an empty reply packet
>>
>> if(p->qtype.getCode()==QType::IXFR) {
>> r->setRcode(RCode::NotImp);
>> return r;
>> }
>>
>> bool found=false;
>> string target=p->qdomain;
>> if (doDNSCheckRequest(p, r, target))
>> goto sendit;
>> if(doVersionRequest(p,r,target)) // catch version.bind requests
>> goto sendit;
>>
>> if(p->qclass==255) // any class query r->setA(false);
>> else if(p->qclass!=1) // we only know about IN, so we don't find
>> anything
>> goto sendit;
>>
>> retargeted:;
>> if(retargetcount++>10) {
>> L<<Logger::Error<<"Detected wildcard CNAME loop involving
>> '"<<target<<"'"<<endl;
>> r->setRcode(RCode::ServFail);
>> goto sendit;
>> }
>>
>> if(makeCanonic(p,r,target)>0) // traverse CNAME chain until we
>> have a useful record (may actually give the correct answer!)
>> goto sendit; // this might be the end of it (client requested a
>> CNAME, or we found the answer already)
>> if(d_doFancyRecords) { // MBOXFW, URL <- fake records, emulated
>> with MX and A
>> int res=doFancyRecords(p,r,target);
>> if(res) { // had a result
>> if(res<0) // it was an error
>> r->setRcode(RCode::ServFail);
>> goto sendit; }
>> }
>> // now ready to start the real direct search
>>
>> if(p->qtype.getCode()==QType::SOA ||
>> p->qtype.getCode()==QType::ANY) { // this is special
>>
>> if(B.getSOA(target,sd)) {
>> rr.qname=target;
>> rr.qtype=QType::SOA;
>> rr.content=DNSPacket::serializeSOAData(sd);
>> rr.ttl=sd.ttl;
>> rr.domain_id=sd.domain_id;
>> rr.d_place=DNSResourceRecord::ANSWER;
>> r->addRecord(rr);
>> if(p->qtype.getCode()==QType::SOA) { // we are done
>> goto sendit;
>> }
>> }
>> }
>>
>> noSameLevelNS=true;
>>
>> if(p->qtype.getCode()!=QType::SOA) { // regular direct lookup
>> B.lookup(QType(QType::ANY), target,p);
>> while(B.get(rr)) {
>> if(rr.qtype.getCode()==QType::SOA) // skip any direct SOA
>> responses as they may be different
>> continue;
>> if(rr.qtype==p->qtype || p->qtype.getCode()==QType::ANY ) {
>> DLOG(L<<"Found a direct answer: "<<rr.content<<endl);
>> found=true;
>> r->addRecord(rr); // and add
>> }
>> else
>> if(rr.qtype.getCode()==QType::NS)
>> noSameLevelNS=false;
>> }
>> if(p->qtype.getCode()==QType::ANY) {
>> if(d_doFancyRecords) { int res=findMboxFW(p,r,target);
>> if(res<0)
>> L<<Logger::Error<<"Error finding a mailbox record after an
>> ANY query"<<endl;
>> if(res>0) {
>> DLOG(L<<Logger::Error<<"Frobbed an MX in!"<<endl);
>> found=true;
>> }
>> }
>> }
>> if(found) goto sendit;
>> }
>> // not found yet, try wildcards (we only try here in case of
>> recursion - we should check before we hand off)
>>
>> if(p->d.rd && d_doRecursion && d_doWildcards) { int
>> res=doWildcardRecords(p,r,target);
>> if(res) { // had a result
>> // FIXME: wildCard may retarget us in the future
>> if(res==1) // had a straight result
>> goto sendit; if(res==2)
>> goto retargeted;
>> goto sendit; }
>> }
>>
>> // RECURSION CUT-OUT!
>>
>> bool weAuth;
>> int zoneId;
>> zoneId=-1;
>> if(p->d.rd && d_doRecursion &&
>> arg().mustDo("allow-recursion-override"))
>> weAuth=getAuth(p, &sd, target, &zoneId);
>> else
>> weAuth=false;
>>
>> if(p->d.rd && d_doRecursion && !weAuth && DP->sendPacket(p)) {
>> delete r;
>> return 0;
>> }
>>
>> string::size_type pos;
>> DLOG(L<<"Nothing found so far for '"<<target<<"', do we even
>> have authority over this domain?"<<endl);
>>
>> if(zoneId==-1)
>> weAuth=getAuth(p, &sd, target, &zoneId); // TLDAuth perhaps
>>
>> if(weAuth) {
>> DLOG(L<<Logger::Warning<<"Soa found: "<<soa<<endl);
>> ;
>> }
>> if(!weAuth) {
>> if(p->d.rd || target==p->qdomain) { // only servfail if we
>> didn't follow a CNAME
>> if(d_logDNSDetails)
>> L<<Logger::Warning<<"Not authoritative for '"<< target<<"',
>> sending servfail to "<<
>> p->getRemote()<< (p->d.rd ? " (recursion was desired)" : "")
>> <<endl;
>>
>> r->setA(false);
>> r->setRcode(RCode::ServFail); // 'sorry' - this is where we
>> might send out a root referral
>> }
>>
>> S.ringAccount("unauth-queries",p->qdomain+"/"+p->qtype.getName());
>> S.ringAccount("remotes-unauth",p->getRemote());
>> }
>> else {
>> DLOG(L<<Logger::Warning<<"We ARE authoritative for a subdomain
>> of '"<<target<<"' ("<<sd.qname<<"), perhaps we have a suitable NS
>> record then"<<endl);
>> subdomain=target;
>> found=0;
>> pos=0; do {
>> if(pos) // skip dot
>> pos++;
>>
>> subdomain=subdomain.substr(pos);
>> if(noSameLevelNS) { // skip first lookup if it is known not to exist
>> noSameLevelNS=false;
>> continue;
>> }
>>
>> if(!Utility::strcasecmp(subdomain.c_str(),sd.qname.c_str())) //
>> about to break out of our zone
>> break;
>> B.lookup("NS", subdomain,p,zoneId); // start our search at the
>> backend
>>
>> while(B.get(rr)) {
>> found=true;
>> rr.d_place=DNSResourceRecord::AUTHORITY; // this for the
>> authority section
>> r->addRecord(rr);
>> }
>> if(found || (!subdomain.empty() && subdomain[0]=='.')) { // this
>> catches '..'
>> r->setA(false); // send out an NS referral, which should be
>> unauth
>> break;
>> }
>> }while((pos=subdomain.find("."))!=string::npos);
>> if(!found) {
>> // try wildcards then if(d_doWildcards) { int
>> res=doWildcardRecords(p,r,target);
>>
>> if(res==1) // had a straight result
>> goto sendit; if(res==2)
>> goto retargeted;
>> }
>>
>> // we have authority but no answer, so we add the SOA for
>> negative caching
>> rr.qname=sd.qname;
>> rr.qtype=QType::SOA;
>> rr.content=DNSPacket::serializeSOAData(sd);
>> rr.ttl=sd.ttl;
>> rr.domain_id=sd.domain_id;
>> rr.d_place=DNSResourceRecord::AUTHORITY;
>> r->addRecord(rr);
>>
>>
>> // need to send NXDOMAIN if there are 0 records for whatever type
>> for target
>>
>> B.lookup("ANY",target,p);
>> while(B.get(rr))
>> found=true;
>>
>> if(!found) {
>> SOAData sd2;
>> if(B.getSOA(target,sd2)) // is there a SOA perhaps? (which may
>> not appear in an ANY query)
>> found=true;
>> }
>>
>> if(!found) { if(d_logDNSDetails)
>> L<<Logger::Notice<<"Authoritative NXDOMAIN to "<<
>> p->getRemote() <<" for '"<<target<<"' ("<<p->qtype.getName()<<")"<<endl;
>>
>> r->setRcode(RCode::NXDomain);
>> S.ringAccount("nxdomain-queries",p->qdomain+"/"+p->qtype.getName());
>> }
>> else {
>> if(d_logDNSDetails)
>> L<<Logger::Notice<<"Authoritative empty NO ERROR to "<<
>> p->getRemote() <<" for '"<<target<<"' ("<<p->qtype.getName()<<"),
>> other types do exist"<<endl;
>>
>> S.ringAccount("noerror-queries",p->qdomain+"/"+p->qtype.getName());
>> }
>> }
>> }
>> // whatever we've built so far, do additional processing
>> sendit:;
>>
>> if(doAdditionalProcessingAndDropAA(p,r)<0)
>> return 0;
>>
>>
>> r->wrapup(); // needed for inserting in cache
>> PC.insert(p,r); // in the packet cache
>> }
>> catch(DBException &e) {
>> L<<Logger::Error<<"Database module reported condition which
>> prevented lookup - sending out servfail"<<endl;
>> r->setRcode(RCode::ServFail);
>> S.inc("servfail-packets");
>> S.ringAccount("servfail-queries",p->qdomain);
>> }
>> return r;
>> }
>>
>>
>>
>
>
> _______________________________________________
> Pdns-users mailing list
> Pdns-users at mailman.powerdns.com
> http://mailman.powerdns.com/mailman/listinfo/pdns-users
More information about the Pdns-users
mailing list