diff options
| author | christos <christos@NetBSD.org> | 2004-11-06 23:53:21 +0000 |
|---|---|---|
| committer | christos <christos@NetBSD.org> | 2004-11-06 23:53:21 +0000 |
| commit | dfd98c8a16d53dff0d1bdca29bcddc6571054129 (patch) | |
| tree | 24f3891f470a8e79f037a71c4b43266f23767859 /dist/bind/lib/isc | |
| parent | aefec4290d9fd9e83eaf8b2b4ada33ff37ecaedb (diff) | |
Import bind-9.3.0
Diffstat (limited to 'dist/bind/lib/isc')
| -rw-r--r-- | dist/bind/lib/isc/Makefile.in | 4 | ||||
| -rw-r--r-- | dist/bind/lib/isc/api | 2 | ||||
| -rw-r--r-- | dist/bind/lib/isc/include/isc/result.h | 7 | ||||
| -rw-r--r-- | dist/bind/lib/isc/inet_ntop.c | 5 | ||||
| -rw-r--r-- | dist/bind/lib/isc/lex.c | 5 | ||||
| -rw-r--r-- | dist/bind/lib/isc/log.c | 27 | ||||
| -rw-r--r-- | dist/bind/lib/isc/netaddr.c | 7 | ||||
| -rw-r--r-- | dist/bind/lib/isc/result.c | 9 | ||||
| -rw-r--r-- | dist/bind/lib/isc/sockaddr.c | 12 | ||||
| -rw-r--r-- | dist/bind/lib/isc/unix/Makefile.in | 5 | ||||
| -rw-r--r-- | dist/bind/lib/isc/unix/ifiter_ioctl.c | 39 | ||||
| -rw-r--r-- | dist/bind/lib/isc/unix/interfaceiter.c | 10 | ||||
| -rw-r--r-- | dist/bind/lib/isc/unix/socket.c | 10 | ||||
| -rw-r--r-- | dist/bind/lib/isc/win32/socket.c | 437 |
14 files changed, 331 insertions, 248 deletions
diff --git a/dist/bind/lib/isc/Makefile.in b/dist/bind/lib/isc/Makefile.in index 0c0c65df60c..c7bb871674d 100644 --- a/dist/bind/lib/isc/Makefile.in +++ b/dist/bind/lib/isc/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# Id: Makefile.in,v 1.71.2.2.2.7 2004/03/08 09:04:48 marka Exp +# Id: Makefile.in,v 1.71.2.2.2.8 2004/07/20 07:01:58 marka Exp srcdir = @srcdir@ VPATH = @srcdir@ @@ -94,7 +94,7 @@ libisc.@SA@: ${OBJS} libisc.la: ${OBJS} ${LIBTOOL_MODE_LINK} \ - ${CC} ${ALL_CFLAGS} -o libisc.la -rpath ${libdir} \ + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc.la -rpath ${libdir} \ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ ${OBJS} ${LIBS} diff --git a/dist/bind/lib/isc/api b/dist/bind/lib/isc/api index 75a502768ef..9d7fc51c828 100644 --- a/dist/bind/lib/isc/api +++ b/dist/bind/lib/isc/api @@ -1,3 +1,3 @@ LIBINTERFACE = 10 -LIBREVISION = 0 +LIBREVISION = 4 LIBAGE = 1 diff --git a/dist/bind/lib/isc/include/isc/result.h b/dist/bind/lib/isc/include/isc/result.h index 431c57e643e..33e4ef70309 100644 --- a/dist/bind/lib/isc/include/isc/result.h +++ b/dist/bind/lib/isc/include/isc/result.h @@ -1,4 +1,4 @@ -/* $NetBSD: result.h,v 1.1.1.1 2004/05/17 23:45:04 christos Exp $ */ +/* $NetBSD: result.h,v 1.1.1.2 2004/11/06 23:55:51 christos Exp $ */ /* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") @@ -17,7 +17,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* Id: result.h,v 1.57.2.2.8.4 2004/03/08 09:04:53 marka Exp */ +/* Id: result.h,v 1.57.2.2.8.5 2004/05/15 03:46:13 jinmei Exp */ #ifndef ISC_RESULT_H #define ISC_RESULT_H 1 @@ -84,11 +84,12 @@ #define ISC_R_BADNUMBER 56 /* not a valid number */ #define ISC_R_DISABLED 57 /* disabled */ #define ISC_R_MAXSIZE 58 /* max size */ +#define ISC_R_BADADDRESSFORM 59 /* invalid address format */ /* * Not a result code: the number of results. */ -#define ISC_R_NRESULTS 59 +#define ISC_R_NRESULTS 60 ISC_LANG_BEGINDECLS diff --git a/dist/bind/lib/isc/inet_ntop.c b/dist/bind/lib/isc/inet_ntop.c index af350d36992..85f3d5eb000 100644 --- a/dist/bind/lib/isc/inet_ntop.c +++ b/dist/bind/lib/isc/inet_ntop.c @@ -1,4 +1,4 @@ -/* $NetBSD: inet_ntop.c,v 1.1.1.1 2004/05/17 23:45:02 christos Exp $ */ +/* $NetBSD: inet_ntop.c,v 1.1.1.2 2004/11/06 23:55:49 christos Exp $ */ /* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") @@ -19,7 +19,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char rcsid[] = - "Id: inet_ntop.c,v 1.12.12.3 2004/03/08 09:04:49 marka Exp"; + "Id: inet_ntop.c,v 1.12.12.4 2004/08/28 06:25:21 marka Exp"; #endif /* LIBC_SCCS and not lint */ #include <config.h> @@ -29,6 +29,7 @@ static char rcsid[] = #include <string.h> #include <isc/net.h> +#include <isc/print.h> #define NS_INT16SZ 2 #define NS_IN6ADDRSZ 16 diff --git a/dist/bind/lib/isc/lex.c b/dist/bind/lib/isc/lex.c index 2d9072c39e1..53f5d21ffda 100644 --- a/dist/bind/lib/isc/lex.c +++ b/dist/bind/lib/isc/lex.c @@ -1,4 +1,4 @@ -/* $NetBSD: lex.c,v 1.1.1.1 2004/05/17 23:45:02 christos Exp $ */ +/* $NetBSD: lex.c,v 1.1.1.2 2004/11/06 23:55:49 christos Exp $ */ /* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") @@ -17,7 +17,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* Id: lex.c,v 1.66.2.6.2.7 2004/03/06 08:14:31 marka Exp */ +/* Id: lex.c,v 1.66.2.6.2.8 2004/08/28 06:25:21 marka Exp */ #include <config.h> @@ -31,6 +31,7 @@ #include <isc/mem.h> #include <isc/msgs.h> #include <isc/parseint.h> +#include <isc/print.h> #include <isc/stdio.h> #include <isc/string.h> #include <isc/util.h> diff --git a/dist/bind/lib/isc/log.c b/dist/bind/lib/isc/log.c index 9192bac76f0..777532810c1 100644 --- a/dist/bind/lib/isc/log.c +++ b/dist/bind/lib/isc/log.c @@ -1,4 +1,4 @@ -/* $NetBSD: log.c,v 1.1.1.1 2004/05/17 23:45:02 christos Exp $ */ +/* $NetBSD: log.c,v 1.1.1.2 2004/11/06 23:55:49 christos Exp $ */ /* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") @@ -17,7 +17,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* Id: log.c,v 1.70.2.8.2.10 2004/04/10 04:31:40 marka Exp */ +/* Id: log.c,v 1.70.2.8.2.12 2004/06/11 00:35:38 marka Exp */ /* Principal Authors: DCL */ @@ -1142,6 +1142,10 @@ greatest_version(isc_logchannel_t *channel, int *greatestp) { unsigned int basenamelen; isc_dir_t dir; isc_result_t result; + char sep = '/'; +#ifdef _WIN32 + char *basename2; +#endif REQUIRE(channel->type == ISC_LOG_TOFILE); @@ -1149,7 +1153,15 @@ greatest_version(isc_logchannel_t *channel, int *greatestp) { * It is safe to DE_CONST the file.name because it was copied * with isc_mem_strdup in isc_log_createchannel. */ - basename = strrchr(FILE_NAME(channel), '/'); + basename = strrchr(FILE_NAME(channel), sep); +#ifdef _WIN32 + basename2 = strrchr(FILE_NAME(channel), '\\'); + if ((basename != NULL && basename2 != NULL && basename2 > basename) || + (basename == NULL && basename2 != NULL)) { + basename = basename2; + sep = '\\'; + } +#endif if (basename != NULL) { *basename++ = '\0'; dirname = FILE_NAME(channel); @@ -1166,7 +1178,7 @@ greatest_version(isc_logchannel_t *channel, int *greatestp) { * Replace the file separator if it was taken out. */ if (basename != FILE_NAME(channel)) - *(basename - 1) = '/'; + *(basename - 1) = sep; /* * Return if the directory open failed. @@ -1319,8 +1331,11 @@ isc_log_open(isc_logchannel_t *channel) { if (stat(path, &statbuf) == 0) { regular_file = S_ISREG(statbuf.st_mode) ? ISC_TRUE : ISC_FALSE; /* XXXDCL if not regular_file complain? */ - roll = ISC_TF(regular_file && FILE_MAXSIZE(channel) > 0 && - statbuf.st_size >= FILE_MAXSIZE(channel)); + if ((FILE_MAXSIZE(channel) == 0 && + FILE_VERSIONS(channel) != ISC_LOG_ROLLNEVER) || + (FILE_MAXSIZE(channel) > 0 && + statbuf.st_size >= FILE_MAXSIZE(channel))) + roll = regular_file; } else if (errno == ENOENT) regular_file = ISC_TRUE; else diff --git a/dist/bind/lib/isc/netaddr.c b/dist/bind/lib/isc/netaddr.c index f19890d1166..9d318f0676a 100644 --- a/dist/bind/lib/isc/netaddr.c +++ b/dist/bind/lib/isc/netaddr.c @@ -1,4 +1,4 @@ -/* $NetBSD: netaddr.c,v 1.1.1.1 2004/05/17 23:45:02 christos Exp $ */ +/* $NetBSD: netaddr.c,v 1.1.1.2 2004/11/06 23:55:49 christos Exp $ */ /* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") @@ -17,7 +17,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* Id: netaddr.c,v 1.18.12.8 2004/03/08 09:04:49 marka Exp */ +/* Id: netaddr.c,v 1.18.12.9 2004/05/15 03:46:12 jinmei Exp */ #include <config.h> @@ -49,7 +49,8 @@ isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) { break; case AF_INET6: if (memcmp(&a->type.in6, &b->type.in6, - sizeof(a->type.in6)) != 0) + sizeof(a->type.in6)) != 0 || + a->zone != b->zone) return (ISC_FALSE); break; default: diff --git a/dist/bind/lib/isc/result.c b/dist/bind/lib/isc/result.c index dc9c17af9b8..18127be04ce 100644 --- a/dist/bind/lib/isc/result.c +++ b/dist/bind/lib/isc/result.c @@ -1,4 +1,4 @@ -/* $NetBSD: result.c,v 1.1.1.1 2004/05/17 23:45:03 christos Exp $ */ +/* $NetBSD: result.c,v 1.1.1.2 2004/11/06 23:55:50 christos Exp $ */ /* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") @@ -17,7 +17,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* Id: result.c,v 1.56.2.2.8.5 2004/03/08 09:04:50 marka Exp */ +/* Id: result.c,v 1.56.2.2.8.7 2004/06/11 00:31:01 marka Exp */ #include <config.h> @@ -98,7 +98,8 @@ static const char *text[ISC_R_NRESULTS] = { "soft quota reached", /* 55 */ "not a valid number", /* 56 */ "disabled", /* 57 */ - "max size" /* 58 */ + "max size", /* 58 */ + "invalid address format" /* 59 */ }; #define ISC_RESULT_RESULTSET 2 @@ -126,7 +127,7 @@ register_table(unsigned int base, unsigned int nresults, const char **text, if (table == NULL) return (ISC_R_NOMEMORY); table->base = base; - table->last = base + nresults; + table->last = base + nresults - 1; table->text = text; table->msgcat = msgcat; table->set = set; diff --git a/dist/bind/lib/isc/sockaddr.c b/dist/bind/lib/isc/sockaddr.c index b34e261749f..66ee4cabc12 100644 --- a/dist/bind/lib/isc/sockaddr.c +++ b/dist/bind/lib/isc/sockaddr.c @@ -1,4 +1,4 @@ -/* $NetBSD: sockaddr.c,v 1.1.1.1 2004/05/17 23:45:02 christos Exp $ */ +/* $NetBSD: sockaddr.c,v 1.1.1.2 2004/11/06 23:55:50 christos Exp $ */ /* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") @@ -17,7 +17,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* Id: sockaddr.c,v 1.48.2.1.2.9 2004/03/08 09:04:50 marka Exp */ +/* Id: sockaddr.c,v 1.48.2.1.2.10 2004/05/15 03:46:12 jinmei Exp */ #include <config.h> @@ -59,6 +59,10 @@ isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { if (memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr, sizeof(a->type.sin6.sin6_addr)) != 0) return (ISC_FALSE); +#ifdef ISC_PLATFORM_HAVESCOPEID + if (a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id) + return (ISC_FALSE); +#endif if (a->type.sin6.sin6_port != b->type.sin6.sin6_port) return (ISC_FALSE); break; @@ -88,6 +92,10 @@ isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { if (memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr, sizeof(a->type.sin6.sin6_addr)) != 0) return (ISC_FALSE); +#ifdef ISC_PLATFORM_HAVESCOPEID + if (a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id) + return (ISC_FALSE); +#endif break; default: if (memcmp(&a->type, &b->type, a->length) != 0) diff --git a/dist/bind/lib/isc/unix/Makefile.in b/dist/bind/lib/isc/unix/Makefile.in index 84eaa8cfc9e..d0c6c4b6c2a 100644 --- a/dist/bind/lib/isc/unix/Makefile.in +++ b/dist/bind/lib/isc/unix/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# Id: Makefile.in,v 1.35.2.1.10.1 2004/03/06 08:14:57 marka Exp +# Id: Makefile.in,v 1.35.2.1.10.2 2004/06/22 02:48:36 marka Exp srcdir = @srcdir@ VPATH = @srcdir@ @@ -46,3 +46,6 @@ SUBDIRS = include TARGETS = ${OBJS} @BIND9_MAKE_RULES@ + +interfaceiter.@O@: interfaceiter.c ifiter_ioctl.c ifiter_sysctl.c ifiter_getifaddrs.c + diff --git a/dist/bind/lib/isc/unix/ifiter_ioctl.c b/dist/bind/lib/isc/unix/ifiter_ioctl.c index 2f4c958b0bc..6ef96fbb387 100644 --- a/dist/bind/lib/isc/unix/ifiter_ioctl.c +++ b/dist/bind/lib/isc/unix/ifiter_ioctl.c @@ -1,4 +1,4 @@ -/* $NetBSD: ifiter_ioctl.c,v 1.1.1.1 2004/05/17 23:45:05 christos Exp $ */ +/* $NetBSD: ifiter_ioctl.c,v 1.1.1.2 2004/11/06 23:55:52 christos Exp $ */ /* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") @@ -17,7 +17,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* Id: ifiter_ioctl.c,v 1.19.2.5.2.10 2004/04/15 07:03:50 marka Exp */ +/* Id: ifiter_ioctl.c,v 1.19.2.5.2.14 2004/06/22 04:40:23 marka Exp */ /* * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl. @@ -52,7 +52,7 @@ #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC) #define ISC_IF_INET6_SZ \ - sizeof("00000000000000000000000000000001 01 80 10 80 lo\n") + sizeof("00000000000000000000000000000001 01 80 10 80 XXXXXXloXXXXXXXX\n") struct isc_interfaceiter { unsigned int magic; /* Magic number. */ @@ -102,6 +102,16 @@ struct isc_interfaceiter { #define IFCONF_BUFSIZE_INITIAL 4096 #define IFCONF_BUFSIZE_MAX 1048576 +#ifdef __linux +#ifndef IF_NAMESIZE +# ifdef IFNAMSIZ +# define IF_NAMESIZE IFNAMSIZ +# else +# define IF_NAMESIZE 16 +# endif +#endif +#endif + static isc_result_t getbuf4(isc_interfaceiter_t *iter) { char strbuf[ISC_STRERRORSIZE]; @@ -446,15 +456,28 @@ linux_if_inet6_current(isc_interfaceiter_t *iter) { if (iter->valid != ISC_R_SUCCESS) return (iter->valid); - if (iter->proc == NULL) + if (iter->proc == NULL) { + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR, + "/proc/net/if_inet6:iter->proc == NULL"); return (ISC_R_FAILURE); + } res = sscanf(iter->entry, "%32[a-f0-9] %x %x %x %x %16s\n", address, &ifindex, &prefix, &flag3, &flag4, name); - if (res != 6) + if (res != 6) { + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR, + "/proc/net/if_inet6:sscanf() -> %d (expected 6)", + res); return (ISC_R_FAILURE); - if (strlen(address) != 32) + } + if (strlen(address) != 32) { + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR, + "/proc/net/if_inet6:strlen(%s) != 32", address); return (ISC_R_FAILURE); + } for (i = 0; i < 16; i++) { unsigned char byte; static const char hex[] = "0123456789abcdef"; @@ -945,7 +968,7 @@ internal_next(isc_interfaceiter_t *iter) { #endif #ifdef HAVE_TRUCLUSTER if (!iter->clua_done) { - clua_result = clua_getaliasaddress(&intr->clua_sa, + clua_result = clua_getaliasaddress(&iter->clua_sa, &iter->clua_context); if (clua_result != CLUA_SUCCESS) iter->clua_done = ISC_TRUE; @@ -985,7 +1008,7 @@ void internal_first(isc_interfaceiter_t *iter) { #endif #ifdef HAVE_TRUCLUSTER iter->clua_context = 0; - clua_result = clua_getaliasaddress(&intr->clua_sa, + clua_result = clua_getaliasaddress(&iter->clua_sa, &iter->clua_context); iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS); #endif diff --git a/dist/bind/lib/isc/unix/interfaceiter.c b/dist/bind/lib/isc/unix/interfaceiter.c index a8427bfeaff..db8ec2ed0d5 100644 --- a/dist/bind/lib/isc/unix/interfaceiter.c +++ b/dist/bind/lib/isc/unix/interfaceiter.c @@ -1,4 +1,4 @@ -/* $NetBSD: interfaceiter.c,v 1.1.1.1 2004/05/17 23:45:05 christos Exp $ */ +/* $NetBSD: interfaceiter.c,v 1.1.1.2 2004/11/06 23:55:52 christos Exp $ */ /* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") @@ -17,7 +17,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* Id: interfaceiter.c,v 1.22.2.1.10.12 2004/04/20 06:46:53 marka Exp */ +/* Id: interfaceiter.c,v 1.22.2.1.10.14 2004/08/28 06:25:22 marka Exp */ #include <config.h> @@ -38,6 +38,7 @@ #include <isc/mem.h> #include <isc/msgs.h> #include <isc/net.h> +#include <isc/print.h> #include <isc/result.h> #include <isc/strerror.h> #include <isc/string.h> @@ -67,6 +68,11 @@ get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src, { struct sockaddr_in6 *sa6; +#if !defined(ISC_PLATFORM_HAVEIFNAMETOINDEX) || \ + !defined(ISC_PLATFORM_HAVESCOPEID) + UNUSED(ifname); +#endif + /* clear any remaining value for safety */ memset(dst, 0, sizeof(*dst)); diff --git a/dist/bind/lib/isc/unix/socket.c b/dist/bind/lib/isc/unix/socket.c index a75a4b2d69d..c5ff6c293b8 100644 --- a/dist/bind/lib/isc/unix/socket.c +++ b/dist/bind/lib/isc/unix/socket.c @@ -1,4 +1,4 @@ -/* $NetBSD: socket.c,v 1.1.1.1 2004/05/17 23:45:06 christos Exp $ */ +/* $NetBSD: socket.c,v 1.1.1.2 2004/11/06 23:55:53 christos Exp $ */ /* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") @@ -17,7 +17,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* Id: socket.c,v 1.207.2.19.2.11 2004/04/19 03:05:22 marka Exp */ +/* Id: socket.c,v 1.207.2.19.2.13 2004/07/01 04:51:15 marka Exp */ #include <config.h> @@ -2861,7 +2861,11 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr) { UNLOCK(&sock->lock); return (ISC_R_FAMILYMISMATCH); } - if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, + /* + * Only set SO_REUSEADDR when we want a specific port. + */ + if (isc_sockaddr_getport(sockaddr) != (in_port_t)0 && + setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)) < 0) { UNEXPECTED_ERROR(__FILE__, __LINE__, "setsockopt(%d) %s", sock->fd, diff --git a/dist/bind/lib/isc/win32/socket.c b/dist/bind/lib/isc/win32/socket.c index d8ed9e78bef..980f11ad7f5 100644 --- a/dist/bind/lib/isc/win32/socket.c +++ b/dist/bind/lib/isc/win32/socket.c @@ -1,4 +1,4 @@ -/* $NetBSD: socket.c,v 1.1.1.1 2004/05/17 23:45:07 christos Exp $ */ +/* $NetBSD: socket.c,v 1.1.1.2 2004/11/06 23:55:58 christos Exp $ */ /* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") @@ -17,7 +17,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* Id: socket.c,v 1.5.2.13.2.8 2004/03/06 08:15:10 marka Exp */ +/* Id: socket.c,v 1.5.2.13.2.13 2004/09/01 04:32:18 marka Exp */ /* This code has been rewritten to take advantage of Windows Sockets * I/O Completion Ports and Events. I/O Completion Ports is ONLY @@ -241,8 +241,10 @@ struct isc_socket { listener : 1, /* listener socket */ connected : 1, connecting : 1, /* connect pending */ - bound : 1; /* bound to local addr */ - + bound : 1, /* bound to local addr */ + pending_free: 1; + unsigned int pending_recv; + unsigned int pending_send; }; /* @@ -348,11 +350,8 @@ static isc_threadresult_t WINAPI SocketIoThread(LPVOID ThreadContext); static void free_socket(isc_socket_t **); enum { - SOCKET_CANCEL, - SOCKET_SHUTDOWN, SOCKET_RECV, SOCKET_SEND, - SOCK_ACCEPT }; enum { @@ -360,9 +359,6 @@ enum { EVENT_DELETE }; -#define SOCK_DEAD(s) ((s)->references == 0) - - #if defined(ISC_SOCKET_DEBUG) /* * This is used to dump the contents of the sock structure @@ -456,7 +452,7 @@ iocompletionport_createthreads(int total_threads, isc_socketmgr_t *manager) { * We need at least one */ for (i = 0; i < total_threads; i++) { - manager->hIOCPThreads[i] = CreateThread( NULL, 0, SocketIoThread, + manager->hIOCPThreads[i] = CreateThread(NULL, 0, SocketIoThread, manager, 0, &manager->dwIOCPThreadIds[i]); if(manager->hIOCPThreads[i] == NULL) { @@ -523,7 +519,8 @@ iocompletionport_exit(isc_socketmgr_t *manager) { } /* - * Add sockets in here and pass the sock data in as part of the information needed + * Add sockets in here and pass the sock data in as part of the + * information needed. */ void iocompletionport_update(isc_socket_t *sock) { @@ -654,9 +651,10 @@ socket_eventlist_add(event_change_t *evchange, sock_event_list *evlist, sock->evthread_id = GetCurrentThreadId(); return (ISC_TRUE); } + /* - * Note that the eventLock is locked before calling this function - * All Events and associated sockes are closed here + * Note that the eventLock is locked before calling this function. + * All Events and associated sockets are closed here. */ isc_boolean_t socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist) { @@ -666,7 +664,7 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist) { REQUIRE(evchange != NULL); /* Make sure this is the right thread from which to delete the event */ - if(evchange->evthread_id != GetCurrentThreadId()) + if (evchange->evthread_id != GetCurrentThreadId()) return (ISC_FALSE); REQUIRE(evlist != NULL); @@ -680,6 +678,7 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist) { break; } } + /* Actual event start at 1 */ if (iEvent < 1) return (ISC_FALSE); @@ -688,6 +687,7 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist) { evlist->aEventList[i] = evlist->aEventList[i + 1]; evlist->aSockList[i] = evlist->aSockList[i + 1]; } + evlist->aEventList[evlist->max_event - 1] = 0; evlist->aSockList[evlist->max_event - 1] = NULL; @@ -700,6 +700,7 @@ socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist) { return (ISC_TRUE); } + /* * Get the event changes off of the list and apply the * requested changes. The manager lock is taken out at @@ -724,15 +725,20 @@ process_eventlist(sock_event_list *evlist, isc_socketmgr_t *manager) { LOCK(&manager->lock); - /* First the deletes */ + /* + * First the deletes. + */ evchange = ISC_LIST_HEAD(manager->event_updates); while (evchange != NULL) { next = ISC_LIST_NEXT(evchange, link); del = ISC_FALSE; - if(evchange->action == EVENT_DELETE) { + if (evchange->action == EVENT_DELETE) { del = socket_eventlist_delete(evchange, evlist); - /* Delete only if this thread's socket list was updated */ + /* + * Delete only if this thread's socket list was + * updated. + */ if (del) { ISC_LIST_DEQUEUE(manager->event_updates, evchange, link); @@ -742,15 +748,21 @@ process_eventlist(sock_event_list *evlist, isc_socketmgr_t *manager) { } evchange = next; } - /* Now the adds */ + + /* + * Now the adds. + */ evchange = ISC_LIST_HEAD(manager->event_updates); while (evchange != NULL) { next = ISC_LIST_NEXT(evchange, link); del = ISC_FALSE; - if(evchange->action == EVENT_ADD) { + if (evchange->action == EVENT_ADD) { del = socket_eventlist_add(evchange, evlist, manager); - /* Delete only if this thread's socket list was updated */ + /* + * Delete only if this thread's socket list was + * updated. + */ if (del) { ISC_LIST_DEQUEUE(manager->event_updates, evchange, link); @@ -763,13 +775,15 @@ process_eventlist(sock_event_list *evlist, isc_socketmgr_t *manager) { UNLOCK(&manager->lock); return (ISC_R_SUCCESS); } + /* * Add the event list changes to the queue and notify the * event loop */ static void notify_eventlist(isc_socket_t *sock, isc_socketmgr_t *manager, - unsigned int action) { + unsigned int action) +{ event_change_t *evchange; @@ -795,6 +809,7 @@ notify_eventlist(isc_socket_t *sock, isc_socketmgr_t *manager, else WSASetEvent(manager->prime_alert); } + /* * Note that the socket is already locked before calling this function */ @@ -832,6 +847,7 @@ socket_event_add(isc_socket_t *sock, long type) { notify_eventlist(sock, sock->manager, EVENT_ADD); return (ISC_R_SUCCESS); } + /* * Note that the socket is not locked before calling this function */ @@ -849,8 +865,8 @@ socket_event_delete(isc_socket_t *sock) { sock->hAlert = NULL; sock->evthread_id = 0; } - } + /* * Routine to cleanup and then close the socket. * Only close the socket here if it is NOT associated @@ -874,6 +890,7 @@ socket_close(isc_socket_t *sock) { } } + /* * Initialize socket services */ @@ -895,7 +912,8 @@ BOOL InitSockets() { int internal_sendmsg(isc_socket_t *sock, IoCompletionInfo *lpo, - struct msghdr *messagehdr, int flags, int *Error) { + struct msghdr *messagehdr, int flags, int *Error) +{ int Result; DWORD BytesSent; DWORD Flags = flags; @@ -920,19 +938,20 @@ internal_sendmsg(isc_socket_t *sock, IoCompletionInfo *lpo, *Error = WSAGetLastError(); switch (*Error) { + case WSA_IO_INCOMPLETE : + case WSA_WAIT_IO_COMPLETION : + case WSA_IO_PENDING : + sock->pending_send++; + case NO_ERROR : + break; - case NO_ERROR : - case WSA_IO_INCOMPLETE : - case WSA_WAIT_IO_COMPLETION : - case WSA_IO_PENDING : - break; - - default : - return (-1); - break; - } - } - if(lpo != NULL) + default : + return (-1); + break; + } + } else + sock->pending_send++; + if (lpo != NULL) return (0); else return (total_sent); @@ -940,7 +959,8 @@ internal_sendmsg(isc_socket_t *sock, IoCompletionInfo *lpo, int internal_recvmsg(isc_socket_t *sock, IoCompletionInfo *lpo, - struct msghdr *messagehdr, int flags, int *Error) { + struct msghdr *messagehdr, int flags, int *Error) +{ DWORD Flags = 0; DWORD NumBytes = 0; int total_bytes = 0; @@ -948,14 +968,14 @@ internal_recvmsg(isc_socket_t *sock, IoCompletionInfo *lpo, *Error = 0; Result = WSARecvFrom((SOCKET) sock->fd, - messagehdr->msg_iov, - messagehdr->msg_iovlen, - &NumBytes, - &Flags, - messagehdr->msg_name, - (int *)&(messagehdr->msg_namelen), - (LPOVERLAPPED) lpo, - NULL); + messagehdr->msg_iov, + messagehdr->msg_iovlen, + &NumBytes, + &Flags, + messagehdr->msg_name, + (int *)&(messagehdr->msg_namelen), + (LPOVERLAPPED) lpo, + NULL); total_bytes = (int) NumBytes; @@ -965,31 +985,32 @@ internal_recvmsg(isc_socket_t *sock, IoCompletionInfo *lpo, *Error = WSAGetLastError(); switch (*Error) { + case WSA_IO_INCOMPLETE: + case WSA_WAIT_IO_COMPLETION: + case WSA_IO_PENDING: + sock->pending_recv++; + case NO_ERROR: + break; - case NO_ERROR : - case WSA_IO_INCOMPLETE : - case WSA_WAIT_IO_COMPLETION : - case WSA_IO_PENDING : - break; + default : + return (-1); + break; + } + } else + sock->pending_recv++; - default : - return (-1); - break; - } - } /* Return the flags received in header */ messagehdr->msg_flags = Flags; - if(lpo != NULL) + if (lpo != NULL) return (-1); else return (total_bytes); - } static void -manager_log(isc_socketmgr_t *sockmgr, - isc_logcategory_t *category, isc_logmodule_t *module, int level, - const char *fmt, ...) { +manager_log(isc_socketmgr_t *sockmgr, isc_logcategory_t *category, + isc_logmodule_t *module, int level, const char *fmt, ...) +{ char msgbuf[2048]; va_list ap; @@ -1009,11 +1030,13 @@ 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, isc_msgcat_t *msgcat, int msgset, int message, - const char *fmt, ...) { + const char *fmt, ...) +{ char msgbuf[2048]; char peerbuf[256]; va_list ap; @@ -1060,6 +1083,7 @@ make_nonblock(SOCKET fd) { return (ISC_R_SUCCESS); } + /* * Windows 2000 systems incorrectly cause UDP sockets using WASRecvFrom * to not work correctly, returning a WSACONNRESET error when a WSASendTo @@ -1109,7 +1133,8 @@ connection_reset_fix(SOCKET fd) { static void build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *msg, char *cmsg, - WSABUF *iov, size_t *write_countp) { + WSABUF *iov, size_t *write_countp) +{ unsigned int iovcount; isc_buffer_t *buffer; isc_region_t used; @@ -1196,7 +1221,8 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev, static void build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *msg, char *cmsg, - WSABUF *iov, size_t *read_countp) { + WSABUF *iov, size_t *read_countp) +{ unsigned int iovcount; isc_buffer_t *buffer; isc_region_t available; @@ -1226,10 +1252,10 @@ build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev, iov[0].len = read_count; iovcount = 1; } else { - /* - * Multibuffer I/O. - * Skip empty buffers. - */ + /* + * Multibuffer I/O. + * Skip empty buffers. + */ while (buffer != NULL) { REQUIRE(ISC_BUFFER_VALID(buffer)); if (isc_buffer_availablelength(buffer) != 0) @@ -1268,7 +1294,8 @@ build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev, static void set_dev_address(isc_sockaddr_t *address, isc_socket_t *sock, - isc_socketevent_t *dev) { + isc_socketevent_t *dev) +{ if (sock->type == isc_sockettype_udp) { if (address != NULL) dev->address = *address; @@ -1282,14 +1309,14 @@ set_dev_address(isc_sockaddr_t *address, isc_socket_t *sock, static isc_socketevent_t * allocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype, - isc_taskaction_t action, const void *arg) { + isc_taskaction_t action, const void *arg) +{ isc_socketevent_t *ev; ev = (isc_socketevent_t *)isc_event_allocate(sock->manager->mctx, sock, eventtype, action, arg, sizeof(*ev)); - if (ev == NULL) return (NULL); @@ -1326,7 +1353,8 @@ dump_msg(struct msghdr *msg, isc_socket_t *sock) { static int completeio_recv(isc_socket_t *sock, isc_socketevent_t *dev, - struct msghdr *messagehdr, int cc, int recv_errno) { + struct msghdr *messagehdr, int cc, int recv_errno) +{ size_t actual_count; isc_buffer_t *buffer; @@ -1444,31 +1472,27 @@ completeio_recv(isc_socket_t *sock, isc_socketevent_t *dev, dev->result = ISC_R_SUCCESS; return (DOIO_SUCCESS); } + static int startio_recv(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes, - BOOL bwait, int *recv_errno) { + int *recv_errno) +{ char *cmsg = NULL; char strbuf[ISC_STRERRORSIZE]; IoCompletionInfo *lpo; int status; - struct msghdr messagehdr; struct msghdr *msghdr; - if (!bwait) { - lpo = (IoCompletionInfo *) HeapAlloc(hHeapHandle, - HEAP_ZERO_MEMORY, sizeof(IoCompletionInfo)); - lpo->request_type = SOCKET_RECV; - lpo->dev = dev; - msghdr = &lpo->messagehdr; - } else { /* Wait for recv to complete */ - lpo = NULL; - msghdr = &messagehdr; - } - sock->references++; + lpo = (IoCompletionInfo *) HeapAlloc(hHeapHandle, + HEAP_ZERO_MEMORY, + sizeof(IoCompletionInfo)); + lpo->request_type = SOCKET_RECV; + lpo->dev = dev; + msghdr = &lpo->messagehdr; memset(msghdr, 0, sizeof(struct msghdr)); build_msghdr_recv(sock, dev, msghdr, cmsg, sock->iov, - &(sock->totalBytes)); + &(sock->totalBytes)); #if defined(ISC_SOCKET_DEBUG) dump_msg(msghdr, sock); @@ -1487,13 +1511,12 @@ startio_recv(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes, socket_log(sock, NULL, IOEVENT, isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_DOIORECV, - "startio_recv: recvmsg(%d) %d bytes, err %d/%s", + "startio_recv: recvmsg(%d) %d bytes, " + "err %d/%s", sock->fd, *nbytes, *recv_errno, strbuf); } - status = completeio_recv(sock, dev, msghdr, *nbytes, *recv_errno); - if(status != DOIO_SOFT) { - sock->references--; - } + status = completeio_recv(sock, dev, msghdr, + *nbytes, *recv_errno); goto done; } dev->result = ISC_R_SUCCESS; @@ -1501,6 +1524,7 @@ startio_recv(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes, done: return (status); } + /* * Returns: * DOIO_SUCCESS The operation succeeded. dev->result contains @@ -1515,8 +1539,9 @@ done: * No other return values are possible. */ static int -completeio_send(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *messagehdr, int cc, - int send_errno) { +completeio_send(isc_socket_t *sock, isc_socketevent_t *dev, + struct msghdr *messagehdr, int cc, int send_errno) +{ char addrbuf[ISC_SOCKADDR_FORMATSIZE]; char strbuf[ISC_STRERRORSIZE]; @@ -1594,28 +1619,24 @@ completeio_send(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *messa dev->result = ISC_R_SUCCESS; return (DOIO_SUCCESS); } + static int startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes, - BOOL bwait, int *send_errno) { + int *send_errno) +{ char *cmsg = NULL; char strbuf[ISC_STRERRORSIZE]; IoCompletionInfo *lpo; int status; - struct msghdr messagehdr; struct msghdr *msghdr; - if (!bwait) { - lpo = (IoCompletionInfo *) HeapAlloc(hHeapHandle, - HEAP_ZERO_MEMORY, sizeof(IoCompletionInfo)); - lpo->request_type = SOCKET_SEND; - lpo->dev = dev; - msghdr = &lpo->messagehdr; - } else { /* Wait for send to complete */ - lpo = NULL; - msghdr = &messagehdr; - } + lpo = (IoCompletionInfo *) HeapAlloc(hHeapHandle, + HEAP_ZERO_MEMORY, + sizeof(IoCompletionInfo)); + lpo->request_type = SOCKET_SEND; + lpo->dev = dev; + msghdr = &lpo->messagehdr; memset(msghdr, 0, sizeof(struct msghdr)); - sock->references++; build_msghdr_send(sock, dev, msghdr, cmsg, sock->iov, &(sock->totalBytes)); @@ -1633,13 +1654,12 @@ startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes, socket_log(sock, NULL, IOEVENT, isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND, - "startio_send: internal_sendmsg(%d) %d bytes, err %d/%s", + "startio_send: internal_sendmsg(%d) %d " + "bytes, err %d/%s", sock->fd, *nbytes, *send_errno, strbuf); } - status = completeio_send(sock, dev, msghdr, *nbytes, *send_errno); - if(status != DOIO_SOFT) { - sock->references--; - } + status = completeio_send(sock, dev, msghdr, + *nbytes, *send_errno); goto done; } dev->result = ISC_R_SUCCESS; @@ -1647,6 +1667,7 @@ startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes, done: return (status); } + /* * Kill. * @@ -1657,6 +1678,7 @@ static void destroy_socket(isc_socket_t **sockp) { isc_socket_t *sock = *sockp; isc_socketmgr_t *manager = sock->manager; + isc_boolean_t dofree = ISC_TRUE; REQUIRE(sock != NULL); @@ -1670,15 +1692,14 @@ destroy_socket(isc_socket_t **sockp) { LOCK(&manager->lock); - /* - * No one has this socket open and the socket doesn't have to be - * locked. The socket_close function makes sure that if needed - * the event_wait loop removes any associated event from the list - * of events being waited on. - */ + LOCK(&sock->lock); socket_close(sock); - + if (sock->pending_recv != 0 || sock->pending_send != 0) { + dofree = ISC_FALSE; + sock->pending_free = 1; + } ISC_LIST_UNLINK(manager->socklist, sock, link); + UNLOCK(&sock->lock); if (ISC_LIST_EMPTY(manager->socklist)) SIGNAL(&manager->shutdown_ok); @@ -1686,10 +1707,10 @@ destroy_socket(isc_socket_t **sockp) { /* * XXX should reset manager->maxfd here */ - UNLOCK(&manager->lock); - free_socket(sockp); + if (dofree) + free_socket(sockp); } static isc_result_t @@ -1723,6 +1744,9 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, sock->connect_ev = NULL; sock->pending_accept = 0; sock->pending_close = 0; + sock->pending_recv = 0; + sock->pending_send = 0; + sock->pending_free = 0; sock->iocp = 0; sock->listener = 0; sock->connected = 0; @@ -1824,11 +1848,13 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, switch (type) { case isc_sockettype_udp: sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP); - result = connection_reset_fix(sock->fd); - if (result != ISC_R_SUCCESS) { - closesocket(sock->fd); - free_socket(&sock); - return (result); + if (sock->fd != INVALID_SOCKET) { + result = connection_reset_fix(sock->fd); + if (result != ISC_R_SUCCESS) { + closesocket(sock->fd); + free_socket(&sock); + return (result); + } } break; case isc_sockettype_tcp: @@ -1894,7 +1920,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, if ((pf == AF_INET6) && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO, (void *)&on, sizeof(on)) < 0)) { - isc__strerror(WSAGetLaastError(), strbuf, sizeof(strbuf)); + isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "setsockopt(%d, IPV6_PKTINFO) %s: %s", sock->fd, @@ -2068,14 +2094,6 @@ internal_accept(isc_socket_t *sock, int accept_errno) { INSIST(sock->pending_accept == 1); sock->pending_accept = 0; - INSIST(sock->references > 0); - sock->references--; /* the internal event is done with this socket */ - if (sock->references == 0) { - UNLOCK(&sock->lock); - destroy_socket(&sock); - return; - } - /* * Check any possible error status from the event notification here. * Note that we don't take any action since it was only @@ -2287,18 +2305,6 @@ internal_connect(isc_socket_t *sock, int connect_errno) { LOCK(&sock->lock); /* - * When the internal event was sent the reference count was bumped - * to keep the socket around for us. Decrement the count here. - */ - INSIST(sock->references > 0); - sock->references--; - if (sock->references == 0) { - UNLOCK(&sock->lock); - destroy_socket(&sock); - return; - } - - /* * Has this event been canceled? */ dev = sock->connect_ev; @@ -2368,7 +2374,9 @@ internal_connect(isc_socket_t *sock, int connect_errno) { } static void -internal_recv(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *messagehdr, int nbytes, int recv_errno) { +internal_recv(isc_socket_t *sock, isc_socketevent_t *dev, + struct msghdr *messagehdr, int nbytes, int recv_errno) +{ isc_socketevent_t *ldev; int io_state; int cc; @@ -2380,14 +2388,8 @@ internal_recv(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *message isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV, "internal_recv: task got socket event %p", dev); - INSIST(sock->references > 0); - sock->references--; /* the internal event is done with this socket */ - if (sock->references == 0) { - UNLOCK(&sock->lock); - destroy_socket(&sock); - return; - } - + INSIST(sock->pending_recv > 0); + sock->pending_recv--; /* If the event is no longer in the list we can just return */ ldev = ISC_LIST_HEAD(sock->recv_list); while (ldev != NULL && ldev != dev) { @@ -2400,34 +2402,36 @@ internal_recv(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *message * Try to do as much I/O as possible on this socket. There are no * limits here, currently. */ - switch (completeio_recv(sock, dev, messagehdr, nbytes, recv_errno)) { - case DOIO_SOFT: - cc = 0; - recv_errno = 0; - io_state = startio_recv(sock, dev, &cc, FALSE, &recv_errno); - goto done; + switch (completeio_recv(sock, dev, messagehdr, nbytes, recv_errno)) { + case DOIO_SOFT: + cc = 0; + recv_errno = 0; + io_state = startio_recv(sock, dev, &cc, &recv_errno); + goto done; - case DOIO_EOF: - /* - * read of 0 means the remote end was closed. - * Run through the event queue and dispatch all - * the events with an EOF result code. - */ - dev->result = ISC_R_EOF; - send_recvdone_event(sock, &dev); - goto done; + case DOIO_EOF: + /* + * read of 0 means the remote end was closed. + * Run through the event queue and dispatch all + * the events with an EOF result code. + */ + dev->result = ISC_R_EOF; + send_recvdone_event(sock, &dev); + goto done; - case DOIO_SUCCESS: - case DOIO_HARD: - send_recvdone_event(sock, &dev); - break; - } + case DOIO_SUCCESS: + case DOIO_HARD: + send_recvdone_event(sock, &dev); + break; + } done: UNLOCK(&sock->lock); } static void -internal_send(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *messagehdr, int nbytes, int send_errno) { +internal_send(isc_socket_t *sock, isc_socketevent_t *dev, + struct msghdr *messagehdr, int nbytes, int send_errno) +{ isc_socketevent_t *ldev; int io_state; int cc; @@ -2442,13 +2446,8 @@ internal_send(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *message isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND, "internal_send: task got socket event %p", dev); - INSIST(sock->references > 0); - sock->references--; /* the internal event is done with this socket */ - if (sock->references == 0) { - UNLOCK(&sock->lock); - destroy_socket(&sock); - return; - } + INSIST(sock->pending_send > 0); + sock->pending_send--; /* If the event is no longer in the list we can just return */ ldev = ISC_LIST_HEAD(sock->send_list); @@ -2465,7 +2464,7 @@ internal_send(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *message case DOIO_SOFT: cc = 0; send_errno = 0; - io_state = startio_send(sock, dev, &cc, FALSE, &send_errno); + io_state = startio_send(sock, dev, &cc, &send_errno); goto done; case DOIO_HARD: @@ -2489,8 +2488,6 @@ SocketIoThread(LPVOID ThreadContext) { isc_socketmgr_t *manager = ThreadContext; BOOL bSuccess = FALSE; DWORD nbytes; - DWORD tbytes; - DWORD tflags; IoCompletionInfo *lpo = NULL; isc_socket_t *sock = NULL; int request; @@ -2506,7 +2503,9 @@ SocketIoThread(LPVOID ThreadContext) { * preempt normal recv packet processing, but not * higher than the timer sync thread. */ - if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL)) { + if (!SetThreadPriority(GetCurrentThread(), + THREAD_PRIORITY_ABOVE_NORMAL)) + { errval = GetLastError(); isc__strerror(errval, strbuf, sizeof(strbuf)); FATAL_ERROR(__FILE__, __LINE__, @@ -2516,33 +2515,53 @@ SocketIoThread(LPVOID ThreadContext) { strbuf); } - /* * Loop forever waiting on I/O Completions and then processing them */ - while(TRUE) { + while (TRUE) { bSuccess = GetQueuedCompletionStatus ( manager->hIoCompletionPort, &nbytes, (LPDWORD) &sock, (LPOVERLAPPED *)&lpo, - INFINITE - ); - if(lpo == NULL ) { + INFINITE); + if (lpo == NULL) { /* * Received request to exit */ break; } errstatus = 0; - if(!bSuccess) { + if (!bSuccess) { + isc_boolean_t dofree = ISC_FALSE; + REQUIRE(VALID_SOCKET(sock)); /* - * I/O Failure - * Find out why + * Was this the socket closed under us? */ - WSAGetOverlappedResult(sock->fd, (LPWSAOVERLAPPED) &lpo, - &tbytes, FALSE, &tflags); - dev = lpo->dev; + errstatus = WSAGetLastError(); + if (nbytes == 0 && errstatus == WSA_OPERATION_ABORTED) { + LOCK(&sock->lock); + switch (lpo->request_type) { + case SOCKET_RECV: + INSIST(sock->pending_recv > 0); + sock->pending_recv--; + break; + case SOCKET_SEND: + INSIST(sock->pending_send > 0); + sock->pending_send--; + break; + } + if (sock->pending_recv == 0 && + sock->pending_send == 0 && + sock->pending_free) + dofree = ISC_TRUE; + UNLOCK(&sock->lock); + if (dofree) + free_socket(&sock); + if (lpo != NULL) + HeapFree(hHeapHandle, 0, lpo); + continue; + } } request = lpo->request_type; @@ -2550,20 +2569,17 @@ SocketIoThread(LPVOID ThreadContext) { messagehdr = &lpo->messagehdr; switch (request) { - case SOCKET_CANCEL: - break; case SOCKET_RECV: internal_recv(sock, dev, messagehdr, nbytes, errstatus); break; case SOCKET_SEND: internal_send(sock, dev, messagehdr, nbytes, errstatus); break; - default: - break; /* Unknown: Just ignore it */ } if (lpo != NULL) HeapFree(hHeapHandle, 0, lpo); } + /* * Exit Completion Port Thread */ @@ -2572,6 +2588,7 @@ SocketIoThread(LPVOID ThreadContext) { ISC_MSG_EXITING, "SocketIoThread exiting")); return ((isc_threadresult_t)0); } + /* * This is the thread that will loop forever, waiting for an event to * happen. @@ -2633,7 +2650,6 @@ event_wait(void *uap) { } while (cc < 0 && !manager->bShutdown && manager->event_written == 0); - if (manager->bShutdown) break; @@ -2692,11 +2708,9 @@ event_wait(void *uap) { if (wsock->listener == 1 && wsock->pending_accept == 0) { wsock->pending_accept = 1; - wsock->references++; internal_accept(wsock, event_errno); } else { - wsock->references++; internal_connect(wsock, event_errno); } } @@ -2708,6 +2722,7 @@ event_wait(void *uap) { return ((isc_threadresult_t)0); } + /* * Create a new socket manager. */ @@ -2863,7 +2878,8 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) { static isc_result_t socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, - unsigned int flags) { + unsigned int flags) +{ int io_state; int cc = 0; isc_task_t *ntask = NULL; @@ -2874,7 +2890,7 @@ socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, LOCK(&sock->lock); iocompletionport_update(sock); - io_state = startio_recv(sock, dev, &cc, FALSE, &recv_errno); + io_state = startio_recv(sock, dev, &cc, &recv_errno); switch (io_state) { case DOIO_SOFT: @@ -3052,7 +3068,7 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, LOCK(&sock->lock); have_lock = ISC_TRUE; iocompletionport_update(sock); - io_state = startio_send(sock, dev, &cc, FALSE, &send_errno); + io_state = startio_send(sock, dev, &cc, &send_errno); switch (io_state) { case DOIO_SOFT: @@ -3211,7 +3227,11 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr) { UNLOCK(&sock->lock); return (ISC_R_FAMILYMISMATCH); } - if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, + /* + * Only set SO_REUSEADDR when we want a specific port. + */ + if (isc_sockaddr_getport(sockaddr) != (in_port_t)0 && + setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)) < 0) { UNEXPECTED_ERROR(__FILE__, __LINE__, "setsockopt(%d) %s", sock->fd, @@ -3645,7 +3665,6 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) { isc_task_t *current_task; dev = ISC_LIST_HEAD(sock->accept_list); - socket_event_delete(sock); while (dev != NULL) { current_task = dev->ev_sender; |
