home *** CD-ROM | disk | FTP | other *** search
- package Net::DNS;
- #
- # $Id: DNS.pm,v 2.107 2004/02/21 12:44:18 ctriv Exp $
- #
- use strict;
- use vars qw(
- $HAVE_XS
- $VERSION
- $DNSSEC
- @ISA
- @EXPORT
- %typesbyname
- %typesbyval
- %qtypesbyname
- %qtypesbyval
- %metatypesbyname
- %metatypesbyval
- %classesbyname
- %classesbyval
- %opcodesbyname
- %opcodesbyval
- %rcodesbyname
- %rcodesbyval
- );
-
-
-
- BEGIN {
- require DynaLoader;
- require Exporter;
-
- @ISA = qw(Exporter DynaLoader);
- $VERSION = '0.46';
- $HAVE_XS = eval { __PACKAGE__->bootstrap(); 1 } ? 1 : 0;
- }
-
- use Net::DNS::Resolver;
- use Net::DNS::Packet;
- use Net::DNS::Update;
- use Net::DNS::Header;
- use Net::DNS::Question;
- use Net::DNS::RR;
-
- BEGIN {
- $DNSSEC = eval { require Net::DNS::RR::SIG; 1 } ? 1 : 0;
- }
-
-
-
- @EXPORT = qw(mx yxrrset nxrrset yxdomain nxdomain rr_add rr_del);
-
- #
- # If you implement an RR record make sure you also add it to
- # %Net::DNS::RR::RR hash otherwise it will be treated as unknown type.
- #
-
- # Do not use these tybesby hashes directly. Use the interface
- # functions, see below.
-
- %typesbyname = (
- 'SIGZERO' => 0, # RFC2931 consider this a pseudo type
- 'A' => 1, # RFC 1035, Section 3.4.1
- 'NS' => 2, # RFC 1035, Section 3.3.11
- 'MD' => 3, # RFC 1035, Section 3.3.4 (obsolete)
- 'MF' => 4, # RFC 1035, Section 3.3.5 (obsolete)
- 'CNAME' => 5, # RFC 1035, Section 3.3.1
- 'SOA' => 6, # RFC 1035, Section 3.3.13
- 'MB' => 7, # RFC 1035, Section 3.3.3
- 'MG' => 8, # RFC 1035, Section 3.3.6
- 'MR' => 9, # RFC 1035, Section 3.3.8
- 'NULL' => 10, # RFC 1035, Section 3.3.10
- 'WKS' => 11, # RFC 1035, Section 3.4.2 (deprecated)
- 'PTR' => 12, # RFC 1035, Section 3.3.12
- 'HINFO' => 13, # RFC 1035, Section 3.3.2
- 'MINFO' => 14, # RFC 1035, Section 3.3.7
- 'MX' => 15, # RFC 1035, Section 3.3.9
- 'TXT' => 16, # RFC 1035, Section 3.3.14
- 'RP' => 17, # RFC 1183, Section 2.2
- 'AFSDB' => 18, # RFC 1183, Section 1
- 'X25' => 19, # RFC 1183, Section 3.1
- 'ISDN' => 20, # RFC 1183, Section 3.2
- 'RT' => 21, # RFC 1183, Section 3.3
- 'NSAP' => 22, # RFC 1706, Section 5
- 'NSAP_PTR' => 23, # RFC 1348 (obsolete)
- # The following 2 RRs are impemented in Net::DNS::SEC
- 'SIG' => 24, # RFC 2535, Section 4.1
- 'KEY' => 25, # RFC 2535, Section 3.1
- 'PX' => 26, # RFC 2163,
- 'GPOS' => 27, # RFC 1712 (obsolete)
- 'AAAA' => 28, # RFC 1886, Section 2.1
- 'LOC' => 29, # RFC 1876
- # The following RR is impemented in Net::DNS::SEC
- 'NXT' => 30, # RFC 2535, Section 5.2
- 'EID' => 31, # draft-ietf-nimrod-dns-xx.txt
- 'NIMLOC' => 32, # draft-ietf-nimrod-dns-xx.txt
- 'SRV' => 33, # RFC 2052
- 'ATMA' => 34, # ???
- 'NAPTR' => 35, # RFC 2168
- 'KX' => 36, # RFC 2230
- 'CERT' => 37, # RFC 2538
- 'DNAME' => 39, # RFC 2672
- 'OPT' => 41, # RFC 2671
- # The following 4 RRs are impemented in Net::DNS::SEC
- # Aug 2003: These RRs will be published as RFCs shortly
- 'DS' => 43, # draft-ietf-dnsext-delegation-signer
- 'RRSIG' => 46, # draft-ietf-dnsext-dnssec-2535typecode-change
- 'NSEC' => 47, # draft-ietf-dnsext-dnssec-2535typecode-change
- 'DNSKEY' => 48, # draft-ietf-dnsext-dnssec-2535typecode-change
- 'UINFO' => 100, # non-standard
- 'UID' => 101, # non-standard
- 'GID' => 102, # non-standard
- 'UNSPEC' => 103, # non-standard
- 'TKEY' => 249, # RFC 2930
- 'TSIG' => 250, # RFC 2931
- 'IXFR' => 251, # RFC 1995
- 'AXFR' => 252, # RFC 1035
- 'MAILB' => 253, # RFC 1035 (MB, MG, MR)
- 'MAILA' => 254, # RFC 1035 (obsolete - see MX)
- 'ANY' => 255, # RFC 1035
- );
- %typesbyval = reverse %typesbyname;
-
-
- #
- # typesbyval and typesbyname functions are wrappers around the similarly named
- # hashes. They are used for 'unknown' DNS RR types (RFC3597)
-
- # typesbyname returns they TYPEcode as a function of the TYPE
- # mnemonic. If the TYPE mapping is not specified the generic mnemonic
- # TYPE### is returned.
-
-
- # typesbyval returns they TYPE mnemonic as a function of the TYPE
- # code. If the TYPE mapping is not specified the generic mnemonic
- # TYPE### is returned.
- #
-
- sub typesbyname {
- my $name = uc shift;
-
- return $typesbyname{$name} if $typesbyname{$name};
-
- die "Net::DNS::typesbyval() argument is not TYPE### ($name)" unless
- $name =~ m/^\s*TYPE(\d+)\s*$/;
-
- my $val = $1;
-
- die 'Net::DNS::typesbyval() argument larger than ' . 0xffff if $val > 0xffff;
-
- return $val;
- }
-
-
-
- sub typesbyval {
- my $val = shift;
-
- die "Net::DNS::typesbyname() argument is not numeric ($val)" unless
- $val =~ m/^\s*\d+\s*$/;
-
- $val =~ s/\s*//g;
- $val =~ s/^0*//;
-
- return $typesbyval{$val} if $typesbyval{$val};
-
- die 'Net::DNS::typesbyname() argument larger than '. 0xffff if
- $val > 0xffff;
-
- return "TYPE$val";
- }
-
-
-
- #
- # Do not use these classesby hashes directly. See below.
- #
-
- %classesbyname = (
- 'IN' => 1, # RFC 1035
- 'CH' => 3, # RFC 1035
- 'HS' => 4, # RFC 1035
- 'NONE' => 254, # RFC 2136
- 'ANY' => 255, # RFC 1035
- );
- %classesbyval = reverse %classesbyname;
-
-
-
- # classesbyval and classesbyname functions are wrappers around the
- # similarly named hashes. They are used for 'unknown' DNS RR classess
- # (RFC3597)
-
- # See typesbyval and typesbyname, these beasts have the same functionality
-
- sub classesbyname {
- my $name = uc shift;
- return $classesbyname{$name} if $classesbyname{$name};
-
- die "Net::DNS::classesbyval() argument is not CLASS### ($name)" unless
- $name =~ m/^\s*CLASS(\d+)\s*$/;
-
- my $val = $1;
-
- die 'Net::DNS::classesbyval() argument larger than '. 0xffff if $val > 0xffff;
-
- return $val;
- }
-
-
-
- sub classesbyval {
- my $val = shift;
-
- die "Net::DNS::classesbyname() argument is not numeric ($val)" unless
- $val=~/^\s*\d+\s*$/;
-
- $val =~ s/\s*//g;
- $val =~ s/^0*//;
-
- return $classesbyval{$val} if $classesbyval{$val};
-
- die 'Net::DNS::classesbyname() argument larger than ' . 0xffff if $val > 0xffff;
-
- return "CLASS$val";
- }
-
-
-
- # The qtypesbyval and metatypesbyval specify special typecodes
- # See rfc2929 and the relevant IANA registry
- # http://www.iana.org/assignments/dns-parameters
-
-
- %qtypesbyname = (
- 'IXFR' => 251, # incremental transfer [RFC1995]
- 'AXFR' => 252, # transfer of an entire zone [RFC1035]
- 'MAILB' => 253, # mailbox-related RRs (MB, MG or MR) [RFC1035]
- 'MAILA' => 254, # mail agent RRs (Obsolete - see MX) [RFC1035]
- 'ANY' => 255, # all records [RFC1035]
- );
- %qtypesbyval = reverse %qtypesbyname;
-
-
- %metatypesbyname = (
- 'TKEY' => 249, # Transaction Key [RFC2930]
- 'TSIG' => 250, # Transaction Signature [RFC2845]
- 'OPT' => 41, # RFC 2671
- );
- %metatypesbyval = reverse %metatypesbyname;
-
-
- %opcodesbyname = (
- 'QUERY' => 0, # RFC 1035
- 'IQUERY' => 1, # RFC 1035
- 'STATUS' => 2, # RFC 1035
- 'NS_NOTIFY_OP' => 4, # RFC 1996
- 'UPDATE' => 5, # RFC 2136
- );
- %opcodesbyval = reverse %opcodesbyname;
-
-
- %rcodesbyname = (
- 'NOERROR' => 0, # RFC 1035
- 'FORMERR' => 1, # RFC 1035
- 'SERVFAIL' => 2, # RFC 1035
- 'NXDOMAIN' => 3, # RFC 1035
- 'NOTIMP' => 4, # RFC 1035
- 'REFUSED' => 5, # RFC 1035
- 'YXDOMAIN' => 6, # RFC 2136
- 'YXRRSET' => 7, # RFC 2136
- 'NXRRSET' => 8, # RFC 2136
- 'NOTAUTH' => 9, # RFC 2136
- 'NOTZONE' => 10, # RFC 2136
- );
- %rcodesbyval = reverse %rcodesbyname;
-
-
- sub version { $VERSION; }
- sub PACKETSZ () { 512; }
- sub HFIXEDSZ () { 12; }
- sub QFIXEDSZ () { 4; }
- sub RRFIXEDSZ () { 10; }
- sub INT32SZ () { 4; }
- sub INT16SZ () { 2; }
-
-
-
- # mx()
- #
- # Usage:
- # my @mxes = mx('example.com', 'IN');
- #
- sub mx {
- my $res = ref $_[0] ? shift : Net::DNS::Resolver->new;
-
- my ($name, $class) = @_;
- $class ||= 'IN';
-
- my $ans = $res->query($name, 'MX', $class) || return;
-
- # This construct is best read backwords.
- #
- # First we take the answer secion of the packet.
- # Then we take just the MX records from that list
- # Then we sort the list by preference
- # Then we return it.
- # We do this into an array to force list context.
- my @ret = sort { $a->preference <=> $b->preference }
- grep { $_->type eq 'MX'} $ans->answer;
-
-
- return @ret;
- }
-
- sub yxrrset {
- return Net::DNS::RR->new_from_string(shift, 'yxrrset');
- }
-
- sub nxrrset {
- return Net::DNS::RR->new_from_string(shift, 'nxrrset');
- }
-
- sub yxdomain {
- return Net::DNS::RR->new_from_string(shift, 'yxdomain');
- }
-
- sub nxdomain {
- return Net::DNS::RR->new_from_string(shift, 'nxdomain');
- }
-
- sub rr_add {
- return Net::DNS::RR->new_from_string(shift, 'rr_add');
- }
-
- sub rr_del {
- return Net::DNS::RR->new_from_string(shift, 'rr_del');
- }
-
- 1;
- __END__
-
- =head1 NAME
-
- Net::DNS - Perl interface to the DNS resolver
-
- =head1 SYNOPSIS
-
- C<use Net::DNS;>
-
- =head1 DESCRIPTION
-
- Net::DNS is a collection of Perl modules that act as a Domain
- Name System (DNS) resolver. It allows the programmer to perform
- DNS queries that are beyond the capabilities of C<gethostbyname>
- and C<gethostbyaddr>.
-
- The programmer should be somewhat familiar with the format of
- a DNS packet and its various sections. See RFC 1035 or
- I<DNS and BIND> (Albitz & Liu) for details.
-
- =head2 Resolver Objects
-
- A resolver object is an instance of the
- L<Net::DNS::Resolver|Net::DNS::Resolver> class. A program can have
- multiple resolver objects, each maintaining its own state information
- such as the nameservers to be queried, whether recursion is desired,
- etc.
-
- =head2 Packet Objects
-
- L<Net::DNS::Resolver|Net::DNS::Resolver> queries return
- L<Net::DNS::Packet|Net::DNS::Packet> objects. Packet objects have five
- sections:
-
- =over 3
-
- =item *
-
- The header section, a L<Net::DNS::Header|Net::DNS::Header> object.
-
- =item *
-
- The question section, a list of L<Net::DNS::Question|Net::DNS::Question>
- objects.
-
- =item *
-
- The answer section, a list of L<Net::DNS::RR|Net::DNS::RR> objects.
-
- =item *
-
- The authority section, a list of L<Net::DNS::RR|Net::DNS::RR> objects.
-
- =item *
-
- The additional section, a list of L<Net::DNS::RR|Net::DNS::RR> objects.
-
- =back
-
- =head2 Update Objects
-
- The L<Net::DNS::Update|Net::DNS::Update> package is a subclass of
- L<Net::DNS::Packet|Net::DNS::Packet> for creating packet objects to be
- used in dynamic updates.
-
- =head2 Header Objects
-
- L<Net::DNS::Header|Net::DNS::Header> objects represent the header
- section of a DNS packet.
-
- =head2 Question Objects
-
- L<Net::DNS::Question|Net::DNS::Question> objects represent the question
- section of a DNS packet.
-
- =head2 RR Objects
-
- L<Net::DNS::RR|Net::DNS::RR> is the base class for DNS resource record
- (RR) objects in the answer, authority, and additional sections of a DNS
- packet.
-
- Don't assume that RR objects will be of the type you requested -- always
- check an RR object's type before calling any of its methods.
-
- =head1 METHODS
-
- See the manual pages listed above for other class-specific methods.
-
- =head2 version
-
- print Net::DNS->version, "\n";
-
- Returns the version of Net::DNS.
-
- =head2 mx
-
- # Use a default resolver -- can't get an error string this way.
- use Net::DNS;
- my @mx = mx("example.com");
-
- # Use your own resolver object.
- use Net::DNS;
- my $res = Net::DNS::Resolver->new;
- my @mx = mx($res, "example.com");
-
- Returns a list of L<Net::DNS::RR::MX|Net::DNS::RR::MX> objects
- representing the MX records for the specified name; the list will be
- sorted by preference. Returns an empty list if the query failed or no MX
- records were found.
-
- This method does not look up A records -- it only performs MX queries.
-
- See L</EXAMPLES> for a more complete example.
-
- =head2 yxrrset
-
- Use this method to add an "RRset exists" prerequisite to a dynamic
- update packet. There are two forms, value-independent and
- value-dependent:
-
- # RRset exists (value-independent)
- $update->push(pre => yxrrset("host.example.com A"));
-
- Meaning: At least one RR with the specified name and type must
- exist.
-
- # RRset exists (value-dependent)
- $packet->push(pre => yxrrset("host.example.com A 10.1.2.3"));
-
- Meaning: At least one RR with the specified name and type must
- exist and must have matching data.
-
- Returns a C<Net::DNS::RR> object or C<undef> if the object couldn't
- be created.
-
- =head2 nxrrset
-
- Use this method to add an "RRset does not exist" prerequisite to
- a dynamic update packet.
-
- $packet->push(pre => nxrrset("host.example.com A"));
-
- Meaning: No RRs with the specified name and type can exist.
-
- Returns a C<Net::DNS::RR> object or C<undef> if the object couldn't
- be created.
-
- =head2 yxdomain
-
- Use this method to add a "name is in use" prerequisite to a dynamic
- update packet.
-
- $packet->push(pre => yxdomain("host.example.com"));
-
- Meaning: At least one RR with the specified name must exist.
-
- Returns a C<Net::DNS::RR> object or C<undef> if the object couldn't
- be created.
-
- =head2 nxdomain
-
- Use this method to add a "name is not in use" prerequisite to a
- dynamic update packet.
-
- $packet->push(pre => nxdomain("host.example.com"));
-
- Meaning: No RR with the specified name can exist.
-
- Returns a C<Net::DNS::RR> object or C<undef> if the object couldn't
- be created.
-
- =head2 rr_add
-
- Use this method to add RRs to a zone.
-
- $packet->push(update => rr_add("host.example.com A 10.1.2.3"));
-
- Meaning: Add this RR to the zone.
-
- RR objects created by this method should be added to the "update"
- section of a dynamic update packet. The TTL defaults to 86400
- seconds (24 hours) if not specified.
-
- Returns a C<Net::DNS::RR> object or C<undef> if the object couldn't
- be created.
-
- =head2 rr_del
-
- Use this method to delete RRs from a zone. There are three forms:
- delete an RRset, delete all RRsets, and delete an RR.
-
- # Delete an RRset.
- $packet->push(update => rr_del("host.example.com A"));
-
- Meaning: Delete all RRs having the specified name and type.
-
- # Delete all RRsets.
- $packet->push(update => rr_del("host.example.com"));
-
- Meaning: Delete all RRs having the specified name.
-
- # Delete an RR.
- $packet->push(update => rr_del("host.example.com A 10.1.2.3"));
-
- Meaning: Delete all RRs having the specified name, type, and data.
-
- RR objects created by this method should be added to the "update"
- section of a dynamic update packet.
-
- Returns a C<Net::DNS::RR> object or C<undef> if the object couldn't
- be created.
-
- =head1 EXAMPLES
-
- The following examples show how to use the C<Net::DNS> modules.
- See the other manual pages and the demo scripts included with the
- source code for additional examples.
-
- See the C<Net::DNS::Update> manual page for an example of performing
- dynamic updates.
-
- =head2 Look up a host's addresses.
-
- use Net::DNS;
- my $res = Net::DNS::Resolver->new;
- my $query = $res->search("host.example.com");
-
- if ($query) {
- foreach my $rr ($query->answer) {
- next unless $rr->type eq "A";
- print $rr->address, "\n";
- }
- } else {
- warn "query failed: ", $res->errorstring, "\n";
- }
-
- =head2 Find the nameservers for a domain.
-
- use Net::DNS;
- my $res = Net::DNS::Resolver->new;
- my $query = $res->query("example.com", "NS");
-
- if ($query) {
- foreach $rr (grep { $_->type eq 'NS' } $query->answer) {
- print $rr->nsdname, "\n";
- }
- }
- else {
- warn "query failed: ", $res->errorstring, "\n";
- }
-
- =head2 Find the MX records for a domain.
-
- use Net::DNS;
- my $name = "example.com";
- my $res = Net::DNS::Resolver->new;
- my @mx = mx($res, $name);
-
- if (@mx) {
- foreach $rr (@mx) {
- print $rr->preference, " ", $rr->exchange, "\n";
- }
- } else {
- warn "Can't find MX records for $name: ", $res->errorstring, "\n";
- }
-
-
- =head2 Print a domain's SOA record in zone file format.
-
- use Net::DNS;
- my $res = Net::DNS::Resolver->new;
- my $query = $res->query("example.com", "SOA");
-
- if ($query) {
- ($query->answer)[0]->print;
- } else {
- print "query failed: ", $res->errorstring, "\n";
- }
-
- =head2 Perform a zone transfer and print all the records.
-
- use Net::DNS;
- my $res = Net::DNS::Resolver->new;
- $res->nameservers("ns.example.com");
-
- my @zone = $res->axfr("example.com");
-
- foreach $rr (@zone) {
- $rr->print;
- }
-
- =head2 Perform a background query and do some other work while waiting
- for the answer.
-
- use Net::DNS;
- my $res = Net::DNS::Resolver->new;
- my $socket = $res->bgsend("host.example.com");
-
- until ($res->bgisready($socket)) {
- # do some work here while waiting for the answer
- # ...and some more here
- }
-
- my $packet = $res->bgread($socket);
- $packet->print;
-
-
- =head2 Send a background query and use select to determine when the answer
- has arrived.
-
- use Net::DNS;
- use IO::Select;
-
- my $timeout = 5;
- my $res = Net::DNS::Resolver->new;
- my $bgsock = $res->bgsend("host.example.com");
- my $sel = IO::Select->new($bgsock);
-
- # Add more sockets to $sel if desired.
- my @ready = $sel->can_read($timeout);
- if (@ready) {
- foreach my $sock (@ready) {
- if ($sock == $bgsock) {
- my $packet = $res->bgread($bgsock);
- $packet->print;
- $bgsock = undef;
- }
- # Check for the other sockets.
- $sel->remove($sock);
- $sock = undef;
- }
- } else {
- warn "timed out after $timeout seconds\n";
- }
-
- =head1 BUGS
-
- C<Net::DNS> is slow.
-
- For other items to be fixed, please see the TODO file included with
- the source distribution.
-
- =head1 COPYRIGHT
-
- Copyright (c) 1997-2002 Michael Fuhr.
-
- Portions Copyright (c) 2002-2003 Chris Reinhardt.
-
- All rights reserved. This program is free software; you may redistribute
- it and/or modify it under the same terms as Perl itself.
-
- =head1 AUTHOR INFORMATION
-
- Net::DNS is currently maintained by a group, led by:
- Chris Reinhardt
- ctriv@net-dns.org
-
- Net::DNS was created by:
- Michael Fuhr
- mike@fuhr.org
-
- For more information see:
- http://www.net-dns.org/
-
- =head1 SEE ALSO
-
- L<perl(1)>, L<Net::DNS::Resolver>, L<Net::DNS::Packet>, L<Net::DNS::Update>,
- L<Net::DNS::Header>, L<Net::DNS::Question>, L<Net::DNS::RR>, RFC 1035,
- I<DNS and BIND> by Paul Albitz & Cricket Liu
-
- =cut
-