[prev in list] [next in list] [prev in thread] [next in thread]
List: apr-dev
Subject: [PATCH] apr_sockaddr with APR_UNIX socket paths longer than sizeof(sun_path)
From: Yann Ylavic <ylavic.dev () gmail ! com>
Date: 2014-10-07 1:37:59
Message-ID: CAKQ1sVM+C2yFCwDhUo55-h-0Y1CZ5tdFkKJ9YYafD61WqN4o0g () mail ! gmail ! com
[Download RAW message or body]
Hello,
the attached patch allows the APR to handle Unix Domain Socket paths
longer than the the limit imposed by the size of struct sockaddr_un
(for systems that support it, eg. *BSD), with no API/ABI change.
To do so, new functions to manipulate the different type of addresses
and socket internals (about local/remote addresses) are implemented in
network_io/unix/sockaddr.c, and declared in each
include/arch/*/apr_arch_networkio.h, like the existing
apr_sockaddr_vars_set().
This allows to also reuse code for non-unix platforms (Windows, OS/2),
hence all network_io/*/sockets.c have been modified (aligned) to use
them where needed.
The corresponding tests have also been added to the suite.
Unfortunatly I can't test nor even compile on Windows/OS2 currently,
testers welcome (TIA).
Thanks for your feedbacks.
Regards,
Yann.
["apr-trunk-sockaddr.patch" (application/x-download)]
Index: include/apr_portable.h
===================================================================
--- include/apr_portable.h (revision 1628634)
+++ include/apr_portable.h (working copy)
@@ -386,6 +386,11 @@ APR_DECLARE(apr_status_t) apr_os_dir_put(apr_dir_t
* @param cont The socket we are converting to an apr type.
* @remark If it is a true socket, it is best to call apr_os_sock_make()
* and provide APR with more information about the socket.
+ * The given *sock MUST either point to an existing apr_socket_t or
+ * be NULL. In the former case, no action is taken by this function
+ * on the existing os socket descriptor, it is up to the caller to
+ * close it either with apr_socket_close() before the call or by using
+ * the corresponding os (native) function on the available descriptor.
*/
APR_DECLARE(apr_status_t) apr_os_sock_put(apr_socket_t **sock,
apr_os_sock_t *thesock,
Index: include/arch/win32/apr_arch_networkio.h
===================================================================
--- include/arch/win32/apr_arch_networkio.h (revision 1628634)
+++ include/arch/win32/apr_arch_networkio.h (working copy)
@@ -19,6 +19,7 @@
#include "apr_network_io.h"
#include "apr_general.h"
+#include "apr_portable.h"
#include "apr_poll.h"
typedef struct sock_userdata_t sock_userdata_t;
@@ -74,6 +75,11 @@ apr_status_t status_from_res_error(int);
const char *apr_inet_ntop(int af, const void *src, char *dst, apr_size_t size);
int apr_inet_pton(int af, const char *src, void *dst);
void apr_sockaddr_vars_set(apr_sockaddr_t *, int, apr_port_t);
+void apr_sockaddr_put(apr_sockaddr_t **addr, int family,
+ const struct sockaddr *sa, apr_socklen_t salen,
+ const char *hostname, const char *servname,
+ apr_pool_t *pool);
+void apr_socket_addr_put(apr_socket_t *sock, const apr_os_sock_info_t *info);
#define apr_is_option_set(skt, option) \
(((skt)->options & (option)) == (option))
Index: include/arch/os2/apr_arch_networkio.h
===================================================================
--- include/arch/os2/apr_arch_networkio.h (revision 1628634)
+++ include/arch/os2/apr_arch_networkio.h (working copy)
@@ -20,6 +20,7 @@
#include "apr_private.h"
#include "apr_network_io.h"
#include "apr_general.h"
+#include "apr_portable.h"
#include "apr_arch_os2calls.h"
#include "apr_poll.h"
@@ -71,6 +72,11 @@ struct apr_socket_t {
const char *apr_inet_ntop(int af, const void *src, char *dst, apr_size_t size);
int apr_inet_pton(int af, const char *src, void *dst);
void apr_sockaddr_vars_set(apr_sockaddr_t *, int, apr_port_t);
+void apr_sockaddr_put(apr_sockaddr_t **addr, int family,
+ const struct sockaddr *sa, apr_socklen_t salen,
+ const char *hostname, const char *servname,
+ apr_pool_t *pool);
+void apr_socket_addr_put(apr_socket_t *sock, const apr_os_sock_info_t *info);
#endif /* ! NETWORK_IO_H */
Index: include/arch/unix/apr_arch_networkio.h
===================================================================
--- include/arch/unix/apr_arch_networkio.h (revision 1628634)
+++ include/arch/unix/apr_arch_networkio.h (working copy)
@@ -22,6 +22,7 @@
#include "apr_network_io.h"
#include "apr_errno.h"
#include "apr_general.h"
+#include "apr_portable.h"
#include "apr_lib.h"
#ifndef WAITIO_USES_POLL
#include "apr_poll.h"
@@ -129,6 +130,11 @@ struct apr_socket_t {
const char *apr_inet_ntop(int af, const void *src, char *dst, apr_size_t size);
int apr_inet_pton(int af, const char *src, void *dst);
void apr_sockaddr_vars_set(apr_sockaddr_t *, int, apr_port_t);
+void apr_sockaddr_put(apr_sockaddr_t **addr, int family,
+ const struct sockaddr *sa, apr_socklen_t salen,
+ const char *hostname, const char *servname,
+ apr_pool_t *pool);
+void apr_socket_addr_put(apr_socket_t *sock, const apr_os_sock_info_t *info);
#define apr_is_option_set(skt, option) \
(((skt)->options & (option)) == (option))
Index: include/apr_network_io.h
===================================================================
--- include/apr_network_io.h (revision 1628634)
+++ include/apr_network_io.h (working copy)
@@ -784,6 +784,7 @@ APR_DECLARE(int) apr_sockaddr_is_wildcard(const ap
* Return the type of the socket.
* @param sock The socket to query.
* @param type The returned type (e.g., SOCK_STREAM).
+ * @return non-zero if the type cannot be determined.
*/
APR_DECLARE(apr_status_t) apr_socket_type_get(apr_socket_t *sock,
int *type);
Index: network_io/unix/sockaddr.c
===================================================================
--- network_io/unix/sockaddr.c (revision 1628634)
+++ network_io/unix/sockaddr.c (working copy)
@@ -77,39 +77,95 @@ static void *getservbyname(const char *name, const
}
#endif
-static apr_status_t get_local_addr(apr_socket_t *sock)
+static apr_status_t get_sock_addr(apr_socket_t *sock, apr_interface_e which)
{
- sock->local_addr->salen = sizeof(sock->local_addr->sa);
- if (getsockname(sock->socketdes, (struct sockaddr *)&sock->local_addr->sa,
- &sock->local_addr->salen) < 0) {
- return apr_get_netos_error();
+ int rc;
+ apr_sockaddr_t *sa;
+
+ if (which == APR_LOCAL) {
+ sa = sock->local_addr;
+ sa->salen = sizeof(sa->sa);
+ rc = getsockname(sock->socketdes,
+ (struct sockaddr *)&sa->sa,
+ &sa->salen);
}
else {
- sock->local_port_unknown = sock->local_interface_unknown = 0;
- /* XXX assumes sin_port and sin6_port at same offset */
- sock->local_addr->port = ntohs(sock->local_addr->sa.sin.sin_port);
- return APR_SUCCESS;
+ sa = sock->remote_addr;
+ sa->salen = sizeof(sa->sa);
+ rc = getpeername(sock->socketdes,
+ (struct sockaddr *)&sa->sa,
+ &sa->salen);
}
-}
-
-static apr_status_t get_remote_addr(apr_socket_t *sock)
-{
- sock->remote_addr->salen = sizeof(sock->remote_addr->sa);
- if (getpeername(sock->socketdes, (struct sockaddr *)&sock->remote_addr->sa,
- &sock->remote_addr->salen) < 0) {
+ if (rc < 0) {
return apr_get_netos_error();
}
else {
- sock->remote_addr_unknown = 0;
- /* XXX assumes sin_port and sin6_port at same offset */
- sock->remote_addr->port = ntohs(sock->remote_addr->sa.sin.sin_port);
- return APR_SUCCESS;
+ apr_port_t port = 0;
+ int family = sa->sa.sin.sin_family;
+ if (family == APR_INET) {
+ port = ntohs(sa->sa.sin.sin_port);
+ }
+#if APR_HAVE_IPV6
+ else if (family == APR_INET6) {
+ port = ntohs(sa->sa.sin6.sin6_port);
+ }
+#endif
+ else if (family == APR_UNIX) {
+#if !APR_HAVE_SOCKADDR_UN
+ return APR_ENOTIMPL;
+#else
+ /* Always NUL terminate sun_path. */
+ if (sa->salen >= sizeof(sa->sa)) {
+ apr_sockaddr_t *newsa;
+ newsa = apr_pcalloc(sock->pool,
+ APR_OFFSETOF(apr_sockaddr_t, sa) +
+ sa->salen + 1);
+ memcpy(newsa, sa, APR_OFFSETOF(apr_sockaddr_t, sa));
+ newsa->salen = sa->salen + 1;
+ if (which == APR_LOCAL) {
+ rc = getsockname(sock->socketdes,
+ (struct sockaddr *)&newsa->sa,
+ &newsa->salen);
+ if (rc < 0) {
+ return apr_get_netos_error();
+ }
+ sock->local_addr = newsa;
+ }
+ else {
+ rc = getpeername(sock->socketdes,
+ (struct sockaddr *)&newsa->sa,
+ &newsa->salen);
+ if (rc < 0) {
+ return apr_get_netos_error();
+ }
+ sock->remote_addr = newsa;
+ }
+ sa = newsa;
+ }
+ ((char*)&sa->sa)[sa->salen] = '\0';
+#endif
+ }
+ apr_sockaddr_vars_set(sa, family, port);
}
+
+ return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_sockaddr_ip_getbuf(char *buf, apr_size_t buflen,
apr_sockaddr_t *sockaddr)
{
+#if APR_HAVE_SOCKADDR_UN
+ if (sockaddr->family == APR_UNIX) {
+ char *end = apr_cpystrn(buf, sockaddr->sa.unx.sun_path, buflen);
+ if (sockaddr->sa.unx.sun_path[end - buf] == '\0') {
+ return APR_SUCCESS;
+ }
+ else {
+ return APR_ENOSPC;
+ }
+ }
+#endif
+
if (!apr_inet_ntop(sockaddr->family, sockaddr->ipaddr_ptr, buf, buflen)) {
return APR_ENOSPC;
}
@@ -142,10 +198,10 @@ void apr_sockaddr_vars_set(apr_sockaddr_t *addr, i
{
addr->family = family;
addr->sa.sin.sin_family = family;
+ addr->port = port;
if (port) {
/* XXX IPv6: assumes sin_port and sin6_port at same offset */
addr->sa.sin.sin_port = htons(port);
- addr->port = port;
}
#if AIX_SERVNAME_HACK
else {
@@ -169,35 +225,113 @@ void apr_sockaddr_vars_set(apr_sockaddr_t *addr, i
#endif
#if APR_HAVE_SOCKADDR_UN
else if (family == APR_UNIX) {
- addr->salen = sizeof(struct sockaddr_un);
- addr->addr_str_len = sizeof(addr->sa.unx.sun_path);;
+ apr_socklen_t pathlen = strlen(addr->sa.unx.sun_path);
+ addr->salen = APR_OFFSETOF(struct sockaddr_un, sun_path) + pathlen;
+ addr->addr_str_len = pathlen + 1;
addr->ipaddr_ptr = &(addr->sa.unx.sun_path);
- addr->ipaddr_len = addr->addr_str_len;
+ addr->ipaddr_len = pathlen;
+ addr->port = 0;
}
#endif
}
+void apr_sockaddr_put(apr_sockaddr_t **addr, int family,
+ const struct sockaddr *sa, apr_socklen_t salen,
+ const char *hostname, const char *servname,
+ apr_pool_t *pool)
+{
+ apr_size_t len;
+ apr_port_t port = 0;
+
+ if (salen == 0) {
+ if (family == APR_INET) {
+ salen = sizeof(struct sockaddr_in);
+ }
+#if APR_HAVE_IPV6
+ else if (family == APR_INET6) {
+ salen = sizeof(struct sockaddr_in6);
+ }
+#endif
+#if APR_HAVE_SOCKADDR_UN
+ else if (family == APR_UNIX) {
+ struct sockaddr_un *sun = (struct sockaddr_un *)sa;
+ salen = APR_OFFSETOF(struct sockaddr_un, sun_path) +
+ strlen(sun->sun_path);
+ }
+#endif
+ }
+ len = APR_OFFSETOF(apr_sockaddr_t, sa) + salen;
+#if APR_HAVE_SOCKADDR_UN
+ if (family == APR_UNIX) {
+ len++;
+ }
+#endif
+ if (len < sizeof(apr_sockaddr_t)) {
+ len = sizeof(apr_sockaddr_t);
+ }
+ *addr = apr_pcalloc(pool, len);
+ memcpy(&(*addr)->sa, sa, salen);
+ (*addr)->hostname = apr_pstrdup(pool, hostname);
+ (*addr)->servname = apr_pstrdup(pool, servname);
+ (*addr)->pool = pool;
+
+ if (family == APR_INET) {
+ port = ntohs((*addr)->sa.sin.sin_port);
+ }
+#if APR_HAVE_IPV6
+ else if (family == APR_INET6) {
+ port = ntohs((*addr)->sa.sin6.sin6_port);
+ }
+#endif
+#if APR_HAVE_SOCKADDR_UN
+ else if (family == APR_UNIX) {
+ ((char*)&(*addr)->sa)[salen] = '\0';
+ }
+#endif
+
+ apr_sockaddr_vars_set(*addr, family, port);
+}
+
+void apr_socket_addr_put(apr_socket_t *sock, const apr_os_sock_info_t *info)
+{
+ /* XXX: apr_os_sock_info_t does not not allow to specify
+ * the length of the struct sockaddr (eg. local_len for
+ * local_addr, or remote_len for remote_addr), so with
+ * APR_UNIX we asume that the sun_path is NUL terminated.
+ */
+ if (info->local) {
+ apr_sockaddr_put(&sock->local_addr, info->family,
+ info->local, 0, NULL, NULL, sock->pool);
+ sock->local_port_unknown = sock->local_interface_unknown = 0;
+ }
+ if (info->remote) {
+ apr_sockaddr_put(&sock->remote_addr, info->family,
+ info->remote, 0, NULL, NULL, sock->pool);
+ sock->remote_addr_unknown = 0;
+ }
+}
+
APR_DECLARE(apr_status_t) apr_socket_addr_get(apr_sockaddr_t **sa,
apr_interface_e which,
apr_socket_t *sock)
{
if (which == APR_LOCAL) {
if (sock->local_interface_unknown || sock->local_port_unknown) {
- apr_status_t rv = get_local_addr(sock);
-
+ apr_status_t rv = get_sock_addr(sock, which);
if (rv != APR_SUCCESS) {
return rv;
}
+ sock->local_port_unknown = sock->local_interface_unknown = 0;
}
*sa = sock->local_addr;
}
else if (which == APR_REMOTE) {
if (sock->remote_addr_unknown) {
- apr_status_t rv = get_remote_addr(sock);
-
+ apr_status_t rv = get_sock_addr(sock, which);
if (rv != APR_SUCCESS) {
return rv;
}
+ sock->remote_addr_unknown = 0;
}
*sa = sock->remote_addr;
}
@@ -625,26 +759,32 @@ APR_DECLARE(apr_status_t) apr_sockaddr_info_get(ap
if (family == APR_UNIX) {
#if APR_HAVE_SOCKADDR_UN
if (hostname) {
- *sa = apr_pcalloc(p, sizeof(apr_sockaddr_t));
+ apr_socklen_t salen, pathlen = strlen(hostname);
+ salen = APR_OFFSETOF(struct sockaddr_un, sun_path) + pathlen;
+ /* Always NUL terminate sun_path. */
+ if (salen >= sizeof((*sa)->sa)) {
+ *sa = apr_pcalloc(p, APR_OFFSETOF(apr_sockaddr_t, sa) +
+ salen + 1);
+ }
+ else {
+ *sa = apr_pcalloc(p, sizeof(apr_sockaddr_t));
+ }
(*sa)->pool = p;
- apr_cpystrn((*sa)->sa.unx.sun_path, hostname,
- sizeof((*sa)->sa.unx.sun_path));
- (*sa)->hostname = apr_pstrdup(p, hostname);
- (*sa)->family = APR_UNIX;
- (*sa)->sa.unx.sun_family = APR_UNIX;
- (*sa)->salen = sizeof(struct sockaddr_un);
- (*sa)->addr_str_len = sizeof((*sa)->sa.unx.sun_path);
+ (*sa)->salen = salen;
+ (*sa)->addr_str_len = pathlen + 1;
+ (*sa)->hostname = apr_pstrmemdup(p, hostname, pathlen);
+ (*sa)->family = (*sa)->sa.unx.sun_family = APR_UNIX;
+ memcpy((*sa)->sa.unx.sun_path, hostname, pathlen);
(*sa)->ipaddr_ptr = &((*sa)->sa.unx.sun_path);
- (*sa)->ipaddr_len = (*sa)->addr_str_len;
-
+ (*sa)->ipaddr_len = pathlen;
return APR_SUCCESS;
}
- else
+ else {
+ return APR_EINVAL;
+ }
+#else
+ return APR_ENOTIMPL;
#endif
- {
- *sa = NULL;
- return APR_ENOTIMPL;
- }
}
#if !APR_HAVE_IPV6
/* What may happen is that APR is not IPv6-enabled, but we're still
@@ -668,11 +808,17 @@ APR_DECLARE(apr_status_t) apr_sockaddr_info_copy(a
const apr_sockaddr_t *s;
for (*dst = d = NULL, s = src; s; s = s->next) {
+ apr_size_t n = sizeof(*s);
+#if APR_HAVE_SOCKADDR_UN
+ if (s->family == APR_UNIX && s->salen >= sizeof(s->sa)) {
+ n += s->salen - sizeof(s->sa) + 1;
+ }
+#endif
if (!d) {
- *dst = d = apr_pmemdup(p, s, sizeof *s);
+ *dst = d = apr_pmemdup(p, s, n);
}
else {
- d = d->next = apr_pmemdup(p, s, sizeof *s);
+ d = d->next = apr_pmemdup(p, s, n);
}
if (s->hostname) {
if (s == src || s->hostname != src->hostname) {
@@ -693,6 +839,7 @@ APR_DECLARE(apr_status_t) apr_sockaddr_info_copy(a
d->pool = p;
apr_sockaddr_vars_set(d, s->family, s->port);
}
+
return APR_SUCCESS;
}
@@ -925,6 +1072,11 @@ APR_DECLARE(int) apr_sockaddr_is_wildcard(const ap
#endif
] = {0};
+#if APR_HAVE_SOCKADDR_UN
+ if (addr->family == APR_UNIX) {
+ return 0;
+ }
+#endif
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)) {
Index: network_io/unix/sockets.c
===================================================================
--- network_io/unix/sockets.c (revision 1628634)
+++ network_io/unix/sockets.c (working copy)
@@ -26,15 +26,6 @@
#define close closesocket
#endif /* BEOS_R5 */
-#if APR_HAVE_SOCKADDR_UN
-#define GENERIC_INADDR_ANY_LEN sizeof(struct sockaddr_un)
-#else
-#define GENERIC_INADDR_ANY_LEN 16
-#endif
-
-/* big enough for IPv4, IPv6 and optionally sun_path */
-static char generic_inaddr_any[GENERIC_INADDR_ANY_LEN] = {0};
-
static apr_status_t socket_cleanup(void *sock)
{
apr_socket_t *thesocket = sock;
@@ -78,8 +69,18 @@ static void set_socket_vars(apr_socket_t *sock, in
{
sock->type = type;
sock->protocol = protocol;
- apr_sockaddr_vars_set(sock->local_addr, family, 0);
- apr_sockaddr_vars_set(sock->remote_addr, family, 0);
+ if (sock->local_addr == NULL) {
+ sock->local_addr = (apr_sockaddr_t *)apr_pcalloc(sock->pool,
+ sizeof(apr_sockaddr_t));
+ sock->local_addr->pool = sock->pool;
+ apr_sockaddr_vars_set(sock->local_addr, family, 0);
+ }
+ if (sock->remote_addr == NULL) {
+ sock->remote_addr = (apr_sockaddr_t *)apr_pcalloc(sock->pool,
+ sizeof(apr_sockaddr_t));
+ sock->remote_addr->pool = sock->pool;
+ apr_sockaddr_vars_set(sock->remote_addr, family, 0);
+ }
sock->options = 0;
#if defined(BEOS) && !defined(BEOS_BONE)
/* BeOS pre-BONE has TCP_NODELAY on by default and it can't be
@@ -93,13 +94,9 @@ static void alloc_socket(apr_socket_t **new, apr_p
{
*new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t));
(*new)->pool = p;
- (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool,
- sizeof(apr_sockaddr_t));
- (*new)->local_addr->pool = p;
- (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool,
- sizeof(apr_sockaddr_t));
- (*new)->remote_addr->pool = p;
(*new)->remote_addr_unknown = 1;
+ (*new)->local_port_unknown = (*new)->local_interface_unknown = 1;
+
#ifndef WAITIO_USES_POLL
/* Create a pollset with room for one descriptor. */
/* ### check return codes */
@@ -130,11 +127,13 @@ apr_status_t apr_socket_create(apr_socket_t **new,
family = APR_INET;
#endif
}
+ else if (family == APR_UNIX) {
#if APR_HAVE_SOCKADDR_UN
- if (family == APR_UNIX) {
protocol = 0;
+#else
+ return APR_ENOTIMPL;
+#endif
}
-#endif
alloc_socket(new, cont);
#ifndef BEOS_R5
@@ -170,7 +169,6 @@ apr_status_t apr_socket_create(apr_socket_t **new,
if ((*new)->socketdes < 0) {
return errno;
}
- set_socket_vars(*new, family, type, oprotocol);
#ifndef HAVE_SOCK_CLOEXEC
{
@@ -191,8 +189,11 @@ apr_status_t apr_socket_create(apr_socket_t **new,
}
#endif
+ set_socket_vars(*new, family, type, oprotocol);
+
(*new)->timeout = -1;
(*new)->inherit = 0;
+
apr_pool_cleanup_register((*new)->pool, (void *)(*new), socket_cleanup,
socket_child_cleanup);
@@ -217,17 +218,39 @@ apr_status_t apr_socket_bind(apr_socket_t *sock, a
return errno;
}
else {
- sock->local_addr = sa;
- /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
+ /* Make local address. */
+ apr_sockaddr_put(&sock->local_addr, sa->sa.sin.sin_family,
+ (const struct sockaddr*)&sa->sa, sa->salen,
+ sa->hostname, sa->servname, sock->pool);
+ sock->local_port_unknown = sock->local_interface_unknown = 0;
#if APR_HAVE_SOCKADDR_UN
if (sock->local_addr->family == APR_UNIX) {
sock->bound = 1;
- sock->local_port_unknown = 1;
+ /* Local port and interface have no meaning for UDS,
+ * pretend we know them to avoid further resolution,
+ * hence keep unknown things to 0.
+ */
}
else
#endif
- if (sock->local_addr->sa.sin.sin_port == 0) { /* no need for ntohs() when comparing w/ 0 */
- sock->local_port_unknown = 1; /* kernel got us an ephemeral port */
+ {
+ /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
+ /* no need for ntohs() when comparing w/ 0 */
+ if (sock->local_addr->sa.sin.sin_port == 0) {
+ /* kernel got us an ephemeral port */
+ sock->local_port_unknown = 1;
+ }
+ if (apr_sockaddr_is_wildcard(sock->local_addr)) {
+ /* If the interface address inside the listening socket's
+ * local_addr wasn't up-to-date, we don't know local interface
+ * of the connected socket either.
+ *
+ * If the listening socket was not bound to a specific
+ * interface, we don't know the local_addr of the connected
+ * socket.
+ */
+ sock->local_interface_unknown = 1;
+ }
}
return APR_SUCCESS;
}
@@ -277,59 +300,66 @@ apr_status_t apr_socket_accept(apr_socket_t **new,
return APR_EINTR;
}
#endif
+
alloc_socket(new, connection_context);
- /* Set up socket variables -- note that it may be possible for
- * *new to be an AF_INET socket when sock is AF_INET6 in some
- * dual-stack configurations, so ensure that the remote_/local_addr
- * structures are adjusted for the family of the accepted
- * socket: */
- set_socket_vars(*new, sa.sa.sin.sin_family, SOCK_STREAM, sock->protocol);
-
#ifndef HAVE_POLL
(*new)->connected = 1;
#endif
(*new)->timeout = -1;
- (*new)->remote_addr_unknown = 0;
-
(*new)->socketdes = s;
- /* Copy in peer's address. */
- (*new)->remote_addr->sa = sa.sa;
- (*new)->remote_addr->salen = sa.salen;
+ /* Make peer address. */
+ apr_sockaddr_put(&(*new)->remote_addr, sa.sa.sin.sin_family,
+ (const struct sockaddr*)&sa.sa, sa.salen,
+ NULL, NULL, (*new)->pool);
+ (*new)->remote_addr_unknown = 0;
- *(*new)->local_addr = *sock->local_addr;
-
- /* The above assignment just overwrote the pool entry. Setting the local_addr
- pool for the accepted socket back to what it should be. Otherwise all
- allocations for this socket will come from a server pool that is not
- freed until the process goes down.*/
- (*new)->local_addr->pool = connection_context;
-
- /* fix up any pointers which are no longer valid */
- if (sock->local_addr->sa.sin.sin_family == AF_INET) {
- (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr;
- }
-#if APR_HAVE_IPV6
- else if (sock->local_addr->sa.sin.sin_family == AF_INET6) {
- (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin6.sin6_addr;
- }
-#endif
+ /* Make local address. */
+ apr_sockaddr_put(&(*new)->local_addr, sa.sa.sin.sin_family,
+ (const struct sockaddr*)&sock->local_addr->sa,
+ sock->local_addr->salen,
+ sock->local_addr->hostname,
+ sock->local_addr->servname,
+ (*new)->pool);
+ (*new)->local_port_unknown = 0;
+ (*new)->local_interface_unknown = 0;
#if APR_HAVE_SOCKADDR_UN
- else if (sock->local_addr->sa.sin.sin_family == AF_UNIX) {
- *(*new)->remote_addr = *sock->local_addr;
- (*new)->local_addr->ipaddr_ptr = &((*new)->local_addr->sa.unx.sun_path);
- (*new)->remote_addr->ipaddr_ptr = &((*new)->remote_addr->sa.unx.sun_path);
+ if (sa.sa.sin.sin_family == APR_UNIX) {
+ /* Local port and interface have no meaning for UDS,
+ * pretend we know them to avoid further resolution,
+ * hence keep unknown things to 0.
+ */
}
- if (sock->local_addr->sa.sin.sin_family != AF_UNIX)
+ else
#endif
- (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port);
- if (sock->local_port_unknown) {
- /* not likely for a listening socket, but theoretically possible :) */
- (*new)->local_port_unknown = 1;
+ {
+ if ((*new)->local_addr->port == 0) {
+ /* not likely for a listening socket,
+ * but theoretically possible :) */
+ (*new)->local_port_unknown = 1;
+ }
+ if (apr_sockaddr_is_wildcard(sock->local_addr)) {
+ /* If the interface address inside the listening socket's
+ * local_addr wasn't up-to-date, we don't know local interface
+ * of the connected socket either.
+ *
+ * If the listening socket was not bound to a specific
+ * interface, we don't know the local_addr of the connected
+ * socket.
+ */
+ (*new)->local_interface_unknown = 1;
+ }
}
+ /* Set up socket variables -- note that it may be possible for
+ * *new to be an AF_INET socket when sock is AF_INET6 in some
+ * dual-stack configurations, so ensure that the remote_/local_addr
+ * structures are adjusted for the family of the accepted
+ * socket: */
+ set_socket_vars(*new, sa.sa.sin.sin_family, SOCK_STREAM, sock->protocol);
+
#if APR_TCP_NODELAY_INHERITED
if (apr_is_option_set(sock, APR_TCP_NODELAY) == 1) {
apr_set_option(*new, APR_TCP_NODELAY, 1);
@@ -341,19 +371,6 @@ apr_status_t apr_socket_accept(apr_socket_t **new,
}
#endif /* APR_O_NONBLOCK_INHERITED */
- if (sock->local_interface_unknown ||
- !memcmp(sock->local_addr->ipaddr_ptr,
- generic_inaddr_any,
- sock->local_addr->ipaddr_len)) {
- /* If the interface address inside the listening socket's local_addr wasn't
- * up-to-date, we don't know local interface of the connected socket either.
- *
- * If the listening socket was not bound to a specific interface, we
- * don't know the local_addr of the connected socket.
- */
- (*new)->local_interface_unknown = 1;
- }
-
#ifndef HAVE_ACCEPT4
{
int flags;
@@ -385,15 +402,17 @@ apr_status_t apr_socket_connect(apr_socket_t *sock
do {
rc = connect(sock->socketdes,
- (const struct sockaddr *)&sa->sa.sin,
+ (const struct sockaddr *)&sa->sa,
sa->salen);
} while (rc == -1 && errno == EINTR);
+ if (rc == -1) {
+ rc = errno;
+ }
/* we can see EINPROGRESS the first time connect is called on a non-blocking
* socket; if called again, we can see EALREADY
*/
- if ((rc == -1) && (errno == EINPROGRESS || errno == EALREADY)
- && (sock->timeout > 0)) {
+ if ((rc == EINPROGRESS || rc == EALREADY) && (sock->timeout > 0)) {
rc = apr_wait_for_io_or_timeout(NULL, sock, 0);
if (rc != APR_SUCCESS) {
return rc;
@@ -414,41 +433,56 @@ apr_status_t apr_socket_connect(apr_socket_t *sock
#endif /* SO_ERROR */
}
- if (memcmp(sa->ipaddr_ptr, generic_inaddr_any, sa->ipaddr_len)) {
+ if (0 ||
+#if APR_HAVE_SOCKADDR_UN
+ sa->sa.sin.sin_family == APR_UNIX ||
+
+#endif
+ !apr_sockaddr_is_wildcard(sa)) {
/* A real remote address was passed in. If the unspecified
* address was used, the actual remote addr will have to be
* determined using getpeername() if required. */
sock->remote_addr_unknown = 0;
- /* Copy the address structure details in. */
- sock->remote_addr->sa = sa->sa;
- sock->remote_addr->salen = sa->salen;
- /* Adjust ipaddr_ptr et al. */
- apr_sockaddr_vars_set(sock->remote_addr, sa->family, sa->port);
+ /* Make remote address from connect()ed one. */
+ apr_sockaddr_put(&sock->remote_addr, sa->sa.sin.sin_family,
+ (const struct sockaddr*)&sa->sa, sa->salen,
+ sa->hostname, sa->servname, sock->pool);
}
+ else {
+ sock->remote_addr_unknown = 1;
+ }
- if (sock->local_addr->port == 0) {
- /* connect() got us an ephemeral port */
- sock->local_port_unknown = 1;
- }
+ sock->local_port_unknown = 0;
+ sock->local_interface_unknown = 0;
#if APR_HAVE_SOCKADDR_UN
- if (sock->local_addr->sa.sin.sin_family == AF_UNIX) {
- /* Assign connect address as local. */
- sock->local_addr = sa;
+ if (sa->sa.sin.sin_family == APR_UNIX) {
+ /* Make local address from connect()ed one. */
+ apr_sockaddr_put(&sock->local_addr, sa->sa.sin.sin_family,
+ (const struct sockaddr*)&sa->sa, sa->salen,
+ sa->hostname, sa->servname, sock->pool);
+ /* Local port and interface have no meaning for UDS,
+ * pretend we know them to avoid further resolution,
+ * hence keep unknown things set to 0 above.
+ */
}
else
#endif
- if (!memcmp(sock->local_addr->ipaddr_ptr,
- generic_inaddr_any,
- sock->local_addr->ipaddr_len)) {
- /* not bound to specific local interface; connect() had to assign
- * one for the socket
- */
- sock->local_interface_unknown = 1;
+ {
+ if (sock->local_addr->port == 0) {
+ /* connect() got us an ephemeral port */
+ sock->local_port_unknown = 1;
+ }
+ if (apr_sockaddr_is_wildcard(sock->local_addr)) {
+ /* not bound to specific local interface; connect() had to assign
+ * one for the socket
+ */
+ sock->local_interface_unknown = 1;
+ }
}
- if (rc == -1 && errno != EISCONN) {
- return errno;
+ if (rc && rc != EISCONN) {
+ return rc;
}
#ifndef HAVE_POLL
@@ -508,49 +542,45 @@ apr_status_t apr_os_sock_make(apr_socket_t **apr_s
apr_pool_t *cont)
{
alloc_socket(apr_sock, cont);
- set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol);
+
+#if !APR_HAVE_SOCKADDR_UN
+ if (os_sock_info->family == APR_UNIX) {
+ return APR_ENOTIMPL;
+ }
+#endif
+
(*apr_sock)->timeout = -1;
(*apr_sock)->socketdes = *os_sock_info->os_sock;
- if (os_sock_info->local) {
- memcpy(&(*apr_sock)->local_addr->sa.sin,
- os_sock_info->local,
- (*apr_sock)->local_addr->salen);
- /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
- (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port);
- }
- else {
- (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1;
- }
+#ifndef HAVE_POLL
if (os_sock_info->remote) {
-#ifndef HAVE_POLL
(*apr_sock)->connected = 1;
+ }
#endif
- memcpy(&(*apr_sock)->remote_addr->sa.sin,
- os_sock_info->remote,
- (*apr_sock)->remote_addr->salen);
- /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
- (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port);
- }
- else {
- (*apr_sock)->remote_addr_unknown = 1;
- }
-
- (*apr_sock)->inherit = 0;
+
+ apr_socket_addr_put((*apr_sock), os_sock_info);
+ set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type,
+ os_sock_info->protocol);
+
apr_pool_cleanup_register((*apr_sock)->pool, (void *)(*apr_sock),
socket_cleanup, socket_cleanup);
return APR_SUCCESS;
}
apr_status_t apr_os_sock_put(apr_socket_t **sock, apr_os_sock_t *thesock,
- apr_pool_t *cont)
+ apr_pool_t *cont)
{
- /* XXX Bogus assumption that *sock points at anything legit */
+ /* XXX: *sock must point to something legit or be NULL
+ * according to the declaration/doc(xygen).
+ */
if ((*sock) == NULL) {
+ if (cont == NULL) {
+ return APR_ENOPOOL;
+ }
alloc_socket(sock, cont);
- /* XXX IPv6 figure out the family here! */
- /* XXX figure out the actual socket type here */
- /* *or* just decide that apr_os_sock_put() has to be told the family and type */
- set_socket_vars(*sock, APR_INET, SOCK_STREAM, 0);
+ /* Let's wait for the user to ask for them before determining
+ * the socket type or the local/remote addresses.
+ */
+ set_socket_vars(*sock, APR_UNSPEC, SOCK_STREAM, 0);
(*sock)->timeout = -1;
}
(*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1;
Index: network_io/win32/sockets.c
===================================================================
--- network_io/win32/sockets.c (revision 1628634)
+++ network_io/win32/sockets.c (working copy)
@@ -24,8 +24,6 @@
#include "apr_arch_inherit.h"
#include "apr_arch_misc.h"
-static char generic_inaddr_any[16] = {0}; /* big enough for IPv4 or IPv6 */
-
static apr_status_t socket_cleanup(void *sock)
{
apr_socket_t *thesocket = sock;
@@ -49,8 +47,18 @@ static void set_socket_vars(apr_socket_t *sock, in
{
sock->type = type;
sock->protocol = protocol;
- apr_sockaddr_vars_set(sock->local_addr, family, 0);
- apr_sockaddr_vars_set(sock->remote_addr, family, 0);
+ if (sock->local_addr == NULL) {
+ sock->local_addr = (apr_sockaddr_t *)apr_pcalloc(sock->pool,
+ sizeof(apr_sockaddr_t));
+ sock->local_addr->pool = sock->pool;
+ apr_sockaddr_vars_set(sock->local_addr, family, 0);
+ }
+ if (sock->remote_addr == NULL) {
+ sock->remote_addr = (apr_sockaddr_t *)apr_pcalloc(sock->pool,
+ sizeof(apr_sockaddr_t));
+ sock->remote_addr->pool = sock->pool;
+ apr_sockaddr_vars_set(sock->remote_addr, family, 0);
+ }
#if APR_HAVE_IPV6
/* hard-coded behavior for older Windows IPv6 */
if (apr_os_level < APR_WIN_VISTA && family == AF_INET6) {
@@ -62,14 +70,8 @@ static void alloc_socket(apr_socket_t **new, apr_p
{
*new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t));
(*new)->pool = p;
- (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool,
- sizeof(apr_sockaddr_t));
- (*new)->local_addr->pool = p;
-
- (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool,
- sizeof(apr_sockaddr_t));
- (*new)->remote_addr->pool = p;
(*new)->remote_addr_unknown = 1;
+ (*new)->local_port_unknown = (*new)->local_interface_unknown = 1;
/* Create a pollset with room for one descriptor. */
/* ### check return codes */
@@ -91,11 +93,11 @@ APR_DECLARE(apr_status_t) apr_socket_create(apr_so
int downgrade = (family == AF_UNSPEC);
#endif
- if (family == AF_UNSPEC) {
+ if (family == APR_UNSPEC) {
#if APR_HAVE_IPV6
- family = AF_INET6;
+ family = APR_INET6;
#else
- family = AF_INET;
+ family = APR_INET;
#endif
}
@@ -107,7 +109,7 @@ APR_DECLARE(apr_status_t) apr_socket_create(apr_so
(*new)->socketdes = socket(family, type, protocol);
#if APR_HAVE_IPV6
if ((*new)->socketdes == INVALID_SOCKET && downgrade) {
- family = AF_INET;
+ family = APR_INET;
(*new)->socketdes = socket(family, type, protocol);
}
#endif
@@ -212,10 +214,25 @@ APR_DECLARE(apr_status_t) apr_socket_bind(apr_sock
return apr_get_netos_error();
}
else {
- sock->local_addr = sa;
+ /* Make local address. */
+ apr_sockaddr_put(&sock->local_addr, sa->sa.sin.sin_family,
+ (const struct sockaddr*)&sa->sa, sa->salen,
+ sa->hostname, sa->servname, sock->pool);
+ sock->local_port_unknown = sock->local_interface_unknown = 0;
if (sock->local_addr->sa.sin.sin_port == 0) {
sock->local_port_unknown = 1; /* ephemeral port */
}
+ if (apr_sockaddr_is_wildcard(sock->local_addr)) {
+ /* If the interface address inside the listening socket's
+ * local_addr wasn't up-to-date, we don't know local interface
+ * of the connected socket either.
+ *
+ * If the listening socket was not bound to a specific
+ * interface, we don't know the local_addr of the connected
+ * socket.
+ */
+ sock->local_interface_unknown = 1;
+ }
return APR_SUCCESS;
}
}
@@ -233,56 +250,57 @@ APR_DECLARE(apr_status_t) apr_socket_accept(apr_so
apr_socket_t *sock, apr_pool_t *p)
{
SOCKET s;
-#if APR_HAVE_IPV6
- struct sockaddr_storage sa;
-#else
- struct sockaddr sa;
-#endif
- int salen = sizeof(sock->remote_addr->sa);
+ apr_sockaddr_t sa;
+ sa.salen = sizeof(sa.sa);
+
/* Don't allocate the memory until after we call accept. This allows
us to work with nonblocking sockets. */
- s = accept(sock->socketdes, (struct sockaddr *)&sa, &salen);
+ s = accept(sock->socketdes, (struct sockaddr *)&sa.sa, &sa.salen);
if (s == INVALID_SOCKET) {
return apr_get_netos_error();
}
alloc_socket(new, p);
- set_socket_vars(*new, sock->local_addr->sa.sin.sin_family, SOCK_STREAM,
- sock->protocol);
(*new)->timeout = -1;
(*new)->disconnected = 0;
(*new)->socketdes = s;
- /* XXX next line looks bogus w.r.t. AF_INET6 support */
- (*new)->remote_addr->salen = sizeof((*new)->remote_addr->sa);
- memcpy (&(*new)->remote_addr->sa, &sa, salen);
+
+ /* Make peer address. */
+ apr_sockaddr_put(&(*new)->remote_addr, sa.sa.sin.sin_family,
+ (const struct sockaddr*)&sa.sa, sa.salen,
+ NULL, NULL, (*new)->pool);
(*new)->remote_addr_unknown = 0;
- *(*new)->local_addr = *sock->local_addr;
-
- /* The above assignment just overwrote the pool entry. Setting the local_addr
- pool for the accepted socket back to what it should be. Otherwise all
- allocations for this socket will come from a server pool that is not
- freed until the process goes down.*/
- (*new)->local_addr->pool = p;
-
- /* fix up any pointers which are no longer valid */
- if (sock->local_addr->sa.sin.sin_family == AF_INET) {
- (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr;
- }
-#if APR_HAVE_IPV6
- else if (sock->local_addr->sa.sin.sin_family == AF_INET6) {
- (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin6.sin6_addr;
- }
-#endif
- (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port);
- if (sock->local_port_unknown) {
+ /* Make local address. */
+ apr_sockaddr_put(&(*new)->local_addr, sa.sa.sin.sin_family,
+ (const struct sockaddr*)&sock->local_addr->sa,
+ sock->local_addr->salen,
+ sock->local_addr->hostname,
+ sock->local_addr->servname,
+ (*new)->pool);
+ (*new)->local_port_unknown = 0;
+ (*new)->local_interface_unknown = 0;
+ if ((*new)->local_addr->port == 0) {
/* not likely for a listening socket, but theoretically possible :) */
(*new)->local_port_unknown = 1;
}
+ if (apr_sockaddr_is_wildcard((*new)->local_addr)) {
+ /* If the interface address inside the listening socket's
+ * local_addr wasn't up-to-date, we don't know local interface
+ * of the connected socket either.
+ *
+ * If the listening socket was not bound to a specific
+ * interface, we don't know the local_addr of the connected
+ * socket.
+ */
+ (*new)->local_interface_unknown = 1;
+ }
+ set_socket_vars(*new, sa.sa.sin.sin_family, SOCK_STREAM, sock->protocol);
+
#if APR_TCP_NODELAY_INHERITED
if (apr_is_option_set(sock, APR_TCP_NODELAY) == 1) {
apr_set_option(*new, APR_TCP_NODELAY, 1);
@@ -294,19 +312,6 @@ APR_DECLARE(apr_status_t) apr_socket_accept(apr_so
}
#endif /* APR_O_NONBLOCK_INHERITED */
- if (sock->local_interface_unknown ||
- !memcmp(sock->local_addr->ipaddr_ptr,
- generic_inaddr_any,
- sock->local_addr->ipaddr_len)) {
- /* If the interface address inside the listening socket's local_addr wasn't
- * up-to-date, we don't know local interface of the connected socket either.
- *
- * If the listening socket was not bound to a specific interface, we
- * don't know the local_addr of the connected socket.
- */
- (*new)->local_interface_unknown = 1;
- }
-
apr_pool_cleanup_register((*new)->pool, (void *)(*new),
socket_cleanup, apr_pool_cleanup_null);
return APR_SUCCESS;
@@ -387,23 +392,28 @@ APR_DECLARE(apr_status_t) apr_socket_connect(apr_s
}
}
- if (memcmp(sa->ipaddr_ptr, generic_inaddr_any, sa->ipaddr_len)) {
+ if (!apr_sockaddr_is_wildcard(sa)) {
/* A real remote address was passed in. If the unspecified
* address was used, the actual remote addr will have to be
* determined using getpeername() if required. */
sock->remote_addr_unknown = 0;
- /* Copy the address structure details in. */
- sock->remote_addr = sa;
+ /* Make remote address from connect()ed one. */
+ apr_sockaddr_put(&sock->remote_addr, sa->sa.sin.sin_family,
+ (const struct sockaddr*)&sa->sa, sa->salen,
+ sa->hostname, sa->servname, sock->pool);
}
+ else {
+ sock->remote_addr_unknown = 1;
+ }
- if (sock->local_addr->sa.sin.sin_port == 0) {
+ sock->local_port_unknown = 0;
+ sock->local_interface_unknown = 0;
+ if (sock->local_addr->port == 0) {
/* connect() got us an ephemeral port */
sock->local_port_unknown = 1;
}
- if (!memcmp(sock->local_addr->ipaddr_ptr,
- generic_inaddr_any,
- sock->local_addr->ipaddr_len)) {
+ if (apr_sockaddr_is_wildcard(sock->local_addr)) {
/* not bound to specific local interface; connect() had to assign
* one for the socket
*/
@@ -471,31 +481,14 @@ APR_DECLARE(apr_status_t) apr_os_sock_make(apr_soc
apr_pool_t *cont)
{
alloc_socket(apr_sock, cont);
- set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol);
+
(*apr_sock)->timeout = -1;
- (*apr_sock)->disconnected = 0;
(*apr_sock)->socketdes = *os_sock_info->os_sock;
- if (os_sock_info->local) {
- memcpy(&(*apr_sock)->local_addr->sa.sin,
- os_sock_info->local,
- (*apr_sock)->local_addr->salen);
- (*apr_sock)->local_addr->pool = cont;
- /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
- (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port);
- }
- else {
- (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1;
- }
- if (os_sock_info->remote) {
- memcpy(&(*apr_sock)->remote_addr->sa.sin,
- os_sock_info->remote,
- (*apr_sock)->remote_addr->salen);
- (*apr_sock)->remote_addr->pool = cont;
- /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
- (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port);
- (*apr_sock)->remote_addr_unknown = 0;
- }
-
+
+ apr_socket_addr_put((*apr_sock), os_sock_info);
+ set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type,
+ os_sock_info->protocol);
+
apr_pool_cleanup_register((*apr_sock)->pool, (void *)(*apr_sock),
socket_cleanup, apr_pool_cleanup_null);
@@ -506,11 +499,18 @@ APR_DECLARE(apr_status_t) apr_os_sock_put(apr_sock
apr_os_sock_t *thesock,
apr_pool_t *cont)
{
+ /* XXX: *sock must point to something legit or be NULL
+ * according to the declaration/doc(xygen).
+ */
if ((*sock) == NULL) {
+ if (cont == NULL) {
+ return APR_ENOPOOL;
+ }
alloc_socket(sock, cont);
- /* XXX figure out the actual socket type here */
- /* *or* just decide that apr_os_sock_put() has to be told the family and type */
- set_socket_vars(*sock, AF_INET, SOCK_STREAM, 0);
+ /* Let's wait for the user to ask for them before determining
+ * the socket type or the local/remote addresses.
+ */
+ set_socket_vars(*sock, APR_UNSPEC, SOCK_STREAM, 0);
(*sock)->timeout = -1;
(*sock)->disconnected = 0;
}
Index: network_io/os2/sockets.c
===================================================================
--- network_io/os2/sockets.c (revision 1628634)
+++ network_io/os2/sockets.c (working copy)
@@ -51,22 +51,26 @@ static void set_socket_vars(apr_socket_t *sock, in
{
sock->type = type;
sock->protocol = protocol;
- apr_sockaddr_vars_set(sock->local_addr, family, 0);
- apr_sockaddr_vars_set(sock->remote_addr, family, 0);
+ if (sock->local_addr == NULL) {
+ sock->local_addr = (apr_sockaddr_t *)apr_pcalloc(sock->pool,
+ sizeof(apr_sockaddr_t));
+ sock->local_addr->pool = sock->pool;
+ apr_sockaddr_vars_set(sock->local_addr, family, 0);
+ }
+ if (sock->remote_addr == NULL) {
+ sock->remote_addr = (apr_sockaddr_t *)apr_pcalloc(sock->pool,
+ sizeof(apr_sockaddr_t));
+ sock->remote_addr->pool = sock->pool;
+ apr_sockaddr_vars_set(sock->remote_addr, family, 0);
+ }
}
static void alloc_socket(apr_socket_t **new, apr_pool_t *p)
{
*new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t));
(*new)->pool = p;
- (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool,
- sizeof(apr_sockaddr_t));
- (*new)->local_addr->pool = p;
-
- (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->pool,
- sizeof(apr_sockaddr_t));
- (*new)->remote_addr->pool = p;
(*new)->remote_addr_unknown = 1;
+ (*new)->local_port_unknown = (*new)->local_interface_unknown = 1;
/* Create a pollset with room for one descriptor. */
/* ### check return codes */
@@ -86,15 +90,14 @@ APR_DECLARE(apr_status_t) apr_socket_create(apr_so
apr_pollfd_t pfd;
int oprotocol = protocol;
- if (family == AF_UNSPEC) {
+ if (family == APR_UNSPEC) {
#if APR_HAVE_IPV6
- family = AF_INET6;
+ family = APR_INET6;
#else
- family = AF_INET;
+ family = APR_INET;
#endif
}
-
- if (family == APR_UNIX) {
+ else if (family == APR_UNIX) {
protocol = 0;
}
@@ -103,7 +106,7 @@ APR_DECLARE(apr_status_t) apr_socket_create(apr_so
(*new)->socketdes = socket(family, type, protocol);
#if APR_HAVE_IPV6
if ((*new)->socketdes < 0 && downgrade) {
- family = AF_INET;
+ family = APR_INET;
(*new)->socketdes = socket(family, type, protocol);
}
#endif
@@ -146,11 +149,25 @@ APR_DECLARE(apr_status_t) apr_socket_bind(apr_sock
sa->salen) == -1)
return APR_FROM_OS_ERROR(sock_errno());
else {
- sock->local_addr = sa;
- /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
- if (sock->local_addr->sa.sin.sin_port == 0) { /* no need for ntohs() when comparing w/ 0 */
- sock->local_port_unknown = 1; /* kernel got us an ephemeral port */
+ /* Make local address. */
+ apr_sockaddr_put(&sock->local_addr, sa->sa.sin.sin_family,
+ (const struct sockaddr*)&sa->sa, sa->salen,
+ sa->hostname, sa->servname, sock->pool);
+ sock->local_port_unknown = sock->local_interface_unknown = 0;
+ if (sock->local_addr->sa.sin.sin_port == 0) {
+ sock->local_port_unknown = 1; /* ephemeral port */
}
+ if (apr_sockaddr_is_wildcard(sock->local_addr)) {
+ /* If the interface address inside the listening socket's
+ * local_addr wasn't up-to-date, we don't know local interface
+ * of the connected socket either.
+ *
+ * If the listening socket was not bound to a specific
+ * interface, we don't know the local_addr of the connected
+ * socket.
+ */
+ sock->local_interface_unknown = 1;
+ }
return APR_SUCCESS;
}
}
@@ -182,15 +199,39 @@ APR_DECLARE(apr_status_t) apr_socket_accept(apr_so
return APR_FROM_OS_ERROR(sock_errno());
}
- *(*new)->local_addr = *sock->local_addr;
- (*new)->local_addr->pool = connection_context;
- (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port);
+ /* Make peer address. */
+ apr_sockaddr_put(&(*new)->remote_addr, sa.sa.sin.sin_family,
+ (const struct sockaddr*)&sa.sa, sa.salen,
+ NULL, NULL, (*new)->pool);
+ (*new)->remote_addr_unknown = 0;
- /* fix up any pointers which are no longer valid */
- if (sock->local_addr->sa.sin.sin_family == AF_INET) {
- (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr;
+ /* Make local address. */
+ apr_sockaddr_put(&(*new)->local_addr, sa.sa.sin.sin_family,
+ (const struct sockaddr*)&sock->local_addr->sa,
+ sock->local_addr->salen,
+ sock->local_addr->hostname,
+ sock->local_addr->servname,
+ (*new)->pool);
+ (*new)->local_port_unknown = 0;
+ (*new)->local_interface_unknown = 0;
+ if ((*new)->local_addr->port == 0) {
+ /* not likely for a listening socket, but theoretically possible :) */
+ (*new)->local_port_unknown = 1;
}
+ if (apr_sockaddr_is_wildcard((*new)->local_addr)) {
+ /* If the interface address inside the listening socket's
+ * local_addr wasn't up-to-date, we don't know local interface
+ * of the connected socket either.
+ *
+ * If the listening socket was not bound to a specific
+ * interface, we don't know the local_addr of the connected
+ * socket.
+ */
+ (*new)->local_interface_unknown = 1;
+ }
+ set_socket_vars(*new, sa.sa.sin.sin_family, SOCK_STREAM, sock->protocol);
+
apr_pool_cleanup_register((*new)->pool, (void *)(*new),
socket_cleanup, apr_pool_cleanup_null);
return APR_SUCCESS;
@@ -204,13 +245,36 @@ APR_DECLARE(apr_status_t) apr_socket_connect(apr_s
(sock_errno() != SOCEINPROGRESS)) {
return APR_FROM_OS_ERROR(sock_errno());
}
+
+ if (!apr_sockaddr_is_wildcard(sa)) {
+ /* A real remote address was passed in. If the unspecified
+ * address was used, the actual remote addr will have to be
+ * determined using getpeername() if required. */
+ sock->remote_addr_unknown = 0;
+
+ /* Make remote address from connect()ed one. */
+ apr_sockaddr_put(&sock->remote_addr, sa->sa.sin.sin_family,
+ (const struct sockaddr*)&sa->sa, sa->salen,
+ sa->hostname, sa->servname, sock->pool);
+ }
else {
- int namelen = sizeof(sock->local_addr->sa.sin);
- getsockname(sock->socketdes, (struct sockaddr *)&sock->local_addr->sa.sin,
- &namelen);
- sock->remote_addr = sa;
- return APR_SUCCESS;
+ sock->remote_addr_unknown = 1;
}
+
+ sock->local_port_unknown = 0;
+ sock->local_interface_unknown = 0;
+ if (sock->local_addr->port == 0) {
+ /* connect() got us an ephemeral port */
+ sock->local_port_unknown = 1;
+ }
+ if (apr_sockaddr_is_wildcard(sock->local_addr)) {
+ /* not bound to specific local interface; connect() had to assign
+ * one for the socket
+ */
+ sock->local_interface_unknown = 1;
+ }
+
+ return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_socket_type_get(apr_socket_t *sock, int *type)
@@ -267,47 +331,38 @@ APR_DECLARE(apr_status_t) apr_os_sock_make(apr_soc
apr_pool_t *cont)
{
alloc_socket(apr_sock, cont);
- set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol);
+
(*apr_sock)->timeout = -1;
(*apr_sock)->socketdes = *os_sock_info->os_sock;
- if (os_sock_info->local) {
- memcpy(&(*apr_sock)->local_addr->sa.sin,
- os_sock_info->local,
- (*apr_sock)->local_addr->salen);
- /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
- (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port);
- }
- else {
- (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1;
- }
- if (os_sock_info->remote) {
- memcpy(&(*apr_sock)->remote_addr->sa.sin,
- os_sock_info->remote,
- (*apr_sock)->remote_addr->salen);
- /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */
- (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port);
- }
- else {
- (*apr_sock)->remote_addr_unknown = 1;
- }
-
+
+ apr_socket_addr_put((*apr_sock), os_sock_info);
+ set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type,
+ os_sock_info->protocol);
+
apr_pool_cleanup_register((*apr_sock)->pool, (void *)(*apr_sock),
socket_cleanup, apr_pool_cleanup_null);
return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_os_sock_put(apr_socket_t **sock, apr_os_sock_t *thesock, apr_pool_t *cont)
+APR_DECLARE(apr_status_t) apr_os_sock_put(apr_socket_t **sock,
+ apr_os_sock_t *thesock,
+ apr_pool_t *cont)
{
- if (cont == NULL) {
- return APR_ENOPOOL;
- }
+ /* XXX: *sock must point to something legit or be NULL
+ * according to the declaration/doc(xygen).
+ */
if ((*sock) == NULL) {
+ if (cont == NULL) {
+ return APR_ENOPOOL;
+ }
alloc_socket(sock, cont);
- set_socket_vars(*sock, AF_INET, SOCK_STREAM, 0);
+ /* Let's wait for the user to ask for them before determining
+ * the socket type or the local/remote addresses.
+ */
+ set_socket_vars(*sock, APR_UNSPEC, SOCK_STREAM, 0);
(*sock)->timeout = -1;
}
-
(*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1;
(*sock)->remote_addr_unknown = 1;
(*sock)->socketdes = *thesock;
Index: strings/apr_snprintf.c
===================================================================
--- strings/apr_snprintf.c (revision 1628634)
+++ strings/apr_snprintf.c (working copy)
@@ -449,31 +449,59 @@ static char *conv_apr_sockaddr(apr_sockaddr_t *sa,
int is_negative;
apr_size_t sub_len;
char *ipaddr_str;
+ char trailer;
+#if APR_HAVE_SOCKADDR_UN
+ if (sa->family == APR_UNIX) {
+ ipaddr_str = buf_end - NUM_BUF_SIZE;
+ if (apr_sockaddr_ip_getbuf(ipaddr_str, p - ipaddr_str, sa)) {
+ /* Should only fail if the buffer is too small,
+ * mark the returned path as truncated. */
+ *(p - 2) = '?';
+ }
+ /* Add a trailing '=' (like ls -F for sockets). */
+ *len = strlen(ipaddr_str);
+ ipaddr_str[(*len)++] = '=';
+ return ipaddr_str;
+ }
+#endif
p = conv_10(sa->port, TRUE, &is_negative, p, &sub_len);
- *--p = ':';
ipaddr_str = buf_end - NUM_BUF_SIZE;
- if (apr_sockaddr_ip_getbuf(ipaddr_str, sa->addr_str_len, sa)) {
+#if APR_HAVE_IPV6
+ if (sa->family == APR_INET6 &&
+ !IN6_IS_ADDR_V4MAPPED(&sa->sa.sin6.sin6_addr)) {
+ *--p = ':';
+ *ipaddr_str++ = '[';
+ trailer = ']';
+ }
+ else
+#endif
+ trailer = ':';
+ *--p = trailer;
+ if (apr_sockaddr_ip_getbuf(ipaddr_str, p - ipaddr_str, sa)) {
/* Should only fail if the buffer is too small, which it
* should not be; but fail safe anyway: */
+ *p = trailer; /* replace the '\0' */
*--p = '?';
- *len = buf_end - p;
- return p;
+ if (trailer == ']') {
+ *--p = '[';
+ }
}
- sub_len = strlen(ipaddr_str);
-#if APR_HAVE_IPV6
- if (sa->family == APR_INET6 &&
- !IN6_IS_ADDR_V4MAPPED(&sa->sa.sin6.sin6_addr)) {
- *(p - 1) = ']';
- p -= sub_len + 2;
- *p = '[';
- memcpy(p + 1, ipaddr_str, sub_len);
+ else if (*p == '\0') {
+ /* We are already aligned (unlikely). */
+ *p = trailer; /* replace the '\0' */
+ p = ipaddr_str;
}
- else
-#endif
- {
+ else {
+ /* We have to align from :port (likely). */
+ sub_len = strlen(ipaddr_str);
+ if (trailer == ']') {
+ ipaddr_str--;
+ sub_len++;
+ }
p -= sub_len;
- memcpy(p, ipaddr_str, sub_len);
+ /* Use memmove since source and destination may overlap */
+ memmove(p, ipaddr_str, sub_len);
}
*len = buf_end - p;
Index: test/testsock.c
===================================================================
--- test/testsock.c (revision 1628634)
+++ test/testsock.c (working copy)
@@ -26,11 +26,14 @@
#define APR_WANT_BYTEFUNC
#include "apr_want.h"
-#define UNIX_SOCKET_NAME "/tmp/apr-socket"
-#define IPV4_SOCKET_NAME "127.0.0.1"
-static char *socket_name = NULL;
-static int socket_type = APR_INET;
+#define IPV4_SOCKET_NAME "127.0.0.1"
+#define IPV6_SOCKET_NAME "::1"
+#define UNIX_SOCKET_NAME "/tmp/apr-socket"
+static const char *socket_name = IPV4_SOCKET_NAME;
+static int socket_type = APR_INET;
+static int socket_prot = APR_PROTO_TCP;
+
static void launch_child(abts_case *tc, apr_proc_t *proc, const char *arg1, apr_pool_t *p)
{
apr_procattr_t *procattr;
@@ -86,10 +89,31 @@ static void test_addr_info(abts_case *tc, void *da
rv = apr_sockaddr_info_get(&sa, "127.0.0.1", APR_UNSPEC, 80, 0, p);
APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
ABTS_STR_EQUAL(tc, "127.0.0.1", sa->hostname);
+ ABTS_INT_EQUAL(tc, 80, sa->port);
rc = apr_sockaddr_is_wildcard(sa);
ABTS_INT_EQUAL(tc, 0, rc);
+#if APR_HAVE_IPV6
+ rv = apr_sockaddr_info_get(&sa, IPV6_SOCKET_NAME, APR_UNSPEC, 80, 0, p);
+ APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+ ABTS_STR_EQUAL(tc, IPV6_SOCKET_NAME, sa->hostname);
+ ABTS_INT_EQUAL(tc, 80, sa->port);
+
+ rc = apr_sockaddr_is_wildcard(sa);
+ ABTS_INT_EQUAL(tc, 0, rc);
+#endif
+
+#if APR_HAVE_SOCKADDR_UN
+ rv = apr_sockaddr_info_get(&sa, UNIX_SOCKET_NAME, APR_UNSPEC, 80, 0, p);
+ APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+ ABTS_STR_EQUAL(tc, UNIX_SOCKET_NAME, sa->hostname);
+ ABTS_INT_EQUAL(tc, 0, sa->port);
+
+ rc = apr_sockaddr_is_wildcard(sa);
+ ABTS_INT_EQUAL(tc, 0, rc);
+#endif
+
rv = apr_sockaddr_info_get(&sa, "127.0.0.1", APR_UNSPEC, 0, 0, p);
APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
ABTS_STR_EQUAL(tc, "127.0.0.1", sa->hostname);
@@ -102,17 +126,24 @@ static void test_addr_copy(abts_case *tc, void *da
apr_status_t rv;
apr_sockaddr_t *sa1, *sa2;
int rc;
- const char *hosts[] = {
- "127.0.0.1",
+ struct {
+ const char *host;
+ apr_port_t port;
+ } entries[] = {
+ {IPV4_SOCKET_NAME, 80},
#if APR_HAVE_IPV6
- "::1",
+ {IPV6_SOCKET_NAME, 80},
#endif
- NULL
- }, **host = hosts;
+#if APR_HAVE_SOCKADDR_UN
+ {UNIX_SOCKET_NAME, 0},
+#endif
+ {NULL, 80}
+ }, *entry = entries;
/* Loop up to and including NULL */
do {
- rv = apr_sockaddr_info_get(&sa1, *host, APR_UNSPEC, 80, 0, p);
+ rv = apr_sockaddr_info_get(&sa1, entry->host, APR_UNSPEC,
+ entry->port, 0, p);
APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
rv = apr_sockaddr_info_copy(&sa2, sa1, p);
@@ -124,15 +155,18 @@ static void test_addr_copy(abts_case *tc, void *da
rc = apr_sockaddr_equal(sa2, sa1);
ABTS_INT_NEQUAL(tc, 0, rc);
- ABTS_INT_EQUAL(tc, 80, sa1->port);
+ ABTS_INT_EQUAL(tc, entry->port, sa1->port);
ABTS_INT_EQUAL(tc, sa2->port, sa1->port);
- ABTS_INT_EQUAL(tc, 80, ntohs(sa1->sa.sin.sin_port));
- ABTS_INT_EQUAL(tc, ntohs(sa2->sa.sin.sin_port), ntohs(sa1->sa.sin.sin_port));
+ if (entry->port) {
+ ABTS_INT_EQUAL(tc, entry->port, ntohs(sa1->sa.sin.sin_port));
+ ABTS_INT_EQUAL(tc, ntohs(sa2->sa.sin.sin_port),
+ ntohs(sa1->sa.sin.sin_port));
+ }
- if (*host) {
+ if (entry->host) {
ABTS_PTR_NOTNULL(tc, sa1->hostname);
ABTS_PTR_NOTNULL(tc, sa2->hostname);
- ABTS_STR_EQUAL(tc, *host, sa1->hostname);
+ ABTS_STR_EQUAL(tc, entry->host, sa1->hostname);
ABTS_STR_EQUAL(tc, sa1->hostname, sa2->hostname);
ABTS_TRUE(tc, sa1->hostname != sa2->hostname);
}
@@ -144,7 +178,7 @@ static void test_addr_copy(abts_case *tc, void *da
} while ((sa2 = sa2->next, sa1 = sa1->next));
ABTS_PTR_EQUAL(tc, NULL, sa2);
- } while (*host++);
+ } while ((entry++)->host);
}
static void test_serv_by_name(abts_case *tc, void *data)
@@ -176,7 +210,7 @@ static apr_socket_t *setup_socket(abts_case *tc)
rv = apr_sockaddr_info_get(&sa, socket_name, socket_type, 8021, 0, p);
APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
- rv = apr_socket_create(&sock, sa->family, SOCK_STREAM, APR_PROTO_TCP, p);
+ rv = apr_socket_create(&sock, sa->family, SOCK_STREAM, socket_prot, p);
APR_ASSERT_SUCCESS(tc, "Problem creating socket", rv);
rv = apr_socket_opt_set(sock, APR_SO_REUSEADDR, 1);
@@ -221,7 +255,7 @@ static void test_send(abts_case *tc, void *data)
APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
apr_socket_protocol_get(sock2, &protocol);
- ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol);
+ ABTS_INT_EQUAL(tc, socket_prot, protocol);
length = strlen(DATASTR);
apr_socket_send(sock2, DATASTR, &length);
@@ -254,7 +288,7 @@ static void test_recv(abts_case *tc, void *data)
APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
apr_socket_protocol_get(sock2, &protocol);
- ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol);
+ ABTS_INT_EQUAL(tc, socket_prot, protocol);
memset(datastr, 0, STRLEN);
apr_socket_recv(sock2, datastr, &length);
@@ -348,7 +382,7 @@ static void test_timeout(abts_case *tc, void *data
APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
apr_socket_protocol_get(sock2, &protocol);
- ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol);
+ ABTS_INT_EQUAL(tc, socket_prot, protocol);
exit = wait_child(tc, &proc);
ABTS_INT_EQUAL(tc, SOCKET_TIMEOUT, exit);
@@ -367,23 +401,25 @@ static void test_print_addr(abts_case *tc, void *d
apr_sockaddr_t *sa;
apr_status_t rv;
char *s;
+ int rc;
rv = apr_sockaddr_info_get(&sa, "0.0.0.0", APR_INET, 80, 0, p);
APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+ rc = apr_sockaddr_is_wildcard(sa);
+ ABTS_INT_NEQUAL(tc, 0, rc);
+
s = apr_psprintf(p, "foo %pI bar", sa);
-
ABTS_STR_EQUAL(tc, "foo 0.0.0.0:80 bar", s);
#if APR_HAVE_IPV6
+ /* sa should be a v4-mapped IPv6 address. */
rv = apr_sockaddr_info_get(&sa, "::ffff:0.0.0.0", APR_INET6, 80, 0, p);
APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
if (rv == APR_SUCCESS)
ABTS_TRUE(tc, sa != NULL);
if (rv == APR_SUCCESS && sa) {
- /* sa should now be a v4-mapped IPv6 address. */
char buf[128];
- int rc;
rc = apr_sockaddr_is_wildcard(sa);
ABTS_INT_NEQUAL(tc, 0, rc);
@@ -391,11 +427,103 @@ static void test_print_addr(abts_case *tc, void *d
memset(buf, 'z', sizeof buf);
APR_ASSERT_SUCCESS(tc, "could not get IP address",
- apr_sockaddr_ip_getbuf(buf, 22, sa));
-
+ apr_sockaddr_ip_getbuf(buf, sizeof buf, sa));
ABTS_STR_EQUAL(tc, "0.0.0.0", buf);
+
+ s = apr_psprintf(p, "%pI", sa);
+ ABTS_STR_EQUAL(tc, "0.0.0.0:80", s);
}
+
+ /* sa should be a real (though arbitrary choosen) IPv6 address. */
+ rv = apr_sockaddr_info_get(&sa, "fe80::250:56ff:fec0:8", APR_INET6, 80, 0, p);
+ APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+ if (rv == APR_SUCCESS)
+ ABTS_TRUE(tc, sa != NULL);
+ if (rv == APR_SUCCESS && sa) {
+ char buf[128];
+ int rc;
+
+ rc = apr_sockaddr_is_wildcard(sa);
+ ABTS_INT_EQUAL(tc, 0, rc);
+
+ memset(buf, 'z', sizeof buf);
+
+ APR_ASSERT_SUCCESS(tc, "could not get IP address",
+ apr_sockaddr_ip_getbuf(buf, sizeof buf, sa));
+ ABTS_STR_EQUAL(tc, "fe80::250:56ff:fec0:8", buf);
+
+ s = apr_psprintf(p, "%pI", sa);
+ ABTS_STR_EQUAL(tc, "[fe80::250:56ff:fec0:8]:80", s);
+ }
#endif
+
+#if APR_HAVE_SOCKADDR_UN
+ rv = apr_sockaddr_info_get(&sa, UNIX_SOCKET_NAME, APR_UNIX, 0, 0, p);
+ APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+ if (rv == APR_SUCCESS)
+ ABTS_TRUE(tc, sa != NULL);
+ if (rv == APR_SUCCESS && sa) {
+ char buf[128];
+ int rc;
+
+ rc = apr_sockaddr_is_wildcard(sa);
+ ABTS_INT_EQUAL(tc, 0, rc);
+
+ memset(buf, 'z', sizeof buf);
+
+ APR_ASSERT_SUCCESS(tc, "could not get IP address",
+ apr_sockaddr_ip_getbuf(buf, sizeof buf, sa));
+ ABTS_STR_EQUAL(tc, UNIX_SOCKET_NAME, buf);
+
+ s = apr_psprintf(p, "%pI", sa);
+ ABTS_STR_EQUAL(tc, UNIX_SOCKET_NAME"=", s);
+ }
+ /* Let's try a huge path of length APR_PATH_MAX - 1:
+ * creating a sockaddr should always work, binding
+ * or connecting a socket on that path depends on the
+ * OS though, we won't try this...
+ */
+ {
+ char *sockpath;
+ apr_size_t namelen;
+#define NUM_BUF_SIZE 512 /* from strings/apr_snprintf.c */
+
+ namelen = strlen(UNIX_SOCKET_NAME);
+ sockpath = apr_palloc(p, APR_PATH_MAX + 1);
+ memcpy(sockpath, UNIX_SOCKET_NAME, namelen);
+ memset(sockpath + namelen, 'x', APR_PATH_MAX - namelen - 1);
+ sockpath[APR_PATH_MAX - 1] = '\0';
+
+ rv = apr_sockaddr_info_get(&sa, sockpath, APR_UNIX, 0, 0, p);
+ APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+ if (rv == APR_SUCCESS)
+ ABTS_TRUE(tc, sa != NULL);
+ if (rv == APR_SUCCESS && sa) {
+ char *path;
+
+ path = apr_palloc(p, APR_PATH_MAX + 1);
+ memset(path, 'z', APR_PATH_MAX + 1);
+
+ APR_ASSERT_SUCCESS(tc, "could not get IP address",
+ apr_sockaddr_ip_getbuf(path, APR_PATH_MAX + 1,
+ sa));
+ ABTS_STR_EQUAL(tc, sockpath, path);
+
+ if (NUM_BUF_SIZE >= APR_PATH_MAX) {
+ sockpath[APR_PATH_MAX - 1] = '=';
+ sockpath[APR_PATH_MAX] = '\0';
+ }
+ else {
+ /* the path will be truncated by apr_psprintf() */
+ sockpath[NUM_BUF_SIZE - 2] = '?';
+ sockpath[NUM_BUF_SIZE - 1] = '=';
+ sockpath[NUM_BUF_SIZE] = '\0';
+ }
+ s = apr_psprintf(p, "%pI", sa);
+ ABTS_STR_EQUAL(tc, sockpath, s);
+ }
+ }
+#endif
}
static void test_get_addr(abts_case *tc, void *data)
@@ -415,28 +543,16 @@ static void test_get_addr(abts_case *tc, void *dat
"get local address of bound socket",
apr_socket_addr_get(&sa, APR_LOCAL, ld));
- rv = apr_socket_create(&cd, sa->family, SOCK_STREAM,
- APR_PROTO_TCP, subp);
+ rv = apr_socket_create(&cd, sa->family, SOCK_STREAM, socket_prot, subp);
APR_ASSERT_SUCCESS(tc, "create client socket", rv);
APR_ASSERT_SUCCESS(tc, "enable non-block mode",
apr_socket_opt_set(cd, APR_SO_NONBLOCK, 1));
- /* It is valid for a connect() on a socket with NONBLOCK set to
- * succeed (if the connection can be established synchronously),
- * but if it does, this test cannot proceed. */
rv = apr_socket_connect(cd, sa);
- if (rv == APR_SUCCESS) {
+ if (rv != APR_SUCCESS && !APR_STATUS_IS_EINPROGRESS(rv)) {
apr_socket_close(ld);
apr_socket_close(cd);
- ABTS_NOT_IMPL(tc, "Cannot test if connect completes "
- "synchronously");
- return;
- }
-
- if (!APR_STATUS_IS_EINPROGRESS(rv)) {
- apr_socket_close(ld);
- apr_socket_close(cd);
APR_ASSERT_SUCCESS(tc, "connect to listener", rv);
return;
}
@@ -444,7 +560,10 @@ static void test_get_addr(abts_case *tc, void *dat
APR_ASSERT_SUCCESS(tc, "accept connection",
apr_socket_accept(&sd, ld, subp));
- {
+ /* It is valid for a connect() on a socket with NONBLOCK set to
+ * succeed (if the connection can be established synchronously),
+ * and if it does, we don't need to wait here. */
+ if (rv != APR_SUCCESS) {
/* wait for writability */
apr_pollfd_t pfd;
int n;
@@ -484,8 +603,16 @@ static void test_get_addr(abts_case *tc, void *dat
/* Check equivalence. */
a = apr_psprintf(p, "%pI fam=%d", sa, sa->family);
b = apr_psprintf(p, "%pI fam=%d", ca, ca->family);
+ if (socket_type == APR_UNIX && *b == '=') {
+ /* The remote address may be empty (unavailable)
+ * for APR_UNIX, compare from %pI's trailing '='. */
+ a = strchr(a, '=');
+ ABTS_PTR_NOTNULL(tc, a);
+ }
ABTS_STR_EQUAL(tc, a, b);
+ /* Test that the pool of the returned sockaddr objects exactly
+ * match the socket. */
ABTS_PTR_EQUAL(tc, subp, sa->pool);
ABTS_PTR_EQUAL(tc, subp, ca->pool);
@@ -610,30 +737,54 @@ static void test_nonblock_inheritance(abts_case *t
abts_suite *testsock(abts_suite *suite)
{
suite = ADD_SUITE(suite)
- socket_name = IPV4_SOCKET_NAME;
+
abts_run_test(suite, test_addr_info, NULL);
abts_run_test(suite, test_addr_copy, NULL);
abts_run_test(suite, test_serv_by_name, NULL);
+
+ socket_name = IPV4_SOCKET_NAME;
+ socket_type = APR_INET;
+ socket_prot = APR_PROTO_TCP;
abts_run_test(suite, test_create_bind_listen, NULL);
+ abts_run_test(suite, test_print_addr, NULL);
abts_run_test(suite, test_send, NULL);
abts_run_test(suite, test_recv, NULL);
abts_run_test(suite, test_atreadeof, NULL);
abts_run_test(suite, test_timeout, NULL);
- abts_run_test(suite, test_print_addr, NULL);
abts_run_test(suite, test_get_addr, NULL);
abts_run_test(suite, test_wait, NULL);
abts_run_test(suite, test_nonblock_inheritance, NULL);
+
+#if APR_HAVE_IPV6
+ socket_name = IPV6_SOCKET_NAME;
+ socket_type = APR_INET6;
+ socket_prot = APR_PROTO_TCP;
+ abts_run_test(suite, test_create_bind_listen, NULL);
+ abts_run_test(suite, test_send, NULL);
+ abts_run_test(suite, test_recv, NULL);
+ abts_run_test(suite, test_atreadeof, NULL);
+ abts_run_test(suite, test_timeout, NULL);
+ abts_run_test(suite, test_get_addr, NULL);
+ abts_run_test(suite, test_wait, NULL);
+ abts_run_test(suite, test_nonblock_inheritance, NULL);
+#endif
+
#if APR_HAVE_SOCKADDR_UN
socket_name = UNIX_SOCKET_NAME;
socket_type = APR_UNIX;
+ socket_prot = 0;
/* in case AF_UNIX socket exists from a previous run: */
apr_file_remove(socket_name, p);
abts_run_test(suite, test_create_bind_listen, NULL);
abts_run_test(suite, test_send, NULL);
abts_run_test(suite, test_recv, NULL);
+ abts_run_test(suite, test_atreadeof, NULL);
abts_run_test(suite, test_timeout, NULL);
+ abts_run_test(suite, test_get_addr, NULL);
abts_run_test(suite, test_wait, NULL);
+ abts_run_test(suite, test_nonblock_inheritance, NULL);
#endif
+
return suite;
}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic