File Coverage

blib/lib/Net/DNS/Resolver/Base.pm
Criterion Covered Total %
statement 612 612 100.0
branch 264 264 100.0
condition 80 80 100.0
subroutine 84 84 100.0
pod 24 29 100.0
total 1064 1069 100.0


line stmt bran cond sub pod time code
1             package Net::DNS::Resolver::Base;
2              
3 90     90   759 use strict;
  90         188  
  90         2552  
4 90     90   453 use warnings;
  90         186  
  90         5569  
5             our $VERSION = (qw$Id: Base.pm 1930 2023-08-21 14:10:10Z willem $)[2];
6              
7              
8             #
9             # Implementation notes wrt IPv6 support when using perl before 5.20.0.
10             #
11             # In general we try to be gracious to those stacks that do not have IPv6 support.
12             # The socket code is conditionally compiled depending upon the availability of
13             # the IO::Socket::IP package.
14             #
15             # We have chosen not to use mapped IPv4 addresses, there seem to be issues
16             # with this; as a result we use separate sockets for each family type.
17             #
18             # inet_pton is not available on WIN32, so we only use the getaddrinfo
19             # call to translate IP addresses to socketaddress.
20             #
21             # The configuration options force_v4, force_v6, prefer_v4 and prefer_v6
22             # are provided to control IPv6 behaviour for test purposes.
23             #
24             # Olaf Kolkman, RIPE NCC, December 2003.
25             # [Revised March 2016, June 2018]
26              
27              
28 90     90   588 use constant USE_SOCKET_IP => defined eval 'use IO::Socket::IP 0.38; 1;'; ## no critic
  90     90   267  
  90         7333  
  90         60335  
  90         3475173  
  90         627  
29             require IO::Socket::INET unless USE_SOCKET_IP;
30              
31 90     90   823 use constant IPv6 => USE_SOCKET_IP;
  90         208  
  90         6657  
32              
33              
34             # If SOCKSified Perl, use TCP instead of UDP and keep the socket open.
35 90     90   662 use constant SOCKS => scalar eval { require Config; $Config::Config{usesocks}; };
  90         203  
  90         223  
  90         400  
  90         18299  
36              
37              
38             # Allow taint tests to be optimised away when appropriate.
39 90     90   740 use constant TAINT => eval { ${^TAINT} };
  90         196  
  90         214  
  90         7591  
40 90     90   617 use constant TESTS => TAINT && defined eval { require Scalar::Util; };
  90         187  
  90         4351  
41              
42              
43 90     90   3933 use integer;
  90         264  
  90         816  
44 90     90   2745 use Carp;
  90         233  
  90         5690  
45 90     90   45562 use IO::File;
  90         173818  
  90         9982  
46 90     90   45843 use IO::Select;
  90         159687  
  90         4377  
47 90     90   790 use IO::Socket;
  90         213  
  90         625  
48 90     90   78502 use Socket;
  90         249  
  90         52438  
49              
50 90     90   50810 use Net::DNS::RR;
  90         293  
  90         3099  
51 90     90   49494 use Net::DNS::Packet;
  90         333  
  90         2961  
52              
53 90     90   678 use constant PACKETSZ => 512;
  90         226  
  90         310490  
