[Pdns-dev] Recursion Desired in pdns_recursor
Robert Bartl
robert at edv-bartl.at
Fri Jan 16 23:30:14 CET 2009
Hello,
In our monitoring setup we need to forward DNS Queries to a number of
backend Servers and also to a Server running dnscache, which doesnt like
to be queried without the Recursion Desired Bit (the authoritative
Server is not directly reachable).
I've changed the behaviour of the recursor to send queries with the rd
bit set if configured, below is the patch.
It can be configured in forward-zones and forward-zones-file by
prefixing the domainname with a "+" sign.
bye, robert.
------------------
Index: syncres.cc
===================================================================
--- syncres.cc (revision 1324)
+++ syncres.cc (working copy)
@@ -190,6 +190,7 @@
int SyncRes::doResolve(const string &qname, const QType &qtype,
vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere)
{
string prefix;
+ int rd = 0;
if(s_log) {
prefix=d_prefix;
prefix.append(depth, ' ');
@@ -242,7 +243,7 @@
set<string, CIStringCompare> nsset;
bool flawedNSSet=false;
for(int tries=0;tries<2 && nsset.empty();++tries) {
- subdomain=getBestNSNamesFromCache(subdomain, nsset, &flawedNSSet,
depth, beenthere); // pass beenthere to both occasions
+ subdomain=getBestNSNamesFromCache(subdomain, nsset, &flawedNSSet,
depth, beenthere,rd); // pass beenthere to both occasions
if(nsset.empty()) { // must've lost root records
LOG<<prefix<<qname<<": our root expired, repriming from hints and
retrying"<<endl;
@@ -250,7 +251,7 @@
}
}
- if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype,
ret, depth, beenthere)))
+ if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype,
ret, depth, beenthere,rd)))
return 0;
LOG<<prefix<<qname<<": failed (res="<<res<<")"<<endl;
@@ -368,7 +369,7 @@
}
/** doesn't actually do the work, leaves that to getBestNSFromCache */
-string SyncRes::getBestNSNamesFromCache(const string &qname,
set<string, CIStringCompare>& nsset, bool* flawedNSSet, int depth,
set<GetBestNSAnswer>&beenthere)
+string SyncRes::getBestNSNamesFromCache(const string &qname,
set<string, CIStringCompare>& nsset, bool* flawedNSSet, int depth,
set<GetBestNSAnswer>&beenthere, int &rd)
{
string subdomain(qname);
string authdomain(qname);
@@ -379,7 +380,10 @@
nsset.insert(string()); // this gets picked up in doResolveAt, if
empty it means "we are auth", otherwise it denotes a forward
else {
for(vector<ComboAddress>::const_iterator
server=iter->second.d_servers.begin(); server !=
iter->second.d_servers.end(); ++server)
- nsset.insert(server->toStringWithPort());
+ {
+ if (iter->second.rd!=0) rd = 1;
+ nsset.insert(server->toStringWithPort());
+ }
}
return authdomain;
@@ -590,7 +594,7 @@
/** returns -1 in case of no results, rcode otherwise */
int SyncRes::doResolveAt(set<string, CIStringCompare> nameservers,
string auth, bool flawedNSSet, const string &qname, const QType &qtype,
vector<DNSResourceRecord>&ret,
- int depth, set<GetBestNSAnswer>&beenthere)
+ int depth, set<GetBestNSAnswer>&beenthere,int rd)
{
string prefix;
if(s_log) {
@@ -688,7 +692,7 @@
resolveret=asyncresolve(*remoteIP, qname,
(qtype.getCode() == QType::ADDR ?
QType::ANY : qtype.getCode()),
- doTCP, d_doEDNS0, &d_now, &lwr);
// <- we go out on the wire!
+ doTCP, d_doEDNS0, &d_now,
&lwr,rd); // <- we go out on the wire!
if(resolveret != 1) {
if(resolveret==0) {
LOG<<prefix<<qname<<": timeout resolving "<< (doTCP ?
"over TCP" : "")<<endl;
Index: syncres.hh
===================================================================
--- syncres.hh (revision 1324)
+++ syncres.hh (working copy)
@@ -327,6 +327,7 @@
struct AuthDomain
{
vector<ComboAddress> d_servers;
+ int rd;
typedef multi_index_container <
DNSResourceRecord,
indexed_by <
@@ -354,7 +355,7 @@
private:
struct GetBestNSAnswer;
int doResolveAt(set<string, CIStringCompare> nameservers, string
auth, bool flawedNSSet, const string &qname, const QType &qtype,
vector<DNSResourceRecord>&ret,
- int depth, set<GetBestNSAnswer>&beenthere);
+ int depth, set<GetBestNSAnswer>&beenthere,int rd=0);
int doResolve(const string &qname, const QType &qtype,
vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere);
bool doOOBResolve(const string &qname, const QType &qtype,
vector<DNSResourceRecord>&ret, int depth, int &res);
domainmap_t::const_iterator getBestAuthZone(string* qname);
@@ -362,7 +363,7 @@
bool doCacheCheck(const string &qname, const QType &qtype,
vector<DNSResourceRecord>&ret, int depth, int &res);
void getBestNSFromCache(const string &qname,
set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth,
set<GetBestNSAnswer>& beenthere);
void addCruft(const string &qname, vector<DNSResourceRecord>& ret);
- string getBestNSNamesFromCache(const string &qname,set<string,
CIStringCompare>& nsset, bool* flawedNSSet, int depth,
set<GetBestNSAnswer>&beenthere);
+ string getBestNSNamesFromCache(const string &qname,set<string,
CIStringCompare>& nsset, bool* flawedNSSet, int depth,
set<GetBestNSAnswer>&beenthere, int &rd);
void addAuthorityRecords(const string& qname,
vector<DNSResourceRecord>& ret, int depth);
inline vector<string> shuffleInSpeedOrder(set<string,
CIStringCompare> &nameservers, const string &prefix);
Index: pdns_recursor.cc
===================================================================
--- pdns_recursor.cc (revision 1324)
+++ pdns_recursor.cc (working copy)
@@ -1515,6 +1515,12 @@
pair<string,string> headers=splitField(*iter, '=');
trim(headers.first);
trim(headers.second);
+
+ if (headers.first[0] == '+')
+ {
+ headers.first = headers.first.substr(1);
+ ad.rd = 1;
+ }
headers.first=toCanonic("", headers.first);
if(n==0) {
L<<Logger::Error<<"Parsing authoritative data for zone
'"<<headers.first<<"' from file '"<<headers.second<<"'"<<endl;
@@ -1563,7 +1569,11 @@
tie(domain, instructions)=splitField(line, '=');
trim(domain);
trim(instructions);
-
+ if (domain[0] == '+')
+ {
+ domain = domain.substr(1);
+ ad.rd = 1;
+ }
if(domain.empty())
throw AhuException("Error parsing line
"+lexical_cast<string>(linenum)+" of " +::arg()["forward-zones-file"]);
Index: lwres.cc
===================================================================
--- lwres.cc (revision 1324)
+++ lwres.cc (working copy)
@@ -54,7 +54,7 @@
//! returns -2 for OS limits error, -1 for permanent error that has to
do with remote, 0 for timeout, 1 for success
/** Never throws! */
-int asyncresolve(const ComboAddress& ip, const string& domain, int
type, bool doTCP, bool doEDNS0, struct timeval* now, LWResult *lwr)
+int asyncresolve(const ComboAddress& ip, const string& domain, int
type, bool doTCP, bool doEDNS0, struct timeval* now, LWResult *lwr, int rd)
{
int len;
int bufsize=1500;
@@ -63,7 +63,7 @@
// string mapped0x20=dns0x20(domain);
DNSPacketWriter pw(vpacket, domain, type);
- pw.getHeader()->rd=0;
+ pw.getHeader()->rd=rd;
pw.getHeader()->id=dns_random(0xffff);
if(doEDNS0 && !doTCP) {
More information about the Pdns-dev
mailing list