Skip to content

ext/sockets: rfc 3542 support of destination and hop options #18630

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions ext/sockets/conversions.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
# include <sys/socket.h>
# include <arpa/inet.h>
# include <netinet/in.h>
# ifdef HAVE_IPV6
# include <netinet/ip6.h>
# endif
# include <sys/un.h>
# include <sys/ioctl.h>
# include <net/if.h>
Expand Down Expand Up @@ -404,6 +407,25 @@ static void from_zval_write_uint32(const zval *arr_value, char *field, ser_conte
ival = (uint32_t)lval;
memcpy(field, &ival, sizeof(ival));
}
static void from_zval_write_uint8(const zval *arr_value, char *field, ser_context *ctx)
{
zend_long lval;
uint8_t ival;

lval = from_zval_integer_common(arr_value, ctx);
if (ctx->err.has_error) {
return;
}

if (lval < 0 || lval > 0xFF) {
do_from_zval_err(ctx, "%s", "given PHP integer is out of bounds "
"for an unsigned 8-bit integer");
return;
}

ival = (uint8_t)lval;
memcpy(field, &ival, sizeof(ival));
}
static void from_zval_write_net_uint16(const zval *arr_value, char *field, ser_context *ctx)
{
zend_long lval;
Expand Down Expand Up @@ -529,6 +551,13 @@ static void to_zval_read_uint32(const char *data, zval *zv, res_context *ctx)

ZVAL_LONG(zv, (zend_long)ival);
}
static void to_zval_read_uint8(const char *data, zval *zv, res_context *ctx)
{
uint8_t ival;
memcpy(&ival, data, sizeof(ival));

ZVAL_LONG(zv, (zend_long)ival);
}
#endif
#if defined(SO_PASSCRED) || defined(LOCAL_CREDS_PERSISTENT) || defined(LOCAL_CREDS)
static void to_zval_read_pid_t(const char *data, zval *zv, res_context *ctx)
Expand Down Expand Up @@ -1307,6 +1336,22 @@ static const field_descriptor descriptors_in6_pktinfo[] = {
{"ifindex", sizeof("ifindex"), true, offsetof(struct in6_pktinfo, ipi6_ifindex), from_zval_write_ifindex, to_zval_read_unsigned},
{0}
};

#if defined(IPV6_HOPOPTS) && !defined(PHP_WIN32)
static const field_descriptor descriptors_ip6_hbh[] = {
{"nxt", sizeof("nxt"), true, offsetof(struct ip6_hbh, ip6h_nxt), from_zval_write_uint8, to_zval_read_uint8},
{"len", sizeof("len"), true, offsetof(struct ip6_hbh, ip6h_len), from_zval_write_uint8, to_zval_read_uint8},
{0}
};
#endif
#if defined(IPV6_DSTOPTS) && !defined(PHP_WIN32)
static const field_descriptor descriptors_ip6_dest[] = {
{"nxt", sizeof("nxt"), true, offsetof(struct ip6_dest, ip6d_nxt), from_zval_write_uint8, to_zval_read_uint8},
{"len", sizeof("len"), true, offsetof(struct ip6_dest, ip6d_len), from_zval_write_uint8, to_zval_read_uint8},
{0}
};
#endif

void from_zval_write_in6_pktinfo(const zval *container, char *in6_pktinfo_c, ser_context *ctx)
{
from_zval_write_aggregation(container, in6_pktinfo_c, descriptors_in6_pktinfo, ctx);
Expand All @@ -1317,6 +1362,34 @@ void to_zval_read_in6_pktinfo(const char *data, zval *zv, res_context *ctx)

to_zval_read_aggregation(data, zv, descriptors_in6_pktinfo, ctx);
}

#if defined(IPV6_HOPOPTS) && !defined(PHP_WIN32)
void from_zval_write_ip6_hbh(const zval *container, char *in6_hbh_c, ser_context *ctx)
{
from_zval_write_aggregation(container, in6_hbh_c, descriptors_ip6_hbh, ctx);
}

void to_zval_read_ip6_hbh(const char *data, zval *zv, res_context *ctx)
{
array_init_size(zv, 2);

to_zval_read_aggregation(data, zv, descriptors_ip6_hbh, ctx);
}
#endif

#if defined(IPV6_DSTOPTS) && !defined(PHP_WIN32)
void from_zval_write_ip6_dest(const zval *container, char *in6_dest_c, ser_context *ctx)
{
from_zval_write_aggregation(container, in6_dest_c, descriptors_ip6_dest, ctx);
}

void to_zval_read_ip6_dest(const char *data, zval *zv, res_context *ctx)
{
array_init_size(zv, 2);

to_zval_read_aggregation(data, zv, descriptors_ip6_dest, ctx);
}
#endif
#endif

