… | |
… | |
50 | |
50 | |
51 | our @EXPORT = qw( |
51 | our @EXPORT = qw( |
52 | parse_hostport |
52 | parse_hostport |
53 | parse_ipv4 parse_ipv6 |
53 | parse_ipv4 parse_ipv6 |
54 | parse_ip parse_address |
54 | parse_ip parse_address |
|
|
55 | format_ipv4 format_ipv6 |
55 | format_ip format_address |
56 | format_ip format_address |
56 | address_family |
57 | address_family |
57 | inet_aton |
58 | inet_aton |
58 | tcp_server |
59 | tcp_server |
59 | tcp_connect |
60 | tcp_connect |
60 | ); |
61 | ); |
61 | |
62 | |
62 | our $VERSION = 4.32; |
63 | our $VERSION = 4.81; |
63 | |
64 | |
64 | =item $ipn = parse_ipv4 $dotted_quad |
65 | =item $ipn = parse_ipv4 $dotted_quad |
65 | |
66 | |
66 | Tries to parse the given dotted quad IPv4 address and return it in |
67 | Tries to parse the given dotted quad IPv4 address and return it in |
67 | octet form (or undef when it isn't in a parsable format). Supports all |
68 | octet form (or undef when it isn't in a parsable format). Supports all |
… | |
… | |
144 | ? pack "S", AF_UNIX |
145 | ? pack "S", AF_UNIX |
145 | : undef |
146 | : undef |
146 | |
147 | |
147 | } |
148 | } |
148 | |
149 | |
149 | =item $ipn = parse_address $text |
150 | =item $ipn = parse_address $ip |
150 | |
151 | |
151 | Combines C<parse_ipv4> and C<parse_ipv6> in one function. The address |
152 | Combines C<parse_ipv4> and C<parse_ipv6> in one function. The address |
152 | here refers to the host address (not socket address) in network form |
153 | here refers to the host address (not socket address) in network form |
153 | (binary). |
154 | (binary). |
154 | |
155 | |
155 | If the C<$text> is C<unix/>, then this function returns a special token |
156 | If the C<$text> is C<unix/>, then this function returns a special token |
156 | recognised by the other functions in this module to mean "UNIX domain |
157 | recognised by the other functions in this module to mean "UNIX domain |
157 | socket". |
158 | socket". |
158 | |
159 | |
|
|
160 | If the C<$text> to parse is a mapped IPv4 in IPv6 address (:ffff::<ipv4>), |
|
|
161 | then it will be treated as an IPv4 address. If you don't want that, you |
|
|
162 | have to call C<parse_ipv4> and/or C<parse_ipv6> manually. |
|
|
163 | |
159 | =item $text = AnyEvent::Socket::aton $ipn |
164 | =item $ipn = AnyEvent::Socket::aton $ip |
160 | |
165 | |
161 | Same as C<parse_address>, but not exported (think C<Socket::inet_aton> but |
166 | Same as C<parse_address>, but not exported (think C<Socket::inet_aton> but |
162 | I<without> name resolution). |
167 | I<without> name resolution). |
163 | |
168 | |
164 | =cut |
169 | =cut |
165 | |
170 | |
166 | sub parse_address($) { |
171 | sub parse_address($) { |
167 | &parse_ipv4 || &parse_ipv6 || &parse_unix |
172 | for (&parse_ipv6) { |
|
|
173 | if ($_) { |
|
|
174 | s/^\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff//; |
|
|
175 | return $_; |
|
|
176 | } else { |
|
|
177 | return &parse_ipv4 || &parse_unix |
|
|
178 | } |
|
|
179 | } |
168 | } |
180 | } |
169 | |
181 | |
170 | *aton = \&parse_address; |
182 | *aton = \&parse_address; |
171 | |
183 | |
172 | =item ($host, $service) = parse_hostport $string[, $default_service] |
184 | =item ($host, $service) = parse_hostport $string[, $default_service] |
… | |
… | |
259 | : 16 == length $_[0] |
271 | : 16 == length $_[0] |
260 | ? AF_INET6 |
272 | ? AF_INET6 |
261 | : unpack "S", $_[0] |
273 | : unpack "S", $_[0] |
262 | } |
274 | } |
263 | |
275 | |
|
|
276 | =item $text = format_ipv4 $ipn |
|
|
277 | |
|
|
278 | Expects a four octet string representing a binary IPv4 address and returns |
|
|
279 | its textual format. Rarely used, see C<format_address> for a nicer |
|
|
280 | interface. |
|
|
281 | |
|
|
282 | =item $text = format_ipv6 $ipn |
|
|
283 | |
|
|
284 | Expects a sixteen octet string representing a binary IPv6 address and |
|
|
285 | returns its textual format. Rarely used, see C<format_address> for a |
|
|
286 | nicer interface. |
|
|
287 | |
264 | =item $text = format_address $ipn |
288 | =item $text = format_address $ipn |
265 | |
289 | |
266 | Covnvert a host address in network format (e.g. 4 octets for IPv4 or 16 |
290 | Covnvert a host address in network format (e.g. 4 octets for IPv4 or 16 |
267 | octets for IPv6) and convert it into textual form. |
291 | octets for IPv6) and convert it into textual form. |
268 | |
292 | |
… | |
… | |
271 | This function works similarly to C<inet_ntop AF_INET || AF_INET6, ...>, |
295 | This function works similarly to C<inet_ntop AF_INET || AF_INET6, ...>, |
272 | except it automatically detects the address type. |
296 | except it automatically detects the address type. |
273 | |
297 | |
274 | Returns C<undef> if it cannot detect the type. |
298 | Returns C<undef> if it cannot detect the type. |
275 | |
299 | |
|
|
300 | If the C<$ipn> is a mapped IPv4 in IPv6 address (:ffff::<ipv4>), then just |
|
|
301 | the contained IPv4 address will be returned. If you do not want that, you |
|
|
302 | have to call C<format_ipv6> manually. |
|
|
303 | |
276 | =item $text = AnyEvent::Socket::ntoa $ipn |
304 | =item $text = AnyEvent::Socket::ntoa $ipn |
277 | |
305 | |
278 | Same as format_address, but not exported (think C<inet_ntoa>). |
306 | Same as format_address, but not exported (think C<inet_ntoa>). |
279 | |
307 | |
280 | =cut |
308 | =cut |
281 | |
309 | |
282 | sub format_address; |
310 | sub format_ipv4($) { |
|
|
311 | join ".", unpack "C4", $_[0] |
|
|
312 | } |
|
|
313 | |
|
|
314 | sub format_ipv6($) { |
|
|
315 | if (v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 eq $_[0]) { |
|
|
316 | return "::"; |
|
|
317 | } elsif (v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1 eq $_[0]) { |
|
|
318 | return "::1"; |
|
|
319 | } elsif (v0.0.0.0.0.0.0.0.0.0.0.0 eq substr $_[0], 0, 12) { |
|
|
320 | # v4compatible |
|
|
321 | return "::" . format_ipv4 substr $_[0], 12; |
|
|
322 | } elsif (v0.0.0.0.0.0.0.0.0.0.255.255 eq substr $_[0], 0, 12) { |
|
|
323 | # v4mapped |
|
|
324 | return "::ffff:" . format_ipv4 substr $_[0], 12; |
|
|
325 | } elsif (v0.0.0.0.0.0.0.0.255.255.0.0 eq substr $_[0], 0, 12) { |
|
|
326 | # v4translated |
|
|
327 | return "::ffff:0:" . format_ipv4 substr $_[0], 12; |
|
|
328 | } else { |
|
|
329 | my $ip = sprintf "%x:%x:%x:%x:%x:%x:%x:%x", unpack "n8", $_[0]; |
|
|
330 | |
|
|
331 | # this is rather sucky, I admit |
|
|
332 | $ip =~ s/^0:(?:0:)*(0$)?/::/ |
|
|
333 | or $ip =~ s/(:0){7}$/::/ or $ip =~ s/(:0){7}/:/ |
|
|
334 | or $ip =~ s/(:0){6}$/::/ or $ip =~ s/(:0){6}/:/ |
|
|
335 | or $ip =~ s/(:0){5}$/::/ or $ip =~ s/(:0){5}/:/ |
|
|
336 | or $ip =~ s/(:0){4}$/::/ or $ip =~ s/(:0){4}/:/ |
|
|
337 | or $ip =~ s/(:0){3}$/::/ or $ip =~ s/(:0){3}/:/ |
|
|
338 | or $ip =~ s/(:0){2}$/::/ or $ip =~ s/(:0){2}/:/ |
|
|
339 | or $ip =~ s/(:0){1}$/::/ or $ip =~ s/(:0){1}/:/; |
|
|
340 | return $ip |
|
|
341 | } |
|
|
342 | } |
|
|
343 | |
283 | sub format_address($) { |
344 | sub format_address($) { |
284 | my $af = address_family $_[0]; |
345 | my $af = address_family $_[0]; |
285 | if ($af == AF_INET) { |
346 | if ($af == AF_INET) { |
286 | return join ".", unpack "C4", $_[0] |
347 | return &format_ipv4; |
287 | } elsif ($af == AF_INET6) { |
348 | } elsif ($af == AF_INET6) { |
288 | if (v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 eq $_[0]) { |
|
|
289 | return "::"; |
|
|
290 | } elsif (v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1 eq $_[0]) { |
|
|
291 | return "::1"; |
|
|
292 | } elsif (v0.0.0.0.0.0.0.0.0.0.0.0 eq substr $_[0], 0, 12) { |
|
|
293 | # v4compatible |
|
|
294 | return "::" . format_address substr $_[0], 12; |
|
|
295 | } elsif (v0.0.0.0.0.0.0.0.0.0.255.255 eq substr $_[0], 0, 12) { |
349 | return (v0.0.0.0.0.0.0.0.0.0.255.255 eq substr $_[0], 0, 12) |
296 | # v4mapped |
350 | ? format_ipv4 substr $_[0], 12 |
297 | return "::ffff:" . format_address substr $_[0], 12; |
351 | : &format_ipv6; |
298 | } elsif (v0.0.0.0.0.0.0.0.255.255.0.0 eq substr $_[0], 0, 12) { |
|
|
299 | # v4translated |
|
|
300 | return "::ffff:0:" . format_address substr $_[0], 12; |
|
|
301 | } else { |
|
|
302 | my $ip = sprintf "%x:%x:%x:%x:%x:%x:%x:%x", unpack "n8", $_[0]; |
|
|
303 | |
|
|
304 | # this is rather sucky, I admit |
|
|
305 | $ip =~ s/^0:(?:0:)*(0$)?/::/ |
|
|
306 | or $ip =~ s/(:0){7}$/::/ or $ip =~ s/(:0){7}/:/ |
|
|
307 | or $ip =~ s/(:0){6}$/::/ or $ip =~ s/(:0){6}/:/ |
|
|
308 | or $ip =~ s/(:0){5}$/::/ or $ip =~ s/(:0){5}/:/ |
|
|
309 | or $ip =~ s/(:0){4}$/::/ or $ip =~ s/(:0){4}/:/ |
|
|
310 | or $ip =~ s/(:0){3}$/::/ or $ip =~ s/(:0){3}/:/ |
|
|
311 | or $ip =~ s/(:0){2}$/::/ or $ip =~ s/(:0){2}/:/ |
|
|
312 | or $ip =~ s/(:0){1}$/::/ or $ip =~ s/(:0){1}/:/; |
|
|
313 | return $ip |
|
|
314 | } |
|
|
315 | } elsif ($af == AF_UNIX) { |
352 | } elsif ($af == AF_UNIX) { |
316 | return "unix/" |
353 | return "unix/" |
317 | } else { |
354 | } else { |
318 | return undef |
355 | return undef |
319 | } |
356 | } |