mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
ext/sockets: linux AF_PACKET support.
close GH-17440
This commit is contained in:
10
NEWS
10
NEWS
@@ -96,10 +96,6 @@ PHP NEWS
|
||||
. Fixed bug #49169 (SoapServer calls wrong function, although "SOAP action"
|
||||
header is correct). (nielsdos)
|
||||
|
||||
- Sodium:
|
||||
. Fix overall theorical overflows on zend_string buffer allocations.
|
||||
(David Carlier/nielsdos)
|
||||
|
||||
- Sockets:
|
||||
. Added IPPROTO_ICMP/IPPROTO_ICMPV6 to create raw socket for ICMP usage.
|
||||
(David Carlier)
|
||||
@@ -124,6 +120,12 @@ PHP NEWS
|
||||
. socket_set_option with the options MCAST_LEAVE_GROUP/MCAST_LEAVE_SOURCE_GROUP
|
||||
will throw an exception if its value is not a valid array/object.
|
||||
(David Carlier)
|
||||
. socket_getsockname/socket_create/socket_bind handled AF_PACKET family socket.
|
||||
(David Carlier)
|
||||
|
||||
- Sodium:
|
||||
. Fix overall theorical overflows on zend_string buffer allocations.
|
||||
(David Carlier/nielsdos)
|
||||
|
||||
- Standard:
|
||||
. Fixed crypt() tests on musl when using --with-external-libcrypt
|
||||
|
||||
@@ -164,6 +164,9 @@ PHP 8.5 UPGRADE NOTES
|
||||
. socket_set_option with MCAST_LEAVE_GROUP/MCAST_LEAVE_SOURCE_GROUP
|
||||
options will throw an exception if the value isn't a valid object
|
||||
or array.
|
||||
. socket_create/socket_bind can create AF_PACKET family sockets.
|
||||
. socket_getsockname gets the interface index and its string
|
||||
representation with AF_PACKET socket.
|
||||
|
||||
- Zlib:
|
||||
. The "use_include_path" argument for the
|
||||
@@ -241,6 +244,7 @@ PHP 8.5 UPGRADE NOTES
|
||||
. TCP_REUSPORT_LB_NUMA_NODOM (FreeBSD only).
|
||||
. TCP_REUSPORT_LB_NUMA_CURDOM (FreeBSD only).
|
||||
. TCP_BBR_ALGORITHM (FreeBSD only).
|
||||
. AF_PACKET (Linux only).
|
||||
|
||||
========================================
|
||||
11. Changes to INI File Handling
|
||||
|
||||
@@ -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])
|
||||
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.])
|
||||
|
||||
|
||||
@@ -64,6 +64,12 @@
|
||||
# else
|
||||
# undef SO_BPF_EXTENSIONS
|
||||
# endif
|
||||
# if defined(HAVE_LINUX_IF_PACKET_H)
|
||||
# include <linux/if_packet.h>
|
||||
# endif
|
||||
# if defined(HAVE_LINUX_IF_ETHER_H)
|
||||
# include <linux/if_ether.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
@@ -91,6 +97,18 @@ ZEND_DECLARE_MODULE_GLOBALS(sockets)
|
||||
#define PF_INET AF_INET
|
||||
#endif
|
||||
|
||||
#if defined(AF_PACKET)
|
||||
#define PHP_ETH_PROTO_CHECK(protocol, family) \
|
||||
do { \
|
||||
/* We ll let EINVAL errno warning about miusage, too many protocols conflicts */ \
|
||||
if (protocol <= USHRT_MAX && family == AF_PACKET) { \
|
||||
protocol = htons(protocol); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define PHP_ETH_PROTO_CHECK(protocol, family) (0)
|
||||
#endif
|
||||
|
||||
static PHP_GINIT_FUNCTION(sockets);
|
||||
static PHP_GSHUTDOWN_FUNCTION(sockets);
|
||||
static PHP_MINIT_FUNCTION(sockets);
|
||||
@@ -960,13 +978,16 @@ PHP_FUNCTION(socket_read)
|
||||
/* {{{ Queries the remote side of the given socket which may either result in host/port or in a UNIX filesystem path, dependent on its type. */
|
||||
PHP_FUNCTION(socket_getsockname)
|
||||
{
|
||||
zval *arg1, *addr, *port = NULL;
|
||||
zval *arg1, *addr, *objint = NULL;
|
||||
php_sockaddr_storage sa_storage = {0};
|
||||
php_socket *php_sock;
|
||||
struct sockaddr *sa;
|
||||
struct sockaddr_in *sin;
|
||||
#ifdef HAVE_IPV6
|
||||
struct sockaddr_in6 *sin6;
|
||||
#endif
|
||||
#ifdef AF_PACKET
|
||||
struct sockaddr_ll *sll;
|
||||
#endif
|
||||
char addrbuf[INET6_ADDRSTRLEN];
|
||||
struct sockaddr_un *s_un;
|
||||
@@ -977,7 +998,7 @@ PHP_FUNCTION(socket_getsockname)
|
||||
Z_PARAM_OBJECT_OF_CLASS(arg1, socket_ce)
|
||||
Z_PARAM_ZVAL(addr)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_ZVAL(port)
|
||||
Z_PARAM_ZVAL(objint)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
php_sock = Z_SOCKET_P(arg1);
|
||||
@@ -997,8 +1018,8 @@ PHP_FUNCTION(socket_getsockname)
|
||||
inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf, sizeof(addrbuf));
|
||||
ZEND_TRY_ASSIGN_REF_STRING(addr, addrbuf);
|
||||
|
||||
if (port != NULL) {
|
||||
ZEND_TRY_ASSIGN_REF_LONG(port, htons(sin6->sin6_port));
|
||||
if (objint != NULL) {
|
||||
ZEND_TRY_ASSIGN_REF_LONG(objint, htons(sin6->sin6_port));
|
||||
}
|
||||
RETURN_TRUE;
|
||||
break;
|
||||
@@ -1008,8 +1029,8 @@ PHP_FUNCTION(socket_getsockname)
|
||||
addr_string = inet_ntop(AF_INET, &sin->sin_addr, addrbuf, sizeof(addrbuf));
|
||||
ZEND_TRY_ASSIGN_REF_STRING(addr, addr_string);
|
||||
|
||||
if (port != NULL) {
|
||||
ZEND_TRY_ASSIGN_REF_LONG(port, htons(sin->sin_port));
|
||||
if (objint != NULL) {
|
||||
ZEND_TRY_ASSIGN_REF_LONG(objint, htons(sin->sin_port));
|
||||
}
|
||||
RETURN_TRUE;
|
||||
break;
|
||||
@@ -1020,9 +1041,26 @@ PHP_FUNCTION(socket_getsockname)
|
||||
ZEND_TRY_ASSIGN_REF_STRING(addr, s_un->sun_path);
|
||||
RETURN_TRUE;
|
||||
break;
|
||||
#ifdef AF_PACKET
|
||||
case AF_PACKET:
|
||||
sll = (struct sockaddr_ll *) sa;
|
||||
char ifrname[IFNAMSIZ];
|
||||
|
||||
if (UNEXPECTED(!if_indextoname(sll->sll_ifindex, ifrname))) {
|
||||
zend_throw_error(NULL, "invalid interface index");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
ZEND_TRY_ASSIGN_REF_STRING(addr, ifrname);
|
||||
if (objint != NULL) {
|
||||
ZEND_TRY_ASSIGN_REF_LONG(objint, sll->sll_ifindex);
|
||||
}
|
||||
RETURN_TRUE;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
zend_argument_value_error(1, "must be one of AF_UNIX, AF_INET, or AF_INET6");
|
||||
zend_argument_value_error(1, "must be one of AF_UNIX, AF_PACKET, AF_INET, or AF_INET6");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
}
|
||||
@@ -1117,9 +1155,12 @@ PHP_FUNCTION(socket_create)
|
||||
if (domain != AF_UNIX
|
||||
#ifdef HAVE_IPV6
|
||||
&& domain != AF_INET6
|
||||
#endif
|
||||
#ifdef AF_PACKET
|
||||
&& domain != AF_PACKET
|
||||
#endif
|
||||
&& domain != AF_INET) {
|
||||
zend_argument_value_error(1, "must be one of AF_UNIX, AF_INET6, or AF_INET");
|
||||
zend_argument_value_error(1, "must be one of AF_UNIX, AF_PACKET, AF_INET6, or AF_INET");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
@@ -1138,6 +1179,8 @@ PHP_FUNCTION(socket_create)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
PHP_ETH_PROTO_CHECK(protocol, domain);
|
||||
|
||||
object_init_ex(return_value, socket_ce);
|
||||
php_sock = Z_SOCKET_P(return_value);
|
||||
|
||||
@@ -1275,20 +1318,20 @@ PHP_FUNCTION(socket_bind)
|
||||
php_socket *php_sock;
|
||||
char *addr;
|
||||
size_t addr_len;
|
||||
zend_long port = 0;
|
||||
zend_long objint = 0;
|
||||
zend_long retval = 0;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(2, 3)
|
||||
Z_PARAM_OBJECT_OF_CLASS(arg1, socket_ce)
|
||||
Z_PARAM_STRING(addr, addr_len)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_LONG(port)
|
||||
Z_PARAM_LONG(objint)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
php_sock = Z_SOCKET_P(arg1);
|
||||
ENSURE_SOCKET_VALID(php_sock);
|
||||
|
||||
if (port < 0 || port > USHRT_MAX) {
|
||||
if (objint < 0 || objint > USHRT_MAX) {
|
||||
zend_argument_value_error(3, "must be between 0 and %u", USHRT_MAX);
|
||||
RETURN_THROWS();
|
||||
}
|
||||
@@ -1316,7 +1359,7 @@ PHP_FUNCTION(socket_bind)
|
||||
struct sockaddr_in *sa = (struct sockaddr_in *) sock_type;
|
||||
|
||||
sa->sin_family = AF_INET;
|
||||
sa->sin_port = htons((unsigned short) port);
|
||||
sa->sin_port = htons((unsigned short) objint);
|
||||
|
||||
if (! php_set_inet_addr(sa, addr, php_sock)) {
|
||||
RETURN_FALSE;
|
||||
@@ -1331,7 +1374,7 @@ PHP_FUNCTION(socket_bind)
|
||||
struct sockaddr_in6 *sa = (struct sockaddr_in6 *) sock_type;
|
||||
|
||||
sa->sin6_family = AF_INET6;
|
||||
sa->sin6_port = htons((unsigned short) port);
|
||||
sa->sin6_port = htons((unsigned short) objint);
|
||||
|
||||
if (! php_set_inet6_addr(sa, addr, php_sock)) {
|
||||
RETURN_FALSE;
|
||||
@@ -1340,9 +1383,26 @@ PHP_FUNCTION(socket_bind)
|
||||
retval = bind(php_sock->bsd_socket, (struct sockaddr *)sa, sizeof(struct sockaddr_in6));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef AF_PACKET
|
||||
case AF_PACKET:
|
||||
{
|
||||
struct sockaddr_ll *sa = (struct sockaddr_ll *) sock_type;
|
||||
socklen_t sa_len = sizeof(sa);
|
||||
|
||||
if (getsockname(php_sock->bsd_socket, sock_type, &sa_len) < 0) {
|
||||
zend_value_error("invalid AF_PACKET socket");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
sa->sll_ifindex = if_nametoindex(addr);
|
||||
|
||||
retval = bind(php_sock->bsd_socket, sock_type, sizeof(struct sockaddr_ll));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
zend_argument_value_error(1, "must be one of AF_UNIX, AF_INET, or AF_INET6");
|
||||
zend_argument_value_error(1, "must be one of AF_UNIX, AF_PACKET, AF_INET, or AF_INET6");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
@@ -1443,6 +1503,9 @@ PHP_FUNCTION(socket_recvfrom)
|
||||
struct sockaddr_in sin;
|
||||
#ifdef HAVE_IPV6
|
||||
struct sockaddr_in6 sin6;
|
||||
#endif
|
||||
#ifdef AF_PACKET
|
||||
//struct sockaddr_ll sll;
|
||||
#endif
|
||||
char addrbuf[INET6_ADDRSTRLEN];
|
||||
socklen_t slen;
|
||||
@@ -1547,6 +1610,38 @@ PHP_FUNCTION(socket_recvfrom)
|
||||
ZEND_TRY_ASSIGN_REF_STRING(arg5, addrbuf[0] ? addrbuf : "::");
|
||||
ZEND_TRY_ASSIGN_REF_LONG(arg6, ntohs(sin6.sin6_port));
|
||||
break;
|
||||
#endif
|
||||
#ifdef AF_PACKET
|
||||
/*
|
||||
case AF_PACKET:
|
||||
// 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];
|
||||
|
||||
retval = recvfrom(php_sock->bsd_socket, ZSTR_VAL(recv_buf), arg3, arg4, (struct sockaddr *)&sll, (socklen_t *)&slen);
|
||||
|
||||
if (retval < 0) {
|
||||
PHP_SOCKET_ERROR(php_sock, "unable to recvfrom", errno);
|
||||
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);
|
||||
zend_string_efree(recv_buf);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
ZEND_TRY_ASSIGN_REF_NEW_STR(arg2, recv_buf);
|
||||
ZEND_TRY_ASSIGN_REF_STRING(arg5, ifrname);
|
||||
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");
|
||||
@@ -1566,6 +1661,9 @@ PHP_FUNCTION(socket_sendto)
|
||||
struct sockaddr_in sin;
|
||||
#ifdef HAVE_IPV6
|
||||
struct sockaddr_in6 sin6;
|
||||
#endif
|
||||
#ifdef AF_PACKET
|
||||
//struct sockaddr_ll sll;
|
||||
#endif
|
||||
int retval;
|
||||
size_t buf_len, addr_len;
|
||||
@@ -1639,6 +1737,22 @@ PHP_FUNCTION(socket_sendto)
|
||||
|
||||
retval = sendto(php_sock->bsd_socket, buf, ((size_t)len > buf_len) ? buf_len : (size_t)len, flags, (struct sockaddr *) &sin6, sizeof(sin6));
|
||||
break;
|
||||
#endif
|
||||
#ifdef AF_PACKET
|
||||
/*
|
||||
case AF_PACKET:
|
||||
if (port_is_null) {
|
||||
zend_argument_value_error(6, "cannot be null when the socket type is AF_PACKET");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
memset(&sll, 0, sizeof(sll));
|
||||
sll.sll_family = AF_PACKET;
|
||||
sll.sll_ifindex = port;
|
||||
|
||||
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, or AF_INET6");
|
||||
@@ -2702,6 +2816,8 @@ PHP_FUNCTION(socket_addrinfo_bind)
|
||||
|
||||
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);
|
||||
|
||||
@@ -2765,6 +2881,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);
|
||||
|
||||
|
||||
@@ -26,6 +26,13 @@ const AF_INET6 = UNKNOWN;
|
||||
*/
|
||||
const AF_DIVERT = UNKNOWN;
|
||||
#endif
|
||||
#ifdef AF_PACKET
|
||||
/**
|
||||
* @var int
|
||||
* @cvalue AF_PACKET
|
||||
*/
|
||||
const AF_PACKET = UNKNOWN;
|
||||
#endif
|
||||
/**
|
||||
* @var int
|
||||
* @cvalue SOCK_STREAM
|
||||
@@ -1978,6 +1985,28 @@ const UDPLITE_SEND_CSCOV = UNKNOWN;
|
||||
*/
|
||||
const UDPLITE_RECV_CSCOV = UNKNOWN;
|
||||
#endif
|
||||
#if defined(ETH_P_ALL)
|
||||
/**
|
||||
* @var int
|
||||
* @cvalue ETH_P_IP
|
||||
*/
|
||||
const ETH_P_IP = UNKNOWN;
|
||||
/**
|
||||
* @var int
|
||||
* @cvalue ETH_P_IPV6
|
||||
*/
|
||||
const ETH_P_IPV6 = UNKNOWN;
|
||||
/**
|
||||
* @var int
|
||||
* @cvalue ETH_P_LOOP
|
||||
*/
|
||||
const ETH_P_LOOP = UNKNOWN;
|
||||
/**
|
||||
* @var int
|
||||
* @cvalue ETH_P_ALL
|
||||
*/
|
||||
const ETH_P_ALL = UNKNOWN;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @strict-properties
|
||||
|
||||
17
ext/sockets/sockets_arginfo.h
generated
17
ext/sockets/sockets_arginfo.h
generated
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 2c5f4685d5dab42426d4fe0553dd17cb9935a572 */
|
||||
* Stub hash: 0be24cb2f268ab3d43121637ae451d8da4b50410 */
|
||||
|
||||
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)
|
||||
@@ -319,6 +319,9 @@ static void register_sockets_symbols(int module_number)
|
||||
#endif
|
||||
#if defined(AF_DIVERT)
|
||||
REGISTER_LONG_CONSTANT("AF_DIVERT", AF_DIVERT, CONST_PERSISTENT);
|
||||
#endif
|
||||
#if defined(AF_PACKET)
|
||||
REGISTER_LONG_CONSTANT("AF_PACKET", AF_PACKET, CONST_PERSISTENT);
|
||||
#endif
|
||||
REGISTER_LONG_CONSTANT("SOCK_STREAM", SOCK_STREAM, CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("SOCK_DGRAM", SOCK_DGRAM, CONST_PERSISTENT);
|
||||
@@ -1087,6 +1090,18 @@ static void register_sockets_symbols(int module_number)
|
||||
#if defined(UDPLITE_RECV_CSCOV)
|
||||
REGISTER_LONG_CONSTANT("UDPLITE_RECV_CSCOV", UDPLITE_RECV_CSCOV, CONST_PERSISTENT);
|
||||
#endif
|
||||
#if defined(ETH_P_ALL)
|
||||
REGISTER_LONG_CONSTANT("ETH_P_IP", ETH_P_IP, CONST_PERSISTENT);
|
||||
#endif
|
||||
#if defined(ETH_P_ALL)
|
||||
REGISTER_LONG_CONSTANT("ETH_P_IPV6", ETH_P_IPV6, CONST_PERSISTENT);
|
||||
#endif
|
||||
#if defined(ETH_P_ALL)
|
||||
REGISTER_LONG_CONSTANT("ETH_P_LOOP", ETH_P_LOOP, CONST_PERSISTENT);
|
||||
#endif
|
||||
#if defined(ETH_P_ALL)
|
||||
REGISTER_LONG_CONSTANT("ETH_P_ALL", ETH_P_ALL, CONST_PERSISTENT);
|
||||
#endif
|
||||
}
|
||||
|
||||
static zend_class_entry *register_class_Socket(void)
|
||||
|
||||
37
ext/sockets/tests/socket_afpacket.phpt
Normal file
37
ext/sockets/tests/socket_afpacket.phpt
Normal file
@@ -0,0 +1,37 @@
|
||||
--TEST--
|
||||
socket_getsockname from AF_PACKET socket
|
||||
--EXTENSIONS--
|
||||
sockets
|
||||
posix
|
||||
--SKIPIF--
|
||||
<?php
|
||||
|
||||
if (!defined("AF_PACKET")) {
|
||||
die('SKIP AF_PACKET not supported on this platform.');
|
||||
}
|
||||
if (!function_exists("posix_getuid") || posix_getuid() != 0) {
|
||||
die('SKIP AF_PACKET requires root permissions.');
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$s_c = socket_create(AF_PACKET, SOCK_RAW, ETH_P_IP);
|
||||
$s_bind = socket_bind($s_c, 'lo');
|
||||
var_dump($s_bind);
|
||||
|
||||
// sock_getsockname in this context gets the interface rather than the address.
|
||||
$s_conn = socket_getsockname($s_c, $istr, $iindex);
|
||||
var_dump($s_conn);
|
||||
var_dump($istr);
|
||||
var_dump($iindex);
|
||||
|
||||
socket_getpeername($s_c, $istr2, $iindex2);
|
||||
socket_close($s_c);
|
||||
?>
|
||||
--EXPECTF--
|
||||
bool(true)
|
||||
bool(true)
|
||||
string(2) "lo"
|
||||
int(%i)
|
||||
|
||||
Warning: socket_getpeername(): unable to retrieve peer name [95]: Operation not supported in %s on line %d
|
||||
Reference in New Issue
Block a user