29# define O_RDONLY _O_RDONLY
36#ifdef HAVE_SYS_SOCKET_H
37#include <sys/socket.h>
44#ifdef HAVE_SYS_SELECT_H
45#include <sys/select.h>
55#include <netinet/in.h>
57#ifdef HAVE_ARPA_INET_H
64#if defined(PHP_WIN32) || defined(__riscos__)
76# define SOCK_ERR INVALID_SOCKET
77# define SOCK_CONN_ERR SOCKET_ERROR
78# define PHP_TIMEOUT_ERROR_VALUE WSAETIMEDOUT
81const struct in6_addr in6addr_any = {0};
86# define SOCK_CONN_ERR -1
87# define PHP_TIMEOUT_ERROR_VALUE ETIMEDOUT
90#ifdef HAVE_GETADDRINFO
91# if !defined(PHP_WIN32) && !defined(HAVE_GAI_STRERROR)
93static const char *php_gai_strerror(
int code)
100 {EAI_ADDRFAMILY,
"Address family for hostname not supported"},
102 {EAI_AGAIN,
"Temporary failure in name resolution"},
103 {EAI_BADFLAGS,
"Bad value for ai_flags"},
104 {EAI_FAIL,
"Non-recoverable failure in name resolution"},
105 {EAI_FAMILY,
"ai_family not supported"},
106 {EAI_MEMORY,
"Memory allocation failure"},
108 {EAI_NODATA,
"No address associated with hostname"},
110 {EAI_NONAME,
"Name or service not known"},
111 {EAI_SERVICE,
"Servname not supported for ai_socktype"},
112 {EAI_SOCKTYPE,
"ai_socktype not supported"},
114 {EAI_SYSTEM,
"System error"},
120 for (i = 0; values[i].msg !=
NULL; i++) {
121 if (values[i].code == code) {
122 return (
char *)values[i].msg;
126 return "Unknown error";
135 struct sockaddr **sap;
139 for (sap = sal; *sap !=
NULL; sap++)
150 struct sockaddr **sap;
152#ifdef HAVE_GETADDRINFO
154 static int ipv6_borked = -1;
156 struct addrinfo hints, *
res, *sai;
158 struct hostent *host_info;
165#ifdef HAVE_GETADDRINFO
166 memset(&hints,
'\0',
sizeof(hints));
169 hints.ai_socktype = socktype;
178 if (ipv6_borked == -1) {
189 hints.ai_family = ipv6_borked ?
AF_INET : AF_UNSPEC;
192 if ((
n = getaddrinfo(host,
NULL, &hints, &
res))) {
193# if defined(PHP_WIN32)
195# elif defined(HAVE_GAI_STRERROR)
196 const char *gai_error = gai_strerror(
n);
198 const char *gai_error = php_gai_strerror(
n)
205 *error_string =
strpprintf(0,
"php_network_getaddresses: getaddrinfo for %s failed: %s", host, gai_error);
220 *error_string =
strpprintf(0,
"php_network_getaddresses: getaddrinfo for %s failed (null result pointer) errno=%d", host,
errno);
229 for (
n = 1; (sai = sai->ai_next) !=
NULL;
n++)
237 *sap =
emalloc(sai->ai_addrlen);
238 memcpy(*sap, sai->ai_addr, sai->ai_addrlen);
240 }
while ((sai = sai->ai_next) !=
NULL);
251 if (host_info ==
NULL) {
257 *error_string =
strpprintf(0,
"php_network_getaddresses: gethostbyname failed. errno=%d",
errno);
264 in = *((
struct in_addr *) host_info->h_addr);
269 *sap =
emalloc(
sizeof(
struct sockaddr_in));
271 ((
struct sockaddr_in *)*sap)->sin_addr = in;
282#define O_NONBLOCK O_NDELAY
287# define SET_SOCKET_BLOCKING_MODE(sock, save) \
288 save = TRUE; ioctlsocket(sock, FIONBIO, &save)
289# define RESTORE_SOCKET_BLOCKING_MODE(sock, save) \
290 ioctlsocket(sock, FIONBIO, &save)
293# define SET_SOCKET_BLOCKING_MODE(sock, save) \
294 save = fcntl(sock, F_GETFL, 0); \
295 fcntl(sock, F_SETFL, save | O_NONBLOCK)
296# define RESTORE_SOCKET_BLOCKING_MODE(sock, save) \
297 fcntl(sock, F_SETFL, save)
300#ifdef HAVE_GETTIMEOFDAY
302static inline void sub_times(
struct timeval
a,
struct timeval b,
struct timeval *
result)
304 result->tv_usec =
a.tv_usec - b.tv_usec;
305 if (
result->tv_usec < 0L) {
307 result->tv_usec += 1000000L;
309 result->tv_sec =
a.tv_sec - b.tv_sec;
310 if (
result->tv_sec < 0L) {
312 result->tv_usec -= 1000000L;
316static inline void php_network_set_limit_time(
struct timeval *limit_time,
317 struct timeval *timeout)
320 limit_time->tv_sec += timeout->tv_sec;
321 limit_time->tv_usec += timeout->tv_usec;
322 if (limit_time->tv_usec >= 1000000) {
323 limit_time->tv_usec -= 1000000;
324 limit_time->tv_sec++;
335 const struct sockaddr *
addr,
338 struct timeval *timeout,
350 if ((
n = connect(sockfd,
addr, addrlen)) != 0) {
385 struct timeval working_timeout;
386#ifdef HAVE_GETTIMEOFDAY
387 struct timeval limit_time, time_now;
390 memcpy(&working_timeout, timeout,
sizeof(working_timeout));
391#ifdef HAVE_GETTIMEOFDAY
392 php_network_set_limit_time(&limit_time, &working_timeout);
397 n = php_pollfd_for(sockfd, events, timeout ? &working_timeout :
NULL);
399 if (
errno == EINTR) {
400#ifdef HAVE_GETTIMEOFDAY
404 if (!
timercmp(&time_now, &limit_time, <)) {
410 sub_times(limit_time, time_now, &working_timeout);
458 int num_addrs,
n,
err = 0;
460 struct sockaddr **sal, **psal, *sa;
466 if (num_addrs == 0) {
471 for (sal = psal; *sal !=
NULL; sal++) {
474 switch (sa->sa_family) {
475#if defined(HAVE_GETADDRINFO) && defined(HAVE_IPV6)
477 ((
struct sockaddr_in6 *)sa)->sin6_port = htons(port);
478 socklen =
sizeof(
struct sockaddr_in6);
482 ((
struct sockaddr_in *)sa)->sin_port = htons(port);
483 socklen =
sizeof(
struct sockaddr_in);
491 sock = socket(sa->sa_family, socktype, 0);
520 setsockopt(sock, IPPROTO_TCP,
TCP_NODELAY, (
char*)&sockoptval,
sizeof(sockoptval));
524 n = bind(sock, sa, socklen);
558 struct sockaddr_in *in4 = (
struct sockaddr_in*)sa;
559 struct sockaddr **psal;
563 struct sockaddr_in6 *in6 = (
struct sockaddr_in6*)sa;
565 memset(in6, 0,
sizeof(
struct sockaddr_in6));
567 memset(in4, 0,
sizeof(
struct sockaddr_in));
571 colon = memchr(
addr + 1,
']', addrlen-1);
572 if (!colon || colon[1] !=
':') {
575 port = atoi(colon + 2);
578 colon = memchr(
addr,
':', addrlen);
582 port = atoi(colon + 1);
591 in6->sin6_port = htons(port);
593 *sl =
sizeof(
struct sockaddr_in6);
599 in4->sin_port = htons(port);
601 *sl =
sizeof(
struct sockaddr_in);
618 switch ((*psal)->sa_family) {
619#if defined(HAVE_GETADDRINFO) && defined(HAVE_IPV6)
621 *in6 = **(
struct sockaddr_in6**)psal;
622 in6->sin6_port = htons(port);
623 *sl =
sizeof(
struct sockaddr_in6);
628 *in4 = **(
struct sockaddr_in**)psal;
629 in4->sin_port = htons(port);
630 *sl =
sizeof(
struct sockaddr_in);
649 struct sockaddr **
addr,
663 switch (sa->sa_family) {
666 buf =
inet_ntop(
AF_INET, &((
struct sockaddr_in*)sa)->sin_addr, (
char *)&abuf,
sizeof(abuf));
669 buf, ntohs(((
struct sockaddr_in*)sa)->sin_port));
676 buf = (
char*)
inet_ntop(sa->sa_family, &((
struct sockaddr_in6*)sa)->sin6_addr, (
char *)&abuf,
sizeof(abuf));
679 buf, ntohs(((
struct sockaddr_in6*)sa)->sin6_port));
687 struct sockaddr_un *ua = (
struct sockaddr_un*)sa;
689 if (ua->sun_path[0] ==
'\0') {
691 int len = sl -
sizeof(sa_family_t);
692 *textaddr = zend_string_init((
char*)ua->sun_path,
len, 0);
695 *textaddr = zend_string_init((
char*)ua->sun_path,
len, 0);
708 struct sockaddr **
addr,
714 memset(&sa, 0,
sizeof(sa));
716 if (getpeername(sock, (
struct sockaddr*)&sa, &sl) == 0) {
728 struct sockaddr **
addr,
734 memset(&sa, 0,
sizeof(sa));
736 if (getsockname(sock, (
struct sockaddr*)&sa, &sl) == 0) {
759 struct sockaddr **
addr,
761 struct timeval *timeout,
776 }
else if (
n == -1) {
781 clisock = accept(srvsock, (
struct sockaddr*)&sa, &sl);
790 setsockopt(clisock, IPPROTO_TCP,
TCP_NODELAY, (
char*)&tcp_nodelay,
sizeof(tcp_nodelay));
817 int socktype,
int asynchronous,
struct timeval *timeout,
zend_string **error_string,
818 int *
error_code,
const char *bindto,
unsigned short bindport,
long sockopts
821 int num_addrs,
n, fatal = 0;
823 struct sockaddr **sal, **psal, *sa;
824 struct timeval working_timeout;
826#ifdef HAVE_GETTIMEOFDAY
827 struct timeval limit_time, time_now;
832 if (num_addrs == 0) {
838 memcpy(&working_timeout, timeout,
sizeof(working_timeout));
839#ifdef HAVE_GETTIMEOFDAY
840 php_network_set_limit_time(&limit_time, &working_timeout);
844 for (sal = psal; !fatal && *sal !=
NULL; sal++) {
847 switch (sa->sa_family) {
848#if defined(HAVE_GETADDRINFO) && defined(HAVE_IPV6)
850 if (!bindto ||
strchr(bindto,
':')) {
851 ((
struct sockaddr_in6 *)sa)->sin6_port = htons(port);
852 socklen =
sizeof(
struct sockaddr_in6);
860 ((
struct sockaddr_in *)sa)->sin_port = htons(port);
861 socklen =
sizeof(
struct sockaddr_in);
862 if (bindto && (
strchr(bindto,
':') || !
strcmp(bindto,
"0"))) {
873 sock = socket(sa->sa_family, socktype, 0);
883 struct sockaddr common;
884 struct sockaddr_in in4;
886 struct sockaddr_in6 in6;
888 } local_address = {0};
889 size_t local_address_len = 0;
891 if (sa->sa_family ==
AF_INET) {
893 local_address_len =
sizeof(
struct sockaddr_in);
894 local_address.in4.sin_family = sa->sa_family;
895 local_address.in4.sin_port = htons(bindport);
901 local_address_len =
sizeof(
struct sockaddr_in6);
902 local_address.in6.sin6_family = sa->sa_family;
903 local_address.in6.sin6_port = htons(bindport);
907#ifdef IP_BIND_ADDRESS_NO_PORT
913 if (local_address_len == 0) {
915 }
else if (bind(sock, &local_address.common, local_address_len)) {
920 if (error_string && *error_string) {
922 *error_string =
NULL;
943 timeout ? &working_timeout :
NULL,
951#ifdef HAVE_GETTIMEOFDAY
955 if (!
timercmp(&time_now, &limit_time, <)) {
960 sub_times(limit_time, time_now, &working_timeout);
973 memcpy(&working_timeout, timeout,
sizeof(working_timeout));
999 struct sockaddr_in6 *sin6 = (
struct sockaddr_in6 *)
addr;
1001 sin6->sin6_port = htons(port);
1002 sin6->sin6_addr = in6addr_any;
1007 struct sockaddr_in *
sin = (
struct sockaddr_in *)
addr;
1009 sin->sin_port = htons(port);
1010 sin->sin_addr.s_addr = htonl(INADDR_ANY);
1022 switch (((
struct sockaddr *)
addr)->sa_family) {
1024 return sizeof(
struct sockaddr_in);
1027 return sizeof(
struct sockaddr_in6);
1031 return sizeof(
struct sockaddr_un);
1050 errstr = strerror(
err);
1054 strncpy(
buf, errstr, bufsize);
1055 buf[bufsize?(bufsize-1):0] = 0;
1061 sysbuf =
"Unknown Error";
1067 strncpy(
buf, sysbuf, bufsize);
1068 buf[bufsize?(bufsize-1):0] = 0;
1084 errstr = strerror(
err);
1085 return zend_string_init(errstr,
strlen(errstr), 0);
1091 sysbuf =
"Unknown Error";
1094 ret = zend_string_init(sysbuf,
strlen(sysbuf), 0);
1113 sock->
timeout.tv_sec =
FG(default_socket_timeout);
1119 if (stream ==
NULL) {
1120 pefree(sock, persistent_id ? 1 : 0);
1129 int socktype,
struct timeval *timeout,
const char *persistent_id
STREAMS_DC)
1135 reslen =
spprintf(&
res, 0,
"tcp://%s:%d", host, port);
1154 if (ioctlsocket(socketd, FIONBIO, &
flags) == SOCKET_ERROR) {
1159 int flags = fcntl(socketd, F_GETFL);
1163#elif defined(O_NDELAY)
1171 if (fcntl(socketd, F_SETFL,
flags) == -1) {
1183 "PHP needs to be recompiled with a larger value of FD_SETSIZE.\n"
1184 "If this binary is from an official www.php.net package, file a bug report\n"
1185 "at https://github.com/php/php-src/issues, including the following information:\n"
1186 "FD_SETSIZE=%d, but you are using %d.\n"
1187 " --enable-fd-setsize=%d is recommended, but you may want to set it\n"
1188 "to match to maximum number of sockets each script will work with at\n"
1189 "one time, in order to avoid seeing this error again at a later date.",
1190 FD_SETSIZE, max_fd, (max_fd + 128) & ~127);
1193 "You MUST recompile PHP with a larger value of FD_SETSIZE.\n"
1194 "It is set to %d, but you have descriptors numbered at least as high as %d.\n"
1195 " --enable-fd-setsize=%d is recommended, but you may want to set it\n"
1196 "to equal the maximum number of open files supported by your system,\n"
1197 "in order to avoid seeing this error again at a later date.",
1198 FD_SETSIZE, max_fd, (max_fd + 1024) & ~1023);
1202#if defined(PHP_USE_POLL_2_EMULATION)
1208 fd_set rset, wset, eset;
1216 for (i = 0; i < nfds; i++) {
1217 if (ufds[i].
fd > max_fd)
1218 max_fd = ufds[i].
fd;
1224 WSASetLastError(WSAEINVAL);
1235 for (i = 0; i < nfds; i++) {
1239 if (ufds[i].events &
POLLOUT) {
1242 if (ufds[i].events &
POLLPRI) {
1248 tv.tv_sec = timeout / 1000;
1249 tv.tv_usec = (timeout - (
tv.tv_sec * 1000)) * 1000;
1257 n = select(max_fd + 1, &rset, &wset, &eset, timeout >= 0 ? &
tv :
NULL);
1260 for (i = 0; i < nfds; i++) {
1279#if defined(HAVE_GETHOSTBYNAME_R)
1280#ifdef HAVE_FUNC_GETHOSTBYNAME_R_6
1281static struct hostent * gethostname_re (
const char *host,
struct hostent *hostbuf,
char **tmphstbuf,
size_t *hstbuflen)
1286 if (*hstbuflen == 0) {
1288 *tmphstbuf = (
char *)malloc (*hstbuflen);
1292 gethostbyname_r(host,hostbuf,*tmphstbuf,*hstbuflen,&hp,&herr))
1293 && (
errno == ERANGE)) {
1296 *tmphstbuf = (
char *)realloc (*tmphstbuf,*hstbuflen);
1306#ifdef HAVE_FUNC_GETHOSTBYNAME_R_5
1307static struct hostent * gethostname_re (
const char *host,
struct hostent *hostbuf,
char **tmphstbuf,
size_t *hstbuflen)
1312 if (*hstbuflen == 0) {
1314 *tmphstbuf = (
char *)malloc (*hstbuflen);
1317 while ((
NULL == ( hp =
1318 gethostbyname_r(host,hostbuf,*tmphstbuf,*hstbuflen,&herr)))
1319 && (
errno == ERANGE)) {
1322 *tmphstbuf = (
char *)realloc (*tmphstbuf,*hstbuflen);
1327#ifdef HAVE_FUNC_GETHOSTBYNAME_R_3
1328static struct hostent * gethostname_re (
const char *host,
struct hostent *hostbuf,
char **tmphstbuf,
size_t *hstbuflen)
1330 if (*hstbuflen == 0) {
1331 *hstbuflen =
sizeof(
struct hostent_data);
1332 *tmphstbuf = (
char *)malloc (*hstbuflen);
1334 if (*hstbuflen <
sizeof(
struct hostent_data)) {
1335 *hstbuflen =
sizeof(
struct hostent_data);
1336 *tmphstbuf = (
char *)realloc(*tmphstbuf, *hstbuflen);
1339 memset((
void *)(*tmphstbuf),0,*hstbuflen);
1341 if (0 != gethostbyname_r(host,hostbuf,(
struct hostent_data *)*tmphstbuf)) {
1351#if !defined(HAVE_GETHOSTBYNAME_R)
1354 if (
FG(tmp_host_buf)) {
1355 free(
FG(tmp_host_buf));
1359 FG(tmp_host_buf_len) = 0;
1361 memset(&
FG(tmp_host_info), 0,
sizeof(
struct hostent));
1363 return gethostname_re(
name, &
FG(tmp_host_info), &
FG(tmp_host_buf), &
FG(tmp_host_buf_len));
gettimeofday(bool $as_float=false)
gethostbyname(string $hostname)
strchr(string $haystack, string $needle, bool $before_needle=false)
memset(ptr, 0, type->size)
zend_ffi_ctype_name_buf buf
#define timercmp(a, b, CMP)
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
inet_ntop(AF_INET, addr, addr_str, sizeof(addr_str))
PHPAPI zend_result php_set_sock_blocking(php_socket_t socketd, bool block)
PHPAPI int php_network_connect_socket(php_socket_t sockfd, const struct sockaddr *addr, socklen_t addrlen, int asynchronous, struct timeval *timeout, zend_string **error_string, int *error_code)
PHPAPI php_stream * _php_stream_sock_open_host(const char *host, unsigned short port, int socktype, struct timeval *timeout, const char *persistent_id STREAMS_DC)
PHPAPI void _php_emit_fd_setsize_warning(int max_fd)
PHPAPI char * php_socket_strerror(long err, char *buf, size_t bufsize)
#define SET_SOCKET_BLOCKING_MODE(sock, save)
PHPAPI void php_network_freeaddresses(struct sockaddr **sal)
PHPAPI socklen_t php_sockaddr_size(php_sockaddr_storage *addr)
PHPAPI int php_poll2(php_pollfd *ufds, unsigned int nfds, int timeout)
PHPAPI void php_network_populate_name_from_sockaddr(struct sockaddr *sa, socklen_t sl, zend_string **textaddr, struct sockaddr **addr, socklen_t *addrlen)
PHPAPI struct hostent * php_network_gethostbyname(const char *name)
PHPAPI zend_result php_network_parse_network_address_with_port(const char *addr, size_t addrlen, struct sockaddr *sa, socklen_t *sl)
PHPAPI int php_network_get_sock_name(php_socket_t sock, zend_string **textaddr, struct sockaddr **addr, socklen_t *addrlen)
PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock, zend_string **textaddr, struct sockaddr **addr, socklen_t *addrlen, struct timeval *timeout, zend_string **error_string, int *error_code, int tcp_nodelay)
int php_non_blocking_flags_t
PHPAPI php_stream * _php_stream_sock_open_from_socket(php_socket_t socket, const char *persistent_id STREAMS_DC)
PHPAPI zend_string * php_socket_error_str(long err)
#define RESTORE_SOCKET_BLOCKING_MODE(sock, save)
php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short port, int socktype, int asynchronous, struct timeval *timeout, zend_string **error_string, int *error_code, const char *bindto, unsigned short bindport, long sockopts)
php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned port, int socktype, long sockopts, zend_string **error_string, int *error_code)
#define PHP_TIMEOUT_ERROR_VALUE
PHPAPI int php_network_getaddresses(const char *host, int socktype, struct sockaddr ***sal, zend_string **error_string)
PHPAPI void php_any_addr(int family, php_sockaddr_storage *addr, unsigned short port)
PHPAPI int php_network_get_peer_name(php_socket_t sock, zend_string **textaddr, struct sockaddr **addr, socklen_t *addrlen)
php_json_error_code error_code
#define PHP_SAFE_FD_ISSET(fd, set)
struct _php_netstream_data_t php_netstream_data_t
#define STREAM_SOCKOP_IPV6_V6ONLY
const php_stream_ops php_stream_generic_socket_ops
#define PHP_SAFE_FD_SET(fd, set)
#define STREAM_SOCKOP_IPV6_V6ONLY_ENABLED
#define STREAM_SOCKOP_TCP_NODELAY
struct _php_pollfd php_pollfd
#define STREAM_SOCKOP_SO_BROADCAST
#define php_socket_errno()
#define PHP_SAFE_MAX_FD(m, n)
#define STREAM_SOCKOP_SO_REUSEPORT
#define php_stream_xport_create(name, namelen, options, flags, persistent_id, timeout, context, estr, ecode)
#define STREAM_XPORT_CONNECT
#define STREAM_XPORT_CLIENT
struct _php_stream php_stream
#define php_stream_alloc_rel(ops, thisptr, persistent, mode)
#define PHP_STREAM_FLAG_AVOID_BLOCKING
const IP_BIND_ADDRESS_NO_PORT
PHP_WINUTIL_API char * php_win32_error_to_msg(HRESULT error)
PHP_WINUTIL_API void php_win32_error_msg_free(char *msg)
#define estrndup(s, length)
#define pefree(ptr, persistent)
#define pemalloc(size, persistent)
#define safe_emalloc(nmemb, size, offset)
strcmp(string $string1, string $string2)
zend_string_release_ex(func->internal_function.function_name, 0)
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
struct _zend_string zend_string
ZEND_RESULT_CODE zend_result