diff options
Diffstat (limited to 'lib/isc/win32')
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 |