diff --git a/ext/sockets/conversions.c b/ext/sockets/conversions.c index b1a4c3486d7a..8d290ea1ca15 100644 --- a/ext/sockets/conversions.c +++ b/ext/sockets/conversions.c @@ -17,6 +17,9 @@ # include # include # include +# ifdef HAVE_IPV6 +# include +# endif # include # include # include @@ -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; @@ -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) @@ -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); @@ -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 */ diff --git a/ext/sockets/conversions.h b/ext/sockets/conversions.h index 1f1fd29c5c05..4deca0eb91cd 100644 --- a/ext/sockets/conversions.h +++ b/ext/sockets/conversions.h @@ -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); diff --git a/ext/sockets/sendrecvmsg.c b/ext/sockets/sendrecvmsg.c index cd7fd4839fb0..313c11abf794 100644 --- a/ext/sockets/sendrecvmsg.c +++ b/ext/sockets/sendrecvmsg.c @@ -23,6 +23,9 @@ #include "sendrecvmsg.h" #include "conversions.h" #include +#if !defined(PHP_WIN32) && defined(HAVE_IPV6) +# include +#endif #include #ifdef ZTS #include @@ -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, @@ -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); @@ -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) @@ -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 } @@ -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; diff --git a/ext/sockets/sockets.stub.php b/ext/sockets/sockets.stub.php index d94352e36288..3012a78803df 100644 --- a/ext/sockets/sockets.stub.php +++ b/ext/sockets/sockets.stub.php @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 /** diff --git a/ext/sockets/sockets_arginfo.h b/ext/sockets/sockets_arginfo.h index 78f2212a5182..b23dd236fdd8 100644 --- a/ext/sockets/sockets_arginfo.h +++ b/ext/sockets/sockets_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 0ff66adfea41b603b9d58f1f0a82a950f4034cc4 */ + * Stub hash: e395a47dbff5d85d8d65b4036ad180550f9f5895 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_select, 0, 4, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(1, read, IS_ARRAY, 1) @@ -963,6 +963,12 @@ static void register_sockets_symbols(int module_number) REGISTER_LONG_CONSTANT("IPPROTO_IP", IPPROTO_IP, CONST_PERSISTENT); #if defined(HAVE_IPV6) REGISTER_LONG_CONSTANT("IPPROTO_IPV6", IPPROTO_IPV6, CONST_PERSISTENT); +#endif +#if defined(IPPROTO_UDP) + REGISTER_LONG_CONSTANT("IPPROTO_UDP", IPPROTO_UDP, CONST_PERSISTENT); +#endif +#if defined(IPPROTO_RAW) + REGISTER_LONG_CONSTANT("IPPROTO_RAW", IPPROTO_RAW, CONST_PERSISTENT); #endif REGISTER_LONG_CONSTANT("SOL_TCP", IPPROTO_TCP, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SOL_UDP", IPPROTO_UDP, CONST_PERSISTENT); @@ -1000,24 +1006,36 @@ static void register_sockets_symbols(int module_number) #if defined(SOL_LOCAL) REGISTER_LONG_CONSTANT("SOL_LOCAL", SOL_LOCAL, CONST_PERSISTENT); #endif -#if (defined(IPV6_RECVPKTINFO) && defined(HAVE_IPV6)) +#if defined(HAVE_IPV6) && defined(IPV6_RECVPKTINFO) REGISTER_LONG_CONSTANT("IPV6_RECVPKTINFO", IPV6_RECVPKTINFO, CONST_PERSISTENT); #endif -#if (defined(IPV6_RECVPKTINFO) && defined(HAVE_IPV6)) +#if defined(HAVE_IPV6) && defined(IPV6_RECVPKTINFO) REGISTER_LONG_CONSTANT("IPV6_PKTINFO", IPV6_PKTINFO, CONST_PERSISTENT); #endif -#if (defined(IPV6_RECVHOPLIMIT) && defined(HAVE_IPV6)) +#if defined(HAVE_IPV6) && defined(IPV6_RECVHOPLIMIT) REGISTER_LONG_CONSTANT("IPV6_RECVHOPLIMIT", IPV6_RECVHOPLIMIT, CONST_PERSISTENT); #endif -#if (defined(IPV6_RECVHOPLIMIT) && defined(HAVE_IPV6)) +#if defined(HAVE_IPV6) && defined(IPV6_RECVHOPLIMIT) REGISTER_LONG_CONSTANT("IPV6_HOPLIMIT", IPV6_HOPLIMIT, CONST_PERSISTENT); #endif -#if (defined(IPV6_RECVTCLASS) && defined(HAVE_IPV6)) +#if defined(HAVE_IPV6) && defined(IPV6_RECVTCLASS) REGISTER_LONG_CONSTANT("IPV6_RECVTCLASS", IPV6_RECVTCLASS, CONST_PERSISTENT); #endif -#if (defined(IPV6_RECVTCLASS) && defined(HAVE_IPV6)) +#if defined(HAVE_IPV6) && defined(IPV6_RECVTCLASS) REGISTER_LONG_CONSTANT("IPV6_TCLASS", IPV6_TCLASS, CONST_PERSISTENT); #endif +#if defined(HAVE_IPV6) && defined(IPV6_RECVHOPOPTS) + REGISTER_LONG_CONSTANT("IPV6_RECVHOPOPTS", IPV6_RECVHOPOPTS, CONST_PERSISTENT); +#endif +#if defined(HAVE_IPV6) && defined(IPV6_RECVHOPOPTS) + REGISTER_LONG_CONSTANT("IPV6_HOPOPTS", IPV6_HOPOPTS, CONST_PERSISTENT); +#endif +#if defined(HAVE_IPV6) && defined(IPV6_RECVDSTOPTS) + REGISTER_LONG_CONSTANT("IPV6_RECVDSTOPTS", IPV6_RECVDSTOPTS, CONST_PERSISTENT); +#endif +#if defined(HAVE_IPV6) && defined(IPV6_RECVDSTOPTS) + REGISTER_LONG_CONSTANT("IPV6_DSTOPTS", IPV6_DSTOPTS, CONST_PERSISTENT); +#endif #if defined(SCM_RIGHTS) REGISTER_LONG_CONSTANT("SCM_RIGHTS", SCM_RIGHTS, CONST_PERSISTENT); #endif