diff options
Diffstat (limited to 'lib/isc/win32/socket.c')
-rw-r--r-- | lib/isc/win32/socket.c | 483 |
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 */ |