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   5747388 use strict;
  84         1008  
  84         2475  
4 84     84   468 use warnings;
  84         204  
  84         7032  
5              
6             our $VERSION;
7             $VERSION = '1.40';
8             $VERSION = eval {$VERSION};
9             our $SVNVERSION = (qw$Id: DNS.pm 1936 2023-08-30 18:05:44Z 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   45273 use integer;
  84         1231  
  84         471  
33              
34 84     84   3143 use base qw(Exporter);
  84         174  
  84         100106  
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 136740 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 1183 my @arg = @_;
60 7 100       46 my $res = ( ref( $arg[0] ) ? shift @arg : Net::DNS::Resolver->new() );
61              
62 7         36 my $reply = $res->query(@arg);
63 7 100       55 my @list = $reply ? $reply->answer : ();
64 7         118 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 974 my @arg = @_;
77 4 100       21 my @res = ( ref( $arg[0] ) ? shift @arg : () );
78 4         11 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         15 my @list = sort { $a->preference <=> $b->preference }
89 4         15 grep { $_->type eq 'MX' } &rr( @res, $name, 'MX', @class );
  6         39  
90 4         49 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 2789 my @arg = @_;
102 12         26 my $rrtype = uc shift @arg;
103 12         26 my ( $attribute, @rr ) = @arg; ## NB: attribute is optional
104 12 100       51 ( @rr, $attribute ) = @arg if ref($attribute) =~ /^Net::DNS::RR/;
105              
106 12         24 my @extracted = grep { $_->type eq $rrtype } @rr;
  89         184  
107 12 100       33 return @extracted unless scalar @extracted;
108 10         52 my $func = "Net::DNS::RR::$rrtype"->get_rrsort_func($attribute);
109 10         47 my @sorted = sort $func @extracted;
110 10         50 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 21 sub SEQUENTIAL { return (undef) }
123              
124 1     1 1 13 sub UNIXTIME { return CORE::time; }
125              
126             sub YYYYMMDDxx {
127 2     2 1 83 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 1492 my @arg = @_;
138 5         24 my $rr = Net::DNS::RR->new(@arg);
139 5         17 $rr->ttl(0);
140 5 100       16 $rr->class('ANY') unless $rr->rdata;
141 5         21 return $rr;
142             }
143              
144             sub nxrrset {
145 2     2 1 663 my @arg = @_;
146 2         8 my $rr = Net::DNS::RR->new(@arg);
147 2         7 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 813 my @arg = @_;
156 2         7 my ( $domain, @etc ) = map {split} @arg;
  3         10  
157 2 100       13 my $rr = Net::DNS::RR->new( scalar(@etc) ? @arg : ( name => $domain ) );
158 2         11 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 849 my @arg = @_;
167 2         7 my ( $domain, @etc ) = map {split} @arg;
  3         11  
168 2 100       23 my $rr = Net::DNS::RR->new( scalar(@etc) ? @arg : ( name => $domain ) );
169 2         20 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 1064 my @arg = @_;
178 4         17 my $rr = Net::DNS::RR->new(@arg);
179 4 100       17 $rr->{ttl} = 86400 unless defined $rr->{ttl};
180 4         51 return $rr;
181             }
182              
183             sub rr_del {
184 3     3 1 1446 my @arg = @_;
185 3         11 my ( $domain, @etc ) = map {split} @arg;
  3         16  
186 3 100       18 my $rr = Net::DNS::RR->new( scalar(@etc) ? @arg : ( name => $domain, type => 'ANY' ) );
187 3 100       24 $rr->class( $rr->rdata ? 'NONE' : 'ANY' );
188 3         42 $rr->ttl(0);
189 3         12 return $rr;
190             }
191              
192              
193             1;
194             __END__