diff options
Diffstat (limited to 'network_io/unix')
-rw-r--r-- | network_io/unix/sendrecv.c | 2 | ||||
-rw-r--r-- | network_io/unix/sockaddr.c | 29 | ||||
-rw-r--r-- | network_io/unix/socket_util.c | 3 | ||||
-rw-r--r-- | network_io/unix/sockets.c | 15 | ||||
-rw-r--r-- | network_io/unix/sockopt.c | 12 |
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) { |