in reply to How would I do this "dig" command in Perl?

This is basically a DNS query. Most likely, you can do the same by using (for example) Net::DNS, AnyEvent::DNS or by querying your WAN modem if it has UPnP enabled.

In principle, you could get most of this by using gethostbyname, except that this will not use the resolver1.opendns.com resolver but whatever your machine is configured to use for resolving hostnames.

Replies are listed 'Best First'.
Re^2: How would I do this "dig" command in Perl?
by Nige (Beadle) on Feb 05, 2016 at 07:28 UTC
    The real question is how would you do it just in simple Perl!

    Imagine a server that has no nslookup or dig utilities.
    It has a recent Perl, you can "use Socket;", but not Net::DNS. You are not root, so can't install anything.
    You have an IP address for something you think is a DNS server, and want to lookup some names. How?

        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('') }
Re^2: How would I do this "dig" command in Perl?
by Todd Chester (Scribe) on Nov 11, 2015 at 03:02 UTC
    Thank you!