From: Steve Peters Date: Fri, 27 Mar 2009 00:59:23 +0000 (-0500) Subject: Add inet_pton() and inet_ntop() to Socket. X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=036d8bd42e6e430b0e760ef10edcff408b0b2527;p=p5sagit%2Fp5-mst-13.2.git Add inet_pton() and inet_ntop() to Socket. --- diff --git a/ext/Socket/Socket.pm b/ext/Socket/Socket.pm index ad5e618..8ef4fb3 100644 --- a/ext/Socket/Socket.pm +++ b/ext/Socket/Socket.pm @@ -1,11 +1,11 @@ package Socket; our($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); -$VERSION = "1.81"; +$VERSION = "1.90"; =head1 NAME -Socket, sockaddr_in, sockaddr_un, inet_aton, inet_ntoa - load the C socket.h defines and structure manipulators +Socket, sockaddr_in, sockaddr_un, inet_aton, inet_ntoa, inet_pton, inet_ntop - load the C socket.h defines and structure manipulators =head1 SYNOPSIS @@ -171,6 +171,21 @@ Takes a sockaddr_un structure (as returned by pack_sockaddr_un()) and returns the pathname. Will croak if the structure does not have AF_UNIX in the right place. +=item inet_pton ADDRESS_FAMILY, HOSTNAME + +Takes an address family, either AF_INET or AF_INET6, and a string giving +the name of a host, and translates that to an opaque string +(if programming in C, struct in_addr or struct in6_addr depending on the +address family passed in). The host string may be a string hostname, such +as 'www.perl.org', or an IP address. If using an IP address, the type of +IP address must be consistant with the address family passed into the function. + +=item inet_ntop ADDRESS_FAMILY, IP_ADDRESS + +Takes an address family, either AF_INET or AF_INET6, and a string +(an opaque string as returned by inet_aton() or inet_pton()) and +translates it to an IPv4 or IPv6 address string. + =back =cut diff --git a/ext/Socket/Socket.xs b/ext/Socket/Socket.xs index 076297f..064de2e 100644 --- a/ext/Socket/Socket.xs +++ b/ext/Socket/Socket.xs @@ -442,3 +442,53 @@ unpack_sockaddr_in(sin_sv) PUSHs(sv_2mortal(newSViv((IV) port))); PUSHs(sv_2mortal(newSVpvn((char *)&ip_address, sizeof ip_address))); } + +void +inet_ntop(af, ip_address_sv) + int af + SV * ip_address_sv + CODE: +#ifdef HAS_INETNTOP + STRLEN addrlen, struct_size; + struct in6_addr addr; + char str[INET6_ADDRSTRLEN]; + char *ip_address = SvPV(ip_address_sv, addrlen); + + if(af == AF_INET) { + struct_size = sizeof(struct in_addr); + } else if(af == AF_INET6) { + struct_size = sizeof(struct in6_addr); + } else { + croak("Bad address family for Socket::inet_ntop, got %d, should be either AF_INET or AF_INET6", + af); + } + + Copy( ip_address, &addr, sizeof addr, char ); + inet_ntop(af, &addr, str, INET6_ADDRSTRLEN); + + ST(0) = sv_2mortal(newSVpv(str, strlen(str))); +#else + ST(0) = (SV *)not_here("inet_ntop"); +#endif + +void +inet_pton(af, host) + int af + const char * host + CODE: +#ifdef HAS_INETPTON + struct in6_addr ip_address; + if(af != AF_INET && af != AF_INET6) { + croak("Bad address family for %s, got %d, should be either AF_INET or AF_INET6", + "Socket::inet_pton", + af); + } + int ok = (*host != '\0') && inet_pton(af, host, &ip_address); + + ST(0) = sv_newmortal(); + if (ok) { + sv_setpvn( ST(0), (char *)&ip_address, sizeof ip_address ); + } +#else + ST(0) = (SV *)not_here("inet_pton"); +#endif diff --git a/ext/Socket/t/Socket.t b/ext/Socket/t/Socket.t index f707999..cec72e7 100755 --- a/ext/Socket/t/Socket.t +++ b/ext/Socket/t/Socket.t @@ -14,7 +14,7 @@ BEGIN { use Socket qw(:all); -print "1..17\n"; +print "1..20\n"; $has_echo = $^O ne 'MSWin32'; $alarmed = 0; @@ -167,3 +167,13 @@ if ($^O eq 'linux') { # doesn't have abstract socket support print "ok 17 - skipped on this platform\n"; } + +if($Config{d_inetntop} && $Config{d_inetaton}){ + print ((inet_ntop(AF_INET, inet_pton(AF_INET, "10.20.30.40")) eq "10.20.30.40") ? "ok 18\n" : "not ok 18\n"); + print ((inet_ntop(AF_INET, inet_aton("10.20.30.40")) eq "10.20.30.40") ? "ok 19\n" : "not ok 19\n"); + print (lc(inet_ntop(AF_INET6, inet_pton(AF_INET6, "2001:503:BA3E::2:30")) eq "2001:503:ba3e::2:30") ? "ok 20\n" : "not ok 20\n"); +} else { + # no IPv6 + print "ok 18 - skipped on this platform\n"; + print "ok 19 - skipped on this platform\n"; +}