summaryrefslogtreecommitdiff
path: root/main/network.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/network.c')
-rw-r--r--main/network.c195
1 files changed, 124 insertions, 71 deletions
diff --git a/main/network.c b/main/network.c
index 636afc62b0..e4c99ec064 100644
--- a/main/network.c
+++ b/main/network.c
@@ -1,6 +1,6 @@
/*
+----------------------------------------------------------------------+
- | PHP Version 5 |
+ | PHP Version 7 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2015 The PHP Group |
+----------------------------------------------------------------------+
@@ -166,7 +166,7 @@ PHPAPI void php_network_freeaddresses(struct sockaddr **sal)
/* {{{ php_network_getaddresses
* Returns number of addresses, 0 for none/error
*/
-PHPAPI int php_network_getaddresses(const char *host, int socktype, struct sockaddr ***sal, char **error_string TSRMLS_DC)
+PHPAPI int php_network_getaddresses(const char *host, int socktype, struct sockaddr ***sal, zend_string **error_string)
{
struct sockaddr **sap;
int n;
@@ -212,18 +212,18 @@ PHPAPI int php_network_getaddresses(const char *host, int socktype, struct socka
if ((n = getaddrinfo(host, NULL, &hints, &res))) {
if (error_string) {
- spprintf(error_string, 0, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n));
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", *error_string);
+ *error_string = strpprintf(0, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n));
+ php_error_docref(NULL, E_WARNING, "%s", (*error_string)->val);
} else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n));
+ php_error_docref(NULL, E_WARNING, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n));
}
return 0;
} else if (res == NULL) {
if (error_string) {
- spprintf(error_string, 0, "php_network_getaddresses: getaddrinfo failed (null result pointer) errno=%d", errno);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", *error_string);
+ *error_string = strpprintf(0, "php_network_getaddresses: getaddrinfo failed (null result pointer) errno=%d", errno);
+ php_error_docref(NULL, E_WARNING, "%s", (*error_string)->val);
} else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: getaddrinfo failed (null result pointer)");
+ php_error_docref(NULL, E_WARNING, "php_network_getaddresses: getaddrinfo failed (null result pointer)");
}
return 0;
}
@@ -254,10 +254,10 @@ PHPAPI int php_network_getaddresses(const char *host, int socktype, struct socka
}
if (host_info == NULL) {
if (error_string) {
- spprintf(error_string, 0, "php_network_getaddresses: gethostbyname failed. errno=%d", errno);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", *error_string);
+ error_string = strpprintf(0, "php_network_getaddresses: gethostbyname failed. errno=%d", errno);
+ php_error_docref(NULL, E_WARNING, "%s", (*error_string)->val);
} else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: gethostbyname failed");
+ php_error_docref(NULL, E_WARNING, "php_network_getaddresses: gethostbyname failed");
}
return 0;
}
@@ -310,7 +310,7 @@ PHPAPI int php_network_connect_socket(php_socket_t sockfd,
socklen_t addrlen,
int asynchronous,
struct timeval *timeout,
- char **error_string,
+ zend_string **error_string,
int *error_code)
{
#if HAVE_NON_BLOCKING_CONNECT
@@ -331,7 +331,7 @@ PHPAPI int php_network_connect_socket(php_socket_t sockfd,
if (error != EINPROGRESS) {
if (error_string) {
- *error_string = php_socket_strerror(error, NULL, 0);
+ *error_string = php_socket_error_str(error);
}
return -1;
@@ -387,13 +387,13 @@ ok:
if (error) {
ret = -1;
if (error_string) {
- *error_string = php_socket_strerror(error, NULL, 0);
+ *error_string = php_socket_error_str(error);
}
}
return ret;
#else
if (asynchronous) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Asynchronous connect() not supported on this platform");
+ php_error_docref(NULL, E_WARNING, "Asynchronous connect() not supported on this platform");
}
return (connect(sockfd, addr, addrlen) == 0) ? 0 : -1;
#endif
@@ -421,15 +421,16 @@ static inline void sub_times(struct timeval a, struct timeval b, struct timeval
* */
/* {{{ php_network_bind_socket_to_local_addr */
php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned port,
- int socktype, char **error_string, int *error_code
- TSRMLS_DC)
+ int socktype, long sockopts, zend_string **error_string, int *error_code
+ )
{
int num_addrs, n, err = 0;
php_socket_t sock;
struct sockaddr **sal, **psal, *sa;
socklen_t socklen;
+ int sockoptval = 1;
- num_addrs = php_network_getaddresses(host, socktype, &psal, error_string TSRMLS_CC);
+ num_addrs = php_network_getaddresses(host, socktype, &psal, error_string);
if (num_addrs == 0) {
/* could not resolve address(es) */
@@ -469,9 +470,16 @@ php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned po
/* attempt to bind */
#ifdef SO_REUSEADDR
- {
- int val = 1;
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val));
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&sockoptval, sizeof(sockoptval));
+#endif
+#ifdef SO_REUSEPORT
+ if (sockopts & STREAM_SOCKOP_SO_REUSEPORT) {
+ setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char*)&sockoptval, sizeof(sockoptval));
+ }
+#endif
+#ifdef SO_BROADCAST
+ if (sockopts & STREAM_SOCKOP_SO_BROADCAST) {
+ setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&sockoptval, sizeof(sockoptval));
}
#endif
@@ -492,7 +500,7 @@ php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned po
*error_code = err;
}
if (error_string) {
- *error_string = php_socket_strerror(err, NULL, 0);
+ *error_string = php_socket_error_str(err);
}
bound:
@@ -504,7 +512,7 @@ bound:
}
/* }}} */
-PHPAPI int php_network_parse_network_address_with_port(const char *addr, long addrlen, struct sockaddr *sa, socklen_t *sl TSRMLS_DC)
+PHPAPI int php_network_parse_network_address_with_port(const char *addr, zend_long addrlen, struct sockaddr *sa, socklen_t *sl)
{
char *colon;
char *tmp;
@@ -513,7 +521,7 @@ PHPAPI int php_network_parse_network_address_with_port(const char *addr, long ad
struct sockaddr_in *in4 = (struct sockaddr_in*)sa;
struct sockaddr **psal;
int n;
- char *errstr = NULL;
+ zend_string *errstr = NULL;
#if HAVE_IPV6
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)sa;
#endif
@@ -555,12 +563,12 @@ PHPAPI int php_network_parse_network_address_with_port(const char *addr, long ad
}
/* looks like we'll need to resolve it */
- n = php_network_getaddresses(tmp, SOCK_DGRAM, &psal, &errstr TSRMLS_CC);
+ n = php_network_getaddresses(tmp, SOCK_DGRAM, &psal, &errstr);
if (n == 0) {
if (errstr) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to resolve `%s': %s", tmp, errstr);
- STR_FREE(errstr);
+ php_error_docref(NULL, E_WARNING, "Failed to resolve `%s': %s", tmp, errstr->val);
+ zend_string_release(errstr);
}
goto out;
}
@@ -586,7 +594,7 @@ PHPAPI int php_network_parse_network_address_with_port(const char *addr, long ad
php_network_freeaddresses(psal);
out:
- STR_FREE(tmp);
+ efree(tmp);
return ret;
}
@@ -595,11 +603,11 @@ PHPAPI void php_network_populate_name_from_sockaddr(
/* input address */
struct sockaddr *sa, socklen_t sl,
/* output readable address */
- char **textaddr, long *textaddrlen,
+ zend_string **textaddr,
/* output address */
struct sockaddr **addr,
socklen_t *addrlen
- TSRMLS_DC)
+ )
{
if (addr) {
*addr = emalloc(sl);
@@ -618,7 +626,7 @@ PHPAPI void php_network_populate_name_from_sockaddr(
/* generally not thread safe, but it *is* thread safe under win32 */
buf = inet_ntoa(((struct sockaddr_in*)sa)->sin_addr);
if (buf) {
- *textaddrlen = spprintf(textaddr, 0, "%s:%d",
+ *textaddr = strpprintf(0, "%s:%d",
buf, ntohs(((struct sockaddr_in*)sa)->sin_port));
}
@@ -628,7 +636,7 @@ PHPAPI void php_network_populate_name_from_sockaddr(
case AF_INET6:
buf = (char*)inet_ntop(sa->sa_family, &((struct sockaddr_in6*)sa)->sin6_addr, (char *)&abuf, sizeof(abuf));
if (buf) {
- *textaddrlen = spprintf(textaddr, 0, "%s:%d",
+ *textaddr = strpprintf(0, "%s:%d",
buf, ntohs(((struct sockaddr_in6*)sa)->sin6_port));
}
@@ -642,13 +650,10 @@ PHPAPI void php_network_populate_name_from_sockaddr(
if (ua->sun_path[0] == '\0') {
/* abstract name */
int len = strlen(ua->sun_path + 1) + 1;
- *textaddrlen = len;
- *textaddr = emalloc(len + 1);
- memcpy(*textaddr, ua->sun_path, len);
- (*textaddr)[len] = '\0';
+ *textaddr = zend_string_init((char*)ua->sun_path, len, 0);
} else {
- *textaddrlen = strlen(ua->sun_path);
- *textaddr = estrndup(ua->sun_path, *textaddrlen);
+ int len = strlen(ua->sun_path);
+ *textaddr = zend_string_init((char*)ua->sun_path, len, 0);
}
}
break;
@@ -660,10 +665,10 @@ PHPAPI void php_network_populate_name_from_sockaddr(
}
PHPAPI int php_network_get_peer_name(php_socket_t sock,
- char **textaddr, long *textaddrlen,
+ zend_string **textaddr,
struct sockaddr **addr,
socklen_t *addrlen
- TSRMLS_DC)
+ )
{
php_sockaddr_storage sa;
socklen_t sl = sizeof(sa);
@@ -671,19 +676,19 @@ PHPAPI int php_network_get_peer_name(php_socket_t sock,
if (getpeername(sock, (struct sockaddr*)&sa, &sl) == 0) {
php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
- textaddr, textaddrlen,
+ textaddr,
addr, addrlen
- TSRMLS_CC);
+ );
return 0;
}
return -1;
}
PHPAPI int php_network_get_sock_name(php_socket_t sock,
- char **textaddr, long *textaddrlen,
+ zend_string **textaddr,
struct sockaddr **addr,
socklen_t *addrlen
- TSRMLS_DC)
+ )
{
php_sockaddr_storage sa;
socklen_t sl = sizeof(sa);
@@ -691,9 +696,9 @@ PHPAPI int php_network_get_sock_name(php_socket_t sock,
if (getsockname(sock, (struct sockaddr*)&sa, &sl) == 0) {
php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
- textaddr, textaddrlen,
+ textaddr,
addr, addrlen
- TSRMLS_CC);
+ );
return 0;
}
return -1;
@@ -705,19 +710,19 @@ PHPAPI int php_network_get_sock_name(php_socket_t sock,
* using an optional timeout.
* Returns the peer address in addr/addrlen (it will emalloc
* these, so be sure to efree the result).
- * If you specify textaddr/textaddrlen, a text-printable
+ * If you specify textaddr, a text-printable
* version of the address will be emalloc'd and returned.
* */
/* {{{ php_network_accept_incoming */
PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
- char **textaddr, long *textaddrlen,
+ zend_string **textaddr,
struct sockaddr **addr,
socklen_t *addrlen,
struct timeval *timeout,
- char **error_string,
+ zend_string **error_string,
int *error_code
- TSRMLS_DC)
+ )
{
php_socket_t clisock = -1;
int error = 0, n;
@@ -737,9 +742,9 @@ PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
if (clisock != SOCK_ERR) {
php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
- textaddr, textaddrlen,
+ textaddr,
addr, addrlen
- TSRMLS_CC);
+ );
} else {
error = php_socket_errno();
}
@@ -749,7 +754,7 @@ PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
*error_code = error;
}
if (error_string) {
- *error_string = php_socket_strerror(error, NULL, 0);
+ *error_string = php_socket_error_str(error);
}
return clisock;
@@ -766,9 +771,9 @@ PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
/* {{{ php_network_connect_socket_to_host */
php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short port,
- int socktype, int asynchronous, struct timeval *timeout, char **error_string,
- int *error_code, char *bindto, unsigned short bindport
- TSRMLS_DC)
+ int socktype, int asynchronous, struct timeval *timeout, zend_string **error_string,
+ int *error_code, char *bindto, unsigned short bindport, long sockopts
+ )
{
int num_addrs, n, fatal = 0;
php_socket_t sock;
@@ -779,7 +784,7 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short
struct timeval limit_time, time_now;
#endif
- num_addrs = php_network_getaddresses(host, socktype, &psal, error_string TSRMLS_CC);
+ num_addrs = php_network_getaddresses(host, socktype, &psal, error_string);
if (num_addrs == 0) {
/* could not resolve address(es) */
@@ -849,7 +854,7 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short
in4->sin_family = sa->sa_family;
in4->sin_port = htons(bindport);
if (!inet_aton(bindto, &in4->sin_addr)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid IP Address: %s", bindto);
+ php_error_docref(NULL, E_WARNING, "Invalid IP Address: %s", bindto);
goto skip_bind;
}
memset(&(in4->sin_zero), 0, sizeof(in4->sin_zero));
@@ -864,13 +869,14 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short
in6->sin6_family = sa->sa_family;
in6->sin6_port = htons(bindport);
if (inet_pton(AF_INET6, bindto, &in6->sin6_addr) < 1) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid IP Address: %s", bindto);
+ php_error_docref(NULL, E_WARNING, "Invalid IP Address: %s", bindto);
goto skip_bind;
}
}
#endif
+
if (!local_address || bind(sock, local_address, local_address_len)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to bind to '%s:%d', system said: %s", bindto, bindport, strerror(errno));
+ php_error_docref(NULL, E_WARNING, "failed to bind to '%s:%d', system said: %s", bindto, bindport, strerror(errno));
}
skip_bind:
if (local_address) {
@@ -879,10 +885,18 @@ skip_bind:
}
/* free error string received during previous iteration (if any) */
if (error_string && *error_string) {
- efree(*error_string);
+ zend_string_release(*error_string);
*error_string = NULL;
}
+#ifdef SO_BROADCAST
+ {
+ int val = 1;
+ if (sockopts & STREAM_SOCKOP_SO_BROADCAST) {
+ setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&val, sizeof(val));
+ }
+ }
+#endif
n = php_network_connect_socket(sock, sa, socklen, asynchronous,
timeout ? &working_timeout : NULL,
error_string, error_code);
@@ -1034,8 +1048,46 @@ PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize)
}
/* }}} */
+/* {{{ php_socket_error_str */
+PHPAPI zend_string *php_socket_error_str(long err)
+{
+#ifndef PHP_WIN32
+ char *errstr;
+
+ errstr = strerror(err);
+ return zend_string_init(errstr, strlen(errstr), 0);
+#else
+ zend_string *ret;
+ char *sysbuf;
+ int free_it = 1;
+
+ if (!FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ err,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR)&sysbuf,
+ 0,
+ NULL)) {
+ free_it = 0;
+ sysbuf = "Unknown Error";
+ }
+
+ ret = zend_string_init(sysbuf, strlen(sysbuf), 0);
+
+ if (free_it) {
+ LocalFree(sysbuf);
+ }
+
+ return ret;
+#endif
+}
+/* }}} */
+
/* deprecated */
-PHPAPI php_stream *_php_stream_sock_open_from_socket(php_socket_t socket, const char *persistent_id STREAMS_DC TSRMLS_DC)
+PHPAPI php_stream *_php_stream_sock_open_from_socket(php_socket_t socket, const char *persistent_id STREAMS_DC)
{
php_stream *stream;
php_netstream_data_t *sock;
@@ -1060,10 +1112,10 @@ PHPAPI php_stream *_php_stream_sock_open_from_socket(php_socket_t socket, const
}
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 TSRMLS_DC)
+ int socktype, struct timeval *timeout, const char *persistent_id STREAMS_DC)
{
char *res;
- long reslen;
+ zend_long reslen;
php_stream *stream;
reslen = spprintf(&res, 0, "tcp://%s:%d", host, port);
@@ -1076,20 +1128,22 @@ PHPAPI php_stream *_php_stream_sock_open_host(const char *host, unsigned short p
return stream;
}
-PHPAPI int php_set_sock_blocking(int socketd, int block TSRMLS_DC)
+PHPAPI int php_set_sock_blocking(php_socket_t socketd, int block)
{
int ret = SUCCESS;
- int flags;
- int myflag = 0;
#ifdef PHP_WIN32
+ u_long flags;
+
/* with ioctlsocket, a non-zero sets nonblocking, a zero sets blocking */
flags = !block;
if (ioctlsocket(socketd, FIONBIO, &flags) == SOCKET_ERROR) {
ret = FAILURE;
}
#else
- flags = fcntl(socketd, F_GETFL);
+ int myflag = 0;
+ int flags = fcntl(socketd, F_GETFL);
+
#ifdef O_NONBLOCK
myflag = O_NONBLOCK; /* POSIX version */
#elif defined(O_NDELAY)
@@ -1109,10 +1163,9 @@ PHPAPI int php_set_sock_blocking(int socketd, int block TSRMLS_DC)
PHPAPI void _php_emit_fd_setsize_warning(int max_fd)
{
- TSRMLS_FETCH();
#ifdef PHP_WIN32
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ php_error_docref(NULL, E_WARNING,
"PHP needs to be recompiled with a larger value of FD_SETSIZE.\n"
"If this binary is from an official www.php.net package, file a bug report\n"
"at http://bugs.php.net, including the following information:\n"
@@ -1122,7 +1175,7 @@ PHPAPI void _php_emit_fd_setsize_warning(int max_fd)
"one time, in order to avoid seeing this error again at a later date.",
FD_SETSIZE, max_fd, (max_fd + 128) & ~127);
#else
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ php_error_docref(NULL, E_WARNING,
"You MUST recompile PHP with a larger value of FD_SETSIZE.\n"
"It is set to %d, but you have descriptors numbered at least as high as %d.\n"
" --enable-fd-setsize=%d is recommended, but you may want to set it\n"