mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +02:00
socket: support unix paths in the abstract namespace
Those starting with '\0'.
This commit is contained in:
parent
e2744f1aa3
commit
710150ccb7
4 changed files with 119 additions and 11 deletions
|
@ -98,8 +98,8 @@ typedef struct {
|
|||
} field_descriptor;
|
||||
|
||||
#define KEY_FILL_SOCKADDR "fill_sockaddr"
|
||||
#define KEY_RECVMSG_RET "recvmsg_ret"
|
||||
#define KEY_CMSG_LEN "cmsg_len"
|
||||
#define KEY_RECVMSG_RET "recvmsg_ret"
|
||||
#define KEY_CMSG_LEN "cmsg_len"
|
||||
|
||||
const struct key_value empty_key_value_list[] = {{0}};
|
||||
|
||||
|
@ -667,6 +667,13 @@ static void from_zval_write_sun_path(const zval *path, char *sockaddr_un_c, ser_
|
|||
path = &lzval;
|
||||
}
|
||||
|
||||
/* code in this file relies on the path being nul terminated, even though
|
||||
* this is not required, at least on linux for abstract paths. It also
|
||||
* assumes that the path is not empty */
|
||||
if (Z_STRLEN_P(path) == 0) {
|
||||
do_from_zval_err(ctx, "%s", "the path is cannot be empty");
|
||||
return;
|
||||
}
|
||||
if (Z_STRLEN_P(path) >= sizeof(saddr->sun_path)) {
|
||||
do_from_zval_err(ctx, "the path is too long, the maximum permitted "
|
||||
"length is %ld", sizeof(saddr->sun_path) - 1);
|
||||
|
@ -768,10 +775,22 @@ static void from_zval_write_sockaddr_aux(const zval *container,
|
|||
return;
|
||||
}
|
||||
*sockaddr_ptr = accounted_ecalloc(1, sizeof(struct sockaddr_un), ctx);
|
||||
*sockaddr_len = sizeof(struct sockaddr_un);
|
||||
if (fill_sockaddr) {
|
||||
struct sockaddr_un *sock_un = (struct sockaddr_un*)*sockaddr_ptr;
|
||||
|
||||
from_zval_write_sockaddr_un(container, (char*)*sockaddr_ptr, ctx);
|
||||
(*sockaddr_ptr)->sa_family = AF_UNIX;
|
||||
|
||||
/* calculating length is more complicated here. Giving the size of
|
||||
* struct sockaddr_un here and relying on the nul termination of
|
||||
* sun_path does not work for paths in the abstract namespace. Note
|
||||
* that we always assume the path is not empty and nul terminated */
|
||||
*sockaddr_len = offsetof(struct sockaddr_un, sun_path) +
|
||||
(sock_un->sun_path[0] == '\0'
|
||||
? (1 + strlen(&sock_un->sun_path[1]))
|
||||
: strlen(sock_un->sun_path));
|
||||
} else {
|
||||
*sockaddr_len = sizeof(struct sockaddr_un);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -1479,7 +1479,7 @@ PHP_FUNCTION(socket_strerror)
|
|||
PHP_FUNCTION(socket_bind)
|
||||
{
|
||||
zval *arg1;
|
||||
php_sockaddr_storage sa_storage;
|
||||
php_sockaddr_storage sa_storage = {0};
|
||||
struct sockaddr *sock_type = (struct sockaddr*) &sa_storage;
|
||||
php_socket *php_sock;
|
||||
char *addr;
|
||||
|
@ -1497,10 +1497,19 @@ PHP_FUNCTION(socket_bind)
|
|||
case AF_UNIX:
|
||||
{
|
||||
struct sockaddr_un *sa = (struct sockaddr_un *) sock_type;
|
||||
memset(sa, 0, sizeof(sa_storage));
|
||||
|
||||
sa->sun_family = AF_UNIX;
|
||||
snprintf(sa->sun_path, 108, "%s", addr);
|
||||
retval = bind(php_sock->bsd_socket, (struct sockaddr *) sa, SUN_LEN(sa));
|
||||
|
||||
if (addr_len >= sizeof(sa->sun_path)) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||
"Invalid path: too long (maximum size is %d)",
|
||||
(int)sizeof(sa->sun_path) - 1);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
memcpy(&sa->sun_path, addr, addr_len);
|
||||
|
||||
retval = bind(php_sock->bsd_socket, (struct sockaddr *) sa,
|
||||
offsetof(struct sockaddr_un, sun_path) + addr_len);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1508,8 +1517,6 @@ PHP_FUNCTION(socket_bind)
|
|||
{
|
||||
struct sockaddr_in *sa = (struct sockaddr_in *) sock_type;
|
||||
|
||||
memset(sa, 0, sizeof(sa_storage)); /* Apparently, Mac OSX needs this */
|
||||
|
||||
sa->sin_family = AF_INET;
|
||||
sa->sin_port = htons((unsigned short) port);
|
||||
|
||||
|
@ -1525,8 +1532,6 @@ PHP_FUNCTION(socket_bind)
|
|||
{
|
||||
struct sockaddr_in6 *sa = (struct sockaddr_in6 *) sock_type;
|
||||
|
||||
memset(sa, 0, sizeof(sa_storage)); /* Apparently, Mac OSX needs this */
|
||||
|
||||
sa->sin6_family = AF_INET6;
|
||||
sa->sin6_port = htons((unsigned short) port);
|
||||
|
||||
|
|
44
ext/sockets/tests/socket_abstract_path.phpt
Normal file
44
ext/sockets/tests/socket_abstract_path.phpt
Normal file
|
@ -0,0 +1,44 @@
|
|||
--TEST--
|
||||
Support for paths in the abstract namespace (bind, connect)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('sockets'))
|
||||
die('skip sockets extension not available.');
|
||||
|
||||
if (PHP_OS != 'Linux') {
|
||||
die('skip For Linux only');
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
include __DIR__."/mcast_helpers.php.inc";
|
||||
|
||||
$path = "\x00/foo_bar";
|
||||
|
||||
echo "creating server socket\n";
|
||||
$servers = socket_create(AF_UNIX, SOCK_STREAM, 0) or die("err");
|
||||
socket_bind($servers, $path) or die("Could not bind");
|
||||
socket_listen($servers) or die("Could not listen");
|
||||
socket_set_nonblock($servers) or die("Could not put in non-blocking mode");
|
||||
|
||||
echo "creating client socket\n";
|
||||
$clients = socket_create(AF_UNIX, SOCK_STREAM, 0) or die("err");
|
||||
socket_connect($clients, $path) or die("Error connecting");
|
||||
|
||||
$conns = socket_accept($servers) or die("Could not accept connection");
|
||||
|
||||
$r = socket_sendmsg($clients, [
|
||||
//"name" => [ "addr" => $path, ],
|
||||
"iov" => ["test ", "thing", "\n"],
|
||||
], 0);
|
||||
var_dump($r);
|
||||
checktimeout($conns, 500);
|
||||
|
||||
if (!socket_recv($conns, $buf, 20, 0)) die("recv");
|
||||
print_r($buf);
|
||||
?>
|
||||
--EXPECTF--
|
||||
creating server socket
|
||||
creating client socket
|
||||
int(11)
|
||||
test thing
|
40
ext/sockets/tests/socket_abstract_path_sendmsg.phpt
Normal file
40
ext/sockets/tests/socket_abstract_path_sendmsg.phpt
Normal file
|
@ -0,0 +1,40 @@
|
|||
--TEST--
|
||||
Support for paths in the abstract namespace (bind, sendmsg, recvmsg)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('sockets'))
|
||||
die('skip sockets extension not available.');
|
||||
|
||||
if (PHP_OS != 'Linux') {
|
||||
die('skip For Linux only');
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
include __DIR__."/mcast_helpers.php.inc";
|
||||
|
||||
$path = "\x00/bar_foo";
|
||||
|
||||
echo "creating send socket\n";
|
||||
$sends1 = socket_create(AF_UNIX, SOCK_DGRAM, 0) or die("err");
|
||||
socket_set_nonblock($sends1) or die("Could not put in non-blocking mode");
|
||||
|
||||
echo "creating receive socket\n";
|
||||
$s = socket_create(AF_UNIX, SOCK_DGRAM, 0) or die("err");
|
||||
socket_bind($s, $path) or die("err");
|
||||
|
||||
$r = socket_sendmsg($sends1, [
|
||||
"name" => [ "path" => $path],
|
||||
"iov" => ["test ", "thing", "\n"],
|
||||
], 0);
|
||||
var_dump($r);
|
||||
checktimeout($s, 500);
|
||||
|
||||
if (!socket_recv($s, $buf, 20, 0)) die("recv");
|
||||
print_r($buf);
|
||||
?>
|
||||
--EXPECTF--
|
||||
creating send socket
|
||||
creating receive socket
|
||||
int(11)
|
||||
test thing
|
Loading…
Add table
Add a link
Reference in a new issue