Here’s a bit of code I wrote for work that I thought was kind of neat; it uses a recursive function and Net::DNS to recurse DNS.
#!/usr/bin/perl
use strict;
use warnings;
use Net::DNS;
my $domain = 'schwer.us';
my $sonicrns= 'ns2.sonic.net';
my @root_ns = map $_ . '.root-servers.net', 'a'..'m';
&recurse($domain);
sub recurse($)
{
my $domain = shift;
my $rns = $root_ns[int(rand(@root_ns))];
&_recurse($domain,$rns);
}
sub _recurse($$)
{
my $domain = shift;
my $ns = shift;
print "Asking $ns about $domain.\n";
my $res = Net::DNS::Resolver->new('nameservers'=>[$ns]);
my $que = $res->send("$domain.",'NS');
if ( $que )
{
my @ns = $que->authority;
# check headers for 'aa' bit
my $header = $que->header;
print "answer is ", $header->aa ? "" : "non-", "authoritative\n";
if ( $header->aa ) # stop recursing when we have an authoritative answer.
{
my @authns = $que->answer;
foreach my $authns ( @authns )
{
$authns->print;
}
}
else # keep recursing no authoritative answer yet.
{
my $nsname = '';
# my host is IPv4 only, so I can only ask IPv4 name servers.
# this finds the first IPv4 name server and asks it.
foreach my $ns ( @ns )
{
$nsname = $ns->nsdname;
my $r = Net::DNS::Resolver->new('nameservers'=>[$sonicrns]);
my $q = $r->query($nsname,'A');
if ( $q )
{
my @answer = $q->answer;
if ( $answer[0]->type eq 'A' )
{
last;
}
}
$nsname = ''; # in-case we reach the end of the list and can't find an 'A' record.
}
if ( $nsname )
{
print "$nsname answers for $domain.\n";;
&_recurse($domain,$nsname);
}
else
{
print "No IPv4 name servers to query for $domain.\n";
}
}
}
else
{
print "Could not find NS records for $domain.\n";
}
}
Nice one! I might play around with this!