… | |
… | |
76 | Example: |
76 | Example: |
77 | |
77 | |
78 | AnyEvent::DNS::srv "sip", "udp", "schmorp.de", sub { ... |
78 | AnyEvent::DNS::srv "sip", "udp", "schmorp.de", sub { ... |
79 | # @_ = ( [10, 10, 5060, "sip1.schmorp.de" ] ) |
79 | # @_ = ( [10, 10, 5060, "sip1.schmorp.de" ] ) |
80 | |
80 | |
81 | =item AnyEvent::DNS::ptr $ipv4_or_6, $cb->(@hostnames) |
81 | =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) |
82 | |
93 | |
83 | Tries to reverse-resolve the given IPv4 or IPv6 address (in textual form) |
94 | Tries to reverse-resolve the given IPv4 or IPv6 address (in textual form) |
84 | into it's hostname(s). |
95 | 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. |
85 | |
108 | |
86 | Example: |
109 | Example: |
87 | |
110 | |
88 | AnyEvent::DNS::ptr "2001:500:2f::f", sub { print shift }; |
111 | AnyEvent::DNS::ptr "2001:500:2f::f", sub { print shift }; |
89 | # => f.root-servers.net |
112 | # => f.root-servers.net |
90 | |
|
|
91 | =item AnyEvent::DNS::any $domain, $cb->(@rrs) |
|
|
92 | |
|
|
93 | Tries to resolve the given domain and passes all resource records found to |
|
|
94 | the callback. |
|
|
95 | |
113 | |
96 | =cut |
114 | =cut |
97 | |
115 | |
98 | sub MAX_PKT() { 4096 } # max packet size we advertise and accept |
116 | sub MAX_PKT() { 4096 } # max packet size we advertise and accept |
99 | |
117 | |
… | |
… | |
149 | $cb->(map [@$_[3,4,5,6]], sort { $a->[3] <=> $b->[3] || $b->[4] <=> $a->[4] } @_); |
167 | $cb->(map [@$_[3,4,5,6]], sort { $a->[3] <=> $b->[3] || $b->[4] <=> $a->[4] } @_); |
150 | }); |
168 | }); |
151 | } |
169 | } |
152 | |
170 | |
153 | sub ptr($$) { |
171 | sub ptr($$) { |
|
|
172 | my ($domain, $cb) = @_; |
|
|
173 | |
|
|
174 | resolver->resolve ($domain => "ptr", sub { |
|
|
175 | $cb->(map $_->[3], @_); |
|
|
176 | }); |
|
|
177 | } |
|
|
178 | |
|
|
179 | sub any($$) { |
|
|
180 | my ($domain, $cb) = @_; |
|
|
181 | |
|
|
182 | resolver->resolve ($domain => "*", $cb); |
|
|
183 | } |
|
|
184 | |
|
|
185 | # convert textual ip address into reverse lookup form |
|
|
186 | sub _munge_ptr($) { |
|
|
187 | my $ipn = $_[0] |
|
|
188 | or return; |
|
|
189 | |
|
|
190 | my $ptr; |
|
|
191 | |
|
|
192 | my $af = AnyEvent::Socket::address_family ($ipn); |
|
|
193 | |
|
|
194 | if ($af == AF_INET6) { |
|
|
195 | $ipn = substr $ipn, 0, 16; # anticipate future expansion |
|
|
196 | |
|
|
197 | # handle v4mapped and v4compat |
|
|
198 | if ($ipn =~ s/^\x00{10}(?:\xff\xff|\x00\x00)//) { |
|
|
199 | $af = AF_INET; |
|
|
200 | } else { |
|
|
201 | $ptr = join ".", (reverse split //, unpack "H32", $ipn), "ip6.arpa."; |
|
|
202 | } |
|
|
203 | } |
|
|
204 | |
|
|
205 | if ($af == AF_INET) { |
|
|
206 | $ptr = join ".", (reverse unpack "C4", $ipn), "in-addr.arpa."; |
|
|
207 | } |
|
|
208 | |
|
|
209 | $ptr |
|
|
210 | } |
|
|
211 | |
|
|
212 | sub reverse_lookup($$) { |
154 | my ($ip, $cb) = @_; |
213 | my ($ip, $cb) = @_; |
155 | |
214 | |
156 | $ip = AnyEvent::Socket::parse_address ($ip) |
215 | $ip = _munge_ptr AnyEvent::Socket::parse_address ($ip) |
157 | or return $cb->(); |
216 | or return $cb->(); |
158 | |
|
|
159 | my $af = AnyEvent::Socket::address_family ($ip); |
|
|
160 | |
|
|
161 | if ($af == AF_INET) { |
|
|
162 | $ip = join ".", (reverse split /\./, $ip), "in-addr.arpa."; |
|
|
163 | } elsif ($af == AF_INET6) { |
|
|
164 | $ip = join ".", (reverse split //, unpack "H*", $ip), "ip6.arpa."; |
|
|
165 | } else { |
|
|
166 | return $cb->(); |
|
|
167 | } |
|
|
168 | |
217 | |
169 | resolver->resolve ($ip => "ptr", sub { |
218 | resolver->resolve ($ip => "ptr", sub { |
170 | $cb->(map $_->[3], @_); |
219 | $cb->(map $_->[3], @_); |
171 | }); |
220 | }); |
172 | } |
221 | } |
173 | |
222 | |
174 | sub any($$) { |
223 | sub reverse_verify($$) { |
175 | my ($domain, $cb) = @_; |
224 | my ($ip, $cb) = @_; |
|
|
225 | |
|
|
226 | my $ipn = AnyEvent::Socket::parse_address ($ip) |
|
|
227 | or return $cb->(); |
176 | |
228 | |
177 | resolver->resolve ($domain => "*", $cb); |
229 | my $af = AnyEvent::Socket::address_family ($ipn); |
|
|
230 | |
|
|
231 | my @res; |
|
|
232 | my $cnt; |
|
|
233 | |
|
|
234 | my $ptr = _munge_ptr $ipn |
|
|
235 | or return $cb->(); |
|
|
236 | |
|
|
237 | $ip = AnyEvent::Socket::format_address ($ipn); # normalise into the same form |
|
|
238 | |
|
|
239 | ptr $ptr, sub { |
|
|
240 | for my $name (@_) { |
|
|
241 | ++$cnt; |
|
|
242 | |
|
|
243 | # () around AF_INET to work around bug in 5.8 |
|
|
244 | resolver->resolve ($name => ($af == (AF_INET) ? "a" : "aaaa"), sub { |
|
|
245 | for (@_) { |
|
|
246 | push @res, $name |
|
|
247 | if $_->[3] eq $ip; |
|
|
248 | } |
|
|
249 | $cb->(@res) unless --$cnt; |
|
|
250 | }); |
|
|
251 | } |
|
|
252 | |
|
|
253 | $cb->() unless $cnt; |
|
|
254 | }; |
178 | } |
255 | } |
179 | |
256 | |
180 | ################################################################################# |
257 | ################################################################################# |
181 | |
258 | |
182 | =back |
259 | =back |