]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
unmodified bind-9.9.1
authorDave Hart <hart@ntp.org>
Fri, 1 Jun 2012 18:17:30 +0000 (18:17 +0000)
committerDave Hart <hart@ntp.org>
Fri, 1 Jun 2012 18:17:30 +0000 (18:17 +0000)
bk: 4fc9073amjXl8T1sjgPH6WuZo73Odg

146 files changed:
lib/isc/Atffile [new file with mode: 0644]
lib/isc/alpha/include/isc/atomic.h
lib/isc/api
lib/isc/app_api.c [new file with mode: 0644]
lib/isc/assertions.c
lib/isc/backtrace-emptytbl.c [new file with mode: 0644]
lib/isc/backtrace.c [new file with mode: 0644]
lib/isc/base32.c
lib/isc/base64.c
lib/isc/entropy.c
lib/isc/hash.c
lib/isc/heap.c
lib/isc/hmacmd5.c
lib/isc/hmacsha.c
lib/isc/httpd.c
lib/isc/ia64/include/isc/atomic.h
lib/isc/include/isc/app.h
lib/isc/include/isc/assertions.h
lib/isc/include/isc/backtrace.h [new file with mode: 0644]
lib/isc/include/isc/bind9.h [new file with mode: 0644]
lib/isc/include/isc/buffer.h
lib/isc/include/isc/entropy.h
lib/isc/include/isc/error.h
lib/isc/include/isc/file.h
lib/isc/include/isc/fsaccess.h
lib/isc/include/isc/hash.h
lib/isc/include/isc/heap.h
lib/isc/include/isc/hmacmd5.h
lib/isc/include/isc/hmacsha.h
lib/isc/include/isc/lib.h
lib/isc/include/isc/list.h
lib/isc/include/isc/log.h
lib/isc/include/isc/md5.h
lib/isc/include/isc/mem.h
lib/isc/include/isc/msgs.h
lib/isc/include/isc/namespace.h [new file with mode: 0644]
lib/isc/include/isc/netaddr.h
lib/isc/include/isc/netscope.h
lib/isc/include/isc/platform.h.in
lib/isc/include/isc/portset.h
lib/isc/include/isc/queue.h [new file with mode: 0644]
lib/isc/include/isc/radix.h
lib/isc/include/isc/random.h
lib/isc/include/isc/ratelimiter.h
lib/isc/include/isc/refcount.h
lib/isc/include/isc/result.h
lib/isc/include/isc/resultclass.h
lib/isc/include/isc/serial.h
lib/isc/include/isc/sha1.h
lib/isc/include/isc/sha2.h
lib/isc/include/isc/sockaddr.h
lib/isc/include/isc/socket.h
lib/isc/include/isc/stats.h
lib/isc/include/isc/symtab.h
lib/isc/include/isc/task.h
lib/isc/include/isc/taskpool.h
lib/isc/include/isc/timer.h
lib/isc/include/isc/types.h
lib/isc/include/isc/util.h
lib/isc/inet_aton.c
lib/isc/inet_ntop.c
lib/isc/iterated_hash.c
lib/isc/lib.c
lib/isc/log.c
lib/isc/md5.c
lib/isc/mem.c
lib/isc/mem_api.c [new file with mode: 0644]
lib/isc/mutexblock.c
lib/isc/netaddr.c
lib/isc/powerpc/include/isc/atomic.h
lib/isc/print.c
lib/isc/pthreads/mutex.c
lib/isc/radix.c
lib/isc/random.c
lib/isc/result.c
lib/isc/rwlock.c
lib/isc/sha1.c
lib/isc/sha2.c
lib/isc/sockaddr.c
lib/isc/socket_api.c [new file with mode: 0644]
lib/isc/stats.c
lib/isc/string.c
lib/isc/symtab.c
lib/isc/task.c
lib/isc/task_api.c [new file with mode: 0644]
lib/isc/task_p.h
lib/isc/taskpool.c
lib/isc/tests/Atffile [new file with mode: 0644]
lib/isc/tests/hash_test.c [new file with mode: 0644]
lib/isc/tests/isctest.c [new file with mode: 0644]
lib/isc/tests/isctest.h [new file with mode: 0644]
lib/isc/tests/queue_test.c [new file with mode: 0644]
lib/isc/tests/socket_test.c [new file with mode: 0644]
lib/isc/tests/symtab_test.c [new file with mode: 0644]
lib/isc/tests/task_test.c [new file with mode: 0644]
lib/isc/tests/taskpool_test.c [new file with mode: 0644]
lib/isc/timer.c
lib/isc/timer_api.c [new file with mode: 0644]
lib/isc/timer_p.h
lib/isc/unix/app.c
lib/isc/unix/dir.c
lib/isc/unix/entropy.c
lib/isc/unix/errno2result.c
lib/isc/unix/errno2result.h
lib/isc/unix/file.c
lib/isc/unix/ifiter_getifaddrs.c
lib/isc/unix/ifiter_ioctl.c
lib/isc/unix/include/isc/net.h
lib/isc/unix/include/isc/offset.h
lib/isc/unix/include/isc/stdtime.h
lib/isc/unix/include/isc/strerror.h
lib/isc/unix/include/isc/time.h
lib/isc/unix/interfaceiter.c
lib/isc/unix/net.c
lib/isc/unix/resource.c
lib/isc/unix/socket.c
lib/isc/unix/socket_p.h
lib/isc/unix/stdio.c
lib/isc/unix/strerror.c
lib/isc/unix/time.c
lib/isc/win32/app.c
lib/isc/win32/dir.c
lib/isc/win32/entropy.c
lib/isc/win32/file.c
lib/isc/win32/include/isc/ipv6.h
lib/isc/win32/include/isc/mutex.h
lib/isc/win32/include/isc/net.h
lib/isc/win32/include/isc/ntpaths.h
lib/isc/win32/include/isc/platform.h
lib/isc/win32/include/isc/stat.h
lib/isc/win32/include/isc/stdtime.h
lib/isc/win32/include/isc/thread.h
lib/isc/win32/include/isc/time.h
lib/isc/win32/include/isc/win32os.h
lib/isc/win32/interfaceiter.c
lib/isc/win32/libgen.h [new file with mode: 0644]
lib/isc/win32/libisc.def
lib/isc/win32/libisc.dsp
lib/isc/win32/libisc.mak
lib/isc/win32/net.c
lib/isc/win32/netdb.h
lib/isc/win32/ntgroups.c
lib/isc/win32/ntpaths.c
lib/isc/win32/socket.c
lib/isc/win32/time.c
lib/isc/win32/unistd.h

diff --git a/lib/isc/Atffile b/lib/isc/Atffile
new file mode 100644 (file)
index 0000000..1edb838
--- /dev/null
@@ -0,0 +1,5 @@
+Content-Type: application/X-atf-atffile; version="1"
+
+prop: test-suite = bind9
+
+tp: tests
index bc1510ffa15c379f0e0101dc7510bb90f9c3400a..a6232ada6fc724d2cf54883c3a1c11cdae91c2bd 100644 (file)
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: atomic.h,v 1.5.332.2 2009/04/08 06:47:32 tbox Exp $ */
+/* $Id: atomic.h,v 1.7 2009/04/08 06:48:23 tbox Exp $ */
 
 /*
  * This code was written based on FreeBSD's kernel source whose copyright
index 5ef8dc035a3ef83118d254cd0dee05b741324b77..ed4b69f8b8f7c3d8501c57b3fd5c62f0c203aaa4 100644 (file)
@@ -1,3 +1,8 @@
-LIBINTERFACE = 51
+# LIBINTERFACE ranges
+# 9.6: 50-59, 110-119
+# 9.7: 60-79
+# 9.8: 80-89
+# 9.9: 90-109
+LIBINTERFACE = 91
 LIBREVISION = 1
 LIBAGE = 1
diff --git a/lib/isc/app_api.c b/lib/isc/app_api.c
new file mode 100644 (file)
index 0000000..ce767d1
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: app_api.c,v 1.5 2009/09/02 23:48:02 tbox Exp $ */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/util.h>
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_appctxcreatefunc_t appctx_createfunc = NULL;
+
+#define ISCAPI_APPMETHODS_VALID(m) ISC_MAGIC_VALID(m, ISCAPI_APPMETHODS_MAGIC)
+
+static void
+initialize(void) {
+       RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_app_register(isc_appctxcreatefunc_t createfunc) {
+       isc_result_t result = ISC_R_SUCCESS;
+
+       RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+       LOCK(&createlock);
+       if (appctx_createfunc == NULL)
+               appctx_createfunc = createfunc;
+       else
+               result = ISC_R_EXISTS;
+       UNLOCK(&createlock);
+
+       return (result);
+}
+
+isc_result_t
+isc_appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) {
+       isc_result_t result;
+
+       LOCK(&createlock);
+
+       REQUIRE(appctx_createfunc != NULL);
+       result = (*appctx_createfunc)(mctx, ctxp);
+
+       UNLOCK(&createlock);
+
+       return (result);
+}
+
+void
+isc_appctx_destroy(isc_appctx_t **ctxp) {
+       REQUIRE(ctxp != NULL && ISCAPI_APPCTX_VALID(*ctxp));
+
+       (*ctxp)->methods->ctxdestroy(ctxp);
+
+       ENSURE(*ctxp == NULL);
+}
+
+isc_result_t
+isc_app_ctxstart(isc_appctx_t *ctx) {
+       REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+
+       return (ctx->methods->ctxstart(ctx));
+}
+
+isc_result_t
+isc_app_ctxrun(isc_appctx_t *ctx) {
+       REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+
+       return (ctx->methods->ctxrun(ctx));
+}
+
+isc_result_t
+isc_app_ctxsuspend(isc_appctx_t *ctx) {
+       REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+
+       return (ctx->methods->ctxsuspend(ctx));
+}
+
+isc_result_t
+isc_app_ctxshutdown(isc_appctx_t *ctx) {
+       REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+
+       return (ctx->methods->ctxshutdown(ctx));
+}
+
+void
+isc_app_ctxfinish(isc_appctx_t *ctx) {
+       REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+
+       ctx->methods->ctxfinish(ctx);
+}
+
+void
+isc_appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr) {
+       REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+       REQUIRE(taskmgr != NULL);
+
+       ctx->methods->settaskmgr(ctx, taskmgr);
+}
+
+void
+isc_appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr) {
+       REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+       REQUIRE(socketmgr != NULL);
+
+       ctx->methods->setsocketmgr(ctx, socketmgr);
+}
+
+void
+isc_appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr) {
+       REQUIRE(ISCAPI_APPCTX_VALID(ctx));
+       REQUIRE(timermgr != NULL);
+
+       ctx->methods->settimermgr(ctx, timermgr);
+}
index 4c9251bdcf25199dd622049ae35821775caf842d..31c4fe7c9f273a2d109e43cd2fce2c9ae97aa3b7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1997-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: assertions.c,v 1.23 2008/10/15 23:47:31 tbox Exp $ */
+/* $Id: assertions.c,v 1.26 2009/09/29 15:06:07 fdupont Exp $ */
 
 /*! \file */
 
 #include <stdlib.h>
 
 #include <isc/assertions.h>
+#include <isc/backtrace.h>
 #include <isc/msgs.h>
+#include <isc/result.h>
+
+/*
+ * The maximum number of stack frames to dump on assertion failure.
+ */
+#ifndef BACKTRACE_MAXFRAME
+#define BACKTRACE_MAXFRAME 128
+#endif
 
 /*%
  * Forward.
  */
-/* coverity[+kill] */
 static void
 default_callback(const char *, int, isc_assertiontype_t, const char *);
 
+static isc_assertioncallback_t isc_assertion_failed_cb = default_callback;
+
 /*%
  * Public.
  */
 
-LIBISC_EXTERNAL_DATA isc_assertioncallback_t isc_assertion_failed =
-                                            default_callback;
+/*% assertion failed handler */
+/* coverity[+kill] */
+void
+isc_assertion_failed(const char *file, int line, isc_assertiontype_t type,
+                    const char *cond)
+{
+       isc_assertion_failed_cb(file, line, type, cond);
+       abort();
+       /* NOTREACHED */
+}
 
 /*% Set callback. */
 void
 isc_assertion_setcallback(isc_assertioncallback_t cb) {
        if (cb == NULL)
-               isc_assertion_failed = default_callback;
+               isc_assertion_failed_cb = default_callback;
        else
-               isc_assertion_failed = cb;
+               isc_assertion_failed_cb = cb;
 }
 
 /*% Type to Text */
@@ -87,11 +105,35 @@ static void
 default_callback(const char *file, int line, isc_assertiontype_t type,
                 const char *cond)
 {
-       fprintf(stderr, "%s:%d: %s(%s) %s.\n",
+       void *tracebuf[BACKTRACE_MAXFRAME];
+       int i, nframes;
+       const char *logsuffix = ".";
+       const char *fname;
+       isc_result_t result;
+
+       result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME, &nframes);
+               if (result == ISC_R_SUCCESS && nframes > 0)
+                       logsuffix = ", back trace";
+
+       fprintf(stderr, "%s:%d: %s(%s) %s%s\n",
                file, line, isc_assertion_typetotext(type), cond,
                isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
-                              ISC_MSG_FAILED, "failed"));
+                              ISC_MSG_FAILED, "failed"), logsuffix);
+       if (result == ISC_R_SUCCESS) {
+               for (i = 0; i < nframes; i++) {
+                       unsigned long offset;
+
+                       fname = NULL;
+                       result = isc_backtrace_getsymbol(tracebuf[i], &fname,
+                                                        &offset);
+                       if (result == ISC_R_SUCCESS) {
+                               fprintf(stderr, "#%d %p in %s()+0x%lx\n", i,
+                                       tracebuf[i], fname, offset);
+                       } else {
+                               fprintf(stderr, "#%d %p in ??\n", i,
+                                       tracebuf[i]);
+                       }
+               }
+       }
        fflush(stderr);
-       abort();
-       /* NOTREACHED */
 }
diff --git a/lib/isc/backtrace-emptytbl.c b/lib/isc/backtrace-emptytbl.c
new file mode 100644 (file)
index 0000000..bd534d6
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: backtrace-emptytbl.c,v 1.3 2009/09/01 20:13:44 each Exp $ */
+
+/*! \file */
+
+/*
+ * This file defines an empty (default) symbol table used in backtrace.c
+ * If the application wants to have a complete symbol table, it should redefine
+ * isc__backtrace_symtable with the complete table in some way, and link the
+ * version of the library not including this definition
+ * (e.g. libisc-nosymbol.a).
+ */
+
+#include <config.h>
+
+#include <isc/backtrace.h>
+
+const int isc__backtrace_nsymbols = 0;
+const isc_backtrace_symmap_t isc__backtrace_symtable[] = { { NULL, "" } };
diff --git a/lib/isc/backtrace.c b/lib/isc/backtrace.c
new file mode 100644 (file)
index 0000000..d2f044c
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: backtrace.c,v 1.3 2009/09/02 23:48:02 tbox Exp $ */
+
+/*! \file */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#ifdef HAVE_LIBCTRACE
+#include <execinfo.h>
+#endif
+
+#include <isc/backtrace.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#ifdef ISC_PLATFORM_USEBACKTRACE
+/*
+ * Getting a back trace of a running process is tricky and highly platform
+ * dependent.  Our current approach is as follows:
+ * 1. If the system library supports the "backtrace()" function, use it.
+ * 2. Otherwise, if the compiler is gcc and the architecture is x86_64 or IA64,
+ *    then use gcc's (hidden) Unwind_Backtrace() function.  Note that this
+ *    function doesn't work for C programs on many other architectures.
+ * 3. Otherwise, if the architecture x86 or x86_64, try to unwind the stack
+ *    frame following frame pointers.  This assumes the executable binary
+ *    compiled with frame pointers; this is not always true for x86_64 (rather,
+ *    compiler optimizations often disable frame pointers).  The validation
+ *    checks in getnextframeptr() hopefully rejects bogus values stored in
+ *    the RBP register in such a case.  If the backtrace function itself crashes
+ *    due to this problem, the whole package should be rebuilt with
+ *    --disable-backtrace.
+ */
+#ifdef HAVE_LIBCTRACE
+#define BACKTRACE_LIBC
+#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__ia64__))
+#define BACKTRACE_GCC
+#elif defined(__x86_64__) || defined(__i386__)
+#define BACKTRACE_X86STACK
+#else
+#define BACKTRACE_DISABLED
+#endif  /* HAVE_LIBCTRACE */
+#else  /* !ISC_PLATFORM_USEBACKTRACE */
+#define BACKTRACE_DISABLED
+#endif /* ISC_PLATFORM_USEBACKTRACE */
+
+#ifdef BACKTRACE_LIBC
+isc_result_t
+isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) {
+       int n;
+
+       /*
+        * Validate the arguments: intentionally avoid using REQUIRE().
+        * See notes in backtrace.h.
+        */
+       if (addrs == NULL || nframes == NULL)
+               return (ISC_R_FAILURE);
+
+       /*
+        * backtrace(3) includes this function itself in the address array,
+        * which should be eliminated from the returned sequence.
+        */
+       n = backtrace(addrs, maxaddrs);
+       if (n < 2)
+               return (ISC_R_NOTFOUND);
+       n--;
+       memmove(addrs, &addrs[1], sizeof(void *) * n);
+       *nframes = n;
+       return (ISC_R_SUCCESS);
+}
+#elif defined(BACKTRACE_GCC)
+extern int _Unwind_Backtrace(void* fn, void* a);
+extern void* _Unwind_GetIP(void* ctx);
+
+typedef struct {
+       void **result;
+       int max_depth;
+       int skip_count;
+       int count;
+} trace_arg_t;
+
+static int
+btcallback(void *uc, void *opq) {
+       trace_arg_t *arg = (trace_arg_t *)opq;
+
+       if (arg->skip_count > 0)
+               arg->skip_count--;
+       else
+               arg->result[arg->count++] = (void *)_Unwind_GetIP(uc);
+       if (arg->count == arg->max_depth)
+               return (5); /* _URC_END_OF_STACK */
+
+       return (0); /* _URC_NO_REASON */
+}
+
+isc_result_t
+isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) {
+       trace_arg_t arg;
+
+       /* Argument validation: see above. */
+       if (addrs == NULL || nframes == NULL)
+               return (ISC_R_FAILURE);
+
+       arg.skip_count = 1;
+       arg.result = addrs;
+       arg.max_depth = maxaddrs;
+       arg.count = 0;
+       _Unwind_Backtrace(btcallback, &arg);
+
+       *nframes = arg.count;
+
+       return (ISC_R_SUCCESS);
+}
+#elif defined(BACKTRACE_X86STACK)
+#ifdef __x86_64__
+static unsigned long
+getrbp() {
+       __asm("movq %rbp, %rax\n");
+}
+#endif
+
+static void **
+getnextframeptr(void **sp) {
+       void **newsp = (void **)*sp;
+
+       /*
+        * Perform sanity check for the new frame pointer, derived from
+        * google glog.  This can actually be bogus depending on compiler.
+        */
+
+       /* prohibit the stack frames from growing downwards */
+       if (newsp <= sp)
+               return (NULL);
+
+       /* A heuristics to reject "too large" frame: this actually happened. */
+       if ((char *)newsp - (char *)sp > 100000)
+               return (NULL);
+
+       /*
+        * Not sure if other checks used in glog are needed at this moment.
+        * For our purposes we don't have to consider non-contiguous frames,
+        * for example.
+        */
+
+       return (newsp);
+}
+
+isc_result_t
+isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) {
+       int i = 0;
+       void **sp;
+
+       /* Argument validation: see above. */
+       if (addrs == NULL || nframes == NULL)
+               return (ISC_R_FAILURE);
+
+#ifdef __x86_64__
+       sp = (void **)getrbp();
+       if (sp == NULL)
+               return (ISC_R_NOTFOUND);
+       /*
+        * sp is the frame ptr of this function itself due to the call to
+        * getrbp(), so need to unwind one frame for consistency.
+        */
+       sp = getnextframeptr(sp);
+#else
+       /*
+        * i386: the frame pointer is stored 2 words below the address for the
+        * first argument.  Note that the body of this function cannot be
+        * inlined since it depends on the address of the function argument.
+        */
+       sp = (void **)&addrs - 2;
+#endif
+
+       while (sp != NULL && i < maxaddrs) {
+               addrs[i++] = *(sp + 1);
+               sp = getnextframeptr(sp);
+       }
+
+       *nframes = i;
+
+       return (ISC_R_SUCCESS);
+}
+#elif defined(BACKTRACE_DISABLED)
+isc_result_t
+isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes) {
+       /* Argument validation: see above. */
+       if (addrs == NULL || nframes == NULL)
+               return (ISC_R_FAILURE);
+
+       UNUSED(maxaddrs);
+
+       return (ISC_R_NOTIMPLEMENTED);
+}
+#endif
+
+isc_result_t
+isc_backtrace_getsymbolfromindex(int index, const void **addrp,
+                                const char **symbolp)
+{
+       REQUIRE(addrp != NULL && *addrp == NULL);
+       REQUIRE(symbolp != NULL && *symbolp == NULL);
+
+       if (index < 0 || index >= isc__backtrace_nsymbols)
+               return (ISC_R_RANGE);
+
+       *addrp = isc__backtrace_symtable[index].addr;
+       *symbolp = isc__backtrace_symtable[index].symbol;
+       return (ISC_R_SUCCESS);
+}
+
+static int
+symtbl_compare(const void *addr, const void *entryarg) {
+       const isc_backtrace_symmap_t *entry = entryarg;
+       const isc_backtrace_symmap_t *end =
+               &isc__backtrace_symtable[isc__backtrace_nsymbols - 1];
+
+       if (isc__backtrace_nsymbols == 1 || entry == end) {
+               if (addr >= entry->addr) {
+                       /*
+                        * If addr is equal to or larger than that of the last
+                        * entry of the table, we cannot be sure if this is
+                        * within a valid range so we consider it valid.
+                        */
+                       return (0);
+               }
+               return (-1);
+       }
+
+       /* entry + 1 is a valid entry from now on. */
+       if (addr < entry->addr)
+               return (-1);
+       else if (addr >= (entry + 1)->addr)
+               return (1);
+       return (0);
+}
+
+isc_result_t
+isc_backtrace_getsymbol(const void *addr, const char **symbolp,
+                       unsigned long *offsetp)
+{
+       isc_result_t result = ISC_R_SUCCESS;
+       isc_backtrace_symmap_t *found;
+
+       /*
+        * Validate the arguments: intentionally avoid using REQUIRE().
+        * See notes in backtrace.h.
+        */
+       if (symbolp == NULL || *symbolp != NULL || offsetp == NULL)
+               return (ISC_R_FAILURE);
+
+       if (isc__backtrace_nsymbols < 1)
+               return (ISC_R_NOTFOUND);
+
+       /*
+        * Search the table for the entry that meets:
+        * entry.addr <= addr < next_entry.addr.
+        */
+       found = bsearch(addr, isc__backtrace_symtable, isc__backtrace_nsymbols,
+                       sizeof(isc__backtrace_symtable[0]), symtbl_compare);
+       if (found == NULL)
+               result = ISC_R_NOTFOUND;
+       else {
+               *symbolp = found->symbol;
+               *offsetp = (const char *)addr - (char *)found->addr;
+       }
+
+       return (result);
+}
index 3000a84f2da14b9f1f10724d69993cc5abc5983a..d25e3c4716bbe3ffec344b7d16279c809c04ac48 100644 (file)
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: base32.c,v 1.3.116.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: base32.c,v 1.6 2009/10/21 01:22:29 each Exp $ */
 
 /*! \file */
 
@@ -112,6 +112,8 @@ base32_totext(isc_region_t *source, int wordlength, const char *wordbreak,
                        RETERR(str_totext(wordbreak, target));
                }
        }
+       if (source->length > 0)
+               isc_region_consume(source, source->length);
        return (ISC_R_SUCCESS);
 }
 
index 13ed6b5c5c170af346359046dd4240965497891b..bad1565bea7b329fbe46720a8a419d3b22459f66 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: base64.c,v 1.32 2007/06/19 23:47:17 tbox Exp $ */
+/* $Id: base64.c,v 1.34 2009/10/21 23:48:05 tbox Exp $ */
 
 /*! \file */
 
@@ -85,11 +85,13 @@ isc_base64_totext(isc_region_t *source, int wordlength,
                buf[2] = base64[((source->base[1]<<2)&0x3c)];
                buf[3] = '=';
                RETERR(str_totext(buf, target));
+               isc_region_consume(source, 2);
        } else if (source->length == 1) {
                buf[0] = base64[(source->base[0]>>2)&0x3f];
                buf[1] = base64[((source->base[0]<<4)&0x30)];
                buf[2] = buf[3] = '=';
                RETERR(str_totext(buf, target));
+               isc_region_consume(source, 1);
        }
        return (ISC_R_SUCCESS);
 }
@@ -217,7 +219,7 @@ isc_base64_decodestring(const char *cstr, isc_buffer_t *target) {
                        continue;
                RETERR(base64_decode_char(&ctx, c));
        }
-       RETERR(base64_decode_finish(&ctx));     
+       RETERR(base64_decode_finish(&ctx));
        return (ISC_R_SUCCESS);
 }
 
index 25ab00218956bac7db1a251ac6c5a7c7e5839385..da9e81fb3129afd14ca3e47113da799b5bcdef9e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: entropy.c,v 1.18.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: entropy.c,v 1.22 2010/08/10 23:48:19 tbox Exp $ */
 
 /*! \file
  * \brief
@@ -283,8 +283,11 @@ entropypool_add_word(isc_entropypool_t *rp, isc_uint32_t val) {
        val ^= rp->pool[(rp->cursor + TAP3) & (RND_POOLWORDS - 1)];
        val ^= rp->pool[(rp->cursor + TAP4) & (RND_POOLWORDS - 1)];
        val ^= rp->pool[(rp->cursor + TAP5) & (RND_POOLWORDS - 1)];
-       rp->pool[rp->cursor++] ^=
-         ((val << rp->rotate) | (val >> (32 - rp->rotate)));
+       if (rp->rotate == 0)
+               rp->pool[rp->cursor++] ^= val;
+       else
+               rp->pool[rp->cursor++] ^=
+                 ((val << rp->rotate) | (val >> (32 - rp->rotate)));
 
        /*
         * If we have looped around the pool, increment the rotate
index 9911bdee8fe2fbff983a008bfa61e69024556550..f1d68c7700f50205075490d441058dd90750cbd6 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: hash.c,v 1.13.332.3 2009/05/07 23:47:12 tbox Exp $ */
+/* $Id: hash.c,v 1.16 2009/09/01 00:22:28 jinmei Exp $ */
 
 /*! \file
  * Some portion of this code was derived from universal hash function
@@ -194,8 +194,12 @@ isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy,
        hctx->vectorlen = vlen;
        hctx->rndvector = rv;
 
+#ifdef BIND9
        if (entropy != NULL)
                isc_entropy_attach(entropy, &hctx->entropy);
+#else
+       UNUSED(entropy);
+#endif
 
        *hctxp = hctx;
        return (ISC_R_SUCCESS);
@@ -236,18 +240,22 @@ isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit) {
 
 void
 isc_hash_ctxinit(isc_hash_t *hctx) {
-       isc_result_t result;
-
        LOCK(&hctx->lock);
 
        if (hctx->initialized == ISC_TRUE)
                goto out;
 
        if (hctx->entropy) {
+#ifdef BIND9
+               isc_result_t result;
+
                result = isc_entropy_getdata(hctx->entropy,
                                             hctx->rndvector, hctx->vectorlen,
                                             NULL, 0);
                INSIST(result == ISC_R_SUCCESS);
+#else
+               INSIST(0);
+#endif
        } else {
                isc_uint32_t pr;
                unsigned int i, copylen;
@@ -293,6 +301,7 @@ static void
 destroy(isc_hash_t **hctxp) {
        isc_hash_t *hctx;
        isc_mem_t *mctx;
+       unsigned char canary0[4], canary1[4];
 
        REQUIRE(hctxp != NULL && *hctxp != NULL);
        hctx = *hctxp;
@@ -303,8 +312,10 @@ destroy(isc_hash_t **hctxp) {
        isc_refcount_destroy(&hctx->refcnt);
 
        mctx = hctx->mctx;
+#ifdef BIND9
        if (hctx->entropy != NULL)
                isc_entropy_detach(&hctx->entropy);
+#endif
        if (hctx->rndvector != NULL)
                isc_mem_put(mctx, hctx->rndvector, hctx->vectorlen);
 
@@ -312,7 +323,10 @@ destroy(isc_hash_t **hctxp) {
 
        DESTROYLOCK(&hctx->lock);
 
+       memcpy(canary0, hctx + 1, sizeof(canary0));
        memset(hctx, 0, sizeof(isc_hash_t));
+       memcpy(canary1, hctx + 1, sizeof(canary1));
+       INSIST(memcmp(canary0, canary1, sizeof(canary0)) == 0);
        isc_mem_put(mctx, hctx, sizeof(isc_hash_t));
        isc_mem_detach(&mctx);
 }
index 91d78c06d468bcdb6b0a466e2631717dafbe79bd..ebadd2fd807cc5ac222f33d3c63d893396515769 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2010-2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1997-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: heap.c,v 1.37 2007/10/19 17:15:53 explorer Exp $ */
+/* $Id$ */
 
 /*! \file
  * Heap implementation of priority queues adapted from the following:
@@ -86,8 +86,9 @@ isc_heap_create(isc_mem_t *mctx, isc_heapcompare_t compare,
        if (heap == NULL)
                return (ISC_R_NOMEMORY);
        heap->magic = HEAP_MAGIC;
-       heap->mctx = mctx;
        heap->size = 0;
+       heap->mctx = NULL;
+       isc_mem_attach(mctx, &heap->mctx);
        if (size_increment == 0)
                heap->size_increment = SIZE_INCREMENT;
        else
@@ -114,7 +115,7 @@ isc_heap_destroy(isc_heap_t **heapp) {
                isc_mem_put(heap->mctx, heap->array,
                            heap->size * sizeof(void *));
        heap->magic = 0;
-       isc_mem_put(heap->mctx, heap, sizeof(*heap));
+       isc_mem_putanddetach(&heap->mctx, heap, sizeof(*heap));
 
        *heapp = NULL;
 }
@@ -186,15 +187,17 @@ sink_down(isc_heap_t *heap, unsigned int i, void *elt) {
 
 isc_result_t
 isc_heap_insert(isc_heap_t *heap, void *elt) {
-       unsigned int i;
+       unsigned int new_last;
 
        REQUIRE(VALID_HEAP(heap));
 
-       i = ++heap->last;
-       if (heap->last >= heap->size && !resize(heap))
+       new_last = heap->last + 1;
+       RUNTIME_CHECK(new_last > 0); /* overflow check */
+       if (new_last >= heap->size && !resize(heap))
                return (ISC_R_NOMEMORY);
+       heap->last = new_last;
 
-       float_up(heap, i, elt);
+       float_up(heap, new_last, elt);
 
        return (ISC_R_SUCCESS);
 }
index 63853dcd4191d65e8c51f16c155b58b4d1241c2c..6abe6e27df8e37010db04872efac0fcf5c290898 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: hmacmd5.c,v 1.14 2007/06/19 23:47:17 tbox Exp $ */
+/* $Id: hmacmd5.c,v 1.16 2009/02/06 23:47:42 tbox Exp $ */
 
 /*! \file
  * This code implements the HMAC-MD5 keyed hash algorithm
 #include <isc/assertions.h>
 #include <isc/hmacmd5.h>
 #include <isc/md5.h>
+#include <isc/platform.h>
 #include <isc/string.h>
 #include <isc/types.h>
 #include <isc/util.h>
 
+#ifdef ISC_PLATFORM_OPENSSLHASH
+
+void
+isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
+                unsigned int len)
+{
+       HMAC_Init(ctx, (const void *) key, (int) len, EVP_md5());
+}
+
+void
+isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
+       HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
+                  unsigned int len)
+{
+       HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
+       HMAC_Final(ctx, digest, NULL);
+       HMAC_CTX_cleanup(ctx);
+}
+
+#else
+
 #define PADLEN 64
 #define IPAD 0x36
 #define OPAD 0x5C
@@ -98,6 +128,7 @@ isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
        isc_md5_final(&ctx->md5ctx, digest);
        isc_hmacmd5_invalidate(ctx);
 }
+#endif /* !ISC_PLATFORM_OPENSSLHASH */
 
 /*!
  * Verify signature - finalize MD5 operation and reapply MD5, then
index dfcd8bf5a9f07addf21861a9f07882e3d54adde4..d7b9f1897eb0ebc4e571c2e7cf9558818dd4cf3c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005-2007, 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: hmacsha.c,v 1.8 2007/08/27 03:27:53 marka Exp $ */
+/* $Id$ */
 
 /*
  * This code implements the HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384
 
 #include <isc/assertions.h>
 #include <isc/hmacsha.h>
+#include <isc/platform.h>
 #include <isc/sha1.h>
 #include <isc/sha2.h>
 #include <isc/string.h>
 #include <isc/types.h>
 #include <isc/util.h>
 
+#ifdef ISC_PLATFORM_OPENSSLHASH
+
+void
+isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key,
+                 unsigned int len)
+{
+       HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha1());
+}
+
+void
+isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) {
+       HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf,
+                  unsigned int len)
+{
+       HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
+       unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
+
+       REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
+
+       HMAC_Final(ctx, newdigest, NULL);
+       HMAC_CTX_cleanup(ctx);
+       memcpy(digest, newdigest, len);
+       memset(newdigest, 0, sizeof(newdigest));
+}
+
+void
+isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key,
+                   unsigned int len)
+{
+       HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha224());
+}
+
+void
+isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) {
+       HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf,
+                  unsigned int len)
+{
+       HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
+       unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
+
+       REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
+
+       HMAC_Final(ctx, newdigest, NULL);
+       HMAC_CTX_cleanup(ctx);
+       memcpy(digest, newdigest, len);
+       memset(newdigest, 0, sizeof(newdigest));
+}
+
+void
+isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key,
+                   unsigned int len)
+{
+       HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha256());
+}
+
+void
+isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) {
+       HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf,
+                  unsigned int len)
+{
+       HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
+       unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
+
+       REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
+
+       HMAC_Final(ctx, newdigest, NULL);
+       HMAC_CTX_cleanup(ctx);
+       memcpy(digest, newdigest, len);
+       memset(newdigest, 0, sizeof(newdigest));
+}
+
+void
+isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key,
+                   unsigned int len)
+{
+       HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha384());
+}
+
+void
+isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) {
+       HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf,
+                  unsigned int len)
+{
+       HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
+       unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
+
+       REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
+
+       HMAC_Final(ctx, newdigest, NULL);
+       HMAC_CTX_cleanup(ctx);
+       memcpy(digest, newdigest, len);
+       memset(newdigest, 0, sizeof(newdigest));
+}
+
+void
+isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key,
+                   unsigned int len)
+{
+       HMAC_Init(ctx, (const void *) key, (int) len, EVP_sha512());
+}
+
+void
+isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) {
+       HMAC_CTX_cleanup(ctx);
+}
+
+void
+isc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf,
+                  unsigned int len)
+{
+       HMAC_Update(ctx, buf, (int) len);
+}
+
+void
+isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
+       unsigned char newdigest[ISC_SHA512_DIGESTLENGTH];
+
+       REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
+
+       HMAC_Final(ctx, newdigest, NULL);
+       HMAC_CTX_cleanup(ctx);
+       memcpy(digest, newdigest, len);
+       memset(newdigest, 0, sizeof(newdigest));
+}
+
+#else
+
 #define IPAD 0x36
 #define OPAD 0x5C
 
@@ -64,8 +224,7 @@ isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key,
 void
 isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) {
        isc_sha1_invalidate(&ctx->sha1ctx);
-       memset(ctx->key, 0, sizeof(ctx->key));
-       memset(ctx, 0, sizeof(ctx));
+       memset(ctx, 0, sizeof(*ctx));
 }
 
 /*
@@ -104,19 +263,6 @@ isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
        memset(newdigest, 0, sizeof(newdigest));
 }
 
-/*
- * Verify signature - finalize SHA1 operation and reapply SHA1, then
- * compare to the supplied digest.
- */
-isc_boolean_t
-isc_hmacsha1_verify(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
-       unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
-
-       REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
-       isc_hmacsha1_sign(ctx, newdigest, ISC_SHA1_DIGESTLENGTH);
-       return (ISC_TF(memcmp(digest, newdigest, len) == 0));
-}
-
 /*
  * Start HMAC-SHA224 process.  Initialize an sha224 context and digest the key.
  */
@@ -145,8 +291,7 @@ isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key,
 
 void
 isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) {
-       memset(ctx->key, 0, sizeof(ctx->key));
-       memset(ctx, 0, sizeof(ctx));
+       memset(ctx, 0, sizeof(*ctx));
 }
 
 /*
@@ -184,19 +329,6 @@ isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
        memset(newdigest, 0, sizeof(newdigest));
 }
 
-/*
- * Verify signature - finalize SHA224 operation and reapply SHA224, then
- * compare to the supplied digest.
- */
-isc_boolean_t
-isc_hmacsha224_verify(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
-       unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
-
-       REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
-       isc_hmacsha224_sign(ctx, newdigest, ISC_SHA224_DIGESTLENGTH);
-       return (ISC_TF(memcmp(digest, newdigest, len) == 0));
-}
-
 /*
  * Start HMAC-SHA256 process.  Initialize an sha256 context and digest the key.
  */
@@ -225,8 +357,7 @@ isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key,
 
 void
 isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) {
-       memset(ctx->key, 0, sizeof(ctx->key));
-       memset(ctx, 0, sizeof(ctx));
+       memset(ctx, 0, sizeof(*ctx));
 }
 
 /*
@@ -264,19 +395,6 @@ isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
        memset(newdigest, 0, sizeof(newdigest));
 }
 
-/*
- * Verify signature - finalize SHA256 operation and reapply SHA256, then
- * compare to the supplied digest.
- */
-isc_boolean_t
-isc_hmacsha256_verify(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
-       unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
-
-       REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
-       isc_hmacsha256_sign(ctx, newdigest, ISC_SHA256_DIGESTLENGTH);
-       return (ISC_TF(memcmp(digest, newdigest, len) == 0));
-}
-
 /*
  * Start HMAC-SHA384 process.  Initialize an sha384 context and digest the key.
  */
@@ -305,8 +423,7 @@ isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key,
 
 void
 isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) {
-       memset(ctx->key, 0, sizeof(ctx->key));
-       memset(ctx, 0, sizeof(ctx));
+       memset(ctx, 0, sizeof(*ctx));
 }
 
 /*
@@ -344,19 +461,6 @@ isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
        memset(newdigest, 0, sizeof(newdigest));
 }
 
-/*
- * Verify signature - finalize SHA384 operation and reapply SHA384, then
- * compare to the supplied digest.
- */
-isc_boolean_t
-isc_hmacsha384_verify(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
-       unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
-
-       REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
-       isc_hmacsha384_sign(ctx, newdigest, ISC_SHA384_DIGESTLENGTH);
-       return (ISC_TF(memcmp(digest, newdigest, len) == 0));
-}
-
 /*
  * Start HMAC-SHA512 process.  Initialize an sha512 context and digest the key.
  */
@@ -385,8 +489,7 @@ isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key,
 
 void
 isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) {
-       memset(ctx->key, 0, sizeof(ctx->key));
-       memset(ctx, 0, sizeof(ctx));
+       memset(ctx, 0, sizeof(*ctx));
 }
 
 /*
@@ -423,6 +526,59 @@ isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
        memcpy(digest, newdigest, len);
        memset(newdigest, 0, sizeof(newdigest));
 }
+#endif /* !ISC_PLATFORM_OPENSSLHASH */
+
+/*
+ * Verify signature - finalize SHA1 operation and reapply SHA1, then
+ * compare to the supplied digest.
+ */
+isc_boolean_t
+isc_hmacsha1_verify(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
+       unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
+
+       REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
+       isc_hmacsha1_sign(ctx, newdigest, ISC_SHA1_DIGESTLENGTH);
+       return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+}
+
+/*
+ * Verify signature - finalize SHA224 operation and reapply SHA224, then
+ * compare to the supplied digest.
+ */
+isc_boolean_t
+isc_hmacsha224_verify(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
+       unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
+
+       REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
+       isc_hmacsha224_sign(ctx, newdigest, ISC_SHA224_DIGESTLENGTH);
+       return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+}
+
+/*
+ * Verify signature - finalize SHA256 operation and reapply SHA256, then
+ * compare to the supplied digest.
+ */
+isc_boolean_t
+isc_hmacsha256_verify(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
+       unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
+
+       REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
+       isc_hmacsha256_sign(ctx, newdigest, ISC_SHA256_DIGESTLENGTH);
+       return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+}
+
+/*
+ * Verify signature - finalize SHA384 operation and reapply SHA384, then
+ * compare to the supplied digest.
+ */
+isc_boolean_t
+isc_hmacsha384_verify(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
+       unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
+
+       REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
+       isc_hmacsha384_sign(ctx, newdigest, ISC_SHA384_DIGESTLENGTH);
+       return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+}
 
 /*
  * Verify signature - finalize SHA512 operation and reapply SHA512, then
index fa313253b3e93e4f1c48b9d84e14a9668ecc1ab8..16a8c9fe142bc7764449047dfee70458ecc5b61d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2006-2008, 2010-2012  Internet Systems Consortium, Inc. ("ISC")
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: httpd.c,v 1.16 2008/08/08 05:06:49 marka Exp $ */
+/* $Id$ */
 
 /*! \file */
 
@@ -151,6 +151,7 @@ struct isc_httpdmgr {
 
        ISC_LIST(isc_httpdurl_t) urls;          /*%< urls we manage */
        isc_httpdaction_t      *render_404;
+       isc_httpdaction_t      *render_500;
 };
 
 /*%
@@ -221,6 +222,11 @@ static isc_result_t render_404(const char *, const char *,
                               unsigned int *, const char **,
                               const char **, isc_buffer_t *,
                               isc_httpdfree_t **, void **);
+static isc_result_t render_500(const char *, const char *,
+                              void *,
+                              unsigned int *, const char **,
+                              const char **, isc_buffer_t *,
+                              isc_httpdfree_t **, void **);
 
 static void
 destroy_client(isc_httpd_t **httpdp)
@@ -300,6 +306,7 @@ isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
                goto cleanup;
 
        httpd->render_404 = render_404;
+       httpd->render_500 = render_500;
 
        *httpdp = httpd;
        return (ISC_R_SUCCESS);
@@ -308,7 +315,7 @@ isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
        isc_task_detach(&httpd->task);
        isc_socket_detach(&httpd->sock);
        isc_mem_detach(&httpd->mctx);
-       isc_mutex_destroy(&httpd->lock);
+       (void)isc_mutex_destroy(&httpd->lock);
        isc_mem_put(mctx, httpd, sizeof(isc_httpdmgr_t));
        return (result);
 }
@@ -357,7 +364,7 @@ httpdmgr_destroy(isc_httpdmgr_t *httpdmgr)
        }
 
        UNLOCK(&httpdmgr->lock);
-       isc_mutex_destroy(&httpdmgr->lock);
+       (void)isc_mutex_destroy(&httpdmgr->lock);
 
        if (httpdmgr->ondestroy != NULL)
                (httpdmgr->ondestroy)(httpdmgr->cb_arg);
@@ -579,6 +586,8 @@ isc_httpd_accept(isc_task_t *task, isc_event_t *ev)
        r.length = HTTP_RECVLEN - 1;
        result = isc_socket_recv(httpd->sock, &r, 1, task, isc_httpd_recvdone,
                                 httpd);
+       /* FIXME!!! */
+       POST(result);
        NOTICE("accept queued recv on socket");
 
  requeue:
@@ -623,6 +632,30 @@ render_404(const char *url, const char *querystring,
        return (ISC_R_SUCCESS);
 }
 
+static isc_result_t
+render_500(const char *url, const char *querystring,
+          void *arg,
+          unsigned int *retcode, const char **retmsg,
+          const char **mimetype, isc_buffer_t *b,
+          isc_httpdfree_t **freecb, void **freecb_args)
+{
+       static char msg[] = "Internal server failure.";
+
+       UNUSED(url);
+       UNUSED(querystring);
+       UNUSED(arg);
+
+       *retcode = 500;
+       *retmsg = "Internal server failure";
+       *mimetype = "text/plain";
+       isc_buffer_reinit(b, msg, strlen(msg));
+       isc_buffer_add(b, strlen(msg));
+       *freecb = NULL;
+       *freecb_args = NULL;
+
+       return (ISC_R_SUCCESS);
+}
+
 static void
 isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
 {
@@ -652,8 +685,9 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
                }
                r.base = (unsigned char *)httpd->recvbuf + httpd->recvlen;
                r.length = HTTP_RECVLEN - httpd->recvlen - 1;
-               result = isc_socket_recv(httpd->sock, &r, 1, task,
-                                        isc_httpd_recvdone, httpd);
+               /* check return code? */
+               (void)isc_socket_recv(httpd->sock, &r, 1, task,
+                                     isc_httpd_recvdone, httpd);
                goto out;
        } else if (result != ISC_R_SUCCESS) {
                destroy_client(&httpd);
@@ -691,8 +725,14 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
                                     &httpd->mimetype, &httpd->bodybuffer,
                                     &httpd->freecb, &httpd->freecb_arg);
        if (result != ISC_R_SUCCESS) {
-               destroy_client(&httpd);
-               goto out;
+               result = httpd->mgr->render_500(httpd->url, httpd->querystring,
+                                               NULL, &httpd->retcode,
+                                               &httpd->retmsg,
+                                               &httpd->mimetype,
+                                               &httpd->bodybuffer,
+                                               &httpd->freecb,
+                                               &httpd->freecb_arg);
+               RUNTIME_CHECK(result == ISC_R_SUCCESS);
        }
 
        isc_httpd_response(httpd);
@@ -716,8 +756,9 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
        if (isc_buffer_length(&httpd->bodybuffer) > 0)
                ISC_LIST_APPEND(httpd->bufflist, &httpd->bodybuffer, link);
 
-       result = isc_socket_sendv(httpd->sock, &httpd->bufflist, task,
-                                 isc_httpd_senddone, httpd);
+       /* check return code? */
+       (void)isc_socket_sendv(httpd->sock, &httpd->bufflist, task,
+                              isc_httpd_senddone, httpd);
 
  out:
        isc_event_free(&ev);
@@ -784,7 +825,7 @@ isc_httpd_response(isc_httpd_t *httpd)
        needlen += 3 + 1;  /* room for response code, always 3 bytes */
        needlen += strlen(httpd->retmsg) + 2;  /* return msg + CRLF */
 
-       if (isc_buffer_availablelength(&httpd->headerbuffer) < needlen) {
+       while (isc_buffer_availablelength(&httpd->headerbuffer) < needlen) {
                result = grow_headerspace(httpd);
                if (result != ISC_R_SUCCESS)
                        return (result);
@@ -809,7 +850,7 @@ isc_httpd_addheader(isc_httpd_t *httpd, const char *name,
                needlen += 2 + strlen(val); /* :<space> and val */
        needlen += 2; /* CRLF */
 
-       if (isc_buffer_availablelength(&httpd->headerbuffer) < needlen) {
+       while (isc_buffer_availablelength(&httpd->headerbuffer) < needlen) {
                result = grow_headerspace(httpd);
                if (result != ISC_R_SUCCESS)
                        return (result);
@@ -832,7 +873,7 @@ isc_httpd_endheaders(isc_httpd_t *httpd)
 {
        isc_result_t result;
 
-       if (isc_buffer_availablelength(&httpd->headerbuffer) < 2) {
+       while (isc_buffer_availablelength(&httpd->headerbuffer) < 2) {
                result = grow_headerspace(httpd);
                if (result != ISC_R_SUCCESS)
                        return (result);
@@ -856,7 +897,7 @@ isc_httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val) {
        needlen += 2 + strlen(buf); /* :<space> and val */
        needlen += 2; /* CRLF */
 
-       if (isc_buffer_availablelength(&httpd->headerbuffer) < needlen) {
+       while (isc_buffer_availablelength(&httpd->headerbuffer) < needlen) {
                result = grow_headerspace(httpd);
                if (result != ISC_R_SUCCESS)
                        return (result);
@@ -875,7 +916,6 @@ isc_httpd_senddone(isc_task_t *task, isc_event_t *ev)
 {
        isc_httpd_t *httpd = ev->ev_arg;
        isc_region_t r;
-       isc_result_t result;
        isc_socketevent_t *sev = (isc_socketevent_t *)ev;
 
        ENTER("senddone");
@@ -926,8 +966,9 @@ isc_httpd_senddone(isc_task_t *task, isc_event_t *ev)
 
        r.base = (unsigned char *)httpd->recvbuf;
        r.length = HTTP_RECVLEN - 1;
-       result = isc_socket_recv(httpd->sock, &r, 1, task, isc_httpd_recvdone,
-                                httpd);
+       /* check return code? */
+       (void)isc_socket_recv(httpd->sock, &r, 1, task,
+                             isc_httpd_recvdone, httpd);
 
 out:
        isc_event_free(&ev);
index 4c4679772044388012cd089e260492e00f6da12f..6c22f2a53e28857bcd376a3486ad082fdc8a8d0a 100644 (file)
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: atomic.h,v 1.4.326.2 2009/02/06 23:47:11 tbox Exp $ */
+/* $Id: atomic.h,v 1.7 2009/06/24 02:22:50 marka Exp $ */
 
 #ifndef ISC_ATOMIC_H
 #define ISC_ATOMIC_H 1
  * (e.g., 1 and -1)?
  */
 static inline isc_int32_t
-isc_atomic_xadd(isc_int32_t *p, isc_int32_t val)
 #ifdef __GNUC__
 __attribute__ ((unused))
 #endif
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val)
 {
        isc_int32_t prev, swapped;
 
@@ -57,10 +57,10 @@ __attribute__ ((unused))
  * This routine atomically stores the value 'val' in 'p'.
  */
 static inline void
-isc_atomic_store(isc_int32_t *p, isc_int32_t val)
 #ifdef __GNUC__
 __attribute__ ((unused))
 #endif
+isc_atomic_store(isc_int32_t *p, isc_int32_t val)
 {
        __asm__ volatile(
                "st4.rel %0=%1"
@@ -76,10 +76,10 @@ __attribute__ ((unused))
  * case.
  */
 static inline isc_int32_t
-isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val)
 #ifdef __GNUC__
 __attribute__ ((unused))
 #endif
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val)
 {
        isc_int32_t ret;
 
index c4d54cbe44d9a6d203cdb7d17229c713799380c9..e0be79063709da967193e3d9e0296d90c1467be6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: app.h,v 1.8 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id: app.h,v 1.11 2009/09/02 23:48:03 tbox Exp $ */
 
 #ifndef ISC_APP_H
 #define ISC_APP_H 1
  * Use of this module is not required.  In particular, isc_app_start() is
  * NOT an ISC library initialization routine.
  *
+ * This module also supports per-thread 'application contexts'.  With this
+ * mode, a thread-based application will have a separate context, in which
+ * it uses other ISC library services such as tasks or timers.  Signals are
+ * not caught in this mode, so that the application can handle the signals
+ * in its preferred way.
+ *
  * \li MP:
  *     Clients must ensure that isc_app_start(), isc_app_run(), and
  *     isc_app_finish() are called at most once.  isc_app_shutdown()
  *     is safe to use by any thread (provided isc_app_start() has been
  *     called previously).
  *
+ *     The same note applies to isc_app_ctxXXX() functions, but in this case
+ *     it's a per-thread restriction.  For example, a thread with an
+ *     application context must ensure that isc_app_ctxstart() with the
+ *     context is called at most once.
+ *
  * \li Reliability:
  *     No anticipated impact.
  *
 
 #include <isc/eventclass.h>
 #include <isc/lang.h>
+#include <isc/magic.h>
 #include <isc/result.h>
 
+/***
+ *** Types
+ ***/
+
 typedef isc_event_t isc_appevent_t;
 
 #define ISC_APPEVENT_FIRSTEVENT                (ISC_EVENTCLASS_APP + 0)
 #define ISC_APPEVENT_SHUTDOWN          (ISC_EVENTCLASS_APP + 1)
 #define ISC_APPEVENT_LASTEVENT         (ISC_EVENTCLASS_APP + 65535)
 
+/*%
+ * app module methods.  Only app driver implementations use this structure.
+ * Other clients should use the top-level interfaces (i.e., isc_app_xxx
+ * functions).  magic must be ISCAPI_APPMETHODS_MAGIC.
+ */
+typedef struct isc_appmethods {
+       void            (*ctxdestroy)(isc_appctx_t **ctxp);
+       isc_result_t    (*ctxstart)(isc_appctx_t *ctx);
+       isc_result_t    (*ctxrun)(isc_appctx_t *ctx);
+       isc_result_t    (*ctxsuspend)(isc_appctx_t *ctx);
+       isc_result_t    (*ctxshutdown)(isc_appctx_t *ctx);
+       void            (*ctxfinish)(isc_appctx_t *ctx);
+       void            (*settaskmgr)(isc_appctx_t *ctx,
+                                     isc_taskmgr_t *timermgr);
+       void            (*setsocketmgr)(isc_appctx_t *ctx,
+                                       isc_socketmgr_t *timermgr);
+       void            (*settimermgr)(isc_appctx_t *ctx,
+                                      isc_timermgr_t *timermgr);
+} isc_appmethods_t;
+
+/*%
+ * This structure is actually just the common prefix of an application context
+ * implementation's version of an isc_appctx_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden.  app implementations
+ * may change the structure.  'magic' must be ISCAPI_APPCTX_MAGIC for any
+ * of the isc_app_ routines to work.  app implementations must maintain
+ * all app context invariants.
+ */
+struct isc_appctx {
+       unsigned int            impmagic;
+       unsigned int            magic;
+       isc_appmethods_t        *methods;
+};
+
+#define ISCAPI_APPCTX_MAGIC            ISC_MAGIC('A','a','p','c')
+#define ISCAPI_APPCTX_VALID(c)         ((c) != NULL && \
+                                        (c)->magic == ISCAPI_APPCTX_MAGIC)
+
 ISC_LANG_BEGINDECLS
 
+isc_result_t
+isc_app_ctxstart(isc_appctx_t *ctx);
+
 isc_result_t
 isc_app_start(void);
 /*!<
@@ -93,6 +151,9 @@ isc_app_start(void);
  * Notes:
  *     This call should be made before any other ISC library call, and as
  *     close to the beginning of the application as possible.
+ *
+ * Requires:
+ *     'ctx' is a valid application context (for app_ctxstart()).
  */
 
 isc_result_t
@@ -102,13 +163,16 @@ isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
  * \brief Request delivery of an event when the application is run.
  *
  * Requires:
- *     isc_app_start() has been called.
+ *\li  isc_app_start() has been called.
  *
  * Returns:
  *     ISC_R_SUCCESS
  *     ISC_R_NOMEMORY
  */
 
+isc_result_t
+isc_app_ctxrun(isc_appctx_t *ctx);
+
 isc_result_t
 isc_app_run(void);
 /*!<
@@ -120,17 +184,21 @@ isc_app_run(void);
  *     caller should start shutting down the application.
  *
  * Requires:
- *\li  isc_app_start() has been called.
+ *\li  isc_app_[ctx]start() has been called.
  *
  * Ensures:
  *\li  Any events requested via isc_app_onrun() will have been posted (in
  *     FIFO order) before isc_app_run() blocks.
+ *\li  'ctx' is a valid application context (for app_ctxrun()).
  *
  * Returns:
  *\li  ISC_R_SUCCESS                   Shutdown has been requested.
  *\li  ISC_R_RELOAD                    Reload has been requested.
  */
 
+isc_result_t
+isc_app_ctxshutdown(isc_appctx_t *ctx);
+
 isc_result_t
 isc_app_shutdown(void);
 /*!<
@@ -141,13 +209,20 @@ isc_app_shutdown(void);
  *     only be triggered once.
  *
  * Requires:
- *\li  isc_app_run() has been called.
+ *\li  isc_app_[ctx]run() has been called.
+ *\li  'ctx' is a valid application context (for app_ctxshutdown()).
  *
  * Returns:
  *\li  ISC_R_SUCCESS
  *\li  ISC_R_UNEXPECTED
  */
 
+isc_result_t
+isc_app_ctxsuspend(isc_appctx_t *ctx);
+/*!<
+ * \brief This has the same behavior as isc_app_ctxsuspend().
+ */
+
 isc_result_t
 isc_app_reload(void);
 /*!<
@@ -161,6 +236,9 @@ isc_app_reload(void);
  *\li  ISC_R_UNEXPECTED
  */
 
+void
+isc_app_ctxfinish(isc_appctx_t *ctx);
+
 void
 isc_app_finish(void);
 /*!<
@@ -171,6 +249,7 @@ isc_app_finish(void);
  *
  * Requires:
  *\li  isc_app_start() has been called.
+ *\li  'ctx' is a valid application context (for app_ctxfinish()).
  *
  * Ensures:
  *\li  Any resources allocated by isc_app_start() have been released.
@@ -206,6 +285,90 @@ isc_app_unblock(void);
  * \li isc_app_block() has been called by the same thread.
  */
 
+isc_result_t
+isc_appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp);
+/*!<
+ * \brief Create an application context.
+ *
+ * Requires:
+ *\li  'mctx' is a valid memory context.
+ *\li  'ctxp' != NULL && *ctxp == NULL.
+ */
+
+void
+isc_appctx_destroy(isc_appctx_t **ctxp);
+/*!<
+ * \brief Destroy an application context.
+ *
+ * Requires:
+ *\li  '*ctxp' is a valid application context.
+ *
+ * Ensures:
+ *\li  *ctxp == NULL.
+ */
+
+void
+isc_appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr);
+/*!<
+ * \brief Associate a task manager with an application context.
+ *
+ * This must be done before running tasks within the application context.
+ *
+ * Requires:
+ *\li  'ctx' is a valid application context.
+ *\li  'taskmgr' is a valid task manager.
+ */
+
+void
+isc_appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr);
+/*!<
+ * \brief Associate a socket manager with an application context.
+ *
+ * This must be done before handling socket events within the application
+ * context.
+ *
+ * Requires:
+ *\li  'ctx' is a valid application context.
+ *\li  'socketmgr' is a valid socket manager.
+ */
+
+void
+isc_appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr);
+/*!<
+ * \brief Associate a socket timer with an application context.
+ *
+ * This must be done before handling timer events within the application
+ * context.
+ *
+ * Requires:
+ *\li  'ctx' is a valid application context.
+ *\li  'timermgr' is a valid timer manager.
+ */
+
+#ifdef USE_APPIMPREGISTER
+/*%<
+ * See isc_appctx_create() above.
+ */
+typedef isc_result_t
+(*isc_appctxcreatefunc_t)(isc_mem_t *mctx, isc_appctx_t **ctxp);
+
+isc_result_t
+isc_app_register(isc_appctxcreatefunc_t createfunc);
+/*%<
+ * Register a new application implementation and add it to the list of
+ * supported implementations.  This function must be called when a different
+ * event library is used than the one contained in the ISC library.
+ */
+
+isc_result_t
+isc__app_register(void);
+/*%<
+ * A short cut function that specifies the application module in the ISC
+ * library for isc_app_register().  An application that uses the ISC library
+ * usually do not have to care about this function: it would call
+ * isc_lib_register(), which internally calls this function.
+ */
+#endif /* USE_APPIMPREGISTER */
 
 ISC_LANG_ENDDECLS
 
index b03115216909b8f9d8bcfed5b3327173ad91fa22..2c81b1ae9880cfb51dfdb685d4817006c2be173c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1997-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -16,7 +16,7 @@
  */
 
 /*
- * $Id: assertions.h,v 1.26 2008/10/15 23:47:31 tbox Exp $
+ * $Id: assertions.h,v 1.28 2009/09/29 23:48:04 tbox Exp $
  */
 /*! \file isc/assertions.h
  */
@@ -41,7 +41,9 @@ typedef void (*isc_assertioncallback_t)(const char *, int, isc_assertiontype_t,
                                        const char *);
 
 /* coverity[+kill] */
-LIBISC_EXTERNAL_DATA extern isc_assertioncallback_t isc_assertion_failed;
+ISC_PLATFORM_NORETURN_PRE
+void isc_assertion_failed(const char *, int, isc_assertiontype_t,
+                         const char *) ISC_PLATFORM_NORETURN_POST;
 
 void
 isc_assertion_setcallback(isc_assertioncallback_t);
diff --git a/lib/isc/include/isc/backtrace.h b/lib/isc/include/isc/backtrace.h
new file mode 100644 (file)
index 0000000..c0e98c0
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: backtrace.h,v 1.2 2009/09/01 18:40:25 jinmei Exp $ */
+
+/*! \file isc/backtrace.h
+ * \brief provide a back trace of the running process to help debug problems.
+ *
+ * This module tries to get a back trace of the process using some platform
+ * dependent way when available.  It also manages an internal symbol table
+ * that maps function addresses used in the process to their textual symbols.
+ * This module is expected to be used to help debug when some fatal error
+ * happens.
+ *
+ * IMPORTANT NOTE: since the (major) intended use case of this module is
+ * dumping a back trace on a fatal error, normally followed by self termination,
+ * functions defined in this module generally doesn't employ assertion checks
+ * (if it did, a program bug could cause infinite recursive calls to a
+ * backtrace function).  These functions still perform minimal checks and return
+ * ISC_R_FAILURE if they detect an error, but the caller should therefore be
+ * very careful about the use of these functions, and generally discouraged to
+ * use them except in an exit path.  The exception is
+ * isc_backtrace_getsymbolfromindex(), which is expected to be used in a
+ * non-error-handling context and validates arguments with assertion checks.
+ */
+
+#ifndef ISC_BACKTRACE_H
+#define ISC_BACKTRACE_H 1
+
+/***
+ ***   Imports
+ ***/
+
+#include <isc/types.h>
+
+/***
+ *** Types
+ ***/
+struct isc_backtrace_symmap {
+       void            *addr;
+       const char      *symbol;
+};
+
+extern const int isc__backtrace_nsymbols;
+extern const isc_backtrace_symmap_t isc__backtrace_symtable[];
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+isc_result_t
+isc_backtrace_gettrace(void **addrs, int maxaddrs, int *nframes);
+/*%<
+ * Get a back trace of the running process above this function itself.  On
+ * success, addrs[i] will store the address of the call point of the i-th
+ * stack frame (addrs[0] is the caller of this function).  *nframes will store
+ * the total number of frames.
+ *
+ * Requires (note that these are not ensured by assertion checks, see above):
+ *
+ *\li  'addrs' is a valid array containing at least 'maxaddrs' void * entries.
+ *
+ *\li  'nframes' must be non NULL.
+ *
+ * Returns:
+ *
+ *\li  #ISC_R_SUCCESS
+ *\li  #ISC_R_FAILURE
+ *\li  #ISC_R_NOTFOUND
+ *\li  #ISC_R_NOTIMPLEMENTED
+ */
+
+isc_result_t
+isc_backtrace_getsymbolfromindex(int index, const void **addrp,
+                                const char **symbolp);
+/*%<
+ * Returns the content of the internal symbol table of the given index.
+ * On success, *addrsp and *symbolp point to the address and the symbol of
+ * the 'index'th entry of the table, respectively.  If 'index' is not in the
+ * range of the symbol table, ISC_R_RANGE will be returned.
+ *
+ * Requires
+ *
+ *\li  'addrp' must be non NULL && '*addrp' == NULL.
+ *
+ *\li  'symbolp' must be non NULL && '*symbolp' == NULL.
+ *
+ * Returns:
+ *
+ *\li  #ISC_R_SUCCESS
+ *\li  #ISC_R_RANGE
+ */
+
+isc_result_t
+isc_backtrace_getsymbol(const void *addr, const char **symbolp,
+                       unsigned long *offsetp);
+/*%<
+ * Searches the internal symbol table for the symbol that most matches the
+ * given 'addr'.  On success, '*symbolp' will point to the name of function
+ * to which the address 'addr' belong, and '*offsetp' will store the offset
+ * from the function's entry address to 'addr'.
+ *
+ * Requires (note that these are not ensured by assertion checks, see above):
+ *
+ *\li  'symbolp' must be non NULL && '*symbolp' == NULL.
+ *
+ *\li  'offsetp' must be non NULL.
+ *
+ * Returns:
+ *
+ *\li  #ISC_R_SUCCESS
+ *\li  #ISC_R_FAILURE
+ *\li  #ISC_R_NOTFOUND
+ */
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_BACKTRACE_H */
diff --git a/lib/isc/include/isc/bind9.h b/lib/isc/include/isc/bind9.h
new file mode 100644 (file)
index 0000000..00bcb24
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: bind9.h,v 1.2 2009/12/05 23:31:41 each Exp $ */
+
+#ifndef ISC_BIND9_H
+#define ISC_BIND9_H 1
+
+/*
+ * This determines whether we are building BIND9 or using the exported
+ * libisc/libdns libraries.  The version of this file included in the
+ * standard BIND9 build defines BIND9; the version included with the
+ * exportable libraries does not.
+ */
+#define BIND9 1
+
+#endif /* ISC_BIND9_H */
index 2a02d88e4e8e7e263b29f4ad9d45f2f12e3f8ff1..ae7e4c3dfc3464d934f91044bc47517af93ae062 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008, 2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2002  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: buffer.h,v 1.53 2008/09/25 04:02:39 tbox Exp $ */
+/* $Id: buffer.h,v 1.55 2010/12/20 23:47:21 tbox Exp $ */
 
 #ifndef ISC_BUFFER_H
 #define ISC_BUFFER_H 1
index e9e59c495141537779b8d65e396b03216bc9cb0f..d28f29a56ecf0c512154f7d056b3d193fb169d45 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: entropy.h,v 1.32.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: entropy.h,v 1.35 2009/10/19 02:37:08 marka Exp $ */
 
 #ifndef ISC_ENTROPY_H
 #define ISC_ENTROPY_H 1
@@ -182,8 +182,8 @@ isc_result_t
 isc_entropy_createsamplesource(isc_entropy_t *ent,
                               isc_entropysource_t **sourcep);
 /*!<
- * \brief Create an entropy source that consists of samples.  Each sample is added
- * to the source via isc_entropy_addsamples(), below.
+ * \brief Create an entropy source that consists of samples.  Each sample is
+ * added to the source via isc_entropy_addsamples(), below.
  */
 
 isc_result_t
@@ -254,11 +254,11 @@ void
 isc_entropy_putdata(isc_entropy_t *ent, void *data, unsigned int length,
                    isc_uint32_t entropy);
 /*!<
- * \brief Add "length" bytes in "data" to the entropy pool, incrementing the pool's
- * entropy count by "entropy."
+ * \brief Add "length" bytes in "data" to the entropy pool, incrementing the
+ * pool's entropy count by "entropy."
  *
- * These bytes will prime the pseudorandom portion even no entropy is actually
- * added.
+ * These bytes will prime the pseudorandom portion even if no entropy is
+ * actually added.
  */
 
 void
index efb9b5f3a11c1bf0108f1044fa5dddea5bf77b5d..e0cdfa83e7cba52142aed71131956eeaba685082 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: error.h,v 1.20 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id: error.h,v 1.22 2009/09/29 23:48:04 tbox Exp $ */
 
 #ifndef ISC_ERROR_H
 #define ISC_ERROR_H 1
@@ -26,6 +26,7 @@
 
 #include <isc/formatcheck.h>
 #include <isc/lang.h>
+#include <isc/platform.h>
 
 ISC_LANG_BEGINDECLS
 
@@ -45,9 +46,9 @@ isc_error_unexpected(const char *, int, const char *, ...)
      ISC_FORMAT_PRINTF(3, 4);
 
 /*% fatal error */
-void
+ISC_PLATFORM_NORETURN_PRE void
 isc_error_fatal(const char *, int, const char *, ...)
-     ISC_FORMAT_PRINTF(3, 4);
+ISC_FORMAT_PRINTF(3, 4) ISC_PLATFORM_NORETURN_POST;
 
 /*% runtimecheck error */
 void
index c9457343e0555a82c6dda78650ae8bff6f3a2fc6..8794065b6fba434578848f88f9874290754dd08a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: file.h,v 1.33.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id$ */
 
 #ifndef ISC_FILE_H
 #define ISC_FILE_H 1
@@ -100,6 +100,10 @@ isc_file_mktemplate(const char *path, char *buf, size_t buflen);
 
 isc_result_t
 isc_file_openunique(char *templet, FILE **fp);
+isc_result_t
+isc_file_openuniqueprivate(char *templet, FILE **fp);
+isc_result_t
+isc_file_openuniquemode(char *templet, int mode, FILE **fp);
 /*!<
  * \brief Create and open a file with a unique name based on 'templet'.
  *
@@ -181,6 +185,27 @@ isc_file_isabsolute(const char *filename);
  * \brief Return #ISC_TRUE if the given file name is absolute.
  */
 
+isc_result_t
+isc_file_isplainfile(const char *name);
+/*!<
+ * \brief Check that the file is a plain file
+ *
+ * Returns:
+ *\li  #ISC_R_SUCCESS
+ *             Success. The file is a plain file.
+ *\li  #ISC_R_INVALIDFILE
+ *             The path specified was not usable by the operating system.
+ *\li  #ISC_R_FILENOTFOUND
+ *             The file does not exist. This return code comes from
+ *             errno=ENOENT when stat returns -1. This code is mentioned
+ *             here, because in logconf.c, it is the one rcode that is
+ *             permitted in addition to ISC_R_SUCCESS. This is done since
+ *             the next call in logconf.c is to isc_stdio_open(), which
+ *             will create the file if it can.
+ *\li  #other ISC_R_* errors translated from errno
+ *             These occur when stat returns -1 and an errno.
+ */
+
 isc_boolean_t
 isc_file_iscurrentdir(const char *filename);
 /*!<
@@ -251,6 +276,29 @@ isc_file_truncate(const char *filename, isc_offset_t size);
  * Truncate/extend the file specified to 'size' bytes.
  */
 
+isc_result_t
+isc_file_safecreate(const char *filename, FILE **fp);
+/*%<
+ * Open 'filename' for writing, truncating if necessary.  Ensure that
+ * if it existed it was a normal file.  If creating the file, ensure
+ * that only the owner can read/write it.
+ */
+
+isc_result_t
+isc_file_splitpath(isc_mem_t *mctx, char *path,
+                  char **dirname, char **basename);
+/*%<
+ * Split a path into dirname and basename.  If 'path' contains no slash
+ * (or, on windows, backslash), then '*dirname' is set to ".".
+ *
+ * Allocates memory for '*dirname', which can be freed with isc_mem_free().
+ *
+ * Returns:
+ * - ISC_R_SUCCESS on success
+ * - ISC_R_INVALIDFILE if 'path' is empty or ends with '/'
+ * - ISC_R_NOMEMORY if unable to allocate memory
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* ISC_FILE_H */
index 3b455e5d56be990859d43ff1bdfa5702c8c18455..7962bbe21ab12c4195212b123057b0a2448f5cb9 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: fsaccess.h,v 1.14.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: fsaccess.h,v 1.16 2009/01/17 23:47:43 tbox Exp $ */
 
 #ifndef ISC_FSACCESS_H
 #define ISC_FSACCESS_H 1
index da30a19cdbc443f7f82a7ee77df4c4a463134d78..ca04b4e43c754e08d8976ba3a90efe67cd017e60 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: hash.h,v 1.10.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: hash.h,v 1.12 2009/01/17 23:47:43 tbox Exp $ */
 
 #ifndef ISC_HASH_H
 #define ISC_HASH_H 1
index 82c59826db450f37d8c3afc27bf705e786f72d76..77bf07c34498485282a6dc40baf4352d7e5c68fa 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: heap.h,v 1.24.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: heap.h,v 1.26 2009/01/17 23:47:43 tbox Exp $ */
 
 #ifndef ISC_HEAP_H
 #define ISC_HEAP_H 1
index fab9c580c5d9bf0e6c58276d385ce06e1a28cfa3..9ecad453dfa5454e8ab9fd6a5b211d05c2b4ca59 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: hmacmd5.h,v 1.12 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id: hmacmd5.h,v 1.14 2009/02/06 23:47:42 tbox Exp $ */
 
 /*! \file isc/hmacmd5.h
  * \brief This is the header file for the HMAC-MD5 keyed hash algorithm
 
 #include <isc/lang.h>
 #include <isc/md5.h>
+#include <isc/platform.h>
 #include <isc/types.h>
 
 #define ISC_HMACMD5_KEYLENGTH 64
 
+#ifdef ISC_PLATFORM_OPENSSLHASH
+#include <openssl/hmac.h>
+
+typedef HMAC_CTX isc_hmacmd5_t;
+
+#else
+
 typedef struct {
        isc_md5_t md5ctx;
        unsigned char key[ISC_HMACMD5_KEYLENGTH];
 } isc_hmacmd5_t;
+#endif
 
 ISC_LANG_BEGINDECLS
 
index 362b37f81acdf4ac938762be845a325687c66d06..1d0e18409536ecc405f3975a69e96c1b2b8dd60f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: hmacsha.h,v 1.7 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id: hmacsha.h,v 1.9 2009/02/06 23:47:42 tbox Exp $ */
 
 /*! \file isc/hmacsha.h
  * This is the header file for the HMAC-SHA1, HMAC-SHA224, HMAC-SHA256,
@@ -25,6 +25,7 @@
 #define ISC_HMACSHA_H 1
 
 #include <isc/lang.h>
+#include <isc/platform.h>
 #include <isc/sha1.h>
 #include <isc/sha2.h>
 #include <isc/types.h>
 #define ISC_HMACSHA384_KEYLENGTH ISC_SHA384_BLOCK_LENGTH
 #define ISC_HMACSHA512_KEYLENGTH ISC_SHA512_BLOCK_LENGTH
 
+#ifdef ISC_PLATFORM_OPENSSLHASH
+#include <openssl/hmac.h>
+
+typedef HMAC_CTX isc_hmacsha1_t;
+typedef HMAC_CTX isc_hmacsha224_t;
+typedef HMAC_CTX isc_hmacsha256_t;
+typedef HMAC_CTX isc_hmacsha384_t;
+typedef HMAC_CTX isc_hmacsha512_t;
+
+#else
+
 typedef struct {
        isc_sha1_t sha1ctx;
        unsigned char key[ISC_HMACSHA1_KEYLENGTH];
@@ -59,6 +71,7 @@ typedef struct {
        isc_sha512_t sha512ctx;
        unsigned char key[ISC_HMACSHA512_KEYLENGTH];
 } isc_hmacsha512_t;
+#endif
 
 ISC_LANG_BEGINDECLS
 
index 765cdfaa1996219908803133f47cd041eeb849d4..f24fef8501690119d64136c0c7fa1743c477bb46 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: lib.h,v 1.14 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id: lib.h,v 1.16 2009/09/02 23:48:03 tbox Exp $ */
 
 #ifndef ISC_LIB_H
 #define ISC_LIB_H 1
@@ -36,6 +36,15 @@ isc_lib_initmsgcat(void);
  * has not already been initialized.
  */
 
+void
+isc_lib_register(void);
+/*!<
+ * \brief Register the ISC library implementations for some base services
+ * such as memory or event management and handling socket or timer events.
+ * An external application that wants to use the ISC library must call this
+ * function very early in main().
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* ISC_LIB_H */
index 9338275c940a1f4df71f41de0078fa59285cee95..c9bdfc7ad6bc854c6be4d059b600a6082aa8c562 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2006, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2006, 2007, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1997-2002  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: list.h,v 1.24 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id$ */
 
 #ifndef ISC_LIST_H
 #define ISC_LIST_H 1
                (list2).tail = NULL; \
        } while (0)
 
+#define ISC_LIST_PREPENDLIST(list1, list2, link) \
+       do { \
+               if (ISC_LIST_EMPTY(list1)) \
+                       (list1) = (list2); \
+               else if (!ISC_LIST_EMPTY(list2)) { \
+                       (list2).tail->link.next = (list1).head; \
+                       (list1).head->link.prev = (list2).tail; \
+                       (list1).head = (list2).head; \
+               } \
+               (list2).head = NULL; \
+               (list2).tail = NULL; \
+       } while (0)
+
 #define ISC_LIST_ENQUEUE(list, elt, link) ISC_LIST_APPEND(list, elt, link)
 #define __ISC_LIST_ENQUEUEUNSAFE(list, elt, link) \
        __ISC_LIST_APPENDUNSAFE(list, elt, link)
index c9ba8082e52c38eb31e07120aaf871f9c67d3326..741c5324290c0af082dcb3ede05dfa273b944b7f 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: log.h,v 1.54.332.5 2009/02/16 02:04:05 marka Exp $ */
+/* $Id: log.h,v 1.59 2009/02/16 02:01:16 marka Exp $ */
 
 #ifndef ISC_LOG_H
 #define ISC_LOG_H 1
index 5b0d785cd1c43d7c7fd41f42ac930cb1c1e469a1..dfa586d0a3b04dcfa3e22a2a631d7d7f9129152f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: md5.h,v 1.16 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id: md5.h,v 1.20 2010/01/07 23:48:54 tbox Exp $ */
 
 /*! \file isc/md5.h
  * \brief This is the header file for the MD5 message-digest algorithm.
 #define ISC_MD5_H 1
 
 #include <isc/lang.h>
+#include <isc/platform.h>
 #include <isc/types.h>
 
 #define ISC_MD5_DIGESTLENGTH 16U
+#define ISC_MD5_BLOCK_LENGTH 64U
+
+#ifdef ISC_PLATFORM_OPENSSLHASH
+#include <openssl/evp.h>
+
+typedef EVP_MD_CTX isc_md5_t;
+
+#else
 
 typedef struct {
        isc_uint32_t buf[4];
        isc_uint32_t bytes[2];
        isc_uint32_t in[16];
 } isc_md5_t;
+#endif
 
 ISC_LANG_BEGINDECLS
 
index 480a934078ed9f0d5f660e1a3c6f7672c59daeaf..5101ea3fed1c1b488a7400adc62f0e7e220ccc89 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1997-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: mem.h,v 1.78.120.3 2009/02/11 03:07:01 jinmei Exp $ */
+/* $Id$ */
 
 #ifndef ISC_MEM_H
 #define ISC_MEM_H 1
@@ -121,7 +121,7 @@ LIBISC_EXTERNAL_DATA extern unsigned int isc_mem_debugging;
 
 #if ISC_MEM_TRACKLINES
 #define _ISC_MEM_FILELINE      , __FILE__, __LINE__
-#define _ISC_MEM_FLARG         , const char *, int
+#define _ISC_MEM_FLARG         , const char *, unsigned int
 #else
 #define _ISC_MEM_FILELINE
 #define _ISC_MEM_FLARG
@@ -152,11 +152,29 @@ LIBISC_EXTERNAL_DATA extern unsigned int isc_mem_debugging;
 #endif
 
 
-#define isc_mem_get(c, s)      isc__mem_get((c), (s) _ISC_MEM_FILELINE)
-#define isc_mem_allocate(c, s) isc__mem_allocate((c), (s) _ISC_MEM_FILELINE)
-#define isc_mem_reallocate(c, p, s) isc__mem_reallocate((c), (p), (s) _ISC_MEM_FILELINE)
-#define isc_mem_strdup(c, p)   isc__mem_strdup((c), (p) _ISC_MEM_FILELINE)
-#define isc_mempool_get(c)     isc__mempool_get((c) _ISC_MEM_FILELINE)
+/*%<
+ * We use either isc___mem (three underscores) or isc__mem (two) depending on
+ * whether it's for BIND9's internal purpose (with -DBIND9) or generic export
+ * library.  This condition is generally handled in isc/namespace.h, but for
+ * Windows it doesn't work if it involves multiple times of macro expansion
+ * (such as isc_mem to isc__mem then to isc___mem).  The following definitions
+ * are used to work around this portability issue.  Right now, we don't support
+ * the export library for Windows, so we always use the three-underscore
+ * version.
+ */
+#ifdef WIN32
+#define ISCMEMFUNC(sfx) isc___mem_ ## sfx
+#define ISCMEMPOOLFUNC(sfx) isc___mempool_ ## sfx
+#else
+#define ISCMEMFUNC(sfx) isc__mem_ ## sfx
+#define ISCMEMPOOLFUNC(sfx) isc__mempool_ ## sfx
+#endif
+
+#define isc_mem_get(c, s)      ISCMEMFUNC(get)((c), (s) _ISC_MEM_FILELINE)
+#define isc_mem_allocate(c, s) ISCMEMFUNC(allocate)((c), (s) _ISC_MEM_FILELINE)
+#define isc_mem_reallocate(c, p, s) ISCMEMFUNC(reallocate)((c), (p), (s) _ISC_MEM_FILELINE)
+#define isc_mem_strdup(c, p)   ISCMEMFUNC(strdup)((c), (p) _ISC_MEM_FILELINE)
+#define isc_mempool_get(c)     ISCMEMPOOLFUNC(get)((c) _ISC_MEM_FILELINE)
 
 /*%
  * isc_mem_putanddetach() is a convenience function for use where you
@@ -187,33 +205,102 @@ LIBISC_EXTERNAL_DATA extern unsigned int isc_mem_debugging;
  * \endcode
  */
 
+/*% memory and memory pool methods */
+typedef struct isc_memmethods {
+       void (*attach)(isc_mem_t *source, isc_mem_t **targetp);
+       void (*detach)(isc_mem_t **mctxp);
+       void (*destroy)(isc_mem_t **mctxp);
+       void *(*memget)(isc_mem_t *mctx, size_t size _ISC_MEM_FLARG);
+       void (*memput)(isc_mem_t *mctx, void *ptr, size_t size _ISC_MEM_FLARG);
+       void (*memputanddetach)(isc_mem_t **mctxp, void *ptr,
+                               size_t size _ISC_MEM_FLARG);
+       void *(*memallocate)(isc_mem_t *mctx, size_t size _ISC_MEM_FLARG);
+       void *(*memreallocate)(isc_mem_t *mctx, void *ptr,
+                              size_t size _ISC_MEM_FLARG);
+       char *(*memstrdup)(isc_mem_t *mctx, const char *s _ISC_MEM_FLARG);
+       void (*memfree)(isc_mem_t *mctx, void *ptr _ISC_MEM_FLARG);
+       void (*setdestroycheck)(isc_mem_t *mctx, isc_boolean_t flag);
+       void (*setwater)(isc_mem_t *ctx, isc_mem_water_t water,
+                        void *water_arg, size_t hiwater, size_t lowater);
+       void (*waterack)(isc_mem_t *ctx, int flag);
+       size_t (*inuse)(isc_mem_t *mctx);
+       isc_boolean_t (*isovermem)(isc_mem_t *mctx);
+       isc_result_t (*mpcreate)(isc_mem_t *mctx, size_t size,
+                                isc_mempool_t **mpctxp);
+} isc_memmethods_t;
+
+typedef struct isc_mempoolmethods {
+       void (*destroy)(isc_mempool_t **mpctxp);
+       void *(*get)(isc_mempool_t *mpctx _ISC_MEM_FLARG);
+       void (*put)(isc_mempool_t *mpctx, void *mem _ISC_MEM_FLARG);
+       unsigned int (*getallocated)(isc_mempool_t *mpctx);
+       void (*setmaxalloc)(isc_mempool_t *mpctx, unsigned int limit);
+       void (*setfreemax)(isc_mempool_t *mpctx, unsigned int limit);
+       void (*setname)(isc_mempool_t *mpctx, const char *name);
+       void (*associatelock)(isc_mempool_t *mpctx, isc_mutex_t *lock);
+       void (*setfillcount)(isc_mempool_t *mpctx, unsigned int limit);
+} isc_mempoolmethods_t;
+
+/*%
+ * This structure is actually just the common prefix of a memory context
+ * implementation's version of an isc_mem_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden.  mctx implementations
+ * may change the structure.  'magic' must be ISCAPI_MCTX_MAGIC for any of the
+ * isc_mem_ routines to work.  mctx implementations must maintain all mctx
+ * invariants.
+ */
+struct isc_mem {
+       unsigned int            impmagic;
+       unsigned int            magic;
+       isc_memmethods_t        *methods;
+};
+
+#define ISCAPI_MCTX_MAGIC      ISC_MAGIC('A','m','c','x')
+#define ISCAPI_MCTX_VALID(m)   ((m) != NULL && \
+                                (m)->magic == ISCAPI_MCTX_MAGIC)
+
+/*%
+ * This is the common prefix of a memory pool context.  The same note as
+ * that for the mem structure applies.
+ */
+struct isc_mempool {
+       unsigned int            impmagic;
+       unsigned int            magic;
+       isc_mempoolmethods_t    *methods;
+};
+
+#define ISCAPI_MPOOL_MAGIC     ISC_MAGIC('A','m','p','l')
+#define ISCAPI_MPOOL_VALID(mp) ((mp) != NULL && \
+                                (mp)->magic == ISCAPI_MPOOL_MAGIC)
+
 #if ISC_MEM_DEBUG
 #define isc_mem_put(c, p, s) \
        do { \
-               isc__mem_put((c), (p), (s) _ISC_MEM_FILELINE); \
+               ISCMEMFUNC(put)((c), (p), (s) _ISC_MEM_FILELINE);       \
                (p) = NULL; \
        } while (0)
 #define isc_mem_putanddetach(c, p, s) \
        do { \
-               isc__mem_putanddetach((c), (p), (s) _ISC_MEM_FILELINE); \
+               ISCMEMFUNC(putanddetach)((c), (p), (s) _ISC_MEM_FILELINE); \
                (p) = NULL; \
        } while (0)
 #define isc_mem_free(c, p) \
        do { \
-               isc__mem_free((c), (p) _ISC_MEM_FILELINE); \
+               ISCMEMFUNC(free)((c), (p) _ISC_MEM_FILELINE);   \
                (p) = NULL; \
        } while (0)
 #define isc_mempool_put(c, p) \
        do { \
-               isc__mempool_put((c), (p) _ISC_MEM_FILELINE); \
+               ISCMEMPOOLFUNC(put)((c), (p) _ISC_MEM_FILELINE);        \
                (p) = NULL; \
        } while (0)
 #else
-#define isc_mem_put(c, p, s)   isc__mem_put((c), (p), (s) _ISC_MEM_FILELINE)
+#define isc_mem_put(c, p, s)   ISCMEMFUNC(put)((c), (p), (s) _ISC_MEM_FILELINE)
 #define isc_mem_putanddetach(c, p, s) \
-       isc__mem_putanddetach((c), (p), (s) _ISC_MEM_FILELINE)
-#define isc_mem_free(c, p)     isc__mem_free((c), (p) _ISC_MEM_FILELINE)
-#define isc_mempool_put(c, p)  isc__mempool_put((c), (p) _ISC_MEM_FILELINE)
+       ISCMEMFUNC(putanddetach)((c), (p), (s) _ISC_MEM_FILELINE)
+#define isc_mem_free(c, p)     ISCMEMFUNC(free)((c), (p) _ISC_MEM_FILELINE)
+#define isc_mempool_put(c, p)  ISCMEMPOOLFUNC(put)((c), (p) _ISC_MEM_FILELINE)
 #endif
 
 /*@{*/
@@ -247,7 +334,7 @@ isc_mem_createx2(size_t max_size, size_t target_size,
  * ISC_MEMFLAG_INTERNAL is not set, 'target_size' is ignored.
  *
  * 'max_size' is also used to size the statistics arrays and the array
- * used to record active memory when ISC_MEM_DEBUGRECORD is set.  Settin
+ * used to record active memory when ISC_MEM_DEBUGRECORD is set.  Setting
  * 'max_size' too low can have detrimental effects on performance.
  *
  * A memory context created using isc_mem_createx() will obtain
@@ -334,6 +421,14 @@ isc_mem_inuse(isc_mem_t *mctx);
  * allocated from the system but not yet used.
  */
 
+isc_boolean_t
+isc_mem_isovermem(isc_mem_t *mctx);
+/*%<
+ * Return true iff the memory context is in "over memory" state, i.e.,
+ * a hiwater mark has been set and the used amount of memory has exceeds
+ * the mark.
+ */
+
 void
 isc_mem_setwater(isc_mem_t *mctx, isc_mem_water_t water, void *water_arg,
                 size_t hiwater, size_t lowater);
@@ -605,24 +700,50 @@ isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit);
  * Pseudo-private functions for use via macros.  Do not call directly.
  */
 void *
-isc__mem_get(isc_mem_t *, size_t _ISC_MEM_FLARG);
+ISCMEMFUNC(get)(isc_mem_t *, size_t _ISC_MEM_FLARG);
 void
-isc__mem_putanddetach(isc_mem_t **, void *,
-                                     size_t _ISC_MEM_FLARG);
+ISCMEMFUNC(putanddetach)(isc_mem_t **, void *, size_t _ISC_MEM_FLARG);
 void
-isc__mem_put(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
+ISCMEMFUNC(put)(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
 void *
-isc__mem_allocate(isc_mem_t *, size_t _ISC_MEM_FLARG);
+ISCMEMFUNC(allocate)(isc_mem_t *, size_t _ISC_MEM_FLARG);
 void *
-isc__mem_reallocate(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
+ISCMEMFUNC(reallocate)(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
 void
-isc__mem_free(isc_mem_t *, void * _ISC_MEM_FLARG);
+ISCMEMFUNC(free)(isc_mem_t *, void * _ISC_MEM_FLARG);
 char *
-isc__mem_strdup(isc_mem_t *, const char *_ISC_MEM_FLARG);
+ISCMEMFUNC(strdup)(isc_mem_t *, const char *_ISC_MEM_FLARG);
 void *
-isc__mempool_get(isc_mempool_t * _ISC_MEM_FLARG);
+ISCMEMPOOLFUNC(get)(isc_mempool_t * _ISC_MEM_FLARG);
 void
-isc__mempool_put(isc_mempool_t *, void * _ISC_MEM_FLARG);
+ISCMEMPOOLFUNC(put)(isc_mempool_t *, void * _ISC_MEM_FLARG);
+
+#ifdef USE_MEMIMPREGISTER
+
+/*%<
+ * See isc_mem_create2() above.
+ */
+typedef isc_result_t
+(*isc_memcreatefunc_t)(size_t init_max_size, size_t target_size,
+                      isc_mem_t **ctxp, unsigned int flags);
+
+isc_result_t
+isc_mem_register(isc_memcreatefunc_t createfunc);
+/*%<
+ * Register a new memory management implementation and add it to the list of
+ * supported implementations.  This function must be called when a different
+ * memory management library is used than the one contained in the ISC library.
+ */
+
+isc_result_t
+isc__mem_register(void);
+/*%<
+ * A short cut function that specifies the memory management module in the ISC
+ * library for isc_mem_register().  An application that uses the ISC library
+ * usually do not have to care about this function: it would call
+ * isc_lib_register(), which internally calls this function.
+ */
+#endif /* USE_MEMIMPREGISTER */
 
 ISC_LANG_ENDDECLS
 
index d8f2787a28a4ebdfd15d05546604bb58340456a2..f780284691972fdcde830c2c53238a677ace376c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: msgs.h,v 1.17 2008/08/08 06:28:59 tbox Exp $ */
+/* $Id: msgs.h,v 1.19 2009/10/01 23:48:08 tbox Exp $ */
 
 #ifndef ISC_MSGS_H
 #define ISC_MSGS_H 1
 #define ISC_MSG_FILTER        1421 /*%< setsockopt(SO_ACCEPTFILTER): %s */
 
 #define ISC_MSG_TOOMANYHANDLES 1422 /*%< %s: too many open WSA event handles: %s */
-
+#define ISC_MSG_POKED          1423 /*%< "poked flags: %d" */
 
 #define ISC_MSG_AWAKE         1502 /*%< "awake" */
 #define ISC_MSG_WORKING               1503 /*%< "working" */
diff --git a/lib/isc/include/isc/namespace.h b/lib/isc/include/isc/namespace.h
new file mode 100644 (file)
index 0000000..cd4ec9a
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2009-2012  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id$ */
+
+#ifndef ISCAPI_NAMESPACE_H
+#define ISCAPI_NAMESPACE_H 1
+
+/*%
+ * name space conversions
+ */
+
+#ifdef BIND9
+
+#define isc_app_start isc__app_start
+#define isc_app_ctxstart isc__app_ctxstart
+#define isc_app_onrun isc__app_onrun
+#define isc_app_run isc__app_run
+#define isc_app_ctxrun isc__app_ctxrun
+#define isc_app_shutdown isc__app_shutdown
+#define isc_app_ctxfinish isc__app_ctxfinish
+#define isc_app_ctxshutdown isc__app_ctxshutdown
+#define isc_app_ctxsuspend isc__app_ctxsuspend
+#define isc_app_reload isc__app_reload
+#define isc_app_finish isc__app_finish
+#define isc_app_block isc__app_block
+#define isc_app_unblock isc__app_unblock
+#define isc_appctx_create isc__appctx_create
+#define isc_appctx_destroy isc__appctx_destroy
+#define isc_appctx_settaskmgr isc__appctx_settaskmgr
+#define isc_appctx_setsocketmgr isc__appctx_setsocketmgr
+#define isc_appctx_settimermgr isc__appctx_settimermgr
+
+#define isc_mem_checkdestroyed isc__mem_checkdestroyed
+#define isc_mem_createx isc__mem_createx
+#define isc_mem_createx2 isc__mem_createx2
+#define isc_mem_create isc__mem_create
+#define isc_mem_create2 isc__mem_create2
+#define isc_mem_attach isc__mem_attach
+#define isc_mem_detach isc__mem_detach
+#define isc__mem_putanddetach isc___mem_putanddetach
+#define isc_mem_destroy isc__mem_destroy
+#define isc_mem_ondestroy isc__mem_ondestroy
+#define isc__mem_get isc___mem_get
+#define isc__mem_put isc___mem_put
+#define isc_mem_stats isc__mem_stats
+#define isc__mem_allocate isc___mem_allocate
+#define isc__mem_free isc___mem_free
+#define isc__mem_strdup isc___mem_strdup
+#define isc__mem_reallocate isc___mem_reallocate
+#define isc_mem_references isc__mem_references
+#define isc_mem_setdestroycheck isc__mem_setdestroycheck
+#define isc_mem_setquota isc__mem_setquota
+#define isc_mem_getname isc__mem_getname
+#define isc_mem_getquota isc__mem_getquota
+#define isc_mem_gettag isc__mem_gettag
+#define isc_mem_inuse isc__mem_inuse
+#define isc_mem_isovermem isc__mem_isovermem
+#define isc_mem_setname isc__mem_setname
+#define isc_mem_setwater isc__mem_setwater
+#define isc_mem_printallactive isc__mem_printallactive
+#define isc_mem_waterack isc__mem_waterack
+#define isc_mempool_create isc__mempool_create
+#define isc_mempool_setname isc__mempool_setname
+#define isc_mempool_destroy isc__mempool_destroy
+#define isc_mempool_associatelock isc__mempool_associatelock
+#define isc__mempool_get isc___mempool_get
+#define isc__mempool_put isc___mempool_put
+#define isc_mempool_setfreemax isc__mempool_setfreemax
+#define isc_mempool_getfreemax isc__mempool_getfreemax
+#define isc_mempool_getfreecount isc__mempool_getfreecount
+#define isc_mempool_setmaxalloc isc__mempool_setmaxalloc
+#define isc_mempool_getmaxalloc isc__mempool_getmaxalloc
+#define isc_mempool_getallocated isc__mempool_getallocated
+#define isc_mempool_setfillcount isc__mempool_setfillcount
+#define isc_mempool_getfillcount isc__mempool_getfillcount
+
+#define isc_socket_create isc__socket_create
+#define isc_socket_dup isc__socket_dup
+#define isc_socket_attach isc__socket_attach
+#define isc_socket_detach isc__socket_detach
+#define isc_socketmgr_create isc__socketmgr_create
+#define isc_socketmgr_create2 isc__socketmgr_create2
+#define isc_socketmgr_destroy isc__socketmgr_destroy
+#define isc_socket_open isc__socket_open
+#define isc_socket_close isc__socket_close
+#define isc_socket_recvv isc__socket_recvv
+#define isc_socket_recv isc__socket_recv
+#define isc_socket_recv2 isc__socket_recv2
+#define isc_socket_send isc__socket_send
+#define isc_socket_sendto isc__socket_sendto
+#define isc_socket_sendv isc__socket_sendv
+#define isc_socket_sendtov isc__socket_sendtov
+#define isc_socket_sendto2 isc__socket_sendto2
+#define isc_socket_cleanunix isc__socket_cleanunix
+#define isc_socket_permunix isc__socket_permunix
+#define isc_socket_bind isc__socket_bind
+#define isc_socket_filter isc__socket_filter
+#define isc_socket_listen isc__socket_listen
+#define isc_socket_accept isc__socket_accept
+#define isc_socket_connect isc__socket_connect
+#define isc_socket_getfd isc__socket_getfd
+#define isc_socket_getname isc__socket_getname
+#define isc_socket_gettag isc__socket_gettag
+#define isc_socket_getpeername isc__socket_getpeername
+#define isc_socket_getsockname isc__socket_getsockname
+#define isc_socket_cancel isc__socket_cancel
+#define isc_socket_gettype isc__socket_gettype
+#define isc_socket_isbound isc__socket_isbound
+#define isc_socket_ipv6only isc__socket_ipv6only
+#define isc_socket_setname isc__socket_setname
+#define isc_socketmgr_getmaxsockets isc__socketmgr_getmaxsockets
+#define isc_socketmgr_setstats isc__socketmgr_setstats
+#define isc_socketmgr_setreserved isc__socketmgr_setreserved
+#define isc__socketmgr_maxudp isc___socketmgr_maxudp
+#define isc_socket_fdwatchcreate isc__socket_fdwatchcreate
+#define isc_socket_fdwatchpoke isc__socket_fdwatchpoke
+
+#define isc_task_create isc__task_create
+#define isc_task_attach isc__task_attach
+#define isc_task_detach isc__task_detach
+/* #define isc_task_exiting isc__task_exiting XXXMPA */
+#define isc_task_send isc__task_send
+#define isc_task_sendanddetach isc__task_sendanddetach
+#define isc_task_purgerange isc__task_purgerange
+#define isc_task_purge isc__task_purge
+#define isc_task_purgeevent isc__task_purgeevent
+#define isc_task_unsendrange isc__task_unsendrange
+#define isc_task_unsend isc__task_unsend
+#define isc_task_onshutdown isc__task_onshutdown
+#define isc_task_shutdown isc__task_shutdown
+#define isc_task_destroy isc__task_destroy
+#define isc_task_setname isc__task_setname
+#define isc_task_getname isc__task_getname
+#define isc_task_gettag isc__task_gettag
+#define isc_task_getcurrenttime isc__task_getcurrenttime
+#define isc_taskmgr_create isc__taskmgr_create
+#define isc_taskmgr_setmode isc__taskmgr_setmode
+#define isc_taskmgr_mode isc__taskmgr_mode
+#define isc_taskmgr_destroy isc__taskmgr_destroy
+#define isc_task_beginexclusive isc__task_beginexclusive
+#define isc_task_endexclusive isc__task_endexclusive
+#define isc_task_setprivilege isc__task_setprivilege
+#define isc_task_privilege isc__task_privilege
+
+#define isc_timer_create isc__timer_create
+#define isc_timer_reset isc__timer_reset
+#define isc_timer_gettype isc__timer_gettype
+#define isc_timer_touch isc__timer_touch
+#define isc_timer_attach isc__timer_attach
+#define isc_timer_detach isc__timer_detach
+#define isc_timermgr_create isc__timermgr_create
+#define isc_timermgr_poke isc__timermgr_poke
+#define isc_timermgr_destroy isc__timermgr_destroy
+
+#endif /* BIND9 */
+
+#endif /* ISCAPI_NAMESPACE_H */
index 8bfdbce20c12dbac96470f62852a93603c3ac839..954d77019b69e60f47a63077acf5ad94c7cb1844 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: netaddr.h,v 1.35.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: netaddr.h,v 1.37 2009/01/17 23:47:43 tbox Exp $ */
 
 #ifndef ISC_NETADDR_H
 #define ISC_NETADDR_H 1
index ba4e792a40a4675cad3ae05140c9d12e5e63ca6d..163a08ca2ea766cf91fbc689282ba0603f005d2a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2002  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: netscope.h,v 1.11 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id: netscope.h,v 1.13 2009/06/25 23:48:02 tbox Exp $ */
 
 #ifndef ISC_NETSCOPE_H
 #define ISC_NETSCOPE_H 1
@@ -40,4 +40,4 @@ isc_netscope_pton(int af, char *scopename, void *addr, isc_uint32_t *zoneid);
 
 ISC_LANG_ENDDECLS
 
-#endif /* ISC_NETADDR_H */
+#endif /* ISC_NETSCOPE_H */
index 1ed76b855618b6bf18d16e3aa5cd02f7afc08c54..03c2710bac354154aa6e2c0f59013fc3c7ffb053 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: platform.h.in,v 1.48.84.2 2009/02/16 23:47:15 tbox Exp $ */
+/* $Id: platform.h.in,v 1.56 2010/12/18 01:56:23 each Exp $ */
 
 #ifndef ISC_PLATFORM_H
 #define ISC_PLATFORM_H 1
  */
 @ISC_PLATFORM_HAVEDEVPOLL@
 
+/*! \brief
+ * Define if we want to log backtrace
+ */
+@ISC_PLATFORM_USEBACKTRACE@
+
 /*
  *** Printing.
  ***/
  */
 @ISC_PLATFORM_GSSAPIHEADER@
 
+/*
+ * Defined to <gssapi_krb5.h> or <gssapi/gssapi_krb5.h> for how to
+ * include the GSSAPI KRB5 header.
+ */
+@ISC_PLATFORM_GSSAPI_KRB5_HEADER@
+
+/*
+ * Defined to <krb5.h> or <krb5/krb5.h> for how to include
+ * the KRB5 header.
+ */
+@ISC_PLATFORM_KRB5HEADER@
+
 /*
  * Type used for resource limits.
  */
  */
 @ISC_PLATFORM_HAVESTRINGSH@
 
+/*
+ * Define if the hash functions must be provided by OpenSSL.
+ */
+@ISC_PLATFORM_OPENSSLHASH@
+
+/*
+ * Defines for the noreturn attribute.
+ */
+@ISC_PLATFORM_NORETURN_PRE@
+@ISC_PLATFORM_NORETURN_POST@
+
 /***
  ***   Windows dll support.
  ***/
index dc1f85616eabb8a3d5b56834f466ad469a850fd5..774d6bb18cbdc902ead63a5b8f41e0e73806075c 100644 (file)
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: portset.h,v 1.3.90.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: portset.h,v 1.6 2009/06/25 05:28:34 marka Exp $ */
 
 /*! \file isc/portset.h
  * \brief Transport Protocol Port Manipulation Module
@@ -138,4 +138,4 @@ isc_portset_removerange(isc_portset_t *portset, in_port_t port_lo,
 
 ISC_LANG_ENDDECLS
 
-#endif /* ISC_NETADDR_H */
+#endif /* ISC_PORTSET_H */
diff --git a/lib/isc/include/isc/queue.h b/lib/isc/include/isc/queue.h
new file mode 100644 (file)
index 0000000..5bf84c5
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*
+ * This is a generic implementation of a two-lock concurrent queue.
+ * There are built-in mutex locks for the head and tail of the queue,
+ * allowing elements to be safely added and removed at the same time.
+ */
+
+#ifndef ISC_QUEUE_H
+#define ISC_QUEUE_H 1
+#include <isc/assertions.h>
+#include <isc/boolean.h>
+#include <isc/mutex.h>
+
+#ifdef ISC_QUEUE_CHECKINIT
+#define ISC_QLINK_INSIST(x) ISC_INSIST(x)
+#else
+#define ISC_QLINK_INSIST(x) (void)0
+#endif
+
+#define ISC_QLINK(type) struct { void *next; isc_boolean_t linked; }
+#define ISC_QLINK_INIT(elt, link) \
+       do { \
+               (elt)->link.next = (void *)(-1); \
+               (elt)->link.linked = ISC_FALSE; \
+       } while (0)
+#define ISC_QLINK_LINKED(elt, link) ((elt)->link.linked)
+
+#define ISC_QUEUE(type) struct { \
+       type headnode; \
+       type *head, *tail; \
+       isc_mutex_t headlock, taillock; \
+}
+
+#define ISC_QUEUE_INIT(queue, link) \
+       do { \
+               isc_mutex_init(&(queue).headlock); \
+               isc_mutex_init(&(queue).taillock); \
+               (queue).head = (void *) &((queue).headnode); \
+               (queue).tail = (void *) &((queue).headnode); \
+               ISC_QLINK_INIT((queue).head, link); \
+       } while (0)
+
+#define ISC_QUEUE_EMPTY(queue) ISC_TF((queue).head == (queue).tail)
+
+#define ISC_QUEUE_DESTROY(queue) \
+       do { \
+               ISC_QLINK_INSIST(ISC_QUEUE_EMPTY(queue)); \
+               isc_mutex_destroy(&(queue).headlock); \
+               isc_mutex_destroy(&(queue).taillock); \
+       } while (0)
+
+#define ISC_QUEUE_PUSH(queue, elt, link) \
+       do { \
+               ISC_QLINK_INSIST(!ISC_QLINK_LINKED(elt, link)); \
+               (elt)->link.next = (void *)(-1); \
+               LOCK(&(queue).taillock); \
+               (queue).tail->link.next = elt; \
+               (queue).tail = elt; \
+               UNLOCK(&(queue).taillock); \
+               (elt)->link.linked = ISC_TRUE; \
+       } while (0)
+
+#define ISC_QUEUE_POP(queue, link, ret) \
+       do { \
+               LOCK(&(queue).headlock); \
+               ret = (queue).head->link.next; \
+               if (ret == (void *)(-1)) { \
+                       UNLOCK(&(queue).headlock); \
+                       ret = NULL; \
+               } else { \
+                       (queue).head->link.next = ret->link.next; \
+                       if (ret->link.next == (void *)(-1)) { \
+                               LOCK(&(queue).taillock); \
+                               (queue).tail = (queue).head; \
+                               UNLOCK(&(queue).taillock); \
+                       } \
+                       UNLOCK(&(queue).headlock); \
+                       ret->link.next = (void *)(-1); \
+                       ret->link.linked = ISC_FALSE; \
+               } \
+       } while (0)
+
+#endif /* ISC_QUEUE_H */
index fbb1893d489f869874d22ae7754d59215407f189..6b413a23b909a8dd722f55ed61b776a4161b0c45 100644 (file)
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: radix.h,v 1.11.44.2 2008/12/24 23:47:02 tbox Exp $ */
+/* $Id: radix.h,v 1.13 2008/12/01 23:47:45 tbox Exp $ */
 
 /*
  * This source was adapted from MRT's RCS Ids:
index 9b6ca64e022cc860fb1d8e10daaf8a7f43e52e36..1f9572d30ebf6c020db70bf1e516c788a4aa14b2 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: random.h,v 1.18.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: random.h,v 1.20 2009/01/17 23:47:43 tbox Exp $ */
 
 #ifndef ISC_RANDOM_H
 #define ISC_RANDOM_H 1
index d18cf25b746d4d523856f6a38a2a3c0f16257fcf..00a7209758bbc70bd34c78a5338865f5b38cddbf 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: ratelimiter.h,v 1.21.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: ratelimiter.h,v 1.23 2009/01/18 23:48:14 tbox Exp $ */
 
 #ifndef ISC_RATELIMITER_H
 #define ISC_RATELIMITER_H 1
index 6ab14ae732c3db1d79c5a39af9eb975140f3c57f..b72b1585be39fc75d98668104e67b061266f580d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2001, 2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: refcount.h,v 1.15 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id: refcount.h,v 1.17 2009/09/29 23:48:04 tbox Exp $ */
 
 #ifndef ISC_REFCOUNT_H
 #define ISC_REFCOUNT_H 1
@@ -28,7 +28,7 @@
 #include <isc/util.h>
 
 /*! \file isc/refcount.h
- * \brief Implements a locked reference counter.  
+ * \brief Implements a locked reference counter.
  *
  * These functions may actually be
  * implemented using macros, and implementations of these macros are below.
@@ -42,7 +42,7 @@ ISC_LANG_BEGINDECLS
  * Function prototypes
  */
 
-/* 
+/*
  * isc_result_t
  * isc_refcount_init(isc_refcount_t *ref, unsigned int n);
  *
@@ -103,7 +103,7 @@ typedef struct isc_refcount {
        isc_int32_t refs;
 } isc_refcount_t;
 
-#define isc_refcount_destroy(rp) (REQUIRE((rp)->refs == 0))
+#define isc_refcount_destroy(rp) REQUIRE((rp)->refs == 0)
 #define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
 
 #define isc_refcount_increment0(rp, tp)                                \
@@ -192,7 +192,7 @@ typedef struct isc_refcount {
        int refs;
 } isc_refcount_t;
 
-#define isc_refcount_destroy(rp) (REQUIRE((rp)->refs == 0))
+#define isc_refcount_destroy(rp) REQUIRE((rp)->refs == 0)
 #define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
 
 #define isc_refcount_increment0(rp, tp)                                        \
index 56b4ca6d691a837fc2086ea859a276a46c0f8757..dcd457b3d1b0cb648b63c98b6917e53ec7f90fcc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: result.h,v 1.71 2008/09/25 04:02:39 tbox Exp $ */
+/* $Id$ */
 
 #ifndef ISC_RESULT_H
 #define ISC_RESULT_H 1
@@ -42,6 +42,7 @@
 #define ISC_R_EOF                      14      /*%< end of file */
 #define ISC_R_BOUND                    15      /*%< socket already bound */
 #define ISC_R_RELOAD                   16      /*%< reload */
+#define ISC_R_SUSPEND        ISC_R_RELOAD      /*%< alias of 'reload' */
 #define ISC_R_LOCKBUSY                 17      /*%< lock busy */
 #define ISC_R_EXISTS                   18      /*%< already exists */
 #define ISC_R_NOSPACE                  19      /*%< ran out of space */
 #define ISC_R_MAXSIZE                  58      /*%< max size */
 #define ISC_R_BADADDRESSFORM           59      /*%< invalid address format */
 #define ISC_R_BADBASE32                        60      /*%< bad base32 encoding */
+#define ISC_R_UNSET                    61      /*%< unset */
 
 /*% Not a result code: the number of results. */
-#define ISC_R_NRESULTS                         61
+#define ISC_R_NRESULTS                         62
 
 ISC_LANG_BEGINDECLS
 
index b32426fee283bf9c9bbe5f9040a513c25d4439aa..d91e800e063ccb2b5902146bf99ad89ee91e2f7f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: resultclass.h,v 1.18 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id: resultclass.h,v 1.20 2009/09/02 23:48:03 tbox Exp $ */
 
 #ifndef ISC_RESULTCLASS_H
 #define ISC_RESULTCLASS_H 1
@@ -45,6 +45,7 @@
 #define        ISC_RESULTCLASS_DNSRCODE        ISC_RESULTCLASS_FROMNUM(3)
 #define        ISC_RESULTCLASS_OMAPI           ISC_RESULTCLASS_FROMNUM(4)
 #define        ISC_RESULTCLASS_ISCCC           ISC_RESULTCLASS_FROMNUM(5)
+#define        ISC_RESULTCLASS_DHCP            ISC_RESULTCLASS_FROMNUM(6)
 
 
 #endif /* ISC_RESULTCLASS_H */
index f7e3049e026e6b4a83f06d9ac3c42184bc2a1276..a5e03970c3e67cd6f43c1eebcae640ec289e5781 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: serial.h,v 1.16.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: serial.h,v 1.18 2009/01/18 23:48:14 tbox Exp $ */
 
 #ifndef ISC_SERIAL_H
 #define ISC_SERIAL_H 1
index 63f12bb1e0c7ee93e36563bea99b3bb38e28d88b..313ff96391b2528614d36b8b7c044310e8dd17ca 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -18,7 +18,7 @@
 #ifndef ISC_SHA1_H
 #define ISC_SHA1_H 1
 
-/* $Id: sha1.h,v 1.17 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id: sha1.h,v 1.19 2009/02/06 23:47:42 tbox Exp $ */
 
 /*     $NetBSD: sha1.h,v 1.2 1998/05/29 22:55:44 thorpej Exp $ */
 
  */
 
 #include <isc/lang.h>
+#include <isc/platform.h>
 #include <isc/types.h>
 
 #define ISC_SHA1_DIGESTLENGTH 20U
 #define ISC_SHA1_BLOCK_LENGTH 64U
 
+#ifdef ISC_PLATFORM_OPENSSLHASH
+#include <openssl/evp.h>
+
+typedef EVP_MD_CTX isc_sha1_t;
+
+#else
+
 typedef struct {
        isc_uint32_t state[5];
        isc_uint32_t count[2];
        unsigned char buffer[ISC_SHA1_BLOCK_LENGTH];
 } isc_sha1_t;
+#endif
 
 ISC_LANG_BEGINDECLS
 
index 203600fda396b49d9bc38b4ea9af42f63e1475e4..439bbb948e4e7ecde8644a6f30ce9a7ecea7797c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: sha2.h,v 1.9 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id: sha2.h,v 1.12 2009/10/22 02:21:31 each Exp $ */
 
 /*     $FreeBSD: src/sys/crypto/sha2/sha2.h,v 1.1.2.1 2001/07/03 11:01:36 ume Exp $    */
 /*     $KAME: sha2.h,v 1.3 2001/03/12 08:27:48 itojun Exp $    */
@@ -39,7 +39,7 @@
  * 3. Neither the name of the copyright holder nor the names of contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -58,6 +58,7 @@
 #define ISC_SHA2_H
 
 #include <isc/lang.h>
+#include <isc/platform.h>
 #include <isc/types.h>
 
 /*** SHA-224/256/384/512 Various Length Definitions ***********************/
 #define ISC_SHA512_DIGESTLENGTH        64U
 #define ISC_SHA512_DIGESTSTRINGLENGTH  (ISC_SHA512_DIGESTLENGTH * 2 + 1)
 
+/*** SHA-256/384/512 Context Structures *******************************/
 
-ISC_LANG_BEGINDECLS
+#ifdef ISC_PLATFORM_OPENSSLHASH
+#include <openssl/evp.h>
 
-/*** SHA-256/384/512 Context Structures *******************************/
+typedef EVP_MD_CTX isc_sha256_t;
+typedef EVP_MD_CTX isc_sha512_t;
+
+#else
 
 /*
  * Keep buffer immediately after bitcount to preserve alignment.
@@ -97,31 +103,38 @@ typedef struct {
        isc_uint64_t    bitcount[2];
        isc_uint8_t     buffer[ISC_SHA512_BLOCK_LENGTH];
 } isc_sha512_t;
+#endif
 
 typedef isc_sha256_t isc_sha224_t;
 typedef isc_sha512_t isc_sha384_t;
 
+ISC_LANG_BEGINDECLS
+
 /*** SHA-224/256/384/512 Function Prototypes ******************************/
 
 void isc_sha224_init (isc_sha224_t *);
+void isc_sha224_invalidate (isc_sha224_t *);
 void isc_sha224_update (isc_sha224_t *, const isc_uint8_t *, size_t);
 void isc_sha224_final (isc_uint8_t[ISC_SHA224_DIGESTLENGTH], isc_sha224_t *);
 char *isc_sha224_end (isc_sha224_t *, char[ISC_SHA224_DIGESTSTRINGLENGTH]);
 char *isc_sha224_data (const isc_uint8_t *, size_t, char[ISC_SHA224_DIGESTSTRINGLENGTH]);
 
 void isc_sha256_init (isc_sha256_t *);
+void isc_sha256_invalidate (isc_sha256_t *);
 void isc_sha256_update (isc_sha256_t *, const isc_uint8_t *, size_t);
 void isc_sha256_final (isc_uint8_t[ISC_SHA256_DIGESTLENGTH], isc_sha256_t *);
 char *isc_sha256_end (isc_sha256_t *, char[ISC_SHA256_DIGESTSTRINGLENGTH]);
 char *isc_sha256_data (const isc_uint8_t *, size_t, char[ISC_SHA256_DIGESTSTRINGLENGTH]);
 
 void isc_sha384_init (isc_sha384_t *);
+void isc_sha384_invalidate (isc_sha384_t *);
 void isc_sha384_update (isc_sha384_t *, const isc_uint8_t *, size_t);
 void isc_sha384_final (isc_uint8_t[ISC_SHA384_DIGESTLENGTH], isc_sha384_t *);
 char *isc_sha384_end (isc_sha384_t *, char[ISC_SHA384_DIGESTSTRINGLENGTH]);
 char *isc_sha384_data (const isc_uint8_t *, size_t, char[ISC_SHA384_DIGESTSTRINGLENGTH]);
 
 void isc_sha512_init (isc_sha512_t *);
+void isc_sha512_invalidate (isc_sha512_t *);
 void isc_sha512_update (isc_sha512_t *, const isc_uint8_t *, size_t);
 void isc_sha512_final (isc_uint8_t[ISC_SHA512_DIGESTLENGTH], isc_sha512_t *);
 char *isc_sha512_end (isc_sha512_t *, char[ISC_SHA512_DIGESTSTRINGLENGTH]);
index 62cc77397a09dccf13df172610095f24434aa6ee..1e6914222c1ba6f89981533efcc3d9a3ee69aec6 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: sockaddr.h,v 1.55.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: sockaddr.h,v 1.57 2009/01/18 23:48:14 tbox Exp $ */
 
 #ifndef ISC_SOCKADDR_H
 #define ISC_SOCKADDR_H 1
index 035c99485084e5f3d45ede973361696238caedbb..38f6f78025df1e80b9f0697aff97dd708ff96b3b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2002  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: socket.h,v 1.85.58.3 2009/01/29 22:40:35 jinmei Exp $ */
+/* $Id$ */
 
 #ifndef ISC_SOCKET_H
 #define ISC_SOCKET_H 1
@@ -260,6 +260,88 @@ typedef enum {
 #define ISC_SOCKFDWATCH_WRITE  0x00000002      /*%< watch for writable */
 /*@}*/
 
+/*% Socket and socket manager methods */
+typedef struct isc_socketmgrmethods {
+       void            (*destroy)(isc_socketmgr_t **managerp);
+       isc_result_t    (*socketcreate)(isc_socketmgr_t *manager, int pf,
+                                       isc_sockettype_t type,
+                                       isc_socket_t **socketp);
+       isc_result_t    (*fdwatchcreate)(isc_socketmgr_t *manager, int fd,
+                                        int flags,
+                                        isc_sockfdwatch_t callback,
+                                        void *cbarg, isc_task_t *task,
+                                        isc_socket_t **socketp);
+} isc_socketmgrmethods_t;
+
+typedef struct isc_socketmethods {
+       void            (*attach)(isc_socket_t *socket,
+                                 isc_socket_t **socketp);
+       void            (*detach)(isc_socket_t **socketp);
+       isc_result_t    (*bind)(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+                               unsigned int options);
+       isc_result_t    (*sendto)(isc_socket_t *sock, isc_region_t *region,
+                                 isc_task_t *task, isc_taskaction_t action,
+                                 const void *arg, isc_sockaddr_t *address,
+                                 struct in6_pktinfo *pktinfo);
+       isc_result_t    (*connect)(isc_socket_t *sock, isc_sockaddr_t *addr,
+                                  isc_task_t *task, isc_taskaction_t action,
+                                  const void *arg);
+       isc_result_t    (*recv)(isc_socket_t *sock, isc_region_t *region,
+                               unsigned int minimum, isc_task_t *task,
+                               isc_taskaction_t action, const void *arg);
+       void            (*cancel)(isc_socket_t *sock, isc_task_t *task,
+                                 unsigned int how);
+       isc_result_t    (*getsockname)(isc_socket_t *sock,
+                                      isc_sockaddr_t *addressp);
+       isc_sockettype_t (*gettype)(isc_socket_t *sock);
+       void            (*ipv6only)(isc_socket_t *sock, isc_boolean_t yes);
+       isc_result_t    (*fdwatchpoke)(isc_socket_t *sock, int flags);
+       isc_result_t            (*dup)(isc_socket_t *socket,
+                                 isc_socket_t **socketp);
+       int             (*getfd)(isc_socket_t *socket);
+} isc_socketmethods_t;
+
+/*%
+ * This structure is actually just the common prefix of a socket manager
+ * object implementation's version of an isc_socketmgr_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden.  socket implementations
+ * may change the structure.  'magic' must be ISCAPI_SOCKETMGR_MAGIC for any
+ * of the isc_socket_ routines to work.  socket implementations must maintain
+ * all socket invariants.
+ * In effect, this definition is used only for non-BIND9 version ("export")
+ * of the library, and the export version does not work for win32.  So, to avoid
+ * the definition conflict with win32/socket.c, we enable this definition only
+ * for non-Win32 (i.e. Unix) platforms.
+ */
+#ifndef WIN32
+struct isc_socketmgr {
+       unsigned int            impmagic;
+       unsigned int            magic;
+       isc_socketmgrmethods_t  *methods;
+};
+#endif
+
+#define ISCAPI_SOCKETMGR_MAGIC         ISC_MAGIC('A','s','m','g')
+#define ISCAPI_SOCKETMGR_VALID(m)      ((m) != NULL && \
+                                        (m)->magic == ISCAPI_SOCKETMGR_MAGIC)
+
+/*%
+ * This is the common prefix of a socket object.  The same note as
+ * that for the socketmgr structure applies.
+ */
+#ifndef WIN32
+struct isc_socket {
+       unsigned int            impmagic;
+       unsigned int            magic;
+       isc_socketmethods_t     *methods;
+};
+#endif
+
+#define ISCAPI_SOCKET_MAGIC    ISC_MAGIC('A','s','c','t')
+#define ISCAPI_SOCKET_VALID(s) ((s) != NULL && \
+                                (s)->magic == ISCAPI_SOCKET_MAGIC)
+
 /***
  *** Socket and Socket Manager Functions
  ***
@@ -306,6 +388,35 @@ isc_socket_fdwatchcreate(isc_socketmgr_t *manager,
  *\li  #ISC_R_UNEXPECTED
  */
 
+isc_result_t
+isc_socket_fdwatchpoke(isc_socket_t *sock,
+                      int flags);
+/*%<
+ * Poke a file descriptor watch socket informing the manager that it
+ * should restart watching the socket
+ *
+ * Note:
+ *
+ *\li   'sock' is the socket returned by isc_socket_fdwatchcreate
+ *
+ *\li   'flags' indicates what the manager should watch for on the socket
+ *      in addition to what it may already be watching.  It can be one or
+ *      both of ISC_SOCKFDWATCH_READ and ISC_SOCKFDWATCH_WRITE.  To
+ *      temporarily disable watching on a socket the value indicating
+ *      no more data should be returned from the call back routine.
+ *
+ *\li  This function is not available on Windows.
+ *
+ * Requires:
+ *
+ *\li  'sock' is a valid isc socket
+ *
+ *
+ * Returns:
+ *
+ *\li  #ISC_R_SUCCESS
+ */
+
 isc_result_t
 isc_socket_create(isc_socketmgr_t *manager,
                  int pf,
@@ -341,6 +452,12 @@ isc_socket_create(isc_socketmgr_t *manager,
  *\li  #ISC_R_UNEXPECTED
  */
 
+isc_result_t
+isc_socket_dup(isc_socket_t *sock0, isc_socket_t **socketp);
+/*%<
+ * Duplicate an existing socket, reusing its file descriptor.
+ */
+
 void
 isc_socket_cancel(isc_socket_t *sock, isc_task_t *task,
                  unsigned int how);
@@ -820,6 +937,10 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
  */
 /*@}*/
 
+isc_result_t
+isc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+                         isc_socketmgr_t **managerp);
+
 isc_result_t
 isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp);
 
@@ -831,6 +952,8 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
  * maximum number of sockets that the created manager should handle.
  * isc_socketmgr_create() is equivalent of isc_socketmgr_create2() with
  * "maxsocks" being zero.
+ * isc_socketmgr_createinctx() also associates the new manager with the
+ * specified application context.
  *
  * Notes:
  *
@@ -842,6 +965,8 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
  *
  *\li  'managerp' points to a NULL isc_socketmgr_t.
  *
+ *\li  'actx' is a valid application context (for createinctx()).
+ *
  * Ensures:
  *
  *\li  '*managerp' is a valid isc_socketmgr_t.
@@ -986,12 +1111,23 @@ void *isc_socket_gettag(isc_socket_t *socket);
  * Get the tag associated with a socket, if any.
  */
 
+int isc_socket_getfd(isc_socket_t *socket);
+/*%<
+ * Get the file descriptor associated with a socket
+ */
+
 void
 isc__socketmgr_setreserved(isc_socketmgr_t *mgr, isc_uint32_t);
 /*%<
  * Temporary.  For use by named only.
  */
 
+void
+isc__socketmgr_maxudp(isc_socketmgr_t *mgr, int maxudp);
+/*%<
+ * Test interface. Drop UDP packet > 'maxudp'.
+ */
+
 #ifdef HAVE_LIBXML2
 
 void
@@ -1002,6 +1138,31 @@ isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer);
 
 #endif /* HAVE_LIBXML2 */
 
+#ifdef USE_SOCKETIMPREGISTER
+/*%<
+ * See isc_socketmgr_create() above.
+ */
+typedef isc_result_t
+(*isc_socketmgrcreatefunc_t)(isc_mem_t *mctx, isc_socketmgr_t **managerp);
+
+isc_result_t
+isc_socket_register(isc_socketmgrcreatefunc_t createfunc);
+/*%<
+ * Register a new socket I/O implementation and add it to the list of
+ * supported implementations.  This function must be called when a different
+ * event library is used than the one contained in the ISC library.
+ */
+
+isc_result_t
+isc__socket_register(void);
+/*%<
+ * A short cut function that specifies the socket I/O module in the ISC
+ * library for isc_socket_register().  An application that uses the ISC library
+ * usually do not have to care about this function: it would call
+ * isc_lib_register(), which internally calls this function.
+ */
+#endif /* USE_SOCKETIMPREGISTER */
+
 ISC_LANG_ENDDECLS
 
 #endif /* ISC_SOCKET_H */
index a6156d861a3e0c225e7961de0df03d54e5db2272..682eefdedf13bfcc1b456d2a2d58442031d2a22b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2009, 2012  Internet Systems Consortium, Inc. ("ISC")
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: stats.h,v 1.4.2.2 2009/01/29 23:47:44 tbox Exp $ */
+/* $Id$ */
 
 #ifndef ISC_STATS_H
 #define ISC_STATS_H 1
index 396d64539607046d0a75a564b242145d7bff9693..9d0e5e2f23f04933187e63a624efd71e615f32c2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1996-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: symtab.h,v 1.24.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id$ */
 
 #ifndef ISC_SYMTAB_H
 #define ISC_SYMTAB_H 1
  * undefined.  It can be used to free memory associated with keys and/or
  * values.
  *
+ * A symbol table is implemented as a hash table of lists; the size of the
+ * hash table is set by the 'size' parameter to isc_symtbl_create().  When
+ * the number of entries in the symbol table reaches three quarters of this
+ * value, the hash table is reallocated with size doubled, in order to
+ * optimize lookup performance.  This has a negative effect on insertion
+ * performance, which can be mitigated by sizing the table appropriately
+ * when creating it.
+ *
  * \li MP:
  *     The callers of this module must ensure any required synchronization.
  *
index 8106571c761e7f49bbcfe099731e4b06bbe5c7e6..594d80f3451099cdf244ef29402f88ba05817cd3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009-2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: task.h,v 1.61.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id$ */
 
 #ifndef ISC_TASK_H
 #define ISC_TASK_H 1
@@ -88,6 +88,7 @@
 
 #define ISC_TASKEVENT_FIRSTEVENT       (ISC_EVENTCLASS_TASK + 0)
 #define ISC_TASKEVENT_SHUTDOWN         (ISC_EVENTCLASS_TASK + 1)
+#define ISC_TASKEVENT_TEST             (ISC_EVENTCLASS_TASK + 1)
 #define ISC_TASKEVENT_LASTEVENT                (ISC_EVENTCLASS_TASK + 65535)
 
 /*****
 
 ISC_LANG_BEGINDECLS
 
+/***
+ *** Types
+ ***/
+
+typedef enum {
+               isc_taskmgrmode_normal = 0,
+               isc_taskmgrmode_privileged
+} isc_taskmgrmode_t;
+
+/*% Task and task manager methods */
+typedef struct isc_taskmgrmethods {
+       void            (*destroy)(isc_taskmgr_t **managerp);
+       void            (*setmode)(isc_taskmgr_t *manager,
+                                  isc_taskmgrmode_t mode);
+       isc_taskmgrmode_t (*mode)(isc_taskmgr_t *manager);
+       isc_result_t    (*taskcreate)(isc_taskmgr_t *manager,
+                                     unsigned int quantum,
+                                     isc_task_t **taskp);
+} isc_taskmgrmethods_t;
+
+typedef struct isc_taskmethods {
+       void (*attach)(isc_task_t *source, isc_task_t **targetp);
+       void (*detach)(isc_task_t **taskp);
+       void (*destroy)(isc_task_t **taskp);
+       void (*send)(isc_task_t *task, isc_event_t **eventp);
+       void (*sendanddetach)(isc_task_t **taskp, isc_event_t **eventp);
+       unsigned int (*unsend)(isc_task_t *task, void *sender, isc_eventtype_t type,
+                              void *tag, isc_eventlist_t *events);
+       isc_result_t (*onshutdown)(isc_task_t *task, isc_taskaction_t action,
+                                  const void *arg);
+       void (*shutdown)(isc_task_t *task);
+       void (*setname)(isc_task_t *task, const char *name, void *tag);
+       unsigned int (*purgeevents)(isc_task_t *task, void *sender,
+                                   isc_eventtype_t type, void *tag);
+       unsigned int (*purgerange)(isc_task_t *task, void *sender,
+                                  isc_eventtype_t first, isc_eventtype_t last,
+                                  void *tag);
+       isc_result_t (*beginexclusive)(isc_task_t *task);
+       void (*endexclusive)(isc_task_t *task);
+    void (*setprivilege)(isc_task_t *task, isc_boolean_t priv);
+    isc_boolean_t (*privilege)(isc_task_t *task);
+} isc_taskmethods_t;
+
+/*%
+ * This structure is actually just the common prefix of a task manager
+ * object implementation's version of an isc_taskmgr_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden.  task implementations
+ * may change the structure.  'magic' must be ISCAPI_TASKMGR_MAGIC for any
+ * of the isc_task_ routines to work.  task implementations must maintain
+ * all task invariants.
+ */
+struct isc_taskmgr {
+       unsigned int            impmagic;
+       unsigned int            magic;
+       isc_taskmgrmethods_t    *methods;
+};
+
+#define ISCAPI_TASKMGR_MAGIC   ISC_MAGIC('A','t','m','g')
+#define ISCAPI_TASKMGR_VALID(m)        ((m) != NULL && \
+                                (m)->magic == ISCAPI_TASKMGR_MAGIC)
+
+/*%
+ * This is the common prefix of a task object.  The same note as
+ * that for the taskmgr structure applies.
+ */
+struct isc_task {
+       unsigned int            impmagic;
+       unsigned int            magic;
+       isc_taskmethods_t       *methods;
+};
+
+#define ISCAPI_TASK_MAGIC      ISC_MAGIC('A','t','s','t')
+#define ISCAPI_TASK_VALID(s)   ((s) != NULL && \
+                                (s)->magic == ISCAPI_TASK_MAGIC)
+
 isc_result_t
 isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
                isc_task_t **taskp);
@@ -535,15 +612,56 @@ isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t);
  *\li  '*t' has the "current time".
  */
 
+isc_boolean_t
+isc_task_exiting(isc_task_t *t);
+/*%<
+ * Returns ISC_TRUE if the task is in the process of shutting down,
+ * ISC_FALSE otherwise.
+ *
+ * Requires:
+ *\li  'task' is a valid task.
+ */
+
+void
+isc_task_setprivilege(isc_task_t *task, isc_boolean_t priv);
+/*%<
+ * Set or unset the task's "privileged" flag depending on the value of
+ * 'priv'.
+ *
+ * Under normal circumstances this flag has no effect on the task behavior,
+ * but when the task manager has been set to privileged exeuction mode via
+ * isc_taskmgr_setmode(), only tasks with the flag set will be executed,
+ * and all other tasks will wait until they're done.  Once all privileged
+ * tasks have finished executing, the task manager will automatically
+ * return to normal execution mode and nonprivileged task can resume.
+ *
+ * Requires:
+ *\li  'task' is a valid task.
+ */
+
+isc_boolean_t
+isc_task_privilege(isc_task_t *task);
+/*%<
+ * Returns the current value of the task's privilege flag.
+ *
+ * Requires:
+ *\li  'task' is a valid task.
+ */
+
 /*****
  ***** Task Manager.
  *****/
 
 isc_result_t
+isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+                       unsigned int workers, unsigned int default_quantum,
+                       isc_taskmgr_t **managerp);
+isc_result_t
 isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
                   unsigned int default_quantum, isc_taskmgr_t **managerp);
 /*%<
- * Create a new task manager.
+ * Create a new task manager.  isc_taskmgr_createinctx() also associates
+ * the new manager with the specified application context.
  *
  * Notes:
  *
@@ -565,6 +683,8 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
  *
  *\li  managerp != NULL && *managerp == NULL
  *
+ *\li  'actx' is a valid application context (for createinctx()).
+ *
  * Ensures:
  *
  *\li  On success, '*managerp' will be attached to the newly created task
@@ -574,8 +694,35 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
  *
  *\li  #ISC_R_SUCCESS
  *\li  #ISC_R_NOMEMORY
- *\li  #ISC_R_NOTHREADS                        No threads could be created.
+ *\li  #ISC_R_NOTHREADS                No threads could be created.
  *\li  #ISC_R_UNEXPECTED               An unexpected error occurred.
+ *\li  #ISC_R_SHUTTINGDOWN             The non-threaded, shared, task
+ *                                     manager shutting down.
+ */
+
+void
+isc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode);
+
+isc_taskmgrmode_t
+isc_taskmgr_mode(isc_taskmgr_t *manager);
+/*%<
+ * Set/get the current operating mode of the task manager.  Valid modes are:
+ *
+ *\li  isc_taskmgrmode_normal
+ *\li  isc_taskmgrmode_privileged
+ *
+ * In privileged execution mode, only tasks that have had the "privilege"
+ * flag set via isc_task_setprivilege() can be executed.  When all such
+ * tasks are complete, the manager automatically returns to normal mode
+ * and proceeds with running non-privileged ready tasks.  This means it is
+ * necessary to have at least one privileged task waiting on the ready
+ * queue *before* setting the manager into privileged execution mode,
+ * which in turn means the task which calls this function should be in
+ * task-exclusive mode when it does so.
+ *
+ * Requires:
+ *
+ *\li      'manager' is a valid task manager.
  */
 
 void
@@ -619,6 +766,31 @@ isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer);
 
 #endif
 
+/*%<
+ * See isc_taskmgr_create() above.
+ */
+typedef isc_result_t
+(*isc_taskmgrcreatefunc_t)(isc_mem_t *mctx, unsigned int workers,
+                          unsigned int default_quantum,
+                          isc_taskmgr_t **managerp);
+
+isc_result_t
+isc_task_register(isc_taskmgrcreatefunc_t createfunc);
+/*%<
+ * Register a new task management implementation and add it to the list of
+ * supported implementations.  This function must be called when a different
+ * event library is used than the one contained in the ISC library.
+ */
+
+isc_result_t
+isc__task_register(void);
+/*%<
+ * A short cut function that specifies the task management module in the ISC
+ * library for isc_task_register().  An application that uses the ISC library
+ * usually do not have to care about this function: it would call
+ * isc_lib_register(), which internally calls this function.
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* ISC_TASK_H */
index fd07bfd5b126ff5654147c3039b20b213376202d..46f395ea246fc0610f60d783fdaf91952e07280f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: taskpool.h,v 1.15 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id$ */
 
 #ifndef ISC_TASKPOOL_H
 #define ISC_TASKPOOL_H 1
@@ -83,11 +83,50 @@ isc_taskpool_create(isc_taskmgr_t *tmgr, isc_mem_t *mctx,
  *\li  #ISC_R_UNEXPECTED
  */
 
-void 
-isc_taskpool_gettask(isc_taskpool_t *pool, unsigned int hash,
-                         isc_task_t **targetp);
+void
+isc_taskpool_gettask(isc_taskpool_t *pool, isc_task_t **targetp);
+/*%<
+ * Attach to a task from the pool.  Currently the next task is chosen
+ * from the pool at random.  (This may be changed in the future to
+ * something that guaratees balance.)
+ */
+
+int
+isc_taskpool_size(isc_taskpool_t *pool);
 /*%<
- * Attach to the task corresponding to the hash value "hash".
+ * Returns the number of tasks in the task pool 'pool'.
+ */
+
+isc_result_t
+isc_taskpool_expand(isc_taskpool_t **sourcep, unsigned int size,
+                                       isc_taskpool_t **targetp);
+
+/*%<
+ * If 'size' is larger than the number of tasks in the pool pointed to by
+ * 'sourcep', then a new taskpool of size 'size' is allocated, the existing
+ * tasks from are moved into it, additional tasks are created to bring the
+ * total number up to 'size', and the resulting pool is attached to
+ * 'targetp'.
+ *
+ * If 'size' is less than or equal to the tasks in pool 'source', then
+ * 'sourcep' is attached to 'targetp' without any other action being taken.
+ *
+ * In either case, 'sourcep' is detached.
+ *
+ * Requires:
+ *
+ * \li 'sourcep' is not NULL and '*source' is not NULL
+ * \li 'targetp' is not NULL and '*source' is NULL
+ *
+ * Ensures:
+ *
+ * \li On success, '*targetp' points to a valid task pool.
+ * \li On success, '*sourcep' points to NULL.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
  */
 
 void
@@ -100,6 +139,19 @@ isc_taskpool_destroy(isc_taskpool_t **poolp);
  * \li '*poolp' is a valid task pool.
  */
 
+void
+isc_taskpool_setprivilege(isc_taskpool_t *pool, isc_boolean_t priv);
+/*%<
+ * Set the privilege flag on all tasks in 'pool' to 'priv'.  If 'priv' is
+ * true, then when the task manager is set into privileged mode, only
+ * tasks wihin this pool will be able to execute.  (Note:  It is important
+ * to turn the pool tasks' privilege back off before the last task finishes
+ * executing.)
+ *
+ * Requires:
+ * \li 'pool' is a valid task pool.
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* ISC_TASKPOOL_H */
index a4b2df7a54b06bb4837808513339b18ac3b1a74b..fa9abb16aa9d56a455cdc748700ab61b78a17997 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2002  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: timer.h,v 1.40 2008/06/23 23:47:11 tbox Exp $ */
+/* $Id: timer.h,v 1.43 2009/09/02 23:48:03 tbox Exp $ */
 
 #ifndef ISC_TIMER_H
 #define ISC_TIMER_H 1
@@ -103,6 +103,61 @@ typedef struct isc_timerevent {
 #define ISC_TIMEREVENT_LIFE            (ISC_EVENTCLASS_TIMER + 3)
 #define ISC_TIMEREVENT_LASTEVENT       (ISC_EVENTCLASS_TIMER + 65535)
 
+/*% Timer and timer manager methods */
+typedef struct {
+       void            (*destroy)(isc_timermgr_t **managerp);
+       isc_result_t    (*timercreate)(isc_timermgr_t *manager,
+                                      isc_timertype_t type,
+                                      isc_time_t *expires,
+                                      isc_interval_t *interval,
+                                      isc_task_t *task,
+                                      isc_taskaction_t action,
+                                      const void *arg,
+                                      isc_timer_t **timerp);
+} isc_timermgrmethods_t;
+
+typedef struct {
+       void            (*attach)(isc_timer_t *timer, isc_timer_t **timerp);
+       void            (*detach)(isc_timer_t **timerp);
+       isc_result_t    (*reset)(isc_timer_t *timer, isc_timertype_t type,
+                                isc_time_t *expires, isc_interval_t *interval,
+                                isc_boolean_t purge);
+       isc_result_t    (*touch)(isc_timer_t *timer);
+} isc_timermethods_t;
+
+/*%
+ * This structure is actually just the common prefix of a timer manager
+ * object implementation's version of an isc_timermgr_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden.  timer implementations
+ * may change the structure.  'magic' must be ISCAPI_TIMERMGR_MAGIC for any
+ * of the isc_timer_ routines to work.  timer implementations must maintain
+ * all timer invariants.
+ */
+struct isc_timermgr {
+       unsigned int            impmagic;
+       unsigned int            magic;
+       isc_timermgrmethods_t   *methods;
+};
+
+#define ISCAPI_TIMERMGR_MAGIC          ISC_MAGIC('A','t','m','g')
+#define ISCAPI_TIMERMGR_VALID(m)       ((m) != NULL && \
+                                        (m)->magic == ISCAPI_TIMERMGR_MAGIC)
+
+/*%
+ * This is the common prefix of a timer object.  The same note as
+ * that for the timermgr structure applies.
+ */
+struct isc_timer {
+       unsigned int            impmagic;
+       unsigned int            magic;
+       isc_timermethods_t      *methods;
+};
+
+#define ISCAPI_TIMER_MAGIC     ISC_MAGIC('A','t','m','r')
+#define ISCAPI_TIMER_VALID(s)  ((s) != NULL && \
+                                (s)->magic == ISCAPI_TIMER_MAGIC)
+
 /***
  *** Timer and Timer Manager Functions
  ***
@@ -288,10 +343,15 @@ isc_timer_gettype(isc_timer_t *timer);
  *\li  'timer' to be a valid timer.
  */
 
+isc_result_t
+isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+                        isc_timermgr_t **managerp);
+
 isc_result_t
 isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
 /*%<
- * Create a timer manager.
+ * Create a timer manager.  isc_timermgr_createinctx() also associates
+ * the new manager with the specified application context.
  *
  * Notes:
  *
@@ -303,6 +363,8 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
  *
  *\li  'managerp' points to a NULL isc_timermgr_t.
  *
+ *\li  'actx' is a valid application context (for createinctx()).
+ *
  * Ensures:
  *
  *\li  '*managerp' is a valid isc_timermgr_t.
@@ -339,6 +401,31 @@ isc_timermgr_destroy(isc_timermgr_t **managerp);
 
 void isc_timermgr_poke(isc_timermgr_t *m);
 
+#ifdef USE_TIMERIMPREGISTER
+/*%<
+ * See isc_timermgr_create() above.
+ */
+typedef isc_result_t
+(*isc_timermgrcreatefunc_t)(isc_mem_t *mctx, isc_timermgr_t **managerp);
+
+isc_result_t
+isc__timer_register(void);
+/*%<
+ * Register a new timer management implementation and add it to the list of
+ * supported implementations.  This function must be called when a different
+ * event library is used than the one contained in the ISC library.
+ */
+
+isc_result_t
+isc_timer_register(isc_timermgrcreatefunc_t createfunc);
+/*%<
+ * A short cut function that specifies the timer management module in the ISC
+ * library for isc_timer_register().  An application that uses the ISC library
+ * usually do not have to care about this function: it would call
+ * isc_lib_register(), which internally calls this function.
+ */
+#endif /* USE_TIMERIMPREGISTER */
+
 ISC_LANG_ENDDECLS
 
 #endif /* ISC_TIMER_H */
index 4dccbf981569777f143c7dfdcfdbb46346a5e5aa..8dbf67ed109e4e54e5edee3a9a55e6ee0d85b685 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: types.h,v 1.46.84.2 2009/01/29 23:47:44 tbox Exp $ */
+/* $Id$ */
 
 #ifndef ISC_TYPES_H
 #define ISC_TYPES_H 1
 
+#include <isc/bind9.h>
+#include <isc/namespace.h>
+
 /*! \file isc/types.h
  * \brief
  * OS-specific types, from the OS-specific include directories.
@@ -40,6 +43,8 @@
 
 /* Core Types.  Alphabetized by defined type. */
 
+typedef struct isc_appctx              isc_appctx_t;           /*%< Application context */
+typedef struct isc_backtrace_symmap    isc_backtrace_symmap_t; /*%< Symbol Table Entry */
 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 */
@@ -94,7 +99,7 @@ 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 *);
-typedef int (*isc_sockfdwatch_t)(isc_task_t *, isc_socket_t *, void *);
+typedef int (*isc_sockfdwatch_t)(isc_task_t *, isc_socket_t *, void *, int);
 
 /* The following cannot be listed alphabetically due to forward reference */
 typedef isc_result_t (isc_httpdaction_t)(const char *url,
index 8a3b95d9da36f1b21b7306f6e3faad44f7c57446..0a7799cd6a387b6bff6bf86d5b8e6e1b436245d9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2010-2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: util.h,v 1.30 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id$ */
 
 #ifndef ISC_UTIL_H
 #define ISC_UTIL_H 1
  */
 #define UNUSED(x)      (void)(x)
 
+/*%
+ * The opposite: silent warnings about stored values which are never read.
+ */
+#define POST(x)        (void)(x)
+
 #define ISC_MAX(a, b)  ((a) > (b) ? (a) : (b))
 #define ISC_MIN(a, b)  ((a) < (b) ? (a) : (b))
 
index ad9401f696f0024280a64c610291e937b2a18bf3..14b4887f4f16bbf9dcbff3d875e1ed580ecece4a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Portions Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
  * Portions Copyright (C) 1996-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -71,7 +71,7 @@
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)inet_addr.c        8.1 (Berkeley) 6/17/93";
-static char rcsid[] = "$Id: inet_aton.c,v 1.21.332.2 2009/03/05 23:47:03 tbox Exp $";
+static char rcsid[] = "$Id: inet_aton.c,v 1.23 2008/12/01 23:47:45 tbox Exp $";
 #endif /* LIBC_SCCS and not lint */
 
 #include <config.h>
index dc053ededfba7d5abc655df77104355a0b255dac..94910f03eee5aa7d1ac2e7d77d02cb4ff6aff73b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1996-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -19,7 +19,7 @@
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char rcsid[] =
-       "$Id: inet_ntop.c,v 1.19 2007/06/19 23:47:17 tbox Exp $";
+       "$Id: inet_ntop.c,v 1.21 2009/07/17 23:47:41 tbox Exp $";
 #endif /* LIBC_SCCS and not lint */
 
 #include <config.h>
@@ -52,7 +52,7 @@ static const char *inet_ntop6(const unsigned char *src, char *dst,
  *     convert a network format address to presentation format.
  * \return
  *     pointer to presentation format address (`dst'), or NULL (see errno).
- * \author 
+ * \author
  *     Paul Vixie, 1996.
  */
 const char *
@@ -169,8 +169,9 @@ inet_ntop6(const unsigned char *src, char *dst, size_t size)
                if (i != 0)
                        *tp++ = ':';
                /* Is this address an encapsulated IPv4? */
-               if (i == 6 && best.base == 0 &&
-                   (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
+               if (i == 6 && best.base == 0 && (best.len == 6 ||
+                   (best.len == 7 && words[7] != 0x0001) ||
+                   (best.len == 5 && words[5] == 0xffff))) {
                        if (!inet_ntop4(src+12, tp,
                                        sizeof(tmp) - (tp - tmp)))
                                return (NULL);
index 16743143faeabf7c6e0e16c2adbee5547b5c179f..86dedde2880c2fe81aa5f2ecabc7ae4cf8702d16 100644 (file)
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: iterated_hash.c,v 1.4.48.2 2009/02/18 23:47:12 tbox Exp $ */
+/* $Id: iterated_hash.c,v 1.6 2009/02/18 23:47:48 tbox Exp $ */
 
 #include "config.h"
 
index f3a2c2dc790e37f6559ba24bbf6b7f26b3b69286..a50542551df32dc9fc096221bce3e88d417da92f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: lib.c,v 1.14 2007/06/19 23:47:17 tbox Exp $ */
+/* $Id: lib.c,v 1.16 2009/09/02 23:48:02 tbox Exp $ */
 
 /*! \file */
 
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <isc/once.h>
-#include <isc/msgs.h>
+#include <isc/app.h>
 #include <isc/lib.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/once.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
 
 /***
  *** Globals
@@ -41,7 +47,6 @@ LIBISC_EXTERNAL_DATA isc_msgcat_t *           isc_msgcat = NULL;
 
 static isc_once_t              msgcat_once = ISC_ONCE_INIT;
 
-
 /***
  *** Functions
  ***/
@@ -77,3 +82,22 @@ isc_lib_initmsgcat(void) {
                abort();
        }
 }
+
+#ifndef BIND9
+static isc_once_t              register_once = ISC_ONCE_INIT;
+
+static void
+do_register(void) {
+       RUNTIME_CHECK(isc__mem_register() == ISC_R_SUCCESS);
+       RUNTIME_CHECK(isc__app_register() == ISC_R_SUCCESS);
+       RUNTIME_CHECK(isc__task_register() == ISC_R_SUCCESS);
+       RUNTIME_CHECK(isc__socket_register() == ISC_R_SUCCESS);
+       RUNTIME_CHECK(isc__timer_register() == ISC_R_SUCCESS);
+}
+
+void
+isc_lib_register() {
+       RUNTIME_CHECK(isc_once_do(&register_once, do_register)
+                     == ISC_R_SUCCESS);
+}
+#endif
index e19c9ba98eaa973b3cec16b9dcd956453c4dafe2..f1c925cd3fc4d2762c497e52fa59eb0ad1dedd05 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: log.c,v 1.94.332.5 2009/02/16 02:04:05 marka Exp $ */
+/* $Id$ */
 
 /*! \file
  * \author  Principal Authors: DCL */
@@ -1342,9 +1342,10 @@ isc_log_open(isc_logchannel_t *channel) {
                    (FILE_MAXSIZE(channel) > 0 &&
                     statbuf.st_size >= FILE_MAXSIZE(channel)))
                        roll = regular_file;
-       } else if (errno == ENOENT)
+       } else if (errno == ENOENT) {
                regular_file = ISC_TRUE;
-       else
+               POST(regular_file);
+       } else
                result = ISC_R_INVALIDFILE;
 
        /*
index 5004c3e4db4670d1de377173d517799eeb28c706..7c6419b2a9c7ab692958b354a7bde7f3bdf2f272 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: md5.c,v 1.14 2007/06/19 23:47:17 tbox Exp $ */
+/* $Id: md5.c,v 1.16 2009/02/06 23:47:42 tbox Exp $ */
 
 /*! \file
  * This code implements the MD5 message-digest algorithm.
 
 #include <isc/assertions.h>
 #include <isc/md5.h>
+#include <isc/platform.h>
 #include <isc/string.h>
 #include <isc/types.h>
 #include <isc/util.h>
 
+#ifdef ISC_PLATFORM_OPENSSLHASH
+
+void
+isc_md5_init(isc_md5_t *ctx) {
+       EVP_DigestInit(ctx, EVP_md5());
+}
+
+void
+isc_md5_invalidate(isc_md5_t *ctx) {
+       EVP_MD_CTX_cleanup(ctx);
+}
+
+void
+isc_md5_update(isc_md5_t *ctx, const unsigned char *buf, unsigned int len) {
+       EVP_DigestUpdate(ctx, (const void *) buf, (size_t) len);
+}
+
+void
+isc_md5_final(isc_md5_t *ctx, unsigned char *digest) {
+       EVP_DigestFinal(ctx, digest, NULL);
+}
+
+#else
+
 static void
 byteSwap(isc_uint32_t *buf, unsigned words)
 {
@@ -249,3 +274,4 @@ isc_md5_final(isc_md5_t *ctx, unsigned char *digest) {
        memcpy(digest, ctx->buf, 16);
        memset(ctx, 0, sizeof(isc_md5_t));      /* In case it's sensitive */
 }
+#endif
index 9c37d7478bdb70f675a5ec425258179d8dc1064b..5b4b16c570f6df36a1a5e78a79a2889ba6025212 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1997-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: mem.c,v 1.145.120.4 2009/02/16 03:17:05 marka Exp $ */
+/* $Id$ */
 
 /*! \file */
 
@@ -60,6 +60,9 @@ LIBISC_EXTERNAL_DATA unsigned int isc_mem_debugging = ISC_MEM_DEBUGGING;
 /*
  * Types.
  */
+typedef struct isc__mem isc__mem_t;
+typedef struct isc__mempool isc__mempool_t;
+
 #if ISC_MEM_TRACKLINES
 typedef struct debuglink debuglink_t;
 struct debuglink {
@@ -72,7 +75,7 @@ struct debuglink {
 };
 
 #define FLARG_PASS     , file, line
-#define FLARG          , const char *file, int line
+#define FLARG          , const char *file, unsigned int line
 #else
 #define FLARG_PASS
 #define FLARG
@@ -89,7 +92,7 @@ typedef struct {
         */
        union {
                size_t          size;
-               isc_mem_t       *ctx;
+               isc__mem_t      *ctx;
                char            bytes[ALIGNMENT_SIZE];
        } u;
 } size_info;
@@ -110,7 +113,7 @@ typedef ISC_LIST(debuglink_t)       debuglist_t;
 
 /* List of all active memory contexts. */
 
-static ISC_LIST(isc_mem_t)     contexts;
+static ISC_LIST(isc__mem_t)    contexts;
 static isc_once_t              once = ISC_ONCE_INIT;
 static isc_mutex_t             lock;
 
@@ -120,8 +123,8 @@ static isc_mutex_t          lock;
  */
 static isc_uint64_t            totallost;
 
-struct isc_mem {
-       unsigned int            magic;
+struct isc__mem {
+       isc_mem_t               common;
        isc_ondestroy_t         ondestroy;
        unsigned int            flags;
        isc_mutex_t             lock;
@@ -141,9 +144,10 @@ struct isc_mem {
        size_t                  hi_water;
        size_t                  lo_water;
        isc_boolean_t           hi_called;
+       isc_boolean_t           is_overmem;
        isc_mem_water_t         water;
        void *                  water_arg;
-       ISC_LIST(isc_mempool_t) pools;
+       ISC_LIST(isc__mempool_t) pools;
        unsigned int            poolcnt;
 
        /*  ISC_MEMFLAG_INTERNAL */
@@ -162,19 +166,19 @@ struct isc_mem {
 #endif
 
        unsigned int            memalloc_failures;
-       ISC_LINK(isc_mem_t)     link;
+       ISC_LINK(isc__mem_t)    link;
 };
 
 #define MEMPOOL_MAGIC          ISC_MAGIC('M', 'E', 'M', 'p')
 #define VALID_MEMPOOL(c)       ISC_MAGIC_VALID(c, MEMPOOL_MAGIC)
 
-struct isc_mempool {
+struct isc__mempool {
        /* always unlocked */
-       unsigned int    magic;          /*%< magic number */
+       isc_mempool_t   common;         /*%< common header of mempool's */
        isc_mutex_t    *lock;           /*%< optional lock */
-       isc_mem_t      *mctx;           /*%< our memory context */
+       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 */
+       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 */
@@ -209,17 +213,192 @@ struct isc_mempool {
 #define DELETE_TRACE(a, b, c, d, e)    delete_trace_entry(a, b, c, d, e)
 
 static void
-print_active(isc_mem_t *ctx, FILE *out);
+print_active(isc__mem_t *ctx, FILE *out);
+
+/*%
+ * The following can be either static or public, depending on build environment.
+ */
+
+#ifdef BIND9
+#define ISC_MEMFUNC_SCOPE
+#else
+#define ISC_MEMFUNC_SCOPE static
+#endif
+
+ISC_MEMFUNC_SCOPE isc_result_t
+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);
+ISC_MEMFUNC_SCOPE 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_MEMFUNC_SCOPE isc_result_t
+isc__mem_create(size_t init_max_size, size_t target_size, isc_mem_t **ctxp);
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_create2(size_t init_max_size, size_t target_size,
+                isc_mem_t **ctxp, unsigned int flags);
+ISC_MEMFUNC_SCOPE void
+isc__mem_attach(isc_mem_t *source, isc_mem_t **targetp);
+ISC_MEMFUNC_SCOPE void
+isc__mem_detach(isc_mem_t **ctxp);
+ISC_MEMFUNC_SCOPE void
+isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG);
+ISC_MEMFUNC_SCOPE void
+isc__mem_destroy(isc_mem_t **ctxp);
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event);
+ISC_MEMFUNC_SCOPE void *
+isc___mem_get(isc_mem_t *ctx, size_t size FLARG);
+ISC_MEMFUNC_SCOPE void
+isc___mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG);
+ISC_MEMFUNC_SCOPE void
+isc__mem_stats(isc_mem_t *ctx, FILE *out);
+ISC_MEMFUNC_SCOPE void *
+isc___mem_allocate(isc_mem_t *ctx, size_t size FLARG);
+ISC_MEMFUNC_SCOPE void *
+isc___mem_reallocate(isc_mem_t *ctx, void *ptr, size_t size FLARG);
+ISC_MEMFUNC_SCOPE void
+isc___mem_free(isc_mem_t *ctx, void *ptr FLARG);
+ISC_MEMFUNC_SCOPE char *
+isc___mem_strdup(isc_mem_t *mctx, const char *s FLARG);
+ISC_MEMFUNC_SCOPE void
+isc__mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag);
+ISC_MEMFUNC_SCOPE void
+isc__mem_setquota(isc_mem_t *ctx, size_t quota);
+ISC_MEMFUNC_SCOPE size_t
+isc__mem_getquota(isc_mem_t *ctx);
+ISC_MEMFUNC_SCOPE size_t
+isc__mem_inuse(isc_mem_t *ctx);
+ISC_MEMFUNC_SCOPE isc_boolean_t
+isc__mem_isovermem(isc_mem_t *ctx);
+ISC_MEMFUNC_SCOPE void
+isc__mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
+                 size_t hiwater, size_t lowater);
+ISC_MEMFUNC_SCOPE void
+isc__mem_waterack(isc_mem_t *ctx0, int flag);
+ISC_MEMFUNC_SCOPE void
+isc__mem_setname(isc_mem_t *ctx, const char *name, void *tag);
+ISC_MEMFUNC_SCOPE const char *
+isc__mem_getname(isc_mem_t *ctx);
+ISC_MEMFUNC_SCOPE void *
+isc__mem_gettag(isc_mem_t *ctx);
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setname(isc_mempool_t *mpctx, const char *name);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_destroy(isc_mempool_t **mpctxp);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock);
+ISC_MEMFUNC_SCOPE void *
+isc___mempool_get(isc_mempool_t *mpctx FLARG);
+ISC_MEMFUNC_SCOPE void
+isc___mempool_put(isc_mempool_t *mpctx, void *mem FLARG);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfreemax(isc_mempool_t *mpctx);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfreecount(isc_mempool_t *mpctx);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getmaxalloc(isc_mempool_t *mpctx);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getallocated(isc_mempool_t *mpctx);
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfillcount(isc_mempool_t *mpctx);
+#ifdef BIND9
+ISC_MEMFUNC_SCOPE void
+isc__mem_printactive(isc_mem_t *ctx0, FILE *file);
+ISC_MEMFUNC_SCOPE void
+isc__mem_printallactive(FILE *file);
+ISC_MEMFUNC_SCOPE void
+isc__mem_checkdestroyed(FILE *file);
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mem_references(isc_mem_t *ctx0);
+#endif
+
+static struct isc__memmethods {
+       isc_memmethods_t methods;
+
+       /*%
+        * The following are defined just for avoiding unused static functions.
+        */
+#ifndef BIND9
+       void *createx, *create, *create2, *ondestroy, *stats,
+               *setquota, *getquota, *setname, *getname, *gettag;
+#endif
+} memmethods = {
+       {
+               isc__mem_attach,
+               isc__mem_detach,
+               isc__mem_destroy,
+               isc___mem_get,
+               isc___mem_put,
+               isc___mem_putanddetach,
+               isc___mem_allocate,
+               isc___mem_reallocate,
+               isc___mem_strdup,
+               isc___mem_free,
+               isc__mem_setdestroycheck,
+               isc__mem_setwater,
+               isc__mem_waterack,
+               isc__mem_inuse,
+               isc__mem_isovermem,
+               isc__mempool_create
+       }
+#ifndef BIND9
+       ,
+       (void *)isc__mem_createx, (void *)isc__mem_create,
+       (void *)isc__mem_create2, (void *)isc__mem_ondestroy,
+       (void *)isc__mem_stats, (void *)isc__mem_setquota,
+       (void *)isc__mem_getquota, (void *)isc__mem_setname,
+       (void *)isc__mem_getname, (void *)isc__mem_gettag
+#endif
+};
+
+static struct isc__mempoolmethods {
+       isc_mempoolmethods_t methods;
+
+       /*%
+        * The following are defined just for avoiding unused static functions.
+        */
+#ifndef BIND9
+       void *getfreemax, *getfreecount, *getmaxalloc, *getfillcount;
+#endif
+} mempoolmethods = {
+       {
+               isc__mempool_destroy,
+               isc___mempool_get,
+               isc___mempool_put,
+               isc__mempool_getallocated,
+               isc__mempool_setmaxalloc,
+               isc__mempool_setfreemax,
+               isc__mempool_setname,
+               isc__mempool_associatelock,
+               isc__mempool_setfillcount
+       }
+#ifndef BIND9
+       ,
+       (void *)isc__mempool_getfreemax, (void *)isc__mempool_getfreecount,
+       (void *)isc__mempool_getmaxalloc, (void *)isc__mempool_getfillcount
+#endif
+};
 
 /*!
  * mctx must be locked.
  */
 static inline void
-add_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size
+add_trace_entry(isc__mem_t *mctx, const void *ptr, unsigned int size
                FLARG)
 {
        debuglink_t *dl;
        unsigned int i;
+       unsigned int mysize = size;
 
        if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0)
                fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
@@ -231,10 +410,10 @@ add_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size
        if (mctx->debuglist == NULL)
                return;
 
-       if (size > mctx->max_size)
-               size = mctx->max_size;
+       if (mysize > mctx->max_size)
+               mysize = mctx->max_size;
 
-       dl = ISC_LIST_HEAD(mctx->debuglist[size]);
+       dl = ISC_LIST_HEAD(mctx->debuglist[mysize]);
        while (dl != NULL) {
                if (dl->count == DEBUGLIST_COUNT)
                        goto next;
@@ -269,12 +448,12 @@ add_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size
        dl->line[0] = line;
        dl->count = 1;
 
-       ISC_LIST_PREPEND(mctx->debuglist[size], dl, link);
+       ISC_LIST_PREPEND(mctx->debuglist[mysize], dl, link);
        mctx->debuglistcnt++;
 }
 
 static inline void
-delete_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size,
+delete_trace_entry(isc__mem_t *mctx, const void *ptr, unsigned int size,
                   const char *file, unsigned int line)
 {
        debuglink_t *dl;
@@ -345,7 +524,7 @@ quantize(size_t size) {
 }
 
 static inline isc_boolean_t
-more_basic_blocks(isc_mem_t *ctx) {
+more_basic_blocks(isc__mem_t *ctx) {
        void *new;
        unsigned char *curr, *next;
        unsigned char *first, *last;
@@ -415,7 +594,7 @@ more_basic_blocks(isc_mem_t *ctx) {
 }
 
 static inline isc_boolean_t
-more_frags(isc_mem_t *ctx, size_t new_size) {
+more_frags(isc__mem_t *ctx, size_t new_size) {
        int i, frags;
        size_t total_size;
        void *new;
@@ -477,7 +656,7 @@ more_frags(isc_mem_t *ctx, size_t new_size) {
 }
 
 static inline void *
-mem_getunlocked(isc_mem_t *ctx, size_t size) {
+mem_getunlocked(isc__mem_t *ctx, size_t size) {
        size_t new_size = quantize(size);
        void *ret;
 
@@ -558,7 +737,7 @@ check_overrun(void *mem, size_t size, size_t new_size) {
 #endif
 
 static inline void
-mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) {
+mem_putunlocked(isc__mem_t *ctx, void *mem, size_t size) {
        size_t new_size = quantize(size);
 
        if (size == ctx->max_size || new_size >= ctx->max_size) {
@@ -606,7 +785,7 @@ mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) {
  * Perform a malloc, doing memory filling and overrun detection as necessary.
  */
 static inline void *
-mem_get(isc_mem_t *ctx, size_t size) {
+mem_get(isc__mem_t *ctx, size_t size) {
        char *ret;
 
 #if ISC_MEM_CHECKOVERRUN
@@ -634,7 +813,7 @@ mem_get(isc_mem_t *ctx, size_t size) {
  * Perform a free, doing memory filling and overrun detection as necessary.
  */
 static inline void
-mem_put(isc_mem_t *ctx, void *mem, size_t size) {
+mem_put(isc__mem_t *ctx, void *mem, size_t size) {
 #if ISC_MEM_CHECKOVERRUN
        INSIST(((unsigned char *)mem)[size] == 0xbe);
 #endif
@@ -650,7 +829,7 @@ mem_put(isc_mem_t *ctx, void *mem, size_t size) {
  * Update internal counters after a memory get.
  */
 static inline void
-mem_getstats(isc_mem_t *ctx, size_t size) {
+mem_getstats(isc__mem_t *ctx, size_t size) {
        ctx->total += size;
        ctx->inuse += size;
 
@@ -667,7 +846,7 @@ mem_getstats(isc_mem_t *ctx, size_t size) {
  * Update internal counters after a memory put.
  */
 static inline void
-mem_putstats(isc_mem_t *ctx, void *ptr, size_t size) {
+mem_putstats(isc__mem_t *ctx, void *ptr, size_t size) {
        UNUSED(ptr);
 
        INSIST(ctx->inuse >= size);
@@ -711,22 +890,22 @@ initialize_action(void) {
  * Public.
  */
 
-isc_result_t
-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)
+ISC_MEMFUNC_SCOPE isc_result_t
+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));
+       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_MEMFUNC_SCOPE 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__mem_t *ctx;
        isc_result_t result;
 
        REQUIRE(ctxp != NULL && *ctxp == NULL);
@@ -764,9 +943,12 @@ isc_mem_createx2(size_t init_max_size, size_t target_size,
        ctx->hi_water = 0;
        ctx->lo_water = 0;
        ctx->hi_called = ISC_FALSE;
+       ctx->is_overmem = ISC_FALSE;
        ctx->water = NULL;
        ctx->water_arg = NULL;
-       ctx->magic = MEM_MAGIC;
+       ctx->common.impmagic = MEM_MAGIC;
+       ctx->common.magic = ISCAPI_MCTX_MAGIC;
+       ctx->common.methods = (isc_memmethods_t *)&memmethods;
        isc_ondestroy_init(&ctx->ondestroy);
        ctx->memalloc = memalloc;
        ctx->memfree = memfree;
@@ -831,7 +1013,7 @@ isc_mem_createx2(size_t init_max_size, size_t target_size,
        ISC_LIST_INITANDAPPEND(contexts, ctx, link);
        UNLOCK(&lock);
 
-       *ctxp = ctx;
+       *ctxp = (isc_mem_t *)ctx;
        return (ISC_R_SUCCESS);
 
   error:
@@ -852,36 +1034,35 @@ isc_mem_createx2(size_t init_max_size, size_t target_size,
        return (result);
 }
 
-isc_result_t
-isc_mem_create(size_t init_max_size, size_t target_size,
-              isc_mem_t **ctxp)
-{
-       return (isc_mem_createx2(init_max_size, target_size,
-                                default_memalloc, default_memfree, NULL,
-                                ctxp, ISC_MEMFLAG_DEFAULT));
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_create(size_t init_max_size, size_t target_size, isc_mem_t **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)
+ISC_MEMFUNC_SCOPE 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));
+       return (isc__mem_createx2(init_max_size, target_size,
+                                 default_memalloc, default_memfree, NULL,
+                                 ctxp, flags));
 }
 
 static void
-destroy(isc_mem_t *ctx) {
+destroy(isc__mem_t *ctx) {
        unsigned int i;
        isc_ondestroy_t ondest;
 
-       ctx->magic = 0;
-
        LOCK(&lock);
        ISC_LIST_UNLINK(contexts, ctx, link);
        totallost += ctx->inuse;
        UNLOCK(&lock);
 
+       ctx->common.impmagic = 0;
+       ctx->common.magic = 0;
+
        INSIST(ISC_LIST_EMPTY(ctx->pools));
 
 #if ISC_MEM_TRACKLINES
@@ -938,8 +1119,10 @@ destroy(isc_mem_t *ctx) {
        isc_ondestroy_notify(&ondest, ctx);
 }
 
-void
-isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
+ISC_MEMFUNC_SCOPE void
+isc__mem_attach(isc_mem_t *source0, isc_mem_t **targetp) {
+       isc__mem_t *source = (isc__mem_t *)source0;
+
        REQUIRE(VALID_CONTEXT(source));
        REQUIRE(targetp != NULL && *targetp == NULL);
 
@@ -947,16 +1130,16 @@ isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
        source->references++;
        MCTXUNLOCK(source, &source->lock);
 
-       *targetp = source;
+       *targetp = (isc_mem_t *)source;
 }
 
-void
-isc_mem_detach(isc_mem_t **ctxp) {
-       isc_mem_t *ctx;
+ISC_MEMFUNC_SCOPE void
+isc__mem_detach(isc_mem_t **ctxp) {
+       isc__mem_t *ctx;
        isc_boolean_t want_destroy = ISC_FALSE;
 
        REQUIRE(ctxp != NULL);
-       ctx = *ctxp;
+       ctx = (isc__mem_t *)*ctxp;
        REQUIRE(VALID_CONTEXT(ctx));
 
        MCTXLOCK(ctx, &ctx->lock);
@@ -982,15 +1165,15 @@ isc_mem_detach(isc_mem_t **ctxp) {
  * isc_mem_detach(&mctx);
  */
 
-void
-isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
-       isc_mem_t *ctx;
+ISC_MEMFUNC_SCOPE 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;
+       ctx = (isc__mem_t *)*ctxp;
        REQUIRE(VALID_CONTEXT(ctx));
        REQUIRE(ptr != NULL);
 
@@ -1008,7 +1191,7 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
                                oldsize -= ALIGNMENT_SIZE;
                        INSIST(oldsize == size);
                }
-               isc__mem_free(ctx, ptr FLARG_PASS);
+               isc_mem_free((isc_mem_t *)ctx, ptr);
 
                MCTXLOCK(ctx, &ctx->lock);
                ctx->references--;
@@ -1042,9 +1225,9 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
                destroy(ctx);
 }
 
-void
-isc_mem_destroy(isc_mem_t **ctxp) {
-       isc_mem_t *ctx;
+ISC_MEMFUNC_SCOPE void
+isc__mem_destroy(isc_mem_t **ctxp) {
+       isc__mem_t *ctx;
 
        /*
         * This routine provides legacy support for callers who use mctxs
@@ -1052,7 +1235,7 @@ isc_mem_destroy(isc_mem_t **ctxp) {
         */
 
        REQUIRE(ctxp != NULL);
-       ctx = *ctxp;
+       ctx = (isc__mem_t *)*ctxp;
        REQUIRE(VALID_CONTEXT(ctx));
 
        MCTXLOCK(ctx, &ctx->lock);
@@ -1069,8 +1252,9 @@ isc_mem_destroy(isc_mem_t **ctxp) {
        *ctxp = NULL;
 }
 
-isc_result_t
-isc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) {
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mem_ondestroy(isc_mem_t *ctx0, isc_task_t *task, isc_event_t **event) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
        isc_result_t res;
 
        MCTXLOCK(ctx, &ctx->lock);
@@ -1080,16 +1264,16 @@ isc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) {
        return (res);
 }
 
-
-void *
-isc__mem_get(isc_mem_t *ctx, size_t size FLARG) {
+ISC_MEMFUNC_SCOPE void *
+isc___mem_get(isc_mem_t *ctx0, size_t size FLARG) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
        void *ptr;
        isc_boolean_t call_water = ISC_FALSE;
 
        REQUIRE(VALID_CONTEXT(ctx));
 
        if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0)
-               return (isc__mem_allocate(ctx, size FLARG_PASS));
+               return (isc__mem_allocate(ctx0, size FLARG_PASS));
 
        if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
                MCTXLOCK(ctx, &ctx->lock);
@@ -1102,6 +1286,10 @@ isc__mem_get(isc_mem_t *ctx, size_t size FLARG) {
        }
 
        ADD_TRACE(ctx, ptr, size, file, line);
+       if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water &&
+           !ctx->is_overmem) {
+               ctx->is_overmem = ISC_TRUE;
+       }
        if (ctx->hi_water != 0U && !ctx->hi_called &&
            ctx->inuse > ctx->hi_water) {
                call_water = ISC_TRUE;
@@ -1121,9 +1309,9 @@ isc__mem_get(isc_mem_t *ctx, size_t size FLARG) {
        return (ptr);
 }
 
-void
-isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
-{
+ISC_MEMFUNC_SCOPE void
+isc___mem_put(isc_mem_t *ctx0, void *ptr, size_t size FLARG) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
        isc_boolean_t call_water = ISC_FALSE;
        size_info *si;
        size_t oldsize;
@@ -1139,7 +1327,7 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
                                oldsize -= ALIGNMENT_SIZE;
                        INSIST(oldsize == size);
                }
-               isc__mem_free(ctx, ptr FLARG_PASS);
+               isc_mem_free((isc_mem_t *)ctx, ptr);
                return;
        }
 
@@ -1159,6 +1347,10 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
         * 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->is_overmem &&
+           (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
+               ctx->is_overmem = ISC_FALSE;
+       }
        if (ctx->hi_called &&
            (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
                if (ctx->water != NULL)
@@ -1170,8 +1362,10 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
                (ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
 }
 
-void
-isc_mem_waterack(isc_mem_t *ctx, int flag) {
+ISC_MEMFUNC_SCOPE void
+isc__mem_waterack(isc_mem_t *ctx0, int flag) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
        REQUIRE(VALID_CONTEXT(ctx));
 
        MCTXLOCK(ctx, &ctx->lock);
@@ -1184,7 +1378,7 @@ isc_mem_waterack(isc_mem_t *ctx, int flag) {
 
 #if ISC_MEM_TRACKLINES
 static void
-print_active(isc_mem_t *mctx, FILE *out) {
+print_active(isc__mem_t *mctx, FILE *out) {
        if (mctx->debuglist != NULL) {
                debuglink_t *dl;
                unsigned int i, j;
@@ -1226,11 +1420,12 @@ print_active(isc_mem_t *mctx, FILE *out) {
 /*
  * Print the stats[] on the stream "out" with suitable formatting.
  */
-void
-isc_mem_stats(isc_mem_t *ctx, FILE *out) {
+ISC_MEMFUNC_SCOPE void
+isc__mem_stats(isc_mem_t *ctx0, FILE *out) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
        size_t i;
        const struct stats *s;
-       const isc_mempool_t *pool;
+       const isc__mempool_t *pool;
 
        REQUIRE(VALID_CONTEXT(ctx));
        MCTXLOCK(ctx, &ctx->lock);
@@ -1303,7 +1498,8 @@ isc_mem_stats(isc_mem_t *ctx, FILE *out) {
  */
 
 static void *
-isc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) {
+isc__mem_allocateunlocked(isc_mem_t *ctx0, size_t size) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
        size_info *si;
 
        size += ALIGNMENT_SIZE;
@@ -1325,8 +1521,9 @@ isc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) {
        return (&si[1]);
 }
 
-void *
-isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
+ISC_MEMFUNC_SCOPE void *
+isc___mem_allocate(isc_mem_t *ctx0, size_t size FLARG) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
        size_info *si;
        isc_boolean_t call_water = ISC_FALSE;
 
@@ -1334,9 +1531,9 @@ isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
 
        if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
                MCTXLOCK(ctx, &ctx->lock);
-               si = isc__mem_allocateunlocked(ctx, size);
+               si = isc__mem_allocateunlocked((isc_mem_t *)ctx, size);
        } else {
-               si = isc__mem_allocateunlocked(ctx, size);
+               si = isc__mem_allocateunlocked((isc_mem_t *)ctx, size);
                MCTXLOCK(ctx, &ctx->lock);
                if (si != NULL)
                        mem_getstats(ctx, si[-1].u.size);
@@ -1345,6 +1542,11 @@ isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
 #if ISC_MEM_TRACKLINES
        ADD_TRACE(ctx, si, si[-1].u.size, file, line);
 #endif
+       if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water &&
+           !ctx->is_overmem) {
+               ctx->is_overmem = ISC_TRUE;
+       }
+
        if (ctx->hi_water != 0U && !ctx->hi_called &&
            ctx->inuse > ctx->hi_water) {
                ctx->hi_called = ISC_TRUE;
@@ -1365,8 +1567,9 @@ isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
        return (si);
 }
 
-void *
-isc__mem_reallocate(isc_mem_t *ctx, void *ptr, size_t size FLARG) {
+ISC_MEMFUNC_SCOPE void *
+isc___mem_reallocate(isc_mem_t *ctx0, void *ptr, size_t size FLARG) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
        void *new_ptr = NULL;
        size_t oldsize, copysize;
 
@@ -1384,23 +1587,24 @@ isc__mem_reallocate(isc_mem_t *ctx, void *ptr, size_t size FLARG) {
         *     NULL if allocation fails or doesn't happen.
         */
        if (size > 0U) {
-               new_ptr = isc__mem_allocate(ctx, size FLARG_PASS);
+               new_ptr = isc__mem_allocate(ctx0, size FLARG_PASS);
                if (new_ptr != NULL && ptr != NULL) {
                        oldsize = (((size_info *)ptr)[-1]).u.size;
                        INSIST(oldsize >= ALIGNMENT_SIZE);
                        oldsize -= ALIGNMENT_SIZE;
                        copysize = oldsize > size ? size : oldsize;
                        memcpy(new_ptr, ptr, copysize);
-                       isc__mem_free(ctx, ptr FLARG_PASS);
+                       isc__mem_free(ctx0, ptr FLARG_PASS);
                }
        } else if (ptr != NULL)
-               isc__mem_free(ctx, ptr FLARG_PASS);
+               isc__mem_free(ctx0, ptr FLARG_PASS);
 
        return (new_ptr);
 }
 
-void
-isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) {
+ISC_MEMFUNC_SCOPE void
+isc___mem_free(isc_mem_t *ctx0, void *ptr FLARG) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
        size_info *si;
        size_t size;
        isc_boolean_t call_water= ISC_FALSE;
@@ -1433,6 +1637,11 @@ isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) {
         * 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->is_overmem &&
+           (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
+               ctx->is_overmem = ISC_FALSE;
+       }
+
        if (ctx->hi_called &&
            (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
                ctx->hi_called = ISC_FALSE;
@@ -1451,8 +1660,9 @@ isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) {
  * Other useful things.
  */
 
-char *
-isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
+ISC_MEMFUNC_SCOPE char *
+isc___mem_strdup(isc_mem_t *mctx0, const char *s FLARG) {
+       isc__mem_t *mctx = (isc__mem_t *)mctx0;
        size_t len;
        char *ns;
 
@@ -1461,7 +1671,7 @@ isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
 
        len = strlen(s);
 
-       ns = isc__mem_allocate(mctx, len + 1 FLARG_PASS);
+       ns = isc___mem_allocate((isc_mem_t *)mctx, len + 1 FLARG_PASS);
 
        if (ns != NULL)
                strncpy(ns, s, len + 1);
@@ -1469,8 +1679,10 @@ isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
        return (ns);
 }
 
-void
-isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) {
+ISC_MEMFUNC_SCOPE void
+isc__mem_setdestroycheck(isc_mem_t *ctx0, isc_boolean_t flag) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
        REQUIRE(VALID_CONTEXT(ctx));
        MCTXLOCK(ctx, &ctx->lock);
 
@@ -1483,8 +1695,10 @@ isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) {
  * Quotas
  */
 
-void
-isc_mem_setquota(isc_mem_t *ctx, size_t quota) {
+ISC_MEMFUNC_SCOPE void
+isc__mem_setquota(isc_mem_t *ctx0, size_t quota) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
        REQUIRE(VALID_CONTEXT(ctx));
        MCTXLOCK(ctx, &ctx->lock);
 
@@ -1493,8 +1707,9 @@ isc_mem_setquota(isc_mem_t *ctx, size_t quota) {
        MCTXUNLOCK(ctx, &ctx->lock);
 }
 
-size_t
-isc_mem_getquota(isc_mem_t *ctx) {
+ISC_MEMFUNC_SCOPE size_t
+isc__mem_getquota(isc_mem_t *ctx0) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
        size_t quota;
 
        REQUIRE(VALID_CONTEXT(ctx));
@@ -1507,8 +1722,9 @@ isc_mem_getquota(isc_mem_t *ctx) {
        return (quota);
 }
 
-size_t
-isc_mem_inuse(isc_mem_t *ctx) {
+ISC_MEMFUNC_SCOPE size_t
+isc__mem_inuse(isc_mem_t *ctx0) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
        size_t inuse;
 
        REQUIRE(VALID_CONTEXT(ctx));
@@ -1521,10 +1737,11 @@ isc_mem_inuse(isc_mem_t *ctx) {
        return (inuse);
 }
 
-void
-isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
+ISC_MEMFUNC_SCOPE void
+isc__mem_setwater(isc_mem_t *ctx0, isc_mem_water_t water, void *water_arg,
                 size_t hiwater, size_t lowater)
 {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
        isc_boolean_t callwater = ISC_FALSE;
        isc_mem_water_t oldwater;
        void *oldwater_arg;
@@ -1559,8 +1776,24 @@ isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
                (oldwater)(oldwater_arg, ISC_MEM_LOWATER);
 }
 
-void
-isc_mem_setname(isc_mem_t *ctx, const char *name, void *tag) {
+ISC_MEMFUNC_SCOPE isc_boolean_t
+isc__mem_isovermem(isc_mem_t *ctx0) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
+       REQUIRE(VALID_CONTEXT(ctx));
+
+       /*
+        * We don't bother to lock the context because 100% accuracy isn't
+        * necessary (and even if we locked the context the returned value
+        * could be different from the actual state when it's used anyway)
+        */
+       return (ctx->is_overmem);
+}
+
+ISC_MEMFUNC_SCOPE void
+isc__mem_setname(isc_mem_t *ctx0, const char *name, void *tag) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
        REQUIRE(VALID_CONTEXT(ctx));
 
        LOCK(&ctx->lock);
@@ -1570,15 +1803,19 @@ isc_mem_setname(isc_mem_t *ctx, const char *name, void *tag) {
        UNLOCK(&ctx->lock);
 }
 
-const char *
-isc_mem_getname(isc_mem_t *ctx) {
+ISC_MEMFUNC_SCOPE const char *
+isc__mem_getname(isc_mem_t *ctx0) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
        REQUIRE(VALID_CONTEXT(ctx));
 
        return (ctx->name);
 }
 
-void *
-isc_mem_gettag(isc_mem_t *ctx) {
+ISC_MEMFUNC_SCOPE void *
+isc__mem_gettag(isc_mem_t *ctx0) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
+
        REQUIRE(VALID_CONTEXT(ctx));
 
        return (ctx->tag);
@@ -1588,9 +1825,10 @@ isc_mem_gettag(isc_mem_t *ctx) {
  * Memory pool stuff
  */
 
-isc_result_t
-isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
-       isc_mempool_t *mpctx;
+ISC_MEMFUNC_SCOPE isc_result_t
+isc__mempool_create(isc_mem_t *mctx0, size_t size, isc_mempool_t **mpctxp) {
+       isc__mem_t *mctx = (isc__mem_t *)mctx0;
+       isc__mempool_t *mpctx;
 
        REQUIRE(VALID_CONTEXT(mctx));
        REQUIRE(size > 0U);
@@ -1600,11 +1838,13 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
         * Allocate space for this pool, initialize values, and if all works
         * well, attach to the memory context.
         */
-       mpctx = isc_mem_get(mctx, sizeof(isc_mempool_t));
+       mpctx = isc_mem_get((isc_mem_t *)mctx, sizeof(isc__mempool_t));
        if (mpctx == NULL)
                return (ISC_R_NOMEMORY);
 
-       mpctx->magic = MEMPOOL_MAGIC;
+       mpctx->common.methods = (isc_mempoolmethods_t *)&mempoolmethods;
+       mpctx->common.impmagic = MEMPOOL_MAGIC;
+       mpctx->common.magic = ISCAPI_MPOOL_MAGIC;
        mpctx->lock = NULL;
        mpctx->mctx = mctx;
        mpctx->size = size;
@@ -1619,7 +1859,7 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
 #endif
        mpctx->items = NULL;
 
-       *mpctxp = mpctx;
+       *mpctxp = (isc_mempool_t *)mpctx;
 
        MCTXLOCK(mctx, &mctx->lock);
        ISC_LIST_INITANDAPPEND(mctx->pools, mpctx, link);
@@ -1629,9 +1869,12 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
        return (ISC_R_SUCCESS);
 }
 
-void
-isc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setname(isc_mempool_t *mpctx0, const char *name) {
+       isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
        REQUIRE(name != NULL);
+       REQUIRE(VALID_MEMPOOL(mpctx));
 
 #if ISC_MEMPOOL_NAMES
        if (mpctx->lock != NULL)
@@ -1648,20 +1891,20 @@ isc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
 #endif
 }
 
-void
-isc_mempool_destroy(isc_mempool_t **mpctxp) {
-       isc_mempool_t *mpctx;
-       isc_mem_t *mctx;
+ISC_MEMFUNC_SCOPE void
+isc__mempool_destroy(isc_mempool_t **mpctxp) {
+       isc__mempool_t *mpctx;
+       isc__mem_t *mctx;
        isc_mutex_t *lock;
        element *item;
 
        REQUIRE(mpctxp != NULL);
-       mpctx = *mpctxp;
+       mpctx = (isc__mempool_t *)*mpctxp;
        REQUIRE(VALID_MEMPOOL(mpctx));
 #if ISC_MEMPOOL_NAMES
        if (mpctx->allocated > 0)
                UNEXPECTED_ERROR(__FILE__, __LINE__,
-                                "isc_mempool_destroy(): mempool %s "
+                                "isc__mempool_destroy(): mempool %s "
                                 "leaked memory",
                                 mpctx->name);
 #endif
@@ -1701,9 +1944,10 @@ isc_mempool_destroy(isc_mempool_t **mpctxp) {
        mctx->poolcnt--;
        MCTXUNLOCK(mctx, &mctx->lock);
 
-       mpctx->magic = 0;
+       mpctx->common.impmagic = 0;
+       mpctx->common.magic = 0;
 
-       isc_mem_put(mpctx->mctx, mpctx, sizeof(isc_mempool_t));
+       isc_mem_put((isc_mem_t *)mpctx->mctx, mpctx, sizeof(isc__mempool_t));
 
        if (lock != NULL)
                UNLOCK(lock);
@@ -1711,8 +1955,10 @@ isc_mempool_destroy(isc_mempool_t **mpctxp) {
        *mpctxp = NULL;
 }
 
-void
-isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) {
+ISC_MEMFUNC_SCOPE void
+isc__mempool_associatelock(isc_mempool_t *mpctx0, isc_mutex_t *lock) {
+       isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
        REQUIRE(VALID_MEMPOOL(mpctx));
        REQUIRE(mpctx->lock == NULL);
        REQUIRE(lock != NULL);
@@ -1720,10 +1966,11 @@ isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) {
        mpctx->lock = lock;
 }
 
-void *
-isc__mempool_get(isc_mempool_t *mpctx FLARG) {
+ISC_MEMFUNC_SCOPE void *
+isc___mempool_get(isc_mempool_t *mpctx0 FLARG) {
+       isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
        element *item;
-       isc_mem_t *mctx;
+       isc__mem_t *mctx;
        unsigned int i;
 
        REQUIRE(VALID_MEMPOOL(mpctx));
@@ -1802,9 +2049,10 @@ isc__mempool_get(isc_mempool_t *mpctx FLARG) {
        return (item);
 }
 
-void
-isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
-       isc_mem_t *mctx;
+ISC_MEMFUNC_SCOPE void
+isc___mempool_put(isc_mempool_t *mpctx0, void *mem FLARG) {
+       isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+       isc__mem_t *mctx;
        element *item;
 
        REQUIRE(VALID_MEMPOOL(mpctx));
@@ -1859,8 +2107,10 @@ isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
  * Quotas
  */
 
-void
-isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) {
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setfreemax(isc_mempool_t *mpctx0, unsigned int limit) {
+       isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
        REQUIRE(VALID_MEMPOOL(mpctx));
 
        if (mpctx->lock != NULL)
@@ -1872,8 +2122,9 @@ isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) {
                UNLOCK(mpctx->lock);
 }
 
-unsigned int
-isc_mempool_getfreemax(isc_mempool_t *mpctx) {
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfreemax(isc_mempool_t *mpctx0) {
+       isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
        unsigned int freemax;
 
        REQUIRE(VALID_MEMPOOL(mpctx));
@@ -1889,8 +2140,9 @@ isc_mempool_getfreemax(isc_mempool_t *mpctx) {
        return (freemax);
 }
 
-unsigned int
-isc_mempool_getfreecount(isc_mempool_t *mpctx) {
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfreecount(isc_mempool_t *mpctx0) {
+       isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
        unsigned int freecount;
 
        REQUIRE(VALID_MEMPOOL(mpctx));
@@ -1906,8 +2158,10 @@ isc_mempool_getfreecount(isc_mempool_t *mpctx) {
        return (freecount);
 }
 
-void
-isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) {
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setmaxalloc(isc_mempool_t *mpctx0, unsigned int limit) {
+       isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
        REQUIRE(limit > 0);
 
        REQUIRE(VALID_MEMPOOL(mpctx));
@@ -1921,8 +2175,9 @@ isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) {
                UNLOCK(mpctx->lock);
 }
 
-unsigned int
-isc_mempool_getmaxalloc(isc_mempool_t *mpctx) {
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getmaxalloc(isc_mempool_t *mpctx0) {
+       isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
        unsigned int maxalloc;
 
        REQUIRE(VALID_MEMPOOL(mpctx));
@@ -1938,8 +2193,9 @@ isc_mempool_getmaxalloc(isc_mempool_t *mpctx) {
        return (maxalloc);
 }
 
-unsigned int
-isc_mempool_getallocated(isc_mempool_t *mpctx) {
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getallocated(isc_mempool_t *mpctx0) {
+       isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
        unsigned int allocated;
 
        REQUIRE(VALID_MEMPOOL(mpctx));
@@ -1955,8 +2211,10 @@ isc_mempool_getallocated(isc_mempool_t *mpctx) {
        return (allocated);
 }
 
-void
-isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) {
+ISC_MEMFUNC_SCOPE void
+isc__mempool_setfillcount(isc_mempool_t *mpctx0, unsigned int limit) {
+       isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
        REQUIRE(limit > 0);
        REQUIRE(VALID_MEMPOOL(mpctx));
 
@@ -1969,8 +2227,10 @@ isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) {
                UNLOCK(mpctx->lock);
 }
 
-unsigned int
-isc_mempool_getfillcount(isc_mempool_t *mpctx) {
+ISC_MEMFUNC_SCOPE unsigned int
+isc__mempool_getfillcount(isc_mempool_t *mpctx0) {
+       isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
+
        unsigned int fillcount;
 
        REQUIRE(VALID_MEMPOOL(mpctx));
@@ -1986,8 +2246,17 @@ isc_mempool_getfillcount(isc_mempool_t *mpctx) {
        return (fillcount);
 }
 
-void
-isc_mem_printactive(isc_mem_t *ctx, FILE *file) {
+#ifdef USE_MEMIMPREGISTER
+isc_result_t
+isc__mem_register() {
+       return (isc_mem_register(isc__mem_create2));
+}
+#endif
+
+#ifdef BIND9
+ISC_MEMFUNC_SCOPE void
+isc__mem_printactive(isc_mem_t *ctx0, FILE *file) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
 
        REQUIRE(VALID_CONTEXT(ctx));
        REQUIRE(file != NULL);
@@ -2000,12 +2269,12 @@ isc_mem_printactive(isc_mem_t *ctx, FILE *file) {
 #endif
 }
 
-void
-isc_mem_printallactive(FILE *file) {
+ISC_MEMFUNC_SCOPE void
+isc__mem_printallactive(FILE *file) {
 #if !ISC_MEM_TRACKLINES
        UNUSED(file);
 #else
-       isc_mem_t *ctx;
+       isc__mem_t *ctx;
 
        RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
 
@@ -2020,15 +2289,15 @@ isc_mem_printallactive(FILE *file) {
 #endif
 }
 
-void
-isc_mem_checkdestroyed(FILE *file) {
+ISC_MEMFUNC_SCOPE 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;
+               isc__mem_t *ctx;
 
                for (ctx = ISC_LIST_HEAD(contexts);
                     ctx != NULL;
@@ -2043,9 +2312,11 @@ isc_mem_checkdestroyed(FILE *file) {
        UNLOCK(&lock);
 }
 
-unsigned int
-isc_mem_references(isc_mem_t *ctx) {
+ISC_MEMFUNC_SCOPE unsigned int
+isc_mem_references(isc_mem_t *ctx0) {
+       isc__mem_t *ctx = (isc__mem_t *)ctx0;
        unsigned int references;
+
        REQUIRE(VALID_CONTEXT(ctx));
 
        MCTXLOCK(ctx, &ctx->lock);
@@ -2065,7 +2336,7 @@ typedef struct summarystat {
 } summarystat_t;
 
 static void
-renderctx(isc_mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) {
+renderctx(isc__mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) {
        REQUIRE(VALID_CONTEXT(ctx));
 
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "context");
@@ -2151,7 +2422,7 @@ renderctx(isc_mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) {
 
 void
 isc_mem_renderxml(xmlTextWriterPtr writer) {
-       isc_mem_t *ctx;
+       isc__mem_t *ctx;
        summarystat_t summary;
        isc_uint64_t lost;
 
@@ -2203,3 +2474,4 @@ isc_mem_renderxml(xmlTextWriterPtr writer) {
 }
 
 #endif /* HAVE_LIBXML2 */
+#endif /* BIND9 */
diff --git a/lib/isc/mem_api.c b/lib/isc/mem_api.c
new file mode 100644 (file)
index 0000000..85abb9b
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2009, 2010  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: mem_api.c,v 1.8 2010/08/12 21:30:26 jinmei Exp $ */
+
+#include <config.h>
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/util.h>
+
+#if ISC_MEM_TRACKLINES
+#define FLARG_PASS     , file, line
+#define FLARG          , const char *file, unsigned int line
+#else
+#define FLARG_PASS
+#define FLARG
+#endif
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_memcreatefunc_t mem_createfunc = NULL;
+
+static void
+initialize(void) {
+       RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_mem_register(isc_memcreatefunc_t createfunc) {
+       isc_result_t result = ISC_R_SUCCESS;
+
+       RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+       LOCK(&createlock);
+       if (mem_createfunc == NULL)
+               mem_createfunc = createfunc;
+       else
+               result = ISC_R_EXISTS;
+       UNLOCK(&createlock);
+
+       return (result);
+}
+
+isc_result_t
+isc_mem_create(size_t init_max_size, size_t target_size, isc_mem_t **mctxp) {
+       isc_result_t result;
+
+       LOCK(&createlock);
+
+       REQUIRE(mem_createfunc != NULL);
+       result = (*mem_createfunc)(init_max_size, target_size, mctxp,
+                                  ISC_MEMFLAG_DEFAULT);
+
+       UNLOCK(&createlock);
+
+       return (result);
+}
+
+isc_result_t
+isc_mem_create2(size_t init_max_size, size_t target_size, isc_mem_t **mctxp,
+               unsigned int flags)
+{
+       isc_result_t result;
+
+       LOCK(&createlock);
+
+       REQUIRE(mem_createfunc != NULL);
+       result = (*mem_createfunc)(init_max_size, target_size, mctxp, flags);
+
+       UNLOCK(&createlock);
+
+       return (result);
+}
+
+void
+isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
+       REQUIRE(ISCAPI_MCTX_VALID(source));
+       REQUIRE(targetp != NULL && *targetp == NULL);
+
+       source->methods->attach(source, targetp);
+
+       ENSURE(*targetp == source);
+}
+
+void
+isc_mem_detach(isc_mem_t **mctxp) {
+       REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
+
+       (*mctxp)->methods->detach(mctxp);
+
+       ENSURE(*mctxp == NULL);
+}
+
+void
+isc_mem_destroy(isc_mem_t **mctxp) {
+       REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
+
+       (*mctxp)->methods->destroy(mctxp);
+
+       ENSURE(*mctxp == NULL);
+}
+
+void *
+isc__mem_get(isc_mem_t *mctx, size_t size FLARG) {
+       REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+       return (mctx->methods->memget(mctx, size FLARG_PASS));
+}
+
+void
+isc__mem_put(isc_mem_t *mctx, void *ptr, size_t size FLARG) {
+       REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+       mctx->methods->memput(mctx, ptr, size FLARG_PASS);
+}
+
+void
+isc__mem_putanddetach(isc_mem_t **mctxp, void *ptr, size_t size FLARG) {
+       REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
+
+       (*mctxp)->methods->memputanddetach(mctxp, ptr, size FLARG_PASS);
+
+       /*
+        * XXX: We cannot always ensure *mctxp == NULL here
+        * (see lib/isc/mem.c).
+        */
+}
+
+void *
+isc__mem_allocate(isc_mem_t *mctx, size_t size FLARG) {
+       REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+       return (mctx->methods->memallocate(mctx, size FLARG_PASS));
+}
+
+void *
+isc__mem_reallocate(isc_mem_t *mctx, void *ptr, size_t size FLARG) {
+       REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+       return (mctx->methods->memreallocate(mctx, ptr, size FLARG_PASS));
+}
+
+char *
+isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
+       REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+       return (mctx->methods->memstrdup(mctx, s FLARG_PASS));
+}
+
+void
+isc__mem_free(isc_mem_t *mctx, void *ptr FLARG) {
+       REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+       mctx->methods->memfree(mctx, ptr FLARG_PASS);
+}
+
+void
+isc_mem_setdestroycheck(isc_mem_t *mctx, isc_boolean_t flag) {
+       REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+       mctx->methods->setdestroycheck(mctx, flag);
+}
+
+void
+isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
+                size_t hiwater, size_t lowater)
+{
+       REQUIRE(ISCAPI_MCTX_VALID(ctx));
+
+       ctx->methods->setwater(ctx, water, water_arg, hiwater, lowater);
+}
+
+void
+isc_mem_waterack(isc_mem_t *ctx, int flag) {
+       REQUIRE(ISCAPI_MCTX_VALID(ctx));
+
+       ctx->methods->waterack(ctx, flag);
+}
+
+size_t
+isc_mem_inuse(isc_mem_t *mctx) {
+       REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+       return (mctx->methods->inuse(mctx));
+}
+
+isc_boolean_t
+isc_mem_isovermem(isc_mem_t *mctx) {
+       REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+       return (mctx->methods->isovermem(mctx));
+}
+
+void
+isc_mem_setname(isc_mem_t *mctx, const char *name, void *tag) {
+       REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+       UNUSED(name);
+       UNUSED(tag);
+
+       return;
+}
+
+const char *
+isc_mem_getname(isc_mem_t *mctx) {
+       REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+       return ("");
+}
+
+void *
+isc_mem_gettag(isc_mem_t *mctx) {
+       REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+       return (NULL);
+}
+
+isc_result_t
+isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
+       REQUIRE(ISCAPI_MCTX_VALID(mctx));
+
+       return (mctx->methods->mpcreate(mctx, size, mpctxp));
+}
+
+void
+isc_mempool_destroy(isc_mempool_t **mpctxp) {
+       REQUIRE(mpctxp != NULL && ISCAPI_MPOOL_VALID(*mpctxp));
+
+       (*mpctxp)->methods->destroy(mpctxp);
+
+       ENSURE(*mpctxp == NULL);
+}
+
+void *
+isc__mempool_get(isc_mempool_t *mpctx FLARG) {
+       REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+       return (mpctx->methods->get(mpctx FLARG_PASS));
+}
+
+void
+isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
+       REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+       mpctx->methods->put(mpctx, mem FLARG_PASS);
+}
+
+unsigned int
+isc_mempool_getallocated(isc_mempool_t *mpctx) {
+       REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+       return (mpctx->methods->getallocated(mpctx));
+}
+
+void
+isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) {
+       REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+       mpctx->methods->setmaxalloc(mpctx, limit);
+}
+
+void
+isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) {
+       REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+       mpctx->methods->setfreemax(mpctx, limit);
+}
+
+void
+isc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
+       REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+       mpctx->methods->setname(mpctx, name);
+}
+
+void
+isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) {
+       REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+       mpctx->methods->associatelock(mpctx, lock);
+}
+
+void
+isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) {
+       REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
+
+       mpctx->methods->setfillcount(mpctx, limit);
+}
index d45ad0e1e485abf24b956a3e34014bf10398f8fa..d41e9d28d86deae7f9549860f4338865746d0537 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: mutexblock.c,v 1.20 2007/06/19 23:47:17 tbox Exp $ */
+/* $Id$ */
 
 /*! \file */
 
@@ -32,10 +32,9 @@ isc_mutexblock_init(isc_mutex_t *block, unsigned int count) {
        for (i = 0; i < count; i++) {
                result = isc_mutex_init(&block[i]);
                if (result != ISC_R_SUCCESS) {
-                       i--;
-                       while (i > 0) {
-                               DESTROYLOCK(&block[i]);
+                       while (i > 0U) {
                                i--;
+                               DESTROYLOCK(&block[i]);
                        }
                        return (result);
                }
index 85dd53e03eb6b883ccfe73213910ca8882bd9a9c..5cce1bc1a03e9353b1320902cfddcce028833cde 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2010-2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2002  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: netaddr.c,v 1.38 2007/06/18 23:47:44 tbox Exp $ */
+/* $Id$ */
 
 /*! \file */
 
@@ -69,10 +69,10 @@ isc_boolean_t
 isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
                     unsigned int prefixlen)
 {
-       const unsigned char *pa, *pb;
-       unsigned int ipabytes; /* Length of whole IP address in bytes */
-       unsigned int nbytes;   /* Number of significant whole bytes */
-       unsigned int nbits;    /* Number of significant leftover bits */
+       const unsigned char *pa = NULL, *pb = NULL;
+       unsigned int ipabytes = 0; /* Length of whole IP address in bytes */
+       unsigned int nbytes;       /* Number of significant whole bytes */
+       unsigned int nbits;        /* Number of significant leftover bits */
 
        REQUIRE(a != NULL && b != NULL);
 
@@ -94,8 +94,6 @@ isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
                ipabytes = 16;
                break;
        default:
-               pa = pb = NULL; /* Avoid silly compiler warning. */
-               ipabytes = 0; /* Ditto. */
                return (ISC_FALSE);
        }
 
@@ -188,6 +186,9 @@ isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) {
        isc_buffer_init(&buf, array, size);
        result = isc_netaddr_totext(na, &buf);
 
+       if (size == 0)
+               return;
+
        /*
         * Null terminate.
         */
@@ -212,7 +213,7 @@ isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) {
 isc_result_t
 isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) {
        static const unsigned char zeros[16];
-       unsigned int nbits, nbytes, ipbytes;
+       unsigned int nbits, nbytes, ipbytes = 0;
        const unsigned char *p;
 
        switch (na->family) {
@@ -229,7 +230,6 @@ isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) {
                        return (ISC_R_RANGE);
                break;
        default:
-               ipbytes = 0;
                return (ISC_R_NOTIMPLEMENTED);
        }
        nbytes = prefixlen / 8;
@@ -246,7 +246,7 @@ isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) {
 
 isc_result_t
 isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) {
-       unsigned int nbits, nbytes, ipbytes, i;
+       unsigned int nbits = 0, nbytes = 0, ipbytes = 0, i;
        const unsigned char *p;
 
        switch (s->family) {
@@ -259,10 +259,8 @@ isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) {
                ipbytes = 16;
                break;
        default:
-               ipbytes = 0;
                return (ISC_R_NOTIMPLEMENTED);
        }
-       nbytes = nbits = 0;
        for (i = 0; i < ipbytes; i++) {
                if (p[i] != 0xFF)
                        break;
@@ -303,18 +301,18 @@ isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) {
 isc_result_t
 isc_netaddr_frompath(isc_netaddr_t *netaddr, const char *path) {
 #ifdef ISC_PLATFORM_HAVESYSUNH
-        if (strlen(path) > sizeof(netaddr->type.un) - 1)
-                return (ISC_R_NOSPACE);
-
-        memset(netaddr, 0, sizeof(*netaddr));
-        netaddr->family = AF_UNIX;
-        strcpy(netaddr->type.un, path);
-        netaddr->zone = 0;
-        return (ISC_R_SUCCESS);
-#else 
+       if (strlen(path) > sizeof(netaddr->type.un) - 1)
+               return (ISC_R_NOSPACE);
+
+       memset(netaddr, 0, sizeof(*netaddr));
+       netaddr->family = AF_UNIX;
+       strcpy(netaddr->type.un, path);
+       netaddr->zone = 0;
+       return (ISC_R_SUCCESS);
+#else
        UNUSED(netaddr);
        UNUSED(path);
-        return (ISC_R_NOTIMPLEMENTED);
+       return (ISC_R_NOTIMPLEMENTED);
 #endif
 }
 
index 765cb6d72a8ccbcee04ff090e42de2e0be1a9d80..030007f34ed7fc9bf9dcaa4d7999d1aae374c804 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005, 2007, 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: atomic.h,v 1.6 2007/06/18 23:47:47 tbox Exp $ */
+/* $Id$ */
 
 #ifndef ISC_ATOMIC_H
 #define ISC_ATOMIC_H 1
 
 #include <sys/atomic_op.h>
 
-#define isc_atomic_xadd(p, v) fetch_and_add(p, v)
 #define isc_atomic_store(p, v) _clear_lock(p, v)
 
+#ifdef __GNUC__
+static inline isc_int32_t
+#else
+static isc_int32_t
+#endif
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+       int ret;
+
+#ifdef __GNUC__
+       asm("ics");
+#else
+        __isync();
+#endif
+
+       ret = fetch_and_add((atomic_p)p, (int)val);
+
+#ifdef __GNUC__
+       asm("ics");
+#else
+        __isync();
+#endif
+
+        return (ret);
+}
+
 #ifdef __GNUC__
 static inline int
 #else
 static int
 #endif
 isc_atomic_cmpxchg(atomic_p p, int old, int new) {
-        int orig = old;
+       int orig = old;
+
+#ifdef __GNUC__
+       asm("ics");
+#else
+        __isync();
+#endif
+       if (compare_and_swap(p, &orig, new))
+               orig = old;
 
 #ifdef __GNUC__
-        asm("ics");
+       asm("ics");
 #else
-         __isync();
+        __isync();
 #endif
-        if (compare_and_swap(p, &orig, new))
-               return (old);
-        return (orig);
+
+       return (orig);
 }
 
 #elif defined(ISC_PLATFORM_USEGCCASM) || defined(ISC_PLATFORM_USEMACASM)
@@ -76,17 +107,19 @@ isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
 #ifdef ISC_PLATFORM_USEMACASM
                "1:"
                "lwarx r6, 0, %1\n"
-               "mr %0, r6\n"
+               "mr %0, r6\n"
                "add r6, r6, %2\n"
                "stwcx. r6, 0, %1\n"
-               "bne- 1b"
+               "bne- 1b\n"
+               "sync"
 #else
                "1:"
                "lwarx 6, 0, %1\n"
-               "mr %0, 6\n"
+               "mr %0, 6\n"
                "add 6, 6, %2\n"
                "stwcx. 6, 0, %1\n"
-               "bne- 1b"
+               "bne- 1b\n"
+               "sync"
 #endif
                : "=&r"(orig)
                : "r"(p), "r"(val)
@@ -104,13 +137,15 @@ isc_atomic_store(void *p, isc_int32_t val) {
                "lwarx r6, 0, %0\n"
                "lwz r6, %1\n"
                "stwcx. r6, 0, %0\n"
-               "bne- 1b"
+               "bne- 1b\n"
+               "sync"
 #else
                "1:"
                "lwarx 6, 0, %0\n"
                "lwz 6, %1\n"
                "stwcx. 6, 0, %0\n"
-               "bne- 1b"
+               "bne- 1b\n"
+               "sync"
 #endif
                :
                : "r"(p), "m"(val)
@@ -132,7 +167,8 @@ isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
                "mr r6, %3\n"
                "stwcx. r6, 0, %1\n"
                "bne- 1b\n"
-               "2:"
+               "2:\n"
+               "sync"
 #else
                "1:"
                "lwarx 6, 0, %1\n"
@@ -142,7 +178,8 @@ isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
                "mr 6, %3\n"
                "stwcx. 6, 0, %1\n"
                "bne- 1b\n"
-               "2:"
+               "2:\n"
+               "sync"
 #endif
                : "=&r" (orig)
                : "r"(p), "r"(cmpval), "r"(val)
index b892e3a2ed09660d2d665d71616013b24b3f8de1..a5e5ba6699d6627daf6ad104065f1e457f96fc43 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008, 2010  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: print.c,v 1.35 2008/02/18 23:46:59 tbox Exp $ */
+/* $Id: print.c,v 1.37 2010/10/18 23:47:08 tbox Exp $ */
 
 /*! \file */
 
@@ -468,7 +468,7 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
                        if (width > 0) {
                                count += width;
                                width--;
-                               if (left) {
+                               if (left && size > 1) {
                                        *str++ = c;
                                        size--;
                                }
index b57d9eee8daa3543f2eab74b7e33ba5708658d03..c7e5795b6807a95228b204833d855324fa1d98d1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000-2002  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: mutex.c,v 1.16 2008/04/04 23:47:01 tbox Exp $ */
+/* $Id: mutex.c,v 1.18 2011/01/04 23:47:14 tbox Exp $ */
 
 /*! \file */
 
@@ -78,7 +78,7 @@ struct isc_mutexstats {
 };
 
 #ifndef ISC_MUTEX_PROFTABLESIZE
-#define ISC_MUTEX_PROFTABLESIZE (16 * 1024)
+#define ISC_MUTEX_PROFTABLESIZE (1024 * 1024)
 #endif
 static isc_mutexstats_t stats[ISC_MUTEX_PROFTABLESIZE];
 static int stats_next = 0;
@@ -200,24 +200,24 @@ isc_mutex_statsprofile(FILE *fp) {
 
        fprintf(fp, "Mutex stats (in us)\n");
        for (i = 0; i < stats_next; i++) {
-               fprintf(fp, "%-12s %4d: %10u  %lu.%06lu %lu.%06lu\n",
+               fprintf(fp, "%-12s %4d: %10u  %lu.%06lu %lu.%06lu %5d\n",
                        stats[i].file, stats[i].line, stats[i].count,
                        stats[i].locked_total.tv_sec,
                        stats[i].locked_total.tv_usec,
                        stats[i].wait_total.tv_sec,
-                       stats[i].wait_total.tv_usec
-                       );
+                       stats[i].wait_total.tv_usec,
+                       i);
                for (j = 0; j < ISC_MUTEX_MAX_LOCKERS; j++) {
                        locker = &stats[i].lockers[j];
                        if (locker->file == NULL)
                                continue;
-                       fprintf(fp, " %-11s %4d: %10u  %lu.%06lu %lu.%06lu\n",
+                       fprintf(fp, " %-11s %4d: %10u  %lu.%06lu %lu.%06lu %5d\n",
                                locker->file, locker->line, locker->count,
                                locker->locked_total.tv_sec,
                                locker->locked_total.tv_usec,
                                locker->wait_total.tv_sec,
-                               locker->wait_total.tv_usec
-                               );
+                               locker->wait_total.tv_usec,
+                               i);
                }
        }
 }
@@ -234,10 +234,13 @@ isc_mutex_init_errcheck(isc_mutex_t *mp)
        if (pthread_mutexattr_init(&attr) != 0)
                return (ISC_R_UNEXPECTED);
 
-       if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0)
+       if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0) {
+               pthread_mutexattr_destroy(&attr);
                return (ISC_R_UNEXPECTED);
+       }
 
        err = pthread_mutex_init(mp, &attr) != 0)
+       pthread_mutexattr_destroy(&attr);
        if (err == ENOMEM)
                return (ISC_R_NOMEMORY);
        return ((err == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED);
index 7786984169a2e006d42b18c3bf71f2869bfab4fe..ac211efb6a8747743f70067ec786dae54177a51a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2007-2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: radix.c,v 1.20.36.3 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id$ */
 
 /*
  * This source was adapted from MRT's RCS Ids:
@@ -275,7 +275,7 @@ isc_radix_search(isc_radix_tree_t *radix, isc_radix_node_t **target,
        if (node && node->prefix)
                stack[cnt++] = node;
 
-       while (--cnt >= 0) {
+       while (cnt-- > 0) {
                node = stack[cnt];
 
                if (_comp_with_mask(isc_prefix_tochar(node->prefix),
index 0329abde72b29bc4674b8eaa5a03c22ebdd061fe..8b73ed56927d6bc9fb56c0c0a2574a1f956889f7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: random.c,v 1.25 2007/06/19 23:47:17 tbox Exp $ */
+/* $Id: random.c,v 1.28 2009/07/16 05:52:46 marka Exp $ */
 
 /*! \file */
 
@@ -43,7 +43,7 @@ initialize_rand(void)
 {
 #ifndef HAVE_ARC4RANDOM
        unsigned int pid = getpid();
-       
+
        /*
         * The low bits of pid generally change faster.
         * Xor them with the high bits of time which change slowly.
@@ -84,7 +84,16 @@ isc_random_get(isc_uint32_t *val)
         * rand()'s lower bits are not random.
         * rand()'s upper bit is zero.
         */
+#if RAND_MAX >= 0xfffff
+       /* We have at least 20 bits.  Use lower 16 excluding lower most 4 */
        *val = ((rand() >> 4) & 0xffff) | ((rand() << 12) & 0xffff0000);
+#elif RAND_MAX >= 0x7fff
+       /* We have at least 15 bits.  Use lower 10/11 excluding lower most 4 */
+       *val = ((rand() >> 4) & 0x000007ff) | ((rand() << 7) & 0x003ff800) |
+               ((rand() << 18) & 0xffc00000);
+#else
+#error RAND_MAX is too small
+#endif
 #else
        *val = arc4random();
 #endif
@@ -92,13 +101,13 @@ isc_random_get(isc_uint32_t *val)
 
 isc_uint32_t
 isc_random_jitter(isc_uint32_t max, isc_uint32_t jitter) {
-       REQUIRE(jitter < max);
+       isc_uint32_t rnd;
+
+       REQUIRE(jitter < max || (jitter == 0 && max == 0));
+
        if (jitter == 0)
                return (max);
-       else
-#ifndef HAVE_ARC4RANDOM
-               return (max - rand() % jitter);
-#else
-               return (max - arc4random() % jitter);
-#endif
+
+       isc_random_get(&rnd);
+       return (max - rnd % jitter);
 }
index 571358054e8f9b60a75cafbcdde42f57f66f35e6..a9405fddf0557bb56fb4d07597bc9497978e2705 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: result.c,v 1.71 2008/09/25 04:02:39 tbox Exp $ */
+/* $Id$ */
 
 /*! \file */
 
@@ -102,6 +102,7 @@ static const char *text[ISC_R_NRESULTS] = {
        "max size",                             /*%< 58 */
        "invalid address format",               /*%< 59 */
        "bad base32 encoding",                  /*%< 60 */
+       "unset",                                /*%< 61 */
 };
 
 #define ISC_RESULT_RESULTSET                   2
index ca8e83dfc13f877dbf9b8244bd5f972e6a408a60..9c84c258a28b1268423918c93df8f90645749ce1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: rwlock.c,v 1.44.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id$ */
 
 /*! \file */
 
@@ -261,6 +261,7 @@ isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
                }
 
                cntflag = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
+               POST(cntflag);
                while (1) {
                        if ((rwl->cnt_and_flag & WRITER_ACTIVE) == 0)
                                break;
index 3575288481eb13049151e0a88994989b798b821a..cce96036045f35e03517db07666aa6dbf8b6ce92 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: sha1.c,v 1.18 2007/06/19 23:47:17 tbox Exp $ */
+/* $Id$ */
 
 /*     $NetBSD: sha1.c,v 1.5 2000/01/22 22:19:14 mycroft Exp $ */
 /*     $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $       */
 #include "config.h"
 
 #include <isc/assertions.h>
+#include <isc/platform.h>
 #include <isc/sha1.h>
 #include <isc/string.h>
 #include <isc/types.h>
 #include <isc/util.h>
 
+#ifdef ISC_PLATFORM_OPENSSLHASH
+
+void
+isc_sha1_init(isc_sha1_t *context)
+{
+       INSIST(context != NULL);
+
+       EVP_DigestInit(context, EVP_sha1());
+}
+
+void
+isc_sha1_invalidate(isc_sha1_t *context) {
+       EVP_MD_CTX_cleanup(context);
+}
+
+void
+isc_sha1_update(isc_sha1_t *context, const unsigned char *data,
+               unsigned int len)
+{
+       INSIST(context != 0);
+       INSIST(data != 0);
+
+       EVP_DigestUpdate(context, (const void *) data, (size_t) len);
+}
+
+void
+isc_sha1_final(isc_sha1_t *context, unsigned char *digest) {
+       INSIST(digest != 0);
+       INSIST(context != 0);
+
+       EVP_DigestFinal(context, digest, NULL);
+}
+
+#else
+
 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
 
 /*@{*/
@@ -220,6 +256,8 @@ transform(isc_uint32_t state[5], const unsigned char buffer[64]) {
 
        /* Wipe variables */
        a = b = c = d = e = 0;
+       /* Avoid compiler warnings */
+       POST(a); POST(b); POST(c); POST(d); POST(e);
 }
 
 
@@ -313,3 +351,4 @@ isc_sha1_final(isc_sha1_t *context, unsigned char *digest) {
 
        memset(context, 0, sizeof(isc_sha1_t));
 }
+#endif
index 6cd900dd18dc5bbc657a40d69c516c33805bc835..db2e3496c454a3b011bcfa2fc376ac9a414fe136 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2005-2007, 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: sha2.c,v 1.13.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id$ */
 
 /*     $FreeBSD: src/sys/crypto/sha2/sha2.c,v 1.2.2.2 2002/03/05 08:36:47 ume Exp $    */
 /*     $KAME: sha2.c,v 1.8 2001/11/08 01:07:52 itojun Exp $    */
 #include <config.h>
 
 #include <isc/assertions.h>
+#include <isc/platform.h>
 #include <isc/sha2.h>
 #include <isc/string.h>
 #include <isc/util.h>
 
+#ifdef ISC_PLATFORM_OPENSSLHASH
+
+void
+isc_sha224_init(isc_sha224_t *context) {
+       if (context == (isc_sha224_t *)0) {
+               return;
+       }
+       EVP_DigestInit(context, EVP_sha224());
+}
+
+void
+isc_sha224_invalidate(isc_sha224_t *context) {
+       EVP_MD_CTX_cleanup(context);
+}
+
+void
+isc_sha224_update(isc_sha224_t *context, const isc_uint8_t* data, size_t len) {
+       if (len == 0U) {
+               /* Calling with no data is valid - we do nothing */
+               return;
+       }
+
+       /* Sanity check: */
+       REQUIRE(context != (isc_sha224_t *)0 && data != (isc_uint8_t*)0);
+
+       EVP_DigestUpdate(context, (const void *) data, len);
+}
+
+void
+isc_sha224_final(isc_uint8_t digest[], isc_sha224_t *context) {
+       /* Sanity check: */
+       REQUIRE(context != (isc_sha224_t *)0);
+
+       /* If no digest buffer is passed, we don't bother doing this: */
+       if (digest != (isc_uint8_t*)0) {
+               EVP_DigestFinal(context, digest, NULL);
+       } else {
+               EVP_MD_CTX_cleanup(context);
+       }
+}
+
+void
+isc_sha256_init(isc_sha256_t *context) {
+       if (context == (isc_sha256_t *)0) {
+               return;
+       }
+       EVP_DigestInit(context, EVP_sha256());
+}
+
+void
+isc_sha256_invalidate(isc_sha256_t *context) {
+       EVP_MD_CTX_cleanup(context);
+}
+
+void
+isc_sha256_update(isc_sha256_t *context, const isc_uint8_t *data, size_t len) {
+       if (len == 0U) {
+               /* Calling with no data is valid - we do nothing */
+               return;
+       }
+
+       /* Sanity check: */
+       REQUIRE(context != (isc_sha256_t *)0 && data != (isc_uint8_t*)0);
+
+       EVP_DigestUpdate(context, (const void *) data, len);
+}
+
+void
+isc_sha256_final(isc_uint8_t digest[], isc_sha256_t *context) {
+       /* Sanity check: */
+       REQUIRE(context != (isc_sha256_t *)0);
+
+       /* If no digest buffer is passed, we don't bother doing this: */
+       if (digest != (isc_uint8_t*)0) {
+               EVP_DigestFinal(context, digest, NULL);
+       } else {
+               EVP_MD_CTX_cleanup(context);
+       }
+}
+
+void
+isc_sha512_init(isc_sha512_t *context) {
+       if (context == (isc_sha512_t *)0) {
+               return;
+       }
+       EVP_DigestInit(context, EVP_sha512());
+}
+
+void
+isc_sha512_invalidate(isc_sha512_t *context) {
+       EVP_MD_CTX_cleanup(context);
+}
+
+void isc_sha512_update(isc_sha512_t *context, const isc_uint8_t *data, size_t len) {
+       if (len == 0U) {
+               /* Calling with no data is valid - we do nothing */
+               return;
+       }
+
+       /* Sanity check: */
+       REQUIRE(context != (isc_sha512_t *)0 && data != (isc_uint8_t*)0);
+
+       EVP_DigestUpdate(context, (const void *) data, len);
+}
+
+void isc_sha512_final(isc_uint8_t digest[], isc_sha512_t *context) {
+       /* Sanity check: */
+       REQUIRE(context != (isc_sha512_t *)0);
+
+       /* If no digest buffer is passed, we don't bother doing this: */
+       if (digest != (isc_uint8_t*)0) {
+               EVP_DigestFinal(context, digest, NULL);
+       } else {
+               EVP_MD_CTX_cleanup(context);
+       }
+}
+
+void
+isc_sha384_init(isc_sha384_t *context) {
+       if (context == (isc_sha384_t *)0) {
+               return;
+       }
+       EVP_DigestInit(context, EVP_sha384());
+}
+
+void
+isc_sha384_invalidate(isc_sha384_t *context) {
+       EVP_MD_CTX_cleanup(context);
+}
+
+void
+isc_sha384_update(isc_sha384_t *context, const isc_uint8_t* data, size_t len) {
+       if (len == 0U) {
+               /* Calling with no data is valid - we do nothing */
+               return;
+       }
+
+       /* Sanity check: */
+       REQUIRE(context != (isc_sha512_t *)0 && data != (isc_uint8_t*)0);
+
+       EVP_DigestUpdate(context, (const void *) data, len);
+}
+
+void
+isc_sha384_final(isc_uint8_t digest[], isc_sha384_t *context) {
+       /* Sanity check: */
+       REQUIRE(context != (isc_sha384_t *)0);
+
+       /* If no digest buffer is passed, we don't bother doing this: */
+       if (digest != (isc_uint8_t*)0) {
+               EVP_DigestFinal(context, digest, NULL);
+       } else {
+               EVP_MD_CTX_cleanup(context);
+       }
+}
+
+#else
+
 /*
  * UNROLLED TRANSFORM LOOP NOTE:
  * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
@@ -394,13 +553,6 @@ static const isc_uint64_t sha512_initial_hash_value[8] = {
 };
 #endif
 
-/*
- * Constant used by SHA256/384/512_End() functions for converting the
- * digest to a readable hexadecimal character string:
- */
-static const char *sha2_hex_digits = "0123456789abcdef";
-
-
 
 /*** SHA-224: *********************************************************/
 void
@@ -414,6 +566,11 @@ isc_sha224_init(isc_sha224_t *context) {
        context->bitcount = 0;
 }
 
+void
+isc_sha224_invalidate(isc_sha224_t *context) {
+       memset(context, 0, sizeof(isc_sha224_t));
+}
+
 void
 isc_sha224_update(isc_sha224_t *context, const isc_uint8_t* data, size_t len) {
        isc_sha256_update((isc_sha256_t *)context, data, len);
@@ -427,41 +584,6 @@ isc_sha224_final(isc_uint8_t digest[], isc_sha224_t *context) {
        memset(sha256_digest, 0, ISC_SHA256_DIGESTLENGTH);
 }
 
-char *
-isc_sha224_end(isc_sha224_t *context, char buffer[]) {
-       isc_uint8_t     digest[ISC_SHA224_DIGESTLENGTH], *d = digest;
-       unsigned int    i;
-
-       /* Sanity check: */
-       REQUIRE(context != (isc_sha224_t *)0);
-
-       if (buffer != (char*)0) {
-               isc_sha224_final(digest, context);
-
-               for (i = 0; i < ISC_SHA224_DIGESTLENGTH; i++) {
-                       *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
-                       *buffer++ = sha2_hex_digits[*d & 0x0f];
-                       d++;
-               }
-               *buffer = (char)0;
-       } else {
-               memset(context, 0, sizeof(context));
-       }
-       memset(digest, 0, ISC_SHA224_DIGESTLENGTH);
-       return buffer;
-}
-
-char*
-isc_sha224_data(const isc_uint8_t *data, size_t len,
-               char digest[ISC_SHA224_DIGESTSTRINGLENGTH])
-{
-       isc_sha224_t context;
-
-       isc_sha224_init(&context);
-       isc_sha224_update(&context, data, len);
-       return (isc_sha224_end(&context, digest));
-}
-
 /*** SHA-256: *********************************************************/
 void
 isc_sha256_init(isc_sha256_t *context) {
@@ -474,6 +596,11 @@ isc_sha256_init(isc_sha256_t *context) {
        context->bitcount = 0;
 }
 
+void
+isc_sha256_invalidate(isc_sha256_t *context) {
+       memset(context, 0, sizeof(isc_sha256_t));
+}
+
 #ifdef ISC_SHA2_UNROLL_TRANSFORM
 
 /* Unrolled SHA-256 round macros: */
@@ -565,6 +692,9 @@ void isc_sha256_transform(isc_sha256_t *context, const isc_uint32_t* data) {
 
        /* Clean up */
        a = b = c = d = e = f = g = h = T1 = 0;
+       /* Avoid compiler warnings */
+       POST(a); POST(b); POST(c); POST(d); POST(e); POST(f);
+       POST(g); POST(h); POST(T1);
 }
 
 #else /* ISC_SHA2_UNROLL_TRANSFORM */
@@ -646,6 +776,9 @@ isc_sha256_transform(isc_sha256_t *context, const isc_uint32_t* data) {
 
        /* Clean up */
        a = b = c = d = e = f = g = h = T1 = T2 = 0;
+       /* Avoid compiler warnings */
+       POST(a); POST(b); POST(c); POST(d); POST(e); POST(f);
+       POST(g); POST(h); POST(T1); POST(T2);
 }
 
 #endif /* ISC_SHA2_UNROLL_TRANSFORM */
@@ -682,6 +815,8 @@ isc_sha256_update(isc_sha256_t *context, const isc_uint8_t *data, size_t len) {
                        context->bitcount += len << 3;
                        /* Clean up: */
                        usedspace = freespace = 0;
+                       /* Avoid compiler warnings: */
+                       POST(usedspace); POST(freespace);
                        return;
                }
        }
@@ -700,6 +835,8 @@ isc_sha256_update(isc_sha256_t *context, const isc_uint8_t *data, size_t len) {
        }
        /* Clean up: */
        usedspace = freespace = 0;
+       /* Avoid compiler warnings: */
+       POST(usedspace); POST(freespace);
 }
 
 void
@@ -768,46 +905,11 @@ isc_sha256_final(isc_uint8_t digest[], isc_sha256_t *context) {
        }
 
        /* Clean up state data: */
-       memset(context, 0, sizeof(context));
+       memset(context, 0, sizeof(*context));
        usedspace = 0;
+       POST(usedspace);
 }
 
-char *
-isc_sha256_end(isc_sha256_t *context, char buffer[]) {
-       isc_uint8_t     digest[ISC_SHA256_DIGESTLENGTH], *d = digest;
-       unsigned int    i;
-
-       /* Sanity check: */
-       REQUIRE(context != (isc_sha256_t *)0);
-
-       if (buffer != (char*)0) {
-               isc_sha256_final(digest, context);
-
-               for (i = 0; i < ISC_SHA256_DIGESTLENGTH; i++) {
-                       *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
-                       *buffer++ = sha2_hex_digits[*d & 0x0f];
-                       d++;
-               }
-               *buffer = (char)0;
-       } else {
-               memset(context, 0, sizeof(context));
-       }
-       memset(digest, 0, ISC_SHA256_DIGESTLENGTH);
-       return buffer;
-}
-
-char *
-isc_sha256_data(const isc_uint8_t* data, size_t len,
-               char digest[ISC_SHA256_DIGESTSTRINGLENGTH])
-{
-       isc_sha256_t context;
-
-       isc_sha256_init(&context);
-       isc_sha256_update(&context, data, len);
-       return (isc_sha256_end(&context, digest));
-}
-
-
 /*** SHA-512: *********************************************************/
 void
 isc_sha512_init(isc_sha512_t *context) {
@@ -820,6 +922,11 @@ isc_sha512_init(isc_sha512_t *context) {
        context->bitcount[0] = context->bitcount[1] =  0;
 }
 
+void
+isc_sha512_invalidate(isc_sha512_t *context) {
+       memset(context, 0, sizeof(isc_sha512_t));
+}
+
 #ifdef ISC_SHA2_UNROLL_TRANSFORM
 
 /* Unrolled SHA-512 round macros: */
@@ -907,6 +1014,9 @@ void isc_sha512_transform(isc_sha512_t *context, const isc_uint64_t* data) {
 
        /* Clean up */
        a = b = c = d = e = f = g = h = T1 = 0;
+       /* Avoid compiler warnings */
+       POST(a); POST(b); POST(c); POST(d); POST(e); POST(f);
+       POST(g); POST(h); POST(T1);
 }
 
 #else /* ISC_SHA2_UNROLL_TRANSFORM */
@@ -986,6 +1096,9 @@ isc_sha512_transform(isc_sha512_t *context, const isc_uint64_t* data) {
 
        /* Clean up */
        a = b = c = d = e = f = g = h = T1 = T2 = 0;
+       /* Avoid compiler warnings */
+       POST(a); POST(b); POST(c); POST(d); POST(e); POST(f);
+       POST(g); POST(h); POST(T1); POST(T2);
 }
 
 #endif /* ISC_SHA2_UNROLL_TRANSFORM */
@@ -1021,6 +1134,8 @@ void isc_sha512_update(isc_sha512_t *context, const isc_uint8_t *data, size_t le
                        ADDINC128(context->bitcount, len << 3);
                        /* Clean up: */
                        usedspace = freespace = 0;
+                       /* Avoid compiler warnings: */
+                       POST(usedspace); POST(freespace);
                        return;
                }
        }
@@ -1039,6 +1154,8 @@ void isc_sha512_update(isc_sha512_t *context, const isc_uint8_t *data, size_t le
        }
        /* Clean up: */
        usedspace = freespace = 0;
+       /* Avoid compiler warnings: */
+       POST(usedspace); POST(freespace);
 }
 
 void isc_sha512_last(isc_sha512_t *context) {
@@ -1112,42 +1229,7 @@ void isc_sha512_final(isc_uint8_t digest[], isc_sha512_t *context) {
        }
 
        /* Zero out state data */
-       memset(context, 0, sizeof(context));
-}
-
-char *
-isc_sha512_end(isc_sha512_t *context, char buffer[]) {
-       isc_uint8_t     digest[ISC_SHA512_DIGESTLENGTH], *d = digest;
-       unsigned int    i;
-
-       /* Sanity check: */
-       REQUIRE(context != (isc_sha512_t *)0);
-
-       if (buffer != (char*)0) {
-               isc_sha512_final(digest, context);
-
-               for (i = 0; i < ISC_SHA512_DIGESTLENGTH; i++) {
-                       *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
-                       *buffer++ = sha2_hex_digits[*d & 0x0f];
-                       d++;
-               }
-               *buffer = (char)0;
-       } else {
-               memset(context, 0, sizeof(context));
-       }
-       memset(digest, 0, ISC_SHA512_DIGESTLENGTH);
-       return buffer;
-}
-
-char *
-isc_sha512_data(const isc_uint8_t *data, size_t len,
-               char digest[ISC_SHA512_DIGESTSTRINGLENGTH])
-{
-       isc_sha512_t    context;
-
-       isc_sha512_init(&context);
-       isc_sha512_update(&context, data, len);
-       return (isc_sha512_end(&context, digest));
+       memset(context, 0, sizeof(*context));
 }
 
 
@@ -1163,6 +1245,11 @@ isc_sha384_init(isc_sha384_t *context) {
        context->bitcount[0] = context->bitcount[1] = 0;
 }
 
+void
+isc_sha384_invalidate(isc_sha384_t *context) {
+       memset(context, 0, sizeof(isc_sha384_t));
+}
+
 void
 isc_sha384_update(isc_sha384_t *context, const isc_uint8_t* data, size_t len) {
        isc_sha512_update((isc_sha512_t *)context, data, len);
@@ -1195,7 +1282,131 @@ isc_sha384_final(isc_uint8_t digest[], isc_sha384_t *context) {
        }
 
        /* Zero out state data */
-       memset(context, 0, sizeof(context));
+       memset(context, 0, sizeof(*context));
+}
+#endif /* !ISC_PLATFORM_OPENSSLHASH */
+
+/*
+ * Constant used by SHA256/384/512_End() functions for converting the
+ * digest to a readable hexadecimal character string:
+ */
+static const char *sha2_hex_digits = "0123456789abcdef";
+
+char *
+isc_sha224_end(isc_sha224_t *context, char buffer[]) {
+       isc_uint8_t     digest[ISC_SHA224_DIGESTLENGTH], *d = digest;
+       unsigned int    i;
+
+       /* Sanity check: */
+       REQUIRE(context != (isc_sha224_t *)0);
+
+       if (buffer != (char*)0) {
+               isc_sha224_final(digest, context);
+
+               for (i = 0; i < ISC_SHA224_DIGESTLENGTH; i++) {
+                       *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+                       *buffer++ = sha2_hex_digits[*d & 0x0f];
+                       d++;
+               }
+               *buffer = (char)0;
+       } else {
+#ifdef ISC_PLATFORM_OPENSSLHASH
+               EVP_MD_CTX_cleanup(context);
+#else
+               memset(context, 0, sizeof(*context));
+#endif
+       }
+       memset(digest, 0, ISC_SHA224_DIGESTLENGTH);
+       return buffer;
+}
+
+char *
+isc_sha224_data(const isc_uint8_t *data, size_t len,
+               char digest[ISC_SHA224_DIGESTSTRINGLENGTH])
+{
+       isc_sha224_t context;
+
+       isc_sha224_init(&context);
+       isc_sha224_update(&context, data, len);
+       return (isc_sha224_end(&context, digest));
+}
+
+char *
+isc_sha256_end(isc_sha256_t *context, char buffer[]) {
+       isc_uint8_t     digest[ISC_SHA256_DIGESTLENGTH], *d = digest;
+       unsigned int    i;
+
+       /* Sanity check: */
+       REQUIRE(context != (isc_sha256_t *)0);
+
+       if (buffer != (char*)0) {
+               isc_sha256_final(digest, context);
+
+               for (i = 0; i < ISC_SHA256_DIGESTLENGTH; i++) {
+                       *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+                       *buffer++ = sha2_hex_digits[*d & 0x0f];
+                       d++;
+               }
+               *buffer = (char)0;
+       } else {
+#ifdef ISC_PLATFORM_OPENSSLHASH
+               EVP_MD_CTX_cleanup(context);
+#else
+               memset(context, 0, sizeof(*context));
+#endif
+       }
+       memset(digest, 0, ISC_SHA256_DIGESTLENGTH);
+       return buffer;
+}
+
+char *
+isc_sha256_data(const isc_uint8_t* data, size_t len,
+               char digest[ISC_SHA256_DIGESTSTRINGLENGTH])
+{
+       isc_sha256_t context;
+
+       isc_sha256_init(&context);
+       isc_sha256_update(&context, data, len);
+       return (isc_sha256_end(&context, digest));
+}
+
+char *
+isc_sha512_end(isc_sha512_t *context, char buffer[]) {
+       isc_uint8_t     digest[ISC_SHA512_DIGESTLENGTH], *d = digest;
+       unsigned int    i;
+
+       /* Sanity check: */
+       REQUIRE(context != (isc_sha512_t *)0);
+
+       if (buffer != (char*)0) {
+               isc_sha512_final(digest, context);
+
+               for (i = 0; i < ISC_SHA512_DIGESTLENGTH; i++) {
+                       *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+                       *buffer++ = sha2_hex_digits[*d & 0x0f];
+                       d++;
+               }
+               *buffer = (char)0;
+       } else {
+#ifdef ISC_PLATFORM_OPENSSLHASH
+               EVP_MD_CTX_cleanup(context);
+#else
+               memset(context, 0, sizeof(*context));
+#endif
+       }
+       memset(digest, 0, ISC_SHA512_DIGESTLENGTH);
+       return buffer;
+}
+
+char *
+isc_sha512_data(const isc_uint8_t *data, size_t len,
+               char digest[ISC_SHA512_DIGESTSTRINGLENGTH])
+{
+       isc_sha512_t    context;
+
+       isc_sha512_init(&context);
+       isc_sha512_update(&context, data, len);
+       return (isc_sha512_end(&context, digest));
 }
 
 char *
@@ -1216,13 +1427,17 @@ isc_sha384_end(isc_sha384_t *context, char buffer[]) {
                }
                *buffer = (char)0;
        } else {
-               memset(context, 0, sizeof(context));
+#ifdef ISC_PLATFORM_OPENSSLHASH
+               EVP_MD_CTX_cleanup(context);
+#else
+               memset(context, 0, sizeof(*context));
+#endif
        }
        memset(digest, 0, ISC_SHA384_DIGESTLENGTH);
        return buffer;
 }
 
-char*
+char *
 isc_sha384_data(const isc_uint8_t *data, size_t len,
                char digest[ISC_SHA384_DIGESTSTRINGLENGTH])
 {
index 62975df34ddf0ecf4979b679898abb5701f22bf9..7b43b8f31bb86f38f3b31d84a036a4bff87ea120 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2010-2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: sockaddr.c,v 1.70 2007/06/19 23:47:17 tbox Exp $ */
+/* $Id$ */
 
 /*! \file */
 
@@ -182,6 +182,9 @@ isc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size) {
        isc_result_t result;
        isc_buffer_t buf;
 
+       if (size == 0U)
+               return;
+
        isc_buffer_init(&buf, array, size);
        result = isc_sockaddr_totext(sa, &buf);
        if (result != ISC_R_SUCCESS) {
@@ -390,8 +393,8 @@ isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na,
 #endif
                sockaddr->type.sin6.sin6_port = htons(port);
                break;
-        default:
-                INSIST(0);
+       default:
+               INSIST(0);
        }
        ISC_LINK_INIT(sockaddr, link);
 }
diff --git a/lib/isc/socket_api.c b/lib/isc/socket_api.c
new file mode 100644 (file)
index 0000000..3394ce0
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include <config.h>
+
+#include <isc/app.h>
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/socket.h>
+#include <isc/util.h>
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_socketmgrcreatefunc_t socketmgr_createfunc = NULL;
+
+static void
+initialize(void) {
+       RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_socket_register(isc_socketmgrcreatefunc_t createfunc) {
+       isc_result_t result = ISC_R_SUCCESS;
+
+       RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+       LOCK(&createlock);
+       if (socketmgr_createfunc == NULL)
+               socketmgr_createfunc = createfunc;
+       else
+               result = ISC_R_EXISTS;
+       UNLOCK(&createlock);
+
+       return (result);
+}
+
+isc_result_t
+isc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+                         isc_socketmgr_t **managerp)
+{
+       isc_result_t result;
+
+       LOCK(&createlock);
+
+       REQUIRE(socketmgr_createfunc != NULL);
+       result = (*socketmgr_createfunc)(mctx, managerp);
+
+       UNLOCK(&createlock);
+
+       if (result == ISC_R_SUCCESS)
+               isc_appctx_setsocketmgr(actx, *managerp);
+
+       return (result);
+}
+
+isc_result_t
+isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
+       isc_result_t result;
+
+       LOCK(&createlock);
+
+       REQUIRE(socketmgr_createfunc != NULL);
+       result = (*socketmgr_createfunc)(mctx, managerp);
+
+       UNLOCK(&createlock);
+
+       return (result);
+}
+
+void
+isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
+       REQUIRE(managerp != NULL && ISCAPI_SOCKETMGR_VALID(*managerp));
+
+       (*managerp)->methods->destroy(managerp);
+
+       ENSURE(*managerp == NULL);
+}
+
+isc_result_t
+isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+                 isc_socket_t **socketp)
+{
+       REQUIRE(ISCAPI_SOCKETMGR_VALID(manager));
+
+       return (manager->methods->socketcreate(manager, pf, type, socketp));
+}
+
+void
+isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
+       REQUIRE(ISCAPI_SOCKET_VALID(sock));
+       REQUIRE(socketp != NULL && *socketp == NULL);
+
+       sock->methods->attach(sock, socketp);
+
+       ENSURE(*socketp == sock);
+}
+
+void
+isc_socket_detach(isc_socket_t **socketp) {
+       REQUIRE(socketp != NULL && ISCAPI_SOCKET_VALID(*socketp));
+
+       (*socketp)->methods->detach(socketp);
+
+       ENSURE(*socketp == NULL);
+}
+
+isc_result_t
+isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+               unsigned int options)
+{
+       REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+       return (sock->methods->bind(sock, sockaddr, options));
+}
+
+isc_result_t
+isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, isc_task_t *task,
+                 isc_taskaction_t action, const void *arg,
+                 isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+{
+       REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+       return (sock->methods->sendto(sock, region, task, action, arg, address,
+                                     pktinfo));
+}
+
+isc_result_t
+isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, isc_task_t *task,
+                  isc_taskaction_t action, const void *arg)
+{
+       REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+       return (sock->methods->connect(sock, addr, task, action, arg));
+}
+
+isc_result_t
+isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
+               isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+       REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+       return (sock->methods->recv(sock, region, minimum, task, action, arg));
+}
+
+void
+isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
+       REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+       sock->methods->cancel(sock, task, how);
+}
+
+isc_result_t
+isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+       REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+       return (sock->methods->getsockname(sock, addressp));
+}
+
+void
+isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
+       REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+       sock->methods->ipv6only(sock, yes);
+}
+
+isc_sockettype_t
+isc_socket_gettype(isc_socket_t *sock) {
+       REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+       return (sock->methods->gettype(sock));
+}
+
+void
+isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) {
+       REQUIRE(ISCAPI_SOCKET_VALID(socket));
+
+       UNUSED(socket);         /* in case REQUIRE() is empty */
+       UNUSED(name);
+       UNUSED(tag);
+}
+
+isc_result_t
+isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
+                        isc_sockfdwatch_t callback, void *cbarg,
+                        isc_task_t *task, isc_socket_t **socketp)
+{
+       REQUIRE(ISCAPI_SOCKETMGR_VALID(manager));
+
+       return (manager->methods->fdwatchcreate(manager, fd, flags,
+                                               callback, cbarg, task,
+                                               socketp));
+}
+
+isc_result_t
+isc_socket_fdwatchpoke(isc_socket_t *sock, int flags)
+{
+       REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+       return(sock->methods->fdwatchpoke(sock, flags));
+}
+
+isc_result_t
+isc_socket_dup(isc_socket_t *sock, isc_socket_t **socketp) {
+       REQUIRE(ISCAPI_SOCKET_VALID(sock));
+       REQUIRE(socketp != NULL && *socketp == NULL);
+
+       return(sock->methods->dup(sock, socketp));
+}
+
+int
+isc_socket_getfd(isc_socket_t *sock) {
+       REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+       return(sock->methods->getfd(sock));
+}
index 9e4e089b527d7655985b2741c913f3c441eeb081..8b624b2d478de9a74043416e40f9aa9d65432007 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2009, 2012  Internet Systems Consortium, Inc. ("ISC")
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -14,7 +14,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: stats.c,v 1.3.6.2 2009/01/29 23:47:44 tbox Exp $ */
+/* $Id$ */
 
 /*! \file */
 
index b9c43e7bb150d03ca488bea71daac2a50a02426e..cba517c568f96d58cbf58b735e7cf4ba9a8fb6c6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: string.c,v 1.20 2007/06/19 23:47:17 tbox Exp $ */
+/* $Id$ */
 
 /*! \file */
 
@@ -165,14 +165,15 @@ isc_string_printf(char *target, size_t size, const char *format, ...) {
 }
 
 void
-isc_string_printf_truncate(char *target, size_t size, const char *format, ...) {
+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);
+       /* check return code? */
+       (void)vsnprintf(target, size, format, args);
        va_end(args);
 
        ENSURE(strlen(target) < size);
index 9f8e798df368ba9e8377842ae1004308a5d3bd4d..d4c1dccf0ad90fc6c38f4946670a8733a8853fb0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1996-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: symtab.c,v 1.30 2007/06/19 23:47:17 tbox Exp $ */
+/* $Id$ */
 
 /*! \file */
 
@@ -46,6 +46,8 @@ struct isc_symtab {
        unsigned int                    magic;
        isc_mem_t *                     mctx;
        unsigned int                    size;
+       unsigned int                    count;
+       unsigned int                    maxload;
        eltlist_t *                     table;
        isc_symtabaction_t              undefine_action;
        void *                          undefine_arg;
@@ -79,6 +81,8 @@ isc_symtab_create(isc_mem_t *mctx, unsigned int size,
                INIT_LIST(symtab->table[i]);
        symtab->mctx = mctx;
        symtab->size = size;
+       symtab->count = 0;
+       symtab->maxload = size * 3 / 4;
        symtab->undefine_action = undefine_action;
        symtab->undefine_arg = undefine_arg;
        symtab->case_sensitive = case_sensitive;
@@ -181,6 +185,46 @@ isc_symtab_lookup(isc_symtab_t *symtab, const char *key, unsigned int type,
        return (ISC_R_SUCCESS);
 }
 
+static void
+grow_table(isc_symtab_t *symtab) {
+       eltlist_t *newtable;
+       unsigned int i, newsize, newmax;
+
+       REQUIRE(symtab != NULL);
+
+       newsize = symtab->size * 2;
+       newmax = newsize * 3 / 4;
+       INSIST(newsize > 0U && newmax > 0U);
+
+       newtable = isc_mem_get(symtab->mctx, newsize * sizeof(eltlist_t));
+       if (newtable == NULL)
+               return;
+
+       for (i = 0; i < newsize; i++)
+               INIT_LIST(newtable[i]);
+
+       for (i = 0; i < symtab->size; i++) {
+               elt_t *elt, *nelt;
+
+               for (elt = HEAD(symtab->table[i]); elt != NULL; elt = nelt) {
+                       unsigned int hv;
+
+                       nelt = NEXT(elt, link);
+
+                       UNLINK(symtab->table[i], elt, link);
+                       hv = hash(elt->key, symtab->case_sensitive);
+                       APPEND(newtable[hv % newsize], elt, link);
+               }
+       }
+
+       isc_mem_put(symtab->mctx, symtab->table,
+                   symtab->size * sizeof(eltlist_t));
+
+       symtab->table = newtable;
+       symtab->size = newsize;
+       symtab->maxload = newmax;
+}
+
 isc_result_t
 isc_symtab_define(isc_symtab_t *symtab, const char *key, unsigned int type,
                  isc_symvalue_t value, isc_symexists_t exists_policy)
@@ -208,6 +252,7 @@ isc_symtab_define(isc_symtab_t *symtab, const char *key, unsigned int type,
                if (elt == NULL)
                        return (ISC_R_NOMEMORY);
                ISC_LINK_INIT(elt, link);
+               symtab->count++;
        }
 
        /*
@@ -226,6 +271,9 @@ isc_symtab_define(isc_symtab_t *symtab, const char *key, unsigned int type,
         */
        PREPEND(symtab->table[bucket], elt, link);
 
+       if (symtab->count > symtab->maxload)
+               grow_table(symtab);
+
        return (ISC_R_SUCCESS);
 }
 
@@ -247,6 +295,7 @@ isc_symtab_undefine(isc_symtab_t *symtab, const char *key, unsigned int type) {
                                          elt->value, symtab->undefine_arg);
        UNLINK(symtab->table[bucket], elt, link);
        isc_mem_put(symtab->mctx, elt, sizeof(*elt));
+       symtab->count--;
 
        return (ISC_R_SUCCESS);
 }
index a630173d940556dabd3ae01472de8d5fc66e4ae0..227b29596c075deb02135cfb926497d828eba2c0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: task.c,v 1.107 2008/03/27 23:46:57 tbox Exp $ */
+/* $Id$ */
 
 /*! \file
  * \author Principal Author: Bob Halley
 #include <isc/util.h>
 #include <isc/xml.h>
 
-#ifndef ISC_PLATFORM_USETHREADS
+#ifdef OPENSSL_LEAKS
+#include <openssl/err.h>
+#endif
+
+/*%
+ * For BIND9 internal applications:
+ * when built with threads we use multiple worker threads shared by the whole
+ * application.
+ * when built without threads we share a single global task manager and use
+ * an integrated event loop for socket, timer, and other generic task events.
+ * For generic library:
+ * we don't use either of them: an application can have multiple task managers
+ * whether or not it's threaded, and if the application is threaded each thread
+ * is expected to have a separate manager; no "worker threads" are shared by
+ * the application threads.
+ */
+#ifdef BIND9
+#ifdef ISC_PLATFORM_USETHREADS
+#define USE_WORKER_THREADS
+#else
+#define USE_SHARED_MANAGER
+#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* BIND9 */
+
 #include "task_p.h"
-#endif /* ISC_PLATFORM_USETHREADS */
 
 #ifdef ISC_TASK_TRACE
 #define XTRACE(m)              fprintf(stderr, "task %p thread %lu: %s\n", \
@@ -66,7 +88,7 @@ typedef enum {
        task_state_done
 } task_state_t;
 
-#ifdef HAVE_LIBXML2
+#if defined(HAVE_LIBXML2) && defined(BIND9)
 static const char *statenames[] = {
        "idle", "ready", "running", "done",
 };
@@ -75,10 +97,13 @@ static const char *statenames[] = {
 #define TASK_MAGIC                     ISC_MAGIC('T', 'A', 'S', 'K')
 #define VALID_TASK(t)                  ISC_MAGIC_VALID(t, TASK_MAGIC)
 
-struct isc_task {
+typedef struct isc__task isc__task_t;
+typedef struct isc__taskmgr isc__taskmgr_t;
+
+struct isc__task {
        /* Not locked. */
-       unsigned int                    magic;
-       isc_taskmgr_t *                 manager;
+       isc_task_t                      common;
+       isc__taskmgr_t *                manager;
        isc_mutex_t                     lock;
        /* Locked by task lock. */
        task_state_t                    state;
@@ -91,11 +116,13 @@ struct isc_task {
        char                            name[16];
        void *                          tag;
        /* Locked by task manager lock. */
-       LINK(isc_task_t)                link;
-       LINK(isc_task_t)                ready_link;
+       LINK(isc__task_t)               link;
+       LINK(isc__task_t)               ready_link;
+       LINK(isc__task_t)               ready_priority_link;
 };
 
 #define TASK_F_SHUTTINGDOWN            0x01
+#define TASK_F_PRIVILEGED              0x02
 
 #define TASK_SHUTTINGDOWN(t)           (((t)->flags & TASK_F_SHUTTINGDOWN) \
                                         != 0)
@@ -103,9 +130,11 @@ struct isc_task {
 #define TASK_MANAGER_MAGIC             ISC_MAGIC('T', 'S', 'K', 'M')
 #define VALID_MANAGER(m)               ISC_MAGIC_VALID(m, TASK_MANAGER_MAGIC)
 
-struct isc_taskmgr {
+typedef ISC_LIST(isc__task_t)  isc__tasklist_t;
+
+struct isc__taskmgr {
        /* Not locked. */
-       unsigned int                    magic;
+       isc_taskmgr_t                   common;
        isc_mem_t *                     mctx;
        isc_mutex_t                     lock;
 #ifdef ISC_PLATFORM_USETHREADS
@@ -114,16 +143,20 @@ struct isc_taskmgr {
 #endif /* ISC_PLATFORM_USETHREADS */
        /* Locked by task manager lock. */
        unsigned int                    default_quantum;
-       LIST(isc_task_t)                tasks;
-       isc_tasklist_t                  ready_tasks;
+       LIST(isc__task_t)               tasks;
+       isc__tasklist_t                 ready_tasks;
+       isc__tasklist_t                 ready_priority_tasks;
+       isc_taskmgrmode_t               mode;
 #ifdef ISC_PLATFORM_USETHREADS
        isc_condition_t                 work_available;
        isc_condition_t                 exclusive_granted;
+       isc_condition_t                 paused;
 #endif /* ISC_PLATFORM_USETHREADS */
        unsigned int                    tasks_running;
+       isc_boolean_t                   pause_requested;
        isc_boolean_t                   exclusive_requested;
        isc_boolean_t                   exiting;
-#ifndef ISC_PLATFORM_USETHREADS
+#ifdef USE_SHARED_MANAGER
        unsigned int                    refs;
 #endif /* ISC_PLATFORM_USETHREADS */
 };
@@ -132,17 +165,137 @@ struct isc_taskmgr {
 #define DEFAULT_DEFAULT_QUANTUM                5
 #define FINISHED(m)                    ((m)->exiting && EMPTY((m)->tasks))
 
-#ifndef ISC_PLATFORM_USETHREADS
-static isc_taskmgr_t *taskmgr = NULL;
-#endif /* ISC_PLATFORM_USETHREADS */
+#ifdef USE_SHARED_MANAGER
+static isc__taskmgr_t *taskmgr = NULL;
+#endif /* USE_SHARED_MANAGER */
+
+/*%
+ * The following can be either static or public, depending on build environment.
+ */
+
+#ifdef BIND9
+#define ISC_TASKFUNC_SCOPE
+#else
+#define ISC_TASKFUNC_SCOPE static
+#endif
+
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_create(isc_taskmgr_t *manager0, unsigned int quantum,
+                isc_task_t **taskp);
+ISC_TASKFUNC_SCOPE void
+isc__task_attach(isc_task_t *source0, isc_task_t **targetp);
+ISC_TASKFUNC_SCOPE void
+isc__task_detach(isc_task_t **taskp);
+ISC_TASKFUNC_SCOPE void
+isc__task_send(isc_task_t *task0, isc_event_t **eventp);
+ISC_TASKFUNC_SCOPE void
+isc__task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp);
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_purgerange(isc_task_t *task0, void *sender, isc_eventtype_t first,
+                    isc_eventtype_t last, void *tag);
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
+               void *tag);
+ISC_TASKFUNC_SCOPE isc_boolean_t
+isc__task_purgeevent(isc_task_t *task0, isc_event_t *event);
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
+                     isc_eventtype_t last, void *tag,
+                     isc_eventlist_t *events);
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
+                void *tag, isc_eventlist_t *events);
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_onshutdown(isc_task_t *task0, isc_taskaction_t action,
+                    const void *arg);
+ISC_TASKFUNC_SCOPE void
+isc__task_shutdown(isc_task_t *task0);
+ISC_TASKFUNC_SCOPE void
+isc__task_destroy(isc_task_t **taskp);
+ISC_TASKFUNC_SCOPE void
+isc__task_setname(isc_task_t *task0, const char *name, void *tag);
+ISC_TASKFUNC_SCOPE const char *
+isc__task_getname(isc_task_t *task0);
+ISC_TASKFUNC_SCOPE void *
+isc__task_gettag(isc_task_t *task0);
+ISC_TASKFUNC_SCOPE void
+isc__task_getcurrenttime(isc_task_t *task0, isc_stdtime_t *t);
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers,
+                   unsigned int default_quantum, isc_taskmgr_t **managerp);
+ISC_TASKFUNC_SCOPE void
+isc__taskmgr_destroy(isc_taskmgr_t **managerp);
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_beginexclusive(isc_task_t *task);
+ISC_TASKFUNC_SCOPE void
+isc__task_endexclusive(isc_task_t *task0);
+ISC_TASKFUNC_SCOPE void
+isc__task_setprivilege(isc_task_t *task0, isc_boolean_t priv);
+ISC_TASKFUNC_SCOPE isc_boolean_t
+isc__task_privilege(isc_task_t *task0);
+ISC_TASKFUNC_SCOPE void
+isc__taskmgr_setmode(isc_taskmgr_t *manager0, isc_taskmgrmode_t mode);
+ISC_TASKFUNC_SCOPE isc_taskmgrmode_t
+isc__taskmgr_mode(isc_taskmgr_t *manager0);
+
+static inline isc_boolean_t
+empty_readyq(isc__taskmgr_t *manager);
+
+static inline isc__task_t *
+pop_readyq(isc__taskmgr_t *manager);
+
+static inline void
+push_readyq(isc__taskmgr_t *manager, isc__task_t *task);
+
+static struct isc__taskmethods {
+       isc_taskmethods_t methods;
+
+       /*%
+        * The following are defined just for avoiding unused static functions.
+        */
+#ifndef BIND9
+       void *purgeevent, *unsendrange, *getname, *gettag, *getcurrenttime;
+#endif
+} taskmethods = {
+       {
+               isc__task_attach,
+               isc__task_detach,
+               isc__task_destroy,
+               isc__task_send,
+               isc__task_sendanddetach,
+               isc__task_unsend,
+               isc__task_onshutdown,
+               isc__task_shutdown,
+               isc__task_setname,
+               isc__task_purge,
+               isc__task_purgerange,
+               isc__task_beginexclusive,
+               isc__task_endexclusive,
+               isc__task_setprivilege,
+               isc__task_privilege
+       }
+#ifndef BIND9
+       ,
+       (void *)isc__task_purgeevent, (void *)isc__task_unsendrange,
+       (void *)isc__task_getname, (void *)isc__task_gettag,
+       (void *)isc__task_getcurrenttime
+#endif
+};
+
+static isc_taskmgrmethods_t taskmgrmethods = {
+       isc__taskmgr_destroy,
+       isc__taskmgr_setmode,
+       isc__taskmgr_mode,
+       isc__task_create
+};
 
 /***
  *** Tasks.
  ***/
 
 static void
-task_finished(isc_task_t *task) {
-       isc_taskmgr_t *manager = task->manager;
+task_finished(isc__task_t *task) {
+       isc__taskmgr_t *manager = task->manager;
 
        REQUIRE(EMPTY(task->events));
        REQUIRE(EMPTY(task->on_shutdown));
@@ -153,7 +306,7 @@ task_finished(isc_task_t *task) {
 
        LOCK(&manager->lock);
        UNLINK(manager->tasks, task, link);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
        if (FINISHED(manager)) {
                /*
                 * All tasks have completed and the
@@ -163,19 +316,21 @@ task_finished(isc_task_t *task) {
                 */
                BROADCAST(&manager->work_available);
        }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
        UNLOCK(&manager->lock);
 
        DESTROYLOCK(&task->lock);
-       task->magic = 0;
+       task->common.impmagic = 0;
+       task->common.magic = 0;
        isc_mem_put(manager->mctx, task, sizeof(*task));
 }
 
-isc_result_t
-isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
-               isc_task_t **taskp)
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_create(isc_taskmgr_t *manager0, unsigned int quantum,
+                isc_task_t **taskp)
 {
-       isc_task_t *task;
+       isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
+       isc__task_t *task;
        isc_boolean_t exiting;
        isc_result_t result;
 
@@ -203,6 +358,7 @@ isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
        task->tag = NULL;
        INIT_LINK(task, link);
        INIT_LINK(task, ready_link);
+       INIT_LINK(task, ready_priority_link);
 
        exiting = ISC_FALSE;
        LOCK(&manager->lock);
@@ -220,14 +376,17 @@ isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
                return (ISC_R_SHUTTINGDOWN);
        }
 
-       task->magic = TASK_MAGIC;
-       *taskp = task;
+       task->common.methods = (isc_taskmethods_t *)&taskmethods;
+       task->common.magic = ISCAPI_TASK_MAGIC;
+       task->common.impmagic = TASK_MAGIC;
+       *taskp = (isc_task_t *)task;
 
        return (ISC_R_SUCCESS);
 }
 
-void
-isc_task_attach(isc_task_t *source, isc_task_t **targetp) {
+ISC_TASKFUNC_SCOPE void
+isc__task_attach(isc_task_t *source0, isc_task_t **targetp) {
+       isc__task_t *source = (isc__task_t *)source0;
 
        /*
         * Attach *targetp to source.
@@ -242,11 +401,11 @@ isc_task_attach(isc_task_t *source, isc_task_t **targetp) {
        source->references++;
        UNLOCK(&source->lock);
 
-       *targetp = source;
+       *targetp = (isc_task_t *)source;
 }
 
 static inline isc_boolean_t
-task_shutdown(isc_task_t *task) {
+task_shutdown(isc__task_t *task) {
        isc_boolean_t was_idle = ISC_FALSE;
        isc_event_t *event, *prev;
 
@@ -267,6 +426,7 @@ task_shutdown(isc_task_t *task) {
                }
                INSIST(task->state == task_state_ready ||
                       task->state == task_state_running);
+
                /*
                 * Note that we post shutdown events LIFO.
                 */
@@ -282,9 +442,17 @@ task_shutdown(isc_task_t *task) {
        return (was_idle);
 }
 
+/*
+ * Moves a task onto the appropriate run queue.
+ *
+ * Caller must NOT hold manager lock.
+ */
 static inline void
-task_ready(isc_task_t *task) {
-       isc_taskmgr_t *manager = task->manager;
+task_ready(isc__task_t *task) {
+       isc__taskmgr_t *manager = task->manager;
+#ifdef USE_WORKER_THREADS
+       isc_boolean_t has_privilege = isc__task_privilege((isc_task_t *) task);
+#endif /* USE_WORKER_THREADS */
 
        REQUIRE(VALID_MANAGER(manager));
        REQUIRE(task->state == task_state_ready);
@@ -292,17 +460,16 @@ task_ready(isc_task_t *task) {
        XTRACE("task_ready");
 
        LOCK(&manager->lock);
-
-       ENQUEUE(manager->ready_tasks, task, ready_link);
-#ifdef ISC_PLATFORM_USETHREADS
-       SIGNAL(&manager->work_available);
-#endif /* ISC_PLATFORM_USETHREADS */
-
+       push_readyq(manager, task);
+#ifdef USE_WORKER_THREADS
+       if (manager->mode == isc_taskmgrmode_normal || has_privilege)
+               SIGNAL(&manager->work_available);
+#endif /* USE_WORKER_THREADS */
        UNLOCK(&manager->lock);
 }
 
 static inline isc_boolean_t
-task_detach(isc_task_t *task) {
+task_detach(isc__task_t *task) {
 
        /*
         * Caller must be holding the task lock.
@@ -330,9 +497,9 @@ task_detach(isc_task_t *task) {
        return (ISC_FALSE);
 }
 
-void
-isc_task_detach(isc_task_t **taskp) {
-       isc_task_t *task;
+ISC_TASKFUNC_SCOPE void
+isc__task_detach(isc_task_t **taskp) {
+       isc__task_t *task;
        isc_boolean_t was_idle;
 
        /*
@@ -340,7 +507,7 @@ isc_task_detach(isc_task_t **taskp) {
         */
 
        REQUIRE(taskp != NULL);
-       task = *taskp;
+       task = (isc__task_t *)*taskp;
        REQUIRE(VALID_TASK(task));
 
        XTRACE("isc_task_detach");
@@ -356,7 +523,7 @@ isc_task_detach(isc_task_t **taskp) {
 }
 
 static inline isc_boolean_t
-task_send(isc_task_t *task, isc_event_t **eventp) {
+task_send(isc__task_t *task, isc_event_t **eventp) {
        isc_boolean_t was_idle = ISC_FALSE;
        isc_event_t *event;
 
@@ -385,8 +552,9 @@ task_send(isc_task_t *task, isc_event_t **eventp) {
        return (was_idle);
 }
 
-void
-isc_task_send(isc_task_t *task, isc_event_t **eventp) {
+ISC_TASKFUNC_SCOPE void
+isc__task_send(isc_task_t *task0, isc_event_t **eventp) {
+       isc__task_t *task = (isc__task_t *)task0;
        isc_boolean_t was_idle;
 
        /*
@@ -426,10 +594,10 @@ isc_task_send(isc_task_t *task, isc_event_t **eventp) {
        }
 }
 
-void
-isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
+ISC_TASKFUNC_SCOPE void
+isc__task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
        isc_boolean_t idle1, idle2;
-       isc_task_t *task;
+       isc__task_t *task;
 
        /*
         * Send '*event' to '*taskp' and then detach '*taskp' from its
@@ -437,7 +605,7 @@ isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
         */
 
        REQUIRE(taskp != NULL);
-       task = *taskp;
+       task = (isc__task_t *)*taskp;
        REQUIRE(VALID_TASK(task));
 
        XTRACE("isc_task_sendanddetach");
@@ -463,7 +631,7 @@ isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
 #define PURGE_OK(event)        (((event)->ev_attributes & ISC_EVENTATTR_NOPURGE) == 0)
 
 static unsigned int
-dequeue_events(isc_task_t *task, void *sender, isc_eventtype_t first,
+dequeue_events(isc__task_t *task, void *sender, isc_eventtype_t first,
               isc_eventtype_t last, void *tag,
               isc_eventlist_t *events, isc_boolean_t purging)
 {
@@ -502,10 +670,11 @@ dequeue_events(isc_task_t *task, void *sender, isc_eventtype_t first,
        return (count);
 }
 
-unsigned int
-isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
-                   isc_eventtype_t last, void *tag)
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_purgerange(isc_task_t *task0, void *sender, isc_eventtype_t first,
+                    isc_eventtype_t last, void *tag)
 {
+       isc__task_t *task = (isc__task_t *)task0;
        unsigned int count;
        isc_eventlist_t events;
        isc_event_t *event, *next_event;
@@ -533,9 +702,9 @@ isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
        return (count);
 }
 
-unsigned int
-isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
-              void *tag)
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
+               void *tag)
 {
        /*
         * Purge events from a task's event queue.
@@ -543,11 +712,12 @@ isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
 
        XTRACE("isc_task_purge");
 
-       return (isc_task_purgerange(task, sender, type, type, tag));
+       return (isc__task_purgerange(task, sender, type, type, tag));
 }
 
-isc_boolean_t
-isc_task_purgeevent(isc_task_t *task, isc_event_t *event) {
+ISC_TASKFUNC_SCOPE isc_boolean_t
+isc__task_purgeevent(isc_task_t *task0, isc_event_t *event) {
+       isc__task_t *task = (isc__task_t *)task0;
        isc_event_t *curr_event, *next_event;
 
        /*
@@ -588,10 +758,10 @@ isc_task_purgeevent(isc_task_t *task, isc_event_t *event) {
        return (ISC_TRUE);
 }
 
-unsigned int
-isc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
-                    isc_eventtype_t last, void *tag,
-                    isc_eventlist_t *events)
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
+                     isc_eventtype_t last, void *tag,
+                     isc_eventlist_t *events)
 {
        /*
         * Remove events from a task's event queue.
@@ -599,13 +769,13 @@ isc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
 
        XTRACE("isc_task_unsendrange");
 
-       return (dequeue_events(task, sender, first, last, tag, events,
-                              ISC_FALSE));
+       return (dequeue_events((isc__task_t *)task, sender, first,
+                              last, tag, events, ISC_FALSE));
 }
 
-unsigned int
-isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
-               void *tag, isc_eventlist_t *events)
+ISC_TASKFUNC_SCOPE unsigned int
+isc__task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
+                void *tag, isc_eventlist_t *events)
 {
        /*
         * Remove events from a task's event queue.
@@ -613,13 +783,15 @@ isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
 
        XTRACE("isc_task_unsend");
 
-       return (dequeue_events(task, sender, type, type, tag, events,
-                              ISC_FALSE));
+       return (dequeue_events((isc__task_t *)task, sender, type,
+                              type, tag, events, ISC_FALSE));
 }
 
-isc_result_t
-isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg)
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_onshutdown(isc_task_t *task0, isc_taskaction_t action,
+                    const void *arg)
 {
+       isc__task_t *task = (isc__task_t *)task0;
        isc_boolean_t disallowed = ISC_FALSE;
        isc_result_t result = ISC_R_SUCCESS;
        isc_event_t *event;
@@ -655,8 +827,9 @@ isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg)
        return (result);
 }
 
-void
-isc_task_shutdown(isc_task_t *task) {
+ISC_TASKFUNC_SCOPE void
+isc__task_shutdown(isc_task_t *task0) {
+       isc__task_t *task = (isc__task_t *)task0;
        isc_boolean_t was_idle;
 
        /*
@@ -673,8 +846,8 @@ isc_task_shutdown(isc_task_t *task) {
                task_ready(task);
 }
 
-void
-isc_task_destroy(isc_task_t **taskp) {
+ISC_TASKFUNC_SCOPE void
+isc__task_destroy(isc_task_t **taskp) {
 
        /*
         * Destroy '*taskp'.
@@ -686,8 +859,9 @@ isc_task_destroy(isc_task_t **taskp) {
        isc_task_detach(taskp);
 }
 
-void
-isc_task_setname(isc_task_t *task, const char *name, void *tag) {
+ISC_TASKFUNC_SCOPE void
+isc__task_setname(isc_task_t *task0, const char *name, void *tag) {
+       isc__task_t *task = (isc__task_t *)task0;
 
        /*
         * Name 'task'.
@@ -702,38 +876,108 @@ isc_task_setname(isc_task_t *task, const char *name, void *tag) {
        UNLOCK(&task->lock);
 }
 
-const char *
-isc_task_getname(isc_task_t *task) {
+ISC_TASKFUNC_SCOPE const char *
+isc__task_getname(isc_task_t *task0) {
+       isc__task_t *task = (isc__task_t *)task0;
+
+       REQUIRE(VALID_TASK(task));
+
        return (task->name);
 }
 
-void *
-isc_task_gettag(isc_task_t *task) {
+ISC_TASKFUNC_SCOPE void *
+isc__task_gettag(isc_task_t *task0) {
+       isc__task_t *task = (isc__task_t *)task0;
+
+       REQUIRE(VALID_TASK(task));
+
        return (task->tag);
 }
 
-void
-isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t) {
+ISC_TASKFUNC_SCOPE void
+isc__task_getcurrenttime(isc_task_t *task0, isc_stdtime_t *t) {
+       isc__task_t *task = (isc__task_t *)task0;
+
        REQUIRE(VALID_TASK(task));
        REQUIRE(t != NULL);
 
        LOCK(&task->lock);
-
        *t = task->now;
-
        UNLOCK(&task->lock);
 }
 
 /***
  *** Task Manager.
  ***/
+
+/*
+ * Return ISC_TRUE if the current ready list for the manager, which is
+ * either ready_tasks or the ready_priority_tasks, depending on whether
+ * the manager is currently in normal or privileged execution mode.
+ *
+ * Caller must hold the task manager lock.
+ */
+static inline isc_boolean_t
+empty_readyq(isc__taskmgr_t *manager) {
+       isc__tasklist_t queue;
+
+       if (manager->mode == isc_taskmgrmode_normal)
+               queue = manager->ready_tasks;
+       else
+               queue = manager->ready_priority_tasks;
+
+       return (ISC_TF(EMPTY(queue)));
+}
+
+/*
+ * Dequeue and return a pointer to the first task on the current ready
+ * list for the manager.
+ * If the task is privileged, dequeue it from the other ready list
+ * as well.
+ *
+ * Caller must hold the task manager lock.
+ */
+static inline isc__task_t *
+pop_readyq(isc__taskmgr_t *manager) {
+       isc__task_t *task;
+
+       if (manager->mode == isc_taskmgrmode_normal)
+               task = HEAD(manager->ready_tasks);
+       else
+               task = HEAD(manager->ready_priority_tasks);
+
+       if (task != NULL) {
+               DEQUEUE(manager->ready_tasks, task, ready_link);
+               if (ISC_LINK_LINKED(task, ready_priority_link))
+                       DEQUEUE(manager->ready_priority_tasks, task,
+                               ready_priority_link);
+       }
+
+       return (task);
+}
+
+/*
+ * Push 'task' onto the ready_tasks queue.  If 'task' has the privilege
+ * flag set, then also push it onto the ready_priority_tasks queue.
+ *
+ * Caller must hold the task manager lock.
+ */
+static inline void
+push_readyq(isc__taskmgr_t *manager, isc__task_t *task) {
+       ENQUEUE(manager->ready_tasks, task, ready_link);
+       if ((task->flags & TASK_F_PRIVILEGED) != 0)
+               ENQUEUE(manager->ready_priority_tasks, task,
+                       ready_priority_link);
+}
+
 static void
-dispatch(isc_taskmgr_t *manager) {
-       isc_task_t *task;
-#ifndef ISC_PLATFORM_USETHREADS
+dispatch(isc__taskmgr_t *manager) {
+       isc__task_t *task;
+#ifndef USE_WORKER_THREADS
        unsigned int total_dispatch_count = 0;
-       isc_tasklist_t ready_tasks;
-#endif /* ISC_PLATFORM_USETHREADS */
+       isc__tasklist_t new_ready_tasks;
+       isc__tasklist_t new_priority_tasks;
+#endif /* USE_WORKER_THREADS */
 
        REQUIRE(VALID_MANAGER(manager));
 
@@ -787,22 +1031,26 @@ dispatch(isc_taskmgr_t *manager) {
         * unlocks.  The while expression is always protected by the lock.
         */
 
-#ifndef ISC_PLATFORM_USETHREADS
-       ISC_LIST_INIT(ready_tasks);
+#ifndef USE_WORKER_THREADS
+       ISC_LIST_INIT(new_ready_tasks);
+       ISC_LIST_INIT(new_priority_tasks);
 #endif
        LOCK(&manager->lock);
+
        while (!FINISHED(manager)) {
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
                /*
                 * For reasons similar to those given in the comment in
                 * isc_task_send() above, it is safe for us to dequeue
                 * the task while only holding the manager lock, and then
                 * change the task to running state while only holding the
                 * task lock.
+                *
+                * If a pause has been requested, don't do any work
+                * until it's been released.
                 */
-               while ((EMPTY(manager->ready_tasks) ||
-                       manager->exclusive_requested) &&
-                       !FINISHED(manager))
+               while ((empty_readyq(manager) || manager->pause_requested ||
+                       manager->exclusive_requested) && !FINISHED(manager))
                {
                        XTHREADTRACE(isc_msgcat_get(isc_msgcat,
                                                    ISC_MSGSET_GENERAL,
@@ -812,15 +1060,15 @@ dispatch(isc_taskmgr_t *manager) {
                                                    ISC_MSGSET_TASK,
                                                    ISC_MSG_AWAKE, "awake"));
                }
-#else /* ISC_PLATFORM_USETHREADS */
+#else /* USE_WORKER_THREADS */
                if (total_dispatch_count >= DEFAULT_TASKMGR_QUANTUM ||
-                   EMPTY(manager->ready_tasks))
+                   empty_readyq(manager))
                        break;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
                XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TASK,
                                            ISC_MSG_WORKING, "working"));
 
-               task = HEAD(manager->ready_tasks);
+               task = pop_readyq(manager);
                if (task != NULL) {
                        unsigned int dispatch_count = 0;
                        isc_boolean_t done = ISC_FALSE;
@@ -835,7 +1083,6 @@ dispatch(isc_taskmgr_t *manager) {
                         * have a task to do.  We must reacquire the manager
                         * lock before exiting the 'if (task != NULL)' block.
                         */
-                       DEQUEUE(manager->ready_tasks, task, ready_link);
                        manager->tasks_running++;
                        UNLOCK(&manager->lock);
 
@@ -859,13 +1106,15 @@ dispatch(isc_taskmgr_t *manager) {
                                                            "execute action"));
                                        if (event->ev_action != NULL) {
                                                UNLOCK(&task->lock);
-                                               (event->ev_action)(task,event);
+                                               (event->ev_action)(
+                                                       (isc_task_t *)task,
+                                                       event);
                                                LOCK(&task->lock);
                                        }
                                        dispatch_count++;
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_WORKER_THREADS
                                        total_dispatch_count++;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
                                }
 
                                if (task->references == 0 &&
@@ -950,12 +1199,15 @@ dispatch(isc_taskmgr_t *manager) {
 
                        LOCK(&manager->lock);
                        manager->tasks_running--;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
                        if (manager->exclusive_requested &&
                            manager->tasks_running == 1) {
                                SIGNAL(&manager->exclusive_granted);
+                       } else if (manager->pause_requested &&
+                                  manager->tasks_running == 0) {
+                               SIGNAL(&manager->paused);
                        }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
                        if (requeue) {
                                /*
                                 * We know we're awake, so we don't have
@@ -976,28 +1228,50 @@ dispatch(isc_taskmgr_t *manager) {
                                 * were usually nonempty, the 'optimization'
                                 * might even hurt rather than help.
                                 */
-#ifdef ISC_PLATFORM_USETHREADS
-                               ENQUEUE(manager->ready_tasks, task,
-                                       ready_link);
+#ifdef USE_WORKER_THREADS
+                               push_readyq(manager, task);
 #else
-                               ENQUEUE(ready_tasks, task, ready_link);
+                               ENQUEUE(new_ready_tasks, task, ready_link);
+                               if ((task->flags & TASK_F_PRIVILEGED) != 0)
+                                       ENQUEUE(new_priority_tasks, task,
+                                               ready_priority_link);
 #endif
                        }
                }
+
+#ifdef USE_WORKER_THREADS
+               /*
+                * If we are in privileged execution mode and there are no
+                * tasks remaining on the current ready queue, then
+                * we're stuck.  Automatically drop privileges at that
+                * point and continue with the regular ready queue.
+                */
+               if (manager->tasks_running == 0 && empty_readyq(manager)) {
+                       manager->mode = isc_taskmgrmode_normal;
+                       if (!empty_readyq(manager))
+                               BROADCAST(&manager->work_available);
+               }
+#endif
        }
-#ifndef ISC_PLATFORM_USETHREADS
-       ISC_LIST_APPENDLIST(manager->ready_tasks, ready_tasks, ready_link);
+
+#ifndef USE_WORKER_THREADS
+       ISC_LIST_APPENDLIST(manager->ready_tasks, new_ready_tasks, ready_link);
+       ISC_LIST_APPENDLIST(manager->ready_priority_tasks, new_priority_tasks,
+                           ready_priority_link);
+       if (empty_readyq(manager))
+               manager->mode = isc_taskmgrmode_normal;
 #endif
+
        UNLOCK(&manager->lock);
 }
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
 static isc_threadresult_t
 #ifdef _WIN32
 WINAPI
 #endif
 run(void *uap) {
-       isc_taskmgr_t *manager = uap;
+       isc__taskmgr_t *manager = uap;
 
        XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
                                    ISC_MSG_STARTING, "starting"));
@@ -1007,33 +1281,43 @@ run(void *uap) {
        XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
                                    ISC_MSG_EXITING, "exiting"));
 
+#ifdef OPENSSL_LEAKS
+       ERR_remove_state(0);
+#endif
+
        return ((isc_threadresult_t)0);
 }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
 
 static void
-manager_free(isc_taskmgr_t *manager) {
+manager_free(isc__taskmgr_t *manager) {
        isc_mem_t *mctx;
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
        (void)isc_condition_destroy(&manager->exclusive_granted);
        (void)isc_condition_destroy(&manager->work_available);
+       (void)isc_condition_destroy(&manager->paused);
        isc_mem_free(manager->mctx, manager->threads);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
        DESTROYLOCK(&manager->lock);
-       manager->magic = 0;
+       manager->common.impmagic = 0;
+       manager->common.magic = 0;
        mctx = manager->mctx;
        isc_mem_put(mctx, manager, sizeof(*manager));
        isc_mem_detach(&mctx);
+
+#ifdef USE_SHARED_MANAGER
+       taskmgr = NULL;
+#endif /* USE_SHARED_MANAGER */
 }
 
-isc_result_t
-isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
-                  unsigned int default_quantum, isc_taskmgr_t **managerp)
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers,
+                   unsigned int default_quantum, isc_taskmgr_t **managerp)
 {
        isc_result_t result;
        unsigned int i, started = 0;
-       isc_taskmgr_t *manager;
+       isc__taskmgr_t *manager;
 
        /*
         * Create a new task manager.
@@ -1042,28 +1326,34 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
        REQUIRE(workers > 0);
        REQUIRE(managerp != NULL && *managerp == NULL);
 
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_WORKER_THREADS
        UNUSED(i);
        UNUSED(started);
-       UNUSED(workers);
+#endif
 
+#ifdef USE_SHARED_MANAGER
        if (taskmgr != NULL) {
+               if (taskmgr->refs == 0)
+                       return (ISC_R_SHUTTINGDOWN);
                taskmgr->refs++;
-               *managerp = taskmgr;
+               *managerp = (isc_taskmgr_t *)taskmgr;
                return (ISC_R_SUCCESS);
        }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_SHARED_MANAGER */
 
        manager = isc_mem_get(mctx, sizeof(*manager));
        if (manager == NULL)
                return (ISC_R_NOMEMORY);
-       manager->magic = TASK_MANAGER_MAGIC;
+       manager->common.methods = &taskmgrmethods;
+       manager->common.impmagic = TASK_MANAGER_MAGIC;
+       manager->common.magic = ISCAPI_TASKMGR_MAGIC;
+       manager->mode = isc_taskmgrmode_normal;
        manager->mctx = NULL;
        result = isc_mutex_init(&manager->lock);
        if (result != ISC_R_SUCCESS)
                goto cleanup_mgr;
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
        manager->workers = 0;
        manager->threads = isc_mem_allocate(mctx,
                                            workers * sizeof(isc_thread_t));
@@ -1087,19 +1377,29 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
                result = ISC_R_UNEXPECTED;
                goto cleanup_workavailable;
        }
-#endif /* ISC_PLATFORM_USETHREADS */
+       if (isc_condition_init(&manager->paused) != ISC_R_SUCCESS) {
+               UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                "isc_condition_init() %s",
+                                isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+                                               ISC_MSG_FAILED, "failed"));
+               result = ISC_R_UNEXPECTED;
+               goto cleanup_exclusivegranted;
+       }
+#endif /* USE_WORKER_THREADS */
        if (default_quantum == 0)
                default_quantum = DEFAULT_DEFAULT_QUANTUM;
        manager->default_quantum = default_quantum;
        INIT_LIST(manager->tasks);
        INIT_LIST(manager->ready_tasks);
+       INIT_LIST(manager->ready_priority_tasks);
        manager->tasks_running = 0;
        manager->exclusive_requested = ISC_FALSE;
+       manager->pause_requested = ISC_FALSE;
        manager->exiting = ISC_FALSE;
 
        isc_mem_attach(mctx, &manager->mctx);
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
        LOCK(&manager->lock);
        /*
         * Start workers.
@@ -1119,16 +1419,19 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
                return (ISC_R_NOTHREADS);
        }
        isc_thread_setconcurrency(workers);
-#else /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WORKER_THREADS */
+#ifdef USE_SHARED_MANAGER
        manager->refs = 1;
        taskmgr = manager;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_SHARED_MANAGER */
 
-       *managerp = manager;
+       *managerp = (isc_taskmgr_t *)manager;
 
        return (ISC_R_SUCCESS);
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
+ cleanup_exclusivegranted:
+       (void)isc_condition_destroy(&manager->exclusive_granted);
  cleanup_workavailable:
        (void)isc_condition_destroy(&manager->work_available);
  cleanup_threads:
@@ -1141,10 +1444,10 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
        return (result);
 }
 
-void
-isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
-       isc_taskmgr_t *manager;
-       isc_task_t *task;
+ISC_TASKFUNC_SCOPE void
+isc__taskmgr_destroy(isc_taskmgr_t **managerp) {
+       isc__taskmgr_t *manager;
+       isc__task_t *task;
        unsigned int i;
 
        /*
@@ -1152,18 +1455,20 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
         */
 
        REQUIRE(managerp != NULL);
-       manager = *managerp;
+       manager = (isc__taskmgr_t *)*managerp;
        REQUIRE(VALID_MANAGER(manager));
 
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_WORKER_THREADS
        UNUSED(i);
+#endif /* USE_WORKER_THREADS */
 
-       if (manager->refs > 1) {
-               manager->refs--;
+#ifdef USE_SHARED_MANAGER
+       manager->refs--;
+       if (manager->refs > 0) {
                *managerp = NULL;
                return;
        }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif
 
        XTHREADTRACE("isc_taskmgr_destroy");
        /*
@@ -1191,6 +1496,11 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
        INSIST(!manager->exiting);
        manager->exiting = ISC_TRUE;
 
+       /*
+        * If privileged mode was on, turn it off.
+        */
+       manager->mode = isc_taskmgrmode_normal;
+
        /*
         * Post shutdown event(s) to every task (if they haven't already been
         * posted).
@@ -1200,10 +1510,10 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
             task = NEXT(task, link)) {
                LOCK(&task->lock);
                if (task_shutdown(task))
-                       ENQUEUE(manager->ready_tasks, task, ready_link);
+                       push_readyq(manager, task);
                UNLOCK(&task->lock);
        }
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
        /*
         * Wake up any sleeping workers.  This ensures we get work done if
         * there's work left to do, and if there are already no tasks left
@@ -1217,36 +1527,76 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
         */
        for (i = 0; i < manager->workers; i++)
                (void)isc_thread_join(manager->threads[i], NULL);
-#else /* ISC_PLATFORM_USETHREADS */
+#else /* USE_WORKER_THREADS */
        /*
         * Dispatch the shutdown events.
         */
        UNLOCK(&manager->lock);
-       while (isc__taskmgr_ready())
-               (void)isc__taskmgr_dispatch();
+       while (isc__taskmgr_ready((isc_taskmgr_t *)manager))
+               (void)isc__taskmgr_dispatch((isc_taskmgr_t *)manager);
+#ifdef BIND9
        if (!ISC_LIST_EMPTY(manager->tasks))
                isc_mem_printallactive(stderr);
+#endif
        INSIST(ISC_LIST_EMPTY(manager->tasks));
-#endif /* ISC_PLATFORM_USETHREADS */
+#ifdef USE_SHARED_MANAGER
+       taskmgr = NULL;
+#endif
+#endif /* USE_WORKER_THREADS */
 
        manager_free(manager);
 
        *managerp = NULL;
 }
 
-#ifndef ISC_PLATFORM_USETHREADS
+ISC_TASKFUNC_SCOPE void
+isc__taskmgr_setmode(isc_taskmgr_t *manager0, isc_taskmgrmode_t mode) {
+       isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
+
+       LOCK(&manager->lock);
+       manager->mode = mode;
+       UNLOCK(&manager->lock);
+}
+
+ISC_TASKFUNC_SCOPE isc_taskmgrmode_t
+isc__taskmgr_mode(isc_taskmgr_t *manager0) {
+       isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
+       isc_taskmgrmode_t mode;
+       LOCK(&manager->lock);
+       mode = manager->mode;
+       UNLOCK(&manager->lock);
+       return (mode);
+}
+
+#ifndef USE_WORKER_THREADS
 isc_boolean_t
-isc__taskmgr_ready(void) {
-       if (taskmgr == NULL)
+isc__taskmgr_ready(isc_taskmgr_t *manager0) {
+       isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
+       isc_boolean_t is_ready;
+
+#ifdef USE_SHARED_MANAGER
+       if (manager == NULL)
+               manager = taskmgr;
+#endif
+       if (manager == NULL)
                return (ISC_FALSE);
-       return (ISC_TF(!ISC_LIST_EMPTY(taskmgr->ready_tasks)));
+
+       LOCK(&manager->lock);
+       is_ready = !empty_readyq(manager);
+       UNLOCK(&manager->lock);
+
+       return (is_ready);
 }
 
 isc_result_t
-isc__taskmgr_dispatch(void) {
-       isc_taskmgr_t *manager = taskmgr;
+isc__taskmgr_dispatch(isc_taskmgr_t *manager0) {
+       isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
 
-       if (taskmgr == NULL)
+#ifdef USE_SHARED_MANAGER
+       if (manager == NULL)
+               manager = taskmgr;
+#endif
+       if (manager == NULL)
                return (ISC_R_NOTFOUND);
 
        dispatch(manager);
@@ -1254,12 +1604,36 @@ isc__taskmgr_dispatch(void) {
        return (ISC_R_SUCCESS);
 }
 
-#endif /* ISC_PLATFORM_USETHREADS */
+#else
+ISC_TASKFUNC_SCOPE void
+isc__taskmgr_pause(isc_taskmgr_t *manager0) {
+       isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
+       LOCK(&manager->lock);
+       while (manager->tasks_running > 0) {
+               WAIT(&manager->paused, &manager->lock);
+       }
+       manager->pause_requested = ISC_TRUE;
+       UNLOCK(&manager->lock);
+}
 
-isc_result_t
-isc_task_beginexclusive(isc_task_t *task) {
-#ifdef ISC_PLATFORM_USETHREADS
-       isc_taskmgr_t *manager = task->manager;
+ISC_TASKFUNC_SCOPE void
+isc__taskmgr_resume(isc_taskmgr_t *manager0) {
+       isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
+
+       LOCK(&manager->lock);
+       if (manager->pause_requested) {
+               manager->pause_requested = ISC_FALSE;
+               BROADCAST(&manager->work_available);
+       }
+       UNLOCK(&manager->lock);
+}
+#endif /* USE_WORKER_THREADS */
+
+ISC_TASKFUNC_SCOPE isc_result_t
+isc__task_beginexclusive(isc_task_t *task0) {
+#ifdef USE_WORKER_THREADS
+       isc__task_t *task = (isc__task_t *)task0;
+       isc__taskmgr_t *manager = task->manager;
        REQUIRE(task->state == task_state_running);
        LOCK(&manager->lock);
        if (manager->exclusive_requested) {
@@ -1272,15 +1646,17 @@ isc_task_beginexclusive(isc_task_t *task) {
        }
        UNLOCK(&manager->lock);
 #else
-       UNUSED(task);
+       UNUSED(task0);
 #endif
        return (ISC_R_SUCCESS);
 }
 
-void
-isc_task_endexclusive(isc_task_t *task) {
-#ifdef ISC_PLATFORM_USETHREADS
-       isc_taskmgr_t *manager = task->manager;
+ISC_TASKFUNC_SCOPE void
+isc__task_endexclusive(isc_task_t *task0) {
+#ifdef USE_WORKER_THREADS
+       isc__task_t *task = (isc__task_t *)task0;
+       isc__taskmgr_t *manager = task->manager;
+
        REQUIRE(task->state == task_state_running);
        LOCK(&manager->lock);
        REQUIRE(manager->exclusive_requested);
@@ -1288,16 +1664,69 @@ isc_task_endexclusive(isc_task_t *task) {
        BROADCAST(&manager->work_available);
        UNLOCK(&manager->lock);
 #else
-       UNUSED(task);
+       UNUSED(task0);
 #endif
 }
 
-#ifdef HAVE_LIBXML2
+ISC_TASKFUNC_SCOPE void
+isc__task_setprivilege(isc_task_t *task0, isc_boolean_t priv) {
+       isc__task_t *task = (isc__task_t *)task0;
+       isc__taskmgr_t *manager = task->manager;
+       isc_boolean_t oldpriv;
 
+       LOCK(&task->lock);
+       oldpriv = ISC_TF((task->flags & TASK_F_PRIVILEGED) != 0);
+       if (priv)
+               task->flags |= TASK_F_PRIVILEGED;
+       else
+               task->flags &= ~TASK_F_PRIVILEGED;
+       UNLOCK(&task->lock);
+
+       if (priv == oldpriv)
+               return;
+
+       LOCK(&manager->lock);
+       if (priv && ISC_LINK_LINKED(task, ready_link))
+               ENQUEUE(manager->ready_priority_tasks, task,
+                       ready_priority_link);
+       else if (!priv && ISC_LINK_LINKED(task, ready_priority_link))
+               DEQUEUE(manager->ready_priority_tasks, task,
+                       ready_priority_link);
+       UNLOCK(&manager->lock);
+}
+
+ISC_TASKFUNC_SCOPE isc_boolean_t
+isc__task_privilege(isc_task_t *task0) {
+       isc__task_t *task = (isc__task_t *)task0;
+       isc_boolean_t priv;
+
+       LOCK(&task->lock);
+       priv = ISC_TF((task->flags & TASK_F_PRIVILEGED) != 0);
+       UNLOCK(&task->lock);
+       return (priv);
+}
+
+#ifdef USE_SOCKETIMPREGISTER
+isc_result_t
+isc__task_register() {
+       return (isc_task_register(isc__taskmgr_create));
+}
+#endif
+
+isc_boolean_t
+isc_task_exiting(isc_task_t *t) {
+       isc__task_t *task = (isc__task_t *)t;
+
+       REQUIRE(VALID_TASK(task));
+       return (TASK_SHUTTINGDOWN(task));
+}
+
+
+#if defined(HAVE_LIBXML2) && defined(BIND9)
 void
-isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer)
-{
-       isc_task_t *task;
+isc_taskmgr_renderxml(isc_taskmgr_t *mgr0, xmlTextWriterPtr writer) {
+       isc__taskmgr_t *mgr = (isc__taskmgr_t *)mgr0;
+       isc__task_t *task;
 
        LOCK(&mgr->lock);
 
@@ -1373,4 +1802,4 @@ isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer)
 
        UNLOCK(&mgr->lock);
 }
-#endif /* HAVE_LIBXML2 */
+#endif /* HAVE_LIBXML2 && BIND9 */
diff --git a/lib/isc/task_api.c b/lib/isc/task_api.c
new file mode 100644 (file)
index 0000000..34510ff
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2009-2012  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id$ */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_taskmgrcreatefunc_t taskmgr_createfunc = NULL;
+
+static void
+initialize(void) {
+       RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_task_register(isc_taskmgrcreatefunc_t createfunc) {
+       isc_result_t result = ISC_R_SUCCESS;
+
+       RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+       LOCK(&createlock);
+       if (taskmgr_createfunc == NULL)
+               taskmgr_createfunc = createfunc;
+       else
+               result = ISC_R_EXISTS;
+       UNLOCK(&createlock);
+
+       return (result);
+}
+
+isc_result_t
+isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+                       unsigned int workers, unsigned int default_quantum,
+                       isc_taskmgr_t **managerp)
+{
+       isc_result_t result;
+
+       LOCK(&createlock);
+
+       REQUIRE(taskmgr_createfunc != NULL);
+       result = (*taskmgr_createfunc)(mctx, workers, default_quantum,
+                                      managerp);
+
+       UNLOCK(&createlock);
+
+       if (result == ISC_R_SUCCESS)
+               isc_appctx_settaskmgr(actx, *managerp);
+
+       return (result);
+}
+
+isc_result_t
+isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
+                  unsigned int default_quantum, isc_taskmgr_t **managerp)
+{
+       isc_result_t result;
+
+       LOCK(&createlock);
+
+       REQUIRE(taskmgr_createfunc != NULL);
+       result = (*taskmgr_createfunc)(mctx, workers, default_quantum,
+                                      managerp);
+
+       UNLOCK(&createlock);
+
+       return (result);
+}
+
+void
+isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
+       REQUIRE(managerp != NULL && ISCAPI_TASKMGR_VALID(*managerp));
+
+       (*managerp)->methods->destroy(managerp);
+
+       ENSURE(*managerp == NULL);
+}
+
+void
+isc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode) {
+       REQUIRE(ISCAPI_TASKMGR_VALID(manager));
+
+       manager->methods->setmode(manager, mode);
+}
+
+isc_taskmgrmode_t
+isc_taskmgr_mode(isc_taskmgr_t *manager) {
+       REQUIRE(ISCAPI_TASKMGR_VALID(manager));
+
+       return (manager->methods->mode(manager));
+}
+
+isc_result_t
+isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
+               isc_task_t **taskp)
+{
+       REQUIRE(ISCAPI_TASKMGR_VALID(manager));
+       REQUIRE(taskp != NULL && *taskp == NULL);
+
+       return (manager->methods->taskcreate(manager, quantum, taskp));
+}
+
+void
+isc_task_attach(isc_task_t *source, isc_task_t **targetp) {
+       REQUIRE(ISCAPI_TASK_VALID(source));
+       REQUIRE(targetp != NULL && *targetp == NULL);
+
+       source->methods->attach(source, targetp);
+
+       ENSURE(*targetp == source);
+}
+
+void
+isc_task_detach(isc_task_t **taskp) {
+       REQUIRE(taskp != NULL && ISCAPI_TASK_VALID(*taskp));
+
+       (*taskp)->methods->detach(taskp);
+
+       ENSURE(*taskp == NULL);
+}
+
+void
+isc_task_send(isc_task_t *task, isc_event_t **eventp) {
+       REQUIRE(ISCAPI_TASK_VALID(task));
+       REQUIRE(eventp != NULL && *eventp != NULL);
+
+       task->methods->send(task, eventp);
+
+       ENSURE(*eventp == NULL);
+}
+
+void
+isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
+       REQUIRE(taskp != NULL && ISCAPI_TASK_VALID(*taskp));
+       REQUIRE(eventp != NULL && *eventp != NULL);
+
+       (*taskp)->methods->sendanddetach(taskp, eventp);
+
+       ENSURE(*taskp == NULL && *eventp == NULL);
+}
+
+unsigned int
+isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
+               void *tag, isc_eventlist_t *events)
+{
+       REQUIRE(ISCAPI_TASK_VALID(task));
+
+       return (task->methods->unsend(task, sender, type, tag, events));
+}
+
+isc_result_t
+isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+       REQUIRE(ISCAPI_TASK_VALID(task));
+
+       return (task->methods->onshutdown(task, action, arg));
+}
+
+void
+isc_task_shutdown(isc_task_t *task) {
+       REQUIRE(ISCAPI_TASK_VALID(task));
+
+       task->methods->shutdown(task);
+}
+
+void
+isc_task_setname(isc_task_t *task, const char *name, void *tag) {
+       REQUIRE(ISCAPI_TASK_VALID(task));
+
+       task->methods->setname(task, name, tag);
+}
+
+unsigned int
+isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, void *tag)
+{
+       REQUIRE(ISCAPI_TASK_VALID(task));
+
+       return (task->methods->purgeevents(task, sender, type, tag));
+}
+
+isc_result_t
+isc_task_beginexclusive(isc_task_t *task) {
+       REQUIRE(ISCAPI_TASK_VALID(task));
+
+       return (task->methods->beginexclusive(task));
+}
+
+void
+isc_task_endexclusive(isc_task_t *task) {
+       REQUIRE(ISCAPI_TASK_VALID(task));
+
+       task->methods->endexclusive(task);
+}
+
+void
+isc_task_setprivilege(isc_task_t *task, isc_boolean_t priv) {
+       REQUIRE(ISCAPI_TASK_VALID(task));
+
+       task->methods->setprivilege(task, priv);
+}
+
+isc_boolean_t
+isc_task_privilege(isc_task_t *task) {
+       REQUIRE(ISCAPI_TASK_VALID(task));
+
+       return (task->methods->privilege(task));
+}
+
+
+/*%
+ * This is necessary for libisc's internal timer implementation.  Other
+ * implementation might skip implementing this.
+ */
+unsigned int
+isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
+                   isc_eventtype_t last, void *tag)
+{
+       REQUIRE(ISCAPI_TASK_VALID(task));
+
+       return (task->methods->purgerange(task, sender, first, last, tag));
+}
index c88810390890741c5c968328a291b60d6e2f8372..8c1e4c52fa4c0205c970caf203acff92215e7708 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: task_p.h,v 1.11 2007/06/19 23:47:17 tbox Exp $ */
+/* $Id$ */
 
 #ifndef ISC_TASK_P_H
 #define ISC_TASK_P_H
 
 /*! \file */
 
+#if defined(BIND9) && defined(ISC_PLATFORM_USETHREADS)
+void
+isc__taskmgr_pause(isc_taskmgr_t *taskmgr);
+
+void
+isc__taskmgr_resume(isc_taskmgr_t *taskmgr);
+#else
 isc_boolean_t
-isc__taskmgr_ready(void);
+isc__taskmgr_ready(isc_taskmgr_t *taskmgr);
 
 isc_result_t
-isc__taskmgr_dispatch(void);
+isc__taskmgr_dispatch(isc_taskmgr_t *taskmgr);
+#endif /* !BIND9 || !ISC_PLATFORM_USETHREADS */
 
 #endif /* ISC_TASK_P_H */
index d9c2fbe2f31a3dbf3b4ee2dee3265dadbeb88bd4..25d951682889d537a40076e73edaa4940799168f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: taskpool.c,v 1.18 2007/06/18 23:47:44 tbox Exp $ */
+/* $Id$ */
 
 /*! \file */
 
 #include <config.h>
 
 #include <isc/mem.h>
+#include <isc/random.h>
 #include <isc/taskpool.h>
 #include <isc/util.h>
 
 
 struct isc_taskpool {
        isc_mem_t *                     mctx;
+       isc_taskmgr_t *                 tmgr;
        unsigned int                    ntasks;
+       unsigned int                    quantum;
        isc_task_t **                   tasks;
 };
+
 /***
  *** Functions.
  ***/
 
-isc_result_t
-isc_taskpool_create(isc_taskmgr_t *tmgr, isc_mem_t *mctx,
-                   unsigned int ntasks, unsigned int quantum,
-                   isc_taskpool_t **poolp)
+static isc_result_t
+alloc_pool(isc_taskmgr_t *tmgr, isc_mem_t *mctx, unsigned int ntasks,
+          unsigned int quantum, isc_taskpool_t **poolp)
 {
-       unsigned int i;
        isc_taskpool_t *pool;
-       isc_result_t result;
+       unsigned int i;
 
-       INSIST(ntasks > 0);
        pool = isc_mem_get(mctx, sizeof(*pool));
        if (pool == NULL)
                return (ISC_R_NOMEMORY);
        pool->mctx = mctx;
        pool->ntasks = ntasks;
+       pool->quantum = quantum;
+       pool->tmgr = tmgr;
        pool->tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
        if (pool->tasks == NULL) {
                isc_mem_put(mctx, pool, sizeof(*pool));
@@ -60,6 +63,28 @@ isc_taskpool_create(isc_taskmgr_t *tmgr, isc_mem_t *mctx,
        }
        for (i = 0; i < ntasks; i++)
                pool->tasks[i] = NULL;
+
+       *poolp = pool;
+       return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_taskpool_create(isc_taskmgr_t *tmgr, isc_mem_t *mctx,
+                   unsigned int ntasks, unsigned int quantum,
+                   isc_taskpool_t **poolp)
+{
+       unsigned int i;
+       isc_taskpool_t *pool = NULL;
+       isc_result_t result;
+
+       INSIST(ntasks > 0);
+
+       /* Allocate the pool structure */
+       result = alloc_pool(tmgr, mctx, ntasks, quantum, &pool);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+
+       /* Create the tasks */
        for (i = 0; i < ntasks; i++) {
                result = isc_task_create(tmgr, quantum, &pool->tasks[i]);
                if (result != ISC_R_SUCCESS) {
@@ -68,14 +93,69 @@ isc_taskpool_create(isc_taskmgr_t *tmgr, isc_mem_t *mctx,
                }
                isc_task_setname(pool->tasks[i], "taskpool", NULL);
        }
+
        *poolp = pool;
        return (ISC_R_SUCCESS);
 }
 
-void isc_taskpool_gettask(isc_taskpool_t *pool, unsigned int hash,
-                         isc_task_t **targetp)
+void
+isc_taskpool_gettask(isc_taskpool_t *pool, isc_task_t **targetp) {
+       isc_uint32_t i;
+       isc_random_get(&i);
+       isc_task_attach(pool->tasks[i % pool->ntasks], targetp);
+}
+
+int
+isc_taskpool_size(isc_taskpool_t *pool) {
+       REQUIRE(pool != NULL);
+       return (pool->ntasks);
+}
+
+isc_result_t
+isc_taskpool_expand(isc_taskpool_t **sourcep, unsigned int size,
+                   isc_taskpool_t **targetp)
 {
-       isc_task_attach(pool->tasks[hash % pool->ntasks], targetp);
+       isc_result_t result;
+       isc_taskpool_t *pool;
+
+       REQUIRE(sourcep != NULL && *sourcep != NULL);
+       REQUIRE(targetp != NULL && *targetp == NULL);
+
+       pool = *sourcep;
+       if (size > pool->ntasks) {
+               isc_taskpool_t *newpool = NULL;
+               unsigned int i;
+
+               /* Allocate a new pool structure */
+               result = alloc_pool(pool->tmgr, pool->mctx, size,
+                                   pool->quantum, &newpool);
+               if (result != ISC_R_SUCCESS)
+                       return (result);
+
+               /* Copy over the tasks from the old pool */
+               for (i = 0; i < pool->ntasks; i++) {
+                       newpool->tasks[i] = pool->tasks[i];
+                       pool->tasks[i] = NULL;
+               }
+
+               /* Create new tasks */
+               for (i = pool->ntasks; i < size; i++) {
+                       result = isc_task_create(pool->tmgr, pool->quantum,
+                                                &newpool->tasks[i]);
+                       if (result != ISC_R_SUCCESS) {
+                               isc_taskpool_destroy(&newpool);
+                               return (result);
+                       }
+                       isc_task_setname(newpool->tasks[i], "taskpool", NULL);
+               }
+
+               isc_taskpool_destroy(&pool);
+               pool = newpool;
+       }
+
+       *sourcep = NULL;
+       *targetp = pool;
+       return (ISC_R_SUCCESS);
 }
 
 void
@@ -83,9 +163,8 @@ isc_taskpool_destroy(isc_taskpool_t **poolp) {
        unsigned int i;
        isc_taskpool_t *pool = *poolp;
        for (i = 0; i < pool->ntasks; i++) {
-               if (pool->tasks[i] != NULL) {
+               if (pool->tasks[i] != NULL)
                        isc_task_detach(&pool->tasks[i]);
-               }
        }
        isc_mem_put(pool->mctx, pool->tasks,
                    pool->ntasks * sizeof(isc_task_t *));
@@ -93,4 +172,14 @@ isc_taskpool_destroy(isc_taskpool_t **poolp) {
        *poolp = NULL;
 }
 
+void
+isc_taskpool_setprivilege(isc_taskpool_t *pool, isc_boolean_t priv) {
+       unsigned int i;
+
+       REQUIRE(pool != NULL);
 
+       for (i = 0; i < pool->ntasks; i++) {
+               if (pool->tasks[i] != NULL)
+                       isc_task_setprivilege(pool->tasks[i], priv);
+       }
+}
diff --git a/lib/isc/tests/Atffile b/lib/isc/tests/Atffile
new file mode 100644 (file)
index 0000000..c3e044f
--- /dev/null
@@ -0,0 +1,5 @@
+Content-Type: application/X-atf-atffile; version="1"
+
+prop: test-suite = bind9
+
+tp-glob: *_test
diff --git a/lib/isc/tests/hash_test.c b/lib/isc/tests/hash_test.c
new file mode 100644 (file)
index 0000000..836d7b6
--- /dev/null
@@ -0,0 +1,1805 @@
+/*
+ * Copyright (C) 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id$ */
+
+/* ! \file */
+
+#include <config.h>
+
+#include <atf-c.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <isc/hmacmd5.h>
+#include <isc/hmacsha.h>
+#include <isc/md5.h>
+#include <isc/sha1.h>
+#include <isc/util.h>
+#include <isc/string.h>
+
+/*
+ * Test data from RFC6234
+ */
+
+unsigned char digest[ISC_SHA512_DIGESTLENGTH];
+unsigned char buffer[1024];
+const char *s;
+char str[ISC_SHA512_DIGESTLENGTH];
+unsigned char key[20];
+int i = 0;
+
+isc_result_t
+tohexstr(unsigned char *d, unsigned int len, char *out);
+/*
+ * Precondition: a hexadecimal number in *d, the length of that number in len,
+ *   and a pointer to a character array to put the output (*out).
+ * Postcondition: A String representation of the given hexadecimal number is
+ *   placed into the array *out
+ *
+ * 'out' MUST point to an array of at least len / 2 + 1
+ *
+ * Return values: ISC_R_SUCCESS if the operation is sucessful
+ */
+
+isc_result_t
+tohexstr(unsigned char *d, unsigned int len, char *out) {
+
+       out[0]='\0';
+       char c_ret[] = "AA";
+       unsigned int i;
+       strcat(out, "0x");
+       for (i = 0; i < len; i++) {
+               sprintf(c_ret, "%02X", d[i]);
+               strcat(out, c_ret);
+       }
+       strcat(out, "\0");
+       return (ISC_R_SUCCESS);
+}
+
+
+#define TEST_INPUT(x) (x), sizeof(x)-1
+
+typedef struct hash_testcase {
+       const char *input;
+       size_t input_len;
+       const char *result;
+       int repeats;
+} hash_testcase_t;
+
+typedef struct hash_test_key {
+       const char *key;
+       const int len;
+} hash_test_key_t;
+
+/* non-hmac tests */
+
+ATF_TC(isc_sha1);
+ATF_TC_HEAD(isc_sha1, tc) {
+       atf_tc_set_md_var(tc, "descr", "sha1 examples from RFC4634");
+}
+ATF_TC_BODY(isc_sha1, tc) {
+       isc_sha1_t sha1;
+
+       UNUSED(tc);
+
+       /*
+        * These are the various test vectors.  All of these are passed
+        * through the hash function and the results are compared to the
+        * result specified here.
+        */
+       hash_testcase_t testcases[] = {
+               /* Test 1 */
+               {
+                       TEST_INPUT("abc"),
+                       "0xA9993E364706816ABA3E25717850C26C9CD0D89D",
+                       1
+               },
+               /* Test 2 */
+               {
+                       TEST_INPUT("abcdbcdecdefdefgefghfghighijhijkijk"
+                                  "ljklmklmnlmnomnopnopq"),
+                       "0x84983E441C3BD26EBAAE4AA1F95129E5E54670F1",
+                       1
+               },
+               /* Test 3 */
+               {
+                       TEST_INPUT("a") /* times 1000000 */,
+                       "0x34AA973CD4C4DAA4F61EEB2BDBAD27316534016F",
+                       1000000
+               },
+               /* Test 4 -- exact multiple of 512 bits */
+               {
+                       TEST_INPUT("01234567012345670123456701234567"),
+                       "0xDEA356A2CDDD90C7A7ECEDC5EBB563934F460452",
+                       20 /* 20 times */
+               },
+#if 0
+               /* Test 5 -- optional feature, not implemented */
+               {
+                       TEST_INPUT(""),
+                       /* "extrabits": 0x98 , "numberextrabits": 5 */
+                       "0x29826B003B906E660EFF4027CE98AF3531AC75BA",
+                       1
+               },
+#endif
+               /* Test 6 */
+               {
+                       TEST_INPUT("\x5e"),
+                       "0x5E6F80A34A9798CAFC6A5DB96CC57BA4C4DB59C2",
+                       1
+               },
+#if 0
+               /* Test 7 -- optional feature, not implemented */
+               {
+                       TEST_INPUT("\x49\xb2\xae\xc2\x59\x4b\xbe\x3a"
+                                  "\x3b\x11\x75\x42\xd9\x4a\xc8"),
+                       /* "extrabits": 0x80, "numberextrabits": 3 */
+                 "0x6239781E03729919C01955B3FFA8ACB60B988340", 1 },
+#endif
+               /* Test 8 */
+               {
+                       TEST_INPUT("\x9a\x7d\xfd\xf1\xec\xea\xd0\x6e\xd6\x46"
+                                  "\xaa\x55\xfe\x75\x71\x46"),
+                       "0x82ABFF6605DBE1C17DEF12A394FA22A82B544A35",
+                       1
+               },
+#if 0
+               /* Test 9 -- optional feature, not implemented */
+               {
+                       TEST_INPUT("\x65\xf9\x32\x99\x5b\xa4\xce\x2c\xb1\xb4"
+                                  "\xa2\xe7\x1a\xe7\x02\x20\xaa\xce\xc8\x96"
+                                  "\x2d\xd4\x49\x9c\xbd\x7c\x88\x7a\x94\xea"
+                                  "\xaa\x10\x1e\xa5\xaa\xbc\x52\x9b\x4e\x7e"
+                                  "\x43\x66\x5a\x5a\xf2\xcd\x03\xfe\x67\x8e"
+                                  "\xa6\xa5\x00\x5b\xba\x3b\x08\x22\x04\xc2"
+                                  "\x8b\x91\x09\xf4\x69\xda\xc9\x2a\xaa\xb3"
+                                  "\xaa\x7c\x11\xa1\xb3\x2a"),
+                       /* "extrabits": 0xE0 , "numberextrabits": 3 */
+                       "0x8C5B2A5DDAE5A97FC7F9D85661C672ADBF7933D4",
+                       1
+               },
+#endif
+               /* Test 10 */
+               {
+                       TEST_INPUT("\xf7\x8f\x92\x14\x1b\xcd\x17\x0a\xe8\x9b"
+                                  "\x4f\xba\x15\xa1\xd5\x9f\x3f\xd8\x4d\x22"
+                                  "\x3c\x92\x51\xbd\xac\xbb\xae\x61\xd0\x5e"
+                                  "\xd1\x15\xa0\x6a\x7c\xe1\x17\xb7\xbe\xea"
+                                  "\xd2\x44\x21\xde\xd9\xc3\x25\x92\xbd\x57"
+                                  "\xed\xea\xe3\x9c\x39\xfa\x1f\xe8\x94\x6a"
+                                  "\x84\xd0\xcf\x1f\x7b\xee\xad\x17\x13\xe2"
+                                  "\xe0\x95\x98\x97\x34\x7f\x67\xc8\x0b\x04"
+                                  "\x00\xc2\x09\x81\x5d\x6b\x10\xa6\x83\x83"
+                                  "\x6f\xd5\x56\x2a\x56\xca\xb1\xa2\x8e\x81"
+                                  "\xb6\x57\x66\x54\x63\x1c\xf1\x65\x66\xb8"
+                                  "\x6e\x3b\x33\xa1\x08\xb0\x53\x07\xc0\x0a"
+                                  "\xff\x14\xa7\x68\xed\x73\x50\x60\x6a\x0f"
+                                  "\x85\xe6\xa9\x1d\x39\x6f\x5b\x5c\xbe\x57"
+                                  "\x7f\x9b\x38\x80\x7c\x7d\x52\x3d\x6d\x79"
+                                  "\x2f\x6e\xbc\x24\xa4\xec\xf2\xb3\xa4\x27"
+                                  "\xcd\xbb\xfb"),
+                       "0xCB0082C8F197D260991BA6A460E76E202BAD27B3",
+                       1
+               },
+               { NULL, 0, NULL, 1 }
+       };
+
+       hash_testcase_t *testcase = testcases;
+
+       while (testcase->input != NULL && testcase->result != NULL) {
+               isc_sha1_init(&sha1);
+               for(i = 0; i < testcase->repeats; i++) {
+                       isc_sha1_update(&sha1,
+                                       (const isc_uint8_t *) testcase->input,
+                                       testcase->input_len);
+               }
+               isc_sha1_final(&sha1, digest);
+               tohexstr(digest, ISC_SHA1_DIGESTLENGTH, str);
+               ATF_CHECK_STREQ(str, testcase->result);
+
+               testcase++;
+       }
+}
+
+
+ATF_TC(isc_sha224);
+ATF_TC_HEAD(isc_sha224, tc) {
+       atf_tc_set_md_var(tc, "descr", "sha224 examples from RFC4634");
+}
+ATF_TC_BODY(isc_sha224, tc) {
+       isc_sha224_t sha224;
+
+       UNUSED(tc);
+
+       /*
+        * These are the various test vectors.  All of these are passed
+        * through the hash function and the results are compared to the
+        * result specified here.
+        */
+       hash_testcase_t testcases[] = {
+               /* Test 1 */
+               {
+                       TEST_INPUT("abc"),
+                       "0x23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7"
+                               "E36C9DA7",
+                       1
+               },
+               /* Test 2 */
+               {
+                       TEST_INPUT("abcdbcdecdefdefgefghfghighijhijkijklj"
+                                  "klmklmnlmnomnopnopq"),
+                       "0x75388B16512776CC5DBA5DA1FD890150B0C6455CB4F58B"
+                               "1952522525",
+                       1
+               },
+               /* Test 3 */
+               {
+                       TEST_INPUT("a"),
+                       "0x20794655980C91D8BBB4C1EA97618A4BF03F42581948B2"
+                               "EE4EE7AD67",
+                       1000000
+               },
+               /* Test 4 */
+               {
+                       TEST_INPUT("01234567012345670123456701234567"),
+                       "0x567F69F168CD7844E65259CE658FE7AADFA25216E68ECA"
+                               "0EB7AB8262",
+                       20
+               },
+#if 0
+               /* Test 5 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT(""),
+                       "0xXXX",
+                       1
+               },
+#endif
+               /* Test 6 */
+               {
+                       TEST_INPUT("\x07"),
+                       "0x00ECD5F138422B8AD74C9799FD826C531BAD2FCABC7450"
+                               "BEE2AA8C2A",
+                       1
+               },
+#if 0
+               /* Test 7 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT(""),
+                       "0xXXX",
+                       1
+               },
+#endif
+               /* Test 8 */
+               {
+                       TEST_INPUT("\x18\x80\x40\x05\xdd\x4f\xbd\x15\x56\x29"
+                                  "\x9d\x6f\x9d\x93\xdf\x62"),
+                       "0xDF90D78AA78821C99B40BA4C966921ACCD8FFB1E98AC38"
+                               "8E56191DB1",
+                       1
+               },
+#if 0
+               /* Test 9 */
+               {
+                       TEST_INPUT(""),
+                       "0xXXX",
+                       1
+               },
+#endif
+               /* Test 10 */
+               {
+                       TEST_INPUT("\x55\xb2\x10\x07\x9c\x61\xb5\x3a\xdd\x52"
+                                  "\x06\x22\xd1\xac\x97\xd5\xcd\xbe\x8c\xb3"
+                                  "\x3a\xa0\xae\x34\x45\x17\xbe\xe4\xd7\xba"
+                                  "\x09\xab\xc8\x53\x3c\x52\x50\x88\x7a\x43"
+                                  "\xbe\xbb\xac\x90\x6c\x2e\x18\x37\xf2\x6b"
+                                  "\x36\xa5\x9a\xe3\xbe\x78\x14\xd5\x06\x89"
+                                  "\x6b\x71\x8b\x2a\x38\x3e\xcd\xac\x16\xb9"
+                                  "\x61\x25\x55\x3f\x41\x6f\xf3\x2c\x66\x74"
+                                  "\xc7\x45\x99\xa9\x00\x53\x86\xd9\xce\x11"
+                                  "\x12\x24\x5f\x48\xee\x47\x0d\x39\x6c\x1e"
+                                  "\xd6\x3b\x92\x67\x0c\xa5\x6e\xc8\x4d\xee"
+                                  "\xa8\x14\xb6\x13\x5e\xca\x54\x39\x2b\xde"
+                                  "\xdb\x94\x89\xbc\x9b\x87\x5a\x8b\xaf\x0d"
+                                  "\xc1\xae\x78\x57\x36\x91\x4a\xb7\xda\xa2"
+                                  "\x64\xbc\x07\x9d\x26\x9f\x2c\x0d\x7e\xdd"
+                                  "\xd8\x10\xa4\x26\x14\x5a\x07\x76\xf6\x7c"
+                                  "\x87\x82\x73"),
+                       "0x0B31894EC8937AD9B91BDFBCBA294D9ADEFAA18E09305E"
+                               "9F20D5C3A4",
+                       1
+               },
+               { NULL, 0, NULL, 1 }
+       };
+
+       hash_testcase_t *testcase = testcases;
+
+       while (testcase->input != NULL && testcase->result != NULL) {
+               isc_sha224_init(&sha224);
+               for(i = 0; i < testcase->repeats; i++) {
+                       isc_sha224_update(&sha224,
+                                         (const isc_uint8_t *) testcase->input,
+                                         testcase->input_len);
+               }
+               isc_sha224_final(digest, &sha224);
+               /*
+               *API inconsistency BUG HERE
+               * in order to be consistant with the other isc_hash_final
+               * functions the call should be
+               * isc_sha224_final(&sha224, digest);
+                */
+               tohexstr(digest, ISC_SHA224_DIGESTLENGTH, str);
+               ATF_CHECK_STREQ(str, testcase->result);
+
+               testcase++;
+       }
+
+}
+
+ATF_TC(isc_sha256);
+ATF_TC_HEAD(isc_sha256, tc) {
+       atf_tc_set_md_var(tc, "descr", "sha224 examples from RFC4634");
+}
+ATF_TC_BODY(isc_sha256, tc) {
+       isc_sha256_t sha256;
+
+       UNUSED(tc);
+
+       /*
+        * These are the various test vectors.  All of these are passed
+        * through the hash function and the results are compared to the
+        * result specified here.
+        */
+       hash_testcase_t testcases[] = {
+               /* Test 1 */
+               {
+                       TEST_INPUT("abc"),
+                       "0xBA7816BF8F01CFEA414140DE5DAE2223B00361A396177A"
+                               "9CB410FF61F20015AD",
+                       1
+               },
+               /* Test 2 */
+               {
+                       TEST_INPUT("abcdbcdecdefdefgefghfghighijhijkijkljk"
+                                  "lmklmnlmnomnopnopq"),
+                       "0x248D6A61D20638B8E5C026930C3E6039A33CE45964FF21"
+                               "67F6ECEDD419DB06C1",
+                       1
+               },
+               /* Test 3 */
+               {
+                       TEST_INPUT("a"),
+                       "0xCDC76E5C9914FB9281A1C7E284D73E67F1809A48A49720"
+                               "0E046D39CCC7112CD0",
+                       1000000 },
+               /* Test 4 */
+               {
+                       TEST_INPUT("01234567012345670123456701234567"),
+                       "0x594847328451BDFA85056225462CC1D867D877FB388DF0"
+                               "CE35F25AB5562BFBB5",
+                       20
+               },
+#if 0
+               /* Test 5 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT(""),
+                       "0xXXX",
+                       1
+               },
+#endif
+               /* Test 6 */
+               {
+                       TEST_INPUT("\x19"),
+                       "0x68AA2E2EE5DFF96E3355E6C7EE373E3D6A4E17F75F9518"
+                               "D843709C0C9BC3E3D4",
+                       1
+               },
+#if 0
+               /* Test 7 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT(""),
+                       "0xXXX",
+                       1
+               },
+#endif
+               /* Test 8 */
+               {
+                       TEST_INPUT("\xe3\xd7\x25\x70\xdc\xdd\x78\x7c\xe3"
+                                  "\x88\x7a\xb2\xcd\x68\x46\x52"),
+                       "0x175EE69B02BA9B58E2B0A5FD13819CEA573F3940A94F82"
+                               "5128CF4209BEABB4E8",
+                       1
+               },
+#if 0
+               /* Test 9 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT(""),
+                       "0xXXX",
+                       1
+               },
+#endif
+               /* Test 10 */
+               {
+                       TEST_INPUT("\x83\x26\x75\x4e\x22\x77\x37\x2f\x4f\xc1"
+                                  "\x2b\x20\x52\x7a\xfe\xf0\x4d\x8a\x05\x69"
+                                  "\x71\xb1\x1a\xd5\x71\x23\xa7\xc1\x37\x76"
+                                  "\x00\x00\xd7\xbe\xf6\xf3\xc1\xf7\xa9\x08"
+                                  "\x3a\xa3\x9d\x81\x0d\xb3\x10\x77\x7d\xab"
+                                  "\x8b\x1e\x7f\x02\xb8\x4a\x26\xc7\x73\x32"
+                                  "\x5f\x8b\x23\x74\xde\x7a\x4b\x5a\x58\xcb"
+                                  "\x5c\x5c\xf3\x5b\xce\xe6\xfb\x94\x6e\x5b"
+                                  "\xd6\x94\xfa\x59\x3a\x8b\xeb\x3f\x9d\x65"
+                                  "\x92\xec\xed\xaa\x66\xca\x82\xa2\x9d\x0c"
+                                  "\x51\xbc\xf9\x33\x62\x30\xe5\xd7\x84\xe4"
+                                  "\xc0\xa4\x3f\x8d\x79\xa3\x0a\x16\x5c\xba"
+                                  "\xbe\x45\x2b\x77\x4b\x9c\x71\x09\xa9\x7d"
+                                  "\x13\x8f\x12\x92\x28\x96\x6f\x6c\x0a\xdc"
+                                  "\x10\x6a\xad\x5a\x9f\xdd\x30\x82\x57\x69"
+                                  "\xb2\xc6\x71\xaf\x67\x59\xdf\x28\xeb\x39"
+                                  "\x3d\x54\xd6"),
+                       "0x97DBCA7DF46D62C8A422C941DD7E835B8AD3361763F7E9"
+                               "B2D95F4F0DA6E1CCBC",
+                       1
+               },
+               { NULL, 0, NULL, 1 }
+       };
+
+       hash_testcase_t *testcase = testcases;
+
+       while (testcase->input != NULL && testcase->result != NULL) {
+               isc_sha256_init(&sha256);
+               for(i = 0; i < testcase->repeats; i++) {
+                       isc_sha256_update(&sha256,
+                                         (const isc_uint8_t *) testcase->input,
+                                         testcase->input_len);
+               }
+               isc_sha256_final(digest, &sha256);
+               /*
+               *API inconsistency BUG HERE
+               * in order to be consistant with the other isc_hash_final
+               * functions the call should be
+               * isc_sha224_final(&sha224, digest);
+                */
+               tohexstr(digest, ISC_SHA256_DIGESTLENGTH, str);
+               ATF_CHECK_STREQ(str, testcase->result);
+
+               testcase++;
+       }
+
+}
+
+ATF_TC(isc_sha384);
+ATF_TC_HEAD(isc_sha384, tc) {
+       atf_tc_set_md_var(tc, "descr", "sha224 examples from RFC4634");
+}
+ATF_TC_BODY(isc_sha384, tc) {
+       isc_sha384_t sha384;
+
+       UNUSED(tc);
+
+       /*
+        * These are the various test vectors.  All of these are passed
+        * through the hash function and the results are compared to the
+        * result specified here.
+        */
+       hash_testcase_t testcases[] = {
+               /* Test 1 */
+               {
+                       TEST_INPUT("abc"),
+                       "0xCB00753F45A35E8BB5A03D699AC65007272C32AB0EDED1"
+                               "631A8B605A43FF5BED8086072BA1E7CC2358BAEC"
+                               "A134C825A7",
+                       1
+               },
+               /* Test 2 */
+               {
+                       TEST_INPUT("abcdefghbcdefghicdefghijdefghijkefghijkl"
+                                  "fghijklmghijklmnhijklmnoijklmnopjklmnopq"
+                                  "klmnopqrlmnopqrsmnopqrstnopqrstu"),
+                       "0x09330C33F71147E83D192FC782CD1B4753111B173B3B05"
+                               "D22FA08086E3B0F712FCC7C71A557E2DB966C3E9"
+                               "FA91746039",
+                       1
+               },
+               /* Test 3 */
+               {
+                       TEST_INPUT("a"),
+                       "0x9D0E1809716474CB086E834E310A4A1CED149E9C00F248"
+                               "527972CEC5704C2A5B07B8B3DC38ECC4EBAE97DD"
+                               "D87F3D8985",
+                       1000000
+               },
+               /* Test 4 */
+               {
+                       TEST_INPUT("01234567012345670123456701234567"),
+                       "0x2FC64A4F500DDB6828F6A3430B8DD72A368EB7F3A8322A"
+                               "70BC84275B9C0B3AB00D27A5CC3C2D224AA6B61A"
+                               "0D79FB4596",
+                       20
+               },
+#if 0
+               /* Test 5 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT(""),
+                       "0xXXX",
+                       1
+               },
+#endif
+               /* Test 6 */
+               { TEST_INPUT("\xb9"),
+                       "0xBC8089A19007C0B14195F4ECC74094FEC64F01F9092928"
+                               "2C2FB392881578208AD466828B1C6C283D2722CF"
+                               "0AD1AB6938",
+                       1
+               },
+#if 0
+               /* Test 7 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT(""),
+                       "0xXXX",
+                       1
+               },
+#endif
+               /* Test 8 */
+               {
+                       TEST_INPUT("\xa4\x1c\x49\x77\x79\xc0\x37\x5f\xf1"
+                                  "\x0a\x7f\x4e\x08\x59\x17\x39"),
+                       "0xC9A68443A005812256B8EC76B00516F0DBB74FAB26D665"
+                               "913F194B6FFB0E91EA9967566B58109CBC675CC2"
+                               "08E4C823F7",
+                       1
+               },
+#if 0
+               /* Test 9 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT(""),
+                       "0xXXX",
+                       1
+               },
+#endif
+               /* Test 10 */
+               {
+                       TEST_INPUT("\x39\x96\x69\xe2\x8f\x6b\x9c\x6d\xbc\xbb"
+                                  "\x69\x12\xec\x10\xff\xcf\x74\x79\x03\x49"
+                                  "\xb7\xdc\x8f\xbe\x4a\x8e\x7b\x3b\x56\x21"
+                                  "\xdb\x0f\x3e\x7d\xc8\x7f\x82\x32\x64\xbb"
+                                  "\xe4\x0d\x18\x11\xc9\xea\x20\x61\xe1\xc8"
+                                  "\x4a\xd1\x0a\x23\xfa\xc1\x72\x7e\x72\x02"
+                                  "\xfc\x3f\x50\x42\xe6\xbf\x58\xcb\xa8\xa2"
+                                  "\x74\x6e\x1f\x64\xf9\xb9\xea\x35\x2c\x71"
+                                  "\x15\x07\x05\x3c\xf4\xe5\x33\x9d\x52\x86"
+                                  "\x5f\x25\xcc\x22\xb5\xe8\x77\x84\xa1\x2f"
+                                  "\xc9\x61\xd6\x6c\xb6\xe8\x95\x73\x19\x9a"
+                                  "\x2c\xe6\x56\x5c\xbd\xf1\x3d\xca\x40\x38"
+                                  "\x32\xcf\xcb\x0e\x8b\x72\x11\xe8\x3a\xf3"
+                                  "\x2a\x11\xac\x17\x92\x9f\xf1\xc0\x73\xa5"
+                                  "\x1c\xc0\x27\xaa\xed\xef\xf8\x5a\xad\x7c"
+                                  "\x2b\x7c\x5a\x80\x3e\x24\x04\xd9\x6d\x2a"
+                                  "\x77\x35\x7b\xda\x1a\x6d\xae\xed\x17\x15"
+                                  "\x1c\xb9\xbc\x51\x25\xa4\x22\xe9\x41\xde"
+                                  "\x0c\xa0\xfc\x50\x11\xc2\x3e\xcf\xfe\xfd"
+                                  "\xd0\x96\x76\x71\x1c\xf3\xdb\x0a\x34\x40"
+                                  "\x72\x0e\x16\x15\xc1\xf2\x2f\xbc\x3c\x72"
+                                  "\x1d\xe5\x21\xe1\xb9\x9b\xa1\xbd\x55\x77"
+                                  "\x40\x86\x42\x14\x7e\xd0\x96"),
+                       "0x4F440DB1E6EDD2899FA335F09515AA025EE177A79F4B4A"
+                               "AF38E42B5C4DE660F5DE8FB2A5B2FBD2A3CBFFD2"
+                               "0CFF1288C0",
+                       1
+               },
+               { NULL, 0, NULL, 1 }
+       };
+
+       hash_testcase_t *testcase = testcases;
+
+       while (testcase->input != NULL && testcase->result != NULL) {
+               isc_sha384_init(&sha384);
+               for(i = 0; i < testcase->repeats; i++) {
+                       isc_sha384_update(&sha384,
+                                         (const isc_uint8_t *) testcase->input,
+                                         testcase->input_len);
+               }
+               isc_sha384_final(digest, &sha384);
+               /*
+               *API inconsistency BUG HERE
+               * in order to be consistant with the other isc_hash_final
+               * functions the call should be
+               * isc_sha224_final(&sha224, digest);
+                */
+               tohexstr(digest, ISC_SHA384_DIGESTLENGTH, str);
+               ATF_CHECK_STREQ(str, testcase->result);
+
+               testcase++;
+       }
+
+}
+
+ATF_TC(isc_sha512);
+ATF_TC_HEAD(isc_sha512, tc) {
+       atf_tc_set_md_var(tc, "descr", "sha224 examples from RFC4634");
+}
+ATF_TC_BODY(isc_sha512, tc) {
+       isc_sha512_t sha512;
+
+       UNUSED(tc);
+
+       /*
+        * These are the various test vectors.  All of these are passed
+        * through the hash function and the results are compared to the
+        * result specified here.
+        */
+       hash_testcase_t testcases[] = {
+               /* Test 1 */
+               {
+                       TEST_INPUT("abc"),
+                       "0xDDAF35A193617ABACC417349AE20413112E6FA4E89A97E"
+                               "A20A9EEEE64B55D39A2192992A274FC1A836BA3C"
+                               "23A3FEEBBD454D4423643CE80E2A9AC94FA54CA49F",
+                       1
+               },
+               /* Test 2 */
+               {
+                       TEST_INPUT("abcdefghbcdefghicdefghijdefghijkefghijkl"
+                                  "fghijklmghijklmnhijklmnoijklmnopjklmnopq"
+                                  "klmnopqrlmnopqrsmnopqrstnopqrstu"),
+                       "0x8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7F"
+                               "A17299AEADB6889018501D289E4900F7E4331B99"
+                               "DEC4B5433AC7D329EEB6DD26545E96E55B874BE909",
+                       1
+               },
+               /* Test 3 */
+               {
+                       TEST_INPUT("a"),
+                       "0xE718483D0CE769644E2E42C7BC15B4638E1F98B13B2044"
+                               "285632A803AFA973EBDE0FF244877EA60A4CB043"
+                               "2CE577C31BEB009C5C2C49AA2E4EADB217AD8CC09B",
+                       1000000
+               },
+               /* Test 4 */
+               {
+                       TEST_INPUT("01234567012345670123456701234567"),
+                       "0x89D05BA632C699C31231DED4FFC127D5A894DAD412C0E0"
+                               "24DB872D1ABD2BA8141A0F85072A9BE1E2AA04CF"
+                               "33C765CB510813A39CD5A84C4ACAA64D3F3FB7BAE9",
+                       20
+               },
+#if 0
+               /* Test 5 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT(""),
+                       "0xXXX",
+                       1
+               },
+#endif
+               /* Test 6 */
+               {
+                       TEST_INPUT("\xD0"),
+                       "0x9992202938E882E73E20F6B69E68A0A7149090423D93C8"
+                               "1BAB3F21678D4ACEEEE50E4E8CAFADA4C85A54EA"
+                               "8306826C4AD6E74CECE9631BFA8A549B4AB3FBBA15",
+                       1
+               },
+#if 0
+               /* Test 7 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT(""),
+                       "0xXXX",
+                       1
+               },
+#endif
+               /* Test 8 */
+               {
+                       TEST_INPUT("\x8d\x4e\x3c\x0e\x38\x89\x19\x14\x91\x81"
+                                  "\x6e\x9d\x98\xbf\xf0\xa0"),
+                       "0xCB0B67A4B8712CD73C9AABC0B199E9269B20844AFB75AC"
+                               "BDD1C153C9828924C3DDEDAAFE669C5FDD0BC66F"
+                               "630F6773988213EB1B16F517AD0DE4B2F0C95C90F8",
+                       1
+               },
+#if 0
+               /* Test 9 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT(""),
+                       "0xXXX",
+                       1
+               },
+#endif
+               /* Test 10 */
+               {
+                       TEST_INPUT("\xa5\x5f\x20\xc4\x11\xaa\xd1\x32\x80\x7a"
+                                  "\x50\x2d\x65\x82\x4e\x31\xa2\x30\x54\x32"
+                                  "\xaa\x3d\x06\xd3\xe2\x82\xa8\xd8\x4e\x0d"
+                                  "\xe1\xde\x69\x74\xbf\x49\x54\x69\xfc\x7f"
+                                  "\x33\x8f\x80\x54\xd5\x8c\x26\xc4\x93\x60"
+                                  "\xc3\xe8\x7a\xf5\x65\x23\xac\xf6\xd8\x9d"
+                                  "\x03\xe5\x6f\xf2\xf8\x68\x00\x2b\xc3\xe4"
+                                  "\x31\xed\xc4\x4d\xf2\xf0\x22\x3d\x4b\xb3"
+                                  "\xb2\x43\x58\x6e\x1a\x7d\x92\x49\x36\x69"
+                                  "\x4f\xcb\xba\xf8\x8d\x95\x19\xe4\xeb\x50"
+                                  "\xa6\x44\xf8\xe4\xf9\x5e\xb0\xea\x95\xbc"
+                                  "\x44\x65\xc8\x82\x1a\xac\xd2\xfe\x15\xab"
+                                  "\x49\x81\x16\x4b\xbb\x6d\xc3\x2f\x96\x90"
+                                  "\x87\xa1\x45\xb0\xd9\xcc\x9c\x67\xc2\x2b"
+                                  "\x76\x32\x99\x41\x9c\xc4\x12\x8b\xe9\xa0"
+                                  "\x77\xb3\xac\xe6\x34\x06\x4e\x6d\x99\x28"
+                                  "\x35\x13\xdc\x06\xe7\x51\x5d\x0d\x73\x13"
+                                  "\x2e\x9a\x0d\xc6\xd3\xb1\xf8\xb2\x46\xf1"
+                                  "\xa9\x8a\x3f\xc7\x29\x41\xb1\xe3\xbb\x20"
+                                  "\x98\xe8\xbf\x16\xf2\x68\xd6\x4f\x0b\x0f"
+                                  "\x47\x07\xfe\x1e\xa1\xa1\x79\x1b\xa2\xf3"
+                                  "\xc0\xc7\x58\xe5\xf5\x51\x86\x3a\x96\xc9"
+                                  "\x49\xad\x47\xd7\xfb\x40\xd2"),
+                 "0xC665BEFB36DA189D78822D10528CBF3B12B3EEF7260399"
+                         "09C1A16A270D48719377966B957A878E72058477"
+                         "9A62825C18DA26415E49A7176A894E7510FD1451F5",
+                 1
+               },
+               { NULL, 0, NULL, 1 }
+       };
+
+       hash_testcase_t *testcase = testcases;
+
+       while (testcase->input != NULL && testcase->result != NULL) {
+               isc_sha512_init(&sha512);
+               for(i = 0; i < testcase->repeats; i++) {
+                       isc_sha512_update(&sha512,
+                                         (const isc_uint8_t *) testcase->input,
+                                         testcase->input_len);
+               }
+               isc_sha512_final(digest, &sha512);
+               /*
+               *API inconsistency BUG HERE
+               * in order to be consistant with the other isc_hash_final
+               * functions the call should be
+               * isc_sha224_final(&sha224, digest);
+                */
+               tohexstr(digest, ISC_SHA512_DIGESTLENGTH, str);
+               ATF_CHECK_STREQ(str, testcase->result);
+
+               testcase++;
+       }
+
+}
+
+ATF_TC(isc_md5);
+ATF_TC_HEAD(isc_md5, tc) {
+       atf_tc_set_md_var(tc, "descr", "md5 example from RFC1321");
+}
+ATF_TC_BODY(isc_md5, tc) {
+       isc_md5_t md5;
+
+       UNUSED(tc);
+
+       /*
+        * These are the various test vectors.  All of these are passed
+        * through the hash function and the results are compared to the
+        * result specified here.
+        */
+       hash_testcase_t testcases[] = {
+               {
+                       TEST_INPUT(""),
+                       "0xD41D8CD98F00B204E9800998ECF8427E",
+                       1
+               },
+               {
+                       TEST_INPUT("a"),
+                       "0x0CC175B9C0F1B6A831C399E269772661",
+                       1
+               },
+               {
+                       TEST_INPUT("abc"),
+                       "0x900150983CD24FB0D6963F7D28E17F72",
+                       1
+               },
+               {
+                       TEST_INPUT("message digest"),
+                       "0xF96B697D7CB7938D525A2F31AAF161D0",
+                       1
+               },
+               {
+                       TEST_INPUT("abcdefghijklmnopqrstuvwxyz"),
+                       "0xC3FCD3D76192E4007DFB496CCA67E13B",
+                       1
+               },
+               {
+                       TEST_INPUT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm"
+                                  "nopqrstuvwxyz0123456789"),
+                       "0xD174AB98D277D9F5A5611C2C9F419D9F",
+                       1
+               },
+               {
+                       TEST_INPUT("123456789012345678901234567890123456789"
+                                  "01234567890123456789012345678901234567890"),
+                       "0x57EDF4A22BE3C955AC49DA2E2107B67A",
+                       1
+               },
+               { NULL, 0, NULL, 1 }
+       };
+
+       hash_testcase_t *testcase = testcases;
+
+       while (testcase->input != NULL && testcase->result != NULL) {
+               isc_md5_init(&md5);
+               for(i = 0; i < testcase->repeats; i++) {
+                       isc_md5_update(&md5,
+                                      (const isc_uint8_t *) testcase->input,
+                                      testcase->input_len);
+               }
+               isc_md5_final(&md5, digest);
+               tohexstr(digest, ISC_MD5_DIGESTLENGTH, str);
+               ATF_CHECK_STREQ(str, testcase->result);
+
+               testcase++;
+       }
+}
+
+/* HMAC-SHA1 test */
+ATF_TC(isc_hmacsha1);
+ATF_TC_HEAD(isc_hmacsha1, tc) {
+       atf_tc_set_md_var(tc, "descr", "HMAC-SHA1 examples from RFC2104");
+}
+ATF_TC_BODY(isc_hmacsha1, tc) {
+       isc_hmacsha1_t hmacsha1;
+
+       UNUSED(tc);
+       /*
+        * These are the various test vectors.  All of these are passed
+        * through the hash function and the results are compared to the
+        * result specified here.
+        */
+       hash_testcase_t testcases[] = {
+               /* Test 1 */
+               {
+                       TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"),
+                       "0xB617318655057264E28BC0B6FB378C8EF146BE00",
+                       1
+               },
+               /* Test 2 */
+               {
+                       TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61"
+                                  "\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20"
+                                  "\x6e\x6f\x74\x68\x69\x6e\x67\x3f"),
+                       "0xEFFCDF6AE5EB2FA2D27416D5F184DF9C259A7C79",
+                       1
+               },
+               /* Test 3 */
+               {
+                       TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"),
+                       "0x125D7342B9AC11CD91A39AF48AA17B4F63F175D3",
+                       1
+               },
+               /* Test 4 */
+               {
+                       TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"),
+                       "0x4C9007F4026250C6BC8414F9BF50C86C2D7235DA",
+                       1
+               },
+#if 0
+               /* Test 5 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT("Test With Truncation"),
+                       "0x4C1A03424B55E07FE7F27BE1",
+                       1
+               },
+#endif
+               /* Test 6 */
+               {
+                       TEST_INPUT("Test Using Larger Than Block-Size Key - "
+                                  "Hash Key First"),
+                       "0xAA4AE5E15272D00E95705637CE8A3B55ED402112", 1 },
+               /* Test 7 */
+               {
+                       TEST_INPUT("Test Using Larger Than Block-Size Key and "
+                                  "Larger Than One Block-Size Data"),
+                       "0xE8E99D0F45237D786D6BBAA7965C7808BBFF1A91",
+                       1
+               },
+               { NULL, 0, NULL, 1 }
+       };
+
+       hash_testcase_t *testcase = testcases;
+
+       hash_test_key_t test_keys[] = {
+               /* Key 1 */
+               { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+                 "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 20 },
+               /* Key 2 */
+               { "Jefe", 4 },
+               /* Key 3 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 20 },
+               /* Key 4 */
+               { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a"
+                 "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
+                 "\x15\x16\x17\x18\x19", 25 },
+#if 0
+               /* Key 5 */
+               { "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
+                 "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", 20 },
+#endif
+               /* Key 6 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80 },
+               /* Key 7 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 80 },
+               { "", 0 }
+       };
+
+       hash_test_key_t *test_key = test_keys;
+
+       while (testcase->input != NULL && testcase->result != NULL) {
+               memcpy(buffer, test_key->key, test_key->len);
+               isc_hmacsha1_init(&hmacsha1, buffer, test_key->len);
+               isc_hmacsha1_update(&hmacsha1,
+                                   (const isc_uint8_t *) testcase->input,
+                                   testcase->input_len);
+               isc_hmacsha1_sign(&hmacsha1, digest, ISC_SHA1_DIGESTLENGTH);
+               tohexstr(digest, ISC_SHA1_DIGESTLENGTH, str);
+               ATF_CHECK_STREQ(str, testcase->result);
+
+               testcase++;
+               test_key++;
+       }
+}
+
+/* HMAC-SHA224 test */
+ATF_TC(isc_hmacsha224);
+ATF_TC_HEAD(isc_hmacsha224, tc) {
+       atf_tc_set_md_var(tc, "descr", "HMAC-SHA224 examples from RFC4634");
+}
+ATF_TC_BODY(isc_hmacsha224, tc) {
+       isc_hmacsha224_t hmacsha224;
+
+       UNUSED(tc);
+
+       /*
+        * These are the various test vectors.  All of these are passed
+        * through the hash function and the results are compared to the
+        * result specified here.
+        */
+       hash_testcase_t testcases[] = {
+               /* Test 1 */
+               {
+                       TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"),
+                       "0x896FB1128ABBDF196832107CD49DF33F47B4B1169912BA"
+                               "4F53684B22",
+                       1
+               },
+               /* Test 2 */
+               {
+                       TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61"
+                                  "\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20"
+                                  "\x6e\x6f\x74\x68\x69\x6e\x67\x3f"),
+                       "0xA30E01098BC6DBBF45690F3A7E9E6D0F8BBEA2A39E61480"
+                               "08FD05E44",
+                       1
+               },
+               /* Test 3 */
+               {
+                       TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"),
+                       "0x7FB3CB3588C6C1F6FFA9694D7D6AD2649365B0C1F65D69"
+                               "D1EC8333EA",
+                       1
+               },
+               /* Test 4 */
+               {
+                       TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"),
+                       "0x6C11506874013CAC6A2ABC1BB382627CEC6A90D86EFC01"
+                               "2DE7AFEC5A",
+                       1
+               },
+#if 0
+               /* Test 5 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT("Test With Truncation"),
+                       "0x4C1A03424B55E07FE7F27BE1",
+                       1
+               },
+#endif
+               /* Test 6 */
+               {
+                       TEST_INPUT("Test Using Larger Than Block-Size Key - "
+                                  "Hash Key First"),
+                       "0x95E9A0DB962095ADAEBE9B2D6F0DBCE2D499F112F2D2B7"
+                               "273FA6870E",
+                       1
+               },
+               /* Test 7 */
+               {
+                       TEST_INPUT("\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20"
+                                  "\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67"
+                                  "\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20"
+                                  "\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b"
+                                  "\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20"
+                                  "\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67"
+                                  "\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c"
+                                  "\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64"
+                                  "\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b"
+                                  "\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74"
+                                  "\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65"
+                                  "\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62"
+                                  "\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20"
+                                  "\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41"
+                                  "\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68"
+                                  "\x6d\x2e"),
+                       "0x3A854166AC5D9F023F54D517D0B39DBD946770DB9C2B95"
+                               "C9F6F565D1",
+                       1
+               },
+               { NULL, 0, NULL, 1 }
+       };
+
+       hash_testcase_t *testcase = testcases;
+
+       hash_test_key_t test_keys[] = {
+               /* Key 1 */
+               { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+                 "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 20 },
+               /* Key 2 */
+               { "Jefe", 4 },
+               /* Key 3 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 20 },
+               /* Key 4 */
+               { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a"
+                 "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
+                 "\x15\x16\x17\x18\x19", 25 },
+#if 0
+               /* Key 5 */
+               { "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
+                 "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", 20 },
+#endif
+               /* Key 6 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 131 },
+               /* Key 7 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 131 },
+               { "", 0 }
+       };
+
+       hash_test_key_t *test_key = test_keys;
+
+       while (testcase->input != NULL && testcase->result != NULL) {
+               memcpy(buffer, test_key->key, test_key->len);
+               isc_hmacsha224_init(&hmacsha224, buffer, test_key->len);
+               isc_hmacsha224_update(&hmacsha224,
+                                     (const isc_uint8_t *) testcase->input,
+                                     testcase->input_len);
+               isc_hmacsha224_sign(&hmacsha224, digest, ISC_SHA224_DIGESTLENGTH);
+               tohexstr(digest, ISC_SHA224_DIGESTLENGTH, str);
+               ATF_CHECK_STREQ(str, testcase->result);
+
+               testcase++;
+               test_key++;
+       }
+}
+
+/* HMAC-SHA256 test */
+ATF_TC(isc_hmacsha256);
+ATF_TC_HEAD(isc_hmacsha256, tc) {
+       atf_tc_set_md_var(tc, "descr", "HMAC-SHA256 examples from RFC4634");
+}
+ATF_TC_BODY(isc_hmacsha256, tc) {
+       isc_hmacsha256_t hmacsha256;
+
+       UNUSED(tc);
+
+       /*
+        * These are the various test vectors.  All of these are passed
+        * through the hash function and the results are compared to the
+        * result specified here.
+        */
+       hash_testcase_t testcases[] = {
+               /* Test 1 */
+               {
+                       TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"),
+                       "0xB0344C61D8DB38535CA8AFCEAF0BF12B881DC200C9833D"
+                               "A726E9376C2E32CFF7",
+                       1
+               },
+               /* Test 2 */
+               {
+                       TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61"
+                                  "\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20"
+                                  "\x6e\x6f\x74\x68\x69\x6e\x67\x3f"),
+                       "0x5BDCC146BF60754E6A042426089575C75A003F089D2739"
+                               "839DEC58B964EC3843",
+                       1
+               },
+               /* Test 3 */
+               {
+                       TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"),
+                       "0x773EA91E36800E46854DB8EBD09181A72959098B3EF8C1"
+                               "22D9635514CED565FE",
+                       1
+               },
+               /* Test 4 */
+               {
+                       TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"),
+                       "0x82558A389A443C0EA4CC819899F2083A85F0FAA3E578F8"
+                               "077A2E3FF46729665B",
+                       1
+               },
+#if 0
+               /* Test 5 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT("Test With Truncation"),
+                       "0x4C1A03424B55E07FE7F27BE1",
+                       1
+               },
+#endif
+               /* Test 6 */
+               {
+                       TEST_INPUT("Test Using Larger Than Block-Size Key - "
+                                  "Hash Key First"),
+                       "0x60E431591EE0B67F0D8A26AACBF5B77F8E0BC6213728C5"
+                               "140546040F0EE37F54",
+                       1
+               },
+               /* Test 7 */
+               {
+                       TEST_INPUT("\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20"
+                                  "\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67"
+                                  "\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20"
+                                  "\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b"
+                                  "\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20"
+                                  "\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67"
+                                  "\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c"
+                                  "\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64"
+                                  "\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b"
+                                  "\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74"
+                                  "\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65"
+                                  "\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62"
+                                  "\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20"
+                                  "\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41"
+                                  "\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68"
+                                  "\x6d\x2e"),
+                       "0x9B09FFA71B942FCB27635FBCD5B0E944BFDC63644F0713"
+                               "938A7F51535C3A35E2",
+                       1
+               },
+               { NULL, 0, NULL, 1 }
+       };
+
+       hash_testcase_t *testcase = testcases;
+
+       hash_test_key_t test_keys[] = {
+               /* Key 1 */
+               { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+                 "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 20 },
+               /* Key 2 */
+               { "Jefe", 4 },
+               /* Key 3 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 20 },
+               /* Key 4 */
+               { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a"
+                 "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
+                 "\x15\x16\x17\x18\x19", 25 },
+#if 0
+               /* Key 5 */
+               { "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
+                 "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", 20 },
+#endif
+               /* Key 6 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 131 },
+               /* Key 7 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 131 },
+               { "", 0 }
+       };
+
+       hash_test_key_t *test_key = test_keys;
+
+       while (testcase->input != NULL && testcase->result != NULL) {
+               memcpy(buffer, test_key->key, test_key->len);
+               isc_hmacsha256_init(&hmacsha256, buffer, test_key->len);
+               isc_hmacsha256_update(&hmacsha256,
+                                     (const isc_uint8_t *) testcase->input,
+                                     testcase->input_len);
+               isc_hmacsha256_sign(&hmacsha256, digest, ISC_SHA256_DIGESTLENGTH);
+               tohexstr(digest, ISC_SHA256_DIGESTLENGTH, str);
+               ATF_CHECK_STREQ(str, testcase->result);
+
+               testcase++;
+               test_key++;
+       }
+}
+
+/* HMAC-SHA384 test */
+ATF_TC(isc_hmacsha384);
+ATF_TC_HEAD(isc_hmacsha384, tc) {
+       atf_tc_set_md_var(tc, "descr", "HMAC-SHA384 examples from RFC4634");
+}
+ATF_TC_BODY(isc_hmacsha384, tc) {
+       isc_hmacsha384_t hmacsha384;
+
+       UNUSED(tc);
+
+       /*
+        * These are the various test vectors.  All of these are passed
+        * through the hash function and the results are compared to the
+        * result specified here.
+        */
+       hash_testcase_t testcases[] = {
+               /* Test 1 */
+               {
+                       TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"),
+                       "0xAFD03944D84895626B0825F4AB46907F15F9DADBE4101E"
+                               "C682AA034C7CEBC59CFAEA9EA9076EDE7F4AF152"
+                               "E8B2FA9CB6",
+                       1
+               },
+               /* Test 2 */
+               {
+                       TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61"
+                                  "\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20"
+                                  "\x6e\x6f\x74\x68\x69\x6e\x67\x3f"),
+                       "0xAF45D2E376484031617F78D2B58A6B1B9C7EF464F5A01B"
+                               "47E42EC3736322445E8E2240CA5E69E2C78B3239"
+                               "ECFAB21649",
+                       1
+               },
+               /* Test 3 */
+               {
+                       TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"),
+                       "0x88062608D3E6AD8A0AA2ACE014C8A86F0AA635D947AC9F"
+                               "EBE83EF4E55966144B2A5AB39DC13814B94E3AB6"
+                               "E101A34F27",
+                       1
+               },
+               /* Test 4 */
+               {
+                       TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"),
+                       "0x3E8A69B7783C25851933AB6290AF6CA77A998148085000"
+                               "9CC5577C6E1F573B4E6801DD23C4A7D679CCF8A3"
+                               "86C674CFFB",
+                       1
+               },
+#if 0
+               /* Test 5 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT("Test With Truncation"),
+                       "0x4C1A03424B55E07FE7F27BE1",
+                       1
+               },
+#endif
+               /* Test 6 */
+               {
+                       TEST_INPUT("Test Using Larger Than Block-Size Key - "
+                                  "Hash Key First"),
+                       "0x4ECE084485813E9088D2C63A041BC5B44F9EF1012A2B58"
+                               "8F3CD11F05033AC4C60C2EF6AB4030FE8296248D"
+                               "F163F44952",
+                       1
+               },
+               /* Test 7 */
+               {
+                       TEST_INPUT("\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20"
+                                  "\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67"
+                                  "\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20"
+                                  "\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b"
+                                  "\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20"
+                                  "\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67"
+                                  "\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c"
+                                  "\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64"
+                                  "\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b"
+                                  "\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74"
+                                  "\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65"
+                                  "\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62"
+                                  "\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20"
+                                  "\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41"
+                                  "\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68"
+                                  "\x6d\x2e"),
+                       "0x6617178E941F020D351E2F254E8FD32C602420FEB0B8FB"
+                               "9ADCCEBB82461E99C5A678CC31E799176D3860E6"
+                               "110C46523E",
+                       1
+               },
+               { NULL, 0, NULL, 1 }
+       };
+
+       hash_testcase_t *testcase = testcases;
+
+       hash_test_key_t test_keys[] = {
+               /* Key 1 */
+               { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+                 "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 20 },
+               /* Key 2 */
+               { "Jefe", 4 },
+               /* Key 3 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 20 },
+               /* Key 4 */
+               { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a"
+                 "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
+                 "\x15\x16\x17\x18\x19", 25 },
+#if 0
+               /* Key 5 */
+               { "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
+                 "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", 20 },
+#endif
+               /* Key 6 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 131 },
+               /* Key 7 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 131 },
+               { "", 0 }
+       };
+
+       hash_test_key_t *test_key = test_keys;
+
+       while (testcase->input != NULL && testcase->result != NULL) {
+               memcpy(buffer, test_key->key, test_key->len);
+               isc_hmacsha384_init(&hmacsha384, buffer, test_key->len);
+               isc_hmacsha384_update(&hmacsha384,
+                                     (const isc_uint8_t *) testcase->input,
+                                     testcase->input_len);
+               isc_hmacsha384_sign(&hmacsha384, digest, ISC_SHA384_DIGESTLENGTH);
+               tohexstr(digest, ISC_SHA384_DIGESTLENGTH, str);
+               ATF_CHECK_STREQ(str, testcase->result);
+
+               testcase++;
+               test_key++;
+       }
+}
+
+/* HMAC-SHA512 test */
+ATF_TC(isc_hmacsha512);
+ATF_TC_HEAD(isc_hmacsha512, tc) {
+       atf_tc_set_md_var(tc, "descr", "HMAC-SHA512 examples from RFC4634");
+}
+ATF_TC_BODY(isc_hmacsha512, tc) {
+       isc_hmacsha512_t hmacsha512;
+
+       UNUSED(tc);
+
+       /*
+        * These are the various test vectors.  All of these are passed
+        * through the hash function and the results are compared to the
+        * result specified here.
+        */
+       hash_testcase_t testcases[] = {
+               /* Test 1 */
+               {
+                       TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"),
+                       "0x87AA7CDEA5EF619D4FF0B4241A1D6CB02379F4E2CE4EC2"
+                               "787AD0B30545E17CDEDAA833B7D6B8A702038B27"
+                               "4EAEA3F4E4BE9D914EEB61F1702E696C203A126854",
+                       1
+               },
+               /* Test 2 */
+               {
+                       TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61"
+                                  "\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20"
+                                  "\x6e\x6f\x74\x68\x69\x6e\x67\x3f"),
+                       "0x164B7A7BFCF819E2E395FBE73B56E0A387BD64222E831F"
+                               "D610270CD7EA2505549758BF75C05A994A6D034F"
+                               "65F8F0E6FDCAEAB1A34D4A6B4B636E070A38BCE737",
+                       1
+               },
+               /* Test 3 */
+               {
+                       TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"),
+                       "0xFA73B0089D56A284EFB0F0756C890BE9B1B5DBDD8EE81A"
+                               "3655F83E33B2279D39BF3E848279A722C806B485"
+                               "A47E67C807B946A337BEE8942674278859E13292FB",
+                       1
+               },
+               /* Test 4 */
+               {
+                       TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"),
+                       "0xB0BA465637458C6990E5A8C5F61D4AF7E576D97FF94B87"
+                               "2DE76F8050361EE3DBA91CA5C11AA25EB4D67927"
+                               "5CC5788063A5F19741120C4F2DE2ADEBEB10A298DD",
+                       1
+               },
+#if 0
+               /* Test 5 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT("Test With Truncation"),
+                       "0x4C1A03424B55E07FE7F27BE1",
+                       1
+               },
+#endif
+               /* Test 6 */
+               {
+                       TEST_INPUT("Test Using Larger Than Block-Size Key - "
+                                  "Hash Key First"),
+                       "0x80B24263C7C1A3EBB71493C1DD7BE8B49B46D1F41B4AEE"
+                               "C1121B013783F8F3526B56D037E05F2598BD0FD2"
+                               "215D6A1E5295E64F73F63F0AEC8B915A985D786598",
+                       1
+               },
+               /* Test 7 */
+               {
+                       TEST_INPUT("\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20"
+                                  "\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67"
+                                  "\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20"
+                                  "\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b"
+                                  "\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20"
+                                  "\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67"
+                                  "\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c"
+                                  "\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64"
+                                  "\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b"
+                                  "\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74"
+                                  "\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65"
+                                  "\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62"
+                                  "\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20"
+                                  "\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41"
+                                  "\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68"
+                                  "\x6d\x2e"),
+                       "0xE37B6A775DC87DBAA4DFA9F96E5E3FFDDEBD71F8867289"
+                               "865DF5A32D20CDC944B6022CAC3C4982B10D5EEB"
+                               "55C3E4DE15134676FB6DE0446065C97440FA8C6A58",
+                       1
+               },
+               { NULL, 0, NULL, 1 }
+       };
+
+       hash_testcase_t *testcase = testcases;
+
+       hash_test_key_t test_keys[] = {
+               /* Key 1 */
+               { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+                 "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 20 },
+               /* Key 2 */
+               { "Jefe", 4 },
+               /* Key 3 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 20 },
+               /* Key 4 */
+               { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a"
+                 "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
+                 "\x15\x16\x17\x18\x19", 25 },
+#if 0
+               /* Key 5 */
+               { "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
+                 "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", 20 },
+#endif
+               /* Key 6 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 131 },
+               /* Key 7 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 131 },
+               { "", 0 }
+       };
+
+       hash_test_key_t *test_key = test_keys;
+
+       while (testcase->input != NULL && testcase->result != NULL) {
+               memcpy(buffer, test_key->key, test_key->len);
+               isc_hmacsha512_init(&hmacsha512, buffer, test_key->len);
+               isc_hmacsha512_update(&hmacsha512,
+                                     (const isc_uint8_t *) testcase->input,
+                                     testcase->input_len);
+               isc_hmacsha512_sign(&hmacsha512, digest, ISC_SHA512_DIGESTLENGTH);
+               tohexstr(digest, ISC_SHA512_DIGESTLENGTH, str);
+               ATF_CHECK_STREQ(str, testcase->result);
+
+               testcase++;
+               test_key++;
+       }
+}
+
+
+/* HMAC-MD5 Test */
+ATF_TC(isc_hmacmd5);
+ATF_TC_HEAD(isc_hmacmd5, tc) {
+       atf_tc_set_md_var(tc, "descr", "HMAC-MD5 examples from RFC2104");
+}
+ATF_TC_BODY(isc_hmacmd5, tc) {
+       isc_hmacmd5_t hmacmd5;
+
+       UNUSED(tc);
+
+       /*
+        * These are the various test vectors.  All of these are passed
+        * through the hash function and the results are compared to the
+        * result specified here.
+        */
+       hash_testcase_t testcases[] = {
+               /* Test 1 */
+               {
+                       TEST_INPUT("\x48\x69\x20\x54\x68\x65\x72\x65"),
+                       "0x9294727A3638BB1C13F48EF8158BFC9D",
+                       1
+               },
+               /* Test 2 */
+               {
+                       TEST_INPUT("\x77\x68\x61\x74\x20\x64\x6f\x20\x79"
+                                  "\x61\x20\x77\x61\x6e\x74\x20\x66\x6f"
+                                  "\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f"),
+                       "0x750C783E6AB0B503EAA86E310A5DB738", 1
+               },
+               /* Test 3 */
+               {
+                       TEST_INPUT("\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+                                  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"),
+                       "0x56BE34521D144C88DBB8C733F0E8B3F6",
+                       1
+               },
+               /* Test 4 */
+               {
+                       TEST_INPUT("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+                                  "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"),
+                       "0x697EAF0ACA3A3AEA3A75164746FFAA79",
+                       1
+               },
+#if 0
+               /* Test 5 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT("Test With Truncation"),
+                       "0x4C1A03424B55E07FE7F27BE1",
+                       1
+               },
+               /* Test 6 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT("Test Using Larger Than Block-Size Key - "
+                                  "Hash Key First"),
+                       "0xAA4AE5E15272D00E95705637CE8A3B55ED402112",
+                       1
+                },
+               /* Test 7 -- unimplemented optional functionality */
+               {
+                       TEST_INPUT("Test Using Larger Than Block-Size Key and "
+                                  "Larger Than One Block-Size Data"),
+                       "0xE8E99D0F45237D786D6BBAA7965C7808BBFF1A91",
+                       1
+               },
+#endif
+               { NULL, 0, NULL, 1 }
+       };
+
+       hash_testcase_t *testcase = testcases;
+
+       hash_test_key_t test_keys[] = {
+               /* Key 1 */
+               { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+                 "\x0b\x0b\x0b\x0b\x0b\x0b", 16 },
+               /* Key 2 */
+               { "Jefe", 4 },
+               /* Key 3 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa", 16 },
+               /* Key 4 */
+               { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a"
+                 "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
+                 "\x15\x16\x17\x18\x19", 25 },
+#if 0
+               /* Key 5 */
+               { "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
+                 "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", 20 },
+               /* Key 6 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 131 },
+               /* Key 7 */
+               { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+                 "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 131 },
+#endif
+               { "", 0 }
+       };
+
+       hash_test_key_t *test_key = test_keys;
+
+       while (testcase->input != NULL && testcase->result != NULL) {
+               memcpy(buffer, test_key->key, test_key->len);
+               isc_hmacmd5_init(&hmacmd5, buffer, test_key->len);
+               isc_hmacmd5_update(&hmacmd5,
+                                  (const isc_uint8_t *) testcase->input,
+                                  testcase->input_len);
+               isc_hmacmd5_sign(&hmacmd5, digest);
+               tohexstr(digest, ISC_MD5_DIGESTLENGTH, str);
+               ATF_CHECK_STREQ(str, testcase->result);
+
+               testcase++;
+               test_key++;
+       }
+}
+
+/*
+ * Main
+ */
+ATF_TP_ADD_TCS(tp) {
+       ATF_TP_ADD_TC(tp, isc_hmacmd5);
+       ATF_TP_ADD_TC(tp, isc_hmacsha1);
+       ATF_TP_ADD_TC(tp, isc_hmacsha224);
+       ATF_TP_ADD_TC(tp, isc_hmacsha256);
+       ATF_TP_ADD_TC(tp, isc_hmacsha384);
+       ATF_TP_ADD_TC(tp, isc_hmacsha512);
+       ATF_TP_ADD_TC(tp, isc_md5);
+       ATF_TP_ADD_TC(tp, isc_sha1);
+       ATF_TP_ADD_TC(tp, isc_sha224);
+       ATF_TP_ADD_TC(tp, isc_sha256);
+       ATF_TP_ADD_TC(tp, isc_sha384);
+       ATF_TP_ADD_TC(tp, isc_sha512);
+       return (atf_no_error());
+}
+
diff --git a/lib/isc/tests/isctest.c b/lib/isc/tests/isctest.c
new file mode 100644 (file)
index 0000000..e118bbf
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <time.h>
+
+#include <isc/app.h>
+#include <isc/buffer.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/os.h>
+#include <isc/socket.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include "isctest.h"
+
+isc_mem_t *mctx = NULL;
+isc_entropy_t *ectx = NULL;
+isc_log_t *lctx = NULL;
+isc_taskmgr_t *taskmgr = NULL;
+isc_timermgr_t *timermgr = NULL;
+isc_socketmgr_t *socketmgr = NULL;
+int ncpus;
+
+static isc_boolean_t hash_active = ISC_FALSE;
+
+/*
+ * Logging categories: this needs to match the list in bin/named/log.c.
+ */
+static isc_logcategory_t categories[] = {
+               { "",                0 },
+               { "client",          0 },
+               { "network",         0 },
+               { "update",          0 },
+               { "queries",         0 },
+               { "unmatched",       0 },
+               { "update-security", 0 },
+               { "query-errors",    0 },
+               { NULL,              0 }
+};
+
+static void
+cleanup_managers() {
+       if (socketmgr != NULL)
+               isc_socketmgr_destroy(&socketmgr);
+       if (taskmgr != NULL)
+               isc_taskmgr_destroy(&taskmgr);
+       if (timermgr != NULL)
+               isc_timermgr_destroy(&timermgr);
+}
+
+static isc_result_t
+create_managers() {
+       isc_result_t result;
+#ifdef ISC_PLATFORM_USETHREADS
+       ncpus = isc_os_ncpus();
+#else
+       ncpus = 1;
+#endif
+
+       CHECK(isc_taskmgr_create(mctx, ncpus, 0, &taskmgr));
+       CHECK(isc_timermgr_create(mctx, &timermgr));
+       CHECK(isc_socketmgr_create(mctx, &socketmgr));
+       return (ISC_R_SUCCESS);
+
+  cleanup:
+       cleanup_managers();
+       return (result);
+}
+
+isc_result_t
+isc_test_begin(FILE *logfile, isc_boolean_t start_managers) {
+       isc_result_t result;
+
+       isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+       CHECK(isc_mem_create(0, 0, &mctx));
+       CHECK(isc_entropy_create(mctx, &ectx));
+
+       CHECK(isc_hash_create(mctx, ectx, 255));
+       hash_active = ISC_TRUE;
+
+       if (logfile != NULL) {
+               isc_logdestination_t destination;
+               isc_logconfig_t *logconfig = NULL;
+
+               CHECK(isc_log_create(mctx, &lctx, &logconfig));
+               isc_log_registercategories(lctx, categories);
+               isc_log_setcontext(lctx);
+
+               destination.file.stream = logfile;
+               destination.file.name = NULL;
+               destination.file.versions = ISC_LOG_ROLLNEVER;
+               destination.file.maximum_size = 0;
+               CHECK(isc_log_createchannel(logconfig, "stderr",
+                                           ISC_LOG_TOFILEDESC,
+                                           ISC_LOG_DYNAMIC,
+                                           &destination, 0));
+               CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL));
+       }
+
+#ifdef ISC_PLATFORM_USETHREADS
+       ncpus = isc_os_ncpus();
+#else
+       ncpus = 1;
+#endif
+
+       if (start_managers)
+               CHECK(create_managers());
+
+       return (ISC_R_SUCCESS);
+
+  cleanup:
+       isc_test_end();
+       return (result);
+}
+
+void
+isc_test_end() {
+       if (taskmgr != NULL)
+               isc_taskmgr_destroy(&taskmgr);
+       if (lctx != NULL)
+               isc_log_destroy(&lctx);
+       if (hash_active) {
+               isc_hash_destroy();
+               hash_active = ISC_FALSE;
+       }
+       if (ectx != NULL)
+               isc_entropy_detach(&ectx);
+
+       cleanup_managers();
+
+       if (mctx != NULL)
+               isc_mem_destroy(&mctx);
+}
+
+/*
+ * Sleep for 'usec' microseconds.
+ */
+void
+isc_test_nap(isc_uint32_t usec) {
+#ifdef HAVE_NANOSLEEP
+       struct timespec ts;
+
+       ts.tv_sec = usec / 1000000;
+       ts.tv_nsec = (usec % 1000000) * 1000;
+       nanosleep(&ts, NULL);
+#elif HAVE_USLEEP
+       usleep(usec);
+#else
+       /*
+        * No fractional-second sleep function is available, so we
+        * round up to the nearest second and sleep instead
+        */
+       sleep((usec / 1000000) + 1);
+#endif
+}
diff --git a/lib/isc/tests/isctest.h b/lib/isc/tests/isctest.h
new file mode 100644 (file)
index 0000000..03423c8
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/buffer.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#define CHECK(r) \
+       do { \
+               result = (r); \
+               if (result != ISC_R_SUCCESS) \
+                       goto cleanup; \
+       } while (0)
+
+extern isc_mem_t *mctx;
+extern isc_entropy_t *ectx;
+extern isc_log_t *lctx;
+extern isc_taskmgr_t *taskmgr;
+isc_timermgr_t *timermgr;
+isc_socketmgr_t *socketmgr;
+extern int ncpus;
+
+isc_result_t
+isc_test_begin(FILE *logfile, isc_boolean_t start_managers);
+
+void
+isc_test_end(void);
+
+void
+isc_test_nap(isc_uint32_t usec);
diff --git a/lib/isc/tests/queue_test.c b/lib/isc/tests/queue_test.c
new file mode 100644 (file)
index 0000000..74620fe
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <atf-c.h>
+
+#include <unistd.h>
+#include <time.h>
+
+#include <isc/queue.h>
+
+#include "isctest.h"
+
+typedef struct item {
+       int                     value;
+       ISC_QLINK(item_t)       qlink;
+} item_t;
+
+typedef ISC_QUEUE(item_t) item_queue_t;
+
+static void
+item_init(item_t *item, int value) {
+       item->value = value;
+       ISC_QLINK_INIT(item, qlink);
+}
+
+/*
+ * Individual unit tests
+ */
+
+/* Test UDP sendto/recv (IPv4) */
+ATF_TC(queue_valid);
+ATF_TC_HEAD(queue_valid, tc) {
+       atf_tc_set_md_var(tc, "descr", "Check queue validity");
+}
+ATF_TC_BODY(queue_valid, tc) {
+       isc_result_t result;
+       item_queue_t queue;
+       item_t one, two, three, four, five;
+       item_t *p;
+
+       UNUSED(tc);
+
+       ISC_QUEUE_INIT(queue, qlink);
+
+       item_init(&one, 1);
+       item_init(&two, 2);
+       item_init(&three, 3);
+       item_init(&four, 4);
+       item_init(&five, 5);
+
+       result = isc_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       ATF_CHECK(ISC_QUEUE_EMPTY(queue));
+
+       ISC_QUEUE_POP(queue, qlink, p);
+       ATF_CHECK(p == NULL);
+
+       ATF_CHECK(! ISC_QLINK_LINKED(&one, qlink));
+       ISC_QUEUE_PUSH(queue, &one, qlink);
+       ATF_CHECK(ISC_QLINK_LINKED(&one, qlink));
+
+       ATF_CHECK(! ISC_QUEUE_EMPTY(queue));
+
+       ISC_QUEUE_POP(queue, qlink, p);
+       ATF_REQUIRE(p != NULL);
+       ATF_CHECK_EQ(p->value, 1);
+       ATF_CHECK(ISC_QUEUE_EMPTY(queue));
+       ATF_CHECK(! ISC_QLINK_LINKED(p, qlink));
+
+       ISC_QUEUE_PUSH(queue, p, qlink);
+       ATF_CHECK(! ISC_QUEUE_EMPTY(queue));
+       ATF_CHECK(ISC_QLINK_LINKED(p, qlink));
+
+       ATF_CHECK(! ISC_QLINK_LINKED(&two, qlink));
+       ISC_QUEUE_PUSH(queue, &two, qlink);
+       ATF_CHECK(ISC_QLINK_LINKED(&two, qlink));
+
+       ATF_CHECK(! ISC_QLINK_LINKED(&three, qlink));
+       ISC_QUEUE_PUSH(queue, &three, qlink);
+       ATF_CHECK(ISC_QLINK_LINKED(&three, qlink));
+
+       ATF_CHECK(! ISC_QLINK_LINKED(&four, qlink));
+       ISC_QUEUE_PUSH(queue, &four, qlink);
+       ATF_CHECK(ISC_QLINK_LINKED(&four, qlink));
+
+       ATF_CHECK(! ISC_QLINK_LINKED(&five, qlink));
+       ISC_QUEUE_PUSH(queue, &five, qlink);
+       ATF_CHECK(ISC_QLINK_LINKED(&five, qlink));
+
+       ISC_QUEUE_POP(queue, qlink, p);
+       ATF_REQUIRE(p != NULL);
+       ATF_CHECK_EQ(p->value, 1);
+
+       ISC_QUEUE_POP(queue, qlink, p);
+       ATF_REQUIRE(p != NULL);
+       ATF_CHECK_EQ(p->value, 2);
+
+       ISC_QUEUE_POP(queue, qlink, p);
+       ATF_REQUIRE(p != NULL);
+       ATF_CHECK_EQ(p->value, 3);
+
+       ISC_QUEUE_POP(queue, qlink, p);
+       ATF_REQUIRE(p != NULL);
+       ATF_CHECK_EQ(p->value, 4);
+
+       ISC_QUEUE_POP(queue, qlink, p);
+       ATF_REQUIRE(p != NULL);
+       ATF_CHECK_EQ(p->value, 5);
+
+       ATF_CHECK(ISC_QUEUE_EMPTY(queue));
+
+       ISC_QUEUE_DESTROY(queue);
+       isc_test_end();
+}
+
+/*
+ * Main
+ */
+ATF_TP_ADD_TCS(tp) {
+       ATF_TP_ADD_TC(tp, queue_valid);
+
+       return (atf_no_error());
+}
+
diff --git a/lib/isc/tests/socket_test.c b/lib/isc/tests/socket_test.c
new file mode 100644 (file)
index 0000000..724d79d
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <atf-c.h>
+
+#include <unistd.h>
+#include <time.h>
+
+#include <isc/socket.h>
+
+#include "../task_p.h"
+#include "isctest.h"
+
+/*
+ * Helper functions
+ */
+typedef struct {
+       isc_boolean_t done;
+       isc_result_t result;
+} completion_t;
+
+static void
+completion_init(completion_t *completion) {
+       completion->done = ISC_FALSE;
+}
+
+static void
+event_done(isc_task_t *task, isc_event_t *event) {
+       isc_socketevent_t *dev;
+       completion_t *completion = event->ev_arg;
+
+       UNUSED(task);
+
+       dev = (isc_socketevent_t *) event;
+       completion->result = dev->result;
+       completion->done = ISC_TRUE;
+       isc_event_free(&event);
+}
+
+static isc_result_t
+waitfor(completion_t *completion) {
+       int i = 0;
+       while (!completion->done && i++ < 5000) {
+#ifndef ISC_PLATFORM_USETHREADS
+               while (isc__taskmgr_ready(taskmgr))
+                       isc__taskmgr_dispatch(taskmgr);
+#endif
+               isc_test_nap(1000);
+       }
+       if (completion->done)
+               return (ISC_R_SUCCESS);
+       return (ISC_R_FAILURE);
+}
+
+/*
+ * Individual unit tests
+ */
+
+/* Test UDP sendto/recv (IPv4) */
+ATF_TC(udp_sendto);
+ATF_TC_HEAD(udp_sendto, tc) {
+       atf_tc_set_md_var(tc, "descr", "UDP sendto/recv");
+}
+ATF_TC_BODY(udp_sendto, tc) {
+       isc_result_t result;
+       isc_sockaddr_t addr1, addr2;
+       struct in_addr in;
+       isc_socket_t *s1 = NULL, *s2 = NULL;
+       isc_task_t *task = NULL;
+       char sendbuf[BUFSIZ], recvbuf[BUFSIZ];
+       completion_t completion;
+       isc_region_t r;
+
+       UNUSED(tc);
+
+       result = isc_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       /*
+        * Create two sockets: 127.0.0.1/5444 and 127.0.0.1/5445, talking to
+        * each other.
+        */
+       in.s_addr = inet_addr("127.0.0.1");
+       isc_sockaddr_fromin(&addr1, &in, 5444);
+       isc_sockaddr_fromin(&addr2, &in, 5445);
+
+       result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s1);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       result = isc_socket_bind(s1, &addr1, ISC_SOCKET_REUSEADDRESS);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s2);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       result = isc_socket_bind(s2, &addr2, ISC_SOCKET_REUSEADDRESS);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_task_create(taskmgr, 0, &task);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       strcpy(sendbuf, "Hello");
+       r.base = (void *) sendbuf;
+       r.length = strlen(sendbuf) + 1;
+
+       completion_init(&completion);
+       result = isc_socket_sendto(s1, &r, task, event_done, &completion,
+                                  &addr2, NULL);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+
+       r.base = (void *) recvbuf;
+       r.length = BUFSIZ;
+       completion_init(&completion);
+       result = isc_socket_recv(s2, &r, 1, task, event_done, &completion);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+       ATF_CHECK_STREQ(recvbuf, "Hello");
+
+       isc_task_detach(&task);
+
+       isc_socket_detach(&s1);
+       isc_socket_detach(&s2);
+
+       isc_test_end();
+}
+
+/* Test UDP sendto/recv with duplicated socket */
+ATF_TC(udp_dup);
+ATF_TC_HEAD(udp_dup, tc) {
+       atf_tc_set_md_var(tc, "descr", "duplicated socket sendto/recv");
+}
+ATF_TC_BODY(udp_dup, tc) {
+       isc_result_t result;
+       isc_sockaddr_t addr1, addr2;
+       struct in_addr in;
+       isc_socket_t *s1 = NULL, *s2 = NULL, *s3 = NULL;
+       isc_task_t *task = NULL;
+       char sendbuf[BUFSIZ], recvbuf[BUFSIZ];
+       completion_t completion;
+       isc_region_t r;
+
+       UNUSED(tc);
+
+       result = isc_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       /*
+        * Create two sockets: 127.0.0.1/5444 and 127.0.0.1/5445, talking to
+        * each other.
+        */
+       in.s_addr = inet_addr("127.0.0.1");
+       isc_sockaddr_fromin(&addr1, &in, 5444);
+       isc_sockaddr_fromin(&addr2, &in, 5445);
+
+       result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s1);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       result = isc_socket_bind(s1, &addr1, ISC_SOCKET_REUSEADDRESS);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s2);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       result = isc_socket_bind(s2, &addr2, ISC_SOCKET_REUSEADDRESS);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_socket_dup(s2, &s3);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_task_create(taskmgr, 0, &task);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       strcpy(sendbuf, "Hello");
+       r.base = (void *) sendbuf;
+       r.length = strlen(sendbuf) + 1;
+
+       completion_init(&completion);
+       result = isc_socket_sendto(s1, &r, task, event_done, &completion,
+                                  &addr2, NULL);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+
+       strcpy(sendbuf, "World");
+       r.base = (void *) sendbuf;
+       r.length = strlen(sendbuf) + 1;
+
+       completion_init(&completion);
+       result = isc_socket_sendto(s1, &r, task, event_done, &completion,
+                                  &addr2, NULL);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+
+       r.base = (void *) recvbuf;
+       r.length = BUFSIZ;
+       completion_init(&completion);
+       result = isc_socket_recv(s2, &r, 1, task, event_done, &completion);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+       ATF_CHECK_STREQ(recvbuf, "Hello");
+
+       r.base = (void *) recvbuf;
+       r.length = BUFSIZ;
+       completion_init(&completion);
+       result = isc_socket_recv(s3, &r, 1, task, event_done, &completion);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+       ATF_CHECK_STREQ(recvbuf, "World");
+
+       isc_task_detach(&task);
+
+       isc_socket_detach(&s1);
+       isc_socket_detach(&s2);
+       isc_socket_detach(&s3);
+
+       isc_test_end();
+}
+
+/*
+ * Main
+ */
+ATF_TP_ADD_TCS(tp) {
+       ATF_TP_ADD_TC(tp, udp_sendto);
+       ATF_TP_ADD_TC(tp, udp_dup);
+
+       return (atf_no_error());
+}
+
diff --git a/lib/isc/tests/symtab_test.c b/lib/isc/tests/symtab_test.c
new file mode 100644 (file)
index 0000000..21444b4
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <atf-c.h>
+
+#include <unistd.h>
+
+#include <isc/symtab.h>
+#include <isc/print.h>
+
+#include "isctest.h"
+
+static void
+undefine(char *key, unsigned int type, isc_symvalue_t value, void *arg) {
+       UNUSED(arg);
+
+       ATF_REQUIRE_EQ(type, 1);
+       isc_mem_free(mctx, key);
+       isc_mem_free(mctx, value.as_pointer);
+}
+
+/*
+ * Individual unit tests
+ */
+
+ATF_TC(symtab_grow);
+ATF_TC_HEAD(symtab_grow, tc) {
+       atf_tc_set_md_var(tc, "descr", "symbol table growth");
+}
+ATF_TC_BODY(symtab_grow, tc) {
+       isc_result_t result;
+       isc_symtab_t *st = NULL;
+       isc_symvalue_t value;
+       isc_symexists_t policy = isc_symexists_reject;
+       int i;
+
+       UNUSED(tc);
+
+       result = isc_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_symtab_create(mctx, 3, undefine, NULL, ISC_FALSE, &st);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       ATF_REQUIRE(st != NULL);
+
+       /* Nothing should be in the table yet */
+
+       /*
+        * Put 1024 entries in the table (this should necessate
+        * regrowing the hash table several times
+        */
+       for (i = 0; i < 1024; i++) {
+               char str[16], *key;
+
+               snprintf(str, sizeof(str), "%04x", i);
+               key = isc_mem_strdup(mctx, str);
+               ATF_REQUIRE(key != NULL);
+               value.as_pointer = isc_mem_strdup(mctx, str);
+               ATF_REQUIRE(value.as_pointer != NULL);
+               result = isc_symtab_define(st, key, 1, value, policy);
+               ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+               if (result != ISC_R_SUCCESS)
+                       undefine(key, 1, value, NULL);
+       }
+
+       /*
+        * Try to put them in again; this should fail
+        */
+       for (i = 0; i < 1024; i++) {
+               char str[16], *key;
+
+               snprintf(str, sizeof(str), "%04x", i);
+               key = isc_mem_strdup(mctx, str);
+               ATF_REQUIRE(key != NULL);
+               value.as_pointer = isc_mem_strdup(mctx, str);
+               ATF_REQUIRE(value.as_pointer != NULL);
+               result = isc_symtab_define(st, key, 1, value, policy);
+               ATF_CHECK_EQ(result, ISC_R_EXISTS);
+               undefine(key, 1, value, NULL);
+       }
+
+       /*
+        * Retrieve them; this should succeed
+        */
+       for (i = 0; i < 1024; i++) {
+               char str[16];
+
+               snprintf(str, sizeof(str), "%04x", i);
+               result = isc_symtab_lookup(st, str, 0, &value);
+               ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+               ATF_CHECK_STREQ(str, value.as_pointer);
+       }
+
+       /*
+        * Undefine them
+        */
+       for (i = 0; i < 1024; i++) {
+               char str[16];
+
+               snprintf(str, sizeof(str), "%04x", i);
+               result = isc_symtab_undefine(st, str, 1);
+               ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       }
+
+       /*
+        * Retrieve them again; this should fail
+        */
+       for (i = 0; i < 1024; i++) {
+               char str[16];
+
+               snprintf(str, sizeof(str), "%04x", i);
+               result = isc_symtab_lookup(st, str, 0, &value);
+               ATF_CHECK_EQ(result, ISC_R_NOTFOUND);
+       }
+
+       isc_symtab_destroy(&st);
+       isc_test_end();
+}
+
+/*
+ * Main
+ */
+ATF_TP_ADD_TCS(tp) {
+       ATF_TP_ADD_TC(tp, symtab_grow);
+
+       return (atf_no_error());
+}
+
diff --git a/lib/isc/tests/task_test.c b/lib/isc/tests/task_test.c
new file mode 100644 (file)
index 0000000..7294d86
--- /dev/null
@@ -0,0 +1,416 @@
+/*
+ * Copyright (C) 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <atf-c.h>
+
+#include <unistd.h>
+
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include "../task_p.h"
+#include "isctest.h"
+
+/*
+ * Helper functions
+ */
+
+/* task event handler, sets a boolean to true */
+int counter = 0;
+isc_mutex_t set_lock;
+
+static void
+set(isc_task_t *task, isc_event_t *event) {
+       int *value = (int *) event->ev_arg;
+
+       UNUSED(task);
+
+       isc_event_free(&event);
+       LOCK(&set_lock);
+       *value = counter++;
+       UNLOCK(&set_lock);
+}
+
+static void
+set_and_drop(isc_task_t *task, isc_event_t *event) {
+       int *value = (int *) event->ev_arg;
+
+       UNUSED(task);
+
+       isc_event_free(&event);
+       LOCK(&set_lock);
+       *value = (int) isc_taskmgr_mode(taskmgr);
+       counter++;
+       UNLOCK(&set_lock);
+       isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_normal);
+}
+
+/*
+ * Individual unit tests
+ */
+
+/* Create a task */
+ATF_TC(create_task);
+ATF_TC_HEAD(create_task, tc) {
+       atf_tc_set_md_var(tc, "descr", "create and destroy a task");
+}
+ATF_TC_BODY(create_task, tc) {
+       isc_result_t result;
+       isc_task_t *task = NULL;
+
+       UNUSED(tc);
+
+       result = isc_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_task_create(taskmgr, 0, &task);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       isc_task_destroy(&task);
+       ATF_REQUIRE_EQ(task, NULL);
+
+       isc_test_end();
+}
+
+/* Process events */
+ATF_TC(all_events);
+ATF_TC_HEAD(all_events, tc) {
+       atf_tc_set_md_var(tc, "descr", "process task events");
+}
+ATF_TC_BODY(all_events, tc) {
+       isc_result_t result;
+       isc_task_t *task = NULL;
+       isc_event_t *event;
+       int a = 0, b = 0;
+       int i = 0;
+
+       UNUSED(tc);
+
+       counter = 1;
+
+       result = isc_mutex_init(&set_lock);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_task_create(taskmgr, 0, &task);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       /* First event */
+       event = isc_event_allocate(mctx, task, ISC_TASKEVENT_TEST,
+                                  set, &a, sizeof (isc_event_t));
+       ATF_REQUIRE(event != NULL);
+
+       ATF_CHECK_EQ(a, 0);
+       isc_task_send(task, &event);
+
+       event = isc_event_allocate(mctx, task, ISC_TASKEVENT_TEST,
+                                  set, &b, sizeof (isc_event_t));
+       ATF_REQUIRE(event != NULL);
+
+       ATF_CHECK_EQ(b, 0);
+       isc_task_send(task, &event);
+
+       while ((a == 0 || b == 0) && i++ < 5000) {
+#ifndef ISC_PLATFORM_USETHREADS
+               while (isc__taskmgr_ready(taskmgr))
+                       isc__taskmgr_dispatch(taskmgr);
+#endif
+               isc_test_nap(1000);
+       }
+
+       ATF_CHECK(a != 0);
+       ATF_CHECK(b != 0);
+
+       isc_task_destroy(&task);
+       ATF_REQUIRE_EQ(task, NULL);
+
+       isc_test_end();
+}
+
+/* Privileged events */
+ATF_TC(privileged_events);
+ATF_TC_HEAD(privileged_events, tc) {
+       atf_tc_set_md_var(tc, "descr", "process privileged events");
+}
+ATF_TC_BODY(privileged_events, tc) {
+       isc_result_t result;
+       isc_task_t *task1 = NULL, *task2 = NULL;
+       isc_event_t *event;
+       int a = 0, b = 0, c = 0, d = 0, e = 0;
+       int i = 0;
+
+       UNUSED(tc);
+
+       counter = 1;
+       result = isc_mutex_init(&set_lock);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+#ifdef ISC_PLATFORM_USETHREADS
+       /*
+        * Pause the task manager so we can fill up the work queue
+        * without things happening while we do it.
+        */
+       isc__taskmgr_pause(taskmgr);
+#endif
+
+       result = isc_task_create(taskmgr, 0, &task1);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       isc_task_setname(task1, "privileged", NULL);
+       ATF_CHECK(!isc_task_privilege(task1));
+       isc_task_setprivilege(task1, ISC_TRUE);
+       ATF_CHECK(isc_task_privilege(task1));
+
+       result = isc_task_create(taskmgr, 0, &task2);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       isc_task_setname(task2, "normal", NULL);
+       ATF_CHECK(!isc_task_privilege(task2));
+
+       /* First event: privileged */
+       event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST,
+                                  set, &a, sizeof (isc_event_t));
+       ATF_REQUIRE(event != NULL);
+
+       ATF_CHECK_EQ(a, 0);
+       isc_task_send(task1, &event);
+
+       /* Second event: not privileged */
+       event = isc_event_allocate(mctx, task2, ISC_TASKEVENT_TEST,
+                                  set, &b, sizeof (isc_event_t));
+       ATF_REQUIRE(event != NULL);
+
+       ATF_CHECK_EQ(b, 0);
+       isc_task_send(task2, &event);
+
+       /* Third event: privileged */
+       event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST,
+                                  set, &c, sizeof (isc_event_t));
+       ATF_REQUIRE(event != NULL);
+
+       ATF_CHECK_EQ(c, 0);
+       isc_task_send(task1, &event);
+
+       /* Fourth event: privileged */
+       event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST,
+                                  set, &d, sizeof (isc_event_t));
+       ATF_REQUIRE(event != NULL);
+
+       ATF_CHECK_EQ(d, 0);
+       isc_task_send(task1, &event);
+
+       /* Fifth event: not privileged */
+       event = isc_event_allocate(mctx, task2, ISC_TASKEVENT_TEST,
+                                  set, &e, sizeof (isc_event_t));
+       ATF_REQUIRE(event != NULL);
+
+       ATF_CHECK_EQ(e, 0);
+       isc_task_send(task2, &event);
+
+       ATF_CHECK_EQ(isc_taskmgr_mode(taskmgr), isc_taskmgrmode_normal);
+       isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_privileged);
+       ATF_CHECK_EQ(isc_taskmgr_mode(taskmgr), isc_taskmgrmode_privileged);
+
+#ifdef ISC_PLATFORM_USETHREADS
+       isc__taskmgr_resume(taskmgr);
+#endif
+
+       /* We're waiting for *all* variables to be set */
+       while ((a == 0 || b == 0 || c == 0 || d == 0 || e == 0) && i++ < 5000) {
+#ifndef ISC_PLATFORM_USETHREADS
+               while (isc__taskmgr_ready(taskmgr))
+                       isc__taskmgr_dispatch(taskmgr);
+#endif
+               isc_test_nap(1000);
+       }
+
+       /*
+        * We can't guarantee what order the events fire, but
+        * we do know the privileged tasks that set a, c, and d
+        * would have fired first.
+        */
+       ATF_CHECK(a <= 3);
+       ATF_CHECK(c <= 3);
+       ATF_CHECK(d <= 3);
+
+       /* ...and the non-privileged tasks that set b and e, last */
+       ATF_CHECK(b >= 4);
+       ATF_CHECK(e >= 4);
+
+       ATF_CHECK_EQ(counter, 6);
+
+       isc_task_setprivilege(task1, ISC_FALSE);
+       ATF_CHECK(!isc_task_privilege(task1));
+
+       ATF_CHECK_EQ(isc_taskmgr_mode(taskmgr), isc_taskmgrmode_normal);
+
+       isc_task_destroy(&task1);
+       ATF_REQUIRE_EQ(task1, NULL);
+       isc_task_destroy(&task2);
+       ATF_REQUIRE_EQ(task2, NULL);
+
+       isc_test_end();
+}
+
+/*
+ * Edge case: this tests that the task manager behaves as expected when
+ * we explicitly set it into normal mode *while* running privileged.
+ */
+ATF_TC(privilege_drop);
+ATF_TC_HEAD(privilege_drop, tc) {
+       atf_tc_set_md_var(tc, "descr", "process privileged events");
+}
+ATF_TC_BODY(privilege_drop, tc) {
+       isc_result_t result;
+       isc_task_t *task1 = NULL, *task2 = NULL;
+       isc_event_t *event;
+       int a = -1, b = -1, c = -1, d = -1, e = -1;     /* non valid states */
+       int i = 0;
+
+       UNUSED(tc);
+
+       counter = 1;
+       result = isc_mutex_init(&set_lock);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+#ifdef ISC_PLATFORM_USETHREADS
+       /*
+        * Pause the task manager so we can fill up the work queue
+        * without things happening while we do it.
+        */
+       isc__taskmgr_pause(taskmgr);
+#endif
+
+       result = isc_task_create(taskmgr, 0, &task1);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       isc_task_setname(task1, "privileged", NULL);
+       ATF_CHECK(!isc_task_privilege(task1));
+       isc_task_setprivilege(task1, ISC_TRUE);
+       ATF_CHECK(isc_task_privilege(task1));
+
+       result = isc_task_create(taskmgr, 0, &task2);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       isc_task_setname(task2, "normal", NULL);
+       ATF_CHECK(!isc_task_privilege(task2));
+
+       /* First event: privileged */
+       event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST,
+                                  set_and_drop, &a, sizeof (isc_event_t));
+       ATF_REQUIRE(event != NULL);
+
+       ATF_CHECK_EQ(a, -1);
+       isc_task_send(task1, &event);
+
+       /* Second event: not privileged */
+       event = isc_event_allocate(mctx, task2, ISC_TASKEVENT_TEST,
+                                  set_and_drop, &b, sizeof (isc_event_t));
+       ATF_REQUIRE(event != NULL);
+
+       ATF_CHECK_EQ(b, -1);
+       isc_task_send(task2, &event);
+
+       /* Third event: privileged */
+       event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST,
+                                  set_and_drop, &c, sizeof (isc_event_t));
+       ATF_REQUIRE(event != NULL);
+
+       ATF_CHECK_EQ(c, -1);
+       isc_task_send(task1, &event);
+
+       /* Fourth event: privileged */
+       event = isc_event_allocate(mctx, task1, ISC_TASKEVENT_TEST,
+                                  set_and_drop, &d, sizeof (isc_event_t));
+       ATF_REQUIRE(event != NULL);
+
+       ATF_CHECK_EQ(d, -1);
+       isc_task_send(task1, &event);
+
+       /* Fifth event: not privileged */
+       event = isc_event_allocate(mctx, task2, ISC_TASKEVENT_TEST,
+                                  set_and_drop, &e, sizeof (isc_event_t));
+       ATF_REQUIRE(event != NULL);
+
+       ATF_CHECK_EQ(e, -1);
+       isc_task_send(task2, &event);
+
+       ATF_CHECK_EQ(isc_taskmgr_mode(taskmgr), isc_taskmgrmode_normal);
+       isc_taskmgr_setmode(taskmgr, isc_taskmgrmode_privileged);
+       ATF_CHECK_EQ(isc_taskmgr_mode(taskmgr), isc_taskmgrmode_privileged);
+
+#ifdef ISC_PLATFORM_USETHREADS
+       isc__taskmgr_resume(taskmgr);
+#endif
+
+       /* We're waiting for all variables to be set. */
+       while ((a == -1 || b == -1 || c == -1 || d == -1 || e == -1) &&
+              i++ < 5000) {
+#ifndef ISC_PLATFORM_USETHREADS
+               while (isc__taskmgr_ready(taskmgr))
+                       isc__taskmgr_dispatch(taskmgr);
+#endif
+               isc_test_nap(1000);
+       }
+
+       /*
+        * We can't guarantee what order the events fire, but
+        * we do know *exactly one* of the privileged tasks will
+        * have run in privileged mode...
+        */
+       ATF_CHECK(a == isc_taskmgrmode_privileged ||
+                 c == isc_taskmgrmode_privileged ||
+                 d == isc_taskmgrmode_privileged);
+       ATF_CHECK(a + c + d == isc_taskmgrmode_privileged);
+
+       /* ...and neither of the non-privileged tasks did... */
+       ATF_CHECK(b == isc_taskmgrmode_normal || e == isc_taskmgrmode_normal);
+
+       /* ...but all five of them did run. */
+       ATF_CHECK_EQ(counter, 6);
+
+       ATF_CHECK_EQ(isc_taskmgr_mode(taskmgr), isc_taskmgrmode_normal);
+
+       isc_task_destroy(&task1);
+       ATF_REQUIRE_EQ(task1, NULL);
+       isc_task_destroy(&task2);
+       ATF_REQUIRE_EQ(task2, NULL);
+
+       isc_test_end();
+}
+
+/*
+ * Main
+ */
+ATF_TP_ADD_TCS(tp) {
+       ATF_TP_ADD_TC(tp, create_task);
+       ATF_TP_ADD_TC(tp, all_events);
+       ATF_TP_ADD_TC(tp, privileged_events);
+       ATF_TP_ADD_TC(tp, privilege_drop);
+
+       return (atf_no_error());
+}
+
diff --git a/lib/isc/tests/taskpool_test.c b/lib/isc/tests/taskpool_test.c
new file mode 100644 (file)
index 0000000..aecb694
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <atf-c.h>
+
+#include <unistd.h>
+
+#include <isc/task.h>
+#include <isc/taskpool.h>
+
+#include "isctest.h"
+
+/*
+ * Individual unit tests
+ */
+
+/* Create a taskpool */
+ATF_TC(create_pool);
+ATF_TC_HEAD(create_pool, tc) {
+       atf_tc_set_md_var(tc, "descr", "create a taskpool");
+}
+ATF_TC_BODY(create_pool, tc) {
+       isc_result_t result;
+       isc_taskpool_t *pool = NULL;
+
+       UNUSED(tc);
+
+       result = isc_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_taskpool_create(taskmgr, mctx, 8, 2, &pool);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       ATF_REQUIRE_EQ(isc_taskpool_size(pool), 8);
+
+       isc_taskpool_destroy(&pool);
+       ATF_REQUIRE_EQ(pool, NULL);
+
+       isc_test_end();
+}
+
+/* Resize a taskpool */
+ATF_TC(expand_pool);
+ATF_TC_HEAD(expand_pool, tc) {
+       atf_tc_set_md_var(tc, "descr", "expand a taskpool");
+}
+ATF_TC_BODY(expand_pool, tc) {
+       isc_result_t result;
+       isc_taskpool_t *pool1 = NULL, *pool2 = NULL, *hold = NULL;
+
+       UNUSED(tc);
+
+       result = isc_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_taskpool_create(taskmgr, mctx, 10, 2, &pool1);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       ATF_REQUIRE_EQ(isc_taskpool_size(pool1), 10);
+
+       /* resizing to a smaller size should have no effect */
+       hold = pool1;
+       result = isc_taskpool_expand(&pool1, 5, &pool2);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       ATF_REQUIRE_EQ(isc_taskpool_size(pool2), 10);
+       ATF_REQUIRE_EQ(pool2, hold);
+       ATF_REQUIRE_EQ(pool1, NULL);
+       pool1 = pool2;
+       pool2 = NULL;
+
+       /* resizing to the same size should have no effect */
+       hold = pool1;
+       result = isc_taskpool_expand(&pool1, 10, &pool2);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       ATF_REQUIRE_EQ(isc_taskpool_size(pool2), 10);
+       ATF_REQUIRE_EQ(pool2, hold);
+       ATF_REQUIRE_EQ(pool1, NULL);
+       pool1 = pool2;
+       pool2 = NULL;
+
+       /* resizing to larger size should make a new pool */
+       hold = pool1;
+       result = isc_taskpool_expand(&pool1, 20, &pool2);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       ATF_REQUIRE_EQ(isc_taskpool_size(pool2), 20);
+       ATF_REQUIRE(pool2 != hold);
+       ATF_REQUIRE_EQ(pool1, NULL);
+
+       isc_taskpool_destroy(&pool2);
+       ATF_REQUIRE_EQ(pool2, NULL);
+
+       isc_test_end();
+}
+
+/* Get tasks */
+ATF_TC(get_tasks);
+ATF_TC_HEAD(get_tasks, tc) {
+       atf_tc_set_md_var(tc, "descr", "create a taskpool");
+}
+ATF_TC_BODY(get_tasks, tc) {
+       isc_result_t result;
+       isc_taskpool_t *pool = NULL;
+       isc_task_t *task1 = NULL, *task2 = NULL, *task3 = NULL;
+
+       UNUSED(tc);
+
+       result = isc_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_taskpool_create(taskmgr, mctx, 2, 2, &pool);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       ATF_REQUIRE_EQ(isc_taskpool_size(pool), 2);
+
+       /* two tasks in pool; make sure we can access them more than twice */
+       isc_taskpool_gettask(pool, &task1);
+       ATF_REQUIRE(ISCAPI_TASK_VALID(task1));
+
+       isc_taskpool_gettask(pool, &task2);
+       ATF_REQUIRE(ISCAPI_TASK_VALID(task2));
+
+       isc_taskpool_gettask(pool, &task3);
+       ATF_REQUIRE(ISCAPI_TASK_VALID(task3));
+
+       isc_task_destroy(&task1);
+       isc_task_destroy(&task2);
+       isc_task_destroy(&task3);
+
+       isc_taskpool_destroy(&pool);
+       ATF_REQUIRE_EQ(pool, NULL);
+
+       isc_test_end();
+}
+
+/* Get tasks */
+ATF_TC(set_privilege);
+ATF_TC_HEAD(set_privilege, tc) {
+       atf_tc_set_md_var(tc, "descr", "create a taskpool");
+}
+ATF_TC_BODY(set_privilege, tc) {
+       isc_result_t result;
+       isc_taskpool_t *pool = NULL;
+       isc_task_t *task1 = NULL, *task2 = NULL, *task3 = NULL;
+
+       UNUSED(tc);
+
+       result = isc_test_begin(NULL, ISC_TRUE);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       result = isc_taskpool_create(taskmgr, mctx, 2, 2, &pool);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+       ATF_REQUIRE_EQ(isc_taskpool_size(pool), 2);
+
+       isc_taskpool_setprivilege(pool, ISC_TRUE);
+
+       isc_taskpool_gettask(pool, &task1);
+       isc_taskpool_gettask(pool, &task2);
+       isc_taskpool_gettask(pool, &task3);
+
+       ATF_CHECK(ISCAPI_TASK_VALID(task1));
+       ATF_CHECK(ISCAPI_TASK_VALID(task2));
+       ATF_CHECK(ISCAPI_TASK_VALID(task3));
+
+       ATF_CHECK(isc_task_privilege(task1));
+       ATF_CHECK(isc_task_privilege(task2));
+       ATF_CHECK(isc_task_privilege(task3));
+
+       isc_taskpool_setprivilege(pool, ISC_FALSE);
+
+       ATF_CHECK(!isc_task_privilege(task1));
+       ATF_CHECK(!isc_task_privilege(task2));
+       ATF_CHECK(!isc_task_privilege(task3));
+
+       isc_task_destroy(&task1);
+       isc_task_destroy(&task2);
+       isc_task_destroy(&task3);
+
+       isc_taskpool_destroy(&pool);
+       ATF_REQUIRE_EQ(pool, NULL);
+
+       isc_test_end();
+}
+
+/*
+ * Main
+ */
+ATF_TP_ADD_TCS(tp) {
+       ATF_TP_ADD_TC(tp, create_pool);
+       ATF_TP_ADD_TC(tp, expand_pool);
+       ATF_TP_ADD_TC(tp, get_tasks);
+       ATF_TP_ADD_TC(tp, set_privilege);
+
+       return (atf_no_error());
+}
+
index 21fcd694eff1c2b54ea71f1656e44e29c5367b41..0da251f4c31b3b2ee2701aff5bacf9d5458f75cc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2002  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: timer.c,v 1.84.58.4 2009/01/23 23:47:21 tbox Exp $ */
+/* $Id$ */
 
 /*! \file */
 
 #include <isc/timer.h>
 #include <isc/util.h>
 
-#ifndef ISC_PLATFORM_USETHREADS
+#ifdef OPENSSL_LEAKS
+#include <openssl/err.h>
+#endif
+
+/* See task.c about the following definition: */
+#ifdef BIND9
+#ifdef ISC_PLATFORM_USETHREADS
+#define USE_TIMER_THREAD
+#else
+#define USE_SHARED_MANAGER
+#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* BIND9 */
+
+#ifndef USE_TIMER_THREAD
 #include "timer_p.h"
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
 
 #ifdef ISC_TIMER_TRACE
 #define XTRACE(s)                      fprintf(stderr, "%s\n", (s))
 #define TIMER_MAGIC                    ISC_MAGIC('T', 'I', 'M', 'R')
 #define VALID_TIMER(t)                 ISC_MAGIC_VALID(t, TIMER_MAGIC)
 
-struct isc_timer {
+typedef struct isc__timer isc__timer_t;
+typedef struct isc__timermgr isc__timermgr_t;
+
+struct isc__timer {
        /*! Not locked. */
-       unsigned int                    magic;
-       isc_timermgr_t *                manager;
+       isc_timer_t                     common;
+       isc__timermgr_t *               manager;
        isc_mutex_t                     lock;
        /*! Locked by timer lock. */
        unsigned int                    references;
@@ -75,45 +91,119 @@ struct isc_timer {
        void *                          arg;
        unsigned int                    index;
        isc_time_t                      due;
-       LINK(isc_timer_t)               link;
+       LINK(isc__timer_t)              link;
 };
 
 #define TIMER_MANAGER_MAGIC            ISC_MAGIC('T', 'I', 'M', 'M')
 #define VALID_MANAGER(m)               ISC_MAGIC_VALID(m, TIMER_MANAGER_MAGIC)
 
-struct isc_timermgr {
+struct isc__timermgr {
        /* Not locked. */
-       unsigned int                    magic;
+       isc_timermgr_t                  common;
        isc_mem_t *                     mctx;
        isc_mutex_t                     lock;
        /* Locked by manager lock. */
        isc_boolean_t                   done;
-       LIST(isc_timer_t)               timers;
+       LIST(isc__timer_t)              timers;
        unsigned int                    nscheduled;
        isc_time_t                      due;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
        isc_condition_t                 wakeup;
        isc_thread_t                    thread;
-#else /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
+#ifdef USE_SHARED_MANAGER
        unsigned int                    refs;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_SHARED_MANAGER */
        isc_heap_t *                    heap;
 };
 
-#ifndef ISC_PLATFORM_USETHREADS
+/*%
+ * The followings can be either static or public, depending on build
+ * environment.
+ */
+
+#ifdef BIND9
+#define ISC_TIMERFUNC_SCOPE
+#else
+#define ISC_TIMERFUNC_SCOPE static
+#endif
+
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_create(isc_timermgr_t *manager, isc_timertype_t type,
+                 isc_time_t *expires, isc_interval_t *interval,
+                 isc_task_t *task, isc_taskaction_t action, const void *arg,
+                 isc_timer_t **timerp);
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_reset(isc_timer_t *timer, isc_timertype_t type,
+                isc_time_t *expires, isc_interval_t *interval,
+                isc_boolean_t purge);
+ISC_TIMERFUNC_SCOPE isc_timertype_t
+isc__timer_gettype(isc_timer_t *timer);
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_touch(isc_timer_t *timer);
+ISC_TIMERFUNC_SCOPE void
+isc__timer_attach(isc_timer_t *timer0, isc_timer_t **timerp);
+ISC_TIMERFUNC_SCOPE void
+isc__timer_detach(isc_timer_t **timerp);
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
+ISC_TIMERFUNC_SCOPE void
+isc__timermgr_poke(isc_timermgr_t *manager0);
+ISC_TIMERFUNC_SCOPE void
+isc__timermgr_destroy(isc_timermgr_t **managerp);
+
+static struct isc__timermethods {
+       isc_timermethods_t methods;
+
+       /*%
+        * The following are defined just for avoiding unused static functions.
+        */
+#ifndef BIND9
+       void *gettype;
+#endif
+} timermethods = {
+       {
+               isc__timer_attach,
+               isc__timer_detach,
+               isc__timer_reset,
+               isc__timer_touch
+       }
+#ifndef BIND9
+       ,
+       (void *)isc__timer_gettype
+#endif
+};
+
+static struct isc__timermgrmethods {
+       isc_timermgrmethods_t methods;
+#ifndef BIND9
+       void *poke;             /* see above */
+#endif
+} timermgrmethods = {
+       {
+               isc__timermgr_destroy,
+               isc__timer_create
+       }
+#ifndef BIND9
+       ,
+       (void *)isc__timermgr_poke
+#endif
+};
+
+#ifdef USE_SHARED_MANAGER
 /*!
- * If threads are not in use, there can be only one.
+ * If the manager is supposed to be shared, there can be only one.
  */
-static isc_timermgr_t *timermgr = NULL;
-#endif /* ISC_PLATFORM_USETHREADS */
+static isc__timermgr_t *timermgr = NULL;
+#endif /* USE_SHARED_MANAGER */
 
 static inline isc_result_t
-schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) {
+schedule(isc__timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) {
        isc_result_t result;
-       isc_timermgr_t *manager;
+       isc__timermgr_t *manager;
        isc_time_t due;
        int cmp;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
        isc_boolean_t timedwait;
 #endif
 
@@ -123,13 +213,13 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) {
 
        REQUIRE(timer->type != isc_timertype_inactive);
 
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_TIMER_THREAD
        UNUSED(signal_ok);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
 
        manager = timer->manager;
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
        /*!
         * If the manager was timed wait, we may need to signal the
         * manager to force a wakeup.
@@ -199,7 +289,7 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) {
         * the current "next" timer.  We do this either by waking up the
         * run thread, or explicitly setting the value in the manager.
         */
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
 
        /*
         * This is a temporary (probably) hack to fix a bug on tru64 5.1
@@ -232,19 +322,21 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) {
                                      "signal (schedule)"));
                SIGNAL(&manager->wakeup);
        }
-#else /* ISC_PLATFORM_USETHREADS */
+#else /* USE_TIMER_THREAD */
        if (timer->index == 1 &&
            isc_time_compare(&timer->due, &manager->due) < 0)
                manager->due = timer->due;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
 
        return (ISC_R_SUCCESS);
 }
 
 static inline void
-deschedule(isc_timer_t *timer) {
+deschedule(isc__timer_t *timer) {
+#ifdef USE_TIMER_THREAD
        isc_boolean_t need_wakeup = ISC_FALSE;
-       isc_timermgr_t *manager;
+#endif
+       isc__timermgr_t *manager;
 
        /*
         * The caller must ensure locking.
@@ -252,26 +344,28 @@ deschedule(isc_timer_t *timer) {
 
        manager = timer->manager;
        if (timer->index > 0) {
+#ifdef USE_TIMER_THREAD
                if (timer->index == 1)
                        need_wakeup = ISC_TRUE;
+#endif
                isc_heap_delete(manager->heap, timer->index);
                timer->index = 0;
                INSIST(manager->nscheduled > 0);
                manager->nscheduled--;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
                if (need_wakeup) {
                        XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
                                              ISC_MSG_SIGNALDESCHED,
                                              "signal (deschedule)"));
                        SIGNAL(&manager->wakeup);
                }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
        }
 }
 
 static void
-destroy(isc_timer_t *timer) {
-       isc_timermgr_t *manager = timer->manager;
+destroy(isc__timer_t *timer) {
+       isc__timermgr_t *manager = timer->manager;
 
        /*
         * The caller must ensure it is safe to destroy the timer.
@@ -291,17 +385,19 @@ destroy(isc_timer_t *timer) {
 
        isc_task_detach(&timer->task);
        DESTROYLOCK(&timer->lock);
-       timer->magic = 0;
+       timer->common.impmagic = 0;
+       timer->common.magic = 0;
        isc_mem_put(manager->mctx, timer, sizeof(*timer));
 }
 
-isc_result_t
-isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type,
-                isc_time_t *expires, isc_interval_t *interval,
-                isc_task_t *task, isc_taskaction_t action, const void *arg,
-                isc_timer_t **timerp)
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_create(isc_timermgr_t *manager0, isc_timertype_t type,
+                 isc_time_t *expires, isc_interval_t *interval,
+                 isc_task_t *task, isc_taskaction_t action, const void *arg,
+                 isc_timer_t **timerp)
 {
-       isc_timer_t *timer;
+       isc__timermgr_t *manager = (isc__timermgr_t *)manager0;
+       isc__timer_t *timer;
        isc_result_t result;
        isc_time_t now;
 
@@ -382,7 +478,9 @@ isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type,
                return (result);
        }
        ISC_LINK_INIT(timer, link);
-       timer->magic = TIMER_MAGIC;
+       timer->common.impmagic = TIMER_MAGIC;
+       timer->common.magic = ISCAPI_TIMER_MAGIC;
+       timer->common.methods = (isc_timermethods_t *)&timermethods;
 
        LOCK(&manager->lock);
 
@@ -401,25 +499,27 @@ isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type,
        UNLOCK(&manager->lock);
 
        if (result != ISC_R_SUCCESS) {
-               timer->magic = 0;
+               timer->common.impmagic = 0;
+               timer->common.magic = 0;
                DESTROYLOCK(&timer->lock);
                isc_task_detach(&timer->task);
                isc_mem_put(manager->mctx, timer, sizeof(*timer));
                return (result);
        }
 
-       *timerp = timer;
+       *timerp = (isc_timer_t *)timer;
 
        return (ISC_R_SUCCESS);
 }
 
-isc_result_t
-isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
-               isc_time_t *expires, isc_interval_t *interval,
-               isc_boolean_t purge)
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_reset(isc_timer_t *timer0, isc_timertype_t type,
+                isc_time_t *expires, isc_interval_t *interval,
+                isc_boolean_t purge)
 {
+       isc__timer_t *timer = (isc__timer_t *)timer0;
        isc_time_t now;
-       isc_timermgr_t *manager;
+       isc__timermgr_t *manager;
        isc_result_t result;
 
        /*
@@ -431,6 +531,7 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
        REQUIRE(VALID_TIMER(timer));
        manager = timer->manager;
        REQUIRE(VALID_MANAGER(manager));
+
        if (expires == NULL)
                expires = isc_time_epoch;
        if (interval == NULL)
@@ -454,8 +555,6 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
                isc_time_settoepoch(&now);
        }
 
-       manager = timer->manager;
-
        LOCK(&manager->lock);
        LOCK(&timer->lock);
 
@@ -489,8 +588,9 @@ isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
        return (result);
 }
 
-isc_timertype_t
-isc_timer_gettype(isc_timer_t *timer) {
+ISC_TIMERFUNC_SCOPE isc_timertype_t
+isc__timer_gettype(isc_timer_t *timer0) {
+       isc__timer_t *timer = (isc__timer_t *)timer0;
        isc_timertype_t t;
 
        REQUIRE(VALID_TIMER(timer));
@@ -502,8 +602,9 @@ isc_timer_gettype(isc_timer_t *timer) {
        return (t);
 }
 
-isc_result_t
-isc_timer_touch(isc_timer_t *timer) {
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timer_touch(isc_timer_t *timer0) {
+       isc__timer_t *timer = (isc__timer_t *)timer0;
        isc_result_t result;
        isc_time_t now;
 
@@ -532,8 +633,10 @@ isc_timer_touch(isc_timer_t *timer) {
        return (result);
 }
 
-void
-isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) {
+ISC_TIMERFUNC_SCOPE void
+isc__timer_attach(isc_timer_t *timer0, isc_timer_t **timerp) {
+       isc__timer_t *timer = (isc__timer_t *)timer0;
+
        /*
         * Attach *timerp to timer.
         */
@@ -545,12 +648,12 @@ isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) {
        timer->references++;
        UNLOCK(&timer->lock);
 
-       *timerp = timer;
+       *timerp = (isc_timer_t *)timer;
 }
 
-void
-isc_timer_detach(isc_timer_t **timerp) {
-       isc_timer_t *timer;
+ISC_TIMERFUNC_SCOPE void
+isc__timer_detach(isc_timer_t **timerp) {
+       isc__timer_t *timer;
        isc_boolean_t free_timer = ISC_FALSE;
 
        /*
@@ -558,7 +661,7 @@ isc_timer_detach(isc_timer_t **timerp) {
         */
 
        REQUIRE(timerp != NULL);
-       timer = *timerp;
+       timer = (isc__timer_t *)*timerp;
        REQUIRE(VALID_TIMER(timer));
 
        LOCK(&timer->lock);
@@ -575,11 +678,11 @@ isc_timer_detach(isc_timer_t **timerp) {
 }
 
 static void
-dispatch(isc_timermgr_t *manager, isc_time_t *now) {
+dispatch(isc__timermgr_t *manager, isc_time_t *now) {
        isc_boolean_t done = ISC_FALSE, post_event, need_schedule;
        isc_timerevent_t *event;
        isc_eventtype_t type = 0;
-       isc_timer_t *timer;
+       isc__timer_t *timer;
        isc_result_t result;
        isc_boolean_t idle;
 
@@ -693,13 +796,13 @@ dispatch(isc_timermgr_t *manager, isc_time_t *now) {
        }
 }
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
 static isc_threadresult_t
 #ifdef _WIN32                  /* XXXDCL */
 WINAPI
 #endif
 run(void *uap) {
-       isc_timermgr_t *manager = uap;
+       isc__timermgr_t *manager = uap;
        isc_time_t now;
        isc_result_t result;
 
@@ -732,13 +835,17 @@ run(void *uap) {
        }
        UNLOCK(&manager->lock);
 
+#ifdef OPENSSL_LEAKS
+       ERR_remove_state(0);
+#endif
+
        return ((isc_threadresult_t)0);
 }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
 
 static isc_boolean_t
 sooner(void *v1, void *v2) {
-       isc_timer_t *t1, *t2;
+       isc__timer_t *t1, *t2;
 
        t1 = v1;
        t2 = v2;
@@ -752,7 +859,7 @@ sooner(void *v1, void *v2) {
 
 static void
 set_index(void *what, unsigned int index) {
-       isc_timer_t *timer;
+       isc__timer_t *timer;
 
        timer = what;
        REQUIRE(VALID_TIMER(timer));
@@ -760,9 +867,9 @@ set_index(void *what, unsigned int index) {
        timer->index = index;
 }
 
-isc_result_t
-isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
-       isc_timermgr_t *manager;
+ISC_TIMERFUNC_SCOPE isc_result_t
+isc__timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
+       isc__timermgr_t *manager;
        isc_result_t result;
 
        /*
@@ -771,19 +878,21 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
 
        REQUIRE(managerp != NULL && *managerp == NULL);
 
-#ifndef ISC_PLATFORM_USETHREADS
+#ifdef USE_SHARED_MANAGER
        if (timermgr != NULL) {
                timermgr->refs++;
-               *managerp = timermgr;
+               *managerp = (isc_timermgr_t *)timermgr;
                return (ISC_R_SUCCESS);
        }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_SHARED_MANAGER */
 
        manager = isc_mem_get(mctx, sizeof(*manager));
        if (manager == NULL)
                return (ISC_R_NOMEMORY);
 
-       manager->magic = TIMER_MANAGER_MAGIC;
+       manager->common.impmagic = TIMER_MANAGER_MAGIC;
+       manager->common.magic = ISCAPI_TIMERMGR_MAGIC;
+       manager->common.methods = (isc_timermgrmethods_t *)&timermgrmethods;
        manager->mctx = NULL;
        manager->done = ISC_FALSE;
        INIT_LIST(manager->timers);
@@ -803,7 +912,7 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
                return (result);
        }
        isc_mem_attach(mctx, &manager->mctx);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
        if (isc_condition_init(&manager->wakeup) != ISC_R_SUCCESS) {
                isc_mem_detach(&manager->mctx);
                DESTROYLOCK(&manager->lock);
@@ -828,30 +937,33 @@ isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
                                                ISC_MSG_FAILED, "failed"));
                return (ISC_R_UNEXPECTED);
        }
-#else /* ISC_PLATFORM_USETHREADS */
+#endif
+#ifdef USE_SHARED_MANAGER
        manager->refs = 1;
        timermgr = manager;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_SHARED_MANAGER */
 
-       *managerp = manager;
+       *managerp = (isc_timermgr_t *)manager;
 
        return (ISC_R_SUCCESS);
 }
 
-void
-isc_timermgr_poke(isc_timermgr_t *manager) {
-#ifdef ISC_PLATFORM_USETHREADS
+ISC_TIMERFUNC_SCOPE void
+isc__timermgr_poke(isc_timermgr_t *manager0) {
+#ifdef USE_TIMER_THREAD
+       isc__timermgr_t *manager = (isc__timermgr_t *)manager0;
+
        REQUIRE(VALID_MANAGER(manager));
 
        SIGNAL(&manager->wakeup);
 #else
-       UNUSED(manager);
+       UNUSED(manager0);
 #endif
 }
 
-void
-isc_timermgr_destroy(isc_timermgr_t **managerp) {
-       isc_timermgr_t *manager;
+ISC_TIMERFUNC_SCOPE void
+isc__timermgr_destroy(isc_timermgr_t **managerp) {
+       isc__timermgr_t *manager;
        isc_mem_t *mctx;
 
        /*
@@ -859,34 +971,37 @@ isc_timermgr_destroy(isc_timermgr_t **managerp) {
         */
 
        REQUIRE(managerp != NULL);
-       manager = *managerp;
+       manager = (isc__timermgr_t *)*managerp;
        REQUIRE(VALID_MANAGER(manager));
 
        LOCK(&manager->lock);
 
-#ifndef ISC_PLATFORM_USETHREADS
-       if (manager->refs > 1) {
-               manager->refs--;
+#ifdef USE_SHARED_MANAGER
+       manager->refs--;
+       if (manager->refs > 0) {
                UNLOCK(&manager->lock);
                *managerp = NULL;
                return;
        }
+       timermgr = NULL;
+#endif /* USE_SHARED_MANAGER */
 
-       isc__timermgr_dispatch();
-#endif /* ISC_PLATFORM_USETHREADS */
+#ifndef USE_TIMER_THREAD
+       isc__timermgr_dispatch((isc_timermgr_t *)manager);
+#endif
 
        REQUIRE(EMPTY(manager->timers));
        manager->done = ISC_TRUE;
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
        XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
                              ISC_MSG_SIGNALDESTROY, "signal (destroy)"));
        SIGNAL(&manager->wakeup);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
 
        UNLOCK(&manager->lock);
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
        /*
         * Wait for thread to exit.
         */
@@ -895,39 +1010,63 @@ isc_timermgr_destroy(isc_timermgr_t **managerp) {
                                 "isc_thread_join() %s",
                                 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
                                                ISC_MSG_FAILED, "failed"));
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
 
        /*
         * Clean up.
         */
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_TIMER_THREAD
        (void)isc_condition_destroy(&manager->wakeup);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
        DESTROYLOCK(&manager->lock);
        isc_heap_destroy(&manager->heap);
-       manager->magic = 0;
+       manager->common.impmagic = 0;
+       manager->common.magic = 0;
        mctx = manager->mctx;
        isc_mem_put(mctx, manager, sizeof(*manager));
        isc_mem_detach(&mctx);
 
        *managerp = NULL;
+
+#ifdef USE_SHARED_MANAGER
+       timermgr = NULL;
+#endif
 }
 
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_TIMER_THREAD
 isc_result_t
-isc__timermgr_nextevent(isc_time_t *when) {
-       if (timermgr == NULL || timermgr->nscheduled == 0)
+isc__timermgr_nextevent(isc_timermgr_t *manager0, isc_time_t *when) {
+       isc__timermgr_t *manager = (isc__timermgr_t *)manager0;
+
+#ifdef USE_SHARED_MANAGER
+       if (manager == NULL)
+               manager = timermgr;
+#endif
+       if (manager == NULL || manager->nscheduled == 0)
                return (ISC_R_NOTFOUND);
-       *when = timermgr->due;
+       *when = manager->due;
        return (ISC_R_SUCCESS);
 }
 
 void
-isc__timermgr_dispatch(void) {
+isc__timermgr_dispatch(isc_timermgr_t *manager0) {
+       isc__timermgr_t *manager = (isc__timermgr_t *)manager0;
        isc_time_t now;
-       if (timermgr == NULL)
+
+#ifdef USE_SHARED_MANAGER
+       if (manager == NULL)
+               manager = timermgr;
+#endif
+       if (manager == NULL)
                return;
        TIME_NOW(&now);
-       dispatch(timermgr, &now);
+       dispatch(manager, &now);
 }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_TIMER_THREAD */
+
+#ifdef USE_TIMERIMPREGISTER
+isc_result_t
+isc__timer_register() {
+       return (isc_timer_register(isc__timermgr_create));
+}
+#endif
diff --git a/lib/isc/timer_api.c b/lib/isc/timer_api.c
new file mode 100644 (file)
index 0000000..97e62b3
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: timer_api.c,v 1.4 2009/09/02 23:48:02 tbox Exp $ */
+
+#include <config.h>
+
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_timermgrcreatefunc_t timermgr_createfunc = NULL;
+
+static void
+initialize(void) {
+       RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_timer_register(isc_timermgrcreatefunc_t createfunc) {
+       isc_result_t result = ISC_R_SUCCESS;
+
+       RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+       LOCK(&createlock);
+       if (timermgr_createfunc == NULL)
+               timermgr_createfunc = createfunc;
+       else
+               result = ISC_R_EXISTS;
+       UNLOCK(&createlock);
+
+       return (result);
+}
+
+isc_result_t
+isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+                        isc_timermgr_t **managerp)
+{
+       isc_result_t result;
+
+       LOCK(&createlock);
+
+       REQUIRE(timermgr_createfunc != NULL);
+       result = (*timermgr_createfunc)(mctx, managerp);
+
+       UNLOCK(&createlock);
+
+       if (result == ISC_R_SUCCESS)
+               isc_appctx_settimermgr(actx, *managerp);
+
+       return (result);
+}
+
+isc_result_t
+isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
+       isc_result_t result;
+
+       LOCK(&createlock);
+
+       REQUIRE(timermgr_createfunc != NULL);
+       result = (*timermgr_createfunc)(mctx, managerp);
+
+       UNLOCK(&createlock);
+
+       return (result);
+}
+
+void
+isc_timermgr_destroy(isc_timermgr_t **managerp) {
+       REQUIRE(*managerp != NULL && ISCAPI_TIMERMGR_VALID(*managerp));
+
+       (*managerp)->methods->destroy(managerp);
+
+       ENSURE(*managerp == NULL);
+}
+
+isc_result_t
+isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type,
+                isc_time_t *expires, isc_interval_t *interval,
+                isc_task_t *task, isc_taskaction_t action, const void *arg,
+                isc_timer_t **timerp)
+{
+       REQUIRE(ISCAPI_TIMERMGR_VALID(manager));
+
+       return (manager->methods->timercreate(manager, type, expires,
+                                             interval, task, action, arg,
+                                             timerp));
+}
+
+void
+isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) {
+       REQUIRE(ISCAPI_TIMER_VALID(timer));
+       REQUIRE(timerp != NULL && *timerp == NULL);
+
+       timer->methods->attach(timer, timerp);
+
+       ENSURE(*timerp == timer);
+}
+
+void
+isc_timer_detach(isc_timer_t **timerp) {
+       REQUIRE(timerp != NULL && ISCAPI_TIMER_VALID(*timerp));
+
+       (*timerp)->methods->detach(timerp);
+
+       ENSURE(*timerp == NULL);
+}
+
+isc_result_t
+isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
+               isc_time_t *expires, isc_interval_t *interval,
+               isc_boolean_t purge)
+{
+       REQUIRE(ISCAPI_TIMER_VALID(timer));
+
+       return (timer->methods->reset(timer, type, expires, interval, purge));
+}
+
+isc_result_t
+isc_timer_touch(isc_timer_t *timer) {
+       REQUIRE(ISCAPI_TIMER_VALID(timer));
+
+       return (timer->methods->touch(timer));
+}
index ec8e2e0b788481b7431ceff07d71a25d1843c675..d6f7c996c7e234e1c4dbc03c44ec54dded7fed05 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: timer_p.h,v 1.10 2007/06/19 23:47:17 tbox Exp $ */
+/* $Id: timer_p.h,v 1.12 2009/09/02 23:48:02 tbox Exp $ */
 
 #ifndef ISC_TIMER_P_H
 #define ISC_TIMER_P_H
@@ -23,9 +23,9 @@
 /*! \file */
 
 isc_result_t
-isc__timermgr_nextevent(isc_time_t *when);
+isc__timermgr_nextevent(isc_timermgr_t *timermgr, isc_time_t *when);
 
 void
-isc__timermgr_dispatch(void);
+isc__timermgr_dispatch(isc_timermgr_t *timermgr);
 
 #endif /* ISC_TIMER_P_H */
index 660b438678d6b063a120bdcd4f4a212e2a5db924..5393be94250434ae537e235917bf669f0d0c561c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: app.c,v 1.60 2008/10/15 03:41:17 marka Exp $ */
+/* $Id: app.c,v 1.64 2009/11/04 05:58:46 marka Exp $ */
 
 /*! \file */
 
@@ -37,6 +37,7 @@
 #include <isc/app.h>
 #include <isc/boolean.h>
 #include <isc/condition.h>
+#include <isc/mem.h>
 #include <isc/msgs.h>
 #include <isc/mutex.h>
 #include <isc/event.h>
 #include <isc/time.h>
 #include <isc/util.h>
 
+/*%
+ * For BIND9 internal applications built with threads, we use a single app
+ * context and let multiple worker, I/O, timer threads do actual jobs.
+ * For other cases (including BIND9 built without threads) an app context acts
+ * as an event loop dispatching various events.
+ */
+#if defined(ISC_PLATFORM_USETHREADS) && defined(BIND9)
+#define USE_THREADS_SINGLECTX
+#endif
+
 #ifdef ISC_PLATFORM_USETHREADS
 #include <pthread.h>
-#else /* ISC_PLATFORM_USETHREADS */
+#endif
+
+#ifndef USE_THREADS_SINGLECTX
 #include "../timer_p.h"
 #include "../task_p.h"
 #include "socket_p.h"
+#endif /* USE_THREADS_SINGLECTX */
+
+#ifdef ISC_PLATFORM_USETHREADS
+static pthread_t               blockedthread;
 #endif /* ISC_PLATFORM_USETHREADS */
 
-static isc_eventlist_t         on_run;
-static isc_mutex_t             lock;
-static isc_boolean_t           shutdown_requested = ISC_FALSE;
-static isc_boolean_t           running = ISC_FALSE;
-/*!
- * We assume that 'want_shutdown' can be read and written atomically.
+/*%
+ * The following can be either static or public, depending on build environment.
  */
-static volatile isc_boolean_t  want_shutdown = ISC_FALSE;
+
+#ifdef BIND9
+#define ISC_APPFUNC_SCOPE
+#else
+#define ISC_APPFUNC_SCOPE static
+#endif
+
+ISC_APPFUNC_SCOPE isc_result_t isc__app_start(void);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxstart(isc_appctx_t *ctx);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_onrun(isc_mem_t *mctx,
+                                             isc_task_t *task,
+                                             isc_taskaction_t action,
+                                             void *arg);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxrun(isc_appctx_t *ctx);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_run(void);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxshutdown(isc_appctx_t *ctx);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_shutdown(void);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_reload(void);
+ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxsuspend(isc_appctx_t *ctx);
+ISC_APPFUNC_SCOPE void isc__app_ctxfinish(isc_appctx_t *ctx);
+ISC_APPFUNC_SCOPE void isc__app_finish(void);
+ISC_APPFUNC_SCOPE void isc__app_block(void);
+ISC_APPFUNC_SCOPE void isc__app_unblock(void);
+ISC_APPFUNC_SCOPE isc_result_t isc__appctx_create(isc_mem_t *mctx,
+                                                 isc_appctx_t **ctxp);
+ISC_APPFUNC_SCOPE void isc__appctx_destroy(isc_appctx_t **ctxp);
+ISC_APPFUNC_SCOPE void isc__appctx_settaskmgr(isc_appctx_t *ctx,
+                                             isc_taskmgr_t *taskmgr);
+ISC_APPFUNC_SCOPE void isc__appctx_setsocketmgr(isc_appctx_t *ctx,
+                                               isc_socketmgr_t *socketmgr);
+ISC_APPFUNC_SCOPE void isc__appctx_settimermgr(isc_appctx_t *ctx,
+                                              isc_timermgr_t *timermgr);
+
 /*
- * We assume that 'want_reload' can be read and written atomically.
+ * The application context of this module.  This implementation actually
+ * doesn't use it. (This may change in the future).
  */
-static volatile isc_boolean_t  want_reload = ISC_FALSE;
+#define APPCTX_MAGIC           ISC_MAGIC('A', 'p', 'c', 'x')
+#define VALID_APPCTX(c)                ISC_MAGIC_VALID(c, APPCTX_MAGIC)
+
+typedef struct isc__appctx {
+       isc_appctx_t            common;
+       isc_mem_t               *mctx;
+       isc_mutex_t             lock;
+       isc_eventlist_t         on_run;
+       isc_boolean_t           shutdown_requested;
+       isc_boolean_t           running;
+
+       /*!
+        * We assume that 'want_shutdown' can be read and written atomically.
+        */
+       isc_boolean_t           want_shutdown;
+       /*
+        * We assume that 'want_reload' can be read and written atomically.
+        */
+       isc_boolean_t           want_reload;
 
-static isc_boolean_t           blocked  = ISC_FALSE;
-#ifdef ISC_PLATFORM_USETHREADS
-static pthread_t               blockedthread;
-#endif /* ISC_PLATFORM_USETHREADS */
+       isc_boolean_t           blocked;
+
+       isc_taskmgr_t           *taskmgr;
+       isc_socketmgr_t         *socketmgr;
+       isc_timermgr_t          *timermgr;
+} isc__appctx_t;
+
+static isc__appctx_t isc_g_appctx;
+
+static struct {
+       isc_appmethods_t methods;
+
+       /*%
+        * The following are defined just for avoiding unused static functions.
+        */
+#ifndef BIND9
+       void *run, *shutdown, *start, *onrun, *reload, *finish,
+               *block, *unblock;
+#endif
+} appmethods = {
+       {
+               isc__appctx_destroy,
+               isc__app_ctxstart,
+               isc__app_ctxrun,
+               isc__app_ctxsuspend,
+               isc__app_ctxshutdown,
+               isc__app_ctxfinish,
+               isc__appctx_settaskmgr,
+               isc__appctx_setsocketmgr,
+               isc__appctx_settimermgr
+       }
+#ifndef BIND9
+       ,
+       (void *)isc__app_run, (void *)isc__app_shutdown,
+       (void *)isc__app_start, (void *)isc__app_onrun, (void *)isc__app_reload,
+       (void *)isc__app_finish, (void *)isc__app_block,
+       (void *)isc__app_unblock
+#endif
+};
 
 #ifdef HAVE_LINUXTHREADS
 /*!
@@ -91,13 +190,13 @@ static pthread_t           main_thread;
 static void
 exit_action(int arg) {
        UNUSED(arg);
-       want_shutdown = ISC_TRUE;
+       isc_g_appctx.want_shutdown = ISC_TRUE;
 }
 
 static void
 reload_action(int arg) {
        UNUSED(arg);
-       want_reload = ISC_TRUE;
+       isc_g_appctx.want_reload = ISC_TRUE;
 }
 #endif
 
@@ -123,12 +222,12 @@ handle_signal(int sig, void (*handler)(int)) {
        return (ISC_R_SUCCESS);
 }
 
-isc_result_t
-isc_app_start(void) {
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_ctxstart(isc_appctx_t *ctx0) {
+       isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
        isc_result_t result;
-       int presult;
-       sigset_t sset;
-       char strbuf[ISC_STRERRORSIZE];
+
+       REQUIRE(VALID_APPCTX(ctx));
 
        /*
         * Start an ISC library application.
@@ -151,7 +250,35 @@ isc_app_start(void) {
        main_thread = pthread_self();
 #endif
 
-       result = isc_mutex_init(&lock);
+       result = isc_mutex_init(&ctx->lock);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+
+       ISC_LIST_INIT(ctx->on_run);
+
+       ctx->shutdown_requested = ISC_FALSE;
+       ctx->running = ISC_FALSE;
+       ctx->want_shutdown = ISC_FALSE;
+       ctx->want_reload = ISC_FALSE;
+       ctx->blocked = ISC_FALSE;
+
+       return (ISC_R_SUCCESS);
+}
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_start(void) {
+       isc_result_t result;
+       int presult;
+       sigset_t sset;
+       char strbuf[ISC_STRERRORSIZE];
+
+       isc_g_appctx.common.impmagic = APPCTX_MAGIC;
+       isc_g_appctx.common.magic = ISCAPI_APPCTX_MAGIC;
+       isc_g_appctx.common.methods = &appmethods.methods;
+       isc_g_appctx.mctx = NULL;
+       /* The remaining members will be initialized in ctxstart() */
+
+       result = isc__app_ctxstart((isc_appctx_t *)&isc_g_appctx);
        if (result != ISC_R_SUCCESS)
                return (result);
 
@@ -253,22 +380,20 @@ isc_app_start(void) {
        }
 #endif /* ISC_PLATFORM_USETHREADS */
 
-       ISC_LIST_INIT(on_run);
-
        return (ISC_R_SUCCESS);
 }
 
-isc_result_t
-isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
              void *arg)
 {
        isc_event_t *event;
        isc_task_t *cloned_task = NULL;
        isc_result_t result;
 
-       LOCK(&lock);
+       LOCK(&isc_g_appctx.lock);
 
-       if (running) {
+       if (isc_g_appctx.running) {
                result = ISC_R_ALREADYRUNNING;
                goto unlock;
        }
@@ -285,24 +410,25 @@ isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
                goto unlock;
        }
 
-       ISC_LIST_APPEND(on_run, event, ev_link);
+       ISC_LIST_APPEND(isc_g_appctx.on_run, event, ev_link);
 
        result = ISC_R_SUCCESS;
 
  unlock:
-       UNLOCK(&lock);
+       UNLOCK(&isc_g_appctx.lock);
 
        return (result);
 }
 
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_THREADS_SINGLECTX
 /*!
  * Event loop for nonthreaded programs.
  */
 static isc_result_t
-evloop(void) {
+evloop(isc__appctx_t *ctx) {
        isc_result_t result;
-       while (!want_shutdown) {
+
+       while (!ctx->want_shutdown) {
                int n;
                isc_time_t when, now;
                struct timeval tv, *tvp;
@@ -310,14 +436,27 @@ evloop(void) {
                isc_boolean_t readytasks;
                isc_boolean_t call_timer_dispatch = ISC_FALSE;
 
-               readytasks = isc__taskmgr_ready();
+               /*
+                * Check the reload (or suspend) case first for exiting the
+                * loop as fast as possible in case:
+                *   - the direct call to isc__taskmgr_dispatch() in
+                *     isc__app_ctxrun() completes all the tasks so far,
+                *   - there is thus currently no active task, and
+                *   - there is a timer event
+                */
+               if (ctx->want_reload) {
+                       ctx->want_reload = ISC_FALSE;
+                       return (ISC_R_RELOAD);
+               }
+
+               readytasks = isc__taskmgr_ready(ctx->taskmgr);
                if (readytasks) {
                        tv.tv_sec = 0;
                        tv.tv_usec = 0;
                        tvp = &tv;
                        call_timer_dispatch = ISC_TRUE;
                } else {
-                       result = isc__timermgr_nextevent(&when);
+                       result = isc__timermgr_nextevent(ctx->timermgr, &when);
                        if (result != ISC_R_SUCCESS)
                                tvp = NULL;
                        else {
@@ -334,7 +473,7 @@ evloop(void) {
                }
 
                swait = NULL;
-               n = isc__socketmgr_waitevents(tvp, &swait);
+               n = isc__socketmgr_waitevents(ctx->socketmgr, tvp, &swait);
 
                if (n == 0 || call_timer_dispatch) {
                        /*
@@ -351,20 +490,17 @@ evloop(void) {
                         * call, since this loop only runs in the non-thread
                         * mode.
                         */
-                       isc__timermgr_dispatch();
+                       isc__timermgr_dispatch(ctx->timermgr);
                }
                if (n > 0)
-                       (void)isc__socketmgr_dispatch(swait);
-               (void)isc__taskmgr_dispatch();
-
-               if (want_reload) {
-                       want_reload = ISC_FALSE;
-                       return (ISC_R_RELOAD);
-               }
+                       (void)isc__socketmgr_dispatch(ctx->socketmgr, swait);
+               (void)isc__taskmgr_dispatch(ctx->taskmgr);
        }
        return (ISC_R_SUCCESS);
 }
+#endif /* USE_THREADS_SINGLECTX */
 
+#ifndef ISC_PLATFORM_USETHREADS
 /*
  * This is a gross hack to support waiting for condition
  * variables in nonthreaded programs in a limited way;
@@ -400,11 +536,11 @@ isc__nothread_wait_hack(isc_condition_t *cp, isc_mutex_t *mp) {
        INSIST(*mp == 1); /* Mutex must be locked on entry. */
        --*mp;
 
-       result = evloop();
+       result = evloop(&isc_g_appctx);
        if (result == ISC_R_RELOAD)
-               want_reload = ISC_TRUE;
+               isc_g_appctx.want_reload = ISC_TRUE;
        if (signalled) {
-               want_shutdown = ISC_FALSE;
+               isc_g_appctx.want_shutdown = ISC_FALSE;
                signalled = ISC_FALSE;
        }
 
@@ -420,43 +556,46 @@ isc__nothread_signal_hack(isc_condition_t *cp) {
 
        INSIST(in_recursive_evloop);
 
-       want_shutdown = ISC_TRUE;
+       isc_g_appctx.want_shutdown = ISC_TRUE;
        signalled = ISC_TRUE;
        return (ISC_R_SUCCESS);
 }
 
 #endif /* ISC_PLATFORM_USETHREADS */
 
-isc_result_t
-isc_app_run(void) {
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_ctxrun(isc_appctx_t *ctx0) {
+       isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
        int result;
        isc_event_t *event, *next_event;
        isc_task_t *task;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_THREADS_SINGLECTX
        sigset_t sset;
        char strbuf[ISC_STRERRORSIZE];
 #ifdef HAVE_SIGWAIT
        int sig;
 #endif
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_THREADS_SINGLECTX */
+
+       REQUIRE(VALID_APPCTX(ctx));
 
 #ifdef HAVE_LINUXTHREADS
        REQUIRE(main_thread == pthread_self());
 #endif
 
-       LOCK(&lock);
+       LOCK(&ctx->lock);
 
-       if (!running) {
-               running = ISC_TRUE;
+       if (!ctx->running) {
+               ctx->running = ISC_TRUE;
 
                /*
                 * Post any on-run events (in FIFO order).
                 */
-               for (event = ISC_LIST_HEAD(on_run);
+               for (event = ISC_LIST_HEAD(ctx->on_run);
                     event != NULL;
                     event = next_event) {
                        next_event = ISC_LIST_NEXT(event, ev_link);
-                       ISC_LIST_UNLINK(on_run, event, ev_link);
+                       ISC_LIST_UNLINK(ctx->on_run, event, ev_link);
                        task = event->ev_sender;
                        event->ev_sender = NULL;
                        isc_task_sendanddetach(&task, &event);
@@ -464,7 +603,7 @@ isc_app_run(void) {
 
        }
 
-       UNLOCK(&lock);
+       UNLOCK(&ctx->lock);
 
 #ifndef HAVE_SIGWAIT
        /*
@@ -473,19 +612,27 @@ isc_app_run(void) {
         * We do this here to ensure that the signal handler is installed
         * (i.e. that it wasn't a "one-shot" handler).
         */
-       result = handle_signal(SIGHUP, reload_action);
-       if (result != ISC_R_SUCCESS)
-               return (ISC_R_SUCCESS);
+       if (ctx == &isc_g_appctx) {
+               result = handle_signal(SIGHUP, reload_action);
+               if (result != ISC_R_SUCCESS)
+                       return (ISC_R_SUCCESS);
+       }
 #endif
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_THREADS_SINGLECTX
+       /*
+        * When we are using multiple contexts, we don't rely on signals.
+        */
+       if (ctx != &isc_g_appctx)
+               return (ISC_R_SUCCESS);
+
        /*
         * There is no danger if isc_app_shutdown() is called before we wait
         * for signals.  Signals are blocked, so any such signal will simply
         * be made pending and we will get it when we call sigwait().
         */
 
-       while (!want_shutdown) {
+       while (!ctx->want_shutdown) {
 #ifdef HAVE_SIGWAIT
                /*
                 * Wait for SIGHUP, SIGINT, or SIGTERM.
@@ -503,21 +650,19 @@ isc_app_run(void) {
 #ifndef HAVE_UNIXWARE_SIGWAIT
                result = sigwait(&sset, &sig);
                if (result == 0) {
-                       if (sig == SIGINT ||
-                           sig == SIGTERM)
-                               want_shutdown = ISC_TRUE;
+                       if (sig == SIGINT || sig == SIGTERM)
+                               ctx->want_shutdown = ISC_TRUE;
                        else if (sig == SIGHUP)
-                               want_reload = ISC_TRUE;
+                               ctx->want_reload = ISC_TRUE;
                }
 
 #else /* Using UnixWare sigwait semantics. */
                sig = sigwait(&sset);
                if (sig >= 0) {
-                       if (sig == SIGINT ||
-                           sig == SIGTERM)
-                               want_shutdown = ISC_TRUE;
+                       if (sig == SIGINT || sig == SIGTERM)
+                               ctx->want_shutdown = ISC_TRUE;
                        else if (sig == SIGHUP)
-                               want_reload = ISC_TRUE;
+                               ctx->want_reload = ISC_TRUE;
                }
 
 #endif /* HAVE_UNIXWARE_SIGWAIT */
@@ -528,131 +673,174 @@ isc_app_run(void) {
                if (sigemptyset(&sset) != 0) {
                        isc__strerror(errno, strbuf, sizeof(strbuf));
                        UNEXPECTED_ERROR(__FILE__, __LINE__,
-                                        "isc_app_run() sigsetops: %s", strbuf);
+                                        "isc_app_run() sigsetops: %s",
+                                        strbuf);
                        return (ISC_R_UNEXPECTED);
                }
                result = sigsuspend(&sset);
 #endif /* HAVE_SIGWAIT */
 
-               if (want_reload) {
-                       want_reload = ISC_FALSE;
+               if (ctx->want_reload) {
+                       ctx->want_reload = ISC_FALSE;
                        return (ISC_R_RELOAD);
                }
 
-               if (want_shutdown && blocked)
+               if (ctx->want_shutdown && ctx->blocked)
                        exit(1);
        }
 
-#else /* ISC_PLATFORM_USETHREADS */
+#else /* USE_THREADS_SINGLECTX */
 
-       (void)isc__taskmgr_dispatch();
+       (void)isc__taskmgr_dispatch(ctx->taskmgr);
 
-       result = evloop();
+       result = evloop(ctx);
        if (result != ISC_R_SUCCESS)
                return (result);
 
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_THREADS_SINGLECTX */
 
        return (ISC_R_SUCCESS);
 }
 
-isc_result_t
-isc_app_shutdown(void) {
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_run() {
+       return (isc__app_ctxrun((isc_appctx_t *)&isc_g_appctx));
+}
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_ctxshutdown(isc_appctx_t *ctx0) {
+       isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
        isc_boolean_t want_kill = ISC_TRUE;
        char strbuf[ISC_STRERRORSIZE];
 
-       LOCK(&lock);
+       REQUIRE(VALID_APPCTX(ctx));
 
-       REQUIRE(running);
+       LOCK(&ctx->lock);
 
-       if (shutdown_requested)
+       REQUIRE(ctx->running);
+
+       if (ctx->shutdown_requested)
                want_kill = ISC_FALSE;
        else
-               shutdown_requested = ISC_TRUE;
+               ctx->shutdown_requested = ISC_TRUE;
 
-       UNLOCK(&lock);
+       UNLOCK(&ctx->lock);
 
        if (want_kill) {
+               if (ctx != &isc_g_appctx)
+                       ctx->want_shutdown = ISC_TRUE;
+               else {
 #ifdef HAVE_LINUXTHREADS
-               int result;
-
-               result = pthread_kill(main_thread, SIGTERM);
-               if (result != 0) {
-                       isc__strerror(result, strbuf, sizeof(strbuf));
-                       UNEXPECTED_ERROR(__FILE__, __LINE__,
-                                        "isc_app_shutdown() pthread_kill: %s",
-                                        strbuf);
-                       return (ISC_R_UNEXPECTED);
-               }
+                       int result;
+
+                       result = pthread_kill(main_thread, SIGTERM);
+                       if (result != 0) {
+                               isc__strerror(result, strbuf, sizeof(strbuf));
+                               UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                                "isc_app_shutdown() "
+                                                "pthread_kill: %s",
+                                                strbuf);
+                               return (ISC_R_UNEXPECTED);
+                       }
 #else
-               if (kill(getpid(), SIGTERM) < 0) {
-                       isc__strerror(errno, strbuf, sizeof(strbuf));
-                       UNEXPECTED_ERROR(__FILE__, __LINE__,
-                                        "isc_app_shutdown() kill: %s", strbuf);
-                       return (ISC_R_UNEXPECTED);
+                       if (kill(getpid(), SIGTERM) < 0) {
+                               isc__strerror(errno, strbuf, sizeof(strbuf));
+                               UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                                "isc_app_shutdown() "
+                                                "kill: %s", strbuf);
+                               return (ISC_R_UNEXPECTED);
+                       }
+#endif /* HAVE_LINUXTHREADS */
                }
-#endif
        }
 
        return (ISC_R_SUCCESS);
 }
 
-isc_result_t
-isc_app_reload(void) {
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_shutdown() {
+       return (isc__app_ctxshutdown((isc_appctx_t *)&isc_g_appctx));
+}
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_ctxsuspend(isc_appctx_t *ctx0) {
+       isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
        isc_boolean_t want_kill = ISC_TRUE;
        char strbuf[ISC_STRERRORSIZE];
 
-       LOCK(&lock);
+       REQUIRE(VALID_APPCTX(ctx));
+
+       LOCK(&ctx->lock);
 
-       REQUIRE(running);
+       REQUIRE(ctx->running);
 
        /*
         * Don't send the reload signal if we're shutting down.
         */
-       if (shutdown_requested)
+       if (ctx->shutdown_requested)
                want_kill = ISC_FALSE;
 
-       UNLOCK(&lock);
+       UNLOCK(&ctx->lock);
 
        if (want_kill) {
+               if (ctx != &isc_g_appctx)
+                       ctx->want_reload = ISC_TRUE;
+               else {
 #ifdef HAVE_LINUXTHREADS
-               int result;
-
-               result = pthread_kill(main_thread, SIGHUP);
-               if (result != 0) {
-                       isc__strerror(result, strbuf, sizeof(strbuf));
-                       UNEXPECTED_ERROR(__FILE__, __LINE__,
-                                        "isc_app_reload() pthread_kill: %s",
-                                        strbuf);
-                       return (ISC_R_UNEXPECTED);
-               }
+                       int result;
+
+                       result = pthread_kill(main_thread, SIGHUP);
+                       if (result != 0) {
+                               isc__strerror(result, strbuf, sizeof(strbuf));
+                               UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                                "isc_app_reload() "
+                                                "pthread_kill: %s",
+                                                strbuf);
+                               return (ISC_R_UNEXPECTED);
+                       }
 #else
-               if (kill(getpid(), SIGHUP) < 0) {
-                       isc__strerror(errno, strbuf, sizeof(strbuf));
-                       UNEXPECTED_ERROR(__FILE__, __LINE__,
-                                        "isc_app_reload() kill: %s", strbuf);
-                       return (ISC_R_UNEXPECTED);
-               }
+                       if (kill(getpid(), SIGHUP) < 0) {
+                               isc__strerror(errno, strbuf, sizeof(strbuf));
+                               UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                                "isc_app_reload() "
+                                                "kill: %s", strbuf);
+                               return (ISC_R_UNEXPECTED);
+                       }
 #endif
+               }
        }
 
        return (ISC_R_SUCCESS);
 }
 
-void
-isc_app_finish(void) {
-       DESTROYLOCK(&lock);
+ISC_APPFUNC_SCOPE isc_result_t
+isc__app_reload(void) {
+       return (isc__app_ctxsuspend((isc_appctx_t *)&isc_g_appctx));
+}
+
+ISC_APPFUNC_SCOPE void
+isc__app_ctxfinish(isc_appctx_t *ctx0) {
+       isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+
+       REQUIRE(VALID_APPCTX(ctx));
+
+       DESTROYLOCK(&ctx->lock);
+}
+
+ISC_APPFUNC_SCOPE void
+isc__app_finish(void) {
+       isc__app_ctxfinish((isc_appctx_t *)&isc_g_appctx);
 }
 
-void
-isc_app_block(void) {
+ISC_APPFUNC_SCOPE void
+isc__app_block(void) {
 #ifdef ISC_PLATFORM_USETHREADS
        sigset_t sset;
 #endif /* ISC_PLATFORM_USETHREADS */
-       REQUIRE(running);
-       REQUIRE(!blocked);
+       REQUIRE(isc_g_appctx.running);
+       REQUIRE(!isc_g_appctx.blocked);
 
-       blocked = ISC_TRUE;
+       isc_g_appctx.blocked = ISC_TRUE;
 #ifdef ISC_PLATFORM_USETHREADS
        blockedthread = pthread_self();
        RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
@@ -662,16 +850,16 @@ isc_app_block(void) {
 #endif /* ISC_PLATFORM_USETHREADS */
 }
 
-void
-isc_app_unblock(void) {
+ISC_APPFUNC_SCOPE void
+isc__app_unblock(void) {
 #ifdef ISC_PLATFORM_USETHREADS
        sigset_t sset;
 #endif /* ISC_PLATFORM_USETHREADS */
 
-       REQUIRE(running);
-       REQUIRE(blocked);
+       REQUIRE(isc_g_appctx.running);
+       REQUIRE(isc_g_appctx.blocked);
 
-       blocked = ISC_FALSE;
+       isc_g_appctx.blocked = ISC_FALSE;
 
 #ifdef ISC_PLATFORM_USETHREADS
        REQUIRE(blockedthread == pthread_self());
@@ -682,3 +870,77 @@ isc_app_unblock(void) {
        RUNTIME_CHECK(pthread_sigmask(SIG_BLOCK, &sset, NULL) == 0);
 #endif /* ISC_PLATFORM_USETHREADS */
 }
+
+ISC_APPFUNC_SCOPE isc_result_t
+isc__appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) {
+       isc__appctx_t *ctx;
+
+       REQUIRE(mctx != NULL);
+       REQUIRE(ctxp != NULL && *ctxp == NULL);
+
+       ctx = isc_mem_get(mctx, sizeof(*ctx));
+       if (ctx == NULL)
+               return (ISC_R_NOMEMORY);
+
+       ctx->common.impmagic = APPCTX_MAGIC;
+       ctx->common.magic = ISCAPI_APPCTX_MAGIC;
+       ctx->common.methods = &appmethods.methods;
+
+       ctx->mctx = NULL;
+       isc_mem_attach(mctx, &ctx->mctx);
+
+       ctx->taskmgr = NULL;
+       ctx->socketmgr = NULL;
+       ctx->timermgr = NULL;
+
+       *ctxp = (isc_appctx_t *)ctx;
+
+       return (ISC_R_SUCCESS);
+}
+
+ISC_APPFUNC_SCOPE void
+isc__appctx_destroy(isc_appctx_t **ctxp) {
+       isc__appctx_t *ctx;
+
+       REQUIRE(ctxp != NULL);
+       ctx = (isc__appctx_t *)*ctxp;
+       REQUIRE(VALID_APPCTX(ctx));
+
+       isc_mem_putanddetach(&ctx->mctx, ctx, sizeof(*ctx));
+
+       *ctxp = NULL;
+}
+
+ISC_APPFUNC_SCOPE void
+isc__appctx_settaskmgr(isc_appctx_t *ctx0, isc_taskmgr_t *taskmgr) {
+       isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+
+       REQUIRE(VALID_APPCTX(ctx));
+
+       ctx->taskmgr = taskmgr;
+}
+
+ISC_APPFUNC_SCOPE void
+isc__appctx_setsocketmgr(isc_appctx_t *ctx0, isc_socketmgr_t *socketmgr) {
+       isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+
+       REQUIRE(VALID_APPCTX(ctx));
+
+       ctx->socketmgr = socketmgr;
+}
+
+ISC_APPFUNC_SCOPE void
+isc__appctx_settimermgr(isc_appctx_t *ctx0, isc_timermgr_t *timermgr) {
+       isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+
+       REQUIRE(VALID_APPCTX(ctx));
+
+       ctx->timermgr = timermgr;
+}
+
+#ifdef USE_APPIMPREGISTER
+isc_result_t
+isc__app_register() {
+       return (isc_app_register(isc__appctx_create));
+}
+#endif
index 924414759d06dae4f7cb991610ef8a7aef0e4cba..0d647782a1d9a99f598230c2109c09500d489b63 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dir.c,v 1.25.332.3 2009/02/16 23:47:15 tbox Exp $ */
+/* $Id$ */
 
 /*! \file
  * \author  Principal Authors: DCL */
@@ -79,7 +79,7 @@ isc_dir_open(isc_dir_t *dir, const char *dirname) {
        if (dir->dirname < p && *(p - 1) != '/')
                *p++ = '/';
        *p++ = '*';
-       *p++ = '\0';
+       *p = '\0';
 
        /*
         * Open stream.
index 0e9e2979e3064c8729ce200b18dca2706627711e..ab53faf6754edb114a64aab7454e30adb754cbd9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: entropy.c,v 1.80.332.2 2009/02/16 23:47:15 tbox Exp $ */
+/* $Id: entropy.c,v 1.82 2008/12/01 23:47:45 tbox Exp $ */
 
 /* \file unix/entropy.c
  * \brief
index 606c5600c2f8073b061e1e5881cc635165469a24..f20aa295ca9c2c3b278c0af829028d99232e0b8b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000-2002  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: errno2result.c,v 1.17 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id$ */
 
 /*! \file */
 
@@ -34,7 +34,7 @@
  * not already there.
  */
 isc_result_t
-isc__errno2result(int posixerrno) {
+isc___errno2result(int posixerrno, const char *file, unsigned int line) {
        char strbuf[ISC_STRERRORSIZE];
 
        switch (posixerrno) {
@@ -55,7 +55,7 @@ isc__errno2result(int posixerrno) {
                return (ISC_R_IOERROR);
        case ENOMEM:
                return (ISC_R_NOMEMORY);
-       case ENFILE:    
+       case ENFILE:
        case EMFILE:
                return (ISC_R_TOOMANYOPENFILES);
        case EPIPE:
@@ -108,8 +108,7 @@ isc__errno2result(int posixerrno) {
                return (ISC_R_CONNREFUSED);
        default:
                isc__strerror(posixerrno, strbuf, sizeof(strbuf));
-               UNEXPECTED_ERROR(__FILE__, __LINE__,
-                                "unable to convert errno "
+               UNEXPECTED_ERROR(file, line, "unable to convert errno "
                                 "to isc_result: %d: %s",
                                 posixerrno, strbuf);
                /*
index b5b658d500cdd7bc959aa7a9ca2d58518f7c4388..1e49ed1d6c895e4bd77edea4a77456e1b1bb9b65 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: errno2result.h,v 1.12 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id$ */
 
 #ifndef UNIX_ERRNO2RESULT_H
 #define UNIX_ERRNO2RESULT_H 1
 
 ISC_LANG_BEGINDECLS
 
+#define isc__errno2result(x) isc___errno2result(x, __FILE__, __LINE__)
+
 isc_result_t
-isc__errno2result(int posixerrno);
+isc___errno2result(int posixerrno, const char *file, unsigned int line);
 
 ISC_LANG_ENDDECLS
 
index 748aee889c115d9e1221e093292fc49791175f2e..0538761a2af7dd42b9fc40479c9d8990260b9946 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000-2002  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -48,7 +48,7 @@
  * SUCH DAMAGE.
  */
 
-/* $Id: file.c,v 1.51.332.2 2009/02/16 23:47:15 tbox Exp $ */
+/* $Id$ */
 
 /*! \file */
 
@@ -68,6 +68,7 @@
 #include <isc/dir.h>
 #include <isc/file.h>
 #include <isc/log.h>
+#include <isc/mem.h>
 #include <isc/random.h>
 #include <isc/string.h>
 #include <isc/time.h>
@@ -242,16 +243,26 @@ isc_file_renameunique(const char *file, char *templet) {
        return (ISC_R_SUCCESS);
 }
 
-
 isc_result_t
 isc_file_openunique(char *templet, FILE **fp) {
+       int mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
+       return (isc_file_openuniquemode(templet, mode, fp));
+}
+
+isc_result_t
+isc_file_openuniqueprivate(char *templet, FILE **fp) {
+       int mode = S_IWUSR|S_IRUSR;
+       return (isc_file_openuniquemode(templet, mode, fp));
+}
+
+isc_result_t
+isc_file_openuniquemode(char *templet, int mode, FILE **fp) {
        int fd;
        FILE *f;
        isc_result_t result = ISC_R_SUCCESS;
        char *x;
        char *cp;
        isc_uint32_t which;
-       int mode;
 
        REQUIRE(templet != NULL);
        REQUIRE(fp != NULL && *fp == NULL);
@@ -269,7 +280,6 @@ isc_file_openunique(char *templet, FILE **fp) {
                x = cp--;
        }
 
-       mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
 
        while ((fd = open(templet, O_RDWR|O_CREAT|O_EXCL, mode)) == -1) {
                if (errno != EEXIST)
@@ -338,6 +348,23 @@ isc_file_exists(const char *pathname) {
        return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS));
 }
 
+isc_result_t
+isc_file_isplainfile(const char *filename) {
+       /*
+        * This function returns success if filename is a plain file.
+        */
+       struct stat filestat;
+       memset(&filestat,0,sizeof(struct stat));
+
+       if ((stat(filename, &filestat)) == -1)
+               return(isc__errno2result(errno));
+
+       if(! S_ISREG(filestat.st_mode))
+               return(ISC_R_INVALIDFILE);
+
+       return(ISC_R_SUCCESS);
+}
+
 isc_boolean_t
 isc_file_isabsolute(const char *filename) {
        REQUIRE(filename != NULL);
@@ -442,3 +469,73 @@ isc_file_truncate(const char *filename, isc_offset_t size) {
                result = isc__errno2result(errno);
        return (result);
 }
+
+isc_result_t
+isc_file_safecreate(const char *filename, FILE **fp) {
+       isc_result_t result;
+       int flags;
+       struct stat sb;
+       FILE *f;
+       int fd;
+
+       REQUIRE(filename != NULL);
+       REQUIRE(fp != NULL && *fp == NULL);
+
+       result = file_stats(filename, &sb);
+       if (result == ISC_R_SUCCESS) {
+               if ((sb.st_mode & S_IFREG) == 0)
+                       return (ISC_R_INVALIDFILE);
+               flags = O_WRONLY | O_TRUNC;
+       } else if (result == ISC_R_FILENOTFOUND) {
+               flags = O_WRONLY | O_CREAT | O_EXCL;
+       } else
+               return (result);
+
+       fd = open(filename, flags, S_IRUSR | S_IWUSR);
+       if (fd == -1)
+               return (isc__errno2result(errno));
+
+       f = fdopen(fd, "w");
+       if (f == NULL) {
+               result = isc__errno2result(errno);
+               close(fd);
+               return (result);
+       }
+
+       *fp = f;
+       return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_splitpath(isc_mem_t *mctx, char *path, char **dirname, char **basename)
+{
+       char *dir, *file, *slash;
+
+       slash = strrchr(path, '/');
+
+       if (slash == path) {
+               file = ++slash;
+               dir = isc_mem_strdup(mctx, "/");
+       } else if (slash != NULL) {
+               file = ++slash;
+               dir = isc_mem_allocate(mctx, slash - path);
+               if (dir != NULL)
+                       strlcpy(dir, path, slash - path);
+       } else {
+               file = path;
+               dir = isc_mem_strdup(mctx, ".");
+       }
+
+       if (dir == NULL)
+               return (ISC_R_NOMEMORY);
+
+       if (*file == '\0') {
+               isc_mem_free(mctx, dir);
+               return (ISC_R_INVALIDFILE);
+       }
+
+       *dirname = dir;
+       *basename = file;
+
+       return (ISC_R_SUCCESS);
+}
index b576d4632fbb03357b2fcea662aa03ff8464a24d..637450aaf4f5d05d3dfb0512b5a9b39089af3d55 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: ifiter_getifaddrs.c,v 1.11 2008/03/20 23:47:00 tbox Exp $ */
+/* $Id: ifiter_getifaddrs.c,v 1.13 2009/09/24 23:48:13 tbox Exp $ */
 
 /*! \file
  * \brief
@@ -181,7 +181,7 @@ internal_current(isc_interfaceiter_t *iter) {
                         ifa->ifa_name);
 
        if (ifa->ifa_dstaddr != NULL &&
-           (iter->current.flags & IFF_POINTOPOINT) != 0)
+           (iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0)
                get_addr(family, &iter->current.dstaddress, ifa->ifa_dstaddr,
                         ifa->ifa_name);
 
index a9d29bca5ff588951621dae4dba93e85fc9fbcba..38c34fd61ab13c3ebd0a3ce44f4c1ee2f6e736b0 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: ifiter_ioctl.c,v 1.60.120.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: ifiter_ioctl.c,v 1.62 2009/01/18 23:48:14 tbox Exp $ */
 
 /*! \file
  * \brief
index 53bebd75a22e7b9a85b44cb80ab95405f4050826..efa67c223bef893e0f080c118f80f6f16edaaaad 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: net.h,v 1.48.84.2 2009/02/16 23:47:15 tbox Exp $ */
+/* $Id$ */
 
 #ifndef ISC_NET_H
 #define ISC_NET_H 1
index 0e484becddf6bd9724f51045b30c1f67e1dbd52a..8bf3779997cdac3f88adb82881f13567b7734b87 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: offset.h,v 1.15.332.2 2009/02/16 23:47:15 tbox Exp $ */
+/* $Id: offset.h,v 1.17 2008/12/01 23:47:45 tbox Exp $ */
 
 #ifndef ISC_OFFSET_H
 #define ISC_OFFSET_H 1
index 4cb9e81fa60cd58861fabed796333d7845772974..c4931bfe63626af0c3211999c88ccc519b04db54 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: stdtime.h,v 1.14 2007/06/19 23:47:19 tbox Exp $ */
+/* $Id$ */
 
 #ifndef ISC_STDTIME_H
 #define ISC_STDTIME_H 1
  * about its size.
  */
 typedef isc_uint32_t isc_stdtime_t;
+
+/* but this flag helps... */
+#define STDTIME_ON_32BITS      1
+
 /*
  * isc_stdtime32_t is a 32-bit version of isc_stdtime_t.  A variable of this
  * type should only be used as an opaque integer (e.g.,) to compare two
index 2953f71c6dacf53f26508b0cafbe19e5cf12df84..899043bbffdd3de8e0153d2c7a0d393397870207 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: strerror.h,v 1.8.332.2 2009/02/16 23:47:15 tbox Exp $ */
+/* $Id: strerror.h,v 1.10 2008/12/01 23:47:45 tbox Exp $ */
 
 #ifndef ISC_STRERROR_H
 #define ISC_STRERROR_H
index 45c4510e7603c5368ce523c34379d26d65be2185..dc1cef9ad3f23a2581c4d3d5e567467e937cfc37 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: time.h,v 1.38.56.2 2009/01/05 23:47:23 tbox Exp $ */
+/* $Id: time.h,v 1.40 2009/01/05 23:47:54 tbox Exp $ */
 
 #ifndef ISC_TIME_H
 #define ISC_TIME_H 1
index 4cfc82179e68d8712d95fe9b50f2f9635223a2fc..af2b06d093a6c9bcc7cac301e75a2ece23028a05 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: interfaceiter.c,v 1.44.120.2 2009/02/16 23:47:15 tbox Exp $ */
+/* $Id: interfaceiter.c,v 1.45 2008/12/01 03:51:47 marka Exp $ */
 
 /*! \file */
 
index b2fb30e4ed99620ba59664199a22b888facf70ee..ea4a504ebdec8129c32cbe2171bb061c26448e0f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: net.c,v 1.40 2008/07/04 05:52:31 each Exp $ */
+/* $Id$ */
 
 #include <config.h>
 
index 8bd8885bee8b3e4fc58290e7381011b14be8d912..29596e2aa6a131232b96671cbfcff409674cc3d4 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: resource.c,v 1.21.66.2 2009/02/13 23:47:39 tbox Exp $ */
+/* $Id: resource.c,v 1.23 2009/02/13 23:48:14 tbox Exp $ */
 
 #include <config.h>
 
index d09fe51ab57ce6ce728b11a7765fd0b710c6deaa..5fed888a11ae2752aae4052bcb5d5c23c41ba5a4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: socket.c,v 1.308.12.8 2009/04/18 01:29:26 jinmei Exp $ */
+/* $Id$ */
 
 /*! \file */
 
 #include <sys/epoll.h>
 #endif
 #ifdef ISC_PLATFORM_HAVEDEVPOLL
+#if defined(HAVE_SYS_DEVPOLL_H)
 #include <sys/devpoll.h>
+#elif defined(HAVE_DEVPOLL_H)
+#include <devpoll.h>
+#endif
 #endif
 
 #include "errno2result.h"
 
-#ifndef ISC_PLATFORM_USETHREADS
+/* See task.c about the following definition: */
+#ifdef BIND9
+#ifdef ISC_PLATFORM_USETHREADS
+#define USE_WATCHER_THREAD
+#else
+#define USE_SHARED_MANAGER
+#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* BIND9 */
+
+#ifndef USE_WATCHER_THREAD
 #include "socket_p.h"
-#endif /* ISC_PLATFORM_USETHREADS */
+#include "../task_p.h"
+#endif /* USE_WATCHER_THREAD */
 
 #if defined(SO_BSDCOMPAT) && defined(__linux__)
 #include <sys/utsname.h>
@@ -97,7 +111,7 @@ typedef struct {
 #define USE_SELECT
 #endif /* ISC_PLATFORM_HAVEKQUEUE */
 
-#ifndef ISC_PLATFORM_USETHREADS
+#ifndef USE_WATCHER_THREAD
 #if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
 struct isc_socketwait {
        int nevents;
@@ -110,7 +124,7 @@ struct isc_socketwait {
        int maxfd;
 };
 #endif /* USE_KQUEUE */
-#endif /* !ISC_PLATFORM_USETHREADS */
+#endif /* !USE_WATCHER_THREAD */
 
 /*%
  * Maximum number of allowable open sockets.  This is also the maximum
@@ -244,7 +258,7 @@ typedef enum { poll_idle, poll_active, poll_checking } pollstate_t;
 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)
+#define VALID_SOCKET(s)                ISC_MAGIC_VALID(s, SOCKET_MAGIC)
 
 /*!
  * IPv6 control information.  If the socket is an IPv6 socket we want
@@ -278,16 +292,21 @@ typedef isc_event_t intev_t;
  */
 #define NRETRIES 10
 
-struct isc_socket {
+typedef struct isc__socket isc__socket_t;
+typedef struct isc__socketmgr isc__socketmgr_t;
+
+#define NEWCONNSOCK(ev) ((isc__socket_t *)(ev)->newsocket)
+
+struct isc__socket {
        /* Not locked. */
-       unsigned int            magic;
-       isc_socketmgr_t        *manager;
+       isc_socket_t            common;
+       isc__socketmgr_t        *manager;
        isc_mutex_t             lock;
        isc_sockettype_t        type;
        const isc_statscounter_t        *statsindex;
 
        /* Locked by socket lock. */
-       ISC_LINK(isc_socket_t)  link;
+       ISC_LINK(isc__socket_t) link;
        unsigned int            references;
        int                     fd;
        int                     pf;
@@ -315,7 +334,8 @@ struct isc_socket {
                                listener : 1, /* listener socket */
                                connected : 1,
                                connecting : 1, /* connect pending */
-                               bound : 1; /* bound to local addr */
+                               bound : 1, /* bound to local addr */
+                               dupped : 1;
 
 #ifdef ISC_NET_RECVOVERFLOW
        unsigned char           overflow; /* used for MSG_TRUNC fake */
@@ -335,9 +355,9 @@ struct isc_socket {
 #define SOCKET_MANAGER_MAGIC   ISC_MAGIC('I', 'O', 'm', 'g')
 #define VALID_MANAGER(m)       ISC_MAGIC_VALID(m, SOCKET_MANAGER_MAGIC)
 
-struct isc_socketmgr {
+struct isc__socketmgr {
        /* Not locked. */
-       unsigned int            magic;
+       isc_socketmgr_t         common;
        isc_mem_t              *mctx;
        isc_mutex_t             lock;
        isc_mutex_t             *fdlock;
@@ -366,14 +386,14 @@ struct isc_socketmgr {
 #endif
 
        /* Locked by fdlock. */
-       isc_socket_t           **fds;
+       isc__socket_t          **fds;
        int                     *fdstate;
 #ifdef USE_DEVPOLL
        pollinfo_t              *fdpollinfo;
 #endif
 
        /* Locked by manager lock. */
-       ISC_LIST(isc_socket_t)  socklist;
+       ISC_LIST(isc__socket_t) socklist;
 #ifdef USE_SELECT
        fd_set                  *read_fds;
        fd_set                  *read_fds_copy;
@@ -382,17 +402,18 @@ struct isc_socketmgr {
        int                     maxfd;
 #endif /* USE_SELECT */
        int                     reserved;       /* unlocked */
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        isc_thread_t            watcher;
        isc_condition_t         shutdown_ok;
-#else /* ISC_PLATFORM_USETHREADS */
+#else /* USE_WATCHER_THREAD */
        unsigned int            refs;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
+       int                     maxudp;
 };
 
-#ifndef ISC_PLATFORM_USETHREADS
-static isc_socketmgr_t *socketmgr = NULL;
-#endif /* ISC_PLATFORM_USETHREADS */
+#ifdef USE_SHARED_MANAGER
+static isc__socketmgr_t *socketmgr = NULL;
+#endif /* USE_SHARED_MANAGER */
 
 #define CLOSED                 0       /* this one must be zero */
 #define MANAGED                        1
@@ -408,27 +429,176 @@ static isc_socketmgr_t *socketmgr = NULL;
 # define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER)
 #endif
 
-static void send_recvdone_event(isc_socket_t *, isc_socketevent_t **);
-static void send_senddone_event(isc_socket_t *, isc_socketevent_t **);
-static void free_socket(isc_socket_t **);
-static isc_result_t allocate_socket(isc_socketmgr_t *, isc_sockettype_t,
-                                   isc_socket_t **);
-static void destroy(isc_socket_t **);
+static isc_result_t socket_create(isc_socketmgr_t *manager0, int pf,
+                                 isc_sockettype_t type,
+                                 isc_socket_t **socketp,
+                                 isc_socket_t *dup_socket);
+static void send_recvdone_event(isc__socket_t *, isc_socketevent_t **);
+static void send_senddone_event(isc__socket_t *, isc_socketevent_t **);
+static void free_socket(isc__socket_t **);
+static isc_result_t allocate_socket(isc__socketmgr_t *, isc_sockettype_t,
+                                   isc__socket_t **);
+static void destroy(isc__socket_t **);
 static void internal_accept(isc_task_t *, isc_event_t *);
 static void internal_connect(isc_task_t *, isc_event_t *);
 static void internal_recv(isc_task_t *, isc_event_t *);
 static void internal_send(isc_task_t *, isc_event_t *);
 static void internal_fdwatch_write(isc_task_t *, isc_event_t *);
 static void internal_fdwatch_read(isc_task_t *, isc_event_t *);
-static void process_cmsg(isc_socket_t *, struct msghdr *, isc_socketevent_t *);
-static void build_msghdr_send(isc_socket_t *, isc_socketevent_t *,
+static void process_cmsg(isc__socket_t *, struct msghdr *, isc_socketevent_t *);
+static void build_msghdr_send(isc__socket_t *, isc_socketevent_t *,
                              struct msghdr *, struct iovec *, size_t *);
-static void build_msghdr_recv(isc_socket_t *, isc_socketevent_t *,
+static void build_msghdr_recv(isc__socket_t *, isc_socketevent_t *,
                              struct msghdr *, struct iovec *, size_t *);
-#ifdef ISC_PLATFORM_USETHREADS
-static isc_boolean_t process_ctlfd(isc_socketmgr_t *manager);
+#ifdef USE_WATCHER_THREAD
+static isc_boolean_t process_ctlfd(isc__socketmgr_t *manager);
+#endif
+
+/*%
+ * The following can be either static or public, depending on build environment.
+ */
+
+#ifdef BIND9
+#define ISC_SOCKETFUNC_SCOPE
+#else
+#define ISC_SOCKETFUNC_SCOPE static
+#endif
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+                  isc_socket_t **socketp);
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_attach(isc_socket_t *sock, isc_socket_t **socketp);
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_detach(isc_socket_t **socketp);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
+                      unsigned int maxsocks);
+ISC_SOCKETFUNC_SCOPE void
+isc__socketmgr_destroy(isc_socketmgr_t **managerp);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+                unsigned int minimum, isc_task_t *task,
+                 isc_taskaction_t action, const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recv(isc_socket_t *sock, isc_region_t *region,
+                unsigned int minimum, isc_task_t *task,
+                isc_taskaction_t action, const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recv2(isc_socket_t *sock, isc_region_t *region,
+                 unsigned int minimum, isc_task_t *task,
+                 isc_socketevent_t *event, unsigned int flags);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_send(isc_socket_t *sock, isc_region_t *region,
+                isc_task_t *task, isc_taskaction_t action, const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendto(isc_socket_t *sock, isc_region_t *region,
+                  isc_task_t *task, isc_taskaction_t action, const void *arg,
+                  isc_sockaddr_t *address, struct in6_pktinfo *pktinfo);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+                 isc_task_t *task, isc_taskaction_t action, const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
+                   isc_task_t *task, isc_taskaction_t action, const void *arg,
+                   isc_sockaddr_t *address, struct in6_pktinfo *pktinfo);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendto2(isc_socket_t *sock, isc_region_t *region,
+                   isc_task_t *task,
+                   isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+                   isc_socketevent_t *event, unsigned int flags);
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm,
+                    isc_uint32_t owner, isc_uint32_t group);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+                unsigned int options);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_filter(isc_socket_t *sock, const char *filter);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_listen(isc_socket_t *sock, unsigned int backlog);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_accept(isc_socket_t *sock,
+                  isc_task_t *task, isc_taskaction_t action, const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
+                   isc_task_t *task, isc_taskaction_t action,
+                   const void *arg);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp);
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how);
+ISC_SOCKETFUNC_SCOPE isc_sockettype_t
+isc__socket_gettype(isc_socket_t *sock);
+ISC_SOCKETFUNC_SCOPE isc_boolean_t
+isc__socket_isbound(isc_socket_t *sock);
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes);
+#if defined(HAVE_LIBXML2) && defined(BIND9)
+ISC_SOCKETFUNC_SCOPE void
+isc__socketmgr_renderxml(isc_socketmgr_t *mgr0, xmlTextWriterPtr writer);
 #endif
 
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
+                         isc_sockfdwatch_t callback, void *cbarg,
+                         isc_task_t *task, isc_socket_t **socketp);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_fdwatchpoke(isc_socket_t *sock, int flags);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_dup(isc_socket_t *sock, isc_socket_t **socketp);
+ISC_SOCKETFUNC_SCOPE int
+isc__socket_getfd(isc_socket_t *sock);
+
+static struct {
+       isc_socketmethods_t methods;
+
+       /*%
+        * The following are defined just for avoiding unused static functions.
+        */
+#ifndef BIND9
+       void *recvv, *send, *sendv, *sendto2, *cleanunix, *permunix, *filter,
+               *listen, *accept, *getpeername, *isbound;
+#endif
+} socketmethods = {
+       {
+               isc__socket_attach,
+               isc__socket_detach,
+               isc__socket_bind,
+               isc__socket_sendto,
+               isc__socket_connect,
+               isc__socket_recv,
+               isc__socket_cancel,
+               isc__socket_getsockname,
+               isc__socket_gettype,
+               isc__socket_ipv6only,
+               isc__socket_fdwatchpoke,
+               isc__socket_dup,
+               isc__socket_getfd
+       }
+#ifndef BIND9
+       ,
+       (void *)isc__socket_recvv, (void *)isc__socket_send,
+       (void *)isc__socket_sendv, (void *)isc__socket_sendto2,
+       (void *)isc__socket_cleanunix, (void *)isc__socket_permunix,
+       (void *)isc__socket_filter, (void *)isc__socket_listen,
+       (void *)isc__socket_accept, (void *)isc__socket_getpeername,
+       (void *)isc__socket_isbound
+#endif
+};
+
+static isc_socketmgrmethods_t socketmgrmethods = {
+       isc__socketmgr_destroy,
+       isc__socket_create,
+       isc__socket_fdwatchcreate
+};
+
 #define SELECT_POKE_SHUTDOWN           (-1)
 #define SELECT_POKE_NOTHING            (-2)
 #define SELECT_POKE_READ               (-3)
@@ -527,12 +697,14 @@ static const isc_statscounter_t fdwatchstatsindex[] = {
        isc_sockstatscounter_fdwatchrecvfail
 };
 
+#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) || \
+    defined(USE_WATCHER_THREAD)
 static void
-manager_log(isc_socketmgr_t *sockmgr,
+manager_log(isc__socketmgr_t *sockmgr,
            isc_logcategory_t *category, isc_logmodule_t *module, int level,
            const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);
 static void
-manager_log(isc_socketmgr_t *sockmgr,
+manager_log(isc__socketmgr_t *sockmgr,
            isc_logcategory_t *category, isc_logmodule_t *module, int level,
            const char *fmt, ...)
 {
@@ -549,14 +721,15 @@ manager_log(isc_socketmgr_t *sockmgr,
        isc_log_write(isc_lctx, category, module, level,
                      "sockmgr %p: %s", sockmgr, msgbuf);
 }
+#endif
 
 static void
-socket_log(isc_socket_t *sock, isc_sockaddr_t *address,
+socket_log(isc__socket_t *sock, isc_sockaddr_t *address,
           isc_logcategory_t *category, isc_logmodule_t *module, int level,
           isc_msgcat_t *msgcat, int msgset, int message,
           const char *fmt, ...) ISC_FORMAT_PRINTF(9, 10);
 static void
-socket_log(isc_socket_t *sock, isc_sockaddr_t *address,
+socket_log(isc__socket_t *sock, isc_sockaddr_t *address,
           isc_logcategory_t *category, isc_logmodule_t *module, int level,
           isc_msgcat_t *msgcat, int msgset, int message,
           const char *fmt, ...)
@@ -591,7 +764,7 @@ socket_log(isc_socket_t *sock, isc_sockaddr_t *address,
  * setting IPV6_V6ONLY.
  */
 static void
-FIX_IPV6_RECVPKTINFO(isc_socket_t *sock)
+FIX_IPV6_RECVPKTINFO(isc__socket_t *sock)
 {
        char strbuf[ISC_STRERRORSIZE];
        int on = 1;
@@ -602,6 +775,7 @@ FIX_IPV6_RECVPKTINFO(isc_socket_t *sock)
        if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
                       (void *)&on, sizeof(on)) < 0) {
 
+               isc__strerror(errno, strbuf, sizeof(strbuf));
                UNEXPECTED_ERROR(__FILE__, __LINE__,
                                 "setsockopt(%d, IPV6_RECVPKTINFO) "
                                 "%s: %s", sock->fd,
@@ -628,7 +802,7 @@ inc_stats(isc_stats_t *stats, isc_statscounter_t counterid) {
 }
 
 static inline isc_result_t
-watch_fd(isc_socketmgr_t *manager, int fd, int msg) {
+watch_fd(isc__socketmgr_t *manager, int fd, int msg) {
        isc_result_t result = ISC_R_SUCCESS;
 
 #ifdef USE_KQUEUE
@@ -652,6 +826,7 @@ watch_fd(isc_socketmgr_t *manager, int fd, int msg) {
                event.events = EPOLLIN;
        else
                event.events = EPOLLOUT;
+       memset(&event.data, 0, sizeof(event.data));
        event.data.fd = fd;
        if (epoll_ctl(manager->epoll_fd, EPOLL_CTL_ADD, fd, &event) == -1 &&
            errno != EEXIST) {
@@ -695,7 +870,7 @@ watch_fd(isc_socketmgr_t *manager, int fd, int msg) {
 }
 
 static inline isc_result_t
-unwatch_fd(isc_socketmgr_t *manager, int fd, int msg) {
+unwatch_fd(isc__socketmgr_t *manager, int fd, int msg) {
        isc_result_t result = ISC_R_SUCCESS;
 
 #ifdef USE_KQUEUE
@@ -719,6 +894,7 @@ unwatch_fd(isc_socketmgr_t *manager, int fd, int msg) {
                event.events = EPOLLIN;
        else
                event.events = EPOLLOUT;
+       memset(&event.data, 0, sizeof(event.data));
        event.data.fd = fd;
        if (epoll_ctl(manager->epoll_fd, EPOLL_CTL_DEL, fd, &event) == -1 &&
            errno != ENOENT) {
@@ -781,7 +957,7 @@ unwatch_fd(isc_socketmgr_t *manager, int fd, int msg) {
 }
 
 static void
-wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) {
+wakeup_socket(isc__socketmgr_t *manager, int fd, int msg) {
        isc_result_t result;
        int lockid = FDLOCK_ID(fd);
 
@@ -842,14 +1018,14 @@ wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) {
        }
 }
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
 /*
  * Poke the select loop when there is something for us to do.
  * The write is required (by POSIX) to complete.  That is, we
  * will not get partial writes.
  */
 static void
-select_poke(isc_socketmgr_t *mgr, int fd, int msg) {
+select_poke(isc__socketmgr_t *mgr, int fd, int msg) {
        int cc;
        int buf[2];
        char strbuf[ISC_STRERRORSIZE];
@@ -888,7 +1064,7 @@ select_poke(isc_socketmgr_t *mgr, int fd, int msg) {
  * Read a message on the internal fd.
  */
 static void
-select_readmsg(isc_socketmgr_t *mgr, int *fd, int *msg) {
+select_readmsg(isc__socketmgr_t *mgr, int *fd, int *msg) {
        int buf[2];
        int cc;
        char strbuf[ISC_STRERRORSIZE];
@@ -915,19 +1091,19 @@ select_readmsg(isc_socketmgr_t *mgr, int *fd, int *msg) {
        *fd = buf[0];
        *msg = buf[1];
 }
-#else /* ISC_PLATFORM_USETHREADS */
+#else /* USE_WATCHER_THREAD */
 /*
  * Update the state of the socketmgr when something changes.
  */
 static void
-select_poke(isc_socketmgr_t *manager, int fd, int msg) {
+select_poke(isc__socketmgr_t *manager, int fd, int msg) {
        if (msg == SELECT_POKE_SHUTDOWN)
                return;
        else if (fd >= 0)
                wakeup_socket(manager, fd, msg);
        return;
 }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
 
 /*
  * Make a fd non-blocking.
@@ -1020,7 +1196,7 @@ cmsg_space(ISC_SOCKADDR_LEN_T len) {
  * Process control messages received on a socket.
  */
 static void
-process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
+process_cmsg(isc__socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
 #ifdef USE_CMSG
        struct cmsghdr *cmsgp;
 #ifdef ISC_PLATFORM_HAVEIN6PKTINFO
@@ -1123,7 +1299,7 @@ process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
  * this transaction can send.
  */
 static void
-build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
+build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev,
                  struct msghdr *msg, struct iovec *iov, size_t *write_countp)
 {
        unsigned int iovcount;
@@ -1200,6 +1376,9 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
 #if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
        if ((sock->type == isc_sockettype_udp)
            && ((dev->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0)) {
+#if defined(IPV6_USE_MIN_MTU)
+               int use_min_mtu = 1;    /* -1, 0, 1 */
+#endif
                struct cmsghdr *cmsgp;
                struct in6_pktinfo *pktinfop;
 
@@ -1218,6 +1397,22 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
                cmsgp->cmsg_len = cmsg_len(sizeof(struct in6_pktinfo));
                pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
                memcpy(pktinfop, &dev->pktinfo, sizeof(struct in6_pktinfo));
+#if defined(IPV6_USE_MIN_MTU)
+               /*
+                * Set IPV6_USE_MIN_MTU as a per packet option as FreeBSD
+                * ignores setsockopt(IPV6_USE_MIN_MTU) when IPV6_PKTINFO
+                * is used.
+                */
+               cmsgp = (struct cmsghdr *)(sock->sendcmsgbuf +
+                                          msg->msg_controllen);
+               msg->msg_controllen += cmsg_space(sizeof(use_min_mtu));
+               INSIST(msg->msg_controllen <= sock->sendcmsgbuflen);
+
+               cmsgp->cmsg_level = IPPROTO_IPV6;
+               cmsgp->cmsg_type = IPV6_USE_MIN_MTU;
+               cmsgp->cmsg_len = cmsg_len(sizeof(use_min_mtu));
+               memcpy(CMSG_DATA(cmsgp), &use_min_mtu, sizeof(use_min_mtu));
+#endif
        }
 #endif /* USE_CMSG && ISC_PLATFORM_HAVEIPV6 */
 #else /* ISC_NET_BSD44MSGHDR */
@@ -1242,7 +1437,7 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
  * this transaction can receive.
  */
 static void
-build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
+build_msghdr_recv(isc__socket_t *sock, isc_socketevent_t *dev,
                  struct msghdr *msg, struct iovec *iov, size_t *read_countp)
 {
        unsigned int iovcount;
@@ -1363,7 +1558,7 @@ build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
 }
 
 static void
-set_dev_address(isc_sockaddr_t *address, isc_socket_t *sock,
+set_dev_address(isc_sockaddr_t *address, isc__socket_t *sock,
                isc_socketevent_t *dev)
 {
        if (sock->type == isc_sockettype_udp) {
@@ -1387,7 +1582,7 @@ destroy_socketevent(isc_event_t *event) {
 }
 
 static isc_socketevent_t *
-allocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype,
+allocate_socketevent(isc__socket_t *sock, isc_eventtype_t eventtype,
                     isc_taskaction_t action, const void *arg)
 {
        isc_socketevent_t *ev;
@@ -1400,7 +1595,7 @@ allocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype,
        if (ev == NULL)
                return (NULL);
 
-       ev->result = ISC_R_UNEXPECTED;
+       ev->result = ISC_R_UNSET;
        ISC_LINK_INIT(ev, ev_link);
        ISC_LIST_INIT(ev->bufferlist);
        ev->region.base = NULL;
@@ -1440,7 +1635,7 @@ dump_msg(struct msghdr *msg) {
 #define DOIO_EOF               3       /* EOF, no event sent */
 
 static int
-doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
+doio_recv(isc__socket_t *sock, isc_socketevent_t *dev) {
        int cc;
        struct iovec iov[MAXSCATTERGATHER_RECV];
        size_t read_count;
@@ -1520,12 +1715,22 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
        }
 
        /*
-        * On TCP, zero length reads indicate EOF, while on
-        * UDP, zero length reads are perfectly valid, although
-        * strange.
+        * On TCP and UNIX sockets, zero length reads indicate EOF,
+        * while on UDP sockets, zero length reads are perfectly valid,
+        * although strange.
         */
-       if ((sock->type == isc_sockettype_tcp) && (cc == 0))
-               return (DOIO_EOF);
+       switch (sock->type) {
+       case isc_sockettype_tcp:
+       case isc_sockettype_unix:
+               if (cc == 0)
+                       return (DOIO_EOF);
+               break;
+       case isc_sockettype_udp:
+               break;
+       case isc_sockettype_fdwatch:
+       default:
+               INSIST(0);
+       }
 
        if (sock->type == isc_sockettype_udp) {
                dev->address.length = msghdr.msg_namelen;
@@ -1538,6 +1743,12 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
                        }
                        return (DOIO_SOFT);
                }
+               /*
+                * Simulate a firewall blocking UDP responses bigger than
+                * 512 bytes.
+                */
+               if (sock->manager->maxudp != 0 && cc > sock->manager->maxudp)
+                       return (DOIO_SOFT);
        }
 
        socket_log(sock, &dev->address, IOEVENT,
@@ -1578,6 +1789,7 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
                } else {
                        isc_buffer_add(buffer, actual_count);
                        actual_count = 0;
+                       POST(actual_count);
                        break;
                }
                buffer = ISC_LIST_NEXT(buffer, link);
@@ -1614,7 +1826,7 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
  *     No other return values are possible.
  */
 static int
-doio_send(isc_socket_t *sock, isc_socketevent_t *dev) {
+doio_send(isc__socket_t *sock, isc_socketevent_t *dev) {
        int cc;
        struct iovec iov[MAXSCATTERGATHER_SEND];
        size_t write_count;
@@ -1725,7 +1937,7 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) {
  * references exist.
  */
 static void
-closesocket(isc_socketmgr_t *manager, isc_socket_t *sock, int fd) {
+closesocket(isc__socketmgr_t *manager, isc__socket_t *sock, int fd) {
        isc_sockettype_t type = sock->type;
        int lockid = FDLOCK_ID(fd);
 
@@ -1788,10 +2000,10 @@ closesocket(isc_socketmgr_t *manager, isc_socket_t *sock, int fd) {
 }
 
 static void
-destroy(isc_socket_t **sockp) {
+destroy(isc__socket_t **sockp) {
        int fd;
-       isc_socket_t *sock = *sockp;
-       isc_socketmgr_t *manager = sock->manager;
+       isc__socket_t *sock = *sockp;
+       isc__socketmgr_t *manager = sock->manager;
 
        socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
                   ISC_MSG_DESTROYING, "destroying");
@@ -1812,21 +2024,22 @@ destroy(isc_socket_t **sockp) {
 
        ISC_LIST_UNLINK(manager->socklist, sock, link);
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        if (ISC_LIST_EMPTY(manager->socklist))
                SIGNAL(&manager->shutdown_ok);
-#endif /* ISC_PLATFORM_USETHREADS */
-
-       UNLOCK(&manager->lock);
+#endif /* USE_WATCHER_THREAD */
 
+       /* can't unlock manager as its memory context is still used */
        free_socket(sockp);
+
+       UNLOCK(&manager->lock);
 }
 
 static isc_result_t
-allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
-               isc_socket_t **socketp)
+allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type,
+               isc__socket_t **socketp)
 {
-       isc_socket_t *sock;
+       isc__socket_t *sock;
        isc_result_t result;
        ISC_SOCKADDR_LEN_T cmsgbuflen;
 
@@ -1835,14 +2048,14 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
        if (sock == NULL)
                return (ISC_R_NOMEMORY);
 
-       result = ISC_R_UNEXPECTED;
-
-       sock->magic = 0;
+       sock->common.magic = 0;
+       sock->common.impmagic = 0;
        sock->references = 0;
 
        sock->manager = manager;
        sock->type = type;
        sock->fd = -1;
+       sock->dupped = 0;
        sock->statsindex = NULL;
 
        ISC_LINK_INIT(sock, link);
@@ -1855,7 +2068,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
         */
        cmsgbuflen = 0;
 #if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
-       cmsgbuflen = cmsg_space(sizeof(struct in6_pktinfo));
+       cmsgbuflen += cmsg_space(sizeof(struct in6_pktinfo));
 #endif
 #if defined(USE_CMSG) && defined(SO_TIMESTAMP)
        cmsgbuflen += cmsg_space(sizeof(struct timeval));
@@ -1863,19 +2076,30 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
        sock->recvcmsgbuflen = cmsgbuflen;
        if (sock->recvcmsgbuflen != 0U) {
                sock->recvcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen);
-               if (sock->recvcmsgbuf == NULL)
+               if (sock->recvcmsgbuf == NULL) {
+                       result = ISC_R_NOMEMORY;
                        goto error;
+               }
        }
 
        cmsgbuflen = 0;
 #if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
-       cmsgbuflen = cmsg_space(sizeof(struct in6_pktinfo));
+       cmsgbuflen += cmsg_space(sizeof(struct in6_pktinfo));
+#if defined(IPV6_USE_MIN_MTU)
+       /*
+        * Provide space for working around FreeBSD's broken IPV6_USE_MIN_MTU
+        * support.
+        */
+       cmsgbuflen += cmsg_space(sizeof(int));
+#endif
 #endif
        sock->sendcmsgbuflen = cmsgbuflen;
        if (sock->sendcmsgbuflen != 0U) {
                sock->sendcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen);
-               if (sock->sendcmsgbuf == NULL)
+               if (sock->sendcmsgbuf == NULL) {
+                       result = ISC_R_NOMEMORY;
                        goto error;
+               }
        }
 
        memset(sock->name, 0, sizeof(sock->name));
@@ -1901,7 +2125,8 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
         */
        result = isc_mutex_init(&sock->lock);
        if (result != ISC_R_SUCCESS) {
-               sock->magic = 0;
+               sock->common.magic = 0;
+               sock->common.impmagic = 0;
                goto error;
        }
 
@@ -1915,7 +2140,8 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
                       ISC_EVENTATTR_NOPURGE, NULL, ISC_SOCKEVENT_INTW,
                       NULL, sock, sock, NULL, NULL);
 
-       sock->magic = SOCKET_MAGIC;
+       sock->common.magic = ISCAPI_SOCKET_MAGIC;
+       sock->common.impmagic = SOCKET_MAGIC;
        *socketp = sock;
 
        return (ISC_R_SUCCESS);
@@ -1940,8 +2166,8 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
  * also close the socket.
  */
 static void
-free_socket(isc_socket_t **socketp) {
-       isc_socket_t *sock = *socketp;
+free_socket(isc__socket_t **socketp) {
+       isc__socket_t *sock = *socketp;
 
        INSIST(sock->references == 0);
        INSIST(VALID_SOCKET(sock));
@@ -1961,7 +2187,8 @@ free_socket(isc_socket_t **socketp) {
                isc_mem_put(sock->manager->mctx, sock->sendcmsgbuf,
                            sock->sendcmsgbuflen);
 
-       sock->magic = 0;
+       sock->common.magic = 0;
+       sock->common.impmagic = 0;
 
        DESTROYLOCK(&sock->lock);
 
@@ -2009,7 +2236,10 @@ clear_bsdcompat(void) {
 #endif
 
 static isc_result_t
-opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) {
+opensocket(isc__socketmgr_t *manager, isc__socket_t *sock,
+          isc__socket_t *dup_socket)
+{
+       isc_result_t result;
        char strbuf[ISC_STRERRORSIZE];
        const char *err = "socket";
        int tries = 0;
@@ -2022,22 +2252,29 @@ opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) {
 #endif
 
  again:
-       switch (sock->type) {
-       case isc_sockettype_udp:
-               sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP);
-               break;
-       case isc_sockettype_tcp:
-               sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
-               break;
-       case isc_sockettype_unix:
-               sock->fd = socket(sock->pf, SOCK_STREAM, 0);
-               break;
-       case isc_sockettype_fdwatch:
-               /*
-                * We should not be called for isc_sockettype_fdwatch sockets.
-                */
-               INSIST(0);
-               break;
+       if (dup_socket == NULL) {
+               switch (sock->type) {
+               case isc_sockettype_udp:
+                       sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP);
+                       break;
+               case isc_sockettype_tcp:
+                       sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
+                       break;
+               case isc_sockettype_unix:
+                       sock->fd = socket(sock->pf, SOCK_STREAM, 0);
+                       break;
+               case isc_sockettype_fdwatch:
+                       /*
+                        * We should not be called for isc_sockettype_fdwatch
+                        * sockets.
+                        */
+                       INSIST(0);
+                       break;
+               }
+       } else {
+               sock->fd = dup(dup_socket->fd);
+               sock->dupped = 1;
+               sock->bound = dup_socket->bound;
        }
        if (sock->fd == -1 && errno == EINTR && tries++ < 42)
                goto again;
@@ -2114,9 +2351,13 @@ opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) {
                }
        }
 
-       if (make_nonblock(sock->fd) != ISC_R_SUCCESS) {
+       if (dup_socket != NULL)
+               goto setup_done;
+
+       result = make_nonblock(sock->fd);
+       if (result != ISC_R_SUCCESS) {
                (void)close(sock->fd);
-               return (ISC_R_UNEXPECTED);
+               return (result);
        }
 
 #ifdef SO_BSDCOMPAT
@@ -2216,10 +2457,39 @@ opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) {
 #endif /* ISC_PLATFORM_HAVEIN6PKTINFO */
 #ifdef IPV6_USE_MIN_MTU        /* RFC 3542, not too common yet*/
                /* use minimum MTU */
+               if (sock->pf == AF_INET6 &&
+                   setsockopt(sock->fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
+                              (void *)&on, sizeof(on)) < 0) {
+                       isc__strerror(errno, strbuf, sizeof(strbuf));
+                       UNEXPECTED_ERROR(__FILE__, __LINE__,
+                                        "setsockopt(%d, IPV6_USE_MIN_MTU) "
+                                        "%s: %s", sock->fd,
+                                        isc_msgcat_get(isc_msgcat,
+                                                       ISC_MSGSET_GENERAL,
+                                                       ISC_MSG_FAILED,
+                                                       "failed"),
+                                        strbuf);
+               }
+#endif
+#if defined(IPV6_MTU)
+               /*
+                * Use minimum MTU on IPv6 sockets.
+                */
+               if (sock->pf == AF_INET6) {
+                       int mtu = 1280;
+                       (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MTU,
+                                        &mtu, sizeof(mtu));
+               }
+#endif
+#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
+               /*
+                * Turn off Path MTU discovery on IPv6/UDP sockets.
+                */
                if (sock->pf == AF_INET6) {
+                       int action = IPV6_PMTUDISC_DONT;
                        (void)setsockopt(sock->fd, IPPROTO_IPV6,
-                                        IPV6_USE_MIN_MTU,
-                                        (void *)&on, sizeof(on));
+                                        IPV6_MTU_DISCOVER, &action,
+                                        sizeof(action));
                }
 #endif
 #endif /* ISC_PLATFORM_HAVEIPV6 */
@@ -2269,22 +2539,24 @@ opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) {
        }
 #endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */
 
+setup_done:
        inc_stats(manager->stats, sock->statsindex[STATID_OPEN]);
 
        return (ISC_R_SUCCESS);
 }
 
-/*%
- * 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
- * in 'socketp'.
+/*
+ * Create a 'type' socket or duplicate an existing 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 in 'socketp'.
  */
-isc_result_t
-isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
-                 isc_socket_t **socketp)
+static isc_result_t
+socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
+             isc_socket_t **socketp, isc_socket_t *dup_socket)
 {
-       isc_socket_t *sock = NULL;
+       isc__socket_t *sock = NULL;
+       isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
        isc_result_t result;
        int lockid;
 
@@ -2313,15 +2585,17 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
        }
 
        sock->pf = pf;
-       result = opensocket(manager, sock);
+
+       result = opensocket(manager, sock, (isc__socket_t *)dup_socket);
        if (result != ISC_R_SUCCESS) {
                inc_stats(manager->stats, sock->statsindex[STATID_OPENFAIL]);
                free_socket(&sock);
                return (result);
        }
 
+       sock->common.methods = (isc_socketmethods_t *)&socketmethods;
        sock->references = 1;
-       *socketp = sock;
+       *socketp = (isc_socket_t *)sock;
 
        /*
         * Note we don't have to lock the socket like we normally would because
@@ -2347,14 +2621,45 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
        UNLOCK(&manager->lock);
 
        socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
-                  ISC_MSG_CREATED, "created");
+                  ISC_MSG_CREATED, dup_socket == NULL ? "dupped" : "created");
 
        return (ISC_R_SUCCESS);
 }
 
-isc_result_t
-isc_socket_open(isc_socket_t *sock) {
+/*%
+ * 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
+ * in 'socketp'.
+ */
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
+                  isc_socket_t **socketp)
+{
+       return (socket_create(manager0, pf, type, socketp, NULL));
+}
+
+/*%
+ * Duplicate an existing socket.  The new socket is returned
+ * in 'socketp'.
+ */
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_dup(isc_socket_t *sock0, isc_socket_t **socketp) {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
+
+       REQUIRE(VALID_SOCKET(sock));
+       REQUIRE(socketp != NULL && *socketp == NULL);
+
+       return (socket_create((isc_socketmgr_t *) sock->manager,
+                             sock->pf, sock->type, socketp,
+                             sock0));
+}
+
+#ifdef BIND9
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_open(isc_socket_t *sock0) {
        isc_result_t result;
+       isc__socket_t *sock = (isc__socket_t *)sock0;
 
        REQUIRE(VALID_SOCKET(sock));
 
@@ -2368,7 +2673,7 @@ isc_socket_open(isc_socket_t *sock) {
         */
        REQUIRE(sock->fd == -1);
 
-       result = opensocket(sock->manager, sock);
+       result = opensocket(sock->manager, sock, NULL);
        if (result != ISC_R_SUCCESS)
                sock->fd = -1;
 
@@ -2394,6 +2699,7 @@ isc_socket_open(isc_socket_t *sock) {
 
        return (result);
 }
+#endif /* BIND9 */
 
 /*
  * Create a new 'type' socket managed by 'manager'.  Events
@@ -2401,12 +2707,13 @@ isc_socket_open(isc_socket_t *sock) {
  * called with 'arg' as the arg value.  The new socket is returned
  * in 'socketp'.
  */
-isc_result_t
-isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
-                        isc_sockfdwatch_t callback, void *cbarg,
-                        isc_task_t *task, isc_socket_t **socketp)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_fdwatchcreate(isc_socketmgr_t *manager0, int fd, int flags,
+                         isc_sockfdwatch_t callback, void *cbarg,
+                         isc_task_t *task, isc_socket_t **socketp)
 {
-       isc_socket_t *sock = NULL;
+       isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+       isc__socket_t *sock = NULL;
        isc_result_t result;
        int lockid;
 
@@ -2424,8 +2731,9 @@ isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
        sock->fdwatchtask = task;
        sock->statsindex = fdwatchstatsindex;
 
+       sock->common.methods = (isc_socketmethods_t *)&socketmethods;
        sock->references = 1;
-       *socketp = sock;
+       *socketp = (isc_socket_t *)sock;
 
        /*
         * Note we don't have to lock the socket like we normally would because
@@ -2457,11 +2765,51 @@ isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
        return (ISC_R_SUCCESS);
 }
 
+/*
+ * Indicate to the manager that it should watch the socket again.
+ * This can be used to restart watching if the previous event handler
+ * didn't indicate there was more data to be processed.  Primarily
+ * it is for writing but could be used for reading if desired
+ */
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_fdwatchpoke(isc_socket_t *sock0, int flags)
+{
+       isc__socket_t *sock = (isc__socket_t *)sock0;
+
+       REQUIRE(VALID_SOCKET(sock));
+
+       /*
+        * We check both flags first to allow us to get the lock
+        * once but only if we need it.
+        */
+
+       if ((flags & (ISC_SOCKFDWATCH_READ | ISC_SOCKFDWATCH_WRITE)) != 0) {
+               LOCK(&sock->lock);
+               if (((flags & ISC_SOCKFDWATCH_READ) != 0) &&
+                   !sock->pending_recv)
+                       select_poke(sock->manager, sock->fd,
+                                   SELECT_POKE_READ);
+               if (((flags & ISC_SOCKFDWATCH_WRITE) != 0) &&
+                   !sock->pending_send)
+                       select_poke(sock->manager, sock->fd,
+                                   SELECT_POKE_WRITE);
+               UNLOCK(&sock->lock);
+       }
+
+       socket_log(sock, NULL, TRACE, isc_msgcat, ISC_MSGSET_SOCKET,
+                  ISC_MSG_POKED, "fdwatch-poked flags: %d", flags);
+
+       return (ISC_R_SUCCESS);
+}
+
 /*
  * Attach to a socket.  Caller must explicitly detach when it is done.
  */
-void
-isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_attach(isc_socket_t *sock0, isc_socket_t **socketp) {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
+
        REQUIRE(VALID_SOCKET(sock));
        REQUIRE(socketp != NULL && *socketp == NULL);
 
@@ -2469,20 +2817,20 @@ isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
        sock->references++;
        UNLOCK(&sock->lock);
 
-       *socketp = sock;
+       *socketp = (isc_socket_t *)sock;
 }
 
 /*
  * Dereference a socket.  If this is the last reference to it, clean things
  * up by destroying the socket.
  */
-void
-isc_socket_detach(isc_socket_t **socketp) {
-       isc_socket_t *sock;
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_detach(isc_socket_t **socketp) {
+       isc__socket_t *sock;
        isc_boolean_t kill_socket = ISC_FALSE;
 
        REQUIRE(socketp != NULL);
-       sock = *socketp;
+       sock = (isc__socket_t *)*socketp;
        REQUIRE(VALID_SOCKET(sock));
 
        LOCK(&sock->lock);
@@ -2498,12 +2846,14 @@ isc_socket_detach(isc_socket_t **socketp) {
        *socketp = NULL;
 }
 
-isc_result_t
-isc_socket_close(isc_socket_t *sock) {
+#ifdef BIND9
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_close(isc_socket_t *sock0) {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
        int fd;
-       isc_socketmgr_t *manager;
-       isc_sockettype_t type;
+       isc__socketmgr_t *manager;
 
+       fflush(stdout);
        REQUIRE(VALID_SOCKET(sock));
 
        LOCK(&sock->lock);
@@ -2522,9 +2872,9 @@ isc_socket_close(isc_socket_t *sock) {
        INSIST(sock->connect_ev == NULL);
 
        manager = sock->manager;
-       type = sock->type;
        fd = sock->fd;
        sock->fd = -1;
+       sock->dupped = 0;
        memset(sock->name, 0, sizeof(sock->name));
        sock->tag = NULL;
        sock->listener = 0;
@@ -2539,6 +2889,7 @@ isc_socket_close(isc_socket_t *sock) {
 
        return (ISC_R_SUCCESS);
 }
+#endif /* BIND9 */
 
 /*
  * I/O is possible on a given socket.  Schedule an event to this task that
@@ -2549,7 +2900,7 @@ isc_socket_close(isc_socket_t *sock) {
  * The socket and manager must be locked before calling this function.
  */
 static void
-dispatch_recv(isc_socket_t *sock) {
+dispatch_recv(isc__socket_t *sock) {
        intev_t *iev;
        isc_socketevent_t *ev;
        isc_task_t *sender;
@@ -2583,7 +2934,7 @@ dispatch_recv(isc_socket_t *sock) {
 }
 
 static void
-dispatch_send(isc_socket_t *sock) {
+dispatch_send(isc__socket_t *sock) {
        intev_t *iev;
        isc_socketevent_t *ev;
        isc_task_t *sender;
@@ -2620,7 +2971,7 @@ dispatch_send(isc_socket_t *sock) {
  * Dispatch an internal accept event.
  */
 static void
-dispatch_accept(isc_socket_t *sock) {
+dispatch_accept(isc__socket_t *sock) {
        intev_t *iev;
        isc_socket_newconnev_t *ev;
 
@@ -2646,7 +2997,7 @@ dispatch_accept(isc_socket_t *sock) {
 }
 
 static void
-dispatch_connect(isc_socket_t *sock) {
+dispatch_connect(isc__socket_t *sock) {
        intev_t *iev;
        isc_socket_connev_t *ev;
 
@@ -2676,7 +3027,7 @@ dispatch_connect(isc_socket_t *sock) {
  * Caller must have the socket locked if the event is attached to the socket.
  */
 static void
-send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
+send_recvdone_event(isc__socket_t *sock, isc_socketevent_t **dev) {
        isc_task_t *task;
 
        task = (*dev)->ev_sender;
@@ -2699,7 +3050,7 @@ send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
  * Caller must have the socket locked if the event is attached to the socket.
  */
 static void
-send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
+send_senddone_event(isc__socket_t *sock, isc_socketevent_t **dev) {
        isc_task_t *task;
 
        INSIST(dev != NULL && *dev != NULL);
@@ -2730,8 +3081,8 @@ send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
  */
 static void
 internal_accept(isc_task_t *me, isc_event_t *ev) {
-       isc_socket_t *sock;
-       isc_socketmgr_t *manager;
+       isc__socket_t *sock;
+       isc__socketmgr_t *manager;
        isc_socket_newconnev_t *dev;
        isc_task_t *task;
        ISC_SOCKADDR_LEN_T addrlen;
@@ -2786,9 +3137,9 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
         * daemons such as BIND 8 and Apache.
         */
 
-       addrlen = sizeof(dev->newsocket->peer_address.type);
-       memset(&dev->newsocket->peer_address.type, 0, addrlen);
-       fd = accept(sock->fd, &dev->newsocket->peer_address.type.sa,
+       addrlen = sizeof(NEWCONNSOCK(dev)->peer_address.type);
+       memset(&NEWCONNSOCK(dev)->peer_address.type, 0, addrlen);
+       fd = accept(sock->fd, &NEWCONNSOCK(dev)->peer_address.type.sa,
                    (void *)&addrlen);
 
 #ifdef F_DUPFD
@@ -2858,14 +3209,14 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
 
                        (void)close(fd);
                        goto soft_error;
-               } else if (dev->newsocket->peer_address.type.sa.sa_family !=
+               } else if (NEWCONNSOCK(dev)->peer_address.type.sa.sa_family !=
                           sock->pf)
                {
                        UNEXPECTED_ERROR(__FILE__, __LINE__,
                                         "internal_accept(): "
                                         "accept() returned peer address "
                                         "family %u (expected %u)",
-                                        dev->newsocket->peer_address.
+                                        NEWCONNSOCK(dev)->peer_address.
                                         type.sa.sa_family,
                                         sock->pf);
                        (void)close(fd);
@@ -2884,8 +3235,8 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
        }
 
        if (fd != -1) {
-               dev->newsocket->peer_address.length = addrlen;
-               dev->newsocket->pf = sock->pf;
+               NEWCONNSOCK(dev)->peer_address.length = addrlen;
+               NEWCONNSOCK(dev)->pf = sock->pf;
        }
 
        /*
@@ -2901,10 +3252,12 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
 
        UNLOCK(&sock->lock);
 
-       if (fd != -1 && (make_nonblock(fd) != ISC_R_SUCCESS)) {
-               (void)close(fd);
-               fd = -1;
-               result = ISC_R_UNEXPECTED;
+       if (fd != -1) {
+               result = make_nonblock(fd);
+               if (result != ISC_R_SUCCESS) {
+                       (void)close(fd);
+                       fd = -1;
+               }
        }
 
        /*
@@ -2914,28 +3267,28 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
                int lockid = FDLOCK_ID(fd);
 
                LOCK(&manager->fdlock[lockid]);
-               manager->fds[fd] = dev->newsocket;
+               manager->fds[fd] = NEWCONNSOCK(dev);
                manager->fdstate[fd] = MANAGED;
                UNLOCK(&manager->fdlock[lockid]);
 
                LOCK(&manager->lock);
-               ISC_LIST_APPEND(manager->socklist, dev->newsocket, link);
+               ISC_LIST_APPEND(manager->socklist, NEWCONNSOCK(dev), link);
 
-               dev->newsocket->fd = fd;
-               dev->newsocket->bound = 1;
-               dev->newsocket->connected = 1;
+               NEWCONNSOCK(dev)->fd = fd;
+               NEWCONNSOCK(dev)->bound = 1;
+               NEWCONNSOCK(dev)->connected = 1;
 
                /*
                 * Save away the remote address
                 */
-               dev->address = dev->newsocket->peer_address;
+               dev->address = NEWCONNSOCK(dev)->peer_address;
 
 #ifdef USE_SELECT
                if (manager->maxfd < fd)
                        manager->maxfd = fd;
 #endif
 
-               socket_log(sock, &dev->newsocket->peer_address, CREATION,
+               socket_log(sock, &NEWCONNSOCK(dev)->peer_address, CREATION,
                           isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
                           "accepted connection, new socket %p",
                           dev->newsocket);
@@ -2945,8 +3298,8 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
                inc_stats(manager->stats, sock->statsindex[STATID_ACCEPT]);
        } else {
                inc_stats(manager->stats, sock->statsindex[STATID_ACCEPTFAIL]);
-               dev->newsocket->references--;
-               free_socket(&dev->newsocket);
+               NEWCONNSOCK(dev)->references--;
+               free_socket((isc__socket_t **)&dev->newsocket);
        }
 
        /*
@@ -2970,7 +3323,7 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
 static void
 internal_recv(isc_task_t *me, isc_event_t *ev) {
        isc_socketevent_t *dev;
-       isc_socket_t *sock;
+       isc__socket_t *sock;
 
        INSIST(ev->ev_type == ISC_SOCKEVENT_INTR);
 
@@ -3035,14 +3388,14 @@ internal_recv(isc_task_t *me, isc_event_t *ev) {
 static void
 internal_send(isc_task_t *me, isc_event_t *ev) {
        isc_socketevent_t *dev;
-       isc_socket_t *sock;
+       isc__socket_t *sock;
 
        INSIST(ev->ev_type == ISC_SOCKEVENT_INTW);
 
        /*
         * Find out what socket this is and lock it.
         */
-       sock = (isc_socket_t *)ev->ev_sender;
+       sock = (isc__socket_t *)ev->ev_sender;
        INSIST(VALID_SOCKET(sock));
 
        LOCK(&sock->lock);
@@ -3089,7 +3442,7 @@ internal_send(isc_task_t *me, isc_event_t *ev) {
 
 static void
 internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) {
-       isc_socket_t *sock;
+       isc__socket_t *sock;
        int more_data;
 
        INSIST(ev->ev_type == ISC_SOCKEVENT_INTW);
@@ -3097,7 +3450,7 @@ internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) {
        /*
         * Find out what socket this is and lock it.
         */
-       sock = (isc_socket_t *)ev->ev_sender;
+       sock = (isc__socket_t *)ev->ev_sender;
        INSIST(VALID_SOCKET(sock));
 
        LOCK(&sock->lock);
@@ -3108,7 +3461,8 @@ internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) {
        INSIST(sock->pending_send == 1);
 
        UNLOCK(&sock->lock);
-       more_data = (sock->fdwatchcb)(me, sock, sock->fdwatcharg);
+       more_data = (sock->fdwatchcb)(me, (isc_socket_t *)sock,
+                                     sock->fdwatcharg, ISC_SOCKFDWATCH_WRITE);
        LOCK(&sock->lock);
 
        sock->pending_send = 0;
@@ -3129,7 +3483,7 @@ internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) {
 
 static void
 internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) {
-       isc_socket_t *sock;
+       isc__socket_t *sock;
        int more_data;
 
        INSIST(ev->ev_type == ISC_SOCKEVENT_INTR);
@@ -3137,7 +3491,7 @@ internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) {
        /*
         * Find out what socket this is and lock it.
         */
-       sock = (isc_socket_t *)ev->ev_sender;
+       sock = (isc__socket_t *)ev->ev_sender;
        INSIST(VALID_SOCKET(sock));
 
        LOCK(&sock->lock);
@@ -3148,7 +3502,8 @@ internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) {
        INSIST(sock->pending_recv == 1);
 
        UNLOCK(&sock->lock);
-       more_data = (sock->fdwatchcb)(me, sock, sock->fdwatcharg);
+       more_data = (sock->fdwatchcb)(me, (isc_socket_t *)sock,
+                                     sock->fdwatcharg, ISC_SOCKFDWATCH_READ);
        LOCK(&sock->lock);
 
        sock->pending_recv = 0;
@@ -3172,10 +3527,10 @@ internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) {
  * and unlocking twice if both reads and writes are possible.
  */
 static void
-process_fd(isc_socketmgr_t *manager, int fd, isc_boolean_t readable,
+process_fd(isc__socketmgr_t *manager, int fd, isc_boolean_t readable,
           isc_boolean_t writeable)
 {
-       isc_socket_t *sock;
+       isc__socket_t *sock;
        isc_boolean_t unlock_sock;
        isc_boolean_t unwatch_read = ISC_FALSE, unwatch_write = ISC_FALSE;
        int lockid = FDLOCK_ID(fd);
@@ -3241,11 +3596,11 @@ check_write:
 
 #ifdef USE_KQUEUE
 static isc_boolean_t
-process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) {
+process_fds(isc__socketmgr_t *manager, struct kevent *events, int nevents) {
        int i;
        isc_boolean_t readable, writable;
        isc_boolean_t done = ISC_FALSE;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        isc_boolean_t have_ctlevent = ISC_FALSE;
 #endif
 
@@ -3263,7 +3618,7 @@ process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) {
 
        for (i = 0; i < nevents; i++) {
                REQUIRE(events[i].ident < manager->maxsocks);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
                if (events[i].ident == (uintptr_t)manager->pipe_fds[0]) {
                        have_ctlevent = ISC_TRUE;
                        continue;
@@ -3274,7 +3629,7 @@ process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) {
                process_fd(manager, events[i].ident, readable, writable);
        }
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        if (have_ctlevent)
                done = process_ctlfd(manager);
 #endif
@@ -3283,10 +3638,11 @@ process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) {
 }
 #elif defined(USE_EPOLL)
 static isc_boolean_t
-process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) {
+process_fds(isc__socketmgr_t *manager, struct epoll_event *events, int nevents)
+{
        int i;
        isc_boolean_t done = ISC_FALSE;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        isc_boolean_t have_ctlevent = ISC_FALSE;
 #endif
 
@@ -3299,7 +3655,7 @@ process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) {
 
        for (i = 0; i < nevents; i++) {
                REQUIRE(events[i].data.fd < (int)manager->maxsocks);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
                if (events[i].data.fd == manager->pipe_fds[0]) {
                        have_ctlevent = ISC_TRUE;
                        continue;
@@ -3321,7 +3677,7 @@ process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) {
                           (events[i].events & EPOLLOUT) != 0);
        }
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        if (have_ctlevent)
                done = process_ctlfd(manager);
 #endif
@@ -3330,10 +3686,10 @@ process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) {
 }
 #elif defined(USE_DEVPOLL)
 static isc_boolean_t
-process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) {
+process_fds(isc__socketmgr_t *manager, struct pollfd *events, int nevents) {
        int i;
        isc_boolean_t done = ISC_FALSE;
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        isc_boolean_t have_ctlevent = ISC_FALSE;
 #endif
 
@@ -3346,7 +3702,7 @@ process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) {
 
        for (i = 0; i < nevents; i++) {
                REQUIRE(events[i].fd < (int)manager->maxsocks);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
                if (events[i].fd == manager->pipe_fds[0]) {
                        have_ctlevent = ISC_TRUE;
                        continue;
@@ -3357,7 +3713,7 @@ process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) {
                           (events[i].events & POLLOUT) != 0);
        }
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        if (have_ctlevent)
                done = process_ctlfd(manager);
 #endif
@@ -3366,27 +3722,27 @@ process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) {
 }
 #elif defined(USE_SELECT)
 static void
-process_fds(isc_socketmgr_t *manager, int maxfd,
-           fd_set *readfds, fd_set *writefds)
+process_fds(isc__socketmgr_t *manager, int maxfd, fd_set *readfds,
+           fd_set *writefds)
 {
        int i;
 
        REQUIRE(maxfd <= (int)manager->maxsocks);
 
        for (i = 0; i < maxfd; i++) {
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
                if (i == manager->pipe_fds[0] || i == manager->pipe_fds[1])
                        continue;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
                process_fd(manager, i, FD_ISSET(i, readfds),
                           FD_ISSET(i, writefds));
        }
 }
 #endif
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
 static isc_boolean_t
-process_ctlfd(isc_socketmgr_t *manager) {
+process_ctlfd(isc__socketmgr_t *manager) {
        int msg, fd;
 
        for (;;) {
@@ -3434,9 +3790,8 @@ process_ctlfd(isc_socketmgr_t *manager) {
  */
 static isc_threadresult_t
 watcher(void *uap) {
-       isc_socketmgr_t *manager = uap;
+       isc__socketmgr_t *manager = uap;
        isc_boolean_t done;
-       int ctlfd;
        int cc;
 #ifdef USE_KQUEUE
        const char *fnname = "kevent()";
@@ -3448,16 +3803,19 @@ watcher(void *uap) {
 #elif defined (USE_SELECT)
        const char *fnname = "select()";
        int maxfd;
+       int ctlfd;
 #endif
        char strbuf[ISC_STRERRORSIZE];
 #ifdef ISC_SOCKET_USE_POLLWATCH
        pollstate_t pollstate = poll_idle;
 #endif
 
+#if defined (USE_SELECT)
        /*
         * Get the control fd here.  This will never change.
         */
        ctlfd = manager->pipe_fds[0];
+#endif
        done = ISC_FALSE;
        while (!done) {
                do {
@@ -3549,22 +3907,34 @@ watcher(void *uap) {
 
        return ((isc_threadresult_t)0);
 }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
 
-void
-isc__socketmgr_setreserved(isc_socketmgr_t *manager, isc_uint32_t reserved) {
+#ifdef BIND9
+ISC_SOCKETFUNC_SCOPE void
+isc__socketmgr_setreserved(isc_socketmgr_t *manager0, isc_uint32_t reserved) {
+       isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
 
        REQUIRE(VALID_MANAGER(manager));
 
        manager->reserved = reserved;
 }
 
+ISC_SOCKETFUNC_SCOPE void
+isc___socketmgr_maxudp(isc_socketmgr_t *manager0, int maxudp) {
+       isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+
+       REQUIRE(VALID_MANAGER(manager));
+
+       manager->maxudp = maxudp;
+}
+#endif /* BIND9 */
+
 /*
  * Create a new socket manager.
  */
 
 static isc_result_t
-setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
+setup_watcher(isc_mem_t *mctx, isc__socketmgr_t *manager) {
        isc_result_t result;
 #if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
        char strbuf[ISC_STRERRORSIZE];
@@ -3590,7 +3960,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
                return (result);
        }
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
        if (result != ISC_R_SUCCESS) {
                close(manager->kqueue_fd);
@@ -3598,7 +3968,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
                            sizeof(struct kevent) * manager->nevents);
                return (result);
        }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
 #elif defined(USE_EPOLL)
        manager->nevents = ISC_SOCKET_MAXEVENTS;
        manager->events = isc_mem_get(mctx, sizeof(struct epoll_event) *
@@ -3618,7 +3988,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
                            sizeof(struct epoll_event) * manager->nevents);
                return (result);
        }
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
        if (result != ISC_R_SUCCESS) {
                close(manager->epoll_fd);
@@ -3626,7 +3996,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
                            sizeof(struct epoll_event) * manager->nevents);
                return (result);
        }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
 #elif defined(USE_DEVPOLL)
        /*
         * XXXJT: /dev/poll seems to reject large numbers of events,
@@ -3645,7 +4015,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
                                          manager->maxsocks);
        if (manager->fdpollinfo == NULL) {
                isc_mem_put(mctx, manager->events,
-                           sizeof(pollinfo_t) * manager->maxsocks);
+                           sizeof(struct pollfd) * manager->nevents);
                return (ISC_R_NOMEMORY);
        }
        memset(manager->fdpollinfo, 0, sizeof(pollinfo_t) * manager->maxsocks);
@@ -3664,7 +4034,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
                            sizeof(pollinfo_t) * manager->maxsocks);
                return (result);
        }
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
        if (result != ISC_R_SUCCESS) {
                close(manager->devpoll_fd);
@@ -3674,7 +4044,7 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
                            sizeof(pollinfo_t) * manager->maxsocks);
                return (result);
        }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
 #elif defined(USE_SELECT)
        UNUSED(result);
 
@@ -3722,20 +4092,20 @@ setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
        memset(manager->read_fds, 0, manager->fd_bufsize);
        memset(manager->write_fds, 0, manager->fd_bufsize);
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        (void)watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
        manager->maxfd = manager->pipe_fds[0];
-#else /* ISC_PLATFORM_USETHREADS */
+#else /* USE_WATCHER_THREAD */
        manager->maxfd = 0;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
 #endif /* USE_KQUEUE */
 
        return (ISC_R_SUCCESS);
 }
 
 static void
-cleanup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
-#ifdef ISC_PLATFORM_USETHREADS
+cleanup_watcher(isc_mem_t *mctx, isc__socketmgr_t *manager) {
+#ifdef USE_WATCHER_THREAD
        isc_result_t result;
 
        result = unwatch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
@@ -3745,7 +4115,7 @@ cleanup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
                                 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
                                                ISC_MSG_FAILED, "failed"));
        }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
 
 #ifdef USE_KQUEUE
        close(manager->kqueue_fd);
@@ -3773,35 +4143,35 @@ cleanup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
 #endif /* USE_KQUEUE */
 }
 
-isc_result_t
-isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
-       return (isc_socketmgr_create2(mctx, managerp, 0));
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
+       return (isc__socketmgr_create2(mctx, managerp, 0));
 }
 
-isc_result_t
-isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
-                     unsigned int maxsocks)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
+                      unsigned int maxsocks)
 {
        int i;
-       isc_socketmgr_t *manager;
-#ifdef ISC_PLATFORM_USETHREADS
+       isc__socketmgr_t *manager;
+#ifdef USE_WATCHER_THREAD
        char strbuf[ISC_STRERRORSIZE];
 #endif
        isc_result_t result;
 
        REQUIRE(managerp != NULL && *managerp == NULL);
 
-#ifndef ISC_PLATFORM_USETHREADS
+#ifdef USE_SHARED_MANAGER
        if (socketmgr != NULL) {
                /* Don't allow maxsocks to be updated */
                if (maxsocks > 0 && socketmgr->maxsocks != maxsocks)
                        return (ISC_R_EXISTS);
 
                socketmgr->refs++;
-               *managerp = socketmgr;
+               *managerp = (isc_socketmgr_t *)socketmgr;
                return (ISC_R_SUCCESS);
        }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_SHARED_MANAGER */
 
        if (maxsocks == 0)
                maxsocks = ISC_SOCKET_MAXSOCKETS;
@@ -3814,8 +4184,9 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
        memset(manager, 0, sizeof(*manager));
        manager->maxsocks = maxsocks;
        manager->reserved = 0;
+       manager->maxudp = 0;
        manager->fds = isc_mem_get(mctx,
-                                  manager->maxsocks * sizeof(isc_socket_t *));
+                                  manager->maxsocks * sizeof(isc__socket_t *));
        if (manager->fds == NULL) {
                result = ISC_R_NOMEMORY;
                goto free_manager;
@@ -3827,7 +4198,9 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
        }
        manager->stats = NULL;
 
-       manager->magic = SOCKET_MANAGER_MAGIC;
+       manager->common.methods = &socketmgrmethods;
+       manager->common.magic = ISCAPI_SOCKETMGR_MAGIC;
+       manager->common.impmagic = SOCKET_MANAGER_MAGIC;
        manager->mctx = NULL;
        memset(manager->fds, 0, manager->maxsocks * sizeof(isc_socket_t *));
        ISC_LIST_INIT(manager->socklist);
@@ -3851,7 +4224,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
                }
        }
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) {
                UNEXPECTED_ERROR(__FILE__, __LINE__,
                                 "isc_condition_init() %s",
@@ -3880,9 +4253,11 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
 #if 0
        RUNTIME_CHECK(make_nonblock(manager->pipe_fds[1]) == ISC_R_SUCCESS);
 #endif
-#else /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
+
+#ifdef USE_SHARED_MANAGER
        manager->refs = 1;
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_SHARED_MANAGER */
 
        /*
         * Set up initial state for the select loop
@@ -3891,7 +4266,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
        if (result != ISC_R_SUCCESS)
                goto cleanup;
        memset(manager->fdstate, 0, manager->maxsocks * sizeof(int));
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        /*
         * Start up the select/poll thread.
         */
@@ -3905,26 +4280,26 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
                result = ISC_R_UNEXPECTED;
                goto cleanup;
        }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
        isc_mem_attach(mctx, &manager->mctx);
 
-#ifndef ISC_PLATFORM_USETHREADS
+#ifdef USE_SHARED_MANAGER
        socketmgr = manager;
-#endif /* ISC_PLATFORM_USETHREADS */
-       *managerp = manager;
+#endif /* USE_SHARED_MANAGER */
+       *managerp = (isc_socketmgr_t *)manager;
 
        return (ISC_R_SUCCESS);
 
 cleanup:
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        (void)close(manager->pipe_fds[0]);
        (void)close(manager->pipe_fds[1]);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
 cleanup_condition:
        (void)isc_condition_destroy(&manager->shutdown_ok);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
 
 
 cleanup_lock:
@@ -3952,8 +4327,10 @@ free_manager:
        return (result);
 }
 
+#ifdef BIND9
 isc_result_t
-isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) {
+isc__socketmgr_getmaxsockets(isc_socketmgr_t *manager0, unsigned int *nsockp) {
+       isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
        REQUIRE(VALID_MANAGER(manager));
        REQUIRE(nsockp != NULL);
 
@@ -3963,7 +4340,9 @@ isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) {
 }
 
 void
-isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) {
+isc__socketmgr_setstats(isc_socketmgr_t *manager0, isc_stats_t *stats) {
+       isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+
        REQUIRE(VALID_MANAGER(manager));
        REQUIRE(ISC_LIST_EMPTY(manager->socklist));
        REQUIRE(manager->stats == NULL);
@@ -3971,10 +4350,11 @@ isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) {
 
        isc_stats_attach(stats, &manager->stats);
 }
+#endif
 
-void
-isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
-       isc_socketmgr_t *manager;
+ISC_SOCKETFUNC_SCOPE void
+isc__socketmgr_destroy(isc_socketmgr_t **managerp) {
+       isc__socketmgr_t *manager;
        int i;
        isc_mem_t *mctx;
 
@@ -3983,42 +4363,36 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
         */
 
        REQUIRE(managerp != NULL);
-       manager = *managerp;
+       manager = (isc__socketmgr_t *)*managerp;
        REQUIRE(VALID_MANAGER(manager));
 
-#ifndef ISC_PLATFORM_USETHREADS
-       if (manager->refs > 1) {
-               manager->refs--;
+#ifdef USE_SHARED_MANAGER
+       manager->refs--;
+       if (manager->refs > 0) {
                *managerp = NULL;
                return;
        }
-#endif /* ISC_PLATFORM_USETHREADS */
+       socketmgr = NULL;
+#endif /* USE_SHARED_MANAGER */
 
        LOCK(&manager->lock);
 
-#ifdef ISC_PLATFORM_USETHREADS
        /*
         * Wait for all sockets to be destroyed.
         */
        while (!ISC_LIST_EMPTY(manager->socklist)) {
+#ifdef USE_WATCHER_THREAD
                manager_log(manager, CREATION, "%s",
                            isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
                                           ISC_MSG_SOCKETSREMAIN,
                                           "sockets exist"));
                WAIT(&manager->shutdown_ok, &manager->lock);
+#else /* USE_WATCHER_THREAD */
+               UNLOCK(&manager->lock);
+               isc__taskmgr_dispatch(NULL);
+               LOCK(&manager->lock);
+#endif /* USE_WATCHER_THREAD */
        }
-#else /* ISC_PLATFORM_USETHREADS */
-       /*
-        * Hope all sockets have been destroyed.
-        */
-       if (!ISC_LIST_EMPTY(manager->socklist)) {
-               manager_log(manager, CREATION, "%s",
-                           isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
-                                          ISC_MSG_SOCKETSREMAIN,
-                                          "sockets exist"));
-               INSIST(0);
-       }
-#endif /* ISC_PLATFORM_USETHREADS */
 
        UNLOCK(&manager->lock);
 
@@ -4029,7 +4403,7 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
         */
        select_poke(manager, 0, SELECT_POKE_SHUTDOWN);
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        /*
         * Wait for thread to exit.
         */
@@ -4038,25 +4412,25 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
                                 "isc_thread_join() %s",
                                 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
                                                ISC_MSG_FAILED, "failed"));
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
 
        /*
         * Clean up.
         */
        cleanup_watcher(manager->mctx, manager);
 
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WATCHER_THREAD
        (void)close(manager->pipe_fds[0]);
        (void)close(manager->pipe_fds[1]);
        (void)isc_condition_destroy(&manager->shutdown_ok);
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
 
        for (i = 0; i < (int)manager->maxsocks; i++)
                if (manager->fdstate[i] == CLOSE_PENDING) /* no need to lock */
                        (void)close(i);
 
        isc_mem_put(manager->mctx, manager->fds,
-                   manager->maxsocks * sizeof(isc_socket_t *));
+                   manager->maxsocks * sizeof(isc__socket_t *));
        isc_mem_put(manager->mctx, manager->fdstate,
                    manager->maxsocks * sizeof(int));
 
@@ -4070,17 +4444,22 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
                            FDLOCK_COUNT * sizeof(isc_mutex_t));
        }
        DESTROYLOCK(&manager->lock);
-       manager->magic = 0;
+       manager->common.magic = 0;
+       manager->common.impmagic = 0;
        mctx= manager->mctx;
        isc_mem_put(mctx, manager, sizeof(*manager));
 
        isc_mem_detach(&mctx);
 
        *managerp = NULL;
+
+#ifdef USE_SHARED_MANAGER
+       socketmgr = NULL;
+#endif
 }
 
 static isc_result_t
-socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
+socket_recv(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
            unsigned int flags)
 {
        int io_state;
@@ -4151,13 +4530,14 @@ socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
        return (result);
 }
 
-isc_result_t
-isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
-                unsigned int minimum, isc_task_t *task,
-                isc_taskaction_t action, const void *arg)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recvv(isc_socket_t *sock0, isc_bufferlist_t *buflist,
+                 unsigned int minimum, isc_task_t *task,
+                 isc_taskaction_t action, const void *arg)
 {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
        isc_socketevent_t *dev;
-       isc_socketmgr_t *manager;
+       isc__socketmgr_t *manager;
        unsigned int iocount;
        isc_buffer_t *buffer;
 
@@ -4176,9 +4556,8 @@ isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
        INSIST(sock->bound);
 
        dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
-       if (dev == NULL) {
+       if (dev == NULL)
                return (ISC_R_NOMEMORY);
-       }
 
        /*
         * UDP sockets are always partial read
@@ -4205,12 +4584,14 @@ isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
        return (socket_recv(sock, dev, task, 0));
 }
 
-isc_result_t
-isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
-               isc_task_t *task, isc_taskaction_t action, const void *arg)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recv(isc_socket_t *sock0, isc_region_t *region,
+                unsigned int minimum, isc_task_t *task,
+                isc_taskaction_t action, const void *arg)
 {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
        isc_socketevent_t *dev;
-       isc_socketmgr_t *manager;
+       isc__socketmgr_t *manager;
 
        REQUIRE(VALID_SOCKET(sock));
        REQUIRE(action != NULL);
@@ -4224,16 +4605,18 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
        if (dev == NULL)
                return (ISC_R_NOMEMORY);
 
-       return (isc_socket_recv2(sock, region, minimum, task, dev, 0));
+       return (isc__socket_recv2(sock0, region, minimum, task, dev, 0));
 }
 
-isc_result_t
-isc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
-                unsigned int minimum, isc_task_t *task,
-                isc_socketevent_t *event, unsigned int flags)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_recv2(isc_socket_t *sock0, isc_region_t *region,
+                 unsigned int minimum, isc_task_t *task,
+                 isc_socketevent_t *event, unsigned int flags)
 {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
+
        event->ev_sender = sock;
-       event->result = ISC_R_UNEXPECTED;
+       event->result = ISC_R_UNSET;
        ISC_LIST_INIT(event->bufferlist);
        event->region = *region;
        event->n = 0;
@@ -4256,7 +4639,7 @@ isc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
 }
 
 static isc_result_t
-socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
+socket_send(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
            isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
            unsigned int flags)
 {
@@ -4347,24 +4730,25 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
        return (result);
 }
 
-isc_result_t
-isc_socket_send(isc_socket_t *sock, isc_region_t *region,
-               isc_task_t *task, isc_taskaction_t action, const void *arg)
+ISC_SOCKETFUNC_SCOPE 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)
 {
        /*
         * REQUIRE() checking is performed in isc_socket_sendto().
         */
-       return (isc_socket_sendto(sock, region, task, action, arg, NULL,
-                                 NULL));
+       return (isc__socket_sendto(sock, region, task, action, arg, NULL,
+                                  NULL));
 }
 
-isc_result_t
-isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
-                 isc_task_t *task, isc_taskaction_t action, const void *arg,
-                 isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendto(isc_socket_t *sock0, isc_region_t *region,
+                  isc_task_t *task, isc_taskaction_t action, const void *arg,
+                  isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
 {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
        isc_socketevent_t *dev;
-       isc_socketmgr_t *manager;
+       isc__socketmgr_t *manager;
 
        REQUIRE(VALID_SOCKET(sock));
        REQUIRE(region != NULL);
@@ -4377,30 +4761,30 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
        INSIST(sock->bound);
 
        dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg);
-       if (dev == NULL) {
+       if (dev == NULL)
                return (ISC_R_NOMEMORY);
-       }
 
        dev->region = *region;
 
        return (socket_send(sock, dev, task, address, pktinfo, 0));
 }
 
-isc_result_t
-isc_socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
-                isc_task_t *task, isc_taskaction_t action, const void *arg)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+                 isc_task_t *task, isc_taskaction_t action, const void *arg)
 {
-       return (isc_socket_sendtov(sock, buflist, task, action, arg, NULL,
-                                  NULL));
+       return (isc__socket_sendtov(sock, buflist, task, action, arg, NULL,
+                                   NULL));
 }
 
-isc_result_t
-isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
-                  isc_task_t *task, isc_taskaction_t action, const void *arg,
-                  isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendtov(isc_socket_t *sock0, isc_bufferlist_t *buflist,
+                   isc_task_t *task, isc_taskaction_t action, const void *arg,
+                   isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
 {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
        isc_socketevent_t *dev;
-       isc_socketmgr_t *manager;
+       isc__socketmgr_t *manager;
        unsigned int iocount;
        isc_buffer_t *buffer;
 
@@ -4417,9 +4801,8 @@ isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
        REQUIRE(iocount > 0);
 
        dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg);
-       if (dev == NULL) {
+       if (dev == NULL)
                return (ISC_R_NOMEMORY);
-       }
 
        /*
         * Move each buffer from the passed in list to our internal one.
@@ -4434,17 +4817,20 @@ isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
        return (socket_send(sock, dev, task, address, pktinfo, 0));
 }
 
-isc_result_t
-isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
-                  isc_task_t *task,
-                  isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
-                  isc_socketevent_t *event, unsigned int flags)
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_sendto2(isc_socket_t *sock0, isc_region_t *region,
+                   isc_task_t *task,
+                   isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+                   isc_socketevent_t *event, unsigned int flags)
 {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
+
+       REQUIRE(VALID_SOCKET(sock));
        REQUIRE((flags & ~(ISC_SOCKFLAG_IMMEDIATE|ISC_SOCKFLAG_NORETRY)) == 0);
        if ((flags & ISC_SOCKFLAG_NORETRY) != 0)
                REQUIRE(sock->type == isc_sockettype_udp);
        event->ev_sender = sock;
-       event->result = ISC_R_UNEXPECTED;
+       event->result = ISC_R_UNSET;
        ISC_LIST_INIT(event->bufferlist);
        event->region = *region;
        event->n = 0;
@@ -4454,8 +4840,8 @@ 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) {
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active) {
 #ifdef ISC_PLATFORM_HAVESYSUNH
        int s;
        struct stat sb;
@@ -4584,8 +4970,8 @@ isc_socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active) {
 #endif
 }
 
-isc_result_t
-isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm,
+ISC_SOCKETFUNC_SCOPE 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
@@ -4638,20 +5024,25 @@ isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm,
 #endif
 }
 
-isc_result_t
-isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
-               unsigned int options) {
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_bind(isc_socket_t *sock0, isc_sockaddr_t *sockaddr,
+                unsigned int options) {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
        char strbuf[ISC_STRERRORSIZE];
        int on = 1;
 
+       REQUIRE(VALID_SOCKET(sock));
+
        LOCK(&sock->lock);
 
        INSIST(!sock->bound);
+       INSIST(!sock->dupped);
 
        if (sock->pf != sockaddr->type.sa.sa_family) {
                UNLOCK(&sock->lock);
                return (ISC_R_FAMILYMISMATCH);
        }
+
        /*
         * Only set SO_REUSEADDR when we want a specific port.
         */
@@ -4702,9 +5093,17 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
        return (ISC_R_SUCCESS);
 }
 
-isc_result_t
-isc_socket_filter(isc_socket_t *sock, const char *filter) {
-#ifdef SO_ACCEPTFILTER
+/*
+ * Enable this only for specific OS versions, and only when they have repaired
+ * their problems with it.  Until then, this is is broken and needs to be
+ * diabled by default.  See RT22589 for details.
+ */
+#undef ENABLE_ACCEPTFILTER
+
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_filter(isc_socket_t *sock0, const char *filter) {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
+#if defined(SO_ACCEPTFILTER) && defined(ENABLE_ACCEPTFILTER)
        char strbuf[ISC_STRERRORSIZE];
        struct accept_filter_arg afa;
 #else
@@ -4714,7 +5113,7 @@ isc_socket_filter(isc_socket_t *sock, const char *filter) {
 
        REQUIRE(VALID_SOCKET(sock));
 
-#ifdef SO_ACCEPTFILTER
+#if defined(SO_ACCEPTFILTER) && defined(ENABLE_ACCEPTFILTER)
        bzero(&afa, sizeof(afa));
        strncpy(afa.af_name, filter, sizeof(afa.af_name));
        if (setsockopt(sock->fd, SOL_SOCKET, SO_ACCEPTFILTER,
@@ -4741,8 +5140,9 @@ isc_socket_filter(isc_socket_t *sock, const char *filter) {
  * is a new connection we'll have to allocate a new one anyway, so we might
  * as well keep things simple rather than having to track them.
  */
-isc_result_t
-isc_socket_listen(isc_socket_t *sock, unsigned int backlog) {
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_listen(isc_socket_t *sock0, unsigned int backlog) {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
        char strbuf[ISC_STRERRORSIZE];
 
        REQUIRE(VALID_SOCKET(sock));
@@ -4775,14 +5175,15 @@ isc_socket_listen(isc_socket_t *sock, unsigned int backlog) {
 /*
  * This should try to do aggressive accept() XXXMLG
  */
-isc_result_t
-isc_socket_accept(isc_socket_t *sock,
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_accept(isc_socket_t *sock0,
                  isc_task_t *task, isc_taskaction_t action, const void *arg)
 {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
        isc_socket_newconnev_t *dev;
-       isc_socketmgr_t *manager;
+       isc__socketmgr_t *manager;
        isc_task_t *ntask = NULL;
-       isc_socket_t *nsock;
+       isc__socket_t *nsock;
        isc_result_t result;
        isc_boolean_t do_poke = ISC_FALSE;
 
@@ -4819,11 +5220,18 @@ isc_socket_accept(isc_socket_t *sock,
         * Attach to socket and to task.
         */
        isc_task_attach(task, &ntask);
+       if (isc_task_exiting(ntask)) {
+               free_socket(&nsock);
+               isc_task_detach(&ntask);
+               isc_event_free(ISC_EVENT_PTR(&dev));
+               UNLOCK(&sock->lock);
+               return (ISC_R_SHUTTINGDOWN);
+       }
        nsock->references++;
        nsock->statsindex = sock->statsindex;
 
        dev->ev_sender = ntask;
-       dev->newsocket = nsock;
+       dev->newsocket = (isc_socket_t *)nsock;
 
        /*
         * Poke watcher here.  We still have the socket locked, so there
@@ -4842,15 +5250,17 @@ isc_socket_accept(isc_socket_t *sock,
        return (ISC_R_SUCCESS);
 }
 
-isc_result_t
-isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_connect(isc_socket_t *sock0, isc_sockaddr_t *addr,
                   isc_task_t *task, isc_taskaction_t action, const void *arg)
 {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
        isc_socket_connev_t *dev;
        isc_task_t *ntask = NULL;
-       isc_socketmgr_t *manager;
+       isc__socketmgr_t *manager;
        int cc;
        char strbuf[ISC_STRERRORSIZE];
+       char addrbuf[ISC_SOCKADDR_FORMATSIZE];
 
        REQUIRE(VALID_SOCKET(sock));
        REQUIRE(addr != NULL);
@@ -4919,7 +5329,9 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
                sock->connected = 0;
 
                isc__strerror(errno, strbuf, sizeof(strbuf));
-               UNEXPECTED_ERROR(__FILE__, __LINE__, "%d/%s", errno, strbuf);
+               isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
+               UNEXPECTED_ERROR(__FILE__, __LINE__, "connect(%s) %d/%s",
+                                addrbuf, errno, strbuf);
 
                UNLOCK(&sock->lock);
                inc_stats(sock->manager->stats,
@@ -4985,7 +5397,7 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
  */
 static void
 internal_connect(isc_task_t *me, isc_event_t *ev) {
-       isc_socket_t *sock;
+       isc__socket_t *sock;
        isc_socket_connev_t *dev;
        isc_task_t *task;
        int cc;
@@ -5099,8 +5511,9 @@ internal_connect(isc_task_t *me, isc_event_t *ev) {
        isc_task_sendanddetach(&task, ISC_EVENT_PTR(&dev));
 }
 
-isc_result_t
-isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_getpeername(isc_socket_t *sock0, isc_sockaddr_t *addressp) {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
        isc_result_t result;
 
        REQUIRE(VALID_SOCKET(sock));
@@ -5120,8 +5533,9 @@ isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) {
        return (result);
 }
 
-isc_result_t
-isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_getsockname(isc_socket_t *sock0, isc_sockaddr_t *addressp) {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
        ISC_SOCKADDR_LEN_T len;
        isc_result_t result;
        char strbuf[ISC_STRERRORSIZE];
@@ -5158,8 +5572,9 @@ isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
  * Run through the list of events on this socket, and cancel the ones
  * queued for task "task" of type "how".  "how" is a bitmask.
  */
-void
-isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_cancel(isc_socket_t *sock0, isc_task_t *task, unsigned int how) {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
 
        REQUIRE(VALID_SOCKET(sock));
 
@@ -5238,8 +5653,8 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
                                ISC_LIST_UNLINK(sock->accept_list, dev,
                                                ev_link);
 
-                               dev->newsocket->references--;
-                               free_socket(&dev->newsocket);
+                               NEWCONNSOCK(dev)->references--;
+                               free_socket((isc__socket_t **)&dev->newsocket);
 
                                dev->result = ISC_R_CANCELED;
                                dev->ev_sender = sock;
@@ -5278,17 +5693,22 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
        UNLOCK(&sock->lock);
 }
 
-isc_sockettype_t
-isc_socket_gettype(isc_socket_t *sock) {
+ISC_SOCKETFUNC_SCOPE isc_sockettype_t
+isc__socket_gettype(isc_socket_t *sock0) {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
+
        REQUIRE(VALID_SOCKET(sock));
 
        return (sock->type);
 }
 
-isc_boolean_t
-isc_socket_isbound(isc_socket_t *sock) {
+ISC_SOCKETFUNC_SCOPE isc_boolean_t
+isc__socket_isbound(isc_socket_t *sock0) {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
        isc_boolean_t val;
 
+       REQUIRE(VALID_SOCKET(sock));
+
        LOCK(&sock->lock);
        val = ((sock->bound) ? ISC_TRUE : ISC_FALSE);
        UNLOCK(&sock->lock);
@@ -5296,8 +5716,9 @@ isc_socket_isbound(isc_socket_t *sock) {
        return (val);
 }
 
-void
-isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
+ISC_SOCKETFUNC_SCOPE void
+isc__socket_ipv6only(isc_socket_t *sock0, isc_boolean_t yes) {
+       isc__socket_t *sock = (isc__socket_t *)sock0;
 #if defined(IPV6_V6ONLY)
        int onoff = yes ? 1 : 0;
 #else
@@ -5306,13 +5727,14 @@ isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
 #endif
 
        REQUIRE(VALID_SOCKET(sock));
+       INSIST(!sock->dupped);
 
 #ifdef IPV6_V6ONLY
        if (sock->pf == AF_INET6) {
                if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY,
                               (void *)&onoff, sizeof(int)) < 0) {
                        char strbuf[ISC_STRERRORSIZE];
-
+                       isc__strerror(errno, strbuf, sizeof(strbuf));
                        UNEXPECTED_ERROR(__FILE__, __LINE__,
                                         "setsockopt(%d, IPV6_V6ONLY) "
                                         "%s: %s", sock->fd,
@@ -5327,12 +5749,21 @@ isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
 #endif
 }
 
-#ifndef ISC_PLATFORM_USETHREADS
-/* In our assumed scenario, we can simply use a single static object. */
+#ifndef USE_WATCHER_THREAD
+/*
+ * In our assumed scenario, we can simply use a single static object.
+ * XXX: this is not true if the application uses multiple threads with
+ *      'multi-context' mode.  Fixing this is a future TODO item.
+ */
 static isc_socketwait_t swait_private;
 
 int
-isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) {
+isc__socketmgr_waitevents(isc_socketmgr_t *manager0, struct timeval *tvp,
+                         isc_socketwait_t **swaitp)
+{
+       isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+
+
        int n;
 #ifdef USE_KQUEUE
        struct timespec ts, *tsp;
@@ -5346,7 +5777,11 @@ isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) {
 
        REQUIRE(swaitp != NULL && *swaitp == NULL);
 
-       if (socketmgr == NULL)
+#ifdef USE_SHARED_MANAGER
+       if (manager == NULL)
+               manager = socketmgr;
+#endif
+       if (manager == NULL)
                return (0);
 
 #ifdef USE_KQUEUE
@@ -5356,8 +5791,8 @@ isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) {
                tsp = &ts;
        } else
                tsp = NULL;
-       swait_private.nevents = kevent(socketmgr->kqueue_fd, NULL, 0,
-                                      socketmgr->events, socketmgr->nevents,
+       swait_private.nevents = kevent(manager->kqueue_fd, NULL, 0,
+                                      manager->events, manager->nevents,
                                       tsp);
        n = swait_private.nevents;
 #elif defined(USE_EPOLL)
@@ -5365,29 +5800,28 @@ isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) {
                timeout = tvp->tv_sec * 1000 + (tvp->tv_usec + 999) / 1000;
        else
                timeout = -1;
-       swait_private.nevents = epoll_wait(socketmgr->epoll_fd,
-                                          socketmgr->events,
-                                          socketmgr->nevents, timeout);
+       swait_private.nevents = epoll_wait(manager->epoll_fd,
+                                          manager->events,
+                                          manager->nevents, timeout);
        n = swait_private.nevents;
 #elif defined(USE_DEVPOLL)
-       dvp.dp_fds = socketmgr->events;
-       dvp.dp_nfds = socketmgr->nevents;
+       dvp.dp_fds = manager->events;
+       dvp.dp_nfds = manager->nevents;
        if (tvp != NULL) {
                dvp.dp_timeout = tvp->tv_sec * 1000 +
                        (tvp->tv_usec + 999) / 1000;
        } else
                dvp.dp_timeout = -1;
-       swait_private.nevents = ioctl(socketmgr->devpoll_fd, DP_POLL, &dvp);
+       swait_private.nevents = ioctl(manager->devpoll_fd, DP_POLL, &dvp);
        n = swait_private.nevents;
 #elif defined(USE_SELECT)
-       memcpy(socketmgr->read_fds_copy, socketmgr->read_fds,
-              socketmgr->fd_bufsize);
-       memcpy(socketmgr->write_fds_copy, socketmgr->write_fds,
-              socketmgr->fd_bufsize);
+       memcpy(manager->read_fds_copy, manager->read_fds,  manager->fd_bufsize);
+       memcpy(manager->write_fds_copy, manager->write_fds,
+              manager->fd_bufsize);
 
-       swait_private.readset = socketmgr->read_fds_copy;
-       swait_private.writeset = socketmgr->write_fds_copy;
-       swait_private.maxfd = socketmgr->maxfd + 1;
+       swait_private.readset = manager->read_fds_copy;
+       swait_private.writeset = manager->write_fds_copy;
+       swait_private.maxfd = manager->maxfd + 1;
 
        n = select(swait_private.maxfd, swait_private.readset,
                   swait_private.writeset, NULL, tvp);
@@ -5398,24 +5832,32 @@ isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) {
 }
 
 isc_result_t
-isc__socketmgr_dispatch(isc_socketwait_t *swait) {
+isc__socketmgr_dispatch(isc_socketmgr_t *manager0, isc_socketwait_t *swait) {
+       isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
+
        REQUIRE(swait == &swait_private);
 
-       if (socketmgr == NULL)
+#ifdef USE_SHARED_MANAGER
+       if (manager == NULL)
+               manager = socketmgr;
+#endif
+       if (manager == NULL)
                return (ISC_R_NOTFOUND);
 
 #if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
-       (void)process_fds(socketmgr, socketmgr->events, swait->nevents);
+       (void)process_fds(manager, manager->events, swait->nevents);
        return (ISC_R_SUCCESS);
 #elif defined(USE_SELECT)
-       process_fds(socketmgr, swait->maxfd, swait->readset, swait->writeset);
+       process_fds(manager, swait->maxfd, swait->readset, swait->writeset);
        return (ISC_R_SUCCESS);
 #endif
 }
-#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_WATCHER_THREAD */
 
+#ifdef BIND9
 void
-isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) {
+isc__socket_setname(isc_socket_t *socket0, const char *name, void *tag) {
+       isc__socket_t *socket = (isc__socket_t *)socket0;
 
        /*
         * Name 'socket'.
@@ -5430,17 +5872,36 @@ isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) {
        UNLOCK(&socket->lock);
 }
 
-const char *
-isc_socket_getname(isc_socket_t *socket) {
+ISC_SOCKETFUNC_SCOPE const char *
+isc__socket_getname(isc_socket_t *socket0) {
+       isc__socket_t *socket = (isc__socket_t *)socket0;
+
        return (socket->name);
 }
 
 void *
-isc_socket_gettag(isc_socket_t *socket) {
+isc__socket_gettag(isc_socket_t *socket0) {
+       isc__socket_t *socket = (isc__socket_t *)socket0;
+
        return (socket->tag);
 }
+#endif /* BIND9 */
 
-#ifdef HAVE_LIBXML2
+#ifdef USE_SOCKETIMPREGISTER
+isc_result_t
+isc__socket_register() {
+       return (isc_socket_register(isc__socketmgr_create));
+}
+#endif
+
+ISC_SOCKETFUNC_SCOPE int
+isc__socket_getfd(isc_socket_t *socket0) {
+       isc__socket_t *socket = (isc__socket_t *)socket0;
+
+       return ((short) socket->fd);
+}
+
+#if defined(HAVE_LIBXML2) && defined(BIND9)
 
 static const char *
 _socktype(isc_sockettype_t type)
@@ -5457,21 +5918,21 @@ _socktype(isc_sockettype_t type)
                return ("not-initialized");
 }
 
-void
-isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer)
-{
-       isc_socket_t *sock;
+ISC_SOCKETFUNC_SCOPE void
+isc_socketmgr_renderxml(isc_socketmgr_t *mgr0, xmlTextWriterPtr writer) {
+       isc__socketmgr_t *mgr = (isc__socketmgr_t *)mgr0;
+       isc__socket_t *sock;
        char peerbuf[ISC_SOCKADDR_FORMATSIZE];
        isc_sockaddr_t addr;
        ISC_SOCKADDR_LEN_T len;
 
        LOCK(&mgr->lock);
 
-#ifndef ISC_PLATFORM_USETHREADS
+#ifdef USE_SHARED_MANAGER
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
        xmlTextWriterWriteFormatString(writer, "%d", mgr->refs);
        xmlTextWriterEndElement(writer);
-#endif
+#endif /* USE_SHARED_MANAGER */
 
        xmlTextWriterStartElement(writer, ISC_XMLCHAR "sockets");
        sock = ISC_LIST_HEAD(mgr->socklist);
index fc044e58b2943c2dfaaeb13acab188802bd62564..13160117391f3eaa246cf0fb3abd0d379f10ec26 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: socket_p.h,v 1.13 2008/06/23 23:47:11 tbox Exp $ */
+/* $Id: socket_p.h,v 1.15 2009/09/02 23:48:03 tbox Exp $ */
 
 #ifndef ISC_SOCKET_P_H
 #define ISC_SOCKET_P_H
@@ -27,6 +27,7 @@
 #endif
 
 typedef struct isc_socketwait isc_socketwait_t;
-int isc__socketmgr_waitevents(struct timeval *, isc_socketwait_t **);
-isc_result_t isc__socketmgr_dispatch(isc_socketwait_t *);
+int isc__socketmgr_waitevents(isc_socketmgr_t *, struct timeval *,
+                             isc_socketwait_t **);
+isc_result_t isc__socketmgr_dispatch(isc_socketmgr_t *, isc_socketwait_t *);
 #endif /* ISC_SOCKET_P_H */
index 4e294dbc2fee07dd4d2d53a2d5d6bd8f8def5c27..360c8c644afc214bf8be70cdeb496dceaf9e5d11 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: stdio.c,v 1.8 2007/06/19 23:47:18 tbox Exp $ */
+/* $Id$ */
 
 #include <config.h>
 
@@ -23,6 +23,7 @@
 #include <unistd.h>
 
 #include <isc/stdio.h>
+#include <isc/stat.h>
 
 #include "errno2result.h"
 
@@ -104,12 +105,23 @@ isc_stdio_flush(FILE *f) {
                return (isc__errno2result(errno));
 }
 
+/*
+ * OpenBSD has deprecated ENOTSUP in favor of EOPNOTSUPP.
+ */
+#if defined(EOPNOTSUPP) && !defined(ENOTSUP)
+#define ENOTSUP EOPNOTSUPP
+#endif
+
 isc_result_t
 isc_stdio_sync(FILE *f) {
        int r;
 
        r = fsync(fileno(f));
-       if (r == 0)
+       /*
+        * fsync is not supported on sockets and pipes which
+        * result in EINVAL / ENOTSUP.
+        */
+       if (r == 0 || errno == EINVAL || errno == ENOTSUP)
                return (ISC_R_SUCCESS);
        else
                return (isc__errno2result(errno));
index 349c8bd92cf7b6340d60556f373d0a7f211fc3f3..caa6659154f98d519570c2ea2190135d4e60192e 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: strerror.c,v 1.8.332.2 2009/02/16 23:47:15 tbox Exp $ */
+/* $Id: strerror.c,v 1.10 2009/02/16 23:48:04 tbox Exp $ */
 
 /*! \file */
 
index 59428d3ca776b203f7932d0591c7a3f742cf993f..ac23ae092804e2c9d60810240293352ea8ee22ee 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: time.c,v 1.56 2008/02/15 23:46:51 tbox Exp $ */
+/* $Id$ */
 
 /*! \file */
 
@@ -319,7 +319,7 @@ isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2) {
        /*
         * Convert to microseconds.
         */
-       i3 = (i1 - i2) / NS_PER_US;
+       i3 /= NS_PER_US;
 
        return (i3);
 }
@@ -334,7 +334,6 @@ isc_time_seconds(const isc_time_t *t) {
 
 isc_result_t
 isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp) {
-       isc_uint64_t i;
        time_t seconds;
 
        REQUIRE(t != NULL);
@@ -354,33 +353,16 @@ isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp) {
         * pretty much only true if time_t is a signed integer of the same
         * size as the return value of isc_time_seconds.
         *
-        * The use of the 64 bit integer ``i'' takes advantage of C's
-        * conversion rules to either zero fill or sign extend the widened
-        * type.
-        *
-        * Solaris 5.6 gives this warning about the left shift:
-        *      warning: integer overflow detected: op "<<"
-        * if the U(nsigned) qualifier is not on the 1.
+        * If the paradox in the if clause below is true, t->seconds is out
+        * of range for time_t.
         */
        seconds = (time_t)t->seconds;
 
        INSIST(sizeof(unsigned int) == sizeof(isc_uint32_t));
        INSIST(sizeof(time_t) >= sizeof(isc_uint32_t));
 
-       if (sizeof(time_t) == sizeof(isc_uint32_t) &&          /* Same size. */
-           (time_t)0.5 != 0.5 &&              /* Not a floating point type. */
-           (i = (time_t)-1) != 4294967295u &&                 /* Is signed. */
-           (seconds &
-            (1U << (sizeof(time_t) * CHAR_BIT - 1))) != 0U) {   /* Negative. */
-               /*
-                * This UNUSED() is here to shut up the IRIX compiler:
-                *      variable "i" was set but never used
-                * when the value of i *was* used in the third test.
-                * (Let's hope the compiler got the actual test right.)
-                */
-               UNUSED(i);
+       if (t->seconds > (~0U>>1) && seconds <= (time_t)(~0U>>1))
                return (ISC_R_RANGE);
-       }
 
        *secondsp = seconds;
 
index b0db90d410bdb06e048fbc0b9739b46bb3b6c5d2..04b1638783eb7927bbc25a00ad0a9460407337b6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: app.c,v 1.7 2007/06/19 23:47:19 tbox Exp $ */
+/* $Id: app.c,v 1.9 2009/09/02 23:48:03 tbox Exp $ */
 
 #include <config.h>
 
@@ -75,7 +75,7 @@ DWORD  dwWaitResult;
 static isc_thread_t    main_thread;
 
 isc_result_t
-isc_app_start(void) {
+isc__app_start(void) {
        isc_result_t result;
 
        /*
@@ -99,7 +99,7 @@ isc_app_start(void) {
 }
 
 isc_result_t
-isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
+isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
              void *arg) {
        isc_event_t *event;
        isc_task_t *cloned_task = NULL;
@@ -133,7 +133,7 @@ isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
 }
 
 isc_result_t
-isc_app_run(void) {
+isc__app_run(void) {
        isc_event_t *event, *next_event;
        isc_task_t *task;
        HANDLE *pHandles = NULL;
@@ -170,7 +170,7 @@ isc_app_run(void) {
                                                      FALSE, INFINITE);
 
                /* See why we returned */
-               
+
                if (WaitSucceeded(dwWaitResult, NUM_EVENTS)) {
                        /*
                         * The return was due to one of the events
@@ -199,7 +199,7 @@ isc_app_run(void) {
 }
 
 isc_result_t
-isc_app_shutdown(void) {
+isc__app_shutdown(void) {
        isc_boolean_t want_kill = ISC_TRUE;
 
        LOCK(&lock);
@@ -218,7 +218,7 @@ isc_app_shutdown(void) {
 }
 
 isc_result_t
-isc_app_reload(void) {
+isc__app_reload(void) {
        isc_boolean_t want_reload = ISC_TRUE;
 
        LOCK(&lock);
@@ -238,12 +238,12 @@ isc_app_reload(void) {
 }
 
 void
-isc_app_finish(void) {
+isc__app_finish(void) {
        DESTROYLOCK(&lock);
 }
 
 void
-isc_app_block(void) {
+isc__app_block(void) {
        REQUIRE(running);
        REQUIRE(!blocked);
 
@@ -252,7 +252,7 @@ isc_app_block(void) {
 }
 
 void
-isc_app_unblock(void) {
+isc__app_unblock(void) {
        REQUIRE(running);
        REQUIRE(blocked);
        blocked = ISC_FALSE;
index cbeacbaafaba41c6a39f86287e2d6613ee96373c..14fadde46af38275b72295f536be92245fac1298 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007-2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dir.c,v 1.16.22.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id$ */
 
 /* Principal Authors: DCL */
 
@@ -85,7 +85,7 @@ isc_dir_open(isc_dir_t *dir, const char *dirname) {
        if (dir->dirname < p && *(p - 1) != '\\' && *(p - 1) != ':')
                *p++ = '\\';
        *p++ = '*';
-       *p++ = '\0';
+       *p = '\0';
 
        /*
         * Open stream.
index 7f4bb3fb39cf580f99f2bb45669693d0fbe3df41..5a316e6e5cff04deaab30cd6a8387adc5109a75f 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: entropy.c,v 1.8.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: entropy.c,v 1.10 2009/01/18 23:48:14 tbox Exp $ */
 
 /*
  * This is the system dependent part of the ISC entropy API.
index baf7953a00ec781e30769d630193a01375513861..c6b9e4f56f1f89452b0bf4f928d6b14cbf99d105 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000-2002  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: file.c,v 1.31 2007/06/19 23:47:19 tbox Exp $ */
+/* $Id$ */
 
 #include <config.h>
 
 #include <sys/utime.h>
 
 #include <isc/file.h>
+#include <isc/mem.h>
 #include <isc/result.h>
 #include <isc/time.h>
 #include <isc/util.h>
 #include <isc/stat.h>
+#include <isc/string.h>
 
 #include "errno2result.h"
 
@@ -213,9 +215,9 @@ isc_file_getmodtime(const char *file, isc_time_t *time) {
                         &time->absolute))
        {
                close(fh);
-                errno = EINVAL;
-                return (isc__errno2result(errno));
-        }
+               errno = EINVAL;
+               return (isc__errno2result(errno));
+       }
        close(fh);
        return (ISC_R_SUCCESS);
 }
@@ -229,23 +231,23 @@ isc_file_settime(const char *file, isc_time_t *time) {
        if ((fh = open(file, _O_RDWR | _O_BINARY)) < 0)
                return (isc__errno2result(errno));
 
-        /*
+       /*
         * Set the date via the filedate system call and return.  Failing
-         * this call implies the new file times are not supported by the
-         * underlying file system.
-         */
+        * this call implies the new file times are not supported by the
+        * underlying file system.
+        */
        if (!SetFileTime((HANDLE) _get_osfhandle(fh),
                         NULL,
                         &time->absolute,
                         &time->absolute))
        {
                close(fh);
-                errno = EINVAL;
-                return (isc__errno2result(errno));
-        }
+               errno = EINVAL;
+               return (isc__errno2result(errno));
+       }
 
        close(fh);
-        return (ISC_R_SUCCESS);
+       return (ISC_R_SUCCESS);
 
 }
 
@@ -314,8 +316,20 @@ isc_file_renameunique(const char *file, char *templet) {
        return (result);
 }
 
+isc_result_t
+isc_file_openuniqueprivate(char *templet, FILE **fp) {
+       int mode = _S_IREAD | _S_IWRITE;
+       return (isc_file_openuniquemode(templet, mode, fp));
+}
+
 isc_result_t
 isc_file_openunique(char *templet, FILE **fp) {
+       int mode = _S_IREAD | _S_IWRITE;
+       return (isc_file_openuniquemode(templet, mode, fp));
+}
+
+isc_result_t
+isc_file_openuniquemode(char *templet, int mode, FILE **fp) {
        int fd;
        FILE *f;
        isc_result_t result = ISC_R_SUCCESS;
@@ -331,6 +345,11 @@ isc_file_openunique(char *templet, FILE **fp) {
        if (fd == -1)
                result = isc__errno2result(errno);
        if (result == ISC_R_SUCCESS) {
+#if 1
+               UNUSED(mode);
+#else
+               (void)fchmod(fd, mode);
+#endif
                f = fdopen(fd, "w+");
                if (f == NULL) {
                        result = isc__errno2result(errno);
@@ -379,6 +398,23 @@ isc_file_exists(const char *pathname) {
        return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS));
 }
 
+isc_result_t
+isc_file_isplainfile(const char *filename) {
+       /*
+        * This function returns success if filename is a plain file.
+        */
+       struct stat filestat;
+       memset(&filestat,0,sizeof(struct stat));
+
+       if ((stat(filename, &filestat)) == -1)
+               return(isc__errno2result(errno));
+
+       if(! S_ISREG(filestat.st_mode))
+               return(ISC_R_INVALIDFILE);
+
+       return(ISC_R_SUCCESS);
+}
+
 isc_boolean_t
 isc_file_isabsolute(const char *filename) {
        REQUIRE(filename != NULL);
@@ -457,7 +493,7 @@ isc_file_progname(const char *filename, char *progname, size_t namelen) {
                return (ISC_R_SUCCESS);
        }
 
-       /* 
+       /*
         * Copy the result to the buffer
         */
        len = p - s;
@@ -505,3 +541,79 @@ isc_file_truncate(const char *filename, isc_offset_t size) {
 
        return (ISC_R_SUCCESS);
 }
+
+isc_result_t
+isc_file_safecreate(const char *filename, FILE **fp) {
+       isc_result_t result;
+       int flags;
+       struct stat sb;
+       FILE *f;
+       int fd;
+
+       REQUIRE(filename != NULL);
+       REQUIRE(fp != NULL && *fp == NULL);
+
+       result = file_stats(filename, &sb);
+       if (result == ISC_R_SUCCESS) {
+               if ((sb.st_mode & S_IFREG) == 0)
+                       return (ISC_R_INVALIDFILE);
+               flags = O_WRONLY | O_TRUNC;
+       } else if (result == ISC_R_FILENOTFOUND) {
+               flags = O_WRONLY | O_CREAT | O_EXCL;
+       } else
+               return (result);
+
+       fd = open(filename, flags, S_IRUSR | S_IWUSR);
+       if (fd == -1)
+               return (isc__errno2result(errno));
+
+       f = fdopen(fd, "w");
+       if (f == NULL) {
+               result = isc__errno2result(errno);
+               close(fd);
+               return (result);
+       }
+
+       *fp = f;
+       return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_splitpath(isc_mem_t *mctx, char *path, char **dirname, char **basename)
+{
+       char *dir, *file, *slash;
+       char *backslash;
+
+       slash = strrchr(path, '/');
+
+       backslash = strrchr(path, '\\');
+       if ((slash != NULL && backslash != NULL && backslash > slash) ||
+           (slash == NULL && backslash != NULL))
+               slash = backslash;
+
+       if (slash == path) {
+               file = ++slash;
+               dir = isc_mem_strdup(mctx, "/");
+       } else if (slash != NULL) {
+               file = ++slash;
+               dir = isc_mem_allocate(mctx, slash - path);
+               if (dir != NULL)
+                       strlcpy(dir, path, slash - path);
+       } else {
+               file = path;
+               dir = isc_mem_strdup(mctx, ".");
+       }
+
+       if (dir == NULL)
+               return (ISC_R_NOMEMORY);
+
+       if (*file == '\0') {
+               isc_mem_free(mctx, dir);
+               return (ISC_R_INVALIDFILE);
+       }
+
+       *dirname = dir;
+       *basename = file;
+
+       return (ISC_R_SUCCESS);
+}
index c9add0b37944c44be3c3bf584d1f306fadcea0aa..8f085c1f13a88c22acb2727a443bfd5a3901a929 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2002  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: ipv6.h,v 1.19 2007/06/18 23:47:49 tbox Exp $ */
+/* $Id$ */
 
 #ifndef ISC_IPV6_H
 #define ISC_IPV6_H 1
@@ -111,14 +111,14 @@ LIBISC_EXTERNAL_DATA extern const struct in6_addr isc_in6addr_loopback;
  */
 #ifndef IN6_IS_ADDR_LINKLOCAL
 #define IN6_IS_ADDR_LINKLOCAL(a)       (\
-(*((u_long *)((a)->s6_addr)    ) == 0xfe) && \
-((*((u_long *)((a)->s6_addr) + 1) & 0xc0) == 0x80))
+       ((a)->s6_addr[0] == 0xfe) && \
+       (((a)->s6_addr[1] & 0xc0) == 0x80))
 #endif
 
 #ifndef IN6_IS_ADDR_SITELOCAL
 #define IN6_IS_ADDR_SITELOCAL(a)       (\
-(*((u_long *)((a)->s6_addr)    ) == 0xfe) && \
-((*((u_long *)((a)->s6_addr) + 1) & 0xc0) == 0xc0))
+       ((a)->s6_addr[0] == 0xfe) && \
+       (((a)->s6_addr[1] & 0xc0) == 0xc0))
 #endif
 
 #endif /* ISC_IPV6_H */
index 921c1e9380b1a22bd127f0b45c4a0af8c70e11dd..5cf1bae1ba60834c20c74751aed12441c71e16d0 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: mutex.h,v 1.20.56.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: mutex.h,v 1.22 2009/01/18 23:48:14 tbox Exp $ */
 
 #ifndef ISC_MUTEX_H
 #define ISC_MUTEX_H 1
index 249a50a8310639d716deaa23ba3ed39e033a974c..43e424d865360e98175c61f1e423a313290440cc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: net.h,v 1.30.82.2 2009/02/16 23:47:15 tbox Exp $ */
+/* $Id$ */
 
 #ifndef ISC_NET_H
 #define ISC_NET_H 1
index 7cd185a031d428149d79b542a8ce840e914989ba..39bcb6276f6c1f0a9caf5cf3270c25e2c808fd38 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: ntpaths.h,v 1.16 2007/06/19 23:47:20 tbox Exp $ */
+/* $Id: ntpaths.h,v 1.20 2009/07/14 22:54:57 each Exp $ */
 
 /*
  * Windows-specific path definitions
@@ -40,7 +40,8 @@ enum NtPaths {
        LWRESD_PID_PATH,
        LOCAL_STATE_DIR,
        SYS_CONF_DIR,
-       RNDC_KEY_PATH
+       RNDC_KEY_PATH,
+       SESSION_KEY_PATH
 };
 
 /*
@@ -49,9 +50,9 @@ enum NtPaths {
 #define NAMED_CONFFILE isc_ntpaths_get(NAMED_CONF_PATH)
 #define RNDC_CONFFILE isc_ntpaths_get(RNDC_CONF_PATH)
 #define RNDC_KEYFILE isc_ntpaths_get(RNDC_KEY_PATH)
+#define SESSION_KEYFILE isc_ntpaths_get(SESSION_KEY_PATH)
 #define RESOLV_CONF isc_ntpaths_get(RESOLV_CONF_PATH)
 
-
 /*
  * Information about where the files are on disk
  */
index c93b50c7472044b974d037b69f2de18faf536c64..d632d3cf7e581982b51b06e87180321f2d4fc726 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: platform.h,v 1.16.118.2 2009/02/16 23:47:15 tbox Exp $ */
+/* $Id: platform.h,v 1.19 2009/09/29 23:48:04 tbox Exp $ */
 
 #ifndef ISC_PLATFORM_H
 #define ISC_PLATFORM_H 1
  */
 #undef ISC_PLATFORM_HAVESYSUNH
 
+/*
+ * Defines for the noreturn attribute.
+ */
+#define ISC_PLATFORM_NORETURN_PRE __declspec(noreturn)
+#define ISC_PLATFORM_NORETURN_POST
+
  /*
  * Set up a macro for importing and exporting from the DLL
  */
index 2638a916ddc8bb1de295ae08b82127a25304fac8..2c822b9e7d751cc582e91423d4201ef381b465c5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: stat.h,v 1.7 2007/06/19 23:47:20 tbox Exp $ */
+/* $Id: stat.h,v 1.9 2009/10/01 23:48:08 tbox Exp $ */
 
 #ifndef ISC_STAT_H
 #define ISC_STAT_H 1
@@ -24,7 +24,7 @@
 
 /* open() under unix allows setting of read/write permissions
  * at the owner, group and other levels.  These don't exist in NT
- * We'll just map them all to the NT equivalent 
+ * We'll just map them all to the NT equivalent
  */
 
 #define S_IREAD        _S_IREAD        /* read permission, owner */
 #define S_IROTH _S_IREAD       /* Other read permission */
 #define S_IWOTH _S_IWRITE      /* Other write permission */
 
+#ifndef S_IFMT
+# define S_IFMT   _S_IFMT
+#endif
+#ifndef S_IFDIR
+# define S_IFDIR  _S_IFDIR
+#endif
+#ifndef S_IFCHR
+# define S_IFCHR  _S_IFCHR
+#endif
+#ifndef S_IFREG
+# define S_IFREG  _S_IFREG
+#endif
+
 #ifndef S_ISDIR
 # define S_ISDIR(m)    (((m) & S_IFMT) == S_IFDIR)
 #endif
index 4f9eb74c54b6c3003f35c47727870f3653284695..abbbc16c1d69676950d07f236079f6f3efc38b88 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: stdtime.h,v 1.12 2007/06/19 23:47:20 tbox Exp $ */
+/* $Id$ */
 
 #ifndef ISC_STDTIME_H
 #define ISC_STDTIME_H 1
  * about its size.
  */
 typedef isc_uint32_t isc_stdtime_t;
+
+/* but this flag helps... */
+#define STDTIME_ON_32BITS      1
+
 /*
  * isc_stdtime32_t is a 32-bit version of isc_stdtime_t.  A variable of this
  * type should only be used as an opaque integer (e.g.,) to compare two
index 78e663f457d2599e5f832583c814aa4911acf04f..2eb923b2e61b7a3c2c0ebf7eaa29ff72cda7b03f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: thread.h,v 1.22 2007/06/19 23:47:20 tbox Exp $ */
+/* $Id: thread.h,v 1.25 2009/09/29 04:37:08 marka Exp $ */
 
 #ifndef ISC_THREAD_H
 #define ISC_THREAD_H 1
@@ -37,18 +37,18 @@ inline BOOL IsValidHandle( HANDLE hHandle) {
 /* validate wait return codes... */
 inline BOOL WaitSucceeded( DWORD dwWaitResult, DWORD dwHandleCount) {
     return ((dwWaitResult >= WAIT_OBJECT_0) &&
-            (dwWaitResult < WAIT_OBJECT_0 + dwHandleCount));
+           (dwWaitResult < WAIT_OBJECT_0 + dwHandleCount));
 }
 
 inline BOOL WaitAbandoned( DWORD dwWaitResult, DWORD dwHandleCount) {
     return ((dwWaitResult >= WAIT_ABANDONED_0) &&
-            (dwWaitResult < WAIT_ABANDONED_0 + dwHandleCount));
+           (dwWaitResult < WAIT_ABANDONED_0 + dwHandleCount));
 }
 
 inline BOOL WaitTimeout( DWORD dwWaitResult) {
     return (dwWaitResult == WAIT_TIMEOUT);
 }
-    
+
 inline BOOL WaitFailed( DWORD dwWaitResult) {
     return (dwWaitResult == WAIT_FAILED);
 }
@@ -65,7 +65,7 @@ inline DWORD WaitAbandonedIndex( DWORD dwWaitResult) {
 
 
 typedef HANDLE isc_thread_t;
-typedef unsigned int isc_threadresult_t;
+typedef DWORD isc_threadresult_t;
 typedef void * isc_threadarg_t;
 typedef isc_threadresult_t (WINAPI *isc_threadfunc_t)(isc_threadarg_t);
 typedef DWORD isc_thread_key_t;
@@ -90,7 +90,7 @@ int
 isc_thread_key_delete(isc_thread_key_t key);
 
 void *
-isc_thread_key_getspecific(isc_thread_key);
+isc_thread_key_getspecific(isc_thread_key_t);
 
 int
 isc_thread_key_setspecific(isc_thread_key_t key, void *value);
index ce3c4c6a27a26e4f19a340ce5e1ec51312139ba6..8ffb24b11428c3c217b65d5fc9298479b9a70c69 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: time.h,v 1.33.56.2 2009/01/05 23:47:23 tbox Exp $ */
+/* $Id: time.h,v 1.35 2009/01/05 23:47:54 tbox Exp $ */
 
 #ifndef ISC_TIME_H
 #define ISC_TIME_H 1
index d86820532c35f588aa1b15fd7d09d53a1db05c68..bd40393619138f36cf6e1d90a208d0c2f22e24f3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2002  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: win32os.h,v 1.5 2007/06/19 23:47:20 tbox Exp $ */
+/* $Id: win32os.h,v 1.7 2009/06/25 23:48:02 tbox Exp $ */
 
 #ifndef ISC_WIN32OS_H
 #define ISC_WIN32OS_H 1
@@ -68,4 +68,4 @@ isc_win32os_versioncheck(unsigned int major, unsigned int minor,
 
 ISC_LANG_ENDDECLS
 
-#endif /* ISC_OS_H */
+#endif /* ISC_WIN32OS_H */
index a69b70269492366e858d7b3ca8db3a7aa390daba..58ef8836390d6bd475a68aa6b32f60699dfb8ce2 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: interfaceiter.c,v 1.13.110.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: interfaceiter.c,v 1.15 2009/01/18 23:48:14 tbox Exp $ */
 
 /*
  * Note that this code will need to be revisited to support IPv6 Interfaces.
diff --git a/lib/isc/win32/libgen.h b/lib/isc/win32/libgen.h
new file mode 100644 (file)
index 0000000..1c58a95
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: libgen.h,v 1.3 2009/07/17 23:47:41 tbox Exp $ */
+
+#ifndef LIBGEN_H
+#define LIBGEN_H 1
+
+char *basename(const char *);
+char *dirname(const char *);
+
+#endif
index 19a2fef6613debd50c3d4d9f7f9b35d38aa076e6..fb084103da5317aac6df35608335339cf81aa79f 100644 (file)
@@ -5,6 +5,26 @@ EXPORTS
 
 NTReportError
 closelog
+isc___mem_allocate
+isc___mem_free
+isc___mem_get
+isc___mem_put
+isc___mem_putanddetach
+isc___mem_reallocate
+isc___mem_strdup
+isc___mempool_get
+isc___mempool_put
+isc___socketmgr_maxudp
+isc__app_block
+isc__app_finish
+isc__app_onrun
+isc__app_reload
+isc__app_run
+isc__app_shutdown
+isc__app_start
+isc__app_unblock
+isc__backtrace_nsymbols
+isc__backtrace_symtable
 isc__buffer_activeregion
 isc__buffer_add
 isc__buffer_availableregion
@@ -26,27 +46,116 @@ isc__buffer_remainingregion
 isc__buffer_setactive
 isc__buffer_subtract
 isc__buffer_usedregion
-isc__mem_allocate
-isc__mem_free
-isc__mem_get
-isc__mem_put
-isc__mem_putanddetach
-isc__mem_reallocate
-isc__mem_strdup
-isc__mempool_get
-isc__mempool_put
+isc__mem_attach
+isc__mem_checkdestroyed
+isc__mem_create
+isc__mem_create2
+isc__mem_createx
+isc__mem_createx2
+isc__mem_destroy
+isc__mem_detach
+isc__mem_getname
+isc__mem_getquota
+isc__mem_gettag
+isc__mem_inuse
+isc__mem_isovermem
+isc__mem_ondestroy
+isc__mem_references
+isc__mem_setdestroycheck
+isc__mem_setname
+isc__mem_setquota
+isc__mem_setwater
+isc__mem_stats
+isc__mem_waterack
+isc__mempool_associatelock
+isc__mempool_create
+isc__mempool_destroy
+isc__mempool_getallocated
+isc__mempool_getfillcount
+isc__mempool_getfreecount
+isc__mempool_getfreemax
+isc__mempool_getmaxalloc
+isc__mempool_setfillcount
+isc__mempool_setfreemax
+isc__mempool_setmaxalloc
+isc__mempool_setname
+isc__socket_accept
+isc__socket_attach
+isc__socket_bind
+isc__socket_cancel
+isc__socket_cleanunix
+isc__socket_close
+isc__socket_connect
+isc__socket_create
+isc__socket_detach
+isc__socket_dup
+isc__socket_filter
+isc__socket_getfd
+isc__socket_getname
+isc__socket_getpeername
+isc__socket_getsockname
+isc__socket_gettag
+isc__socket_gettype
+isc__socket_ipv6only
+isc__socket_isbound
+isc__socket_listen
+isc__socket_open
+isc__socket_permunix
+isc__socket_recv
+isc__socket_recv2
+isc__socket_recvv
+isc__socket_send
+isc__socket_sendto
+isc__socket_sendto2
+isc__socket_sendtov
+isc__socket_sendv
+isc__socket_setname
+isc__socketmgr_create
+isc__socketmgr_create2
+isc__socketmgr_destroy
+isc__socketmgr_getmaxsockets
 isc__socketmgr_setreserved
+isc__socketmgr_setstats
 isc__strerror
-isc_app_block
-isc_app_finish
-isc_app_onrun
-isc_app_reload
-isc_app_run
-isc_app_shutdown
-isc_app_start
-isc_app_unblock
+isc__task_attach
+isc__task_beginexclusive
+isc__task_create
+isc__task_destroy
+isc__task_detach
+isc__task_endexclusive
+isc__task_getcurrenttime
+isc__task_getname
+isc__task_gettag
+isc__task_onshutdown
+isc__task_privilege
+isc__task_purge
+isc__task_purgeevent
+isc__task_purgerange
+isc__task_send
+isc__task_sendanddetach
+isc__task_setname
+isc__task_setprivilege
+isc__task_shutdown
+isc__task_unsend
+isc__task_unsendrange
+isc__taskmgr_create
+isc__taskmgr_destroy
+isc__taskmgr_mode
+isc__taskmgr_setmode
+isc__timer_attach
+isc__timer_create
+isc__timer_detach
+isc__timer_reset
+isc__timer_touch
+isc__timermgr_create
+isc__timermgr_destroy
+isc__timermgr_poke
+isc_assertion_failed
 isc_assertion_setcallback
 isc_assertion_typetotext
+isc_backtrace_getsymbol
+isc_backtrace_getsymbolfromindex
+isc_backtrace_gettrace
 isc_base32_decoderegion
 isc_base32_decodestring
 isc_base32_tobuffer
@@ -114,14 +223,19 @@ isc_file_getmodtime
 isc_file_isabsolute
 isc_file_ischdiridempotent
 isc_file_iscurrentdir
+isc_file_isplainfile
 isc_file_mktemplate
 isc_file_openunique
+isc_file_openuniquemode
+isc_file_openuniqueprivate
 isc_file_progname
 isc_file_remove
 isc_file_rename
 isc_file_renameunique
+isc_file_safecreate
 isc_file_safemovefile
 isc_file_settime
+isc_file_splitpath
 isc_file_template
 isc_file_truncate
 isc_fsaccess_add
@@ -250,38 +364,7 @@ isc_md5_final
 isc_md5_init
 isc_md5_invalidate
 isc_md5_update
-isc_mem_attach
-isc_mem_checkdestroyed
-isc_mem_create
-isc_mem_create2
-isc_mem_createx
-isc_mem_createx2
-isc_mem_destroy
-isc_mem_detach
-isc_mem_getname
-isc_mem_getquota
-isc_mem_gettag
-isc_mem_inuse
-isc_mem_ondestroy
-isc_mem_references
-isc_mem_setdestroycheck
-isc_mem_setname
-isc_mem_setquota
-isc_mem_setwater
-isc_mem_stats
-isc_mem_waterack
-isc_mempool_associatelock
-isc_mempool_create
-isc_mempool_destroy
-isc_mempool_getallocated
-isc_mempool_getfillcount
-isc_mempool_getfreecount
-isc_mempool_getfreemax
-isc_mempool_getmaxalloc
-isc_mempool_setfillcount
-isc_mempool_setfreemax
-isc_mempool_setmaxalloc
-isc_mempool_setname
+isc_mem_renderxml
 isc_msgcat_close
 isc_msgcat_get
 isc_msgcat_open
@@ -308,6 +391,7 @@ isc_netaddr_fromin6
 isc_netaddr_frompath
 isc_netaddr_fromsockaddr
 isc_netaddr_fromv4mapped
+isc_netaddr_getzone
 isc_netaddr_ismulticast
 isc_netaddr_masktoprefixlen
 isc_netaddr_prefixok
@@ -382,15 +466,20 @@ isc_sha1_invalidate
 isc_sha1_update
 isc_sha224_final
 isc_sha224_init
+isc_sha224_invalidate
 isc_sha224_update
+isc_sha256_data
 isc_sha256_final
 isc_sha256_init
+isc_sha256_invalidate
 isc_sha256_update
 isc_sha384_final
 isc_sha384_init
+isc_sha384_invalidate
 isc_sha384_update
 isc_sha512_final
 isc_sha512_init
+isc_sha512_invalidate
 isc_sha512_update
 isc_sockaddr_any
 isc_sockaddr_any6
@@ -412,47 +501,14 @@ isc_sockaddr_pf
 isc_sockaddr_setport
 isc_sockaddr_totext
 isc_sockaddr_v6fromin
-isc_socket_accept
-isc_socket_attach
-isc_socket_bind
-isc_socket_cancel
-isc_socket_cleanunix
-isc_socket_close
-isc_socket_connect
-isc_socket_create
-isc_socket_detach
-isc_socket_filter
-isc_socket_getname
-isc_socket_getpeername
-isc_socket_getsockname
-isc_socket_gettag
-isc_socket_gettype
-isc_socket_ipv6only
-isc_socket_isbound
-isc_socket_listen
-isc_socket_open
-isc_socket_permunix
-isc_socket_recv
-isc_socket_recv2
-isc_socket_recvv
-isc_socket_send
-isc_socket_sendto
-isc_socket_sendto2
-isc_socket_sendtov
-isc_socket_sendv
-isc_socket_setname
-isc_socketmgr_create
-isc_socketmgr_create2
-isc_socketmgr_destroy
-isc_socketmgr_getmaxsockets
-isc_socketmgr_setstats
-isc_stats_create
+isc_socketmgr_renderxml
 isc_stats_attach
-isc_stats_detach
-isc_stats_ncounters
-isc_stats_increment
+isc_stats_create
 isc_stats_decrement
+isc_stats_detach
 isc_stats_dump
+isc_stats_increment
+isc_stats_ncounters
 isc_stdio_close
 isc_stdio_flush
 isc_stdio_open
@@ -478,30 +534,13 @@ isc_symtab_destroy
 isc_symtab_lookup
 isc_symtab_undefine
 isc_syslog_facilityfromstring
-isc_task_attach
-isc_task_beginexclusive
-isc_task_create
-isc_task_destroy
-isc_task_detach
-isc_task_endexclusive
-isc_task_getcurrenttime
-isc_task_getname
-isc_task_gettag
-isc_task_onshutdown
-isc_task_purge
-isc_task_purgeevent
-isc_task_purgerange
-isc_task_send
-isc_task_sendanddetach
-isc_task_setname
-isc_task_shutdown
-isc_task_unsend
-isc_task_unsendrange
-isc_taskmgr_create
-isc_taskmgr_destroy
+isc_taskmgr_renderxml
 isc_taskpool_create
 isc_taskpool_destroy
+isc_taskpool_expand
 isc_taskpool_gettask
+isc_taskpool_setprivilege
+isc_taskpool_size
 isc_thread_create
 isc_thread_join
 isc_thread_key_create
@@ -511,6 +550,8 @@ isc_thread_key_setspecific
 isc_thread_setconcurrency
 isc_time_add
 isc_time_compare
+isc_time_formatISO8601
+isc_time_formattimestamp
 isc_time_isepoch
 isc_time_microdiff
 isc_time_nanoseconds
@@ -520,14 +561,6 @@ isc_time_seconds
 isc_time_set
 isc_time_settoepoch
 isc_time_subtract
-isc_timer_attach
-isc_timer_create
-isc_timer_detach
-isc_timer_reset
-isc_timer_touch
-isc_timermgr_create
-isc_timermgr_destroy
-isc_timermgr_poke
 isc_win32os_majorversion
 isc_win32os_minorversion
 isc_win32os_servicepackmajor
@@ -540,7 +573,6 @@ syslog
 
 EXPORTS
 
-isc_assertion_failed           DATA
 isc_commandline_argument       DATA
 isc_commandline_errprint       DATA
 isc_commandline_index          DATA
index c0ffb713cf489dbd15cda493e634a28035a9529f..8e4441c39fabe4235a92cd3cc477399411293d23 100644 (file)
@@ -42,8 +42,8 @@ RSC=rc.exe
 # PROP Intermediate_Dir "Release"
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "../noatomic/include" /I "win32" /I "../../isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /c
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "BIND9" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../../libxml2-2.7.3/include" /I "include" /I "../include" /I "../noatomic/include" /I "win32" /I "../../isccfg/include" /D "BIND9" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /c
 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
@@ -53,6 +53,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 ../../../../libxml2-2.7.3/win32/bin.msvc/libxml2.lib 
 # ADD LINK32 user32.lib advapi32.lib ws2_32.lib /nologo /dll /machine:I386 /out:"../../../Build/Release/libisc.dll"
 # SUBTRACT LINK32 /pdb:none
 
@@ -69,8 +70,8 @@ LINK32=link.exe
 # PROP Intermediate_Dir "Debug"
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "../noatomic/include" /I "win32" /I "../../isccfg/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR /YX /FD /GZ /c
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "BIND9" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../../libxml2-2.7.3/include" /I "include" /I "../include" /I "../noatomic/include" /I "win32" /I "../../isccfg/include" /D "BIND9" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR /YX /FD /GZ /c
 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
 # ADD BASE RSC /l 0x409 /d "_DEBUG"
@@ -80,6 +81,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ../../../../libxml2-2.7.3/win32/bin.msvc/libxml2.lib 
 # ADD LINK32 user32.lib advapi32.lib ws2_32.lib /nologo /dll /map /debug /machine:I386 /out:"../../../Build/Debug/libisc.dll" /pdbtype:sept
 
 !ENDIF 
@@ -205,6 +207,14 @@ SOURCE=..\include\isc\assertions.h
 # End Source File
 # Begin Source File
 
+SOURCE=..\include\isc\backtrace.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\backtrace-emptytbl.h
+# End Source File
+# Begin Source File
+
 SOURCE=..\include\isc\base32.h
 # End Source File
 # Begin Source File
@@ -577,6 +587,14 @@ SOURCE=..\assertions.c
 # End Source File
 # Begin Source File
 
+SOURCE=..\backtrace.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\backtrace-emptytbl.c
+# End Source File
+# Begin Source File
+
 SOURCE=..\base32.c
 # End Source File
 # Begin Source File
index 47d7b970726306d146002eeaf24975ec206f1983..e15b46b3f862368533d1c2dda6bfd414e89a9ea2 100644 (file)
@@ -28,6 +28,7 @@ NULL=nul
 CPP=cl.exe
 MTL=midl.exe
 RSC=rc.exe
+LIBXML=../../../../libxml2-2.7.3/win32/bin.msvc/libxml2.lib
 
 !IF  "$(CFG)" == "libisc - Win32 Release"
 _VC_MANIFEST_INC=0
@@ -115,6 +116,8 @@ ALL : "..\..\..\Build\Release\libisc.dll"
 CLEAN :
        -@erase "$(INTDIR)\app.obj"
        -@erase "$(INTDIR)\assertions.obj"
+       -@erase "$(INTDIR)\backtrace.obj"
+       -@erase "$(INTDIR)\backtrace-emptytbl.obj"
        -@erase "$(INTDIR)\base32.obj"
        -@erase "$(INTDIR)\base64.obj"
        -@erase "$(INTDIR)\bitstring.obj"
@@ -197,14 +200,14 @@ CLEAN :
 "$(OUTDIR)" :
     if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
 
-CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/noatomic/include" /I "win32" /I "../../isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /Fp"$(INTDIR)\libisc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/noatomic/include" /I "win32" /I "../../isccfg/include" /I "../../../../libxml2-2.7.3/include" /D "BIND9" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /Fp"$(INTDIR)\libisc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
 MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 
 BSC32=bscmake.exe
 BSC32_FLAGS=/nologo /o"$(OUTDIR)\libisc.bsc" 
 BSC32_SBRS= \
        
 LINK32=link.exe
-LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\libisc.pdb" /machine:I386 /def:".\libisc.def" /out:"../../../Build/Release/libisc.dll" /implib:"$(OUTDIR)\libisc.lib" 
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib $(LIBXML) /nologo /dll /incremental:no /pdb:"$(OUTDIR)\libisc.pdb" /machine:I386 /def:".\libisc.def" /out:"../../../Build/Release/libisc.dll" /implib:"$(OUTDIR)\libisc.lib" 
 DEF_FILE= \
        ".\libisc.def"
 LINK32_OBJS= \
@@ -235,6 +238,8 @@ LINK32_OBJS= \
        "$(INTDIR)\version.obj" \
        "$(INTDIR)\win32os.obj" \
        "$(INTDIR)\assertions.obj" \
+       "$(INTDIR)\backtrace.obj" \
+       "$(INTDIR)\backtrace-emptytbl.obj" \
        "$(INTDIR)\base32.obj" \
        "$(INTDIR)\base64.obj" \
        "$(INTDIR)\bitstring.obj" \
@@ -306,6 +311,10 @@ CLEAN :
        -@erase "$(INTDIR)\app.sbr"
        -@erase "$(INTDIR)\assertions.obj"
        -@erase "$(INTDIR)\assertions.sbr"
+       -@erase "$(INTDIR)\backtrace.obj"
+       -@erase "$(INTDIR)\backtrace-emptytbl.obj"
+       -@erase "$(INTDIR)\backtrace.sbr"
+       -@erase "$(INTDIR)\backtrace-emptytbl.sbr"
        -@erase "$(INTDIR)\base32.obj"
        -@erase "$(INTDIR)\base32.sbr"
        -@erase "$(INTDIR)\base64.obj"
@@ -466,7 +475,7 @@ CLEAN :
 "$(OUTDIR)" :
     if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
 
-CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/noatomic/include" /I "win32" /I "../../isccfg/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\libisc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/noatomic/include" /I "win32" /I "../../isccfg/include" /I "../../../../libxml2-2.7.3/include" /D "BIND9" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\libisc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
 MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 
 BSC32=bscmake.exe
 BSC32_FLAGS=/nologo /o"$(OUTDIR)\libisc.bsc" 
@@ -498,6 +507,8 @@ BSC32_SBRS= \
        "$(INTDIR)\version.sbr" \
        "$(INTDIR)\win32os.sbr" \
        "$(INTDIR)\assertions.sbr" \
+       "$(INTDIR)\backtrace.sbr" \
+       "$(INTDIR)\backtrace-emptytbl.sbr" \
        "$(INTDIR)\base32.sbr" \
        "$(INTDIR)\base64.sbr" \
        "$(INTDIR)\bitstring.sbr" \
@@ -553,7 +564,7 @@ BSC32_SBRS= \
 <<
 
 LINK32=link.exe
-LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\libisc.pdb" /map:"$(INTDIR)\libisc.map" /debug /machine:I386 /def:".\libisc.def" /out:"../../../Build/Debug/libisc.dll" /implib:"$(OUTDIR)\libisc.lib" /pdbtype:sept 
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib $(LIBXML) /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\libisc.pdb" /map:"$(INTDIR)\libisc.map" /debug /machine:I386 /def:".\libisc.def" /out:"../../../Build/Debug/libisc.dll" /implib:"$(OUTDIR)\libisc.lib" /pdbtype:sept 
 DEF_FILE= \
        ".\libisc.def"
 LINK32_OBJS= \
@@ -584,6 +595,8 @@ LINK32_OBJS= \
        "$(INTDIR)\version.obj" \
        "$(INTDIR)\win32os.obj" \
        "$(INTDIR)\assertions.obj" \
+       "$(INTDIR)\backtrace.obj" \
+       "$(INTDIR)\backtrace-emptytbl.obj" \
        "$(INTDIR)\base32.obj" \
        "$(INTDIR)\base64.obj" \
        "$(INTDIR)\bitstring.obj" \
@@ -1099,6 +1112,42 @@ SOURCE=..\assertions.c
        $(CPP) $(CPP_PROJ) $(SOURCE)
 
 
+!ENDIF 
+
+SOURCE=..\backtrace.c
+
+!IF  "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\backtrace.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\backtrace.obj"      "$(INTDIR)\backtrace.sbr" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF 
+
+SOURCE=..\backtrace-emptytbl.c
+
+!IF  "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\backtrace-emptytbl.obj" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF  "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\backtrace-emptytbl.obj"     "$(INTDIR)\backtrace-emptytbl.sbr" : $(SOURCE) "$(INTDIR)"
+       $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
 !ENDIF 
 
 SOURCE=..\base32.c
index 3785f8abdf1b08f68ea1ba86524f4bb1e8ff3121..06d09819e662811acdd31193771b616d1ac7d3c3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: net.c,v 1.18 2008/08/08 05:06:49 marka Exp $ */
+/* $Id$ */
 
 #include <config.h>
 
@@ -166,7 +166,8 @@ try_ipv6only(void) {
        }
 
        on = 1;
-       if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
+       if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&on,
+                      sizeof(on)) < 0) {
                ipv6only_result = ISC_R_NOTFOUND;
                goto close;
        }
@@ -189,7 +190,8 @@ try_ipv6only(void) {
        }
 
        on = 1;
-       if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
+       if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&on,
+                      sizeof(on)) < 0) {
                ipv6only_result = ISC_R_NOTFOUND;
                goto close;
        }
@@ -197,7 +199,7 @@ try_ipv6only(void) {
        ipv6only_result = ISC_R_SUCCESS;
 
 close:
-       closeocket(s);
+       closesocket(s);
        return;
 #endif /* IPV6_V6ONLY */
 }
index fa941800484f2429510a16b2c4d58fc31ea7ee1a..f8d936a99f35d01a9b069a0885f66d783d77aa8a 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: netdb.h,v 1.7.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id: netdb.h,v 1.9 2009/01/18 23:48:14 tbox Exp $ */
 
 #ifndef NETDB_H
 #define NETDB_H 1
index 351adc5e74b92d84d80c396bb0fa5a8b1a087a67..729cf07e74f0e026226374c9620ccd95f1632ba1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2006, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2006, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: ntgroups.c,v 1.10 2007/06/19 23:47:19 tbox Exp $ */
+/* $Id: ntgroups.c,v 1.12 2009/09/29 23:48:04 tbox Exp $ */
 
 /*
  * The NT Groups have two groups that are not well documented and are
@@ -63,28 +63,28 @@ isc_ntsecurity_getaccountgroups(char *username, char **GroupList,
        DWORD dwTotalEntries = 0;
        NET_API_STATUS nStatus;
        DWORD dwTotalCount = 0;
-       int retlen;
+       size_t retlen;
        wchar_t user[MAX_NAME_LENGTH];
 
        retlen = mbstowcs(user, username, MAX_NAME_LENGTH);
 
        *totalGroups = 0;
        /*
-        * Call the NetUserGetLocalGroups function 
+        * Call the NetUserGetLocalGroups function
         * specifying information level 0.
         *
-        * The LG_INCLUDE_INDIRECT flag specifies that the 
-        * function should also return the names of the local 
+        * The LG_INCLUDE_INDIRECT flag specifies that the
+        * function should also return the names of the local
         * groups in which the user is indirectly a member.
         */
        nStatus = NetUserGetLocalGroups(NULL,
-                                   user,
-                                   dwLevel,
-                                   dwFlags,
-                                   (LPBYTE *) &pBuf,
-                                   dwPrefMaxLen,
-                                   &dwEntriesRead,
-                                   &dwTotalEntries);
+                                  user,
+                                  dwLevel,
+                                  dwFlags,
+                                  (LPBYTE *) &pBuf,
+                                  dwPrefMaxLen,
+                                  &dwEntriesRead,
+                                  &dwTotalEntries);
        /*
         * See if the call succeeds,
         */
@@ -103,7 +103,7 @@ isc_ntsecurity_getaccountgroups(char *username, char **GroupList,
                /*
                 * Loop through the entries
                 */
-                for (i = 0;
+                for (i = 0;
                     (i < dwEntriesRead && *totalGroups < maxgroups); i++) {
                        assert(pTmpLBuf != NULL);
                        if (pTmpLBuf == NULL)
@@ -127,17 +127,17 @@ isc_ntsecurity_getaccountgroups(char *username, char **GroupList,
        if (pBuf != NULL)
                NetApiBufferFree(pBuf);
 
-   
+
        /*
         * Call the NetUserGetGroups function, specifying level 0.
         */
        nStatus = NetUserGetGroups(NULL,
-                              user,
-                              dwLevel,
-                              (LPBYTE*)&pgrpBuf,
-                              dwPrefMaxLen,
-                              &dwEntriesRead,
-                              &dwTotalEntries);
+                             user,
+                             dwLevel,
+                             (LPBYTE*)&pgrpBuf,
+                             dwPrefMaxLen,
+                             &dwEntriesRead,
+                             &dwTotalEntries);
        /*
         * See if the call succeeds,
         */
@@ -149,13 +149,13 @@ isc_ntsecurity_getaccountgroups(char *username, char **GroupList,
                if (nStatus == NERR_UserNotFound)
                        dwEntriesRead = 0;
        }
+
        if (pgrpBuf != NULL) {
                pTmpBuf = pgrpBuf;
                /*
                 * Loop through the entries
                 */
-                for (i = 0;
+                for (i = 0;
                     (i < dwEntriesRead && *totalGroups < maxgroups); i++) {
                        assert(pTmpBuf != NULL);
 
index d1c622fa957416ef0aa9842ec35670a6645d7a98..1ff8c5a9b5c3e5bc637f72da614872e9d453fae1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007, 2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: ntpaths.c,v 1.11 2007/06/18 23:47:49 tbox Exp $ */
+/* $Id: ntpaths.c,v 1.15 2009/07/14 22:54:57 each Exp $ */
 
 /*
  * This module fetches the required path information that is specific
@@ -44,6 +44,7 @@ static char lwresd_defaultpidfile[MAX_PATH];
 static char local_state_dir[MAX_PATH];
 static char sys_conf_dir[MAX_PATH];
 static char rndc_keyFile[MAX_PATH];
+static char session_keyFile[MAX_PATH];
 
 static DWORD baseLen = MAX_PATH;
 static BOOL Initialized = FALSE;
@@ -57,7 +58,7 @@ isc_ntpaths_init() {
        if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, BIND_SUBKEY, 0, KEY_READ, &hKey)
                != ERROR_SUCCESS)
                keyFound = FALSE;
-       
+
        if (keyFound == TRUE) {
                /* Get the named directory */
                if (RegQueryValueEx(hKey, "InstallDir", NULL, NULL,
@@ -84,6 +85,9 @@ isc_ntpaths_init() {
        strcpy(rndc_keyFile, namedBase);
        strcat(rndc_keyFile, "\\etc\\rndc.key");
 
+       strcpy(session_keyFile, namedBase);
+       strcat(session_keyFile, "\\etc\\session.key");
+
        strcpy(rndc_confFile, namedBase);
        strcat(rndc_confFile, "\\etc\\rndc.conf");
        strcpy(ns_defaultpidfile, namedBase);
@@ -97,7 +101,7 @@ isc_ntpaths_init() {
 
        strcpy(sys_conf_dir, namedBase);
        strcat(sys_conf_dir, "\\etc");
-       
+
        Initialized = TRUE;
 }
 
@@ -134,6 +138,9 @@ isc_ntpaths_get(int ind) {
        case RNDC_KEY_PATH:
                return (rndc_keyFile);
                break;
+       case SESSION_KEY_PATH:
+               return (session_keyFile);
+               break;
        default:
                return (NULL);
        }
index 7c4068fbdc2bb867edf9e028a69992e46964272e..ffcefb0606c83ad797dd0f9b9da3879c4a86d953 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2009  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: socket.c,v 1.70.54.4 2009/01/29 22:40:36 jinmei Exp $ */
+/* $Id$ */
 
 /* This code uses functions which are only available on Server 2003 and
  * higher, and Windows XP and higher.
@@ -265,7 +265,8 @@ struct isc_socket {
        unsigned int            listener : 1,   /* listener socket */
                                connected : 1,
                                pending_connect : 1, /* connect pending */
-                               bound : 1;      /* bound to local addr */
+                               bound : 1,      /* bound to local addr */
+                               dupped : 1;     /* created by isc_socket_dup() */
        unsigned int            pending_iocp;   /* Should equal the counters below. Debug. */
        unsigned int            pending_recv;  /* Number of outstanding recv() calls. */
        unsigned int            pending_send;  /* Number of outstanding send() calls. */
@@ -351,6 +352,10 @@ enum {
 #define MAXSCATTERGATHER_SEND  (ISC_SOCKET_MAXSCATTERGATHER)
 #define MAXSCATTERGATHER_RECV  (ISC_SOCKET_MAXSCATTERGATHER)
 
+static isc_result_t socket_create(isc_socketmgr_t *manager0, int pf,
+                                 isc_sockettype_t type,
+                                 isc_socket_t **socketp,
+                                 isc_socket_t *dup_socket);
 static isc_threadresult_t WINAPI SocketIoThread(LPVOID ThreadContext);
 static void maybe_free_socket(isc_socket_t **, int);
 static void free_socket(isc_socket_t **, int);
@@ -716,21 +721,31 @@ queue_receive_request(isc_socket_t *sock) {
        int total_bytes = 0;
        int Result;
        int Error;
+       int need_retry;
        WSABUF iov[1];
-       IoCompletionInfo *lpo;
+       IoCompletionInfo *lpo = NULL;
        isc_result_t isc_result;
 
+ retry:
+       need_retry = ISC_FALSE;
+
        /*
         * If we already have a receive pending, do nothing.
         */
-       if (sock->pending_recv > 0)
+       if (sock->pending_recv > 0) {
+               if (lpo != NULL)
+                       HeapFree(hHeapHandle, 0, lpo);
                return;
+       }
 
        /*
         * If no one is waiting, do nothing.
         */
-       if (ISC_LIST_EMPTY(sock->recv_list))
+       if (ISC_LIST_EMPTY(sock->recv_list)) {
+               if (lpo != NULL)
+                       HeapFree(hHeapHandle, 0, lpo);
                return;
+       }
 
        INSIST(sock->recvbuf.remaining == 0);
        INSIST(sock->fd != INVALID_SOCKET);
@@ -738,10 +753,13 @@ queue_receive_request(isc_socket_t *sock) {
        iov[0].len = sock->recvbuf.len;
        iov[0].buf = sock->recvbuf.base;
 
-       lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
-                                           HEAP_ZERO_MEMORY,
-                                           sizeof(IoCompletionInfo));
-       RUNTIME_CHECK(lpo != NULL);
+       if (lpo == NULL) {
+               lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
+                                                   HEAP_ZERO_MEMORY,
+                                                   sizeof(IoCompletionInfo));
+               RUNTIME_CHECK(lpo != NULL);
+       } else
+               ZeroMemory(lpo, sizeof(IoCompletionInfo));
        lpo->request_type = SOCKET_RECV;
 
        sock->recvbuf.from_addr_len = sizeof(sock->recvbuf.from_addr);
@@ -763,6 +781,17 @@ queue_receive_request(isc_socket_t *sock) {
                        sock->pending_recv++;
                        break;
 
+               /* direct error: no completion event */
+               case ERROR_HOST_UNREACHABLE:
+               case WSAENETRESET:
+               case WSAECONNRESET:
+                       if (!sock->connected) {
+                               /* soft error */
+                               need_retry = ISC_TRUE;
+                               break;
+                       }
+                       /* FALLTHROUGH */
+
                default:
                        isc_result = isc__errno2result(Error);
                        if (isc_result == ISC_R_UNEXPECTED)
@@ -770,6 +799,8 @@ queue_receive_request(isc_socket_t *sock) {
                                        "WSARecvFrom: Windows error code: %d, isc result %d",
                                        Error, isc_result);
                        send_recvdone_abort(sock, isc_result);
+                       HeapFree(hHeapHandle, 0, lpo);
+                       lpo = NULL;
                        break;
                }
        } else {
@@ -789,6 +820,9 @@ queue_receive_request(isc_socket_t *sock) {
                   sock->fd, Result, Error);
 
        CONSISTENT(sock);
+
+       if (need_retry)
+               goto retry;
 }
 
 static void
@@ -866,7 +900,7 @@ make_nonblock(SOCKET fd) {
 }
 
 /*
- * Windows 2000 systems incorrectly cause UDP sockets using WASRecvFrom
+ * Windows 2000 systems incorrectly cause UDP sockets using WSARecvFrom
  * to not work correctly, returning a WSACONNRESET error when a WSASendTo
  * fails with an "ICMP port unreachable" response and preventing the
  * socket from using the WSARecvFrom in subsequent operations.
@@ -1318,7 +1352,7 @@ completeio_send(isc_socket_t *sock, isc_socketevent_t *dev,
                UNEXPECTED_ERROR(__FILE__, __LINE__, "completeio_send: %s: %s",
                                 addrbuf, strbuf);
                dev->result = isc__errno2result(send_errno);
-       return (DOIO_HARD);
+               return (DOIO_HARD);
        }
 
        /*
@@ -1387,6 +1421,7 @@ startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes,
                                   "bytes, err %d/%s",
                                   sock->fd, *nbytes, *send_errno, strbuf);
                }
+               status = DOIO_HARD;
                goto done;
        }
        dev->result = ISC_R_SUCCESS;
@@ -1431,6 +1466,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
        sock->connected = 0;
        sock->pending_connect = 0;
        sock->bound = 0;
+       sock->dupped = 0;
        memset(sock->name, 0, sizeof(sock->name));      // zero the name field
        _set_state(sock, SOCK_INITIALIZED);
 
@@ -1593,9 +1629,10 @@ free_socket(isc_socket_t **sockp, int lineno) {
  * called with 'arg' as the arg value.  The new socket is returned
  * in 'socketp'.
  */
-isc_result_t
-isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
-                 isc_socket_t **socketp) {
+static isc_result_t
+socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+             isc_socket_t **socketp, isc_socket_t *dup_socket)
+{
        isc_socket_t *sock = NULL;
        isc_result_t result;
 #if defined(USE_CMSG)
@@ -1612,33 +1649,54 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
        REQUIRE(socketp != NULL && *socketp == NULL);
        REQUIRE(type != isc_sockettype_fdwatch);
 
+       if (dup_socket != NULL)
+               return (ISC_R_NOTIMPLEMENTED);
+
        result = allocate_socket(manager, type, &sock);
        if (result != ISC_R_SUCCESS)
                return (result);
 
        sock->pf = pf;
-       switch (type) {
-       case isc_sockettype_udp:
-               sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
-               if (sock->fd != INVALID_SOCKET) {
-                       result = connection_reset_fix(sock->fd);
-                       if (result != ISC_R_SUCCESS) {
-                               socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
-                                       "closed %d %d %d con_reset_fix_failed",
-                                       sock->pending_recv, sock->pending_send,
-                                       sock->references);
-                               closesocket(sock->fd);
-                               _set_state(sock, SOCK_CLOSED);
-                               sock->fd = INVALID_SOCKET;
-                               free_socket(&sock, __LINE__);
-                               return (result);
+#if 0
+       if (dup_socket == NULL) {
+#endif
+               switch (type) {
+               case isc_sockettype_udp:
+                       sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
+                       if (sock->fd != INVALID_SOCKET) {
+                               result = connection_reset_fix(sock->fd);
+                               if (result != ISC_R_SUCCESS) {
+                                       socket_log(__LINE__, sock,
+                                               NULL, EVENT, NULL, 0, 0,
+                                               "closed %d %d %d "
+                                               "con_reset_fix_failed",
+                                               sock->pending_recv,
+                                               sock->pending_send,
+                                               sock->references);
+                                       closesocket(sock->fd);
+                                       _set_state(sock, SOCK_CLOSED);
+                                       sock->fd = INVALID_SOCKET;
+                                       free_socket(&sock, __LINE__);
+                                       return (result);
+                               }
                        }
+                       break;
+               case isc_sockettype_tcp:
+                       sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
+                       break;
                }
-               break;
-       case isc_sockettype_tcp:
-               sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
-               break;
+#if 0
+       } else {
+               /*
+                * XXX: dup() is deprecated in windows, use _dup()
+                * instead.  In future we may want to investigate
+                * WSADuplicateSocket().
+                */
+               sock->fd = _dup(dup_socket->fd);
+               sock->dupped = 1;
+               sock->bound = dup_socket->bound;
        }
+#endif
 
        if (sock->fd == INVALID_SOCKET) {
                socket_errno = WSAGetLastError();
@@ -1689,7 +1747,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
                /* 2292bis */
                if ((pf == AF_INET6)
                    && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
-                                  (void *)&on, sizeof(on)) < 0)) {
+                                  (char *)&on, sizeof(on)) < 0)) {
                        isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
                        UNEXPECTED_ERROR(__FILE__, __LINE__,
                                         "setsockopt(%d, IPV6_RECVPKTINFO) "
@@ -1704,7 +1762,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
                /* 2292 */
                if ((pf == AF_INET6)
                    && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO,
-                                  (void *)&on, sizeof(on)) < 0)) {
+                                  (char *)&on, sizeof(on)) < 0)) {
                        isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
                        UNEXPECTED_ERROR(__FILE__, __LINE__,
                                         "setsockopt(%d, IPV6_PKTINFO) %s: %s",
@@ -1721,7 +1779,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
                if (pf == AF_INET6) {
                        (void)setsockopt(sock->fd, IPPROTO_IPV6,
                                         IPV6_USE_MIN_MTU,
-                                        (void *)&on, sizeof(on));
+                                        (char *)&on, sizeof(on));
                }
 #endif
 #endif /* ISC_PLATFORM_HAVEIPV6 */
@@ -1730,11 +1788,11 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
 #if defined(SO_RCVBUF)
               optlen = sizeof(size);
               if (getsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
-                             (void *)&size, &optlen) >= 0 &&
+                             (char *)&size, &optlen) >= 0 &&
                    size < RCVBUFSIZE) {
                       size = RCVBUFSIZE;
                       (void)setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
-                                       (void *)&size, sizeof(size));
+                                       (char *)&size, sizeof(size));
               }
 #endif
 
@@ -1756,12 +1814,33 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
        InterlockedIncrement(&manager->totalSockets);
        UNLOCK(&manager->lock);
 
-       socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
-                  ISC_MSG_CREATED, "created %u type %u", sock->fd, type);
+       socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat,
+                  ISC_MSGSET_SOCKET, ISC_MSG_CREATED,
+                  "created %u type %u", sock->fd, type);
 
        return (ISC_R_SUCCESS);
 }
 
+isc_result_t
+isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+                  isc_socket_t **socketp)
+{
+       return (socket_create(manager, pf, type, socketp, NULL));
+}
+
+isc_result_t
+isc__socket_dup(isc_socket_t *sock, isc_socket_t **socketp) {
+       REQUIRE(VALID_SOCKET(sock));
+       REQUIRE(socketp != NULL && *socketp == NULL);
+
+#if 1
+       return (ISC_R_NOTIMPLEMENTED);
+#else
+       return (socket_create(sock->manager, sock->pf, sock->type,
+                             socketp, sock));
+#endif
+}
+
 isc_result_t
 isc_socket_open(isc_socket_t *sock) {
        REQUIRE(VALID_SOCKET(sock));
@@ -1774,7 +1853,7 @@ isc_socket_open(isc_socket_t *sock) {
  * Attach to a socket.  Caller must explicitly detach when it is done.
  */
 void
-isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
+isc__socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
        REQUIRE(VALID_SOCKET(sock));
        REQUIRE(socketp != NULL && *socketp == NULL);
 
@@ -1791,7 +1870,7 @@ isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
  * up by destroying the socket.
  */
 void
-isc_socket_detach(isc_socket_t **socketp) {
+isc__socket_detach(isc_socket_t **socketp) {
        isc_socket_t *sock;
        isc_boolean_t kill_socket = ISC_FALSE;
 
@@ -1990,7 +2069,7 @@ internal_accept(isc_socket_t *sock, IoCompletionInfo *lpo, int accept_errno) {
        INSIST(result == ISC_R_SUCCESS);
 
        INSIST(setsockopt(nsock->fd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
-              (char *)&sock->fd, sizeof(sock->fd)) == 0);
+                         (char *)&sock->fd, sizeof(sock->fd)) == 0);
 
        /*
         * Hook it up into the manager.
@@ -2096,7 +2175,8 @@ internal_connect(isc_socket_t *sock, IoCompletionInfo *lpo, int connect_errno) {
                                         strbuf);
                }
        } else {
-               INSIST(setsockopt(sock->fd, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0) == 0);
+               INSIST(setsockopt(sock->fd, SOL_SOCKET,
+                                 SO_UPDATE_CONNECT_CONTEXT, NULL, 0) == 0);
                cdev->result = ISC_R_SUCCESS;
                sock->connected = 1;
                socket_log(__LINE__, sock, &sock->address, IOEVENT,
@@ -2273,6 +2353,63 @@ connectdone_is_active(isc_socket_t *sock, isc_socket_connev_t *dev)
        return (sock->connect_ev == dev ? ISC_TRUE : ISC_FALSE);
 }
 
+//
+// The Windows network stack seems to have two very distinct paths depending
+// on what is installed.  Specifically, if something is looking at network
+// connections (like an anti-virus or anti-malware application, such as
+// McAfee products) Windows may return additional error conditions which
+// were not previously returned.
+//
+// One specific one is when a TCP SYN scan is used.  In this situation,
+// Windows responds with the SYN-ACK, but the scanner never responds with
+// the 3rd packet, the ACK.  Windows consiers this a partially open connection.
+// Most Unix networking stacks, and Windows without McAfee installed, will
+// not return this to the caller.  However, with this product installed,
+// Windows returns this as a failed status on the Accept() call.  Here, we
+// will just re-issue the ISCAcceptEx() call as if nothing had happened.
+//
+// This code should only be called when the listening socket has received
+// such an error.  Additionally, the "parent" socket must be locked.
+// Additionally, the lpo argument is re-used here, and must not be freed
+// by the caller.
+//
+static isc_result_t
+restart_accept(isc_socket_t *parent, IoCompletionInfo *lpo)
+{
+       isc_socket_t *nsock = lpo->adev->newsocket;
+       SOCKET new_fd;
+
+       /*
+        * AcceptEx() requires we pass in a socket.  Note that we carefully
+        * do not close the previous socket in case of an error message returned by
+        * our new socket() call.  If we return an error here, our caller will
+        * clean up.
+        */
+       new_fd = socket(parent->pf, SOCK_STREAM, IPPROTO_TCP);
+       if (nsock->fd == INVALID_SOCKET) {
+               return (ISC_R_FAILURE); // parent will ask windows for error message
+       }
+       closesocket(nsock->fd);
+       nsock->fd = new_fd;
+
+       memset(&lpo->overlapped, 0, sizeof(lpo->overlapped));
+
+       ISCAcceptEx(parent->fd,
+                   nsock->fd,                          /* Accepted Socket */
+                   lpo->acceptbuffer,                  /* Buffer for initial Recv */
+                   0,                                  /* Length of Buffer */
+                   sizeof(SOCKADDR_STORAGE) + 16,      /* Local address length + 16 */
+                   sizeof(SOCKADDR_STORAGE) + 16,      /* Remote address lengh + 16 */
+                   (LPDWORD)&lpo->received_bytes,      /* Bytes Recved */
+                   (LPOVERLAPPED)lpo                   /* Overlapped structure */
+                   );
+
+       InterlockedDecrement(&nsock->manager->iocp_total);
+       iocompletionport_update(nsock);
+
+       return (ISC_R_SUCCESS);
+}
+
 /*
  * This is the I/O Completion Port Worker Function. It loops forever
  * waiting for I/O to complete and then forwards them for further
@@ -2313,6 +2450,7 @@ SocketIoThread(LPVOID ThreadContext) {
         * Loop forever waiting on I/O Completions and then processing them
         */
        while (TRUE) {
+               wait_again:
                bSuccess = GetQueuedCompletionStatus(manager->hIoCompletionPort,
                                                     &nbytes, (LPDWORD)&sock,
                                                     (LPWSAOVERLAPPED *)&lpo,
@@ -2331,7 +2469,7 @@ SocketIoThread(LPVOID ThreadContext) {
                        /*
                         * Did the I/O operation complete?
                         */
-                       errstatus = WSAGetLastError();
+                       errstatus = GetLastError();
                        isc_result = isc__errno2resultx(errstatus, __FILE__, __LINE__);
 
                        LOCK(&sock->lock);
@@ -2342,6 +2480,14 @@ SocketIoThread(LPVOID ThreadContext) {
                                sock->pending_iocp--;
                                INSIST(sock->pending_recv > 0);
                                sock->pending_recv--;
+                               if (!sock->connected &&
+                                   ((errstatus == ERROR_HOST_UNREACHABLE) ||
+                                    (errstatus == WSAENETRESET) ||
+                                    (errstatus == WSAECONNRESET))) {
+                                       /* ignore soft errors */
+                                       queue_receive_request(sock);
+                                       break;
+                               }
                                send_recvdone_abort(sock, isc_result);
                                if (isc_result == ISC_R_UNEXPECTED) {
                                        UNEXPECTED_ERROR(__FILE__, __LINE__,
@@ -2365,8 +2511,25 @@ SocketIoThread(LPVOID ThreadContext) {
 
                        case SOCKET_ACCEPT:
                                INSIST(sock->pending_iocp > 0);
-                               sock->pending_iocp--;
                                INSIST(sock->pending_accept > 0);
+
+                               socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+                                       "Accept: errstatus=%d isc_result=%d", errstatus, isc_result);
+
+                               if (acceptdone_is_active(sock, lpo->adev)) {
+                                       if (restart_accept(sock, lpo) == ISC_R_SUCCESS) {
+                                               UNLOCK(&sock->lock);
+                                               goto wait_again;
+                                       } else {
+                                               errstatus = GetLastError();
+                                               isc_result = isc__errno2resultx(errstatus, __FILE__, __LINE__);
+                                               socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+                                                       "restart_accept() failed: errstatus=%d isc_result=%d",
+                                                       errstatus, isc_result);
+                                       }
+                               }
+
+                               sock->pending_iocp--;
                                sock->pending_accept--;
                                if (acceptdone_is_active(sock, lpo->adev)) {
                                        closesocket(lpo->adev->newsocket->fd);
@@ -2434,13 +2597,13 @@ SocketIoThread(LPVOID ThreadContext) {
  * Create a new socket manager.
  */
 isc_result_t
-isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
+isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
        return (isc_socketmgr_create2(mctx, managerp, 0));
 }
 
 isc_result_t
-isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
-                    unsigned int maxsocks)
+isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
+                      unsigned int maxsocks)
 {
        isc_socketmgr_t *manager;
        isc_result_t result;
@@ -2489,7 +2652,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
 }
 
 isc_result_t
-isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) {
+isc__socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) {
        REQUIRE(VALID_MANAGER(manager));
        REQUIRE(nsockp != NULL);
 
@@ -2497,7 +2660,7 @@ isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) {
 }
 
 void
-isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) {
+isc__socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) {
        REQUIRE(VALID_MANAGER(manager));
        REQUIRE(ISC_LIST_EMPTY(manager->socklist));
        REQUIRE(manager->stats == NULL);
@@ -2507,7 +2670,7 @@ isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) {
 }
 
 void
-isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
+isc__socketmgr_destroy(isc_socketmgr_t **managerp) {
        isc_socketmgr_t *manager;
        int i;
        isc_mem_t *mctx;
@@ -2635,7 +2798,7 @@ socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
 }
 
 isc_result_t
-isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+isc__socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
                 unsigned int minimum, isc_task_t *task,
                 isc_taskaction_t action, const void *arg)
 {
@@ -2705,8 +2868,9 @@ isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
 }
 
 isc_result_t
-isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
-               isc_task_t *task, isc_taskaction_t action, const void *arg)
+isc__socket_recv(isc_socket_t *sock, isc_region_t *region,
+                unsigned int minimum, isc_task_t *task,
+                isc_taskaction_t action, const void *arg)
 {
        isc_socketevent_t *dev;
        isc_socketmgr_t *manager;
@@ -2742,9 +2906,9 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
 }
 
 isc_result_t
-isc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
-                unsigned int minimum, isc_task_t *task,
-                isc_socketevent_t *event, unsigned int flags)
+isc__socket_recv2(isc_socket_t *sock, isc_region_t *region,
+                 unsigned int minimum, isc_task_t *task,
+                 isc_socketevent_t *event, unsigned int flags)
 {
        isc_result_t ret;
 
@@ -2852,8 +3016,8 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
 }
 
 isc_result_t
-isc_socket_send(isc_socket_t *sock, isc_region_t *region,
-               isc_task_t *task, isc_taskaction_t action, const void *arg)
+isc__socket_send(isc_socket_t *sock, isc_region_t *region,
+                isc_task_t *task, isc_taskaction_t action, const void *arg)
 {
        /*
         * REQUIRE() checking is performed in isc_socket_sendto().
@@ -2863,9 +3027,9 @@ isc_socket_send(isc_socket_t *sock, isc_region_t *region,
 }
 
 isc_result_t
-isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
-                 isc_task_t *task, isc_taskaction_t action, const void *arg,
-                 isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+isc__socket_sendto(isc_socket_t *sock, isc_region_t *region,
+                  isc_task_t *task, isc_taskaction_t action, const void *arg,
+                  isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
 {
        isc_socketevent_t *dev;
        isc_socketmgr_t *manager;
@@ -2906,17 +3070,17 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
 }
 
 isc_result_t
-isc_socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
-                isc_task_t *task, isc_taskaction_t action, const void *arg)
+isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+                 isc_task_t *task, isc_taskaction_t action, const void *arg)
 {
        return (isc_socket_sendtov(sock, buflist, task, action, arg, NULL,
                                   NULL));
 }
 
 isc_result_t
-isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
-                  isc_task_t *task, isc_taskaction_t action, const void *arg,
-                  isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+isc__socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
+                   isc_task_t *task, isc_taskaction_t action, const void *arg,
+                   isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
 {
        isc_socketevent_t *dev;
        isc_socketmgr_t *manager;
@@ -2969,10 +3133,10 @@ isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
 }
 
 isc_result_t
-isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
-                  isc_task_t *task,
-                  isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
-                  isc_socketevent_t *event, unsigned int flags)
+isc__socket_sendto2(isc_socket_t *sock, isc_region_t *region,
+                   isc_task_t *task,
+                   isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+                   isc_socketevent_t *event, unsigned int flags)
 {
        isc_result_t ret;
 
@@ -3004,8 +3168,8 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
 }
 
 isc_result_t
-isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
-               unsigned int options) {
+isc__socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+                unsigned int options) {
        int bind_errno;
        char strbuf[ISC_STRERRORSIZE];
        int on = 1;
@@ -3023,6 +3187,7 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
        }
 
        INSIST(!sock->bound);
+       INSIST(!sock->dupped);
 
        if (sock->pf != sockaddr->type.sa.sa_family) {
                UNLOCK(&sock->lock);
@@ -3033,7 +3198,7 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
         */
        if ((options & ISC_SOCKET_REUSEADDRESS) != 0 &&
            isc_sockaddr_getport(sockaddr) != (in_port_t)0 &&
-           setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
+           setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
                       sizeof(on)) < 0) {
                UNEXPECTED_ERROR(__FILE__, __LINE__,
                                 "setsockopt(%d) %s", sock->fd,
@@ -3070,7 +3235,7 @@ isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
 }
 
 isc_result_t
-isc_socket_filter(isc_socket_t *sock, const char *filter) {
+isc__socket_filter(isc_socket_t *sock, const char *filter) {
        UNUSED(sock);
        UNUSED(filter);
 
@@ -3089,7 +3254,7 @@ isc_socket_filter(isc_socket_t *sock, const char *filter) {
  * as well keep things simple rather than having to track them.
  */
 isc_result_t
-isc_socket_listen(isc_socket_t *sock, unsigned int backlog) {
+isc__socket_listen(isc_socket_t *sock, unsigned int backlog) {
        char strbuf[ISC_STRERRORSIZE];
 
        REQUIRE(VALID_SOCKET(sock));
@@ -3134,8 +3299,8 @@ isc_socket_listen(isc_socket_t *sock, unsigned int backlog) {
  * This should try to do aggressive accept() XXXMLG
  */
 isc_result_t
-isc_socket_accept(isc_socket_t *sock,
-                 isc_task_t *task, isc_taskaction_t action, const void *arg)
+isc__socket_accept(isc_socket_t *sock,
+                  isc_task_t *task, isc_taskaction_t action, const void *arg)
 {
        isc_socket_newconnev_t *adev;
        isc_socketmgr_t *manager;
@@ -3198,6 +3363,13 @@ isc_socket_accept(isc_socket_t *sock,
         * Attach to socket and to task.
         */
        isc_task_attach(task, &ntask);
+       if (isc_task_exiting(ntask)) {
+               free_socket(&nsock, __LINE__);
+               isc_task_detach(&ntask);
+               isc_event_free(ISC_EVENT_PTR(&adev));
+               UNLOCK(&sock->lock);
+               return (ISC_R_SHUTTINGDOWN);
+       }
        nsock->references++;
 
        adev->ev_sender = ntask;
@@ -3245,8 +3417,8 @@ isc_socket_accept(isc_socket_t *sock,
 }
 
 isc_result_t
-isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
-                  isc_task_t *task, isc_taskaction_t action, const void *arg)
+isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
+                   isc_task_t *task, isc_taskaction_t action, const void *arg)
 {
        char strbuf[ISC_STRERRORSIZE];
        isc_socket_connev_t *cdev;
@@ -3360,7 +3532,7 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
 }
 
 isc_result_t
-isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+isc__socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) {
        isc_result_t result;
 
        REQUIRE(VALID_SOCKET(sock));
@@ -3390,7 +3562,7 @@ isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) {
 }
 
 isc_result_t
-isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+isc__socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
        ISC_SOCKADDR_LEN_T len;
        isc_result_t result;
        char strbuf[ISC_STRERRORSIZE];
@@ -3437,7 +3609,7 @@ isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
  * queued for task "task" of type "how".  "how" is a bitmask.
  */
 void
-isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
+isc__socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
 
        REQUIRE(VALID_SOCKET(sock));
 
@@ -3563,7 +3735,7 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
 }
 
 isc_sockettype_t
-isc_socket_gettype(isc_socket_t *sock) {
+isc__socket_gettype(isc_socket_t *sock) {
        isc_sockettype_t type;
 
        REQUIRE(VALID_SOCKET(sock));
@@ -3584,7 +3756,7 @@ isc_socket_gettype(isc_socket_t *sock) {
 }
 
 isc_boolean_t
-isc_socket_isbound(isc_socket_t *sock) {
+isc__socket_isbound(isc_socket_t *sock) {
        isc_boolean_t val;
 
        REQUIRE(VALID_SOCKET(sock));
@@ -3607,7 +3779,7 @@ isc_socket_isbound(isc_socket_t *sock) {
 }
 
 void
-isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
+isc__socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
 #if defined(IPV6_V6ONLY)
        int onoff = yes ? 1 : 0;
 #else
@@ -3619,20 +3791,20 @@ isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
 #ifdef IPV6_V6ONLY
        if (sock->pf == AF_INET6) {
                (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY,
-                                (void *)&onoff, sizeof(onoff));
+                                (char *)&onoff, sizeof(onoff));
        }
 #endif
 }
 
 void
-isc_socket_cleanunix(isc_sockaddr_t *addr, isc_boolean_t active) {
+isc__socket_cleanunix(isc_sockaddr_t *addr, isc_boolean_t active) {
        UNUSED(addr);
        UNUSED(active);
 }
 
 isc_result_t
-isc_socket_permunix(isc_sockaddr_t *addr, isc_uint32_t perm,
-                   isc_uint32_t owner, isc_uint32_t group)
+isc__socket_permunix(isc_sockaddr_t *addr, isc_uint32_t perm,
+                    isc_uint32_t owner,        isc_uint32_t group)
 {
        UNUSED(addr);
        UNUSED(perm);
@@ -3642,7 +3814,7 @@ isc_socket_permunix(isc_sockaddr_t *addr, isc_uint32_t perm,
 }
 
 void
-isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) {
+isc__socket_setname(isc_socket_t *socket, const char *name, void *tag) {
 
        /*
         * Name 'socket'.
@@ -3658,17 +3830,138 @@ isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) {
 }
 
 const char *
-isc_socket_getname(isc_socket_t *socket) {
+isc__socket_getname(isc_socket_t *socket) {
        return (socket->name);
 }
 
 void *
-isc_socket_gettag(isc_socket_t *socket) {
+isc__socket_gettag(isc_socket_t *socket) {
        return (socket->tag);
 }
 
+int
+isc__socket_getfd(isc_socket_t *socket) {
+       return ((short) socket->fd);
+}
+
 void
 isc__socketmgr_setreserved(isc_socketmgr_t *manager, isc_uint32_t reserved) {
        UNUSED(manager);
        UNUSED(reserved);
 }
+
+void
+isc___socketmgr_maxudp(isc_socketmgr_t *manager, int maxudp) {
+
+       UNUSED(manager);
+       UNUSED(maxudp);
+}
+
+#ifdef HAVE_LIBXML2
+
+static const char *
+_socktype(isc_sockettype_t type)
+{
+       if (type == isc_sockettype_udp)
+               return ("udp");
+       else if (type == isc_sockettype_tcp)
+               return ("tcp");
+       else if (type == isc_sockettype_unix)
+               return ("unix");
+       else if (type == isc_sockettype_fdwatch)
+               return ("fdwatch");
+       else
+               return ("not-initialized");
+}
+
+void
+isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer)
+{
+       isc_socket_t *sock;
+       char peerbuf[ISC_SOCKADDR_FORMATSIZE];
+       isc_sockaddr_t addr;
+       ISC_SOCKADDR_LEN_T len;
+
+       LOCK(&mgr->lock);
+
+#ifndef ISC_PLATFORM_USETHREADS
+       xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
+       xmlTextWriterWriteFormatString(writer, "%d", mgr->refs);
+       xmlTextWriterEndElement(writer);
+#endif
+
+       xmlTextWriterStartElement(writer, ISC_XMLCHAR "sockets");
+       sock = ISC_LIST_HEAD(mgr->socklist);
+       while (sock != NULL) {
+               LOCK(&sock->lock);
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "socket");
+
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "id");
+               xmlTextWriterWriteFormatString(writer, "%p", sock);
+               xmlTextWriterEndElement(writer);
+
+               if (sock->name[0] != 0) {
+                       xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+                       xmlTextWriterWriteFormatString(writer, "%s",
+                                                      sock->name);
+                       xmlTextWriterEndElement(writer); /* name */
+               }
+
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
+               xmlTextWriterWriteFormatString(writer, "%d", sock->references);
+               xmlTextWriterEndElement(writer);
+
+               xmlTextWriterWriteElement(writer, ISC_XMLCHAR "type",
+                                         ISC_XMLCHAR _socktype(sock->type));
+
+               if (sock->connected) {
+                       isc_sockaddr_format(&sock->address, peerbuf,
+                                           sizeof(peerbuf));
+                       xmlTextWriterWriteElement(writer,
+                                                 ISC_XMLCHAR "peer-address",
+                                                 ISC_XMLCHAR peerbuf);
+               }
+
+               len = sizeof(addr);
+               if (getsockname(sock->fd, &addr.type.sa, (void *)&len) == 0) {
+                       isc_sockaddr_format(&addr, peerbuf, sizeof(peerbuf));
+                       xmlTextWriterWriteElement(writer,
+                                                 ISC_XMLCHAR "local-address",
+                                                 ISC_XMLCHAR peerbuf);
+               }
+
+               xmlTextWriterStartElement(writer, ISC_XMLCHAR "states");
+               if (sock->pending_recv)
+                       xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+                                               ISC_XMLCHAR "pending-receive");
+               if (sock->pending_send)
+                       xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+                                                 ISC_XMLCHAR "pending-send");
+               if (sock->pending_accept)
+                       xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+                                                ISC_XMLCHAR "pending_accept");
+               if (sock->listener)
+                       xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+                                                 ISC_XMLCHAR "listener");
+               if (sock->connected)
+                       xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+                                                 ISC_XMLCHAR "connected");
+               if (sock->pending_connect)
+                       xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+                                                 ISC_XMLCHAR "connecting");
+               if (sock->bound)
+                       xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+                                                 ISC_XMLCHAR "bound");
+
+               xmlTextWriterEndElement(writer); /* states */
+
+               xmlTextWriterEndElement(writer); /* socket */
+
+               UNLOCK(&sock->lock);
+               sock = ISC_LIST_NEXT(sock, link);
+       }
+       xmlTextWriterEndElement(writer); /* sockets */
+
+       UNLOCK(&mgr->lock);
+}
+#endif /* HAVE_LIBXML2 */
index aebf73d3121c85d86762d3f77f3d0e2a6101b4cd..aafd70b124de0c663ed5dd38a1074a126a5ca68e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2006-2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2006-2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1998-2001, 2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: time.c,v 1.48 2008/09/08 23:47:10 tbox Exp $ */
+/* $Id: time.c,v 1.52 2009/08/14 07:51:08 marka Exp $ */
 
 #include <config.h>
 
@@ -226,28 +226,30 @@ isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2) {
 
 isc_uint32_t
 isc_time_seconds(const isc_time_t *t) {
-       SYSTEMTIME st;
+       SYSTEMTIME epoch = { 1970, 1, 4, 1, 0, 0, 0, 0 };
+       FILETIME temp;
+       ULARGE_INTEGER i1, i2;
+       LONGLONG i3;
 
-       /*
-        * Convert the time to a SYSTEMTIME structure and the grab the
-        * milliseconds
-        */
-       FileTimeToSystemTime(&t->absolute, &st);
+       SystemTimeToFileTime(&epoch, &temp);
 
-       return ((isc_uint32_t)(st.wMilliseconds / 1000));
+       i1.LowPart  = t->absolute.dwLowDateTime;
+       i1.HighPart = t->absolute.dwHighDateTime;
+       i2.LowPart  = temp.dwLowDateTime;
+       i2.HighPart = temp.dwHighDateTime;
+
+       i3 = (i1.QuadPart - i2.QuadPart) / 10000000;
+
+       return ((isc_uint32_t)i3);
 }
 
 isc_uint32_t
 isc_time_nanoseconds(const isc_time_t *t) {
-       SYSTEMTIME st;
-
-       /*
-        * Convert the time to a SYSTEMTIME structure and the grab the
-        * milliseconds
-        */
-       FileTimeToSystemTime(&t->absolute, &st);
+       ULARGE_INTEGER i;
 
-       return ((isc_uint32_t)(st.wMilliseconds * 1000000));
+       i.LowPart  = t->absolute.dwLowDateTime;
+       i.HighPart = t->absolute.dwHighDateTime;
+       return ((isc_uint32_t)(i.QuadPart % 10000000) * 100);
 }
 
 void
@@ -280,10 +282,12 @@ isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) {
        char DateBuf[50];
        char TimeBuf[50];
 
+/* strftime() format: "%a, %d %b %Y %H:%M:%S GMT" */
+
        REQUIRE(len > 0);
        if (FileTimeToSystemTime(&t->absolute, &st)) {
-               GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, "ddd',', dd-MMM-yyyy",
-                             DateBuf, 50);
+               GetDateFormat(LOCALE_USER_DEFAULT, 0, &st,
+                             "ddd',', dd-MMM-yyyy", DateBuf, 50);
                GetTimeFormat(LOCALE_USER_DEFAULT,
                              TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
                              &st, "hh':'mm':'ss", TimeBuf, 50);
@@ -293,3 +297,24 @@ isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) {
                buf[0] = 0;
        }
 }
+
+void
+isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
+       SYSTEMTIME st;
+       char DateBuf[50];
+       char TimeBuf[50];
+
+/* strtime() format: "%Y-%m-%dT%H:%M:%SZ" */
+
+       REQUIRE(len > 0);
+       if (FileTimeToSystemTime(&t->absolute, &st)) {
+               GetDateFormat(LOCALE_NEUTRAL, 0, &st, "yyyy-MM-dd",
+                             DateBuf, 50);
+               GetTimeFormat(LOCALE_NEUTRAL,
+                             TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
+                             &st, "hh':'mm':'ss", TimeBuf, 50);
+               snprintf(buf, len, "%s%sZ", DateBuf, TimeBuf);
+       } else {
+               buf[0] = 0;
+       }
+}
index 889f0b8c59fae1b21d2c91166e67f9014a44bb4f..bcb3b256da275201dabdf854dbbf88bf0e42aefa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2007-2009  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 2000, 2001  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: unistd.h,v 1.8 2008/01/23 03:22:43 tbox Exp $ */
+/* $Id: unistd.h,v 1.10 2009/07/17 23:47:41 tbox Exp $ */
 
 /* None of these are defined in NT, so define them for our use */
 #define O_NONBLOCK 1
@@ -39,6 +39,13 @@ int fcntl(int, int, ...);
  * access() related definitions for winXP
  */
 #include <io.h>
+#ifndef F_OK
+#define        F_OK    0
+#endif
+
+#ifndef X_OK
+#define        X_OK    1
+#endif
 
 #ifndef W_OK
 #define W_OK 2