/* CONVERSIONS for struct ucred */
Expand Down
10 changes: 10 additions & 0 deletions ext/sockets/conversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ void from_zval_write_in6_pktinfo(const zval *container, char *in6_pktinfo_c, ser
void to_zval_read_in6_pktinfo(const char *data, zval *zv, res_context *ctx);
#endif

#ifdef IPV6_HOPOPTS
void from_zval_write_ip6_hbh(const zval *container, char *in6_hbh_c, ser_context *ctx);
void to_zval_read_ip6_hbh(const char *data, zval *zv, res_context *ctx);
#endif

#ifdef IPV6_DSTOPTS
void from_zval_write_ip6_dest(const zval *container, char *in6_dest_c, ser_context *ctx);
void to_zval_read_ip6_dest(const char *data, zval *zv, res_context *ctx);
#endif

#if defined(SO_PASSCRED) || defined(LOCAL_CREDS_PERSISTENT) || defined(LOCAL_CREDS)
void from_zval_write_ucred(const zval *container, char *ucred_c, ser_context *ctx);
void to_zval_read_ucred(const char *data, zval *zv, res_context *ctx);
Expand Down
66 changes: 57 additions & 9 deletions ext/sockets/sendrecvmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#include "sendrecvmsg.h"
#include "conversions.h"
#include <limits.h>
#if !defined(PHP_WIN32) && defined(HAVE_IPV6)
# include <netinet/ip6.h>
#endif
#include <Zend/zend_llist.h>
#ifdef ZTS
#include <TSRM/TSRM.h>
Expand Down Expand Up @@ -107,21 +110,33 @@ static void init_ancillary_registry(void)
key.cmsg_type = type; \
zend_hash_str_update_mem(&ancillary_registry.ht, (char*)&key, sizeof(key), (void*)&entry, sizeof(entry))

#if defined(IPV6_PKTINFO) && defined(HAVE_IPV6)
#if defined(HAVE_IPV6)
#if defined(IPV6_PKTINFO)
PUT_ENTRY(sizeof(struct in6_pktinfo), 0, 0, from_zval_write_in6_pktinfo,
to_zval_read_in6_pktinfo, IPPROTO_IPV6, IPV6_PKTINFO);
#endif

#if defined(IPV6_HOPLIMIT) && defined(HAVE_IPV6)
#if defined(IPV6_HOPLIMIT)
PUT_ENTRY(sizeof(int), 0, 0, from_zval_write_int,
to_zval_read_int, IPPROTO_IPV6, IPV6_HOPLIMIT);
#endif

#if defined(IPV6_TCLASS) && defined(HAVE_IPV6)
#if defined(IPV6_TCLASS)
PUT_ENTRY(sizeof(int), 0, 0, from_zval_write_int,
to_zval_read_int, IPPROTO_IPV6, IPV6_TCLASS);
#endif

#if defined(IPV6_HOPOPTS) && !defined(PHP_WIN32)
PUT_ENTRY(sizeof(struct ip6_hbh), 0, 0, from_zval_write_ip6_hbh,
to_zval_read_ip6_hbh, IPPROTO_IPV6, IPV6_HOPOPTS);
#endif

#if defined(IPV6_DSTPOPTS) && !defined(PHP_WIN32)
PUT_ENTRY(sizeof(struct ip6_dest), 0, 0, from_zval_write_ip6_dest,
to_zval_read_ip6_dest, IPPROTO_IPV6, IPV6_DSTOPTS);
#endif
#endif

#ifdef SO_PASSCRED
#ifdef HAVE_STRUCT_UCRED
PUT_ENTRY(sizeof(struct ucred), 0, 0, from_zval_write_ucred,
Expand Down Expand Up @@ -156,7 +171,6 @@ static void destroy_ancillary_registry(void)
ancillary_reg_entry *get_ancillary_reg_entry(int cmsg_level, int msg_type)
{
anc_reg_key key = { cmsg_level, msg_type };
ancillary_reg_entry *entry;

#ifdef ZTS
tsrm_mutex_lock(ancillary_mutex);
Expand All @@ -168,11 +182,7 @@ ancillary_reg_entry *get_ancillary_reg_entry(int cmsg_level, int msg_type)
tsrm_mutex_unlock(ancillary_mutex);
#endif

if ((entry = zend_hash_str_find_ptr(&ancillary_registry.ht, (char*)&key, sizeof(key))) != NULL) {
return entry;
} else {
return NULL;
}
return zend_hash_str_find_ptr(&ancillary_registry.ht, (char*)&key, sizeof(key));
}

PHP_FUNCTION(socket_sendmsg)
Expand Down Expand Up @@ -361,6 +371,32 @@ int php_do_setsockopt_ipv6_rfc3542(php_socket *php_sock, int level, int optname,

optlen = sizeof(struct in6_pktinfo);
goto dosockopt;
#endif
#ifndef PHP_WIN32 // set but seems more like for "future implementation" ?
#ifdef IPV6_HOPOPTS
case IPV6_HOPOPTS:
opt_ptr = from_zval_run_conversions(arg4, php_sock, from_zval_write_ip6_hbh,
sizeof(struct ip6_hbh), "ip6_hbh", &allocations, &err);
if (err.has_error) {
err_msg_dispose(&err);
return FAILURE;
}

optlen = sizeof(struct ip6_hbh);
goto dosockopt;
#endif
#ifdef IPV6_DSTOPTS
case IPV6_DSTOPTS:
opt_ptr = from_zval_run_conversions(arg4, php_sock, from_zval_write_ip6_dest,
sizeof(struct ip6_dest), "ip6_dest", &allocations, &err);
if (err.has_error) {
err_msg_dispose(&err);
return FAILURE;
}

optlen = sizeof(struct ip6_dest);
goto dosockopt;
#endif
#endif
}

Expand Down Expand Up @@ -394,6 +430,18 @@ int php_do_getsockopt_ipv6_rfc3542(php_socket *php_sock, int level, int optname,
size = sizeof(struct in6_pktinfo);
reader = &to_zval_read_in6_pktinfo;
break;
#endif
#if defined(IPV6_HOPOPTS) && !defined(PHP_WIN32)
case IPV6_HOPOPTS:
size = sizeof(struct ip6_hbh);
reader = &to_zval_read_ip6_hbh;
break;
#endif
#if defined(IPV6_DSTOPTS) && !defined(PHP_WIN32)
case IPV6_DSTOPTS:
size = sizeof(struct ip6_dest);
reader = &to_zval_read_ip6_dest;
break;
#endif
default:
return 1;
Expand Down
46 changes: 43 additions & 3 deletions ext/sockets/sockets.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -1681,6 +1681,20 @@
*/
const IPPROTO_IPV6 = UNKNOWN;
#endif
#ifdef IPPROTO_UDP
/**
* @var int
* @cvalue IPPROTO_UDP
*/
const IPPROTO_UDP = UNKNOWN;
#endif
#ifdef IPPROTO_RAW
/**
* @var int
* @cvalue IPPROTO_RAW
*/
const IPPROTO_RAW = UNKNOWN;
#endif

/**
* @var int
Expand Down Expand Up @@ -1783,7 +1797,8 @@
const SOL_LOCAL = UNKNOWN;
#endif

#if (defined(IPV6_RECVPKTINFO) && defined(HAVE_IPV6))
#if defined(HAVE_IPV6)
#if defined(IPV6_RECVPKTINFO)
/**
* IPv6 ancillary data
* @var int
Expand All @@ -1796,7 +1811,7 @@
*/
const IPV6_PKTINFO = UNKNOWN;
#endif
#if (defined(IPV6_RECVHOPLIMIT) && defined(HAVE_IPV6))
#if defined(IPV6_RECVHOPLIMIT)
/**
* @var int
* @cvalue IPV6_RECVHOPLIMIT
Expand All @@ -1809,7 +1824,7 @@
const IPV6_HOPLIMIT = UNKNOWN;
#endif

#if (defined(IPV6_RECVTCLASS) && defined(HAVE_IPV6))
#if defined(IPV6_RECVTCLASS)
/**
* @var int
* @cvalue IPV6_RECVTCLASS
Expand All @@ -1821,6 +1836,31 @@
*/
const IPV6_TCLASS = UNKNOWN;
#endif
#if defined(IPV6_RECVHOPOPTS)
/**
* @var int
* @cvalue IPV6_RECVHOPOPTS
*/
const IPV6_RECVHOPOPTS = UNKNOWN;
/**
* @var int
* @cvalue IPV6_HOPOPTS
*/
const IPV6_HOPOPTS = UNKNOWN;
#endif
#if defined(IPV6_RECVDSTOPTS)
/**
* @var int
* @cvalue IPV6_RECVDSTOPTS
*/
const IPV6_RECVDSTOPTS = UNKNOWN;
/**
* @var int
* @cvalue IPV6_DSTOPTS
*/
const IPV6_DSTOPTS = UNKNOWN;
#endif
#endif

#ifdef SCM_RIGHTS
/**
Expand Down
32 changes: 25 additions & 7 deletions ext/sockets/sockets_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.