NAME
   Net::DNS::Dig - dig like methods

SYNOPSIS
   IO methods and functions to return DNS information

   These functions do not use "SIG_ALRM" and are safe to use in CGI
   programs.

     use Net::DNS::Dig qw(
           :forceEmu
           ndd_gethostbyaddr
           ndd_gethostbyname
           ndd_gethostbyname2
           AF_INET
           AF_INET6
     );

     $dig = new Net::DNS::Dig();
     $dig = new Net::DNS::Dig( %hash );
     $dig = new Net::DNS::Dig( \%hash );

     $dobj = $dig->for(name, type);
     $tobj = $dig->to_text();

     $array_ptr =  $dig->data($section);
     $array_ptr = $tobj->data($section);

     $array_ptr =  $dig->records($type,$sect);
     $array_ptr = $tobj->records($type,$sect);

     $text  = $dig->sprintf;

     $rv    = $dig->rcode(true/false);
     $rdata =  $dig->rdata($type,$sect);
     $rdata = $tobj->rdata($type,$sect;

        or in array context
     @array = $dig->data($section);
     @array = $dig->records($type,$sect);
     @rdata = $dig->rdata($type,$sect);

     ($name,$aliases,$addrtype,$length,@addrs)
           = ndd_gethostbyaddr( naddr_naddr6 );

     ($name,$aliases,$addrtype,$length,@addrs)
           = ndd_gethostbyname( name_ipV4_ipV6 );

     ($name,$aliases,$addrtype,$length,@addrs)
           = ndd_gethostbyname2( name_ipV4_ipV6 AF_family);

       or in array context
     $name    = ndd_gethostbyaddr(netaddr);
     $netaddr = ndd_gethostbyname(name_ipV4);
     $netaddr = ndd_gethostbyname2(name_ipV4_ipV6,AF_family);

DESCRIPTION
   * $dig = new Net::DNS::Dig( # optional parameters
          Timeout   => 15,          # default
          Class     => 'IN',        # default
          PeerAddr  => host or [name1, name2, ...] default local NS
          PeerPort  => 53,          # default
          Proto     => 'UDP',       # default
          Recursion => 1,           # default
          QuesHead  => 0,           # default, print question header
          QuesBody  => 0,           # default, print question body
          RespHead  => 0,           # default, print response header
          RespBody  => 0,           # default, print response body
        );

   * $dobj = $dig->for(name, type);
    This method returns a blessed object containing the binary query
    response object

      $dobj is $dig filled with the following data

      input:        query name      i.e. host name, ip address, etc...
                    type            [optional type] A, MX, etc...
      returns:      blessed object of the form...

      $dobj = {
            Timeout   => input value,
            Class     => input value,
            PeerAddr  => [input value],
            PeerPort  => input value,
            Proto     => input value,
            Recursion => input value,

            Errno     => posix error number or set to zero

            ELAPSED   => milliseconds,      # query time
            NRECS     => number of records,
            BYTES     => number of bytes
            TEXT      => '',                # this field is empty
            SERVER    => name,              # of query server

            HEADER    => {
                    ID      => return value,
                    QR      => return value,
                    AA      => return value,
                    TC      => return value,
                    RD      => return value,
                    RA      => return value,
                    MBZ     => return value,
                    AD      => return value,
                    CD      => return value,
                    RCODE   => return value,
                    OPCODE  => return value,
                    QDCOUNT => return value, # question
                    ANCOUNT => return value, # answer
                    NSCOUNT => return value, # authority
                    ARCOUNT => return value, # additional
            },
            QUESTION  => [
                    {
                    NAME    => return name,
                    TYPE    => return type,
                    CLASS   => return class,
                    },
            ],
            ANSWER    => [  # for each answer record
                    {
                    NAME    => return name,
                    TYPE    => return type,
                    CLASS   => return class,
                    TTL     => return ttl,
                    RDLEN   => $n,          # octets
                    RDATA   => @rdata,      # data fields
                    },
            ],
            AUTHORITY  => [ # for each authority record
                    {
                    NAME    => return name,
                    TYPE    => return type,
                    CLASS   => return class,
                    TTL     => return ttl,
                    RDLEN   => $n,          # octets
                    RDATA   => @rdata,      # data fields
                    },
            ],
            ADDITIONAL  => [        # for each glue record
                    {
                    NAME    => return name,
                    TYPE    => return type,
                    CLASS   => return class,
                    TTL     => return ttl,
                    RDLEN   => $n,          # octets
                    RDATA   => @rdata,      # data fields
                    },
            ],
      };

   * $tobj = $dig->to_text();
    This method returns a blessed object of the same form as dig above with
    the following fields converted to text:

            RCODE
            OPCODE
            QUESTION
            ANSWER
            AUTHORITY
            ADDITIONAL

    The TEXT value scalar is filled with a formatted text string like that
    returned from *NIX "dig"

   * $array_ptr = $dig->data($section);
   * $array_ptr = $tobj->data($section);
      or

   * @array = $dig->data($section);
    This method returns a pointer or array in binary or text form from from
    a $dig or $tobj object pointer, respectively.

    In scalar context returns a pointer to an array of query response
    hash's representing each record returned.

    In array context returns an array of hash's for each query response
    record.

      input:    section name [optional, default ANSWER]

      returns:  array pr pointer to array of one or more hash's
                ->[ {}, {}, {}, ...];

      where $section if one of:
       QUESTION, ANSWER, AUTHORITY, ADDITIONAL

    Each answer hash is of the form described above for:

            $dig->for();

   * $array_ptr = $dig->records($type,$sect);
   * $array_ptr = $tobj->records($type,$sect);
      or

   * @array = $dig->records($type,$sect);
    This method returns a pointer to or an array of RDATA arrays for each
    query response record.

      input:    $type  [optional record type, A, NS, etc...]
        not case sensitive, defaults to TYPE of original query
                $sect  [optional section, defaults to ANSWER]

      returns:  array or pointer to array of one or more rdata arrays
                    ->[ [], [], [], ...] ];

      where $sect is one of ANSWER, AUTHORITY, ADDITIONAL

    Each answer array is of the form described above for RDATA in:

            $dig->for();

   * $rdata = $dig->rdata($type,$sect);
   * $rdata = $tobj->rdata($type,$sect;
      or

   * @rdata = $dig->rdata($type,$sect);
    This method returns the first element or a list of rdata items. See the
    appropriate RFC's for types such as MX which have two elements per
    record.

      i.e.  MX rdata => (priority, name)

      multiple records would be returned as a list of
            pri, name, pri, name, etc...

      input:    $type  [optional record type, A, NS, etc...]
        not case sensitive, defaults to TYPE of original query
                $sect  [optional section, defaults to ANSWER]

      returns: a list or its first element

   * $rv = $dig->rcode(true/false);
    This method returns the query response code in numeric form if argument
    is false and the text response code if the argument is true.

      NOERROR   => 0,
      FORMERR   => 1,
      SERVFAIL  => 2,
      NXDOMAIN  => 3,
      NOTIMP    => 4,
      REFUSED   => 5,
      YXDOMAIN  => 6,
      YXRRSET   => 7,
      NXRRSET   => 8,
      NOTAUTH   => 9,
      NOTZONE   => 10,

   * $text = $dig->sprintf;
    This method return the dig query response text from either the dig
    object pointer or a dig text object pointer. "to_text" is called
    automatically if required.

   * $netaddr = ndd_gethostbyname($name);
    or

   * @array = ndd_gethostbyname($name);
      ($name,$aliases,$aftype,$len,@addrs)
            = ndd_gethostbyname($name);

   * $netaddr = ndd_gethostbyname2($name,$AF_family);
    or

   * @array = ndd_gethostbyname2
      ($name,$aliases,$aftype,$len,@addrs)
            = ndd_gethostbyname2($name,$AF_family);

   * $name = ndd_gethostbyaddr($iaddr,$AF_family);
    or

   * @array = ndd_gethostbyaddr
      ($name,$aliases,$aftype,$len,@addrs)
            = ndd_gethostbyaddr($iaddr,$AF_family);

   These functions use or emulate the underlying system calls of the same
   name, enhancing the capability of Perl to support IPv6 where needed. If
   the function is present in Perl and/or Socket6, the Perl function is
   called directly.

   If "use Net::DNS::Dig qw( :forceEmu )" is loaded with the force
   emulation tag, the Net::DNS;Dig's version of the function is always
   used. This is useful when the underlying system "gethostbyname2" and/or
   "gethostbyaddr" functions are present but broken.

   NOTE: the emulations do not check NIS or system "hosts" file.

     Function Net::DNS::Dig (ndd_) gethostbyname

     input:        $name           text string or ip address
       [optional]  $timeout        seconds

   ndd_gethostbyname emulates or uses Perl's gethostbyname system call.

     Function Net::DNS::Dig (ndd_) gethostbyname2

     input:        $name           text string or ip address
       [optional]  $AF_family      address family type
       [optional]  $timeout        seconds for the emulation

   ndd_gethostbyname2 provides a fully functional gethostbyname2
   implementation that will work on systems that do not support IPv6 or
   have broken IPv6 socket libraries.

   If $AF_family is false, ndd_gethostbyname2 will examine the supplied
   $name to try and determine the appropriate AF_family if the name is an
   IPv4 address of the form d+.d+.d+.d+ or and IPv6 address in one of the
   RFC1884 formats it will do the right thing and return a text version of
   the address. Otherwise, AF_INET is assumed by default and a DNS lookup
   will be performed.

     Function Net::DNS::Dig (ndd_) gethostbyaddr

     input:        $naddr          network address
       [optional]  $AF_family      address family type
       [optional]  $timeout        seconds for the emulation

   If $AF_family is false, ndd_gethostbyaddr will examine the supplied
   $naddr and determine the appropriate AF_family.

   Common return, all functions

     $name         text name
     $aliases      space separated list of text names
     $atype        address type - AF_family constant
     $len          length of the address 4 or 16
     @addrs        array of naddrs in network form

   * $constant = AF_INET;
   * $constant = AF_INET6;
   These two functions return the constant value for the AF_families,
   respectively, of the underlying operating system.

EXAMPLES
   Example usage of Net::DNS::Dig

     ########### example 1 retrieving netaddrs

     use NetAddr::IP::Util qw(inet_ntoa);
     use Net::DNS::Dig;

     $name = 'gmail.com';

     # return one of the gmail 'A' records

     $netaddr = Net::DNS::Dig->new()->for($name)->rdata();

     print inet_ntoa($netaddr),"\n";

     ########### example 2 retrieve many netaddrs

     use NetAddr::IP::Util qw(inet_ntoa);
     use Net::DNS::Dig;

     $name = 'gmail.com';

     # return all of the gmail 'A' records

     @netaddrs = Net::DNS::Dig->new()->for( $name )->rdata();

     foreach ( @netaddrs ) {
       print inet_ntoa( $_ ),"\n";
     }

     ########### example 3 retrieve MX host for email

     use Net::DNS::Dig;

     $email = '[email protected]';

     ( $name = $email ) =~ s/.+\@(.+)/$1/;

     # return all of the gmail 'MX' records
     # records return PRIORITY, HOST, ...
     # hostnames are unique

     my %mx_info = reverse Net::DNS::Dig->new()->for( $name,'MX' )->rdata();

     my @host_by_priority;

     foreach ( sort {
           $mx_info{$a} <=> $mx_info{$b}
                    } keys %mx_info ) {
       push @host_by_priority, $_;
     }

     foreach ( @host_by_priority ) {
       print "$_\t    $mx_info{$_}\n";

     }

     ########### example 4 a simple 'dig' script

     #!/usr/bin/perl
     #
     # example simple 'dig.pl' script
     #
     use Net::DNS::Dig;

     my ($name,$type);

     while ( $_ = shift @ARGV ) {
       if ( $_ eq '-t' ) {
         $type = shift;
       } else {
         $name = $_;
       }
     }

     print Net::DNS::Dig->new()->for( $name, $type )->sprintf;

   # end of script simple dig.pl

     command prompt > dig.pl -t aaaa arpa.com

     [response]

     ; <<>> Net::DNS::Dig 0.01 <<>> -t aaaa arpa.com.
     ;;
     ;; Got answer.
     ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35979
     ;; flags: qr ra; QUERY: 1, ANSWER: 0, AUTHORITY: 8, ADDITIONAL: 8

     ;; QUESTION SECTION:
     ;arpa.com.              IN      AAAA

     ;; AUTHORITY SECTION:
     arpa.com.       79436   IN      NS       pdns2.ultradns.net.
     arpa.com.       79436   IN      NS       pdns1.ultradns.net.
     arpa.com.       79436   IN      NS       pdns5.ultradns.info.
     arpa.com.       79436   IN      NS       pdns3.ultradns.org.
     arpa.com.       79436   IN      NS       udns2.ultradns.net.
     arpa.com.       79436   IN      NS       pdns4.ultradns.org.
     arpa.com.       79436   IN      NS       udns1.ultradns.net.
     arpa.com.       79436   IN      NS       pdns6.ultradns.co.uk.

     ;; ADDITIONAL SECTION:
     pdns1.ultradns.net.     54013   IN      A        204.74.108.1
     pdns2.ultradns.net.     54013   IN      A        204.74.109.1
     pdns3.ultradns.org.     67699   IN      A        199.7.68.1
     pdns4.ultradns.org.     67699   IN      A        199.7.69.1
     pdns5.ultradns.info.    67699   IN      A        204.74.114.1
     pdns6.ultradns.co.uk.   67699   IN      A        204.74.115.1
     udns1.ultradns.net.     67698   IN      A        204.69.234.1
     udns2.ultradns.net.     67698   IN      A        204.74.101.1

     ;; Query time: 27 ms
     ;; SERVER: 192.168.1.171# 53(192.168.1.171)
     ;; WHEN: Mon Oct 10 17:23:39 2011
     ;; MSG SIZE rcvd: 365 -- XFR size: 17 records

     ########### example 5 a complex 'dig' script

     #!/usr/bin/perl
     #
     # example complex 'dig.pl' script
     #
     use Net::DNS::Dig qw(
           ndd_gethostbyname
     );

     my($name, $type, $port, $server, $tcp, $time, $recurse);

     unless (@ARGV) {
       print qq|\nusage: $0 [options] name

           -t [type]               a, mx, etc...
           -p [port number]
           +tcp                    use TCP
           +norecursive
           +time=[seconds]         timeout

     |;
       exit;
     }

     while ( $_ = shift @ARGV ) {
       if ( $_ eq '-t' ) {
         $type = shift;
       }
       elsif ( $_ eq '-p' ) {
         $port = shift;
       }
       elsif ( $_ =~ /^\@(.+)/ ) {
         $server = $1;
       }
       elsif ( lc $_ eq '\+tcp' ) {
         $tcp = 'tcp';
       }
       elsif ( $_ =~ /^\+time=(\d+)/ ) {
         $time = $1;
       }
       elsif ( $_ =~ /^\+norecursive/ ) {
         $recurse = 1;
       }
       else {
         $name = $_;
       }
     }

     my $config = {
           Timeout   => $time,
           PeerAddr  => $server,
           PeerPort  => $port,
           Proto     => $tcp,
           Recursion => $recurse,
     };

     print Net::DNS::Dig->new($config)->for($name,$type)->to_text->sprintf;

     # end of script complex dig.pl

EXPORTS_OK
           :forceEmu
           ndd_gethostbyaddr
           ndd_gethostbyname
           ndd_gethostbyname2
           AF_INET
           AF_INET6

AUTHOR
   Michael Robinton <[email protected]>

COPYRIGHT 2011-2014
   Michael Robinton <[email protected]>

   All rights reserved.

   This program is free software; you can redistribute it and/or modify it
   under the terms of either:

     a) the GNU General Public License as published by the Free
     Software Foundation; either version 2, or (at your option) any
     later version, or

     b) the "Artistic License" which comes with this distribution.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU
   General Public License or the Artistic License for more details.

   You should have received a copy of the Artistic License with this
   distribution, in the file named "Artistic". If not, I'll be glad to
   provide one.

   You should also have received a copy of the GNU General Public License
   along with this program in the file named "Copying". If not, write to
   the

           Free Software Foundation, Inc.
           59 Temple Place, Suite 330
           Boston, MA  02111-1307, USA

   or visit their web page on the internet at:

           http://www.gnu.org/copyleft/gpl.html.

See also:
   Net::DNS::Codes(3), Net::DNS::ToolKit(3),
   Net::DNS::ToolKit::Utilities(3), NetAddr::IP::Util(3)