aboutsummaryrefslogtreecommitdiff
path: root/contrib/apr/network_io/unix
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2013-07-28 06:02:40 +0000
committerPeter Wemm <peter@FreeBSD.org>2013-07-28 06:02:40 +0000
commit4705e3668dd7eb98b83cf4c6dc952e4be2709bba (patch)
tree6a96e078c28ea05d418b4e2722bc03b0b930a78b /contrib/apr/network_io/unix
parent363a2c3c1360b816703a78e9d05ae59357f07136 (diff)
parentd08b300705ff687948b1a2b89543e3a452e90c32 (diff)
downloadsrc-4705e3668dd7eb98b83cf4c6dc952e4be2709bba.tar.gz
src-4705e3668dd7eb98b83cf4c6dc952e4be2709bba.zip
Update subversion-1.8.0 -> 1.8.1. Update supporting
components: apr-1.4.6 -> 1.4.8 and apr-util-1.4.1 -> 1.5.2. This is a post point-zero bug-fix / fix-sharp-edges release, including some workarounds for UTF-8 for people who haven't yet turned on WITH_ICONV.
Notes
Notes: svn path=/head/; revision=253734
Diffstat (limited to 'contrib/apr/network_io/unix')
-rw-r--r--contrib/apr/network_io/unix/multicast.c21
-rw-r--r--contrib/apr/network_io/unix/sendrecv.c14
-rw-r--r--contrib/apr/network_io/unix/sockaddr.c44
-rw-r--r--contrib/apr/network_io/unix/sockopt.c29
4 files changed, 84 insertions, 24 deletions
diff --git a/contrib/apr/network_io/unix/multicast.c b/contrib/apr/network_io/unix/multicast.c
index 67ab24574038..3767bfdd15c1 100644
--- a/contrib/apr/network_io/unix/multicast.c
+++ b/contrib/apr/network_io/unix/multicast.c
@@ -193,36 +193,39 @@ static apr_status_t do_mcast(int type, apr_socket_t *sock,
return rv;
}
+/* Set the IP_MULTICAST_TTL or IP_MULTICAST_LOOP option, or IPv6
+ * equivalents, for the socket, to the given value. Note that this
+ * function *only works* for those particular option types. */
static apr_status_t do_mcast_opt(int type, apr_socket_t *sock,
apr_byte_t value)
{
apr_status_t rv = APR_SUCCESS;
if (sock_is_ipv4(sock)) {
+ /* For the IP_MULTICAST_* options, this must be a (char *)
+ * pointer. */
if (setsockopt(sock->socketdes, IPPROTO_IP, type,
(const void *) &value, sizeof(value)) == -1) {
rv = errno;
}
}
#if APR_HAVE_IPV6
- else if (sock_is_ipv6(sock) && type == IP_MULTICAST_LOOP) {
- unsigned int loopopt = value;
- type = IPV6_MULTICAST_LOOP;
- if (setsockopt(sock->socketdes, IPPROTO_IPV6, type,
- (const void *) &loopopt, sizeof(loopopt)) == -1) {
- rv = errno;
- }
- }
else if (sock_is_ipv6(sock)) {
+ /* For the IPV6_* options, an (int *) pointer must be used. */
+ int ivalue = value;
+
if (type == IP_MULTICAST_TTL) {
type = IPV6_MULTICAST_HOPS;
}
+ else if (type == IP_MULTICAST_LOOP) {
+ type = IPV6_MULTICAST_LOOP;
+ }
else {
return APR_ENOTIMPL;
}
if (setsockopt(sock->socketdes, IPPROTO_IPV6, type,
- &value, sizeof(value)) == -1) {
+ (const void *) &ivalue, sizeof(ivalue)) == -1) {
rv = errno;
}
}
diff --git a/contrib/apr/network_io/unix/sendrecv.c b/contrib/apr/network_io/unix/sendrecv.c
index c133a26d9c7b..6b14643cd58b 100644
--- a/contrib/apr/network_io/unix/sendrecv.c
+++ b/contrib/apr/network_io/unix/sendrecv.c
@@ -174,7 +174,14 @@ apr_status_t apr_socket_recvfrom(apr_sockaddr_t *from, apr_socket_t *sock,
return errno;
}
- apr_sockaddr_vars_set(from, from->sa.sin.sin_family, ntohs(from->sa.sin.sin_port));
+ /*
+ * Check if we have a valid address. recvfrom() with MSG_PEEK may return
+ * success without filling in the address.
+ */
+ if (from->salen > APR_OFFSETOF(struct sockaddr_in, sin_port)) {
+ apr_sockaddr_vars_set(from, from->sa.sin.sin_family,
+ ntohs(from->sa.sin.sin_port));
+ }
(*len) = rv;
if (rv == 0 && sock->type == SOCK_STREAM) {
@@ -245,7 +252,7 @@ do_select:
/* Define a structure to pass in when we have a NULL header value */
static apr_hdtr_t no_hdtr;
-#if defined(__linux__) && defined(HAVE_WRITEV)
+#if (defined(__linux__) || defined(__GNU__)) && defined(HAVE_WRITEV)
apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file,
apr_hdtr_t *hdtr, apr_off_t *offset,
@@ -285,9 +292,6 @@ apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file,
hdtr = &no_hdtr;
}
- /* Ignore flags for now. */
- flags = 0;
-
if (hdtr->numheaders > 0) {
apr_size_t hdrbytes;
diff --git a/contrib/apr/network_io/unix/sockaddr.c b/contrib/apr/network_io/unix/sockaddr.c
index ed4c474dc63d..9253a27461fb 100644
--- a/contrib/apr/network_io/unix/sockaddr.c
+++ b/contrib/apr/network_io/unix/sockaddr.c
@@ -356,9 +356,27 @@ static apr_status_t call_resolver(apr_sockaddr_t **sa,
}
error = getaddrinfo(hostname, servname, &hints, &ai_list);
#ifdef HAVE_GAI_ADDRCONFIG
- if (error == EAI_BADFLAGS && family == APR_UNSPEC) {
- /* Retry with no flags if AI_ADDRCONFIG was rejected. */
- hints.ai_flags = 0;
+ /*
+ * Using AI_ADDRCONFIG involves some unfortunate guesswork because it
+ * does not consider loopback addresses when trying to determine if
+ * IPv4 or IPv6 is configured on a system (see RFC 3493).
+ * This is a problem if one actually wants to listen on or connect to
+ * the loopback address of a protocol family that is not otherwise
+ * configured on the system. See PR 52709.
+ * To work around some of the problems, retry without AI_ADDRCONFIG
+ * in case of EAI_ADDRFAMILY.
+ * XXX: apr_sockaddr_info_get() should really accept a flag to determine
+ * XXX: if AI_ADDRCONFIG's guesswork is wanted and if the address is
+ * XXX: to be used for listen() or connect().
+ *
+ * In case of EAI_BADFLAGS, AI_ADDRCONFIG is not supported.
+ */
+ if ((family == APR_UNSPEC) && (error == EAI_BADFLAGS
+#ifdef EAI_ADDRFAMILY
+ || error == EAI_ADDRFAMILY
+#endif
+ )) {
+ hints.ai_flags &= ~AI_ADDRCONFIG;
error = getaddrinfo(hostname, servname, &hints, &ai_list);
}
#endif
@@ -367,7 +385,7 @@ static apr_status_t call_resolver(apr_sockaddr_t **sa,
return apr_get_netos_error();
#else
if (error == EAI_SYSTEM) {
- return errno;
+ return errno ? errno : APR_EGENERAL;
}
else
{
@@ -422,6 +440,15 @@ static apr_status_t call_resolver(apr_sockaddr_t **sa,
ai = ai->ai_next;
}
freeaddrinfo(ai_list);
+
+ if (prev_sa == NULL) {
+ /*
+ * getaddrinfo returned only useless entries and *sa is still empty.
+ * This should be treated as an error.
+ */
+ return APR_EGENERAL;
+ }
+
return APR_SUCCESS;
}
@@ -555,6 +582,11 @@ static apr_status_t find_addresses(apr_sockaddr_t **sa,
++curaddr;
}
+ if (prev_sa == NULL) {
+ /* this should not happen but no result should be treated as error */
+ return APR_EGENERAL;
+ }
+
return APR_SUCCESS;
}
@@ -1010,7 +1042,7 @@ APR_DECLARE(int) apr_ipsubnet_test(apr_ipsubnet_t *ipsub, apr_sockaddr_t *sa)
/* XXX This line will segv on Win32 build with APR_HAVE_IPV6,
* but without the IPV6 drivers installed.
*/
- if (sa->sa.sin.sin_family == AF_INET) {
+ if (sa->family == AF_INET) {
if (ipsub->family == AF_INET &&
((sa->sa.sin.sin_addr.s_addr & ipsub->mask[0]) == ipsub->sub[0])) {
return 1;
@@ -1022,7 +1054,7 @@ APR_DECLARE(int) apr_ipsubnet_test(apr_ipsubnet_t *ipsub, apr_sockaddr_t *sa)
return 1;
}
}
- else {
+ else if (sa->family == AF_INET6 && ipsub->family == AF_INET6) {
apr_uint32_t *addr = (apr_uint32_t *)sa->ipaddr_ptr;
if ((addr[0] & ipsub->mask[0]) == ipsub->sub[0] &&
diff --git a/contrib/apr/network_io/unix/sockopt.c b/contrib/apr/network_io/unix/sockopt.c
index 3fc932f42f5e..7b67c2ec13a1 100644
--- a/contrib/apr/network_io/unix/sockopt.c
+++ b/contrib/apr/network_io/unix/sockopt.c
@@ -381,12 +381,33 @@ apr_status_t apr_gethostname(char *buf, apr_int32_t len, apr_pool_t *cont)
}
#if APR_HAS_SO_ACCEPTFILTER
-apr_status_t apr_socket_accept_filter(apr_socket_t *sock, char *name,
- char *args)
+apr_status_t apr_socket_accept_filter(apr_socket_t *sock, char *nonconst_name,
+ char *nonconst_args)
{
+ /* these should have been const; act like they are */
+ const char *name = nonconst_name;
+ const char *args = nonconst_args;
+
struct accept_filter_arg af;
- strncpy(af.af_name, name, 16);
- strncpy(af.af_arg, args, 256 - 16);
+ socklen_t optlen = sizeof(af);
+
+ /* FreeBSD returns an error if the filter is already set; ignore
+ * this call if we previously set it to the same value.
+ */
+ if ((getsockopt(sock->socketdes, SOL_SOCKET, SO_ACCEPTFILTER,
+ &af, &optlen)) == 0) {
+ if (!strcmp(name, af.af_name) && !strcmp(args, af.af_arg)) {
+ return APR_SUCCESS;
+ }
+ }
+
+ /* Uhh, at least in FreeBSD 9 the fields are declared as arrays of
+ * these lengths; did sizeof not work in some ancient release?
+ *
+ * FreeBSD kernel sets the last byte to a '\0'.
+ */
+ apr_cpystrn(af.af_name, name, 16);
+ apr_cpystrn(af.af_arg, args, 256 - 16);
if ((setsockopt(sock->socketdes, SOL_SOCKET, SO_ACCEPTFILTER,
&af, sizeof(af))) < 0) {