Skip to content

Commit b271edd

Browse files
committed
ext/sockets: linux AF_PACKET support.
1 parent 11937b3 commit b271edd

File tree

4 files changed

+116
-13
lines changed

4 files changed

+116
-13
lines changed

ext/sockets/config.m4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ PHP_ARG_ENABLE([sockets],
55

66
if test "$PHP_SOCKETS" != "no"; then
77
AC_CHECK_FUNCS([hstrerror if_nametoindex if_indextoname sockatmark])
8-
AC_CHECK_HEADERS([sys/sockio.h linux/filter.h])
8+
AC_CHECK_HEADERS([sys/sockio.h linux/filter.h linux/if_packet.h linux/if_ether.h])
99
AC_DEFINE([HAVE_SOCKETS], [1],
1010
[Define to 1 if the PHP extension 'sockets' is available.])
1111

ext/sockets/sockets.c

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@
6464
# else
6565
# undef SO_BPF_EXTENSIONS
6666
# endif
67+
# if defined(HAVE_LINUX_IF_PACKET_H)
68+
# include <linux/if_packet.h>
69+
# endif
70+
# if defined(HAVE_LINUX_IF_ETHER_H)
71+
# include <linux/if_ether.h>
72+
# endif
6773
#endif
6874

6975
#include <stddef.h>
@@ -960,13 +966,16 @@ PHP_FUNCTION(socket_read)
960966
/* {{{ 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. */
961967
PHP_FUNCTION(socket_getsockname)
962968
{
963-
zval *arg1, *addr, *port = NULL;
969+
zval *arg1, *addr, *objint = NULL;
964970
php_sockaddr_storage sa_storage = {0};
965971
php_socket *php_sock;
966972
struct sockaddr *sa;
967973
struct sockaddr_in *sin;
968974
#ifdef HAVE_IPV6
969975
struct sockaddr_in6 *sin6;
976+
#endif
977+
#ifdef AF_PACKET
978+
struct sockaddr_ll *sll;
970979
#endif
971980
char addrbuf[INET6_ADDRSTRLEN];
972981
struct sockaddr_un *s_un;
@@ -977,7 +986,7 @@ PHP_FUNCTION(socket_getsockname)
977986
Z_PARAM_OBJECT_OF_CLASS(arg1, socket_ce)
978987
Z_PARAM_ZVAL(addr)
979988
Z_PARAM_OPTIONAL
980-
Z_PARAM_ZVAL(port)
989+
Z_PARAM_ZVAL(objint)
981990
ZEND_PARSE_PARAMETERS_END();
982991

983992
php_sock = Z_SOCKET_P(arg1);
@@ -997,8 +1006,8 @@ PHP_FUNCTION(socket_getsockname)
9971006
inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf, sizeof(addrbuf));
9981007
ZEND_TRY_ASSIGN_REF_STRING(addr, addrbuf);
9991008

1000-
if (port != NULL) {
1001-
ZEND_TRY_ASSIGN_REF_LONG(port, htons(sin6->sin6_port));
1009+
if (objint != NULL) {
1010+
ZEND_TRY_ASSIGN_REF_LONG(objint, htons(sin6->sin6_port));
10021011
}
10031012
RETURN_TRUE;
10041013
break;
@@ -1008,8 +1017,8 @@ PHP_FUNCTION(socket_getsockname)
10081017
addr_string = inet_ntop(AF_INET, &sin->sin_addr, addrbuf, sizeof(addrbuf));
10091018
ZEND_TRY_ASSIGN_REF_STRING(addr, addr_string);
10101019

1011-
if (port != NULL) {
1012-
ZEND_TRY_ASSIGN_REF_LONG(port, htons(sin->sin_port));
1020+
if (objint != NULL) {
1021+
ZEND_TRY_ASSIGN_REF_LONG(objint, htons(sin->sin_port));
10131022
}
10141023
RETURN_TRUE;
10151024
break;
@@ -1020,9 +1029,19 @@ PHP_FUNCTION(socket_getsockname)
10201029
ZEND_TRY_ASSIGN_REF_STRING(addr, s_un->sun_path);
10211030
RETURN_TRUE;
10221031
break;
1032+
#ifdef AF_PACKET
1033+
case AF_PACKET:
1034+
sll = (struct sockaddr_ll *) sa;
1035+
1036+
if (objint != NULL) {
1037+
ZEND_TRY_ASSIGN_REF_LONG(objint, sll->sll_ifindex);
1038+
}
1039+
RETURN_TRUE;
1040+
break;
1041+
#endif
10231042

10241043
default:
1025-
zend_argument_value_error(1, "must be one of AF_UNIX, AF_INET, or AF_INET6");
1044+
zend_argument_value_error(1, "must be one of AF_UNIX, AF_PACKET, AF_INET, or AF_INET6");
10261045
RETURN_THROWS();
10271046
}
10281047
}
@@ -1038,6 +1057,9 @@ PHP_FUNCTION(socket_getpeername)
10381057
struct sockaddr_in *sin;
10391058
#ifdef HAVE_IPV6
10401059
struct sockaddr_in6 *sin6;
1060+
#endif
1061+
#ifdef AF_PACKET
1062+
struct sockaddr_ll *sll;
10411063
#endif
10421064
char addrbuf[INET6_ADDRSTRLEN];
10431065
struct sockaddr_un *s_un;
@@ -1094,6 +1116,17 @@ PHP_FUNCTION(socket_getpeername)
10941116
ZEND_TRY_ASSIGN_REF_STRING(arg2, s_un->sun_path);
10951117
RETURN_TRUE;
10961118
break;
1119+
#ifdef AF_PACKET
1120+
case AF_PACKET:
1121+
sll = (struct sockaddr_ll *) sa;
1122+
1123+
if (arg3 != NULL) {
1124+
ZEND_TRY_ASSIGN_REF_LONG(arg3, sll->sll_ifindex);
1125+
}
1126+
RETURN_TRUE;
1127+
break;
1128+
#endif
1129+
10971130

10981131
default:
10991132
zend_argument_value_error(1, "must be one of AF_UNIX, AF_INET, or AF_INET6");
@@ -1117,9 +1150,12 @@ PHP_FUNCTION(socket_create)
11171150
if (domain != AF_UNIX
11181151
#ifdef HAVE_IPV6
11191152
&& domain != AF_INET6
1153+
#endif
1154+
#ifdef AF_PACKET
1155+
&& domain != AF_PACKET
11201156
#endif
11211157
&& domain != AF_INET) {
1122-
zend_argument_value_error(1, "must be one of AF_UNIX, AF_INET6, or AF_INET");
1158+
zend_argument_value_error(1, "must be one of AF_UNIX, AF_PACKET, AF_INET6, or AF_INET");
11231159
RETURN_THROWS();
11241160
}
11251161

@@ -1138,6 +1174,17 @@ PHP_FUNCTION(socket_create)
11381174
RETURN_THROWS();
11391175
}
11401176

