1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
|
#!/usr/bin/perl
# The new, improced "debug hostname" which makes it easy to make an
# offline test suite based on real-world DNS records
# This is the MaraDNS 0.9.17 version og debug.hostname
# Some global variables
$ASKMARA = "/usr/bin/askmara";
$TIMEOUT = "3";
$hostname = shift || "Awww.example.com.";
$ROOT_SERVER = shift || "198.41.0.4";
# Try to get the IP for a singlr host name; this has to be a
# function because of the way DNS is set up...we may need to
# recurse
# Input: Name to resolve; server to bug; bailiwick; recursion depth
# Ouput: the IPs in ddip format
sub resolve_name {
my($name,$server,$bailiwick,$depth,@visited) = @_;
my($level) = 1;
my(@name_servers,@name_server_ips,@name_server_ips_new);
my($answer) = ("");
my(%seen,$item);
foreach $item (@visited) {
$seen{$item} = 1;
}
if($depth > 0) {print "# Entering recursion level $depth\n"}
if($depth > 20) {
return "255.255.255.255";
}
# Convert name in to an askmara-compatible format
if($name !~ /^A/) {
$name = "A" . $name;
}
if($name !~ /\.$/) {
$name = $name . ".";
}
# Make the name lower case
$name =~ tr/A-Z/a-z/;
$name =~ s/^a/A/;
print "# The canonical name is $name\n";
# Add this name to the list of name servers we shall not attempt to
# resolve again (stops loops)
if($seen{$name}) {
print "# Already visited $name, exiting\n";
return "255.255.255.255";
}
@visited = ($name,@visited);
print "# Processing query for $name\n";
# Convert server in to name_server_ip format
@name_server_ips = ($server);
@name_servers = ("Aroot-server.invalid.");
# OK, get the name
while($level < 20) {
my($line);
# Run askmara
foreach $server (@name_server_ips) {
start_askmara:
if(!$server) {
goto nextserver;
}
#print "$ASKMARA -n -t $TIMEOUT $name $server \n";
open(ASKMARA,"$ASKMARA -n -t $TIMEOUT $name $server |") ||
die "Can not run $ASKMARA: $!\n";
# Process the output of askmara
@name_servers = ();
@name_servers_ips_new = ();
# See if we get a timeout or other hard error
$line = (<ASKMARA>); print $line;
if($line !~ /^# Querying/) {
close(ASKMARA);
return "255.255.255.255";
}
$line = (<ASKMARA>); print $line;
if($line =~ /^# Hard Error/) {
close(ASKMARA);
goto nextserver;
}
print "# Name: $name\n";
if($line !~ /^\# Question\: $name/) {
close(ASKMARA);
goto start_askmara;
}
$line = (<ASKMARA>); print $line;
# Authoritative answers
my($answer) = "";
while($line =~ /^[A-Z@]/) {
chop($line);
my(@fields) = split(/\|/,$line);
# A answers
if($line =~ /^A/) {
if($fields[2] eq "255.255.255.255") {
goto nextline;
}
if($answer) {
$answer .= ";" . $fields[2];
}
else {
$answer = $fields[2];
}
}
# CNAME answers
elsif($line =~ /^C/) {
my($query) = "A" . $fields[2];
# Recursion time
if(!$seen{$query}) {
my($reply) = (resolve_name($query,$ROOT_SERVER,".",
$depth + 1),@visited);
}
if($reply ne "255.255.255.255") {
if($answer) {
$answer .= ";" . $reply;
}
else {
$answer = $reply;
}
}
}
nextline:
$line = (<ASKMARA>); print $line;
}
if($answer) {
if($depth > 0) {print "# Exiting recursion level $depth\n"}
return $answer;
}
# Referrals
# Ignore everything until we hit the referral section
while($line !~ /^# NS replies:/) {
$line = (<ASKMARA>); print $line;
if(eof(ASKMARA)) {
print("# A SECTION ASKMARA EOF\n");
return "255.255.255.255";
}
}
$line = (<ASKMARA>); print $line;
# Handle the NS replies
while($line =~ s/^\#?N//) {
chop($line);
my(@fields) = split(/\|/,$line);
# Make sure we are in bailiwick
if($fields[1] !~ /$bailiwick$/i) {
print "# Out-of-bailiwick; going to next server\n";
goto nextserver; # Sometimes, you gotta
}
@name_servers = (@name_servers,$fields[2]);
$line = (<ASKMARA>); print $line;
}
# Host not here is always an error
if($line =~ /^#S/) {
return "255.255.255.255";
}
# Handle the AR records
if($line !~ /^# AR replies:/) {
goto nextserver;
}
print "# Next-level name servers for $name: @name_servers\n";
@name_server_ips_new = ();
# And the AR replies
while(<ASKMARA>) {
$line = $_;
print $line;
chop($line);
if($line =~ s/^\#?A//) {
my(@fields) = split(/\|/,$line);
my($counter);
for($counter = 0; $counter <= $#name_servers;
$counter++) {
if($name_servers[$counter] eq $fields[0]) {
unshift(@name_server_ips_new,$fields[2]);
splice(@name_servers,$counter,1);
}
}
}
}
# The only elements in @name_servers at this point
# is the glueless stuff
my($ns);
foreach $ns (@name_servers) {
my($reply);
if(!$seen{$ns}) {
$reply = resolve_name($ns,$ROOT_SERVER,".",$depth + 1,
@visited);
}
if($reply ne "255.255.255.255") {
unshift(@name_server_ips_new,$reply);
}
}
print "# Next-level name server IPs for $name: @name_server_ips_new\n";
goto lastserver;
nextserver:
}
lastserver:
@name_server_ips = @name_server_ips_new;
@name_servers = ();
$level++;
print "# Level $level\n";
}
}
resolve_name($hostname,$ROOT_SERVER,".",0);
|