aboutsummaryrefslogtreecommitdiff
path: root/network_io/unix
diff options
context:
space:
mode:
Diffstat (limited to 'network_io/unix')
-rw-r--r--network_io/unix/sendrecv.c2
-rw-r--r--network_io/unix/sockaddr.c29
-rw-r--r--network_io/unix/socket_util.c3
-rw-r--r--network_io/unix/sockets.c15
-rw-r--r--network_io/unix/sockopt.c12
5 files changed, 58 insertions, 3 deletions
diff --git a/network_io/unix/sendrecv.c b/network_io/unix/sendrecv.c
index 6b14643cd58b..4c0e0a6fce5a 100644
--- a/network_io/unix/sendrecv.c
+++ b/network_io/unix/sendrecv.c
@@ -552,7 +552,7 @@ apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file,
/* On early versions of FreeBSD sendfile, the number of bytes to send
* must include the length of the headers. Don't look at the man page
- * for this :( Instead, look at the the logic in
+ * for this :( Instead, look at the logic in
* src/sys/kern/uipc_syscalls::sendfile().
*
* This was fixed in the middle of 4.6-STABLE
diff --git a/network_io/unix/sockaddr.c b/network_io/unix/sockaddr.c
index 9253a27461fb..0dd1a2d4518d 100644
--- a/network_io/unix/sockaddr.c
+++ b/network_io/unix/sockaddr.c
@@ -839,6 +839,35 @@ APR_DECLARE(int) apr_sockaddr_equal(const apr_sockaddr_t *addr1,
return 0; /* not equal */
}
+APR_DECLARE(int) apr_sockaddr_is_wildcard(const apr_sockaddr_t *addr)
+{
+ static const char inaddr_any[
+#if APR_HAVE_IPV6
+ sizeof(struct in6_addr)
+#else
+ sizeof(struct in_addr)
+#endif
+ ] = {0};
+
+ if (addr->ipaddr_ptr /* IP address initialized */
+ && addr->ipaddr_len <= sizeof inaddr_any) { /* else bug elsewhere? */
+ if (!memcmp(inaddr_any, addr->ipaddr_ptr, addr->ipaddr_len)) {
+ return 1;
+ }
+#if APR_HAVE_IPV6
+ if (addr->family == AF_INET6
+ && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)addr->ipaddr_ptr)) {
+ struct in_addr *v4 = (struct in_addr *)&((apr_uint32_t *)addr->ipaddr_ptr)[3];
+
+ if (!memcmp(inaddr_any, v4, sizeof *v4)) {
+ return 1;
+ }
+ }
+#endif
+ }
+ return 0;
+}
+
static apr_status_t parse_network(apr_ipsubnet_t *ipsub, const char *network)
{
/* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */
diff --git a/network_io/unix/socket_util.c b/network_io/unix/socket_util.c
index 6cd28a55c432..93fe25976adb 100644
--- a/network_io/unix/socket_util.c
+++ b/network_io/unix/socket_util.c
@@ -46,7 +46,8 @@ APR_DECLARE(apr_status_t) apr_socket_atreadeof(apr_socket_t *sock, int *atreadeo
/* Some other error -> unexpected error. */
return rv;
}
- else if (nfds == 1 && pfds[0].rtnevents == APR_POLLIN) {
+ /* Many platforms return only APR_POLLIN; OS X returns APR_POLLHUP|APR_POLLIN */
+ else if (nfds == 1 && (pfds[0].rtnevents & APR_POLLIN) == APR_POLLIN) {
apr_sockaddr_t unused;
apr_size_t len = 1;
char buf;
diff --git a/network_io/unix/sockets.c b/network_io/unix/sockets.c
index 748dd707d87e..514edb1a499a 100644
--- a/network_io/unix/sockets.c
+++ b/network_io/unix/sockets.c
@@ -207,7 +207,20 @@ apr_status_t apr_socket_accept(apr_socket_t **new, apr_socket_t *sock,
sa.salen = sizeof(sa.sa);
#ifdef HAVE_ACCEPT4
- s = accept4(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen, SOCK_CLOEXEC);
+ {
+ int flags = SOCK_CLOEXEC;
+
+#if defined(SOCK_NONBLOCK) && APR_O_NONBLOCK_INHERITED
+ /* With FreeBSD accept4() (avail in 10+), O_NONBLOCK is not inherited
+ * (unlike Linux). Mimic the accept() behavior here in a way that
+ * may help other platforms.
+ */
+ if (apr_is_option_set(sock, APR_SO_NONBLOCK) == 1) {
+ flags |= SOCK_NONBLOCK;
+ }
+#endif
+ s = accept4(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen, flags);
+ }
#else
s = accept(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen);
#endif
diff --git a/network_io/unix/sockopt.c b/network_io/unix/sockopt.c
index 7b67c2ec13a1..6ce4b911efc0 100644
--- a/network_io/unix/sockopt.c
+++ b/network_io/unix/sockopt.c
@@ -141,6 +141,18 @@ apr_status_t apr_socket_opt_set(apr_socket_t *sock,
apr_set_option(sock, APR_SO_DEBUG, on);
}
break;
+ case APR_SO_BROADCAST:
+#ifdef SO_BROADCAST
+ if (on != apr_is_option_set(sock, APR_SO_BROADCAST)) {
+ if (setsockopt(sock->socketdes, SOL_SOCKET, SO_BROADCAST, (void *)&one, sizeof(int)) == -1) {
+ return errno;
+ }
+ apr_set_option(sock, APR_SO_BROADCAST, on);
+ }
+#else
+ return APR_ENOTIMPL;
+#endif
+ break;
case APR_SO_REUSEADDR:
if (on != apr_is_option_set(sock, APR_SO_REUSEADDR)) {
if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(int)) == -1) {