ext/sockets: adding IPPROTO_ICMP* constants for socket creations.

Is to create socket for Internet Control Message Protocol context.
Due to their nature, they are meant to be used via
raw sockets rather than TCP/UDP.

close GH-16737
This commit is contained in:
David Carlier 2024-11-09 12:24:06 +00:00
parent 7202d119cd
commit 33ba1a4ab9
No known key found for this signature in database
GPG key ID: 8486F847B4B94EF1
5 changed files with 85 additions and 1 deletions

4
NEWS
View file

@ -45,6 +45,10 @@ PHP NEWS
. Fixed bug #49169 (SoapServer calls wrong function, although "SOAP action" . Fixed bug #49169 (SoapServer calls wrong function, although "SOAP action"
header is correct). (nielsdos) header is correct). (nielsdos)
- Sockets:
. Added IPPROTO_ICMP/IPPROTO_ICMPV6 to create raw socket for ICMP usage.
(David Carlier)
- Standard: - Standard:
. Fixed crypt() tests on musl when using --with-external-libcrypt . Fixed crypt() tests on musl when using --with-external-libcrypt
(Michael Orlitzky). (Michael Orlitzky).

View file

@ -129,6 +129,9 @@ PHP 8.5 UPGRADE NOTES
- POSIX: - POSIX:
. POSIX_SC_OPEN_MAX. . POSIX_SC_OPEN_MAX.
- Sockets:
. IPPROTO_ICMP/IPPROTO_ICMPV6.
======================================== ========================================
11. Changes to INI File Handling 11. Changes to INI File Handling
======================================== ========================================

View file

@ -1647,6 +1647,20 @@ const SOL_UDP = UNKNOWN;
*/ */
const SOL_UDPLITE = UNKNOWN; const SOL_UDPLITE = UNKNOWN;
#endif #endif
#if defined(IPPROTO_ICMP) || defined(PHP_WIN32)
/**
* @var int
* @cvalue IPPROTO_ICMP
*/
const IPPROTO_ICMP = UNKNOWN;
#endif
#if defined(IPPROTO_ICMPV6) || defined(PHP_WIN32)
/**
* @var int
* @cvalue IPPROTO_ICMPV6
*/
const IPPROTO_ICMPV6 = UNKNOWN;
#endif
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
/** /**

View file

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead. /* This is a generated file, edit the .stub.php file instead.
* Stub hash: 08677a3dd11366b55a1c539475adead74109595e */ * Stub hash: 4fdd210a2de6f3b5df10caf5ac7fefa6aa71926c */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_select, 0, 4, MAY_BE_LONG|MAY_BE_FALSE) 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) ZEND_ARG_TYPE_INFO(1, read, IS_ARRAY, 1)
@ -945,6 +945,12 @@ static void register_sockets_symbols(int module_number)
#if defined(IPPROTO_UDPLITE) #if defined(IPPROTO_UDPLITE)
REGISTER_LONG_CONSTANT("SOL_UDPLITE", IPPROTO_UDPLITE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SOL_UDPLITE", IPPROTO_UDPLITE, CONST_PERSISTENT);
#endif #endif
#if defined(IPPROTO_ICMP) || defined(PHP_WIN32)
REGISTER_LONG_CONSTANT("IPPROTO_ICMP", IPPROTO_ICMP, CONST_PERSISTENT);
#endif
#if defined(IPPROTO_ICMPV6) || defined(PHP_WIN32)
REGISTER_LONG_CONSTANT("IPPROTO_ICMPV6", IPPROTO_ICMPV6, CONST_PERSISTENT);
#endif
#if defined(HAVE_IPV6) #if defined(HAVE_IPV6)
REGISTER_LONG_CONSTANT("IPV6_UNICAST_HOPS", IPV6_UNICAST_HOPS, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IPV6_UNICAST_HOPS", IPV6_UNICAST_HOPS, CONST_PERSISTENT);
#endif #endif

View file

@ -0,0 +1,57 @@
--TEST--
socket_create with IPPROTO_ICMP
--EXTENSIONS--
sockets
--SKIPIF--
<?php
if (!defined("IPPROTO_ICMP")) die("skip IPPROTO_ICMP not available");
// IPPROTO_ICMP* functions with raw sockets, thus requiring administrative role.
if (PHP_OS_FAMILY !== "Windows" && (!function_exists("posix_getuid") || posix_getuid() != 0)) die('skip IPPROTO_ICMP requires root permissions.');
?>
--FILE--
<?php
$host = '127.0.0.1';
$type = 8;
$code = 0;
$identifier = 16;
$sequence = 1;
$data = "ECHO";
$socket = socket_create(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (!$socket) {
die("Unable to create socket: " . socket_strerror(socket_last_error()) . "\n");
}
$header = pack('C2n3a*', $type, $code, 0, $identifier, $sequence, $data);
$checksum = function($header): int {
$bit = unpack('n*', $header);
$sum = array_sum($bit);
while ($sum >> 16) {
$sum = ($sum & 0xFFFF) + ($sum >> 16);
}
return ~ $sum & 0xFFFF;
};
$header = pack('C2n3a*', $type, $code, $checksum($header), $identifier, $sequence, $data);
if (!socket_sendto($socket, $header, strlen($header), 0, $host, 0)) {
die("Unable to send packet: " . socket_strerror(socket_last_error($socket)) . "\n");
}
$read = [$socket];
$write = $except = [];
$timeout = ['sec' => 4, 'usec' => 0];
if (socket_select($read, $write, $except, $timeout['sec'], $timeout['usec']) > 0) {
$response = '';
socket_recv($socket, $response, 65535, 0);
var_dump(bin2hex($response));
} else {
die("Unable to read the response\n");
}
socket_close($socket);
?>
--EXPECTF--
string(64) "%s"