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   716 use strict;
  90         177  
  90         2583  
4 90     90   425 use warnings;
  90         168  
  90         5192  
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   636 use constant USE_SOCKET_IP => defined eval 'use IO::Socket::IP 0.38; 1;'; ## no critic
  90     90   195  
  90         7031  
  90         58470  
  90         3336777  
  90         600  
29             require IO::Socket::INET unless USE_SOCKET_IP;
30              
31 90     90   784 use constant IPv6 => USE_SOCKET_IP;
  90         216  
  90         6616  
32              
33              
34             # If SOCKSified Perl, use TCP instead of UDP and keep the socket open.
35 90     90   978 use constant SOCKS => scalar eval { require Config; $Config::Config{usesocks}; };
  90         202  
  90         195  
  90         340  
  90         16943  
36              
37              
38             # Allow taint tests to be optimised away when appropriate.
39 90     90   734 use constant TAINT => eval { ${^TAINT} };
  90         198  
  90         189  
  90         7064  
40 90     90   611 use constant TESTS => TAINT && defined eval { require Scalar::Util; };
  90         198  
  90         4237  
41              
42              
43 90     90   4069 use integer;
  90         288  
  90         650  
44 90     90   2616 use Carp;
  90         202  
  90         5303  
45 90     90   43947 use IO::File;
  90         167327  
  90         9932  
46 90     90   43489 use IO::Select;
  90         153486  
  90         4362  
47 90     90   741 use IO::Socket;
  90         598  
  90         539  
48 90     90   75381 use Socket;
  90         230  
  90         50942  
49              
50 90     90   47588 use Net::DNS::RR;
  90         290  
  90         3033  
51 90     90   46984 use Net::DNS::Packet;
  90         259  
  90         2873  
