diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2009-08-25 17:09:53 +0200 |
---|---|---|
committer | Rafael Garcia-Suarez <rgarciasuarez@gmail.com> | 2009-08-26 11:53:01 +0200 |
commit | 99f13d4c3419e967e95c5ac6a3af61e9bb0fd3c0 (patch) | |
tree | 5fedd2c1612b3a21f5a0945b138998ce73c0d4fc /ext/Socket | |
parent | 289d61c2fe0a9a435b7e5828a3fbe9df5967f4d9 (diff) | |
download | perl-99f13d4c3419e967e95c5ac6a3af61e9bb0fd3c0.tar.gz |
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 <lkundrak@fedoraproject.org>
Diffstat (limited to 'ext/Socket')
-rw-r--r-- | ext/Socket/Socket.xs | 13 | ||||
-rw-r--r-- | ext/Socket/t/Socket.t | 20 |
2 files changed, 27 insertions, 6 deletions
diff --git a/ext/Socket/Socket.xs b/ext/Socket/Socket.xs index 75d0f33870..d46a6b9892 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 aeeb2a0352..09d25f9b95 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; } |