| 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__ |