ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/DNS.pm
Revision: 1.93
Committed: Mon Jun 22 11:57:05 2009 UTC (15 years ago) by root
Branch: MAIN
Changes since 1.92: +13 -4 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3     AnyEvent::DNS - fully asynchronous DNS resolution
4    
5     =head1 SYNOPSIS
6    
7 root 1.57 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 root 1.26
14 root 1.1 =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 root 1.46 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 root 1.12
23 root 1.1 =head2 CONVENIENCE FUNCTIONS
24    
25     =over 4
26    
27     =cut
28    
29     package AnyEvent::DNS;
30    
31 root 1.3 no warnings;
32 root 1.1 use strict;
33    
34 root 1.29 use Socket qw(AF_INET SOCK_DGRAM SOCK_STREAM);
35    
36 root 1.35 use AnyEvent ();
37 root 1.6 use AnyEvent::Handle ();
38 root 1.37 use AnyEvent::Util qw(AF_INET6);
39 root 1.1
40 root 1.92 our $VERSION = 4.411;
41 root 1.39
42 root 1.32 our @DNS_FALLBACK = (v208.67.220.220, v208.67.222.222);
43    
44 root 1.4 =item AnyEvent::DNS::a $domain, $cb->(@addrs)
45    
46     Tries to resolve the given domain to IPv4 address(es).
47    
48 root 1.17 =item AnyEvent::DNS::aaaa $domain, $cb->(@addrs)
49    
50     Tries to resolve the given domain to IPv6 address(es).
51    
52 root 1.4 =item AnyEvent::DNS::mx $domain, $cb->(@hostnames)
53    
54     Tries to resolve the given domain into a sorted (lower preference value
55     first) list of domain names.
56    
57     =item AnyEvent::DNS::ns $domain, $cb->(@hostnames)
58    
59     Tries to resolve the given domain name into a list of name servers.
60    
61     =item AnyEvent::DNS::txt $domain, $cb->(@hostnames)
62    
63     Tries to resolve the given domain name into a list of text records.
64    
65     =item AnyEvent::DNS::srv $service, $proto, $domain, $cb->(@srv_rr)
66    
67     Tries to resolve the given service, protocol and domain name into a list
68     of service records.
69    
70 root 1.59 Each C<$srv_rr> is an array reference with the following contents:
71 root 1.4 C<[$priority, $weight, $transport, $target]>.
72    
73 root 1.49 They will be sorted with lowest priority first, then randomly
74     distributed by weight as per RFC 2782.
75 root 1.4
76     Example:
77    
78     AnyEvent::DNS::srv "sip", "udp", "schmorp.de", sub { ...
79     # @_ = ( [10, 10, 5060, "sip1.schmorp.de" ] )
80    
81 root 1.48 =item AnyEvent::DNS::ptr $domain, $cb->(@hostnames)
82    
83     Tries to make a PTR lookup on the given domain. See C<reverse_lookup>
84     and C<reverse_verify> if you want to resolve an IP address to a hostname
85     instead.
86    
87     =item AnyEvent::DNS::any $domain, $cb->(@rrs)
88    
89     Tries to resolve the given domain and passes all resource records found to
90     the callback.
91    
92     =item AnyEvent::DNS::reverse_lookup $ipv4_or_6, $cb->(@hostnames)
93 root 1.4
94     Tries to reverse-resolve the given IPv4 or IPv6 address (in textual form)
95 root 1.48 into it's hostname(s). Handles V4MAPPED and V4COMPAT IPv6 addresses
96     transparently.
97    
98     =item AnyEvent::DNS::reverse_verify $ipv4_or_6, $cb->(@hostnames)
99    
100     The same as C<reverse_lookup>, but does forward-lookups to verify that
101     the resolved hostnames indeed point to the address, which makes spoofing
102     harder.
103    
104     If you want to resolve an address into a hostname, this is the preferred
105     method: The DNS records could still change, but at least this function
106     verified that the hostname, at one point in the past, pointed at the IP
107     address you originally resolved.
108 root 1.4
109     Example:
110    
111     AnyEvent::DNS::ptr "2001:500:2f::f", sub { print shift };
112     # => f.root-servers.net
113    
114     =cut
115    
116 root 1.38 sub MAX_PKT() { 4096 } # max packet size we advertise and accept
117    
118     sub DOMAIN_PORT() { 53 } # if this changes drop me a note
119    
120 root 1.4 sub resolver;
121    
122     sub a($$) {
123     my ($domain, $cb) = @_;
124    
125     resolver->resolve ($domain => "a", sub {
126     $cb->(map $_->[3], @_);
127     });
128     }
129    
130 root 1.17 sub aaaa($$) {
131     my ($domain, $cb) = @_;
132    
133     resolver->resolve ($domain => "aaaa", sub {
134     $cb->(map $_->[3], @_);
135     });
136     }
137    
138 root 1.4 sub mx($$) {
139     my ($domain, $cb) = @_;
140    
141     resolver->resolve ($domain => "mx", sub {
142     $cb->(map $_->[4], sort { $a->[3] <=> $b->[3] } @_);
143     });
144     }
145    
146     sub ns($$) {
147     my ($domain, $cb) = @_;
148    
149     resolver->resolve ($domain => "ns", sub {
150     $cb->(map $_->[3], @_);
151     });
152     }
153    
154     sub txt($$) {
155     my ($domain, $cb) = @_;
156    
157     resolver->resolve ($domain => "txt", sub {
158     $cb->(map $_->[3], @_);
159     });
160     }
161    
162     sub srv($$$$) {
163     my ($service, $proto, $domain, $cb) = @_;
164    
165     # todo, ask for any and check glue records
166     resolver->resolve ("_$service._$proto.$domain" => "srv", sub {
167 root 1.49 my @res;
168    
169     # classify by priority
170     my %pri;
171     push @{ $pri{$_->[3]} }, [ @$_[3,4,5,6] ]
172     for @_;
173    
174     # order by priority
175 elmex 1.64 for my $pri (sort { $a <=> $b } keys %pri) {
176 root 1.49 # order by weight
177     my @rr = sort { $a->[1] <=> $b->[1] } @{ delete $pri{$pri} };
178    
179     my $sum; $sum += $_->[1] for @rr;
180    
181     while (@rr) {
182     my $w = int rand $sum + 1;
183     for (0 .. $#rr) {
184     if (($w -= $rr[$_][1]) <= 0) {
185     $sum -= $rr[$_][1];
186     push @res, splice @rr, $_, 1, ();
187     last;
188     }
189     }
190     }
191     }
192    
193     $cb->(@res);
194 root 1.4 });
195     }
196    
197     sub ptr($$) {
198 root 1.48 my ($domain, $cb) = @_;
199    
200     resolver->resolve ($domain => "ptr", sub {
201     $cb->(map $_->[3], @_);
202     });
203     }
204    
205     sub any($$) {
206     my ($domain, $cb) = @_;
207    
208     resolver->resolve ($domain => "*", $cb);
209     }
210    
211     # convert textual ip address into reverse lookup form
212     sub _munge_ptr($) {
213     my $ipn = $_[0]
214     or return;
215    
216     my $ptr;
217    
218     my $af = AnyEvent::Socket::address_family ($ipn);
219 root 1.4
220 root 1.48 if ($af == AF_INET6) {
221     $ipn = substr $ipn, 0, 16; # anticipate future expansion
222 root 1.4
223 root 1.48 # handle v4mapped and v4compat
224     if ($ipn =~ s/^\x00{10}(?:\xff\xff|\x00\x00)//) {
225     $af = AF_INET;
226     } else {
227     $ptr = join ".", (reverse split //, unpack "H32", $ipn), "ip6.arpa.";
228     }
229     }
230 root 1.37
231     if ($af == AF_INET) {
232 root 1.48 $ptr = join ".", (reverse unpack "C4", $ipn), "in-addr.arpa.";
233 root 1.4 }
234    
235 root 1.48 $ptr
236     }
237    
238     sub reverse_lookup($$) {
239     my ($ip, $cb) = @_;
240    
241     $ip = _munge_ptr AnyEvent::Socket::parse_address ($ip)
242     or return $cb->();
243    
244 root 1.17 resolver->resolve ($ip => "ptr", sub {
245 root 1.4 $cb->(map $_->[3], @_);
246     });
247     }
248 root 1.1
249 root 1.48 sub reverse_verify($$) {
250     my ($ip, $cb) = @_;
251    
252     my $ipn = AnyEvent::Socket::parse_address ($ip)
253     or return $cb->();
254    
255     my $af = AnyEvent::Socket::address_family ($ipn);
256    
257     my @res;
258     my $cnt;
259    
260     my $ptr = _munge_ptr $ipn
261     or return $cb->();
262    
263     $ip = AnyEvent::Socket::format_address ($ipn); # normalise into the same form
264    
265     ptr $ptr, sub {
266     for my $name (@_) {
267     ++$cnt;
268    
269     # () around AF_INET to work around bug in 5.8
270 root 1.55 resolver->resolve ("$name." => ($af == (AF_INET) ? "a" : "aaaa"), sub {
271 root 1.48 for (@_) {
272     push @res, $name
273     if $_->[3] eq $ip;
274     }
275     $cb->(@res) unless --$cnt;
276     });
277     }
278 root 1.5
279 root 1.48 $cb->() unless $cnt;
280     };
281 root 1.5 }
282    
283 root 1.36 #################################################################################
284 root 1.18
285 root 1.15 =back
286    
287 root 1.13 =head2 LOW-LEVEL DNS EN-/DECODING FUNCTIONS
288 root 1.1
289     =over 4
290    
291 root 1.11 =item $AnyEvent::DNS::EDNS0
292    
293 root 1.13 This variable decides whether dns_pack automatically enables EDNS0
294 root 1.24 support. By default, this is disabled (C<0>), unless overridden by
295 root 1.40 C<$ENV{PERL_ANYEVENT_EDNS0}>, but when set to C<1>, AnyEvent::DNS will use
296 root 1.21 EDNS0 in all requests.
297 root 1.11
298 root 1.1 =cut
299    
300 root 1.93 our $EDNS0 = $ENV{PERL_ANYEVENT_EDNS0}*1; # set to 1 to enable (partial) edns0
301 root 1.10
302 root 1.1 our %opcode_id = (
303     query => 0,
304     iquery => 1,
305     status => 2,
306 root 1.5 notify => 4,
307     update => 5,
308     map +($_ => $_), 3, 6..15
309 root 1.1 );
310    
311     our %opcode_str = reverse %opcode_id;
312    
313     our %rcode_id = (
314 root 1.5 noerror => 0,
315     formerr => 1,
316     servfail => 2,
317     nxdomain => 3,
318     notimp => 4,
319     refused => 5,
320     yxdomain => 6, # Name Exists when it should not [RFC 2136]
321     yxrrset => 7, # RR Set Exists when it should not [RFC 2136]
322     nxrrset => 8, # RR Set that should exist does not [RFC 2136]
323     notauth => 9, # Server Not Authoritative for zone [RFC 2136]
324     notzone => 10, # Name not contained in zone [RFC 2136]
325     # EDNS0 16 BADVERS Bad OPT Version [RFC 2671]
326     # EDNS0 16 BADSIG TSIG Signature Failure [RFC 2845]
327     # EDNS0 17 BADKEY Key not recognized [RFC 2845]
328     # EDNS0 18 BADTIME Signature out of time window [RFC 2845]
329     # EDNS0 19 BADMODE Bad TKEY Mode [RFC 2930]
330     # EDNS0 20 BADNAME Duplicate key name [RFC 2930]
331     # EDNS0 21 BADALG Algorithm not supported [RFC 2930]
332     map +($_ => $_), 11..15
333 root 1.1 );
334    
335     our %rcode_str = reverse %rcode_id;
336    
337     our %type_id = (
338     a => 1,
339     ns => 2,
340     md => 3,
341     mf => 4,
342     cname => 5,
343     soa => 6,
344     mb => 7,
345     mg => 8,
346     mr => 9,
347     null => 10,
348     wks => 11,
349     ptr => 12,
350     hinfo => 13,
351     minfo => 14,
352     mx => 15,
353     txt => 16,
354     aaaa => 28,
355     srv => 33,
356 root 1.47 naptr => 35, # rfc2915
357 root 1.90 dname => 39, # rfc2672
358 root 1.5 opt => 41,
359     spf => 99,
360     tkey => 249,
361     tsig => 250,
362     ixfr => 251,
363 root 1.1 axfr => 252,
364     mailb => 253,
365     "*" => 255,
366     );
367    
368     our %type_str = reverse %type_id;
369    
370     our %class_id = (
371 root 1.5 in => 1,
372     ch => 3,
373     hs => 4,
374     none => 254,
375     "*" => 255,
376 root 1.1 );
377    
378     our %class_str = reverse %class_id;
379    
380 root 1.34 sub _enc_name($) {
381 root 1.29 pack "(C/a*)*", (split /\./, shift), ""
382 root 1.1 }
383    
384     sub _enc_qd() {
385 root 1.34 (_enc_name $_->[0]) . pack "nn",
386 root 1.1 ($_->[1] > 0 ? $_->[1] : $type_id {$_->[1]}),
387     ($_->[2] > 0 ? $_->[2] : $class_id{$_->[2] || "in"})
388     }
389    
390     sub _enc_rr() {
391     die "encoding of resource records is not supported";
392     }
393    
394     =item $pkt = AnyEvent::DNS::dns_pack $dns
395    
396 root 1.50 Packs a perl data structure into a DNS packet. Reading RFC 1035 is strongly
397 root 1.1 recommended, then everything will be totally clear. Or maybe not.
398    
399     Resource records are not yet encodable.
400    
401     Examples:
402    
403 root 1.57 # very simple request, using lots of default values:
404     { rd => 1, qd => [ [ "host.domain", "a"] ] }
405    
406     # more complex example, showing how flags etc. are named:
407    
408     {
409     id => 10000,
410     op => "query",
411     rc => "nxdomain",
412    
413     # flags
414     qr => 1,
415     aa => 0,
416     tc => 0,
417     rd => 0,
418     ra => 0,
419     ad => 0,
420     cd => 0,
421    
422     qd => [@rr], # query section
423     an => [@rr], # answer section
424     ns => [@rr], # authority section
425     ar => [@rr], # additional records section
426     }
427 root 1.1
428     =cut
429    
430     sub dns_pack($) {
431     my ($req) = @_;
432    
433 root 1.7 pack "nn nnnn a* a* a* a* a*",
434 root 1.1 $req->{id},
435    
436     ! !$req->{qr} * 0x8000
437     + $opcode_id{$req->{op}} * 0x0800
438     + ! !$req->{aa} * 0x0400
439     + ! !$req->{tc} * 0x0200
440     + ! !$req->{rd} * 0x0100
441     + ! !$req->{ra} * 0x0080
442 root 1.5 + ! !$req->{ad} * 0x0020
443     + ! !$req->{cd} * 0x0010
444 root 1.1 + $rcode_id{$req->{rc}} * 0x0001,
445    
446     scalar @{ $req->{qd} || [] },
447     scalar @{ $req->{an} || [] },
448     scalar @{ $req->{ns} || [] },
449 root 1.44 $EDNS0 + scalar @{ $req->{ar} || [] }, # EDNS0 option included here
450 root 1.1
451     (join "", map _enc_qd, @{ $req->{qd} || [] }),
452     (join "", map _enc_rr, @{ $req->{an} || [] }),
453     (join "", map _enc_rr, @{ $req->{ns} || [] }),
454 root 1.7 (join "", map _enc_rr, @{ $req->{ar} || [] }),
455    
456 root 1.44 ($EDNS0 ? pack "C nnNn", 0, 41, MAX_PKT, 0, 0 : "") # EDNS0 option
457 root 1.1 }
458    
459     our $ofs;
460     our $pkt;
461    
462     # bitches
463 root 1.34 sub _dec_name {
464 root 1.1 my @res;
465     my $redir;
466     my $ptr = $ofs;
467     my $cnt;
468    
469     while () {
470     return undef if ++$cnt >= 256; # to avoid DoS attacks
471    
472     my $len = ord substr $pkt, $ptr++, 1;
473    
474 root 1.34 if ($len >= 0xc0) {
475 root 1.1 $ptr++;
476     $ofs = $ptr if $ptr > $ofs;
477     $ptr = (unpack "n", substr $pkt, $ptr - 2, 2) & 0x3fff;
478     } elsif ($len) {
479     push @res, substr $pkt, $ptr, $len;
480     $ptr += $len;
481     } else {
482     $ofs = $ptr if $ptr > $ofs;
483     return join ".", @res;
484     }
485     }
486     }
487    
488     sub _dec_qd {
489 root 1.34 my $qname = _dec_name;
490 root 1.1 my ($qt, $qc) = unpack "nn", substr $pkt, $ofs; $ofs += 4;
491     [$qname, $type_str{$qt} || $qt, $class_str{$qc} || $qc]
492     }
493    
494     our %dec_rr = (
495 root 1.29 1 => sub { join ".", unpack "C4", $_ }, # a
496 root 1.34 2 => sub { local $ofs = $ofs - length; _dec_name }, # ns
497     5 => sub { local $ofs = $ofs - length; _dec_name }, # cname
498 root 1.1 6 => sub {
499     local $ofs = $ofs - length;
500 root 1.34 my $mname = _dec_name;
501     my $rname = _dec_name;
502 root 1.1 ($mname, $rname, unpack "NNNNN", substr $pkt, $ofs)
503     }, # soa
504 root 1.29 11 => sub { ((join ".", unpack "C4", $_), unpack "C a*", substr $_, 4) }, # wks
505 root 1.34 12 => sub { local $ofs = $ofs - length; _dec_name }, # ptr
506 root 1.29 13 => sub { unpack "C/a* C/a*", $_ }, # hinfo
507 root 1.34 15 => sub { local $ofs = $ofs + 2 - length; ((unpack "n", $_), _dec_name) }, # mx
508 root 1.29 16 => sub { unpack "(C/a*)*", $_ }, # txt
509 root 1.36 28 => sub { AnyEvent::Socket::format_address ($_) }, # aaaa
510 root 1.34 33 => sub { local $ofs = $ofs + 6 - length; ((unpack "nnn", $_), _dec_name) }, # srv
511 root 1.47 35 => sub { # naptr
512 root 1.66 # requires perl 5.10, sorry
513 root 1.47 my ($order, $preference, $flags, $service, $regexp, $offset) = unpack "nn C/a* C/a* C/a* .", $_;
514     local $ofs = $ofs + $offset - length;
515     ($order, $preference, $flags, $service, $regexp, _dec_name)
516     },
517 root 1.90 39 => sub { local $ofs = $ofs - length; _dec_name }, # dname
518 root 1.29 99 => sub { unpack "(C/a*)*", $_ }, # spf
519 root 1.1 );
520    
521     sub _dec_rr {
522 root 1.34 my $name = _dec_name;
523 root 1.1
524     my ($rt, $rc, $ttl, $rdlen) = unpack "nn N n", substr $pkt, $ofs; $ofs += 10;
525     local $_ = substr $pkt, $ofs, $rdlen; $ofs += $rdlen;
526    
527     [
528 root 1.34 $name,
529 root 1.1 $type_str{$rt} || $rt,
530     $class_str{$rc} || $rc,
531     ($dec_rr{$rt} || sub { $_ })->(),
532     ]
533     }
534    
535     =item $dns = AnyEvent::DNS::dns_unpack $pkt
536    
537     Unpacks a DNS packet into a perl data structure.
538    
539     Examples:
540    
541 root 1.57 # an unsuccessful reply
542     {
543     'qd' => [
544     [ 'ruth.plan9.de.mach.uni-karlsruhe.de', '*', 'in' ]
545     ],
546     'rc' => 'nxdomain',
547     'ar' => [],
548     'ns' => [
549     [
550     'uni-karlsruhe.de',
551     'soa',
552     'in',
553     'netserv.rz.uni-karlsruhe.de',
554     'hostmaster.rz.uni-karlsruhe.de',
555     2008052201, 10800, 1800, 2592000, 86400
556     ]
557     ],
558     'tc' => '',
559     'ra' => 1,
560     'qr' => 1,
561     'id' => 45915,
562     'aa' => '',
563     'an' => [],
564     'rd' => 1,
565     'op' => 'query'
566     }
567    
568     # a successful reply
569    
570     {
571     'qd' => [ [ 'www.google.de', 'a', 'in' ] ],
572     'rc' => 0,
573     'ar' => [
574     [ 'a.l.google.com', 'a', 'in', '209.85.139.9' ],
575     [ 'b.l.google.com', 'a', 'in', '64.233.179.9' ],
576     [ 'c.l.google.com', 'a', 'in', '64.233.161.9' ],
577     ],
578     'ns' => [
579     [ 'l.google.com', 'ns', 'in', 'a.l.google.com' ],
580     [ 'l.google.com', 'ns', 'in', 'b.l.google.com' ],
581     ],
582     'tc' => '',
583     'ra' => 1,
584     'qr' => 1,
585     'id' => 64265,
586     'aa' => '',
587     'an' => [
588     [ 'www.google.de', 'cname', 'in', 'www.google.com' ],
589     [ 'www.google.com', 'cname', 'in', 'www.l.google.com' ],
590     [ 'www.l.google.com', 'a', 'in', '66.249.93.104' ],
591     [ 'www.l.google.com', 'a', 'in', '66.249.93.147' ],
592     ],
593     'rd' => 1,
594     'op' => 0
595     }
596 root 1.1
597     =cut
598    
599     sub dns_unpack($) {
600     local $pkt = shift;
601     my ($id, $flags, $qd, $an, $ns, $ar)
602     = unpack "nn nnnn A*", $pkt;
603    
604     local $ofs = 6 * 2;
605    
606     {
607     id => $id,
608     qr => ! ! ($flags & 0x8000),
609     aa => ! ! ($flags & 0x0400),
610     tc => ! ! ($flags & 0x0200),
611     rd => ! ! ($flags & 0x0100),
612     ra => ! ! ($flags & 0x0080),
613 root 1.5 ad => ! ! ($flags & 0x0020),
614     cd => ! ! ($flags & 0x0010),
615 root 1.1 op => $opcode_str{($flags & 0x001e) >> 11},
616     rc => $rcode_str{($flags & 0x000f)},
617    
618     qd => [map _dec_qd, 1 .. $qd],
619     an => [map _dec_rr, 1 .. $an],
620     ns => [map _dec_rr, 1 .. $ns],
621     ar => [map _dec_rr, 1 .. $ar],
622     }
623     }
624    
625     #############################################################################
626    
627     =back
628    
629     =head2 THE AnyEvent::DNS RESOLVER CLASS
630    
631 root 1.13 This is the class which does the actual protocol work.
632 root 1.1
633     =over 4
634    
635     =cut
636    
637     use Carp ();
638     use Scalar::Util ();
639     use Socket ();
640    
641     our $NOW;
642    
643 root 1.2 =item AnyEvent::DNS::resolver
644    
645     This function creates and returns a resolver that is ready to use and
646     should mimic the default resolver for your system as good as possible.
647    
648     It only ever creates one resolver and returns this one on subsequent
649     calls.
650    
651     Unless you have special needs, prefer this function over creating your own
652     resolver object.
653    
654     =cut
655    
656     our $RESOLVER;
657    
658     sub resolver() {
659     $RESOLVER || do {
660 root 1.93 $RESOLVER = new AnyEvent::DNS untaint => 1;
661 root 1.14 $RESOLVER->os_config;
662 root 1.2 $RESOLVER
663     }
664     }
665    
666 root 1.1 =item $resolver = new AnyEvent::DNS key => value...
667    
668 root 1.6 Creates and returns a new resolver.
669 root 1.2
670     The following options are supported:
671 root 1.1
672     =over 4
673    
674     =item server => [...]
675    
676 root 1.41 A list of server addresses (default: C<v127.0.0.1>) in network format
677 root 1.42 (i.e. as returned by C<AnyEvent::Socket::parse_address> - both IPv4 and
678 root 1.41 IPv6 are supported).
679 root 1.1
680     =item timeout => [...]
681    
682     A list of timeouts to use (also determines the number of retries). To make
683     three retries with individual time-outs of 2, 5 and 5 seconds, use C<[2,
684     5, 5]>, which is also the default.
685    
686     =item search => [...]
687    
688     The default search list of suffixes to append to a domain name (default: none).
689    
690 root 1.2 =item ndots => $integer
691 root 1.1
692     The number of dots (default: C<1>) that a name must have so that the resolver
693     tries to resolve the name without any suffixes first.
694    
695 root 1.2 =item max_outstanding => $integer
696 root 1.1
697 root 1.43 Most name servers do not handle many parallel requests very well. This
698     option limits the number of outstanding requests to C<$integer>
699     (default: C<10>), that means if you request more than this many requests,
700     then the additional requests will be queued until some other requests have
701     been resolved.
702 root 1.1
703 root 1.13 =item reuse => $seconds
704    
705 root 1.22 The number of seconds (default: C<300>) that a query id cannot be re-used
706 root 1.54 after a timeout. If there was no time-out then query ids can be reused
707 root 1.22 immediately.
708 root 1.13
709 root 1.93 =item untaint => $boolean
710    
711     When true, then the resolver will automatically untaint results, and might
712     also ignore certain environment variables.
713    
714 root 1.1 =back
715    
716     =cut
717    
718     sub new {
719     my ($class, %arg) = @_;
720    
721     my $self = bless {
722 root 1.32 server => [],
723 root 1.1 timeout => [2, 5, 5],
724     search => [],
725     ndots => 1,
726     max_outstanding => 10,
727 root 1.54 reuse => 300,
728 root 1.1 %arg,
729     reuse_q => [],
730     }, $class;
731    
732     # search should default to gethostname's domain
733     # but perl lacks a good posix module
734    
735 root 1.63 # try to create an ipv4 and an ipv6 socket
736     # only fail when we cannot create either
737     my $got_socket;
738    
739 root 1.1 Scalar::Util::weaken (my $wself = $self);
740 root 1.38
741 root 1.63 if (socket my $fh4, AF_INET , &Socket::SOCK_DGRAM, 0) {
742     ++$got_socket;
743    
744 root 1.38 AnyEvent::Util::fh_nonblocking $fh4, 1;
745     $self->{fh4} = $fh4;
746     $self->{rw4} = AnyEvent->io (fh => $fh4, poll => "r", cb => sub {
747     if (my $peer = recv $fh4, my $pkt, MAX_PKT, 0) {
748     $wself->_recv ($pkt, $peer);
749     }
750     });
751     }
752    
753 root 1.63 if (AF_INET6 && socket my $fh6, AF_INET6, &Socket::SOCK_DGRAM, 0) {
754     ++$got_socket;
755    
756 root 1.38 $self->{fh6} = $fh6;
757     AnyEvent::Util::fh_nonblocking $fh6, 1;
758     $self->{rw6} = AnyEvent->io (fh => $fh6, poll => "r", cb => sub {
759     if (my $peer = recv $fh6, my $pkt, MAX_PKT, 0) {
760     $wself->_recv ($pkt, $peer);
761     }
762     });
763     }
764 root 1.1
765 root 1.63 $got_socket
766     or Carp::croak "unable to create either an IPv4 or an IPv6 socket";
767    
768 root 1.1 $self->_compile;
769    
770     $self
771     }
772    
773     =item $resolver->parse_resolv_conv ($string)
774    
775 root 1.24 Parses the given string as if it were a F<resolv.conf> file. The following
776     directives are supported (but not necessarily implemented).
777 root 1.1
778     C<#>-style comments, C<nameserver>, C<domain>, C<search>, C<sortlist>,
779     C<options> (C<timeout>, C<attempts>, C<ndots>).
780    
781     Everything else is silently ignored.
782    
783     =cut
784    
785     sub parse_resolv_conf {
786     my ($self, $resolvconf) = @_;
787    
788     $self->{server} = [];
789     $self->{search} = [];
790    
791     my $attempts;
792    
793     for (split /\n/, $resolvconf) {
794     if (/^\s*#/) {
795     # comment
796     } elsif (/^\s*nameserver\s+(\S+)\s*$/i) {
797     my $ip = $1;
798 root 1.36 if (my $ipn = AnyEvent::Socket::parse_address ($ip)) {
799 root 1.25 push @{ $self->{server} }, $ipn;
800 root 1.1 } else {
801     warn "nameserver $ip invalid and ignored\n";
802     }
803     } elsif (/^\s*domain\s+(\S*)\s+$/i) {
804     $self->{search} = [$1];
805     } elsif (/^\s*search\s+(.*?)\s*$/i) {
806     $self->{search} = [split /\s+/, $1];
807     } elsif (/^\s*sortlist\s+(.*?)\s*$/i) {
808     # ignored, NYI
809     } elsif (/^\s*options\s+(.*?)\s*$/i) {
810     for (split /\s+/, $1) {
811     if (/^timeout:(\d+)$/) {
812     $self->{timeout} = [$1];
813     } elsif (/^attempts:(\d+)$/) {
814     $attempts = $1;
815     } elsif (/^ndots:(\d+)$/) {
816     $self->{ndots} = $1;
817     } else {
818     # debug, rotate, no-check-names, inet6
819     }
820     }
821     }
822     }
823    
824     $self->{timeout} = [($self->{timeout}[0]) x $attempts]
825     if $attempts;
826    
827     $self->_compile;
828     }
829    
830 root 1.14 =item $resolver->os_config
831 root 1.1
832 root 1.93 Tries so load and parse F</etc/resolv.conf> on portable operating
833     systems. Tries various egregious hacks on windows to force the DNS servers
834     and searchlist out of the system.
835 root 1.1
836     =cut
837    
838 root 1.14 sub os_config {
839 root 1.1 my ($self) = @_;
840    
841 root 1.32 $self->{server} = [];
842     $self->{search} = [];
843    
844 root 1.35 if (AnyEvent::WIN32 || $^O =~ /cygwin/i) {
845 root 1.32 no strict 'refs';
846    
847     # there are many options to find the current nameservers etc. on windows
848     # all of them don't work consistently:
849     # - the registry thing needs separate code on win32 native vs. cygwin
850     # - the registry layout differs between windows versions
851     # - calling windows api functions doesn't work on cygwin
852     # - ipconfig uses locale-specific messages
853    
854 root 1.54 # we use ipconfig parsing because, despite all its brokenness,
855 root 1.32 # it seems most stable in practise.
856     # for good measure, we append a fallback nameserver to our list.
857 root 1.14
858     if (open my $fh, "ipconfig /all |") {
859 root 1.32 # parsing strategy: we go through the output and look for
860     # :-lines with DNS in them. everything in those is regarded as
861     # either a nameserver (if it parses as an ip address), or a suffix
862     # (all else).
863 root 1.14
864 root 1.32 my $dns;
865 root 1.14 while (<$fh>) {
866 root 1.32 if (s/^\s.*\bdns\b.*://i) {
867     $dns = 1;
868     } elsif (/^\S/ || /^\s[^:]{16,}: /) {
869     $dns = 0;
870     }
871     if ($dns && /^\s*(\S+)\s*$/) {
872     my $s = $1;
873 root 1.54 $s =~ s/%\d+(?!\S)//; # get rid of ipv6 scope id
874 root 1.36 if (my $ipn = AnyEvent::Socket::parse_address ($s)) {
875 root 1.32 push @{ $self->{server} }, $ipn;
876     } else {
877     push @{ $self->{search} }, $s;
878 root 1.14 }
879     }
880     }
881    
882 root 1.32 # always add one fallback server
883     push @{ $self->{server} }, $DNS_FALLBACK[rand @DNS_FALLBACK];
884 root 1.14
885     $self->_compile;
886     }
887     } else {
888     # try resolv.conf everywhere
889 root 1.1
890 root 1.14 if (open my $fh, "</etc/resolv.conf") {
891     local $/;
892     $self->parse_resolv_conf (<$fh>);
893     }
894     }
895 root 1.1 }
896    
897 root 1.53 =item $resolver->timeout ($timeout, ...)
898    
899     Sets the timeout values. See the C<timeout> constructor argument (and note
900 root 1.54 that this method uses the values itself, not an array-reference).
901 root 1.53
902     =cut
903    
904     sub timeout {
905     my ($self, @timeout) = @_;
906    
907     $self->{timeout} = \@timeout;
908     $self->_compile;
909     }
910    
911     =item $resolver->max_outstanding ($nrequests)
912    
913     Sets the maximum number of outstanding requests to C<$nrequests>. See the
914     C<max_outstanding> constructor argument.
915    
916     =cut
917    
918     sub max_outstanding {
919     my ($self, $max) = @_;
920    
921     $self->{max_outstanding} = $max;
922     $self->_scheduler;
923     }
924    
925 root 1.1 sub _compile {
926     my $self = shift;
927    
928 root 1.38 my %search; $self->{search} = [grep 0 < length, grep !$search{$_}++, @{ $self->{search} }];
929     my %server; $self->{server} = [grep 0 < length, grep !$server{$_}++, @{ $self->{server} }];
930 root 1.32
931     unless (@{ $self->{server} }) {
932     # use 127.0.0.1 by default, and one opendns nameserver as fallback
933     $self->{server} = [v127.0.0.1, $DNS_FALLBACK[rand @DNS_FALLBACK]];
934     }
935    
936 root 1.1 my @retry;
937    
938     for my $timeout (@{ $self->{timeout} }) {
939     for my $server (@{ $self->{server} }) {
940     push @retry, [$server, $timeout];
941     }
942     }
943    
944     $self->{retry} = \@retry;
945     }
946    
947 root 1.6 sub _feed {
948     my ($self, $res) = @_;
949    
950 root 1.93 ($res) = $res =~ /^(.*)$/s
951     if AnyEvent::TAINT && $self->{untaint};
952    
953 root 1.6 $res = dns_unpack $res
954     or return;
955    
956     my $id = $self->{id}{$res->{id}};
957    
958     return unless ref $id;
959    
960     $NOW = time;
961     $id->[1]->($res);
962     }
963    
964 root 1.1 sub _recv {
965 root 1.38 my ($self, $pkt, $peer) = @_;
966 root 1.1
967 root 1.32 # we ignore errors (often one gets port unreachable, but there is
968     # no good way to take advantage of that.
969 root 1.1
970 root 1.38 my ($port, $host) = AnyEvent::Socket::unpack_sockaddr ($peer);
971    
972     return unless $port == 53 && grep $_ eq $host, @{ $self->{server} };
973 root 1.1
974 root 1.38 $self->_feed ($pkt);
975 root 1.1 }
976    
977 root 1.22 sub _free_id {
978     my ($self, $id, $timeout) = @_;
979    
980     if ($timeout) {
981     # we need to block the id for a while
982     $self->{id}{$id} = 1;
983     push @{ $self->{reuse_q} }, [$NOW + $self->{reuse}, $id];
984     } else {
985     # we can quickly recycle the id
986     delete $self->{id}{$id};
987     }
988    
989     --$self->{outstanding};
990     $self->_scheduler;
991     }
992    
993     # execute a single request, involves sending it with timeouts to multiple servers
994 root 1.1 sub _exec {
995 root 1.22 my ($self, $req) = @_;
996    
997     my $retry; # of retries
998     my $do_retry;
999    
1000     $do_retry = sub {
1001     my $retry_cfg = $self->{retry}[$retry++]
1002     or do {
1003     # failure
1004     $self->_free_id ($req->[2], $retry > 1);
1005     undef $do_retry; return $req->[1]->();
1006     };
1007 root 1.1
1008     my ($server, $timeout) = @$retry_cfg;
1009    
1010     $self->{id}{$req->[2]} = [AnyEvent->timer (after => $timeout, cb => sub {
1011     $NOW = time;
1012    
1013     # timeout, try next
1014 root 1.70 &$do_retry if $do_retry;
1015 root 1.1 }), sub {
1016     my ($res) = @_;
1017    
1018 root 1.6 if ($res->{tc}) {
1019     # success, but truncated, so use tcp
1020 root 1.38 AnyEvent::Socket::tcp_connect (AnyEvent::Socket::format_address ($server), DOMAIN_PORT, sub {
1021 root 1.52 return unless $do_retry; # some other request could have invalidated us already
1022    
1023 root 1.6 my ($fh) = @_
1024 root 1.22 or return &$do_retry;
1025 root 1.6
1026 root 1.52 my $handle; $handle = new AnyEvent::Handle
1027 root 1.6 fh => $fh,
1028 root 1.52 timeout => $timeout,
1029 root 1.6 on_error => sub {
1030 root 1.52 undef $handle;
1031     return unless $do_retry; # some other request could have invalidated us already
1032 root 1.6 # failure, try next
1033 root 1.22 &$do_retry;
1034 root 1.6 };
1035    
1036     $handle->push_write (pack "n/a", $req->[0]);
1037 root 1.27 $handle->push_read (chunk => 2, sub {
1038     $handle->unshift_read (chunk => (unpack "n", $_[1]), sub {
1039 root 1.52 undef $handle;
1040 root 1.6 $self->_feed ($_[1]);
1041     });
1042     });
1043    
1044 root 1.17 }, sub { $timeout });
1045 root 1.1
1046 root 1.6 } else {
1047     # success
1048 root 1.22 $self->_free_id ($req->[2], $retry > 1);
1049     undef $do_retry; return $req->[1]->($res);
1050 root 1.6 }
1051 root 1.1 }];
1052 root 1.38
1053     my $sa = AnyEvent::Socket::pack_sockaddr (DOMAIN_PORT, $server);
1054    
1055 root 1.39 my $fh = AF_INET == Socket::sockaddr_family ($sa)
1056 root 1.38 ? $self->{fh4} : $self->{fh6}
1057     or return &$do_retry;
1058 root 1.1
1059 root 1.38 send $fh, $req->[0], 0, $sa;
1060 root 1.22 };
1061 root 1.1
1062 root 1.22 &$do_retry;
1063 root 1.1 }
1064    
1065     sub _scheduler {
1066     my ($self) = @_;
1067    
1068 root 1.51 no strict 'refs';
1069    
1070 root 1.1 $NOW = time;
1071    
1072     # first clear id reuse queue
1073     delete $self->{id}{ (shift @{ $self->{reuse_q} })->[1] }
1074 root 1.13 while @{ $self->{reuse_q} } && $self->{reuse_q}[0][0] <= $NOW;
1075 root 1.1
1076     while ($self->{outstanding} < $self->{max_outstanding}) {
1077 root 1.13
1078     if (@{ $self->{reuse_q} } >= 30000) {
1079     # we ran out of ID's, wait a bit
1080     $self->{reuse_to} ||= AnyEvent->timer (after => $self->{reuse_q}[0][0] - $NOW, cb => sub {
1081     delete $self->{reuse_to};
1082     $self->_scheduler;
1083     });
1084     last;
1085     }
1086    
1087 root 1.51 if (my $req = shift @{ $self->{queue} }) {
1088     # found a request in the queue, execute it
1089     while () {
1090     $req->[2] = int rand 65536;
1091     last unless exists $self->{id}{$req->[2]};
1092     }
1093    
1094     ++$self->{outstanding};
1095     $self->{id}{$req->[2]} = 1;
1096     substr $req->[0], 0, 2, pack "n", $req->[2];
1097    
1098     $self->_exec ($req);
1099    
1100     } elsif (my $cb = shift @{ $self->{wait} }) {
1101     # found a wait_for_slot callback, call that one first
1102     $cb->($self);
1103 root 1.1
1104 root 1.51 } else {
1105     # nothing to do, just exit
1106     last;
1107 root 1.1 }
1108     }
1109     }
1110    
1111     =item $resolver->request ($req, $cb->($res))
1112    
1113 root 1.54 This is the main low-level workhorse for sending DNS requests.
1114    
1115     This function sends a single request (a hash-ref formated as specified
1116     for C<dns_pack>) to the configured nameservers in turn until it gets a
1117     response. It handles timeouts, retries and automatically falls back to
1118     virtual circuit mode (TCP) when it receives a truncated reply.
1119    
1120     Calls the callback with the decoded response packet if a reply was
1121     received, or no arguments in case none of the servers answered.
1122 root 1.1
1123     =cut
1124    
1125     sub request($$) {
1126     my ($self, $req, $cb) = @_;
1127    
1128 root 1.3 push @{ $self->{queue} }, [dns_pack $req, $cb];
1129 root 1.1 $self->_scheduler;
1130     }
1131    
1132 root 1.80 =item $resolver->resolve ($qname, $qtype, %options, $cb->(@rr))
1133 root 1.1
1134 root 1.44 Queries the DNS for the given domain name C<$qname> of type C<$qtype>.
1135    
1136 root 1.54 A C<$qtype> is either a numerical query type (e.g. C<1> for A records) or
1137 root 1.44 a lowercase name (you have to look at the source to see which aliases are
1138 root 1.50 supported, but all types from RFC 1035, C<aaaa>, C<srv>, C<spf> and a few
1139 root 1.54 more are known to this module). A C<$qtype> of "*" is supported and means
1140 root 1.44 "any" record type.
1141 root 1.1
1142     The callback will be invoked with a list of matching result records or
1143     none on any error or if the name could not be found.
1144    
1145 root 1.61 CNAME chains (although illegal) are followed up to a length of 10.
1146 root 1.1
1147 root 1.83 The callback will be invoked with arraryefs of the form C<[$name, $type,
1148     $class, @data>], where C<$name> is the domain name, C<$type> a type string
1149     or number, C<$class> a class name and @data is resource-record-dependent
1150     data. For C<a> records, this will be the textual IPv4 addresses, for C<ns>
1151     or C<cname> records this will be a domain name, for C<txt> records these
1152     are all the strings and so on.
1153 root 1.44
1154 root 1.55 All types mentioned in RFC 1035, C<aaaa>, C<srv>, C<naptr> and C<spf> are
1155     decoded. All resource records not known to this module will have
1156 root 1.44 the raw C<rdata> field as fourth entry.
1157    
1158 root 1.24 Note that this resolver is just a stub resolver: it requires a name server
1159 root 1.3 supporting recursive queries, will not do any recursive queries itself and
1160     is not secure when used against an untrusted name server.
1161    
1162 root 1.1 The following options are supported:
1163    
1164     =over 4
1165    
1166     =item search => [$suffix...]
1167    
1168     Use the given search list (which might be empty), by appending each one
1169     in turn to the C<$qname>. If this option is missing then the configured
1170 root 1.55 C<ndots> and C<search> values define its value (depending on C<ndots>, the
1171     empty suffix will be prepended or appended to that C<search> value). If
1172     the C<$qname> ends in a dot, then the searchlist will be ignored.
1173 root 1.1
1174     =item accept => [$type...]
1175    
1176     Lists the acceptable result types: only result types in this set will be
1177     accepted and returned. The default includes the C<$qtype> and nothing
1178 root 1.44 else. If this list includes C<cname>, then CNAME-chains will not be
1179     followed (because you asked for the CNAME record).
1180 root 1.1
1181     =item class => "class"
1182    
1183     Specify the query class ("in" for internet, "ch" for chaosnet and "hs" for
1184 root 1.2 hesiod are the only ones making sense). The default is "in", of course.
1185 root 1.1
1186     =back
1187    
1188     Examples:
1189    
1190 root 1.46 # full example, you can paste this into perl:
1191 root 1.45 use Data::Dumper;
1192     use AnyEvent::DNS;
1193     AnyEvent::DNS::resolver->resolve (
1194     "google.com", "*", my $cv = AnyEvent->condvar);
1195     warn Dumper [$cv->recv];
1196    
1197     # shortened result:
1198     # [
1199     # [ 'google.com', 'soa', 'in', 'ns1.google.com', 'dns-admin.google.com',
1200     # 2008052701, 7200, 1800, 1209600, 300 ],
1201     # [
1202     # 'google.com', 'txt', 'in',
1203     # 'v=spf1 include:_netblocks.google.com ~all'
1204     # ],
1205     # [ 'google.com', 'a', 'in', '64.233.187.99' ],
1206     # [ 'google.com', 'mx', 'in', 10, 'smtp2.google.com' ],
1207     # [ 'google.com', 'ns', 'in', 'ns2.google.com' ],
1208     # ]
1209    
1210     # resolve a records:
1211     $res->resolve ("ruth.plan9.de", "a", sub { warn Dumper [@_] });
1212    
1213     # result:
1214     # [
1215     # [ 'ruth.schmorp.de', 'a', 'in', '129.13.162.95' ]
1216     # ]
1217 root 1.1
1218 root 1.45 # resolve any records, but return only a and aaaa records:
1219 root 1.1 $res->resolve ("test1.laendle", "*",
1220     accept => ["a", "aaaa"],
1221     sub {
1222     warn Dumper [@_];
1223     }
1224     );
1225    
1226 root 1.45 # result:
1227     # [
1228     # [ 'test1.laendle', 'a', 'in', '10.0.0.255' ],
1229     # [ 'test1.laendle', 'aaaa', 'in', '3ffe:1900:4545:0002:0240:0000:0000:f7e1' ]
1230     # ]
1231 root 1.1
1232     =cut
1233    
1234     sub resolve($%) {
1235     my $cb = pop;
1236     my ($self, $qname, $qtype, %opt) = @_;
1237    
1238     my @search = $qname =~ s/\.$//
1239     ? ""
1240     : $opt{search}
1241     ? @{ $opt{search} }
1242     : ($qname =~ y/.//) >= $self->{ndots}
1243     ? ("", @{ $self->{search} })
1244     : (@{ $self->{search} }, "");
1245    
1246     my $class = $opt{class} || "in";
1247    
1248     my %atype = $opt{accept}
1249     ? map +($_ => 1), @{ $opt{accept} }
1250     : ($qtype => 1);
1251    
1252     # advance in searchlist
1253 root 1.22 my ($do_search, $do_req);
1254    
1255     $do_search = sub {
1256 root 1.1 @search
1257 root 1.22 or (undef $do_search), (undef $do_req), return $cb->();
1258 root 1.1
1259 root 1.4 (my $name = lc "$qname." . shift @search) =~ s/\.$//;
1260 root 1.61 my $depth = 10;
1261 root 1.1
1262     # advance in cname-chain
1263 root 1.22 $do_req = sub {
1264 root 1.1 $self->request ({
1265     rd => 1,
1266     qd => [[$name, $qtype, $class]],
1267     }, sub {
1268     my ($res) = @_
1269     or return $do_search->();
1270    
1271     my $cname;
1272    
1273     while () {
1274 root 1.2 # results found?
1275 root 1.4 my @rr = grep $name eq lc $_->[0] && ($atype{"*"} || $atype{$_->[1]}), @{ $res->{an} };
1276 root 1.1
1277 root 1.22 (undef $do_search), (undef $do_req), return $cb->(@rr)
1278 root 1.1 if @rr;
1279    
1280     # see if there is a cname we can follow
1281 root 1.4 my @rr = grep $name eq lc $_->[0] && $_->[1] eq "cname", @{ $res->{an} };
1282 root 1.1
1283     if (@rr) {
1284     $depth--
1285     or return $do_search->(); # cname chain too long
1286    
1287     $cname = 1;
1288     $name = $rr[0][3];
1289    
1290     } elsif ($cname) {
1291     # follow the cname
1292     return $do_req->();
1293    
1294     } else {
1295 root 1.2 # no, not found anything
1296 root 1.1 return $do_search->();
1297     }
1298     }
1299     });
1300     };
1301    
1302     $do_req->();
1303     };
1304    
1305     $do_search->();
1306     }
1307    
1308 root 1.51 =item $resolver->wait_for_slot ($cb->($resolver))
1309    
1310     Wait until a free request slot is available and call the callback with the
1311     resolver object.
1312    
1313     A request slot is used each time a request is actually sent to the
1314     nameservers: There are never more than C<max_outstanding> of them.
1315    
1316     Although you can submit more requests (they will simply be queued until
1317     a request slot becomes available), sometimes, usually for rate-limiting
1318     purposes, it is useful to instead wait for a slot before generating the
1319     request (or simply to know when the request load is low enough so one can
1320     submit requests again).
1321    
1322     This is what this method does: The callback will be called when submitting
1323     a DNS request will not result in that request being queued. The callback
1324     may or may not generate any requests in response.
1325    
1326     Note that the callback will only be invoked when the request queue is
1327     empty, so this does not play well if somebody else keeps the request queue
1328     full at all times.
1329    
1330     =cut
1331    
1332     sub wait_for_slot {
1333     my ($self, $cb) = @_;
1334    
1335     push @{ $self->{wait} }, $cb;
1336     $self->_scheduler;
1337     }
1338    
1339 root 1.17 use AnyEvent::Socket (); # circular dependency, so do not import anything and do it at the end
1340    
1341 root 1.1 1;
1342    
1343     =back
1344    
1345     =head1 AUTHOR
1346    
1347 root 1.58 Marc Lehmann <schmorp@schmorp.de>
1348     http://home.schmorp.de/
1349 root 1.1
1350     =cut
1351