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