ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/DNS.pm
Revision: 1.92
Committed: Sun Jun 7 16:48:38 2009 UTC (15 years ago) by root
Branch: MAIN
CVS Tags: rel-4_411
Changes since 1.91: +1 -1 lines
Log Message:
4.411

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.21 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     $RESOLVER = new AnyEvent::DNS;
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.1 =back
710    
711     =cut
712    
713     sub new {
714     my ($class, %arg) = @_;
715    
716     my $self = bless {
717 root 1.32 server => [],
718 root 1.1 timeout => [2, 5, 5],
719     search => [],
720     ndots => 1,
721     max_outstanding => 10,
722 root 1.54 reuse => 300,
723 root 1.1 %arg,
724     reuse_q => [],
725     }, $class;
726    
727     # search should default to gethostname's domain
728     # but perl lacks a good posix module
729    
730 root 1.63 # try to create an ipv4 and an ipv6 socket
731     # only fail when we cannot create either
732     my $got_socket;
733    
734 root 1.1 Scalar::Util::weaken (my $wself = $self);
735 root 1.38
736 root 1.63 if (socket my $fh4, AF_INET , &Socket::SOCK_DGRAM, 0) {
737     ++$got_socket;
738    
739 root 1.38 AnyEvent::Util::fh_nonblocking $fh4, 1;
740     $self->{fh4} = $fh4;
741     $self->{rw4} = AnyEvent->io (fh => $fh4, poll => "r", cb => sub {
742     if (my $peer = recv $fh4, my $pkt, MAX_PKT, 0) {
743     $wself->_recv ($pkt, $peer);
744     }
745     });
746     }
747    
748 root 1.63 if (AF_INET6 && socket my $fh6, AF_INET6, &Socket::SOCK_DGRAM, 0) {
749     ++$got_socket;
750    
751 root 1.38 $self->{fh6} = $fh6;
752     AnyEvent::Util::fh_nonblocking $fh6, 1;
753     $self->{rw6} = AnyEvent->io (fh => $fh6, poll => "r", cb => sub {
754     if (my $peer = recv $fh6, my $pkt, MAX_PKT, 0) {
755     $wself->_recv ($pkt, $peer);
756     }
757     });
758     }
759 root 1.1
760 root 1.63 $got_socket
761     or Carp::croak "unable to create either an IPv4 or an IPv6 socket";
762    
763 root 1.1 $self->_compile;
764    
765     $self
766     }
767    
768     =item $resolver->parse_resolv_conv ($string)
769    
770 root 1.24 Parses the given string as if it were a F<resolv.conf> file. The following
771     directives are supported (but not necessarily implemented).
772 root 1.1
773     C<#>-style comments, C<nameserver>, C<domain>, C<search>, C<sortlist>,
774     C<options> (C<timeout>, C<attempts>, C<ndots>).
775    
776     Everything else is silently ignored.
777    
778     =cut
779    
780     sub parse_resolv_conf {
781     my ($self, $resolvconf) = @_;
782    
783     $self->{server} = [];
784     $self->{search} = [];
785    
786     my $attempts;
787    
788     for (split /\n/, $resolvconf) {
789     if (/^\s*#/) {
790     # comment
791     } elsif (/^\s*nameserver\s+(\S+)\s*$/i) {
792     my $ip = $1;
793 root 1.36 if (my $ipn = AnyEvent::Socket::parse_address ($ip)) {
794 root 1.25 push @{ $self->{server} }, $ipn;
795 root 1.1 } else {
796     warn "nameserver $ip invalid and ignored\n";
797     }
798     } elsif (/^\s*domain\s+(\S*)\s+$/i) {
799     $self->{search} = [$1];
800     } elsif (/^\s*search\s+(.*?)\s*$/i) {
801     $self->{search} = [split /\s+/, $1];
802     } elsif (/^\s*sortlist\s+(.*?)\s*$/i) {
803     # ignored, NYI
804     } elsif (/^\s*options\s+(.*?)\s*$/i) {
805     for (split /\s+/, $1) {
806     if (/^timeout:(\d+)$/) {
807     $self->{timeout} = [$1];
808     } elsif (/^attempts:(\d+)$/) {
809     $attempts = $1;
810     } elsif (/^ndots:(\d+)$/) {
811     $self->{ndots} = $1;
812     } else {
813     # debug, rotate, no-check-names, inet6
814     }
815     }
816     }
817     }
818    
819     $self->{timeout} = [($self->{timeout}[0]) x $attempts]
820     if $attempts;
821    
822     $self->_compile;
823     }
824    
825 root 1.14 =item $resolver->os_config
826 root 1.1
827 root 1.24 Tries so load and parse F</etc/resolv.conf> on portable operating systems. Tries various
828     egregious hacks on windows to force the DNS servers and searchlist out of the system.
829 root 1.1
830     =cut
831    
832 root 1.14 sub os_config {
833 root 1.1 my ($self) = @_;
834    
835 root 1.32 $self->{server} = [];
836     $self->{search} = [];
837    
838 root 1.35 if (AnyEvent::WIN32 || $^O =~ /cygwin/i) {
839 root 1.32 no strict 'refs';
840    
841     # there are many options to find the current nameservers etc. on windows
842     # all of them don't work consistently:
843     # - the registry thing needs separate code on win32 native vs. cygwin
844     # - the registry layout differs between windows versions
845     # - calling windows api functions doesn't work on cygwin
846     # - ipconfig uses locale-specific messages
847    
848 root 1.54 # we use ipconfig parsing because, despite all its brokenness,
849 root 1.32 # it seems most stable in practise.
850     # for good measure, we append a fallback nameserver to our list.
851 root 1.14
852     if (open my $fh, "ipconfig /all |") {
853 root 1.32 # parsing strategy: we go through the output and look for
854     # :-lines with DNS in them. everything in those is regarded as
855     # either a nameserver (if it parses as an ip address), or a suffix
856     # (all else).
857 root 1.14
858 root 1.32 my $dns;
859 root 1.14 while (<$fh>) {
860 root 1.32 if (s/^\s.*\bdns\b.*://i) {
861     $dns = 1;
862     } elsif (/^\S/ || /^\s[^:]{16,}: /) {
863     $dns = 0;
864     }
865     if ($dns && /^\s*(\S+)\s*$/) {
866     my $s = $1;
867 root 1.54 $s =~ s/%\d+(?!\S)//; # get rid of ipv6 scope id
868 root 1.36 if (my $ipn = AnyEvent::Socket::parse_address ($s)) {
869 root 1.32 push @{ $self->{server} }, $ipn;
870     } else {
871     push @{ $self->{search} }, $s;
872 root 1.14 }
873     }
874     }
875    
876 root 1.32 # always add one fallback server
877     push @{ $self->{server} }, $DNS_FALLBACK[rand @DNS_FALLBACK];
878 root 1.14
879     $self->_compile;
880     }
881     } else {
882     # try resolv.conf everywhere
883 root 1.1
884 root 1.14 if (open my $fh, "</etc/resolv.conf") {
885     local $/;
886     $self->parse_resolv_conf (<$fh>);
887     }
888     }
889 root 1.1 }
890    
891 root 1.53 =item $resolver->timeout ($timeout, ...)
892    
893     Sets the timeout values. See the C<timeout> constructor argument (and note
894 root 1.54 that this method uses the values itself, not an array-reference).
895 root 1.53
896     =cut
897    
898     sub timeout {
899     my ($self, @timeout) = @_;
900    
901     $self->{timeout} = \@timeout;
902     $self->_compile;
903     }
904    
905     =item $resolver->max_outstanding ($nrequests)
906    
907     Sets the maximum number of outstanding requests to C<$nrequests>. See the
908     C<max_outstanding> constructor argument.
909    
910     =cut
911    
912     sub max_outstanding {
913     my ($self, $max) = @_;
914    
915     $self->{max_outstanding} = $max;
916     $self->_scheduler;
917     }
918    
919 root 1.1 sub _compile {
920     my $self = shift;
921    
922 root 1.38 my %search; $self->{search} = [grep 0 < length, grep !$search{$_}++, @{ $self->{search} }];
923     my %server; $self->{server} = [grep 0 < length, grep !$server{$_}++, @{ $self->{server} }];
924 root 1.32
925     unless (@{ $self->{server} }) {
926     # use 127.0.0.1 by default, and one opendns nameserver as fallback
927     $self->{server} = [v127.0.0.1, $DNS_FALLBACK[rand @DNS_FALLBACK]];
928     }
929    
930 root 1.1 my @retry;
931    
932     for my $timeout (@{ $self->{timeout} }) {
933     for my $server (@{ $self->{server} }) {
934     push @retry, [$server, $timeout];
935     }
936     }
937    
938     $self->{retry} = \@retry;
939     }
940    
941 root 1.6 sub _feed {
942     my ($self, $res) = @_;
943    
944     $res = dns_unpack $res
945     or return;
946    
947     my $id = $self->{id}{$res->{id}};
948    
949     return unless ref $id;
950    
951     $NOW = time;
952     $id->[1]->($res);
953     }
954    
955 root 1.1 sub _recv {
956 root 1.38 my ($self, $pkt, $peer) = @_;
957 root 1.1
958 root 1.32 # we ignore errors (often one gets port unreachable, but there is
959     # no good way to take advantage of that.
960 root 1.1
961 root 1.38 my ($port, $host) = AnyEvent::Socket::unpack_sockaddr ($peer);
962    
963     return unless $port == 53 && grep $_ eq $host, @{ $self->{server} };
964 root 1.1
965 root 1.38 $self->_feed ($pkt);
966 root 1.1 }
967    
968 root 1.22 sub _free_id {
969     my ($self, $id, $timeout) = @_;
970    
971     if ($timeout) {
972     # we need to block the id for a while
973     $self->{id}{$id} = 1;
974     push @{ $self->{reuse_q} }, [$NOW + $self->{reuse}, $id];
975     } else {
976     # we can quickly recycle the id
977     delete $self->{id}{$id};
978     }
979    
980     --$self->{outstanding};
981     $self->_scheduler;
982     }
983    
984     # execute a single request, involves sending it with timeouts to multiple servers
985 root 1.1 sub _exec {
986 root 1.22 my ($self, $req) = @_;
987    
988     my $retry; # of retries
989     my $do_retry;
990    
991     $do_retry = sub {
992     my $retry_cfg = $self->{retry}[$retry++]
993     or do {
994     # failure
995     $self->_free_id ($req->[2], $retry > 1);
996     undef $do_retry; return $req->[1]->();
997     };
998 root 1.1
999     my ($server, $timeout) = @$retry_cfg;
1000    
1001     $self->{id}{$req->[2]} = [AnyEvent->timer (after => $timeout, cb => sub {
1002     $NOW = time;
1003    
1004     # timeout, try next
1005 root 1.70 &$do_retry if $do_retry;
1006 root 1.1 }), sub {
1007     my ($res) = @_;
1008    
1009 root 1.6 if ($res->{tc}) {
1010     # success, but truncated, so use tcp
1011 root 1.38 AnyEvent::Socket::tcp_connect (AnyEvent::Socket::format_address ($server), DOMAIN_PORT, sub {
1012 root 1.52 return unless $do_retry; # some other request could have invalidated us already
1013    
1014 root 1.6 my ($fh) = @_
1015 root 1.22 or return &$do_retry;
1016 root 1.6
1017 root 1.52 my $handle; $handle = new AnyEvent::Handle
1018 root 1.6 fh => $fh,
1019 root 1.52 timeout => $timeout,
1020 root 1.6 on_error => sub {
1021 root 1.52 undef $handle;
1022     return unless $do_retry; # some other request could have invalidated us already
1023 root 1.6 # failure, try next
1024 root 1.22 &$do_retry;
1025 root 1.6 };
1026    
1027     $handle->push_write (pack "n/a", $req->[0]);
1028 root 1.27 $handle->push_read (chunk => 2, sub {
1029     $handle->unshift_read (chunk => (unpack "n", $_[1]), sub {
1030 root 1.52 undef $handle;
1031 root 1.6 $self->_feed ($_[1]);
1032     });
1033     });
1034    
1035 root 1.17 }, sub { $timeout });
1036 root 1.1
1037 root 1.6 } else {
1038     # success
1039 root 1.22 $self->_free_id ($req->[2], $retry > 1);
1040     undef $do_retry; return $req->[1]->($res);
1041 root 1.6 }
1042 root 1.1 }];
1043 root 1.38
1044     my $sa = AnyEvent::Socket::pack_sockaddr (DOMAIN_PORT, $server);
1045    
1046 root 1.39 my $fh = AF_INET == Socket::sockaddr_family ($sa)
1047 root 1.38 ? $self->{fh4} : $self->{fh6}
1048     or return &$do_retry;
1049 root 1.1
1050 root 1.38 send $fh, $req->[0], 0, $sa;
1051 root 1.22 };
1052 root 1.1
1053 root 1.22 &$do_retry;
1054 root 1.1 }
1055    
1056     sub _scheduler {
1057     my ($self) = @_;
1058    
1059 root 1.51 no strict 'refs';
1060    
1061 root 1.1 $NOW = time;
1062    
1063     # first clear id reuse queue
1064     delete $self->{id}{ (shift @{ $self->{reuse_q} })->[1] }
1065 root 1.13 while @{ $self->{reuse_q} } && $self->{reuse_q}[0][0] <= $NOW;
1066 root 1.1
1067     while ($self->{outstanding} < $self->{max_outstanding}) {
1068 root 1.13
1069     if (@{ $self->{reuse_q} } >= 30000) {
1070     # we ran out of ID's, wait a bit
1071     $self->{reuse_to} ||= AnyEvent->timer (after => $self->{reuse_q}[0][0] - $NOW, cb => sub {
1072     delete $self->{reuse_to};
1073     $self->_scheduler;
1074     });
1075     last;
1076     }
1077    
1078 root 1.51 if (my $req = shift @{ $self->{queue} }) {
1079     # found a request in the queue, execute it
1080     while () {
1081     $req->[2] = int rand 65536;
1082     last unless exists $self->{id}{$req->[2]};
1083     }
1084    
1085     ++$self->{outstanding};
1086     $self->{id}{$req->[2]} = 1;
1087     substr $req->[0], 0, 2, pack "n", $req->[2];
1088    
1089     $self->_exec ($req);
1090    
1091     } elsif (my $cb = shift @{ $self->{wait} }) {
1092     # found a wait_for_slot callback, call that one first
1093     $cb->($self);
1094 root 1.1
1095 root 1.51 } else {
1096     # nothing to do, just exit
1097     last;
1098 root 1.1 }
1099     }
1100     }
1101    
1102     =item $resolver->request ($req, $cb->($res))
1103    
1104 root 1.54 This is the main low-level workhorse for sending DNS requests.
1105    
1106     This function sends a single request (a hash-ref formated as specified
1107     for C<dns_pack>) to the configured nameservers in turn until it gets a
1108     response. It handles timeouts, retries and automatically falls back to
1109     virtual circuit mode (TCP) when it receives a truncated reply.
1110    
1111     Calls the callback with the decoded response packet if a reply was
1112     received, or no arguments in case none of the servers answered.
1113 root 1.1
1114     =cut
1115    
1116     sub request($$) {
1117     my ($self, $req, $cb) = @_;
1118    
1119 root 1.3 push @{ $self->{queue} }, [dns_pack $req, $cb];
1120 root 1.1 $self->_scheduler;
1121     }
1122    
1123 root 1.80 =item $resolver->resolve ($qname, $qtype, %options, $cb->(@rr))
1124 root 1.1
1125 root 1.44 Queries the DNS for the given domain name C<$qname> of type C<$qtype>.
1126    
1127 root 1.54 A C<$qtype> is either a numerical query type (e.g. C<1> for A records) or
1128 root 1.44 a lowercase name (you have to look at the source to see which aliases are
1129 root 1.50 supported, but all types from RFC 1035, C<aaaa>, C<srv>, C<spf> and a few
1130 root 1.54 more are known to this module). A C<$qtype> of "*" is supported and means
1131 root 1.44 "any" record type.
1132 root 1.1
1133     The callback will be invoked with a list of matching result records or
1134     none on any error or if the name could not be found.
1135    
1136 root 1.61 CNAME chains (although illegal) are followed up to a length of 10.
1137 root 1.1
1138 root 1.83 The callback will be invoked with arraryefs of the form C<[$name, $type,
1139     $class, @data>], where C<$name> is the domain name, C<$type> a type string
1140     or number, C<$class> a class name and @data is resource-record-dependent
1141     data. For C<a> records, this will be the textual IPv4 addresses, for C<ns>
1142     or C<cname> records this will be a domain name, for C<txt> records these
1143     are all the strings and so on.
1144 root 1.44
1145 root 1.55 All types mentioned in RFC 1035, C<aaaa>, C<srv>, C<naptr> and C<spf> are
1146     decoded. All resource records not known to this module will have
1147 root 1.44 the raw C<rdata> field as fourth entry.
1148    
1149 root 1.24 Note that this resolver is just a stub resolver: it requires a name server
1150 root 1.3 supporting recursive queries, will not do any recursive queries itself and
1151     is not secure when used against an untrusted name server.
1152    
1153 root 1.1 The following options are supported:
1154    
1155     =over 4
1156    
1157     =item search => [$suffix...]
1158    
1159     Use the given search list (which might be empty), by appending each one
1160     in turn to the C<$qname>. If this option is missing then the configured
1161 root 1.55 C<ndots> and C<search> values define its value (depending on C<ndots>, the
1162     empty suffix will be prepended or appended to that C<search> value). If
1163     the C<$qname> ends in a dot, then the searchlist will be ignored.
1164 root 1.1
1165     =item accept => [$type...]
1166    
1167     Lists the acceptable result types: only result types in this set will be
1168     accepted and returned. The default includes the C<$qtype> and nothing
1169 root 1.44 else. If this list includes C<cname>, then CNAME-chains will not be
1170     followed (because you asked for the CNAME record).
1171 root 1.1
1172     =item class => "class"
1173    
1174     Specify the query class ("in" for internet, "ch" for chaosnet and "hs" for
1175 root 1.2 hesiod are the only ones making sense). The default is "in", of course.
1176 root 1.1
1177     =back
1178    
1179     Examples:
1180    
1181 root 1.46 # full example, you can paste this into perl:
1182 root 1.45 use Data::Dumper;
1183     use AnyEvent::DNS;
1184     AnyEvent::DNS::resolver->resolve (
1185     "google.com", "*", my $cv = AnyEvent->condvar);
1186     warn Dumper [$cv->recv];
1187    
1188     # shortened result:
1189     # [
1190     # [ 'google.com', 'soa', 'in', 'ns1.google.com', 'dns-admin.google.com',
1191     # 2008052701, 7200, 1800, 1209600, 300 ],
1192     # [
1193     # 'google.com', 'txt', 'in',
1194     # 'v=spf1 include:_netblocks.google.com ~all'
1195     # ],
1196     # [ 'google.com', 'a', 'in', '64.233.187.99' ],
1197     # [ 'google.com', 'mx', 'in', 10, 'smtp2.google.com' ],
1198     # [ 'google.com', 'ns', 'in', 'ns2.google.com' ],
1199     # ]
1200    
1201     # resolve a records:
1202     $res->resolve ("ruth.plan9.de", "a", sub { warn Dumper [@_] });
1203    
1204     # result:
1205     # [
1206     # [ 'ruth.schmorp.de', 'a', 'in', '129.13.162.95' ]
1207     # ]
1208 root 1.1
1209 root 1.45 # resolve any records, but return only a and aaaa records:
1210 root 1.1 $res->resolve ("test1.laendle", "*",
1211     accept => ["a", "aaaa"],
1212     sub {
1213     warn Dumper [@_];
1214     }
1215     );
1216    
1217 root 1.45 # result:
1218     # [
1219     # [ 'test1.laendle', 'a', 'in', '10.0.0.255' ],
1220     # [ 'test1.laendle', 'aaaa', 'in', '3ffe:1900:4545:0002:0240:0000:0000:f7e1' ]
1221     # ]
1222 root 1.1
1223     =cut
1224    
1225     sub resolve($%) {
1226     my $cb = pop;
1227     my ($self, $qname, $qtype, %opt) = @_;
1228    
1229     my @search = $qname =~ s/\.$//
1230     ? ""
1231     : $opt{search}
1232     ? @{ $opt{search} }
1233     : ($qname =~ y/.//) >= $self->{ndots}
1234     ? ("", @{ $self->{search} })
1235     : (@{ $self->{search} }, "");
1236    
1237     my $class = $opt{class} || "in";
1238    
1239     my %atype = $opt{accept}
1240     ? map +($_ => 1), @{ $opt{accept} }
1241     : ($qtype => 1);
1242    
1243     # advance in searchlist
1244 root 1.22 my ($do_search, $do_req);
1245    
1246     $do_search = sub {
1247 root 1.1 @search
1248 root 1.22 or (undef $do_search), (undef $do_req), return $cb->();
1249 root 1.1
1250 root 1.4 (my $name = lc "$qname." . shift @search) =~ s/\.$//;
1251 root 1.61 my $depth = 10;
1252 root 1.1
1253     # advance in cname-chain
1254 root 1.22 $do_req = sub {
1255 root 1.1 $self->request ({
1256     rd => 1,
1257     qd => [[$name, $qtype, $class]],
1258     }, sub {
1259     my ($res) = @_
1260     or return $do_search->();
1261    
1262     my $cname;
1263    
1264     while () {
1265 root 1.2 # results found?
1266 root 1.4 my @rr = grep $name eq lc $_->[0] && ($atype{"*"} || $atype{$_->[1]}), @{ $res->{an} };
1267 root 1.1
1268 root 1.22 (undef $do_search), (undef $do_req), return $cb->(@rr)
1269 root 1.1 if @rr;
1270    
1271     # see if there is a cname we can follow
1272 root 1.4 my @rr = grep $name eq lc $_->[0] && $_->[1] eq "cname", @{ $res->{an} };
1273 root 1.1
1274     if (@rr) {
1275     $depth--
1276     or return $do_search->(); # cname chain too long
1277    
1278     $cname = 1;
1279     $name = $rr[0][3];
1280    
1281     } elsif ($cname) {
1282     # follow the cname
1283     return $do_req->();
1284    
1285     } else {
1286 root 1.2 # no, not found anything
1287 root 1.1 return $do_search->();
1288     }
1289     }
1290     });
1291     };
1292    
1293     $do_req->();
1294     };
1295    
1296     $do_search->();
1297     }
1298    
1299 root 1.51 =item $resolver->wait_for_slot ($cb->($resolver))
1300    
1301     Wait until a free request slot is available and call the callback with the
1302     resolver object.
1303    
1304     A request slot is used each time a request is actually sent to the
1305     nameservers: There are never more than C<max_outstanding> of them.
1306    
1307     Although you can submit more requests (they will simply be queued until
1308     a request slot becomes available), sometimes, usually for rate-limiting
1309     purposes, it is useful to instead wait for a slot before generating the
1310     request (or simply to know when the request load is low enough so one can
1311     submit requests again).
1312    
1313     This is what this method does: The callback will be called when submitting
1314     a DNS request will not result in that request being queued. The callback
1315     may or may not generate any requests in response.
1316    
1317     Note that the callback will only be invoked when the request queue is
1318     empty, so this does not play well if somebody else keeps the request queue
1319     full at all times.
1320    
1321     =cut
1322    
1323     sub wait_for_slot {
1324     my ($self, $cb) = @_;
1325    
1326     push @{ $self->{wait} }, $cb;
1327     $self->_scheduler;
1328     }
1329    
1330 root 1.17 use AnyEvent::Socket (); # circular dependency, so do not import anything and do it at the end
1331    
1332 root 1.1 1;
1333    
1334     =back
1335    
1336     =head1 AUTHOR
1337    
1338 root 1.58 Marc Lehmann <schmorp@schmorp.de>
1339     http://home.schmorp.de/
1340 root 1.1
1341     =cut
1342