Skip to content

Commit

Permalink
ext/sockets: adding IPPROTO_ICMP* constants for socket creations.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
devnexen committed Nov 12, 2024
1 parent 7202d11 commit 33ba1a4
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 1 deletion.
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ PHP NEWS
. Fixed bug #49169 (SoapServer calls wrong function, although "SOAP action"
header is correct). (nielsdos)

- Sockets:
. Added IPPROTO_ICMP/IPPROTO_ICMPV6 to create raw socket for ICMP usage.
(David Carlier)

- Standard:
. Fixed crypt() tests on musl when using --with-external-libcrypt
(Michael Orlitzky).
Expand Down
3 changes: 3 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ PHP 8.5 UPGRADE NOTES
- POSIX:
. POSIX_SC_OPEN_MAX.

- Sockets:
. IPPROTO_ICMP/IPPROTO_ICMPV6.

========================================
11. Changes to INI File Handling
========================================
Expand Down
14 changes: 14 additions & 0 deletions ext/sockets/sockets.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -1647,6 +1647,20 @@
*/
const SOL_UDPLITE = UNKNOWN;
#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
/**
Expand Down
8 changes: 7 additions & 1 deletion ext/sockets/sockets_arginfo.h

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

57 changes: 57 additions & 0 deletions ext/sockets/tests/socket_icmp.phpt
Original file line number Diff line number Diff line change
@@ -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"

0 comments on commit 33ba1a4

Please sign in to comment.