summaryrefslogtreecommitdiffstats
path: root/lib/isc/win32
diff options
context:
space:
mode:
Diffstat (limited to 'lib/isc/win32')
-rw-r--r--lib/isc/win32/DLLMain.c51
-rw-r--r--lib/isc/win32/Makefile.in34
-rw-r--r--lib/isc/win32/app.c481
-rw-r--r--lib/isc/win32/condition.c255
-rw-r--r--lib/isc/win32/dir.c307
-rw-r--r--lib/isc/win32/entropy.c299
-rw-r--r--lib/isc/win32/errno.c21
-rw-r--r--lib/isc/win32/errno2result.c118
-rw-r--r--lib/isc/win32/errno2result.h35
-rw-r--r--lib/isc/win32/file.c928
-rw-r--r--lib/isc/win32/fsaccess.c365
-rw-r--r--lib/isc/win32/include/Makefile.in17
-rw-r--r--lib/isc/win32/include/isc/Makefile.in30
-rw-r--r--lib/isc/win32/include/isc/atomic.h75
-rw-r--r--lib/isc/win32/include/isc/bind_registry.h43
-rw-r--r--lib/isc/win32/include/isc/bindevt.h84
-rw-r--r--lib/isc/win32/include/isc/condition.h60
-rw-r--r--lib/isc/win32/include/isc/dir.h73
-rw-r--r--lib/isc/win32/include/isc/ipv6.h120
-rw-r--r--lib/isc/win32/include/isc/keyboard.h42
-rw-r--r--lib/isc/win32/include/isc/mutex.h48
-rw-r--r--lib/isc/win32/include/isc/net.h431
-rw-r--r--lib/isc/win32/include/isc/netdb.h47
-rw-r--r--lib/isc/win32/include/isc/ntgroups.h28
-rw-r--r--lib/isc/win32/include/isc/ntpaths.h66
-rw-r--r--lib/isc/win32/include/isc/offset.h24
-rw-r--r--lib/isc/win32/include/isc/once.h36
-rw-r--r--lib/isc/win32/include/isc/platform.h.in157
-rw-r--r--lib/isc/win32/include/isc/stat.h57
-rw-r--r--lib/isc/win32/include/isc/stdtime.h55
-rw-r--r--lib/isc/win32/include/isc/strerror.h35
-rw-r--r--lib/isc/win32/include/isc/syslog.h38
-rw-r--r--lib/isc/win32/include/isc/thread.h98
-rw-r--r--lib/isc/win32/include/isc/time.h357
-rw-r--r--lib/isc/win32/include/isc/win32os.h40
-rw-r--r--lib/isc/win32/include/pkcs11/Makefile.in26
-rw-r--r--lib/isc/win32/include/pkcs11/cryptoki.h66
-rw-r--r--lib/isc/win32/interfaceiter.c543
-rw-r--r--lib/isc/win32/ipv6.c20
-rw-r--r--lib/isc/win32/keyboard.c82
-rw-r--r--lib/isc/win32/libgen.h19
-rw-r--r--lib/isc/win32/libisc.def.exclude42
-rw-r--r--lib/isc/win32/libisc.def.in836
-rw-r--r--lib/isc/win32/libisc.dsp.in949
-rw-r--r--lib/isc/win32/libisc.dsw29
-rw-r--r--lib/isc/win32/libisc.mak.in2398
-rw-r--r--lib/isc/win32/libisc.vcxproj.filters.in675
-rw-r--r--lib/isc/win32/libisc.vcxproj.in530
-rw-r--r--lib/isc/win32/libisc.vcxproj.user3
-rw-r--r--lib/isc/win32/meminfo.c26
-rw-r--r--lib/isc/win32/net.c341
-rw-r--r--lib/isc/win32/netdb.h182
-rw-r--r--lib/isc/win32/ntgroups.c177
-rw-r--r--lib/isc/win32/ntpaths.c157
-rw-r--r--lib/isc/win32/once.c44
-rw-r--r--lib/isc/win32/os.c38
-rw-r--r--lib/isc/win32/pk11_api.c675
-rw-r--r--lib/isc/win32/resource.c65
-rw-r--r--lib/isc/win32/socket.c4277
-rw-r--r--lib/isc/win32/stdio.c150
-rw-r--r--lib/isc/win32/stdtime.c30
-rw-r--r--lib/isc/win32/strerror.c452
-rw-r--r--lib/isc/win32/syslog.c174
-rw-r--r--lib/isc/win32/syslog.h69
-rw-r--r--lib/isc/win32/thread.c89
-rw-r--r--lib/isc/win32/time.c388
-rw-r--r--lib/isc/win32/unistd.h53
-rw-r--r--lib/isc/win32/version.c21
-rw-r--r--lib/isc/win32/win32os.c117
69 files changed, 18698 insertions, 0 deletions
diff --git a/lib/isc/win32/DLLMain.c b/lib/isc/win32/DLLMain.c
new file mode 100644
index 0000000..f14260e
--- /dev/null
+++ b/lib/isc/win32/DLLMain.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <windows.h>
+#include <stdio.h>
+
+/*
+ * Called when we enter the DLL
+ */
+__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL,
+ DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ /*
+ * The DLL is loading due to process
+ * initialization or a call to LoadLibrary.
+ */
+ case DLL_PROCESS_ATTACH:
+ break;
+
+ /* The attached process creates a new thread. */
+ case DLL_THREAD_ATTACH:
+ break;
+
+ /* The thread of the attached process terminates. */
+ case DLL_THREAD_DETACH:
+ break;
+
+ /*
+ * The DLL is unloading from a process due to
+ * process termination or a call to FreeLibrary.
+ */
+ case DLL_PROCESS_DETACH:
+ break;
+
+ default:
+ break;
+ }
+ return (TRUE);
+}
+
diff --git a/lib/isc/win32/Makefile.in b/lib/isc/win32/Makefile.in
new file mode 100644
index 0000000..19b46bd
--- /dev/null
+++ b/lib/isc/win32/Makefile.in
@@ -0,0 +1,34 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# 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 http://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@
+
+CINCLUDES = -I${srcdir}/.. \
+ -I./include \
+ -I${srcdir}/include \
+ -I${srcdir}/../include
+CDEFINES =
+CWARNINGS =
+
+# Alphabetically
+OBJS = condition.@O@ dir.@O@ errno.@O@ file.@O@ \
+ meminfo.@O@ fsaccess.@O@ \
+ once.@O@ stdtime.@O@ thread.@O@ time.@O@ @ISC_PK11_API_O@
+
+# Alphabetically
+SRCS = condition.c dir.c errno.c file.c \
+ meminfo.c once.c fsaccess.c \
+ stdtime.c thread.c time.c @ISC_PK11_API_C@
+
+SUBDIRS = include
+TARGETS = ${OBJS}
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/win32/app.c b/lib/isc/win32/app.c
new file mode 100644
index 0000000..35274a2
--- /dev/null
+++ b/lib/isc/win32/app.c
@@ -0,0 +1,481 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <process.h>
+
+#include <isc/app.h>
+#include <isc/condition.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/mutex.h>
+#include <isc/event.h>
+#include <isc/platform.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/util.h>
+#include <isc/thread.h>
+
+/*%
+ * For BIND9 internal applications built with threads, we use a single app
+ * context and let multiple worker, I/O, timer threads do actual jobs.
+ */
+
+static isc_thread_t blockedthread;
+
+/*%
+ * The following are intended for internal use (indicated by "isc__"
+ * prefix) but are not declared as static, allowing direct access from
+ * unit tests etc.
+ */
+isc_result_t isc__app_start(void);
+isc_result_t isc__app_ctxstart(isc_appctx_t *ctx);
+isc_result_t isc__app_onrun(isc_mem_t *mctx, isc_task_t *task,
+ isc_taskaction_t action, void *arg);
+isc_result_t isc__app_ctxrun(isc_appctx_t *ctx);
+isc_result_t isc__app_run(void);
+isc_result_t isc__app_ctxshutdown(isc_appctx_t *ctx);
+isc_result_t isc__app_shutdown(void);
+isc_result_t isc__app_reload(void);
+isc_result_t isc__app_ctxsuspend(isc_appctx_t *ctx);
+void isc__app_ctxfinish(isc_appctx_t *ctx);
+void isc__app_finish(void);
+void isc__app_block(void);
+void isc__app_unblock(void);
+isc_result_t isc__appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp);
+void isc__appctx_destroy(isc_appctx_t **ctxp);
+void isc__appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr);
+void isc__appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr);
+void isc__appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr);
+isc_result_t isc__app_ctxonrun(isc_appctx_t *ctx, isc_mem_t *mctx,
+ isc_task_t *task, isc_taskaction_t action,
+ void *arg);
+
+/*
+ * The application context of this module. This implementation actually
+ * doesn't use it. (This may change in the future).
+ */
+#define APPCTX_MAGIC ISC_MAGIC('A', 'p', 'c', 'x')
+#define VALID_APPCTX(c) ISC_MAGIC_VALID(c, APPCTX_MAGIC)
+
+/* Events to wait for */
+
+#define NUM_EVENTS 2
+
+enum {
+ RELOAD_EVENT,
+ SHUTDOWN_EVENT
+};
+
+typedef struct isc__appctx {
+ isc_appctx_t common;
+ isc_mem_t *mctx;
+ isc_eventlist_t on_run;
+ isc_mutex_t lock;
+ bool shutdown_requested;
+ bool running;
+ /*
+ * We assume that 'want_shutdown' can be read and written atomically.
+ */
+ bool want_shutdown;
+ /*
+ * We assume that 'want_reload' can be read and written atomically.
+ */
+ bool want_reload;
+
+ bool blocked;
+
+ HANDLE hEvents[NUM_EVENTS];
+
+ isc_taskmgr_t *taskmgr;
+ isc_socketmgr_t *socketmgr;
+ isc_timermgr_t *timermgr;
+} isc__appctx_t;
+
+static isc__appctx_t isc_g_appctx;
+
+static struct {
+ isc_appmethods_t methods;
+
+ /*%
+ * The following are defined just for avoiding unused static functions.
+ */
+ void *run, *shutdown, *start, *reload, *finish, *block, *unblock;
+} appmethods = {
+ {
+ isc__appctx_destroy,
+ isc__app_ctxstart,
+ isc__app_ctxrun,
+ isc__app_ctxsuspend,
+ isc__app_ctxshutdown,
+ isc__app_ctxfinish,
+ isc__appctx_settaskmgr,
+ isc__appctx_setsocketmgr,
+ isc__appctx_settimermgr,
+ isc__app_ctxonrun
+ },
+ (void *)isc__app_run,
+ (void *)isc__app_shutdown,
+ (void *)isc__app_start,
+ (void *)isc__app_reload,
+ (void *)isc__app_finish,
+ (void *)isc__app_block,
+ (void *)isc__app_unblock
+};
+
+/*
+ * We need to remember which thread is the main thread...
+ */
+static isc_thread_t main_thread;
+
+isc_result_t
+isc__app_ctxstart(isc_appctx_t *ctx0) {
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+ isc_result_t result;
+
+ REQUIRE(VALID_APPCTX(ctx));
+
+ /*
+ * Start an ISC library application.
+ */
+
+ main_thread = GetCurrentThread();
+
+ result = isc_mutex_init(&ctx->lock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ ctx->shutdown_requested = false;
+ ctx->running = false;
+ ctx->want_shutdown = false;
+ ctx->want_reload = false;
+ ctx->blocked = false;
+
+ /* Create the reload event in a non-signaled state */
+ ctx->hEvents[RELOAD_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ /* Create the shutdown event in a non-signaled state */
+ ctx->hEvents[SHUTDOWN_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ ISC_LIST_INIT(ctx->on_run);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__app_start(void) {
+ isc_g_appctx.common.impmagic = APPCTX_MAGIC;
+ isc_g_appctx.common.magic = ISCAPI_APPCTX_MAGIC;
+ isc_g_appctx.common.methods = &appmethods.methods;
+ isc_g_appctx.mctx = NULL;
+ /* The remaining members will be initialized in ctxstart() */
+
+ return (isc__app_ctxstart((isc_appctx_t *)&isc_g_appctx));
+}
+
+isc_result_t
+isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
+ void *arg)
+{
+ return (isc__app_ctxonrun((isc_appctx_t *)&isc_g_appctx, mctx,
+ task, action, arg));
+}
+
+isc_result_t
+isc__app_ctxonrun(isc_appctx_t *ctx0, isc_mem_t *mctx, isc_task_t *task,
+ isc_taskaction_t action, void *arg)
+{
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+ isc_event_t *event;
+ isc_task_t *cloned_task = NULL;
+ isc_result_t result;
+
+ LOCK(&ctx->lock);
+
+ if (ctx->running) {
+ result = ISC_R_ALREADYRUNNING;
+ goto unlock;
+ }
+
+ /*
+ * Note that we store the task to which we're going to send the event
+ * in the event's "sender" field.
+ */
+ isc_task_attach(task, &cloned_task);
+ event = isc_event_allocate(mctx, cloned_task, ISC_APPEVENT_SHUTDOWN,
+ action, arg, sizeof(*event));
+ if (event == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto unlock;
+ }
+
+ ISC_LINK_INIT(event, ev_link);
+ ISC_LIST_APPEND(ctx->on_run, event, ev_link);
+
+ result = ISC_R_SUCCESS;
+
+ unlock:
+ UNLOCK(&ctx->lock);
+
+ return (result);
+}
+
+isc_result_t
+isc__app_ctxrun(isc_appctx_t *ctx0) {
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+ isc_event_t *event, *next_event;
+ isc_task_t *task;
+ HANDLE *pHandles = NULL;
+ DWORD dwWaitResult;
+
+ REQUIRE(VALID_APPCTX(ctx));
+
+ REQUIRE(main_thread == GetCurrentThread());
+
+ LOCK(&ctx->lock);
+
+ if (!ctx->running) {
+ ctx->running = true;
+
+ /*
+ * Post any on-run events (in FIFO order).
+ */
+ for (event = ISC_LIST_HEAD(ctx->on_run);
+ event != NULL;
+ event = next_event) {
+ next_event = ISC_LIST_NEXT(event, ev_link);
+ ISC_LIST_UNLINK(ctx->on_run, event, ev_link);
+ task = event->ev_sender;
+ event->ev_sender = NULL;
+ isc_task_sendanddetach(&task, &event);
+ }
+
+ }
+
+ UNLOCK(&ctx->lock);
+
+ /*
+ * There is no danger if isc_app_shutdown() is called before we wait
+ * for events.
+ */
+
+ while (!ctx->want_shutdown) {
+ dwWaitResult = WaitForMultipleObjects(NUM_EVENTS, ctx->hEvents,
+ FALSE, INFINITE);
+
+ /* See why we returned */
+
+ if (WaitSucceeded(dwWaitResult, NUM_EVENTS)) {
+ /*
+ * The return was due to one of the events
+ * being signaled
+ */
+ switch (WaitSucceededIndex(dwWaitResult)) {
+ case RELOAD_EVENT:
+ ctx->want_reload = true;
+ break;
+
+ case SHUTDOWN_EVENT:
+ ctx->want_shutdown = true;
+ break;
+ }
+ }
+
+ if (ctx->want_reload) {
+ ctx->want_reload = false;
+ return (ISC_R_RELOAD);
+ }
+
+ if (ctx->want_shutdown && ctx->blocked)
+ exit(-1);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__app_run(void) {
+ return (isc__app_ctxrun((isc_appctx_t *)&isc_g_appctx));
+}
+
+isc_result_t
+isc__app_ctxshutdown(isc_appctx_t *ctx0) {
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+ bool want_kill = true;
+
+ REQUIRE(VALID_APPCTX(ctx));
+
+ LOCK(&ctx->lock);
+
+ REQUIRE(ctx->running);
+
+ if (ctx->shutdown_requested)
+ want_kill = false; /* We're only signaling once */
+ else
+ ctx->shutdown_requested = true;
+
+ UNLOCK(&ctx->lock);
+
+ if (want_kill)
+ SetEvent(ctx->hEvents[SHUTDOWN_EVENT]);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__app_shutdown(void) {
+ return (isc__app_ctxshutdown((isc_appctx_t *)&isc_g_appctx));
+}
+
+isc_result_t
+isc__app_ctxsuspend(isc_appctx_t *ctx0) {
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+ bool want_kill = true;
+
+ REQUIRE(VALID_APPCTX(ctx));
+
+ LOCK(&ctx->lock);
+
+ REQUIRE(ctx->running);
+
+ /*
+ * Don't send the reload signal if we're shutting down.
+ */
+ if (ctx->shutdown_requested)
+ want_kill = false;
+
+ UNLOCK(&ctx->lock);
+
+ if (want_kill)
+ SetEvent(ctx->hEvents[RELOAD_EVENT]);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__app_reload(void) {
+ return (isc__app_ctxsuspend((isc_appctx_t *)&isc_g_appctx));
+}
+
+void
+isc__app_ctxfinish(isc_appctx_t *ctx0) {
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+
+ REQUIRE(VALID_APPCTX(ctx));
+
+ DESTROYLOCK(&ctx->lock);
+}
+
+void
+isc__app_finish(void) {
+ isc__app_ctxfinish((isc_appctx_t *)&isc_g_appctx);
+}
+
+void
+isc__app_block(void) {
+ REQUIRE(isc_g_appctx.running);
+ REQUIRE(!isc_g_appctx.blocked);
+
+ isc_g_appctx.blocked = true;
+ blockedthread = GetCurrentThread();
+}
+
+void
+isc__app_unblock(void) {
+ REQUIRE(isc_g_appctx.running);
+ REQUIRE(isc_g_appctx.blocked);
+
+ isc_g_appctx.blocked = false;
+ REQUIRE(blockedthread == GetCurrentThread());
+}
+
+isc_result_t
+isc__appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) {
+ isc__appctx_t *ctx;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(ctxp != NULL && *ctxp == NULL);
+
+ ctx = isc_mem_get(mctx, sizeof(*ctx));
+ if (ctx == NULL)
+ return (ISC_R_NOMEMORY);
+
+ ctx->common.impmagic = APPCTX_MAGIC;
+ ctx->common.magic = ISCAPI_APPCTX_MAGIC;
+ ctx->common.methods = &appmethods.methods;
+
+ ctx->mctx = NULL;
+ isc_mem_attach(mctx, &ctx->mctx);
+
+ ctx->taskmgr = NULL;
+ ctx->socketmgr = NULL;
+ ctx->timermgr = NULL;
+
+ *ctxp = (isc_appctx_t *)ctx;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc__appctx_destroy(isc_appctx_t **ctxp) {
+ isc__appctx_t *ctx;
+
+ REQUIRE(ctxp != NULL);
+ ctx = (isc__appctx_t *)*ctxp;
+ REQUIRE(VALID_APPCTX(ctx));
+
+ isc_mem_putanddetach(&ctx->mctx, ctx, sizeof(*ctx));
+
+ *ctxp = NULL;
+}
+
+void
+isc__appctx_settaskmgr(isc_appctx_t *ctx0, isc_taskmgr_t *taskmgr) {
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+
+ REQUIRE(VALID_APPCTX(ctx));
+
+ ctx->taskmgr = taskmgr;
+}
+
+void
+isc__appctx_setsocketmgr(isc_appctx_t *ctx0, isc_socketmgr_t *socketmgr) {
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+
+ REQUIRE(VALID_APPCTX(ctx));
+
+ ctx->socketmgr = socketmgr;
+}
+
+void
+isc__appctx_settimermgr(isc_appctx_t *ctx0, isc_timermgr_t *timermgr) {
+ isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
+
+ REQUIRE(VALID_APPCTX(ctx));
+
+ ctx->timermgr = timermgr;
+}
+
+isc_result_t
+isc__app_register(void) {
+ return (isc_app_register(isc__appctx_create));
+}
+
+#include "../app_api.c"
diff --git a/lib/isc/win32/condition.c b/lib/isc/win32/condition.c
new file mode 100644
index 0000000..7887508
--- /dev/null
+++ b/lib/isc/win32/condition.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <isc/condition.h>
+#include <isc/assertions.h>
+#include <isc/util.h>
+#include <isc/thread.h>
+#include <isc/time.h>
+
+#define LSIGNAL 0
+#define LBROADCAST 1
+
+isc_result_t
+isc_condition_init(isc_condition_t *cond) {
+ HANDLE h;
+
+ REQUIRE(cond != NULL);
+
+ cond->waiters = 0;
+ /*
+ * This handle is shared across all threads
+ */
+ h = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (h == NULL) {
+ /* XXX */
+ return (ISC_R_UNEXPECTED);
+ }
+ cond->events[LSIGNAL] = h;
+
+ /*
+ * The threadlist will hold the actual events needed
+ * for the wait condition
+ */
+ ISC_LIST_INIT(cond->threadlist);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Add the thread to the threadlist along with the required events
+ */
+static isc_result_t
+register_thread(unsigned long thrd, isc_condition_t *gblcond,
+ isc_condition_thread_t **localcond)
+{
+ HANDLE hc;
+ isc_condition_thread_t *newthread;
+
+ REQUIRE(localcond != NULL && *localcond == NULL);
+
+ newthread = malloc(sizeof(isc_condition_thread_t));
+ if (newthread == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /*
+ * Create the thread-specific handle
+ */
+ hc = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (hc == NULL) {
+ free(newthread);
+ return (ISC_R_UNEXPECTED);
+ }
+
+ /*
+ * Add the thread ID and handles to list of threads for broadcast
+ */
+ newthread->handle[LSIGNAL] = gblcond->events[LSIGNAL];
+ newthread->handle[LBROADCAST] = hc;
+ newthread->th = thrd;
+
+ /*
+ * The thread is holding the manager lock so this is safe
+ */
+ ISC_LINK_INIT(newthread, link);
+ ISC_LIST_APPEND(gblcond->threadlist, newthread, link);
+ *localcond = newthread;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+find_thread_condition(unsigned long thrd, isc_condition_t *cond,
+ isc_condition_thread_t **threadcondp)
+{
+ isc_condition_thread_t *threadcond;
+
+ REQUIRE(threadcondp != NULL && *threadcondp == NULL);
+
+ /*
+ * Look for the thread ID.
+ */
+ for (threadcond = ISC_LIST_HEAD(cond->threadlist);
+ threadcond != NULL;
+ threadcond = ISC_LIST_NEXT(threadcond, link)) {
+
+ if (threadcond->th == thrd) {
+ *threadcondp = threadcond;
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ /*
+ * Not found, so add it.
+ */
+ return (register_thread(thrd, cond, threadcondp));
+}
+
+isc_result_t
+isc_condition_signal(isc_condition_t *cond) {
+
+ /*
+ * Unlike pthreads, the caller MUST hold the lock associated with
+ * the condition variable when calling us.
+ */
+ REQUIRE(cond != NULL);
+
+ if (!SetEvent(cond->events[LSIGNAL])) {
+ /* XXX */
+ return (ISC_R_UNEXPECTED);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_condition_broadcast(isc_condition_t *cond) {
+
+ isc_condition_thread_t *threadcond;
+ bool failed = false;
+
+ /*
+ * Unlike pthreads, the caller MUST hold the lock associated with
+ * the condition variable when calling us.
+ */
+ REQUIRE(cond != NULL);
+
+ /*
+ * Notify every thread registered for this
+ */
+ for (threadcond = ISC_LIST_HEAD(cond->threadlist);
+ threadcond != NULL;
+ threadcond = ISC_LIST_NEXT(threadcond, link)) {
+
+ if (!SetEvent(threadcond->handle[LBROADCAST]))
+ failed = true;
+ }
+
+ if (failed)
+ return (ISC_R_UNEXPECTED);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_condition_destroy(isc_condition_t *cond) {
+
+ isc_condition_thread_t *next, *threadcond;
+
+ REQUIRE(cond != NULL);
+ REQUIRE(cond->waiters == 0);
+
+ (void)CloseHandle(cond->events[LSIGNAL]);
+
+ /*
+ * Delete the threadlist
+ */
+ threadcond = ISC_LIST_HEAD(cond->threadlist);
+
+ while (threadcond != NULL) {
+ next = ISC_LIST_NEXT(threadcond, link);
+ DEQUEUE(cond->threadlist, threadcond, link);
+ (void) CloseHandle(threadcond->handle[LBROADCAST]);
+ free(threadcond);
+ threadcond = next;
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * This is always called when the mutex (lock) is held, but because
+ * we are waiting we need to release it and reacquire it as soon as the wait
+ * is over. This allows other threads to make use of the object guarded
+ * by the mutex but it should never try to delete it as long as the
+ * number of waiters > 0. Always reacquire the mutex regardless of the
+ * result of the wait. Note that EnterCriticalSection will wait to acquire
+ * the mutex.
+ */
+static isc_result_t
+wait(isc_condition_t *cond, isc_mutex_t *mutex, DWORD milliseconds) {
+ DWORD result;
+ isc_result_t tresult;
+ isc_condition_thread_t *threadcond = NULL;
+
+ /*
+ * Get the thread events needed for the wait
+ */
+ tresult = find_thread_condition(isc_thread_self(), cond, &threadcond);
+ if (tresult != ISC_R_SUCCESS)
+ return (tresult);
+
+ cond->waiters++;
+ LeaveCriticalSection(mutex);
+ result = WaitForMultipleObjects(2, threadcond->handle, FALSE,
+ milliseconds);
+ EnterCriticalSection(mutex);
+ cond->waiters--;
+ if (result == WAIT_FAILED) {
+ /* XXX */
+ return (ISC_R_UNEXPECTED);
+ }
+ if (result == WAIT_TIMEOUT)
+ return (ISC_R_TIMEDOUT);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_condition_wait(isc_condition_t *cond, isc_mutex_t *mutex) {
+ return (wait(cond, mutex, INFINITE));
+}
+
+isc_result_t
+isc_condition_waituntil(isc_condition_t *cond, isc_mutex_t *mutex,
+ isc_time_t *t) {
+ DWORD milliseconds;
+ uint64_t microseconds;
+ isc_time_t now;
+
+ if (isc_time_now(&now) != ISC_R_SUCCESS) {
+ /* XXX */
+ return (ISC_R_UNEXPECTED);
+ }
+
+ microseconds = isc_time_microdiff(t, &now);
+ if (microseconds > 0xFFFFFFFFi64 * 1000)
+ milliseconds = 0xFFFFFFFF;
+ else
+ milliseconds = (DWORD)(microseconds / 1000);
+
+ return (wait(cond, mutex, milliseconds));
+}
diff --git a/lib/isc/win32/dir.c b/lib/isc/win32/dir.c
new file mode 100644
index 0000000..5db2c23
--- /dev/null
+++ b/lib/isc/win32/dir.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <direct.h>
+#include <process.h>
+#include <io.h>
+
+#include <sys/stat.h>
+
+#include <isc/assertions.h>
+#include <isc/dir.h>
+#include <isc/magic.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include "errno2result.h"
+
+#define ISC_DIR_MAGIC ISC_MAGIC('D', 'I', 'R', '*')
+#define VALID_DIR(dir) ISC_MAGIC_VALID(dir, ISC_DIR_MAGIC)
+
+static isc_result_t
+start_directory(isc_dir_t *p);
+
+void
+isc_dir_init(isc_dir_t *dir) {
+ REQUIRE(dir != NULL);
+
+ dir->dirname[0] = '\0';
+
+ dir->entry.name[0] = '\0';
+ dir->entry.length = 0;
+ memset(&(dir->entry.find_data), 0, sizeof(dir->entry.find_data));
+
+ dir->entry_filled = false;
+ dir->search_handle = INVALID_HANDLE_VALUE;
+
+ dir->magic = ISC_DIR_MAGIC;
+}
+
+/*
+ * Allocate workspace and open directory stream. If either one fails,
+ * NULL will be returned.
+ */
+isc_result_t
+isc_dir_open(isc_dir_t *dir, const char *dirname) {
+ char *p;
+ isc_result_t result;
+
+ REQUIRE(dirname != NULL);
+ REQUIRE(VALID_DIR(dir) && dir->search_handle == INVALID_HANDLE_VALUE);
+
+ /*
+ * Copy directory name. Need to have enough space for the name,
+ * a possible path separator, the wildcard, and the final NUL.
+ */
+ if (strlen(dirname) + 3 > sizeof(dir->dirname))
+ /* XXXDCL ? */
+ return (ISC_R_NOSPACE);
+ strlcpy(dir->dirname, dirname, sizeof(dir->dirname));
+
+ /*
+ * Append path separator, if needed, and "*".
+ */
+ p = dir->dirname + strlen(dir->dirname);
+ if (dir->dirname < p && *(p - 1) != '\\' && *(p - 1) != ':')
+ *p++ = '\\';
+ *p++ = '*';
+ *p = '\0';
+
+ /*
+ * Open stream.
+ */
+ result = start_directory(dir);
+
+ return (result);
+}
+
+/*
+ * Return previously retrieved file or get next one. Unix's dirent has
+ * separate open and read functions, but the Win32 and DOS interfaces open
+ * the dir stream and reads the first file in one operation.
+ */
+isc_result_t
+isc_dir_read(isc_dir_t *dir) {
+ REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE);
+
+ if (dir->entry_filled)
+ /*
+ * start_directory() already filled in the first entry.
+ */
+ dir->entry_filled = false;
+
+ else {
+ /*
+ * Fetch next file in directory.
+ */
+ if (FindNextFile(dir->search_handle,
+ &dir->entry.find_data) == FALSE)
+ /*
+ * Either the last file has been processed or
+ * an error has occurred. The former is not
+ * really an error, but the latter is.
+ */
+ if (GetLastError() == ERROR_NO_MORE_FILES)
+ return (ISC_R_NOMORE);
+ else
+ return (ISC_R_UNEXPECTED);
+ }
+
+ /*
+ * Make sure that the space for the name is long enough.
+ */
+ strlcpy(dir->entry.name, dir->entry.find_data.cFileName,
+ sizeof(dir->entry.name));
+ dir->entry.length = strlen(dir->entry.name);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Close directory stream.
+ */
+void
+isc_dir_close(isc_dir_t *dir) {
+ REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE);
+
+ FindClose(dir->search_handle);
+ dir->search_handle = INVALID_HANDLE_VALUE;
+}
+
+/*
+ * Reposition directory stream at start.
+ */
+isc_result_t
+isc_dir_reset(isc_dir_t *dir) {
+ isc_result_t result;
+
+ REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE);
+ REQUIRE(dir->dirname != NULL);
+
+ /*
+ * NT cannot reposition the seek pointer to the beginning of the
+ * the directory stream, but rather the directory needs to be
+ * closed and reopened. The latter might fail.
+ */
+
+ isc_dir_close(dir);
+
+ result = start_directory(dir);
+
+ return (result);
+}
+
+/*
+ * Initialize isc_dir_t structure with new directory. The function
+ * returns 0 on failure and nonzero on success.
+ *
+ * Note:
+ * - Be sure to close previous stream before opening new one
+ */
+static isc_result_t
+start_directory(isc_dir_t *dir)
+{
+ REQUIRE(VALID_DIR(dir));
+ REQUIRE(dir->search_handle == INVALID_HANDLE_VALUE);
+
+ dir->entry_filled = false;
+
+ /*
+ * Open stream and retrieve first file.
+ */
+ dir->search_handle = FindFirstFile(dir->dirname,
+ &dir->entry.find_data);
+
+ if (dir->search_handle == INVALID_HANDLE_VALUE) {
+ /*
+ * Something went wrong but we don't know what. GetLastError()
+ * could give us more information about the error, but the
+ * MSDN documentation is frustratingly thin about what
+ * possible errors could have resulted. (Score one for
+ * the Unix manual pages.) So there is just this lame error
+ * instead of being able to differentiate ISC_R_NOTFOUND
+ * from ISC_R_UNEXPECTED.
+ */
+ return (ISC_R_FAILURE);
+ }
+
+ /*
+ * Make sure that the space for the name is long enough.
+ */
+ INSIST(sizeof(dir->entry.name) >
+ strlen(dir->entry.find_data.cFileName));
+
+ /*
+ * Fill in the data for the first entry of the directory.
+ */
+ strlcpy(dir->entry.name, dir->entry.find_data.cFileName,
+ sizeof(dir->entry.name));
+ dir->entry.length = strlen(dir->entry.name);
+
+ dir->entry_filled = true;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_dir_chdir(const char *dirname) {
+ /*
+ * Change the current directory to 'dirname'.
+ */
+
+ REQUIRE(dirname != NULL);
+
+ if (chdir(dirname) < 0)
+ return (isc__errno2result(errno));
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_dir_chroot(const char *dirname) {
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+isc_result_t
+isc_dir_createunique(char *templet) {
+ isc_result_t result;
+ char *x;
+ char *p;
+ int i;
+ int pid;
+
+ REQUIRE(templet != NULL);
+
+ /*
+ * mkdtemp is not portable, so this emulates it.
+ */
+
+ pid = getpid();
+
+ /*
+ * Replace trailing Xs with the process-id, zero-filled.
+ */
+ for (x = templet + strlen(templet) - 1; *x == 'X' && x >= templet;
+ x--, pid /= 10)
+ *x = pid % 10 + '0';
+
+ x++; /* Set x to start of ex-Xs. */
+
+ do {
+ i = mkdir(templet);
+ if (i == 0)
+ i = chmod(templet, 0700);
+
+ if (i == 0 || errno != EEXIST)
+ break;
+
+ /*
+ * The BSD algorithm.
+ */
+ p = x;
+ while (*p != '\0') {
+ if (isdigit(*p & 0xff))
+ *p = 'a';
+ else if (*p != 'z')
+ ++*p;
+ else {
+ /*
+ * Reset character and move to next.
+ */
+ *p++ = 'a';
+ continue;
+ }
+
+ break;
+ }
+
+ if (*p == '\0') {
+ /*
+ * Tried all combinations. errno should already
+ * be EEXIST, but ensure it is anyway for
+ * isc__errno2result().
+ */
+ errno = EEXIST;
+ break;
+ }
+ } while (1);
+
+ if (i == -1)
+ result = isc__errno2result(errno);
+ else
+ result = ISC_R_SUCCESS;
+
+ return (result);
+}
diff --git a/lib/isc/win32/entropy.c b/lib/isc/win32/entropy.c
new file mode 100644
index 0000000..2480c02
--- /dev/null
+++ b/lib/isc/win32/entropy.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*
+ * This is the system dependent part of the ISC entropy API.
+ */
+
+#include <config.h>
+
+#include <stdbool.h>
+
+#include <windows.h>
+#include <wincrypt.h>
+
+#include <process.h>
+#include <io.h>
+#include <share.h>
+
+/*
+ * There is only one variable in the entropy data structures that is not
+ * system independent, but pulling the structure that uses it into this file
+ * ultimately means pulling several other independent structures here also to
+ * resolve their interdependencies. Thus only the problem variable's type
+ * is defined here.
+ */
+#define FILESOURCE_HANDLE_TYPE HCRYPTPROV
+
+typedef struct {
+ int dummy;
+} isc_entropyusocketsource_t;
+
+#include "../entropy.c"
+
+static unsigned int
+get_from_filesource(isc_entropysource_t *source, uint32_t desired) {
+ isc_entropy_t *ent = source->ent;
+ unsigned char buf[128];
+ HCRYPTPROV hcryptprov = source->sources.file.handle;
+ ssize_t ndesired;
+ unsigned int added;
+
+ if (source->bad)
+ return (0);
+
+ desired = desired / 8 + (((desired & 0x07) > 0) ? 1 : 0);
+
+ added = 0;
+ while (desired > 0) {
+ ndesired = ISC_MIN(desired, sizeof(buf));
+ if (!CryptGenRandom(hcryptprov, (DWORD)ndesired, buf)) {
+ CryptReleaseContext(hcryptprov, 0);
+ source->bad = true;
+ goto out;
+ }
+
+ entropypool_adddata(ent, buf,
+ (unsigned int)ndesired,
+ (unsigned int)ndesired * 8);
+ added += (unsigned int)ndesired * 8;
+ desired -= (uint32_t)ndesired;
+ }
+
+ out:
+ return (added);
+}
+
+/*
+ * Poll each source, trying to get data from it to stuff into the entropy
+ * pool.
+ */
+static void
+fillpool(isc_entropy_t *ent, unsigned int desired, bool blocking) {
+ unsigned int added;
+ unsigned int remaining;
+ unsigned int needed;
+ unsigned int nsource;
+ isc_entropysource_t *source;
+ isc_entropysource_t *firstsource;
+
+ REQUIRE(VALID_ENTROPY(ent));
+
+ needed = desired;
+
+ /*
+ * This logic is a little strange, so an explanation is in order.
+ *
+ * If needed is 0, it means we are being asked to "fill to whatever
+ * we think is best." This means that if we have at least a
+ * partially full pool (say, > 1/4th of the pool) we probably don't
+ * need to add anything.
+ *
+ * Also, we will check to see if the "pseudo" count is too high.
+ * If it is, try to mix in better data. Too high is currently
+ * defined as 1/4th of the pool.
+ *
+ * Next, if we are asked to add a specific bit of entropy, make
+ * certain that we will do so. Clamp how much we try to add to
+ * (DIGEST_SIZE * 8 < needed < POOLBITS - entropy).
+ *
+ * Note that if we are in a blocking mode, we will only try to
+ * get as much data as we need, not as much as we might want
+ * to build up.
+ */
+ if (needed == 0) {
+ REQUIRE(!blocking);
+
+ if ((ent->pool.entropy >= RND_POOLBITS / 4)
+ && (ent->pool.pseudo <= RND_POOLBITS / 4))
+ return;
+
+ needed = THRESHOLD_BITS * 4;
+ } else {
+ needed = ISC_MAX(needed, THRESHOLD_BITS);
+ needed = ISC_MIN(needed, RND_POOLBITS);
+ }
+
+ /*
+ * In any case, clamp how much we need to how much we can add.
+ */
+ needed = ISC_MIN(needed, RND_POOLBITS - ent->pool.entropy);
+
+ /*
+ * But wait! If we're not yet initialized, we need at least
+ * THRESHOLD_BITS
+ * of randomness.
+ */
+ if (ent->initialized < THRESHOLD_BITS)
+ needed = ISC_MAX(needed, THRESHOLD_BITS - ent->initialized);
+
+ /*
+ * Poll each file source to see if we can read anything useful from
+ * it. XXXMLG When where are multiple sources, we should keep a
+ * record of which one we last used so we can start from it (or the
+ * next one) to avoid letting some sources build up entropy while
+ * others are always drained.
+ */
+
+ added = 0;
+ remaining = needed;
+ if (ent->nextsource == NULL) {
+ ent->nextsource = ISC_LIST_HEAD(ent->sources);
+ if (ent->nextsource == NULL)
+ return;
+ }
+ source = ent->nextsource;
+ /*
+ * Remember the first source so we can break if we have looped back to
+ * the beginning and still have nothing
+ */
+ firstsource = source;
+ again_file:
+ for (nsource = 0; nsource < ent->nsources; nsource++) {
+ unsigned int got;
+
+ if (remaining == 0)
+ break;
+
+ got = 0;
+
+ if (source->type == ENTROPY_SOURCETYPE_FILE)
+ got = get_from_filesource(source, remaining);
+
+ added += got;
+
+ remaining -= ISC_MIN(remaining, got);
+
+ source = ISC_LIST_NEXT(source, link);
+ if (source == NULL)
+ source = ISC_LIST_HEAD(ent->sources);
+ }
+ ent->nextsource = source;
+
+ /*
+ * Go again only if there's been progress and we've not
+ * gone back to the beginning
+ */
+ if (!(ent->nextsource == firstsource && added == 0)) {
+ if (blocking && remaining != 0) {
+ goto again_file;
+ }
+ }
+
+ /*
+ * Here, if there are bits remaining to be had and we can block,
+ * check to see if we have a callback source. If so, call them.
+ */
+ source = ISC_LIST_HEAD(ent->sources);
+ while ((remaining != 0) && (source != NULL)) {
+ unsigned int got;
+
+ got = 0;
+
+ if (source->type == ENTROPY_SOURCETYPE_CALLBACK)
+ got = get_from_callback(source, remaining, blocking);
+
+ added += got;
+ remaining -= ISC_MIN(remaining, got);
+
+ if (added >= needed)
+ break;
+
+ source = ISC_LIST_NEXT(source, link);
+ }
+
+ /*
+ * Mark as initialized if we've added enough data.
+ */
+ if (ent->initialized < THRESHOLD_BITS)
+ ent->initialized += added;
+}
+
+
+
+/*
+ * Requires "ent" be locked.
+ */
+static void
+destroyfilesource(isc_entropyfilesource_t *source) {
+ CryptReleaseContext(source->handle, 0);
+}
+
+static void
+destroyusocketsource(isc_entropyusocketsource_t *source) {
+ UNUSED(source);
+}
+
+
+isc_result_t
+isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) {
+ isc_result_t ret;
+ isc_entropysource_t *source;
+ HCRYPTPROV hcryptprov;
+ BOOL err;
+
+ REQUIRE(VALID_ENTROPY(ent));
+ REQUIRE(fname != NULL);
+
+ LOCK(&ent->lock);
+
+ source = NULL;
+
+ /*
+ * The first time we just try to acquire the context
+ */
+ err = CryptAcquireContext(&hcryptprov, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT);
+ if (!err){
+ (void)GetLastError();
+ ret = ISC_R_IOERROR;
+ goto errout;
+ }
+
+ source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
+ if (source == NULL) {
+ ret = ISC_R_NOMEMORY;
+ goto closecontext;
+ }
+
+ /*
+ * From here down, no failures can occur.
+ */
+ source->magic = SOURCE_MAGIC;
+ source->type = ENTROPY_SOURCETYPE_FILE;
+ source->ent = ent;
+ source->total = 0;
+ source->bad = false;
+ memset(source->name, 0, sizeof(source->name));
+ ISC_LINK_INIT(source, link);
+ source->sources.file.handle = hcryptprov;
+
+ /*
+ * Hook it into the entropy system.
+ */
+ ISC_LIST_APPEND(ent->sources, source, link);
+ ent->nsources++;
+
+ UNLOCK(&ent->lock);
+ return (ISC_R_SUCCESS);
+
+ closecontext:
+ CryptReleaseContext(hcryptprov, 0);
+
+ errout:
+ if (source != NULL)
+ isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
+
+ UNLOCK(&ent->lock);
+
+ return (ret);
+}
diff --git a/lib/isc/win32/errno.c b/lib/isc/win32/errno.c
new file mode 100644
index 0000000..74ebf0c
--- /dev/null
+++ b/lib/isc/win32/errno.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include "errno2result.h"
+
+isc_result_t
+isc_errno_toresult(int err) {
+ return (isc__errno2resultx(err, false, 0, 0));
+}
diff --git a/lib/isc/win32/errno2result.c b/lib/isc/win32/errno2result.c
new file mode 100644
index 0000000..83dbb4e
--- /dev/null
+++ b/lib/isc/win32/errno2result.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <stdbool.h>
+
+#include <winsock2.h>
+#include "errno2result.h"
+#include <isc/result.h>
+#include <isc/strerror.h>
+#include <isc/util.h>
+
+/*
+ * Convert a POSIX errno value into an isc_result_t. The
+ * list of supported errno values is not complete; new users
+ * of this function should add any expected errors that are
+ * not already there.
+ */
+isc_result_t
+isc__errno2resultx(int posixerrno, bool dolog,
+ const char *file, int line)
+{
+ char strbuf[ISC_STRERRORSIZE];
+
+ switch (posixerrno) {
+ case ENOTDIR:
+ case WSAELOOP:
+ case WSAEINVAL:
+ case EINVAL: /* XXX sometimes this is not for files */
+ case ENAMETOOLONG:
+ case WSAENAMETOOLONG:
+ case EBADF:
+ case WSAEBADF:
+ return (ISC_R_INVALIDFILE);
+ case ENOENT:
+ return (ISC_R_FILENOTFOUND);
+ case EACCES:
+ case WSAEACCES:
+ case EPERM:
+ return (ISC_R_NOPERM);
+ case EEXIST:
+ return (ISC_R_FILEEXISTS);
+ case EIO:
+ return (ISC_R_IOERROR);
+ case ENOMEM:
+ return (ISC_R_NOMEMORY);
+#ifdef EOVERFLOW
+ case EOVERFLOW:
+ return (ISC_R_RANGE);
+#endif
+ case ENFILE:
+ case EMFILE:
+ case WSAEMFILE:
+ return (ISC_R_TOOMANYOPENFILES);
+ case ERROR_CANCELLED:
+ return (ISC_R_CANCELED);
+ case ERROR_CONNECTION_REFUSED:
+ case WSAECONNREFUSED:
+ return (ISC_R_CONNREFUSED);
+ case WSAENOTCONN:
+ case ERROR_CONNECTION_INVALID:
+ return (ISC_R_NOTCONNECTED);
+ case ERROR_HOST_UNREACHABLE:
+ case WSAEHOSTUNREACH:
+ return (ISC_R_HOSTUNREACH);
+ case ERROR_NETWORK_UNREACHABLE:
+ case WSAENETUNREACH:
+ return (ISC_R_NETUNREACH);
+ case ERROR_NO_NETWORK:
+ return (ISC_R_NETUNREACH);
+ case ERROR_PORT_UNREACHABLE:
+ return (ISC_R_HOSTUNREACH);
+ case ERROR_SEM_TIMEOUT:
+ return (ISC_R_TIMEDOUT);
+ case WSAECONNRESET:
+ case WSAENETRESET:
+ case WSAECONNABORTED:
+ case WSAEDISCON:
+ case ERROR_OPERATION_ABORTED:
+ case ERROR_CONNECTION_ABORTED:
+ case ERROR_REQUEST_ABORTED:
+ return (ISC_R_CONNECTIONRESET);
+ case WSAEADDRNOTAVAIL:
+ return (ISC_R_ADDRNOTAVAIL);
+ case ERROR_NETNAME_DELETED:
+ case WSAENETDOWN:
+ return (ISC_R_NETUNREACH);
+ case WSAEHOSTDOWN:
+ return (ISC_R_HOSTUNREACH);
+ case WSAENOBUFS:
+ return (ISC_R_NORESOURCES);
+ default:
+ if (dolog) {
+ isc__strerror(posixerrno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(file, line,
+ "unable to convert errno "
+ "to isc_result: %d: %s",
+ posixerrno, strbuf);
+ }
+ /*
+ * XXXDCL would be nice if perhaps this function could
+ * return the system's error string, so the caller
+ * might have something more descriptive than "unexpected
+ * error" to log with.
+ */
+ return (ISC_R_UNEXPECTED);
+ }
+}
diff --git a/lib/isc/win32/errno2result.h b/lib/isc/win32/errno2result.h
new file mode 100644
index 0000000..99752ae
--- /dev/null
+++ b/lib/isc/win32/errno2result.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef UNIX_ERRNO2RESULT_H
+#define UNIX_ERRNO2RESULT_H 1
+
+/* XXXDCL this should be moved to lib/isc/include/isc/errno2result.h. */
+
+#include <errno.h> /* Provides errno. */
+#include <stdbool.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+#define isc__errno2result(posixerrno) \
+ isc__errno2resultx(posixerrno, true, __FILE__, __LINE__)
+
+isc_result_t
+isc__errno2resultx(int posixerrno, bool dolog,
+ const char *file, int line);
+
+ISC_LANG_ENDDECLS
+
+#endif /* UNIX_ERRNO2RESULT_H */
diff --git a/lib/isc/win32/file.c b/lib/isc/win32/file.c
new file mode 100644
index 0000000..d281ba1
--- /dev/null
+++ b/lib/isc/win32/file.c
@@ -0,0 +1,928 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#undef rename
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <io.h>
+#include <process.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/utime.h>
+
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/result.h>
+#include <isc/sha2.h>
+#include <isc/stat.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include "errno2result.h"
+
+static const char alphnum[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+/*
+ * Emulate UNIX mkstemp, which returns an open FD to the new file
+ *
+ */
+static int
+gettemp(char *path, bool binary, int *doopen) {
+ char *start, *trv;
+ struct stat sbuf;
+ int flags = O_CREAT|O_EXCL|O_RDWR;
+
+ if (binary)
+ flags |= _O_BINARY;
+
+ trv = strrchr(path, 'X');
+ trv++;
+ /* extra X's get set to 0's */
+ while (*--trv == 'X') {
+ uint32_t which;
+
+ isc_random_get(&which);
+ *trv = alphnum[which % (sizeof(alphnum) - 1)];
+ }
+ /*
+ * check the target directory; if you have six X's and it
+ * doesn't exist this runs for a *very* long time.
+ */
+ for (start = trv + 1;; --trv) {
+ if (trv <= path)
+ break;
+ if (*trv == '\\') {
+ *trv = '\0';
+ if (stat(path, &sbuf))
+ return (0);
+ if (!S_ISDIR(sbuf.st_mode)) {
+ errno = ENOTDIR;
+ return (0);
+ }
+ *trv = '\\';
+ break;
+ }
+ }
+
+ for (;;) {
+ if (doopen) {
+ if ((*doopen =
+ open(path, flags, _S_IREAD | _S_IWRITE)) >= 0)
+ return (1);
+ if (errno != EEXIST)
+ return (0);
+ } else if (stat(path, &sbuf))
+ return (errno == ENOENT ? 1 : 0);
+
+ /* tricky little algorithm for backward compatibility */
+ for (trv = start;;) {
+ if (!*trv)
+ return (0);
+ if (*trv == 'z')
+ *trv++ = 'a';
+ else {
+ if (isdigit(*trv))
+ *trv = 'a';
+ else
+ ++*trv;
+ break;
+ }
+ }
+ }
+ /*NOTREACHED*/
+}
+
+static int
+mkstemp(char *path, bool binary) {
+ int fd;
+
+ return (gettemp(path, binary, &fd) ? fd : -1);
+}
+
+/*
+ * XXXDCL As the API for accessing file statistics undoubtedly gets expanded,
+ * it might be good to provide a mechanism that allows for the results
+ * of a previous stat() to be used again without having to do another stat,
+ * such as perl's mechanism of using "_" in place of a file name to indicate
+ * that the results of the last stat should be used. But then you get into
+ * annoying MP issues. BTW, Win32 has stat().
+ */
+static isc_result_t
+file_stats(const char *file, struct stat *stats) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(file != NULL);
+ REQUIRE(stats != NULL);
+
+ if (stat(file, stats) != 0)
+ result = isc__errno2result(errno);
+
+ return (result);
+}
+
+static isc_result_t
+fd_stats(int fd, struct stat *stats) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(stats != NULL);
+
+ if (fstat(fd, stats) != 0)
+ result = isc__errno2result(errno);
+
+ return (result);
+}
+
+isc_result_t
+isc_file_getsizefd(int fd, off_t *size) {
+ isc_result_t result;
+ struct stat stats;
+
+ REQUIRE(size != NULL);
+
+ result = fd_stats(fd, &stats);
+
+ if (result == ISC_R_SUCCESS)
+ *size = stats.st_size;
+ return (result);
+}
+
+isc_result_t
+isc_file_mode(const char *file, mode_t *modep) {
+ isc_result_t result;
+ struct stat stats;
+
+ REQUIRE(modep != NULL);
+
+ result = file_stats(file, &stats);
+ if (result == ISC_R_SUCCESS)
+ *modep = (stats.st_mode & 07777);
+ return (result);
+}
+
+/*
+ * isc_file_safemovefile is needed to be defined here to ensure that
+ * any file with the new name is renamed to a backup name and then the
+ * rename is done. If all goes well then the backup can be deleted,
+ * otherwise it gets renamed back.
+ */
+
+int
+isc_file_safemovefile(const char *oldname, const char *newname) {
+ BOOL filestatus;
+ char buf[512];
+ struct stat sbuf;
+ BOOL exists = FALSE;
+ int tmpfd;
+
+ /*
+ * Make sure we have something to do
+ */
+ if (stat(oldname, &sbuf) != 0) {
+ errno = ENOENT;
+ return (-1);
+ }
+
+ /*
+ * Rename to a backup the new file if it still exists
+ */
+ if (stat(newname, &sbuf) == 0) {
+ exists = TRUE;
+ strlcpy(buf, newname, sizeof(buf));
+ strlcat(buf, ".XXXXX", sizeof(buf));
+ tmpfd = mkstemp(buf, true);
+ if (tmpfd > 0)
+ _close(tmpfd);
+ (void)DeleteFile(buf);
+ _chmod(newname, _S_IREAD | _S_IWRITE);
+
+ filestatus = MoveFile(newname, buf);
+ }
+ /* Now rename the file to the new name
+ */
+ _chmod(oldname, _S_IREAD | _S_IWRITE);
+
+ filestatus = MoveFile(oldname, newname);
+ if (filestatus == 0) {
+ /*
+ * Try to rename the backup back to the original name
+ * if the backup got created
+ */
+ if (exists == TRUE) {
+ filestatus = MoveFile(buf, newname);
+ if (filestatus == 0)
+ errno = EACCES;
+ }
+ return (-1);
+ }
+
+ /*
+ * Delete the backup file if it got created
+ */
+ if (exists == TRUE)
+ (void)DeleteFile(buf);
+ return (0);
+}
+
+isc_result_t
+isc_file_getmodtime(const char *file, isc_time_t *time) {
+ int fh;
+
+ REQUIRE(file != NULL);
+ REQUIRE(time != NULL);
+
+ if ((fh = open(file, _O_RDONLY | _O_BINARY)) < 0)
+ return (isc__errno2result(errno));
+
+ if (!GetFileTime((HANDLE) _get_osfhandle(fh),
+ NULL,
+ NULL,
+ &time->absolute))
+ {
+ close(fh);
+ errno = EINVAL;
+ return (isc__errno2result(errno));
+ }
+ close(fh);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_getsize(const char *file, off_t *size) {
+ isc_result_t result;
+ struct stat stats;
+
+ REQUIRE(file != NULL);
+ REQUIRE(size != NULL);
+
+ result = file_stats(file, &stats);
+
+ if (result == ISC_R_SUCCESS)
+ *size = stats.st_size;
+
+ return (result);
+}
+
+isc_result_t
+isc_file_settime(const char *file, isc_time_t *time) {
+ int fh;
+
+ REQUIRE(file != NULL && time != NULL);
+
+ if ((fh = open(file, _O_RDWR | _O_BINARY)) < 0)
+ return (isc__errno2result(errno));
+
+ /*
+ * Set the date via the filedate system call and return. Failing
+ * this call implies the new file times are not supported by the
+ * underlying file system.
+ */
+ if (!SetFileTime((HANDLE) _get_osfhandle(fh),
+ NULL,
+ &time->absolute,
+ &time->absolute))
+ {
+ close(fh);
+ errno = EINVAL;
+ return (isc__errno2result(errno));
+ }
+
+ close(fh);
+ return (ISC_R_SUCCESS);
+
+}
+
+#undef TEMPLATE
+#define TEMPLATE "XXXXXXXXXX.tmp" /* 14 characters. */
+
+isc_result_t
+isc_file_mktemplate(const char *path, char *buf, size_t buflen) {
+ return (isc_file_template(path, TEMPLATE, buf, buflen));
+}
+
+isc_result_t
+isc_file_template(const char *path, const char *templet, char *buf,
+ size_t buflen)
+{
+ char *s;
+
+ REQUIRE(templet != NULL);
+ REQUIRE(buf != NULL);
+
+ if (path == NULL)
+ path = "";
+
+ s = strrchr(templet, '\\');
+ if (s != NULL)
+ templet = s + 1;
+
+ s = strrchr(path, '\\');
+
+ if (s != NULL) {
+ size_t prefixlen = s - path + 1;
+ if ((prefixlen + strlen(templet) + 1) > buflen)
+ return (ISC_R_NOSPACE);
+
+ /* Copy 'prefixlen' bytes and NUL terminate. */
+ strlcpy(buf, path, ISC_MIN(prefixlen + 1, buflen));
+ strlcat(buf, templet, buflen);
+ } else {
+ if ((strlen(templet) + 1) > buflen)
+ return (ISC_R_NOSPACE);
+
+ strlcpy(buf, templet, buflen);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_renameunique(const char *file, char *templet) {
+ int fd;
+ int res = 0;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(file != NULL);
+ REQUIRE(templet != NULL);
+
+ fd = mkstemp(templet, true);
+ if (fd == -1)
+ result = isc__errno2result(errno);
+ else
+ close(fd);
+
+ if (result == ISC_R_SUCCESS) {
+ res = isc_file_safemovefile(file, templet);
+ if (res != 0) {
+ result = isc__errno2result(errno);
+ (void)unlink(templet);
+ }
+ }
+ return (result);
+}
+
+static isc_result_t
+openuniquemode(char *templet, int mode, bool binary, FILE **fp) {
+ int fd;
+ FILE *f;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(templet != NULL);
+ REQUIRE(fp != NULL && *fp == NULL);
+
+ /*
+ * Win32 does not have mkstemp. Using emulation above.
+ */
+ fd = mkstemp(templet, binary);
+
+ if (fd == -1)
+ result = isc__errno2result(errno);
+ if (result == ISC_R_SUCCESS) {
+#if 1
+ UNUSED(mode);
+#else
+ (void)fchmod(fd, mode);
+#endif
+ f = fdopen(fd, binary ? "wb+" : "w+");
+ if (f == NULL) {
+ result = isc__errno2result(errno);
+ (void)remove(templet);
+ (void)close(fd);
+ } else
+ *fp = f;
+ }
+
+ return (result);
+}
+
+isc_result_t
+isc_file_openuniqueprivate(char *templet, FILE **fp) {
+ int mode = _S_IREAD | _S_IWRITE;
+ return (openuniquemode(templet, mode, false, fp));
+}
+
+isc_result_t
+isc_file_openunique(char *templet, FILE **fp) {
+ int mode = _S_IREAD | _S_IWRITE;
+ return (openuniquemode(templet, mode, false, fp));
+}
+
+isc_result_t
+isc_file_openuniquemode(char *templet, int mode, FILE **fp) {
+ return (openuniquemode(templet, mode, false, fp));
+}
+
+isc_result_t
+isc_file_bopenuniqueprivate(char *templet, FILE **fp) {
+ int mode = _S_IREAD | _S_IWRITE;
+ return (openuniquemode(templet, mode, true, fp));
+}
+
+isc_result_t
+isc_file_bopenunique(char *templet, FILE **fp) {
+ int mode = _S_IREAD | _S_IWRITE;
+ return (openuniquemode(templet, mode, true, fp));
+}
+
+isc_result_t
+isc_file_bopenuniquemode(char *templet, int mode, FILE **fp) {
+ return (openuniquemode(templet, mode, true, fp));
+}
+
+isc_result_t
+isc_file_remove(const char *filename) {
+ int r;
+
+ REQUIRE(filename != NULL);
+
+ r = unlink(filename);
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_file_rename(const char *oldname, const char *newname) {
+ int r;
+
+ REQUIRE(oldname != NULL);
+ REQUIRE(newname != NULL);
+
+ r = isc_file_safemovefile(oldname, newname);
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+bool
+isc_file_exists(const char *pathname) {
+ struct stat stats;
+
+ REQUIRE(pathname != NULL);
+
+ return (file_stats(pathname, &stats) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_isplainfile(const char *filename) {
+ /*
+ * This function returns success if filename is a plain file.
+ */
+ struct stat filestat;
+ memset(&filestat,0,sizeof(struct stat));
+
+ if ((stat(filename, &filestat)) == -1)
+ return(isc__errno2result(errno));
+
+ if(! S_ISREG(filestat.st_mode))
+ return(ISC_R_INVALIDFILE);
+
+ return(ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_isplainfilefd(int fd) {
+ /*
+ * This function returns success if filename is a plain file.
+ */
+ struct stat filestat;
+ memset(&filestat,0,sizeof(struct stat));
+
+ if ((fstat(fd, &filestat)) == -1)
+ return(isc__errno2result(errno));
+
+ if(! S_ISREG(filestat.st_mode))
+ return(ISC_R_INVALIDFILE);
+
+ return(ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_isdirectory(const char *filename) {
+ /*
+ * This function returns success if filename is a directory.
+ */
+ struct stat filestat;
+ memset(&filestat,0,sizeof(struct stat));
+
+ if ((stat(filename, &filestat)) == -1)
+ return(isc__errno2result(errno));
+
+ if(! S_ISDIR(filestat.st_mode))
+ return(ISC_R_INVALIDFILE);
+
+ return(ISC_R_SUCCESS);
+}
+
+
+bool
+isc_file_isabsolute(const char *filename) {
+ REQUIRE(filename != NULL);
+ /*
+ * Look for c:\path\... style, c:/path/... or \\computer\shar\path...
+ * the UNC style file specs
+ */
+ if ((filename[0] == '\\') && (filename[1] == '\\'))
+ return (true);
+ if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '\\')
+ return (true);
+ if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '/')
+ return (true);
+ return (false);
+}
+
+bool
+isc_file_iscurrentdir(const char *filename) {
+ REQUIRE(filename != NULL);
+ return (filename[0] == '.' && filename[1] == '\0');
+}
+
+bool
+isc_file_ischdiridempotent(const char *filename) {
+ REQUIRE(filename != NULL);
+
+ if (isc_file_isabsolute(filename))
+ return (true);
+ if (filename[0] == '\\')
+ return (true);
+ if (filename[0] == '/')
+ return (true);
+ if (isc_file_iscurrentdir(filename))
+ return (true);
+ return (false);
+}
+
+const char *
+isc_file_basename(const char *filename) {
+ char *s;
+
+ REQUIRE(filename != NULL);
+
+ s = strrchr(filename, '\\');
+ if (s == NULL)
+ return (filename);
+ return (s + 1);
+}
+
+isc_result_t
+isc_file_progname(const char *filename, char *progname, size_t namelen) {
+ const char *s;
+ const char *p;
+ size_t len;
+
+ REQUIRE(filename != NULL);
+ REQUIRE(progname != NULL);
+
+ /*
+ * Strip the path from the name
+ */
+ s = isc_file_basename(filename);
+ if (s == NULL) {
+ return (ISC_R_NOSPACE);
+ }
+
+ /*
+ * Strip any and all suffixes
+ */
+ p = strchr(s, '.');
+ if (p == NULL) {
+ if (namelen <= strlen(s))
+ return (ISC_R_NOSPACE);
+
+ strlcpy(progname, s, namelen);
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Copy the result to the buffer
+ */
+ len = p - s;
+ if (len >= namelen)
+ return (ISC_R_NOSPACE);
+
+ /* Copy up to 'len' bytes and NUL terminate. */
+ strlcpy(progname, s, ISC_MIN(len + 1, namelen));
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_absolutepath(const char *filename, char *path, size_t pathlen) {
+ char *ptrname;
+ DWORD retval;
+
+ REQUIRE(filename != NULL);
+ REQUIRE(path != NULL);
+
+ retval = GetFullPathName(filename, (DWORD) pathlen, path, &ptrname);
+
+ /* Something went wrong in getting the path */
+ if (retval == 0)
+ return (ISC_R_NOTFOUND);
+ /* Caller needs to provide a larger buffer to contain the string */
+ if (retval >= pathlen)
+ return (ISC_R_NOSPACE);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_truncate(const char *filename, isc_offset_t size) {
+ int fh;
+
+ REQUIRE(filename != NULL && size >= 0);
+
+ if ((fh = open(filename, _O_RDWR | _O_BINARY)) < 0)
+ return (isc__errno2result(errno));
+
+ if(_chsize(fh, size) != 0) {
+ close(fh);
+ return (isc__errno2result(errno));
+ }
+ close(fh);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_safecreate(const char *filename, FILE **fp) {
+ isc_result_t result;
+ int flags;
+ struct stat sb;
+ FILE *f;
+ int fd;
+
+ REQUIRE(filename != NULL);
+ REQUIRE(fp != NULL && *fp == NULL);
+
+ result = file_stats(filename, &sb);
+ if (result == ISC_R_SUCCESS) {
+ if ((sb.st_mode & S_IFREG) == 0)
+ return (ISC_R_INVALIDFILE);
+ flags = O_WRONLY | O_TRUNC;
+ } else if (result == ISC_R_FILENOTFOUND) {
+ flags = O_WRONLY | O_CREAT | O_EXCL;
+ } else
+ return (result);
+
+ fd = open(filename, flags, S_IRUSR | S_IWUSR);
+ if (fd == -1)
+ return (isc__errno2result(errno));
+
+ f = fdopen(fd, "w");
+ if (f == NULL) {
+ result = isc__errno2result(errno);
+ close(fd);
+ return (result);
+ }
+
+ *fp = f;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_splitpath(isc_mem_t *mctx, const char *path, char **dirname,
+ char const ** basename)
+{
+ char *dir;
+ const char *file, *slash;
+ char *backslash;
+
+ slash = strrchr(path, '/');
+
+ backslash = strrchr(path, '\\');
+ if ((slash != NULL && backslash != NULL && backslash > slash) ||
+ (slash == NULL && backslash != NULL))
+ slash = backslash;
+
+ if (slash == path) {
+ file = ++slash;
+ dir = isc_mem_strdup(mctx, "/");
+ } else if (slash != NULL) {
+ file = ++slash;
+ dir = isc_mem_allocate(mctx, slash - path);
+ if (dir != NULL)
+ strlcpy(dir, path, slash - path);
+ } else {
+ file = path;
+ dir = isc_mem_strdup(mctx, ".");
+ }
+
+ if (dir == NULL)
+ return (ISC_R_NOMEMORY);
+
+ if (*file == '\0') {
+ isc_mem_free(mctx, dir);
+ return (ISC_R_INVALIDFILE);
+ }
+
+ *dirname = dir;
+ *basename = file;
+
+ return (ISC_R_SUCCESS);
+}
+
+void *
+isc_file_mmap(void *addr, size_t len, int prot,
+ int flags, int fd, off_t offset)
+{
+ void *buf;
+ ssize_t ret;
+ off_t end;
+
+ UNUSED(addr);
+ UNUSED(prot);
+ UNUSED(flags);
+
+ end = lseek(fd, 0, SEEK_END);
+ lseek(fd, offset, SEEK_SET);
+ if (end - offset < (off_t) len)
+ len = end - offset;
+
+ buf = malloc(len);
+ if (buf == NULL)
+ return (NULL);
+
+ ret = read(fd, buf, (unsigned int) len);
+ if (ret != (ssize_t) len) {
+ free(buf);
+ buf = NULL;
+ }
+
+ return (buf);
+}
+
+int
+isc_file_munmap(void *addr, size_t len) {
+ UNUSED(len);
+ free(addr);
+ return (0);
+}
+
+#define DISALLOW "\\/:ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+isc_result_t
+isc_file_sanitize(const char *dir, const char *base, const char *ext,
+ char *path, size_t length)
+{
+ char buf[PATH_MAX], hash[ISC_SHA256_DIGESTSTRINGLENGTH];
+ size_t l = 0;
+
+ REQUIRE(base != NULL);
+ REQUIRE(path != NULL);
+
+ l = strlen(base) + 1;
+
+ /*
+ * allow room for a full sha256 hash (64 chars
+ * plus null terminator)
+ */
+ if (l < 65)
+ l = 65;
+
+ if (dir != NULL)
+ l += strlen(dir) + 1;
+ if (ext != NULL)
+ l += strlen(ext) + 1;
+
+ if (l > length || l > PATH_MAX)
+ return (ISC_R_NOSPACE);
+
+ /* Check whether the full-length SHA256 hash filename exists */
+ isc_sha256_data((const void *) base, strlen(base), hash);
+ snprintf(buf, sizeof(buf), "%s%s%s%s%s",
+ dir != NULL ? dir : "", dir != NULL ? "/" : "",
+ hash, ext != NULL ? "." : "", ext != NULL ? ext : "");
+ if (isc_file_exists(buf)) {
+ strlcpy(path, buf, length);
+ return (ISC_R_SUCCESS);
+ }
+
+ /* Check for a truncated SHA256 hash filename */
+ hash[16] = '\0';
+ snprintf(buf, sizeof(buf), "%s%s%s%s%s",
+ dir != NULL ? dir : "", dir != NULL ? "/" : "",
+ hash, ext != NULL ? "." : "", ext != NULL ? ext : "");
+ if (isc_file_exists(buf)) {
+ strlcpy(path, buf, length);
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * If neither hash filename already exists, then we'll use
+ * the original base name if it has no disallowed characters,
+ * or the truncated hash name if it does.
+ */
+ if (strpbrk(base, DISALLOW) != NULL) {
+ strlcpy(path, buf, length);
+ return (ISC_R_SUCCESS);
+ }
+
+ snprintf(buf, sizeof(buf), "%s%s%s%s%s",
+ dir != NULL ? dir : "", dir != NULL ? "/" : "",
+ base, ext != NULL ? "." : "", ext != NULL ? ext : "");
+ strlcpy(path, buf, length);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Based on http://blog.aaronballman.com/2011/08/how-to-check-access-rights/
+ */
+bool
+isc_file_isdirwritable(const char *path) {
+ DWORD length = 0;
+ HANDLE hToken = NULL;
+ PSECURITY_DESCRIPTOR security = NULL;
+ bool answer = false;
+
+ if (isc_file_isdirectory(path) != ISC_R_SUCCESS) {
+ return (answer);
+ }
+
+ /*
+ * Figure out buffer size. GetFileSecurity() should not succeed.
+ */
+ if (GetFileSecurity(path, OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ NULL, 0, &length))
+ {
+ return (answer);
+ }
+
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ return (answer);
+ }
+
+ security = malloc(length);
+ if (security == NULL) {
+ return (answer);
+ }
+
+ /*
+ * GetFileSecurity() should succeed.
+ */
+ if (!GetFileSecurity(path, OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ security, length, &length))
+ {
+ return (answer);
+ }
+
+ if (OpenProcessToken(GetCurrentProcess(), TOKEN_IMPERSONATE |
+ TOKEN_QUERY | TOKEN_DUPLICATE |
+ STANDARD_RIGHTS_READ, &hToken))
+ {
+ HANDLE hImpersonatedToken = NULL;
+
+ if (DuplicateToken(hToken, SecurityImpersonation,
+ &hImpersonatedToken))
+ {
+ GENERIC_MAPPING mapping;
+ PRIVILEGE_SET privileges = { 0 };
+ DWORD grantedAccess = 0;
+ DWORD privilegesLength = sizeof(privileges);
+ BOOL result = FALSE;
+ DWORD genericAccessRights = GENERIC_WRITE;
+
+ mapping.GenericRead = FILE_GENERIC_READ;
+ mapping.GenericWrite = FILE_GENERIC_WRITE;
+ mapping.GenericExecute = FILE_GENERIC_EXECUTE;
+ mapping.GenericAll = FILE_ALL_ACCESS;
+
+ MapGenericMask(&genericAccessRights, &mapping);
+ if (AccessCheck(security, hImpersonatedToken,
+ genericAccessRights, &mapping,
+ &privileges, &privilegesLength,
+ &grantedAccess, &result))
+ {
+ answer = result;
+ }
+ CloseHandle(hImpersonatedToken);
+ }
+ CloseHandle(hToken);
+ }
+ free(security);
+ return (answer);
+}
diff --git a/lib/isc/win32/fsaccess.c b/lib/isc/win32/fsaccess.c
new file mode 100644
index 0000000..164985d
--- /dev/null
+++ b/lib/isc/win32/fsaccess.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*
+ * Note that Win32 does not have the concept of files having access
+ * and ownership bits. The FAT File system only has a readonly flag
+ * for everyone and that's all. NTFS uses ACL's which is a totally
+ * different concept of controlling access.
+ *
+ * This code needs to be revisited to set up proper access control for
+ * NTFS file systems. Nothing can be done for FAT file systems.
+ */
+
+#include <config.h>
+
+#include <aclapi.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#include <isc/file.h>
+#include <isc/stat.h>
+#include <isc/string.h>
+
+#include "errno2result.h"
+
+/*
+ * The OS-independent part of the API is in lib/isc.
+ */
+#include "../fsaccess.c"
+
+/* Store the user account name locally */
+static char username[255] = "\0";
+static DWORD namelen = 0;
+
+/*
+ * In order to set or retrieve access information, we need to obtain
+ * the File System type. These could be UNC-type shares.
+ */
+
+BOOL
+is_ntfs(const char * file) {
+
+ char drive[255];
+ char FSType[20];
+ char tmpbuf[256];
+ char *machinename;
+ char *sharename;
+ char filename[1024];
+
+ REQUIRE(filename != NULL);
+
+ if (isc_file_absolutepath(file, filename,
+ sizeof(filename)) != ISC_R_SUCCESS) {
+ return (FALSE);
+ }
+
+ /*
+ * Look for c:\path\... style, c:/path/... or \\computer\shar\path...
+ * the UNC style file specs
+ */
+ if (isalpha(filename[0]) && filename[1] == ':' &&
+ (filename[2] == '\\' || filename[2] == '/')) {
+ /* Copy 'c:\' or 'c:/' and NUL terminate. */
+ strlcpy(drive, filename, ISC_MIN(3 + 1, sizeof(drive)));
+ } else if ((filename[0] == '\\') && (filename[1] == '\\')) {
+ /* Find the machine and share name and rebuild the UNC */
+ strlcpy(tmpbuf, filename, sizeof(tmpbuf));
+ machinename = strtok(tmpbuf, "\\");
+ sharename = strtok(NULL, "\\");
+ strlcpy(drive, "\\\\", sizeof(drive));
+ strlcat(drive, machinename, sizeof(drive));
+ strlcat(drive, "\\", sizeof(drive));
+ strlcat(drive, sharename, sizeof(drive));
+ strlcat(drive, "\\", sizeof(drive));
+
+ } else /* Not determinable */
+ return (FALSE);
+
+ GetVolumeInformation(drive, NULL, 0, NULL, 0, NULL, FSType,
+ sizeof(FSType));
+ if (strcmp(FSType, "NTFS") == 0)
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+/*
+ * If it's not NTFS, we assume that it is FAT and proceed
+ * with almost nothing to do. Only the write flag can be set or
+ * cleared.
+ */
+isc_result_t
+FAT_fsaccess_set(const char *path, isc_fsaccess_t access) {
+ int mode;
+ isc_fsaccess_t bits;
+
+ /*
+ * Done with checking bad bits. Set mode_t.
+ */
+ mode = 0;
+
+#define SET_AND_CLEAR1(modebit) \
+ if ((access & bits) != 0) { \
+ mode |= modebit; \
+ access &= ~bits; \
+ }
+#define SET_AND_CLEAR(user, group, other) \
+ SET_AND_CLEAR1(user); \
+ bits <<= STEP; \
+ SET_AND_CLEAR1(group); \
+ bits <<= STEP; \
+ SET_AND_CLEAR1(other);
+
+ bits = ISC_FSACCESS_READ | ISC_FSACCESS_LISTDIRECTORY;
+
+ SET_AND_CLEAR(S_IRUSR, S_IRGRP, S_IROTH);
+
+ bits = ISC_FSACCESS_WRITE |
+ ISC_FSACCESS_CREATECHILD |
+ ISC_FSACCESS_DELETECHILD;
+
+ SET_AND_CLEAR(S_IWUSR, S_IWGRP, S_IWOTH);
+
+ INSIST(access == 0);
+
+ if (_chmod(path, mode) < 0)
+ return (isc__errno2result(errno));
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+NTFS_Access_Control(const char *filename, const char *user, int access,
+ bool isdir) {
+ SECURITY_DESCRIPTOR sd;
+ BYTE aclBuffer[1024];
+ PACL pacl=(PACL)&aclBuffer;
+ BYTE sidBuffer[100];
+ PSID psid=(PSID) &sidBuffer;
+ DWORD sidBufferSize = sizeof(sidBuffer);
+ BYTE adminSidBuffer[100];
+ PSID padminsid=(PSID) &adminSidBuffer;
+ DWORD adminSidBufferSize = sizeof(adminSidBuffer);
+ BYTE otherSidBuffer[100];
+ PSID pothersid=(PSID) &otherSidBuffer;
+ DWORD otherSidBufferSize = sizeof(otherSidBuffer);
+ char domainBuffer[100];
+ DWORD domainBufferSize = sizeof(domainBuffer);
+ SID_NAME_USE snu;
+ DWORD NTFSbits;
+ int caccess;
+
+
+ /* Initialize an ACL */
+ if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
+ return (ISC_R_NOPERM);
+ if (!InitializeAcl(pacl, sizeof(aclBuffer), ACL_REVISION))
+ return (ISC_R_NOPERM);
+ if (!LookupAccountName(0, user, psid, &sidBufferSize, domainBuffer,
+ &domainBufferSize, &snu))
+ return (ISC_R_NOPERM);
+ domainBufferSize = sizeof(domainBuffer);
+ if (!LookupAccountName(0, "Administrators", padminsid,
+ &adminSidBufferSize, domainBuffer, &domainBufferSize, &snu)) {
+ (void)GetLastError();
+ return (ISC_R_NOPERM);
+ }
+ domainBufferSize = sizeof(domainBuffer);
+ if (!LookupAccountName(0, "Everyone", pothersid,
+ &otherSidBufferSize, domainBuffer, &domainBufferSize, &snu)) {
+ (void)GetLastError();
+ return (ISC_R_NOPERM);
+ }
+
+ caccess = access;
+ /* Owner check */
+
+ NTFSbits = 0;
+ if (caccess & ISC_FSACCESS_READ)
+ NTFSbits |= FILE_GENERIC_READ;
+ if (caccess & ISC_FSACCESS_WRITE)
+ NTFSbits |= FILE_GENERIC_WRITE;
+ if (caccess & ISC_FSACCESS_EXECUTE)
+ NTFSbits |= FILE_GENERIC_EXECUTE;
+
+ /* For directories check the directory-specific bits */
+ if (isdir == true) {
+ if (caccess & ISC_FSACCESS_CREATECHILD)
+ NTFSbits |= FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE;
+ if (caccess & ISC_FSACCESS_DELETECHILD)
+ NTFSbits |= FILE_DELETE_CHILD;
+ if (caccess & ISC_FSACCESS_LISTDIRECTORY)
+ NTFSbits |= FILE_LIST_DIRECTORY;
+ if (caccess & ISC_FSACCESS_ACCESSCHILD)
+ NTFSbits |= FILE_TRAVERSE;
+ }
+
+ if (NTFSbits == (FILE_GENERIC_READ | FILE_GENERIC_WRITE
+ | FILE_GENERIC_EXECUTE))
+ NTFSbits |= FILE_ALL_ACCESS;
+ /*
+ * Owner and Administrator also get STANDARD_RIGHTS_ALL
+ * to ensure that they have full control
+ */
+
+ NTFSbits |= STANDARD_RIGHTS_ALL;
+
+ /* Add the ACE to the ACL */
+ if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits, psid))
+ return (ISC_R_NOPERM);
+ if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits, padminsid))
+ return (ISC_R_NOPERM);
+
+ /*
+ * Group is ignored since we can be in multiple groups or no group
+ * and its meaning is not clear on Win32
+ */
+
+ caccess = caccess >> STEP;
+
+ /*
+ * Other check. We translate this to be the same as Everyone
+ */
+
+ caccess = caccess >> STEP;
+
+ NTFSbits = 0;
+ if (caccess & ISC_FSACCESS_READ)
+ NTFSbits |= FILE_GENERIC_READ;
+ if (caccess & ISC_FSACCESS_WRITE)
+ NTFSbits |= FILE_GENERIC_WRITE;
+ if (caccess & ISC_FSACCESS_EXECUTE)
+ NTFSbits |= FILE_GENERIC_EXECUTE;
+
+ /* For directories check the directory-specific bits */
+ if (isdir == TRUE) {
+ if (caccess & ISC_FSACCESS_CREATECHILD)
+ NTFSbits |= FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE;
+ if (caccess & ISC_FSACCESS_DELETECHILD)
+ NTFSbits |= FILE_DELETE_CHILD;
+ if (caccess & ISC_FSACCESS_LISTDIRECTORY)
+ NTFSbits |= FILE_LIST_DIRECTORY;
+ if (caccess & ISC_FSACCESS_ACCESSCHILD)
+ NTFSbits |= FILE_TRAVERSE;
+ }
+ /* Add the ACE to the ACL */
+ if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits,
+ pothersid))
+ return (ISC_R_NOPERM);
+
+ if (!SetSecurityDescriptorDacl(&sd, TRUE, pacl, FALSE))
+ return (ISC_R_NOPERM);
+ if (!SetFileSecurity(filename, DACL_SECURITY_INFORMATION, &sd)) {
+ return (ISC_R_NOPERM);
+ }
+
+ return(ISC_R_SUCCESS);
+}
+
+isc_result_t
+NTFS_fsaccess_set(const char *path, isc_fsaccess_t access,
+ bool isdir){
+
+ /*
+ * For NTFS we first need to get the name of the account under
+ * which BIND is running
+ */
+ if (namelen == 0) {
+ namelen = sizeof(username);
+ if (GetUserName(username, &namelen) == 0)
+ return (ISC_R_FAILURE);
+ }
+ return (NTFS_Access_Control(path, username, access, isdir));
+}
+
+isc_result_t
+isc_fsaccess_set(const char *path, isc_fsaccess_t access) {
+ struct stat statb;
+ bool is_dir = false;
+ isc_result_t result;
+
+ if (stat(path, &statb) != 0)
+ return (isc__errno2result(errno));
+
+ if ((statb.st_mode & S_IFDIR) != 0)
+ is_dir = true;
+ else if ((statb.st_mode & S_IFREG) == 0)
+ return (ISC_R_INVALIDFILE);
+
+ result = check_bad_bits(access, is_dir);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Determine if this is a FAT or NTFS disk and
+ * call the appropriate function to set the permissions
+ */
+ if (is_ntfs(path))
+ return (NTFS_fsaccess_set(path, access, is_dir));
+ else
+ return (FAT_fsaccess_set(path, access));
+}
+
+isc_result_t
+isc_fsaccess_changeowner(const char *filename, const char *user) {
+ SECURITY_DESCRIPTOR psd;
+ BYTE sidBuffer[500];
+ BYTE groupBuffer[500];
+ PSID psid=(PSID) &sidBuffer;
+ DWORD sidBufferSize = sizeof(sidBuffer);
+ char domainBuffer[100];
+ DWORD domainBufferSize = sizeof(domainBuffer);
+ SID_NAME_USE snu;
+ PSID pSidGroup = (PSID) &groupBuffer;
+ DWORD groupBufferSize = sizeof(groupBuffer);
+
+
+ /*
+ * Determine if this is a FAT or NTFS disk and
+ * call the appropriate function to set the ownership
+ * FAT disks do not have ownership attributes so it's
+ * a noop.
+ */
+ if (is_ntfs(filename) == FALSE)
+ return (ISC_R_SUCCESS);
+
+ if (!InitializeSecurityDescriptor(&psd, SECURITY_DESCRIPTOR_REVISION))
+ return (ISC_R_NOPERM);
+
+ if (!LookupAccountName(0, user, psid, &sidBufferSize, domainBuffer,
+ &domainBufferSize, &snu))
+ return (ISC_R_NOPERM);
+
+ /* Make sure administrators can get to it */
+ domainBufferSize = sizeof(domainBuffer);
+ if (!LookupAccountName(0, "Administrators", pSidGroup,
+ &groupBufferSize, domainBuffer, &domainBufferSize, &snu))
+ return (ISC_R_NOPERM);
+
+ if (!SetSecurityDescriptorOwner(&psd, psid, FALSE))
+ return (ISC_R_NOPERM);
+
+ if (!SetSecurityDescriptorGroup(&psd, pSidGroup, FALSE))
+ return (ISC_R_NOPERM);
+
+ if (!SetFileSecurity(filename,
+ OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION,
+ &psd))
+ return (ISC_R_NOPERM);
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isc/win32/include/Makefile.in b/lib/isc/win32/include/Makefile.in
new file mode 100644
index 0000000..2cbf021
--- /dev/null
+++ b/lib/isc/win32/include/Makefile.in
@@ -0,0 +1,17 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# 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 http://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 pkcs11
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/win32/include/isc/Makefile.in b/lib/isc/win32/include/isc/Makefile.in
new file mode 100644
index 0000000..a7c0243
--- /dev/null
+++ b/lib/isc/win32/include/isc/Makefile.in
@@ -0,0 +1,30 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# 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 http://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@
+
+HEADERS = dir.h keyboard.h mutex.h net.h netdb.h once.h \
+ stat.h stdtime.h thread.h time.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 $(includedir)\isc || exit 1; \
+ done
diff --git a/lib/isc/win32/include/isc/atomic.h b/lib/isc/win32/include/isc/atomic.h
new file mode 100644
index 0000000..4b3d92d
--- /dev/null
+++ b/lib/isc/win32/include/isc/atomic.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+#include <inttypes.h>
+
+#include <isc/platform.h>
+#include <isc/types.h>
+
+/*
+ * This routine atomically increments the value stored in 'p' by 'val', and
+ * returns the previous value.
+ */
+#ifdef ISC_PLATFORM_HAVEXADD
+static __inline int32_t
+isc_atomic_xadd(int32_t *p, int32_t val) {
+ return (int32_t) _InterlockedExchangeAdd((long *)p, (long)val);
+}
+#endif
+
+#ifdef ISC_PLATFORM_HAVEXADDQ
+static __inline int64_t
+isc_atomic_xaddq(int64_t *p, int64_t val) {
+ return (int64_t) _InterlockedExchangeAdd64((__int64 *)p,
+ (__int64) val);
+}
+#endif
+
+/*
+ * This routine atomically stores the value 'val' in 'p' (32-bit version).
+ */
+#ifdef ISC_PLATFORM_HAVEATOMICSTORE
+static __inline void
+isc_atomic_store(int32_t *p, int32_t val) {
+ (void) _InterlockedExchange((long *)p, (long)val);
+}
+#endif
+
+/*
+ * This routine atomically stores the value 'val' in 'p' (64-bit version).
+ */
+#ifdef ISC_PLATFORM_HAVEATOMICSTOREQ
+static __inline void
+isc_atomic_storeq(int64_t *p, int64_t val) {
+ (void) _InterlockedExchange64((__int64 *)p, (__int64)val);
+}
+#endif
+
+/*
+ * This routine atomically replaces the value in 'p' with 'val', if the
+ * original value is equal to 'cmpval'. The original value is returned in any
+ * case.
+ */
+#ifdef ISC_PLATFORM_HAVECMPXCHG
+static __inline int32_t
+isc_atomic_cmpxchg(int32_t *p, int32_t cmpval, int32_t val) {
+ /* beware: swap arguments */
+ return (int32_t) _InterlockedCompareExchange((long *)p,
+ (long)val,
+ (long)cmpval);
+}
+#endif
+
+#endif /* ISC_ATOMIC_H */
diff --git a/lib/isc/win32/include/isc/bind_registry.h b/lib/isc/win32/include/isc/bind_registry.h
new file mode 100644
index 0000000..57970be
--- /dev/null
+++ b/lib/isc/win32/include/isc/bind_registry.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_BINDREGISTRY_H
+#define ISC_BINDREGISTRY_H
+
+/*
+ * BIND makes use of the following Registry keys in various places, especially
+ * during startup and installation
+ */
+
+#define BIND_SUBKEY "Software\\ISC\\BIND"
+#define BIND_SESSION "CurrentSession"
+#define BIND_SESSION_SUBKEY "Software\\ISC\\BIND\\CurrentSession"
+#define BIND_UNINSTALL_SUBKEY \
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ISC BIND"
+
+#define EVENTLOG_APP_SUBKEY \
+ "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application"
+#define BIND_MESSAGE_SUBKEY \
+ "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\named"
+#define BIND_MESSAGE_NAME "named"
+
+#define BIND_SERVICE_SUBKEY \
+ "SYSTEM\\CurrentControlSet\\Services\\named"
+
+
+#define BIND_CONFIGFILE 0
+#define BIND_DEBUGLEVEL 1
+#define BIND_QUERYLOG 2
+#define BIND_FOREGROUND 3
+#define BIND_PORT 4
+
+#endif /* ISC_BINDREGISTRY_H */
diff --git a/lib/isc/win32/include/isc/bindevt.h b/lib/isc/win32/include/isc/bindevt.h
new file mode 100644
index 0000000..d4088e8
--- /dev/null
+++ b/lib/isc/win32/include/isc/bindevt.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_BINDEVT_H
+#define ISC_BINDEVT_H 1
+
+/*
+ * This is used for the event log for both logging the messages and
+ * later on by the event viewer when looking at the events
+ */
+
+/*
+ * Values are 32 bit values layed out as follows:
+ *
+ * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +---+-+-+-----------------------+-------------------------------+
+ * |Sev|C|R| Facility | Code |
+ * +---+-+-+-----------------------+-------------------------------+
+ *
+ * where
+ *
+ * Sev - is the severity code
+ *
+ * 00 - Success
+ * 01 - Informational
+ * 10 - Warning
+ * 11 - Error
+ *
+ * C - is the Customer code flag
+ *
+ * R - is a reserved bit
+ *
+ * Facility - is the facility code
+ *
+ * Code - is the facility's status code
+ *
+ *
+ * Define the facility codes
+ */
+
+
+/*
+ * Define the severity codes
+ */
+
+
+/*
+ * MessageId: BIND_ERR_MSG
+ *
+ * MessageText:
+ *
+ * %1
+ */
+#define BIND_ERR_MSG ((DWORD)0xC0000001L)
+
+/*
+ * MessageId: BIND_WARN_MSG
+ *
+ * MessageText:
+ *
+ * %1
+ */
+#define BIND_WARN_MSG ((DWORD)0x80000002L)
+
+/*
+ * MessageId: BIND_INFO_MSG
+ *
+ * MessageText:
+ *
+ * %1
+ */
+#define BIND_INFO_MSG ((DWORD)0x40000003L)
+
+#endif /* ISC_BINDEVT_H */
diff --git a/lib/isc/win32/include/isc/condition.h b/lib/isc/win32/include/isc/condition.h
new file mode 100644
index 0000000..1f5b2d6
--- /dev/null
+++ b/lib/isc/win32/include/isc/condition.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_CONDITION_H
+#define ISC_CONDITION_H 1
+
+#include <windows.h>
+
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/thread.h>
+#include <isc/types.h>
+
+typedef struct isc_condition_thread isc_condition_thread_t;
+
+struct isc_condition_thread {
+ unsigned long th;
+ HANDLE handle[2];
+ ISC_LINK(isc_condition_thread_t) link;
+
+};
+
+typedef struct isc_condition {
+ HANDLE events[2];
+ unsigned int waiters;
+ ISC_LIST(isc_condition_thread_t) threadlist;
+} isc_condition_t;
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_condition_init(isc_condition_t *);
+
+isc_result_t
+isc_condition_wait(isc_condition_t *, isc_mutex_t *);
+
+isc_result_t
+isc_condition_signal(isc_condition_t *);
+
+isc_result_t
+isc_condition_broadcast(isc_condition_t *);
+
+isc_result_t
+isc_condition_destroy(isc_condition_t *);
+
+isc_result_t
+isc_condition_waituntil(isc_condition_t *, isc_mutex_t *, isc_time_t *);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_CONDITION_H */
diff --git a/lib/isc/win32/include/isc/dir.h b/lib/isc/win32/include/isc/dir.h
new file mode 100644
index 0000000..7370fa6
--- /dev/null
+++ b/lib/isc/win32/include/isc/dir.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef ISC_DIR_H
+#define ISC_DIR_H 1
+
+#include <windows.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+#define ISC_DIR_NAMEMAX _MAX_FNAME
+#define ISC_DIR_PATHMAX _MAX_PATH
+
+typedef struct {
+ char name[ISC_DIR_NAMEMAX];
+ unsigned int length;
+ WIN32_FIND_DATA find_data;
+} isc_direntry_t;
+
+typedef struct {
+ unsigned int magic;
+ char dirname[ISC_DIR_PATHMAX];
+ isc_direntry_t entry;
+ bool entry_filled;
+ HANDLE search_handle;
+} isc_dir_t;
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_dir_init(isc_dir_t *dir);
+
+isc_result_t
+isc_dir_open(isc_dir_t *dir, const char *dirname);
+
+isc_result_t
+isc_dir_read(isc_dir_t *dir);
+
+isc_result_t
+isc_dir_reset(isc_dir_t *dir);
+
+void
+isc_dir_close(isc_dir_t *dir);
+
+isc_result_t
+isc_dir_chdir(const char *dirname);
+
+isc_result_t
+isc_dir_chroot(const char *dirname);
+
+isc_result_t
+isc_dir_createunique(char *templet);
+/*
+ * Use a templet (such as from isc_file_mktemplate()) to create a uniquely
+ * named, empty directory. The templet string is modified in place.
+ * If result == ISC_R_SUCCESS, it is the name of the directory that was
+ * created.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_DIR_H */
diff --git a/lib/isc/win32/include/isc/ipv6.h b/lib/isc/win32/include/isc/ipv6.h
new file mode 100644
index 0000000..bee1bd0
--- /dev/null
+++ b/lib/isc/win32/include/isc/ipv6.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_IPV6_H
+#define ISC_IPV6_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*
+ * IPv6 definitions for systems which do not support IPv6.
+ *
+ * MP:
+ * No impact.
+ *
+ * Reliability:
+ * No anticipated impact.
+ *
+ * Resources:
+ * N/A.
+ *
+ * Security:
+ * No anticipated impact.
+ *
+ * Standards:
+ * RFC2553.
+ */
+
+#if _MSC_VER < 1300
+#define in6_addr in_addr6
+#endif
+
+#ifndef IN6ADDR_ANY_INIT
+#define IN6ADDR_ANY_INIT {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}
+#endif
+#ifndef IN6ADDR_LOOPBACK_INIT
+#define IN6ADDR_LOOPBACK_INIT {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}
+#endif
+#ifndef IN6ADDR_V4MAPPED_INIT
+#define IN6ADDR_V4MAPPED_INIT {{ 0,0,0,0,0,0,0,0,0,0,0xff,0xff,0,0,0,0 }}
+#endif
+
+LIBISC_EXTERNAL_DATA extern const struct in6_addr isc_in6addr_any;
+LIBISC_EXTERNAL_DATA extern const struct in6_addr isc_in6addr_loopback;
+
+/*
+ * Unspecified
+ */
+#ifndef IN6_IS_ADDR_UNSPECIFIED
+#define IN6_IS_ADDR_UNSPECIFIED(a) (\
+*((u_long *)((a)->s6_addr) ) == 0 && \
+*((u_long *)((a)->s6_addr) + 1) == 0 && \
+*((u_long *)((a)->s6_addr) + 2) == 0 && \
+*((u_long *)((a)->s6_addr) + 3) == 0 \
+)
+#endif
+
+/*
+ * Loopback
+ */
+#ifndef IN6_IS_ADDR_LOOPBACK
+#define IN6_IS_ADDR_LOOPBACK(a) (\
+*((u_long *)((a)->s6_addr) ) == 0 && \
+*((u_long *)((a)->s6_addr) + 1) == 0 && \
+*((u_long *)((a)->s6_addr) + 2) == 0 && \
+*((u_long *)((a)->s6_addr) + 3) == htonl(1) \
+)
+#endif
+
+/*
+ * IPv4 compatible
+ */
+#define IN6_IS_ADDR_V4COMPAT(a) (\
+*((u_long *)((a)->s6_addr) ) == 0 && \
+*((u_long *)((a)->s6_addr) + 1) == 0 && \
+*((u_long *)((a)->s6_addr) + 2) == 0 && \
+*((u_long *)((a)->s6_addr) + 3) != 0 && \
+*((u_long *)((a)->s6_addr) + 3) != htonl(1) \
+)
+
+/*
+ * Mapped
+ */
+#define IN6_IS_ADDR_V4MAPPED(a) (\
+*((u_long *)((a)->s6_addr) ) == 0 && \
+*((u_long *)((a)->s6_addr) + 1) == 0 && \
+*((u_long *)((a)->s6_addr) + 2) == htonl(0x0000ffff))
+
+/*
+ * Multicast
+ */
+#define IN6_IS_ADDR_MULTICAST(a) \
+ ((a)->s6_addr[0] == 0xffU)
+
+/*
+ * Unicast link / site local.
+ */
+#ifndef IN6_IS_ADDR_LINKLOCAL
+#define IN6_IS_ADDR_LINKLOCAL(a) (\
+ ((a)->s6_addr[0] == 0xfe) && \
+ (((a)->s6_addr[1] & 0xc0) == 0x80))
+#endif
+
+#ifndef IN6_IS_ADDR_SITELOCAL
+#define IN6_IS_ADDR_SITELOCAL(a) (\
+ ((a)->s6_addr[0] == 0xfe) && \
+ (((a)->s6_addr[1] & 0xc0) == 0xc0))
+#endif
+
+#endif /* ISC_IPV6_H */
diff --git a/lib/isc/win32/include/isc/keyboard.h b/lib/isc/win32/include/isc/keyboard.h
new file mode 100644
index 0000000..009523a
--- /dev/null
+++ b/lib/isc/win32/include/isc/keyboard.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_KEYBOARD_H
+#define ISC_KEYBOARD_H 1
+
+#include <stdbool.h>
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef struct {
+ int fd;
+ isc_result_t result;
+} isc_keyboard_t;
+
+isc_result_t
+isc_keyboard_open(isc_keyboard_t *keyboard);
+
+isc_result_t
+isc_keyboard_close(isc_keyboard_t *keyboard, unsigned int sleepseconds);
+
+isc_result_t
+isc_keyboard_getchar(isc_keyboard_t *keyboard, unsigned char *cp);
+
+bool
+isc_keyboard_canceled(isc_keyboard_t *keyboard);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_KEYBOARD_H */
diff --git a/lib/isc/win32/include/isc/mutex.h b/lib/isc/win32/include/isc/mutex.h
new file mode 100644
index 0000000..6815741
--- /dev/null
+++ b/lib/isc/win32/include/isc/mutex.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_MUTEX_H
+#define ISC_MUTEX_H 1
+
+#include <isc/net.h>
+#include <windows.h>
+
+#include <isc/result.h>
+
+typedef CRITICAL_SECTION isc_mutex_t;
+
+/*
+ * This definition is here since some versions of WINBASE.H
+ * omits it for some reason.
+ */
+#if (_WIN32_WINNT < 0x0400)
+WINBASEAPI BOOL WINAPI
+TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
+#endif /* _WIN32_WINNT < 0x0400 */
+
+#define isc_mutex_init(mp) \
+ (InitializeCriticalSection((mp)), ISC_R_SUCCESS)
+#define isc_mutex_lock(mp) \
+ (EnterCriticalSection((mp)), ISC_R_SUCCESS)
+#define isc_mutex_unlock(mp) \
+ (LeaveCriticalSection((mp)), ISC_R_SUCCESS)
+#define isc_mutex_trylock(mp) \
+ (TryEnterCriticalSection((mp)) ? ISC_R_SUCCESS : ISC_R_LOCKBUSY)
+#define isc_mutex_destroy(mp) \
+ (DeleteCriticalSection((mp)), ISC_R_SUCCESS)
+
+/*
+ * This is a placeholder for now since we are not keeping any mutex stats
+ */
+#define isc_mutex_stats(fp) do {} while (0)
+
+#endif /* ISC_MUTEX_H */
diff --git a/lib/isc/win32/include/isc/net.h b/lib/isc/win32/include/isc/net.h
new file mode 100644
index 0000000..9712a6a
--- /dev/null
+++ b/lib/isc/win32/include/isc/net.h
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* $Id$ */
+
+#ifndef ISC_NET_H
+#define ISC_NET_H 1
+
+/*
+ * Also define LWRES_IPV6_H to keep it from being included if liblwres is
+ * being used, or redefinition errors will occur.
+ */
+#define LWRES_IPV6_H 1
+
+
+
+/*****
+ ***** Module Info
+ *****/
+
+/*
+ * Basic Networking Types
+ *
+ * This module is responsible for defining the following basic networking
+ * types:
+ *
+ * struct in_addr
+ * struct in6_addr
+ * struct in6_pktinfo
+ * struct sockaddr
+ * struct sockaddr_in
+ * struct sockaddr_in6
+ * in_port_t
+ *
+ * It ensures that the AF_ and PF_ macros are defined.
+ *
+ * It declares ntoh[sl]() and hton[sl]().
+ *
+ * It declares inet_aton(), inet_ntop(), and inet_pton().
+ *
+ * It ensures that INADDR_ANY, IN6ADDR_ANY_INIT, in6addr_any, and
+ * in6addr_loopback are available.
+ *
+ * It ensures that IN_MULTICAST() is available to check for multicast
+ * addresses.
+ *
+ * MP:
+ * No impact.
+ *
+ * Reliability:
+ * No anticipated impact.
+ *
+ * Resources:
+ * N/A.
+ *
+ * Security:
+ * No anticipated impact.
+ *
+ * Standards:
+ * BSD Socket API
+ * RFC2553
+ */
+
+/***
+ *** Imports.
+ ***/
+#include <inttypes.h>
+
+#include <isc/platform.h>
+
+/*
+ * Because of some sort of problem in the MS header files, this cannot
+ * be simple "#include <winsock2.h>", because winsock2.h tries to include
+ * windows.h, which then generates an error out of mswsock.h. _You_
+ * figure it out.
+ */
+#ifndef _WINSOCKAPI_
+#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
+#endif
+
+#include <winsock2.h>
+
+#include <sys/types.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#include <ws2tcpip.h>
+#include <isc/ipv6.h>
+
+/*
+ * This is here because named client, interfacemgr.c, etc. use the name as
+ * a variable
+ */
+#undef interface
+
+#ifndef INADDR_ANY
+#define INADDR_ANY 0x00000000UL
+#endif
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK 0x7f000001UL
+#endif
+
+#ifndef ISC_PLATFORM_HAVEIN6PKTINFO
+struct in6_pktinfo {
+ struct in6_addr ipi6_addr; /* src/dst IPv6 address */
+ unsigned int ipi6_ifindex; /* send/recv interface index */
+};
+#endif
+
+#if _MSC_VER < 1300
+#define in6addr_any isc_in6addr_any
+#define in6addr_loopback isc_in6addr_loopback
+#endif
+
+/*
+ * Ensure type in_port_t is defined.
+ */
+#ifdef ISC_PLATFORM_NEEDPORTT
+typedef uint16_t in_port_t;
+#endif
+
+/*
+ * If this system does not have MSG_TRUNC (as returned from recvmsg())
+ * ISC_PLATFORM_RECVOVERFLOW will be defined. This will enable the MSG_TRUNC
+ * faking code in socket.c.
+ */
+#ifndef MSG_TRUNC
+#define ISC_PLATFORM_RECVOVERFLOW
+#endif
+
+#define ISC__IPADDR(x) ((uint32_t)htonl((uint32_t)(x)))
+
+#define ISC_IPADDR_ISMULTICAST(i) \
+ (((uint32_t)(i) & ISC__IPADDR(0xf0000000)) \
+ == ISC__IPADDR(0xe0000000))
+
+#define ISC_IPADDR_ISEXPERIMENTAL(i) \
+ (((uint32_t)(i) & ISC__IPADDR(0xf0000000)) \
+ == ISC__IPADDR(0xf0000000))
+
+/*
+ * Fix the FD_SET and FD_CLR Macros to properly cast
+ */
+#undef FD_CLR
+#define FD_CLR(fd, set) do { \
+ u_int __i; \
+ for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count; __i++) { \
+ if (((fd_set FAR *)(set))->fd_array[__i] == (SOCKET) fd) { \
+ while (__i < ((fd_set FAR *)(set))->fd_count-1) { \
+ ((fd_set FAR *)(set))->fd_array[__i] = \
+ ((fd_set FAR *)(set))->fd_array[__i+1]; \
+ __i++; \
+ } \
+ ((fd_set FAR *)(set))->fd_count--; \
+ break; \
+ } \
+ } \
+} while (0)
+
+#undef FD_SET
+#define FD_SET(fd, set) do { \
+ u_int __i; \
+ for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count; __i++) { \
+ if (((fd_set FAR *)(set))->fd_array[__i] == (SOCKET)(fd)) { \
+ break; \
+ } \
+ } \
+ if (__i == ((fd_set FAR *)(set))->fd_count) { \
+ if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) { \
+ ((fd_set FAR *)(set))->fd_array[__i] = (SOCKET)(fd); \
+ ((fd_set FAR *)(set))->fd_count++; \
+ } \
+ } \
+} while (0)
+
+/*
+ * Windows Sockets errors redefined as regular Berkeley error constants.
+ * These are usually commented out in Windows NT to avoid conflicts with errno.h.
+ * Use the WSA constants instead.
+ */
+
+#include <errno.h>
+
+#ifndef EWOULDBLOCK
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#endif
+#ifndef EINPROGRESS
+#define EINPROGRESS WSAEINPROGRESS
+#endif
+#ifndef EALREADY
+#define EALREADY WSAEALREADY
+#endif
+#ifndef ENOTSOCK
+#define ENOTSOCK WSAENOTSOCK
+#endif
+#ifndef EDESTADDRREQ
+#define EDESTADDRREQ WSAEDESTADDRREQ
+#endif
+#ifndef EMSGSIZE
+#define EMSGSIZE WSAEMSGSIZE
+#endif
+#ifndef EPROTOTYPE
+#define EPROTOTYPE WSAEPROTOTYPE
+#endif
+#ifndef ENOPROTOOPT
+#define ENOPROTOOPT WSAENOPROTOOPT
+#endif
+#ifndef EPROTONOSUPPORT
+#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+#endif
+#ifndef ESOCKTNOSUPPORT
+#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+#endif
+#ifndef EOPNOTSUPP
+#define EOPNOTSUPP WSAEOPNOTSUPP
+#endif
+#ifndef EPFNOSUPPORT
+#define EPFNOSUPPORT WSAEPFNOSUPPORT
+#endif
+#ifndef EAFNOSUPPORT
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#endif
+#ifndef EADDRINUSE
+#define EADDRINUSE WSAEADDRINUSE
+#endif
+#ifndef EADDRNOTAVAIL
+#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#endif
+#ifndef ENETDOWN
+#define ENETDOWN WSAENETDOWN
+#endif
+#ifndef ENETUNREACH
+#define ENETUNREACH WSAENETUNREACH
+#endif
+#ifndef ENETRESET
+#define ENETRESET WSAENETRESET
+#endif
+#ifndef ECONNABORTED
+#define ECONNABORTED WSAECONNABORTED
+#endif
+#ifndef ECONNRESET
+#define ECONNRESET WSAECONNRESET
+#endif
+#ifndef ENOBUFS
+#define ENOBUFS WSAENOBUFS
+#endif
+#ifndef EISCONN
+#define EISCONN WSAEISCONN
+#endif
+#ifndef ENOTCONN
+#define ENOTCONN WSAENOTCONN
+#endif
+#ifndef ESHUTDOWN
+#define ESHUTDOWN WSAESHUTDOWN
+#endif
+#ifndef ETOOMANYREFS
+#define ETOOMANYREFS WSAETOOMANYREFS
+#endif
+#ifndef ETIMEDOUT
+#define ETIMEDOUT WSAETIMEDOUT
+#endif
+#ifndef ECONNREFUSED
+#define ECONNREFUSED WSAECONNREFUSED
+#endif
+#ifndef ELOOP
+#define ELOOP WSAELOOP
+#endif
+#ifndef EHOSTDOWN
+#define EHOSTDOWN WSAEHOSTDOWN
+#endif
+#ifndef EHOSTUNREACH
+#define EHOSTUNREACH WSAEHOSTUNREACH
+#endif
+#ifndef EPROCLIM
+#define EPROCLIM WSAEPROCLIM
+#endif
+#ifndef EUSERS
+#define EUSERS WSAEUSERS
+#endif
+#ifndef EDQUOT
+#define EDQUOT WSAEDQUOT
+#endif
+#ifndef ESTALE
+#define ESTALE WSAESTALE
+#endif
+#ifndef EREMOTE
+#define EREMOTE WSAEREMOTE
+#endif
+
+
+/***
+ *** Functions.
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_net_probeipv4(void);
+/*
+ * Check if the system's kernel supports IPv4.
+ *
+ * Returns:
+ *
+ * ISC_R_SUCCESS IPv4 is supported.
+ * ISC_R_NOTFOUND IPv4 is not supported.
+ * ISC_R_DISABLED IPv4 is disabled.
+ * ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_net_probeipv6(void);
+/*
+ * Check if the system's kernel supports IPv6.
+ *
+ * Returns:
+ *
+ * ISC_R_SUCCESS IPv6 is supported.
+ * ISC_R_NOTFOUND IPv6 is not supported.
+ * ISC_R_DISABLED IPv6 is disabled.
+ * ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_net_probeunix(void);
+/*
+ * Check if UNIX domain sockets are supported.
+ *
+ * Returns:
+ *
+ * ISC_R_SUCCESS
+ * ISC_R_NOTFOUND
+ */
+
+#define ISC_NET_DSCPRECVV4 0x01 /* Can receive sent DSCP value IPv4 */
+#define ISC_NET_DSCPRECVV6 0x02 /* Can receive sent DSCP value IPv6 */
+#define ISC_NET_DSCPSETV4 0x04 /* Can set DSCP on socket IPv4 */
+#define ISC_NET_DSCPSETV6 0x08 /* Can set DSCP on socket IPv6 */
+#define ISC_NET_DSCPPKTV4 0x10 /* Can set DSCP on per packet IPv4 */
+#define ISC_NET_DSCPPKTV6 0x20 /* Can set DSCP on per packet IPv6 */
+#define ISC_NET_DSCPALL 0x3f /* All valid flags */
+
+unsigned int
+isc_net_probedscp(void);
+/*%<
+ * Probe the level of DSCP support.
+ */
+
+isc_result_t
+isc_net_probe_ipv6only(void);
+/*
+ * Check if the system's kernel supports the IPV6_V6ONLY socket option.
+ *
+ * Returns:
+ *
+ * ISC_R_SUCCESS the option is supported for both TCP and UDP.
+ * ISC_R_NOTFOUND IPv6 itself or the option is not supported.
+ * ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_net_probe_ipv6pktinfo(void);
+/*
+ * Check if the system's kernel supports the IPV6_(RECV)PKTINFO socket option
+ * for UDP sockets.
+ *
+ * Returns:
+ *
+ * ISC_R_SUCCESS the option is supported.
+ * ISC_R_NOTFOUND IPv6 itself or the option is not supported.
+ * ISC_R_UNEXPECTED
+ */
+
+void
+isc_net_disableipv4(void);
+
+void
+isc_net_disableipv6(void);
+
+void
+isc_net_enableipv4(void);
+
+void
+isc_net_enableipv6(void);
+
+isc_result_t
+isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high);
+/*%<
+ * Returns system's default range of ephemeral UDP ports, if defined.
+ * If the range is not available or unknown, ISC_NET_PORTRANGELOW and
+ * ISC_NET_PORTRANGEHIGH will be returned.
+ *
+ * Requires:
+ *
+ *\li 'low' and 'high' must be non NULL.
+ *
+ * Returns:
+ *
+ *\li *low and *high will be the ports specifying the low and high ends of
+ * the range.
+ */
+
+#ifdef ISC_PLATFORM_NEEDNTOP
+const char *
+isc_net_ntop(int af, const void *src, char *dst, size_t size);
+#undef inet_ntop
+#define inet_ntop isc_net_ntop
+#endif
+
+#ifdef ISC_PLATFORM_NEEDPTON
+int
+isc_net_pton(int af, const char *src, void *dst);
+#define inet_pton isc_net_pton
+#endif
+
+int
+isc_net_aton(const char *cp, struct in_addr *addr);
+#define inet_aton isc_net_aton
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NET_H */
diff --git a/lib/isc/win32/include/isc/netdb.h b/lib/isc/win32/include/isc/netdb.h
new file mode 100644
index 0000000..c07194d
--- /dev/null
+++ b/lib/isc/win32/include/isc/netdb.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_NETDB_H
+#define ISC_NETDB_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*
+ * Portable netdb.h support.
+ *
+ * This module is responsible for defining the get<x>by<y> APIs.
+ *
+ * MP:
+ * No impact.
+ *
+ * Reliability:
+ * No anticipated impact.
+ *
+ * Resources:
+ * N/A.
+ *
+ * Security:
+ * No anticipated impact.
+ *
+ * Standards:
+ * BSD API
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/net.h>
+
+#endif /* ISC_NETDB_H */
diff --git a/lib/isc/win32/include/isc/ntgroups.h b/lib/isc/win32/include/isc/ntgroups.h
new file mode 100644
index 0000000..e8352fc
--- /dev/null
+++ b/lib/isc/win32/include/isc/ntgroups.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_NTGROUPS_H
+#define ISC_NTGROUPS_H 1
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+
+isc_result_t
+isc_ntsecurity_getaccountgroups(char *name, char **Groups, unsigned int maxgroups,
+ unsigned int *total);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NTGROUPS_H */
diff --git a/lib/isc/win32/include/isc/ntpaths.h b/lib/isc/win32/include/isc/ntpaths.h
new file mode 100644
index 0000000..c0010fc
--- /dev/null
+++ b/lib/isc/win32/include/isc/ntpaths.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*
+ * Windows-specific path definitions
+ * These routines are used to set up and return system-specific path
+ * information about the files enumerated in NtPaths
+ */
+
+#ifndef ISC_NTPATHS_H
+#define ISC_NTPATHS_H
+
+#include <isc/lang.h>
+
+/*
+ * Index of paths needed
+ */
+enum NtPaths {
+ NAMED_CONF_PATH,
+ LWRES_CONF_PATH,
+ RESOLV_CONF_PATH,
+ RNDC_CONF_PATH,
+ NAMED_PID_PATH,
+ LWRESD_PID_PATH,
+ NAMED_LOCK_PATH,
+ LOCAL_STATE_DIR,
+ SYS_CONF_DIR,
+ RNDC_KEY_PATH,
+ SESSION_KEY_PATH
+};
+
+/*
+ * Define macros to get the path of the config files
+ */
+#define NAMED_CONFFILE isc_ntpaths_get(NAMED_CONF_PATH)
+#define RNDC_CONFFILE isc_ntpaths_get(RNDC_CONF_PATH)
+#define RNDC_KEYFILE isc_ntpaths_get(RNDC_KEY_PATH)
+#define SESSION_KEYFILE isc_ntpaths_get(SESSION_KEY_PATH)
+#define RESOLV_CONF isc_ntpaths_get(RESOLV_CONF_PATH)
+
+/*
+ * Information about where the files are on disk
+ */
+#define NS_LOCALSTATEDIR "/dns/bin"
+#define NS_SYSCONFDIR "/dns/etc"
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_ntpaths_init(void);
+
+char *
+isc_ntpaths_get(int);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NTPATHS_H */
diff --git a/lib/isc/win32/include/isc/offset.h b/lib/isc/win32/include/isc/offset.h
new file mode 100644
index 0000000..14ef06f
--- /dev/null
+++ b/lib/isc/win32/include/isc/offset.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_OFFSET_H
+#define ISC_OFFSET_H 1
+
+/*
+ * File offsets are operating-system dependent.
+ */
+#include <limits.h> /* Required for CHAR_BIT. */
+#include <sys/types.h>
+
+typedef _off_t isc_offset_t;
+
+#endif /* ISC_OFFSET_H */
diff --git a/lib/isc/win32/include/isc/once.h b/lib/isc/win32/include/isc/once.h
new file mode 100644
index 0000000..c005b0b
--- /dev/null
+++ b/lib/isc/win32/include/isc/once.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_ONCE_H
+#define ISC_ONCE_H 1
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef struct {
+ int status;
+ int counter;
+} isc_once_t;
+
+#define ISC_ONCE_INIT_NEEDED 0
+#define ISC_ONCE_INIT_DONE 1
+
+#define ISC_ONCE_INIT { ISC_ONCE_INIT_NEEDED, 1 }
+
+isc_result_t
+isc_once_do(isc_once_t *controller, void(*function)(void));
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_ONCE_H */
diff --git a/lib/isc/win32/include/isc/platform.h.in b/lib/isc/win32/include/isc/platform.h.in
new file mode 100644
index 0000000..5b8a2c9
--- /dev/null
+++ b/lib/isc/win32/include/isc/platform.h.in
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://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
+
+/*****
+ ***** Platform-dependent defines.
+ *****/
+
+#define ISC_PLATFORM_USETHREADS 1
+
+/***
+ *** Network.
+ ***/
+
+#ifndef PATH_MAX
+#define PATH_MAX _MAX_PATH
+#endif
+
+#define ISC_PLATFORM_HAVEIPV6
+#if _MSC_VER > 1200
+#define ISC_PLATFORM_HAVEIN6PKTINFO
+#endif
+#define ISC_PLATFORM_HAVESCOPEID
+#define ISC_PLATFORM_NEEDPORTT
+#undef MSG_TRUNC
+#define ISC_PLATFORM_NEEDNTOP
+#define ISC_PLATFORM_NEEDPTON
+#define ISC_PLATFORM_HAVESOCKADDRSTORAGE
+
+#define ISC_PLATFORM_NEEDSTRSEP
+#define ISC_PLATFORM_NEEDSTRLCPY
+#define ISC_PLATFORM_NEEDSTRLCAT
+#define ISC_PLATFORM_NEEDSTRLCPY
+
+/*
+ * Used to control how extern data is linked; needed for Win32 platforms.
+ */
+#define ISC_PLATFORM_USEDECLSPEC 1
+
+/*
+ * Define this here for now as winsock2.h defines h_errno
+ * and we don't want to redeclare it.
+ */
+#define ISC_PLATFORM_NONSTDHERRNO
+
+/*
+ * Define if the platform has <sys/un.h>.
+ */
+#undef ISC_PLATFORM_HAVESYSUNH
+
+/*
+ * Define if we want to log backtrace
+ */
+@ISC_PLATFORM_USEBACKTRACE@
+
+/*
+ * Defines for the noreturn attribute.
+ */
+#define ISC_PLATFORM_NORETURN_PRE __declspec(noreturn)
+#define ISC_PLATFORM_NORETURN_POST
+
+/*
+ * Define if the hash functions must be provided by OpenSSL.
+ */
+@ISC_PLATFORM_OPENSSLHASH@
+
+/*
+ * Define if AES support is wanted
+ */
+@ISC_PLATFORM_WANTAES@
+
+/*
+ * If the "xadd" operation is available on this architecture,
+ * ISC_PLATFORM_HAVEXADD will be defined.
+ */
+@ISC_PLATFORM_HAVEXADD@
+
+/*
+ * If the "xaddq" operation (64bit xadd) is available on this architecture,
+ * ISC_PLATFORM_HAVEXADDQ will be defined.
+ */
+@ISC_PLATFORM_HAVEXADDQ@
+
+/*
+ * If the "atomic swap" operation is available on this architecture,
+ * ISC_PLATFORM_HAVEATOMICSTORE" will be defined.
+ */
+@ISC_PLATFORM_HAVEATOMICSTORE@
+
+/*
+ * If the "compare-and-exchange" operation is available on this architecture,
+ * ISC_PLATFORM_HAVECMPXCHG will be defined.
+ */
+@ISC_PLATFORM_HAVECMPXCHG@
+
+/*
+ * Define with the busy wait nop asm or function call.
+ */
+@ISC_PLATFORM_BUSYWAITNOP@
+
+/*
+ * If the strcasestr() operation is not available on this platform,
+ * ISC_PLATFORM_NEEDSTRCASESTR will be defined.
+ */
+@ISC_PLATFORM_NEEDSTRCASESTR@
+
+/*
+ * Set up a macro for importing and exporting from the DLL
+ */
+
+#ifdef LIBISC_EXPORTS
+#define LIBISC_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISC_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#ifdef LIBDNS_EXPORTS
+#define LIBDNS_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBDNS_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#ifdef LIBISCCC_EXPORTS
+#define LIBISCCC_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISCCC_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#ifdef LIBISCCFG_EXPORTS
+#define LIBISCCFG_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISCCFG_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#ifdef LIBBIND9_EXPORTS
+#define LIBBIND9_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBBIND9_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#ifdef LIBTESTS_EXPORTS
+#define LIBTESTS_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBTESTS_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#endif /* ISC_PLATFORM_H */
diff --git a/lib/isc/win32/include/isc/stat.h b/lib/isc/win32/include/isc/stat.h
new file mode 100644
index 0000000..8b7d685
--- /dev/null
+++ b/lib/isc/win32/include/isc/stat.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_STAT_H
+#define ISC_STAT_H 1
+
+#include <sys/stat.h>
+
+/*
+ * Windows doesn't typedef this.
+ */
+typedef unsigned short mode_t;
+
+/* open() under unix allows setting of read/write permissions
+ * at the owner, group and other levels. These don't exist in NT
+ * We'll just map them all to the NT equivalent
+ */
+
+#define S_IREAD _S_IREAD /* read permission, owner */
+#define S_IWRITE _S_IWRITE /* write permission, owner */
+#define S_IRUSR _S_IREAD /* Owner read permission */
+#define S_IWUSR _S_IWRITE /* Owner write permission */
+#define S_IRGRP _S_IREAD /* Group read permission */
+#define S_IWGRP _S_IWRITE /* Group write permission */
+#define S_IROTH _S_IREAD /* Other read permission */
+#define S_IWOTH _S_IWRITE /* Other write permission */
+
+#ifndef S_IFMT
+# define S_IFMT _S_IFMT
+#endif
+#ifndef S_IFDIR
+# define S_IFDIR _S_IFDIR
+#endif
+#ifndef S_IFCHR
+# define S_IFCHR _S_IFCHR
+#endif
+#ifndef S_IFREG
+# define S_IFREG _S_IFREG
+#endif
+
+#ifndef S_ISDIR
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+#ifndef S_ISREG
+# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+
+#endif /* ISC_STAT_H */
diff --git a/lib/isc/win32/include/isc/stdtime.h b/lib/isc/win32/include/isc/stdtime.h
new file mode 100644
index 0000000..e11647f
--- /dev/null
+++ b/lib/isc/win32/include/isc/stdtime.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_STDTIME_H
+#define ISC_STDTIME_H 1
+
+#include <isc/lang.h>
+#include <inttypes.h>
+
+/*
+ * It's public information that 'isc_stdtime_t' is an unsigned integral type.
+ * Applications that want maximum portability should not assume anything
+ * about its size.
+ */
+typedef uint32_t isc_stdtime_t;
+
+/* but this flag helps... */
+#define STDTIME_ON_32BITS 1
+
+/*
+ * isc_stdtime32_t is a 32-bit version of isc_stdtime_t. A variable of this
+ * type should only be used as an opaque integer (e.g.,) to compare two
+ * time values.
+ */
+typedef uint32_t isc_stdtime32_t;
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_stdtime_get(isc_stdtime_t *t);
+/*
+ * Set 't' to the number of seconds since 00:00:00 UTC, January 1, 1970.
+ *
+ * Requires:
+ *
+ * 't' is a valid pointer.
+ */
+
+#define isc_stdtime_convert32(t, t32p) (*(t32p) = t)
+/*
+ * Convert the standard time to its 32-bit version.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STDTIME_H */
diff --git a/lib/isc/win32/include/isc/strerror.h b/lib/isc/win32/include/isc/strerror.h
new file mode 100644
index 0000000..ae040a4
--- /dev/null
+++ b/lib/isc/win32/include/isc/strerror.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_STRERROR_H
+#define ISC_STRERROR_H
+
+#include <sys/types.h>
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+#define ISC_STRERRORSIZE 128
+
+/*
+ * Provide a thread safe wrapper to strerrror().
+ *
+ * Requires:
+ * 'buf' to be non NULL.
+ */
+void
+isc__strerror(int num, char *buf, size_t bufsize);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STRERROR_H */
diff --git a/lib/isc/win32/include/isc/syslog.h b/lib/isc/win32/include/isc/syslog.h
new file mode 100644
index 0000000..66431e5
--- /dev/null
+++ b/lib/isc/win32/include/isc/syslog.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_SYSLOG_H
+#define ISC_SYSLOG_H 1
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_syslog_facilityfromstring(const char *str, int *facilityp);
+/*
+ * Convert 'str' to the appropriate syslog facility constant.
+ *
+ * Requires:
+ *
+ * 'str' is not NULL
+ * 'facilityp' is not NULL
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * ISC_R_NOTFOUND
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SYSLOG_H */
diff --git a/lib/isc/win32/include/isc/thread.h b/lib/isc/win32/include/isc/thread.h
new file mode 100644
index 0000000..be1343a
--- /dev/null
+++ b/lib/isc/win32/include/isc/thread.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_THREAD_H
+#define ISC_THREAD_H 1
+
+#include <windows.h>
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+/*
+ * Inlines to help with wait return checking
+ */
+
+/* check handle for NULL and INVALID_HANDLE */
+inline BOOL IsValidHandle( HANDLE hHandle) {
+ return ((hHandle != NULL) && (hHandle != INVALID_HANDLE_VALUE));
+}
+
+/* validate wait return codes... */
+inline BOOL WaitSucceeded( DWORD dwWaitResult, DWORD dwHandleCount) {
+ return ((dwWaitResult >= WAIT_OBJECT_0) &&
+ (dwWaitResult < WAIT_OBJECT_0 + dwHandleCount));
+}
+
+inline BOOL WaitAbandoned( DWORD dwWaitResult, DWORD dwHandleCount) {
+ return ((dwWaitResult >= WAIT_ABANDONED_0) &&
+ (dwWaitResult < WAIT_ABANDONED_0 + dwHandleCount));
+}
+
+inline BOOL WaitTimeout( DWORD dwWaitResult) {
+ return (dwWaitResult == WAIT_TIMEOUT);
+}
+
+inline BOOL WaitFailed( DWORD dwWaitResult) {
+ return (dwWaitResult == WAIT_FAILED);
+}
+
+/* compute object indices for waits... */
+inline DWORD WaitSucceededIndex( DWORD dwWaitResult) {
+ return (dwWaitResult - WAIT_OBJECT_0);
+}
+
+inline DWORD WaitAbandonedIndex( DWORD dwWaitResult) {
+ return (dwWaitResult - WAIT_ABANDONED_0);
+}
+
+
+
+typedef HANDLE isc_thread_t;
+typedef DWORD isc_threadresult_t;
+typedef void * isc_threadarg_t;
+typedef isc_threadresult_t (WINAPI *isc_threadfunc_t)(isc_threadarg_t);
+typedef DWORD isc_thread_key_t;
+
+#define isc_thread_self (unsigned long)GetCurrentThreadId
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_thread_create(isc_threadfunc_t, isc_threadarg_t, isc_thread_t *);
+
+isc_result_t
+isc_thread_join(isc_thread_t, isc_threadresult_t *);
+
+void
+isc_thread_setconcurrency(unsigned int level);
+
+void
+isc_thread_setname(isc_thread_t, const char *);
+
+int
+isc_thread_key_create(isc_thread_key_t *key, void (*func)(void *));
+
+int
+isc_thread_key_delete(isc_thread_key_t key);
+
+void *
+isc_thread_key_getspecific(isc_thread_key_t);
+
+int
+isc_thread_key_setspecific(isc_thread_key_t key, void *value);
+
+#define isc_thread_yield() Sleep(0)
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_THREAD_H */
diff --git a/lib/isc/win32/include/isc/time.h b/lib/isc/win32/include/isc/time.h
new file mode 100644
index 0000000..486f527
--- /dev/null
+++ b/lib/isc/win32/include/isc/time.h
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_TIME_H
+#define ISC_TIME_H 1
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <windows.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/***
+ *** Intervals
+ ***/
+
+/*
+ * The contents of this structure are private, and MUST NOT be accessed
+ * directly by callers.
+ *
+ * The contents are exposed only to allow callers to avoid dynamic allocation.
+ */
+struct isc_interval {
+ int64_t interval;
+};
+
+LIBISC_EXTERNAL_DATA extern const isc_interval_t * const isc_interval_zero;
+
+/*
+ * ISC_FORMATHTTPTIMESTAMP_SIZE needs to be 30 in C locale and potentially
+ * more for other locales to handle longer national abbreviations when
+ * expanding strftime's %a and %b.
+ */
+#define ISC_FORMATHTTPTIMESTAMP_SIZE 50
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_interval_set(isc_interval_t *i,
+ unsigned int seconds, unsigned int nanoseconds);
+/*
+ * Set 'i' to a value representing an interval of 'seconds' seconds and
+ * 'nanoseconds' nanoseconds, suitable for use in isc_time_add() and
+ * isc_time_subtract().
+ *
+ * Requires:
+ *
+ * 't' is a valid pointer.
+ * nanoseconds < 1000000000.
+ */
+
+bool
+isc_interval_iszero(const isc_interval_t *i);
+/*
+ * Returns true iff. 'i' is the zero interval.
+ *
+ * Requires:
+ *
+ * 'i' is a valid pointer.
+ */
+
+/***
+ *** Absolute Times
+ ***/
+
+/*
+ * The contents of this structure are private, and MUST NOT be accessed
+ * directly by callers.
+ *
+ * The contents are exposed only to allow callers to avoid dynamic allocation.
+ */
+
+struct isc_time {
+ FILETIME absolute;
+};
+
+LIBISC_EXTERNAL_DATA extern const isc_time_t * const isc_time_epoch;
+
+void
+isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds);
+/*%<
+ * Set 't' to a value which represents the given number of seconds and
+ * nanoseconds since 00:00:00 January 1, 1970, UTC.
+ *
+ * Requires:
+ *\li 't' is a valid pointer.
+ *\li nanoseconds < 1000000000.
+ */
+
+void
+isc_time_settoepoch(isc_time_t *t);
+/*
+ * Set 't' to the time of the epoch.
+ *
+ * Notes:
+ * The date of the epoch is platform-dependent.
+ *
+ * Requires:
+ *
+ * 't' is a valid pointer.
+ */
+
+bool
+isc_time_isepoch(const isc_time_t *t);
+/*
+ * Returns true iff. 't' is the epoch ("time zero").
+ *
+ * Requires:
+ *
+ * 't' is a valid pointer.
+ */
+
+isc_result_t
+isc_time_now(isc_time_t *t);
+/*
+ * Set 't' to the current absolute time.
+ *
+ * Requires:
+ *
+ * 't' is a valid pointer.
+ *
+ * Returns:
+ *
+ * Success
+ * Unexpected error
+ * Getting the time from the system failed.
+ * Out of range
+ * The time from the system is too large to be represented
+ * in the current definition of isc_time_t.
+ */
+
+isc_result_t
+isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i);
+/*
+ * Set *t to the current absolute time + i.
+ *
+ * Note:
+ * This call is equivalent to:
+ *
+ * isc_time_now(t);
+ * isc_time_add(t, i, t);
+ *
+ * Requires:
+ *
+ * 't' and 'i' are valid pointers.
+ *
+ * Returns:
+ *
+ * Success
+ * Unexpected error
+ * Getting the time from the system failed.
+ * Out of range
+ * The interval added to the time from the system is too large to
+ * be represented in the current definition of isc_time_t.
+ */
+
+int
+isc_time_compare(const isc_time_t *t1, const isc_time_t *t2);
+/*
+ * Compare the times referenced by 't1' and 't2'
+ *
+ * Requires:
+ *
+ * 't1' and 't2' are valid pointers.
+ *
+ * Returns:
+ *
+ * -1 t1 < t2 (comparing times, not pointers)
+ * 0 t1 = t2
+ * 1 t1 > t2
+ */
+
+isc_result_t
+isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result);
+/*
+ * Add 'i' to 't', storing the result in 'result'.
+ *
+ * Requires:
+ *
+ * 't', 'i', and 'result' are valid pointers.
+ *
+ * Returns:
+ * Success
+ * Out of range
+ * The interval added to the time is too large to
+ * be represented in the current definition of isc_time_t.
+ */
+
+isc_result_t
+isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
+ isc_time_t *result);
+/*
+ * Subtract 'i' from 't', storing the result in 'result'.
+ *
+ * Requires:
+ *
+ * 't', 'i', and 'result' are valid pointers.
+ *
+ * Returns:
+ * Success
+ * Out of range
+ * The interval is larger than the time since the epoch.
+ */
+
+uint64_t
+isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2);
+/*
+ * Find the difference in milliseconds between time t1 and time t2.
+ * t2 is the subtrahend of t1; ie, difference = t1 - t2.
+ *
+ * Requires:
+ *
+ * 't1' and 't2' are valid pointers.
+ *
+ * Returns:
+ * The difference of t1 - t2, or 0 if t1 <= t2.
+ */
+
+isc_result_t
+isc_time_parsehttptimestamp(char *input, isc_time_t *t);
+/*%<
+ * Parse the time in 'input' into the isc_time_t pointed to by 't',
+ * expecting a format like "Mon, 30 Aug 2000 04:06:47 GMT"
+ *
+ * Requires:
+ *\li 'buf' and 't' are not NULL.
+ */
+
+uint32_t
+isc_time_nanoseconds(const isc_time_t *t);
+/*
+ * Return the number of nanoseconds stored in a time structure.
+ *
+ * Notes:
+ * This is the number of nanoseconds in excess of the number
+ * of seconds since the epoch; it will always be less than one
+ * full second.
+ *
+ * Requires:
+ * 't' is a valid pointer.
+ *
+ * Ensures:
+ * The returned value is less than 1*10^9.
+ */
+
+void
+isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len);
+/*
+ * Format the time 't' into the buffer 'buf' of length 'len',
+ * using a format like "30-Aug-2000 04:06:47.997" and the local time zone.
+ * If the text does not fit in the buffer, the result is indeterminate,
+ * but is always guaranteed to be null terminated.
+ *
+ * Requires:
+ * 'len' > 0
+ * 'buf' points to an array of at least len chars
+ *
+ */
+
+void
+isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len);
+/*
+ * Format the time 't' into the buffer 'buf' of length 'len',
+ * using a format like "Mon, 30 Aug 2000 04:06:47 GMT"
+ * If the text does not fit in the buffer, the result is indeterminate,
+ * but is always guaranteed to be null terminated.
+ *
+ * Requires:
+ * 'len' > 0
+ * 'buf' points to an array of at least len chars
+ *
+ */
+
+isc_result_t
+isc_time_parsehttptimestamp(char *input, isc_time_t *t);
+/*%<
+ * Parse the time in 'input' into the isc_time_t pointed to by 't',
+ * expecting a format like "Mon, 30 Aug 2000 04:06:47 GMT"
+ *
+ * Requires:
+ *\li 'buf' and 't' are not NULL.
+ */
+
+void
+isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len);
+/*%<
+ * Format the time 't' into the buffer 'buf' of length 'len',
+ * using the ISO8601 format: "yyyy-mm-ddThh:mm:ssZ"
+ * If the text does not fit in the buffer, the result is indeterminate,
+ * but is always guaranteed to be null terminated.
+ *
+ * Requires:
+ *\li 'len' > 0
+ *\li 'buf' points to an array of at least len chars
+ *
+ */
+
+void
+isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len);
+/*%<
+ * Format the time 't' into the buffer 'buf' of length 'len',
+ * using the ISO8601 format: "yyyy-mm-ddThh:mm:ss.sssZ"
+ * If the text does not fit in the buffer, the result is indeterminate,
+ * but is always guaranteed to be null terminated.
+ *
+ * Requires:
+ *\li 'len' > 0
+ *\li 'buf' points to an array of at least len chars
+ *
+ */
+
+uint32_t
+isc_time_seconds(const isc_time_t *t);
+/*%<
+ * Return the number of seconds since the epoch stored in a time structure.
+ *
+ * Requires:
+ *
+ *\li 't' is a valid pointer.
+ */
+
+isc_result_t
+isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp);
+/*%<
+ * Ensure the number of seconds in an isc_time_t is representable by a time_t.
+ *
+ * Notes:
+ *\li The number of seconds stored in an isc_time_t might be larger
+ * than the number of seconds a time_t is able to handle. Since
+ * time_t is mostly opaque according to the ANSI/ISO standard
+ * (essentially, all you can be sure of is that it is an arithmetic type,
+ * not even necessarily integral), it can be tricky to ensure that
+ * the isc_time_t is in the range a time_t can handle. Use this
+ * function in place of isc_time_seconds() any time you need to set a
+ * time_t from an isc_time_t.
+ *
+ * Requires:
+ *\li 't' is a valid pointer.
+ *
+ * Returns:
+ *\li Success
+ *\li Out of range
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_TIME_H */
diff --git a/lib/isc/win32/include/isc/win32os.h b/lib/isc/win32/include/isc/win32os.h
new file mode 100644
index 0000000..bc18c40
--- /dev/null
+++ b/lib/isc/win32/include/isc/win32os.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef ISC_WIN32OS_H
+#define ISC_WIN32OS_H 1
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+/*
+ * Return the number of CPUs available on the system, or 1 if this cannot
+ * be determined.
+ */
+
+int
+isc_win32os_versioncheck(unsigned int major, unsigned int minor,
+ unsigned int updatemajor, unsigned int updateminor);
+
+/*
+ * Checks the current version of the operating system with the
+ * supplied version information.
+ * Returns:
+ * -1 if less than the version information supplied
+ * 0 if equal to all of the version information supplied
+ * +1 if greater than the version information supplied
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_WIN32OS_H */
diff --git a/lib/isc/win32/include/pkcs11/Makefile.in b/lib/isc/win32/include/pkcs11/Makefile.in
new file mode 100644
index 0000000..e9a85d4
--- /dev/null
+++ b/lib/isc/win32/include/pkcs11/Makefile.in
@@ -0,0 +1,26 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# 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 http://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@
+
+HEADERS = cryptoki.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
diff --git a/lib/isc/win32/include/pkcs11/cryptoki.h b/lib/isc/win32/include/pkcs11/cryptoki.h
new file mode 100644
index 0000000..2a681c4
--- /dev/null
+++ b/lib/isc/win32/include/pkcs11/cryptoki.h
@@ -0,0 +1,66 @@
+/* cryptoki.h include file for PKCS #11. */
+/* $Revision: 1.2 $ */
+
+/* License to copy and use this software is granted provided that it is
+ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
+ * (Cryptoki)" in all material mentioning or referencing this software.
+
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Security Inc. PKCS #11
+ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
+ * referencing the derived work.
+
+ * RSA Security Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this software for
+ * any particular purpose. It is provided "as is" without express or implied
+ * warranty of any kind.
+ */
+
+/* This is a sample file containing the top level include directives
+ * for building Win32 Cryptoki libraries and applications.
+ */
+
+#ifndef ___CRYPTOKI_H_INC___
+#define ___CRYPTOKI_H_INC___
+
+#pragma pack(push, cryptoki, 1)
+
+/* Specifies that the function is a DLL entry point. */
+#define CK_IMPORT_SPEC __declspec(dllimport)
+
+/* Define CRYPTOKI_EXPORTS during the build of cryptoki libraries. Do
+ * not define it in applications.
+ */
+#ifdef CRYPTOKI_EXPORTS
+/* Specified that the function is an exported DLL entry point. */
+#define CK_EXPORT_SPEC __declspec(dllexport)
+#else
+#define CK_EXPORT_SPEC CK_IMPORT_SPEC
+#endif
+
+/* Ensures the calling convention for Win32 builds */
+#define CK_CALL_SPEC __cdecl
+
+#define CK_PTR *
+
+#define CK_DEFINE_FUNCTION(returnType, name) \
+ returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION(returnType, name) \
+ returnType CK_EXPORT_SPEC CK_CALL_SPEC name
+
+#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
+ returnType CK_IMPORT_SPEC (CK_CALL_SPEC CK_PTR name)
+
+#define CK_CALLBACK_FUNCTION(returnType, name) \
+ returnType (CK_CALL_SPEC CK_PTR name)
+
+#ifndef NULL_PTR
+#define NULL_PTR 0
+#endif
+
+#include <pkcs11/pkcs11.h>
+
+#pragma pack(pop, cryptoki)
+
+#endif /* ___CRYPTOKI_H_INC___ */
diff --git a/lib/isc/win32/interfaceiter.c b/lib/isc/win32/interfaceiter.c
new file mode 100644
index 0000000..1bbd0f8
--- /dev/null
+++ b/lib/isc/win32/interfaceiter.c
@@ -0,0 +1,543 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*
+ * Note that this code will need to be revisited to support IPv6 Interfaces.
+ * For now we just iterate through IPv4 interfaces.
+ */
+
+#include <config.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <sys/types.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <isc/interfaceiter.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/strerror.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+void InitSockets(void);
+
+/* Common utility functions */
+
+/*
+ * Extract the network address part from a "struct sockaddr".
+ *
+ * The address family is given explicitly
+ * instead of using src->sa_family, because the latter does not work
+ * for copying a network mask obtained by SIOCGIFNETMASK (it does
+ * not have a valid address family).
+ */
+
+
+#define IFITER_MAGIC 0x49464954U /* IFIT. */
+#define VALID_IFITER(t) ((t) != NULL && (t)->magic == IFITER_MAGIC)
+
+struct isc_interfaceiter {
+ unsigned int magic; /* Magic number. */
+ isc_mem_t *mctx;
+ SOCKET socket;
+ INTERFACE_INFO IFData; /* Current Interface Info. */
+ int numIF; /* Current Interface count. */
+ int v4IF; /* Number of IPv4 Interfaces */
+ INTERFACE_INFO *buf4; /* Buffer for WSAIoctl data. */
+ unsigned int buf4size; /* Bytes allocated. */
+ INTERFACE_INFO *pos4; /* Current offset in IF List */
+ SOCKET_ADDRESS_LIST *buf6; /* Buffer for WSAIoctl data. */
+ unsigned int buf6size; /* Bytes allocated. */
+ unsigned int pos6; /* Which entry to process. */
+ bool v6loop; /* See IPv6 loop address. */
+ bool pos6zero; /* Done pos6 == 0. */
+ isc_interface_t current; /* Current interface data. */
+ isc_result_t result; /* Last result code. */
+};
+
+
+/*
+ * Size of buffer for SIO_GET_INTERFACE_LIST, in number of interfaces.
+ * We assume no sane system will have more than than 1K of IP addresses on
+ * all of its adapters.
+ */
+#define IFCONF_SIZE_INITIAL 16
+#define IFCONF_SIZE_INCREMENT 64
+#define IFCONF_SIZE_MAX 1040
+
+static void
+get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src) {
+ dst->family = family;
+ switch (family) {
+ case AF_INET:
+ memmove(&dst->type.in,
+ &((struct sockaddr_in *) src)->sin_addr,
+ sizeof(struct in_addr));
+ break;
+ case AF_INET6:
+ memmove(&dst->type.in6,
+ &((struct sockaddr_in6 *) src)->sin6_addr,
+ sizeof(struct in6_addr));
+ dst->zone = ((struct sockaddr_in6 *) src)->sin6_scope_id;
+ break;
+ default:
+ INSIST(0);
+ break;
+ }
+}
+
+isc_result_t
+isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
+ char strbuf[ISC_STRERRORSIZE];
+ isc_interfaceiter_t *iter;
+ isc_result_t result;
+ int error;
+ unsigned long bytesReturned = 0;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(iterp != NULL);
+ REQUIRE(*iterp == NULL);
+
+ iter = isc_mem_get(mctx, sizeof(*iter));
+ if (iter == NULL)
+ return (ISC_R_NOMEMORY);
+
+ InitSockets();
+
+ iter->mctx = mctx;
+ iter->buf4 = NULL;
+ iter->buf6 = NULL;
+ iter->pos4 = NULL;
+ iter->pos6 = 0;
+ iter->v6loop = true;
+ iter->pos6zero = true;
+ iter->buf6size = 0;
+ iter->buf4size = 0;
+ iter->result = ISC_R_FAILURE;
+ iter->numIF = 0;
+ iter->v4IF = 0;
+
+ /*
+ * Create an unbound datagram socket to do the
+ * SIO_GET_INTERFACE_LIST WSAIoctl on.
+ */
+ iter->socket = socket(AF_INET, SOCK_DGRAM, 0);
+ if (iter->socket == INVALID_SOCKET) {
+ error = WSAGetLastError();
+ if (error == WSAEAFNOSUPPORT)
+ goto inet6_only;
+ isc__strerror(error, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "making interface scan socket: %s",
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto socket_failure;
+ }
+
+ /*
+ * Get the interface configuration, allocating more memory if
+ * necessary.
+ */
+ iter->buf4size = IFCONF_SIZE_INITIAL*sizeof(INTERFACE_INFO);
+
+ for (;;) {
+ iter->buf4 = isc_mem_get(mctx, iter->buf4size);
+ if (iter->buf4 == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto alloc_failure;
+ }
+
+ if (WSAIoctl(iter->socket, SIO_GET_INTERFACE_LIST,
+ 0, 0, iter->buf4, iter->buf4size,
+ &bytesReturned, 0, 0) == SOCKET_ERROR)
+ {
+ error = WSAGetLastError();
+ if (error != WSAEFAULT && error != WSAENOBUFS) {
+ errno = error;
+ isc__strerror(error, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "get interface configuration: %s",
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto ioctl_failure;
+ }
+ /*
+ * EINVAL. Retry with a bigger buffer.
+ */
+ } else {
+ /*
+ * The WSAIoctl succeeded.
+ * If the number of the returned bytes is the same
+ * as the buffer size, we will grow it just in
+ * case and retry.
+ */
+ if (bytesReturned > 0 &&
+ (bytesReturned < iter->buf4size))
+ break;
+ }
+ if (iter->buf4size >= IFCONF_SIZE_MAX*sizeof(INTERFACE_INFO)) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "get interface configuration: "
+ "maximum buffer size exceeded");
+ result = ISC_R_UNEXPECTED;
+ goto ioctl_failure;
+ }
+ isc_mem_put(mctx, iter->buf4, iter->buf4size);
+
+ iter->buf4size += IFCONF_SIZE_INCREMENT *
+ sizeof(INTERFACE_INFO);
+ }
+
+ /*
+ * A newly created iterator has an undefined position
+ * until isc_interfaceiter_first() is called.
+ */
+ iter->v4IF = bytesReturned/sizeof(INTERFACE_INFO);
+
+ /* We don't need the socket any more, so close it */
+ closesocket(iter->socket);
+
+ inet6_only:
+ /*
+ * Create an unbound datagram socket to do the
+ * SIO_ADDRESS_LIST_QUERY WSAIoctl on.
+ */
+ iter->socket = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (iter->socket == INVALID_SOCKET) {
+ error = WSAGetLastError();
+ if (error == WSAEAFNOSUPPORT)
+ goto inet_only;
+ isc__strerror(error, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "making interface scan socket: %s",
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto ioctl_failure;
+ }
+
+ /*
+ * Get the interface configuration, allocating more memory if
+ * necessary.
+ */
+ iter->buf6size = sizeof(SOCKET_ADDRESS_LIST) +
+ IFCONF_SIZE_INITIAL*sizeof(SOCKET_ADDRESS);
+
+ for (;;) {
+ iter->buf6 = isc_mem_get(mctx, iter->buf6size);
+ if (iter->buf6 == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto ioctl_failure;
+ }
+
+ if (WSAIoctl(iter->socket, SIO_ADDRESS_LIST_QUERY,
+ 0, 0, iter->buf6, iter->buf6size,
+ &bytesReturned, 0, 0) == SOCKET_ERROR)
+ {
+ error = WSAGetLastError();
+ if (error != WSAEFAULT && error != WSAENOBUFS) {
+ errno = error;
+ isc__strerror(error, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "sio address list query: %s",
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto ioctl6_failure;
+ }
+ /*
+ * EINVAL. Retry with a bigger buffer.
+ */
+ } else
+ break;
+
+ if (iter->buf6size >= IFCONF_SIZE_MAX*sizeof(SOCKET_ADDRESS)) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "get interface configuration: "
+ "maximum buffer size exceeded");
+ result = ISC_R_UNEXPECTED;
+ goto ioctl6_failure;
+ }
+ isc_mem_put(mctx, iter->buf6, iter->buf6size);
+
+ iter->buf6size += IFCONF_SIZE_INCREMENT *
+ sizeof(SOCKET_ADDRESS);
+ }
+
+ closesocket(iter->socket);
+
+ inet_only:
+ iter->magic = IFITER_MAGIC;
+ *iterp = iter;
+ return (ISC_R_SUCCESS);
+
+ ioctl6_failure:
+ isc_mem_put(mctx, iter->buf6, iter->buf6size);
+
+ ioctl_failure:
+ if (iter->buf4 != NULL)
+ isc_mem_put(mctx, iter->buf4, iter->buf4size);
+
+ alloc_failure:
+ if (iter->socket != INVALID_SOCKET)
+ (void) closesocket(iter->socket);
+
+ socket_failure:
+ isc_mem_put(mctx, iter, sizeof(*iter));
+ return (result);
+}
+
+/*
+ * Get information about the current interface to iter->current.
+ * If successful, return ISC_R_SUCCESS.
+ * If the interface has an unsupported address family, or if
+ * some operation on it fails, return ISC_R_IGNORE to make
+ * the higher-level iterator code ignore it.
+ */
+
+static isc_result_t
+internal_current(isc_interfaceiter_t *iter) {
+ BOOL ifNamed = FALSE;
+ unsigned long flags;
+
+ REQUIRE(VALID_IFITER(iter));
+ REQUIRE(iter->numIF >= 0);
+
+ memset(&iter->current, 0, sizeof(iter->current));
+ iter->current.af = AF_INET;
+
+ get_addr(AF_INET, &iter->current.address,
+ (struct sockaddr *)&(iter->IFData.iiAddress));
+
+ /*
+ * Get interface flags.
+ */
+
+ iter->current.flags = 0;
+ flags = iter->IFData.iiFlags;
+
+ if ((flags & IFF_UP) != 0)
+ iter->current.flags |= INTERFACE_F_UP;
+
+ if ((flags & IFF_POINTTOPOINT) != 0) {
+ iter->current.flags |= INTERFACE_F_POINTTOPOINT;
+ snprintf(iter->current.name, sizeof(iter->current.name),
+ "PPP Interface %d", iter->numIF);
+ ifNamed = TRUE;
+ }
+
+ if ((flags & IFF_LOOPBACK) != 0) {
+ iter->current.flags |= INTERFACE_F_LOOPBACK;
+ snprintf(iter->current.name, sizeof(iter->current.name),
+ "Loopback Interface %d", iter->numIF);
+ ifNamed = TRUE;
+ }
+
+ /*
+ * If the interface is point-to-point, get the destination address.
+ */
+ if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
+ get_addr(AF_INET, &iter->current.dstaddress,
+ (struct sockaddr *)&(iter->IFData.iiBroadcastAddress));
+ }
+
+ if (ifNamed == FALSE)
+ snprintf(iter->current.name, sizeof(iter->current.name),
+ "TCP/IP Interface %d", iter->numIF);
+
+ /*
+ * Get the network mask.
+ */
+ get_addr(AF_INET, &iter->current.netmask,
+ (struct sockaddr *)&(iter->IFData.iiNetmask));
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+internal_current6(isc_interfaceiter_t *iter) {
+ SOCKET fd;
+ int i;
+
+ REQUIRE(VALID_IFITER(iter));
+ REQUIRE(iter->buf6 != NULL);
+
+ memset(&iter->current, 0, sizeof(iter->current));
+ iter->current.af = AF_INET6;
+
+ if (!iter->pos6zero) {
+ if (iter->pos6 == 0U)
+ iter->pos6zero = true;
+ get_addr(AF_INET6, &iter->current.address,
+ iter->buf6->Address[iter->pos6].lpSockaddr);
+
+ /*
+ * Set interface flags.
+ */
+
+ iter->current.flags = INTERFACE_F_UP;
+
+ snprintf(iter->current.name, sizeof(iter->current.name),
+ "TCP/IPv6 Interface %u", iter->pos6 + 1);
+
+ for (i = 0; i < 16; i++)
+ iter->current.netmask.type.in6.s6_addr[i] = 0xff;
+ iter->current.netmask.family = AF_INET6;
+ if (IN6_IS_ADDR_LOOPBACK(&iter->current.address.type.in6))
+ iter->v6loop = true;
+ } else {
+ /*
+ * See if we can bind to the ::1 and if so return ::1.
+ */
+ struct sockaddr_in6 sin6;
+
+ iter->v6loop = true; /* So we don't loop forever. */
+
+ fd = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (fd == INVALID_SOCKET)
+ return (ISC_R_IGNORE);
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_addr.s6_addr[15] = 1;
+ if (bind(fd, (struct sockaddr *)&sin6, sizeof(sin6)) < 0) {
+ closesocket(fd);
+ return (ISC_R_IGNORE);
+ }
+ closesocket(fd);
+
+ iter->current.flags = INTERFACE_F_UP | INTERFACE_F_LOOPBACK;
+ snprintf(iter->current.name, sizeof(iter->current.name),
+ "TCP/IPv6 Loopback Interface");
+ for (i = 0; i < 16; i++) {
+ if (i != 15)
+ iter->current.address.type.in6.s6_addr[i] = 0;
+ else
+ iter->current.address.type.in6.s6_addr[i] = 1;
+ iter->current.netmask.type.in6.s6_addr[i] = 0xff;
+ }
+ iter->current.address.family = AF_INET6;
+ iter->current.netmask.family = AF_INET6;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Step the iterator to the next interface. Unlike
+ * isc_interfaceiter_next(), this may leave the iterator
+ * positioned on an interface that will ultimately
+ * be ignored. Return ISC_R_NOMORE if there are no more
+ * interfaces, otherwise ISC_R_SUCCESS.
+ */
+static isc_result_t
+internal_next(isc_interfaceiter_t *iter) {
+ if (iter->numIF >= iter->v4IF)
+ return (ISC_R_NOMORE);
+
+ /*
+ * The first one needs to be set up to point to the last
+ * Element of the array. Go to the end and back up
+ * Microsoft's implementation is peculiar for returning
+ * the list in reverse order
+ */
+
+ if (iter->numIF == 0)
+ iter->pos4 = (INTERFACE_INFO *)(iter->buf4 + (iter->v4IF));
+
+ iter->pos4--;
+ if (&(iter->pos4) < &(iter->buf4))
+ return (ISC_R_NOMORE);
+
+ memset(&(iter->IFData), 0, sizeof(INTERFACE_INFO));
+ memmove(&(iter->IFData), iter->pos4, sizeof(INTERFACE_INFO));
+ iter->numIF++;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+internal_next6(isc_interfaceiter_t *iter) {
+ if (iter->pos6 == 0U && iter->v6loop)
+ return (ISC_R_NOMORE);
+ if (iter->pos6 != 0U)
+ iter->pos6--;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_interfaceiter_current(isc_interfaceiter_t *iter,
+ isc_interface_t *ifdata) {
+ REQUIRE(iter->result == ISC_R_SUCCESS);
+ memmove(ifdata, &iter->current, sizeof(*ifdata));
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_interfaceiter_first(isc_interfaceiter_t *iter) {
+
+ REQUIRE(VALID_IFITER(iter));
+
+ if (iter->buf6 != NULL) {
+ iter->pos6 = iter->buf6->iAddressCount;
+ iter->v6loop = false;
+ iter->pos6zero = (iter->pos6 == 0U);
+ }
+ iter->result = ISC_R_SUCCESS;
+ return (isc_interfaceiter_next(iter));
+}
+
+isc_result_t
+isc_interfaceiter_next(isc_interfaceiter_t *iter) {
+ isc_result_t result;
+
+ REQUIRE(VALID_IFITER(iter));
+ REQUIRE(iter->result == ISC_R_SUCCESS);
+
+ for (;;) {
+ result = internal_next(iter);
+ if (result == ISC_R_NOMORE) {
+ result = internal_next6(iter);
+ if (result != ISC_R_SUCCESS)
+ break;
+ result = internal_current6(iter);
+ if (result == ISC_R_IGNORE)
+ continue;
+ break;
+ } else if (result != ISC_R_SUCCESS)
+ break;
+ result = internal_current(iter);
+ if (result != ISC_R_IGNORE)
+ break;
+ }
+ iter->result = result;
+ return (result);
+}
+
+void
+isc_interfaceiter_destroy(isc_interfaceiter_t **iterp) {
+ isc_interfaceiter_t *iter;
+ REQUIRE(iterp != NULL);
+ iter = *iterp;
+ REQUIRE(VALID_IFITER(iter));
+
+ if (iter->buf4 != NULL)
+ isc_mem_put(iter->mctx, iter->buf4, iter->buf4size);
+ if (iter->buf6 != NULL)
+ isc_mem_put(iter->mctx, iter->buf6, iter->buf6size);
+
+ iter->magic = 0;
+ isc_mem_put(iter->mctx, iter, sizeof(*iter));
+ *iterp = NULL;
+}
diff --git a/lib/isc/win32/ipv6.c b/lib/isc/win32/ipv6.c
new file mode 100644
index 0000000..c2a4ac5
--- /dev/null
+++ b/lib/isc/win32/ipv6.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <isc/net.h>
+#include <isc/platform.h>
+
+LIBISC_EXTERNAL_DATA const struct in6_addr isc_in6addr_any =
+ IN6ADDR_ANY_INIT;
+
+LIBISC_EXTERNAL_DATA const struct in6_addr isc_in6addr_loopback =
+ IN6ADDR_LOOPBACK_INIT;
diff --git a/lib/isc/win32/keyboard.c b/lib/isc/win32/keyboard.c
new file mode 100644
index 0000000..6e6f800
--- /dev/null
+++ b/lib/isc/win32/keyboard.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#include <windows.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <io.h>
+
+#include <isc/keyboard.h>
+#include <isc/util.h>
+
+isc_result_t
+isc_keyboard_open(isc_keyboard_t *keyboard) {
+ int fd;
+
+ REQUIRE(keyboard != NULL);
+
+ fd = _fileno(stdin);
+ if (fd < 0)
+ return (ISC_R_IOERROR);
+
+ keyboard->fd = fd;
+
+ keyboard->result = ISC_R_SUCCESS;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_keyboard_close(isc_keyboard_t *keyboard, unsigned int sleeptime) {
+ REQUIRE(keyboard != NULL);
+
+ if (sleeptime > 0 && keyboard->result != ISC_R_CANCELED)
+ (void)Sleep(sleeptime*1000);
+
+ keyboard->fd = -1;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_keyboard_getchar(isc_keyboard_t *keyboard, unsigned char *cp) {
+ ssize_t cc;
+ unsigned char c;
+
+ REQUIRE(keyboard != NULL);
+ REQUIRE(cp != NULL);
+
+ cc = read(keyboard->fd, &c, 1);
+ if (cc < 0) {
+ keyboard->result = ISC_R_IOERROR;
+ return (keyboard->result);
+ }
+
+ *cp = c;
+
+ return (ISC_R_SUCCESS);
+}
+
+bool
+isc_keyboard_canceled(isc_keyboard_t *keyboard) {
+ return (keyboard->result == ISC_R_CANCELED);
+}
diff --git a/lib/isc/win32/libgen.h b/lib/isc/win32/libgen.h
new file mode 100644
index 0000000..e74740f
--- /dev/null
+++ b/lib/isc/win32/libgen.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef LIBGEN_H
+#define LIBGEN_H 1
+
+char *basename(const char *);
+char *dirname(const char *);
+
+#endif
diff --git a/lib/isc/win32/libisc.def.exclude b/lib/isc/win32/libisc.def.exclude
new file mode 100644
index 0000000..41e8562
--- /dev/null
+++ b/lib/isc/win32/libisc.def.exclude
@@ -0,0 +1,42 @@
+; These symbols are not needed by the WIN32 build, but build-tarballs
+; will complain if they aren't present here.
+isc_print_fprintf
+isc_print_printf
+isc_print_snprintf
+isc_print_sprintf
+isc_print_vsnprintf
+isc_socket_accept
+isc_socket_attach
+isc_socket_bind
+isc_socket_cancel
+isc_socket_cleanunix
+isc_socket_close
+isc_socket_connect
+isc_socket_create
+isc_socket_detach
+isc_socket_dscp
+isc_socket_dup
+isc_socket_fdwatchcreate
+isc_socket_fdwatchpoke
+isc_socket_filter
+isc_socket_getpeername
+isc_socket_getsockname
+isc_socket_gettype
+isc_socket_ipv6only
+isc_socket_listen
+isc_socket_open
+isc_socket_permunix
+isc_socket_recv
+isc_socket_recv2
+isc_socket_recvv
+isc_socket_register
+isc_socket_send
+isc_socket_sendto
+isc_socket_sendto2
+isc_socket_sendtov
+isc_socket_sendtov2
+isc_socket_sendv
+isc_socketmgr_create
+isc_socketmgr_create2
+isc_socketmgr_destroy
+isc_socketmgr_setstats
diff --git a/lib/isc/win32/libisc.def.in b/lib/isc/win32/libisc.def.in
new file mode 100644
index 0000000..a82face
--- /dev/null
+++ b/lib/isc/win32/libisc.def.in
@@ -0,0 +1,836 @@
+LIBRARY libisc
+
+; Exported Functions
+EXPORTS
+
+NTReportError
+closelog
+@IF PKCS11
+getpassphrase
+@END PKCS11
+isc___socketmgr_maxudp
+isc__app_block
+isc__app_ctxfinish
+isc__app_ctxonrun
+isc__app_ctxrun
+isc__app_ctxshutdown
+isc__app_ctxstart
+isc__app_ctxsuspend
+isc__app_finish
+isc__app_onrun
+isc__app_reload
+isc__app_run
+isc__app_shutdown
+isc__app_start
+isc__app_unblock
+isc__appctx_create
+isc__appctx_destroy
+isc__appctx_setsocketmgr
+isc__appctx_settaskmgr
+isc__appctx_settimermgr
+isc__buffer_activeregion
+isc__buffer_add
+isc__buffer_availableregion
+isc__buffer_back
+isc__buffer_clear
+isc__buffer_consumedregion
+isc__buffer_first
+isc__buffer_forward
+isc__buffer_init
+isc__buffer_initnull
+isc__buffer_invalidate
+isc__buffer_putmem
+isc__buffer_putstr
+isc__buffer_putuint16
+isc__buffer_putuint24
+isc__buffer_putuint32
+isc__buffer_putuint48
+isc__buffer_putuint8
+isc__buffer_region
+isc__buffer_remainingregion
+isc__buffer_setactive
+isc__buffer_subtract
+isc__buffer_usedregion
+isc__hash_setvec
+isc__mem_allocate
+isc__mem_free
+isc__mem_get
+isc__mem_put
+isc__mem_putanddetach
+isc__mem_reallocate
+isc__mem_strdup
+isc__mempool_get
+isc__mempool_put
+isc__socket_accept
+isc__socket_attach
+isc__socket_bind
+isc__socket_cancel
+isc__socket_cleanunix
+isc__socket_close
+isc__socket_connect
+isc__socket_create
+isc__socket_detach
+isc__socket_dscp
+isc__socket_dup
+isc__socket_filter
+isc__socket_getfd
+isc__socket_getname
+isc__socket_getpeername
+isc__socket_getsockname
+isc__socket_gettag
+isc__socket_gettype
+isc__socket_ipv6only
+isc__socket_isbound
+isc__socket_listen
+isc__socket_open
+isc__socket_permunix
+isc__socket_recv
+isc__socket_recv2
+isc__socket_recvv
+isc__socket_register
+isc__socket_send
+isc__socket_sendto
+isc__socket_sendto2
+isc__socket_sendtov
+isc__socket_sendtov2
+isc__socket_sendv
+isc__socket_setname
+isc__socketmgr_create
+isc__socketmgr_create2
+isc__socketmgr_destroy
+isc__socketmgr_getmaxsockets
+isc__socketmgr_setreserved
+isc__socketmgr_setstats
+isc__strerror
+isc__task_getname
+isc__task_gettag
+isc__task_unsendrange
+isc__taskmgr_mode
+@IF AES
+isc_aes128_crypt
+isc_aes192_crypt
+isc_aes256_crypt
+@END AES
+isc_app_block
+isc_app_ctxfinish
+isc_app_ctxonrun
+isc_app_ctxrun
+isc_app_ctxshutdown
+isc_app_ctxstart
+isc_app_ctxsuspend
+isc_app_finish
+isc_app_isrunning
+isc_app_onrun
+isc_app_register
+isc_app_reload
+isc_app_run
+isc_app_shutdown
+isc_app_start
+isc_app_unblock
+isc_appctx_create
+isc_appctx_destroy
+isc_appctx_setsocketmgr
+isc_appctx_settaskmgr
+isc_appctx_settimermgr
+isc_assertion_failed
+isc_assertion_setcallback
+isc_assertion_typetotext
+isc_backtrace_getsymbol
+isc_backtrace_getsymbolfromindex
+isc_backtrace_gettrace
+isc_base32_decoderegion
+isc_base32_decodestring
+isc_base32_tobuffer
+isc_base32_totext
+isc_base32hex_decoderegion
+isc_base32hex_decodestring
+isc_base32hex_tobuffer
+isc_base32hex_totext
+isc_base32hexnp_decoderegion
+isc_base32hexnp_decodestring
+isc_base32hexnp_tobuffer
+isc_base32hexnp_totext
+isc_base64_decodestring
+isc_base64_tobuffer
+isc_base64_totext
+isc_buffer_allocate
+isc_buffer_compact
+isc_buffer_copyregion
+isc_buffer_dup
+isc_buffer_free
+isc_buffer_getuint16
+isc_buffer_getuint32
+isc_buffer_getuint48
+isc_buffer_getuint8
+isc_buffer_putdecint
+isc_buffer_reallocate
+isc_buffer_reinit
+isc_buffer_reserve
+isc_buffer_setautorealloc
+isc_bufferlist_availablecount
+isc_bufferlist_usedcount
+isc_commandline_parse
+isc_commandline_strtoargv
+isc_condition_broadcast
+isc_condition_destroy
+isc_condition_init
+isc_condition_signal
+isc_condition_wait
+isc_condition_waituntil
+isc_counter_attach
+isc_counter_create
+isc_counter_detach
+isc_counter_increment
+isc_counter_setlimit
+isc_counter_used
+isc_crc64_final
+isc_crc64_init
+isc_crc64_update
+isc_dir_chdir
+isc_dir_chroot
+isc_dir_close
+isc_dir_createunique
+isc_dir_init
+isc_dir_open
+isc_dir_read
+isc_dir_reset
+isc_entropy_addcallbacksample
+isc_entropy_addsample
+isc_entropy_attach
+isc_entropy_create
+isc_entropy_createcallbacksource
+isc_entropy_createfilesource
+isc_entropy_createsamplesource
+isc_entropy_destroysource
+isc_entropy_detach
+isc_entropy_getdata
+isc_entropy_putdata
+isc_entropy_stats
+isc_entropy_status
+isc_entropy_stopcallbacksources
+isc_entropy_usebestsource
+isc_errno_toresult
+isc_error_fatal
+isc_error_runtimecheck
+isc_error_setfatal
+isc_error_setunexpected
+isc_error_unexpected
+isc_event_allocate
+isc_event_constallocate
+isc_event_free
+isc_file_absolutepath
+isc_file_basename
+isc_file_bopenunique
+isc_file_bopenuniquemode
+isc_file_bopenuniqueprivate
+isc_file_exists
+isc_file_getmodtime
+isc_file_getsize
+isc_file_getsizefd
+isc_file_isabsolute
+isc_file_ischdiridempotent
+isc_file_iscurrentdir
+isc_file_isdirectory
+isc_file_isdirwritable
+isc_file_isplainfile
+isc_file_isplainfilefd
+isc_file_mktemplate
+isc_file_mmap
+isc_file_mode
+isc_file_munmap
+isc_file_openunique
+isc_file_openuniquemode
+isc_file_openuniqueprivate
+isc_file_progname
+isc_file_remove
+isc_file_rename
+isc_file_renameunique
+isc_file_safecreate
+isc_file_safemovefile
+isc_file_sanitize
+isc_file_settime
+isc_file_splitpath
+isc_file_template
+isc_file_truncate
+isc_fsaccess_add
+isc_fsaccess_changeowner
+isc_fsaccess_remove
+isc_fsaccess_set
+isc_hash_calc
+isc_hash_create
+isc_hash_ctxattach
+isc_hash_ctxcalc
+isc_hash_ctxcreate
+isc_hash_ctxdetach
+isc_hash_ctxinit
+isc_hash_destroy
+isc_hash_function
+isc_hash_function_reverse
+isc_hash_get_initializer
+isc_hash_init
+isc_hash_set_initializer
+isc_heap_create
+isc_heap_decreased
+isc_heap_delete
+isc_heap_destroy
+isc_heap_foreach
+isc_heap_element
+isc_heap_increased
+isc_heap_insert
+isc_hex_decodestring
+isc_hex_tobuffer
+isc_hex_totext
+isc_hmacmd5_check
+isc_hmacmd5_init
+isc_hmacmd5_invalidate
+isc_hmacmd5_sign
+isc_hmacmd5_update
+isc_hmacmd5_verify
+isc_hmacmd5_verify2
+isc_hmacsha1_check
+isc_hmacsha1_init
+isc_hmacsha1_invalidate
+isc_hmacsha1_sign
+isc_hmacsha1_update
+isc_hmacsha1_verify
+isc_hmacsha224_init
+isc_hmacsha224_invalidate
+isc_hmacsha224_sign
+isc_hmacsha224_update
+isc_hmacsha224_verify
+isc_hmacsha256_init
+isc_hmacsha256_invalidate
+isc_hmacsha256_sign
+isc_hmacsha256_update
+isc_hmacsha256_verify
+isc_hmacsha384_init
+isc_hmacsha384_invalidate
+isc_hmacsha384_sign
+isc_hmacsha384_update
+isc_hmacsha384_verify
+isc_hmacsha512_init
+isc_hmacsha512_invalidate
+isc_hmacsha512_sign
+isc_hmacsha512_update
+isc_hmacsha512_verify
+isc_ht_add
+isc_ht_count
+isc_ht_delete
+isc_ht_destroy
+isc_ht_find
+isc_ht_init
+isc_ht_iter_create
+isc_ht_iter_current
+isc_ht_iter_currentkey
+isc_ht_iter_delcurrent_next
+isc_ht_iter_destroy
+isc_ht_iter_first
+isc_ht_iter_next
+isc_httpd_addheader
+isc_httpd_addheaderuint
+isc_httpd_response
+isc_httpd_setfinishhook
+isc_httpdmgr_addurl
+isc_httpdmgr_addurl2
+isc_httpdmgr_create
+isc_httpdmgr_shutdown
+isc_interfaceiter_create
+isc_interfaceiter_current
+isc_interfaceiter_destroy
+isc_interfaceiter_first
+isc_interfaceiter_next
+isc_interval_iszero
+isc_interval_set
+isc_iterated_hash
+isc_keyboard_canceled
+isc_keyboard_close
+isc_keyboard_getchar
+isc_keyboard_open
+isc_lex_close
+isc_lex_create
+isc_lex_destroy
+isc_lex_getcomments
+isc_lex_getlasttokentext
+isc_lex_getmastertoken
+isc_lex_getoctaltoken
+isc_lex_getsourceline
+isc_lex_getsourcename
+isc_lex_getspecials
+isc_lex_gettoken
+isc_lex_isfile
+isc_lex_openbuffer
+isc_lex_openfile
+isc_lex_openstream
+isc_lex_setcomments
+isc_lex_setsourceline
+isc_lex_setsourcename
+isc_lex_setspecials
+isc_lex_ungettoken
+isc_lfsr_generate
+isc_lfsr_generate32
+isc_lfsr_init
+isc_lfsr_skip
+isc_lib_initmsgcat
+isc_lib_register
+isc_log_categorybyname
+isc_log_closefilelogs
+isc_log_create
+isc_log_createchannel
+isc_log_destroy
+isc_log_getdebuglevel
+isc_log_getduplicateinterval
+isc_log_gettag
+isc_log_ivwrite
+isc_log_ivwrite1
+isc_log_iwrite
+isc_log_iwrite1
+isc_log_modulebyname
+isc_log_opensyslog
+isc_log_registercategories
+isc_log_registermodules
+isc_log_setcontext
+isc_log_setdebuglevel
+isc_log_setduplicateinterval
+isc_log_settag
+isc_log_usechannel
+isc_log_vwrite
+isc_log_vwrite1
+isc_log_wouldlog
+isc_log_write
+isc_log_write1
+isc_logconfig_create
+isc_logconfig_destroy
+isc_logconfig_get
+isc_logconfig_use
+isc_logfile_roll
+isc_md5_check
+isc_md5_final
+isc_md5_init
+isc_md5_invalidate
+isc_md5_update
+isc_mem_attach
+isc_mem_checkdestroyed
+isc_mem_create
+isc_mem_create2
+isc_mem_createx
+isc_mem_createx2
+isc_mem_destroy
+isc_mem_detach
+isc_mem_getname
+isc_mem_getquota
+isc_mem_gettag
+isc_mem_inuse
+isc_mem_isovermem
+isc_mem_maxinuse
+isc_mem_ondestroy
+isc_mem_printallactive
+isc_mem_references
+isc_mem_register
+@IF NOTYET
+isc_mem_renderjson
+@END NOTYET
+@IF LIBXML2
+isc_mem_renderxml
+@END LIBXML2
+isc_mem_setdestroycheck
+isc_mem_setname
+isc_mem_setquota
+isc_mem_setwater
+isc_mem_stats
+isc_mem_total
+isc_mem_waterack
+isc_meminfo_totalphys
+isc_mempool_associatelock
+isc_mempool_create
+isc_mempool_destroy
+isc_mempool_getallocated
+isc_mempool_getfillcount
+isc_mempool_getfreecount
+isc_mempool_getfreemax
+isc_mempool_getmaxalloc
+isc_mempool_setfillcount
+isc_mempool_setfreemax
+isc_mempool_setmaxalloc
+isc_mempool_setname
+isc_msgcat_close
+isc_msgcat_get
+isc_msgcat_open
+isc_mutexblock_destroy
+isc_mutexblock_init
+isc_net_aton
+isc_net_disableipv4
+isc_net_disableipv6
+isc_net_enableipv4
+isc_net_enableipv6
+isc_net_getudpportrange
+isc_net_ntop
+isc_net_probe_ipv6only
+isc_net_probe_ipv6pktinfo
+isc_net_probedscp
+isc_net_probeipv4
+isc_net_probeipv6
+isc_net_probeunix
+isc_net_pton
+isc_netaddr_any
+isc_netaddr_any6
+isc_netaddr_eqprefix
+isc_netaddr_equal
+isc_netaddr_format
+isc_netaddr_fromin
+isc_netaddr_fromin6
+isc_netaddr_frompath
+isc_netaddr_fromsockaddr
+isc_netaddr_fromv4mapped
+isc_netaddr_getzone
+isc_netaddr_isexperimental
+isc_netaddr_islinklocal
+isc_netaddr_isloopback
+isc_netaddr_ismulticast
+isc_netaddr_isnetzero
+isc_netaddr_issitelocal
+isc_netaddr_masktoprefixlen
+isc_netaddr_prefixok
+isc_netaddr_setzone
+isc_netaddr_totext
+isc_netscope_pton
+isc_ntpaths_get
+isc_ntpaths_init
+isc_once_do
+isc_ondestroy_init
+isc_ondestroy_notify
+isc_ondestroy_register
+isc_os_ncpus
+isc_parse_uint16
+isc_parse_uint32
+isc_parse_uint8
+isc_pool_count
+isc_pool_create
+isc_pool_destroy
+isc_pool_expand
+isc_pool_get
+isc_portset_add
+isc_portset_addrange
+isc_portset_create
+isc_portset_destroy
+isc_portset_isset
+isc_portset_nports
+isc_portset_remove
+isc_portset_removerange
+isc_quota_attach
+isc_quota_destroy
+isc_quota_detach
+isc_quota_init
+isc_quota_max
+isc_quota_release
+isc_quota_reserve
+isc_quota_soft
+isc_radix_create
+isc_radix_destroy
+isc_radix_insert
+isc_radix_process
+isc_radix_remove
+isc_radix_search
+isc_random_get
+isc_random_jitter
+isc_random_seed
+isc_ratelimiter_attach
+isc_ratelimiter_create
+isc_ratelimiter_dequeue
+isc_ratelimiter_detach
+isc_ratelimiter_enqueue
+isc_ratelimiter_release
+isc_ratelimiter_setinterval
+isc_ratelimiter_setpertic
+isc_ratelimiter_setpushpop
+isc_ratelimiter_shutdown
+isc_ratelimiter_stall
+isc_refcount_init
+isc_regex_validate
+isc_region_compare
+isc_resource_getcurlimit
+isc_resource_getlimit
+isc_resource_setlimit
+isc_result_register
+isc_result_registerids
+isc_result_toid
+isc_result_totext
+isc_rng_attach
+isc_rng_create
+isc_rng_detach
+isc_rng_random
+isc_rng_uniformrandom
+isc_rwlock_destroy
+isc_rwlock_downgrade
+isc_rwlock_init
+isc_rwlock_lock
+isc_rwlock_trylock
+isc_rwlock_tryupgrade
+isc_rwlock_unlock
+isc_safe_memcompare
+isc_safe_memequal
+isc_safe_memwipe
+isc_serial_eq
+isc_serial_ge
+isc_serial_gt
+isc_serial_le
+isc_serial_lt
+isc_serial_ne
+isc_sha1_check
+isc_sha1_final
+isc_sha1_init
+isc_sha1_invalidate
+isc_sha1_update
+isc_sha224_data
+isc_sha224_end
+isc_sha224_final
+isc_sha224_init
+isc_sha224_invalidate
+isc_sha224_update
+isc_sha256_data
+isc_sha256_end
+isc_sha256_final
+isc_sha256_init
+isc_sha256_invalidate
+isc_sha256_update
+isc_sha384_data
+isc_sha384_end
+isc_sha384_final
+isc_sha384_init
+isc_sha384_invalidate
+isc_sha384_update
+isc_sha512_data
+isc_sha512_end
+isc_sha512_final
+isc_sha512_init
+isc_sha512_invalidate
+isc_sha512_update
+isc_sockaddr_any
+isc_sockaddr_any6
+isc_sockaddr_anyofpf
+isc_sockaddr_compare
+isc_sockaddr_eqaddr
+isc_sockaddr_eqaddrprefix
+isc_sockaddr_equal
+isc_sockaddr_format
+isc_sockaddr_fromin
+isc_sockaddr_fromin6
+isc_sockaddr_fromnetaddr
+isc_sockaddr_frompath
+isc_sockaddr_getport
+isc_sockaddr_hash
+isc_sockaddr_isexperimental
+isc_sockaddr_islinklocal
+isc_sockaddr_ismulticast
+isc_sockaddr_isnetzero
+isc_sockaddr_issitelocal
+isc_sockaddr_pf
+isc_sockaddr_setport
+isc_sockaddr_totext
+isc_sockaddr_v6fromin
+isc_socket_socketevent
+isc_socketmgr_createinctx
+@IF NOTYET
+isc_socketmgr_renderjson
+@END NOTYET
+@IF LIBXML2
+isc_socketmgr_renderxml
+@END LIBXML2
+isc_stats_attach
+isc_stats_create
+isc_stats_decrement
+isc_stats_detach
+isc_stats_dump
+isc_stats_increment
+isc_stats_ncounters
+isc_stats_set
+isc_stdio_close
+isc_stdio_flush
+isc_stdio_open
+isc_stdio_read
+isc_stdio_seek
+isc_stdio_sync
+isc_stdio_tell
+isc_stdio_write
+isc_stdtime_get
+isc_string_append
+isc_string_append_truncate
+isc_string_copy
+isc_string_copy_truncate
+isc_string_printf
+isc_string_printf_truncate
+isc_string_regiondup
+isc_string_separate
+isc_string_strcasestr
+isc_string_strlcat
+isc_string_strlcpy
+isc_string_touint64
+isc_symtab_count
+isc_symtab_create
+isc_symtab_define
+isc_symtab_destroy
+isc_symtab_lookup
+isc_symtab_undefine
+isc_syslog_facilityfromstring
+isc_task_attach
+isc_task_beginexclusive
+isc_task_create
+isc_task_destroy
+isc_task_detach
+isc_task_endexclusive
+isc_task_exiting
+isc_task_getcurrenttime
+isc_task_getcurrenttimex
+isc_task_onshutdown
+isc_task_privilege
+isc_task_purge
+isc_task_purgeevent
+isc_task_purgerange
+isc_task_register
+isc_task_send
+isc_task_sendanddetach
+isc_task_setname
+isc_task_setprivilege
+isc_task_shutdown
+isc_task_unsend
+isc_taskmgr_create
+isc_taskmgr_createinctx
+isc_taskmgr_destroy
+isc_taskmgr_excltask
+isc_taskmgr_mode
+@IF NOTYET
+isc_taskmgr_renderjson
+@END NOTYET
+@IF LIBXML2
+isc_taskmgr_renderxml
+@END LIBXML2
+isc_taskmgr_setexcltask
+isc_taskmgr_setmode
+isc_taskpool_create
+isc_taskpool_destroy
+isc_taskpool_expand
+isc_taskpool_gettask
+isc_taskpool_setprivilege
+isc_taskpool_size
+isc_thread_create
+isc_thread_join
+isc_thread_key_create
+isc_thread_key_delete
+isc_thread_key_getspecific
+isc_thread_key_setspecific
+isc_thread_setconcurrency
+isc_thread_setname
+isc_time_add
+isc_time_compare
+isc_time_formatISO8601
+isc_time_formatISO8601ms
+isc_time_formathttptimestamp
+isc_time_formattimestamp
+isc_time_isepoch
+isc_time_microdiff
+isc_time_nanoseconds
+isc_time_now
+isc_time_nowplusinterval
+isc_time_parsehttptimestamp
+isc_time_secondsastimet
+isc_time_seconds
+isc_time_set
+isc_time_settoepoch
+isc_time_subtract
+isc_timer_attach
+isc_timer_create
+isc_timer_detach
+isc_timer_gettype
+isc_timer_register
+isc_timer_reset
+isc_timer_touch
+isc_timermgr_create
+isc_timermgr_createinctx
+isc_timermgr_destroy
+isc_timermgr_poke
+isc_tm_timegm
+isc_tm_strptime
+isc_win32os_versioncheck
+openlog
+@IF PKCS11
+pk11_attribute_bytype
+pk11_attribute_first
+pk11_attribute_next
+pk11_dump_tokens
+pk11_error_fatalcheck
+pk11_finalize
+pk11_get_best_token
+pk11_get_lib_name
+pk11_get_load_error_message
+pk11_get_session
+pk11_initialize
+pk11_initmsgcat
+pk11_mem_get
+pk11_mem_put
+pk11_numbits
+pk11_parse_uri
+pk11_rand_bytes
+pk11_rand_seed_fromfile
+pk11_result_register
+pk11_result_totext
+pk11_return_session
+pk11_set_lib_name
+pkcs_C_CloseSession
+pkcs_C_CreateObject
+pkcs_C_DeriveKey
+pkcs_C_DestroyObject
+pkcs_C_DigestFinal
+pkcs_C_DigestInit
+pkcs_C_DigestUpdate
+pkcs_C_Encrypt
+pkcs_C_EncryptInit
+pkcs_C_Finalize
+pkcs_C_FindObjects
+pkcs_C_FindObjectsFinal
+pkcs_C_FindObjectsInit
+pkcs_C_GenerateKey
+pkcs_C_GenerateKeyPair
+pkcs_C_GenerateRandom
+pkcs_C_GetAttributeValue
+pkcs_C_GetMechanismInfo
+pkcs_C_GetSlotList
+pkcs_C_GetTokenInfo
+pkcs_C_Initialize
+pkcs_C_Login
+pkcs_C_Logout
+pkcs_C_OpenSession
+pkcs_C_SeedRandom
+pkcs_C_SetAttributeValue
+pkcs_C_Sign
+pkcs_C_SignFinal
+pkcs_C_SignInit
+pkcs_C_SignUpdate
+pkcs_C_Verify
+pkcs_C_VerifyFinal
+pkcs_C_VerifyInit
+pkcs_C_VerifyUpdate
+@END PKCS11
+syslog
+
+@IF NOLONGER
+; Exported Data
+
+EXPORTS
+
+isc__backtrace_nsymbols DATA
+isc__backtrace_symtable DATA
+isc_bind9 DATA
+isc_commandline_argument DATA
+isc_commandline_errprint DATA
+isc_commandline_index DATA
+isc_commandline_option DATA
+isc_commandline_progname DATA
+isc_commandline_reset DATA
+isc_dscp_check_value DATA
+isc_hashctx DATA
+isc_mem_debugging DATA
+isc_msgcat DATA
+@IF PKCS11
+pk11_msgcat DATA
+pk11_verbose_init DATA
+@END PKCS11
+@END NOLONGER
diff --git a/lib/isc/win32/libisc.dsp.in b/lib/isc/win32/libisc.dsp.in
new file mode 100644
index 0000000..d21edb8
--- /dev/null
+++ b/lib/isc/win32/libisc.dsp.in
@@ -0,0 +1,949 @@
+# Microsoft Developer Studio Project File - Name="libisc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Dynamic-Link Library" 0x0102
+
+CFG=libisc - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "libisc.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libisc - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Dynamic-Link Library")
+!MESSAGE "libisc - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 @COPTX@ @COPTI@ /O2 /D "BIND9" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" @COPTY@ /FD /c
+@IF PKCS11
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @ZLIB_INC@ /I "include" /I "../include" /I "win32" /I "../../isccfg/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /D "BIND9" @CRYPTO@ @PK11_LIB_LOCATION@ /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" @COPTY@ /FD /c
+@ELSE PKCS11
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @ZLIB_INC@ /I "include" /I "../include" /I "win32" /I "../../isccfg/include" /D "BIND9" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" @COPTY@ /FD /c
+@END PKCS11
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll @MACHINE@
+# ADD LINK32 @LIBXML2_LIB@ @OPENSSL_LIB@ @ZLIB_LIB@ user32.lib advapi32.lib ws2_32.lib /nologo /dll @MACHINE@ /out:"../../../Build/Release/libisc.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "BIND9" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" @COPTY@ /FD /GZ /c
+@IF PKCS11
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @ZLIB_INC@ /I "include" /I "../include" /I "win32" /I "../../isccfg/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /D "BIND9" @CRYPTO@ @PK11_LIB_LOCATION@ /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR @COPTY@ /FD /GZ /c
+@ELSE PKCS11
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @ZLIB_INC@ /I "include" /I "../include" /I "win32" /I "../../isccfg/include" /D "BIND9" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR @COPTY@ /FD /GZ /c
+@END PKCS11
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 @LIBXML2_LIB@ @OPENSSL_LIB@ @ZLIB_LIB@ user32.lib advapi32.lib ws2_32.lib /nologo /dll /map /debug @MACHINE@ /out:"../../../Build/Debug/libisc.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "libisc - @PLATFORM@ Release"
+# Name "libisc - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\app.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\condition.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dir.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\DLLMain.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\entropy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\errno.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\errno2result.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fsaccess.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\interfaceiter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ipv6.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\keyboard.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\meminfo.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\net.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ntpaths.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\once.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os.c
+# End Source File
+@IF PKCS11
+# Begin Source File
+
+SOURCE=.\pk11_api.c
+# End Source File
+@END PKCS11
+# Begin Source File
+
+SOURCE=.\resource.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\socket.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\stdio.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\stdtime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strerror.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\syslog.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\thread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\time.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\version.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\win32os.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+@IF AES
+# Begin Source File
+
+SOURCE=..\include\isc\aes.h
+# End Source File
+@END AES
+# Begin Source File
+
+SOURCE=..\include\isc\app.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\assertions.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\backtrace.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\base32.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\base64.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\bind9.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\bind_registry.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\bindevt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\boolean.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\buffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\bufferlist.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\commandline.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\counter.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\condition.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\crc64.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\dir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\entropy.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\errno.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\errno2result.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\error.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\event.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\eventclass.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\file.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\formatcheck.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\fsaccess.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\hash.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\heap.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\hex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\hmacmd5.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\hmacsha.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\ht.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\httpd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\int.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\interfaceiter.h
+# End Source File
+@IF PKCS11
+# Begin Source File
+
+SOURCE=..\include\pk11\internal.h
+# End Source File
+@END PKCS11
+# Begin Source File
+
+SOURCE=.\include\isc\ipv6.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\iterated_hash.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\keyboard.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\json.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\lang.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\lex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\lfsr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\lib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\list.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\log.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\magic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\md5.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\mem.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\meminfo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\msgcat.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\mutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\mutexblock.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\net.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\netaddr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\netscope.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\netdb.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\ntgroups.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\ntpaths.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\offset.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\once.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\ondestroy.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\os.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\parseint.h
+# End Source File
+@IF PKCS11
+# Begin Source File
+
+SOURCE=..\include\pk11\pk11.h
+# End Source File
+@END PKCS11
+# Begin Source File
+
+SOURCE=..\include\isc\pool.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\portset.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\platform.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\print.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\queue.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\quota.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\radix.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\random.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\ratelimiter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\refcount.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\regex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\region.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\result.h
+# End Source File
+@IF PKCS11
+# Begin Source File
+
+SOURCE=..\include\pk11\result.h
+# End Source File
+@END PKCS11
+# Begin Source File
+
+SOURCE=..\include\isc\resultclass.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\rwlock.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\safe.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\serial.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\sha1.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\sha2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\sockaddr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\socket.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\stat.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\stats.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\stdio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\stdlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\stdtime.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\strerror.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\string.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\symtab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\syslog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\syslog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\task.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\taskpool.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\thread.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\time.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\timer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\tm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\win32os.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\types.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\unistd.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\util.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\versions.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\xml.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Main Isc Lib"
+
+# PROP Default_Filter "c"
+@IF AES
+# Begin Source File
+
+SOURCE=..\aes.c
+# End Source File
+@END AES
+# Begin Source File
+
+SOURCE=..\assertions.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\backtrace.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\backtrace-emptytbl.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\base32.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\base64.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\bind9.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\buffer.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\bufferlist.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\commandline.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\counter.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\crc64.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\error.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\event.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\hash.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\heap.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\hex.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\hmacmd5.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\hmacsha.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ht.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\httpd.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\inet_aton.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\inet_ntop.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\inet_pton.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\iterated_hash.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lex.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lfsr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\log.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\md5.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mem.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\nls\msgcat.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mutexblock.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\netaddr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\netscope.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ondestroy.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\parseint.c
+# End Source File
+@IF PKCS11
+# Begin Source File
+
+SOURCE=..\pk11.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\pk11_result.c
+# End Source File
+@END PKCS11
+# Begin Source File
+
+SOURCE=..\pool.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\portset.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\quota.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\radix.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\random.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ratelimiter.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\refcount.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\regex.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\region.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\result.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\rwlock.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\safe.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\serial.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\sha1.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\sha2.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\sockaddr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\stats.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\string.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\symtab.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\task.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\taskpool.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\timer.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\tm.c
+# End Source File
+# End Group
+@IF ATOMIC
+# Begin Source File
+
+SOURCE=.\include\atomic.h
+# End Source File
+@ELSE ATOMIC
+# Begin Source File
+
+SOURCE=..\noatomic\include\atomic.h
+# End Source File
+@END ATOMIC
+# Begin Source File
+
+SOURCE=.\libisc.def
+# End Source File
+# End Target
+# End Project
diff --git a/lib/isc/win32/libisc.dsw b/lib/isc/win32/libisc.dsw
new file mode 100644
index 0000000..49c089c
--- /dev/null
+++ b/lib/isc/win32/libisc.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "libisc"=".\libisc.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/lib/isc/win32/libisc.mak.in b/lib/isc/win32/libisc.mak.in
new file mode 100644
index 0000000..9a6acd5
--- /dev/null
+++ b/lib/isc/win32/libisc.mak.in
@@ -0,0 +1,2398 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on libisc.dsp
+!IF "$(CFG)" == ""
+CFG=libisc - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to libisc - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "libisc - @PLATFORM@ Release" && "$(CFG)" != "libisc - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libisc - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Dynamic-Link Library")
+!MESSAGE "libisc - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+LIBXML=@LIBXML2_LIB@
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\libisc.dll"
+
+
+CLEAN :
+@IF AES
+ -@erase "$(INTDIR)\aes.obj"
+@END AES
+ -@erase "$(INTDIR)\app.obj"
+ -@erase "$(INTDIR)\assertions.obj"
+ -@erase "$(INTDIR)\backtrace.obj"
+ -@erase "$(INTDIR)\backtrace-emptytbl.obj"
+ -@erase "$(INTDIR)\base32.obj"
+ -@erase "$(INTDIR)\base64.obj"
+ -@erase "$(INTDIR)\bind9.obj"
+ -@erase "$(INTDIR)\buffer.obj"
+ -@erase "$(INTDIR)\bufferlist.obj"
+ -@erase "$(INTDIR)\commandline.obj"
+ -@erase "$(INTDIR)\counter.obj"
+ -@erase "$(INTDIR)\condition.obj"
+ -@erase "$(INTDIR)\crc64.obj"
+ -@erase "$(INTDIR)\dir.obj"
+ -@erase "$(INTDIR)\DLLMain.obj"
+ -@erase "$(INTDIR)\entropy.obj"
+ -@erase "$(INTDIR)\errno.obj"
+ -@erase "$(INTDIR)\errno2result.obj"
+ -@erase "$(INTDIR)\error.obj"
+ -@erase "$(INTDIR)\event.obj"
+ -@erase "$(INTDIR)\file.obj"
+ -@erase "$(INTDIR)\fsaccess.obj"
+ -@erase "$(INTDIR)\hash.obj"
+ -@erase "$(INTDIR)\heap.obj"
+ -@erase "$(INTDIR)\hex.obj"
+ -@erase "$(INTDIR)\hmacmd5.obj"
+ -@erase "$(INTDIR)\hmacsha.obj"
+ -@erase "$(INTDIR)\ht.obj"
+ -@erase "$(INTDIR)\httpd.obj"
+ -@erase "$(INTDIR)\inet_aton.obj"
+ -@erase "$(INTDIR)\inet_ntop.obj"
+ -@erase "$(INTDIR)\inet_pton.obj"
+ -@erase "$(INTDIR)\interfaceiter.obj"
+ -@erase "$(INTDIR)\ipv6.obj"
+ -@erase "$(INTDIR)\iterated_hash.obj"
+ -@erase "$(INTDIR)\keyboard.obj"
+ -@erase "$(INTDIR)\lex.obj"
+ -@erase "$(INTDIR)\lfsr.obj"
+ -@erase "$(INTDIR)\lib.obj"
+ -@erase "$(INTDIR)\log.obj"
+ -@erase "$(INTDIR)\md5.obj"
+ -@erase "$(INTDIR)\mem.obj"
+ -@erase "$(INTDIR)\msgcat.obj"
+ -@erase "$(INTDIR)\mutexblock.obj"
+ -@erase "$(INTDIR)\meminfo.obj"
+ -@erase "$(INTDIR)\net.obj"
+ -@erase "$(INTDIR)\netaddr.obj"
+ -@erase "$(INTDIR)\netscope.obj"
+ -@erase "$(INTDIR)\ntpaths.obj"
+ -@erase "$(INTDIR)\once.obj"
+ -@erase "$(INTDIR)\ondestroy.obj"
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(INTDIR)\parseint.obj"
+@IF PKCS11
+ -@erase "$(INTDIR)\pk11.obj"
+ -@erase "$(INTDIR)\pk11_api.obj"
+ -@erase "$(INTDIR)\pk11_result.obj"
+@END PKCS11
+ -@erase "$(INTDIR)\pool.obj"
+ -@erase "$(INTDIR)\portset.obj"
+ -@erase "$(INTDIR)\quota.obj"
+ -@erase "$(INTDIR)\radix.obj"
+ -@erase "$(INTDIR)\random.obj"
+ -@erase "$(INTDIR)\ratelimiter.obj"
+ -@erase "$(INTDIR)\refcount.obj"
+ -@erase "$(INTDIR)\regex.obj"
+ -@erase "$(INTDIR)\region.obj"
+ -@erase "$(INTDIR)\resource.obj"
+ -@erase "$(INTDIR)\result.obj"
+ -@erase "$(INTDIR)\rwlock.obj"
+ -@erase "$(INTDIR)\safe.obj"
+ -@erase "$(INTDIR)\serial.obj"
+ -@erase "$(INTDIR)\sha1.obj"
+ -@erase "$(INTDIR)\sha2.obj"
+ -@erase "$(INTDIR)\sockaddr.obj"
+ -@erase "$(INTDIR)\socket.obj"
+ -@erase "$(INTDIR)\stats.obj"
+ -@erase "$(INTDIR)\stdio.obj"
+ -@erase "$(INTDIR)\stdtime.obj"
+ -@erase "$(INTDIR)\strerror.obj"
+ -@erase "$(INTDIR)\string.obj"
+ -@erase "$(INTDIR)\symtab.obj"
+ -@erase "$(INTDIR)\syslog.obj"
+ -@erase "$(INTDIR)\task.obj"
+ -@erase "$(INTDIR)\taskpool.obj"
+ -@erase "$(INTDIR)\thread.obj"
+ -@erase "$(INTDIR)\time.obj"
+ -@erase "$(INTDIR)\timer.obj"
+ -@erase "$(INTDIR)\tm.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\version.obj"
+ -@erase "$(INTDIR)\win32os.obj"
+ -@erase "$(OUTDIR)\libisc.exp"
+ -@erase "$(OUTDIR)\libisc.lib"
+ -@erase "..\..\..\Build\Release\libisc.dll"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+@IF PKCS11
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "win32" /I "../../isccfg/include" /I "../../dns/win32/include" /I "../../dns/include" @LIBXML2_INC@ @OPENSSL_INC@ @ZLIB_INC@ /D "BIND9" @CRYPTO@ @PK11_LIB_LOCATION@ /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /Fp"$(INTDIR)\libisc.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+@ELSE PKCS11
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "win32" /I "../../isccfg/include" @LIBXML2_INC@ @OPENSSL_INC@ @ZLIB_INC@ /D "BIND9" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /Fp"$(INTDIR)\libisc.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+@END PKCS11
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\libisc.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib $(LIBXML) @OPENSSL_LIB@ @ZLIB_LIB@ /nologo /dll /incremental:no /pdb:"$(OUTDIR)\libisc.pdb" @MACHINE@ /def:".\libisc.def" /out:"../../../Build/Release/libisc.dll" /implib:"$(OUTDIR)\libisc.lib"
+DEF_FILE= \
+ ".\libisc.def"
+LINK32_OBJS= \
+ "$(INTDIR)\app.obj" \
+ "$(INTDIR)\condition.obj" \
+ "$(INTDIR)\dir.obj" \
+ "$(INTDIR)\DLLMain.obj" \
+ "$(INTDIR)\entropy.obj" \
+ "$(INTDIR)\errno.obj" \
+ "$(INTDIR)\errno2result.obj" \
+ "$(INTDIR)\file.obj" \
+ "$(INTDIR)\fsaccess.obj" \
+ "$(INTDIR)\interfaceiter.obj" \
+ "$(INTDIR)\ipv6.obj" \
+ "$(INTDIR)\iterated_hash.obj" \
+ "$(INTDIR)\keyboard.obj" \
+ "$(INTDIR)\meminfo.obj" \
+ "$(INTDIR)\net.obj" \
+ "$(INTDIR)\ntpaths.obj" \
+ "$(INTDIR)\once.obj" \
+ "$(INTDIR)\os.obj" \
+@IF PKCS11
+ "$(INTDIR)\pk11_api.obj" \
+@END PKCS11
+ "$(INTDIR)\resource.obj" \
+ "$(INTDIR)\socket.obj" \
+ "$(INTDIR)\stdio.obj" \
+ "$(INTDIR)\stdtime.obj" \
+ "$(INTDIR)\strerror.obj" \
+ "$(INTDIR)\syslog.obj" \
+ "$(INTDIR)\thread.obj" \
+ "$(INTDIR)\time.obj" \
+ "$(INTDIR)\version.obj" \
+ "$(INTDIR)\win32os.obj" \
+@IF AES
+ "$(INTDIR)\aes.obj" \
+@END AES
+ "$(INTDIR)\assertions.obj" \
+ "$(INTDIR)\backtrace.obj" \
+ "$(INTDIR)\backtrace-emptytbl.obj" \
+ "$(INTDIR)\base32.obj" \
+ "$(INTDIR)\base64.obj" \
+ "$(INTDIR)\bind9.obj" \
+ "$(INTDIR)\buffer.obj" \
+ "$(INTDIR)\bufferlist.obj" \
+ "$(INTDIR)\commandline.obj" \
+ "$(INTDIR)\counter.obj" \
+ "$(INTDIR)\crc64.obj" \
+ "$(INTDIR)\error.obj" \
+ "$(INTDIR)\event.obj" \
+ "$(INTDIR)\hash.obj" \
+ "$(INTDIR)\heap.obj" \
+ "$(INTDIR)\hex.obj" \
+ "$(INTDIR)\hmacmd5.obj" \
+ "$(INTDIR)\hmacsha.obj" \
+ "$(INTDIR)\ht.obj" \
+ "$(INTDIR)\httpd.obj" \
+ "$(INTDIR)\inet_aton.obj" \
+ "$(INTDIR)\inet_ntop.obj" \
+ "$(INTDIR)\inet_pton.obj" \
+ "$(INTDIR)\lex.obj" \
+ "$(INTDIR)\lfsr.obj" \
+ "$(INTDIR)\lib.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\md5.obj" \
+ "$(INTDIR)\mem.obj" \
+ "$(INTDIR)\msgcat.obj" \
+ "$(INTDIR)\mutexblock.obj" \
+ "$(INTDIR)\netaddr.obj" \
+ "$(INTDIR)\netscope.obj" \
+ "$(INTDIR)\ondestroy.obj" \
+@IF PKCS11
+ "$(INTDIR)\pk11.obj" \
+ "$(INTDIR)\pk11_result.obj" \
+@END PKCS11
+ "$(INTDIR)\quota.obj" \
+ "$(INTDIR)\radix.obj" \
+ "$(INTDIR)\random.obj" \
+ "$(INTDIR)\ratelimiter.obj" \
+ "$(INTDIR)\refcount.obj" \
+ "$(INTDIR)\result.obj" \
+ "$(INTDIR)\rwlock.obj" \
+ "$(INTDIR)\safe.obj" \
+ "$(INTDIR)\serial.obj" \
+ "$(INTDIR)\sha1.obj" \
+ "$(INTDIR)\sha2.obj" \
+ "$(INTDIR)\sockaddr.obj" \
+ "$(INTDIR)\stats.obj" \
+ "$(INTDIR)\string.obj" \
+ "$(INTDIR)\symtab.obj" \
+ "$(INTDIR)\task.obj" \
+ "$(INTDIR)\taskpool.obj" \
+ "$(INTDIR)\timer.obj" \
+ "$(INTDIR)\tm.obj" \
+ "$(INTDIR)\parseint.obj" \
+ "$(INTDIR)\pool.obj" \
+ "$(INTDIR)\portset.obj" \
+ "$(INTDIR)\regex.obj" \
+ "$(INTDIR)\region.obj"
+
+"..\..\..\Build\Release\libisc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_DLL)
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\libisc.dll" "$(OUTDIR)\libisc.bsc"
+
+
+CLEAN :
+@IF AES
+ -@erase "$(INTDIR)\aes.obj"
+ -@erase "$(INTDIR)\aes.sbr"
+@END AES
+ -@erase "$(INTDIR)\app.obj"
+ -@erase "$(INTDIR)\app.sbr"
+ -@erase "$(INTDIR)\assertions.obj"
+ -@erase "$(INTDIR)\assertions.sbr"
+ -@erase "$(INTDIR)\backtrace.obj"
+ -@erase "$(INTDIR)\backtrace-emptytbl.obj"
+ -@erase "$(INTDIR)\backtrace.sbr"
+ -@erase "$(INTDIR)\backtrace-emptytbl.sbr"
+ -@erase "$(INTDIR)\base32.obj"
+ -@erase "$(INTDIR)\base32.sbr"
+ -@erase "$(INTDIR)\base64.obj"
+ -@erase "$(INTDIR)\base64.sbr"
+ -@erase "$(INTDIR)\bind9.obj"
+ -@erase "$(INTDIR)\bind9.sbr"
+ -@erase "$(INTDIR)\buffer.obj"
+ -@erase "$(INTDIR)\buffer.sbr"
+ -@erase "$(INTDIR)\bufferlist.obj"
+ -@erase "$(INTDIR)\bufferlist.sbr"
+ -@erase "$(INTDIR)\commandline.obj"
+ -@erase "$(INTDIR)\commandline.sbr"
+ -@erase "$(INTDIR)\counter.obj"
+ -@erase "$(INTDIR)\counter.sbr"
+ -@erase "$(INTDIR)\condition.obj"
+ -@erase "$(INTDIR)\condition.sbr"
+ -@erase "$(INTDIR)\crc64.obj"
+ -@erase "$(INTDIR)\crc64.sbr"
+ -@erase "$(INTDIR)\dir.obj"
+ -@erase "$(INTDIR)\dir.sbr"
+ -@erase "$(INTDIR)\DLLMain.obj"
+ -@erase "$(INTDIR)\DLLMain.sbr"
+ -@erase "$(INTDIR)\entropy.obj"
+ -@erase "$(INTDIR)\entropy.sbr"
+ -@erase "$(INTDIR)\errno.obj"
+ -@erase "$(INTDIR)\errno.sbr"
+ -@erase "$(INTDIR)\errno2result.obj"
+ -@erase "$(INTDIR)\errno2result.sbr"
+ -@erase "$(INTDIR)\error.obj"
+ -@erase "$(INTDIR)\error.sbr"
+ -@erase "$(INTDIR)\event.obj"
+ -@erase "$(INTDIR)\event.sbr"
+ -@erase "$(INTDIR)\file.obj"
+ -@erase "$(INTDIR)\file.sbr"
+ -@erase "$(INTDIR)\fsaccess.obj"
+ -@erase "$(INTDIR)\fsaccess.sbr"
+ -@erase "$(INTDIR)\hash.obj"
+ -@erase "$(INTDIR)\hash.sbr"
+ -@erase "$(INTDIR)\heap.obj"
+ -@erase "$(INTDIR)\heap.sbr"
+ -@erase "$(INTDIR)\hex.obj"
+ -@erase "$(INTDIR)\hex.sbr"
+ -@erase "$(INTDIR)\hmacmd5.obj"
+ -@erase "$(INTDIR)\hmacmd5.sbr"
+ -@erase "$(INTDIR)\hmacsha.obj"
+ -@erase "$(INTDIR)\hmacsha.sbr"
+ -@erase "$(INTDIR)\ht.obj"
+ -@erase "$(INTDIR)\ht.sbr"
+ -@erase "$(INTDIR)\httpd.obj"
+ -@erase "$(INTDIR)\httpd.sbr"
+ -@erase "$(INTDIR)\inet_aton.obj"
+ -@erase "$(INTDIR)\inet_aton.sbr"
+ -@erase "$(INTDIR)\inet_ntop.obj"
+ -@erase "$(INTDIR)\inet_ntop.sbr"
+ -@erase "$(INTDIR)\inet_pton.obj"
+ -@erase "$(INTDIR)\inet_pton.sbr"
+ -@erase "$(INTDIR)\interfaceiter.obj"
+ -@erase "$(INTDIR)\interfaceiter.sbr"
+ -@erase "$(INTDIR)\ipv6.obj"
+ -@erase "$(INTDIR)\ipv6.sbr"
+ -@erase "$(INTDIR)\iterated_hash.obj"
+ -@erase "$(INTDIR)\iterated_hash.sbr"
+ -@erase "$(INTDIR)\keyboard.obj"
+ -@erase "$(INTDIR)\keyboard.sbr"
+ -@erase "$(INTDIR)\lex.obj"
+ -@erase "$(INTDIR)\lex.sbr"
+ -@erase "$(INTDIR)\lfsr.obj"
+ -@erase "$(INTDIR)\lfsr.sbr"
+ -@erase "$(INTDIR)\lib.obj"
+ -@erase "$(INTDIR)\lib.sbr"
+ -@erase "$(INTDIR)\log.obj"
+ -@erase "$(INTDIR)\log.sbr"
+ -@erase "$(INTDIR)\md5.obj"
+ -@erase "$(INTDIR)\md5.sbr"
+ -@erase "$(INTDIR)\mem.obj"
+ -@erase "$(INTDIR)\mem.sbr"
+ -@erase "$(INTDIR)\msgcat.obj"
+ -@erase "$(INTDIR)\msgcat.sbr"
+ -@erase "$(INTDIR)\mutexblock.obj"
+ -@erase "$(INTDIR)\mutexblock.sbr"
+ -@erase "$(INTDIR)\meminfo.obj"
+ -@erase "$(INTDIR)\meminfo.sbr"
+ -@erase "$(INTDIR)\net.obj"
+ -@erase "$(INTDIR)\net.sbr"
+ -@erase "$(INTDIR)\netaddr.obj"
+ -@erase "$(INTDIR)\netaddr.sbr"
+ -@erase "$(INTDIR)\netscope.obj"
+ -@erase "$(INTDIR)\netscope.sbr"
+ -@erase "$(INTDIR)\ntpaths.obj"
+ -@erase "$(INTDIR)\ntpaths.sbr"
+ -@erase "$(INTDIR)\once.obj"
+ -@erase "$(INTDIR)\once.sbr"
+ -@erase "$(INTDIR)\ondestroy.obj"
+ -@erase "$(INTDIR)\ondestroy.sbr"
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(INTDIR)\os.sbr"
+ -@erase "$(INTDIR)\parseint.obj"
+ -@erase "$(INTDIR)\parseint.sbr"
+@IF PKCS11
+ -@erase "$(INTDIR)\pk11.obj"
+ -@erase "$(INTDIR)\pk11_api.obj"
+ -@erase "$(INTDIR)\pk11_result.obj"
+@END PKCS11
+ -@erase "$(INTDIR)\pool.obj"
+ -@erase "$(INTDIR)\pool.sbr"
+ -@erase "$(INTDIR)\portset.obj"
+ -@erase "$(INTDIR)\portset.sbr"
+ -@erase "$(INTDIR)\quota.obj"
+ -@erase "$(INTDIR)\quota.sbr"
+ -@erase "$(INTDIR)\radix.obj"
+ -@erase "$(INTDIR)\radix.sbr"
+ -@erase "$(INTDIR)\random.obj"
+ -@erase "$(INTDIR)\random.sbr"
+ -@erase "$(INTDIR)\ratelimiter.obj"
+ -@erase "$(INTDIR)\ratelimiter.sbr"
+ -@erase "$(INTDIR)\refcount.obj"
+ -@erase "$(INTDIR)\refcount.sbr"
+ -@erase "$(INTDIR)\regex.obj"
+ -@erase "$(INTDIR)\regex.sbr"
+ -@erase "$(INTDIR)\region.obj"
+ -@erase "$(INTDIR)\region.sbr"
+ -@erase "$(INTDIR)\resource.obj"
+ -@erase "$(INTDIR)\resource.sbr"
+ -@erase "$(INTDIR)\result.obj"
+ -@erase "$(INTDIR)\result.sbr"
+ -@erase "$(INTDIR)\rwlock.obj"
+ -@erase "$(INTDIR)\rwlock.sbr"
+ -@erase "$(INTDIR)\safe.obj"
+ -@erase "$(INTDIR)\safe.sbr"
+ -@erase "$(INTDIR)\serial.obj"
+ -@erase "$(INTDIR)\serial.sbr"
+ -@erase "$(INTDIR)\sha1.obj"
+ -@erase "$(INTDIR)\sha1.sbr"
+ -@erase "$(INTDIR)\sha2.obj"
+ -@erase "$(INTDIR)\sha2.sbr"
+ -@erase "$(INTDIR)\sockaddr.obj"
+ -@erase "$(INTDIR)\sockaddr.sbr"
+ -@erase "$(INTDIR)\socket.obj"
+ -@erase "$(INTDIR)\socket.sbr"
+ -@erase "$(INTDIR)\stats.obj"
+ -@erase "$(INTDIR)\stats.sbr"
+ -@erase "$(INTDIR)\stdio.obj"
+ -@erase "$(INTDIR)\stdio.sbr"
+ -@erase "$(INTDIR)\stdtime.obj"
+ -@erase "$(INTDIR)\stdtime.sbr"
+ -@erase "$(INTDIR)\strerror.obj"
+ -@erase "$(INTDIR)\strerror.sbr"
+ -@erase "$(INTDIR)\string.obj"
+ -@erase "$(INTDIR)\string.sbr"
+ -@erase "$(INTDIR)\symtab.obj"
+ -@erase "$(INTDIR)\symtab.sbr"
+ -@erase "$(INTDIR)\syslog.obj"
+ -@erase "$(INTDIR)\syslog.sbr"
+ -@erase "$(INTDIR)\task.obj"
+ -@erase "$(INTDIR)\task.sbr"
+ -@erase "$(INTDIR)\taskpool.obj"
+ -@erase "$(INTDIR)\taskpool.sbr"
+ -@erase "$(INTDIR)\thread.obj"
+ -@erase "$(INTDIR)\thread.sbr"
+ -@erase "$(INTDIR)\time.obj"
+ -@erase "$(INTDIR)\time.sbr"
+ -@erase "$(INTDIR)\timer.obj"
+ -@erase "$(INTDIR)\timer.sbr"
+ -@erase "$(INTDIR)\tm.obj"
+ -@erase "$(INTDIR)\tm.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\version.obj"
+ -@erase "$(INTDIR)\version.sbr"
+ -@erase "$(INTDIR)\win32os.obj"
+ -@erase "$(INTDIR)\win32os.sbr"
+ -@erase "$(OUTDIR)\libisc.bsc"
+ -@erase "$(OUTDIR)\libisc.exp"
+ -@erase "$(OUTDIR)\libisc.lib"
+ -@erase "$(OUTDIR)\libisc.map"
+ -@erase "$(OUTDIR)\libisc.pdb"
+ -@erase "..\..\..\Build\Debug\libisc.dll"
+ -@erase "..\..\..\Build\Debug\libisc.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+@IF PKCS11
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "win32" /I "../../isccfg/include" /I "../../dns/win32/include" /I "../../dns/include" @LIBXML2_INC@ @OPENSSL_INC@ @ZLIB_INC@ /D "BIND9" @CRYPTO@ @PK11_LIB_LOCATION@ /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\libisc.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+@ELSE PKCS11
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "win32" /I "../../isccfg/include" @LIBXML2_INC@ @OPENSSL_INC@ @ZLIB_INC@ /D "BIND9" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\libisc.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+@END PKCS11
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\libisc.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\app.sbr" \
+ "$(INTDIR)\condition.sbr" \
+ "$(INTDIR)\dir.sbr" \
+ "$(INTDIR)\DLLMain.sbr" \
+ "$(INTDIR)\entropy.sbr" \
+ "$(INTDIR)\errno.sbr" \
+ "$(INTDIR)\errno2result.sbr" \
+ "$(INTDIR)\file.sbr" \
+ "$(INTDIR)\fsaccess.sbr" \
+ "$(INTDIR)\interfaceiter.sbr" \
+ "$(INTDIR)\ipv6.sbr" \
+ "$(INTDIR)\iterated_hash.sbr" \
+ "$(INTDIR)\keyboard.sbr" \
+ "$(INTDIR)\meminfo.sbr" \
+ "$(INTDIR)\net.sbr" \
+ "$(INTDIR)\ntpaths.sbr" \
+ "$(INTDIR)\once.sbr" \
+ "$(INTDIR)\os.sbr" \
+@IF PKCS11
+ "$(INTDIR)\pk11_api.sbr" \
+@END PKCS11
+ "$(INTDIR)\resource.sbr" \
+ "$(INTDIR)\socket.sbr" \
+ "$(INTDIR)\stdio.sbr" \
+ "$(INTDIR)\stdtime.sbr" \
+ "$(INTDIR)\strerror.sbr" \
+ "$(INTDIR)\syslog.sbr" \
+ "$(INTDIR)\thread.sbr" \
+ "$(INTDIR)\time.sbr" \
+ "$(INTDIR)\version.sbr" \
+ "$(INTDIR)\win32os.sbr" \
+@IF AES
+ "$(INTDIR)\aes.sbr" \
+@END AES
+ "$(INTDIR)\assertions.sbr" \
+ "$(INTDIR)\backtrace.sbr" \
+ "$(INTDIR)\backtrace-emptytbl.sbr" \
+ "$(INTDIR)\base32.sbr" \
+ "$(INTDIR)\base64.sbr" \
+ "$(INTDIR)\bind9.sbr" \
+ "$(INTDIR)\buffer.sbr" \
+ "$(INTDIR)\bufferlist.sbr" \
+ "$(INTDIR)\commandline.sbr" \
+ "$(INTDIR)\counter.sbr" \
+ "$(INTDIR)\crc64.sbr" \
+ "$(INTDIR)\error.sbr" \
+ "$(INTDIR)\event.sbr" \
+ "$(INTDIR)\hash.sbr" \
+ "$(INTDIR)\heap.sbr" \
+ "$(INTDIR)\hex.sbr" \
+ "$(INTDIR)\hmacmd5.sbr" \
+ "$(INTDIR)\hmacsha.sbr" \
+ "$(INTDIR)\ht.sbr" \
+ "$(INTDIR)\httpd.sbr" \
+ "$(INTDIR)\inet_aton.sbr" \
+ "$(INTDIR)\inet_ntop.sbr" \
+ "$(INTDIR)\inet_pton.sbr" \
+ "$(INTDIR)\lex.sbr" \
+ "$(INTDIR)\lfsr.sbr" \
+ "$(INTDIR)\lib.sbr" \
+ "$(INTDIR)\log.sbr" \
+ "$(INTDIR)\md5.sbr" \
+ "$(INTDIR)\mem.sbr" \
+ "$(INTDIR)\msgcat.sbr" \
+ "$(INTDIR)\mutexblock.sbr" \
+ "$(INTDIR)\netaddr.sbr" \
+ "$(INTDIR)\netscope.sbr" \
+ "$(INTDIR)\ondestroy.sbr" \
+@IF PKCS11
+ "$(INTDIR)\pk11.sbr" \
+ "$(INTDIR)\pk11_result.sbr" \
+@END PKCS11
+ "$(INTDIR)\quota.sbr" \
+ "$(INTDIR)\radix.sbr" \
+ "$(INTDIR)\random.sbr" \
+ "$(INTDIR)\ratelimiter.sbr" \
+ "$(INTDIR)\refcount.sbr" \
+ "$(INTDIR)\result.sbr" \
+ "$(INTDIR)\rwlock.sbr" \
+ "$(INTDIR)\safe.sbr" \
+ "$(INTDIR)\serial.sbr" \
+ "$(INTDIR)\sha1.sbr" \
+ "$(INTDIR)\sha2.sbr" \
+ "$(INTDIR)\sockaddr.sbr" \
+ "$(INTDIR)\stats.sbr" \
+ "$(INTDIR)\string.sbr" \
+ "$(INTDIR)\symtab.sbr" \
+ "$(INTDIR)\task.sbr" \
+ "$(INTDIR)\taskpool.sbr" \
+ "$(INTDIR)\timer.sbr" \
+ "$(INTDIR)\tm.sbr" \
+ "$(INTDIR)\parseint.sbr" \
+ "$(INTDIR)\pool.sbr" \
+ "$(INTDIR)\portset.sbr" \
+ "$(INTDIR)\regex.sbr" \
+ "$(INTDIR)\region.sbr"
+
+"$(OUTDIR)\libisc.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib $(LIBXML) @OPENSSL_LIB@ @ZLIB_LIB@ /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\libisc.pdb" /map:"$(INTDIR)\libisc.map" /debug @MACHINE@ /def:".\libisc.def" /out:"../../../Build/Debug/libisc.dll" /implib:"$(OUTDIR)\libisc.lib" /pdbtype:sept
+DEF_FILE= \
+ ".\libisc.def"
+LINK32_OBJS= \
+ "$(INTDIR)\app.obj" \
+ "$(INTDIR)\condition.obj" \
+ "$(INTDIR)\dir.obj" \
+ "$(INTDIR)\DLLMain.obj" \
+ "$(INTDIR)\entropy.obj" \
+ "$(INTDIR)\errno.obj" \
+ "$(INTDIR)\errno2result.obj" \
+ "$(INTDIR)\file.obj" \
+ "$(INTDIR)\fsaccess.obj" \
+ "$(INTDIR)\interfaceiter.obj" \
+ "$(INTDIR)\ipv6.obj" \
+ "$(INTDIR)\iterated_hash.obj" \
+ "$(INTDIR)\keyboard.obj" \
+ "$(INTDIR)\meminfo.obj" \
+ "$(INTDIR)\net.obj" \
+ "$(INTDIR)\ntpaths.obj" \
+ "$(INTDIR)\once.obj" \
+ "$(INTDIR)\os.obj" \
+@IF PKCS11
+ "$(INTDIR)\pk11_api.obj" \
+@END PKCS11
+ "$(INTDIR)\resource.obj" \
+ "$(INTDIR)\socket.obj" \
+ "$(INTDIR)\stdio.obj" \
+ "$(INTDIR)\stdtime.obj" \
+ "$(INTDIR)\strerror.obj" \
+ "$(INTDIR)\syslog.obj" \
+ "$(INTDIR)\thread.obj" \
+ "$(INTDIR)\time.obj" \
+ "$(INTDIR)\version.obj" \
+ "$(INTDIR)\win32os.obj" \
+@IF AES
+ "$(INTDIR)\aes.obj" \
+@END AES
+ "$(INTDIR)\assertions.obj" \
+ "$(INTDIR)\backtrace.obj" \
+ "$(INTDIR)\backtrace-emptytbl.obj" \
+ "$(INTDIR)\base32.obj" \
+ "$(INTDIR)\base64.obj" \
+ "$(INTDIR)\bind9.obj" \
+ "$(INTDIR)\buffer.obj" \
+ "$(INTDIR)\bufferlist.obj" \
+ "$(INTDIR)\commandline.obj" \
+ "$(INTDIR)\counter.obj" \
+ "$(INTDIR)\crc64.obj" \
+ "$(INTDIR)\error.obj" \
+ "$(INTDIR)\event.obj" \
+ "$(INTDIR)\hash.obj" \
+ "$(INTDIR)\heap.obj" \
+ "$(INTDIR)\hex.obj" \
+ "$(INTDIR)\hmacmd5.obj" \
+ "$(INTDIR)\hmacsha.obj" \
+ "$(INTDIR)\ht.obj" \
+ "$(INTDIR)\httpd.obj" \
+ "$(INTDIR)\inet_aton.obj" \
+ "$(INTDIR)\inet_ntop.obj" \
+ "$(INTDIR)\inet_pton.obj" \
+ "$(INTDIR)\lex.obj" \
+ "$(INTDIR)\lfsr.obj" \
+ "$(INTDIR)\lib.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\md5.obj" \
+ "$(INTDIR)\mem.obj" \
+ "$(INTDIR)\msgcat.obj" \
+ "$(INTDIR)\mutexblock.obj" \
+ "$(INTDIR)\netaddr.obj" \
+ "$(INTDIR)\netscope.obj" \
+ "$(INTDIR)\ondestroy.obj" \
+@IF PKCS11
+ "$(INTDIR)\pk11.obj" \
+ "$(INTDIR)\pk11_result.obj" \
+@END PKCS11
+ "$(INTDIR)\quota.obj" \
+ "$(INTDIR)\radix.obj" \
+ "$(INTDIR)\random.obj" \
+ "$(INTDIR)\ratelimiter.obj" \
+ "$(INTDIR)\refcount.obj" \
+ "$(INTDIR)\result.obj" \
+ "$(INTDIR)\rwlock.obj" \
+ "$(INTDIR)\safe.obj" \
+ "$(INTDIR)\serial.obj" \
+ "$(INTDIR)\sha1.obj" \
+ "$(INTDIR)\sha2.obj" \
+ "$(INTDIR)\sockaddr.obj" \
+ "$(INTDIR)\stats.obj" \
+ "$(INTDIR)\string.obj" \
+ "$(INTDIR)\symtab.obj" \
+ "$(INTDIR)\task.obj" \
+ "$(INTDIR)\taskpool.obj" \
+ "$(INTDIR)\timer.obj" \
+ "$(INTDIR)\tm.obj" \
+ "$(INTDIR)\parseint.obj" \
+ "$(INTDIR)\pool.obj" \
+ "$(INTDIR)\portset.obj" \
+ "$(INTDIR)\regex.obj" \
+ "$(INTDIR)\region.obj"
+
+"..\..\..\Build\Debug\libisc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_DLL)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("libisc.dep")
+!INCLUDE "libisc.dep"
+!ELSE
+!MESSAGE Warning: cannot find "libisc.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release" || "$(CFG)" == "libisc - @PLATFORM@ Debug"
+SOURCE=.\app.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\app.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\app.obj" "$(INTDIR)\app.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\condition.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\condition.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\condition.obj" "$(INTDIR)\condition.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\dir.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dir.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dir.obj" "$(INTDIR)\dir.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\DLLMain.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\DLLMain.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\DLLMain.obj" "$(INTDIR)\DLLMain.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\entropy.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\entropy.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\entropy.obj" "$(INTDIR)\entropy.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\errno.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\errno.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\errno.obj" "$(INTDIR)\errno.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+
+SOURCE=.\errno2result.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\errno2result.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\errno2result.obj" "$(INTDIR)\errno2result.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\file.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\file.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\file.obj" "$(INTDIR)\file.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\fsaccess.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\fsaccess.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\fsaccess.obj" "$(INTDIR)\fsaccess.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\interfaceiter.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\interfaceiter.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\interfaceiter.obj" "$(INTDIR)\interfaceiter.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\ipv6.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\ipv6.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\ipv6.obj" "$(INTDIR)\ipv6.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+
+SOURCE=.\keyboard.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\keyboard.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\keyboard.obj" "$(INTDIR)\keyboard.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\meminfo.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\meminfo.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\meminfo.obj" "$(INTDIR)\meminfo.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\net.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\net.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\net.obj" "$(INTDIR)\net.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\ntpaths.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\ntpaths.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\ntpaths.obj" "$(INTDIR)\ntpaths.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\once.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\once.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\once.obj" "$(INTDIR)\once.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\os.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\os.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\os.obj" "$(INTDIR)\os.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\pk11_api.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\pk11_api.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\pk11_api.obj" "$(INTDIR)\pk11_api.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\resource.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\resource.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\resource.obj" "$(INTDIR)\resource.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\socket.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\socket.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\socket.obj" "$(INTDIR)\socket.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\stdio.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\stdio.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\stdio.obj" "$(INTDIR)\stdio.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\stdtime.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\stdtime.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\stdtime.obj" "$(INTDIR)\stdtime.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\strerror.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\strerror.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\strerror.obj" "$(INTDIR)\strerror.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\syslog.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\syslog.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\syslog.obj" "$(INTDIR)\syslog.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\thread.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\thread.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\thread.obj" "$(INTDIR)\thread.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\time.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\time.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\time.obj" "$(INTDIR)\time.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\version.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\version.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\version.obj" "$(INTDIR)\version.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\win32os.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\win32os.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\win32os.obj" "$(INTDIR)\win32os.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+@IF AES
+SOURCE=..\aes.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\aes.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\aes.obj" "$(INTDIR)\aes.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+@END AES
+
+SOURCE=..\assertions.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\assertions.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\assertions.obj" "$(INTDIR)\assertions.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\backtrace.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\backtrace.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\backtrace.obj" "$(INTDIR)\backtrace.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\backtrace-emptytbl.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\backtrace-emptytbl.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\backtrace-emptytbl.obj" "$(INTDIR)\backtrace-emptytbl.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\base32.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\base32.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\base32.obj" "$(INTDIR)\base32.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\base64.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\base64.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\base64.obj" "$(INTDIR)\base64.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\bind9.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\bind9.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\bind9.obj" "$(INTDIR)\bind9.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\buffer.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\buffer.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\buffer.obj" "$(INTDIR)\buffer.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\bufferlist.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\bufferlist.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\bufferlist.obj" "$(INTDIR)\bufferlist.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\commandline.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\commandline.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\commandline.obj" "$(INTDIR)\commandline.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\counter.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\counter.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\counter.obj" "$(INTDIR)\counter.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\crc64.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\crc64.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\crc64.obj" "$(INTDIR)\crc64.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\error.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\error.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\error.obj" "$(INTDIR)\error.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\event.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\event.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\event.obj" "$(INTDIR)\event.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\hash.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\hash.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\hash.obj" "$(INTDIR)\hash.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\heap.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\heap.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\heap.obj" "$(INTDIR)\heap.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\hex.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\hex.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\hex.obj" "$(INTDIR)\hex.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\hmacmd5.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\hmacmd5.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\hmacmd5.obj" "$(INTDIR)\hmacmd5.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\hmacsha.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\hmacsha.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\hmacsha.obj" "$(INTDIR)\hmacsha.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ht.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\ht.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\ht.obj" "$(INTDIR)\ht.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\httpd.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\httpd.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\httpd.obj" "$(INTDIR)\httpd.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\inet_aton.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\inet_aton.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\inet_aton.obj" "$(INTDIR)\inet_aton.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\inet_ntop.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\inet_ntop.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\inet_ntop.obj" "$(INTDIR)\inet_ntop.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\inet_pton.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\inet_pton.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\inet_pton.obj" "$(INTDIR)\inet_pton.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\iterated_hash.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\iterated_hash.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\iterated_hash.obj" "$(INTDIR)\iterated_hash.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lex.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\lex.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\lex.obj" "$(INTDIR)\lex.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lfsr.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\lfsr.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\lfsr.obj" "$(INTDIR)\lfsr.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lib.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\lib.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\lib.obj" "$(INTDIR)\lib.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\log.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\log.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\log.obj" "$(INTDIR)\log.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\md5.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\md5.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\md5.obj" "$(INTDIR)\md5.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\mem.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\mem.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\mem.obj" "$(INTDIR)\mem.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\nls\msgcat.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\msgcat.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\msgcat.obj" "$(INTDIR)\msgcat.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\mutexblock.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\mutexblock.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\mutexblock.obj" "$(INTDIR)\mutexblock.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\netaddr.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\netaddr.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\netaddr.obj" "$(INTDIR)\netaddr.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\netscope.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\netscope.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\netscope.obj" "$(INTDIR)\netscope.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ondestroy.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\ondestroy.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\ondestroy.obj" "$(INTDIR)\ondestroy.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\parseint.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\parseint.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\parseint.obj" "$(INTDIR)\parseint.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\pk11.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\pk11.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\pk11.obj" "$(INTDIR)\pk11.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\pk11_result.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\pk11_result.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\pk11_result.obj" "$(INTDIR)\pk11_result.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\pool.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\pool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\pool.obj" "$(INTDIR)\pool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\portset.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\portset.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\portset.obj" "$(INTDIR)\portset.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\quota.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\quota.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\quota.obj" "$(INTDIR)\quota.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\radix.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\radix.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\radix.obj" "$(INTDIR)\radix.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\random.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\random.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\random.obj" "$(INTDIR)\random.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ratelimiter.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\ratelimiter.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\ratelimiter.obj" "$(INTDIR)\ratelimiter.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\refcount.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\refcount.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\refcount.obj" "$(INTDIR)\refcount.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\regex.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\regex.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\regex.obj" "$(INTDIR)\regex.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+SOURCE=..\region.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\region.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\region.obj" "$(INTDIR)\region.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\result.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\result.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\result.obj" "$(INTDIR)\result.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\rwlock.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\rwlock.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\rwlock.obj" "$(INTDIR)\rwlock.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\safe.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\safe.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\safe.obj" "$(INTDIR)\safe.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\serial.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\serial.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\serial.obj" "$(INTDIR)\serial.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\sha1.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\sha1.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\sha1.obj" "$(INTDIR)\sha1.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\sha2.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\sha2.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\sha2.obj" "$(INTDIR)\sha2.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\sockaddr.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\sockaddr.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\sockaddr.obj" "$(INTDIR)\sockaddr.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\stats.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\stats.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\stats.obj" "$(INTDIR)\stats.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\string.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\string.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\string.obj" "$(INTDIR)\string.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\symtab.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\symtab.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\symtab.obj" "$(INTDIR)\symtab.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\task.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\task.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\task.obj" "$(INTDIR)\task.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\taskpool.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\taskpool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\taskpool.obj" "$(INTDIR)\taskpool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\timer.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\timer.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\timer.obj" "$(INTDIR)\timer.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\tm.c
+
+!IF "$(CFG)" == "libisc - @PLATFORM@ Release"
+
+
+"$(INTDIR)\tm.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\tm.obj" "$(INTDIR)\tm.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/lib/isc/win32/libisc.vcxproj.filters.in b/lib/isc/win32/libisc.vcxproj.filters.in
new file mode 100644
index 0000000..d6a5234
--- /dev/null
+++ b/lib/isc/win32/libisc.vcxproj.filters.in
@@ -0,0 +1,675 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Library Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Win32 Source Files">
+ <UniqueIdentifier>{289562c2-1bdd-4582-b6bd-3f598ee23cbd}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Win32 Header Files">
+ <UniqueIdentifier>{d03c3e6a-e78e-4a01-bd77-64c839b1adfe}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Library Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="libisc.def" />
+ </ItemGroup>
+ <ItemGroup>
+@IF AES
+ <ClInclude Include="..\include\isc\aes.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+@END AES
+ <ClInclude Include="..\include\isc\app.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\assertions.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\backtrace.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\base32.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\base64.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\bind9.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\boolean.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\buffer.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\bufferlist.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\commandline.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\counter.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\crc64.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\entropy.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\errno.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\error.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\event.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\eventclass.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\file.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\formatcheck.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\fsaccess.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\hash.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\heap.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\hex.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\hmacmd5.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\hmacsha.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\ht.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\httpd.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\int.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\interfaceiter.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\iterated_hash.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\json.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\lang.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\lex.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\lfsr.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\lib.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\list.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\log.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\magic.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\md5.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\mem.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\meminfo.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\msgcat.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\msgs.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\mutexblock.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\netaddr.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\netscope.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\ondestroy.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\os.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\parseint.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\pool.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\portset.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\print.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\queue.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\quota.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\radix.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\random.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\ratelimiter.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\refcount.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\regex.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\region.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\resource.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\result.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\resultclass.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\rwlock.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\safe.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\serial.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\sha1.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\sha2.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\sockaddr.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\socket.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\stats.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\stdio.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\stdlib.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\string.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\symtab.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\task.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\taskpool.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\timer.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\tm.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\types.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\util.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\version.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\isc\xml.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+@IF PKCS11
+ <ClInclude Include="..\include\pk11\constants.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\pk11\internal.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\pk11\pk11.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\pk11\result.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\pkcs11\pkcs11.h">
+ <Filter>Pkcs11 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\pkcs11\pkcs11f.h">
+ <Filter>Pkcs11 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\pkcs11\pkcs11t.h">
+ <Filter>Pkcs11 Header Files</Filter>
+ </ClInclude>
+@END PKCS11
+ <ClInclude Include="include\isc\bind_registry.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\bindevt.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\condition.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\dir.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\ipv6.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\keyboard.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\mutex.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\net.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\netdb.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\ntgroups.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\ntpaths.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\offset.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\once.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\platform.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\stat.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\stdtime.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\strerror.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\syslog.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\thread.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\time.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\isc\win32os.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="errno2result.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="syslog.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="unistd.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+@IF PKCS11
+ <ClInclude Include="include\pkcs11\cryptoki.h">
+ <Filter>Win32 Header Files</Filter>
+ </ClInclude>
+@END PKCS11
+@IF ATOMIC
+ <ClInclude Include="include\isc\atomic.h">
+@ELSE ATOMIC
+ <ClInclude Include="..\noatomic\include\isc\atomic.h">
+@END ATOMIC
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\config.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\versions.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="app.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="condition.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="dir.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="DLLMain.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="entropy.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="errno.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="errno2result.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="file.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="fsaccess.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="interfaceiter.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ipv6.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="keyboard.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="meminfo.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="net.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ntpaths.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="once.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="os.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="resource.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="socket.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="stdio.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="stdtime.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="strerror.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="syslog.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="thread.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="time.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="version.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="win32os.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+@IF PKCS11
+ <ClCompile Include="pk11_api.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+@END PKCS11
+@IF AES
+ <ClCompile Include="..\aes.c">
+ <Filter>Win32 Source Files</Filter>
+ </ClCompile>
+@END AES
+ <ClCompile Include="..\assertions.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\backtrace.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\backtrace-emptytbl.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\base32.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\base64.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\bind9.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\buffer.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\bufferlist.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\commandline.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\counter.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\crc64.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\error.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\event.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\hash.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\heap.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\hex.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\hmacmd5.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\hmacsha.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\ht.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\httpd.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\inet_aton.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\inet_ntop.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\inet_pton.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\iterated_hash.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\lex.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\lfsr.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\lib.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\log.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\md5.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\mem.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\nls\msgcat.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\mutexblock.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\netaddr.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\netscope.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\ondestroy.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\parseint.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\pool.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\portset.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\quota.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\radix.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\random.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\ratelimiter.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\refcount.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\regex.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\region.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\result.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\rwlock.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\safe.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\serial.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\sha1.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\sha2.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\sockaddr.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\stats.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\string.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\symtab.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\task.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\taskpool.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\timer.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\tm.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+@IF PKCS11
+ <ClCompile Include="..\pk11.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\pk11_result.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
+@END PKCS11
+ </ItemGroup>
+</Project>
diff --git a/lib/isc/win32/libisc.vcxproj.in b/lib/isc/win32/libisc.vcxproj.in
new file mode 100644
index 0000000..fb9222a
--- /dev/null
+++ b/lib/isc/win32/libisc.vcxproj.in
@@ -0,0 +1,530 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{3840E563-D180-4761-AA9C-E6155F02EAFF}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>libisc</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+@IF PKCS11
+ <PreprocessorDefinitions>BIND9;@CRYPTO@@PK11_LIB_LOCATION@WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBISC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;win32;..\..\isccfg\include;..\..\dns\win32\include;..\..\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+@ELSE PKCS11
+ <PreprocessorDefinitions>BIND9;WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBISC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;win32;..\..\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+@END PKCS11
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalDependencies>@LIBXML2_LIB@@OPENSSL_LIB@@ZLIB_LIB@ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ModuleDefinitionFile>$(ProjectName).def</ModuleDefinitionFile>
+ <ImportLibrary>.\$(Configuration)\$(ProjectName).lib</ImportLibrary>
+ </Link>
+ <PreBuildEvent>
+ <Command>cd ..\..\..\win32utils
+
+if NOT Exist ..\Build mkdir ..\Build
+if NOT Exist ..\Build\Debug mkdir ..\Build\Debug
+
+echo Copying COPYRIGHT notice.
+
+copy ..\COPYRIGHT ..\Build\Debug
+
+@IF OPENSSL
+echo Copying the OpenSSL DLL and LICENSE.
+
+copy @OPENSSL_DLL@ ..\Build\Debug\
+copy @OPENSSL_PATH@\LICENSE ..\Build\Debug\OpenSSL-LICENSE
+@END OPENSSL
+
+@IF LIBXML2
+echo Copying the libxml DLL.
+
+copy @LIBXML2_DLL@ ..\Build\Debug\
+@END LIBXML2
+
+@IF GSSAPI
+echo Copying the GSSAPI and KRB5 DLLs.
+
+copy @GSSAPI_DLL@ ..\Build\Debug\
+copy @KRB5_DLL@ ..\Build\Debug\
+copy @COMERR_DLL@ ..\Build\Debug\
+copy @K5SPRT_DLL@ ..\Build\Debug\
+copy @WSHELP_DLL@ ..\Build\Debug\
+@END GSSAPI
+
+@IF GEOIP
+echo Copying the GeoIP DLL.
+
+copy @GEOIP_DLL@ ..\Build\Debug\
+@END GEOIP
+
+@IF IDNKIT
+echo Copying the IDN kit DLL.
+
+copy @IDN_DLL@ ..\Build\Debug\
+copy @ICONV_DLL@ ..\Build\Debug\
+@END IDNKIT
+
+@IF ZLIB
+echo Copying the zlib DLL.
+
+copy @ZLIB_DLL@ ..\Build\Debug\
+@END ZLIB
+
+echo Copying Visual C x86 Redistributable Installer.
+
+copy /Y @VCREDIST_PATH@ ..\Build\Debug\
+
+echo Copying install files (flags and file list).
+
+copy InstallFlags ..\Build\Debug\
+copy InstallFiles ..\Build\Debug\
+
+</Command>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+@IF PKCS11
+ <PreprocessorDefinitions>BIND9;@CRYPTO@@PK11_LIB_LOCATION@WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBISC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;win32;..\..\isccfg\include;..\..\dns\win32\include;..\..\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+@ELSE PKCS11
+ <PreprocessorDefinitions>BIND9;WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBISC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;win32;..\..\isccfg\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+@END PKCS11
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalDependencies>@LIBXML2_LIB@@OPENSSL_LIB@@ZLIB_LIB@ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ModuleDefinitionFile>$(ProjectName).def</ModuleDefinitionFile>
+ <ImportLibrary>.\$(Configuration)\$(ProjectName).lib</ImportLibrary>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ </Link>
+ <PreBuildEvent>
+ <Command>cd ..\..\..\win32utils
+
+if NOT Exist ..\Build mkdir ..\Build
+if NOT Exist ..\Build\Release mkdir ..\Build\Release
+
+echo Copying the ARM and the Installation Notes.
+
+copy ..\COPYRIGHT ..\Build\Release
+copy ..\README ..\Build\Release
+copy ..\HISTORY ..\Build\Release
+copy readme1st.txt ..\Build\Release
+copy index.html ..\Build\Release
+copy ..\doc\arm\*.html ..\Build\Release
+copy ..\doc\arm\notes.pdf ..\Build\Release
+copy ..\doc\arm\Bv9ARM.pdf ..\Build\Release
+copy ..\CHANGES ..\Build\Release
+if Exist ..\CHANGES.SE copy ..\CHANGES.SE ..\Build\Release
+copy ..\FAQ ..\Build\Release
+
+echo Copying the standalone manual pages.
+
+copy ..\bin\named\named.html ..\Build\Release
+copy ..\bin\named\named.conf.html ..\Build\Release
+copy ..\bin\named\lwresd.html ..\Build\Release
+copy ..\bin\rndc\*.html ..\Build\Release
+copy ..\bin\confgen\*.html ..\Build\Release
+copy ..\bin\dig\*.html ..\Build\Release
+copy ..\bin\delv\*.html ..\Build\Release
+copy ..\bin\nsupdate\*.html ..\Build\Release
+copy ..\bin\check\*.html ..\Build\Release
+copy ..\bin\dnssec\dnssec-keygen.html ..\Build\Release
+copy ..\bin\dnssec\dnssec-signzone.html ..\Build\Release
+copy ..\bin\dnssec\dnssec-dsfromkey.html ..\Build\Release
+copy ..\bin\dnssec\dnssec-keyfromlabel.html ..\Build\Release
+copy ..\bin\dnssec\dnssec-settime.html ..\Build\Release
+copy ..\bin\dnssec\dnssec-revoke.html ..\Build\Release
+copy ..\bin\dnssec\dnssec-verify.html ..\Build\Release
+copy ..\bin\dnssec\dnssec-importkey.html ..\Build\Release
+@IF PYTHON
+copy ..\bin\python\dnssec-checkds.html ..\Build\Release
+copy ..\bin\python\dnssec-coverage.html ..\Build\Release
+copy ..\bin\python\dnssec-keymgr.html ..\Build\Release
+@END PYTHON
+@IF PKCS11
+copy ..\bin\pkcs11\pkcs11-keygen.html ..\Build\Release
+copy ..\bin\pkcs11\pkcs11-list.html ..\Build\Release
+copy ..\bin\pkcs11\pkcs11-destroy.html ..\Build\Release
+copy ..\bin\pkcs11\pkcs11-tokens.html ..\Build\Release
+@END PKCS11
+copy ..\bin\tools\arpaname.html ..\Build\Release
+copy ..\bin\tools\genrandom.html ..\Build\Release
+copy ..\bin\tools\isc-hmac-fixup.html ..\Build\Release
+copy ..\bin\tools\named-journalprint.html ..\Build\Release
+copy ..\bin\tools\named-rrchecker.html ..\Build\Release
+copy ..\bin\tools\nsec3hash.html ..\Build\Release
+copy ..\bin\tools\mdig.html ..\Build\Release
+
+echo Copying the migration notes.
+
+copy ..\doc\misc\migration ..\Build\Release
+copy ..\doc\misc\migration-4to9 ..\Build\Release
+
+@IF OPENSSL
+echo Copying the OpenSSL DLL and LICENSE.
+
+copy @OPENSSL_DLL@ ..\Build\Release\
+copy @OPENSSL_PATH@\LICENSE ..\Build\Release\OpenSSL-LICENSE
+@END OPENSSL
+
+@IF LIBXML2
+echo Copying the libxml DLL.
+
+copy @LIBXML2_DLL@ ..\Build\Release\
+@END LIBXML2
+
+@IF GSSAPI
+echo Copying the GSSAPI and KRB5 DLLs.
+
+copy @GSSAPI_DLL@ ..\Build\Release\
+copy @KRB5_DLL@ ..\Build\Release\
+copy @COMERR_DLL@ ..\Build\Release\
+copy @K5SPRT_DLL@ ..\Build\Release\
+copy @WSHELP_DLL@ ..\Build\Release\
+@END GSSAPI
+
+@IF GEOIP
+echo Copying the GeoIP DLL.
+
+copy @GEOIP_DLL@ ..\Build\Release\
+@END GEOIP
+
+@IF IDNKIT
+echo Copying the IDN kit DLL.
+
+copy @IDN_DLL@ ..\Build\Release\
+copy @ICONV_DLL@ ..\Build\Release\
+@END IDNKIT
+
+@IF ZLIB
+echo Copying the zlib DLL.
+
+copy @ZLIB_DLL@ ..\Build\Release\
+@END ZLIB
+
+echo Copying Visual C x86 Redistributable Installer.
+
+copy /Y @VCREDIST_PATH@ ..\Build\Release\
+
+echo Copying install files (flags and file list).
+
+copy InstallFlags ..\Build\Release\
+copy InstallFiles ..\Build\Release\
+
+</Command>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <None Include="libisc.def" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\config.h" />
+@IF AES
+ <ClInclude Include="..\include\isc\aes.h" />
+@END AES
+ <ClInclude Include="..\include\isc\app.h" />
+ <ClInclude Include="..\include\isc\assertions.h" />
+ <ClInclude Include="..\include\isc\backtrace.h" />
+ <ClInclude Include="..\include\isc\base32.h" />
+ <ClInclude Include="..\include\isc\base64.h" />
+ <ClInclude Include="..\include\isc\bind9.h" />
+ <ClInclude Include="..\include\isc\boolean.h" />
+ <ClInclude Include="..\include\isc\buffer.h" />
+ <ClInclude Include="..\include\isc\bufferlist.h" />
+ <ClInclude Include="..\include\isc\commandline.h" />
+ <ClInclude Include="..\include\isc\counter.h" />
+ <ClInclude Include="..\include\isc\crc64.h" />
+ <ClInclude Include="..\include\isc\entropy.h" />
+ <ClInclude Include="..\include\isc\errno.h" />
+ <ClInclude Include="..\include\isc\error.h" />
+ <ClInclude Include="..\include\isc\event.h" />
+ <ClInclude Include="..\include\isc\eventclass.h" />
+ <ClInclude Include="..\include\isc\file.h" />
+ <ClInclude Include="..\include\isc\formatcheck.h" />
+ <ClInclude Include="..\include\isc\fsaccess.h" />
+ <ClInclude Include="..\include\isc\hash.h" />
+ <ClInclude Include="..\include\isc\heap.h" />
+ <ClInclude Include="..\include\isc\hex.h" />
+ <ClInclude Include="..\include\isc\hmacmd5.h" />
+ <ClInclude Include="..\include\isc\hmacsha.h" />
+ <ClInclude Include="..\include\isc\ht.h" />
+ <ClInclude Include="..\include\isc\httpd.h" />
+ <ClInclude Include="..\include\isc\int.h" />
+ <ClInclude Include="..\include\isc\interfaceiter.h" />
+ <ClInclude Include="..\include\isc\iterated_hash.h" />
+ <ClInclude Include="..\include\isc\json.h" />
+ <ClInclude Include="..\include\isc\lang.h" />
+ <ClInclude Include="..\include\isc\lex.h" />
+ <ClInclude Include="..\include\isc\lfsr.h" />
+ <ClInclude Include="..\include\isc\lib.h" />
+ <ClInclude Include="..\include\isc\list.h" />
+ <ClInclude Include="..\include\isc\log.h" />
+ <ClInclude Include="..\include\isc\magic.h" />
+ <ClInclude Include="..\include\isc\md5.h" />
+ <ClInclude Include="..\include\isc\mem.h" />
+ <ClInclude Include="..\include\isc\meminfo.h" />
+ <ClInclude Include="..\include\isc\msgcat.h" />
+ <ClInclude Include="..\include\isc\msgs.h" />
+ <ClInclude Include="..\include\isc\mutexblock.h" />
+ <ClInclude Include="..\include\isc\netaddr.h" />
+ <ClInclude Include="..\include\isc\netscope.h" />
+ <ClInclude Include="..\include\isc\ondestroy.h" />
+ <ClInclude Include="..\include\isc\os.h" />
+ <ClInclude Include="..\include\isc\parseint.h" />
+ <ClInclude Include="..\include\isc\pool.h" />
+ <ClInclude Include="..\include\isc\portset.h" />
+ <ClInclude Include="..\include\isc\print.h" />
+ <ClInclude Include="..\include\isc\queue.h" />
+ <ClInclude Include="..\include\isc\quota.h" />
+ <ClInclude Include="..\include\isc\radix.h" />
+ <ClInclude Include="..\include\isc\random.h" />
+ <ClInclude Include="..\include\isc\ratelimiter.h" />
+ <ClInclude Include="..\include\isc\refcount.h" />
+ <ClInclude Include="..\include\isc\regex.h" />
+ <ClInclude Include="..\include\isc\region.h" />
+ <ClInclude Include="..\include\isc\resource.h" />
+ <ClInclude Include="..\include\isc\result.h" />
+ <ClInclude Include="..\include\isc\resultclass.h" />
+ <ClInclude Include="..\include\isc\rwlock.h" />
+ <ClInclude Include="..\include\isc\safe.h" />
+ <ClInclude Include="..\include\isc\serial.h" />
+ <ClInclude Include="..\include\isc\sha1.h" />
+ <ClInclude Include="..\include\isc\sha2.h" />
+ <ClInclude Include="..\include\isc\sockaddr.h" />
+ <ClInclude Include="..\include\isc\socket.h" />
+ <ClInclude Include="..\include\isc\stats.h" />
+ <ClInclude Include="..\include\isc\stdio.h" />
+ <ClInclude Include="..\include\isc\stdlib.h" />
+ <ClInclude Include="..\include\isc\string.h" />
+ <ClInclude Include="..\include\isc\symtab.h" />
+ <ClInclude Include="..\include\isc\task.h" />
+ <ClInclude Include="..\include\isc\taskpool.h" />
+ <ClInclude Include="..\include\isc\timer.h" />
+ <ClInclude Include="..\include\isc\tm.h" />
+ <ClInclude Include="..\include\isc\types.h" />
+ <ClInclude Include="..\include\isc\util.h" />
+ <ClInclude Include="..\include\isc\version.h" />
+ <ClInclude Include="..\include\isc\xml.h" />
+@IF PKCS11
+ <ClInclude Include="..\include\pk11\constants.h" />
+ <ClInclude Include="..\include\pk11\internal.h" />
+ <ClInclude Include="..\include\pk11\pk11.h" />
+ <ClInclude Include="..\include\pk11\result.h" />
+ <ClInclude Include="..\include\pkcs11\pkcs11.h" />
+ <ClInclude Include="..\include\pkcs11\pkcs11f.h" />
+ <ClInclude Include="..\include\pkcs11\pkcs11t.h" />
+@END PKCS11
+@IF ATOMIC
+ <ClInclude Include="include\isc\atomic.h" />
+@ELSE ATOMIC
+ <ClInclude Include="..\noatomic\include\isc\atomic.h" />
+@END ATOMIC
+ <ClInclude Include="errno2result.h" />
+ <ClInclude Include="include\isc\bindevt.h" />
+ <ClInclude Include="include\isc\bind_registry.h" />
+ <ClInclude Include="include\isc\condition.h" />
+ <ClInclude Include="include\isc\dir.h" />
+ <ClInclude Include="include\isc\ipv6.h" />
+ <ClInclude Include="include\isc\keyboard.h" />
+ <ClInclude Include="include\isc\mutex.h" />
+ <ClInclude Include="include\isc\net.h" />
+ <ClInclude Include="include\isc\netdb.h" />
+ <ClInclude Include="include\isc\ntgroups.h" />
+ <ClInclude Include="include\isc\ntpaths.h" />
+ <ClInclude Include="include\isc\offset.h" />
+ <ClInclude Include="include\isc\once.h" />
+ <ClInclude Include="include\isc\platform.h" />
+ <ClInclude Include="include\isc\stat.h" />
+ <ClInclude Include="include\isc\stdtime.h" />
+ <ClInclude Include="include\isc\strerror.h" />
+ <ClInclude Include="include\isc\syslog.h" />
+ <ClInclude Include="include\isc\thread.h" />
+ <ClInclude Include="include\isc\time.h" />
+ <ClInclude Include="include\isc\win32os.h" />
+ <ClInclude Include="syslog.h" />
+ <ClInclude Include="unistd.h" />
+@IF PKCS11
+ <ClInclude Include="include\pkcs11\cryptoki.h" />
+@END PKCS11
+ <ClInclude Include="..\..\versions.h" />
+ </ItemGroup>
+ <ItemGroup>
+@IF AES
+ <ClCompile Include="..\aes.c" />
+@END AES
+ <ClCompile Include="..\assertions.c" />
+ <ClCompile Include="..\backtrace-emptytbl.c" />
+ <ClCompile Include="..\backtrace.c" />
+ <ClCompile Include="..\base32.c" />
+ <ClCompile Include="..\base64.c" />
+ <ClCompile Include="..\bind9.c" />
+ <ClCompile Include="..\buffer.c" />
+ <ClCompile Include="..\bufferlist.c" />
+ <ClCompile Include="..\commandline.c" />
+ <ClCompile Include="..\counter.c" />
+ <ClCompile Include="..\crc64.c" />
+ <ClCompile Include="..\error.c" />
+ <ClCompile Include="..\event.c" />
+ <ClCompile Include="..\hash.c" />
+ <ClCompile Include="..\heap.c" />
+ <ClCompile Include="..\hex.c" />
+ <ClCompile Include="..\hmacmd5.c" />
+ <ClCompile Include="..\hmacsha.c" />
+ <ClCompile Include="..\ht.c" />
+ <ClCompile Include="..\httpd.c" />
+ <ClCompile Include="..\inet_aton.c" />
+ <ClCompile Include="..\inet_ntop.c" />
+ <ClCompile Include="..\inet_pton.c" />
+ <ClCompile Include="..\iterated_hash.c" />
+ <ClCompile Include="..\lex.c" />
+ <ClCompile Include="..\lfsr.c" />
+ <ClCompile Include="..\lib.c" />
+ <ClCompile Include="..\log.c" />
+ <ClCompile Include="..\md5.c" />
+ <ClCompile Include="..\mem.c" />
+ <ClCompile Include="..\mutexblock.c" />
+ <ClCompile Include="..\netaddr.c" />
+ <ClCompile Include="..\netscope.c" />
+ <ClCompile Include="..\nls\msgcat.c" />
+ <ClCompile Include="..\ondestroy.c" />
+ <ClCompile Include="..\parseint.c" />
+ <ClCompile Include="..\pool.c" />
+ <ClCompile Include="..\portset.c" />
+ <ClCompile Include="..\quota.c" />
+ <ClCompile Include="..\radix.c" />
+ <ClCompile Include="..\random.c" />
+ <ClCompile Include="..\ratelimiter.c" />
+ <ClCompile Include="..\refcount.c" />
+ <ClCompile Include="..\regex.c" />
+ <ClCompile Include="..\region.c" />
+ <ClCompile Include="..\result.c" />
+ <ClCompile Include="..\rwlock.c" />
+ <ClCompile Include="..\safe.c" />
+ <ClCompile Include="..\serial.c" />
+ <ClCompile Include="..\sha1.c" />
+ <ClCompile Include="..\sha2.c" />
+ <ClCompile Include="..\sockaddr.c" />
+ <ClCompile Include="..\stats.c" />
+ <ClCompile Include="..\string.c" />
+ <ClCompile Include="..\symtab.c" />
+ <ClCompile Include="..\task.c" />
+ <ClCompile Include="..\taskpool.c" />
+ <ClCompile Include="..\timer.c" />
+ <ClCompile Include="..\tm.c" />
+@IF PKCS11
+ <ClCompile Include="..\pk11.c" />
+ <ClCompile Include="..\pk11_result.c" />
+@END PKCS11
+ <ClCompile Include="app.c" />
+ <ClCompile Include="condition.c" />
+ <ClCompile Include="dir.c" />
+ <ClCompile Include="DLLMain.c" />
+ <ClCompile Include="entropy.c" />
+ <ClCompile Include="errno.c" />
+ <ClCompile Include="errno2result.c" />
+ <ClCompile Include="file.c" />
+ <ClCompile Include="fsaccess.c" />
+ <ClCompile Include="interfaceiter.c" />
+ <ClCompile Include="ipv6.c" />
+ <ClCompile Include="keyboard.c" />
+ <ClCompile Include="meminfo.c" />
+ <ClCompile Include="net.c" />
+ <ClCompile Include="ntpaths.c" />
+ <ClCompile Include="once.c" />
+ <ClCompile Include="os.c" />
+ <ClCompile Include="resource.c" />
+ <ClCompile Include="socket.c" />
+ <ClCompile Include="stdio.c" />
+ <ClCompile Include="stdtime.c" />
+ <ClCompile Include="strerror.c" />
+ <ClCompile Include="syslog.c" />
+ <ClCompile Include="thread.c" />
+ <ClCompile Include="time.c" />
+ <ClCompile Include="version.c" />
+ <ClCompile Include="win32os.c" />
+@IF PKCS11
+ <ClCompile Include="pk11_api.c" />
+@END PKCS11
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/lib/isc/win32/libisc.vcxproj.user b/lib/isc/win32/libisc.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/lib/isc/win32/libisc.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/lib/isc/win32/meminfo.c b/lib/isc/win32/meminfo.c
new file mode 100644
index 0000000..51077f6
--- /dev/null
+++ b/lib/isc/win32/meminfo.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <windows.h>
+
+#include <isc/meminfo.h>
+
+uint64_t
+isc_meminfo_totalphys(void) {
+ MEMORYSTATUSEX statex;
+
+ statex.dwLength = sizeof(statex);
+ GlobalMemoryStatusEx(&statex);
+ return ((uint64_t)statex.ullTotalPhys);
+}
diff --git a/lib/isc/win32/net.c b/lib/isc/win32/net.c
new file mode 100644
index 0000000..c49bb6b
--- /dev/null
+++ b/lib/isc/win32/net.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <isc/log.h>
+#include <isc/msgs.h>
+#include <isc/net.h>
+#include <isc/once.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+/*%
+ * Definitions about UDP port range specification. This is a total mess of
+ * portability variants: some use sysctl (but the sysctl names vary), some use
+ * system-specific interfaces, some have the same interface for IPv4 and IPv6,
+ * some separate them, etc...
+ */
+
+/*%
+ * The last resort defaults: use all non well known port space
+ */
+#ifndef ISC_NET_PORTRANGELOW
+#define ISC_NET_PORTRANGELOW 1024
+#endif /* ISC_NET_PORTRANGELOW */
+#ifndef ISC_NET_PORTRANGEHIGH
+#define ISC_NET_PORTRANGEHIGH 65535
+#endif /* ISC_NET_PORTRANGEHIGH */
+
+#if defined(ISC_PLATFORM_HAVEIPV6) && defined(ISC_PLATFORM_NEEDIN6ADDRANY)
+const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT;
+#endif
+
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_once_t once_ipv6only = ISC_ONCE_INIT;
+static isc_once_t once_ipv6pktinfo = ISC_ONCE_INIT;
+static isc_result_t ipv4_result = ISC_R_NOTFOUND;
+static isc_result_t ipv6_result = ISC_R_NOTFOUND;
+static isc_result_t ipv6only_result = ISC_R_NOTFOUND;
+static isc_result_t ipv6pktinfo_result = ISC_R_NOTFOUND;
+
+void InitSockets(void);
+
+static isc_result_t
+try_proto(int domain) {
+ SOCKET s;
+ char strbuf[ISC_STRERRORSIZE];
+ int errval;
+
+ s = socket(domain, SOCK_STREAM, IPPROTO_TCP);
+ if (s == INVALID_SOCKET) {
+ errval = WSAGetLastError();
+ switch (errval) {
+ case WSAEAFNOSUPPORT:
+ case WSAEPROTONOSUPPORT:
+ case WSAEINVAL:
+ return (ISC_R_NOTFOUND);
+ default:
+ isc__strerror(errval, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+ }
+
+ closesocket(s);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+initialize_action(void) {
+ InitSockets();
+ ipv4_result = try_proto(PF_INET);
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+ ipv6_result = try_proto(PF_INET6);
+#endif
+#endif
+#endif
+}
+
+static void
+initialize(void) {
+ RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_net_probeipv4(void) {
+ initialize();
+ return (ipv4_result);
+}
+
+isc_result_t
+isc_net_probeipv6(void) {
+ initialize();
+ return (ipv6_result);
+}
+
+isc_result_t
+isc_net_probeunix(void) {
+ return (ISC_R_NOTFOUND);
+}
+
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+static void
+try_ipv6only(void) {
+#ifdef IPV6_V6ONLY
+ SOCKET s;
+ int on;
+ char strbuf[ISC_STRERRORSIZE];
+#endif
+ isc_result_t result;
+
+ result = isc_net_probeipv6();
+ if (result != ISC_R_SUCCESS) {
+ ipv6only_result = result;
+ return;
+ }
+
+#ifndef IPV6_V6ONLY
+ ipv6only_result = ISC_R_NOTFOUND;
+ return;
+#else
+ /* check for TCP sockets */
+ s = socket(PF_INET6, SOCK_STREAM, 0);
+ if (s == INVALID_SOCKET) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ ipv6only_result = ISC_R_UNEXPECTED;
+ return;
+ }
+
+ on = 1;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&on,
+ sizeof(on)) < 0) {
+ ipv6only_result = ISC_R_NOTFOUND;
+ goto close;
+ }
+
+ closesocket(s);
+
+ /* check for UDP sockets */
+ s = socket(PF_INET6, SOCK_DGRAM, 0);
+ if (s == INVALID_SOCKET) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ ipv6only_result = ISC_R_UNEXPECTED;
+ return;
+ }
+
+ on = 1;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&on,
+ sizeof(on)) < 0) {
+ ipv6only_result = ISC_R_NOTFOUND;
+ goto close;
+ }
+
+ ipv6only_result = ISC_R_SUCCESS;
+
+close:
+ closesocket(s);
+ return;
+#endif /* IPV6_V6ONLY */
+}
+
+static void
+initialize_ipv6only(void) {
+ RUNTIME_CHECK(isc_once_do(&once_ipv6only,
+ try_ipv6only) == ISC_R_SUCCESS);
+}
+
+#ifdef __notyet__
+/*
+ * XXXMPA requires win32/socket.c to be updated to support
+ * WSASendMsg and WSARecvMsg which are themselves Winsock
+ * and compiler version dependent.
+ */
+static void
+try_ipv6pktinfo(void) {
+ SOCKET s;
+ int on;
+ char strbuf[ISC_STRERRORSIZE];
+ isc_result_t result;
+ int optname;
+
+ result = isc_net_probeipv6();
+ if (result != ISC_R_SUCCESS) {
+ ipv6pktinfo_result = result;
+ return;
+ }
+
+ /* we only use this for UDP sockets */
+ s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (s == INVALID_SOCKET) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ ipv6pktinfo_result = ISC_R_UNEXPECTED;
+ return;
+ }
+
+#ifdef IPV6_RECVPKTINFO
+ optname = IPV6_RECVPKTINFO;
+#else
+ optname = IPV6_PKTINFO;
+#endif
+ on = 1;
+ if (setsockopt(s, IPPROTO_IPV6, optname, (const char *) &on,
+ sizeof(on)) < 0) {
+ ipv6pktinfo_result = ISC_R_NOTFOUND;
+ goto close;
+ }
+
+ ipv6pktinfo_result = ISC_R_SUCCESS;
+
+close:
+ closesocket(s);
+ return;
+}
+
+static void
+initialize_ipv6pktinfo(void) {
+ RUNTIME_CHECK(isc_once_do(&once_ipv6pktinfo,
+ try_ipv6pktinfo) == ISC_R_SUCCESS);
+}
+#endif /* __notyet__ */
+#endif /* WANT_IPV6 */
+#endif /* ISC_PLATFORM_HAVEIPV6 */
+
+isc_result_t
+isc_net_probe_ipv6only(void) {
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+ initialize_ipv6only();
+#else
+ ipv6only_result = ISC_R_NOTFOUND;
+#endif
+#endif
+ return (ipv6only_result);
+}
+
+isc_result_t
+isc_net_probe_ipv6pktinfo(void) {
+#ifdef __notyet__
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+ initialize_ipv6pktinfo();
+#else
+ ipv6pktinfo_result = ISC_R_NOTFOUND;
+#endif
+#endif
+#endif /* __notyet__ */
+ return (ipv6pktinfo_result);
+}
+
+isc_result_t
+isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high) {
+ int result = ISC_R_FAILURE;
+
+ REQUIRE(low != NULL && high != NULL);
+
+ UNUSED(af);
+
+ if (result != ISC_R_SUCCESS) {
+ *low = ISC_NET_PORTRANGELOW;
+ *high = ISC_NET_PORTRANGEHIGH;
+ }
+
+ return (ISC_R_SUCCESS); /* we currently never fail in this function */
+}
+
+void
+isc_net_disableipv4(void) {
+ initialize();
+ if (ipv4_result == ISC_R_SUCCESS)
+ ipv4_result = ISC_R_DISABLED;
+}
+
+void
+isc_net_disableipv6(void) {
+ initialize();
+ if (ipv6_result == ISC_R_SUCCESS)
+ ipv6_result = ISC_R_DISABLED;
+}
+
+void
+isc_net_enableipv4(void) {
+ initialize();
+ if (ipv4_result == ISC_R_DISABLED)
+ ipv4_result = ISC_R_SUCCESS;
+}
+
+void
+isc_net_enableipv6(void) {
+ initialize();
+ if (ipv6_result == ISC_R_DISABLED)
+ ipv6_result = ISC_R_SUCCESS;
+}
+
+unsigned int
+isc_net_probedscp(void) {
+ return (0);
+}
diff --git a/lib/isc/win32/netdb.h b/lib/isc/win32/netdb.h
new file mode 100644
index 0000000..a9398c8
--- /dev/null
+++ b/lib/isc/win32/netdb.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef NETDB_H
+#define NETDB_H 1
+
+#include <stddef.h>
+#include <winsock2.h>
+
+/*
+ * Define if <netdb.h> does not declare struct addrinfo.
+ */
+
+#if _MSC_VER < 1600
+struct addrinfo {
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ size_t ai_addrlen; /* Length of ai_addr */
+ char *ai_canonname; /* Canonical name for hostname */
+ struct sockaddr *ai_addr; /* Binary address */
+ struct addrinfo *ai_next; /* Next structure in linked list */
+};
+#endif
+
+
+/*
+ * Undefine all \#defines we are interested in as <netdb.h> may or may not have
+ * defined them.
+ */
+
+/*
+ * Error return codes from gethostbyname() and gethostbyaddr()
+ * (left in extern int h_errno).
+ */
+
+#undef NETDB_INTERNAL
+#undef NETDB_SUCCESS
+#undef HOST_NOT_FOUND
+#undef TRY_AGAIN
+#undef NO_RECOVERY
+#undef NO_DATA
+#undef NO_ADDRESS
+
+#define NETDB_INTERNAL -1 /* see errno */
+#define NETDB_SUCCESS 0 /* no problem */
+#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */
+#define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL */
+#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
+#define NO_DATA 4 /* Valid name, no data record of requested type */
+#define NO_ADDRESS NO_DATA /* no address, look for MX record */
+
+/*
+ * Error return codes from getaddrinfo()
+ */
+
+#undef EAI_ADDRFAMILY
+#undef EAI_AGAIN
+#undef EAI_BADFLAGS
+#undef EAI_FAIL
+#undef EAI_FAMILY
+#undef EAI_MEMORY
+#undef EAI_NODATA
+#undef EAI_NONAME
+#undef EAI_SERVICE
+#undef EAI_SOCKTYPE
+#undef EAI_SYSTEM
+#undef EAI_BADHINTS
+#undef EAI_PROTOCOL
+#undef EAI_MAX
+
+#define EAI_ADDRFAMILY 1 /* address family for hostname not supported */
+#define EAI_AGAIN 2 /* temporary failure in name resolution */
+#define EAI_BADFLAGS 3 /* invalid value for ai_flags */
+#define EAI_FAIL 4 /* non-recoverable failure in name resolution */
+#define EAI_FAMILY 5 /* ai_family not supported */
+#define EAI_MEMORY 6 /* memory allocation failure */
+#define EAI_NODATA 7 /* no address associated with hostname */
+#define EAI_NONAME 8 /* hostname nor servname provided, or not known */
+#define EAI_SERVICE 9 /* servname not supported for ai_socktype */
+#define EAI_SOCKTYPE 10 /* ai_socktype not supported */
+#define EAI_SYSTEM 11 /* system error returned in errno */
+#define EAI_BADHINTS 12
+#define EAI_PROTOCOL 13
+#define EAI_MAX 14
+
+/*
+ * Flag values for getaddrinfo()
+ */
+#undef AI_PASSIVE
+#undef AI_CANONNAME
+#undef AI_NUMERICHOST
+
+#define AI_PASSIVE 0x00000001
+#define AI_CANONNAME 0x00000002
+#define AI_NUMERICHOST 0x00000004
+
+/*
+ * Flag values for getipnodebyname()
+ */
+#undef AI_V4MAPPED
+#undef AI_ALL
+#undef AI_ADDRCONFIG
+#undef AI_DEFAULT
+
+#define AI_V4MAPPED 0x00000008
+#define AI_ALL 0x00000010
+#define AI_ADDRCONFIG 0x00000020
+#define AI_DEFAULT (AI_V4MAPPED|AI_ADDRCONFIG)
+
+/*
+ * Constants for getnameinfo()
+ */
+#undef NI_MAXHOST
+#undef NI_MAXSERV
+
+#define NI_MAXHOST 1025
+#define NI_MAXSERV 32
+
+/*
+ * Flag values for getnameinfo()
+ */
+#undef NI_NOFQDN
+#undef NI_NUMERICHOST
+#undef NI_NAMEREQD
+#undef NI_NUMERICSERV
+#undef NI_DGRAM
+#undef NI_NUMERICSCOPE
+
+#define NI_NOFQDN 0x00000001
+#define NI_NUMERICHOST 0x00000002
+#define NI_NAMEREQD 0x00000004
+#define NI_NUMERICSERV 0x00000008
+#define NI_DGRAM 0x00000010
+#define NI_NUMERICSCOPE 0x00000020 /*2553bis-00*/
+
+/*
+ * Structures for getrrsetbyname()
+ */
+struct rdatainfo {
+ unsigned int rdi_length;
+ unsigned char *rdi_data;
+};
+
+struct rrsetinfo {
+ unsigned int rri_flags;
+ int rri_rdclass;
+ int rri_rdtype;
+ unsigned int rri_ttl;
+ unsigned int rri_nrdatas;
+ unsigned int rri_nsigs;
+ char *rri_name;
+ struct rdatainfo *rri_rdatas;
+ struct rdatainfo *rri_sigs;
+};
+
+/*
+ * Flags for getrrsetbyname()
+ */
+#define RRSET_VALIDATED 0x00000001
+ /* Set was dnssec validated */
+
+/*
+ * Return codes for getrrsetbyname()
+ */
+#define ERRSET_SUCCESS 0
+#define ERRSET_NOMEMORY 1
+#define ERRSET_FAIL 2
+#define ERRSET_INVAL 3
+
+
+#endif /* NETDB_H */
diff --git a/lib/isc/win32/ntgroups.c b/lib/isc/win32/ntgroups.c
new file mode 100644
index 0000000..e3a45ca
--- /dev/null
+++ b/lib/isc/win32/ntgroups.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*
+ * The NT Groups have two groups that are not well documented and are
+ * not normally seen: None and Everyone. A user account belongs to
+ * any number of groups, but if it is not a member of any group then
+ * it is a member of the None Group. The None group is not listed
+ * anywhere. You cannot remove an account from the none group except
+ * by making it a member of some other group, The second group is the
+ * Everyone group. All accounts, no matter how many groups that they
+ * belong to, also belong to the Everyone group. You cannot remove an
+ * account from the Everyone group.
+ */
+
+#ifndef UNICODE
+#define UNICODE
+#endif /* UNICODE */
+
+/*
+ * Silence warnings.
+ */
+#define _CRT_SECURE_NO_DEPRECATE 1
+
+#include <windows.h>
+#include <assert.h>
+#include <lm.h>
+
+#include <isc/ntgroups.h>
+#include <isc/result.h>
+
+#define MAX_NAME_LENGTH 256
+
+isc_result_t
+isc_ntsecurity_getaccountgroups(char *username, char **GroupList,
+ unsigned int maxgroups,
+ unsigned int *totalGroups) {
+ LPGROUP_USERS_INFO_0 pTmpBuf;
+ LPLOCALGROUP_USERS_INFO_0 pTmpLBuf;
+ DWORD i;
+ LPLOCALGROUP_USERS_INFO_0 pBuf = NULL;
+ LPGROUP_USERS_INFO_0 pgrpBuf = NULL;
+ DWORD dwLevel = 0;
+ DWORD dwFlags = LG_INCLUDE_INDIRECT;
+ DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;
+ DWORD dwEntriesRead = 0;
+ DWORD dwTotalEntries = 0;
+ NET_API_STATUS nStatus;
+ size_t retlen;
+ wchar_t user[MAX_NAME_LENGTH];
+
+ retlen = mbstowcs(user, username, MAX_NAME_LENGTH);
+
+ *totalGroups = 0;
+ /*
+ * Call the NetUserGetLocalGroups function
+ * specifying information level 0.
+ *
+ * The LG_INCLUDE_INDIRECT flag specifies that the
+ * function should also return the names of the local
+ * groups in which the user is indirectly a member.
+ */
+ nStatus = NetUserGetLocalGroups(NULL,
+ user,
+ dwLevel,
+ dwFlags,
+ (LPBYTE *) &pBuf,
+ dwPrefMaxLen,
+ &dwEntriesRead,
+ &dwTotalEntries);
+ /*
+ * See if the call succeeds,
+ */
+ if (nStatus != NERR_Success) {
+ if (nStatus == ERROR_ACCESS_DENIED)
+ return (ISC_R_NOPERM);
+ if (nStatus == ERROR_MORE_DATA)
+ return (ISC_R_NOSPACE);
+ if (nStatus == NERR_UserNotFound)
+ dwEntriesRead = 0;
+ }
+
+ if (pBuf != NULL) {
+ pTmpLBuf = pBuf;
+ /*
+ * Loop through the entries
+ */
+ for (i = 0;
+ (i < dwEntriesRead && *totalGroups < maxgroups); i++) {
+ assert(pTmpLBuf != NULL);
+ if (pTmpLBuf == NULL)
+ break;
+ retlen = wcslen(pTmpLBuf->lgrui0_name);
+ GroupList[*totalGroups] = (char *) malloc(retlen +1);
+ if (GroupList[*totalGroups] == NULL)
+ return (ISC_R_NOMEMORY);
+
+ retlen = wcstombs(GroupList[*totalGroups],
+ pTmpLBuf->lgrui0_name, retlen);
+ GroupList[*totalGroups][retlen] = '\0';
+ if (strcmp(GroupList[*totalGroups], "None") == 0)
+ free(GroupList[*totalGroups]);
+ else
+ (*totalGroups)++;
+ pTmpLBuf++;
+ }
+ }
+ /* Free the allocated memory. */
+ if (pBuf != NULL)
+ NetApiBufferFree(pBuf);
+
+
+ /*
+ * Call the NetUserGetGroups function, specifying level 0.
+ */
+ nStatus = NetUserGetGroups(NULL,
+ user,
+ dwLevel,
+ (LPBYTE*)&pgrpBuf,
+ dwPrefMaxLen,
+ &dwEntriesRead,
+ &dwTotalEntries);
+ /*
+ * See if the call succeeds,
+ */
+ if (nStatus != NERR_Success) {
+ if (nStatus == ERROR_ACCESS_DENIED)
+ return (ISC_R_NOPERM);
+ if (nStatus == ERROR_MORE_DATA)
+ return (ISC_R_NOSPACE);
+ if (nStatus == NERR_UserNotFound)
+ dwEntriesRead = 0;
+ }
+
+ if (pgrpBuf != NULL) {
+ pTmpBuf = pgrpBuf;
+ /*
+ * Loop through the entries
+ */
+ for (i = 0;
+ (i < dwEntriesRead && *totalGroups < maxgroups); i++) {
+ assert(pTmpBuf != NULL);
+
+ if (pTmpBuf == NULL)
+ break;
+ retlen = wcslen(pTmpBuf->grui0_name);
+ GroupList[*totalGroups] = (char *) malloc(retlen +1);
+ if (GroupList[*totalGroups] == NULL)
+ return (ISC_R_NOMEMORY);
+
+ retlen = wcstombs(GroupList[*totalGroups],
+ pTmpBuf->grui0_name, retlen);
+ GroupList[*totalGroups][retlen] = '\0';
+ if (strcmp(GroupList[*totalGroups], "None") == 0)
+ free(GroupList[*totalGroups]);
+ else
+ (*totalGroups)++;
+ pTmpBuf++;
+ }
+ }
+ /*
+ * Free the allocated memory.
+ */
+ if (pgrpBuf != NULL)
+ NetApiBufferFree(pgrpBuf);
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isc/win32/ntpaths.c b/lib/isc/win32/ntpaths.c
new file mode 100644
index 0000000..df71bfa
--- /dev/null
+++ b/lib/isc/win32/ntpaths.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*
+ * This module fetches the required path information that is specific
+ * to NT systems which can have its configuration and system files
+ * almost anywhere. It can be used to override whatever the application
+ * had previously assigned to the pointer. Basic information about the
+ * file locations are stored in the registry.
+ */
+
+#include <config.h>
+
+#include <isc/bind_registry.h>
+#include <isc/ntpaths.h>
+#include <isc/string.h>
+
+/*
+ * Module Variables
+ */
+
+static char systemDir[MAX_PATH];
+static char namedBase[MAX_PATH];
+static char ns_confFile[MAX_PATH];
+static char lwresd_confFile[MAX_PATH];
+static char lwresd_resolvconfFile[MAX_PATH];
+static char rndc_confFile[MAX_PATH];
+static char ns_defaultpidfile[MAX_PATH];
+static char lwresd_defaultpidfile[MAX_PATH];
+static char ns_lockfile[MAX_PATH];
+static char local_state_dir[MAX_PATH];
+static char sys_conf_dir[MAX_PATH];
+static char rndc_keyFile[MAX_PATH];
+static char session_keyFile[MAX_PATH];
+
+static DWORD baseLen = MAX_PATH;
+static BOOL Initialized = FALSE;
+
+void
+isc_ntpaths_init(void) {
+ HKEY hKey;
+ BOOL keyFound = TRUE;
+
+ memset(namedBase, 0, sizeof(namedBase));
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, BIND_SUBKEY, 0, KEY_READ, &hKey)
+ != ERROR_SUCCESS)
+ keyFound = FALSE;
+
+ if (keyFound == TRUE) {
+ /* Get the named directory */
+ if (RegQueryValueEx(hKey, "InstallDir", NULL, NULL,
+ (LPBYTE)namedBase, &baseLen) != ERROR_SUCCESS)
+ keyFound = FALSE;
+ RegCloseKey(hKey);
+ }
+
+ GetSystemDirectory(systemDir, MAX_PATH);
+
+ if (keyFound == FALSE) {
+ /* Use the System Directory as a default */
+ strlcpy(namedBase, systemDir, sizeof(namedBase));
+ }
+
+ strlcpy(lwresd_confFile, namedBase, sizeof(lwresd_confFile)) ;
+ strlcat(lwresd_confFile, "\\etc\\lwresd.conf",
+ sizeof(lwresd_confFile));
+
+ strlcpy(lwresd_defaultpidfile, namedBase,
+ sizeof(lwresd_defaultpidfile));
+ strlcat(lwresd_defaultpidfile, "\\etc\\lwresd.pid",
+ sizeof(lwresd_defaultpidfile));
+
+ strlcpy(lwresd_resolvconfFile, systemDir,
+ sizeof(lwresd_resolvconfFile));
+ strlcat(lwresd_resolvconfFile, "\\Drivers\\etc\\resolv.conf",
+ sizeof(lwresd_resolvconfFile));
+
+ strlcpy(ns_confFile, namedBase, sizeof(ns_confFile));
+ strlcat(ns_confFile, "\\etc\\named.conf", sizeof(ns_confFile));
+
+ strlcpy(rndc_keyFile, namedBase, sizeof(rndc_keyFile));
+ strlcat(rndc_keyFile, "\\etc\\rndc.key", sizeof(rndc_keyFile));
+
+ strlcpy(session_keyFile, namedBase, sizeof(session_keyFile));
+ strlcat(session_keyFile, "\\etc\\session.key", sizeof(session_keyFile));
+
+ strlcpy(rndc_confFile, namedBase, sizeof(rndc_confFile));
+ strlcat(rndc_confFile, "\\etc\\rndc.conf", sizeof(rndc_confFile));
+
+ strlcpy(ns_defaultpidfile, namedBase, sizeof(ns_defaultpidfile));
+ strlcat(ns_defaultpidfile, "\\etc\\named.pid",
+ sizeof(ns_defaultpidfile));
+
+ strlcpy(ns_lockfile, namedBase, sizeof(ns_lockfile));
+ strlcat(ns_lockfile, "\\etc\\named.lock", sizeof(ns_lockfile));
+
+ strlcpy(local_state_dir, namedBase, sizeof(local_state_dir));
+ strlcat(local_state_dir, "\\bin", sizeof(local_state_dir));
+
+ strlcpy(sys_conf_dir, namedBase, sizeof(sys_conf_dir));
+ strlcat(sys_conf_dir, "\\etc", sizeof(sys_conf_dir));
+
+ Initialized = TRUE;
+}
+
+char *
+isc_ntpaths_get(int ind) {
+ if (!Initialized)
+ isc_ntpaths_init();
+
+ switch (ind) {
+ case NAMED_CONF_PATH:
+ return (ns_confFile);
+ break;
+ case LWRES_CONF_PATH:
+ return (lwresd_confFile);
+ break;
+ case RESOLV_CONF_PATH:
+ return (lwresd_resolvconfFile);
+ break;
+ case RNDC_CONF_PATH:
+ return (rndc_confFile);
+ break;
+ case NAMED_PID_PATH:
+ return (ns_defaultpidfile);
+ break;
+ case LWRESD_PID_PATH:
+ return (lwresd_defaultpidfile);
+ break;
+ case NAMED_LOCK_PATH:
+ return (ns_lockfile);
+ break;
+ case LOCAL_STATE_DIR:
+ return (local_state_dir);
+ break;
+ case SYS_CONF_DIR:
+ return (sys_conf_dir);
+ break;
+ case RNDC_KEY_PATH:
+ return (rndc_keyFile);
+ break;
+ case SESSION_KEY_PATH:
+ return (session_keyFile);
+ break;
+ default:
+ return (NULL);
+ }
+}
diff --git a/lib/isc/win32/once.c b/lib/isc/win32/once.c
new file mode 100644
index 0000000..baf178d
--- /dev/null
+++ b/lib/isc/win32/once.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <windows.h>
+
+#include <isc/once.h>
+#include <isc/assertions.h>
+#include <isc/util.h>
+
+isc_result_t
+isc_once_do(isc_once_t *controller, void(*function)(void)) {
+ REQUIRE(controller != NULL && function != NULL);
+
+ if (controller->status == ISC_ONCE_INIT_NEEDED) {
+
+ if (InterlockedDecrement(&controller->counter) == 0) {
+ if (controller->status == ISC_ONCE_INIT_NEEDED) {
+ function();
+ controller->status = ISC_ONCE_INIT_DONE;
+ }
+ } else {
+ while (controller->status == ISC_ONCE_INIT_NEEDED) {
+ /*
+ * Sleep(0) indicates that this thread
+ * should be suspended to allow other
+ * waiting threads to execute.
+ */
+ Sleep(0);
+ }
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isc/win32/os.c b/lib/isc/win32/os.c
new file mode 100644
index 0000000..0f4023f
--- /dev/null
+++ b/lib/isc/win32/os.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <windows.h>
+
+#include <isc/os.h>
+
+static BOOL bInit = FALSE;
+static SYSTEM_INFO SystemInfo;
+
+static void
+initialize_action(void) {
+ if (bInit)
+ return;
+
+ GetSystemInfo(&SystemInfo);
+ bInit = TRUE;
+}
+
+unsigned int
+isc_os_ncpus(void) {
+ long ncpus;
+ initialize_action();
+ ncpus = SystemInfo.dwNumberOfProcessors;
+ if (ncpus <= 0)
+ ncpus = 1;
+
+ return ((unsigned int)ncpus);
+}
diff --git a/lib/isc/win32/pk11_api.c b/lib/isc/win32/pk11_api.c
new file mode 100644
index 0000000..76e4abb
--- /dev/null
+++ b/lib/isc/win32/pk11_api.c
@@ -0,0 +1,675 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/*! \file */
+
+/* missing code for WIN32 */
+
+#include <config.h>
+
+#include <string.h>
+#include <windows.h>
+
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/print.h>
+#include <isc/stdio.h>
+#include <isc/thread.h>
+#include <isc/util.h>
+
+#include <pk11/pk11.h>
+#include <pk11/internal.h>
+
+#define HAVE_GETPASSPHRASE
+
+char *
+getpassphrase(const char *prompt) {
+ static char buf[128];
+ HANDLE h;
+ DWORD cc, mode;
+ int cnt;
+
+ h = GetStdHandle(STD_INPUT_HANDLE);
+ fputs(prompt, stderr);
+ fflush(stderr);
+ fflush(stdout);
+ FlushConsoleInputBuffer(h);
+ GetConsoleMode(h, &mode);
+ SetConsoleMode(h, ENABLE_PROCESSED_INPUT);
+
+ for (cnt = 0; cnt < sizeof(buf) - 1; cnt++)
+ {
+ ReadFile(h, buf + cnt, 1, &cc, NULL);
+ if (buf[cnt] == '\r')
+ break;
+ fputc('*', stdout);
+ fflush(stderr);
+ fflush(stdout);
+ }
+
+ SetConsoleMode(h, mode);
+ buf[cnt] = '\0';
+ fputs("\n", stderr);
+ return (buf);
+}
+
+/* load PKCS11 DLL */
+
+static HINSTANCE hPK11 = NULL;
+static char loaderrmsg[1024];
+
+CK_RV
+pkcs_C_Initialize(CK_VOID_PTR pReserved) {
+ CK_C_Initialize sym;
+ const char *lib_name = pk11_get_lib_name();
+
+ if (hPK11 != NULL)
+ return (CKR_LIBRARY_ALREADY_INITIALIZED);
+
+ if (lib_name == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ /* Visual Studio convertion issue... */
+ if (*lib_name == ' ')
+ lib_name++;
+
+ hPK11 = LoadLibraryA(lib_name);
+
+ if (hPK11 == NULL) {
+ const DWORD err = GetLastError();
+ snprintf(loaderrmsg, sizeof(loaderrmsg),
+ "LoadLibraryA(\"%s\") failed with 0x%X\n",
+ lib_name, err);
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ }
+ sym = (CK_C_Initialize)GetProcAddress(hPK11, "C_Initialize");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(pReserved);
+}
+
+char *pk11_get_load_error_message(void) {
+ return (loaderrmsg);
+}
+
+CK_RV
+pkcs_C_Finalize(CK_VOID_PTR pReserved) {
+ CK_C_Finalize sym;
+ CK_RV rv;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ sym = (CK_C_Finalize)GetProcAddress(hPK11, "C_Finalize");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ rv = (*sym)(pReserved);
+ if ((rv == CKR_OK) && (FreeLibrary(hPK11) == 0))
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ hPK11 = NULL;
+ return (rv);
+}
+
+CK_RV
+pkcs_C_GetSlotList(CK_BBOOL tokenPresent,
+ CK_SLOT_ID_PTR pSlotList,
+ CK_ULONG_PTR pulCount)
+{
+ static CK_C_GetSlotList sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_GetSlotList)GetProcAddress(hPK11, "C_GetSlotList");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(tokenPresent, pSlotList, pulCount);
+}
+
+CK_RV
+pkcs_C_GetTokenInfo(CK_SLOT_ID slotID,
+ CK_TOKEN_INFO_PTR pInfo)
+{
+ static CK_C_GetTokenInfo sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_GetTokenInfo)GetProcAddress(hPK11,
+ "C_GetTokenInfo");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(slotID, pInfo);
+}
+
+CK_RV
+pkcs_C_GetMechanismInfo(CK_SLOT_ID slotID,
+ CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR pInfo)
+{
+ static CK_C_GetMechanismInfo sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_GetMechanismInfo)GetProcAddress(hPK11,
+ "C_GetMechanismInfo");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(slotID, type, 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)
+{
+ static CK_C_OpenSession sym = NULL;
+
+ if (hPK11 == NULL)
+ hPK11 = LoadLibraryA(pk11_get_lib_name());
+ if (hPK11 == NULL) {
+ const DWORD err = GetLastError();
+ snprintf(loaderrmsg, sizeof(loaderrmsg),
+ "LoadLibraryA(\"%s\") failed with 0x%X\n",
+ pk11_get_lib_name(), err);
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ }
+ if (sym == NULL)
+ sym = (CK_C_OpenSession)GetProcAddress(hPK11, "C_OpenSession");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(slotID, flags, pApplication, Notify, phSession);
+}
+
+CK_RV
+pkcs_C_CloseSession(CK_SESSION_HANDLE hSession) {
+ static CK_C_CloseSession sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_CloseSession)GetProcAddress(hPK11,
+ "C_CloseSession");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession);
+}
+
+CK_RV
+pkcs_C_Login(CK_SESSION_HANDLE hSession,
+ CK_USER_TYPE userType,
+ CK_CHAR_PTR pPin,
+ CK_ULONG usPinLen)
+{
+ static CK_C_Login sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_Login)GetProcAddress(hPK11, "C_Login");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, userType, pPin, usPinLen);
+}
+
+CK_RV
+pkcs_C_Logout(CK_SESSION_HANDLE hSession) {
+ static CK_C_Logout sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_Logout)GetProcAddress(hPK11, "C_Logout");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession);
+}
+
+CK_RV
+pkcs_C_CreateObject(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG usCount,
+ CK_OBJECT_HANDLE_PTR phObject)
+{
+ static CK_C_CreateObject sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_CreateObject)GetProcAddress(hPK11,
+ "C_CreateObject");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pTemplate, usCount, phObject);
+}
+
+CK_RV
+pkcs_C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) {
+ static CK_C_DestroyObject sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_DestroyObject)GetProcAddress(hPK11,
+ "C_DestroyObject");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, hObject);
+}
+
+CK_RV
+pkcs_C_GetAttributeValue(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG usCount)
+{
+ static CK_C_GetAttributeValue sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_GetAttributeValue)GetProcAddress(hPK11,
+ "C_GetAttributeValue");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, hObject, pTemplate, usCount);
+}
+
+CK_RV
+pkcs_C_SetAttributeValue(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG usCount)
+{
+ static CK_C_SetAttributeValue sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_SetAttributeValue)GetProcAddress(hPK11,
+ "C_SetAttributeValue");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, hObject, pTemplate, usCount);
+}
+
+CK_RV
+pkcs_C_FindObjectsInit(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate,
+ CK_ULONG usCount)
+{
+ static CK_C_FindObjectsInit sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_FindObjectsInit)GetProcAddress(hPK11,
+ "C_FindObjectsInit");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pTemplate, usCount);
+}
+
+CK_RV
+pkcs_C_FindObjects(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE_PTR phObject,
+ CK_ULONG usMaxObjectCount,
+ CK_ULONG_PTR pusObjectCount)
+{
+ static CK_C_FindObjects sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_FindObjects)GetProcAddress(hPK11, "C_FindObjects");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, phObject, usMaxObjectCount, pusObjectCount);
+}
+
+CK_RV
+pkcs_C_FindObjectsFinal(CK_SESSION_HANDLE hSession) {
+ static CK_C_FindObjectsFinal sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_FindObjectsFinal)GetProcAddress(hPK11,
+ "C_FindObjectsFinal");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession);
+}
+
+CK_RV
+pkcs_C_EncryptInit(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ static CK_C_EncryptInit sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_EncryptInit)GetProcAddress(hPK11, "C_EncryptInit");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pMechanism, 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)
+{
+ static CK_C_Encrypt sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_Encrypt)GetProcAddress(hPK11, "C_Encrypt");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pData, ulDataLen,
+ pEncryptedData, pulEncryptedDataLen);
+}
+
+CK_RV
+pkcs_C_DigestInit(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism)
+{
+ static CK_C_DigestInit sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_DigestInit)GetProcAddress(hPK11, "C_DigestInit");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pMechanism);
+}
+
+CK_RV
+pkcs_C_DigestUpdate(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen)
+{
+ static CK_C_DigestUpdate sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_DigestUpdate)GetProcAddress(hPK11,
+ "C_DigestUpdate");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pPart, ulPartLen);
+}
+
+CK_RV
+pkcs_C_DigestFinal(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pDigest,
+ CK_ULONG_PTR pulDigestLen)
+{
+ static CK_C_DigestFinal sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_DigestFinal)GetProcAddress(hPK11, "C_DigestFinal");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pDigest, pulDigestLen);
+}
+
+CK_RV
+pkcs_C_SignInit(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ static CK_C_SignInit sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_SignInit)GetProcAddress(hPK11, "C_SignInit");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pMechanism, 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)
+{
+ static CK_C_Sign sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_Sign)GetProcAddress(hPK11, "C_Sign");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pData, ulDataLen, pSignature, pulSignatureLen);
+}
+
+CK_RV
+pkcs_C_SignUpdate(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen)
+{
+ static CK_C_SignUpdate sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_SignUpdate)GetProcAddress(hPK11, "C_SignUpdate");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pPart, ulPartLen);
+}
+
+CK_RV
+pkcs_C_SignFinal(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pSignature,
+ CK_ULONG_PTR pulSignatureLen)
+{
+ static CK_C_SignFinal sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_SignFinal)GetProcAddress(hPK11, "C_SignFinal");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pSignature, pulSignatureLen);
+}
+
+CK_RV
+pkcs_C_VerifyInit(CK_SESSION_HANDLE hSession,
+ CK_MECHANISM_PTR pMechanism,
+ CK_OBJECT_HANDLE hKey)
+{
+ static CK_C_VerifyInit sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_VerifyInit)GetProcAddress(hPK11, "C_VerifyInit");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pMechanism, hKey);
+}
+
+CK_RV
+pkcs_C_Verify(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pData,
+ CK_ULONG ulDataLen,
+ CK_BYTE_PTR pSignature,
+ CK_ULONG ulSignatureLen)
+{
+ static CK_C_Verify sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_Verify)GetProcAddress(hPK11, "C_Verify");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pData, ulDataLen, pSignature, ulSignatureLen);
+}
+
+CK_RV
+pkcs_C_VerifyUpdate(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pPart,
+ CK_ULONG ulPartLen)
+{
+ static CK_C_VerifyUpdate sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_VerifyUpdate)GetProcAddress(hPK11,
+ "C_VerifyUpdate");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pPart, ulPartLen);
+}
+
+CK_RV
+pkcs_C_VerifyFinal(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pSignature,
+ CK_ULONG ulSignatureLen)
+{
+ static CK_C_VerifyFinal sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_VerifyFinal)GetProcAddress(hPK11, "C_VerifyFinal");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pSignature, 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)
+{
+ static CK_C_GenerateKey sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_GenerateKey)GetProcAddress(hPK11, "C_GenerateKey");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pMechanism, pTemplate, ulCount, 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)
+{
+ static CK_C_GenerateKeyPair sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_GenerateKeyPair)GetProcAddress(hPK11,
+ "C_GenerateKeyPair");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession,
+ pMechanism,
+ pPublicKeyTemplate,
+ usPublicKeyAttributeCount,
+ pPrivateKeyTemplate,
+ usPrivateKeyAttributeCount,
+ phPrivateKey,
+ 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)
+{
+ static CK_C_DeriveKey sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_DeriveKey)GetProcAddress(hPK11, "C_DeriveKey");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession,
+ pMechanism,
+ hBaseKey,
+ pTemplate,
+ ulAttributeCount,
+ phKey);
+}
+
+CK_RV
+pkcs_C_SeedRandom(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR pSeed,
+ CK_ULONG ulSeedLen)
+{
+ static CK_C_SeedRandom sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_SeedRandom)GetProcAddress(hPK11, "C_SeedRandom");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, pSeed, ulSeedLen);
+}
+
+CK_RV
+pkcs_C_GenerateRandom(CK_SESSION_HANDLE hSession,
+ CK_BYTE_PTR RandomData,
+ CK_ULONG ulRandomLen)
+{
+ static CK_C_GenerateRandom sym = NULL;
+
+ if (hPK11 == NULL)
+ return (CKR_LIBRARY_FAILED_TO_LOAD);
+ if (sym == NULL)
+ sym = (CK_C_GenerateRandom)GetProcAddress(hPK11,
+ "C_GenerateRandom");
+ if (sym == NULL)
+ return (CKR_SYMBOL_RESOLUTION_FAILED);
+ return (*sym)(hSession, RandomData, ulRandomLen);
+}
diff --git a/lib/isc/win32/resource.c b/lib/isc/win32/resource.c
new file mode 100644
index 0000000..0fbc9a4
--- /dev/null
+++ b/lib/isc/win32/resource.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <isc/platform.h>
+#include <isc/resource.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include "errno2result.h"
+
+/*
+ * Windows limits the maximum number of open files to 2048
+ */
+
+#define WIN32_MAX_OPEN_FILES 2048
+
+isc_result_t
+isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) {
+ isc_resourcevalue_t rlim_value;
+ int wresult;
+
+ if (resource != isc_resource_openfiles)
+ return (ISC_R_NOTIMPLEMENTED);
+
+
+ if (value == ISC_RESOURCE_UNLIMITED)
+ rlim_value = WIN32_MAX_OPEN_FILES;
+ else
+ rlim_value = min(value, WIN32_MAX_OPEN_FILES);
+
+ wresult = _setmaxstdio((int) rlim_value);
+
+ if (wresult > 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
+
+ if (resource != isc_resource_openfiles)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ *value = WIN32_MAX_OPEN_FILES;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
+ return (isc_resource_getlimit(resource, value));
+}
diff --git a/lib/isc/win32/socket.c b/lib/isc/win32/socket.c
new file mode 100644
index 0000000..75b1c26
--- /dev/null
+++ b/lib/isc/win32/socket.c
@@ -0,0 +1,4277 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/* This code uses functions which are only available on Server 2003 and
+ * higher, and Windows XP and higher.
+ *
+ * This code is by nature multithreaded and takes advantage of various
+ * features to pass on information through the completion port for
+ * when I/O is completed. All sends, receives, accepts, and connects are
+ * completed through the completion port.
+ *
+ * The number of Completion Port Worker threads used is the total number
+ * of CPU's + 1. This increases the likelihood that a Worker Thread is
+ * available for processing a completed request.
+ *
+ * XXXPDM 5 August, 2002
+ */
+
+#include <config.h>
+
+#define MAKE_EXTERNAL 1
+
+#include <sys/types.h>
+
+#ifndef _WINSOCKAPI_
+#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
+#endif
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <io.h>
+#include <fcntl.h>
+#include <process.h>
+
+#include <isc/app.h>
+#include <isc/buffer.h>
+#include <isc/bufferlist.h>
+#include <isc/condition.h>
+#include <isc/list.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/mutex.h>
+#include <isc/net.h>
+#include <isc/once.h>
+#include <isc/os.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/socket.h>
+#include <isc/stats.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+#include <isc/syslog.h>
+#include <isc/task.h>
+#include <isc/thread.h>
+#include <isc/util.h>
+#include <isc/win32os.h>
+
+#include <mswsock.h>
+
+#include "errno2result.h"
+
+/*
+ * Set by the -T dscp option on the command line. If set to a value
+ * other than -1, we check to make sure DSCP values match it, and
+ * assert if not.
+ */
+LIBISC_EXTERNAL_DATA int isc_dscp_check_value = -1;
+
+/*
+ * How in the world can Microsoft exist with APIs like this?
+ * We can't actually call this directly, because it turns out
+ * no library exports this function. Instead, we need to
+ * issue a runtime call to get the address.
+ */
+LPFN_CONNECTEX ISCConnectEx;
+LPFN_ACCEPTEX ISCAcceptEx;
+LPFN_GETACCEPTEXSOCKADDRS ISCGetAcceptExSockaddrs;
+
+/*
+ * Run expensive internal consistency checks.
+ */
+#ifdef ISC_SOCKET_CONSISTENCY_CHECKS
+#define CONSISTENT(sock) consistent(sock)
+#else
+#define CONSISTENT(sock) do {} while (0)
+#endif
+static void consistent(isc_socket_t *sock);
+
+/*
+ * Define this macro to control the behavior of connection
+ * resets on UDP sockets. See Microsoft KnowledgeBase Article Q263823
+ * for details.
+ * NOTE: This requires that Windows 2000 systems install Service Pack 2
+ * or later.
+ */
+#ifndef SIO_UDP_CONNRESET
+#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
+#endif
+
+/*
+ * Some systems define the socket length argument as an int, some as size_t,
+ * some as socklen_t. This is here so it can be easily changed if needed.
+ */
+#ifndef ISC_SOCKADDR_LEN_T
+#define ISC_SOCKADDR_LEN_T unsigned int
+#endif
+
+/*
+ * Define what the possible "soft" errors can be. These are non-fatal returns
+ * of various network related functions, like recv() and so on.
+ */
+#define SOFT_ERROR(e) ((e) == WSAEINTR || \
+ (e) == WSAEWOULDBLOCK || \
+ (e) == EWOULDBLOCK || \
+ (e) == EINTR || \
+ (e) == EAGAIN || \
+ (e) == 0)
+
+/*
+ * Pending errors are not really errors and should be
+ * kept separate
+ */
+#define PENDING_ERROR(e) ((e) == WSA_IO_PENDING || (e) == 0)
+
+#define DOIO_SUCCESS 0 /* i/o ok, event sent */
+#define DOIO_SOFT 1 /* i/o ok, soft error, no event sent */
+#define DOIO_HARD 2 /* i/o error, event sent */
+#define DOIO_EOF 3 /* EOF, no event sent */
+#define DOIO_PENDING 4 /* status when i/o is in process */
+#define DOIO_NEEDMORE 5 /* IO was processed, but we need more due to minimum */
+
+#define DLVL(x) ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(x)
+
+/*
+ * DLVL(90) -- Function entry/exit and other tracing.
+ * DLVL(70) -- Socket "correctness" -- including returning of events, etc.
+ * DLVL(60) -- Socket data send/receive
+ * DLVL(50) -- Event tracing, including receiving/sending completion events.
+ * DLVL(20) -- Socket creation/destruction.
+ */
+#define TRACE_LEVEL 90
+#define CORRECTNESS_LEVEL 70
+#define IOEVENT_LEVEL 60
+#define EVENT_LEVEL 50
+#define CREATION_LEVEL 20
+
+#define TRACE DLVL(TRACE_LEVEL)
+#define CORRECTNESS DLVL(CORRECTNESS_LEVEL)
+#define IOEVENT DLVL(IOEVENT_LEVEL)
+#define EVENT DLVL(EVENT_LEVEL)
+#define CREATION DLVL(CREATION_LEVEL)
+
+typedef isc_event_t intev_t;
+
+/*
+ * Socket State
+ */
+enum {
+ SOCK_INITIALIZED, /* Socket Initialized */
+ SOCK_OPEN, /* Socket opened but nothing yet to do */
+ SOCK_DATA, /* Socket sending or receiving data */
+ SOCK_LISTEN, /* TCP Socket listening for connects */
+ SOCK_ACCEPT, /* TCP socket is waiting to accept */
+ SOCK_CONNECT, /* TCP Socket connecting */
+ SOCK_CLOSED, /* Socket has been closed */
+};
+
+#define SOCKET_MAGIC ISC_MAGIC('I', 'O', 'i', 'o')
+#define VALID_SOCKET(t) ISC_MAGIC_VALID(t, SOCKET_MAGIC)
+
+/*
+ * IPv6 control information. If the socket is an IPv6 socket we want
+ * to collect the destination address and interface so the client can
+ * set them on outgoing packets.
+ */
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifndef USE_CMSG
+#define USE_CMSG 1
+#endif
+#endif
+
+/*
+ * We really don't want to try and use these control messages. Win32
+ * doesn't have this mechanism before XP.
+ */
+#undef USE_CMSG
+
+/*
+ * Message header for recvmsg and sendmsg calls.
+ * Used value-result for recvmsg, value only for sendmsg.
+ */
+struct msghdr {
+ SOCKADDR_STORAGE to_addr; /* UDP send/recv address */
+ int to_addr_len; /* length of the address */
+ WSABUF *msg_iov; /* scatter/gather array */
+ u_int msg_iovlen; /* # elements in msg_iov */
+ void *msg_control; /* ancillary data, see below */
+ u_int msg_controllen; /* ancillary data buffer len */
+ u_int msg_totallen; /* total length of this message */
+} msghdr;
+
+/*
+ * The size to raise the receive buffer to.
+ */
+#define RCVBUFSIZE (32*1024)
+
+/*
+ * The number of times a send operation is repeated if the result
+ * is WSAEINTR.
+ */
+#define NRETRIES 10
+
+struct isc_socket {
+ /* Not locked. */
+ unsigned int magic;
+ isc_socketmgr_t *manager;
+ isc_mutex_t lock;
+ isc_sockettype_t type;
+
+ /* Pointers to scatter/gather buffers */
+ WSABUF iov[ISC_SOCKET_MAXSCATTERGATHER];
+
+ /* Locked by socket lock. */
+ ISC_LINK(isc_socket_t) link;
+ unsigned int references; /* EXTERNAL references */
+ SOCKET fd; /* file handle */
+ int pf; /* protocol family */
+ char name[16];
+ void * tag;
+
+ /*
+ * Each recv() call uses this buffer. It is a per-socket receive
+ * buffer that allows us to decouple the system recv() from the
+ * recv_list done events. This means the items on the recv_list
+ * can be removed without having to cancel pending system recv()
+ * calls. It also allows us to read-ahead in some cases.
+ */
+ struct {
+ SOCKADDR_STORAGE from_addr; // UDP send/recv address
+ int from_addr_len; // length of the address
+ char *base; // the base of the buffer
+ char *consume_position; // where to start copying data from next
+ unsigned int len; // the actual size of this buffer
+ unsigned int remaining; // the number of bytes remaining
+ } recvbuf;
+
+ ISC_LIST(isc_socketevent_t) send_list;
+ ISC_LIST(isc_socketevent_t) recv_list;
+ ISC_LIST(isc_socket_newconnev_t) accept_list;
+ ISC_LIST(isc_socket_connev_t) connect_list;
+
+ isc_sockaddr_t address; /* remote address */
+
+ unsigned int listener : 1, /* listener socket */
+ connected : 1,
+ pending_connect : 1, /* connect pending */
+ bound : 1, /* bound to local addr */
+ dupped : 1; /* created by isc_socket_dup() */
+ unsigned int pending_iocp; /* Should equal the counters below. Debug. */
+ unsigned int pending_recv; /* Number of outstanding recv() calls. */
+ unsigned int pending_send; /* Number of outstanding send() calls. */
+ unsigned int pending_accept; /* Number of outstanding accept() calls. */
+ unsigned int state; /* Socket state. Debugging and consistency checking. */
+ int state_lineno; /* line which last touched state */
+};
+
+#define _set_state(sock, _state) do { (sock)->state = (_state); (sock)->state_lineno = __LINE__; } while (0)
+
+/*
+ * Buffer structure
+ */
+typedef struct buflist buflist_t;
+
+struct buflist {
+ void *buf;
+ unsigned int buflen;
+ ISC_LINK(buflist_t) link;
+};
+
+/*
+ * I/O Completion ports Info structures
+ */
+
+static HANDLE hHeapHandle = NULL;
+typedef struct IoCompletionInfo {
+ OVERLAPPED overlapped;
+ isc_socketevent_t *dev; /* send()/recv() done event */
+ isc_socket_connev_t *cdev; /* connect() done event */
+ isc_socket_newconnev_t *adev; /* accept() done event */
+ void *acceptbuffer;
+ DWORD received_bytes;
+ int request_type;
+ struct msghdr messagehdr;
+ ISC_LIST(buflist_t) bufferlist; /*%< list of buffers */
+} IoCompletionInfo;
+
+/*
+ * Define a maximum number of I/O Completion Port worker threads
+ * to handle the load on the Completion Port. The actual number
+ * used is the number of CPU's + 1.
+ */
+#define MAX_IOCPTHREADS 20
+
+#define SOCKET_MANAGER_MAGIC ISC_MAGIC('I', 'O', 'm', 'g')
+#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, SOCKET_MANAGER_MAGIC)
+
+struct isc_socketmgr {
+ /* Not locked. */
+ unsigned int magic;
+ isc_mem_t *mctx;
+ isc_mutex_t lock;
+ isc_stats_t *stats;
+
+ /* Locked by manager lock. */
+ ISC_LIST(isc_socket_t) socklist;
+ bool bShutdown;
+ isc_condition_t shutdown_ok;
+ HANDLE hIoCompletionPort;
+ int maxIOCPThreads;
+ HANDLE hIOCPThreads[MAX_IOCPTHREADS];
+ DWORD dwIOCPThreadIds[MAX_IOCPTHREADS];
+
+ /*
+ * Debugging.
+ * Modified by InterlockedIncrement() and InterlockedDecrement()
+ */
+ LONG totalSockets;
+ LONG iocp_total;
+};
+
+enum {
+ SOCKET_RECV,
+ SOCKET_SEND,
+ SOCKET_ACCEPT,
+ SOCKET_CONNECT
+};
+
+/*
+ * send() and recv() iovec counts
+ */
+#define MAXSCATTERGATHER_SEND (ISC_SOCKET_MAXSCATTERGATHER)
+#define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER)
+
+static isc_result_t socket_create(isc_socketmgr_t *manager0, int pf,
+ isc_sockettype_t type,
+ isc_socket_t **socketp,
+ isc_socket_t *dup_socket);
+static isc_threadresult_t WINAPI SocketIoThread(LPVOID ThreadContext);
+static void maybe_free_socket(isc_socket_t **, int);
+static void free_socket(isc_socket_t **, int);
+static bool senddone_is_active(isc_socket_t *sock, isc_socketevent_t *dev);
+static bool acceptdone_is_active(isc_socket_t *sock, isc_socket_newconnev_t *dev);
+static bool connectdone_is_active(isc_socket_t *sock, isc_socket_connev_t *dev);
+static void send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev);
+static void send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev);
+static void send_acceptdone_event(isc_socket_t *sock, isc_socket_newconnev_t **adev);
+static void send_connectdone_event(isc_socket_t *sock, isc_socket_connev_t **cdev);
+static void send_recvdone_abort(isc_socket_t *sock, isc_result_t result);
+static void send_connectdone_abort(isc_socket_t *sock, isc_result_t result);
+static void queue_receive_event(isc_socket_t *sock, isc_task_t *task, isc_socketevent_t *dev);
+static void queue_receive_request(isc_socket_t *sock);
+
+/*
+ * This is used to dump the contents of the sock structure
+ * You should make sure that the sock is locked before
+ * dumping it. Since the code uses simple printf() statements
+ * it should only be used interactively.
+ */
+void
+sock_dump(isc_socket_t *sock) {
+ isc_socketevent_t *ldev;
+ isc_socket_newconnev_t *ndev;
+ isc_socket_connev_t *cdev;
+
+#if 0
+ isc_sockaddr_t addr;
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_result_t result;
+
+ result = isc_socket_getpeername(sock, &addr);
+ if (result == ISC_R_SUCCESS) {
+ isc_sockaddr_format(&addr, socktext, sizeof(socktext));
+ printf("Remote Socket: %s\n", socktext);
+ }
+ result = isc_socket_getsockname(sock, &addr);
+ if (result == ISC_R_SUCCESS) {
+ isc_sockaddr_format(&addr, socktext, sizeof(socktext));
+ printf("This Socket: %s\n", socktext);
+ }
+#endif
+
+ printf("\n\t\tSock Dump\n");
+ printf("\t\tfd: %Iu\n", sock->fd);
+ printf("\t\treferences: %u\n", sock->references);
+ printf("\t\tpending_accept: %u\n", sock->pending_accept);
+ printf("\t\tconnecting: %u\n", sock->pending_connect);
+ printf("\t\tconnected: %u\n", sock->connected);
+ printf("\t\tbound: %u\n", sock->bound);
+ printf("\t\tpending_iocp: %u\n", sock->pending_iocp);
+ printf("\t\tsocket type: %d\n", sock->type);
+
+ printf("\n\t\tSock Recv List\n");
+ ldev = ISC_LIST_HEAD(sock->recv_list);
+ while (ldev != NULL) {
+ printf("\t\tdev: %p\n", ldev);
+ ldev = ISC_LIST_NEXT(ldev, ev_link);
+ }
+
+ printf("\n\t\tSock Send List\n");
+ ldev = ISC_LIST_HEAD(sock->send_list);
+ while (ldev != NULL) {
+ printf("\t\tdev: %p\n", ldev);
+ ldev = ISC_LIST_NEXT(ldev, ev_link);
+ }
+
+ printf("\n\t\tSock Accept List\n");
+ ndev = ISC_LIST_HEAD(sock->accept_list);
+ while (ndev != NULL) {
+ printf("\t\tdev: %p\n", ldev);
+ ndev = ISC_LIST_NEXT(ndev, ev_link);
+ }
+
+ printf("\n\t\tSock Connect List\n");
+ cdev = ISC_LIST_HEAD(sock->connect_list);
+ while (cdev != NULL) {
+ printf("\t\tdev: %p\n", cdev);
+ cdev = ISC_LIST_NEXT(cdev, ev_link);
+ }
+}
+
+static void
+socket_log(int lineno, isc_socket_t *sock, isc_sockaddr_t *address,
+ isc_logcategory_t *category, isc_logmodule_t *module, int level,
+ isc_msgcat_t *msgcat, int msgset, int message,
+ const char *fmt, ...) ISC_FORMAT_PRINTF(9, 10);
+
+/* This function will add an entry to the I/O completion port
+ * that will signal the I/O thread to exit (gracefully)
+ */
+static void
+signal_iocompletionport_exit(isc_socketmgr_t *manager) {
+ int i;
+ int errval;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(VALID_MANAGER(manager));
+ for (i = 0; i < manager->maxIOCPThreads; i++) {
+ if (!PostQueuedCompletionStatus(manager->hIoCompletionPort,
+ 0, 0, 0)) {
+ errval = GetLastError();
+ isc__strerror(errval, strbuf, sizeof(strbuf));
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_FAILED,
+ "Can't request service thread to exit: %s"),
+ strbuf);
+ }
+ }
+}
+
+/*
+ * Create the worker threads for the I/O Completion Port
+ */
+void
+iocompletionport_createthreads(int total_threads, isc_socketmgr_t *manager) {
+ int errval;
+ char strbuf[ISC_STRERRORSIZE];
+ int i;
+
+ INSIST(total_threads > 0);
+ REQUIRE(VALID_MANAGER(manager));
+ /*
+ * We need at least one
+ */
+ for (i = 0; i < total_threads; i++) {
+ manager->hIOCPThreads[i] = CreateThread(NULL, 0, SocketIoThread,
+ manager, 0,
+ &manager->dwIOCPThreadIds[i]);
+ if (manager->hIOCPThreads[i] == NULL) {
+ errval = GetLastError();
+ isc__strerror(errval, strbuf, sizeof(strbuf));
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_FAILED,
+ "Can't create IOCP thread: %s"),
+ strbuf);
+ }
+ }
+}
+
+/*
+ * Create/initialise the I/O completion port
+ */
+void
+iocompletionport_init(isc_socketmgr_t *manager) {
+ int errval;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(VALID_MANAGER(manager));
+ /*
+ * Create a private heap to handle the socket overlapped structure
+ * The minimum number of structures is 10, there is no maximum
+ */
+ hHeapHandle = HeapCreate(0, 10 * sizeof(IoCompletionInfo), 0);
+ if (hHeapHandle == NULL) {
+ errval = GetLastError();
+ isc__strerror(errval, strbuf, sizeof(strbuf));
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_FAILED,
+ "HeapCreate() failed during "
+ "initialization: %s"),
+ strbuf);
+ }
+
+ manager->maxIOCPThreads = min(isc_os_ncpus() + 1, MAX_IOCPTHREADS);
+
+ /* Now Create the Completion Port */
+ manager->hIoCompletionPort = CreateIoCompletionPort(
+ INVALID_HANDLE_VALUE, NULL,
+ 0, manager->maxIOCPThreads);
+ if (manager->hIoCompletionPort == NULL) {
+ errval = GetLastError();
+ isc__strerror(errval, strbuf, sizeof(strbuf));
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_FAILED,
+ "CreateIoCompletionPort() failed "
+ "during initialization: %s"),
+ strbuf);
+ }
+
+ /*
+ * Worker threads for servicing the I/O
+ */
+ iocompletionport_createthreads(manager->maxIOCPThreads, manager);
+}
+
+/*
+ * Associate a socket with an IO Completion Port. This allows us to queue events for it
+ * and have our worker pool of threads process them.
+ */
+void
+iocompletionport_update(isc_socket_t *sock) {
+ HANDLE hiocp;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ hiocp = CreateIoCompletionPort((HANDLE)sock->fd,
+ sock->manager->hIoCompletionPort, (ULONG_PTR)sock, 0);
+
+ if (hiocp == NULL) {
+ DWORD errval = GetLastError();
+ isc__strerror(errval, strbuf, sizeof(strbuf));
+ isc_log_iwrite(isc_lctx,
+ ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_TOOMANYHANDLES,
+ "iocompletionport_update: failed to open"
+ " io completion port: %s",
+ strbuf);
+
+ /* XXXMLG temporary hack to make failures detected.
+ * This function should return errors to the caller, not
+ * exit here.
+ */
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_FAILED,
+ "CreateIoCompletionPort() failed "
+ "during initialization: %s"),
+ strbuf);
+ }
+
+ InterlockedIncrement(&sock->manager->iocp_total);
+}
+
+/*
+ * Routine to cleanup and then close the socket.
+ * Only close the socket here if it is NOT associated
+ * with an event, otherwise the WSAWaitForMultipleEvents
+ * may fail due to the fact that the Wait should not
+ * be running while closing an event or a socket.
+ * The socket is locked before calling this function
+ */
+void
+socket_close(isc_socket_t *sock) {
+
+ REQUIRE(sock != NULL);
+
+ if (sock->fd != INVALID_SOCKET) {
+ closesocket(sock->fd);
+ sock->fd = INVALID_SOCKET;
+ _set_state(sock, SOCK_CLOSED);
+ InterlockedDecrement(&sock->manager->totalSockets);
+ }
+}
+
+static isc_once_t initialise_once = ISC_ONCE_INIT;
+static bool initialised = false;
+
+static void
+initialise(void) {
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+ SOCKET sock;
+ GUID GUIDConnectEx = WSAID_CONNECTEX;
+ GUID GUIDAcceptEx = WSAID_ACCEPTEX;
+ GUID GUIDGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
+ DWORD dwBytes;
+
+ /* Need Winsock 2.2 or better */
+ wVersionRequested = MAKEWORD(2, 2);
+
+ err = WSAStartup(wVersionRequested, &wsaData);
+ if (err != 0) {
+ char strbuf[ISC_STRERRORSIZE];
+ isc__strerror(err, strbuf, sizeof(strbuf));
+ FATAL_ERROR(__FILE__, __LINE__, "WSAStartup() %s: %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"),
+ strbuf);
+ }
+ /*
+ * The following APIs do not exist as functions in a library, but
+ * we must ask winsock for them. They are "extensions" -- but why
+ * they cannot be actual functions is beyond me. So, ask winsock
+ * for the pointers to the functions we need.
+ */
+ sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ INSIST(sock != INVALID_SOCKET);
+ err = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &GUIDConnectEx, sizeof(GUIDConnectEx),
+ &ISCConnectEx, sizeof(ISCConnectEx),
+ &dwBytes, NULL, NULL);
+ INSIST(err == 0);
+
+ err = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &GUIDAcceptEx, sizeof(GUIDAcceptEx),
+ &ISCAcceptEx, sizeof(ISCAcceptEx),
+ &dwBytes, NULL, NULL);
+ INSIST(err == 0);
+
+ err = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &GUIDGetAcceptExSockaddrs, sizeof(GUIDGetAcceptExSockaddrs),
+ &ISCGetAcceptExSockaddrs, sizeof(ISCGetAcceptExSockaddrs),
+ &dwBytes, NULL, NULL);
+ INSIST(err == 0);
+
+ closesocket(sock);
+
+ initialised = true;
+}
+
+/*
+ * Initialize socket services
+ */
+void
+InitSockets(void) {
+ RUNTIME_CHECK(isc_once_do(&initialise_once,
+ initialise) == ISC_R_SUCCESS);
+ if (!initialised)
+ exit(1);
+}
+
+int
+internal_sendmsg(isc_socket_t *sock, IoCompletionInfo *lpo,
+ struct msghdr *messagehdr, int flags, int *Error)
+{
+ int Result;
+ DWORD BytesSent;
+ DWORD Flags = flags;
+ int total_sent;
+
+ *Error = 0;
+ Result = WSASendTo(sock->fd, messagehdr->msg_iov,
+ messagehdr->msg_iovlen, &BytesSent,
+ Flags, (SOCKADDR *)&messagehdr->to_addr,
+ messagehdr->to_addr_len, (LPWSAOVERLAPPED)lpo,
+ NULL);
+
+ total_sent = (int)BytesSent;
+
+ /* Check for errors.*/
+ if (Result == SOCKET_ERROR) {
+ *Error = WSAGetLastError();
+
+ switch (*Error) {
+ case WSA_IO_INCOMPLETE:
+ case WSA_WAIT_IO_COMPLETION:
+ case WSA_IO_PENDING:
+ case NO_ERROR: /* Strange, but okay */
+ sock->pending_iocp++;
+ sock->pending_send++;
+ break;
+
+ default:
+ return (-1);
+ break;
+ }
+ } else {
+ sock->pending_iocp++;
+ sock->pending_send++;
+ }
+
+ if (lpo != NULL)
+ return (0);
+ else
+ return (total_sent);
+}
+
+static void
+queue_receive_request(isc_socket_t *sock) {
+ DWORD Flags = 0;
+ DWORD NumBytes = 0;
+ int Result;
+ int Error;
+ int need_retry;
+ WSABUF iov[1];
+ IoCompletionInfo *lpo = NULL;
+ isc_result_t isc_result;
+
+ retry:
+ need_retry = false;
+
+ /*
+ * If we already have a receive pending, do nothing.
+ */
+ if (sock->pending_recv > 0) {
+ if (lpo != NULL)
+ HeapFree(hHeapHandle, 0, lpo);
+ return;
+ }
+
+ /*
+ * If no one is waiting, do nothing.
+ */
+ if (ISC_LIST_EMPTY(sock->recv_list)) {
+ if (lpo != NULL)
+ HeapFree(hHeapHandle, 0, lpo);
+ return;
+ }
+
+ INSIST(sock->recvbuf.remaining == 0);
+ INSIST(sock->fd != INVALID_SOCKET);
+
+ iov[0].len = sock->recvbuf.len;
+ iov[0].buf = sock->recvbuf.base;
+
+ if (lpo == NULL) {
+ lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
+ HEAP_ZERO_MEMORY,
+ sizeof(IoCompletionInfo));
+ RUNTIME_CHECK(lpo != NULL);
+ } else
+ ZeroMemory(lpo, sizeof(IoCompletionInfo));
+ lpo->request_type = SOCKET_RECV;
+
+ sock->recvbuf.from_addr_len = sizeof(sock->recvbuf.from_addr);
+
+ Error = 0;
+ Result = WSARecvFrom((SOCKET)sock->fd, iov, 1,
+ &NumBytes, &Flags,
+ (SOCKADDR *)&sock->recvbuf.from_addr,
+ &sock->recvbuf.from_addr_len,
+ (LPWSAOVERLAPPED)lpo, NULL);
+
+ /* Check for errors. */
+ if (Result == SOCKET_ERROR) {
+ Error = WSAGetLastError();
+
+ switch (Error) {
+ case WSA_IO_PENDING:
+ sock->pending_iocp++;
+ sock->pending_recv++;
+ break;
+
+ /* direct error: no completion event */
+ case ERROR_HOST_UNREACHABLE:
+ case WSAENETRESET:
+ case WSAECONNRESET:
+ if (!sock->connected) {
+ /* soft error */
+ need_retry = true;
+ break;
+ }
+ /* FALLTHROUGH */
+
+ default:
+ isc_result = isc__errno2result(Error);
+ if (isc_result == ISC_R_UNEXPECTED)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "WSARecvFrom: Windows error code: %d, isc result %d",
+ Error, isc_result);
+ send_recvdone_abort(sock, isc_result);
+ HeapFree(hHeapHandle, 0, lpo);
+ lpo = NULL;
+ break;
+ }
+ } else {
+ /*
+ * The recv() finished immediately, but we will still get
+ * a completion event. Rather than duplicate code, let
+ * that thread handle sending the data along its way.
+ */
+ sock->pending_iocp++;
+ sock->pending_recv++;
+ }
+
+ socket_log(__LINE__, sock, NULL, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_DOIORECV,
+ "queue_io_request: fd %d result %d error %d",
+ sock->fd, Result, Error);
+
+ CONSISTENT(sock);
+
+ if (need_retry)
+ goto retry;
+}
+
+static void
+manager_log(isc_socketmgr_t *sockmgr, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *fmt, ...)
+{
+ char msgbuf[2048];
+ va_list ap;
+
+ if (!isc_log_wouldlog(isc_lctx, level))
+ return;
+
+ va_start(ap, fmt);
+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+ va_end(ap);
+
+ isc_log_write(isc_lctx, category, module, level,
+ "sockmgr %p: %s", sockmgr, msgbuf);
+}
+
+static void
+socket_log(int lineno, isc_socket_t *sock, isc_sockaddr_t *address,
+ isc_logcategory_t *category, isc_logmodule_t *module, int level,
+ isc_msgcat_t *msgcat, int msgset, int message,
+ const char *fmt, ...)
+{
+ char msgbuf[2048];
+ char peerbuf[256];
+ va_list ap;
+
+
+ if (!isc_log_wouldlog(isc_lctx, level))
+ return;
+
+ va_start(ap, fmt);
+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+ va_end(ap);
+
+ if (address == NULL) {
+ isc_log_iwrite(isc_lctx, category, module, level,
+ msgcat, msgset, message,
+ "socket %p line %d: %s", sock, lineno, msgbuf);
+ } else {
+ isc_sockaddr_format(address, peerbuf, sizeof(peerbuf));
+ isc_log_iwrite(isc_lctx, category, module, level,
+ msgcat, msgset, message,
+ "socket %p line %d %s: %s", sock, lineno,
+ peerbuf, msgbuf);
+ }
+
+}
+
+/*
+ * Make an fd SOCKET non-blocking.
+ */
+static isc_result_t
+make_nonblock(SOCKET fd) {
+ int ret;
+ unsigned long flags = 1;
+ char strbuf[ISC_STRERRORSIZE];
+
+ /* Set the socket to non-blocking */
+ ret = ioctlsocket(fd, FIONBIO, &flags);
+
+ if (ret == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "ioctlsocket(%d, FIOBIO, %d): %s",
+ fd, flags, strbuf);
+
+ return (ISC_R_UNEXPECTED);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Windows 2000 systems incorrectly cause UDP sockets using WSARecvFrom
+ * to not work correctly, returning a WSACONNRESET error when a WSASendTo
+ * fails with an "ICMP port unreachable" response and preventing the
+ * socket from using the WSARecvFrom in subsequent operations.
+ * The function below fixes this, but requires that Windows 2000
+ * Service Pack 2 or later be installed on the system. NT 4.0
+ * systems are not affected by this and work correctly.
+ * See Microsoft Knowledge Base Article Q263823 for details of this.
+ */
+isc_result_t
+connection_reset_fix(SOCKET fd) {
+ DWORD dwBytesReturned = 0;
+ BOOL bNewBehavior = FALSE;
+ DWORD status;
+
+ if (isc_win32os_versioncheck(5, 0, 0, 0) < 0)
+ return (ISC_R_SUCCESS); /* NT 4.0 has no problem */
+
+ /* disable bad behavior using IOCTL: SIO_UDP_CONNRESET */
+ status = WSAIoctl(fd, SIO_UDP_CONNRESET, &bNewBehavior,
+ sizeof(bNewBehavior), NULL, 0,
+ &dwBytesReturned, NULL, NULL);
+ if (status != SOCKET_ERROR)
+ return (ISC_R_SUCCESS);
+ else {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "WSAIoctl(SIO_UDP_CONNRESET, oldBehaviour) %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ return (ISC_R_UNEXPECTED);
+ }
+}
+
+/*
+ * Construct an iov array and attach it to the msghdr passed in. This is
+ * the SEND constructor, which will use the used region of the buffer
+ * (if using a buffer list) or will use the internal region (if a single
+ * buffer I/O is requested).
+ *
+ * Nothing can be NULL, and the done event must list at least one buffer
+ * on the buffer linked list for this function to be meaningful.
+ */
+static void
+build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
+ struct msghdr *msg, char *cmsg, WSABUF *iov,
+ IoCompletionInfo *lpo)
+{
+ unsigned int iovcount;
+ isc_buffer_t *buffer;
+ buflist_t *cpbuffer;
+ isc_region_t used;
+ size_t write_count;
+ size_t skip_count;
+
+ memset(msg, 0, sizeof(*msg));
+
+ memmove(&msg->to_addr, &dev->address.type, dev->address.length);
+ msg->to_addr_len = dev->address.length;
+
+ buffer = ISC_LIST_HEAD(dev->bufferlist);
+ write_count = 0;
+ iovcount = 0;
+
+ /*
+ * Single buffer I/O? Skip what we've done so far in this region.
+ */
+ if (buffer == NULL) {
+ write_count = dev->region.length - dev->n;
+ cpbuffer = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, sizeof(buflist_t));
+ RUNTIME_CHECK(cpbuffer != NULL);
+ cpbuffer->buf = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, write_count);
+ RUNTIME_CHECK(cpbuffer->buf != NULL);
+
+ socket_log(__LINE__, sock, NULL, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+ "alloc_buffer %p %d %p %d", cpbuffer, sizeof(buflist_t),
+ cpbuffer->buf, write_count);
+
+ memmove(cpbuffer->buf,(dev->region.base + dev->n), write_count);
+ cpbuffer->buflen = (unsigned int)write_count;
+ ISC_LINK_INIT(cpbuffer, link);
+ ISC_LIST_ENQUEUE(lpo->bufferlist, cpbuffer, link);
+ iov[0].buf = cpbuffer->buf;
+ iov[0].len = (u_long)write_count;
+ iovcount = 1;
+
+ goto config;
+ }
+
+ /*
+ * Multibuffer I/O.
+ * Skip the data in the buffer list that we have already written.
+ */
+ skip_count = dev->n;
+ while (buffer != NULL) {
+ REQUIRE(ISC_BUFFER_VALID(buffer));
+ if (skip_count < isc_buffer_usedlength(buffer))
+ break;
+ skip_count -= isc_buffer_usedlength(buffer);
+ buffer = ISC_LIST_NEXT(buffer, link);
+ }
+
+ while (buffer != NULL) {
+ INSIST(iovcount < MAXSCATTERGATHER_SEND);
+
+ isc_buffer_usedregion(buffer, &used);
+
+ if (used.length > 0) {
+ int uselen = (int)(used.length - skip_count);
+ cpbuffer = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, sizeof(buflist_t));
+ RUNTIME_CHECK(cpbuffer != NULL);
+ cpbuffer->buf = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, uselen);
+ RUNTIME_CHECK(cpbuffer->buf != NULL);
+
+ socket_log(__LINE__, sock, NULL, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+ "alloc_buffer %p %d %p %d", cpbuffer, sizeof(buflist_t),
+ cpbuffer->buf, write_count);
+
+ memmove(cpbuffer->buf,(used.base + skip_count), uselen);
+ cpbuffer->buflen = uselen;
+ iov[iovcount].buf = cpbuffer->buf;
+ iov[iovcount].len = (u_long)(used.length - skip_count);
+ write_count += uselen;
+ skip_count = 0;
+ iovcount++;
+ }
+ buffer = ISC_LIST_NEXT(buffer, link);
+ }
+
+ INSIST(skip_count == 0);
+
+ config:
+ msg->msg_iov = iov;
+ msg->msg_iovlen = iovcount;
+ msg->msg_totallen = (u_int)write_count;
+}
+
+static void
+set_dev_address(isc_sockaddr_t *address, isc_socket_t *sock,
+ isc_socketevent_t *dev)
+{
+ if (sock->type == isc_sockettype_udp) {
+ if (address != NULL)
+ dev->address = *address;
+ else
+ dev->address = sock->address;
+ } else if (sock->type == isc_sockettype_tcp) {
+ INSIST(address == NULL);
+ dev->address = sock->address;
+ }
+}
+
+static void
+destroy_socketevent(isc_event_t *event) {
+ isc_socketevent_t *ev = (isc_socketevent_t *)event;
+
+ INSIST(ISC_LIST_EMPTY(ev->bufferlist));
+
+ (ev->destroy)(event);
+}
+
+static isc_socketevent_t *
+allocate_socketevent(isc_mem_t *mctx, isc_socket_t *sock,
+ isc_eventtype_t eventtype, isc_taskaction_t action,
+ void *arg)
+{
+ isc_socketevent_t *ev;
+
+ ev = (isc_socketevent_t *)isc_event_allocate(mctx, sock, eventtype,
+ action, arg,
+ sizeof(*ev));
+ if (ev == NULL)
+ return (NULL);
+
+ ev->result = ISC_R_IOERROR; // XXXMLG temporary change to detect failure to set
+ ISC_LINK_INIT(ev, ev_link);
+ ISC_LIST_INIT(ev->bufferlist);
+ ev->region.base = NULL;
+ ev->n = 0;
+ ev->offset = 0;
+ ev->attributes = 0;
+ ev->destroy = ev->ev_destroy;
+ ev->ev_destroy = destroy_socketevent;
+ ev->dscp = 0;
+
+ return (ev);
+}
+
+#if defined(ISC_SOCKET_DEBUG)
+static void
+dump_msg(struct msghdr *msg, isc_socket_t *sock) {
+ unsigned int i;
+
+ printf("MSGHDR %p, Socket #: %Iu\n", msg, sock->fd);
+ printf("\tname %p, namelen %d\n", msg->msg_name, msg->msg_namelen);
+ printf("\tiov %p, iovlen %d\n", msg->msg_iov, msg->msg_iovlen);
+ for (i = 0; i < (unsigned int)msg->msg_iovlen; i++)
+ printf("\t\t%u\tbase %p, len %u\n", i,
+ msg->msg_iov[i].buf, msg->msg_iov[i].len);
+}
+#endif
+
+/*
+ * map the error code
+ */
+int
+map_socket_error(isc_socket_t *sock, int windows_errno, int *isc_errno,
+ char *errorstring, size_t bufsize) {
+
+ int doreturn;
+ switch (windows_errno) {
+ case WSAECONNREFUSED:
+ *isc_errno = ISC_R_CONNREFUSED;
+ if (sock->connected)
+ doreturn = DOIO_HARD;
+ else
+ doreturn = DOIO_SOFT;
+ break;
+ case WSAENETUNREACH:
+ case ERROR_NETWORK_UNREACHABLE:
+ *isc_errno = ISC_R_NETUNREACH;
+ if (sock->connected)
+ doreturn = DOIO_HARD;
+ else
+ doreturn = DOIO_SOFT;
+ break;
+ case ERROR_PORT_UNREACHABLE:
+ case ERROR_HOST_UNREACHABLE:
+ case WSAEHOSTUNREACH:
+ *isc_errno = ISC_R_HOSTUNREACH;
+ if (sock->connected)
+ doreturn = DOIO_HARD;
+ else
+ doreturn = DOIO_SOFT;
+ break;
+ case WSAENETDOWN:
+ *isc_errno = ISC_R_NETDOWN;
+ if (sock->connected)
+ doreturn = DOIO_HARD;
+ else
+ doreturn = DOIO_SOFT;
+ break;
+ case WSAEHOSTDOWN:
+ *isc_errno = ISC_R_HOSTDOWN;
+ if (sock->connected)
+ doreturn = DOIO_HARD;
+ else
+ doreturn = DOIO_SOFT;
+ break;
+ case WSAEACCES:
+ *isc_errno = ISC_R_NOPERM;
+ if (sock->connected)
+ doreturn = DOIO_HARD;
+ else
+ doreturn = DOIO_SOFT;
+ break;
+ case WSAECONNRESET:
+ case WSAENETRESET:
+ case WSAECONNABORTED:
+ case WSAEDISCON:
+ *isc_errno = ISC_R_CONNECTIONRESET;
+ if (sock->connected)
+ doreturn = DOIO_HARD;
+ else
+ doreturn = DOIO_SOFT;
+ break;
+ case WSAENOTCONN:
+ *isc_errno = ISC_R_NOTCONNECTED;
+ if (sock->connected)
+ doreturn = DOIO_HARD;
+ else
+ doreturn = DOIO_SOFT;
+ break;
+ case ERROR_OPERATION_ABORTED:
+ case ERROR_CONNECTION_ABORTED:
+ case ERROR_REQUEST_ABORTED:
+ *isc_errno = ISC_R_CONNECTIONRESET;
+ doreturn = DOIO_HARD;
+ break;
+ case WSAENOBUFS:
+ *isc_errno = ISC_R_NORESOURCES;
+ doreturn = DOIO_HARD;
+ break;
+ case WSAEAFNOSUPPORT:
+ *isc_errno = ISC_R_FAMILYNOSUPPORT;
+ doreturn = DOIO_HARD;
+ break;
+ case WSAEADDRNOTAVAIL:
+ *isc_errno = ISC_R_ADDRNOTAVAIL;
+ doreturn = DOIO_HARD;
+ break;
+ case WSAEDESTADDRREQ:
+ *isc_errno = ISC_R_BADADDRESSFORM;
+ doreturn = DOIO_HARD;
+ break;
+ case ERROR_NETNAME_DELETED:
+ *isc_errno = ISC_R_NETDOWN;
+ doreturn = DOIO_HARD;
+ break;
+ default:
+ *isc_errno = ISC_R_IOERROR;
+ doreturn = DOIO_HARD;
+ break;
+ }
+ if (doreturn == DOIO_HARD) {
+ isc__strerror(windows_errno, errorstring, bufsize);
+ }
+ return (doreturn);
+}
+
+static void
+fill_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
+ isc_region_t r;
+ int copylen;
+ isc_buffer_t *buffer;
+
+ INSIST(dev->n < dev->minimum);
+ INSIST(sock->recvbuf.remaining > 0);
+ INSIST(sock->pending_recv == 0);
+
+ if (sock->type == isc_sockettype_udp) {
+ dev->address.length = sock->recvbuf.from_addr_len;
+ memmove(&dev->address.type, &sock->recvbuf.from_addr,
+ sock->recvbuf.from_addr_len);
+ if (isc_sockaddr_getport(&dev->address) == 0) {
+ if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) {
+ socket_log(__LINE__, sock, &dev->address, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_ZEROPORT,
+ "dropping source port zero packet");
+ }
+ sock->recvbuf.remaining = 0;
+ return;
+ }
+ } else if (sock->type == isc_sockettype_tcp) {
+ dev->address = sock->address;
+ }
+
+ /*
+ * Run through the list of buffers we were given, and find the
+ * first one with space. Once it is found, loop through, filling
+ * the buffers as much as possible.
+ */
+ buffer = ISC_LIST_HEAD(dev->bufferlist);
+ if (buffer != NULL) { // Multi-buffer receive
+ while (buffer != NULL && sock->recvbuf.remaining > 0) {
+ REQUIRE(ISC_BUFFER_VALID(buffer));
+ if (isc_buffer_availablelength(buffer) > 0) {
+ isc_buffer_availableregion(buffer, &r);
+ copylen = min(r.length,
+ sock->recvbuf.remaining);
+ memmove(r.base, sock->recvbuf.consume_position,
+ copylen);
+ sock->recvbuf.consume_position += copylen;
+ sock->recvbuf.remaining -= copylen;
+ isc_buffer_add(buffer, copylen);
+ dev->n += copylen;
+ }
+ buffer = ISC_LIST_NEXT(buffer, link);
+ }
+ } else { // Single-buffer receive
+ copylen = min(dev->region.length - dev->n, sock->recvbuf.remaining);
+ memmove(dev->region.base + dev->n,
+ sock->recvbuf.consume_position, copylen);
+ sock->recvbuf.consume_position += copylen;
+ sock->recvbuf.remaining -= copylen;
+ dev->n += copylen;
+ }
+
+ /*
+ * UDP receives are all-consuming. That is, if we have 4k worth of
+ * data in our receive buffer, and the caller only gave us
+ * 1k of space, we will toss the remaining 3k of data. TCP
+ * will keep the extra data around and use it for later requests.
+ */
+ if (sock->type == isc_sockettype_udp)
+ sock->recvbuf.remaining = 0;
+}
+
+/*
+ * Copy out as much data from the internal buffer to done events.
+ * As each done event is filled, send it along its way.
+ */
+static void
+completeio_recv(isc_socket_t *sock)
+{
+ isc_socketevent_t *dev;
+
+ /*
+ * If we are in the process of filling our buffer, we cannot
+ * touch it yet, so don't.
+ */
+ if (sock->pending_recv > 0)
+ return;
+
+ while (sock->recvbuf.remaining > 0 && !ISC_LIST_EMPTY(sock->recv_list)) {
+ dev = ISC_LIST_HEAD(sock->recv_list);
+
+ /*
+ * See if we have sufficient data in our receive buffer
+ * to handle this. If we do, copy out the data.
+ */
+ fill_recv(sock, dev);
+
+ /*
+ * Did we satisfy it?
+ */
+ if (dev->n >= dev->minimum) {
+ dev->result = ISC_R_SUCCESS;
+ send_recvdone_event(sock, &dev);
+ }
+ }
+}
+
+/*
+ * Returns:
+ * DOIO_SUCCESS The operation succeeded. dev->result contains
+ * ISC_R_SUCCESS.
+ *
+ * DOIO_HARD A hard or unexpected I/O error was encountered.
+ * dev->result contains the appropriate error.
+ *
+ * DOIO_SOFT A soft I/O error was encountered. No senddone
+ * event was sent. The operation should be retried.
+ *
+ * No other return values are possible.
+ */
+static int
+completeio_send(isc_socket_t *sock, isc_socketevent_t *dev,
+ struct msghdr *messagehdr, int cc, int send_errno)
+{
+ char strbuf[ISC_STRERRORSIZE];
+
+ if (send_errno != 0) {
+ if (SOFT_ERROR(send_errno))
+ return (DOIO_SOFT);
+
+ return (map_socket_error(sock, send_errno, &dev->result,
+ strbuf, sizeof(strbuf)));
+ }
+
+ /*
+ * If we write less than we expected, update counters, poke.
+ */
+ dev->n += cc;
+ if (cc != messagehdr->msg_totallen)
+ return (DOIO_SOFT);
+
+ /*
+ * Exactly what we wanted to write. We're done with this
+ * entry. Post its completion event.
+ */
+ dev->result = ISC_R_SUCCESS;
+ return (DOIO_SUCCESS);
+}
+
+static int
+startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes,
+ int *send_errno)
+{
+ char *cmsg = NULL;
+ char strbuf[ISC_STRERRORSIZE];
+ IoCompletionInfo *lpo;
+ int status;
+ struct msghdr *mh;
+
+ lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
+ HEAP_ZERO_MEMORY,
+ sizeof(IoCompletionInfo));
+ RUNTIME_CHECK(lpo != NULL);
+ lpo->request_type = SOCKET_SEND;
+ lpo->dev = dev;
+ mh = &lpo->messagehdr;
+ memset(mh, 0, sizeof(struct msghdr));
+ ISC_LIST_INIT(lpo->bufferlist);
+
+ build_msghdr_send(sock, dev, mh, cmsg, sock->iov, lpo);
+
+ *nbytes = internal_sendmsg(sock, lpo, mh, 0, send_errno);
+
+ if (*nbytes <= 0) {
+ /*
+ * I/O has been initiated
+ * completion will be through the completion port
+ */
+ if (PENDING_ERROR(*send_errno)) {
+ status = DOIO_PENDING;
+ goto done;
+ }
+
+ if (SOFT_ERROR(*send_errno)) {
+ status = DOIO_SOFT;
+ goto done;
+ }
+
+ /*
+ * If we got this far then something is wrong
+ */
+ if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) {
+ isc__strerror(*send_errno, strbuf, sizeof(strbuf));
+ socket_log(__LINE__, sock, NULL, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_INTERNALSEND,
+ "startio_send: internal_sendmsg(%d) %d "
+ "bytes, err %d/%s",
+ sock->fd, *nbytes, *send_errno, strbuf);
+ }
+ status = DOIO_HARD;
+ goto done;
+ }
+ dev->result = ISC_R_SUCCESS;
+ status = DOIO_SOFT;
+ done:
+ _set_state(sock, SOCK_DATA);
+ return (status);
+}
+
+static void
+use_min_mtu(isc_socket_t *sock) {
+#ifdef IPV6_USE_MIN_MTU
+ /* use minimum MTU */
+ if (sock->pf == AF_INET6) {
+ int on = 1;
+ (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
+ (void *)&on, sizeof(on));
+ }
+#else
+ UNUSED(sock);
+#endif
+}
+
+static isc_result_t
+allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
+ isc_socket_t **socketp) {
+ isc_socket_t *sock;
+ isc_result_t result;
+
+ sock = isc_mem_get(manager->mctx, sizeof(*sock));
+
+ if (sock == NULL)
+ return (ISC_R_NOMEMORY);
+
+ sock->magic = 0;
+ sock->references = 0;
+
+ sock->manager = manager;
+ sock->type = type;
+ sock->fd = INVALID_SOCKET;
+
+ ISC_LINK_INIT(sock, link);
+
+ /*
+ * Set up list of readers and writers to be initially empty.
+ */
+ ISC_LIST_INIT(sock->recv_list);
+ ISC_LIST_INIT(sock->send_list);
+ ISC_LIST_INIT(sock->accept_list);
+ ISC_LIST_INIT(sock->connect_list);
+ sock->pending_accept = 0;
+ sock->pending_recv = 0;
+ sock->pending_send = 0;
+ sock->pending_iocp = 0;
+ sock->listener = 0;
+ sock->connected = 0;
+ sock->pending_connect = 0;
+ sock->bound = 0;
+ sock->dupped = 0;
+ memset(sock->name, 0, sizeof(sock->name)); // zero the name field
+ _set_state(sock, SOCK_INITIALIZED);
+
+ sock->recvbuf.len = 65536;
+ sock->recvbuf.consume_position = sock->recvbuf.base;
+ sock->recvbuf.remaining = 0;
+ sock->recvbuf.base = isc_mem_get(manager->mctx, sock->recvbuf.len); // max buffer size
+ if (sock->recvbuf.base == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto error;
+ }
+
+ /*
+ * Initialize the lock.
+ */
+ result = isc_mutex_init(&sock->lock);
+ if (result != ISC_R_SUCCESS)
+ goto error;
+
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "allocated");
+
+ sock->magic = SOCKET_MAGIC;
+ *socketp = sock;
+
+ return (ISC_R_SUCCESS);
+
+ error:
+ if (sock->recvbuf.base != NULL)
+ isc_mem_put(manager->mctx, sock->recvbuf.base, sock->recvbuf.len);
+ isc_mem_put(manager->mctx, sock, sizeof(*sock));
+
+ return (result);
+}
+
+/*
+ * Verify that the socket state is consistent.
+ */
+static void
+consistent(isc_socket_t *sock) {
+
+ isc_socketevent_t *dev;
+ isc_socket_newconnev_t *nev;
+ unsigned int count;
+ char *crash_reason;
+ bool crash = false;
+
+ REQUIRE(sock->pending_iocp == sock->pending_recv + sock->pending_send
+ + sock->pending_accept + sock->pending_connect);
+
+ dev = ISC_LIST_HEAD(sock->send_list);
+ count = 0;
+ while (dev != NULL) {
+ count++;
+ dev = ISC_LIST_NEXT(dev, ev_link);
+ }
+ if (count > sock->pending_send) {
+ crash = true;
+ crash_reason = "send_list > sock->pending_send";
+ }
+
+ nev = ISC_LIST_HEAD(sock->accept_list);
+ count = 0;
+ while (nev != NULL) {
+ count++;
+ nev = ISC_LIST_NEXT(nev, ev_link);
+ }
+ if (count > sock->pending_accept) {
+ crash = true;
+ crash_reason = "accept_list > sock->pending_accept";
+ }
+
+ if (crash) {
+ socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_DESTROYING, "SOCKET INCONSISTENT: %s",
+ crash_reason);
+ sock_dump(sock);
+ INSIST(crash == false);
+ }
+}
+
+/*
+ * Maybe free the socket.
+ *
+ * This function will verify tht the socket is no longer in use in any way,
+ * either internally or externally. This is the only place where this
+ * check is to be made; if some bit of code believes that IT is done with
+ * the socket (e.g., some reference counter reaches zero), it should call
+ * this function.
+ *
+ * When calling this function, the socket must be locked, and the manager
+ * must be unlocked.
+ *
+ * When this function returns, *socketp will be NULL. No tricks to try
+ * to hold on to this pointer are allowed.
+ */
+static void
+maybe_free_socket(isc_socket_t **socketp, int lineno) {
+ isc_socket_t *sock = *socketp;
+ *socketp = NULL;
+
+ INSIST(VALID_SOCKET(sock));
+ CONSISTENT(sock);
+
+ if (sock->pending_iocp > 0
+ || sock->pending_recv > 0
+ || sock->pending_send > 0
+ || sock->pending_accept > 0
+ || sock->references > 0
+ || sock->pending_connect == 1
+ || !ISC_LIST_EMPTY(sock->recv_list)
+ || !ISC_LIST_EMPTY(sock->send_list)
+ || !ISC_LIST_EMPTY(sock->accept_list)
+ || !ISC_LIST_EMPTY(sock->connect_list)
+ || sock->fd != INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return;
+ }
+ UNLOCK(&sock->lock);
+
+ free_socket(&sock, lineno);
+}
+
+void
+free_socket(isc_socket_t **sockp, int lineno) {
+ isc_socketmgr_t *manager;
+ isc_socket_t *sock = *sockp;
+ *sockp = NULL;
+
+ /*
+ * Seems we can free the socket after all.
+ */
+ manager = sock->manager;
+ socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat,
+ ISC_MSGSET_SOCKET, ISC_MSG_DESTROYING,
+ "freeing socket line %d fd %d lock %p semaphore %p",
+ lineno, sock->fd, &sock->lock, sock->lock.LockSemaphore);
+
+ sock->magic = 0;
+ DESTROYLOCK(&sock->lock);
+
+ if (sock->recvbuf.base != NULL)
+ isc_mem_put(manager->mctx, sock->recvbuf.base,
+ sock->recvbuf.len);
+
+ LOCK(&manager->lock);
+ if (ISC_LINK_LINKED(sock, link))
+ ISC_LIST_UNLINK(manager->socklist, sock, link);
+ isc_mem_put(manager->mctx, sock, sizeof(*sock));
+
+ if (ISC_LIST_EMPTY(manager->socklist))
+ SIGNAL(&manager->shutdown_ok);
+ UNLOCK(&manager->lock);
+}
+
+/*
+ * Create a new 'type' socket managed by 'manager'. Events
+ * will be posted to 'task' and when dispatched 'action' will be
+ * called with 'arg' as the arg value. The new socket is returned
+ * in 'socketp'.
+ */
+static isc_result_t
+socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+ isc_socket_t **socketp, isc_socket_t *dup_socket)
+{
+ isc_socket_t *sock = NULL;
+ isc_result_t result;
+#if defined(USE_CMSG)
+ int on = 1;
+#endif
+#if defined(SO_RCVBUF)
+ ISC_SOCKADDR_LEN_T optlen;
+ int size;
+#endif
+ int socket_errno;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(socketp != NULL && *socketp == NULL);
+ REQUIRE(type != isc_sockettype_fdwatch);
+
+#ifndef SOCK_RAW
+ if (type == isc_sockettype_raw)
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+
+ result = allocate_socket(manager, type, &sock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ sock->pf = pf;
+ switch (type) {
+ case isc_sockettype_udp:
+ sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock->fd != INVALID_SOCKET) {
+ result = connection_reset_fix(sock->fd);
+ if (result != ISC_R_SUCCESS) {
+ socket_log(__LINE__, sock,
+ NULL, EVENT, NULL, 0, 0,
+ "closed %d %d %d "
+ "con_reset_fix_failed",
+ sock->pending_recv,
+ sock->pending_send,
+ sock->references);
+ closesocket(sock->fd);
+ _set_state(sock, SOCK_CLOSED);
+ sock->fd = INVALID_SOCKET;
+ free_socket(&sock, __LINE__);
+ return (result);
+ }
+ }
+ break;
+ case isc_sockettype_tcp:
+ sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
+ break;
+#ifdef SOCK_RAW
+ case isc_sockettype_raw:
+ sock->fd = socket(pf, SOCK_RAW, 0);
+#ifdef PF_ROUTE
+ if (pf == PF_ROUTE)
+ sock->bound = 1;
+#endif
+ break;
+#endif
+ }
+
+ if (sock->fd == INVALID_SOCKET) {
+ socket_errno = WSAGetLastError();
+ free_socket(&sock, __LINE__);
+
+ switch (socket_errno) {
+ case WSAEMFILE:
+ case WSAENOBUFS:
+ return (ISC_R_NORESOURCES);
+
+ case WSAEPROTONOSUPPORT:
+ case WSAEPFNOSUPPORT:
+ case WSAEAFNOSUPPORT:
+ return (ISC_R_FAMILYNOSUPPORT);
+
+ default:
+ isc__strerror(socket_errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+ }
+
+ result = make_nonblock(sock->fd);
+ if (result != ISC_R_SUCCESS) {
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "closed %d %d %d make_nonblock_failed",
+ sock->pending_recv, sock->pending_send,
+ sock->references);
+ closesocket(sock->fd);
+ sock->fd = INVALID_SOCKET;
+ free_socket(&sock, __LINE__);
+ return (result);
+ }
+
+ /*
+ * Use minimum mtu if possible.
+ */
+ use_min_mtu(sock);
+
+#if defined(USE_CMSG) || defined(SO_RCVBUF)
+ if (type == isc_sockettype_udp) {
+
+#if defined(USE_CMSG)
+#if defined(ISC_PLATFORM_HAVEIPV6)
+#ifdef IPV6_RECVPKTINFO
+ /* 2292bis */
+ if ((pf == AF_INET6)
+ && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
+ (char *)&on, sizeof(on)) < 0)) {
+ isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, IPV6_RECVPKTINFO) "
+ "%s: %s", sock->fd,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ }
+#else
+ /* 2292 */
+ if ((pf == AF_INET6)
+ && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO,
+ (char *)&on, sizeof(on)) < 0)) {
+ isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, IPV6_PKTINFO) %s: %s",
+ sock->fd,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ }
+#endif /* IPV6_RECVPKTINFO */
+#endif /* ISC_PLATFORM_HAVEIPV6 */
+#endif /* defined(USE_CMSG) */
+
+#if defined(SO_RCVBUF)
+ optlen = sizeof(size);
+ if (getsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
+ (char *)&size, &optlen) >= 0 &&
+ size < RCVBUFSIZE) {
+ size = RCVBUFSIZE;
+ (void)setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
+ (char *)&size, sizeof(size));
+ }
+#endif
+
+ }
+#endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */
+
+ _set_state(sock, SOCK_OPEN);
+ sock->references = 1;
+ *socketp = sock;
+
+ iocompletionport_update(sock);
+
+ if (dup_socket) {
+#ifndef ISC_ALLOW_MAPPED
+ isc__socket_ipv6only(sock, true);
+#endif
+
+ if (dup_socket->bound) {
+ isc_sockaddr_t local;
+
+ result = isc__socket_getsockname(dup_socket, &local);
+ if (result != ISC_R_SUCCESS) {
+ isc_socket_close(sock);
+ return (result);
+ }
+ result = isc__socket_bind(sock, &local,
+ ISC_SOCKET_REUSEADDRESS);
+ if (result != ISC_R_SUCCESS) {
+ isc_socket_close(sock);
+ return (result);
+ }
+ }
+ sock->dupped = 1;
+ }
+
+ /*
+ * Note we don't have to lock the socket like we normally would because
+ * there are no external references to it yet.
+ */
+ LOCK(&manager->lock);
+ ISC_LIST_APPEND(manager->socklist, sock, link);
+ InterlockedIncrement(&manager->totalSockets);
+ UNLOCK(&manager->lock);
+
+ socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat,
+ ISC_MSGSET_SOCKET, ISC_MSG_CREATED,
+ "created %u type %u", sock->fd, type);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+ isc_socket_t **socketp)
+{
+ return (socket_create(manager, pf, type, socketp, NULL));
+}
+
+isc_result_t
+isc__socket_dup(isc_socket_t *sock, isc_socket_t **socketp) {
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(socketp != NULL && *socketp == NULL);
+
+ return (socket_create(sock->manager, sock->pf, sock->type,
+ socketp, sock));
+}
+
+isc_result_t
+isc_socket_open(isc_socket_t *sock) {
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(sock->type != isc_sockettype_fdwatch);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+/*
+ * Attach to a socket. Caller must explicitly detach when it is done.
+ */
+void
+isc__socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(socketp != NULL && *socketp == NULL);
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+ sock->references++;
+ UNLOCK(&sock->lock);
+
+ *socketp = sock;
+}
+
+/*
+ * Dereference a socket. If this is the last reference to it, clean things
+ * up by destroying the socket.
+ */
+void
+isc__socket_detach(isc_socket_t **socketp) {
+ isc_socket_t *sock;
+
+ REQUIRE(socketp != NULL);
+ sock = *socketp;
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(sock->type != isc_sockettype_fdwatch);
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+ REQUIRE(sock->references > 0);
+ sock->references--;
+
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "detach_socket %d %d %d",
+ sock->pending_recv, sock->pending_send,
+ sock->references);
+
+ if (sock->references == 0 && sock->fd != INVALID_SOCKET) {
+ closesocket(sock->fd);
+ sock->fd = INVALID_SOCKET;
+ _set_state(sock, SOCK_CLOSED);
+ }
+
+ maybe_free_socket(&sock, __LINE__);
+
+ *socketp = NULL;
+}
+
+isc_result_t
+isc_socket_close(isc_socket_t *sock) {
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(sock->type != isc_sockettype_fdwatch);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+/*
+ * Dequeue an item off the given socket's read queue, set the result code
+ * in the done event to the one provided, and send it to the task it was
+ * destined for.
+ *
+ * If the event to be sent is on a list, remove it before sending. If
+ * asked to, send and detach from the task as well.
+ *
+ * Caller must have the socket locked if the event is attached to the socket.
+ */
+static void
+send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
+ isc_task_t *task;
+
+ task = (*dev)->ev_sender;
+ (*dev)->ev_sender = sock;
+
+ if (ISC_LINK_LINKED(*dev, ev_link))
+ ISC_LIST_DEQUEUE(sock->recv_list, *dev, ev_link);
+
+ if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)
+ == ISC_SOCKEVENTATTR_ATTACHED)
+ isc_task_sendanddetach(&task, (isc_event_t **)dev);
+ else
+ isc_task_send(task, (isc_event_t **)dev);
+
+ CONSISTENT(sock);
+}
+
+/*
+ * See comments for send_recvdone_event() above.
+ */
+static void
+send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
+ isc_task_t *task;
+
+ INSIST(dev != NULL && *dev != NULL);
+
+ task = (*dev)->ev_sender;
+ (*dev)->ev_sender = sock;
+
+ if (ISC_LINK_LINKED(*dev, ev_link))
+ ISC_LIST_DEQUEUE(sock->send_list, *dev, ev_link);
+
+ if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)
+ == ISC_SOCKEVENTATTR_ATTACHED)
+ isc_task_sendanddetach(&task, (isc_event_t **)dev);
+ else
+ isc_task_send(task, (isc_event_t **)dev);
+
+ CONSISTENT(sock);
+}
+
+/*
+ * See comments for send_recvdone_event() above.
+ */
+static void
+send_acceptdone_event(isc_socket_t *sock, isc_socket_newconnev_t **adev) {
+ isc_task_t *task;
+
+ INSIST(adev != NULL && *adev != NULL);
+
+ task = (*adev)->ev_sender;
+ (*adev)->ev_sender = sock;
+
+ if (ISC_LINK_LINKED(*adev, ev_link))
+ ISC_LIST_DEQUEUE(sock->accept_list, *adev, ev_link);
+
+ isc_task_sendanddetach(&task, (isc_event_t **)adev);
+
+ CONSISTENT(sock);
+}
+
+/*
+ * See comments for send_recvdone_event() above.
+ */
+static void
+send_connectdone_event(isc_socket_t *sock, isc_socket_connev_t **cdev) {
+ isc_task_t *task;
+
+ INSIST(cdev != NULL && *cdev != NULL);
+
+ task = (*cdev)->ev_sender;
+ (*cdev)->ev_sender = sock;
+
+ if (ISC_LINK_LINKED(*cdev, ev_link))
+ ISC_LIST_DEQUEUE(sock->connect_list, *cdev, ev_link);
+
+ isc_task_sendanddetach(&task, (isc_event_t **)cdev);
+
+ CONSISTENT(sock);
+}
+
+/*
+ * On entry to this function, the event delivered is the internal
+ * readable event, and the first item on the accept_list should be
+ * the done event we want to send. If the list is empty, this is a no-op,
+ * so just close the new connection, unlock, and return.
+ *
+ * Note the socket is locked before entering here
+ */
+static void
+internal_accept(isc_socket_t *sock, IoCompletionInfo *lpo, int accept_errno) {
+ isc_socket_newconnev_t *adev;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_socket_t *nsock;
+ struct sockaddr *localaddr;
+ int localaddr_len = sizeof(*localaddr);
+ struct sockaddr *remoteaddr;
+ int remoteaddr_len = sizeof(*remoteaddr);
+
+ INSIST(VALID_SOCKET(sock));
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ socket_log(__LINE__, sock, NULL, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+ "internal_accept called");
+
+ INSIST(sock->listener);
+
+ INSIST(sock->pending_iocp > 0);
+ sock->pending_iocp--;
+ INSIST(sock->pending_accept > 0);
+ sock->pending_accept--;
+
+ adev = lpo->adev;
+
+ /*
+ * If the event is no longer in the list we can just return.
+ */
+ if (!acceptdone_is_active(sock, adev))
+ goto done;
+
+ nsock = adev->newsocket;
+
+ /*
+ * Pull off the done event.
+ */
+ ISC_LIST_UNLINK(sock->accept_list, adev, ev_link);
+
+ /*
+ * Extract the addresses from the socket, copy them into the structure,
+ * and return the new socket.
+ */
+ ISCGetAcceptExSockaddrs(lpo->acceptbuffer, 0,
+ sizeof(SOCKADDR_STORAGE) + 16, sizeof(SOCKADDR_STORAGE) + 16,
+ (LPSOCKADDR *)&localaddr, &localaddr_len,
+ (LPSOCKADDR *)&remoteaddr, &remoteaddr_len);
+ memmove(&adev->address.type, remoteaddr, remoteaddr_len);
+ adev->address.length = remoteaddr_len;
+ nsock->address = adev->address;
+ nsock->pf = adev->address.type.sa.sa_family;
+
+ socket_log(__LINE__, nsock, &nsock->address, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+ "internal_accept parent %p", sock);
+
+ result = make_nonblock(adev->newsocket->fd);
+ INSIST(result == ISC_R_SUCCESS);
+
+ /*
+ * Use minimum mtu if possible.
+ */
+ use_min_mtu(adev->newsocket);
+
+ INSIST(setsockopt(nsock->fd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
+ (char *)&sock->fd, sizeof(sock->fd)) == 0);
+
+ /*
+ * Hook it up into the manager.
+ */
+ nsock->bound = 1;
+ nsock->connected = 1;
+ _set_state(nsock, SOCK_OPEN);
+
+ LOCK(&nsock->manager->lock);
+ ISC_LIST_APPEND(nsock->manager->socklist, nsock, link);
+ InterlockedIncrement(&nsock->manager->totalSockets);
+ UNLOCK(&nsock->manager->lock);
+
+ socket_log(__LINE__, sock, &nsock->address, CREATION,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
+ "accepted_connection new_socket %p fd %d",
+ nsock, nsock->fd);
+
+ adev->result = result;
+ send_acceptdone_event(sock, &adev);
+
+done:
+ CONSISTENT(sock);
+ UNLOCK(&sock->lock);
+
+ HeapFree(hHeapHandle, 0, lpo->acceptbuffer);
+ lpo->acceptbuffer = NULL;
+}
+
+/*
+ * Called when a socket with a pending connect() finishes.
+ * Note that the socket is locked before entering.
+ */
+static void
+internal_connect(isc_socket_t *sock, IoCompletionInfo *lpo, int connect_errno) {
+ isc_socket_connev_t *cdev;
+ isc_result_t result;
+ char strbuf[ISC_STRERRORSIZE];
+
+ INSIST(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+
+ INSIST(sock->pending_iocp > 0);
+ sock->pending_iocp--;
+ INSIST(sock->pending_connect == 1);
+ sock->pending_connect = 0;
+
+ /*
+ * If the event is no longer in the list we can just close and return.
+ */
+ cdev = lpo->cdev;
+ if (!connectdone_is_active(sock, cdev)) {
+ sock->pending_connect = 0;
+ if (sock->fd != INVALID_SOCKET) {
+ closesocket(sock->fd);
+ sock->fd = INVALID_SOCKET;
+ _set_state(sock, SOCK_CLOSED);
+ }
+ CONSISTENT(sock);
+ UNLOCK(&sock->lock);
+ return;
+ }
+
+ /*
+ * Check possible Windows network event error status here.
+ */
+ if (connect_errno != 0) {
+ /*
+ * If the error is SOFT, just try again on this
+ * fd and pretend nothing strange happened.
+ */
+ if (SOFT_ERROR(connect_errno) ||
+ connect_errno == WSAEINPROGRESS) {
+ sock->pending_connect = 1;
+ CONSISTENT(sock);
+ UNLOCK(&sock->lock);
+ return;
+ }
+
+ /*
+ * Translate other errors into ISC_R_* flavors.
+ */
+ switch (connect_errno) {
+#define ERROR_MATCH(a, b) case a: result = b; break;
+ ERROR_MATCH(WSAEACCES, ISC_R_NOPERM);
+ ERROR_MATCH(WSAEADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
+ ERROR_MATCH(WSAEAFNOSUPPORT, ISC_R_ADDRNOTAVAIL);
+ ERROR_MATCH(WSAECONNREFUSED, ISC_R_CONNREFUSED);
+ ERROR_MATCH(WSAEHOSTUNREACH, ISC_R_HOSTUNREACH);
+ ERROR_MATCH(WSAEHOSTDOWN, ISC_R_HOSTDOWN);
+ ERROR_MATCH(WSAENETUNREACH, ISC_R_NETUNREACH);
+ ERROR_MATCH(WSAENETDOWN, ISC_R_NETDOWN);
+ ERROR_MATCH(WSAENOBUFS, ISC_R_NORESOURCES);
+ ERROR_MATCH(WSAECONNRESET, ISC_R_CONNECTIONRESET);
+ ERROR_MATCH(WSAECONNABORTED, ISC_R_CONNECTIONRESET);
+ ERROR_MATCH(WSAETIMEDOUT, ISC_R_TIMEDOUT);
+#undef ERROR_MATCH
+ default:
+ result = ISC_R_UNEXPECTED;
+ isc__strerror(connect_errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "internal_connect: connect() %s",
+ strbuf);
+ }
+ } else {
+ INSIST(setsockopt(sock->fd, SOL_SOCKET,
+ SO_UPDATE_CONNECT_CONTEXT, NULL, 0) == 0);
+ result = ISC_R_SUCCESS;
+ sock->connected = 1;
+ socket_log(__LINE__, sock, &sock->address, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
+ "internal_connect: success");
+ }
+
+ do {
+ cdev->result = result;
+ send_connectdone_event(sock, &cdev);
+ cdev = ISC_LIST_HEAD(sock->connect_list);
+ } while (cdev != NULL);
+
+ UNLOCK(&sock->lock);
+}
+
+/*
+ * Loop through the socket, returning ISC_R_EOF for each done event pending.
+ */
+static void
+send_recvdone_abort(isc_socket_t *sock, isc_result_t result) {
+ isc_socketevent_t *dev;
+
+ while (!ISC_LIST_EMPTY(sock->recv_list)) {
+ dev = ISC_LIST_HEAD(sock->recv_list);
+ dev->result = result;
+ send_recvdone_event(sock, &dev);
+ }
+}
+
+/*
+ * Loop through the socket, returning result for each done event pending.
+ */
+static void
+send_connectdone_abort(isc_socket_t *sock, isc_result_t result) {
+ isc_socket_connev_t *dev;
+
+ while (!ISC_LIST_EMPTY(sock->connect_list)) {
+ dev = ISC_LIST_HEAD(sock->connect_list);
+ dev->result = result;
+ send_connectdone_event(sock, &dev);
+ }
+}
+
+/*
+ * Take the data we received in our private buffer, and if any recv() calls on
+ * our list are satisfied, send the corresponding done event.
+ *
+ * If we need more data (there are still items on the recv_list after we consume all
+ * our data) then arrange for another system recv() call to fill our buffers.
+ */
+static void
+internal_recv(isc_socket_t *sock, int nbytes)
+{
+ INSIST(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ socket_log(__LINE__, sock, NULL, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV,
+ "internal_recv: %d bytes received", nbytes);
+
+ /*
+ * If we got here, the I/O operation succeeded. However, we might still have removed this
+ * event from our notification list (or never placed it on it due to immediate completion.)
+ * Handle the reference counting here, and handle the cancellation event just after.
+ */
+ INSIST(sock->pending_iocp > 0);
+ sock->pending_iocp--;
+ INSIST(sock->pending_recv > 0);
+ sock->pending_recv--;
+
+ /*
+ * The only way we could have gotten here is that our I/O has successfully completed.
+ * Update our pointers, and move on. The only odd case here is that we might not
+ * have received enough data on a TCP stream to satisfy the minimum requirements. If
+ * this is the case, we will re-issue the recv() call for what we need.
+ *
+ * We do check for a recv() of 0 bytes on a TCP stream. This means the remote end
+ * has closed.
+ */
+ if (nbytes == 0 && sock->type == isc_sockettype_tcp) {
+ send_recvdone_abort(sock, ISC_R_EOF);
+ maybe_free_socket(&sock, __LINE__);
+ return;
+ }
+ sock->recvbuf.remaining = nbytes;
+ sock->recvbuf.consume_position = sock->recvbuf.base;
+ completeio_recv(sock);
+
+ /*
+ * If there are more receivers waiting for data, queue another receive
+ * here.
+ */
+ queue_receive_request(sock);
+
+ /*
+ * Unlock and/or destroy if we are the last thing this socket has left to do.
+ */
+ maybe_free_socket(&sock, __LINE__);
+}
+
+static void
+internal_send(isc_socket_t *sock, isc_socketevent_t *dev,
+ struct msghdr *messagehdr, int nbytes, int send_errno, IoCompletionInfo *lpo)
+{
+ buflist_t *buffer;
+
+ /*
+ * Find out what socket this is and lock it.
+ */
+ INSIST(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ socket_log(__LINE__, sock, NULL, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND,
+ "internal_send: task got socket event %p", dev);
+
+ buffer = ISC_LIST_HEAD(lpo->bufferlist);
+ while (buffer != NULL) {
+ ISC_LIST_DEQUEUE(lpo->bufferlist, buffer, link);
+
+ socket_log(__LINE__, sock, NULL, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+ "free_buffer %p %p", buffer, buffer->buf);
+
+ HeapFree(hHeapHandle, 0, buffer->buf);
+ HeapFree(hHeapHandle, 0, buffer);
+ buffer = ISC_LIST_HEAD(lpo->bufferlist);
+ }
+
+ INSIST(sock->pending_iocp > 0);
+ sock->pending_iocp--;
+ INSIST(sock->pending_send > 0);
+ sock->pending_send--;
+
+ /* If the event is no longer in the list we can just return */
+ if (!senddone_is_active(sock, dev))
+ goto done;
+
+ /*
+ * Set the error code and send things on its way.
+ */
+ switch (completeio_send(sock, dev, messagehdr, nbytes, send_errno)) {
+ case DOIO_SOFT:
+ break;
+ case DOIO_HARD:
+ case DOIO_SUCCESS:
+ send_senddone_event(sock, &dev);
+ break;
+ }
+
+ done:
+ maybe_free_socket(&sock, __LINE__);
+}
+
+/*
+ * These return if the done event passed in is on the list.
+ * Using these ensures we will not double-send an event.
+ */
+static bool
+senddone_is_active(isc_socket_t *sock, isc_socketevent_t *dev)
+{
+ isc_socketevent_t *ldev;
+
+ ldev = ISC_LIST_HEAD(sock->send_list);
+ while (ldev != NULL && ldev != dev)
+ ldev = ISC_LIST_NEXT(ldev, ev_link);
+
+ return (ldev == NULL ? false : true);
+}
+
+static bool
+acceptdone_is_active(isc_socket_t *sock, isc_socket_newconnev_t *dev)
+{
+ isc_socket_newconnev_t *ldev;
+
+ ldev = ISC_LIST_HEAD(sock->accept_list);
+ while (ldev != NULL && ldev != dev)
+ ldev = ISC_LIST_NEXT(ldev, ev_link);
+
+ return (ldev == NULL ? false : true);
+}
+
+static bool
+connectdone_is_active(isc_socket_t *sock, isc_socket_connev_t *dev)
+{
+ isc_socket_connev_t *cdev;
+
+ cdev = ISC_LIST_HEAD(sock->connect_list);
+ while (cdev != NULL && cdev != dev)
+ cdev = ISC_LIST_NEXT(cdev, ev_link);
+
+ return (cdev == NULL ? false : true);
+}
+
+//
+// The Windows network stack seems to have two very distinct paths depending
+// on what is installed. Specifically, if something is looking at network
+// connections (like an anti-virus or anti-malware application, such as
+// McAfee products) Windows may return additional error conditions which
+// were not previously returned.
+//
+// One specific one is when a TCP SYN scan is used. In this situation,
+// Windows responds with the SYN-ACK, but the scanner never responds with
+// the 3rd packet, the ACK. Windows consiers this a partially open connection.
+// Most Unix networking stacks, and Windows without McAfee installed, will
+// not return this to the caller. However, with this product installed,
+// Windows returns this as a failed status on the Accept() call. Here, we
+// will just re-issue the ISCAcceptEx() call as if nothing had happened.
+//
+// This code should only be called when the listening socket has received
+// such an error. Additionally, the "parent" socket must be locked.
+// Additionally, the lpo argument is re-used here, and must not be freed
+// by the caller.
+//
+static isc_result_t
+restart_accept(isc_socket_t *parent, IoCompletionInfo *lpo)
+{
+ isc_socket_t *nsock = lpo->adev->newsocket;
+ SOCKET new_fd;
+
+ /*
+ * AcceptEx() requires we pass in a socket. Note that we carefully
+ * do not close the previous socket in case of an error message returned by
+ * our new socket() call. If we return an error here, our caller will
+ * clean up.
+ */
+ new_fd = socket(parent->pf, SOCK_STREAM, IPPROTO_TCP);
+ if (nsock->fd == INVALID_SOCKET) {
+ return (ISC_R_FAILURE); // parent will ask windows for error message
+ }
+ closesocket(nsock->fd);
+ nsock->fd = new_fd;
+
+ memset(&lpo->overlapped, 0, sizeof(lpo->overlapped));
+
+ ISCAcceptEx(parent->fd,
+ nsock->fd, /* Accepted Socket */
+ lpo->acceptbuffer, /* Buffer for initial Recv */
+ 0, /* Length of Buffer */
+ sizeof(SOCKADDR_STORAGE) + 16, /* Local address length + 16 */
+ sizeof(SOCKADDR_STORAGE) + 16, /* Remote address lengh + 16 */
+ (LPDWORD)&lpo->received_bytes, /* Bytes Recved */
+ (LPOVERLAPPED)lpo /* Overlapped structure */
+ );
+
+ InterlockedDecrement(&nsock->manager->iocp_total);
+ iocompletionport_update(nsock);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * This is the I/O Completion Port Worker Function. It loops forever
+ * waiting for I/O to complete and then forwards them for further
+ * processing. There are a number of these in separate threads.
+ */
+static isc_threadresult_t WINAPI
+SocketIoThread(LPVOID ThreadContext) {
+ isc_socketmgr_t *manager = ThreadContext;
+ BOOL bSuccess = FALSE;
+ DWORD nbytes;
+ IoCompletionInfo *lpo = NULL;
+ isc_socket_t *sock = NULL;
+ int request;
+ struct msghdr *messagehdr = NULL;
+ int errval;
+ char strbuf[ISC_STRERRORSIZE];
+ int errstatus;
+
+ REQUIRE(VALID_MANAGER(manager));
+
+ /*
+ * Set the thread priority high enough so I/O will
+ * preempt normal recv packet processing, but not
+ * higher than the timer sync thread.
+ */
+ if (!SetThreadPriority(GetCurrentThread(),
+ THREAD_PRIORITY_ABOVE_NORMAL)) {
+ errval = GetLastError();
+ isc__strerror(errval, strbuf, sizeof(strbuf));
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_FAILED,
+ "Can't set thread priority: %s"),
+ strbuf);
+ }
+
+ /*
+ * Loop forever waiting on I/O Completions and then processing them
+ */
+ while (TRUE) {
+ wait_again:
+ bSuccess = GetQueuedCompletionStatus(manager->hIoCompletionPort,
+ &nbytes,
+ (PULONG_PTR)&sock,
+ (LPWSAOVERLAPPED *)&lpo,
+ INFINITE);
+ if (lpo == NULL) /* Received request to exit */
+ break;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ request = lpo->request_type;
+
+ if (!bSuccess)
+ errstatus = GetLastError();
+ else
+ errstatus = 0;
+ if (!bSuccess && errstatus != ERROR_MORE_DATA) {
+ isc_result_t isc_result;
+
+ /*
+ * Did the I/O operation complete?
+ */
+ isc_result = isc__errno2result(errstatus);
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+ switch (request) {
+ case SOCKET_RECV:
+ INSIST(sock->pending_iocp > 0);
+ sock->pending_iocp--;
+ INSIST(sock->pending_recv > 0);
+ sock->pending_recv--;
+ if (!sock->connected &&
+ ((errstatus == ERROR_HOST_UNREACHABLE) ||
+ (errstatus == WSAENETRESET) ||
+ (errstatus == WSAECONNRESET))) {
+ /* ignore soft errors */
+ queue_receive_request(sock);
+ break;
+ }
+ send_recvdone_abort(sock, isc_result);
+ if (isc_result == ISC_R_UNEXPECTED) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "SOCKET_RECV: Windows error code: %d, returning ISC error %d",
+ errstatus, isc_result);
+ }
+ break;
+
+ case SOCKET_SEND:
+ INSIST(sock->pending_iocp > 0);
+ sock->pending_iocp--;
+ INSIST(sock->pending_send > 0);
+ sock->pending_send--;
+ if (senddone_is_active(sock, lpo->dev)) {
+ lpo->dev->result = isc_result;
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "canceled_send");
+ send_senddone_event(sock, &lpo->dev);
+ }
+ break;
+
+ case SOCKET_ACCEPT:
+ INSIST(sock->pending_iocp > 0);
+ INSIST(sock->pending_accept > 0);
+
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "Accept: errstatus=%d isc_result=%d", errstatus, isc_result);
+
+ if (acceptdone_is_active(sock, lpo->adev)) {
+ if (restart_accept(sock, lpo) == ISC_R_SUCCESS) {
+ UNLOCK(&sock->lock);
+ goto wait_again;
+ } else {
+ errstatus = GetLastError();
+ isc_result = isc__errno2result(errstatus);
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "restart_accept() failed: errstatus=%d isc_result=%d",
+ errstatus, isc_result);
+ }
+ }
+
+ sock->pending_iocp--;
+ sock->pending_accept--;
+ if (acceptdone_is_active(sock, lpo->adev)) {
+ closesocket(lpo->adev->newsocket->fd);
+ lpo->adev->newsocket->fd = INVALID_SOCKET;
+ lpo->adev->newsocket->references--;
+ free_socket(&lpo->adev->newsocket, __LINE__);
+ lpo->adev->result = isc_result;
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "canceled_accept");
+ send_acceptdone_event(sock, &lpo->adev);
+ }
+ break;
+
+ case SOCKET_CONNECT:
+ INSIST(sock->pending_iocp > 0);
+ sock->pending_iocp--;
+ INSIST(sock->pending_connect == 1);
+ sock->pending_connect = 0;
+ if (connectdone_is_active(sock, lpo->cdev)) {
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "canceled_connect");
+ send_connectdone_abort(sock, isc_result);
+ }
+ break;
+ }
+ maybe_free_socket(&sock, __LINE__);
+
+ if (lpo != NULL)
+ HeapFree(hHeapHandle, 0, lpo);
+ continue;
+ }
+
+ messagehdr = &lpo->messagehdr;
+
+ switch (request) {
+ case SOCKET_RECV:
+ internal_recv(sock, nbytes);
+ break;
+ case SOCKET_SEND:
+ internal_send(sock, lpo->dev, messagehdr, nbytes, errstatus, lpo);
+ break;
+ case SOCKET_ACCEPT:
+ internal_accept(sock, lpo, errstatus);
+ break;
+ case SOCKET_CONNECT:
+ internal_connect(sock, lpo, errstatus);
+ break;
+ }
+
+ if (lpo != NULL)
+ HeapFree(hHeapHandle, 0, lpo);
+ }
+
+ /*
+ * Exit Completion Port Thread
+ */
+ manager_log(manager, TRACE,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_EXITING, "SocketIoThread exiting"));
+ return ((isc_threadresult_t)0);
+}
+
+/*
+ * Create a new socket manager.
+ */
+isc_result_t
+isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
+ return (isc_socketmgr_create2(mctx, managerp, 0));
+}
+
+isc_result_t
+isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
+ unsigned int maxsocks)
+{
+ isc_socketmgr_t *manager;
+ isc_result_t result;
+
+ REQUIRE(managerp != NULL && *managerp == NULL);
+
+ if (maxsocks != 0)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ manager = isc_mem_get(mctx, sizeof(*manager));
+ if (manager == NULL)
+ return (ISC_R_NOMEMORY);
+
+ InitSockets();
+
+ manager->magic = SOCKET_MANAGER_MAGIC;
+ manager->mctx = NULL;
+ manager->stats = NULL;
+ ISC_LIST_INIT(manager->socklist);
+ result = isc_mutex_init(&manager->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, manager, sizeof(*manager));
+ return (result);
+ }
+ if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) {
+ DESTROYLOCK(&manager->lock);
+ isc_mem_put(mctx, manager, sizeof(*manager));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_condition_init() %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ return (ISC_R_UNEXPECTED);
+ }
+
+ isc_mem_attach(mctx, &manager->mctx);
+
+ iocompletionport_init(manager); /* Create the Completion Ports */
+
+ manager->bShutdown = false;
+ manager->totalSockets = 0;
+ manager->iocp_total = 0;
+
+ *managerp = manager;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) {
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(nsockp != NULL);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+void
+isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) {
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(ISC_LIST_EMPTY(manager->socklist));
+ REQUIRE(manager->stats == NULL);
+ REQUIRE(isc_stats_ncounters(stats) == isc_sockstatscounter_max);
+
+ isc_stats_attach(stats, &manager->stats);
+}
+
+void
+isc__socketmgr_destroy(isc_socketmgr_t **managerp) {
+ isc_socketmgr_t *manager;
+ int i;
+ isc_mem_t *mctx;
+
+ /*
+ * Destroy a socket manager.
+ */
+
+ REQUIRE(managerp != NULL);
+ manager = *managerp;
+ REQUIRE(VALID_MANAGER(manager));
+
+ LOCK(&manager->lock);
+
+ /*
+ * Wait for all sockets to be destroyed.
+ */
+ while (!ISC_LIST_EMPTY(manager->socklist)) {
+ manager_log(manager, CREATION,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_SOCKETSREMAIN,
+ "sockets exist"));
+ WAIT(&manager->shutdown_ok, &manager->lock);
+ }
+
+ UNLOCK(&manager->lock);
+
+ /*
+ * Here, we need to had some wait code for the completion port
+ * thread.
+ */
+ signal_iocompletionport_exit(manager);
+ manager->bShutdown = true;
+
+ /*
+ * Wait for threads to exit.
+ */
+ for (i = 0; i < manager->maxIOCPThreads; i++) {
+ if (isc_thread_join((isc_thread_t) manager->hIOCPThreads[i],
+ NULL) != ISC_R_SUCCESS)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_thread_join() for Completion Port %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ }
+ /*
+ * Clean up.
+ */
+
+ CloseHandle(manager->hIoCompletionPort);
+
+ (void)isc_condition_destroy(&manager->shutdown_ok);
+
+ DESTROYLOCK(&manager->lock);
+ if (manager->stats != NULL)
+ isc_stats_detach(&manager->stats);
+ manager->magic = 0;
+ mctx= manager->mctx;
+ isc_mem_put(mctx, manager, sizeof(*manager));
+
+ isc_mem_detach(&mctx);
+
+ *managerp = NULL;
+}
+
+static void
+queue_receive_event(isc_socket_t *sock, isc_task_t *task, isc_socketevent_t *dev)
+{
+ isc_task_t *ntask = NULL;
+
+ isc_task_attach(task, &ntask);
+ dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
+
+ /*
+ * Enqueue the request.
+ */
+ INSIST(!ISC_LINK_LINKED(dev, ev_link));
+ ISC_LIST_ENQUEUE(sock->recv_list, dev, ev_link);
+
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "queue_receive_event: event %p -> task %p",
+ dev, ntask);
+}
+
+/*
+ * Check the pending receive queue, and if we have data pending, give it to this
+ * caller. If we have none, queue an I/O request. If this caller is not the first
+ * on the list, then we will just queue this event and return.
+ *
+ * Caller must have the socket locked.
+ */
+static isc_result_t
+socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
+ unsigned int flags)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+
+ dev->ev_sender = task;
+
+ if (sock->fd == INVALID_SOCKET)
+ return (ISC_R_EOF);
+
+ /*
+ * Queue our event on the list of things to do. Call our function to
+ * attempt to fill buffers as much as possible, and return done events.
+ * We are going to lie about our handling of the ISC_SOCKFLAG_IMMEDIATE
+ * here and tell our caller that we could not satisfy it immediately.
+ */
+ queue_receive_event(sock, task, dev);
+ if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
+ result = ISC_R_INPROGRESS;
+
+ completeio_recv(sock);
+
+ /*
+ * If there are more receivers waiting for data, queue another receive
+ * here. If the
+ */
+ queue_receive_request(sock);
+
+ return (result);
+}
+
+isc_result_t
+isc__socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+ unsigned int minimum, isc_task_t *task,
+ isc_taskaction_t action, void *arg)
+{
+ isc_socketevent_t *dev;
+ isc_socketmgr_t *manager;
+ unsigned int iocount;
+ isc_buffer_t *buffer;
+ isc_result_t ret;
+
+ REQUIRE(VALID_SOCKET(sock));
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * Make sure that the socket is not closed. XXXMLG change error here?
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ REQUIRE(buflist != NULL);
+ REQUIRE(!ISC_LIST_EMPTY(*buflist));
+ REQUIRE(task != NULL);
+ REQUIRE(action != NULL);
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+
+ iocount = isc_bufferlist_availablecount(buflist);
+ REQUIRE(iocount > 0);
+
+ INSIST(sock->bound);
+
+ dev = allocate_socketevent(manager->mctx, sock,
+ ISC_SOCKEVENT_RECVDONE, action, arg);
+ if (dev == NULL) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_NOMEMORY);
+ }
+
+ /*
+ * UDP sockets are always partial read
+ */
+ if (sock->type == isc_sockettype_udp)
+ dev->minimum = 1;
+ else {
+ if (minimum == 0)
+ dev->minimum = iocount;
+ else
+ dev->minimum = minimum;
+ }
+
+ /*
+ * Move each buffer from the passed in list to our internal one.
+ */
+ buffer = ISC_LIST_HEAD(*buflist);
+ while (buffer != NULL) {
+ ISC_LIST_DEQUEUE(*buflist, buffer, link);
+ ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link);
+ buffer = ISC_LIST_HEAD(*buflist);
+ }
+
+ ret = socket_recv(sock, dev, task, 0);
+
+ UNLOCK(&sock->lock);
+ return (ret);
+}
+
+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_socketevent_t *dev;
+ isc_socketmgr_t *manager;
+ isc_result_t ret;
+
+ REQUIRE(VALID_SOCKET(sock));
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+ REQUIRE(action != NULL);
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+
+ INSIST(sock->bound);
+
+ dev = allocate_socketevent(manager->mctx, sock,
+ ISC_SOCKEVENT_RECVDONE, action, arg);
+ if (dev == NULL) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_NOMEMORY);
+ }
+
+ ret = isc_socket_recv2(sock, region, minimum, task, dev, 0);
+ UNLOCK(&sock->lock);
+ return (ret);
+}
+
+isc_result_t
+isc__socket_recv2(isc_socket_t *sock, isc_region_t *region,
+ unsigned int minimum, isc_task_t *task,
+ isc_socketevent_t *event, unsigned int flags)
+{
+ isc_result_t ret;
+
+ REQUIRE(VALID_SOCKET(sock));
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ event->result = ISC_R_UNEXPECTED;
+ event->ev_sender = sock;
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ ISC_LIST_INIT(event->bufferlist);
+ event->region = *region;
+ event->n = 0;
+ event->offset = 0;
+ event->attributes = 0;
+
+ /*
+ * UDP sockets are always partial read.
+ */
+ if (sock->type == isc_sockettype_udp)
+ event->minimum = 1;
+ else {
+ if (minimum == 0)
+ event->minimum = region->length;
+ else
+ event->minimum = minimum;
+ }
+
+ ret = socket_recv(sock, event, task, flags);
+ UNLOCK(&sock->lock);
+ return (ret);
+}
+
+/*
+ * Caller must have the socket locked.
+ */
+static isc_result_t
+socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+ unsigned int flags)
+{
+ int io_state;
+ int send_errno = 0;
+ int cc = 0;
+ isc_task_t *ntask = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ dev->ev_sender = task;
+
+ set_dev_address(address, sock, dev);
+ if (pktinfo != NULL) {
+ socket_log(__LINE__, sock, NULL, TRACE, isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_PKTINFOPROVIDED,
+ "pktinfo structure provided, ifindex %u (set to 0)",
+ pktinfo->ipi6_ifindex);
+
+ dev->attributes |= ISC_SOCKEVENTATTR_PKTINFO;
+ dev->pktinfo = *pktinfo;
+ /*
+ * Set the pktinfo index to 0 here, to let the kernel decide
+ * what interface it should send on.
+ */
+ dev->pktinfo.ipi6_ifindex = 0;
+ }
+
+ io_state = startio_send(sock, dev, &cc, &send_errno);
+ switch (io_state) {
+ case DOIO_PENDING: /* I/O started. Enqueue completion event. */
+ case DOIO_SOFT:
+ /*
+ * We couldn't send all or part of the request right now, so
+ * queue it unless ISC_SOCKFLAG_NORETRY is set.
+ */
+ if ((flags & ISC_SOCKFLAG_NORETRY) == 0 ||
+ io_state == DOIO_PENDING) {
+ isc_task_attach(task, &ntask);
+ dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
+
+ /*
+ * Enqueue the request.
+ */
+ INSIST(!ISC_LINK_LINKED(dev, ev_link));
+ ISC_LIST_ENQUEUE(sock->send_list, dev, ev_link);
+
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "socket_send: event %p -> task %p",
+ dev, ntask);
+
+ if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
+ result = ISC_R_INPROGRESS;
+ break;
+ }
+
+ case DOIO_SUCCESS:
+ break;
+ }
+
+ return (result);
+}
+
+isc_result_t
+isc__socket_send(isc_socket_t *sock, isc_region_t *region,
+ isc_task_t *task, isc_taskaction_t action, void *arg)
+{
+ /*
+ * REQUIRE() checking is performed in isc_socket_sendto().
+ */
+ return (isc_socket_sendto(sock, region, task, action, arg, NULL,
+ NULL));
+}
+
+isc_result_t
+isc__socket_sendto(isc_socket_t *sock, isc_region_t *region,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+{
+ isc_socketevent_t *dev;
+ isc_socketmgr_t *manager;
+ isc_result_t ret;
+
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(sock->type != isc_sockettype_fdwatch);
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+ REQUIRE(region != NULL);
+ REQUIRE(task != NULL);
+ REQUIRE(action != NULL);
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+
+ INSIST(sock->bound);
+
+ dev = allocate_socketevent(manager->mctx, sock,
+ ISC_SOCKEVENT_SENDDONE, action, arg);
+ if (dev == NULL) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_NOMEMORY);
+ }
+ dev->region = *region;
+
+ ret = socket_send(sock, dev, task, address, pktinfo, 0);
+ UNLOCK(&sock->lock);
+ return (ret);
+}
+
+isc_result_t
+isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist,
+ isc_task_t *task, isc_taskaction_t action, void *arg)
+{
+ return (isc_socket_sendtov2(sock, buflist, task, action, arg, NULL,
+ NULL, 0));
+}
+
+isc_result_t
+isc__socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+{
+ return (isc_socket_sendtov2(sock, buflist, task, action, arg, address,
+ pktinfo, 0));
+}
+
+isc_result_t
+isc__socket_sendtov2(isc_socket_t *sock, isc_bufferlist_t *buflist,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+ unsigned int flags)
+{
+ isc_socketevent_t *dev;
+ isc_socketmgr_t *manager;
+ unsigned int iocount;
+ isc_buffer_t *buffer;
+ isc_result_t ret;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+ REQUIRE(buflist != NULL);
+ REQUIRE(!ISC_LIST_EMPTY(*buflist));
+ REQUIRE(task != NULL);
+ REQUIRE(action != NULL);
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+
+ iocount = isc_bufferlist_usedcount(buflist);
+ REQUIRE(iocount > 0);
+
+ dev = allocate_socketevent(manager->mctx, sock,
+ ISC_SOCKEVENT_SENDDONE, action, arg);
+ if (dev == NULL) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_NOMEMORY);
+ }
+
+ /*
+ * Move each buffer from the passed in list to our internal one.
+ */
+ buffer = ISC_LIST_HEAD(*buflist);
+ while (buffer != NULL) {
+ ISC_LIST_DEQUEUE(*buflist, buffer, link);
+ ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link);
+ buffer = ISC_LIST_HEAD(*buflist);
+ }
+
+ ret = socket_send(sock, dev, task, address, pktinfo, flags);
+ UNLOCK(&sock->lock);
+ return (ret);
+}
+
+isc_result_t
+isc__socket_sendto2(isc_socket_t *sock, isc_region_t *region,
+ isc_task_t *task,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
+ isc_socketevent_t *event, unsigned int flags)
+{
+ isc_result_t ret;
+
+ REQUIRE(VALID_SOCKET(sock));
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ REQUIRE((flags & ~(ISC_SOCKFLAG_IMMEDIATE|ISC_SOCKFLAG_NORETRY)) == 0);
+ if ((flags & ISC_SOCKFLAG_NORETRY) != 0)
+ REQUIRE(sock->type == isc_sockettype_udp);
+ event->ev_sender = sock;
+ event->result = ISC_R_UNEXPECTED;
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+ ISC_LIST_INIT(event->bufferlist);
+ event->region = *region;
+ event->n = 0;
+ event->offset = 0;
+ event->attributes = 0;
+
+ ret = socket_send(sock, event, task, address, pktinfo, flags);
+ UNLOCK(&sock->lock);
+ return (ret);
+}
+
+isc_result_t
+isc__socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+ unsigned int options) {
+ int bind_errno;
+ char strbuf[ISC_STRERRORSIZE];
+ int on = 1;
+
+ REQUIRE(VALID_SOCKET(sock));
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ INSIST(!sock->bound);
+ INSIST(!sock->dupped);
+
+ if (sock->pf != sockaddr->type.sa.sa_family) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_FAMILYMISMATCH);
+ }
+ /*
+ * Only set SO_REUSEADDR when we want a specific port.
+ */
+ if ((options & ISC_SOCKET_REUSEADDRESS) != 0 &&
+ isc_sockaddr_getport(sockaddr) != (in_port_t)0 &&
+ setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
+ sizeof(on)) < 0) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d) %s", sock->fd,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ /* Press on... */
+ }
+ if (bind(sock->fd, &sockaddr->type.sa, sockaddr->length) < 0) {
+ bind_errno = WSAGetLastError();
+ UNLOCK(&sock->lock);
+ switch (bind_errno) {
+ case WSAEACCES:
+ return (ISC_R_NOPERM);
+ case WSAEADDRNOTAVAIL:
+ return (ISC_R_ADDRNOTAVAIL);
+ case WSAEADDRINUSE:
+ return (ISC_R_ADDRINUSE);
+ case WSAEINVAL:
+ return (ISC_R_BOUND);
+ default:
+ isc__strerror(bind_errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "bind: %s",
+ strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+ }
+
+ socket_log(__LINE__, sock, sockaddr, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, "bound");
+ sock->bound = 1;
+
+ UNLOCK(&sock->lock);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__socket_filter(isc_socket_t *sock, const char *filter) {
+ UNUSED(sock);
+ UNUSED(filter);
+
+ REQUIRE(VALID_SOCKET(sock));
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+/*
+ * Set up to listen on a given socket. We do this by creating an internal
+ * event that will be dispatched when the socket has read activity. The
+ * watcher will send the internal event to the task when there is a new
+ * connection.
+ *
+ * Unlike in read, we don't preallocate a done event here. Every time there
+ * is a new connection we'll have to allocate a new one anyway, so we might
+ * as well keep things simple rather than having to track them.
+ */
+isc_result_t
+isc__socket_listen(isc_socket_t *sock, unsigned int backlog) {
+ char strbuf[ISC_STRERRORSIZE];
+#if defined(ISC_PLATFORM_HAVETFO) && defined(TCP_FASTOPEN)
+ char on = 1;
+#endif
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ REQUIRE(!sock->listener);
+ REQUIRE(sock->bound);
+ REQUIRE(sock->type == isc_sockettype_tcp);
+
+ if (backlog == 0)
+ backlog = SOMAXCONN;
+
+ if (listen(sock->fd, (int)backlog) < 0) {
+ UNLOCK(&sock->lock);
+ isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
+
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "listen: %s", strbuf);
+
+ return (ISC_R_UNEXPECTED);
+ }
+
+#if defined(ISC_PLATFORM_HAVETFO) && defined(TCP_FASTOPEN)
+ if (setsockopt(sock->fd, IPPROTO_TCP, TCP_FASTOPEN,
+ &on, sizeof(on)) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, TCP_FASTOPEN) failed with %s",
+ sock->fd, strbuf);
+ /* TCP_FASTOPEN is experimental so ignore failures */
+ }
+#endif
+
+ socket_log(__LINE__, sock, NULL, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, "listening");
+ sock->listener = 1;
+ _set_state(sock, SOCK_LISTEN);
+
+ UNLOCK(&sock->lock);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * This should try to do aggressive accept() XXXMLG
+ */
+isc_result_t
+isc__socket_accept(isc_socket_t *sock,
+ isc_task_t *task, isc_taskaction_t action, void *arg)
+{
+ isc_socket_newconnev_t *adev;
+ isc_socketmgr_t *manager;
+ isc_task_t *ntask = NULL;
+ isc_socket_t *nsock;
+ isc_result_t result;
+ IoCompletionInfo *lpo;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ REQUIRE(sock->listener);
+
+ /*
+ * Sender field is overloaded here with the task we will be sending
+ * this event to. Just before the actual event is delivered the
+ * actual ev_sender will be touched up to be the socket.
+ */
+ adev = (isc_socket_newconnev_t *)
+ isc_event_allocate(manager->mctx, task, ISC_SOCKEVENT_NEWCONN,
+ action, arg, sizeof(*adev));
+ if (adev == NULL) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_NOMEMORY);
+ }
+ ISC_LINK_INIT(adev, ev_link);
+
+ result = allocate_socket(manager, sock->type, &nsock);
+ if (result != ISC_R_SUCCESS) {
+ isc_event_free((isc_event_t **)&adev);
+ UNLOCK(&sock->lock);
+ return (result);
+ }
+
+ /*
+ * AcceptEx() requires we pass in a socket.
+ */
+ nsock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
+ if (nsock->fd == INVALID_SOCKET) {
+ free_socket(&nsock, __LINE__);
+ isc_event_free((isc_event_t **)&adev);
+ UNLOCK(&sock->lock);
+ return (ISC_R_FAILURE); // XXXMLG need real error message
+ }
+
+ /*
+ * Attach to socket and to task.
+ */
+ isc_task_attach(task, &ntask);
+ if (isc_task_exiting(ntask)) {
+ free_socket(&nsock, __LINE__);
+ isc_task_detach(&ntask);
+ isc_event_free(ISC_EVENT_PTR(&adev));
+ UNLOCK(&sock->lock);
+ return (ISC_R_SHUTTINGDOWN);
+ }
+ nsock->references++;
+
+ adev->ev_sender = ntask;
+ adev->newsocket = nsock;
+ _set_state(nsock, SOCK_ACCEPT);
+
+ /*
+ * Queue io completion for an accept().
+ */
+ lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
+ HEAP_ZERO_MEMORY,
+ sizeof(IoCompletionInfo));
+ RUNTIME_CHECK(lpo != NULL);
+ lpo->acceptbuffer = (void *)HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY,
+ (sizeof(SOCKADDR_STORAGE) + 16) * 2);
+ RUNTIME_CHECK(lpo->acceptbuffer != NULL);
+
+ lpo->adev = adev;
+ lpo->request_type = SOCKET_ACCEPT;
+
+ ISCAcceptEx(sock->fd,
+ nsock->fd, /* Accepted Socket */
+ lpo->acceptbuffer, /* Buffer for initial Recv */
+ 0, /* Length of Buffer */
+ sizeof(SOCKADDR_STORAGE) + 16, /* Local address length + 16 */
+ sizeof(SOCKADDR_STORAGE) + 16, /* Remote address lengh + 16 */
+ (LPDWORD)&lpo->received_bytes, /* Bytes Recved */
+ (LPOVERLAPPED)lpo /* Overlapped structure */
+ );
+ iocompletionport_update(nsock);
+
+ socket_log(__LINE__, sock, NULL, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND,
+ "accepting for nsock %p fd %d", nsock, nsock->fd);
+
+ /*
+ * Enqueue the event
+ */
+ ISC_LIST_ENQUEUE(sock->accept_list, adev, ev_link);
+ sock->pending_accept++;
+ sock->pending_iocp++;
+
+ UNLOCK(&sock->lock);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
+ isc_task_t *task, isc_taskaction_t action, void *arg)
+{
+ char strbuf[ISC_STRERRORSIZE];
+ isc_socket_connev_t *cdev;
+ isc_task_t *ntask = NULL;
+ isc_socketmgr_t *manager;
+ IoCompletionInfo *lpo;
+ int bind_errno;
+
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(addr != NULL);
+ REQUIRE(task != NULL);
+ REQUIRE(action != NULL);
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(addr != NULL);
+
+ if (isc_sockaddr_ismulticast(addr))
+ return (ISC_R_MULTICAST);
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ /*
+ * Windows sockets won't connect unless the socket is bound.
+ */
+ if (!sock->bound) {
+ isc_sockaddr_t any;
+
+ isc_sockaddr_anyofpf(&any, isc_sockaddr_pf(addr));
+ if (bind(sock->fd, &any.type.sa, any.length) < 0) {
+ bind_errno = WSAGetLastError();
+ UNLOCK(&sock->lock);
+ switch (bind_errno) {
+ case WSAEACCES:
+ return (ISC_R_NOPERM);
+ case WSAEADDRNOTAVAIL:
+ return (ISC_R_ADDRNOTAVAIL);
+ case WSAEADDRINUSE:
+ return (ISC_R_ADDRINUSE);
+ case WSAEINVAL:
+ return (ISC_R_BOUND);
+ default:
+ isc__strerror(bind_errno, strbuf,
+ sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "bind: %s", strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+ }
+ sock->bound = 1;
+ }
+
+ cdev = (isc_socket_connev_t *)isc_event_allocate(manager->mctx, sock,
+ ISC_SOCKEVENT_CONNECT,
+ action, arg,
+ sizeof(*cdev));
+ if (cdev == NULL) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_NOMEMORY);
+ }
+ ISC_LINK_INIT(cdev, ev_link);
+
+ if (sock->connected) {
+ INSIST(isc_sockaddr_equal(&sock->address, addr));
+ cdev->result = ISC_R_SUCCESS;
+ isc_task_send(task, ISC_EVENT_PTR(&cdev));
+
+ UNLOCK(&sock->lock);
+ return (ISC_R_SUCCESS);
+ }
+
+ if ((sock->type == isc_sockettype_tcp) && !sock->pending_connect) {
+ /*
+ * Queue io completion for an accept().
+ */
+ lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
+ HEAP_ZERO_MEMORY,
+ sizeof(IoCompletionInfo));
+ lpo->cdev = cdev;
+ lpo->request_type = SOCKET_CONNECT;
+
+ sock->address = *addr;
+ ISCConnectEx(sock->fd, &addr->type.sa, addr->length,
+ NULL, 0, NULL, (LPOVERLAPPED)lpo);
+
+ /*
+ * Attach to task.
+ */
+ isc_task_attach(task, &ntask);
+ cdev->ev_sender = ntask;
+
+ sock->pending_connect = 1;
+ _set_state(sock, SOCK_CONNECT);
+
+ /*
+ * Enqueue the request.
+ */
+ INSIST(!ISC_LINK_LINKED(cdev, ev_link));
+ ISC_LIST_ENQUEUE(sock->connect_list, cdev, ev_link);
+ sock->pending_iocp++;
+ } else if (sock->type == isc_sockettype_tcp) {
+ INSIST(sock->pending_connect);
+ INSIST(isc_sockaddr_equal(&sock->address, addr));
+ isc_task_attach(task, &ntask);
+ cdev->ev_sender = ntask;
+ INSIST(!ISC_LINK_LINKED(cdev, ev_link));
+ ISC_LIST_ENQUEUE(sock->connect_list, cdev, ev_link);
+ } else {
+ REQUIRE(!sock->pending_connect);
+ WSAConnect(sock->fd, &addr->type.sa, addr->length, NULL, NULL, NULL, NULL);
+ cdev->result = ISC_R_SUCCESS;
+ isc_task_send(task, (isc_event_t **)&cdev);
+ }
+ CONSISTENT(sock);
+ UNLOCK(&sock->lock);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+ isc_result_t result;
+
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(addressp != NULL);
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ if (sock->connected) {
+ *addressp = sock->address;
+ result = ISC_R_SUCCESS;
+ } else {
+ result = ISC_R_NOTCONNECTED;
+ }
+
+ UNLOCK(&sock->lock);
+
+ return (result);
+}
+
+isc_result_t
+isc__socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+ ISC_SOCKADDR_LEN_T len;
+ isc_result_t result;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(addressp != NULL);
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ if (!sock->bound) {
+ result = ISC_R_NOTBOUND;
+ goto out;
+ }
+
+ result = ISC_R_SUCCESS;
+
+ len = sizeof(addressp->type);
+ if (getsockname(sock->fd, &addressp->type.sa, (void *)&len) < 0) {
+ isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "getsockname: %s",
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto out;
+ }
+ addressp->length = (unsigned int)len;
+
+ out:
+ UNLOCK(&sock->lock);
+
+ return (result);
+}
+
+/*
+ * Run through the list of events on this socket, and cancel the ones
+ * queued for task "task" of type "how". "how" is a bitmask.
+ */
+void
+isc__socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ /*
+ * Quick exit if there is nothing to do. Don't even bother locking
+ * in this case.
+ */
+ if (how == 0)
+ return;
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return;
+ }
+
+ /*
+ * All of these do the same thing, more or less.
+ * Each will:
+ * o If the internal event is marked as "posted" try to
+ * remove it from the task's queue. If this fails, mark it
+ * as canceled instead, and let the task clean it up later.
+ * o For each I/O request for that task of that type, post
+ * its done event with status of "ISC_R_CANCELED".
+ * o Reset any state needed.
+ */
+
+ if ((how & ISC_SOCKCANCEL_RECV) == ISC_SOCKCANCEL_RECV) {
+ isc_socketevent_t *dev;
+ isc_socketevent_t *next;
+ isc_task_t *current_task;
+
+ dev = ISC_LIST_HEAD(sock->recv_list);
+ while (dev != NULL) {
+ current_task = dev->ev_sender;
+ next = ISC_LIST_NEXT(dev, ev_link);
+ if ((task == NULL) || (task == current_task)) {
+ dev->result = ISC_R_CANCELED;
+ send_recvdone_event(sock, &dev);
+ }
+ dev = next;
+ }
+ }
+ how &= ~ISC_SOCKCANCEL_RECV;
+
+ if ((how & ISC_SOCKCANCEL_SEND) == ISC_SOCKCANCEL_SEND) {
+ isc_socketevent_t *dev;
+ isc_socketevent_t *next;
+ isc_task_t *current_task;
+
+ dev = ISC_LIST_HEAD(sock->send_list);
+
+ while (dev != NULL) {
+ current_task = dev->ev_sender;
+ next = ISC_LIST_NEXT(dev, ev_link);
+ if ((task == NULL) || (task == current_task)) {
+ dev->result = ISC_R_CANCELED;
+ send_senddone_event(sock, &dev);
+ }
+ dev = next;
+ }
+ }
+ how &= ~ISC_SOCKCANCEL_SEND;
+
+ if (((how & ISC_SOCKCANCEL_ACCEPT) == ISC_SOCKCANCEL_ACCEPT)
+ && !ISC_LIST_EMPTY(sock->accept_list)) {
+ isc_socket_newconnev_t *dev;
+ isc_socket_newconnev_t *next;
+ isc_task_t *current_task;
+
+ dev = ISC_LIST_HEAD(sock->accept_list);
+ while (dev != NULL) {
+ current_task = dev->ev_sender;
+ next = ISC_LIST_NEXT(dev, ev_link);
+
+ if ((task == NULL) || (task == current_task)) {
+
+ dev->newsocket->references--;
+ closesocket(dev->newsocket->fd);
+ dev->newsocket->fd = INVALID_SOCKET;
+ free_socket(&dev->newsocket, __LINE__);
+
+ dev->result = ISC_R_CANCELED;
+ send_acceptdone_event(sock, &dev);
+ }
+
+ dev = next;
+ }
+ }
+ how &= ~ISC_SOCKCANCEL_ACCEPT;
+
+ if (((how & ISC_SOCKCANCEL_CONNECT) == ISC_SOCKCANCEL_CONNECT)
+ && !ISC_LIST_EMPTY(sock->connect_list)) {
+ isc_socket_connev_t *dev;
+ isc_socket_connev_t *next;
+ isc_task_t *current_task;
+
+ INSIST(sock->pending_connect);
+
+ dev = ISC_LIST_HEAD(sock->connect_list);
+
+ while (dev != NULL) {
+ current_task = dev->ev_sender;
+ next = ISC_LIST_NEXT(dev, ev_link);
+ if ((task == NULL) || (task == current_task)) {
+ dev->result = ISC_R_CANCELED;
+ send_connectdone_event(sock, &dev);
+ }
+ dev = next;
+ }
+ closesocket(sock->fd);
+ sock->fd = INVALID_SOCKET;
+ _set_state(sock, SOCK_CLOSED);
+ }
+ how &= ~ISC_SOCKCANCEL_CONNECT;
+
+ maybe_free_socket(&sock, __LINE__);
+}
+
+isc_sockettype_t
+isc__socket_gettype(isc_socket_t *sock) {
+ isc_sockettype_t type;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ type = sock->type;
+ UNLOCK(&sock->lock);
+ return (type);
+}
+
+bool
+isc__socket_isbound(isc_socket_t *sock) {
+ bool val;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (false);
+ }
+
+ val = ((sock->bound) ? true : false);
+ UNLOCK(&sock->lock);
+
+ return (val);
+}
+
+void
+isc__socket_ipv6only(isc_socket_t *sock, bool yes) {
+#if defined(IPV6_V6ONLY)
+ int onoff = yes ? 1 : 0;
+#else
+ UNUSED(yes);
+#endif
+
+ REQUIRE(VALID_SOCKET(sock));
+
+#ifdef IPV6_V6ONLY
+ if (sock->pf == AF_INET6) {
+ (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *)&onoff, sizeof(onoff));
+ }
+#endif
+}
+
+void
+isc__socket_dscp(isc_socket_t *sock, isc_dscp_t dscp) {
+#if !defined(IP_TOS) && !defined(IPV6_TCLASS)
+ UNUSED(dscp);
+#else
+ if (dscp < 0)
+ return;
+
+ dscp <<= 2;
+ dscp &= 0xff;
+#endif
+
+ REQUIRE(VALID_SOCKET(sock));
+
+#ifdef IP_TOS
+ if (sock->pf == AF_INET) {
+ (void)setsockopt(sock->fd, IPPROTO_IP, IP_TOS,
+ (char *)&dscp, sizeof(dscp));
+ }
+#endif
+#ifdef IPV6_TCLASS
+ if (sock->pf == AF_INET6) {
+ (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_TCLASS,
+ (char *)&dscp, sizeof(dscp));
+ }
+#endif
+}
+
+void
+isc__socket_cleanunix(isc_sockaddr_t *addr, bool active) {
+ UNUSED(addr);
+ UNUSED(active);
+}
+
+isc_result_t
+isc__socket_permunix(isc_sockaddr_t *addr, uint32_t perm,
+ uint32_t owner, uint32_t group)
+{
+ UNUSED(addr);
+ UNUSED(perm);
+ UNUSED(owner);
+ UNUSED(group);
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+void
+isc__socket_setname(isc_socket_t *socket, const char *name, void *tag) {
+
+ /*
+ * Name 'socket'.
+ */
+
+ REQUIRE(VALID_SOCKET(socket));
+
+ LOCK(&socket->lock);
+ strlcpy(socket->name, name, sizeof(socket->name));
+ socket->tag = tag;
+ UNLOCK(&socket->lock);
+}
+
+const char *
+isc__socket_getname(isc_socket_t *socket) {
+ return (socket->name);
+}
+
+void *
+isc__socket_gettag(isc_socket_t *socket) {
+ return (socket->tag);
+}
+
+int
+isc__socket_getfd(isc_socket_t *socket) {
+ return ((short) socket->fd);
+}
+
+void
+isc__socketmgr_setreserved(isc_socketmgr_t *manager, uint32_t reserved) {
+ UNUSED(manager);
+ UNUSED(reserved);
+}
+
+void
+isc___socketmgr_maxudp(isc_socketmgr_t *manager, int maxudp) {
+
+ UNUSED(manager);
+ UNUSED(maxudp);
+}
+
+isc_socketevent_t *
+isc_socket_socketevent(isc_mem_t *mctx, void *sender,
+ isc_eventtype_t eventtype, isc_taskaction_t action,
+ void *arg)
+{
+ return (allocate_socketevent(mctx, sender, eventtype, action, arg));
+}
+
+#ifdef HAVE_LIBXML2
+
+static const char *
+_socktype(isc_sockettype_t type) {
+ if (type == isc_sockettype_udp)
+ return ("udp");
+ else if (type == isc_sockettype_tcp)
+ return ("tcp");
+ else if (type == isc_sockettype_unix)
+ return ("unix");
+ else if (type == isc_sockettype_fdwatch)
+ return ("fdwatch");
+ else
+ return ("not-initialized");
+}
+
+#define TRY0(a) do { xmlrc = (a); if (xmlrc < 0) goto error; } while(0)
+int
+isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer)
+{
+ isc_socket_t *sock = NULL;
+ char peerbuf[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_t addr;
+ ISC_SOCKADDR_LEN_T len;
+ int xmlrc;
+
+ LOCK(&mgr->lock);
+
+#ifndef ISC_PLATFORM_USETHREADS
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "references"));
+ TRY0(xmlTextWriterWriteFormatString(writer, "%d", mgr->refs));
+ TRY0(xmlTextWriterEndElement(writer));
+#endif
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "sockets"));
+ sock = ISC_LIST_HEAD(mgr->socklist);
+ while (sock != NULL) {
+ LOCK(&sock->lock);
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "socket"));
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "id"));
+ TRY0(xmlTextWriterWriteFormatString(writer, "%p", sock));
+ TRY0(xmlTextWriterEndElement(writer));
+
+ if (sock->name[0] != 0) {
+ TRY0(xmlTextWriterStartElement(writer,
+ ISC_XMLCHAR "name"));
+ TRY0(xmlTextWriterWriteFormatString(writer, "%s",
+ sock->name));
+ TRY0(xmlTextWriterEndElement(writer)); /* name */
+ }
+
+ TRY0(xmlTextWriterStartElement(writer,
+ ISC_XMLCHAR "references"));
+ TRY0(xmlTextWriterWriteFormatString(writer, "%d",
+ sock->references));
+ TRY0(xmlTextWriterEndElement(writer));
+
+ TRY0(xmlTextWriterWriteElement(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR _socktype(sock->type)));
+
+ if (sock->connected) {
+ isc_sockaddr_format(&sock->address, peerbuf,
+ sizeof(peerbuf));
+ TRY0(xmlTextWriterWriteElement(writer,
+ ISC_XMLCHAR "peer-address",
+ ISC_XMLCHAR peerbuf));
+ }
+
+ len = sizeof(addr);
+ if (getsockname(sock->fd, &addr.type.sa, (void *)&len) == 0) {
+ isc_sockaddr_format(&addr, peerbuf, sizeof(peerbuf));
+ TRY0(xmlTextWriterWriteElement(writer,
+ ISC_XMLCHAR "local-address",
+ ISC_XMLCHAR peerbuf));
+ }
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "states"));
+ if (sock->pending_recv)
+ TRY0(xmlTextWriterWriteElement(writer,
+ ISC_XMLCHAR "state",
+ ISC_XMLCHAR "pending-receive"));
+ if (sock->pending_send)
+ TRY0(xmlTextWriterWriteElement(writer,
+ ISC_XMLCHAR "state",
+ ISC_XMLCHAR "pending-send"));
+ if (sock->pending_accept)
+ TRY0(xmlTextWriterWriteElement(writer,
+ ISC_XMLCHAR "state",
+ ISC_XMLCHAR "pending_accept"));
+ if (sock->listener)
+ TRY0(xmlTextWriterWriteElement(writer,
+ ISC_XMLCHAR "state",
+ ISC_XMLCHAR "listener"));
+ if (sock->connected)
+ TRY0(xmlTextWriterWriteElement(writer,
+ ISC_XMLCHAR "state",
+ ISC_XMLCHAR "connected"));
+ if (sock->pending_connect)
+ TRY0(xmlTextWriterWriteElement(writer,
+ ISC_XMLCHAR "state",
+ ISC_XMLCHAR "connecting"));
+ if (sock->bound)
+ TRY0(xmlTextWriterWriteElement(writer,
+ ISC_XMLCHAR "state",
+ ISC_XMLCHAR "bound"));
+
+ TRY0(xmlTextWriterEndElement(writer)); /* states */
+
+ TRY0(xmlTextWriterEndElement(writer)); /* socket */
+
+ UNLOCK(&sock->lock);
+ sock = ISC_LIST_NEXT(sock, link);
+ }
+ TRY0(xmlTextWriterEndElement(writer)); /* sockets */
+
+error:
+ if (sock != NULL)
+ UNLOCK(&sock->lock);
+
+ UNLOCK(&mgr->lock);
+
+ return (xmlrc);
+}
+#endif /* HAVE_LIBXML2 */
+
+#ifdef HAVE_JSON
+#define CHECKMEM(m) do { \
+ if (m == NULL) { \
+ result = ISC_R_NOMEMORY;\
+ goto error;\
+ } \
+} while(0)
+
+isc_result_t
+isc_socketmgr_renderjson(isc_socketmgr_t *mgr, json_object *stats) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_socket_t *sock = NULL;
+ char peerbuf[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_t addr;
+ ISC_SOCKADDR_LEN_T len;
+ json_object *obj, *array = json_object_new_array();
+
+ CHECKMEM(array);
+
+ LOCK(&mgr->lock);
+
+#ifdef USE_SHARED_MANAGER
+ obj = json_object_new_int(mgr->refs);
+ CHECKMEM(obj);
+ json_object_object_add(stats, "references", obj);
+#endif /* USE_SHARED_MANAGER */
+
+ sock = ISC_LIST_HEAD(mgr->socklist);
+ while (sock != NULL) {
+ json_object *states, *entry = json_object_new_object();
+ char buf[255];
+
+ CHECKMEM(entry);
+ json_object_array_add(array, entry);
+
+ LOCK(&sock->lock);
+
+ snprintf(buf, sizeof(buf), "%p", sock);
+ obj = json_object_new_string(buf);
+ CHECKMEM(obj);
+ json_object_object_add(entry, "id", obj);
+
+ if (sock->name[0] != 0) {
+ obj = json_object_new_string(sock->name);
+ CHECKMEM(obj);
+ json_object_object_add(entry, "name", obj);
+ }
+
+ obj = json_object_new_int(sock->references);
+ CHECKMEM(obj);
+ json_object_object_add(entry, "references", obj);
+
+ obj = json_object_new_string(_socktype(sock->type));
+ CHECKMEM(obj);
+ json_object_object_add(entry, "type", obj);
+
+ if (sock->connected) {
+ isc_sockaddr_format(&sock->address, peerbuf,
+ sizeof(peerbuf));
+ obj = json_object_new_string(peerbuf);
+ CHECKMEM(obj);
+ json_object_object_add(entry, "peer-address", obj);
+ }
+
+ len = sizeof(addr);
+ if (getsockname(sock->fd, &addr.type.sa, (void *)&len) == 0) {
+ isc_sockaddr_format(&addr, peerbuf, sizeof(peerbuf));
+ obj = json_object_new_string(peerbuf);
+ CHECKMEM(obj);
+ json_object_object_add(entry, "local-address", obj);
+ }
+
+ states = json_object_new_array();
+ CHECKMEM(states);
+ json_object_object_add(entry, "states", states);
+
+ if (sock->pending_recv) {
+ obj = json_object_new_string("pending-receive");
+ CHECKMEM(obj);
+ json_object_array_add(states, obj);
+ }
+
+ if (sock->pending_send) {
+ obj = json_object_new_string("pending-send");
+ CHECKMEM(obj);
+ json_object_array_add(states, obj);
+ }
+
+ if (sock->pending_accept) {
+ obj = json_object_new_string("pending-accept");
+ CHECKMEM(obj);
+ json_object_array_add(states, obj);
+ }
+
+ if (sock->listener) {
+ obj = json_object_new_string("listener");
+ CHECKMEM(obj);
+ json_object_array_add(states, obj);
+ }
+
+ if (sock->connected) {
+ obj = json_object_new_string("connected");
+ CHECKMEM(obj);
+ json_object_array_add(states, obj);
+ }
+
+ if (sock->pending_connect) {
+ obj = json_object_new_string("connecting");
+ CHECKMEM(obj);
+ json_object_array_add(states, obj);
+ }
+
+ if (sock->bound) {
+ obj = json_object_new_string("bound");
+ CHECKMEM(obj);
+ json_object_array_add(states, obj);
+ }
+
+ UNLOCK(&sock->lock);
+ sock = ISC_LIST_NEXT(sock, link);
+ }
+
+ json_object_object_add(stats, "sockets", array);
+ array = NULL;
+ result = ISC_R_SUCCESS;
+
+ error:
+ if (array != NULL)
+ json_object_put(array);
+
+ if (sock != NULL)
+ UNLOCK(&sock->lock);
+
+ UNLOCK(&mgr->lock);
+
+ return (result);
+}
+#endif /* HAVE_JSON */
+
+/*
+ * Replace ../socket_api.c
+ */
+
+isc_result_t
+isc__socket_register(void) {
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
+ isc_socketmgr_t **managerp)
+{
+ isc_result_t result;
+
+ result = isc_socketmgr_create(mctx, managerp);
+
+ if (result == ISC_R_SUCCESS)
+ isc_appctx_setsocketmgr(actx, *managerp);
+
+ return (result);
+}
diff --git a/lib/isc/win32/stdio.c b/lib/isc/win32/stdio.c
new file mode 100644
index 0000000..a4c8134
--- /dev/null
+++ b/lib/isc/win32/stdio.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <io.h>
+#include <errno.h>
+
+#include <isc/stdio.h>
+#include <isc/util.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "errno2result.h"
+
+isc_result_t
+isc_stdio_open(const char *filename, const char *mode, FILE **fp) {
+ FILE *f;
+
+ f = fopen(filename, mode);
+ if (f == NULL)
+ return (isc__errno2result(errno));
+ *fp = f;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_stdio_close(FILE *f) {
+ int r;
+
+ r = fclose(f);
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_stdio_seek(FILE *f, off_t offset, int whence) {
+ int r;
+
+#ifndef _WIN64
+ r = fseek(f, offset, whence);
+#else
+ r = _fseeki64(f, offset, whence);
+#endif
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_stdio_tell(FILE *f, off_t *offsetp) {
+#ifndef _WIN64
+ long r;
+#else
+ __int64 r;
+#endif
+
+ REQUIRE(offsetp != NULL);
+
+#ifndef _WIN64
+ r = ftell(f);
+#else
+ r = _ftelli64(f);
+#endif
+ if (r >= 0) {
+ *offsetp = r;
+ return (ISC_R_SUCCESS);
+ } else
+ return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_stdio_read(void *ptr, size_t size, size_t nmemb, FILE *f, size_t *nret) {
+ isc_result_t result = ISC_R_SUCCESS;
+ size_t r;
+
+ clearerr(f);
+ r = fread(ptr, size, nmemb, f);
+ if (r != nmemb) {
+ if (feof(f))
+ result = ISC_R_EOF;
+ else
+ result = isc__errno2result(errno);
+ }
+ if (nret != NULL)
+ *nret = r;
+ return (result);
+}
+
+isc_result_t
+isc_stdio_write(const void *ptr, size_t size, size_t nmemb, FILE *f,
+ size_t *nret)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ size_t r;
+
+ clearerr(f);
+ r = fwrite(ptr, size, nmemb, f);
+ if (r != nmemb)
+ result = isc__errno2result(errno);
+ if (nret != NULL)
+ *nret = r;
+ return (result);
+}
+
+isc_result_t
+isc_stdio_flush(FILE *f) {
+ int r;
+
+ r = fflush(f);
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_stdio_sync(FILE *f) {
+ struct _stat buf;
+ int r;
+
+ if (_fstat(_fileno(f), &buf) != 0)
+ return (isc__errno2result(errno));
+
+ /*
+ * Only call _commit() on regular files.
+ */
+ if ((buf.st_mode & S_IFMT) != S_IFREG)
+ return (ISC_R_SUCCESS);
+
+ r = _commit(_fileno(f));
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
diff --git a/lib/isc/win32/stdtime.c b/lib/isc/win32/stdtime.c
new file mode 100644
index 0000000..bff6fd1
--- /dev/null
+++ b/lib/isc/win32/stdtime.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <time.h>
+
+#include <isc/assertions.h>
+#include <isc/stdtime.h>
+#include <isc/util.h>
+
+void
+isc_stdtime_get(isc_stdtime_t *t) {
+ /*
+ * Set 't' to the number of seconds past 00:00:00 UTC, January 1, 1970.
+ */
+
+ REQUIRE(t != NULL);
+
+ (void)_time32(t);
+}
diff --git a/lib/isc/win32/strerror.c b/lib/isc/win32/strerror.c
new file mode 100644
index 0000000..36c9b79
--- /dev/null
+++ b/lib/isc/win32/strerror.c
@@ -0,0 +1,452 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <winsock2.h>
+
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/print.h>
+#include <isc/strerror.h>
+#include <isc/util.h>
+
+/*
+ * Forward declarations
+ */
+
+char *
+FormatError(int error);
+
+char *
+GetWSAErrorMessage(int errval);
+
+char *
+NTstrerror(int err, BOOL *bfreebuf);
+
+/*
+ * We need to do this this way for profiled locks.
+ */
+
+static isc_mutex_t isc_strerror_lock;
+static void init_lock(void) {
+ RUNTIME_CHECK(isc_mutex_init(&isc_strerror_lock) == ISC_R_SUCCESS);
+}
+
+/*
+ * This routine needs to free up any buffer allocated by FormatMessage
+ * if that routine gets used.
+ */
+
+void
+isc__strerror(int num, char *buf, size_t size) {
+ char *msg;
+ BOOL freebuf;
+ unsigned int unum = num;
+ static isc_once_t once = ISC_ONCE_INIT;
+
+ REQUIRE(buf != NULL);
+
+ RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS);
+
+ LOCK(&isc_strerror_lock);
+ freebuf = FALSE;
+ msg = NTstrerror(num, &freebuf);
+ if (msg != NULL)
+ snprintf(buf, size, "%s", msg);
+ else
+ snprintf(buf, size, "Unknown error: %u", unum);
+ if(freebuf && msg != NULL) {
+ LocalFree(msg);
+ }
+ UNLOCK(&isc_strerror_lock);
+}
+
+/*
+ * Note this will cause a memory leak unless the memory allocated here
+ * is freed by calling LocalFree. isc__strerror does this before unlocking.
+ * This only gets called if there is a system type of error and will likely
+ * be an unusual event.
+ */
+char *
+FormatError(int error) {
+ LPVOID lpMsgBuf = NULL;
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ error,
+ /* Default language */
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL);
+
+ return (lpMsgBuf);
+}
+
+/*
+ * This routine checks the error value and calls the WSA Windows Sockets
+ * Error message function GetWSAErrorMessage below if it's within that range
+ * since those messages are not available in the system error messages.
+ */
+char *
+NTstrerror(int err, BOOL *bfreebuf) {
+ char *retmsg = NULL;
+
+ /* Copy the error value first in case of other errors */
+ DWORD errval = err;
+
+ *bfreebuf = FALSE;
+
+ /* Get the Winsock2 error messages */
+ if (errval >= WSABASEERR && errval <= (WSABASEERR + 1015)) {
+ retmsg = GetWSAErrorMessage(errval);
+ if (retmsg != NULL)
+ return (retmsg);
+ }
+ /*
+ * If it's not one of the standard Unix error codes,
+ * try a system error message
+ */
+ if (errval > (DWORD) _sys_nerr) {
+ *bfreebuf = TRUE;
+ return (FormatError(errval));
+ } else {
+ return (strerror(errval));
+ }
+}
+
+/*
+ * This is a replacement for perror
+ */
+void __cdecl
+NTperror(char *errmsg) {
+ /* Copy the error value first in case of other errors */
+ int errval = errno;
+ BOOL bfreebuf = FALSE;
+ char *msg;
+
+ msg = NTstrerror(errval, &bfreebuf);
+ fprintf(stderr, "%s: %s\n", errmsg, msg);
+ if(bfreebuf == TRUE) {
+ LocalFree(msg);
+ }
+
+}
+
+/*
+ * Return the error string related to Winsock2 errors.
+ * This function is necessary since FormatMessage knows nothing about them
+ * and there is no function to get them.
+ */
+char *
+GetWSAErrorMessage(int errval) {
+ char *msg;
+
+ switch (errval) {
+
+ case WSAEINTR:
+ msg = "Interrupted system call";
+ break;
+
+ case WSAEBADF:
+ msg = "Bad file number";
+ break;
+
+ case WSAEACCES:
+ msg = "Permission denied";
+ break;
+
+ case WSAEFAULT:
+ msg = "Bad address";
+ break;
+
+ case WSAEINVAL:
+ msg = "Invalid argument";
+ break;
+
+ case WSAEMFILE:
+ msg = "Too many open sockets";
+ break;
+
+ case WSAEWOULDBLOCK:
+ msg = "Operation would block";
+ break;
+
+ case WSAEINPROGRESS:
+ msg = "Operation now in progress";
+ break;
+
+ case WSAEALREADY:
+ msg = "Operation already in progress";
+ break;
+
+ case WSAENOTSOCK:
+ msg = "Socket operation on non-socket";
+ break;
+
+ case WSAEDESTADDRREQ:
+ msg = "Destination address required";
+ break;
+
+ case WSAEMSGSIZE:
+ msg = "Message too long";
+ break;
+
+ case WSAEPROTOTYPE:
+ msg = "Protocol wrong type for socket";
+ break;
+
+ case WSAENOPROTOOPT:
+ msg = "Bad protocol option";
+ break;
+
+ case WSAEPROTONOSUPPORT:
+ msg = "Protocol not supported";
+ break;
+
+ case WSAESOCKTNOSUPPORT:
+ msg = "Socket type not supported";
+ break;
+
+ case WSAEOPNOTSUPP:
+ msg = "Operation not supported on socket";
+ break;
+
+ case WSAEPFNOSUPPORT:
+ msg = "Protocol family not supported";
+ break;
+
+ case WSAEAFNOSUPPORT:
+ msg = "Address family not supported";
+ break;
+
+ case WSAEADDRINUSE:
+ msg = "Address already in use";
+ break;
+
+ case WSAEADDRNOTAVAIL:
+ msg = "Can't assign requested address";
+ break;
+
+ case WSAENETDOWN:
+ msg = "Network is down";
+ break;
+
+ case WSAENETUNREACH:
+ msg = "Network is unreachable";
+ break;
+
+ case WSAENETRESET:
+ msg = "Net connection reset";
+ break;
+
+ case WSAECONNABORTED:
+ msg = "Software caused connection abort";
+ break;
+
+ case WSAECONNRESET:
+ msg = "Connection reset by peer";
+ break;
+
+ case WSAENOBUFS:
+ msg = "No buffer space available";
+ break;
+
+ case WSAEISCONN:
+ msg = "Socket is already connected";
+ break;
+
+ case WSAENOTCONN:
+ msg = "Socket is not connected";
+ break;
+
+ case WSAESHUTDOWN:
+ msg = "Can't send after socket shutdown";
+ break;
+
+ case WSAETOOMANYREFS:
+ msg = "Too many references: can't splice";
+ break;
+
+ case WSAETIMEDOUT:
+ msg = "Connection timed out";
+ break;
+
+ case WSAECONNREFUSED:
+ msg = "Connection refused";
+ break;
+
+ case WSAELOOP:
+ msg = "Too many levels of symbolic links";
+ break;
+
+ case WSAENAMETOOLONG:
+ msg = "File name too long";
+ break;
+
+ case WSAEHOSTDOWN:
+ msg = "Host is down";
+ break;
+
+ case WSAEHOSTUNREACH:
+ msg = "No route to host";
+ break;
+
+ case WSAENOTEMPTY:
+ msg = "Directory not empty";
+ break;
+
+ case WSAEPROCLIM:
+ msg = "Too many processes";
+ break;
+
+ case WSAEUSERS:
+ msg = "Too many users";
+ break;
+
+ case WSAEDQUOT:
+ msg = "Disc quota exceeded";
+ break;
+
+ case WSAESTALE:
+ msg = "Stale NFS file handle";
+ break;
+
+ case WSAEREMOTE:
+ msg = "Too many levels of remote in path";
+ break;
+
+ case WSASYSNOTREADY:
+ msg = "Network system is unavailable";
+ break;
+
+ case WSAVERNOTSUPPORTED:
+ msg = "Winsock version out of range";
+ break;
+
+ case WSANOTINITIALISED:
+ msg = "WSAStartup not yet called";
+ break;
+
+ case WSAEDISCON:
+ msg = "Graceful shutdown in progress";
+ break;
+/*
+ case WSAHOST_NOT_FOUND:
+ msg = "Host not found";
+ break;
+
+ case WSANO_DATA:
+ msg = "No host data of that type was found";
+ break;
+*/
+ default:
+ msg = NULL;
+ break;
+ }
+ return (msg);
+}
+
+/*
+ * These error messages are more informative about CryptAPI Errors than the
+ * standard error messages
+ */
+
+char *
+GetCryptErrorMessage(int errval) {
+ char *msg;
+
+ switch (errval) {
+
+ case NTE_BAD_FLAGS:
+ msg = "The dwFlags parameter has an illegal value.";
+ break;
+ case NTE_BAD_KEYSET:
+ msg = "The Registry entry for the key container "
+ "could not be opened and may not exist.";
+ break;
+ case NTE_BAD_KEYSET_PARAM:
+ msg = "The pszContainer or pszProvider parameter "
+ "is set to an illegal value.";
+ break;
+ case NTE_BAD_PROV_TYPE:
+ msg = "The value of the dwProvType parameter is out "
+ "of range. All provider types must be from "
+ "1 to 999, inclusive.";
+ break;
+ case NTE_BAD_SIGNATURE:
+ msg = "The provider DLL signature did not verify "
+ "correctly. Either the DLL or the digital "
+ "signature has been tampered with.";
+ break;
+ case NTE_EXISTS:
+ msg = "The dwFlags parameter is CRYPT_NEWKEYSET, but the key"
+ " container already exists.";
+ break;
+ case NTE_KEYSET_ENTRY_BAD:
+ msg = "The Registry entry for the pszContainer key container "
+ "was found (in the HKEY_CURRENT_USER window), but is "
+ "corrupt. See the section System Administration for "
+ " etails about CryptoAPI's Registry usage.";
+ break;
+ case NTE_KEYSET_NOT_DEF:
+ msg = "No Registry entry exists in the HKEY_CURRENT_USER "
+ "window for the key container specified by "
+ "pszContainer.";
+ break;
+ case NTE_NO_MEMORY:
+ msg = "The CSP ran out of memory during the operation.";
+ break;
+ case NTE_PROV_DLL_NOT_FOUND:
+ msg = "The provider DLL file does not exist or is not on the "
+ "current path.";
+ break;
+ case NTE_PROV_TYPE_ENTRY_BAD:
+ msg = "The Registry entry for the provider type specified by "
+ "dwProvType is corrupt. This error may relate to "
+ "either the user default CSP list or the machine "
+ "default CSP list. See the section System "
+ "Administration for details about CryptoAPI's "
+ "Registry usage.";
+ break;
+ case NTE_PROV_TYPE_NO_MATCH:
+ msg = "The provider type specified by dwProvType does not "
+ "match the provider type found in the Registry. Note "
+ "that this error can only occur when pszProvider "
+ "specifies an actual CSP name.";
+ break;
+ case NTE_PROV_TYPE_NOT_DEF:
+ msg = "No Registry entry exists for the provider type "
+ "specified by dwProvType.";
+ break;
+ case NTE_PROVIDER_DLL_FAIL:
+ msg = "The provider DLL file could not be loaded, and "
+ "may not exist. If it exists, then the file is "
+ "not a valid DLL.";
+ break;
+ case NTE_SIGNATURE_FILE_BAD:
+ msg = "An error occurred while loading the DLL file image, "
+ "prior to verifying its signature.";
+ break;
+
+ default:
+ msg = NULL;
+ break;
+ }
+ return msg;
+}
+
diff --git a/lib/isc/win32/syslog.c b/lib/isc/win32/syslog.c
new file mode 100644
index 0000000..071e187
--- /dev/null
+++ b/lib/isc/win32/syslog.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <stdio.h>
+#include <windows.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+
+#include <isc/bindevt.h>
+#include <isc/result.h>
+#include <isc/syslog.h>
+#include <isc/util.h>
+
+static HANDLE hAppLog = NULL;
+static FILE *log_stream;
+static int debug_level = 0;
+
+static struct dsn_c_pvt_sfnt {
+ int val;
+ const char *strval;
+} facilities[] = {
+ { LOG_KERN, "kern" },
+ { LOG_USER, "user" },
+ { LOG_MAIL, "mail" },
+ { LOG_DAEMON, "daemon" },
+ { LOG_AUTH, "auth" },
+ { LOG_SYSLOG, "syslog" },
+ { LOG_LPR, "lpr" },
+#ifdef LOG_NEWS
+ { LOG_NEWS, "news" },
+#endif
+#ifdef LOG_UUCP
+ { LOG_UUCP, "uucp" },
+#endif
+#ifdef LOG_CRON
+ { LOG_CRON, "cron" },
+#endif
+#ifdef LOG_AUTHPRIV
+ { LOG_AUTHPRIV, "authpriv" },
+#endif
+#ifdef LOG_FTP
+ { LOG_FTP, "ftp" },
+#endif
+ { LOG_LOCAL0, "local0"},
+ { LOG_LOCAL1, "local1"},
+ { LOG_LOCAL2, "local2"},
+ { LOG_LOCAL3, "local3"},
+ { LOG_LOCAL4, "local4"},
+ { LOG_LOCAL5, "local5"},
+ { LOG_LOCAL6, "local6"},
+ { LOG_LOCAL7, "local7"},
+ { 0, NULL }
+};
+
+isc_result_t
+isc_syslog_facilityfromstring(const char *str, int *facilityp) {
+ int i;
+
+ REQUIRE(str != NULL);
+ REQUIRE(facilityp != NULL);
+
+ for (i = 0; facilities[i].strval != NULL; i++) {
+ if (strcasecmp(facilities[i].strval, str) == 0) {
+ *facilityp = facilities[i].val;
+ return (ISC_R_SUCCESS);
+ }
+ }
+ return (ISC_R_NOTFOUND);
+}
+
+/*
+ * Log to the NT Event Log
+ */
+void
+syslog(int level, const char *fmt, ...) {
+ va_list ap;
+ char buf[1024];
+ char *str[1];
+
+ str[0] = buf;
+
+ va_start(ap, fmt);
+ vsprintf(buf, fmt, ap);
+ va_end(ap);
+
+ /* Make sure that the channel is open to write the event */
+ if (hAppLog != NULL) {
+ switch (level) {
+ case LOG_INFO:
+ case LOG_NOTICE:
+ case LOG_DEBUG:
+ ReportEvent(hAppLog, EVENTLOG_INFORMATION_TYPE, 0,
+ BIND_INFO_MSG, NULL, 1, 0, str, NULL);
+ break;
+ case LOG_WARNING:
+ ReportEvent(hAppLog, EVENTLOG_WARNING_TYPE, 0,
+ BIND_WARN_MSG, NULL, 1, 0, str, NULL);
+ break;
+ default:
+ ReportEvent(hAppLog, EVENTLOG_ERROR_TYPE, 0,
+ BIND_ERR_MSG, NULL, 1, 0, str, NULL);
+ break;
+ }
+ }
+}
+
+/*
+ * Initialize event logging
+ */
+void
+openlog(const char *name, int flags, ...) {
+ /* Get a handle to the Application event log */
+ hAppLog = RegisterEventSource(NULL, name);
+}
+
+/*
+ * Close the Handle to the application Event Log
+ * We don't care whether or not we succeeded so ignore return values
+ * In fact if we failed then we would have nowhere to put the message
+ */
+void
+closelog(void) {
+ DeregisterEventSource(hAppLog);
+}
+
+/*
+ * Keep event logging synced with the current debug level
+ */
+void
+ModifyLogLevel(int level) {
+ debug_level = level;
+}
+
+/*
+ * Initialize logging for the port section of libbind.
+ * Piggyback onto stream given.
+ */
+void
+InitNTLogging(FILE *stream, int debug) {
+ log_stream = stream;
+ ModifyLogLevel(debug);
+}
+/*
+ * This function is for reporting errors to the application
+ * event log in case the regular syslog is not available
+ * mainly during startup. It should not be used under normal
+ * circumstances.
+ */
+void
+NTReportError(const char *name, const char *str) {
+ HANDLE hNTAppLog = NULL;
+ const char *buf[1];
+
+ buf[0] = str;
+
+ hNTAppLog = RegisterEventSource(NULL, name);
+
+ ReportEvent(hNTAppLog, EVENTLOG_ERROR_TYPE, 0,
+ BIND_ERR_MSG, NULL, 1, 0, buf, NULL);
+
+ DeregisterEventSource(hNTAppLog);
+}
diff --git a/lib/isc/win32/syslog.h b/lib/isc/win32/syslog.h
new file mode 100644
index 0000000..0197165
--- /dev/null
+++ b/lib/isc/win32/syslog.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#ifndef _SYSLOG_H
+#define _SYSLOG_H
+
+#include <stdio.h>
+
+/* Constant definitions for openlog() */
+#define LOG_PID 1
+#define LOG_CONS 2
+/* NT event log does not support facility level */
+#define LOG_KERN 0
+#define LOG_USER 0
+#define LOG_MAIL 0
+#define LOG_DAEMON 0
+#define LOG_AUTH 0
+#define LOG_SYSLOG 0
+#define LOG_LPR 0
+#define LOG_LOCAL0 0
+#define LOG_LOCAL1 0
+#define LOG_LOCAL2 0
+#define LOG_LOCAL3 0
+#define LOG_LOCAL4 0
+#define LOG_LOCAL5 0
+#define LOG_LOCAL6 0
+#define LOG_LOCAL7 0
+
+#define LOG_EMERG 0 /* system is unusable */
+#define LOG_ALERT 1 /* action must be taken immediately */
+#define LOG_CRIT 2 /* critical conditions */
+#define LOG_ERR 3 /* error conditions */
+#define LOG_WARNING 4 /* warning conditions */
+#define LOG_NOTICE 5 /* normal but signification condition */
+#define LOG_INFO 6 /* informational */
+#define LOG_DEBUG 7 /* debug-level messages */
+
+void
+syslog(int level, const char *fmt, ...);
+
+void
+openlog(const char *, int, ...);
+
+void
+closelog(void);
+
+void
+ModifyLogLevel(int level);
+
+void
+InitNTLogging(FILE *, int);
+
+void
+NTReportError(const char *, const char *);
+/*
+ * Include the event codes required for logging.
+ */
+#include <isc/bindevt.h>
+
+#endif
diff --git a/lib/isc/win32/thread.c b/lib/isc/win32/thread.c
new file mode 100644
index 0000000..ebc2f29
--- /dev/null
+++ b/lib/isc/win32/thread.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <process.h>
+
+#include <isc/thread.h>
+#include <isc/util.h>
+
+isc_result_t
+isc_thread_create(isc_threadfunc_t start, isc_threadarg_t arg,
+ isc_thread_t *threadp)
+{
+ isc_thread_t thread;
+ unsigned int id;
+
+ thread = (isc_thread_t)_beginthreadex(NULL, 0, start, arg, 0, &id);
+ if (thread == NULL) {
+ /* XXX */
+ return (ISC_R_UNEXPECTED);
+ }
+
+ *threadp = thread;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_thread_join(isc_thread_t thread, isc_threadresult_t *rp) {
+ DWORD result;
+
+ result = WaitForSingleObject(thread, INFINITE);
+ if (result != WAIT_OBJECT_0) {
+ /* XXX */
+ return (ISC_R_UNEXPECTED);
+ }
+ if (rp != NULL && !GetExitCodeThread(thread, rp)) {
+ /* XXX */
+ return (ISC_R_UNEXPECTED);
+ }
+ (void)CloseHandle(thread);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_thread_setconcurrency(unsigned int level) {
+ /*
+ * This is unnecessary on Win32 systems, but is here so that the
+ * call exists
+ */
+}
+
+void
+isc_thread_setname(isc_thread_t thread, const char *name) {
+ UNUSED(thread);
+ UNUSED(name);
+}
+
+void *
+isc_thread_key_getspecific(isc_thread_key_t key) {
+ return(TlsGetValue(key));
+}
+
+int
+isc_thread_key_setspecific(isc_thread_key_t key, void *value) {
+ return (TlsSetValue(key, value) ? 0 : GetLastError());
+}
+
+int
+isc_thread_key_create(isc_thread_key_t *key, void (*func)(void *)) {
+ *key = TlsAlloc();
+
+ return ((*key != -1) ? 0 : GetLastError());
+}
+
+int
+isc_thread_key_delete(isc_thread_key_t key) {
+ return (TlsFree(key) ? 0 : GetLastError());
+}
diff --git a/lib/isc/win32/time.c b/lib/isc/win32/time.c
new file mode 100644
index 0000000..a1c8a84
--- /dev/null
+++ b/lib/isc/win32/time.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <config.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <windows.h>
+
+#include <isc/assertions.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/tm.h>
+#include <isc/util.h>
+
+/*
+ * struct FILETIME uses "100-nanoseconds intervals".
+ * NS / S = 1000000000 (10^9).
+ * While it is reasonably obvious that this makes the needed
+ * conversion factor 10^7, it is coded this way for additional clarity.
+ */
+#define NS_PER_S 1000000000
+#define NS_INTERVAL 100
+#define INTERVALS_PER_S (NS_PER_S / NS_INTERVAL)
+
+/***
+ *** Absolute Times
+ ***/
+
+static const isc_time_t epoch = { { 0, 0 } };
+LIBISC_EXTERNAL_DATA const isc_time_t * const isc_time_epoch = &epoch;
+
+/***
+ *** Intervals
+ ***/
+
+static const isc_interval_t zero_interval = { 0 };
+LIBISC_EXTERNAL_DATA const isc_interval_t * const isc_interval_zero = &zero_interval;
+
+void
+isc_interval_set(isc_interval_t *i, unsigned int seconds,
+ unsigned int nanoseconds)
+{
+ REQUIRE(i != NULL);
+ REQUIRE(nanoseconds < NS_PER_S);
+
+ /*
+ * This rounds nanoseconds up not down.
+ */
+ i->interval = (LONGLONG)seconds * INTERVALS_PER_S
+ + (nanoseconds + NS_INTERVAL - 1) / NS_INTERVAL;
+}
+
+bool
+isc_interval_iszero(const isc_interval_t *i) {
+ REQUIRE(i != NULL);
+ if (i->interval == 0)
+ return (true);
+
+ return (false);
+}
+
+void
+isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) {
+ SYSTEMTIME epoch1970 = { 1970, 1, 4, 1, 0, 0, 0, 0 };
+ FILETIME temp;
+ ULARGE_INTEGER i1;
+
+ REQUIRE(t != NULL);
+ REQUIRE(nanoseconds < NS_PER_S);
+
+ SystemTimeToFileTime(&epoch1970, &temp);
+
+ i1.LowPart = temp.dwLowDateTime;
+ i1.HighPart = temp.dwHighDateTime;
+
+ i1.QuadPart += (unsigned __int64)nanoseconds/100;
+ i1.QuadPart += (unsigned __int64)seconds*10000000;
+
+ t->absolute.dwLowDateTime = i1.LowPart;
+ t->absolute.dwHighDateTime = i1.HighPart;
+}
+
+void
+isc_time_settoepoch(isc_time_t *t) {
+ REQUIRE(t != NULL);
+
+ t->absolute.dwLowDateTime = 0;
+ t->absolute.dwHighDateTime = 0;
+}
+
+bool
+isc_time_isepoch(const isc_time_t *t) {
+ REQUIRE(t != NULL);
+
+ if (t->absolute.dwLowDateTime == 0 &&
+ t->absolute.dwHighDateTime == 0)
+ return (true);
+
+ return (false);
+}
+
+isc_result_t
+isc_time_now(isc_time_t *t) {
+ REQUIRE(t != NULL);
+
+ GetSystemTimeAsFileTime(&t->absolute);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) {
+ ULARGE_INTEGER i1;
+
+ REQUIRE(t != NULL);
+ REQUIRE(i != NULL);
+
+ GetSystemTimeAsFileTime(&t->absolute);
+
+ i1.LowPart = t->absolute.dwLowDateTime;
+ i1.HighPart = t->absolute.dwHighDateTime;
+
+ if (UINT64_MAX - i1.QuadPart < (unsigned __int64)i->interval)
+ return (ISC_R_RANGE);
+
+ i1.QuadPart += i->interval;
+
+ t->absolute.dwLowDateTime = i1.LowPart;
+ t->absolute.dwHighDateTime = i1.HighPart;
+
+ return (ISC_R_SUCCESS);
+}
+
+int
+isc_time_compare(const isc_time_t *t1, const isc_time_t *t2) {
+ REQUIRE(t1 != NULL && t2 != NULL);
+
+ return ((int)CompareFileTime(&t1->absolute, &t2->absolute));
+}
+
+isc_result_t
+isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result)
+{
+ ULARGE_INTEGER i1;
+
+ REQUIRE(t != NULL && i != NULL && result != NULL);
+
+ i1.LowPart = t->absolute.dwLowDateTime;
+ i1.HighPart = t->absolute.dwHighDateTime;
+
+ if (UINT64_MAX - i1.QuadPart < (unsigned __int64)i->interval)
+ return (ISC_R_RANGE);
+
+ i1.QuadPart += i->interval;
+
+ result->absolute.dwLowDateTime = i1.LowPart;
+ result->absolute.dwHighDateTime = i1.HighPart;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
+ isc_time_t *result) {
+ ULARGE_INTEGER i1;
+
+ REQUIRE(t != NULL && i != NULL && result != NULL);
+
+ i1.LowPart = t->absolute.dwLowDateTime;
+ i1.HighPart = t->absolute.dwHighDateTime;
+
+ if (i1.QuadPart < (unsigned __int64) i->interval)
+ return (ISC_R_RANGE);
+
+ i1.QuadPart -= i->interval;
+
+ result->absolute.dwLowDateTime = i1.LowPart;
+ result->absolute.dwHighDateTime = i1.HighPart;
+
+ return (ISC_R_SUCCESS);
+}
+
+uint64_t
+isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2) {
+ ULARGE_INTEGER i1, i2;
+ LONGLONG i3;
+
+ REQUIRE(t1 != NULL && t2 != NULL);
+
+ i1.LowPart = t1->absolute.dwLowDateTime;
+ i1.HighPart = t1->absolute.dwHighDateTime;
+ i2.LowPart = t2->absolute.dwLowDateTime;
+ i2.HighPart = t2->absolute.dwHighDateTime;
+
+ if (i1.QuadPart <= i2.QuadPart)
+ return (0);
+
+ /*
+ * Convert to microseconds.
+ */
+ i3 = (i1.QuadPart - i2.QuadPart) / 10;
+
+ return (i3);
+}
+
+uint32_t
+isc_time_seconds(const isc_time_t *t) {
+ SYSTEMTIME epoch1970 = { 1970, 1, 4, 1, 0, 0, 0, 0 };
+ FILETIME temp;
+ ULARGE_INTEGER i1, i2;
+ LONGLONG i3;
+
+ SystemTimeToFileTime(&epoch1970, &temp);
+
+ i1.LowPart = t->absolute.dwLowDateTime;
+ i1.HighPart = t->absolute.dwHighDateTime;
+ i2.LowPart = temp.dwLowDateTime;
+ i2.HighPart = temp.dwHighDateTime;
+
+ i3 = (i1.QuadPart - i2.QuadPart) / 10000000;
+
+ return ((uint32_t)i3);
+}
+
+isc_result_t
+isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp) {
+ time_t seconds;
+
+ REQUIRE(t != NULL);
+
+ seconds = (time_t)isc_time_seconds(t);
+
+ INSIST(sizeof(unsigned int) == sizeof(uint32_t));
+ INSIST(sizeof(time_t) >= sizeof(uint32_t));
+
+ if (isc_time_seconds(t) > (~0U>>1) && seconds <= (time_t)(~0U>>1))
+ return (ISC_R_RANGE);
+
+ *secondsp = seconds;
+
+ return (ISC_R_SUCCESS);
+}
+
+
+uint32_t
+isc_time_nanoseconds(const isc_time_t *t) {
+ ULARGE_INTEGER i;
+
+ i.LowPart = t->absolute.dwLowDateTime;
+ i.HighPart = t->absolute.dwHighDateTime;
+ return ((uint32_t)(i.QuadPart % 10000000) * 100);
+}
+
+void
+isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) {
+ FILETIME localft;
+ SYSTEMTIME st;
+ char DateBuf[50];
+ char TimeBuf[50];
+
+ REQUIRE(t != NULL);
+ REQUIRE(buf != NULL);
+ REQUIRE(len > 0);
+
+ if (FileTimeToLocalFileTime(&t->absolute, &localft) &&
+ FileTimeToSystemTime(&localft, &st)) {
+ GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, "dd-MMM-yyyy",
+ DateBuf, 50);
+ GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER|
+ TIME_FORCE24HOURFORMAT, &st, NULL, TimeBuf, 50);
+
+ snprintf(buf, len, "%s %s.%03u", DateBuf, TimeBuf,
+ st.wMilliseconds);
+
+ } else {
+ strlcpy(buf, "99-Bad-9999 99:99:99.999", len);
+ }
+}
+
+void
+isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) {
+ SYSTEMTIME st;
+ char DateBuf[50];
+ char TimeBuf[50];
+
+/* strftime() format: "%a, %d %b %Y %H:%M:%S GMT" */
+
+ REQUIRE(t != NULL);
+ REQUIRE(buf != NULL);
+ REQUIRE(len > 0);
+
+ if (FileTimeToSystemTime(&t->absolute, &st)) {
+ GetDateFormat(LOCALE_USER_DEFAULT, 0, &st,
+ "ddd',' dd MMM yyyy", DateBuf, 50);
+ GetTimeFormat(LOCALE_USER_DEFAULT,
+ TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
+ &st, "hh':'mm':'ss", TimeBuf, 50);
+
+ snprintf(buf, len, "%s %s GMT", DateBuf, TimeBuf);
+ } else {
+ buf[0] = 0;
+ }
+}
+
+isc_result_t
+isc_time_parsehttptimestamp(char *buf, isc_time_t *t) {
+ struct tm t_tm;
+ time_t when;
+ char *p;
+
+ REQUIRE(buf != NULL);
+ REQUIRE(t != NULL);
+
+ p = isc_tm_strptime(buf, "%a, %d %b %Y %H:%M:%S", &t_tm);
+ if (p == NULL)
+ return (ISC_R_UNEXPECTED);
+ when = isc_tm_timegm(&t_tm);
+ if (when == -1)
+ return (ISC_R_UNEXPECTED);
+ isc_time_set(t, (unsigned int)when, 0);
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
+ SYSTEMTIME st;
+ char DateBuf[50];
+ char TimeBuf[50];
+
+ /* strtime() format: "%Y-%m-%dT%H:%M:%SZ" */
+
+ REQUIRE(t != NULL);
+ REQUIRE(buf != NULL);
+ REQUIRE(len > 0);
+
+ if (FileTimeToSystemTime(&t->absolute, &st)) {
+ GetDateFormat(LOCALE_NEUTRAL, 0, &st, "yyyy-MM-dd",
+ DateBuf, 50);
+ GetTimeFormat(LOCALE_NEUTRAL,
+ TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
+ &st, "hh':'mm':'ss", TimeBuf, 50);
+ snprintf(buf, len, "%sT%sZ", DateBuf, TimeBuf);
+ } else {
+ buf[0] = 0;
+ }
+}
+
+void
+isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len) {
+ SYSTEMTIME st;
+ char DateBuf[50];
+ char TimeBuf[50];
+
+ /* strtime() format: "%Y-%m-%dT%H:%M:%S.SSSZ" */
+
+ REQUIRE(t != NULL);
+ REQUIRE(buf != NULL);
+ REQUIRE(len > 0);
+
+ if (FileTimeToSystemTime(&t->absolute, &st)) {
+ GetDateFormat(LOCALE_NEUTRAL, 0, &st, "yyyy-MM-dd",
+ DateBuf, 50);
+ GetTimeFormat(LOCALE_NEUTRAL,
+ TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
+ &st, "hh':'mm':'ss", TimeBuf, 50);
+ snprintf(buf, len, "%sT%s.%03uZ", DateBuf, TimeBuf,
+ st.wMilliseconds);
+ } else {
+ buf[0] = 0;
+ }
+}
diff --git a/lib/isc/win32/unistd.h b/lib/isc/win32/unistd.h
new file mode 100644
index 0000000..170577e
--- /dev/null
+++ b/lib/isc/win32/unistd.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+/* None of these are defined in NT, so define them for our use */
+#define O_NONBLOCK 1
+#define PORT_NONBLOCK O_NONBLOCK
+
+/*
+ * fcntl() commands
+ */
+#define F_SETFL 0
+#define F_GETFL 1
+#define F_SETFD 2
+#define F_GETFD 3
+/*
+ * Enough problems not having full fcntl() without worrying about this!
+ */
+#undef F_DUPFD
+
+int fcntl(int, int, ...);
+
+/*
+ * access() related definitions for winXP
+ */
+#include <io.h>
+#ifndef F_OK
+#define F_OK 0
+#endif
+
+#ifndef X_OK
+#define X_OK 1
+#endif
+
+#ifndef W_OK
+#define W_OK 2
+#endif
+
+#ifndef R_OK
+#define R_OK 4
+#endif
+
+#define access _access
+
+#include <process.h>
diff --git a/lib/isc/win32/version.c b/lib/isc/win32/version.c
new file mode 100644
index 0000000..d86c781
--- /dev/null
+++ b/lib/isc/win32/version.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+
+#include <versions.h>
+
+#include <isc/version.h>
+
+LIBISC_EXTERNAL_DATA const char isc_version[] = VERSION;
+
+LIBISC_EXTERNAL_DATA const unsigned int isc_libinterface = LIBINTERFACE;
+LIBISC_EXTERNAL_DATA const unsigned int isc_librevision = LIBREVISION;
+LIBISC_EXTERNAL_DATA const unsigned int isc_libage = LIBAGE;
diff --git a/lib/isc/win32/win32os.c b/lib/isc/win32/win32os.c
new file mode 100644
index 0000000..9af95c8
--- /dev/null
+++ b/lib/isc/win32/win32os.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <windows.h>
+
+#ifndef TESTVERSION
+#include <isc/win32os.h>
+#else
+#include <stdio.h>
+#include <isc/util.h>
+#endif
+#include <isc/print.h>
+
+int
+isc_win32os_versioncheck(unsigned int major, unsigned int minor,
+ unsigned int spmajor, unsigned int spminor)
+{
+ OSVERSIONINFOEX osVer;
+ DWORD typeMask;
+ ULONGLONG conditionMask;
+
+ memset(&osVer, 0, sizeof(OSVERSIONINFOEX));
+ osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ typeMask = 0;
+ conditionMask = 0;
+
+ /* Optimistic: likely greater */
+ osVer.dwMajorVersion = major;
+ typeMask |= VER_MAJORVERSION;
+ conditionMask = VerSetConditionMask(conditionMask,
+ VER_MAJORVERSION,
+ VER_GREATER);
+ osVer.dwMinorVersion = minor;
+ typeMask |= VER_MINORVERSION;
+ conditionMask = VerSetConditionMask(conditionMask,
+ VER_MINORVERSION,
+ VER_GREATER);
+ osVer.wServicePackMajor = spmajor;
+ typeMask |= VER_SERVICEPACKMAJOR;
+ conditionMask = VerSetConditionMask(conditionMask,
+ VER_SERVICEPACKMAJOR,
+ VER_GREATER);
+ osVer.wServicePackMinor = spminor;
+ typeMask |= VER_SERVICEPACKMINOR;
+ conditionMask = VerSetConditionMask(conditionMask,
+ VER_SERVICEPACKMINOR,
+ VER_GREATER);
+ if (VerifyVersionInfo(&osVer, typeMask, conditionMask))
+ return (1);
+
+ /* Failed: retry with equal */
+ conditionMask = 0;
+ conditionMask = VerSetConditionMask(conditionMask,
+ VER_MAJORVERSION,
+ VER_EQUAL);
+ conditionMask = VerSetConditionMask(conditionMask,
+ VER_MINORVERSION,
+ VER_EQUAL);
+ conditionMask = VerSetConditionMask(conditionMask,
+ VER_SERVICEPACKMAJOR,
+ VER_EQUAL);
+ conditionMask = VerSetConditionMask(conditionMask,
+ VER_SERVICEPACKMINOR,
+ VER_EQUAL);
+ if (VerifyVersionInfo(&osVer, typeMask, conditionMask))
+ return (0);
+ else
+ return (-1);
+}
+
+#ifdef TESTVERSION
+int
+main(int argc, char **argv) {
+ unsigned int major = 0;
+ unsigned int minor = 0;
+ unsigned int spmajor = 0;
+ unsigned int spminor = 0;
+ int ret;
+
+ if (argc > 1) {
+ --argc;
+ ++argv;
+ major = (unsigned int) atoi(argv[0]);
+ }
+ if (argc > 1) {
+ --argc;
+ ++argv;
+ minor = (unsigned int) atoi(argv[0]);
+ }
+ if (argc > 1) {
+ --argc;
+ ++argv;
+ spmajor = (unsigned int) atoi(argv[0]);
+ }
+ if (argc > 1) {
+ --argc;
+ POST(argc);
+ ++argv;
+ spminor = (unsigned int) atoi(argv[0]);
+ }
+
+ ret = isc_win32os_versioncheck(major, minor, spmajor, spminor);
+
+ printf("%s major %u minor %u SP major %u SP minor %u\n",
+ ret > 0 ? "greater" : (ret == 0 ? "equal" : "less"),
+ major, minor, spmajor, spminor);
+ return (ret);
+}
+#endif