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   5665296 use strict;
  84         912  
  84         2430  
4 84     84   436 use warnings;
  84         163  
  84         6925  
5              
6             our $VERSION;
7             $VERSION = '1.39_01';
8             $VERSION = eval {$VERSION};
9             our $SVNVERSION = (qw$Id: DNS.pm 1932 2023-08-23 13:15:34Z 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   44954 use integer;
  84         1215  
  84         401  
33              
34 84     84   2951 use base qw(Exporter);
  84         166  
  84         98361  
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 128084 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 1294 my @arg = @_;
60 7 100       47 my $res = ( ref( $arg[0] ) ? shift @arg : Net::DNS::Resolver->new() );
61              
62 7         34 my $reply = $res->query(@arg);
63 7 100       60 my @list = $reply ? $reply->answer : ();
64 7         127 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 1130 my @arg = @_;
77 4 100       21 my @res = ( ref( $arg[0] ) ? shift @arg : () );
78 4         14 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         17 my @list = sort { $a->preference <=> $b->preference }
89 4         17 grep { $_->type eq 'MX' } &rr( @res, $name, 'MX', @class );
  6         41  
90 4         55 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 2264 my @arg = @_;
102 12         24 my $rrtype = uc shift @arg;
103 12         26 my ( $attribute, @rr ) = @arg; ## NB: attribute is optional
104 12 100       43 ( @rr, $attribute ) = @arg if ref($attribute) =~ /^Net::DNS::RR/;
105              
106 12         20 my @extracted = grep { $_->type eq $rrtype } @rr;
  89         195  
107 12 100       33 return @extracted unless scalar @extracted;
108 10         52 my $func = "Net::DNS::RR::$rrtype"->get_rrsort_func($attribute);
109 10         46 my @sorted = sort $func @extracted;
110 10         45 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 23 sub SEQUENTIAL { return (undef) }
123              
124 1     1 1 7 sub UNIXTIME { return CORE::time; }
125              
126             sub YYYYMMDDxx {
127 2     2 1 99 my ( $dd, $mm, $yy ) = (localtime)[3 .. 5];
128 2         23 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 1146 my @arg = @_;
138 5         24 my $rr = Net::DNS::RR->new(@arg);
139 5         18 $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 543 my @arg = @_;
146 2         8 my $rr = Net::DNS::RR->new(@arg);
147 2         8 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 619 my @arg = @_;
156 2         6 my ( $domain, @etc ) = map {split} @arg;
  3         12  
157 2 100       11 my $rr = Net::DNS::RR->new( scalar(@etc) ? @arg : ( name => $domain ) );
158 2         10 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 574 my @arg = @_;
167 2         6 my ( $domain, @etc ) = map {split} @arg;
  3         12  
168 2 100       12 my $rr = Net::DNS::RR->new( scalar(@etc) ? @arg : ( name => $domain ) );
169 2         7 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 815 my @arg = @_;
178 4         16 my $rr = Net::DNS::RR->new(@arg);
179 4 100       16 $rr->{ttl} = 86400 unless defined $rr->{ttl};
180 4         13 return $rr;
181             }
182              
183             sub rr_del {
184 3     3 1 1125 my @arg = @_;
185 3         8 my ( $domain, @etc ) = map {split} @arg;
  3         17  
186 3 100       16 my $rr = Net::DNS::RR->new( scalar(@etc) ? @arg : ( name => $domain, type => 'ANY' ) );
187 3 100       10 $rr->class( $rr->rdata ? 'NONE' : 'ANY' );
188 3         8 $rr->ttl(0);
189 3         10 return $rr;
190             }
191              
192              
193             1;
194             __END__