ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/DNS.pm
Revision: 1.81
Committed: Fri Nov 21 01:35:59 2008 UTC (15 years, 7 months ago) by root
Branch: MAIN
CVS Tags: rel-4_33
Changes since 1.80: +1 -1 lines
Log Message:
4.33

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.81 our $VERSION = 4.33;
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.5 opt => 41,
358     spf => 99,
359     tkey => 249,
360     tsig => 250,
361     ixfr => 251,
362 root 1.1 axfr => 252,
363     mailb => 253,
364     "*" => 255,
365     );
366    
367     our %type_str = reverse %type_id;
368    
369     our %class_id = (
370 root 1.5 in => 1,
371     ch => 3,
372     hs => 4,
373     none => 254,
374     "*" => 255,
375 root 1.1 );
376    
377     our %class_str = reverse %class_id;
378    
379 root 1.34 sub _enc_name($) {
380 root 1.29 pack "(C/a*)*", (split /\./, shift), ""
381 root 1.1 }
382    
383     sub _enc_qd() {
384 root 1.34 (_enc_name $_->[0]) . pack "nn",
385 root 1.1 ($_->[1] > 0 ? $_->[1] : $type_id {$_->[1]}),
386     ($_->[2] > 0 ? $_->[2] : $class_id{$_->[2] || "in"})
387     }
388    
389     sub _enc_rr() {
390     die "encoding of resource records is not supported";
391     }
392    
393     =item $pkt = AnyEvent::DNS::dns_pack $dns
394    
395 root 1.50 Packs a perl data structure into a DNS packet. Reading RFC 1035 is strongly
396 root 1.1 recommended, then everything will be totally clear. Or maybe not.
397    
398     Resource records are not yet encodable.
399    
400     Examples:
401    
402 root 1.57 # very simple request, using lots of default values:
403     { rd => 1, qd => [ [ "host.domain", "a"] ] }
404    
405     # more complex example, showing how flags etc. are named:
406    
407     {
408     id => 10000,
409     op => "query",
410     rc => "nxdomain",
411    
412     # flags
413     qr => 1,
414     aa => 0,
415     tc => 0,
416     rd => 0,
417     ra => 0,
418     ad => 0,
419     cd => 0,
420    
421     qd => [@rr], # query section
422     an => [@rr], # answer section
423     ns => [@rr], # authority section
424     ar => [@rr], # additional records section
425     }
426 root 1.1
427     =cut
428    
429     sub dns_pack($) {
430     my ($req) = @_;
431    
432 root 1.7 pack "nn nnnn a* a* a* a* a*",
433 root 1.1 $req->{id},
434    
435     ! !$req->{qr} * 0x8000
436     + $opcode_id{$req->{op}} * 0x0800
437     + ! !$req->{aa} * 0x0400
438     + ! !$req->{tc} * 0x0200
439     + ! !$req->{rd} * 0x0100
440     + ! !$req->{ra} * 0x0080
441 root 1.5 + ! !$req->{ad} * 0x0020
442     + ! !$req->{cd} * 0x0010
443 root 1.1 + $rcode_id{$req->{rc}} * 0x0001,
444    
445     scalar @{ $req->{qd} || [] },
446     scalar @{ $req->{an} || [] },
447     scalar @{ $req->{ns} || [] },
448 root 1.44 $EDNS0 + scalar @{ $req->{ar} || [] }, # EDNS0 option included here
449 root 1.1
450     (join "", map _enc_qd, @{ $req->{qd} || [] }),
451     (join "", map _enc_rr, @{ $req->{an} || [] }),
452     (join "", map _enc_rr, @{ $req->{ns} || [] }),
453 root 1.7 (join "", map _enc_rr, @{ $req->{ar} || [] }),
454    
455 root 1.44 ($EDNS0 ? pack "C nnNn", 0, 41, MAX_PKT, 0, 0 : "") # EDNS0 option
456 root 1.1 }
457    
458     our $ofs;
459     our $pkt;
460    
461     # bitches
462 root 1.34 sub _dec_name {
463 root 1.1 my @res;
464     my $redir;
465     my $ptr = $ofs;
466     my $cnt;
467    
468     while () {
469     return undef if ++$cnt >= 256; # to avoid DoS attacks
470    
471     my $len = ord substr $pkt, $ptr++, 1;
472    
473 root 1.34 if ($len >= 0xc0) {
474 root 1.1 $ptr++;
475     $ofs = $ptr if $ptr > $ofs;
476     $ptr = (unpack "n", substr $pkt, $ptr - 2, 2) & 0x3fff;
477     } elsif ($len) {
478     push @res, substr $pkt, $ptr, $len;
479     $ptr += $len;
480     } else {
481     $ofs = $ptr if $ptr > $ofs;
482     return join ".", @res;
483     }
484     }
485     }
486    
487     sub _dec_qd {
488 root 1.34 my $qname = _dec_name;
489 root 1.1 my ($qt, $qc) = unpack "nn", substr $pkt, $ofs; $ofs += 4;
490     [$qname, $type_str{$qt} || $qt, $class_str{$qc} || $qc]
491     }
492    
493     our %dec_rr = (
494 root 1.29 1 => sub { join ".", unpack "C4", $_ }, # a
495 root 1.34 2 => sub { local $ofs = $ofs - length; _dec_name }, # ns
496     5 => sub { local $ofs = $ofs - length; _dec_name }, # cname
497 root 1.1 6 => sub {
498     local $ofs = $ofs - length;
499 root 1.34 my $mname = _dec_name;
500     my $rname = _dec_name;
501 root 1.1 ($mname, $rname, unpack "NNNNN", substr $pkt, $ofs)
502     }, # soa
503 root 1.29 11 => sub { ((join ".", unpack "C4", $_), unpack "C a*", substr $_, 4) }, # wks
504 root 1.34 12 => sub { local $ofs = $ofs - length; _dec_name }, # ptr
505 root 1.29 13 => sub { unpack "C/a* C/a*", $_ }, # hinfo
506 root 1.34 15 => sub { local $ofs = $ofs + 2 - length; ((unpack "n", $_), _dec_name) }, # mx
507 root 1.29 16 => sub { unpack "(C/a*)*", $_ }, # txt
508 root 1.36 28 => sub { AnyEvent::Socket::format_address ($_) }, # aaaa
509 root 1.34 33 => sub { local $ofs = $ofs + 6 - length; ((unpack "nnn", $_), _dec_name) }, # srv
510 root 1.47 35 => sub { # naptr
511 root 1.66 # requires perl 5.10, sorry
512 root 1.47 my ($order, $preference, $flags, $service, $regexp, $offset) = unpack "nn C/a* C/a* C/a* .", $_;
513     local $ofs = $ofs + $offset - length;
514     ($order, $preference, $flags, $service, $regexp, _dec_name)
515     },
516 root 1.29 99 => sub { unpack "(C/a*)*", $_ }, # spf
517 root 1.1 );
518    
519     sub _dec_rr {
520 root 1.34 my $name = _dec_name;
521 root 1.1
522     my ($rt, $rc, $ttl, $rdlen) = unpack "nn N n", substr $pkt, $ofs; $ofs += 10;
523     local $_ = substr $pkt, $ofs, $rdlen; $ofs += $rdlen;
524    
525     [
526 root 1.34 $name,
527 root 1.1 $type_str{$rt} || $rt,
528     $class_str{$rc} || $rc,
529     ($dec_rr{$rt} || sub { $_ })->(),
530     ]
531     }
532    
533     =item $dns = AnyEvent::DNS::dns_unpack $pkt
534    
535     Unpacks a DNS packet into a perl data structure.
536    
537     Examples:
538    
539 root 1.57 # an unsuccessful reply
540     {
541     'qd' => [
542     [ 'ruth.plan9.de.mach.uni-karlsruhe.de', '*', 'in' ]
543     ],
544     'rc' => 'nxdomain',
545     'ar' => [],
546     'ns' => [
547     [
548     'uni-karlsruhe.de',
549     'soa',
550     'in',
551     'netserv.rz.uni-karlsruhe.de',
552     'hostmaster.rz.uni-karlsruhe.de',
553     2008052201, 10800, 1800, 2592000, 86400
554     ]
555     ],
556     'tc' => '',
557     'ra' => 1,
558     'qr' => 1,
559     'id' => 45915,
560     'aa' => '',
561     'an' => [],
562     'rd' => 1,
563     'op' => 'query'
564     }
565    
566     # a successful reply
567    
568     {
569     'qd' => [ [ 'www.google.de', 'a', 'in' ] ],
570     'rc' => 0,
571     'ar' => [
572     [ 'a.l.google.com', 'a', 'in', '209.85.139.9' ],
573     [ 'b.l.google.com', 'a', 'in', '64.233.179.9' ],
574     [ 'c.l.google.com', 'a', 'in', '64.233.161.9' ],
575     ],
576     'ns' => [
577     [ 'l.google.com', 'ns', 'in', 'a.l.google.com' ],
578     [ 'l.google.com', 'ns', 'in', 'b.l.google.com' ],
579     ],
580     'tc' => '',
581     'ra' => 1,
582     'qr' => 1,
583     'id' => 64265,
584     'aa' => '',
585     'an' => [
586     [ 'www.google.de', 'cname', 'in', 'www.google.com' ],
587     [ 'www.google.com', 'cname', 'in', 'www.l.google.com' ],
588     [ 'www.l.google.com', 'a', 'in', '66.249.93.104' ],
589     [ 'www.l.google.com', 'a', 'in', '66.249.93.147' ],
590     ],
591     'rd' => 1,
592     'op' => 0
593     }
594 root 1.1
595     =cut
596    
597     sub dns_unpack($) {
598     local $pkt = shift;
599     my ($id, $flags, $qd, $an, $ns, $ar)
600     = unpack "nn nnnn A*", $pkt;
601    
602     local $ofs = 6 * 2;
603    
604     {
605     id => $id,
606     qr => ! ! ($flags & 0x8000),
607     aa => ! ! ($flags & 0x0400),
608     tc => ! ! ($flags & 0x0200),
609     rd => ! ! ($flags & 0x0100),
610     ra => ! ! ($flags & 0x0080),
611 root 1.5 ad => ! ! ($flags & 0x0020),
612     cd => ! ! ($flags & 0x0010),
613 root 1.1 op => $opcode_str{($flags & 0x001e) >> 11},
614     rc => $rcode_str{($flags & 0x000f)},
615    
616     qd => [map _dec_qd, 1 .. $qd],
617     an => [map _dec_rr, 1 .. $an],
618     ns => [map _dec_rr, 1 .. $ns],
619     ar => [map _dec_rr, 1 .. $ar],
620     }
621     }
622    
623     #############################################################################
624    
625     =back
626    
627     =head2 THE AnyEvent::DNS RESOLVER CLASS
628    
629 root 1.13 This is the class which does the actual protocol work.
630 root 1.1
631     =over 4
632    
633     =cut
634    
635     use Carp ();
636     use Scalar::Util ();
637     use Socket ();
638    
639     our $NOW;
640    
641 root 1.2 =item AnyEvent::DNS::resolver
642    
643     This function creates and returns a resolver that is ready to use and
644     should mimic the default resolver for your system as good as possible.
645    
646     It only ever creates one resolver and returns this one on subsequent
647     calls.
648    
649     Unless you have special needs, prefer this function over creating your own
650     resolver object.
651    
652     =cut
653    
654     our $RESOLVER;
655    
656     sub resolver() {
657     $RESOLVER || do {
658     $RESOLVER = new AnyEvent::DNS;
659 root 1.14 $RESOLVER->os_config;
660 root 1.2 $RESOLVER
661     }
662     }
663    
664 root 1.1 =item $resolver = new AnyEvent::DNS key => value...
665    
666 root 1.6 Creates and returns a new resolver.
667 root 1.2
668     The following options are supported:
669 root 1.1
670     =over 4
671    
672     =item server => [...]
673    
674 root 1.41 A list of server addresses (default: C<v127.0.0.1>) in network format
675 root 1.42 (i.e. as returned by C<AnyEvent::Socket::parse_address> - both IPv4 and
676 root 1.41 IPv6 are supported).
677 root 1.1
678     =item timeout => [...]
679    
680     A list of timeouts to use (also determines the number of retries). To make
681     three retries with individual time-outs of 2, 5 and 5 seconds, use C<[2,
682     5, 5]>, which is also the default.
683    
684     =item search => [...]
685    
686     The default search list of suffixes to append to a domain name (default: none).
687    
688 root 1.2 =item ndots => $integer
689 root 1.1
690     The number of dots (default: C<1>) that a name must have so that the resolver
691     tries to resolve the name without any suffixes first.
692    
693 root 1.2 =item max_outstanding => $integer
694 root 1.1
695 root 1.43 Most name servers do not handle many parallel requests very well. This
696     option limits the number of outstanding requests to C<$integer>
697     (default: C<10>), that means if you request more than this many requests,
698     then the additional requests will be queued until some other requests have
699     been resolved.
700 root 1.1
701 root 1.13 =item reuse => $seconds
702    
703 root 1.22 The number of seconds (default: C<300>) that a query id cannot be re-used
704 root 1.54 after a timeout. If there was no time-out then query ids can be reused
705 root 1.22 immediately.
706 root 1.13
707 root 1.1 =back
708    
709     =cut
710    
711     sub new {
712     my ($class, %arg) = @_;
713    
714     my $self = bless {
715 root 1.32 server => [],
716 root 1.1 timeout => [2, 5, 5],
717     search => [],
718     ndots => 1,
719     max_outstanding => 10,
720 root 1.54 reuse => 300,
721 root 1.1 %arg,
722     reuse_q => [],
723     }, $class;
724    
725     # search should default to gethostname's domain
726     # but perl lacks a good posix module
727    
728 root 1.63 # try to create an ipv4 and an ipv6 socket
729     # only fail when we cannot create either
730     my $got_socket;
731    
732 root 1.1 Scalar::Util::weaken (my $wself = $self);
733 root 1.38
734 root 1.63 if (socket my $fh4, AF_INET , &Socket::SOCK_DGRAM, 0) {
735     ++$got_socket;
736    
737 root 1.38 AnyEvent::Util::fh_nonblocking $fh4, 1;
738     $self->{fh4} = $fh4;
739     $self->{rw4} = AnyEvent->io (fh => $fh4, poll => "r", cb => sub {
740     if (my $peer = recv $fh4, my $pkt, MAX_PKT, 0) {
741     $wself->_recv ($pkt, $peer);
742     }
743     });
744     }
745    
746 root 1.63 if (AF_INET6 && socket my $fh6, AF_INET6, &Socket::SOCK_DGRAM, 0) {
747     ++$got_socket;
748    
749 root 1.38 $self->{fh6} = $fh6;
750     AnyEvent::Util::fh_nonblocking $fh6, 1;
751     $self->{rw6} = AnyEvent->io (fh => $fh6, poll => "r", cb => sub {
752     if (my $peer = recv $fh6, my $pkt, MAX_PKT, 0) {
753     $wself->_recv ($pkt, $peer);
754     }
755     });
756     }
757 root 1.1
758 root 1.63 $got_socket
759     or Carp::croak "unable to create either an IPv4 or an IPv6 socket";
760    
761 root 1.1 $self->_compile;
762    
763     $self
764     }
765    
766     =item $resolver->parse_resolv_conv ($string)
767    
768 root 1.24 Parses the given string as if it were a F<resolv.conf> file. The following
769     directives are supported (but not necessarily implemented).
770 root 1.1
771     C<#>-style comments, C<nameserver>, C<domain>, C<search>, C<sortlist>,
772     C<options> (C<timeout>, C<attempts>, C<ndots>).
773    
774     Everything else is silently ignored.
775    
776     =cut
777    
778     sub parse_resolv_conf {
779     my ($self, $resolvconf) = @_;
780    
781     $self->{server} = [];
782     $self->{search} = [];
783    
784     my $attempts;
785    
786     for (split /\n/, $resolvconf) {
787     if (/^\s*#/) {
788     # comment
789     } elsif (/^\s*nameserver\s+(\S+)\s*$/i) {
790     my $ip = $1;
791 root 1.36 if (my $ipn = AnyEvent::Socket::parse_address ($ip)) {
792 root 1.25 push @{ $self->{server} }, $ipn;
793 root 1.1 } else {
794     warn "nameserver $ip invalid and ignored\n";
795     }
796     } elsif (/^\s*domain\s+(\S*)\s+$/i) {
797     $self->{search} = [$1];
798     } elsif (/^\s*search\s+(.*?)\s*$/i) {
799     $self->{search} = [split /\s+/, $1];
800     } elsif (/^\s*sortlist\s+(.*?)\s*$/i) {
801     # ignored, NYI
802     } elsif (/^\s*options\s+(.*?)\s*$/i) {
803     for (split /\s+/, $1) {
804     if (/^timeout:(\d+)$/) {
805     $self->{timeout} = [$1];
806     } elsif (/^attempts:(\d+)$/) {
807     $attempts = $1;
808     } elsif (/^ndots:(\d+)$/) {
809     $self->{ndots} = $1;
810     } else {
811     # debug, rotate, no-check-names, inet6
812     }
813     }
814     }
815     }
816    
817     $self->{timeout} = [($self->{timeout}[0]) x $attempts]
818     if $attempts;
819    
820     $self->_compile;
821     }
822    
823 root 1.14 =item $resolver->os_config
824 root 1.1
825 root 1.24 Tries so load and parse F</etc/resolv.conf> on portable operating systems. Tries various
826     egregious hacks on windows to force the DNS servers and searchlist out of the system.
827 root 1.1
828     =cut
829    
830 root 1.14 sub os_config {
831 root 1.1 my ($self) = @_;
832    
833 root 1.32 $self->{server} = [];
834     $self->{search} = [];
835    
836 root 1.35 if (AnyEvent::WIN32 || $^O =~ /cygwin/i) {
837 root 1.32 no strict 'refs';
838    
839     # there are many options to find the current nameservers etc. on windows
840     # all of them don't work consistently:
841     # - the registry thing needs separate code on win32 native vs. cygwin
842     # - the registry layout differs between windows versions
843     # - calling windows api functions doesn't work on cygwin
844     # - ipconfig uses locale-specific messages
845    
846 root 1.54 # we use ipconfig parsing because, despite all its brokenness,
847 root 1.32 # it seems most stable in practise.
848     # for good measure, we append a fallback nameserver to our list.
849 root 1.14
850     if (open my $fh, "ipconfig /all |") {
851 root 1.32 # parsing strategy: we go through the output and look for
852     # :-lines with DNS in them. everything in those is regarded as
853     # either a nameserver (if it parses as an ip address), or a suffix
854     # (all else).
855 root 1.14
856 root 1.32 my $dns;
857 root 1.14 while (<$fh>) {
858 root 1.32 if (s/^\s.*\bdns\b.*://i) {
859     $dns = 1;
860     } elsif (/^\S/ || /^\s[^:]{16,}: /) {
861     $dns = 0;
862     }
863     if ($dns && /^\s*(\S+)\s*$/) {
864     my $s = $1;
865 root 1.54 $s =~ s/%\d+(?!\S)//; # get rid of ipv6 scope id
866 root 1.36 if (my $ipn = AnyEvent::Socket::parse_address ($s)) {
867 root 1.32 push @{ $self->{server} }, $ipn;
868     } else {
869     push @{ $self->{search} }, $s;
870 root 1.14 }
871     }
872     }
873    
874 root 1.32 # always add one fallback server
875     push @{ $self->{server} }, $DNS_FALLBACK[rand @DNS_FALLBACK];
876 root 1.14
877     $self->_compile;
878     }
879     } else {
880     # try resolv.conf everywhere
881 root 1.1
882 root 1.14 if (open my $fh, "</etc/resolv.conf") {
883     local $/;
884     $self->parse_resolv_conf (<$fh>);
885     }
886     }
887 root 1.1 }
888    
889 root 1.53 =item $resolver->timeout ($timeout, ...)
890    
891     Sets the timeout values. See the C<timeout> constructor argument (and note
892 root 1.54 that this method uses the values itself, not an array-reference).
893 root 1.53
894     =cut
895    
896     sub timeout {
897     my ($self, @timeout) = @_;
898    
899     $self->{timeout} = \@timeout;
900     $self->_compile;
901     }
902    
903     =item $resolver->max_outstanding ($nrequests)
904    
905     Sets the maximum number of outstanding requests to C<$nrequests>. See the
906     C<max_outstanding> constructor argument.
907    
908     =cut
909    
910     sub max_outstanding {
911     my ($self, $max) = @_;
912    
913     $self->{max_outstanding} = $max;
914     $self->_scheduler;
915     }
916    
917 root 1.1 sub _compile {
918     my $self = shift;
919    
920 root 1.38 my %search; $self->{search} = [grep 0 < length, grep !$search{$_}++, @{ $self->{search} }];
921     my %server; $self->{server} = [grep 0 < length, grep !$server{$_}++, @{ $self->{server} }];
922 root 1.32
923     unless (@{ $self->{server} }) {
924     # use 127.0.0.1 by default, and one opendns nameserver as fallback
925     $self->{server} = [v127.0.0.1, $DNS_FALLBACK[rand @DNS_FALLBACK]];
926     }
927    
928 root 1.1 my @retry;
929    
930     for my $timeout (@{ $self->{timeout} }) {
931     for my $server (@{ $self->{server} }) {
932     push @retry, [$server, $timeout];
933     }
934     }
935    
936     $self->{retry} = \@retry;
937     }
938    
939 root 1.6 sub _feed {
940     my ($self, $res) = @_;
941    
942     $res = dns_unpack $res
943     or return;
944    
945     my $id = $self->{id}{$res->{id}};
946    
947     return unless ref $id;
948    
949     $NOW = time;
950     $id->[1]->($res);
951     }
952    
953 root 1.1 sub _recv {
954 root 1.38 my ($self, $pkt, $peer) = @_;
955 root 1.1
956 root 1.32 # we ignore errors (often one gets port unreachable, but there is
957     # no good way to take advantage of that.
958 root 1.1
959 root 1.38 my ($port, $host) = AnyEvent::Socket::unpack_sockaddr ($peer);
960    
961     return unless $port == 53 && grep $_ eq $host, @{ $self->{server} };
962 root 1.1
963 root 1.38 $self->_feed ($pkt);
964 root 1.1 }
965    
966 root 1.22 sub _free_id {
967     my ($self, $id, $timeout) = @_;
968    
969     if ($timeout) {
970     # we need to block the id for a while
971     $self->{id}{$id} = 1;
972     push @{ $self->{reuse_q} }, [$NOW + $self->{reuse}, $id];
973     } else {
974     # we can quickly recycle the id
975     delete $self->{id}{$id};
976     }
977    
978     --$self->{outstanding};
979     $self->_scheduler;
980     }
981    
982     # execute a single request, involves sending it with timeouts to multiple servers
983 root 1.1 sub _exec {
984 root 1.22 my ($self, $req) = @_;
985    
986     my $retry; # of retries
987     my $do_retry;
988    
989     $do_retry = sub {
990     my $retry_cfg = $self->{retry}[$retry++]
991     or do {
992     # failure
993     $self->_free_id ($req->[2], $retry > 1);
994     undef $do_retry; return $req->[1]->();
995     };
996 root 1.1
997     my ($server, $timeout) = @$retry_cfg;
998    
999     $self->{id}{$req->[2]} = [AnyEvent->timer (after => $timeout, cb => sub {
1000     $NOW = time;
1001    
1002     # timeout, try next
1003 root 1.70 &$do_retry if $do_retry;
1004 root 1.1 }), sub {
1005     my ($res) = @_;
1006    
1007 root 1.6 if ($res->{tc}) {
1008     # success, but truncated, so use tcp
1009 root 1.38 AnyEvent::Socket::tcp_connect (AnyEvent::Socket::format_address ($server), DOMAIN_PORT, sub {
1010 root 1.52 return unless $do_retry; # some other request could have invalidated us already
1011    
1012 root 1.6 my ($fh) = @_
1013 root 1.22 or return &$do_retry;
1014 root 1.6
1015 root 1.52 my $handle; $handle = new AnyEvent::Handle
1016 root 1.6 fh => $fh,
1017 root 1.52 timeout => $timeout,
1018 root 1.6 on_error => sub {
1019 root 1.52 undef $handle;
1020     return unless $do_retry; # some other request could have invalidated us already
1021 root 1.6 # failure, try next
1022 root 1.22 &$do_retry;
1023 root 1.6 };
1024    
1025     $handle->push_write (pack "n/a", $req->[0]);
1026 root 1.27 $handle->push_read (chunk => 2, sub {
1027     $handle->unshift_read (chunk => (unpack "n", $_[1]), sub {
1028 root 1.52 undef $handle;
1029 root 1.6 $self->_feed ($_[1]);
1030     });
1031     });
1032    
1033 root 1.17 }, sub { $timeout });
1034 root 1.1
1035 root 1.6 } else {
1036     # success
1037 root 1.22 $self->_free_id ($req->[2], $retry > 1);
1038     undef $do_retry; return $req->[1]->($res);
1039 root 1.6 }
1040 root 1.1 }];
1041 root 1.38
1042     my $sa = AnyEvent::Socket::pack_sockaddr (DOMAIN_PORT, $server);
1043    
1044 root 1.39 my $fh = AF_INET == Socket::sockaddr_family ($sa)
1045 root 1.38 ? $self->{fh4} : $self->{fh6}
1046     or return &$do_retry;
1047 root 1.1
1048 root 1.38 send $fh, $req->[0], 0, $sa;
1049 root 1.22 };
1050 root 1.1
1051 root 1.22 &$do_retry;
1052 root 1.1 }
1053    
1054     sub _scheduler {
1055     my ($self) = @_;
1056    
1057 root 1.51 no strict 'refs';
1058    
1059 root 1.1 $NOW = time;
1060    
1061     # first clear id reuse queue
1062     delete $self->{id}{ (shift @{ $self->{reuse_q} })->[1] }
1063 root 1.13 while @{ $self->{reuse_q} } && $self->{reuse_q}[0][0] <= $NOW;
1064 root 1.1
1065     while ($self->{outstanding} < $self->{max_outstanding}) {
1066 root 1.13
1067     if (@{ $self->{reuse_q} } >= 30000) {
1068     # we ran out of ID's, wait a bit
1069     $self->{reuse_to} ||= AnyEvent->timer (after => $self->{reuse_q}[0][0] - $NOW, cb => sub {
1070     delete $self->{reuse_to};
1071     $self->_scheduler;
1072     });
1073     last;
1074     }
1075    
1076 root 1.51 if (my $req = shift @{ $self->{queue} }) {
1077     # found a request in the queue, execute it
1078     while () {
1079     $req->[2] = int rand 65536;
1080     last unless exists $self->{id}{$req->[2]};
1081     }
1082    
1083     ++$self->{outstanding};
1084     $self->{id}{$req->[2]} = 1;
1085     substr $req->[0], 0, 2, pack "n", $req->[2];
1086    
1087     $self->_exec ($req);
1088    
1089     } elsif (my $cb = shift @{ $self->{wait} }) {
1090     # found a wait_for_slot callback, call that one first
1091     $cb->($self);
1092 root 1.1
1093 root 1.51 } else {
1094     # nothing to do, just exit
1095     last;
1096 root 1.1 }
1097     }
1098     }
1099    
1100     =item $resolver->request ($req, $cb->($res))
1101    
1102 root 1.54 This is the main low-level workhorse for sending DNS requests.
1103    
1104     This function sends a single request (a hash-ref formated as specified
1105     for C<dns_pack>) to the configured nameservers in turn until it gets a
1106     response. It handles timeouts, retries and automatically falls back to
1107     virtual circuit mode (TCP) when it receives a truncated reply.
1108    
1109     Calls the callback with the decoded response packet if a reply was
1110     received, or no arguments in case none of the servers answered.
1111 root 1.1
1112     =cut
1113    
1114     sub request($$) {
1115     my ($self, $req, $cb) = @_;
1116    
1117 root 1.3 push @{ $self->{queue} }, [dns_pack $req, $cb];
1118 root 1.1 $self->_scheduler;
1119     }
1120    
1121 root 1.80 =item $resolver->resolve ($qname, $qtype, %options, $cb->(@rr))
1122 root 1.1
1123 root 1.44 Queries the DNS for the given domain name C<$qname> of type C<$qtype>.
1124    
1125 root 1.54 A C<$qtype> is either a numerical query type (e.g. C<1> for A records) or
1126 root 1.44 a lowercase name (you have to look at the source to see which aliases are
1127 root 1.50 supported, but all types from RFC 1035, C<aaaa>, C<srv>, C<spf> and a few
1128 root 1.54 more are known to this module). A C<$qtype> of "*" is supported and means
1129 root 1.44 "any" record type.
1130 root 1.1
1131     The callback will be invoked with a list of matching result records or
1132     none on any error or if the name could not be found.
1133    
1134 root 1.61 CNAME chains (although illegal) are followed up to a length of 10.
1135 root 1.1
1136 root 1.44 The callback will be invoked with an result code in string form (noerror,
1137     formerr, servfail, nxdomain, notimp, refused and so on), or numerical
1138     form if the result code is not supported. The remaining arguments are
1139     arraryefs of the form C<[$name, $type, $class, @data>], where C<$name> is
1140     the domain name, C<$type> a type string or number, C<$class> a class name
1141     and @data is resource-record-dependent data. For C<a> records, this will
1142     be the textual IPv4 addresses, for C<ns> or C<cname> records this will be
1143     a domain name, for C<txt> records these are all the strings and so on.
1144    
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