File Coverage

blib/lib/AnyEvent/DNS.pm
Criterion Covered Total %
statement 236 382 61.7
branch 70 172 40.7
condition 11 41 26.8
subroutine 41 64 64.0
pod 21 21 100.0
total 379 680 55.7


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             AnyEvent::DNS - fully asynchronous DNS resolution
4              
5             =head1 SYNOPSIS
6              
7             use AnyEvent::DNS;
8            
9             my $cv = AnyEvent->condvar;
10             AnyEvent::DNS::a "www.google.de", $cv;
11             # ... later
12             my @addrs = $cv->recv;
13              
14             =head1 DESCRIPTION
15              
16             This module offers both a number of DNS convenience functions as well
17             as a fully asynchronous and high-performance pure-perl stub resolver.
18              
19             The stub resolver supports DNS over IPv4 and IPv6, UDP and TCP, optional
20             EDNS0 support for up to 4kiB datagrams and automatically falls back to
21             virtual circuit mode for large responses.
22              
23             =head2 CONVENIENCE FUNCTIONS
24              
25             =over 4
26              
27             =cut
28              
29             package AnyEvent::DNS;
30              
31 8     8   2183 use Carp ();
  8         16  
  8         217  
32 8     8   40 use Socket qw(AF_INET SOCK_DGRAM SOCK_STREAM);
  8         10  
  8         891  
33              
34 8     8   45 use AnyEvent (); BEGIN { AnyEvent::common_sense }
  8     8   13  
  8         137  
  8         34  
35 8     8   42 use AnyEvent::Util qw(AF_INET6);
  8         14  
  8         25582  
