… | |
… | |
24 | package AnyEvent::DNS; |
24 | package AnyEvent::DNS; |
25 | |
25 | |
26 | no warnings; |
26 | no warnings; |
27 | use strict; |
27 | use strict; |
28 | |
28 | |
29 | use AnyEvent::Socket (); |
|
|
30 | use AnyEvent::Handle (); |
29 | use AnyEvent::Handle (); |
31 | |
30 | |
32 | =item AnyEvent::DNS::addr $node, $service, $family, $type, $cb->(@addrs) |
31 | =item AnyEvent::DNS::addr $node, $service, $family, $type, $cb->(@addrs) |
33 | |
32 | |
34 | NOT YET IMPLEMENTED |
33 | NOT YET IMPLEMENTED |
… | |
… | |
44 | |
43 | |
45 | =item AnyEvent::DNS::a $domain, $cb->(@addrs) |
44 | =item AnyEvent::DNS::a $domain, $cb->(@addrs) |
46 | |
45 | |
47 | Tries to resolve the given domain to IPv4 address(es). |
46 | Tries to resolve the given domain to IPv4 address(es). |
48 | |
47 | |
|
|
48 | =item AnyEvent::DNS::aaaa $domain, $cb->(@addrs) |
|
|
49 | |
|
|
50 | Tries to resolve the given domain to IPv6 address(es). |
|
|
51 | |
49 | =item AnyEvent::DNS::mx $domain, $cb->(@hostnames) |
52 | =item AnyEvent::DNS::mx $domain, $cb->(@hostnames) |
50 | |
53 | |
51 | Tries to resolve the given domain into a sorted (lower preference value |
54 | Tries to resolve the given domain into a sorted (lower preference value |
52 | first) list of domain names. |
55 | first) list of domain names. |
53 | |
56 | |
… | |
… | |
78 | =item AnyEvent::DNS::ptr $ipv4_or_6, $cb->(@hostnames) |
81 | =item AnyEvent::DNS::ptr $ipv4_or_6, $cb->(@hostnames) |
79 | |
82 | |
80 | Tries to reverse-resolve the given IPv4 or IPv6 address (in textual form) |
83 | Tries to reverse-resolve the given IPv4 or IPv6 address (in textual form) |
81 | into it's hostname(s). |
84 | into it's hostname(s). |
82 | |
85 | |
83 | Requires the Socket6 module for IPv6 support. |
|
|
84 | |
|
|
85 | Example: |
86 | Example: |
86 | |
87 | |
87 | AnyEvent::DNS::ptr "2001:500:2f::f", sub { print shift }; |
88 | AnyEvent::DNS::ptr "2001:500:2f::f", sub { print shift }; |
88 | # => f.root-servers.net |
89 | # => f.root-servers.net |
89 | |
90 | |
… | |
… | |
98 | |
99 | |
99 | sub a($$) { |
100 | sub a($$) { |
100 | my ($domain, $cb) = @_; |
101 | my ($domain, $cb) = @_; |
101 | |
102 | |
102 | resolver->resolve ($domain => "a", sub { |
103 | resolver->resolve ($domain => "a", sub { |
|
|
104 | $cb->(map $_->[3], @_); |
|
|
105 | }); |
|
|
106 | } |
|
|
107 | |
|
|
108 | sub aaaa($$) { |
|
|
109 | my ($domain, $cb) = @_; |
|
|
110 | |
|
|
111 | resolver->resolve ($domain => "aaaa", sub { |
103 | $cb->(map $_->[3], @_); |
112 | $cb->(map $_->[3], @_); |
104 | }); |
113 | }); |
105 | } |
114 | } |
106 | |
115 | |
107 | sub mx($$) { |
116 | sub mx($$) { |
… | |
… | |
138 | } |
147 | } |
139 | |
148 | |
140 | sub ptr($$) { |
149 | sub ptr($$) { |
141 | my ($ip, $cb) = @_; |
150 | my ($ip, $cb) = @_; |
142 | |
151 | |
143 | my $name; |
152 | $ip = AnyEvent::Socket::parse_ip ($ip) |
|
|
153 | or return $cb->(); |
144 | |
154 | |
145 | if (AnyEvent::Util::dotted_quad $ip) { |
155 | if (4 == length $ip) { |
146 | $name = join ".", (reverse split /\./, $ip), "in-addr.arpa."; |
156 | $ip = join ".", (reverse split /\./, $ip), "in-addr.arpa."; |
147 | } else { |
157 | } else { |
148 | require Socket6; |
158 | $ip = join ".", (reverse split //, unpack "H*", $ip), "ip6.arpa."; |
149 | $name = join ".", |
|
|
150 | (reverse split //, |
|
|
151 | unpack "H*", Socket6::inet_pton (Socket::AF_INET6, $ip)), |
|
|
152 | "ip6.arpa."; |
|
|
153 | } |
159 | } |
154 | |
160 | |
155 | resolver->resolve ($name => "ptr", sub { |
161 | resolver->resolve ($ip => "ptr", sub { |
156 | $cb->(map $_->[3], @_); |
162 | $cb->(map $_->[3], @_); |
157 | }); |
163 | }); |
158 | } |
164 | } |
159 | |
165 | |
160 | sub any($$) { |
166 | sub any($$) { |
… | |
… | |
369 | my ($qt, $qc) = unpack "nn", substr $pkt, $ofs; $ofs += 4; |
375 | my ($qt, $qc) = unpack "nn", substr $pkt, $ofs; $ofs += 4; |
370 | [$qname, $type_str{$qt} || $qt, $class_str{$qc} || $qc] |
376 | [$qname, $type_str{$qt} || $qt, $class_str{$qc} || $qc] |
371 | } |
377 | } |
372 | |
378 | |
373 | our %dec_rr = ( |
379 | our %dec_rr = ( |
374 | 1 => sub { Socket::inet_ntoa $_ }, # a |
380 | 1 => sub { join ".", unpack "C4" }, # a |
375 | 2 => sub { local $ofs = $ofs - length; _dec_qname }, # ns |
381 | 2 => sub { local $ofs = $ofs - length; _dec_qname }, # ns |
376 | 5 => sub { local $ofs = $ofs - length; _dec_qname }, # cname |
382 | 5 => sub { local $ofs = $ofs - length; _dec_qname }, # cname |
377 | 6 => sub { |
383 | 6 => sub { |
378 | local $ofs = $ofs - length; |
384 | local $ofs = $ofs - length; |
379 | my $mname = _dec_qname; |
385 | my $mname = _dec_qname; |
380 | my $rname = _dec_qname; |
386 | my $rname = _dec_qname; |
381 | ($mname, $rname, unpack "NNNNN", substr $pkt, $ofs) |
387 | ($mname, $rname, unpack "NNNNN", substr $pkt, $ofs) |
382 | }, # soa |
388 | }, # soa |
383 | 11 => sub { ((Socket::inet_aton substr $_, 0, 4), unpack "C a*", substr $_, 4) }, # wks |
389 | 11 => sub { ((join ".", unpack "C4"), unpack "C a*", substr $_, 4) }, # wks |
384 | 12 => sub { local $ofs = $ofs - length; _dec_qname }, # ptr |
390 | 12 => sub { local $ofs = $ofs - length; _dec_qname }, # ptr |
385 | 13 => sub { unpack "C/a C/a", $_ }, # hinfo |
391 | 13 => sub { unpack "C/a C/a", $_ }, # hinfo |
386 | 15 => sub { local $ofs = $ofs + 2 - length; ((unpack "n", $_), _dec_qname) }, # mx |
392 | 15 => sub { local $ofs = $ofs + 2 - length; ((unpack "n", $_), _dec_qname) }, # mx |
387 | 16 => sub { unpack "(C/a)*", $_ }, # txt |
393 | 16 => sub { unpack "(C/a)*", $_ }, # txt |
388 | 28 => sub { sprintf "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", unpack "n8" }, # aaaa |
394 | 28 => sub { AnyEvent::Socket::format_ip ($_) }, # aaaa |
389 | 33 => sub { local $ofs = $ofs + 6 - length; ((unpack "nnn", $_), _dec_qname) }, # srv |
395 | 33 => sub { local $ofs = $ofs + 6 - length; ((unpack "nnn", $_), _dec_qname) }, # srv |
390 | 99 => sub { unpack "(C/a)*", $_ }, # spf |
396 | 99 => sub { unpack "(C/a)*", $_ }, # spf |
391 | ); |
397 | ); |
392 | |
398 | |
393 | sub _dec_rr { |
399 | sub _dec_rr { |
… | |
… | |
776 | }), sub { |
782 | }), sub { |
777 | my ($res) = @_; |
783 | my ($res) = @_; |
778 | |
784 | |
779 | if ($res->{tc}) { |
785 | if ($res->{tc}) { |
780 | # success, but truncated, so use tcp |
786 | # success, but truncated, so use tcp |
781 | AnyEvent::Socket::tcp_connect +(Socket::inet_ntoa $server), 53, sub { |
787 | AnyEvent::Socket::tcp_connect ((Socket::inet_ntoa $server), 53, sub { |
782 | my ($fh) = @_ |
788 | my ($fh) = @_ |
783 | or return $self->_exec ($req, $retry + 1); |
789 | or return $self->_exec ($req, $retry + 1); |
784 | |
790 | |
785 | my $handle = new AnyEvent::Handle |
791 | my $handle = new AnyEvent::Handle |
786 | fh => $fh, |
792 | fh => $fh, |
… | |
… | |
795 | $self->_feed ($_[1]); |
801 | $self->_feed ($_[1]); |
796 | }); |
802 | }); |
797 | }); |
803 | }); |
798 | shutdown $fh, 1; |
804 | shutdown $fh, 1; |
799 | |
805 | |
800 | }, sub { $timeout }; |
806 | }, sub { $timeout }); |
801 | |
807 | |
802 | } else { |
808 | } else { |
803 | # success |
809 | # success |
804 | $self->{id}{$req->[2]} = 1; |
810 | $self->{id}{$req->[2]} = 1; |
805 | push @{ $self->{reuse_q} }, [$NOW + $self->{reuse}, $req->[2]]; |
811 | push @{ $self->{reuse_q} }, [$NOW + $self->{reuse}, $req->[2]]; |
… | |
… | |
1021 | }; |
1027 | }; |
1022 | |
1028 | |
1023 | $do_search->(); |
1029 | $do_search->(); |
1024 | } |
1030 | } |
1025 | |
1031 | |
|
|
1032 | use AnyEvent::Socket (); # circular dependency, so do not import anything and do it at the end |
|
|
1033 | |
1026 | 1; |
1034 | 1; |
1027 | |
1035 | |
1028 | =back |
1036 | =back |
1029 | |
1037 | |
1030 | =head1 AUTHOR |
1038 | =head1 AUTHOR |