diff options
Diffstat (limited to 'usr.sbin/bind/lib/isc')
39 files changed, 2647 insertions, 1143 deletions
diff --git a/usr.sbin/bind/lib/isc/Makefile.in b/usr.sbin/bind/lib/isc/Makefile.in index 9d48c91b6da..88478f6e177 100644 --- a/usr.sbin/bind/lib/isc/Makefile.in +++ b/usr.sbin/bind/lib/isc/Makefile.in @@ -1,7 +1,7 @@ -# Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2003 Internet Software Consortium. # -# Permission to use, copy, modify, and distribute this software for any +# Permission to use, copy, modify, and/or 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. # @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $ISC: Makefile.in,v 1.71.2.2.2.8 2004/07/20 07:01:58 marka Exp $ +# $ISC: Makefile.in,v 1.81.18.8 2007/09/14 23:46:18 tbox Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -25,6 +25,7 @@ top_srcdir = @top_srcdir@ CINCLUDES = -I${srcdir}/unix/include \ -I${srcdir}/@ISC_THREAD_DIR@/include \ + -I${srcdir}/@ISC_ARCH_DIR@/include \ -I./include \ -I${srcdir}/include CDEFINES = @@ -53,30 +54,32 @@ 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@ \ - hash.@O@ heap.@O@ hex.@O@ hmacmd5.@O@ \ - lcg.@O@ lex.@O@ lfsr.@O@ lib.@O@ log.@O@ md5.@O@ \ + lcg.@O@ \ + hash.@O@ heap.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@\ + lex.@O@ lfsr.@O@ lib.@O@ log.@O@ md5.@O@ \ mem.@O@ mutexblock.@O@ netaddr.@O@ netscope.@O@ ondestroy.@O@ \ parseint.@O@ quota.@O@ random.@O@ \ - ratelimiter.@O@ region.@O@ result.@O@ rwlock.@O@ \ - serial.@O@ sha1.@O@ sockaddr.@O@ string.@O@ strtoul.@O@ \ - symtab.@O@ task.@O@ taskpool.@O@ timer.@O@ version.@O@ \ - ${UNIXOBJS} ${NLSOBJS} ${THREADOBJS} + ratelimiter.@O@ refcount.@O@ region.@O@ result.@O@ rwlock.@O@ \ + serial.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ string.@O@ \ + strtoul.@O@ symtab.@O@ task.@O@ taskpool.@O@ timer.@O@ \ + version.@O@ ${UNIXOBJS} ${NLSOBJS} ${THREADOBJS} # Alphabetically SRCS = @ISC_EXTRA_SRCS@ \ assertions.c base64.c bitstring.c buffer.c \ bufferlist.c commandline.c error.c event.c \ - heap.c hex.c hmacmd5.c \ - lcg.c lex.c lfsr.c lib.c log.c \ + lcg.c \ + heap.c hex.c hmacmd5.c hmacsha.c \ + lex.c lfsr.c lib.c log.c \ md5.c mem.c mutexblock.c netaddr.c netscope.c ondestroy.c \ parseint.c quota.c random.c \ - ratelimiter.c result.c rwlock.c \ - serial.c sha1.c sockaddr.c string.c strtoul.c symtab.c \ + ratelimiter.c refcount.c region.c result.c rwlock.c \ + serial.c sha1.c sha2.c sockaddr.c string.c strtoul.c symtab.c \ task.c taskpool.c timer.c version.c LIBS = @LIBS@ -SUBDIRS = include unix nls @ISC_THREAD_DIR@ +SUBDIRS = include unix nls @ISC_THREAD_DIR@ @ISC_ARCH_DIR@ TARGETS = timestamp @BIND9_MAKE_RULES@ diff --git a/usr.sbin/bind/lib/isc/api b/usr.sbin/bind/lib/isc/api index b4d017358ad..ecadc93c94f 100644 --- a/usr.sbin/bind/lib/isc/api +++ b/usr.sbin/bind/lib/isc/api @@ -1,3 +1,3 @@ -LIBINTERFACE = 12 -LIBREVISION = 1 -LIBAGE = 1 +LIBINTERFACE = 32 +LIBREVISION = 5 +LIBAGE = 0 diff --git a/usr.sbin/bind/lib/isc/base64.c b/usr.sbin/bind/lib/isc/base64.c index 444e2c2e293..b717565822f 100644 --- a/usr.sbin/bind/lib/isc/base64.c +++ b/usr.sbin/bind/lib/isc/base64.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,9 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: base64.c,v 1.23.2.2.2.3 2004/03/06 08:14:27 marka Exp $ */ +/* $ISC: base64.c,v 1.28.18.2 2005/04/29 00:16:44 marka Exp $ */ + +/*! \file */ #include <config.h> @@ -32,7 +34,8 @@ } while (0) -/* +/*@{*/ +/*! * These static functions are also present in lib/dns/rdata.c. I'm not * sure where they should go. -- bwelling */ @@ -44,6 +47,7 @@ mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length); static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; +/*@}*/ isc_result_t isc_base64_totext(isc_region_t *source, int wordlength, @@ -90,14 +94,14 @@ isc_base64_totext(isc_region_t *source, int wordlength, return (ISC_R_SUCCESS); } -/* +/*% * State of a base64 decoding process in progress. */ typedef struct { - int length; /* Desired length of binary data or -1 */ - isc_buffer_t *target; /* Buffer for resulting binary data */ - int digits; /* Number of buffered base64 digits */ - isc_boolean_t seen_end; /* True if "=" end marker seen */ + int length; /*%< Desired length of binary data or -1 */ + isc_buffer_t *target; /*%< Buffer for resulting binary data */ + int digits; /*%< Number of buffered base64 digits */ + isc_boolean_t seen_end; /*%< True if "=" end marker seen */ int val[4]; } base64_decode_ctx_t; diff --git a/usr.sbin/bind/lib/isc/commandline.c b/usr.sbin/bind/lib/isc/commandline.c index 4bb46e52547..57c4eb8f9cd 100644 --- a/usr.sbin/bind/lib/isc/commandline.c +++ b/usr.sbin/bind/lib/isc/commandline.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -48,9 +48,9 @@ * SUCH DAMAGE. */ -/* $ISC: commandline.c,v 1.15.206.1 2004/03/06 08:14:28 marka Exp $ */ +/* $ISC: commandline.c,v 1.16.18.2 2005/04/29 00:16:45 marka Exp $ */ -/* +/*! \file * This file was adapted from the NetBSD project's source tree, RCS ID: * NetBSD: getopt.c,v 1.15 1999/09/20 04:39:37 lukem Exp * @@ -59,8 +59,8 @@ */ /* - * Principal Authors: Computer Systems Research Group at UC Berkeley - * Principal ISC caretaker: DCL + * \author Principal Authors: Computer Systems Research Group at UC Berkeley + * \author Principal ISC caretaker: DCL */ #include <config.h> @@ -72,17 +72,17 @@ #include <isc/string.h> #include <isc/util.h> -/* Index into parent argv vector. */ +/*% Index into parent argv vector. */ LIBISC_EXTERNAL_DATA int isc_commandline_index = 1; -/* Character checked for validity. */ +/*% Character checked for validity. */ LIBISC_EXTERNAL_DATA int isc_commandline_option; -/* Argument associated with option. */ +/*% Argument associated with option. */ LIBISC_EXTERNAL_DATA char *isc_commandline_argument; -/* For printing error messages. */ +/*% For printing error messages. */ LIBISC_EXTERNAL_DATA char *isc_commandline_progname; -/* Print error messages. */ +/*% Print error messages. */ LIBISC_EXTERNAL_DATA isc_boolean_t isc_commandline_errprint = ISC_TRUE; -/* Reset processing. */ +/*% Reset processing. */ LIBISC_EXTERNAL_DATA isc_boolean_t isc_commandline_reset = ISC_TRUE; static char endopt = '\0'; @@ -91,7 +91,7 @@ static char endopt = '\0'; #define BADARG ':' #define ENDOPT &endopt -/* +/*! * getopt -- * Parse argc/argv argument vector. */ diff --git a/usr.sbin/bind/lib/isc/entropy.c b/usr.sbin/bind/lib/isc/entropy.c index 41ba03a8904..b4c0afd839d 100644 --- a/usr.sbin/bind/lib/isc/entropy.c +++ b/usr.sbin/bind/lib/isc/entropy.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,12 +15,16 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: entropy.c,v 1.3.2.2.2.7 2004/03/08 09:04:48 marka Exp $ */ +/* $ISC: entropy.c,v 1.11.18.3 2005/07/12 01:22:28 marka Exp $ */ -/* +/*! \file + * \brief * This is the system independent part of the entropy module. It is * compiled via inclusion from the relevant OS source file, ie, - * unix/entropy.c or win32/entropy.c. + * \link unix/entropy.c unix/entropy.c \endlink or win32/entropy.c. + * + * \author Much of this code is modeled after the NetBSD /dev/random implementation, + * written by Michael Graff <explorer@netbsd.org>. */ #include <errno.h> @@ -42,10 +46,6 @@ #include <isc/time.h> #include <isc/util.h> -/* - * Much of this code is modeled after the NetBSD /dev/random implementation, - * written by Michael Graff <explorer@netbsd.org>. - */ #define ENTROPY_MAGIC ISC_MAGIC('E', 'n', 't', 'e') #define SOURCE_MAGIC ISC_MAGIC('E', 'n', 't', 's') @@ -58,26 +58,28 @@ *** you are doing. ***/ -/* - * size of entropy pool in 32-bit words. This _MUST_ be a power of 2. +/*% + * Size of entropy pool in 32-bit words. This _MUST_ be a power of 2. */ #define RND_POOLWORDS 128 +/*% Pool in bytes. */ #define RND_POOLBYTES (RND_POOLWORDS * 4) +/*% Pool in bits. */ #define RND_POOLBITS (RND_POOLWORDS * 32) -/* +/*% * Number of bytes returned per hash. This must be true: * threshold * 2 <= digest_size_in_bytes */ #define RND_ENTROPY_THRESHOLD 10 #define THRESHOLD_BITS (RND_ENTROPY_THRESHOLD * 8) -/* +/*% * Size of the input event queue in samples. */ #define RND_EVENTQSIZE 32 -/* +/*% * The number of times we'll "reseed" for pseudorandom seeds. This is an * extremely weak pseudorandom seed. If the caller is using lots of * pseudorandom data and they cannot provide a stronger random source, @@ -86,12 +88,13 @@ */ #define RND_INITIALIZE 128 +/*% Entropy Pool */ typedef struct { - isc_uint32_t cursor; /* current add point in the pool */ - isc_uint32_t entropy; /* current entropy estimate in bits */ - isc_uint32_t pseudo; /* bits extracted in pseudorandom */ - isc_uint32_t rotate; /* how many bits to rotate by */ - isc_uint32_t pool[RND_POOLWORDS]; /* random pool data */ + isc_uint32_t cursor; /*%< current add point in the pool */ + isc_uint32_t entropy; /*%< current entropy estimate in bits */ + isc_uint32_t pseudo; /*%< bits extracted in pseudorandom */ + isc_uint32_t rotate; /*%< how many bits to rotate by */ + isc_uint32_t pool[RND_POOLWORDS]; /*%< random pool data */ } isc_entropypool_t; struct isc_entropy { @@ -107,13 +110,14 @@ struct isc_entropy { ISC_LIST(isc_entropysource_t) sources; }; +/*% Sample Queue */ typedef struct { - isc_uint32_t last_time; /* last time recorded */ - isc_uint32_t last_delta; /* last delta value */ - isc_uint32_t last_delta2; /* last delta2 value */ - isc_uint32_t nsamples; /* number of samples filled in */ - isc_uint32_t *samples; /* the samples */ - isc_uint32_t *extra; /* extra samples added in */ + isc_uint32_t last_time; /*%< last time recorded */ + isc_uint32_t last_delta; /*%< last delta value */ + isc_uint32_t last_delta2; /*%< last delta2 value */ + isc_uint32_t nsamples; /*%< number of samples filled in */ + isc_uint32_t *samples; /*%< the samples */ + isc_uint32_t *extra; /*%< extra samples added in */ } sample_queue_t; typedef struct { @@ -137,7 +141,7 @@ struct isc_entropysource { unsigned int magic; unsigned int type; isc_entropy_t *ent; - isc_uint32_t total; /* entropy from this source */ + isc_uint32_t total; /*%< entropy from this source */ ISC_LINK(isc_entropysource_t) link; char name[32]; isc_boolean_t bad; @@ -151,12 +155,13 @@ struct isc_entropysource { } sources; }; -#define ENTROPY_SOURCETYPE_SAMPLE 1 /* Type is a sample source */ -#define ENTROPY_SOURCETYPE_FILE 2 /* Type is a file source */ -#define ENTROPY_SOURCETYPE_CALLBACK 3 /* Type is a callback source */ -#define ENTROPY_SOURCETYPE_USOCKET 4 /* Type is a Unix socket source */ +#define ENTROPY_SOURCETYPE_SAMPLE 1 /*%< Type is a sample source */ +#define ENTROPY_SOURCETYPE_FILE 2 /*%< Type is a file source */ +#define ENTROPY_SOURCETYPE_CALLBACK 3 /*%< Type is a callback source */ +#define ENTROPY_SOURCETYPE_USOCKET 4 /*%< Type is a Unix socket source */ -/* +/*@{*/ +/*% * The random pool "taps" */ #define TAP1 99 @@ -164,8 +169,10 @@ struct isc_entropysource { #define TAP3 31 #define TAP4 9 #define TAP5 7 +/*@}*/ -/* +/*@{*/ +/*% * Declarations for function provided by the system dependent sources that * include this file. */ @@ -181,6 +188,7 @@ destroyfilesource(isc_entropyfilesource_t *source); static void destroyusocketsource(isc_entropyusocketsource_t *source); +/*@}*/ static void samplequeue_release(isc_entropy_t *ent, sample_queue_t *sq) { @@ -211,7 +219,7 @@ samplesource_allocate(isc_entropy_t *ent, sample_queue_t *sq) { return (ISC_R_SUCCESS); } -/* +/*% * Add in entropy, even when the value we're adding in could be * very large. */ @@ -225,7 +233,7 @@ add_entropy(isc_entropy_t *ent, isc_uint32_t entropy) { ent->pool.entropy = ISC_MIN(entropy, RND_POOLBITS); } -/* +/*% * Decrement the amount of entropy the pool has. */ static inline void @@ -234,7 +242,7 @@ subtract_entropy(isc_entropy_t *ent, isc_uint32_t entropy) { ent->pool.entropy -= entropy; } -/* +/*! * Add in entropy, even when the value we're adding in could be * very large. */ @@ -248,7 +256,7 @@ add_pseudo(isc_entropy_t *ent, isc_uint32_t pseudo) { ent->pool.pseudo = ISC_MIN(pseudo, RND_POOLBITS * 8); } -/* +/*! * Decrement the amount of pseudo the pool has. */ static inline void @@ -257,7 +265,7 @@ subtract_pseudo(isc_entropy_t *ent, isc_uint32_t pseudo) { ent->pool.pseudo -= pseudo; } -/* +/*! * Add one word to the pool, rotating the input as needed. */ static inline void @@ -292,7 +300,7 @@ entropypool_add_word(isc_entropypool_t *rp, isc_uint32_t val) { } } -/* +/*! * Add a buffer's worth of data to the pool. * * Requires that the lock is held on the entropy pool. @@ -362,7 +370,7 @@ reseed(isc_entropy_t *ent) { entropypool_adddata(ent, &pid, sizeof(pid), 0); } - /* + /*! * After we've reseeded 100 times, only add new timing info every * 50 requests. This will keep us from using lots and lots of * CPU just to return bad pseudorandom data anyway. @@ -382,7 +390,7 @@ estimate_entropy(sample_queue_t *sq, isc_uint32_t t) { isc_int32_t delta2; isc_int32_t delta3; - /* + /*! * If the time counter has overflowed, calculate the real difference. * If it has not, it is simpler. */ @@ -661,7 +669,7 @@ isc_entropypool_invalidate(isc_entropypool_t *pool) { isc_result_t isc_entropy_create(isc_mem_t *mctx, isc_entropy_t **entp) { - isc_result_t ret; + isc_result_t result; isc_entropy_t *ent; REQUIRE(mctx != NULL); @@ -674,10 +682,9 @@ isc_entropy_create(isc_mem_t *mctx, isc_entropy_t **entp) { /* * We need a lock. */ - if (isc_mutex_init(&ent->lock) != ISC_R_SUCCESS) { - ret = ISC_R_UNEXPECTED; + result = isc_mutex_init(&ent->lock); + if (result != ISC_R_SUCCESS) goto errout; - } /* * From here down, no failures will/can occur. @@ -700,10 +707,10 @@ isc_entropy_create(isc_mem_t *mctx, isc_entropy_t **entp) { errout: isc_mem_put(mctx, ent, sizeof(isc_entropy_t)); - return (ret); + return (result); } -/* +/*! * Requires "ent" be locked. */ static void @@ -851,7 +858,7 @@ isc_entropy_createcallbacksource(isc_entropy_t *ent, void *arg, isc_entropysource_t **sourcep) { - isc_result_t ret; + isc_result_t result; isc_entropysource_t *source; isc_cbsource_t *cbs; @@ -863,15 +870,15 @@ isc_entropy_createcallbacksource(isc_entropy_t *ent, source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t)); if (source == NULL) { - ret = ISC_R_NOMEMORY; + result = ISC_R_NOMEMORY; goto errout; } source->bad = ISC_FALSE; cbs = &source->sources.callback; - ret = samplesource_allocate(ent, &cbs->samplequeue); - if (ret != ISC_R_SUCCESS) + result = samplesource_allocate(ent, &cbs->samplequeue); + if (result != ISC_R_SUCCESS) goto errout; cbs->start_called = ISC_FALSE; @@ -907,7 +914,7 @@ isc_entropy_createcallbacksource(isc_entropy_t *ent, UNLOCK(&ent->lock); - return (ret); + return (result); } void @@ -939,7 +946,7 @@ isc_result_t isc_entropy_createsamplesource(isc_entropy_t *ent, isc_entropysource_t **sourcep) { - isc_result_t ret; + isc_result_t result; isc_entropysource_t *source; sample_queue_t *sq; @@ -950,13 +957,13 @@ isc_entropy_createsamplesource(isc_entropy_t *ent, source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t)); if (source == NULL) { - ret = ISC_R_NOMEMORY; + result = ISC_R_NOMEMORY; goto errout; } sq = &source->sources.sample.samplequeue; - ret = samplesource_allocate(ent, sq); - if (ret != ISC_R_SUCCESS) + result = samplesource_allocate(ent, sq); + if (result != ISC_R_SUCCESS) goto errout; /* @@ -986,10 +993,10 @@ isc_entropy_createsamplesource(isc_entropy_t *ent, UNLOCK(&ent->lock); - return (ret); + return (result); } -/* +/*! * Add a sample, and return ISC_R_SUCCESS if the queue has become full, * ISC_R_NOENTROPY if it has space remaining, and ISC_R_NOMORE if the * queue was full when this function was called. diff --git a/usr.sbin/bind/lib/isc/hash.c b/usr.sbin/bind/lib/isc/hash.c index e3e624b1246..e4603dcbeee 100644 --- a/usr.sbin/bind/lib/isc/hash.c +++ b/usr.sbin/bind/lib/isc/hash.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,14 +15,12 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: hash.c,v 1.2.2.4.2.3 2006/01/04 00:37:22 marka Exp $ */ +/* $ISC: hash.c,v 1.6.18.5 2006/01/04 00:37:23 marka Exp $ */ -/* +/*! \file * Some portion of this code was derived from universal hash function * libraries of Rice University. - */ - -/* "UH Universal Hashing Library" +\section license UH Universal Hashing Library Copyright ((c)) 2002, Rice University All rights reserved. @@ -74,28 +72,31 @@ if advised of the possibility of such damage. #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; +/*@}*/ +/*% isc hash structure */ 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 */ + 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_mutex_t createlock; @@ -141,7 +142,7 @@ 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_result_t result; isc_hash_t *hctx; size_t vlen; hash_random_t *rv; @@ -167,17 +168,16 @@ isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy, vlen = sizeof(hash_random_t) * (limit + 1); rv = isc_mem_get(mctx, vlen); if (rv == NULL) { - ret = ISC_R_NOMEMORY; + result = ISC_R_NOMEMORY; goto errout; } /* * We need a lock. */ - if (isc_mutex_init(&hctx->lock) != ISC_R_SUCCESS) { - ret = ISC_R_UNEXPECTED; + result = isc_mutex_init(&hctx->lock); + if (result != ISC_R_SUCCESS) goto errout; - } /* * From here down, no failures will/can occur. @@ -186,7 +186,9 @@ isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy, hctx->mctx = NULL; isc_mem_attach(mctx, &hctx->mctx); hctx->initialized = ISC_FALSE; - isc_refcount_init(&hctx->refcnt, 1); + result = isc_refcount_init(&hctx->refcnt, 1); + if (result != ISC_R_SUCCESS) + goto cleanup_lock; hctx->entropy = NULL; hctx->limit = limit; hctx->vectorlen = vlen; @@ -198,12 +200,14 @@ isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy, *hctxp = hctx; return (ISC_R_SUCCESS); + cleanup_lock: + DESTROYLOCK(&hctx->lock); errout: isc_mem_put(mctx, hctx, sizeof(isc_hash_t)); if (rv != NULL) isc_mem_put(mctx, rv, vlen); - return (ret); + return (result); } static void diff --git a/usr.sbin/bind/lib/isc/include/isc/Makefile.in b/usr.sbin/bind/lib/isc/include/isc/Makefile.in index b3e0ed58f70..10e8e916ee7 100644 --- a/usr.sbin/bind/lib/isc/include/isc/Makefile.in +++ b/usr.sbin/bind/lib/isc/include/isc/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2001, 2003 Internet Software Consortium. # # Permission to use, copy, modify, and distribute this software for any @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $ISC: Makefile.in,v 1.50.12.6 2005/03/22 02:32:07 marka Exp $ +# $ISC: Makefile.in,v 1.54.18.4 2006/01/27 23:57:45 marka Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -35,9 +35,9 @@ HEADERS = app.h assertions.h base64.h bitstring.h boolean.h buffer.h \ mutexblock.h netaddr.h ondestroy.h os.h parseint.h \ print.h quota.h random.h ratelimiter.h \ refcount.h region.h resource.h \ - result.h resultclass.h rwlock.h serial.h sha1.h sockaddr.h \ - socket.h stdio.h stdlib.h string.h symtab.h task.h taskpool.h \ - timer.h types.h util.h version.h + result.h resultclass.h rwlock.h serial.h sha1.h sha2.h \ + sockaddr.h socket.h stdio.h stdlib.h string.h symtab.h \ + task.h taskpool.h timer.h types.h util.h version.h SUBDIRS = TARGETS = diff --git a/usr.sbin/bind/lib/isc/include/isc/hash.h b/usr.sbin/bind/lib/isc/include/isc/hash.h index c6a69aaf5d2..77fb0f16aae 100644 --- a/usr.sbin/bind/lib/isc/include/isc/hash.h +++ b/usr.sbin/bind/lib/isc/include/isc/hash.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: hash.h,v 1.2.2.1.2.2 2004/03/06 08:14:41 marka Exp $ */ +/* $ISC: hash.h,v 1.4.18.2 2005/04/29 00:16:55 marka Exp $ */ #ifndef ISC_HASH_H #define ISC_HASH_H 1 @@ -24,12 +24,10 @@ ***** Module Info *****/ -/* - * Hash - * - * The hash API +/*! \file * - * Provides an unpredictable hash value for variable length data. + * \brief 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. * @@ -48,27 +46,27 @@ * 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: + * \li 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: + * \li 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: + * \li Resources: * A buffer, used as a random vector for calculating hash values. * - * Security: + * \li 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: + * \li Standards: * None. */ @@ -88,10 +86,11 @@ 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. +/*!< + * \brief 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. * @@ -105,15 +104,16 @@ isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit); void isc_hash_ctxattach(isc_hash_t *hctx, isc_hash_t **hctxp); -/* - * Attach to a hash object. +/*!< + * \brief 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. +/*!< + * \brief Detach from a hash object. * * This function is for the multiple-context mode, and takes a valid * hash object as an argument. @@ -121,19 +121,23 @@ isc_hash_ctxdetach(isc_hash_t **hctxp); void isc_hash_destroy(void); -/* - * This function is for the single-context mode, and is expected to be used +/*!< + * \brief 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 +/*!< + * \brief 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. @@ -142,26 +146,31 @@ isc_hash_init(void); * * 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. +/*!< + * \brief 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. * @@ -169,6 +178,7 @@ isc_hash_calc(const unsigned char *key, unsigned int keylen, * case_sensitive values. It should typically be ISC_FALSE if the hash key * is a DNS name. */ +/*@}*/ ISC_LANG_ENDDECLS diff --git a/usr.sbin/bind/lib/isc/include/isc/log.h b/usr.sbin/bind/lib/isc/include/isc/log.h index 9c2df1b9eb5..6873f9c605e 100644 --- a/usr.sbin/bind/lib/isc/include/isc/log.h +++ b/usr.sbin/bind/lib/isc/include/isc/log.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,11 +15,13 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: log.h,v 1.39.2.4.2.7 2004/04/10 04:31:40 marka Exp $ */ +/* $ISC: log.h,v 1.47.18.3 2005/04/29 00:16:58 marka Exp $ */ #ifndef ISC_LOG_H #define ISC_LOG_H 1 +/*! \file */ + #include <stdio.h> #include <stdarg.h> #include <syslog.h> /* XXXDCL NT */ @@ -29,29 +31,36 @@ #include <isc/platform.h> #include <isc/types.h> -/* - * Severity levels, patterned after Unix's syslog levels. +/*@{*/ +/*! + * \brief Severity levels, patterned after Unix's syslog levels. * - * ISC_LOG_DYNAMIC can only be used for defining channels with - * isc_log_createchannel(), not to specify a level in isc_log_write(). */ #define ISC_LOG_DEBUG(level) (level) +/*! + * #ISC_LOG_DYNAMIC can only be used for defining channels with + * isc_log_createchannel(), not to specify a level in isc_log_write(). + */ #define ISC_LOG_DYNAMIC 0 #define ISC_LOG_INFO (-1) #define ISC_LOG_NOTICE (-2) #define ISC_LOG_WARNING (-3) #define ISC_LOG_ERROR (-4) #define ISC_LOG_CRITICAL (-5) +/*@}*/ -/* - * Destinations. +/*@{*/ +/*! + * \brief Destinations. */ #define ISC_LOG_TONULL 1 #define ISC_LOG_TOSYSLOG 2 #define ISC_LOG_TOFILE 3 #define ISC_LOG_TOFILEDESC 4 +/*@}*/ -/* +/*@{*/ +/*% * Channel flags. */ #define ISC_LOG_PRINTTIME 0x0001 @@ -62,18 +71,24 @@ #define ISC_LOG_PRINTALL 0x001F #define ISC_LOG_DEBUGONLY 0x1000 #define ISC_LOG_OPENERR 0x8000 /* internal */ +/*@}*/ -/* - * Other options. +/*@{*/ +/*! + * \brief Other options. + * * XXXDCL INFINITE doesn't yet work. Arguably it isn't needed, but * since I am intend to make large number of versions work efficiently, * INFINITE is going to be trivial to add to that. */ #define ISC_LOG_ROLLINFINITE (-1) #define ISC_LOG_ROLLNEVER (-2) +/*@}*/ -/* - * Used to name the categories used by a library. An array of isc_logcategory +/*! + * \brief Used to name the categories used by a library. + * + * An array of isc_logcategory * structures names each category, and the id value is initialized by calling * isc_log_registercategories. */ @@ -82,28 +97,30 @@ struct isc_logcategory { unsigned int id; }; -/* - * Similar to isc_logcategory above, but for all the modules a library defines. +/*% + * Similar to isc_logcategory, but for all the modules a library defines. */ struct isc_logmodule { const char *name; unsigned int id; }; -/* +/*% * The isc_logfile structure is initialized as part of an isc_logdestination - * before calling isc_log_createchannel(). When defining an ISC_LOG_TOFILE + * before calling isc_log_createchannel(). + * + * When defining an #ISC_LOG_TOFILE * channel the name, versions and maximum_size should be set before calling - * isc_log_createchannel(). To define an ISC_LOG_TOFILEDESC channel set only + * isc_log_createchannel(). To define an #ISC_LOG_TOFILEDESC channel set only * the stream before the call. * * Setting maximum_size to zero implies no maximum. */ typedef struct isc_logfile { - FILE *stream; /* Initialized to NULL for ISC_LOG_TOFILE. */ - const char *name; /* NULL for ISC_LOG_TOFILEDESC. */ - int versions; /* >= 0, ISC_LOG_ROLLNEVER, ISC_LOG_ROLLINFINITE. */ - /* + FILE *stream; /*%< Initialized to NULL for #ISC_LOG_TOFILE. */ + const char *name; /*%< NULL for #ISC_LOG_TOFILEDESC. */ + int versions; /* >= 0, #ISC_LOG_ROLLNEVER, #ISC_LOG_ROLLINFINITE. */ + /*% * stdio's ftell is standardized to return a long, which may well not * be big enough for the largest file supportable by the operating * system (though it is _probably_ big enough for the largest log @@ -111,10 +128,10 @@ typedef struct isc_logfile { * to a size large enough for the largest possible file on a system. */ isc_offset_t maximum_size; - isc_boolean_t maximum_reached; /* Private. */ + isc_boolean_t maximum_reached; /*%< Private. */ } isc_logfile_t; -/* +/*% * Passed to isc_log_createchannel to define the attributes of either * a stdio or a syslog log. */ @@ -123,7 +140,8 @@ typedef union isc_logdestination { int facility; /* XXXDCL NT */ } isc_logdestination_t; -/* +/*@{*/ +/*% * The built-in categories of libisc. * * Each library registering categories should provide library_LOGCATEGORY_name @@ -133,13 +151,16 @@ typedef union isc_logdestination { LIBISC_EXTERNAL_DATA extern isc_logcategory_t isc_categories[]; LIBISC_EXTERNAL_DATA extern isc_log_t *isc_lctx; LIBISC_EXTERNAL_DATA extern isc_logmodule_t isc_modules[]; +/*@}*/ -/* +/*@{*/ +/*% * Do not log directly to DEFAULT. Use another category. When in doubt, * use GENERAL. */ #define ISC_LOGCATEGORY_DEFAULT (&isc_categories[0]) #define ISC_LOGCATEGORY_GENERAL (&isc_categories[1]) +/*@}*/ #define ISC_LOGMODULE_SOCKET (&isc_modules[0]) #define ISC_LOGMODULE_TIME (&isc_modules[1]) @@ -150,33 +171,33 @@ ISC_LANG_BEGINDECLS isc_result_t isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp); -/* +/*%< * Establish a new logging context, with default channels. * * Notes: - * isc_log_create calls isc_logconfig_create, so see its comment + *\li isc_log_create() calls isc_logconfig_create(), so see its comment * below for more information. * * Requires: - * mctx is a valid memory context. - * lctxp is not null and *lctxp is null. - * lcfgp is null or lcfgp is not null and *lcfgp is null. + *\li mctx is a valid memory context. + *\li lctxp is not null and *lctxp is null. + *\li lcfgp is null or lcfgp is not null and *lcfgp is null. * * Ensures: - * *lctxp will point to a valid logging context if all of the necessary + *\li *lctxp will point to a valid logging context if all of the necessary * memory was allocated, or NULL otherwise. - * *lcfgp will point to a valid logging configuration if all of the + *\li *lcfgp will point to a valid logging configuration if all of the * necessary memory was allocated, or NULL otherwise. - * On failure, no additional memory is allocated. + *\li On failure, no additional memory is allocated. * * Returns: - * ISC_R_SUCCESS Success - * ISC_R_NOMEMORY Resource limit: Out of memory + *\li #ISC_R_SUCCESS Success + *\li #ISC_R_NOMEMORY Resource limit: Out of memory */ isc_result_t isc_logconfig_create(isc_log_t *lctx, isc_logconfig_t **lcfgp); -/* +/*%< * Create the data structure that holds all of the configurable information * about where messages are actually supposed to be sent -- the information * that could changed based on some configuration file, as opposed to the @@ -184,190 +205,192 @@ isc_logconfig_create(isc_log_t *lctx, isc_logconfig_t **lcfgp); * into a program, or the debug_level which is dynamic state information. * * Notes: - * It is necessary to specify the logging context the configuration + *\li It is necessary to specify the logging context the configuration * will be used with because the number of categories and modules * needs to be known in order to set the configuration. However, * the configuration is not used by the logging context until the * isc_logconfig_use function is called. * - * The memory context used for operations that allocate memory for + *\li The memory context used for operations that allocate memory for * the configuration is that of the logging context, as specified * in the isc_log_create call. * - * Four default channels are established: + *\li Four default channels are established: + *\verbatim * default_syslog - * - log to syslog's daemon facility ISC_LOG_INFO or higher + * - log to syslog's daemon facility #ISC_LOG_INFO or higher * default_stderr - * - log to stderr ISC_LOG_INFO or higher + * - log to stderr #ISC_LOG_INFO or higher * default_debug - * - log to stderr ISC_LOG_DEBUG dynamically + * - log to stderr #ISC_LOG_DEBUG dynamically * null * - log nothing + *\endverbatim * * Requires: - * lctx is a valid logging context. - * lcftp is not null and *lcfgp is null. + *\li lctx is a valid logging context. + *\li lcftp is not null and *lcfgp is null. * * Ensures: - * *lcfgp will point to a valid logging context if all of the necessary + *\li *lcfgp will point to a valid logging context if all of the necessary * memory was allocated, or NULL otherwise. - * On failure, no additional memory is allocated. + *\li On failure, no additional memory is allocated. * * Returns: - * ISC_R_SUCCESS Success - * ISC_R_NOMEMORY Resource limit: Out of memory + *\li #ISC_R_SUCCESS Success + *\li #ISC_R_NOMEMORY Resource limit: Out of memory */ isc_logconfig_t * isc_logconfig_get(isc_log_t *lctx); -/* +/*%< * Returns a pointer to the configuration currently in use by the log context. * * Requires: - * lctx is a valid context. + *\li lctx is a valid context. * * Ensures: - * The configuration pointer is non-null. + *\li The configuration pointer is non-null. * * Returns: - * The configuration pointer. + *\li The configuration pointer. */ isc_result_t isc_logconfig_use(isc_log_t *lctx, isc_logconfig_t *lcfg); -/* +/*%< * Associate a new configuration with a logging context. * * Notes: - * This is thread safe. The logging context will lock a mutex + *\li This is thread safe. The logging context will lock a mutex * before attempting to swap in the new configuration, and isc_log_doit * (the internal function used by all of isc_log_[v]write[1]) locks * the same lock for the duration of its use of the configuration. * * Requires: - * lctx is a valid logging context. - * lcfg is a valid logging configuration. - * lctx is the same configuration given to isc_logconfig_create + *\li lctx is a valid logging context. + *\li lcfg is a valid logging configuration. + *\li lctx is the same configuration given to isc_logconfig_create * when the configuration was created. * * Ensures: - * Future calls to isc_log_write will use the new configuration. + *\li Future calls to isc_log_write will use the new configuration. * * Returns: - * ISC_R_SUCCESS Success - * ISC_R_NOMEMORY Resource limit: Out of memory + *\li #ISC_R_SUCCESS Success + *\li #ISC_R_NOMEMORY Resource limit: Out of memory */ void isc_log_destroy(isc_log_t **lctxp); -/* +/*%< * Deallocate the memory associated with a logging context. * * Requires: - * *lctx is a valid logging context. + *\li *lctx is a valid logging context. * * Ensures: - * All of the memory associated with the logging context is returned + *\li All of the memory associated with the logging context is returned * to the free memory pool. * - * Any open files are closed. + *\li Any open files are closed. * - * The logging context is marked as invalid. + *\li The logging context is marked as invalid. */ void isc_logconfig_destroy(isc_logconfig_t **lcfgp); -/* +/*%< * Destroy a logging configuration. * * Notes: - * This function cannot be used directly with the return value of + *\li This function cannot be used directly with the return value of * isc_logconfig_get, because a logging context must always have * a valid configuration associated with it. * * Requires: - * lcfgp is not null and *lcfgp is a valid logging configuration. - * The logging configuration is not in use by an existing logging context. + *\li lcfgp is not null and *lcfgp is a valid logging configuration. + *\li The logging configuration is not in use by an existing logging context. * * Ensures: - * All memory allocated for the configuration is freed. + *\li All memory allocated for the configuration is freed. * - * The configuration is marked as invalid. + *\li The configuration is marked as invalid. */ void isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]); -/* +/*%< * Identify logging categories a library will use. * * Notes: - * A category should only be registered once, but no mechanism enforces + *\li A category should only be registered once, but no mechanism enforces * this rule. * - * The end of the categories array is identified by a NULL name. + *\li The end of the categories array is identified by a NULL name. * - * Because the name is used by ISC_LOG_PRINTCATEGORY, it should not + *\li Because the name is used by #ISC_LOG_PRINTCATEGORY, it should not * be altered or destroyed after isc_log_registercategories(). * - * Because each element of the categories array is used by + *\li Because each element of the categories array is used by * isc_log_categorybyname, it should not be altered or destroyed * after registration. * - * The value of the id integer in each structure is overwritten + *\li The value of the id integer in each structure is overwritten * by this function, and so id need not be initialized to any particular * value prior to the function call. * - * A subsequent call to isc_log_registercategories with the same + *\li A subsequent call to isc_log_registercategories with the same * logging context (but new categories) will cause the last * element of the categories array from the prior call to have * its "name" member changed from NULL to point to the new * categories array, and its "id" member set to UINT_MAX. * * Requires: - * lctx is a valid logging context. - * categories != NULL. - * categories[0].name != NULL. + *\li lctx is a valid logging context. + *\li categories != NULL. + *\li categories[0].name != NULL. * * Ensures: - * There are references to each category in the logging context, + * \li There are references to each category in the logging context, * so they can be used with isc_log_usechannel() and isc_log_write(). */ void isc_log_registermodules(isc_log_t *lctx, isc_logmodule_t modules[]); -/* +/*%< * Identify logging categories a library will use. * * Notes: - * A module should only be registered once, but no mechanism enforces + *\li A module should only be registered once, but no mechanism enforces * this rule. * - * The end of the modules array is identified by a NULL name. + *\li The end of the modules array is identified by a NULL name. * - * Because the name is used by ISC_LOG_PRINTMODULE, it should not + *\li Because the name is used by #ISC_LOG_PRINTMODULE, it should not * be altered or destroyed after isc_log_registermodules(). * - * Because each element of the modules array is used by + *\li Because each element of the modules array is used by * isc_log_modulebyname, it should not be altered or destroyed * after registration. * - * The value of the id integer in each structure is overwritten + *\li The value of the id integer in each structure is overwritten * by this function, and so id need not be initialized to any particular * value prior to the function call. * - * A subsequent call to isc_log_registermodules with the same + *\li A subsequent call to isc_log_registermodules with the same * logging context (but new modules) will cause the last * element of the modules array from the prior call to have * its "name" member changed from NULL to point to the new * modules array, and its "id" member set to UINT_MAX. * * Requires: - * lctx is a valid logging context. - * modules != NULL. - * modules[0].name != NULL; + *\li lctx is a valid logging context. + *\li modules != NULL. + *\li modules[0].name != NULL; * * Ensures: - * Each module has a reference in the logging context, so they can be + *\li Each module has a reference in the logging context, so they can be * used with isc_log_usechannel() and isc_log_write(). */ @@ -376,68 +399,67 @@ isc_log_createchannel(isc_logconfig_t *lcfg, const char *name, unsigned int type, int level, const isc_logdestination_t *destination, unsigned int flags); -/* +/*%< * Specify the parameters of a logging channel. * * Notes: - * The name argument is copied to memory in the logging context, so + *\li The name argument is copied to memory in the logging context, so * it can be altered or destroyed after isc_log_createchannel(). * - * Defining a very large number of channels will have a performance + *\li Defining a very large number of channels will have a performance * impact on isc_log_usechannel(), since the names are searched * linearly until a match is made. This same issue does not affect * isc_log_write, however. * - * Channel names can be redefined; this is primarily useful for programs + *\li Channel names can be redefined; this is primarily useful for programs * that want their own definition of default_syslog, default_debug * and default_stderr. * - * Any channel that is redefined will not affect logging that was + *\li Any channel that is redefined will not affect logging that was * already directed to its original definition, _except_ for the * default_stderr channel. This case is handled specially so that * the default logging category can be changed by redefining * default_stderr. (XXXDCL Though now that I think of it, the default * logging category can be changed with only one additional function * call by defining a new channel and then calling isc_log_usechannel() - * for ISC_LOGCATEGORY_DEFAULT.) + * for #ISC_LOGCATEGORY_DEFAULT.) * - * Specifying ISC_LOG_PRINTTIME or ISC_LOG_PRINTTAG for syslog is allowed, + *\li Specifying #ISC_LOG_PRINTTIME or #ISC_LOG_PRINTTAG for syslog is allowed, * but probably not what you wanted to do. * - * ISC_LOG_DEBUGONLY will mark the channel as usable only when the + * #ISC_LOG_DEBUGONLY will mark the channel as usable only when the * debug level of the logging context (see isc_log_setdebuglevel) * is non-zero. * * Requires: - * lcfg is a valid logging configuration. + *\li lcfg is a valid logging configuration. * - * name is not NULL. + *\li name is not NULL. * - * type is ISC_LOG_TOSYSLOG, ISC_LOG_TOFILE, ISC_LOG_TOFILEDESC or - * ISC_LOG_TONULL. + *\li type is #ISC_LOG_TOSYSLOG, #ISC_LOG_TOFILE, #ISC_LOG_TOFILEDESC or + * #ISC_LOG_TONULL. * - * destination is not NULL unless type is ISC_LOG_TONULL. + *\li destination is not NULL unless type is #ISC_LOG_TONULL. * - * level is >= ISC_LOG_CRITICAL (the most negative logging level). + *\li level is >= #ISC_LOG_CRITICAL (the most negative logging level). * - * flags does not include any bits aside from the ISC_LOG_PRINT* bits - * or ISC_LOG_DEBUGONLY. + *\li flags does not include any bits aside from the ISC_LOG_PRINT* bits + * or #ISC_LOG_DEBUGONLY. * * Ensures: - * ISC_R_SUCCESS + *\li #ISC_R_SUCCESS * A channel with the given name is usable with * isc_log_usechannel(). * - * ISC_R_NOMEMORY or ISC_R_UNEXPECTED + *\li #ISC_R_NOMEMORY or #ISC_R_UNEXPECTED * No additional memory is being used by the logging context. - * * Any channel that previously existed with the given name * is not redefined. * * Returns: - * ISC_R_SUCCESS Success - * ISC_R_NOMEMORY Resource limit: Out of memory - * ISC_R_UNEXPECTED type was out of range and REQUIRE() + *\li #ISC_R_SUCCESS Success + *\li #ISC_R_NOMEMORY Resource limit: Out of memory + *\li #ISC_R_UNEXPECTED type was out of range and REQUIRE() * was disabled. */ @@ -445,166 +467,186 @@ isc_result_t isc_log_usechannel(isc_logconfig_t *lcfg, const char *name, const isc_logcategory_t *category, const isc_logmodule_t *module); -/* +/*%< * Associate a named logging channel with a category and module that * will use it. * * Notes: - * The name is searched for linearly in the set of known channel names + *\li The name is searched for linearly in the set of known channel names * until a match is found. (Note the performance impact of a very large * number of named channels.) When multiple channels of the same * name are defined, the most recent definition is found. * - * Specifing a very large number of channels for a category will have + *\li Specifing a very large number of channels for a category will have * a moderate impact on performance in isc_log_write(), as each * call looks up the category for the start of a linked list, which * it follows all the way to the end to find matching modules. The * test for matching modules is integral, though. * - * If category is NULL, then the channel is associated with the indicated + *\li If category is NULL, then the channel is associated with the indicated * module for all known categories (including the "default" category). * - * If module is NULL, then the channel is associated with every module + *\li If module is NULL, then the channel is associated with every module * that uses that category. * - * Passing both category and module as NULL would make every log message + *\li Passing both category and module as NULL would make every log message * use the indicated channel. * - * Specifying a channel that is ISC_LOG_TONULL for a category/module pair + * \li Specifying a channel that is #ISC_LOG_TONULL for a category/module pair * has no effect on any other channels associated with that pair, * regardless of ordering. Thus you cannot use it to "mask out" one * category/module pair when you have specified some other channel that * is also used by that category/module pair. * * Requires: - * lcfg is a valid logging configuration. + *\li lcfg is a valid logging configuration. * - * category is NULL or has an id that is in the range of known ids. + *\li category is NULL or has an id that is in the range of known ids. * * module is NULL or has an id that is in the range of known ids. * * Ensures: - * ISC_R_SUCCESS + *\li #ISC_R_SUCCESS * The channel will be used by the indicated category/module * arguments. * - * ISC_R_NOMEMORY + *\li #ISC_R_NOMEMORY * If assignment for a specific category has been requested, * the channel has not been associated with the indicated * category/module arguments and no additional memory is * used by the logging context. - * * If assignment for all categories has been requested * then _some_ may have succeeded (starting with category * "default" and progressing through the order of categories - * passed to isc_log_registercategories) and additional memory + * passed to isc_log_registercategories()) and additional memory * is being used by whatever assignments succeeded. * * Returns: - * ISC_R_SUCCESS Success - * ISC_R_NOMEMORY Resource limit: Out of memory + *\li #ISC_R_SUCCESS Success + *\li #ISC_R_NOMEMORY Resource limit: Out of memory */ -void -isc_log_write(isc_log_t *lctx, isc_logcategory_t *category, - isc_logmodule_t *module, int level, - const char *format, ...) -ISC_FORMAT_PRINTF(5, 6); -/* +/* Attention: next four comments PRECEED code */ +/*! + * \brief * Write a message to the log channels. * * Notes: - * Log messages containing natural language text should be logged with + *\li Log messages containing natural language text should be logged with * isc_log_iwrite() to allow for localization. * - * lctx can be NULL; this is allowed so that programs which use + *\li lctx can be NULL; this is allowed so that programs which use * libraries that use the ISC logging system are not required to * also use it. * - * The format argument is a printf(3) string, with additional arguments + *\li The format argument is a printf(3) string, with additional arguments * as necessary. * * Requires: - * lctx is a valid logging context. + *\li lctx is a valid logging context. * - * The category and module arguments must have ids that are in the + *\li The category and module arguments must have ids that are in the * range of known ids, as estabished by isc_log_registercategories() * and isc_log_registermodules(). * - * level != ISC_LOG_DYNAMIC. ISC_LOG_DYNAMIC is used only to define + *\li level != #ISC_LOG_DYNAMIC. ISC_LOG_DYNAMIC is used only to define * channels, and explicit debugging level must be identified for * isc_log_write() via ISC_LOG_DEBUG(level). * - * format != NULL. + *\li format != NULL. * * Ensures: - * The log message is written to every channel associated with the + *\li The log message is written to every channel associated with the * indicated category/module pair. * * Returns: - * Nothing. Failure to log a message is not construed as a + *\li Nothing. Failure to log a message is not construed as a * meaningful error. */ - void -isc_log_vwrite(isc_log_t *lctx, isc_logcategory_t *category, +isc_log_write(isc_log_t *lctx, isc_logcategory_t *category, isc_logmodule_t *module, int level, - const char *format, va_list args) -ISC_FORMAT_PRINTF(5, 0); -/* + const char *format, ...) + +ISC_FORMAT_PRINTF(5, 6); + +/*% * Write a message to the log channels. * * Notes: - * lctx can be NULL; this is allowed so that programs which use + *\li lctx can be NULL; this is allowed so that programs which use * libraries that use the ISC logging system are not required to * also use it. * - * The format argument is a printf(3) string, with additional arguments + *\li The format argument is a printf(3) string, with additional arguments * as necessary. * * Requires: - * lctx is a valid logging context. + *\li lctx is a valid logging context. * - * The category and module arguments must have ids that are in the + *\li The category and module arguments must have ids that are in the * range of known ids, as estabished by isc_log_registercategories() * and isc_log_registermodules(). * - * level != ISC_LOG_DYNAMIC. ISC_LOG_DYNAMIC is used only to define + *\li level != #ISC_LOG_DYNAMIC. ISC_LOG_DYNAMIC is used only to define * channels, and explicit debugging level must be identified for * isc_log_write() via ISC_LOG_DEBUG(level). * - * format != NULL. + *\li format != NULL. * * Ensures: - * The log message is written to every channel associated with the + *\li The log message is written to every channel associated with the * indicated category/module pair. * * Returns: - * Nothing. Failure to log a message is not construed as a + *\li Nothing. Failure to log a message is not construed as a * meaningful error. */ +void +isc_log_vwrite(isc_log_t *lctx, isc_logcategory_t *category, + isc_logmodule_t *module, int level, + const char *format, va_list args) + +ISC_FORMAT_PRINTF(5, 0); +/*% + * Write a message to the log channels, pruning duplicates that occur within + * a configurable amount of seconds (see isc_log_[sg]etduplicateinterval). + * This function is otherwise identical to isc_log_write(). + */ void isc_log_write1(isc_log_t *lctx, isc_logcategory_t *category, isc_logmodule_t *module, int level, const char *format, ...) + ISC_FORMAT_PRINTF(5, 6); -/* + +/*% * Write a message to the log channels, pruning duplicates that occur within * a configurable amount of seconds (see isc_log_[sg]etduplicateinterval). - * This function is otherwise identical to isc_log_write(). + * This function is otherwise identical to isc_log_vwrite(). */ - void isc_log_vwrite1(isc_log_t *lctx, isc_logcategory_t *category, isc_logmodule_t *module, int level, const char *format, va_list args) + ISC_FORMAT_PRINTF(5, 0); -/* - * Write a message to the log channels, pruning duplicates that occur within - * a configurable amount of seconds (see isc_log_[sg]etduplicateinterval). - * This function is otherwise identical to isc_log_vwrite(). - */ +/*% + * These are four internationalized versions of the the isc_log_[v]write[1] + * functions. + * + * The only difference is that they take arguments for a message + * catalog, message set, and message number, all immediately preceding the + * format argument. The format argument becomes the default text, a la + * isc_msgcat_get. If the message catalog is NULL, no lookup is attempted + * for a message -- which makes the message set and message number irrelevant, + * and the non-internationalized call should have probably been used instead. + * + * Yes, that means there are now *eight* interfaces to logging a message. + * Sheesh. Make the madness stop! + */ +/*@{*/ void isc_log_iwrite(isc_log_t *lctx, isc_logcategory_t *category, isc_logmodule_t *module, int level, @@ -632,72 +674,61 @@ isc_log_ivwrite1(isc_log_t *lctx, isc_logcategory_t *category, isc_msgcat_t *msgcat, int msgset, int message, const char *format, va_list args) ISC_FORMAT_PRINTF(8, 0); -/* - * These are four internationalized versions of the the isc_log_[v]write[1] - * functions. The only difference is that they take arguments for a message - * catalog, message set, and message number, all immediately preceding the - * format argument. The format argument becomes the default text, a la - * isc_msgcat_get. If the message catalog is NULL, no lookup is attempted - * for a message -- which makes the message set and message number irrelevant, - * and the non-internationalized call should have probably been used instead. - * - * Yes, that means there are now *eight* interfaces to logging a message. - * Sheesh. Make the madness stop! - */ +/*@}*/ void isc_log_setdebuglevel(isc_log_t *lctx, unsigned int level); -/* +/*%< * Set the debugging level used for logging. * * Notes: - * Setting the debugging level to 0 disables debugging log messages. + *\li Setting the debugging level to 0 disables debugging log messages. * * Requires: - * lctx is a valid logging context. + *\li lctx is a valid logging context. * * Ensures: - * The debugging level is set to the requested value. + *\li The debugging level is set to the requested value. */ unsigned int isc_log_getdebuglevel(isc_log_t *lctx); -/* +/*%< * Get the current debugging level. * * Notes: - * This is provided so that a program can have a notion of + *\li This is provided so that a program can have a notion of * "increment debugging level" or "decrement debugging level" * without needing to keep track of what the current level is. * - * A return value of 0 indicates that debugging messages are disabled. + *\li A return value of 0 indicates that debugging messages are disabled. * * Requires: - * lctx is a valid logging context. + *\li lctx is a valid logging context. * * Ensures: - * The current logging debugging level is returned. + *\li The current logging debugging level is returned. */ isc_boolean_t isc_log_wouldlog(isc_log_t *lctx, int level); -/* +/*%< * Determine whether logging something to 'lctx' at 'level' would * actually cause something to be logged somewhere. * - * If ISC_FALSE is returned, it is guaranteed that nothing would + * If #ISC_FALSE is returned, it is guaranteed that nothing would * be logged, allowing the caller to omit unnecessary * isc_log_write() calls and possible message preformatting. */ void isc_log_setduplicateinterval(isc_logconfig_t *lcfg, unsigned int interval); -/* +/*%< * Set the interval over which duplicate log messages will be ignored * by isc_log_[v]write1(), in seconds. * * Notes: - * Increasing the duplicate interval from X to Y will not necessarily + *\li Increasing the duplicate interval from X to Y will not necessarily * filter out duplicates of messages logged in Y - X seconds since the * increase. (Example: Message1 is logged at midnight. Message2 * is logged at 00:01:00, when the interval is only 30 seconds, causing @@ -707,43 +738,43 @@ isc_log_setduplicateinterval(isc_logconfig_t *lcfg, unsigned int interval); * passed since the first occurrence. * * Requires: - * lctx is a valid logging context. + *\li lctx is a valid logging context. */ unsigned int isc_log_getduplicateinterval(isc_logconfig_t *lcfg); -/* +/*%< * Get the current duplicate filtering interval. * * Requires: - * lctx is a valid logging context. + *\li lctx is a valid logging context. * * Returns: - * The current duplicate filtering interval. + *\li The current duplicate filtering interval. */ isc_result_t isc_log_settag(isc_logconfig_t *lcfg, const char *tag); -/* - * Set the program name or other identifier for ISC_LOG_PRINTTAG. +/*%< + * Set the program name or other identifier for #ISC_LOG_PRINTTAG. * * Requires: - * lcfg is a valid logging configuration. + *\li lcfg is a valid logging configuration. * * Notes: - * If this function has not set the tag to a non-NULL, non-empty value, - * then the ISC_LOG_PRINTTAG channel flag will not print anything. + *\li If this function has not set the tag to a non-NULL, non-empty value, + * then the #ISC_LOG_PRINTTAG channel flag will not print anything. * Unlike some implementations of syslog on Unix systems, you *must* set * the tag in order to get it logged. It is not implicitly derived from * the program name (which is pretty impossible to infer portably). * - * Setting the tag to NULL or the empty string will also cause the - * ISC_LOG_PRINTTAG channel flag to not print anything. If tag equals the + *\li Setting the tag to NULL or the empty string will also cause the + * #ISC_LOG_PRINTTAG channel flag to not print anything. If tag equals the * empty string, calls to isc_log_gettag will return NULL. * * Returns: - * ISC_R_SUCCESS Success - * ISC_R_NOMEMORY Resource Limit: Out of memory + *\li #ISC_R_SUCCESS Success + *\li #ISC_R_NOMEMORY Resource Limit: Out of memory * * XXXDCL when creating a new isc_logconfig_t, it might be nice if the tag * of the currently active isc_logconfig_t was inherited. this does not @@ -752,33 +783,35 @@ isc_log_settag(isc_logconfig_t *lcfg, const char *tag); char * isc_log_gettag(isc_logconfig_t *lcfg); -/* - * Get the current identifier printed with ISC_LOG_PRINTTAG. +/*%< + * Get the current identifier printed with #ISC_LOG_PRINTTAG. * * Requires: - * lcfg is a valid logging configuration. + *\li lcfg is a valid logging configuration. * * Notes: - * Since isc_log_settag() will not associate a zero-length string + *\li Since isc_log_settag() will not associate a zero-length string * with the logging configuration, attempts to do so will cause * this function to return NULL. However, a determined programmer * will observe that (currently) a tag of length greater than zero * could be set, and then modified to be zero length. * * Returns: - * A pointer to the current identifier, or NULL if none has been set. + *\li A pointer to the current identifier, or NULL if none has been set. */ void isc_log_opensyslog(const char *tag, int options, int facility); -/* +/*%< * Initialize syslog logging. * * Notes: - * XXXDCL NT + *\li XXXDCL NT * This is currently equivalent to openlog(), but is not going to remain * that way. In the meantime, the arguments are all identical to * those used by openlog(3), as follows: + * + * \code * tag: The string to use in the position of the program * name in syslog messages. Most (all?) syslogs * will use basename(argv[0]) if tag is NULL. @@ -789,89 +822,90 @@ isc_log_opensyslog(const char *tag, int options, int facility); * facility: The default syslog facility. This is irrelevant * since isc_log_write will ALWAYS use the channel's * declared facility. + * \endcode * - * Zero effort has been made (yet) to accomodate systems with openlog() + *\li Zero effort has been made (yet) to accomodate systems with openlog() * that only takes two arguments, or to identify valid syslog * facilities or options for any given architecture. * - * It is necessary to call isc_log_opensyslog() to initialize + *\li It is necessary to call isc_log_opensyslog() to initialize * syslogging on machines which do not support network connections to * syslogd because they require a Unix domain socket to be used. Since * this is a chore to determine at run-time, it is suggested that it * always be called by programs using the ISC logging system. * * Requires: - * Nothing. + *\li Nothing. * * Ensures: - * openlog() is called to initialize the syslog system. + *\li openlog() is called to initialize the syslog system. */ void isc_log_closefilelogs(isc_log_t *lctx); -/* - * Close all open files used by ISC_LOG_TOFILE channels. +/*%< + * Close all open files used by #ISC_LOG_TOFILE channels. * * Notes: - * This function is provided for programs that want to use their own + *\li This function is provided for programs that want to use their own * log rolling mechanism rather than the one provided internally. * For example, a program that wanted to keep daily logs would define - * a channel which used ISC_LOG_ROLLNEVER, then once a day would + * a channel which used #ISC_LOG_ROLLNEVER, then once a day would * rename the log file and call isc_log_closefilelogs(). * - * ISC_LOG_TOFILEDESC channels are unaffected. + *\li #ISC_LOG_TOFILEDESC channels are unaffected. * * Requires: - * lctx is a valid context. + *\li lctx is a valid context. * * Ensures: - * The open files are closed and will be reopened when they are + *\li The open files are closed and will be reopened when they are * next needed. */ isc_logcategory_t * isc_log_categorybyname(isc_log_t *lctx, const char *name); -/* +/*%< * Find a category by its name. * * Notes: - * The string name of a category is not required to be unique. + *\li The string name of a category is not required to be unique. * * Requires: - * lctx is a valid context. - * name is not NULL. + *\li lctx is a valid context. + *\li name is not NULL. * * Returns: - * A pointer to the _first_ isc_logcategory_t structure used by "name". + *\li A pointer to the _first_ isc_logcategory_t structure used by "name". * - * NULL if no category exists by that name. + *\li NULL if no category exists by that name. */ isc_logmodule_t * isc_log_modulebyname(isc_log_t *lctx, const char *name); -/* +/*%< * Find a module by its name. * * Notes: - * The string name of a module is not required to be unique. + *\li The string name of a module is not required to be unique. * * Requires: - * lctx is a valid context. - * name is not NULL. + *\li lctx is a valid context. + *\li name is not NULL. * * Returns: - * A pointer to the _first_ isc_logmodule_t structure used by "name". + *\li A pointer to the _first_ isc_logmodule_t structure used by "name". * - * NULL if no module exists by that name. + *\li NULL if no module exists by that name. */ void isc_log_setcontext(isc_log_t *lctx); -/* +/*%< * Sets the context used by the libisc for logging. * * Requires: - * lctx be a valid context. + *\li lctx be a valid context. */ ISC_LANG_ENDDECLS diff --git a/usr.sbin/bind/lib/isc/include/isc/platform.h.in b/usr.sbin/bind/lib/isc/include/isc/platform.h.in index 2ebd5cb2636..125dfca86aa 100644 --- a/usr.sbin/bind/lib/isc/include/isc/platform.h.in +++ b/usr.sbin/bind/lib/isc/include/isc/platform.h.in @@ -1,8 +1,8 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * - * Permission to use, copy, modify, and distribute this software for any + * Permission to use, copy, modify, and/or 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. * @@ -15,208 +15,259 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: platform.h.in,v 1.24.2.1.10.11 2004/03/08 09:04:52 marka Exp $ */ +/* $ISC: platform.h.in,v 1.34.18.9 2007/09/13 05:04:01 each Exp $ */ #ifndef ISC_PLATFORM_H #define ISC_PLATFORM_H 1 +/*! \file */ + /***** ***** Platform-dependent defines. *****/ +/* + * Define if the platform has <strings.h>. + */ +@ISC_PLATFORM_HAVESTRINGSH@ + /*** *** Network. ***/ -/* +/*! \brief * Define if this system needs the <netinet/in6.h> header file included * for full IPv6 support (pretty much only UnixWare). */ @ISC_PLATFORM_NEEDNETINETIN6H@ -/* +/*! \brief * Define if this system needs the <netinet6/in6.h> header file included * to support in6_pkinfo (pretty much only BSD/OS). */ @ISC_PLATFORM_NEEDNETINET6IN6H@ -/* +/*! \brief * If sockaddrs on this system have an sa_len field, ISC_PLATFORM_HAVESALEN * will be defined. */ @ISC_PLATFORM_HAVESALEN@ -/* +/*! \brief * If this system has the IPv6 structure definitions, ISC_PLATFORM_HAVEIPV6 * will be defined. */ @ISC_PLATFORM_HAVEIPV6@ -/* +/*! \brief * If this system is missing in6addr_any, ISC_PLATFORM_NEEDIN6ADDRANY will * be defined. */ @ISC_PLATFORM_NEEDIN6ADDRANY@ -/* +/*! \brief * If this system is missing in6addr_loopback, ISC_PLATFORM_NEEDIN6ADDRLOOPBACK * will be defined. */ @ISC_PLATFORM_NEEDIN6ADDRLOOPBACK@ -/* +/*! \brief * If this system has in6_pktinfo, ISC_PLATFORM_HAVEIN6PKTINFO will be * defined. */ @ISC_PLATFORM_HAVEIN6PKTINFO@ -/* +/*! \brief * If this system has in_addr6, rather than in6_addr, ISC_PLATFORM_HAVEINADDR6 * will be defined. */ @ISC_PLATFORM_HAVEINADDR6@ -/* +/*! \brief * If this system has sin6_scope_id, ISC_PLATFORM_HAVESCOPEID will be defined. */ @ISC_PLATFORM_HAVESCOPEID@ -/* +/*! \brief * If this system needs inet_ntop(), ISC_PLATFORM_NEEDNTOP will be defined. */ @ISC_PLATFORM_NEEDNTOP@ -/* +/*! \brief * If this system needs inet_pton(), ISC_PLATFORM_NEEDPTON will be defined. */ @ISC_PLATFORM_NEEDPTON@ -/* +/*! \brief * If this system needs inet_aton(), ISC_PLATFORM_NEEDATON will be defined. */ @ISC_PLATFORM_NEEDATON@ -/* +/*! \brief * If this system needs in_port_t, ISC_PLATFORM_NEEDPORTT will be defined. */ @ISC_PLATFORM_NEEDPORTT@ -/* +/*! \brief * If the system needs strsep(), ISC_PLATFORM_NEEDSTRSEP will be defined. */ @ISC_PLATFORM_NEEDSTRSEP@ -/* +/*! \brief * If the system needs strlcpy(), ISC_PLATFORM_NEEDSTRLCPY will be defined. */ @ISC_PLATFORM_NEEDSTRLCPY@ -/* +/*! \brief * If the system needs strlcat(), ISC_PLATFORM_NEEDSTRLCAT will be defined. */ @ISC_PLATFORM_NEEDSTRLCAT@ -/* +/*! \brief * Define either ISC_PLATFORM_BSD44MSGHDR or ISC_PLATFORM_BSD43MSGHDR. */ @ISC_PLATFORM_MSGHDRFLAVOR@ -/* +/*! \brief * Define if PTHREAD_ONCE_INIT should be surrounded by braces to * prevent compiler warnings (such as with gcc on Solaris 2.8). */ @ISC_PLATFORM_BRACEPTHREADONCEINIT@ -/* +/*! \brief * Define on some UnixWare systems to fix erroneous definitions of various * IN6_IS_ADDR_* macros. */ @ISC_PLATFORM_FIXIN6ISADDR@ -/*** +/* *** Printing. ***/ -/* +/*! \brief * If this system needs vsnprintf() and snprintf(), ISC_PLATFORM_NEEDVSNPRINTF * will be defined. */ @ISC_PLATFORM_NEEDVSNPRINTF@ -/* +/*! \brief * If this system need a modern sprintf() that returns (int) not (char*). */ @ISC_PLATFORM_NEEDSPRINTF@ -/* +/*! \brief * The printf format string modifier to use with isc_uint64_t values. */ @ISC_PLATFORM_QUADFORMAT@ -/* +/*! \brief * Defined if we are using threads. */ @ISC_PLATFORM_USETHREADS@ -/* +/*! \brief * Defined if unistd.h does not cause fd_set to be delared. */ @ISC_PLATFORM_NEEDSYSSELECTH@ -/* +/*! \brief * Type used for resource limits. */ @ISC_PLATFORM_RLIMITTYPE@ -/* +/*! \brief * Define if your compiler supports "long long int". */ @ISC_PLATFORM_HAVELONGLONG@ -/* +/*! \brief * Define if the system has struct lifconf which is a extended struct ifconf * for IPv6. */ @ISC_PLATFORM_HAVELIFCONF@ -/* +/*! \brief * Define if the system has struct if_laddrconf which is a extended struct * ifconf for IPv6. */ @ISC_PLATFORM_HAVEIF_LADDRCONF@ -/* +/*! \brief * Define if the system has struct if_laddrreq. */ @ISC_PLATFORM_HAVEIF_LADDRREQ@ -/* +/*! \brief * Used to control how extern data is linked; needed for Win32 platforms. */ @ISC_PLATFORM_USEDECLSPEC@ -/* +/*! \brief * Define if the system supports if_nametoindex. */ @ISC_PLATFORM_HAVEIFNAMETOINDEX@ -/* +/*! \brief * Define if this system needs strtoul. */ @ISC_PLATFORM_NEEDSTRTOUL@ -/* +/*! \brief * Define if this system needs memmove. */ @ISC_PLATFORM_NEEDMEMMOVE@ +/* + * Define if the platform has <sys/un.h>. + */ +@ISC_PLATFORM_HAVESYSUNH@ + +/* + * If the "xadd" operation is available on this architecture, + * ISC_PLATFORM_HAVEXADD will be defined. + */ +@ISC_PLATFORM_HAVEXADD@ + +/* + * If the "atomic swap" operation is available on this architecture, + * ISC_PLATFORM_HAVEATOMICSTORE" will be defined. + */ +@ISC_PLATFORM_HAVEATOMICSTORE@ + +/* + * If the "compare-and-exchange" operation is available on this architecture, + * ISC_PLATFORM_HAVECMPXCHG will be defined. + */ +@ISC_PLATFORM_HAVECMPXCHG@ + +/* + * Define if gcc ASM extension is available + */ +@ISC_PLATFORM_USEGCCASM@ + +/* + * Define if Tru64 style ASM syntax must be used. + */ +@ISC_PLATFORM_USEOSFASM@ + +/* + * Define if the standard __asm function must be used. + */ +@ISC_PLATFORM_USESTDASM@ + +/* + * Define if MacOS style of PPC assembly must be used. + * e.g. "r6", not "6", for register six. + */ +@ISC_PLATFORM_USEMACASM@ + #ifndef ISC_PLATFORM_USEDECLSPEC #define LIBISC_EXTERNAL_DATA #define LIBDNS_EXTERNAL_DATA #define LIBISCCC_EXTERNAL_DATA #define LIBISCCFG_EXTERNAL_DATA #define LIBBIND9_EXTERNAL_DATA -#else /* ISC_PLATFORM_USEDECLSPEC */ +#else /*! \brief ISC_PLATFORM_USEDECLSPEC */ #ifdef LIBISC_EXPORTS #define LIBISC_EXTERNAL_DATA __declspec(dllexport) #else @@ -242,7 +293,7 @@ #else #define LIBBIND9_EXTERNAL_DATA __declspec(dllimport) #endif -#endif /* ISC_PLATFORM_USEDECLSPEC */ +#endif /*! \brief ISC_PLATFORM_USEDECLSPEC */ /* * Tell emacs to use C mode for this file. diff --git a/usr.sbin/bind/lib/isc/include/isc/refcount.h b/usr.sbin/bind/lib/isc/include/isc/refcount.h index 0e1ebf2e288..8dd87399762 100644 --- a/usr.sbin/bind/lib/isc/include/isc/refcount.h +++ b/usr.sbin/bind/lib/isc/include/isc/refcount.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,19 +15,22 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: refcount.h,v 1.3.2.2.2.2 2004/04/14 05:12:25 marka Exp $ */ +/* $ISC: refcount.h,v 1.6.18.5 2005/07/12 01:22:31 marka Exp $ */ #ifndef ISC_REFCOUNT_H #define ISC_REFCOUNT_H 1 +#include <isc/atomic.h> #include <isc/lang.h> #include <isc/mutex.h> #include <isc/platform.h> #include <isc/types.h> #include <isc/util.h> -/* - * Implements a locked reference counter. These functions may actually be +/*! \file + * \brief Implements a locked reference counter. + * + * These functions may actually be * implemented using macros, and implementations of these macros are below. * The isc_refcount_t type should not be accessed directly, as its contents * depend on the implementation. @@ -39,8 +42,8 @@ ISC_LANG_BEGINDECLS * Function prototypes */ -/* - * void +/* + * isc_result_t * isc_refcount_init(isc_refcount_t *ref, unsigned int n); * * Initialize the reference counter. There will be 'n' initial references. @@ -63,9 +66,14 @@ ISC_LANG_BEGINDECLS /* * void * isc_refcount_increment(isc_refcount_t *ref, unsigned int *targetp); + * isc_refcount_increment0(isc_refcount_t *ref, unsigned int *targetp); * * Increments the reference count, returning the new value in targetp if it's - * not NULL. + * not NULL. The reference counter typically begins with the initial counter + * of 1, and will be destroyed once the counter reaches 0. Thus, + * isc_refcount_increment() additionally requires the previous counter be + * larger than 0 so that an error which violates the usage can be easily + * caught. isc_refcount_increment0() does not have this restriction. * * Requires: * ref != NULL. @@ -87,20 +95,54 @@ ISC_LANG_BEGINDECLS * Sample implementations */ #ifdef ISC_PLATFORM_USETHREADS +#ifdef ISC_PLATFORM_HAVEXADD + +#define ISC_REFCOUNT_HAVEATOMIC 1 typedef struct isc_refcount { - int refs; - isc_mutex_t lock; + isc_int32_t refs; } isc_refcount_t; -#define isc_refcount_init(rp, n) \ - do { \ - isc_result_t _r; \ - (rp)->refs = (n); \ - _r = isc_mutex_init(&(rp)->lock); \ - RUNTIME_CHECK(_r == ISC_R_SUCCESS); \ +#define isc_refcount_destroy(rp) (REQUIRE((rp)->refs == 0)) +#define isc_refcount_current(rp) ((unsigned int)((rp)->refs)) + +#define isc_refcount_increment0(rp, tp) \ + do { \ + unsigned int *_tmp = (unsigned int *)(tp); \ + isc_int32_t prev; \ + prev = isc_atomic_xadd(&(rp)->refs, 1); \ + if (_tmp != NULL) \ + *_tmp = prev + 1; \ } while (0) +#define isc_refcount_increment(rp, tp) \ + do { \ + unsigned int *_tmp = (unsigned int *)(tp); \ + isc_int32_t prev; \ + prev = isc_atomic_xadd(&(rp)->refs, 1); \ + REQUIRE(prev > 0); \ + if (_tmp != NULL) \ + *_tmp = prev + 1; \ + } while (0) + +#define isc_refcount_decrement(rp, tp) \ + do { \ + unsigned int *_tmp = (unsigned int *)(tp); \ + isc_int32_t prev; \ + prev = isc_atomic_xadd(&(rp)->refs, -1); \ + REQUIRE(prev > 0); \ + if (_tmp != NULL) \ + *_tmp = prev - 1; \ + } while (0) + +#else /* ISC_PLATFORM_HAVEXADD */ + +typedef struct isc_refcount { + int refs; + isc_mutex_t lock; +} isc_refcount_t; + +/*% Destroys a reference counter. */ #define isc_refcount_destroy(rp) \ do { \ REQUIRE((rp)->refs == 0); \ @@ -109,6 +151,17 @@ typedef struct isc_refcount { #define isc_refcount_current(rp) ((unsigned int)((rp)->refs)) +/*% Increments the reference count, returning the new value in targetp if it's not NULL. */ +#define isc_refcount_increment0(rp, tp) \ + do { \ + unsigned int *_tmp = (unsigned int *)(tp); \ + LOCK(&(rp)->lock); \ + ++((rp)->refs); \ + if (_tmp != NULL) \ + *_tmp = ((rp)->refs); \ + UNLOCK(&(rp)->lock); \ + } while (0) + #define isc_refcount_increment(rp, tp) \ do { \ unsigned int *_tmp = (unsigned int *)(tp); \ @@ -120,6 +173,7 @@ typedef struct isc_refcount { UNLOCK(&(rp)->lock); \ } while (0) +/*% Decrements the reference count, returning the new value in targetp if it's not NULL. */ #define isc_refcount_decrement(rp, tp) \ do { \ unsigned int *_tmp = (unsigned int *)(tp); \ @@ -131,17 +185,17 @@ typedef struct isc_refcount { UNLOCK(&(rp)->lock); \ } while (0) -#else +#endif /* ISC_PLATFORM_HAVEXADD */ +#else /* ISC_PLATFORM_USETHREADS */ typedef struct isc_refcount { int refs; } isc_refcount_t; -#define isc_refcount_init(rp, n) ((rp)->refs = (n)) #define isc_refcount_destroy(rp) (REQUIRE((rp)->refs == 0)) #define isc_refcount_current(rp) ((unsigned int)((rp)->refs)) -#define isc_refcount_increment(rp, tp) \ +#define isc_refcount_increment0(rp, tp) \ do { \ unsigned int *_tmp = (unsigned int *)(tp); \ int _n = ++(rp)->refs; \ @@ -149,15 +203,30 @@ typedef struct isc_refcount { *_tmp = _n; \ } while (0) +#define isc_refcount_increment(rp, tp) \ + do { \ + unsigned int *_tmp = (unsigned int *)(tp); \ + int _n; \ + REQUIRE((rp)->refs > 0); \ + _n = ++(rp)->refs; \ + if (_tmp != NULL) \ + *_tmp = _n; \ + } while (0) + #define isc_refcount_decrement(rp, tp) \ do { \ unsigned int *_tmp = (unsigned int *)(tp); \ - int _n = --(rp)->refs; \ + int _n; \ + REQUIRE((rp)->refs > 0); \ + _n = --(rp)->refs; \ if (_tmp != NULL) \ *_tmp = _n; \ } while (0) -#endif +#endif /* ISC_PLATFORM_USETHREADS */ + +isc_result_t +isc_refcount_init(isc_refcount_t *ref, unsigned int n); ISC_LANG_ENDDECLS diff --git a/usr.sbin/bind/lib/isc/include/isc/rwlock.h b/usr.sbin/bind/lib/isc/include/isc/rwlock.h index c13e1166f0b..78a591a4f7a 100644 --- a/usr.sbin/bind/lib/isc/include/isc/rwlock.h +++ b/usr.sbin/bind/lib/isc/include/isc/rwlock.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,11 +15,13 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: rwlock.h,v 1.18.2.3.2.1 2004/03/06 08:14:47 marka Exp $ */ +/* $ISC: rwlock.h,v 1.21.18.3 2005/06/04 06:23:44 jinmei Exp $ */ #ifndef ISC_RWLOCK_H #define ISC_RWLOCK_H 1 +/*! \file */ + #include <isc/condition.h> #include <isc/lang.h> #include <isc/platform.h> @@ -34,19 +36,56 @@ typedef enum { } isc_rwlocktype_t; #ifdef ISC_PLATFORM_USETHREADS +#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG) +#define ISC_RWLOCK_USEATOMIC 1 +#endif + struct isc_rwlock { /* Unlocked. */ unsigned int magic; isc_mutex_t lock; + +#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG) + /* + * When some atomic instructions with hardware assistance are + * available, rwlock will use those so that concurrent readers do not + * interfere with each other through mutex as long as no writers + * appear, massively reducing the lock overhead in the typical case. + * + * The basic algorithm of this approach is the "simple + * writer-preference lock" shown in the following URL: + * http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/rw.html + * but our implementation does not rely on the spin lock unlike the + * original algorithm to be more portable as a user space application. + */ + + /* Read or modified atomically. */ + isc_int32_t write_requests; + isc_int32_t write_completions; + isc_int32_t cnt_and_flag; + /* Locked by lock. */ isc_condition_t readable; isc_condition_t writeable; + unsigned int readers_waiting; + + /* Locked by rwlock itself. */ + unsigned int write_granted; + + /* Unlocked. */ + unsigned int write_quota; + +#else /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */ + + /*%< Locked by lock. */ + isc_condition_t readable; + isc_condition_t writeable; isc_rwlocktype_t type; - /* The number of threads that have the lock. */ + /*% The number of threads that have the lock. */ unsigned int active; - /* + /*% * The number of lock grants made since the lock was last switched * from reading to writing or vice versa; used in determining * when the quota is reached and it is time to switch. @@ -58,6 +97,7 @@ struct isc_rwlock { unsigned int read_quota; unsigned int write_quota; isc_rwlocktype_t original; +#endif /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */ }; #else /* ISC_PLATFORM_USETHREADS */ struct isc_rwlock { diff --git a/usr.sbin/bind/lib/isc/include/isc/socket.h b/usr.sbin/bind/lib/isc/include/isc/socket.h index b30acf1e276..e5e76cab964 100644 --- a/usr.sbin/bind/lib/isc/include/isc/socket.h +++ b/usr.sbin/bind/lib/isc/include/isc/socket.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: socket.h,v 1.54.12.4 2004/03/08 09:04:53 marka Exp $ */ +/* $ISC: socket.h,v 1.57.18.6 2006/06/07 00:29:45 marka Exp $ */ #ifndef ISC_SOCKET_H #define ISC_SOCKET_H 1 @@ -24,36 +24,32 @@ ***** Module Info *****/ -/* - * Sockets - * - * Provides TCP and UDP sockets for network I/O. The sockets are event +/*! \file + * \brief Provides TCP and UDP sockets for network I/O. The sockets are event * sources in the task system. * * When I/O completes, a completion event for the socket is posted to the * event queue of the task which requested the I/O. * - * MP: + * \li MP: * The module ensures appropriate synchronization of data structures it * creates and manipulates. - * * Clients of this module must not be holding a socket's task's lock when * making a call that affects that socket. Failure to follow this rule * can result in deadlock. - * * The caller must ensure that isc_socketmgr_destroy() is called only * once for a given manager. * - * Reliability: + * \li Reliability: * No anticipated impact. * - * Resources: - * <TBS> + * \li Resources: + * TBS * - * Security: + * \li Security: * No anticipated impact. * - * Standards: + * \li Standards: * None. */ @@ -75,7 +71,7 @@ ISC_LANG_BEGINDECLS *** Constants ***/ -/* +/*% * Maximum number of buffers in a scatter/gather read/write. The operating * system in use must support at least this number (plus one on some.) */ @@ -87,33 +83,35 @@ ISC_LANG_BEGINDECLS struct isc_socketevent { ISC_EVENT_COMMON(isc_socketevent_t); - isc_result_t result; /* OK, EOF, whatever else */ - unsigned int minimum; /* minimum i/o for event */ - unsigned int n; /* bytes read or written */ - unsigned int offset; /* offset into buffer list */ - isc_region_t region; /* for single-buffer i/o */ - isc_bufferlist_t bufferlist; /* list of buffers */ - isc_sockaddr_t address; /* source address */ - isc_time_t timestamp; /* timestamp of packet recv */ - struct in6_pktinfo pktinfo; /* ipv6 pktinfo */ - isc_uint32_t attributes; /* see below */ + isc_result_t result; /*%< OK, EOF, whatever else */ + unsigned int minimum; /*%< minimum i/o for event */ + unsigned int n; /*%< bytes read or written */ + unsigned int offset; /*%< offset into buffer list */ + isc_region_t region; /*%< for single-buffer i/o */ + isc_bufferlist_t bufferlist; /*%< list of buffers */ + isc_sockaddr_t address; /*%< source address */ + isc_time_t timestamp; /*%< timestamp of packet recv */ + struct in6_pktinfo pktinfo; /*%< ipv6 pktinfo */ + isc_uint32_t attributes; /*%< see below */ + isc_eventdestructor_t destroy; /*%< original destructor */ }; typedef struct isc_socket_newconnev isc_socket_newconnev_t; struct isc_socket_newconnev { ISC_EVENT_COMMON(isc_socket_newconnev_t); isc_socket_t * newsocket; - isc_result_t result; /* OK, EOF, whatever else */ - isc_sockaddr_t address; /* source address */ + isc_result_t result; /*%< OK, EOF, whatever else */ + isc_sockaddr_t address; /*%< source address */ }; typedef struct isc_socket_connev isc_socket_connev_t; struct isc_socket_connev { ISC_EVENT_COMMON(isc_socket_connev_t); - isc_result_t result; /* OK, EOF, whatever else */ + isc_result_t result; /*%< OK, EOF, whatever else */ }; -/* +/*@{*/ +/*! * _ATTACHED: Internal use only. * _TRUNC: Packet was truncated on receive. * _CTRUNC: Packet control information was truncated. This can @@ -129,6 +127,7 @@ struct isc_socket_connev { #define ISC_SOCKEVENTATTR_TIMESTAMP 0x00200000U /* public */ #define ISC_SOCKEVENTATTR_PKTINFO 0x00100000U /* public */ #define ISC_SOCKEVENTATTR_MULTICAST 0x00080000U /* public */ +/*@}*/ #define ISC_SOCKEVENT_ANYEVENT (0) #define ISC_SOCKEVENT_RECVDONE (ISC_EVENTCLASS_SOCKET + 1) @@ -144,30 +143,37 @@ struct isc_socket_connev { typedef enum { isc_sockettype_udp = 1, - isc_sockettype_tcp = 2 + isc_sockettype_tcp = 2, + isc_sockettype_unix = 3 } isc_sockettype_t; -/* +/*@{*/ +/*! * How a socket should be shutdown in isc_socket_shutdown() calls. */ -#define ISC_SOCKSHUT_RECV 0x00000001 /* close read side */ -#define ISC_SOCKSHUT_SEND 0x00000002 /* close write side */ -#define ISC_SOCKSHUT_ALL 0x00000003 /* close them all */ +#define ISC_SOCKSHUT_RECV 0x00000001 /*%< close read side */ +#define ISC_SOCKSHUT_SEND 0x00000002 /*%< close write side */ +#define ISC_SOCKSHUT_ALL 0x00000003 /*%< close them all */ +/*@}*/ -/* +/*@{*/ +/*! * What I/O events to cancel in isc_socket_cancel() calls. */ -#define ISC_SOCKCANCEL_RECV 0x00000001 /* cancel recv */ -#define ISC_SOCKCANCEL_SEND 0x00000002 /* cancel send */ -#define ISC_SOCKCANCEL_ACCEPT 0x00000004 /* cancel accept */ -#define ISC_SOCKCANCEL_CONNECT 0x00000008 /* cancel connect */ -#define ISC_SOCKCANCEL_ALL 0x0000000f /* cancel everything */ - -/* +#define ISC_SOCKCANCEL_RECV 0x00000001 /*%< cancel recv */ +#define ISC_SOCKCANCEL_SEND 0x00000002 /*%< cancel send */ +#define ISC_SOCKCANCEL_ACCEPT 0x00000004 /*%< cancel accept */ +#define ISC_SOCKCANCEL_CONNECT 0x00000008 /*%< cancel connect */ +#define ISC_SOCKCANCEL_ALL 0x0000000f /*%< cancel everything */ +/*@}*/ + +/*@{*/ +/*! * Flags for isc_socket_send() and isc_socket_recv() calls. */ -#define ISC_SOCKFLAG_IMMEDIATE 0x00000001 /* send event only if needed */ -#define ISC_SOCKFLAG_NORETRY 0x00000002 /* drop failed UDP sends */ +#define ISC_SOCKFLAG_IMMEDIATE 0x00000001 /*%< send event only if needed */ +#define ISC_SOCKFLAG_NORETRY 0x00000002 /*%< drop failed UDP sends */ +/*@}*/ /*** *** Socket and Socket Manager Functions @@ -181,18 +187,18 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, isc_socket_t **socketp); -/* +/*%< * Create a new 'type' socket managed by 'manager'. * * Note: * - * 'pf' is the desired protocol family, e.g. PF_INET or PF_INET6. + *\li 'pf' is the desired protocol family, e.g. PF_INET or PF_INET6. * * Requires: * - * 'manager' is a valid manager + *\li 'manager' is a valid manager * - * 'socketp' is a valid pointer, and *socketp == NULL + *\li 'socketp' is a valid pointer, and *socketp == NULL * * Ensures: * @@ -200,16 +206,16 @@ isc_socket_create(isc_socketmgr_t *manager, * * Returns: * - * ISC_R_SUCCESS - * ISC_R_NOMEMORY - * ISC_R_NORESOURCES - * ISC_R_UNEXPECTED + *\li #ISC_R_SUCCESS + *\li #ISC_R_NOMEMORY + *\li #ISC_R_NORESOURCES + *\li #ISC_R_UNEXPECTED */ void isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how); -/* +/*%< * Cancel pending I/O of the type specified by "how". * * Note: if "task" is NULL, then the cancel applies to all tasks using the @@ -217,45 +223,45 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, * * Requires: * - * "socket" is a valid socket + * \li "socket" is a valid socket * - * "task" is NULL or a valid task + * \li "task" is NULL or a valid task * * "how" is a bitmask describing the type of cancelation to perform. * The type ISC_SOCKCANCEL_ALL will cancel all pending I/O on this * socket. * - * ISC_SOCKCANCEL_RECV: + * \li ISC_SOCKCANCEL_RECV: * Cancel pending isc_socket_recv() calls. * - * ISC_SOCKCANCEL_SEND: + * \li ISC_SOCKCANCEL_SEND: * Cancel pending isc_socket_send() and isc_socket_sendto() calls. * - * ISC_SOCKCANCEL_ACCEPT: + * \li ISC_SOCKCANCEL_ACCEPT: * Cancel pending isc_socket_accept() calls. * - * ISC_SOCKCANCEL_CONNECT: + * \li ISC_SOCKCANCEL_CONNECT: * Cancel pending isc_socket_connect() call. */ void isc_socket_shutdown(isc_socket_t *sock, unsigned int how); -/* +/*%< * Shutdown 'socket' according to 'how'. * * Requires: * - * 'socket' is a valid socket. + * \li 'socket' is a valid socket. * - * 'task' is NULL or is a valid task. + * \li 'task' is NULL or is a valid task. * - * If 'how' is 'ISC_SOCKSHUT_RECV' or 'ISC_SOCKSHUT_ALL' then + * \li If 'how' is 'ISC_SOCKSHUT_RECV' or 'ISC_SOCKSHUT_ALL' then * * The read queue must be empty. * * No further read requests may be made. * - * If 'how' is 'ISC_SOCKSHUT_SEND' or 'ISC_SOCKSHUT_ALL' then + * \li If 'how' is 'ISC_SOCKSHUT_SEND' or 'ISC_SOCKSHUT_ALL' then * * The write queue must be empty. * @@ -264,39 +270,39 @@ isc_socket_shutdown(isc_socket_t *sock, unsigned int how); void isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp); -/* +/*%< * Attach *socketp to socket. * * Requires: * - * 'socket' is a valid socket. + * \li 'socket' is a valid socket. * - * 'socketp' points to a NULL socket. + * \li 'socketp' points to a NULL socket. * * Ensures: * - * *socketp is attached to socket. + * \li *socketp is attached to socket. */ void isc_socket_detach(isc_socket_t **socketp); -/* +/*%< * Detach *socketp from its socket. * * Requires: * - * 'socketp' points to a valid socket. + * \li 'socketp' points to a valid socket. * - * If '*socketp' is the last reference to the socket, + * \li If '*socketp' is the last reference to the socket, * then: * * There must be no pending I/O requests. * * Ensures: * - * *socketp is NULL. + * \li *socketp is NULL. * - * If '*socketp' is the last reference to the socket, + * \li If '*socketp' is the last reference to the socket, * then: * * The socket will be shutdown (both reading and writing) @@ -307,23 +313,23 @@ isc_socket_detach(isc_socket_t **socketp); isc_result_t isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *addressp); -/* +/*%< * Bind 'socket' to '*addressp'. * * Requires: * - * 'socket' is a valid socket + * \li 'socket' is a valid socket * - * 'addressp' points to a valid isc_sockaddr. + * \li 'addressp' points to a valid isc_sockaddr. * * Returns: * - * ISC_R_SUCCESS - * ISC_R_NOPERM - * ISC_R_ADDRNOTAVAIL - * ISC_R_ADDRINUSE - * ISC_R_BOUND - * ISC_R_UNEXPECTED + * \li ISC_R_SUCCESS + * \li ISC_R_NOPERM + * \li ISC_R_ADDRNOTAVAIL + * \li ISC_R_ADDRINUSE + * \li ISC_R_BOUND + * \li ISC_R_UNEXPECTED */ isc_result_t @@ -331,124 +337,125 @@ isc_socket_privsep(int); isc_result_t isc_socket_filter(isc_socket_t *sock, const char *filter); -/* +/*%< * Inform the kernel that it should perform accept filtering. * If filter is NULL the current filter will be removed.:w */ isc_result_t isc_socket_listen(isc_socket_t *sock, unsigned int backlog); -/* +/*%< * Set listen mode on the socket. After this call, the only function that * can be used (other than attach and detach) is isc_socket_accept(). * * Notes: * - * 'backlog' is as in the UNIX system call listen() and may be + * \li 'backlog' is as in the UNIX system call listen() and may be * ignored by non-UNIX implementations. * - * If 'backlog' is zero, a reasonable system default is used, usually + * \li If 'backlog' is zero, a reasonable system default is used, usually * SOMAXCONN. * * Requires: * - * 'socket' is a valid, bound TCP socket. + * \li 'socket' is a valid, bound TCP socket or a valid, bound UNIX socket. * * Returns: * - * ISC_R_SUCCESS - * ISC_R_UNEXPECTED + * \li ISC_R_SUCCESS + * \li ISC_R_UNEXPECTED */ isc_result_t isc_socket_accept(isc_socket_t *sock, isc_task_t *task, isc_taskaction_t action, const void *arg); -/* +/*%< * Queue accept event. When a new connection is received, the task will * get an ISC_SOCKEVENT_NEWCONN event with the sender set to the listen * socket. The new socket structure is sent inside the isc_socket_newconnev_t * event type, and is attached to the task 'task'. * * REQUIRES: - * 'socket' is a valid TCP socket that isc_socket_listen() was called + * \li 'socket' is a valid TCP socket that isc_socket_listen() was called * on. * - * 'task' is a valid task + * \li 'task' is a valid task * - * 'action' is a valid action + * \li 'action' is a valid action * * RETURNS: - * ISC_R_SUCCESS - * ISC_R_NOMEMORY - * ISC_R_UNEXPECTED + * \li ISC_R_SUCCESS + * \li ISC_R_NOMEMORY + * \li ISC_R_UNEXPECTED */ isc_result_t isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addressp, isc_task_t *task, isc_taskaction_t action, const void *arg); -/* +/*%< * Connect 'socket' to peer with address *saddr. When the connection * succeeds, or when an error occurs, a CONNECT event with action 'action' * and arg 'arg' will be posted to the event queue for 'task'. * * Requires: * - * 'socket' is a valid TCP socket + * \li 'socket' is a valid TCP socket * - * 'addressp' points to a valid isc_sockaddr + * \li 'addressp' points to a valid isc_sockaddr * - * 'task' is a valid task + * \li 'task' is a valid task * - * 'action' is a valid action + * \li 'action' is a valid action * * Returns: * - * ISC_R_SUCCESS - * ISC_R_NOMEMORY - * ISC_R_UNEXPECTED + * \li ISC_R_SUCCESS + * \li ISC_R_NOMEMORY + * \li ISC_R_UNEXPECTED * * Posted event's result code: * - * ISC_R_SUCCESS - * ISC_R_TIMEDOUT - * ISC_R_CONNREFUSED - * ISC_R_NETUNREACH - * ISC_R_UNEXPECTED + * \li ISC_R_SUCCESS + * \li ISC_R_TIMEDOUT + * \li ISC_R_CONNREFUSED + * \li ISC_R_NETUNREACH + * \li ISC_R_UNEXPECTED */ isc_result_t isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp); -/* +/*%< * Get the name of the peer connected to 'socket'. * * Requires: * - * 'socket' is a valid TCP socket. + * \li 'socket' is a valid TCP socket. * * Returns: * - * ISC_R_SUCCESS - * ISC_R_TOOSMALL - * ISC_R_UNEXPECTED + * \li ISC_R_SUCCESS + * \li ISC_R_TOOSMALL + * \li ISC_R_UNEXPECTED */ isc_result_t isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp); -/* +/*%< * Get the name of 'socket'. * * Requires: * - * 'socket' is a valid socket. + * \li 'socket' is a valid socket. * * Returns: * - * ISC_R_SUCCESS - * ISC_R_TOOSMALL - * ISC_R_UNEXPECTED + * \li ISC_R_SUCCESS + * \li ISC_R_TOOSMALL + * \li ISC_R_UNEXPECTED */ +/*@{*/ isc_result_t isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum, @@ -463,39 +470,39 @@ isc_socket_recv2(isc_socket_t *sock, isc_region_t *region, unsigned int minimum, isc_task_t *task, isc_socketevent_t *event, unsigned int flags); -/* +/*! * Receive from 'socket', storing the results in region. * * Notes: * - * Let 'length' refer to the length of 'region' or to the sum of all + *\li Let 'length' refer to the length of 'region' or to the sum of all * available regions in the list of buffers '*buflist'. * - * If 'minimum' is non-zero and at least that many bytes are read, + *\li If 'minimum' is non-zero and at least that many bytes are read, * the completion event will be posted to the task 'task.' If minimum * is zero, the exact number of bytes requested in the region must * be read for an event to be posted. This only makes sense for TCP * connections, and is always set to 1 byte for UDP. * - * The read will complete when the desired number of bytes have been + *\li The read will complete when the desired number of bytes have been * read, if end-of-input occurs, or if an error occurs. A read done * event with the given 'action' and 'arg' will be posted to the * event queue of 'task'. * - * The caller may not modify 'region', the buffers which are passed + *\li The caller may not modify 'region', the buffers which are passed * into this function, or any data they refer to until the completion * event is received. * - * For isc_socket_recvv(): + *\li For isc_socket_recvv(): * On successful completion, '*buflist' will be empty, and the list of * all buffers will be returned in the done event's 'bufferlist' * member. On error return, '*buflist' will be unchanged. * - * For isc_socket_recv2(): + *\li For isc_socket_recv2(): * 'event' is not NULL, and the non-socket specific fields are * expected to be initialized. * - * For isc_socket_recv2(): + *\li For isc_socket_recv2(): * The only defined value for 'flags' is ISC_SOCKFLAG_IMMEDIATE. If * set and the operation completes, the return value will be * ISC_R_SUCCESS and the event will be filled in and not sent. If the @@ -505,36 +512,38 @@ isc_socket_recv2(isc_socket_t *sock, isc_region_t *region, * * Requires: * - * 'socket' is a valid, bound socket. + *\li 'socket' is a valid, bound socket. * - * For isc_socket_recv(): + *\li For isc_socket_recv(): * 'region' is a valid region * - * For isc_socket_recvv(): + *\li For isc_socket_recvv(): * 'buflist' is non-NULL, and '*buflist' contain at least one buffer. * - * 'task' is a valid task + *\li 'task' is a valid task * - * For isc_socket_recv() and isc_socket_recvv(): + *\li For isc_socket_recv() and isc_socket_recvv(): * action != NULL and is a valid action * - * For isc_socket_recv2(): + *\li For isc_socket_recv2(): * event != NULL * * Returns: * - * ISC_R_SUCCESS - * ISC_R_INPROGRESS - * ISC_R_NOMEMORY - * ISC_R_UNEXPECTED + *\li #ISC_R_SUCCESS + *\li #ISC_R_INPROGRESS + *\li #ISC_R_NOMEMORY + *\li #ISC_R_UNEXPECTED * * Event results: * - * ISC_R_SUCCESS - * ISC_R_UNEXPECTED - * XXX needs other net-type errors + *\li #ISC_R_SUCCESS + *\li #ISC_R_UNEXPECTED + *\li XXX needs other net-type errors */ +/*@}*/ +/*@{*/ isc_result_t isc_socket_send(isc_socket_t *sock, isc_region_t *region, isc_task_t *task, isc_taskaction_t action, const void *arg); @@ -555,41 +564,41 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, isc_socketevent_t *event, unsigned int flags); -/* +/*! * Send the contents of 'region' to the socket's peer. * * Notes: * - * Shutting down the requestor's task *may* result in any + *\li Shutting down the requestor's task *may* result in any * still pending writes being dropped or completed, depending on the * underlying OS implementation. * - * If 'action' is NULL, then no completion event will be posted. + *\li If 'action' is NULL, then no completion event will be posted. * - * The caller may not modify 'region', the buffers which are passed + *\li The caller may not modify 'region', the buffers which are passed * into this function, or any data they refer to until the completion * event is received. * - * For isc_socket_sendv() and isc_socket_sendtov(): + *\li For isc_socket_sendv() and isc_socket_sendtov(): * On successful completion, '*buflist' will be empty, and the list of * all buffers will be returned in the done event's 'bufferlist' * member. On error return, '*buflist' will be unchanged. * - * For isc_socket_sendto2(): + *\li For isc_socket_sendto2(): * 'event' is not NULL, and the non-socket specific fields are * expected to be initialized. * - * For isc_socket_sendto2(): + *\li For isc_socket_sendto2(): * The only defined values for 'flags' are ISC_SOCKFLAG_IMMEDIATE * and ISC_SOCKFLAG_NORETRY. * - * If ISC_SOCKFLAG_IMMEDIATE is set and the operation completes, the + *\li If ISC_SOCKFLAG_IMMEDIATE is set and the operation completes, the * return value will be ISC_R_SUCCESS and the event will be filled * in and not sent. If the operation does not complete, the return * value will be ISC_R_INPROGRESS and the event will be sent when * the operation completes. * - * ISC_SOCKFLAG_NORETRY can only be set for UDP sockets. If set + *\li ISC_SOCKFLAG_NORETRY can only be set for UDP sockets. If set * and the send operation fails due to a transient error, the send * will not be retried and the error will be indicated in the event. * Using this option along with ISC_SOCKFLAG_IMMEDIATE allows the caller @@ -597,109 +606,148 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, * * Requires: * - * 'socket' is a valid, bound socket. + *\li 'socket' is a valid, bound socket. * - * For isc_socket_send(): + *\li For isc_socket_send(): * 'region' is a valid region * - * For isc_socket_sendv() and isc_socket_sendtov(): + *\li For isc_socket_sendv() and isc_socket_sendtov(): * 'buflist' is non-NULL, and '*buflist' contain at least one buffer. * - * 'task' is a valid task + *\li 'task' is a valid task * - * For isc_socket_sendv(), isc_socket_sendtov(), isc_socket_send(), and + *\li For isc_socket_sendv(), isc_socket_sendtov(), isc_socket_send(), and * isc_socket_sendto(): * action == NULL or is a valid action * - * For isc_socket_sendto2(): + *\li For isc_socket_sendto2(): * event != NULL * * Returns: * - * ISC_R_SUCCESS - * ISC_R_INPROGRESS - * ISC_R_NOMEMORY - * ISC_R_UNEXPECTED + *\li #ISC_R_SUCCESS + *\li #ISC_R_INPROGRESS + *\li #ISC_R_NOMEMORY + *\li #ISC_R_UNEXPECTED * * Event results: * - * ISC_R_SUCCESS - * ISC_R_UNEXPECTED - * XXX needs other net-type errors + *\li #ISC_R_SUCCESS + *\li #ISC_R_UNEXPECTED + *\li XXX needs other net-type errors */ +/*@}*/ isc_result_t isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp); -/* +/*%< * Create a socket manager. * * Notes: * - * All memory will be allocated in memory context 'mctx'. + *\li All memory will be allocated in memory context 'mctx'. * * Requires: * - * 'mctx' is a valid memory context. + *\li 'mctx' is a valid memory context. * - * 'managerp' points to a NULL isc_socketmgr_t. + *\li 'managerp' points to a NULL isc_socketmgr_t. * * Ensures: * - * '*managerp' is a valid isc_socketmgr_t. + *\li '*managerp' is a valid isc_socketmgr_t. * * Returns: * - * ISC_R_SUCCESS - * ISC_R_NOMEMORY - * ISC_R_UNEXPECTED + *\li #ISC_R_SUCCESS + *\li #ISC_R_NOMEMORY + *\li #ISC_R_UNEXPECTED */ void isc_socketmgr_destroy(isc_socketmgr_t **managerp); -/* +/*%< * Destroy a socket manager. * * Notes: * - * This routine blocks until there are no sockets left in the manager, + *\li This routine blocks until there are no sockets left in the manager, * so if the caller holds any socket references using the manager, it * must detach them before calling isc_socketmgr_destroy() or it will * block forever. * * Requires: * - * '*managerp' is a valid isc_socketmgr_t. + *\li '*managerp' is a valid isc_socketmgr_t. * - * All sockets managed by this manager are fully detached. + *\li All sockets managed by this manager are fully detached. * * Ensures: * - * *managerp == NULL + *\li *managerp == NULL * - * All resources used by the manager have been freed. + *\li All resources used by the manager have been freed. */ isc_sockettype_t isc_socket_gettype(isc_socket_t *sock); -/* +/*%< * Returns the socket type for "sock." * * Requires: * - * "sock" is a valid socket. + *\li "sock" is a valid socket. */ +/*@{*/ isc_boolean_t isc_socket_isbound(isc_socket_t *sock); void isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes); -/* +/*%< * If the socket is an IPv6 socket set/clear the IPV6_IPV6ONLY socket * option if the host OS supports this option. * * Requires: - * 'sock' is a valid socket. + *\li 'sock' is a valid socket. + */ +/*@}*/ + +void +isc_socket_cleanunix(isc_sockaddr_t *addr, isc_boolean_t active); + +/*%< + * Cleanup UNIX domain sockets in the file-system. If 'active' is true + * then just unlink the socket. If 'active' is false try to determine + * if there is a listener of the socket or not. If no listener is found + * then unlink socket. + * + * Prior to unlinking the path is tested to see if it a socket. + * + * Note: there are a number of race conditions which cannot be avoided + * both in the filesystem and any application using UNIX domain + * sockets (e.g. socket is tested between bind() and listen(), + * the socket is deleted and replaced in the file-system between + * stat() and unlink()). + */ + +isc_result_t +isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm, + isc_uint32_t owner, isc_uint32_t group); +/*%< + * Set ownership and file permissions on the UNIX domain socket. + * + * Note: On Solaris and SunOS this secures the directory containing + * the socket as Solaris and SunOS do not honour the filesytem + * permissions on the socket. + * + * Requires: + * \li 'sockaddr' to be a valid UNIX domain sockaddr. + * + * Returns: + * \li #ISC_R_SUCCESS + * \li #ISC_R_FAILURE */ ISC_LANG_ENDDECLS diff --git a/usr.sbin/bind/lib/isc/include/isc/string.h b/usr.sbin/bind/lib/isc/include/isc/string.h index 742b620ecf1..5931750c01b 100644 --- a/usr.sbin/bind/lib/isc/include/isc/string.h +++ b/usr.sbin/bind/lib/isc/include/isc/string.h @@ -1,8 +1,8 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * - * Permission to use, copy, modify, and distribute this software for any + * Permission to use, copy, modify, and/or 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. * @@ -15,22 +15,32 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: string.h,v 1.9.164.3 2004/03/06 08:14:49 marka Exp $ */ +/* $ISC: string.h,v 1.12.18.6 2007/09/13 05:04:01 each Exp $ */ #ifndef ISC_STRING_H #define ISC_STRING_H 1 -#include <string.h> +/*! \file */ +#include <isc/formatcheck.h> #include <isc/int.h> #include <isc/lang.h> #include <isc/platform.h> +#include <isc/types.h> + +#include <string.h> + +#ifdef ISC_PLATFORM_HAVESTRINGSH +#include <strings.h> +#endif + +#define ISC_STRING_MAGIC 0x5e ISC_LANG_BEGINDECLS isc_uint64_t isc_string_touint64(char *source, char **endp, int base); -/* +/*%< * Convert the string pointed to by 'source' to isc_uint64_t. * * On successful conversion 'endp' points to the first character @@ -43,6 +53,151 @@ isc_string_touint64(char *source, char **endp, int base); * On error 'endp' points to 'source'. */ +isc_result_t +isc_string_copy(char *target, size_t size, const char *source); +/* + * Copy the string pointed to by 'source' to 'target' which is a + * pointer to a string of at least 'size' bytes. + * + * Requires: + * 'target' is a pointer to a char[] of at least 'size' bytes. + * 'size' an integer > 0. + * 'source' == NULL or points to a NUL terminated string. + * + * Ensures: + * If result == ISC_R_SUCCESS + * 'target' will be a NUL terminated string of no more + * than 'size' bytes (including NUL). + * + * If result == ISC_R_NOSPACE + * 'target' is undefined. + * + * Returns: + * ISC_R_SUCCESS -- 'source' was successfully copied to 'target'. + * ISC_R_NOSPACE -- 'source' could not be copied since 'target' + * is too small. + */ + +void +isc_string_copy_truncate(char *target, size_t size, const char *source); +/* + * Copy the string pointed to by 'source' to 'target' which is a + * pointer to a string of at least 'size' bytes. + * + * Requires: + * 'target' is a pointer to a char[] of at least 'size' bytes. + * 'size' an integer > 0. + * 'source' == NULL or points to a NUL terminated string. + * + * Ensures: + * 'target' will be a NUL terminated string of no more + * than 'size' bytes (including NUL). + */ + +isc_result_t +isc_string_append(char *target, size_t size, const char *source); +/* + * Append the string pointed to by 'source' to 'target' which is a + * pointer to a NUL terminated string of at least 'size' bytes. + * + * Requires: + * 'target' is a pointer to a NUL terminated char[] of at + * least 'size' bytes. + * 'size' an integer > 0. + * 'source' == NULL or points to a NUL terminated string. + * + * Ensures: + * If result == ISC_R_SUCCESS + * 'target' will be a NUL terminated string of no more + * than 'size' bytes (including NUL). + * + * If result == ISC_R_NOSPACE + * 'target' is undefined. + * + * Returns: + * ISC_R_SUCCESS -- 'source' was successfully appended to 'target'. + * ISC_R_NOSPACE -- 'source' could not be appended since 'target' + * is too small. + */ + +void +isc_string_append_truncate(char *target, size_t size, const char *source); +/* + * Append the string pointed to by 'source' to 'target' which is a + * pointer to a NUL terminated string of at least 'size' bytes. + * + * Requires: + * 'target' is a pointer to a NUL terminated char[] of at + * least 'size' bytes. + * 'size' an integer > 0. + * 'source' == NULL or points to a NUL terminated string. + * + * Ensures: + * 'target' will be a NUL terminated string of no more + * than 'size' bytes (including NUL). + */ + +isc_result_t +isc_string_printf(char *target, size_t size, const char *format, ...) + ISC_FORMAT_PRINTF(3, 4); +/* + * Print 'format' to 'target' which is a pointer to a string of at least + * 'size' bytes. + * + * Requires: + * 'target' is a pointer to a char[] of at least 'size' bytes. + * 'size' an integer > 0. + * 'format' == NULL or points to a NUL terminated string. + * + * Ensures: + * If result == ISC_R_SUCCESS + * 'target' will be a NUL terminated string of no more + * than 'size' bytes (including NUL). + * + * If result == ISC_R_NOSPACE + * 'target' is undefined. + * + * Returns: + * ISC_R_SUCCESS -- 'format' was successfully printed to 'target'. + * ISC_R_NOSPACE -- 'format' could not be printed to 'target' since it + * is too small. + */ + +void +isc_string_printf_truncate(char *target, size_t size, const char *format, ...) + ISC_FORMAT_PRINTF(3, 4); +/* + * Print 'format' to 'target' which is a pointer to a string of at least + * 'size' bytes. + * + * Requires: + * 'target' is a pointer to a char[] of at least 'size' bytes. + * 'size' an integer > 0. + * 'format' == NULL or points to a NUL terminated string. + * + * Ensures: + * 'target' will be a NUL terminated string of no more + * than 'size' bytes (including NUL). + */ + + +char * +isc_string_regiondup(isc_mem_t *mctx, const isc_region_t *source); +/* + * Copy the region pointed to by r to a NUL terminated string + * allocated from the memory context pointed to by mctx. + * + * The result should be deallocated using isc_mem_free() + * + * Requires: + * 'mctx' is a point to a valid memory context. + * 'source' is a pointer to a valid region. + * + * Returns: + * a pointer to a NUL terminated string or + * NULL if memory for the copy could not be allocated + * + */ char * isc_string_separate(char **stringp, const char *delim); diff --git a/usr.sbin/bind/lib/isc/include/isc/types.h b/usr.sbin/bind/lib/isc/include/isc/types.h index 79bb73238e5..c421239af34 100644 --- a/usr.sbin/bind/lib/isc/include/isc/types.h +++ b/usr.sbin/bind/lib/isc/include/isc/types.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,12 +15,13 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: types.h,v 1.32.2.3.2.1 2004/03/06 08:14:50 marka Exp $ */ +/* $ISC: types.h,v 1.35.18.2 2005/04/29 00:17:04 marka Exp $ */ #ifndef ISC_TYPES_H #define ISC_TYPES_H 1 -/* +/*! \file + * \brief * OS-specific types, from the OS-specific include directories. */ #include <isc/int.h> @@ -37,57 +38,56 @@ */ #include <isc/list.h> -/*** - *** Core Types. Alphabetized by defined type. - ***/ +/* Core Types. Alphabetized by defined type. */ -typedef struct isc_bitstring isc_bitstring_t; -typedef struct isc_buffer isc_buffer_t; -typedef ISC_LIST(isc_buffer_t) isc_bufferlist_t; -typedef struct isc_constregion isc_constregion_t; -typedef struct isc_consttextregion isc_consttextregion_t; -typedef struct isc_entropy isc_entropy_t; -typedef struct isc_entropysource isc_entropysource_t; -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; -typedef struct isc_lex isc_lex_t; -typedef struct isc_log isc_log_t; -typedef struct isc_logcategory isc_logcategory_t; -typedef struct isc_logconfig isc_logconfig_t; -typedef struct isc_logmodule isc_logmodule_t; -typedef struct isc_mem isc_mem_t; -typedef struct isc_mempool isc_mempool_t; -typedef struct isc_msgcat isc_msgcat_t; -typedef struct isc_ondestroy isc_ondestroy_t; -typedef struct isc_netaddr isc_netaddr_t; -typedef struct isc_quota isc_quota_t; -typedef struct isc_random isc_random_t; -typedef struct isc_ratelimiter isc_ratelimiter_t; -typedef struct isc_region isc_region_t; -typedef isc_uint64_t isc_resourcevalue_t; -typedef unsigned int isc_result_t; -typedef struct isc_rwlock isc_rwlock_t; -typedef struct isc_sockaddr isc_sockaddr_t; -typedef struct isc_socket isc_socket_t; -typedef struct isc_socketevent isc_socketevent_t; -typedef struct isc_socketmgr isc_socketmgr_t; -typedef struct isc_symtab isc_symtab_t; -typedef struct isc_task isc_task_t; -typedef ISC_LIST(isc_task_t) isc_tasklist_t; -typedef struct isc_taskmgr isc_taskmgr_t; -typedef struct isc_textregion isc_textregion_t; -typedef struct isc_time isc_time_t; -typedef struct isc_timer isc_timer_t; -typedef struct isc_timermgr isc_timermgr_t; +typedef struct isc_bitstring isc_bitstring_t; /*%< Bitstring */ +typedef struct isc_buffer isc_buffer_t; /*%< Buffer */ +typedef ISC_LIST(isc_buffer_t) isc_bufferlist_t; /*%< Buffer List */ +typedef struct isc_constregion isc_constregion_t; /*%< Const region */ +typedef struct isc_consttextregion isc_consttextregion_t; /*%< Const Text Region */ +typedef struct isc_entropy isc_entropy_t; /*%< Entropy */ +typedef struct isc_entropysource isc_entropysource_t; /*%< Entropy Source */ +typedef struct isc_event isc_event_t; /*%< Event */ +typedef ISC_LIST(isc_event_t) isc_eventlist_t; /*%< Event List */ +typedef unsigned int isc_eventtype_t; /*%< Event Type */ +typedef isc_uint32_t isc_fsaccess_t; /*%< FS Access */ +typedef struct isc_hash isc_hash_t; /*%< Hash */ +typedef struct isc_interface isc_interface_t; /*%< Interface */ +typedef struct isc_interfaceiter isc_interfaceiter_t; /*%< Interface Iterator */ +typedef struct isc_interval isc_interval_t; /*%< Interval */ +typedef struct isc_lex isc_lex_t; /*%< Lex */ +typedef struct isc_log isc_log_t; /*%< Log */ +typedef struct isc_logcategory isc_logcategory_t; /*%< Log Category */ +typedef struct isc_logconfig isc_logconfig_t; /*%< Log Configuration */ +typedef struct isc_logmodule isc_logmodule_t; /*%< Log Module */ +typedef struct isc_mem isc_mem_t; /*%< Memory */ +typedef struct isc_mempool isc_mempool_t; /*%< Memory Pool */ +typedef struct isc_msgcat isc_msgcat_t; /*%< Message Catalog */ +typedef struct isc_ondestroy isc_ondestroy_t; /*%< On Destroy */ +typedef struct isc_netaddr isc_netaddr_t; /*%< Net Address */ +typedef struct isc_quota isc_quota_t; /*%< Quota */ +typedef struct isc_random isc_random_t; /*%< Random */ +typedef struct isc_ratelimiter isc_ratelimiter_t; /*%< Rate Limiter */ +typedef struct isc_region isc_region_t; /*%< Region */ +typedef isc_uint64_t isc_resourcevalue_t; /*%< Resource Value */ +typedef unsigned int isc_result_t; /*%< Result */ +typedef struct isc_rwlock isc_rwlock_t; /*%< Read Write Lock */ +typedef struct isc_sockaddr isc_sockaddr_t; /*%< Socket Address */ +typedef struct isc_socket isc_socket_t; /*%< Socket */ +typedef struct isc_socketevent isc_socketevent_t; /*%< Socket Event */ +typedef struct isc_socketmgr isc_socketmgr_t; /*%< Socket Manager */ +typedef struct isc_symtab isc_symtab_t; /*%< Symbol Table */ +typedef struct isc_task isc_task_t; /*%< Task */ +typedef ISC_LIST(isc_task_t) isc_tasklist_t; /*%< Task List */ +typedef struct isc_taskmgr isc_taskmgr_t; /*%< Task Manager */ +typedef struct isc_textregion isc_textregion_t; /*%< Text Region */ +typedef struct isc_time isc_time_t; /*%< Time */ +typedef struct isc_timer isc_timer_t; /*%< Timer */ +typedef struct isc_timermgr isc_timermgr_t; /*%< Timer Manager */ typedef void (*isc_taskaction_t)(isc_task_t *, isc_event_t *); +/*% Resource */ typedef enum { isc_resource_coresize = 1, isc_resource_cputime, diff --git a/usr.sbin/bind/lib/isc/inet_aton.c b/usr.sbin/bind/lib/isc/inet_aton.c index e88525b1109..ba9d3c28bf2 100644 --- a/usr.sbin/bind/lib/isc/inet_aton.c +++ b/usr.sbin/bind/lib/isc/inet_aton.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1996-2001 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -67,10 +67,11 @@ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ +/*! \file */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; -static char rcsid[] = "$ISC: inet_aton.c,v 1.15.12.3 2004/03/08 09:04:49 marka Exp $"; +static char rcsid[] = "$ISC: inet_aton.c,v 1.17.18.2 2005/04/29 00:16:46 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include <config.h> @@ -81,7 +82,7 @@ static char rcsid[] = "$ISC: inet_aton.c,v 1.15.12.3 2004/03/08 09:04:49 marka E #include <isc/types.h> #include <isc/net.h> -/* +/*% * Check whether "cp" is a valid ascii representation * of an Internet address and convert to a binary address. * Returns 1 if the address is valid, 0 if not. diff --git a/usr.sbin/bind/lib/isc/inet_ntop.c b/usr.sbin/bind/lib/isc/inet_ntop.c index daa94209f03..13fdfa54e20 100644 --- a/usr.sbin/bind/lib/isc/inet_ntop.c +++ b/usr.sbin/bind/lib/isc/inet_ntop.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1996-2001 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,9 +15,11 @@ * PERFORMANCE OF THIS SOFTWARE. */ +/*! \file */ + #if defined(LIBC_SCCS) && !defined(lint) static char rcsid[] = - "$ISC: inet_ntop.c,v 1.12.12.4 2004/08/28 06:25:21 marka Exp $"; + "$ISC: inet_ntop.c,v 1.14.18.3 2005/04/29 00:16:46 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include <config.h> @@ -45,12 +47,12 @@ static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size); #endif -/* char * +/*! char * * isc_net_ntop(af, src, dst, size) * convert a network format address to presentation format. - * return: + * \return * pointer to presentation format address (`dst'), or NULL (see errno). - * author: + * \author * Paul Vixie, 1996. */ const char * @@ -70,15 +72,16 @@ isc_net_ntop(int af, const void *src, char *dst, size_t size) /* NOTREACHED */ } -/* const char * +/*! const char * * inet_ntop4(src, dst, size) * format an IPv4 address - * return: + * \return * `dst' (as a const) - * notes: + * \note * (1) uses no statics + * \note * (2) takes a unsigned char* not an in_addr as input - * author: + * \author * Paul Vixie, 1996. */ static const char * @@ -97,10 +100,10 @@ inet_ntop4(const unsigned char *src, char *dst, size_t size) return (dst); } -/* const char * +/*! const char * * isc_inet_ntop6(src, dst, size) * convert IPv6 binary address into presentation (printable) format - * author: + * \author * Paul Vixie, 1996. */ #ifdef AF_INET6 diff --git a/usr.sbin/bind/lib/isc/inet_pton.c b/usr.sbin/bind/lib/isc/inet_pton.c index 75b8c4161bc..c45819c52dd 100644 --- a/usr.sbin/bind/lib/isc/inet_pton.c +++ b/usr.sbin/bind/lib/isc/inet_pton.c @@ -15,9 +15,11 @@ * PERFORMANCE OF THIS SOFTWARE. */ +/*! \file */ + #if defined(LIBC_SCCS) && !defined(lint) static char rcsid[] = - "$ISC: inet_pton.c,v 1.10.2.4.2.3 2005/03/31 23:56:14 marka Exp $"; + "$ISC: inet_pton.c,v 1.13.18.4 2005/04/29 00:16:46 marka Exp $"; #endif /* LIBC_SCCS and not lint */ #include <config.h> @@ -27,8 +29,11 @@ static char rcsid[] = #include <isc/net.h> +/*% INT16 Size */ #define NS_INT16SZ 2 +/*% IPv4 Address Size */ #define NS_INADDRSZ 4 +/*% IPv6 Address Size */ #define NS_IN6ADDRSZ 16 /* @@ -39,15 +44,14 @@ static char rcsid[] = static int inet_pton4(const char *src, unsigned char *dst); static int inet_pton6(const char *src, unsigned char *dst); -/* int - * isc_net_pton(af, src, dst) +/*% * convert from presentation format (which usually means ASCII printable) * to network format (which is usually some kind of binary format). - * return: + * \return * 1 if the address was valid for the specified address family * 0 if the address wasn't valid (`dst' is untouched in this case) * -1 if some other error occurred (`dst' is untouched in this case, too) - * author: + * \author * Paul Vixie, 1996. */ int @@ -64,14 +68,14 @@ isc_net_pton(int af, const char *src, void *dst) { /* NOTREACHED */ } -/* int - * inet_pton4(src, dst) +/*!\fn static int inet_pton4(const char *src, unsigned char *dst) + * \brief * like inet_aton() but without all the hexadecimal and shorthand. - * return: + * \return * 1 if `src' is a valid dotted quad, else 0. - * notice: + * \note * does not touch `dst' unless it's returning 1. - * author: + * \author * Paul Vixie, 1996. */ static int @@ -113,17 +117,17 @@ inet_pton4(const char *src, unsigned char *dst) { return (1); } -/* int - * inet_pton6(src, dst) +/*% * convert presentation level address to network order binary form. - * return: + * \return * 1 if `src' is a valid [RFC1884 2.2] address, else 0. - * notice: + * \note * (1) does not touch `dst' unless it's returning 1. + * \note * (2) :: in a full address is silently ignored. - * credit: + * \author * inspired by Mark Andrews. - * author: + * \author * Paul Vixie, 1996. */ static int diff --git a/usr.sbin/bind/lib/isc/lex.c b/usr.sbin/bind/lib/isc/lex.c index ac355926bc6..ae98ac92fc0 100644 --- a/usr.sbin/bind/lib/isc/lex.c +++ b/usr.sbin/bind/lib/isc/lex.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,9 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: lex.c,v 1.66.2.6.2.10 2006/01/04 23:50:21 marka Exp $ */ +/* $ISC: lex.c,v 1.78.18.5 2005/11/30 03:44:39 marka Exp $ */ + +/*! \file */ #include <config.h> @@ -563,7 +565,11 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { } else if (isdigit((unsigned char)c) && (options & ISC_LEXOPT_NUMBER) != 0) { lex->last_was_eol = ISC_FALSE; - state = lexstate_number; + if ((options & ISC_LEXOPT_OCTAL) != 0 && + (c == '8' || c == '9')) + state = lexstate_string; + else + state = lexstate_number; goto no_read; } else { lex->last_was_eol = ISC_FALSE; @@ -584,7 +590,9 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { c == '\n' || c == EOF || lex->specials[c]) { int base; - if ((options & ISC_LEXOPT_CNUMBER) != 0) + if ((options & ISC_LEXOPT_OCTAL) != 0) + base = 8; + else if ((options & ISC_LEXOPT_CNUMBER) != 0) base = 0; else base = 10; @@ -620,6 +628,9 @@ isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) { /* Above test supports hex numbers */ state = lexstate_string; } + } else if ((options & ISC_LEXOPT_OCTAL) != 0 && + (c == '8' || c == '9')) { + state = lexstate_string; } if (remaining == 0U) { result = grow_data(lex, &remaining, @@ -821,6 +832,33 @@ isc_lex_getmastertoken(isc_lex_t *lex, isc_token_t *token, return (ISC_R_SUCCESS); } +isc_result_t +isc_lex_getoctaltoken(isc_lex_t *lex, isc_token_t *token, isc_boolean_t eol) +{ + unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | + ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE| + ISC_LEXOPT_NUMBER | ISC_LEXOPT_OCTAL; + isc_result_t result; + + result = isc_lex_gettoken(lex, options, token); + if (result == ISC_R_RANGE) + isc_lex_ungettoken(lex, token); + if (result != ISC_R_SUCCESS) + return (result); + + if (eol && ((token->type == isc_tokentype_eol) || + (token->type == isc_tokentype_eof))) + return (ISC_R_SUCCESS); + if (token->type != isc_tokentype_number) { + isc_lex_ungettoken(lex, token); + if (token->type == isc_tokentype_eol || + token->type == isc_tokentype_eof) + return (ISC_R_UNEXPECTEDEND); + return (ISC_R_BADNUMBER); + } + return (ISC_R_SUCCESS); +} + void isc_lex_ungettoken(isc_lex_t *lex, isc_token_t *tokenp) { inputsource *source; diff --git a/usr.sbin/bind/lib/isc/lfsr.c b/usr.sbin/bind/lib/isc/lfsr.c index c317744b3a1..2792156466d 100644 --- a/usr.sbin/bind/lib/isc/lfsr.c +++ b/usr.sbin/bind/lib/isc/lfsr.c @@ -15,7 +15,9 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: lfsr.c,v 1.11.2.2.2.6 2005/10/14 01:38:50 marka Exp $ */ +/* $ISC: lfsr.c,v 1.14.18.4 2005/10/14 01:28:29 marka Exp $ */ + +/*! \file */ #include <config.h> @@ -50,7 +52,7 @@ isc_lfsr_init(isc_lfsr_t *lfsr, isc_uint32_t state, unsigned int bits, lfsr->state = 0xffffffffU >> (32 - lfsr->bits); } -/* +/*! * Return the next state of the lfsr. */ static inline isc_uint32_t diff --git a/usr.sbin/bind/lib/isc/log.c b/usr.sbin/bind/lib/isc/log.c index 68f27152290..b7433cb7049 100644 --- a/usr.sbin/bind/lib/isc/log.c +++ b/usr.sbin/bind/lib/isc/log.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,9 +15,10 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: log.c,v 1.70.2.8.2.14 2006/03/02 00:37:20 marka Exp $ */ +/* $ISC: log.c,v 1.84.18.8 2006/03/02 00:37:22 marka Exp $ */ -/* Principal Authors: DCL */ +/*! \file + * \author Principal Authors: DCL */ #include <config.h> @@ -56,7 +57,7 @@ #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 * found by doing strcmp()s with the names down the list. Their should @@ -76,7 +77,7 @@ struct isc_logchannel { ISC_LINK(isc_logchannel_t) link; }; -/* +/*! * The logchannellist structure associates categories and modules with * channels. First the appropriate channellist is found based on the * category, and then each structure in the linked list is checked for @@ -92,7 +93,7 @@ struct isc_logchannellist { ISC_LINK(isc_logchannellist_t) link; }; -/* +/*! * This structure is used to remember messages for pruning via * isc_log_[v]write1(). */ @@ -104,7 +105,7 @@ struct isc_logmessage { ISC_LINK(isc_logmessage_t) link; }; -/* +/*! * The isc_logconfig structure is used to store the configurable information * about where messages are actually supposed to be sent -- the information * that could changed based on some configuration file, as opposed to the @@ -123,7 +124,7 @@ struct isc_logconfig { isc_boolean_t dynamic; }; -/* +/*! * This isc_log structure provides the context for the isc_log functions. * The log context locks itself in isc_log_doit, the internal backend to * isc_log_write. The locking is necessary both to provide exclusive access @@ -156,7 +157,7 @@ struct isc_log { ISC_LIST(isc_logmessage_t) messages; }; -/* +/*! * Used when ISC_LOG_PRINTLEVEL is enabled for a channel. */ static const char *log_level_strings[] = { @@ -168,7 +169,7 @@ static const char *log_level_strings[] = { "critical" }; -/* +/*! * Used to convert ISC_LOG_* priorities into syslog priorities. * XXXDCL This will need modification for NT. */ @@ -181,7 +182,7 @@ static const int syslog_map[] = { LOG_CRIT }; -/* +/*! * When adding new categories, a corresponding ISC_LOGCATEGORY_foo * definition needs to be added to <isc/log.h>. * @@ -195,8 +196,8 @@ LIBISC_EXTERNAL_DATA isc_logcategory_t isc_categories[] = { { NULL, 0 } }; -/* - * See above comment for categories, and apply it to modules. +/*! + * See above comment for categories on LIBISC_EXTERNAL_DATA, and apply it to modules. */ LIBISC_EXTERNAL_DATA isc_logmodule_t isc_modules[] = { { "socket", 0 }, @@ -206,19 +207,19 @@ LIBISC_EXTERNAL_DATA isc_logmodule_t isc_modules[] = { { NULL, 0 } }; -/* +/*! * This essentially constant structure must be filled in at run time, * because its channel member is pointed to a channel that is created * dynamically with isc_log_createchannel. */ static isc_logchannellist_t default_channel; -/* +/*! * libisc logs to this context. */ LIBISC_EXTERNAL_DATA isc_log_t *isc_lctx = NULL; -/* +/*! * Forward declarations. */ static isc_result_t @@ -241,7 +242,8 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category, const char *format, va_list args) ISC_FORMAT_PRINTF(9, 0); -/* +/*@{*/ +/*! * Convenience macros. */ @@ -252,6 +254,7 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category, #define FILE_MAXSIZE(channel) (channel->destination.file.maximum_size) #define FILE_MAXREACHED(channel) (channel->destination.file.maximum_reached) +/*@}*/ /**** **** Public interfaces. ****/ @@ -280,7 +283,11 @@ isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp) { ISC_LIST_INIT(lctx->messages); - RUNTIME_CHECK(isc_mutex_init(&lctx->lock) == ISC_R_SUCCESS); + result = isc_mutex_init(&lctx->lock); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, lctx, sizeof(*lctx)); + return (result); + } /* * Normally setting the magic number is the last step done diff --git a/usr.sbin/bind/lib/isc/mem.c b/usr.sbin/bind/lib/isc/mem.c index 4a5ea4b33df..f7533b9b949 100644 --- a/usr.sbin/bind/lib/isc/mem.c +++ b/usr.sbin/bind/lib/isc/mem.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1997-2003 Internet Software Consortium. * - * Permission to use, copy, modify, and distribute this software for any + * Permission to use, copy, modify, and/or 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. * @@ -15,7 +15,9 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: mem.c,v 1.98.2.7.2.7 2005/03/17 03:58:32 marka Exp $ */ +/* $ISC: mem.c,v 1.116.18.18 2007/10/30 23:31:43 marka Exp $ */ + +/*! \file */ #include <config.h> @@ -28,35 +30,29 @@ #include <isc/magic.h> #include <isc/mem.h> #include <isc/msgs.h> +#include <isc/once.h> #include <isc/ondestroy.h> #include <isc/string.h> #include <isc/mutex.h> #include <isc/util.h> +#define MCTXLOCK(m, l) if (((m)->flags & ISC_MEMFLAG_NOLOCK) == 0) LOCK(l) +#define MCTXUNLOCK(m, l) if (((m)->flags & ISC_MEMFLAG_NOLOCK) == 0) UNLOCK(l) + #ifndef ISC_MEM_DEBUGGING #define ISC_MEM_DEBUGGING 0 #endif LIBISC_EXTERNAL_DATA unsigned int isc_mem_debugging = ISC_MEM_DEBUGGING; /* - * Define ISC_MEM_USE_INTERNAL_MALLOC=1 to use the internal malloc() - * implementation in preference to the system one. The internal malloc() - * is very space-efficient, and quite fast on uniprocessor systems. It - * performs poorly on multiprocessor machines. - */ -#ifndef ISC_MEM_USE_INTERNAL_MALLOC -#define ISC_MEM_USE_INTERNAL_MALLOC 0 -#endif - -/* * Constants. */ #define DEF_MAX_SIZE 1100 #define DEF_MEM_TARGET 4096 -#define ALIGNMENT_SIZE 8 /* must be a power of 2 */ -#define NUM_BASIC_BLOCKS 64 /* must be > 1 */ +#define ALIGNMENT_SIZE 8 /*%< must be a power of 2 */ +#define NUM_BASIC_BLOCKS 64 /*%< must be > 1 */ #define TABLE_INCREMENT 1024 #define DEBUGLIST_COUNT 1024 @@ -87,11 +83,12 @@ struct element { }; typedef struct { - /* + /*! * This structure must be ALIGNMENT_SIZE bytes. */ union { size_t size; + isc_mem_t *ctx; char bytes[ALIGNMENT_SIZE]; } u; } size_info; @@ -99,10 +96,8 @@ typedef struct { struct stats { unsigned long gets; unsigned long totalgets; -#if ISC_MEM_USE_INTERNAL_MALLOC unsigned long blocks; unsigned long freefrags; -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ }; #define MEM_MAGIC ISC_MAGIC('M', 'e', 'm', 'C') @@ -112,9 +107,16 @@ struct stats { typedef ISC_LIST(debuglink_t) debuglist_t; #endif +/* List of all active memory contexts. */ + +static ISC_LIST(isc_mem_t) contexts; +static isc_once_t once = ISC_ONCE_INIT; +static isc_mutex_t lock; + struct isc_mem { unsigned int magic; isc_ondestroy_t ondestroy; + unsigned int flags; isc_mutex_t lock; isc_memalloc_t memalloc; isc_memfree_t memfree; @@ -134,7 +136,7 @@ struct isc_mem { void * water_arg; ISC_LIST(isc_mempool_t) pools; -#if ISC_MEM_USE_INTERNAL_MALLOC + /* ISC_MEMFLAG_INTERNAL */ size_t mem_target; element ** freelists; element * basic_blocks; @@ -143,13 +145,13 @@ struct isc_mem { unsigned int basic_table_size; unsigned char * lowest; unsigned char * highest; -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ #if ISC_MEM_TRACKLINES debuglist_t * debuglist; #endif unsigned int memalloc_failures; + ISC_LINK(isc_mem_t) link; }; #define MEMPOOL_MAGIC ISC_MAGIC('M', 'E', 'M', 'p') @@ -157,24 +159,24 @@ struct isc_mem { struct isc_mempool { /* always unlocked */ - unsigned int magic; /* magic number */ - isc_mutex_t *lock; /* optional lock */ - isc_mem_t *mctx; /* our memory context */ - /* locked via the memory context's lock */ - ISC_LINK(isc_mempool_t) link; /* next pool in this mem context */ - /* optionally locked from here down */ - element *items; /* low water item list */ - size_t size; /* size of each item on this pool */ - unsigned int maxalloc; /* max number of items allowed */ - unsigned int allocated; /* # of items currently given out */ - unsigned int freecount; /* # of items on reserved list */ - unsigned int freemax; /* # of items allowed on free list */ - unsigned int fillcount; /* # of items to fetch on each fill */ - /* Stats only. */ - unsigned int gets; /* # of requests to this pool */ - /* Debugging only. */ + unsigned int magic; /*%< magic number */ + isc_mutex_t *lock; /*%< optional lock */ + isc_mem_t *mctx; /*%< our memory context */ + /*%< locked via the memory context's lock */ + ISC_LINK(isc_mempool_t) link; /*%< next pool in this mem context */ + /*%< optionally locked from here down */ + element *items; /*%< low water item list */ + size_t size; /*%< size of each item on this pool */ + unsigned int maxalloc; /*%< max number of items allowed */ + unsigned int allocated; /*%< # of items currently given out */ + unsigned int freecount; /*%< # of items on reserved list */ + unsigned int freemax; /*%< # of items allowed on free list */ + unsigned int fillcount; /*%< # of items to fetch on each fill */ + /*%< Stats only. */ + unsigned int gets; /*%< # of requests to this pool */ + /*%< Debugging only. */ #if ISC_MEMPOOL_NAMES - char name[16]; /* printed name in stats reports */ + char name[16]; /*%< printed name in stats reports */ #endif }; @@ -198,7 +200,7 @@ struct isc_mempool { static void print_active(isc_mem_t *ctx, FILE *out); -/* +/*! * mctx must be locked. */ static inline void @@ -309,7 +311,6 @@ delete_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size, } #endif /* ISC_MEM_TRACKLINES */ -#if ISC_MEM_USE_INTERNAL_MALLOC static inline size_t rmsize(size_t size) { /* @@ -320,13 +321,13 @@ rmsize(size_t size) { static inline size_t quantize(size_t size) { - /* + /*! * Round up the result in order to get a size big * enough to satisfy the request and be aligned on ALIGNMENT_SIZE * byte boundaries. */ - if (size == 0) + if (size == 0U) return (ALIGNMENT_SIZE); return ((size + ALIGNMENT_SIZE - 1) & (~(ALIGNMENT_SIZE - 1))); } @@ -347,7 +348,7 @@ more_basic_blocks(isc_mem_t *ctx) { * Did we hit the quota for this context? */ increment = NUM_BASIC_BLOCKS * ctx->mem_target; - if (ctx->quota != 0 && ctx->total + increment > ctx->quota) + if (ctx->quota != 0U && ctx->total + increment > ctx->quota) return (ISC_FALSE); INSIST(ctx->basic_table_count <= ctx->basic_table_size); @@ -408,7 +409,7 @@ more_frags(isc_mem_t *ctx, size_t new_size) { void *new; unsigned char *curr, *next; - /* + /*! * Try to get more fragments by chopping up a basic block. */ @@ -448,7 +449,7 @@ more_frags(isc_mem_t *ctx, size_t new_size) { * Add the remaining fragment of the basic block to a free list. */ total_size = rmsize(total_size); - if (total_size > 0) { + if (total_size > 0U) { ((element *)next)->next = ctx->freelists[total_size]; ctx->freelists[total_size] = (element *)next; ctx->stats[total_size].freefrags++; @@ -472,7 +473,7 @@ mem_getunlocked(isc_mem_t *ctx, size_t size) { /* * memget() was called on something beyond our upper limit. */ - if (ctx->quota != 0 && ctx->total + size > ctx->quota) { + if (ctx->quota != 0U && ctx->total + size > ctx->quota) { ret = NULL; goto done; } @@ -556,7 +557,7 @@ mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) { memset(mem, 0xde, size); /* Mnemonic for "dead". */ #endif (ctx->memfree)(ctx->arg, mem); - INSIST(ctx->stats[ctx->max_size].gets != 0); + INSIST(ctx->stats[ctx->max_size].gets != 0U); ctx->stats[ctx->max_size].gets--; INSIST(size <= ctx->total); ctx->inuse -= size; @@ -583,15 +584,13 @@ mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) { * max. size (max_size) ends up getting recorded as a call to * max_size. */ - INSIST(ctx->stats[size].gets != 0); + INSIST(ctx->stats[size].gets != 0U); ctx->stats[size].gets--; ctx->stats[new_size].freefrags++; ctx->inuse -= new_size; } -#else /* ISC_MEM_USE_INTERNAL_MALLOC */ - -/* +/*! * Perform a malloc, doing memory filling and overrun detection as necessary. */ static inline void * @@ -619,7 +618,7 @@ mem_get(isc_mem_t *ctx, size_t size) { return (ret); } -/* +/*! * Perform a free, doing memory filling and overrun detection as necessary. */ static inline void @@ -635,7 +634,7 @@ mem_put(isc_mem_t *ctx, void *mem, size_t size) { (ctx->memfree)(ctx->arg, mem); } -/* +/*! * Update internal counters after a memory get. */ static inline void @@ -652,7 +651,7 @@ mem_getstats(isc_mem_t *ctx, size_t size) { } } -/* +/*! * Update internal counters after a memory put. */ static inline void @@ -671,8 +670,6 @@ mem_putstats(isc_mem_t *ctx, void *ptr, size_t size) { } } -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ - /* * Private. */ @@ -691,6 +688,12 @@ default_memfree(void *arg, void *ptr) { free(ptr); } +static void +initialize_action(void) { + RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS); + ISC_LIST_INIT(contexts); +} + /* * Public. */ @@ -700,6 +703,16 @@ isc_mem_createx(size_t init_max_size, size_t target_size, isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg, isc_mem_t **ctxp) { + return (isc_mem_createx2(init_max_size, target_size, memalloc, memfree, + arg, ctxp, ISC_MEMFLAG_DEFAULT)); + +} + +isc_result_t +isc_mem_createx2(size_t init_max_size, size_t target_size, + isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg, + isc_mem_t **ctxp, unsigned int flags) +{ isc_mem_t *ctx; isc_result_t result; @@ -709,27 +722,25 @@ isc_mem_createx(size_t init_max_size, size_t target_size, INSIST((ALIGNMENT_SIZE & (ALIGNMENT_SIZE - 1)) == 0); -#if !ISC_MEM_USE_INTERNAL_MALLOC - UNUSED(target_size); -#endif + RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS); ctx = (memalloc)(arg, sizeof(*ctx)); if (ctx == NULL) return (ISC_R_NOMEMORY); - if (isc_mutex_init(&ctx->lock) != ISC_R_SUCCESS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_mutex_init() %s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed")); - (memfree)(arg, ctx); - return (ISC_R_UNEXPECTED); + if ((flags & ISC_MEMFLAG_NOLOCK) == 0) { + result = isc_mutex_init(&ctx->lock); + if (result != ISC_R_SUCCESS) { + (memfree)(arg, ctx); + return (result); + } } if (init_max_size == 0U) ctx->max_size = DEF_MAX_SIZE; else ctx->max_size = init_max_size; + ctx->flags = flags; ctx->references = 1; ctx->quota = 0; ctx->total = 0; @@ -751,10 +762,13 @@ isc_mem_createx(size_t init_max_size, size_t target_size, ctx->debuglist = NULL; #endif ISC_LIST_INIT(ctx->pools); - -#if ISC_MEM_USE_INTERNAL_MALLOC ctx->freelists = NULL; -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ + ctx->basic_blocks = NULL; + ctx->basic_table = NULL; + ctx->basic_table_count = 0; + ctx->basic_table_size = 0; + ctx->lowest = NULL; + ctx->highest = NULL; ctx->stats = (memalloc)(arg, (ctx->max_size+1) * sizeof(struct stats)); @@ -764,25 +778,20 @@ isc_mem_createx(size_t init_max_size, size_t target_size, } memset(ctx->stats, 0, (ctx->max_size + 1) * sizeof(struct stats)); -#if ISC_MEM_USE_INTERNAL_MALLOC - if (target_size == 0) - ctx->mem_target = DEF_MEM_TARGET; - else - ctx->mem_target = target_size; - ctx->freelists = (memalloc)(arg, ctx->max_size * sizeof(element *)); - if (ctx->freelists == NULL) { - result = ISC_R_NOMEMORY; - goto error; + if ((flags & ISC_MEMFLAG_INTERNAL) != 0) { + if (target_size == 0U) + ctx->mem_target = DEF_MEM_TARGET; + else + ctx->mem_target = target_size; + ctx->freelists = (memalloc)(arg, ctx->max_size * + sizeof(element *)); + if (ctx->freelists == NULL) { + result = ISC_R_NOMEMORY; + goto error; + } + memset(ctx->freelists, 0, + ctx->max_size * sizeof(element *)); } - memset(ctx->freelists, 0, - ctx->max_size * sizeof(element *)); - ctx->basic_blocks = NULL; - ctx->basic_table = NULL; - ctx->basic_table_count = 0; - ctx->basic_table_size = 0; - ctx->lowest = NULL; - ctx->highest = NULL; -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ #if ISC_MEM_TRACKLINES if ((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0) { @@ -801,6 +810,10 @@ isc_mem_createx(size_t init_max_size, size_t target_size, ctx->memalloc_failures = 0; + LOCK(&lock); + ISC_LIST_INITANDAPPEND(contexts, ctx, link); + UNLOCK(&lock); + *ctxp = ctx; return (ISC_R_SUCCESS); @@ -808,15 +821,14 @@ isc_mem_createx(size_t init_max_size, size_t target_size, if (ctx != NULL) { if (ctx->stats != NULL) (memfree)(arg, ctx->stats); -#if ISC_MEM_USE_INTERNAL_MALLOC if (ctx->freelists != NULL) (memfree)(arg, ctx->freelists); -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ #if ISC_MEM_TRACKLINES if (ctx->debuglist != NULL) (ctx->memfree)(ctx->arg, ctx->debuglist); #endif /* ISC_MEM_TRACKLINES */ - DESTROYLOCK(&ctx->lock); + if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0) + DESTROYLOCK(&ctx->lock); (memfree)(arg, ctx); } @@ -827,9 +839,18 @@ isc_result_t isc_mem_create(size_t init_max_size, size_t target_size, isc_mem_t **ctxp) { - return (isc_mem_createx(init_max_size, target_size, - default_memalloc, default_memfree, NULL, - ctxp)); + return (isc_mem_createx2(init_max_size, target_size, + default_memalloc, default_memfree, NULL, + ctxp, ISC_MEMFLAG_DEFAULT)); +} + +isc_result_t +isc_mem_create2(size_t init_max_size, size_t target_size, + isc_mem_t **ctxp, unsigned int flags) +{ + return (isc_mem_createx2(init_max_size, target_size, + default_memalloc, default_memfree, NULL, + ctxp, flags)); } static void @@ -839,9 +860,11 @@ destroy(isc_mem_t *ctx) { ctx->magic = 0; -#if ISC_MEM_USE_INTERNAL_MALLOC + LOCK(&lock); + ISC_LIST_UNLINK(contexts, ctx, link); + UNLOCK(&lock); + INSIST(ISC_LIST_EMPTY(ctx->pools)); -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ #if ISC_MEM_TRACKLINES if (ctx->debuglist != NULL) { @@ -880,16 +903,17 @@ destroy(isc_mem_t *ctx) { (ctx->memfree)(ctx->arg, ctx->stats); -#if ISC_MEM_USE_INTERNAL_MALLOC - for (i = 0; i < ctx->basic_table_count; i++) - (ctx->memfree)(ctx->arg, ctx->basic_table[i]); - (ctx->memfree)(ctx->arg, ctx->freelists); - (ctx->memfree)(ctx->arg, ctx->basic_table); -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ + if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) { + for (i = 0; i < ctx->basic_table_count; i++) + (ctx->memfree)(ctx->arg, ctx->basic_table[i]); + (ctx->memfree)(ctx->arg, ctx->freelists); + (ctx->memfree)(ctx->arg, ctx->basic_table); + } ondest = ctx->ondestroy; - DESTROYLOCK(&ctx->lock); + if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0) + DESTROYLOCK(&ctx->lock); (ctx->memfree)(ctx->arg, ctx); isc_ondestroy_notify(&ondest, ctx); @@ -900,9 +924,9 @@ isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) { REQUIRE(VALID_CONTEXT(source)); REQUIRE(targetp != NULL && *targetp == NULL); - LOCK(&source->lock); + MCTXLOCK(source, &source->lock); source->references++; - UNLOCK(&source->lock); + MCTXUNLOCK(source, &source->lock); *targetp = source; } @@ -916,12 +940,12 @@ isc_mem_detach(isc_mem_t **ctxp) { ctx = *ctxp; REQUIRE(VALID_CONTEXT(ctx)); - LOCK(&ctx->lock); + MCTXLOCK(ctx, &ctx->lock); INSIST(ctx->references > 0); ctx->references--; if (ctx->references == 0) want_destroy = ISC_TRUE; - UNLOCK(&ctx->lock); + MCTXUNLOCK(ctx, &ctx->lock); if (want_destroy) destroy(ctx); @@ -943,6 +967,8 @@ void isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) { isc_mem_t *ctx; isc_boolean_t want_destroy = ISC_FALSE; + size_info *si; + size_t oldsize; REQUIRE(ctxp != NULL); ctx = *ctxp; @@ -955,14 +981,35 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) { */ *ctxp = NULL; -#if ISC_MEM_USE_INTERNAL_MALLOC - LOCK(&ctx->lock); - mem_putunlocked(ctx, ptr, size); -#else /* ISC_MEM_USE_INTERNAL_MALLOC */ - mem_put(ctx, ptr, size); - LOCK(&ctx->lock); - mem_putstats(ctx, ptr, size); -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ + if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) { + if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) { + si = &(((size_info *)ptr)[-1]); + oldsize = si->u.size - ALIGNMENT_SIZE; + if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) + oldsize -= ALIGNMENT_SIZE; + INSIST(oldsize == size); + } + isc__mem_free(ctx, ptr FLARG_PASS); + + MCTXLOCK(ctx, &ctx->lock); + ctx->references--; + if (ctx->references == 0) + want_destroy = ISC_TRUE; + MCTXUNLOCK(ctx, &ctx->lock); + if (want_destroy) + destroy(ctx); + + return; + } + + if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) { + MCTXLOCK(ctx, &ctx->lock); + mem_putunlocked(ctx, ptr, size); + } else { + mem_put(ctx, ptr, size); + MCTXLOCK(ctx, &ctx->lock); + mem_putstats(ctx, ptr, size); + } DELETE_TRACE(ctx, ptr, size, file, line); INSIST(ctx->references > 0); @@ -970,7 +1017,7 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) { if (ctx->references == 0) want_destroy = ISC_TRUE; - UNLOCK(&ctx->lock); + MCTXUNLOCK(ctx, &ctx->lock); if (want_destroy) destroy(ctx); @@ -989,14 +1036,14 @@ isc_mem_destroy(isc_mem_t **ctxp) { ctx = *ctxp; REQUIRE(VALID_CONTEXT(ctx)); - LOCK(&ctx->lock); + MCTXLOCK(ctx, &ctx->lock); #if ISC_MEM_TRACKLINES if (ctx->references != 1) print_active(ctx, stderr); #endif REQUIRE(ctx->references == 1); ctx->references--; - UNLOCK(&ctx->lock); + MCTXUNLOCK(ctx, &ctx->lock); destroy(ctx); @@ -1007,9 +1054,9 @@ isc_result_t isc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) { isc_result_t res; - LOCK(&ctx->lock); + MCTXLOCK(ctx, &ctx->lock); res = isc_ondestroy_register(&ctx->ondestroy, task, event); - UNLOCK(&ctx->lock); + MCTXUNLOCK(ctx, &ctx->lock); return (res); } @@ -1022,15 +1069,18 @@ isc__mem_get(isc_mem_t *ctx, size_t size FLARG) { REQUIRE(VALID_CONTEXT(ctx)); -#if ISC_MEM_USE_INTERNAL_MALLOC - LOCK(&ctx->lock); - ptr = mem_getunlocked(ctx, size); -#else /* ISC_MEM_USE_INTERNAL_MALLOC */ - ptr = mem_get(ctx, size); - LOCK(&ctx->lock); - if (ptr != NULL) - mem_getstats(ctx, size); -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ + if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) + return (isc__mem_allocate(ctx, size FLARG_PASS)); + + if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) { + MCTXLOCK(ctx, &ctx->lock); + ptr = mem_getunlocked(ctx, size); + } else { + ptr = mem_get(ctx, size); + MCTXLOCK(ctx, &ctx->lock); + if (ptr != NULL) + mem_getstats(ctx, size); + } ADD_TRACE(ctx, ptr, size, file, line); if (ctx->hi_water != 0U && !ctx->hi_called && @@ -1045,7 +1095,7 @@ isc__mem_get(isc_mem_t *ctx, size_t size FLARG) { fprintf(stderr, "maxinuse = %lu\n", (unsigned long)ctx->inuse); } - UNLOCK(&ctx->lock); + MCTXUNLOCK(ctx, &ctx->lock); if (call_water) (ctx->water)(ctx->water_arg, ISC_MEM_HIWATER); @@ -1057,18 +1107,32 @@ void isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG) { isc_boolean_t call_water = ISC_FALSE; + size_info *si; + size_t oldsize; REQUIRE(VALID_CONTEXT(ctx)); REQUIRE(ptr != NULL); -#if ISC_MEM_USE_INTERNAL_MALLOC - LOCK(&ctx->lock); - mem_putunlocked(ctx, ptr, size); -#else /* ISC_MEM_USE_INTERNAL_MALLOC */ - mem_put(ctx, ptr, size); - LOCK(&ctx->lock); - mem_putstats(ctx, ptr, size); -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ + if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) { + if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) { + si = &(((size_info *)ptr)[-1]); + oldsize = si->u.size - ALIGNMENT_SIZE; + if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) + oldsize -= ALIGNMENT_SIZE; + INSIST(oldsize == size); + } + isc__mem_free(ctx, ptr FLARG_PASS); + return; + } + + if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) { + MCTXLOCK(ctx, &ctx->lock); + mem_putunlocked(ctx, ptr, size); + } else { + mem_put(ctx, ptr, size); + MCTXLOCK(ctx, &ctx->lock); + mem_putstats(ctx, ptr, size); + } DELETE_TRACE(ctx, ptr, size, file, line); @@ -1084,7 +1148,7 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG) if (ctx->water != NULL) call_water = ISC_TRUE; } - UNLOCK(&ctx->lock); + MCTXUNLOCK(ctx, &ctx->lock); if (call_water) (ctx->water)(ctx->water_arg, ISC_MEM_LOWATER); @@ -1141,7 +1205,7 @@ isc_mem_stats(isc_mem_t *ctx, FILE *out) { const isc_mempool_t *pool; REQUIRE(VALID_CONTEXT(ctx)); - LOCK(&ctx->lock); + MCTXLOCK(ctx, &ctx->lock); for (i = 0; i <= ctx->max_size; i++) { s = &ctx->stats[i]; @@ -1151,11 +1215,10 @@ isc_mem_stats(isc_mem_t *ctx, FILE *out) { fprintf(out, "%s%5lu: %11lu gets, %11lu rem", (i == ctx->max_size) ? ">=" : " ", (unsigned long) i, s->totalgets, s->gets); -#if ISC_MEM_USE_INTERNAL_MALLOC - if (s->blocks != 0 || s->freefrags != 0) + if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0 && + (s->blocks != 0U || s->freefrags != 0U)) fprintf(out, " (%lu bl, %lu ff)", s->blocks, s->freefrags); -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ fputc('\n', out); } @@ -1203,7 +1266,7 @@ isc_mem_stats(isc_mem_t *ctx, FILE *out) { print_active(ctx, out); #endif - UNLOCK(&ctx->lock); + MCTXUNLOCK(ctx, &ctx->lock); } /* @@ -1216,13 +1279,20 @@ isc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) { size_info *si; size += ALIGNMENT_SIZE; -#if ISC_MEM_USE_INTERNAL_MALLOC - si = mem_getunlocked(ctx, size); -#else /* ISC_MEM_USE_INTERNAL_MALLOC */ - si = mem_get(ctx, size); -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ + if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) + size += ALIGNMENT_SIZE; + + if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) + si = mem_getunlocked(ctx, size); + else + si = mem_get(ctx, size); + if (si == NULL) return (NULL); + if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) { + si->u.ctx = ctx; + si++; + } si->u.size = size; return (&si[1]); } @@ -1230,24 +1300,39 @@ isc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) { void * isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) { size_info *si; + isc_boolean_t call_water = ISC_FALSE; REQUIRE(VALID_CONTEXT(ctx)); -#if ISC_MEM_USE_INTERNAL_MALLOC - LOCK(&ctx->lock); - si = isc__mem_allocateunlocked(ctx, size); -#else /* ISC_MEM_USE_INTERNAL_MALLOC */ - si = isc__mem_allocateunlocked(ctx, size); - LOCK(&ctx->lock); - if (si != NULL) - mem_getstats(ctx, si[-1].u.size); -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ + if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) { + MCTXLOCK(ctx, &ctx->lock); + si = isc__mem_allocateunlocked(ctx, size); + } else { + si = isc__mem_allocateunlocked(ctx, size); + MCTXLOCK(ctx, &ctx->lock); + if (si != NULL) + mem_getstats(ctx, si[-1].u.size); + } #if ISC_MEM_TRACKLINES ADD_TRACE(ctx, si, si[-1].u.size, file, line); #endif + 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 != 0U && ctx->inuse > ctx->hi_water && + (isc_mem_debugging & ISC_MEM_DEBUGUSAGE) != 0) + fprintf(stderr, "maxinuse = %lu\n", + (unsigned long)ctx->inuse); + } + MCTXUNLOCK(ctx, &ctx->lock); - UNLOCK(&ctx->lock); + if (call_water) + (ctx->water)(ctx->water_arg, ISC_MEM_HIWATER); return (si); } @@ -1256,25 +1341,47 @@ void isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) { size_info *si; size_t size; + isc_boolean_t call_water= ISC_FALSE; REQUIRE(VALID_CONTEXT(ctx)); REQUIRE(ptr != NULL); - si = &(((size_info *)ptr)[-1]); - size = si->u.size; + if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) { + si = &(((size_info *)ptr)[-2]); + REQUIRE(si->u.ctx == ctx); + size = si[1].u.size; + } else { + si = &(((size_info *)ptr)[-1]); + size = si->u.size; + } -#if ISC_MEM_USE_INTERNAL_MALLOC - LOCK(&ctx->lock); - mem_putunlocked(ctx, si, size); -#else /* ISC_MEM_USE_INTERNAL_MALLOC */ - mem_put(ctx, si, size); - LOCK(&ctx->lock); - mem_putstats(ctx, si, size); -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ + if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) { + MCTXLOCK(ctx, &ctx->lock); + mem_putunlocked(ctx, si, size); + } else { + mem_put(ctx, si, size); + MCTXLOCK(ctx, &ctx->lock); + mem_putstats(ctx, si, size); + } DELETE_TRACE(ctx, ptr, size, file, line); - UNLOCK(&ctx->lock); + /* + * The check against ctx->lo_water == 0 is for the condition + * when the context was pushed over hi_water but then had + * isc_mem_setwater() called with 0 for hi_water and lo_water. + */ + if (ctx->hi_called && + (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) { + ctx->hi_called = ISC_FALSE; + + if (ctx->water != NULL) + call_water = ISC_TRUE; + } + MCTXUNLOCK(ctx, &ctx->lock); + + if (call_water) + (ctx->water)(ctx->water_arg, ISC_MEM_LOWATER); } @@ -1303,11 +1410,11 @@ isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) { void isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) { REQUIRE(VALID_CONTEXT(ctx)); - LOCK(&ctx->lock); + MCTXLOCK(ctx, &ctx->lock); ctx->checkfree = flag; - UNLOCK(&ctx->lock); + MCTXUNLOCK(ctx, &ctx->lock); } /* @@ -1317,11 +1424,11 @@ isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) { void isc_mem_setquota(isc_mem_t *ctx, size_t quota) { REQUIRE(VALID_CONTEXT(ctx)); - LOCK(&ctx->lock); + MCTXLOCK(ctx, &ctx->lock); ctx->quota = quota; - UNLOCK(&ctx->lock); + MCTXUNLOCK(ctx, &ctx->lock); } size_t @@ -1329,11 +1436,11 @@ isc_mem_getquota(isc_mem_t *ctx) { size_t quota; REQUIRE(VALID_CONTEXT(ctx)); - LOCK(&ctx->lock); + MCTXLOCK(ctx, &ctx->lock); quota = ctx->quota; - UNLOCK(&ctx->lock); + MCTXUNLOCK(ctx, &ctx->lock); return (quota); } @@ -1343,11 +1450,11 @@ isc_mem_inuse(isc_mem_t *ctx) { size_t inuse; REQUIRE(VALID_CONTEXT(ctx)); - LOCK(&ctx->lock); + MCTXLOCK(ctx, &ctx->lock); inuse = ctx->inuse; - UNLOCK(&ctx->lock); + MCTXUNLOCK(ctx, &ctx->lock); return (inuse); } @@ -1356,24 +1463,38 @@ void isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg, size_t hiwater, size_t lowater) { + isc_boolean_t callwater = ISC_FALSE; + isc_mem_water_t oldwater; + void *oldwater_arg; + REQUIRE(VALID_CONTEXT(ctx)); REQUIRE(hiwater >= lowater); - LOCK(&ctx->lock); + MCTXLOCK(ctx, &ctx->lock); + oldwater = ctx->water; + oldwater_arg = ctx->water_arg; if (water == NULL) { + callwater = ctx->hi_called; ctx->water = NULL; ctx->water_arg = NULL; ctx->hi_water = 0; ctx->lo_water = 0; ctx->hi_called = ISC_FALSE; } else { + if (ctx->hi_called && + (ctx->water != water || ctx->water_arg != water_arg || + ctx->inuse < lowater || lowater == 0U)) + callwater = ISC_TRUE; ctx->water = water; ctx->water_arg = water_arg; ctx->hi_water = hiwater; ctx->lo_water = lowater; ctx->hi_called = ISC_FALSE; } - UNLOCK(&ctx->lock); + MCTXUNLOCK(ctx, &ctx->lock); + + if (callwater && oldwater != NULL) + (oldwater)(oldwater_arg, ISC_MEM_LOWATER); } /* @@ -1413,9 +1534,9 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) { *mpctxp = mpctx; - LOCK(&mctx->lock); + MCTXLOCK(mctx, &mctx->lock); ISC_LIST_INITANDAPPEND(mctx->pools, mpctx, link); - UNLOCK(&mctx->lock); + MCTXUNLOCK(mctx, &mctx->lock); return (ISC_R_SUCCESS); } @@ -1467,28 +1588,28 @@ isc_mempool_destroy(isc_mempool_t **mpctxp) { /* * Return any items on the free list */ - LOCK(&mctx->lock); + MCTXLOCK(mctx, &mctx->lock); while (mpctx->items != NULL) { INSIST(mpctx->freecount > 0); mpctx->freecount--; item = mpctx->items; mpctx->items = item->next; -#if ISC_MEM_USE_INTERNAL_MALLOC - mem_putunlocked(mctx, item, mpctx->size); -#else /* ISC_MEM_USE_INTERNAL_MALLOC */ - mem_put(mctx, item, mpctx->size); - mem_putstats(mctx, item, mpctx->size); -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ + if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) { + mem_putunlocked(mctx, item, mpctx->size); + } else { + mem_put(mctx, item, mpctx->size); + mem_putstats(mctx, item, mpctx->size); + } } - UNLOCK(&mctx->lock); + MCTXUNLOCK(mctx, &mctx->lock); /* * Remove our linked list entry from the memory context. */ - LOCK(&mctx->lock); + MCTXLOCK(mctx, &mctx->lock); ISC_LIST_UNLINK(mctx->pools, mpctx, link); - UNLOCK(&mctx->lock); + MCTXUNLOCK(mctx, &mctx->lock); mpctx->magic = 0; @@ -1547,22 +1668,22 @@ isc__mempool_get(isc_mempool_t *mpctx FLARG) { * We need to dip into the well. Lock the memory context here and * fill up our free list. */ - LOCK(&mctx->lock); + MCTXLOCK(mctx, &mctx->lock); for (i = 0; i < mpctx->fillcount; i++) { -#if ISC_MEM_USE_INTERNAL_MALLOC - item = mem_getunlocked(mctx, mpctx->size); -#else /* ISC_MEM_USE_INTERNAL_MALLOC */ - item = mem_get(mctx, mpctx->size); - if (item != NULL) - mem_getstats(mctx, mpctx->size); -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ + if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) { + item = mem_getunlocked(mctx, mpctx->size); + } else { + item = mem_get(mctx, mpctx->size); + if (item != NULL) + mem_getstats(mctx, mpctx->size); + } if (item == NULL) break; item->next = mpctx->items; mpctx->items = item; mpctx->freecount++; } - UNLOCK(&mctx->lock); + MCTXUNLOCK(mctx, &mctx->lock); /* * If we didn't get any items, return NULL. @@ -1582,9 +1703,9 @@ isc__mempool_get(isc_mempool_t *mpctx FLARG) { #if ISC_MEM_TRACKLINES if (item != NULL) { - LOCK(&mctx->lock); + MCTXLOCK(mctx, &mctx->lock); ADD_TRACE(mctx, item, mpctx->size, file, line); - UNLOCK(&mctx->lock); + MCTXUNLOCK(mctx, &mctx->lock); } #endif /* ISC_MEM_TRACKLINES */ @@ -1608,25 +1729,25 @@ isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) { mpctx->allocated--; #if ISC_MEM_TRACKLINES - LOCK(&mctx->lock); + MCTXLOCK(mctx, &mctx->lock); DELETE_TRACE(mctx, mem, mpctx->size, file, line); - UNLOCK(&mctx->lock); + MCTXUNLOCK(mctx, &mctx->lock); #endif /* ISC_MEM_TRACKLINES */ /* * If our free list is full, return this to the mctx directly. */ if (mpctx->freecount >= mpctx->freemax) { -#if ISC_MEM_USE_INTERNAL_MALLOC - LOCK(&mctx->lock); - mem_putunlocked(mctx, mem, mpctx->size); - UNLOCK(&mctx->lock); -#else /* ISC_MEM_USE_INTERNAL_MALLOC */ - mem_put(mctx, mem, mpctx->size); - LOCK(&mctx->lock); - mem_putstats(mctx, mem, mpctx->size); - UNLOCK(&mctx->lock); -#endif /* ISC_MEM_USE_INTERNAL_MALLOC */ + if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) { + MCTXLOCK(mctx, &mctx->lock); + mem_putunlocked(mctx, mem, mpctx->size); + MCTXUNLOCK(mctx, &mctx->lock); + } else { + mem_put(mctx, mem, mpctx->size); + MCTXLOCK(mctx, &mctx->lock); + mem_putstats(mctx, mem, mpctx->size); + MCTXUNLOCK(mctx, &mctx->lock); + } if (mpctx->lock != NULL) UNLOCK(mpctx->lock); return; @@ -1774,3 +1895,60 @@ isc_mempool_getfillcount(isc_mempool_t *mpctx) { return (fillcount); } + +void +isc_mem_printactive(isc_mem_t *ctx, FILE *file) { + + REQUIRE(VALID_CONTEXT(ctx)); + REQUIRE(file != NULL); + +#if !ISC_MEM_TRACKLINES + UNUSED(ctx); + UNUSED(file); +#else + print_active(ctx, file); +#endif +} + +void +isc_mem_printallactive(FILE *file) { +#if !ISC_MEM_TRACKLINES + UNUSED(file); +#else + isc_mem_t *ctx; + + RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS); + + LOCK(&lock); + for (ctx = ISC_LIST_HEAD(contexts); + ctx != NULL; + ctx = ISC_LIST_NEXT(ctx, link)) { + fprintf(file, "context: %p\n", ctx); + print_active(ctx, file); + } + UNLOCK(&lock); +#endif +} + +void +isc_mem_checkdestroyed(FILE *file) { + + RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS); + + LOCK(&lock); + if (!ISC_LIST_EMPTY(contexts)) { +#if ISC_MEM_TRACKLINES + isc_mem_t *ctx; + + for (ctx = ISC_LIST_HEAD(contexts); + ctx != NULL; + ctx = ISC_LIST_NEXT(ctx, link)) { + fprintf(file, "context: %p\n", ctx); + print_active(ctx, file); + } + fflush(file); +#endif + INSIST(0); + } + UNLOCK(&lock); +} diff --git a/usr.sbin/bind/lib/isc/print.c b/usr.sbin/bind/lib/isc/print.c index 696ad3cb7df..d0436316d27 100644 --- a/usr.sbin/bind/lib/isc/print.c +++ b/usr.sbin/bind/lib/isc/print.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: print.c,v 1.22.2.3.2.4 2006/04/17 18:27:20 explorer Exp $ */ +/* $ISC: print.c,v 1.27.18.3 2006/04/17 18:27:33 explorer Exp $ */ /*! \file */ diff --git a/usr.sbin/bind/lib/isc/pthreads/thread.c b/usr.sbin/bind/lib/isc/pthreads/thread.c index 459e65a9dfe..fd216c2054d 100644 --- a/usr.sbin/bind/lib/isc/pthreads/thread.c +++ b/usr.sbin/bind/lib/isc/pthreads/thread.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,9 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: thread.c,v 1.9.2.2.2.2 2004/12/04 06:50:03 marka Exp $ */ +/* $ISC: thread.c,v 1.12.18.3 2005/04/29 00:17:05 marka Exp $ */ + +/*! \file */ #include <config.h> diff --git a/usr.sbin/bind/lib/isc/random.c b/usr.sbin/bind/lib/isc/random.c index 2d4f9495930..442d35cd485 100644 --- a/usr.sbin/bind/lib/isc/random.c +++ b/usr.sbin/bind/lib/isc/random.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,9 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: random.c,v 1.15.74.5 2004/03/08 09:04:49 marka Exp $ */ +/* $ISC: random.c,v 1.21.18.2 2005/04/29 00:16:48 marka Exp $ */ + +/*! \file */ #include <config.h> diff --git a/usr.sbin/bind/lib/isc/rwlock.c b/usr.sbin/bind/lib/isc/rwlock.c index 8cec462b9d4..ba0bd8ba9b8 100644 --- a/usr.sbin/bind/lib/isc/rwlock.c +++ b/usr.sbin/bind/lib/isc/rwlock.c @@ -15,12 +15,15 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: rwlock.c,v 1.33.2.4.2.3 2005/03/17 03:58:32 marka Exp $ */ +/* $ISC: rwlock.c,v 1.37.18.5 2005/07/12 01:22:30 marka Exp $ */ + +/*! \file */ #include <config.h> #include <stddef.h> +#include <isc/atomic.h> #include <isc/magic.h> #include <isc/msgs.h> #include <isc/platform.h> @@ -81,6 +84,20 @@ isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota, */ rwl->magic = 0; +#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG) + rwl->write_requests = 0; + rwl->write_completions = 0; + rwl->cnt_and_flag = 0; + rwl->readers_waiting = 0; + rwl->write_granted = 0; + if (read_quota != 0) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "read quota is not supported"); + } + if (write_quota == 0) + write_quota = RWLOCK_DEFAULT_WRITE_QUOTA; + rwl->write_quota = write_quota; +#else rwl->type = isc_rwlocktype_read; rwl->original = isc_rwlocktype_none; rwl->active = 0; @@ -93,15 +110,12 @@ isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota, if (write_quota == 0) write_quota = RWLOCK_DEFAULT_WRITE_QUOTA; rwl->write_quota = write_quota; +#endif + result = isc_mutex_init(&rwl->lock); - if (result != ISC_R_SUCCESS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_mutex_init() %s: %s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed"), - isc_result_totext(result)); - return (ISC_R_UNEXPECTED); - } + if (result != ISC_R_SUCCESS) + return (result); + result = isc_condition_init(&rwl->readable); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, @@ -111,7 +125,6 @@ isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota, isc_result_totext(result)); result = ISC_R_UNEXPECTED; goto destroy_lock; - } result = isc_condition_init(&rwl->writeable); if (result != ISC_R_SUCCESS) { @@ -136,6 +149,389 @@ isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota, return (result); } +void +isc_rwlock_destroy(isc_rwlock_t *rwl) { + REQUIRE(VALID_RWLOCK(rwl)); + +#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG) + REQUIRE(rwl->write_requests == rwl->write_completions && + rwl->cnt_and_flag == 0 && rwl->readers_waiting == 0); +#else + LOCK(&rwl->lock); + REQUIRE(rwl->active == 0 && + rwl->readers_waiting == 0 && + rwl->writers_waiting == 0); + UNLOCK(&rwl->lock); +#endif + + rwl->magic = 0; + (void)isc_condition_destroy(&rwl->readable); + (void)isc_condition_destroy(&rwl->writeable); + DESTROYLOCK(&rwl->lock); +} + +#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG) + +/* + * When some architecture-dependent atomic operations are available, + * rwlock can be more efficient than the generic algorithm defined below. + * The basic algorithm is described in the following URL: + * http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/rw.html + * + * The key is to use the following integer variables modified atomically: + * write_requests, write_completions, and cnt_and_flag. + * + * write_requests and write_completions act as a waiting queue for writers + * in order to ensure the FIFO order. Both variables begin with the initial + * value of 0. When a new writer tries to get a write lock, it increments + * write_requests and gets the previous value of the variable as a "ticket". + * When write_completions reaches the ticket number, the new writer can start + * writing. When the writer completes its work, it increments + * write_completions so that another new writer can start working. If the + * write_requests is not equal to write_completions, it means a writer is now + * working or waiting. In this case, a new readers cannot start reading, or + * in other words, this algorithm basically prefers writers. + * + * cnt_and_flag is a "lock" shared by all readers and writers. This integer + * variable is a kind of structure with two members: writer_flag (1 bit) and + * reader_count (31 bits). The writer_flag shows whether a writer is working, + * and the reader_count shows the number of readers currently working or almost + * ready for working. A writer who has the current "ticket" tries to get the + * lock by exclusively setting the writer_flag to 1, provided that the whole + * 32-bit is 0 (meaning no readers or writers working). On the other hand, + * a new reader tries to increment the "reader_count" field provided that + * the writer_flag is 0 (meaning there is no writer working). + * + * If some of the above operations fail, the reader or the writer sleeps + * until the related condition changes. When a working reader or writer + * completes its work, some readers or writers are sleeping, and the condition + * that suspended the reader or writer has changed, it wakes up the sleeping + * readers or writers. + * + * As already noted, this algorithm basically prefers writers. In order to + * prevent readers from starving, however, the algorithm also introduces the + * "writer quota" (Q). When Q consecutive writers have completed their work, + * suspending readers, the last writer will wake up the readers, even if a new + * writer is waiting. + * + * Implementation specific note: due to the combination of atomic operations + * and a mutex lock, ordering between the atomic operation and locks can be + * very sensitive in some cases. In particular, it is generally very important + * to check the atomic variable that requires a reader or writer to sleep after + * locking the mutex and before actually sleeping; otherwise, it could be very + * likely to cause a deadlock. For example, assume "var" is a variable + * atomically modified, then the corresponding code would be: + * if (var == need_sleep) { + * LOCK(lock); + * if (var == need_sleep) + * WAIT(cond, lock); + * UNLOCK(lock); + * } + * The second check is important, since "var" is protected by the atomic + * operation, not by the mutex, and can be changed just before sleeping. + * (The first "if" could be omitted, but this is also important in order to + * make the code efficient by avoiding the use of the mutex unless it is + * really necessary.) + */ + +#define WRITER_ACTIVE 0x1 +#define READER_INCR 0x2 + +isc_result_t +isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { + isc_int32_t cntflag; + + REQUIRE(VALID_RWLOCK(rwl)); + +#ifdef ISC_RWLOCK_TRACE + print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, + ISC_MSG_PRELOCK, "prelock"), rwl, type); +#endif + + if (type == isc_rwlocktype_read) { + if (rwl->write_requests != rwl->write_completions) { + /* there is a waiting or active writer */ + LOCK(&rwl->lock); + if (rwl->write_requests != rwl->write_completions) { + rwl->readers_waiting++; + WAIT(&rwl->readable, &rwl->lock); + rwl->readers_waiting--; + } + UNLOCK(&rwl->lock); + } + + cntflag = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR); + while (1) { + if ((rwl->cnt_and_flag & WRITER_ACTIVE) == 0) + break; + + /* A writer is still working */ + LOCK(&rwl->lock); + rwl->readers_waiting++; + if ((rwl->cnt_and_flag & WRITER_ACTIVE) != 0) + WAIT(&rwl->readable, &rwl->lock); + rwl->readers_waiting--; + UNLOCK(&rwl->lock); + + /* + * Typically, the reader should be able to get a lock + * at this stage: + * (1) there should have been no pending writer when + * the reader was trying to increment the + * counter; otherwise, the writer should be in + * the waiting queue, preventing the reader from + * proceeding to this point. + * (2) once the reader increments the counter, no + * more writer can get a lock. + * Still, it is possible another writer can work at + * this point, e.g. in the following scenario: + * A previous writer unlocks the writer lock. + * This reader proceeds to point (1). + * A new writer appears, and gets a new lock before + * the reader increments the counter. + * The reader then increments the counter. + * The previous writer notices there is a waiting + * reader who is almost ready, and wakes it up. + * So, the reader needs to confirm whether it can now + * read explicitly (thus we loop). Note that this is + * not an infinite process, since the reader has + * incremented the counter at this point. + */ + } + + /* + * If we are temporarily preferred to writers due to the writer + * quota, reset the condition (race among readers doesn't + * matter). + */ + rwl->write_granted = 0; + } else { + isc_int32_t prev_writer; + + /* enter the waiting queue, and wait for our turn */ + prev_writer = isc_atomic_xadd(&rwl->write_requests, 1); + while (rwl->write_completions != prev_writer) { + LOCK(&rwl->lock); + if (rwl->write_completions != prev_writer) { + WAIT(&rwl->writeable, &rwl->lock); + UNLOCK(&rwl->lock); + continue; + } + UNLOCK(&rwl->lock); + break; + } + + while (1) { + cntflag = isc_atomic_cmpxchg(&rwl->cnt_and_flag, 0, + WRITER_ACTIVE); + if (cntflag == 0) + break; + + /* Another active reader or writer is working. */ + LOCK(&rwl->lock); + if (rwl->cnt_and_flag != 0) + WAIT(&rwl->writeable, &rwl->lock); + UNLOCK(&rwl->lock); + } + + INSIST((rwl->cnt_and_flag & WRITER_ACTIVE) != 0); + rwl->write_granted++; + } + +#ifdef ISC_RWLOCK_TRACE + print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, + ISC_MSG_POSTLOCK, "postlock"), rwl, type); +#endif + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { + isc_int32_t cntflag; + + REQUIRE(VALID_RWLOCK(rwl)); + +#ifdef ISC_RWLOCK_TRACE + print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, + ISC_MSG_PRELOCK, "prelock"), rwl, type); +#endif + + if (type == isc_rwlocktype_read) { + /* If a writer is waiting or working, we fail. */ + if (rwl->write_requests != rwl->write_completions) + return (ISC_R_LOCKBUSY); + + /* Otherwise, be ready for reading. */ + cntflag = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR); + if ((cntflag & WRITER_ACTIVE) != 0) { + /* + * A writer is working. We lose, and cancel the read + * request. + */ + cntflag = isc_atomic_xadd(&rwl->cnt_and_flag, + -READER_INCR); + /* + * If no other readers are waiting and we've suspended + * new writers in this short period, wake them up. + */ + if (cntflag == READER_INCR && + rwl->write_completions != rwl->write_requests) { + LOCK(&rwl->lock); + BROADCAST(&rwl->writeable); + UNLOCK(&rwl->lock); + } + + return (ISC_R_LOCKBUSY); + } + } else { + /* Try locking without entering the waiting queue. */ + cntflag = isc_atomic_cmpxchg(&rwl->cnt_and_flag, 0, + WRITER_ACTIVE); + if (cntflag != 0) + return (ISC_R_LOCKBUSY); + + /* + * XXXJT: jump into the queue, possibly breaking the writer + * order. + */ + (void)isc_atomic_xadd(&rwl->write_completions, -1); + + rwl->write_granted++; + } + +#ifdef ISC_RWLOCK_TRACE + print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, + ISC_MSG_POSTLOCK, "postlock"), rwl, type); +#endif + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_rwlock_tryupgrade(isc_rwlock_t *rwl) { + isc_int32_t prevcnt; + + REQUIRE(VALID_RWLOCK(rwl)); + + /* Try to acquire write access. */ + prevcnt = isc_atomic_cmpxchg(&rwl->cnt_and_flag, + READER_INCR, WRITER_ACTIVE); + /* + * There must have been no writer, and there must have been at least + * one reader. + */ + INSIST((prevcnt & WRITER_ACTIVE) == 0 && + (prevcnt & ~WRITER_ACTIVE) != 0); + + if (prevcnt == READER_INCR) { + /* + * We are the only reader and have been upgraded. + * Now jump into the head of the writer waiting queue. + */ + (void)isc_atomic_xadd(&rwl->write_completions, -1); + } else + return (ISC_R_LOCKBUSY); + + return (ISC_R_SUCCESS); + +} + +void +isc_rwlock_downgrade(isc_rwlock_t *rwl) { + isc_int32_t prev_readers; + + REQUIRE(VALID_RWLOCK(rwl)); + + /* Become an active reader. */ + prev_readers = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR); + /* We must have been a writer. */ + INSIST((prev_readers & WRITER_ACTIVE) != 0); + + /* Complete write */ + (void)isc_atomic_xadd(&rwl->cnt_and_flag, -WRITER_ACTIVE); + (void)isc_atomic_xadd(&rwl->write_completions, 1); + + /* Resume other readers */ + LOCK(&rwl->lock); + if (rwl->readers_waiting > 0) + BROADCAST(&rwl->readable); + UNLOCK(&rwl->lock); +} + +isc_result_t +isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { + isc_int32_t prev_cnt; + + REQUIRE(VALID_RWLOCK(rwl)); + +#ifdef ISC_RWLOCK_TRACE + print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, + ISC_MSG_PREUNLOCK, "preunlock"), rwl, type); +#endif + + if (type == isc_rwlocktype_read) { + prev_cnt = isc_atomic_xadd(&rwl->cnt_and_flag, -READER_INCR); + + /* + * If we're the last reader and any writers are waiting, wake + * them up. We need to wake up all of them to ensure the + * FIFO order. + */ + if (prev_cnt == READER_INCR && + rwl->write_completions != rwl->write_requests) { + LOCK(&rwl->lock); + BROADCAST(&rwl->writeable); + UNLOCK(&rwl->lock); + } + } else { + isc_boolean_t wakeup_writers = ISC_TRUE; + + /* + * Reset the flag, and (implicitly) tell other writers + * we are done. + */ + (void)isc_atomic_xadd(&rwl->cnt_and_flag, -WRITER_ACTIVE); + (void)isc_atomic_xadd(&rwl->write_completions, 1); + + if (rwl->write_granted >= rwl->write_quota || + rwl->write_requests == rwl->write_completions || + (rwl->cnt_and_flag & ~WRITER_ACTIVE) != 0) { + /* + * We have passed the write quota, no writer is + * waiting, or some readers are almost ready, pending + * possible writers. Note that the last case can + * happen even if write_requests != write_completions + * (which means a new writer in the queue), so we need + * to catch the case explicitly. + */ + LOCK(&rwl->lock); + if (rwl->readers_waiting > 0) { + wakeup_writers = ISC_FALSE; + BROADCAST(&rwl->readable); + } + UNLOCK(&rwl->lock); + } + + if (rwl->write_requests != rwl->write_completions && + wakeup_writers) { + LOCK(&rwl->lock); + BROADCAST(&rwl->writeable); + UNLOCK(&rwl->lock); + } + } + +#ifdef ISC_RWLOCK_TRACE + print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, + ISC_MSG_POSTUNLOCK, "postunlock"), + rwl, type); +#endif + + return (ISC_R_SUCCESS); +} + +#else /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */ + static isc_result_t doit(isc_rwlock_t *rwl, isc_rwlocktype_t type, isc_boolean_t nonblock) { isc_boolean_t skip = ISC_FALSE; @@ -321,22 +717,7 @@ isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { return (ISC_R_SUCCESS); } -void -isc_rwlock_destroy(isc_rwlock_t *rwl) { - REQUIRE(VALID_RWLOCK(rwl)); - - LOCK(&rwl->lock); - REQUIRE(rwl->active == 0 && - rwl->readers_waiting == 0 && - rwl->writers_waiting == 0); - UNLOCK(&rwl->lock); - - rwl->magic = 0; - (void)isc_condition_destroy(&rwl->readable); - (void)isc_condition_destroy(&rwl->writeable); - DESTROYLOCK(&rwl->lock); -} - +#endif /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */ #else /* ISC_PLATFORM_USETHREADS */ isc_result_t diff --git a/usr.sbin/bind/lib/isc/sha1.c b/usr.sbin/bind/lib/isc/sha1.c index e94a9b845f5..30d5cc33ddf 100644 --- a/usr.sbin/bind/lib/isc/sha1.c +++ b/usr.sbin/bind/lib/isc/sha1.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,16 +15,14 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: sha1.c,v 1.10.2.2.2.3 2004/03/06 08:14:35 marka Exp $ */ +/* $ISC: sha1.c,v 1.14.18.2 2005/04/29 00:16:49 marka Exp $ */ +/* $OpenBSD: sha1.c,v 1.4 2007/12/09 13:39:44 jakob Exp $ */ -/* $NetBSD: sha1.c,v 1.5 2000/01/22 22:19:14 mycroft Exp $ */ -/* $OpenBSD: sha1.c,v 1.3 2004/09/28 17:14:07 jakob Exp $ */ - -/* +/*! \file * SHA-1 in C - * By Steve Reid <steve@edmweb.com> + * \author By Steve Reid <steve@edmweb.com> * 100% Public Domain - * + * \verbatim * Test Vectors (from FIPS PUB 180-1) * "abc" * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D @@ -32,6 +30,7 @@ * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 * A million repetitions of "a" * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F + * \endverbatim */ #include "config.h" @@ -44,7 +43,8 @@ #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) -/* +/*@{*/ +/*! * blk0() and blk() perform the initial expand. * I got the idea of expanding during the round function from SSLeay */ @@ -61,7 +61,9 @@ ^ block->l[(i + 2) & 15] \ ^ block->l[i & 15], 1)) -/* +/*@}*/ +/*@{*/ +/*! * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 */ #define R0(v,w,x,y,z,i) \ @@ -80,6 +82,8 @@ z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ w = rol(w, 30); +/*@}*/ + typedef union { unsigned char c[64]; unsigned int l[16]; @@ -154,7 +158,7 @@ do_R4(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, isc_uint32_t *d, } #endif -/* +/*! * Hash a single 512-bit block. This is the core of the algorithm. */ static void @@ -217,7 +221,7 @@ transform(isc_uint32_t state[5], const unsigned char buffer[64]) { } -/* +/*! * isc_sha1_init - Initialize new context */ void @@ -240,7 +244,7 @@ isc_sha1_invalidate(isc_sha1_t *context) { memset(context, 0, sizeof(isc_sha1_t)); } -/* +/*! * Run your data through this. */ void @@ -270,7 +274,7 @@ isc_sha1_update(isc_sha1_t *context, const unsigned char *data, } -/* +/*! * Add padding and return the message digest. */ diff --git a/usr.sbin/bind/lib/isc/sockaddr.c b/usr.sbin/bind/lib/isc/sockaddr.c index 1819cfda06e..730376f3f84 100644 --- a/usr.sbin/bind/lib/isc/sockaddr.c +++ b/usr.sbin/bind/lib/isc/sockaddr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,9 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: sockaddr.c,v 1.48.2.1.2.12 2006/03/02 00:37:20 marka Exp $ */ +/* $ISC: sockaddr.c,v 1.59.18.9 2006/06/21 01:25:40 marka Exp $ */ + +/*! \file */ #include <config.h> @@ -33,6 +35,21 @@ isc_boolean_t isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { + return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR| + ISC_SOCKADDR_CMPPORT| + ISC_SOCKADDR_CMPSCOPE)); +} + +isc_boolean_t +isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { + return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR| + ISC_SOCKADDR_CMPSCOPE)); +} + +isc_boolean_t +isc_sockaddr_compare(const isc_sockaddr_t *a, const isc_sockaddr_t *b, + unsigned int flags) +{ REQUIRE(a != NULL && b != NULL); if (a->length != b->length) @@ -47,21 +64,33 @@ isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { return (ISC_FALSE); switch (a->type.sa.sa_family) { case AF_INET: - if (memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr, + if ((flags & ISC_SOCKADDR_CMPADDR) != 0 && + memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr, sizeof(a->type.sin.sin_addr)) != 0) return (ISC_FALSE); - if (a->type.sin.sin_port != b->type.sin.sin_port) + if ((flags & ISC_SOCKADDR_CMPPORT) != 0 && + a->type.sin.sin_port != b->type.sin.sin_port) return (ISC_FALSE); break; case AF_INET6: - if (memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr, + if ((flags & ISC_SOCKADDR_CMPADDR) != 0 && + memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr, sizeof(a->type.sin6.sin6_addr)) != 0) return (ISC_FALSE); #ifdef ISC_PLATFORM_HAVESCOPEID - if (a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id) + /* + * If ISC_SOCKADDR_CMPSCOPEZERO is set then don't return + * ISC_FALSE if one of the scopes in zero. + */ + if ((flags & ISC_SOCKADDR_CMPSCOPE) != 0 && + a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id && + ((flags & ISC_SOCKADDR_CMPSCOPEZERO) == 0 || + (a->type.sin6.sin6_scope_id != 0 && + b->type.sin6.sin6_scope_id != 0))) return (ISC_FALSE); #endif - if (a->type.sin6.sin6_port != b->type.sin6.sin6_port) + if ((flags & ISC_SOCKADDR_CMPPORT) != 0 && + a->type.sin6.sin6_port != b->type.sin6.sin6_port) return (ISC_FALSE); break; default: @@ -72,37 +101,6 @@ isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { } isc_boolean_t -isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) { - REQUIRE(a != NULL && b != NULL); - - if (a->length != b->length) - return (ISC_FALSE); - - if (a->type.sa.sa_family != b->type.sa.sa_family) - return (ISC_FALSE); - switch (a->type.sa.sa_family) { - case AF_INET: - if (memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr, - sizeof(a->type.sin.sin_addr)) != 0) - return (ISC_FALSE); - break; - case AF_INET6: - if (memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr, - sizeof(a->type.sin6.sin6_addr)) != 0) - return (ISC_FALSE); -#ifdef ISC_PLATFORM_HAVESCOPEID - if (a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id) - return (ISC_FALSE); -#endif - break; - default: - if (memcmp(&a->type, &b->type, a->length) != 0) - return (ISC_FALSE); - } - return (ISC_TRUE); -} - -isc_boolean_t isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b, unsigned int prefixlen) { @@ -134,6 +132,23 @@ isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target) { case AF_INET6: snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin6.sin6_port)); break; +#ifdef ISC_PLAFORM_HAVESYSUNH + case AF_UNIX: + plen = strlen(sockaddr->type.sunix.sun_path); + if (plen >= isc_buffer_availablelength(target)) + return (ISC_R_NOSPACE); + + isc_buffer_putmem(target, sockaddr->type.sunix.sun_path, plen); + + /* + * Null terminate after used region. + */ + isc_buffer_availableregion(target, &avail); + INSIST(avail.length >= 1); + avail.base[0] = '\0'; + + return (ISC_R_SUCCESS); +#endif default: return (ISC_R_FAILURE); } @@ -425,8 +440,12 @@ isc_boolean_t isc_sockaddr_ismulticast(const isc_sockaddr_t *sockaddr) { isc_netaddr_t netaddr; - isc_netaddr_fromsockaddr(&netaddr, sockaddr); - return (isc_netaddr_ismulticast(&netaddr)); + if (sockaddr->type.sa.sa_family == AF_INET || + sockaddr->type.sa.sa_family == AF_INET6) { + isc_netaddr_fromsockaddr(&netaddr, sockaddr); + return (isc_netaddr_ismulticast(&netaddr)); + } + return (ISC_FALSE); } isc_boolean_t @@ -461,3 +480,24 @@ isc_sockaddr_islinklocal(const isc_sockaddr_t *sockaddr) { } return (ISC_FALSE); } + +isc_result_t +isc_sockaddr_frompath(isc_sockaddr_t *sockaddr, const char *path) { +#ifdef ISC_PLATFORM_HAVESYSUNH + if (strlen(path) >= sizeof(sockaddr->type.sunix.sun_path)) + return (ISC_R_NOSPACE); + memset(sockaddr, 0, sizeof(*sockaddr)); + sockaddr->length = sizeof(sockaddr->type.sunix); + sockaddr->type.sunix.sun_family = AF_UNIX; +#ifdef ISC_PLATFORM_HAVESALEN + sockaddr->type.sunix.sun_len = + (unsigned char)sizeof(sockaddr->type.sunix); +#endif + strcpy(sockaddr->type.sunix.sun_path, path); + return (ISC_R_SUCCESS); +#else + UNUSED(sockaddr); + UNUSED(path); + return (ISC_R_NOTIMPLEMENTED); +#endif +} diff --git a/usr.sbin/bind/lib/isc/string.c b/usr.sbin/bind/lib/isc/string.c index d01af8ac755..e556f5b9ed1 100644 --- a/usr.sbin/bind/lib/isc/string.c +++ b/usr.sbin/bind/lib/isc/string.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,13 +15,19 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: string.c,v 1.6.164.5 2004/09/16 01:00:58 marka Exp $ */ +/* $ISC: string.c,v 1.10.18.7 2006/10/03 23:50:51 marka Exp $ */ + +/*! \file */ #include <config.h> #include <ctype.h> +#include <isc/mem.h> +#include <isc/print.h> +#include <isc/region.h> #include <isc/string.h> +#include <isc/util.h> static char digits[] = "0123456789abcdefghijklmnoprstuvwxyz"; @@ -89,6 +95,105 @@ isc_string_touint64(char *source, char **end, int base) { return (tmp); } +isc_result_t +isc_string_copy(char *target, size_t size, const char *source) { + REQUIRE(size > 0U); + + if (strlcpy(target, source, size) >= size) { + memset(target, ISC_STRING_MAGIC, size); + return (ISC_R_NOSPACE); + } + + ENSURE(strlen(target) < size); + + return (ISC_R_SUCCESS); +} + +void +isc_string_copy_truncate(char *target, size_t size, const char *source) { + REQUIRE(size > 0U); + + strlcpy(target, source, size); + + ENSURE(strlen(target) < size); +} + +isc_result_t +isc_string_append(char *target, size_t size, const char *source) { + REQUIRE(size > 0U); + REQUIRE(strlen(target) < size); + + if (strlcat(target, source, size) >= size) { + memset(target, ISC_STRING_MAGIC, size); + return (ISC_R_NOSPACE); + } + + ENSURE(strlen(target) < size); + + return (ISC_R_SUCCESS); +} + +void +isc_string_append_truncate(char *target, size_t size, const char *source) { + REQUIRE(size > 0U); + REQUIRE(strlen(target) < size); + + strlcat(target, source, size); + + ENSURE(strlen(target) < size); +} + +isc_result_t +isc_string_printf(char *target, size_t size, const char *format, ...) { + va_list args; + size_t n; + + REQUIRE(size > 0U); + + va_start(args, format); + n = vsnprintf(target, size, format, args); + va_end(args); + + if (n >= size) { + memset(target, ISC_STRING_MAGIC, size); + return (ISC_R_NOSPACE); + } + + ENSURE(strlen(target) < size); + + return (ISC_R_SUCCESS); +} + +void +isc_string_printf_truncate(char *target, size_t size, const char *format, ...) { + va_list args; + size_t n; + + REQUIRE(size > 0U); + + va_start(args, format); + n = vsnprintf(target, size, format, args); + va_end(args); + + ENSURE(strlen(target) < size); +} + +char * +isc_string_regiondup(isc_mem_t *mctx, const isc_region_t *source) { + char *target; + + REQUIRE(mctx != NULL); + REQUIRE(source != NULL); + + target = (char *) isc_mem_allocate(mctx, source->length + 1); + if (target != NULL) { + memcpy(source->base, target, source->length); + target[source->length] = '\0'; + } + + return (target); +} + char * isc_string_separate(char **stringp, const char *delim) { char *string = *stringp; diff --git a/usr.sbin/bind/lib/isc/task.c b/usr.sbin/bind/lib/isc/task.c index ce0327067b6..efffd536323 100644 --- a/usr.sbin/bind/lib/isc/task.c +++ b/usr.sbin/bind/lib/isc/task.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,10 +15,10 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: task.c,v 1.85.2.3.8.5 2004/10/15 00:45:45 marka Exp $ */ +/* $ISC: task.c,v 1.91.18.6 2006/01/04 23:50:23 marka Exp $ */ -/* - * Principal Author: Bob Halley +/*! \file + * \author Principal Author: Bob Halley */ /* @@ -174,6 +174,7 @@ isc_task_create(isc_taskmgr_t *manager, unsigned int quantum, { isc_task_t *task; isc_boolean_t exiting; + isc_result_t result; REQUIRE(VALID_MANAGER(manager)); REQUIRE(taskp != NULL && *taskp == NULL); @@ -183,13 +184,10 @@ isc_task_create(isc_taskmgr_t *manager, unsigned int quantum, return (ISC_R_NOMEMORY); XTRACE("isc_task_create"); task->manager = manager; - if (isc_mutex_init(&task->lock) != ISC_R_SUCCESS) { + result = isc_mutex_init(&task->lock); + if (result != ISC_R_SUCCESS) { isc_mem_put(manager->mctx, task, sizeof(*task)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_mutex_init() %s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed")); - return (ISC_R_UNEXPECTED); + return (result); } task->state = task_state_idle; task->references = 1; @@ -1066,14 +1064,10 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, return (ISC_R_NOMEMORY); manager->magic = TASK_MANAGER_MAGIC; manager->mctx = NULL; - if (isc_mutex_init(&manager->lock) != ISC_R_SUCCESS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_mutex_init() %s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed")); - result = ISC_R_UNEXPECTED; + result = isc_mutex_init(&manager->lock); + if (result != ISC_R_SUCCESS) goto cleanup_mgr; - } + #ifdef ISC_PLATFORM_USETHREADS manager->workers = 0; manager->threads = isc_mem_allocate(mctx, @@ -1235,6 +1229,8 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) { UNLOCK(&manager->lock); while (isc__taskmgr_ready()) (void)isc__taskmgr_dispatch(); + if (!ISC_LIST_EMPTY(manager->tasks)) + isc_mem_printallactive(stderr); INSIST(ISC_LIST_EMPTY(manager->tasks)); #endif /* ISC_PLATFORM_USETHREADS */ diff --git a/usr.sbin/bind/lib/isc/unix/Makefile.in b/usr.sbin/bind/lib/isc/unix/Makefile.in index 38c331edf85..9aa87a11aa4 100644 --- a/usr.sbin/bind/lib/isc/unix/Makefile.in +++ b/usr.sbin/bind/lib/isc/unix/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $ISC: Makefile.in,v 1.35.2.1.10.2 2004/06/22 02:48:36 marka Exp $ +# $ISC: Makefile.in,v 1.38.18.1 2004/06/22 02:54:06 marka Exp $ srcdir = @srcdir@ VPATH = @srcdir@ diff --git a/usr.sbin/bind/lib/isc/unix/dir.c b/usr.sbin/bind/lib/isc/unix/dir.c index 5167cc7f5df..78b3014f928 100644 --- a/usr.sbin/bind/lib/isc/unix/dir.c +++ b/usr.sbin/bind/lib/isc/unix/dir.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,9 +15,10 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: dir.c,v 1.18.2.1.2.3 2004/03/08 09:04:55 marka Exp $ */ +/* $ISC: dir.c,v 1.20.18.3 2005/09/05 00:18:30 marka Exp $ */ -/* Principal Authors: DCL */ +/*! \file + * \author Principal Authors: DCL */ #include <config.h> @@ -50,18 +51,37 @@ isc_dir_init(isc_dir_t *dir) { dir->magic = ISC_DIR_MAGIC; } -/* - * Allocate workspace and open directory stream. If either one fails, +/*! + * \brief Allocate workspace and open directory stream. If either one fails, * NULL will be returned. */ isc_result_t isc_dir_open(isc_dir_t *dir, const char *dirname) { + char *p; isc_result_t result = ISC_R_SUCCESS; REQUIRE(VALID_DIR(dir)); REQUIRE(dirname != NULL); /* + * Copy directory name. Need to have enough space for the name, + * a possible path separator, the wildcard, and the final NUL. + */ + if (strlen(dirname) + 3 > sizeof(dir->dirname)) + /* XXXDCL ? */ + return (ISC_R_NOSPACE); + strcpy(dir->dirname, dirname); + + /* + * Append path separator, if needed, and "*". + */ + p = dir->dirname + strlen(dir->dirname); + if (dir->dirname < p && *(p - 1) != '/') + *p++ = '/'; + *p++ = '*'; + *p++ = '\0'; + + /* * Open stream. */ dir->handle = opendir(dirname); @@ -72,8 +92,10 @@ isc_dir_open(isc_dir_t *dir, const char *dirname) { return (result); } -/* - * Return previously retrieved file or get next one. Unix's dirent has +/*! + * \brief Return previously retrieved file or get next one. + + * Unix's dirent has * separate open and read functions, but the Win32 and DOS interfaces open * the dir stream and reads the first file in one operation. */ @@ -107,8 +129,8 @@ isc_dir_read(isc_dir_t *dir) { return (ISC_R_SUCCESS); } -/* - * Close directory stream. +/*! + * \brief Close directory stream. */ void isc_dir_close(isc_dir_t *dir) { @@ -118,8 +140,8 @@ isc_dir_close(isc_dir_t *dir) { dir->handle = NULL; } -/* - * Reposition directory stream at start. +/*! + * \brief Reposition directory stream at start. */ isc_result_t isc_dir_reset(isc_dir_t *dir) { @@ -132,8 +154,8 @@ isc_dir_reset(isc_dir_t *dir) { isc_result_t isc_dir_chdir(const char *dirname) { - /* - * Change the current directory to 'dirname'. + /*! + * \brief Change the current directory to 'dirname'. */ REQUIRE(dirname != NULL); @@ -165,8 +187,8 @@ isc_dir_createunique(char *templet) { REQUIRE(templet != NULL); - /* - * mkdtemp is not portable, so this emulates it. + /*! + * \brief mkdtemp is not portable, so this emulates it. */ pid = getpid(); diff --git a/usr.sbin/bind/lib/isc/unix/entropy.c b/usr.sbin/bind/lib/isc/unix/entropy.c index b39bba0a4aa..57609868a57 100644 --- a/usr.sbin/bind/lib/isc/unix/entropy.c +++ b/usr.sbin/bind/lib/isc/unix/entropy.c @@ -15,10 +15,11 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: entropy.c,v 1.60.2.3.8.14 2006/03/02 23:29:17 marka Exp $ */ +/* $ISC: entropy.c,v 1.71.18.7 2006/12/07 04:53:03 marka Exp $ */ -/* - * This is the system depenedent part of the ISC entropy API. +/* \file unix/entropy.c + * \brief + * This is the system dependent part of the ISC entropy API. */ #include <config.h> @@ -41,7 +42,7 @@ #include "errno2result.h" -/* +/*% * There is only one variable in the entropy data structures that is not * system independent, but pulling the structure that uses it into this file * ultimately means pulling several other independent structures here also to @@ -486,8 +487,6 @@ isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) { LOCK(&ent->lock); - source = NULL; - if (stat(fname, &_stat) < 0) { ret = isc__errno2result(errno); goto errout; @@ -588,9 +587,6 @@ isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) { (void)close(fd); errout: - if (source != NULL) - isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t)); - UNLOCK(&ent->lock); return (ret); diff --git a/usr.sbin/bind/lib/isc/unix/file.c b/usr.sbin/bind/lib/isc/unix/file.c index c5610ef52f5..4fc69cd49f6 100644 --- a/usr.sbin/bind/lib/isc/unix/file.c +++ b/usr.sbin/bind/lib/isc/unix/file.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2002 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -48,7 +48,9 @@ * SUCH DAMAGE. */ -/* $ISC: file.c,v 1.38.12.8 2004/03/16 05:50:25 marka Exp $ */ +/* $ISC: file.c,v 1.47.18.2 2005/04/29 00:17:07 marka Exp $ */ + +/*! \file */ #include <config.h> @@ -154,7 +156,7 @@ isc_file_settime(const char *file, isc_time_t *time) { } #undef TEMPLATE -#define TEMPLATE "tmp-XXXXXXXXXX" /* 14 characters. */ +#define TEMPLATE "tmp-XXXXXXXXXX" /*%< 14 characters. */ isc_result_t isc_file_mktemplate(const char *path, char *buf, size_t buflen) { diff --git a/usr.sbin/bind/lib/isc/unix/fsaccess.c b/usr.sbin/bind/lib/isc/unix/fsaccess.c index 8b6250c8144..6b565ef22bd 100644 --- a/usr.sbin/bind/lib/isc/unix/fsaccess.c +++ b/usr.sbin/bind/lib/isc/unix/fsaccess.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: fsaccess.c,v 1.6.206.3 2006/08/25 05:25:50 marka Exp $ */ +/* $ISC: fsaccess.c,v 1.7.18.4 2006/08/25 05:25:51 marka Exp $ */ #include <config.h> @@ -26,7 +26,8 @@ #include "errno2result.h" -/* +/*! \file + * \brief * The OS-independent part of the API is in lib/isc. */ #include "../fsaccess.c" diff --git a/usr.sbin/bind/lib/isc/unix/ifiter_ioctl.c b/usr.sbin/bind/lib/isc/unix/ifiter_ioctl.c index 0053d015828..51a05218d54 100644 --- a/usr.sbin/bind/lib/isc/unix/ifiter_ioctl.c +++ b/usr.sbin/bind/lib/isc/unix/ifiter_ioctl.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * - * Permission to use, copy, modify, and distribute this software for any + * Permission to use, copy, modify, and/or 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. * @@ -15,9 +15,10 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: ifiter_ioctl.c,v 1.19.2.5.2.19 2006/02/03 23:51:37 marka Exp $ */ +/* $ISC: ifiter_ioctl.c,v 1.44.18.13 2007/08/31 23:46:25 tbox Exp $ */ -/* +/*! \file + * \brief * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl. * See netintro(4). */ @@ -93,7 +94,7 @@ struct isc_interfaceiter { #endif -/* +/*% * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system * will have more than a megabyte of interface configuration data. */ @@ -904,7 +905,8 @@ internal_next4(isc_interfaceiter_t *iter) { struct ifreq *ifrp; #endif - REQUIRE (iter->pos < (unsigned int) iter->ifc.ifc_len); + REQUIRE(iter->ifc.ifc_len == 0 || + iter->pos < (unsigned int) iter->ifc.ifc_len); #ifdef __linux if (linux_if_inet6_next(iter) == ISC_R_SUCCESS) @@ -912,6 +914,10 @@ internal_next4(isc_interfaceiter_t *iter) { if (!iter->first) return (ISC_R_SUCCESS); #endif + + if (iter->ifc.ifc_len == 0) + return (ISC_R_NOMORE); + #ifdef ISC_PLATFORM_HAVESALEN ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos); diff --git a/usr.sbin/bind/lib/isc/unix/include/isc/stat.h b/usr.sbin/bind/lib/isc/unix/include/isc/stat.h index aecbb6b0dd9..8efbce0e418 100644 --- a/usr.sbin/bind/lib/isc/unix/include/isc/stat.h +++ b/usr.sbin/bind/lib/isc/unix/include/isc/stat.h @@ -1,6 +1,5 @@ /* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") - * 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 @@ -15,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: stat.h,v 1.1.2.1.4.1 2004/03/06 08:15:05 marka Exp $ */ +/* $ISC: stat.h,v 1.2.18.1 2004/08/19 04:42:54 marka Exp $ */ #ifndef ISC_STAT_H #define ISC_STAT_H 1 diff --git a/usr.sbin/bind/lib/isc/unix/socket.c b/usr.sbin/bind/lib/isc/unix/socket.c index 128f39467ea..97822cef4e2 100644 --- a/usr.sbin/bind/lib/isc/unix/socket.c +++ b/usr.sbin/bind/lib/isc/unix/socket.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * - * Permission to use, copy, modify, and distribute this software for any + * Permission to use, copy, modify, and/or 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. * @@ -15,13 +15,19 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: socket.c,v 1.207.2.19.2.26 2006/05/19 02:53:36 marka Exp $ */ +/* $ISC: socket.c,v 1.237.18.29 2007/08/28 07:20:06 tbox Exp $ */ + +/*! \file */ #include <config.h> #include <sys/param.h> #include <sys/types.h> #include <sys/socket.h> +#include <sys/stat.h> +#ifdef ISC_PLATFORM_HAVESYSUNH +#include <sys/un.h> +#endif #include <sys/time.h> #include <sys/uio.h> @@ -42,6 +48,7 @@ #include <isc/msgs.h> #include <isc/mutex.h> #include <isc/net.h> +#include <isc/once.h> #include <isc/platform.h> #include <isc/print.h> #include <isc/privsep.h> @@ -58,7 +65,7 @@ #include "socket_p.h" #endif /* ISC_PLATFORM_USETHREADS */ -/* +/*% * 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. */ @@ -66,7 +73,12 @@ #define ISC_SOCKADDR_LEN_T unsigned int #endif -/* + +#if defined(SO_BSDCOMPAT) && defined(__linux__) +#include <sys/utsname.h> +#endif + +/*% * Define what the possible "soft" errors can be. These are non-fatal returns * of various network related functions, like recv() and so on. * @@ -81,7 +93,7 @@ #define DLVL(x) ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(x) -/* +/*!< * DLVL(90) -- Function entry/exit and other tracing. * DLVL(70) -- Socket "correctness" -- including returning of events, etc. * DLVL(60) -- Socket data send/receive @@ -105,7 +117,7 @@ typedef isc_event_t intev_t; #define SOCKET_MAGIC ISC_MAGIC('I', 'O', 'i', 'o') #define VALID_SOCKET(t) ISC_MAGIC_VALID(t, SOCKET_MAGIC) -/* +/*! * IPv6 control information. If the socket is an IPv6 socket we want * to collect the destination address and interface so the client can * set them on outgoing packets. @@ -116,7 +128,7 @@ typedef isc_event_t intev_t; #endif #endif -/* +/*% * NetBSD and FreeBSD can timestamp packets. XXXMLG Should we have * a setsockopt() like interface to request timestamps, and if the OS * doesn't do it for us, call gettimeofday() on every UDP receive? @@ -127,7 +139,12 @@ typedef isc_event_t intev_t; #endif #endif -/* +/*% + * The size to raise the recieve buffer to (from BIND 8). + */ +#define RCVBUFSIZE (32*1024) + +/*% * The number of times a send operation is repeated if the result is EINTR. */ #define NRETRIES 10 @@ -241,9 +258,9 @@ static void build_msghdr_recv(isc_socket_t *, isc_socketevent_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_ACCEPT (-3) /*%< Same as _READ */ #define SELECT_POKE_WRITE (-4) -#define SELECT_POKE_CONNECT (-4) /* Same as _WRITE */ +#define SELECT_POKE_CONNECT (-4) /*%< Same as _WRITE */ #define SELECT_POKE_CLOSE (-5) #define SOCK_DEAD(s) ((s)->references == 0) @@ -873,6 +890,15 @@ set_dev_address(isc_sockaddr_t *address, isc_socket_t *sock, } } +static void +destroy_socketevent(isc_event_t *event) { + isc_socketevent_t *ev = (isc_socketevent_t *)event; + + INSIST(ISC_LIST_EMPTY(ev->bufferlist)); + + (ev->destroy)(event); +} + static isc_socketevent_t * allocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype, isc_taskaction_t action, const void *arg) @@ -894,6 +920,8 @@ allocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype, ev->n = 0; ev->offset = 0; ev->attributes = 0; + ev->destroy = ev->ev_destroy; + ev->ev_destroy = destroy_socketevent; return (ev); } @@ -1228,7 +1256,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, isc_socket_t **socketp) { isc_socket_t *sock; - isc_result_t ret; + isc_result_t result; ISC_SOCKADDR_LEN_T cmsgbuflen; sock = isc_mem_get(manager->mctx, sizeof(*sock)); @@ -1236,7 +1264,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, if (sock == NULL) return (ISC_R_NOMEMORY); - ret = ISC_R_UNEXPECTED; + result = ISC_R_UNEXPECTED; sock->magic = 0; sock->references = 0; @@ -1296,13 +1324,9 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, /* * initialize the lock */ - if (isc_mutex_init(&sock->lock) != ISC_R_SUCCESS) { + result = isc_mutex_init(&sock->lock); + if (result != ISC_R_SUCCESS) { sock->magic = 0; - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_mutex_init() %s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed")); - ret = ISC_R_UNEXPECTED; goto error; } @@ -1330,7 +1354,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, sock->sendcmsgbuflen); isc_mem_put(manager->mctx, sock, sizeof(*sock)); - return (ret); + return (result); } /* @@ -1371,7 +1395,45 @@ free_socket(isc_socket_t **socketp) { *socketp = NULL; } +#ifdef SO_BSDCOMPAT /* + * This really should not be necessary to do. Having to workout + * which kernel version we are on at run time so that we don't cause + * the kernel to issue a warning about us using a deprecated socket option. + * Such warnings should *never* be on by default in production kernels. + * + * We can't do this a build time because executables are moved between + * machines and hence kernels. + * + * We can't just not set SO_BSDCOMAT because some kernels require it. + */ + +static isc_once_t bsdcompat_once = ISC_ONCE_INIT; +isc_boolean_t bsdcompat = ISC_TRUE; + +static void +clear_bsdcompat(void) { +#ifdef __linux__ + struct utsname buf; + char *endp; + long int major; + long int minor; + + uname(&buf); /* Can only fail if buf is bad in Linux. */ + + /* Paranoia in parsing can be increased, but we trust uname(). */ + major = strtol(buf.release, &endp, 10); + if (*endp == '.') { + minor = strtol(endp+1, &endp, 10); + if ((major > 2) || ((major == 2) && (minor >= 4))) { + bsdcompat = ISC_FALSE; + } + } +#endif /* __linux __ */ +} +#endif + +/*% * Create a new 'type' socket managed by 'manager'. Events * will be posted to 'task' and when dispatched 'action' will be * called with 'arg' as the arg value. The new socket is returned @@ -1382,21 +1444,27 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, isc_socket_t **socketp) { isc_socket_t *sock = NULL; - isc_result_t ret; + isc_result_t result; #if defined(USE_CMSG) || defined(SO_BSDCOMPAT) int on = 1; #endif +#if defined(SO_RCVBUF) + ISC_SOCKADDR_LEN_T optlen; + int size; +#endif char strbuf[ISC_STRERRORSIZE]; const char *err = "socket"; + int try = 0; REQUIRE(VALID_MANAGER(manager)); REQUIRE(socketp != NULL && *socketp == NULL); - ret = allocate_socket(manager, type, &sock); - if (ret != ISC_R_SUCCESS) - return (ret); + result = allocate_socket(manager, type, &sock); + if (result != ISC_R_SUCCESS) + return (result); sock->pf = pf; + again: switch (type) { case isc_sockettype_udp: sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP); @@ -1404,7 +1472,12 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, case isc_sockettype_tcp: sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP); break; + case isc_sockettype_unix: + sock->fd = socket(pf, SOCK_STREAM, 0); + break; } + if (sock->fd == -1 && errno == EINTR && try++ < 42) + goto again; #ifdef F_DUPFD /* @@ -1471,7 +1544,10 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, } #ifdef SO_BSDCOMPAT - if (setsockopt(sock->fd, SOL_SOCKET, SO_BSDCOMPAT, + RUNTIME_CHECK(isc_once_do(&bsdcompat_once, + clear_bsdcompat) == ISC_R_SUCCESS); + if (type != isc_sockettype_unix && bsdcompat && + setsockopt(sock->fd, SOL_SOCKET, SO_BSDCOMPAT, (void *)&on, sizeof(on)) < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, @@ -1484,9 +1560,10 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, } #endif -#if defined(USE_CMSG) +#if defined(USE_CMSG) || defined(SO_RCVBUF) if (type == isc_sockettype_udp) { +#if defined(USE_CMSG) #if defined(SO_TIMESTAMP) if (setsockopt(sock->fd, SOL_SOCKET, SO_TIMESTAMP, (void *)&on, sizeof(on)) < 0 @@ -1516,7 +1593,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, } #ifdef ISC_PLATFORM_HAVEIN6PKTINFO #ifdef IPV6_RECVPKTINFO - /* 2292bis */ + /* RFC 3542 */ if ((pf == AF_INET6) && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, (void *)&on, sizeof(on)) < 0)) { @@ -1531,7 +1608,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, strbuf); } #else - /* 2292 */ + /* RFC 2292 */ if ((pf == AF_INET6) && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO, (void *)&on, sizeof(on)) < 0)) { @@ -1547,7 +1624,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, } #endif /* IPV6_RECVPKTINFO */ #endif /* ISC_PLATFORM_HAVEIN6PKTINFO */ -#ifdef IPV6_USE_MIN_MTU /*2292bis, not too common yet*/ +#ifdef IPV6_USE_MIN_MTU /* RFC 3542, not too common yet*/ /* use minimum MTU */ if (pf == AF_INET6) { (void)setsockopt(sock->fd, IPPROTO_IPV6, @@ -1556,9 +1633,30 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, } #endif #endif /* ISC_PLATFORM_HAVEIPV6 */ - +#endif /* defined(USE_CMSG) */ + +#if defined(SO_RCVBUF) + optlen = sizeof(size); + if (getsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF, + (void *)&size, &optlen) >= 0 && + size < RCVBUFSIZE) { + size = RCVBUFSIZE; + if (setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF, + (void *)&size, sizeof(size)) == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "setsockopt(%d, SO_RCVBUF, %d) %s: %s", + sock->fd, size, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, + "failed"), + strbuf); + } + } +#endif } -#endif /* USE_CMSG */ +#endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */ sock->references = 1; *socketp = sock; @@ -2319,6 +2417,7 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { #ifdef ISC_PLATFORM_USETHREADS char strbuf[ISC_STRERRORSIZE]; #endif + isc_result_t result; REQUIRE(managerp != NULL && *managerp == NULL); @@ -2338,13 +2437,10 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { manager->mctx = NULL; memset(manager->fds, 0, sizeof(manager->fds)); ISC_LIST_INIT(manager->socklist); - if (isc_mutex_init(&manager->lock) != ISC_R_SUCCESS) { + result = isc_mutex_init(&manager->lock); + if (result != ISC_R_SUCCESS) { isc_mem_put(mctx, manager, sizeof(*manager)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_mutex_init() %s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed")); - return (ISC_R_UNEXPECTED); + return (result); } #ifdef ISC_PLATFORM_USETHREADS if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) { @@ -2887,6 +2983,190 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, return (socket_send(sock, event, task, address, pktinfo, flags)); } +void +isc_socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active) { +#ifdef ISC_PLATFORM_HAVESYSUNH + int s; + struct stat sb; + char strbuf[ISC_STRERRORSIZE]; + + if (sockaddr->type.sa.sa_family != AF_UNIX) + return; + +#ifndef S_ISSOCK +#if defined(S_IFMT) && defined(S_IFSOCK) +#define S_ISSOCK(mode) ((mode & S_IFMT)==S_IFSOCK) +#elif defined(_S_IFMT) && defined(S_IFSOCK) +#define S_ISSOCK(mode) ((mode & _S_IFMT)==S_IFSOCK) +#endif +#endif + +#ifndef S_ISFIFO +#if defined(S_IFMT) && defined(S_IFIFO) +#define S_ISFIFO(mode) ((mode & S_IFMT)==S_IFIFO) +#elif defined(_S_IFMT) && defined(S_IFIFO) +#define S_ISFIFO(mode) ((mode & _S_IFMT)==S_IFIFO) +#endif +#endif + +#if !defined(S_ISFIFO) && !defined(S_ISSOCK) +#error You need to define S_ISFIFO and S_ISSOCK as appropriate for your platform. See <sys/stat.h>. +#endif + +#ifndef S_ISFIFO +#define S_ISFIFO(mode) 0 +#endif + +#ifndef S_ISSOCK +#define S_ISSOCK(mode) 0 +#endif + + if (active) { + if (stat(sockaddr->type.sunix.sun_path, &sb) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, + "isc_socket_cleanunix: stat(%s): %s", + sockaddr->type.sunix.sun_path, strbuf); + return; + } + if (!(S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode))) { + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, + "isc_socket_cleanunix: %s: not a socket", + sockaddr->type.sunix.sun_path); + return; + } + if (unlink(sockaddr->type.sunix.sun_path) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, + "isc_socket_cleanunix: unlink(%s): %s", + sockaddr->type.sunix.sun_path, strbuf); + } + return; + } + + s = socket(AF_UNIX, SOCK_STREAM, 0); + if (s < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING, + "isc_socket_cleanunix: socket(%s): %s", + sockaddr->type.sunix.sun_path, strbuf); + return; + } + + if (stat(sockaddr->type.sunix.sun_path, &sb) < 0) { + switch (errno) { + case ENOENT: /* We exited cleanly last time */ + break; + default: + isc__strerror(errno, strbuf, sizeof(strbuf)); + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING, + "isc_socket_cleanunix: stat(%s): %s", + sockaddr->type.sunix.sun_path, strbuf); + break; + } + goto cleanup; + } + + if (!(S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode))) { + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING, + "isc_socket_cleanunix: %s: not a socket", + sockaddr->type.sunix.sun_path); + goto cleanup; + } + + if (connect(s, (struct sockaddr *)&sockaddr->type.sunix, + sizeof(sockaddr->type.sunix)) < 0) { + switch (errno) { + case ECONNREFUSED: + case ECONNRESET: + if (unlink(sockaddr->type.sunix.sun_path) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_SOCKET, + ISC_LOG_WARNING, + "isc_socket_cleanunix: " + "unlink(%s): %s", + sockaddr->type.sunix.sun_path, + strbuf); + } + break; + default: + isc__strerror(errno, strbuf, sizeof(strbuf)); + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING, + "isc_socket_cleanunix: connect(%s): %s", + sockaddr->type.sunix.sun_path, strbuf); + break; + } + } + cleanup: + close(s); +#else + UNUSED(sockaddr); + UNUSED(active); +#endif +} + +isc_result_t +isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm, + isc_uint32_t owner, isc_uint32_t group) +{ +#ifdef ISC_PLATFORM_HAVESYSUNH + isc_result_t result = ISC_R_SUCCESS; + char strbuf[ISC_STRERRORSIZE]; + char path[sizeof(sockaddr->type.sunix.sun_path)]; +#ifdef NEED_SECURE_DIRECTORY + char *slash; +#endif + + REQUIRE(sockaddr->type.sa.sa_family == AF_UNIX); + INSIST(strlen(sockaddr->type.sunix.sun_path) < sizeof(path)); + strcpy(path, sockaddr->type.sunix.sun_path); + +#ifdef NEED_SECURE_DIRECTORY + slash = strrchr(path, '/'); + if (slash != NULL) { + if (slash != path) + *slash = '\0'; + else + strcpy(path, "/"); + } else + strcpy(path, "."); +#endif + + if (chmod(path, perm) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, + "isc_socket_permunix: chmod(%s, %d): %s", + path, perm, strbuf); + result = ISC_R_FAILURE; + } + if (chown(path, owner, group) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, + "isc_socket_permunix: chown(%s, %d, %d): %s", + path, owner, group, + strbuf); + result = ISC_R_FAILURE; + } + return (result); +#else + UNUSED(sockaddr); + UNUSED(perm); + UNUSED(owner); + UNUSED(group); + return (ISC_R_NOTIMPLEMENTED); +#endif +} + isc_result_t isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr) { char strbuf[ISC_STRERRORSIZE]; @@ -2903,6 +3183,10 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr) { /* * Only set SO_REUSEADDR when we want a specific port. */ +#ifdef AF_UNIX + if (sock->pf == AF_UNIX) + goto bind_socket; +#endif if (isc_sockaddr_getport(sockaddr) != (in_port_t)0 && setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)) < 0) { @@ -2915,6 +3199,9 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr) { if ((privsep ? isc_priv_bind(sock->fd, &sockaddr->type.sa, sockaddr->length) : bind(sock->fd, &sockaddr->type.sa, sockaddr->length)) < 0) { +#ifdef AF_UNIX + bind_socket: +#endif UNLOCK(&sock->lock); switch (errno) { case EACCES: @@ -2996,7 +3283,8 @@ isc_socket_listen(isc_socket_t *sock, unsigned int backlog) { REQUIRE(!sock->listener); REQUIRE(sock->bound); - REQUIRE(sock->type == isc_sockettype_tcp); + REQUIRE(sock->type == isc_sockettype_tcp || + sock->type == isc_sockettype_unix); if (backlog == 0) backlog = SOMAXCONN; @@ -3027,7 +3315,7 @@ isc_socket_accept(isc_socket_t *sock, isc_socketmgr_t *manager; isc_task_t *ntask = NULL; isc_socket_t *nsock; - isc_result_t ret; + isc_result_t result; isc_boolean_t do_poke = ISC_FALSE; REQUIRE(VALID_SOCKET(sock)); @@ -3052,11 +3340,11 @@ isc_socket_accept(isc_socket_t *sock, } ISC_LINK_INIT(dev, ev_link); - ret = allocate_socket(manager, sock->type, &nsock); - if (ret != ISC_R_SUCCESS) { + result = allocate_socket(manager, sock->type, &nsock); + if (result != ISC_R_SUCCESS) { isc_event_free(ISC_EVENT_PTR(&dev)); UNLOCK(&sock->lock); - return (ret); + return (result); } /* @@ -3320,7 +3608,7 @@ internal_connect(isc_task_t *me, isc_event_t *ev) { isc_result_t isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) { - isc_result_t ret; + isc_result_t result; REQUIRE(VALID_SOCKET(sock)); REQUIRE(addressp != NULL); @@ -3329,20 +3617,20 @@ isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) { if (sock->connected) { *addressp = sock->address; - ret = ISC_R_SUCCESS; + result = ISC_R_SUCCESS; } else { - ret = ISC_R_NOTCONNECTED; + result = ISC_R_NOTCONNECTED; } UNLOCK(&sock->lock); - return (ret); + return (result); } isc_result_t isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) { ISC_SOCKADDR_LEN_T len; - isc_result_t ret; + isc_result_t result; char strbuf[ISC_STRERRORSIZE]; REQUIRE(VALID_SOCKET(sock)); @@ -3351,18 +3639,18 @@ isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) { LOCK(&sock->lock); if (!sock->bound) { - ret = ISC_R_NOTBOUND; + result = ISC_R_NOTBOUND; goto out; } - ret = ISC_R_SUCCESS; + result = ISC_R_SUCCESS; len = sizeof(addressp->type); if (getsockname(sock->fd, &addressp->type.sa, (void *)&len) < 0) { isc__strerror(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "getsockname: %s", strbuf); - ret = ISC_R_UNEXPECTED; + result = ISC_R_UNEXPECTED; goto out; } addressp->length = (unsigned int)len; @@ -3370,7 +3658,7 @@ isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) { out: UNLOCK(&sock->lock); - return (ret); + return (result); } /* diff --git a/usr.sbin/bind/lib/isc/unix/time.c b/usr.sbin/bind/lib/isc/unix/time.c index 34cfde620d2..09d9686c251 100644 --- a/usr.sbin/bind/lib/isc/unix/time.c +++ b/usr.sbin/bind/lib/isc/unix/time.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,7 +15,9 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $ISC: time.c,v 1.34.2.6.2.4 2004/03/06 08:15:03 marka Exp $ */ +/* $ISC: time.c,v 1.47.18.2 2005/04/29 00:17:09 marka Exp $ */ + +/*! \file */ #include <config.h> @@ -33,9 +35,9 @@ #include <isc/time.h> #include <isc/util.h> -#define NS_PER_S 1000000000 /* Nanoseconds per second. */ -#define NS_PER_US 1000 /* Nanoseconds per microsecond. */ -#define US_PER_S 1000000 /* Microseconds per second. */ +#define NS_PER_S 1000000000 /*%< Nanoseconds per second. */ +#define NS_PER_US 1000 /*%< Nanoseconds per microsecond. */ +#define US_PER_S 1000000 /*%< Microseconds per second. */ /* * All of the INSIST()s checks of nanoseconds < NS_PER_S are for @@ -48,7 +50,7 @@ #define ISC_FIX_TV_USEC 1 #endif -/*** +/*% *** Intervals ***/ |