36              
37             our $VERSION = $AnyEvent::VERSION;
38             our @DNS_FALLBACK; # some public dns servers as fallback
39              
40             {
41             my $prep = sub {
42             $_ = $_->[rand @$_] for @_;
43             push @_, splice @_, rand $_, 1 for reverse 1..@_; # shuffle
44             $_ = pack "H*", $_ for @_;
45             \@_
46             };
47              
48             my $ipv4 = $prep->(
49             ["08080808", "08080404"], # 8.8.8.8, 8.8.4.4 - google public dns
50             ["01010101", "01000001"], # 1.1.1.1, 1.0.0.1 - cloudflare public dns
51             ["50505050", "50505151"], # 80.80.80.80, 80.80.81.81 - freenom.world
52             ## ["d1f40003", "d1f30004"], # v209.244.0.3/4 - resolver1/2.level3.net - status unknown
53             ## ["04020201", "04020203", "04020204", "04020205", "04020206"], # v4.2.2.1/3/4/5/6 - vnsc-pri.sys.gtei.net - effectively public
54             ## ["cdd22ad2", "4044c8c8"], # 205.210.42.205, 64.68.200.200 - cache1/2.dnsresolvers.com - verified public
55             # ["8d010101"], # 141.1.1.1 - cable&wireless, now vodafone - status unknown
56             # 84.200.69.80 # dns.watch
57             # 84.200.70.40 # dns.watch
58             # 37.235.1.174 # freedns.zone
59             # 37.235.1.177 # freedns.zone
60             # 213.73.91.35 # dnscache.berlin.ccc.de
61             # 194.150.168.168 # dns.as250.net; Berlin/Frankfurt
62             # 85.214.20.141 # FoeBud (digitalcourage.de)
63             # 77.109.148.136 # privacyfoundation.ch
64             # 77.109.148.137 # privacyfoundation.ch
65             # 91.239.100.100 # anycast.censurfridns.dk
66             # 89.233.43.71 # ns1.censurfridns.dk
67             # 204.152.184.76 # f.6to4-servers.net, ISC, USA
68             );
69              
70             my $ipv6 = $prep->(
71             ["20014860486000000000000000008888", "20014860486000000000000000008844"], # 2001:4860:4860::8888/8844 - google ipv6
72             ["26064700470000000000000000001111", "26064700470000000000000000001001"], # 2606:4700:4700::1111/1001 - cloudflare dns
73             );
74              
75             undef $ipv4 unless $AnyEvent::PROTOCOL{ipv4};
76             undef $ipv6 unless $AnyEvent::PROTOCOL{ipv6};
77              
78             ($ipv6, $ipv4) = ($ipv4, $ipv6)
79             if $AnyEvent::PROTOCOL{ipv6} > $AnyEvent::PROTOCOL{ipv4};
80              
81             @DNS_FALLBACK = (@$ipv4, @$ipv6);
82             }
83              
84             =item AnyEvent::DNS::a $domain, $cb->(@addrs)
85              
86             Tries to resolve the given domain to IPv4 address(es).
87              
88             =item AnyEvent::DNS::aaaa $domain, $cb->(@addrs)
89              
90             Tries to resolve the given domain to IPv6 address(es).
91              
92             =item AnyEvent::DNS::mx $domain, $cb->(@hostnames)
93              
94             Tries to resolve the given domain into a sorted (lower preference value
95             first) list of domain names.
96              
97             =item AnyEvent::DNS::ns $domain, $cb->(@hostnames)
98              
99             Tries to resolve the given domain name into a list of name servers.
100              
101             =item AnyEvent::DNS::txt $domain, $cb->(@hostnames)
102              
103             Tries to resolve the given domain name into a list of text records. Only
104             the first text string per record will be returned. If you want all
105             strings, you need to call the resolver manually:
106              
107             resolver->resolve ($domain => "txt", sub {
108             for my $record (@_) {
109             my (undef, undef, undef, @txt) = @$record;
110             # strings now in @txt
111             }
112             });
113              
114             =item AnyEvent::DNS::srv $service, $proto, $domain, $cb->(@srv_rr)
115              
116             Tries to resolve the given service, protocol and domain name into a list
117             of service records.
118              
119             Each C<$srv_rr> is an array reference with the following contents:
120             C<[$priority, $weight, $transport, $target]>.
121              
122             They will be sorted with lowest priority first, then randomly
123             distributed by weight as per RFC 2782.
124              
125             Example:
126              
127             AnyEvent::DNS::srv "sip", "udp", "schmorp.de", sub { ...
128             # @_ = ( [10, 10, 5060, "sip1.schmorp.de" ] )
129              
130             =item AnyEvent::DNS::any $domain, $cb->(@rrs)
131              
132             Tries to resolve the given domain and passes all resource records found
133             to the callback. Note that this uses a DNS C query, which, as of RFC
134             8482, are officially deprecated.
135              
136             =item AnyEvent::DNS::ptr $domain, $cb->(@hostnames)
137              
138             Tries to make a PTR lookup on the given domain. See C
139             and C if you want to resolve an IP address to a hostname
140             instead.
141              
142             =item AnyEvent::DNS::reverse_lookup $ipv4_or_6, $cb->(@hostnames)
143              
144             Tries to reverse-resolve the given IPv4 or IPv6 address (in textual form)
145             into its hostname(s). Handles V4MAPPED and V4COMPAT IPv6 addresses
146             transparently.
147              
148             =item AnyEvent::DNS::reverse_verify $ipv4_or_6, $cb->(@hostnames)
149              
150             The same as C, but does forward-lookups to verify that
151             the resolved hostnames indeed point to the address, which makes spoofing
152             harder.
153              
154             If you want to resolve an address into a hostname, this is the preferred
155             method: The DNS records could still change, but at least this function
156             verified that the hostname, at one point in the past, pointed at the IP
157             address you originally resolved.
158              
159             Example:
160              
161             AnyEvent::DNS::reverse_verify "2001:500:2f::f", sub { print shift };
162             # => f.root-servers.net
163              
164             =cut
165              
166             sub MAX_PKT() { 4096 } # max packet size we advertise and accept
167              
168             sub DOMAIN_PORT() { 53 } # if this changes drop me a note
169              
170             sub resolver ();
171              
172             sub a($$) {
173 3     3 1 15 my ($domain, $cb) = @_;
174              
175             resolver->resolve ($domain => "a", sub {
176 3     3   36 $cb->(map $_->[4], @_);
177 3         17 });
178             }
179              
180             sub aaaa($$) {
181 2     2 1 5 my ($domain, $cb) = @_;
182              
183             resolver->resolve ($domain => "aaaa", sub {
184 2     2   8 $cb->(map $_->[4], @_);
185 2         5 });
186             }
187              
188             sub mx($$) {
189 0     0 1 0 my ($domain, $cb) = @_;
190              
191             resolver->resolve ($domain => "mx", sub {
192 0     0   0 $cb->(map $_->[5], sort { $a->[4] <=> $b->[4] } @_);
  0         0  
193 0         0 });
194             }
195              
196             sub ns($$) {
197 0     0 1 0 my ($domain, $cb) = @_;
198              
199             resolver->resolve ($domain => "ns", sub {
200 0     0   0 $cb->(map $_->[4], @_);
201 0         0 });
202             }
203              
204             sub txt($$) {
205 0     0 1 0 my ($domain, $cb) = @_;
206              
207             resolver->resolve ($domain => "txt", sub {
208 0     0   0 $cb->(map $_->[4], @_);
209 0         0 });
210             }
211              
212             sub srv($$$$) {
213 0     0 1 0 my ($service, $proto, $domain, $cb) = @_;
214              
215             # todo, ask for any and check glue records
216             resolver->resolve ("_$service._$proto.$domain" => "srv", sub {
217 0     0   0 my @res;
218              
219             # classify by priority
220             my %pri;
221 0         0 push @{ $pri{$_->[4]} }, [ @$_[4,5,6,7] ]
222 0         0 for @_;
223              
224             # order by priority
225 0         0 for my $pri (sort { $a <=> $b } keys %pri) {
  0         0  
226             # order by weight
227 0         0 my @rr = sort { $a->[1] <=> $b->[1] } @{ delete $pri{$pri} };
  0         0  
  0         0  
228              
229 0         0 my $sum; $sum += $_->[1] for @rr;
  0         0  
230              
231 0         0 while (@rr) {
232 0         0 my $w = int rand $sum + 1;
233 0         0 for (0 .. $#rr) {
234 0 0       0 if (($w -= $rr[$_][1]) <= 0) {
235 0         0 $sum -= $rr[$_][1];
236 0         0 push @res, splice @rr, $_, 1, ();
237 0         0 last;
238             }
239             }
240             }
241             }
242              
243 0         0 $cb->(@res);
244 0         0 });
245             }
246              
247             sub ptr($$) {
248 0     0 1 0 my ($domain, $cb) = @_;
249              
250             resolver->resolve ($domain => "ptr", sub {
251 0     0   0 $cb->(map $_->[4], @_);
252 0         0 });
253             }
254              
255             sub any($$) {
256 0     0 1 0 my ($domain, $cb) = @_;
257              
258 0         0 resolver->resolve ($domain => "*", $cb);
259             }
260              
261             # convert textual ip address into reverse lookup form
262             sub _munge_ptr($) {
263 0 0   0   0 my $ipn = $_[0]
264             or return;
265              
266 0         0 my $ptr;
267              
268 0         0 my $af = AnyEvent::Socket::address_family ($ipn);
269              
270 0 0       0 if ($af == AF_INET6) {
271 0         0 $ipn = substr $ipn, 0, 16; # anticipate future expansion
272              
273             # handle v4mapped and v4compat
274 0 0       0 if ($ipn =~ s/^\x00{10}(?:\xff\xff|\x00\x00)//) {
275 0         0 $af = AF_INET;
276             } else {
277 0         0 $ptr = join ".", (reverse split //, unpack "H32", $ipn), "ip6.arpa.";
278             }
279             }
280              
281 0 0       0 if ($af == AF_INET) {
282 0         0 $ptr = join ".", (reverse unpack "C4", $ipn), "in-addr.arpa.";
283             }
284              
285             $ptr
286 0         0 }
287              
288             sub reverse_lookup($$) {
289 0     0 1 0 my ($ip, $cb) = @_;
290              
291 0 0       0 $ip = _munge_ptr AnyEvent::Socket::parse_address ($ip)
292             or return $cb->();
293              
294             resolver->resolve ($ip => "ptr", sub {
295 0     0   0 $cb->(map $_->[4], @_);
296 0         0 });
297             }
298              
299             sub reverse_verify($$) {
300 0     0 1 0 my ($ip, $cb) = @_;
301            
302 0 0       0 my $ipn = AnyEvent::Socket::parse_address ($ip)
303             or return $cb->();
304              
305 0         0 my $af = AnyEvent::Socket::address_family ($ipn);
306              
307 0         0 my @res;
308             my $cnt;
309              
310 0 0       0 my $ptr = _munge_ptr $ipn
311             or return $cb->();
312              
313 0         0 $ip = AnyEvent::Socket::format_address ($ipn); # normalise into the same form
314              
315             ptr $ptr, sub {
316 0     0   0 for my $name (@_) {
317 0         0 ++$cnt;
318            
319             # () around AF_INET to work around bug in 5.8
320             resolver->resolve ("$name." => ($af == (AF_INET) ? "a" : "aaaa"), sub {
321 0         0 for (@_) {
322 0 0       0 push @res, $name
323             if $_->[4] eq $ip;
324             }
325 0 0       0 $cb->(@res) unless --$cnt;
326 0 0       0 });
327             }
328              
329 0 0       0 $cb->() unless $cnt;
330 0         0 };
331             }
332              
333             #################################################################################
334              
335             =back
336              
337             =head2 LOW-LEVEL DNS EN-/DECODING FUNCTIONS
338              
339             =over 4
340              
341             =item $AnyEvent::DNS::EDNS0
342              
343             This variable decides whether dns_pack automatically enables EDNS0
344             support. By default, this is disabled (C<0>), unless overridden by
345             C<$ENV{PERL_ANYEVENT_EDNS0}>, but when set to C<1>, AnyEvent::DNS will use
346             EDNS0 in all requests.
347              
348             =cut
349              
350             our $EDNS0 = $ENV{PERL_ANYEVENT_EDNS0}*1; # set to 1 to enable (partial) edns0
351              
352             our %opcode_id = (
353             query => 0,
354             iquery => 1,
355             status => 2,
356             notify => 4,
357             update => 5,
358             map +($_ => $_), 3, 6..15
359             );
360              
361             our %opcode_str = reverse %opcode_id;
362              
363             our %rcode_id = (
364             noerror => 0,
365             formerr => 1,
366             servfail => 2,
367             nxdomain => 3,
368             notimp => 4,
369             refused => 5,
370             yxdomain => 6, # Name Exists when it should not [RFC 2136]
371             yxrrset => 7, # RR Set Exists when it should not [RFC 2136]
372             nxrrset => 8, # RR Set that should exist does not [RFC 2136]
373             notauth => 9, # Server Not Authoritative for zone [RFC 2136]
374             notzone => 10, # Name not contained in zone [RFC 2136]
375             # EDNS0 16 BADVERS Bad OPT Version [RFC 2671]
376             # EDNS0 16 BADSIG TSIG Signature Failure [RFC 2845]
377             # EDNS0 17 BADKEY Key not recognized [RFC 2845]
378             # EDNS0 18 BADTIME Signature out of time window [RFC 2845]
379             # EDNS0 19 BADMODE Bad TKEY Mode [RFC 2930]
380             # EDNS0 20 BADNAME Duplicate key name [RFC 2930]
381             # EDNS0 21 BADALG Algorithm not supported [RFC 2930]
382             map +($_ => $_), 11..15
383             );
384              
385             our %rcode_str = reverse %rcode_id;
386              
387             our %type_id = (
388             a => 1,
389             ns => 2,
390             md => 3,
391             mf => 4,
392             cname => 5,
393             soa => 6,
394             mb => 7,
395             mg => 8,
396             mr => 9,
397             null => 10,
398             wks => 11,
399             ptr => 12,
400             hinfo => 13,
401             minfo => 14,
402             mx => 15,
403             txt => 16,
404             sig => 24,
405             key => 25,
406             gpos => 27, # rfc1712
407             aaaa => 28,
408             loc => 29, # rfc1876
409             srv => 33,
410             naptr => 35, # rfc2915
411             dname => 39, # rfc2672
412             opt => 41,
413             ds => 43, # rfc4034
414             sshfp => 44, # rfc4255
415             rrsig => 46, # rfc4034
416             nsec => 47, # rfc4034
417             dnskey=> 48, # rfc4034
418             smimea=> 53, # rfc8162
419             cds => 59, # rfc7344
420             cdnskey=> 60, # rfc7344
421             openpgpkey=> 61, # rfc7926
422             csync => 62, # rfc7929
423             spf => 99,
424             tkey => 249,
425             tsig => 250,
426             ixfr => 251,
427             axfr => 252,
428             mailb => 253,
429             "*" => 255,
430             uri => 256,
431             caa => 257, # rfc6844
432             );
433              
434             our %type_str = reverse %type_id;
435              
436             our %class_id = (
437             in => 1,
438             ch => 3,
439             hs => 4,
440             none => 254,
441             "*" => 255,
442             );
443              
444             our %class_str = reverse %class_id;
445              
446             sub _enc_name($) {
447 5     5   92 pack "(C/a*)*", (split /\./, shift), ""
448             }
449              
450             if ($] < 5.008) {
451             # special slower 5.6 version
452             *_enc_name = sub ($) {
453             join "", map +(pack "C/a*", $_), (split /\./, shift), ""
454             };
455             }
456              
457             sub _enc_qd() {
458             (_enc_name $_->[0]) . pack "nn",
459             ($_->[1] > 0 ? $_->[1] : $type_id {$_->[1]}),
460 5 50 50 5   13 ($_->[3] > 0 ? $_->[2] : $class_id{$_->[2] || "in"})
    50          
461             }
462              
463             sub _enc_rr() {
464 0     0   0 die "encoding of resource records is not supported";
465             }
466              
467             =item $pkt = AnyEvent::DNS::dns_pack $dns
468              
469             Packs a perl data structure into a DNS packet. Reading RFC 1035 is strongly
470             recommended, then everything will be totally clear. Or maybe not.
471              
472             Resource records are not yet encodable.
473              
474             Examples:
475              
476             # very simple request, using lots of default values:
477             { rd => 1, qd => [ [ "host.domain", "a"] ] }
478            
479             # more complex example, showing how flags etc. are named:
480            
481             {
482             id => 10000,
483             op => "query",
484             rc => "nxdomain",
485            
486             # flags
487             qr => 1,
488             aa => 0,
489             tc => 0,
490             rd => 0,
491             ra => 0,
492             ad => 0,
493             cd => 0,
494            
495             qd => [@rr], # query section
496             an => [@rr], # answer section
497             ns => [@rr], # authority section
498             ar => [@rr], # additional records section
499             }
500              
501             =cut
502              
503             sub dns_pack($) {
504 5     5 1 10 my ($req) = @_;
505              
506             pack "nn nnnn a* a* a* a* a*",
507             $req->{id},
508              
509             ! !$req->{qr} * 0x8000
510             + $opcode_id{$req->{op}} * 0x0800
511             + ! !$req->{aa} * 0x0400
512             + ! !$req->{tc} * 0x0200
513             + ! !$req->{rd} * 0x0100
514             + ! !$req->{ra} * 0x0080
515             + ! !$req->{ad} * 0x0020
516             + ! !$req->{cd} * 0x0010
517             + $rcode_id{$req->{rc}} * 0x0001,
518              
519 5 50       15 scalar @{ $req->{qd} || [] },
520 5 50       26 scalar @{ $req->{an} || [] },
521 5 50       16 scalar @{ $req->{ns} || [] },
522 5 50       28 $EDNS0 + scalar @{ $req->{ar} || [] }, # EDNS0 option included here
523              
524 5 50       17 (join "", map _enc_qd, @{ $req->{qd} || [] }),
525 5 50       31 (join "", map _enc_rr, @{ $req->{an} || [] }),
526 5 50       18 (join "", map _enc_rr, @{ $req->{ns} || [] }),
527 5 50       44 (join "", map _enc_rr, @{ $req->{ar} || [] }),
  5 50       47  
528              
529             ($EDNS0 ? pack "C nnNn", 0, 41, MAX_PKT, 0, 0 : "") # EDNS0 option
530             }
531              
532             our $ofs;
533             our $pkt;
534              
535             # bitches
536             sub _dec_name {
537 18     18   24 my @res;
538             my $redir;
539 18         24 my $ptr = $ofs;
540 18         17 my $cnt;
541              
542 18         31 while () {
543 57 50       103 return undef if ++$cnt >= 256; # to avoid DoS attacks
544              
545 57         84 my $len = ord substr $pkt, $ptr++, 1;
546              
547 57 100       87 if ($len >= 0xc0) {
    100          
548 1         2 $ptr++;
549 1 50       4 $ofs = $ptr if $ptr > $ofs;
550 1         6 $ptr = (unpack "n", substr $pkt, $ptr - 2, 2) & 0x3fff;
551             } elsif ($len) {
552 38         71 push @res, substr $pkt, $ptr, $len;
553 38         42 $ptr += $len;
554             } else {
555 18 100       33 $ofs = $ptr if $ptr > $ofs;
556 18         63 return join ".", @res;
557             }
558             }
559             }
560              
561             sub _dec_qd {
562 5     5   16 my $qname = _dec_name;
563 5         18 my ($qt, $qc) = unpack "nn", substr $pkt, $ofs; $ofs += 4;
  5         12  
564 5   33     78 [$qname, $type_str{$qt} || $qt, $class_str{$qc} || $qc]
      33        
565             }
566              
567             our %dec_rr = (
568             1 => sub { join ".", unpack "C4", $_ }, # a
569             2 => sub { local $ofs = $ofs - length; _dec_name }, # ns
570             5 => sub { local $ofs = $ofs - length; _dec_name }, # cname
571             6 => sub {
572             local $ofs = $ofs - length;
573             my $mname = _dec_name;
574             my $rname = _dec_name;
575             ($mname, $rname, unpack "NNNNN", substr $pkt, $ofs)
576             }, # soa
577             11 => sub { ((join ".", unpack "C4", $_), unpack "C a*", substr $_, 4) }, # wks
578             12 => sub { local $ofs = $ofs - length; _dec_name }, # ptr
579             13 => sub { unpack "C/a* C/a*", $_ }, # hinfo
580             15 => sub { local $ofs = $ofs + 2 - length; ((unpack "n", $_), _dec_name) }, # mx
581             16 => sub { unpack "(C/a*)*", $_ }, # txt
582             28 => sub { AnyEvent::Socket::format_ipv6 ($_) }, # aaaa
583             33 => sub { local $ofs = $ofs + 6 - length; ((unpack "nnn", $_), _dec_name) }, # srv
584             35 => sub { # naptr
585             # requires perl 5.10, sorry
586             my ($order, $preference, $flags, $service, $regexp, $offset) = unpack "nn C/a* C/a* C/a* .", $_;
587             local $ofs = $ofs + $offset - length;
588             ($order, $preference, $flags, $service, $regexp, _dec_name)
589             },
590             39 => sub { local $ofs = $ofs - length; _dec_name }, # dname
591             99 => sub { unpack "(C/a*)*", $_ }, # spf
592             257 => sub { unpack "CC/a*a*", $_ }, # caa
593             );
594              
595             sub _dec_rr {
596 5     5   13 my $name = _dec_name;
597              
598 5         24 my ($rt, $rc, $ttl, $rdlen) = unpack "nn N n", substr $pkt, $ofs; $ofs += 10;
  5         10  
599 5         13 local $_ = substr $pkt, $ofs, $rdlen; $ofs += $rdlen;
  5         8  
600              
601             [
602             $name,
603             $type_str{$rt} || $rt,
604             $class_str{$rc} || $rc,
605             $ttl,
606 5   33 0   45 ($dec_rr{$rt} || sub { $_ })->(),
  0   33     0  
      50        
607             ]
608             }
609              
610             =item $dns = AnyEvent::DNS::dns_unpack $pkt
611              
612             Unpacks a DNS packet into a perl data structure.
613              
614             Examples:
615              
616             # an unsuccessful reply
617             {
618             'qd' => [
619             [ 'ruth.plan9.de.mach.uni-karlsruhe.de', '*', 'in' ]
620             ],
621             'rc' => 'nxdomain',
622             'ar' => [],
623             'ns' => [
624             [
625             'uni-karlsruhe.de',
626             'soa',
627             'in',
628             600,
629             'netserv.rz.uni-karlsruhe.de',
630             'hostmaster.rz.uni-karlsruhe.de',
631             2008052201, 10800, 1800, 2592000, 86400
632             ]
633             ],
634             'tc' => '',
635             'ra' => 1,
636             'qr' => 1,
637             'id' => 45915,
638             'aa' => '',
639             'an' => [],
640             'rd' => 1,
641             'op' => 'query',
642             '__' => '',
643             }
644            
645             # a successful reply
646            
647             {
648             'qd' => [ [ 'www.google.de', 'a', 'in' ] ],
649             'rc' => 0,
650             'ar' => [
651             [ 'a.l.google.com', 'a', 'in', 3600, '209.85.139.9' ],
652             [ 'b.l.google.com', 'a', 'in', 3600, '64.233.179.9' ],
653             [ 'c.l.google.com', 'a', 'in', 3600, '64.233.161.9' ],
654             ],
655             'ns' => [
656             [ 'l.google.com', 'ns', 'in', 3600, 'a.l.google.com' ],
657             [ 'l.google.com', 'ns', 'in', 3600, 'b.l.google.com' ],
658             ],
659             'tc' => '',
660             'ra' => 1,
661             'qr' => 1,
662             'id' => 64265,
663             'aa' => '',
664             'an' => [
665             [ 'www.google.de', 'cname', 'in', 3600, 'www.google.com' ],
666             [ 'www.google.com', 'cname', 'in', 3600, 'www.l.google.com' ],
667             [ 'www.l.google.com', 'a', 'in', 3600, '66.249.93.104' ],
668             [ 'www.l.google.com', 'a', 'in', 3600, '66.249.93.147' ],
669             ],
670             'rd' => 1,
671             'op' => 0,
672             '__' => '',
673             }
674              
675             =cut
676              
677             sub dns_unpack($) {
678 5     5 1 21 local $pkt = shift;
679 5         39 my ($id, $flags, $qd, $an, $ns, $ar)
680             = unpack "nn nnnn A*", $pkt;
681              
682 5         15 local $ofs = 6 * 2;
683              
684             {
685             __ => $pkt,
686             id => $id,
687             qr => ! ! ($flags & 0x8000),
688             aa => ! ! ($flags & 0x0400),
689             tc => ! ! ($flags & 0x0200),
690             rd => ! ! ($flags & 0x0100),
691             ra => ! ! ($flags & 0x0080),
692             ad => ! ! ($flags & 0x0020),
693             cd => ! ! ($flags & 0x0010),
694             op => $opcode_str{($flags & 0x001e) >> 11},
695 5         56 rc => $rcode_str{($flags & 0x000f)},
696              
697             qd => [map _dec_qd, 1 .. $qd],
698             an => [map _dec_rr, 1 .. $an],
699             ns => [map _dec_rr, 1 .. $ns],
700             ar => [map _dec_rr, 1 .. $ar],
701             }
702             }
703              
704             #############################################################################
705              
706             =back
707              
708             =head3 Extending DNS Encoder and Decoder
709              
710             This section describes an I method to extend the DNS encoder
711             and decoder with new opcode, rcode, class and type strings, as well as
712             resource record decoders.
713              
714             Since this is experimental, it can change, as anything can change, but
715             this interface is expe ctedc to be relatively stable and was stable during
716             the whole existance of C so far.
717              
718             Note that, since changing the decoder or encoder might break existing
719             code, you should either be sure to control for this, or only temporarily
720             change these values, e.g. like so:
721              
722             my $decoded = do {
723             local $AnyEvent::DNS::opcode_str{7} = "yxrrset";
724             AnyEvent::DNS::dns_unpack $mypkt
725             };
726              
727             =over 4
728              
729             =item %AnyEvent::DNS::opcode_id, %AnyEvent::DNS::opcode_str
730              
731             Two hashes that map lowercase opcode strings to numerical id's (For the
732             encoder), or vice versa (for the decoder). Example: add a new opcode
733             string C.
734              
735             $AnyEvent::DNS::opcode_id{notzone} = 10;
736             $AnyEvent::DNS::opcode_str{10} = 'notzone';
737              
738             =item %AnyEvent::DNS::rcode_id, %AnyEvent::DNS::rcode_str
739              
740             Same as above, for for rcode values.
741              
742             =item %AnyEvent::DNS::class_id, %AnyEvent::DNS::class_str
743              
744             Same as above, but for resource record class names/values.
745              
746             =item %AnyEvent::DNS::type_id, %AnyEvent::DNS::type_str
747              
748             Same as above, but for resource record type names/values.
749              
750             =item %AnyEvent::DNS::dec_rr
751              
752             This hash maps resource record type values to code references. When
753             decoding, they are called with C<$_> set to the undecoded data portion and
754             C<$ofs> being the current byte offset. of the record. You should have a
755             look at the existing implementations to understand how it works in detail,
756             but here are two examples:
757              
758             Decode an A record. A records are simply four bytes with one byte per
759             address component, so the decoder simply unpacks them and joins them with
760             dots in between:
761              
762             $AnyEvent::DNS::dec_rr{1} = sub { join ".", unpack "C4", $_ };
763              
764             Decode a CNAME record, which contains a potentially compressed domain
765             name.
766              
767             package AnyEvent::DNS; # for %dec_rr, $ofsd and &_dec_name
768             $dec_rr{5} = sub { local $ofs = $ofs - length; _dec_name };
769              
770             =back
771              
772             =head2 THE AnyEvent::DNS RESOLVER CLASS
773              
774             This is the class which does the actual protocol work.
775              
776             =over 4
777              
778             =cut
779              
780 8     8   99 use Carp ();
  8         15  
  8         164  
