Skip to content

Commit 33ba1a4

Browse files
committed
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 phpGH-16737
1 parent 7202d11 commit 33ba1a4

File tree

5 files changed

+85
-1
lines changed

5 files changed

+85
-1
lines changed

NEWS

+4
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ PHP NEWS
4545
. Fixed bug #49169 (SoapServer calls wrong function, although "SOAP action"
4646
header is correct). (nielsdos)
4747

48+
- Sockets:
49+
. Added IPPROTO_ICMP/IPPROTO_ICMPV6 to create raw socket for ICMP usage.
50+
(David Carlier)
51+
4852
- Standard:
4953
. Fixed crypt() tests on musl when using --with-external-libcrypt
5054
(Michael Orlitzky).

UPGRADING

+3
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ PHP 8.5 UPGRADE NOTES
129129
- POSIX:
130130
. POSIX_SC_OPEN_MAX.
131131

132+
- Sockets:
133+
. IPPROTO_ICMP/IPPROTO_ICMPV6.
134+
132135
========================================
133136
11. Changes to INI File Handling
134137
========================================

ext/sockets/sockets.stub.php

+14
Original file line numberDiff line numberDiff line change
@@ -1647,6 +1647,20 @@
16471647
*/
16481648
const SOL_UDPLITE = UNKNOWN;
16491649
#endif
1650+
#if defined(IPPROTO_ICMP) || defined(PHP_WIN32)
1651+
/**
1652+
* @var int
1653+
* @cvalue IPPROTO_ICMP
1654+
*/
1655+
const IPPROTO_ICMP = UNKNOWN;
1656+
#endif
1657+
#if defined(IPPROTO_ICMPV6) || defined(PHP_WIN32)
1658+
/**
1659+
* @var int
1660+
* @cvalue IPPROTO_ICMPV6
1661+
*/
1662+
const IPPROTO_ICMPV6 = UNKNOWN;
1663+
#endif
16501664

16511665
#ifdef HAVE_IPV6
16521666
/**

ext/sockets/sockets_arginfo.h

+7-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/sockets/tests/socket_icmp.phpt

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
--TEST--
2+
socket_create with IPPROTO_ICMP
3+
--EXTENSIONS--
4+
sockets
5+
--SKIPIF--
6+
<?php
7+
if (!defined("IPPROTO_ICMP")) die("skip IPPROTO_ICMP not available");
8+
// IPPROTO_ICMP* functions with raw sockets, thus requiring administrative role.
9+
if (PHP_OS_FAMILY !== "Windows" && (!function_exists("posix_getuid") || posix_getuid() != 0)) die('skip IPPROTO_ICMP requires root permissions.');
10+
?>
11+
--FILE--
12+
<?php
13+
14+
$host = '127.0.0.1';
15+
16+
$type = 8;
17+
$code = 0;
18+
$identifier = 16;
19+
$sequence = 1;
20+
$data = "ECHO";
21+
22+
$socket = socket_create(AF_INET, SOCK_RAW, IPPROTO_ICMP);
23+
if (!$socket) {
24+
die("Unable to create socket: " . socket_strerror(socket_last_error()) . "\n");
25+
}
26+
27+
$header = pack('C2n3a*', $type, $code, 0, $identifier, $sequence, $data);
28+
$checksum = function($header): int {
29+
$bit = unpack('n*', $header);
30+
$sum = array_sum($bit);
31+
32+
while ($sum >> 16) {
33+
$sum = ($sum & 0xFFFF) + ($sum >> 16);
34+
}
35+
return ~ $sum & 0xFFFF;
36+
};
37+
$header = pack('C2n3a*', $type, $code, $checksum($header), $identifier, $sequence, $data);
38+
39+
if (!socket_sendto($socket, $header, strlen($header), 0, $host, 0)) {
40+
die("Unable to send packet: " . socket_strerror(socket_last_error($socket)) . "\n");
41+
}
42+
43+
$read = [$socket];
44+
$write = $except = [];
45+
$timeout = ['sec' => 4, 'usec' => 0];
46+
if (socket_select($read, $write, $except, $timeout['sec'], $timeout['usec']) > 0) {
47+
$response = '';
48+
socket_recv($socket, $response, 65535, 0);
49+
var_dump(bin2hex($response));
50+
} else {
51+
die("Unable to read the response\n");
52+
}
53+
54+
socket_close($socket);
55+
?>
56+
--EXPECTF--
57+
string(64) "%s"

0 commit comments

Comments
 (0)