File Coverage

blib/lib/Net/DNS.pm
Criterion Covered Total %
statement 68 68 100.0
branch 22 22 100.0
condition n/a
subroutine 17 17 100.0
pod 13 13 100.0
total 120 120 100.0


line stmt bran cond sub pod time code
1             package Net::DNS;
2              
3 86     86   11146116 use strict;
  86         189  
  86         4042  
4 86     86   473 use warnings;
  86         172  
  86         11728  
5              
6             our $VERSION;
7             $VERSION = '1.54';
8             $VERSION = eval {$VERSION};
9             our $SVNVERSION = (qw$Id: DNS.pm 2045 2026-01-16 12:30:12Z willem $)[2];
10              
11              
12             =head1 NAME
13              
14             Net::DNS - Perl Interface to the Domain Name System
15              
16             =head1 SYNOPSIS
17              
18             use Net::DNS;
19             my $resolver = Net::DNS::Resolver->new(...);
20             my $response = $resolver->send(...);
21              
22             =head1 DESCRIPTION
23              
24             Net::DNS is a collection of Perl modules that act as a Domain Name System
25             (DNS) resolver. It allows the programmer to perform DNS queries that are
26             beyond the capabilities of "gethostbyname" and "gethostbyaddr".
27              
28             The programmer should be familiar with the structure of a DNS packet
29             and the zone file presentation format described in RFC1035.
30              
31             =cut
32              
33              
34 86     86   52320 use integer;
  86         1547  
  86         450  
35              
36 86     86   4153 use base qw(Exporter);
  86         250  
  86         121391  
37             our @EXPORT = qw(SEQUENTIAL UNIXTIME YYYYMMDDxx
38             yxrrset nxrrset yxdomain nxdomain rr_add rr_del
39             mx rr rrsort);
40              
41              
42             local $SIG{__DIE__};
43             require Net::DNS::Resolver;
44             require Net::DNS::Packet;
45             require Net::DNS::RR;
46             require Net::DNS::Update;
47              
48              
49 1     1 1 163014 sub version { return $VERSION; }
50              
51              
52             #
53             # rr()
54             #
55             # Usage:
56             # @rr = rr('example.com');
57             # @rr = rr('example.com', 'A', 'IN');
58             # @rr = rr($res, 'example.com' ... );
59             #
60             sub rr {
61 7     7 1 1681 my @arg = @_;
62 7 100       76 my $res = ( ref( $arg[0] ) ? shift @arg : Net::DNS::Resolver->new() );
63              
64 7         46 my $reply = $res->query(@arg);
65 7 100       55 my @list = $reply ? $reply->answer : ();
66 7         176 return @list;
67             }
68              
69              
70             #
71             # mx()
72             #
73             # Usage:
74             # @mx = mx('example.com');
75             # @mx = mx($res, 'example.com');
76             #
77             sub mx {
78 4     4 1 1675 my @arg = @_;
79 4 100       26 my @res = ( ref( $arg[0] ) ? shift @arg : () );
80 4         10 my ( $name, @class ) = @arg;
81              
82             # This construct is best read backwards.
83             #
84             # First we take the answer section of the packet.
85             # Then we take just the MX records from that list
86             # Then we sort the list by preference
87             # We do this into an array to force list context.
88             # Then we return the list.
89              
90 3         21 my @list = sort { $a->preference <=> $b->preference }
91 4         21 grep { $_->type eq 'MX' } &rr( @res, $name, 'MX', @class );
  6         41  
92 4         69 return @list;
93             }
94              
95              
96             #
97             # rrsort()
98             #
99             # Usage:
100             # @prioritysorted = rrsort( "SRV", "priority", @rr_array );
101             #
102             sub rrsort {
103 12     12 1 3048 my @arg = @_;
104 12         30 my $rrtype = uc shift @arg;
105 12         32 my ( $attribute, @rr ) = @arg; ## NB: attribute is optional
106 12 100       65 ( @rr, $attribute ) = @arg if ref($attribute) =~ /^Net::DNS::RR/;
107              
108 12         27 my @extracted = grep { $_->type eq $rrtype } @rr;
  89         186  
109 12 100       36 return @extracted unless scalar @extracted;
110 10         56 my $func = "Net::DNS::RR::$rrtype"->get_rrsort_func($attribute);
111 10         43 my @sorted = sort $func @extracted;
112 10         79 return @sorted;
113             }
114              
115              
116             #
117             # Auxiliary functions to support policy-driven zone serial numbering.
118             #
119             # $successor = $soa->serial(SEQUENTIAL);
120             # $successor = $soa->serial(UNIXTIME);
121             # $successor = $soa->serial(YYYYMMDDxx);
122             #
123              
124 3     3 1 20 sub SEQUENTIAL { return (undef) }
125              
126 1     1 1 10 sub UNIXTIME { return CORE::time; }
127              
128             sub YYYYMMDDxx {
129 2     2 1 107 my ( $dd, $mm, $yy ) = (localtime)[3 .. 5];
130 2         23 return 1900010000 + sprintf '%d%0.2d%0.2d00', $yy, $mm, $dd;
131             }
132              
133              
134             #
135             # Auxiliary functions to support dynamic update.
136             #
137              
138             sub yxrrset {
139 5     5 1 1894 my @arg = @_;
140 5         29 my $rr = Net::DNS::RR->new(@arg);
141 5         22 $rr->ttl(0);
142 5 100       21 $rr->class('ANY') unless $rr->rdata;
143 5         29 return $rr;
144             }
145              
146             sub nxrrset {
147 2     2 1 945 my @arg = @_;
148 2         10 my $rr = Net::DNS::RR->new(@arg);
149 2         11 return Net::DNS::RR->new(
150             name => $rr->name,
151             type => $rr->type,
152             class => 'NONE'
153             );
154             }
155              
156             sub yxdomain {
157 2     2 1 865 my @arg = @_;
158 2         6 my ( $domain, @etc ) = map {split} @arg;
  3         12  
159 2 100       20 my $rr = Net::DNS::RR->new( scalar(@etc) ? @arg : ( name => $domain ) );
160 2         11 return Net::DNS::RR->new(
161             name => $rr->name,
162             type => 'ANY',
163             class => 'ANY'
164             );
165             }
166              
167             sub nxdomain {
168 2     2 1 821 my @arg = @_;
169 2         5 my ( $domain, @etc ) = map {split} @arg;
  3         12  
170 2 100       33 my $rr = Net::DNS::RR->new( scalar(@etc) ? @arg : ( name => $domain ) );
171 2         8 return Net::DNS::RR->new(
172             name => $rr->name,
173             type => 'ANY',
174             class => 'NONE'
175             );
176             }
177              
178             sub rr_add {
179 4     4 1 1434 my @arg = @_;
180 4         19 my $rr = Net::DNS::RR->new(@arg);
181 4 100       20 $rr->{ttl} = 86400 unless defined $rr->{ttl};
182 4         17 return $rr;
183             }
184              
185             sub rr_del {
186 3     3 1 1825 my @arg = @_;
187 3         9 my ( $domain, @etc ) = map {split} @arg;
  3         18  
188 3 100       21 my $rr = Net::DNS::RR->new( scalar(@etc) ? @arg : ( name => $domain, type => 'ANY' ) );
189 3 100       14 $rr->class( $rr->rdata ? 'NONE' : 'ANY' );
190 3         12 $rr->ttl(0);
191 3         14 return $rr;
192             }
193              
194              
195             1;
196             __END__