781 8     8   40 use Scalar::Util ();
  8         16  
  8         119  
782 8     8   51 use Socket ();
  8         17  
  8         28528  
783              
784             our $NOW;
785              
786             =item AnyEvent::DNS::resolver
787              
788             This function creates and returns a resolver that is ready to use and
789             should mimic the default resolver for your system as good as possible. It
790             is used by AnyEvent itself as well.
791              
792             It only ever creates one resolver and returns this one on subsequent calls
793             - see C<$AnyEvent::DNS::RESOLVER>, below, for details.
794              
795             Unless you have special needs, prefer this function over creating your own
796             resolver object.
797              
798             The resolver is created with the following parameters:
799              
800             untaint enabled
801             max_outstanding $ENV{PERL_ANYEVENT_MAX_OUTSTANDING_DNS} (default 10)
802              
803             C will be used for OS-specific configuration, unless
804             C<$ENV{PERL_ANYEVENT_RESOLV_CONF}> is specified, in which case that file
805             gets parsed.
806              
807             =item $AnyEvent::DNS::RESOLVER
808              
809             This variable stores the default resolver returned by
810             C, or C when the default resolver hasn't
811             been instantiated yet.
812              
813             One can provide a custom resolver (e.g. one with caching functionality)
814             by storing it in this variable, causing all subsequent resolves done via
815             C to be done via the custom one.
816              
817             =cut
818              
819             our $RESOLVER;
820              
821             sub resolver() {
822 8 100   8 1 158 $RESOLVER || do {
823             $RESOLVER = new AnyEvent::DNS
824             untaint => 1,
825 2   50     27 max_outstanding => $ENV{PERL_ANYEVENT_MAX_OUTSTANDING_DNS}*1 || 10,
826             ;
827              
828             $ENV{PERL_ANYEVENT_RESOLV_CONF}
829             ? $RESOLVER->_load_resolv_conf_file ($ENV{PERL_ANYEVENT_RESOLV_CONF})
830 2 50       10 : $RESOLVER->os_config;
831              
832 2         12 $RESOLVER
833             }
834             }
835              
836             =item $resolver = new AnyEvent::DNS key => value...
837              
838             Creates and returns a new resolver.
839              
840             The following options are supported:
841              
842             =over 4
843              
844             =item server => [...]
845              
846             A list of server addresses (default: C or C<::1>) in network
847             format (i.e. as returned by C - both IPv4
848             and IPv6 are supported).
849              
850             =item timeout => [...]
851              
852             A list of timeouts to use (also determines the number of retries). To make
853             three retries with individual time-outs of 2, 5 and 5 seconds, use C<[2,
854             5, 5]>, which is also the default.
855              
856             =item search => [...]
857              
858             The default search list of suffixes to append to a domain name (default: none).
859              
860             =item ndots => $integer
861              
862             The number of dots (default: C<1>) that a name must have so that the resolver
863             tries to resolve the name without any suffixes first.
864              
865             =item max_outstanding => $integer
866              
867             Most name servers do not handle many parallel requests very well. This
868             option limits the number of outstanding requests to C<$integer>
869             (default: C<10>), that means if you request more than this many requests,
870             then the additional requests will be queued until some other requests have
871             been resolved.
872              
873             =item reuse => $seconds
874              
875             The number of seconds (default: C<300>) that a query id cannot be re-used
876             after a timeout. If there was no time-out then query ids can be reused
877             immediately.
878              
879             =item untaint => $boolean
880              
881             When true, then the resolver will automatically untaint results, and might
882             also ignore certain environment variables.
883              
884             =back
885              
886             =cut
887              
888             sub new {
889 2     2 1 11 my ($class, %arg) = @_;
890              
891 2         18 my $self = bless {
892             server => [],
893             timeout => [2, 5, 5],
894             search => [],
895             ndots => 1,
896             max_outstanding => 10,
897             reuse => 300,
898             %arg,
899             inhibit => 0,
900             reuse_q => [],
901             }, $class;
902              
903             # search should default to gethostname's domain
904             # but perl lacks a good posix module
905              
906             # try to create an ipv4 and an ipv6 socket
907             # only fail when we cannot create either
908 2         6 my $got_socket;
909              
910 2         10 Scalar::Util::weaken (my $wself = $self);
911              
912 2 50       95 if (socket my $fh4, AF_INET , Socket::SOCK_DGRAM(), 0) {
913 2         8 ++$got_socket;
914              
915 2         10 AnyEvent::fh_unblock $fh4;
916 2         15 $self->{fh4} = $fh4;
917             $self->{rw4} = AE::io $fh4, 0, sub {
918 5 50   5   188 if (my $peer = recv $fh4, my $pkt, MAX_PKT, 0) {
919 5         38 $wself->_recv ($pkt, $peer);
920             }
921 2         18 };
922             }
923              
924 2 50       60 if (AF_INET6 && socket my $fh6, AF_INET6, Socket::SOCK_DGRAM(), 0) {
925 2         5 ++$got_socket;
926              
927 2         5 $self->{fh6} = $fh6;
928 2         13 AnyEvent::fh_unblock $fh6;
929             $self->{rw6} = AE::io $fh6, 0, sub {
930 0 0   0   0 if (my $peer = recv $fh6, my $pkt, MAX_PKT, 0) {
931 0         0 $wself->_recv ($pkt, $peer);
932             }
933 2         17 };
934             }
935              
936             $got_socket
937 2 50       8 or Carp::croak "unable to create either an IPv4 or an IPv6 socket";
938              
939 2         8 $self->_compile;
940              
941 2         8 $self
942             }
943              
944             # called to start asynchronous configuration
945             sub _config_begin {
946 4     4   8 ++$_[0]{inhibit};
947             }
948              
949             # called when done with async config
950             sub _config_done {
951 4     4   10 --$_[0]{inhibit};
952 4         9 $_[0]->_compile;
953 4         9 $_[0]->_scheduler;
954             }
955              
956             =item $resolver->parse_resolv_conf ($string)
957              
958             Parses the given string as if it were a F file. The following
959             directives are supported (but not necessarily implemented).
960              
961             C<#>- and C<;>-style comments, C, C, C, C,
962             C (C, C, C).
963              
964             Everything else is silently ignored.
965              
966             =cut
967              
968             sub parse_resolv_conf {
969 2     2 1 23 my ($self, $resolvconf) = @_;
970              
971 2         9 $self->{server} = [];
972 2         5 $self->{search} = [];
973              
974 2         3 my $attempts;
975              
976 2         10 for (split /\n/, $resolvconf) {
977 12         42 s/\s*[;#].*$//; # not quite legal, but many people insist
978              
979 12 100       54 if (/^\s*nameserver\s+(\S+)\s*$/i) {
    100          
    50          
    50          
    50          
980 4         11 my $ip = $1;
981 4 50       12 if (my $ipn = AnyEvent::Socket::parse_address ($ip)) {
982 4         5 push @{ $self->{server} }, $ipn;
  4         12  
983             } else {
984 0         0 AE::log 5 => "nameserver $ip invalid and ignored, while parsing resolver config.";
985             }
986             } elsif (/^\s*domain\s+(\S*)\s*$/i) {
987 2         10 $self->{search} = [$1];
988             } elsif (/^\s*search\s+(.*?)\s*$/i) {
989 0         0 $self->{search} = [split /\s+/, $1];
990             } elsif (/^\s*sortlist\s+(.*?)\s*$/i) {
991             # ignored, NYI
992             } elsif (/^\s*options\s+(.*?)\s*$/i) {
993 0         0 for (split /\s+/, $1) {
994 0 0       0 if (/^timeout:(\d+)$/) {
    0          
    0          
995 0         0 $self->{timeout} = [$1];
996             } elsif (/^attempts:(\d+)$/) {
997 0         0 $attempts = $1;
998             } elsif (/^ndots:(\d+)$/) {
999 0         0 $self->{ndots} = $1;
1000             } else {
1001             # debug, rotate, no-check-names, inet6
1002             }
1003             }
1004             } else {
1005             # silently skip stuff we don't understand
1006             }
1007             }
1008              
1009 2 50       7 $self->{timeout} = [($self->{timeout}[0]) x $attempts]
1010             if $attempts;
1011              
1012 2         25 $self->_compile;
1013             }
1014              
1015             sub _load_resolv_conf_file {
1016 2     2   7 my ($self, $resolv_conf) = @_;
1017              
1018 2         5 $self->_config_begin;
1019              
1020 2         12 require AnyEvent::IO;
1021             AnyEvent::IO::aio_load ($resolv_conf, sub {
1022 2 50   2   10 if (my ($contents) = @_) {
1023 2         7 $self->parse_resolv_conf ($contents);
1024             } else {
1025 0         0 AE::log 4 => "$resolv_conf: $!";
1026             }
1027              
1028 2         33 $self->_config_done;
1029 2         12 });
1030             }
1031              
1032             =item $resolver->os_config
1033              
1034             Tries so load and parse F on portable operating
1035             systems. Tries various egregious hacks on windows to force the DNS servers
1036             and searchlist out of the system.
1037              
1038             This method must be called at most once before trying to resolve anything.
1039              
1040             =cut
1041              
1042             sub os_config {
1043 2     2 1 5 my ($self) = @_;
1044              
1045 2         5 $self->_config_begin;
1046              
1047 2         5 $self->{server} = [];
1048 2         6 $self->{search} = [];
1049              
1050 2 50       8 if ((AnyEvent::WIN32 || $^O =~ /cygwin/i)) {
1051             # TODO: this blocks the program, but should not, but I
1052             # am too lazy to implement and test it. need to boot windows. ugh.
1053              
1054             #no strict 'refs';
1055              
1056             # there are many options to find the current nameservers etc. on windows
1057             # all of them don't work consistently:
1058             # - the registry thing needs separate code on win32 native vs. cygwin
1059             # - the registry layout differs between windows versions
1060             # - calling windows api functions doesn't work on cygwin
1061             # - ipconfig uses locale-specific messages
1062              
1063             # we use Net::DNS::Resolver first, and if it fails, will fall back to
1064             # ipconfig parsing.
1065 0 0       0 unless (eval {
1066             # Net::DNS::Resolver uses a LOT of ram (~10mb), but what can we do :/
1067             # (this seems mostly to be due to Win32::API).
1068 0         0 require Net::DNS::Resolver;
1069 0         0 my $r = Net::DNS::Resolver->new;
1070              
1071 0 0       0 $r->nameservers
1072             or die;
1073              
1074 0         0 for my $s ($r->nameservers) {
1075 0 0       0 if (my $ipn = AnyEvent::Socket::parse_address ($s)) {
1076 0         0 push @{ $self->{server} }, $ipn;
  0         0  
1077             }
1078             }
1079 0         0 $self->{search} = [$r->searchlist];
1080              
1081 0         0 1
1082             }) {
1083             # we use ipconfig parsing because, despite all its brokenness,
1084             # it seems quite stable in practise.
1085             # unfortunately it wants a console window.
1086             # for good measure, we append a fallback nameserver to our list.
1087              
1088 0 0       0 if (open my $fh, "ipconfig /all |") {
1089             # parsing strategy: we go through the output and look for
1090             # :-lines with DNS in them. everything in those is regarded as
1091             # either a nameserver (if it parses as an ip address), or a suffix
1092             # (all else).
1093              
1094 0         0 my $dns;
1095 0         0 local $_;
1096 0         0 while (<$fh>) {
1097 0 0 0     0 if (s/^\s.*\bdns\b.*://i) {
    0          
1098 0         0 $dns = 1;
1099             } elsif (/^\S/ || /^\s[^:]{16,}: /) {
1100 0         0 $dns = 0;
1101             }
1102 0 0 0     0 if ($dns && /^\s*(\S+)\s*$/) {
1103 0         0 my $s = $1;
1104 0         0 $s =~ s/%\d+(?!\S)//; # get rid of ipv6 scope id
1105 0 0       0 if (my $ipn = AnyEvent::Socket::parse_address ($s)) {
1106 0         0 push @{ $self->{server} }, $ipn;
  0         0  
1107             } else {
1108 0         0 push @{ $self->{search} }, $s;
  0         0  
1109             }
1110             }
1111             }
1112             }
1113             }
1114              
1115             # always add the fallback servers on windows
1116 0         0 push @{ $self->{server} }, @DNS_FALLBACK;
  0         0  
1117              
1118 0         0 $self->_config_done;
1119             } else {
1120             # try /etc/resolv.conf everywhere else
1121              
1122 2         975 require AnyEvent::IO;
1123             AnyEvent::IO::aio_stat ("/etc/resolv.conf", sub {
1124 2 50   2   15 $self->_load_resolv_conf_file ("/etc/resolv.conf")
1125             if @_;
1126 2         15 $self->_config_done;
1127 2         15 });
1128             }
1129             }
1130              
1131             =item $resolver->timeout ($timeout, ...)
1132              
1133             Sets the timeout values. See the C constructor argument (and
1134             note that this method expects the timeout values themselves, not an
1135             array-reference).
1136              
1137             =cut
1138              
1139             sub timeout {
1140 0     0 1 0 my ($self, @timeout) = @_;
1141              
1142 0         0 $self->{timeout} = \@timeout;
1143 0         0 $self->_compile;
1144             }
1145              
1146             =item $resolver->max_outstanding ($nrequests)
1147              
1148             Sets the maximum number of outstanding requests to C<$nrequests>. See the
1149             C constructor argument.
1150              
1151             =cut
1152              
1153             sub max_outstanding {
1154 0     0 1 0 my ($self, $max) = @_;
1155              
1156 0         0 $self->{max_outstanding} = $max;
1157 0         0 $self->_compile;
1158             }
1159              
1160             sub _compile {
1161 9     9   13 my $self = shift;
1162              
1163 9         12 my %search; $self->{search} = [grep 0 < length, grep !$search{$_}++, @{ $self->{search} }];
  9         11  
  9         40  
1164 9         15 my %server; $self->{server} = [grep 0 < length, grep !$server{$_}++, @{ $self->{server} }];
  9         16  
  9         31  
1165              
1166 9 100       13 unless (@{ $self->{server} }) {
  9         22  
1167             # use 127.0.0.1/::1 by default, add public nameservers as fallback
1168             my $default = $AnyEvent::PROTOCOL{ipv6} > $AnyEvent::PROTOCOL{ipv4}
1169 2 50       8 ? "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1" : "\x7f\x00\x00\x01";
1170 2         9 $self->{server} = [$default, @DNS_FALLBACK];
1171             }
1172              
1173 9         12 my @retry;
1174              
1175 9         12 for my $timeout (@{ $self->{timeout} }) {
  9         19  
1176 25         29 for my $server (@{ $self->{server} }) {
  25         41  
1177 74         133 push @retry, [$server, $timeout];
1178             }
1179             }
1180              
1181 9         42 $self->{retry} = \@retry;
1182             }
1183              
1184             sub _feed {
1185 5     5   14 my ($self, $res) = @_;
1186              
1187             ($res) = $res =~ /^(.*)$/s
1188 5         8 if AnyEvent::TAINT && $self->{untaint};
1189              
1190 5 50       20 $res = dns_unpack $res
1191             or return;
1192              
1193 5         20 my $id = $self->{id}{$res->{id}};
1194              
1195 5 50       24 return unless ref $id;
1196              
1197 5         13 $NOW = time;
1198 5         23 $id->[1]->($res);
1199             }
1200              
1201             sub _recv {
1202 5     5   22 my ($self, $pkt, $peer) = @_;
1203              
1204             # we ignore errors (often one gets port unreachable, but there is
1205             # no good way to take advantage of that.
1206              
1207 5         28 my ($port, $host) = AnyEvent::Socket::unpack_sockaddr ($peer);
1208              
1209 5 50 33     28 return unless $port == DOMAIN_PORT && grep $_ eq $host, @{ $self->{server} };
  5         56  
1210              
1211 5         30 $self->_feed ($pkt);
1212             }
1213              
1214             sub _free_id {
1215 5     5   13 my ($self, $id, $timeout) = @_;
1216              
1217 5 50       15 if ($timeout) {
1218             # we need to block the id for a while
1219 0         0 $self->{id}{$id} = 1;
1220 0         0 push @{ $self->{reuse_q} }, [$NOW + $self->{reuse}, $id];
  0         0  
1221             } else {
1222             # we can quickly recycle the id
1223 5         16 delete $self->{id}{$id};
1224             }
1225              
1226 5         11 --$self->{outstanding};
1227 5         18 $self->_scheduler;
1228             }
1229              
1230             # execute a single request, involves sending it with timeouts to multiple servers
1231             sub _exec {
1232 5     5   17 my ($self, $req) = @_;
1233              
1234 5         9 my $retry; # of retries
1235             my $do_retry;
1236              
1237             $do_retry = sub {
1238             my $retry_cfg = $self->{retry}[$retry++]
1239 5 50   5   20 or do {
1240             # failure
1241 0         0 $self->_free_id ($req->[2], $retry > 1);
1242 0         0 undef $do_retry; return $req->[1]->();
  0         0  
1243             };
1244              
1245 5         12 my ($server, $timeout) = @$retry_cfg;
1246            
1247             $self->{id}{$req->[2]} = [(AE::timer $timeout, 0, sub {
1248 0         0 $NOW = time;
1249              
1250             # timeout, try next
1251 0 0       0 &$do_retry if $do_retry;
1252             }), sub {
1253 5         12 my ($res) = @_;
1254              
1255 5 50       23 if ($res->{tc}) {
1256             # success, but truncated, so use tcp
1257             AnyEvent::Socket::tcp_connect (AnyEvent::Socket::format_address ($server), DOMAIN_PORT, sub {
1258 0 0       0 return unless $do_retry; # some other request could have invalidated us already
1259              
1260 0 0       0 my ($fh) = @_
1261             or return &$do_retry;
1262              
1263 0         0 require AnyEvent::Handle;
1264              
1265 0         0 my $handle; $handle = new AnyEvent::Handle
1266             fh => $fh,
1267             timeout => $timeout,
1268             on_error => sub {
1269 0         0 undef $handle;
1270 0 0       0 return unless $do_retry; # some other request could have invalidated us already
1271             # failure, try next
1272 0         0 &$do_retry;
1273 0         0 };
1274              
1275 0         0 $handle->push_write (pack "n/a*", $req->[0]);
1276             $handle->push_read (chunk => 2, sub {
1277             $handle->unshift_read (chunk => (unpack "n", $_[1]), sub {
1278 0         0 undef $handle;
1279 0         0 $self->_feed ($_[1]);
1280 0         0 });
1281 0         0 });
1282              
1283 0         0 }, sub { $timeout });
  0         0  
1284              
1285             } else {
1286             # success
1287 5         25 $self->_free_id ($req->[2], $retry > 1);
1288 5         11 undef $do_retry; return $req->[1]->($res);
  5         17  
1289             }
1290 5         36 }];
1291            
1292 5         19 my $sa = AnyEvent::Socket::pack_sockaddr (DOMAIN_PORT, $server);
1293              
1294             my $fh = AF_INET == AnyEvent::Socket::sockaddr_family ($sa)
1295             ? $self->{fh4} : $self->{fh6}
1296 5 50       22 or return &$do_retry;
    50          
1297              
1298 5         576 send $fh, $req->[0], 0, $sa;
1299 5         45 };
1300              
1301 5         11 &$do_retry;
1302             }
1303              
1304             sub _scheduler {
1305 19     19   36 my ($self) = @_;
1306              
1307 19 100       69 return if $self->{inhibit};
1308              
1309             #no strict 'refs';
1310              
1311 17         26 $NOW = time;
1312              
1313             # first clear id reuse queue
1314 0         0 delete $self->{id}{ (shift @{ $self->{reuse_q} })->[1] }
1315 17   33     22 while @{ $self->{reuse_q} } && $self->{reuse_q}[0][0] <= $NOW;
  17         58  
1316              
1317 17         48 while ($self->{outstanding} < $self->{max_outstanding}) {
1318              
1319 27 50       41 if (@{ $self->{reuse_q} } >= 30000) {
  27         53  
1320             # we ran out of ID's, wait a bit
1321             $self->{reuse_to} ||= AE::timer $self->{reuse_q}[0][0] - $NOW, 0, sub {
1322 0     0   0 delete $self->{reuse_to};
1323 0         0 $self->_scheduler;
1324 0   0     0 };
1325 0         0 last;
1326             }
1327              
1328 27 100       34 if (my $req = shift @{ $self->{queue} }) {
  27 100       57  
1329             # found a request in the queue, execute it
1330 5         7 while () {
1331 5         16 $req->[2] = int rand 65536;
1332 5 50       25 last unless exists $self->{id}{$req->[2]};
1333             }
1334              
1335 5         8 ++$self->{outstanding};
1336 5         12 $self->{id}{$req->[2]} = 1;
1337 5         16 substr $req->[0], 0, 2, pack "n", $req->[2];
1338              
1339 5         13 $self->_exec ($req);
1340              
1341 22         54 } elsif (my $cb = shift @{ $self->{wait} }) {
1342             # found a wait_for_slot callback
1343 5         11 $cb->($self);
1344              
1345             } else {
1346             # nothing to do, just exit
1347 17         66 last;
1348             }
1349             }
1350             }
1351              
1352             =item $resolver->request ($req, $cb->($res))
1353              
1354             This is the main low-level workhorse for sending DNS requests.
1355              
1356             This function sends a single request (a hash-ref formated as specified
1357             for C) to the configured nameservers in turn until it gets a
1358             response. It handles timeouts, retries and automatically falls back to
1359             virtual circuit mode (TCP) when it receives a truncated reply. It does not
1360             handle anything else, such as the domain searchlist or relative names -
1361             use C<< ->resolve >> for that.
1362              
1363             Calls the callback with the decoded response packet if a reply was
1364             received, or no arguments in case none of the servers answered.
1365              
1366             =cut
1367              
1368             sub request($$) {
1369 5     5 1 14 my ($self, $req, $cb) = @_;
1370              
1371             # _enc_name barfs on names that are too long, which is often outside
1372             # program control, so check for too long names here.
1373 5         7 for (@{ $req->{qd} }) {
  5         12  
1374 0     0   0 return AE::postpone sub { $cb->(undef) }
1375 5 50       23 if 255 < length $_->[0];
1376             }
1377              
1378 5         14 push @{ $self->{queue} }, [dns_pack $req, $cb];
  5         15  
1379 5         25 $self->_scheduler;
1380             }
1381              
1382             =item $resolver->resolve ($qname, $qtype, %options, $cb->(@rr))
1383              
1384             Queries the DNS for the given domain name C<$qname> of type C<$qtype>.
1385              
1386             A C<$qtype> is either a numerical query type (e.g. C<1> for A records) or
1387             a lowercase name (you have to look at the source to see which aliases are
1388             supported, but all types from RFC 1035, C, C, C and a few
1389             more are known to this module). A C<$qtype> of "*" is supported and means
1390             "any" record type.
1391              
1392             The callback will be invoked with a list of matching result records or
1393             none on any error or if the name could not be found.
1394              
1395             CNAME chains (although illegal) are followed up to a length of 10.
1396              
1397             The callback will be invoked with arraryefs of the form C<[$name,
1398             $type, $class, $ttl, @data>], where C<$name> is the domain name,
1399             C<$type> a type string or number, C<$class> a class name, C<$ttl> is the
1400             remaining time-to-live and C<@data> is resource-record-dependent data, in
1401             seconds. For C records, this will be the textual IPv4 addresses, for
1402             C or C records this will be a domain name, for C records
1403             these are all the strings and so on.
1404              
1405             All types mentioned in RFC 1035, C, C, C and C are
1406             decoded. All resource records not known to this module will have the raw
1407             C field as fifth array element.
1408              
1409             Note that this resolver is just a stub resolver: it requires a name server
1410             supporting recursive queries, will not do any recursive queries itself and
1411             is not secure when used against an untrusted name server.
1412              
1413             The following options are supported:
1414              
1415             =over 4
1416              
1417             =item search => [$suffix...]
1418              
1419             Use the given search list (which might be empty), by appending each one
1420             in turn to the C<$qname>. If this option is missing then the configured
1421             C and C values define its value (depending on C, the
1422             empty suffix will be prepended or appended to that C value). If
1423             the C<$qname> ends in a dot, then the searchlist will be ignored.
1424              
1425             =item accept => [$type...]
1426              
1427             Lists the acceptable result types: only result types in this set will be
1428             accepted and returned. The default includes the C<$qtype> and nothing
1429             else. If this list includes C, then CNAME-chains will not be
1430             followed (because you asked for the CNAME record).
1431              
1432             =item class => "class"
1433              
1434             Specify the query class ("in" for internet, "ch" for chaosnet and "hs" for
1435             hesiod are the only ones making sense). The default is "in", of course.
1436              
1437             =back
1438              
1439             Examples:
1440              
1441             # full example, you can paste this into perl:
1442             use Data::Dumper;
1443             use AnyEvent::DNS;
1444             AnyEvent::DNS::resolver->resolve (
1445             "google.com", "*", my $cv = AnyEvent->condvar);
1446             warn Dumper [$cv->recv];
1447              
1448             # shortened result:
1449             # [
1450             # [ 'google.com', 'soa', 'in', 3600, 'ns1.google.com', 'dns-admin.google.com',
1451             # 2008052701, 7200, 1800, 1209600, 300 ],
1452             # [
1453             # 'google.com', 'txt', 'in', 3600,
1454             # 'v=spf1 include:_netblocks.google.com ~all'
1455             # ],
1456             # [ 'google.com', 'a', 'in', 3600, '64.233.187.99' ],
1457             # [ 'google.com', 'mx', 'in', 3600, 10, 'smtp2.google.com' ],
1458             # [ 'google.com', 'ns', 'in', 3600, 'ns2.google.com' ],
1459             # ]
1460              
1461             # resolve a records:
1462             $res->resolve ("ruth.plan9.de", "a", sub { warn Dumper [@_] });
1463              
1464             # result:
1465             # [
1466             # [ 'ruth.schmorp.de', 'a', 'in', 86400, '129.13.162.95' ]
1467             # ]
1468              
1469             # resolve any records, but return only a and aaaa records:
1470             $res->resolve ("test1.laendle", "*",
1471             accept => ["a", "aaaa"],
1472             sub {
1473             warn Dumper [@_];
1474             }
1475             );
1476              
1477             # result:
1478             # [
1479             # [ 'test1.laendle', 'a', 'in', 86400, '10.0.0.255' ],
1480             # [ 'test1.laendle', 'aaaa', 'in', 60, '3ffe:1900:4545:0002:0240:0000:0000:f7e1' ]
1481             # ]
1482              
1483             =cut
1484              
1485             sub resolve($%) {
1486 5     5 1 12 my $cb = pop;
1487 5         11 my ($self, $qname, $qtype, %opt) = @_;
1488              
1489             $self->wait_for_slot (sub {
1490 5     5   7 my $self = shift;
1491              
1492             my @search = $qname =~ s/\.$//
1493             ? ""
1494             : $opt{search}
1495 0         0 ? @{ $opt{search} }
1496             : ($qname =~ y/.//) >= $self->{ndots}
1497 1         5 ? ("", @{ $self->{search} })
1498 5 50       32 : (@{ $self->{search} }, "");
  0 50       0  
    100          
1499              
1500 5   50     21 my $class = $opt{class} || "in";
1501              
1502             my %atype = $opt{accept}
1503 5 50       16 ? map +($_ => 1), @{ $opt{accept} }
  0         0  
1504             : ($qtype => 1);
1505              
1506             # advance in searchlist
1507 5         8 my ($do_search, $do_req);
1508            
1509             $do_search = sub {
1510             @search
1511 9 100       37 or (undef $do_search), (undef $do_req), return $cb->();
1512              
1513 5         28 (my $name = lc "$qname." . shift @search) =~ s/\.$//;
1514 5         8 my $depth = 10;
1515              
1516             # advance in cname-chain
1517             $do_req = sub {
1518             $self->request ({
1519             rd => 1,
1520             qd => [[$name, $qtype, $class]],
1521             }, sub {
1522 5 50       15 my ($res) = @_
1523             or return $do_search->();
1524              
1525 5         8 my $cname;
1526              
1527 5         7 while () {
1528             # results found?
1529 5   33     16 my @rr = grep $name eq lc $_->[0] && ($atype{"*"} || $atype{$_->[1]}), @{ $res->{an} };
  5         23  
1530              
1531 5 100       17 (undef $do_search), (undef $do_req), return $cb->(@rr)
1532             if @rr;
1533              
1534             # see if there is a cname we can follow
1535 4   0     6 my @rr = grep $name eq lc $_->[0] && $_->[1] eq "cname", @{ $res->{an} };
  4         9  
1536              
1537 4 50       10 if (@rr) {
    50          
1538 0 0       0 $depth--
1539             or return $do_search->(); # cname chain too long
1540              
1541 0         0 $cname = 1;
1542 0         0 $name = lc $rr[0][4];
1543              
1544             } elsif ($cname) {
1545             # follow the cname
1546 0         0 return $do_req->();
1547              
1548             } else {
1549             # no, not found anything
1550 4         31 return $do_search->();
1551             }
1552             }
1553 5         52 });
1554 5         19 };
1555              
1556 5         8 $do_req->();
1557 5         26 };
1558              
1559 5         12 $do_search->();
1560 5         30 });
1561             }
1562              
1563             =item $resolver->wait_for_slot ($cb->($resolver))
1564              
1565             Wait until a free request slot is available and call the callback with the
1566             resolver object.
1567              
1568             A request slot is used each time a request is actually sent to the
1569             nameservers: There are never more than C of them.
1570              
1571             Although you can submit more requests (they will simply be queued until
1572             a request slot becomes available), sometimes, usually for rate-limiting
1573             purposes, it is useful to instead wait for a slot before generating the
1574             request (or simply to know when the request load is low enough so one can
1575             submit requests again).
1576              
1577             This is what this method does: The callback will be called when submitting
1578             a DNS request will not result in that request being queued. The callback
1579             may or may not generate any requests in response.
1580              
1581             Note that the callback will only be invoked when the request queue is
1582             empty, so this does not play well if somebody else keeps the request queue
1583             full at all times.
1584              
1585             =cut
1586              
1587             sub wait_for_slot {
1588 5     5 1 13 my ($self, $cb) = @_;
1589              
1590 5         6 push @{ $self->{wait} }, $cb;
  5         10  
1591 5         12 $self->_scheduler;
1592             }
1593              
1594 8     8   1986 use AnyEvent::Socket (); # circular dependency, so do not import anything and do it at the end
  8         19  
  8         527  
1595              
1596             =back
1597              
1598             =head1 AUTHOR
1599              
1600             Marc Lehmann
1601             http://anyevent.schmorp.de
1602              
1603             =cut
1604              
1605             1