ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/DNS.pm
(Generate patch)

Comparing AnyEvent/lib/AnyEvent/DNS.pm (file contents):
Revision 1.61 by root, Wed Jun 4 09:55:16 2008 UTC vs.
Revision 1.106 by root, Fri Jul 17 18:08:35 2009 UTC

29package AnyEvent::DNS; 29package AnyEvent::DNS;
30 30
31no warnings; 31no warnings;
32use strict; 32use strict;
33 33
34use Carp ();
34use Socket qw(AF_INET SOCK_DGRAM SOCK_STREAM); 35use Socket qw(AF_INET SOCK_DGRAM SOCK_STREAM);
35 36
36use AnyEvent (); 37use AnyEvent ();
37use AnyEvent::Handle ();
38use AnyEvent::Util qw(AF_INET6); 38use AnyEvent::Util qw(AF_INET6);
39 39
40our $VERSION = 4.12; 40our $VERSION = 4.83;
41 41
42our @DNS_FALLBACK = (v208.67.220.220, v208.67.222.222); 42our @DNS_FALLBACK = (v208.67.220.220, v208.67.222.222);
43 43
44=item AnyEvent::DNS::a $domain, $cb->(@addrs) 44=item AnyEvent::DNS::a $domain, $cb->(@addrs)
45 45
170 my %pri; 170 my %pri;
171 push @{ $pri{$_->[3]} }, [ @$_[3,4,5,6] ] 171 push @{ $pri{$_->[3]} }, [ @$_[3,4,5,6] ]
172 for @_; 172 for @_;
173 173
174 # order by priority 174 # order by priority
175 for my $pri (sort { $a->[0] <=> $b->[0] } keys %pri) { 175 for my $pri (sort { $a <=> $b } keys %pri) {
176 # order by weight 176 # order by weight
177 my @rr = sort { $a->[1] <=> $b->[1] } @{ delete $pri{$pri} }; 177 my @rr = sort { $a->[1] <=> $b->[1] } @{ delete $pri{$pri} };
178 178
179 my $sum; $sum += $_->[1] for @rr; 179 my $sum; $sum += $_->[1] for @rr;
180 180
295C<$ENV{PERL_ANYEVENT_EDNS0}>, but when set to C<1>, AnyEvent::DNS will use 295C<$ENV{PERL_ANYEVENT_EDNS0}>, but when set to C<1>, AnyEvent::DNS will use
296EDNS0 in all requests. 296EDNS0 in all requests.
297 297
298=cut 298=cut
299 299
300our $EDNS0 = $ENV{PERL_ANYEVENT_EDNS0} * 1; # set to 1 to enable (partial) edns0 300our $EDNS0 = $ENV{PERL_ANYEVENT_EDNS0}*1; # set to 1 to enable (partial) edns0
301 301
302our %opcode_id = ( 302our %opcode_id = (
303 query => 0, 303 query => 0,
304 iquery => 1, 304 iquery => 1,
305 status => 2, 305 status => 2,
352 mx => 15, 352 mx => 15,
353 txt => 16, 353 txt => 16,
354 aaaa => 28, 354 aaaa => 28,
355 srv => 33, 355 srv => 33,
356 naptr => 35, # rfc2915 356 naptr => 35, # rfc2915
357 dname => 39, # rfc2672
357 opt => 41, 358 opt => 41,
358 spf => 99, 359 spf => 99,
359 tkey => 249, 360 tkey => 249,
360 tsig => 250, 361 tsig => 250,
361 ixfr => 251, 362 ixfr => 251,
376 377
377our %class_str = reverse %class_id; 378our %class_str = reverse %class_id;
378 379
379sub _enc_name($) { 380sub _enc_name($) {
380 pack "(C/a*)*", (split /\./, shift), "" 381 pack "(C/a*)*", (split /\./, shift), ""
382}
383
384if ($[ < 5.008) {
385 # special slower 5.6 version
386 *_enc_name = sub {
387 join "", map +(pack "C/a*", $_), (split /\./, shift), ""
388 };
381} 389}
382 390
383sub _enc_qd() { 391sub _enc_qd() {
384 (_enc_name $_->[0]) . pack "nn", 392 (_enc_name $_->[0]) . pack "nn",
385 ($_->[1] > 0 ? $_->[1] : $type_id {$_->[1]}), 393 ($_->[1] > 0 ? $_->[1] : $type_id {$_->[1]}),
503 11 => sub { ((join ".", unpack "C4", $_), unpack "C a*", substr $_, 4) }, # wks 511 11 => sub { ((join ".", unpack "C4", $_), unpack "C a*", substr $_, 4) }, # wks
504 12 => sub { local $ofs = $ofs - length; _dec_name }, # ptr 512 12 => sub { local $ofs = $ofs - length; _dec_name }, # ptr
505 13 => sub { unpack "C/a* C/a*", $_ }, # hinfo 513 13 => sub { unpack "C/a* C/a*", $_ }, # hinfo
506 15 => sub { local $ofs = $ofs + 2 - length; ((unpack "n", $_), _dec_name) }, # mx 514 15 => sub { local $ofs = $ofs + 2 - length; ((unpack "n", $_), _dec_name) }, # mx
507 16 => sub { unpack "(C/a*)*", $_ }, # txt 515 16 => sub { unpack "(C/a*)*", $_ }, # txt
508 28 => sub { AnyEvent::Socket::format_address ($_) }, # aaaa 516 28 => sub { AnyEvent::Socket::format_ipv6 ($_) }, # aaaa
509 33 => sub { local $ofs = $ofs + 6 - length; ((unpack "nnn", $_), _dec_name) }, # srv 517 33 => sub { local $ofs = $ofs + 6 - length; ((unpack "nnn", $_), _dec_name) }, # srv
510 35 => sub { # naptr 518 35 => sub { # naptr
519 # requires perl 5.10, sorry
511 my ($order, $preference, $flags, $service, $regexp, $offset) = unpack "nn C/a* C/a* C/a* .", $_; 520 my ($order, $preference, $flags, $service, $regexp, $offset) = unpack "nn C/a* C/a* C/a* .", $_;
512 local $ofs = $ofs + $offset - length; 521 local $ofs = $ofs + $offset - length;
513 ($order, $preference, $flags, $service, $regexp, _dec_name) 522 ($order, $preference, $flags, $service, $regexp, _dec_name)
514 }, 523 },
524 39 => sub { local $ofs = $ofs - length; _dec_name }, # dname
515 99 => sub { unpack "(C/a*)*", $_ }, # spf 525 99 => sub { unpack "(C/a*)*", $_ }, # spf
516); 526);
517 527
518sub _dec_rr { 528sub _dec_rr {
519 my $name = _dec_name; 529 my $name = _dec_name;
646calls. 656calls.
647 657
648Unless you have special needs, prefer this function over creating your own 658Unless you have special needs, prefer this function over creating your own
649resolver object. 659resolver object.
650 660
661The resolver is created with the following parameters:
662
663 untaint enabled
664 max_outstanding $ENV{PERL_ANYEVENT_MAX_OUTSTANDING_DNS}
665
666C<os_config> will be used for OS-specific configuration, unless
667C<$ENV{PERL_ANYEVENT_RESOLV_CONF}> is specified, in which case that file
668gets parsed.
669
651=cut 670=cut
652 671
653our $RESOLVER; 672our $RESOLVER;
654 673
655sub resolver() { 674sub resolver() {
656 $RESOLVER || do { 675 $RESOLVER || do {
657 $RESOLVER = new AnyEvent::DNS; 676 $RESOLVER = new AnyEvent::DNS
677 untaint => 1,
678 exists $ENV{PERL_ANYEVENT_MAX_OUTSTANDING_DNS}
679 ? (max_outstanding => $ENV{PERL_ANYEVENT_MAX_OUTSTANDING_DNS}*1 || 1) : (),
680 ;
681
682 exists $ENV{PERL_ANYEVENT_RESOLV_CONF}
683 ? length $ENV{PERL_ANYEVENT_RESOLV_CONF} && $RESOLVER->_parse_resolv_conf_file ($ENV{PERL_ANYEVENT_RESOLV_CONF})
658 $RESOLVER->os_config; 684 : $RESOLVER->os_config;
685
659 $RESOLVER 686 $RESOLVER
660 } 687 }
661} 688}
662 689
663=item $resolver = new AnyEvent::DNS key => value... 690=item $resolver = new AnyEvent::DNS key => value...
701 728
702The number of seconds (default: C<300>) that a query id cannot be re-used 729The number of seconds (default: C<300>) that a query id cannot be re-used
703after a timeout. If there was no time-out then query ids can be reused 730after a timeout. If there was no time-out then query ids can be reused
704immediately. 731immediately.
705 732
733=item untaint => $boolean
734
735When true, then the resolver will automatically untaint results, and might
736also ignore certain environment variables.
737
706=back 738=back
707 739
708=cut 740=cut
709 741
710sub new { 742sub new {
711 my ($class, %arg) = @_; 743 my ($class, %arg) = @_;
712
713 # try to create a ipv4 and an ipv6 socket
714 # only fail when we cnanot create either
715
716 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 744
722 my $self = bless { 745 my $self = bless {
723 server => [], 746 server => [],
724 timeout => [2, 5, 5], 747 timeout => [2, 5, 5],
725 search => [], 748 search => [],
731 }, $class; 754 }, $class;
732 755
733 # search should default to gethostname's domain 756 # search should default to gethostname's domain
734 # but perl lacks a good posix module 757 # but perl lacks a good posix module
735 758
759 # try to create an ipv4 and an ipv6 socket
760 # only fail when we cannot create either
761 my $got_socket;
762
736 Scalar::Util::weaken (my $wself = $self); 763 Scalar::Util::weaken (my $wself = $self);
737 764
738 if ($fh4) { 765 if (socket my $fh4, AF_INET , &Socket::SOCK_DGRAM, 0) {
766 ++$got_socket;
767
739 AnyEvent::Util::fh_nonblocking $fh4, 1; 768 AnyEvent::Util::fh_nonblocking $fh4, 1;
740 $self->{fh4} = $fh4; 769 $self->{fh4} = $fh4;
741 $self->{rw4} = AnyEvent->io (fh => $fh4, poll => "r", cb => sub { 770 $self->{rw4} = AnyEvent->io (fh => $fh4, poll => "r", cb => sub {
742 if (my $peer = recv $fh4, my $pkt, MAX_PKT, 0) { 771 if (my $peer = recv $fh4, my $pkt, MAX_PKT, 0) {
743 $wself->_recv ($pkt, $peer); 772 $wself->_recv ($pkt, $peer);
744 } 773 }
745 }); 774 });
746 } 775 }
747 776
748 if ($fh6) { 777 if (AF_INET6 && socket my $fh6, AF_INET6, &Socket::SOCK_DGRAM, 0) {
778 ++$got_socket;
779
749 $self->{fh6} = $fh6; 780 $self->{fh6} = $fh6;
750 AnyEvent::Util::fh_nonblocking $fh6, 1; 781 AnyEvent::Util::fh_nonblocking $fh6, 1;
751 $self->{rw6} = AnyEvent->io (fh => $fh6, poll => "r", cb => sub { 782 $self->{rw6} = AnyEvent->io (fh => $fh6, poll => "r", cb => sub {
752 if (my $peer = recv $fh6, my $pkt, MAX_PKT, 0) { 783 if (my $peer = recv $fh6, my $pkt, MAX_PKT, 0) {
753 $wself->_recv ($pkt, $peer); 784 $wself->_recv ($pkt, $peer);
754 } 785 }
755 }); 786 });
756 } 787 }
757 788
789 $got_socket
790 or Carp::croak "unable to create either an IPv4 or an IPv6 socket";
791
758 $self->_compile; 792 $self->_compile;
759 793
760 $self 794 $self
761} 795}
762 796
763=item $resolver->parse_resolv_conv ($string) 797=item $resolver->parse_resolv_conf ($string)
764 798
765Parses the given string as if it were a F<resolv.conf> file. The following 799Parses the given string as if it were a F<resolv.conf> file. The following
766directives are supported (but not necessarily implemented). 800directives are supported (but not necessarily implemented).
767 801
768C<#>-style comments, C<nameserver>, C<domain>, C<search>, C<sortlist>, 802C<#>-style comments, C<nameserver>, C<domain>, C<search>, C<sortlist>,
815 if $attempts; 849 if $attempts;
816 850
817 $self->_compile; 851 $self->_compile;
818} 852}
819 853
854sub _parse_resolv_conf_file {
855 my ($self, $resolv_conf) = @_;
856
857 open my $fh, "<", $resolv_conf
858 or Carp::croak "$resolv_conf: $!";
859
860 local $/;
861 $self->parse_resolv_conf (<$fh>);
862}
863
820=item $resolver->os_config 864=item $resolver->os_config
821 865
822Tries so load and parse F</etc/resolv.conf> on portable operating systems. Tries various 866Tries so load and parse F</etc/resolv.conf> on portable operating
823egregious hacks on windows to force the DNS servers and searchlist out of the system. 867systems. Tries various egregious hacks on windows to force the DNS servers
868and searchlist out of the system.
824 869
825=cut 870=cut
826 871
827sub os_config { 872sub os_config {
828 my ($self) = @_; 873 my ($self) = @_;
829 874
830 $self->{server} = []; 875 $self->{server} = [];
831 $self->{search} = []; 876 $self->{search} = [];
832 877
833 if (AnyEvent::WIN32 || $^O =~ /cygwin/i) { 878 if ((AnyEvent::WIN32 || $^O =~ /cygwin/i)) {
834 no strict 'refs'; 879 no strict 'refs';
835 880
836 # there are many options to find the current nameservers etc. on windows 881 # there are many options to find the current nameservers etc. on windows
837 # all of them don't work consistently: 882 # all of them don't work consistently:
838 # - the registry thing needs separate code on win32 native vs. cygwin 883 # - the registry thing needs separate code on win32 native vs. cygwin
872 push @{ $self->{server} }, $DNS_FALLBACK[rand @DNS_FALLBACK]; 917 push @{ $self->{server} }, $DNS_FALLBACK[rand @DNS_FALLBACK];
873 918
874 $self->_compile; 919 $self->_compile;
875 } 920 }
876 } else { 921 } else {
877 # try resolv.conf everywhere 922 # try resolv.conf everywhere else
878 923
879 if (open my $fh, "</etc/resolv.conf") { 924 $self->_parse_resolv_conf_file ("/etc/resolv.conf")
880 local $/; 925 if -e "/etc/resolv.conf";
881 $self->parse_resolv_conf (<$fh>);
882 }
883 } 926 }
884} 927}
885 928
886=item $resolver->timeout ($timeout, ...) 929=item $resolver->timeout ($timeout, ...)
887 930
933 $self->{retry} = \@retry; 976 $self->{retry} = \@retry;
934} 977}
935 978
936sub _feed { 979sub _feed {
937 my ($self, $res) = @_; 980 my ($self, $res) = @_;
981
982 ($res) = $res =~ /^(.*)$/s
983 if AnyEvent::TAINT && $self->{untaint};
938 984
939 $res = dns_unpack $res 985 $res = dns_unpack $res
940 or return; 986 or return;
941 987
942 my $id = $self->{id}{$res->{id}}; 988 my $id = $self->{id}{$res->{id}};
995 1041
996 $self->{id}{$req->[2]} = [AnyEvent->timer (after => $timeout, cb => sub { 1042 $self->{id}{$req->[2]} = [AnyEvent->timer (after => $timeout, cb => sub {
997 $NOW = time; 1043 $NOW = time;
998 1044
999 # timeout, try next 1045 # timeout, try next
1000 &$do_retry; 1046 &$do_retry if $do_retry;
1001 }), sub { 1047 }), sub {
1002 my ($res) = @_; 1048 my ($res) = @_;
1003 1049
1004 if ($res->{tc}) { 1050 if ($res->{tc}) {
1005 # success, but truncated, so use tcp 1051 # success, but truncated, so use tcp
1006 AnyEvent::Socket::tcp_connect (AnyEvent::Socket::format_address ($server), DOMAIN_PORT, sub { 1052 AnyEvent::Socket::tcp_connect (AnyEvent::Socket::format_address ($server), DOMAIN_PORT, sub {
1007 return unless $do_retry; # some other request could have invalidated us already 1053 return unless $do_retry; # some other request could have invalidated us already
1008 1054
1009 my ($fh) = @_ 1055 my ($fh) = @_
1010 or return &$do_retry; 1056 or return &$do_retry;
1057
1058 require AnyEvent::Handle;
1011 1059
1012 my $handle; $handle = new AnyEvent::Handle 1060 my $handle; $handle = new AnyEvent::Handle
1013 fh => $fh, 1061 fh => $fh,
1014 timeout => $timeout, 1062 timeout => $timeout,
1015 on_error => sub { 1063 on_error => sub {
1036 } 1084 }
1037 }]; 1085 }];
1038 1086
1039 my $sa = AnyEvent::Socket::pack_sockaddr (DOMAIN_PORT, $server); 1087 my $sa = AnyEvent::Socket::pack_sockaddr (DOMAIN_PORT, $server);
1040 1088
1041 my $fh = AF_INET == Socket::sockaddr_family ($sa) 1089 my $fh = AF_INET == AnyEvent::Socket::sockaddr_family ($sa)
1042 ? $self->{fh4} : $self->{fh6} 1090 ? $self->{fh4} : $self->{fh6}
1043 or return &$do_retry; 1091 or return &$do_retry;
1044 1092
1045 send $fh, $req->[0], 0, $sa; 1093 send $fh, $req->[0], 0, $sa;
1046 }; 1094 };
1113 1161
1114 push @{ $self->{queue} }, [dns_pack $req, $cb]; 1162 push @{ $self->{queue} }, [dns_pack $req, $cb];
1115 $self->_scheduler; 1163 $self->_scheduler;
1116} 1164}
1117 1165
1118=item $resolver->resolve ($qname, $qtype, %options, $cb->($rcode, @rr)) 1166=item $resolver->resolve ($qname, $qtype, %options, $cb->(@rr))
1119 1167
1120Queries the DNS for the given domain name C<$qname> of type C<$qtype>. 1168Queries the DNS for the given domain name C<$qname> of type C<$qtype>.
1121 1169
1122A C<$qtype> is either a numerical query type (e.g. C<1> for A records) or 1170A C<$qtype> is either a numerical query type (e.g. C<1> for A records) or
1123a lowercase name (you have to look at the source to see which aliases are 1171a lowercase name (you have to look at the source to see which aliases are
1128The callback will be invoked with a list of matching result records or 1176The callback will be invoked with a list of matching result records or
1129none on any error or if the name could not be found. 1177none on any error or if the name could not be found.
1130 1178
1131CNAME chains (although illegal) are followed up to a length of 10. 1179CNAME chains (although illegal) are followed up to a length of 10.
1132 1180
1133The callback will be invoked with an result code in string form (noerror, 1181The callback will be invoked with arraryefs of the form C<[$name, $type,
1134formerr, servfail, nxdomain, notimp, refused and so on), or numerical 1182$class, @data>], where C<$name> is the domain name, C<$type> a type string
1135form if the result code is not supported. The remaining arguments are 1183or number, C<$class> a class name and @data is resource-record-dependent
1136arraryefs of the form C<[$name, $type, $class, @data>], where C<$name> is 1184data. For C<a> records, this will be the textual IPv4 addresses, for C<ns>
1137the domain name, C<$type> a type string or number, C<$class> a class name 1185or C<cname> records this will be a domain name, for C<txt> records these
1138and @data is resource-record-dependent data. For C<a> records, this will 1186are all the strings and so on.
1139be the textual IPv4 addresses, for C<ns> or C<cname> records this will be
1140a domain name, for C<txt> records these are all the strings and so on.
1141 1187
1142All types mentioned in RFC 1035, C<aaaa>, C<srv>, C<naptr> and C<spf> are 1188All types mentioned in RFC 1035, C<aaaa>, C<srv>, C<naptr> and C<spf> are
1143decoded. All resource records not known to this module will have 1189decoded. All resource records not known to this module will have
1144the raw C<rdata> field as fourth entry. 1190the raw C<rdata> field as fourth entry.
1145 1191
1271 if (@rr) { 1317 if (@rr) {
1272 $depth-- 1318 $depth--
1273 or return $do_search->(); # cname chain too long 1319 or return $do_search->(); # cname chain too long
1274 1320
1275 $cname = 1; 1321 $cname = 1;
1276 $name = $rr[0][3]; 1322 $name = lc $rr[0][3];
1277 1323
1278 } elsif ($cname) { 1324 } elsif ($cname) {
1279 # follow the cname 1325 # follow the cname
1280 return $do_req->(); 1326 return $do_req->();
1281 1327

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines