aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/isc/Atffile5
-rw-r--r--lib/isc/alpha/include/isc/atomic.h4
-rw-r--r--lib/isc/api7
-rw-r--r--lib/isc/app_api.c136
-rw-r--r--lib/isc/assertions.c64
-rw-r--r--lib/isc/backtrace-emptytbl.c34
-rw-r--r--lib/isc/backtrace.c285
-rw-r--r--lib/isc/base32.c4
-rw-r--r--lib/isc/base64.c8
-rw-r--r--lib/isc/entropy.c11
-rw-r--r--lib/isc/hash.c20
-rw-r--r--lib/isc/heap.c19
-rw-r--r--lib/isc/hmacmd5.c35
-rw-r--r--lib/isc/hmacsha.c284
-rw-r--r--lib/isc/httpd.c75
-rw-r--r--lib/isc/ia64/include/isc/atomic.h8
-rw-r--r--lib/isc/include/isc/app.h173
-rw-r--r--lib/isc/include/isc/assertions.h8
-rw-r--r--lib/isc/include/isc/backtrace.h131
-rw-r--r--lib/isc/include/isc/bind9.h30
-rw-r--r--lib/isc/include/isc/buffer.h4
-rw-r--r--lib/isc/include/isc/entropy.h14
-rw-r--r--lib/isc/include/isc/error.h9
-rw-r--r--lib/isc/include/isc/file.h56
-rw-r--r--lib/isc/include/isc/fsaccess.h2
-rw-r--r--lib/isc/include/isc/hash.h2
-rw-r--r--lib/isc/include/isc/heap.h2
-rw-r--r--lib/isc/include/isc/hmacmd5.h13
-rw-r--r--lib/isc/include/isc/hmacsha.h17
-rw-r--r--lib/isc/include/isc/lib.h13
-rw-r--r--lib/isc/include/isc/list.h17
-rw-r--r--lib/isc/include/isc/log.h2
-rw-r--r--lib/isc/include/isc/md5.h14
-rw-r--r--lib/isc/include/isc/mem.h175
-rw-r--r--lib/isc/include/isc/msgs.h6
-rw-r--r--lib/isc/include/isc/namespace.h171
-rw-r--r--lib/isc/include/isc/netaddr.h2
-rw-r--r--lib/isc/include/isc/netscope.h6
-rw-r--r--lib/isc/include/isc/platform.h.in32
-rw-r--r--lib/isc/include/isc/portset.h4
-rw-r--r--lib/isc/include/isc/queue.h100
-rw-r--r--lib/isc/include/isc/radix.h2
-rw-r--r--lib/isc/include/isc/random.h2
-rw-r--r--lib/isc/include/isc/ratelimiter.h2
-rw-r--r--lib/isc/include/isc/refcount.h12
-rw-r--r--lib/isc/include/isc/result.h8
-rw-r--r--lib/isc/include/isc/resultclass.h5
-rw-r--r--lib/isc/include/isc/serial.h2
-rw-r--r--lib/isc/include/isc/sha1.h13
-rw-r--r--lib/isc/include/isc/sha2.h25
-rw-r--r--lib/isc/include/isc/sockaddr.h2
-rw-r--r--lib/isc/include/isc/socket.h165
-rw-r--r--lib/isc/include/isc/stats.h4
-rw-r--r--lib/isc/include/isc/symtab.h12
-rw-r--r--lib/isc/include/isc/task.h180
-rw-r--r--lib/isc/include/isc/taskpool.h64
-rw-r--r--lib/isc/include/isc/timer.h93
-rw-r--r--lib/isc/include/isc/types.h11
-rw-r--r--lib/isc/include/isc/util.h11
-rw-r--r--lib/isc/inet_aton.c4
-rw-r--r--lib/isc/inet_ntop.c26
-rw-r--r--lib/isc/inet_pton.c1
-rw-r--r--lib/isc/iterated_hash.c2
-rw-r--r--lib/isc/lib.c34
-rw-r--r--lib/isc/log.c16
-rw-r--r--lib/isc/md5.c30
-rw-r--r--lib/isc/mem.c616
-rw-r--r--lib/isc/mem_api.c303
-rw-r--r--lib/isc/mutexblock.c9
-rw-r--r--lib/isc/netaddr.c33
-rw-r--r--lib/isc/powerpc/include/isc/atomic.h71
-rw-r--r--lib/isc/print.c6
-rw-r--r--lib/isc/pthreads/mutex.c32
-rw-r--r--lib/isc/radix.c6
-rw-r--r--lib/isc/random.c29
-rw-r--r--lib/isc/result.c31
-rw-r--r--lib/isc/rwlock.c5
-rw-r--r--lib/isc/sha1.c43
-rw-r--r--lib/isc/sha2.c457
-rw-r--r--lib/isc/sockaddr.c13
-rw-r--r--lib/isc/socket_api.c231
-rw-r--r--lib/isc/sparc64/include/isc/atomic.h2
-rw-r--r--lib/isc/stats.c4
-rw-r--r--lib/isc/string.c11
-rw-r--r--lib/isc/symtab.c53
-rw-r--r--lib/isc/task.c799
-rw-r--r--lib/isc/task_api.c244
-rw-r--r--lib/isc/task_p.h16
-rw-r--r--lib/isc/taskpool.c117
-rw-r--r--lib/isc/tests/Atffile5
-rw-r--r--lib/isc/tests/hash_test.c1805
-rw-r--r--lib/isc/tests/isctest.c178
-rw-r--r--lib/isc/tests/isctest.h57
-rw-r--r--lib/isc/tests/queue_test.c144
-rw-r--r--lib/isc/tests/socket_test.c255
-rw-r--r--lib/isc/tests/symtab_test.c147
-rw-r--r--lib/isc/tests/task_test.c416
-rw-r--r--lib/isc/tests/taskpool_test.c211
-rw-r--r--lib/isc/timer.c353
-rw-r--r--lib/isc/timer_api.c144
-rw-r--r--lib/isc/timer_p.h8
-rw-r--r--lib/isc/unix/app.c540
-rw-r--r--lib/isc/unix/dir.c21
-rw-r--r--lib/isc/unix/entropy.c4
-rw-r--r--lib/isc/unix/errno2result.c11
-rw-r--r--lib/isc/unix/errno2result.h8
-rw-r--r--lib/isc/unix/file.c134
-rw-r--r--lib/isc/unix/ifiter_getifaddrs.c34
-rw-r--r--lib/isc/unix/ifiter_ioctl.c43
-rw-r--r--lib/isc/unix/ifiter_sysctl.c13
-rw-r--r--lib/isc/unix/include/isc/net.h4
-rw-r--r--lib/isc/unix/include/isc/offset.h4
-rw-r--r--lib/isc/unix/include/isc/stdtime.h8
-rw-r--r--lib/isc/unix/include/isc/strerror.h4
-rw-r--r--lib/isc/unix/include/isc/time.h2
-rw-r--r--lib/isc/unix/interfaceiter.c35
-rw-r--r--lib/isc/unix/net.c7
-rw-r--r--lib/isc/unix/resource.c2
-rw-r--r--lib/isc/unix/socket.c1239
-rw-r--r--lib/isc/unix/socket_p.h9
-rw-r--r--lib/isc/unix/stdio.c18
-rw-r--r--lib/isc/unix/strerror.c2
-rw-r--r--lib/isc/unix/time.c30
-rw-r--r--lib/isc/win32/app.c22
-rw-r--r--lib/isc/win32/dir.c6
-rw-r--r--lib/isc/win32/entropy.c2
-rw-r--r--lib/isc/win32/file.c140
-rw-r--r--lib/isc/win32/include/isc/ipv6.h4
-rw-r--r--lib/isc/win32/include/isc/mutex.h2
-rw-r--r--lib/isc/win32/include/isc/net.h4
-rw-r--r--lib/isc/win32/include/isc/ntpaths.h9
-rw-r--r--lib/isc/win32/include/isc/platform.h10
-rw-r--r--lib/isc/win32/include/isc/stat.h23
-rw-r--r--lib/isc/win32/include/isc/stdtime.h8
-rw-r--r--lib/isc/win32/include/isc/thread.h12
-rw-r--r--lib/isc/win32/include/isc/time.h2
-rw-r--r--lib/isc/win32/include/isc/win32os.h6
-rw-r--r--lib/isc/win32/interfaceiter.c10
-rw-r--r--lib/isc/win32/libgen.h25
-rw-r--r--lib/isc/win32/libisc.def266
-rw-r--r--lib/isc/win32/libisc.dsp26
-rw-r--r--lib/isc/win32/libisc.mak57
-rw-r--r--lib/isc/win32/net.c10
-rw-r--r--lib/isc/win32/netdb.h2
-rw-r--r--lib/isc/win32/ntgroups.c46
-rw-r--r--lib/isc/win32/ntpaths.c15
-rw-r--r--lib/isc/win32/socket.c483
-rw-r--r--lib/isc/win32/time.c63
-rw-r--r--lib/isc/win32/unistd.h11
149 files changed, 11031 insertions, 1987 deletions
diff --git a/lib/isc/Atffile b/lib/isc/Atffile
new file mode 100644
index 000000000000..1edb838c66cc
--- /dev/null
+++ b/lib/isc/Atffile
@@ -0,0 +1,5 @@
+Content-Type: application/X-atf-atffile; version="1"
+
+prop: test-suite = bind9
+
+tp: tests
diff --git a/lib/isc/alpha/include/isc/atomic.h b/lib/isc/alpha/include/isc/atomic.h
index f60f9fdc174a..a6232ada6fc7 100644
--- a/lib/isc/alpha/include/isc/atomic.h
+++ b/lib/isc/alpha/include/isc/atomic.h
@@ -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
@@ -46,7 +46,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: src/sys/alpha/include/atomic.h,v 1.18.6.1 2004/09/13 21:52:04 wilko Exp $
*/
#ifndef ISC_ATOMIC_H
diff --git a/lib/isc/api b/lib/isc/api
index 5ef8dc035a3e..ed4b69f8b8f7 100644
--- a/lib/isc/api
+++ b/lib/isc/api
@@ -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
index 000000000000..ce767d175053
--- /dev/null
+++ b/lib/isc/app_api.c
@@ -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);
+}
diff --git a/lib/isc/assertions.c b/lib/isc/assertions.c
index 4c9251bdcf25..31c4fe7c9f27 100644
--- a/lib/isc/assertions.c
+++ b/lib/isc/assertions.c
@@ -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 */
@@ -25,29 +25,47 @@
#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
index 000000000000..bd534d60c8e2
--- /dev/null
+++ b/lib/isc/backtrace-emptytbl.c
@@ -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
index 000000000000..d2f044cb8c4c
--- /dev/null
+++ b/lib/isc/backtrace.c
@@ -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);
+}
diff --git a/lib/isc/base32.c b/lib/isc/base32.c
index 3000a84f2da1..d25e3c4716bb 100644
--- a/lib/isc/base32.c
+++ b/lib/isc/base32.c
@@ -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);
}
diff --git a/lib/isc/base64.c b/lib/isc/base64.c
index 13ed6b5c5c17..bad1565bea7b 100644
--- a/lib/isc/base64.c
+++ b/lib/isc/base64.c
@@ -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);
}
diff --git a/lib/isc/entropy.c b/lib/isc/entropy.c
index 25ab00218956..da9e81fb3129 100644
--- a/lib/isc/entropy.c
+++ b/lib/isc/entropy.c
@@ -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
diff --git a/lib/isc/hash.c b/lib/isc/hash.c
index 9911bdee8fe2..f1d68c7700f5 100644
--- a/lib/isc/hash.c
+++ b/lib/isc/hash.c
@@ -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);
}
diff --git a/lib/isc/heap.c b/lib/isc/heap.c
index 91d78c06d468..ebadd2fd807c 100644
--- a/lib/isc/heap.c
+++ b/lib/isc/heap.c
@@ -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);
}
diff --git a/lib/isc/hmacmd5.c b/lib/isc/hmacmd5.c
index 63853dcd4191..6abe6e27df8e 100644
--- a/lib/isc/hmacmd5.c
+++ b/lib/isc/hmacmd5.c
@@ -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
@@ -27,10 +27,40 @@
#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
diff --git a/lib/isc/hmacsha.c b/lib/isc/hmacsha.c
index dfcd8bf5a9f0..d7b9f1897eb0 100644
--- a/lib/isc/hmacsha.c
+++ b/lib/isc/hmacsha.c
@@ -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
@@ -26,12 +26,172 @@
#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));
}
/*
@@ -105,19 +264,6 @@ isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
}
/*
- * 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.
*/
void
@@ -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));
}
/*
@@ -185,19 +330,6 @@ isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
}
/*
- * 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.
*/
void
@@ -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));
}
/*
@@ -265,19 +396,6 @@ isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
}
/*
- * 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.
*/
void
@@ -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));
}
/*
@@ -345,19 +462,6 @@ isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
}
/*
- * 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.
*/
void
@@ -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
diff --git a/lib/isc/httpd.c b/lib/isc/httpd.c
index fa313253b3e9..16a8c9fe142b 100644
--- a/lib/isc/httpd.c
+++ b/lib/isc/httpd.c
@@ -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);
diff --git a/lib/isc/ia64/include/isc/atomic.h b/lib/isc/ia64/include/isc/atomic.h
index 4c4679772044..6c22f2a53e28 100644
--- a/lib/isc/ia64/include/isc/atomic.h
+++ b/lib/isc/ia64/include/isc/atomic.h
@@ -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
@@ -31,10 +31,10 @@
* (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;
diff --git a/lib/isc/include/isc/app.h b/lib/isc/include/isc/app.h
index c4d54cbe44d9..e0be79063709 100644
--- a/lib/isc/include/isc/app.h
+++ b/lib/isc/include/isc/app.h
@@ -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
@@ -54,12 +54,23 @@
* 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.
*
@@ -75,17 +86,64 @@
#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);
/*!<
* \brief Start an ISC library application.
@@ -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,7 +163,7 @@ 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
@@ -110,6 +171,9 @@ isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
*/
isc_result_t
+isc_app_ctxrun(isc_appctx_t *ctx);
+
+isc_result_t
isc_app_run(void);
/*!<
* \brief Run an ISC library application.
@@ -120,11 +184,12 @@ 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.
@@ -132,6 +197,9 @@ isc_app_run(void);
*/
isc_result_t
+isc_app_ctxshutdown(isc_appctx_t *ctx);
+
+isc_result_t
isc_app_shutdown(void);
/*!<
* \brief Request application shutdown.
@@ -141,7 +209,8 @@ 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
@@ -149,6 +218,12 @@ isc_app_shutdown(void);
*/
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);
/*!<
* \brief Request application reload.
@@ -162,6 +237,9 @@ isc_app_reload(void);
*/
void
+isc_app_ctxfinish(isc_appctx_t *ctx);
+
+void
isc_app_finish(void);
/*!<
* \brief Finish an ISC library application.
@@ -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
diff --git a/lib/isc/include/isc/assertions.h b/lib/isc/include/isc/assertions.h
index b03115216909..2c81b1ae9880 100644
--- a/lib/isc/include/isc/assertions.h
+++ b/lib/isc/include/isc/assertions.h
@@ -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
index 000000000000..c0e98c0b7530
--- /dev/null
+++ b/lib/isc/include/isc/backtrace.h
@@ -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
index 000000000000..00bcb24c4a9b
--- /dev/null
+++ b/lib/isc/include/isc/bind9.h
@@ -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 */
diff --git a/lib/isc/include/isc/buffer.h b/lib/isc/include/isc/buffer.h
index 2a02d88e4e8e..ae7e4c3dfc34 100644
--- a/lib/isc/include/isc/buffer.h
+++ b/lib/isc/include/isc/buffer.h
@@ -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
diff --git a/lib/isc/include/isc/entropy.h b/lib/isc/include/isc/entropy.h
index e9e59c495141..d28f29a56ecf 100644
--- a/lib/isc/include/isc/entropy.h
+++ b/lib/isc/include/isc/entropy.h
@@ -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
diff --git a/lib/isc/include/isc/error.h b/lib/isc/include/isc/error.h
index efb9b5f3a11c..e0cdfa83e7cb 100644
--- a/lib/isc/include/isc/error.h
+++ b/lib/isc/include/isc/error.h
@@ -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
diff --git a/lib/isc/include/isc/file.h b/lib/isc/include/isc/file.h
index c9457343e055..5db506a389a4 100644
--- a/lib/isc/include/isc/file.h
+++ b/lib/isc/include/isc/file.h
@@ -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
@@ -30,10 +30,10 @@
ISC_LANG_BEGINDECLS
isc_result_t
-isc_file_settime(const char *file, isc_time_t *time);
+isc_file_settime(const char *file, isc_time_t *itime);
isc_result_t
-isc_file_getmodtime(const char *file, isc_time_t *time);
+isc_file_getmodtime(const char *file, isc_time_t *itime);
/*!<
* \brief Get the time of last modification of a file.
*
@@ -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 */
diff --git a/lib/isc/include/isc/fsaccess.h b/lib/isc/include/isc/fsaccess.h
index 3b455e5d56be..7962bbe21ab1 100644
--- a/lib/isc/include/isc/fsaccess.h
+++ b/lib/isc/include/isc/fsaccess.h
@@ -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
diff --git a/lib/isc/include/isc/hash.h b/lib/isc/include/isc/hash.h
index da30a19cdbc4..ca04b4e43c75 100644
--- a/lib/isc/include/isc/hash.h
+++ b/lib/isc/include/isc/hash.h
@@ -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
diff --git a/lib/isc/include/isc/heap.h b/lib/isc/include/isc/heap.h
index 82c59826db45..77bf07c34498 100644
--- a/lib/isc/include/isc/heap.h
+++ b/lib/isc/include/isc/heap.h
@@ -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
diff --git a/lib/isc/include/isc/hmacmd5.h b/lib/isc/include/isc/hmacmd5.h
index fab9c580c5d9..9ecad453dfa5 100644
--- a/lib/isc/include/isc/hmacmd5.h
+++ b/lib/isc/include/isc/hmacmd5.h
@@ -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
@@ -27,14 +27,23 @@
#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
diff --git a/lib/isc/include/isc/hmacsha.h b/lib/isc/include/isc/hmacsha.h
index 362b37f81acd..1d0e18409536 100644
--- a/lib/isc/include/isc/hmacsha.h
+++ b/lib/isc/include/isc/hmacsha.h
@@ -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>
@@ -35,6 +36,17 @@
#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
diff --git a/lib/isc/include/isc/lib.h b/lib/isc/include/isc/lib.h
index 765cdfaa1996..f24fef850169 100644
--- a/lib/isc/include/isc/lib.h
+++ b/lib/isc/include/isc/lib.h
@@ -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 */
diff --git a/lib/isc/include/isc/list.h b/lib/isc/include/isc/list.h
index 9338275c940a..c9bdfc7ad6bc 100644
--- a/lib/isc/include/isc/list.h
+++ b/lib/isc/include/isc/list.h
@@ -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
@@ -169,6 +169,19 @@
(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)
diff --git a/lib/isc/include/isc/log.h b/lib/isc/include/isc/log.h
index c9ba8082e52c..741c5324290c 100644
--- a/lib/isc/include/isc/log.h
+++ b/lib/isc/include/isc/log.h
@@ -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
diff --git a/lib/isc/include/isc/md5.h b/lib/isc/include/isc/md5.h
index 5b0d785cd1c4..dfa586d0a3b0 100644
--- a/lib/isc/include/isc/md5.h
+++ b/lib/isc/include/isc/md5.h
@@ -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.
@@ -44,15 +44,25 @@
#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
diff --git a/lib/isc/include/isc/mem.h b/lib/isc/include/isc/mem.h
index 480a934078ed..5101ea3fed1c 100644
--- a/lib/isc/include/isc/mem.h
+++ b/lib/isc/include/isc/mem.h
@@ -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
diff --git a/lib/isc/include/isc/msgs.h b/lib/isc/include/isc/msgs.h
index 4b4d8ab4de63..60c5c7caf882 100644
--- a/lib/isc/include/isc/msgs.h
+++ b/lib/isc/include/isc/msgs.h
@@ -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
@@ -157,7 +157,7 @@
#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
index 000000000000..cd4ec9ad1689
--- /dev/null
+++ b/lib/isc/include/isc/namespace.h
@@ -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 */
diff --git a/lib/isc/include/isc/netaddr.h b/lib/isc/include/isc/netaddr.h
index 8bfdbce20c12..954d77019b69 100644
--- a/lib/isc/include/isc/netaddr.h
+++ b/lib/isc/include/isc/netaddr.h
@@ -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
diff --git a/lib/isc/include/isc/netscope.h b/lib/isc/include/isc/netscope.h
index ba4e792a40a4..163a08ca2ea7 100644
--- a/lib/isc/include/isc/netscope.h
+++ b/lib/isc/include/isc/netscope.h
@@ -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 */
diff --git a/lib/isc/include/isc/platform.h.in b/lib/isc/include/isc/platform.h.in
index 1ed76b855618..03c2710bac35 100644
--- a/lib/isc/include/isc/platform.h.in
+++ b/lib/isc/include/isc/platform.h.in
@@ -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
@@ -146,6 +146,11 @@
*/
@ISC_PLATFORM_HAVEDEVPOLL@
+/*! \brief
+ * Define if we want to log backtrace
+ */
+@ISC_PLATFORM_USEBACKTRACE@
+
/*
*** Printing.
***/
@@ -215,6 +220,18 @@
@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_RLIMITTYPE@
@@ -284,6 +301,17 @@
*/
@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.
***/
diff --git a/lib/isc/include/isc/portset.h b/lib/isc/include/isc/portset.h
index dc1f85616eab..774d6bb18cbd 100644
--- a/lib/isc/include/isc/portset.h
+++ b/lib/isc/include/isc/portset.h
@@ -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
index 000000000000..5bf84c527c13
--- /dev/null
+++ b/lib/isc/include/isc/queue.h
@@ -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 */
diff --git a/lib/isc/include/isc/radix.h b/lib/isc/include/isc/radix.h
index fbb1893d489f..6b413a23b909 100644
--- a/lib/isc/include/isc/radix.h
+++ b/lib/isc/include/isc/radix.h
@@ -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:
diff --git a/lib/isc/include/isc/random.h b/lib/isc/include/isc/random.h
index 9b6ca64e022c..1f9572d30ebf 100644
--- a/lib/isc/include/isc/random.h
+++ b/lib/isc/include/isc/random.h
@@ -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
diff --git a/lib/isc/include/isc/ratelimiter.h b/lib/isc/include/isc/ratelimiter.h
index d18cf25b746d..00a7209758bb 100644
--- a/lib/isc/include/isc/ratelimiter.h
+++ b/lib/isc/include/isc/ratelimiter.h
@@ -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
diff --git a/lib/isc/include/isc/refcount.h b/lib/isc/include/isc/refcount.h
index 6ab14ae732c3..b72b1585be39 100644
--- a/lib/isc/include/isc/refcount.h
+++ b/lib/isc/include/isc/refcount.h
@@ -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) \
diff --git a/lib/isc/include/isc/result.h b/lib/isc/include/isc/result.h
index 56b4ca6d691a..dcd457b3d1b0 100644
--- a/lib/isc/include/isc/result.h
+++ b/lib/isc/include/isc/result.h
@@ -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 */
@@ -86,9 +87,10 @@
#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
diff --git a/lib/isc/include/isc/resultclass.h b/lib/isc/include/isc/resultclass.h
index b32426fee283..d91e800e063c 100644
--- a/lib/isc/include/isc/resultclass.h
+++ b/lib/isc/include/isc/resultclass.h
@@ -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 */
diff --git a/lib/isc/include/isc/serial.h b/lib/isc/include/isc/serial.h
index f7e3049e026e..a5e03970c3e6 100644
--- a/lib/isc/include/isc/serial.h
+++ b/lib/isc/include/isc/serial.h
@@ -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
diff --git a/lib/isc/include/isc/sha1.h b/lib/isc/include/isc/sha1.h
index 63f12bb1e0c7..313ff96391b2 100644
--- a/lib/isc/include/isc/sha1.h
+++ b/lib/isc/include/isc/sha1.h
@@ -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 $ */
@@ -29,16 +29,25 @@
*/
#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
diff --git a/lib/isc/include/isc/sha2.h b/lib/isc/include/isc/sha2.h
index 211e25505a95..439bbb948e4e 100644
--- a/lib/isc/include/isc/sha2.h
+++ b/lib/isc/include/isc/sha2.h
@@ -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,9 +14,9 @@
* 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$ */
+/* $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 ***********************/
@@ -75,10 +76,15 @@
#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]);
diff --git a/lib/isc/include/isc/sockaddr.h b/lib/isc/include/isc/sockaddr.h
index 62cc77397a09..1e6914222c1b 100644
--- a/lib/isc/include/isc/sockaddr.h
+++ b/lib/isc/include/isc/sockaddr.h
@@ -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
diff --git a/lib/isc/include/isc/socket.h b/lib/isc/include/isc/socket.h
index 035c99485084..38f6f78025df 100644
--- a/lib/isc/include/isc/socket.h
+++ b/lib/isc/include/isc/socket.h
@@ -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
***
@@ -307,6 +389,35 @@ isc_socket_fdwatchcreate(isc_socketmgr_t *manager,
*/
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,
isc_sockettype_t type,
@@ -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);
@@ -821,6 +938,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);
isc_result_t
@@ -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 */
diff --git a/lib/isc/include/isc/stats.h b/lib/isc/include/isc/stats.h
index a6156d861a3e..682eefdedf13 100644
--- a/lib/isc/include/isc/stats.h
+++ b/lib/isc/include/isc/stats.h
@@ -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
diff --git a/lib/isc/include/isc/symtab.h b/lib/isc/include/isc/symtab.h
index 396d64539607..9d0e5e2f23f0 100644
--- a/lib/isc/include/isc/symtab.h
+++ b/lib/isc/include/isc/symtab.h
@@ -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
@@ -57,6 +57,14 @@
* 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.
*
diff --git a/lib/isc/include/isc/task.h b/lib/isc/include/isc/task.h
index 8106571c761e..594d80f34510 100644
--- a/lib/isc/include/isc/task.h
+++ b/lib/isc/include/isc/task.h
@@ -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)
/*****
@@ -96,6 +97,82 @@
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 */
diff --git a/lib/isc/include/isc/taskpool.h b/lib/isc/include/isc/taskpool.h
index fd07bfd5b126..46f395ea246f 100644
--- a/lib/isc/include/isc/taskpool.h
+++ b/lib/isc/include/isc/taskpool.h
@@ -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 */
diff --git a/lib/isc/include/isc/timer.h b/lib/isc/include/isc/timer.h
index a4b2df7a54b0..fa9abb16aa9d 100644
--- a/lib/isc/include/isc/timer.h
+++ b/lib/isc/include/isc/timer.h
@@ -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
***
@@ -289,9 +344,14 @@ isc_timer_gettype(isc_timer_t *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 */
diff --git a/lib/isc/include/isc/types.h b/lib/isc/include/isc/types.h
index 4dccbf981569..8dbf67ed109e 100644
--- a/lib/isc/include/isc/types.h
+++ b/lib/isc/include/isc/types.h
@@ -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
@@ -15,11 +15,14 @@
* 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,
diff --git a/lib/isc/include/isc/util.h b/lib/isc/include/isc/util.h
index 8a3b95d9da36..670b28bc4c01 100644
--- a/lib/isc/include/isc/util.h
+++ b/lib/isc/include/isc/util.h
@@ -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
@@ -48,6 +48,11 @@
*/
#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))
@@ -70,7 +75,7 @@
* Use this in translation units that would otherwise be empty, to
* suppress compiler warnings.
*/
-#define EMPTY_TRANSLATION_UNIT static void isc__empty(void) { isc__empty(); }
+#define EMPTY_TRANSLATION_UNIT extern void exit(int);
/*%
* We use macros instead of calling the routines directly because
diff --git a/lib/isc/inet_aton.c b/lib/isc/inet_aton.c
index ad9401f696f0..14b4887f4f16 100644
--- a/lib/isc/inet_aton.c
+++ b/lib/isc/inet_aton.c
@@ -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>
diff --git a/lib/isc/inet_ntop.c b/lib/isc/inet_ntop.c
index 997bfd9bfa8c..26d5dcad1f0a 100644
--- a/lib/isc/inet_ntop.c
+++ b/lib/isc/inet_ntop.c
@@ -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>
@@ -31,8 +31,6 @@ static char rcsid[] =
#include <isc/net.h>
#include <isc/print.h>
-#include "ntp_sprintf.h" /* NTP local change, helps SunOS 4 */
-
#define NS_INT16SZ 2
#define NS_IN6ADDRSZ 16
@@ -48,13 +46,14 @@ static const char *inet_ntop4(const unsigned char *src, char *dst,
static const char *inet_ntop6(const unsigned char *src, char *dst,
size_t size);
#endif
+const char *isc_net_ntop(int af, const void *src, char *dst, size_t size);
/*! char *
* isc_net_ntop(af, src, dst, size)
* 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 *
@@ -91,15 +90,15 @@ inet_ntop4(const unsigned char *src, char *dst, size_t size)
{
static const char *fmt = "%u.%u.%u.%u";
char tmp[sizeof("255.255.255.255")];
+ int len;
- /* NTP local change to use SNPRINTF() macro for SunOS4 compat */
- if (SNPRINTF((tmp, sizeof(tmp), fmt, src[0], src[1], src[2],
- src[3])) >= size)
+ len = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
+ if (len < 0 || (size_t)len >= size)
{
errno = ENOSPC;
return (NULL);
}
- strcpy(dst, tmp);
+ memcpy(dst, tmp, 1 + len);
return (dst);
}
@@ -173,15 +172,16 @@ 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);
tp += strlen(tp);
break;
}
- tp += SPRINTF((tp, "%x", words[i])); /* NTP local change */
+ tp += snprintf(tp, sizeof(tmp) - (tp - tmp), "%x", words[i]);
}
/* Was it a trailing run of 0x00's? */
if (best.base != -1 && (best.base + best.len) ==
@@ -196,7 +196,7 @@ inet_ntop6(const unsigned char *src, char *dst, size_t size)
errno = ENOSPC;
return (NULL);
}
- strcpy(dst, tmp);
+ memcpy(dst, tmp, (size_t)(tp - tmp));
return (dst);
}
#endif /* AF_INET6 */
diff --git a/lib/isc/inet_pton.c b/lib/isc/inet_pton.c
index cd5bb79b53ba..66b5de0bf4d2 100644
--- a/lib/isc/inet_pton.c
+++ b/lib/isc/inet_pton.c
@@ -43,6 +43,7 @@ static char rcsid[] =
static int inet_pton4(const char *src, unsigned char *dst);
static int inet_pton6(const char *src, unsigned char *dst);
+int isc_net_pton(int af, const char *src, void *dst);
/*%
* convert from presentation format (which usually means ASCII printable)
diff --git a/lib/isc/iterated_hash.c b/lib/isc/iterated_hash.c
index 16743143faea..86dedde2880c 100644
--- a/lib/isc/iterated_hash.c
+++ b/lib/isc/iterated_hash.c
@@ -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"
diff --git a/lib/isc/lib.c b/lib/isc/lib.c
index f3a2c2dc790e..a50542551df3 100644
--- a/lib/isc/lib.c
+++ b/lib/isc/lib.c
@@ -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 */
@@ -24,9 +24,15 @@
#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
diff --git a/lib/isc/log.c b/lib/isc/log.c
index e19c9ba98eaa..0c142ce7707a 100644
--- a/lib/isc/log.c
+++ b/lib/isc/log.c
@@ -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 */
@@ -41,6 +41,7 @@
#include <isc/string.h>
#include <isc/time.h>
#include <isc/util.h>
+#include "ntp_stdlib.h" /* NTP change for strlcpy, strlcat */
#define LCTX_MAGIC ISC_MAGIC('L', 'c', 't', 'x')
#define VALID_CONTEXT(lctx) ISC_MAGIC_VALID(lctx, LCTX_MAGIC)
@@ -1342,9 +1343,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;
/*
@@ -1408,6 +1410,7 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
int syslog_level;
char time_string[64];
char level_string[24];
+ size_t octets;
const char *iformat;
struct stat statbuf;
isc_boolean_t matched = ISC_FALSE;
@@ -1618,16 +1621,17 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
* It wasn't in the duplicate interval,
* so add it to the message list.
*/
+ octets = strlen(lctx->buffer) + 1;
new = isc_mem_get(lctx->mctx,
sizeof(isc_logmessage_t) +
- strlen(lctx->buffer) + 1);
+ octets);
if (new != NULL) {
/*
* Put the text immediately after
* the struct. The strcpy is safe.
*/
new->text = (char *)(new + 1);
- strcpy(new->text, lctx->buffer);
+ strlcpy(new->text, lctx->buffer, octets);
TIME_NOW(&new->time);
diff --git a/lib/isc/md5.c b/lib/isc/md5.c
index 5004c3e4db46..7c6419b2a9c7 100644
--- a/lib/isc/md5.c
+++ b/lib/isc/md5.c
@@ -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.
@@ -38,10 +38,35 @@
#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
diff --git a/lib/isc/mem.c b/lib/isc/mem.c
index 9c37d7478bdb..5b4b16c570f6 100644
--- a/lib/isc/mem.c
+++ b/lib/isc/mem.c
@@ -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
index 000000000000..85abb9b4507c
--- /dev/null
+++ b/lib/isc/mem_api.c
@@ -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);
+}
diff --git a/lib/isc/mutexblock.c b/lib/isc/mutexblock.c
index d45ad0e1e485..d41e9d28d86d 100644
--- a/lib/isc/mutexblock.c
+++ b/lib/isc/mutexblock.c
@@ -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);
}
diff --git a/lib/isc/netaddr.c b/lib/isc/netaddr.c
index 2d745feb82a2..d6928c10df8b 100644
--- a/lib/isc/netaddr.c
+++ b/lib/isc/netaddr.c
@@ -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 */
@@ -31,6 +31,7 @@
#include <isc/sockaddr.h>
#include <isc/string.h>
#include <isc/util.h>
+#include "ntp_stdlib.h" /* NTP change for strlcpy, strlcat */
isc_boolean_t
isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) {
@@ -69,10 +70,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 +95,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 +187,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 +214,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] = { 0 };
- unsigned int nbits, nbytes, ipbytes;
+ unsigned int nbits, nbytes, ipbytes = 0;
const unsigned char *p;
switch (na->family) {
@@ -229,7 +231,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 +247,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 +260,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 +302,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);
+ 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);
+ strlcpy(netaddr->type.un, path, sizeof(netaddr->type.un));
netaddr->zone = 0;
return (ISC_R_SUCCESS);
#else
UNUSED(netaddr);
UNUSED(path);
- return (ISC_R_NOTIMPLEMENTED);
+ return (ISC_R_NOTIMPLEMENTED);
#endif
}
diff --git a/lib/isc/powerpc/include/isc/atomic.h b/lib/isc/powerpc/include/isc/atomic.h
index 765cb6d72a8c..030007f34ed7 100644
--- a/lib/isc/powerpc/include/isc/atomic.h
+++ b/lib/isc/powerpc/include/isc/atomic.h
@@ -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
@@ -46,25 +46,56 @@
#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)
diff --git a/lib/isc/print.c b/lib/isc/print.c
index b892e3a2ed09..a5e5ba6699d6 100644
--- a/lib/isc/print.c
+++ b/lib/isc/print.c
@@ -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--;
}
diff --git a/lib/isc/pthreads/mutex.c b/lib/isc/pthreads/mutex.c
index b57d9eee8daa..62ad540a7e17 100644
--- a/lib/isc/pthreads/mutex.c
+++ b/lib/isc/pthreads/mutex.c
@@ -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 */
@@ -30,6 +30,15 @@
#include <isc/util.h>
#include <isc/strerror.h>
+#if HAVE_PTHREADS < 5 /* HP-UX 10.20 has 4, needs this */
+# define pthread_mutex_init(m, a) \
+ pthread_mutex_init(m, (a) \
+ ? *(const pthread_mutexattr_t *)(a) \
+ : pthread_mutexattr_default)
+# define PTHREAD_MUTEX_RECURSIVE MUTEX_RECURSIVE_NP
+# define pthread_mutexattr_settype pthread_mutexattr_setkind_np
+#endif
+
#if ISC_MUTEX_PROFILE
/*@{*/
@@ -78,7 +87,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 +209,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 +243,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);
diff --git a/lib/isc/radix.c b/lib/isc/radix.c
index 7786984169a2..ac211efb6a87 100644
--- a/lib/isc/radix.c
+++ b/lib/isc/radix.c
@@ -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),
diff --git a/lib/isc/random.c b/lib/isc/random.c
index 0329abde72b2..8b73ed56927d 100644
--- a/lib/isc/random.c
+++ b/lib/isc/random.c
@@ -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);
}
diff --git a/lib/isc/result.c b/lib/isc/result.c
index 571358054e8f..520f1613acd1 100644
--- a/lib/isc/result.c
+++ b/lib/isc/result.c
@@ -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
@@ -112,14 +113,14 @@ static ISC_LIST(resulttable) tables;
static isc_mutex_t lock;
static isc_result_t
-register_table(unsigned int base, unsigned int nresults, const char **text,
+register_table(unsigned int base, unsigned int nresults, const char **txt,
isc_msgcat_t *msgcat, int set)
{
resulttable *table;
REQUIRE(base % ISC_RESULTCLASS_SIZE == 0);
REQUIRE(nresults <= ISC_RESULTCLASS_SIZE);
- REQUIRE(text != NULL);
+ REQUIRE(txt != NULL);
/*
* We use malloc() here because we we want to be able to use
@@ -130,7 +131,7 @@ register_table(unsigned int base, unsigned int nresults, const char **text,
return (ISC_R_NOMEMORY);
table->base = base;
table->last = base + nresults - 1;
- table->text = text;
+ table->text = txt;
table->msgcat = msgcat;
table->set = set;
ISC_LINK_INIT(table, link);
@@ -170,14 +171,14 @@ initialize(void) {
const char *
isc_result_totext(isc_result_t result) {
resulttable *table;
- const char *text, *default_text;
+ const char *txt, *default_text;
int index;
initialize();
LOCK(&lock);
- text = NULL;
+ txt = NULL;
for (table = ISC_LIST_HEAD(tables);
table != NULL;
table = ISC_LIST_NEXT(table, link)) {
@@ -189,25 +190,25 @@ isc_result_totext(isc_result_t result) {
* instead of index because isc_msgcat_get() requires
* the message number to be > 0.
*/
- text = isc_msgcat_get(table->msgcat, table->set,
- index + 1, default_text);
+ txt = isc_msgcat_get(table->msgcat, table->set,
+ index + 1, default_text);
break;
}
}
- if (text == NULL)
- text = isc_msgcat_get(isc_msgcat, ISC_RESULT_UNAVAILABLESET,
- 1, "(result code text not available)");
+ if (txt == NULL)
+ txt = isc_msgcat_get(isc_msgcat, ISC_RESULT_UNAVAILABLESET,
+ 1, "(result code text not available)");
UNLOCK(&lock);
- return (text);
+ return (txt);
}
isc_result_t
isc_result_register(unsigned int base, unsigned int nresults,
- const char **text, isc_msgcat_t *msgcat, int set)
+ const char **txt, isc_msgcat_t *msgcat, int set)
{
initialize();
- return (register_table(base, nresults, text, msgcat, set));
+ return (register_table(base, nresults, txt, msgcat, set));
}
diff --git a/lib/isc/rwlock.c b/lib/isc/rwlock.c
index ca8e83dfc13f..9c84c258a28b 100644
--- a/lib/isc/rwlock.c
+++ b/lib/isc/rwlock.c
@@ -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;
diff --git a/lib/isc/sha1.c b/lib/isc/sha1.c
index 3575288481eb..cce96036045f 100644
--- a/lib/isc/sha1.c
+++ b/lib/isc/sha1.c
@@ -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 $ */
@@ -38,11 +38,47 @@
#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
diff --git a/lib/isc/sha2.c b/lib/isc/sha2.c
index 70eea4f96700..db2e3496c454 100644
--- a/lib/isc/sha2.c
+++ b/lib/isc/sha2.c
@@ -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,9 +14,9 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sha2.c,v 1.13.332.2 2009/01/18 23:47:41 tbox Exp $ */
+/* $Id$ */
-/* $FreeBSD$ */
+/* $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 $ */
/*
@@ -58,10 +58,169 @@
#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
@@ -415,6 +567,11 @@ isc_sha224_init(isc_sha224_t *context) {
}
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));
}
@@ -1164,6 +1246,11 @@ isc_sha384_init(isc_sha384_t *context) {
}
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])
{
diff --git a/lib/isc/sockaddr.c b/lib/isc/sockaddr.c
index a0578a0d4bf1..2a7268f96131 100644
--- a/lib/isc/sockaddr.c
+++ b/lib/isc/sockaddr.c
@@ -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) {
@@ -217,7 +220,7 @@ isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) {
case AF_INET6:
in6 = &sockaddr->type.sin6.sin6_addr;
if (IN6_IS_ADDR_V4MAPPED(in6)) {
- s = (const unsigned char *)&in6[12];
+ s = (const unsigned char *)&in6 + 12;
length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
} else {
s = (const unsigned char *)in6;
@@ -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
index 000000000000..3394ce059b50
--- /dev/null
+++ b/lib/isc/socket_api.c
@@ -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));
+}
diff --git a/lib/isc/sparc64/include/isc/atomic.h b/lib/isc/sparc64/include/isc/atomic.h
index b92009561593..5533ddb0cc6f 100644
--- a/lib/isc/sparc64/include/isc/atomic.h
+++ b/lib/isc/sparc64/include/isc/atomic.h
@@ -48,7 +48,7 @@
* SUCH DAMAGE.
*
* from: FreeBSD: src/sys/i386/include/atomic.h,v 1.20 2001/02/11
- * $FreeBSD$
+ * $FreeBSD: src/sys/sparc64/include/atomic.h,v 1.8 2004/05/22 00:52:16 marius Exp $
*/
#ifndef ISC_ATOMIC_H
diff --git a/lib/isc/stats.c b/lib/isc/stats.c
index 9e4e089b527d..8b624b2d478d 100644
--- a/lib/isc/stats.c
+++ b/lib/isc/stats.c
@@ -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 */
diff --git a/lib/isc/string.c b/lib/isc/string.c
index b9c43e7bb150..cba517c568f9 100644
--- a/lib/isc/string.c
+++ b/lib/isc/string.c
@@ -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);
diff --git a/lib/isc/symtab.c b/lib/isc/symtab.c
index 9f8e798df368..d4c1dccf0ad9 100644
--- a/lib/isc/symtab.c
+++ b/lib/isc/symtab.c
@@ -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);
}
diff --git a/lib/isc/task.c b/lib/isc/task.c
index a630173d9405..cd19d2d5270b 100644
--- a/lib/isc/task.c
+++ b/lib/isc/task.c
@@ -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
@@ -40,9 +40,31 @@
#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;
@@ -186,12 +341,14 @@ isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
if (task == NULL)
return (ISC_R_NOMEMORY);
XTRACE("isc_task_create");
- task->manager = manager;
result = isc_mutex_init(&task->lock);
if (result != ISC_R_SUCCESS) {
isc_mem_put(manager->mctx, task, sizeof(*task));
return (result);
}
+ LOCK(&manager->lock);
+ LOCK(&task->lock); /* helps coverity analysis noise ratio */
+ task->manager = manager;
task->state = task_state_idle;
task->references = 1;
INIT_LIST(task->events);
@@ -203,6 +360,9 @@ 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);
+ UNLOCK(&task->lock);
+ UNLOCK(&manager->lock);
exiting = ISC_FALSE;
LOCK(&manager->lock);
@@ -220,14 +380,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 +405,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 +430,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 +446,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 +464,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 +501,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 +511,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 +527,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 +556,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 +598,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 +609,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 +635,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 +674,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 +706,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 +716,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 +762,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 +773,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 +787,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 +831,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 +850,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 +863,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 +880,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 +1035,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 +1064,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 +1087,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 +1110,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 +1203,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 +1232,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 +1285,45 @@ 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
+ LOCK(&manager->lock);
+#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 */
- DESTROYLOCK(&manager->lock);
- manager->magic = 0;
+#endif /* USE_WORKER_THREADS */
+ manager->common.impmagic = 0;
+ manager->common.magic = 0;
mctx = manager->mctx;
+ UNLOCK(&manager->lock);
+ DESTROYLOCK(&manager->lock);
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 +1332,35 @@ 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;
+ LOCK(&manager->lock);
-#ifdef ISC_PLATFORM_USETHREADS
+#ifdef USE_WORKER_THREADS
manager->workers = 0;
manager->threads = isc_mem_allocate(mctx,
workers * sizeof(isc_thread_t));
@@ -1087,20 +1384,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
- LOCK(&manager->lock);
+#ifdef USE_WORKER_THREADS
/*
* Start workers.
*/
@@ -1119,21 +1425,26 @@ 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;
+ UNLOCK(&manager->lock);
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:
isc_mem_free(mctx, manager->threads);
cleanup_lock:
+ UNLOCK(&manager->lock);
DESTROYLOCK(&manager->lock);
#endif
cleanup_mgr:
@@ -1141,10 +1452,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 +1463,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");
/*
@@ -1192,6 +1505,11 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
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 +1518,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 +1535,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 +1612,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 +1654,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 +1672,69 @@ isc_task_endexclusive(isc_task_t *task) {
BROADCAST(&manager->work_available);
UNLOCK(&manager->lock);
#else
- UNUSED(task);
+ UNUSED(task0);
+#endif
+}
+
+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));
}
-#ifdef HAVE_LIBXML2
+#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 +1810,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
index 000000000000..34510ff64c47
--- /dev/null
+++ b/lib/isc/task_api.c
@@ -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));
+}
diff --git a/lib/isc/task_p.h b/lib/isc/task_p.h
index c88810390890..8c1e4c52fa4c 100644
--- a/lib/isc/task_p.h
+++ b/lib/isc/task_p.h
@@ -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
@@ -15,17 +15,25 @@
* 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 */
diff --git a/lib/isc/taskpool.c b/lib/isc/taskpool.c
index d9c2fbe2f31a..25d951682889 100644
--- a/lib/isc/taskpool.c
+++ b/lib/isc/taskpool.c
@@ -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,13 +15,14 @@
* 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>
@@ -31,28 +32,30 @@
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
index 000000000000..c3e044f41a84
--- /dev/null
+++ b/lib/isc/tests/Atffile
@@ -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
index 000000000000..836d7b67abc7
--- /dev/null
+++ b/lib/isc/tests/hash_test.c
@@ -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
index 000000000000..e118bbf2ad9e
--- /dev/null
+++ b/lib/isc/tests/isctest.c
@@ -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
index 000000000000..03423c807bb7
--- /dev/null
+++ b/lib/isc/tests/isctest.h
@@ -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
index 000000000000..74620fef42aa
--- /dev/null
+++ b/lib/isc/tests/queue_test.c
@@ -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
index 000000000000..724d79df2bd1
--- /dev/null
+++ b/lib/isc/tests/socket_test.c
@@ -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
index 000000000000..21444b4c48ec
--- /dev/null
+++ b/lib/isc/tests/symtab_test.c
@@ -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
index 000000000000..7294d861d38a
--- /dev/null
+++ b/lib/isc/tests/task_test.c
@@ -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
index 000000000000..aecb694f2f3f
--- /dev/null
+++ b/lib/isc/tests/taskpool_test.c
@@ -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());
+}
+
diff --git a/lib/isc/timer.c b/lib/isc/timer.c
index 21fcd694eff1..0da251f4c31b 100644
--- a/lib/isc/timer.c
+++ b/lib/isc/timer.c
@@ -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 */
@@ -34,9 +34,22 @@
#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))
@@ -58,10 +71,13 @@
#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
index 000000000000..97e62b3f0ec4
--- /dev/null
+++ b/lib/isc/timer_api.c
@@ -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));
+}
diff --git a/lib/isc/timer_p.h b/lib/isc/timer_p.h
index ec8e2e0b7884..d6f7c996c7e2 100644
--- a/lib/isc/timer_p.h
+++ b/lib/isc/timer_p.h
@@ -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 */
diff --git a/lib/isc/unix/app.c b/lib/isc/unix/app.c
index 660b438678d6..5393be942504 100644
--- a/lib/isc/unix/app.c
+++ b/lib/isc/unix/app.c
@@ -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>
@@ -47,31 +48,129 @@
#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
diff --git a/lib/isc/unix/dir.c b/lib/isc/unix/dir.c
index 924414759d06..613ee5630d65 100644
--- a/lib/isc/unix/dir.c
+++ b/lib/isc/unix/dir.c
@@ -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 */
@@ -35,6 +35,7 @@
#include <isc/util.h>
#include "errno2result.h"
+#include "ntp_stdlib.h" /* NTP change for strlcpy, strlcat */
#define ISC_DIR_MAGIC ISC_MAGIC('D', 'I', 'R', '*')
#define VALID_DIR(dir) ISC_MAGIC_VALID(dir, ISC_DIR_MAGIC)
@@ -58,6 +59,7 @@ isc_dir_init(isc_dir_t *dir) {
isc_result_t
isc_dir_open(isc_dir_t *dir, const char *dirname) {
char *p;
+ size_t octets;
isc_result_t result = ISC_R_SUCCESS;
REQUIRE(VALID_DIR(dir));
@@ -67,10 +69,11 @@ isc_dir_open(isc_dir_t *dir, const char *dirname) {
* Copy directory name. Need to have enough space for the name,
* a possible path separator, the wildcard, and the final NUL.
*/
- if (strlen(dirname) + 3 > sizeof(dir->dirname))
+ octets = strlen(dirname) + 1;
+ if (octets + 2 > sizeof(dir->dirname))
/* XXXDCL ? */
return (ISC_R_NOSPACE);
- strcpy(dir->dirname, dirname);
+ strlcpy(dir->dirname, dirname, octets);
/*
* Append path separator, if needed, and "*".
@@ -79,7 +82,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.
@@ -102,6 +105,7 @@ isc_dir_open(isc_dir_t *dir, const char *dirname) {
isc_result_t
isc_dir_read(isc_dir_t *dir) {
struct dirent *entry;
+ size_t octets;
REQUIRE(VALID_DIR(dir) && dir->handle != NULL);
@@ -116,10 +120,11 @@ isc_dir_read(isc_dir_t *dir) {
/*
* Make sure that the space for the name is long enough.
*/
- if (sizeof(dir->entry.name) <= strlen(entry->d_name))
- return (ISC_R_UNEXPECTED);
+ octets = strlen(entry->d_name) + 1;
+ if (sizeof(dir->entry.name) < octets)
+ return (ISC_R_UNEXPECTED);
- strcpy(dir->entry.name, entry->d_name);
+ strlcpy(dir->entry.name, entry->d_name, octets);
/*
* Some dirents have d_namlen, but it is not portable.
diff --git a/lib/isc/unix/entropy.c b/lib/isc/unix/entropy.c
index 0e9e2979e306..ab53faf6754e 100644
--- a/lib/isc/unix/entropy.c
+++ b/lib/isc/unix/entropy.c
@@ -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
diff --git a/lib/isc/unix/errno2result.c b/lib/isc/unix/errno2result.c
index 606c5600c2f8..f20aa295ca9c 100644
--- a/lib/isc/unix/errno2result.c
+++ b/lib/isc/unix/errno2result.c
@@ -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);
/*
diff --git a/lib/isc/unix/errno2result.h b/lib/isc/unix/errno2result.h
index b5b658d500cd..1e49ed1d6c89 100644
--- a/lib/isc/unix/errno2result.h
+++ b/lib/isc/unix/errno2result.h
@@ -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
@@ -31,8 +31,10 @@
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
diff --git a/lib/isc/unix/file.c b/lib/isc/unix/file.c
index 748aee889c11..3b59e86b0755 100644
--- a/lib/isc/unix/file.c
+++ b/lib/isc/unix/file.c
@@ -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,12 +68,14 @@
#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>
#include <isc/util.h>
#include "errno2result.h"
+#include "ntp_stdlib.h" /* NTP change for strlcpy, strlcat */
/*
* XXXDCL As the API for accessing file statistics undoubtedly gets expanded,
@@ -97,12 +99,12 @@ file_stats(const char *file, struct stat *stats) {
}
isc_result_t
-isc_file_getmodtime(const char *file, isc_time_t *time) {
+isc_file_getmodtime(const char *file, isc_time_t *itime) {
isc_result_t result;
struct stat stats;
REQUIRE(file != NULL);
- REQUIRE(time != NULL);
+ REQUIRE(itime != NULL);
result = file_stats(file, &stats);
@@ -111,16 +113,16 @@ isc_file_getmodtime(const char *file, isc_time_t *time) {
* XXXDCL some operating systems provide nanoseconds, too,
* such as BSD/OS via st_mtimespec.
*/
- isc_time_set(time, stats.st_mtime, 0);
+ isc_time_set(itime, stats.st_mtime, 0);
return (result);
}
isc_result_t
-isc_file_settime(const char *file, isc_time_t *time) {
+isc_file_settime(const char *file, isc_time_t *itime) {
struct timeval times[2];
- REQUIRE(file != NULL && time != NULL);
+ REQUIRE(file != NULL && itime != NULL);
/*
* tv_sec is at least a 32 bit quantity on all platforms we're
@@ -132,7 +134,7 @@ isc_file_settime(const char *file, isc_time_t *time) {
* * isc_time_seconds is changed to be > 32 bits but long is 32 bits
* and isc_time_seconds has at least 33 significant bits.
*/
- times[0].tv_sec = times[1].tv_sec = (long)isc_time_seconds(time);
+ times[0].tv_sec = times[1].tv_sec = (long)isc_time_seconds(itime);
/*
* Here is the real check for the high bit being set.
@@ -148,7 +150,7 @@ isc_file_settime(const char *file, isc_time_t *time) {
* we can at least cast to signed so the IRIX compiler shuts up.
*/
times[0].tv_usec = times[1].tv_usec =
- (isc_int32_t)(isc_time_nanoseconds(time) / 1000);
+ (isc_int32_t)(isc_time_nanoseconds(itime) / 1000);
if (utimes(file, times) < 0)
return (isc__errno2result(errno));
@@ -183,14 +185,14 @@ isc_file_template(const char *path, const char *templet, char *buf,
if ((s - path + 1 + strlen(templet) + 1) > buflen)
return (ISC_R_NOSPACE);
- strncpy(buf, path, s - path + 1);
+ strlcpy(buf, path, buflen);
buf[s - path + 1] = '\0';
- strcat(buf, templet);
+ strlcat(buf, templet, buflen);
} else {
if ((strlen(templet) + 1) > buflen)
return (ISC_R_NOSPACE);
- strcpy(buf, templet);
+ strlcpy(buf, templet, buflen);
}
return (ISC_R_SUCCESS);
@@ -242,16 +244,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 +281,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 +349,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);
@@ -416,7 +444,7 @@ dir_current(char *dirname, size_t length) {
if (strlen(dirname) + 1 == length)
result = ISC_R_NOSPACE;
else if (dirname[1] != '\0')
- strcat(dirname, "/");
+ strlcat(dirname, "/", length);
}
return (result);
@@ -430,7 +458,7 @@ isc_file_absolutepath(const char *filename, char *path, size_t pathlen) {
return (result);
if (strlen(path) + strlen(filename) + 1 > pathlen)
return (ISC_R_NOSPACE);
- strcat(path, filename);
+ strlcat(path, filename, pathlen);
return (ISC_R_SUCCESS);
}
@@ -442,3 +470,75 @@ 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;
+
+ REQUIRE(path != NULL);
+
+ 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);
+}
diff --git a/lib/isc/unix/ifiter_getifaddrs.c b/lib/isc/unix/ifiter_getifaddrs.c
index ba04b447efe3..547a83f07937 100644
--- a/lib/isc/unix/ifiter_getifaddrs.c
+++ b/lib/isc/unix/ifiter_getifaddrs.c
@@ -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
@@ -55,6 +55,7 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
isc_interfaceiter_t *iter;
isc_result_t result;
char strbuf[ISC_STRERRORSIZE];
+ int trys, ret;
REQUIRE(mctx != NULL);
REQUIRE(iterp != NULL);
@@ -73,22 +74,31 @@ isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
* Only open "/proc/net/if_inet6" if we have never seen a IPv6
* address returned by getifaddrs().
*/
- if (!seenv6)
+ if (!seenv6) {
iter->proc = fopen("/proc/net/if_inet6", "r");
- else
+ if (iter->proc == NULL) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING,
+ "failed to open /proc/net/if_inet6");
+ }
+ } else
iter->proc = NULL;
iter->valid = ISC_R_FAILURE;
#endif
- if (getifaddrs(&iter->ifaddrs) < 0) {
+ /* If interrupted, try again */
+ for (trys = 0; trys < 3; trys++) {
+ if ((ret = getifaddrs(&iter->ifaddrs)) >= 0)
+ break;
+ if (errno != EINTR)
+ break;
+ }
+ if (ret < 0) {
isc__strerror(errno, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- isc_msgcat_get(isc_msgcat,
- ISC_MSGSET_IFITERGETIFADDRS,
- ISC_MSG_GETIFADDRS,
- "getting interface "
- "addresses: getifaddrs: %s"),
- strbuf);
+ UNEXPECTED_ERROR(__FILE__, __LINE__, isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERGETIFADDRS, ISC_MSG_GETIFADDRS,
+ "getting interface addresses: getifaddrs: %s"), strbuf);
result = ISC_R_UNEXPECTED;
goto failure;
}
diff --git a/lib/isc/unix/ifiter_ioctl.c b/lib/isc/unix/ifiter_ioctl.c
index a69979326883..a684867ce71f 100644
--- a/lib/isc/unix/ifiter_ioctl.c
+++ b/lib/isc/unix/ifiter_ioctl.c
@@ -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
@@ -109,6 +109,21 @@ struct isc_interfaceiter {
#endif
#endif
+int
+isc_ioctl(int fildes, int req, char *arg) {
+ int trys;
+ int ret;
+
+ for (trys = 0; trys < 3; trys++) {
+ if ((ret = ioctl(fildes, req, arg)) < 0) {
+ if (errno == EINTR)
+ continue;
+ }
+ break;
+ }
+ return (ret);
+}
+
static isc_result_t
getbuf4(isc_interfaceiter_t *iter) {
char strbuf[ISC_STRERRORSIZE];
@@ -128,7 +143,7 @@ getbuf4(isc_interfaceiter_t *iter) {
* conversion". It comes from its own macro definition,
* and is really hard to shut up.
*/
- if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
+ if (isc_ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
== -1) {
if (errno != EINVAL) {
isc__strerror(errno, strbuf, sizeof(strbuf));
@@ -208,7 +223,7 @@ getbuf6(isc_interfaceiter_t *iter) {
* conversion". It comes from its own macro definition,
* and is really hard to shut up.
*/
- if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
+ if (isc_ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
== -1) {
#ifdef __hpux
/*
@@ -453,7 +468,7 @@ internal_current4(isc_interfaceiter_t *iter) {
INSIST( iter->pos < (unsigned int) iter->ifc.ifc_len);
- ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
+ ifrp = (void *)((char *) iter->ifc.ifc_req + iter->pos);
memset(&ifreq, 0, sizeof(ifreq));
memcpy(&ifreq, ifrp, sizeof(ifreq));
@@ -502,7 +517,7 @@ internal_current4(isc_interfaceiter_t *iter) {
* conversion. It comes from its own macro definition,
* and is really hard to shut up.
*/
- if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
+ if (isc_ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"%s: getting interface flags: %s",
@@ -538,7 +553,7 @@ internal_current4(isc_interfaceiter_t *iter) {
memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6,
sizeof(iter->current.address.type.in6));
- if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
+ if (isc_ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"%s: getting interface address: %s",
@@ -588,7 +603,7 @@ internal_current4(isc_interfaceiter_t *iter) {
* conversion. It comes from its own macro definition,
* and is really hard to shut up.
*/
- if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
+ if (isc_ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
< 0) {
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
@@ -611,7 +626,7 @@ internal_current4(isc_interfaceiter_t *iter) {
* conversion. It comes from its own macro definition,
* and is really hard to shut up.
*/
- if (ioctl(iter->socket, SIOCGIFBRDADDR, (char *)&ifreq)
+ if (isc_ioctl(iter->socket, SIOCGIFBRDADDR, (char *)&ifreq)
< 0) {
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
@@ -637,7 +652,7 @@ internal_current4(isc_interfaceiter_t *iter) {
* conversion. It comes from its own macro definition,
* and is really hard to shut up.
*/
- if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
+ if (isc_ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
isc_msgcat_get(isc_msgcat,
@@ -666,7 +681,7 @@ internal_current6(isc_interfaceiter_t *iter) {
return (iter->result6);
REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
- ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
+ ifrp = (void *)((char *)iter->lifc.lifc_req + iter->pos6);
memset(&lifreq, 0, sizeof(lifreq));
memcpy(&lifreq, ifrp, sizeof(lifreq));
@@ -725,7 +740,7 @@ internal_current6(isc_interfaceiter_t *iter) {
* conversion. It comes from its own macro definition,
* and is really hard to shut up.
*/
- if (ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
+ if (isc_ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"%s: getting interface flags: %s",
@@ -764,7 +779,7 @@ internal_current6(isc_interfaceiter_t *iter) {
* conversion. It comes from its own macro definition,
* and is really hard to shut up.
*/
- if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
+ if (isc_ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
< 0) {
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
@@ -789,7 +804,7 @@ internal_current6(isc_interfaceiter_t *iter) {
* conversion. It comes from its own macro definition,
* and is really hard to shut up.
*/
- if (ioctl(iter->socket, SIOCGLIFBRDADDR, (char *)&lifreq)
+ if (isc_ioctl(iter->socket, SIOCGLIFBRDADDR, (char *)&lifreq)
< 0) {
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
@@ -839,7 +854,7 @@ internal_current6(isc_interfaceiter_t *iter) {
* conversion. It comes from its own macro definition,
* and is really hard to shut up.
*/
- if (ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
+ if (isc_ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
isc_msgcat_get(isc_msgcat,
diff --git a/lib/isc/unix/ifiter_sysctl.c b/lib/isc/unix/ifiter_sysctl.c
index 072e3494f756..0fbb3778e73a 100644
--- a/lib/isc/unix/ifiter_sysctl.c
+++ b/lib/isc/unix/ifiter_sysctl.c
@@ -159,6 +159,10 @@ internal_current(isc_interfaceiter_t *iter) {
ifam = (struct ifa_msghdr *) ((char *) iter->buf + iter->pos);
ifam_end = (struct ifa_msghdr *) ((char *) iter->buf + iter->bufused);
+ // Skip wrong RTM version headers
+ if (ifam->ifam_version != RTM_VERSION)
+ return (ISC_R_IGNORE);
+
if (ifam->ifam_type == RTM_IFINFO) {
struct if_msghdr *ifm = (struct if_msghdr *) ifam;
struct sockaddr_dl *sdl = (struct sockaddr_dl *) (ifm + 1);
@@ -272,10 +276,11 @@ internal_current(isc_interfaceiter_t *iter) {
return (ISC_R_SUCCESS);
} else {
- printf(isc_msgcat_get(isc_msgcat, ISC_MSGSET_IFITERSYSCTL,
- ISC_MSG_UNEXPECTEDTYPE,
- "warning: unexpected interface list "
- "message type\n"));
+ printf("%s", isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERSYSCTL,
+ ISC_MSG_UNEXPECTEDTYPE,
+ "warning: unexpected interface "
+ "list message type\n"));
return (ISC_R_IGNORE);
}
}
diff --git a/lib/isc/unix/include/isc/net.h b/lib/isc/unix/include/isc/net.h
index 7d478833c9a9..37a0f3b81fe8 100644
--- a/lib/isc/unix/include/isc/net.h
+++ b/lib/isc/unix/include/isc/net.h
@@ -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
diff --git a/lib/isc/unix/include/isc/offset.h b/lib/isc/unix/include/isc/offset.h
index 0e484becddf6..8bf3779997cd 100644
--- a/lib/isc/unix/include/isc/offset.h
+++ b/lib/isc/unix/include/isc/offset.h
@@ -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
diff --git a/lib/isc/unix/include/isc/stdtime.h b/lib/isc/unix/include/isc/stdtime.h
index 4cb9e81fa60c..c4931bfe6362 100644
--- a/lib/isc/unix/include/isc/stdtime.h
+++ b/lib/isc/unix/include/isc/stdtime.h
@@ -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
@@ -31,6 +31,10 @@
* 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
diff --git a/lib/isc/unix/include/isc/strerror.h b/lib/isc/unix/include/isc/strerror.h
index 2953f71c6dac..899043bbffdd 100644
--- a/lib/isc/unix/include/isc/strerror.h
+++ b/lib/isc/unix/include/isc/strerror.h
@@ -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
diff --git a/lib/isc/unix/include/isc/time.h b/lib/isc/unix/include/isc/time.h
index 45c4510e7603..dc1cef9ad3f2 100644
--- a/lib/isc/unix/include/isc/time.h
+++ b/lib/isc/unix/include/isc/time.h
@@ -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
diff --git a/lib/isc/unix/interfaceiter.c b/lib/isc/unix/interfaceiter.c
index 996669fc91e0..c42fa685c920 100644
--- a/lib/isc/unix/interfaceiter.c
+++ b/lib/isc/unix/interfaceiter.c
@@ -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 */
@@ -189,11 +189,9 @@ static isc_result_t
linux_if_inet6_current(isc_interfaceiter_t *iter) {
char address[33];
char name[IF_NAMESIZE+1];
- char strbuf[ISC_STRERRORSIZE];
struct in6_addr addr6;
unsigned int ifindex;
int prefix, scope, flags;
- struct ifreq ifreq;
int res;
unsigned int i;
@@ -238,34 +236,7 @@ linux_if_inet6_current(isc_interfaceiter_t *iter) {
addr6.s6_addr[i] = byte;
}
iter->current.af = AF_INET6;
- iter->current.flags = 0;
- memset(&ifreq, 0, sizeof(ifreq));
- INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
- strncpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name));
-
- if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "%s: getting interface flags: %s",
- ifreq.ifr_name, strbuf);
- return (ISC_R_IGNORE);
- }
-
- if ((ifreq.ifr_flags & IFF_UP) != 0)
- iter->current.flags |= INTERFACE_F_UP;
-#ifdef IFF_POINTOPOINT
- if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
- iter->current.flags |= INTERFACE_F_POINTTOPOINT;
-#endif
- if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
- iter->current.flags |= INTERFACE_F_LOOPBACK;
- if ((ifreq.ifr_flags & IFF_BROADCAST) != 0)
- iter->current.flags |= INTERFACE_F_BROADCAST;
-#ifdef IFF_MULTICAST
- if ((ifreq.ifr_flags & IFF_MULTICAST) != 0)
- iter->current.flags |= INTERFACE_F_MULTICAST;
-#endif
-
+ iter->current.flags = INTERFACE_F_UP;
isc_netaddr_fromin6(&iter->current.address, &addr6);
iter->current.ifindex = ifindex;
if (isc_netaddr_islinklocal(&iter->current.address)) {
diff --git a/lib/isc/unix/net.c b/lib/isc/unix/net.c
index 669a5be897ca..2ba17d165067 100644
--- a/lib/isc/unix/net.c
+++ b/lib/isc/unix/net.c
@@ -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>
@@ -302,8 +302,6 @@ try_ipv6only(void) {
goto close;
}
- close(s);
-
ipv6only_result = ISC_R_SUCCESS;
close:
@@ -358,7 +356,6 @@ try_ipv6pktinfo(void) {
goto close;
}
- close(s);
ipv6pktinfo_result = ISC_R_SUCCESS;
close:
diff --git a/lib/isc/unix/resource.c b/lib/isc/unix/resource.c
index 8bd8885bee8b..29596e2aa6a1 100644
--- a/lib/isc/unix/resource.c
+++ b/lib/isc/unix/resource.c
@@ -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>
diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c
index d09fe51ab57c..5fed888a11ae 100644
--- a/lib/isc/unix/socket.c
+++ b/lib/isc/unix/socket.c
@@ -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 */
@@ -67,14 +67,28 @@
#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
@@ -2458,10 +2766,50 @@ isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
}
/*
+ * 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);
diff --git a/lib/isc/unix/socket_p.h b/lib/isc/unix/socket_p.h
index fc044e58b294..13160117391f 100644
--- a/lib/isc/unix/socket_p.h
+++ b/lib/isc/unix/socket_p.h
@@ -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 */
diff --git a/lib/isc/unix/stdio.c b/lib/isc/unix/stdio.c
index 4e294dbc2fee..360c8c644afc 100644
--- a/lib/isc/unix/stdio.c
+++ b/lib/isc/unix/stdio.c
@@ -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));
diff --git a/lib/isc/unix/strerror.c b/lib/isc/unix/strerror.c
index 0353e12e5f22..22780095b546 100644
--- a/lib/isc/unix/strerror.c
+++ b/lib/isc/unix/strerror.c
@@ -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 */
diff --git a/lib/isc/unix/time.c b/lib/isc/unix/time.c
index 59428d3ca776..ac23ae092804 100644
--- a/lib/isc/unix/time.c
+++ b/lib/isc/unix/time.c
@@ -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;
diff --git a/lib/isc/win32/app.c b/lib/isc/win32/app.c
index b0db90d410bd..04b1638783eb 100644
--- a/lib/isc/win32/app.c
+++ b/lib/isc/win32/app.c
@@ -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;
diff --git a/lib/isc/win32/dir.c b/lib/isc/win32/dir.c
index cbeacbaafaba..14fadde46af3 100644
--- a/lib/isc/win32/dir.c
+++ b/lib/isc/win32/dir.c
@@ -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.
diff --git a/lib/isc/win32/entropy.c b/lib/isc/win32/entropy.c
index 7f4bb3fb39cf..5a316e6e5cff 100644
--- a/lib/isc/win32/entropy.c
+++ b/lib/isc/win32/entropy.c
@@ -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.
diff --git a/lib/isc/win32/file.c b/lib/isc/win32/file.c
index baf7953a00ec..c6b9e4f56f1f 100644
--- a/lib/isc/win32/file.c
+++ b/lib/isc/win32/file.c
@@ -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>
@@ -31,10 +31,12 @@
#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);
}
@@ -315,7 +317,19 @@ isc_file_renameunique(const char *file, char *templet) {
}
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);
+}
diff --git a/lib/isc/win32/include/isc/ipv6.h b/lib/isc/win32/include/isc/ipv6.h
index 51a6090715bb..27384a3557f7 100644
--- a/lib/isc/win32/include/isc/ipv6.h
+++ b/lib/isc/win32/include/isc/ipv6.h
@@ -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
diff --git a/lib/isc/win32/include/isc/mutex.h b/lib/isc/win32/include/isc/mutex.h
index 921c1e9380b1..5cf1bae1ba60 100644
--- a/lib/isc/win32/include/isc/mutex.h
+++ b/lib/isc/win32/include/isc/mutex.h
@@ -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
diff --git a/lib/isc/win32/include/isc/net.h b/lib/isc/win32/include/isc/net.h
index 33e688238cac..10be85b44408 100644
--- a/lib/isc/win32/include/isc/net.h
+++ b/lib/isc/win32/include/isc/net.h
@@ -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
diff --git a/lib/isc/win32/include/isc/ntpaths.h b/lib/isc/win32/include/isc/ntpaths.h
index 7cd185a031d4..39bcb6276f6c 100644
--- a/lib/isc/win32/include/isc/ntpaths.h
+++ b/lib/isc/win32/include/isc/ntpaths.h
@@ -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
*/
diff --git a/lib/isc/win32/include/isc/platform.h b/lib/isc/win32/include/isc/platform.h
index d74fc76b0598..94b8ba508141 100644
--- a/lib/isc/win32/include/isc/platform.h
+++ b/lib/isc/win32/include/isc/platform.h
@@ -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
@@ -40,7 +40,9 @@
#define ISC_PLATFORM_NEEDNTOP
#define ISC_PLATFORM_NEEDPTON
+#ifndef ISC_PLATFORM_QUADFORMAT
#define ISC_PLATFORM_QUADFORMAT "I64"
+#endif
#define ISC_PLATFORM_NEEDSTRSEP
#define ISC_PLATFORM_NEEDSTRLCPY
@@ -64,6 +66,12 @@
#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
*
* To build static libraries on win32, #define ISC_STATIC_WIN
diff --git a/lib/isc/win32/include/isc/stat.h b/lib/isc/win32/include/isc/stat.h
index 5fd411b91620..f95e3b0dd99c 100644
--- a/lib/isc/win32/include/isc/stat.h
+++ b/lib/isc/win32/include/isc/stat.h
@@ -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 */
@@ -37,11 +37,18 @@
#define S_IROTH _S_IREAD /* Other read permission */
#define S_IWOTH _S_IWRITE /* Other write permission */
-#define S_IFMT _S_IFMT /* file type mask */
-#define S_IFDIR _S_IFDIR /* directory */
-#define S_IFCHR _S_IFCHR /* character special */
-#define S_IFIFO _S_IFIFO /* pipe */
-#define S_IFREG _S_IFREG /* regular */
+#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)
diff --git a/lib/isc/win32/include/isc/stdtime.h b/lib/isc/win32/include/isc/stdtime.h
index 4f9eb74c54b6..abbbc16c1d69 100644
--- a/lib/isc/win32/include/isc/stdtime.h
+++ b/lib/isc/win32/include/isc/stdtime.h
@@ -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
@@ -29,6 +29,10 @@
* 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
diff --git a/lib/isc/win32/include/isc/thread.h b/lib/isc/win32/include/isc/thread.h
index b75a028f9230..2eb923b2e61b 100644
--- a/lib/isc/win32/include/isc/thread.h
+++ b/lib/isc/win32/include/isc/thread.h
@@ -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;
diff --git a/lib/isc/win32/include/isc/time.h b/lib/isc/win32/include/isc/time.h
index ce3c4c6a27a2..8ffb24b11428 100644
--- a/lib/isc/win32/include/isc/time.h
+++ b/lib/isc/win32/include/isc/time.h
@@ -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
diff --git a/lib/isc/win32/include/isc/win32os.h b/lib/isc/win32/include/isc/win32os.h
index d86820532c35..bd4039361913 100644
--- a/lib/isc/win32/include/isc/win32os.h
+++ b/lib/isc/win32/include/isc/win32os.h
@@ -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 */
diff --git a/lib/isc/win32/interfaceiter.c b/lib/isc/win32/interfaceiter.c
index 34c9428bcb5f..8753aa8a9977 100644
--- a/lib/isc/win32/interfaceiter.c
+++ b/lib/isc/win32/interfaceiter.c
@@ -15,17 +15,17 @@
* 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 $ */
#include <config.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <iphlpapi.h>
-#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
+#include <sys/types.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <gaa_compat.h>
#include <isc/interfaceiter.h>
#include <isc/mem.h>
diff --git a/lib/isc/win32/libgen.h b/lib/isc/win32/libgen.h
new file mode 100644
index 000000000000..1c58a9569a0e
--- /dev/null
+++ b/lib/isc/win32/libgen.h
@@ -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
diff --git a/lib/isc/win32/libisc.def b/lib/isc/win32/libisc.def
index 19a2fef6613d..fb084103da53 100644
--- a/lib/isc/win32/libisc.def
+++ b/lib/isc/win32/libisc.def
@@ -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
diff --git a/lib/isc/win32/libisc.dsp b/lib/isc/win32/libisc.dsp
index c0ffb713cf48..8e4441c39fab 100644
--- a/lib/isc/win32/libisc.dsp
+++ b/lib/isc/win32/libisc.dsp
@@ -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
diff --git a/lib/isc/win32/libisc.mak b/lib/isc/win32/libisc.mak
index 47d7b9707263..e15b46b3f862 100644
--- a/lib/isc/win32/libisc.mak
+++ b/lib/isc/win32/libisc.mak
@@ -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" \
@@ -1101,6 +1114,42 @@ SOURCE=..\assertions.c
!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
!IF "$(CFG)" == "libisc - Win32 Release"
diff --git a/lib/isc/win32/net.c b/lib/isc/win32/net.c
index 240c78336c07..12876da2b880 100644
--- a/lib/isc/win32/net.c
+++ b/lib/isc/win32/net.c
@@ -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>
@@ -170,7 +170,8 @@ try_ipv6only(void) {
}
on = 1;
- if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)) < 0) {
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&on,
+ sizeof(on)) < 0) {
ipv6only_result = ISC_R_NOTFOUND;
goto close;
}
@@ -193,7 +194,8 @@ try_ipv6only(void) {
}
on = 1;
- if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)) < 0) {
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&on,
+ sizeof(on)) < 0) {
ipv6only_result = ISC_R_NOTFOUND;
goto close;
}
diff --git a/lib/isc/win32/netdb.h b/lib/isc/win32/netdb.h
index fa941800484f..f8d936a99f35 100644
--- a/lib/isc/win32/netdb.h
+++ b/lib/isc/win32/netdb.h
@@ -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
diff --git a/lib/isc/win32/ntgroups.c b/lib/isc/win32/ntgroups.c
index 351adc5e74b9..729cf07e74f0 100644
--- a/lib/isc/win32/ntgroups.c
+++ b/lib/isc/win32/ntgroups.c
@@ -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);
diff --git a/lib/isc/win32/ntpaths.c b/lib/isc/win32/ntpaths.c
index d1c622fa9574..1ff8c5a9b5c3 100644
--- a/lib/isc/win32/ntpaths.c
+++ b/lib/isc/win32/ntpaths.c
@@ -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);
}
diff --git a/lib/isc/win32/socket.c b/lib/isc/win32/socket.c
index 7c4068fbdc2b..ffcefb0606c8 100644
--- a/lib/isc/win32/socket.c
+++ b/lib/isc/win32/socket.c
@@ -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,13 +1814,34 @@ 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));
REQUIRE(sock->type != isc_sockettype_fdwatch);
@@ -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 */
diff --git a/lib/isc/win32/time.c b/lib/isc/win32/time.c
index aebf73d3121c..aafd70b124de 100644
--- a/lib/isc/win32/time.c
+++ b/lib/isc/win32/time.c
@@ -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;
+ }
+}
diff --git a/lib/isc/win32/unistd.h b/lib/isc/win32/unistd.h
index 889f0b8c59fa..bcb3b256da27 100644
--- a/lib/isc/win32/unistd.h
+++ b/lib/isc/win32/unistd.h
@@ -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