diff --git a/lib/isc/win32/socket.c b/lib/isc/win32/socket.c index afd51fa235..ecbea80162 100644 --- a/lib/isc/win32/socket.c +++ b/lib/isc/win32/socket.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket.c,v 1.6 2001/09/16 06:19:22 mayer Exp $ */ +/* $Id: socket.c,v 1.7 2001/11/07 04:24:38 mayer Exp $ */ #define MAKE_EXTERNAL 1 @@ -27,8 +27,6 @@ #define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */ #endif -#include "errno2result.h" - #include #include #include @@ -50,10 +48,12 @@ #include #include #include +#include #include #include #include +#include "errno2result.h" /* * Some systems define the socket length argument as an int, some as size_t, * some as socklen_t. This is here so it can be easily changed if needed. @@ -70,9 +70,11 @@ * from recv() but will have errno==0. This is broken, but we have to * work around it here. */ -#define SOFT_ERROR(e) ((e) == EAGAIN || \ +#define SOFT_ERROR(e) ((e) == WSAEINTR || \ (e) == WSAEWOULDBLOCK || \ - (e) == WSAEINTR || \ + (e) == EWOULDBLOCK || \ + (e) == EINTR || \ + (e) == EAGAIN || \ (e) == 0) #define DLVL(x) ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(x) @@ -98,8 +100,8 @@ typedef isc_event_t intev_t; -#define SOCKET_MAGIC 0x494f696fU /* IOio */ -#define VALID_SOCKET(t) ((t) != NULL && (t)->magic == SOCKET_MAGIC) +#define SOCKET_MAGIC ISC_MAGIC('I', 'O', 'i', 'o') +#define VALID_SOCKET(t) ISC_MAGIC_VALID(t, SOCKET_MAGIC) /* * IPv6 control information. If the socket is an IPv6 socket we want @@ -156,6 +158,11 @@ struct msghdr { int msg_flags; /* flags on received message */ } msghdr; +/* + * The number of times a send operation is repeated if the result is EINTR. + */ +#define NRETRIES 10 + struct isc_socket { /* Not locked. */ unsigned int magic; @@ -197,9 +204,9 @@ struct isc_socket { #endif }; -#define SOCKET_MANAGER_MAGIC 0x494f6d67U /* IOmg */ -#define VALID_MANAGER(m) ((m) != NULL && \ - (m)->magic == SOCKET_MANAGER_MAGIC) +#define SOCKET_MANAGER_MAGIC ISC_MAGIC('I', 'O', 'm', 'g') +#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, SOCKET_MANAGER_MAGIC) + struct isc_socketmgr { /* Not locked. */ unsigned int magic; @@ -209,6 +216,7 @@ struct isc_socketmgr { ISC_LIST(isc_socket_t) socklist; fd_set read_fds; fd_set write_fds; + fd_set except_fds; isc_socket_t *fds[FD_SETSIZE]; int fdstate[FD_SETSIZE]; int maxfd; @@ -256,8 +264,8 @@ static void build_msghdr_recv(isc_socket_t *, isc_socketevent_t *, #define SELECT_POKE_READ (-3) #define SELECT_POKE_ACCEPT (-3) /* Same as _READ */ #define SELECT_POKE_WRITE (-4) -#define SELECT_POKE_CONNECT (-4) /* Same as _WRITE */ -#define SELECT_POKE_CLOSE (-5) +#define SELECT_POKE_CONNECT (-5) +#define SELECT_POKE_CLOSE (-6) long bpipe_written = 0; @@ -315,21 +323,21 @@ internal_sendmsg(int sock, const struct msghdr *msg, int flags) { NULL, NULL); - if (Error == SOCKET_ERROR) { - BytesSent = -1; - /* There is an error... */ - Error = WSAGetLastError(); - if (Error == WSA_IO_PENDING) { + if (Error == SOCKET_ERROR) { + BytesSent = -1; + /* There is an error... */ + Error = WSAGetLastError(); + if (Error == WSA_IO_PENDING) { /* Overlapped send successfully initiated. */ errno = EAGAIN; - } else { - /* An unexpected error occurred. */ - errno = Error; - } - } + } else { + /* An unexpected error occurred. */ + errno = Error; + } + } - /* No error -- the I/O request was completed immediately... */ - return (BytesSent); + /* No error -- the I/O request was completed immediately... */ + return (BytesSent); } int @@ -394,6 +402,11 @@ manager_log(isc_socketmgr_t *sockmgr, "sockmgr %p: %s", sockmgr, msgbuf); } +static void +socket_log(isc_socket_t *sock, isc_sockaddr_t *address, + isc_logcategory_t *category, isc_logmodule_t *module, int level, + isc_msgcat_t *msgcat, int msgset, int message, + const char *fmt, ...) ISC_FORMAT_PRINTF(9, 10); static void socket_log(isc_socket_t *sock, isc_sockaddr_t *address, isc_logcategory_t *category, isc_logmodule_t *module, int level, @@ -432,12 +445,14 @@ wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) { * process of being closed, start watching it for either reads * or writes. */ - INSIST(fd < FD_SETSIZE); + + INSIST(fd >= 0 && fd < FD_SETSIZE); if (manager->fdstate[fd] == CLOSE_PENDING) { manager->fdstate[fd] = CLOSED; FD_CLR(fd, &manager->read_fds); FD_CLR(fd, &manager->write_fds); + FD_CLR(fd, &manager->except_fds); closesocket(fd); return; } @@ -455,6 +470,10 @@ wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) { FD_SET(sock->fd, &manager->read_fds); if (msg == SELECT_POKE_WRITE) FD_SET(sock->fd, &manager->write_fds); + if (msg == SELECT_POKE_CONNECT) { /* Need both here */ + FD_SET(sock->fd, &manager->write_fds); + FD_SET(sock->fd, &manager->except_fds); + } } #ifdef ISC_PLATFORM_USETHREADS @@ -467,7 +486,7 @@ static void select_poke(isc_socketmgr_t *mgr, int fd, int msg) { int cc; int buf[2]; - int errval; + char strbuf[ISC_STRERRORSIZE]; buf[0] = fd; buf[1] = msg; @@ -475,17 +494,17 @@ select_poke(isc_socketmgr_t *mgr, int fd, int msg) { if (msg == SELECT_POKE_SHUTDOWN) { do { cc = _write(mgr->pipe_fds[1], buf, sizeof(buf)); - errval = errno; } while (cc < 0 && SOFT_ERROR(errno)); - if (cc < 0) + if (cc < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); FATAL_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_SOCKET, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_WRITEFAILED, - "_write() failed " + "write() failed " "during watcher poke: %s"), - strerror(errno)); + strbuf); + } INSIST(cc == sizeof(buf)); @@ -502,6 +521,7 @@ static void select_readmsg(isc_socketmgr_t *mgr, int *fd, int *msg) { int buf[2]; int cc; + char strbuf[ISC_STRERRORSIZE]; cc = _read(mgr->pipe_fds[0], buf, sizeof(buf)); if (cc < 0) { @@ -509,12 +529,14 @@ select_readmsg(isc_socketmgr_t *mgr, int *fd, int *msg) { if (SOFT_ERROR(errno)) return; + isc__strerror(errno, strbuf, sizeof(strbuf)); FATAL_ERROR(__FILE__, __LINE__, isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_READFAILED, - "_read() failed " + "read() failed " "during watcher poke: %s"), - strerror(errno)); + strbuf); + return; } INSIST(cc == sizeof(buf)); @@ -543,14 +565,16 @@ static isc_result_t make_nonblock(int fd) { int ret; unsigned long flags = 1; + char strbuf[ISC_STRERRORSIZE]; /* Set the socket to non-blocking */ ret = ioctlsocket((SOCKET) fd, FIONBIO, &flags); if (ret == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "ioctlsocket(%d, FIOBIO, %d): %s", - fd, flags, strerror(errno)); + fd, flags, strbuf); return (ISC_R_UNEXPECTED); } @@ -598,12 +622,6 @@ process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) { dev->attributes |= ISC_SOCKEVENTATTR_CTRUNC; #endif - /* - * Check for multicast. - */ - if (isc_sockaddr_ismulticast(&dev->address)) - dev->attributes |= ISC_SOCKEVENTATTR_MULTICAST; - #ifndef USE_CMSG return; #else @@ -636,6 +654,8 @@ process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) { ISC_MSG_IFRECEIVED, "interface received on ifindex %u", dev->pktinfo.ipi6_ifindex); + if (IN6_IS_ADDR_MULTICAST(&pktinfop->ipi6_addr)) + dev->attributes |= ISC_SOCKEVENTATTR_MULTICAST; goto next; } #endif @@ -752,7 +772,7 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev, msg->msg_control = NULL; msg->msg_controllen = 0; msg->msg_flags = 0; -#ifdef USE_CMSG +#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIPV6) if ((sock->type == isc_sockettype_udp) && ((dev->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0)) { struct cmsghdr *cmsgp; @@ -773,7 +793,7 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev, pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp); memcpy(pktinfop, &dev->pktinfo, sizeof(struct in6_pktinfo)); } -#endif /* USE_CMSG */ +#endif /* USE_CMSG && ISC_PLATFORM_HAVEIPV6 */ #endif /* ISC_NET_BSD44MSGHDR */ if (write_countp != NULL) @@ -833,10 +853,8 @@ build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev, iov[0].buf = (void *)(dev->region.base + dev->n); iov[0].len = read_count; iovcount = 1; - } else { - /* * Multibuffer I/O. * Skip empty buffers. @@ -968,11 +986,13 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { size_t actual_count; struct msghdr msghdr; isc_buffer_t *buffer; + int recv_errno; #if USE_CMSG char cmsg[CMSG_BUF_SIZE]; #else char *cmsg = NULL; #endif + char strbuf[ISC_STRERRORSIZE]; build_msghdr_recv(sock, dev, &msghdr, cmsg, iov, &read_count); @@ -981,21 +1001,23 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { #endif cc = internal_recvmsg(sock->fd, &msghdr, 0); + recv_errno = WSAGetLastError(); if (cc < 0) { - if (SOFT_ERROR(errno)) + if (SOFT_ERROR(recv_errno)) return (DOIO_SOFT); - if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) + if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) { + isc__strerror(recv_errno, strbuf, sizeof(strbuf)); socket_log(sock, NULL, IOEVENT, isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_DOIORECV, - "doio_recv: internal_recvmsg(%d) %d bytes, " - "err %d/%s", - sock->fd, cc, errno, NTstrerror(errno)); + "doio_recv: recvmsg(%d) %d bytes, err %d/%s", + sock->fd, cc, recv_errno, strbuf); + } #define SOFT_OR_HARD(_system, _isc) \ - if (errno == _system) { \ + if (recv_errno == _system) { \ if (sock->connected) { \ dev->result = _isc; \ return (DOIO_HARD); \ @@ -1003,7 +1025,7 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { return (DOIO_SOFT); \ } #define ALWAYS_HARD(_system, _isc) \ - if (errno == _system) { \ + if (recv_errno == _system) { \ dev->result = _isc; \ return (DOIO_HARD); \ } @@ -1020,7 +1042,7 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { #undef SOFT_OR_HARD #undef ALWAYS_HARD - dev->result = ISC_R_UNEXPECTED; + dev->result = isc__errno2result(recv_errno); return (DOIO_HARD); } @@ -1120,20 +1142,28 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) { #else char *cmsg = NULL; #endif + int attempts = 0; + int send_errno; + char strbuf[ISC_STRERRORSIZE]; build_msghdr_send(sock, dev, &msghdr, cmsg, iov, &write_count); +resend: cc = internal_sendmsg(sock->fd, &msghdr, 0); + send_errno = WSAGetLastError(); /* * Check for error or block condition. */ if (cc < 0) { - if (SOFT_ERROR(errno)) + if (send_errno == WSAEINTR && ++attempts < NRETRIES) + goto resend; + + if (SOFT_ERROR(send_errno)) return (DOIO_SOFT); #define SOFT_OR_HARD(_system, _isc) \ - if (errno == _system) { \ + if (send_errno == _system) { \ if (sock->connected) { \ dev->result = _isc; \ return (DOIO_HARD); \ @@ -1141,7 +1171,7 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) { return (DOIO_SOFT); \ } #define ALWAYS_HARD(_system, _isc) \ - if (errno == _system) { \ + if (send_errno == _system) { \ dev->result = _isc; \ return (DOIO_HARD); \ } @@ -1174,10 +1204,10 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) { * a status. */ isc_sockaddr_format(&dev->address, addrbuf, sizeof(addrbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "internal_send: %s: %s", - addrbuf, strerror(errno)); - dev->result = ISC_R_UNEXPECTED; + isc__strerror(send_errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, "internal_send: %s: %s", + addrbuf, strbuf); + dev->result = isc__errno2result(send_errno); return (DOIO_HARD); } @@ -1220,6 +1250,7 @@ destroy(isc_socket_t **sockp) { INSIST(ISC_LIST_EMPTY(sock->recv_list)); INSIST(ISC_LIST_EMPTY(sock->send_list)); INSIST(sock->connect_ev == NULL); + REQUIRE(sock->fd >= 0 && sock->fd < FD_SETSIZE); LOCK(&manager->lock); @@ -1356,13 +1387,14 @@ free_socket(isc_socket_t **socketp) { */ isc_result_t isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, - isc_socket_t **socketp) -{ + isc_socket_t **socketp) { isc_socket_t *sock = NULL; isc_result_t ret; #if defined(USE_CMSG) || defined(SO_BSDCOMPAT) int on = 1; #endif + int socket_errno; + char strbuf[ISC_STRERRORSIZE]; REQUIRE(VALID_MANAGER(manager)); REQUIRE(socketp != NULL && *socketp == NULL); @@ -1380,28 +1412,41 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP); break; } + + if (sock->fd >= FD_SETSIZE) { + (void)closesocket(sock->fd); + isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, + isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_TOOMANYFDS, + "%s: too many open file descriptors", "socket"); + free_socket(&sock); + return (ISC_R_NORESOURCES); + } + if (sock->fd < 0) { + socket_errno = WSAGetLastError(); free_socket(&sock); - switch (errno) { - case EMFILE: - case ENFILE: - case ENOBUFS: + switch (socket_errno) { + case WSAEMFILE: + case WSAENOBUFS: return (ISC_R_NORESOURCES); - case EPROTONOSUPPORT: - case EPFNOSUPPORT: - case EAFNOSUPPORT: + case WSAEPROTONOSUPPORT: + case WSAEPFNOSUPPORT: + case WSAEAFNOSUPPORT: return (ISC_R_FAMILYNOSUPPORT); default: + isc__strerror(socket_errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "socket() %s: %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed"), - strerror(errno)); + strbuf); return (ISC_R_UNEXPECTED); } } @@ -1414,12 +1459,14 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, #ifdef SO_BSDCOMPAT if (setsockopt(sock->fd, SOL_SOCKET, SO_BSDCOMPAT, (void *)&on, sizeof on) < 0) { + socket_errno = WSAGetLastError(); + isc__strerror(socket_errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "setsockopt(%d, SO_BSDCOMPAT) %s: %s", sock->fd, isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed"), - strerror(errno)); + strbuf); /* Press on... */ } #endif @@ -1430,7 +1477,8 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, #if defined(SO_TIMESTAMP) if (setsockopt(sock->fd, SOL_SOCKET, SO_TIMESTAMP, (void *)&on, sizeof on) < 0 - && errno != ENOPROTOOPT) { + && WSAGetLastError() != WSAENOPROTOOPT) { + isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "setsockopt(%d, SO_TIMESTAMP) %s: %s", sock->fd, @@ -1438,7 +1486,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed"), - strerror(errno)); + strbuf); /* Press on... */ } #endif /* SO_TIMESTAMP */ @@ -1449,6 +1497,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, if ((pf == AF_INET6) && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, (void *)&on, sizeof (on)) < 0)) { + isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "setsockopt(%d, IPV6_RECVPKTINFO) " "%s: %s", sock->fd, @@ -1456,13 +1505,14 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed"), - strerror(errno)); + strbuf); } #else /* 2292 */ if ((pf == AF_INET6) && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO, (void *)&on, sizeof (on)) < 0)) { + isc__strerror(WSAGetLaastError(), strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "setsockopt(%d, IPV6_PKTINFO) %s: %s", sock->fd, @@ -1470,7 +1520,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed"), - strerror(errno)); + strbuf); } #endif /* IPV6_RECVPKTINFO */ #ifdef IPV6_USE_MIN_MTU /*2292bis, not too common yet*/ @@ -1730,6 +1780,8 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { ISC_SOCKADDR_LEN_T addrlen; int fd; isc_result_t result = ISC_R_SUCCESS; + int accept_errno; + char strbuf[ISC_STRERRORSIZE]; UNUSED(me); @@ -1776,16 +1828,18 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { fd = accept(sock->fd, &dev->newsocket->address.type.sa, (void *)&addrlen); if (fd < 0) { - if (SOFT_ERROR(errno)) { + accept_errno = WSAGetLastError(); + if (SOFT_ERROR(accept_errno) || accept_errno == WSAECONNRESET) { goto soft_error; } else { + isc__strerror(accept_errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "internal_accept: accept() %s: %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed"), - strerror(errno)); + strbuf); fd = -1; result = ISC_R_UNEXPECTED; } @@ -1810,6 +1864,15 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { sock->pf); (void)closesocket(fd); goto soft_error; + } else if (fd >= FD_SETSIZE) { + isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, + isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_TOOMANYFDS, + "%s: too many open file descriptors", + "accept"); + (void)closesocket(fd); + goto soft_error; } } @@ -1837,13 +1900,13 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { result = ISC_R_UNEXPECTED; } - LOCK(&manager->lock); - ISC_LIST_APPEND(manager->socklist, dev->newsocket, link); - /* * -1 means the new socket didn't happen. */ if (fd != -1) { + LOCK(&manager->lock); + ISC_LIST_APPEND(manager->socklist, dev->newsocket, link); + dev->newsocket->fd = fd; dev->newsocket->bound = 1; dev->newsocket->connected = 1; @@ -1862,9 +1925,12 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN, "accepted connection, new socket %p", dev->newsocket); - } UNLOCK(&manager->lock); + } else { + dev->newsocket->references--; + free_socket(&dev->newsocket); + } /* * Fill in the done event details and send it off. @@ -1895,7 +1961,7 @@ internal_recv(isc_task_t *me, isc_event_t *ev) { LOCK(&sock->lock); socket_log(sock, NULL, IOEVENT, isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV, - "internal_recv: task %p got event %p", me, ev, sock); + "internal_recv: task %p got event %p", me, ev); INSIST(sock->pending_recv == 1); sock->pending_recv = 0; @@ -1963,7 +2029,7 @@ internal_send(isc_task_t *me, isc_event_t *ev) { LOCK(&sock->lock); socket_log(sock, NULL, IOEVENT, isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND, - "internal_send: task %p got event %p", me, ev, sock); + "internal_send: task %p got event %p", me, ev); INSIST(sock->pending_send == 1); sock->pending_send = 0; @@ -2004,11 +2070,14 @@ internal_send(isc_task_t *me, isc_event_t *ev) { static void process_fds(isc_socketmgr_t *manager, int maxfd, - fd_set *readfds, fd_set *writefds) + fd_set *readfds, fd_set *writefds, fd_set *exceptfds) { int i; isc_socket_t *sock; isc_boolean_t unlock_sock; + BOOL conn_check = FALSE; + + REQUIRE(maxfd <= FD_SETSIZE); /* * Process read/writes on other fds here. Avoid locking @@ -2019,6 +2088,7 @@ process_fds(isc_socketmgr_t *manager, int maxfd, manager->fdstate[i] = CLOSED; FD_CLR(i, &manager->read_fds); FD_CLR(i, &manager->write_fds); + FD_CLR(i, &manager->except_fds); closesocket(i); @@ -2053,13 +2123,37 @@ process_fds(isc_socketmgr_t *manager, int maxfd, LOCK(&sock->lock); } if (!SOCK_DEAD(sock)) { - if (sock->connecting) + if (sock->connecting) { dispatch_connect(sock); + conn_check = TRUE; + } else dispatch_send(sock); } FD_CLR(i, &manager->write_fds); } + if (FD_ISSET(i, exceptfds)) { + if (sock == NULL) { + FD_CLR(i, &manager->except_fds); + continue; + } + if (!unlock_sock) { + unlock_sock = ISC_TRUE; + LOCK(&sock->lock); + } + if (!SOCK_DEAD(sock)) { + if (sock->connecting) { + dispatch_connect(sock); + conn_check = TRUE; + } + } + FD_CLR(i, &manager->write_fds); + FD_CLR(i, &manager->except_fds); + } + +// if(sock != NULL && sock->connecting && conn_check == FALSE) +// dispatch_connect(sock); + if (unlock_sock) UNLOCK(&sock->lock); } @@ -2081,8 +2175,10 @@ watcher(void *uap) { int cc; fd_set readfds; fd_set writefds; + fd_set exceptfds; int msg, fd; int maxfd; + char strbuf[ISC_STRERRORSIZE]; /* 30 Second timeout on select in case it's necesasary */ struct timeval tv; @@ -2100,20 +2196,24 @@ watcher(void *uap) { do { readfds = manager->read_fds; writefds = manager->write_fds; + exceptfds = manager->except_fds; maxfd = manager->maxfd + 1; UNLOCK(&manager->lock); - cc = select(maxfd, &readfds, &writefds, NULL, &tv); + cc = select(maxfd, &readfds, &writefds, &exceptfds, &tv); if (cc < 0) { - if (!SOFT_ERROR(errno)) + if (!SOFT_ERROR(errno)) { + isc__strerror(errno, strbuf, + sizeof(strbuf)); FATAL_ERROR(__FILE__, __LINE__, "select() %s: %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed"), - strerror(errno)); + strbuf); + } } LOCK(&manager->lock); @@ -2152,7 +2252,7 @@ watcher(void *uap) { break; } } - process_fds(manager, maxfd, &readfds, &writefds); + process_fds(manager, maxfd, &readfds, &writefds, &exceptfds); } manager_log(manager, TRACE, @@ -2170,6 +2270,9 @@ watcher(void *uap) { isc_result_t isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { isc_socketmgr_t *manager; +#ifdef ISC_PLATFORM_USETHREADS + char strbuf[ISC_STRERRORSIZE]; +#endif REQUIRE(managerp != NULL && *managerp == NULL); @@ -2214,11 +2317,12 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { if (internal_pipe(manager->pipe_fds) != 0) { DESTROYLOCK(&manager->lock); isc_mem_put(mctx, manager, sizeof *manager); + isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "pipe() %s: %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed"), - strerror(errno)); + strbuf); return (ISC_R_UNEXPECTED); } @@ -2229,6 +2333,7 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { */ FD_ZERO(&manager->read_fds); FD_ZERO(&manager->write_fds); + FD_ZERO(&manager->except_fds); manager->maxfd = 0; memset(manager->fdstate, 0, sizeof(manager->fdstate)); @@ -2565,8 +2670,9 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, case DOIO_SOFT: /* * We couldn't send all or part of the request right now, so - * queue it. + * queue it unless ISC_SOCKFLAG_NORETRY is set. */ + if ((flags & ISC_SOCKFLAG_NORETRY) == 0) { isc_task_attach(task, &ntask); dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED; @@ -2591,6 +2697,7 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0) result = ISC_R_INPROGRESS; break; + } case DOIO_HARD: case DOIO_SUCCESS: @@ -2698,6 +2805,9 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, isc_socketevent_t *event, unsigned int flags) { + REQUIRE((flags & ~(ISC_SOCKFLAG_IMMEDIATE|ISC_SOCKFLAG_NORETRY)) == 0); + if ((flags & ISC_SOCKFLAG_NORETRY) != 0) + REQUIRE(sock->type == isc_sockettype_udp); event->ev_sender = sock; event->result = ISC_R_UNEXPECTED; ISC_LIST_INIT(event->bufferlist); @@ -2711,6 +2821,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) { + int bind_errno; + char strbuf[ISC_STRERRORSIZE]; int on = 1; LOCK(&sock->lock); @@ -2730,19 +2842,21 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr) { /* Press on... */ } if (bind(sock->fd, &sockaddr->type.sa, sockaddr->length) < 0) { + bind_errno = WSAGetLastError(); UNLOCK(&sock->lock); - switch (errno) { - case EACCES: + switch (bind_errno) { + case WSAEACCES: return (ISC_R_NOPERM); - case EADDRNOTAVAIL: + case WSAEADDRNOTAVAIL: return (ISC_R_ADDRNOTAVAIL); - case EADDRINUSE: + case WSAEADDRINUSE: return (ISC_R_ADDRINUSE); - case EINVAL: + case WSAEINVAL: return (ISC_R_BOUND); default: - UNEXPECTED_ERROR(__FILE__, __LINE__, - "bind: %s", strerror(errno)); + isc__strerror(bind_errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, "bind: %s", + strbuf); return (ISC_R_UNEXPECTED); } } @@ -2767,6 +2881,8 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr) { */ isc_result_t isc_socket_listen(isc_socket_t *sock, unsigned int backlog) { + char strbuf[ISC_STRERRORSIZE]; + REQUIRE(VALID_SOCKET(sock)); LOCK(&sock->lock); @@ -2780,8 +2896,9 @@ isc_socket_listen(isc_socket_t *sock, unsigned int backlog) { if (listen(sock->fd, (int)backlog) < 0) { UNLOCK(&sock->lock); - UNEXPECTED_ERROR(__FILE__, __LINE__, "listen: %s", - strerror(errno)); + isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf)); + + UNEXPECTED_ERROR(__FILE__, __LINE__, "listen: %s", strbuf); return (ISC_R_UNEXPECTED); } @@ -2869,6 +2986,8 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, isc_task_t *ntask = NULL; isc_socketmgr_t *manager; int cc; + int errval; + char strbuf[ISC_STRERRORSIZE]; REQUIRE(VALID_SOCKET(sock)); REQUIRE(addr != NULL); @@ -2903,10 +3022,11 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, sock->address = *addr; cc = connect(sock->fd, &addr->type.sa, addr->length); if (cc < 0) { - if (SOFT_ERROR(errno) || errno == EINPROGRESS) + errval = WSAGetLastError(); + if (SOFT_ERROR(errval) || errval == WSAEINPROGRESS) goto queue; - switch (errno) { + switch (errval) { #define ERROR_MATCH(a, b) case a: dev->result = b; goto err_exit; ERROR_MATCH(WSAEACCES, ISC_R_NOPERM); ERROR_MATCH(WSAEADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL); @@ -2923,8 +3043,8 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, sock->connected = 0; - UNEXPECTED_ERROR(__FILE__, __LINE__, "%d/%s", - errno, strerror(errno)); + isc__strerror(errval, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, "%d/%s", errval, strbuf); UNLOCK(&sock->lock); isc_event_free((isc_event_t **)&dev); @@ -2986,6 +3106,8 @@ internal_connect(isc_task_t *me, isc_event_t *ev) { isc_task_t *task; int cc; ISC_SOCKADDR_LEN_T optlen; + int connect_errno; + char strbuf[ISC_STRERRORSIZE]; UNUSED(me); INSIST(ev->ev_type == ISC_SOCKEVENT_INTW); @@ -3026,16 +3148,16 @@ internal_connect(isc_task_t *me, isc_event_t *ev) { optlen = sizeof(cc); if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, (void *)&cc, (void *)&optlen) < 0) - cc = errno; + connect_errno = WSAGetLastError(); else - errno = cc; + connect_errno = cc; - if (errno != 0) { + if (connect_errno != 0) { /* * If the error is EAGAIN, just re-select on this * fd and pretend nothing strange happened. */ - if (SOFT_ERROR(errno) || errno == EINPROGRESS) { + if (SOFT_ERROR(connect_errno) || connect_errno == WSAEINPROGRESS) { sock->connecting = 1; select_poke(sock->manager, sock->fd, SELECT_POKE_CONNECT); @@ -3047,7 +3169,7 @@ internal_connect(isc_task_t *me, isc_event_t *ev) { /* * Translate other errors into ISC_R_* flavors. */ - switch (errno) { + switch (connect_errno) { #define ERROR_MATCH(a, b) case a: dev->result = b; break; ERROR_MATCH(WSAEACCES, ISC_R_NOPERM); ERROR_MATCH(WSAEADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL); @@ -3063,9 +3185,10 @@ internal_connect(isc_task_t *me, isc_event_t *ev) { #undef ERROR_MATCH default: dev->result = ISC_R_UNEXPECTED; + isc__strerror(connect_errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "internal_connect: connect() %s", - strerror(errno)); + strbuf); } } else { dev->result = ISC_R_SUCCESS; @@ -3107,6 +3230,7 @@ isc_result_t isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) { ISC_SOCKADDR_LEN_T len; isc_result_t ret; + char strbuf[ISC_STRERRORSIZE]; REQUIRE(VALID_SOCKET(sock)); REQUIRE(addressp != NULL); @@ -3122,8 +3246,9 @@ isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) { len = sizeof addressp->type; if (getsockname(sock->fd, &addressp->type.sa, (void *)&len) < 0) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "getsockname: %s", strerror(errno)); + isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, "getsockname: %s", + strbuf); ret = ISC_R_UNEXPECTED; goto out; }