ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/DNS.pm
Revision: 1.107
Committed: Fri Jul 17 23:12:20 2009 UTC (14 years, 11 months ago) by root
Branch: MAIN
Changes since 1.106: +1 -4 lines
Log Message:
*** empty log message ***

File Contents

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