summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/Socket/Socket.pm13
-rwxr-xr-xext/Socket/Socket.t11
-rw-r--r--ext/Socket/Socket.xs14
3 files changed, 36 insertions, 2 deletions
diff --git a/ext/Socket/Socket.pm b/ext/Socket/Socket.pm
index dce0e88bc4..c8f2fdea9f 100644
--- a/ext/Socket/Socket.pm
+++ b/ext/Socket/Socket.pm
@@ -112,6 +112,15 @@ Note - does not return a number.
Returns the 4-byte 'invalid' ip address. Normally equivalent
to inet_aton('255.255.255.255').
+=item sockaddr_family SOCKADDR
+
+Takes a sockaddr structure (as returned by pack_sockaddr_in(),
+pack_sockaddr_un() or the perl builtin functions getsockname() and
+getpeername()) and returns the address family tag. It will match the
+constant AF_INET for a sockaddr_in and AF_UNIX for a sockaddr_un. It
+can be used to figure out what unpacker to use for a sockaddr of
+unknown type.
+
=item sockaddr_in PORT, ADDRESS
=item sockaddr_in SOCKADDR_IN
@@ -173,7 +182,9 @@ require Exporter;
use XSLoader ();
@ISA = qw(Exporter);
@EXPORT = qw(
- inet_aton inet_ntoa pack_sockaddr_in unpack_sockaddr_in
+ inet_aton inet_ntoa
+ sockaddr_family
+ pack_sockaddr_in unpack_sockaddr_in
pack_sockaddr_un unpack_sockaddr_un
sockaddr_in sockaddr_un
INADDR_ANY INADDR_BROADCAST INADDR_LOOPBACK INADDR_NONE
diff --git a/ext/Socket/Socket.t b/ext/Socket/Socket.t
index 94d4fb5599..ebf5a5f072 100755
--- a/ext/Socket/Socket.t
+++ b/ext/Socket/Socket.t
@@ -13,7 +13,7 @@ BEGIN {
use Socket;
-print "1..14\n";
+print "1..16\n";
if (socket(T,PF_INET,SOCK_STREAM,6)) {
print "ok 1\n";
@@ -103,3 +103,12 @@ print ((inet_ntoa(v10.20.30.40) eq "10.20.30.40") ? "ok 11\n" : "not ok 11\n");
eval { inet_ntoa(v10.20.30.400) };
print (($@ =~ /^Wide character in Socket::inet_ntoa at/) ? "ok 14\n" : "not ok 14\n");
+
+if (sockaddr_family(pack_sockaddr_in(100,inet_aton("10.250.230.10"))) == AF_INET) {
+ print "ok 15\n";
+} else {
+ print "not ok 15\n";
+}
+
+eval { sockaddr_family("") };
+print (($@ =~ /^Bad arg length for Socket::sockaddr_family, length is 0, should be at least \d+/) ? "ok 16\n" : "not ok 16\n");
diff --git a/ext/Socket/Socket.xs b/ext/Socket/Socket.xs
index fb60dc229f..1c3c239b3e 100644
--- a/ext/Socket/Socket.xs
+++ b/ext/Socket/Socket.xs
@@ -273,6 +273,20 @@ inet_ntoa(ip_address_sv)
}
void
+sockaddr_family(sockaddr)
+ SV * sockaddr
+ PREINIT:
+ STRLEN sockaddr_len;
+ char *sockaddr_pv = SvPV(sockaddr, sockaddr_len);
+ CODE:
+ if (sockaddr_len < offsetof(struct sockaddr, sa_data)) {
+ croak("Bad arg length for %s, length is %d, should be at least %d",
+ "Socket::sockaddr_family", sockaddr_len,
+ offsetof(struct sockaddr, sa_data));
+ }
+ ST(0) = sv_2mortal(newSViv(((struct sockaddr*)sockaddr_pv)->sa_family));
+
+void
pack_sockaddr_un(pathname)
char * pathname
CODE: