From: Lubomir Rintel Date: Tue, 25 Aug 2009 15:09:53 +0000 (+0200) Subject: Add support for Abstract namespace sockets X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=99f13d4c3419e967e95c5ac6a3af61e9bb0fd3c0;p=p5sagit%2Fp5-mst-13.2.git Add support for Abstract namespace sockets Abstract namespace sockets are Linux-specific socket type that live in AF_UNIX family, slightly abusing it to be able to use arbitrary character arrays as addresses: They start with nul byte and are not terminated by nul byte, but with the length passed to the socket() system call. Added regression test for the correct address length computation. Signed-off-by: Lubomir Rintel --- diff --git a/ext/Socket/Socket.xs b/ext/Socket/Socket.xs index 75d0f33..d46a6b9 100644 --- a/ext/Socket/Socket.xs +++ b/ext/Socket/Socket.xs @@ -303,6 +303,7 @@ pack_sockaddr_un(pathname) struct sockaddr_un sun_ad; /* fear using sun */ STRLEN len; char * pathname_pv; + int addr_len; Zero( &sun_ad, sizeof sun_ad, char ); sun_ad.sun_family = AF_UNIX; @@ -336,7 +337,17 @@ pack_sockaddr_un(pathname) Copy( pathname_pv, sun_ad.sun_path, len, char ); # endif if (0) not_here("dummy"); - ST(0) = sv_2mortal(newSVpvn((char *)&sun_ad, sizeof sun_ad)); + if (len > 1 && sun_ad.sun_path[0] == '\0') { + /* Linux-style abstract-namespace socket. + * The name is not a file name, but an array of arbitrary + * character, starting with \0 and possibly including \0s, + * therefore the length of the structure must denote the + * end of that character array */ + addr_len = (void *)&sun_ad.sun_path - (void *)&sun_ad + len; + } else { + addr_len = sizeof sun_ad; + } + ST(0) = sv_2mortal(newSVpvn((char *)&sun_ad, addr_len)); #else ST(0) = (SV *) not_here("pack_sockaddr_un"); #endif diff --git a/ext/Socket/t/Socket.t b/ext/Socket/t/Socket.t index aeeb2a0..09d25f9 100644 --- a/ext/Socket/t/Socket.t +++ b/ext/Socket/t/Socket.t @@ -14,7 +14,7 @@ BEGIN { use Socket qw(:all); -print "1..20\n"; +print "1..21\n"; $has_echo = $^O ne 'MSWin32'; $alarmed = 0; @@ -163,16 +163,26 @@ if ($^O eq 'linux') { print "# got <$path>\n"; print "not ok 17\n"; } + + # see if we calculate the address structure length correctly + if (length ($test_abstract_socket) + 2 == length $addr) { + print "ok 18\n"; + } else { + print "# got ".(length $addr)."\n"; + print "not ok 18\n"; + } + } else { # doesn't have abstract socket support print "ok 17 - skipped on this platform\n"; + print "ok 18 - 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"); + print ((inet_ntop(AF_INET, inet_pton(AF_INET, "10.20.30.40")) eq "10.20.30.40") ? "ok 19\n" : "not ok 19\n"); + print ((inet_ntop(AF_INET, inet_aton("10.20.30.40")) eq "10.20.30.40") ? "ok 20\n" : "not ok 20\n"); + print (lc(inet_ntop(AF_INET6, inet_pton(AF_INET6, "2001:503:BA3E::2:30")) eq "2001:503:ba3e::2:30") ? "ok 21\n" : "not ok 21\n"); } else { # no IPv6 - print "ok $_ - skipped on this platform\n" for 18 .. 20; + print "ok $_ - skipped on this platform\n" for 19 .. 21; }