summaryrefslogtreecommitdiff
path: root/lib/isc/win32/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/isc/win32/socket.c')
-rw-r--r--lib/isc/win32/socket.c483
1 files changed, 388 insertions, 95 deletions
diff --git a/lib/isc/win32/socket.c b/lib/isc/win32/socket.c
index 7c4068fbdc2b..ffcefb0606c8 100644
--- a/lib/isc/win32/socket.c
+++ b/lib/isc/win32/socket.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: socket.c,v 1.70.54.4 2009/01/29 22:40:36 jinmei Exp $ */
+/* $Id$ */
/* This code uses functions which are only available on Server 2003 and
* higher, and Windows XP and higher.
@@ -265,7 +265,8 @@ struct isc_socket {
unsigned int listener : 1, /* listener socket */
connected : 1,
pending_connect : 1, /* connect pending */
- bound : 1; /* bound to local addr */
+ bound : 1, /* bound to local addr */
+ dupped : 1; /* created by isc_socket_dup() */
unsigned int pending_iocp; /* Should equal the counters below. Debug. */
unsigned int pending_recv; /* Number of outstanding recv() calls. */
unsigned int pending_send; /* Number of outstanding send() calls. */
@@ -351,6 +352,10 @@ enum {
#define MAXSCATTERGATHER_SEND (ISC_SOCKET_MAXSCATTERGATHER)
#define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER)
+static isc_result_t socket_create(isc_socketmgr_t *manager0, int pf,
+ isc_sockettype_t type,
+ isc_socket_t **socketp,
+ isc_socket_t *dup_socket);
static isc_threadresult_t WINAPI SocketIoThread(LPVOID ThreadContext);
static void maybe_free_socket(isc_socket_t **, int);
static void free_socket(isc_socket_t **, int);
@@ -716,21 +721,31 @@ queue_receive_request(isc_socket_t *sock) {
int total_bytes = 0;
int Result;
int Error;
+ int need_retry;
WSABUF iov[1];
- IoCompletionInfo *lpo;
+ IoCompletionInfo *lpo = NULL;
isc_result_t isc_result;
+ retry:
+ need_retry = ISC_FALSE;
+
/*
* If we already have a receive pending, do nothing.
*/
- if (sock->pending_recv > 0)
+ if (sock->pending_recv > 0) {
+ if (lpo != NULL)
+ HeapFree(hHeapHandle, 0, lpo);
return;
+ }
/*
* If no one is waiting, do nothing.
*/
- if (ISC_LIST_EMPTY(sock->recv_list))
+ if (ISC_LIST_EMPTY(sock->recv_list)) {
+ if (lpo != NULL)
+ HeapFree(hHeapHandle, 0, lpo);
return;
+ }
INSIST(sock->recvbuf.remaining == 0);
INSIST(sock->fd != INVALID_SOCKET);
@@ -738,10 +753,13 @@ queue_receive_request(isc_socket_t *sock) {
iov[0].len = sock->recvbuf.len;
iov[0].buf = sock->recvbuf.base;
- lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
- HEAP_ZERO_MEMORY,
- sizeof(IoCompletionInfo));
- RUNTIME_CHECK(lpo != NULL);
+ if (lpo == NULL) {
+ lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
+ HEAP_ZERO_MEMORY,
+ sizeof(IoCompletionInfo));
+ RUNTIME_CHECK(lpo != NULL);
+ } else
+ ZeroMemory(lpo, sizeof(IoCompletionInfo));
lpo->request_type = SOCKET_RECV;
sock->recvbuf.from_addr_len = sizeof(sock->recvbuf.from_addr);
@@ -763,6 +781,17 @@ queue_receive_request(isc_socket_t *sock) {
sock->pending_recv++;
break;
+ /* direct error: no completion event */
+ case ERROR_HOST_UNREACHABLE:
+ case WSAENETRESET:
+ case WSAECONNRESET:
+ if (!sock->connected) {
+ /* soft error */
+ need_retry = ISC_TRUE;
+ break;
+ }
+ /* FALLTHROUGH */
+
default:
isc_result = isc__errno2result(Error);
if (isc_result == ISC_R_UNEXPECTED)
@@ -770,6 +799,8 @@ queue_receive_request(isc_socket_t *sock) {
"WSARecvFrom: Windows error code: %d, isc result %d",
Error, isc_result);
send_recvdone_abort(sock, isc_result);
+ HeapFree(hHeapHandle, 0, lpo);
+ lpo = NULL;
break;
}
} else {
@@ -789,6 +820,9 @@ queue_receive_request(isc_socket_t *sock) {
sock->fd, Result, Error);
CONSISTENT(sock);
+
+ if (need_retry)
+ goto retry;
}
static void
@@ -866,7 +900,7 @@ make_nonblock(SOCKET fd) {
}
/*
- * Windows 2000 systems incorrectly cause UDP sockets using WASRecvFrom
+ * Windows 2000 systems incorrectly cause UDP sockets using WSARecvFrom
* to not work correctly, returning a WSACONNRESET error when a WSASendTo
* fails with an "ICMP port unreachable" response and preventing the
* socket from using the WSARecvFrom in subsequent operations.
@@ -1318,7 +1352,7 @@ completeio_send(isc_socket_t *sock, isc_socketevent_t *dev,
UNEXPECTED_ERROR(__FILE__, __LINE__, "completeio_send: %s: %s",
addrbuf, strbuf);
dev->result = isc__errno2result(send_errno);
- return (DOIO_HARD);
+ return (DOIO_HARD);
}
/*
@@ -1387,6 +1421,7 @@ startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes,
"bytes, err %d/%s",
sock->fd, *nbytes, *send_errno, strbuf);
}
+ status = DOIO_HARD;
goto done;
}
dev->result = ISC_R_SUCCESS;
@@ -1431,6 +1466,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
sock->connected = 0;
sock->pending_connect = 0;
sock->bound = 0;
+ sock->dupped = 0;
memset(sock->name, 0, sizeof(sock->name)); // zero the name field
_set_state(sock, SOCK_INITIALIZED);
@@ -1593,9 +1629,10 @@ free_socket(isc_socket_t **sockp, int lineno) {
* called with 'arg' as the arg value. The new socket is returned
* in 'socketp'.
*/
-isc_result_t
-isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
- isc_socket_t **socketp) {
+static isc_result_t
+socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+ isc_socket_t **socketp, isc_socket_t *dup_socket)
+{
isc_socket_t *sock = NULL;
isc_result_t result;
#if defined(USE_CMSG)
@@ -1612,33 +1649,54 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
REQUIRE(socketp != NULL && *socketp == NULL);
REQUIRE(type != isc_sockettype_fdwatch);
+ if (dup_socket != NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+
result = allocate_socket(manager, type, &sock);
if (result != ISC_R_SUCCESS)
return (result);
sock->pf = pf;
- switch (type) {
- case isc_sockettype_udp:
- sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
- if (sock->fd != INVALID_SOCKET) {
- result = connection_reset_fix(sock->fd);
- if (result != ISC_R_SUCCESS) {
- socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
- "closed %d %d %d con_reset_fix_failed",
- sock->pending_recv, sock->pending_send,
- sock->references);
- closesocket(sock->fd);
- _set_state(sock, SOCK_CLOSED);
- sock->fd = INVALID_SOCKET;
- free_socket(&sock, __LINE__);
- return (result);
+#if 0
+ if (dup_socket == NULL) {
+#endif
+ switch (type) {
+ case isc_sockettype_udp:
+ sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock->fd != INVALID_SOCKET) {
+ result = connection_reset_fix(sock->fd);
+ if (result != ISC_R_SUCCESS) {
+ socket_log(__LINE__, sock,
+ NULL, EVENT, NULL, 0, 0,
+ "closed %d %d %d "
+ "con_reset_fix_failed",
+ sock->pending_recv,
+ sock->pending_send,
+ sock->references);
+ closesocket(sock->fd);
+ _set_state(sock, SOCK_CLOSED);
+ sock->fd = INVALID_SOCKET;
+ free_socket(&sock, __LINE__);
+ return (result);
+ }
}
+ break;
+ case isc_sockettype_tcp:
+ sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
+ break;
}
- break;
- case isc_sockettype_tcp:
- sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
- break;
+#if 0
+ } else {
+ /*
+ * XXX: dup() is deprecated in windows, use _dup()
+ * instead. In future we may want to investigate
+ * WSADuplicateSocket().
+ */
+ sock->fd = _dup(dup_socket->fd);
+ sock->dupped = 1;
+ sock->bound = dup_socket->bound;
}
+#endif
if (sock->fd == INVALID_SOCKET) {
socket_errno = WSAGetLastError();
@@ -1689,7 +1747,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
/* 2292bis */
if ((pf == AF_INET6)
&& (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
- (void *)&on, sizeof(on)) < 0)) {
+ (char *)&on, sizeof(on)) < 0)) {
isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"setsockopt(%d, IPV6_RECVPKTINFO) "
@@ -1704,7 +1762,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
/* 2292 */
if ((pf == AF_INET6)
&& (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO,
- (void *)&on, sizeof(on)) < 0)) {
+ (char *)&on, sizeof(on)) < 0)) {
isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"setsockopt(%d, IPV6_PKTINFO) %s: %s",
@@ -1721,7 +1779,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
if (pf == AF_INET6) {
(void)setsockopt(sock->fd, IPPROTO_IPV6,
IPV6_USE_MIN_MTU,
- (void *)&on, sizeof(on));
+ (char *)&on, sizeof(on));
}
#endif
#endif /* ISC_PLATFORM_HAVEIPV6 */
@@ -1730,11 +1788,11 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
#if defined(SO_RCVBUF)
optlen = sizeof(size);
if (getsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
- (void *)&size, &optlen) >= 0 &&
+ (char *)&size, &optlen) >= 0 &&
size < RCVBUFSIZE) {
size = RCVBUFSIZE;
(void)setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
- (void *)&size, sizeof(size));
+ (char *)&size, sizeof(size));
}
#endif
@@ -1756,13 +1814,34 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
InterlockedIncrement(&manager->totalSockets);
UNLOCK(&manager->lock);
- socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
- ISC_MSG_CREATED, "created %u type %u", sock->fd, type);
+ socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat,
+ ISC_MSGSET_SOCKET, ISC_MSG_CREATED,
+ "created %u type %u", sock->fd, type);
return (ISC_R_SUCCESS);
}
isc_result_t
+isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+ isc_socket_t **socketp)
+{
+ return (socket_create(manager, pf, type, socketp, NULL));
+}
+
+isc_result_t
+isc__socket_dup(isc_socket_t *sock, isc_socket_t **socketp) {
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(socketp != NULL && *socketp == NULL);
+
+#if 1
+ return (ISC_R_NOTIMPLEMENTED);
+#else
+ return (socket_create(sock->manager, sock->pf, sock->type,
+ socketp, sock));
+#endif
+}
+
+isc_result_t
isc_socket_open(isc_socket_t *sock) {
REQUIRE(VALID_SOCKET(sock));
REQUIRE(sock->type != isc_sockettype_fdwatch);
@@ -1774,7 +1853,7 @@ isc_socket_open(isc_socket_t *sock) {
* Attach to a socket. Caller must explicitly detach when it is done.
*/
void
-isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
+isc__socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
REQUIRE(VALID_SOCKET(sock));
REQUIRE(socketp != NULL && *socketp == NULL);
@@ -1791,7 +1870,7 @@ isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
* up by destroying the socket.
*/
void
-isc_socket_detach(isc_socket_t **socketp) {
+isc__socket_detach(isc_socket_t **socketp) {
isc_socket_t *sock;
isc_boolean_t kill_socket = ISC_FALSE;
@@ -1990,7 +2069,7 @@ internal_accept(isc_socket_t *sock, IoCompletionInfo *lpo, int accept_errno) {
INSIST(result == ISC_R_SUCCESS);
INSIST(setsockopt(nsock->fd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
- (char *)&sock->fd, sizeof(sock->fd)) == 0);
+ (char *)&sock->fd, sizeof(sock->fd)) == 0);
/*
* Hook it up into the manager.
@@ -2096,7 +2175,8 @@ internal_connect(isc_socket_t *sock, IoCompletionInfo *lpo, int connect_errno) {
strbuf);
}
} else {
- INSIST(setsockopt(sock->fd, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0) == 0);
+ INSIST(setsockopt(sock->fd, SOL_SOCKET,
+ SO_UPDATE_CONNECT_CONTEXT, NULL, 0) == 0);
cdev->result = ISC_R_SUCCESS;
sock->connected = 1;
socket_log(__LINE__, sock, &sock->address, IOEVENT,
@@ -2273,6 +2353,63 @@ connectdone_is_active(isc_socket_t *sock, isc_socket_connev_t *dev)
return (sock->connect_ev == dev ? ISC_TRUE : ISC_FALSE);
}
+//
+// The Windows network stack seems to have two very distinct paths depending
+// on what is installed. Specifically, if something is looking at network
+// connections (like an anti-virus or anti-malware application, such as
+// McAfee products) Windows may return additional error conditions which
+// were not previously returned.
+//
+// One specific one is when a TCP SYN scan is used. In this situation,
+// Windows responds with the SYN-ACK, but the scanner never responds with
+// the 3rd packet, the ACK. Windows consiers this a partially open connection.
+// Most Unix networking stacks, and Windows without McAfee installed, will
+// not return this to the caller. However, with this product installed,
+// Windows returns this as a failed status on the Accept() call. Here, we
+// will just re-issue the ISCAcceptEx() call as if nothing had happened.
+//
+// This code should only be called when the listening socket has received
+// such an error. Additionally, the "parent" socket must be locked.
+// Additionally, the lpo argument is re-used here, and must not be freed
+// by the caller.
+//
+static isc_result_t
+restart_accept(isc_socket_t *parent, IoCompletionInfo *lpo)
+{
+ isc_socket_t *nsock = lpo->adev->newsocket;
+ SOCKET new_fd;
+
+ /*
+ * AcceptEx() requires we pass in a socket. Note that we carefully
+ * do not close the previous socket in case of an error message returned by
+ * our new socket() call. If we return an error here, our caller will
+ * clean up.
+ */
+ new_fd = socket(parent->pf, SOCK_STREAM, IPPROTO_TCP);
+ if (nsock->fd == INVALID_SOCKET) {
+ return (ISC_R_FAILURE); // parent will ask windows for error message
+ }
+ closesocket(nsock->fd);
+ nsock->fd = new_fd;
+
+ memset(&lpo->overlapped, 0, sizeof(lpo->overlapped));
+
+ ISCAcceptEx(parent->fd,
+ nsock->fd, /* Accepted Socket */
+ lpo->acceptbuffer, /* Buffer for initial Recv */
+ 0, /* Length of Buffer */
+ sizeof(SOCKADDR_STORAGE) + 16, /* Local address length + 16 */
+ sizeof(SOCKADDR_STORAGE) + 16, /* Remote address lengh + 16 */
+ (LPDWORD)&lpo->received_bytes, /* Bytes Recved */
+ (LPOVERLAPPED)lpo /* Overlapped structure */
+ );
+
+ InterlockedDecrement(&nsock->manager->iocp_total);
+ iocompletionport_update(nsock);
+
+ return (ISC_R_SUCCESS);
+}
+
/*
* This is the I/O Completion Port Worker Function. It loops forever
* waiting for I/O to complete and then forwards them for further
@@ -2313,6 +2450,7 @@ SocketIoThread(LPVOID ThreadContext) {
* Loop forever waiting on I/O Completions and then processing them
*/
while (TRUE) {
+ wait_again:
bSuccess = GetQueuedCompletionStatus(manager->hIoCompletionPort,
&nbytes, (LPDWORD)&sock,
(LPWSAOVERLAPPED *)&lpo,
@@ -2331,7 +2469,7 @@ SocketIoThread(LPVOID ThreadContext) {
/*
* Did the I/O operation complete?
*/
- errstatus = WSAGetLastError();
+ errstatus = GetLastError();
isc_result = isc__errno2resultx(errstatus, __FILE__, __LINE__);
LOCK(&sock->lock);
@@ -2342,6 +2480,14 @@ SocketIoThread(LPVOID ThreadContext) {
sock->pending_iocp--;
INSIST(sock->pending_recv > 0);
sock->pending_recv--;
+ if (!sock->connected &&
+ ((errstatus == ERROR_HOST_UNREACHABLE) ||
+ (errstatus == WSAENETRESET) ||
+ (errstatus == WSAECONNRESET))) {
+ /* ignore soft errors */
+ queue_receive_request(sock);
+ break;
+ }
send_recvdone_abort(sock, isc_result);
if (isc_result == ISC_R_UNEXPECTED) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
@@ -2365,8 +2511,25 @@ SocketIoThread(LPVOID ThreadContext) {
case SOCKET_ACCEPT:
INSIST(sock->pending_iocp > 0);
- sock->pending_iocp--;
INSIST(sock->pending_accept > 0);
+
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "Accept: errstatus=%d isc_result=%d", errstatus, isc_result);
+
+ if (acceptdone_is_active(sock, lpo->adev)) {
+ if (restart_accept(sock, lpo) == ISC_R_SUCCESS) {
+ UNLOCK(&sock->lock);
+ goto wait_again;
+ } else {
+ errstatus = GetLastError();
+ isc_result = isc__errno2resultx(errstatus, __FILE__, __LINE__);
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "restart_accept() failed: errstatus=%d isc_result=%d",
+ errstatus, isc_result);
+ }
+ }
+
+ sock->pending_iocp--;
sock->pending_accept--;
if (acceptdone_is_active(sock, lpo->adev)) {
closesocket(lpo->adev->newsocket->fd);
@@ -2434,13 +2597,13 @@ SocketIoThread(LPVOID ThreadContext) {
* Create a new socket manager.
*/
isc_result_t
-isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
+isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
return (isc_socketmgr_create2(mctx, managerp, 0));
}
isc_result_t
-isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
- unsigned int maxsocks)
+isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
+ unsigned int maxsocks)
{
isc_socketmgr_t *manager;
isc_result_t result;
@@ -2489,7 +2652,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
}
isc_result_t
-isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) {
+isc__socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) {
REQUIRE(VALID_MANAGER(manager));
REQUIRE(nsockp != NULL);
@@ -2497,7 +2660,7 @@ isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) {
}
void
-isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) {
+isc__socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) {
REQUIRE(VALID_MANAGER(manager));
REQUIRE(ISC_LIST_EMPTY(manager->socklist));
REQUIRE(manager->stats == NULL);
@@ -2507,7 +2670,7 @@ isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) {
}
void
-isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
+isc__socketmgr_destroy(isc_socketmgr_t **managerp) {
isc_socketmgr_t *manager;
int i;
isc_mem_t *mctx;
@@ -2635,7 +2798,7 @@ socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
}
isc_result_t
-isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+isc__socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
unsigned int minimum, isc_task_t *task,
isc_taskaction_t action, const void *arg)
{
@@ -2705,8 +2868,9 @@ isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
}
isc_result_t
-isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
- isc_task_t *task, isc_taskaction_t action, const void *arg)
+isc__socket_recv(isc_socket_t *sock, isc_region_t *region,
+ unsigned int minimum, isc_task_t *task,
+ isc_taskaction_t action, const void *arg)
{
isc_socketevent_t *dev;
isc_socketmgr_t *manager;
@@ -2742,9 +2906,9 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
}
isc_result_t
-isc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
- unsigned int minimum, isc_task_t *task,
- isc_socketevent_t *event, unsigned int flags)
+isc__socket_recv2(isc_socket_t *sock, isc_region_t *region,
+ unsigned int minimum, isc_task_t *task,
+ isc_socketevent_t *event, unsigned int flags)
{
isc_result_t ret;
@@ -2852,8 +3016,8 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
}
isc_result_t
-isc_socket_send(isc_socket_t *sock, isc_region_t *region,
- isc_task_t *task, isc_taskaction_t action, const void *arg)
+isc__socket_send(isc_socket_t *sock, isc_region_t *region,
+ isc_task_t *task, isc_taskaction_t action, const void *arg)
{
/*
* REQUIRE() checking is performed in isc_socket_sendto().
@@ -2863,9 +3027,9 @@ isc_socket_send(isc_socket_t *sock, isc_region_t *region,
}
isc_result_t
-isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
- isc_task_t *task, isc_taskaction_t action, const void *arg,
- isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+isc__socket_sendto(isc_socket_t *sock, isc_region_t *region,
+ isc_task_t *task, isc_taskaction_t action, const void *arg,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
{
isc_socketevent_t *dev;
isc_socketmgr_t *manager;
@@ -2906,17 +3070,17 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
}
isc_result_t
-isc_socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
- isc_task_t *task, isc_taskaction_t action, const void *arg)
+isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+ isc_task_t *task, isc_taskaction_t action, const void *arg)
{
return (isc_socket_sendtov(sock, buflist, task, action, arg, NULL,
NULL));
}
isc_result_t
-isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
- isc_task_t *task, isc_taskaction_t action, const void *arg,
- isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+isc__socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
+ isc_task_t *task, isc_taskaction_t action, const void *arg,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
{
isc_socketevent_t *dev;
isc_socketmgr_t *manager;
@@ -2969,10 +3133,10 @@ isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
}
isc_result_t
-isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
- isc_task_t *task,
- isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
- isc_socketevent_t *event, unsigned int flags)
+isc__socket_sendto2(isc_socket_t *sock, isc_region_t *region,
+ isc_task_t *task,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+ isc_socketevent_t *event, unsigned int flags)
{
isc_result_t ret;
@@ -3004,8 +3168,8 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
}
isc_result_t
-isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
- unsigned int options) {
+isc__socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+ unsigned int options) {
int bind_errno;
char strbuf[ISC_STRERRORSIZE];
int on = 1;
@@ -3023,6 +3187,7 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
}
INSIST(!sock->bound);
+ INSIST(!sock->dupped);
if (sock->pf != sockaddr->type.sa.sa_family) {
UNLOCK(&sock->lock);
@@ -3033,7 +3198,7 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
*/
if ((options & ISC_SOCKET_REUSEADDRESS) != 0 &&
isc_sockaddr_getport(sockaddr) != (in_port_t)0 &&
- setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
+ setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
sizeof(on)) < 0) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"setsockopt(%d) %s", sock->fd,
@@ -3070,7 +3235,7 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
}
isc_result_t
-isc_socket_filter(isc_socket_t *sock, const char *filter) {
+isc__socket_filter(isc_socket_t *sock, const char *filter) {
UNUSED(sock);
UNUSED(filter);
@@ -3089,7 +3254,7 @@ isc_socket_filter(isc_socket_t *sock, const char *filter) {
* as well keep things simple rather than having to track them.
*/
isc_result_t
-isc_socket_listen(isc_socket_t *sock, unsigned int backlog) {
+isc__socket_listen(isc_socket_t *sock, unsigned int backlog) {
char strbuf[ISC_STRERRORSIZE];
REQUIRE(VALID_SOCKET(sock));
@@ -3134,8 +3299,8 @@ isc_socket_listen(isc_socket_t *sock, unsigned int backlog) {
* This should try to do aggressive accept() XXXMLG
*/
isc_result_t
-isc_socket_accept(isc_socket_t *sock,
- isc_task_t *task, isc_taskaction_t action, const void *arg)
+isc__socket_accept(isc_socket_t *sock,
+ isc_task_t *task, isc_taskaction_t action, const void *arg)
{
isc_socket_newconnev_t *adev;
isc_socketmgr_t *manager;
@@ -3198,6 +3363,13 @@ isc_socket_accept(isc_socket_t *sock,
* Attach to socket and to task.
*/
isc_task_attach(task, &ntask);
+ if (isc_task_exiting(ntask)) {
+ free_socket(&nsock, __LINE__);
+ isc_task_detach(&ntask);
+ isc_event_free(ISC_EVENT_PTR(&adev));
+ UNLOCK(&sock->lock);
+ return (ISC_R_SHUTTINGDOWN);
+ }
nsock->references++;
adev->ev_sender = ntask;
@@ -3245,8 +3417,8 @@ isc_socket_accept(isc_socket_t *sock,
}
isc_result_t
-isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
- isc_task_t *task, isc_taskaction_t action, const void *arg)
+isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
+ isc_task_t *task, isc_taskaction_t action, const void *arg)
{
char strbuf[ISC_STRERRORSIZE];
isc_socket_connev_t *cdev;
@@ -3360,7 +3532,7 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
}
isc_result_t
-isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+isc__socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) {
isc_result_t result;
REQUIRE(VALID_SOCKET(sock));
@@ -3390,7 +3562,7 @@ isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) {
}
isc_result_t
-isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+isc__socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
ISC_SOCKADDR_LEN_T len;
isc_result_t result;
char strbuf[ISC_STRERRORSIZE];
@@ -3437,7 +3609,7 @@ isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
* queued for task "task" of type "how". "how" is a bitmask.
*/
void
-isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
+isc__socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
REQUIRE(VALID_SOCKET(sock));
@@ -3563,7 +3735,7 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
}
isc_sockettype_t
-isc_socket_gettype(isc_socket_t *sock) {
+isc__socket_gettype(isc_socket_t *sock) {
isc_sockettype_t type;
REQUIRE(VALID_SOCKET(sock));
@@ -3584,7 +3756,7 @@ isc_socket_gettype(isc_socket_t *sock) {
}
isc_boolean_t
-isc_socket_isbound(isc_socket_t *sock) {
+isc__socket_isbound(isc_socket_t *sock) {
isc_boolean_t val;
REQUIRE(VALID_SOCKET(sock));
@@ -3607,7 +3779,7 @@ isc_socket_isbound(isc_socket_t *sock) {
}
void
-isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
+isc__socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
#if defined(IPV6_V6ONLY)
int onoff = yes ? 1 : 0;
#else
@@ -3619,20 +3791,20 @@ isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
#ifdef IPV6_V6ONLY
if (sock->pf == AF_INET6) {
(void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY,
- (void *)&onoff, sizeof(onoff));
+ (char *)&onoff, sizeof(onoff));
}
#endif
}
void
-isc_socket_cleanunix(isc_sockaddr_t *addr, isc_boolean_t active) {
+isc__socket_cleanunix(isc_sockaddr_t *addr, isc_boolean_t active) {
UNUSED(addr);
UNUSED(active);
}
isc_result_t
-isc_socket_permunix(isc_sockaddr_t *addr, isc_uint32_t perm,
- isc_uint32_t owner, isc_uint32_t group)
+isc__socket_permunix(isc_sockaddr_t *addr, isc_uint32_t perm,
+ isc_uint32_t owner, isc_uint32_t group)
{
UNUSED(addr);
UNUSED(perm);
@@ -3642,7 +3814,7 @@ isc_socket_permunix(isc_sockaddr_t *addr, isc_uint32_t perm,
}
void
-isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) {
+isc__socket_setname(isc_socket_t *socket, const char *name, void *tag) {
/*
* Name 'socket'.
@@ -3658,17 +3830,138 @@ isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) {
}
const char *
-isc_socket_getname(isc_socket_t *socket) {
+isc__socket_getname(isc_socket_t *socket) {
return (socket->name);
}
void *
-isc_socket_gettag(isc_socket_t *socket) {
+isc__socket_gettag(isc_socket_t *socket) {
return (socket->tag);
}
+int
+isc__socket_getfd(isc_socket_t *socket) {
+ return ((short) socket->fd);
+}
+
void
isc__socketmgr_setreserved(isc_socketmgr_t *manager, isc_uint32_t reserved) {
UNUSED(manager);
UNUSED(reserved);
}
+
+void
+isc___socketmgr_maxudp(isc_socketmgr_t *manager, int maxudp) {
+
+ UNUSED(manager);
+ UNUSED(maxudp);
+}
+
+#ifdef HAVE_LIBXML2
+
+static const char *
+_socktype(isc_sockettype_t type)
+{
+ if (type == isc_sockettype_udp)
+ return ("udp");
+ else if (type == isc_sockettype_tcp)
+ return ("tcp");
+ else if (type == isc_sockettype_unix)
+ return ("unix");
+ else if (type == isc_sockettype_fdwatch)
+ return ("fdwatch");
+ else
+ return ("not-initialized");
+}
+
+void
+isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer)
+{
+ isc_socket_t *sock;
+ char peerbuf[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_t addr;
+ ISC_SOCKADDR_LEN_T len;
+
+ LOCK(&mgr->lock);
+
+#ifndef ISC_PLATFORM_USETHREADS
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
+ xmlTextWriterWriteFormatString(writer, "%d", mgr->refs);
+ xmlTextWriterEndElement(writer);
+#endif
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "sockets");
+ sock = ISC_LIST_HEAD(mgr->socklist);
+ while (sock != NULL) {
+ LOCK(&sock->lock);
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "socket");
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "id");
+ xmlTextWriterWriteFormatString(writer, "%p", sock);
+ xmlTextWriterEndElement(writer);
+
+ if (sock->name[0] != 0) {
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+ xmlTextWriterWriteFormatString(writer, "%s",
+ sock->name);
+ xmlTextWriterEndElement(writer); /* name */
+ }
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
+ xmlTextWriterWriteFormatString(writer, "%d", sock->references);
+ xmlTextWriterEndElement(writer);
+
+ xmlTextWriterWriteElement(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR _socktype(sock->type));
+
+ if (sock->connected) {
+ isc_sockaddr_format(&sock->address, peerbuf,
+ sizeof(peerbuf));
+ xmlTextWriterWriteElement(writer,
+ ISC_XMLCHAR "peer-address",
+ ISC_XMLCHAR peerbuf);
+ }
+
+ len = sizeof(addr);
+ if (getsockname(sock->fd, &addr.type.sa, (void *)&len) == 0) {
+ isc_sockaddr_format(&addr, peerbuf, sizeof(peerbuf));
+ xmlTextWriterWriteElement(writer,
+ ISC_XMLCHAR "local-address",
+ ISC_XMLCHAR peerbuf);
+ }
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "states");
+ if (sock->pending_recv)
+ xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+ ISC_XMLCHAR "pending-receive");
+ if (sock->pending_send)
+ xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+ ISC_XMLCHAR "pending-send");
+ if (sock->pending_accept)
+ xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+ ISC_XMLCHAR "pending_accept");
+ if (sock->listener)
+ xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+ ISC_XMLCHAR "listener");
+ if (sock->connected)
+ xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+ ISC_XMLCHAR "connected");
+ if (sock->pending_connect)
+ xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+ ISC_XMLCHAR "connecting");
+ if (sock->bound)
+ xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+ ISC_XMLCHAR "bound");
+
+ xmlTextWriterEndElement(writer); /* states */
+
+ xmlTextWriterEndElement(writer); /* socket */
+
+ UNLOCK(&sock->lock);
+ sock = ISC_LIST_NEXT(sock, link);
+ }
+ xmlTextWriterEndElement(writer); /* sockets */
+
+ UNLOCK(&mgr->lock);
+}
+#endif /* HAVE_LIBXML2 */