summaryrefslogtreecommitdiffstats
path: root/lib/isc/win32
diff options
context:
space:
mode:
Diffstat (limited to 'lib/isc/win32')
-rw-r--r--lib/isc/win32/DLLMain.c58
-rw-r--r--lib/isc/win32/Makefile.in40
-rw-r--r--lib/isc/win32/app.c260
-rw-r--r--lib/isc/win32/condition.c258
-rw-r--r--lib/isc/win32/dir.c312
-rw-r--r--lib/isc/win32/entropy.c307
-rw-r--r--lib/isc/win32/errno2result.c113
-rw-r--r--lib/isc/win32/errno2result.h40
-rw-r--r--lib/isc/win32/file.c507
-rw-r--r--lib/isc/win32/fsaccess.c375
-rw-r--r--lib/isc/win32/include/Makefile.in25
-rw-r--r--lib/isc/win32/include/isc/Makefile.in38
-rw-r--r--lib/isc/win32/include/isc/bind_registry.h50
-rw-r--r--lib/isc/win32/include/isc/bindevt.h91
-rw-r--r--lib/isc/win32/include/isc/condition.h67
-rw-r--r--lib/isc/win32/include/isc/dir.h83
-rw-r--r--lib/isc/win32/include/isc/int.h56
-rw-r--r--lib/isc/win32/include/isc/ipv6.h124
-rw-r--r--lib/isc/win32/include/isc/keyboard.h47
-rw-r--r--lib/isc/win32/include/isc/mutex.h55
-rw-r--r--lib/isc/win32/include/isc/net.h346
-rw-r--r--lib/isc/win32/include/isc/netdb.h54
-rw-r--r--lib/isc/win32/include/isc/ntgroups.h35
-rw-r--r--lib/isc/win32/include/isc/ntpaths.h71
-rw-r--r--lib/isc/win32/include/isc/offset.h44
-rw-r--r--lib/isc/win32/include/isc/once.h43
-rw-r--r--lib/isc/win32/include/isc/platform.h101
-rw-r--r--lib/isc/win32/include/isc/stat.h46
-rw-r--r--lib/isc/win32/include/isc/stdtime.h58
-rw-r--r--lib/isc/win32/include/isc/strerror.h42
-rw-r--r--lib/isc/win32/include/isc/syslog.h45
-rw-r--r--lib/isc/win32/include/isc/thread.h100
-rw-r--r--lib/isc/win32/include/isc/time.h291
-rw-r--r--lib/isc/win32/include/isc/win32os.h71
-rw-r--r--lib/isc/win32/interfaceiter.c500
-rw-r--r--lib/isc/win32/ipv6.c27
-rw-r--r--lib/isc/win32/keyboard.c89
-rw-r--r--lib/isc/win32/libisc.def542
-rw-r--r--lib/isc/win32/libisc.dsp780
-rw-r--r--lib/isc/win32/libisc.dsw29
-rw-r--r--lib/isc/win32/libisc.mak1982
-rw-r--r--lib/isc/win32/net.c332
-rw-r--r--lib/isc/win32/netdb.h187
-rw-r--r--lib/isc/win32/ntgroups.c186
-rw-r--r--lib/isc/win32/ntpaths.c140
-rw-r--r--lib/isc/win32/once.c54
-rw-r--r--lib/isc/win32/os.c45
-rw-r--r--lib/isc/win32/resource.c72
-rw-r--r--lib/isc/win32/socket.c3658
-rw-r--r--lib/isc/win32/stdio.c117
-rw-r--r--lib/isc/win32/stdtime.c37
-rw-r--r--lib/isc/win32/strerror.c459
-rw-r--r--lib/isc/win32/syslog.c181
-rw-r--r--lib/isc/win32/syslog.h76
-rw-r--r--lib/isc/win32/thread.c90
-rw-r--r--lib/isc/win32/time.c295
-rw-r--r--lib/isc/win32/unistd.h53
-rw-r--r--lib/isc/win32/version.c28
-rw-r--r--lib/isc/win32/win32os.c101
59 files changed, 14313 insertions, 0 deletions
diff --git a/lib/isc/win32/DLLMain.c b/lib/isc/win32/DLLMain.c
new file mode 100644
index 0000000..ed84fcf
--- /dev/null
+++ b/lib/isc/win32/DLLMain.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: DLLMain.c,v 1.7 2007/06/18 23:47:49 tbox Exp $ */
+
+#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..5c71dff
--- /dev/null
+++ b/lib/isc/win32/Makefile.in
@@ -0,0 +1,40 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-2001 Internet Software Consortium.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# $Id: Makefile.in,v 1.11 2007/06/19 23:47:19 tbox Exp $
+
+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@ file.@O@ fsaccess.@O@ once.@O@ \
+ stdtime.@O@ thread.@O@ time.@O@
+
+# Alphabetically
+SRCS = condition.c dir.c file.c once.c fsaccess.c \
+ stdtime.c thread.c time.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..b0db90d
--- /dev/null
+++ b/lib/isc/win32/app.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: app.c,v 1.7 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <process.h>
+
+#include <isc/app.h>
+#include <isc/boolean.h>
+#include <isc/condition.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>
+
+static isc_eventlist_t on_run;
+static isc_mutex_t lock;
+static isc_boolean_t shutdown_requested = ISC_FALSE;
+static isc_boolean_t running = ISC_FALSE;
+/*
+ * We assume that 'want_shutdown' can be read and written atomically.
+ */
+static isc_boolean_t want_shutdown = ISC_FALSE;
+/*
+ * We assume that 'want_reload' can be read and written atomically.
+ */
+static isc_boolean_t want_reload = ISC_FALSE;
+
+static isc_boolean_t blocked = ISC_FALSE;
+
+static isc_thread_t blockedthread;
+
+/* Events to wait for */
+
+#define NUM_EVENTS 2
+
+enum {
+ RELOAD_EVENT,
+ SHUTDOWN_EVENT
+};
+
+static HANDLE hEvents[NUM_EVENTS];
+DWORD dwWaitResult;
+
+/*
+ * We need to remember which thread is the main thread...
+ */
+static isc_thread_t main_thread;
+
+isc_result_t
+isc_app_start(void) {
+ isc_result_t result;
+
+ /*
+ * Start an ISC library application.
+ */
+
+ main_thread = GetCurrentThread();
+
+ result = isc_mutex_init(&lock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /* Create the reload event in a non-signaled state */
+ hEvents[RELOAD_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ /* Create the shutdown event in a non-signaled state */
+ hEvents[SHUTDOWN_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ ISC_LIST_INIT(on_run);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
+ void *arg) {
+ isc_event_t *event;
+ isc_task_t *cloned_task = NULL;
+ isc_result_t result;
+
+
+ LOCK(&lock);
+ if (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_LIST_APPEND(on_run, event, ev_link);
+ result = ISC_R_SUCCESS;
+
+ unlock:
+ UNLOCK(&lock);
+ return (result);
+}
+
+isc_result_t
+isc_app_run(void) {
+ isc_event_t *event, *next_event;
+ isc_task_t *task;
+ HANDLE *pHandles = NULL;
+
+ REQUIRE(main_thread == GetCurrentThread());
+ LOCK(&lock);
+ if (!running) {
+ running = ISC_TRUE;
+
+ /*
+ * Post any on-run events (in FIFO order).
+ */
+ for (event = ISC_LIST_HEAD(on_run);
+ event != NULL;
+ event = next_event) {
+ next_event = ISC_LIST_NEXT(event, ev_link);
+ ISC_LIST_UNLINK(on_run, event, ev_link);
+ task = event->ev_sender;
+ event->ev_sender = NULL;
+ isc_task_sendanddetach(&task, &event);
+ }
+
+ }
+
+ UNLOCK(&lock);
+
+ /*
+ * There is no danger if isc_app_shutdown() is called before we wait
+ * for events.
+ */
+
+ while (!want_shutdown) {
+ dwWaitResult = WaitForMultipleObjects(NUM_EVENTS, 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:
+ want_reload = ISC_TRUE;
+ break;
+
+ case SHUTDOWN_EVENT:
+ want_shutdown = ISC_TRUE;
+ break;
+ }
+ }
+ if (want_reload) {
+ want_reload = ISC_FALSE;
+ return (ISC_R_RELOAD);
+ }
+
+ if (want_shutdown && blocked)
+ exit(-1);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_app_shutdown(void) {
+ isc_boolean_t want_kill = ISC_TRUE;
+
+ LOCK(&lock);
+ REQUIRE(running);
+
+ if (shutdown_requested)
+ want_kill = ISC_FALSE; /* We're only signaling once */
+ else
+ shutdown_requested = ISC_TRUE;
+
+ UNLOCK(&lock);
+ if (want_kill)
+ SetEvent(hEvents[SHUTDOWN_EVENT]);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_app_reload(void) {
+ isc_boolean_t want_reload = ISC_TRUE;
+
+ LOCK(&lock);
+ REQUIRE(running);
+
+ /*
+ * Don't send the reload signal if we're shutting down.
+ */
+ if (shutdown_requested)
+ want_reload = ISC_FALSE;
+
+ UNLOCK(&lock);
+ if (want_reload)
+ SetEvent(hEvents[RELOAD_EVENT]);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_app_finish(void) {
+ DESTROYLOCK(&lock);
+}
+
+void
+isc_app_block(void) {
+ REQUIRE(running);
+ REQUIRE(!blocked);
+
+ blocked = ISC_TRUE;
+ blockedthread = GetCurrentThread();
+}
+
+void
+isc_app_unblock(void) {
+ REQUIRE(running);
+ REQUIRE(blocked);
+ blocked = ISC_FALSE;
+ REQUIRE(blockedthread == GetCurrentThread());
+}
diff --git a/lib/isc/win32/condition.c b/lib/isc/win32/condition.c
new file mode 100644
index 0000000..27d4e76
--- /dev/null
+++ b/lib/isc/win32/condition.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: condition.c,v 1.23 2007/06/18 23:47:49 tbox Exp $ */
+
+#include <config.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_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;
+ isc_boolean_t failed = ISC_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 = ISC_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;
+ isc_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..93cc650
--- /dev/null
+++ b/lib/isc/win32/dir.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dir.c,v 1.16 2008/11/02 23:47:01 tbox Exp $ */
+
+/* Principal Authors: DCL */
+
+#include <config.h>
+
+#include <string.h>
+#include <direct.h>
+#include <process.h>
+#include <io.h>
+
+#include <sys/stat.h>
+
+#include <isc/dir.h>
+#include <isc/magic.h>
+#include <isc/assertions.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 = ISC_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);
+ strcpy(dir->dirname, 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 = ISC_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 occured. 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.
+ */
+ strcpy(dir->entry.name, dir->entry.find_data.cFileName);
+ 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 = ISC_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.
+ */
+ strcpy(dir->entry.name, dir->entry.find_data.cFileName);
+ dir->entry.length = strlen(dir->entry.name);
+
+ dir->entry_filled = ISC_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);
+ 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..a505ab3
--- /dev/null
+++ b/lib/isc/win32/entropy.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: entropy.c,v 1.8 2007/06/19 23:47:19 tbox Exp $ */
+
+/*
+ * This is the system depenedent part of the ISC entropy API.
+ */
+
+#include <config.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, isc_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, ndesired, buf)) {
+ CryptReleaseContext(hcryptprov, 0);
+ source->bad = ISC_TRUE;
+ goto out;
+ }
+
+ entropypool_adddata(ent, buf, ndesired, ndesired * 8);
+ added += ndesired * 8;
+ desired -= 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, isc_boolean_t 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;
+ DWORD errval;
+ 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){
+ errval = 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 = ISC_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/errno2result.c b/lib/isc/win32/errno2result.c
new file mode 100644
index 0000000..c3d54d6
--- /dev/null
+++ b/lib/isc/win32/errno2result.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: errno2result.c,v 1.17 2008/09/12 04:46:25 marka Exp $ */
+
+#include <config.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, 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);
+ 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:
+ 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..41682db
--- /dev/null
+++ b/lib/isc/win32/errno2result.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: errno2result.h,v 1.10 2007/06/19 23:47:19 tbox Exp $ */
+
+#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 <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+#define isc__errno2result(posixerrno) \
+ isc__errno2resultx(posixerrno, __FILE__, __LINE__)
+
+isc_result_t
+isc__errno2resultx(int posixerrno, 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..baf7953
--- /dev/null
+++ b/lib/isc/win32/file.c
@@ -0,0 +1,507 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: file.c,v 1.31 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#undef rename
+#include <errno.h>
+#include <limits.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/result.h>
+#include <isc/time.h>
+#include <isc/util.h>
+#include <isc/stat.h>
+
+#include "errno2result.h"
+
+/*
+ * Emulate UNIX mkstemp, which returns an open FD to the new file
+ *
+ */
+static int
+gettemp(char *path, int *doopen) {
+ char *start, *trv;
+ struct stat sbuf;
+ int pid;
+
+ trv = strrchr(path, 'X');
+ trv++;
+ pid = getpid();
+ /* extra X's get set to 0's */
+ while (*--trv == 'X') {
+ *trv = (pid % 10) + '0';
+ pid /= 10;
+ }
+ /*
+ * 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, O_CREAT|O_EXCL|O_RDWR,
+ _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) {
+ int fd;
+
+ return (gettemp(path, &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);
+}
+
+/*
+ * 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;
+ strcpy(buf, newname);
+ strcat(buf, ".XXXXX");
+ tmpfd = mkstemp(buf);
+ if (tmpfd > 0)
+ _close(tmpfd);
+ 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)
+ filestatus = 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_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(path != NULL);
+ REQUIRE(templet != NULL);
+ REQUIRE(buf != NULL);
+
+ s = strrchr(templet, '\\');
+ if (s != NULL)
+ templet = s + 1;
+
+ s = strrchr(path, '\\');
+
+ if (s != NULL) {
+ if ((s - path + 1 + strlen(templet) + 1) > buflen)
+ return (ISC_R_NOSPACE);
+
+ strncpy(buf, path, s - path + 1);
+ buf[s - path + 1] = '\0';
+ strcat(buf, templet);
+ } else {
+ if ((strlen(templet) + 1) > buflen)
+ return (ISC_R_NOSPACE);
+
+ strcpy(buf, templet);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_renameunique(const char *file, char *templet) {
+ int fd = -1;
+ int res = 0;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(file != NULL);
+ REQUIRE(templet != NULL);
+
+ fd = mkstemp(templet);
+ 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);
+}
+
+isc_result_t
+isc_file_openunique(char *templet, 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);
+
+ if (fd == -1)
+ result = isc__errno2result(errno);
+ if (result == ISC_R_SUCCESS) {
+ f = fdopen(fd, "w+");
+ if (f == NULL) {
+ result = isc__errno2result(errno);
+ (void)remove(templet);
+ (void)close(fd);
+ } else
+ *fp = f;
+ }
+
+ return (result);
+}
+
+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));
+}
+
+isc_boolean_t
+isc_file_exists(const char *pathname) {
+ struct stat stats;
+
+ REQUIRE(pathname != NULL);
+
+ return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS));
+}
+
+isc_boolean_t
+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 (ISC_TRUE);
+ if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '\\')
+ return (ISC_TRUE);
+ if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '/')
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+isc_file_iscurrentdir(const char *filename) {
+ REQUIRE(filename != NULL);
+ return (ISC_TF(filename[0] == '.' && filename[1] == '\0'));
+}
+
+isc_boolean_t
+isc_file_ischdiridempotent(const char *filename) {
+ REQUIRE(filename != NULL);
+
+ if (isc_file_isabsolute(filename))
+ return (ISC_TRUE);
+ if (filename[0] == '\\')
+ return (ISC_TRUE);
+ if (filename[0] == '/')
+ return (ISC_TRUE);
+ if (isc_file_iscurrentdir(filename))
+ return (ISC_TRUE);
+ return (ISC_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;
+ 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);
+
+ strcpy(progname, s);
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Copy the result to the buffer
+ */
+ len = p - s;
+ if (len >= namelen)
+ return (ISC_R_NOSPACE);
+
+ strncpy(progname, s, len);
+ progname[len] = '\0';
+ 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, 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);
+}
diff --git a/lib/isc/win32/fsaccess.c b/lib/isc/win32/fsaccess.c
new file mode 100644
index 0000000..8de793f
--- /dev/null
+++ b/lib/isc/win32/fsaccess.c
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: fsaccess.c,v 1.15 2007/06/19 23:47:19 tbox Exp $ */
+
+/*
+ * 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 <isc/file.h>
+#include <isc/stat.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] == '/')) {
+ strncpy(drive, filename, 3);
+ drive[3] = '\0';
+ }
+
+ else if ((filename[0] == '\\') && (filename[1] == '\\')) {
+ /* Find the machine and share name and rebuild the UNC */
+ strcpy(tmpbuf, filename);
+ machinename = strtok(tmpbuf, "\\");
+ sharename = strtok(NULL, "\\");
+ strcpy(drive, "\\\\");
+ strcat(drive, machinename);
+ strcat(drive, "\\");
+ strcat(drive, sharename);
+ strcat(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,
+ isc_boolean_t 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;
+ int errval;
+ 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)) {
+ errval = GetLastError();
+ return (ISC_R_NOPERM);
+ }
+ domainBufferSize = sizeof(domainBuffer);
+ if (!LookupAccountName(0, "Everyone", pothersid,
+ &otherSidBufferSize, domainBuffer, &domainBufferSize, &snu)) {
+ errval = 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 == ISC_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,
+ isc_boolean_t 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;
+ isc_boolean_t is_dir = ISC_FALSE;
+ isc_result_t result;
+
+ if (stat(path, &statb) != 0)
+ return (isc__errno2result(errno));
+
+ if ((statb.st_mode & S_IFDIR) != 0)
+ is_dir = ISC_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..c74b52d
--- /dev/null
+++ b/lib/isc/win32/include/Makefile.in
@@ -0,0 +1,25 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-2001 Internet Software Consortium.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# $Id: Makefile.in,v 1.9 2007/06/19 23:47:19 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isc
+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..dcd8519
--- /dev/null
+++ b/lib/isc/win32/include/isc/Makefile.in
@@ -0,0 +1,38 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-2001 Internet Software Consortium.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# $Id: Makefile.in,v 1.11 2007/06/19 23:47:20 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+HEADERS = dir.h int.h mutex.h net.h netdb.h once.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 ; \
+ done
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..c4dc876
--- /dev/null
+++ b/lib/isc/win32/include/isc/bind_registry.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: bind_registry.h,v 1.8 2007/06/19 23:47:20 tbox Exp $ */
+
+#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..72cf2d1
--- /dev/null
+++ b/lib/isc/win32/include/isc/bindevt.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: bindevt.h,v 1.6 2007/06/19 23:47:20 tbox Exp $ */
+
+#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..34015bc
--- /dev/null
+++ b/lib/isc/win32/include/isc/condition.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: condition.h,v 1.17 2007/06/18 23:47:49 tbox Exp $ */
+
+#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..653427a
--- /dev/null
+++ b/lib/isc/win32/include/isc/dir.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dir.h,v 1.15 2007/06/19 23:47:20 tbox Exp $ */
+
+/* Principal Authors: DCL */
+
+#ifndef ISC_DIR_H
+#define ISC_DIR_H 1
+
+#include <windows.h>
+#include <stdlib.h>
+
+#include <isc/lang.h>
+#include <isc/boolean.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;
+ isc_boolean_t 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/int.h b/lib/isc/win32/include/isc/int.h
new file mode 100644
index 0000000..2ee8bf9
--- /dev/null
+++ b/lib/isc/win32/include/isc/int.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: int.h,v 1.13 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_INT_H
+#define ISC_INT_H 1
+
+#define _INTEGRAL_MAX_BITS 64
+#include <limits.h>
+
+typedef __int8 isc_int8_t;
+typedef unsigned __int8 isc_uint8_t;
+typedef __int16 isc_int16_t;
+typedef unsigned __int16 isc_uint16_t;
+typedef __int32 isc_int32_t;
+typedef unsigned __int32 isc_uint32_t;
+typedef __int64 isc_int64_t;
+typedef unsigned __int64 isc_uint64_t;
+
+#define ISC_INT8_MIN -128
+#define ISC_INT8_MAX 127
+#define ISC_UINT8_MAX 255
+
+#define ISC_INT16_MIN -32768
+#define ISC_INT16_MAX 32767
+#define ISC_UINT16_MAX 65535
+
+/*
+ * Note that "int" is 32 bits on all currently supported Unix-like operating
+ * systems, but "long" can be either 32 bits or 64 bits, thus the 32 bit
+ * constants are not qualified with "L".
+ */
+#define ISC_INT32_MIN _I32_MIN
+#define ISC_INT32_MAX _I32_MAX
+#define ISC_UINT32_MAX _UI32_MAX
+
+#define ISC_INT64_MIN _I64_MIN
+#define ISC_INT64_MAX _I64_MAX
+#define ISC_UINT64_MAX _UI64_MAX
+
+#endif /* ISC_INT_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..c9add0b
--- /dev/null
+++ b/lib/isc/win32/include/isc/ipv6.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ipv6.h,v 1.19 2007/06/18 23:47:49 tbox Exp $ */
+
+#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
+
+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) (\
+(*((u_long *)((a)->s6_addr) ) == 0xfe) && \
+((*((u_long *)((a)->s6_addr) + 1) & 0xc0) == 0x80))
+#endif
+
+#ifndef IN6_IS_ADDR_SITELOCAL
+#define IN6_IS_ADDR_SITELOCAL(a) (\
+(*((u_long *)((a)->s6_addr) ) == 0xfe) && \
+((*((u_long *)((a)->s6_addr) + 1) & 0xc0) == 0xc0))
+#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..e781c5f
--- /dev/null
+++ b/lib/isc/win32/include/isc/keyboard.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: keyboard.h,v 1.6 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_KEYBOARD_H
+#define ISC_KEYBOARD_H 1
+
+#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);
+
+isc_boolean_t
+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..e5320c3
--- /dev/null
+++ b/lib/isc/win32/include/isc/mutex.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: mutex.h,v 1.20 2008/09/12 04:46:25 marka Exp $ */
+
+#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 somve 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..a89bce0
--- /dev/null
+++ b/lib/isc/win32/include/isc/net.h
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: net.h,v 1.30 2008/07/01 23:47:17 tbox Exp $ */
+
+#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 <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_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 isc_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) ((isc_uint32_t)htonl((isc_uint32_t)(x)))
+
+#define ISC_IPADDR_ISMULTICAST(i) \
+ (((isc_uint32_t)(i) & ISC__IPADDR(0xf0000000)) \
+ == ISC__IPADDR(0xe0000000))
+
+#define ISC_IPADDR_ISEXPERIMENTAL(i) \
+ (((isc_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.
+ */
+
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define EINPROGRESS WSAEINPROGRESS
+#define EALREADY WSAEALREADY
+#define ENOTSOCK WSAENOTSOCK
+#define EDESTADDRREQ WSAEDESTADDRREQ
+#define EMSGSIZE WSAEMSGSIZE
+#define EPROTOTYPE WSAEPROTOTYPE
+#define ENOPROTOOPT WSAENOPROTOOPT
+#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+#define EOPNOTSUPP WSAEOPNOTSUPP
+#define EPFNOSUPPORT WSAEPFNOSUPPORT
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#define EADDRINUSE WSAEADDRINUSE
+#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#define ENETDOWN WSAENETDOWN
+#define ENETUNREACH WSAENETUNREACH
+#define ENETRESET WSAENETRESET
+#define ECONNABORTED WSAECONNABORTED
+#define ECONNRESET WSAECONNRESET
+#define ENOBUFS WSAENOBUFS
+#define EISCONN WSAEISCONN
+#define ENOTCONN WSAENOTCONN
+#define ESHUTDOWN WSAESHUTDOWN
+#define ETOOMANYREFS WSAETOOMANYREFS
+#define ETIMEDOUT WSAETIMEDOUT
+#define ECONNREFUSED WSAECONNREFUSED
+#define ELOOP WSAELOOP
+#define EHOSTDOWN WSAEHOSTDOWN
+#define EHOSTUNREACH WSAEHOSTUNREACH
+#define EPROCLIM WSAEPROCLIM
+#define EUSERS WSAEUSERS
+#define EDQUOT WSAEDQUOT
+#define ESTALE WSAESTALE
+#define EREMOTE WSAEREMOTE
+
+
+/***
+ *** 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
+ */
+
+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);
+#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
+
+#ifdef ISC_PLATFORM_NEEDATON
+int
+isc_net_aton(const char *cp, struct in_addr *addr);
+#define inet_aton isc_net_aton
+#endif
+
+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..6625afd
--- /dev/null
+++ b/lib/isc/win32/include/isc/netdb.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: netdb.h,v 1.9 2007/06/19 23:47:20 tbox Exp $ */
+
+#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..b4cd020
--- /dev/null
+++ b/lib/isc/win32/include/isc/ntgroups.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ntgroups.h,v 1.5 2007/06/19 23:47:20 tbox Exp $ */
+
+#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..7cd185a
--- /dev/null
+++ b/lib/isc/win32/include/isc/ntpaths.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ntpaths.h,v 1.16 2007/06/19 23:47:20 tbox Exp $ */
+
+/*
+ * 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,
+ LOCAL_STATE_DIR,
+ SYS_CONF_DIR,
+ RNDC_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 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..f22fdce
--- /dev/null
+++ b/lib/isc/win32/include/isc/offset.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: offset.h,v 1.6 2007/06/19 23:47:20 tbox Exp $ */
+
+#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;
+
+/*
+ * POSIX says "Additionally, blkcnt_t and off_t are extended signed integral
+ * types", so the maximum value is all 1s except for the high bit.
+ * This definition is more complex than it really needs to be because it was
+ * crafted to keep both the SunOS 5.6 and the HP/UX 11 compilers quiet about
+ * integer overflow. For example, though this is equivalent to just left
+ * shifting 1 to the high bit and then inverting the bits, the SunOS compiler
+ * is unhappy about shifting a positive "1" to negative in a signed integer.
+ */
+#define ISC_OFFSET_MAXIMUM \
+ (~(((off_t)-1 >> (sizeof(off_t) * CHAR_BIT - 1)) \
+ << (sizeof(off_t) * CHAR_BIT - 1)))
+
+#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..32af1bd
--- /dev/null
+++ b/lib/isc/win32/include/isc/once.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: once.h,v 1.9 2007/06/19 23:47:20 tbox Exp $ */
+
+#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 b/lib/isc/win32/include/isc/platform.h
new file mode 100644
index 0000000..b3426e5
--- /dev/null
+++ b/lib/isc/win32/include/isc/platform.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: platform.h,v 1.16 2008/04/02 23:46:58 tbox Exp $ */
+
+#ifndef ISC_PLATFORM_H
+#define ISC_PLATFORM_H 1
+
+/*****
+ ***** Platform-dependent defines.
+ *****/
+
+#define ISC_PLATFORM_USETHREADS
+
+/***
+ *** Network.
+ ***/
+
+#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_NEEDATON
+
+#define ISC_PLATFORM_QUADFORMAT "I64"
+
+#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
+
+ /*
+ * 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 LIBISCCFG_EXPORTS
+#define LIBISCCFG_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISCCFG_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#ifdef LIBISCCC_EXPORTS
+#define LIBISCCC_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISCCC_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#ifdef LIBDNS_EXPORTS
+#define LIBDNS_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBDNS_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#ifdef LIBBIND9_EXPORTS
+#define LIBBIND9_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBBIND9_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..2638a91
--- /dev/null
+++ b/lib/isc/win32/include/isc/stat.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: stat.h,v 1.7 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_STAT_H
+#define ISC_STAT_H 1
+
+#include <sys/stat.h>
+
+/* 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_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..4f9eb74
--- /dev/null
+++ b/lib/isc/win32/include/isc/stdtime.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: stdtime.h,v 1.12 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_STDTIME_H
+#define ISC_STDTIME_H 1
+
+#include <isc/lang.h>
+#include <isc/int.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 isc_uint32_t isc_stdtime_t;
+/*
+ * 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 isc_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..38d2ef2
--- /dev/null
+++ b/lib/isc/win32/include/isc/strerror.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: strerror.h,v 1.5 2007/06/19 23:47:20 tbox Exp $ */
+
+#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..765c0e5
--- /dev/null
+++ b/lib/isc/win32/include/isc/syslog.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: syslog.h,v 1.5 2007/06/19 23:47:20 tbox Exp $ */
+
+#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..78e663f
--- /dev/null
+++ b/lib/isc/win32/include/isc/thread.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: thread.h,v 1.22 2007/06/19 23:47:20 tbox Exp $ */
+
+#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 retrun 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 unsigned int 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);
+
+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);
+
+int
+isc_thread_key_setspecific(isc_thread_key_t key, void *value);
+
+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..af0cddb
--- /dev/null
+++ b/lib/isc/win32/include/isc/time.h
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2004, 2006-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: time.h,v 1.33 2008/09/08 23:47:10 tbox Exp $ */
+
+#ifndef ISC_TIME_H
+#define ISC_TIME_H 1
+
+#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 {
+ isc_int64_t interval;
+};
+
+LIBISC_EXTERNAL_DATA extern isc_interval_t *isc_interval_zero;
+
+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.
+ */
+
+isc_boolean_t
+isc_interval_iszero(const isc_interval_t *i);
+/*
+ * Returns ISC_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 isc_time_t *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.
+ */
+
+isc_boolean_t
+isc_time_isepoch(const isc_time_t *t);
+/*
+ * Returns ISC_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.
+ */
+
+isc_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_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 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
+ *
+ */
+
+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
+ *
+ */
+
+isc_uint32_t
+isc_time_seconds(const isc_time_t *t);
+
+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..d868205
--- /dev/null
+++ b/lib/isc/win32/include/isc/win32os.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: win32os.h,v 1.5 2007/06/19 23:47:20 tbox Exp $ */
+
+#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.
+ */
+
+unsigned int
+isc_win32os_majorversion(void);
+/*
+ * Major Version of the O/S.
+ */
+
+unsigned int
+isc_win32os_minorversion(void);
+/*
+ * Minor Version of the O/S.
+ */
+
+unsigned int
+isc_win32os_servicepackmajor(void);
+/*
+ * Major Version of the Service Pack for O/S.
+ */
+
+unsigned int
+isc_win32os_servicepackminor(void);
+/*
+ * Minor Version of the Service Pack for O/S.
+ */
+
+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_OS_H */
diff --git a/lib/isc/win32/interfaceiter.c b/lib/isc/win32/interfaceiter.c
new file mode 100644
index 0000000..1451249
--- /dev/null
+++ b/lib/isc/win32/interfaceiter.c
@@ -0,0 +1,500 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: interfaceiter.c,v 1.13 2008/04/18 19:47:48 each Exp $ */
+
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <isc/interfaceiter.h>
+#include <isc/mem.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 explicity
+ * 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;
+ int 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;
+ unsigned int buf6size; /* Bytes allocated. */
+ unsigned int pos6;
+ 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:
+ memcpy(&dst->type.in,
+ &((struct sockaddr_in *) src)->sin_addr,
+ sizeof(struct in_addr));
+ break;
+ case AF_INET6:
+ memcpy(&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->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.
+ */
+ if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ 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.
+ */
+ if ((iter->socket = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ 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 >= 0)
+ (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;
+ sprintf(iter->current.name, "PPP Interface %d", iter->numIF);
+ ifNamed = TRUE;
+ }
+
+ if ((flags & IFF_LOOPBACK) != 0) {
+ iter->current.flags |= INTERFACE_F_LOOPBACK;
+ sprintf(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)
+ sprintf(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) {
+ BOOL ifNamed = FALSE;
+ int i;
+
+ REQUIRE(VALID_IFITER(iter));
+ REQUIRE(iter->pos6 >= 0);
+ REQUIRE(iter->buf6 != 0);
+
+ memset(&iter->current, 0, sizeof(iter->current));
+ iter->current.af = AF_INET6;
+
+ get_addr(AF_INET6, &iter->current.address,
+ iter->buf6->Address[iter->pos6].lpSockaddr);
+
+ /*
+ * Get interface flags.
+ */
+
+ iter->current.flags = INTERFACE_F_UP;
+
+ if (ifNamed == FALSE)
+ sprintf(iter->current.name,
+ "TCP/IPv6 Interface %d", iter->pos6 + 1);
+
+ for (i = 0; i< 16; i++)
+ iter->current.netmask.type.in6.s6_addr[i] = 0xff;
+ 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));
+ memcpy(&(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 == 0)
+ return (ISC_R_NOMORE);
+ 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);
+ memcpy(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->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)
+ 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..511ae21
--- /dev/null
+++ b/lib/isc/win32/ipv6.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ipv6.c,v 1.8 2007/06/19 23:47:19 tbox Exp $ */
+
+#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..d569e7c
--- /dev/null
+++ b/lib/isc/win32/keyboard.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: keyboard.c,v 1.7 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#include <windows.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.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);
+}
+
+isc_boolean_t
+isc_keyboard_canceled(isc_keyboard_t *keyboard) {
+ return (ISC_TF(keyboard->result == ISC_R_CANCELED));
+}
+
diff --git a/lib/isc/win32/libisc.def b/lib/isc/win32/libisc.def
new file mode 100644
index 0000000..065a602
--- /dev/null
+++ b/lib/isc/win32/libisc.def
@@ -0,0 +1,542 @@
+LIBRARY libisc
+
+; Exported Functions
+EXPORTS
+
+NTReportError
+closelog
+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_invalidate
+isc__buffer_putmem
+isc__buffer_putstr
+isc__buffer_putuint16
+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__mem_allocate
+isc__mem_free
+isc__mem_get
+isc__mem_put
+isc__mem_putanddetach
+isc__mem_strdup
+isc__mempool_get
+isc__mempool_put
+isc__socketmgr_setreserved
+isc__strerror
+isc_app_block
+isc_app_finish
+isc_app_onrun
+isc_app_reload
+isc_app_run
+isc_app_shutdown
+isc_app_start
+isc_app_unblock
+isc_assertion_setcallback
+isc_assertion_typetotext
+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_base64_decodestring
+isc_base64_tobuffer
+isc_base64_totext
+isc_bitstring_copy
+isc_bitstring_init
+isc_bitstring_invalidate
+isc_buffer_allocate
+isc_buffer_compact
+isc_buffer_copyregion
+isc_buffer_free
+isc_buffer_getuint16
+isc_buffer_getuint32
+isc_buffer_getuint8
+isc_buffer_reinit
+isc_bufferlist_availablecount
+isc_bufferlist_usedcount
+isc_commandline_parse
+isc_condition_broadcast
+isc_condition_destroy
+isc_condition_init
+isc_condition_signal
+isc_condition_wait
+isc_condition_waituntil
+isc_dir_chdir
+isc_dir_chroot
+isc_dir_close
+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_error_fatal
+isc_error_runtimecheck
+isc_error_setfatal
+isc_error_setunexpected
+isc_error_unexpected
+isc_event_allocate
+isc_event_free
+isc_file_absolutepath
+isc_file_basename
+isc_file_exists
+isc_file_getmodtime
+isc_file_isabsolute
+isc_file_ischdiridempotent
+isc_file_iscurrentdir
+isc_file_mktemplate
+isc_file_openunique
+isc_file_progname
+isc_file_remove
+isc_file_rename
+isc_file_renameunique
+isc_file_safemovefile
+isc_file_settime
+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_init
+isc_heap_create
+isc_heap_decreased
+isc_heap_delete
+isc_heap_destroy
+isc_heap_element
+isc_heap_increased
+isc_heap_insert
+isc_hex_decodestring
+isc_hex_tobuffer
+isc_hex_totext
+isc_hmacmd5_init
+isc_hmacmd5_invalidate
+isc_hmacmd5_sign
+isc_hmacmd5_update
+isc_hmacmd5_verify
+isc_hmacmd5_verify2
+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_httpdmgr_addurl
+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_setspecials
+isc_lex_ungettoken
+isc_lfsr_generate
+isc_lfsr_generate32
+isc_lfsr_init
+isc_lfsr_skip
+isc_lib_initmsgcat
+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_md5_final
+isc_md5_init
+isc_md5_invalidate
+isc_md5_update
+isc_mem_attach
+isc_mem_checkdestroyed
+isc_mem_create
+isc_mem_create2
+isc_mem_createx
+isc_mem_createx2
+isc_mem_destroy
+isc_mem_detach
+isc_mem_getname
+isc_mem_getquota
+isc_mem_gettag
+isc_mem_inuse
+isc_mem_ondestroy
+isc_mem_references
+isc_mem_setdestroycheck
+isc_mem_setname
+isc_mem_setquota
+isc_mem_setwater
+isc_mem_stats
+isc_mem_waterack
+isc_mempool_associatelock
+isc_mempool_create
+isc_mempool_destroy
+isc_mempool_getallocated
+isc_mempool_getfillcount
+isc_mempool_getfreecount
+isc_mempool_getfreemax
+isc_mempool_getmaxalloc
+isc_mempool_setfillcount
+isc_mempool_setfreemax
+isc_mempool_setmaxalloc
+isc_mempool_setname
+isc_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_getudpportrange
+isc_net_ntop
+isc_net_probe_ipv6only
+isc_net_probe_ipv6pktinfo
+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_ismulticast
+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_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_detach
+isc_ratelimiter_enqueue
+isc_ratelimiter_setinterval
+isc_ratelimiter_setpertic
+isc_ratelimiter_shutdown
+isc_refcount_init
+isc_region_compare
+isc_resource_getcurlimit
+isc_resource_getlimit
+isc_resource_setlimit
+isc_result_register
+isc_result_totext
+isc_rwlock_destroy
+isc_rwlock_downgrade
+isc_rwlock_init
+isc_rwlock_lock
+isc_rwlock_trylock
+isc_rwlock_tryupgrade
+isc_rwlock_unlock
+isc_serial_eq
+isc_serial_ge
+isc_serial_gt
+isc_serial_le
+isc_serial_lt
+isc_serial_ne
+isc_sha1_final
+isc_sha1_init
+isc_sha1_invalidate
+isc_sha1_update
+isc_sha224_final
+isc_sha224_init
+isc_sha224_update
+isc_sha256_final
+isc_sha256_init
+isc_sha256_update
+isc_sha384_final
+isc_sha384_init
+isc_sha384_update
+isc_sha512_final
+isc_sha512_init
+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_ismulticast
+isc_sockaddr_pf
+isc_sockaddr_setport
+isc_sockaddr_totext
+isc_sockaddr_v6fromin
+isc_socket_accept
+isc_socket_attach
+isc_socket_bind
+isc_socket_cancel
+isc_socket_cleanunix
+isc_socket_close
+isc_socket_connect
+isc_socket_create
+isc_socket_detach
+isc_socket_filter
+isc_socket_getname
+isc_socket_getpeername
+isc_socket_getsockname
+isc_socket_gettag
+isc_socket_gettype
+isc_socket_ipv6only
+isc_socket_isbound
+isc_socket_listen
+isc_socket_open
+isc_socket_permunix
+isc_socket_recv
+isc_socket_recv2
+isc_socket_recvv
+isc_socket_send
+isc_socket_sendto
+isc_socket_sendto2
+isc_socket_sendtov
+isc_socket_sendv
+isc_socket_setname
+isc_socketmgr_create
+isc_socketmgr_create2
+isc_socketmgr_destroy
+isc_socketmgr_getmaxsockets
+isc_stdio_close
+isc_stdio_flush
+isc_stdio_open
+isc_stdio_read
+isc_stdio_seek
+isc_stdio_sync
+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_strlcat
+isc_string_strlcpy
+isc_string_touint64
+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_getcurrenttime
+isc_task_getname
+isc_task_gettag
+isc_task_onshutdown
+isc_task_purge
+isc_task_purgeevent
+isc_task_purgerange
+isc_task_send
+isc_task_sendanddetach
+isc_task_setname
+isc_task_shutdown
+isc_task_unsend
+isc_task_unsendrange
+isc_taskmgr_create
+isc_taskmgr_destroy
+isc_taskpool_create
+isc_taskpool_destroy
+isc_taskpool_gettask
+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_time_add
+isc_time_compare
+isc_time_isepoch
+isc_time_microdiff
+isc_time_nanoseconds
+isc_time_now
+isc_time_nowplusinterval
+isc_time_seconds
+isc_time_set
+isc_time_settoepoch
+isc_time_subtract
+isc_timer_attach
+isc_timer_create
+isc_timer_detach
+isc_timer_reset
+isc_timer_touch
+isc_timermgr_create
+isc_timermgr_destroy
+isc_timermgr_poke
+isc_win32os_majorversion
+isc_win32os_minorversion
+isc_win32os_servicepackmajor
+isc_win32os_servicepackminor
+isc_win32os_versioncheck
+openlog
+syslog
+
+; Exported Data
+
+EXPORTS
+
+isc_assertion_failed 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_mem_debugging DATA
+
diff --git a/lib/isc/win32/libisc.dsp b/lib/isc/win32/libisc.dsp
new file mode 100644
index 0000000..d8094cd
--- /dev/null
+++ b/lib/isc/win32/libisc.dsp
@@ -0,0 +1,780 @@
+# Microsoft Developer Studio Project File - Name="libisc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=libisc - Win32 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 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libisc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libisc - Win32 Debug" (based on "Win32 (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 - Win32 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 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "../noatomic/include" /I "win32" /I "../../isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /c
+# ADD BASE 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:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib /nologo /dll /machine:I386 /out:"../../../Build/Release/libisc.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "libisc - Win32 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 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "../noatomic/include" /I "win32" /I "../../isccfg/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR /YX /FD /GZ /c
+# ADD BASE 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:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib /nologo /dll /map /debug /machine:I386 /out:"../../../Build/Debug/libisc.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "libisc - Win32 Release"
+# Name "libisc - Win32 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=.\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=..\iterated_hash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\keyboard.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
+# Begin Source File
+
+SOURCE=.\resource.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\socket.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strerror.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=.\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
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# 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\base32.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\base64.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\bitstring.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\condition.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\config.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=.\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\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
+# 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\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\msgcat.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\msioctl.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\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\parseint.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\portset.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\os.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\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\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
+# 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\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\stdio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\strerror.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\stdtime.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\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
+# 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"
+# Begin Source File
+
+SOURCE=..\assertions.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=..\bitstring.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=..\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=..\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=..\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
+# 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=..\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=..\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=..\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=.\win32os.c
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\noatomic\include\atomic.h
+# End Source File
+# 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 b/lib/isc/win32/libisc.mak
new file mode 100644
index 0000000..ea7d32f
--- /dev/null
+++ b/lib/isc/win32/libisc.mak
@@ -0,0 +1,1982 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on libisc.dsp
+!IF "$(CFG)" == ""
+CFG=libisc - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to libisc - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "libisc - Win32 Release" && "$(CFG)" != "libisc - Win32 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 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libisc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libisc - Win32 Debug" (based on "Win32 (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
+
+!IF "$(CFG)" == "libisc - Win32 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 - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\libisc.dll"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\app.obj"
+ -@erase "$(INTDIR)\assertions.obj"
+ -@erase "$(INTDIR)\base32.obj"
+ -@erase "$(INTDIR)\base64.obj"
+ -@erase "$(INTDIR)\bitstring.obj"
+ -@erase "$(INTDIR)\buffer.obj"
+ -@erase "$(INTDIR)\bufferlist.obj"
+ -@erase "$(INTDIR)\commandline.obj"
+ -@erase "$(INTDIR)\condition.obj"
+ -@erase "$(INTDIR)\dir.obj"
+ -@erase "$(INTDIR)\DLLMain.obj"
+ -@erase "$(INTDIR)\entropy.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)\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)\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"
+ -@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)\region.obj"
+ -@erase "$(INTDIR)\resource.obj"
+ -@erase "$(INTDIR)\result.obj"
+ -@erase "$(INTDIR)\rwlock.obj"
+ -@erase "$(INTDIR)\serial.obj"
+ -@erase "$(INTDIR)\sha1.obj"
+ -@erase "$(INTDIR)\sha2.obj"
+ -@erase "$(INTDIR)\sockaddr.obj"
+ -@erase "$(INTDIR)\socket.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)\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)"
+
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/noatomic/include" /I "win32" /I "../../isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /Fp"$(INTDIR)\libisc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\libisc.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\libisc.pdb" /machine:I386 /def:".\libisc.def" /out:"../../../Build/Release/libisc.dll" /implib:"$(OUTDIR)\libisc.lib"
+DEF_FILE= \
+ ".\libisc.def"
+LINK32_OBJS= \
+ "$(INTDIR)\app.obj" \
+ "$(INTDIR)\condition.obj" \
+ "$(INTDIR)\dir.obj" \
+ "$(INTDIR)\DLLMain.obj" \
+ "$(INTDIR)\entropy.obj" \
+ "$(INTDIR)\errno2result.obj" \
+ "$(INTDIR)\file.obj" \
+ "$(INTDIR)\fsaccess.obj" \
+ "$(INTDIR)\interfaceiter.obj" \
+ "$(INTDIR)\ipv6.obj" \
+ "$(INTDIR)\iterated_hash.obj" \
+ "$(INTDIR)\keyboard.obj" \
+ "$(INTDIR)\net.obj" \
+ "$(INTDIR)\ntpaths.obj" \
+ "$(INTDIR)\once.obj" \
+ "$(INTDIR)\os.obj" \
+ "$(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" \
+ "$(INTDIR)\assertions.obj" \
+ "$(INTDIR)\base32.obj" \
+ "$(INTDIR)\base64.obj" \
+ "$(INTDIR)\bitstring.obj" \
+ "$(INTDIR)\buffer.obj" \
+ "$(INTDIR)\bufferlist.obj" \
+ "$(INTDIR)\commandline.obj" \
+ "$(INTDIR)\error.obj" \
+ "$(INTDIR)\event.obj" \
+ "$(INTDIR)\hash.obj" \
+ "$(INTDIR)\heap.obj" \
+ "$(INTDIR)\hex.obj" \
+ "$(INTDIR)\hmacmd5.obj" \
+ "$(INTDIR)\hmacsha.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" \
+ "$(INTDIR)\quota.obj" \
+ "$(INTDIR)\radix.obj" \
+ "$(INTDIR)\random.obj" \
+ "$(INTDIR)\ratelimiter.obj" \
+ "$(INTDIR)\refcount.obj" \
+ "$(INTDIR)\result.obj" \
+ "$(INTDIR)\rwlock.obj" \
+ "$(INTDIR)\serial.obj" \
+ "$(INTDIR)\sha1.obj" \
+ "$(INTDIR)\sha2.obj" \
+ "$(INTDIR)\sockaddr.obj" \
+ "$(INTDIR)\string.obj" \
+ "$(INTDIR)\symtab.obj" \
+ "$(INTDIR)\task.obj" \
+ "$(INTDIR)\taskpool.obj" \
+ "$(INTDIR)\timer.obj" \
+ "$(INTDIR)\parseint.obj" \
+ "$(INTDIR)\portset.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 - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\libisc.dll" "$(OUTDIR)\libisc.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\app.obj"
+ -@erase "$(INTDIR)\app.sbr"
+ -@erase "$(INTDIR)\assertions.obj"
+ -@erase "$(INTDIR)\assertions.sbr"
+ -@erase "$(INTDIR)\base32.obj"
+ -@erase "$(INTDIR)\base32.sbr"
+ -@erase "$(INTDIR)\base64.obj"
+ -@erase "$(INTDIR)\base64.sbr"
+ -@erase "$(INTDIR)\bitstring.obj"
+ -@erase "$(INTDIR)\bitstring.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)\condition.obj"
+ -@erase "$(INTDIR)\condition.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)\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)\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)\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"
+ -@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)\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)\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)\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)\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)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/noatomic/include" /I "win32" /I "../../isccfg/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\libisc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+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)\errno2result.sbr" \
+ "$(INTDIR)\file.sbr" \
+ "$(INTDIR)\fsaccess.sbr" \
+ "$(INTDIR)\interfaceiter.sbr" \
+ "$(INTDIR)\ipv6.sbr" \
+ "$(INTDIR)\iterated_hash.sbr" \
+ "$(INTDIR)\keyboard.sbr" \
+ "$(INTDIR)\net.sbr" \
+ "$(INTDIR)\ntpaths.sbr" \
+ "$(INTDIR)\once.sbr" \
+ "$(INTDIR)\os.sbr" \
+ "$(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" \
+ "$(INTDIR)\assertions.sbr" \
+ "$(INTDIR)\base32.sbr" \
+ "$(INTDIR)\base64.sbr" \
+ "$(INTDIR)\bitstring.sbr" \
+ "$(INTDIR)\buffer.sbr" \
+ "$(INTDIR)\bufferlist.sbr" \
+ "$(INTDIR)\commandline.sbr" \
+ "$(INTDIR)\error.sbr" \
+ "$(INTDIR)\event.sbr" \
+ "$(INTDIR)\hash.sbr" \
+ "$(INTDIR)\heap.sbr" \
+ "$(INTDIR)\hex.sbr" \
+ "$(INTDIR)\hmacmd5.sbr" \
+ "$(INTDIR)\hmacsha.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" \
+ "$(INTDIR)\quota.sbr" \
+ "$(INTDIR)\radix.sbr" \
+ "$(INTDIR)\random.sbr" \
+ "$(INTDIR)\ratelimiter.sbr" \
+ "$(INTDIR)\refcount.sbr" \
+ "$(INTDIR)\result.sbr" \
+ "$(INTDIR)\rwlock.sbr" \
+ "$(INTDIR)\serial.sbr" \
+ "$(INTDIR)\sha1.sbr" \
+ "$(INTDIR)\sha2.sbr" \
+ "$(INTDIR)\sockaddr.sbr" \
+ "$(INTDIR)\string.sbr" \
+ "$(INTDIR)\symtab.sbr" \
+ "$(INTDIR)\task.sbr" \
+ "$(INTDIR)\taskpool.sbr" \
+ "$(INTDIR)\timer.sbr" \
+ "$(INTDIR)\parseint.sbr" \
+ "$(INTDIR)\portset.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 /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\libisc.pdb" /map:"$(INTDIR)\libisc.map" /debug /machine:I386 /def:".\libisc.def" /out:"../../../Build/Debug/libisc.dll" /implib:"$(OUTDIR)\libisc.lib" /pdbtype:sept
+DEF_FILE= \
+ ".\libisc.def"
+LINK32_OBJS= \
+ "$(INTDIR)\app.obj" \
+ "$(INTDIR)\condition.obj" \
+ "$(INTDIR)\dir.obj" \
+ "$(INTDIR)\DLLMain.obj" \
+ "$(INTDIR)\entropy.obj" \
+ "$(INTDIR)\errno2result.obj" \
+ "$(INTDIR)\file.obj" \
+ "$(INTDIR)\fsaccess.obj" \
+ "$(INTDIR)\interfaceiter.obj" \
+ "$(INTDIR)\ipv6.obj" \
+ "$(INTDIR)\iterated_hash.obj" \
+ "$(INTDIR)\keyboard.obj" \
+ "$(INTDIR)\net.obj" \
+ "$(INTDIR)\ntpaths.obj" \
+ "$(INTDIR)\once.obj" \
+ "$(INTDIR)\os.obj" \
+ "$(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" \
+ "$(INTDIR)\assertions.obj" \
+ "$(INTDIR)\base32.obj" \
+ "$(INTDIR)\base64.obj" \
+ "$(INTDIR)\bitstring.obj" \
+ "$(INTDIR)\buffer.obj" \
+ "$(INTDIR)\bufferlist.obj" \
+ "$(INTDIR)\commandline.obj" \
+ "$(INTDIR)\error.obj" \
+ "$(INTDIR)\event.obj" \
+ "$(INTDIR)\hash.obj" \
+ "$(INTDIR)\heap.obj" \
+ "$(INTDIR)\hex.obj" \
+ "$(INTDIR)\hmacmd5.obj" \
+ "$(INTDIR)\hmacsha.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" \
+ "$(INTDIR)\quota.obj" \
+ "$(INTDIR)\radix.obj" \
+ "$(INTDIR)\random.obj" \
+ "$(INTDIR)\ratelimiter.obj" \
+ "$(INTDIR)\refcount.obj" \
+ "$(INTDIR)\result.obj" \
+ "$(INTDIR)\rwlock.obj" \
+ "$(INTDIR)\serial.obj" \
+ "$(INTDIR)\sha1.obj" \
+ "$(INTDIR)\sha2.obj" \
+ "$(INTDIR)\sockaddr.obj" \
+ "$(INTDIR)\string.obj" \
+ "$(INTDIR)\symtab.obj" \
+ "$(INTDIR)\task.obj" \
+ "$(INTDIR)\taskpool.obj" \
+ "$(INTDIR)\timer.obj" \
+ "$(INTDIR)\parseint.obj" \
+ "$(INTDIR)\portset.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 - Win32 Release" || "$(CFG)" == "libisc - Win32 Debug"
+SOURCE=.\app.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\app.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\app.obj" "$(INTDIR)\app.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\condition.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\condition.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\condition.obj" "$(INTDIR)\condition.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\dir.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\dir.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\dir.obj" "$(INTDIR)\dir.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\DLLMain.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\DLLMain.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\DLLMain.obj" "$(INTDIR)\DLLMain.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\entropy.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\entropy.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\entropy.obj" "$(INTDIR)\entropy.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\errno2result.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\errno2result.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\errno2result.obj" "$(INTDIR)\errno2result.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\file.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\file.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\file.obj" "$(INTDIR)\file.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\fsaccess.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\fsaccess.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\fsaccess.obj" "$(INTDIR)\fsaccess.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\interfaceiter.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\interfaceiter.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\interfaceiter.obj" "$(INTDIR)\interfaceiter.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\ipv6.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\ipv6.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\ipv6.obj" "$(INTDIR)\ipv6.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+
+SOURCE=.\keyboard.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\keyboard.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\keyboard.obj" "$(INTDIR)\keyboard.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\net.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\net.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\net.obj" "$(INTDIR)\net.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\ntpaths.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\ntpaths.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\ntpaths.obj" "$(INTDIR)\ntpaths.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\once.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\once.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\once.obj" "$(INTDIR)\once.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\os.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\os.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\os.obj" "$(INTDIR)\os.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\resource.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\resource.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\resource.obj" "$(INTDIR)\resource.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\socket.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\socket.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\socket.obj" "$(INTDIR)\socket.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\stdio.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\stdio.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\stdio.obj" "$(INTDIR)\stdio.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\stdtime.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\stdtime.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\stdtime.obj" "$(INTDIR)\stdtime.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\strerror.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\strerror.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\strerror.obj" "$(INTDIR)\strerror.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\syslog.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\syslog.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\syslog.obj" "$(INTDIR)\syslog.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\thread.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\thread.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\thread.obj" "$(INTDIR)\thread.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\time.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\time.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\time.obj" "$(INTDIR)\time.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\version.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\version.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\version.obj" "$(INTDIR)\version.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\win32os.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\win32os.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\win32os.obj" "$(INTDIR)\win32os.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=..\assertions.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\assertions.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\assertions.obj" "$(INTDIR)\assertions.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\base32.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\base32.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\base32.obj" "$(INTDIR)\base32.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\base64.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\base64.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\base64.obj" "$(INTDIR)\base64.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\bitstring.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\bitstring.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\bitstring.obj" "$(INTDIR)\bitstring.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\buffer.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\buffer.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\buffer.obj" "$(INTDIR)\buffer.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\bufferlist.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\bufferlist.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\bufferlist.obj" "$(INTDIR)\bufferlist.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\commandline.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\commandline.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\commandline.obj" "$(INTDIR)\commandline.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\error.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\error.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\error.obj" "$(INTDIR)\error.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\event.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\event.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\event.obj" "$(INTDIR)\event.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\hash.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\hash.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\hash.obj" "$(INTDIR)\hash.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\heap.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\heap.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\heap.obj" "$(INTDIR)\heap.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\hex.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\hex.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\hex.obj" "$(INTDIR)\hex.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\hmacmd5.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\hmacmd5.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\hmacmd5.obj" "$(INTDIR)\hmacmd5.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\hmacsha.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\hmacsha.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\hmacsha.obj" "$(INTDIR)\hmacsha.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\httpd.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\httpd.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\httpd.obj" "$(INTDIR)\httpd.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\inet_aton.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\inet_aton.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\inet_aton.obj" "$(INTDIR)\inet_aton.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\inet_ntop.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\inet_ntop.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\inet_ntop.obj" "$(INTDIR)\inet_ntop.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\inet_pton.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\inet_pton.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\inet_pton.obj" "$(INTDIR)\inet_pton.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\iterated_hash.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\iterated_hash.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\iterated_hash.obj" "$(INTDIR)\iterated_hash.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lex.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\lex.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\lex.obj" "$(INTDIR)\lex.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lfsr.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\lfsr.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\lfsr.obj" "$(INTDIR)\lfsr.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lib.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\lib.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\lib.obj" "$(INTDIR)\lib.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\log.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\log.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\log.obj" "$(INTDIR)\log.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\md5.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\md5.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\md5.obj" "$(INTDIR)\md5.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\mem.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\mem.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\mem.obj" "$(INTDIR)\mem.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\nls\msgcat.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\msgcat.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\msgcat.obj" "$(INTDIR)\msgcat.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\mutexblock.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\mutexblock.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\mutexblock.obj" "$(INTDIR)\mutexblock.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\netaddr.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\netaddr.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\netaddr.obj" "$(INTDIR)\netaddr.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\netscope.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\netscope.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\netscope.obj" "$(INTDIR)\netscope.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ondestroy.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\ondestroy.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\ondestroy.obj" "$(INTDIR)\ondestroy.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\parseint.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\parseint.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\parseint.obj" "$(INTDIR)\parseint.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\portset.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\portset.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\portset.obj" "$(INTDIR)\portset.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\quota.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\quota.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\quota.obj" "$(INTDIR)\quota.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\radix.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\radix.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\radix.obj" "$(INTDIR)\radix.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\random.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\random.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\random.obj" "$(INTDIR)\random.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ratelimiter.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\ratelimiter.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\ratelimiter.obj" "$(INTDIR)\ratelimiter.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\refcount.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\refcount.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\refcount.obj" "$(INTDIR)\refcount.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\region.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\region.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\region.obj" "$(INTDIR)\region.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\result.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\result.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\result.obj" "$(INTDIR)\result.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\rwlock.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\rwlock.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\rwlock.obj" "$(INTDIR)\rwlock.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\serial.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\serial.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\serial.obj" "$(INTDIR)\serial.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\sha1.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\sha1.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\sha1.obj" "$(INTDIR)\sha1.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\sha2.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\sha2.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\sha2.obj" "$(INTDIR)\sha2.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\sockaddr.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\sockaddr.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\sockaddr.obj" "$(INTDIR)\sockaddr.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\string.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\string.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\string.obj" "$(INTDIR)\string.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\symtab.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\symtab.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\symtab.obj" "$(INTDIR)\symtab.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\task.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\task.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\task.obj" "$(INTDIR)\task.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\taskpool.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\taskpool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\taskpool.obj" "$(INTDIR)\taskpool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\timer.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\timer.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\timer.obj" "$(INTDIR)\timer.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/net.c b/lib/isc/win32/net.c
new file mode 100644
index 0000000..3785f8a
--- /dev/null
+++ b/lib/isc/win32/net.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: net.c,v 1.18 2008/08/08 05:06:49 marka Exp $ */
+
+#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;
+ isc_result_t result = ISC_R_SUCCESS;
+ 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, &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, &on, sizeof(on)) < 0) {
+ ipv6only_result = ISC_R_NOTFOUND;
+ goto close;
+ }
+
+ ipv6only_result = ISC_R_SUCCESS;
+
+close:
+ closeocket(s);
+ return;
+#endif /* IPV6_V6ONLY */
+}
+
+static void
+initialize_ipv6only(void) {
+ RUNTIME_CHECK(isc_once_do(&once_ipv6only,
+ try_ipv6only) == ISC_R_SUCCESS);
+}
+
+static void
+try_ipv6pktinfo(void) {
+ int s, 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 /* 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 ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+ initialize_ipv6pktinfo();
+#else
+ ipv6pktinfo_result = ISC_R_NOTFOUND;
+#endif
+#endif
+ 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;
+}
diff --git a/lib/isc/win32/netdb.h b/lib/isc/win32/netdb.h
new file mode 100644
index 0000000..4e3a935
--- /dev/null
+++ b/lib/isc/win32/netdb.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: netdb.h,v 1.7 2007/06/19 23:47:19 tbox Exp $ */
+
+#ifndef NETDB_H
+#define NETDB_H 1
+
+#include <stddef.h>
+#include <winsock2.h>
+
+/*
+ * Define if <netdb.h> does not declare struct addrinfo.
+ */
+
+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 */
+};
+
+
+/*
+ * 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-Authoritive 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..351adc5
--- /dev/null
+++ b/lib/isc/win32/ntgroups.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ntgroups.c,v 1.10 2007/06/19 23:47:19 tbox Exp $ */
+
+/*
+ * 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;
+ DWORD dwTotalCount = 0;
+ int 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;
+ }
+
+ dwTotalCount = 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..d1c622f
--- /dev/null
+++ b/lib/isc/win32/ntpaths.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: ntpaths.c,v 1.11 2007/06/18 23:47:49 tbox Exp $ */
+
+/*
+ * 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>
+
+/*
+ * 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 local_state_dir[MAX_PATH];
+static char sys_conf_dir[MAX_PATH];
+static char rndc_keyFile[MAX_PATH];
+
+static DWORD baseLen = MAX_PATH;
+static BOOL Initialized = FALSE;
+
+void
+isc_ntpaths_init() {
+ HKEY hKey;
+ BOOL keyFound = TRUE;
+
+ memset(namedBase, 0, MAX_PATH);
+ 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 */
+ strcpy(namedBase, systemDir);
+
+ strcpy(ns_confFile, namedBase);
+ strcat(ns_confFile, "\\etc\\named.conf");
+
+ strcpy(lwresd_confFile, namedBase);
+ strcat(lwresd_confFile, "\\etc\\lwresd.conf");
+
+ strcpy(lwresd_resolvconfFile, systemDir);
+ strcat(lwresd_resolvconfFile, "\\Drivers\\etc\\resolv.conf");
+
+ strcpy(rndc_keyFile, namedBase);
+ strcat(rndc_keyFile, "\\etc\\rndc.key");
+
+ strcpy(rndc_confFile, namedBase);
+ strcat(rndc_confFile, "\\etc\\rndc.conf");
+ strcpy(ns_defaultpidfile, namedBase);
+ strcat(ns_defaultpidfile, "\\etc\\named.pid");
+
+ strcpy(lwresd_defaultpidfile, namedBase);
+ strcat(lwresd_defaultpidfile, "\\etc\\lwresd.pid");
+
+ strcpy(local_state_dir, namedBase);
+ strcat(local_state_dir, "\\bin");
+
+ strcpy(sys_conf_dir, namedBase);
+ strcat(sys_conf_dir, "\\etc");
+
+ 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 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;
+ default:
+ return (NULL);
+ }
+}
diff --git a/lib/isc/win32/once.c b/lib/isc/win32/once.c
new file mode 100644
index 0000000..b504776
--- /dev/null
+++ b/lib/isc/win32/once.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: once.c,v 1.12 2007/06/18 23:47:49 tbox Exp $ */
+
+/* Principal Authors: DCL */
+
+#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..bbd5f1d
--- /dev/null
+++ b/lib/isc/win32/os.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: os.c,v 1.8 2007/06/19 23:47:19 tbox Exp $ */
+
+#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 = 1;
+ initialize_action();
+ ncpus = SystemInfo.dwNumberOfProcessors;
+ if (ncpus <= 0)
+ ncpus = 1;
+
+ return ((unsigned int)ncpus);
+}
diff --git a/lib/isc/win32/resource.c b/lib/isc/win32/resource.c
new file mode 100644
index 0000000..e7e7cf4
--- /dev/null
+++ b/lib/isc/win32/resource.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: resource.c,v 1.10 2008/07/11 23:47:09 tbox Exp $ */
+
+#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..082fb7d
--- /dev/null
+++ b/lib/isc/win32/socket.c
@@ -0,0 +1,3658 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: socket.c,v 1.70 2008/09/16 17:19:01 explorer Exp $ */
+
+/* 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
+ */
+
+#define MAKE_EXTERNAL 1
+#include <config.h>
+
+#include <sys/types.h>
+
+#ifndef _WINSOCKAPI_
+#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
+#endif
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <io.h>
+#include <fcntl.h>
+#include <process.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/strerror.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"
+
+/*
+ * 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 consistancy 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 */
+ 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_socket_connev_t *connect_ev;
+
+ 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 */
+ 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;
+ /* Locked by manager lock. */
+ ISC_LIST(isc_socket_t) socklist;
+ isc_boolean_t 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_threadresult_t WINAPI SocketIoThread(LPVOID ThreadContext);
+static void maybe_free_socket(isc_socket_t **, int);
+static void free_socket(isc_socket_t **, int);
+static isc_boolean_t senddone_is_active(isc_socket_t *sock, isc_socketevent_t *dev);
+static isc_boolean_t acceptdone_is_active(isc_socket_t *sock, isc_socket_newconnev_t *dev);
+static isc_boolean_t 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 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;
+
+#if 0
+ isc_sockaddr_t addr;
+ char socktext[256];
+
+ isc_socket_getpeername(sock, &addr);
+ isc_sockaddr_format(&addr, socktext, sizeof(socktext));
+ printf("Remote Socket: %s\n", socktext);
+ isc_socket_getsockname(sock, &addr);
+ isc_sockaddr_format(&addr, socktext, sizeof(socktext));
+ printf("This Socket: %s\n", socktext);
+#endif
+
+ printf("\n\t\tSock Dump\n");
+ printf("\t\tfd: %u\n", sock->fd);
+ printf("\t\treferences: %d\n", sock->references);
+ printf("\t\tpending_accept: %d\n", sock->pending_accept);
+ printf("\t\tconnecting: %d\n", sock->pending_connect);
+ printf("\t\tconnected: %d\n", sock->connected);
+ printf("\t\tbound: %d\n", sock->bound);
+ printf("\t\tpending_iocp: %d\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);
+ }
+}
+
+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);
+ exit(1);
+ }
+ }
+}
+
+/*
+ * 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 miniumum 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);
+ exit(1);
+ }
+
+ 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);
+ exit(1);
+ }
+
+ /*
+ * 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);
+ exit(1);
+ }
+
+ 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 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 isc_boolean_t initialised = ISC_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);
+ exit(1);
+ }
+ /*
+ * 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 = ISC_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 total_bytes = 0;
+ int Result;
+ int Error;
+ WSABUF iov[1];
+ IoCompletionInfo *lpo;
+ isc_result_t isc_result;
+
+ /*
+ * If we already have a receive pending, do nothing.
+ */
+ if (sock->pending_recv > 0)
+ return;
+
+ /*
+ * If no one is waiting, do nothing.
+ */
+ if (ISC_LIST_EMPTY(sock->recv_list))
+ return;
+
+ INSIST(sock->recvbuf.remaining == 0);
+ INSIST(sock->fd != INVALID_SOCKET);
+
+ iov[0].len = sock->recvbuf.len;
+ iov[0].buf = sock->recvbuf.base;
+
+ lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
+ HEAP_ZERO_MEMORY,
+ sizeof(IoCompletionInfo));
+ RUNTIME_CHECK(lpo != NULL);
+ 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;
+
+ 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);
+ 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);
+}
+
+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 peer %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 WASRecvFrom
+ * 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_majorversion() < 5)
+ 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));
+
+ memcpy(&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);
+
+ memcpy(cpbuffer->buf,(dev->region.base + dev->n), write_count);
+ cpbuffer->buflen = write_count;
+ ISC_LIST_ENQUEUE(lpo->bufferlist, cpbuffer, link);
+ iov[0].buf = cpbuffer->buf;
+ iov[0].len = 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 = 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);
+
+ memcpy(cpbuffer->buf,(used.base + skip_count), uselen);
+ cpbuffer->buflen = uselen;
+ iov[iovcount].buf = cpbuffer->buf;
+ iov[iovcount].len = 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 = 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_socket_t *sock, isc_eventtype_t eventtype,
+ isc_taskaction_t action, const void *arg)
+{
+ isc_socketevent_t *ev;
+
+ ev = (isc_socketevent_t *)isc_event_allocate(sock->manager->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;
+
+ 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 #: %u\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%d\tbase %p, len %d\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;
+ memcpy(&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);
+ memcpy(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);
+ memcpy(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 addrbuf[ISC_SOCKADDR_FORMATSIZE];
+ 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)));
+
+ /*
+ * The other error types depend on whether or not the
+ * socket is UDP or TCP. If it is UDP, some errors
+ * that we expect to be fatal under TCP are merely
+ * annoying, and are really soft errors.
+ *
+ * However, these soft errors are still returned as
+ * a status.
+ */
+ isc_sockaddr_format(&dev->address, addrbuf, sizeof(addrbuf));
+ isc__strerror(send_errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "completeio_send: %s: %s",
+ addrbuf, strbuf);
+ dev->result = isc__errno2result(send_errno);
+ return (DOIO_HARD);
+ }
+
+ /*
+ * 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 *msghdr;
+
+ lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
+ HEAP_ZERO_MEMORY,
+ sizeof(IoCompletionInfo));
+ RUNTIME_CHECK(lpo != NULL);
+ lpo->request_type = SOCKET_SEND;
+ lpo->dev = dev;
+ msghdr = &lpo->messagehdr;
+ memset(msghdr, 0, sizeof(struct msghdr));
+ ISC_LIST_INIT(lpo->bufferlist);
+
+ build_msghdr_send(sock, dev, msghdr, cmsg, sock->iov, lpo);
+
+ *nbytes = internal_sendmsg(sock, lpo, msghdr, 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);
+ }
+ goto done;
+ }
+ dev->result = ISC_R_SUCCESS;
+ status = DOIO_SOFT;
+ done:
+ _set_state(sock, SOCK_DATA);
+ return (status);
+}
+
+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);
+ sock->connect_ev = NULL;
+ 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;
+ 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) {
+ sock->magic = 0;
+ goto error;
+ }
+
+ /*
+ * initialize the lock
+ */
+ result = isc_mutex_init(&sock->lock);
+ if (result != ISC_R_SUCCESS) {
+ sock->magic = 0;
+ isc_mem_put(manager->mctx, sock->recvbuf.base, sock->recvbuf.len);
+ sock->recvbuf.base = NULL;
+ goto error;
+ }
+
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "allocated");
+
+ sock->magic = SOCKET_MAGIC;
+ *socketp = sock;
+
+ return (ISC_R_SUCCESS);
+
+ error:
+ 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;
+ isc_boolean_t crash = ISC_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 = ISC_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 = ISC_TRUE;
+ crash_reason = "send_list > sock->pending_send";
+ }
+
+ 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 == ISC_FALSE);
+ }
+}
+
+/*
+ * Maybe free the socket.
+ *
+ * This function will veriy 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)
+ || 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;
+
+ manager = sock->manager;
+
+ /*
+ * 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'.
+ */
+isc_result_t
+isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+ isc_socket_t **socketp) {
+ isc_socket_t *sock = NULL;
+ isc_result_t 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);
+
+ 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;
+ }
+
+ 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);
+ }
+
+
+#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,
+ (void *)&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,
+ (void *)&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 */
+#ifdef IPV6_USE_MIN_MTU /*2292bis, not too common yet*/
+ /* use minimum MTU */
+ if (pf == AF_INET6) {
+ (void)setsockopt(sock->fd, IPPROTO_IPV6,
+ IPV6_USE_MIN_MTU,
+ (void *)&on, sizeof(on));
+ }
+#endif
+#endif /* ISC_PLATFORM_HAVEIPV6 */
+#endif /* definef(USE_CMSG) */
+
+#if defined(SO_RCVBUF)
+ optlen = sizeof(size);
+ if (getsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
+ (void *)&size, &optlen) >= 0 &&
+ size < RCVBUFSIZE) {
+ size = RCVBUFSIZE;
+ (void)setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
+ (void *)&size, sizeof(size));
+ }
+#endif
+
+ }
+#endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */
+
+ _set_state(sock, SOCK_OPEN);
+ sock->references = 1;
+ *socketp = sock;
+
+ iocompletionport_update(sock);
+
+ /*
+ * 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_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;
+ isc_boolean_t kill_socket = ISC_FALSE;
+
+ 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;
+
+ sock->connect_ev = NULL;
+
+ 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 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);
+ memcpy(&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);
+
+ 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;
+ 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;
+
+ /*
+ * Has this event been canceled?
+ */
+ 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: cdev->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:
+ cdev->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);
+ cdev->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");
+ }
+
+ send_connectdone_event(sock, &cdev);
+
+ 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);
+ }
+}
+
+/*
+ * 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 (or for connect, is
+ * the one we're waiting for. Using these ensures we will not double-send an
+ * event.
+ */
+static isc_boolean_t
+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 ? ISC_FALSE : ISC_TRUE);
+}
+
+static isc_boolean_t
+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 ? ISC_FALSE : ISC_TRUE);
+}
+
+static isc_boolean_t
+connectdone_is_active(isc_socket_t *sock, isc_socket_connev_t *dev)
+{
+ return (sock->connect_ev == dev ? ISC_TRUE : ISC_FALSE);
+}
+
+/*
+ * 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) {
+ bSuccess = GetQueuedCompletionStatus(manager->hIoCompletionPort,
+ &nbytes, (LPDWORD)&sock,
+ (LPWSAOVERLAPPED *)&lpo,
+ INFINITE);
+ if (lpo == NULL) /* Received request to exit */
+ break;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ request = lpo->request_type;
+
+ errstatus = 0;
+ if (!bSuccess) {
+ isc_result_t isc_result;
+
+ /*
+ * Did the I/O operation complete?
+ */
+ errstatus = WSAGetLastError();
+ isc_result = isc__errno2resultx(errstatus, __FILE__, __LINE__);
+
+ 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--;
+ 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,
+ "cancelled_send");
+ send_senddone_event(sock, &lpo->dev);
+ }
+ break;
+
+ case SOCKET_ACCEPT:
+ INSIST(sock->pending_iocp > 0);
+ sock->pending_iocp--;
+ INSIST(sock->pending_accept > 0);
+ 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,
+ "cancelled_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)) {
+ lpo->cdev->result = isc_result;
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "cancelled_connect");
+ send_connectdone_event(sock, &lpo->cdev);
+ }
+ 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;
+ 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 = ISC_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_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 = ISC_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);
+ 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)
+{
+ int cc = 0;
+ isc_task_t *ntask = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ int recv_errno = 0;
+
+ 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, const 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(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, const 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(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. Nothing more to do */
+ 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) {
+ 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, const 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, const 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(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, const void *arg)
+{
+ return (isc_socket_sendtov(sock, buflist, task, action, arg, NULL,
+ NULL));
+}
+
+isc_result_t
+isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
+ isc_task_t *task, isc_taskaction_t action, const void *arg,
+ isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
+{
+ isc_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(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, 0);
+ 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);
+
+ 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, (void *)&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];
+
+ 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);
+ }
+
+ 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 agressive accept() XXXMLG
+ */
+isc_result_t
+isc_socket_accept(isc_socket_t *sock,
+ isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+ isc_socket_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);
+ 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, const 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;
+ }
+
+ REQUIRE(!sock->pending_connect);
+
+ 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->type == isc_sockettype_tcp) {
+ /*
+ * 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.
+ */
+ sock->connect_ev = cdev;
+ sock->pending_iocp++;
+ } else {
+ 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;
+
+ /*
+ * Connecting is not a list.
+ */
+ if (((how & ISC_SOCKCANCEL_CONNECT) == ISC_SOCKCANCEL_CONNECT)
+ && sock->connect_ev != NULL) {
+ isc_socket_connev_t *dev;
+ isc_task_t *current_task;
+
+ INSIST(sock->pending_connect);
+
+ dev = sock->connect_ev;
+ current_task = dev->ev_sender;
+
+ if ((task == NULL) || (task == current_task)) {
+ closesocket(sock->fd);
+ sock->fd = INVALID_SOCKET;
+ _set_state(sock, SOCK_CLOSED);
+
+ sock->connect_ev = NULL;
+ dev->result = ISC_R_CANCELED;
+ send_connectdone_event(sock, &dev);
+ }
+ }
+ 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);
+}
+
+isc_boolean_t
+isc_socket_isbound(isc_socket_t *sock) {
+ isc_boolean_t 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 (ISC_FALSE);
+ }
+
+ val = ((sock->bound) ? ISC_TRUE : ISC_FALSE);
+ UNLOCK(&sock->lock);
+
+ return (val);
+}
+
+void
+isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t 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,
+ (void *)&onoff, sizeof(onoff));
+ }
+#endif
+}
+
+void
+isc_socket_cleanunix(isc_sockaddr_t *addr, isc_boolean_t active) {
+ UNUSED(addr);
+ UNUSED(active);
+}
+
+isc_result_t
+isc_socket_permunix(isc_sockaddr_t *addr, isc_uint32_t perm,
+ isc_uint32_t owner, isc_uint32_t group)
+{
+ 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);
+ memset(socket->name, 0, sizeof(socket->name));
+ strncpy(socket->name, name, sizeof(socket->name) - 1);
+ 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);
+}
+
+void
+isc__socketmgr_setreserved(isc_socketmgr_t *manager, isc_uint32_t reserved) {
+ UNUSED(manager);
+ UNUSED(reserved);
+}
diff --git a/lib/isc/win32/stdio.c b/lib/isc/win32/stdio.c
new file mode 100644
index 0000000..427a8e1
--- /dev/null
+++ b/lib/isc/win32/stdio.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: stdio.c,v 1.6 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <io.h>
+#include <errno.h>
+
+#include <isc/stdio.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, long offset, int whence) {
+ int r;
+
+ r = fseek(f, offset, whence);
+ if (r == 0)
+ 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) {
+ int r;
+
+ 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..574297e
--- /dev/null
+++ b/lib/isc/win32/stdtime.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: stdtime.c,v 1.12 2007/06/19 23:47:19 tbox Exp $ */
+
+#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)time(t);
+}
diff --git a/lib/isc/win32/strerror.c b/lib/isc/win32/strerror.c
new file mode 100644
index 0000000..4174332
--- /dev/null
+++ b/lib/isc/win32/strerror.c
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001, 2002 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: strerror.c,v 1.8 2007/06/19 23:47:19 tbox Exp $ */
+
+#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..375784f
--- /dev/null
+++ b/lib/isc/win32/syslog.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001-2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: syslog.c,v 1.10 2007/06/19 23:47:19 tbox Exp $ */
+
+#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() {
+ 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..fd4b3a6
--- /dev/null
+++ b/lib/isc/win32/syslog.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001, 2002 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: syslog.h,v 1.7 2007/06/19 23:47:19 tbox Exp $ */
+
+#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..be955ea
--- /dev/null
+++ b/lib/isc/win32/thread.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: thread.c,v 1.24 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <process.h>
+
+#include <isc/thread.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_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..aebf73d
--- /dev/null
+++ b/lib/isc/win32/time.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2004, 2006-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001, 2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: time.c,v 1.48 2008/09/08 23:47:10 tbox Exp $ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <windows.h>
+
+#include <isc/assertions.h>
+#include <isc/time.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)
+#define UINT64_MAX _UI64_MAX
+
+/***
+ *** Absolute Times
+ ***/
+
+static isc_time_t epoch = { { 0, 0 } };
+LIBISC_EXTERNAL_DATA isc_time_t *isc_time_epoch = &epoch;
+
+/***
+ *** Intervals
+ ***/
+
+static isc_interval_t zero_interval = { 0 };
+LIBISC_EXTERNAL_DATA isc_interval_t *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;
+}
+
+isc_boolean_t
+isc_interval_iszero(const isc_interval_t *i) {
+ REQUIRE(i != NULL);
+ if (i->interval == 0)
+ return (ISC_TRUE);
+
+ return (ISC_FALSE);
+}
+
+void
+isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) {
+ SYSTEMTIME epoch = { 1970, 1, 4, 1, 0, 0, 0, 0 };
+ FILETIME temp;
+ ULARGE_INTEGER i1;
+
+ REQUIRE(t != NULL);
+ REQUIRE(nanoseconds < NS_PER_S);
+
+ SystemTimeToFileTime(&epoch, &temp);
+
+ i1.LowPart = t->absolute.dwLowDateTime;
+ i1.HighPart = t->absolute.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;
+}
+
+isc_boolean_t
+isc_time_isepoch(const isc_time_t *t) {
+ REQUIRE(t != NULL);
+
+ if (t->absolute.dwLowDateTime == 0 &&
+ t->absolute.dwHighDateTime == 0)
+ return (ISC_TRUE);
+
+ return (ISC_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);
+}
+
+isc_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);
+}
+
+isc_uint32_t
+isc_time_seconds(const isc_time_t *t) {
+ SYSTEMTIME st;
+
+ /*
+ * Convert the time to a SYSTEMTIME structure and the grab the
+ * milliseconds
+ */
+ FileTimeToSystemTime(&t->absolute, &st);
+
+ return ((isc_uint32_t)(st.wMilliseconds / 1000));
+}
+
+isc_uint32_t
+isc_time_nanoseconds(const isc_time_t *t) {
+ SYSTEMTIME st;
+
+ /*
+ * Convert the time to a SYSTEMTIME structure and the grab the
+ * milliseconds
+ */
+ FileTimeToSystemTime(&t->absolute, &st);
+
+ return ((isc_uint32_t)(st.wMilliseconds * 1000000));
+}
+
+void
+isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) {
+ FILETIME localft;
+ SYSTEMTIME st;
+ char DateBuf[50];
+ char TimeBuf[50];
+
+ static const char badtime[] = "99-Bad-9999 99:99:99.999";
+
+ 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
+ snprintf(buf, len, badtime);
+}
+
+void
+isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) {
+ SYSTEMTIME st;
+ char DateBuf[50];
+ char TimeBuf[50];
+
+ 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;
+ }
+}
diff --git a/lib/isc/win32/unistd.h b/lib/isc/win32/unistd.h
new file mode 100644
index 0000000..889f0b8
--- /dev/null
+++ b/lib/isc/win32/unistd.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000, 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: unistd.h,v 1.8 2008/01/23 03:22:43 tbox Exp $ */
+
+/* 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 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..6d5c1fd
--- /dev/null
+++ b/lib/isc/win32/version.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: version.c,v 1.7 2007/06/19 23:47:19 tbox Exp $ */
+
+#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..56498d0
--- /dev/null
+++ b/lib/isc/win32/win32os.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: win32os.c,v 1.5 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <windows.h>
+
+#include <isc/win32os.h>
+
+static BOOL bInit = FALSE;
+static OSVERSIONINFOEX osVer;
+
+static void
+initialize_action(void) {
+ BOOL bSuccess;
+
+ if (bInit)
+ return;
+ /*
+ * NOTE: VC++ 6.0 gets this function declaration wrong
+ * so we compensate by casting the argument
+ */
+ osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ bSuccess = GetVersionEx((OSVERSIONINFO *) &osVer);
+
+ /*
+ * Versions of NT before NT4.0 SP6 did not return the
+ * extra info that the EX structure provides and returns
+ * a failure so we need to retry with the old structure.
+ */
+ if(!bSuccess) {
+ osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ bSuccess = GetVersionEx((OSVERSIONINFO *) &osVer);
+ }
+ bInit = TRUE;
+}
+
+unsigned int
+isc_win32os_majorversion(void) {
+ initialize_action();
+ return ((unsigned int)osVer.dwMajorVersion);
+}
+
+unsigned int
+isc_win32os_minorversion(void) {
+ initialize_action();
+ return ((unsigned int)osVer.dwMinorVersion);
+}
+
+unsigned int
+isc_win32os_servicepackmajor(void) {
+ initialize_action();
+ return ((unsigned int)osVer.wServicePackMajor);
+}
+
+unsigned int
+isc_win32os_servicepackminor(void) {
+ initialize_action();
+ return ((unsigned int)osVer.wServicePackMinor);
+}
+
+int
+isc_win32os_versioncheck(unsigned int major, unsigned int minor,
+ unsigned int spmajor, unsigned int spminor) {
+
+ initialize_action();
+
+ if (major < isc_win32os_majorversion())
+ return (1);
+ if (major > isc_win32os_majorversion())
+ return (-1);
+ if (minor < isc_win32os_minorversion())
+ return (1);
+ if (minor > isc_win32os_minorversion())
+ return (-1);
+ if (spmajor < isc_win32os_servicepackmajor())
+ return (1);
+ if (spmajor > isc_win32os_servicepackmajor())
+ return (-1);
+ if (spminor < isc_win32os_servicepackminor())
+ return (1);
+ if (spminor > isc_win32os_servicepackminor())
+ return (-1);
+
+ /* Exact */
+ return (0);
+} \ No newline at end of file