Using other people's maintained code is always best, but in some environments it is just not plausible. Tarring/packaging up lots of modules, onto a remote platform that is locked down for security reasons, is not trivial.
Here is a paste of my long script that just uses plain simple Perl. It is somewhere in-between nslookup and dig. It was written for a Telco environment. Tested on MacOSX, RHEL6 & 7. Sorry about any bugs, and the use of ts=8
#!/usr/bin/perl -w
#=====================================================================
+=========
#
# = NAME
# nsdig.pl - A cross between nslookup and dig
#
# = DESCRIPTION
# DNS lookups when BIND/dig/nslookup packages not installed
#
# = AUTHOR
# Nigel Pearson. nigel.pearson.au@gmail.com
#
# Thanks to http://docstore.mik.ua/orelly/perl/sysadmin/ch05_03.htm
# http://www.binarytides.com/dns-query-code-in-c-with-linux-sockets
# (and Net::DNS + Perl Cookbook chapter 18, for earlier versions)
# and tokai on PerlMonks.org for his hexdump().
#
# = VERSION
# 0.7, circa 2016.
#
# = COPYRIGHT
# Released into public domain 29th Jan, 2021.
#=====================================================================
+=========
use strict;
use IO::Socket::INET;
my $DEBUG = 0;
my $EXTRA = 0; # Output extra sections, like AUTHORITY and ADDITION
+AL.
my $TEST = 0;
my $DefNS = '8.8.8.8';
my $NS;
#=====================================================================
+=========
sub Debug($)
{
$DEBUG && print STDERR @_, "\n"
}
sub hexdump($)
{
return if ( ! $DEBUG );
my $data = shift;
my $offset = 0;
foreach my $chunk ( unpack '(a16)*', $data ) # fails with old P
+erl?
{
my $hex = unpack 'H*', $chunk; # hexadecimal magic
$chunk =~ tr/ -~/./c; # replace unprintables
$hex =~ s/(.{1,8})/$1 /gs; # insert spaces
printf "0x%08x (%05u) %-*s %s\n", $offset, $offset, 36, $hex, $ch
+unk;
$offset += 16
}
}
#=====================================================================
+=========
#
# Make a possibly compressed IPv6 into its full representation.
#
# Does not cope with '::' at the start (e.g. '::' or '::1')
# We assume those are already filtered out.
#
sub ExpandIPv6($)
{
my $address = pop;
$address =~ s/^(.):/000$1:/g; # Leading zeros
$address =~ s/^(..):/00$1:/g;
$address =~ s/^(...):/0$1:/g;
$address =~ s/:(.):/:000$1:/g; # Same thing in middle
$address =~ s/:(..):/:00$1:/g;
$address =~ s/:(...):/:0$1:/g;
if ( $address =~ /\w::/ )
{
# A full address is 8 quad hex, plus 7 ':' (39)
my $insLen = 39 - length $address;
my $insert = substr ':0000:0000:0000:0000:0000:0000:0000',
0, $insLen+2; # The '::' is included
$address =~ s/::/$insert/
}
return $address
}
if ( 0 )
{
my $addr = '2001:0db8:ac10:fe01::';
print "ExpandIPv6($addr) = " . &ExpandIPv6($addr) . "\n";
$addr = 'f::';
print "ExpandIPv6($addr) = " . &ExpandIPv6($addr) . "\n";
exit;
}
#=====================================================================
+=========
#
# dn_expand_PP() from Net::DNS::Packet.pm
#
sub GetDN($$)
{
my ($data, $offset) = @_;
my $datalen = length $data;
my @domain = ();
if ( $offset >= $datalen )
{
&Debug("GenDN(,$offset) - Error, offset >= length data ($datalen)"
+);
return undef, $offset
}
if ( $DEBUG )
{
my $str = substr $data, $offset, 20;
my $hex = unpack 'H*', $str; # hexadecimal magic
$hex =~ s/(.{1,8})/$1 /gs; # insert spaces
$str =~ tr/ -~/./c; # replace unprintables
print "GetDN(,$offset) $hex $str\n"
}
while ( $offset < $datalen )
{
my $len = unpack "\@$offset C", $data;
if ( ( $len & 0xC0 ) == 0xC0 ) # Offset/pointer
{
my $ptr = 0x3FFF & ( unpack "\@$offset n", $data );
Debug("GetDN() - found pointer to $ptr");
my ($FQDN, undef) = &GetDN($data, $ptr);
push @domain, $FQDN; # pop???
return (join '.', @domain), $offset+2
}
if ( $len )
{
push @domain, substr $data, $offset+1, $len;
$offset += $len+1 # Includes the unpacked length byte
}
else
{ last }
}
if ( ! length $data )
{ die "GetDN() - ran over end of buffer!" }
++$offset; # Past zero/null at end
Debug("GetDN() - Got '" . join ('.', @domain) . "', offset now $o
+ffset");
return (join '.', @domain), $offset
}
my @typesbyval = ( 'SIGZERO', 'A', 'NS', 'MD', 'MF', 'CNAME', # [0]=
+SIGZERO
'SOA', 'MB', 'MG', 'MR', 'NULL', # [10]=NULL
'WKS', 'PTR', 'HINFO', 'MINFO', 'MX',
'TXT', 'RP', 'AFSDB', 'X25', 'ISDN', # [20]=ISDN
'RT', 'NSAP', 'NSAP_PTR', 'SIG', 'KEY',
'PX', 'GPOS', 'AAAA', 'LOC', 'NXT', # [30]=NXT
'EID', 'NIMLOC', 'SRV', 'ATMA', 'NAPTR',
'KX', 'CERT', 'A6', 'DNAME', 'SINK', # [40]=SINK
'OPT', 'APL', 'DS', 'SSHFP', 'IPSECKEY',
'RRSIG', 'NSEC', 'DNSKEY', 'DHCID', 'NSEC3',# [50]=NSEC3
'NSEC3PARAM' );
$typesbyval[55] = 'HIP';
$typesbyval[56] = 'NINFO';
$typesbyval[57] = 'RKEY';
$typesbyval[99] = 'SPF';
$typesbyval[100] = 'UINFO';
$typesbyval[101] = 'UID';
$typesbyval[102] = 'GID';
$typesbyval[103] = 'UNSPEC';
$typesbyval[249] = 'TKEY';
$typesbyval[250] = 'TSIG';
$typesbyval[251] = 'IXFR';
$typesbyval[252] = 'AXFR';
$typesbyval[253] = 'ILB';
$typesbyval[254] = 'MAILA';
$typesbyval[255] = 'ANY';
$typesbyval[32768] = 'TA';
$typesbyval[32769] = 'DLV';
my @classesbyval = ( '', 'IN', '', 'CH', 'HS');
$classesbyval[254] = 'NONE';
$classesbyval[255] = 'ANY';
#
# Simplified GetDN() used for resource record processing.
# Generic strings don't use pointer compression, thus no recursion
#
sub GetStr($$)
{
my ($data, $offset) = @_;
if ( $DEBUG )
{
my $str = substr $data, $offset, 20;
my $hex = unpack 'H*', $str; # hexadecimal magic
$hex =~ s/(.{1,8})/$1 /gs; # insert spaces
$str =~ tr/ -~/./c; # replace unprintables
print "GetStr(,$offset) $hex $str\n"
}
my $len = unpack "\@$offset C", $data;
my $str = substr $data, $offset+1, $len;
Debug("GetStr() - Got '$str', offset now $offset+$len+1");
return $str, $offset+$len+1
}
#
# Slightly based on DNS::Question->parse().
# My caller doesn't need to know the length of what we parse,
# so the recursion and offset stuff in dn_expand_PP() isn't needed!
#
sub ParseQ($)
{
my $data = shift;
my $FQDN = '';
while ( length $data > 0 )
{
my $len = unpack 'C', $data;
my $str = substr $data, 1, $len;
$data =~ s/^.$str//;
if ( ! $len ) # Strings seem to end with a zero/null
{ last } # which is also stripped by the above =~
$FQDN .= "$str."
}
if ( ! length $data )
{ die "ParseQ() - ran over end of QNAME!" }
chop $FQDN;
my ($type, $class) = unpack 'n2', $data;
return $FQDN, $typesbyval[$type], $classesbyval[$class]
}
#
# Rewrite of Net:DNS:RR->parse() and new_from_data()
#
sub ParseRR($$)
{
my ($data, $offset) = @_;
Debug("ParseRR() Getting name at $offset");
my ($name, $index) = GetDN($data, $offset);
my ($type, $class, $TTL, $rdlen) = unpack "\@$index n2 N n", $data
+;
$offset = $index + 10;
Debug("ParseRR() Type $type, Class $class, TTL $TTL, rdlen $rdlen"
+);
if ( length $data < ($offset + $rdlen) )
{ die 'ParseRR(): incomplete data' }
Debug("ParseRR() Reading RDATA from offset $offset");
my $rdata = substr $data, $offset, $rdlen;
#
# Now, a lot of munging to return appropriate data:
#
$type = $typesbyval[$type];
if ( $type eq 'OPT' ) # RFC2671, 4.3
{ $class = "uint16 $class" }
else
{ $class = $classesbyval[$class] }
my $result = '';
if ( $type =~ m/^(CNAME|MB|MG|MR|NS|PTR)$/ ) # MOSTLY UNTESTED
{ ($result, undef) = GetDN($data, $offset) }
if ( $type eq 'SOA' )
{
my ($mname, $skip1) = GetDN($data, $offset);
my ($rname, $skip2) = GetDN($data, $skip1);
if ( $rname !~ m/\@/ ) # If this doesn't look like an email
+,
{ $rname =~ s/\./@/ } # hack it !
my ($serial, $refr, $rtry, $exp) = unpack "\@$skip2 N4", $data;
$result = "$mname $rname ( $serial $refr $rtry $exp $TTL )"
}
if ( $type eq 'MX' )
{
$result = unpack 'n', $rdata;
my ($exchange, undef) = GetDN($data, $offset+2);
$result .= " $exchange"
}
if ( $type eq 'NAPTR' )
{
my ($order, $preference) = unpack 'n2 ', $rdata;
$result = "$order $preference ";
my ($flags, $skip1) = GetStr($data, $offset+4);
my ($service, $skip2) = GetStr($data, $skip1);
my ($regexp, $skip3) = GetStr($data, $skip2);
my ($replace, undef) = GetDN($data, $skip3);
$result .= "'$flags' '$service' '$regexp' '$replace'"
}
if ( $type eq 'SRV' )
{
my ($pri, $weight, $port) = unpack 'n3 ', $rdata;
my ($target, undef) = GetDN($data, $offset+6);
$result = "$pri $weight $port $target.";
}
# OPT? SRV? LOC? MINFO
if ( $type =~ m/(HINFO|ISDN|SPF|TXT|X25)/ ) # UNTESTED
{
my $byte = 0;
while ( $byte < $rdlen )
{
my $len = unpack 'n', $rdata; $byte += 2;
$result .= substr $rdata, 0, $len; $byte += $len;
$result .= ' '
}
}
if ( $type eq 'A' )
{ $result = inet_ntoa(substr $rdata, 0, 4) }
if ( $type eq 'AAAA' )
{
$result = unpack 'H32', $rdata; # hex from network order (high fir
+st)
$result =~ s/(....)/$1:/g;
chop $result;
$result =~ s/^0+:/:/; # leading zeroes
$result =~ s/:0+/:/g; # leading zeroes in each quad
$result =~ s/:+:/::/g; # excess contractions!
if ( $result eq '::' ) { $result .= ' (unspecified, all zeros)' }
}
return $name, $type, $class, $TTL, $result, $offset+$rdlen
}
#
# Generate a UDP header, send to name server, read and return results
#
sub QueryV4($$$@)
{
my ($format, $type, $ns, @query) = @_;
my $query = pack ( 'n C2 n4',
$$, # Process ID - hopefully a short
0 + # Std. query, not authoritative, non-truncated
1, # Recursion desired
0, # No checking, authentication, recursion, z?
1, # 1 question entry supplied
0, # no answer entries ,,
0, # no nameserv entries ,,
0 ) # no resource entries ,,
. pack ( $format,
@query,
0, # end of query strings
$type,
1 ); # Query class of IN
Debug("\nSending ..."); hexdump($query); Debug(" to $ns");
my ($datagram, $sock);
$sock = new IO::Socket::INET (PeerAddr=>$ns, PeerPort=>53, Proto=>
+'udp')
or die "Can't create socket: $@";
$sock->send($query);
# Allow 3 seconds to respond.
# If nothing back in that time, $ns is unreachable?
eval
{
local $SIG{ALRM} = sub { die 'TIMEOUT'; };
alarm 3;
# DNS over UDP is always up to 576 bytes? (512 payload)
$sock->recv($datagram, 512 );
alarm 0;
};
alarm 0;
if ( $@ && $@ =~ 'TIMEOUT' )
{ return 0, 'TIMEOUT' }
close $sock;
Debug("\nReceived ..."); hexdump($datagram);
return length $query, $datagram
}
#
# Lookup a nameserver and return either name, or "dig"-like output
#
sub Query($$$$)
{
my ($ns, $thingy, $qtype, $nameOnly) = @_;
if ( $ns =~ m/:/ )
{ return QueryErr($nameOnly, "$ns - Cannot query IPv6 servers y
+et") }
if ( $ns !~ m/^\d+\.\d+\.\d+\.\d+$/ )
{ return QueryErr($nameOnly, "'$ns' is not an IP addresses") }
if ( $thingy !~ m/\./ )
{ return QueryErr($nameOnly, "Cannot lookup '$thingy' - no domai
+n!") }
if ( ! defined $qtype or $qtype !~ m/\d/ )
{ $qtype = 1 } # IN type A=1
if ( ! defined $nameOnly )
{ $nameOnly = 0 }
#
# Construct Query string for outgoing request:
#
my $qformat = '';
my @query = ();
for (split ( /\./, $thingy ) )
{ $qformat .= 'C a* '; push @query, length; push @query, $_ }
$qformat .= 'C n2';
my $qtypestr = $typesbyval[$qtype];
my ($skip, $datagram) = QueryV4($qformat, $qtype, $ns, @query);
if ( $datagram eq 'TIMEOUT' )
{ return QueryErr($nameOnly, "Timeout receiving data from $ns")
+ }
my $size = length $datagram;
if ( $size < 40 )
{
return QueryErr($nameOnly, "Short response from '$ns' - $size byte
+s")
}
# Header is easy:
my ($id, $flags1, $flags2, $queries, $answers, $authNSs, $addt)
= unpack 'n C2 n4', $datagram;
my $offset = 12;
if ( $id != $$ or $queries != 1 )
{ return QueryErr($nameOnly, "We got someone else's query? Damn
+ UDP!") }
if ( $nameOnly and $answers lt 1 )
{ return QueryErr($nameOnly, "Cannot find $thingy on $ns") }
if ( $answers+$authNSs lt 1 )
{
return QueryErr($nameOnly, "Cannot find 'IN $qtypestr' $thingy on
+$ns")
}
Debug("$answers answers, $authNSs authoritative NSs, $addt additio
+nal.");
#
# Parse results and make output to be similar tothat from dig(1)
#
my $lines = "\n; <<>> nsdig.pl 0.7 <<>> ";
if ( $qtype != 1 ) { $lines .= "-t$qtypestr " }
$lines .= "\@$ns $thingy\n";
#
# We should parse the question section like this:
#
# $lines .= "\n;; QUESTION SECTION;\n";
# for ( 1 .. $queries )
# {
# my ($name,$type,$class,undef) = ParseQ(substr $datagram, $offset)
+;
# $lines .= "$name\t\t$class $type\n"
# }
#
# but since query received = query sent, save time:
#
$offset = $skip;
my $foundIPv6 = 0;
if ( $answers )
{
if ( $nameOnly )
{ $lines = '' }
else
{ $lines .= "\n;; ANSWER SECTION:\n" }
for ( 1 .. $answers )
{
my ($name, $type, $class, $TTL, $result, $skip)
= ParseRR($datagram, $offset);
$offset = $skip;
$lines .= "$name\t$TTL\t$class $type $result\n";
if ( $type eq 'AAAA' )
{ $foundIPv6 = 1 }
}
}
#
# Since many DNS servers also have IPv6 data for thingy,
# do another request if the first one was default lookup for addre
+sses
#
if ( $qtype == 1 and ! $foundIPv6 )
{
my ($skip, $data) = QueryV4($qformat, 28, $ns, @query); # type AA
+AA=28
if ( length $data < 40 )
{ next }
my ($id, $flags1, $flags2, $queries, $answers, $authNSs, $addt)
= unpack 'n C2 n4', $data;
&Debug("IPv6: $answers answers,"
. " $authNSs authoritative NSs, $addt additional.");
if ( $id == $$ and $queries == 1 and $answers > 0 )
{
for ( 1 .. $answers )
{
my ($name, $type, $class, $TTL, $result, $skip2)
= ParseRR($data, $skip);
$skip = $skip2;
if ( $type eq 'AAAA' )
{ $lines .= "$name\t$TTL\t$class $type $result\n" }
}
}
}
$lines .= "\n";
if ( $nameOnly ) { return $lines }
if ( $authNSs )
{
$lines .= ";; AUTHORITY SECTION:\n";
for ( 1 .. $authNSs )
{
my ($name, $type, $class, $TTL, $result, $skip)
= ParseRR($datagram, $offset);
$offset = $skip;
$lines .= "$name\t$TTL\t$class $type $result\n"
}
$lines .= "\n";
}
if ( $addt )
{
$lines .= ";; ADDITIONAL SECTION:\n";
for ( 1 .. $addt )
{
my ($name, $type, $class, $TTL, $result, $skip)
= ParseRR($datagram, $offset);
$offset = $skip;
$lines .= "$name\t$TTL\t$class\t$type\t$result\n"
}
$lines .= "\n";
}
$lines .= ";; SERVER: $ns#53\n";
$lines .= ";; When: " . `date '+%a %b %e %H:%M:%S %Y' `;
$lines .= ";; MSG SIZE rcvd: $size\n";
return $lines
}
#
# Return error from Query in appropriate format
#
sub QueryErr($$)
{
my ($short, $err) = @_;
if ( $short )
{ return $err }
return "\nERROR -- $err\n"
}
#
# Use PTR lookup to find names for IP address
#
sub LookupIP($$)
{
my ($ns, $IP) = @_;
if ( $ns !~ m/^\d+\.\d+\.\d+\.\d+$/ )
{ return "Error - '$ns' is not an IP addresses" }
#
# Construct Query string for outgoing request:
#
my $qformat = '';
my @query = ();
for (split ( /\./, $IP ) )
{ $qformat .= 'C a* '; push @query, length; push @query, $_ }
$qformat .= 'C n2';
my ($skip, $datagram) = QueryV4($qformat, 12, $ns, @query); # P
+TR=12
my $size = length $datagram;
if ( $size < 40 )
{ return "Short Name Server response - $size bytes" }
# Header is easy:
my ($id, $flags1, $flags2, $queries, $answers, $authNSs, $addt)
= unpack 'n C2 n4', $datagram;
my $offset = 12;
if ( $id != $$ or $queries != 1 )
{ return "We got someone else's query? Damn UDP!" }
if ( $answers lt 1 )
{ return "Cannot find 'IN PTR $IP' on $ns" }
Debug("$answers answers, $authNSs authoritative NSs, $addt additio
+nal.");
#
# We should parse the question section like this:
#
# $lines .= "\n;; QUESTION SECTION;\n";
# for ( 1 .. $queries )
# {
# my ($name,$type,$class,undef) = ParseQ(substr $datagram, $offset)
+;
# $lines .= "$name\t\t$class $type\n"
# }
#
# but since query received = query sent, save time:
#
$offset = $skip;
my @names;
for ( 1 .. $answers )
{
my ($name, $type, $class, $TTL, $result, $skip)
= ParseRR($datagram, $offset);
$offset = $skip;
push @names, $result
}
# Very unlikely!
for ( 1 .. $authNSs )
{
my ($name, $type, $class, $TTL, $result, $skip)
= ParseRR($datagram, $offset);
$offset = $skip;
push @names, $result
}
# Also very unlikely!
for ( 1 .. $addt )
{
my ($name, $type, $class, $TTL, $result, $skip)
= ParseRR($datagram, $offset);
$offset = $skip;
push @names, $result
}
return @names;
}
sub Lookup($$$)
{
my ($thingy, $ns, $qtype) = @_;
if ( ! defined $ns )
{ $ns = $NS }
my $result = '';
if ( $thingy =~ /:\/\/(.+)/ ) # Most URLs like http://
{
$result = "URL: $thingy\n";
$thingy = $1;
$thingy =~ s,/.*,,;
}
if ( $thingy =~ /^\w+:.*@(.+)/ ) # URIs like mailto: sip:
{
$result = "URI: $thingy\n";
$thingy = $1;
}
# Simple IPv4 reverse lookups:
if ( $thingy =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)\/?/ or # A.B.C.D o
+r A.B.C.D/
$thingy =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+):\d+/ ) # A.B.C.D:port/
+blah
{
$result .= "IP addr: $thingy\n";
my $IP = "$4.$3.$2.$1.in-addr.arpa";
my $names = join ', ', LookupIP($ns, $IP);
if ( $names =~ /^Cannot find/ )
{ return $result . " - $names" }
else
{ return $result . "Name: $names" }
}
# Same for IPv6:
if ( $thingy =~ /(::|[\dabcdef]+:[\dabcdef:]+)/ )
{
# Strip [] from a possible URL. e.g. http:[.*]/blah
$thingy =~ s/^\[//, $thingy =~ s/\].*//;
$result .= "IPv6: $thingy\n";
if ( $thingy eq '::' or $thingy eq '0:0:0:0:0:0:0:0' )
{ return $result . 'Meaning: "Unspecified" address' }
if ( $thingy eq '::1' or $thingy eq '0:0:0:0:0:0:0:1' )
{ return $result . 'Meaning: Local/loopback address' }
$thingy = ExpandIPv6($thingy);
$thingy =~ s/://g;
my $IP = chop $thingy;
while ( $thingy )
{ $IP .= '.' . chop $thingy }
my $names = join ', ', LookupIP($ns, "$IP.ip6.arpa");
if ( $names =~ /^Cannot find/ )
{ return $result . " - $names" }
else
{ return $result . "Name: $names" }
}
if ( $thingy =~ /\w+\.\w+/ ) # FQDN
{
$result .= "Domain: $thingy\n";
if ( ! defined $qtype )
{ $qtype = 1 } # IN A - Address
my $addr .= Query($ns, $thingy, $qtype, 1);
if ( $addr =~ /^Cannot find/ )
{ return $result . " - $addr" }
else
{ return $result . "IP addr: $addr" }
}
if ( $result )
{ $result .= " - Unable to lookup '$thingy'" }
else
{ $result = "ERROR -- Unable to lookup '$thingy'" }
return $result
}
#=====================================================================
+=========
sub Usage($)
{
my $err = shift;
if ( $err )
{ $err = "ERROR: $err\n" }
print <<EOF;
DNS lookup for hostname, FQDN, IP addresses, or simple URIs!
$err
usage: $0 -test
usage: $0 name server
usage: $0 -type=query-type name server
usage: $0 \@server name*
usage: $0 \@server -t query-type name*
usage: $0 -extra name*
usage: $0 -debug name*
usage: $0 name*
Note that name can be a number of host.domain, URI or an IP-address,
but if you specify two of them, I'll assume second one is a DNS server
+ :-)
EOF
exit 0
}
if ( ( scalar grep /^\@.+/, @ARGV) > 1 )
{ Usage('multiple @server arguments') }
my @args = ();
my $qtype = '';
foreach ( @ARGV )
{
# Ugly hack for split word arguments:
if ( $qtype eq 'NEXTLOOP' ) { $qtype = $_; next }
if ( /^-t$/ ) { $qtype = 'NEXTLOOP'; next }
if ( /^@(.*)/ ) { $NS = $1; next }
if ( /^-type=(.*)/ or
/^--type=(.*)/ ) { $qtype = $1; next }
if ( /^-debug/ or /^--debug/ ) { $DEBUG = 1; next }
if ( /^-extra/ or /^--extra/ ) { $EXTRA = 1; next }
if ( /^-test/ or /^--test/ ) { $TEST = 1; next }
if ( /^-h/ or /^--help/ ) { Usage('') }
# Otherwise, assume list of things to lookup
push @args, $_
}
if ( $qtype eq 'NEXTLOOP' )
{ Usage('-t argument missing.') }
if ( $qtype )
{
my $i = 0;
while ( $i < $#typesbyval )
{
if ( defined $typesbyval[$i] # there are gaps in @typesbyval
and (uc $qtype) eq $typesbyval[$i] )
{ $qtype = $i; last }
$i++;
}
if ( $i == $#typesbyval )
{ $qtype = undef }
}
#
# Finally start the lookups
#
if ( scalar @args == 2 )
{ print &Query($args[1], $args[0], $qtype, $EXTRA==0) . "\n"; exit;
+ }
if ( ! $NS )
{
$NS = `egrep nameserver /etc/resolv.conf | head -n 1`; chop $NS;
if ( $NS )
{ $NS =~ s/^nameserver\W*// }
else
{ $NS = $DefNS }
}
if ( scalar @args > 0 )
{
foreach ( @args )
{
if ( $EXTRA )
{ print Query($NS, $_, $qtype, 0) }
else
{ print Lookup($_, $NS, $qtype) }
}
}
elsif ( $TEST )
{
print &Query('2001:4860:4860::8888','www.apple.com');
print &Query('dns.google.com', 'blah.blah');
print &Query('8.8.8.8', 'blah');
my $sep = '=======================================================
+=======';
print $sep . &Query($NS, 'apple.com');
print $sep . &Query($NS, 'apple.com', 6); # 6=SOA
print $sep . &Query($NS, 'apple.com', 15); # 15=MX
print $sep . &Query($NS, 'apple.com', 35); # 35=NAPTR
print $sep . &Query($NS, 'www.apple.com');
print $sep . &Query($NS, 'www.apple.com', 28); # 28=AAAA
$sep = "\n........\n";
print $sep . &Lookup('http://127.0.0.1');
print $sep . &Lookup('anyoldrubbish');
print $sep . &Lookup('10.97.217.136');
print $sep . &Lookup('mailto:nigel\@ind.tansu.com.au');
print $sep . &Lookup('https://149.135.128.11/~nigel');
print $sep . &Lookup('2001:67c:2d7c:66::53');
print $sep . &Lookup('fdac:45f8:8cea:66d7:924:694f:bcd:d155');
print $sep . &Lookup('tel:+61285765449');
print $sep . &Lookup('sip:+61285765449;npdi@[fdac:45f8:8cea:66d7:9
+24:694f:bcd:d155];param=yes') . "\n";
exit 0;
}
else { Usage('') }
| [reply] [d/l] |