summaryrefslogtreecommitdiffstats
path: root/lib/isc/include
diff options
context:
space:
mode:
Diffstat (limited to 'lib/isc/include')
l---------lib/isc/include/.clang-format1
-rw-r--r--lib/isc/include/Makefile.in19
-rw-r--r--lib/isc/include/isc/Makefile.in63
-rw-r--r--lib/isc/include/isc/aes.h44
-rw-r--r--lib/isc/include/isc/app.h283
-rw-r--r--lib/isc/include/isc/assertions.h79
-rw-r--r--lib/isc/include/isc/astack.h49
-rw-r--r--lib/isc/include/isc/atomic.h73
-rw-r--r--lib/isc/include/isc/backtrace.h127
-rw-r--r--lib/isc/include/isc/barrier.h39
-rw-r--r--lib/isc/include/isc/base32.h146
-rw-r--r--lib/isc/include/isc/base64.h101
-rw-r--r--lib/isc/include/isc/bind9.h29
-rw-r--r--lib/isc/include/isc/buffer.h1103
-rw-r--r--lib/isc/include/isc/bufferlist.h80
-rw-r--r--lib/isc/include/isc/cmocka.h55
-rw-r--r--lib/isc/include/isc/commandline.h59
-rw-r--r--lib/isc/include/isc/counter.h87
-rw-r--r--lib/isc/include/isc/crc64.h58
-rw-r--r--lib/isc/include/isc/deprecated.h23
-rw-r--r--lib/isc/include/isc/endian.h190
-rw-r--r--lib/isc/include/isc/errno.h30
-rw-r--r--lib/isc/include/isc/error.h57
-rw-r--r--lib/isc/include/isc/event.h120
-rw-r--r--lib/isc/include/isc/eventclass.h48
-rw-r--r--lib/isc/include/isc/file.h400
-rw-r--r--lib/isc/include/isc/formatcheck.h36
-rw-r--r--lib/isc/include/isc/fsaccess.h174
-rw-r--r--lib/isc/include/isc/fuzz.h26
-rw-r--r--lib/isc/include/isc/hash.h66
-rw-r--r--lib/isc/include/isc/heap.h164
-rw-r--r--lib/isc/include/isc/hex.h101
-rw-r--r--lib/isc/include/isc/hmac.h147
-rw-r--r--lib/isc/include/isc/ht.h183
-rw-r--r--lib/isc/include/isc/httpd.h85
-rw-r--r--lib/isc/include/isc/interfaceiter.h130
-rw-r--r--lib/isc/include/isc/iterated_hash.h38
-rw-r--r--lib/isc/include/isc/lang.h27
-rw-r--r--lib/isc/include/isc/lex.h447
-rw-r--r--lib/isc/include/isc/lfsr.h124
-rw-r--r--lib/isc/include/isc/lib.h47
-rw-r--r--lib/isc/include/isc/likely.h33
-rw-r--r--lib/isc/include/isc/list.h229
-rw-r--r--lib/isc/include/isc/log.h848
-rw-r--r--lib/isc/include/isc/magic.h37
-rw-r--r--lib/isc/include/isc/managers.h29
-rw-r--r--lib/isc/include/isc/md.h205
-rw-r--r--lib/isc/include/isc/mem.h633
-rw-r--r--lib/isc/include/isc/meminfo.h33
-rw-r--r--lib/isc/include/isc/mutexblock.h57
-rw-r--r--lib/isc/include/isc/netaddr.h199
-rw-r--r--lib/isc/include/isc/netmgr.h540
-rw-r--r--lib/isc/include/isc/netscope.h39
-rw-r--r--lib/isc/include/isc/nonce.h33
-rw-r--r--lib/isc/include/isc/os.h32
-rw-r--r--lib/isc/include/isc/parseint.h60
-rw-r--r--lib/isc/include/isc/platform.h.in100
-rw-r--r--lib/isc/include/isc/pool.h141
-rw-r--r--lib/isc/include/isc/portset.h138
-rw-r--r--lib/isc/include/isc/print.h33
-rw-r--r--lib/isc/include/isc/quota.h156
-rw-r--r--lib/isc/include/isc/radix.h224
-rw-r--r--lib/isc/include/isc/random.h65
-rw-r--r--lib/isc/include/isc/ratelimiter.h148
-rw-r--r--lib/isc/include/isc/refcount.h156
-rw-r--r--lib/isc/include/isc/regex.h36
-rw-r--r--lib/isc/include/isc/region.h98
-rw-r--r--lib/isc/include/isc/resource.h90
-rw-r--r--lib/isc/include/isc/result.h122
-rw-r--r--lib/isc/include/isc/resultclass.h43
-rw-r--r--lib/isc/include/isc/rwlock.h107
-rw-r--r--lib/isc/include/isc/safe.h47
-rw-r--r--lib/isc/include/isc/serial.h72
-rw-r--r--lib/isc/include/isc/siphash.h37
-rw-r--r--lib/isc/include/isc/sockaddr.h254
-rw-r--r--lib/isc/include/isc/socket.h914
-rw-r--r--lib/isc/include/isc/stats.h256
-rw-r--r--lib/isc/include/isc/stdio.h74
-rw-r--r--lib/isc/include/isc/strerr.h23
-rw-r--r--lib/isc/include/isc/string.h43
-rw-r--r--lib/isc/include/isc/symtab.h138
-rw-r--r--lib/isc/include/isc/task.h721
-rw-r--r--lib/isc/include/isc/taskpool.h138
-rw-r--r--lib/isc/include/isc/timer.h323
-rw-r--r--lib/isc/include/isc/tm.h42
-rw-r--r--lib/isc/include/isc/types.h131
-rw-r--r--lib/isc/include/isc/url.h82
-rw-r--r--lib/isc/include/isc/utf8.h43
-rw-r--r--lib/isc/include/isc/util.h445
-rw-r--r--lib/isc/include/isc/version.h18
-rw-r--r--lib/isc/include/pk11/Makefile.in40
-rw-r--r--lib/isc/include/pk11/constants.h37
-rw-r--r--lib/isc/include/pk11/internal.h49
-rw-r--r--lib/isc/include/pk11/pk11.h290
-rw-r--r--lib/isc/include/pk11/result.h48
-rw-r--r--lib/isc/include/pk11/site.h16
-rw-r--r--lib/isc/include/pkcs11/Makefile.in40
-rw-r--r--lib/isc/include/pkcs11/pkcs11.h1655
98 files changed, 15798 insertions, 0 deletions
diff --git a/lib/isc/include/.clang-format b/lib/isc/include/.clang-format
new file mode 120000
index 0000000..0e62f72
--- /dev/null
+++ b/lib/isc/include/.clang-format
@@ -0,0 +1 @@
+../../../.clang-format.headers \ No newline at end of file
diff --git a/lib/isc/include/Makefile.in b/lib/isc/include/Makefile.in
new file mode 100644
index 0000000..b052e73
--- /dev/null
+++ b/lib/isc/include/Makefile.in
@@ -0,0 +1,19 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isc pk11 pkcs11
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/include/isc/Makefile.in b/lib/isc/include/isc/Makefile.in
new file mode 100644
index 0000000..a42c9e0
--- /dev/null
+++ b/lib/isc/include/isc/Makefile.in
@@ -0,0 +1,63 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+#
+# Only list headers that are to be installed and are not
+# machine generated. The latter are handled specially in the
+# install target below.
+#
+HEADERS = aes.h app.h assertions.h astack.h atomic.h backtrace.h \
+ barrier.h base32.h base64.h bind9.h buffer.h bufferlist.h \
+ cmocka.h commandline.h counter.h crc64.h deprecated.h \
+ endian.h errno.h error.h event.h eventclass.h \
+ file.h formatcheck.h fsaccess.h fuzz.h \
+ hash.h heap.h hex.h hmac.h ht.h httpd.h \
+ interfaceiter.h iterated_hash.h \
+ lang.h lex.h lfsr.h lib.h likely.h list.h log.h \
+ magic.h managers.h md.h mem.h meminfo.h \
+ mutexblock.h \
+ netaddr.h netmgr.h netscope.h nonce.h os.h parseint.h \
+ pool.h portset.h print.h quota.h \
+ radix.h random.h ratelimiter.h refcount.h regex.h \
+ region.h resource.h result.h resultclass.h rwlock.h \
+ safe.h serial.h siphash.h sockaddr.h socket.h \
+ stats.h stdio.h strerr.h string.h symtab.h \
+ task.h taskpool.h timer.h tm.h types.h \
+ url.h utf8.h util.h version.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/isc || exit 1; \
+ done
+ ${INSTALL_DATA} platform.h ${DESTDIR}${includedir}/isc
+
+uninstall::
+ rm -f ${DESTDIR}${includedir}/isc/platform.h
+ for i in ${HEADERS}; do \
+ rm -f ${DESTDIR}${includedir}/isc/$$i || exit 1; \
+ done
+
+distclean::
+ rm -f platform.h
diff --git a/lib/isc/include/isc/aes.h b/lib/isc/include/isc/aes.h
new file mode 100644
index 0000000..00449b5
--- /dev/null
+++ b/lib/isc/include/isc/aes.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file isc/aes.h */
+
+#ifndef ISC_AES_H
+#define ISC_AES_H 1
+
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#define ISC_AES128_KEYLENGTH 16U
+#define ISC_AES192_KEYLENGTH 24U
+#define ISC_AES256_KEYLENGTH 32U
+#define ISC_AES_BLOCK_LENGTH 16U
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_aes128_crypt(const unsigned char *key, const unsigned char *in,
+ unsigned char *out);
+
+void
+isc_aes192_crypt(const unsigned char *key, const unsigned char *in,
+ unsigned char *out);
+
+void
+isc_aes256_crypt(const unsigned char *key, const unsigned char *in,
+ unsigned char *out);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_AES_H */
diff --git a/lib/isc/include/isc/app.h b/lib/isc/include/isc/app.h
new file mode 100644
index 0000000..9e8140b
--- /dev/null
+++ b/lib/isc/include/isc/app.h
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_APP_H
+#define ISC_APP_H 1
+
+/*****
+***** Module Info
+*****/
+
+/*! \file isc/app.h
+ * \brief ISC Application Support
+ *
+ * Dealing with program termination can be difficult, especially in a
+ * multithreaded program. The routines in this module help coordinate
+ * the shutdown process. They are used as follows by the initial (main)
+ * thread of the application:
+ *
+ *\li isc_app_start(); Call very early in main(), before
+ * any other threads have been created.
+ *
+ *\li isc_app_run(); This will post any on-run events,
+ * and then block until application
+ * shutdown is requested. A shutdown
+ * request is made by calling
+ * isc_app_shutdown(), or by sending
+ * SIGINT or SIGTERM to the process.
+ * After isc_app_run() returns, the
+ * application should shutdown itself.
+ *
+ *\li isc_app_finish(); Call very late in main().
+ *
+ * Applications that want to use SIGHUP/isc_app_reload() to trigger reloading
+ * should check the result of isc_app_run() and call the reload routine if
+ * the result is ISC_R_RELOAD. They should then call isc_app_run() again
+ * to resume waiting for reload or termination.
+ *
+ * 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.
+ *
+ * \li Resources:
+ * None.
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ */
+
+#include <stdbool.h>
+
+#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)
+
+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.
+ *
+ * Notes:
+ * This call should be made before any other ISC library call, and as
+ * close to the beginning of the application as possible.
+ *
+ * Requires:
+ *\li 'ctx' is a valid application context (for app_ctxstart()).
+ */
+
+isc_result_t
+isc_app_ctxonrun(isc_appctx_t *ctx, isc_mem_t *mctx, isc_task_t *task,
+ isc_taskaction_t action, void *arg);
+isc_result_t
+isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
+ void *arg);
+/*!<
+ * \brief Request delivery of an event when the application is run.
+ *
+ * Requires:
+ *\li isc_app_start() has been called.
+ *\li 'ctx' is a valid application context (for app_ctxonrun()).
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * ISC_R_NOMEMORY
+ */
+
+isc_result_t
+isc_app_ctxrun(isc_appctx_t *ctx);
+
+isc_result_t
+isc_app_run(void);
+/*!<
+ * \brief Run an ISC library application.
+ *
+ * Notes:
+ *\li The caller (typically the initial thread of an application) will
+ * block until shutdown is requested. When the call returns, the
+ * caller should start shutting down the application.
+ *
+ * Requires:
+ *\li isc_app_[ctx]start() has been called.
+ *
+ * Ensures:
+ *\li Any events requested via isc_app_onrun() will have been posted (in
+ * FIFO order) before isc_app_run() blocks.
+ *\li 'ctx' is a valid application context (for app_ctxrun()).
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS Shutdown has been requested.
+ *\li ISC_R_RELOAD Reload has been requested.
+ */
+
+bool
+isc_app_isrunning(void);
+/*!<
+ * \brief Return if the ISC library application is running.
+ *
+ * Returns:
+ *\li true App is running.
+ *\li false App is not running.
+ */
+
+void
+isc_app_ctxshutdown(isc_appctx_t *ctx);
+
+void
+isc_app_shutdown(void);
+/*!<
+ * \brief Request application shutdown.
+ *
+ * Notes:
+ *\li It is safe to call isc_app_shutdown() multiple times. Shutdown will
+ * only be triggered once.
+ *
+ * Requires:
+ *\li isc_app_[ctx]run() has been called.
+ *\li 'ctx' is a valid application context (for app_ctxshutdown()).
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_UNEXPECTED
+ */
+
+void
+isc_app_ctxsuspend(isc_appctx_t *ctx);
+/*!<
+ * \brief This has the same behavior as isc_app_ctxsuspend().
+ */
+
+void
+isc_app_reload(void);
+/*!<
+ * \brief Request application reload.
+ *
+ * Requires:
+ *\li isc_app_run() has been called.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_UNEXPECTED
+ */
+
+void
+isc_app_ctxfinish(isc_appctx_t *ctx);
+
+void
+isc_app_finish(void);
+/*!<
+ * \brief Finish an ISC library application.
+ *
+ * Notes:
+ *\li This call should be made at or near the end of main().
+ *
+ * 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.
+ */
+
+void
+isc_app_block(void);
+/*!<
+ * \brief Indicate that a blocking operation will be performed.
+ *
+ * Notes:
+ *\li If a blocking operation is in process, a call to isc_app_shutdown()
+ * or an external signal will abort the program, rather than allowing
+ * clean shutdown. This is primarily useful for reading user input.
+ *
+ * Requires:
+ * \li isc_app_start() has been called.
+ * \li No other blocking operations are in progress.
+ */
+
+void
+isc_app_unblock(void);
+/*!<
+ * \brief Indicate that a blocking operation is complete.
+ *
+ * Notes:
+ * \li When a blocking operation has completed, return the program to a
+ * state where a call to isc_app_shutdown() or an external signal will
+ * shutdown normally.
+ *
+ * Requires:
+ * \li isc_app_start() has been called.
+ * \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.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_APP_H */
diff --git a/lib/isc/include/isc/assertions.h b/lib/isc/include/isc/assertions.h
new file mode 100644
index 0000000..e68adfa
--- /dev/null
+++ b/lib/isc/include/isc/assertions.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file isc/assertions.h
+ */
+
+#ifndef ISC_ASSERTIONS_H
+#define ISC_ASSERTIONS_H 1
+
+#include <isc/lang.h>
+#include <isc/likely.h>
+#include <isc/platform.h>
+
+ISC_LANG_BEGINDECLS
+
+/*% isc assertion type */
+typedef enum {
+ isc_assertiontype_require,
+ isc_assertiontype_ensure,
+ isc_assertiontype_insist,
+ isc_assertiontype_invariant
+} isc_assertiontype_t;
+
+typedef void (*isc_assertioncallback_t)(const char *, int, isc_assertiontype_t,
+ const char *);
+
+/* coverity[+kill] */
+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);
+
+const char *
+isc_assertion_typetotext(isc_assertiontype_t type);
+
+#define ISC_REQUIRE(cond) \
+ ((void)(ISC_LIKELY(cond) || \
+ ((isc_assertion_failed)(__FILE__, __LINE__, \
+ isc_assertiontype_require, #cond), \
+ 0)))
+
+#define ISC_ENSURE(cond) \
+ ((void)(ISC_LIKELY(cond) || \
+ ((isc_assertion_failed)(__FILE__, __LINE__, \
+ isc_assertiontype_ensure, #cond), \
+ 0)))
+
+#define ISC_INSIST(cond) \
+ ((void)(ISC_LIKELY(cond) || \
+ ((isc_assertion_failed)(__FILE__, __LINE__, \
+ isc_assertiontype_insist, #cond), \
+ 0)))
+
+#define ISC_INVARIANT(cond) \
+ ((void)(ISC_LIKELY(cond) || \
+ ((isc_assertion_failed)(__FILE__, __LINE__, \
+ isc_assertiontype_invariant, #cond), \
+ 0)))
+
+#define ISC_UNREACHABLE() \
+ (isc_assertion_failed(__FILE__, __LINE__, isc_assertiontype_insist, \
+ "unreachable"), \
+ __builtin_unreachable())
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_ASSERTIONS_H */
diff --git a/lib/isc/include/isc/astack.h b/lib/isc/include/isc/astack.h
new file mode 100644
index 0000000..a4f6762
--- /dev/null
+++ b/lib/isc/include/isc/astack.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+#include <inttypes.h>
+
+#include <isc/mem.h>
+#include <isc/types.h>
+
+isc_astack_t *
+isc_astack_new(isc_mem_t *mctx, size_t size);
+/*%<
+ * Allocate and initialize a new array stack of size 'size'.
+ */
+
+void
+isc_astack_destroy(isc_astack_t *stack);
+/*%<
+ * Free an array stack 'stack'.
+ *
+ * Requires:
+ * \li 'stack' is empty.
+ */
+
+bool
+isc_astack_trypush(isc_astack_t *stack, void *obj);
+/*%<
+ * Try to push 'obj' onto array stack 'astack'. On failure, either
+ * because the stack size limit has been reached or because another
+ * thread has already changed the stack pointer, return 'false'.
+ */
+
+void *
+isc_astack_pop(isc_astack_t *stack);
+/*%<
+ * Pop an object off of array stack 'stack'. If the stack is empty,
+ * return NULL.
+ */
diff --git a/lib/isc/include/isc/atomic.h b/lib/isc/include/isc/atomic.h
new file mode 100644
index 0000000..fd29202
--- /dev/null
+++ b/lib/isc/include/isc/atomic.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+#if HAVE_STDATOMIC_H
+#include <stdatomic.h>
+#else /* if HAVE_STDATOMIC_H */
+#include <isc/stdatomic.h>
+#endif /* if HAVE_STDATOMIC_H */
+
+/*
+ * We define a few additional macros to make things easier
+ */
+
+/* Relaxed Memory Ordering */
+
+#define atomic_store_relaxed(o, v) \
+ atomic_store_explicit((o), (v), memory_order_relaxed)
+#define atomic_load_relaxed(o) atomic_load_explicit((o), memory_order_relaxed)
+#define atomic_fetch_add_relaxed(o, v) \
+ atomic_fetch_add_explicit((o), (v), memory_order_relaxed)
+#define atomic_fetch_sub_relaxed(o, v) \
+ atomic_fetch_sub_explicit((o), (v), memory_order_relaxed)
+#define atomic_fetch_or_relaxed(o, v) \
+ atomic_fetch_or_explicit((o), (v), memory_order_relaxed)
+#define atomic_fetch_and_relaxed(o, v) \
+ atomic_fetch_and_explicit((o), (v), memory_order_relaxed)
+#define atomic_exchange_relaxed(o, v) \
+ atomic_exchange_explicit((o), (v), memory_order_relaxed)
+#define atomic_compare_exchange_weak_relaxed(o, e, d) \
+ atomic_compare_exchange_weak_explicit( \
+ (o), (e), (d), memory_order_relaxed, memory_order_relaxed)
+#define atomic_compare_exchange_strong_relaxed(o, e, d) \
+ atomic_compare_exchange_strong_explicit( \
+ (o), (e), (d), memory_order_relaxed, memory_order_relaxed)
+#define atomic_compare_exchange_strong_acq_rel(o, e, d) \
+ atomic_compare_exchange_strong_explicit( \
+ (o), (e), (d), memory_order_acq_rel, memory_order_acquire)
+
+/* Acquire-Release Memory Ordering */
+
+#define atomic_store_release(o, v) \
+ atomic_store_explicit((o), (v), memory_order_release)
+#define atomic_load_acquire(o) atomic_load_explicit((o), memory_order_acquire)
+#define atomic_fetch_add_release(o, v) \
+ atomic_fetch_add_explicit((o), (v), memory_order_release)
+#define atomic_fetch_sub_release(o, v) \
+ atomic_fetch_sub_explicit((o), (v), memory_order_release)
+#define atomic_fetch_and_release(o, v) \
+ atomic_fetch_and_explicit((o), (v), memory_order_release)
+#define atomic_fetch_or_release(o, v) \
+ atomic_fetch_or_explicit((o), (v), memory_order_release)
+#define atomic_exchange_acq_rel(o, v) \
+ atomic_exchange_explicit((o), (v), memory_order_acq_rel)
+#define atomic_fetch_sub_acq_rel(o, v) \
+ atomic_fetch_sub_explicit((o), (v), memory_order_acq_rel)
+#define atomic_compare_exchange_weak_acq_rel(o, e, d) \
+ atomic_compare_exchange_weak_explicit( \
+ (o), (e), (d), memory_order_acq_rel, memory_order_acquire)
+#define atomic_compare_exchange_strong_acq_rel(o, e, d) \
+ atomic_compare_exchange_strong_explicit( \
+ (o), (e), (d), memory_order_acq_rel, memory_order_acquire)
diff --git a/lib/isc/include/isc/backtrace.h b/lib/isc/include/isc/backtrace.h
new file mode 100644
index 0000000..d32748a
--- /dev/null
+++ b/lib/isc/include/isc/backtrace.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \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;
+};
+
+LIBISC_EXTERNAL_DATA extern const int isc__backtrace_nsymbols;
+LIBISC_EXTERNAL_DATA 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/barrier.h b/lib/isc/include/isc/barrier.h
new file mode 100644
index 0000000..1a2a90b
--- /dev/null
+++ b/lib/isc/include/isc/barrier.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+#include <isc/util.h>
+
+#if __SANITIZE_THREAD__ && !defined(WIN32)
+
+#include <pthread.h>
+
+#define isc_barrier_t pthread_barrier_t
+
+#define isc_barrier_init(barrier, count) \
+ pthread_barrier_init(barrier, NULL, count)
+#define isc_barrier_destroy(barrier) pthread_barrier_destroy(barrier)
+#define isc_barrier_wait(barrier) pthread_barrier_wait(barrier)
+
+#else
+
+#include <uv.h>
+
+#define isc_barrier_t uv_barrier_t
+
+#define isc_barrier_init(barrier, count) uv_barrier_init(barrier, count)
+#define isc_barrier_destroy(barrier) uv_barrier_destroy(barrier)
+#define isc_barrier_wait(barrier) uv_barrier_wait(barrier)
+
+#endif /* __SANITIZE_THREAD__ */
diff --git a/lib/isc/include/isc/base32.h b/lib/isc/include/isc/base32.h
new file mode 100644
index 0000000..befe047
--- /dev/null
+++ b/lib/isc/include/isc/base32.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_BASE32_H
+#define ISC_BASE32_H 1
+
+/*! \file */
+
+/*
+ * Routines for manipulating base 32 and base 32 hex encoded data.
+ * Based on RFC 4648.
+ *
+ * Base 32 hex preserves the sort order of data when it is encoded /
+ * decoded.
+ *
+ * Base 32 hex "np" is base 32 hex but no padding is produced or accepted.
+ */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isc_base32_totext(isc_region_t *source, int wordlength, const char *wordbreak,
+ isc_buffer_t *target);
+isc_result_t
+isc_base32hex_totext(isc_region_t *source, int wordlength,
+ const char *wordbreak, isc_buffer_t *target);
+isc_result_t
+isc_base32hexnp_totext(isc_region_t *source, int wordlength,
+ const char *wordbreak, isc_buffer_t *target);
+/*!<
+ * \brief Convert data into base32 encoded text.
+ *
+ * Notes:
+ *\li The base32 encoded text in 'target' will be divided into
+ * words of at most 'wordlength' characters, separated by
+ * the 'wordbreak' string. No parentheses will surround
+ * the text.
+ *
+ * Requires:
+ *\li 'source' is a region containing binary data
+ *\li 'target' is a text buffer containing available space
+ *\li 'wordbreak' points to a null-terminated string of
+ * zero or more whitespace characters
+ *
+ * Ensures:
+ *\li target will contain the base32 encoded version of the data
+ * in source. The 'used' pointer in target will be advanced as
+ * necessary.
+ */
+
+isc_result_t
+isc_base32_decodestring(const char *cstr, isc_buffer_t *target);
+isc_result_t
+isc_base32hex_decodestring(const char *cstr, isc_buffer_t *target);
+isc_result_t
+isc_base32hexnp_decodestring(const char *cstr, isc_buffer_t *target);
+/*!<
+ * \brief Decode a null-terminated string in base32, base32hex, or
+ * base32hex non-padded.
+ *
+ * Requires:
+ *\li 'cstr' is non-null.
+ *\li 'target' is a valid buffer.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- the entire decoded representation of 'cstring'
+ * fit in 'target'.
+ *\li #ISC_R_BADBASE32 -- 'cstr' is not a valid base32 encoding.
+ *
+ * Other error returns are any possible error code from:
+ *\li isc_lex_create(),
+ *\li isc_lex_openbuffer(),
+ *\li isc_base32_tobuffer().
+ */
+
+isc_result_t
+isc_base32_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
+isc_result_t
+isc_base32hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
+isc_result_t
+isc_base32hexnp_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
+/*!<
+ * \brief Convert text encoded in base32, base32hex, or base32hex
+ * non-padded from a lexer context into `target`. If 'length' is
+ * non-negative, it is the expected number of encoded octets to convert.
+ *
+ * If 'length' is -1 then 0 or more encoded octets are expected.
+ * If 'length' is -2 then 1 or more encoded octets are expected.
+ *
+ * Returns:
+ *\li #ISC_R_BADBASE32 -- invalid base32 encoding.
+ *\li #ISC_R_UNEXPECTEDEND: the text does not contain the expected
+ * number of encoded octets.
+ *
+ * Requires:
+ *\li 'lexer' is a valid lexer context
+ *\li 'target' is a buffer containing binary data
+ *\li 'length' is -2, -1, or non-negative
+ *
+ * Ensures:
+ *\li target will contain the data represented by the base32 encoded
+ * string parsed by the lexer. No more than `length` octets will
+ * be read, if `length` is non-negative. The 'used' pointer in
+ * 'target' will be advanced as necessary.
+ */
+
+isc_result_t
+isc_base32_decoderegion(isc_region_t *source, isc_buffer_t *target);
+isc_result_t
+isc_base32hex_decoderegion(isc_region_t *source, isc_buffer_t *target);
+isc_result_t
+isc_base32hexnp_decoderegion(isc_region_t *source, isc_buffer_t *target);
+/*!<
+ * \brief Decode a packed (no white space permitted) region in
+ * base32, base32hex or base32hex non-padded.
+ *
+ * Requires:
+ *\li 'source' is a valid region.
+ *\li 'target' is a valid buffer.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- the entire decoded representation of 'cstring'
+ * fit in 'target'.
+ *\li #ISC_R_BADBASE32 -- 'source' is not a valid base32 encoding.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_BASE32_H */
diff --git a/lib/isc/include/isc/base64.h b/lib/isc/include/isc/base64.h
new file mode 100644
index 0000000..057eabb
--- /dev/null
+++ b/lib/isc/include/isc/base64.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_BASE64_H
+#define ISC_BASE64_H 1
+
+/*! \file isc/base64.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isc_base64_totext(isc_region_t *source, int wordlength, const char *wordbreak,
+ isc_buffer_t *target);
+/*!<
+ * \brief Convert data into base64 encoded text.
+ *
+ * Notes:
+ *\li The base64 encoded text in 'target' will be divided into
+ * words of at most 'wordlength' characters, separated by
+ * the 'wordbreak' string. No parentheses will surround
+ * the text.
+ *
+ * Requires:
+ *\li 'source' is a region containing binary data
+ *\li 'target' is a text buffer containing available space
+ *\li 'wordbreak' points to a null-terminated string of
+ * zero or more whitespace characters
+ *
+ * Ensures:
+ *\li target will contain the base64 encoded version of the data
+ * in source. The 'used' pointer in target will be advanced as
+ * necessary.
+ */
+
+isc_result_t
+isc_base64_decodestring(const char *cstr, isc_buffer_t *target);
+/*!<
+ * \brief Decode a null-terminated base64 string.
+ *
+ * Requires:
+ *\li 'cstr' is non-null.
+ *\li 'target' is a valid buffer.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- the entire decoded representation of 'cstring'
+ * fit in 'target'.
+ *\li #ISC_R_BADBASE64 -- 'cstr' is not a valid base64 encoding.
+ *
+ * Other error returns are any possible error code from:
+ *\li isc_lex_create(),
+ *\li isc_lex_openbuffer(),
+ *\li isc_base64_tobuffer().
+ */
+
+isc_result_t
+isc_base64_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
+/*!<
+ * \brief Convert base64 encoded text from a lexer context into
+ * `target`. If 'length' is non-negative, it is the expected number of
+ * encoded octets to convert.
+ *
+ * If 'length' is -1 then 0 or more encoded octets are expected.
+ * If 'length' is -2 then 1 or more encoded octets are expected.
+ *
+ * Returns:
+ *\li #ISC_R_BADBASE64 -- invalid base64 encoding.
+ *\li #ISC_R_UNEXPECTEDEND: the text does not contain the expected
+ * number of encoded octets.
+ *
+ * Requires:
+ *\li 'lexer' is a valid lexer context
+ *\li 'target' is a buffer containing binary data
+ *\li 'length' is -2, -1, or non-negative
+ *
+ * Ensures:
+ *\li target will contain the data represented by the base64 encoded
+ * string parsed by the lexer. No more than `length` octets will
+ * be read, if `length` is non-negative. The 'used' pointer in
+ * 'target' will be advanced as necessary.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_BASE64_H */
diff --git a/lib/isc/include/isc/bind9.h b/lib/isc/include/isc/bind9.h
new file mode 100644
index 0000000..3c25a76
--- /dev/null
+++ b/lib/isc/include/isc/bind9.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_BIND9_H
+#define ISC_BIND9_H 1
+
+#include <stdbool.h>
+
+#include <isc/platform.h>
+
+/*
+ * This determines whether we are using the libisc/libdns libraries
+ * in BIND9 or in some other application. For BIND9 (named and related
+ * tools) it must be set to true at runtime. Export library clients
+ * will call isc_lib_register(), which will set it to false.
+ */
+LIBISC_EXTERNAL_DATA extern bool isc_bind9;
+
+#endif /* ISC_BIND9_H */
diff --git a/lib/isc/include/isc/buffer.h b/lib/isc/include/isc/buffer.h
new file mode 100644
index 0000000..f3becae
--- /dev/null
+++ b/lib/isc/include/isc/buffer.h
@@ -0,0 +1,1103 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_BUFFER_H
+#define ISC_BUFFER_H 1
+
+/*****
+***** Module Info
+*****/
+
+/*! \file isc/buffer.h
+ *
+ * \brief A buffer is a region of memory, together with a set of related
+ * subregions. Buffers are used for parsing and I/O operations.
+ *
+ * The 'used region' and the 'available region' are disjoint, and their
+ * union is the buffer's region. The used region extends from the beginning
+ * of the buffer region to the last used byte. The available region
+ * extends from one byte greater than the last used byte to the end of the
+ * buffer's region. The size of the used region can be changed using various
+ * buffer commands. Initially, the used region is empty.
+ *
+ * The used region is further subdivided into two disjoint regions: the
+ * 'consumed region' and the 'remaining region'. The union of these two
+ * regions is the used region. The consumed region extends from the beginning
+ * of the used region to the byte before the 'current' offset (if any). The
+ * 'remaining' region extends from the current offset to the end of the used
+ * region. The size of the consumed region can be changed using various
+ * buffer commands. Initially, the consumed region is empty.
+ *
+ * The 'active region' is an (optional) subregion of the remaining region.
+ * It extends from the current offset to an offset in the remaining region
+ * that is selected with isc_buffer_setactive(). Initially, the active region
+ * is empty. If the current offset advances beyond the chosen offset, the
+ * active region will also be empty.
+ *
+ * \verbatim
+ * /------------entire length---------------\
+ * /----- used region -----\/-- available --\
+ * +----------------------------------------+
+ * | consumed | remaining | |
+ * +----------------------------------------+
+ * a b c d e
+ *
+ * a == base of buffer.
+ * b == current pointer. Can be anywhere between a and d.
+ * c == active pointer. Meaningful between b and d.
+ * d == used pointer.
+ * e == length of buffer.
+ *
+ * a-e == entire length of buffer.
+ * a-d == used region.
+ * a-b == consumed region.
+ * b-d == remaining region.
+ * b-c == optional active region.
+ *\endverbatim
+ *
+ * The following invariants are maintained by all routines:
+ *
+ *\code
+ * length > 0
+ *
+ * base is a valid pointer to length bytes of memory
+ *
+ * 0 <= used <= length
+ *
+ * 0 <= current <= used
+ *
+ * 0 <= active <= used
+ * (although active < current implies empty active region)
+ *\endcode
+ *
+ * \li MP:
+ * Buffers have no synchronization. Clients must ensure exclusive
+ * access.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Resources:
+ * Memory: 1 pointer + 6 unsigned integers per buffer.
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/assertions.h>
+#include <isc/formatcheck.h>
+#include <isc/lang.h>
+#include <isc/likely.h>
+#include <isc/list.h>
+#include <isc/magic.h>
+#include <isc/types.h>
+
+/*!
+ * To make many functions be inline macros (via \#define) define this.
+ * If it is undefined, a function will be used.
+ */
+/* #define ISC_BUFFER_USEINLINE */
+
+ISC_LANG_BEGINDECLS
+
+/*@{*/
+/*!
+ *** Magic numbers
+ ***/
+#define ISC_BUFFER_MAGIC 0x42756621U /* Buf!. */
+#define ISC_BUFFER_VALID(b) ISC_MAGIC_VALID(b, ISC_BUFFER_MAGIC)
+/*@}*/
+
+/*!
+ * Size granularity for dynamically resizable buffers; when reserving
+ * space in a buffer, we round the allocated buffer length up to the
+ * nearest * multiple of this value.
+ */
+#define ISC_BUFFER_INCR 2048
+
+/*
+ * The following macros MUST be used only on valid buffers. It is the
+ * caller's responsibility to ensure this by using the ISC_BUFFER_VALID
+ * check above, or by calling another isc_buffer_*() function (rather than
+ * another macro.)
+ */
+
+/*@{*/
+/*!
+ * Fundamental buffer elements. (A through E in the introductory comment.)
+ */
+#define isc_buffer_base(b) ((void *)(b)->base) /*a*/
+#define isc_buffer_current(b) \
+ ((void *)((unsigned char *)(b)->base + (b)->current)) /*b*/
+#define isc_buffer_active(b) \
+ ((void *)((unsigned char *)(b)->base + (b)->active)) /*c*/
+#define isc_buffer_used(b) \
+ ((void *)((unsigned char *)(b)->base + (b)->used)) /*d*/
+#define isc_buffer_length(b) ((b)->length) /*e*/
+/*@}*/
+
+/*@{*/
+/*!
+ * Derived lengths. (Described in the introductory comment.)
+ */
+#define isc_buffer_usedlength(b) ((b)->used) /* d-a */
+#define isc_buffer_consumedlength(b) ((b)->current) /* b-a */
+#define isc_buffer_remaininglength(b) ((b)->used - (b)->current) /* d-b */
+#define isc_buffer_activelength(b) ((b)->active - (b)->current) /* c-b */
+#define isc_buffer_availablelength(b) ((b)->length - (b)->used) /* e-d */
+/*@}*/
+
+/*!
+ * Note that the buffer structure is public. This is principally so buffer
+ * operations can be implemented using macros. Applications are strongly
+ * discouraged from directly manipulating the structure.
+ */
+
+struct isc_buffer {
+ unsigned int magic;
+ void *base;
+ /*@{*/
+ /*! The following integers are byte offsets from 'base'. */
+ unsigned int length;
+ unsigned int used;
+ unsigned int current;
+ unsigned int active;
+ /*@}*/
+ /*! linkable */
+ ISC_LINK(isc_buffer_t) link;
+ /*! private internal elements */
+ isc_mem_t *mctx;
+ /* automatically realloc buffer at put* */
+ bool autore;
+};
+
+/***
+ *** Functions
+ ***/
+
+void
+isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
+ unsigned int length);
+/*!<
+ * \brief Allocate a dynamic linkable buffer which has "length" bytes in the
+ * data region.
+ *
+ * Requires:
+ *\li "mctx" is valid.
+ *
+ *\li "dynbuffer" is non-NULL, and "*dynbuffer" is NULL.
+ *
+ * Note:
+ *\li Changing the buffer's length field is not permitted.
+ */
+
+isc_result_t
+isc_buffer_reserve(isc_buffer_t **dynbuffer, unsigned int size);
+/*!<
+ * \brief Make "size" bytes of space available in the buffer. The buffer
+ * pointer may move when you call this function.
+ *
+ * Requires:
+ *\li "dynbuffer" is not NULL.
+ *
+ *\li "*dynbuffer" is a valid dynamic buffer.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS - success
+ *\li ISC_R_NOMEMORY - no memory available
+ *
+ * Ensures:
+ *\li "*dynbuffer" will be valid on return and will contain all the
+ * original data. However, the buffer pointer may be moved during
+ * reallocation.
+ */
+
+void
+isc_buffer_free(isc_buffer_t **dynbuffer);
+/*!<
+ * \brief Release resources allocated for a dynamic buffer.
+ *
+ * Requires:
+ *\li "dynbuffer" is not NULL.
+ *
+ *\li "*dynbuffer" is a valid dynamic buffer.
+ *
+ * Ensures:
+ *\li "*dynbuffer" will be NULL on return, and all memory associated with
+ * the dynamic buffer is returned to the memory context used in
+ * isc_buffer_allocate().
+ */
+
+void
+isc__buffer_init(isc_buffer_t *b, void *base, unsigned int length);
+/*!<
+ * \brief Make 'b' refer to the 'length'-byte region starting at base.
+ *
+ * Requires:
+ *
+ *\li 'length' > 0
+ *
+ *\li 'base' is a pointer to a sequence of 'length' bytes.
+ *
+ */
+
+void
+isc__buffer_initnull(isc_buffer_t *b);
+/*!<
+ *\brief Initialize a buffer 'b' with a null data and zero length/
+ */
+
+void
+isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length);
+/*!<
+ * \brief Make 'b' refer to the 'length'-byte region starting at base.
+ * Any existing data will be copied.
+ *
+ * Requires:
+ *
+ *\li 'length' > 0 AND length >= previous length
+ *
+ *\li 'base' is a pointer to a sequence of 'length' bytes.
+ *
+ */
+
+void
+isc__buffer_invalidate(isc_buffer_t *b);
+/*!<
+ * \brief Make 'b' an invalid buffer.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ * Ensures:
+ *\li If assertion checking is enabled, future attempts to use 'b' without
+ * calling isc_buffer_init() on it will cause an assertion failure.
+ */
+
+void
+isc_buffer_setautorealloc(isc_buffer_t *b, bool enable);
+/*!<
+ * \brief Enable or disable autoreallocation on 'b'.
+ *
+ * Requires:
+ *\li 'b' is a valid dynamic buffer (b->mctx != NULL).
+ *
+ */
+
+void
+isc__buffer_region(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the region of 'b'.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'r' points to a region structure.
+ */
+
+void
+isc__buffer_usedregion(const isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the used region of 'b'.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'r' points to a region structure.
+ */
+
+void
+isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the available region of 'b'.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'r' points to a region structure.
+ */
+
+void
+isc__buffer_add(isc_buffer_t *b, unsigned int n);
+/*!<
+ * \brief Increase the 'used' region of 'b' by 'n' bytes.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer
+ *
+ *\li used + n <= length
+ *
+ */
+
+void
+isc__buffer_subtract(isc_buffer_t *b, unsigned int n);
+/*!<
+ * \brief Decrease the 'used' region of 'b' by 'n' bytes.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer
+ *
+ *\li used >= n
+ *
+ */
+
+void
+isc__buffer_clear(isc_buffer_t *b);
+/*!<
+ * \brief Make the used region empty.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer
+ *
+ * Ensures:
+ *
+ *\li used = 0
+ *
+ */
+
+void
+isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the consumed region of 'b'.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'r' points to a region structure.
+ */
+
+void
+isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the remaining region of 'b'.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'r' points to a region structure.
+ */
+
+void
+isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the active region of 'b'.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'r' points to a region structure.
+ */
+
+void
+isc__buffer_setactive(isc_buffer_t *b, unsigned int n);
+/*!<
+ * \brief Sets the end of the active region 'n' bytes after current.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li current + n <= used
+ */
+
+void
+isc__buffer_first(isc_buffer_t *b);
+/*!<
+ * \brief Make the consumed region empty.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer
+ *
+ * Ensures:
+ *
+ *\li current == 0
+ *
+ */
+
+void
+isc__buffer_forward(isc_buffer_t *b, unsigned int n);
+/*!<
+ * \brief Increase the 'consumed' region of 'b' by 'n' bytes.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer
+ *
+ *\li current + n <= used
+ *
+ */
+
+void
+isc__buffer_back(isc_buffer_t *b, unsigned int n);
+/*!<
+ * \brief Decrease the 'consumed' region of 'b' by 'n' bytes.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer
+ *
+ *\li n <= current
+ *
+ */
+
+void
+isc_buffer_compact(isc_buffer_t *b);
+/*!<
+ * \brief Compact the used region by moving the remaining region so it occurs
+ * at the start of the buffer. The used region is shrunk by the size of
+ * the consumed region, and the consumed region is then made empty.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer
+ *
+ * Ensures:
+ *
+ *\li current == 0
+ *
+ *\li The size of the used region is now equal to the size of the remaining
+ * region (as it was before the call). The contents of the used region
+ * are those of the remaining region (as it was before the call).
+ */
+
+uint8_t
+isc_buffer_getuint8(isc_buffer_t *b);
+/*!<
+ * \brief Read an unsigned 8-bit integer from 'b' and return it.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the remaining region of 'b' is at least 1.
+ *
+ * Ensures:
+ *
+ *\li The current pointer in 'b' is advanced by 1.
+ *
+ * Returns:
+ *
+ *\li A 8-bit unsigned integer.
+ */
+
+void
+isc__buffer_putuint8(isc_buffer_t *b, uint8_t val);
+/*!<
+ * \brief Store an unsigned 8-bit integer from 'val' into 'b'.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the available region of 'b' is at least 1
+ * or the buffer has autoreallocation enabled.
+ *
+ * Ensures:
+ *\li The used pointer in 'b' is advanced by 1.
+ */
+
+uint16_t
+isc_buffer_getuint16(isc_buffer_t *b);
+/*!<
+ * \brief Read an unsigned 16-bit integer in network byte order from 'b',
+ * convert it to host byte order, and return it.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the remaining region of 'b' is at least 2.
+ *
+ * Ensures:
+ *
+ *\li The current pointer in 'b' is advanced by 2.
+ *
+ * Returns:
+ *
+ *\li A 16-bit unsigned integer.
+ */
+
+void
+isc__buffer_putuint16(isc_buffer_t *b, uint16_t val);
+/*!<
+ * \brief Store an unsigned 16-bit integer in host byte order from 'val'
+ * into 'b' in network byte order.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the available region of 'b' is at least 2
+ * or the buffer has autoreallocation enabled.
+ *
+ * Ensures:
+ *\li The used pointer in 'b' is advanced by 2.
+ */
+
+uint32_t
+isc_buffer_getuint32(isc_buffer_t *b);
+/*!<
+ * \brief Read an unsigned 32-bit integer in network byte order from 'b',
+ * convert it to host byte order, and return it.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the remaining region of 'b' is at least 4.
+ *
+ * Ensures:
+ *
+ *\li The current pointer in 'b' is advanced by 4.
+ *
+ * Returns:
+ *
+ *\li A 32-bit unsigned integer.
+ */
+
+void
+isc__buffer_putuint32(isc_buffer_t *b, uint32_t val);
+/*!<
+ * \brief Store an unsigned 32-bit integer in host byte order from 'val'
+ * into 'b' in network byte order.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the available region of 'b' is at least 4
+ * or the buffer has autoreallocation enabled.
+ *
+ * Ensures:
+ *\li The used pointer in 'b' is advanced by 4.
+ */
+
+uint64_t
+isc_buffer_getuint48(isc_buffer_t *b);
+/*!<
+ * \brief Read an unsigned 48-bit integer in network byte order from 'b',
+ * convert it to host byte order, and return it.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the remaining region of 'b' is at least 6.
+ *
+ * Ensures:
+ *
+ *\li The current pointer in 'b' is advanced by 6.
+ *
+ * Returns:
+ *
+ *\li A 48-bit unsigned integer (stored in a 64-bit integer).
+ */
+
+void
+isc__buffer_putuint48(isc_buffer_t *b, uint64_t val);
+/*!<
+ * \brief Store an unsigned 48-bit integer in host byte order from 'val'
+ * into 'b' in network byte order.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the available region of 'b' is at least 6
+ * or the buffer has autoreallocation enabled.
+ *
+ * Ensures:
+ *\li The used pointer in 'b' is advanced by 6.
+ */
+
+void
+isc__buffer_putuint24(isc_buffer_t *b, uint32_t val);
+/*!<
+ * Store an unsigned 24-bit integer in host byte order from 'val'
+ * into 'b' in network byte order.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the available region of 'b' is at least 3
+ * or the buffer has autoreallocation enabled.
+ *
+ * Ensures:
+ *\li The used pointer in 'b' is advanced by 3.
+ */
+
+void
+isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
+ unsigned int length);
+/*!<
+ * \brief Copy 'length' bytes of memory at 'base' into 'b'.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'base' points to 'length' bytes of valid memory.
+ *
+ *\li The length of the available region of 'b' is at least 'length'
+ * or the buffer has autoreallocation enabled.
+ *
+ * Ensures:
+ *\li The used pointer in 'b' is advanced by 'length'.
+ */
+
+void
+isc__buffer_putstr(isc_buffer_t *b, const char *source);
+/*!<
+ * \brief Copy 'source' into 'b', not including terminating NUL.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'source' is a valid NULL terminated string.
+ *
+ *\li The length of the available region of 'b' is at least strlen('source')
+ * or the buffer has autoreallocation enabled.
+ *
+ * Ensures:
+ *\li The used pointer in 'b' is advanced by strlen('source').
+ */
+
+void
+isc_buffer_putdecint(isc_buffer_t *b, int64_t v);
+/*!<
+ * \brief Put decimal representation of 'v' in b
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the available region of 'b' is at least strlen(dec('v'))
+ * or the buffer has autoreallocation enabled.
+ *
+ * Ensures:
+ *\li The used pointer in 'b' is advanced by strlen(dec('v')).
+ */
+
+isc_result_t
+isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r);
+/*!<
+ * \brief Copy the contents of 'r' into 'b'.
+ *
+ * Notes:
+ *\li If 'b' has autoreallocation enabled, and the length of 'r' is greater
+ * than the length of the available region of 'b', 'b' is reallocated.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'r' is a valid region.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOSPACE The available region of 'b' is not
+ * big enough.
+ */
+
+isc_result_t
+isc_buffer_dup(isc_mem_t *mctx, isc_buffer_t **dstp, const isc_buffer_t *src);
+/*!<
+ * \brief Allocate 'dst' and copy used contents of 'src' into it.
+ *
+ * Requires:
+ *\li 'dstp' is not NULL and *dst is NULL.
+ *\li 'src' is a valid buffer.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ */
+
+isc_result_t
+isc_buffer_printf(isc_buffer_t *b, const char *format, ...)
+ ISC_FORMAT_PRINTF(2, 3);
+/*!<
+ * \brief Append a formatted string to the used region of 'b'.
+ *
+ * Notes:
+ *
+ *\li The 'format' argument is a printf(3) string, with additional arguments
+ * as necessary.
+ *
+ *\li If 'b' has autoreallocation enabled, and the length of the formatted
+ * string is greater than the length of the available region of 'b', 'b'
+ * is reallocated.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ * Ensures:
+ *
+ *\li The used pointer in 'b' is advanced by the number of bytes appended
+ * (excluding the terminating NULL byte).
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS Operation succeeded.
+ *\li #ISC_R_NOSPACE 'b' does not allow reallocation and appending the
+ * formatted string to it would cause it to overflow.
+ *\li #ISC_R_NOMEMORY Reallocation failed.
+ *\li #ISC_R_FAILURE Other error occurred.
+ */
+
+ISC_LANG_ENDDECLS
+
+/*
+ * Inline macro versions of the functions. These should never be called
+ * directly by an application, but will be used by the functions within
+ * buffer.c. The callers should always use "isc_buffer_*()" names, never
+ * ones beginning with "isc__"
+ */
+
+/*! \note
+ * XXXDCL Something more could be done with initializing buffers that
+ * point to const data. For example, isc_buffer_constinit() could
+ * set a new boolean flag in the buffer structure indicating whether
+ * the buffer was initialized with that function. * Then if the
+ * boolean were true, the isc_buffer_put* functions could assert a
+ * contractual requirement for a non-const buffer.
+ *
+ * One drawback is that the isc_buffer_* functions (macros) that return
+ * pointers would still need to return non-const pointers to avoid compiler
+ * warnings, so it would be up to code that uses them to have to deal
+ * with the possibility that the buffer was initialized as const --
+ * a problem that they *already* have to deal with but have absolutely
+ * no ability to. With a new isc_buffer_isconst() function returning
+ * true/false, they could at least assert a contractual requirement for
+ * non-const buffers when needed.
+ */
+#define ISC__BUFFER_INIT(_b, _base, _length) \
+ do { \
+ ISC_REQUIRE((_b) != NULL); \
+ (_b)->base = _base; \
+ (_b)->length = (_length); \
+ (_b)->used = 0; \
+ (_b)->current = 0; \
+ (_b)->active = 0; \
+ (_b)->mctx = NULL; \
+ ISC_LINK_INIT(_b, link); \
+ (_b)->magic = ISC_BUFFER_MAGIC; \
+ (_b)->autore = false; \
+ } while (0)
+
+#define ISC__BUFFER_INITNULL(_b) ISC__BUFFER_INIT(_b, NULL, 0)
+
+#define ISC__BUFFER_INVALIDATE(_b) \
+ do { \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ ISC_REQUIRE(!ISC_LINK_LINKED((_b), link)); \
+ ISC_REQUIRE((_b)->mctx == NULL); \
+ (_b)->magic = 0; \
+ (_b)->base = NULL; \
+ (_b)->length = 0; \
+ (_b)->used = 0; \
+ (_b)->current = 0; \
+ (_b)->active = 0; \
+ } while (0)
+
+#define ISC__BUFFER_REGION(_b, _r) \
+ do { \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ ISC_REQUIRE((_r) != NULL); \
+ (_r)->base = (_b)->base; \
+ (_r)->length = (_b)->length; \
+ } while (0)
+
+#define ISC__BUFFER_USEDREGION(_b, _r) \
+ do { \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ ISC_REQUIRE((_r) != NULL); \
+ (_r)->base = (_b)->base; \
+ (_r)->length = (_b)->used; \
+ } while (0)
+
+#define ISC__BUFFER_AVAILABLEREGION(_b, _r) \
+ do { \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ ISC_REQUIRE((_r) != NULL); \
+ (_r)->base = isc_buffer_used(_b); \
+ (_r)->length = isc_buffer_availablelength(_b); \
+ } while (0)
+
+#define ISC__BUFFER_ADD(_b, _n) \
+ do { \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ ISC_REQUIRE((_b)->used + (_n) <= (_b)->length); \
+ (_b)->used += (_n); \
+ } while (0)
+
+#define ISC__BUFFER_SUBTRACT(_b, _n) \
+ do { \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ ISC_REQUIRE((_b)->used >= (_n)); \
+ (_b)->used -= (_n); \
+ if ((_b)->current > (_b)->used) \
+ (_b)->current = (_b)->used; \
+ if ((_b)->active > (_b)->used) \
+ (_b)->active = (_b)->used; \
+ } while (0)
+
+#define ISC__BUFFER_CLEAR(_b) \
+ do { \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ (_b)->used = 0; \
+ (_b)->current = 0; \
+ (_b)->active = 0; \
+ } while (0)
+
+#define ISC__BUFFER_CONSUMEDREGION(_b, _r) \
+ do { \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ ISC_REQUIRE((_r) != NULL); \
+ (_r)->base = (_b)->base; \
+ (_r)->length = (_b)->current; \
+ } while (0)
+
+#define ISC__BUFFER_REMAININGREGION(_b, _r) \
+ do { \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ ISC_REQUIRE((_r) != NULL); \
+ (_r)->base = isc_buffer_current(_b); \
+ (_r)->length = isc_buffer_remaininglength(_b); \
+ } while (0)
+
+#define ISC__BUFFER_ACTIVEREGION(_b, _r) \
+ do { \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ ISC_REQUIRE((_r) != NULL); \
+ if ((_b)->current < (_b)->active) { \
+ (_r)->base = isc_buffer_current(_b); \
+ (_r)->length = isc_buffer_activelength(_b); \
+ } else { \
+ (_r)->base = NULL; \
+ (_r)->length = 0; \
+ } \
+ } while (0)
+
+#define ISC__BUFFER_SETACTIVE(_b, _n) \
+ do { \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ ISC_REQUIRE((_b)->current + (_n) <= (_b)->used); \
+ (_b)->active = (_b)->current + (_n); \
+ } while (0)
+
+#define ISC__BUFFER_FIRST(_b) \
+ do { \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ (_b)->current = 0; \
+ } while (0)
+
+#define ISC__BUFFER_FORWARD(_b, _n) \
+ do { \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ ISC_REQUIRE((_b)->current + (_n) <= (_b)->used); \
+ (_b)->current += (_n); \
+ } while (0)
+
+#define ISC__BUFFER_BACK(_b, _n) \
+ do { \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ ISC_REQUIRE((_n) <= (_b)->current); \
+ (_b)->current -= (_n); \
+ } while (0)
+
+#define ISC__BUFFER_PUTMEM(_b, _base, _length) \
+ do { \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ if (ISC_UNLIKELY((_b)->autore)) { \
+ isc_buffer_t *_tmp = _b; \
+ ISC_REQUIRE(isc_buffer_reserve(&_tmp, _length) == \
+ ISC_R_SUCCESS); \
+ } \
+ ISC_REQUIRE(isc_buffer_availablelength(_b) >= \
+ (unsigned int)_length); \
+ if (_length > 0U) { \
+ memmove(isc_buffer_used(_b), (_base), (_length)); \
+ (_b)->used += (_length); \
+ } \
+ } while (0)
+
+#define ISC__BUFFER_PUTSTR(_b, _source) \
+ do { \
+ unsigned int _length; \
+ unsigned char *_cp; \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ ISC_REQUIRE((_source) != NULL); \
+ _length = (unsigned int)strlen(_source); \
+ if (ISC_UNLIKELY((_b)->autore)) { \
+ isc_buffer_t *_tmp = _b; \
+ ISC_REQUIRE(isc_buffer_reserve(&_tmp, _length) == \
+ ISC_R_SUCCESS); \
+ } \
+ ISC_REQUIRE(isc_buffer_availablelength(_b) >= _length); \
+ _cp = isc_buffer_used(_b); \
+ memmove(_cp, (_source), _length); \
+ (_b)->used += (_length); \
+ } while (0)
+
+#define ISC__BUFFER_PUTUINT8(_b, _val) \
+ do { \
+ unsigned char *_cp; \
+ /* evaluate (_val) only once */ \
+ uint8_t _val2 = (_val); \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ if (ISC_UNLIKELY((_b)->autore)) { \
+ isc_buffer_t *_tmp = _b; \
+ ISC_REQUIRE(isc_buffer_reserve(&_tmp, 1) == \
+ ISC_R_SUCCESS); \
+ } \
+ ISC_REQUIRE(isc_buffer_availablelength(_b) >= 1U); \
+ _cp = isc_buffer_used(_b); \
+ (_b)->used++; \
+ _cp[0] = _val2; \
+ } while (0)
+
+#define ISC__BUFFER_PUTUINT16(_b, _val) \
+ do { \
+ unsigned char *_cp; \
+ /* evaluate (_val) only once */ \
+ uint16_t _val2 = (_val); \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ if (ISC_UNLIKELY((_b)->autore)) { \
+ isc_buffer_t *_tmp = _b; \
+ ISC_REQUIRE(isc_buffer_reserve(&_tmp, 2) == \
+ ISC_R_SUCCESS); \
+ } \
+ ISC_REQUIRE(isc_buffer_availablelength(_b) >= 2U); \
+ _cp = isc_buffer_used(_b); \
+ (_b)->used += 2; \
+ _cp[0] = (unsigned char)(_val2 >> 8); \
+ _cp[1] = (unsigned char)_val2; \
+ } while (0)
+
+#define ISC__BUFFER_PUTUINT24(_b, _val) \
+ do { \
+ unsigned char *_cp; \
+ /* evaluate (_val) only once */ \
+ uint32_t _val2 = (_val); \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ if (ISC_UNLIKELY((_b)->autore)) { \
+ isc_buffer_t *_tmp = _b; \
+ ISC_REQUIRE(isc_buffer_reserve(&_tmp, 3) == \
+ ISC_R_SUCCESS); \
+ } \
+ ISC_REQUIRE(isc_buffer_availablelength(_b) >= 3U); \
+ _cp = isc_buffer_used(_b); \
+ (_b)->used += 3; \
+ _cp[0] = (unsigned char)(_val2 >> 16); \
+ _cp[1] = (unsigned char)(_val2 >> 8); \
+ _cp[2] = (unsigned char)_val2; \
+ } while (0)
+
+#define ISC__BUFFER_PUTUINT32(_b, _val) \
+ do { \
+ unsigned char *_cp; \
+ /* evaluate (_val) only once */ \
+ uint32_t _val2 = (_val); \
+ ISC_REQUIRE(ISC_BUFFER_VALID(_b)); \
+ if (ISC_UNLIKELY((_b)->autore)) { \
+ isc_buffer_t *_tmp = _b; \
+ ISC_REQUIRE(isc_buffer_reserve(&_tmp, 4) == \
+ ISC_R_SUCCESS); \
+ } \
+ ISC_REQUIRE(isc_buffer_availablelength(_b) >= 4U); \
+ _cp = isc_buffer_used(_b); \
+ (_b)->used += 4; \
+ _cp[0] = (unsigned char)(_val2 >> 24); \
+ _cp[1] = (unsigned char)(_val2 >> 16); \
+ _cp[2] = (unsigned char)(_val2 >> 8); \
+ _cp[3] = (unsigned char)_val2; \
+ } while (0)
+
+#if defined(ISC_BUFFER_USEINLINE)
+#define isc_buffer_init ISC__BUFFER_INIT
+#define isc_buffer_initnull ISC__BUFFER_INITNULL
+#define isc_buffer_invalidate ISC__BUFFER_INVALIDATE
+#define isc_buffer_region ISC__BUFFER_REGION
+#define isc_buffer_usedregion ISC__BUFFER_USEDREGION
+#define isc_buffer_availableregion ISC__BUFFER_AVAILABLEREGION
+#define isc_buffer_add ISC__BUFFER_ADD
+#define isc_buffer_subtract ISC__BUFFER_SUBTRACT
+#define isc_buffer_clear ISC__BUFFER_CLEAR
+#define isc_buffer_consumedregion ISC__BUFFER_CONSUMEDREGION
+#define isc_buffer_remainingregion ISC__BUFFER_REMAININGREGION
+#define isc_buffer_activeregion ISC__BUFFER_ACTIVEREGION
+#define isc_buffer_setactive ISC__BUFFER_SETACTIVE
+#define isc_buffer_first ISC__BUFFER_FIRST
+#define isc_buffer_forward ISC__BUFFER_FORWARD
+#define isc_buffer_back ISC__BUFFER_BACK
+#define isc_buffer_putmem ISC__BUFFER_PUTMEM
+#define isc_buffer_putstr ISC__BUFFER_PUTSTR
+#define isc_buffer_putuint8 ISC__BUFFER_PUTUINT8
+#define isc_buffer_putuint16 ISC__BUFFER_PUTUINT16
+#define isc_buffer_putuint24 ISC__BUFFER_PUTUINT24
+#define isc_buffer_putuint32 ISC__BUFFER_PUTUINT32
+#else /* if defined(ISC_BUFFER_USEINLINE) */
+#define isc_buffer_init isc__buffer_init
+#define isc_buffer_initnull isc__buffer_initnull
+#define isc_buffer_invalidate isc__buffer_invalidate
+#define isc_buffer_region isc__buffer_region
+#define isc_buffer_usedregion isc__buffer_usedregion
+#define isc_buffer_availableregion isc__buffer_availableregion
+#define isc_buffer_add isc__buffer_add
+#define isc_buffer_subtract isc__buffer_subtract
+#define isc_buffer_clear isc__buffer_clear
+#define isc_buffer_consumedregion isc__buffer_consumedregion
+#define isc_buffer_remainingregion isc__buffer_remainingregion
+#define isc_buffer_activeregion isc__buffer_activeregion
+#define isc_buffer_setactive isc__buffer_setactive
+#define isc_buffer_first isc__buffer_first
+#define isc_buffer_forward isc__buffer_forward
+#define isc_buffer_back isc__buffer_back
+#define isc_buffer_putmem isc__buffer_putmem
+#define isc_buffer_putstr isc__buffer_putstr
+#define isc_buffer_putuint8 isc__buffer_putuint8
+#define isc_buffer_putuint16 isc__buffer_putuint16
+#define isc_buffer_putuint24 isc__buffer_putuint24
+#define isc_buffer_putuint32 isc__buffer_putuint32
+#endif /* if defined(ISC_BUFFER_USEINLINE) */
+
+#define isc_buffer_constinit(_b, _d, _l) \
+ do { \
+ union { \
+ void *_var; \
+ const void *_const; \
+ } _deconst; \
+ _deconst._const = (_d); \
+ isc_buffer_init((_b), _deconst._var, (_l)); \
+ } while (0)
+
+/*
+ * No inline method for this one (yet).
+ */
+#define isc_buffer_putuint48 isc__buffer_putuint48
+
+#endif /* ISC_BUFFER_H */
diff --git a/lib/isc/include/isc/bufferlist.h b/lib/isc/include/isc/bufferlist.h
new file mode 100644
index 0000000..95ad3ef
--- /dev/null
+++ b/lib/isc/include/isc/bufferlist.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_BUFFERLIST_H
+#define ISC_BUFFERLIST_H 1
+
+/*****
+***** Module Info
+*****/
+
+/*! \file isc/bufferlist.h
+ *
+ *
+ *\brief Buffer lists have no synchronization. Clients must ensure
+ * exclusive * access.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+unsigned int
+isc_bufferlist_usedcount(isc_bufferlist_t *bl);
+/*!<
+ * \brief Return the length of the sum of all used regions of all buffers in
+ * the buffer list 'bl'
+ *
+ * Requires:
+ *
+ *\li 'bl' is not NULL.
+ *
+ * Returns:
+ *\li sum of all used regions' lengths.
+ */
+
+unsigned int
+isc_bufferlist_availablecount(isc_bufferlist_t *bl);
+/*!<
+ * \brief Return the length of the sum of all available regions of all buffers
+ * in the buffer list 'bl'
+ *
+ * Requires:
+ *
+ *\li 'bl' is not NULL.
+ *
+ * Returns:
+ *\li sum of all available regions' lengths.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_BUFFERLIST_H */
diff --git a/lib/isc/include/isc/cmocka.h b/lib/isc/include/isc/cmocka.h
new file mode 100644
index 0000000..de86d5a
--- /dev/null
+++ b/lib/isc/include/isc/cmocka.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file isc/cmocka.h */
+
+#pragma once
+
+#include <cmocka.h>
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+/*
+ * Copy the test identified by 'name' from 'tests' to 'selected'.
+ */
+#define cmocka_add_test_byname(tests, name, selected) \
+ _cmocka_add_test_byname(tests, sizeof(tests) / sizeof(tests[0]), name, \
+ selected, \
+ sizeof(selected) / sizeof(selected[0]))
+
+static inline bool
+_cmocka_add_test_byname(const struct CMUnitTest *tests, size_t ntests,
+ const char *name, struct CMUnitTest *selected,
+ size_t nselected) {
+ size_t i, j;
+
+ for (i = 0; i < ntests && tests[i].name != NULL; i++) {
+ if (strcmp(tests[i].name, name) != 0) {
+ continue;
+ }
+ for (j = 0; j < nselected && selected[j].name != NULL; j++) {
+ if (strcmp(tests[j].name, name) == 0) {
+ break;
+ }
+ }
+ if (j < nselected && selected[j].name == NULL) {
+ selected[j] = tests[i];
+ }
+ return (true);
+ }
+ return (false);
+}
+
+ISC_LANG_ENDDECLS
diff --git a/lib/isc/include/isc/commandline.h b/lib/isc/include/isc/commandline.h
new file mode 100644
index 0000000..69143ce
--- /dev/null
+++ b/lib/isc/include/isc/commandline.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_COMMANDLINE_H
+#define ISC_COMMANDLINE_H 1
+
+/*! \file isc/commandline.h */
+
+#include <stdbool.h>
+
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/result.h>
+
+/*% Index into parent argv vector. */
+LIBISC_EXTERNAL_DATA extern int isc_commandline_index;
+/*% Character checked for validity. */
+LIBISC_EXTERNAL_DATA extern int isc_commandline_option;
+/*% Argument associated with option. */
+LIBISC_EXTERNAL_DATA extern char *isc_commandline_argument;
+/*% For printing error messages. */
+LIBISC_EXTERNAL_DATA extern char *isc_commandline_progname;
+/*% Print error message. */
+LIBISC_EXTERNAL_DATA extern bool isc_commandline_errprint;
+/*% Reset getopt. */
+LIBISC_EXTERNAL_DATA extern bool isc_commandline_reset;
+
+ISC_LANG_BEGINDECLS
+
+int
+isc_commandline_parse(int argc, char *const *argv, const char *options);
+/*%<
+ * Parse a command line (similar to getopt())
+ */
+
+isc_result_t
+isc_commandline_strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp,
+ char ***argvp, unsigned int n);
+/*%<
+ * Tokenize the string "s" into whitespace-separated words,
+ * returning the number of words in '*argcp' and an array
+ * of pointers to the words in '*argvp'. The caller
+ * must free the array using isc_mem_free(). The string
+ * is modified in-place.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_COMMANDLINE_H */
diff --git a/lib/isc/include/isc/counter.h b/lib/isc/include/isc/counter.h
new file mode 100644
index 0000000..f61a55b
--- /dev/null
+++ b/lib/isc/include/isc/counter.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_COUNTER_H
+#define ISC_COUNTER_H 1
+
+/*****
+***** Module Info
+*****/
+
+/*! \file isc/counter.h
+ *
+ * \brief The isc_counter_t object is a simplified version of the
+ * isc_quota_t object; it tracks the consumption of limited
+ * resources, returning an error condition when the quota is
+ * exceeded. However, unlike isc_quota_t, attaching and detaching
+ * from a counter object does not increment or decrement the counter.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/types.h>
+
+/*****
+***** Types.
+*****/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp);
+/*%<
+ * Allocate and initialize a counter object.
+ */
+
+isc_result_t
+isc_counter_increment(isc_counter_t *counter);
+/*%<
+ * Increment the counter.
+ *
+ * If the counter limit is nonzero and has been reached, then
+ * return ISC_R_QUOTA, otherwise ISC_R_SUCCESS. (The counter is
+ * incremented regardless of return value.)
+ */
+
+unsigned int
+isc_counter_used(isc_counter_t *counter);
+/*%<
+ * Return the current counter value.
+ */
+
+void
+isc_counter_setlimit(isc_counter_t *counter, int limit);
+/*%<
+ * Set the counter limit.
+ */
+
+void
+isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp);
+/*%<
+ * Attach to a counter object, increasing its reference counter.
+ */
+
+void
+isc_counter_detach(isc_counter_t **counterp);
+/*%<
+ * Detach (and destroy if reference counter has dropped to zero)
+ * a counter object.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_COUNTER_H */
diff --git a/lib/isc/include/isc/crc64.h b/lib/isc/include/isc/crc64.h
new file mode 100644
index 0000000..a3fdfb4
--- /dev/null
+++ b/lib/isc/include/isc/crc64.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_CRC64_H
+#define ISC_CRC64_H 1
+
+/*! \file isc/crc64.h
+ * \brief CRC64 in C
+ */
+
+#include <inttypes.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_crc64_init(uint64_t *crc);
+/*%
+ * Initialize a new CRC.
+ *
+ * Requires:
+ * * 'crc' is not NULL.
+ */
+
+void
+isc_crc64_update(uint64_t *crc, const void *data, size_t len);
+/*%
+ * Add data to the CRC.
+ *
+ * Requires:
+ * * 'crc' is not NULL.
+ * * 'data' is not NULL.
+ */
+
+void
+isc_crc64_final(uint64_t *crc);
+/*%
+ * Finalize the CRC.
+ *
+ * Requires:
+ * * 'crc' is not NULL.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_CRC64_H */
diff --git a/lib/isc/include/isc/deprecated.h b/lib/isc/include/isc/deprecated.h
new file mode 100644
index 0000000..73ce584
--- /dev/null
+++ b/lib/isc/include/isc/deprecated.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_DEPRECATED_H
+#define ISC_DEPRECATED_H
+
+#if (__GNUC__ + 0) > 3
+#define ISC_DEPRECATED __attribute__((deprecated))
+#else /* if (__GNUC__ + 0) > 3 */
+#define ISC_DEPRECATED /* none */
+#endif /* __GNUC__ > 3*/
+
+#endif /* ifndef ISC_DEPRECATED_H */
diff --git a/lib/isc/include/isc/endian.h b/lib/isc/include/isc/endian.h
new file mode 100644
index 0000000..e598a7b
--- /dev/null
+++ b/lib/isc/include/isc/endian.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
+ defined(__OpenBSD__) || defined(__bsdi__)
+
+#include <sys/endian.h>
+
+/*
+ * Recent BSDs should have [bl]e{16,32,64}toh() defined in <sys/endian.h>.
+ * Older ones might not, but these should have the alternatively named
+ * [bl]etoh{16,32,64}() functions defined.
+ */
+#ifndef be16toh
+#define be16toh(x) betoh16(x)
+#define le16toh(x) letoh16(x)
+#define be32toh(x) betoh32(x)
+#define le32toh(x) letoh32(x)
+#define be64toh(x) betoh64(x)
+#define le64toh(x) letoh64(x)
+#endif /* !be16toh */
+
+#elif defined(_WIN32)
+
+/*
+ * Windows is always little-endian and has its own byte-swapping routines, so
+ * use these.
+ */
+
+#include <stdlib.h>
+
+#define htobe16(x) _byteswap_ushort(x)
+#define htole16(x) (x)
+#define be16toh(x) _byteswap_ushort(x)
+#define le16toh(x) (x)
+
+#define htobe32(x) _byteswap_ulong(x)
+#define htole32(x) (x)
+#define be32toh(x) _byteswap_ulong(x)
+#define le32toh(x) (x)
+
+#define htobe64(x) _byteswap_uint64(x)
+#define htole64(x) (x)
+#define be64toh(x) _byteswap_uint64(x)
+#define le64toh(x) (x)
+
+#elif defined __APPLE__
+
+/*
+ * macOS has its own byte-swapping routines, so use these.
+ */
+
+#include <libkern/OSByteOrder.h>
+
+#define htobe16(x) OSSwapHostToBigInt16(x)
+#define htole16(x) OSSwapHostToLittleInt16(x)
+#define be16toh(x) OSSwapBigToHostInt16(x)
+#define le16toh(x) OSSwapLittleToHostInt16(x)
+
+#define htobe32(x) OSSwapHostToBigInt32(x)
+#define htole32(x) OSSwapHostToLittleInt32(x)
+#define be32toh(x) OSSwapBigToHostInt32(x)
+#define le32toh(x) OSSwapLittleToHostInt32(x)
+
+#define htobe64(x) OSSwapHostToBigInt64(x)
+#define htole64(x) OSSwapHostToLittleInt64(x)
+#define be64toh(x) OSSwapBigToHostInt64(x)
+#define le64toh(x) OSSwapLittleToHostInt64(x)
+
+#elif defined(sun) || defined(__sun) || defined(__SVR4)
+
+/*
+ * For Solaris, rely on the fallback definitions below, though use
+ * Solaris-specific versions of bswap_{16,32,64}().
+ */
+
+#include <sys/byteorder.h>
+
+#define bswap_16(x) BSWAP_16(x)
+#define bswap_32(x) BSWAP_32(x)
+#define bswap_64(x) BSWAP_64(x)
+
+#elif defined(__ANDROID__) || defined(__CYGWIN__) || defined(__GNUC__) || \
+ defined(__GNU__)
+
+#include <byteswap.h>
+#include <endian.h>
+
+#else /* if defined(__DragonFly__) || defined(__FreeBSD__) || \
+ * defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) */
+
+#endif /* Specific platform support */
+
+/*
+ * Fallback definitions.
+ */
+
+#include <inttypes.h>
+
+#ifndef bswap_16
+#define bswap_16(x) \
+ ((uint16_t)((((uint16_t)(x)&0xff00) >> 8) | \
+ (((uint16_t)(x)&0x00ff) << 8)))
+#endif /* !bswap_16 */
+
+#ifndef bswap_32
+#define bswap_32(x) \
+ ((uint32_t)((((uint32_t)(x)&0xff000000) >> 24) | \
+ (((uint32_t)(x)&0x00ff0000) >> 8) | \
+ (((uint32_t)(x)&0x0000ff00) << 8) | \
+ (((uint32_t)(x)&0x000000ff) << 24)))
+#endif /* !bswap_32 */
+
+#ifndef bswap_64
+#define bswap_64(x) \
+ ((uint64_t)((((uint64_t)(x)&0xff00000000000000ULL) >> 56) | \
+ (((uint64_t)(x)&0x00ff000000000000ULL) >> 40) | \
+ (((uint64_t)(x)&0x0000ff0000000000ULL) >> 24) | \
+ (((uint64_t)(x)&0x000000ff00000000ULL) >> 8) | \
+ (((uint64_t)(x)&0x00000000ff000000ULL) << 8) | \
+ (((uint64_t)(x)&0x0000000000ff0000ULL) << 24) | \
+ (((uint64_t)(x)&0x000000000000ff00ULL) << 40) | \
+ (((uint64_t)(x)&0x00000000000000ffULL) << 56)))
+#endif /* !bswap_64 */
+
+#ifndef htobe16
+#if WORDS_BIGENDIAN
+
+#define htobe16(x) (x)
+#define htole16(x) bswap_16(x)
+#define be16toh(x) (x)
+#define le16toh(x) bswap_16(x)
+
+#else /* WORDS_BIGENDIAN */
+
+#define htobe16(x) bswap_16(x)
+#define htole16(x) (x)
+#define be16toh(x) bswap_16(x)
+#define le16toh(x) (x)
+
+#endif /* WORDS_BIGENDIAN */
+#endif /* !htobe16 */
+
+#ifndef htobe32
+#if WORDS_BIGENDIAN
+
+#define htobe32(x) (x)
+#define htole32(x) bswap_32(x)
+#define be32toh(x) (x)
+#define le32toh(x) bswap_32(x)
+
+#else /* WORDS_BIGENDIAN */
+
+#define htobe32(x) bswap_32(x)
+#define htole32(x) (x)
+#define be32toh(x) bswap_32(x)
+#define le32toh(x) (x)
+
+#endif /* WORDS_BIGENDIAN */
+#endif /* !htobe32 */
+
+#ifndef htobe64
+#if WORDS_BIGENDIAN
+
+#define htobe64(x) (x)
+#define htole64(x) bswap_64(x)
+#define be64toh(x) (x)
+#define le64toh(x) bswap_64(x)
+
+#else /* WORDS_BIGENDIAN */
+
+#define htobe64(x) bswap_64(x)
+#define htole64(x) (x)
+#define be64toh(x) bswap_64(x)
+#define le64toh(x) (x)
+
+#endif /* WORDS_BIGENDIAN */
+#endif /* !htobe64 */
diff --git a/lib/isc/include/isc/errno.h b/lib/isc/include/isc/errno.h
new file mode 100644
index 0000000..1b058dd
--- /dev/null
+++ b/lib/isc/include/isc/errno.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_ERRNO_H
+#define ISC_ERRNO_H 1
+
+/*! \file isc/file.h */
+
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_errno_toresult(int err);
+/*!<
+ * \brief Convert a POSIX errno value to an ISC result code.
+ */
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_ERRNO_H */
diff --git a/lib/isc/include/isc/error.h b/lib/isc/include/isc/error.h
new file mode 100644
index 0000000..4f6fba3
--- /dev/null
+++ b/lib/isc/include/isc/error.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_ERROR_H
+#define ISC_ERROR_H 1
+
+/*! \file isc/error.h */
+
+#include <stdarg.h>
+
+#include <isc/formatcheck.h>
+#include <isc/lang.h>
+#include <isc/likely.h>
+#include <isc/platform.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef void (*isc_errorcallback_t)(const char *, int, const char *, va_list);
+
+/*% set unexpected error */
+void isc_error_setunexpected(isc_errorcallback_t);
+
+/*% set fatal error */
+void isc_error_setfatal(isc_errorcallback_t);
+
+/*% unexpected error */
+void
+isc_error_unexpected(const char *, int, const char *, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+
+/*% fatal error */
+ISC_PLATFORM_NORETURN_PRE void
+isc_error_fatal(const char *, int, const char *, ...)
+ ISC_FORMAT_PRINTF(3, 4) ISC_PLATFORM_NORETURN_POST;
+
+/*% runtimecheck error */
+ISC_PLATFORM_NORETURN_PRE void
+isc_error_runtimecheck(const char *, int,
+ const char *) ISC_PLATFORM_NORETURN_POST;
+
+#define ISC_ERROR_RUNTIMECHECK(cond) \
+ ((void)(ISC_LIKELY(cond) || \
+ ((isc_error_runtimecheck)(__FILE__, __LINE__, #cond), 0)))
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_ERROR_H */
diff --git a/lib/isc/include/isc/event.h b/lib/isc/include/isc/event.h
new file mode 100644
index 0000000..e79a8d8
--- /dev/null
+++ b/lib/isc/include/isc/event.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_EVENT_H
+#define ISC_EVENT_H 1
+
+/*! \file isc/event.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*****
+***** Events.
+*****/
+
+typedef void (*isc_eventdestructor_t)(isc_event_t *);
+
+#define ISC_EVENT_COMMON(ltype) \
+ size_t ev_size; \
+ unsigned int ev_attributes; \
+ void *ev_tag; \
+ isc_eventtype_t ev_type; \
+ isc_taskaction_t ev_action; \
+ void *ev_arg; \
+ void *ev_sender; \
+ isc_eventdestructor_t ev_destroy; \
+ void *ev_destroy_arg; \
+ ISC_LINK(ltype) ev_link; \
+ ISC_LINK(ltype) ev_ratelink
+
+/*%
+ * Attributes matching a mask of 0x000000ff are reserved for the task library's
+ * definition. Attributes of 0xffffff00 may be used by the application
+ * or non-ISC libraries.
+ */
+#define ISC_EVENTATTR_NOPURGE 0x00000001
+
+/*%
+ * The ISC_EVENTATTR_CANCELED attribute is intended to indicate
+ * that an event is delivered as a result of a canceled operation
+ * rather than successful completion, by mutual agreement
+ * between the sender and receiver. It is not set or used by
+ * the task system.
+ */
+#define ISC_EVENTATTR_CANCELED 0x00000002
+
+#define ISC_EVENT_INIT(event, sz, at, ta, ty, ac, ar, sn, df, da) \
+ do { \
+ (event)->ev_size = (sz); \
+ (event)->ev_attributes = (at); \
+ (event)->ev_tag = (ta); \
+ (event)->ev_type = (ty); \
+ (event)->ev_action = (ac); \
+ (event)->ev_arg = (ar); \
+ (event)->ev_sender = (sn); \
+ (event)->ev_destroy = (df); \
+ (event)->ev_destroy_arg = (da); \
+ ISC_LINK_INIT((event), ev_link); \
+ ISC_LINK_INIT((event), ev_ratelink); \
+ } while (0)
+
+/*%
+ * This structure is public because "subclassing" it may be useful when
+ * defining new event types.
+ */
+struct isc_event {
+ ISC_EVENT_COMMON(struct isc_event);
+};
+
+#define ISC_EVENTTYPE_FIRSTEVENT 0x00000000
+#define ISC_EVENTTYPE_LASTEVENT 0xffffffff
+
+#define ISC_EVENT_PTR(p) ((isc_event_t **)(void *)(p))
+
+ISC_LANG_BEGINDECLS
+
+isc_event_t *
+isc_event_allocate(isc_mem_t *mctx, void *sender, isc_eventtype_t type,
+ isc_taskaction_t action, void *arg, size_t size);
+isc_event_t *
+isc_event_constallocate(isc_mem_t *mctx, void *sender, isc_eventtype_t type,
+ isc_taskaction_t action, const void *arg, size_t size);
+/*%<
+ * Allocate an event structure.
+ *
+ * Allocate and initialize in a structure with initial elements
+ * defined by:
+ *
+ * \code
+ * struct {
+ * ISC_EVENT_COMMON(struct isc_event);
+ * ...
+ * };
+ * \endcode
+ *
+ * Requires:
+ *\li 'size' >= sizeof(struct isc_event)
+ *\li 'action' to be non NULL
+ *
+ * Returns:
+ *\li a pointer to a initialized structure of the requested size.
+ *\li NULL if unable to allocate memory.
+ */
+
+void
+isc_event_free(isc_event_t **);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_EVENT_H */
diff --git a/lib/isc/include/isc/eventclass.h b/lib/isc/include/isc/eventclass.h
new file mode 100644
index 0000000..300848a
--- /dev/null
+++ b/lib/isc/include/isc/eventclass.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_EVENTCLASS_H
+#define ISC_EVENTCLASS_H 1
+
+/*! \file isc/eventclass.h
+ ***** Registry of Predefined Event Type Classes
+ *****/
+
+/*%
+ * An event class is an unsigned 16 bit number. Each class may contain up
+ * to 65536 events. An event type is formed by adding the event number
+ * within the class to the class number.
+ *
+ */
+
+#define ISC_EVENTCLASS(eclass) ((eclass) << 16)
+
+/*@{*/
+/*!
+ * Classes < 1024 are reserved for ISC use.
+ * Event classes >= 1024 and <= 65535 are reserved for application use.
+ */
+
+#define ISC_EVENTCLASS_TASK ISC_EVENTCLASS(0)
+#define ISC_EVENTCLASS_TIMER ISC_EVENTCLASS(1)
+#define ISC_EVENTCLASS_SOCKET ISC_EVENTCLASS(2)
+#define ISC_EVENTCLASS_FILE ISC_EVENTCLASS(3)
+#define ISC_EVENTCLASS_DNS ISC_EVENTCLASS(4)
+#define ISC_EVENTCLASS_APP ISC_EVENTCLASS(5)
+#define ISC_EVENTCLASS_OMAPI ISC_EVENTCLASS(6)
+#define ISC_EVENTCLASS_RATELIMITER ISC_EVENTCLASS(7)
+#define ISC_EVENTCLASS_ISCCC ISC_EVENTCLASS(8)
+#define ISC_EVENTCLASS_NS ISC_EVENTCLASS(9)
+/*@}*/
+
+#endif /* ISC_EVENTCLASS_H */
diff --git a/lib/isc/include/isc/file.h b/lib/isc/include/isc/file.h
new file mode 100644
index 0000000..6ef2a39
--- /dev/null
+++ b/lib/isc/include/isc/file.h
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_FILE_H
+#define ISC_FILE_H 1
+
+/*! \file isc/file.h */
+
+#include <stdbool.h>
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/stat.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_file_settime(const char *file, isc_time_t *time);
+
+isc_result_t
+isc_file_mode(const char *file, mode_t *modep);
+
+isc_result_t
+isc_file_getmodtime(const char *file, isc_time_t *time);
+/*!<
+ * \brief Get the time of last modification of a file.
+ *
+ * Notes:
+ *\li The time that is set is relative to the (OS-specific) epoch, as are
+ * all isc_time_t structures.
+ *
+ * Requires:
+ *\li file != NULL.
+ *\li time != NULL.
+ *
+ * Ensures:
+ *\li If the file could not be accessed, 'time' is unchanged.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ * Success.
+ *\li #ISC_R_NOTFOUND
+ * No such file exists.
+ *\li #ISC_R_INVALIDFILE
+ * The path specified was not usable by the operating system.
+ *\li #ISC_R_NOPERM
+ * The file's metainformation could not be retrieved because
+ * permission was denied to some part of the file's path.
+ *\li #ISC_R_IOERROR
+ * Hardware error interacting with the filesystem.
+ *\li #ISC_R_UNEXPECTED
+ * Something totally unexpected happened.
+ *
+ */
+
+isc_result_t
+isc_file_mktemplate(const char *path, char *buf, size_t buflen);
+/*!<
+ * \brief Generate a template string suitable for use with
+ * isc_file_openunique().
+ *
+ * Notes:
+ *\li This function is intended to make creating temporary files
+ * portable between different operating systems.
+ *
+ *\li The path is prepended to an implementation-defined string and
+ * placed into buf. The string has no path characters in it,
+ * and its maximum length is 14 characters plus a NUL. Thus
+ * buflen should be at least strlen(path) + 15 characters or
+ * an error will be returned.
+ *
+ * Requires:
+ *\li buf != NULL.
+ *
+ * Ensures:
+ *\li If result == #ISC_R_SUCCESS:
+ * buf contains a string suitable for use as the template argument
+ * to isc_file_openunique().
+ *
+ *\li If result != #ISC_R_SUCCESS:
+ * buf is unchanged.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success.
+ *\li #ISC_R_NOSPACE buflen indicates buf is too small for the catenation
+ * of the path with the internal template string.
+ */
+
+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);
+isc_result_t
+isc_file_bopenunique(char *templet, FILE **fp);
+isc_result_t
+isc_file_bopenuniqueprivate(char *templet, FILE **fp);
+isc_result_t
+isc_file_bopenuniquemode(char *templet, int mode, FILE **fp);
+/*!<
+ * \brief Create and open a file with a unique name based on 'templet'.
+ * isc_file_bopen*() open the file in binary mode in Windows.
+ * isc_file_open*() open the file in text mode in Windows.
+ *
+ * Notes:
+ *\li 'template' is a reserved work in C++. If you want to complain
+ * about the spelling of 'templet', first look it up in the
+ * Merriam-Webster English dictionary. (http://www.m-w.com/)
+ *
+ *\li This function works by using the template to generate file names.
+ * The template must be a writable string, as it is modified in place.
+ * Trailing X characters in the file name (full file name on Unix,
+ * basename on Win32 -- eg, tmp-XXXXXX vs XXXXXX.tmp, respectively)
+ * are replaced with ASCII characters until a non-existent filename
+ * is found. If the template does not include pathname information,
+ * the files in the working directory of the program are searched.
+ *
+ *\li isc_file_mktemplate is a good, portable way to get a template.
+ *
+ * Requires:
+ *\li 'fp' is non-NULL and '*fp' is NULL.
+ *
+ *\li 'template' is non-NULL, and of a form suitable for use by
+ * the system as described above.
+ *
+ * Ensures:
+ *\li If result is #ISC_R_SUCCESS:
+ * *fp points to an stream opening in stdio's "w+" mode.
+ *
+ *\li If result is not #ISC_R_SUCCESS:
+ * *fp is NULL.
+ *
+ * No file is open. Even if one was created (but unable
+ * to be reopened as a stdio FILE pointer) then it has been
+ * removed.
+ *
+ *\li This function does *not* ensure that the template string has not been
+ * modified, even if the operation was unsuccessful.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ * Success.
+ *\li #ISC_R_EXISTS
+ * No file with a unique name could be created based on the
+ * template.
+ *\li #ISC_R_INVALIDFILE
+ * The path specified was not usable by the operating system.
+ *\li #ISC_R_NOPERM
+ * The file could not be created because permission was denied
+ * to some part of the file's path.
+ *\li #ISC_R_IOERROR
+ * Hardware error interacting with the filesystem.
+ *\li #ISC_R_UNEXPECTED
+ * Something totally unexpected happened.
+ */
+
+isc_result_t
+isc_file_remove(const char *filename);
+/*!<
+ * \brief Remove the file named by 'filename'.
+ */
+
+isc_result_t
+isc_file_rename(const char *oldname, const char *newname);
+/*!<
+ * \brief Rename the file 'oldname' to 'newname'.
+ */
+
+bool
+isc_file_exists(const char *pathname);
+/*!<
+ * \brief Return #true if the calling process can tell that the given file
+ * exists. Will not return true if the calling process has insufficient
+ * privileges to search the entire path.
+ */
+
+bool
+isc_file_isabsolute(const char *filename);
+/*!<
+ * \brief Return #true if the given file name is absolute.
+ */
+
+isc_result_t
+isc_file_isplainfile(const char *name);
+
+isc_result_t
+isc_file_isplainfilefd(int fd);
+/*!<
+ * \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_result_t
+isc_file_isdirectory(const char *name);
+/*!<
+ * \brief Check that 'name' exists and is a directory.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ * Success, file is a directory.
+ *\li #ISC_R_INVALIDFILE
+ * File is not a directory.
+ *\li #ISC_R_FILENOTFOUND
+ * File does not exist.
+ *\li other ISC_R_* errors translated from errno
+ * These occur when stat returns -1 and an errno.
+ */
+
+bool
+isc_file_iscurrentdir(const char *filename);
+/*!<
+ * \brief Return #true if the given file name is the current directory (".").
+ */
+
+bool
+isc_file_ischdiridempotent(const char *filename);
+/*%<
+ * Return #true if calling chdir(filename) multiple times will give
+ * the same result as calling it once.
+ */
+
+const char *
+isc_file_basename(const char *filename);
+/*%<
+ * Return the final component of the path in the file name.
+ */
+
+isc_result_t
+isc_file_progname(const char *filename, char *buf, size_t buflen);
+/*!<
+ * \brief Given an operating system specific file name "filename"
+ * referring to a program, return the canonical program name.
+ *
+ * Any directory prefix or executable file name extension (if
+ * used on the OS in case) is stripped. On systems where program
+ * names are case insensitive, the name is canonicalized to all
+ * lower case. The name is written to 'buf', an array of 'buflen'
+ * chars, and null terminated.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOSPACE The name did not fit in 'buf'.
+ */
+
+isc_result_t
+isc_file_template(const char *path, const char *templet, char *buf,
+ size_t buflen);
+/*%<
+ * Create an OS specific template using 'path' to define the directory
+ * 'templet' to describe the filename and store the result in 'buf'
+ * such that path can be renamed to buf atomically.
+ */
+
+isc_result_t
+isc_file_renameunique(const char *file, char *templet);
+/*%<
+ * Rename 'file' using 'templet' as a template for the new file name.
+ */
+
+isc_result_t
+isc_file_absolutepath(const char *filename, char *path, size_t pathlen);
+/*%<
+ * Given a file name, return the fully qualified path to the file.
+ */
+
+/*
+ * XXX We should also have a isc_file_writeeopen() function
+ * for safely open a file in a publicly writable directory
+ * (see write_open() in BIND 8's ns_config.c).
+ */
+
+isc_result_t
+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, const char *path, char **dirname,
+ char const **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_result_t
+isc_file_getsize(const char *file, off_t *size);
+/*%<
+ * Return the size of the file (stored in the parameter pointed
+ * to by 'size') in bytes.
+ *
+ * Returns:
+ * - ISC_R_SUCCESS on success
+ */
+
+isc_result_t
+isc_file_getsizefd(int fd, off_t *size);
+/*%<
+ * Return the size of the file (stored in the parameter pointed
+ * to by 'size') in bytes.
+ *
+ * Returns:
+ * - ISC_R_SUCCESS on success
+ */
+
+void *
+isc_file_mmap(void *addr, size_t len, int prot, int flags, int fd,
+ off_t offset);
+/*%<
+ * Portable front-end to mmap(). If mmap() is not defined on this
+ * platform, then we simulate it by calling malloc() and read().
+ * (In this event, the addr, prot, and flags parameters are ignored).
+ */
+
+int
+isc_file_munmap(void *addr, size_t len);
+/*%<
+ * Portable front-end to munmap(). If munmap() is not defined on
+ * this platform, then we simply free the memory.
+ */
+
+isc_result_t
+isc_file_sanitize(const char *dir, const char *base, const char *ext,
+ char *path, size_t length);
+/*%<
+ * Generate a sanitized filename, such as for MKEYS or NZF files.
+ *
+ * Historically, MKEYS and NZF files used SHA256 hashes of the view
+ * name for the filename; this was to deal with the possibility of
+ * forbidden characters such as "/" being in a view name, and to
+ * avoid problems with case-insensitive file systems.
+ *
+ * Given a basename 'base' and an extension 'ext', this function checks
+ * for the existence of file using the old-style name format in directory
+ * 'dir'. If found, it returns the path to that file. If there is no
+ * file already in place, a new pathname is generated; if the basename
+ * contains any excluded characters, then a truncated SHA256 hash is
+ * used, otherwise the basename is used. The path name is copied
+ * into 'path', which must point to a buffer of at least 'length'
+ * bytes.
+ *
+ * Requires:
+ * - base != NULL
+ * - path != NULL
+ *
+ * Returns:
+ * - ISC_R_SUCCESS on success
+ * - ISC_R_NOSPACE if the resulting path would be longer than 'length'
+ */
+
+bool
+isc_file_isdirwritable(const char *path);
+/*%<
+ * Return true if the path is a directory and is writable
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_FILE_H */
diff --git a/lib/isc/include/isc/formatcheck.h b/lib/isc/include/isc/formatcheck.h
new file mode 100644
index 0000000..28bd573
--- /dev/null
+++ b/lib/isc/include/isc/formatcheck.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_FORMATCHECK_H
+#define ISC_FORMATCHECK_H 1
+
+/*! \file isc/formatcheck.h */
+
+/*%
+ * ISC_FORMAT_PRINTF().
+ *
+ * \li fmt is the location of the format string parameter.
+ * \li args is the location of the first argument (or 0 for no argument
+ * checking).
+ *
+ * Note:
+ * \li The first parameter is 1, not 0.
+ */
+#ifdef __GNUC__
+#define ISC_FORMAT_PRINTF(fmt, args) \
+ __attribute__((__format__(__printf__, fmt, args)))
+#else /* ifdef __GNUC__ */
+#define ISC_FORMAT_PRINTF(fmt, args)
+#endif /* ifdef __GNUC__ */
+
+#endif /* ISC_FORMATCHECK_H */
diff --git a/lib/isc/include/isc/fsaccess.h b/lib/isc/include/isc/fsaccess.h
new file mode 100644
index 0000000..46c8774
--- /dev/null
+++ b/lib/isc/include/isc/fsaccess.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_FSACCESS_H
+#define ISC_FSACCESS_H 1
+
+/*! \file isc/fsaccess.h
+ * \brief The ISC filesystem access module encapsulates the setting of file
+ * and directory access permissions into one API that is meant to be
+ * portable to multiple operating systems.
+ *
+ * The two primary operating system flavors that are initially accommodated
+ * are POSIX and Windows NT 4.0 and later. The Windows NT access model is
+ * considerable more flexible than POSIX's model (as much as I am loathe to
+ * admit it), and so the ISC API has a higher degree of complexity than would
+ * be needed to simply address POSIX's needs.
+ *
+ * The full breadth of NT's flexibility is not available either, for the
+ * present time. Much of it is to provide compatibility with what Unix
+ * programmers are expecting. This is also due to not yet really needing all
+ * of the functionality of an NT system (or, for that matter, a POSIX system)
+ * in BIND9, and so resolving how to handle the various incompatibilities has
+ * been a purely theoretical exercise with no operational experience to
+ * indicate how flawed the thinking may be.
+ *
+ * Some of the more notable dumbing down of NT for this API includes:
+ *
+ *\li Each of FILE_READ_DATA and FILE_READ_EA are set with #ISC_FSACCESS_READ.
+ *
+ * \li All of FILE_WRITE_DATA, FILE_WRITE_EA and FILE_APPEND_DATA are
+ * set with #ISC_FSACCESS_WRITE. FILE_WRITE_ATTRIBUTES is not set
+ * so as to be consistent with Unix, where only the owner of the file
+ * or the superuser can change the attributes/mode of a file.
+ *
+ * \li Both of FILE_ADD_FILE and FILE_ADD_SUBDIRECTORY are set with
+ * #ISC_FSACCESS_CREATECHILD. This is similar to setting the WRITE
+ * permission on a Unix directory.
+ *
+ * \li SYNCHRONIZE is always set for files and directories, unless someone
+ * can give me a reason why this is a bad idea.
+ *
+ * \li READ_CONTROL and FILE_READ_ATTRIBUTES are always set; this is
+ * consistent with Unix, where any file or directory can be stat()'d
+ * unless the directory path disallows complete access somewhere along
+ * the way.
+ *
+ * \li WRITE_DAC is only set for the owner. This too is consistent with
+ * Unix, and is tighter security than allowing anyone else to be
+ * able to set permissions.
+ *
+ * \li DELETE is only set for the owner. On Unix the ability to delete
+ * a file is controlled by the directory permissions, but it isn't
+ * currently clear to me what happens on NT if the directory has
+ * FILE_DELETE_CHILD set but a file within it does not have DELETE
+ * set. Always setting DELETE on the file/directory for the owner
+ * gives maximum flexibility to the owner without exposing the
+ * file to deletion by others.
+ *
+ * \li WRITE_OWNER is never set. This too is consistent with Unix,
+ * and is also tighter security than allowing anyone to change the
+ * ownership of the file apart from the superu..ahem, Administrator.
+ *
+ * \li Inheritance is set to NO_INHERITANCE.
+ *
+ * Unix's dumbing down includes:
+ *
+ * \li The sticky bit cannot be set.
+ *
+ * \li setuid and setgid cannot be set.
+ *
+ * \li Only regular files and directories can be set.
+ *
+ * The rest of this comment discusses a few of the incompatibilities
+ * between the two systems that need more thought if this API is to
+ * be extended to accommodate them.
+ *
+ * The Windows standard access right "DELETE" doesn't have a direct
+ * equivalent in the Unix world, so it isn't clear what should be done
+ * with it.
+ *
+ * The Unix sticky bit is not supported. While NT does have a concept
+ * of allowing users to create files in a directory but not delete or
+ * rename them, it does not have a concept of allowing them to be deleted
+ * if they are owned by the user trying to delete/rename. While it is
+ * probable that something could be cobbled together in NT 5 with inheritance,
+ * it can't really be done in NT 4 as a single property that you could
+ * set on a directory. You'd need to coordinate something with file creation
+ * so that every file created had DELETE set for the owner but no one else.
+ *
+ * On Unix systems, setting #ISC_FSACCESS_LISTDIRECTORY sets READ.
+ * ... setting either #ISC_FSACCESS_CREATECHILD or #ISC_FSACCESS_DELETECHILD
+ * sets WRITE.
+ * ... setting #ISC_FSACCESS_ACCESSCHILD sets EXECUTE.
+ *
+ * On NT systems, setting #ISC_FSACCESS_LISTDIRECTORY sets FILE_LIST_DIRECTORY.
+ * ... setting #ISC_FSACCESS_CREATECHILD sets FILE_CREATE_CHILD independently.
+ * ... setting #ISC_FSACCESS_DELETECHILD sets FILE_DELETE_CHILD independently.
+ * ... setting #ISC_FSACCESS_ACCESSCHILD sets FILE_TRAVERSE.
+ *
+ * Unresolved: XXXDCL
+ * \li What NT access right controls the ability to rename a file?
+ * \li How does DELETE work? If a directory has FILE_DELETE_CHILD but a
+ * file or directory within it does not have DELETE, is that file
+ * or directory deletable?
+ * \li To implement isc_fsaccess_get(), mapping an existing Unix permission
+ * mode_t back to an isc_fsaccess_t is pretty trivial; however, mapping
+ * an NT DACL could be impossible to do in a responsible way.
+ * \li Similarly, trying to implement the functionality of being able to
+ * say "add group writability to whatever permissions already exist"
+ * could be tricky on NT because of the order-of-entry issue combined
+ * with possibly having one or more matching ACEs already explicitly
+ * granting or denying access. Because this functionality is
+ * not yet needed by the ISC, no code has been written to try to
+ * solve this problem.
+ */
+
+#include <inttypes.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*
+ * Trustees.
+ */
+#define ISC_FSACCESS_OWNER 0x1 /*%< User account. */
+#define ISC_FSACCESS_GROUP 0x2 /*%< Primary group owner. */
+#define ISC_FSACCESS_OTHER 0x4 /*%< Not the owner or the group owner. */
+#define ISC_FSACCESS_WORLD 0x7 /*%< User, Group, Other. */
+
+/*
+ * Types of permission.
+ */
+#define ISC_FSACCESS_READ 0x00000001 /*%< File only. */
+#define ISC_FSACCESS_WRITE 0x00000002 /*%< File only. */
+#define ISC_FSACCESS_EXECUTE 0x00000004 /*%< File only. */
+#define ISC_FSACCESS_CREATECHILD 0x00000008 /*%< Dir only. */
+#define ISC_FSACCESS_DELETECHILD 0x00000010 /*%< Dir only. */
+#define ISC_FSACCESS_LISTDIRECTORY 0x00000020 /*%< Dir only. */
+#define ISC_FSACCESS_ACCESSCHILD 0x00000040 /*%< Dir only. */
+
+/*%
+ * Adding any permission bits beyond 0x200 would mean typedef'ing
+ * isc_fsaccess_t as uint64_t, and redefining this value to
+ * reflect the new range of permission types, Probably to 21 for
+ * maximum flexibility. The number of bits has to accommodate all of
+ * the permission types, and three full sets of them have to fit
+ * within an isc_fsaccess_t.
+ */
+#define ISC__FSACCESS_PERMISSIONBITS 10
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_fsaccess_add(int trustee, int permission, isc_fsaccess_t *access);
+
+void
+isc_fsaccess_remove(int trustee, int permission, isc_fsaccess_t *access);
+
+isc_result_t
+isc_fsaccess_set(const char *path, isc_fsaccess_t access);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_FSACCESS_H */
diff --git a/lib/isc/include/isc/fuzz.h b/lib/isc/include/isc/fuzz.h
new file mode 100644
index 0000000..207728e
--- /dev/null
+++ b/lib/isc/include/isc/fuzz.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_FUZZ_H
+#define ISC_FUZZ_H
+
+typedef enum {
+ isc_fuzz_none,
+ isc_fuzz_client,
+ isc_fuzz_tcpclient,
+ isc_fuzz_resolver,
+ isc_fuzz_http,
+ isc_fuzz_rndc
+} isc_fuzztype_t;
+
+#endif /* ISC_FUZZ_H */
diff --git a/lib/isc/include/isc/hash.h b/lib/isc/include/isc/hash.h
new file mode 100644
index 0000000..62ba186
--- /dev/null
+++ b/lib/isc/include/isc/hash.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_HASH_H
+#define ISC_HASH_H 1
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include "isc/lang.h"
+#include "isc/types.h"
+
+/***
+ *** Functions
+ ***/
+ISC_LANG_BEGINDECLS
+
+const void *
+isc_hash_get_initializer(void);
+
+void
+isc_hash_set_initializer(const void *initializer);
+
+#define isc_hash_function isc_hash64
+
+uint32_t
+isc_hash32(const void *data, const size_t length, const bool case_sensitive);
+uint64_t
+isc_hash64(const void *data, const size_t length, const bool case_sensitive);
+/*!<
+ * \brief Calculate a hash over data.
+ *
+ * This hash function is useful for hashtables. The hash function is
+ * opaque and not important to the caller. The returned hash values are
+ * non-deterministic and will have different mapping every time a
+ * process using this library is run, but will have uniform
+ * distribution.
+ *
+ * isc_hash_32/64() calculates the hash from start to end over the
+ * input data.
+ *
+ * 'data' is the data to be hashed.
+ *
+ * 'length' is the size of the data to be hashed.
+ *
+ * 'case_sensitive' specifies whether the hash key should be treated as
+ * case_sensitive values. It should typically be false if the hash key
+ * is a DNS name.
+ *
+ * Returns:
+ * \li 32 or 64-bit hash value
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_HASH_H */
diff --git a/lib/isc/include/isc/heap.h b/lib/isc/include/isc/heap.h
new file mode 100644
index 0000000..d492c60
--- /dev/null
+++ b/lib/isc/include/isc/heap.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_HEAP_H
+#define ISC_HEAP_H 1
+
+/*! \file isc/heap.h */
+
+#include <stdbool.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*%
+ * The comparison function returns true if the first argument has
+ * higher priority than the second argument, and false otherwise.
+ */
+typedef bool (*isc_heapcompare_t)(void *, void *);
+
+/*%
+ * The index function allows the client of the heap to receive a callback
+ * when an item's index number changes. This allows it to maintain
+ * sync with its external state, but still delete itself, since deletions
+ * from the heap require the index be provided.
+ */
+typedef void (*isc_heapindex_t)(void *, unsigned int);
+
+/*%
+ * The heapaction function is used when iterating over the heap.
+ *
+ * NOTE: The heap structure CANNOT BE MODIFIED during the call to
+ * isc_heap_foreach().
+ */
+typedef void (*isc_heapaction_t)(void *, void *);
+
+typedef struct isc_heap isc_heap_t;
+
+void
+isc_heap_create(isc_mem_t *mctx, isc_heapcompare_t compare,
+ isc_heapindex_t index, unsigned int size_increment,
+ isc_heap_t **heapp);
+/*!<
+ * \brief Create a new heap. The heap is implemented using a space-efficient
+ * storage method. When the heap elements are deleted space is not freed
+ * but will be reused when new elements are inserted.
+ *
+ * Heap elements are indexed from 1.
+ *
+ * Requires:
+ *\li "mctx" is valid.
+ *\li "compare" is a function which takes two void * arguments and
+ * returns true if the first argument has a higher priority than
+ * the second, and false otherwise.
+ *\li "index" is a function which takes a void *, and an unsigned int
+ * argument. This function will be called whenever an element's
+ * index value changes, so it may continue to delete itself from the
+ * heap. This option may be NULL if this functionality is unneeded.
+ *\li "size_increment" is a hint about how large the heap should grow
+ * when resizing is needed. If this is 0, a default size will be
+ * used, which is currently 1024, allowing space for an additional 1024
+ * heap elements to be inserted before adding more space.
+ *\li "heapp" is not NULL, and "*heap" is NULL.
+ */
+
+void
+isc_heap_destroy(isc_heap_t **heapp);
+/*!<
+ * \brief Destroys a heap.
+ *
+ * Requires:
+ *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ */
+
+void
+isc_heap_insert(isc_heap_t *heap, void *elt);
+/*!<
+ * \brief Inserts a new element into a heap.
+ *
+ * Requires:
+ *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ */
+
+void
+isc_heap_delete(isc_heap_t *heap, unsigned int index);
+/*!<
+ * \brief Deletes an element from a heap, by element index.
+ *
+ * Requires:
+ *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ *\li "index" is a valid element index, as provided by the "index" callback
+ * provided during heap creation.
+ */
+
+void
+isc_heap_increased(isc_heap_t *heap, unsigned int index);
+/*!<
+ * \brief Indicates to the heap that an element's priority has increased.
+ * This function MUST be called whenever an element has increased in priority.
+ *
+ * Requires:
+ *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ *\li "index" is a valid element index, as provided by the "index" callback
+ * provided during heap creation.
+ */
+
+void
+isc_heap_decreased(isc_heap_t *heap, unsigned int index);
+/*!<
+ * \brief Indicates to the heap that an element's priority has decreased.
+ * This function MUST be called whenever an element has decreased in priority.
+ *
+ * Requires:
+ *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ *\li "index" is a valid element index, as provided by the "index" callback
+ * provided during heap creation.
+ */
+
+void *
+isc_heap_element(isc_heap_t *heap, unsigned int index);
+/*!<
+ * \brief Returns the element for a specific element index.
+ *
+ * Requires:
+ *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ *\li "index" is a valid element index, as provided by the "index" callback
+ * provided during heap creation.
+ *
+ * Returns:
+ *\li A pointer to the element for the element index.
+ */
+
+void
+isc_heap_foreach(isc_heap_t *heap, isc_heapaction_t action, void *uap);
+/*!<
+ * \brief Iterate over the heap, calling an action for each element. The
+ * order of iteration is not sorted.
+ *
+ * Requires:
+ *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ *\li "action" is not NULL, and is a function which takes two arguments.
+ * The first is a void *, representing the element, and the second is
+ * "uap" as provided to isc_heap_foreach.
+ *\li "uap" is a caller-provided argument, and may be NULL.
+ *
+ * Note:
+ *\li The heap structure CANNOT be modified during this iteration. The only
+ * safe function to call while iterating the heap is isc_heap_element().
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_HEAP_H */
diff --git a/lib/isc/include/isc/hex.h b/lib/isc/include/isc/hex.h
new file mode 100644
index 0000000..a0e5e39
--- /dev/null
+++ b/lib/isc/include/isc/hex.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_HEX_H
+#define ISC_HEX_H 1
+
+/*! \file isc/hex.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isc_hex_totext(isc_region_t *source, int wordlength, const char *wordbreak,
+ isc_buffer_t *target);
+/*!<
+ * \brief Convert data into hex encoded text.
+ *
+ * Notes:
+ *\li The hex encoded text in 'target' will be divided into
+ * words of at most 'wordlength' characters, separated by
+ * the 'wordbreak' string. No parentheses will surround
+ * the text.
+ *
+ * Requires:
+ *\li 'source' is a region containing binary data
+ *\li 'target' is a text buffer containing available space
+ *\li 'wordbreak' points to a null-terminated string of
+ * zero or more whitespace characters
+ *
+ * Ensures:
+ *\li target will contain the hex encoded version of the data
+ * in source. The 'used' pointer in target will be advanced as
+ * necessary.
+ */
+
+isc_result_t
+isc_hex_decodestring(const char *cstr, isc_buffer_t *target);
+/*!<
+ * \brief Decode a null-terminated hex string.
+ *
+ * Requires:
+ *\li 'cstr' is non-null.
+ *\li 'target' is a valid buffer.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- the entire decoded representation of 'cstring'
+ * fit in 'target'.
+ *\li #ISC_R_BADHEX -- 'cstr' is not a valid hex encoding.
+ *
+ * Other error returns are any possible error code from:
+ * isc_lex_create(),
+ * isc_lex_openbuffer(),
+ * isc_hex_tobuffer().
+ */
+
+isc_result_t
+isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
+/*!<
+ * \brief Convert hex-encoded text from a lexer context into
+ * `target`. If 'length' is non-negative, it is the expected number of
+ * encoded octets to convert.
+ *
+ * If 'length' is -1 then 0 or more encoded octets are expected.
+ * If 'length' is -2 then 1 or more encoded octets are expected.
+ *
+ * Returns:
+ *\li #ISC_R_BADHEX -- invalid hex encoding
+ *\li #ISC_R_UNEXPECTEDEND: the text does not contain the expected
+ * number of encoded octets.
+ *
+ * Requires:
+ *\li 'lexer' is a valid lexer context
+ *\li 'target' is a buffer containing binary data
+ *\li 'length' is -2, -1, or non-negative
+ *
+ * Ensures:
+ *\li target will contain the data represented by the hex encoded
+ * string parsed by the lexer. No more than `length` octets will
+ * be read, if `length` is non-negative. The 'used' pointer in
+ * 'target' will be advanced as necessary.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_HEX_H */
diff --git a/lib/isc/include/isc/hmac.h b/lib/isc/include/isc/hmac.h
new file mode 100644
index 0000000..3d0e741
--- /dev/null
+++ b/lib/isc/include/isc/hmac.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*!
+ * \file isc/hmac.h
+ * \brief This is the header for for message authentication code.
+ */
+
+#pragma once
+
+#include <isc/lang.h>
+#include <isc/md.h>
+#include <isc/platform.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+typedef void isc_hmac_t;
+
+/**
+ * isc_hmac:
+ * @type: the digest type
+ * @key: the key
+ * @keylen: the length of the key
+ * @buf: data to hash
+ * @len: length of the data to hash
+ * @digest: the output buffer
+ * @digestlen: the length of the data written to @digest
+ *
+ * This function computes the message authentication code using a digest type
+ * @type with key @key which is @keylen bytes long from data in @buf which is
+ * @len bytes long, and places the output into @digest, which must have space
+ * for the hash function output (use ISC_MAX_MD_SIZE if unsure). If the
+ * @digestlen parameter is not NULL then the number of bytes of data written
+ * (i.e. the length of the digest) will be written to the @digestlen.
+ */
+isc_result_t
+isc_hmac(const isc_md_type_t *type, const void *key, const int keylen,
+ const unsigned char *buf, const size_t len, unsigned char *digest,
+ unsigned int *digestlen);
+
+/**
+ * isc_hmac_new:
+ *
+ * This function allocates, initializes and returns HMAC context.
+ */
+isc_hmac_t *
+isc_hmac_new(void);
+
+/**
+ * isc_hmac_free:
+ * @md: HMAC context
+ *
+ * This function cleans up HMAC context and frees up the space allocated to it.
+ */
+void
+isc_hmac_free(isc_hmac_t *hmac);
+
+/**
+ * isc_hmac_init:
+ * @md: HMAC context
+ * @key: HMAC key
+ * @keylen: HMAC key length
+ * @type: digest type
+ *
+ * This function sets up HMAC context to use a hash function of @type and key
+ * @key which is @keylen bytes long.
+ */
+
+isc_result_t
+isc_hmac_init(isc_hmac_t *hmac, const void *key, size_t keylen,
+ const isc_md_type_t *type);
+
+/**
+ * isc_hmac_reset:
+ * @hmac: HMAC context
+ *
+ * This function resets the HMAC context. This can be used to reuse an already
+ * existing context.
+ */
+isc_result_t
+isc_hmac_reset(isc_hmac_t *hmac);
+
+/**
+ * isc_hmac_update:
+ * @hmac: HMAC context
+ * @buf: data to hash
+ * @len: length of the data to hash
+ *
+ * This function can be called repeatedly with chunks of the message @buf to be
+ * authenticated which is @len bytes long.
+ */
+isc_result_t
+isc_hmac_update(isc_hmac_t *hmac, const unsigned char *buf, const size_t len);
+
+/**
+ * isc_hmac_final:
+ * @hmac: HMAC context
+ * @digest: the output buffer
+ * @digestlen: the length of the data written to @digest
+ *
+ * This function retrieves the message authentication code from @hmac and places
+ * it in @digest, which must have space for the hash function output. If the
+ * @digestlen parameter is not NULL then the number of bytes of data written
+ * (i.e. the length of the digest) will be written to the @digestlen. After
+ * calling this function no additional calls to isc_hmac_update() can be made.
+ */
+isc_result_t
+isc_hmac_final(isc_hmac_t *hmac, unsigned char *digest,
+ unsigned int *digestlen);
+
+/**
+ * isc_hmac_md_type:
+ * @hmac: HMAC context
+ *
+ * This function return the isc_md_type_t previously set for the supplied
+ * HMAC context or NULL if no isc_md_type_t has been set.
+ */
+const isc_md_type_t *
+isc_hmac_get_md_type(isc_hmac_t *hmac);
+
+/**
+ * isc_hmac_get_size:
+ *
+ * This function return the size of the message digest when passed an isc_hmac_t
+ * structure, i.e. the size of the hash.
+ */
+size_t
+isc_hmac_get_size(isc_hmac_t *hmac);
+
+/**
+ * isc_hmac_get_block_size:
+ *
+ * This function return the block size of the message digest when passed an
+ * isc_hmac_t structure.
+ */
+int
+isc_hmac_get_block_size(isc_hmac_t *hmac);
diff --git a/lib/isc/include/isc/ht.h b/lib/isc/include/isc/ht.h
new file mode 100644
index 0000000..f1386bb
--- /dev/null
+++ b/lib/isc/include/isc/ht.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* ! \file */
+
+#ifndef ISC_HT_H
+#define ISC_HT_H 1
+
+#include <inttypes.h>
+#include <string.h>
+
+#include <isc/result.h>
+#include <isc/types.h>
+
+typedef struct isc_ht isc_ht_t;
+typedef struct isc_ht_iter isc_ht_iter_t;
+
+/*%
+ * Initialize hashtable at *htp, using memory context and size of (1<<bits)
+ *
+ * Requires:
+ *\li 'htp' is not NULL and '*htp' is NULL.
+ *\li 'mctx' is a valid memory context.
+ *\li 'bits' >=1 and 'bits' <=32
+ *
+ */
+void
+isc_ht_init(isc_ht_t **htp, isc_mem_t *mctx, uint8_t bits);
+
+/*%
+ * Destroy hashtable, freeing everything
+ *
+ * Requires:
+ * \li '*htp' is valid hashtable
+ */
+void
+isc_ht_destroy(isc_ht_t **htp);
+
+/*%
+ * Add a node to hashtable, pointed by binary key 'key' of size 'keysize';
+ * set its value to 'value'
+ *
+ * Requires:
+ *\li 'ht' is a valid hashtable
+ *
+ * Returns:
+ *\li #ISC_R_NOMEMORY -- not enough memory to create pool
+ *\li #ISC_R_EXISTS -- node of the same key already exists
+ *\li #ISC_R_SUCCESS -- all is well.
+ */
+isc_result_t
+isc_ht_add(isc_ht_t *ht, const unsigned char *key, uint32_t keysize,
+ void *value);
+
+/*%
+ * Find a node matching 'key'/'keysize' in hashtable 'ht';
+ * if found, set '*valuep' to its value. (If 'valuep' is NULL,
+ * then simply return SUCCESS or NOTFOUND to indicate whether the
+ * key exists in the hashtable.)
+ *
+ * Requires:
+ * \li 'ht' is a valid hashtable
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS -- success
+ * \li #ISC_R_NOTFOUND -- key not found
+ */
+isc_result_t
+isc_ht_find(const isc_ht_t *ht, const unsigned char *key, uint32_t keysize,
+ void **valuep);
+
+/*%
+ * Delete node from hashtable
+ *
+ * Requires:
+ *\li ht is a valid hashtable
+ *
+ * Returns:
+ *\li #ISC_R_NOTFOUND -- key not found
+ *\li #ISC_R_SUCCESS -- all is well
+ */
+isc_result_t
+isc_ht_delete(isc_ht_t *ht, const unsigned char *key, uint32_t keysize);
+
+/*%
+ * Create an iterator for the hashtable; point '*itp' to it.
+ *
+ * Requires:
+ *\li 'ht' is a valid hashtable
+ *\li 'itp' is non NULL and '*itp' is NULL.
+ */
+void
+isc_ht_iter_create(isc_ht_t *ht, isc_ht_iter_t **itp);
+
+/*%
+ * Destroy the iterator '*itp', set it to NULL
+ *
+ * Requires:
+ *\li 'itp' is non NULL and '*itp' is non NULL.
+ */
+void
+isc_ht_iter_destroy(isc_ht_iter_t **itp);
+
+/*%
+ * Set an iterator to the first entry.
+ *
+ * Requires:
+ *\li 'it' is non NULL.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS -- success
+ * \li #ISC_R_NOMORE -- no data in the hashtable
+ */
+isc_result_t
+isc_ht_iter_first(isc_ht_iter_t *it);
+
+/*%
+ * Set an iterator to the next entry.
+ *
+ * Requires:
+ *\li 'it' is non NULL.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS -- success
+ * \li #ISC_R_NOMORE -- end of hashtable reached
+ */
+isc_result_t
+isc_ht_iter_next(isc_ht_iter_t *it);
+
+/*%
+ * Delete current entry and set an iterator to the next entry.
+ *
+ * Requires:
+ *\li 'it' is non NULL.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS -- success
+ * \li #ISC_R_NOMORE -- end of hashtable reached
+ */
+isc_result_t
+isc_ht_iter_delcurrent_next(isc_ht_iter_t *it);
+
+/*%
+ * Set 'value' to the current value under the iterator
+ *
+ * Requires:
+ *\li 'it' is non NULL.
+ *\li 'valuep' is non NULL and '*valuep' is NULL.
+ */
+void
+isc_ht_iter_current(isc_ht_iter_t *it, void **valuep);
+
+/*%
+ * Set 'key' and 'keysize to the current key and keysize for the value
+ * under the iterator
+ *
+ * Requires:
+ *\li 'it' is non NULL.
+ *\li 'key' is non NULL and '*key' is NULL.
+ *\li 'keysize' is non NULL.
+ */
+void
+isc_ht_iter_currentkey(isc_ht_iter_t *it, unsigned char **key, size_t *keysize);
+
+/*%
+ * Returns the number of items in the hashtable.
+ *
+ * Requires:
+ *\li 'ht' is a valid hashtable
+ */
+unsigned int
+isc_ht_count(isc_ht_t *ht);
+#endif /* ifndef ISC_HT_H */
diff --git a/lib/isc/include/isc/httpd.h b/lib/isc/include/isc/httpd.h
new file mode 100644
index 0000000..7b66049
--- /dev/null
+++ b/lib/isc/include/isc/httpd.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_HTTPD_H
+#define ISC_HTTPD_H 1
+
+/*! \file */
+
+#include <stdbool.h>
+
+#include <isc/event.h>
+#include <isc/eventclass.h>
+#include <isc/mutex.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/types.h>
+
+/*%
+ * HTTP urls. These are the URLs we manage, and the function to call to
+ * provide the data for it. We pass in the base url (so the same function
+ * can handle multiple requests), and a structure to fill in to return a
+ * result to the client. We also pass in a pointer to be filled in for
+ * the data cleanup function.
+ */
+struct isc_httpdurl {
+ char *url;
+ isc_httpdaction_t *action;
+ void *action_arg;
+ bool isstatic;
+ isc_time_t loadtime;
+ ISC_LINK(isc_httpdurl_t) link;
+};
+
+#define HTTPD_EVENTCLASS ISC_EVENTCLASS(4300)
+#define HTTPD_SHUTDOWN (HTTPD_EVENTCLASS + 0x0001)
+
+#define ISC_HTTPDMGR_FLAGSHUTTINGDOWN 0x00000001
+
+/*
+ * Create a new http daemon which will send, once every time period,
+ * a http-like header followed by HTTP data.
+ */
+isc_result_t
+isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
+ isc_httpdclientok_t *client_ok,
+ isc_httpdondestroy_t *ondestory, void *cb_arg,
+ isc_timermgr_t *tmgr, isc_httpdmgr_t **httpdp);
+
+void
+isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdp);
+
+isc_result_t
+isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
+ isc_httpdaction_t *func, void *arg);
+
+isc_result_t
+isc_httpdmgr_addurl2(isc_httpdmgr_t *httpdmgr, const char *url, bool isstatic,
+ isc_httpdaction_t *func, void *arg);
+
+isc_result_t
+isc_httpd_response(isc_httpd_t *httpd);
+
+isc_result_t
+isc_httpd_addheader(isc_httpd_t *httpd, const char *name, const char *val);
+
+isc_result_t
+isc_httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val);
+
+isc_result_t
+isc_httpd_endheaders(isc_httpd_t *httpd);
+
+void
+isc_httpd_setfinishhook(void (*fn)(void));
+
+#endif /* ISC_HTTPD_H */
diff --git a/lib/isc/include/isc/interfaceiter.h b/lib/isc/include/isc/interfaceiter.h
new file mode 100644
index 0000000..5f6cbe2
--- /dev/null
+++ b/lib/isc/include/isc/interfaceiter.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_INTERFACEITER_H
+#define ISC_INTERFACEITER_H 1
+
+/*****
+***** Module Info
+*****/
+
+/*! \file isc/interfaceiter.h
+ * \brief Iterates over the list of network interfaces.
+ *
+ * Interfaces whose address family is not supported are ignored and never
+ * returned by the iterator. Interfaces whose netmask, interface flags,
+ * or similar cannot be obtained are also ignored, and the failure is logged.
+ *
+ * Standards:
+ * The API for scanning varies greatly among operating systems.
+ * This module attempts to hide the differences.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <inttypes.h>
+
+#include <isc/lang.h>
+#include <isc/netaddr.h>
+#include <isc/types.h>
+
+/*!
+ * \brief Public structure describing a network interface.
+ */
+
+struct isc_interface {
+ char name[32]; /*%< Interface name, null-terminated. */
+ unsigned int af; /*%< Address family. */
+ isc_netaddr_t address; /*%< Local address. */
+ isc_netaddr_t netmask; /*%< Network mask. */
+ isc_netaddr_t dstaddress; /*%< Destination address
+ * (point-to-point
+ * only). */
+ uint32_t flags; /*%< Flags; see INTERFACE flags. */
+};
+
+/*@{*/
+/*! Interface flags. */
+
+#define INTERFACE_F_UP 0x00000001U
+#define INTERFACE_F_POINTTOPOINT 0x00000002U
+#define INTERFACE_F_LOOPBACK 0x00000004U
+/*@}*/
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp);
+/*!<
+ * \brief Create an iterator for traversing the operating system's list
+ * of network interfaces.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
+ *\li Various network-related errors
+ */
+
+isc_result_t
+isc_interfaceiter_first(isc_interfaceiter_t *iter);
+/*!<
+ * \brief Position the iterator on the first interface.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success.
+ *\li #ISC_R_NOMORE There are no interfaces.
+ */
+
+isc_result_t
+isc_interfaceiter_current(isc_interfaceiter_t *iter, isc_interface_t *ifdata);
+/*!<
+ * \brief Get information about the interface the iterator is currently
+ * positioned at and store it at *ifdata.
+ *
+ * Requires:
+ *\li The iterator has been successfully positioned using
+ * isc_interface_iter_first() / isc_interface_iter_next().
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success.
+ */
+
+isc_result_t
+isc_interfaceiter_next(isc_interfaceiter_t *iter);
+/*!<
+ * \brief Position the iterator on the next interface.
+ *
+ * Requires:
+ * \li The iterator has been successfully positioned using
+ * isc_interface_iter_first() / isc_interface_iter_next().
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success.
+ *\li #ISC_R_NOMORE There are no more interfaces.
+ */
+
+void
+isc_interfaceiter_destroy(isc_interfaceiter_t **iterp);
+/*!<
+ * \brief Destroy the iterator.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_INTERFACEITER_H */
diff --git a/lib/isc/include/isc/iterated_hash.h b/lib/isc/include/isc/iterated_hash.h
new file mode 100644
index 0000000..b5d6ab6
--- /dev/null
+++ b/lib/isc/include/isc/iterated_hash.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+#include <isc/lang.h>
+
+/*
+ * The maximal hash length that can be encoded in a name
+ * using base32hex. floor(255/8)*5
+ */
+#define NSEC3_MAX_HASH_LENGTH 155
+
+/*
+ * The maximum has that can be encoded in a single label using
+ * base32hex. floor(63/8)*5
+ */
+#define NSEC3_MAX_LABEL_HASH 35
+
+ISC_LANG_BEGINDECLS
+
+int
+isc_iterated_hash(unsigned char *out, const unsigned int hashalg,
+ const int iterations, const unsigned char *salt,
+ const int saltlength, const unsigned char *in,
+ const int inlength);
+
+ISC_LANG_ENDDECLS
diff --git a/lib/isc/include/isc/lang.h b/lib/isc/include/isc/lang.h
new file mode 100644
index 0000000..35346db
--- /dev/null
+++ b/lib/isc/include/isc/lang.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_LANG_H
+#define ISC_LANG_H 1
+
+/*! \file isc/lang.h */
+
+#ifdef __cplusplus
+#define ISC_LANG_BEGINDECLS extern "C" {
+#define ISC_LANG_ENDDECLS }
+#else /* ifdef __cplusplus */
+#define ISC_LANG_BEGINDECLS
+#define ISC_LANG_ENDDECLS
+#endif /* ifdef __cplusplus */
+
+#endif /* ISC_LANG_H */
diff --git a/lib/isc/include/isc/lex.h b/lib/isc/include/isc/lex.h
new file mode 100644
index 0000000..0209cbe
--- /dev/null
+++ b/lib/isc/include/isc/lex.h
@@ -0,0 +1,447 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_LEX_H
+#define ISC_LEX_H 1
+
+/*****
+***** Module Info
+*****/
+
+/*! \file isc/lex.h
+ * \brief The "lex" module provides a lightweight tokenizer. It can operate
+ * on files or buffers, and can handle "include". It is designed for
+ * parsing of DNS master files and the BIND configuration file, but
+ * should be general enough to tokenize other things, e.g. HTTP.
+ *
+ * \li MP:
+ * No synchronization is provided. Clients must ensure exclusive
+ * access.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Resources:
+ * TBS
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <stdbool.h>
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/region.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Options
+ ***/
+
+/*@{*/
+/*!
+ * Various options for isc_lex_gettoken().
+ */
+
+#define ISC_LEXOPT_EOL 0x0001 /*%< Want end-of-line token. */
+#define ISC_LEXOPT_EOF 0x0002 /*%< Want end-of-file token. */
+#define ISC_LEXOPT_INITIALWS 0x0004 /*%< Want initial whitespace. */
+#define ISC_LEXOPT_NUMBER 0x0008 /*%< Recognize numbers. */
+#define ISC_LEXOPT_QSTRING 0x0010 /*%< Recognize qstrings. */
+/*@}*/
+
+/*@{*/
+/*!
+ * The ISC_LEXOPT_DNSMULTILINE option handles the processing of '(' and ')' in
+ * the DNS master file format. If this option is set, then the
+ * ISC_LEXOPT_INITIALWS and ISC_LEXOPT_EOL options will be ignored when
+ * the paren count is > 0. To use this option, '(' and ')' must be special
+ * characters.
+ */
+#define ISC_LEXOPT_DNSMULTILINE 0x0020 /*%< Handle '(' and ')'. */
+#define ISC_LEXOPT_NOMORE 0x0040 /*%< Want "no more" token. */
+
+#define ISC_LEXOPT_CNUMBER 0x0080 /*%< Recognize octal and hex. */
+#define ISC_LEXOPT_ESCAPE 0x0100 /*%< Recognize escapes. */
+#define ISC_LEXOPT_QSTRINGMULTILINE 0x0200 /*%< Allow multiline "" strings */
+#define ISC_LEXOPT_OCTAL 0x0400 /*%< Expect a octal number. */
+#define ISC_LEXOPT_BTEXT 0x0800 /*%< Bracketed text. */
+#define ISC_LEXOPT_VPAIR 0x1000 /*%< Recognize value pair. */
+#define ISC_LEXOPT_QVPAIR 0x2000 /*%< Recognize quoted value pair. */
+/*@}*/
+/*@{*/
+/*!
+ * Various commenting styles, which may be changed at any time with
+ * isc_lex_setcomments().
+ */
+
+#define ISC_LEXCOMMENT_C 0x01
+#define ISC_LEXCOMMENT_CPLUSPLUS 0x02
+#define ISC_LEXCOMMENT_SHELL 0x04
+#define ISC_LEXCOMMENT_DNSMASTERFILE 0x08
+/*@}*/
+
+/***
+ *** Types
+ ***/
+
+/*! Lex */
+
+typedef char isc_lexspecials_t[256];
+
+/* Tokens */
+
+typedef enum {
+ isc_tokentype_unknown = 0,
+ isc_tokentype_string = 1,
+ isc_tokentype_number = 2,
+ isc_tokentype_qstring = 3,
+ isc_tokentype_eol = 4,
+ isc_tokentype_eof = 5,
+ isc_tokentype_initialws = 6,
+ isc_tokentype_special = 7,
+ isc_tokentype_nomore = 8,
+ isc_tokentype_btext = 9,
+ isc_tokentype_vpair = 10,
+ isc_tokentype_qvpair = 11,
+} isc_tokentype_t;
+
+typedef union {
+ char as_char;
+ unsigned long as_ulong;
+ isc_region_t as_region;
+ isc_textregion_t as_textregion;
+ void *as_pointer;
+} isc_tokenvalue_t;
+
+typedef struct isc_token {
+ isc_tokentype_t type;
+ isc_tokenvalue_t value;
+} isc_token_t;
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isc_lex_create(isc_mem_t *mctx, size_t max_token, isc_lex_t **lexp);
+/*%<
+ * Create a lexer.
+ *
+ * 'max_token' is a hint of the number of bytes in the largest token.
+ *
+ * Requires:
+ *\li '*lexp' is a valid lexer.
+ *
+ * Ensures:
+ *\li On success, *lexp is attached to the newly created lexer.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+void
+isc_lex_destroy(isc_lex_t **lexp);
+/*%<
+ * Destroy the lexer.
+ *
+ * Requires:
+ *\li '*lexp' is a valid lexer.
+ *
+ * Ensures:
+ *\li *lexp == NULL
+ */
+
+unsigned int
+isc_lex_getcomments(isc_lex_t *lex);
+/*%<
+ * Return the current lexer commenting styles.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ * Returns:
+ *\li The commenting styles which are currently allowed.
+ */
+
+void
+isc_lex_setcomments(isc_lex_t *lex, unsigned int comments);
+/*%<
+ * Set allowed lexer commenting styles.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li 'comments' has meaningful values.
+ */
+
+void
+isc_lex_getspecials(isc_lex_t *lex, isc_lexspecials_t specials);
+/*%<
+ * Put the current list of specials into 'specials'.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ */
+
+void
+isc_lex_setspecials(isc_lex_t *lex, isc_lexspecials_t specials);
+/*!<
+ * The characters in 'specials' are returned as tokens. Along with
+ * whitespace, they delimit strings and numbers.
+ *
+ * Note:
+ *\li Comment processing takes precedence over special character
+ * recognition.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ */
+
+isc_result_t
+isc_lex_openfile(isc_lex_t *lex, const char *filename);
+/*%<
+ * Open 'filename' and make it the current input source for 'lex'.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li filename is a valid C string.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY Out of memory
+ *\li #ISC_R_NOTFOUND File not found
+ *\li #ISC_R_NOPERM No permission to open file
+ *\li #ISC_R_FAILURE Couldn't open file, not sure why
+ *\li #ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_lex_openstream(isc_lex_t *lex, FILE *stream);
+/*%<
+ * Make 'stream' the current input source for 'lex'.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li 'stream' is a valid C stream.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY Out of memory
+ */
+
+isc_result_t
+isc_lex_openbuffer(isc_lex_t *lex, isc_buffer_t *buffer);
+/*%<
+ * Make 'buffer' the current input source for 'lex'.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li 'buffer' is a valid buffer.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY Out of memory
+ */
+
+isc_result_t
+isc_lex_close(isc_lex_t *lex);
+/*%<
+ * Close the most recently opened object (i.e. file or buffer).
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMORE No more input sources
+ */
+
+isc_result_t
+isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp);
+/*%<
+ * Get the next token.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li 'lex' has an input source.
+ *
+ *\li 'options' contains valid options.
+ *
+ *\li '*tokenp' is a valid pointer.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_UNEXPECTEDEND
+ *\li #ISC_R_NOMEMORY
+ *
+ * These two results are returned only if their corresponding lexer
+ * options are not set.
+ *
+ *\li #ISC_R_EOF End of input source
+ *\li #ISC_R_NOMORE No more input sources
+ */
+
+isc_result_t
+isc_lex_getmastertoken(isc_lex_t *lex, isc_token_t *token,
+ isc_tokentype_t expect, bool eol);
+/*%<
+ * Get the next token from a DNS master file type stream. This is a
+ * convenience function that sets appropriate options and handles quoted
+ * strings and end of line correctly for master files. It also ungets
+ * unexpected tokens. If `eol` is set then expect end-of-line otherwise
+ * eol is a error.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li 'token' is a valid pointer
+ *
+ * Returns:
+ *
+ * \li any return code from isc_lex_gettoken().
+ */
+
+isc_result_t
+isc_lex_getoctaltoken(isc_lex_t *lex, isc_token_t *token, bool eol);
+/*%<
+ * Get the next token from a DNS master file type stream. This is a
+ * convenience function that sets appropriate options and handles end
+ * of line correctly for master files. It also ungets unexpected tokens.
+ * If `eol` is set then expect end-of-line otherwise eol is a error.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li 'token' is a valid pointer
+ *
+ * Returns:
+ *
+ * \li any return code from isc_lex_gettoken().
+ */
+
+void
+isc_lex_ungettoken(isc_lex_t *lex, isc_token_t *tokenp);
+/*%<
+ * Unget the current token.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li 'lex' has an input source.
+ *
+ *\li 'tokenp' points to a valid token.
+ *
+ *\li There is no ungotten token already.
+ */
+
+void
+isc_lex_getlasttokentext(isc_lex_t *lex, isc_token_t *tokenp, isc_region_t *r);
+/*%<
+ * Returns a region containing the text of the last token returned.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li 'lex' has an input source.
+ *
+ *\li 'tokenp' points to a valid token.
+ *
+ *\li A token has been gotten and not ungotten.
+ */
+
+char *
+isc_lex_getsourcename(isc_lex_t *lex);
+/*%<
+ * Return the input source name.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ * Returns:
+ * \li source name or NULL if no current source.
+ *\li result valid while current input source exists.
+ */
+
+unsigned long
+isc_lex_getsourceline(isc_lex_t *lex);
+/*%<
+ * Return the input source line number.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ * Returns:
+ *\li Current line number or 0 if no current source.
+ */
+
+isc_result_t
+isc_lex_setsourcename(isc_lex_t *lex, const char *name);
+/*%<
+ * Assigns a new name to the input source.
+ *
+ * Requires:
+ *
+ * \li 'lex' is a valid lexer.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
+ * \li #ISC_R_NOTFOUND - there are no sources.
+ */
+
+isc_result_t
+isc_lex_setsourceline(isc_lex_t *lex, unsigned long line);
+/*%<
+ * Assigns a new line number to the input source. This can be used
+ * when parsing a buffer that's been excerpted from the middle a file,
+ * allowing logged messages to display the correct line number,
+ * rather than the line number within the buffer.
+ *
+ * Requires:
+ *
+ * \li 'lex' is a valid lexer.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOTFOUND - there are no sources.
+ */
+
+bool
+isc_lex_isfile(isc_lex_t *lex);
+/*%<
+ * Return whether the current input source is a file.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ * Returns:
+ * \li #true if the current input is a file,
+ *\li #false otherwise.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_LEX_H */
diff --git a/lib/isc/include/isc/lfsr.h b/lib/isc/include/isc/lfsr.h
new file mode 100644
index 0000000..0e4f7f2
--- /dev/null
+++ b/lib/isc/include/isc/lfsr.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_LFSR_H
+#define ISC_LFSR_H 1
+
+/*! \file isc/lfsr.h */
+
+#include <inttypes.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+typedef struct isc_lfsr isc_lfsr_t;
+
+/*%
+ * This function is called when reseeding is needed. It is allowed to
+ * modify any state in the LFSR in any way it sees fit OTHER THAN "bits".
+ *
+ * It MUST set "count" to a new value or the lfsr will never reseed again.
+ *
+ * Also, a reseed will never occur in the middle of an extraction. This
+ * is purely an optimization, and is probably what one would want.
+ */
+typedef void (*isc_lfsrreseed_t)(isc_lfsr_t *, void *);
+
+/*%
+ * The members of this structure can be used by the application, but care
+ * needs to be taken to not change state once the lfsr is in operation.
+ */
+struct isc_lfsr {
+ uint32_t state; /*%< previous state */
+ unsigned int bits; /*%< length */
+ uint32_t tap; /*%< bit taps */
+ unsigned int count; /*%< reseed count (in BITS!) */
+ isc_lfsrreseed_t reseed; /*%< reseed function */
+ void *arg; /*%< reseed function argument */
+};
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_lfsr_init(isc_lfsr_t *lfsr, uint32_t state, unsigned int bits, uint32_t tap,
+ unsigned int count, isc_lfsrreseed_t reseed, void *arg);
+/*%<
+ * Initialize an LFSR.
+ *
+ * Note:
+ *
+ *\li Putting untrusted values into this function will cause the LFSR to
+ * generate (perhaps) non-maximal length sequences.
+ *
+ * Requires:
+ *
+ *\li lfsr != NULL
+ *
+ *\li 8 <= bits <= 32
+ *
+ *\li tap != 0
+ */
+
+void
+isc_lfsr_generate(isc_lfsr_t *lfsr, void *data, unsigned int count);
+/*%<
+ * Returns "count" bytes of data from the LFSR.
+ *
+ * Requires:
+ *
+ *\li lfsr be valid.
+ *
+ *\li data != NULL.
+ *
+ *\li count > 0.
+ */
+
+void
+isc_lfsr_skip(isc_lfsr_t *lfsr, unsigned int skip);
+/*%<
+ * Skip "skip" states.
+ *
+ * Requires:
+ *
+ *\li lfsr be valid.
+ */
+
+uint32_t
+isc_lfsr_generate32(isc_lfsr_t *lfsr1, isc_lfsr_t *lfsr2);
+/*%<
+ * Given two LFSRs, use the current state from each to skip entries in the
+ * other. The next states are then xor'd together and returned.
+ *
+ * WARNING:
+ *
+ *\li This function is used only for very, very low security data, such
+ * as DNS message IDs where it is desired to have an unpredictable
+ * stream of bytes that are harder to predict than a simple flooding
+ * attack.
+ *
+ * Notes:
+ *
+ *\li Since the current state from each of the LFSRs is used to skip
+ * state in the other, it is important that no state be leaked
+ * from either LFSR.
+ *
+ * Requires:
+ *
+ *\li lfsr1 and lfsr2 be valid.
+ *
+ *\li 1 <= skipbits <= 31
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_LFSR_H */
diff --git a/lib/isc/include/isc/lib.h b/lib/isc/include/isc/lib.h
new file mode 100644
index 0000000..60d638d
--- /dev/null
+++ b/lib/isc/include/isc/lib.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file isc/lib.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+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().
+ */
+
+#ifdef WIN32
+int
+isc_lib_ntservice(int(WINAPI *mainfunc)(int argc, char *argv[]), int argc,
+ char *argv[]);
+/*!<
+ * \brief Execute a special routine needed when running as a Windows Service.
+ */
+#endif /* ifdef WIN32 */
+
+extern void
+isc_enable_constructors(void);
+/*!<
+ * \brief Enable constructor linkage in non-libtool static builds.
+ */
+
+ISC_LANG_ENDDECLS
diff --git a/lib/isc/include/isc/likely.h b/lib/isc/include/isc/likely.h
new file mode 100644
index 0000000..360c383
--- /dev/null
+++ b/lib/isc/include/isc/likely.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_LIKELY_H
+#define ISC_LIKELY_H 1
+
+/*%
+ * Performance
+ */
+#ifdef CPPCHECK
+#define ISC_LIKELY(x) (x)
+#define ISC_UNLIKELY(x) (x)
+#else /* ifdef CPPCHECK */
+#ifdef HAVE_BUILTIN_EXPECT
+#define ISC_LIKELY(x) __builtin_expect(!!(x), 1)
+#define ISC_UNLIKELY(x) __builtin_expect(!!(x), 0)
+#else /* ifdef HAVE_BUILTIN_EXPECT */
+#define ISC_LIKELY(x) (x)
+#define ISC_UNLIKELY(x) (x)
+#endif /* ifdef HAVE_BUILTIN_EXPECT */
+#endif /* ifdef CPPCHECK */
+
+#endif /* ISC_LIKELY_H */
diff --git a/lib/isc/include/isc/list.h b/lib/isc/include/isc/list.h
new file mode 100644
index 0000000..2cf4437
--- /dev/null
+++ b/lib/isc/include/isc/list.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+#include <isc/assertions.h>
+
+#define ISC_LINK_TOMBSTONE(type) ((type *)-1)
+
+#define ISC_LIST_INITIALIZER \
+ { \
+ .head = NULL, .tail = NULL, \
+ }
+#define ISC_LINK_INITIALIZER_TYPE(type) \
+ { \
+ .prev = ISC_LINK_TOMBSTONE(type), \
+ .next = ISC_LINK_TOMBSTONE(type), \
+ }
+#define ISC_LINK_INITIALIZER ISC_LINK_INITIALIZER_TYPE(void)
+
+#ifdef ISC_LIST_CHECKINIT
+#define ISC_LINK_INSIST(x) ISC_INSIST(x)
+#else /* ifdef ISC_LIST_CHECKINIT */
+#define ISC_LINK_INSIST(x)
+#endif /* ifdef ISC_LIST_CHECKINIT */
+
+#define ISC_LIST(type) \
+ struct { \
+ type *head, *tail; \
+ }
+#define ISC_LIST_INIT(list) \
+ do { \
+ (list).head = NULL; \
+ (list).tail = NULL; \
+ } while (0)
+
+#define ISC_LINK(type) \
+ struct { \
+ type *prev, *next; \
+ }
+#define ISC_LINK_INIT_TYPE(elt, link, type) \
+ do { \
+ (elt)->link.prev = ISC_LINK_TOMBSTONE(type); \
+ (elt)->link.next = ISC_LINK_TOMBSTONE(type); \
+ } while (0)
+#define ISC_LINK_INIT(elt, link) ISC_LINK_INIT_TYPE(elt, link, void)
+#define ISC_LINK_LINKED_TYPE(elt, link, type) \
+ ((type *)((elt)->link.prev) != ISC_LINK_TOMBSTONE(type))
+#define ISC_LINK_LINKED(elt, link) ISC_LINK_LINKED_TYPE(elt, link, void)
+
+#define ISC_LIST_HEAD(list) ((list).head)
+#define ISC_LIST_TAIL(list) ((list).tail)
+#define ISC_LIST_EMPTY(list) ((list).head == NULL)
+
+#define __ISC_LIST_PREPENDUNSAFE(list, elt, link) \
+ do { \
+ if ((list).head != NULL) { \
+ (list).head->link.prev = (elt); \
+ } else { \
+ (list).tail = (elt); \
+ } \
+ (elt)->link.prev = NULL; \
+ (elt)->link.next = (list).head; \
+ (list).head = (elt); \
+ } while (0)
+
+#define ISC_LIST_PREPEND(list, elt, link) \
+ do { \
+ ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
+ __ISC_LIST_PREPENDUNSAFE(list, elt, link); \
+ } while (0)
+
+#define ISC_LIST_INITANDPREPEND(list, elt, link) \
+ __ISC_LIST_PREPENDUNSAFE(list, elt, link)
+
+#define __ISC_LIST_APPENDUNSAFE(list, elt, link) \
+ do { \
+ if ((list).tail != NULL) { \
+ (list).tail->link.next = (elt); \
+ } else { \
+ (list).head = (elt); \
+ } \
+ (elt)->link.prev = (list).tail; \
+ (elt)->link.next = NULL; \
+ (list).tail = (elt); \
+ } while (0)
+
+#define ISC_LIST_APPEND(list, elt, link) \
+ do { \
+ ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
+ __ISC_LIST_APPENDUNSAFE(list, elt, link); \
+ } while (0)
+
+#define ISC_LIST_INITANDAPPEND(list, elt, link) \
+ __ISC_LIST_APPENDUNSAFE(list, elt, link)
+
+#define __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type) \
+ do { \
+ if ((elt)->link.next != NULL) { \
+ (elt)->link.next->link.prev = (elt)->link.prev; \
+ } else { \
+ ISC_INSIST((list).tail == (elt)); \
+ (list).tail = (elt)->link.prev; \
+ } \
+ if ((elt)->link.prev != NULL) { \
+ (elt)->link.prev->link.next = (elt)->link.next; \
+ } else { \
+ ISC_INSIST((list).head == (elt)); \
+ (list).head = (elt)->link.next; \
+ } \
+ (elt)->link.prev = ISC_LINK_TOMBSTONE(type); \
+ (elt)->link.next = ISC_LINK_TOMBSTONE(type); \
+ ISC_INSIST((list).head != (elt)); \
+ ISC_INSIST((list).tail != (elt)); \
+ } while (0)
+
+#define __ISC_LIST_UNLINKUNSAFE(list, elt, link) \
+ __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, void)
+
+#define ISC_LIST_UNLINK_TYPE(list, elt, link, type) \
+ do { \
+ ISC_LINK_INSIST(ISC_LINK_LINKED(elt, link)); \
+ __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type); \
+ } while (0)
+#define ISC_LIST_UNLINK(list, elt, link) \
+ ISC_LIST_UNLINK_TYPE(list, elt, link, void)
+
+#define ISC_LIST_PREV(elt, link) ((elt)->link.prev)
+#define ISC_LIST_NEXT(elt, link) ((elt)->link.next)
+
+#define __ISC_LIST_INSERTBEFOREUNSAFE(list, before, elt, link) \
+ do { \
+ if ((before)->link.prev == NULL) { \
+ ISC_LIST_PREPEND(list, elt, link); \
+ } else { \
+ (elt)->link.prev = (before)->link.prev; \
+ (before)->link.prev = (elt); \
+ (elt)->link.prev->link.next = (elt); \
+ (elt)->link.next = (before); \
+ } \
+ } while (0)
+
+#define ISC_LIST_INSERTBEFORE(list, before, elt, link) \
+ do { \
+ ISC_LINK_INSIST(ISC_LINK_LINKED(before, link)); \
+ ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
+ __ISC_LIST_INSERTBEFOREUNSAFE(list, before, elt, link); \
+ } while (0)
+
+#define __ISC_LIST_INSERTAFTERUNSAFE(list, after, elt, link) \
+ do { \
+ if ((after)->link.next == NULL) { \
+ ISC_LIST_APPEND(list, elt, link); \
+ } else { \
+ (elt)->link.next = (after)->link.next; \
+ (after)->link.next = (elt); \
+ (elt)->link.next->link.prev = (elt); \
+ (elt)->link.prev = (after); \
+ } \
+ } while (0)
+
+#define ISC_LIST_INSERTAFTER(list, after, elt, link) \
+ do { \
+ ISC_LINK_INSIST(ISC_LINK_LINKED(after, link)); \
+ ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
+ __ISC_LIST_INSERTAFTERUNSAFE(list, after, elt, link); \
+ } while (0)
+
+#define ISC_LIST_APPENDLIST(list1, list2, link) \
+ do { \
+ if (ISC_LIST_EMPTY(list1)) { \
+ (list1) = (list2); \
+ } else if (!ISC_LIST_EMPTY(list2)) { \
+ (list1).tail->link.next = (list2).head; \
+ (list2).head->link.prev = (list1).tail; \
+ (list1).tail = (list2).tail; \
+ } \
+ (list2).head = NULL; \
+ (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)
+#define ISC_LIST_DEQUEUE(list, elt, link) \
+ ISC_LIST_UNLINK_TYPE(list, elt, link, void)
+#define ISC_LIST_DEQUEUE_TYPE(list, elt, link, type) \
+ ISC_LIST_UNLINK_TYPE(list, elt, link, type)
+#define __ISC_LIST_DEQUEUEUNSAFE(list, elt, link) \
+ __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, void)
+#define __ISC_LIST_DEQUEUEUNSAFE_TYPE(list, elt, link, type) \
+ __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type)
+
+#define ISC_LIST_MOVEUNSAFE(dest, src) \
+ { \
+ (dest).head = (src).head; \
+ (dest).tail = (src).tail; \
+ (src).head = NULL; \
+ (src).tail = NULL; \
+ }
+
+#define ISC_LIST_MOVE(dest, src) \
+ { \
+ INSIST(ISC_LIST_EMPTY(dest)); \
+ ISC_LIST_MOVEUNSAFE(dest, src); \
+ }
diff --git a/lib/isc/include/isc/log.h b/lib/isc/include/isc/log.h
new file mode 100644
index 0000000..289cbd7
--- /dev/null
+++ b/lib/isc/include/isc/log.h
@@ -0,0 +1,848 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_LOG_H
+#define ISC_LOG_H 1
+
+/*! \file isc/log.h */
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <syslog.h> /* XXXDCL NT */
+
+#include <isc/formatcheck.h>
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+
+/*@{*/
+/*!
+ * \brief Severity levels, patterned after Unix's syslog levels.
+ *
+ */
+#define ISC_LOG_DEBUG(level) (level)
+/*!
+ * #ISC_LOG_DYNAMIC can only be used for defining channels with
+ * isc_log_createchannel(), not to specify a level in isc_log_write().
+ */
+#define ISC_LOG_DYNAMIC 0
+#define ISC_LOG_INFO (-1)
+#define ISC_LOG_NOTICE (-2)
+#define ISC_LOG_WARNING (-3)
+#define ISC_LOG_ERROR (-4)
+#define ISC_LOG_CRITICAL (-5)
+/*@}*/
+
+/*@{*/
+/*!
+ * \brief Destinations.
+ */
+#define ISC_LOG_TONULL 1
+#define ISC_LOG_TOSYSLOG 2
+#define ISC_LOG_TOFILE 3
+#define ISC_LOG_TOFILEDESC 4
+/*@}*/
+
+/*@{*/
+/*%
+ * Channel flags.
+ */
+#define ISC_LOG_PRINTTIME 0x00001
+#define ISC_LOG_PRINTLEVEL 0x00002
+#define ISC_LOG_PRINTCATEGORY 0x00004
+#define ISC_LOG_PRINTMODULE 0x00008
+#define ISC_LOG_PRINTTAG 0x00010 /* tag and ":" */
+#define ISC_LOG_PRINTPREFIX 0x00020 /* tag only, no colon */
+#define ISC_LOG_PRINTALL 0x0003F
+#define ISC_LOG_BUFFERED 0x00040
+#define ISC_LOG_DEBUGONLY 0x01000
+#define ISC_LOG_OPENERR 0x08000 /* internal */
+#define ISC_LOG_ISO8601 0x10000 /* if PRINTTIME, use ISO8601 */
+#define ISC_LOG_UTC 0x20000 /* if PRINTTIME, use UTC */
+/*@}*/
+
+/*@{*/
+/*!
+ * \brief Other options.
+ *
+ * XXXDCL INFINITE doesn't yet work. Arguably it isn't needed, but
+ * since I am intend to make large number of versions work efficiently,
+ * INFINITE is going to be trivial to add to that.
+ */
+#define ISC_LOG_ROLLINFINITE (-1)
+#define ISC_LOG_ROLLNEVER (-2)
+#define ISC_LOG_MAX_VERSIONS 256
+/*@}*/
+
+/*@{*/
+/*!
+ * \brief Type of suffix used on rolled log files.
+ */
+typedef enum {
+ isc_log_rollsuffix_increment,
+ isc_log_rollsuffix_timestamp
+} isc_log_rollsuffix_t;
+/*@}*/
+
+/*!
+ * \brief Used to name the categories used by a library.
+ *
+ * An array of isc_logcategory
+ * structures names each category, and the id value is initialized by calling
+ * isc_log_registercategories.
+ */
+struct isc_logcategory {
+ const char *name;
+ unsigned int id;
+};
+
+/*%
+ * Similar to isc_logcategory, but for all the modules a library defines.
+ */
+struct isc_logmodule {
+ const char *name;
+ unsigned int id;
+};
+
+/*%
+ * The isc_logfile structure is initialized as part of an isc_logdestination
+ * before calling isc_log_createchannel().
+ *
+ * When defining an #ISC_LOG_TOFILE
+ * channel the name, versions and maximum_size should be set before calling
+ * isc_log_createchannel(). To define an #ISC_LOG_TOFILEDESC channel set only
+ * the stream before the call.
+ *
+ * Setting maximum_size to zero implies no maximum.
+ */
+typedef struct isc_logfile {
+ FILE *stream; /*%< Initialized to NULL for
+ * #ISC_LOG_TOFILE. */
+ const char *name; /*%< NULL for #ISC_LOG_TOFILEDESC. */
+ int versions; /* >= 0, #ISC_LOG_ROLLNEVER,
+ * #ISC_LOG_ROLLINFINITE. */
+ isc_log_rollsuffix_t suffix;
+ /*%
+ * stdio's ftell is standardized to return a long, which may well not
+ * be big enough for the largest file supportable by the operating
+ * system (though it is _probably_ big enough for the largest log
+ * anyone would want). st_size returned by fstat should be typedef'd
+ * to a size large enough for the largest possible file on a system.
+ */
+ isc_offset_t maximum_size;
+ bool maximum_reached; /*%< Private. */
+} isc_logfile_t;
+
+/*%
+ * Passed to isc_log_createchannel to define the attributes of either
+ * a stdio or a syslog log.
+ */
+typedef union isc_logdestination {
+ isc_logfile_t file;
+ int facility; /* XXXDCL NT */
+} isc_logdestination_t;
+
+/*@{*/
+/*%
+ * The built-in categories of libisc.
+ *
+ * Each library registering categories should provide library_LOGCATEGORY_name
+ * definitions with indexes into its isc_logcategory structure corresponding to
+ * the order of the names.
+ */
+LIBISC_EXTERNAL_DATA extern isc_logcategory_t isc_categories[];
+LIBISC_EXTERNAL_DATA extern isc_log_t *isc_lctx;
+LIBISC_EXTERNAL_DATA extern isc_logmodule_t isc_modules[];
+/*@}*/
+
+/*@{*/
+/*%
+ * Do not log directly to DEFAULT. Use another category. When in doubt,
+ * use GENERAL.
+ */
+#define ISC_LOGCATEGORY_DEFAULT (&isc_categories[0])
+#define ISC_LOGCATEGORY_GENERAL (&isc_categories[1])
+/*@}*/
+
+#define ISC_LOGMODULE_SOCKET (&isc_modules[0])
+#define ISC_LOGMODULE_TIME (&isc_modules[1])
+#define ISC_LOGMODULE_INTERFACE (&isc_modules[2])
+#define ISC_LOGMODULE_TIMER (&isc_modules[3])
+#define ISC_LOGMODULE_FILE (&isc_modules[4])
+#define ISC_LOGMODULE_NETMGR (&isc_modules[5])
+#define ISC_LOGMODULE_OTHER (&isc_modules[6])
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp);
+/*%<
+ * Establish a new logging context, with default channels.
+ *
+ * Notes:
+ *\li isc_log_create() calls isc_logconfig_create(), so see its comment
+ * below for more information.
+ *
+ * Requires:
+ *\li mctx is a valid memory context.
+ *\li lctxp is not null and *lctxp is null.
+ *\li lcfgp is null or lcfgp is not null and *lcfgp is null.
+ *
+ * Ensures:
+ *\li *lctxp will point to a valid logging context if all of the necessary
+ * memory was allocated, or NULL otherwise.
+ *\li *lcfgp will point to a valid logging configuration if all of the
+ * necessary memory was allocated, or NULL otherwise.
+ *\li On failure, no additional memory is allocated.
+ */
+
+void
+isc_logconfig_create(isc_log_t *lctx, isc_logconfig_t **lcfgp);
+/*%<
+ * Create the data structure that holds all of the configurable information
+ * about where messages are actually supposed to be sent -- the information
+ * that could changed based on some configuration file, as opposed to the
+ * the category/module specification of isc_log_[v]write[1] that is compiled
+ * into a program, or the debug_level which is dynamic state information.
+ *
+ * Notes:
+ *\li It is necessary to specify the logging context the configuration
+ * will be used with because the number of categories and modules
+ * needs to be known in order to set the configuration. However,
+ * the configuration is not used by the logging context until the
+ * isc_logconfig_use function is called.
+ *
+ *\li The memory context used for operations that allocate memory for
+ * the configuration is that of the logging context, as specified
+ * in the isc_log_create call.
+ *
+ *\li Four default channels are established:
+ *\verbatim
+ * default_syslog
+ * - log to syslog's daemon facility #ISC_LOG_INFO or higher
+ * default_stderr
+ * - log to stderr #ISC_LOG_INFO or higher
+ * default_debug
+ * - log to stderr #ISC_LOG_DEBUG dynamically
+ * null
+ * - log nothing
+ *\endverbatim
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *\li lcftp is not null and *lcfgp is null.
+ *
+ * Ensures:
+ *\li *lcfgp will point to a valid logging context if all of the necessary
+ * memory was allocated, or NULL otherwise.
+ *\li On failure, no additional memory is allocated.
+ */
+
+void
+isc_logconfig_use(isc_log_t *lctx, isc_logconfig_t *lcfg);
+/*%<
+ * Associate a new configuration with a logging context.
+ *
+ * Notes:
+ *\li This is thread safe. The logging context will lock a mutex
+ * before attempting to swap in the new configuration, and isc_log_doit
+ * (the internal function used by all of isc_log_[v]write[1]) locks
+ * the same lock for the duration of its use of the configuration.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *\li lcfg is a valid logging configuration.
+ *\li lctx is the same configuration given to isc_logconfig_create
+ * when the configuration was created.
+ *
+ * Ensures:
+ *\li Future calls to isc_log_write will use the new configuration.
+ */
+
+void
+isc_log_destroy(isc_log_t **lctxp);
+/*%<
+ * Deallocate the memory associated with a logging context.
+ *
+ * Requires:
+ *\li *lctx is a valid logging context.
+ *
+ * Ensures:
+ *\li All of the memory associated with the logging context is returned
+ * to the free memory pool.
+ *
+ *\li Any open files are closed.
+ *
+ *\li The logging context is marked as invalid.
+ */
+
+void
+isc_logconfig_destroy(isc_logconfig_t **lcfgp);
+/*%<
+ * Destroy a logging configuration.
+ *
+ * Requires:
+ *\li lcfgp is not null and *lcfgp is a valid logging configuration.
+ *\li The logging configuration is not in use by an existing logging context.
+ *
+ * Ensures:
+ *\li All memory allocated for the configuration is freed.
+ *
+ *\li The configuration is marked as invalid.
+ */
+
+void
+isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]);
+/*%<
+ * Identify logging categories a library will use.
+ *
+ * Notes:
+ *\li A category should only be registered once, but no mechanism enforces
+ * this rule.
+ *
+ *\li The end of the categories array is identified by a NULL name.
+ *
+ *\li Because the name is used by #ISC_LOG_PRINTCATEGORY, it should not
+ * be altered or destroyed after isc_log_registercategories().
+ *
+ *\li Because each element of the categories array is used by
+ * isc_log_categorybyname, it should not be altered or destroyed
+ * after registration.
+ *
+ *\li The value of the id integer in each structure is overwritten
+ * by this function, and so id need not be initialized to any particular
+ * value prior to the function call.
+ *
+ *\li A subsequent call to isc_log_registercategories with the same
+ * logging context (but new categories) will cause the last
+ * element of the categories array from the prior call to have
+ * its "name" member changed from NULL to point to the new
+ * categories array, and its "id" member set to UINT_MAX.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *\li categories != NULL.
+ *\li categories[0].name != NULL.
+ *
+ * Ensures:
+ * \li There are references to each category in the logging context,
+ * so they can be used with isc_log_usechannel() and isc_log_write().
+ */
+
+void
+isc_log_registermodules(isc_log_t *lctx, isc_logmodule_t modules[]);
+/*%<
+ * Identify logging categories a library will use.
+ *
+ * Notes:
+ *\li A module should only be registered once, but no mechanism enforces
+ * this rule.
+ *
+ *\li The end of the modules array is identified by a NULL name.
+ *
+ *\li Because the name is used by #ISC_LOG_PRINTMODULE, it should not
+ * be altered or destroyed after isc_log_registermodules().
+ *
+ *\li Because each element of the modules array is used by
+ * isc_log_modulebyname, it should not be altered or destroyed
+ * after registration.
+ *
+ *\li The value of the id integer in each structure is overwritten
+ * by this function, and so id need not be initialized to any particular
+ * value prior to the function call.
+ *
+ *\li A subsequent call to isc_log_registermodules with the same
+ * logging context (but new modules) will cause the last
+ * element of the modules array from the prior call to have
+ * its "name" member changed from NULL to point to the new
+ * modules array, and its "id" member set to UINT_MAX.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *\li modules != NULL.
+ *\li modules[0].name != NULL;
+ *
+ * Ensures:
+ *\li Each module has a reference in the logging context, so they can be
+ * used with isc_log_usechannel() and isc_log_write().
+ */
+
+void
+isc_log_createchannel(isc_logconfig_t *lcfg, const char *name,
+ unsigned int type, int level,
+ const isc_logdestination_t *destination,
+ unsigned int flags);
+/*%<
+ * Specify the parameters of a logging channel.
+ *
+ * Notes:
+ *\li The name argument is copied to memory in the logging context, so
+ * it can be altered or destroyed after isc_log_createchannel().
+ *
+ *\li Defining a very large number of channels will have a performance
+ * impact on isc_log_usechannel(), since the names are searched
+ * linearly until a match is made. This same issue does not affect
+ * isc_log_write, however.
+ *
+ *\li Channel names can be redefined; this is primarily useful for programs
+ * that want their own definition of default_syslog, default_debug
+ * and default_stderr.
+ *
+ *\li Any channel that is redefined will not affect logging that was
+ * already directed to its original definition, _except_ for the
+ * default_stderr channel. This case is handled specially so that
+ * the default logging category can be changed by redefining
+ * default_stderr. (XXXDCL Though now that I think of it, the default
+ * logging category can be changed with only one additional function
+ * call by defining a new channel and then calling isc_log_usechannel()
+ * for #ISC_LOGCATEGORY_DEFAULT.)
+ *
+ *\li Specifying #ISC_LOG_PRINTTIME or #ISC_LOG_PRINTTAG for syslog is
+ * allowed, but probably not what you wanted to do.
+ *
+ * #ISC_LOG_DEBUGONLY will mark the channel as usable only when the
+ * debug level of the logging context (see isc_log_setdebuglevel)
+ * is non-zero.
+ *
+ * Requires:
+ *\li lcfg is a valid logging configuration.
+ *
+ *\li name is not NULL.
+ *
+ *\li type is #ISC_LOG_TOSYSLOG, #ISC_LOG_TOFILE, #ISC_LOG_TOFILEDESC or
+ * #ISC_LOG_TONULL.
+ *
+ *\li destination is not NULL unless type is #ISC_LOG_TONULL.
+ *
+ *\li level is >= #ISC_LOG_CRITICAL (the most negative logging level).
+ *
+ *\li flags does not include any bits aside from the ISC_LOG_PRINT* bits,
+ * #ISC_LOG_DEBUGONLY or #ISC_LOG_BUFFERED.
+ *
+ * Ensures:
+ *\li #ISC_R_SUCCESS
+ * A channel with the given name is usable with
+ * isc_log_usechannel().
+ *
+ *\li #ISC_R_NOMEMORY or #ISC_R_UNEXPECTED
+ * No additional memory is being used by the logging context.
+ * Any channel that previously existed with the given name
+ * is not redefined.
+ */
+
+isc_result_t
+isc_log_usechannel(isc_logconfig_t *lcfg, const char *name,
+ const isc_logcategory_t *category,
+ const isc_logmodule_t *module);
+/*%<
+ * Associate a named logging channel with a category and module that
+ * will use it.
+ *
+ * Notes:
+ *\li The name is searched for linearly in the set of known channel names
+ * until a match is found. (Note the performance impact of a very large
+ * number of named channels.) When multiple channels of the same
+ * name are defined, the most recent definition is found.
+ *
+ *\li Specifying a very large number of channels for a category will have
+ * a moderate impact on performance in isc_log_write(), as each
+ * call looks up the category for the start of a linked list, which
+ * it follows all the way to the end to find matching modules. The
+ * test for matching modules is integral, though.
+ *
+ *\li If category is NULL, then the channel is associated with the indicated
+ * module for all known categories (including the "default" category).
+ *
+ *\li If module is NULL, then the channel is associated with every module
+ * that uses that category.
+ *
+ *\li Passing both category and module as NULL would make every log message
+ * use the indicated channel.
+ *
+ * \li Specifying a channel that is #ISC_LOG_TONULL for a category/module pair
+ * has no effect on any other channels associated with that pair,
+ * regardless of ordering. Thus you cannot use it to "mask out" one
+ * category/module pair when you have specified some other channel that
+ * is also used by that category/module pair.
+ *
+ * Requires:
+ *\li lcfg is a valid logging configuration.
+ *
+ *\li category is NULL or has an id that is in the range of known ids.
+ *
+ * module is NULL or has an id that is in the range of known ids.
+ *
+ * Ensures:
+ *\li #ISC_R_SUCCESS
+ * The channel will be used by the indicated category/module
+ * arguments.
+ *
+ *\li #ISC_R_NOMEMORY
+ * If assignment for a specific category has been requested,
+ * the channel has not been associated with the indicated
+ * category/module arguments and no additional memory is
+ * used by the logging context.
+ * If assignment for all categories has been requested
+ * then _some_ may have succeeded (starting with category
+ * "default" and progressing through the order of categories
+ * passed to isc_log_registercategories()) and additional memory
+ * is being used by whatever assignments succeeded.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_NOMEMORY Resource limit: Out of memory
+ */
+
+/* Attention: next four comments PRECEDE code */
+/*!
+ * \brief
+ * Write a message to the log channels.
+ *
+ * Notes:
+ *\li lctx can be NULL; this is allowed so that programs which use
+ * libraries that use the ISC logging system are not required to
+ * also use it.
+ *
+ *\li The format argument is a printf(3) string, with additional arguments
+ * as necessary.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *
+ *\li The category and module arguments must have ids that are in the
+ * range of known ids, as established by isc_log_registercategories()
+ * and isc_log_registermodules().
+ *
+ *\li level != #ISC_LOG_DYNAMIC. ISC_LOG_DYNAMIC is used only to define
+ * channels, and explicit debugging level must be identified for
+ * isc_log_write() via ISC_LOG_DEBUG(level).
+ *
+ *\li format != NULL.
+ *
+ * Ensures:
+ *\li The log message is written to every channel associated with the
+ * indicated category/module pair.
+ *
+ * Returns:
+ *\li Nothing. Failure to log a message is not construed as a
+ * meaningful error.
+ */
+void
+isc_log_write(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *format, ...)
+
+ ISC_FORMAT_PRINTF(5, 6);
+
+/*%
+ * Write a message to the log channels.
+ *
+ * Notes:
+ *\li lctx can be NULL; this is allowed so that programs which use
+ * libraries that use the ISC logging system are not required to
+ * also use it.
+ *
+ *\li The format argument is a printf(3) string, with additional arguments
+ * as necessary.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *
+ *\li The category and module arguments must have ids that are in the
+ * range of known ids, as established by isc_log_registercategories()
+ * and isc_log_registermodules().
+ *
+ *\li level != #ISC_LOG_DYNAMIC. ISC_LOG_DYNAMIC is used only to define
+ * channels, and explicit debugging level must be identified for
+ * isc_log_write() via ISC_LOG_DEBUG(level).
+ *
+ *\li format != NULL.
+ *
+ * Ensures:
+ *\li The log message is written to every channel associated with the
+ * indicated category/module pair.
+ *
+ * Returns:
+ *\li Nothing. Failure to log a message is not construed as a
+ * meaningful error.
+ */
+void
+isc_log_vwrite(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *format,
+ va_list args)
+
+ ISC_FORMAT_PRINTF(5, 0);
+
+/*%
+ * Write a message to the log channels, pruning duplicates that occur within
+ * a configurable amount of seconds (see isc_log_[sg]etduplicateinterval).
+ * This function is otherwise identical to isc_log_write().
+ */
+void
+isc_log_write1(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *format, ...)
+
+ ISC_FORMAT_PRINTF(5, 6);
+
+/*%
+ * Write a message to the log channels, pruning duplicates that occur within
+ * a configurable amount of seconds (see isc_log_[sg]etduplicateinterval).
+ * This function is otherwise identical to isc_log_vwrite().
+ */
+void
+isc_log_vwrite1(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *format,
+ va_list args)
+
+ ISC_FORMAT_PRINTF(5, 0);
+
+void
+isc_log_setdebuglevel(isc_log_t *lctx, unsigned int level);
+/*%<
+ * Set the debugging level used for logging.
+ *
+ * Notes:
+ *\li Setting the debugging level to 0 disables debugging log messages.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *
+ * Ensures:
+ *\li The debugging level is set to the requested value.
+ */
+
+unsigned int
+isc_log_getdebuglevel(isc_log_t *lctx);
+/*%<
+ * Get the current debugging level.
+ *
+ * Notes:
+ *\li This is provided so that a program can have a notion of
+ * "increment debugging level" or "decrement debugging level"
+ * without needing to keep track of what the current level is.
+ *
+ *\li A return value of 0 indicates that debugging messages are disabled.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *
+ * Ensures:
+ *\li The current logging debugging level is returned.
+ */
+
+bool
+isc_log_wouldlog(isc_log_t *lctx, int level);
+/*%<
+ * Determine whether logging something to 'lctx' at 'level' would
+ * actually cause something to be logged somewhere.
+ *
+ * If #false is returned, it is guaranteed that nothing would
+ * be logged, allowing the caller to omit unnecessary
+ * isc_log_write() calls and possible message preformatting.
+ */
+
+void
+isc_log_setduplicateinterval(isc_logconfig_t *lcfg, unsigned int interval);
+/*%<
+ * Set the interval over which duplicate log messages will be ignored
+ * by isc_log_[v]write1(), in seconds.
+ *
+ * Notes:
+ *\li Increasing the duplicate interval from X to Y will not necessarily
+ * filter out duplicates of messages logged in Y - X seconds since the
+ * increase. (Example: Message1 is logged at midnight. Message2
+ * is logged at 00:01:00, when the interval is only 30 seconds, causing
+ * Message1 to be expired from the log message history. Then the interval
+ * is increased to 3000 (five minutes) and at 00:04:00 Message1 is logged
+ * again. It will appear the second time even though less than five
+ * passed since the first occurrence.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ */
+
+unsigned int
+isc_log_getduplicateinterval(isc_logconfig_t *lcfg);
+/*%<
+ * Get the current duplicate filtering interval.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *
+ * Returns:
+ *\li The current duplicate filtering interval.
+ */
+
+void
+isc_log_settag(isc_logconfig_t *lcfg, const char *tag);
+/*%<
+ * Set the program name or other identifier for #ISC_LOG_PRINTTAG.
+ *
+ * Requires:
+ *\li lcfg is a valid logging configuration.
+ *
+ * Notes:
+ *\li If this function has not set the tag to a non-NULL, non-empty value,
+ * then the #ISC_LOG_PRINTTAG channel flag will not print anything.
+ * Unlike some implementations of syslog on Unix systems, you *must* set
+ * the tag in order to get it logged. It is not implicitly derived from
+ * the program name (which is pretty impossible to infer portably).
+ *
+ *\li Setting the tag to NULL or the empty string will also cause the
+ * #ISC_LOG_PRINTTAG channel flag to not print anything. If tag equals the
+ * empty string, calls to isc_log_gettag will return NULL.
+ *
+ * XXXDCL when creating a new isc_logconfig_t, it might be nice if the tag
+ * of the currently active isc_logconfig_t was inherited. this does not
+ * currently happen.
+ */
+
+char *
+isc_log_gettag(isc_logconfig_t *lcfg);
+/*%<
+ * Get the current identifier printed with #ISC_LOG_PRINTTAG.
+ *
+ * Requires:
+ *\li lcfg is a valid logging configuration.
+ *
+ * Notes:
+ *\li Since isc_log_settag() will not associate a zero-length string
+ * with the logging configuration, attempts to do so will cause
+ * this function to return NULL. However, a determined programmer
+ * will observe that (currently) a tag of length greater than zero
+ * could be set, and then modified to be zero length.
+ *
+ * Returns:
+ *\li A pointer to the current identifier, or NULL if none has been set.
+ */
+
+void
+isc_log_opensyslog(const char *tag, int options, int facility);
+/*%<
+ * Initialize syslog logging.
+ *
+ * Notes:
+ *\li XXXDCL NT
+ * This is currently equivalent to openlog(), but is not going to remain
+ * that way. In the meantime, the arguments are all identical to
+ * those used by openlog(3), as follows:
+ *
+ * \code
+ * tag: The string to use in the position of the program
+ * name in syslog messages. Most (all?) syslogs
+ * will use basename(argv[0]) if tag is NULL.
+ *
+ * options: LOG_CONS, LOG_PID, LOG_NDELAY ... whatever your
+ * syslog supports.
+ *
+ * facility: The default syslog facility. This is irrelevant
+ * since isc_log_write will ALWAYS use the channel's
+ * declared facility.
+ * \endcode
+ *
+ *\li Zero effort has been made (yet) to accommodate systems with openlog()
+ * that only takes two arguments, or to identify valid syslog
+ * facilities or options for any given architecture.
+ *
+ *\li It is necessary to call isc_log_opensyslog() to initialize
+ * syslogging on machines which do not support network connections to
+ * syslogd because they require a Unix domain socket to be used. Since
+ * this is a chore to determine at run-time, it is suggested that it
+ * always be called by programs using the ISC logging system.
+ *
+ * Requires:
+ *\li Nothing.
+ *
+ * Ensures:
+ *\li openlog() is called to initialize the syslog system.
+ */
+
+void
+isc_log_closefilelogs(isc_log_t *lctx);
+/*%<
+ * Close all open files used by #ISC_LOG_TOFILE channels.
+ *
+ * Notes:
+ *\li This function is provided for programs that want to use their own
+ * log rolling mechanism rather than the one provided internally.
+ * For example, a program that wanted to keep daily logs would define
+ * a channel which used #ISC_LOG_ROLLNEVER, then once a day would
+ * rename the log file and call isc_log_closefilelogs().
+ *
+ *\li #ISC_LOG_TOFILEDESC channels are unaffected.
+ *
+ * Requires:
+ *\li lctx is a valid context.
+ *
+ * Ensures:
+ *\li The open files are closed and will be reopened when they are
+ * next needed.
+ */
+
+isc_logcategory_t *
+isc_log_categorybyname(isc_log_t *lctx, const char *name);
+/*%<
+ * Find a category by its name.
+ *
+ * Notes:
+ *\li The string name of a category is not required to be unique.
+ *
+ * Requires:
+ *\li lctx is a valid context.
+ *\li name is not NULL.
+ *
+ * Returns:
+ *\li A pointer to the _first_ isc_logcategory_t structure used by "name".
+ *
+ *\li NULL if no category exists by that name.
+ */
+
+isc_logmodule_t *
+isc_log_modulebyname(isc_log_t *lctx, const char *name);
+/*%<
+ * Find a module by its name.
+ *
+ * Notes:
+ *\li The string name of a module is not required to be unique.
+ *
+ * Requires:
+ *\li lctx is a valid context.
+ *\li name is not NULL.
+ *
+ * Returns:
+ *\li A pointer to the _first_ isc_logmodule_t structure used by "name".
+ *
+ *\li NULL if no module exists by that name.
+ */
+
+void
+isc_log_setcontext(isc_log_t *lctx);
+/*%<
+ * Sets the context used by the libisc for logging.
+ *
+ * Requires:
+ *\li lctx be a valid context.
+ */
+
+isc_result_t
+isc_logfile_roll(isc_logfile_t *file);
+/*%<
+ * Roll a logfile.
+ *
+ * Requires:
+ *\li file is not NULL.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_LOG_H */
diff --git a/lib/isc/include/isc/magic.h b/lib/isc/include/isc/magic.h
new file mode 100644
index 0000000..1dc9fc2
--- /dev/null
+++ b/lib/isc/include/isc/magic.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_MAGIC_H
+#define ISC_MAGIC_H 1
+
+#include <isc/likely.h>
+
+/*! \file isc/magic.h */
+
+typedef struct {
+ unsigned int magic;
+} isc__magic_t;
+
+/*%
+ * To use this macro the magic number MUST be the first thing in the
+ * structure, and MUST be of type "unsigned int".
+ * The intent of this is to allow magic numbers to be checked even though
+ * the object is otherwise opaque.
+ */
+#define ISC_MAGIC_VALID(a, b) \
+ (ISC_LIKELY((a) != NULL) && \
+ ISC_LIKELY(((const isc__magic_t *)(a))->magic == (b)))
+
+#define ISC_MAGIC(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
+
+#endif /* ISC_MAGIC_H */
diff --git a/lib/isc/include/isc/managers.h b/lib/isc/include/isc/managers.h
new file mode 100644
index 0000000..0ed17ff
--- /dev/null
+++ b/lib/isc/include/isc/managers.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+#include <isc/netmgr.h>
+#include <isc/result.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+
+typedef struct isc_managers isc_managers_t;
+
+isc_result_t
+isc_managers_create(isc_mem_t *mctx, size_t workers, size_t quantum,
+ isc_nm_t **netmgrp, isc_taskmgr_t **taskmgrp);
+
+void
+isc_managers_destroy(isc_nm_t **netmgrp, isc_taskmgr_t **taskmgrp);
diff --git a/lib/isc/include/isc/md.h b/lib/isc/include/isc/md.h
new file mode 100644
index 0000000..eb9c863
--- /dev/null
+++ b/lib/isc/include/isc/md.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*!
+ * \file isc/md.h
+ * \brief This is the header file for message digest algorithms.
+ */
+
+#pragma once
+
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+typedef void isc_md_t;
+
+/**
+ * isc_md_type_t:
+ * @ISC_MD_MD5: MD5
+ * @ISC_MD_SHA1: SHA-1
+ * @ISC_MD_SHA224: SHA-224
+ * @ISC_MD_SHA256: SHA-256
+ * @ISC_MD_SHA384: SHA-384
+ * @ISC_MD_SHA512: SHA-512
+ *
+ * Enumeration of supported message digest algorithms.
+ */
+typedef void isc_md_type_t;
+
+#define ISC_MD_MD5 isc__md_md5()
+#define ISC_MD_SHA1 isc__md_sha1()
+#define ISC_MD_SHA224 isc__md_sha224()
+#define ISC_MD_SHA256 isc__md_sha256()
+#define ISC_MD_SHA384 isc__md_sha384()
+#define ISC_MD_SHA512 isc__md_sha512()
+
+const isc_md_type_t *
+isc__md_md5(void);
+const isc_md_type_t *
+isc__md_sha1(void);
+const isc_md_type_t *
+isc__md_sha224(void);
+const isc_md_type_t *
+isc__md_sha256(void);
+const isc_md_type_t *
+isc__md_sha384(void);
+const isc_md_type_t *
+isc__md_sha512(void);
+
+#define ISC_MD5_DIGESTLENGTH isc_md_type_get_size(ISC_MD_MD5)
+#define ISC_MD5_BLOCK_LENGTH isc_md_type_get_block_size(ISC_MD_MD5)
+#define ISC_SHA1_DIGESTLENGTH isc_md_type_get_size(ISC_MD_SHA1)
+#define ISC_SHA1_BLOCK_LENGTH isc_md_type_get_block_size(ISC_MD_SHA1)
+#define ISC_SHA224_DIGESTLENGTH isc_md_type_get_size(ISC_MD_SHA224)
+#define ISC_SHA224_BLOCK_LENGTH isc_md_type_get_block_size(ISC_MD_SHA224)
+#define ISC_SHA256_DIGESTLENGTH isc_md_type_get_size(ISC_MD_SHA256)
+#define ISC_SHA256_BLOCK_LENGTH isc_md_type_get_block_size(ISC_MD_SHA256)
+#define ISC_SHA384_DIGESTLENGTH isc_md_type_get_size(ISC_MD_SHA384)
+#define ISC_SHA384_BLOCK_LENGTH isc_md_type_get_block_size(ISC_MD_SHA384)
+#define ISC_SHA512_DIGESTLENGTH isc_md_type_get_size(ISC_MD_SHA512)
+#define ISC_SHA512_BLOCK_LENGTH isc_md_type_get_block_size(ISC_MD_SHA512)
+
+#define ISC_MAX_MD_SIZE 64U /* EVP_MAX_MD_SIZE */
+#define ISC_MAX_BLOCK_SIZE 128U /* ISC_SHA512_BLOCK_LENGTH */
+
+/**
+ * isc_md:
+ * @type: the digest type
+ * @buf: the data to hash
+ * @len: the length of the data to hash
+ * @digest: the output buffer
+ * @digestlen: the length of the data written to @digest
+ *
+ * This function hashes @len bytes of data at @buf and places the result in
+ * @digest. If the @digestlen parameter is not NULL then the number of bytes of
+ * data written (i.e. the length of the digest) will be written to the integer
+ * at @digestlen, at most ISC_MAX_MD_SIZE bytes will be written.
+ */
+isc_result_t
+isc_md(const isc_md_type_t *type, const unsigned char *buf, const size_t len,
+ unsigned char *digest, unsigned int *digestlen);
+
+/**
+ * isc_md_new:
+ *
+ * This function allocates, initializes and returns a digest context.
+ */
+isc_md_t *
+isc_md_new(void);
+
+/**
+ * isc_md_free:
+ * @md: message digest context
+ *
+ * This function cleans up digest context ctx and frees up the space allocated
+ * to it.
+ */
+void
+isc_md_free(isc_md_t *);
+
+/**
+ * isc_md_init:
+ * @md: message digest context
+ * @type: digest type
+ *
+ * This function sets up digest context @md to use a digest @type. @md must be
+ * initialized before calling this function.
+ */
+isc_result_t
+isc_md_init(isc_md_t *, const isc_md_type_t *md_type);
+
+/**
+ * isc_md_reset:
+ * @md: message digest context
+ *
+ * This function resets the digest context ctx. This can be used to reuse an
+ * already existing context.
+ */
+isc_result_t
+isc_md_reset(isc_md_t *md);
+
+/**
+ * isc_md_update:
+ * @md: message digest context
+ * @buf: data to hash
+ * @len: length of the data to hash
+ *
+ * This function hashes @len bytes of data at @buf into the digest context @md.
+ * This function can be called several times on the same @md to hash additional
+ * data.
+ */
+isc_result_t
+isc_md_update(isc_md_t *md, const unsigned char *buf, const size_t len);
+
+/**
+ * isc_md_final:
+ * @md: message digest context
+ * @digest: the output buffer
+ * @digestlen: the length of the data written to @digest
+ *
+ * This function retrieves the digest value from @md and places it in @digest.
+ * If the @digestlen parameter is not NULL then the number of bytes of data
+ * written (i.e. the length of the digest) will be written to the integer at
+ * @digestlen, at most ISC_MAX_MD_SIZE bytes will be written. After calling
+ * this function no additional calls to isc_md_update() can be made.
+ */
+isc_result_t
+isc_md_final(isc_md_t *md, unsigned char *digest, unsigned int *digestlen);
+
+/**
+ * isc_md_get_type:
+ * @md: message digest contezt
+ *
+ * This function return the isc_md_type_t previously set for the supplied
+ * message digest context or NULL if no isc_md_type_t has been set.
+ */
+const isc_md_type_t *
+isc_md_get_md_type(isc_md_t *md);
+
+/**
+ * isc_md_size:
+ *
+ * This function return the size of the message digest when passed an isc_md_t
+ * structure, i.e. the size of the hash.
+ */
+size_t
+isc_md_get_size(isc_md_t *md);
+
+/**
+ * isc_md_block_size:
+ *
+ * This function return the block size of the message digest when passed an
+ * isc_md_t structure.
+ */
+size_t
+isc_md_get_block_size(isc_md_t *md);
+
+/**
+ * isc_md_size:
+ *
+ * This function return the size of the message digest when passed an
+ * isc_md_type_t , i.e. the size of the hash.
+ */
+size_t
+isc_md_type_get_size(const isc_md_type_t *md_type);
+
+/**
+ * isc_md_block_size:
+ *
+ * This function return the block size of the message digest when passed an
+ * isc_md_type_t.
+ */
+size_t
+isc_md_type_get_block_size(const isc_md_type_t *md_type);
diff --git a/lib/isc/include/isc/mem.h b/lib/isc/include/isc/mem.h
new file mode 100644
index 0000000..1542edd
--- /dev/null
+++ b/lib/isc/include/isc/mem.h
@@ -0,0 +1,633 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_MEM_H
+#define ISC_MEM_H 1
+
+/*! \file isc/mem.h */
+
+#include <stdbool.h>
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+ISC_LANG_BEGINDECLS
+
+#define ISC_MEM_LOWATER 0
+#define ISC_MEM_HIWATER 1
+typedef void (*isc_mem_water_t)(void *, int);
+
+/*%
+ * Define ISC_MEM_TRACKLINES=1 to turn on detailed tracing of memory
+ * allocation and freeing by file and line number.
+ */
+#ifndef ISC_MEM_TRACKLINES
+#define ISC_MEM_TRACKLINES 1
+#endif /* ifndef ISC_MEM_TRACKLINES */
+
+/*%
+ * Define ISC_MEM_CHECKOVERRUN=1 to turn on checks for using memory outside
+ * the requested space. This will increase the size of each allocation.
+ *
+ * If we are performing a Coverity static analysis then ISC_MEM_CHECKOVERRUN
+ * can hide bugs that would otherwise discovered so force to zero.
+ */
+#ifdef __COVERITY__
+#undef ISC_MEM_CHECKOVERRUN
+#define ISC_MEM_CHECKOVERRUN 0
+#endif /* ifdef __COVERITY__ */
+#ifndef ISC_MEM_CHECKOVERRUN
+#define ISC_MEM_CHECKOVERRUN 1
+#endif /* ifndef ISC_MEM_CHECKOVERRUN */
+
+/*%
+ * Define ISC_MEMPOOL_NAMES=1 to make memory pools store a symbolic
+ * name so that the leaking pool can be more readily identified in
+ * case of a memory leak.
+ */
+#ifndef ISC_MEMPOOL_NAMES
+#define ISC_MEMPOOL_NAMES 1
+#endif /* ifndef ISC_MEMPOOL_NAMES */
+
+LIBISC_EXTERNAL_DATA extern unsigned int isc_mem_debugging;
+LIBISC_EXTERNAL_DATA extern unsigned int isc_mem_defaultflags;
+
+/*@{*/
+#define ISC_MEM_DEBUGTRACE 0x00000001U
+#define ISC_MEM_DEBUGRECORD 0x00000002U
+#define ISC_MEM_DEBUGUSAGE 0x00000004U
+#define ISC_MEM_DEBUGSIZE 0x00000008U
+#define ISC_MEM_DEBUGCTX 0x00000010U
+#define ISC_MEM_DEBUGALL 0x0000001FU
+/*!<
+ * The variable isc_mem_debugging holds a set of flags for
+ * turning certain memory debugging options on or off at
+ * runtime. It is initialized to the value ISC_MEM_DEGBUGGING,
+ * which is 0 by default but may be overridden at compile time.
+ * The following flags can be specified:
+ *
+ * \li #ISC_MEM_DEBUGTRACE
+ * Log each allocation and free to isc_lctx.
+ *
+ * \li #ISC_MEM_DEBUGRECORD
+ * Remember each allocation, and match them up on free.
+ * Crash if a free doesn't match an allocation.
+ *
+ * \li #ISC_MEM_DEBUGUSAGE
+ * If a hi_water mark is set, print the maximum inuse memory
+ * every time it is raised once it exceeds the hi_water mark.
+ *
+ * \li #ISC_MEM_DEBUGSIZE
+ * Check the size argument being passed to isc_mem_put() matches
+ * that passed to isc_mem_get().
+ *
+ * \li #ISC_MEM_DEBUGCTX
+ * Check the mctx argument being passed to isc_mem_put() matches
+ * that passed to isc_mem_get().
+ */
+/*@}*/
+
+#if ISC_MEM_TRACKLINES
+#define _ISC_MEM_FILELINE , __FILE__, __LINE__
+#define _ISC_MEM_FLARG , const char *, unsigned int
+#else /* if ISC_MEM_TRACKLINES */
+#define _ISC_MEM_FILELINE
+#define _ISC_MEM_FLARG
+#endif /* if ISC_MEM_TRACKLINES */
+
+/*!
+ * Define ISC_MEM_USE_INTERNAL_MALLOC=1 to use the internal malloc()
+ * implementation in preference to the system one. The internal malloc()
+ * is very space-efficient, and quite fast on uniprocessor systems. It
+ * performs poorly on multiprocessor machines.
+ * JT: we can overcome the performance issue on multiprocessor machines
+ * by carefully separating memory contexts.
+ */
+
+#if !defined(ISC_MEM_USE_INTERNAL_MALLOC) && !__SANITIZE_ADDRESS__
+#define ISC_MEM_USE_INTERNAL_MALLOC 0
+#endif /* ifndef ISC_MEM_USE_INTERNAL_MALLOC */
+
+/*
+ * Flags for isc_mem_create() calls.
+ */
+#define ISC_MEMFLAG_RESERVED 0x00000001 /* reserved, obsoleted, don't use */
+#define ISC_MEMFLAG_INTERNAL 0x00000002 /* use internal malloc */
+#define ISC_MEMFLAG_FILL \
+ 0x00000004 /* fill with pattern after alloc and frees */
+
+/*%
+ * Define ISC_MEM_DEFAULTFILL=1 to turn filling the memory with pattern
+ * after alloc and free.
+ */
+#if !ISC_MEM_USE_INTERNAL_MALLOC
+
+#if ISC_MEM_DEFAULTFILL
+#define ISC_MEMFLAG_DEFAULT ISC_MEMFLAG_FILL
+#else /* if ISC_MEM_DEFAULTFILL */
+#define ISC_MEMFLAG_DEFAULT 0
+#endif /* if ISC_MEM_DEFAULTFILL */
+
+#else /* if !ISC_MEM_USE_INTERNAL_MALLOC */
+
+#if ISC_MEM_DEFAULTFILL
+#define ISC_MEMFLAG_DEFAULT ISC_MEMFLAG_INTERNAL | ISC_MEMFLAG_FILL
+#else /* if ISC_MEM_DEFAULTFILL */
+#define ISC_MEMFLAG_DEFAULT ISC_MEMFLAG_INTERNAL
+#endif /* if ISC_MEM_DEFAULTFILL */
+
+#endif /* if !ISC_MEM_USE_INTERNAL_MALLOC */
+
+/*%
+ * isc_mem_putanddetach() is a convenience function for use where you
+ * have a structure with an attached memory context.
+ *
+ * Given:
+ *
+ * \code
+ * struct {
+ * ...
+ * isc_mem_t *mctx;
+ * ...
+ * } *ptr;
+ *
+ * isc_mem_t *mctx;
+ *
+ * isc_mem_putanddetach(&ptr->mctx, ptr, sizeof(*ptr));
+ * \endcode
+ *
+ * is the equivalent of:
+ *
+ * \code
+ * mctx = NULL;
+ * isc_mem_attach(ptr->mctx, &mctx);
+ * isc_mem_detach(&ptr->mctx);
+ * isc_mem_put(mctx, ptr, sizeof(*ptr));
+ * isc_mem_detach(&mctx);
+ * \endcode
+ */
+
+/*% memory and memory pool methods */
+typedef struct isc_memmethods {
+ 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);
+ char *(*memstrndup)(isc_mem_t *mctx, const char *s,
+ size_t size _ISC_MEM_FLARG);
+ void (*memfree)(isc_mem_t *mctx, void *ptr _ISC_MEM_FLARG);
+} isc_memmethods_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;
+};
+
+#define ISCAPI_MPOOL_MAGIC ISC_MAGIC('A', 'm', 'p', 'l')
+#define ISCAPI_MPOOL_VALID(mp) \
+ ((mp) != NULL && (mp)->magic == ISCAPI_MPOOL_MAGIC)
+
+/*%
+ * These functions are actually implemented in isc__mem_<function>
+ * (two underscores). The single-underscore macros are used to pass
+ * __FILE__ and __LINE__, and in the case of the put functions, to
+ * set the pointer being freed to NULL in the calling function.
+ *
+ * Many of these functions have a further isc___mem_<function>
+ * (three underscores) implementation, which is called indirectly
+ * via the isc_memmethods structure in the mctx so that dynamically
+ * loaded modules can use them even if named is statically linked.
+ */
+
+#define ISCMEMFUNC(sfx) isc__mem_##sfx
+#define ISCMEMPOOLFUNC(sfx) isc__mempool_##sfx
+
+#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_mem_strndup(c, p, s) \
+ ISCMEMFUNC(strndup)((c), (p), (s)_ISC_MEM_FILELINE)
+#define isc_mempool_get(c) ISCMEMPOOLFUNC(get)((c)_ISC_MEM_FILELINE)
+
+#define isc_mem_put(c, p, s) \
+ do { \
+ ISCMEMFUNC(put)((c), (p), (s)_ISC_MEM_FILELINE); \
+ (p) = NULL; \
+ } while (0)
+#define isc_mem_putanddetach(c, p, s) \
+ do { \
+ ISCMEMFUNC(putanddetach)((c), (p), (s)_ISC_MEM_FILELINE); \
+ (p) = NULL; \
+ } while (0)
+#define isc_mem_free(c, p) \
+ do { \
+ ISCMEMFUNC(free)((c), (p)_ISC_MEM_FILELINE); \
+ (p) = NULL; \
+ } while (0)
+#define isc_mempool_put(c, p) \
+ do { \
+ ISCMEMPOOLFUNC(put)((c), (p)_ISC_MEM_FILELINE); \
+ (p) = NULL; \
+ } while (0)
+
+/*@{*/
+void
+isc_mem_create(isc_mem_t **mctxp);
+
+/*!<
+ * \brief Create a memory context.
+ *
+ * Requires:
+ * mctxp != NULL && *mctxp == NULL */
+/*@}*/
+
+/*@{*/
+void
+isc_mem_attach(isc_mem_t *, isc_mem_t **);
+void
+isc_mem_detach(isc_mem_t **);
+/*!<
+ * \brief Attach to / detach from a memory context.
+ *
+ * This is intended for applications that use multiple memory contexts
+ * in such a way that it is not obvious when the last allocations from
+ * a given context has been freed and destroying the context is safe.
+ *
+ * Most applications do not need to call these functions as they can
+ * simply create a single memory context at the beginning of main()
+ * and destroy it at the end of main(), thereby guaranteeing that it
+ * is not destroyed while there are outstanding allocations.
+ */
+/*@}*/
+
+void
+isc_mem_destroy(isc_mem_t **);
+/*%<
+ * Destroy a memory context.
+ */
+
+void
+isc_mem_stats(isc_mem_t *mctx, FILE *out);
+/*%<
+ * Print memory usage statistics for 'mctx' on the stream 'out'.
+ */
+
+void
+isc_mem_setdestroycheck(isc_mem_t *mctx, bool on);
+/*%<
+ * If 'on' is true, 'mctx' will check for memory leaks when
+ * destroyed and abort the program if any are present.
+ */
+
+size_t
+isc_mem_inuse(isc_mem_t *mctx);
+/*%<
+ * Get an estimate of the amount of memory in use in 'mctx', in bytes.
+ * This includes quantization overhead, but does not include memory
+ * allocated from the system but not yet used.
+ */
+
+size_t
+isc_mem_maxinuse(isc_mem_t *mctx);
+/*%<
+ * Get an estimate of the largest amount of memory that has been in
+ * use in 'mctx' at any time.
+ */
+
+size_t
+isc_mem_total(isc_mem_t *mctx);
+/*%<
+ * Get the total amount of memory in 'mctx', in bytes, including memory
+ * not yet used.
+ */
+
+bool
+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);
+/*%<
+ * Set high and low water marks for this memory context.
+ *
+ * When the memory usage of 'mctx' exceeds 'hiwater',
+ * '(water)(water_arg, #ISC_MEM_HIWATER)' will be called. 'water' needs to
+ * call isc_mem_waterack() with #ISC_MEM_HIWATER to acknowledge the state
+ * change. 'water' may be called multiple times.
+ *
+ * When the usage drops below 'lowater', 'water' will again be called, this
+ * time with #ISC_MEM_LOWATER. 'water' need to calls isc_mem_waterack() with
+ * #ISC_MEM_LOWATER to acknowledge the change.
+ *
+ * static void
+ * water(void *arg, int mark) {
+ * struct foo *foo = arg;
+ *
+ * LOCK(&foo->marklock);
+ * if (foo->mark != mark) {
+ * foo->mark = mark;
+ * ....
+ * isc_mem_waterack(foo->mctx, mark);
+ * }
+ * UNLOCK(&foo->marklock);
+ * }
+ *
+ * If 'water' is NULL then 'water_arg', 'hi_water' and 'lo_water' are
+ * ignored and the state is reset.
+ *
+ * Requires:
+ *
+ * 'water' is not NULL.
+ * hi_water >= lo_water
+ */
+
+void
+isc_mem_waterack(isc_mem_t *ctx, int mark);
+/*%<
+ * Called to acknowledge changes in signaled by calls to 'water'.
+ */
+
+void
+isc_mem_checkdestroyed(FILE *file);
+/*%<
+ * Check that all memory contexts have been destroyed.
+ * Prints out those that have not been.
+ * Fatally fails if there are still active contexts.
+ */
+
+unsigned int
+isc_mem_references(isc_mem_t *ctx);
+/*%<
+ * Return the current reference count.
+ */
+
+void
+isc_mem_setname(isc_mem_t *ctx, const char *name, void *tag);
+/*%<
+ * Name 'ctx'.
+ *
+ * Notes:
+ *
+ *\li Only the first 15 characters of 'name' will be copied.
+ *
+ *\li 'tag' is for debugging purposes only.
+ *
+ * Requires:
+ *
+ *\li 'ctx' is a valid ctx.
+ */
+
+const char *
+isc_mem_getname(isc_mem_t *ctx);
+/*%<
+ * Get the name of 'ctx', as previously set using isc_mem_setname().
+ *
+ * Requires:
+ *\li 'ctx' is a valid ctx.
+ *
+ * Returns:
+ *\li A non-NULL pointer to a null-terminated string.
+ * If the ctx has not been named, the string is
+ * empty.
+ */
+
+void *
+isc_mem_gettag(isc_mem_t *ctx);
+/*%<
+ * Get the tag value for 'task', as previously set using isc_mem_setname().
+ *
+ * Requires:
+ *\li 'ctx' is a valid ctx.
+ *
+ * Notes:
+ *\li This function is for debugging purposes only.
+ *
+ * Requires:
+ *\li 'ctx' is a valid task.
+ */
+
+#ifdef HAVE_LIBXML2
+int
+isc_mem_renderxml(void *writer0);
+/*%<
+ * Render all contexts' statistics and status in XML for writer.
+ */
+#endif /* HAVE_LIBXML2 */
+
+#ifdef HAVE_JSON_C
+isc_result_t
+isc_mem_renderjson(void *memobj0);
+/*%<
+ * Render all contexts' statistics and status in JSON.
+ */
+#endif /* HAVE_JSON_C */
+
+/*
+ * Memory pools
+ */
+
+void
+isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp);
+/*%<
+ * Create a memory pool.
+ *
+ * Requires:
+ *\li mctx is a valid memory context.
+ *\li size > 0
+ *\li mpctxp != NULL and *mpctxp == NULL
+ *
+ * Defaults:
+ *\li maxalloc = UINT_MAX
+ *\li freemax = 1
+ *\li fillcount = 1
+ *
+ * Returns:
+ *\li #ISC_R_NOMEMORY -- not enough memory to create pool
+ *\li #ISC_R_SUCCESS -- all is well.
+ */
+
+void
+isc_mempool_destroy(isc_mempool_t **mpctxp);
+/*%<
+ * Destroy a memory pool.
+ *
+ * Requires:
+ *\li mpctxp != NULL && *mpctxp is a valid pool.
+ *\li The pool has no un"put" allocations outstanding
+ */
+
+void
+isc_mempool_setname(isc_mempool_t *mpctx, const char *name);
+/*%<
+ * Associate a name with a memory pool. At most 15 characters may be used.
+ *
+ * Requires:
+ *\li mpctx is a valid pool.
+ *\li name != NULL;
+ */
+
+/*
+ * The following functions get/set various parameters. Note that due to
+ * the unlocked nature of pools these are potentially random values unless
+ * the imposed externally provided locking protocols are followed.
+ *
+ * Also note that the quota limits will not always take immediate effect.
+ * For instance, setting "maxalloc" to a number smaller than the currently
+ * allocated count is permitted. New allocations will be refused until
+ * the count drops below this threshold.
+ *
+ * All functions require (in addition to other requirements):
+ * mpctx is a valid memory pool
+ */
+
+unsigned int
+isc_mempool_getfreemax(isc_mempool_t *mpctx);
+/*%<
+ * Returns the maximum allowed size of the free list.
+ */
+
+void
+isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit);
+/*%<
+ * Sets the maximum allowed size of the free list.
+ */
+
+unsigned int
+isc_mempool_getfreecount(isc_mempool_t *mpctx);
+/*%<
+ * Returns current size of the free list.
+ */
+
+unsigned int
+isc_mempool_getmaxalloc(isc_mempool_t *mpctx);
+/*!<
+ * Returns the maximum allowed number of allocations.
+ */
+
+void
+isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit);
+/*%<
+ * Sets the maximum allowed number of allocations.
+ *
+ * Additional requirements:
+ *\li limit > 0
+ */
+
+unsigned int
+isc_mempool_getallocated(isc_mempool_t *mpctx);
+/*%<
+ * Returns the number of items allocated from this pool.
+ */
+
+unsigned int
+isc_mempool_getfillcount(isc_mempool_t *mpctx);
+/*%<
+ * Returns the number of items allocated as a block from the parent memory
+ * context when the free list is empty.
+ */
+
+void
+isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit);
+/*%<
+ * Sets the fillcount.
+ *
+ * Additional requirements:
+ *\li limit > 0
+ */
+
+#if defined(UNIT_TESTING) && defined(malloc)
+/*
+ * cmocka.h redefined malloc as a macro, we #undef it
+ * to avoid replacing ISC_ATTR_MALLOC with garbage.
+ */
+#pragma push_macro("malloc")
+#undef malloc
+#define POP_MALLOC_MACRO 1
+#endif
+
+/*
+ * Pseudo-private functions for use via macros. Do not call directly.
+ */
+void ISCMEMFUNC(putanddetach)(isc_mem_t **, void *, size_t _ISC_MEM_FLARG);
+void ISCMEMFUNC(put)(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
+void ISCMEMFUNC(free)(isc_mem_t *, void *_ISC_MEM_FLARG);
+
+ISC_ATTR_RETURNS_NONNULL
+ISC_ATTR_MALLOC_DEALLOCATOR_IDX(ISCMEMFUNC(put), 2)
+void *ISCMEMFUNC(get)(isc_mem_t *, size_t _ISC_MEM_FLARG);
+
+ISC_ATTR_RETURNS_NONNULL
+ISC_ATTR_MALLOC_DEALLOCATOR_IDX(ISCMEMFUNC(free), 2)
+void *ISCMEMFUNC(allocate)(isc_mem_t *, size_t _ISC_MEM_FLARG);
+
+ISC_ATTR_RETURNS_NONNULL
+ISC_ATTR_DEALLOCATOR_IDX(ISCMEMFUNC(free), 2)
+void *ISCMEMFUNC(reallocate)(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
+
+ISC_ATTR_RETURNS_NONNULL
+ISC_ATTR_MALLOC_DEALLOCATOR_IDX(ISCMEMFUNC(free), 2)
+char *ISCMEMFUNC(strdup)(isc_mem_t *, const char *_ISC_MEM_FLARG);
+char *ISCMEMFUNC(strndup)(isc_mem_t *, const char *, size_t _ISC_MEM_FLARG);
+
+ISC_ATTR_MALLOC_DEALLOCATOR_IDX(ISCMEMPOOLFUNC(put), 2)
+void *ISCMEMPOOLFUNC(get)(isc_mempool_t *_ISC_MEM_FLARG);
+
+void ISCMEMPOOLFUNC(put)(isc_mempool_t *, void *_ISC_MEM_FLARG);
+
+#ifdef POP_MALLOC_MACRO
+/*
+ * Restore cmocka.h macro for malloc.
+ */
+#pragma pop_macro("malloc")
+#endif
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_MEM_H */
diff --git a/lib/isc/include/isc/meminfo.h b/lib/isc/include/isc/meminfo.h
new file mode 100644
index 0000000..3cda5b2
--- /dev/null
+++ b/lib/isc/include/isc/meminfo.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_MEMINFO_H
+#define ISC_MEMINFO_H 1
+
+#include <inttypes.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+uint64_t
+isc_meminfo_totalphys(void);
+/*%<
+ * Return total available physical memory in bytes, or 0 if this cannot
+ * be determined
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_MEMINFO_H */
diff --git a/lib/isc/include/isc/mutexblock.h b/lib/isc/include/isc/mutexblock.h
new file mode 100644
index 0000000..d2144e1
--- /dev/null
+++ b/lib/isc/include/isc/mutexblock.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_MUTEXBLOCK_H
+#define ISC_MUTEXBLOCK_H 1
+
+/*! \file isc/mutexblock.h */
+
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_mutexblock_init(isc_mutex_t *block, unsigned int count);
+/*%<
+ * Initialize a block of locks. If an error occurs all initialized locks
+ * will be destroyed, if possible.
+ *
+ * Requires:
+ *
+ *\li block != NULL
+ *
+ *\li count > 0
+ *
+ */
+
+void
+isc_mutexblock_destroy(isc_mutex_t *block, unsigned int count);
+/*%<
+ * Destroy a block of locks.
+ *
+ * Requires:
+ *
+ *\li block != NULL
+ *
+ *\li count > 0
+ *
+ *\li Each lock in the block be initialized via isc_mutex_init() or
+ * the whole block was initialized via isc_mutex_initblock().
+ *
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_MUTEXBLOCK_H */
diff --git a/lib/isc/include/isc/netaddr.h b/lib/isc/include/isc/netaddr.h
new file mode 100644
index 0000000..519aec7
--- /dev/null
+++ b/lib/isc/include/isc/netaddr.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_NETADDR_H
+#define ISC_NETADDR_H 1
+
+/*! \file isc/netaddr.h */
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/lang.h>
+#include <isc/net.h>
+#include <isc/types.h>
+
+#ifdef ISC_PLATFORM_HAVESYSUNH
+#include <sys/types.h>
+#include <sys/un.h>
+#endif /* ifdef ISC_PLATFORM_HAVESYSUNH */
+
+ISC_LANG_BEGINDECLS
+
+/*
+ * Any updates to this structure should also be applied in
+ * contrib/modules/dlz/dlz_minmal.h.
+ */
+struct isc_netaddr {
+ unsigned int family;
+ union {
+ struct in_addr in;
+ struct in6_addr in6;
+#ifdef ISC_PLATFORM_HAVESYSUNH
+ char un[sizeof(((struct sockaddr_un *)0)->sun_path)];
+#endif /* ifdef ISC_PLATFORM_HAVESYSUNH */
+ } type;
+ uint32_t zone;
+};
+
+bool
+isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b);
+
+/*%<
+ * Compare network addresses 'a' and 'b'. Return #true if
+ * they are equal, #false if not.
+ */
+
+bool
+isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
+ unsigned int prefixlen);
+/*%<
+ * Compare the 'prefixlen' most significant bits of the network
+ * addresses 'a' and 'b'. If 'b''s scope is zero then 'a''s scope is
+ * ignored. Return #true if they are equal, #false if not.
+ */
+
+isc_result_t
+isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp);
+/*%<
+ * Convert a netmask in 's' into a prefix length in '*lenp'.
+ * The mask should consist of zero or more '1' bits in the
+ * most significant part of the address, followed by '0' bits.
+ * If this is not the case, #ISC_R_MASKNONCONTIG is returned.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_MASKNONCONTIG
+ */
+
+isc_result_t
+isc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target);
+/*%<
+ * Append a text representation of 'sockaddr' to the buffer 'target'.
+ * The text is NOT null terminated. Handles IPv4 and IPv6 addresses.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOSPACE The text or the null termination did not fit.
+ *\li #ISC_R_FAILURE Unspecified failure
+ */
+
+void
+isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size);
+/*%<
+ * Format a human-readable representation of the network address '*na'
+ * into the character array 'array', which is of size 'size'.
+ * The resulting string is guaranteed to be null-terminated.
+ */
+
+#define ISC_NETADDR_FORMATSIZE \
+ sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:XXX.XXX.XXX.XXX%SSSSSSSSSS")
+/*%<
+ * Minimum size of array to pass to isc_netaddr_format().
+ */
+
+void
+isc_netaddr_fromsockaddr(isc_netaddr_t *netaddr, const isc_sockaddr_t *source);
+
+void
+isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina);
+
+void
+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);
+
+void
+isc_netaddr_setzone(isc_netaddr_t *netaddr, uint32_t zone);
+
+uint32_t
+isc_netaddr_getzone(const isc_netaddr_t *netaddr);
+
+void
+isc_netaddr_any(isc_netaddr_t *netaddr);
+/*%<
+ * Return the IPv4 wildcard address.
+ */
+
+void
+isc_netaddr_any6(isc_netaddr_t *netaddr);
+/*%<
+ * Return the IPv6 wildcard address.
+ */
+
+void
+isc_netaddr_unspec(isc_netaddr_t *netaddr);
+/*%<
+ * Initialize as AF_UNSPEC address.
+ */
+
+bool
+isc_netaddr_ismulticast(const isc_netaddr_t *na);
+/*%<
+ * Returns true if the address is a multicast address.
+ */
+
+bool
+isc_netaddr_isexperimental(const isc_netaddr_t *na);
+/*%<
+ * Returns true if the address is a experimental (CLASS E) address.
+ */
+
+bool
+isc_netaddr_islinklocal(const isc_netaddr_t *na);
+/*%<
+ * Returns #true if the address is a link local address.
+ */
+
+bool
+isc_netaddr_issitelocal(const isc_netaddr_t *na);
+/*%<
+ * Returns #true if the address is a site local address.
+ */
+
+bool
+isc_netaddr_isnetzero(const isc_netaddr_t *na);
+/*%<
+ * Returns #true if the address is in net zero.
+ */
+
+void
+isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s);
+/*%<
+ * Convert an IPv6 v4mapped address into an IPv4 address.
+ */
+
+isc_result_t
+isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen);
+/*
+ * Test whether the netaddr 'na' and 'prefixlen' are consistent.
+ * e.g. prefixlen within range.
+ * na does not have bits set which are not covered by the prefixlen.
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * ISC_R_RANGE prefixlen out of range
+ * ISC_R_NOTIMPLEMENTED unsupported family
+ * ISC_R_FAILURE extra bits.
+ */
+
+bool
+isc_netaddr_isloopback(const isc_netaddr_t *na);
+/*
+ * Test whether the netaddr 'na' is a loopback IPv4 or IPv6 address (in
+ * 127.0.0.0/8 or ::1).
+ */
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NETADDR_H */
diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h
new file mode 100644
index 0000000..f1747be
--- /dev/null
+++ b/lib/isc/include/isc/netmgr.h
@@ -0,0 +1,540 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+#include <unistd.h>
+
+#include <isc/mem.h>
+#include <isc/region.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+#ifndef _WIN32
+#include <sys/socket.h>
+#include <sys/types.h>
+#endif
+
+#if defined(SO_REUSEPORT_LB) || (defined(SO_REUSEPORT) && defined(__linux__))
+#define HAVE_SO_REUSEPORT_LB 1
+#endif
+
+/*
+ * Replacement for isc_sockettype_t provided by socket.h.
+ */
+typedef enum {
+ isc_socktype_tcp = 1,
+ isc_socktype_udp = 2,
+ isc_socktype_unix = 3,
+ isc_socktype_raw = 4
+} isc_socktype_t;
+
+typedef void (*isc_nm_recv_cb_t)(isc_nmhandle_t *handle, isc_result_t eresult,
+ isc_region_t *region, void *cbarg);
+/*%<
+ * Callback function to be used when receiving a packet.
+ *
+ * 'handle' the handle that can be used to send back the answer.
+ * 'eresult' the result of the event.
+ * 'region' contains the received data, if any. It will be freed
+ * after return by caller.
+ * 'cbarg' the callback argument passed to isc_nm_listenudp(),
+ * isc_nm_listentcpdns(), or isc_nm_read().
+ */
+typedef isc_result_t (*isc_nm_accept_cb_t)(isc_nmhandle_t *handle,
+ isc_result_t result, void *cbarg);
+/*%<
+ * Callback function to be used when accepting a connection. (This differs
+ * from isc_nm_cb_t below in that it returns a result code.)
+ *
+ * 'handle' the handle that can be used to send back the answer.
+ * 'eresult' the result of the event.
+ * 'cbarg' the callback argument passed to isc_nm_listentcp() or
+ * isc_nm_listentcpdns().
+ */
+
+typedef void (*isc_nm_cb_t)(isc_nmhandle_t *handle, isc_result_t result,
+ void *cbarg);
+/*%<
+ * Callback function for other network completion events (send, connect).
+ *
+ * 'handle' the handle on which the event took place.
+ * 'eresult' the result of the event.
+ * 'cbarg' the callback argument passed to isc_nm_send(),
+ * isc_nm_tcp_connect(), or isc_nm_listentcp()
+ */
+
+typedef void (*isc_nm_opaquecb_t)(void *arg);
+/*%<
+ * Opaque callback function, used for isc_nmhandle 'reset' and 'free'
+ * callbacks.
+ */
+
+typedef void (*isc_nm_workcb_t)(void *arg);
+typedef void (*isc_nm_after_workcb_t)(void *arg, isc_result_t result);
+/*%<
+ * Callback functions for libuv threadpool work (see uv_work_t)
+ */
+
+void
+isc_nm_attach(isc_nm_t *mgr, isc_nm_t **dst);
+void
+isc_nm_detach(isc_nm_t **mgr0);
+/*%<
+ * Attach/detach a network manager. When all references have been
+ * released, the network manager is shut down, freeing all resources.
+ * Destroy is working the same way as detach, but it actively waits
+ * for all other references to be gone.
+ */
+
+/* Return thread ID of current thread, or ISC_NETMGR_TID_UNKNOWN */
+int
+isc_nm_tid(void);
+
+void
+isc_nmsocket_close(isc_nmsocket_t **sockp);
+/*%<
+ * isc_nmsocket_close() detaches a listening socket that was
+ * created by isc_nm_listenudp(), isc_nm_listentcp(), or
+ * isc_nm_listentcpdns(). Once there are no remaining child
+ * sockets with active handles, the socket will be closed.
+ */
+
+#ifdef NETMGR_TRACE
+#define isc_nmhandle_attach(handle, dest) \
+ isc__nmhandle_attach(handle, dest, __FILE__, __LINE__, __func__)
+#define isc_nmhandle_detach(handlep) \
+ isc__nmhandle_detach(handlep, __FILE__, __LINE__, __func__)
+#define FLARG , const char *file, unsigned int line, const char *func
+#else
+#define isc_nmhandle_attach(handle, dest) isc__nmhandle_attach(handle, dest)
+#define isc_nmhandle_detach(handlep) isc__nmhandle_detach(handlep)
+#define FLARG
+#endif
+
+void
+isc__nmhandle_attach(isc_nmhandle_t *handle, isc_nmhandle_t **dest FLARG);
+void
+isc__nmhandle_detach(isc_nmhandle_t **handlep FLARG);
+/*%<
+ * Increment/decrement the reference counter in a netmgr handle,
+ * but (unlike the attach/detach functions) do not change the pointer
+ * value. If reference counters drop to zero, the handle can be
+ * marked inactive, possibly triggering deletion of its associated
+ * socket.
+ *
+ * (This will be used to prevent a client from being cleaned up when
+ * it's passed to an isc_task event handler. The libuv code would not
+ * otherwise know that the handle was in use and might free it, along
+ * with the client.)
+ */
+#undef FLARG
+
+void *
+isc_nmhandle_getdata(isc_nmhandle_t *handle);
+
+void *
+isc_nmhandle_getextra(isc_nmhandle_t *handle);
+
+bool
+isc_nmhandle_is_stream(isc_nmhandle_t *handle);
+
+void
+isc_nmhandle_setdata(isc_nmhandle_t *handle, void *arg,
+ isc_nm_opaquecb_t doreset, isc_nm_opaquecb_t dofree);
+/*%<
+ * isc_nmhandle_t has a void* opaque field (for example, ns_client_t).
+ * We reuse handle and `opaque` can also be reused between calls.
+ * This function sets this field and two callbacks:
+ * - doreset resets the `opaque` to initial state
+ * - dofree frees everything associated with `opaque`
+ */
+
+void
+isc_nmhandle_settimeout(isc_nmhandle_t *handle, uint32_t timeout);
+void
+isc_nmhandle_cleartimeout(isc_nmhandle_t *handle);
+/*%<
+ * Set/clear the read/recv timeout for the socket connected to 'handle'
+ * to 'timeout' (in milliseconds), and reset the timer.
+ *
+ * When this is called on a 'wrapper' socket handle (for example,
+ * a TCPDNS socket wrapping a TCP connection), the timer is set for
+ * both socket layers.
+ */
+
+void
+isc_nmhandle_keepalive(isc_nmhandle_t *handle, bool value);
+/*%<
+ * Enable/disable keepalive on this connection by setting it to 'value'.
+ *
+ * When keepalive is active, we switch to using the keepalive timeout
+ * to determine when to close a connection, rather than the idle timeout.
+ *
+ * This applies only to TCP-based DNS connections (i.e., TCPDNS).
+ * On other types of connection it has no effect.
+ */
+
+isc_sockaddr_t
+isc_nmhandle_peeraddr(isc_nmhandle_t *handle);
+/*%<
+ * Return the peer address for the given handle.
+ */
+isc_sockaddr_t
+isc_nmhandle_localaddr(isc_nmhandle_t *handle);
+/*%<
+ * Return the local address for the given handle.
+ */
+
+isc_nm_t *
+isc_nmhandle_netmgr(isc_nmhandle_t *handle);
+/*%<
+ * Return a pointer to the netmgr object for the given handle.
+ */
+
+isc_result_t
+isc_nm_listenudp(isc_nm_t *mgr, isc_sockaddr_t *iface, isc_nm_recv_cb_t cb,
+ void *cbarg, size_t extrasize, isc_nmsocket_t **sockp);
+/*%<
+ * Start listening for UDP packets on interface 'iface' using net manager
+ * 'mgr'.
+ *
+ * On success, 'sockp' will be updated to contain a new listening UDP socket.
+ *
+ * When a packet is received on the socket, 'cb' will be called with 'cbarg'
+ * as its argument.
+ *
+ * When handles are allocated for the socket, 'extrasize' additional bytes
+ * can be allocated along with the handle for an associated object, which
+ * can then be freed automatically when the handle is destroyed.
+ */
+
+void
+isc_nm_udpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
+ isc_nm_cb_t cb, void *cbarg, unsigned int timeout,
+ size_t extrahandlesize);
+/*%<
+ * Open a UDP socket, bind to 'local' and connect to 'peer', and
+ * immediately call 'cb' with a handle so that the caller can begin
+ * sending packets over UDP.
+ *
+ * When handles are allocated for the socket, 'extrasize' additional bytes
+ * can be allocated along with the handle for an associated object, which
+ * can then be freed automatically when the handle is destroyed.
+ *
+ * 'timeout' specifies the timeout interval in milliseconds.
+ *
+ * The connected socket can only be accessed via the handle passed to
+ * 'cb'.
+ */
+
+void
+isc_nm_stoplistening(isc_nmsocket_t *sock);
+/*%<
+ * Stop listening on socket 'sock'.
+ */
+
+void
+isc_nm_pause(isc_nm_t *mgr);
+/*%<
+ * Pause all processing, equivalent to taskmgr exclusive tasks.
+ * It won't return until all workers have been paused.
+ */
+
+void
+isc_nm_resume(isc_nm_t *mgr);
+/*%<
+ * Resume paused processing. It will return immediately after signalling
+ * workers to resume.
+ */
+
+void
+isc_nm_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg);
+/*
+ * Begin (or continue) reading on the socket associated with 'handle', and
+ * update its recv callback to 'cb', which will be called as soon as there
+ * is data to process.
+ */
+
+void
+isc_nm_pauseread(isc_nmhandle_t *handle);
+/*%<
+ * Pause reading on this handle's socket, but remember the callback.
+ *
+ * Requires:
+ * \li 'handle' is a valid netmgr handle.
+ */
+
+void
+isc_nm_cancelread(isc_nmhandle_t *handle);
+/*%<
+ * Cancel reading on a connected socket. Calls the read/recv callback on
+ * active handles with a result code of ISC_R_CANCELED.
+ *
+ * Requires:
+ * \li 'sock' is a valid netmgr socket
+ * \li ...for which a read/recv callback has been defined.
+ */
+
+void
+isc_nm_resumeread(isc_nmhandle_t *handle);
+/*%<
+ * Resume reading on the handle's socket.
+ *
+ * Requires:
+ * \li 'handle' is a valid netmgr handle.
+ * \li ...for a socket with a defined read/recv callback.
+ */
+
+void
+isc_nm_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
+ void *cbarg);
+/*%<
+ * Send the data in 'region' via 'handle'. Afterward, the callback 'cb' is
+ * called with the argument 'cbarg'.
+ *
+ * 'region' is not copied; it has to be allocated beforehand and freed
+ * in 'cb'.
+ */
+
+isc_result_t
+isc_nm_listentcp(isc_nm_t *mgr, isc_sockaddr_t *iface,
+ isc_nm_accept_cb_t accept_cb, void *accept_cbarg,
+ size_t extrahandlesize, int backlog, isc_quota_t *quota,
+ isc_nmsocket_t **sockp);
+/*%<
+ * Start listening for raw messages over the TCP interface 'iface', using
+ * net manager 'mgr'.
+ *
+ * On success, 'sockp' will be updated to contain a new listening TCP
+ * socket.
+ *
+ * When connection is accepted on the socket, 'accept_cb' will be called with
+ * 'accept_cbarg' as its argument. The callback is expected to start a read.
+ *
+ * When handles are allocated for the socket, 'extrasize' additional bytes
+ * will be allocated along with the handle for an associated object.
+ *
+ * If 'quota' is not NULL, then the socket is attached to the specified
+ * quota. This allows us to enforce TCP client quota limits.
+ *
+ */
+
+void
+isc_nm_tcpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
+ isc_nm_cb_t cb, void *cbarg, unsigned int timeout,
+ size_t extrahandlesize);
+/*%<
+ * Create a socket using netmgr 'mgr', bind it to the address 'local',
+ * and connect it to the address 'peer'.
+ *
+ * When the connection is complete or has timed out, call 'cb' with
+ * argument 'cbarg'. Allocate 'extrahandlesize' additional bytes along
+ * with the handle to use for an associated object.
+ *
+ * 'timeout' specifies the timeout interval in milliseconds.
+ *
+ * The connected socket can only be accessed via the handle passed to
+ * 'cb'.
+ */
+
+isc_result_t
+isc_nm_listentcpdns(isc_nm_t *mgr, isc_sockaddr_t *iface,
+ isc_nm_recv_cb_t recv_cb, void *recv_cbarg,
+ isc_nm_accept_cb_t accept_cb, void *accept_cbarg,
+ size_t extrahandlesize, int backlog, isc_quota_t *quota,
+ isc_nmsocket_t **sockp);
+/*%<
+ * Start listening for DNS messages over the TCP interface 'iface', using
+ * net manager 'mgr'.
+ *
+ * On success, 'sockp' will be updated to contain a new listening TCPDNS
+ * socket. This is a wrapper around a raw TCP socket, which sends and
+ * receives DNS messages via that socket. It handles message buffering
+ * and pipelining, and automatically prepends messages with a two-byte
+ * length field.
+ *
+ * When a complete DNS message is received on the socket, 'cb' will be
+ * called with 'cbarg' as its argument.
+ *
+ * When a new TCPDNS connection is accepted, 'accept_cb' will be called
+ * with 'accept_cbarg' as its argument.
+ *
+ * When handles are allocated for the socket, 'extrasize' additional bytes
+ * will be allocated along with the handle for an associated object
+ * (typically ns_client).
+ *
+ * 'quota' is passed to isc_nm_listentcp() when opening the raw TCP socket.
+ */
+
+void
+isc_nm_tcpdns_sequential(isc_nmhandle_t *handle);
+/*%<
+ * Disable pipelining on this connection. Each DNS packet will be only
+ * processed after the previous completes.
+ *
+ * The socket must be unpaused after the query is processed. This is done
+ * the response is sent, or if we're dropping the query, it will be done
+ * when a handle is fully dereferenced by calling the socket's
+ * closehandle_cb callback.
+ *
+ * Note: This can only be run while a message is being processed; if it is
+ * run before any messages are read, no messages will be read.
+ *
+ * Also note: once this has been set, it cannot be reversed for a given
+ * connection.
+ */
+
+void
+isc_nm_tcpdns_keepalive(isc_nmhandle_t *handle, bool value);
+/*%<
+ * Enable/disable keepalive on this connection by setting it to 'value'.
+ *
+ * When keepalive is active, we switch to using the keepalive timeout
+ * to determine when to close a connection, rather than the idle timeout.
+ */
+
+void
+isc_nm_settimeouts(isc_nm_t *mgr, uint32_t init, uint32_t idle,
+ uint32_t keepalive, uint32_t advertised);
+/*%<
+ * Sets the initial, idle, and keepalive timeout values (in milliseconds) to use
+ * for TCP connections, and the timeout value to advertise in responses using
+ * the EDNS TCP Keepalive option (which should ordinarily be the same
+ * as 'keepalive'), in milliseconds.
+ *
+ * Requires:
+ * \li 'mgr' is a valid netmgr.
+ */
+
+bool
+isc_nm_getloadbalancesockets(isc_nm_t *mgr);
+void
+isc_nm_setloadbalancesockets(isc_nm_t *mgr, bool enabled);
+/*%<
+ * Get and set value of load balancing of the sockets.
+ *
+ * Requires:
+ * \li 'mgr' is a valid netmgr.
+ */
+
+void
+isc_nm_gettimeouts(isc_nm_t *mgr, uint32_t *initial, uint32_t *idle,
+ uint32_t *keepalive, uint32_t *advertised);
+/*%<
+ * Gets the initial, idle, keepalive, or advertised timeout values,
+ * in milliseconds.
+ *
+ * Any integer pointer parameter not set to NULL will be updated to
+ * contain the corresponding timeout value.
+ *
+ * Requires:
+ * \li 'mgr' is a valid netmgr.
+ */
+
+void
+isc_nm_maxudp(isc_nm_t *mgr, uint32_t maxudp);
+/*%<
+ * Simulate a broken firewall that blocks UDP messages larger than a given
+ * size.
+ */
+
+void
+isc_nm_setstats(isc_nm_t *mgr, isc_stats_t *stats);
+/*%<
+ * Set a socket statistics counter set 'stats' for 'mgr'.
+ *
+ * Requires:
+ *\li 'mgr' is valid and doesn't have stats already set.
+ *
+ *\li stats is a valid set of statistics counters supporting the
+ * full range of socket-related stats counter numbers.
+ */
+
+void
+isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
+ isc_nm_cb_t cb, void *cbarg, unsigned int timeout,
+ size_t extrahandlesize);
+/*%<
+ * Establish a DNS client connection via a TCP connection, bound to
+ * the address 'local' and connected to the address 'peer'.
+ *
+ * When the connection is complete or has timed out, call 'cb' with
+ * argument 'cbarg'. Allocate 'extrahandlesize' additional bytes along
+ * with the handle to use for an associated object.
+ *
+ * 'timeout' specifies the timeout interval in milliseconds.
+ *
+ * The connected socket can only be accessed via the handle passed to
+ * 'cb'.
+ */
+
+void
+isc_nm_task_enqueue(isc_nm_t *mgr, isc_task_t *task, int threadid);
+/*%<
+ * Enqueue the 'task' onto the netmgr ievents queue.
+ *
+ * Requires:
+ * \li 'mgr' is a valid netmgr object
+ * \li 'task' is a valid task
+ * \li 'threadid' is either the preferred netmgr tid or -1, in which case
+ * tid will be picked randomly. The threadid is capped (by modulo) to
+ * maximum number of 'workers' as specifed in isc_nm_start()
+ */
+
+void
+isc_nm_work_offload(isc_nm_t *mgr, isc_nm_workcb_t work_cb,
+ isc_nm_after_workcb_t after_work_cb, void *data);
+/*%<
+ * Schedules a job to be handled by the libuv thread pool (see uv_work_t).
+ * The function specified in `work_cb` will be run by a thread in the
+ * thread pool; when complete, the `after_work_cb` function will run.
+ *
+ * Requires:
+ * \li 'mgr' is a valid netmgr object.
+ * \li We are currently running in a network manager thread.
+ */
+
+void
+isc__nm_force_tid(int tid);
+/*%<
+ * Force the thread ID to 'tid'. This is STRICTLY for use in unit
+ * tests and should not be used in any production code.
+ */
+
+void
+isc_nmhandle_setwritetimeout(isc_nmhandle_t *handle, uint64_t write_timeout);
+
+/*
+ * Timer related functions
+ */
+
+typedef struct isc_nm_timer isc_nm_timer_t;
+
+typedef void (*isc_nm_timer_cb)(void *, isc_result_t);
+
+void
+isc_nm_timer_create(isc_nmhandle_t *, isc_nm_timer_cb, void *,
+ isc_nm_timer_t **);
+
+void
+isc_nm_timer_attach(isc_nm_timer_t *, isc_nm_timer_t **);
+
+void
+isc_nm_timer_detach(isc_nm_timer_t **);
+
+void
+isc_nm_timer_start(isc_nm_timer_t *, uint64_t);
+
+void
+isc_nm_timer_stop(isc_nm_timer_t *);
diff --git a/lib/isc/include/isc/netscope.h b/lib/isc/include/isc/netscope.h
new file mode 100644
index 0000000..0622548
--- /dev/null
+++ b/lib/isc/include/isc/netscope.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_NETSCOPE_H
+#define ISC_NETSCOPE_H 1
+
+/*! \file isc/netscope.h */
+
+#include <inttypes.h>
+
+ISC_LANG_BEGINDECLS
+
+/*%
+ * Convert a string of an IPv6 scope zone to zone index. If the conversion
+ * succeeds, 'zoneid' will store the index value.
+ *
+ * XXXJT: when a standard interface for this purpose is defined,
+ * we should use it.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS: conversion succeeds
+ * \li ISC_R_FAILURE: conversion fails
+ */
+isc_result_t
+isc_netscope_pton(int af, char *scopename, void *addr, uint32_t *zoneid);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NETSCOPE_H */
diff --git a/lib/isc/include/isc/nonce.h b/lib/isc/include/isc/nonce.h
new file mode 100644
index 0000000..b593e41
--- /dev/null
+++ b/lib/isc/include/isc/nonce.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+#include <stdlib.h>
+
+#include <isc/lang.h>
+
+/*! \file isc/nonce.h
+ * \brief Provides a function for generating an arbitrarily long nonce.
+ */
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_nonce_buf(void *buf, size_t buflen);
+/*!<
+ * Fill 'buf', up to 'buflen' bytes, with random data from the
+ * crypto provider's random function.
+ */
+
+ISC_LANG_ENDDECLS
diff --git a/lib/isc/include/isc/os.h b/lib/isc/include/isc/os.h
new file mode 100644
index 0000000..585abc0
--- /dev/null
+++ b/lib/isc/include/isc/os.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_OS_H
+#define ISC_OS_H 1
+
+/*! \file isc/os.h */
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+unsigned int
+isc_os_ncpus(void);
+/*%<
+ * Return the number of CPUs available on the system, or 1 if this cannot
+ * be determined.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_OS_H */
diff --git a/lib/isc/include/isc/parseint.h b/lib/isc/include/isc/parseint.h
new file mode 100644
index 0000000..d41c57e
--- /dev/null
+++ b/lib/isc/include/isc/parseint.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_PARSEINT_H
+#define ISC_PARSEINT_H 1
+
+#include <inttypes.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*! \file isc/parseint.h
+ * \brief Parse integers, in a saner way than atoi() or strtoul() do.
+ */
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_parse_uint32(uint32_t *uip, const char *string, int base);
+
+isc_result_t
+isc_parse_uint16(uint16_t *uip, const char *string, int base);
+
+isc_result_t
+isc_parse_uint8(uint8_t *uip, const char *string, int base);
+/*%<
+ * Parse the null-terminated string 'string' containing a base 'base'
+ * integer, storing the result in '*uip'.
+ * The base is interpreted
+ * as in strtoul(). Unlike strtoul(), leading whitespace, minus or
+ * plus signs are not accepted, and all errors (including overflow)
+ * are reported uniformly through the return value.
+ *
+ * Requires:
+ *\li 'string' points to a null-terminated string
+ *\li 0 <= 'base' <= 36
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_BADNUMBER The string is not numeric (in the given base)
+ *\li #ISC_R_RANGE The number is not representable as the requested type.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_PARSEINT_H */
diff --git a/lib/isc/include/isc/platform.h.in b/lib/isc/include/isc/platform.h.in
new file mode 100644
index 0000000..85b468c
--- /dev/null
+++ b/lib/isc/include/isc/platform.h.in
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_PLATFORM_H
+#define ISC_PLATFORM_H 1
+
+/*! \file */
+
+/*****
+ ***** Platform-dependent defines.
+ *****/
+
+/***
+ *** Default strerror_r buffer size
+ ***/
+
+#define ISC_STRERRORSIZE 128
+
+/***
+ *** System limitations
+ ***/
+
+#include <limits.h>
+
+#ifndef NAME_MAX
+#define NAME_MAX 256
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#ifndef IOV_MAX
+#define IOV_MAX 1024
+#endif
+
+/***
+ *** Miscellaneous.
+ ***/
+
+/*
+ * Defined to <gssapi.h> or <gssapi/gssapi.h> for how to include
+ * the GSSAPI header.
+ */
+@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@
+
+/*
+ * Define if the platform has <sys/un.h>.
+ */
+@ISC_PLATFORM_HAVESYSUNH@
+
+/*
+ * Defines for the noreturn attribute.
+ */
+@ISC_PLATFORM_NORETURN_PRE@
+@ISC_PLATFORM_NORETURN_POST@
+
+/***
+ *** Windows dll support.
+ ***/
+
+#define LIBISC_EXTERNAL_DATA
+#define LIBDNS_EXTERNAL_DATA
+#define LIBISCCC_EXTERNAL_DATA
+#define LIBISCCFG_EXTERNAL_DATA
+#define LIBNS_EXTERNAL_DATA
+#define LIBBIND9_EXTERNAL_DATA
+#define LIBTESTS_EXTERNAL_DATA
+
+/*
+ * Tell emacs to use C mode for this file.
+ *
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
+#endif /* ISC_PLATFORM_H */
diff --git a/lib/isc/include/isc/pool.h b/lib/isc/include/isc/pool.h
new file mode 100644
index 0000000..b354c18
--- /dev/null
+++ b/lib/isc/include/isc/pool.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_OBJPOOL_H
+#define ISC_OBJPOOL_H 1
+
+/*****
+***** Module Info
+*****/
+
+/*! \file isc/pool.h
+ * \brief An object pool is a mechanism for sharing a small pool of
+ * fungible objects among a large number of objects that depend on them.
+ *
+ * This is useful, for example, when it causes performance problems for
+ * large number of zones to share a single memory context or task object,
+ * but it would create a different set of problems for them each to have an
+ * independent task or memory context.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/lang.h>
+#include <isc/mem.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*****
+***** Types.
+*****/
+
+typedef void (*isc_pooldeallocator_t)(void **object);
+
+typedef isc_result_t (*isc_poolinitializer_t)(void **target, void *arg);
+
+typedef struct isc_pool isc_pool_t;
+
+/*****
+***** Functions.
+*****/
+
+isc_result_t
+isc_pool_create(isc_mem_t *mctx, unsigned int count, isc_pooldeallocator_t free,
+ isc_poolinitializer_t init, void *initarg, isc_pool_t **poolp);
+/*%<
+ * Create a pool of "count" object pointers. If 'free' is not NULL,
+ * it points to a function that will detach the objects. 'init'
+ * points to a function that will initialize the arguments, and
+ * 'arg' to an argument to be passed into that function (for example,
+ * a relevant manager or context object).
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li init != NULL
+ *
+ *\li poolp != NULL && *poolp == NULL
+ *
+ * Ensures:
+ *
+ *\li On success, '*poolp' points to the new object pool.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_UNEXPECTED
+ */
+
+void *
+isc_pool_get(isc_pool_t *pool);
+/*%<
+ * Returns a pointer to an object from the pool. Currently the object
+ * is chosen from the pool at random. (This may be changed in the future
+ * to something that guaratees balance.)
+ */
+
+int
+isc_pool_count(isc_pool_t *pool);
+/*%<
+ * Returns the number of objcts in the pool 'pool'.
+ */
+
+isc_result_t
+isc_pool_expand(isc_pool_t **sourcep, unsigned int count, isc_pool_t **targetp);
+
+/*%<
+ * If 'size' is larger than the number of objects in the pool pointed to by
+ * 'sourcep', then a new pool of size 'count' is allocated, the existing
+ * objects are copied into it, additional ones created to bring the
+ * total number up to 'count', and the resulting pool is attached to
+ * 'targetp'.
+ *
+ * If 'count' is less than or equal to the number of objects in '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
+isc_pool_destroy(isc_pool_t **poolp);
+/*%<
+ * Destroy a task pool. The tasks in the pool are detached but not
+ * shut down.
+ *
+ * Requires:
+ * \li '*poolp' is a valid task pool.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_OBJPOOL_H */
diff --git a/lib/isc/include/isc/portset.h b/lib/isc/include/isc/portset.h
new file mode 100644
index 0000000..fbdde82
--- /dev/null
+++ b/lib/isc/include/isc/portset.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file isc/portset.h
+ * \brief Transport Protocol Port Manipulation Module
+ *
+ * This module provides simple utilities to handle a set of transport protocol
+ * (UDP or TCP) port numbers, e.g., for creating an ACL list. An isc_portset_t
+ * object is an opaque instance of a port set, for which the user can add or
+ * remove a specific port or a range of consecutive ports. This object is
+ * expected to be used as a temporary work space only, and does not protect
+ * simultaneous access from multiple threads. Therefore it must not be stored
+ * in a place that can be accessed from multiple threads.
+ */
+
+#ifndef ISC_PORTSET_H
+#define ISC_PORTSET_H 1
+
+/***
+ *** Imports
+ ***/
+
+#include <stdbool.h>
+
+#include <isc/net.h>
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_portset_create(isc_mem_t *mctx, isc_portset_t **portsetp);
+/*%<
+ * Create a port set and initialize it as an empty set.
+ *
+ * Requires:
+ *\li 'mctx' to be valid.
+ *\li 'portsetp' to be non NULL and '*portsetp' to be NULL;
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+void
+isc_portset_destroy(isc_mem_t *mctx, isc_portset_t **portsetp);
+/*%<
+ * Destroy a port set.
+ *
+ * Requires:
+ *\li 'mctx' to be valid and must be the same context given when the port set
+ * was created.
+ *\li '*portsetp' to be a valid set.
+ */
+
+bool
+isc_portset_isset(isc_portset_t *portset, in_port_t port);
+/*%<
+ * Test whether the given port is stored in the portset.
+ *
+ * Requires:
+ *\li 'portset' to be a valid set.
+ *
+ * Returns
+ * \li #true if the port is found, false otherwise.
+ */
+
+unsigned int
+isc_portset_nports(isc_portset_t *portset);
+/*%<
+ * Provides the number of ports stored in the given portset.
+ *
+ * Requires:
+ *\li 'portset' to be a valid set.
+ *
+ * Returns
+ * \li the number of ports stored in portset.
+ */
+
+void
+isc_portset_add(isc_portset_t *portset, in_port_t port);
+/*%<
+ * Add the given port to the portset. The port may or may not be stored in
+ * the portset.
+ *
+ * Requires:
+ *\li 'portlist' to be valid.
+ */
+
+void
+isc_portset_remove(isc_portset_t *portset, in_port_t port);
+/*%<
+ * Remove the given port to the portset. The port may or may not be stored in
+ * the portset.
+ *
+ * Requires:
+ *\li 'portlist' to be valid.
+ */
+
+void
+isc_portset_addrange(isc_portset_t *portset, in_port_t port_lo,
+ in_port_t port_hi);
+/*%<
+ * Add a subset of [port_lo, port_hi] (inclusive) to the portset. Ports in the
+ * subset may or may not be stored in portset.
+ *
+ * Requires:
+ *\li 'portlist' to be valid.
+ *\li port_lo <= port_hi
+ */
+
+void
+isc_portset_removerange(isc_portset_t *portset, in_port_t port_lo,
+ in_port_t port_hi);
+/*%<
+ * Subtract a subset of [port_lo, port_hi] (inclusive) from the portset. Ports
+ * in the subset may or may not be stored in portset.
+ *
+ * Requires:
+ *\li 'portlist' to be valid.
+ *\li port_lo <= port_hi
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_PORTSET_H */
diff --git a/lib/isc/include/isc/print.h b/lib/isc/include/isc/print.h
new file mode 100644
index 0000000..b3ae7fd
--- /dev/null
+++ b/lib/isc/include/isc/print.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_PRINT_H
+#define ISC_PRINT_H 1
+
+/*! \file isc/print.h */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/formatcheck.h> /* Required for ISC_FORMAT_PRINTF() macro. */
+#include <isc/lang.h>
+#include <isc/platform.h>
+
+/***
+ *** Functions
+ ***/
+
+#include <stdio.h>
+
+#endif /* ISC_PRINT_H */
diff --git a/lib/isc/include/isc/quota.h b/lib/isc/include/isc/quota.h
new file mode 100644
index 0000000..b9f9a24
--- /dev/null
+++ b/lib/isc/include/isc/quota.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_QUOTA_H
+#define ISC_QUOTA_H 1
+
+/*****
+***** Module Info
+*****/
+
+/*! \file isc/quota.h
+ *
+ * \brief The isc_quota_t object is a simple helper object for implementing
+ * quotas on things like the number of simultaneous connections to
+ * a server. It keeps track of the amount of quota in use, and
+ * encapsulates the locking necessary to allow multiple tasks to
+ * share a quota.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/atomic.h>
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/types.h>
+
+/*****
+***** Types.
+*****/
+
+ISC_LANG_BEGINDECLS
+
+/*% isc_quota_cb - quota callback structure */
+typedef struct isc_quota_cb isc_quota_cb_t;
+typedef void (*isc_quota_cb_func_t)(isc_quota_t *quota, void *data);
+struct isc_quota_cb {
+ int magic;
+ isc_quota_cb_func_t cb_func;
+ void *data;
+ ISC_LINK(isc_quota_cb_t) link;
+};
+
+/*% isc_quota structure */
+struct isc_quota {
+ int magic;
+ atomic_uint_fast32_t max;
+ atomic_uint_fast32_t used;
+ atomic_uint_fast32_t soft;
+ atomic_uint_fast32_t waiting;
+ isc_mutex_t cblock;
+ ISC_LIST(isc_quota_cb_t) cbs;
+};
+
+void
+isc_quota_init(isc_quota_t *quota, unsigned int max);
+/*%<
+ * Initialize a quota object.
+ */
+
+void
+isc_quota_destroy(isc_quota_t *quota);
+/*%<
+ * Destroy a quota object.
+ */
+
+void
+isc_quota_soft(isc_quota_t *quota, unsigned int soft);
+/*%<
+ * Set a soft quota.
+ */
+
+void
+isc_quota_max(isc_quota_t *quota, unsigned int max);
+/*%<
+ * Re-set a maximum quota.
+ */
+
+unsigned int
+isc_quota_getmax(isc_quota_t *quota);
+/*%<
+ * Get the maximum quota.
+ */
+
+unsigned int
+isc_quota_getsoft(isc_quota_t *quota);
+/*%<
+ * Get the soft quota.
+ */
+
+unsigned int
+isc_quota_getused(isc_quota_t *quota);
+/*%<
+ * Get the current usage of quota.
+ */
+
+isc_result_t
+isc_quota_attach(isc_quota_t *quota, isc_quota_t **p);
+/*%<
+ *
+ * Attempt to reserve one unit of 'quota', and also attaches '*p' to the quota
+ * if successful (ISC_R_SUCCESS or ISC_R_SOFTQUOTA).
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS Success
+ * \li #ISC_R_SOFTQUOTA Success soft quota reached
+ * \li #ISC_R_QUOTA Quota is full
+ */
+
+isc_result_t
+isc_quota_attach_cb(isc_quota_t *quota, isc_quota_t **p, isc_quota_cb_t *cb);
+/*%<
+ *
+ * Like isc_quota_attach(), but if there's no quota left then cb->cb_func will
+ * be called when we are attached to quota.
+ *
+ * Note: It's the caller's responsibility to make sure that we don't end up
+ * with a huge number of callbacks waiting, making it easy to create a
+ * resource exhaustion attack. For example, in the case of TCP listening,
+ * we simply don't accept new connections when the quota is exceeded, so
+ * the number of callbacks waiting in the queue will be limited by the
+ * listen() backlog.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS Success
+ * \li #ISC_R_SOFTQUOTA Success soft quota reached
+ * \li #ISC_R_QUOTA Quota is full
+ */
+
+void
+isc_quota_cb_init(isc_quota_cb_t *cb, isc_quota_cb_func_t cb_func, void *data);
+/*%<
+ * Initialize isc_quota_cb_t - setup the list, set the callback and data.
+ */
+
+void
+isc_quota_detach(isc_quota_t **p);
+/*%<
+ * Release one unit of quota, and also detaches '*p' from the quota.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_QUOTA_H */
diff --git a/lib/isc/include/isc/radix.h b/lib/isc/include/isc/radix.h
new file mode 100644
index 0000000..7c004e9
--- /dev/null
+++ b/lib/isc/include/isc/radix.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef _RADIX_H
+#define _RADIX_H
+
+#include <inttypes.h>
+#include <string.h>
+
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/net.h>
+#include <isc/refcount.h>
+#include <isc/types.h>
+
+#define NETADDR_TO_PREFIX_T(na, pt, bits) \
+ do { \
+ const void *p = na; \
+ memset(&(pt), 0, sizeof(pt)); \
+ if (p != NULL) { \
+ (pt).family = (na)->family; \
+ (pt).bitlen = (bits); \
+ if ((pt).family == AF_INET6) { \
+ memmove(&(pt).add.sin6, &(na)->type.in6, \
+ ((bits) + 7) / 8); \
+ } else \
+ memmove(&(pt).add.sin, &(na)->type.in, \
+ ((bits) + 7) / 8); \
+ } else { \
+ (pt).family = AF_UNSPEC; \
+ (pt).bitlen = 0; \
+ } \
+ isc_refcount_init(&(pt).refcount, 0); \
+ } while (0)
+
+typedef struct isc_prefix {
+ isc_mem_t *mctx;
+ unsigned int family; /* AF_INET | AF_INET6, or AF_UNSPEC for
+ * "any" */
+ unsigned int bitlen; /* 0 for "any" */
+ isc_refcount_t refcount;
+ union {
+ struct in_addr sin;
+ struct in6_addr sin6;
+ } add;
+} isc_prefix_t;
+
+typedef void (*isc_radix_destroyfunc_t)(void *);
+typedef void (*isc_radix_processfunc_t)(isc_prefix_t *, void **);
+
+#define isc_prefix_tochar(prefix) ((char *)&(prefix)->add.sin)
+#define isc_prefix_touchar(prefix) ((u_char *)&(prefix)->add.sin)
+
+/*
+ * We need "first match" when we search the radix tree to preserve
+ * compatibility with the existing ACL implementation. Radix trees
+ * naturally lend themselves to "best match". In order to get "first match"
+ * behavior, we keep track of the order in which entries are added to the
+ * tree--and when a search is made, we find all matching entries, and
+ * return the one that was added first.
+ *
+ * An IPv4 prefix and an IPv6 prefix may share a radix tree node if they
+ * have the same length and bit pattern (e.g., 127/8 and 7f::/8). To
+ * disambiguate between them, node_num and data are two-element arrays:
+ *
+ * - node_num[0] and data[0] are used for IPv4 client addresses
+ * - node_num[1] and data[1] are used for IPv6 client addresses
+ *
+ * A prefix of 0/0 (aka "any" or "none"), is always stored as IPv4,
+ * but matches all IPv6 addresses too.
+ */
+
+#define RADIX_V4 0
+#define RADIX_V6 1
+#define RADIX_FAMILIES 2
+
+#define ISC_RADIX_FAMILY(p) (((p)->family == AF_INET6) ? RADIX_V6 : RADIX_V4)
+
+typedef struct isc_radix_node {
+ isc_mem_t *mctx;
+ uint32_t bit; /* bit length of the prefix */
+ isc_prefix_t *prefix; /* who we are in radix tree */
+ struct isc_radix_node *l, *r; /* left and right children */
+ struct isc_radix_node *parent; /* may be used */
+ void *data[RADIX_FAMILIES]; /* pointers to IPv4
+ * and IPV6 data */
+ int node_num[RADIX_FAMILIES]; /* which node
+ * this was in
+ * the tree,
+ * or -1 for glue
+ * nodes */
+} isc_radix_node_t;
+
+#define RADIX_TREE_MAGIC ISC_MAGIC('R', 'd', 'x', 'T');
+#define RADIX_TREE_VALID(a) ISC_MAGIC_VALID(a, RADIX_TREE_MAGIC);
+
+typedef struct isc_radix_tree {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ isc_radix_node_t *head;
+ uint32_t maxbits; /* for IP, 32 bit addresses */
+ int num_active_node; /* for debugging purposes */
+ int num_added_node; /* total number of nodes */
+} isc_radix_tree_t;
+
+isc_result_t
+isc_radix_search(isc_radix_tree_t *radix, isc_radix_node_t **target,
+ isc_prefix_t *prefix);
+/*%<
+ * Search 'radix' for the best match to 'prefix'.
+ * Return the node found in '*target'.
+ *
+ * Requires:
+ * \li 'radix' to be valid.
+ * \li 'target' is not NULL and "*target" is NULL.
+ * \li 'prefix' to be valid.
+ *
+ * Returns:
+ * \li ISC_R_NOTFOUND
+ * \li ISC_R_SUCCESS
+ */
+
+isc_result_t
+isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
+ isc_radix_node_t *source, isc_prefix_t *prefix);
+/*%<
+ * Insert 'source' or 'prefix' into the radix tree 'radix'.
+ * Return the node added in 'target'.
+ *
+ * Requires:
+ * \li 'radix' to be valid.
+ * \li 'target' is not NULL and "*target" is NULL.
+ * \li 'prefix' to be valid or 'source' to be non NULL and contain
+ * a valid prefix.
+ *
+ * Returns:
+ * \li ISC_R_NOMEMORY
+ * \li ISC_R_SUCCESS
+ */
+
+void
+isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node);
+/*%<
+ * Remove the node 'node' from the radix tree 'radix'.
+ *
+ * Requires:
+ * \li 'radix' to be valid.
+ * \li 'node' to be valid.
+ */
+
+isc_result_t
+isc_radix_create(isc_mem_t *mctx, isc_radix_tree_t **target, int maxbits);
+/*%<
+ * Create a radix tree with a maximum depth of 'maxbits';
+ *
+ * Requires:
+ * \li 'mctx' to be valid.
+ * \li 'target' to be non NULL and '*target' to be NULL.
+ * \li 'maxbits' to be less than or equal to RADIX_MAXBITS.
+ *
+ * Returns:
+ * \li ISC_R_NOMEMORY
+ * \li ISC_R_SUCCESS
+ */
+
+void
+isc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func);
+/*%<
+ * Destroy a radix tree optionally calling 'func' to clean up node data.
+ *
+ * Requires:
+ * \li 'radix' to be valid.
+ */
+
+void
+isc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func);
+/*%<
+ * Walk a radix tree calling 'func' to process node data.
+ *
+ * Requires:
+ * \li 'radix' to be valid.
+ * \li 'func' to point to a function.
+ */
+
+#define RADIX_MAXBITS 128
+#define RADIX_NBIT(x) (0x80 >> ((x)&0x7f))
+#define RADIX_NBYTE(x) ((x) >> 3)
+
+#define RADIX_WALK(Xhead, Xnode) \
+ do { \
+ isc_radix_node_t *Xstack[RADIX_MAXBITS + 1]; \
+ isc_radix_node_t **Xsp = Xstack; \
+ isc_radix_node_t *Xrn = (Xhead); \
+ while ((Xnode = Xrn)) { \
+ if (Xnode->prefix)
+
+#define RADIX_WALK_END \
+ if (Xrn->l) { \
+ if (Xrn->r) { \
+ *Xsp++ = Xrn->r; \
+ } \
+ Xrn = Xrn->l; \
+ } else if (Xrn->r) { \
+ Xrn = Xrn->r; \
+ } else if (Xsp != Xstack) { \
+ Xrn = *(--Xsp); \
+ } else { \
+ Xrn = (isc_radix_node_t *)0; \
+ } \
+ } \
+ } \
+ while (0)
+
+#endif /* _RADIX_H */
diff --git a/lib/isc/include/isc/random.h b/lib/isc/include/isc/random.h
new file mode 100644
index 0000000..1e30d0c
--- /dev/null
+++ b/lib/isc/include/isc/random.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+#include <inttypes.h>
+#include <stdlib.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*! \file isc/random.h
+ * \brief Implements wrapper around a non-cryptographically secure
+ * pseudo-random number generator.
+ *
+ */
+
+ISC_LANG_BEGINDECLS
+
+uint8_t
+isc_random8(void);
+/*!<
+ * \brief Returns a single 8-bit random value.
+ */
+
+uint16_t
+isc_random16(void);
+/*!<
+ * \brief Returns a single 16-bit random value.
+ */
+
+uint32_t
+isc_random32(void);
+/*!<
+ * \brief Returns a single 32-bit random value.
+ */
+
+void
+isc_random_buf(void *buf, size_t buflen);
+/*!<
+ * \brief Fills the region buf of length buflen with random data.
+ */
+
+uint32_t
+isc_random_uniform(uint32_t upper_bound);
+/*!<
+ * \brief Will return a single 32-bit value, uniformly distributed but
+ * less than upper_bound. This is recommended over
+ * constructions like ``isc_random() % upper_bound'' as it
+ * avoids "modulo bias" when the upper bound is not a power of
+ * two. In the worst case, this function may require multiple
+ * iterations to ensure uniformity.
+ */
+
+ISC_LANG_ENDDECLS
diff --git a/lib/isc/include/isc/ratelimiter.h b/lib/isc/include/isc/ratelimiter.h
new file mode 100644
index 0000000..08862dc
--- /dev/null
+++ b/lib/isc/include/isc/ratelimiter.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_RATELIMITER_H
+#define ISC_RATELIMITER_H 1
+
+/*****
+***** Module Info
+*****/
+
+/*! \file isc/ratelimiter.h
+ * \brief A rate limiter is a mechanism for dispatching events at a limited
+ * rate. This is intended to be used when sending zone maintenance
+ * SOA queries, NOTIFY messages, etc.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*****
+***** Functions.
+*****/
+
+isc_result_t
+isc_ratelimiter_create(isc_mem_t *mctx, isc_timermgr_t *timermgr,
+ isc_task_t *task, isc_ratelimiter_t **ratelimiterp);
+/*%<
+ * Create a rate limiter. The execution interval is initially undefined.
+ */
+
+isc_result_t
+isc_ratelimiter_setinterval(isc_ratelimiter_t *rl, isc_interval_t *interval);
+/*!<
+ * Set the minimum interval between event executions.
+ * The interval value is copied, so the caller need not preserve it.
+ *
+ * Requires:
+ * '*interval' is a nonzero interval.
+ */
+
+void
+isc_ratelimiter_setpertic(isc_ratelimiter_t *rl, uint32_t perint);
+/*%<
+ * Set the number of events processed per interval timer tick.
+ * If 'perint' is zero it is treated as 1.
+ */
+
+void
+isc_ratelimiter_setpushpop(isc_ratelimiter_t *rl, bool pushpop);
+/*%<
+ * Set / clear the ratelimiter to from push pop mode rather
+ * first in - first out mode (default).
+ */
+
+isc_result_t
+isc_ratelimiter_enqueue(isc_ratelimiter_t *rl, isc_task_t *task,
+ isc_event_t **eventp);
+/*%<
+ * Queue an event for rate-limited execution.
+ *
+ * This is similar
+ * to doing an isc_task_send() to the 'task', except that the
+ * execution may be delayed to achieve the desired rate of
+ * execution.
+ *
+ * '(*eventp)->ev_sender' is used to hold the task. The caller
+ * must ensure that the task exists until the event is delivered.
+ *
+ * Requires:
+ *\li An interval has been set by calling
+ * isc_ratelimiter_setinterval().
+ *
+ *\li 'task' to be non NULL.
+ *\li '(*eventp)->ev_sender' to be NULL.
+ */
+
+isc_result_t
+isc_ratelimiter_dequeue(isc_ratelimiter_t *rl, isc_event_t *event);
+/*
+ * Dequeue a event off the ratelimiter queue.
+ *
+ * Returns:
+ * \li ISC_R_NOTFOUND if the event is no longer linked to the rate limiter.
+ * \li ISC_R_SUCCESS
+ */
+
+void
+isc_ratelimiter_shutdown(isc_ratelimiter_t *ratelimiter);
+/*%<
+ * Shut down a rate limiter.
+ *
+ * Ensures:
+ *\li All events that have not yet been
+ * dispatched to the task are dispatched immediately with
+ * the #ISC_EVENTATTR_CANCELED bit set in ev_attributes.
+ *
+ *\li Further attempts to enqueue events will fail with
+ * #ISC_R_SHUTTINGDOWN.
+ *
+ *\li The rate limiter is no longer attached to its task.
+ */
+
+void
+isc_ratelimiter_attach(isc_ratelimiter_t *source, isc_ratelimiter_t **target);
+/*%<
+ * Attach to a rate limiter.
+ */
+
+void
+isc_ratelimiter_detach(isc_ratelimiter_t **ratelimiterp);
+/*%<
+ * Detach from a rate limiter.
+ */
+
+isc_result_t
+isc_ratelimiter_stall(isc_ratelimiter_t *rl);
+/*%<
+ * Stall event processing.
+ */
+
+isc_result_t
+isc_ratelimiter_release(isc_ratelimiter_t *rl);
+/*%<
+ * Release a stalled rate limiter.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_RATELIMITER_H */
diff --git a/lib/isc/include/isc/refcount.h b/lib/isc/include/isc/refcount.h
new file mode 100644
index 0000000..68e512c
--- /dev/null
+++ b/lib/isc/include/isc/refcount.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+#include <inttypes.h>
+
+#include <isc/assertions.h>
+#include <isc/atomic.h>
+#include <isc/error.h>
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+
+/*! \file isc/refcount.h
+ * \brief Implements a locked reference counter.
+ *
+ * These macros uses C11(-like) atomic functions to implement reference
+ * counting. The isc_refcount_t type must not be accessed directly.
+ */
+
+ISC_LANG_BEGINDECLS
+
+typedef atomic_uint_fast32_t isc_refcount_t;
+
+/** \def isc_refcount_init(ref, n)
+ * \brief Initialize the reference counter.
+ * \param[in] ref pointer to reference counter.
+ * \param[in] n an initial number of references.
+ * \return nothing.
+ *
+ * \warning No memory barrier are being imposed here.
+ */
+#define isc_refcount_init(target, value) atomic_init(target, value)
+
+/** \def isc_refcount_current(ref)
+ * \brief Returns current number of references.
+ * \param[in] ref pointer to reference counter.
+ * \returns current value of reference counter.
+ *
+ * Undo implicit promotion to 64 bits in our Windows implementation of
+ * atomic_load_explicit() by casting to uint_fast32_t.
+ */
+
+#define isc_refcount_current(target) (uint_fast32_t) atomic_load_acquire(target)
+
+/** \def isc_refcount_destroy(ref)
+ * \brief a destructor that makes sure that all references were cleared.
+ * \param[in] ref pointer to reference counter.
+ * \returns nothing.
+ */
+#define isc_refcount_destroy(target) \
+ ISC_REQUIRE(isc_refcount_current(target) == 0)
+
+/** \def isc_refcount_increment0(ref)
+ * \brief increases reference counter by 1.
+ * \param[in] ref pointer to reference counter.
+ * \returns previous value of reference counter.
+ */
+#if _MSC_VER
+static inline uint_fast32_t
+isc_refcount_increment0(isc_refcount_t *target) {
+ uint_fast32_t __v;
+ __v = (uint_fast32_t)atomic_fetch_add_relaxed(target, 1);
+ INSIST(__v < UINT32_MAX);
+ return (__v);
+}
+#else /* _MSC_VER */
+#define isc_refcount_increment0(target) \
+ ({ \
+ /* cppcheck-suppress shadowVariable */ \
+ uint_fast32_t __v; \
+ __v = atomic_fetch_add_relaxed(target, 1); \
+ INSIST(__v < UINT32_MAX); \
+ __v; \
+ })
+#endif /* _MSC_VER */
+
+/** \def isc_refcount_increment(ref)
+ * \brief increases reference counter by 1.
+ * \param[in] ref pointer to reference counter.
+ * \returns previous value of reference counter.
+ */
+#if _MSC_VER
+static inline uint_fast32_t
+isc_refcount_increment(isc_refcount_t *target) {
+ uint_fast32_t __v;
+ __v = (uint_fast32_t)atomic_fetch_add_relaxed(target, 1);
+ INSIST(__v > 0 && __v < UINT32_MAX);
+ return (__v);
+}
+#else /* _MSC_VER */
+#define isc_refcount_increment(target) \
+ ({ \
+ /* cppcheck-suppress shadowVariable */ \
+ uint_fast32_t __v; \
+ __v = atomic_fetch_add_relaxed(target, 1); \
+ INSIST(__v > 0 && __v < UINT32_MAX); \
+ __v; \
+ })
+#endif /* _MSC_VER */
+
+/** \def isc_refcount_decrement(ref)
+ * \brief decreases reference counter by 1.
+ * \param[in] ref pointer to reference counter.
+ * \returns previous value of reference counter.
+ */
+#if _MSC_VER
+static inline uint_fast32_t
+isc_refcount_decrement(isc_refcount_t *target) {
+ uint_fast32_t __v;
+ __v = (uint_fast32_t)atomic_fetch_sub_acq_rel(target, 1);
+ INSIST(__v > 0);
+ return (__v);
+}
+#else /* _MSC_VER */
+#define isc_refcount_decrement(target) \
+ ({ \
+ /* cppcheck-suppress shadowVariable */ \
+ uint_fast32_t __v; \
+ __v = atomic_fetch_sub_acq_rel(target, 1); \
+ INSIST(__v > 0); \
+ __v; \
+ })
+#endif /* _MSC_VER */
+
+#define isc_refcount_decrementz(target) \
+ do { \
+ uint_fast32_t _refs = isc_refcount_decrement(target); \
+ ISC_INSIST(_refs == 1); \
+ } while (0)
+
+#define isc_refcount_decrement1(target) \
+ do { \
+ uint_fast32_t _refs = isc_refcount_decrement(target); \
+ ISC_INSIST(_refs > 1); \
+ } while (0)
+
+#define isc_refcount_decrement0(target) \
+ do { \
+ uint_fast32_t _refs = isc_refcount_decrement(target); \
+ ISC_INSIST(_refs > 0); \
+ } while (0)
+
+ISC_LANG_ENDDECLS
diff --git a/lib/isc/include/isc/regex.h b/lib/isc/include/isc/regex.h
new file mode 100644
index 0000000..f288d86
--- /dev/null
+++ b/lib/isc/include/isc/regex.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_REGEX_H
+#define ISC_REGEX_H 1
+
+/*! \file isc/regex.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+int
+isc_regex_validate(const char *expression);
+/*%<
+ * Check a regular expression for syntactic correctness.
+ *
+ * Returns:
+ *\li -1 on error.
+ *\li the number of groups in the expression.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_REGEX_H */
diff --git a/lib/isc/include/isc/region.h b/lib/isc/include/isc/region.h
new file mode 100644
index 0000000..c386617
--- /dev/null
+++ b/lib/isc/include/isc/region.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_REGION_H
+#define ISC_REGION_H 1
+
+/*! \file isc/region.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+struct isc_region {
+ unsigned char *base;
+ unsigned int length;
+};
+
+struct isc_textregion {
+ char *base;
+ unsigned int length;
+};
+
+/* XXXDCL questionable ... bears discussion. we have been putting off
+ * discussing the region api.
+ */
+struct isc_constregion {
+ const void *base;
+ unsigned int length;
+};
+
+struct isc_consttextregion {
+ const char *base;
+ unsigned int length;
+};
+
+/*@{*/
+/*!
+ * The region structure is not opaque, and is usually directly manipulated.
+ * Some macros are defined below for convenience.
+ */
+
+#define isc_region_consume(r, l) \
+ do { \
+ isc_region_t *_r = (r); \
+ unsigned int _l = (l); \
+ INSIST(_r->length >= _l); \
+ _r->base += _l; \
+ _r->length -= _l; \
+ } while (0)
+
+#define isc_textregion_consume(r, l) \
+ do { \
+ isc_textregion_t *_r = (r); \
+ unsigned int _l = (l); \
+ INSIST(_r->length >= _l); \
+ _r->base += _l; \
+ _r->length -= _l; \
+ } while (0)
+
+#define isc_constregion_consume(r, l) \
+ do { \
+ isc_constregion_t *_r = (r); \
+ unsigned int _l = (l); \
+ INSIST(_r->length >= _l); \
+ _r->base += _l; \
+ _r->length -= _l; \
+ } while (0)
+/*@}*/
+
+ISC_LANG_BEGINDECLS
+
+int
+isc_region_compare(isc_region_t *r1, isc_region_t *r2);
+/*%<
+ * Compares the contents of two regions
+ *
+ * Requires:
+ *\li 'r1' is a valid region
+ *\li 'r2' is a valid region
+ *
+ * Returns:
+ *\li < 0 if r1 is lexicographically less than r2
+ *\li = 0 if r1 is lexicographically identical to r2
+ *\li > 0 if r1 is lexicographically greater than r2
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_REGION_H */
diff --git a/lib/isc/include/isc/resource.h b/lib/isc/include/isc/resource.h
new file mode 100644
index 0000000..f9e6e20
--- /dev/null
+++ b/lib/isc/include/isc/resource.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_RESOURCE_H
+#define ISC_RESOURCE_H 1
+
+/*! \file isc/resource.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#define ISC_RESOURCE_UNLIMITED ((isc_resourcevalue_t)UINT64_MAX)
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value);
+/*%<
+ * Set the maximum limit for a system resource.
+ *
+ * Notes:
+ *\li If 'value' exceeds the maximum possible on the operating system,
+ * it is silently limited to that maximum -- or to "infinity", if
+ * the operating system has that concept. #ISC_RESOURCE_UNLIMITED
+ * can be used to explicitly ask for the maximum.
+ *
+ * Requires:
+ *\li 'resource' is a valid member of the isc_resource_t enumeration.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success.
+ *\li #ISC_R_NOTIMPLEMENTED 'resource' is not a type known by the OS.
+ *\li #ISC_R_NOPERM The calling process did not have adequate permission
+ * to change the resource limit.
+ */
+
+isc_result_t
+isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value);
+/*%<
+ * Get the maximum limit for a system resource.
+ *
+ * Notes:
+ *\li 'value' is set to the maximum limit.
+ *
+ *\li #ISC_RESOURCE_UNLIMITED is the maximum value of isc_resourcevalue_t.
+ *
+ *\li On many (all?) Unix systems, RLIM_INFINITY is a valid value that is
+ * significantly less than #ISC_RESOURCE_UNLIMITED, but which in practice
+ * behaves the same.
+ *
+ *\li The current ISC libdns configuration file parser assigns a value
+ * of UINT32_MAX for a size_spec of "unlimited" and ISC_UNIT32_MAX - 1
+ * for "default", the latter of which is supposed to represent "the
+ * limit that was in force when the server started". Since these are
+ * valid values in the middle of the range of isc_resourcevalue_t,
+ * there is the possibility for confusion over what exactly those
+ * particular values are supposed to represent in a particular context --
+ * discrete integral values or generalized concepts.
+ *
+ * Requires:
+ *\li 'resource' is a valid member of the isc_resource_t enumeration.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success.
+ *\li #ISC_R_NOTIMPLEMENTED 'resource' is not a type known by the OS.
+ */
+
+isc_result_t
+isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value);
+/*%<
+ * Same as isc_resource_getlimit(), but returns the current (soft) limit.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success.
+ *\li #ISC_R_NOTIMPLEMENTED 'resource' is not a type known by the OS.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_RESOURCE_H */
diff --git a/lib/isc/include/isc/result.h b/lib/isc/include/isc/result.h
new file mode 100644
index 0000000..11ff7f6
--- /dev/null
+++ b/lib/isc/include/isc/result.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_RESULT_H
+#define ISC_RESULT_H 1
+
+/*! \file isc/result.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#define ISC_R_SUCCESS 0 /*%< success */
+#define ISC_R_NOMEMORY 1 /*%< out of memory */
+#define ISC_R_TIMEDOUT 2 /*%< timed out */
+#define ISC_R_NOTHREADS 3 /*%< no available threads */
+#define ISC_R_ADDRNOTAVAIL 4 /*%< address not available */
+#define ISC_R_ADDRINUSE 5 /*%< address in use */
+#define ISC_R_NOPERM 6 /*%< permission denied */
+#define ISC_R_NOCONN 7 /*%< no pending connections */
+#define ISC_R_NETUNREACH 8 /*%< network unreachable */
+#define ISC_R_HOSTUNREACH 9 /*%< host unreachable */
+#define ISC_R_NETDOWN 10 /*%< network down */
+#define ISC_R_HOSTDOWN 11 /*%< host down */
+#define ISC_R_CONNREFUSED 12 /*%< connection refused */
+#define ISC_R_NORESOURCES 13 /*%< not enough free resources */
+#define ISC_R_EOF 14 /*%< end of file */
+#define ISC_R_BOUND 15 /*%< socket already bound */
+#define ISC_R_RELOAD 16 /*%< reload */
+#define ISC_R_SUSPEND ISC_R_RELOAD /*%< alias of 'reload' */
+#define ISC_R_LOCKBUSY 17 /*%< lock busy */
+#define ISC_R_EXISTS 18 /*%< already exists */
+#define ISC_R_NOSPACE 19 /*%< ran out of space */
+#define ISC_R_CANCELED 20 /*%< operation canceled */
+#define ISC_R_NOTBOUND 21 /*%< socket is not bound */
+#define ISC_R_SHUTTINGDOWN 22 /*%< shutting down */
+#define ISC_R_NOTFOUND 23 /*%< not found */
+#define ISC_R_UNEXPECTEDEND 24 /*%< unexpected end of input */
+#define ISC_R_FAILURE 25 /*%< generic failure */
+#define ISC_R_IOERROR 26 /*%< I/O error */
+#define ISC_R_NOTIMPLEMENTED 27 /*%< not implemented */
+#define ISC_R_UNBALANCED 28 /*%< unbalanced parentheses */
+#define ISC_R_NOMORE 29 /*%< no more */
+#define ISC_R_INVALIDFILE 30 /*%< invalid file */
+#define ISC_R_BADBASE64 31 /*%< bad base64 encoding */
+#define ISC_R_UNEXPECTEDTOKEN 32 /*%< unexpected token */
+#define ISC_R_QUOTA 33 /*%< quota reached */
+#define ISC_R_UNEXPECTED 34 /*%< unexpected error */
+#define ISC_R_ALREADYRUNNING 35 /*%< already running */
+#define ISC_R_IGNORE 36 /*%< ignore */
+#define ISC_R_MASKNONCONTIG 37 /*%< addr mask not contiguous */
+#define ISC_R_FILENOTFOUND 38 /*%< file not found */
+#define ISC_R_FILEEXISTS 39 /*%< file already exists */
+#define ISC_R_NOTCONNECTED 40 /*%< socket is not connected */
+#define ISC_R_RANGE 41 /*%< out of range */
+#define ISC_R_NOENTROPY 42 /*%< out of entropy */
+#define ISC_R_MULTICAST 43 /*%< invalid use of multicast */
+#define ISC_R_NOTFILE 44 /*%< not a file */
+#define ISC_R_NOTDIRECTORY 45 /*%< not a directory */
+#define ISC_R_EMPTY 46 /*%< queue is empty */
+#define ISC_R_FAMILYMISMATCH 47 /*%< address family mismatch */
+#define ISC_R_FAMILYNOSUPPORT 48 /*%< AF not supported */
+#define ISC_R_BADHEX 49 /*%< bad hex encoding */
+#define ISC_R_TOOMANYOPENFILES 50 /*%< too many open files */
+#define ISC_R_NOTBLOCKING 51 /*%< not blocking */
+#define ISC_R_UNBALANCEDQUOTES 52 /*%< unbalanced quotes */
+#define ISC_R_INPROGRESS 53 /*%< operation in progress */
+#define ISC_R_CONNECTIONRESET 54 /*%< connection reset */
+#define ISC_R_SOFTQUOTA 55 /*%< soft quota reached */
+#define ISC_R_BADNUMBER 56 /*%< not a valid number */
+#define ISC_R_DISABLED 57 /*%< disabled */
+#define ISC_R_MAXSIZE 58 /*%< max size */
+#define ISC_R_BADADDRESSFORM 59 /*%< invalid address format */
+#define ISC_R_BADBASE32 60 /*%< bad base32 encoding */
+#define ISC_R_UNSET 61 /*%< unset */
+#define ISC_R_MULTIPLE 62 /*%< multiple */
+#define ISC_R_WOULDBLOCK 63 /*%< would block */
+#define ISC_R_COMPLETE 64 /*%< complete */
+#define ISC_R_CRYPTOFAILURE 65 /*%< cryptography library failure */
+#define ISC_R_DISCQUOTA 66 /*%< disc quota */
+#define ISC_R_DISCFULL 67 /*%< disc full */
+#define ISC_R_DEFAULT 68 /*%< default */
+#define ISC_R_IPV4PREFIX 69 /*%< IPv4 prefix */
+#define ISC_R_TLSERROR 70 /*%< TLS error */
+#define ISC_R_HTTP2ALPNERROR 71 /*%< ALPN for HTTP/2 failed */
+
+/*% Not a result code: the number of results. */
+#define ISC_R_NRESULTS 72
+
+ISC_LANG_BEGINDECLS
+
+const char *isc_result_totext(isc_result_t);
+/*%<
+ * Convert an isc_result_t into a string message describing the result.
+ */
+
+const char *isc_result_toid(isc_result_t);
+/*%<
+ * Convert an isc_result_t into a string identifier such as
+ * "ISC_R_SUCCESS".
+ */
+
+isc_result_t
+isc_result_register(unsigned int base, unsigned int nresults, const char **text,
+ int set);
+
+isc_result_t
+isc_result_registerids(unsigned int base, unsigned int nresults,
+ const char **ids, int set);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_RESULT_H */
diff --git a/lib/isc/include/isc/resultclass.h b/lib/isc/include/isc/resultclass.h
new file mode 100644
index 0000000..a3a5079
--- /dev/null
+++ b/lib/isc/include/isc/resultclass.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_RESULTCLASS_H
+#define ISC_RESULTCLASS_H 1
+
+/*! \file isc/resultclass.h
+ * \brief Registry of Predefined Result Type Classes
+ *
+ * A result class number is an unsigned 16 bit number. Each class may
+ * contain up to 65536 results. A result code is formed by adding the
+ * result number within the class to the class number multiplied by 65536.
+ *
+ * Classes < 1024 are reserved for ISC use.
+ * Result classes >= 1024 and <= 65535 are reserved for application use.
+ */
+
+#define ISC_RESULTCLASS_FROMNUM(num) ((num) << 16)
+#define ISC_RESULTCLASS_TONUM(rclass) ((rclass) >> 16)
+#define ISC_RESULTCLASS_SIZE 65536
+#define ISC_RESULTCLASS_INCLASS(rclass, result) \
+ ((rclass) == ((result)&0xFFFF0000))
+
+#define ISC_RESULTCLASS_ISC ISC_RESULTCLASS_FROMNUM(0)
+#define ISC_RESULTCLASS_DNS ISC_RESULTCLASS_FROMNUM(1)
+#define ISC_RESULTCLASS_DST ISC_RESULTCLASS_FROMNUM(2)
+#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)
+#define ISC_RESULTCLASS_PK11 ISC_RESULTCLASS_FROMNUM(7)
+
+#endif /* ISC_RESULTCLASS_H */
diff --git a/lib/isc/include/isc/rwlock.h b/lib/isc/include/isc/rwlock.h
new file mode 100644
index 0000000..3309d71
--- /dev/null
+++ b/lib/isc/include/isc/rwlock.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_RWLOCK_H
+#define ISC_RWLOCK_H 1
+
+#include <inttypes.h>
+
+/*! \file isc/rwlock.h */
+
+#include <isc/atomic.h>
+#include <isc/condition.h>
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef enum {
+ isc_rwlocktype_none = 0,
+ isc_rwlocktype_read,
+ isc_rwlocktype_write
+} isc_rwlocktype_t;
+
+#if USE_PTHREAD_RWLOCK
+#include <pthread.h>
+
+struct isc_rwlock {
+ pthread_rwlock_t rwlock;
+ atomic_bool downgrade;
+};
+
+#else /* USE_PTHREAD_RWLOCK */
+
+struct isc_rwlock {
+ /* Unlocked. */
+ unsigned int magic;
+ isc_mutex_t lock;
+ atomic_int_fast32_t spins;
+
+ /*
+ * When some atomic instructions with hardware assistance are
+ * available, rwlock will use those so that concurrent readers do not
+ * interfere with each other through mutex as long as no writers
+ * appear, massively reducing the lock overhead in the typical case.
+ *
+ * The basic algorithm of this approach is the "simple
+ * writer-preference lock" shown in the following URL:
+ * http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/rw.html
+ * but our implementation does not rely on the spin lock unlike the
+ * original algorithm to be more portable as a user space application.
+ */
+
+ /* Read or modified atomically. */
+ atomic_int_fast32_t write_requests;
+ atomic_int_fast32_t write_completions;
+ atomic_int_fast32_t cnt_and_flag;
+
+ /* Locked by lock. */
+ isc_condition_t readable;
+ isc_condition_t writeable;
+ unsigned int readers_waiting;
+
+ /* Locked by rwlock itself. */
+ atomic_uint_fast32_t write_granted;
+
+ /* Unlocked. */
+ unsigned int write_quota;
+};
+
+#endif /* USE_PTHREAD_RWLOCK */
+
+void
+isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
+ unsigned int write_quota);
+
+isc_result_t
+isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
+
+isc_result_t
+isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
+
+isc_result_t
+isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
+
+isc_result_t
+isc_rwlock_tryupgrade(isc_rwlock_t *rwl);
+
+void
+isc_rwlock_downgrade(isc_rwlock_t *rwl);
+
+void
+isc_rwlock_destroy(isc_rwlock_t *rwl);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_RWLOCK_H */
diff --git a/lib/isc/include/isc/safe.h b/lib/isc/include/isc/safe.h
new file mode 100644
index 0000000..f5bad62
--- /dev/null
+++ b/lib/isc/include/isc/safe.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_SAFE_H
+#define ISC_SAFE_H 1
+
+/*! \file isc/safe.h */
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+int
+isc_safe_memequal(const void *, const void *, size_t);
+
+/*%<
+ * Returns true iff. two blocks of memory are equal, otherwise
+ * false.
+ *
+ */
+
+void
+isc_safe_memwipe(void *, size_t);
+
+/*%<
+ * Clear the memory of length `len` pointed to by `ptr`.
+ *
+ * Some crypto code calls memset() on stack allocated buffers just
+ * before return so that they are wiped. Such memset() calls can be
+ * optimized away by the compiler. We provide this external non-inline C
+ * function to perform the memset operation so that the compiler cannot
+ * infer about what the function does and optimize the call away.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SAFE_H */
diff --git a/lib/isc/include/isc/serial.h b/lib/isc/include/isc/serial.h
new file mode 100644
index 0000000..e2d5225
--- /dev/null
+++ b/lib/isc/include/isc/serial.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_SERIAL_H
+#define ISC_SERIAL_H 1
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*! \file isc/serial.h
+ * \brief Implement 32 bit serial space arithmetic comparison functions.
+ * Note: Undefined results are returned as false.
+ */
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+bool
+isc_serial_lt(uint32_t a, uint32_t b);
+/*%<
+ * Return true if 'a' < 'b' otherwise false.
+ */
+
+bool
+isc_serial_gt(uint32_t a, uint32_t b);
+/*%<
+ * Return true if 'a' > 'b' otherwise false.
+ */
+
+bool
+isc_serial_le(uint32_t a, uint32_t b);
+/*%<
+ * Return true if 'a' <= 'b' otherwise false.
+ */
+
+bool
+isc_serial_ge(uint32_t a, uint32_t b);
+/*%<
+ * Return true if 'a' >= 'b' otherwise false.
+ */
+
+bool
+isc_serial_eq(uint32_t a, uint32_t b);
+/*%<
+ * Return true if 'a' == 'b' otherwise false.
+ */
+
+bool
+isc_serial_ne(uint32_t a, uint32_t b);
+/*%<
+ * Return true if 'a' != 'b' otherwise false.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SERIAL_H */
diff --git a/lib/isc/include/isc/siphash.h b/lib/isc/include/isc/siphash.h
new file mode 100644
index 0000000..3974c6f
--- /dev/null
+++ b/lib/isc/include/isc/siphash.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file isc/siphash.h */
+
+#pragma once
+
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#define ISC_SIPHASH24_KEY_LENGTH 128 / 8
+#define ISC_SIPHASH24_TAG_LENGTH 64 / 8
+
+#define ISC_HALFSIPHASH24_KEY_LENGTH 64 / 8
+#define ISC_HALFSIPHASH24_TAG_LENGTH 32 / 8
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_siphash24(const uint8_t *key, const uint8_t *in, const size_t inlen,
+ uint8_t *out);
+void
+isc_halfsiphash24(const uint8_t *key, const uint8_t *in, const size_t inlen,
+ uint8_t *out);
+
+ISC_LANG_ENDDECLS
diff --git a/lib/isc/include/isc/sockaddr.h b/lib/isc/include/isc/sockaddr.h
new file mode 100644
index 0000000..b776bb3
--- /dev/null
+++ b/lib/isc/include/isc/sockaddr.h
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_SOCKADDR_H
+#define ISC_SOCKADDR_H 1
+
+/*! \file isc/sockaddr.h */
+
+#include <stdbool.h>
+
+#include <isc/lang.h>
+#include <isc/net.h>
+#include <isc/types.h>
+#ifdef ISC_PLATFORM_HAVESYSUNH
+#include <sys/un.h>
+#endif /* ifdef ISC_PLATFORM_HAVESYSUNH */
+
+/*
+ * Any updates to this structure should also be applied in
+ * contrib/modules/dlz/dlz_minmal.h.
+ */
+struct isc_sockaddr {
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ struct sockaddr_storage ss;
+#ifdef ISC_PLATFORM_HAVESYSUNH
+ struct sockaddr_un sunix;
+#endif /* ifdef ISC_PLATFORM_HAVESYSUNH */
+ } type;
+ unsigned int length; /* XXXRTH beginning? */
+ ISC_LINK(struct isc_sockaddr) link;
+};
+
+#define ISC_SOCKADDR_CMPADDR \
+ 0x0001 /*%< compare the address \
+ * sin_addr/sin6_addr */
+#define ISC_SOCKADDR_CMPPORT \
+ 0x0002 /*%< compare the port \
+ * sin_port/sin6_port */
+#define ISC_SOCKADDR_CMPSCOPE \
+ 0x0004 /*%< compare the scope \
+ * sin6_scope */
+#define ISC_SOCKADDR_CMPSCOPEZERO \
+ 0x0008 /*%< when comparing scopes \
+ * zero scopes always match */
+
+ISC_LANG_BEGINDECLS
+
+bool
+isc_sockaddr_compare(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
+ unsigned int flags);
+/*%<
+ * Compare the elements of the two address ('a' and 'b') as specified
+ * by 'flags' and report if they are equal or not.
+ *
+ * 'flags' is set from ISC_SOCKADDR_CMP*.
+ */
+
+bool
+isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b);
+/*%<
+ * Return true iff the socket addresses 'a' and 'b' are equal.
+ */
+
+bool
+isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b);
+/*%<
+ * Return true iff the address parts of the socket addresses
+ * 'a' and 'b' are equal, ignoring the ports.
+ */
+
+bool
+isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
+ unsigned int prefixlen);
+/*%<
+ * Return true iff the most significant 'prefixlen' bits of the
+ * socket addresses 'a' and 'b' are equal, ignoring the ports.
+ * If 'b''s scope is zero then 'a''s scope will be ignored.
+ */
+
+unsigned int
+isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, bool address_only);
+/*%<
+ * Return a hash value for the socket address 'sockaddr'. If 'address_only'
+ * is true, the hash value will not depend on the port.
+ *
+ * IPv6 addresses containing mapped IPv4 addresses generate the same hash
+ * value as the equivalent IPv4 address.
+ */
+
+void
+isc_sockaddr_any(isc_sockaddr_t *sockaddr);
+/*%<
+ * Return the IPv4 wildcard address.
+ */
+
+void
+isc_sockaddr_any6(isc_sockaddr_t *sockaddr);
+/*%<
+ * Return the IPv6 wildcard address.
+ */
+
+void
+isc_sockaddr_anyofpf(isc_sockaddr_t *sockaddr, int family);
+/*%<
+ * Set '*sockaddr' to the wildcard address of protocol family
+ * 'family'.
+ *
+ * Requires:
+ * \li 'family' is AF_INET or AF_INET6.
+ */
+
+void
+isc_sockaddr_fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
+ in_port_t port);
+/*%<
+ * Construct an isc_sockaddr_t from an IPv4 address and port.
+ */
+
+void
+isc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, const struct in6_addr *ina6,
+ in_port_t port);
+/*%<
+ * Construct an isc_sockaddr_t from an IPv6 address and port.
+ */
+
+void
+isc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
+ in_port_t port);
+/*%<
+ * Construct an IPv6 isc_sockaddr_t representing a mapped IPv4 address.
+ */
+
+void
+isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na,
+ in_port_t port);
+/*%<
+ * Construct an isc_sockaddr_t from an isc_netaddr_t and port.
+ */
+
+int
+isc_sockaddr_pf(const isc_sockaddr_t *sockaddr);
+/*%<
+ * Get the protocol family of 'sockaddr'.
+ *
+ * Requires:
+ *
+ *\li 'sockaddr' is a valid sockaddr with an address family of AF_INET
+ * or AF_INET6.
+ *
+ * Returns:
+ *
+ *\li The protocol family of 'sockaddr', e.g. PF_INET or PF_INET6.
+ */
+
+void
+isc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port);
+/*%<
+ * Set the port of 'sockaddr' to 'port'.
+ */
+
+in_port_t
+isc_sockaddr_getport(const isc_sockaddr_t *sockaddr);
+/*%<
+ * Get the port stored in 'sockaddr'.
+ */
+
+isc_result_t
+isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target);
+/*%<
+ * Append a text representation of 'sockaddr' to the buffer 'target'.
+ * The text will include both the IP address (v4 or v6) and the port.
+ * The text is null terminated, but the terminating null is not
+ * part of the buffer's used region.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOSPACE The text or the null termination did not fit.
+ */
+
+void
+isc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size);
+/*%<
+ * Format a human-readable representation of the socket address '*sa'
+ * into the character array 'array', which is of size 'size'.
+ * The resulting string is guaranteed to be null-terminated.
+ */
+
+bool
+isc_sockaddr_ismulticast(const isc_sockaddr_t *sa);
+/*%<
+ * Returns #true if the address is a multicast address.
+ */
+
+bool
+isc_sockaddr_isexperimental(const isc_sockaddr_t *sa);
+/*
+ * Returns true if the address is a experimental (CLASS E) address.
+ */
+
+bool
+isc_sockaddr_islinklocal(const isc_sockaddr_t *sa);
+/*%<
+ * Returns true if the address is a link local address.
+ */
+
+bool
+isc_sockaddr_issitelocal(const isc_sockaddr_t *sa);
+/*%<
+ * Returns true if the address is a sitelocal address.
+ */
+
+bool
+isc_sockaddr_isnetzero(const isc_sockaddr_t *sa);
+/*%<
+ * Returns true if the address is in net zero.
+ */
+
+isc_result_t
+isc_sockaddr_frompath(isc_sockaddr_t *sockaddr, const char *path);
+/*
+ * Create a UNIX domain sockaddr that refers to path.
+ *
+ * Returns:
+ * \li ISC_R_NOSPACE
+ * \li ISC_R_NOTIMPLEMENTED
+ * \li ISC_R_SUCCESS
+ */
+
+isc_result_t
+isc_sockaddr_fromsockaddr(isc_sockaddr_t *isa, const struct sockaddr *sa);
+
+#define ISC_SOCKADDR_FORMATSIZE \
+ sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:XXX.XXX.XXX.XXX%SSSSSSSSSS#" \
+ "YYYYY")
+/*%<
+ * Minimum size of array to pass to isc_sockaddr_format().
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SOCKADDR_H */
diff --git a/lib/isc/include/isc/socket.h b/lib/isc/include/isc/socket.h
new file mode 100644
index 0000000..dc39a3f
--- /dev/null
+++ b/lib/isc/include/isc/socket.h
@@ -0,0 +1,914 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_SOCKET_H
+#define ISC_SOCKET_H 1
+
+/*****
+***** Module Info
+*****/
+
+/*! \file isc/socket.h
+ * \brief Provides TCP and UDP sockets for network I/O. The sockets are event
+ * sources in the task system.
+ *
+ * When I/O completes, a completion event for the socket is posted to the
+ * event queue of the task which requested the I/O.
+ *
+ * \li MP:
+ * The module ensures appropriate synchronization of data structures it
+ * creates and manipulates.
+ * Clients of this module must not be holding a socket's task's lock when
+ * making a call that affects that socket. Failure to follow this rule
+ * can result in deadlock.
+ * The caller must ensure that isc_socketmgr_destroy() is called only
+ * once for a given manager.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Resources:
+ * TBS
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/event.h>
+#include <isc/eventclass.h>
+#include <isc/lang.h>
+#include <isc/region.h>
+#include <isc/sockaddr.h>
+#include <isc/time.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Constants
+ ***/
+
+/*%
+ * Maximum number of buffers in a scatter/gather read/write. The operating
+ * system in use must support at least this number (plus one on some.)
+ */
+#define ISC_SOCKET_MAXSCATTERGATHER 8
+
+/*@{*/
+/*!
+ * Socket options:
+ *
+ * _REUSEADDRESS: Set SO_REUSEADDR prior to calling bind(),
+ * if a non-zero port is specified (applies to
+ * AF_INET and AF_INET6).
+ */
+typedef enum {
+ ISC_SOCKET_REUSEADDRESS = 0x01U,
+} isc_socket_options_t;
+/*@}*/
+
+/*@{*/
+/*!
+ * _ATTACHED: Internal use only.
+ * _TRUNC: Packet was truncated on receive.
+ * _CTRUNC: Packet control information was truncated. This can
+ * indicate that the packet is not complete, even though
+ * all the data is valid.
+ * _TIMESTAMP: The timestamp member is valid.
+ * _PKTINFO: The pktinfo member is valid.
+ * _MULTICAST: The UDP packet was received via a multicast transmission.
+ * _DSCP: The UDP DSCP value is valid.
+ * _USEMINMTU: Set the per packet IPV6_USE_MIN_MTU flag.
+ */
+typedef enum {
+ ISC_SOCKEVENTATTR_ATTACHED = 0x10000000U, /* internal */
+ ISC_SOCKEVENTATTR_TRUNC = 0x00800000U, /* public */
+ ISC_SOCKEVENTATTR_CTRUNC = 0x00400000U, /* public */
+ ISC_SOCKEVENTATTR_TIMESTAMP = 0x00200000U, /* public */
+ ISC_SOCKEVENTATTR_PKTINFO = 0x00100000U, /* public */
+ ISC_SOCKEVENTATTR_MULTICAST = 0x00080000U, /* public */
+ ISC_SOCKEVENTATTR_DSCP = 0x00040000U, /* public */
+ ISC_SOCKEVENTATTR_USEMINMTU = 0x00020000U /* public */
+} isc_sockeventattr_t;
+/*@}*/
+
+/***
+ *** Types
+ ***/
+
+struct isc_socketevent {
+ ISC_EVENT_COMMON(isc_socketevent_t);
+ isc_result_t result; /*%< OK, EOF, whatever else */
+ unsigned int minimum; /*%< minimum i/o for event */
+ unsigned int n; /*%< bytes read or written */
+ unsigned int offset; /*%< offset into buffer list */
+ isc_region_t region; /*%< for single-buffer i/o */
+ isc_sockaddr_t address; /*%< source address */
+ isc_time_t timestamp; /*%< timestamp of packet recv */
+ struct in6_pktinfo pktinfo; /*%< ipv6 pktinfo */
+ isc_sockeventattr_t attributes; /*%< see isc_sockeventattr_t
+ * enum */
+ isc_eventdestructor_t destroy; /*%< original destructor */
+ unsigned int dscp; /*%< UDP dscp value */
+};
+
+typedef struct isc_socket_newconnev isc_socket_newconnev_t;
+struct isc_socket_newconnev {
+ ISC_EVENT_COMMON(isc_socket_newconnev_t);
+ isc_socket_t *newsocket;
+ isc_result_t result; /*%< OK, EOF, whatever else */
+ isc_sockaddr_t address; /*%< source address */
+};
+
+typedef struct isc_socket_connev isc_socket_connev_t;
+struct isc_socket_connev {
+ ISC_EVENT_COMMON(isc_socket_connev_t);
+ isc_result_t result; /*%< OK, EOF, whatever else */
+};
+
+#define ISC_SOCKEVENT_ANYEVENT (0)
+#define ISC_SOCKEVENT_RECVDONE (ISC_EVENTCLASS_SOCKET + 1)
+#define ISC_SOCKEVENT_SENDDONE (ISC_EVENTCLASS_SOCKET + 2)
+#define ISC_SOCKEVENT_NEWCONN (ISC_EVENTCLASS_SOCKET + 3)
+#define ISC_SOCKEVENT_CONNECT (ISC_EVENTCLASS_SOCKET + 4)
+
+/*
+ * Internal events.
+ */
+#define ISC_SOCKEVENT_INTR (ISC_EVENTCLASS_SOCKET + 256)
+#define ISC_SOCKEVENT_INTW (ISC_EVENTCLASS_SOCKET + 257)
+
+typedef enum {
+ isc_sockettype_udp = 1,
+ isc_sockettype_tcp = 2,
+ isc_sockettype_unix = 3,
+ isc_sockettype_raw = 4
+} isc_sockettype_t;
+
+/*@{*/
+/*!
+ * How a socket should be shutdown in isc_socket_shutdown() calls.
+ */
+#define ISC_SOCKSHUT_RECV 0x00000001 /*%< close read side */
+#define ISC_SOCKSHUT_SEND 0x00000002 /*%< close write side */
+#define ISC_SOCKSHUT_ALL 0x00000003 /*%< close them all */
+/*@}*/
+
+/*@{*/
+/*!
+ * What I/O events to cancel in isc_socket_cancel() calls.
+ */
+#define ISC_SOCKCANCEL_RECV 0x00000001 /*%< cancel recv */
+#define ISC_SOCKCANCEL_SEND 0x00000002 /*%< cancel send */
+#define ISC_SOCKCANCEL_ACCEPT 0x00000004 /*%< cancel accept */
+#define ISC_SOCKCANCEL_CONNECT 0x00000008 /*%< cancel connect */
+#define ISC_SOCKCANCEL_ALL 0x0000000f /*%< cancel everything */
+/*@}*/
+
+/*@{*/
+/*!
+ * Flags for isc_socket_send() and isc_socket_recv() calls.
+ */
+#define ISC_SOCKFLAG_IMMEDIATE 0x00000001 /*%< send event only if needed */
+#define ISC_SOCKFLAG_NORETRY 0x00000002 /*%< drop failed UDP sends */
+/*@}*/
+
+/***
+ *** Socket and Socket Manager Functions
+ ***
+ *** Note: all Ensures conditions apply only if the result is success for
+ *** those functions which return an isc_result.
+ ***/
+
+isc_result_t
+isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+ isc_socket_t **socketp);
+/*%<
+ * Create a new 'type' socket managed by 'manager'.
+ *
+ * Note:
+ *
+ *\li 'pf' is the desired protocol family, e.g. PF_INET or PF_INET6.
+ *
+ * Requires:
+ *
+ *\li 'manager' is a valid manager
+ *
+ *\li 'socketp' is a valid pointer, and *socketp == NULL
+ *
+ * Ensures:
+ *
+ * '*socketp' is attached to the newly created socket
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_NORESOURCES
+ *\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);
+/*%<
+ * Cancel pending I/O of the type specified by "how".
+ *
+ * Note: if "task" is NULL, then the cancel applies to all tasks using the
+ * socket.
+ *
+ * Requires:
+ *
+ * \li "socket" is a valid socket
+ *
+ * \li "task" is NULL or a valid task
+ *
+ * "how" is a bitmask describing the type of cancellation to perform.
+ * The type ISC_SOCKCANCEL_ALL will cancel all pending I/O on this
+ * socket.
+ *
+ * \li ISC_SOCKCANCEL_RECV:
+ * Cancel pending isc_socket_recv() calls.
+ *
+ * \li ISC_SOCKCANCEL_SEND:
+ * Cancel pending isc_socket_send() and isc_socket_sendto() calls.
+ *
+ * \li ISC_SOCKCANCEL_ACCEPT:
+ * Cancel pending isc_socket_accept() calls.
+ *
+ * \li ISC_SOCKCANCEL_CONNECT:
+ * Cancel pending isc_socket_connect() call.
+ */
+
+void
+isc_socket_shutdown(isc_socket_t *sock, unsigned int how);
+/*%<
+ * Shutdown 'socket' according to 'how'.
+ *
+ * Requires:
+ *
+ * \li 'socket' is a valid socket.
+ *
+ * \li 'task' is NULL or is a valid task.
+ *
+ * \li If 'how' is 'ISC_SOCKSHUT_RECV' or 'ISC_SOCKSHUT_ALL' then
+ *
+ * The read queue must be empty.
+ *
+ * No further read requests may be made.
+ *
+ * \li If 'how' is 'ISC_SOCKSHUT_SEND' or 'ISC_SOCKSHUT_ALL' then
+ *
+ * The write queue must be empty.
+ *
+ * No further write requests may be made.
+ */
+
+void
+isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp);
+/*%<
+ * Attach *socketp to socket.
+ *
+ * Requires:
+ *
+ * \li 'socket' is a valid socket.
+ *
+ * \li 'socketp' points to a NULL socket.
+ *
+ * Ensures:
+ *
+ * \li *socketp is attached to socket.
+ */
+
+void
+isc_socket_detach(isc_socket_t **socketp);
+/*%<
+ * Detach *socketp from its socket.
+ *
+ * Requires:
+ *
+ * \li 'socketp' points to a valid socket.
+ *
+ * \li If '*socketp' is the last reference to the socket,
+ * then:
+ *
+ * There must be no pending I/O requests.
+ *
+ * Ensures:
+ *
+ * \li *socketp is NULL.
+ *
+ * \li If '*socketp' is the last reference to the socket,
+ * then:
+ *
+ * The socket will be shutdown (both reading and writing)
+ * for all tasks.
+ *
+ * All resources used by the socket have been freed
+ */
+
+isc_result_t
+isc_socket_open(isc_socket_t *sock);
+/*%<
+ * Open a new socket file descriptor of the given socket structure. It simply
+ * opens a new descriptor; all of the other parameters including the socket
+ * type are inherited from the existing socket. This function is provided to
+ * avoid overhead of destroying and creating sockets when many short-lived
+ * sockets are frequently opened and closed. When the efficiency is not an
+ * issue, it should be safer to detach the unused socket and re-create a new
+ * one. This optimization may not be available for some systems, in which
+ * case this function will return ISC_R_NOTIMPLEMENTED and must not be used.
+ *
+ * Requires:
+ *
+ * \li there must be no other reference to this socket.
+ *
+ * \li 'socket' is a valid and previously closed by isc_socket_close()
+ *
+ * Returns:
+ * Same as isc_socket_create().
+ * \li ISC_R_NOTIMPLEMENTED
+ */
+
+isc_result_t
+isc_socket_close(isc_socket_t *sock);
+/*%<
+ * Close a socket file descriptor of the given socket structure. This function
+ * is provided as an alternative to destroying an unused socket when overhead
+ * destroying/re-creating sockets can be significant, and is expected to be
+ * used with isc_socket_open(). This optimization may not be available for some
+ * systems, in which case this function will return ISC_R_NOTIMPLEMENTED and
+ * must not be used.
+ *
+ * Requires:
+ *
+ * \li The socket must have a valid descriptor.
+ *
+ * \li There must be no other reference to this socket.
+ *
+ * \li There must be no pending I/O requests.
+ *
+ * Returns:
+ * \li #ISC_R_NOTIMPLEMENTED
+ */
+
+isc_result_t
+isc_socket_bind(isc_socket_t *sock, const isc_sockaddr_t *addressp,
+ isc_socket_options_t options);
+/*%<
+ * Bind 'socket' to '*addressp'.
+ *
+ * Requires:
+ *
+ * \li 'socket' is a valid socket
+ *
+ * \li 'addressp' points to a valid isc_sockaddr.
+ *
+ * Returns:
+ *
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOPERM
+ * \li ISC_R_ADDRNOTAVAIL
+ * \li ISC_R_ADDRINUSE
+ * \li ISC_R_BOUND
+ * \li ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_filter(isc_socket_t *sock, const char *filter);
+/*%<
+ * Inform the kernel that it should perform accept filtering.
+ * If filter is NULL the current filter will be removed.
+ */
+
+isc_result_t
+isc_socket_listen(isc_socket_t *sock, unsigned int backlog);
+/*%<
+ * Set listen mode on the socket. After this call, the only function that
+ * can be used (other than attach and detach) is isc_socket_accept().
+ *
+ * Notes:
+ *
+ * \li 'backlog' is as in the UNIX system call listen() and may be
+ * ignored by non-UNIX implementations.
+ *
+ * \li If 'backlog' is zero, a reasonable system default is used, usually
+ * SOMAXCONN.
+ *
+ * Requires:
+ *
+ * \li 'socket' is a valid, bound TCP socket or a valid, bound UNIX socket.
+ *
+ * Returns:
+ *
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_accept(isc_socket_t *sock, isc_task_t *task, isc_taskaction_t action,
+ void *arg);
+/*%<
+ * Queue accept event. When a new connection is received, the task will
+ * get an ISC_SOCKEVENT_NEWCONN event with the sender set to the listen
+ * socket. The new socket structure is sent inside the isc_socket_newconnev_t
+ * event type, and is attached to the task 'task'.
+ *
+ * REQUIRES:
+ * \li 'socket' is a valid TCP socket that isc_socket_listen() was called
+ * on.
+ *
+ * \li 'task' is a valid task
+ *
+ * \li 'action' is a valid action
+ *
+ * RETURNS:
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOMEMORY
+ * \li ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_connect(isc_socket_t *sock, const isc_sockaddr_t *addressp,
+ isc_task_t *task, isc_taskaction_t action, void *arg);
+/*%<
+ * Connect 'socket' to peer with address *saddr. When the connection
+ * succeeds, or when an error occurs, a CONNECT event with action 'action'
+ * and arg 'arg' will be posted to the event queue for 'task'.
+ *
+ * Requires:
+ *
+ * \li 'socket' is a valid TCP socket
+ *
+ * \li 'addressp' points to a valid isc_sockaddr
+ *
+ * \li 'task' is a valid task
+ *
+ * \li 'action' is a valid action
+ *
+ * Returns:
+ *
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOMEMORY
+ * \li ISC_R_UNEXPECTED
+ *
+ * Posted event's result code:
+ *
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_TIMEDOUT
+ * \li ISC_R_CONNREFUSED
+ * \li ISC_R_NETUNREACH
+ * \li ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp);
+/*%<
+ * Get the name of the peer connected to 'socket'.
+ *
+ * Requires:
+ *
+ * \li 'socket' is a valid TCP socket.
+ *
+ * Returns:
+ *
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_TOOSMALL
+ * \li ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp);
+/*%<
+ * Get the name of 'socket'.
+ *
+ * Requires:
+ *
+ * \li 'socket' is a valid socket.
+ *
+ * Returns:
+ *
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_TOOSMALL
+ * \li ISC_R_UNEXPECTED
+ */
+
+/*@{*/
+isc_result_t
+isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
+ isc_task_t *task, isc_taskaction_t action, void *arg);
+
+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);
+
+/*!
+ * Receive from 'socket', storing the results in region.
+ *
+ * Notes:
+ *
+ *\li Let 'length' refer to the length of 'region' or to the sum of all
+ * available regions in the list of buffers '*buflist'.
+ *
+ *\li If 'minimum' is non-zero and at least that many bytes are read,
+ * the completion event will be posted to the task 'task.' If minimum
+ * is zero, the exact number of bytes requested in the region must
+ * be read for an event to be posted. This only makes sense for TCP
+ * connections, and is always set to 1 byte for UDP.
+ *
+ *\li The read will complete when the desired number of bytes have been
+ * read, if end-of-input occurs, or if an error occurs. A read done
+ * event with the given 'action' and 'arg' will be posted to the
+ * event queue of 'task'.
+ *
+ *\li The caller may not modify 'region', the buffers which are passed
+ * into this function, or any data they refer to until the completion
+ * event is received.
+ *
+ *\li For isc_socket_recv2():
+ * 'event' is not NULL, and the non-socket specific fields are
+ * expected to be initialized.
+ *
+ *\li For isc_socket_recv2():
+ * The only defined value for 'flags' is ISC_SOCKFLAG_IMMEDIATE. If
+ * set and the operation completes, the return value will be
+ * ISC_R_SUCCESS and the event will be filled in and not sent. If the
+ * operation does not complete, the return value will be
+ * ISC_R_INPROGRESS and the event will be sent when the operation
+ * completes.
+ *
+ * Requires:
+ *
+ *\li 'socket' is a valid, bound socket.
+ *
+ *\li For isc_socket_recv():
+ * 'region' is a valid region
+ *
+ *\li For isc_socket_recvv():
+ * 'buflist' is non-NULL, and '*buflist' contain at least one buffer.
+ *
+ *\li 'task' is a valid task
+ *
+ *\li For isc_socket_recv() and isc_socket_recvv():
+ * action != NULL and is a valid action
+ *
+ *\li For isc_socket_recv2():
+ * event != NULL
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_INPROGRESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_UNEXPECTED
+ *
+ * Event results:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_UNEXPECTED
+ *\li XXX needs other net-type errors
+ */
+/*@}*/
+
+/*@{*/
+isc_result_t
+isc_socket_send(isc_socket_t *sock, isc_region_t *region, isc_task_t *task,
+ isc_taskaction_t action, void *arg);
+isc_result_t
+isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ const isc_sockaddr_t *address, struct in6_pktinfo *pktinfo);
+isc_result_t
+isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, isc_task_t *task,
+ const isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+ isc_socketevent_t *event, unsigned int flags);
+
+/*!
+ * Send the contents of 'region' to the socket's peer.
+ *
+ * Notes:
+ *
+ *\li Shutting down the requestor's task *may* result in any
+ * still pending writes being dropped or completed, depending on the
+ * underlying OS implementation.
+ *
+ *\li If 'action' is NULL, then no completion event will be posted.
+ *
+ *\li The caller may not modify 'region', the buffers which are passed
+ * into this function, or any data they refer to until the completion
+ * event is received.
+ *
+ *\li For isc_socket_sendto2():
+ * 'event' is not NULL, and the non-socket specific fields are
+ * expected to be initialized.
+ *
+ *\li For isc_socket_sendto2():
+ * The only defined values for 'flags' are ISC_SOCKFLAG_IMMEDIATE
+ * and ISC_SOCKFLAG_NORETRY.
+ *
+ *\li If ISC_SOCKFLAG_IMMEDIATE is set and the operation completes, the
+ * return value will be ISC_R_SUCCESS and the event will be filled
+ * in and not sent. If the operation does not complete, the return
+ * value will be ISC_R_INPROGRESS and the event will be sent when
+ * the operation completes.
+ *
+ *\li ISC_SOCKFLAG_NORETRY can only be set for UDP sockets. If set
+ * and the send operation fails due to a transient error, the send
+ * will not be retried and the error will be indicated in the event.
+ * Using this option along with ISC_SOCKFLAG_IMMEDIATE allows the caller
+ * to specify a region that is allocated on the stack.
+ *
+ * Requires:
+ *
+ *\li 'socket' is a valid, bound socket.
+ *
+ *\li For isc_socket_send():
+ * 'region' is a valid region
+ *
+ *\li For isc_socket_sendv() and isc_socket_sendtov():
+ * 'buflist' is non-NULL, and '*buflist' contain at least one buffer.
+ *
+ *\li 'task' is a valid task
+ *
+ *\li For isc_socket_sendv(), isc_socket_sendtov(), isc_socket_send(), and
+ * isc_socket_sendto():
+ * action == NULL or is a valid action
+ *
+ *\li For isc_socket_sendto2():
+ * event != NULL
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_INPROGRESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_UNEXPECTED
+ *
+ * Event results:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_UNEXPECTED
+ *\li XXX needs other net-type errors
+ */
+/*@}*/
+
+isc_result_t
+isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp);
+
+isc_result_t
+isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
+ unsigned int maxsocks, int nthreads);
+/*%<
+ * Create a socket manager. If "maxsocks" is non-zero, it specifies the
+ * maximum number of sockets that the created manager should handle.
+ * isc_socketmgr_create() is equivalent of isc_socketmgr_create2() with
+ * "maxsocks" being zero.
+ *
+ * Notes:
+ *
+ *\li All memory will be allocated in memory context 'mctx'.
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\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.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_UNEXPECTED
+ *\li #ISC_R_NOTIMPLEMENTED
+ */
+
+isc_result_t
+isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp);
+/*%<
+ * Returns in "*nsockp" the maximum number of sockets this manager may open.
+ *
+ * Requires:
+ *
+ *\li '*manager' is a valid isc_socketmgr_t.
+ *\li 'nsockp' is not NULL.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOTIMPLEMENTED
+ */
+
+void
+isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats);
+/*%<
+ * Set a general socket statistics counter set 'stats' for 'manager'.
+ *
+ * Requires:
+ * \li 'manager' is valid, hasn't opened any socket, and doesn't have
+ * stats already set.
+ *
+ *\li stats is a valid statistics supporting socket statistics counters
+ * (see above).
+ */
+
+void
+isc_socketmgr_destroy(isc_socketmgr_t **managerp);
+/*%<
+ * Destroy a socket manager.
+ *
+ * Notes:
+ *
+ *\li This routine blocks until there are no sockets left in the manager,
+ * so if the caller holds any socket references using the manager, it
+ * must detach them before calling isc_socketmgr_destroy() or it will
+ * block forever.
+ *
+ * Requires:
+ *
+ *\li '*managerp' is a valid isc_socketmgr_t.
+ *
+ *\li All sockets managed by this manager are fully detached.
+ *
+ * Ensures:
+ *
+ *\li *managerp == NULL
+ *
+ *\li All resources used by the manager have been freed.
+ */
+
+isc_sockettype_t
+isc_socket_gettype(isc_socket_t *sock);
+/*%<
+ * Returns the socket type for "sock."
+ *
+ * Requires:
+ *
+ *\li "sock" is a valid socket.
+ */
+
+/*@{*/
+void
+isc_socket_ipv6only(isc_socket_t *sock, bool yes);
+/*%<
+ * If the socket is an IPv6 socket set/clear the IPV6_IPV6ONLY socket
+ * option if the host OS supports this option.
+ *
+ * Requires:
+ *\li 'sock' is a valid socket.
+ */
+/*@}*/
+
+void
+isc_socket_dscp(isc_socket_t *sock, isc_dscp_t dscp);
+/*%<
+ * Sets the Differentiated Services Code Point (DSCP) field for packets
+ * transmitted on this socket. If 'dscp' is -1, return immediately.
+ *
+ * Requires:
+ *\li 'sock' is a valid socket.
+ */
+
+isc_socketevent_t *
+isc_socket_socketevent(isc_mem_t *mctx, void *sender, isc_eventtype_t eventtype,
+ isc_taskaction_t action, void *arg);
+/*%<
+ * Get a isc_socketevent_t to be used with isc_socket_sendto2(), etc.
+ */
+
+void
+isc_socket_cleanunix(const isc_sockaddr_t *addr, bool active);
+
+/*%<
+ * Cleanup UNIX domain sockets in the file-system. If 'active' is true
+ * then just unlink the socket. If 'active' is false try to determine
+ * if there is a listener of the socket or not. If no listener is found
+ * then unlink socket.
+ *
+ * Prior to unlinking the path is tested to see if it a socket.
+ *
+ * Note: there are a number of race conditions which cannot be avoided
+ * both in the filesystem and any application using UNIX domain
+ * sockets (e.g. socket is tested between bind() and listen(),
+ * the socket is deleted and replaced in the file-system between
+ * stat() and unlink()).
+ */
+
+isc_result_t
+isc_socket_permunix(const isc_sockaddr_t *sockaddr, uint32_t perm,
+ uint32_t owner, uint32_t group);
+/*%<
+ * Set ownership and file permissions on the UNIX domain socket.
+ *
+ * Note: On Solaris this secures the directory containing
+ * the socket as Solaris do not honour the filesystem
+ * permissions on the socket.
+ *
+ * Requires:
+ * \li 'sockaddr' to be a valid UNIX domain sockaddr.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_FAILURE
+ */
+
+void
+isc_socket_setname(isc_socket_t *socket, const char *name, void *tag);
+/*%<
+ * Set the name and optional tag for a socket. This allows tracking of the
+ * owner or purpose for this socket, and is useful for tracing and statistics
+ * reporting.
+ */
+
+const char *
+isc_socket_getname(isc_socket_t *socket);
+/*%<
+ * Get the name associated with a socket, if any.
+ */
+
+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, uint32_t);
+/*%<
+ * Temporary. For use by named only.
+ */
+
+void
+isc_socketmgr_maxudp(isc_socketmgr_t *mgr, unsigned int maxudp);
+/*%<
+ * Test interface. Drop UDP packet > 'maxudp'.
+ */
+
+bool
+isc_socket_hasreuseport(void);
+/*%<
+ * Return true if there is SO_REUSEPORT support
+ */
+
+#ifdef HAVE_LIBXML2
+int
+isc_socketmgr_renderxml(isc_socketmgr_t *mgr, void *writer0);
+/*%<
+ * Render internal statistics and other state into the XML document.
+ */
+#endif /* HAVE_LIBXML2 */
+
+#ifdef HAVE_JSON_C
+isc_result_t
+isc_socketmgr_renderjson(isc_socketmgr_t *mgr, void *stats0);
+/*%<
+ * Render internal statistics and other state into JSON format.
+ */
+#endif /* HAVE_JSON_C */
+
+/*%<
+ * See isc_socketmgr_create() above.
+ */
+typedef isc_result_t (*isc_socketmgrcreatefunc_t)(isc_mem_t *mctx,
+ isc_socketmgr_t **managerp);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SOCKET_H */
diff --git a/lib/isc/include/isc/stats.h b/lib/isc/include/isc/stats.h
new file mode 100644
index 0000000..5e25bac
--- /dev/null
+++ b/lib/isc/include/isc/stats.h
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_STATS_H
+#define ISC_STATS_H 1
+
+/*! \file isc/stats.h */
+
+#include <inttypes.h>
+
+#include <isc/types.h>
+
+/*%
+ * Statistics counters. Used as isc_statscounter_t values.
+ */
+enum {
+ /*%
+ * Socket statistics counters.
+ */
+ isc_sockstatscounter_udp4open = 0,
+ isc_sockstatscounter_udp6open = 1,
+ isc_sockstatscounter_tcp4open = 2,
+ isc_sockstatscounter_tcp6open = 3,
+ isc_sockstatscounter_unixopen = 4,
+
+ isc_sockstatscounter_udp4openfail = 5,
+ isc_sockstatscounter_udp6openfail = 6,
+ isc_sockstatscounter_tcp4openfail = 7,
+ isc_sockstatscounter_tcp6openfail = 8,
+ isc_sockstatscounter_unixopenfail = 9,
+
+ isc_sockstatscounter_udp4close = 10,
+ isc_sockstatscounter_udp6close = 11,
+ isc_sockstatscounter_tcp4close = 12,
+ isc_sockstatscounter_tcp6close = 13,
+ isc_sockstatscounter_unixclose = 14,
+ isc_sockstatscounter_fdwatchclose = 15,
+
+ isc_sockstatscounter_udp4bindfail = 16,
+ isc_sockstatscounter_udp6bindfail = 17,
+ isc_sockstatscounter_tcp4bindfail = 18,
+ isc_sockstatscounter_tcp6bindfail = 19,
+ isc_sockstatscounter_unixbindfail = 20,
+ isc_sockstatscounter_fdwatchbindfail = 21,
+
+ isc_sockstatscounter_udp4connect = 22,
+ isc_sockstatscounter_udp6connect = 23,
+ isc_sockstatscounter_tcp4connect = 24,
+ isc_sockstatscounter_tcp6connect = 25,
+ isc_sockstatscounter_unixconnect = 26,
+ isc_sockstatscounter_fdwatchconnect = 27,
+
+ isc_sockstatscounter_udp4connectfail = 28,
+ isc_sockstatscounter_udp6connectfail = 29,
+ isc_sockstatscounter_tcp4connectfail = 30,
+ isc_sockstatscounter_tcp6connectfail = 31,
+ isc_sockstatscounter_unixconnectfail = 32,
+ isc_sockstatscounter_fdwatchconnectfail = 33,
+
+ isc_sockstatscounter_tcp4accept = 34,
+ isc_sockstatscounter_tcp6accept = 35,
+ isc_sockstatscounter_unixaccept = 36,
+
+ isc_sockstatscounter_tcp4acceptfail = 37,
+ isc_sockstatscounter_tcp6acceptfail = 38,
+ isc_sockstatscounter_unixacceptfail = 39,
+
+ isc_sockstatscounter_udp4sendfail = 40,
+ isc_sockstatscounter_udp6sendfail = 41,
+ isc_sockstatscounter_tcp4sendfail = 42,
+ isc_sockstatscounter_tcp6sendfail = 43,
+ isc_sockstatscounter_unixsendfail = 44,
+ isc_sockstatscounter_fdwatchsendfail = 45,
+
+ isc_sockstatscounter_udp4recvfail = 46,
+ isc_sockstatscounter_udp6recvfail = 47,
+ isc_sockstatscounter_tcp4recvfail = 48,
+ isc_sockstatscounter_tcp6recvfail = 49,
+ isc_sockstatscounter_unixrecvfail = 50,
+ isc_sockstatscounter_fdwatchrecvfail = 51,
+
+ isc_sockstatscounter_udp4active = 52,
+ isc_sockstatscounter_udp6active = 53,
+ isc_sockstatscounter_tcp4active = 54,
+ isc_sockstatscounter_tcp6active = 55,
+ isc_sockstatscounter_unixactive = 56,
+
+ isc_sockstatscounter_rawopen = 57,
+ isc_sockstatscounter_rawopenfail = 58,
+ isc_sockstatscounter_rawclose = 59,
+ isc_sockstatscounter_rawrecvfail = 60,
+ isc_sockstatscounter_rawactive = 61,
+
+ isc_sockstatscounter_max = 62
+};
+
+ISC_LANG_BEGINDECLS
+
+/*%<
+ * Flag(s) for isc_stats_dump().
+ */
+#define ISC_STATSDUMP_VERBOSE 0x00000001 /*%< dump 0-value counters */
+
+/*%<
+ * Dump callback type.
+ */
+typedef void (*isc_stats_dumper_t)(isc_statscounter_t, uint64_t, void *);
+
+isc_result_t
+isc_stats_create(isc_mem_t *mctx, isc_stats_t **statsp, int ncounters);
+/*%<
+ * Create a statistics counter structure of general type. It counts a general
+ * set of counters indexed by an ID between 0 and ncounters -1.
+ *
+ * Requires:
+ *\li 'mctx' must be a valid memory context.
+ *
+ *\li 'statsp' != NULL && '*statsp' == NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS -- all ok
+ *
+ *\li anything else -- failure
+ */
+
+void
+isc_stats_attach(isc_stats_t *stats, isc_stats_t **statsp);
+/*%<
+ * Attach to a statistics set.
+ *
+ * Requires:
+ *\li 'stats' is a valid isc_stats_t.
+ *
+ *\li 'statsp' != NULL && '*statsp' == NULL
+ */
+
+void
+isc_stats_detach(isc_stats_t **statsp);
+/*%<
+ * Detaches from the statistics set.
+ *
+ * Requires:
+ *\li 'statsp' != NULL and '*statsp' is a valid isc_stats_t.
+ */
+
+int
+isc_stats_ncounters(isc_stats_t *stats);
+/*%<
+ * Returns the number of counters contained in stats.
+ *
+ * Requires:
+ *\li 'stats' is a valid isc_stats_t.
+ *
+ */
+
+void
+isc_stats_increment(isc_stats_t *stats, isc_statscounter_t counter);
+/*%<
+ * Increment the counter-th counter of stats.
+ *
+ * Requires:
+ *\li 'stats' is a valid isc_stats_t.
+ *
+ *\li counter is less than the maximum available ID for the stats specified
+ * on creation.
+ */
+
+void
+isc_stats_decrement(isc_stats_t *stats, isc_statscounter_t counter);
+/*%<
+ * Decrement the counter-th counter of stats.
+ *
+ * Requires:
+ *\li 'stats' is a valid isc_stats_t.
+ */
+
+void
+isc_stats_dump(isc_stats_t *stats, isc_stats_dumper_t dump_fn, void *arg,
+ unsigned int options);
+/*%<
+ * Dump the current statistics counters in a specified way. For each counter
+ * in stats, dump_fn is called with its current value and the given argument
+ * arg. By default counters that have a value of 0 is skipped; if options has
+ * the ISC_STATSDUMP_VERBOSE flag, even such counters are dumped.
+ *
+ * Requires:
+ *\li 'stats' is a valid isc_stats_t.
+ */
+
+void
+isc_stats_set(isc_stats_t *stats, uint64_t val, isc_statscounter_t counter);
+/*%<
+ * Set the given counter to the specified value.
+ *
+ * Requires:
+ *\li 'stats' is a valid isc_stats_t.
+ */
+
+void
+isc_stats_set(isc_stats_t *stats, uint64_t val, isc_statscounter_t counter);
+/*%<
+ * Set the given counter to the specified value.
+ *
+ * Requires:
+ *\li 'stats' is a valid isc_stats_t.
+ */
+
+void
+isc_stats_update_if_greater(isc_stats_t *stats, isc_statscounter_t counter,
+ isc_statscounter_t value);
+/*%<
+ * Atomically assigns 'value' to 'counter' if value > counter.
+ *
+ * Requires:
+ *\li 'stats' is a valid isc_stats_t.
+ *
+ *\li counter is less than the maximum available ID for the stats specified
+ * on creation.
+ */
+
+isc_statscounter_t
+isc_stats_get_counter(isc_stats_t *stats, isc_statscounter_t counter);
+/*%<
+ * Returns value currently stored in counter.
+ *
+ * Requires:
+ *\li 'stats' is a valid isc_stats_t.
+ *
+ *\li counter is less than the maximum available ID for the stats specified
+ * on creation.
+ */
+
+void
+isc_stats_resize(isc_stats_t **stats, int ncounters);
+/*%<
+ * Resize a statistics counter structure of general type. The new set of
+ * counters are indexed by an ID between 0 and ncounters -1.
+ *
+ * Requires:
+ *\li 'stats' is a valid isc_stats_t.
+ *\li 'ncounters' is a non-zero positive number.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STATS_H */
diff --git a/lib/isc/include/isc/stdio.h b/lib/isc/include/isc/stdio.h
new file mode 100644
index 0000000..2c391d7
--- /dev/null
+++ b/lib/isc/include/isc/stdio.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_STDIO_H
+#define ISC_STDIO_H 1
+
+/*! \file isc/stdio.h */
+
+/*%
+ * These functions are wrappers around the corresponding stdio functions.
+ *
+ * They return a detailed error code in the form of an an isc_result_t. ANSI C
+ * does not guarantee that stdio functions set errno, hence these functions
+ * must use platform dependent methods (e.g., the POSIX errno) to construct the
+ * error code.
+ */
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+/*% Open */
+isc_result_t
+isc_stdio_open(const char *filename, const char *mode, FILE **fp);
+
+/*% Close */
+isc_result_t
+isc_stdio_close(FILE *f);
+
+/*% Seek */
+isc_result_t
+isc_stdio_seek(FILE *f, off_t offset, int whence);
+
+/*% Tell */
+isc_result_t
+isc_stdio_tell(FILE *f, off_t *offsetp);
+
+/*% Read */
+isc_result_t
+isc_stdio_read(void *ptr, size_t size, size_t nmemb, FILE *f, size_t *nret);
+
+/*% Write */
+isc_result_t
+isc_stdio_write(const void *ptr, size_t size, size_t nmemb, FILE *f,
+ size_t *nret);
+
+/*% Flush */
+isc_result_t
+isc_stdio_flush(FILE *f);
+
+isc_result_t
+isc_stdio_sync(FILE *f);
+/*%<
+ * Invoke fsync() on the file descriptor underlying an stdio stream, or an
+ * equivalent system-dependent operation. Note that this function has no
+ * direct counterpart in the stdio library.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STDIO_H */
diff --git a/lib/isc/include/isc/strerr.h b/lib/isc/include/isc/strerr.h
new file mode 100644
index 0000000..ce093b0
--- /dev/null
+++ b/lib/isc/include/isc/strerr.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file isc/strerr.h */
+
+#include <isc/string.h>
+
+#if defined(strerror_r)
+#undef strerror_r
+#endif /* if defined(strerror_r) */
+#define strerror_r isc_string_strerror_r
diff --git a/lib/isc/include/isc/string.h b/lib/isc/include/isc/string.h
new file mode 100644
index 0000000..1bc5693
--- /dev/null
+++ b/lib/isc/include/isc/string.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file isc/string.h */
+
+#include <string.h>
+
+#include "isc/lang.h"
+#include "isc/platform.h"
+
+ISC_LANG_BEGINDECLS
+
+#if !defined(HAVE_STRLCPY)
+size_t
+strlcpy(char *dst, const char *src, size_t size);
+#endif /* !defined(HAVE_STRLCPY) */
+
+#if !defined(HAVE_STRLCAT)
+size_t
+strlcat(char *dst, const char *src, size_t size);
+#endif /* if !defined(HAVE_STRLCAT) */
+
+#if !defined(HAVE_STRNSTR)
+char *
+strnstr(const char *s, const char *find, size_t slen);
+#endif /* if !defined(HAVE_STRNSTR) */
+
+int
+isc_string_strerror_r(int errnum, char *buf, size_t buflen);
+
+ISC_LANG_ENDDECLS
diff --git a/lib/isc/include/isc/symtab.h b/lib/isc/include/isc/symtab.h
new file mode 100644
index 0000000..9ec8564
--- /dev/null
+++ b/lib/isc/include/isc/symtab.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_SYMTAB_H
+#define ISC_SYMTAB_H 1
+
+/*****
+***** Module Info
+*****/
+
+/*! \file isc/symtab.h
+ * \brief Provides a simple memory-based symbol table.
+ *
+ * Keys are C strings, and key comparisons are case-insensitive. A type may
+ * be specified when looking up, defining, or undefining. A type value of
+ * 0 means "match any type"; any other value will only match the given
+ * type.
+ *
+ * It's possible that a client will attempt to define a <key, type, value>
+ * tuple when a tuple with the given key and type already exists in the table.
+ * What to do in this case is specified by the client. Possible policies are:
+ *
+ *\li #isc_symexists_reject Disallow the define, returning #ISC_R_EXISTS
+ *\li #isc_symexists_replace Replace the old value with the new. The
+ * undefine action (if provided) will be called
+ * with the old <key, type, value> tuple.
+ *\li #isc_symexists_add Add the new tuple, leaving the old tuple in
+ * the table. Subsequent lookups will retrieve
+ * the most-recently-defined tuple.
+ *
+ * A lookup of a key using type 0 will return the most-recently defined
+ * symbol with that key. An undefine of a key using type 0 will undefine the
+ * most-recently defined symbol with that key. Trying to define a key with
+ * type 0 is illegal.
+ *
+ * The symbol table library does not make a copy the key field, so the
+ * caller must ensure that any key it passes to isc_symtab_define() will not
+ * change until it calls isc_symtab_undefine() or isc_symtab_destroy().
+ *
+ * A user-specified action will be called (if provided) when a symbol is
+ * 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.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Resources:
+ * TBS
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <stdbool.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*
+ *** Symbol Tables.
+ ***/
+/*% Symbol table value. */
+typedef union isc_symvalue {
+ void *as_pointer;
+ const void *as_cpointer;
+ int as_integer;
+ unsigned int as_uinteger;
+} isc_symvalue_t;
+
+typedef void (*isc_symtabaction_t)(char *key, unsigned int type,
+ isc_symvalue_t value, void *userarg);
+/*% Symbol table exists. */
+typedef enum {
+ isc_symexists_reject = 0, /*%< Disallow the define */
+ isc_symexists_replace = 1, /*%< Replace the old value with the new */
+ isc_symexists_add = 2 /*%< Add the new tuple */
+} isc_symexists_t;
+
+ISC_LANG_BEGINDECLS
+
+/*% Create a symbol table. */
+isc_result_t
+isc_symtab_create(isc_mem_t *mctx, unsigned int size,
+ isc_symtabaction_t undefine_action, void *undefine_arg,
+ bool case_sensitive, isc_symtab_t **symtabp);
+
+/*% Destroy a symbol table. */
+void
+isc_symtab_destroy(isc_symtab_t **symtabp);
+
+/*% Lookup a symbol table. */
+isc_result_t
+isc_symtab_lookup(isc_symtab_t *symtab, const char *key, unsigned int type,
+ isc_symvalue_t *value);
+
+/*% Define a symbol table. */
+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);
+
+/*% Undefine a symbol table. */
+isc_result_t
+isc_symtab_undefine(isc_symtab_t *symtab, const char *key, unsigned int type);
+
+/*% Return the number of items in a symbol table. */
+unsigned int
+isc_symtab_count(isc_symtab_t *symtab);
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SYMTAB_H */
diff --git a/lib/isc/include/isc/task.h b/lib/isc/include/isc/task.h
new file mode 100644
index 0000000..810552d
--- /dev/null
+++ b/lib/isc/include/isc/task.h
@@ -0,0 +1,721 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/task.h
+ * \brief The task system provides a lightweight execution context, which is
+ * basically an event queue.
+ *
+ * When a task's event queue is non-empty, the
+ * task is runnable. A small work crew of threads, typically one per CPU,
+ * execute runnable tasks by dispatching the events on the tasks' event
+ * queues. Context switching between tasks is fast.
+ *
+ * \li MP:
+ * The module ensures appropriate synchronization of data structures it
+ * creates and manipulates.
+ * The caller must ensure that isc_taskmgr_destroy() is called only
+ * once for a given manager.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Resources:
+ * TBS
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ *
+ * \section purge Purging and Unsending
+ *
+ * Events which have been queued for a task but not delivered may be removed
+ * from the task's event queue by purging or unsending.
+ *
+ * With both types, the caller specifies a matching pattern that selects
+ * events based upon their sender, type, and tag.
+ *
+ * Purging calls isc_event_free() on the matching events.
+ *
+ * Unsending returns a list of events that matched the pattern.
+ * The caller is then responsible for them.
+ *
+ * Consumers of events should purge, not unsend.
+ *
+ * Producers of events often want to remove events when the caller indicates
+ * it is no longer interested in the object, e.g. by canceling a timer.
+ * Sometimes this can be done by purging, but for some event types, the
+ * calls to isc_event_free() cause deadlock because the event free routine
+ * wants to acquire a lock the caller is already holding. Unsending instead
+ * of purging solves this problem. As a general rule, producers should only
+ * unsend events which they have sent.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <stdbool.h>
+
+#include <isc/eventclass.h>
+#include <isc/lang.h>
+#include <isc/netmgr.h>
+#include <isc/stdtime.h>
+#include <isc/types.h>
+
+#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)
+
+/*****
+ ***** Tasks.
+ *****/
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Types
+ ***/
+
+typedef enum {
+ isc_taskmgrmode_normal = 0,
+ isc_taskmgrmode_privileged
+} isc_taskmgrmode_t;
+
+isc_result_t
+isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
+ isc_task_t **taskp);
+isc_result_t
+isc_task_create_bound(isc_taskmgr_t *manager, unsigned int quantum,
+ isc_task_t **taskp, int threadid);
+/*%<
+ * Create a task, optionally bound to a particular threadid.
+ *
+ * Notes:
+ *
+ *\li If 'quantum' is non-zero, then only that many events can be dispatched
+ * before the task must yield to other tasks waiting to execute. If
+ * quantum is zero, then the default quantum of the task manager will
+ * be used.
+ *
+ *\li The 'quantum' option may be removed from isc_task_create() in the
+ * future. If this happens, isc_task_getquantum() and
+ * isc_task_setquantum() will be provided.
+ *
+ * Requires:
+ *
+ *\li 'manager' is a valid task manager.
+ *
+ *\li taskp != NULL && *taskp == NULL
+ *
+ * Ensures:
+ *
+ *\li On success, '*taskp' is bound to the new task.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_UNEXPECTED
+ *\li #ISC_R_SHUTTINGDOWN
+ */
+
+void
+isc_task_ready(isc_task_t *task);
+/*%<
+ * Enqueue the task onto netmgr queue.
+ */
+
+isc_result_t
+isc_task_run(isc_task_t *task);
+/*%<
+ * Run all the queued events for the 'task', returning
+ * when the queue is empty or the number of events executed
+ * exceeds the 'quantum' specified when the task was created.
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_QUOTA
+ */
+
+void
+isc_task_attach(isc_task_t *source, isc_task_t **targetp);
+/*%<
+ * Attach *targetp to source.
+ *
+ * Requires:
+ *
+ *\li 'source' is a valid task.
+ *
+ *\li 'targetp' points to a NULL isc_task_t *.
+ *
+ * Ensures:
+ *
+ *\li *targetp is attached to source.
+ */
+
+void
+isc_task_detach(isc_task_t **taskp);
+/*%<
+ * Detach *taskp from its task.
+ *
+ * Requires:
+ *
+ *\li '*taskp' is a valid task.
+ *
+ * Ensures:
+ *
+ *\li *taskp is NULL.
+ *
+ *\li If '*taskp' is the last reference to the task, the task is idle (has
+ * an empty event queue), and has not been shutdown, the task will be
+ * shutdown.
+ *
+ *\li If '*taskp' is the last reference to the task and
+ * the task has been shutdown,
+ * all resources used by the task will be freed.
+ */
+
+void
+isc_task_send(isc_task_t *task, isc_event_t **eventp);
+
+void
+isc_task_sendto(isc_task_t *task, isc_event_t **eventp, int c);
+/*%<
+ * Send '*event' to 'task', if task is idle try starting it on cpu 'c'
+ * If 'c' is smaller than 0 then cpu is selected randomly.
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *\li eventp != NULL && *eventp != NULL.
+ *
+ * Ensures:
+ *
+ *\li *eventp == NULL.
+ */
+
+void
+isc_task_sendtoanddetach(isc_task_t **taskp, isc_event_t **eventp, int c);
+
+void
+isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp);
+/*%<
+ * Send '*event' to '*taskp' and then detach '*taskp' from its
+ * task. If task is idle try starting it on cpu 'c'
+ * If 'c' is smaller than 0 then cpu is selected randomly.
+ *
+ * Requires:
+ *
+ *\li '*taskp' is a valid task.
+ *\li eventp != NULL && *eventp != NULL.
+ *
+ * Ensures:
+ *
+ *\li *eventp == NULL.
+ *
+ *\li *taskp == NULL.
+ *
+ *\li If '*taskp' is the last reference to the task, the task is
+ * idle (has an empty event queue), and has not been shutdown,
+ * the task will be shutdown.
+ *
+ *\li If '*taskp' is the last reference to the task and
+ * the task has been shutdown,
+ * all resources used by the task will be freed.
+ */
+
+unsigned int
+isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
+ isc_eventtype_t last, void *tag);
+/*%<
+ * Purge events from a task's event queue.
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li last >= first
+ *
+ * Ensures:
+ *
+ *\li Events in the event queue of 'task' whose sender is 'sender', whose
+ * type is >= first and <= last, and whose tag is 'tag' will be purged,
+ * unless they are marked as unpurgable.
+ *
+ *\li A sender of NULL will match any sender. A NULL tag matches any
+ * tag.
+ *
+ * Returns:
+ *
+ *\li The number of events purged.
+ */
+
+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.
+ *
+ * Notes:
+ *
+ *\li This function is equivalent to
+ *
+ *\code
+ * isc_task_purgerange(task, sender, type, type, tag);
+ *\endcode
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *
+ * Ensures:
+ *
+ *\li Events in the event queue of 'task' whose sender is 'sender', whose
+ * type is 'type', and whose tag is 'tag' will be purged, unless they
+ * are marked as unpurgable.
+ *
+ *\li A sender of NULL will match any sender. A NULL tag matches any
+ * tag.
+ *
+ * Returns:
+ *
+ *\li The number of events purged.
+ */
+
+bool
+isc_task_purgeevent(isc_task_t *task, isc_event_t *event);
+/*%<
+ * Purge 'event' from a task's event queue.
+ *
+ * XXXRTH: WARNING: This method may be removed before beta.
+ *
+ * Notes:
+ *
+ *\li If 'event' is on the task's event queue, it will be purged,
+ * unless it is marked as unpurgeable. 'event' does not have to be
+ * on the task's event queue; in fact, it can even be an invalid
+ * pointer. Purging only occurs if the event is actually on the task's
+ * event queue.
+ *
+ * \li Purging never changes the state of the task.
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *
+ * Ensures:
+ *
+ *\li 'event' is not in the event queue for 'task'.
+ *
+ * Returns:
+ *
+ *\li #true The event was purged.
+ *\li #false The event was not in the event queue,
+ * or was marked unpurgeable.
+ */
+
+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.
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li last >= first.
+ *
+ *\li *events is a valid list.
+ *
+ * Ensures:
+ *
+ *\li Events in the event queue of 'task' whose sender is 'sender', whose
+ * type is >= first and <= last, and whose tag is 'tag' will be dequeued
+ * and appended to *events.
+ *
+ *\li A sender of NULL will match any sender. A NULL tag matches any
+ * tag.
+ *
+ * Returns:
+ *
+ *\li The number of events unsent.
+ */
+
+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.
+ *
+ * Notes:
+ *
+ *\li This function is equivalent to
+ *
+ *\code
+ * isc_task_unsendrange(task, sender, type, type, tag, events);
+ *\endcode
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li *events is a valid list.
+ *
+ * Ensures:
+ *
+ *\li Events in the event queue of 'task' whose sender is 'sender', whose
+ * type is 'type', and whose tag is 'tag' will be dequeued and appended
+ * to *events.
+ *
+ * Returns:
+ *
+ *\li The number of events unsent.
+ */
+
+isc_result_t
+isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, void *arg);
+/*%<
+ * Send a shutdown event with action 'action' and argument 'arg' when
+ * 'task' is shutdown.
+ *
+ * Notes:
+ *
+ *\li Shutdown events are posted in LIFO order.
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li 'action' is a valid task action.
+ *
+ * Ensures:
+ *
+ *\li When the task is shutdown, shutdown events requested with
+ * isc_task_onshutdown() will be appended to the task's event queue.
+ *
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_SHUTTINGDOWN Task is shutting down.
+ */
+
+void
+isc_task_shutdown(isc_task_t *task);
+/*%<
+ * Shutdown 'task'.
+ *
+ * Notes:
+ *
+ *\li Shutting down a task causes any shutdown events requested with
+ * isc_task_onshutdown() to be posted (in LIFO order). The task
+ * moves into a "shutting down" mode which prevents further calls
+ * to isc_task_onshutdown().
+ *
+ *\li Trying to shutdown a task that has already been shutdown has no
+ * effect.
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *
+ * Ensures:
+ *
+ *\li Any shutdown events requested with isc_task_onshutdown() have been
+ * posted (in LIFO order).
+ */
+
+void
+isc_task_destroy(isc_task_t **taskp);
+/*%<
+ * Destroy '*taskp'.
+ *
+ * Notes:
+ *
+ *\li This call is equivalent to:
+ *
+ *\code
+ * isc_task_shutdown(*taskp);
+ * isc_task_detach(taskp);
+ *\endcode
+ *
+ * Requires:
+ *
+ * '*taskp' is a valid task.
+ *
+ * Ensures:
+ *
+ *\li Any shutdown events requested with isc_task_onshutdown() have been
+ * posted (in LIFO order).
+ *
+ *\li *taskp == NULL
+ *
+ *\li If '*taskp' is the last reference to the task,
+ * all resources used by the task will be freed.
+ */
+
+void
+isc_task_setname(isc_task_t *task, const char *name, void *tag);
+/*%<
+ * Name 'task'.
+ *
+ * Notes:
+ *
+ *\li Only the first 15 characters of 'name' will be copied.
+ *
+ *\li Naming a task is currently only useful for debugging purposes.
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ */
+
+const char *
+isc_task_getname(isc_task_t *task);
+/*%<
+ * Get the name of 'task', as previously set using isc_task_setname().
+ *
+ * Notes:
+ *\li This function is for debugging purposes only.
+ *
+ * Requires:
+ *\li 'task' is a valid task.
+ *
+ * Returns:
+ *\li A non-NULL pointer to a null-terminated string.
+ * If the task has not been named, the string is
+ * empty.
+ *
+ */
+
+isc_nm_t *
+isc_task_getnetmgr(isc_task_t *task);
+
+void *
+isc_task_gettag(isc_task_t *task);
+/*%<
+ * Get the tag value for 'task', as previously set using isc_task_settag().
+ *
+ * Notes:
+ *\li This function is for debugging purposes only.
+ *
+ * Requires:
+ *\li 'task' is a valid task.
+ */
+
+void
+isc_task_setquantum(isc_task_t *task, unsigned int quantum);
+/*%<
+ * Set future 'task' quantum to 'quantum'. The current 'task' quantum will be
+ * kept for the current isc_task_run() loop, and will be changed for the next
+ * run. Therefore, the function is safe to use from the event callback as it
+ * will not affect the current event loop processing.
+ */
+
+isc_result_t
+isc_task_beginexclusive(isc_task_t *task);
+/*%<
+ * Request exclusive access for 'task', which must be the calling
+ * task. Waits for any other concurrently executing tasks to finish their
+ * current event, and prevents any new events from executing in any of the
+ * tasks sharing a task manager with 'task'.
+ * It also pauses processing of network events in netmgr if it was provided
+ * when taskmgr was created.
+ *
+ * The exclusive access must be relinquished by calling
+ * isc_task_endexclusive() before returning from the current event handler.
+ *
+ * Requires:
+ *\li 'task' is the calling task.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS The current task now has exclusive access.
+ *\li #ISC_R_LOCKBUSY Another task has already requested exclusive
+ * access.
+ */
+
+void
+isc_task_endexclusive(isc_task_t *task);
+/*%<
+ * Relinquish the exclusive access obtained by isc_task_beginexclusive(),
+ * allowing other tasks to execute.
+ *
+ * Requires:
+ *\li 'task' is the calling task, and has obtained
+ * exclusive access by calling isc_task_spl().
+ */
+
+void
+isc_task_pause(isc_task_t *task0);
+void
+isc_task_unpause(isc_task_t *task0);
+/*%<
+ * Pause/unpause this task. Pausing a task removes it from the ready
+ * queue if it is present there; this ensures that the task will not
+ * run again until unpaused. This is necessary when the libuv network
+ * thread executes a function which schedules task manager events; this
+ * prevents the task manager from executing the next event in a task
+ * before the network thread has finished.
+ *
+ * Requires:
+ *\li 'task' is a valid task, and is not already paused or shutting down.
+ */
+
+void
+isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t);
+void
+isc_task_getcurrenttimex(isc_task_t *task, isc_time_t *t);
+/*%<
+ * Provide the most recent timestamp on the task. The timestamp is considered
+ * as the "current time".
+ *
+ * isc_task_getcurrentime() returns the time in one-second granularity;
+ * isc_task_getcurrentimex() returns it in nanosecond granularity.
+ *
+ * Requires:
+ *\li 'task' is a valid task.
+ *\li 't' is a valid non NULL pointer.
+ *
+ * Ensures:
+ *\li '*t' has the "current time".
+ */
+
+bool
+isc_task_exiting(isc_task_t *t);
+/*%<
+ * Returns true if the task is in the process of shutting down,
+ * false otherwise.
+ *
+ * Requires:
+ *\li 'task' is a valid task.
+ */
+
+void
+isc_task_setprivilege(isc_task_t *task, bool 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 execution 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 resumes running
+ * non-privileged tasks.
+ *
+ * Requires:
+ *\li 'task' is a valid task.
+ */
+
+bool
+isc_task_getprivilege(isc_task_t *task);
+/*%<
+ * Returns the current value of the task's privilege flag.
+ *
+ * Requires:
+ *\li 'task' is a valid task.
+ */
+
+bool
+isc_task_privileged(isc_task_t *task);
+/*%<
+ * Returns true if the task's privilege flag is set *and* the task
+ * manager is currently in privileged mode.
+ *
+ * Requires:
+ *\li 'task' is a valid task.
+ */
+
+/*****
+ ***** Task Manager.
+ *****/
+
+void
+isc_taskmgr_attach(isc_taskmgr_t *, isc_taskmgr_t **);
+void
+isc_taskmgr_detach(isc_taskmgr_t **);
+/*%<
+ * Attach/detach the task manager.
+ */
+
+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 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, non-privileged tasks resume running. The task calling
+ * this function should be in task-exclusive mode; the privileged tasks
+ * will be run after isc_task_endexclusive() is called.
+ *
+ * Requires:
+ *
+ *\li 'manager' is a valid task manager.
+ */
+
+void
+isc_taskmgr_setexcltask(isc_taskmgr_t *mgr, isc_task_t *task);
+/*%<
+ * Set a task which will be used for all task-exclusive operations.
+ *
+ * Requires:
+ *\li 'manager' is a valid task manager.
+ *
+ *\li 'task' is a valid task.
+ */
+
+isc_result_t
+isc_taskmgr_excltask(isc_taskmgr_t *mgr, isc_task_t **taskp);
+/*%<
+ * Attach '*taskp' to the task set by isc_taskmgr_getexcltask().
+ * This task should be used whenever running in task-exclusive mode,
+ * so as to prevent deadlock between two exclusive tasks.
+ *
+ * Requires:
+ *\li 'manager' is a valid task manager.
+ *
+ *\li taskp != NULL && *taskp == NULL
+ */
+
+#ifdef HAVE_LIBXML2
+int
+isc_taskmgr_renderxml(isc_taskmgr_t *mgr, void *writer0);
+#endif /* ifdef HAVE_LIBXML2 */
+
+#ifdef HAVE_JSON_C
+isc_result_t
+isc_taskmgr_renderjson(isc_taskmgr_t *mgr, void *tasksobj0);
+#endif /* HAVE_JSON_C */
+
+ISC_LANG_ENDDECLS
diff --git a/lib/isc/include/isc/taskpool.h b/lib/isc/include/isc/taskpool.h
new file mode 100644
index 0000000..ea4c569
--- /dev/null
+++ b/lib/isc/include/isc/taskpool.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_TASKPOOL_H
+#define ISC_TASKPOOL_H 1
+
+/*****
+***** Module Info
+*****/
+
+/*! \file isc/taskpool.h
+ * \brief A task pool is a mechanism for sharing a small number of tasks
+ * among a large number of objects such that each object is
+ * assigned a unique task, but each task may be shared by several
+ * objects.
+ *
+ * Task pools are used to let objects that can exist in large
+ * numbers (e.g., zones) use tasks for synchronization without
+ * the memory overhead and unfair scheduling competition that
+ * could result from creating a separate task for each object.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <stdbool.h>
+
+#include <isc/lang.h>
+#include <isc/task.h>
+
+ISC_LANG_BEGINDECLS
+
+/*****
+***** Types.
+*****/
+
+typedef struct isc_taskpool isc_taskpool_t;
+
+/*****
+***** Functions.
+*****/
+
+isc_result_t
+isc_taskpool_create(isc_taskmgr_t *tmgr, isc_mem_t *mctx, unsigned int ntasks,
+ unsigned int quantum, bool priv, isc_taskpool_t **poolp);
+/*%<
+ * Create a task pool of "ntasks" tasks, each with quantum
+ * "quantum".
+ *
+ * Requires:
+ *
+ *\li 'tmgr' is a valid task manager.
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li poolp != NULL && *poolp == NULL
+ *
+ * Ensures:
+ *
+ *\li On success, '*taskp' points to the new task pool.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_UNEXPECTED
+ */
+
+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);
+/*%<
+ * Returns the number of tasks in the task pool 'pool'.
+ */
+
+isc_result_t
+isc_taskpool_expand(isc_taskpool_t **sourcep, unsigned int size, bool priv,
+ 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
+isc_taskpool_destroy(isc_taskpool_t **poolp);
+/*%<
+ * Destroy a task pool. The tasks in the pool are detached but not
+ * shut down.
+ *
+ * Requires:
+ * \li '*poolp' 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
new file mode 100644
index 0000000..4814a65
--- /dev/null
+++ b/lib/isc/include/isc/timer.h
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_TIMER_H
+#define ISC_TIMER_H 1
+
+/*****
+***** Module Info
+*****/
+
+/*! \file isc/timer.h
+ * \brief Provides timers which are event sources in the task system.
+ *
+ * Three types of timers are supported:
+ *
+ *\li 'ticker' timers generate a periodic tick event.
+ *
+ *\li 'once' timers generate an idle timeout event if they are idle for too
+ * long, and generate a life timeout event if their lifetime expires.
+ * They are used to implement both (possibly expiring) idle timers and
+ * 'one-shot' timers.
+ *
+ *\li 'limited' timers generate a periodic tick event until they reach
+ * their lifetime when they generate a life timeout event.
+ *
+ *\li 'inactive' timers generate no events.
+ *
+ * Timers can change type. It is typical to create a timer as
+ * an 'inactive' timer and then change it into a 'ticker' or
+ * 'once' timer.
+ *
+ *\li MP:
+ * The module ensures appropriate synchronization of data structures it
+ * creates and manipulates.
+ * Clients of this module must not be holding a timer's task's lock when
+ * making a call that affects that timer. Failure to follow this rule
+ * can result in deadlock.
+ * The caller must ensure that isc_timermgr_destroy() is called only
+ * once for a given manager.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Resources:
+ * TBS
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <stdbool.h>
+
+#include <isc/event.h>
+#include <isc/eventclass.h>
+#include <isc/lang.h>
+#include <isc/time.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Types
+ ***/
+
+/*% Timer Type */
+typedef enum {
+ isc_timertype_undefined = -1, /*%< Undefined */
+ isc_timertype_ticker = 0, /*%< Ticker */
+ isc_timertype_once = 1, /*%< Once */
+ isc_timertype_limited = 2, /*%< Limited */
+ isc_timertype_inactive = 3 /*%< Inactive */
+} isc_timertype_t;
+
+typedef struct isc_timerevent isc_timerevent_t;
+
+struct isc_timerevent {
+ struct isc_event common;
+ isc_time_t due;
+ ISC_LINK(isc_timerevent_t) ev_timerlink;
+};
+
+#define ISC_TIMEREVENT_FIRSTEVENT (ISC_EVENTCLASS_TIMER + 0)
+#define ISC_TIMEREVENT_TICK (ISC_EVENTCLASS_TIMER + 1)
+#define ISC_TIMEREVENT_IDLE (ISC_EVENTCLASS_TIMER + 2)
+#define ISC_TIMEREVENT_LIFE (ISC_EVENTCLASS_TIMER + 3)
+#define ISC_TIMEREVENT_LASTEVENT (ISC_EVENTCLASS_TIMER + 65535)
+
+/***
+ *** Timer and Timer Manager Functions
+ ***
+ *** Note: all Ensures conditions apply only if the result is success for
+ *** those functions which return an isc_result_t.
+ ***/
+
+isc_result_t
+isc_timer_create(isc_timermgr_t *manager, isc_timertype_t type,
+ const isc_time_t *expires, const isc_interval_t *interval,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ isc_timer_t **timerp);
+/*%<
+ * Create a new 'type' timer managed by 'manager'. The timers parameters
+ * are specified by 'expires' and 'interval'. Events will be posted to
+ * 'task' and when dispatched 'action' will be called with 'arg' as the
+ * arg value. The new timer is returned in 'timerp'.
+ *
+ * Notes:
+ *
+ *\li For ticker timers, the timer will generate a 'tick' event every
+ * 'interval' seconds. The value of 'expires' is ignored.
+ *
+ *\li For once timers, 'expires' specifies the time when a life timeout
+ * event should be generated. If 'expires' is 0 (the epoch), then no life
+ * timeout will be generated. 'interval' specifies how long the timer
+ * can be idle before it generates an idle timeout. If 0, then no
+ * idle timeout will be generated.
+ *
+ *\li If 'expires' is NULL, the epoch will be used.
+ *
+ * If 'interval' is NULL, the zero interval will be used.
+ *
+ * Requires:
+ *
+ *\li 'manager' is a valid manager
+ *
+ *\li 'task' is a valid task
+ *
+ *\li 'action' is a valid action
+ *
+ *\li 'expires' points to a valid time, or is NULL.
+ *
+ *\li 'interval' points to a valid interval, or is NULL.
+ *
+ *\li type == isc_timertype_inactive ||
+ * ('expires' and 'interval' are not both 0)
+ *
+ *\li 'timerp' is a valid pointer, and *timerp == NULL
+ *
+ * Ensures:
+ *
+ *\li '*timerp' is attached to the newly created timer
+ *
+ *\li The timer is attached to the task
+ *
+ *\li An idle timeout will not be generated until at least Now + the
+ * timer's interval if 'timer' is a once timer with a non-zero
+ * interval.
+ *
+ * Returns:
+ *
+ *\li Success
+ *\li No memory
+ *\li Unexpected error
+ */
+
+isc_result_t
+isc_timer_reset(isc_timer_t *timer, isc_timertype_t type,
+ const isc_time_t *expires, const isc_interval_t *interval,
+ bool purge);
+/*%<
+ * Change the timer's type, expires, and interval values to the given
+ * values. If 'purge' is TRUE, any pending events from this timer
+ * are purged from its task's event queue.
+ *
+ * Notes:
+ *
+ *\li If 'expires' is NULL, the epoch will be used.
+ *
+ *\li If 'interval' is NULL, the zero interval will be used.
+ *
+ * Requires:
+ *
+ *\li 'timer' is a valid timer
+ *
+ *\li The same requirements that isc_timer_create() imposes on 'type',
+ * 'expires' and 'interval' apply.
+ *
+ * Ensures:
+ *
+ *\li An idle timeout will not be generated until at least Now + the
+ * timer's interval if 'timer' is a once timer with a non-zero
+ * interval.
+ *
+ * Returns:
+ *
+ *\li Success
+ *\li No memory
+ *\li Unexpected error
+ */
+
+isc_result_t
+isc_timer_touch(isc_timer_t *timer);
+/*%<
+ * Set the last-touched time of 'timer' to the current time.
+ *
+ * Requires:
+ *
+ *\li 'timer' is a valid once timer.
+ *
+ * Ensures:
+ *
+ *\li An idle timeout will not be generated until at least Now + the
+ * timer's interval if 'timer' is a once timer with a non-zero
+ * interval.
+ *
+ * Returns:
+ *
+ *\li Success
+ *\li Unexpected error
+ */
+
+void
+isc_timer_destroy(isc_timer_t **timerp);
+/*%<
+ * Destroy *timerp.
+ *
+ * Requires:
+ *
+ *\li 'timerp' points to a valid timer.
+ *
+ * Ensures:
+ *
+ *\li *timerp is NULL.
+ *
+ *\code
+ * The timer will be shutdown
+ *
+ * The timer will detach from its task
+ *
+ * All resources used by the timer have been freed
+ *
+ * Any events already posted by the timer will be purged.
+ * Therefore, if isc_timer_destroy() is called in the context
+ * of the timer's task, it is guaranteed that no more
+ * timer event callbacks will run after the call.
+ *
+ * If this function is called from the timer event callback
+ * the event itself must be destroyed before the timer
+ * itself.
+ *\endcode
+ */
+
+isc_timertype_t
+isc_timer_gettype(isc_timer_t *timer);
+/*%<
+ * Return the timer type.
+ *
+ * Requires:
+ *
+ *\li 'timer' to be a valid timer.
+ */
+
+isc_result_t
+isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
+/*%<
+ * Create a timer manager.
+ *
+ * Notes:
+ *
+ *\li All memory will be allocated in memory context 'mctx'.
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li 'managerp' points to a NULL isc_timermgr_t.
+ *
+ * Ensures:
+ *
+ *\li '*managerp' is a valid isc_timermgr_t.
+ *
+ * Returns:
+ *
+ *\li Success
+ *\li No memory
+ *\li Unexpected error
+ */
+
+void
+isc_timermgr_destroy(isc_timermgr_t **managerp);
+/*%<
+ * Destroy a timer manager.
+ *
+ * Notes:
+ *
+ *\li This routine blocks until there are no timers left in the manager,
+ * so if the caller holds any timer references using the manager, it
+ * must detach them before calling isc_timermgr_destroy() or it will
+ * block forever.
+ *
+ * Requires:
+ *
+ *\li '*managerp' is a valid isc_timermgr_t.
+ *
+ * Ensures:
+ *
+ *\li *managerp == NULL
+ *
+ *\li All resources used by the manager have been freed.
+ */
+
+void
+isc_timermgr_poke(isc_timermgr_t *m);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_TIMER_H */
diff --git a/lib/isc/include/isc/tm.h b/lib/isc/include/isc/tm.h
new file mode 100644
index 0000000..dd13448
--- /dev/null
+++ b/lib/isc/include/isc/tm.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_TM_H
+#define ISC_TM_H 1
+
+/*! \file isc/tm.h
+ * Provides portable conversion routines for struct tm.
+ */
+#include <time.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+time_t
+isc_tm_timegm(struct tm *tm);
+/*
+ * Convert a tm structure to time_t, using UTC rather than the local
+ * time zone.
+ */
+
+char *
+isc_tm_strptime(const char *buf, const char *fmt, struct tm *tm);
+/*
+ * Parse a formatted date string into struct tm.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_TIMER_H */
diff --git a/lib/isc/include/isc/types.h b/lib/isc/include/isc/types.h
new file mode 100644
index 0000000..60e7114
--- /dev/null
+++ b/lib/isc/include/isc/types.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_TYPES_H
+#define ISC_TYPES_H 1
+
+#include <isc/bind9.h>
+
+/*! \file isc/types.h
+ * \brief
+ * OS-specific types, from the OS-specific include directories.
+ */
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/offset.h>
+
+/*
+ * XXXDCL This is just for ISC_LIST and ISC_LINK, but gets all of the other
+ * list macros too.
+ */
+#include <isc/list.h>
+
+/* Core Types. Alphabetized by defined type. */
+
+typedef struct isc_astack isc_astack_t; /*%< Array-based fast stack */
+typedef struct isc_appctx isc_appctx_t; /*%< Application context */
+typedef struct isc_backtrace_symmap isc_backtrace_symmap_t; /*%< Symbol Table
+ * Entry */
+typedef struct isc_buffer isc_buffer_t; /*%< Buffer */
+typedef ISC_LIST(isc_buffer_t) isc_bufferlist_t; /*%< Buffer List */
+typedef struct isc_constregion isc_constregion_t; /*%< Const region */
+typedef struct isc_consttextregion isc_consttextregion_t; /*%< Const Text Region
+ */
+typedef struct isc_counter isc_counter_t; /*%< Counter */
+typedef int16_t isc_dscp_t; /*%< Diffserv code point */
+typedef struct isc_event isc_event_t; /*%< Event */
+typedef ISC_LIST(isc_event_t) isc_eventlist_t; /*%< Event List */
+typedef unsigned int isc_eventtype_t; /*%< Event Type */
+typedef uint32_t isc_fsaccess_t; /*%< FS Access */
+typedef struct isc_hash isc_hash_t; /*%< Hash */
+typedef struct isc_httpd isc_httpd_t; /*%< HTTP client */
+typedef void(isc_httpdfree_t)(isc_buffer_t *, void *); /*%< HTTP free function
+ */
+typedef struct isc_httpdmgr isc_httpdmgr_t; /*%< HTTP manager */
+typedef struct isc_httpdurl isc_httpdurl_t; /*%< HTTP URL */
+typedef void(isc_httpdondestroy_t)(void *); /*%< Callback on destroying httpd */
+typedef struct isc_interface isc_interface_t; /*%< Interface */
+typedef struct isc_interfaceiter isc_interfaceiter_t; /*%< Interface Iterator */
+typedef struct isc_interval isc_interval_t; /*%< Interval */
+typedef struct isc_lex isc_lex_t; /*%< Lex */
+typedef struct isc_log isc_log_t; /*%< Log */
+typedef struct isc_logcategory isc_logcategory_t; /*%< Log Category */
+typedef struct isc_logconfig isc_logconfig_t; /*%< Log Configuration */
+typedef struct isc_logmodule isc_logmodule_t; /*%< Log Module */
+typedef struct isc_mem isc_mem_t; /*%< Memory */
+typedef struct isc_mempool isc_mempool_t; /*%< Memory Pool */
+typedef struct isc_netaddr isc_netaddr_t; /*%< Net Address */
+typedef struct isc_nm isc_nm_t; /*%< Network manager */
+typedef struct isc_nmsocket isc_nmsocket_t; /*%< Network manager socket */
+typedef struct isc_nmhandle isc_nmhandle_t; /*%< Network manager handle */
+typedef struct isc_portset isc_portset_t; /*%< Port Set */
+typedef struct isc_quota isc_quota_t; /*%< Quota */
+typedef struct isc_ratelimiter isc_ratelimiter_t; /*%< Rate Limiter */
+typedef struct isc_region isc_region_t; /*%< Region */
+typedef uint64_t isc_resourcevalue_t; /*%< Resource Value */
+typedef unsigned int isc_result_t; /*%< Result */
+typedef struct isc_rwlock isc_rwlock_t; /*%< Read Write Lock */
+typedef struct isc_sockaddr isc_sockaddr_t; /*%< Socket Address */
+typedef ISC_LIST(isc_sockaddr_t) isc_sockaddrlist_t; /*%< Socket Address List
+ * */
+typedef struct isc_socket isc_socket_t; /*%< Socket */
+typedef struct isc_socketevent isc_socketevent_t; /*%< Socket Event */
+typedef struct isc_socketmgr isc_socketmgr_t; /*%< Socket Manager */
+typedef struct isc_stats isc_stats_t; /*%< Statistics */
+#if defined(_WIN32) && !defined(_WIN64)
+typedef int_fast32_t isc_statscounter_t; /*%< Statistics Counter */
+#else /* if defined(_WIN32) && !defined(_WIN64) */
+typedef int_fast64_t isc_statscounter_t;
+#endif /* if defined(_WIN32) && !defined(_WIN64) */
+typedef struct isc_symtab isc_symtab_t; /*%< Symbol Table */
+typedef struct isc_task isc_task_t; /*%< Task */
+typedef ISC_LIST(isc_task_t) isc_tasklist_t; /*%< Task List */
+typedef struct isc_taskmgr isc_taskmgr_t; /*%< Task Manager */
+typedef struct isc_textregion isc_textregion_t; /*%< Text Region */
+typedef struct isc_time isc_time_t; /*%< Time */
+typedef struct isc_timer isc_timer_t; /*%< Timer */
+typedef struct isc_timermgr isc_timermgr_t; /*%< Timer Manager */
+
+typedef void (*isc_taskaction_t)(isc_task_t *, isc_event_t *);
+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, isc_httpdurl_t *urlinfo, const char *querystring,
+ const char *headers, void *arg, unsigned int *retcode,
+ const char **retmsg, const char **mimetype, isc_buffer_t *body,
+ isc_httpdfree_t **freecb, void **freecb_args);
+typedef bool(isc_httpdclientok_t)(const isc_sockaddr_t *, void *);
+
+/*% Resource */
+typedef enum {
+ isc_resource_coresize = 1,
+ isc_resource_cputime,
+ isc_resource_datasize,
+ isc_resource_filesize,
+ isc_resource_lockedmemory,
+ isc_resource_openfiles,
+ isc_resource_processes,
+ isc_resource_residentsize,
+ isc_resource_stacksize
+} isc_resource_t;
+
+/*% Statistics formats (text file or XML) */
+typedef enum {
+ isc_statsformat_file,
+ isc_statsformat_xml,
+ isc_statsformat_json
+} isc_statsformat_t;
+
+#endif /* ISC_TYPES_H */
diff --git a/lib/isc/include/isc/url.h b/lib/isc/include/isc/url.h
new file mode 100644
index 0000000..4894a45
--- /dev/null
+++ b/lib/isc/include/isc/url.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0 and MIT
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <isc/result.h>
+
+/*
+ * Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
+ * faster
+ */
+#ifndef HTTP_PARSER_STRICT
+#define HTTP_PARSER_STRICT 1
+#endif
+
+typedef enum {
+ ISC_UF_SCHEMA = 0,
+ ISC_UF_HOST = 1,
+ ISC_UF_PORT = 2,
+ ISC_UF_PATH = 3,
+ ISC_UF_QUERY = 4,
+ ISC_UF_FRAGMENT = 5,
+ ISC_UF_USERINFO = 6,
+ ISC_UF_MAX = 7
+} isc_url_field_t;
+
+/* Result structure for isc_url_parse().
+ *
+ * Callers should index into field_data[] with UF_* values iff field_set
+ * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
+ * because we probably have padding left over), we convert any port to
+ * a uint16_t.
+ */
+typedef struct {
+ uint16_t field_set; /* Bitmask of (1 << UF_*) values */
+ uint16_t port; /* Converted UF_PORT string */
+
+ struct {
+ uint16_t off; /* Offset into buffer in which field starts */
+ uint16_t len; /* Length of run in buffer */
+ } field_data[ISC_UF_MAX];
+} isc_url_parser_t;
+
+isc_result_t
+isc_url_parse(const char *buf, size_t buflen, bool is_connect,
+ isc_url_parser_t *up);
+/*%<
+ * Parse a URL; return nonzero on failure
+ */
diff --git a/lib/isc/include/isc/utf8.h b/lib/isc/include/isc/utf8.h
new file mode 100644
index 0000000..5643c5d
--- /dev/null
+++ b/lib/isc/include/isc/utf8.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file isc/utf8.h */
+
+#pragma once
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+bool
+isc_utf8_bom(const unsigned char *buf, size_t len);
+/*<
+ * Returns 'true' if the string of bytes in 'buf' starts
+ * with an UTF-8 Byte Order Mark.
+ *
+ * Requires:
+ *\li 'buf' != NULL
+ */
+
+bool
+isc_utf8_valid(const unsigned char *buf, size_t len);
+/*<
+ * Returns 'true' if the string of bytes in 'buf' is a valid UTF-8
+ * byte sequence otherwise 'false' is returned.
+ *
+ * Requires:
+ *\li 'buf' != NULL
+ */
+
+ISC_LANG_ENDDECLS
diff --git a/lib/isc/include/isc/util.h b/lib/isc/include/isc/util.h
new file mode 100644
index 0000000..3396559
--- /dev/null
+++ b/lib/isc/include/isc/util.h
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_UTIL_H
+#define ISC_UTIL_H 1
+
+#include <inttypes.h>
+
+/*! \file isc/util.h
+ * NOTE:
+ *
+ * This file is not to be included from any <isc/???.h> (or other) library
+ * files.
+ *
+ * \brief
+ * Including this file puts several macros in your name space that are
+ * not protected (as all the other ISC functions/macros do) by prepending
+ * ISC_ or isc_ to the name.
+ */
+
+/***
+ *** Clang Compatibility Macros
+ ***/
+
+#if !defined(__has_attribute)
+#define __has_attribute(x) 0
+#endif /* if !defined(__has_attribute) */
+
+#if !defined(__has_c_attribute)
+#define __has_c_attribute(x) 0
+#endif /* if !defined(__has_c_attribute) */
+
+#if !defined(__has_feature)
+#define __has_feature(x) 0
+#endif /* if !defined(__has_feature) */
+
+/***
+ *** General Macros.
+ ***/
+
+/*%
+ * Use this to hide unused function arguments.
+ * \code
+ * int
+ * foo(char *bar)
+ * {
+ * UNUSED(bar);
+ * }
+ * \endcode
+ */
+#define UNUSED(x) (void)(x)
+
+#if __GNUC__ >= 8 && !defined(__clang__)
+#define ISC_NONSTRING __attribute__((nonstring))
+#else /* if __GNUC__ >= 8 && !defined(__clang__) */
+#define ISC_NONSTRING
+#endif /* __GNUC__ */
+
+#if __has_c_attribute(fallthrough)
+#define FALLTHROUGH [[fallthrough]]
+#elif __GNUC__ >= 7 && !defined(__clang__)
+#define FALLTHROUGH __attribute__((fallthrough))
+#else
+/* clang-format off */
+#define FALLTHROUGH do {} while (0) /* FALLTHROUGH */
+/* clang-format on */
+#endif
+
+#if HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR && HAVE_FUNC_ATTRIBUTE_DESTRUCTOR
+#define ISC_CONSTRUCTOR __attribute__((constructor))
+#define ISC_DESTRUCTOR __attribute__((destructor))
+#elif WIN32
+#define ISC_CONSTRUCTOR
+#define ISC_DESTRUCTOR
+#endif
+
+/*%
+ * 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))
+
+#define ISC_CLAMP(v, x, y) ((v) < (x) ? (x) : ((v) > (y) ? (y) : (v)))
+
+/*%
+ * Use this to remove the const qualifier of a variable to assign it to
+ * a non-const variable or pass it as a non-const function argument ...
+ * but only when you are sure it won't then be changed!
+ * This is necessary to sometimes shut up some compilers
+ * (as with gcc -Wcast-qual) when there is just no other good way to avoid the
+ * situation.
+ */
+#define DE_CONST(konst, var) \
+ do { \
+ union { \
+ const void *k; \
+ void *v; \
+ } _u; \
+ _u.k = konst; \
+ var = _u.v; \
+ } while (0)
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+
+/*%
+ * Use this in translation units that would otherwise be empty, to
+ * suppress compiler warnings.
+ */
+#define EMPTY_TRANSLATION_UNIT extern int isc__empty;
+
+/*%
+ * We use macros instead of calling the routines directly because
+ * the capital letters make the locking stand out.
+ * We RUNTIME_CHECK for success since in general there's no way
+ * for us to continue if they fail.
+ */
+
+#ifdef ISC_UTIL_TRACEON
+#define ISC_UTIL_TRACE(a) a
+#include <stdio.h> /* Required for fprintf/stderr when tracing. */
+#else /* ifdef ISC_UTIL_TRACEON */
+#define ISC_UTIL_TRACE(a)
+#endif /* ifdef ISC_UTIL_TRACEON */
+
+#include <isc/result.h> /* Contractual promise. */
+
+#define LOCK(lp) \
+ do { \
+ ISC_UTIL_TRACE(fprintf(stderr, "LOCKING %p %s %d\n", (lp), \
+ __FILE__, __LINE__)); \
+ RUNTIME_CHECK(isc_mutex_lock((lp)) == ISC_R_SUCCESS); \
+ ISC_UTIL_TRACE(fprintf(stderr, "LOCKED %p %s %d\n", (lp), \
+ __FILE__, __LINE__)); \
+ } while (0)
+#define UNLOCK(lp) \
+ do { \
+ RUNTIME_CHECK(isc_mutex_unlock((lp)) == ISC_R_SUCCESS); \
+ ISC_UTIL_TRACE(fprintf(stderr, "UNLOCKED %p %s %d\n", (lp), \
+ __FILE__, __LINE__)); \
+ } while (0)
+
+#define BROADCAST(cvp) \
+ do { \
+ ISC_UTIL_TRACE(fprintf(stderr, "BROADCAST %p %s %d\n", (cvp), \
+ __FILE__, __LINE__)); \
+ RUNTIME_CHECK(isc_condition_broadcast((cvp)) == \
+ ISC_R_SUCCESS); \
+ } while (0)
+#define SIGNAL(cvp) \
+ do { \
+ ISC_UTIL_TRACE(fprintf(stderr, "SIGNAL %p %s %d\n", (cvp), \
+ __FILE__, __LINE__)); \
+ RUNTIME_CHECK(isc_condition_signal((cvp)) == ISC_R_SUCCESS); \
+ } while (0)
+#define WAIT(cvp, lp) \
+ do { \
+ ISC_UTIL_TRACE(fprintf(stderr, "WAIT %p LOCK %p %s %d\n", \
+ (cvp), (lp), __FILE__, __LINE__)); \
+ RUNTIME_CHECK(isc_condition_wait((cvp), (lp)) == \
+ ISC_R_SUCCESS); \
+ ISC_UTIL_TRACE(fprintf(stderr, "WAITED %p LOCKED %p %s %d\n", \
+ (cvp), (lp), __FILE__, __LINE__)); \
+ } while (0)
+
+/*
+ * isc_condition_waituntil can return ISC_R_TIMEDOUT, so we
+ * don't RUNTIME_CHECK the result.
+ *
+ * XXX Also, can't really debug this then...
+ */
+
+#define WAITUNTIL(cvp, lp, tp) isc_condition_waituntil((cvp), (lp), (tp))
+
+#define RWLOCK(lp, t) \
+ do { \
+ ISC_UTIL_TRACE(fprintf(stderr, "RWLOCK %p, %d %s %d\n", (lp), \
+ (t), __FILE__, __LINE__)); \
+ RUNTIME_CHECK(isc_rwlock_lock((lp), (t)) == ISC_R_SUCCESS); \
+ ISC_UTIL_TRACE(fprintf(stderr, "RWLOCKED %p, %d %s %d\n", \
+ (lp), (t), __FILE__, __LINE__)); \
+ } while (0)
+#define RWUNLOCK(lp, t) \
+ do { \
+ ISC_UTIL_TRACE(fprintf(stderr, "RWUNLOCK %p, %d %s %d\n", \
+ (lp), (t), __FILE__, __LINE__)); \
+ RUNTIME_CHECK(isc_rwlock_unlock((lp), (t)) == ISC_R_SUCCESS); \
+ } while (0)
+
+/*
+ * List Macros.
+ */
+#include <isc/list.h> /* Contractual promise. */
+
+#define LIST(type) ISC_LIST(type)
+#define INIT_LIST(type) ISC_LIST_INIT(type)
+#define LINK(type) ISC_LINK(type)
+#define INIT_LINK(elt, link) ISC_LINK_INIT(elt, link)
+#define HEAD(list) ISC_LIST_HEAD(list)
+#define TAIL(list) ISC_LIST_TAIL(list)
+#define EMPTY(list) ISC_LIST_EMPTY(list)
+#define PREV(elt, link) ISC_LIST_PREV(elt, link)
+#define NEXT(elt, link) ISC_LIST_NEXT(elt, link)
+#define APPEND(list, elt, link) ISC_LIST_APPEND(list, elt, link)
+#define PREPEND(list, elt, link) ISC_LIST_PREPEND(list, elt, link)
+#define UNLINK(list, elt, link) ISC_LIST_UNLINK(list, elt, link)
+#define ENQUEUE(list, elt, link) ISC_LIST_APPEND(list, elt, link)
+#define DEQUEUE(list, elt, link) ISC_LIST_UNLINK(list, elt, link)
+#define INSERTBEFORE(li, b, e, ln) ISC_LIST_INSERTBEFORE(li, b, e, ln)
+#define INSERTAFTER(li, a, e, ln) ISC_LIST_INSERTAFTER(li, a, e, ln)
+#define APPENDLIST(list1, list2, link) ISC_LIST_APPENDLIST(list1, list2, link)
+
+/*%
+ * Performance
+ */
+#include <isc/likely.h>
+
+/* GCC defines __SANITIZE_ADDRESS__, so reuse the macro for clang */
+#if __has_feature(address_sanitizer)
+#define __SANITIZE_ADDRESS__ 1
+#endif /* if __has_feature(address_sanitizer) */
+
+#if __has_feature(thread_sanitizer)
+#define __SANITIZE_THREAD__ 1
+#endif /* if __has_feature(thread_sanitizer) */
+
+#if __SANITIZE_THREAD__
+#define ISC_NO_SANITIZE_THREAD __attribute__((no_sanitize("thread")))
+#else /* if __SANITIZE_THREAD__ */
+#define ISC_NO_SANITIZE_THREAD
+#endif /* if __SANITIZE_THREAD__ */
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR >= 6)
+#define STATIC_ASSERT(cond, msg) _Static_assert(cond, msg)
+#elif __has_feature(c_static_assert)
+#define STATIC_ASSERT(cond, msg) _Static_assert(cond, msg)
+#else /* if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR >= 6) */
+#define STATIC_ASSERT(cond, msg) INSIST(cond)
+#endif /* if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR >= 6) */
+
+#ifdef UNIT_TESTING
+extern void
+mock_assert(const int result, const char *const expression,
+ const char *const file, const int line);
+/*
+ * Allow clang to determine that the following code is not reached
+ * by calling abort() if the condition fails. The abort() will
+ * never be executed as mock_assert() and _assert_true() longjmp
+ * or exit if the condition is false.
+ */
+#define REQUIRE(expression) \
+ ((!(expression)) \
+ ? (mock_assert(0, #expression, __FILE__, __LINE__), abort()) \
+ : (void)0)
+#define ENSURE(expression) \
+ ((!(int)(expression)) \
+ ? (mock_assert(0, #expression, __FILE__, __LINE__), abort()) \
+ : (void)0)
+#define INSIST(expression) \
+ ((!(expression)) \
+ ? (mock_assert(0, #expression, __FILE__, __LINE__), abort()) \
+ : (void)0)
+#define INVARIANT(expression) \
+ ((!(expression)) \
+ ? (mock_assert(0, #expression, __FILE__, __LINE__), abort()) \
+ : (void)0)
+#define UNREACHABLE() \
+ (mock_assert(0, "unreachable", __FILE__, __LINE__), abort())
+#define _assert_true(c, e, f, l) \
+ ((c) ? (void)0 : (_assert_true(0, e, f, l), abort()))
+#define _assert_int_equal(a, b, f, l) \
+ (((a) == (b)) ? (void)0 : (_assert_int_equal(a, b, f, l), abort()))
+#define _assert_int_not_equal(a, b, f, l) \
+ (((a) != (b)) ? (void)0 : (_assert_int_not_equal(a, b, f, l), abort()))
+#else /* UNIT_TESTING */
+
+#ifndef CPPCHECK
+
+/*
+ * Assertions
+ */
+#include <isc/assertions.h> /* Contractual promise. */
+
+/*% Require Assertion */
+#define REQUIRE(e) ISC_REQUIRE(e)
+/*% Ensure Assertion */
+#define ENSURE(e) ISC_ENSURE(e)
+/*% Insist Assertion */
+#define INSIST(e) ISC_INSIST(e)
+/*% Invariant Assertion */
+#define INVARIANT(e) ISC_INVARIANT(e)
+
+#define UNREACHABLE() ISC_UNREACHABLE()
+
+#else /* CPPCHECK */
+
+/*% Require Assertion */
+#define REQUIRE(e) \
+ if (!(e)) \
+ abort()
+/*% Ensure Assertion */
+#define ENSURE(e) \
+ if (!(e)) \
+ abort()
+/*% Insist Assertion */
+#define INSIST(e) \
+ if (!(e)) \
+ abort()
+/*% Invariant Assertion */
+#define INVARIANT(e) \
+ if (!(e)) \
+ abort()
+
+#define UNREACHABLE() abort()
+
+#endif /* CPPCHECK */
+
+#endif /* UNIT_TESTING */
+
+/*
+ * Errors
+ */
+#include <isc/error.h> /* Contractual promise. */
+
+/*% Unexpected Error */
+#define UNEXPECTED_ERROR isc_error_unexpected
+/*% Fatal Error */
+#define FATAL_ERROR isc_error_fatal
+
+#ifdef UNIT_TESTING
+
+#define RUNTIME_CHECK(expression) \
+ ((!(expression)) \
+ ? (mock_assert(0, #expression, __FILE__, __LINE__), abort()) \
+ : (void)0)
+
+#else /* UNIT_TESTING */
+
+#ifndef CPPCHECK
+/*% Runtime Check */
+#define RUNTIME_CHECK(cond) ISC_ERROR_RUNTIMECHECK(cond)
+#else /* ifndef CPPCHECK */
+#define RUNTIME_CHECK(e) \
+ if (!(e)) \
+ abort()
+#endif /* ifndef CPPCHECK */
+
+#endif /* UNIT_TESTING */
+
+/*%
+ * Time
+ */
+#define TIME_NOW(tp) RUNTIME_CHECK(isc_time_now((tp)) == ISC_R_SUCCESS)
+#define TIME_NOW_HIRES(tp) \
+ RUNTIME_CHECK(isc_time_now_hires((tp)) == ISC_R_SUCCESS)
+
+/*%
+ * Alignment
+ */
+#ifdef __GNUC__
+#define ISC_ALIGN(x, a) (((x) + (a)-1) & ~((typeof(x))(a)-1))
+#else /* ifdef __GNUC__ */
+#define ISC_ALIGN(x, a) (((x) + (a)-1) & ~((uintmax_t)(a)-1))
+#endif /* ifdef __GNUC__ */
+
+#if HAVE_FUNC_ATTRIBUTE_RETURNS_NONNULL
+#define ISC_ATTR_RETURNS_NONNULL __attribute__((returns_nonnull))
+#else
+#define ISC_ATTR_RETURNS_NONNULL
+#endif
+
+/*
+ * Support for malloc attributes.
+ */
+#ifdef HAVE_FUNC_ATTRIBUTE_MALLOC
+/*
+ * Indicates that a function is malloc-like, i.e., that the
+ * pointer P returned by the function cannot alias any other
+ * pointer valid when the function returns.
+ */
+#define ISC_ATTR_MALLOC __attribute__((malloc))
+#if HAVE_MALLOC_EXT_ATTR
+/*
+ * Associates deallocator as a suitable deallocation function
+ * for pointers returned from the function marked with the attribute.
+ */
+#define ISC_ATTR_DEALLOCATOR(deallocator) __attribute__((malloc(deallocator)))
+/*
+ * Similar to ISC_ATTR_DEALLOCATOR, but allows to speficy an index "idx",
+ * which denotes the positional argument to which when the pointer is passed
+ * in calls to deallocator has the effect of deallocating it.
+ */
+#define ISC_ATTR_DEALLOCATOR_IDX(deallocator, idx) \
+ __attribute__((malloc(deallocator, idx)))
+/*
+ * Combines both ISC_ATTR_MALLOC and ISC_ATTR_DEALLOCATOR attributes.
+ */
+#define ISC_ATTR_MALLOC_DEALLOCATOR(deallocator) \
+ __attribute__((malloc, malloc(deallocator)))
+/*
+ * Similar to ISC_ATTR_MALLOC_DEALLOCATOR, but allows to speficy an index "idx",
+ * which denotes the positional argument to which when the pointer is passed
+ * in calls to deallocator has the effect of deallocating it.
+ */
+#define ISC_ATTR_MALLOC_DEALLOCATOR_IDX(deallocator, idx) \
+ __attribute__((malloc, malloc(deallocator, idx)))
+#else /* #ifdef HAVE_MALLOC_EXT_ATTR */
+/*
+ * There is support for malloc attribute but not for
+ * extended attributes, so macros that combine attribute malloc
+ * with a deallocator will only expand to malloc attribute.
+ */
+#define ISC_ATTR_DEALLOCATOR(deallocator)
+#define ISC_ATTR_DEALLOCATOR_IDX(deallocator, idx)
+#define ISC_ATTR_MALLOC_DEALLOCATOR(deallocator) ISC_ATTR_MALLOC
+#define ISC_ATTR_MALLOC_DEALLOCATOR_IDX(deallocator, idx) ISC_ATTR_MALLOC
+#endif
+#else /* #ifdef HAVE_FUNC_ATTRIBUTE_MALLOC */
+/*
+ * There is no support for malloc attribute.
+ */
+#define ISC_ATTR_MALLOC
+#define ISC_ATTR_DEALLOCATOR(deallocator)
+#define ISC_ATTR_DEALLOCATOR_IDX(deallocator, idx)
+#define ISC_ATTR_MALLOC_DEALLOCATOR(deallocator)
+#define ISC_ATTR_MALLOC_DEALLOCATOR_IDX(deallocator, idx)
+#endif /* HAVE_FUNC_ATTRIBUTE_MALLOC */
+
+/*%
+ * Misc
+ */
+#include <isc/deprecated.h>
+
+#endif /* ISC_UTIL_H */
diff --git a/lib/isc/include/isc/version.h b/lib/isc/include/isc/version.h
new file mode 100644
index 0000000..4b81e44
--- /dev/null
+++ b/lib/isc/include/isc/version.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file isc/version.h */
+
+#include <isc/platform.h>
+
+LIBISC_EXTERNAL_DATA extern const char isc_version[];
diff --git a/lib/isc/include/pk11/Makefile.in b/lib/isc/include/pk11/Makefile.in
new file mode 100644
index 0000000..3ba0c1f
--- /dev/null
+++ b/lib/isc/include/pk11/Makefile.in
@@ -0,0 +1,40 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+#
+# Only list headers that are to be installed and are not
+# machine generated. The latter are handled specially in the
+# install target below.
+#
+HEADERS = constants.h internal.h pk11.h result.h site.h
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/pk11
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/pk11 || exit 1; \
+ done
+
+uninstall::
+ for i in ${HEADERS}; do \
+ rm -f ${DESTDIR}${includedir}/pk11/$$i || exit 1; \
+ done
diff --git a/lib/isc/include/pk11/constants.h b/lib/isc/include/pk11/constants.h
new file mode 100644
index 0000000..c682053
--- /dev/null
+++ b/lib/isc/include/pk11/constants.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+#include <inttypes.h>
+
+/*! \file pk11/constants.h */
+
+/*%
+ * Static arrays of data used for key template initialization
+ */
+#define PK11_ECC_PRIME256V1 \
+ (uint8_t[]) { \
+ 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 \
+ }
+#define PK11_ECC_SECP384R1 \
+ (uint8_t[]) { 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22 }
+#define PK11_ECX_ED25519 \
+ (uint8_t[]) { \
+ 0x13, 0xc, 'e', 'd', 'w', 'a', 'r', 'd', 's', '2', '5', '5', \
+ '1', '9' \
+ }
+#define PK11_ECX_ED448 \
+ (uint8_t[]) { \
+ 0x13, 0xa, 'e', 'd', 'w', 'a', 'r', 'd', 's', '4', '4', '8' \
+ }
diff --git a/lib/isc/include/pk11/internal.h b/lib/isc/include/pk11/internal.h
new file mode 100644
index 0000000..38bd751
--- /dev/null
+++ b/lib/isc/include/pk11/internal.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef PK11_INTERNAL_H
+#define PK11_INTERNAL_H 1
+
+/*! \file pk11/internal.h */
+
+#include <pk11/pk11.h>
+
+ISC_LANG_BEGINDECLS
+
+const char *
+pk11_get_lib_name(void);
+
+void *
+pk11_mem_get(size_t size);
+
+void
+pk11_mem_put(void *ptr, size_t size);
+
+CK_SLOT_ID
+pk11_get_best_token(pk11_optype_t optype);
+
+isc_result_t
+pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt, unsigned int *bits);
+
+CK_ATTRIBUTE *
+pk11_attribute_first(const pk11_object_t *obj);
+
+CK_ATTRIBUTE *
+pk11_attribute_next(const pk11_object_t *obj, CK_ATTRIBUTE *attr);
+
+CK_ATTRIBUTE *
+pk11_attribute_bytype(const pk11_object_t *obj, CK_ATTRIBUTE_TYPE type);
+
+ISC_LANG_ENDDECLS
+
+#endif /* PK11_INTERNAL_H */
diff --git a/lib/isc/include/pk11/pk11.h b/lib/isc/include/pk11/pk11.h
new file mode 100644
index 0000000..076c119
--- /dev/null
+++ b/lib/isc/include/pk11/pk11.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef PK11_PK11_H
+#define PK11_PK11_H 1
+
+/*! \file pk11/pk11.h */
+
+#include <stdbool.h>
+#include <unistd.h>
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/types.h>
+
+#define PK11_FATALCHECK(func, args) \
+ ((void)(((rv = (func)args) == CKR_OK) || \
+ ((pk11_error_fatalcheck)(__FILE__, __LINE__, #func, rv), 0)))
+
+#include <pk11/site.h>
+#include <pkcs11/pkcs11.h>
+
+ISC_LANG_BEGINDECLS
+
+#define SES_MAGIC ISC_MAGIC('P', 'K', 'S', 'S')
+#define TOK_MAGIC ISC_MAGIC('P', 'K', 'T', 'K')
+
+#define VALID_SES(x) ISC_MAGIC_VALID(x, SES_MAGIC)
+#define VALID_TOK(x) ISC_MAGIC_VALID(x, TOK_MAGIC)
+
+typedef struct pk11_context pk11_context_t;
+
+struct pk11_object {
+ CK_OBJECT_HANDLE object;
+ CK_SLOT_ID slot;
+ CK_BBOOL ontoken;
+ CK_BBOOL reqlogon;
+ CK_BYTE attrcnt;
+ CK_ATTRIBUTE *repr;
+};
+
+struct pk11_context {
+ void *handle;
+ CK_SESSION_HANDLE session;
+ CK_BBOOL ontoken;
+ CK_OBJECT_HANDLE object;
+};
+
+typedef struct pk11_object pk11_object_t;
+
+typedef enum {
+ OP_ANY = 0,
+ OP_RSA = 1,
+ OP_DH = 3,
+ OP_ECDSA = 4,
+ OP_EDDSA = 5,
+ OP_MAX = 6
+} pk11_optype_t;
+
+/*%
+ * Global flag to make choose_slots() verbose
+ */
+LIBISC_EXTERNAL_DATA extern bool pk11_verbose_init;
+
+/*%
+ * Function prototypes
+ */
+
+void
+pk11_set_lib_name(const char *lib_name);
+/*%<
+ * Set the PKCS#11 provider (aka library) path/name.
+ */
+
+isc_result_t
+pk11_initialize(isc_mem_t *mctx, const char *engine);
+/*%<
+ * Initialize PKCS#11 device
+ *
+ * mctx: memory context to attach to pk11_mctx.
+ * engine: PKCS#11 provider (aka library) path/name.
+ *
+ * returns:
+ * ISC_R_SUCCESS
+ * PK11_R_NOPROVIDER: can't load the provider
+ * PK11_R_INITFAILED: C_Initialize() failed
+ * PK11_R_NORANDOMSERVICE: can't find required random service
+ * PK11_R_NODIGESTSERVICE: can't find required digest service
+ * PK11_R_NOAESSERVICE: can't find required AES service
+ */
+
+isc_result_t
+pk11_get_session(pk11_context_t *ctx, pk11_optype_t optype, bool need_services,
+ bool rw, bool logon, const char *pin, CK_SLOT_ID slot);
+/*%<
+ * Initialize PKCS#11 device and acquire a session.
+ *
+ * need_services:
+ * if true, this session requires full PKCS#11 API
+ * support including random and digest services, and
+ * the lack of these services will cause the session not
+ * to be initialized. If false, the function will return
+ * an error code indicating the missing service, but the
+ * session will be usable for other purposes.
+ * rw: if true, session will be read/write (useful for
+ * generating or destroying keys); otherwise read-only.
+ * login: indicates whether to log in to the device
+ * pin: optional PIN, overriding any PIN currently associated
+ * with the
+ * slot: device slot ID
+ */
+
+void
+pk11_return_session(pk11_context_t *ctx);
+/*%<
+ * Release an active PKCS#11 session for reuse.
+ */
+
+isc_result_t
+pk11_finalize(void);
+/*%<
+ * Shut down PKCS#11 device and free all sessions.
+ */
+
+isc_result_t
+pk11_parse_uri(pk11_object_t *obj, const char *label, isc_mem_t *mctx,
+ pk11_optype_t optype);
+
+ISC_PLATFORM_NORETURN_PRE void
+pk11_error_fatalcheck(const char *file, int line, const char *funcname,
+ CK_RV rv) ISC_PLATFORM_NORETURN_POST;
+
+void
+pk11_dump_tokens(void);
+
+CK_RV
+pkcs_C_Initialize(CK_VOID_PTR pReserved);
+
+char *
+pk11_get_load_error_message(void);
+
+CK_RV
+pkcs_C_Finalize(CK_VOID_PTR pReserved);
+
+CK_RV
+pkcs_C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
+ CK_ULONG_PTR pulCount);
+
+CK_RV
+pkcs_C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo);
+
+CK_RV
+pkcs_C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR pInfo);
+
+CK_RV
+pkcs_C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication,
+ CK_RV (*Notify)(CK_SESSION_HANDLE hSession,
+ CK_NOTIFICATION event,
+ CK_VOID_PTR pApplication),
+ CK_SESSION_HANDLE_PTR phSession);
+
+CK_RV
+pkcs_C_CloseSession(CK_SESSION_HANDLE hSession);
+
+CK_RV
+pkcs_C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
+ CK_CHAR_PTR pPin, CK_ULONG usPinLen);
+
+CK_RV
+pkcs_C_Logout(CK_SESSION_HANDLE hSession);
+
+CK_RV
+pkcs_C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG usCount, CK_OBJECT_HANDLE_PTR phObject);
+
+CK_RV
+pkcs_C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject);
+
+CK_RV
+pkcs_C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount);
+
+CK_RV
+pkcs_C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount);
+
+CK_RV
+pkcs_C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG usCount);
+
+CK_RV
+pkcs_C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject,
+ CK_ULONG usMaxObjectCount, CK_ULONG_PTR pusObjectCount);
+
+CK_RV
+pkcs_C_FindObjectsFinal(CK_SESSION_HANDLE hSession);
+
+CK_RV
+pkcs_C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+
+CK_RV
+pkcs_C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
+ CK_ULONG_PTR pulEncryptedDataLen);
+
+CK_RV
+pkcs_C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism);
+
+CK_RV
+pkcs_C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen);
+
+CK_RV
+pkcs_C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
+ CK_ULONG_PTR pulDigestLen);
+
+CK_RV
+pkcs_C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+
+CK_RV
+pkcs_C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
+ CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen);
+
+CK_RV
+pkcs_C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen);
+
+CK_RV
+pkcs_C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen);
+
+CK_RV
+pkcs_C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey);
+
+CK_RV
+pkcs_C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
+ CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen);
+
+CK_RV
+pkcs_C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen);
+
+CK_RV
+pkcs_C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
+ CK_ULONG ulSignatureLen);
+
+CK_RV
+pkcs_C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
+ CK_OBJECT_HANDLE_PTR phKey);
+
+CK_RV
+pkcs_C_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+ CK_ULONG usPublicKeyAttributeCount,
+ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+ CK_ULONG usPrivateKeyAttributeCount,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ CK_OBJECT_HANDLE_PTR phPublicKey);
+
+CK_RV
+pkcs_C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey);
+
+CK_RV
+pkcs_C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
+ CK_ULONG ulSeedLen);
+
+CK_RV
+pkcs_C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR RandomData,
+ CK_ULONG ulRandomLen);
+
+ISC_LANG_ENDDECLS
+
+#endif /* PK11_PK11_H */
diff --git a/lib/isc/include/pk11/result.h b/lib/isc/include/pk11/result.h
new file mode 100644
index 0000000..d92b15d
--- /dev/null
+++ b/lib/isc/include/pk11/result.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef PK11_RESULT_H
+#define PK11_RESULT_H 1
+
+/*! \file pk11/result.h */
+
+#include <isc/lang.h>
+#include <isc/resultclass.h>
+#include <isc/types.h>
+
+/*
+ * Nothing in this file truly depends on <isc/result.h>, but the
+ * PK11 result codes are considered to be publicly derived from
+ * the ISC result codes, so including this file buys you the ISC_R_
+ * namespace too.
+ */
+#include <isc/result.h> /* Contractual promise. */
+
+#define PK11_R_INITFAILED (ISC_RESULTCLASS_PK11 + 0)
+#define PK11_R_NOPROVIDER (ISC_RESULTCLASS_PK11 + 1)
+#define PK11_R_NORANDOMSERVICE (ISC_RESULTCLASS_PK11 + 2)
+#define PK11_R_NODIGESTSERVICE (ISC_RESULTCLASS_PK11 + 3)
+#define PK11_R_NOAESSERVICE (ISC_RESULTCLASS_PK11 + 4)
+
+#define PK11_R_NRESULTS 5 /* Number of results */
+
+ISC_LANG_BEGINDECLS
+
+const char *pk11_result_totext(isc_result_t);
+
+void
+pk11_result_register(void);
+
+ISC_LANG_ENDDECLS
+
+#endif /* PK11_RESULT_H */
diff --git a/lib/isc/include/pk11/site.h b/lib/isc/include/pk11/site.h
new file mode 100644
index 0000000..ceebb59
--- /dev/null
+++ b/lib/isc/include/pk11/site.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file pk11/site.h */
diff --git a/lib/isc/include/pkcs11/Makefile.in b/lib/isc/include/pkcs11/Makefile.in
new file mode 100644
index 0000000..8822f5a
--- /dev/null
+++ b/lib/isc/include/pkcs11/Makefile.in
@@ -0,0 +1,40 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+#
+# Only list headers that are to be installed and are not
+# machine generated. The latter are handled specially in the
+# install target below.
+#
+HEADERS = pkcs11.h
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/pkcs11
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/pkcs11 || exit 1; \
+ done
+
+uninstall::
+ for i in ${HEADERS}; do \
+ rm -f ${DESTDIR}${includedir}/pkcs11/$$i || exit 1; \
+ done
diff --git a/lib/isc/include/pkcs11/pkcs11.h b/lib/isc/include/pkcs11/pkcs11.h
new file mode 100644
index 0000000..30228d2
--- /dev/null
+++ b/lib/isc/include/pkcs11/pkcs11.h
@@ -0,0 +1,1655 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ * Copyright 2006 Andreas Jellinghaus
+ * Copyright 2006, 2007 g10 Code GmbH
+ * Copyright 2017 Red Hat, Inc.
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* Please submit any changes back to the p11-kit project at
+ * https://github.com/p11-glue/p11-kit/, so that
+ * they can be picked up by other projects from there as well. */
+
+/* This file is a modified implementation of the PKCS #11 standard by
+ * OASIS group. It is mostly a drop-in replacement, with the
+ * following change:
+ *
+ * This header file does not require any macro definitions by the user
+ * (like CK_DEFINE_FUNCTION etc). In fact, it defines those macros
+ * for you (if useful, some are missing, let me know if you need
+ * more).
+ *
+ * There is an additional API available that does comply better to the
+ * GNU coding standard. It can be switched on by defining
+ * CRYPTOKI_GNU before including this header file. For this, the
+ * following changes are made to the specification:
+ *
+ * All structure types are changed to a "struct ck_foo" where CK_FOO
+ * is the type name in PKCS #11.
+ *
+ * All non-structure types are changed to ck_foo_t where CK_FOO is the
+ * lowercase version of the type name in PKCS #11. The basic types
+ * (CK_ULONG et al.) are removed without substitute.
+ *
+ * All members of structures are modified in the following way: Type
+ * indication prefixes are removed, and underscore characters are
+ * inserted before words. Then the result is lowercased.
+ *
+ * Note that function names are still in the original case, as they
+ * need for ABI compatibility.
+ *
+ * CK_FALSE, CK_TRUE and NULL_PTR are removed without substitute. Use
+ * <stdbool.h>.
+ *
+ * If CRYPTOKI_COMPAT is defined before including this header file,
+ * then none of the API changes above take place, and the API is the
+ * one defined by the PKCS #11 standard. */
+
+#ifndef PKCS11_H
+#define PKCS11_H 1
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* if defined(__cplusplus) */
+
+/* The version of cryptoki we implement. The revision is changed with
+ * each modification of this file. */
+#define CRYPTOKI_VERSION_MAJOR 2
+#define CRYPTOKI_VERSION_MINOR 40
+#define P11_KIT_CRYPTOKI_VERSION_REVISION 0
+
+/* Compatibility interface is default, unless CRYPTOKI_GNU is
+ * given. */
+#ifndef CRYPTOKI_GNU
+#ifndef CRYPTOKI_COMPAT
+#define CRYPTOKI_COMPAT 1
+#endif /* ifndef CRYPTOKI_COMPAT */
+#endif /* ifndef CRYPTOKI_GNU */
+
+/* System dependencies. */
+
+#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32)
+
+/* There is a matching pop below. */
+#pragma pack(push, cryptoki, 1)
+
+#ifdef CRYPTOKI_EXPORTS
+#define CK_SPEC __declspec(dllexport)
+#else /* ifdef CRYPTOKI_EXPORTS */
+#define CK_SPEC __declspec(dllimport)
+#endif /* ifdef CRYPTOKI_EXPORTS */
+
+#else /* if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) */
+
+#define CK_SPEC
+
+#endif /* if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) */
+
+#ifdef CRYPTOKI_COMPAT
+/* If we are in compatibility mode, switch all exposed names to the
+ * PKCS #11 variant. There are corresponding #undefs below. */
+
+#define ck_flags_t CK_FLAGS
+#define ck_version _CK_VERSION
+
+#define ck_info _CK_INFO
+#define cryptoki_version cryptokiVersion
+#define manufacturer_id manufacturerID
+#define library_description libraryDescription
+#define library_version libraryVersion
+
+#define ck_notification_t CK_NOTIFICATION
+#define ck_slot_id_t CK_SLOT_ID
+
+#define ck_slot_info _CK_SLOT_INFO
+#define slot_description slotDescription
+#define hardware_version hardwareVersion
+#define firmware_version firmwareVersion
+
+#define ck_token_info _CK_TOKEN_INFO
+#define serial_number serialNumber
+#define max_session_count ulMaxSessionCount
+#define session_count ulSessionCount
+#define max_rw_session_count ulMaxRwSessionCount
+#define rw_session_count ulRwSessionCount
+#define max_pin_len ulMaxPinLen
+#define min_pin_len ulMinPinLen
+#define total_public_memory ulTotalPublicMemory
+#define free_public_memory ulFreePublicMemory
+#define total_private_memory ulTotalPrivateMemory
+#define free_private_memory ulFreePrivateMemory
+#define utc_time utcTime
+
+#define ck_session_handle_t CK_SESSION_HANDLE
+#define ck_user_type_t CK_USER_TYPE
+#define ck_state_t CK_STATE
+
+#define ck_session_info _CK_SESSION_INFO
+#define slot_id slotID
+#define device_error ulDeviceError
+
+#define ck_object_handle_t CK_OBJECT_HANDLE
+#define ck_object_class_t CK_OBJECT_CLASS
+#define ck_hw_feature_type_t CK_HW_FEATURE_TYPE
+#define ck_key_type_t CK_KEY_TYPE
+#define ck_certificate_type_t CK_CERTIFICATE_TYPE
+#define ck_attribute_type_t CK_ATTRIBUTE_TYPE
+
+#define ck_attribute _CK_ATTRIBUTE
+#define value pValue
+#define value_len ulValueLen
+
+#define count ulCount
+
+#define ck_date _CK_DATE
+
+#define ck_mechanism_type_t CK_MECHANISM_TYPE
+
+#define ck_mechanism _CK_MECHANISM
+#define parameter pParameter
+#define parameter_len ulParameterLen
+
+#define params pParams
+
+#define ck_mechanism_info _CK_MECHANISM_INFO
+#define min_key_size ulMinKeySize
+#define max_key_size ulMaxKeySize
+
+#define ck_param_type CK_PARAM_TYPE
+#define ck_otp_param CK_OTP_PARAM
+#define ck_otp_params CK_OTP_PARAMS
+#define ck_otp_signature_info CK_OTP_SIGNATURE_INFO
+
+#define ck_rv_t CK_RV
+#define ck_notify_t CK_NOTIFY
+
+#define ck_function_list _CK_FUNCTION_LIST
+
+#define ck_createmutex_t CK_CREATEMUTEX
+#define ck_destroymutex_t CK_DESTROYMUTEX
+#define ck_lockmutex_t CK_LOCKMUTEX
+#define ck_unlockmutex_t CK_UNLOCKMUTEX
+
+#define ck_c_initialize_args _CK_C_INITIALIZE_ARGS
+#define create_mutex CreateMutex
+#define destroy_mutex DestroyMutex
+#define lock_mutex LockMutex
+#define unlock_mutex UnlockMutex
+#define reserved pReserved
+
+#define ck_rsa_pkcs_mgf_type_t CK_RSA_PKCS_MGF_TYPE
+#define ck_rsa_pkcs_oaep_source_type_t CK_RSA_PKCS_OAEP_SOURCE_TYPE
+#define hash_alg hashAlg
+#define s_len sLen
+#define source_data pSourceData
+#define source_data_len ulSourceDataLen
+
+#define counter_bits ulCounterBits
+#define iv_ptr pIv
+#define iv_len ulIvLen
+#define iv_bits ulIvBits
+#define aad_ptr pAAD
+#define aad_len ulAADLen
+#define tag_bits ulTagBits
+#define shared_data_len ulSharedDataLen
+#define shared_data pSharedData
+#define public_data_len ulPublicDataLen
+#define public_data pPublicData
+#define string_data pData
+#define string_data_len ulLen
+#define data_params pData
+#endif /* CRYPTOKI_COMPAT */
+
+typedef unsigned long ck_flags_t;
+
+struct ck_version {
+ unsigned char major;
+ unsigned char minor;
+};
+
+struct ck_info {
+ struct ck_version cryptoki_version;
+ unsigned char manufacturer_id[32];
+ ck_flags_t flags;
+ unsigned char library_description[32];
+ struct ck_version library_version;
+};
+
+typedef unsigned long ck_notification_t;
+
+#define CKN_SURRENDER (0UL)
+
+typedef unsigned long ck_slot_id_t;
+
+struct ck_slot_info {
+ unsigned char slot_description[64];
+ unsigned char manufacturer_id[32];
+ ck_flags_t flags;
+ struct ck_version hardware_version;
+ struct ck_version firmware_version;
+};
+
+#define CKF_TOKEN_PRESENT (1UL << 0)
+#define CKF_REMOVABLE_DEVICE (1UL << 1)
+#define CKF_HW_SLOT (1UL << 2)
+#define CKF_ARRAY_ATTRIBUTE (1UL << 30)
+
+struct ck_token_info {
+ unsigned char label[32];
+ unsigned char manufacturer_id[32];
+ unsigned char model[16];
+ unsigned char serial_number[16];
+ ck_flags_t flags;
+ unsigned long max_session_count;
+ unsigned long session_count;
+ unsigned long max_rw_session_count;
+ unsigned long rw_session_count;
+ unsigned long max_pin_len;
+ unsigned long min_pin_len;
+ unsigned long total_public_memory;
+ unsigned long free_public_memory;
+ unsigned long total_private_memory;
+ unsigned long free_private_memory;
+ struct ck_version hardware_version;
+ struct ck_version firmware_version;
+ unsigned char utc_time[16];
+};
+
+#define CKF_RNG (1UL << 0)
+#define CKF_WRITE_PROTECTED (1UL << 1)
+#define CKF_LOGIN_REQUIRED (1UL << 2)
+#define CKF_USER_PIN_INITIALIZED (1UL << 3)
+#define CKF_RESTORE_KEY_NOT_NEEDED (1UL << 5)
+#define CKF_CLOCK_ON_TOKEN (1UL << 6)
+#define CKF_PROTECTED_AUTHENTICATION_PATH (1UL << 8)
+#define CKF_DUAL_CRYPTO_OPERATIONS (1UL << 9)
+#define CKF_TOKEN_INITIALIZED (1UL << 10)
+#define CKF_SECONDARY_AUTHENTICATION (1UL << 11)
+#define CKF_USER_PIN_COUNT_LOW (1UL << 16)
+#define CKF_USER_PIN_FINAL_TRY (1UL << 17)
+#define CKF_USER_PIN_LOCKED (1UL << 18)
+#define CKF_USER_PIN_TO_BE_CHANGED (1UL << 19)
+#define CKF_SO_PIN_COUNT_LOW (1UL << 20)
+#define CKF_SO_PIN_FINAL_TRY (1UL << 21)
+#define CKF_SO_PIN_LOCKED (1UL << 22)
+#define CKF_SO_PIN_TO_BE_CHANGED (1UL << 23)
+
+#define CK_UNAVAILABLE_INFORMATION ((unsigned long)-1L)
+#define CK_EFFECTIVELY_INFINITE (0UL)
+
+typedef unsigned long ck_session_handle_t;
+
+#define CK_INVALID_HANDLE (0UL)
+
+typedef unsigned long ck_user_type_t;
+
+#define CKU_SO (0UL)
+#define CKU_USER (1UL)
+#define CKU_CONTEXT_SPECIFIC (2UL)
+
+typedef unsigned long ck_state_t;
+
+#define CKS_RO_PUBLIC_SESSION (0UL)
+#define CKS_RO_USER_FUNCTIONS (1UL)
+#define CKS_RW_PUBLIC_SESSION (2UL)
+#define CKS_RW_USER_FUNCTIONS (3UL)
+#define CKS_RW_SO_FUNCTIONS (4UL)
+
+struct ck_session_info {
+ ck_slot_id_t slot_id;
+ ck_state_t state;
+ ck_flags_t flags;
+ unsigned long device_error;
+};
+
+#define CKF_RW_SESSION (1UL << 1)
+#define CKF_SERIAL_SESSION (1UL << 2)
+
+typedef unsigned long ck_object_handle_t;
+
+typedef unsigned long ck_object_class_t;
+
+#define CKO_DATA (0UL)
+#define CKO_CERTIFICATE (1UL)
+#define CKO_PUBLIC_KEY (2UL)
+#define CKO_PRIVATE_KEY (3UL)
+#define CKO_SECRET_KEY (4UL)
+#define CKO_HW_FEATURE (5UL)
+#define CKO_DOMAIN_PARAMETERS (6UL)
+#define CKO_MECHANISM (7UL)
+#define CKO_OTP_KEY (8UL)
+#define CKO_VENDOR_DEFINED ((unsigned long)(1UL << 31))
+
+typedef unsigned long ck_hw_feature_type_t;
+
+#define CKH_MONOTONIC_COUNTER (1UL)
+#define CKH_CLOCK (2UL)
+#define CKH_USER_INTERFACE (3UL)
+#define CKH_VENDOR_DEFINED ((unsigned long)(1UL << 31))
+
+typedef unsigned long ck_key_type_t;
+
+#define CKK_RSA (0UL)
+#define CKK_DSA (1UL)
+#define CKK_DH (2UL)
+#define CKK_ECDSA (3UL)
+#define CKK_EC (3UL)
+#define CKK_X9_42_DH (4UL)
+#define CKK_KEA (5UL)
+#define CKK_GENERIC_SECRET (0x10UL)
+#define CKK_RC2 (0x11UL)
+#define CKK_RC4 (0x12UL)
+#define CKK_DES (0x13UL)
+#define CKK_DES2 (0x14UL)
+#define CKK_DES3 (0x15UL)
+#define CKK_CAST (0x16UL)
+#define CKK_CAST3 (0x17UL)
+#define CKK_CAST128 (0x18UL)
+#define CKK_RC5 (0x19UL)
+#define CKK_IDEA (0x1aUL)
+#define CKK_SKIPJACK (0x1bUL)
+#define CKK_BATON (0x1cUL)
+#define CKK_JUNIPER (0x1dUL)
+#define CKK_CDMF (0x1eUL)
+#define CKK_AES (0x1fUL)
+#define CKK_BLOWFISH (0x20UL)
+#define CKK_TWOFISH (0x21UL)
+#define CKK_SECURID (0x22UL)
+#define CKK_HOTP (0x23UL)
+#define CKK_ACTI (0x24UL)
+#define CKK_CAMELLIA (0x25UL)
+#define CKK_ARIA (0x26UL)
+#define CKK_MD5_HMAC (0x27UL)
+#define CKK_SHA_1_HMAC (0x28UL)
+#define CKK_RIPEMD128_HMAC (0x29UL)
+#define CKK_RIPEMD160_HMAC (0x2aUL)
+#define CKK_SHA256_HMAC (0x2bUL)
+#define CKK_SHA384_HMAC (0x2cUL)
+#define CKK_SHA512_HMAC (0x2dUL)
+#define CKK_SHA224_HMAC (0x2eUL)
+#define CKK_SEED (0x2fUL)
+#define CKK_GOSTR3410 (0x30UL)
+#define CKK_GOSTR3411 (0x31UL)
+#define CKK_GOST28147 (0x32UL)
+#define CKK_EC_EDWARDS (0x40UL)
+#define CKK_VENDOR_DEFINED ((unsigned long)(1UL << 31))
+
+typedef unsigned long ck_certificate_type_t;
+
+#define CKC_X_509 (0UL)
+#define CKC_X_509_ATTR_CERT (1UL)
+#define CKC_WTLS (2UL)
+#define CKC_VENDOR_DEFINED ((unsigned long)(1UL << 31))
+
+#define CKC_OPENPGP (CKC_VENDOR_DEFINED | 0x504750UL)
+
+typedef unsigned long ck_attribute_type_t;
+
+#define CKA_CLASS (0UL)
+#define CKA_TOKEN (1UL)
+#define CKA_PRIVATE (2UL)
+#define CKA_LABEL (3UL)
+#define CKA_APPLICATION (0x10UL)
+#define CKA_VALUE (0x11UL)
+#define CKA_OBJECT_ID (0x12UL)
+#define CKA_CERTIFICATE_TYPE (0x80UL)
+#define CKA_ISSUER (0x81UL)
+#define CKA_SERIAL_NUMBER (0x82UL)
+#define CKA_AC_ISSUER (0x83UL)
+#define CKA_OWNER (0x84UL)
+#define CKA_ATTR_TYPES (0x85UL)
+#define CKA_TRUSTED (0x86UL)
+#define CKA_CERTIFICATE_CATEGORY (0x87UL)
+#define CKA_JAVA_MIDP_SECURITY_DOMAIN (0x88UL)
+#define CKA_URL (0x89UL)
+#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY (0x8aUL)
+#define CKA_HASH_OF_ISSUER_PUBLIC_KEY (0x8bUL)
+#define CKA_NAME_HASH_ALGORITHM (0x8cUL)
+#define CKA_CHECK_VALUE (0x90UL)
+#define CKA_KEY_TYPE (0x100UL)
+#define CKA_SUBJECT (0x101UL)
+#define CKA_ID (0x102UL)
+#define CKA_SENSITIVE (0x103UL)
+#define CKA_ENCRYPT (0x104UL)
+#define CKA_DECRYPT (0x105UL)
+#define CKA_WRAP (0x106UL)
+#define CKA_UNWRAP (0x107UL)
+#define CKA_SIGN (0x108UL)
+#define CKA_SIGN_RECOVER (0x109UL)
+#define CKA_VERIFY (0x10aUL)
+#define CKA_VERIFY_RECOVER (0x10bUL)
+#define CKA_DERIVE (0x10cUL)
+#define CKA_START_DATE (0x110UL)
+#define CKA_END_DATE (0x111UL)
+#define CKA_MODULUS (0x120UL)
+#define CKA_MODULUS_BITS (0x121UL)
+#define CKA_PUBLIC_EXPONENT (0x122UL)
+#define CKA_PRIVATE_EXPONENT (0x123UL)
+#define CKA_PRIME_1 (0x124UL)
+#define CKA_PRIME_2 (0x125UL)
+#define CKA_EXPONENT_1 (0x126UL)
+#define CKA_EXPONENT_2 (0x127UL)
+#define CKA_COEFFICIENT (0x128UL)
+#define CKA_PUBLIC_KEY_INFO (0x129UL)
+#define CKA_PRIME (0x130UL)
+#define CKA_SUBPRIME (0x131UL)
+#define CKA_BASE (0x132UL)
+#define CKA_PRIME_BITS (0x133UL)
+#define CKA_SUB_PRIME_BITS (0x134UL)
+#define CKA_VALUE_BITS (0x160UL)
+#define CKA_VALUE_LEN (0x161UL)
+#define CKA_EXTRACTABLE (0x162UL)
+#define CKA_LOCAL (0x163UL)
+#define CKA_NEVER_EXTRACTABLE (0x164UL)
+#define CKA_ALWAYS_SENSITIVE (0x165UL)
+#define CKA_KEY_GEN_MECHANISM (0x166UL)
+#define CKA_MODIFIABLE (0x170UL)
+#define CKA_COPYABLE (0x171UL)
+#define CKA_DESTROYABLE (0x172UL)
+#define CKA_ECDSA_PARAMS (0x180UL)
+#define CKA_EC_PARAMS (0x180UL)
+#define CKA_EC_POINT (0x181UL)
+#define CKA_SECONDARY_AUTH (0x200UL)
+#define CKA_AUTH_PIN_FLAGS (0x201UL)
+#define CKA_ALWAYS_AUTHENTICATE (0x202UL)
+#define CKA_WRAP_WITH_TRUSTED (0x210UL)
+#define CKA_OTP_FORMAT (0x220UL)
+#define CKA_OTP_LENGTH (0x221UL)
+#define CKA_OTP_TIME_INTERVAL (0x222UL)
+#define CKA_OTP_USER_FRIENDLY_MODE (0x223UL)
+#define CKA_OTP_CHALLENGE_REQUIREMENT (0x224UL)
+#define CKA_OTP_TIME_REQUIREMENT (0x225UL)
+#define CKA_OTP_COUNTER_REQUIREMENT (0x226UL)
+#define CKA_OTP_PIN_REQUIREMENT (0x227UL)
+#define CKA_OTP_USER_IDENTIFIER (0x22AUL)
+#define CKA_OTP_SERVICE_IDENTIFIER (0x22BUL)
+#define CKA_OTP_SERVICE_LOGO (0x22CUL)
+#define CKA_OTP_SERVICE_LOGO_TYPE (0x22DUL)
+#define CKA_OTP_COUNTER (0x22EUL)
+#define CKA_OTP_TIME (0x22FUL)
+#define CKA_GOSTR3410_PARAMS (0x250UL)
+#define CKA_GOSTR3411_PARAMS (0x251UL)
+#define CKA_GOST28147_PARAMS (0x252UL)
+#define CKA_HW_FEATURE_TYPE (0x300UL)
+#define CKA_RESET_ON_INIT (0x301UL)
+#define CKA_HAS_RESET (0x302UL)
+#define CKA_PIXEL_X (0x400UL)
+#define CKA_PIXEL_Y (0x401UL)
+#define CKA_RESOLUTION (0x402UL)
+#define CKA_CHAR_ROWS (0x403UL)
+#define CKA_CHAR_COLUMNS (0x404UL)
+#define CKA_COLOR (0x405UL)
+#define CKA_BITS_PER_PIXEL (0x406UL)
+#define CKA_CHAR_SETS (0x480UL)
+#define CKA_ENCODING_METHODS (0x481UL)
+#define CKA_MIME_TYPES (0x482UL)
+#define CKA_MECHANISM_TYPE (0x500UL)
+#define CKA_REQUIRED_CMS_ATTRIBUTES (0x501UL)
+#define CKA_DEFAULT_CMS_ATTRIBUTES (0x502UL)
+#define CKA_SUPPORTED_CMS_ATTRIBUTES (0x503UL)
+#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x211UL)
+#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x212UL)
+#define CKA_DERIVE_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x213UL)
+#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x600UL)
+#define CKA_VENDOR_DEFINED ((unsigned long)(1UL << 31))
+
+struct ck_attribute {
+ ck_attribute_type_t type;
+ void *value;
+ unsigned long value_len;
+};
+
+struct ck_date {
+ unsigned char year[4];
+ unsigned char month[2];
+ unsigned char day[2];
+};
+
+typedef unsigned long ck_mechanism_type_t;
+
+#define CKM_RSA_PKCS_KEY_PAIR_GEN (0UL)
+#define CKM_RSA_PKCS (1UL)
+#define CKM_RSA_9796 (2UL)
+#define CKM_RSA_X_509 (3UL)
+#define CKM_MD2_RSA_PKCS (4UL)
+#define CKM_MD5_RSA_PKCS (5UL)
+#define CKM_SHA1_RSA_PKCS (6UL)
+#define CKM_RIPEMD128_RSA_PKCS (7UL)
+#define CKM_RIPEMD160_RSA_PKCS (8UL)
+#define CKM_RSA_PKCS_OAEP (9UL)
+#define CKM_RSA_X9_31_KEY_PAIR_GEN (0xaUL)
+#define CKM_RSA_X9_31 (0xbUL)
+#define CKM_SHA1_RSA_X9_31 (0xcUL)
+#define CKM_RSA_PKCS_PSS (0xdUL)
+#define CKM_SHA1_RSA_PKCS_PSS (0xeUL)
+#define CKM_DSA_KEY_PAIR_GEN (0x10UL)
+#define CKM_DSA (0x11UL)
+#define CKM_DSA_SHA1 (0x12UL)
+#define CKM_DSA_SHA224 (0x13UL)
+#define CKM_DSA_SHA256 (0x14UL)
+#define CKM_DSA_SHA384 (0x15UL)
+#define CKM_DSA_SHA512 (0x16UL)
+#define CKM_DH_PKCS_KEY_PAIR_GEN (0x20UL)
+#define CKM_DH_PKCS_DERIVE (0x21UL)
+#define CKM_X9_42_DH_KEY_PAIR_GEN (0x30UL)
+#define CKM_X9_42_DH_DERIVE (0x31UL)
+#define CKM_X9_42_DH_HYBRID_DERIVE (0x32UL)
+#define CKM_X9_42_MQV_DERIVE (0x33UL)
+#define CKM_SHA256_RSA_PKCS (0x40UL)
+#define CKM_SHA384_RSA_PKCS (0x41UL)
+#define CKM_SHA512_RSA_PKCS (0x42UL)
+#define CKM_SHA256_RSA_PKCS_PSS (0x43UL)
+#define CKM_SHA384_RSA_PKCS_PSS (0x44UL)
+#define CKM_SHA512_RSA_PKCS_PSS (0x45UL)
+#define CKM_SHA512_224 (0x48UL)
+#define CKM_SHA512_224_HMAC (0x49UL)
+#define CKM_SHA512_224_HMAC_GENERAL (0x4aUL)
+#define CKM_SHA512_224_KEY_DERIVATION (0x4bUL)
+#define CKM_SHA512_256 (0x4cUL)
+#define CKM_SHA512_256_HMAC (0x4dUL)
+#define CKM_SHA512_256_HMAC_GENERAL (0x4eUL)
+#define CKM_SHA512_256_KEY_DERIVATION (0x4fUL)
+#define CKM_SHA512_T (0x50UL)
+#define CKM_SHA512_T_HMAC (0x51UL)
+#define CKM_SHA512_T_HMAC_GENERAL (0x52UL)
+#define CKM_SHA512_T_KEY_DERIVATION (0x53UL)
+#define CKM_RC2_KEY_GEN (0x100UL)
+#define CKM_RC2_ECB (0x101UL)
+#define CKM_RC2_CBC (0x102UL)
+#define CKM_RC2_MAC (0x103UL)
+#define CKM_RC2_MAC_GENERAL (0x104UL)
+#define CKM_RC2_CBC_PAD (0x105UL)
+#define CKM_RC4_KEY_GEN (0x110UL)
+#define CKM_RC4 (0x111UL)
+#define CKM_DES_KEY_GEN (0x120UL)
+#define CKM_DES_ECB (0x121UL)
+#define CKM_DES_CBC (0x122UL)
+#define CKM_DES_MAC (0x123UL)
+#define CKM_DES_MAC_GENERAL (0x124UL)
+#define CKM_DES_CBC_PAD (0x125UL)
+#define CKM_DES2_KEY_GEN (0x130UL)
+#define CKM_DES3_KEY_GEN (0x131UL)
+#define CKM_DES3_ECB (0x132UL)
+#define CKM_DES3_CBC (0x133UL)
+#define CKM_DES3_MAC (0x134UL)
+#define CKM_DES3_MAC_GENERAL (0x135UL)
+#define CKM_DES3_CBC_PAD (0x136UL)
+#define CKM_DES3_CMAC_GENERAL (0x137UL)
+#define CKM_DES3_CMAC (0x138UL)
+#define CKM_CDMF_KEY_GEN (0x140UL)
+#define CKM_CDMF_ECB (0x141UL)
+#define CKM_CDMF_CBC (0x142UL)
+#define CKM_CDMF_MAC (0x143UL)
+#define CKM_CDMF_MAC_GENERAL (0x144UL)
+#define CKM_CDMF_CBC_PAD (0x145UL)
+#define CKM_DES_OFB64 (0x150UL)
+#define CKM_DES_OFB8 (0x151UL)
+#define CKM_DES_CFB64 (0x152UL)
+#define CKM_DES_CFB8 (0x153UL)
+#define CKM_MD2 (0x200UL)
+#define CKM_MD2_HMAC (0x201UL)
+#define CKM_MD2_HMAC_GENERAL (0x202UL)
+#define CKM_MD5 (0x210UL)
+#define CKM_MD5_HMAC (0x211UL)
+#define CKM_MD5_HMAC_GENERAL (0x212UL)
+#define CKM_SHA_1 (0x220UL)
+#define CKM_SHA_1_HMAC (0x221UL)
+#define CKM_SHA_1_HMAC_GENERAL (0x222UL)
+#define CKM_RIPEMD128 (0x230UL)
+#define CKM_RIPEMD128_HMAC (0x231UL)
+#define CKM_RIPEMD128_HMAC_GENERAL (0x232UL)
+#define CKM_RIPEMD160 (0x240UL)
+#define CKM_RIPEMD160_HMAC (0x241UL)
+#define CKM_RIPEMD160_HMAC_GENERAL (0x242UL)
+#define CKM_SHA256 (0x250UL)
+#define CKM_SHA256_HMAC (0x251UL)
+#define CKM_SHA256_HMAC_GENERAL (0x252UL)
+#define CKM_SHA384 (0x260UL)
+#define CKM_SHA384_HMAC (0x261UL)
+#define CKM_SHA384_HMAC_GENERAL (0x262UL)
+#define CKM_SHA512 (0x270UL)
+#define CKM_SHA512_HMAC (0x271UL)
+#define CKM_SHA512_HMAC_GENERAL (0x272UL)
+#define CKM_SECURID_KEY_GEN (0x280UL)
+#define CKM_SECURID (0x282UL)
+#define CKM_HOTP_KEY_GEN (0x290UL)
+#define CKM_HOTP (0x291UL)
+#define CKM_ACTI (0x2a0UL)
+#define CKM_ACTI_KEY_GEN (0x2a1UL)
+#define CKM_CAST_KEY_GEN (0x300UL)
+#define CKM_CAST_ECB (0x301UL)
+#define CKM_CAST_CBC (0x302UL)
+#define CKM_CAST_MAC (0x303UL)
+#define CKM_CAST_MAC_GENERAL (0x304UL)
+#define CKM_CAST_CBC_PAD (0x305UL)
+#define CKM_CAST3_KEY_GEN (0x310UL)
+#define CKM_CAST3_ECB (0x311UL)
+#define CKM_CAST3_CBC (0x312UL)
+#define CKM_CAST3_MAC (0x313UL)
+#define CKM_CAST3_MAC_GENERAL (0x314UL)
+#define CKM_CAST3_CBC_PAD (0x315UL)
+#define CKM_CAST5_KEY_GEN (0x320UL)
+#define CKM_CAST128_KEY_GEN (0x320UL)
+#define CKM_CAST5_ECB (0x321UL)
+#define CKM_CAST128_ECB (0x321UL)
+#define CKM_CAST5_CBC (0x322UL)
+#define CKM_CAST128_CBC (0x322UL)
+#define CKM_CAST5_MAC (0x323UL)
+#define CKM_CAST128_MAC (0x323UL)
+#define CKM_CAST5_MAC_GENERAL (0x324UL)
+#define CKM_CAST128_MAC_GENERAL (0x324UL)
+#define CKM_CAST5_CBC_PAD (0x325UL)
+#define CKM_CAST128_CBC_PAD (0x325UL)
+#define CKM_RC5_KEY_GEN (0x330UL)
+#define CKM_RC5_ECB (0x331UL)
+#define CKM_RC5_CBC (0x332UL)
+#define CKM_RC5_MAC (0x333UL)
+#define CKM_RC5_MAC_GENERAL (0x334UL)
+#define CKM_RC5_CBC_PAD (0x335UL)
+#define CKM_IDEA_KEY_GEN (0x340UL)
+#define CKM_IDEA_ECB (0x341UL)
+#define CKM_IDEA_CBC (0x342UL)
+#define CKM_IDEA_MAC (0x343UL)
+#define CKM_IDEA_MAC_GENERAL (0x344UL)
+#define CKM_IDEA_CBC_PAD (0x345UL)
+#define CKM_GENERIC_SECRET_KEY_GEN (0x350UL)
+#define CKM_CONCATENATE_BASE_AND_KEY (0x360UL)
+#define CKM_CONCATENATE_BASE_AND_DATA (0x362UL)
+#define CKM_CONCATENATE_DATA_AND_BASE (0x363UL)
+#define CKM_XOR_BASE_AND_DATA (0x364UL)
+#define CKM_EXTRACT_KEY_FROM_KEY (0x365UL)
+#define CKM_SSL3_PRE_MASTER_KEY_GEN (0x370UL)
+#define CKM_SSL3_MASTER_KEY_DERIVE (0x371UL)
+#define CKM_SSL3_KEY_AND_MAC_DERIVE (0x372UL)
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH (0x373UL)
+#define CKM_TLS_PRE_MASTER_KEY_GEN (0x374UL)
+#define CKM_TLS_MASTER_KEY_DERIVE (0x375UL)
+#define CKM_TLS_KEY_AND_MAC_DERIVE (0x376UL)
+#define CKM_TLS_MASTER_KEY_DERIVE_DH (0x377UL)
+#define CKM_TLS_PRF (0x378UL)
+#define CKM_SSL3_MD5_MAC (0x380UL)
+#define CKM_SSL3_SHA1_MAC (0x381UL)
+#define CKM_MD5_KEY_DERIVATION (0x390UL)
+#define CKM_MD2_KEY_DERIVATION (0x391UL)
+#define CKM_SHA1_KEY_DERIVATION (0x392UL)
+#define CKM_SHA256_KEY_DERIVATION (0x393UL)
+#define CKM_SHA384_KEY_DERIVATION (0x394UL)
+#define CKM_SHA512_KEY_DERIVATION (0x395UL)
+#define CKM_PBE_MD2_DES_CBC (0x3a0UL)
+#define CKM_PBE_MD5_DES_CBC (0x3a1UL)
+#define CKM_PBE_MD5_CAST_CBC (0x3a2UL)
+#define CKM_PBE_MD5_CAST3_CBC (0x3a3UL)
+#define CKM_PBE_MD5_CAST5_CBC (0x3a4UL)
+#define CKM_PBE_MD5_CAST128_CBC (0x3a4UL)
+#define CKM_PBE_SHA1_CAST5_CBC (0x3a5UL)
+#define CKM_PBE_SHA1_CAST128_CBC (0x3a5UL)
+#define CKM_PBE_SHA1_RC4_128 (0x3a6UL)
+#define CKM_PBE_SHA1_RC4_40 (0x3a7UL)
+#define CKM_PBE_SHA1_DES3_EDE_CBC (0x3a8UL)
+#define CKM_PBE_SHA1_DES2_EDE_CBC (0x3a9UL)
+#define CKM_PBE_SHA1_RC2_128_CBC (0x3aaUL)
+#define CKM_PBE_SHA1_RC2_40_CBC (0x3abUL)
+#define CKM_PKCS5_PBKD2 (0x3b0UL)
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC (0x3c0UL)
+#define CKM_WTLS_PRE_MASTER_KEY_GEN (0x3d0UL)
+#define CKM_WTLS_MASTER_KEY_DERIVE (0x3d1UL)
+#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC (0x3d2UL)
+#define CKM_WTLS_PRF (0x3d3UL)
+#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE (0x3d4UL)
+#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE (0x3d5UL)
+#define CKM_TLS10_MAC_SERVER (0x3d6UL)
+#define CKM_TLS10_MAC_CLIENT (0x3d7UL)
+#define CKM_TLS12_MAC (0x3d8UL)
+#define CKM_TLS12_KDF (0x3d9UL)
+#define CKM_TLS12_MASTER_KEY_DERIVE (0x3e0UL)
+#define CKM_TLS12_KEY_AND_MAC_DERIVE (0x3e1UL)
+#define CKM_TLS12_MASTER_KEY_DERIVE_DH (0x3e2UL)
+#define CKM_TLS12_KEY_SAFE_DERIVE (0x3e3UL)
+#define CKM_TLS_MAC (0x3e4UL)
+#define CKM_TLS_KDF (0x3e5UL)
+#define CKM_KEY_WRAP_LYNKS (0x400UL)
+#define CKM_KEY_WRAP_SET_OAEP (0x401UL)
+#define CKM_CMS_SIG (0x500UL)
+#define CKM_KIP_DERIVE (0x510UL)
+#define CKM_KIP_WRAP (0x511UL)
+#define CKM_KIP_MAC (0x512UL)
+#define CKM_ARIA_KEY_GEN (0x560UL)
+#define CKM_ARIA_ECB (0x561UL)
+#define CKM_ARIA_CBC (0x562UL)
+#define CKM_ARIA_MAC (0x563UL)
+#define CKM_ARIA_MAC_GENERAL (0x564UL)
+#define CKM_ARIA_CBC_PAD (0x565UL)
+#define CKM_ARIA_ECB_ENCRYPT_DATA (0x566UL)
+#define CKM_ARIA_CBC_ENCRYPT_DATA (0x567UL)
+#define CKM_SEED_KEY_GEN (0x650UL)
+#define CKM_SEED_ECB (0x651UL)
+#define CKM_SEED_CBC (0x652UL)
+#define CKM_SEED_MAC (0x653UL)
+#define CKM_SEED_MAC_GENERAL (0x654UL)
+#define CKM_SEED_CBC_PAD (0x655UL)
+#define CKM_SEED_ECB_ENCRYPT_DATA (0x656UL)
+#define CKM_SEED_CBC_ENCRYPT_DATA (0x657UL)
+#define CKM_SKIPJACK_KEY_GEN (0x1000UL)
+#define CKM_SKIPJACK_ECB64 (0x1001UL)
+#define CKM_SKIPJACK_CBC64 (0x1002UL)
+#define CKM_SKIPJACK_OFB64 (0x1003UL)
+#define CKM_SKIPJACK_CFB64 (0x1004UL)
+#define CKM_SKIPJACK_CFB32 (0x1005UL)
+#define CKM_SKIPJACK_CFB16 (0x1006UL)
+#define CKM_SKIPJACK_CFB8 (0x1007UL)
+#define CKM_SKIPJACK_WRAP (0x1008UL)
+#define CKM_SKIPJACK_PRIVATE_WRAP (0x1009UL)
+#define CKM_SKIPJACK_RELAYX (0x100aUL)
+#define CKM_KEA_KEY_PAIR_GEN (0x1010UL)
+#define CKM_KEA_KEY_DERIVE (0x1011UL)
+#define CKM_FORTEZZA_TIMESTAMP (0x1020UL)
+#define CKM_BATON_KEY_GEN (0x1030UL)
+#define CKM_BATON_ECB128 (0x1031UL)
+#define CKM_BATON_ECB96 (0x1032UL)
+#define CKM_BATON_CBC128 (0x1033UL)
+#define CKM_BATON_COUNTER (0x1034UL)
+#define CKM_BATON_SHUFFLE (0x1035UL)
+#define CKM_BATON_WRAP (0x1036UL)
+#define CKM_ECDSA_KEY_PAIR_GEN (0x1040UL)
+#define CKM_EC_KEY_PAIR_GEN (0x1040UL)
+#define CKM_ECDSA (0x1041UL)
+#define CKM_ECDSA_SHA1 (0x1042UL)
+#define CKM_ECDSA_SHA224 (0x1043UL)
+#define CKM_ECDSA_SHA256 (0x1044UL)
+#define CKM_ECDSA_SHA384 (0x1045UL)
+#define CKM_ECDSA_SHA512 (0x1046UL)
+#define CKM_ECDH1_DERIVE (0x1050UL)
+#define CKM_ECDH1_COFACTOR_DERIVE (0x1051UL)
+#define CKM_ECMQV_DERIVE (0x1052UL)
+#define CKM_ECDH_AES_KEY_WRAP (0x1053UL)
+#define CKM_RSA_AES_KEY_WRAP (0x1054UL)
+#define CKM_JUNIPER_KEY_GEN (0x1060UL)
+#define CKM_JUNIPER_ECB128 (0x1061UL)
+#define CKM_JUNIPER_CBC128 (0x1062UL)
+#define CKM_JUNIPER_COUNTER (0x1063UL)
+#define CKM_JUNIPER_SHUFFLE (0x1064UL)
+#define CKM_JUNIPER_WRAP (0x1065UL)
+#define CKM_FASTHASH (0x1070UL)
+#define CKM_AES_KEY_GEN (0x1080UL)
+#define CKM_AES_ECB (0x1081UL)
+#define CKM_AES_CBC (0x1082UL)
+#define CKM_AES_MAC (0x1083UL)
+#define CKM_AES_MAC_GENERAL (0x1084UL)
+#define CKM_AES_CBC_PAD (0x1085UL)
+#define CKM_AES_CTR (0x1086UL)
+#define CKM_AES_GCM (0x1087UL)
+#define CKM_AES_CCM (0x1088UL)
+#define CKM_AES_CTS (0x1089UL)
+#define CKM_AES_CMAC (0x108aUL)
+#define CKM_AES_CMAC_GENERAL (0x108bUL)
+#define CKM_AES_XCBC_MAC (0x108cUL)
+#define CKM_AES_XCBC_MAC_96 (0x108dUL)
+#define CKM_AES_GMAC (0x108eUL)
+#define CKM_BLOWFISH_KEY_GEN (0x1090UL)
+#define CKM_BLOWFISH_CBC (0x1091UL)
+#define CKM_TWOFISH_KEY_GEN (0x1092UL)
+#define CKM_TWOFISH_CBC (0x1093UL)
+#define CKM_BLOWFISH_CBC_PAD (0x1094UL)
+#define CKM_TWOFISH_CBC_PAD (0x1095UL)
+#define CKM_DES_ECB_ENCRYPT_DATA (0x1100UL)
+#define CKM_DES_CBC_ENCRYPT_DATA (0x1101UL)
+#define CKM_DES3_ECB_ENCRYPT_DATA (0x1102UL)
+#define CKM_DES3_CBC_ENCRYPT_DATA (0x1103UL)
+#define CKM_AES_ECB_ENCRYPT_DATA (0x1104UL)
+#define CKM_AES_CBC_ENCRYPT_DATA (0x1105UL)
+#define CKM_GOSTR3410_KEY_PAIR_GEN (0x1200UL)
+#define CKM_GOSTR3410 (0x1201UL)
+#define CKM_GOSTR3410_WITH_GOSTR3411 (0x1202UL)
+#define CKM_GOSTR3410_KEY_WRAP (0x1203UL)
+#define CKM_GOSTR3410_DERIVE (0x1204UL)
+#define CKM_GOSTR3411 (0x1210UL)
+#define CKM_GOSTR3411_HMAC (0x1211UL)
+#define CKM_GOST28147_KEY_GEN (0x1220UL)
+#define CKM_GOST28147_ECB (0x1221UL)
+#define CKM_GOST28147 (0x1222UL)
+#define CKM_GOST28147_MAC (0x1223UL)
+#define CKM_GOST28147_KEY_WRAP (0x1224UL)
+#define CKM_DSA_PARAMETER_GEN (0x2000UL)
+#define CKM_DH_PKCS_PARAMETER_GEN (0x2001UL)
+#define CKM_X9_42_DH_PARAMETER_GEN (0x2002UL)
+#define CKM_DSA_PROBABLISTIC_PARAMETER_GEN (0x2003UL)
+#define CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN (0x2004UL)
+#define CKM_AES_OFB (0x2104UL)
+#define CKM_AES_CFB64 (0x2105UL)
+#define CKM_AES_CFB8 (0x2106UL)
+#define CKM_AES_CFB128 (0x2107UL)
+#define CKM_AES_CFB1 (0x2108UL)
+
+#define CKM_VENDOR_DEFINED ((unsigned long)(1UL << 31))
+
+/* Amendments */
+#define CKM_SHA224 (0x255UL)
+#define CKM_SHA224_HMAC (0x256UL)
+#define CKM_SHA224_HMAC_GENERAL (0x257UL)
+#define CKM_SHA224_RSA_PKCS (0x46UL)
+#define CKM_SHA224_RSA_PKCS_PSS (0x47UL)
+#define CKM_SHA224_KEY_DERIVATION (0x396UL)
+
+#define CKM_CAMELLIA_KEY_GEN (0x550UL)
+#define CKM_CAMELLIA_ECB (0x551UL)
+#define CKM_CAMELLIA_CBC (0x552UL)
+#define CKM_CAMELLIA_MAC (0x553UL)
+#define CKM_CAMELLIA_MAC_GENERAL (0x554UL)
+#define CKM_CAMELLIA_CBC_PAD (0x555UL)
+#define CKM_CAMELLIA_ECB_ENCRYPT_DATA (0x556UL)
+#define CKM_CAMELLIA_CBC_ENCRYPT_DATA (0x557UL)
+#define CKM_CAMELLIA_CTR (0x558UL)
+
+#define CKM_AES_KEY_WRAP (0x2109UL)
+#define CKM_AES_KEY_WRAP_PAD (0x210aUL)
+
+#define CKM_RSA_PKCS_TPM_1_1 (0x4001UL)
+#define CKM_RSA_PKCS_OAEP_TPM_1_1 (0x4002UL)
+
+/* From version 3.0 */
+#define CKM_EC_EDWARDS_KEY_PAIR_GEN (0x1055UL)
+#define CKM_EDDSA (0x1057UL)
+
+/* Attribute and other constants related to OTP */
+#define CK_OTP_FORMAT_DECIMAL (0UL)
+#define CK_OTP_FORMAT_HEXADECIMAL (1UL)
+#define CK_OTP_FORMAT_ALPHANUMERIC (2UL)
+#define CK_OTP_FORMAT_BINARY (3UL)
+#define CK_OTP_PARAM_IGNORED (0UL)
+#define CK_OTP_PARAM_OPTIONAL (1UL)
+#define CK_OTP_PARAM_MANDATORY (2UL)
+
+#define CK_OTP_VALUE (0UL)
+#define CK_OTP_PIN (1UL)
+#define CK_OTP_CHALLENGE (2UL)
+#define CK_OTP_TIME (3UL)
+#define CK_OTP_COUNTER (4UL)
+#define CK_OTP_FLAGS (5UL)
+#define CK_OTP_OUTPUT_LENGTH (6UL)
+#define CK_OTP_FORMAT (7UL)
+
+/* OTP mechanism flags */
+#define CKF_NEXT_OTP (0x01UL)
+#define CKF_EXCLUDE_TIME (0x02UL)
+#define CKF_EXCLUDE_COUNTER (0x04UL)
+#define CKF_EXCLUDE_CHALLENGE (0x08UL)
+#define CKF_EXCLUDE_PIN (0x10UL)
+#define CKF_USER_FRIENDLY_OTP (0x20UL)
+
+#define CKN_OTP_CHANGED (0x01UL)
+
+struct ck_mechanism {
+ ck_mechanism_type_t mechanism;
+ void *parameter;
+ unsigned long parameter_len;
+};
+
+struct ck_mechanism_info {
+ unsigned long min_key_size;
+ unsigned long max_key_size;
+ ck_flags_t flags;
+};
+
+typedef unsigned long ck_param_type;
+
+typedef struct ck_otp_param {
+ ck_param_type type;
+ void *value;
+ unsigned long value_len;
+} ck_otp_param;
+
+typedef struct ck_otp_params {
+ struct ck_otp_param *params;
+ unsigned long count;
+} ck_otp_params;
+
+typedef struct ck_otp_signature_info {
+ struct ck_otp_param *params;
+ unsigned long count;
+} ck_otp_signature_info;
+
+#define CKG_MGF1_SHA1 0x00000001UL
+#define CKG_MGF1_SHA224 0x00000005UL
+#define CKG_MGF1_SHA256 0x00000002UL
+#define CKG_MGF1_SHA384 0x00000003UL
+#define CKG_MGF1_SHA512 0x00000004UL
+
+typedef unsigned long ck_rsa_pkcs_mgf_type_t;
+
+struct ck_rsa_pkcs_pss_params {
+ ck_mechanism_type_t hash_alg;
+ ck_rsa_pkcs_mgf_type_t mgf;
+ unsigned long s_len;
+};
+
+typedef unsigned long ck_rsa_pkcs_oaep_source_type_t;
+
+struct ck_rsa_pkcs_oaep_params {
+ ck_mechanism_type_t hash_alg;
+ ck_rsa_pkcs_mgf_type_t mgf;
+ ck_rsa_pkcs_oaep_source_type_t source;
+ void *source_data;
+ unsigned long source_data_len;
+};
+
+struct ck_aes_ctr_params {
+ unsigned long counter_bits;
+ unsigned char cb[16];
+};
+
+struct ck_gcm_params {
+ unsigned char *iv_ptr;
+ unsigned long iv_len;
+ unsigned long iv_bits;
+ unsigned char *aad_ptr;
+ unsigned long aad_len;
+ unsigned long tag_bits;
+};
+
+/* The following EC Key Derivation Functions are defined */
+#define CKD_NULL (0x01UL)
+#define CKD_SHA1_KDF (0x02UL)
+
+/* The following X9.42 DH key derivation functions are defined */
+#define CKD_SHA1_KDF_ASN1 (0x03UL)
+#define CKD_SHA1_KDF_CONCATENATE (0x04UL)
+#define CKD_SHA224_KDF (0x05UL)
+#define CKD_SHA256_KDF (0x06UL)
+#define CKD_SHA384_KDF (0x07UL)
+#define CKD_SHA512_KDF (0x08UL)
+#define CKD_CPDIVERSIFY_KDF (0x09UL)
+
+typedef unsigned long ck_ec_kdf_t;
+
+struct ck_ecdh1_derive_params {
+ ck_ec_kdf_t kdf;
+ unsigned long shared_data_len;
+ unsigned char *shared_data;
+ unsigned long public_data_len;
+ unsigned char *public_data;
+};
+
+struct ck_key_derivation_string_data {
+ unsigned char *string_data;
+ unsigned long string_data_len;
+};
+
+struct ck_des_cbc_encrypt_data_params {
+ unsigned char iv[8];
+ unsigned char *data_params;
+ unsigned long length;
+};
+
+struct ck_aes_cbc_encrypt_data_params {
+ unsigned char iv[16];
+ unsigned char *data_params;
+ unsigned long length;
+};
+
+#define CKF_HW (1UL << 0)
+#define CKF_ENCRYPT (1UL << 8)
+#define CKF_DECRYPT (1UL << 9)
+#define CKF_DIGEST (1UL << 10)
+#define CKF_SIGN (1UL << 11)
+#define CKF_SIGN_RECOVER (1UL << 12)
+#define CKF_VERIFY (1UL << 13)
+#define CKF_VERIFY_RECOVER (1UL << 14)
+#define CKF_GENERATE (1UL << 15)
+#define CKF_GENERATE_KEY_PAIR (1UL << 16)
+#define CKF_WRAP (1UL << 17)
+#define CKF_UNWRAP (1UL << 18)
+#define CKF_DERIVE (1UL << 19)
+#define CKF_EXTENSION ((unsigned long)(1UL << 31))
+
+#define CKF_EC_F_P (1UL << 20)
+#define CKF_EC_NAMEDCURVE (1UL << 23)
+#define CKF_EC_UNCOMPRESS (1UL << 24)
+#define CKF_EC_COMPRESS (1UL << 25)
+
+/* Flags for C_WaitForSlotEvent. */
+#define CKF_DONT_BLOCK (1UL)
+
+typedef unsigned long ck_rv_t;
+
+typedef ck_rv_t (*ck_notify_t)(ck_session_handle_t session,
+ ck_notification_t event, void *application);
+
+/* Forward reference. */
+struct ck_function_list;
+
+#define _CK_DECLARE_FUNCTION(name, args) \
+ typedef ck_rv_t(*CK_##name) args; \
+ ck_rv_t CK_SPEC name args
+
+_CK_DECLARE_FUNCTION(C_Initialize, (void *init_args));
+_CK_DECLARE_FUNCTION(C_Finalize, (void *reserved));
+_CK_DECLARE_FUNCTION(C_GetInfo, (struct ck_info * info));
+_CK_DECLARE_FUNCTION(C_GetFunctionList,
+ (struct ck_function_list * *function_list));
+
+_CK_DECLARE_FUNCTION(C_GetSlotList,
+ (unsigned char token_present, ck_slot_id_t *slot_list,
+ unsigned long *count));
+_CK_DECLARE_FUNCTION(C_GetSlotInfo,
+ (ck_slot_id_t slot_id, struct ck_slot_info *info));
+_CK_DECLARE_FUNCTION(C_GetTokenInfo,
+ (ck_slot_id_t slot_id, struct ck_token_info *info));
+_CK_DECLARE_FUNCTION(C_WaitForSlotEvent,
+ (ck_flags_t flags, ck_slot_id_t *slot, void *reserved));
+_CK_DECLARE_FUNCTION(C_GetMechanismList,
+ (ck_slot_id_t slot_id, ck_mechanism_type_t *mechanism_list,
+ unsigned long *count));
+_CK_DECLARE_FUNCTION(C_GetMechanismInfo,
+ (ck_slot_id_t slot_id, ck_mechanism_type_t type,
+ struct ck_mechanism_info *info));
+_CK_DECLARE_FUNCTION(C_InitToken,
+ (ck_slot_id_t slot_id, unsigned char *pin,
+ unsigned long pin_len, unsigned char *label));
+_CK_DECLARE_FUNCTION(C_InitPIN, (ck_session_handle_t session,
+ unsigned char *pin, unsigned long pin_len));
+_CK_DECLARE_FUNCTION(C_SetPIN, (ck_session_handle_t session,
+ unsigned char *old_pin, unsigned long old_len,
+ unsigned char *new_pin, unsigned long new_len));
+
+_CK_DECLARE_FUNCTION(C_OpenSession,
+ (ck_slot_id_t slot_id, ck_flags_t flags, void *application,
+ ck_notify_t notify, ck_session_handle_t *session));
+_CK_DECLARE_FUNCTION(C_CloseSession, (ck_session_handle_t session));
+_CK_DECLARE_FUNCTION(C_CloseAllSessions, (ck_slot_id_t slot_id));
+_CK_DECLARE_FUNCTION(C_GetSessionInfo, (ck_session_handle_t session,
+ struct ck_session_info *info));
+_CK_DECLARE_FUNCTION(C_GetOperationState, (ck_session_handle_t session,
+ unsigned char *operation_state,
+ unsigned long *operation_state_len));
+_CK_DECLARE_FUNCTION(C_SetOperationState,
+ (ck_session_handle_t session,
+ unsigned char *operation_state,
+ unsigned long operation_state_len,
+ ck_object_handle_t encryption_key,
+ ck_object_handle_t authentiation_key));
+_CK_DECLARE_FUNCTION(C_Login,
+ (ck_session_handle_t session, ck_user_type_t user_type,
+ unsigned char *pin, unsigned long pin_len));
+_CK_DECLARE_FUNCTION(C_Logout, (ck_session_handle_t session));
+
+_CK_DECLARE_FUNCTION(C_CreateObject,
+ (ck_session_handle_t session, struct ck_attribute *templ,
+ unsigned long count, ck_object_handle_t *object));
+_CK_DECLARE_FUNCTION(C_CopyObject,
+ (ck_session_handle_t session, ck_object_handle_t object,
+ struct ck_attribute *templ, unsigned long count,
+ ck_object_handle_t *new_object));
+_CK_DECLARE_FUNCTION(C_DestroyObject,
+ (ck_session_handle_t session, ck_object_handle_t object));
+_CK_DECLARE_FUNCTION(C_GetObjectSize,
+ (ck_session_handle_t session, ck_object_handle_t object,
+ unsigned long *size));
+_CK_DECLARE_FUNCTION(C_GetAttributeValue,
+ (ck_session_handle_t session, ck_object_handle_t object,
+ struct ck_attribute *templ, unsigned long count));
+_CK_DECLARE_FUNCTION(C_SetAttributeValue,
+ (ck_session_handle_t session, ck_object_handle_t object,
+ struct ck_attribute *templ, unsigned long count));
+_CK_DECLARE_FUNCTION(C_FindObjectsInit,
+ (ck_session_handle_t session, struct ck_attribute *templ,
+ unsigned long count));
+_CK_DECLARE_FUNCTION(C_FindObjects,
+ (ck_session_handle_t session, ck_object_handle_t *object,
+ unsigned long max_object_count,
+ unsigned long *object_count));
+_CK_DECLARE_FUNCTION(C_FindObjectsFinal, (ck_session_handle_t session));
+
+_CK_DECLARE_FUNCTION(C_EncryptInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism, ck_object_handle_t key));
+_CK_DECLARE_FUNCTION(C_Encrypt,
+ (ck_session_handle_t session, unsigned char *data,
+ unsigned long data_len, unsigned char *encrypted_data,
+ unsigned long *encrypted_data_len));
+_CK_DECLARE_FUNCTION(C_EncryptUpdate,
+ (ck_session_handle_t session, unsigned char *part,
+ unsigned long part_len, unsigned char *encrypted_part,
+ unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION(C_EncryptFinal, (ck_session_handle_t session,
+ unsigned char *last_encrypted_part,
+ unsigned long *last_encrypted_part_len));
+
+_CK_DECLARE_FUNCTION(C_DecryptInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism, ck_object_handle_t key));
+_CK_DECLARE_FUNCTION(C_Decrypt, (ck_session_handle_t session,
+ unsigned char *encrypted_data,
+ unsigned long encrypted_data_len,
+ unsigned char *data, unsigned long *data_len));
+_CK_DECLARE_FUNCTION(C_DecryptUpdate,
+ (ck_session_handle_t session,
+ unsigned char *encrypted_part,
+ unsigned long encrypted_part_len, unsigned char *part,
+ unsigned long *part_len));
+_CK_DECLARE_FUNCTION(C_DecryptFinal,
+ (ck_session_handle_t session, unsigned char *last_part,
+ unsigned long *last_part_len));
+
+_CK_DECLARE_FUNCTION(C_DigestInit, (ck_session_handle_t session,
+ struct ck_mechanism *mechanism));
+_CK_DECLARE_FUNCTION(C_Digest,
+ (ck_session_handle_t session, unsigned char *data,
+ unsigned long data_len, unsigned char *digest,
+ unsigned long *digest_len));
+_CK_DECLARE_FUNCTION(C_DigestUpdate,
+ (ck_session_handle_t session, unsigned char *part,
+ unsigned long part_len));
+_CK_DECLARE_FUNCTION(C_DigestKey,
+ (ck_session_handle_t session, ck_object_handle_t key));
+_CK_DECLARE_FUNCTION(C_DigestFinal,
+ (ck_session_handle_t session, unsigned char *digest,
+ unsigned long *digest_len));
+
+_CK_DECLARE_FUNCTION(C_SignInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism, ck_object_handle_t key));
+_CK_DECLARE_FUNCTION(C_Sign, (ck_session_handle_t session, unsigned char *data,
+ unsigned long data_len, unsigned char *signature,
+ unsigned long *signature_len));
+_CK_DECLARE_FUNCTION(C_SignUpdate,
+ (ck_session_handle_t session, unsigned char *part,
+ unsigned long part_len));
+_CK_DECLARE_FUNCTION(C_SignFinal,
+ (ck_session_handle_t session, unsigned char *signature,
+ unsigned long *signature_len));
+_CK_DECLARE_FUNCTION(C_SignRecoverInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism, ck_object_handle_t key));
+_CK_DECLARE_FUNCTION(C_SignRecover,
+ (ck_session_handle_t session, unsigned char *data,
+ unsigned long data_len, unsigned char *signature,
+ unsigned long *signature_len));
+
+_CK_DECLARE_FUNCTION(C_VerifyInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism, ck_object_handle_t key));
+_CK_DECLARE_FUNCTION(C_Verify,
+ (ck_session_handle_t session, unsigned char *data,
+ unsigned long data_len, unsigned char *signature,
+ unsigned long signature_len));
+_CK_DECLARE_FUNCTION(C_VerifyUpdate,
+ (ck_session_handle_t session, unsigned char *part,
+ unsigned long part_len));
+_CK_DECLARE_FUNCTION(C_VerifyFinal,
+ (ck_session_handle_t session, unsigned char *signature,
+ unsigned long signature_len));
+_CK_DECLARE_FUNCTION(C_VerifyRecoverInit,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism, ck_object_handle_t key));
+_CK_DECLARE_FUNCTION(C_VerifyRecover,
+ (ck_session_handle_t session, unsigned char *signature,
+ unsigned long signature_len, unsigned char *data,
+ unsigned long *data_len));
+
+_CK_DECLARE_FUNCTION(C_DigestEncryptUpdate,
+ (ck_session_handle_t session, unsigned char *part,
+ unsigned long part_len, unsigned char *encrypted_part,
+ unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION(C_DecryptDigestUpdate,
+ (ck_session_handle_t session,
+ unsigned char *encrypted_part,
+ unsigned long encrypted_part_len, unsigned char *part,
+ unsigned long *part_len));
+_CK_DECLARE_FUNCTION(C_SignEncryptUpdate,
+ (ck_session_handle_t session, unsigned char *part,
+ unsigned long part_len, unsigned char *encrypted_part,
+ unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION(C_DecryptVerifyUpdate,
+ (ck_session_handle_t session,
+ unsigned char *encrypted_part,
+ unsigned long encrypted_part_len, unsigned char *part,
+ unsigned long *part_len));
+
+_CK_DECLARE_FUNCTION(C_GenerateKey,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ struct ck_attribute *templ, unsigned long count,
+ ck_object_handle_t *key));
+_CK_DECLARE_FUNCTION(C_GenerateKeyPair,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ struct ck_attribute *public_key_template,
+ unsigned long public_key_attribute_count,
+ struct ck_attribute *private_key_template,
+ unsigned long private_key_attribute_count,
+ ck_object_handle_t *public_key,
+ ck_object_handle_t *private_key));
+_CK_DECLARE_FUNCTION(C_WrapKey,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t wrapping_key, ck_object_handle_t key,
+ unsigned char *wrapped_key,
+ unsigned long *wrapped_key_len));
+_CK_DECLARE_FUNCTION(C_UnwrapKey,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t unwrapping_key,
+ unsigned char *wrapped_key, unsigned long wrapped_key_len,
+ struct ck_attribute *templ, unsigned long attribute_count,
+ ck_object_handle_t *key));
+_CK_DECLARE_FUNCTION(C_DeriveKey,
+ (ck_session_handle_t session,
+ struct ck_mechanism *mechanism,
+ ck_object_handle_t base_key, struct ck_attribute *templ,
+ unsigned long attribute_count, ck_object_handle_t *key));
+
+_CK_DECLARE_FUNCTION(C_SeedRandom,
+ (ck_session_handle_t session, unsigned char *seed,
+ unsigned long seed_len));
+_CK_DECLARE_FUNCTION(C_GenerateRandom,
+ (ck_session_handle_t session, unsigned char *random_data,
+ unsigned long random_len));
+
+_CK_DECLARE_FUNCTION(C_GetFunctionStatus, (ck_session_handle_t session));
+_CK_DECLARE_FUNCTION(C_CancelFunction, (ck_session_handle_t session));
+
+struct ck_function_list {
+ struct ck_version version;
+ CK_C_Initialize C_Initialize;
+ CK_C_Finalize C_Finalize;
+ CK_C_GetInfo C_GetInfo;
+ CK_C_GetFunctionList C_GetFunctionList;
+ CK_C_GetSlotList C_GetSlotList;
+ CK_C_GetSlotInfo C_GetSlotInfo;
+ CK_C_GetTokenInfo C_GetTokenInfo;
+ CK_C_GetMechanismList C_GetMechanismList;
+ CK_C_GetMechanismInfo C_GetMechanismInfo;
+ CK_C_InitToken C_InitToken;
+ CK_C_InitPIN C_InitPIN;
+ CK_C_SetPIN C_SetPIN;
+ CK_C_OpenSession C_OpenSession;
+ CK_C_CloseSession C_CloseSession;
+ CK_C_CloseAllSessions C_CloseAllSessions;
+ CK_C_GetSessionInfo C_GetSessionInfo;
+ CK_C_GetOperationState C_GetOperationState;
+ CK_C_SetOperationState C_SetOperationState;
+ CK_C_Login C_Login;
+ CK_C_Logout C_Logout;
+ CK_C_CreateObject C_CreateObject;
+ CK_C_CopyObject C_CopyObject;
+ CK_C_DestroyObject C_DestroyObject;
+ CK_C_GetObjectSize C_GetObjectSize;
+ CK_C_GetAttributeValue C_GetAttributeValue;
+ CK_C_SetAttributeValue C_SetAttributeValue;
+ CK_C_FindObjectsInit C_FindObjectsInit;
+ CK_C_FindObjects C_FindObjects;
+ CK_C_FindObjectsFinal C_FindObjectsFinal;
+ CK_C_EncryptInit C_EncryptInit;
+ CK_C_Encrypt C_Encrypt;
+ CK_C_EncryptUpdate C_EncryptUpdate;
+ CK_C_EncryptFinal C_EncryptFinal;
+ CK_C_DecryptInit C_DecryptInit;
+ CK_C_Decrypt C_Decrypt;
+ CK_C_DecryptUpdate C_DecryptUpdate;
+ CK_C_DecryptFinal C_DecryptFinal;
+ CK_C_DigestInit C_DigestInit;
+ CK_C_Digest C_Digest;
+ CK_C_DigestUpdate C_DigestUpdate;
+ CK_C_DigestKey C_DigestKey;
+ CK_C_DigestFinal C_DigestFinal;
+ CK_C_SignInit C_SignInit;
+ CK_C_Sign C_Sign;
+ CK_C_SignUpdate C_SignUpdate;
+ CK_C_SignFinal C_SignFinal;
+ CK_C_SignRecoverInit C_SignRecoverInit;
+ CK_C_SignRecover C_SignRecover;
+ CK_C_VerifyInit C_VerifyInit;
+ CK_C_Verify C_Verify;
+ CK_C_VerifyUpdate C_VerifyUpdate;
+ CK_C_VerifyFinal C_VerifyFinal;
+ CK_C_VerifyRecoverInit C_VerifyRecoverInit;
+ CK_C_VerifyRecover C_VerifyRecover;
+ CK_C_DigestEncryptUpdate C_DigestEncryptUpdate;
+ CK_C_DecryptDigestUpdate C_DecryptDigestUpdate;
+ CK_C_SignEncryptUpdate C_SignEncryptUpdate;
+ CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate;
+ CK_C_GenerateKey C_GenerateKey;
+ CK_C_GenerateKeyPair C_GenerateKeyPair;
+ CK_C_WrapKey C_WrapKey;
+ CK_C_UnwrapKey C_UnwrapKey;
+ CK_C_DeriveKey C_DeriveKey;
+ CK_C_SeedRandom C_SeedRandom;
+ CK_C_GenerateRandom C_GenerateRandom;
+ CK_C_GetFunctionStatus C_GetFunctionStatus;
+ CK_C_CancelFunction C_CancelFunction;
+ CK_C_WaitForSlotEvent C_WaitForSlotEvent;
+};
+
+typedef ck_rv_t (*ck_createmutex_t)(void **mutex);
+typedef ck_rv_t (*ck_destroymutex_t)(void *mutex);
+typedef ck_rv_t (*ck_lockmutex_t)(void *mutex);
+typedef ck_rv_t (*ck_unlockmutex_t)(void *mutex);
+
+struct ck_c_initialize_args {
+ ck_createmutex_t create_mutex;
+ ck_destroymutex_t destroy_mutex;
+ ck_lockmutex_t lock_mutex;
+ ck_unlockmutex_t unlock_mutex;
+ ck_flags_t flags;
+ void *reserved;
+};
+
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS (1UL << 0)
+#define CKF_OS_LOCKING_OK (1UL << 1)
+
+#define CKR_OK (0UL)
+#define CKR_CANCEL (1UL)
+#define CKR_HOST_MEMORY (2UL)
+#define CKR_SLOT_ID_INVALID (3UL)
+#define CKR_GENERAL_ERROR (5UL)
+#define CKR_FUNCTION_FAILED (6UL)
+#define CKR_ARGUMENTS_BAD (7UL)
+#define CKR_NO_EVENT (8UL)
+#define CKR_NEED_TO_CREATE_THREADS (9UL)
+#define CKR_CANT_LOCK (0xaUL)
+#define CKR_ATTRIBUTE_READ_ONLY (0x10UL)
+#define CKR_ATTRIBUTE_SENSITIVE (0x11UL)
+#define CKR_ATTRIBUTE_TYPE_INVALID (0x12UL)
+#define CKR_ATTRIBUTE_VALUE_INVALID (0x13UL)
+#define CKR_ACTION_PROHIBITED (0x1BUL)
+#define CKR_DATA_INVALID (0x20UL)
+#define CKR_DATA_LEN_RANGE (0x21UL)
+#define CKR_DEVICE_ERROR (0x30UL)
+#define CKR_DEVICE_MEMORY (0x31UL)
+#define CKR_DEVICE_REMOVED (0x32UL)
+#define CKR_ENCRYPTED_DATA_INVALID (0x40UL)
+#define CKR_ENCRYPTED_DATA_LEN_RANGE (0x41UL)
+#define CKR_FUNCTION_CANCELED (0x50UL)
+#define CKR_FUNCTION_NOT_PARALLEL (0x51UL)
+#define CKR_FUNCTION_NOT_SUPPORTED (0x54UL)
+#define CKR_KEY_HANDLE_INVALID (0x60UL)
+#define CKR_KEY_SIZE_RANGE (0x62UL)
+#define CKR_KEY_TYPE_INCONSISTENT (0x63UL)
+#define CKR_KEY_NOT_NEEDED (0x64UL)
+#define CKR_KEY_CHANGED (0x65UL)
+#define CKR_KEY_NEEDED (0x66UL)
+#define CKR_KEY_INDIGESTIBLE (0x67UL)
+#define CKR_KEY_FUNCTION_NOT_PERMITTED (0x68UL)
+#define CKR_KEY_NOT_WRAPPABLE (0x69UL)
+#define CKR_KEY_UNEXTRACTABLE (0x6aUL)
+#define CKR_MECHANISM_INVALID (0x70UL)
+#define CKR_MECHANISM_PARAM_INVALID (0x71UL)
+#define CKR_OBJECT_HANDLE_INVALID (0x82UL)
+#define CKR_OPERATION_ACTIVE (0x90UL)
+#define CKR_OPERATION_NOT_INITIALIZED (0x91UL)
+#define CKR_PIN_INCORRECT (0xa0UL)
+#define CKR_PIN_INVALID (0xa1UL)
+#define CKR_PIN_LEN_RANGE (0xa2UL)
+#define CKR_PIN_EXPIRED (0xa3UL)
+#define CKR_PIN_LOCKED (0xa4UL)
+#define CKR_SESSION_CLOSED (0xb0UL)
+#define CKR_SESSION_COUNT (0xb1UL)
+#define CKR_SESSION_HANDLE_INVALID (0xb3UL)
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED (0xb4UL)
+#define CKR_SESSION_READ_ONLY (0xb5UL)
+#define CKR_SESSION_EXISTS (0xb6UL)
+#define CKR_SESSION_READ_ONLY_EXISTS (0xb7UL)
+#define CKR_SESSION_READ_WRITE_SO_EXISTS (0xb8UL)
+#define CKR_SIGNATURE_INVALID (0xc0UL)
+#define CKR_SIGNATURE_LEN_RANGE (0xc1UL)
+#define CKR_TEMPLATE_INCOMPLETE (0xd0UL)
+#define CKR_TEMPLATE_INCONSISTENT (0xd1UL)
+#define CKR_TOKEN_NOT_PRESENT (0xe0UL)
+#define CKR_TOKEN_NOT_RECOGNIZED (0xe1UL)
+#define CKR_TOKEN_WRITE_PROTECTED (0xe2UL)
+#define CKR_UNWRAPPING_KEY_HANDLE_INVALID (0xf0UL)
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE (0xf1UL)
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT (0xf2UL)
+#define CKR_USER_ALREADY_LOGGED_IN (0x100UL)
+#define CKR_USER_NOT_LOGGED_IN (0x101UL)
+#define CKR_USER_PIN_NOT_INITIALIZED (0x102UL)
+#define CKR_USER_TYPE_INVALID (0x103UL)
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN (0x104UL)
+#define CKR_USER_TOO_MANY_TYPES (0x105UL)
+#define CKR_WRAPPED_KEY_INVALID (0x110UL)
+#define CKR_WRAPPED_KEY_LEN_RANGE (0x112UL)
+#define CKR_WRAPPING_KEY_HANDLE_INVALID (0x113UL)
+#define CKR_WRAPPING_KEY_SIZE_RANGE (0x114UL)
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT (0x115UL)
+#define CKR_RANDOM_SEED_NOT_SUPPORTED (0x120UL)
+#define CKR_RANDOM_NO_RNG (0x121UL)
+#define CKR_DOMAIN_PARAMS_INVALID (0x130UL)
+#define CKR_BUFFER_TOO_SMALL (0x150UL)
+#define CKR_SAVED_STATE_INVALID (0x160UL)
+#define CKR_INFORMATION_SENSITIVE (0x170UL)
+#define CKR_STATE_UNSAVEABLE (0x180UL)
+#define CKR_CRYPTOKI_NOT_INITIALIZED (0x190UL)
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED (0x191UL)
+#define CKR_MUTEX_BAD (0x1a0UL)
+#define CKR_MUTEX_NOT_LOCKED (0x1a1UL)
+#define CKR_NEW_PIN_MODE (0x1b0UL)
+#define CKR_NEXT_OTP (0x1b1UL)
+#define CKR_EXCEEDED_MAX_ITERATIONS (0x1c0UL)
+#define CKR_FIPS_SELF_TEST_FAILED (0x1c1UL)
+#define CKR_LIBRARY_LOAD_FAILED (0x1c2UL)
+#define CKR_PIN_TOO_WEAK (0x1c3UL)
+#define CKR_PUBLIC_KEY_INVALID (0x1c4UL)
+#define CKR_FUNCTION_REJECTED (0x200UL)
+#define CKR_VENDOR_DEFINED ((unsigned long)(1UL << 31))
+
+#define CKZ_DATA_SPECIFIED (0x01UL)
+
+/* Compatibility layer. */
+
+#ifdef CRYPTOKI_COMPAT
+
+#undef CK_DEFINE_FUNCTION
+#define CK_DEFINE_FUNCTION(retval, name) retval CK_SPEC name
+
+/* For NULL. */
+#include <stddef.h>
+
+typedef unsigned char CK_BYTE;
+typedef unsigned char CK_CHAR;
+typedef unsigned char CK_UTF8CHAR;
+typedef unsigned char CK_BBOOL;
+typedef unsigned long int CK_ULONG;
+typedef long int CK_LONG;
+typedef CK_BYTE *CK_BYTE_PTR;
+typedef CK_CHAR *CK_CHAR_PTR;
+typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR;
+typedef CK_ULONG *CK_ULONG_PTR;
+typedef void *CK_VOID_PTR;
+typedef void **CK_VOID_PTR_PTR;
+#define CK_FALSE 0
+#define CK_TRUE 1
+#ifndef CK_DISABLE_TRUE_FALSE
+#ifndef FALSE
+#define FALSE 0
+#endif /* ifndef FALSE */
+#ifndef TRUE
+#define TRUE 1
+#endif /* ifndef TRUE */
+#endif /* ifndef CK_DISABLE_TRUE_FALSE */
+
+typedef struct ck_version CK_VERSION;
+typedef struct ck_version *CK_VERSION_PTR;
+
+typedef struct ck_info CK_INFO;
+typedef struct ck_info *CK_INFO_PTR;
+
+typedef ck_slot_id_t *CK_SLOT_ID_PTR;
+
+typedef struct ck_slot_info CK_SLOT_INFO;
+typedef struct ck_slot_info *CK_SLOT_INFO_PTR;
+
+typedef struct ck_token_info CK_TOKEN_INFO;
+typedef struct ck_token_info *CK_TOKEN_INFO_PTR;
+
+typedef ck_session_handle_t *CK_SESSION_HANDLE_PTR;
+
+typedef struct ck_session_info CK_SESSION_INFO;
+typedef struct ck_session_info *CK_SESSION_INFO_PTR;
+
+typedef ck_object_handle_t *CK_OBJECT_HANDLE_PTR;
+
+typedef ck_object_class_t *CK_OBJECT_CLASS_PTR;
+
+typedef struct ck_attribute CK_ATTRIBUTE;
+typedef struct ck_attribute *CK_ATTRIBUTE_PTR;
+
+typedef struct ck_date CK_DATE;
+typedef struct ck_date *CK_DATE_PTR;
+
+typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR;
+
+typedef struct ck_mechanism CK_MECHANISM;
+typedef struct ck_mechanism *CK_MECHANISM_PTR;
+
+typedef struct ck_mechanism_info CK_MECHANISM_INFO;
+typedef struct ck_mechanism_info *CK_MECHANISM_INFO_PTR;
+
+typedef struct ck_otp_mechanism_info CK_OTP_MECHANISM_INFO;
+typedef struct ck_otp_mechanism_info *CK_OTP_MECHANISM_INFO_PTR;
+
+typedef struct ck_function_list CK_FUNCTION_LIST;
+typedef struct ck_function_list *CK_FUNCTION_LIST_PTR;
+typedef struct ck_function_list **CK_FUNCTION_LIST_PTR_PTR;
+
+typedef struct ck_c_initialize_args CK_C_INITIALIZE_ARGS;
+typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR;
+
+typedef struct ck_rsa_pkcs_pss_params CK_RSA_PKCS_PSS_PARAMS;
+typedef struct ck_rsa_pkcs_pss_params *CK_RSA_PKCS_PSS_PARAMS_PTR;
+
+typedef struct ck_rsa_pkcs_oaep_params CK_RSA_PKCS_OAEP_PARAMS;
+typedef struct ck_rsa_pkcs_oaep_params *CK_RSA_PKCS_OAEP_PARAMS_PTR;
+
+typedef struct ck_aes_ctr_params CK_AES_CTR_PARAMS;
+typedef struct ck_aes_ctr_params *CK_AES_CTR_PARAMS_PTR;
+
+typedef struct ck_gcm_params CK_GCM_PARAMS;
+typedef struct ck_gcm_params *CK_GCM_PARAMS_PTR;
+
+typedef struct ck_ecdh1_derive_params CK_ECDH1_DERIVE_PARAMS;
+typedef struct ck_ecdh1_derive_params *CK_ECDH1_DERIVE_PARAMS_PTR;
+
+typedef struct ck_key_derivation_string_data CK_KEY_DERIVATION_STRING_DATA;
+typedef struct ck_key_derivation_string_data *CK_KEY_DERIVATION_STRING_DATA_PTR;
+
+typedef struct ck_des_cbc_encrypt_data_params CK_DES_CBC_ENCRYPT_DATA_PARAMS;
+typedef struct ck_des_cbc_encrypt_data_params
+ *CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+typedef struct ck_aes_cbc_encrypt_data_params CK_AES_CBC_ENCRYPT_DATA_PARAMS;
+typedef struct ck_aes_cbc_encrypt_data_params
+ *CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+
+#ifndef NULL_PTR
+#define NULL_PTR NULL
+#endif /* ifndef NULL_PTR */
+
+/* Delete the helper macros defined at the top of the file. */
+#undef ck_flags_t
+#undef ck_version
+
+#undef ck_info
+#undef cryptoki_version
+#undef manufacturer_id
+#undef library_description
+#undef library_version
+
+#undef ck_notification_t
+#undef ck_slot_id_t
+
+#undef ck_slot_info
+#undef slot_description
+#undef hardware_version
+#undef firmware_version
+
+#undef ck_token_info
+#undef serial_number
+#undef max_session_count
+#undef session_count
+#undef max_rw_session_count
+#undef rw_session_count
+#undef max_pin_len
+#undef min_pin_len
+#undef total_public_memory
+#undef free_public_memory
+#undef total_private_memory
+#undef free_private_memory
+#undef utc_time
+
+#undef ck_session_handle_t
+#undef ck_user_type_t
+#undef ck_state_t
+
+#undef ck_session_info
+#undef slot_id
+#undef device_error
+
+#undef ck_object_handle_t
+#undef ck_object_class_t
+#undef ck_hw_feature_type_t
+#undef ck_key_type_t
+#undef ck_certificate_type_t
+#undef ck_attribute_type_t
+
+#undef ck_attribute
+#undef value
+#undef value_len
+
+#undef params
+#undef count
+
+#undef ck_date
+
+#undef ck_mechanism_type_t
+
+#undef ck_mechanism
+#undef parameter
+#undef parameter_len
+
+#undef ck_mechanism_info
+
+#undef ck_param_type
+#undef ck_otp_param
+#undef ck_otp_params
+#undef ck_otp_signature_info
+
+#undef min_key_size
+#undef max_key_size
+
+#undef ck_rv_t
+#undef ck_notify_t
+
+#undef ck_function_list
+
+#undef ck_createmutex_t
+#undef ck_destroymutex_t
+#undef ck_lockmutex_t
+#undef ck_unlockmutex_t
+
+#undef ck_c_initialize_args
+#undef create_mutex
+#undef destroy_mutex
+#undef lock_mutex
+#undef unlock_mutex
+#undef reserved
+
+#endif /* CRYPTOKI_COMPAT */
+
+/* System dependencies. */
+#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32)
+#pragma pack(pop, cryptoki)
+#endif /* if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) */
+
+#if defined(__cplusplus)
+}
+#endif /* if defined(__cplusplus) */
+
+#endif /* PKCS11_H */