diff --git a/NEWS b/NEWS index fc6564db94fb9..675ac03745659 100644 --- a/NEWS +++ b/NEWS @@ -145,8 +145,6 @@ PHP NEWS . socket_getsockname/socket_create/socket_bind handled AF_PACKET family socket. (David Carlier) . Added IP_BINDANY for a socket to bind to any address. (David Carlier) - . Added support for ethernet frames data for socket_sendto/socket_recvfrom - for SOCK_RAW sockets. (David Carlier) - Sodium: . Fix overall theorical overflows on zend_string buffer allocations. diff --git a/ext/sockets/config.m4 b/ext/sockets/config.m4 index a4a6e55a7926b..37f927a78186a 100644 --- a/ext/sockets/config.m4 +++ b/ext/sockets/config.m4 @@ -5,7 +5,7 @@ PHP_ARG_ENABLE([sockets], if test "$PHP_SOCKETS" != "no"; then AC_CHECK_FUNCS([hstrerror if_nametoindex if_indextoname sockatmark]) - AC_CHECK_HEADERS([sys/sockio.h linux/filter.h linux/if_packet.h linux/if_ether.h netinet/ether.h]) + AC_CHECK_HEADERS([sys/sockio.h linux/filter.h linux/if_packet.h linux/if_ether.h]) AC_DEFINE([HAVE_SOCKETS], [1], [Define to 1 if the PHP extension 'sockets' is available.]) diff --git a/ext/sockets/php_sockets.h b/ext/sockets/php_sockets.h index 550a8d488b06e..89c613ba43074 100644 --- a/ext/sockets/php_sockets.h +++ b/ext/sockets/php_sockets.h @@ -77,10 +77,6 @@ typedef struct { extern PHP_SOCKETS_API zend_class_entry *socket_ce; -#ifdef AF_PACKET -extern PHP_SOCKETS_API zend_class_entry *socket_ethinfo_ce; -#endif - static inline php_socket *socket_from_obj(zend_object *obj) { return (php_socket *)((char *)(obj) - XtOffsetOf(php_socket, std)); } diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index 9e7cadf5a8d86..8a347bdfe45f8 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -41,7 +41,6 @@ # include # include # include -# include # include # include # include @@ -55,11 +54,6 @@ # ifdef HAVE_IF_NAMETOINDEX # include # endif -# ifdef HAVE_NETINET_ETHER_H -# include -# include -# include -# endif # if defined(HAVE_LINUX_SOCK_DIAG_H) # include # else @@ -126,9 +120,6 @@ static PHP_RSHUTDOWN_FUNCTION(sockets); zend_class_entry *socket_ce; static zend_object_handlers socket_object_handlers; -#ifdef AF_PACKET -zend_class_entry *socket_ethinfo_ce; -#endif static zend_object *socket_create_object(zend_class_entry *class_type) { php_socket *intern = zend_object_alloc(sizeof(php_socket), class_type); @@ -491,9 +482,6 @@ static PHP_MINIT_FUNCTION(sockets) socket_object_handlers.get_gc = socket_get_gc; socket_object_handlers.compare = zend_objects_not_comparable; -#if defined(AF_PACKET) - socket_ethinfo_ce = register_class_SocketEthernetInfo(); -#endif address_info_ce = register_class_AddressInfo(); address_info_ce->create_object = address_info_create_object; address_info_ce->default_object_handlers = &address_info_object_handlers; @@ -1400,7 +1388,7 @@ PHP_FUNCTION(socket_bind) struct sockaddr_ll *sa = (struct sockaddr_ll *) sock_type; socklen_t sa_len = sizeof(sa); - if (getsockname(php_sock->bsd_socket, (struct sockaddr *)sa, &sa_len) < 0) { + if (getsockname(php_sock->bsd_socket, sock_type, &sa_len) < 0) { zend_value_error("invalid AF_PACKET socket"); RETURN_THROWS(); } @@ -1515,9 +1503,7 @@ PHP_FUNCTION(socket_recvfrom) struct sockaddr_in6 sin6; #endif #ifdef AF_PACKET - struct sockaddr_ll sll; - int protoid; - socklen_t protoidlen = sizeof(protoid); + //struct sockaddr_ll sll; #endif char addrbuf[INET6_ADDRSTRLEN]; socklen_t slen; @@ -1546,15 +1532,6 @@ PHP_FUNCTION(socket_recvfrom) RETURN_FALSE; } -#ifdef AF_PACKET - // ethernet header + payload - // possibly follow-up PR SOCK_DGRAM - if (php_sock->type == AF_PACKET && arg3 < 60) { - zend_argument_value_error(3, "must be at least 60 for AF_PACKET"); - RETURN_THROWS(); - } -#endif - recv_buf = zend_string_alloc(arg3 + 1, 0); switch (php_sock->type) { @@ -1633,19 +1610,14 @@ PHP_FUNCTION(socket_recvfrom) break; #endif #ifdef AF_PACKET + /* case AF_PACKET: - getsockopt(php_sock->bsd_socket, SOL_SOCKET, SO_TYPE, (char *) &protoid, &protoidlen); - - // TODO: SOCK_DGRAM support - if (protoid != SOCK_RAW) { - zend_argument_value_error(1, "must be SOCK_RAW socket type"); - RETURN_THROWS(); - } + // TODO expose and use proper ethernet frame type instead i.e. src mac, dst mac and payload to userland + // ditto for socket_sendto slen = sizeof(sll); memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; char ifrname[IFNAMSIZ]; - zval zpayload; retval = recvfrom(php_sock->bsd_socket, ZSTR_VAL(recv_buf), arg3, arg4, (struct sockaddr *)&sll, (socklen_t *)&slen); @@ -1654,6 +1626,8 @@ PHP_FUNCTION(socket_recvfrom) zend_string_efree(recv_buf); RETURN_FALSE; } + ZSTR_LEN(recv_buf) = retval; + ZSTR_VAL(recv_buf)[ZSTR_LEN(recv_buf)] = '\0'; if (UNEXPECTED(!if_indextoname(sll.sll_ifindex, ifrname))) { PHP_SOCKET_ERROR(php_sock, "unable to get the interface name", errno); @@ -1661,86 +1635,11 @@ PHP_FUNCTION(socket_recvfrom) RETURN_FALSE; } - struct ethhdr *e = (struct ethhdr *)ZSTR_VAL(recv_buf); - unsigned short protocol = ntohs(e->h_proto); - unsigned char *payload; - - zval obj; - object_init_ex(&obj, socket_ethinfo_ce); - array_init(&zpayload); - - switch (protocol) { - case ETH_P_IP: { - payload = ((unsigned char *)e + sizeof(struct ethhdr)); - struct iphdr *ip = (struct iphdr *)payload; - unsigned char *ipdata = payload + (ip->ihl * 4); - struct in_addr s, d; - s.s_addr = ip->saddr; - d.s_addr = ip->daddr; - add_assoc_string(&zpayload, "ipsrc", inet_ntoa(s)); - add_assoc_string(&zpayload, "ipdst", inet_ntoa(d)); - - switch (ip->protocol) { - case IPPROTO_TCP: { - struct tcphdr *tcp = (struct tcphdr *)ipdata; - add_assoc_long(&zpayload, "portsrc", ntohs(tcp->th_sport)); - add_assoc_long(&zpayload, "portdst", ntohs(tcp->th_dport)); - break; - } - case IPPROTO_UDP: { - struct udphdr *udp = (struct udphdr *)ipdata; - add_assoc_long(&zpayload, "portsrc", ntohs(udp->uh_sport)); - add_assoc_long(&zpayload, "portdst", ntohs(udp->uh_dport)); - break; - } - default: - zend_string_efree(recv_buf); - zval_ptr_dtor(&zpayload); - zval_ptr_dtor(&obj); - zend_value_error("unsupported ip header protocol"); - RETURN_THROWS(); - } - break; - } - case ETH_P_IPV6: { - payload = ((unsigned char *)e + sizeof(struct ethhdr)); - struct ipv6hdr *ip = (struct ipv6hdr *)payload; - char s[INET6_ADDRSTRLEN], d[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &ip->saddr, s, sizeof(s)); - inet_ntop(AF_INET6, &ip->daddr, d, sizeof(d)); - add_assoc_string(&zpayload, "ipsrc", s); - add_assoc_string(&zpayload, "ipdst", d); - break; - } - case ETH_P_LOOP: { - struct ethhdr *innere = (struct ethhdr *)((unsigned char *)e + ETH_HLEN); - add_assoc_string(&zpayload, "macsrc", ether_ntoa((struct ether_addr *)innere->h_source)); - add_assoc_string(&zpayload, "macdst", ether_ntoa((struct ether_addr *)innere->h_dest)); - break; - } - default: - zend_string_efree(recv_buf); - zval_ptr_dtor(&zpayload); - zval_ptr_dtor(&obj); - zend_value_error("unsupported ethernet protocol"); - RETURN_THROWS(); - } - - Z_DELREF(zpayload); - zend_string_efree(recv_buf); - zend_update_property(Z_OBJCE(obj), Z_OBJ(obj), ZEND_STRL("socket"), arg1); - zend_update_property_string(Z_OBJCE(obj), Z_OBJ(obj), ZEND_STRL("macsrc"), ether_ntoa((struct ether_addr *)e->h_source)); - zend_update_property_string(Z_OBJCE(obj), Z_OBJ(obj), ZEND_STRL("macdst"), ether_ntoa((struct ether_addr *)e->h_dest)); - zend_update_property_long(Z_OBJCE(obj), Z_OBJ(obj), ZEND_STRL("ethprotocol"), protocol); - zend_update_property(Z_OBJCE(obj), Z_OBJ(obj), ZEND_STRL("payload"), &zpayload); - - ZEND_TRY_ASSIGN_REF_VALUE(arg2, &obj); + ZEND_TRY_ASSIGN_REF_NEW_STR(arg2, recv_buf); ZEND_TRY_ASSIGN_REF_STRING(arg5, ifrname); - - if (arg6) { - ZEND_TRY_ASSIGN_REF_LONG(arg6, sll.sll_ifindex); - } + ZEND_TRY_ASSIGN_REF_LONG(arg6, sll.sll_ifindex); break; + */ #endif default: zend_argument_value_error(1, "must be one of AF_UNIX, AF_INET, or AF_INET6"); @@ -1762,10 +1661,7 @@ PHP_FUNCTION(socket_sendto) struct sockaddr_in6 sin6; #endif #ifdef AF_PACKET - struct sockaddr_ll sll; - unsigned char halen; - int protoid; - socklen_t protoidlen = sizeof(protoid); + //struct sockaddr_ll sll; #endif int retval; size_t buf_len; @@ -1798,15 +1694,6 @@ PHP_FUNCTION(socket_sendto) RETURN_THROWS(); } -#ifdef AF_PACKET - // ether header + payload - // TODO dealing with SOCK_DGRAM - if (php_sock->type == AF_PACKET && len < 60) { - zend_argument_value_error(3, "must be at least 64 for AF_PACKET"); - RETURN_THROWS(); - } -#endif - switch (php_sock->type) { case AF_UNIX: memset(&s_un, 0, sizeof(s_un)); @@ -1851,33 +1738,23 @@ PHP_FUNCTION(socket_sendto) break; #endif #ifdef AF_PACKET + /* case AF_PACKET: - getsockopt(php_sock->bsd_socket, SOL_SOCKET, SO_TYPE, (char *) &protoid, &protoidlen); - - // TODO: SOCK_DGRAM support - if (protoid != SOCK_RAW) { - zend_argument_value_error(1, "must be SOCK_RAW socket type"); - RETURN_THROWS(); - } if (port_is_null) { zend_argument_value_error(6, "cannot be null when the socket type is AF_PACKET"); RETURN_THROWS(); } - halen = ZSTR_LEN(addr) > ETH_ALEN ? ETH_ALEN : (unsigned char)ZSTR_LEN(addr); - memset(&sll, 0, sizeof(sll)); - memcpy(sll.sll_addr, addr, halen); sll.sll_family = AF_PACKET; sll.sll_ifindex = port; - sll.sll_halen = halen; - // TODO allows to use more user friendly type to replace raw buffer usage - retval = sendto(php_sock->bsd_socket, buf, ((size_t)len > buf_len) ? buf_len : (size_t)len, flags, (struct sockaddr *) &sll, sizeof(sll)); + retval = sendto(php_sock->bsd_socket, buf, ((size_t)len > buf_len) ? buf_len : (size_t)len, flags, (struct sockaddr *) &sin, sizeof(sin)); break; + */ #endif default: - zend_argument_value_error(1, "must be one of AF_UNIX, AF_INET, AF_PACKET or AF_INET6"); + zend_argument_value_error(1, "must be one of AF_UNIX, AF_INET, or AF_INET6"); RETURN_THROWS(); } @@ -3003,6 +2880,8 @@ PHP_FUNCTION(socket_addrinfo_connect) ai = Z_ADDRESS_INFO_P(arg1); + PHP_ETH_PROTO_CHECK(ai->addrinfo.ai_protocol, ai->addrinfo.ai_family); + object_init_ex(return_value, socket_ce); php_sock = Z_SOCKET_P(return_value); diff --git a/ext/sockets/sockets.stub.php b/ext/sockets/sockets.stub.php index 8fd440dae6581..4d6200fcd1ffe 100644 --- a/ext/sockets/sockets.stub.php +++ b/ext/sockets/sockets.stub.php @@ -2013,11 +2013,6 @@ * @cvalue ETH_P_ALL */ const ETH_P_ALL = UNKNOWN; -/** - * @var int - * @cvalue ETH_FRAME_LEN - */ -const ETH_FRAME_LEN = UNKNOWN; #endif /** @@ -2161,19 +2156,3 @@ function socket_wsaprotocol_info_import(string $info_id): Socket|false {} function socket_wsaprotocol_info_release(string $info_id): bool {} #endif - -#ifdef AF_PACKET -final class SocketEthernetInfo -{ - /** @readonly **/ - public Socket $socket; - /** @readonly **/ - public int $ethprotocol; - /** @readonly **/ - public string $macsrc; - /** @readonly **/ - public string $macdst; - /** @readonly **/ - public array $payload; -} -#endif diff --git a/ext/sockets/sockets_arginfo.h b/ext/sockets/sockets_arginfo.h index 1b2139838d351..4a90b4d789feb 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: 9725b1a979cb5aa48079585278fa89c5edb321d4 */ + * Stub hash: aac197335037777d31d83d4a4040bbfcd0c55813 */ 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) @@ -1105,9 +1105,6 @@ static void register_sockets_symbols(int module_number) #if defined(ETH_P_ALL) REGISTER_LONG_CONSTANT("ETH_P_ALL", ETH_P_ALL, CONST_PERSISTENT); #endif -#if defined(ETH_P_ALL) - REGISTER_LONG_CONSTANT("ETH_FRAME_LEN", ETH_FRAME_LEN, CONST_PERSISTENT); -#endif } static zend_class_entry *register_class_Socket(void) @@ -1129,46 +1126,3 @@ static zend_class_entry *register_class_AddressInfo(void) return class_entry; } - -#if defined(AF_PACKET) -static zend_class_entry *register_class_SocketEthernetInfo(void) -{ - zend_class_entry ce, *class_entry; - - INIT_CLASS_ENTRY(ce, "SocketEthernetInfo", NULL); - class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL); - - zval property_socket_default_value; - ZVAL_UNDEF(&property_socket_default_value); - zend_string *property_socket_name = zend_string_init("socket", sizeof("socket") - 1, 1); - zend_string *property_socket_class_Socket = zend_string_init("Socket", sizeof("Socket")-1, 1); - zend_declare_typed_property(class_entry, property_socket_name, &property_socket_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_socket_class_Socket, 0, 0)); - zend_string_release(property_socket_name); - - zval property_ethprotocol_default_value; - ZVAL_UNDEF(&property_ethprotocol_default_value); - zend_string *property_ethprotocol_name = zend_string_init("ethprotocol", sizeof("ethprotocol") - 1, 1); - zend_declare_typed_property(class_entry, property_ethprotocol_name, &property_ethprotocol_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); - zend_string_release(property_ethprotocol_name); - - zval property_macsrc_default_value; - ZVAL_UNDEF(&property_macsrc_default_value); - zend_string *property_macsrc_name = zend_string_init("macsrc", sizeof("macsrc") - 1, 1); - zend_declare_typed_property(class_entry, property_macsrc_name, &property_macsrc_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_macsrc_name); - - zval property_macdst_default_value; - ZVAL_UNDEF(&property_macdst_default_value); - zend_string *property_macdst_name = zend_string_init("macdst", sizeof("macdst") - 1, 1); - zend_declare_typed_property(class_entry, property_macdst_name, &property_macdst_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); - zend_string_release(property_macdst_name); - - zval property_payload_default_value; - ZVAL_UNDEF(&property_payload_default_value); - zend_string *property_payload_name = zend_string_init("payload", sizeof("payload") - 1, 1); - zend_declare_typed_property(class_entry, property_payload_name, &property_payload_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_ARRAY)); - zend_string_release(property_payload_name); - - return class_entry; -} -#endif diff --git a/ext/sockets/tests/socket_afpacket.phpt b/ext/sockets/tests/socket_afpacket.phpt index 93623bcfe9e7a..2e83a654766e0 100644 --- a/ext/sockets/tests/socket_afpacket.phpt +++ b/ext/sockets/tests/socket_afpacket.phpt @@ -15,7 +15,7 @@ if (!function_exists("posix_getuid") || posix_getuid() != 0) { ?> --FILE-- --EXPECTF-- @@ -48,21 +35,3 @@ string(2) "lo" int(%i) Warning: socket_getpeername(): unable to retrieve peer name [95]: %sot supported in %s on line %d -int(60) -int(60) -string(2) "lo" -object(SocketEthernetInfo)#3 (%d) { - ["socket"]=> - object(Socket)#1 (0) { - } - ["ethprotocol"]=> - int(%i) - ["macsrc"]=> - string(11) "0:0:0:0:0:0" - ["macdst"]=> - string(%d) "%s:%s:%s:%s:%s:%s" - ["payload"]=> - array(%d) { - %a - } -}