52              
53 90     90   629 use constant PACKETSZ => 512;
  90         224  
  90         294751  
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 341     341   3470 sub _defaults { return $defaults; }
95             }
96              
97              
98             my %warned;
99              
100             sub _deprecate {
101 7     7   20 my ( undef, @note ) = @_;
102 7 100       551 carp join ' ', 'deprecated method;', "@note" unless $warned{"@note"}++;
103 7         230 return;
104             }
105              
106              
107             sub _untaint { ## no critic # recurses into user list arguments
108 10     10   185 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 93     93 1 53699 my ( $class, %args ) = @_;
124              
125 93         207 my $self;
126 93         346 my $base = $class->_defaults;
127 93         212 my $init = $initial;
128 93   100     561 $initial ||= [%$base];
129 93 100       414 if ( my $file = $args{config_file} ) {
    100          
130 4         57 my $conf = bless {@$initial}, $class;
131 4         23 $conf->_read_config_file($file); # user specified config
132 2         24 $self = bless {_untaint(%$conf)}, $class;
133 2 100       38 %$base = %$self unless $init; # define default configuration
134              
135             } elsif ($init) {
136 81         1424 $self = bless {%$base}, $class;
137              
138             } else {
139 8         82 $class->_init(); # define default configuration
140 8         151 $self = bless {%$base}, $class;
141             }
142              
143 91         563 while ( my ( $attr, $value ) = each %args ) {
144 77 100       290 next unless $public_attr{$attr};
145 75         184 my $ref = ref($value);
146 75 100 100     878 croak "usage: $class->new( $attr => [...] )"
147             if $ref && ( $ref ne 'ARRAY' );
148 71 100       620 $self->$attr( $ref ? @$value : $value );
149             }
150              
151 87         400 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   22 my ( $self, $name, @value ) = @_;
168 10   100     59 my $attribute = $res_option{lc $name} || return;
169 7 100       18 push @value, 1 unless scalar @value;
170 7         49 return $self->$attribute(@value);
171             }
172              
173              
174             sub _read_env { ## read resolver config environment variables
175 8     8   23 my $self = shift;
176              
177 8 100       41 $self->searchlist( map {split} $ENV{LOCALDOMAIN} ) if defined $ENV{LOCALDOMAIN};
  1         5  
178              
179 8 100       36 $self->nameservers( map {split} $ENV{RES_NAMESERVERS} ) if defined $ENV{RES_NAMESERVERS};
  1         6  
180              
181 8 100       29 $self->searchlist( map {split} $ENV{RES_SEARCHLIST} ) if defined $ENV{RES_SEARCHLIST};
  1         5  
182              
183 8   100     59 foreach ( map {split} $ENV{RES_OPTIONS} || '' ) {
  8         45  
184 4         12 $self->_option( split m/:/ );
185             }
186 8         21 return;
187             }
188              
189              
190             sub _read_config_file { ## read resolver config file
191 19     19   67 my ( $self, $file ) = @_;
192              
193 19 100       144 my $filehandle = IO::File->new( $file, '<' ) or croak "$file: $!";
194              
195 17         2169 my @nameserver;
196             my @searchlist;
197              
198 17         82 local $_;
199 17         459 while (<$filehandle>) {
200 58         256 s/[;#].*$//; # strip comments
201              
202 58 100       183 /^nameserver/ && do {
203 10         51 my ( $keyword, @ip ) = grep {defined} split;
  22         80  
204 10         41 push @nameserver, @ip;
205 10         42 next;
206             };
207              
208 48 100       119 /^domain/ && do {
209 2         9 my ( $keyword, $domain ) = grep {defined} split;
  4         14  
210 2         19 $self->domain($domain);
211 2         12 next;
212             };
213              
214 46 100       130 /^search/ && do {
215 10         45 my ( $keyword, @domain ) = grep {defined} split;
  30         355  
216 10         235 push @searchlist, @domain;
217 10         115 next;
218             };
219              
220 36 100       128 /^option/ && do {
221 2         6 my ( $keyword, @option ) = grep {defined} split;
  8         15  
222 2         7 foreach (@option) {
223 6         23 $self->_option( split m/:/ );
224             }
225             };
226             }
227              
228 17         181 close($filehandle);
229              
230 17 100       118 $self->nameservers(@nameserver) if @nameserver;
231 17 100       80 $self->searchlist(@searchlist) if @searchlist;
232 17         115 return;
233             }
234              
235              
236             sub string {
237 2     2 1 6 my $self = shift;
238 2 100       8 $self = $self->_defaults unless ref($self);
239              
240 2         6 my @nslist = $self->nameservers();
241 2         5 my ($force) = ( grep( { $self->{$_} } qw(force_v6 force_v4) ), 'force_v4' );
  4         10  
242 2         4 my ($prefer) = ( grep( { $self->{$_} } qw(prefer_v6 prefer_v4) ), 'prefer_v4' );
  4         8  
243 2         8 return <
244             ;; RESOLVER state:
245             ;; nameservers = @nslist
246 2         47 ;; 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 148 return print shift->string;
261             }
262              
263              
264             sub searchlist {
265 181     181 1 2655 my ( $self, @domain ) = @_;
266 181 100       3673 $self = $self->_defaults unless ref($self);
267              
268 181         1491 foreach (@domain) { $_ = Net::DNS::Domain->new($_)->name }
  40         240  
269 181 100       1267 $self->{searchlist} = \@domain if scalar(@domain);
270 181         743 return @{$self->{searchlist}};
  181         1535  
271             }
272              
273             sub domain {
274 113     113 1 5237 return (&searchlist)[0];
275             }
276              
277              
278             sub nameservers {
279 318     318 1 3594 my ( $self, @ns ) = @_;
280 318 100       957 $self = $self->_defaults unless ref($self);
281              
282 318         632 my @ip;
283 318         902 foreach my $ns ( grep {defined} @ns ) {
  1470         2886  
284 1470 100 100     3044 if ( _ipv4($ns) || _ipv6($ns) ) {
285 1456         4165 push @ip, $ns;
286              
287             } else {
288 14         160 my $defres = ref($self)->new( debug => $self->{debug} );
289 14         52 $defres->{persistent} = $self->{persistent};
290              
291 14         65 my $names = {};
292 14         79 my $packet = $defres->send( $ns, 'A' );
293 14         179 my @iplist = _cname_addr( $packet, $names );
294              
295 14         51 if (IPv6) {
296 14         79 $packet = $defres->send( $ns, 'AAAA' );
297 14         168 push @iplist, _cname_addr( $packet, $names );
298             }
299              
300 14         67 my %unique = map { $_ => $_ } @iplist;
  25         149  
301              
302 14         91 my @address = values(%unique); # tainted
303 14 100       151 carp "unresolvable name: $ns" unless scalar @address;
304              
305 14         371 push @ip, @address;
306             }
307             }
308              
309 318 100 100     1499 if ( scalar(@ns) || !defined(wantarray) ) {
310 139         686 my @ipv4 = grep { _ipv4($_) } @ip;
  1481         2733  
311 139         434 my @ipv6 = grep { _ipv6($_) } @ip;
  1481         2726  
312 139         592 $self->{nameservers} = \@ip;
313 139         375 $self->{nameserver4} = \@ipv4;
314 139         396 $self->{nameserver6} = \@ipv6;
315             }
316              
317 318 100       928 my @ns4 = $self->{force_v6} ? () : @{$self->{nameserver4}};
  315         1020  
318 318 100       821 my @ns6 = $self->{force_v4} ? () : @{$self->{nameserver6}};
  314         890  
319              
320 318         591 my @nameservers = @{$self->{nameservers}};
  318         987  
321 318 100 100     1642 @nameservers = ( @ns4, @ns6 ) if $self->{prefer_v4} || !scalar(@ns6);
322 318 100 100     1314 @nameservers = ( @ns6, @ns4 ) if $self->{prefer_v6} || !scalar(@ns4);
323              
324 318 100       1941 return @nameservers if scalar @nameservers;
325              
326 18         107 my $error = 'no nameservers';
327 18 100       38 $error = 'IPv4 transport disabled' if scalar(@ns4) < scalar @{$self->{nameserver4}};
  18         45  
328 18 100       35 $error = 'IPv6 transport disabled' if scalar(@ns6) < scalar @{$self->{nameserver6}};
  18         39  
329 18         53 $self->errorstring($error);
330 18         60 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 29     29   75 my @null;
341 29   100     202 my $packet = shift || return @null;
342 26         60 my $names = shift;
343              
344 26         103 $names->{lc( $_->qname )}++ foreach $packet->question;
345 26         153 $names->{lc( $_->cname )}++ foreach grep { $_->can('cname') } $packet->answer;
  27         297  
346              
347 26         110 my @addr = grep { $_->can('address') } $packet->answer;
  27         171  
348 26         88 return map { $_->address } grep { $names->{lc( $_->name )} } @addr;
  25         142  
  25         137  
349             }
350              
351              
352             sub replyfrom {
353 2     2 1 17 return shift->{replyfrom};
354             }
355              
356 1     1 0 20 sub answerfrom { return &replyfrom; } # uncoverable pod
357              
358              
359             sub _reset_errorstring {
360 143     143   384 shift->{errorstring} = '';
361 143         282 return;
362             }
363              
364             sub errorstring {
365 488     488 1 1844 my $self = shift;
366 488   100     2641 my $text = shift || return $self->{errorstring};
367 175         663 $self->_diag( 'errorstring:', $text );
368 175         1628 return $self->{errorstring} = $text;
369             }
370              
371              
372             sub query {
373 13     13 1 67 my ( $self, @argument ) = @_;
374              
375 13   100     77 my $name = shift(@argument) || '.';
376 13 100 100     153 my @sfix = $self->{defnames} && ( $name !~ m/[.:]/ ) ? $self->domain : ();
377              
378 13         56 my $fqdn = join '.', $name, @sfix;
379 13         59 $self->_diag( 'query(', $fqdn, @argument, ')' );
380 13   100     54 my $packet = $self->send( $fqdn, @argument ) || return;
381 10 100       54 return $packet->header->ancount ? $packet : undef;
382             }
383              
384              
385             sub search {
386 7     7 1 46 my ( $self, @argument ) = @_;
387              
388 7 100       24 return $self->query(@argument) unless $self->{dnsrch};
389              
390 6   100     38 my $name = shift(@argument) || '.';
391 6         17 my $dots = $name =~ tr/././;
392              
393 6 100       23 my @sfix = ( $dots < $self->{ndots} ) ? @{$self->{searchlist}} : ();
  1         3  
394 6 100       74 my ( $one, @more ) = ( $name =~ m/:|\.\d*$/ ) ? () : ( $dots ? ( undef, @sfix ) : @sfix );
    100          
395              
396 6         18 foreach my $suffix ( $one, @more ) {
397 7 100       18 my $fqname = $suffix ? join( '.', $name, $suffix ) : $name;
398 7         23 $self->_diag( 'search(', $fqname, @argument, ')' );
399 7   100     17 my $packet = $self->send( $fqname, @argument ) || next;
400 2 100       9 return $packet if $packet->header->ancount;
401             }
402              
403 5         34 return;
404             }
405              
406              
407             sub send {
408 127     127 1 479 my ( $self, @argument ) = @_;
409 127         403 my $packet = $self->_make_query_packet(@argument);
410 127         457 my $packet_data = $packet->data;
411              
412 127         579 $self->_reset_errorstring;
413              
414             return $self->_send_tcp( $packet, $packet_data )
415 127 100 100     662 if $self->{usevc} || length $packet_data > $self->_packetsz;
416              
417 120   100     449 my $reply = $self->_send_udp( $packet, $packet_data ) || return;
418              
419 100 100       701 return $reply if $self->{igntc};
420 96 100       532 return $reply unless $reply->header->tc;
421              
422 1         8 $self->_diag('packet truncated: retrying using TCP');
423 1         7 return $self->_send_tcp( $packet, $packet_data );
424             }
425              
426              
427             sub _send_tcp {
428 9     9   68 my ( $self, $query, $query_data ) = @_;
429              
430 9         57 my $tcp_packet = pack 'n a*', length($query_data), $query_data;
431 9         62 my @ns = $self->nameservers();
432 9         22 my $fallback;
433 9         24 my $timeout = $self->{tcp_timeout};
434              
435 9         30 foreach my $ip (@ns) {
436 12         94 $self->_diag( 'tcp send', "[$ip]" );
437              
438 12         113 my $socket = $self->_create_tcp_socket($ip);
439 12         57 $self->errorstring($!);
440 12   100     162 my $select = IO::Select->new( $socket || next );
441              
442 10         915 $socket->send($tcp_packet);
443 10         1626 $self->errorstring($!);
444              
445 10         60 my $buffer = _read_tcp($socket);
446 10         46 $self->{replyfrom} = $ip;
447 10         90 $self->_diag( 'reply from', "[$ip]", length($buffer), 'bytes' );
448              
449 10         165 my $reply = Net::DNS::Packet->decode( \$buffer, $self->{debug} );
450 10         86 $self->errorstring($@);
451 10 100       49 next unless $self->_accept_reply( $reply, $query );
452 8         42 $reply->from($ip);
453              
454 8 100 100     59 if ( $self->{tsig_rr} && !$reply->verify($query) ) {
455 2         8 $self->errorstring( $reply->verifyerr );
456 2         248 next;
457             }
458              
459 6         24 my $rcode = $reply->header->rcode;
460 6 100       356 return $reply if $rcode eq 'NOERROR';
461 3 100       158 return $reply if $rcode eq 'NXDOMAIN';
462 2         332 $fallback = $reply;
463             }
464              
465 5 100       39 $self->{errorstring} = $fallback->header->rcode if $fallback;
466 5 100       33 $self->errorstring('query timed out') unless $self->{errorstring};
467 5         63 return $fallback;
468             }
469              
470              
471             sub _send_udp {
472 121     121   385 my ( $self, $query, $query_data ) = @_;
473              
474 121         372 my @ns = $self->nameservers;
475 121         345 my $port = $self->{port};
476 121   100     471 my $retrans = $self->{retrans} || 1;
477 121   100     349 my $retry = $self->{retry} || 1;
478 121         220 my $servers = scalar(@ns);
479 90 100   90   900 my $timeout = $servers ? do { no integer; $retrans / $servers } : 0;
  90         285  
  90         666  
  121         309  
  117         451  
480 121         209 my $fallback;
481              
482             # Perform each round of retries.
483 121         363 RETRY: for ( 1 .. $retry ) { # assumed to be a small number
484              
485             # Try each nameserver.
486 136         955 my $select = IO::Select->new();
487              
488 136         1809 NAMESERVER: foreach my $ns (@ns) {
489              
490             # state vector replaces corresponding element of @ns array
491 215 100       582 unless ( ref $ns ) {
492 203         592 my $sockaddr = $self->_create_dst_sockaddr( $ns, $port );
493 203   100     725 my $socket = $self->_create_udp_socket($ns) || next;
494 105         422 $ns = [$socket, $ns, $sockaddr];
495             }
496              
497 117         384 my ( $socket, $ip, $sockaddr, $failed ) = @$ns;
498 117 100       343 next if $failed;
499              
500 105         584 $self->_diag( 'udp send', "[$ip]:$port" );
501              
502 105         563 $select->add($socket);
503 105         6500 $socket->send( $query_data, 0, $sockaddr );
504 105         18591 $self->errorstring( $$ns[3] = $! );
505              
506             # handle failure to detect taint inside socket->send()
507 105         187 die 'Insecure dependency while running with -T switch'
508             if TESTS && Scalar::Util::tainted($sockaddr);
509              
510 105         239 my $reply;
511 105         526 while ( my ($socket) = $select->can_read($timeout) ) {
512 105         3785975 my $peer = $self->{replyfrom} = $socket->peerhost;
513              
514 105         8742 my $buffer = _read_udp( $socket, $self->_packetsz );
515 105         876 $self->_diag( "reply from [$peer]", length($buffer), 'bytes' );
516              
517 105         1297 my $packet = Net::DNS::Packet->decode( \$buffer, $self->{debug} );
518 105         548 $self->errorstring($@);
519 105 100       496 next unless $self->_accept_reply( $packet, $query );
520 103         285 $reply = $packet;
521 103         463 $reply->from($peer);
522 103         276 last;
523             } #SELECT LOOP
524              
525 105 100       5005937 next unless $reply;
526              
527 103 100 100     440 if ( $self->{tsig_rr} && !$reply->verify($query) ) {
528 2         9 $self->errorstring( $$ns[3] = $reply->verifyerr );
529 2         18 next;
530             }
531              
532 101         327 my $rcode = $reply->header->rcode;
533 101 100       4829 return $reply if $rcode eq 'NOERROR';
534 5 100       186 return $reply if $rcode eq 'NXDOMAIN';
535 2         12 $fallback = $reply;
536 2         10 $$ns[3] = $rcode;
537             } #NAMESERVER LOOP
538              
539 90     90   33305 no integer;
  90         252  
  90         406  
540 37         163 $timeout += $timeout;
541             } #RETRY LOOP
542              
543 22 100       54 $self->{errorstring} = $fallback->header->rcode if $fallback;
544 22 100       83 $self->errorstring('query timed out') unless $self->{errorstring};
545 22         472 return $fallback;
546             }
547              
548              
549             sub bgsend {
550 16     16 1 3437 my ( $self, @argument ) = @_;
551 16         56 my $packet = $self->_make_query_packet(@argument);
552 16         63 my $packet_data = $packet->data;
553              
554 16         74 $self->_reset_errorstring;
555              
556             return $self->_bgsend_tcp( $packet, $packet_data )
557 16 100 100     94 if $self->{usevc} || length $packet_data > $self->_packetsz;
558              
559 9         49 return $self->_bgsend_udp( $packet, $packet_data );
560             }
561              
562              
563             sub _bgsend_tcp {
564 12     12   53 my ( $self, $packet, $packet_data ) = @_;
565              
566 12         57 my $tcp_packet = pack 'n a*', length($packet_data), $packet_data;
567              
568 12         46 foreach my $ip ( $self->nameservers ) {
569 12         74 $self->_diag( 'bgsend', "[$ip]" );
570              
571 12         47 my $socket = $self->_create_tcp_socket($ip);
572 12         87 $self->errorstring($!);
573 12 100       47 next unless $socket;
574              
575 10         55 $socket->blocking(0);
576 10         187 $socket->send($tcp_packet);
577 10         1681 $self->errorstring($!);
578 10         52 $socket->blocking(1);
579              
580 10         167 my $expire = time() + $self->{tcp_timeout};
581 10         45 ${*$socket}{net_dns_bg} = [$expire, $packet];
  10         57  
582 10         58 return $socket;
583             }
584              
585 2         14 return;
586             }
587              
588              
589             sub _bgsend_udp {
590 10     10   37 my ( $self, $packet, $packet_data ) = @_;
591              
592 10         25 my $port = $self->{port};
593              
594 10         33 foreach my $ip ( $self->nameservers ) {
595 11         53 my $sockaddr = $self->_create_dst_sockaddr( $ip, $port );
596 11   100     41 my $socket = $self->_create_udp_socket($ip) || next;
597              
598 9         51 $self->_diag( 'bgsend', "[$ip]:$port" );
599              
600 9         49 $socket->send( $packet_data, 0, $sockaddr );
601 9         1145 $self->errorstring($!);
602              
603             # handle failure to detect taint inside $socket->send()
604 9         17 die 'Insecure dependency while running with -T switch'
605             if TESTS && Scalar::Util::tainted($sockaddr);
606              
607 9         33 my $expire = time() + $self->{udp_timeout};
608 9         27 ${*$socket}{net_dns_bg} = [$expire, $packet];
  9         47  
609 9         50 return $socket;
610             }
611              
612 1         12 return;
613             }
614              
615              
616             sub bgbusy { ## no critic # overwrites user UDP handle
617 11872     11872 1 4569869 my ( $self, $handle ) = @_;
618 11872 100       22062 return unless $handle;
619              
620 11870   100     14979 my $appendix = ${*$handle}{net_dns_bg} ||= [time() + $self->{udp_timeout}];
  11870         32165  
621 11870         23185 my ( $expire, $query, $read ) = @$appendix;
622 11870 100       22006 return if ref($read);
623              
624 11869 100       23526 return time() <= $expire unless IO::Select->new($handle)->can_read(0);
625              
626 15 100       2376 return unless $query; # SpamAssassin 3.4.1 workaround
627 14 100       83 return if $self->{igntc};
628 11 100       74 return unless $handle->socktype() == SOCK_DGRAM;
629              
630 5         132 my $ans = $self->_bgread($handle);
631 5         23 $$appendix[2] = [$ans];
632 5 100       20 return unless $ans;
633 4 100       12 return unless $ans->header->tc;
634              
635 2         7 $self->_diag('packet truncated: retrying using TCP');
636 2   100     8 my $tcp = $self->_bgsend_tcp( $query, $query->data ) || return;
637 1         6 return defined( $_[1] = $tcp ); # caller's UDP handle now TCP
638             }
639              
640              
641             sub bgisready { ## historical
642 1     1 0 29 __PACKAGE__->_deprecate('prefer ! bgbusy(...)'); # uncoverable pod
643 1         12 return !&bgbusy;
644             }
645              
646              
647             sub bgread {
648 12     12 1 1920 my ( $self, $handle ) = @_;
649 12         54 while (&bgbusy) { # side effect: TCP retry
650 11850         441262 IO::Select->new($handle)->can_read(0.02); # reduce my CPU usage by 3 orders of magnitude
651             }
652 12         152 return &_bgread;
653             }
654              
655              
656             sub _bgread {
657 17     17   49 my ( $self, $handle ) = @_;
658 17 100       59 return unless $handle;
659              
660 16         34 my $appendix = ${*$handle}{net_dns_bg};
  16         66  
661 16         57 my ( $expire, $query, $read ) = @$appendix;
662 16 100       78 return shift(@$read) if ref($read);
663              
664 12         48 my $select = IO::Select->new($handle);
665 12 100       576 unless ( $select->can_read(0) ) {
666 1         22 $self->errorstring('timed out');
667 1         12 return;
668             }
669              
670 11         482 my $peer = $self->{replyfrom} = $handle->peerhost;
671              
672 11         670 my $dgram = $handle->socktype() == SOCK_DGRAM;
673 11 100       178 my $buffer = $dgram ? _read_udp( $handle, $self->_packetsz ) : _read_tcp($handle);
674 11         92 $self->_diag( "reply from [$peer]", length($buffer), 'bytes' );
675              
676 11         137 my $reply = Net::DNS::Packet->decode( \$buffer, $self->{debug} );
677 11         49 $self->errorstring($@);
678 11 100       39 return unless $self->_accept_reply( $reply, $query );
679 10         47 $reply->from($peer);
680              
681 10 100 100     122 return $reply unless $self->{tsig_rr} && !$reply->verify($query);
682 1         8 $self->errorstring( $reply->verifyerr );
683 1         14 return;
684             }
685              
686              
687             sub _accept_reply {
688 131     131   465 my ( $self, $reply, $query ) = @_;
689              
690 131 100       421 return unless $reply;
691              
692 130         522 my $header = $reply->header;
693 130 100       721 return unless $header->qr;
694              
695 129 100 100     720 return if $query && $header->id != $query->header->id;
696              
697 123         650 return $self->errorstring( $header->rcode ); # historical quirk
698             }
699              
700              
701             sub axfr { ## zone transfer
702 9     9 1 2167 my ( $self, @argument ) = @_;
703 9 100       45 my $zone = scalar(@argument) ? shift @argument : $self->domain;
704 9         24 my @class = @argument;
705              
706 9         41 my $request = $self->_make_query_packet( $zone, 'AXFR', @class );
707              
708 8         32 return eval {
709 8         76 $self->_diag("axfr( $zone @class )");
710 8         48 my ( $select, $verify, @rr, $soa ) = $self->_axfr_start($request);
711              
712             my $iterator = sub { ## iterate over RRs
713 2691     2691   10379 my $rr = shift(@rr);
714              
715 2691 100       4844 if ( ref($rr) eq 'Net::DNS::RR::SOA' ) {
716 6 100       38 if ($soa) {
717 3         423 $select = undef;
718 3 100       36 return if $rr->canonical eq $soa->canonical;
719 1         8 croak $self->errorstring('mismatched final SOA');
720             }
721 3         5 $soa = $rr;
722             }
723              
724 2688 100       4289 unless ( scalar @rr ) {
725 31         45 my $reply; # refill @rr
726 31         130 ( $reply, $verify ) = $self->_axfr_next( $select, $verify );
727 31 100       136 @rr = $reply->answer if $reply;
728             }
729              
730 2688         4068 return $rr;
731 3         38 };
732              
733 3 100       20 return $iterator unless wantarray;
734              
735 2         3 my @zone; ## subvert iterator to assemble entire zone
736 2         6 while ( my $rr = $iterator->() ) {
737 22         379 push @zone, $rr, @rr; # copy RRs en bloc
738 22         191 @rr = pop(@zone); # leave last one in @rr
739             }
740 2         961 return @zone;
741             };
742             }
743              
744              
745             sub axfr_start { ## historical
746 1     1 0 27 my ( $self, @argument ) = @_; # uncoverable pod
747 1         8 $self->_deprecate('prefer $iterator = $self->axfr(...)');
748 1         4 my $iterator = $self->axfr(@argument);
749 1     1   57 ( $self->{axfr_iter} ) = grep {defined} ( $iterator, sub {} );
  2         11  
750 1         9 return defined($iterator);
751             }
752              
753              
754             sub axfr_next { ## historical
755 1     1 0 28 my $self = shift; # uncoverable pod
756 1         4 $self->_deprecate('prefer $iterator->()');
757 1         10 return $self->{axfr_iter}->();
758             }
759              
760              
761             sub _axfr_start {
762 8     8   25 my ( $self, $request ) = @_;
763 8         35 my $content = $request->data;
764 8         49 my $TCP_msg = pack 'n a*', length($content), $content;
765              
766 8         32 my ( $select, $reply, $rcode );
767 8         37 foreach my $ns ( $self->nameservers ) {
768 11         71 $self->_diag("axfr send [$ns]");
769              
770 11         51 local $self->{persistent_tcp};
771 11         51 my $socket = $self->_create_tcp_socket($ns);
772 11         63 $self->errorstring($!);
773 11   100     117 $select = IO::Select->new( $socket || next );
774              
775 9         1569 $socket->send($TCP_msg);
776 9         1665 $self->errorstring($!);
777              
778 9         47 ($reply) = $self->_axfr_next($select);
779 9 100       56 last if ( $rcode = $reply->header->rcode ) eq 'NOERROR';
780             }
781              
782 8 100       51 croak $self->errorstring unless $reply;
783              
784 6         35 $self->errorstring($rcode); # historical quirk
785              
786 6 100       32 my $verify = $request->sigrr ? $request : undef;
787 6 100       32 unless ($verify) {
788 3 100       16 croak $self->errorstring unless $rcode eq 'NOERROR';
789 2         12 return ( $select, $verify, $reply->answer );
790             }
791              
792 3         18 my $verifyok = $reply->verify($verify);
793 3 100       23 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   395 my $self = shift;
801 43   100     138 my $select = shift || return;
802 42         79 my $verify = shift;
803              
804 42         192 my ($socket) = $select->can_read( $self->{tcp_timeout} );
805 42 100       179661 croak $self->errorstring('timed out') unless $socket;
806              
807 41         127 my $buffer = _read_tcp($socket);
808 41         349 my $packet = Net::DNS::Packet->decode( \$buffer );
809 41 100       139 croak $@, $self->errorstring('corrupt packet') if $@;
810              
811 40 100       213 return ( $packet, $verify ) unless $verify;
812              
813 11         42 my $verifyok = $packet->verify($verify);
814 11 100       53 croak $self->errorstring( $packet->verifyerr ) unless $verifyok;
815 10         110 return ( $packet, $verifyok );
816             }
817              
818              
819             #
820             # Usage: $data = _read_tcp($socket);
821             #
822             sub _read_tcp {
823 57     57   245 my $socket = shift;
824              
825 57         130 my ( $s1, $s2 );
826 57         332 $socket->recv( $s1, 1 ); # two octet length
827 57         179551 $socket->recv( $s2, 2 - length $s1 ); # possibly fragmented
828 57         1726 my $size = unpack 'n', pack( 'a*a*@2', $s1, $s2 );
829              
830 57         158 my $buffer = '';
831 57         102 for ( ; ; ) {
832 62         91 my $fragment;
833 62         289 $socket->recv( $fragment, $size - length($buffer) );
834 62 100 100     55078 last unless length( $buffer .= $fragment || last ) < $size;
835             }
836 57         1340 return $buffer;
837             }
838              
839              
840             #
841             # Usage: $data = _read_udp($socket, $length);
842             #
843             sub _read_udp {
844 111     111   282 my $socket = shift;
845 111         301 my $buffer = '';
846 111         589 $socket->recv( $buffer, shift );
847 111         5156 return $buffer;
848             }
849              
850              
851             sub _create_tcp_socket {
852 31     31   98 my ( $self, $ip ) = @_;
853              
854 31         62 my $socket;
855 31         128 my $sock_key = "TCP[$ip]";
856 31 100       154 if ( $socket = $self->{persistent}{$sock_key} ) {
857 2         7 $self->_diag( 'using persistent socket', $sock_key );
858 2 100       8 return $socket if $socket->connected;
859 1         87 $self->_diag('socket disconnected (trying to connect)');
860             }
861              
862 30         110 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 30 100       404 if USE_SOCKET_IP;
872              
873 30         531099 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 30 100       181 $self->{persistent}{$sock_key} = $socket if $self->{persistent_tcp};
886 30         99 return $socket;
887             }
888              
889              
890             sub _create_udp_socket {
891 182     182   466 my ( $self, $ip ) = @_;
892              
893 182         323 my $socket;
894 182         493 my $sock_key = "UDP[$ip]";
895 182 100       712 return $socket if $socket = $self->{persistent}{$sock_key};
896              
897 181         404 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 181 100       1471 Proto => 'udp',
902             Type => SOCK_DGRAM
903             )
904             if USE_SOCKET_IP;
905              
906 181         98584 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 181 100       646 $self->{persistent}{$sock_key} = $socket if $self->{persistent_udp};
917 181         824 return $socket;
918             }
919              
920              
921             {
922 90     90   229883 no strict 'subs'; ## no critic ProhibitNoStrict
  90         269  
  90         3940  
923 90     90   652 use constant AI_NUMERICHOST => Socket::AI_NUMERICHOST;
  90         254  
  90         6229  
924 90     90   645 use constant IPPROTO_UDP => Socket::IPPROTO_UDP;
  90         261  
  90         150104  
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 214     214   521 my ( $self, $ip, $port ) = @_;
941              
942 214         328 unless (USE_SOCKET_IP) { # NB: errors raised in socket->send
943             return _ipv6($ip) ? undef : sockaddr_in( $port, inet_aton($ip) );
944             }
945              
946 214 100       523 my @addrinfo = Socket::getaddrinfo( $ip, $port, _ipv6($ip) ? $ip6 : $ip4 );
947 214         717 return ( grep {ref} @addrinfo, {} )[0]->{addr};
  642         1959  
948             }
949             }
950              
951              
952             # Lightweight versions of subroutines from Net::IP module, recoded to fix RT#96812
953              
954             sub _ipv4 {
955 2951     2951   5170 for (shift) {
956 2951 100       8162 last if m/[^.0-9]/; # dots and digits only
957 1527         6839 return m/\.\d+\./; # dots separated by digits
958             }
959 1424         3499 return;
960             }
961              
962             sub _ipv6 {
963 2621     2621   4747 for (shift) {
964 2621 100       8242 last unless m/:.*:/; # must contain two colons
965 1558 100       6415 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         8 return m/^[:0-9A-Fa-f]+:[.0-9]+$/; # prefix : dotted digits
968             }
969 1063         4007 return;
970             }
971              
972              
973             sub _make_query_packet {
974 183     183   521 my ( $self, @argument ) = @_;
975              
976 183         426 my ($packet) = @argument;
977 183 100       610 if ( ref($packet) ) {
978 82         252 my $edns = $packet->edns; # advertise UDPsize for local stack
979 82 100       349 $edns->udpsize( $self->{udppacketsize} ) unless defined $edns->{udpsize};
980             } else {
981 101         518 $packet = Net::DNS::Packet->new(@argument);
982 100         350 $packet->edns->udpsize( $self->{udppacketsize} );
983              
984 100         331 my $header = $packet->header;
985 100         561 $header->ad( $self->{adflag} ); # RFC6840, 5.7
986 100         425 $header->cd( $self->{cdflag} ); # RFC6840, 5.9
987 100 100       350 $header->do(1) if $self->{dnssec};
988 100         344 $header->rd( $self->{recurse} );
989             }
990              
991 182 100       620 if ( $self->{tsig_rr} ) {
992 12 100       83 $packet->sign_tsig( $self->{tsig_rr} ) unless $packet->sigrr;
993             }
994              
995 182         532 return $packet;
996             }
997              
998              
999             sub dnssec {
1000 11     11 1 1850 my ( $self, @argument ) = @_;
1001 11         25 for (@argument) {
1002 7         28 $self->udppacketsize(1232);
1003 7         16 $self->{dnssec} = $_;
1004             }
1005 11         37 return $self->{dnssec};
1006             }
1007              
1008              
1009             sub force_v6 {
1010 8     8 1 1675 my ( $self, @value ) = @_;
1011 8 100       20 for (@value) { $self->{force_v4} = 0 if $self->{force_v6} = $_ }
  5         21  
1012 8 100       29 return $self->{force_v6} ? 1 : 0;
1013             }
1014              
1015             sub force_v4 {
1016 9     9 1 1088 my ( $self, @value ) = @_;
1017 9 100       24 for (@value) { $self->{force_v6} = 0 if $self->{force_v4} = $_ }
  6         23  
1018 9 100       32 return $self->{force_v4} ? 1 : 0;
1019             }
1020              
1021             sub prefer_v6 {
1022 8     8 1 1052 my ( $self, @value ) = @_;
1023 8 100       18 for (@value) { $self->{prefer_v4} = 0 if $self->{prefer_v6} = $_ }
  5         21  
1024 8 100       30 return $self->{prefer_v6} ? 1 : 0;
1025             }
1026              
1027             sub prefer_v4 {
1028 6     6 1 1042 my ( $self, @value ) = @_;
1029 6 100       14 for (@value) { $self->{prefer_v6} = 0 if $self->{prefer_v4} = $_ }
  3         13  
1030 6 100       23 return $self->{prefer_v4} ? 1 : 0;
1031             }
1032              
1033             sub srcaddr {
1034 2     2 1 530 my ( $self, @value ) = @_;
1035 2         5 for (@value) {
1036 2 100       5 my $hashkey = _ipv6($_) ? 'srcaddr6' : 'srcaddr4';
1037 2         11 $self->{$hashkey} = $_;
1038             }
1039 2         13 return shift @value;
1040             }
1041              
1042              
1043             sub tsig {
1044 9     9 1 1134 my ( $self, $arg, @etc ) = @_;
1045 9         21 $self->{tsig_rr} = eval {
1046 9 100       29 return $arg unless $arg;
1047 8 100       36 return $arg if ref($arg) eq 'Net::DNS::RR::TSIG';
1048 7         32 local $SIG{__DIE__};
1049 7         1470 require Net::DNS::RR::TSIG;
1050 7         62 Net::DNS::RR::TSIG->create( $arg, @etc );
1051             };
1052 9 100       1504 croak "${@}unable to create TSIG record" if $@;
1053 8         23 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 255   100 255   1216 my $udpsize = shift->{udppacketsize} || 0;
1062 255 100       1291 return $udpsize > PACKETSZ ? $udpsize : PACKETSZ;
1063             }
1064              
1065             sub udppacketsize {
1066 13     13 1 42 my ( $self, @value ) = @_;
1067 13         78 for (@value) { $self->{udppacketsize} = $_ }
  11         26  
1068 13         39 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 49 __PACKAGE__->_deprecate('see RT#37104'); # uncoverable pod
1077 2         8 return &_make_query_packet;
1078             }
1079              
1080              
1081             sub _diag { ## debug output
1082 591 100   591   2129 return unless shift->{debug};
1083 1         39 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   543 @ip = &$parse_dig unless scalar @ip; # once only, on demand
1108 6         224 splice @ip, 0, 0, splice( @ip, int( rand scalar @ip ) ); # cut deck
1109 6         85 return @ip;
1110             }
1111             }
1112              
1113              
1114       1     sub DESTROY { } ## Avoid tickling AUTOLOAD (in cleanup)
1115              
1116             sub AUTOLOAD { ## Default method
1117 42     42   885 my ($self) = @_;
1118              
1119 90     90   818 no strict 'refs'; ## no critic ProhibitNoStrict
  90         266  
  90         20803  
1120 42         61 our $AUTOLOAD;
1121 42         109 my $name = $AUTOLOAD;
1122 42         282 $name =~ s/.*://;
1123 42 100       233 croak qq[unknown method "$name"] unless $public_attr{$name};
1124              
1125 41         232 *{$AUTOLOAD} = sub {
1126 103     103   4656 my $self = shift;
1127 103 100       327 $self = $self->_defaults unless ref($self);
1128 103 100 100     630 $self->{$name} = shift || 0 if scalar @_;
1129 103         462 return $self->{$name};
1130 41         270 };
1131              
1132 41         148 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