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