diff options
author | Internet Software Consortium, Inc <@isc.org> | 2007-09-07 14:14:31 -0600 |
---|---|---|
committer | LaMont Jones <lamont@debian.org> | 2007-09-07 14:14:31 -0600 |
commit | 827006a436e7babc39b4b5b52797aa54313f5be6 (patch) | |
tree | 897f21a87e0eb0131628e6c39691789563ee78d7 /lib/isc | |
parent | ad2d173ed9521052e7fd8ba2cd10117cdea6f058 (diff) | |
download | bind9-827006a436e7babc39b4b5b52797aa54313f5be6.tar.gz |
9.2.3rc1
Diffstat (limited to 'lib/isc')
40 files changed, 4334 insertions, 2903 deletions
diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in index 40a2ee6e..2345ff48 100644 --- a/lib/isc/Makefile.in +++ b/lib/isc/Makefile.in @@ -13,7 +13,7 @@ # NEGLIGENCE 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.1 2001/10/22 23:28:13 gson Exp $ +# $Id: Makefile.in,v 1.71.2.2 2003/07/25 03:31:44 marka Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -52,7 +52,7 @@ WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/file.@O@ \ OBJS = @ISC_EXTRA_OBJS@ \ assertions.@O@ base64.@O@ bitstring.@O@ buffer.@O@ \ bufferlist.@O@ commandline.@O@ error.@O@ event.@O@ \ - heap.@O@ hex.@O@ hmacmd5.@O@ \ + hash.@O@ heap.@O@ hex.@O@ hmacmd5.@O@ \ lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \ md5.@O@ mem.@O@ mutexblock.@O@ netaddr.@O@ ondestroy.@O@ \ quota.@O@ random.@O@ \ diff --git a/lib/isc/api b/lib/isc/api index ca855cad..9886607d 100644 --- a/lib/isc/api +++ b/lib/isc/api @@ -1,3 +1,3 @@ -LIBINTERFACE = 6 +LIBINTERFACE = 7 LIBREVISION = 0 -LIBAGE = 2 +LIBAGE = 0 diff --git a/lib/isc/base64.c b/lib/isc/base64.c index 183e822f..278c2f06 100644 --- a/lib/isc/base64.c +++ b/lib/isc/base64.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1998-2001 Internet Software Consortium. + * Copyright (C) 1998-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: base64.c,v 1.23 2001/03/22 00:07:04 bwelling Exp $ */ +/* $Id: base64.c,v 1.23.2.2 2003/07/22 04:03:47 marka Exp $ */ #include <config.h> @@ -126,6 +126,17 @@ base64_decode_char(base64_decode_ctx_t *ctx, int c) { return (ISC_R_BADBASE64); if (ctx->val[2] == 64 && ctx->val[3] != 64) return (ISC_R_BADBASE64); + /* + * Check that bits that should be zero are. + */ + if (ctx->val[2] == 64 && (ctx->val[1] & 0xf) != 0) + return (ISC_R_BADBASE64); + /* + * We don't need to test for ctx->val[2] != 64 as + * the bottom two bits of 64 are zero. + */ + if (ctx->val[3] == 64 && (ctx->val[2] & 0x3) != 0) + return (ISC_R_BADBASE64); n = (ctx->val[2] == 64) ? 1 : (ctx->val[3] == 64) ? 2 : 3; if (n != 3) { diff --git a/lib/isc/entropy.c b/lib/isc/entropy.c index d046e3e7..3f9ec233 100644 --- a/lib/isc/entropy.c +++ b/lib/isc/entropy.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: entropy.c,v 1.3.2.1 2001/09/06 00:14:17 gson Exp $ */ +/* $Id: entropy.c,v 1.3.2.2 2003/07/23 06:57:53 marka Exp $ */ /* * This is the system independent part of the entropy module. It is @@ -303,7 +303,7 @@ entropypool_adddata(isc_entropy_t *ent, void *p, unsigned int len, addr = (unsigned long)p; buf = p; - if ((addr & 0x03) != 0) { + if ((addr & 0x03U) != 0U) { val = 0; switch (len) { case 3: diff --git a/lib/isc/hash.c b/lib/isc/hash.c new file mode 100644 index 00000000..87bd804e --- /dev/null +++ b/lib/isc/hash.c @@ -0,0 +1,387 @@ +/* + * Copyright (C) 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: hash.c,v 1.2.2.4 2003/07/30 01:15:18 marka Exp $ */ + +/* + * Some portion of this code was derived from universal hash function + * libraries of Rice University. + */ + +/* "UH Universal Hashing Library" + +Copyright ((c)) 2002, Rice University +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Rice University (RICE) nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + +This software is provided by RICE and the contributors on an "as is" +basis, without any representations or warranties of any kind, express +or implied including, but not limited to, representations or +warranties of non-infringement, merchantability or fitness for a +particular purpose. In no event shall RICE or contributors be liable +for any direct, indirect, incidental, special, exemplary, or +consequential damages (including, but not limited to, procurement of +substitute goods or services; loss of use, data, or profits; or +business interruption) however caused and on any theory of liability, +whether in contract, strict liability, or tort (including negligence +or otherwise) arising in any way out of the use of this software, even +if advised of the possibility of such damage. +*/ + +#include <config.h> + +#include <isc/entropy.h> +#include <isc/hash.h> +#include <isc/mem.h> +#include <isc/magic.h> +#include <isc/mutex.h> +#include <isc/once.h> +#include <isc/random.h> +#include <isc/refcount.h> +#include <isc/rwlock.h> +#include <isc/string.h> +#include <isc/util.h> + +#define HASH_MAGIC ISC_MAGIC('H', 'a', 's', 'h') +#define VALID_HASH(h) ISC_MAGIC_VALID((h), HASH_MAGIC) + +/* + * A large 32-bit prime number that specifies the range of the hash output. + */ +#define PRIME32 0xFFFFFFFB /* 2^32 - 5 */ + +/* + * Types of random seed and hash accumulator. Perhaps they can be system + * dependent. + */ +typedef isc_uint32_t hash_accum_t; +typedef isc_uint16_t hash_random_t; + +struct isc_hash { + unsigned int magic; + isc_mem_t *mctx; + isc_mutex_t lock; + isc_boolean_t initialized; + isc_refcount_t refcnt; + isc_entropy_t *entropy; /* entropy source */ + unsigned int limit; /* upper limit of key length */ + size_t vectorlen; /* size of the vector below */ + hash_random_t *rndvector; /* random vector for universal hashing */ +}; + +static isc_rwlock_t createlock; +static isc_once_t once = ISC_ONCE_INIT; +static isc_hash_t *hash = NULL; + +static unsigned char maptolower[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +isc_result_t +isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy, + unsigned int limit, isc_hash_t **hctxp) +{ + isc_result_t ret; + isc_hash_t *hctx; + size_t vlen; + hash_random_t *rv; + hash_accum_t overflow_limit; + + REQUIRE(mctx != NULL); + REQUIRE(hctxp != NULL && *hctxp == NULL); + + /* + * Overflow check. Since our implementation only does a modulo + * operation at the last stage of hash calculation, the accumulator + * must not overflow. + */ + overflow_limit = + 1 << (((sizeof(hash_accum_t) - sizeof(hash_random_t))) * 8); + if (overflow_limit < (limit + 1) * 0xff) + return (ISC_R_RANGE); + + hctx = isc_mem_get(mctx, sizeof(isc_hash_t)); + if (hctx == NULL) + return (ISC_R_NOMEMORY); + + vlen = sizeof(hash_random_t) * (limit + 1); + rv = isc_mem_get(mctx, vlen); + if (rv == NULL) { + ret = ISC_R_NOMEMORY; + goto errout; + } + + /* + * We need a lock. + */ + if (isc_mutex_init(&hctx->lock) != ISC_R_SUCCESS) { + ret = ISC_R_UNEXPECTED; + goto errout; + } + + /* + * From here down, no failures will/can occur. + */ + hctx->magic = HASH_MAGIC; + hctx->mctx = NULL; + isc_mem_attach(mctx, &hctx->mctx); + hctx->initialized = ISC_FALSE; + isc_refcount_init(&hctx->refcnt, 1); + hctx->entropy = NULL; + hctx->limit = limit; + hctx->vectorlen = vlen; + hctx->rndvector = rv; + + if (entropy != NULL) + isc_entropy_attach(entropy, &hctx->entropy); + + *hctxp = hctx; + return (ISC_R_SUCCESS); + + errout: + isc_mem_put(mctx, hctx, sizeof(isc_hash_t)); + if (rv != NULL) + isc_mem_put(mctx, rv, vlen); + + return (ret); +} + +static void +initialize_lock(void) { + RUNTIME_CHECK(isc_rwlock_init(&createlock, 0, 0) == ISC_R_SUCCESS); +} + +isc_result_t +isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit) { + isc_result_t result = ISC_R_SUCCESS; + + REQUIRE(mctx != NULL); + INSIST(hash == NULL); + + RUNTIME_CHECK(isc_once_do(&once, initialize_lock) == ISC_R_SUCCESS); + + RWLOCK(&createlock, isc_rwlocktype_write); + + if (hash == NULL) + result = isc_hash_ctxcreate(mctx, entropy, limit, &hash); + + RWUNLOCK(&createlock, isc_rwlocktype_write); + + return (result); +} + +void +isc_hash_ctxinit(isc_hash_t *hctx) { + isc_result_t result; + + LOCK(&hctx->lock); + + if (hctx->initialized == ISC_TRUE) + goto out; + + if (hctx->entropy) { + result = isc_entropy_getdata(hctx->entropy, + hctx->rndvector, hctx->vectorlen, + NULL, 0); + INSIST(result == ISC_R_SUCCESS); + } else { + isc_uint32_t pr; + unsigned int i, copylen; + unsigned char *p; + + p = (unsigned char *)hctx->rndvector; + for (i = 0; i < hctx->vectorlen; i += copylen, p += copylen) { + isc_random_get(&pr); + if (i + sizeof(pr) <= hctx->vectorlen) + copylen = sizeof(pr); + else + copylen = hctx->vectorlen - i; + + memcpy(p, &pr, copylen); + } + INSIST(p == (unsigned char *)hctx->rndvector + + hctx->vectorlen); + } + + hctx->initialized = ISC_TRUE; + + out: + UNLOCK(&hctx->lock); +} + +void +isc_hash_init() { + INSIST(hash != NULL && VALID_HASH(hash)); + + isc_hash_ctxinit(hash); +} + +void +isc_hash_ctxattach(isc_hash_t *hctx, isc_hash_t **hctxp) { + REQUIRE(VALID_HASH(hctx)); + REQUIRE(hctxp != NULL && *hctxp == NULL); + + isc_refcount_increment(&hctx->refcnt, NULL); + *hctxp = hctx; +} + +static void +destroy(isc_hash_t **hctxp) { + isc_hash_t *hctx; + isc_mem_t *mctx; + + REQUIRE(hctxp != NULL && *hctxp != NULL); + hctx = *hctxp; + *hctxp = NULL; + + LOCK(&hctx->lock); + + isc_refcount_destroy(&hctx->refcnt); + + mctx = hctx->mctx; + if (hctx->entropy != NULL) + isc_entropy_detach(&hctx->entropy); + if (hctx->rndvector != NULL) + isc_mem_put(mctx, hctx->rndvector, hctx->vectorlen); + + UNLOCK(&hctx->lock); + + DESTROYLOCK(&hctx->lock); + + memset(hctx, 0, sizeof(isc_hash_t)); + isc_mem_put(mctx, hctx, sizeof(isc_hash_t)); + isc_mem_detach(&mctx); +} + +void +isc_hash_ctxdetach(isc_hash_t **hctxp) { + isc_hash_t *hctx; + unsigned int refs; + + REQUIRE(hctxp != NULL && VALID_HASH(*hctxp)); + hctx = *hctxp; + + isc_refcount_decrement(&hctx->refcnt, &refs); + if (refs == 0) + destroy(&hctx); + + *hctxp = NULL; +} + +void +isc_hash_destroy() { + unsigned int refs; + + INSIST(hash != NULL && VALID_HASH(hash)); + + isc_refcount_decrement(&hash->refcnt, &refs); + INSIST(refs == 0); + + destroy(&hash); +} + +static inline unsigned int +hash_calc(isc_hash_t *hctx, const unsigned char *key, unsigned int keylen, + isc_boolean_t case_sensitive) +{ + hash_accum_t partial_sum = 0; + hash_random_t *p = hctx->rndvector; + unsigned int i = 0; + + /* Make it sure that the hash context is initialized. */ + if (hctx->initialized == ISC_FALSE) + isc_hash_ctxinit(hctx); + + if (case_sensitive) { + for (i = 0; i < keylen; i++) + partial_sum += key[i] * (hash_accum_t)p[i]; + } else { + for (i = 0; i < keylen; i++) + partial_sum += maptolower[key[i]] * (hash_accum_t)p[i]; + } + + partial_sum += p[i]; + + return ((unsigned int)(partial_sum % PRIME32)); +} + +unsigned int +isc_hash_ctxcalc(isc_hash_t *hctx, const unsigned char *key, + unsigned int keylen, isc_boolean_t case_sensitive) +{ + REQUIRE(hctx != NULL && VALID_HASH(hctx)); + REQUIRE(keylen <= hctx->limit); + + return (hash_calc(hctx, key, keylen, case_sensitive)); +} + +unsigned int +isc_hash_calc(const unsigned char *key, unsigned int keylen, + isc_boolean_t case_sensitive) +{ + INSIST(hash != NULL && VALID_HASH(hash)); + REQUIRE(keylen <= hash->limit); + + return (hash_calc(hash, key, keylen, case_sensitive)); +} diff --git a/lib/isc/include/isc/hash.h b/lib/isc/include/isc/hash.h new file mode 100644 index 00000000..43080df3 --- /dev/null +++ b/lib/isc/include/isc/hash.h @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: hash.h,v 1.2.2.1 2003/07/25 07:30:43 marka Exp $ */ + +#ifndef ISC_HASH_H +#define ISC_HASH_H 1 + +/***** + ***** Module Info + *****/ + +/* + * Hash + * + * The hash API + * + * Provides an unpredictable hash value for variable length data. + * A hash object contains a random vector (which is hidden from clients + * of this API) to make the actual hash value unpredictable. + * + * The algorithm used in the API guarantees the probability of hash + * collision; in the current implementation, as long as the values stored + * in the random vector are unpredictable, the probability of hash + * collision between arbitrary two different values is at most 1/2^16. + * + * Altough the API is generic about the hash keys, it mainly expects + * DNS names (and sometimes IPv4/v6 addresses) as inputs. It has an + * upper limit of the input length, and may run slow to calculaate the + * has values for large inputs. + * + * This API is designed to be general so that it can provide multiple + * different hash contexts that have different random vectors. However, + * it should be typical to have a single context for an entire system. + * To support such cases, the API also provides a single-context mode. + * + * MP: + * The hash object is almost read-only. Once the internal random vector + * is initialized, no write operation will occur, and there will be no + * need to lock the object to calculate actual hash values. + * + * Reliability: + * In some cases this module uses low-level data copy to initialize the + * random vector. Errors in this part are likely to crash the server or + * corrupt memory. + * + * Resources: + * A buffer, used as a random vector for calculating hash values. + * + * Security: + * This module intends to provide unpredictable hash values in + * adversarial environments in order to avoid denial of service attacks + * to hash buckets. + * Its unpredictability relies on the quality of entropy to build the + * random vector. + * + * Standards: + * None. + */ + +/*** + *** Imports + ***/ + +#include <isc/types.h> + +/*** + *** Functions + ***/ +ISC_LANG_BEGINDECLS + +isc_result_t +isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy, unsigned int limit, + isc_hash_t **hctx); +isc_result_t +isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit); +/* + * Create a new hash object. + * + * isc_hash_ctxcreate() creates a different object. + * isc_hash_create() creates a module-internal object to support the + * single-context mode. It should be called only once. + * + * 'entropy' must be NULL or a valid entropy object. If 'entropy' is NULL, + * pseudo random values will be used to build the random vector, which may + * weaken security. + * + * 'limit' specifies the maximum number of hash keys. If it is too large, + * these functions may fail. + */ + +void +isc_hash_ctxattach(isc_hash_t *hctx, isc_hash_t **hctxp); +/* + * Attach to a hash object. + * This function is only necessary for the multiple-context mode. + */ + +void +isc_hash_ctxdetach(isc_hash_t **hctxp); +/* + * Detach from a hash object. + * + * This function is for the multiple-context mode, and takes a valid + * hash object as an argument. + */ + +void +isc_hash_destroy(void); +/* + * This function is for the single-context mode, and is expected to be used + * as a counterpart of isc_hash_create(). + * A valid module-internal hash object must have been created, and this + * function should be called only once. + */ + +void +isc_hash_ctxinit(isc_hash_t *hctx); +void +isc_hash_init(void); +/* + * Initialize a hash object. It fills in the random vector with a proper + * source of entropy, which is typically from the entropy object specified + * at the creation. Thus, it is desirable to call these functions after + * initializing the entropy object with some good entropy sources. + * + * These functions should be called before the first hash calculation. + * + * isc_hash_ctxinit() is for the multiple-context mode, and takes a valid hash + * object as an argument. + * isc_hash_init() is for the single-context mode. A valid module-internal + * hash object must have been created, and this function should be called only + * once. + */ + +unsigned int +isc_hash_ctxcalc(isc_hash_t *hctx, const unsigned char *key, + unsigned int keylen, isc_boolean_t case_sensitive); +unsigned int +isc_hash_calc(const unsigned char *key, unsigned int keylen, + isc_boolean_t case_sensitive); +/* + * Calculate a hash value. + * + * isc_hash_ctxinit() is for the multiple-context mode, and takes a valid hash + * object as an argument. + * isc_hash_init() is for the single-context mode. A valid module-internal + * hash object must have been created. + * + * 'key' is the hash key, which is a variable length buffer. + * 'keylen' specifies the key length, which must not be larger than the limit + * specified for the corresponding hash object. + * + * 'case_sensitive' specifies whether the hash key should be treated as + * case_sensitive values. It should typically be ISC_FALSE if the hash key + * is a DNS name. + */ + +ISC_LANG_ENDDECLS + +#endif /* ISC_HASH_H */ diff --git a/lib/isc/include/isc/log.h b/lib/isc/include/isc/log.h index 481cb85e..0bfaebb5 100644 --- a/lib/isc/include/isc/log.h +++ b/lib/isc/include/isc/log.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999-2002 Internet Software Consortium. + * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: log.h,v 1.39.2.2 2002/08/05 06:57:15 marka Exp $ */ +/* $Id: log.h,v 1.39.2.4 2003/07/22 04:03:49 marka Exp $ */ #ifndef ISC_LOG_H #define ISC_LOG_H 1 @@ -61,6 +61,7 @@ #define ISC_LOG_PRINTTAG 0x0010 #define ISC_LOG_PRINTALL 0x001F #define ISC_LOG_DEBUGONLY 0x1000 +#define ISC_LOG_OPENERR 0x8000 /* internal */ /* * Other options. diff --git a/lib/isc/include/isc/refcount.h b/lib/isc/include/isc/refcount.h index 265ed8ce..b52e5a29 100644 --- a/lib/isc/include/isc/refcount.h +++ b/lib/isc/include/isc/refcount.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: refcount.h,v 1.3 2001/02/09 00:26:20 gson Exp $ */ +/* $Id: refcount.h,v 1.3.2.2 2003/07/25 05:05:28 marka Exp $ */ #ifndef ISC_REFCOUNT_H #define ISC_REFCOUNT_H 1 @@ -111,21 +111,23 @@ typedef struct isc_refcount { #define isc_refcount_increment(rp, tp) \ do { \ + unsigned int *_tmp = (unsigned int *)(tp); \ LOCK(&(rp)->lock); \ REQUIRE((rp)->refs > 0); \ ++((rp)->refs); \ - if ((tp) != NULL) \ - *(unsigned int *)(tp) = ((rp)->refs); \ + if (_tmp != NULL) \ + *_tmp = ((rp)->refs); \ UNLOCK(&(rp)->lock); \ } while (0) #define isc_refcount_decrement(rp, tp) \ do { \ + unsigned int *_tmp = (unsigned int *)(tp); \ LOCK(&(rp)->lock); \ REQUIRE((rp)->refs > 0); \ --((rp)->refs); \ - if ((tp) != NULL) \ - *(unsigned int *)(tp) = ((rp)->refs); \ + if (_tmp != NULL) \ + *_tmp = ((rp)->refs); \ UNLOCK(&(rp)->lock); \ } while (0) diff --git a/lib/isc/include/isc/rwlock.h b/lib/isc/include/isc/rwlock.h index 0313c050..569cea46 100644 --- a/lib/isc/include/isc/rwlock.h +++ b/lib/isc/include/isc/rwlock.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1998-2001 Internet Software Consortium. + * Copyright (C) 1998-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rwlock.h,v 1.18 2001/03/08 00:55:15 tale Exp $ */ +/* $Id: rwlock.h,v 1.18.2.3 2003/07/22 04:03:49 marka Exp $ */ #ifndef ISC_RWLOCK_H #define ISC_RWLOCK_H 1 @@ -57,6 +57,7 @@ struct isc_rwlock { unsigned int writers_waiting; unsigned int read_quota; unsigned int write_quota; + isc_rwlocktype_t original; }; #else /* ISC_PLATFORM_USETHREADS */ struct isc_rwlock { @@ -80,6 +81,12 @@ isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type); isc_result_t isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type); +isc_result_t +isc_rwlock_tryupgrade(isc_rwlock_t *rwl); + +void +isc_rwlock_downgrade(isc_rwlock_t *rwl); + void isc_rwlock_destroy(isc_rwlock_t *rwl); diff --git a/lib/isc/include/isc/types.h b/lib/isc/include/isc/types.h index f0399d15..54eb868f 100644 --- a/lib/isc/include/isc/types.h +++ b/lib/isc/include/isc/types.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: types.h,v 1.32.2.2 2002/08/06 06:09:07 marka Exp $ */ +/* $Id: types.h,v 1.32.2.3 2003/07/25 03:31:45 marka Exp $ */ #ifndef ISC_TYPES_H #define ISC_TYPES_H 1 @@ -52,6 +52,7 @@ typedef struct isc_event isc_event_t; typedef ISC_LIST(isc_event_t) isc_eventlist_t; typedef unsigned int isc_eventtype_t; typedef isc_uint32_t isc_fsaccess_t; +typedef struct isc_hash isc_hash_t; typedef struct isc_interface isc_interface_t; typedef struct isc_interfaceiter isc_interfaceiter_t; typedef struct isc_interval isc_interval_t; diff --git a/lib/isc/inet_pton.c b/lib/isc/inet_pton.c index f05d1331..d0211510 100644 --- a/lib/isc/inet_pton.c +++ b/lib/isc/inet_pton.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1996-2002 Internet Software Consortium. + * Copyright (C) 1996-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -17,7 +17,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char rcsid[] = - "$Id: inet_pton.c,v 1.10.2.2 2002/03/26 00:55:06 marka Exp $"; + "$Id: inet_pton.c,v 1.10.2.4 2003/07/22 04:03:47 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include <config.h> @@ -196,6 +196,8 @@ inet_pton6(const char *src, unsigned char *dst) { const int n = tp - colonp; int i; + if (tp == endp) + return (0); for (i = 1; i <= n; i++) { endp[- i] = colonp[n - i]; colonp[n - i] = 0; diff --git a/lib/isc/lex.c b/lib/isc/lex.c index a440467f..85813f9f 100644 --- a/lib/isc/lex.c +++ b/lib/isc/lex.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lex.c,v 1.66.2.5 2002/03/26 00:55:07 marka Exp $ */ +/* $Id: lex.c,v 1.66.2.6 2003/07/23 06:57:53 marka Exp $ */ #include <config.h> @@ -92,7 +92,7 @@ isc_lex_create(isc_mem_t *mctx, size_t max_token, isc_lex_t **lexp) { */ REQUIRE(lexp != NULL && *lexp == NULL); - REQUIRE(max_token > 0); + REQUIRE(max_token > 0U); lex = isc_mem_get(mctx, sizeof *lex); if (lex == NULL) @@ -623,13 +623,13 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { state = lexstate_string; } } - if (remaining == 0) { + if (remaining == 0U) { result = grow_data(lex, &remaining, &curr, &prev); if (result != ISC_R_SUCCESS) goto done; } - INSIST(remaining > 0); + INSIST(remaining > 0U); *curr++ = c; *curr = '\0'; remaining--; @@ -653,13 +653,13 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { if ((options & ISC_LEXOPT_ESCAPE) != 0) escaped = (!escaped && c == '\\') ? ISC_TRUE : ISC_FALSE; - if (remaining == 0) { + if (remaining == 0U) { result = grow_data(lex, &remaining, &curr, &prev); if (result != ISC_R_SUCCESS) goto done; } - INSIST(remaining > 0); + INSIST(remaining > 0U); *curr++ = c; *curr = '\0'; remaining--; @@ -750,13 +750,13 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { escaped = ISC_TRUE; else escaped = ISC_FALSE; - if (remaining == 0) { + if (remaining == 0U) { result = grow_data(lex, &remaining, &curr, &prev); if (result != ISC_R_SUCCESS) goto done; } - INSIST(remaining > 0); + INSIST(remaining > 0U); prev = curr; *curr++ = c; *curr = '\0'; diff --git a/lib/isc/lfsr.c b/lib/isc/lfsr.c index e8b1fbbd..6dde5c6e 100644 --- a/lib/isc/lfsr.c +++ b/lib/isc/lfsr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999-2001 Internet Software Consortium. + * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: lfsr.c,v 1.11 2001/01/09 21:56:11 bwelling Exp $ */ +/* $Id: lfsr.c,v 1.11.2.2 2003/07/22 04:03:47 marka Exp $ */ #include <config.h> @@ -74,7 +74,7 @@ lfsr_generate(isc_lfsr_t *lfsr) } if (lfsr->state & 0x01) { - lfsr->state = ((lfsr->state ^ lfsr->tap) >> 1) | highbit; + lfsr->state = (lfsr->state >> 1) ^ lfsr->tap; return (1); } else { lfsr->state >>= 1; diff --git a/lib/isc/log.c b/lib/isc/log.c index 1aa9974c..d462123b 100644 --- a/lib/isc/log.c +++ b/lib/isc/log.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999-2002 Internet Software Consortium. + * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: log.c,v 1.70.2.5 2002/07/11 03:39:06 marka Exp $ */ +/* $Id: log.c,v 1.70.2.8 2003/07/22 04:03:47 marka Exp $ */ /* Principal Authors: DCL */ @@ -36,6 +36,7 @@ #include <isc/mem.h> #include <isc/msgs.h> #include <isc/print.h> +#include <isc/stat.h> #include <isc/stdio.h> #include <isc/string.h> #include <isc/time.h> @@ -52,6 +53,10 @@ */ #define LOG_BUFFER_SIZE (8 * 1024) +#ifndef PATH_MAX +#define PATH_MAX 1024 /* AIX and others don't define this. */ +#endif + /* * This is the structure that holds each named channel. A simple linked * list chains all of the channels together, so an individual channel is @@ -1186,9 +1191,9 @@ greatest_version(isc_logchannel_t *channel, int *greatestp) { static isc_result_t roll_log(isc_logchannel_t *channel) { - int i, greatest, digits = 0; - char current[FILENAME_MAX + 1]; - char new[FILENAME_MAX + 1]; + int i, n, greatest; + char current[PATH_MAX + 1]; + char new[PATH_MAX + 1]; const char *path; isc_result_t result; @@ -1232,37 +1237,58 @@ roll_log(isc_logchannel_t *channel) { * Remove any excess logs on the way to that value. */ while (--greatest >= FILE_VERSIONS(channel)) { - sprintf(current, "%s.%d", path, greatest); - (void)remove(current); + n = snprintf(current, sizeof(current), "%s.%d", + path, greatest); + if (n >= (int)sizeof(current) || n < 0) + result = ISC_R_NOSPACE; + else + result = isc_file_remove(current); + if (result != ISC_R_SUCCESS && + result != ISC_R_FILENOTFOUND) + syslog(LOG_ERR, + "unable to remove log file '%s.%d': %s", + path, greatest, + isc_result_totext(result)); } - for (i = greatest; i > 0; i /= 10) - digits++; - - /* - * Ensure the name fits in the filesystem. Note that in this will not - * trigger failure until there is going to be a log rolled into a name - * that is too long, not when the maximum possible version name would - * be too long. Imagine a case where the name for logs 0-9 is exactly - * as long as the maximum filename, but FILE_VERSIONS is configured as - * 11. log.10's name will be too long, but no error will be triggered - * until log.9 exists and needs to be rolled. - */ - if (strlen(path) + 1 + digits > FILENAME_MAX) - return (ISC_R_INVALIDFILE); - for (i = greatest; i > 0; i--) { - sprintf(current, "%s.%d", path, i - 1); - sprintf(new, "%s.%d", path, i); - (void)isc_file_rename(current, new); + result = ISC_R_SUCCESS; + n = snprintf(current, sizeof(current), "%s.%d", path, i - 1); + if (n >= (int)sizeof(current) || n < 0) + result = ISC_R_NOSPACE; + if (result == ISC_R_SUCCESS) { + n = snprintf(new, sizeof(new), "%s.%d", path, i); + if (n >= (int)sizeof(new) || n < 0) + result = ISC_R_NOSPACE; + } + if (result == ISC_R_SUCCESS) + result = isc_file_rename(current, new); + if (result != ISC_R_SUCCESS && + result != ISC_R_FILENOTFOUND) + syslog(LOG_ERR, + "unable to rename log file '%s.%d' to " + "'%s.%d': %s", path, i - 1, path, i, + isc_result_totext(result)); } if (FILE_VERSIONS(channel) != 0) { - sprintf(new, "%s.0", path); - (void)isc_file_rename(path, new); - - } else if (FILE_VERSIONS(channel) == 0) - (void)remove(path); + n = snprintf(new, sizeof(new), "%s.0", path); + if (n >= (int)sizeof(new) || n < 0) + result = ISC_R_NOSPACE; + else + result = isc_file_rename(path, new); + if (result != ISC_R_SUCCESS && + result != ISC_R_FILENOTFOUND) + syslog(LOG_ERR, + "unable to rename log file '%s' to '%s.0': %s", + path, path, isc_result_totext(result)); + } else { + result = isc_file_remove(path); + if (result != ISC_R_SUCCESS && + result != ISC_R_FILENOTFOUND) + syslog(LOG_ERR, "unable to remove log file '%s': %s", + path, isc_result_totext(result)); + } return (ISC_R_SUCCESS); } @@ -1288,8 +1314,7 @@ isc_log_open(isc_logchannel_t *channel) { * and either has no size limit or has reached its size limit. */ if (stat(path, &statbuf) == 0) { - regular_file = (statbuf.st_mode & S_IFREG) ? - ISC_TRUE : ISC_FALSE; + regular_file = S_ISREG(statbuf.st_mode) ? ISC_TRUE : ISC_FALSE; /* XXXDCL if not regular_file complain? */ roll = ISC_TF(regular_file && statbuf.st_size >= FILE_MAXSIZE(channel)); @@ -1303,8 +1328,17 @@ isc_log_open(isc_logchannel_t *channel) { */ if (result == ISC_R_SUCCESS && roll) { result = roll_log(channel); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + if ((channel->flags & ISC_LOG_OPENERR) == 0) { + syslog(LOG_ERR, + "isc_log_open: roll_log '%s' " + "failed: %s", + FILE_NAME(channel), + isc_result_totext(result)); + channel->flags |= ISC_LOG_OPENERR; + } return (result); + } } result = isc_stdio_open(path, "a", &FILE_STREAM(channel)); @@ -1637,12 +1671,17 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category, if (FILE_STREAM(channel) == NULL) { result = isc_log_open(channel); + if (result != ISC_R_SUCCESS && + (channel->flags & ISC_LOG_OPENERR) == 0) { + syslog(LOG_ERR, + "isc_log_open '%s' failed: %s", + FILE_NAME(channel), + isc_result_totext(result)); + channel->flags |= ISC_LOG_OPENERR; + } if (result != ISC_R_SUCCESS) break; - /* - * Probably something more meaningful should be - * done with an error. - */ + channel->flags &= ~ISC_LOG_OPENERR; } /* FALLTHROUGH */ diff --git a/lib/isc/mem.c b/lib/isc/mem.c index 43c6755b..2926a3e8 100644 --- a/lib/isc/mem.c +++ b/lib/isc/mem.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: mem.c,v 1.98.2.6 2002/07/10 06:10:45 marka Exp $ */ +/* $Id: mem.c,v 1.98.2.7 2003/07/23 06:57:53 marka Exp $ */ #include <config.h> @@ -647,10 +647,10 @@ mem_putstats(isc_mem_t *ctx, void *ptr, size_t size) { ctx->inuse -= size; if (size > ctx->max_size) { - INSIST(ctx->stats[ctx->max_size].gets > 0); + INSIST(ctx->stats[ctx->max_size].gets > 0U); ctx->stats[ctx->max_size].gets--; } else { - INSIST(ctx->stats[size].gets > 0); + INSIST(ctx->stats[size].gets > 0U); ctx->stats[size].gets--; } } @@ -664,7 +664,7 @@ mem_putstats(isc_mem_t *ctx, void *ptr, size_t size) { static void * default_memalloc(void *arg, size_t size) { UNUSED(arg); - if (size == 0) + if (size == 0U) size = 1; return (malloc(size)); } @@ -701,7 +701,7 @@ isc_mem_createx(size_t init_max_size, size_t target_size, if (ctx == NULL) return (ISC_R_NOMEMORY); - if (init_max_size == 0) + if (init_max_size == 0U) ctx->max_size = DEF_MAX_SIZE; else ctx->max_size = init_max_size; @@ -833,7 +833,7 @@ destroy(isc_mem_t *ctx) { if (ctx->stats[i].gets != 0) print_active(ctx, stderr); #endif - INSIST(ctx->stats[i].gets == 0); + INSIST(ctx->stats[i].gets == 0U); } } @@ -992,14 +992,14 @@ isc__mem_get(isc_mem_t *ctx, size_t size FLARG) { #endif /* ISC_MEM_USE_INTERNAL_MALLOC */ ADD_TRACE(ctx, ptr, size, file, line); - if (ctx->hi_water != 0 && !ctx->hi_called && + if (ctx->hi_water != 0U && !ctx->hi_called && ctx->inuse > ctx->hi_water) { ctx->hi_called = ISC_TRUE; call_water = ISC_TRUE; } if (ctx->inuse > ctx->maxinuse) { ctx->maxinuse = ctx->inuse; - if (ctx->hi_water != 0 && ctx->inuse > ctx->hi_water && + if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water && (isc_mem_debugging & ISC_MEM_DEBUGUSAGE) != 0) fprintf(stderr, "maxinuse = %lu\n", (unsigned long)ctx->inuse); @@ -1038,7 +1038,7 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG) * isc_mem_setwater() called with 0 for hi_water and lo_water. */ if (ctx->hi_called && - (ctx->inuse < ctx->lo_water || ctx->lo_water == 0)) { + (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) { ctx->hi_called = ISC_FALSE; if (ctx->water != NULL) @@ -1100,7 +1100,7 @@ isc_mem_stats(isc_mem_t *ctx, FILE *out) { for (i = 0; i <= ctx->max_size; i++) { s = &ctx->stats[i]; - if (s->totalgets == 0 && s->gets == 0) + if (s->totalgets == 0U && s->gets == 0U) continue; fprintf(out, "%s%5lu: %11lu gets, %11lu rem", (i == ctx->max_size) ? ">=" : " ", @@ -1340,7 +1340,7 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) { isc_mempool_t *mpctx; REQUIRE(VALID_CONTEXT(mctx)); - REQUIRE(size > 0); + REQUIRE(size > 0U); REQUIRE(mpctxp != NULL && *mpctxp == NULL); /* diff --git a/lib/isc/print.c b/lib/isc/print.c index 53dc5275..57cc5408 100644 --- a/lib/isc/print.c +++ b/lib/isc/print.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999-2001 Internet Software Consortium. + * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: print.c,v 1.22 2001/05/16 00:52:55 gson Exp $ */ +/* $Id: print.c,v 1.22.2.3 2003/07/22 04:03:47 marka Exp $ */ #include <config.h> @@ -166,7 +166,6 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { *str++ = *format; size--; } - format++; count++; break; case 'q': @@ -350,7 +349,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) { n = precision; tp = cp; - while (n != 0 && *tp != '0') + while (n != 0 && *tp != '\0') n--, tp++; length = precision - n; } else { diff --git a/lib/isc/pthreads/thread.c b/lib/isc/pthreads/thread.c index 7e24cedc..de020c41 100644 --- a/lib/isc/pthreads/thread.c +++ b/lib/isc/pthreads/thread.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: thread.c,v 1.9 2001/01/09 21:58:02 bwelling Exp $ */ +/* $Id: thread.c,v 1.9.2.2 2003/07/25 07:38:23 marka Exp $ */ #include <config.h> @@ -23,7 +23,7 @@ #include <isc/util.h> #ifndef THREAD_MINSTACKSIZE -#define THREAD_MINSTACKSIZE (64 * 1024) +#define THREAD_MINSTACKSIZE (64U * 1024) #endif isc_result_t @@ -36,7 +36,8 @@ isc_thread_create(isc_threadfunc_t func, isc_threadarg_t arg, pthread_attr_init(&attr); -#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE +#if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \ + defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) ret = pthread_attr_getstacksize(&attr, &stacksize); if (ret != 0) return (ISC_R_UNEXPECTED); diff --git a/lib/isc/random.c b/lib/isc/random.c index 4ed13d97..a4251561 100644 --- a/lib/isc/random.c +++ b/lib/isc/random.c @@ -15,11 +15,12 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: random.c,v 1.15 2001/01/09 21:56:22 bwelling Exp $ */ +/* $Id: random.c,v 1.15.2.2 2003/08/05 03:09:52 marka Exp $ */ #include <config.h> #include <stdlib.h> +#include <unistd.h> #include <time.h> /* Required for time(). */ #include <isc/mutex.h> @@ -33,7 +34,17 @@ static isc_once_t once = ISC_ONCE_INIT; static void initialize_rand(void) { - srand(time(NULL)); +#ifndef HAVE_ARC4RANDOM + unsigned int pid = getpid(); + + /* + * The low bits of pid generally change faster. + * Xor them with the high bits of time which change slowly. + */ + pid = ((pid << 16) & 0xffff0000) | ((pid >> 16) & 0xffff); + + srand(time(NULL) ^ pid); +#endif } static void @@ -47,7 +58,11 @@ isc_random_seed(isc_uint32_t seed) { initialize(); +#ifndef HAVE_ARC4RANDOM srand(seed); +#else + arc4random_addrandom((u_char *) &seed, sizeof(isc_uint32_t)); +#endif } void @@ -57,7 +72,15 @@ isc_random_get(isc_uint32_t *val) initialize(); - *val = rand(); +#ifndef HAVE_ARC4RANDOM + /* + * rand()'s lower bits are not random. + * rand()'s upper bit is zero. + */ + *val = ((rand() >> 4) & 0xffff) | ((rand() << 12) & 0xffff0000) ; +#else + *val = arc4random(); +#endif } isc_uint32_t @@ -66,5 +89,9 @@ isc_random_jitter(isc_uint32_t max, isc_uint32_t jitter) { if (jitter == 0) return (max); else +#ifndef HAVE_ARC4RANDOM return (max - rand() % jitter); +#else + return (max - arc4random() % jitter); +#endif } diff --git a/lib/isc/rwlock.c b/lib/isc/rwlock.c index 6ddcbdba..c31b2a11 100644 --- a/lib/isc/rwlock.c +++ b/lib/isc/rwlock.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1998-2001 Internet Software Consortium. + * Copyright (C) 1998-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rwlock.c,v 1.33 2001/04/17 14:36:45 tale Exp $ */ +/* $Id: rwlock.c,v 1.33.2.4 2003/07/23 03:20:24 marka Exp $ */ #include <config.h> @@ -82,6 +82,7 @@ isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota, rwl->magic = 0; rwl->type = isc_rwlocktype_read; + rwl->original = isc_rwlocktype_none; rwl->active = 0; rwl->granted = 0; rwl->readers_waiting = 0; @@ -206,6 +207,50 @@ isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { } isc_result_t +isc_rwlock_tryupgrade(isc_rwlock_t *rwl) { + isc_result_t result = ISC_R_SUCCESS; + + REQUIRE(VALID_RWLOCK(rwl)); + LOCK(&rwl->lock); + REQUIRE(rwl->type == isc_rwlocktype_read); + REQUIRE(rwl->active != 0); + + /* If we are the only reader then succeed. */ + if (rwl->active == 1) { + rwl->original = (rwl->original == isc_rwlocktype_none) ? + isc_rwlocktype_read : isc_rwlocktype_none; + rwl->type = isc_rwlocktype_write; + } else + result = ISC_R_LOCKBUSY; + + UNLOCK(&rwl->lock); + return (result); +} + +void +isc_rwlock_downgrade(isc_rwlock_t *rwl) { + + REQUIRE(VALID_RWLOCK(rwl)); + LOCK(&rwl->lock); + REQUIRE(rwl->type == isc_rwlocktype_write); + REQUIRE(rwl->active == 1); + + rwl->type = isc_rwlocktype_read; + rwl->original = (rwl->original == isc_rwlocktype_none) ? + isc_rwlocktype_write : isc_rwlocktype_none; + /* + * Resume processing any read request that were blocked when + * we upgraded. + */ + if (rwl->original == isc_rwlocktype_none && + (rwl->writers_waiting == 0 || rwl->granted < rwl->read_quota) && + rwl->readers_waiting > 0) + BROADCAST(&rwl->readable); + + UNLOCK(&rwl->lock); +} + +isc_result_t isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { REQUIRE(VALID_RWLOCK(rwl)); @@ -222,6 +267,10 @@ isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { INSIST(rwl->active > 0); rwl->active--; if (rwl->active == 0) { + if (rwl->original != isc_rwlocktype_none) { + rwl->type = rwl->original; + rwl->original = isc_rwlocktype_none; + } if (rwl->type == isc_rwlocktype_read) { rwl->granted = 0; if (rwl->writers_waiting > 0) { @@ -249,6 +298,7 @@ isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { } } } + INSIST(rwl->original == isc_rwlocktype_none); #ifdef ISC_RWLOCK_TRACE print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, @@ -319,6 +369,32 @@ isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { } isc_result_t +isc_rwlock_tryupgrade(isc_rwlock_t *rwl) { + isc_result_t result = ISC_R_SUCCESS; + + REQUIRE(VALID_RWLOCK(rwl)); + REQUIRE(rwl->type == isc_rwlocktype_read); + REQUIRE(rwl->active != 0); + + /* If we are the only reader then succeed. */ + if (rwl->active == 1) + rwl->type = isc_rwlocktype_write; + else + result = ISC_R_LOCKBUSY; + return (result); +} + +void +isc_rwlock_downgrade(isc_rwlock_t *rwl) { + + REQUIRE(VALID_RWLOCK(rwl)); + REQUIRE(rwl->type == isc_rwlocktype_write); + REQUIRE(rwl->active == 1); + + rwl->type = isc_rwlocktype_read; +} + +isc_result_t isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { REQUIRE(VALID_RWLOCK(rwl)); REQUIRE(rwl->type == type); diff --git a/lib/isc/sha1.c b/lib/isc/sha1.c index 6685025c..63d127f0 100644 --- a/lib/isc/sha1.c +++ b/lib/isc/sha1.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001 Internet Software Consortium. + * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sha1.c,v 1.10 2001/01/09 21:56:28 bwelling Exp $ */ +/* $Id: sha1.c,v 1.10.2.2 2003/07/22 04:03:48 marka Exp $ */ /* $NetBSD: sha1.c,v 1.5 2000/01/22 22:19:14 mycroft Exp $ */ /* $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $ */ @@ -85,6 +85,67 @@ typedef union { unsigned int l[16]; } CHAR64LONG16; +#ifdef __sparc_v9__ +static void do_R01(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d, u_int32_t *e, CHAR64LONG16 *); +static void do_R2(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d, u_int32_t *e, CHAR64LONG16 *); +static void do_R3(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d, u_int32_t *e, CHAR64LONG16 *); +static void do_R4(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d, u_int32_t *e, CHAR64LONG16 *); + +#define nR0(v,w,x,y,z,i) R0(*v,*w,*x,*y,*z,i) +#define nR1(v,w,x,y,z,i) R1(*v,*w,*x,*y,*z,i) +#define nR2(v,w,x,y,z,i) R2(*v,*w,*x,*y,*z,i) +#define nR3(v,w,x,y,z,i) R3(*v,*w,*x,*y,*z,i) +#define nR4(v,w,x,y,z,i) R4(*v,*w,*x,*y,*z,i) + +static void +do_R01(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d, u_int32_t *e, CHAR64LONG16 *block) +{ + nR0(a,b,c,d,e, 0); nR0(e,a,b,c,d, 1); nR0(d,e,a,b,c, 2); + nR0(c,d,e,a,b, 3); nR0(b,c,d,e,a, 4); nR0(a,b,c,d,e, 5); + nR0(e,a,b,c,d, 6); nR0(d,e,a,b,c, 7); nR0(c,d,e,a,b, 8); + nR0(b,c,d,e,a, 9); nR0(a,b,c,d,e,10); nR0(e,a,b,c,d,11); + nR0(d,e,a,b,c,12); nR0(c,d,e,a,b,13); nR0(b,c,d,e,a,14); + nR0(a,b,c,d,e,15); nR1(e,a,b,c,d,16); nR1(d,e,a,b,c,17); + nR1(c,d,e,a,b,18); nR1(b,c,d,e,a,19); +} + +static void +do_R2(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d, u_int32_t *e, CHAR64LONG16 *block) +{ + nR2(a,b,c,d,e,20); nR2(e,a,b,c,d,21); nR2(d,e,a,b,c,22); + nR2(c,d,e,a,b,23); nR2(b,c,d,e,a,24); nR2(a,b,c,d,e,25); + nR2(e,a,b,c,d,26); nR2(d,e,a,b,c,27); nR2(c,d,e,a,b,28); + nR2(b,c,d,e,a,29); nR2(a,b,c,d,e,30); nR2(e,a,b,c,d,31); + nR2(d,e,a,b,c,32); nR2(c,d,e,a,b,33); nR2(b,c,d,e,a,34); + nR2(a,b,c,d,e,35); nR2(e,a,b,c,d,36); nR2(d,e,a,b,c,37); + nR2(c,d,e,a,b,38); nR2(b,c,d,e,a,39); +} + +static void +do_R3(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d, u_int32_t *e, CHAR64LONG16 *block) +{ + nR3(a,b,c,d,e,40); nR3(e,a,b,c,d,41); nR3(d,e,a,b,c,42); + nR3(c,d,e,a,b,43); nR3(b,c,d,e,a,44); nR3(a,b,c,d,e,45); + nR3(e,a,b,c,d,46); nR3(d,e,a,b,c,47); nR3(c,d,e,a,b,48); + nR3(b,c,d,e,a,49); nR3(a,b,c,d,e,50); nR3(e,a,b,c,d,51); + nR3(d,e,a,b,c,52); nR3(c,d,e,a,b,53); nR3(b,c,d,e,a,54); + nR3(a,b,c,d,e,55); nR3(e,a,b,c,d,56); nR3(d,e,a,b,c,57); + nR3(c,d,e,a,b,58); nR3(b,c,d,e,a,59); +} + +static void +do_R4(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d, u_int32_t *e, CHAR64LONG16 *block) +{ + nR4(a,b,c,d,e,60); nR4(e,a,b,c,d,61); nR4(d,e,a,b,c,62); + nR4(c,d,e,a,b,63); nR4(b,c,d,e,a,64); nR4(a,b,c,d,e,65); + nR4(e,a,b,c,d,66); nR4(d,e,a,b,c,67); nR4(c,d,e,a,b,68); + nR4(b,c,d,e,a,69); nR4(a,b,c,d,e,70); nR4(e,a,b,c,d,71); + nR4(d,e,a,b,c,72); nR4(c,d,e,a,b,73); nR4(b,c,d,e,a,74); + nR4(a,b,c,d,e,75); nR4(e,a,b,c,d,76); nR4(d,e,a,b,c,77); + nR4(c,d,e,a,b,78); nR4(b,c,d,e,a,79); +} +#endif + /* * Hash a single 512-bit block. This is the core of the algorithm. */ @@ -92,12 +153,12 @@ static void transform(isc_uint32_t state[5], const unsigned char buffer[64]) { isc_uint32_t a, b, c, d, e; CHAR64LONG16 *block; - unsigned char workspace[64]; + CHAR64LONG16 workspace; INSIST(buffer != NULL); INSIST(state != NULL); - block = (CHAR64LONG16 *)(void *)workspace; + block = &workspace; (void)memcpy(block, buffer, 64); /* Copy context->state[] to working vars */ @@ -107,6 +168,12 @@ transform(isc_uint32_t state[5], const unsigned char buffer[64]) { d = state[3]; e = state[4]; +#ifdef __sparc_v9__ + do_R01(&a, &b, &c, &d, &e, block); + do_R2(&a, &b, &c, &d, &e, block); + do_R3(&a, &b, &c, &d, &e, block); + do_R4(&a, &b, &c, &d, &e, block); +#else /* 4 rounds of 20 operations each. Loop unrolled. */ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); @@ -128,6 +195,7 @@ transform(isc_uint32_t state[5], const unsigned char buffer[64]) { R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); +#endif /* Add the working vars back into context.state[] */ state[0] += a; diff --git a/lib/isc/sockaddr.c b/lib/isc/sockaddr.c index 84d3f68d..eae14249 100644 --- a/lib/isc/sockaddr.c +++ b/lib/isc/sockaddr.c @@ -15,13 +15,14 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sockaddr.c,v 1.48 2001/01/09 21:56:29 bwelling Exp $ */ +/* $Id: sockaddr.c,v 1.48.2.1 2003/07/25 03:31:44 marka Exp $ */ #include <config.h> #include <stdio.h> #include <isc/buffer.h> +#include <isc/hash.h> #include <isc/msgs.h> #include <isc/netaddr.h> #include <isc/print.h> @@ -175,47 +176,50 @@ isc_sockaddr_format(isc_sockaddr_t *sa, char *array, unsigned int size) { unsigned int isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) { - unsigned int length; - const unsigned char *s; + unsigned int length = 0; + const unsigned char *s = NULL; unsigned int h = 0; unsigned int g; + unsigned int p = 0; + const struct in6_addr *in6; REQUIRE(sockaddr != NULL); - - if (address_only) { - switch (sockaddr->type.sa.sa_family) { - case AF_INET: - return (ntohl(sockaddr->type.sin.sin_addr.s_addr)); - case AF_INET6: - s = (const unsigned char *)&sockaddr-> - type.sin6.sin6_addr; - length = sizeof sockaddr->type.sin6.sin6_addr; - break; - default: - UNEXPECTED_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_SOCKADDR, - ISC_MSG_UNKNOWNFAMILY, - "unknown " - "address family: %d"), - (int)sockaddr->type.sa.sa_family); - s = (const unsigned char *)&sockaddr->type; - length = sockaddr->length; + switch (sockaddr->type.sa.sa_family) { + case AF_INET: + s = (const unsigned char *)&sockaddr->type.sin.sin_addr; + p = ntohs(sockaddr->type.sin.sin_port); + length = sizeof(sockaddr->type.sin.sin_addr.s_addr); + break; + case AF_INET6: + in6 = &sockaddr->type.sin6.sin6_addr; + if (IN6_IS_ADDR_V4MAPPED(in6)) { + s = (const unsigned char *)&in6[12]; + length = sizeof(sockaddr->type.sin.sin_addr.s_addr); + } else { + s = (const unsigned char *)in6; + length = sizeof(sockaddr->type.sin6.sin6_addr); } - } else { + p = ntohs(sockaddr->type.sin6.sin6_port); + break; + default: + UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_SOCKADDR, + ISC_MSG_UNKNOWNFAMILY, + "unknown address family: %d"), + (int)sockaddr->type.sa.sa_family); s = (const unsigned char *)&sockaddr->type; length = sockaddr->length; + p = 0; } - while (length > 0) { - h = ( h << 4 ) + *s; - if ((g = ( h & 0xf0000000 )) != 0) { - h = h ^ (g >> 24); - h = h ^ g; - } - s++; - length--; + h = isc_hash_calc(s, length, ISC_TRUE); + if (!address_only) { + g = isc_hash_calc((const unsigned char *)&p, sizeof(p), + ISC_TRUE); + h = h ^ g; /* XXX: we should concatenate h and p first */ } + return (h); } diff --git a/lib/isc/unix/dir.c b/lib/isc/unix/dir.c index bb852885..a2f8c6a4 100644 --- a/lib/isc/unix/dir.c +++ b/lib/isc/unix/dir.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dir.c,v 1.18 2001/06/08 23:50:31 tale Exp $ */ +/* $Id: dir.c,v 1.18.2.1 2003/07/23 06:57:54 marka Exp $ */ /* Principal Authors: DCL */ @@ -164,7 +164,7 @@ isc_dir_current(char *dirname, size_t length, isc_boolean_t end_sep) { * XXXDCL Could automatically allocate memory if dirname == NULL. */ REQUIRE(dirname != NULL); - REQUIRE(length > 0); + REQUIRE(length > 0U); cwd = getcwd(dirname, length); diff --git a/lib/isc/unix/ifiter_ioctl.c b/lib/isc/unix/ifiter_ioctl.c index 92ddc781..4eafb6e9 100644 --- a/lib/isc/unix/ifiter_ioctl.c +++ b/lib/isc/unix/ifiter_ioctl.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999-2001 Internet Software Consortium. + * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ifiter_ioctl.c,v 1.19.2.2.4.1 2003/02/19 04:32:41 marka Exp $ */ +/* $Id: ifiter_ioctl.c,v 1.19.2.5 2003/07/22 04:03:49 marka Exp $ */ /* * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl. @@ -133,7 +133,7 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { goto alloc_failure; } - memset(&iter->ifc.lifc_len, 0, sizeof(iter->ifc.lifc_len)); + memset(&iter->ifc, 0, sizeof(iter->ifc)); #ifdef ISC_HAVE_LIFC_FAMILY iter->ifc.lifc_family = AF_UNSPEC; #endif diff --git a/lib/isc/unix/include/isc/stat.h b/lib/isc/unix/include/isc/stat.h new file mode 100644 index 00000000..eef4f587 --- /dev/null +++ b/lib/isc/unix/include/isc/stat.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: stat.h,v 1.1.2.1 2003/05/20 00:06:56 marka Exp $ */ + +#ifndef ISC_STAT_H +#define ISC_STAT_H 1 + +/***** + ***** Module Info + *****/ + +/* + * Portable netdb.h support. + * + * This module is responsible for defining S_IS??? macros. + * + * MP: + * No impact. + * + * Reliability: + * No anticipated impact. + * + * Resources: + * N/A. + * + * Security: + * No anticipated impact. + * + */ + +/*** + *** Imports. + ***/ + +#include <sys/types.h> +#include <sys/stat.h> + +#endif /* ISC_STAT_H */ diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index 8e19b993..c3052f50 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1998-2002 Internet Software Consortium. + * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket.c,v 1.207.2.14.4.2 2003/02/18 07:28:41 marka Exp $ */ +/* $Id: socket.c,v 1.207.2.19 2003/07/23 06:57:54 marka Exp $ */ #include <config.h> @@ -648,7 +648,7 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev, buffer = ISC_LIST_NEXT(buffer, link); } - INSIST(skip_count == 0); + INSIST(skip_count == 0U); config: msg->msg_iov = iov; @@ -990,7 +990,7 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { dev->n += cc; actual_count = cc; buffer = ISC_LIST_HEAD(dev->bufferlist); - while (buffer != NULL && actual_count > 0) { + while (buffer != NULL && actual_count > 0U) { REQUIRE(ISC_BUFFER_VALID(buffer)); if (isc_buffer_availablelength(buffer) <= actual_count) { actual_count -= isc_buffer_availablelength(buffer); @@ -1003,7 +1003,7 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { } buffer = ISC_LIST_NEXT(buffer, link); if (buffer == NULL) { - INSIST(actual_count == 0); + INSIST(actual_count == 0U); } } @@ -1316,6 +1316,20 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, break; } +#ifdef F_DUPFD + /* + * Leave a space for stdio to work in. + */ + if (sock->fd >= 0 && sock->fd < 20) { + int new, tmp; + new = fcntl(sock->fd, F_DUPFD, 20); + tmp = errno; + (void)close(sock->fd); + errno = tmp; + sock->fd = new; + } +#endif + if (sock->fd >= (int)FD_SETSIZE) { (void)close(sock->fd); isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL, @@ -1740,6 +1754,21 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { memset(&dev->newsocket->address.type.sa, 0, addrlen); fd = accept(sock->fd, &dev->newsocket->address.type.sa, (void *)&addrlen); + +#ifdef F_DUPFD + /* + * Leave a space for stdio to work in. + */ + if (fd >= 0 && fd < 20) { + int new, tmp; + new = fcntl(fd, F_DUPFD, 20); + tmp = errno; + (void)close(fd); + errno = tmp; + fd = new; + } +#endif + if (fd < 0) { if (SOFT_ERROR(errno)) goto soft_error; diff --git a/lib/isc/unix/time.c b/lib/isc/unix/time.c index 328f72b7..2945a878 100644 --- a/lib/isc/unix/time.c +++ b/lib/isc/unix/time.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: time.c,v 1.34.2.5 2001/10/22 23:28:26 gson Exp $ */ +/* $Id: time.c,v 1.34.2.6 2003/07/23 06:57:54 marka Exp $ */ #include <config.h> @@ -173,7 +173,7 @@ isc_time_now(isc_time_t *t) { * Ensure the tv_sec value fits in t->seconds. */ if (sizeof(tv.tv_sec) > sizeof(t->seconds) && - ((tv.tv_sec | (unsigned int)-1) ^ (unsigned int)-1) != 0) + ((tv.tv_sec | (unsigned int)-1) ^ (unsigned int)-1) != 0U) return (ISC_R_RANGE); t->seconds = tv.tv_sec; @@ -366,7 +366,7 @@ isc_time_secondsastimet(isc_time_t *t, time_t *secondsp) { (time_t)0.5 != 0.5 && /* Not a floating point type. */ (i = (time_t)-1) != 4294967295u && /* Is signed. */ (seconds & - (1U << (sizeof(time_t) * CHAR_BIT - 1))) != 0) { /* Negative. */ + (1U << (sizeof(time_t) * CHAR_BIT - 1))) != 0U) { /* Negative. */ /* * This UNUSED() is here to shut up the IRIX compiler: * variable "i" was set but never used diff --git a/lib/isc/win32/errno2result.c b/lib/isc/win32/errno2result.c index 9cee47fb..b9cf084d 100644 --- a/lib/isc/win32/errno2result.c +++ b/lib/isc/win32/errno2result.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2002 Internet Software Consortium. + * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: errno2result.c,v 1.4.2.2 2002/02/20 02:17:28 marka Exp $ */ +/* $Id: errno2result.c,v 1.4.2.5 2003/07/22 04:03:50 marka Exp $ */ #include <config.h> @@ -71,372 +71,3 @@ isc__errno2result(int posixerrno) { return (ISC_R_UNEXPECTED); } } - -/* - * Note this will cause a memory leak unless the memory allocated here - * is freed by calling LocalFree - */ -char * -FormatError(int error) { - LPVOID lpMsgBuf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - error, - /* Default language */ - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, - NULL); - - return (lpMsgBuf); -} - -char * __cdecl -NTstrMessage(int err) { - char *retmsg = NULL; - - /* Copy the error value first in case of other errors */ - DWORD errval = err; - - /* Get the Winsock2 error messages */ - if (errval >= WSABASEERR && errval <= (WSABASEERR + 1015)) { - retmsg = GetWSAErrorMessage(errval); - if (retmsg != NULL) - return (retmsg); - } - /* - * If it's not one of the standard Unix error codes, - * try a system error message - */ - if (errval > (DWORD) _sys_nerr) { - return (FormatError(errval)); - } else { - return (strerror(errval)); - } -} - -char * __cdecl -NTstrerror(int err) { - /* Copy the error value first in case of other errors */ - DWORD errval = err; - - return (NTstrMessage(errval)); -} - -/* - * This is a replacement for perror, but it also reports the error value. - */ -void __cdecl -NTperror(char *errmsg) { - /* Copy the error value first in case of other errors */ - int errval = errno; - - fprintf(stderr, "%s: %s\n", errmsg, NTstrMessage(errval)); -} - -/* - * Return the error string related to Winsock2 errors. - * This function is necessary since FormatMessage knows nothing about them - * and there is no function to get them. - */ -char * -GetWSAErrorMessage(int errval) { - char *msg; - - switch (errval) { - - case WSAEINTR: - msg = "Interrupted system call"; - break; - - case WSAEBADF: - msg = "Bad file number"; - break; - - case WSAEACCES: - msg = "Permission denied"; - break; - - case WSAEFAULT: - msg = "Bad address"; - break; - - case WSAEINVAL: - msg = "Invalid argument"; - break; - - case WSAEMFILE: - msg = "Too many open sockets"; - break; - - case WSAEWOULDBLOCK: - msg = "Operation would block"; - break; - - case WSAEINPROGRESS: - msg = "Operation now in progress"; - break; - - case WSAEALREADY: - msg = "Operation already in progress"; - break; - - case WSAENOTSOCK: - msg = "Socket operation on non-socket"; - break; - - case WSAEDESTADDRREQ: - msg = "Destination address required"; - break; - - case WSAEMSGSIZE: - msg = "Message too long"; - break; - - case WSAEPROTOTYPE: - msg = "Protocol wrong type for socket"; - break; - - case WSAENOPROTOOPT: - msg = "Bad protocol option"; - break; - - case WSAEPROTONOSUPPORT: - msg = "Protocol not supported"; - break; - - case WSAESOCKTNOSUPPORT: - msg = "Socket type not supported"; - break; - - case WSAEOPNOTSUPP: - msg = "Operation not supported on socket"; - break; - - case WSAEPFNOSUPPORT: - msg = "Protocol family not supported"; - break; - - case WSAEAFNOSUPPORT: - msg = "Address family not supported"; - break; - - case WSAEADDRINUSE: - msg = "Address already in use"; - break; - - case WSAEADDRNOTAVAIL: - msg = "Can't assign requested address"; - break; - - case WSAENETDOWN: - msg = "Network is down"; - break; - - case WSAENETUNREACH: - msg = "Network is unreachable"; - break; - - case WSAENETRESET: - msg = "Net connection reset"; - break; - - case WSAECONNABORTED: - msg = "Software caused connection abort"; - break; - - case WSAECONNRESET: - msg = "Connection reset by peer"; - break; - - case WSAENOBUFS: - msg = "No buffer space available"; - break; - - case WSAEISCONN: - msg = "Socket is already connected"; - break; - - case WSAENOTCONN: - msg = "Socket is not connected"; - break; - - case WSAESHUTDOWN: - msg = "Can't send after socket shutdown"; - break; - - case WSAETOOMANYREFS: - msg = "Too many references: can't splice"; - break; - - case WSAETIMEDOUT: - msg = "Connection timed out"; - break; - - case WSAECONNREFUSED: - msg = "Connection refused"; - break; - - case WSAELOOP: - msg = "Too many levels of symbolic links"; - break; - - case WSAENAMETOOLONG: - msg = "File name too long"; - break; - - case WSAEHOSTDOWN: - msg = "Host is down"; - break; - - case WSAEHOSTUNREACH: - msg = "No route to host"; - break; - - case WSAENOTEMPTY: - msg = "Directory not empty"; - break; - - case WSAEPROCLIM: - msg = "Too many processes"; - break; - - case WSAEUSERS: - msg = "Too many users"; - break; - - case WSAEDQUOT: - msg = "Disc quota exceeded"; - break; - - case WSAESTALE: - msg = "Stale NFS file handle"; - break; - - case WSAEREMOTE: - msg = "Too many levels of remote in path"; - break; - - case WSASYSNOTREADY: - msg = "Network system is unavailable"; - break; - - case WSAVERNOTSUPPORTED: - msg = "Winsock version out of range"; - break; - - case WSANOTINITIALISED: - msg = "WSAStartup not yet called"; - break; - - case WSAEDISCON: - msg = "Graceful shutdown in progress"; - break; -/* - case WSAHOST_NOT_FOUND: - msg = "Host not found"; - break; - - case WSANO_DATA: - msg = "No host data of that type was found"; - break; -*/ - default: - msg = NULL; - break; - } - return (msg); -} - -/* - * These error messages are more informative about CryptAPI Errors than the - * standard error messages - */ - -char * -GetCryptErrorMessage(int errval) { - char *msg; - - switch (errval) { - - case NTE_BAD_FLAGS: - msg = "The dwFlags parameter has an illegal value."; - break; - case NTE_BAD_KEYSET: - msg = "The Registry entry for the key container " - "could not be opened and may not exist."; - break; - case NTE_BAD_KEYSET_PARAM: - msg = "The pszContainer or pszProvider parameter " - "is set to an illegal value."; - break; - case NTE_BAD_PROV_TYPE: - msg = "The value of the dwProvType parameter is out " - "of range. All provider types must be from " - "1 to 999, inclusive."; - break; - case NTE_BAD_SIGNATURE: - msg = "The provider DLL signature did not verify " - "correctly. Either the DLL or the digital " - "signature has been tampered with."; - break; - case NTE_EXISTS: - msg = "The dwFlags parameter is CRYPT_NEWKEYSET, but the key" - " container already exists."; - break; - case NTE_KEYSET_ENTRY_BAD: - msg = "The Registry entry for the pszContainer key container " - "was found (in the HKEY_CURRENT_USER window), but is " - "corrupt. See the section System Administration for " - " etails about CryptoAPI's Registry usage."; - break; - case NTE_KEYSET_NOT_DEF: - msg = "No Registry entry exists in the HKEY_CURRENT_USER " - "window for the key container specified by " - "pszContainer."; - break; - case NTE_NO_MEMORY: - msg = "The CSP ran out of memory during the operation."; - break; - case NTE_PROV_DLL_NOT_FOUND: - msg = "The provider DLL file does not exist or is not on the " - "current path."; - break; - case NTE_PROV_TYPE_ENTRY_BAD: - msg = "The Registry entry for the provider type specified by " - "dwProvType is corrupt. This error may relate to " - "either the user default CSP list or the machine " - "default CSP list. See the section System " - "Administration for details about CryptoAPI's " - "Registry usage."; - break; - case NTE_PROV_TYPE_NO_MATCH: - msg = "The provider type specified by dwProvType does not " - "match the provider type found in the Registry. Note " - "that this error can only occur when pszProvider " - "specifies an actual CSP name."; - break; - case NTE_PROV_TYPE_NOT_DEF: - msg = "No Registry entry exists for the provider type " - "specified by dwProvType."; - break; - case NTE_PROVIDER_DLL_FAIL: - msg = "The provider DLL file could not be loaded, and " - "may not exist. If it exists, then the file is " - "not a valid DLL."; - break; - case NTE_SIGNATURE_FILE_BAD: - msg = "An error occurred while loading the DLL file image, " - "prior to verifying its signature."; - break; - - default: - msg = NULL; - break; - } - return msg; -} - diff --git a/lib/isc/win32/include/isc/ipv6.h b/lib/isc/win32/include/isc/ipv6.h index 000e9ff6..c45ee52b 100644 --- a/lib/isc/win32/include/isc/ipv6.h +++ b/lib/isc/win32/include/isc/ipv6.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001 Internet Software Consortium. + * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ipv6.h,v 1.9 2001/07/17 20:29:33 gson Exp $ */ +/* $Id: ipv6.h,v 1.9.2.2 2003/07/22 04:03:52 marka Exp $ */ #ifndef ISC_IPV6_H #define ISC_IPV6_H 1 @@ -36,6 +36,7 @@ #define PF_INET6 AF_INET6 #endif +#if _MSC_VER < 1300 #define s6_addr8 s6_addr #define in6_addr in_addr6 @@ -98,6 +99,8 @@ struct in6_pktinfo { #define IN6_IS_ADDR_MULTICAST(a) \ ((a)->s6_addr8[0] == 0xffU) +#endif + ISC_LANG_ENDDECLS #endif /* ISC_IPV6_H */ diff --git a/lib/isc/win32/include/isc/stat.h b/lib/isc/win32/include/isc/stat.h index 04c92797..b75840f9 100644 --- a/lib/isc/win32/include/isc/stat.h +++ b/lib/isc/win32/include/isc/stat.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001 Internet Software Consortium. + * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: stat.h,v 1.3 2001/07/09 21:06:30 gson Exp $ */ +/* $Id: stat.h,v 1.3.2.2 2003/07/22 04:03:52 marka Exp $ */ #ifndef ISC_STAT_H #define ISC_STAT_H 1 @@ -37,7 +37,10 @@ #define S_IWOTH _S_IWRITE /* Other write permission */ #ifndef S_ISDIR -# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR) +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif +#ifndef S_ISREG +# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif #endif /* ISC_STAT_H */ diff --git a/lib/isc/win32/include/isc/win32os.h b/lib/isc/win32/include/isc/win32os.h new file mode 100644 index 00000000..1f4d3348 --- /dev/null +++ b/lib/isc/win32/include/isc/win32os.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: win32os.h,v 1.2.176.2 2003/07/22 04:03:52 marka Exp $ */ + +#ifndef ISC_WIN32OS_H +#define ISC_WIN32OS_H 1 + +#include <isc/lang.h> + +ISC_LANG_BEGINDECLS + +/* + * Return the number of CPUs available on the system, or 1 if this cannot + * be determined. + */ + +unsigned int +isc_win32os_majorversion(void); +/* + * Major Version of the O/S. + */ + +unsigned int +isc_win32os_minorversion(void); +/* + * Minor Version of the O/S. + */ + +unsigned int +isc_win32os_servicepackmajor(void); +/* + * Major Version of the Service Pack for O/S. + */ + +unsigned int +isc_win32os_servicepackminor(void); +/* + * Minor Version of the Service Pack for O/S. + */ + +int +isc_win32os_versioncheck(unsigned int major, unsigned int minor, + unsigned int updatemajor, unsigned int updateminor); + +/* + * Checks the current version of the operating system with the + * supplied version information. + * Returns: + * -1 if less than the version information supplied + * 0 if equal to all of the version information supplied + * +1 if greater than the version information supplied + */ + +ISC_LANG_ENDDECLS + +#endif /* ISC_OS_H */ diff --git a/lib/isc/win32/ipv6.c b/lib/isc/win32/ipv6.c index 694c427c..a55a8181 100644 --- a/lib/isc/win32/ipv6.c +++ b/lib/isc/win32/ipv6.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1999-2001 Internet Software Consortium. + * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,15 +15,17 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ipv6.c,v 1.4 2001/07/12 05:58:27 mayer Exp $ */ +/* $Id: ipv6.c,v 1.4.2.2 2003/07/22 04:03:50 marka Exp $ */ #define off_t _off_t #include <isc/net.h> #include <isc/platform.h> +#if _MSC_VER < 1300 LIBISC_EXTERNAL_DATA const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; LIBISC_EXTERNAL_DATA const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; +#endif diff --git a/lib/isc/win32/libisc.def b/lib/isc/win32/libisc.def index f0bbf5d4..832d99e2 100644 --- a/lib/isc/win32/libisc.def +++ b/lib/isc/win32/libisc.def @@ -1,442 +1,454 @@ -LIBRARY libisc - -; Exported Functions -EXPORTS - -isc_assertion_setcallback -isc_assertion_typetotext -isc_base64_totext -isc_base64_decodestring -isc_base64_tobuffer -isc_bitstring_init -isc_bitstring_invalidate -isc_bitstring_copy -isc_buffer_allocate -isc_buffer_free -isc__buffer_init -isc__buffer_invalidate -isc__buffer_region -isc__buffer_usedregion -isc__buffer_availableregion -isc__buffer_add -isc__buffer_subtract -isc__buffer_clear -isc__buffer_consumedregion -isc__buffer_remainingregion -isc__buffer_activeregion -isc__buffer_setactive -isc__buffer_first -isc__buffer_forward -isc__buffer_back -isc_buffer_compact -isc_buffer_getuint8 -isc__buffer_putuint8 -isc_buffer_getuint16 -isc__buffer_putuint16 -isc_buffer_getuint32 -isc__buffer_putuint32 -isc__buffer_putmem -isc__buffer_putstr -isc_buffer_copyregion -isc_bufferlist_usedcount -isc_bufferlist_availablecount -isc_commandline_parse - - -isc_entropy_create -isc_entropy_attach -isc_entropy_detach -isc_entropy_createfilesource -isc_entropy_destroysource -isc_entropy_createsamplesource -isc_entropy_createcallbacksource -isc_entropy_stopcallbacksources -isc_entropy_addcallbacksample -isc_entropy_addsample -isc_entropy_getdata -isc_entropy_putdata -isc_entropy_stats -isc_entropy_usebestsource -isc_error_setunexpected -isc_error_setfatal -isc_error_unexpected -isc_error_fatal -isc_error_runtimecheck -isc_event_allocate -isc_event_free -isc_file_settime -isc_file_getmodtime -isc_file_mktemplate -isc_file_openunique -isc_file_remove -isc_file_rename -isc_file_exists -isc_file_ischdiridempotent -isc_file_isabsolute -isc_file_iscurrentdir -isc_file_template -isc_file_renameunique -isc_file_basename -isc_file_progname -isc_file_safemovefile -isc_file_absolutepath -isc_fsaccess_add -isc_fsaccess_remove -isc_fsaccess_set -isc_hex_totext -isc_hex_decodestring -isc_hex_tobuffer -isc_hmacmd5_init -isc_hmacmd5_invalidate -isc_hmacmd5_update -isc_hmacmd5_sign -isc_hmacmd5_verify -isc_interfaceiter_create -isc_interfaceiter_first -isc_interfaceiter_current -isc_interfaceiter_next -isc_interfaceiter_destroy -isc_lex_setcomments -isc_lex_create -isc_lex_destroy -isc_lex_getcomments -isc_lex_setcomments -isc_lex_getspecials -isc_lex_setspecials -isc_lex_openfile -isc_lex_openstream -isc_lex_openbuffer -isc_lex_close -isc_lex_gettoken -isc_lex_getmastertoken -isc_lex_ungettoken -isc_lex_getlasttokentext -isc_lex_getsourcename -isc_lex_getsourceline -isc_lex_isfile -isc_lfsr_init -isc_lfsr_generate -isc_lfsr_skip -isc_lfsr_generate32 -isc_lib_initmsgcat -isc_log_createchannel -isc_log_createchannel -isc_log_create -isc_logconfig_create -isc_logconfig_get -isc_logconfig_use -isc_log_destroy -isc_logconfig_destroy -isc_log_registercategories -isc_log_registermodules -isc_log_createchannel -isc_log_usechannel -isc_log_write -isc_log_vwrite -isc_log_write1 -isc_log_vwrite1 -isc_log_iwrite -isc_log_ivwrite -isc_log_iwrite1 -isc_log_ivwrite1 -isc_log_setdebuglevel -isc_log_getdebuglevel -isc_log_wouldlog -isc_log_write -isc_log_setduplicateinterval -isc_log_getduplicateinterval -isc_log_settag -isc_log_gettag -isc_log_opensyslog -isc_log_closefilelogs -isc_log_categorybyname -isc_log_modulebyname -isc_log_setcontext -isc_md5_init -isc_md5_invalidate -isc_md5_update -isc_md5_final -isc_mem_attach -isc_mem_detach -isc_mem_detach -isc_mem_create -isc_mem_createx -isc_mem_attach -isc_mem_detach -isc_mem_destroy -isc_mem_ondestroy -isc_mem_stats -isc_mem_setdestroycheck -isc_mem_setquota -isc_mem_getquota -isc_mem_inuse -isc_mem_setwater -isc_mempool_create -isc_mempool_destroy -isc_mempool_setname -isc_mempool_associatelock -isc_mempool_getfreemax -isc_mempool_setfreemax -isc_mempool_getfreecount -isc_mempool_getmaxalloc -isc_mempool_setmaxalloc -isc_mempool_getallocated -isc_mempool_getfillcount -isc_mempool_setfillcount -isc__mem_get -isc__mem_putanddetach -isc__mem_put -isc__mem_allocate -isc__mem_free -isc__mem_strdup -isc__mempool_get -isc__mempool_put -isc_msgcat_open -isc_msgcat_close -isc_msgcat_get -isc_mutexblock_init -isc_mutexblock_destroy -isc_netaddr_equal -isc_netaddr_eqprefix -isc_netaddr_masktoprefixlen -isc_netaddr_totext -isc_netaddr_format -isc_netaddr_fromsockaddr -isc_netaddr_fromin -isc_netaddr_fromin6 -isc_netaddr_any -isc_netaddr_any6 -isc_netaddr_ismulticast -isc_netaddr_fromv4mapped -isc_ntpaths_init -isc_ntpaths_get -isc_ondestroy_init -isc_ondestroy_register -isc_ondestroy_notify -isc_task_sendanddetach -isc_os_ncpus -isc_quota_init -isc_quota_destroy -isc_quota_reserve -isc_quota_release -isc_quota_attach -isc_quota_detach -isc_random_seed -isc_random_get -isc_random_jitter -isc_ratelimiter_create -isc_ratelimiter_setinterval -isc_ratelimiter_setpertic -isc_ratelimiter_enqueue -isc_ratelimiter_shutdown -isc_ratelimiter_attach -isc_ratelimiter_detach -isc_resource_setlimit -isc_resource_getlimit -isc_result_totext -isc_result_register -isc_rwlock_init -isc_rwlock_lock -isc_rwlock_trylock -isc_rwlock_unlock +LIBRARY libisc
+
+; Exported Functions
+EXPORTS
+
+isc_assertion_setcallback
+isc_assertion_typetotext
+isc_base64_totext
+isc_base64_decodestring
+isc_base64_tobuffer
+isc_bitstring_init
+isc_bitstring_invalidate
+isc_bitstring_copy
+isc_buffer_allocate
+isc_buffer_free
+isc__buffer_init
+isc__buffer_invalidate
+isc__buffer_region
+isc__buffer_usedregion
+isc__buffer_availableregion
+isc__buffer_add
+isc__buffer_subtract
+isc__buffer_clear
+isc__buffer_consumedregion
+isc__buffer_remainingregion
+isc__buffer_activeregion
+isc__buffer_setactive
+isc__buffer_first
+isc__buffer_forward
+isc__buffer_back
+isc_buffer_compact
+isc_buffer_getuint8
+isc__buffer_putuint8
+isc_buffer_getuint16
+isc__buffer_putuint16
+isc_buffer_getuint32
+isc__buffer_putuint32
+isc__buffer_putmem
+isc__buffer_putstr
+isc_buffer_copyregion
+isc_bufferlist_usedcount
+isc_bufferlist_availablecount
+isc_commandline_parse
+
+
+isc_entropy_create
+isc_entropy_attach
+isc_entropy_detach
+isc_entropy_createfilesource
+isc_entropy_destroysource
+isc_entropy_createsamplesource
+isc_entropy_createcallbacksource
+isc_entropy_stopcallbacksources
+isc_entropy_addcallbacksample
+isc_entropy_addsample
+isc_entropy_getdata
+isc_entropy_putdata
+isc_entropy_stats
+isc_entropy_usebestsource
+isc_error_setunexpected
+isc_error_setfatal
+isc_error_unexpected
+isc_error_fatal
+isc_error_runtimecheck
+isc_event_allocate
+isc_event_free
+isc_file_settime
+isc_file_getmodtime
+isc_file_mktemplate
+isc_file_openunique
+isc_file_remove
+isc_file_rename
+isc_file_exists
+isc_file_ischdiridempotent
+isc_file_isabsolute
+isc_file_iscurrentdir
+isc_file_template
+isc_file_renameunique
+isc_file_basename
+isc_file_progname
+isc_file_safemovefile
+isc_file_absolutepath
+isc_fsaccess_add
+isc_fsaccess_remove
+isc_fsaccess_set
+isc_hash_calc +isc_hash_create +isc_hash_ctxattach +isc_hash_ctxcalc +isc_hash_ctxcreate +isc_hash_ctxdetach +isc_hash_ctxinit +isc_hash_destroy +isc_hash_init +isc_hex_totext
+isc_hex_decodestring
+isc_hex_tobuffer
+isc_hmacmd5_init
+isc_hmacmd5_invalidate
+isc_hmacmd5_update
+isc_hmacmd5_sign
+isc_hmacmd5_verify
+isc_interfaceiter_create
+isc_interfaceiter_first
+isc_interfaceiter_current
+isc_interfaceiter_next
+isc_interfaceiter_destroy
+isc_lex_setcomments
+isc_lex_create
+isc_lex_destroy
+isc_lex_getcomments
+isc_lex_setcomments
+isc_lex_getspecials
+isc_lex_setspecials
+isc_lex_openfile
+isc_lex_openstream
+isc_lex_openbuffer
+isc_lex_close
+isc_lex_gettoken
+isc_lex_getmastertoken
+isc_lex_ungettoken
+isc_lex_getlasttokentext
+isc_lex_getsourcename
+isc_lex_getsourceline
+isc_lex_isfile
+isc_lfsr_init
+isc_lfsr_generate
+isc_lfsr_skip
+isc_lfsr_generate32
+isc_lib_initmsgcat
+isc_log_createchannel
+isc_log_createchannel
+isc_log_create
+isc_logconfig_create
+isc_logconfig_get
+isc_logconfig_use
+isc_log_destroy
+isc_logconfig_destroy
+isc_log_registercategories
+isc_log_registermodules
+isc_log_createchannel
+isc_log_usechannel
+isc_log_write
+isc_log_vwrite
+isc_log_write1
+isc_log_vwrite1
+isc_log_iwrite
+isc_log_ivwrite
+isc_log_iwrite1
+isc_log_ivwrite1
+isc_log_setdebuglevel
+isc_log_getdebuglevel
+isc_log_wouldlog
+isc_log_write
+isc_log_setduplicateinterval
+isc_log_getduplicateinterval
+isc_log_settag
+isc_log_gettag
+isc_log_opensyslog
+isc_log_closefilelogs
+isc_log_categorybyname
+isc_log_modulebyname
+isc_log_setcontext
+isc_md5_init
+isc_md5_invalidate
+isc_md5_update
+isc_md5_final
+isc_mem_attach
+isc_mem_detach
+isc_mem_detach
+isc_mem_create
+isc_mem_createx
+isc_mem_attach
+isc_mem_detach
+isc_mem_destroy
+isc_mem_ondestroy
+isc_mem_stats
+isc_mem_setdestroycheck
+isc_mem_setquota
+isc_mem_getquota
+isc_mem_inuse
+isc_mem_setwater
+isc_mempool_create
+isc_mempool_destroy
+isc_mempool_setname
+isc_mempool_associatelock
+isc_mempool_getfreemax
+isc_mempool_setfreemax
+isc_mempool_getfreecount
+isc_mempool_getmaxalloc
+isc_mempool_setmaxalloc
+isc_mempool_getallocated
+isc_mempool_getfillcount
+isc_mempool_setfillcount
+isc__mem_get
+isc__mem_putanddetach
+isc__mem_put
+isc__mem_allocate
+isc__mem_free
+isc__mem_strdup
+isc__mempool_get
+isc__mempool_put
+isc_msgcat_open
+isc_msgcat_close
+isc_msgcat_get
+isc_mutexblock_init
+isc_mutexblock_destroy
+isc_netaddr_equal
+isc_netaddr_eqprefix
+isc_netaddr_masktoprefixlen
+isc_netaddr_totext
+isc_netaddr_format
+isc_netaddr_fromsockaddr
+isc_netaddr_fromin
+isc_netaddr_fromin6
+isc_netaddr_any
+isc_netaddr_any6
+isc_netaddr_ismulticast
+isc_netaddr_fromv4mapped
+isc_ntpaths_init
+isc_ntpaths_get
+isc_ondestroy_init
+isc_ondestroy_register
+isc_ondestroy_notify
+isc_task_sendanddetach
+isc_os_ncpus
+isc_quota_init
+isc_quota_destroy
+isc_quota_reserve
+isc_quota_release
+isc_quota_attach
+isc_quota_detach
+isc_random_seed
+isc_random_get
+isc_random_jitter
+isc_ratelimiter_create
+isc_ratelimiter_setinterval
+isc_ratelimiter_setpertic
+isc_ratelimiter_enqueue
+isc_ratelimiter_shutdown
+isc_ratelimiter_attach
+isc_ratelimiter_detach
+isc_resource_setlimit
+isc_resource_getlimit
+isc_result_totext
+isc_result_register
+isc_rwlock_init
+isc_rwlock_lock
+isc_rwlock_trylock
+isc_rwlock_unlock
isc_rwlock_destroy -isc_serial_lt -isc_serial_gt -isc_serial_le -isc_serial_ge -isc_serial_eq -isc_serial_ne -isc_sha1_init -isc_sha1_invalidate -isc_sha1_update -isc_sha1_final -isc_sockaddr_equal -isc_sockaddr_eqaddr -isc_sockaddr_eqaddrprefix -isc_sockaddr_hash -isc_sockaddr_any -isc_sockaddr_any6 -isc_sockaddr_anyofpf -isc_sockaddr_fromin -isc_sockaddr_fromin6 -isc_sockaddr_v6fromin -isc_sockaddr_fromnetaddr -isc_sockaddr_pf -isc_sockaddr_setport -isc_sockaddr_getport -isc_sockaddr_totext -isc_sockaddr_format -isc_sockaddr_ismulticast -isc_socket_create -isc_socket_cancel -;isc_socket_shutdown -isc_socket_attach -isc_socket_detach -isc_socket_bind -isc_socket_listen -isc_socket_accept -isc_socket_connect -isc_socket_getpeername -isc_socket_getsockname -isc_socket_recv -isc_socket_recvv -isc_socket_recv2 -isc_socket_send -isc_socket_sendto -isc_socket_sendv -isc_socket_sendtov -isc_socket_sendto2 -isc_socketmgr_create -isc_socketmgr_destroy -isc_socket_gettype -isc_socket_isbound -isc_stdio_open -isc_stdio_close -isc_stdio_seek -isc_stdio_read -isc_stdio_write -isc_stdio_flush -isc_stdio_sync -isc_string_touint64 -isc_string_separate -isc_symtab_create -isc_symtab_destroy -isc_symtab_lookup -isc_symtab_define -isc_symtab_undefine -isc_task_create -isc_task_attach -isc_task_detach -isc_task_send -isc_task_sendanddetach -isc_task_purgerange -isc_task_purge -isc_task_purgeevent -isc_task_unsendrange -isc_task_unsend -isc_task_onshutdown -isc_task_shutdown -isc_task_destroy -isc_task_setname -isc_task_getname -isc_task_gettag -isc_task_beginexclusive -isc_task_endexclusive -isc_task_endexclusive -isc_taskmgr_create -isc_taskmgr_destroy -isc_taskpool_create -isc_taskpool_gettask -isc_taskpool_destroy -isc_timer_create -isc_timer_reset -isc_timer_touch -isc_timer_attach -isc_timer_detach -isc_timermgr_create -isc_timermgr_destroy -isc_condition_init -isc_condition_wait -isc_condition_signal -isc_condition_broadcast -isc_condition_destroy -isc_condition_waituntil -isc_dir_init -isc_dir_open -isc_dir_read -isc_dir_reset -isc_dir_close -isc_dir_chdir -isc_dir_chroot -isc_dir_current -isc_net_probeipv4 -isc_net_probeipv6 -isc_net_ntop -isc_net_pton -isc_net_aton -isc_once_do -isc_stdtime_get - -isc_thread_create -isc_thread_join -isc_thread_setconcurrency -isc_interval_set -isc_time_subtract -isc_interval_iszero -isc_time_settoepoch -isc_time_isepoch -isc_time_now -isc_time_nowplusinterval -isc_time_compare -isc_time_add -isc_time_subtract -isc_time_microdiff -isc_time_nanoseconds -isc_keyboard_open -isc_keyboard_close -isc_keyboard_getchar -isc_keyboard_canceled -isc_app_start -isc_app_onrun -isc_app_run -isc_app_shutdown -isc_app_reload -isc_app_finish -isc_app_block -isc_app_unblock -isc_thread_create -isc_thread_join -isc_thread_setconcurrency -isc_net_probeipv4 -isc_net_probeipv6 -isc_net_ntop -isc_net_pton -isc_net_aton -openlog -syslog -closelog -isc_syslog_facilityfromstring -isc_ntfile_fopen -isc_ntfile_fclose -isc_ntfile_fwrite -isc_ntfile_fread -isc_ntfile_fseek -isc_ntfile_flush -isc_ntfile_sync -isc_ntfile_printf -isc_ntfile_fprintf -isc_ntfile_vfprintf -isc_ntfile_getaddress -isc_ntfile_getc -isc_ntfile_fgetc -isc_ntfile_fgets -isc_ntfile_fputc -isc_ntfile_fputs -isc_ntfile_fgetpos -isc_ntfile_freopen -isc_ntfile_fdopen -isc_ntfile_open -isc_ntfile_close -isc_ntfile_read -isc_ntfile_write - - -; Exported Data - -EXPORTS - -;isc_categories -;isc_lctx -;isc_modules - -isc_mem_debugging DATA - -isc_commandline_index -isc_commandline_option DATA -isc_commandline_argument DATA -isc_commandline_progname DATA -isc_commandline_errprint DATA -isc_commandline_reset DATA -isc_assertion_failed DATA -_iob DATA - +isc_rwlock_tryupgrade
+isc_rwlock_downgrade
+isc_serial_lt
+isc_serial_gt
+isc_serial_le
+isc_serial_ge
+isc_serial_eq
+isc_serial_ne
+isc_sha1_init
+isc_sha1_invalidate
+isc_sha1_update
+isc_sha1_final
+isc_sockaddr_equal
+isc_sockaddr_eqaddr
+isc_sockaddr_eqaddrprefix
+isc_sockaddr_hash
+isc_sockaddr_any
+isc_sockaddr_any6
+isc_sockaddr_anyofpf
+isc_sockaddr_fromin
+isc_sockaddr_fromin6
+isc_sockaddr_v6fromin
+isc_sockaddr_fromnetaddr
+isc_sockaddr_pf
+isc_sockaddr_setport
+isc_sockaddr_getport
+isc_sockaddr_totext
+isc_sockaddr_format
+isc_sockaddr_ismulticast
+isc_socket_create
+isc_socket_cancel
+;isc_socket_shutdown
+isc_socket_attach
+isc_socket_detach
+isc_socket_bind
+isc_socket_listen
+isc_socket_accept
+isc_socket_connect
+isc_socket_getpeername
+isc_socket_getsockname
+isc_socket_recv
+isc_socket_recvv
+isc_socket_recv2
+isc_socket_send
+isc_socket_sendto
+isc_socket_sendv
+isc_socket_sendtov
+isc_socket_sendto2
+isc_socketmgr_create
+isc_socketmgr_destroy
+isc_socket_gettype
+isc_socket_isbound
+isc_stdio_open
+isc_stdio_close
+isc_stdio_seek
+isc_stdio_read
+isc_stdio_write
+isc_stdio_flush
+isc_stdio_sync
+isc__strerror
+isc_string_touint64
+isc_string_separate
+isc_symtab_create
+isc_symtab_destroy
+isc_symtab_lookup
+isc_symtab_define
+isc_symtab_undefine
+isc_task_create
+isc_task_attach
+isc_task_detach
+isc_task_send
+isc_task_sendanddetach
+isc_task_purgerange
+isc_task_purge
+isc_task_purgeevent
+isc_task_unsendrange
+isc_task_unsend
+isc_task_onshutdown
+isc_task_shutdown
+isc_task_destroy
+isc_task_setname
+isc_task_getname
+isc_task_gettag
+isc_task_beginexclusive
+isc_task_endexclusive
+isc_task_endexclusive
+isc_taskmgr_create
+isc_taskmgr_destroy
+isc_taskpool_create
+isc_taskpool_gettask
+isc_taskpool_destroy
+isc_timer_create
+isc_timer_reset
+isc_timer_touch
+isc_timer_attach
+isc_timer_detach
+isc_timermgr_create
+isc_timermgr_destroy
+isc_condition_init
+isc_condition_wait
+isc_condition_signal
+isc_condition_broadcast
+isc_condition_destroy
+isc_condition_waituntil
+isc_dir_init
+isc_dir_open
+isc_dir_read
+isc_dir_reset
+isc_dir_close
+isc_dir_chdir
+isc_dir_chroot
+isc_dir_current
+isc_net_probeipv4
+isc_net_probeipv6
+isc_net_ntop
+isc_net_pton
+isc_net_aton
+isc_once_do
+isc_stdtime_get
+
+isc_thread_create
+isc_thread_join
+isc_thread_setconcurrency
+isc_interval_set
+isc_time_subtract
+isc_interval_iszero
+isc_time_settoepoch
+isc_time_isepoch
+isc_time_now
+isc_time_nowplusinterval
+isc_time_compare
+isc_time_add
+isc_time_subtract
+isc_time_microdiff
+isc_time_nanoseconds
+isc_keyboard_open
+isc_keyboard_close
+isc_keyboard_getchar
+isc_keyboard_canceled
+isc_app_start
+isc_app_onrun
+isc_app_run
+isc_app_shutdown
+isc_app_reload
+isc_app_finish
+isc_app_block
+isc_app_unblock
+isc_thread_create
+isc_thread_join
+isc_thread_setconcurrency
+isc_net_probeipv4
+isc_net_probeipv6
+isc_net_ntop
+isc_net_pton
+isc_net_aton
+openlog
+syslog
+closelog
+isc_syslog_facilityfromstring
+isc_ntfile_fopen
+isc_ntfile_fclose
+isc_ntfile_fwrite
+isc_ntfile_fread
+isc_ntfile_fseek
+isc_ntfile_flush
+isc_ntfile_sync
+isc_ntfile_printf
+isc_ntfile_fprintf
+isc_ntfile_vfprintf
+isc_ntfile_getaddress
+isc_ntfile_getc
+isc_ntfile_fgetc
+isc_ntfile_fgets
+isc_ntfile_fputc
+isc_ntfile_fputs
+isc_ntfile_fgetpos
+isc_ntfile_freopen
+isc_ntfile_fdopen
+isc_ntfile_open
+isc_ntfile_close
+isc_ntfile_read
+isc_ntfile_write
+
+
+; Exported Data
+
+EXPORTS
+
+;isc_categories
+;isc_lctx
+;isc_modules
+
+isc_mem_debugging DATA
+
+isc_commandline_index
+isc_commandline_option DATA
+isc_commandline_argument DATA
+isc_commandline_progname DATA
+isc_commandline_errprint DATA
+isc_commandline_reset DATA
+isc_assertion_failed DATA
+_iob DATA
+
diff --git a/lib/isc/win32/libisc.dsp b/lib/isc/win32/libisc.dsp index a9a4b465..0cfc4522 100644 --- a/lib/isc/win32/libisc.dsp +++ b/lib/isc/win32/libisc.dsp @@ -1,676 +1,700 @@ -# Microsoft Developer Studio Project File - Name="libisc" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=libisc - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "libisc.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "libisc.mak" CFG="libisc - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "libisc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "libisc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "libisc - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "win32" /I "../../isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 user32.lib advapi32.lib ws2_32.lib /nologo /dll /machine:I386 /out:"../../../Build/Release/libisc.dll" -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "libisc - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "win32" /I "../../isccfg/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR /YX /FD /GZ /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 user32.lib advapi32.lib ws2_32.lib /nologo /dll /map /debug /machine:I386 /out:"../../../Build/Debug/libisc.dll" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "libisc - Win32 Release" -# Name "libisc - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\app.c -# End Source File -# Begin Source File - -SOURCE=.\condition.c -# End Source File -# Begin Source File - -SOURCE=.\dir.c -# End Source File -# Begin Source File - -SOURCE=.\DLLMain.c -# End Source File -# Begin Source File - -SOURCE=.\entropy.c -# End Source File -# Begin Source File - -SOURCE=.\errno2result.c -# End Source File -# Begin Source File - -SOURCE=.\file.c -# End Source File -# Begin Source File - -SOURCE=.\fsaccess.c -# End Source File -# Begin Source File - -SOURCE=.\interfaceiter.c -# End Source File -# Begin Source File - -SOURCE=.\ipv6.c -# End Source File -# Begin Source File - -SOURCE=.\keyboard.c -# End Source File -# Begin Source File - -SOURCE=.\net.c -# End Source File -# Begin Source File - -SOURCE=.\ntfile.c -# End Source File -# Begin Source File - -SOURCE=.\ntpaths.c -# End Source File -# Begin Source File - -SOURCE=.\once.c -# End Source File -# Begin Source File - -SOURCE=.\os.c -# End Source File -# Begin Source File - -SOURCE=.\resource.c -# End Source File -# Begin Source File - -SOURCE=.\socket.c -# End Source File -# Begin Source File - -SOURCE=.\stdio.c -# End Source File -# Begin Source File - -SOURCE=.\stdtime.c -# End Source File -# Begin Source File - -SOURCE=.\syslog.c -# End Source File -# Begin Source File - -SOURCE=.\thread.c -# End Source File -# Begin Source File - -SOURCE=.\time.c -# End Source File -# Begin Source File - -SOURCE=.\version.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\include\isc\app.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\assertions.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\base64.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\bind_registry.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\bindevt.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\bitstring.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\boolean.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\buffer.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\bufferlist.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\commandline.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\condition.h -# End Source File -# Begin Source File - -SOURCE=..\..\..\config.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\dir.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\entropy.h -# End Source File -# Begin Source File - -SOURCE=.\errno2result.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\error.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\event.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\eventclass.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\file.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\formatcheck.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\fsaccess.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\heap.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\hex.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\hmacmd5.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\int.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\interfaceiter.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\ipv6.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\keyboard.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\lang.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\lex.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\lfsr.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\lib.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\list.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\log.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\magic.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\md5.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\mem.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\msgcat.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\msioctl.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\mutex.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\mutexblock.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\net.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\netaddr.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\netdb.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\ntfile.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\ntpaths.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\offset.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\once.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\ondestroy.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\os.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\platform.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\print.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\quota.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\random.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\ratelimiter.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\region.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\resource.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\result.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\resultclass.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\rwlock.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\serial.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\sha1.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\sockaddr.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\socket.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\stat.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\stdio.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\stdtime.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\string.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\symtab.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\syslog.h -# End Source File -# Begin Source File - -SOURCE=.\syslog.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\task.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\taskpool.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\thread.h -# End Source File -# Begin Source File - -SOURCE=.\include\isc\time.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\timer.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\types.h -# End Source File -# Begin Source File - -SOURCE=.\unistd.h -# End Source File -# Begin Source File - -SOURCE=..\include\isc\util.h -# End Source File -# Begin Source File - -SOURCE=..\..\..\versions.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# Begin Group "Main Isc Lib" - -# PROP Default_Filter "c" -# Begin Source File - -SOURCE=..\assertions.c -# End Source File -# Begin Source File - -SOURCE=..\base64.c -# End Source File -# Begin Source File - -SOURCE=..\bitstring.c -# End Source File -# Begin Source File - -SOURCE=..\buffer.c -# End Source File -# Begin Source File - -SOURCE=..\bufferlist.c -# End Source File -# Begin Source File - -SOURCE=..\commandline.c -# End Source File -# Begin Source File - -SOURCE=..\error.c -# End Source File -# Begin Source File - -SOURCE=..\event.c -# End Source File -# Begin Source File - -SOURCE=..\heap.c -# End Source File -# Begin Source File - -SOURCE=..\hex.c -# End Source File -# Begin Source File - -SOURCE=..\hmacmd5.c -# End Source File -# Begin Source File - -SOURCE=..\inet_aton.c -# End Source File -# Begin Source File - -SOURCE=..\inet_ntop.c -# End Source File -# Begin Source File - -SOURCE=..\inet_pton.c -# End Source File -# Begin Source File - -SOURCE=..\lex.c -# End Source File -# Begin Source File - -SOURCE=..\lfsr.c -# End Source File -# Begin Source File - -SOURCE=..\lib.c -# End Source File -# Begin Source File - -SOURCE=..\log.c -# End Source File -# Begin Source File - -SOURCE=..\md5.c -# End Source File -# Begin Source File - -SOURCE=..\mem.c -# End Source File -# Begin Source File - -SOURCE=..\nls\msgcat.c -# End Source File -# Begin Source File - -SOURCE=..\mutexblock.c -# End Source File -# Begin Source File - -SOURCE=..\netaddr.c -# End Source File -# Begin Source File - -SOURCE=..\ondestroy.c -# End Source File -# Begin Source File - -SOURCE=..\quota.c -# End Source File -# Begin Source File - -SOURCE=..\random.c -# End Source File -# Begin Source File - -SOURCE=..\ratelimiter.c -# End Source File -# Begin Source File - -SOURCE=..\result.c -# End Source File -# Begin Source File - -SOURCE=..\rwlock.c -# End Source File -# Begin Source File - -SOURCE=..\serial.c -# End Source File -# Begin Source File - -SOURCE=..\sha1.c -# End Source File -# Begin Source File - -SOURCE=..\sockaddr.c -# End Source File -# Begin Source File - -SOURCE=..\string.c -# End Source File -# Begin Source File - -SOURCE=..\symtab.c -# End Source File -# Begin Source File - -SOURCE=..\task.c -# End Source File -# Begin Source File - -SOURCE=..\taskpool.c -# End Source File -# Begin Source File - -SOURCE=..\timer.c -# End Source File -# End Group -# Begin Source File - -SOURCE=.\libisc.def -# End Source File -# End Target -# End Project +# Microsoft Developer Studio Project File - Name="libisc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=libisc - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "libisc.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libisc.mak" CFG="libisc - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libisc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libisc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "win32" /I "../../isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib /nologo /dll /machine:I386 /out:"../../../Build/Release/libisc.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "win32" /I "../../isccfg/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib /nologo /dll /map /debug /machine:I386 /out:"../../../Build/Debug/libisc.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "libisc - Win32 Release"
+# Name "libisc - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\app.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\condition.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dir.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\DLLMain.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\entropy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\errno2result.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fsaccess.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\interfaceiter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ipv6.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\keyboard.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\net.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ntfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ntpaths.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\once.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\socket.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strerror.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\stdio.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\stdtime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\syslog.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\thread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\time.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\version.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\include\isc\app.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\assertions.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\base64.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\bind_registry.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\bindevt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\bitstring.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\boolean.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\buffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\bufferlist.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\commandline.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\condition.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\config.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\dir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\entropy.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\errno2result.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\error.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\event.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\eventclass.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\file.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\formatcheck.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\fsaccess.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\hash.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\heap.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\hex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\hmacmd5.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\int.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\interfaceiter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\ipv6.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\keyboard.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\lang.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\lex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\lfsr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\lib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\list.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\log.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\magic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\md5.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\mem.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\msgcat.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\msioctl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\mutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\mutexblock.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\net.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\netaddr.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\netdb.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\ntfile.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\ntpaths.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\offset.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\once.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\ondestroy.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\os.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\platform.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\print.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\quota.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\random.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\ratelimiter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\region.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\result.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\resultclass.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\rwlock.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\serial.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\sha1.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\sockaddr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\socket.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\stat.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\stdio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\strerror.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\stdtime.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\string.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\symtab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\syslog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\syslog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\task.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\taskpool.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\thread.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\time.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\timer.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\win32os.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\types.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\unistd.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\util.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\versions.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Main Isc Lib"
+
+# PROP Default_Filter "c"
+# Begin Source File
+
+SOURCE=..\assertions.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\base64.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\bitstring.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\buffer.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\bufferlist.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\commandline.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\error.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\event.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\hash.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\heap.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\hex.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\hmacmd5.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\inet_aton.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\inet_ntop.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\inet_pton.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lex.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lfsr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\log.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\md5.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mem.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\nls\msgcat.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mutexblock.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\netaddr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ondestroy.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\quota.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\random.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ratelimiter.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\result.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\rwlock.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\serial.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\sha1.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\sockaddr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\string.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\symtab.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\task.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\taskpool.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\timer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\win32os.c
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\libisc.def
+# End Source File
+# End Target
+# End Project
diff --git a/lib/isc/win32/libisc.dsw b/lib/isc/win32/libisc.dsw index c66c56e5..49c089c8 100644 --- a/lib/isc/win32/libisc.dsw +++ b/lib/isc/win32/libisc.dsw @@ -1,29 +1,29 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "libisc"=".\libisc.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - +Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "libisc"=".\libisc.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/lib/isc/win32/libisc.mak b/lib/isc/win32/libisc.mak index aa366c2d..6f4e5f19 100644 --- a/lib/isc/win32/libisc.mak +++ b/lib/isc/win32/libisc.mak @@ -50,6 +50,7 @@ CLEAN : -@erase "$(INTDIR)\event.obj" -@erase "$(INTDIR)\file.obj" -@erase "$(INTDIR)\fsaccess.obj" + -@erase "$(INTDIR)\hash.obj" -@erase "$(INTDIR)\heap.obj" -@erase "$(INTDIR)\hex.obj" -@erase "$(INTDIR)\hmacmd5.obj" @@ -85,6 +86,7 @@ CLEAN : -@erase "$(INTDIR)\sockaddr.obj" -@erase "$(INTDIR)\socket.obj" -@erase "$(INTDIR)\stdio.obj" + -@erase "$(INTDIR)\strerror.obj" -@erase "$(INTDIR)\stdtime.obj" -@erase "$(INTDIR)\string.obj" -@erase "$(INTDIR)\symtab.obj" @@ -96,6 +98,7 @@ CLEAN : -@erase "$(INTDIR)\timer.obj" -@erase "$(INTDIR)\vc60.idb" -@erase "$(INTDIR)\version.obj" + -@erase "$(INTDIR)\win32os.obj" -@erase "$(OUTDIR)\libisc.exp" -@erase "$(OUTDIR)\libisc.lib" -@erase "..\..\..\Build\Release\libisc.dll" @@ -167,6 +170,7 @@ LINK32_OBJS= \ "$(INTDIR)\resource.obj" \ "$(INTDIR)\socket.obj" \ "$(INTDIR)\stdio.obj" \ + "$(INTDIR)\strerror.obj" \ "$(INTDIR)\stdtime.obj" \ "$(INTDIR)\syslog.obj" \ "$(INTDIR)\thread.obj" \ @@ -180,6 +184,7 @@ LINK32_OBJS= \ "$(INTDIR)\commandline.obj" \ "$(INTDIR)\error.obj" \ "$(INTDIR)\event.obj" \ + "$(INTDIR)\hash.obj" \ "$(INTDIR)\heap.obj" \ "$(INTDIR)\hex.obj" \ "$(INTDIR)\hmacmd5.obj" \ @@ -208,7 +213,8 @@ LINK32_OBJS= \ "$(INTDIR)\symtab.obj" \ "$(INTDIR)\task.obj" \ "$(INTDIR)\taskpool.obj" \ - "$(INTDIR)\timer.obj" + "$(INTDIR)\timer.obj" \ + "$(INTDIR)\win32os.obj" "..\..\..\Build\Release\libisc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< @@ -259,6 +265,8 @@ CLEAN : -@erase "$(INTDIR)\file.sbr" -@erase "$(INTDIR)\fsaccess.obj" -@erase "$(INTDIR)\fsaccess.sbr" + -@erase "$(INTDIR)\hash.obj" + -@erase "$(INTDIR)\hash.sbr" -@erase "$(INTDIR)\heap.obj" -@erase "$(INTDIR)\heap.sbr" -@erase "$(INTDIR)\hex.obj" @@ -329,6 +337,8 @@ CLEAN : -@erase "$(INTDIR)\socket.sbr" -@erase "$(INTDIR)\stdio.obj" -@erase "$(INTDIR)\stdio.sbr" + -@erase "$(INTDIR)\strerror.obj" + -@erase "$(INTDIR)\strerror.sbr" -@erase "$(INTDIR)\stdtime.obj" -@erase "$(INTDIR)\stdtime.sbr" -@erase "$(INTDIR)\string.obj" @@ -351,6 +361,8 @@ CLEAN : -@erase "$(INTDIR)\vc60.pdb" -@erase "$(INTDIR)\version.obj" -@erase "$(INTDIR)\version.sbr" + -@erase "$(INTDIR)\win32os.obj" + -@erase "$(INTDIR)\win32os.sbr" -@erase "$(OUTDIR)\libisc.bsc" -@erase "$(OUTDIR)\libisc.exp" -@erase "$(OUTDIR)\libisc.lib" @@ -420,6 +432,7 @@ BSC32_SBRS= \ "$(INTDIR)\resource.sbr" \ "$(INTDIR)\socket.sbr" \ "$(INTDIR)\stdio.sbr" \ + "$(INTDIR)\strerror.sbr" \ "$(INTDIR)\stdtime.sbr" \ "$(INTDIR)\syslog.sbr" \ "$(INTDIR)\thread.sbr" \ @@ -433,6 +446,7 @@ BSC32_SBRS= \ "$(INTDIR)\commandline.sbr" \ "$(INTDIR)\error.sbr" \ "$(INTDIR)\event.sbr" \ + "$(INTDIR)\hash.sbr" \ "$(INTDIR)\heap.sbr" \ "$(INTDIR)\hex.sbr" \ "$(INTDIR)\hmacmd5.sbr" \ @@ -461,7 +475,8 @@ BSC32_SBRS= \ "$(INTDIR)\symtab.sbr" \ "$(INTDIR)\task.sbr" \ "$(INTDIR)\taskpool.sbr" \ - "$(INTDIR)\timer.sbr" + "$(INTDIR)\timer.sbr" \ + "$(INTDIR)\win32os.sbr" \ "$(OUTDIR)\libisc.bsc" : "$(OUTDIR)" $(BSC32_SBRS) $(BSC32) @<< @@ -492,6 +507,7 @@ LINK32_OBJS= \ "$(INTDIR)\resource.obj" \ "$(INTDIR)\socket.obj" \ "$(INTDIR)\stdio.obj" \ + "$(INTDIR)\strerror.obj" \ "$(INTDIR)\stdtime.obj" \ "$(INTDIR)\syslog.obj" \ "$(INTDIR)\thread.obj" \ @@ -505,6 +521,7 @@ LINK32_OBJS= \ "$(INTDIR)\commandline.obj" \ "$(INTDIR)\error.obj" \ "$(INTDIR)\event.obj" \ + "$(INTDIR)\hash.obj" \ "$(INTDIR)\heap.obj" \ "$(INTDIR)\hex.obj" \ "$(INTDIR)\hmacmd5.obj" \ @@ -533,7 +550,8 @@ LINK32_OBJS= \ "$(INTDIR)\symtab.obj" \ "$(INTDIR)\task.obj" \ "$(INTDIR)\taskpool.obj" \ - "$(INTDIR)\timer.obj" + "$(INTDIR)\timer.obj" \ + "$(INTDIR)\win32os.obj" "..\..\..\Build\Debug\libisc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< @@ -857,6 +875,22 @@ SOURCE=.\stdio.c !ENDIF +SOURCE=.\strerror.c + +!IF "$(CFG)" == "libisc - Win32 Release" + + +"$(INTDIR)\strerror.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - Win32 Debug" + + +"$(INTDIR)\strerror.obj" "$(INTDIR)\strerror.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + SOURCE=.\stdtime.c !IF "$(CFG)" == "libisc - Win32 Release" @@ -1081,6 +1115,24 @@ SOURCE=..\event.c !ENDIF +SOURCE=..\hash.c + +!IF "$(CFG)" == "libisc - Win32 Release" + + +"$(INTDIR)\hash.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - Win32 Debug" + + +"$(INTDIR)\hash.obj" "$(INTDIR)\hash.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + SOURCE=..\heap.c !IF "$(CFG)" == "libisc - Win32 Release" @@ -1603,6 +1655,24 @@ SOURCE=..\timer.c !ENDIF +SOURCE=.\win32os.c + +!IF "$(CFG)" == "libisc - Win32 Release" + + +"$(INTDIR)\win32os.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - Win32 Debug" + + +"$(INTDIR)\win32os.obj" "$(INTDIR)\win32os.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + !ENDIF diff --git a/lib/isc/win32/net.c b/lib/isc/win32/net.c index 119c4646..c0d681d6 100644 --- a/lib/isc/win32/net.c +++ b/lib/isc/win32/net.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: net.c,v 1.3.8.2 2003/02/17 07:05:10 marka Exp $ */ +/* $Id: net.c,v 1.3.2.2 2003/03/06 04:38:24 marka Exp $ */ #include <config.h> diff --git a/lib/isc/win32/netdb.h b/lib/isc/win32/netdb.h index 7554c001..ecbb7387 100644 --- a/lib/isc/win32/netdb.h +++ b/lib/isc/win32/netdb.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001 Internet Software Consortium. + * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: netdb.h,v 1.2 2001/07/08 05:09:07 mayer Exp $ */ +/* $Id: netdb.h,v 1.2.2.2 2003/07/22 04:03:50 marka Exp $ */ #ifndef NETDB_H #define NETDB_H 1 @@ -26,7 +26,7 @@ /* * Define if <netdb.h> does not declare struct addrinfo. */ - +#if _MSC_VER < 1300 struct addrinfo { int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ int ai_family; /* PF_xxx */ @@ -37,7 +37,7 @@ struct addrinfo { struct sockaddr *ai_addr; /* Binary address */ struct addrinfo *ai_next; /* Next structure in linked list */ }; - +#endif /* * Undefine all #defines we are interested in as <netdb.h> may or may not have diff --git a/lib/isc/win32/socket.c b/lib/isc/win32/socket.c index d9ed5f12..eecab87c 100644 --- a/lib/isc/win32/socket.c +++ b/lib/isc/win32/socket.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2002 Internet Software Consortium. + * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,8 +15,40 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: socket.c,v 1.5.2.7 2002/07/31 03:10:58 mayer Exp $ */ +/* $Id: socket.c,v 1.5.2.13 2003/07/22 04:03:50 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 + * available on Windows NT, Windows 2000 and Windows XP series of + * the Windows Operating Systems. In CANNOT run on Windows 95, Windows 98 + * or the follow-ons to those Systems. + * + * This code is by nature multithreaded and takes advantage of various + * features to pass on information through the completion port for + * when I/O is completed. All sends and receives are completed through + * the completion port. Due to an implementation bug in Windows 2000, + * Service Pack 2 must installed on the system for this code to run correctly. + * For details on this problem see Knowledge base article Q263823. + * The code checks for this. The number of Completion Port Worker threads + * used is the total number of CPU's + 1. This increases the likelihood that + * a Worker Thread is available for processing a completed request. + * + * All accepts and connects are accomplished through the WSAEventSelect() + * function and the event_wait loop. Events are added to and deleted from + * each event_wait thread via a common event_update stack owned by the socket + * manager. If the event_wait thread runs out of array space in the events + * array it will look for another event_wait thread to add the event. If it + * fails to find another one it will create a new thread to handle the + * outstanding event. + * + * A future enhancement is to use AcceptEx to take avantage of Overlapped + * I/O which allows for enhanced performance of TCP connections. + * This will also reduce the number of events that are waited on by the + * event_wait threads to just the connect sockets and reduce the number + * additional threads required. + * + * XXXPDM 5 August, 2002 + */ #define MAKE_EXTERNAL 1 #include <config.h> @@ -34,6 +66,7 @@ #include <unistd.h> #include <io.h> #include <fcntl.h> +#include <process.h> #include <isc/buffer.h> #include <isc/bufferlist.h> @@ -44,18 +77,31 @@ #include <isc/msgs.h> #include <isc/mutex.h> #include <isc/net.h> +#include <isc/os.h> #include <isc/platform.h> #include <isc/print.h> #include <isc/region.h> #include <isc/socket.h> +#include <isc/strerror.h> +#include <isc/syslog.h> #include <isc/task.h> #include <isc/thread.h> #include <isc/util.h> +#include <isc/win32os.h> #include "errno2result.h" -#define MAX_SELECT_SECONDS 0 -#define MAX_SELECT_MILLISECONDS 40 +/* + * Define this macro to control the behavior of connection + * resets on UDP sockets. See Microsoft KnowledgeBase Article Q263823 + * for details. + * NOTE: This requires that Windows 2000 systems install Service Pack 2 + * or later. + */ +#ifndef SIO_UDP_CONNRESET +#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) +#endif + /* * 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. @@ -73,6 +119,7 @@ * work around it here. */ #define SOFT_ERROR(e) ((e) == WSAEINTR || \ + (e) == WSA_IO_PENDING || \ (e) == WSAEWOULDBLOCK || \ (e) == EWOULDBLOCK || \ (e) == EINTR || \ @@ -121,19 +168,6 @@ typedef isc_event_t intev_t; * a setsockopt() like interface to request timestamps, and if the OS * doesn't do it for us, call gettimeofday() on every UDP receive? */ -#ifdef SO_TIMESTAMP -#ifndef USE_CMSG -#define USE_CMSG 1 -#endif -#endif - -/* - * Check to see if we have even basic support for cracking messages from - * the control data returned from/sent via recvmsg()/sendmsg(). - */ -#if defined(USE_CMSG) && (!defined(CMSG_LEN) || !defined(CMSG_SPACE)) -#undef USE_CMSG -#endif /* * We really don't want to try and use these control messages. Win32 @@ -145,10 +179,7 @@ typedef isc_event_t intev_t; * Message header for recvmsg and sendmsg calls. * Used value-result for recvmsg, value only for sendmsg. */ -struct iovec { - void *iov_base; /* starting address of buffer */ - size_t iov_len; /* size of buffer */ -}; + struct msghdr { void *msg_name; /* optional address */ @@ -159,7 +190,7 @@ struct msghdr { u_int msg_controllen; /* ancillary data buffer len */ int msg_flags; /* flags on received message */ } msghdr; - + /* * The number of times a send operation is repeated if the result is EINTR. */ @@ -171,11 +202,20 @@ struct isc_socket { isc_socketmgr_t *manager; isc_mutex_t lock; isc_sockettype_t type; + OVERLAPPED overlapped; + /* Pointers to scatter/gather buffers */ + WSABUF iov[ISC_SOCKET_MAXSCATTERGATHER]; + size_t totalBytes; + WSAEVENT hEvent; /* Event Handle */ + long wait_type; /* Events to wait on */ + WSAEVENT hAlert; /* Alert Event Handle */ + DWORD evthread_id; /* Event Thread Id for socket */ + /* Locked by socket lock. */ ISC_LINK(isc_socket_t) link; unsigned int references; - int fd; + SOCKET fd; int pf; ISC_LIST(isc_socketevent_t) send_list; @@ -193,17 +233,80 @@ struct isc_socket { isc_sockaddr_t address; /* remote address */ - unsigned int pending_recv : 1, - pending_send : 1, + unsigned int pending_close : 1, pending_accept : 1, - listener : 1, /* listener socket */ + iocp : 1, /* I/O Completion Port */ + listener : 1, /* listener socket */ connected : 1, connecting : 1, /* connect pending */ - bound : 1; /* bound to local addr */ + bound : 1; /* bound to local addr */ -#ifdef ISC_NET_RECVOVERFLOW - unsigned char overflow; /* used for MSG_TRUNC fake */ -#endif +}; + +/* + * I/O Completion ports Info structures + */ + +static HANDLE hHeapHandle = NULL; +static int iocp_total = 0; +typedef struct IoCompletionInfo { + OVERLAPPED overlapped; + isc_socketevent_t *dev; + int request_type; + struct msghdr messagehdr; +} IoCompletionInfo; + +/* + * Define a maximum number of I/O Completion Port worker threads + * to handle the load on the Completion Port. The actual number + * used is the number of CPU's + 1. + */ +#define MAX_IOCPTHREADS 20 + +/* + * event_change structure to handle adds and deletes from the list of + * events in the Wait + */ +typedef struct event_change event_change_t; + +struct event_change { + isc_socket_t *sock; + WSAEVENT hEvent; + DWORD evthread_id; + SOCKET fd; + unsigned int action; + ISC_LINK(event_change_t) link; +}; + +/* + * Note: We are using an array here since *WaitForMultiple* wants an array + * WARNING: This value may not be greater than 64 since the + * WSAWaitForMultipleEvents function is limited to 64 events. + */ + +#define MAX_EVENTS 64 + +/* + * List of events being waited on and their associated sockets + */ +typedef struct sock_event_list { + int max_event; + int total_events; + isc_socket_t *aSockList[MAX_EVENTS]; + WSAEVENT aEventList[MAX_EVENTS]; +} sock_event_list; + +/* + * Thread Event structure for managing the threads handling events + */ +typedef struct events_thread events_thread_t; + +struct events_thread { + isc_thread_t thread_handle; /* Thread's handle */ + DWORD thread_id; /* Thread's id */ + sock_event_list sockev_list; + isc_socketmgr_t *manager; + ISC_LINK(events_thread_t) link; }; #define SOCKET_MANAGER_MAGIC ISC_MAGIC('I', 'O', 'm', 'g') @@ -211,21 +314,21 @@ struct isc_socket { struct isc_socketmgr { /* Not locked. */ - unsigned int magic; - isc_mem_t *mctx; - isc_mutex_t lock; + unsigned int magic; + isc_mem_t *mctx; + isc_mutex_t lock; /* Locked by manager lock. */ - 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; - int minfd; - isc_thread_t watcher; - isc_condition_t shutdown_ok; - int pipe_fds[2]; + ISC_LIST(event_change_t) event_updates; + ISC_LIST(isc_socket_t) socklist; + int event_written; + WSAEVENT prime_alert; + isc_boolean_t bShutdown; + ISC_LIST(events_thread_t) ev_threads; + isc_condition_t shutdown_ok; + HANDLE hIoCompletionPort; + int maxIOCPThreads; + HANDLE hIOCPThreads[MAX_IOCPTHREADS]; + DWORD dwIOCPThreadIds[MAX_IOCPTHREADS]; }; #define CLOSED 0 /* this one must be zero */ @@ -236,68 +339,528 @@ struct isc_socketmgr { * send() and recv() iovec counts */ #define MAXSCATTERGATHER_SEND (ISC_SOCKET_MAXSCATTERGATHER) -#ifdef ISC_NET_RECVOVERFLOW -# define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER + 1) -#else -# define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER) -#endif +#define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER) -static void send_recvdone_event(isc_socket_t *, isc_socketevent_t **); -static void send_senddone_event(isc_socket_t *, isc_socketevent_t **); +static isc_threadresult_t WINAPI event_wait(void *uap); +static isc_threadresult_t WINAPI SocketIoThread(LPVOID ThreadContext); static void free_socket(isc_socket_t **); -static isc_result_t allocate_socket(isc_socketmgr_t *, isc_sockettype_t, - isc_socket_t **); -static void destroy(isc_socket_t **); -static void internal_accept(isc_task_t *, isc_event_t *); -static void internal_connect(isc_task_t *, isc_event_t *); -static void internal_recv(isc_task_t *, isc_event_t *); -static void internal_send(isc_task_t *, isc_event_t *); -static void process_cmsg(isc_socket_t *, struct msghdr *, isc_socketevent_t *); -static void build_msghdr_send(isc_socket_t *, isc_socketevent_t *, - struct msghdr *, char *cmsg, - WSABUF *, size_t *); -static void build_msghdr_recv(isc_socket_t *, isc_socketevent_t *, - struct msghdr *, char *cmsg, - WSABUF *, size_t *); - -#define SELECT_POKE_SHUTDOWN (-1) -#define SELECT_POKE_NOTHING (-2) -#define SELECT_POKE_READ (-3) -#define SELECT_POKE_ACCEPT (-3) /* Same as _READ */ -#define SELECT_POKE_WRITE (-4) -#define SELECT_POKE_CONNECT (-5) -#define SELECT_POKE_CLOSE (-6) - -long bpipe_written = 0; + +enum { + SOCKET_CANCEL, + SOCKET_SHUTDOWN, + SOCKET_RECV, + SOCKET_SEND, + SOCK_ACCEPT +}; + +enum { + EVENT_ADD, + 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 + * You should make sure that the sock is locked before + * dumping it. Since the code uses simple printf() statements + * it should only be used interactively. + */ +void +sock_dump(isc_socket_t *sock) { + isc_socketevent_t *ldev; + isc_socket_newconnev_t *ndev; + isc_sockaddr_t addr; + char socktext[256]; + + + isc_socket_getpeername(sock, &addr); + isc_sockaddr_format(&addr, socktext, sizeof(socktext)); + printf("Remote Socket: %s\n", socktext); + isc_socket_getsockname(sock, &addr); + isc_sockaddr_format(&addr, socktext, sizeof(socktext)); + printf("This Socket: %s\n", socktext); + + printf("\n\t\tSock Dump\n"); + printf("\t\tfd: %u\n", sock->fd); + printf("\t\treferences: %d\n", sock->references); + printf("\t\tpending_accept: %d\n", sock->pending_accept); + printf("\t\tpending_close: %d\n", sock->pending_close); + printf("\t\tconnecting: %d\n", sock->connecting); + printf("\t\tconnected: %d\n", sock->connected); + printf("\t\tbound: %d\n", sock->bound); + printf("\t\tiocp: %d\n", sock->iocp); + printf("\t\tsocket type: %d\n", sock->type); + + printf("\n\t\tSock Recv List\n"); + ldev = ISC_LIST_HEAD(sock->recv_list); + while (ldev != NULL) { + printf("\t\tdev: %p\n", ldev); + ldev = ISC_LIST_NEXT(ldev, ev_link); + } + printf("\n\t\tSock Send List\n"); + ldev = ISC_LIST_HEAD(sock->send_list); + while (ldev != NULL) { + printf("\t\tdev: %p\n", ldev); + ldev = ISC_LIST_NEXT(ldev, ev_link); + } + printf("\n\t\tSock Accept List\n"); + ndev = ISC_LIST_HEAD(sock->accept_list); + while (ndev != NULL) { + printf("\t\tdev: %p\n", ldev); + ndev = ISC_LIST_NEXT(ndev, ev_link); + } +} +#endif + +/* This function will add an entry to the I/O completion port + * that will signal the I/O thread to exit (gracefully) + */ +static void +signal_iocompletionport_exit(isc_socketmgr_t *manager) { + int i; + int errval; + char strbuf[ISC_STRERRORSIZE]; + + REQUIRE(VALID_MANAGER(manager)); + for (i = 0; i < manager->maxIOCPThreads; i++) { + if (!PostQueuedCompletionStatus(manager->hIoCompletionPort, + 0, 0, 0)) { + errval = GetLastError(); + isc__strerror(errval, strbuf, sizeof(strbuf)); + FATAL_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_FAILED, + "Can't request service thread to exit: %s"), + strbuf); + } + } +} + +/* + * Create the worker threads for the I/O Completion Port + */ +void +iocompletionport_createthreads(int total_threads, isc_socketmgr_t *manager) { + int errval; + char strbuf[ISC_STRERRORSIZE]; + int i; + + INSIST(total_threads > 0); + REQUIRE(VALID_MANAGER(manager)); + /* + * We need at least one + */ + for (i = 0; i < total_threads; i++) { + manager->hIOCPThreads[i] = CreateThread( NULL, 0, SocketIoThread, + manager, 0, + &manager->dwIOCPThreadIds[i]); + if(manager->hIOCPThreads[i] == NULL) { + errval = GetLastError(); + isc__strerror(errval, strbuf, sizeof(strbuf)); + FATAL_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_FAILED, + "Can't create IOCP thread: %s"), + strbuf); + } + } +} + +/* + * Create/initialise the I/O completion port + */ +void +iocompletionport_init(isc_socketmgr_t *manager) { + int errval; + char strbuf[ISC_STRERRORSIZE]; + + REQUIRE(VALID_MANAGER(manager)); + /* + * Create a private heap to handle the socket overlapped structure + * The miniumum number of structures is 10, there is no maximum + */ + hHeapHandle = HeapCreate(0, 10*sizeof(IoCompletionInfo), 0); + manager->maxIOCPThreads = min(isc_os_ncpus() + 1, + MAX_IOCPTHREADS); + + /* Now Create the Completion Port */ + manager->hIoCompletionPort = CreateIoCompletionPort( + INVALID_HANDLE_VALUE, NULL, + 0, manager->maxIOCPThreads); + if (manager->hIoCompletionPort == NULL) { + errval = GetLastError(); + isc__strerror(errval, strbuf, sizeof(strbuf)); + FATAL_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_FAILED, + "CreateIoCompletionPort() failed " + "during initialization: %s"), + strbuf); + exit(1); + } + + /* + * Worker threads for servicing the I/O + */ + iocompletionport_createthreads(manager->maxIOCPThreads, manager); +} + + +void +iocompletionport_exit(isc_socketmgr_t *manager) { + + REQUIRE(VALID_MANAGER(manager)); + if (manager->hIoCompletionPort != NULL) { + /* Get each of the service threads to exit + */ + signal_iocompletionport_exit(manager); + } +} + +/* + * Add sockets in here and pass the sock data in as part of the information needed + */ +void +iocompletionport_update(isc_socket_t *sock) { + HANDLE hiocp; + + REQUIRE(sock != NULL); + if(sock->iocp == 0) { + sock->iocp = 1; + hiocp = CreateIoCompletionPort((HANDLE) sock->fd, + sock->manager->hIoCompletionPort, (DWORD) sock, + sock->manager->maxIOCPThreads); + InterlockedIncrement(&iocp_total); + + } +} + +void +socket_event_minit(sock_event_list *evlist) { + BOOL bReset; + int i; + + REQUIRE(evlist != NULL); + /* Initialize the Event List */ + evlist->max_event = 0; + evlist->total_events = 0; + for (i = 0; i < MAX_EVENTS; i++) { + evlist->aSockList[i] = NULL; + evlist->aEventList[i] = (WSAEVENT) 0; + } + + evlist->aEventList[0] = WSACreateEvent(); + (evlist->max_event)++; + bReset = WSAResetEvent(evlist->aEventList[0]); +} /* - * Routine to handle error messages + * Event Thread Initialization */ +isc_result_t +event_thread_create(events_thread_t **evthreadp, isc_socketmgr_t *manager) { + events_thread_t *evthread; + + REQUIRE(VALID_MANAGER(manager)); + REQUIRE(evthreadp != NULL && *evthreadp == NULL); + + evthread = isc_mem_get(manager->mctx, sizeof(*evthread)); + socket_event_minit(&evthread->sockev_list); + ISC_LINK_INIT(evthread, link); + evthread->manager = manager; -#define ISC_STRERRORSIZE 128 + ISC_LIST_APPEND(manager->ev_threads, evthread, link); + /* + * Start up the event wait thread. + */ + if (isc_thread_create(event_wait, evthread, &evthread->thread_handle) != + ISC_R_SUCCESS) { + isc_mem_put(manager->mctx, evthread, sizeof(*evthread)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_thread_create() %s", + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, "failed")); + return (ISC_R_UNEXPECTED); + } + *evthreadp = evthread; + return (ISC_R_SUCCESS); +} +/* + * Locate a thread with space for additional events or create one if + * necessary. The manager is locked at this point so the information + * cannot be changed by another thread while we are searching. + */ void -isc__strerror(int num, char *buf, size_t size) { - char *msg; - unsigned int unum = num; +locate_available_thread(isc_socketmgr_t *manager) { + events_thread_t *evthread; + DWORD threadid = GetCurrentThreadId(); + + evthread = ISC_LIST_HEAD(manager->ev_threads); + while (evthread != NULL) { + /* + * We need to find a thread with space to add an event + * If we find it, alert it to process the event change + * list + */ + if(threadid != evthread->thread_id && + evthread->sockev_list.max_event < MAX_EVENTS) { + WSASetEvent(evthread->sockev_list.aEventList[0]); + return; + } + evthread = ISC_LIST_NEXT(evthread, link); + } + /* + * We need to create a new thread as other threads are full. + * If we succeed in creating the thread, alert it to + * process the event change list since it will have space. + * If we are unable to create one, the event will stay on the + * list and the next event_wait thread will try again to add + * the event. It will call here again if it has no space. + */ + if (event_thread_create(&evthread, manager) == ISC_R_SUCCESS) { + WSASetEvent(evthread->sockev_list.aEventList[0]); + } + +} + +isc_boolean_t +socket_eventlist_add(event_change_t *evchange, sock_event_list *evlist, + isc_socketmgr_t *manager) { + int max_event; + isc_socket_t *sock; + REQUIRE(evchange != NULL); + + sock = evchange->sock; + REQUIRE(sock != NULL); + REQUIRE(sock->hEvent != NULL); + REQUIRE(evlist != NULL); + + max_event = evlist->max_event; + if(max_event >= MAX_EVENTS) { + locate_available_thread(manager); + return (ISC_FALSE); + } + + evlist->aSockList[max_event] = sock; + evlist->aEventList[max_event] = sock->hEvent; + evlist->max_event++; + evlist->total_events++; + sock->hAlert = evlist->aEventList[0]; + 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 + */ +isc_boolean_t +socket_eventlist_delete(event_change_t *evchange, sock_event_list *evlist) { + int i; + WSAEVENT hEvent; + int iEvent = -1; + + REQUIRE(evchange != NULL); + /* Make sure this is the right thread from which to delete the event */ + if(evchange->evthread_id != GetCurrentThreadId()) + return (ISC_FALSE); + + REQUIRE(evlist != NULL); + REQUIRE(evchange->hEvent != NULL); + hEvent = evchange->hEvent; + + /* Find the Event */ + for (i = 1; i < evlist->max_event; i++) { + if (evlist->aEventList[i] == hEvent) { + iEvent = i; + break; + } + } + /* Actual event start at 1 */ + if (iEvent < 1) + return (ISC_FALSE); + + for(i = iEvent; i < (evlist->max_event - 1); i++) { + 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; - REQUIRE(buf != NULL); + /* Cleanup */ + WSACloseEvent(hEvent); + if (evchange->fd >= 0) + closesocket(evchange->fd); + evlist->max_event--; + evlist->total_events--; - msg = NTstrerror(num); - if (msg != NULL) - snprintf(buf, size, "%s", msg); + return (ISC_TRUE); +} +/* + * Get the event changes off of the list and apply the + * requested changes. The manager lock is taken out at + * the start of this function to prevent other event_wait + * threads processing the same information at the same + * time. The queue may not be empty on exit since other + * threads may be involved in processing the queue. + * + * The deletes are done first in order that there be space + * available for the events being added in the same thread + * in case the event list is almost full. This reduces the + * probability of having to create another thread which would + * increase overhead costs. + */ +isc_result_t +process_eventlist(sock_event_list *evlist, isc_socketmgr_t *manager) { + event_change_t *evchange; + event_change_t *next; + isc_boolean_t del; + + REQUIRE(evlist != NULL); + + LOCK(&manager->lock); + + /* 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) { + del = socket_eventlist_delete(evchange, evlist); + + /* Delete only if this thread's socket list was updated */ + if (del) { + ISC_LIST_DEQUEUE(manager->event_updates, + evchange, link); + HeapFree(hHeapHandle, 0, evchange); + manager->event_written--; + } + } + evchange = next; + } + /* 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) { + del = socket_eventlist_add(evchange, evlist, manager); + + /* Delete only if this thread's socket list was updated */ + if (del) { + ISC_LIST_DEQUEUE(manager->event_updates, + evchange, link); + HeapFree(hHeapHandle, 0, evchange); + manager->event_written--; + } + } + evchange = next; + } + 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) { + + event_change_t *evchange; + + REQUIRE(VALID_MANAGER(manager)); + REQUIRE(sock != NULL); + + evchange = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, + sizeof(event_change_t)); + evchange->sock = sock; + evchange->action = action; + evchange->hEvent = sock->hEvent; + evchange->fd = sock->fd; + evchange->evthread_id = sock->evthread_id; + + LOCK(&manager->lock); + ISC_LIST_APPEND(manager->event_updates, evchange, link); + sock->manager->event_written++; + UNLOCK(&manager->lock); + + /* Alert the Wait List */ + if (sock->hAlert != NULL) + WSASetEvent(sock->hAlert); else - snprintf(buf, size, "Unknown error: %u", unum); + WSASetEvent(manager->prime_alert); } +/* + * Note that the socket is already locked before calling this function + */ +isc_result_t +socket_event_add(isc_socket_t *sock, long type) { + int stat; + WSAEVENT hEvent; + REQUIRE(sock != NULL); + hEvent = WSACreateEvent(); + if (hEvent == WSA_INVALID_EVENT) { + stat = WSAGetLastError(); + return (ISC_R_UNEXPECTED); + } + if (WSAEventSelect(sock->fd, hEvent, type) != 0) { + stat = WSAGetLastError(); + WSACloseEvent(hEvent); + return (ISC_R_UNEXPECTED); + } + sock->hEvent = hEvent; + + sock->wait_type = type; + notify_eventlist(sock, sock->manager, EVENT_ADD); + return (ISC_R_SUCCESS); +} /* - * The following routines are here to handle Unix emulation until we - * can rewrite the the routines in Winsock2 style. + * Note that the socket is not locked before calling this function */ +void +socket_event_delete(isc_socket_t *sock) { + REQUIRE(sock != NULL); + REQUIRE(sock->hEvent != NULL); + + if (sock->hEvent != NULL) { + sock->wait_type = 0; + sock->pending_close = 1; + notify_eventlist(sock, sock->manager, EVENT_DELETE); + sock->hEvent = NULL; + 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 + * with an event, otherwise the WSAWaitForMultipleEvents + * may fail due to the fact that the the Wait should not + * be running while closing an event or a socket. + */ +void +socket_close(isc_socket_t *sock) { + + REQUIRE(sock != NULL); + sock->pending_close = 1; + if (sock->hEvent != NULL) + socket_event_delete(sock); + else { + closesocket(sock->fd); + } + if (sock->iocp) { + sock->iocp = 0; + InterlockedDecrement(&iocp_total); + } + +} /* * Initialize socket services */ @@ -312,106 +875,112 @@ BOOL InitSockets() { err = WSAStartup(wVersionRequested, &wsaData); if ( err != 0 ) { /* Tell the user that we could not find a usable Winsock DLL */ - return (FALSE); + return(FALSE); } - - return (TRUE); + return(TRUE); } int -internal_pipe(int filedes[2]) { - int status; - unsigned int pipesize = 65535; - int mode = _O_TEXT; - - status = _pipe(filedes, pipesize, mode); - return (status); - InterlockedExchange(&bpipe_written, 0); -} - -int -internal_sendmsg(int sock, const struct msghdr *msg, int flags, int *merror) { +internal_sendmsg(isc_socket_t *sock, IoCompletionInfo *lpo, + struct msghdr *messagehdr, int flags, int *Error) { + int Result; DWORD BytesSent; DWORD Flags = flags; - - *merror = WSASendTo((SOCKET) sock, - msg->msg_iov, - msg->msg_iovlen, - &BytesSent, - Flags, - msg->msg_name, - msg->msg_namelen, - NULL, - NULL); + int total_sent; + + *Error = 0; + Result = WSASendTo((SOCKET) sock->fd, + messagehdr->msg_iov, + messagehdr->msg_iovlen, + &BytesSent, + Flags, + messagehdr->msg_name, + messagehdr->msg_namelen, + (LPOVERLAPPED) lpo, + NULL); + + total_sent = (int) BytesSent; - if (*merror == SOCKET_ERROR) { - BytesSent = -1; - /* There is an error... */ - *merror = WSAGetLastError(); - if (*merror == WSA_IO_PENDING) { - /* Overlapped send successfully initiated. */ - errno = EAGAIN; - } else { - /* An unexpected error occurred. */ - errno = *merror; - } - } + /* Check for errors.*/ + if (Result == SOCKET_ERROR) { - /* No error -- the I/O request was completed immediately... */ - return (BytesSent); + *Error = WSAGetLastError(); + + switch (*Error) { + + case NO_ERROR : + case WSA_IO_INCOMPLETE : + case WSA_WAIT_IO_COMPLETION : + case WSA_IO_PENDING : + break ; + + default : + return (-1); + break; + } + } + if(lpo != NULL) + return (0); + else + return (total_sent); } int -internal_recvmsg(int sock, struct msghdr *msg, int flags, int *merror) { - DWORD Flags = flags; - DWORD NumBytes; +internal_recvmsg(isc_socket_t *sock, IoCompletionInfo *lpo, + struct msghdr *messagehdr, int flags, int *Error) { + DWORD Flags = 0; + DWORD NumBytes = 0; + int total_bytes = 0; int Result; - Result = WSARecvFrom((SOCKET) sock, - msg->msg_iov, - msg->msg_iovlen, - &NumBytes, - &Flags, - msg->msg_name, - (int *)&(msg->msg_namelen), - NULL, - NULL); + *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); + total_bytes = (int) NumBytes; /* Check for errors. */ if (Result == SOCKET_ERROR) { - *merror = WSAGetLastError(); - NumBytes = -1; + + *Error = WSAGetLastError(); - switch (*merror) { - case WSAEWOULDBLOCK: - /* - * No data received; return to wait for another - * read event. - */ - errno = EAGAIN; - break; + switch (*Error) { - default: - /* Some other error... hit the panic button. */ - errno = *merror; - break; - } + case NO_ERROR : + case WSA_IO_INCOMPLETE : + case WSA_WAIT_IO_COMPLETION : + case WSA_IO_PENDING : + break ; + + default : + return (-1); + break; + } } - msg->msg_flags = Flags; /* Return the flags received in header */ - - return (NumBytes); -} + /* Return the flags received in header */ + messagehdr->msg_flags = Flags; + 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, ...) -{ + const char *fmt, ...) { char msgbuf[2048]; va_list ap; - if (! isc_log_wouldlog(isc_lctx, level)) + if (!isc_log_wouldlog(isc_lctx, level)) return; va_start(ap, fmt); @@ -431,8 +1000,7 @@ 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; @@ -449,134 +1017,27 @@ socket_log(isc_socket_t *sock, isc_sockaddr_t *address, msgcat, msgset, message, "socket %p: %s", sock, msgbuf); } else { - isc_sockaddr_format(address, peerbuf, sizeof(peerbuf)); + isc_sockaddr_format(address, peerbuf, sizeof peerbuf); isc_log_iwrite(isc_lctx, category, module, level, msgcat, msgset, message, "socket %p %s: %s", sock, peerbuf, msgbuf); } } -static void -wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) { - isc_socket_t *sock; - - /* - * This is a wakeup on a socket. If the socket is not in the - * process of being closed, start watching it for either reads - * or writes. - */ - - 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; - } - if (manager->fdstate[fd] != MANAGED) - return; - - sock = manager->fds[fd]; - - /* - * If there are no events, or there is an event but we - * have already queued up the internal event on a task's - * queue, clear the bit. Otherwise, set it. - */ - if (msg == SELECT_POKE_READ) - 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); - } -} - /* - * Poke the select loop when there is something for us to do. - * The write is required (by POSIX) to complete. That is, we - * will not get partial writes. - */ -static void -select_poke(isc_socketmgr_t *mgr, int fd, int msg) { - int cc; - int buf[2]; - char strbuf[ISC_STRERRORSIZE]; - - buf[0] = fd; - buf[1] = msg; - - if (msg == SELECT_POKE_SHUTDOWN) { - do { - cc = _write(mgr->pipe_fds[1], buf, sizeof(buf)); - } while (cc < 0 && SOFT_ERROR(errno)); - - if (cc < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - FATAL_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_WRITEFAILED, - "write() failed " - "during watcher poke: %s"), - strbuf); - } - - INSIST(cc == sizeof(buf)); - - InterlockedIncrement(&bpipe_written); - } else { - wakeup_socket(mgr, fd, msg); - } -} - -/* - * Read a message on the internal fd. - */ -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) { - *msg = SELECT_POKE_NOTHING; - 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 " - "during watcher poke: %s"), - strbuf); - - return; - } - INSIST(cc == sizeof(buf)); - *fd = buf[0]; - *msg = buf[1]; - -} -/* - * Make a fd non-blocking. + * Make an fd SOCKET non-blocking. */ static isc_result_t -make_nonblock(int fd) { +make_nonblock(SOCKET fd) { int ret; unsigned long flags = 1; char strbuf[ISC_STRERRORSIZE]; /* Set the socket to non-blocking */ - ret = ioctlsocket((SOCKET) fd, FIONBIO, &flags); + ret = ioctlsocket(fd, FIONBIO, &flags); if (ret == -1) { - isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf)); + isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "ioctlsocket(%d, FIOBIO, %d): %s", fd, flags, strbuf); @@ -586,103 +1047,33 @@ make_nonblock(int fd) { return (ISC_R_SUCCESS); } - /* - * Process control messages received on a socket. + * Windows 2000 systems incorrectly cause UDP sockets using WASRecvFrom + * 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. + * The function below fixes this, but requires that Windows 2000 + * Service Pack 2 or later be installed on the system. NT 4.0 + * systems are not affected by this and work correctly. + * See Microsoft Knowledge Base Article Q263823 for details of this. */ -static void -process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) { -#ifdef USE_CMSG - struct cmsghdr *cmsgp; -#ifdef ISC_PLATFORM_HAVEIPV6 - struct in6_pktinfo *pktinfop; -#endif -#ifdef SO_TIMESTAMP - struct timeval *timevalp; -#endif -#endif - - /* - * sock is used only when ISC_NET_BSD44MSGHDR and USE_CMSG are defined. - * msg and dev are used only when ISC_NET_BSD44MSGHDR is defined. - * They are all here, outside of the CPP tests, because it is - * more consistent with the usual ISC coding style. - */ - UNUSED(sock); - UNUSED(msg); - UNUSED(dev); - -#ifndef ISC_NET_BSD44MSGHDR - return; - -#else /* defined ISC_NET_BSD44MSGHDR */ - -#ifdef MSG_TRUNC - if ((msg->msg_flags & MSG_TRUNC) == MSG_TRUNC) - dev->attributes |= ISC_SOCKEVENTATTR_TRUNC; -#endif - -#ifdef MSG_CTRUNC - if ((msg->msg_flags & MSG_CTRUNC) == MSG_CTRUNC) - dev->attributes |= ISC_SOCKEVENTATTR_CTRUNC; -#endif - -#ifndef USE_CMSG - return; -#else - if (msg->msg_controllen == 0 || msg->msg_control == NULL) - return; - -#ifdef SO_TIMESTAMP - timevalp = NULL; -#endif -#ifdef ISC_PLATFORM_HAVEIPV6 - pktinfop = NULL; -#endif - - cmsgp = CMSG_FIRSTHDR(msg); - while (cmsgp != NULL) { - socket_log(sock, NULL, TRACE, - isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_PROCESSCMSG, - "processing cmsg %p", cmsgp); - -#ifdef ISC_PLATFORM_HAVEIPV6 - if (cmsgp->cmsg_level == IPPROTO_IPV6 - && cmsgp->cmsg_type == IPV6_PKTINFO) { - - pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp); - memcpy(&dev->pktinfo, pktinfop, - sizeof(struct in6_pktinfo)); - dev->attributes |= ISC_SOCKEVENTATTR_PKTINFO; - socket_log(sock, NULL, TRACE, - isc_msgcat, ISC_MSGSET_SOCKET, - 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 - -#ifdef SO_TIMESTAMP - if (cmsgp->cmsg_level == SOL_SOCKET - && cmsgp->cmsg_type == SCM_TIMESTAMP) { - timevalp = (struct timeval *)CMSG_DATA(cmsgp); - dev->timestamp.seconds = timevalp->tv_sec; - dev->timestamp.nanoseconds = timevalp->tv_usec * 1000; - dev->attributes |= ISC_SOCKEVENTATTR_TIMESTAMP; - goto next; - } -#endif - - next: - cmsgp = CMSG_NXTHDR(msg, cmsgp); - } -#endif /* USE_CMSG */ - -#endif /* ISC_NET_BSD44MSGHDR */ - +isc_result_t +connection_reset_fix(SOCKET fd) { + DWORD dwBytesReturned = 0; + BOOL bNewBehavior = FALSE; + DWORD status; + + if(isc_win32os_majorversion() < 5) + return (ISC_R_SUCCESS); /* NT 4.0 has no problem */ + + /* disable bad behavior using IOCTL: SIO_UDP_CONNRESET */ + status = WSAIoctl(fd, SIO_UDP_CONNRESET, &bNewBehavior, + sizeof(bNewBehavior), NULL, 0, + &dwBytesReturned, NULL, NULL); + if (status != SOCKET_ERROR) + return (ISC_R_SUCCESS); + else + return (ISC_R_UNEXPECTED); } /* @@ -700,18 +1091,13 @@ process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) { 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; size_t write_count; size_t skip_count; -#ifndef USE_CMSG - UNUSED(cmsg); -#endif - memset(msg, 0, sizeof (*msg)); if (sock->type == isc_sockettype_udp) { @@ -758,7 +1144,7 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev, if (used.length > 0) { iov[iovcount].buf = (void *)(used.base - + skip_count); + + skip_count); iov[iovcount].len = used.length - skip_count; write_count += (used.length - skip_count); skip_count = 0; @@ -773,34 +1159,6 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev, msg->msg_iov = iov; msg->msg_iovlen = iovcount; -#ifdef ISC_NET_BSD44MSGHDR - msg->msg_control = NULL; - msg->msg_controllen = 0; - msg->msg_flags = 0; -#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIPV6) - if ((sock->type == isc_sockettype_udp) - && ((dev->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0)) { - struct cmsghdr *cmsgp; - struct in6_pktinfo *pktinfop; - - socket_log(sock, NULL, TRACE, - isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_SENDTODATA, - "sendto pktinfo data, ifindex %u", - dev->pktinfo.ipi6_ifindex); - - msg->msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); - msg->msg_control = (void *)cmsg; - - cmsgp = (struct cmsghdr *)cmsg; - cmsgp->cmsg_level = IPPROTO_IPV6; - cmsgp->cmsg_type = IPV6_PKTINFO; - cmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); - pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp); - memcpy(pktinfop, &dev->pktinfo, sizeof(struct in6_pktinfo)); - } -#endif /* USE_CMSG && ISC_PLATFORM_HAVEIPV6 */ -#endif /* ISC_NET_BSD44MSGHDR */ - if (write_countp != NULL) *write_countp = write_count; } @@ -820,27 +1178,18 @@ 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; size_t read_count; -#ifndef USE_CMSG - UNUSED(cmsg); -#endif - memset(msg, 0, sizeof (struct msghdr)); if (sock->type == isc_sockettype_udp) { memset(&dev->address, 0, sizeof(dev->address)); msg->msg_name = (void *)&dev->address.type.sa; msg->msg_namelen = sizeof(dev->address.type); -#ifdef ISC_NET_RECVOVERFLOW - /* If needed, steal one iovec for overflow detection. */ - maxiov--; -#endif } else { /* TCP */ msg->msg_name = NULL; msg->msg_namelen = 0; @@ -859,10 +1208,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) @@ -891,37 +1240,17 @@ build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev, * we know there is at least one iov left, since we stole it * at the top of this function. */ -#ifdef ISC_NET_RECVOVERFLOW - if (sock->type == isc_sockettype_udp) { - iov[iovcount].iov_base = (void *)(&sock->overflow); - iov[iovcount].iov_len = 1; - iovcount++; - } -#endif msg->msg_iov = iov; msg->msg_iovlen = iovcount; -#ifdef ISC_NET_BSD44MSGHDR - msg->msg_control = NULL; - msg->msg_controllen = 0; - msg->msg_flags = 0; -#if defined(USE_CMSG) - if (sock->type == isc_sockettype_udp) { - msg->msg_control = cmsg; - msg->msg_controllen = CMSG_BUF_SIZE; - } -#endif /* USE_CMSG */ -#endif /* ISC_NET_BSD44MSGHDR */ - if (read_countp != NULL) *read_countp = read_count; } 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; @@ -935,8 +1264,7 @@ 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, @@ -963,17 +1291,13 @@ static void dump_msg(struct msghdr *msg, isc_socket_t *sock) { unsigned int i; - printf("MSGHDR %p, Socket #: %d\n", msg, sock->fd); + printf("MSGHDR %p, Socket #: %u\n", msg, sock->fd); printf("\tname %p, namelen %d\n", msg->msg_name, msg->msg_namelen); printf("\tiov %p, iovlen %d\n", msg->msg_iov, msg->msg_iovlen); for (i = 0 ; i < (unsigned int)msg->msg_iovlen ; i++) printf("\t\t%d\tbase %p, len %d\n", i, msg->msg_iov[i].buf, msg->msg_iov[i].len); -#ifdef ISC_NET_BSD44MSGHDR - printf("\tcontrol %p, controllen %d\n", msg->msg_control, - msg->msg_controllen); -#endif } #endif @@ -983,41 +1307,10 @@ dump_msg(struct msghdr *msg, isc_socket_t *sock) { #define DOIO_EOF 3 /* EOF, no event sent */ static int -doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { - int cc; - WSABUF iov[MAXSCATTERGATHER_RECV]; - size_t read_count; +completeio_recv(isc_socket_t *sock, isc_socketevent_t *dev, + struct msghdr *messagehdr, int cc, int recv_errno) { size_t actual_count; - struct msghdr msghdr; isc_buffer_t *buffer; - int recv_errno = 0; -#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); - -#if defined(ISC_SOCKET_DEBUG) - dump_msg(&msghdr,sock); -#endif - - cc = internal_recvmsg(sock->fd, &msghdr, 0, &recv_errno); - - if (cc < 0) { - if (SOFT_ERROR(recv_errno)) - return (DOIO_SOFT); - - 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: recvmsg(%d) %d bytes, err %d/%s", - sock->fd, cc, recv_errno, strbuf); - } #define SOFT_OR_HARD(_system, _isc) \ if (recv_errno == _system) { \ @@ -1027,19 +1320,30 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { } \ return (DOIO_SOFT); \ } + #define ALWAYS_HARD(_system, _isc) \ if (recv_errno == _system) { \ dev->result = _isc; \ return (DOIO_HARD); \ } + if (recv_errno != 0) { + + if (SOFT_ERROR(recv_errno)) + return (DOIO_SOFT); + SOFT_OR_HARD(WSAECONNREFUSED, ISC_R_CONNREFUSED); SOFT_OR_HARD(WSAENETUNREACH, ISC_R_NETUNREACH); SOFT_OR_HARD(WSAEHOSTUNREACH, ISC_R_HOSTUNREACH); SOFT_OR_HARD(WSAECONNRESET, ISC_R_CONNECTIONRESET); SOFT_OR_HARD(WSAENETRESET, ISC_R_CONNECTIONRESET); + SOFT_OR_HARD(WSAECONNABORTED, ISC_R_CONNECTIONRESET); SOFT_OR_HARD(WSAEDISCON, ISC_R_CONNECTIONRESET); SOFT_OR_HARD(WSAENETDOWN, ISC_R_NETDOWN); + ALWAYS_HARD(ERROR_OPERATION_ABORTED, ISC_R_CONNECTIONRESET); + ALWAYS_HARD(ERROR_PORT_UNREACHABLE, ISC_R_HOSTUNREACH); + ALWAYS_HARD(ERROR_HOST_UNREACHABLE, ISC_R_HOSTUNREACH); + ALWAYS_HARD(ERROR_NETWORK_UNREACHABLE, ISC_R_NETUNREACH); ALWAYS_HARD(WSAENOBUFS, ISC_R_NORESOURCES); #undef SOFT_OR_HARD @@ -1058,7 +1362,7 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { return (DOIO_EOF); if (sock->type == isc_sockettype_udp) { - dev->address.length = msghdr.msg_namelen; + dev->address.length = messagehdr->msg_namelen; if (isc_sockaddr_getport(&dev->address) == 0) { if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) { socket_log(sock, &dev->address, IOEVENT, @@ -1087,13 +1391,6 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { #endif /* - * If there are control messages attached, run through them and pull - * out the interesting bits. - */ - if (sock->type == isc_sockettype_udp) - process_cmsg(sock, &msghdr, dev); - - /* * update the buffers (if any) and the i/o count */ dev->n += cc; @@ -1118,9 +1415,9 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { /* * If we read less than we expected, update counters, - * and let the upper layer poke the descriptor. + * and let the upper layer handle it. */ - if (((size_t)cc != read_count) && (dev->n < dev->minimum)) + if (((size_t)cc != sock->totalBytes) && (dev->n < dev->minimum)) return (DOIO_SOFT); /* @@ -1129,7 +1426,63 @@ doio_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) { + 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++; + memset(msghdr, 0, sizeof(struct msghdr)); + + build_msghdr_recv(sock, dev, msghdr, cmsg, sock->iov, + &(sock->totalBytes)); + +#if defined(ISC_SOCKET_DEBUG) + dump_msg(msghdr, sock); +#endif + + *nbytes = internal_recvmsg(sock, lpo, msghdr, 0, recv_errno); + if (*nbytes < 0) { + if (SOFT_ERROR(*recv_errno)) { + status = DOIO_SOFT; + goto done; + } + + 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, + "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--; + } + goto done; + } + dev->result = ISC_R_SUCCESS; + status = DOIO_SOFT; +done: + return (status); +} /* * Returns: * DOIO_SUCCESS The operation succeeded. dev->result contains @@ -1144,32 +1497,12 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) { * No other return values are possible. */ static int -doio_send(isc_socket_t *sock, isc_socketevent_t *dev) { - int cc; - WSABUF iov[MAXSCATTERGATHER_SEND]; - size_t write_count; - struct msghdr msghdr; +completeio_send(isc_socket_t *sock, isc_socketevent_t *dev, struct msghdr *messagehdr, int cc, + int send_errno) { char addrbuf[ISC_SOCKADDR_FORMATSIZE]; -#if USE_CMSG - char cmsg[CMSG_BUF_SIZE]; -#else - char *cmsg = NULL; -#endif - int attempts = 0; - int send_errno = 0; char strbuf[ISC_STRERRORSIZE]; - build_msghdr_send(sock, dev, &msghdr, cmsg, iov, &write_count); - -resend: - cc = internal_sendmsg(sock->fd, &msghdr, 0, &send_errno); - - /* - * Check for error or block condition. - */ - if (cc < 0) { - if (send_errno == WSAEINTR && ++attempts < NRETRIES) - goto resend; + if(send_errno != 0) { if (SOFT_ERROR(send_errno)) return (DOIO_SOFT); @@ -1193,9 +1526,14 @@ resend: SOFT_OR_HARD(WSAECONNREFUSED, ISC_R_CONNREFUSED); SOFT_OR_HARD(WSAENOTCONN, ISC_R_CONNREFUSED); SOFT_OR_HARD(WSAECONNRESET, ISC_R_CONNECTIONRESET); + SOFT_OR_HARD(WSAECONNABORTED, ISC_R_CONNECTIONRESET); SOFT_OR_HARD(WSAENETRESET, ISC_R_CONNECTIONRESET); SOFT_OR_HARD(WSAEDISCON, ISC_R_CONNECTIONRESET); SOFT_OR_HARD(WSAENETDOWN, ISC_R_NETDOWN); + ALWAYS_HARD(ERROR_OPERATION_ABORTED, ISC_R_CONNECTIONRESET); + ALWAYS_HARD(ERROR_PORT_UNREACHABLE, ISC_R_HOSTUNREACH); + ALWAYS_HARD(ERROR_HOST_UNREACHABLE, ISC_R_HOSTUNREACH); + ALWAYS_HARD(ERROR_NETWORK_UNREACHABLE, ISC_R_NETUNREACH); ALWAYS_HARD(WSAEADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL); ALWAYS_HARD(WSAEHOSTUNREACH, ISC_R_HOSTUNREACH); ALWAYS_HARD(WSAEHOSTDOWN, ISC_R_HOSTUNREACH); @@ -1218,23 +1556,17 @@ resend: */ isc_sockaddr_format(&dev->address, addrbuf, sizeof(addrbuf)); isc__strerror(send_errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, "internal_send: %s: %s", + UNEXPECTED_ERROR(__FILE__, __LINE__, "completeio_send: %s: %s", addrbuf, strbuf); dev->result = isc__errno2result(send_errno); - return (DOIO_HARD); + return (DOIO_HARD); } - if (cc == 0) - UNEXPECTED_ERROR(__FILE__, __LINE__, - "internal_send: send() %s 0", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_RETURNED, "returned")); - /* * If we write less than we expected, update counters, poke. */ dev->n += cc; - if ((size_t)cc != write_count) + if ((size_t)cc != sock->totalBytes) return (DOIO_SOFT); /* @@ -1244,7 +1576,59 @@ resend: 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) { + 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; + } + memset(msghdr, 0, sizeof(struct msghdr)); + sock->references++; + + build_msghdr_send(sock, dev, msghdr, cmsg, sock->iov, + &(sock->totalBytes)); + + *nbytes = internal_sendmsg(sock, lpo, msghdr, 0, send_errno); + + if (*nbytes < 0) { + if (SOFT_ERROR(*send_errno)) { + status = DOIO_SOFT; + goto done; + } + if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) { + isc__strerror(*send_errno, strbuf, sizeof(strbuf)); + socket_log(sock, NULL, IOEVENT, + isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_INTERNALSEND, + "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--; + } + goto done; + } + dev->result = ISC_R_SUCCESS; + status = DOIO_SOFT; +done: + return (status); +} /* * Kill. * @@ -1252,34 +1636,34 @@ resend: * references exist. */ static void -destroy(isc_socket_t **sockp) { +destroy_socket(isc_socket_t **sockp) { isc_socket_t *sock = *sockp; isc_socketmgr_t *manager = sock->manager; + REQUIRE(sock != NULL); + socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_DESTROYING, "destroying"); + ISC_MSG_DESTROYING, "destroying socket %d", sock->fd); INSIST(ISC_LIST_EMPTY(sock->accept_list)); 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); /* - * No one has this socket open, so the watcher doesn't have to be - * poked, and the socket doesn't have to be locked. + * 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. */ - manager->fds[sock->fd] = NULL; - manager->fdstate[sock->fd] = CLOSE_PENDING; - select_poke(manager, sock->fd, SELECT_POKE_CLOSE); + socket_close(sock); + ISC_LIST_UNLINK(manager->socklist, sock, link); -#ifdef ISC_PLATFORM_USETHREADS if (ISC_LIST_EMPTY(manager->socklist)) SIGNAL(&manager->shutdown_ok); -#endif /* ISC_PLATFORM_USETHREADS */ /* * XXX should reset manager->maxfd here @@ -1292,12 +1676,11 @@ destroy(isc_socket_t **sockp) { static isc_result_t allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, - isc_socket_t **socketp) -{ + isc_socket_t **socketp) { isc_socket_t *sock; isc_result_t ret; - sock = isc_mem_get(manager->mctx, sizeof(*sock)); + sock = isc_mem_get(manager->mctx, sizeof *sock); if (sock == NULL) return (ISC_R_NOMEMORY); @@ -1309,7 +1692,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, sock->manager = manager; sock->type = type; - sock->fd = -1; + sock->fd = INVALID_SOCKET; ISC_LINK_INIT(sock, link); @@ -1320,13 +1703,17 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, ISC_LIST_INIT(sock->send_list); ISC_LIST_INIT(sock->accept_list); sock->connect_ev = NULL; - sock->pending_recv = 0; - sock->pending_send = 0; sock->pending_accept = 0; + sock->pending_close = 0; + sock->iocp = 0; sock->listener = 0; sock->connected = 0; sock->connecting = 0; sock->bound = 0; + sock->hEvent = NULL; + sock->hAlert = NULL; + sock->evthread_id = 0; + sock->wait_type = 0; /* * initialize the lock @@ -1360,13 +1747,12 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, return (ret); } - /* * This event requires that the various lists be empty, that the reference * count be 1, and that the magic number is valid. The other socket bits, * like the lock, must be initialized as well. The fd associated must be - * marked as closed, by setting it to -1 on close, or this routine will - * also close the socket. + * marked as closed, by setting it to INVALID_SOCKET on close, or this + * routine will also close the socket. */ static void free_socket(isc_socket_t **socketp) { @@ -1375,8 +1761,6 @@ free_socket(isc_socket_t **socketp) { INSIST(sock->references == 0); INSIST(VALID_SOCKET(sock)); INSIST(!sock->connecting); - INSIST(!sock->pending_recv); - INSIST(!sock->pending_send); INSIST(!sock->pending_accept); INSIST(ISC_LIST_EMPTY(sock->recv_list)); INSIST(ISC_LIST_EMPTY(sock->send_list)); @@ -1406,7 +1790,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, #if defined(USE_CMSG) || defined(SO_BSDCOMPAT) int on = 1; #endif - int socket_errno = 0; + int socket_errno; char strbuf[ISC_STRERRORSIZE]; REQUIRE(VALID_MANAGER(manager)); @@ -1420,24 +1804,18 @@ 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); + if (connection_reset_fix(sock->fd) != ISC_R_SUCCESS) { + closesocket(sock->fd); + free_socket(&sock); + return (ISC_R_UNEXPECTED); + } break; case isc_sockettype_tcp: 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) { + if (sock->fd == INVALID_SOCKET) { socket_errno = WSAGetLastError(); free_socket(&sock); @@ -1469,41 +1847,10 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, return (ISC_R_UNEXPECTED); } -#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"), - strbuf); - /* Press on... */ - } -#endif #if defined(USE_CMSG) if (type == isc_sockettype_udp) { -#if defined(SO_TIMESTAMP) - if (setsockopt(sock->fd, SOL_SOCKET, SO_TIMESTAMP, - (void *)&on, sizeof(on)) < 0 - && WSAGetLastError() != WSAENOPROTOOPT) { - isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "setsockopt(%d, SO_TIMESTAMP) %s: %s", - sock->fd, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), - strbuf); - /* Press on... */ - } -#endif /* SO_TIMESTAMP */ - #if defined(ISC_PLATFORM_HAVEIPV6) #ifdef IPV6_RECVPKTINFO /* 2292bis */ @@ -1559,13 +1906,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, * there are no external references to it yet. */ - manager->fds[sock->fd] = sock; - manager->fdstate[sock->fd] = MANAGED; ISC_LIST_APPEND(manager->socklist, sock, link); - if (manager->maxfd < sock->fd) - manager->maxfd = sock->fd; - manager->minfd = min(manager->minfd, sock->fd); - UNLOCK(&manager->lock); socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET, @@ -1610,119 +1951,12 @@ isc_socket_detach(isc_socket_t **socketp) { UNLOCK(&sock->lock); if (kill_socket) - destroy(&sock); + destroy_socket(&sock); *socketp = NULL; } /* - * I/O is possible on a given socket. Schedule an event to this task that - * will call an internal function to do the I/O. This will charge the - * task with the I/O operation and let our select loop handler get back - * to doing something real as fast as possible. - * - * The socket and manager must be locked before calling this function. - */ -static void -dispatch_recv(isc_socket_t *sock) { - intev_t *iev; - isc_socketevent_t *ev; - - INSIST(!sock->pending_recv); - - ev = ISC_LIST_HEAD(sock->recv_list); - if (ev == NULL) - return; - - sock->pending_recv = 1; - iev = &sock->readable_ev; - - socket_log(sock, NULL, EVENT, NULL, 0, 0, - "dispatch_recv: event %p -> task %p", ev, ev->ev_sender); - - sock->references++; - iev->ev_sender = sock; - iev->ev_action = internal_recv; - iev->ev_arg = sock; - - isc_task_send(ev->ev_sender, (isc_event_t **)&iev); -} - -static void -dispatch_send(isc_socket_t *sock) { - intev_t *iev; - isc_socketevent_t *ev; - - INSIST(!sock->pending_send); - - ev = ISC_LIST_HEAD(sock->send_list); - if (ev == NULL) - return; - - sock->pending_send = 1; - iev = &sock->writable_ev; - - socket_log(sock, NULL, EVENT, NULL, 0, 0, - "dispatch_send: event %p -> task %p", ev, ev->ev_sender); - - sock->references++; - iev->ev_sender = sock; - iev->ev_action = internal_send; - iev->ev_arg = sock; - - isc_task_send(ev->ev_sender, (isc_event_t **)&iev); -} - -/* - * Dispatch an internal accept event. - */ -static void -dispatch_accept(isc_socket_t *sock) { - intev_t *iev; - isc_socket_newconnev_t *ev; - - INSIST(!sock->pending_accept); - - /* - * Are there any done events left, or were they all canceled - * before the manager got the socket lock? - */ - ev = ISC_LIST_HEAD(sock->accept_list); - if (ev == NULL) - return; - - sock->pending_accept = 1; - iev = &sock->readable_ev; - - sock->references++; /* keep socket around for this internal event */ - iev->ev_sender = sock; - iev->ev_action = internal_accept; - iev->ev_arg = sock; - - isc_task_send(ev->ev_sender, (isc_event_t **)&iev); -} - -static void -dispatch_connect(isc_socket_t *sock) { - intev_t *iev; - isc_socket_connev_t *ev; - - iev = &sock->writable_ev; - - ev = sock->connect_ev; - INSIST(ev != NULL); /* XXX */ - - INSIST(sock->connecting); - - sock->references++; /* keep socket around for this internal event */ - iev->ev_sender = sock; - iev->ev_action = internal_connect; - iev->ev_arg = sock; - - isc_task_send(ev->ev_sender, (isc_event_t **)&iev); -} - -/* * Dequeue an item off the given socket's read queue, set the result code * in the done event to the one provided, and send it to the task it was * destined for. @@ -1740,8 +1974,9 @@ send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev) { (*dev)->ev_sender = sock; - if (ISC_LINK_LINKED(*dev, ev_link)) + if (ISC_LINK_LINKED(*dev, ev_link)) { ISC_LIST_DEQUEUE(sock->recv_list, *dev, ev_link); + } if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED) == ISC_SOCKEVENTATTR_ATTACHED) @@ -1764,8 +1999,9 @@ send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) { task = (*dev)->ev_sender; (*dev)->ev_sender = sock; - if (ISC_LINK_LINKED(*dev, ev_link)) + if (ISC_LINK_LINKED(*dev, ev_link)) { ISC_LIST_DEQUEUE(sock->send_list, *dev, ev_link); + } if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED) == ISC_SOCKEVENTATTR_ATTACHED) @@ -1786,20 +2022,15 @@ send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) { * so just unlock and return. */ static void -internal_accept(isc_task_t *me, isc_event_t *ev) { - isc_socket_t *sock; +internal_accept(isc_socket_t *sock, int accept_errno) { isc_socketmgr_t *manager; isc_socket_newconnev_t *dev; isc_task_t *task; ISC_SOCKADDR_LEN_T addrlen; - int fd; + SOCKET fd; isc_result_t result = ISC_R_SUCCESS; - int accept_errno = 0; char strbuf[ISC_STRERRORSIZE]; - UNUSED(me); - - sock = ev->ev_sender; INSIST(VALID_SOCKET(sock)); LOCK(&sock->lock); @@ -1811,6 +2042,7 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { INSIST(VALID_MANAGER(manager)); INSIST(sock->listener); + INSIST(sock->hEvent != NULL); INSIST(sock->pending_accept == 1); sock->pending_accept = 0; @@ -1818,7 +2050,7 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { sock->references--; /* the internal event is done with this socket */ if (sock->references == 0) { UNLOCK(&sock->lock); - destroy(&sock); + destroy_socket(&sock); return; } @@ -1834,14 +2066,14 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { /* * Try to accept the new connection. If the accept fails with - * EAGAIN or EINTR, simply poke the watcher to watch this socket - * again. + * EAGAIN or EINTR, the event wait will be notified again since + * the event will be reset on return to caller. */ - addrlen = sizeof(dev->newsocket->address.type); + addrlen = sizeof dev->newsocket->address.type; memset(&dev->newsocket->address.type.sa, 0, addrlen); fd = accept(sock->fd, &dev->newsocket->address.type.sa, (void *)&addrlen); - if (fd < 0) { + if (fd == INVALID_SOCKET) { accept_errno = WSAGetLastError(); if (SOFT_ERROR(accept_errno) || accept_errno == WSAECONNRESET) { goto soft_error; @@ -1854,7 +2086,7 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { ISC_MSG_FAILED, "failed"), strbuf); - fd = -1; + fd = INVALID_SOCKET; result = ISC_R_UNEXPECTED; } } else { @@ -1878,19 +2110,10 @@ 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; } } - if (fd != -1) { + if (fd != INVALID_SOCKET) { dev->newsocket->address.length = addrlen; dev->newsocket->pf = sock->pf; } @@ -1900,24 +2123,18 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { */ ISC_LIST_UNLINK(sock->accept_list, dev, ev_link); - /* - * Poke watcher if there are more pending accepts. - */ - if (!ISC_LIST_EMPTY(sock->accept_list)) - select_poke(sock->manager, sock->fd, SELECT_POKE_ACCEPT); - UNLOCK(&sock->lock); - if (fd != -1 && (make_nonblock(fd) != ISC_R_SUCCESS)) { + if (fd != INVALID_SOCKET && (make_nonblock(fd) != ISC_R_SUCCESS)) { closesocket(fd); - fd = -1; + fd = INVALID_SOCKET; result = ISC_R_UNEXPECTED; } /* - * -1 means the new socket didn't happen. + * INVALID_SOCKET means the new socket didn't happen. */ - if (fd != -1) { + if (fd != INVALID_SOCKET) { LOCK(&manager->lock); ISC_LIST_APPEND(manager->socklist, dev->newsocket, link); @@ -1930,18 +2147,12 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { */ dev->address = dev->newsocket->address; - manager->fds[fd] = dev->newsocket; - manager->fdstate[fd] = MANAGED; - if (manager->maxfd < fd) - manager->maxfd = fd; - manager->minfd = min(manager->minfd, sock->fd); - socket_log(sock, &dev->newsocket->address, CREATION, isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN, "accepted connection, new socket %p", dev->newsocket); - UNLOCK(&manager->lock); + UNLOCK(&manager->lock); } else { dev->newsocket->references--; free_socket(&dev->newsocket); @@ -1958,46 +2169,151 @@ internal_accept(isc_task_t *me, isc_event_t *ev) { return; soft_error: - select_poke(sock->manager, sock->fd, SELECT_POKE_ACCEPT); UNLOCK(&sock->lock); return; } +/* + * Called when a socket with a pending connect() finishes. + */ static void -internal_recv(isc_task_t *me, isc_event_t *ev) { - isc_socketevent_t *dev; - isc_socket_t *sock; +internal_connect(isc_socket_t *sock, int connect_errno) { + isc_socket_connev_t *dev; + isc_task_t *task; + int cc; + ISC_SOCKADDR_LEN_T optlen; + char strbuf[ISC_STRERRORSIZE]; - INSIST(ev->ev_type == ISC_SOCKEVENT_INTR); + INSIST(VALID_SOCKET(sock)); + + LOCK(&sock->lock); + WSAResetEvent(sock->hEvent); + + /* + * 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; + if (dev == NULL) { + INSIST(!sock->connecting); + UNLOCK(&sock->lock); + return; + } + + INSIST(sock->connecting); + sock->connecting = 0; + + /* + * Get any possible error status here. + */ + optlen = sizeof(cc); + if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, + (void *)&cc, (void *)&optlen) < 0) + connect_errno = WSAGetLastError(); + else + connect_errno = 0; + + if (connect_errno != 0) { + /* + * If the error is EAGAIN, just try again on this + * fd and pretend nothing strange happened. + */ + if (SOFT_ERROR(connect_errno) || connect_errno == WSAEINPROGRESS) { + sock->connecting = 1; + UNLOCK(&sock->lock); + + return; + } + + /* + * Translate other errors into ISC_R_* flavors. + */ + 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); + ERROR_MATCH(WSAEAFNOSUPPORT, ISC_R_ADDRNOTAVAIL); + ERROR_MATCH(WSAECONNREFUSED, ISC_R_CONNREFUSED); + ERROR_MATCH(WSAEHOSTUNREACH, ISC_R_HOSTUNREACH); + ERROR_MATCH(WSAEHOSTDOWN, ISC_R_HOSTUNREACH); + ERROR_MATCH(WSAENETUNREACH, ISC_R_NETUNREACH); + ERROR_MATCH(WSAENOBUFS, ISC_R_NORESOURCES); + ERROR_MATCH(EPERM, ISC_R_HOSTUNREACH); + ERROR_MATCH(EPIPE, ISC_R_NOTCONNECTED); + ERROR_MATCH(WSAETIMEDOUT, ISC_R_TIMEDOUT); +#undef ERROR_MATCH + default: + dev->result = ISC_R_UNEXPECTED; + isc__strerror(connect_errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "internal_connect: connect() %s", + strbuf); + } + } else { + dev->result = ISC_R_SUCCESS; + sock->connected = 1; + sock->bound = 1; + } + + sock->connect_ev = NULL; + + UNLOCK(&sock->lock); + + task = dev->ev_sender; + dev->ev_sender = sock; + isc_task_sendanddetach(&task, (isc_event_t **)&dev); +} + +static void +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; - sock = ev->ev_sender; INSIST(VALID_SOCKET(sock)); 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); - - INSIST(sock->pending_recv == 1); - sock->pending_recv = 0; + "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(&sock); + destroy_socket(&sock); return; } + /* 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) { + ldev = ISC_LIST_NEXT(ldev, ev_link); + } + if (ldev == NULL) + goto done; + /* * Try to do as much I/O as possible on this socket. There are no * limits here, currently. */ - dev = ISC_LIST_HEAD(sock->recv_list); - while (dev != NULL) { - switch (doio_recv(sock, dev)) { + switch (completeio_recv(sock, dev, messagehdr, nbytes, recv_errno)) { case DOIO_SOFT: - goto poke; + cc = 0; + recv_errno = 0; + io_state = startio_recv(sock, dev, &cc, FALSE, &recv_errno); + goto done; case DOIO_EOF: /* @@ -2005,322 +2321,304 @@ internal_recv(isc_task_t *me, isc_event_t *ev) { * Run through the event queue and dispatch all * the events with an EOF result code. */ - do { - dev->result = ISC_R_EOF; - send_recvdone_event(sock, &dev); - dev = ISC_LIST_HEAD(sock->recv_list); - } while (dev != NULL); - goto poke; + dev->result = ISC_R_EOF; + send_recvdone_event(sock, &dev); + goto done; case DOIO_SUCCESS: case DOIO_HARD: send_recvdone_event(sock, &dev); break; } - - dev = ISC_LIST_HEAD(sock->recv_list); - } - - poke: - if (!ISC_LIST_EMPTY(sock->recv_list)) - select_poke(sock->manager, sock->fd, SELECT_POKE_READ); - + done: UNLOCK(&sock->lock); } static void -internal_send(isc_task_t *me, isc_event_t *ev) { - isc_socketevent_t *dev; - isc_socket_t *sock; - - INSIST(ev->ev_type == ISC_SOCKEVENT_INTW); +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; /* * Find out what socket this is and lock it. */ - sock = (isc_socket_t *)ev->ev_sender; INSIST(VALID_SOCKET(sock)); 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); - - INSIST(sock->pending_send == 1); - sock->pending_send = 0; + "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(&sock); + destroy_socket(&sock); return; } + /* If the event is no longer in the list we can just return */ + ldev = ISC_LIST_HEAD(sock->send_list); + while (ldev != NULL && ldev != dev) { + ldev = ISC_LIST_NEXT(ldev, ev_link); + } + if (ldev == NULL) + goto done; /* * Try to do as much I/O as possible on this socket. There are no * limits here, currently. */ - dev = ISC_LIST_HEAD(sock->send_list); - while (dev != NULL) { - switch (doio_send(sock, dev)) { - case DOIO_SOFT: - goto poke; - - case DOIO_HARD: - case DOIO_SUCCESS: - send_senddone_event(sock, &dev); - break; - } + switch (completeio_send(sock, dev, messagehdr, nbytes, send_errno)) { + case DOIO_SOFT: + cc = 0; + send_errno = 0; + io_state = startio_send(sock, dev, &cc, FALSE, &send_errno); + goto done; - dev = ISC_LIST_HEAD(sock->send_list); + case DOIO_HARD: + case DOIO_SUCCESS: + send_senddone_event(sock, &dev); + break; } - poke: - if (!ISC_LIST_EMPTY(sock->send_list)) - select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE); + done: UNLOCK(&sock->lock); } -static void -process_fds(isc_socketmgr_t *manager, int maxfd, int minfd, - fd_set *readfds, fd_set *writefds, fd_set *exceptfds) -{ - int i; - isc_socket_t *sock; - isc_boolean_t unlock_sock; - BOOL conn_check = FALSE; +/* + * This is the I/O Completion Port Worker Function. It loops forever + * waiting for I/O to complete and then forwards them for further + * processing. There are a number of these in separate threads. + */ +static isc_threadresult_t WINAPI +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; + isc_socketevent_t *dev = NULL; + struct msghdr *messagehdr = NULL; + int errval; + char strbuf[ISC_STRERRORSIZE]; + int errstatus; - REQUIRE(maxfd <= FD_SETSIZE); + REQUIRE(VALID_MANAGER(manager)); - /* - * Process read/writes on other fds here. Avoid locking - * and unlocking twice if both reads and writes are possible. + /* Set the thread priority high enough so I/O will + * preempt normal recv packet processing, but not + * higher than the timer sync thread. */ - for (i = minfd ; i <= maxfd ; i++) { - if (manager->fdstate[i] == CLOSE_PENDING) { - manager->fdstate[i] = CLOSED; - FD_CLR(i, &manager->read_fds); - FD_CLR(i, &manager->write_fds); - FD_CLR(i, &manager->except_fds); - - closesocket(i); + if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL)) { + errval = GetLastError(); + isc__strerror(errval, strbuf, sizeof(strbuf)); + FATAL_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_FAILED, + "Can't set thread priority: %s"), + strbuf); + } - continue; - } - sock = manager->fds[i]; - unlock_sock = ISC_FALSE; - if (FD_ISSET(i, readfds)) { - if (sock == NULL) { - FD_CLR(i, &manager->read_fds); - goto check_write; - } - unlock_sock = ISC_TRUE; - LOCK(&sock->lock); - if (!SOCK_DEAD(sock)) { - if (sock->listener) - dispatch_accept(sock); - else - dispatch_recv(sock); - } - FD_CLR(i, &manager->read_fds); - } - check_write: - if (FD_ISSET(i, writefds)) { - if (sock == NULL) { - FD_CLR(i, &manager->write_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; - } - else - dispatch_send(sock); - } - FD_CLR(i, &manager->write_fds); - FD_CLR(i, &manager->except_fds); + /* + * Loop forever waiting on I/O Completions and then processing them + */ + while(TRUE) { + bSuccess = GetQueuedCompletionStatus ( + manager->hIoCompletionPort, + &nbytes, + (LPDWORD) &sock, + (LPOVERLAPPED *)&lpo, + INFINITE + ); + if(lpo == NULL ) { + /* + * Received request to exit + */ + break; } - 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); + errstatus = 0; + if(!bSuccess) { + /* + * I/O Failure + * Find out why + */ + WSAGetOverlappedResult(sock->fd, (LPWSAOVERLAPPED) &lpo, + &tbytes, FALSE, &tflags); + dev = lpo->dev; } - if (unlock_sock) - UNLOCK(&sock->lock); + request = lpo->request_type; + dev = lpo->dev; + 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 + */ + manager_log(manager, TRACE, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_EXITING, "SocketIoThread exiting")); + return ((isc_threadresult_t)0); } - -#ifdef ISC_PLATFORM_USETHREADS /* - * This is the thread that will loop forever, always in a select or poll - * call. + * This is the thread that will loop forever, waiting for an event to + * happen. * - * When select returns something to do, track down what thread gets to do - * this I/O and post the event to it. + * When the wait returns something to do, find the signaled event + * and issue the request for the given socket */ static isc_threadresult_t WINAPI -watcher(void *uap) { - isc_socketmgr_t *manager = uap; - isc_boolean_t done; - int ctlfd; +event_wait(void *uap) { + events_thread_t *evthread = uap; + isc_socketmgr_t *manager = evthread->manager; int cc; - fd_set readfds; - fd_set writefds; - fd_set exceptfds; - int msg, fd; - int maxfd; - int minfd; - int watcher_errno = 0; + int event_errno; char strbuf[ISC_STRERRORSIZE]; + isc_socket_t *wsock; + int iEvent; + int max_event; + sock_event_list *evlist; + WSANETWORKEVENTS NetworkEvents; + int err; - /* Timeout on select in case it's necesasary */ - struct timeval tv; - tv.tv_sec = MAX_SELECT_SECONDS; - tv.tv_usec = MAX_SELECT_MILLISECONDS*1000; + REQUIRE(evthread != NULL); + REQUIRE(VALID_MANAGER(manager)); - /* - * Get the control fd here. This will never change. - */ - LOCK(&manager->lock); - ctlfd = manager->pipe_fds[0]; + /* We need to know the Id of the thread */ + evthread->thread_id = GetCurrentThreadId(); - done = ISC_FALSE; - while (!done) { + evlist = &(evthread->sockev_list); + + /* See if there's anything waiting to add to the event list */ + if (manager->event_written > 0) + process_eventlist(evlist, manager); + + while (!manager->bShutdown) { do { - readfds = manager->read_fds; - writefds = manager->write_fds; - exceptfds = manager->except_fds; - maxfd = manager->maxfd; /* Pipe not included */ - minfd = manager->minfd; - watcher_errno = 0; - - UNLOCK(&manager->lock); - - if(maxfd > 0) { - cc = select(maxfd, &readfds, &writefds, - &exceptfds, &tv); - if (cc < 0 && bpipe_written <= 0) { - watcher_errno = WSAGetLastError(); - if (!SOFT_ERROR(watcher_errno) && - watcher_errno != WSAEINVAL) { - isc__strerror(watcher_errno, - strbuf, sizeof(strbuf)); - FATAL_ERROR(__FILE__, __LINE__, - "select() %s: %s", - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), - strbuf); - } - } - } else { - /* - * Nothing to select on yet, so sleep - * and check again for work - */ - Sleep(MAX_SELECT_SECONDS*1000 - + MAX_SELECT_MILLISECONDS); + max_event = evlist->max_event; + event_errno = 0; + + WSAResetEvent(evlist->aEventList[0]); + cc = WSAWaitForMultipleEvents(max_event, + evlist->aEventList, FALSE, WSA_INFINITE, + FALSE); + if (cc == WSA_WAIT_FAILED) { + event_errno = WSAGetLastError(); + if (!SOFT_ERROR(event_errno)) { + isc__strerror(event_errno, strbuf, + sizeof(strbuf)); + FATAL_ERROR(__FILE__, __LINE__, + "WSAWaitForMultipleEvents() %s: %s", + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, + "failed"), + strbuf); + } } - LOCK(&manager->lock); - } while (cc < 0 && bpipe_written <= 0); + } while (cc < 0 && !manager->bShutdown + && manager->event_written == 0); + + + if (manager->bShutdown) + break; + iEvent = cc - WSA_WAIT_EVENT_0; /* - * Process reads on internal, control fd. + * Add or delete events as requested */ - while (bpipe_written > 0) { - select_readmsg(manager, &fd, &msg); - InterlockedDecrement(&bpipe_written); + if (manager->event_written > 0) + process_eventlist(evlist, manager); + /* + * Stopped to add and delete events on the list + */ + if(iEvent == 0) + continue; - manager_log(manager, IOEVENT, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_SOCKET, - ISC_MSG_WATCHERMSG, - "watcher got message %d"), - msg); - - /* - * Nothing to read? - */ - if (msg == SELECT_POKE_NOTHING) - break; + wsock = evlist->aSockList[iEvent]; + if (wsock == NULL) + continue; - /* - * Handle shutdown message. We really should - * jump out of this loop right away, but - * it doesn't matter if we have to do a little - * more work first. - */ - if (msg == SELECT_POKE_SHUTDOWN) { - done = ISC_TRUE; + if (WSAEnumNetworkEvents( wsock->fd, 0, + &NetworkEvents) == SOCKET_ERROR) { + err = WSAGetLastError(); + isc__strerror(err, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "event_wait: WSAEnumNetworkEvents() %s", + strbuf); + } - break; - } + if(NetworkEvents.lNetworkEvents == 0 ) { + WSAResetEvent(wsock->hEvent); + continue; + } + + if(NetworkEvents.lNetworkEvents & FD_CLOSE) { + WSAResetEvent(wsock->hEvent); + continue; + } + + if (wsock->references > 0 && wsock->pending_close == 0) { + 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); + } } - process_fds(manager, maxfd, minfd, &readfds, &writefds, &exceptfds); + if (wsock->hEvent != NULL) + WSAResetEvent(wsock->hEvent); } manager_log(manager, TRACE, isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_EXITING, "watcher exiting")); + ISC_MSG_EXITING, "event_wait exiting")); - UNLOCK(&manager->lock); return ((isc_threadresult_t)0); } -#endif /* ISC_PLATFORM_USETHREADS */ - /* * Create a new socket manager. */ 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 + events_thread_t *evthread = NULL; REQUIRE(managerp != NULL && *managerp == NULL); -#ifndef ISC_PLATFORM_USETHREADS - if (socketmgr != NULL) { - socketmgr->refs++; - *managerp = socketmgr; - return (ISC_R_SUCCESS); - } -#endif /* ISC_PLATFORM_USETHREADS */ - manager = isc_mem_get(mctx, sizeof(*manager)); if (manager == NULL) return (ISC_R_NOMEMORY); manager->magic = SOCKET_MANAGER_MAGIC; manager->mctx = NULL; - memset(manager->fds, 0, sizeof(manager->fds)); ISC_LIST_INIT(manager->socklist); if (isc_mutex_init(&manager->lock) != ISC_R_SUCCESS) { isc_mem_put(mctx, manager, sizeof(*manager)); @@ -2332,7 +2630,7 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { } if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) { DESTROYLOCK(&manager->lock); - isc_mem_put(mctx, manager, sizeof(*manager)); + isc_mem_put(mctx, manager, sizeof (*manager)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_condition_init() %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, @@ -2340,50 +2638,30 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { return (ISC_R_UNEXPECTED); } - /* - * Create the special fds that will be used to wake up the - * select/poll loop when something internal needs to be done. - */ - 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"), - strbuf); - - return (ISC_R_UNEXPECTED); - } + isc_mem_attach(mctx, &manager->mctx); + iocompletionport_init(manager); /* Create the Completion Ports */ /* - * Set up initial state for the select loop + * Event Wait Thread Initialization */ - FD_ZERO(&manager->read_fds); - FD_ZERO(&manager->write_fds); - FD_ZERO(&manager->except_fds); - manager->maxfd = 0; - manager->minfd = FD_SETSIZE; - memset(manager->fdstate, 0, sizeof(manager->fdstate)); + ISC_LIST_INIT(manager->ev_threads); /* - * Start up the select/poll thread. + * Start up the initial event wait thread. */ - if (isc_thread_create(watcher, manager, &manager->watcher) != - ISC_R_SUCCESS) { + if (event_thread_create(&evthread, manager) != ISC_R_SUCCESS) { DESTROYLOCK(&manager->lock); isc_mem_put(mctx, manager, sizeof(*manager)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_thread_create() %s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed")); - _close(manager->pipe_fds[0]); - _close(manager->pipe_fds[1]); return (ISC_R_UNEXPECTED); } - isc_mem_attach(mctx, &manager->mctx); + + manager->prime_alert = evthread->sockev_list.aEventList[0]; + manager->event_written = 0; + manager->bShutdown = ISC_FALSE; + + /* Initialize the event update list */ + ISC_LIST_INIT(manager->event_updates); *managerp = manager; @@ -2395,6 +2673,7 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) { isc_socketmgr_t *manager; int i; isc_mem_t *mctx; + events_thread_t *evthread; /* * Destroy a socket manager. @@ -2404,17 +2683,8 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) { manager = *managerp; REQUIRE(VALID_MANAGER(manager)); -#ifndef ISC_PLATFORM_USETHREADS - if (manager->refs > 1) { - manager->refs--; - *managerp = NULL; - return; - } -#endif /* ISC_PLATFORM_USETHREADS */ - LOCK(&manager->lock); -#ifdef ISC_PLATFORM_USETHREADS /* * Wait for all sockets to be destroyed. */ @@ -2425,56 +2695,59 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) { "sockets exist")); WAIT(&manager->shutdown_ok, &manager->lock); } -#else /* ISC_PLATFORM_USETHREADS */ - /* - * Hope all sockets have been destroyed. - */ - if (!ISC_LIST_EMPTY(manager->socklist)) { - manager_log(manager, CREATION, - isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_SOCKETSREMAIN, - "sockets exist")); - INSIST(0); - } -#endif /* ISC_PLATFORM_USETHREADS */ UNLOCK(&manager->lock); /* - * Here, poke our select/poll thread. Do this by closing the write - * half of the pipe, which will send EOF to the read half. - * This is currently a no-op in the non-threaded case. + * Here, we need to had some wait code for the completion port + * thread. */ - select_poke(manager, 0, SELECT_POKE_SHUTDOWN); + signal_iocompletionport_exit(manager); + manager->bShutdown = ISC_TRUE; -#ifdef ISC_PLATFORM_USETHREADS /* - * Wait for thread to exit. + * Wait for threads to exit. */ - if (isc_thread_join(manager->watcher, NULL) != ISC_R_SUCCESS) - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_thread_join() %s", + + /* + * Shut down the event wait threads + */ + evthread = ISC_LIST_HEAD(manager->ev_threads); + while (evthread != NULL) { + WSASetEvent(evthread->sockev_list.aEventList[0]); + if (isc_thread_join(evthread->thread_handle, NULL) != ISC_R_SUCCESS) + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_thread_join() for event_wait %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); -#endif /* ISC_PLATFORM_USETHREADS */ + ISC_LIST_DEQUEUE(manager->ev_threads, evthread, link); + isc_mem_put(manager->mctx, evthread, sizeof(*evthread)); + evthread = ISC_LIST_HEAD(manager->ev_threads); + } /* + * Now the I/O Completion Port Worker Threads + */ + for (i = 0; i < manager->maxIOCPThreads; i++) { + if (isc_thread_join((isc_thread_t) manager->hIOCPThreads[i], NULL) + != ISC_R_SUCCESS) + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_thread_join() for Completion Port %s", + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, "failed")); + } + /* * Clean up. */ -#ifdef ISC_PLATFORM_USETHREADS - _close(manager->pipe_fds[0]); - _close(manager->pipe_fds[1]); - (void)isc_condition_destroy(&manager->shutdown_ok); -#endif /* ISC_PLATFORM_USETHREADS */ - for (i = 0 ; i < FD_SETSIZE ; i++) - if (manager->fdstate[i] == CLOSE_PENDING) - closesocket(i); + CloseHandle(manager->hIoCompletionPort); + + (void)isc_condition_destroy(&manager->shutdown_ok); DESTROYLOCK(&manager->lock); manager->magic = 0; mctx= manager->mctx; - isc_mem_put(mctx, manager, sizeof(*manager)); + isc_mem_put(mctx, manager, sizeof *manager); isc_mem_detach(&mctx); @@ -2483,26 +2756,18 @@ 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; - isc_boolean_t have_lock = ISC_FALSE; + int cc = 0; isc_task_t *ntask = NULL; isc_result_t result = ISC_R_SUCCESS; + int recv_errno = 0; dev->ev_sender = task; - if (sock->type == isc_sockettype_udp) { - io_state = doio_recv(sock, dev); - } else { - LOCK(&sock->lock); - have_lock = ISC_TRUE; - - if (ISC_LIST_EMPTY(sock->recv_list)) - io_state = doio_recv(sock, dev); - else - io_state = DOIO_SOFT; - } + LOCK(&sock->lock); + iocompletionport_update(sock); + io_state = startio_recv(sock, dev, &cc, FALSE, &recv_errno); switch (io_state) { case DOIO_SOFT: @@ -2515,17 +2780,9 @@ socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, isc_task_attach(task, &ntask); dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED; - if (!have_lock) { - LOCK(&sock->lock); - have_lock = ISC_TRUE; - } - /* - * Enqueue the request. If the socket was previously not being - * watched, poke the watcher to start paying attention to it. + * Enqueue the request. */ - if (ISC_LIST_EMPTY(sock->recv_list)) - select_poke(sock->manager, sock->fd, SELECT_POKE_READ); ISC_LIST_ENQUEUE(sock->recv_list, dev, ev_link); socket_log(sock, NULL, EVENT, NULL, 0, 0, @@ -2546,9 +2803,7 @@ socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, send_recvdone_event(sock, &dev); break; } - - if (have_lock) - UNLOCK(&sock->lock); + UNLOCK(&sock->lock); return (result); } @@ -2663,6 +2918,8 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, unsigned int flags) { int io_state; + int send_errno = 0; + int cc = 0; isc_boolean_t have_lock = ISC_FALSE; isc_task_t *ntask = NULL; isc_result_t result = ISC_R_SUCCESS; @@ -2685,17 +2942,10 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, dev->pktinfo.ipi6_ifindex = 0; } - if (sock->type == isc_sockettype_udp) - io_state = doio_send(sock, dev); - else { - LOCK(&sock->lock); - have_lock = ISC_TRUE; - - if (ISC_LIST_EMPTY(sock->send_list)) - io_state = doio_send(sock, dev); - else - io_state = DOIO_SOFT; - } + LOCK(&sock->lock); + have_lock = ISC_TRUE; + iocompletionport_update(sock); + io_state = startio_send(sock, dev, &cc, FALSE, &send_errno); switch (io_state) { case DOIO_SOFT: @@ -2703,7 +2953,6 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, * We couldn't send all or part of the request right now, so * queue it unless ISC_SOCKFLAG_NORETRY is set. */ - if ((flags & ISC_SOCKFLAG_NORETRY) == 0) { isc_task_attach(task, &ntask); dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED; @@ -2713,12 +2962,8 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, } /* - * Enqueue the request. If the socket was previously not being - * watched, poke the watcher to start paying attention to it. + * Enqueue the request. */ - if (ISC_LIST_EMPTY(sock->send_list)) - select_poke(sock->manager, sock->fd, - SELECT_POKE_WRITE); ISC_LIST_ENQUEUE(sock->send_list, dev, ev_link); socket_log(sock, NULL, EVENT, NULL, 0, 0, @@ -2728,12 +2973,8 @@ 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: - if ((flags & ISC_SOCKFLAG_IMMEDIATE) == 0) - send_senddone_event(sock, &dev); break; } @@ -2776,7 +3017,6 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, if (dev == NULL) { return (ISC_R_NOMEMORY); } - dev->region = *region; return (socket_send(sock, dev, task, address, pktinfo, 0)); @@ -2852,7 +3092,7 @@ 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 = 0; + int bind_errno; char strbuf[ISC_STRERRORSIZE]; int on = 1; @@ -2865,7 +3105,7 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr) { return (ISC_R_FAMILYMISMATCH); } if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, - sizeof(on)) < 0) { + sizeof on) < 0) { UNEXPECTED_ERROR(__FILE__, __LINE__, "setsockopt(%d) %s", sock->fd, isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, @@ -2900,6 +3140,15 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr) { return (ISC_R_SUCCESS); } +isc_result_t +isc_socket_filter(isc_socket_t *sock, const char *filter) { + UNUSED(sock); + UNUSED(filter); + + REQUIRE(VALID_SOCKET(sock)); + return (ISC_R_NOTIMPLEMENTED); +} + /* * Set up to listen on a given socket. We do this by creating an internal * event that will be dispatched when the socket has read activity. The @@ -2913,6 +3162,7 @@ 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]; + isc_result_t retstat; REQUIRE(VALID_SOCKET(sock)); @@ -2936,6 +3186,20 @@ isc_socket_listen(isc_socket_t *sock, unsigned int backlog) { sock->listener = 1; + /* Add the socket to the list of events to accept */ + retstat = socket_event_add(sock, FD_ACCEPT | FD_CLOSE); + if (retstat != ISC_R_SUCCESS) { + UNLOCK(&sock->lock); + if (retstat != ISC_R_NOSPACE) { + isc__strerror(WSAGetLastError(), strbuf, + sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_socket_listen: socket_event_add: %s", strbuf); + } + return (retstat); + } + + UNLOCK(&sock->lock); return (ISC_R_SUCCESS); } @@ -2952,7 +3216,6 @@ isc_socket_accept(isc_socket_t *sock, isc_task_t *ntask = NULL; isc_socket_t *nsock; isc_result_t ret; - isc_boolean_t do_poke = ISC_FALSE; REQUIRE(VALID_SOCKET(sock)); manager = sock->manager; @@ -2993,18 +3256,10 @@ isc_socket_accept(isc_socket_t *sock, dev->newsocket = nsock; /* - * Poke watcher here. We still have the socket locked, so there - * is no race condition. We will keep the lock for such a short - * bit of time waking it up now or later won't matter all that much. + * Enqueue the event */ - if (ISC_LIST_EMPTY(sock->accept_list)) - do_poke = ISC_TRUE; - ISC_LIST_ENQUEUE(sock->accept_list, dev, ev_link); - if (do_poke) - select_poke(manager, sock->fd, SELECT_POKE_ACCEPT); - UNLOCK(&sock->lock); return (ISC_R_SUCCESS); } @@ -3017,6 +3272,7 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, isc_task_t *ntask = NULL; isc_socketmgr_t *manager; int cc; + int retstat; int errval; char strbuf[ISC_STRERRORSIZE]; @@ -3069,7 +3325,6 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, ERROR_MATCH(WSAENOBUFS, ISC_R_NORESOURCES); ERROR_MATCH(EPERM, ISC_R_HOSTUNREACH); ERROR_MATCH(EPIPE, ISC_R_NOTCONNECTED); - ERROR_MATCH(WSAECONNRESET, ISC_R_CONNECTIONRESET); #undef ERROR_MATCH } @@ -3115,125 +3370,24 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, dev->ev_sender = ntask; /* - * Poke watcher here. We still have the socket locked, so there - * is no race condition. We will keep the lock for such a short - * bit of time waking it up now or later won't matter all that much. + * Enqueue the request. */ - if (sock->connect_ev == NULL) - select_poke(manager, sock->fd, SELECT_POKE_CONNECT); - sock->connect_ev = dev; - - UNLOCK(&sock->lock); - return (ISC_R_SUCCESS); -} - -/* - * Called when a socket with a pending connect() finishes. - */ -static void -internal_connect(isc_task_t *me, isc_event_t *ev) { - isc_socket_t *sock; - isc_socket_connev_t *dev; - isc_task_t *task; - int cc; - ISC_SOCKADDR_LEN_T optlen; - int connect_errno = 0; - char strbuf[ISC_STRERRORSIZE]; - - UNUSED(me); - INSIST(ev->ev_type == ISC_SOCKEVENT_INTW); - - sock = ev->ev_sender; - INSIST(VALID_SOCKET(sock)); - - 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(&sock); - return; - } - - /* - * Has this event been canceled? - */ - dev = sock->connect_ev; - if (dev == NULL) { - INSIST(!sock->connecting); + /* Add the socket to the list of events to connect */ + retstat = socket_event_add(sock, FD_CONNECT | FD_CLOSE); + if (retstat != ISC_R_SUCCESS) { UNLOCK(&sock->lock); - return; - } - - INSIST(sock->connecting); - sock->connecting = 0; - - /* - * Get any possible error status here. - */ - optlen = sizeof(cc); - if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, - (void *)&cc, (void *)&optlen) < 0) - connect_errno = WSAGetLastError(); - - if (connect_errno != 0) { - /* - * If the error is WSAEAGAIN, just re-select on this - * fd and pretend nothing strange happened. - */ - if (SOFT_ERROR(connect_errno) || connect_errno == WSAEINPROGRESS) { - sock->connecting = 1; - select_poke(sock->manager, sock->fd, - SELECT_POKE_CONNECT); - UNLOCK(&sock->lock); - - return; - } - - /* - * Translate other errors into ISC_R_* flavors. - */ - 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); - ERROR_MATCH(WSAEAFNOSUPPORT, ISC_R_ADDRNOTAVAIL); - ERROR_MATCH(WSAECONNREFUSED, ISC_R_CONNREFUSED); - ERROR_MATCH(WSAEHOSTUNREACH, ISC_R_HOSTUNREACH); - ERROR_MATCH(WSAEHOSTDOWN, ISC_R_HOSTUNREACH); - ERROR_MATCH(WSAENETUNREACH, ISC_R_NETUNREACH); - ERROR_MATCH(WSAENOBUFS, ISC_R_NORESOURCES); - ERROR_MATCH(EPERM, ISC_R_HOSTUNREACH); - ERROR_MATCH(EPIPE, ISC_R_NOTCONNECTED); - ERROR_MATCH(WSAETIMEDOUT, ISC_R_TIMEDOUT); - ERROR_MATCH(WSAECONNRESET, ISC_R_CONNECTIONRESET); -#undef ERROR_MATCH - default: - dev->result = ISC_R_UNEXPECTED; - isc__strerror(connect_errno, strbuf, sizeof(strbuf)); + if (retstat != ISC_R_NOSPACE) { + isc__strerror(WSAGetLastError(), strbuf, + sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, - "internal_connect: connect() %s", - strbuf); + "isc_socket_connect: socket_event_add: %s", strbuf); } - } else { - dev->result = ISC_R_SUCCESS; - sock->connected = 1; - sock->bound = 1; + return (retstat); } - sock->connect_ev = NULL; - UNLOCK(&sock->lock); - - task = dev->ev_sender; - dev->ev_sender = sock; - isc_task_sendanddetach(&task, (isc_event_t **)&dev); + return (ISC_R_SUCCESS); } isc_result_t @@ -3275,7 +3429,7 @@ isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) { ret = ISC_R_SUCCESS; - len = sizeof(addressp->type); + len = sizeof addressp->type; if (getsockname(sock->fd, &addressp->type.sa, (void *)&len) < 0) { isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "getsockname: %s", @@ -3330,7 +3484,6 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) { while (dev != NULL) { current_task = dev->ev_sender; next = ISC_LIST_NEXT(dev, ev_link); - if ((task == NULL) || (task == current_task)) { dev->result = ISC_R_CANCELED; send_recvdone_event(sock, &dev); @@ -3350,7 +3503,6 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) { while (dev != NULL) { current_task = dev->ev_sender; next = ISC_LIST_NEXT(dev, ev_link); - if ((task == NULL) || (task == current_task)) { dev->result = ISC_R_CANCELED; send_senddone_event(sock, &dev); @@ -3366,6 +3518,8 @@ 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; next = ISC_LIST_NEXT(dev, ev_link); @@ -3432,3 +3586,22 @@ isc_socket_isbound(isc_socket_t *sock) { return (val); } + +void +isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) { +#if defined(IPV6_V6ONLY) + int onoff = yes ? 1 : 0; +#else + UNUSED(yes); + UNUSED(sock); +#endif + + REQUIRE(VALID_SOCKET(sock)); + +#ifdef IPV6_V6ONLY + if (sock->pf == AF_INET6) { + (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, + (void *)&onoff, sizeof(onoff)); + } +#endif +} diff --git a/lib/isc/win32/strerror.c b/lib/isc/win32/strerror.c new file mode 100644 index 00000000..ceb45c8b --- /dev/null +++ b/lib/isc/win32/strerror.c @@ -0,0 +1,459 @@ +/* + * Copyright (C) 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: strerror.c,v 1.5.186.2 2003/07/22 04:03:51 marka Exp $ */ + +#include <config.h> + +#include <stdio.h> +#include <string.h> +#include <winsock2.h> + +#include <isc/mutex.h> +#include <isc/once.h> +#include <isc/print.h> +#include <isc/strerror.h> +#include <isc/util.h> + +/* + * Forward declarations + */ + +char * +FormatError(int error); + +char * +GetWSAErrorMessage(int errval); + +char * +NTstrerror(int err, BOOL *bfreebuf); + +/* + * We need to do this this way for profiled locks. + */ + +static isc_mutex_t isc_strerror_lock; +static void init_lock(void) { + RUNTIME_CHECK(isc_mutex_init(&isc_strerror_lock) == ISC_R_SUCCESS); +} + +/* + * This routine needs to free up any buffer allocated by FormatMessage + * if that routine gets used. + */ + +void +isc__strerror(int num, char *buf, size_t size) { + char *msg; + BOOL freebuf; + unsigned int unum = num; + static isc_once_t once = ISC_ONCE_INIT; + + REQUIRE(buf != NULL); + + RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS); + + LOCK(&isc_strerror_lock); + freebuf = FALSE; + msg = NTstrerror(num, &freebuf); + if (msg != NULL) + snprintf(buf, size, "%s", msg); + else + snprintf(buf, size, "Unknown error: %u", unum); + if(freebuf && msg != NULL) { + LocalFree(msg); + } + UNLOCK(&isc_strerror_lock); +} + +/* + * Note this will cause a memory leak unless the memory allocated here + * is freed by calling LocalFree. isc__strerror does this before unlocking. + * This only gets called if there is a system type of error and will likely + * be an unusual event. + */ +char * +FormatError(int error) { + LPVOID lpMsgBuf = NULL; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + error, + /* Default language */ + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, + NULL); + + return (lpMsgBuf); +} + +/* + * This routine checks the error value and calls the WSA Windows Sockets + * Error message function GetWSAErrorMessage below if it's within that range + * since those messages are not available in the system error messages. + */ +char * +NTstrerror(int err, BOOL *bfreebuf) { + char *retmsg = NULL; + + /* Copy the error value first in case of other errors */ + DWORD errval = err; + + *bfreebuf = FALSE; + + /* Get the Winsock2 error messages */ + if (errval >= WSABASEERR && errval <= (WSABASEERR + 1015)) { + retmsg = GetWSAErrorMessage(errval); + if (retmsg != NULL) + return (retmsg); + } + /* + * If it's not one of the standard Unix error codes, + * try a system error message + */ + if (errval > (DWORD) _sys_nerr) { + *bfreebuf = TRUE; + return (FormatError(errval)); + } else { + return (strerror(errval)); + } +} + +/* + * This is a replacement for perror + */ +void __cdecl +NTperror(char *errmsg) { + /* Copy the error value first in case of other errors */ + int errval = errno; + BOOL bfreebuf = FALSE; + char *msg; + + msg = NTstrerror(errval, &bfreebuf); + fprintf(stderr, "%s: %s\n", errmsg, msg); + if(bfreebuf == TRUE) { + LocalFree(msg); + } + +} + +/* + * Return the error string related to Winsock2 errors. + * This function is necessary since FormatMessage knows nothing about them + * and there is no function to get them. + */ +char * +GetWSAErrorMessage(int errval) { + char *msg; + + switch (errval) { + + case WSAEINTR: + msg = "Interrupted system call"; + break; + + case WSAEBADF: + msg = "Bad file number"; + break; + + case WSAEACCES: + msg = "Permission denied"; + break; + + case WSAEFAULT: + msg = "Bad address"; + break; + + case WSAEINVAL: + msg = "Invalid argument"; + break; + + case WSAEMFILE: + msg = "Too many open sockets"; + break; + + case WSAEWOULDBLOCK: + msg = "Operation would block"; + break; + + case WSAEINPROGRESS: + msg = "Operation now in progress"; + break; + + case WSAEALREADY: + msg = "Operation already in progress"; + break; + + case WSAENOTSOCK: + msg = "Socket operation on non-socket"; + break; + + case WSAEDESTADDRREQ: + msg = "Destination address required"; + break; + + case WSAEMSGSIZE: + msg = "Message too long"; + break; + + case WSAEPROTOTYPE: + msg = "Protocol wrong type for socket"; + break; + + case WSAENOPROTOOPT: + msg = "Bad protocol option"; + break; + + case WSAEPROTONOSUPPORT: + msg = "Protocol not supported"; + break; + + case WSAESOCKTNOSUPPORT: + msg = "Socket type not supported"; + break; + + case WSAEOPNOTSUPP: + msg = "Operation not supported on socket"; + break; + + case WSAEPFNOSUPPORT: + msg = "Protocol family not supported"; + break; + + case WSAEAFNOSUPPORT: + msg = "Address family not supported"; + break; + + case WSAEADDRINUSE: + msg = "Address already in use"; + break; + + case WSAEADDRNOTAVAIL: + msg = "Can't assign requested address"; + break; + + case WSAENETDOWN: + msg = "Network is down"; + break; + + case WSAENETUNREACH: + msg = "Network is unreachable"; + break; + + case WSAENETRESET: + msg = "Net connection reset"; + break; + + case WSAECONNABORTED: + msg = "Software caused connection abort"; + break; + + case WSAECONNRESET: + msg = "Connection reset by peer"; + break; + + case WSAENOBUFS: + msg = "No buffer space available"; + break; + + case WSAEISCONN: + msg = "Socket is already connected"; + break; + + case WSAENOTCONN: + msg = "Socket is not connected"; + break; + + case WSAESHUTDOWN: + msg = "Can't send after socket shutdown"; + break; + + case WSAETOOMANYREFS: + msg = "Too many references: can't splice"; + break; + + case WSAETIMEDOUT: + msg = "Connection timed out"; + break; + + case WSAECONNREFUSED: + msg = "Connection refused"; + break; + + case WSAELOOP: + msg = "Too many levels of symbolic links"; + break; + + case WSAENAMETOOLONG: + msg = "File name too long"; + break; + + case WSAEHOSTDOWN: + msg = "Host is down"; + break; + + case WSAEHOSTUNREACH: + msg = "No route to host"; + break; + + case WSAENOTEMPTY: + msg = "Directory not empty"; + break; + + case WSAEPROCLIM: + msg = "Too many processes"; + break; + + case WSAEUSERS: + msg = "Too many users"; + break; + + case WSAEDQUOT: + msg = "Disc quota exceeded"; + break; + + case WSAESTALE: + msg = "Stale NFS file handle"; + break; + + case WSAEREMOTE: + msg = "Too many levels of remote in path"; + break; + + case WSASYSNOTREADY: + msg = "Network system is unavailable"; + break; + + case WSAVERNOTSUPPORTED: + msg = "Winsock version out of range"; + break; + + case WSANOTINITIALISED: + msg = "WSAStartup not yet called"; + break; + + case WSAEDISCON: + msg = "Graceful shutdown in progress"; + break; +/* + case WSAHOST_NOT_FOUND: + msg = "Host not found"; + break; + + case WSANO_DATA: + msg = "No host data of that type was found"; + break; +*/ + default: + msg = NULL; + break; + } + return (msg); +} + +/* + * These error messages are more informative about CryptAPI Errors than the + * standard error messages + */ + +char * +GetCryptErrorMessage(int errval) { + char *msg; + + switch (errval) { + + case NTE_BAD_FLAGS: + msg = "The dwFlags parameter has an illegal value."; + break; + case NTE_BAD_KEYSET: + msg = "The Registry entry for the key container " + "could not be opened and may not exist."; + break; + case NTE_BAD_KEYSET_PARAM: + msg = "The pszContainer or pszProvider parameter " + "is set to an illegal value."; + break; + case NTE_BAD_PROV_TYPE: + msg = "The value of the dwProvType parameter is out " + "of range. All provider types must be from " + "1 to 999, inclusive."; + break; + case NTE_BAD_SIGNATURE: + msg = "The provider DLL signature did not verify " + "correctly. Either the DLL or the digital " + "signature has been tampered with."; + break; + case NTE_EXISTS: + msg = "The dwFlags parameter is CRYPT_NEWKEYSET, but the key" + " container already exists."; + break; + case NTE_KEYSET_ENTRY_BAD: + msg = "The Registry entry for the pszContainer key container " + "was found (in the HKEY_CURRENT_USER window), but is " + "corrupt. See the section System Administration for " + " etails about CryptoAPI's Registry usage."; + break; + case NTE_KEYSET_NOT_DEF: + msg = "No Registry entry exists in the HKEY_CURRENT_USER " + "window for the key container specified by " + "pszContainer."; + break; + case NTE_NO_MEMORY: + msg = "The CSP ran out of memory during the operation."; + break; + case NTE_PROV_DLL_NOT_FOUND: + msg = "The provider DLL file does not exist or is not on the " + "current path."; + break; + case NTE_PROV_TYPE_ENTRY_BAD: + msg = "The Registry entry for the provider type specified by " + "dwProvType is corrupt. This error may relate to " + "either the user default CSP list or the machine " + "default CSP list. See the section System " + "Administration for details about CryptoAPI's " + "Registry usage."; + break; + case NTE_PROV_TYPE_NO_MATCH: + msg = "The provider type specified by dwProvType does not " + "match the provider type found in the Registry. Note " + "that this error can only occur when pszProvider " + "specifies an actual CSP name."; + break; + case NTE_PROV_TYPE_NOT_DEF: + msg = "No Registry entry exists for the provider type " + "specified by dwProvType."; + break; + case NTE_PROVIDER_DLL_FAIL: + msg = "The provider DLL file could not be loaded, and " + "may not exist. If it exists, then the file is " + "not a valid DLL."; + break; + case NTE_SIGNATURE_FILE_BAD: + msg = "An error occurred while loading the DLL file image, " + "prior to verifying its signature."; + break; + + default: + msg = NULL; + break; + } + return msg; +} + diff --git a/lib/isc/win32/win32os.c b/lib/isc/win32/win32os.c new file mode 100644 index 00000000..45b3c6ca --- /dev/null +++ b/lib/isc/win32/win32os.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: win32os.c,v 1.2.176.2 2003/07/22 04:03:51 marka Exp $ */ + +#include <windows.h> + +#include <isc/win32os.h> + +static BOOL bInit = FALSE; +static OSVERSIONINFOEX osVer; + +static void +initialize_action(void) { + BOOL bSuccess; + + if (bInit) + return; + /* + * NOTE: VC++ 6.0 gets this function declaration wrong + * so we compensate by casting the argument + */ + osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + bSuccess = GetVersionEx((OSVERSIONINFO *) &osVer); + + /* + * Versions of NT before NT4.0 SP6 did not return the + * extra info that the EX structure provides and returns + * a failure so we need to retry with the old structure. + */ + if(!bSuccess) { + osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + bSuccess = GetVersionEx((OSVERSIONINFO *) &osVer); + } + bInit = TRUE; +} + +unsigned int +isc_win32os_majorversion(void) { + initialize_action(); + return ((unsigned int)osVer.dwMajorVersion); +} + +unsigned int +isc_win32os_minorversion(void) { + initialize_action(); + return ((unsigned int)osVer.dwMinorVersion); +} + +unsigned int +isc_win32os_servicepackmajor(void) { + initialize_action(); + return ((unsigned int)osVer.wServicePackMajor); +} + +unsigned int +isc_win32os_servicepackminor(void) { + initialize_action(); + return ((unsigned int)osVer.wServicePackMinor); +} + +int +isc_win32os_versioncheck(unsigned int major, unsigned int minor, + unsigned int spmajor, unsigned int spminor) { + + initialize_action(); + + if (major < isc_win32os_majorversion()) + return (1); + if (major > isc_win32os_majorversion()) + return (-1); + if (minor < isc_win32os_minorversion()) + return (1); + if (minor > isc_win32os_minorversion()) + return (-1); + if (spmajor < isc_win32os_servicepackmajor()) + return (1); + if (spmajor > isc_win32os_servicepackmajor()) + return (-1); + if (spminor < isc_win32os_servicepackminor()) + return (1); + if (spminor > isc_win32os_servicepackminor()) + return (-1); + + /* Exact */ + return (0); +}
\ No newline at end of file |