1177+
#ifdef ETH_P_ALL
1178+
if (protocol == ETH_P_IP || protocol == ETH_P_ARP || protocol == ETH_P_ALL) {
1179+
if (domain != AF_PACKET) {
1180+
zend_argument_value_error(1, "must be AF_PACKET when one of the ETH_P_* constants is used");
1181+
RETURN_THROWS();
1182+
}
1183+
// Those constants are defined in host byte order
1184+
protocol = htons(protocol);
1185+
}
1186+
#endif
1187+
11411188
object_init_ex(return_value, socket_ce);
11421189
php_sock = Z_SOCKET_P(return_value);
11431190

@@ -2702,6 +2749,18 @@ PHP_FUNCTION(socket_addrinfo_bind)
27022749

27032750
ai = Z_ADDRESS_INFO_P(arg1);
27042751

2752+
#ifdef ETH_P_ALL
2753+
if (ai->addrinfo.ai_protocol == ETH_P_IP || ai->addrinfo.ai_protocol == ETH_P_ARP ||
2754+
ai->addrinfo.ai_protocol == ETH_P_ALL) {
2755+
if (ai->addrinfo.ai_family != AF_PACKET) {
2756+
zend_value_error("\"ai_family\" array option must be AF_PACKET when one of the ETH_P_* constants is used");
2757+
RETURN_THROWS();
2758+
}
2759+
// Those constants are defined in host byte order
2760+
ai->addrinfo.ai_protocol = htons(ai->addrinfo.ai_protocol);
2761+
}
2762+
#endif
2763+
27052764
object_init_ex(return_value, socket_ce);
27062765
php_sock = Z_SOCKET_P(return_value);
27072766

ext/sockets/sockets.stub.php

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@
2626
*/
2727
const AF_DIVERT = UNKNOWN;
2828
#endif
29+
#ifdef AF_PACKET
30+
/**
31+
* @var int
32+
* @cvalue AF_PACKET
33+
*/
34+
const AF_PACKET = UNKNOWN;
35+
#endif
2936
/**
3037
* @var int
3138
* @cvalue SOCK_STREAM
@@ -1978,6 +1985,28 @@
19781985
*/
19791986
const UDPLITE_RECV_CSCOV = UNKNOWN;
19801987
#endif
1988+
#if defined(ETH_P_ALL)
1989+
/**
1990+
* @var int
1991+
* @cvalue ETH_P_IP
1992+
*/
1993+
const ETH_P_IP = UNKNOWN;
1994+
/**
1995+
* @var int
1996+
* @cvalue ETH_P_IPV6
1997+
*/
1998+
const ETH_P_IPV6 = UNKNOWN;
1999+
/**
2000+
* @var int
2001+
* @cvalue ETH_P_ARP
2002+
*/
2003+
const ETH_P_ARP = UNKNOWN;
2004+
/**
2005+
* @var int
2006+
* @cvalue ETH_P_ALL
2007+
*/
2008+
const ETH_P_ALL = UNKNOWN;
2009+
#endif
19812010

19822011
/**
19832012
* @strict-properties
@@ -2017,13 +2046,13 @@ function socket_read(Socket $socket, int $length, int $mode = PHP_BINARY_READ):
20172046
* @param string $address
20182047
* @param int $port
20192048
*/
2020-
function socket_getsockname(Socket $socket, &$address, &$port = null): bool {}
2049+
function socket_getsockname(Socket $socket, &$address, ?int &$objint = null): bool {}
20212050

20222051
/**
20232052
* @param string $address
20242053
* @param int $port
20252054
*/
2026-
function socket_getpeername(Socket $socket, &$address, &$port = null): bool {}
2055+
function socket_getpeername(Socket $socket, &$address, ?int &$objint = null): bool {}
20272056

20282057
function socket_create(int $domain, int $type, int $protocol): Socket|false {}
20292058

ext/sockets/sockets_arginfo.h

Lines changed: 17 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)