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