[Pdns-dev] pdns bug when using multiple backends

Ben McKeegan ben at mckeegan.org
Sun Nov 16 01:50:04 CET 2003


Dear PDNS developers,

I've recently writen my own backend for PowerDNS, intended to return load
balanced sets of A records.  I have been using it in combination with the
bind backend to serve the static records for the domains.  I have
experienced some odd behaviour which I believe to be a misfeature/bug in
PowerDNS itself.

The problem only exists in situations where you have multiple backends
returning different types of records for the same name.  For example, if
your first backend when used by itself returns:

example.com 	A 	1.2.3.4

in response to an A query.


And your second backend when used by itself returns

example.com 	NS 	ns1.example.com.


in response to an NS query, if the two backends are chained together in
this order then the A query will continue to work but the NS query will
return an empty result.  I have also noticed than when I do a query of
type 'A', my backend always receives this as a request of type 'ANY'.


The problem appears to be related to two peices of code.  In
PacketHandler::Question() we have:


    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;
      }


This bit of code appears to use a type of ANY, rather than the requested
type, to look up all the results and then it filters out anything which is
not of the type actually requested.  The only case where it does look at
records of a different type is with the NS records.  Would these not be
better handled with a seperate query, in which case we could just make the
look-up for the type that was actually requested?


In UeberBackend::handle::get(), we have:

  DLOG(L<<"Found an answering backend - will not try another one"<<endl);
  i=parent->backends.size(); // don't go on to the next backend

In the case of an ANY request, at the very least, this is not correct
behaviour.  I believe all the backends ought to be queried in the case of
an ANY request.  Should this clause be made conditional on (qtype.getCode
!= QType::ANY) or should it be removed entirely?


To sum up what is happening:

1. pdns gets an NS request for example.com

2. the request is first passed as an ANY request to the first backend

3. the first backend has A records for example.com, which it correctly 
returns in response to the ANY request.

4. because the first backend returned a result, the second backend (which
has the NS and MX records) is never queried

5. the code in PacketHander::question filters out everything that was not
an NS record (i.e. everything) from the result 

6. an empty result is returned.


The same effect can also be observed for the MX records which are held on
the second backend.


Thanks for your time.

Regards,
Ben.




More information about the Pdns-dev mailing list