upgrade 'tres' so it can now function as your resolver, plus adjust to new simplesocket
This commit is contained in:
parent
642a5a3522
commit
1677111b2d
@ -1,4 +1,4 @@
|
|||||||
CXXFLAGS:=-std=gnu++14 -Wall -O2 -MMD -MP -ggdb -Iext/simplesocket -Iext/catch -pthread
|
CXXFLAGS:=-std=gnu++14 -Wall -O2 -MMD -MP -ggdb -Iext/simplesocket -Iext/simplesocket/ext/fmt-5.2.1/include -Iext/catch -pthread
|
||||||
CFLAGS:= -Wall -O2 -MMD -MP -ggdb
|
CFLAGS:= -Wall -O2 -MMD -MP -ggdb
|
||||||
|
|
||||||
PROGRAMS = tdns tdig tres tdns-c-test
|
PROGRAMS = tdns tdig tres tdns-c-test
|
||||||
@ -14,19 +14,20 @@ check: testrunner tdns tdig
|
|||||||
|
|
||||||
-include *.d
|
-include *.d
|
||||||
|
|
||||||
tdns: tdns.o record-types.o dns-storage.o dnsmessages.o contents.o ext/simplesocket/comboaddress.o ext/simplesocket/sclasses.o ext/simplesocket/swrappers.o tdnssec.o
|
SIMPLESOCKET = ext/simplesocket/comboaddress.o ext/simplesocket/sclasses.o ext/simplesocket/swrappers.o ext/simplesocket/ext/fmt-5.2.1/src/format.o
|
||||||
|
|
||||||
|
tdns: tdns.o record-types.o dns-storage.o dnsmessages.o contents.o tdnssec.o $(SIMPLESOCKET)
|
||||||
g++ -std=gnu++14 $^ -o $@ -pthread
|
g++ -std=gnu++14 $^ -o $@ -pthread
|
||||||
|
|
||||||
tdig: tdig.o record-types.o dns-storage.o dnsmessages.o ext/simplesocket/comboaddress.o ext/simplesocket/sclasses.o ext/simplesocket/swrappers.o
|
tdig: tdig.o record-types.o dns-storage.o dnsmessages.o $(SIMPLESOCKET)
|
||||||
g++ -std=gnu++14 $^ -o $@ -pthread
|
g++ -std=gnu++14 $^ -o $@ -pthread
|
||||||
|
|
||||||
tres: tres.o record-types.o dns-storage.o dnsmessages.o ext/simplesocket/comboaddress.o ext/simplesocket/sclasses.o ext/simplesocket/swrappers.o
|
tres: tres.o record-types.o dns-storage.o dnsmessages.o $(SIMPLESOCKET)
|
||||||
g++ -std=gnu++14 $^ -o $@ -pthread
|
g++ -std=gnu++14 $^ -o $@ -pthread
|
||||||
|
|
||||||
|
|
||||||
tdns-c-test: tdns-c-test.o tdns-c.o record-types.o dns-storage.o dnsmessages.o ext/simplesocket/comboaddress.o ext/simplesocket/sclasses.o ext/simplesocket/swrappers.o
|
tdns-c-test: tdns-c-test.o tdns-c.o record-types.o dns-storage.o dnsmessages.o $(SIMPLESOCKET)
|
||||||
g++ -std=gnu++14 $^ -o $@
|
g++ -std=gnu++14 $^ -o $@
|
||||||
|
|
||||||
|
|
||||||
testrunner: tests.o record-types.o dns-storage.o dnsmessages.o
|
testrunner: tests.o record-types.o dns-storage.o dnsmessages.o
|
||||||
g++ -std=gnu++14 $^ -o $@
|
g++ -std=gnu++14 $^ -o $@
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit dbadaf003470898fc1471c1621ef3c9e824969d6
|
Subproject commit 2b02339cddcfa038626b85b87340065845b932ef
|
146
tdns/tres.cc
146
tdns/tres.cc
@ -6,6 +6,7 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include "record-types.hh"
|
#include "record-types.hh"
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@file
|
@file
|
||||||
@ -52,7 +53,7 @@ DNSMessageReader getResponse(const ComboAddress& server, const DNSName& dn, cons
|
|||||||
bool doEDNS=true, doTCP=false;
|
bool doEDNS=true, doTCP=false;
|
||||||
|
|
||||||
for(int tries = 0; tries < 4 ; ++tries) {
|
for(int tries = 0; tries < 4 ; ++tries) {
|
||||||
if(++g_numqueries > 30) // there is the possibility our algorithm will loop
|
if(++g_numqueries > 300) // there is the possibility our algorithm will loop
|
||||||
throw TooManyQueriesException(); // and send out thousands of queries, so let's not
|
throw TooManyQueriesException(); // and send out thousands of queries, so let's not
|
||||||
|
|
||||||
DNSMessageWriter dmw(dn, dt);
|
DNSMessageWriter dmw(dn, dt);
|
||||||
@ -133,6 +134,22 @@ struct NxdomainException{};
|
|||||||
//! Or if your type does not exist
|
//! Or if your type does not exist
|
||||||
struct NodataException{};
|
struct NodataException{};
|
||||||
|
|
||||||
|
struct ResolveRR
|
||||||
|
{
|
||||||
|
DNSName name;
|
||||||
|
uint32_t ttl;
|
||||||
|
std::unique_ptr<RRGen> rr;
|
||||||
|
};
|
||||||
|
struct ResolveResult
|
||||||
|
{
|
||||||
|
vector<ResolveRR> res;
|
||||||
|
vector<ResolveRR> intermediate;
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
res.clear();
|
||||||
|
intermediate.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/** 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.
|
||||||
@ -141,16 +158,14 @@ struct NodataException{};
|
|||||||
root-servers.
|
root-servers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
vector<std::unique_ptr<RRGen>> resolveAt(const DNSName& dn, const DNSType& dt, int depth=0, const DNSName& auth={}, const multimap<DNSName, ComboAddress>& mservers=g_root)
|
ResolveResult resolveAt(const DNSName& dn, const DNSType& dt, int depth=0, const DNSName& auth={}, const multimap<DNSName, ComboAddress>& mservers=g_root)
|
||||||
{
|
{
|
||||||
std::string prefix(depth, ' ');
|
std::string prefix(depth, ' ');
|
||||||
prefix += dn.toString() + "|"+toString(dt)+" ";
|
prefix += dn.toString() + "|"+toString(dt)+" ";
|
||||||
|
|
||||||
vector<std::unique_ptr<RRGen>> ret;
|
|
||||||
// it is good form to sort the servers in order of response time
|
|
||||||
// for tres, this is not done, but we do randomize
|
|
||||||
|
|
||||||
cout << prefix << "Starting query at authority = "<<auth<< ", have "<<mservers.size() << " addresses to try"<<endl;
|
cout << prefix << "Starting query at authority = "<<auth<< ", have "<<mservers.size() << " addresses to try"<<endl;
|
||||||
|
|
||||||
|
// it is good form to sort the servers in order of response time
|
||||||
|
// for tres, this is not done (since we have no memory), but we do randomize:
|
||||||
|
|
||||||
vector<pair<DNSName, ComboAddress> > servers;
|
vector<pair<DNSName, ComboAddress> > servers;
|
||||||
for(auto& sp : mservers)
|
for(auto& sp : mservers)
|
||||||
@ -160,6 +175,7 @@ vector<std::unique_ptr<RRGen>> resolveAt(const DNSName& dn, const DNSType& dt, i
|
|||||||
std::mt19937 g(rd());
|
std::mt19937 g(rd());
|
||||||
std::shuffle(servers.begin(), servers.end(), g);
|
std::shuffle(servers.begin(), servers.end(), g);
|
||||||
|
|
||||||
|
ResolveResult ret;
|
||||||
for(auto& sp : servers) {
|
for(auto& sp : servers) {
|
||||||
ret.clear();
|
ret.clear();
|
||||||
ComboAddress server=sp.second;
|
ComboAddress server=sp.second;
|
||||||
@ -209,10 +225,12 @@ vector<std::unique_ptr<RRGen>> resolveAt(const DNSName& dn, const DNSType& dt, i
|
|||||||
if(dmr.dh.aa==1) {
|
if(dmr.dh.aa==1) {
|
||||||
if(dn == rrdn && dt == rrdt) {
|
if(dn == rrdn && dt == rrdt) {
|
||||||
cout << prefix<<"We got an answer to our question!"<<endl;
|
cout << prefix<<"We got an answer to our question!"<<endl;
|
||||||
ret.push_back(std::move(rr));
|
ret.res.push_back({dn, ttl, std::move(rr)});
|
||||||
}
|
}
|
||||||
if(dn == rrdn && rrdt == DNSType::CNAME) {
|
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!
|
||||||
cout << prefix<<"We got a CNAME to " << target <<", chasing"<<endl;
|
cout << prefix<<"We got a CNAME to " << target <<", chasing"<<endl;
|
||||||
|
|
||||||
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
|
||||||
@ -221,7 +239,7 @@ vector<std::unique_ptr<RRGen>> resolveAt(const DNSName& dn, const DNSType& dt, i
|
|||||||
while(dmr.getRR(rrsection, rrdn, rrdt, ttl, rr)) {
|
while(dmr.getRR(rrsection, rrdn, rrdt, ttl, rr)) {
|
||||||
if(rrsection==DNSSection::Answer && rrdn == target && rrdt == dt) {
|
if(rrsection==DNSSection::Answer && rrdn == target && rrdt == dt) {
|
||||||
hadMatch=true;
|
hadMatch=true;
|
||||||
ret.push_back(std::move(rr));
|
ret.res.push_back({dn, ttl, std::move(rr)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(hadMatch) { // if it worked, great, otherwise actual chase
|
if(hadMatch) { // if it worked, great, otherwise actual chase
|
||||||
@ -232,7 +250,11 @@ vector<std::unique_ptr<RRGen>> resolveAt(const DNSName& dn, const DNSType& dt, i
|
|||||||
cout <<prefix<<"in-message chase not successful, will do new query for "<<target<<endl;
|
cout <<prefix<<"in-message chase not successful, will do new query for "<<target<<endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolveAt(target, dt, depth + 1);
|
auto chaseres=resolveAt(target, dt, depth + 1);
|
||||||
|
ret.res = std::move(chaseres.res);
|
||||||
|
for(auto& rr : chaseres.intermediate) // add up their intermediates
|
||||||
|
ret.intermediate.push_back(std::move(rr));
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -255,9 +277,9 @@ vector<std::unique_ptr<RRGen>> resolveAt(const DNSName& dn, const DNSType& dt, i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!ret.empty()) {
|
if(!ret.res.empty()) {
|
||||||
// the answer is in!
|
// the answer is in!
|
||||||
cout << prefix<<"Done, returning "<<ret.size()<<" results\n";
|
cout << prefix<<"Done, returning "<<ret.res.size()<<" results, "<<ret.intermediate.size()<<" intermediate\n";
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
else if(dmr.dh.aa) {
|
else if(dmr.dh.aa) {
|
||||||
@ -273,7 +295,7 @@ vector<std::unique_ptr<RRGen>> resolveAt(const DNSName& dn, const DNSType& dt, i
|
|||||||
cout << p.first <<"="<<p.second.toString()<<" ";
|
cout << p.first <<"="<<p.second.toString()<<" ";
|
||||||
cout <<endl;
|
cout <<endl;
|
||||||
auto res2=resolveAt(dn, dt, depth+1, newAuth, addresses);
|
auto res2=resolveAt(dn, dt, depth+1, newAuth, addresses);
|
||||||
if(!res2.empty())
|
if(!res2.res.empty())
|
||||||
return res2;
|
return res2;
|
||||||
cout << prefix<<"The IP addresses we had did not provide a good answer"<<endl;
|
cout << prefix<<"The IP addresses we had did not provide a good answer"<<endl;
|
||||||
}
|
}
|
||||||
@ -288,9 +310,9 @@ vector<std::unique_ptr<RRGen>> resolveAt(const DNSName& dn, const DNSType& dt, i
|
|||||||
for(const DNSType& qtype : {DNSType::A, DNSType::AAAA}) {
|
for(const DNSType& qtype : {DNSType::A, DNSType::AAAA}) {
|
||||||
try {
|
try {
|
||||||
auto result = resolveAt(name, qtype, depth+1);
|
auto result = resolveAt(name, qtype, depth+1);
|
||||||
cout << prefix<<"Got "<<result.size()<<" nameserver IPv4 addresses, adding to list"<<endl;
|
cout << prefix<<"Got "<<result.res.size()<<" nameserver IPv4 addresses, adding to list"<<endl;
|
||||||
for(const auto& res : result)
|
for(const auto& res : result.res)
|
||||||
newns.insert({name, getIP(res)});
|
newns.insert({name, getIP(res.rr)});
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
@ -303,7 +325,7 @@ vector<std::unique_ptr<RRGen>> resolveAt(const DNSName& dn, const DNSType& dt, i
|
|||||||
|
|
||||||
// we have a new (set) of addresses to try
|
// we have a new (set) of addresses to try
|
||||||
auto res2 = resolveAt(dn, dt, depth+1, newAuth, newns);
|
auto res2 = resolveAt(dn, dt, depth+1, newAuth, newns);
|
||||||
if(!res2.empty()) // it worked!
|
if(!res2.res.empty()) // it worked!
|
||||||
return res2;
|
return res2;
|
||||||
// it didn't, let's move on to the next server
|
// it didn't, let's move on to the next server
|
||||||
}
|
}
|
||||||
@ -316,11 +338,61 @@ vector<std::unique_ptr<RRGen>> resolveAt(const DNSName& dn, const DNSType& dt, i
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void processQuery(int sock, ComboAddress client, DNSMessageReader dmr)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
g_numqueries = 0;
|
||||||
|
DNSName dn;
|
||||||
|
DNSType dt;
|
||||||
|
dmr.getQuestion(dn, dt);
|
||||||
|
|
||||||
|
DNSMessageWriter dmw(dn, dt);
|
||||||
|
dmw.dh.rd = dmr.dh.rd;
|
||||||
|
dmw.dh.ra = true;
|
||||||
|
dmw.dh.qr = true;
|
||||||
|
dmw.dh.id = dmr.dh.id;
|
||||||
|
|
||||||
|
ResolveResult res;
|
||||||
|
try {
|
||||||
|
res = resolveAt(dn, dt);
|
||||||
|
cout<<"Result or query for "<< dn <<"|"<<toString(dt)<<endl;
|
||||||
|
for(const auto& r : res.intermediate) {
|
||||||
|
cout<<r.name <<" "<<r.ttl<<" "<<r.rr->getType()<<" " << r.rr->toString()<<endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const auto& r : res.res) {
|
||||||
|
cout<<r.name <<" "<<r.ttl<<" "<<r.rr->getType()<<" "<<r.rr->toString()<<endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(NodataException& nd)
|
||||||
|
{
|
||||||
|
SSendto(sock, dmw.serialize(), client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch(NxdomainException& nx)
|
||||||
|
{
|
||||||
|
dmw.dh.rcode = (int)RCode::Nxdomain;
|
||||||
|
SSendto(sock, dmw.serialize(), client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(const auto& rr : res.intermediate)
|
||||||
|
dmw.putRR(DNSSection::Answer, rr.name, rr.ttl, rr.rr);
|
||||||
|
for(const auto& rr : res.res)
|
||||||
|
dmw.putRR(DNSSection::Answer, rr.name, rr.ttl, rr.rr);
|
||||||
|
string resp = dmw.serialize();
|
||||||
|
SSendto(sock, resp, client);
|
||||||
|
}
|
||||||
|
catch(exception& e)
|
||||||
|
{
|
||||||
|
cerr << "Thread died: " << e.what() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(argc != 3) {
|
if(argc != 2 && argc != 3) {
|
||||||
cerr<<"Syntax: tres name type\n";
|
cerr<<"Syntax: tres name type\n";
|
||||||
|
cerr<<"Syntax: tres ip:port\n";
|
||||||
return(EXIT_FAILURE);
|
return(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
signal(SIGPIPE, SIG_IGN); // TCP, so we need this
|
signal(SIGPIPE, SIG_IGN); // TCP, so we need this
|
||||||
@ -330,7 +402,7 @@ try
|
|||||||
{makeDNSName("k.root-servers.net"), ComboAddress("193.0.14.129", 53)},
|
{makeDNSName("k.root-servers.net"), ComboAddress("193.0.14.129", 53)},
|
||||||
};
|
};
|
||||||
|
|
||||||
// retrieve the actual live NSSET from the hints
|
// retrieve the actual live root NSSET from the hints
|
||||||
for(const auto& h : hints) {
|
for(const auto& h : hints) {
|
||||||
try {
|
try {
|
||||||
DNSMessageReader dmr = getResponse(h.second, makeDNSName("."), DNSType::NS);
|
DNSMessageReader dmr = getResponse(h.second, makeDNSName("."), DNSType::NS);
|
||||||
@ -353,13 +425,45 @@ try
|
|||||||
|
|
||||||
cout<<"Retrieved . NSSET from hints, have "<<g_root.size()<<" addresses"<<endl;
|
cout<<"Retrieved . NSSET from hints, have "<<g_root.size()<<" addresses"<<endl;
|
||||||
|
|
||||||
|
|
||||||
|
if(argc == 2) {
|
||||||
|
ComboAddress local(argv[1]);
|
||||||
|
Socket sock(local.sin4.sin_family, SOCK_DGRAM);
|
||||||
|
SBind(sock, local);
|
||||||
|
string packet;
|
||||||
|
ComboAddress client;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
try {
|
||||||
|
packet = SRecvfrom(sock, 1500, client);
|
||||||
|
cout<<"Received packet from "<< client.toStringWithPort() << endl;
|
||||||
|
DNSMessageReader dmr(packet);
|
||||||
|
if(dmr.dh.qr) {
|
||||||
|
cout << "Packet from " << client.toStringWithPort()<< " was not a query"<<endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::thread t(processQuery, (int)sock, client, dmr);
|
||||||
|
t.detach();
|
||||||
|
}
|
||||||
|
catch(exception& e) {
|
||||||
|
cout << "Processing packet from " << client.toStringWithPort() <<": "<<e.what() << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// single shot operation
|
||||||
|
|
||||||
DNSName dn = makeDNSName(argv[1]);
|
DNSName dn = makeDNSName(argv[1]);
|
||||||
DNSType dt = makeDNSType(argv[2]);
|
DNSType dt = makeDNSType(argv[2]);
|
||||||
|
|
||||||
auto res = resolveAt(dn, dt);
|
auto res = resolveAt(dn, dt);
|
||||||
cout<<"Result or query for "<< dn <<"|"<<toString(dt)<<endl;
|
cout<<"Result or query for "<< dn <<"|"<<toString(dt)<<endl;
|
||||||
for(const auto& r : res) {
|
for(const auto& r : res.intermediate) {
|
||||||
cout<<r->toString()<<endl;
|
cout<<r.name <<" "<<r.ttl<<" "<<r.rr->getType()<<" " << r.rr->toString()<<endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const auto& r : res.res) {
|
||||||
|
cout<<r.name <<" "<<r.ttl<<" "<<r.rr->getType()<<" "<<r.rr->toString()<<endl;
|
||||||
}
|
}
|
||||||
cout<<"Used "<<g_numqueries << " queries"<<endl;
|
cout<<"Used "<<g_numqueries << " queries"<<endl;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user