ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/DNS.pm
Revision: 1.62
Committed: Wed Jun 4 11:45:21 2008 UTC (16 years ago) by root
Branch: MAIN
Changes since 1.61: +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.6 use AnyEvent::Handle ();
38 root 1.37 use AnyEvent::Util qw(AF_INET6);
39 root 1.1
40 root 1.62 our $VERSION = 4.13;
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     for my $pri (sort { $a->[0] <=> $b->[0] } keys %pri) {
176     # 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     my ($order, $preference, $flags, $service, $regexp, $offset) = unpack "nn C/a* C/a* C/a* .", $_;
512     local $ofs = $ofs + $offset - length;
513     ($order, $preference, $flags, $service, $regexp, _dec_name)
514     },
515 root 1.29 99 => sub { unpack "(C/a*)*", $_ }, # spf
516 root 1.1 );
517    
518     sub _dec_rr {
519 root 1.34 my $name = _dec_name;
520 root 1.1
521     my ($rt, $rc, $ttl, $rdlen) = unpack "nn N n", substr $pkt, $ofs; $ofs += 10;
522     local $_ = substr $pkt, $ofs, $rdlen; $ofs += $rdlen;
523    
524     [
525 root 1.34 $name,
526 root 1.1 $type_str{$rt} || $rt,
527     $class_str{$rc} || $rc,
528     ($dec_rr{$rt} || sub { $_ })->(),
529     ]
530     }
531    
532     =item $dns = AnyEvent::DNS::dns_unpack $pkt
533    
534     Unpacks a DNS packet into a perl data structure.
535    
536     Examples:
537    
538 root 1.57 # an unsuccessful reply
539     {
540     'qd' => [
541     [ 'ruth.plan9.de.mach.uni-karlsruhe.de', '*', 'in' ]
542     ],
543     'rc' => 'nxdomain',
544     'ar' => [],
545     'ns' => [
546     [
547     'uni-karlsruhe.de',
548     'soa',
549     'in',
550     'netserv.rz.uni-karlsruhe.de',
551     'hostmaster.rz.uni-karlsruhe.de',
552     2008052201, 10800, 1800, 2592000, 86400
553     ]
554     ],
555     'tc' => '',
556     'ra' => 1,
557     'qr' => 1,
558     'id' => 45915,
559     'aa' => '',
560     'an' => [],
561     'rd' => 1,
562     'op' => 'query'
563     }
564    
565     # a successful reply
566    
567     {
568     'qd' => [ [ 'www.google.de', 'a', 'in' ] ],
569     'rc' => 0,
570     'ar' => [
571     [ 'a.l.google.com', 'a', 'in', '209.85.139.9' ],
572     [ 'b.l.google.com', 'a', 'in', '64.233.179.9' ],
573     [ 'c.l.google.com', 'a', 'in', '64.233.161.9' ],
574     ],
575     'ns' => [
576     [ 'l.google.com', 'ns', 'in', 'a.l.google.com' ],
577     [ 'l.google.com', 'ns', 'in', 'b.l.google.com' ],
578     ],
579     'tc' => '',
580     'ra' => 1,
581     'qr' => 1,
582     'id' => 64265,
583     'aa' => '',
584     'an' => [
585     [ 'www.google.de', 'cname', 'in', 'www.google.com' ],
586     [ 'www.google.com', 'cname', 'in', 'www.l.google.com' ],
587     [ 'www.l.google.com', 'a', 'in', '66.249.93.104' ],
588     [ 'www.l.google.com', 'a', 'in', '66.249.93.147' ],
589     ],
590     'rd' => 1,
591     'op' => 0
592     }
593 root 1.1
594     =cut
595    
596     sub dns_unpack($) {
597     local $pkt = shift;
598     my ($id, $flags, $qd, $an, $ns, $ar)
599     = unpack "nn nnnn A*", $pkt;
600    
601     local $ofs = 6 * 2;
602    
603     {
604     id => $id,
605     qr => ! ! ($flags & 0x8000),
606     aa => ! ! ($flags & 0x0400),
607     tc => ! ! ($flags & 0x0200),
608     rd => ! ! ($flags & 0x0100),
609     ra => ! ! ($flags & 0x0080),
610 root 1.5 ad => ! ! ($flags & 0x0020),
611     cd => ! ! ($flags & 0x0010),
612 root 1.1 op => $opcode_str{($flags & 0x001e) >> 11},
613     rc => $rcode_str{($flags & 0x000f)},
614    
615     qd => [map _dec_qd, 1 .. $qd],
616     an => [map _dec_rr, 1 .. $an],
617     ns => [map _dec_rr, 1 .. $ns],
618     ar => [map _dec_rr, 1 .. $ar],
619     }
620     }
621    
622     #############################################################################
623    
624     =back
625    
626     =head2 THE AnyEvent::DNS RESOLVER CLASS
627    
628 root 1.13 This is the class which does the actual protocol work.
629 root 1.1
630     =over 4
631    
632     =cut
633    
634     use Carp ();
635     use Scalar::Util ();
636     use Socket ();
637    
638     our $NOW;
639    
640 root 1.2 =item AnyEvent::DNS::resolver
641    
642     This function creates and returns a resolver that is ready to use and
643     should mimic the default resolver for your system as good as possible.
644    
645     It only ever creates one resolver and returns this one on subsequent
646     calls.
647    
648     Unless you have special needs, prefer this function over creating your own
649     resolver object.
650    
651     =cut
652    
653     our $RESOLVER;
654    
655     sub resolver() {
656     $RESOLVER || do {
657     $RESOLVER = new AnyEvent::DNS;
658 root 1.14 $RESOLVER->os_config;
659 root 1.2 $RESOLVER
660     }
661     }
662    
663 root 1.1 =item $resolver = new AnyEvent::DNS key => value...
664    
665 root 1.6 Creates and returns a new resolver.
666 root 1.2
667     The following options are supported:
668 root 1.1
669     =over 4
670    
671     =item server => [...]
672    
673 root 1.41 A list of server addresses (default: C<v127.0.0.1>) in network format
674 root 1.42 (i.e. as returned by C<AnyEvent::Socket::parse_address> - both IPv4 and
675 root 1.41 IPv6 are supported).
676 root 1.1
677     =item timeout => [...]
678    
679     A list of timeouts to use (also determines the number of retries). To make
680     three retries with individual time-outs of 2, 5 and 5 seconds, use C<[2,
681     5, 5]>, which is also the default.
682    
683     =item search => [...]
684    
685     The default search list of suffixes to append to a domain name (default: none).
686    
687 root 1.2 =item ndots => $integer
688 root 1.1
689     The number of dots (default: C<1>) that a name must have so that the resolver
690     tries to resolve the name without any suffixes first.
691    
692 root 1.2 =item max_outstanding => $integer
693 root 1.1
694 root 1.43 Most name servers do not handle many parallel requests very well. This
695     option limits the number of outstanding requests to C<$integer>
696     (default: C<10>), that means if you request more than this many requests,
697     then the additional requests will be queued until some other requests have
698     been resolved.
699 root 1.1
700 root 1.13 =item reuse => $seconds
701    
702 root 1.22 The number of seconds (default: C<300>) that a query id cannot be re-used
703 root 1.54 after a timeout. If there was no time-out then query ids can be reused
704 root 1.22 immediately.
705 root 1.13
706 root 1.1 =back
707    
708     =cut
709    
710     sub new {
711     my ($class, %arg) = @_;
712    
713 root 1.38 # try to create a ipv4 and an ipv6 socket
714     # only fail when we cnanot create either
715 root 1.1
716 root 1.38 socket my $fh4, AF_INET , &Socket::SOCK_DGRAM, 0;
717     socket my $fh6, AF_INET6, &Socket::SOCK_DGRAM, 0;
718    
719     $fh4 || $fh6
720     or Carp::croak "unable to create either an IPv6 or an IPv4 socket";
721 root 1.1
722     my $self = bless {
723 root 1.32 server => [],
724 root 1.1 timeout => [2, 5, 5],
725     search => [],
726     ndots => 1,
727     max_outstanding => 10,
728 root 1.54 reuse => 300,
729 root 1.1 %arg,
730     reuse_q => [],
731     }, $class;
732    
733     # search should default to gethostname's domain
734     # but perl lacks a good posix module
735    
736     Scalar::Util::weaken (my $wself = $self);
737 root 1.38
738     if ($fh4) {
739     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     if ($fh6) {
749     $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     $self->_compile;
759    
760     $self
761     }
762    
763     =item $resolver->parse_resolv_conv ($string)
764    
765 root 1.24 Parses the given string as if it were a F<resolv.conf> file. The following
766     directives are supported (but not necessarily implemented).
767 root 1.1
768     C<#>-style comments, C<nameserver>, C<domain>, C<search>, C<sortlist>,
769     C<options> (C<timeout>, C<attempts>, C<ndots>).
770    
771     Everything else is silently ignored.
772    
773     =cut
774    
775     sub parse_resolv_conf {
776     my ($self, $resolvconf) = @_;
777    
778     $self->{server} = [];
779     $self->{search} = [];
780    
781     my $attempts;
782    
783     for (split /\n/, $resolvconf) {
784     if (/^\s*#/) {
785     # comment
786     } elsif (/^\s*nameserver\s+(\S+)\s*$/i) {
787     my $ip = $1;
788 root 1.36 if (my $ipn = AnyEvent::Socket::parse_address ($ip)) {
789 root 1.25 push @{ $self->{server} }, $ipn;
790 root 1.1 } else {
791     warn "nameserver $ip invalid and ignored\n";
792     }
793     } elsif (/^\s*domain\s+(\S*)\s+$/i) {
794     $self->{search} = [$1];
795     } elsif (/^\s*search\s+(.*?)\s*$/i) {
796     $self->{search} = [split /\s+/, $1];
797     } elsif (/^\s*sortlist\s+(.*?)\s*$/i) {
798     # ignored, NYI
799     } elsif (/^\s*options\s+(.*?)\s*$/i) {
800     for (split /\s+/, $1) {
801     if (/^timeout:(\d+)$/) {
802     $self->{timeout} = [$1];
803     } elsif (/^attempts:(\d+)$/) {
804     $attempts = $1;
805     } elsif (/^ndots:(\d+)$/) {
806     $self->{ndots} = $1;
807     } else {
808     # debug, rotate, no-check-names, inet6
809     }
810     }
811     }
812     }
813    
814     $self->{timeout} = [($self->{timeout}[0]) x $attempts]
815     if $attempts;
816    
817     $self->_compile;
818     }
819    
820 root 1.14 =item $resolver->os_config
821 root 1.1
822 root 1.24 Tries so load and parse F</etc/resolv.conf> on portable operating systems. Tries various
823     egregious hacks on windows to force the DNS servers and searchlist out of the system.
824 root 1.1
825     =cut
826    
827 root 1.14 sub os_config {
828 root 1.1 my ($self) = @_;
829    
830 root 1.32 $self->{server} = [];
831     $self->{search} = [];
832    
833 root 1.35 if (AnyEvent::WIN32 || $^O =~ /cygwin/i) {
834 root 1.32 no strict 'refs';
835    
836     # there are many options to find the current nameservers etc. on windows
837     # all of them don't work consistently:
838     # - the registry thing needs separate code on win32 native vs. cygwin
839     # - the registry layout differs between windows versions
840     # - calling windows api functions doesn't work on cygwin
841     # - ipconfig uses locale-specific messages
842    
843 root 1.54 # we use ipconfig parsing because, despite all its brokenness,
844 root 1.32 # it seems most stable in practise.
845     # for good measure, we append a fallback nameserver to our list.
846 root 1.14
847     if (open my $fh, "ipconfig /all |") {
848 root 1.32 # parsing strategy: we go through the output and look for
849     # :-lines with DNS in them. everything in those is regarded as
850     # either a nameserver (if it parses as an ip address), or a suffix
851     # (all else).
852 root 1.14
853 root 1.32 my $dns;
854 root 1.14 while (<$fh>) {
855 root 1.32 if (s/^\s.*\bdns\b.*://i) {
856     $dns = 1;
857     } elsif (/^\S/ || /^\s[^:]{16,}: /) {
858     $dns = 0;
859     }
860     if ($dns && /^\s*(\S+)\s*$/) {
861     my $s = $1;
862 root 1.54 $s =~ s/%\d+(?!\S)//; # get rid of ipv6 scope id
863 root 1.36 if (my $ipn = AnyEvent::Socket::parse_address ($s)) {
864 root 1.32 push @{ $self->{server} }, $ipn;
865     } else {
866     push @{ $self->{search} }, $s;
867 root 1.14 }
868     }
869     }
870    
871 root 1.32 # always add one fallback server
872     push @{ $self->{server} }, $DNS_FALLBACK[rand @DNS_FALLBACK];
873 root 1.14
874     $self->_compile;
875     }
876     } else {
877     # try resolv.conf everywhere
878 root 1.1
879 root 1.14 if (open my $fh, "</etc/resolv.conf") {
880     local $/;
881     $self->parse_resolv_conf (<$fh>);
882     }
883     }
884 root 1.1 }
885    
886 root 1.53 =item $resolver->timeout ($timeout, ...)
887    
888     Sets the timeout values. See the C<timeout> constructor argument (and note
889 root 1.54 that this method uses the values itself, not an array-reference).
890 root 1.53
891     =cut
892    
893     sub timeout {
894     my ($self, @timeout) = @_;
895    
896     $self->{timeout} = \@timeout;
897     $self->_compile;
898     }
899    
900     =item $resolver->max_outstanding ($nrequests)
901    
902     Sets the maximum number of outstanding requests to C<$nrequests>. See the
903     C<max_outstanding> constructor argument.
904    
905     =cut
906    
907     sub max_outstanding {
908     my ($self, $max) = @_;
909    
910     $self->{max_outstanding} = $max;
911     $self->_scheduler;
912     }
913    
914 root 1.1 sub _compile {
915     my $self = shift;
916    
917 root 1.38 my %search; $self->{search} = [grep 0 < length, grep !$search{$_}++, @{ $self->{search} }];
918     my %server; $self->{server} = [grep 0 < length, grep !$server{$_}++, @{ $self->{server} }];
919 root 1.32
920     unless (@{ $self->{server} }) {
921     # use 127.0.0.1 by default, and one opendns nameserver as fallback
922     $self->{server} = [v127.0.0.1, $DNS_FALLBACK[rand @DNS_FALLBACK]];
923     }
924    
925 root 1.1 my @retry;
926    
927     for my $timeout (@{ $self->{timeout} }) {
928     for my $server (@{ $self->{server} }) {
929     push @retry, [$server, $timeout];
930     }
931     }
932    
933     $self->{retry} = \@retry;
934     }
935    
936 root 1.6 sub _feed {
937     my ($self, $res) = @_;
938    
939     $res = dns_unpack $res
940     or return;
941    
942     my $id = $self->{id}{$res->{id}};
943    
944     return unless ref $id;
945    
946     $NOW = time;
947     $id->[1]->($res);
948     }
949    
950 root 1.1 sub _recv {
951 root 1.38 my ($self, $pkt, $peer) = @_;
952 root 1.1
953 root 1.32 # we ignore errors (often one gets port unreachable, but there is
954     # no good way to take advantage of that.
955 root 1.1
956 root 1.38 my ($port, $host) = AnyEvent::Socket::unpack_sockaddr ($peer);
957    
958     return unless $port == 53 && grep $_ eq $host, @{ $self->{server} };
959 root 1.1
960 root 1.38 $self->_feed ($pkt);
961 root 1.1 }
962    
963 root 1.22 sub _free_id {
964     my ($self, $id, $timeout) = @_;
965    
966     if ($timeout) {
967     # we need to block the id for a while
968     $self->{id}{$id} = 1;
969     push @{ $self->{reuse_q} }, [$NOW + $self->{reuse}, $id];
970     } else {
971     # we can quickly recycle the id
972     delete $self->{id}{$id};
973     }
974    
975     --$self->{outstanding};
976     $self->_scheduler;
977     }
978    
979     # execute a single request, involves sending it with timeouts to multiple servers
980 root 1.1 sub _exec {
981 root 1.22 my ($self, $req) = @_;
982    
983     my $retry; # of retries
984     my $do_retry;
985    
986     $do_retry = sub {
987     my $retry_cfg = $self->{retry}[$retry++]
988     or do {
989     # failure
990     $self->_free_id ($req->[2], $retry > 1);
991     undef $do_retry; return $req->[1]->();
992     };
993 root 1.1
994     my ($server, $timeout) = @$retry_cfg;
995    
996     $self->{id}{$req->[2]} = [AnyEvent->timer (after => $timeout, cb => sub {
997     $NOW = time;
998    
999     # timeout, try next
1000 root 1.22 &$do_retry;
1001 root 1.1 }), sub {
1002     my ($res) = @_;
1003    
1004 root 1.6 if ($res->{tc}) {
1005     # success, but truncated, so use tcp
1006 root 1.38 AnyEvent::Socket::tcp_connect (AnyEvent::Socket::format_address ($server), DOMAIN_PORT, sub {
1007 root 1.52 return unless $do_retry; # some other request could have invalidated us already
1008    
1009 root 1.6 my ($fh) = @_
1010 root 1.22 or return &$do_retry;
1011 root 1.6
1012 root 1.52 my $handle; $handle = new AnyEvent::Handle
1013 root 1.6 fh => $fh,
1014 root 1.52 timeout => $timeout,
1015 root 1.6 on_error => sub {
1016 root 1.52 undef $handle;
1017     return unless $do_retry; # some other request could have invalidated us already
1018 root 1.6 # failure, try next
1019 root 1.22 &$do_retry;
1020 root 1.6 };
1021    
1022     $handle->push_write (pack "n/a", $req->[0]);
1023 root 1.27 $handle->push_read (chunk => 2, sub {
1024     $handle->unshift_read (chunk => (unpack "n", $_[1]), sub {
1025 root 1.52 undef $handle;
1026 root 1.6 $self->_feed ($_[1]);
1027     });
1028     });
1029    
1030 root 1.17 }, sub { $timeout });
1031 root 1.1
1032 root 1.6 } else {
1033     # success
1034 root 1.22 $self->_free_id ($req->[2], $retry > 1);
1035     undef $do_retry; return $req->[1]->($res);
1036 root 1.6 }
1037 root 1.1 }];
1038 root 1.38
1039     my $sa = AnyEvent::Socket::pack_sockaddr (DOMAIN_PORT, $server);
1040    
1041 root 1.39 my $fh = AF_INET == Socket::sockaddr_family ($sa)
1042 root 1.38 ? $self->{fh4} : $self->{fh6}
1043     or return &$do_retry;
1044 root 1.1
1045 root 1.38 send $fh, $req->[0], 0, $sa;
1046 root 1.22 };
1047 root 1.1
1048 root 1.22 &$do_retry;
1049 root 1.1 }
1050    
1051     sub _scheduler {
1052     my ($self) = @_;
1053    
1054 root 1.51 no strict 'refs';
1055    
1056 root 1.1 $NOW = time;
1057    
1058     # first clear id reuse queue
1059     delete $self->{id}{ (shift @{ $self->{reuse_q} })->[1] }
1060 root 1.13 while @{ $self->{reuse_q} } && $self->{reuse_q}[0][0] <= $NOW;
1061 root 1.1
1062     while ($self->{outstanding} < $self->{max_outstanding}) {
1063 root 1.13
1064     if (@{ $self->{reuse_q} } >= 30000) {
1065     # we ran out of ID's, wait a bit
1066     $self->{reuse_to} ||= AnyEvent->timer (after => $self->{reuse_q}[0][0] - $NOW, cb => sub {
1067     delete $self->{reuse_to};
1068     $self->_scheduler;
1069     });
1070     last;
1071     }
1072    
1073 root 1.51 if (my $req = shift @{ $self->{queue} }) {
1074     # found a request in the queue, execute it
1075     while () {
1076     $req->[2] = int rand 65536;
1077     last unless exists $self->{id}{$req->[2]};
1078     }
1079    
1080     ++$self->{outstanding};
1081     $self->{id}{$req->[2]} = 1;
1082     substr $req->[0], 0, 2, pack "n", $req->[2];
1083    
1084     $self->_exec ($req);
1085    
1086     } elsif (my $cb = shift @{ $self->{wait} }) {
1087     # found a wait_for_slot callback, call that one first
1088     $cb->($self);
1089 root 1.1
1090 root 1.51 } else {
1091     # nothing to do, just exit
1092     last;
1093 root 1.1 }
1094     }
1095     }
1096    
1097     =item $resolver->request ($req, $cb->($res))
1098    
1099 root 1.54 This is the main low-level workhorse for sending DNS requests.
1100    
1101     This function sends a single request (a hash-ref formated as specified
1102     for C<dns_pack>) to the configured nameservers in turn until it gets a
1103     response. It handles timeouts, retries and automatically falls back to
1104     virtual circuit mode (TCP) when it receives a truncated reply.
1105    
1106     Calls the callback with the decoded response packet if a reply was
1107     received, or no arguments in case none of the servers answered.
1108 root 1.1
1109     =cut
1110    
1111     sub request($$) {
1112     my ($self, $req, $cb) = @_;
1113    
1114 root 1.3 push @{ $self->{queue} }, [dns_pack $req, $cb];
1115 root 1.1 $self->_scheduler;
1116     }
1117    
1118     =item $resolver->resolve ($qname, $qtype, %options, $cb->($rcode, @rr))
1119    
1120 root 1.44 Queries the DNS for the given domain name C<$qname> of type C<$qtype>.
1121    
1122 root 1.54 A C<$qtype> is either a numerical query type (e.g. C<1> for A records) or
1123 root 1.44 a lowercase name (you have to look at the source to see which aliases are
1124 root 1.50 supported, but all types from RFC 1035, C<aaaa>, C<srv>, C<spf> and a few
1125 root 1.54 more are known to this module). A C<$qtype> of "*" is supported and means
1126 root 1.44 "any" record type.
1127 root 1.1
1128     The callback will be invoked with a list of matching result records or
1129     none on any error or if the name could not be found.
1130    
1131 root 1.61 CNAME chains (although illegal) are followed up to a length of 10.
1132 root 1.1
1133 root 1.44 The callback will be invoked with an result code in string form (noerror,
1134     formerr, servfail, nxdomain, notimp, refused and so on), or numerical
1135     form if the result code is not supported. The remaining arguments are
1136     arraryefs of the form C<[$name, $type, $class, @data>], where C<$name> is
1137     the domain name, C<$type> a type string or number, C<$class> a class name
1138     and @data is resource-record-dependent data. For C<a> records, this will
1139     be the textual IPv4 addresses, for C<ns> or C<cname> records this will be
1140     a domain name, for C<txt> records these are all the strings and so on.
1141    
1142 root 1.55 All types mentioned in RFC 1035, C<aaaa>, C<srv>, C<naptr> and C<spf> are
1143     decoded. All resource records not known to this module will have
1144 root 1.44 the raw C<rdata> field as fourth entry.
1145    
1146 root 1.24 Note that this resolver is just a stub resolver: it requires a name server
1147 root 1.3 supporting recursive queries, will not do any recursive queries itself and
1148     is not secure when used against an untrusted name server.
1149    
1150 root 1.1 The following options are supported:
1151    
1152     =over 4
1153    
1154     =item search => [$suffix...]
1155    
1156     Use the given search list (which might be empty), by appending each one
1157     in turn to the C<$qname>. If this option is missing then the configured
1158 root 1.55 C<ndots> and C<search> values define its value (depending on C<ndots>, the
1159     empty suffix will be prepended or appended to that C<search> value). If
1160     the C<$qname> ends in a dot, then the searchlist will be ignored.
1161 root 1.1
1162     =item accept => [$type...]
1163    
1164     Lists the acceptable result types: only result types in this set will be
1165     accepted and returned. The default includes the C<$qtype> and nothing
1166 root 1.44 else. If this list includes C<cname>, then CNAME-chains will not be
1167     followed (because you asked for the CNAME record).
1168 root 1.1
1169     =item class => "class"
1170    
1171     Specify the query class ("in" for internet, "ch" for chaosnet and "hs" for
1172 root 1.2 hesiod are the only ones making sense). The default is "in", of course.
1173 root 1.1
1174     =back
1175    
1176     Examples:
1177    
1178 root 1.46 # full example, you can paste this into perl:
1179 root 1.45 use Data::Dumper;
1180     use AnyEvent::DNS;
1181     AnyEvent::DNS::resolver->resolve (
1182     "google.com", "*", my $cv = AnyEvent->condvar);
1183     warn Dumper [$cv->recv];
1184    
1185     # shortened result:
1186     # [
1187     # [ 'google.com', 'soa', 'in', 'ns1.google.com', 'dns-admin.google.com',
1188     # 2008052701, 7200, 1800, 1209600, 300 ],
1189     # [
1190     # 'google.com', 'txt', 'in',
1191     # 'v=spf1 include:_netblocks.google.com ~all'
1192     # ],
1193     # [ 'google.com', 'a', 'in', '64.233.187.99' ],
1194     # [ 'google.com', 'mx', 'in', 10, 'smtp2.google.com' ],
1195     # [ 'google.com', 'ns', 'in', 'ns2.google.com' ],
1196     # ]
1197    
1198     # resolve a records:
1199     $res->resolve ("ruth.plan9.de", "a", sub { warn Dumper [@_] });
1200    
1201     # result:
1202     # [
1203     # [ 'ruth.schmorp.de', 'a', 'in', '129.13.162.95' ]
1204     # ]
1205 root 1.1
1206 root 1.45 # resolve any records, but return only a and aaaa records:
1207 root 1.1 $res->resolve ("test1.laendle", "*",
1208     accept => ["a", "aaaa"],
1209     sub {
1210     warn Dumper [@_];
1211     }
1212     );
1213    
1214 root 1.45 # result:
1215     # [
1216     # [ 'test1.laendle', 'a', 'in', '10.0.0.255' ],
1217     # [ 'test1.laendle', 'aaaa', 'in', '3ffe:1900:4545:0002:0240:0000:0000:f7e1' ]
1218     # ]
1219 root 1.1
1220     =cut
1221    
1222     sub resolve($%) {
1223     my $cb = pop;
1224     my ($self, $qname, $qtype, %opt) = @_;
1225    
1226     my @search = $qname =~ s/\.$//
1227     ? ""
1228     : $opt{search}
1229     ? @{ $opt{search} }
1230     : ($qname =~ y/.//) >= $self->{ndots}
1231     ? ("", @{ $self->{search} })
1232     : (@{ $self->{search} }, "");
1233    
1234     my $class = $opt{class} || "in";
1235    
1236     my %atype = $opt{accept}
1237     ? map +($_ => 1), @{ $opt{accept} }
1238     : ($qtype => 1);
1239    
1240     # advance in searchlist
1241 root 1.22 my ($do_search, $do_req);
1242    
1243     $do_search = sub {
1244 root 1.1 @search
1245 root 1.22 or (undef $do_search), (undef $do_req), return $cb->();
1246 root 1.1
1247 root 1.4 (my $name = lc "$qname." . shift @search) =~ s/\.$//;
1248 root 1.61 my $depth = 10;
1249 root 1.1
1250     # advance in cname-chain
1251 root 1.22 $do_req = sub {
1252 root 1.1 $self->request ({
1253     rd => 1,
1254     qd => [[$name, $qtype, $class]],
1255     }, sub {
1256     my ($res) = @_
1257     or return $do_search->();
1258    
1259     my $cname;
1260    
1261     while () {
1262 root 1.2 # results found?
1263 root 1.4 my @rr = grep $name eq lc $_->[0] && ($atype{"*"} || $atype{$_->[1]}), @{ $res->{an} };
1264 root 1.1
1265 root 1.22 (undef $do_search), (undef $do_req), return $cb->(@rr)
1266 root 1.1 if @rr;
1267    
1268     # see if there is a cname we can follow
1269 root 1.4 my @rr = grep $name eq lc $_->[0] && $_->[1] eq "cname", @{ $res->{an} };
1270 root 1.1
1271     if (@rr) {
1272     $depth--
1273     or return $do_search->(); # cname chain too long
1274    
1275     $cname = 1;
1276     $name = $rr[0][3];
1277    
1278     } elsif ($cname) {
1279     # follow the cname
1280     return $do_req->();
1281    
1282     } else {
1283 root 1.2 # no, not found anything
1284 root 1.1 return $do_search->();
1285     }
1286     }
1287     });
1288     };
1289    
1290     $do_req->();
1291     };
1292    
1293     $do_search->();
1294     }
1295    
1296 root 1.51 =item $resolver->wait_for_slot ($cb->($resolver))
1297    
1298     Wait until a free request slot is available and call the callback with the
1299     resolver object.
1300    
1301     A request slot is used each time a request is actually sent to the
1302     nameservers: There are never more than C<max_outstanding> of them.
1303    
1304     Although you can submit more requests (they will simply be queued until
1305     a request slot becomes available), sometimes, usually for rate-limiting
1306     purposes, it is useful to instead wait for a slot before generating the
1307     request (or simply to know when the request load is low enough so one can
1308     submit requests again).
1309    
1310     This is what this method does: The callback will be called when submitting
1311     a DNS request will not result in that request being queued. The callback
1312     may or may not generate any requests in response.
1313    
1314     Note that the callback will only be invoked when the request queue is
1315     empty, so this does not play well if somebody else keeps the request queue
1316     full at all times.
1317    
1318     =cut
1319    
1320     sub wait_for_slot {
1321     my ($self, $cb) = @_;
1322    
1323     push @{ $self->{wait} }, $cb;
1324     $self->_scheduler;
1325     }
1326    
1327 root 1.17 use AnyEvent::Socket (); # circular dependency, so do not import anything and do it at the end
1328    
1329 root 1.1 1;
1330    
1331     =back
1332    
1333     =head1 AUTHOR
1334    
1335 root 1.58 Marc Lehmann <schmorp@schmorp.de>
1336     http://home.schmorp.de/
1337 root 1.1
1338     =cut
1339