implement 'dot' debugging output, fix crash if you explicitly queried a CNAME (thanks Marco Davids), strictly test NS glue now
This commit is contained in:
parent
f0866a77c4
commit
1298b7bbae
58
tdns/tres.cc
58
tdns/tres.cc
@ -1,4 +1,4 @@
|
|||||||
#include <cstdint>
|
#include <fstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@ -19,6 +19,8 @@ multimap<DNSName, ComboAddress> g_root;
|
|||||||
unsigned int g_numqueries;
|
unsigned int g_numqueries;
|
||||||
bool g_skipIPv6{false}; //!< set this if you have no functioning IPv6
|
bool g_skipIPv6{false}; //!< set this if you have no functioning IPv6
|
||||||
|
|
||||||
|
ofstream g_dot;
|
||||||
|
|
||||||
/** Helper function that extracts a useable IP address from an
|
/** Helper function that extracts a useable IP address from an
|
||||||
A or AAAA resource record. Returns sin_family == 0 if it didn't work */
|
A or AAAA resource record. Returns sin_family == 0 if it didn't work */
|
||||||
static ComboAddress getIP(const std::unique_ptr<RRGen>& rr)
|
static ComboAddress getIP(const std::unique_ptr<RRGen>& rr)
|
||||||
@ -170,6 +172,29 @@ static auto randomizeServers(const multimap<DNSName, ComboAddress>& mservers)
|
|||||||
return servers;
|
return servers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dotQuery(const DNSName& auth, const DNSName& server)
|
||||||
|
{
|
||||||
|
g_dot << '"' << auth << "\" -> \"" << server << "\"" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dotAnswer(const DNSName& dn, const DNSType& rrdt, const DNSName& server)
|
||||||
|
{
|
||||||
|
g_dot <<"\"" << dn << "/"<<rrdt<<"\" [shape=box]\n";
|
||||||
|
g_dot << '"' << server << "\" -> \"" << dn << "/"<<rrdt<<"\"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dotCNAME(const DNSName& target, const DNSName& server, const DNSName& dn)
|
||||||
|
{
|
||||||
|
g_dot << '"' << target << "\" [shape=box]"<<endl;
|
||||||
|
g_dot << '"' << server << "\" -> \"" << dn << "/CNAME\" -> \"" << target <<"\"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dotDelegation(const DNSName& rrdn, const DNSName& server)
|
||||||
|
{
|
||||||
|
g_dot << '"' << rrdn << "\" [shape=diamond]\n";
|
||||||
|
g_dot << '"' << server << "\" -> \"" << rrdn << "\"\n";
|
||||||
|
}
|
||||||
|
|
||||||
/** This attempts to look up the name dn with type dt. The depth parameter is for
|
/** This attempts to look up the name dn with type dt. The depth parameter is for
|
||||||
trace output.
|
trace output.
|
||||||
the 'auth' field describes the authority of the servers we will be talking to. Defaults to root ('believe everything')
|
the 'auth' field describes the authority of the servers we will be talking to. Defaults to root ('believe everything')
|
||||||
@ -187,9 +212,10 @@ ResolveResult resolveAt(const DNSName& dn, const DNSType& dt, int depth=0, const
|
|||||||
// for tres, this is not done (since we have no memory), but we do randomize:
|
// for tres, this is not done (since we have no memory), but we do randomize:
|
||||||
|
|
||||||
auto servers = randomizeServers(mservers);
|
auto servers = randomizeServers(mservers);
|
||||||
|
|
||||||
ResolveResult ret;
|
ResolveResult ret;
|
||||||
for(auto& sp : servers) {
|
for(auto& sp : servers) {
|
||||||
|
dotQuery(auth, sp.first);
|
||||||
|
|
||||||
ret.clear();
|
ret.clear();
|
||||||
ComboAddress server=sp.second;
|
ComboAddress server=sp.second;
|
||||||
server.sin4.sin_port = htons(53); // just to be sure
|
server.sin4.sin_port = htons(53); // just to be sure
|
||||||
@ -238,13 +264,14 @@ ResolveResult resolveAt(const DNSName& dn, const DNSType& dt, int depth=0, const
|
|||||||
if(dmr.dh.aa==1) { // authoritative answer. We trust this.
|
if(dmr.dh.aa==1) { // authoritative answer. We trust this.
|
||||||
if(rrsection == DNSSection::Answer && dn == rrdn && dt == rrdt) {
|
if(rrsection == DNSSection::Answer && dn == rrdn && dt == rrdt) {
|
||||||
cout << prefix<<"We got an answer to our question!"<<endl;
|
cout << prefix<<"We got an answer to our question!"<<endl;
|
||||||
|
dotAnswer(dn, rrdt, sp.first);
|
||||||
ret.res.push_back({dn, ttl, std::move(rr)});
|
ret.res.push_back({dn, ttl, std::move(rr)});
|
||||||
}
|
}
|
||||||
if(dn == rrdn && rrdt == DNSType::CNAME) {
|
else if(dn == rrdn && rrdt == DNSType::CNAME) {
|
||||||
DNSName target = dynamic_cast<CNAMEGen*>(rr.get())->d_name;
|
DNSName target = dynamic_cast<CNAMEGen*>(rr.get())->d_name;
|
||||||
ret.intermediate.push_back({dn, ttl, std::move(rr)}); // rr is DEAD now!
|
ret.intermediate.push_back({dn, ttl, std::move(rr)}); // rr is DEAD now!
|
||||||
cout << prefix<<"We got a CNAME to " << target <<", chasing"<<endl;
|
cout << prefix<<"We got a CNAME to " << target <<", chasing"<<endl;
|
||||||
|
dotCNAME(target, sp.first, dn);
|
||||||
if(target.isPartOf(auth)) { // this points to something we consider this server auth for
|
if(target.isPartOf(auth)) { // this points to something we consider this server auth for
|
||||||
cout << prefix << "target " << target << " is within " << auth<<", harvesting from packet"<<endl;
|
cout << prefix << "target " << target << " is within " << auth<<", harvesting from packet"<<endl;
|
||||||
bool hadMatch=false; // perhaps the answer is in this DNS message
|
bool hadMatch=false; // perhaps the answer is in this DNS message
|
||||||
@ -270,13 +297,15 @@ ResolveResult resolveAt(const DNSName& dn, const DNSType& dt, int depth=0, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// this picks up nameserver records, and we even believe your glue.. but ONLY for this query
|
// this picks up nameserver records. We check if glue records are within the authority
|
||||||
// from a security perspective, all an auth can do is ruin the result, since we don't cache
|
// of what we approached this server for.
|
||||||
// if an auth serves confused glue, resolution will suffer
|
|
||||||
// (so in other words, if you have an out of zone NS record, we will believe your glue)
|
|
||||||
if(rrsection == DNSSection::Authority && rrdt == DNSType::NS) {
|
if(rrsection == DNSSection::Authority && rrdt == DNSType::NS) {
|
||||||
if(dn.isPartOf(rrdn)) {
|
if(dn.isPartOf(rrdn)) {
|
||||||
DNSName nsname = dynamic_cast<NSGen*>(rr.get())->d_name;
|
DNSName nsname = dynamic_cast<NSGen*>(rr.get())->d_name;
|
||||||
|
|
||||||
|
if(!dmr.dh.aa && (newAuth != rrdn || nsses.empty())) {
|
||||||
|
dotDelegation(rrdn, sp.first);
|
||||||
|
}
|
||||||
nsses.insert(nsname);
|
nsses.insert(nsname);
|
||||||
newAuth = rrdn;
|
newAuth = rrdn;
|
||||||
}
|
}
|
||||||
@ -284,8 +313,12 @@ ResolveResult resolveAt(const DNSName& dn, const DNSType& dt, int depth=0, const
|
|||||||
cout<< prefix << "Authoritative server gave us NS record to which this query does not belong" <<endl;
|
cout<< prefix << "Authoritative server gave us NS record to which this query does not belong" <<endl;
|
||||||
}
|
}
|
||||||
else if(rrsection == DNSSection::Additional && nsses.count(rrdn) && (rrdt == DNSType::A || rrdt == DNSType::AAAA)) {
|
else if(rrsection == DNSSection::Additional && nsses.count(rrdn) && (rrdt == DNSType::A || rrdt == DNSType::AAAA)) {
|
||||||
addresses.insert({rrdn, getIP(rr)}); // this only picks up addresses for NS records we've seen already
|
// this only picks up addresses for NS records we've seen already
|
||||||
// but that is ok: NS is in Authority section
|
// but that is ok: NS is in Authority section
|
||||||
|
if(rrdn.isPartOf(auth))
|
||||||
|
addresses.insert({rrdn, getIP(rr)});
|
||||||
|
else
|
||||||
|
cout << prefix << "Not accepting IP address of " << rrdn <<": out of authority of this server"<<endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -468,7 +501,8 @@ try
|
|||||||
}
|
}
|
||||||
|
|
||||||
// single shot operation
|
// single shot operation
|
||||||
|
g_dot.open("plot.dot");
|
||||||
|
g_dot << "digraph { "<<endl;
|
||||||
DNSName dn = makeDNSName(argv[1]);
|
DNSName dn = makeDNSName(argv[1]);
|
||||||
DNSType dt = makeDNSType(argv[2]);
|
DNSType dt = makeDNSType(argv[2]);
|
||||||
|
|
||||||
@ -482,6 +516,8 @@ try
|
|||||||
cout<<r.name <<" "<<r.ttl<<" "<<r.rr->getType()<<" "<<r.rr->toString()<<endl;
|
cout<<r.name <<" "<<r.ttl<<" "<<r.rr->getType()<<" "<<r.rr->toString()<<endl;
|
||||||
}
|
}
|
||||||
cout<<"Used "<<g_numqueries << " queries"<<endl;
|
cout<<"Used "<<g_numqueries << " queries"<<endl;
|
||||||
|
|
||||||
|
g_dot << "}"<<endl;
|
||||||
}
|
}
|
||||||
catch(std::exception& e)
|
catch(std::exception& e)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user