54              
55              
56             #
57             # Set up a closure to be our class data.
58             #
59             {
60             my $defaults = bless {
61             nameservers => [qw(::1 127.0.0.1)],
62             nameserver4 => ['127.0.0.1'],
63             nameserver6 => ['::1'],
64             port => 53,
65             srcaddr4 => '0.0.0.0',
66             srcaddr6 => '::',
67             srcport => 0,
68             searchlist => [],
69             retrans => 5,
70             retry => 4,
71             usevc => ( SOCKS ? 1 : 0 ),
72             igntc => 0,
73             recurse => 1,
74             defnames => 1,
75             dnsrch => 1,
76             ndots => 1,
77             debug => 0,
78             tcp_timeout => 120,
79             udp_timeout => 30,
80             persistent_tcp => ( SOCKS ? 1 : 0 ),
81             persistent_udp => 0,
82             dnssec => 0,
83             adflag => 0, # see RFC6840, 5.7
84             cdflag => 0, # see RFC6840, 5.9
85             udppacketsize => 0, # value bounded below by PACKETSZ
86             force_v4 => ( IPv6 ? 0 : 1 ),
87             force_v6 => 0, # only relevant if IPv6 is supported
88             prefer_v4 => 0,
89             prefer_v6 => 0,
90             },
91             __PACKAGE__;
92              
93              
94 339     339   3667 sub _defaults { return $defaults; }
95             }
96              
97              
98             my %warned;
99              
100             sub _deprecate {
101 7     7   21 my ( undef, @note ) = @_;
102 7 100       578 carp join ' ', 'deprecated method;', "@note" unless $warned{"@note"}++;
103 7         226 return;
104             }
105              
106              
107             sub _untaint { ## no critic # recurses into user list arguments
108 10     10   190 return TAINT ? map { ref($_) ? [_untaint(@$_)] : do { /^(.*)$/; $1 } } @_ : @_;
109             }
110              
111              
112             # These are the attributes that the user may specify in the new() constructor.
113             my %public_attr = (
114             map { $_ => $_ } keys %{&_defaults},
115             qw(domain nameserver srcaddr),
116             map { $_ => 0 } qw(nameserver4 nameserver6 srcaddr4 srcaddr6),
117             );
118              
119              
120             my $initial;
121              
122             sub new {
123 91     91 1 59121 my ( $class, %args ) = @_;
124              
125 91         233 my $self;
126 91         395 my $base = $class->_defaults;
127 91         200 my $init = $initial;
128 91   100     573 $initial ||= [%$base];
129 91 100       471 if ( my $file = $args{config_file} ) {
    100          
130 4         61 my $conf = bless {@$initial}, $class;
131 4         26 $conf->_read_config_file($file); # user specified config
132 2         25 $self = bless {_untaint(%$conf)}, $class;
133 2 100       37 %$base = %$self unless $init; # define default configuration
134              
135             } elsif ($init) {
136 79         1493 $self = bless {%$base}, $class;
137              
138             } else {
139 8         88 $class->_init(); # define default configuration
140 8         125 $self = bless {%$base}, $class;
141             }
142              
143 89         600 while ( my ( $attr, $value ) = each %args ) {
144 75 100       317 next unless $public_attr{$attr};
145 73         216 my $ref = ref($value);
146 73 100 100     879 croak "usage: $class->new( $attr => [...] )"
147             if $ref && ( $ref ne 'ARRAY' );
148 69 100       604 $self->$attr( $ref ? @$value : $value );
149             }
150              
151 85         371 return $self;
152             }
153              
154              
155             my %resolv_conf = ( ## map traditional resolv.conf option names
156             attempts => 'retry',
157             inet6 => 'prefer_v6',
158             timeout => 'retrans',
159             );
160              
161             my %res_option = ( ## any resolver attribute plus those listed above
162             %public_attr,
163             %resolv_conf,
164             );
165              
166             sub _option {
167 10     10   28 my ( $self, $name, @value ) = @_;
168 10   100     66 my $attribute = $res_option{lc $name} || return;
169 7 100       19 push @value, 1 unless scalar @value;
170 7         63 return $self->$attribute(@value);
171             }
172              
173              
174             sub _read_env { ## read resolver config environment variables
175 8     8   26 my $self = shift;
176              
177 8 100       54 $self->searchlist( map {split} $ENV{LOCALDOMAIN} ) if defined $ENV{LOCALDOMAIN};
  1         7  
178              
179 8 100       36 $self->nameservers( map {split} $ENV{RES_NAMESERVERS} ) if defined $ENV{RES_NAMESERVERS};
  1         7  
180              
181 8 100       36 $self->searchlist( map {split} $ENV{RES_SEARCHLIST} ) if defined $ENV{RES_SEARCHLIST};
  1         5  
182              
183 8   100     68 foreach ( map {split} $ENV{RES_OPTIONS} || '' ) {
  8         55  
184 4         13 $self->_option( split m/:/ );
185             }
186 8         22 return;
187             }
188              
189              
190             sub _read_config_file { ## read resolver config file
191 19     19   69 my ( $self, $file ) = @_;
192              
193 19 100       159 my $filehandle = IO::File->new( $file, '<' ) or croak "$file: $!";
194              
195 17         2338 my @nameserver;
196             my @searchlist;
197              
198 17         73 local $_;
199 17         501 while (<$filehandle>) {
200 58         280 s/[;#].*$//; # strip comments
201              
202 58 100       201 /^nameserver/ && do {
203 10         65 my ( $keyword, @ip ) = grep {defined} split;
  22         77  
204 10         39 push @nameserver, @ip;
205 10         53 next;
206             };
207              
208 48 100       132 /^domain/ && do {
209 2         11 my ( $keyword, $domain ) = grep {defined} split;
  4         13  
210 2         16 $self->domain($domain);
211 2         11 next;
212             };
213              
214 46 100       132 /^search/ && do {
215 10         60 my ( $keyword, @domain ) = grep {defined} split;
  30         432  
216 10         230 push @searchlist, @domain;
217 10         110 next;
218             };
219              
220 36 100       136 /^option/ && do {
221 2         9 my ( $keyword, @option ) = grep {defined} split;
  8         17  
222 2         6 foreach (@option) {
223 6         22 $self->_option( split m/:/ );
224             }
225             };
226             }
227              
228 17         193 close($filehandle);
229              
230 17 100       147 $self->nameservers(@nameserver) if @nameserver;
231 17 100       128 $self->searchlist(@searchlist) if @searchlist;
232 17         132 return;
233             }
234              
235              
236             sub string {
237 2     2 1 5 my $self = shift;
238 2 100       8 $self = $self->_defaults unless ref($self);
239              
240 2         7 my @nslist = $self->nameservers();
241 2         12 my ($force) = ( grep( { $self->{$_} } qw(force_v6 force_v4) ), 'force_v4' );
  4         15  
242 2         6 my ($prefer) = ( grep( { $self->{$_} } qw(prefer_v6 prefer_v4) ), 'prefer_v4' );
  4         13  
243 2         13 return <
244             ;; RESOLVER state:
245             ;; nameservers = @nslist
246 2         51 ;; searchlist = @{$self->{searchlist}}
247             ;; defnames = $self->{defnames} dnsrch = $self->{dnsrch}
248             ;; igntc = $self->{igntc} usevc = $self->{usevc}
249             ;; recurse = $self->{recurse} port = $self->{port}
250             ;; retrans = $self->{retrans} retry = $self->{retry}
251             ;; tcp_timeout = $self->{tcp_timeout} persistent_tcp = $self->{persistent_tcp}
252             ;; udp_timeout = $self->{udp_timeout} persistent_udp = $self->{persistent_udp}
253             ;; ${prefer} = $self->{$prefer} ${force} = $self->{$force}
254             ;; debug = $self->{debug} ndots = $self->{ndots}
255             END
256             }
257              
258              
259             sub print {
260 1     1 1 191 return print shift->string;
261             }
262              
263              
264             sub searchlist {
265 181     181 1 2837 my ( $self, @domain ) = @_;
266 181 100       3722 $self = $self->_defaults unless ref($self);
267              
268 181         1634 foreach (@domain) { $_ = Net::DNS::Domain->new($_)->name }
  40         251  
269 181 100       1511 $self->{searchlist} = \@domain if scalar(@domain);
270 181         794 return @{$self->{searchlist}};
  181         1592  
271             }
272              
273             sub domain {
274 113     113 1 5981 return (&searchlist)[0];
275             }
276              
277              
278             sub nameservers {
279 294     294 1 3665 my ( $self, @ns ) = @_;
280 294 100       955 $self = $self->_defaults unless ref($self);
281              
282 294         561 my @ip;
283 294         804 foreach my $ns ( grep {defined} @ns ) {
  1332         2598  
284 1332 100 100     3218 if ( _ipv4($ns) || _ipv6($ns) ) {
285 1320         3602 push @ip, $ns;
286              
287             } else {
288 12         141 my $defres = ref($self)->new( debug => $self->{debug} );
289 12         47 $defres->{persistent} = $self->{persistent};
290              
291 12         34 my $names = {};
292 12         63 my $packet = $defres->send( $ns, 'A' );
293 12         161 my @iplist = _cname_addr( $packet, $names );
294              
295 12         35 if (IPv6) {
296 12         66 $packet = $defres->send( $ns, 'AAAA' );
297 12         141 push @iplist, _cname_addr( $packet, $names );
298             }
299              
300 12         47 my %unique = map { $_ => $_ } @iplist;
  21         96  
301              
302 12         64 my @address = values(%unique); # tainted
303 12 100       160 carp "unresolvable name: $ns" unless scalar @address;
304              
305 12         319 push @ip, @address;
306             }
307             }
308              
309 294 100 100     1443 if ( scalar(@ns) || !defined(wantarray) ) {
310 126         395 my @ipv4 = grep { _ipv4($_) } @ip;
  1341         2364  
311 126         468 my @ipv6 = grep { _ipv6($_) } @ip;
  1341         2483  
312 126         651 $self->{nameservers} = \@ip;
313 126         386 $self->{nameserver4} = \@ipv4;
314 126         417 $self->{nameserver6} = \@ipv6;
315             }
316              
317 294 100       1042 my @ns4 = $self->{force_v6} ? () : @{$self->{nameserver4}};
  291         968  
318 294 100       828 my @ns6 = $self->{force_v4} ? () : @{$self->{nameserver6}};
  290         877  
319              
320 294         580 my @nameservers = @{$self->{nameservers}};
  294         949  
321 294 100 100     1638 @nameservers = ( @ns4, @ns6 ) if $self->{prefer_v4} || !scalar(@ns6);
322 294 100 100     1340 @nameservers = ( @ns6, @ns4 ) if $self->{prefer_v6} || !scalar(@ns4);
323              
324 294 100       1806 return @nameservers if scalar @nameservers;
325              
326 18         40 my $error = 'no nameservers';
327 18 100       133 $error = 'IPv4 transport disabled' if scalar(@ns4) < scalar @{$self->{nameserver4}};
  18         59  
328 18 100       39 $error = 'IPv6 transport disabled' if scalar(@ns6) < scalar @{$self->{nameserver6}};
  18         63  
329 18         67 $self->errorstring($error);
330 18         55 return @nameservers;
331             }
332              
333 6     6 1 703 sub nameserver { return &nameservers; }
334              
335             sub _cname_addr {
336              
337             # TODO 20081217
338             # This code does not follow CNAME chains, it only looks inside the packet.
339             # Out of bailiwick will fail.
340 25     25   66 my @null;
341 25   100     106 my $packet = shift || return @null;
342 22         50 my $names = shift;
343              
344 22         95 $names->{lc( $_->qname )}++ foreach $packet->question;
345 22         103 $names->{lc( $_->cname )}++ foreach grep { $_->can('cname') } $packet->answer;
  23         264  
346              
347 22         87 my @addr = grep { $_->can('address') } $packet->answer;
  23         128  
348 22         81 return map { $_->address } grep { $names->{lc( $_->name )} } @addr;
  21         116  
  21         129  
349             }
350              
351              
352             sub replyfrom {
353 2     2 1 13 return shift->{replyfrom};
354             }
355              
356 1     1 0 13 sub answerfrom { return &replyfrom; } # uncoverable pod
357              
358              
359             sub _reset_errorstring {
360 131     131   408 shift->{errorstring} = '';
361 131         262 return;
362             }
363              
364             sub errorstring {
365 457     457 1 1628 my $self = shift;
366 457   100     2749 my $text = shift || return $self->{errorstring};
367 165         661 $self->_diag( 'errorstring:', $text );
368 165         1770 return $self->{errorstring} = $text;
369             }
370              
371              
372             sub query {
373 13     13 1 126 my ( $self, @argument ) = @_;
374              
375 13   100     71 my $name = shift(@argument) || '.';
376 13 100 100     207 my @sfix = $self->{defnames} && ( $name !~ m/[.:]/ ) ? $self->domain : ();
377              
378 13         63 my $fqdn = join '.', $name, @sfix;
379 13         79 $self->_diag( 'query(', $fqdn, @argument, ')' );
380 13   100     81 my $packet = $self->send( $fqdn, @argument ) || return;
381 10 100       64 return $packet->header->ancount ? $packet : undef;
382             }
383              
384              
385             sub search {
386 7     7 1 46 my ( $self, @argument ) = @_;
387              
388 7 100       28 return $self->query(@argument) unless $self->{dnsrch};
389              
390 6   100     32 my $name = shift(@argument) || '.';
391 6         18 my $dots = $name =~ tr/././;
392              
393 6 100       22 my @sfix = ( $dots < $self->{ndots} ) ? @{$self->{searchlist}} : ();
  1         5  
394 6 100       85 my ( $one, @more ) = ( $name =~ m/:|\.\d*$/ ) ? () : ( $dots ? ( undef, @sfix ) : @sfix );
    100          
395              
396 6         18 foreach my $suffix ( $one, @more ) {
397 7 100       19 my $fqname = $suffix ? join( '.', $name, $suffix ) : $name;
398 7         26 $self->_diag( 'search(', $fqname, @argument, ')' );
399 7   100     18 my $packet = $self->send( $fqname, @argument ) || next;
400 2 100       12 return $packet if $packet->header->ancount;
401             }
402              
403 5         35 return;
404             }
405              
406              
407             sub send {
408 115     115 1 562 my ( $self, @argument ) = @_;
409 115         473 my $packet = $self->_make_query_packet(@argument);
410 115         437 my $packet_data = $packet->data;
411              
412 115         594 $self->_reset_errorstring;
413              
414             return $self->_send_tcp( $packet, $packet_data )
415 115 100 100     662 if $self->{usevc} || length $packet_data > $self->_packetsz;
416              
417 108   100     426 my $reply = $self->_send_udp( $packet, $packet_data ) || return;
418              
419 88 100       735 return $reply if $self->{igntc};
420 84 100       643 return $reply unless $reply->header->tc;
421              
422 2         28 $self->_diag('packet truncated: retrying using TCP');
423 2         28 return $self->_send_tcp( $packet, $packet_data );
424             }
425              
426              
427             sub _send_tcp {
428 10     10   46 my ( $self, $query, $query_data ) = @_;
429              
430 10         55 my $tcp_packet = pack 'n a*', length($query_data), $query_data;
431 10         50 my @ns = $self->nameservers();
432 10         48 my $fallback;
433 10         39 my $timeout = $self->{tcp_timeout};
434              
435 10         39 foreach my $ip (@ns) {
436 14         103 $self->_diag( 'tcp send', "[$ip]" );
437              
438 14         74 my $socket = $self->_create_tcp_socket($ip);
439 14         93 $self->errorstring($!);
440 14   100     174 my $select = IO::Select->new( $socket || next );
441              
442 11         1080 $socket->send($tcp_packet);
443 11         1923 $self->errorstring($!);
444              
445 11         57 my $buffer = _read_tcp($socket);
446 11         55 $self->{replyfrom} = $ip;
447 11         100 $self->_diag( 'reply from', "[$ip]", length($buffer), 'bytes' );
448              
449 11         177 my $reply = Net::DNS::Packet->decode( \$buffer, $self->{debug} );
450 11         84 $self->errorstring($@);
451 11 100       59 next unless $self->_accept_reply( $reply, $query );
452 9         57 $reply->from($ip);
453              
454 9 100 100     74 if ( $self->{tsig_rr} && !$reply->verify($query) ) {
455 2         11 $self->errorstring( $reply->verifyerr );
456 2         310 next;
457             }
458              
459 7         48 my $rcode = $reply->header->rcode;
460 7 100       591 return $reply if $rcode eq 'NOERROR';
461 3 100       193 return $reply if $rcode eq 'NXDOMAIN';
462 2         309 $fallback = $reply;
463             }
464              
465 5 100       70 $self->{errorstring} = $fallback->header->rcode if $fallback;
466 5 100       37 $self->errorstring('query timed out') unless $self->{errorstring};
467 5         85 return $fallback;
468             }
469              
470              
471             sub _send_udp {
472 109     109   336 my ( $self, $query, $query_data ) = @_;
473              
474 109         348 my @ns = $self->nameservers;
475 109         340 my $port = $self->{port};
476 109   100     394 my $retrans = $self->{retrans} || 1;
477 109   100     347 my $retry = $self->{retry} || 1;
478 109         231 my $servers = scalar(@ns);
479 90 100   90   934 my $timeout = $servers ? do { no integer; $retrans / $servers } : 0;
  90         318  
  90         724  
  109         275  
  105         367  
480 109         210 my $fallback;
481              
482             # Perform each round of retries.
483 109         402 RETRY: for ( 1 .. $retry ) { # assumed to be a small number
484              
485             # Try each nameserver.
486 124         1097 my $select = IO::Select->new();
487              
488 124         1786 NAMESERVER: foreach my $ns (@ns) {
489              
490             # state vector replaces corresponding element of @ns array
491 202 100       593 unless ( ref $ns ) {
492 190         782 my $sockaddr = $self->_create_dst_sockaddr( $ns, $port );
493 190   100     711 my $socket = $self->_create_udp_socket($ns) || next;
494 93         392 $ns = [$socket, $ns, $sockaddr];
495             }
496              
497 105         408 my ( $socket, $ip, $sockaddr, $failed ) = @$ns;
498 105 100       365 next if $failed;
499              
500 93         617 $self->_diag( 'udp send', "[$ip]:$port" );
501              
502 93         557 $select->add($socket);
503 93         6314 $socket->send( $query_data, 0, $sockaddr );
504 93         16534 $self->errorstring( $$ns[3] = $! );
505              
506             # handle failure to detect taint inside socket->send()
507 93         152 die 'Insecure dependency while running with -T switch'
508             if TESTS && Scalar::Util::tainted($sockaddr);
509              
510 93         213 my $reply;
511 93         504 while ( my ($socket) = $select->can_read($timeout) ) {
512 93         6041339 my $peer = $self->{replyfrom} = $socket->peerhost;
513              
514 93         10169 my $buffer = _read_udp( $socket, $self->_packetsz );
515 93         990 $self->_diag( "reply from [$peer]", length($buffer), 'bytes' );
516              
517 93         1847 my $packet = Net::DNS::Packet->decode( \$buffer, $self->{debug} );
518 93         561 $self->errorstring($@);
519 93 100       515 next unless $self->_accept_reply( $packet, $query );
520 91         271 $reply = $packet;
521 91         501 $reply->from($peer);
522 91         294 last;
523             } #SELECT LOOP
524              
525 93 100       5005859 next unless $reply;
526              
527 91 100 100     591 if ( $self->{tsig_rr} && !$reply->verify($query) ) {
528 2         9 $self->errorstring( $$ns[3] = $reply->verifyerr );
529 2         22 next;
530             }
531              
532 89         493 my $rcode = $reply->header->rcode;
533 89 100       5476 return $reply if $rcode eq 'NOERROR';
534 5 100       321 return $reply if $rcode eq 'NXDOMAIN';
535 2         14 $fallback = $reply;
536 2         8 $$ns[3] = $rcode;
537             } #NAMESERVER LOOP
538              
539 90     90   35561 no integer;
  90         261  
  90         443  
540 37         172 $timeout += $timeout;
541             } #RETRY LOOP
542              
543 22 100       76 $self->{errorstring} = $fallback->header->rcode if $fallback;
544 22 100       90 $self->errorstring('query timed out') unless $self->{errorstring};
545 22         452 return $fallback;
546             }
547              
548              
549             sub bgsend {
550 16     16 1 4607 my ( $self, @argument ) = @_;
551 16         77 my $packet = $self->_make_query_packet(@argument);
552 16         75 my $packet_data = $packet->data;
553              
554 16         97 $self->_reset_errorstring;
555              
556             return $self->_bgsend_tcp( $packet, $packet_data )
557 16 100 100     157 if $self->{usevc} || length $packet_data > $self->_packetsz;
558              
559 9         51 return $self->_bgsend_udp( $packet, $packet_data );
560             }
561              
562              
563             sub _bgsend_tcp {
564 12     12   55 my ( $self, $packet, $packet_data ) = @_;
565              
566 12         53 my $tcp_packet = pack 'n a*', length($packet_data), $packet_data;
567              
568 12         60 foreach my $ip ( $self->nameservers ) {
569 12         110 $self->_diag( 'bgsend', "[$ip]" );
570              
571 12         57 my $socket = $self->_create_tcp_socket($ip);
572 12         117 $self->errorstring($!);
573 12 100       59 next unless $socket;
574              
575 10         48 $socket->blocking(0);
576 10         199 $socket->send($tcp_packet);
577 10         1611 $self->errorstring($!);
578 10         44 $socket->blocking(1);
579              
580 10         196 my $expire = time() + $self->{tcp_timeout};
581 10         68 ${*$socket}{net_dns_bg} = [$expire, $packet];
  10         69  
582 10         72 return $socket;
583             }
584              
585 2         15 return;
586             }
587              
588              
589             sub _bgsend_udp {
590 10     10   43 my ( $self, $packet, $packet_data ) = @_;
591              
592 10         33 my $port = $self->{port};
593              
594 10         41 foreach my $ip ( $self->nameservers ) {
595 11         88 my $sockaddr = $self->_create_dst_sockaddr( $ip, $port );
596 11   100     58 my $socket = $self->_create_udp_socket($ip) || next;
597              
598 9         95 $self->_diag( 'bgsend', "[$ip]:$port" );
599              
600 9         55 $socket->send( $packet_data, 0, $sockaddr );
601 9         1386 $self->errorstring($!);
602              
603             # handle failure to detect taint inside $socket->send()
604 9         15 die 'Insecure dependency while running with -T switch'
605             if TESTS && Scalar::Util::tainted($sockaddr);
606              
607 9         48 my $expire = time() + $self->{udp_timeout};
608 9         34 ${*$socket}{net_dns_bg} = [$expire, $packet];
  9         41  
609 9         58 return $socket;
610             }
611              
612 1         15 return;
613             }
614              
615              
616             sub bgbusy { ## no critic # overwrites user UDP handle
617 11700     11700 1 4559644 my ( $self, $handle ) = @_;
618 11700 100       21264 return unless $handle;
619              
620 11698   100     15315 my $appendix = ${*$handle}{net_dns_bg} ||= [time() + $self->{udp_timeout}];
  11698         32378  
621 11698         22379 my ( $expire, $query, $read ) = @$appendix;
622 11698 100       21433 return if ref($read);
623              
624 11697 100       24385 return time() <= $expire unless IO::Select->new($handle)->can_read(0);
625              
626 15 100       2646 return unless $query; # SpamAssassin 3.4.1 workaround
627 14 100       145 return if $self->{igntc};
628 11 100       99 return unless $handle->socktype() == SOCK_DGRAM;
629              
630 5         147 my $ans = $self->_bgread($handle);
631 5         22 $$appendix[2] = [$ans];
632 5 100       19 return unless $ans;
633 4 100       15 return unless $ans->header->tc;
634              
635 2         14 $self->_diag('packet truncated: retrying using TCP');
636 2   100     12 my $tcp = $self->_bgsend_tcp( $query, $query->data ) || return;
637 1         11 return defined( $_[1] = $tcp ); # caller's UDP handle now TCP
638             }
639              
640              
641             sub bgisready { ## historical
642 1     1 0 37 __PACKAGE__->_deprecate('prefer ! bgbusy(...)'); # uncoverable pod
643 1         4 return !&bgbusy;
644             }
645              
646              
647             sub bgread {
648 12     12 1 2835 my ( $self, $handle ) = @_;
649 12         37 while (&bgbusy) { # side effect: TCP retry
650 11678         426818 IO::Select->new($handle)->can_read(0.02); # reduce my CPU usage by 3 orders of magnitude
651             }
652 12         165 return &_bgread;
653             }
654              
655              
656             sub _bgread {
657 17     17   57 my ( $self, $handle ) = @_;
658 17 100       88 return unless $handle;
659              
660 16         40 my $appendix = ${*$handle}{net_dns_bg};
  16         87  
661 16         74 my ( $expire, $query, $read ) = @$appendix;
662 16 100       102 return shift(@$read) if ref($read);
663              
664 12         63 my $select = IO::Select->new($handle);
665 12 100       769 unless ( $select->can_read(0) ) {
666 1         22 $self->errorstring('timed out');
667 1         18 return;
668             }
669              
670 11         670 my $peer = $self->{replyfrom} = $handle->peerhost;
671              
672 11         998 my $dgram = $handle->socktype() == SOCK_DGRAM;
673 11 100       228 my $buffer = $dgram ? _read_udp( $handle, $self->_packetsz ) : _read_tcp($handle);
674 11         97 $self->_diag( "reply from [$peer]", length($buffer), 'bytes' );
675              
676 11         185 my $reply = Net::DNS::Packet->decode( \$buffer, $self->{debug} );
677 11         79 $self->errorstring($@);
678 11 100       57 return unless $self->_accept_reply( $reply, $query );
679 10         86 $reply->from($peer);
680              
681 10 100 100     188 return $reply unless $self->{tsig_rr} && !$reply->verify($query);
682 1         6 $self->errorstring( $reply->verifyerr );
683 1         18 return;
684             }
685              
686              
687             sub _accept_reply {
688 120     120   498 my ( $self, $reply, $query ) = @_;
689              
690 120 100       456 return unless $reply;
691              
692 119         630 my $header = $reply->header;
693 119 100       761 return unless $header->qr;
694              
695 118 100 100     896 return if $query && $header->id != $query->header->id;
696              
697 112         738 return $self->errorstring( $header->rcode ); # historical quirk
698             }
699              
700              
701             sub axfr { ## zone transfer
702 9     9 1 3022 my ( $self, @argument ) = @_;
703 9 100       53 my $zone = scalar(@argument) ? shift @argument : $self->domain;
704 9         26 my @class = @argument;
705              
706 9         43 my $request = $self->_make_query_packet( $zone, 'AXFR', @class );
707              
708 8         39 return eval {
709 8         68 $self->_diag("axfr( $zone @class )");
710 8         75 my ( $select, $verify, @rr, $soa ) = $self->_axfr_start($request);
711              
712             my $iterator = sub { ## iterate over RRs
713 2691     2691   12783 my $rr = shift(@rr);
714              
715 2691 100       4798 if ( ref($rr) eq 'Net::DNS::RR::SOA' ) {
716 6 100       34 if ($soa) {
717 3         660 $select = undef;
718 3 100       37 return if $rr->canonical eq $soa->canonical;
719 1         14 croak $self->errorstring('mismatched final SOA');
720             }
721 3         10 $soa = $rr;
722             }
723              
724 2688 100       4315 unless ( scalar @rr ) {
725 31         92 my $reply; # refill @rr
726 31         167 ( $reply, $verify ) = $self->_axfr_next( $select, $verify );
727 31 100       195 @rr = $reply->answer if $reply;
728             }
729              
730 2688         4009 return $rr;
731 3         47 };
732              
733 3 100       33 return $iterator unless wantarray;
734              
735 2         6 my @zone; ## subvert iterator to assemble entire zone
736 2         9 while ( my $rr = $iterator->() ) {
737 22         420 push @zone, $rr, @rr; # copy RRs en bloc
738 22         221 @rr = pop(@zone); # leave last one in @rr
739             }
740 2         1184 return @zone;
741             };
742             }
743              
744              
745             sub axfr_start { ## historical
746 1     1 0 27 my ( $self, @argument ) = @_; # uncoverable pod
747 1         9 $self->_deprecate('prefer $iterator = $self->axfr(...)');
748 1         3 my $iterator = $self->axfr(@argument);
749 1     1   66 ( $self->{axfr_iter} ) = grep {defined} ( $iterator, sub {} );
  2         16  
750 1         4 return defined($iterator);
751             }
752              
753              
754             sub axfr_next { ## historical
755 1     1 0 39 my $self = shift; # uncoverable pod
756 1         4 $self->_deprecate('prefer $iterator->()');
757 1         4 return $self->{axfr_iter}->();
758             }
759              
760              
761             sub _axfr_start {
762 8     8   31 my ( $self, $request ) = @_;
763 8         37 my $content = $request->data;
764 8         80 my $TCP_msg = pack 'n a*', length($content), $content;
765              
766 8         27 my ( $select, $reply, $rcode );
767 8         58 foreach my $ns ( $self->nameservers ) {
768 11         94 $self->_diag("axfr send [$ns]");
769              
770 11         43 local $self->{persistent_tcp};
771 11         58 my $socket = $self->_create_tcp_socket($ns);
772 11         75 $self->errorstring($!);
773 11   100     150 $select = IO::Select->new( $socket || next );
774              
775 9         1278 $socket->send($TCP_msg);
776 9         1592 $self->errorstring($!);
777              
778 9         69 ($reply) = $self->_axfr_next($select);
779 9 100       59 last if ( $rcode = $reply->header->rcode ) eq 'NOERROR';
780             }
781              
782 8 100       59 croak $self->errorstring unless $reply;
783              
784 6         42 $self->errorstring($rcode); # historical quirk
785              
786 6 100       41 my $verify = $request->sigrr ? $request : undef;
787 6 100       25 unless ($verify) {
788 3 100       19 croak $self->errorstring unless $rcode eq 'NOERROR';
789 2         13 return ( $select, $verify, $reply->answer );
790             }
791              
792 3         18 my $verifyok = $reply->verify($verify);
793 3 100       41 croak $self->errorstring( $reply->verifyerr ) unless $verifyok;
794 2 100       14 croak $self->errorstring if $rcode ne 'NOERROR';
795 1         7 return ( $select, $verifyok, $reply->answer );
796             }
797              
798              
799             sub _axfr_next {
800 43     43   446 my $self = shift;
801 43   100     191 my $select = shift || return;
802 42         121 my $verify = shift;
803              
804 42         307 my ($socket) = $select->can_read( $self->{tcp_timeout} );
805 42 100       180839 croak $self->errorstring('timed out') unless $socket;
806              
807 41         198 my $buffer = _read_tcp($socket);
808 41         473 my $packet = Net::DNS::Packet->decode( \$buffer );
809 41 100       164 croak $@, $self->errorstring('corrupt packet') if $@;
810              
811 40 100       287 return ( $packet, $verify ) unless $verify;
812              
813 11         60 my $verifyok = $packet->verify($verify);
814 11 100       47 croak $self->errorstring( $packet->verifyerr ) unless $verifyok;
815 10         141 return ( $packet, $verifyok );
816             }
817              
818              
819             #
820             # Usage: $data = _read_tcp($socket);
821             #
822             sub _read_tcp {
823 58     58   290 my $socket = shift;
824              
825 58         170 my ( $s1, $s2 );
826 58         412 $socket->recv( $s1, 1 ); # two octet length
827 58         185038 $socket->recv( $s2, 2 - length $s1 ); # possibly fragmented
828 58         1912 my $size = unpack 'n', pack( 'a*a*@2', $s1, $s2 );
829              
830 58         227 my $buffer = '';
831 58         142 for ( ; ; ) {
832 61         211 my $fragment;
833 61         318 $socket->recv( $fragment, $size - length($buffer) );
834 61 100 100     55699 last unless length( $buffer .= $fragment || last ) < $size;
835             }
836 58         1526 return $buffer;
837             }
838              
839              
840             #
841             # Usage: $data = _read_udp($socket, $length);
842             #
843             sub _read_udp {
844 99     99   290 my $socket = shift;
845 99         305 my $buffer = '';
846 99         678 $socket->recv( $buffer, shift );
847 99         5513 return $buffer;
848             }
849              
850              
851             sub _create_tcp_socket {
852 33     33   127 my ( $self, $ip ) = @_;
853              
854 33         80 my $socket;
855 33         147 my $sock_key = "TCP[$ip]";
856 33 100       168 if ( $socket = $self->{persistent}{$sock_key} ) {
857 2         7 $self->_diag( 'using persistent socket', $sock_key );
858 2 100       9 return $socket if $socket->connected;
859 1         99 $self->_diag('socket disconnected (trying to connect)');
860             }
861              
862 32         159 my $ip6_addr = IPv6 && _ipv6($ip);
863             $socket = IO::Socket::IP->new(
864             LocalAddr => $ip6_addr ? $self->{srcaddr6} : $self->{srcaddr4},
865             LocalPort => $self->{srcport},
866             PeerAddr => $ip,
867             PeerPort => $self->{port},
868             Proto => 'tcp',
869             Timeout => $self->{tcp_timeout},
870             )
871 32 100       471 if USE_SOCKET_IP;
872              
873 32         539785 unless (USE_SOCKET_IP) {
874             $socket = IO::Socket::INET->new(
875             LocalAddr => $self->{srcaddr4},
876             LocalPort => $self->{srcport} || undef,
877             PeerAddr => $ip,
878             PeerPort => $self->{port},
879             Proto => 'tcp',
880             Timeout => $self->{tcp_timeout},
881             )
882             unless $ip6_addr;
883             }
884              
885 32 100       219 $self->{persistent}{$sock_key} = $socket if $self->{persistent_tcp};
886 32         116 return $socket;
887             }
888              
889              
890             sub _create_udp_socket {
891 169     169   477 my ( $self, $ip ) = @_;
892              
893 169         302 my $socket;
894 169         540 my $sock_key = "UDP[$ip]";
895 169 100       763 return $socket if $socket = $self->{persistent}{$sock_key};
896              
897 168         377 my $ip6_addr = IPv6 && _ipv6($ip);
898             $socket = IO::Socket::IP->new(
899             LocalAddr => $ip6_addr ? $self->{srcaddr6} : $self->{srcaddr4},
900             LocalPort => $self->{srcport},
901 168 100       1753 Proto => 'udp',
902             Type => SOCK_DGRAM
903             )
904             if USE_SOCKET_IP;
905              
906 168         99009 unless (USE_SOCKET_IP) {
907             $socket = IO::Socket::INET->new(
908             LocalAddr => $self->{srcaddr4},
909             LocalPort => $self->{srcport} || undef,
910             Proto => 'udp',
911             Type => SOCK_DGRAM
912             )
913             unless $ip6_addr;
914             }
915              
916 168 100       657 $self->{persistent}{$sock_key} = $socket if $self->{persistent_udp};
917 168         765 return $socket;
918             }
919              
920              
921             {
922 90     90   240522 no strict 'subs'; ## no critic ProhibitNoStrict
  90         274  
  90         4313  
923 90     90   688 use constant AI_NUMERICHOST => Socket::AI_NUMERICHOST;
  90         251  
  90         6656  
924 90     90   687 use constant IPPROTO_UDP => Socket::IPPROTO_UDP;
  90         264  
  90         157870  
925              
926             my $ip4 = {
927             family => AF_INET,
928             flags => AI_NUMERICHOST,
929             protocol => IPPROTO_UDP,
930             socktype => SOCK_DGRAM
931             };
932             my $ip6 = {
933             family => AF_INET6,
934             flags => AI_NUMERICHOST,
935             protocol => IPPROTO_UDP,
936             socktype => SOCK_DGRAM
937             };
938              
939             sub _create_dst_sockaddr { ## create UDP destination sockaddr structure
940 201     201   582 my ( $self, $ip, $port ) = @_;
941              
942 201         303 unless (USE_SOCKET_IP) { # NB: errors raised in socket->send
943             return _ipv6($ip) ? undef : sockaddr_in( $port, inet_aton($ip) );
944             }
945              
946 201 100       569 my @addrinfo = Socket::getaddrinfo( $ip, $port, _ipv6($ip) ? $ip6 : $ip4 );
947 201         726 return ( grep {ref} @addrinfo, {} )[0]->{addr};
  603         1945  
948             }
949             }
950              
951              
952             # Lightweight versions of subroutines from Net::IP module, recoded to fix RT#96812
953              
954             sub _ipv4 {
955 2673     2673   4459 for (shift) {
956 2673 100       7158 last if m/[^.0-9]/; # dots and digits only
957 1389         6059 return m/\.\d+\./; # dots separated by digits
958             }
959 1284         3065 return;
960             }
961              
962             sub _ipv6 {
963 2387     2387   4108 for (shift) {
964 2387 100       7309 last unless m/:.*:/; # must contain two colons
965 1419 100       5934 return 1 unless m/[^:0-9A-Fa-f]/; # colons and hexdigits only
966 4 100       12 return 1 if m/^[:.0-9A-Fa-f]+\%.+$/; # RFC4007 scoped address
967 2         9 return m/^[:0-9A-Fa-f]+:[.0-9]+$/; # prefix : dotted digits
968             }
969 968         3888 return;
970             }
971              
972              
973             sub _make_query_packet {
974 167     167   484 my ( $self, @argument ) = @_;
975              
976 167         523 my ($packet) = @argument;
977 167 100       576 if ( ref($packet) ) {
978 70         266 my $edns = $packet->edns; # advertise UDPsize for local stack
979 70 100       333 $edns->udpsize( $self->{udppacketsize} ) unless defined $edns->{udpsize};
980             } else {
981 97         556 $packet = Net::DNS::Packet->new(@argument);
982 96         367 $packet->edns->udpsize( $self->{udppacketsize} );
983              
984 96         326 my $header = $packet->header;
985 96         577 $header->ad( $self->{adflag} ); # RFC6840, 5.7
986 96         413 $header->cd( $self->{cdflag} ); # RFC6840, 5.9
987 96 100       407 $header->do(1) if $self->{dnssec};
988 96         451 $header->rd( $self->{recurse} );
989             }
990              
991 166 100       614 if ( $self->{tsig_rr} ) {
992 12 100       45 $packet->sign_tsig( $self->{tsig_rr} ) unless $packet->sigrr;
993             }
994              
995 166         498 return $packet;
996             }
997              
998              
999             sub dnssec {
1000 11     11 1 1561 my ( $self, @argument ) = @_;
1001 11         30 for (@argument) {
1002 7         39 $self->udppacketsize(1232);
1003 7         24 $self->{dnssec} = $_;
1004             }
1005 11         40 return $self->{dnssec};
1006             }
1007              
1008              
1009             sub force_v6 {
1010 8     8 1 1480 my ( $self, @value ) = @_;
1011 8 100       22 for (@value) { $self->{force_v4} = 0 if $self->{force_v6} = $_ }
  5         30  
1012 8 100       31 return $self->{force_v6} ? 1 : 0;
1013             }
1014              
1015             sub force_v4 {
1016 9     9 1 796 my ( $self, @value ) = @_;
1017 9 100       22 for (@value) { $self->{force_v6} = 0 if $self->{force_v4} = $_ }
  6         25  
1018 9 100       34 return $self->{force_v4} ? 1 : 0;
1019             }
1020              
1021             sub prefer_v6 {
1022 8     8 1 794 my ( $self, @value ) = @_;
1023 8 100       28 for (@value) { $self->{prefer_v4} = 0 if $self->{prefer_v6} = $_ }
  5         20  
1024 8 100       27 return $self->{prefer_v6} ? 1 : 0;
1025             }
1026              
1027             sub prefer_v4 {
1028 6     6 1 792 my ( $self, @value ) = @_;
1029 6 100       24 for (@value) { $self->{prefer_v6} = 0 if $self->{prefer_v4} = $_ }
  3         19  
1030 6 100       22 return $self->{prefer_v4} ? 1 : 0;
1031             }
1032              
1033             sub srcaddr {
1034 2     2 1 551 my ( $self, @value ) = @_;
1035 2         7 for (@value) {
1036 2 100       5 my $hashkey = _ipv6($_) ? 'srcaddr6' : 'srcaddr4';
1037 2         11 $self->{$hashkey} = $_;
1038             }
1039 2         15 return shift @value;
1040             }
1041              
1042              
1043             sub tsig {
1044 9     9 1 1176 my ( $self, $arg, @etc ) = @_;
1045 9         20 $self->{tsig_rr} = eval {
1046 9 100       33 return $arg unless $arg;
1047 8 100       30 return $arg if ref($arg) eq 'Net::DNS::RR::TSIG';
1048 7         36 local $SIG{__DIE__};
1049 7         1755 require Net::DNS::RR::TSIG;
1050 7         62 Net::DNS::RR::TSIG->create( $arg, @etc );
1051             };
1052 9 100       1452 croak "${@}unable to create TSIG record" if $@;
1053 8         24 return;
1054             }
1055              
1056              
1057             # if ($self->{udppacketsize} > PACKETSZ
1058             # then we use EDNS and $self->{udppacketsize}
1059             # should be taken as the maximum packet_data length
1060             sub _packetsz {
1061 231   100 231   1503 my $udpsize = shift->{udppacketsize} || 0;
1062 231 100       1448 return $udpsize > PACKETSZ ? $udpsize : PACKETSZ;
1063             }
1064              
1065             sub udppacketsize {
1066 13     13 1 67 my ( $self, @value ) = @_;
1067 13         33 for (@value) { $self->{udppacketsize} = $_ }
  11         48  
1068 13         47 return $self->_packetsz;
1069             }
1070              
1071              
1072             #
1073             # Keep this method around. Folk depend on it although it is neither documented nor exported.
1074             #
1075             sub make_query_packet { ## historical
1076 2     2 0 58 __PACKAGE__->_deprecate('see RT#37104'); # uncoverable pod
1077 2         6 return &_make_query_packet;
1078             }
1079              
1080              
1081             sub _diag { ## debug output
1082 545 100   545   2026 return unless shift->{debug};
1083 1         31 return print "\n;; @_\n";
1084             }
1085              
1086              
1087             {
1088             my $parse_dig = sub {
1089             require Net::DNS::ZoneFile;
1090              
1091             my $dug = Net::DNS::ZoneFile->new( \*DATA );
1092             my @rr = $dug->read;
1093              
1094             my @auth = grep { $_->type eq 'NS' } @rr;
1095             my %auth = map { lc $_->nsdname => 1 } @auth;
1096             my %glue;
1097             my @glue = grep { $auth{lc $_->name} } @rr;
1098             foreach ( grep { $_->can('address') } @glue ) {
1099             push @{$glue{lc $_->name}}, $_->address;
1100             }
1101             map {@$_} values %glue;
1102             };
1103              
1104             my @ip;
1105              
1106             sub _hints { ## default hints
1107 6 100   6   592 @ip = &$parse_dig unless scalar @ip; # once only, on demand
1108 6         210 splice @ip, 0, 0, splice( @ip, int( rand scalar @ip ) ); # cut deck
1109 6         54 return @ip;
1110             }
1111             }
1112              
1113              
1114       1     sub DESTROY { } ## Avoid tickling AUTOLOAD (in cleanup)
1115              
1116             sub AUTOLOAD { ## Default method
1117 42     42   872 my ($self) = @_;
1118              
1119 90     90   937 no strict 'refs'; ## no critic ProhibitNoStrict
  90         306  
  90         21406  
1120 42         67 our $AUTOLOAD;
1121 42         96 my $name = $AUTOLOAD;
1122 42         273 $name =~ s/.*://;
1123 42 100       249 croak qq[unknown method "$name"] unless $public_attr{$name};
1124              
1125 41         214 *{$AUTOLOAD} = sub {
1126 101     101   4873 my $self = shift;
1127 101 100       299 $self = $self->_defaults unless ref($self);
1128 101 100 100     601 $self->{$name} = shift || 0 if scalar @_;
1129 101         401 return $self->{$name};
1130 41         269 };
1131              
1132 41         145 return &$AUTOLOAD;
1133             }
1134              
1135              
1136             1;
1137              
1138              
1139             =head1 NAME
1140              
1141             Net::DNS::Resolver::Base - DNS resolver base class
1142              
1143             =head1 SYNOPSIS
1144              
1145             use base qw(Net::DNS::Resolver::Base);
1146              
1147             =head1 DESCRIPTION
1148              
1149             This class is the common base class for the different platform
1150             sub-classes of L.
1151              
1152             No user serviceable parts inside, see L
1153             for all your resolving needs.
1154              
1155              
1156             =head1 METHODS
1157              
1158             =head2 new, domain, searchlist, nameserver, nameservers,
1159              
1160             =head2 search, query, send, bgsend, bgbusy, bgread, axfr,
1161              
1162             =head2 force_v4, force_v6, prefer_v4, prefer_v6,
1163              
1164             =head2 dnssec, srcaddr, tsig, udppacketsize,
1165              
1166             =head2 print, string, errorstring, replyfrom
1167              
1168             See L.
1169              
1170              
1171             =head1 COPYRIGHT
1172              
1173             Copyright (c)2003,2004 Chris Reinhardt.
1174              
1175             Portions Copyright (c)2005 Olaf Kolkman.
1176              
1177             Portions Copyright (c)2014-2017 Dick Franks.
1178              
1179             All rights reserved.
1180              
1181              
1182             =head1 LICENSE
1183              
1184             Permission to use, copy, modify, and distribute this software and its
1185             documentation for any purpose and without fee is hereby granted, provided
1186             that the original copyright notices appear in all copies and that both
1187             copyright notice and this permission notice appear in supporting
1188             documentation, and that the name of the author not be used in advertising
1189             or publicity pertaining to distribution of the software without specific
1190             prior written permission.
1191              
1192             THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1193             IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1194             FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1195             THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1196             LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1197             FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1198             DEALINGS IN THE SOFTWARE.
1199              
1200              
1201             =head1 SEE ALSO
1202              
1203             L L L
1204              
1205             =cut
1206              
1207              
1208             ########################################
1209              
1210             __DATA__ ## DEFAULT HINTS