diff options
Diffstat (limited to 'network_io/unix/sockets.c')
-rw-r--r-- | network_io/unix/sockets.c | 61 |
1 files changed, 56 insertions, 5 deletions
diff --git a/network_io/unix/sockets.c b/network_io/unix/sockets.c index b95794f183ad..206c65447158 100644 --- a/network_io/unix/sockets.c +++ b/network_io/unix/sockets.c @@ -26,13 +26,26 @@ #define close closesocket #endif /* BEOS_R5 */ -static char generic_inaddr_any[16] = {0}; /* big enough for IPv4 or IPv6 */ +#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 optionaly 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; int sd = thesocket->socketdes; +#if APR_HAVE_SOCKADDR_UN + if (thesocket->bound && thesocket->local_addr->family == APR_UNIX) { + /* XXX: Check for return values ? */ + unlink(thesocket->local_addr->hostname); + } +#endif /* Set socket descriptor to -1 before close(), so that there is no * chance of returning an already closed FD from apr_os_sock_get(). */ @@ -49,6 +62,18 @@ static apr_status_t socket_cleanup(void *sock) } } +static apr_status_t socket_child_cleanup(void *sock) +{ + apr_socket_t *thesocket = sock; + if (close(thesocket->socketdes) == 0) { + thesocket->socketdes = -1; + return APR_SUCCESS; + } + else { + return errno; + } +} + static void set_socket_vars(apr_socket_t *sock, int family, int type, int protocol) { sock->type = type; @@ -92,6 +117,7 @@ apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type, int protocol, apr_pool_t *cont) { int family = ofamily, flags = 0; + int oprotocol = protocol; #ifdef HAVE_SOCK_CLOEXEC flags |= SOCK_CLOEXEC; @@ -104,7 +130,11 @@ apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type, family = APR_INET; #endif } - +#if APR_HAVE_SOCKADDR_UN + if (family == APR_UNIX) { + protocol = 0; + } +#endif alloc_socket(new, cont); #ifndef BEOS_R5 @@ -140,7 +170,7 @@ apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type, if ((*new)->socketdes < 0) { return errno; } - set_socket_vars(*new, family, type, protocol); + set_socket_vars(*new, family, type, oprotocol); #ifndef HAVE_SOCK_CLOEXEC { @@ -167,7 +197,7 @@ apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type, (*new)->timeout = -1; (*new)->inherit = 0; apr_pool_cleanup_register((*new)->pool, (void *)(*new), socket_cleanup, - socket_cleanup); + socket_child_cleanup); return APR_SUCCESS; } @@ -192,6 +222,13 @@ apr_status_t apr_socket_bind(apr_socket_t *sock, apr_sockaddr_t *sa) else { sock->local_addr = sa; /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ +#if APR_HAVE_SOCKADDR_UN + if (sock->local_addr->family == APR_UNIX) { + sock->bound = 1; + sock->local_port_unknown = 1; + } + 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 */ } @@ -282,6 +319,14 @@ apr_status_t apr_socket_accept(apr_socket_t **new, apr_socket_t *sock, (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin6.sin6_addr; } #endif +#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 (sock->local_addr->sa.sin.sin_family != AF_UNIX) +#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 :) */ @@ -375,7 +420,6 @@ apr_status_t apr_socket_connect(apr_socket_t *sock, apr_sockaddr_t *sa) #endif /* SO_ERROR */ } - if (memcmp(sa->ipaddr_ptr, generic_inaddr_any, sa->ipaddr_len)) { /* A real remote address was passed in. If the unspecified * address was used, the actual remote addr will have to be @@ -393,6 +437,13 @@ apr_status_t apr_socket_connect(apr_socket_t *sock, apr_sockaddr_t *sa) /* connect() got us an ephemeral port */ sock->local_port_unknown = 1; } +#if APR_HAVE_SOCKADDR_UN + if (sock->local_addr->sa.sin.sin_family == AF_UNIX) { + /* Assign connect address as local. */ + sock->local_addr = sa; + } + else +#endif if (!memcmp(sock->local_addr->ipaddr_ptr, generic_inaddr_any, sock->local_addr->ipaddr_len)) { |