summaryrefslogtreecommitdiff
path: root/main/network.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/network.c')
-rw-r--r--main/network.c122
1 files changed, 116 insertions, 6 deletions
diff --git a/main/network.c b/main/network.c
index c08194bcd6..aedff7e207 100644
--- a/main/network.c
+++ b/main/network.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 7 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2015 The PHP Group |
+ | Copyright (c) 1997-2016 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -245,16 +245,15 @@ PHPAPI int php_network_getaddresses(const char *host, int socktype, struct socka
freeaddrinfo(res);
#else
if (!inet_aton(host, &in)) {
- /* XXX NOT THREAD SAFE (is safe under win32) */
if(strlen(host) > MAXFQDNLEN) {
host_info = NULL;
errno = E2BIG;
} else {
- host_info = gethostbyname(host);
+ host_info = php_network_gethostbyname(host);
}
if (host_info == NULL) {
if (error_string) {
- error_string = strpprintf(0, "php_network_getaddresses: gethostbyname failed. errno=%d", errno);
+ *error_string = strpprintf(0, "php_network_getaddresses: gethostbyname failed. errno=%d", errno);
php_error_docref(NULL, E_WARNING, "%s", ZSTR_VAL(*error_string));
} else {
php_error_docref(NULL, E_WARNING, "php_network_getaddresses: gethostbyname failed");
@@ -472,6 +471,12 @@ php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned po
#ifdef SO_REUSEADDR
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&sockoptval, sizeof(sockoptval));
#endif
+#ifdef IPV6_V6ONLY
+ if (sockopts & STREAM_SOCKOP_IPV6_V6ONLY) {
+ int ipv6_val = !!(sockopts & STREAM_SOCKOP_IPV6_V6ONLY_ENABLED);
+ setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6_val, sizeof(sockoptval));
+ }
+#endif
#ifdef SO_REUSEPORT
if (sockopts & STREAM_SOCKOP_SO_REUSEPORT) {
setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char*)&sockoptval, sizeof(sockoptval));
@@ -482,6 +487,11 @@ php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned po
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&sockoptval, sizeof(sockoptval));
}
#endif
+#ifdef TCP_NODELAY
+ if (sockopts & STREAM_SOCKOP_TCP_NODELAY) {
+ setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&sockoptval, sizeof(sockoptval));
+ }
+#endif
n = bind(sock, sa, socklen);
@@ -721,7 +731,8 @@ PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
socklen_t *addrlen,
struct timeval *timeout,
zend_string **error_string,
- int *error_code
+ int *error_code,
+ int tcp_nodelay
)
{
php_socket_t clisock = -1;
@@ -745,6 +756,11 @@ PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
textaddr,
addr, addrlen
);
+ if (tcp_nodelay) {
+#ifdef TCP_NODELAY
+ setsockopt(clisock, IPPROTO_TCP, TCP_NODELAY, (char*)&tcp_nodelay, sizeof(tcp_nodelay));
+#endif
+ }
} else {
error = php_socket_errno();
}
@@ -762,7 +778,6 @@ PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
/* }}} */
-
/* Connect to a remote host using an interruptible connect with optional timeout.
* Optionally, the connect can be made asynchronously, which will implicitly
* enable non-blocking mode on the socket.
@@ -897,6 +912,15 @@ skip_bind:
}
}
#endif
+
+#ifdef TCP_NODELAY
+ {
+ int val = 1;
+ if (sockopts & STREAM_SOCKOP_TCP_NODELAY) {
+ setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(val));
+ }
+ }
+#endif
n = php_network_connect_socket(sock, sa, socklen, asynchronous,
timeout ? &working_timeout : NULL,
error_string, error_code);
@@ -1251,9 +1275,95 @@ PHPAPI int php_poll2(php_pollfd *ufds, unsigned int nfds, int timeout)
}
return n;
}
+#endif
+
+#if defined(HAVE_GETHOSTBYNAME_R)
+#ifdef HAVE_FUNC_GETHOSTBYNAME_R_6
+struct hostent * gethostname_re (const char *host,struct hostent *hostbuf,char **tmphstbuf,size_t *hstbuflen)
+{
+ struct hostent *hp;
+ int herr,res;
+
+ if (*hstbuflen == 0) {
+ *hstbuflen = 1024;
+ *tmphstbuf = (char *)malloc (*hstbuflen);
+ }
+
+ while (( res =
+ gethostbyname_r(host,hostbuf,*tmphstbuf,*hstbuflen,&hp,&herr))
+ && (errno == ERANGE)) {
+ /* Enlarge the buffer. */
+ *hstbuflen *= 2;
+ *tmphstbuf = (char *)realloc (*tmphstbuf,*hstbuflen);
+ }
+
+ if (res != SUCCESS) {
+ return NULL;
+ }
+
+ return hp;
+}
+#endif
+#ifdef HAVE_FUNC_GETHOSTBYNAME_R_5
+struct hostent * gethostname_re (const char *host,struct hostent *hostbuf,char **tmphstbuf,size_t *hstbuflen)
+{
+ struct hostent *hp;
+ int herr;
+
+ if (*hstbuflen == 0) {
+ *hstbuflen = 1024;
+ *tmphstbuf = (char *)malloc (*hstbuflen);
+ }
+ while ((NULL == ( hp =
+ gethostbyname_r(host,hostbuf,*tmphstbuf,*hstbuflen,&herr)))
+ && (errno == ERANGE)) {
+ /* Enlarge the buffer. */
+ *hstbuflen *= 2;
+ *tmphstbuf = (char *)realloc (*tmphstbuf,*hstbuflen);
+ }
+ return hp;
+}
#endif
+#ifdef HAVE_FUNC_GETHOSTBYNAME_R_3
+struct hostent * gethostname_re (const char *host,struct hostent *hostbuf,char **tmphstbuf,size_t *hstbuflen)
+{
+ if (*hstbuflen == 0) {
+ *hstbuflen = sizeof(struct hostent_data);
+ *tmphstbuf = (char *)malloc (*hstbuflen);
+ } else {
+ if (*hstbuflen < sizeof(struct hostent_data)) {
+ *hstbuflen = sizeof(struct hostent_data);
+ *tmphstbuf = (char *)realloc(*tmphstbuf, *hstbuflen);
+ }
+ }
+ memset((void *)(*tmphstbuf),0,*hstbuflen);
+
+ if (SUCCESS != gethostbyname_r(host,hostbuf,(struct hostent_data *)*tmphstbuf)) {
+ return NULL;
+ }
+ return hostbuf;
+}
+#endif
+#endif
+
+PHPAPI struct hostent* php_network_gethostbyname(char *name) {
+#if !defined(HAVE_GETHOSTBYNAME_R)
+ return gethostbyname(name);
+#else
+ if (FG(tmp_host_buf)) {
+ free(FG(tmp_host_buf));
+ }
+
+ FG(tmp_host_buf) = NULL;
+ FG(tmp_host_buf_len) = 0;
+
+ memset(&FG(tmp_host_info), 0, sizeof(struct hostent));
+
+ return gethostname_re(name, &FG(tmp_host_info), &FG(tmp_host_buf), &FG(tmp_host_buf_len));
+#endif
+}
/*
* Local variables: