arg().set("webserver-password","Password required for accessing the webserver")="";
arg().setSwitch("out-of-zone-additional-processing","Do out of zone additional processing")="no";
+ arg().setSwitch("do-ipv6-additional-processing", "Do AAAA additional processing")="no";
arg().setSwitch("query-logging","Hint backends that queries should be logged")="no";
arg().set("cache-ttl","Seconds to store packets in the PacketCache")="20";
N->send(AD.A);
numanswered++;
int diff=AD.A->d_dt.udiff();
- avg_latency=(int)(0.999*avg_latency+0.001*diff);
+ avg_latency=(int)(1023*avg_latency/1024+diff/1024);
delete AD.A;
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-// $Id: dnspacket.cc,v 1.17 2003/02/25 12:36:49 ahu Exp $
+// $Id: dnspacket.cc,v 1.18 2003/03/12 16:06:35 ahu Exp $
#include "utility.hh"
#include <cstdio>
rr.ttl=answerp[offset+7]+256*(answerp[offset+6]+256*(answerp[offset+5]+256*answerp[offset+4]));
rr.content="";
length=256*(unsigned char)answerp[offset+8]+(unsigned char)answerp[offset+8+1];
- // was: ntohs(*(u_int16_t*)(answerp+offset+8));
- // XXX check if this 'length' extends beyond the end of the packet!
const unsigned char *datapos=answerp+offset+10;
+
+ if(datapos+length > end)
+ throw AhuException("Record extends beyond end of packet");
+
string part;
offset=0;
</affiliation>
</author>
- <PubDate>v2.1 $Date: 2003/03/04 18:33:39 $</PubDate>
+ <PubDate>v2.1 $Date: 2003/03/12 16:06:35 $</PubDate>
<Abstract>
<para>
<listitem><para>
Maximum number of miliseconds to queue a query. See <xref linkend="performance">.
</para></listitem></varlistentry>
+ <varlistentry><term>query-local-address=...</term>
+ <listitem><para>
+ The IP address to use as a source address for sending queries. Useful if you have multiple IPs and pdns is not bound to the IP address your operating system uses by default for outgoing packets.
+ </para></listitem></varlistentry>
<varlistentry><term>query-logging | query-logging=yes | query-logging=no</term>
<listitem><para>
Hints to a backend that it should log a textual representation of queries it performs. Can be set at runtime.
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>Q: My masters won't allow PowerDNS to access zones as it is using the wrong local IP address</term>
+ <listitem>
+ <para>
+ A: Mark Bergsma contributed the query-local-address setting to tell PowerDNS which local IP address to use.
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term>Q: Can I use a MySQL database with the Windows version of PowerDNS?</term>
<listitem>
</listitem>
</varlistentry>
<varlistentry>
- <term>Q: Will <ulink url="http://express.powerdns.com">PowerDNS Express</ulink> be open sourced?
- <ulink url="http://www.powerdns.com/powermail/">PowerMail?</ulink></term>
+ <term>Q: Will <ulink url="http://express.powerdns.com">PowerDNS Express</ulink> be open sourced?</term>
<listitem>
<para>
- Perhaps, we're not yet sure. PowerMail most probably.
+ Perhaps, we're not yet sure.
</para>
</listitem>
</varlistentry>
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()
DNSResourceRecord rr;
if (p->qclass == 3 && p->qtype.getName() == "HINFO") {
- rr.content = "PowerDNS $Id: packethandler.cc,v 1.10 2003/02/25 12:36:49 ahu Exp $";
+ rr.content = "PowerDNS $Id: packethandler.cc,v 1.11 2003/03/12 16:06:35 ahu Exp $";
rr.ttl = 5;
rr.qname=target;
rr.qtype=13; // hinfo
{
DNSResourceRecord rr;
if(p->qtype.getCode()==QType::TXT && target=="version.bind") {// TXT
- rr.content="Served by POWERDNS "VERSION" $Id: packethandler.cc,v 1.10 2003/02/25 12:36:49 ahu Exp $";
+ rr.content="Served by POWERDNS "VERSION" $Id: packethandler.cc,v 1.11 2003/03/12 16:06:35 ahu Exp $";
rr.ttl=5;
rr.qname=target;
rr.qtype=QType::TXT; // TXT
}
/** dangling is declared true if we were unable to resolve everything */
-int PacketHandler::doAdditionalProcessing(DNSPacket *p, DNSPacket *r)
+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();
-
for(vector<DNSResourceRecord>::const_iterator i=arrs.begin();
i!=arrs.end();
++i) {
- B.lookup("A",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
+
+ if(r->d.aa && i->qtype.getCode()==QType::NS && !B.getSOA(i->qname,sd)) // drop AA in case of non-SOA-level NS answer
+ r->d.aa=false;
+
+ 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);
+
}
-
- 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);
+ 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;
+ catch(ResolverException& re) {
+ // L<<Logger::Error<<"Trying to do additional processing for answer to '"<<p->qdomain<<"' query: "<<re.reason<<endl;
+ }
}
}
}
}
}
}
-
if(found)
goto sendit;
+
}
// not found yet, try wildcards (we only try here in case of recursion - we should check before we hand off)
sendit:;
- if(doAdditionalProcessing(p,r)<0)
+ if(doAdditionalProcessingAndDropAA(p,r)<0)
return 0;
int doVersionRequest(DNSPacket *p, DNSPacket *r, string &target);
bool getAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId);
bool getTLDAuth(DNSPacket *p, SOAData *sd, const string &target, int *zoneId);
- int doAdditionalProcessing(DNSPacket *p, DNSPacket *r);
-
+ int doAdditionalProcessingAndDropAA(DNSPacket *p, DNSPacket *r);
static int s_count;
bool d_doFancyRecords;
bool d_doWildcards;
bool d_doCNAME;
bool d_logDNSDetails;
+ bool d_doIPv6AdditionalProcessing;
UeberBackend B; // every thread an own instance
};
bool SyncRes::doCacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res)
{
+ bool giveNegative=false;
string prefix(d_prefix), tuple;
prefix.append(depth, ' ');
- tuple=toLower(qname)+"|"+qtype.getName();
- LOG<<prefix<<qname<<": Looking for direct cache hit of '"<<tuple<<"', "<<s_negcache.count(tuple)<<endl;
-
string sqname(qname);
QType sqt(qtype);
- res=0;
- map<string,string>::const_iterator ni=s_negcache.find(tuple);
- if(ni!=s_negcache.end()) {
- LOG<<prefix<<qname<<": "<<qtype.getName()<<" is negatively cached, will return immediately if we still have SOA ("<<ni->second<<") to prove it"<<endl;
- res=RCode::NXDomain;
+ if(s_negcache.count(toLower(qname))) {
+ res=0;
+ map<string,string>::const_iterator ni=s_negcache.find(toLower(qname));
+
+ LOG<<prefix<<qname<<": Entire record '"<<toLower(qname)<<"', is negatively cached "<<endl;
+ res=RCode::NXDomain;
+ giveNegative=true;
sqname=ni->second;
sqt="SOA";
}
+ else {
+ tuple=toLower(qname)+"|"+qtype.getName();
+ LOG<<prefix<<qname<<": Looking for direct cache hit of '"<<tuple<<"', "<<s_negcache.count(tuple)<<endl;
+
+ res=0;
+ map<string,string>::const_iterator ni=s_negcache.find(tuple);
+ if(ni!=s_negcache.end()) {
+ LOG<<prefix<<qname<<": "<<qtype.getName()<<" is negatively cached, will return immediately if we still have SOA ("<<ni->second<<") to prove it"<<endl;
+ res=RCode::NoError; // only this record doesn't exist
+ giveNegative=true;
+ sqname=ni->second;
+ sqt="SOA";
+ }
+ }
set<DNSResourceRecord> cset;
bool found=false, expired=false;
if(j->ttl>(unsigned int)time(0)) {
DNSResourceRecord rr=*j;
rr.ttl-=time(0);
- if(res==RCode::NXDomain)
+ if(giveNegative)
rr.d_place=DNSResourceRecord::AUTHORITY;
ret.push_back(rr);
LOG<<"[ttl="<<rr.ttl<<"] ";
string newauth, soaname, newtarget;
for(LWRes::res_t::const_iterator i=result.begin();i!=result.end();++i) {
- if(i->d_place==DNSResourceRecord::AUTHORITY && endsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA) {
- LOG<<prefix<<qname<<": got negative caching indication for '"<<toLower(qname)+"|"+qtype.getName()<<"'"<<endl;
+ if(i->d_place==DNSResourceRecord::AUTHORITY && endsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA &&
+ d_lwr.d_rcode==RCode::NXDomain) {
+ LOG<<prefix<<qname<<": got negative caching indication for RECORD '"<<toLower(qname)+"'"<<endl;
ret.push_back(*i);
- s_negcache[toLower(qname)+"|"+qtype.getName()]=i->qname;
+
+ s_negcache[toLower(qname)]=i->qname;
negindic=true;
}
else if(i->d_place==DNSResourceRecord::ANSWER && i->qname==qname && i->qtype.getCode()==QType::CNAME && (!(qtype==QType(QType::CNAME)))) {
LOG<<prefix<<qname<<": got upwards/level NS record '"<<i->qname<<"' -> '"<<i->content<<"', had '"<<auth<<"'"<<endl;
nsset.insert(toLower(i->content));
}
+ else if(i->d_place==DNSResourceRecord::AUTHORITY && endsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA &&
+ d_lwr.d_rcode==RCode::NoError) {
+ LOG<<prefix<<qname<<": got negative caching indication for '"<<toLower(qname)+"|"+i->qtype.getName()+"'"<<endl;
+ ret.push_back(*i);
+
+ s_negcache[toLower(qname)+"|"+qtype.getName()]=i->qname;
+ negindic=true;
+ }
}
if(done){
}
catch(AhuException &ae) {
L<<Logger::Error<<Logger::NTLog<<"TCP server is unable to launch backends - will try again when questions come in"<<endl;
+ L<<Logger::Error<<"TCP server is unable to launch backends - will try again when questions come in: "<<ae.reason<<endl;
}
pthread_create(&d_tid, 0, launcher, static_cast<void *>(this));
}