From ea648e70a989cca190cd7403fe892fd2dcc290b4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 5 May 2024 20:37:14 +0200 Subject: Adding upstream version 1:9.11.5.P4+dfsg. Signed-off-by: Daniel Baumann --- lib/isc/win32/DLLMain.c | 51 + lib/isc/win32/Makefile.in | 34 + lib/isc/win32/app.c | 481 ++++ lib/isc/win32/condition.c | 255 ++ lib/isc/win32/dir.c | 307 +++ lib/isc/win32/entropy.c | 299 ++ lib/isc/win32/errno.c | 21 + lib/isc/win32/errno2result.c | 118 + lib/isc/win32/errno2result.h | 35 + lib/isc/win32/file.c | 928 +++++++ lib/isc/win32/fsaccess.c | 365 +++ lib/isc/win32/include/Makefile.in | 17 + lib/isc/win32/include/isc/Makefile.in | 30 + lib/isc/win32/include/isc/atomic.h | 75 + lib/isc/win32/include/isc/bind_registry.h | 43 + lib/isc/win32/include/isc/bindevt.h | 84 + lib/isc/win32/include/isc/condition.h | 60 + lib/isc/win32/include/isc/dir.h | 73 + lib/isc/win32/include/isc/ipv6.h | 120 + lib/isc/win32/include/isc/keyboard.h | 42 + lib/isc/win32/include/isc/mutex.h | 48 + lib/isc/win32/include/isc/net.h | 431 +++ lib/isc/win32/include/isc/netdb.h | 47 + lib/isc/win32/include/isc/ntgroups.h | 28 + lib/isc/win32/include/isc/ntpaths.h | 66 + lib/isc/win32/include/isc/offset.h | 24 + lib/isc/win32/include/isc/once.h | 36 + lib/isc/win32/include/isc/platform.h.in | 157 ++ lib/isc/win32/include/isc/stat.h | 57 + lib/isc/win32/include/isc/stdtime.h | 55 + lib/isc/win32/include/isc/strerror.h | 35 + lib/isc/win32/include/isc/syslog.h | 38 + lib/isc/win32/include/isc/thread.h | 98 + lib/isc/win32/include/isc/time.h | 357 +++ lib/isc/win32/include/isc/win32os.h | 40 + lib/isc/win32/include/pkcs11/Makefile.in | 26 + lib/isc/win32/include/pkcs11/cryptoki.h | 66 + lib/isc/win32/interfaceiter.c | 543 ++++ lib/isc/win32/ipv6.c | 20 + lib/isc/win32/keyboard.c | 82 + lib/isc/win32/libgen.h | 19 + lib/isc/win32/libisc.def.exclude | 42 + lib/isc/win32/libisc.def.in | 836 ++++++ lib/isc/win32/libisc.dsp.in | 949 +++++++ lib/isc/win32/libisc.dsw | 29 + lib/isc/win32/libisc.mak.in | 2398 ++++++++++++++++ lib/isc/win32/libisc.vcxproj.filters.in | 675 +++++ lib/isc/win32/libisc.vcxproj.in | 530 ++++ lib/isc/win32/libisc.vcxproj.user | 3 + lib/isc/win32/meminfo.c | 26 + lib/isc/win32/net.c | 341 +++ lib/isc/win32/netdb.h | 182 ++ lib/isc/win32/ntgroups.c | 177 ++ lib/isc/win32/ntpaths.c | 157 ++ lib/isc/win32/once.c | 44 + lib/isc/win32/os.c | 38 + lib/isc/win32/pk11_api.c | 675 +++++ lib/isc/win32/resource.c | 65 + lib/isc/win32/socket.c | 4277 +++++++++++++++++++++++++++++ lib/isc/win32/stdio.c | 150 + lib/isc/win32/stdtime.c | 30 + lib/isc/win32/strerror.c | 452 +++ lib/isc/win32/syslog.c | 174 ++ lib/isc/win32/syslog.h | 69 + lib/isc/win32/thread.c | 89 + lib/isc/win32/time.c | 388 +++ lib/isc/win32/unistd.h | 53 + lib/isc/win32/version.c | 21 + lib/isc/win32/win32os.c | 117 + 69 files changed, 18698 insertions(+) create mode 100644 lib/isc/win32/DLLMain.c create mode 100644 lib/isc/win32/Makefile.in create mode 100644 lib/isc/win32/app.c create mode 100644 lib/isc/win32/condition.c create mode 100644 lib/isc/win32/dir.c create mode 100644 lib/isc/win32/entropy.c create mode 100644 lib/isc/win32/errno.c create mode 100644 lib/isc/win32/errno2result.c create mode 100644 lib/isc/win32/errno2result.h create mode 100644 lib/isc/win32/file.c create mode 100644 lib/isc/win32/fsaccess.c create mode 100644 lib/isc/win32/include/Makefile.in create mode 100644 lib/isc/win32/include/isc/Makefile.in create mode 100644 lib/isc/win32/include/isc/atomic.h create mode 100644 lib/isc/win32/include/isc/bind_registry.h create mode 100644 lib/isc/win32/include/isc/bindevt.h create mode 100644 lib/isc/win32/include/isc/condition.h create mode 100644 lib/isc/win32/include/isc/dir.h create mode 100644 lib/isc/win32/include/isc/ipv6.h create mode 100644 lib/isc/win32/include/isc/keyboard.h create mode 100644 lib/isc/win32/include/isc/mutex.h create mode 100644 lib/isc/win32/include/isc/net.h create mode 100644 lib/isc/win32/include/isc/netdb.h create mode 100644 lib/isc/win32/include/isc/ntgroups.h create mode 100644 lib/isc/win32/include/isc/ntpaths.h create mode 100644 lib/isc/win32/include/isc/offset.h create mode 100644 lib/isc/win32/include/isc/once.h create mode 100644 lib/isc/win32/include/isc/platform.h.in create mode 100644 lib/isc/win32/include/isc/stat.h create mode 100644 lib/isc/win32/include/isc/stdtime.h create mode 100644 lib/isc/win32/include/isc/strerror.h create mode 100644 lib/isc/win32/include/isc/syslog.h create mode 100644 lib/isc/win32/include/isc/thread.h create mode 100644 lib/isc/win32/include/isc/time.h create mode 100644 lib/isc/win32/include/isc/win32os.h create mode 100644 lib/isc/win32/include/pkcs11/Makefile.in create mode 100644 lib/isc/win32/include/pkcs11/cryptoki.h create mode 100644 lib/isc/win32/interfaceiter.c create mode 100644 lib/isc/win32/ipv6.c create mode 100644 lib/isc/win32/keyboard.c create mode 100644 lib/isc/win32/libgen.h create mode 100644 lib/isc/win32/libisc.def.exclude create mode 100644 lib/isc/win32/libisc.def.in create mode 100644 lib/isc/win32/libisc.dsp.in create mode 100644 lib/isc/win32/libisc.dsw create mode 100644 lib/isc/win32/libisc.mak.in create mode 100644 lib/isc/win32/libisc.vcxproj.filters.in create mode 100644 lib/isc/win32/libisc.vcxproj.in create mode 100644 lib/isc/win32/libisc.vcxproj.user create mode 100644 lib/isc/win32/meminfo.c create mode 100644 lib/isc/win32/net.c create mode 100644 lib/isc/win32/netdb.h create mode 100644 lib/isc/win32/ntgroups.c create mode 100644 lib/isc/win32/ntpaths.c create mode 100644 lib/isc/win32/once.c create mode 100644 lib/isc/win32/os.c create mode 100644 lib/isc/win32/pk11_api.c create mode 100644 lib/isc/win32/resource.c create mode 100644 lib/isc/win32/socket.c create mode 100644 lib/isc/win32/stdio.c create mode 100644 lib/isc/win32/stdtime.c create mode 100644 lib/isc/win32/strerror.c create mode 100644 lib/isc/win32/syslog.c create mode 100644 lib/isc/win32/syslog.h create mode 100644 lib/isc/win32/thread.c create mode 100644 lib/isc/win32/time.c create mode 100644 lib/isc/win32/unistd.h create mode 100644 lib/isc/win32/version.c create mode 100644 lib/isc/win32/win32os.c (limited to 'lib/isc/win32') diff --git a/lib/isc/win32/DLLMain.c b/lib/isc/win32/DLLMain.c new file mode 100644 index 0000000..f14260e --- /dev/null +++ b/lib/isc/win32/DLLMain.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include +#include + +/* + * Called when we enter the DLL + */ +__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, + DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + /* + * The DLL is loading due to process + * initialization or a call to LoadLibrary. + */ + case DLL_PROCESS_ATTACH: + break; + + /* The attached process creates a new thread. */ + case DLL_THREAD_ATTACH: + break; + + /* The thread of the attached process terminates. */ + case DLL_THREAD_DETACH: + break; + + /* + * The DLL is unloading from a process due to + * process termination or a call to FreeLibrary. + */ + case DLL_PROCESS_DETACH: + break; + + default: + break; + } + return (TRUE); +} + diff --git a/lib/isc/win32/Makefile.in b/lib/isc/win32/Makefile.in new file mode 100644 index 0000000..19b46bd --- /dev/null +++ b/lib/isc/win32/Makefile.in @@ -0,0 +1,34 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +CINCLUDES = -I${srcdir}/.. \ + -I./include \ + -I${srcdir}/include \ + -I${srcdir}/../include +CDEFINES = +CWARNINGS = + +# Alphabetically +OBJS = condition.@O@ dir.@O@ errno.@O@ file.@O@ \ + meminfo.@O@ fsaccess.@O@ \ + once.@O@ stdtime.@O@ thread.@O@ time.@O@ @ISC_PK11_API_O@ + +# Alphabetically +SRCS = condition.c dir.c errno.c file.c \ + meminfo.c once.c fsaccess.c \ + stdtime.c thread.c time.c @ISC_PK11_API_C@ + +SUBDIRS = include +TARGETS = ${OBJS} + +@BIND9_MAKE_RULES@ diff --git a/lib/isc/win32/app.c b/lib/isc/win32/app.c new file mode 100644 index 0000000..35274a2 --- /dev/null +++ b/lib/isc/win32/app.c @@ -0,0 +1,481 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*% + * For BIND9 internal applications built with threads, we use a single app + * context and let multiple worker, I/O, timer threads do actual jobs. + */ + +static isc_thread_t blockedthread; + +/*% + * The following are intended for internal use (indicated by "isc__" + * prefix) but are not declared as static, allowing direct access from + * unit tests etc. + */ +isc_result_t isc__app_start(void); +isc_result_t isc__app_ctxstart(isc_appctx_t *ctx); +isc_result_t isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, + isc_taskaction_t action, void *arg); +isc_result_t isc__app_ctxrun(isc_appctx_t *ctx); +isc_result_t isc__app_run(void); +isc_result_t isc__app_ctxshutdown(isc_appctx_t *ctx); +isc_result_t isc__app_shutdown(void); +isc_result_t isc__app_reload(void); +isc_result_t isc__app_ctxsuspend(isc_appctx_t *ctx); +void isc__app_ctxfinish(isc_appctx_t *ctx); +void isc__app_finish(void); +void isc__app_block(void); +void isc__app_unblock(void); +isc_result_t isc__appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp); +void isc__appctx_destroy(isc_appctx_t **ctxp); +void isc__appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr); +void isc__appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr); +void isc__appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr); +isc_result_t isc__app_ctxonrun(isc_appctx_t *ctx, isc_mem_t *mctx, + isc_task_t *task, isc_taskaction_t action, + void *arg); + +/* + * The application context of this module. This implementation actually + * doesn't use it. (This may change in the future). + */ +#define APPCTX_MAGIC ISC_MAGIC('A', 'p', 'c', 'x') +#define VALID_APPCTX(c) ISC_MAGIC_VALID(c, APPCTX_MAGIC) + +/* Events to wait for */ + +#define NUM_EVENTS 2 + +enum { + RELOAD_EVENT, + SHUTDOWN_EVENT +}; + +typedef struct isc__appctx { + isc_appctx_t common; + isc_mem_t *mctx; + isc_eventlist_t on_run; + isc_mutex_t lock; + bool shutdown_requested; + bool running; + /* + * We assume that 'want_shutdown' can be read and written atomically. + */ + bool want_shutdown; + /* + * We assume that 'want_reload' can be read and written atomically. + */ + bool want_reload; + + bool blocked; + + HANDLE hEvents[NUM_EVENTS]; + + isc_taskmgr_t *taskmgr; + isc_socketmgr_t *socketmgr; + isc_timermgr_t *timermgr; +} isc__appctx_t; + +static isc__appctx_t isc_g_appctx; + +static struct { + isc_appmethods_t methods; + + /*% + * The following are defined just for avoiding unused static functions. + */ + void *run, *shutdown, *start, *reload, *finish, *block, *unblock; +} appmethods = { + { + isc__appctx_destroy, + isc__app_ctxstart, + isc__app_ctxrun, + isc__app_ctxsuspend, + isc__app_ctxshutdown, + isc__app_ctxfinish, + isc__appctx_settaskmgr, + isc__appctx_setsocketmgr, + isc__appctx_settimermgr, + isc__app_ctxonrun + }, + (void *)isc__app_run, + (void *)isc__app_shutdown, + (void *)isc__app_start, + (void *)isc__app_reload, + (void *)isc__app_finish, + (void *)isc__app_block, + (void *)isc__app_unblock +}; + +/* + * We need to remember which thread is the main thread... + */ +static isc_thread_t main_thread; + +isc_result_t +isc__app_ctxstart(isc_appctx_t *ctx0) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + isc_result_t result; + + REQUIRE(VALID_APPCTX(ctx)); + + /* + * Start an ISC library application. + */ + + main_thread = GetCurrentThread(); + + result = isc_mutex_init(&ctx->lock); + if (result != ISC_R_SUCCESS) + return (result); + + ctx->shutdown_requested = false; + ctx->running = false; + ctx->want_shutdown = false; + ctx->want_reload = false; + ctx->blocked = false; + + /* Create the reload event in a non-signaled state */ + ctx->hEvents[RELOAD_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL); + + /* Create the shutdown event in a non-signaled state */ + ctx->hEvents[SHUTDOWN_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL); + + ISC_LIST_INIT(ctx->on_run); + return (ISC_R_SUCCESS); +} + +isc_result_t +isc__app_start(void) { + isc_g_appctx.common.impmagic = APPCTX_MAGIC; + isc_g_appctx.common.magic = ISCAPI_APPCTX_MAGIC; + isc_g_appctx.common.methods = &appmethods.methods; + isc_g_appctx.mctx = NULL; + /* The remaining members will be initialized in ctxstart() */ + + return (isc__app_ctxstart((isc_appctx_t *)&isc_g_appctx)); +} + +isc_result_t +isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, + void *arg) +{ + return (isc__app_ctxonrun((isc_appctx_t *)&isc_g_appctx, mctx, + task, action, arg)); +} + +isc_result_t +isc__app_ctxonrun(isc_appctx_t *ctx0, isc_mem_t *mctx, isc_task_t *task, + isc_taskaction_t action, void *arg) +{ + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + isc_event_t *event; + isc_task_t *cloned_task = NULL; + isc_result_t result; + + LOCK(&ctx->lock); + + if (ctx->running) { + result = ISC_R_ALREADYRUNNING; + goto unlock; + } + + /* + * Note that we store the task to which we're going to send the event + * in the event's "sender" field. + */ + isc_task_attach(task, &cloned_task); + event = isc_event_allocate(mctx, cloned_task, ISC_APPEVENT_SHUTDOWN, + action, arg, sizeof(*event)); + if (event == NULL) { + result = ISC_R_NOMEMORY; + goto unlock; + } + + ISC_LINK_INIT(event, ev_link); + ISC_LIST_APPEND(ctx->on_run, event, ev_link); + + result = ISC_R_SUCCESS; + + unlock: + UNLOCK(&ctx->lock); + + return (result); +} + +isc_result_t +isc__app_ctxrun(isc_appctx_t *ctx0) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + isc_event_t *event, *next_event; + isc_task_t *task; + HANDLE *pHandles = NULL; + DWORD dwWaitResult; + + REQUIRE(VALID_APPCTX(ctx)); + + REQUIRE(main_thread == GetCurrentThread()); + + LOCK(&ctx->lock); + + if (!ctx->running) { + ctx->running = true; + + /* + * Post any on-run events (in FIFO order). + */ + for (event = ISC_LIST_HEAD(ctx->on_run); + event != NULL; + event = next_event) { + next_event = ISC_LIST_NEXT(event, ev_link); + ISC_LIST_UNLINK(ctx->on_run, event, ev_link); + task = event->ev_sender; + event->ev_sender = NULL; + isc_task_sendanddetach(&task, &event); + } + + } + + UNLOCK(&ctx->lock); + + /* + * There is no danger if isc_app_shutdown() is called before we wait + * for events. + */ + + while (!ctx->want_shutdown) { + dwWaitResult = WaitForMultipleObjects(NUM_EVENTS, ctx->hEvents, + FALSE, INFINITE); + + /* See why we returned */ + + if (WaitSucceeded(dwWaitResult, NUM_EVENTS)) { + /* + * The return was due to one of the events + * being signaled + */ + switch (WaitSucceededIndex(dwWaitResult)) { + case RELOAD_EVENT: + ctx->want_reload = true; + break; + + case SHUTDOWN_EVENT: + ctx->want_shutdown = true; + break; + } + } + + if (ctx->want_reload) { + ctx->want_reload = false; + return (ISC_R_RELOAD); + } + + if (ctx->want_shutdown && ctx->blocked) + exit(-1); + } + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc__app_run(void) { + return (isc__app_ctxrun((isc_appctx_t *)&isc_g_appctx)); +} + +isc_result_t +isc__app_ctxshutdown(isc_appctx_t *ctx0) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + bool want_kill = true; + + REQUIRE(VALID_APPCTX(ctx)); + + LOCK(&ctx->lock); + + REQUIRE(ctx->running); + + if (ctx->shutdown_requested) + want_kill = false; /* We're only signaling once */ + else + ctx->shutdown_requested = true; + + UNLOCK(&ctx->lock); + + if (want_kill) + SetEvent(ctx->hEvents[SHUTDOWN_EVENT]); + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc__app_shutdown(void) { + return (isc__app_ctxshutdown((isc_appctx_t *)&isc_g_appctx)); +} + +isc_result_t +isc__app_ctxsuspend(isc_appctx_t *ctx0) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + bool want_kill = true; + + REQUIRE(VALID_APPCTX(ctx)); + + LOCK(&ctx->lock); + + REQUIRE(ctx->running); + + /* + * Don't send the reload signal if we're shutting down. + */ + if (ctx->shutdown_requested) + want_kill = false; + + UNLOCK(&ctx->lock); + + if (want_kill) + SetEvent(ctx->hEvents[RELOAD_EVENT]); + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc__app_reload(void) { + return (isc__app_ctxsuspend((isc_appctx_t *)&isc_g_appctx)); +} + +void +isc__app_ctxfinish(isc_appctx_t *ctx0) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + + REQUIRE(VALID_APPCTX(ctx)); + + DESTROYLOCK(&ctx->lock); +} + +void +isc__app_finish(void) { + isc__app_ctxfinish((isc_appctx_t *)&isc_g_appctx); +} + +void +isc__app_block(void) { + REQUIRE(isc_g_appctx.running); + REQUIRE(!isc_g_appctx.blocked); + + isc_g_appctx.blocked = true; + blockedthread = GetCurrentThread(); +} + +void +isc__app_unblock(void) { + REQUIRE(isc_g_appctx.running); + REQUIRE(isc_g_appctx.blocked); + + isc_g_appctx.blocked = false; + REQUIRE(blockedthread == GetCurrentThread()); +} + +isc_result_t +isc__appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) { + isc__appctx_t *ctx; + + REQUIRE(mctx != NULL); + REQUIRE(ctxp != NULL && *ctxp == NULL); + + ctx = isc_mem_get(mctx, sizeof(*ctx)); + if (ctx == NULL) + return (ISC_R_NOMEMORY); + + ctx->common.impmagic = APPCTX_MAGIC; + ctx->common.magic = ISCAPI_APPCTX_MAGIC; + ctx->common.methods = &appmethods.methods; + + ctx->mctx = NULL; + isc_mem_attach(mctx, &ctx->mctx); + + ctx->taskmgr = NULL; + ctx->socketmgr = NULL; + ctx->timermgr = NULL; + + *ctxp = (isc_appctx_t *)ctx; + + return (ISC_R_SUCCESS); +} + +void +isc__appctx_destroy(isc_appctx_t **ctxp) { + isc__appctx_t *ctx; + + REQUIRE(ctxp != NULL); + ctx = (isc__appctx_t *)*ctxp; + REQUIRE(VALID_APPCTX(ctx)); + + isc_mem_putanddetach(&ctx->mctx, ctx, sizeof(*ctx)); + + *ctxp = NULL; +} + +void +isc__appctx_settaskmgr(isc_appctx_t *ctx0, isc_taskmgr_t *taskmgr) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + + REQUIRE(VALID_APPCTX(ctx)); + + ctx->taskmgr = taskmgr; +} + +void +isc__appctx_setsocketmgr(isc_appctx_t *ctx0, isc_socketmgr_t *socketmgr) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + + REQUIRE(VALID_APPCTX(ctx)); + + ctx->socketmgr = socketmgr; +} + +void +isc__appctx_settimermgr(isc_appctx_t *ctx0, isc_timermgr_t *timermgr) { + isc__appctx_t *ctx = (isc__appctx_t *)ctx0; + + REQUIRE(VALID_APPCTX(ctx)); + + ctx->timermgr = timermgr; +} + +isc_result_t +isc__app_register(void) { + return (isc_app_register(isc__appctx_create)); +} + +#include "../app_api.c" diff --git a/lib/isc/win32/condition.c b/lib/isc/win32/condition.c new file mode 100644 index 0000000..7887508 --- /dev/null +++ b/lib/isc/win32/condition.c @@ -0,0 +1,255 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#define LSIGNAL 0 +#define LBROADCAST 1 + +isc_result_t +isc_condition_init(isc_condition_t *cond) { + HANDLE h; + + REQUIRE(cond != NULL); + + cond->waiters = 0; + /* + * This handle is shared across all threads + */ + h = CreateEvent(NULL, FALSE, FALSE, NULL); + if (h == NULL) { + /* XXX */ + return (ISC_R_UNEXPECTED); + } + cond->events[LSIGNAL] = h; + + /* + * The threadlist will hold the actual events needed + * for the wait condition + */ + ISC_LIST_INIT(cond->threadlist); + + return (ISC_R_SUCCESS); +} + +/* + * Add the thread to the threadlist along with the required events + */ +static isc_result_t +register_thread(unsigned long thrd, isc_condition_t *gblcond, + isc_condition_thread_t **localcond) +{ + HANDLE hc; + isc_condition_thread_t *newthread; + + REQUIRE(localcond != NULL && *localcond == NULL); + + newthread = malloc(sizeof(isc_condition_thread_t)); + if (newthread == NULL) + return (ISC_R_NOMEMORY); + + /* + * Create the thread-specific handle + */ + hc = CreateEvent(NULL, FALSE, FALSE, NULL); + if (hc == NULL) { + free(newthread); + return (ISC_R_UNEXPECTED); + } + + /* + * Add the thread ID and handles to list of threads for broadcast + */ + newthread->handle[LSIGNAL] = gblcond->events[LSIGNAL]; + newthread->handle[LBROADCAST] = hc; + newthread->th = thrd; + + /* + * The thread is holding the manager lock so this is safe + */ + ISC_LINK_INIT(newthread, link); + ISC_LIST_APPEND(gblcond->threadlist, newthread, link); + *localcond = newthread; + return (ISC_R_SUCCESS); +} + +static isc_result_t +find_thread_condition(unsigned long thrd, isc_condition_t *cond, + isc_condition_thread_t **threadcondp) +{ + isc_condition_thread_t *threadcond; + + REQUIRE(threadcondp != NULL && *threadcondp == NULL); + + /* + * Look for the thread ID. + */ + for (threadcond = ISC_LIST_HEAD(cond->threadlist); + threadcond != NULL; + threadcond = ISC_LIST_NEXT(threadcond, link)) { + + if (threadcond->th == thrd) { + *threadcondp = threadcond; + return (ISC_R_SUCCESS); + } + } + + /* + * Not found, so add it. + */ + return (register_thread(thrd, cond, threadcondp)); +} + +isc_result_t +isc_condition_signal(isc_condition_t *cond) { + + /* + * Unlike pthreads, the caller MUST hold the lock associated with + * the condition variable when calling us. + */ + REQUIRE(cond != NULL); + + if (!SetEvent(cond->events[LSIGNAL])) { + /* XXX */ + return (ISC_R_UNEXPECTED); + } + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_condition_broadcast(isc_condition_t *cond) { + + isc_condition_thread_t *threadcond; + bool failed = false; + + /* + * Unlike pthreads, the caller MUST hold the lock associated with + * the condition variable when calling us. + */ + REQUIRE(cond != NULL); + + /* + * Notify every thread registered for this + */ + for (threadcond = ISC_LIST_HEAD(cond->threadlist); + threadcond != NULL; + threadcond = ISC_LIST_NEXT(threadcond, link)) { + + if (!SetEvent(threadcond->handle[LBROADCAST])) + failed = true; + } + + if (failed) + return (ISC_R_UNEXPECTED); + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_condition_destroy(isc_condition_t *cond) { + + isc_condition_thread_t *next, *threadcond; + + REQUIRE(cond != NULL); + REQUIRE(cond->waiters == 0); + + (void)CloseHandle(cond->events[LSIGNAL]); + + /* + * Delete the threadlist + */ + threadcond = ISC_LIST_HEAD(cond->threadlist); + + while (threadcond != NULL) { + next = ISC_LIST_NEXT(threadcond, link); + DEQUEUE(cond->threadlist, threadcond, link); + (void) CloseHandle(threadcond->handle[LBROADCAST]); + free(threadcond); + threadcond = next; + } + + return (ISC_R_SUCCESS); +} + +/* + * This is always called when the mutex (lock) is held, but because + * we are waiting we need to release it and reacquire it as soon as the wait + * is over. This allows other threads to make use of the object guarded + * by the mutex but it should never try to delete it as long as the + * number of waiters > 0. Always reacquire the mutex regardless of the + * result of the wait. Note that EnterCriticalSection will wait to acquire + * the mutex. + */ +static isc_result_t +wait(isc_condition_t *cond, isc_mutex_t *mutex, DWORD milliseconds) { + DWORD result; + isc_result_t tresult; + isc_condition_thread_t *threadcond = NULL; + + /* + * Get the thread events needed for the wait + */ + tresult = find_thread_condition(isc_thread_self(), cond, &threadcond); + if (tresult != ISC_R_SUCCESS) + return (tresult); + + cond->waiters++; + LeaveCriticalSection(mutex); + result = WaitForMultipleObjects(2, threadcond->handle, FALSE, + milliseconds); + EnterCriticalSection(mutex); + cond->waiters--; + if (result == WAIT_FAILED) { + /* XXX */ + return (ISC_R_UNEXPECTED); + } + if (result == WAIT_TIMEOUT) + return (ISC_R_TIMEDOUT); + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_condition_wait(isc_condition_t *cond, isc_mutex_t *mutex) { + return (wait(cond, mutex, INFINITE)); +} + +isc_result_t +isc_condition_waituntil(isc_condition_t *cond, isc_mutex_t *mutex, + isc_time_t *t) { + DWORD milliseconds; + uint64_t microseconds; + isc_time_t now; + + if (isc_time_now(&now) != ISC_R_SUCCESS) { + /* XXX */ + return (ISC_R_UNEXPECTED); + } + + microseconds = isc_time_microdiff(t, &now); + if (microseconds > 0xFFFFFFFFi64 * 1000) + milliseconds = 0xFFFFFFFF; + else + milliseconds = (DWORD)(microseconds / 1000); + + return (wait(cond, mutex, milliseconds)); +} diff --git a/lib/isc/win32/dir.c b/lib/isc/win32/dir.c new file mode 100644 index 0000000..5db2c23 --- /dev/null +++ b/lib/isc/win32/dir.c @@ -0,0 +1,307 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "errno2result.h" + +#define ISC_DIR_MAGIC ISC_MAGIC('D', 'I', 'R', '*') +#define VALID_DIR(dir) ISC_MAGIC_VALID(dir, ISC_DIR_MAGIC) + +static isc_result_t +start_directory(isc_dir_t *p); + +void +isc_dir_init(isc_dir_t *dir) { + REQUIRE(dir != NULL); + + dir->dirname[0] = '\0'; + + dir->entry.name[0] = '\0'; + dir->entry.length = 0; + memset(&(dir->entry.find_data), 0, sizeof(dir->entry.find_data)); + + dir->entry_filled = false; + dir->search_handle = INVALID_HANDLE_VALUE; + + dir->magic = ISC_DIR_MAGIC; +} + +/* + * Allocate workspace and open directory stream. If either one fails, + * NULL will be returned. + */ +isc_result_t +isc_dir_open(isc_dir_t *dir, const char *dirname) { + char *p; + isc_result_t result; + + REQUIRE(dirname != NULL); + REQUIRE(VALID_DIR(dir) && dir->search_handle == INVALID_HANDLE_VALUE); + + /* + * Copy directory name. Need to have enough space for the name, + * a possible path separator, the wildcard, and the final NUL. + */ + if (strlen(dirname) + 3 > sizeof(dir->dirname)) + /* XXXDCL ? */ + return (ISC_R_NOSPACE); + strlcpy(dir->dirname, dirname, sizeof(dir->dirname)); + + /* + * Append path separator, if needed, and "*". + */ + p = dir->dirname + strlen(dir->dirname); + if (dir->dirname < p && *(p - 1) != '\\' && *(p - 1) != ':') + *p++ = '\\'; + *p++ = '*'; + *p = '\0'; + + /* + * Open stream. + */ + result = start_directory(dir); + + return (result); +} + +/* + * Return previously retrieved file or get next one. Unix's dirent has + * separate open and read functions, but the Win32 and DOS interfaces open + * the dir stream and reads the first file in one operation. + */ +isc_result_t +isc_dir_read(isc_dir_t *dir) { + REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE); + + if (dir->entry_filled) + /* + * start_directory() already filled in the first entry. + */ + dir->entry_filled = false; + + else { + /* + * Fetch next file in directory. + */ + if (FindNextFile(dir->search_handle, + &dir->entry.find_data) == FALSE) + /* + * Either the last file has been processed or + * an error has occurred. The former is not + * really an error, but the latter is. + */ + if (GetLastError() == ERROR_NO_MORE_FILES) + return (ISC_R_NOMORE); + else + return (ISC_R_UNEXPECTED); + } + + /* + * Make sure that the space for the name is long enough. + */ + strlcpy(dir->entry.name, dir->entry.find_data.cFileName, + sizeof(dir->entry.name)); + dir->entry.length = strlen(dir->entry.name); + + return (ISC_R_SUCCESS); +} + +/* + * Close directory stream. + */ +void +isc_dir_close(isc_dir_t *dir) { + REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE); + + FindClose(dir->search_handle); + dir->search_handle = INVALID_HANDLE_VALUE; +} + +/* + * Reposition directory stream at start. + */ +isc_result_t +isc_dir_reset(isc_dir_t *dir) { + isc_result_t result; + + REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE); + REQUIRE(dir->dirname != NULL); + + /* + * NT cannot reposition the seek pointer to the beginning of the + * the directory stream, but rather the directory needs to be + * closed and reopened. The latter might fail. + */ + + isc_dir_close(dir); + + result = start_directory(dir); + + return (result); +} + +/* + * Initialize isc_dir_t structure with new directory. The function + * returns 0 on failure and nonzero on success. + * + * Note: + * - Be sure to close previous stream before opening new one + */ +static isc_result_t +start_directory(isc_dir_t *dir) +{ + REQUIRE(VALID_DIR(dir)); + REQUIRE(dir->search_handle == INVALID_HANDLE_VALUE); + + dir->entry_filled = false; + + /* + * Open stream and retrieve first file. + */ + dir->search_handle = FindFirstFile(dir->dirname, + &dir->entry.find_data); + + if (dir->search_handle == INVALID_HANDLE_VALUE) { + /* + * Something went wrong but we don't know what. GetLastError() + * could give us more information about the error, but the + * MSDN documentation is frustratingly thin about what + * possible errors could have resulted. (Score one for + * the Unix manual pages.) So there is just this lame error + * instead of being able to differentiate ISC_R_NOTFOUND + * from ISC_R_UNEXPECTED. + */ + return (ISC_R_FAILURE); + } + + /* + * Make sure that the space for the name is long enough. + */ + INSIST(sizeof(dir->entry.name) > + strlen(dir->entry.find_data.cFileName)); + + /* + * Fill in the data for the first entry of the directory. + */ + strlcpy(dir->entry.name, dir->entry.find_data.cFileName, + sizeof(dir->entry.name)); + dir->entry.length = strlen(dir->entry.name); + + dir->entry_filled = true; + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_dir_chdir(const char *dirname) { + /* + * Change the current directory to 'dirname'. + */ + + REQUIRE(dirname != NULL); + + if (chdir(dirname) < 0) + return (isc__errno2result(errno)); + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_dir_chroot(const char *dirname) { + return (ISC_R_NOTIMPLEMENTED); +} + +isc_result_t +isc_dir_createunique(char *templet) { + isc_result_t result; + char *x; + char *p; + int i; + int pid; + + REQUIRE(templet != NULL); + + /* + * mkdtemp is not portable, so this emulates it. + */ + + pid = getpid(); + + /* + * Replace trailing Xs with the process-id, zero-filled. + */ + for (x = templet + strlen(templet) - 1; *x == 'X' && x >= templet; + x--, pid /= 10) + *x = pid % 10 + '0'; + + x++; /* Set x to start of ex-Xs. */ + + do { + i = mkdir(templet); + if (i == 0) + i = chmod(templet, 0700); + + if (i == 0 || errno != EEXIST) + break; + + /* + * The BSD algorithm. + */ + p = x; + while (*p != '\0') { + if (isdigit(*p & 0xff)) + *p = 'a'; + else if (*p != 'z') + ++*p; + else { + /* + * Reset character and move to next. + */ + *p++ = 'a'; + continue; + } + + break; + } + + if (*p == '\0') { + /* + * Tried all combinations. errno should already + * be EEXIST, but ensure it is anyway for + * isc__errno2result(). + */ + errno = EEXIST; + break; + } + } while (1); + + if (i == -1) + result = isc__errno2result(errno); + else + result = ISC_R_SUCCESS; + + return (result); +} diff --git a/lib/isc/win32/entropy.c b/lib/isc/win32/entropy.c new file mode 100644 index 0000000..2480c02 --- /dev/null +++ b/lib/isc/win32/entropy.c @@ -0,0 +1,299 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* + * This is the system dependent part of the ISC entropy API. + */ + +#include + +#include + +#include +#include + +#include +#include +#include + +/* + * There is only one variable in the entropy data structures that is not + * system independent, but pulling the structure that uses it into this file + * ultimately means pulling several other independent structures here also to + * resolve their interdependencies. Thus only the problem variable's type + * is defined here. + */ +#define FILESOURCE_HANDLE_TYPE HCRYPTPROV + +typedef struct { + int dummy; +} isc_entropyusocketsource_t; + +#include "../entropy.c" + +static unsigned int +get_from_filesource(isc_entropysource_t *source, uint32_t desired) { + isc_entropy_t *ent = source->ent; + unsigned char buf[128]; + HCRYPTPROV hcryptprov = source->sources.file.handle; + ssize_t ndesired; + unsigned int added; + + if (source->bad) + return (0); + + desired = desired / 8 + (((desired & 0x07) > 0) ? 1 : 0); + + added = 0; + while (desired > 0) { + ndesired = ISC_MIN(desired, sizeof(buf)); + if (!CryptGenRandom(hcryptprov, (DWORD)ndesired, buf)) { + CryptReleaseContext(hcryptprov, 0); + source->bad = true; + goto out; + } + + entropypool_adddata(ent, buf, + (unsigned int)ndesired, + (unsigned int)ndesired * 8); + added += (unsigned int)ndesired * 8; + desired -= (uint32_t)ndesired; + } + + out: + return (added); +} + +/* + * Poll each source, trying to get data from it to stuff into the entropy + * pool. + */ +static void +fillpool(isc_entropy_t *ent, unsigned int desired, bool blocking) { + unsigned int added; + unsigned int remaining; + unsigned int needed; + unsigned int nsource; + isc_entropysource_t *source; + isc_entropysource_t *firstsource; + + REQUIRE(VALID_ENTROPY(ent)); + + needed = desired; + + /* + * This logic is a little strange, so an explanation is in order. + * + * If needed is 0, it means we are being asked to "fill to whatever + * we think is best." This means that if we have at least a + * partially full pool (say, > 1/4th of the pool) we probably don't + * need to add anything. + * + * Also, we will check to see if the "pseudo" count is too high. + * If it is, try to mix in better data. Too high is currently + * defined as 1/4th of the pool. + * + * Next, if we are asked to add a specific bit of entropy, make + * certain that we will do so. Clamp how much we try to add to + * (DIGEST_SIZE * 8 < needed < POOLBITS - entropy). + * + * Note that if we are in a blocking mode, we will only try to + * get as much data as we need, not as much as we might want + * to build up. + */ + if (needed == 0) { + REQUIRE(!blocking); + + if ((ent->pool.entropy >= RND_POOLBITS / 4) + && (ent->pool.pseudo <= RND_POOLBITS / 4)) + return; + + needed = THRESHOLD_BITS * 4; + } else { + needed = ISC_MAX(needed, THRESHOLD_BITS); + needed = ISC_MIN(needed, RND_POOLBITS); + } + + /* + * In any case, clamp how much we need to how much we can add. + */ + needed = ISC_MIN(needed, RND_POOLBITS - ent->pool.entropy); + + /* + * But wait! If we're not yet initialized, we need at least + * THRESHOLD_BITS + * of randomness. + */ + if (ent->initialized < THRESHOLD_BITS) + needed = ISC_MAX(needed, THRESHOLD_BITS - ent->initialized); + + /* + * Poll each file source to see if we can read anything useful from + * it. XXXMLG When where are multiple sources, we should keep a + * record of which one we last used so we can start from it (or the + * next one) to avoid letting some sources build up entropy while + * others are always drained. + */ + + added = 0; + remaining = needed; + if (ent->nextsource == NULL) { + ent->nextsource = ISC_LIST_HEAD(ent->sources); + if (ent->nextsource == NULL) + return; + } + source = ent->nextsource; + /* + * Remember the first source so we can break if we have looped back to + * the beginning and still have nothing + */ + firstsource = source; + again_file: + for (nsource = 0; nsource < ent->nsources; nsource++) { + unsigned int got; + + if (remaining == 0) + break; + + got = 0; + + if (source->type == ENTROPY_SOURCETYPE_FILE) + got = get_from_filesource(source, remaining); + + added += got; + + remaining -= ISC_MIN(remaining, got); + + source = ISC_LIST_NEXT(source, link); + if (source == NULL) + source = ISC_LIST_HEAD(ent->sources); + } + ent->nextsource = source; + + /* + * Go again only if there's been progress and we've not + * gone back to the beginning + */ + if (!(ent->nextsource == firstsource && added == 0)) { + if (blocking && remaining != 0) { + goto again_file; + } + } + + /* + * Here, if there are bits remaining to be had and we can block, + * check to see if we have a callback source. If so, call them. + */ + source = ISC_LIST_HEAD(ent->sources); + while ((remaining != 0) && (source != NULL)) { + unsigned int got; + + got = 0; + + if (source->type == ENTROPY_SOURCETYPE_CALLBACK) + got = get_from_callback(source, remaining, blocking); + + added += got; + remaining -= ISC_MIN(remaining, got); + + if (added >= needed) + break; + + source = ISC_LIST_NEXT(source, link); + } + + /* + * Mark as initialized if we've added enough data. + */ + if (ent->initialized < THRESHOLD_BITS) + ent->initialized += added; +} + + + +/* + * Requires "ent" be locked. + */ +static void +destroyfilesource(isc_entropyfilesource_t *source) { + CryptReleaseContext(source->handle, 0); +} + +static void +destroyusocketsource(isc_entropyusocketsource_t *source) { + UNUSED(source); +} + + +isc_result_t +isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) { + isc_result_t ret; + isc_entropysource_t *source; + HCRYPTPROV hcryptprov; + BOOL err; + + REQUIRE(VALID_ENTROPY(ent)); + REQUIRE(fname != NULL); + + LOCK(&ent->lock); + + source = NULL; + + /* + * The first time we just try to acquire the context + */ + err = CryptAcquireContext(&hcryptprov, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT); + if (!err){ + (void)GetLastError(); + ret = ISC_R_IOERROR; + goto errout; + } + + source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t)); + if (source == NULL) { + ret = ISC_R_NOMEMORY; + goto closecontext; + } + + /* + * From here down, no failures can occur. + */ + source->magic = SOURCE_MAGIC; + source->type = ENTROPY_SOURCETYPE_FILE; + source->ent = ent; + source->total = 0; + source->bad = false; + memset(source->name, 0, sizeof(source->name)); + ISC_LINK_INIT(source, link); + source->sources.file.handle = hcryptprov; + + /* + * Hook it into the entropy system. + */ + ISC_LIST_APPEND(ent->sources, source, link); + ent->nsources++; + + UNLOCK(&ent->lock); + return (ISC_R_SUCCESS); + + closecontext: + CryptReleaseContext(hcryptprov, 0); + + errout: + if (source != NULL) + isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t)); + + UNLOCK(&ent->lock); + + return (ret); +} diff --git a/lib/isc/win32/errno.c b/lib/isc/win32/errno.c new file mode 100644 index 0000000..74ebf0c --- /dev/null +++ b/lib/isc/win32/errno.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include + +#include "errno2result.h" + +isc_result_t +isc_errno_toresult(int err) { + return (isc__errno2resultx(err, false, 0, 0)); +} diff --git a/lib/isc/win32/errno2result.c b/lib/isc/win32/errno2result.c new file mode 100644 index 0000000..83dbb4e --- /dev/null +++ b/lib/isc/win32/errno2result.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include + +#include + +#include +#include "errno2result.h" +#include +#include +#include + +/* + * Convert a POSIX errno value into an isc_result_t. The + * list of supported errno values is not complete; new users + * of this function should add any expected errors that are + * not already there. + */ +isc_result_t +isc__errno2resultx(int posixerrno, bool dolog, + const char *file, int line) +{ + char strbuf[ISC_STRERRORSIZE]; + + switch (posixerrno) { + case ENOTDIR: + case WSAELOOP: + case WSAEINVAL: + case EINVAL: /* XXX sometimes this is not for files */ + case ENAMETOOLONG: + case WSAENAMETOOLONG: + case EBADF: + case WSAEBADF: + return (ISC_R_INVALIDFILE); + case ENOENT: + return (ISC_R_FILENOTFOUND); + case EACCES: + case WSAEACCES: + case EPERM: + return (ISC_R_NOPERM); + case EEXIST: + return (ISC_R_FILEEXISTS); + case EIO: + return (ISC_R_IOERROR); + case ENOMEM: + return (ISC_R_NOMEMORY); +#ifdef EOVERFLOW + case EOVERFLOW: + return (ISC_R_RANGE); +#endif + case ENFILE: + case EMFILE: + case WSAEMFILE: + return (ISC_R_TOOMANYOPENFILES); + case ERROR_CANCELLED: + return (ISC_R_CANCELED); + case ERROR_CONNECTION_REFUSED: + case WSAECONNREFUSED: + return (ISC_R_CONNREFUSED); + case WSAENOTCONN: + case ERROR_CONNECTION_INVALID: + return (ISC_R_NOTCONNECTED); + case ERROR_HOST_UNREACHABLE: + case WSAEHOSTUNREACH: + return (ISC_R_HOSTUNREACH); + case ERROR_NETWORK_UNREACHABLE: + case WSAENETUNREACH: + return (ISC_R_NETUNREACH); + case ERROR_NO_NETWORK: + return (ISC_R_NETUNREACH); + case ERROR_PORT_UNREACHABLE: + return (ISC_R_HOSTUNREACH); + case ERROR_SEM_TIMEOUT: + return (ISC_R_TIMEDOUT); + case WSAECONNRESET: + case WSAENETRESET: + case WSAECONNABORTED: + case WSAEDISCON: + case ERROR_OPERATION_ABORTED: + case ERROR_CONNECTION_ABORTED: + case ERROR_REQUEST_ABORTED: + return (ISC_R_CONNECTIONRESET); + case WSAEADDRNOTAVAIL: + return (ISC_R_ADDRNOTAVAIL); + case ERROR_NETNAME_DELETED: + case WSAENETDOWN: + return (ISC_R_NETUNREACH); + case WSAEHOSTDOWN: + return (ISC_R_HOSTUNREACH); + case WSAENOBUFS: + return (ISC_R_NORESOURCES); + default: + if (dolog) { + isc__strerror(posixerrno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(file, line, + "unable to convert errno " + "to isc_result: %d: %s", + posixerrno, strbuf); + } + /* + * XXXDCL would be nice if perhaps this function could + * return the system's error string, so the caller + * might have something more descriptive than "unexpected + * error" to log with. + */ + return (ISC_R_UNEXPECTED); + } +} diff --git a/lib/isc/win32/errno2result.h b/lib/isc/win32/errno2result.h new file mode 100644 index 0000000..99752ae --- /dev/null +++ b/lib/isc/win32/errno2result.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef UNIX_ERRNO2RESULT_H +#define UNIX_ERRNO2RESULT_H 1 + +/* XXXDCL this should be moved to lib/isc/include/isc/errno2result.h. */ + +#include /* Provides errno. */ +#include + +#include +#include + +ISC_LANG_BEGINDECLS + +#define isc__errno2result(posixerrno) \ + isc__errno2resultx(posixerrno, true, __FILE__, __LINE__) + +isc_result_t +isc__errno2resultx(int posixerrno, bool dolog, + const char *file, int line); + +ISC_LANG_ENDDECLS + +#endif /* UNIX_ERRNO2RESULT_H */ diff --git a/lib/isc/win32/file.c b/lib/isc/win32/file.c new file mode 100644 index 0000000..d281ba1 --- /dev/null +++ b/lib/isc/win32/file.c @@ -0,0 +1,928 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include + +#undef rename +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "errno2result.h" + +static const char alphnum[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + +/* + * Emulate UNIX mkstemp, which returns an open FD to the new file + * + */ +static int +gettemp(char *path, bool binary, int *doopen) { + char *start, *trv; + struct stat sbuf; + int flags = O_CREAT|O_EXCL|O_RDWR; + + if (binary) + flags |= _O_BINARY; + + trv = strrchr(path, 'X'); + trv++; + /* extra X's get set to 0's */ + while (*--trv == 'X') { + uint32_t which; + + isc_random_get(&which); + *trv = alphnum[which % (sizeof(alphnum) - 1)]; + } + /* + * check the target directory; if you have six X's and it + * doesn't exist this runs for a *very* long time. + */ + for (start = trv + 1;; --trv) { + if (trv <= path) + break; + if (*trv == '\\') { + *trv = '\0'; + if (stat(path, &sbuf)) + return (0); + if (!S_ISDIR(sbuf.st_mode)) { + errno = ENOTDIR; + return (0); + } + *trv = '\\'; + break; + } + } + + for (;;) { + if (doopen) { + if ((*doopen = + open(path, flags, _S_IREAD | _S_IWRITE)) >= 0) + return (1); + if (errno != EEXIST) + return (0); + } else if (stat(path, &sbuf)) + return (errno == ENOENT ? 1 : 0); + + /* tricky little algorithm for backward compatibility */ + for (trv = start;;) { + if (!*trv) + return (0); + if (*trv == 'z') + *trv++ = 'a'; + else { + if (isdigit(*trv)) + *trv = 'a'; + else + ++*trv; + break; + } + } + } + /*NOTREACHED*/ +} + +static int +mkstemp(char *path, bool binary) { + int fd; + + return (gettemp(path, binary, &fd) ? fd : -1); +} + +/* + * XXXDCL As the API for accessing file statistics undoubtedly gets expanded, + * it might be good to provide a mechanism that allows for the results + * of a previous stat() to be used again without having to do another stat, + * such as perl's mechanism of using "_" in place of a file name to indicate + * that the results of the last stat should be used. But then you get into + * annoying MP issues. BTW, Win32 has stat(). + */ +static isc_result_t +file_stats(const char *file, struct stat *stats) { + isc_result_t result = ISC_R_SUCCESS; + + REQUIRE(file != NULL); + REQUIRE(stats != NULL); + + if (stat(file, stats) != 0) + result = isc__errno2result(errno); + + return (result); +} + +static isc_result_t +fd_stats(int fd, struct stat *stats) { + isc_result_t result = ISC_R_SUCCESS; + + REQUIRE(stats != NULL); + + if (fstat(fd, stats) != 0) + result = isc__errno2result(errno); + + return (result); +} + +isc_result_t +isc_file_getsizefd(int fd, off_t *size) { + isc_result_t result; + struct stat stats; + + REQUIRE(size != NULL); + + result = fd_stats(fd, &stats); + + if (result == ISC_R_SUCCESS) + *size = stats.st_size; + return (result); +} + +isc_result_t +isc_file_mode(const char *file, mode_t *modep) { + isc_result_t result; + struct stat stats; + + REQUIRE(modep != NULL); + + result = file_stats(file, &stats); + if (result == ISC_R_SUCCESS) + *modep = (stats.st_mode & 07777); + return (result); +} + +/* + * isc_file_safemovefile is needed to be defined here to ensure that + * any file with the new name is renamed to a backup name and then the + * rename is done. If all goes well then the backup can be deleted, + * otherwise it gets renamed back. + */ + +int +isc_file_safemovefile(const char *oldname, const char *newname) { + BOOL filestatus; + char buf[512]; + struct stat sbuf; + BOOL exists = FALSE; + int tmpfd; + + /* + * Make sure we have something to do + */ + if (stat(oldname, &sbuf) != 0) { + errno = ENOENT; + return (-1); + } + + /* + * Rename to a backup the new file if it still exists + */ + if (stat(newname, &sbuf) == 0) { + exists = TRUE; + strlcpy(buf, newname, sizeof(buf)); + strlcat(buf, ".XXXXX", sizeof(buf)); + tmpfd = mkstemp(buf, true); + if (tmpfd > 0) + _close(tmpfd); + (void)DeleteFile(buf); + _chmod(newname, _S_IREAD | _S_IWRITE); + + filestatus = MoveFile(newname, buf); + } + /* Now rename the file to the new name + */ + _chmod(oldname, _S_IREAD | _S_IWRITE); + + filestatus = MoveFile(oldname, newname); + if (filestatus == 0) { + /* + * Try to rename the backup back to the original name + * if the backup got created + */ + if (exists == TRUE) { + filestatus = MoveFile(buf, newname); + if (filestatus == 0) + errno = EACCES; + } + return (-1); + } + + /* + * Delete the backup file if it got created + */ + if (exists == TRUE) + (void)DeleteFile(buf); + return (0); +} + +isc_result_t +isc_file_getmodtime(const char *file, isc_time_t *time) { + int fh; + + REQUIRE(file != NULL); + REQUIRE(time != NULL); + + if ((fh = open(file, _O_RDONLY | _O_BINARY)) < 0) + return (isc__errno2result(errno)); + + if (!GetFileTime((HANDLE) _get_osfhandle(fh), + NULL, + NULL, + &time->absolute)) + { + close(fh); + errno = EINVAL; + return (isc__errno2result(errno)); + } + close(fh); + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_file_getsize(const char *file, off_t *size) { + isc_result_t result; + struct stat stats; + + REQUIRE(file != NULL); + REQUIRE(size != NULL); + + result = file_stats(file, &stats); + + if (result == ISC_R_SUCCESS) + *size = stats.st_size; + + return (result); +} + +isc_result_t +isc_file_settime(const char *file, isc_time_t *time) { + int fh; + + REQUIRE(file != NULL && time != NULL); + + if ((fh = open(file, _O_RDWR | _O_BINARY)) < 0) + return (isc__errno2result(errno)); + + /* + * Set the date via the filedate system call and return. Failing + * this call implies the new file times are not supported by the + * underlying file system. + */ + if (!SetFileTime((HANDLE) _get_osfhandle(fh), + NULL, + &time->absolute, + &time->absolute)) + { + close(fh); + errno = EINVAL; + return (isc__errno2result(errno)); + } + + close(fh); + return (ISC_R_SUCCESS); + +} + +#undef TEMPLATE +#define TEMPLATE "XXXXXXXXXX.tmp" /* 14 characters. */ + +isc_result_t +isc_file_mktemplate(const char *path, char *buf, size_t buflen) { + return (isc_file_template(path, TEMPLATE, buf, buflen)); +} + +isc_result_t +isc_file_template(const char *path, const char *templet, char *buf, + size_t buflen) +{ + char *s; + + REQUIRE(templet != NULL); + REQUIRE(buf != NULL); + + if (path == NULL) + path = ""; + + s = strrchr(templet, '\\'); + if (s != NULL) + templet = s + 1; + + s = strrchr(path, '\\'); + + if (s != NULL) { + size_t prefixlen = s - path + 1; + if ((prefixlen + strlen(templet) + 1) > buflen) + return (ISC_R_NOSPACE); + + /* Copy 'prefixlen' bytes and NUL terminate. */ + strlcpy(buf, path, ISC_MIN(prefixlen + 1, buflen)); + strlcat(buf, templet, buflen); + } else { + if ((strlen(templet) + 1) > buflen) + return (ISC_R_NOSPACE); + + strlcpy(buf, templet, buflen); + } + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_file_renameunique(const char *file, char *templet) { + int fd; + int res = 0; + isc_result_t result = ISC_R_SUCCESS; + + REQUIRE(file != NULL); + REQUIRE(templet != NULL); + + fd = mkstemp(templet, true); + if (fd == -1) + result = isc__errno2result(errno); + else + close(fd); + + if (result == ISC_R_SUCCESS) { + res = isc_file_safemovefile(file, templet); + if (res != 0) { + result = isc__errno2result(errno); + (void)unlink(templet); + } + } + return (result); +} + +static isc_result_t +openuniquemode(char *templet, int mode, bool binary, FILE **fp) { + int fd; + FILE *f; + isc_result_t result = ISC_R_SUCCESS; + + REQUIRE(templet != NULL); + REQUIRE(fp != NULL && *fp == NULL); + + /* + * Win32 does not have mkstemp. Using emulation above. + */ + fd = mkstemp(templet, binary); + + if (fd == -1) + result = isc__errno2result(errno); + if (result == ISC_R_SUCCESS) { +#if 1 + UNUSED(mode); +#else + (void)fchmod(fd, mode); +#endif + f = fdopen(fd, binary ? "wb+" : "w+"); + if (f == NULL) { + result = isc__errno2result(errno); + (void)remove(templet); + (void)close(fd); + } else + *fp = f; + } + + return (result); +} + +isc_result_t +isc_file_openuniqueprivate(char *templet, FILE **fp) { + int mode = _S_IREAD | _S_IWRITE; + return (openuniquemode(templet, mode, false, fp)); +} + +isc_result_t +isc_file_openunique(char *templet, FILE **fp) { + int mode = _S_IREAD | _S_IWRITE; + return (openuniquemode(templet, mode, false, fp)); +} + +isc_result_t +isc_file_openuniquemode(char *templet, int mode, FILE **fp) { + return (openuniquemode(templet, mode, false, fp)); +} + +isc_result_t +isc_file_bopenuniqueprivate(char *templet, FILE **fp) { + int mode = _S_IREAD | _S_IWRITE; + return (openuniquemode(templet, mode, true, fp)); +} + +isc_result_t +isc_file_bopenunique(char *templet, FILE **fp) { + int mode = _S_IREAD | _S_IWRITE; + return (openuniquemode(templet, mode, true, fp)); +} + +isc_result_t +isc_file_bopenuniquemode(char *templet, int mode, FILE **fp) { + return (openuniquemode(templet, mode, true, fp)); +} + +isc_result_t +isc_file_remove(const char *filename) { + int r; + + REQUIRE(filename != NULL); + + r = unlink(filename); + if (r == 0) + return (ISC_R_SUCCESS); + else + return (isc__errno2result(errno)); +} + +isc_result_t +isc_file_rename(const char *oldname, const char *newname) { + int r; + + REQUIRE(oldname != NULL); + REQUIRE(newname != NULL); + + r = isc_file_safemovefile(oldname, newname); + if (r == 0) + return (ISC_R_SUCCESS); + else + return (isc__errno2result(errno)); +} + +bool +isc_file_exists(const char *pathname) { + struct stat stats; + + REQUIRE(pathname != NULL); + + return (file_stats(pathname, &stats) == ISC_R_SUCCESS); +} + +isc_result_t +isc_file_isplainfile(const char *filename) { + /* + * This function returns success if filename is a plain file. + */ + struct stat filestat; + memset(&filestat,0,sizeof(struct stat)); + + if ((stat(filename, &filestat)) == -1) + return(isc__errno2result(errno)); + + if(! S_ISREG(filestat.st_mode)) + return(ISC_R_INVALIDFILE); + + return(ISC_R_SUCCESS); +} + +isc_result_t +isc_file_isplainfilefd(int fd) { + /* + * This function returns success if filename is a plain file. + */ + struct stat filestat; + memset(&filestat,0,sizeof(struct stat)); + + if ((fstat(fd, &filestat)) == -1) + return(isc__errno2result(errno)); + + if(! S_ISREG(filestat.st_mode)) + return(ISC_R_INVALIDFILE); + + return(ISC_R_SUCCESS); +} + +isc_result_t +isc_file_isdirectory(const char *filename) { + /* + * This function returns success if filename is a directory. + */ + struct stat filestat; + memset(&filestat,0,sizeof(struct stat)); + + if ((stat(filename, &filestat)) == -1) + return(isc__errno2result(errno)); + + if(! S_ISDIR(filestat.st_mode)) + return(ISC_R_INVALIDFILE); + + return(ISC_R_SUCCESS); +} + + +bool +isc_file_isabsolute(const char *filename) { + REQUIRE(filename != NULL); + /* + * Look for c:\path\... style, c:/path/... or \\computer\shar\path... + * the UNC style file specs + */ + if ((filename[0] == '\\') && (filename[1] == '\\')) + return (true); + if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '\\') + return (true); + if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '/') + return (true); + return (false); +} + +bool +isc_file_iscurrentdir(const char *filename) { + REQUIRE(filename != NULL); + return (filename[0] == '.' && filename[1] == '\0'); +} + +bool +isc_file_ischdiridempotent(const char *filename) { + REQUIRE(filename != NULL); + + if (isc_file_isabsolute(filename)) + return (true); + if (filename[0] == '\\') + return (true); + if (filename[0] == '/') + return (true); + if (isc_file_iscurrentdir(filename)) + return (true); + return (false); +} + +const char * +isc_file_basename(const char *filename) { + char *s; + + REQUIRE(filename != NULL); + + s = strrchr(filename, '\\'); + if (s == NULL) + return (filename); + return (s + 1); +} + +isc_result_t +isc_file_progname(const char *filename, char *progname, size_t namelen) { + const char *s; + const char *p; + size_t len; + + REQUIRE(filename != NULL); + REQUIRE(progname != NULL); + + /* + * Strip the path from the name + */ + s = isc_file_basename(filename); + if (s == NULL) { + return (ISC_R_NOSPACE); + } + + /* + * Strip any and all suffixes + */ + p = strchr(s, '.'); + if (p == NULL) { + if (namelen <= strlen(s)) + return (ISC_R_NOSPACE); + + strlcpy(progname, s, namelen); + return (ISC_R_SUCCESS); + } + + /* + * Copy the result to the buffer + */ + len = p - s; + if (len >= namelen) + return (ISC_R_NOSPACE); + + /* Copy up to 'len' bytes and NUL terminate. */ + strlcpy(progname, s, ISC_MIN(len + 1, namelen)); + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_file_absolutepath(const char *filename, char *path, size_t pathlen) { + char *ptrname; + DWORD retval; + + REQUIRE(filename != NULL); + REQUIRE(path != NULL); + + retval = GetFullPathName(filename, (DWORD) pathlen, path, &ptrname); + + /* Something went wrong in getting the path */ + if (retval == 0) + return (ISC_R_NOTFOUND); + /* Caller needs to provide a larger buffer to contain the string */ + if (retval >= pathlen) + return (ISC_R_NOSPACE); + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_file_truncate(const char *filename, isc_offset_t size) { + int fh; + + REQUIRE(filename != NULL && size >= 0); + + if ((fh = open(filename, _O_RDWR | _O_BINARY)) < 0) + return (isc__errno2result(errno)); + + if(_chsize(fh, size) != 0) { + close(fh); + return (isc__errno2result(errno)); + } + close(fh); + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_file_safecreate(const char *filename, FILE **fp) { + isc_result_t result; + int flags; + struct stat sb; + FILE *f; + int fd; + + REQUIRE(filename != NULL); + REQUIRE(fp != NULL && *fp == NULL); + + result = file_stats(filename, &sb); + if (result == ISC_R_SUCCESS) { + if ((sb.st_mode & S_IFREG) == 0) + return (ISC_R_INVALIDFILE); + flags = O_WRONLY | O_TRUNC; + } else if (result == ISC_R_FILENOTFOUND) { + flags = O_WRONLY | O_CREAT | O_EXCL; + } else + return (result); + + fd = open(filename, flags, S_IRUSR | S_IWUSR); + if (fd == -1) + return (isc__errno2result(errno)); + + f = fdopen(fd, "w"); + if (f == NULL) { + result = isc__errno2result(errno); + close(fd); + return (result); + } + + *fp = f; + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_file_splitpath(isc_mem_t *mctx, const char *path, char **dirname, + char const ** basename) +{ + char *dir; + const char *file, *slash; + char *backslash; + + slash = strrchr(path, '/'); + + backslash = strrchr(path, '\\'); + if ((slash != NULL && backslash != NULL && backslash > slash) || + (slash == NULL && backslash != NULL)) + slash = backslash; + + if (slash == path) { + file = ++slash; + dir = isc_mem_strdup(mctx, "/"); + } else if (slash != NULL) { + file = ++slash; + dir = isc_mem_allocate(mctx, slash - path); + if (dir != NULL) + strlcpy(dir, path, slash - path); + } else { + file = path; + dir = isc_mem_strdup(mctx, "."); + } + + if (dir == NULL) + return (ISC_R_NOMEMORY); + + if (*file == '\0') { + isc_mem_free(mctx, dir); + return (ISC_R_INVALIDFILE); + } + + *dirname = dir; + *basename = file; + + return (ISC_R_SUCCESS); +} + +void * +isc_file_mmap(void *addr, size_t len, int prot, + int flags, int fd, off_t offset) +{ + void *buf; + ssize_t ret; + off_t end; + + UNUSED(addr); + UNUSED(prot); + UNUSED(flags); + + end = lseek(fd, 0, SEEK_END); + lseek(fd, offset, SEEK_SET); + if (end - offset < (off_t) len) + len = end - offset; + + buf = malloc(len); + if (buf == NULL) + return (NULL); + + ret = read(fd, buf, (unsigned int) len); + if (ret != (ssize_t) len) { + free(buf); + buf = NULL; + } + + return (buf); +} + +int +isc_file_munmap(void *addr, size_t len) { + UNUSED(len); + free(addr); + return (0); +} + +#define DISALLOW "\\/:ABCDEFGHIJKLMNOPQRSTUVWXYZ" +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +isc_result_t +isc_file_sanitize(const char *dir, const char *base, const char *ext, + char *path, size_t length) +{ + char buf[PATH_MAX], hash[ISC_SHA256_DIGESTSTRINGLENGTH]; + size_t l = 0; + + REQUIRE(base != NULL); + REQUIRE(path != NULL); + + l = strlen(base) + 1; + + /* + * allow room for a full sha256 hash (64 chars + * plus null terminator) + */ + if (l < 65) + l = 65; + + if (dir != NULL) + l += strlen(dir) + 1; + if (ext != NULL) + l += strlen(ext) + 1; + + if (l > length || l > PATH_MAX) + return (ISC_R_NOSPACE); + + /* Check whether the full-length SHA256 hash filename exists */ + isc_sha256_data((const void *) base, strlen(base), hash); + snprintf(buf, sizeof(buf), "%s%s%s%s%s", + dir != NULL ? dir : "", dir != NULL ? "/" : "", + hash, ext != NULL ? "." : "", ext != NULL ? ext : ""); + if (isc_file_exists(buf)) { + strlcpy(path, buf, length); + return (ISC_R_SUCCESS); + } + + /* Check for a truncated SHA256 hash filename */ + hash[16] = '\0'; + snprintf(buf, sizeof(buf), "%s%s%s%s%s", + dir != NULL ? dir : "", dir != NULL ? "/" : "", + hash, ext != NULL ? "." : "", ext != NULL ? ext : ""); + if (isc_file_exists(buf)) { + strlcpy(path, buf, length); + return (ISC_R_SUCCESS); + } + + /* + * If neither hash filename already exists, then we'll use + * the original base name if it has no disallowed characters, + * or the truncated hash name if it does. + */ + if (strpbrk(base, DISALLOW) != NULL) { + strlcpy(path, buf, length); + return (ISC_R_SUCCESS); + } + + snprintf(buf, sizeof(buf), "%s%s%s%s%s", + dir != NULL ? dir : "", dir != NULL ? "/" : "", + base, ext != NULL ? "." : "", ext != NULL ? ext : ""); + strlcpy(path, buf, length); + return (ISC_R_SUCCESS); +} + +/* + * Based on http://blog.aaronballman.com/2011/08/how-to-check-access-rights/ + */ +bool +isc_file_isdirwritable(const char *path) { + DWORD length = 0; + HANDLE hToken = NULL; + PSECURITY_DESCRIPTOR security = NULL; + bool answer = false; + + if (isc_file_isdirectory(path) != ISC_R_SUCCESS) { + return (answer); + } + + /* + * Figure out buffer size. GetFileSecurity() should not succeed. + */ + if (GetFileSecurity(path, OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION, + NULL, 0, &length)) + { + return (answer); + } + + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + return (answer); + } + + security = malloc(length); + if (security == NULL) { + return (answer); + } + + /* + * GetFileSecurity() should succeed. + */ + if (!GetFileSecurity(path, OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION, + security, length, &length)) + { + return (answer); + } + + if (OpenProcessToken(GetCurrentProcess(), TOKEN_IMPERSONATE | + TOKEN_QUERY | TOKEN_DUPLICATE | + STANDARD_RIGHTS_READ, &hToken)) + { + HANDLE hImpersonatedToken = NULL; + + if (DuplicateToken(hToken, SecurityImpersonation, + &hImpersonatedToken)) + { + GENERIC_MAPPING mapping; + PRIVILEGE_SET privileges = { 0 }; + DWORD grantedAccess = 0; + DWORD privilegesLength = sizeof(privileges); + BOOL result = FALSE; + DWORD genericAccessRights = GENERIC_WRITE; + + mapping.GenericRead = FILE_GENERIC_READ; + mapping.GenericWrite = FILE_GENERIC_WRITE; + mapping.GenericExecute = FILE_GENERIC_EXECUTE; + mapping.GenericAll = FILE_ALL_ACCESS; + + MapGenericMask(&genericAccessRights, &mapping); + if (AccessCheck(security, hImpersonatedToken, + genericAccessRights, &mapping, + &privileges, &privilegesLength, + &grantedAccess, &result)) + { + answer = result; + } + CloseHandle(hImpersonatedToken); + } + CloseHandle(hToken); + } + free(security); + return (answer); +} diff --git a/lib/isc/win32/fsaccess.c b/lib/isc/win32/fsaccess.c new file mode 100644 index 0000000..164985d --- /dev/null +++ b/lib/isc/win32/fsaccess.c @@ -0,0 +1,365 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* + * Note that Win32 does not have the concept of files having access + * and ownership bits. The FAT File system only has a readonly flag + * for everyone and that's all. NTFS uses ACL's which is a totally + * different concept of controlling access. + * + * This code needs to be revisited to set up proper access control for + * NTFS file systems. Nothing can be done for FAT file systems. + */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "errno2result.h" + +/* + * The OS-independent part of the API is in lib/isc. + */ +#include "../fsaccess.c" + +/* Store the user account name locally */ +static char username[255] = "\0"; +static DWORD namelen = 0; + +/* + * In order to set or retrieve access information, we need to obtain + * the File System type. These could be UNC-type shares. + */ + +BOOL +is_ntfs(const char * file) { + + char drive[255]; + char FSType[20]; + char tmpbuf[256]; + char *machinename; + char *sharename; + char filename[1024]; + + REQUIRE(filename != NULL); + + if (isc_file_absolutepath(file, filename, + sizeof(filename)) != ISC_R_SUCCESS) { + return (FALSE); + } + + /* + * Look for c:\path\... style, c:/path/... or \\computer\shar\path... + * the UNC style file specs + */ + if (isalpha(filename[0]) && filename[1] == ':' && + (filename[2] == '\\' || filename[2] == '/')) { + /* Copy 'c:\' or 'c:/' and NUL terminate. */ + strlcpy(drive, filename, ISC_MIN(3 + 1, sizeof(drive))); + } else if ((filename[0] == '\\') && (filename[1] == '\\')) { + /* Find the machine and share name and rebuild the UNC */ + strlcpy(tmpbuf, filename, sizeof(tmpbuf)); + machinename = strtok(tmpbuf, "\\"); + sharename = strtok(NULL, "\\"); + strlcpy(drive, "\\\\", sizeof(drive)); + strlcat(drive, machinename, sizeof(drive)); + strlcat(drive, "\\", sizeof(drive)); + strlcat(drive, sharename, sizeof(drive)); + strlcat(drive, "\\", sizeof(drive)); + + } else /* Not determinable */ + return (FALSE); + + GetVolumeInformation(drive, NULL, 0, NULL, 0, NULL, FSType, + sizeof(FSType)); + if (strcmp(FSType, "NTFS") == 0) + return (TRUE); + else + return (FALSE); +} + +/* + * If it's not NTFS, we assume that it is FAT and proceed + * with almost nothing to do. Only the write flag can be set or + * cleared. + */ +isc_result_t +FAT_fsaccess_set(const char *path, isc_fsaccess_t access) { + int mode; + isc_fsaccess_t bits; + + /* + * Done with checking bad bits. Set mode_t. + */ + mode = 0; + +#define SET_AND_CLEAR1(modebit) \ + if ((access & bits) != 0) { \ + mode |= modebit; \ + access &= ~bits; \ + } +#define SET_AND_CLEAR(user, group, other) \ + SET_AND_CLEAR1(user); \ + bits <<= STEP; \ + SET_AND_CLEAR1(group); \ + bits <<= STEP; \ + SET_AND_CLEAR1(other); + + bits = ISC_FSACCESS_READ | ISC_FSACCESS_LISTDIRECTORY; + + SET_AND_CLEAR(S_IRUSR, S_IRGRP, S_IROTH); + + bits = ISC_FSACCESS_WRITE | + ISC_FSACCESS_CREATECHILD | + ISC_FSACCESS_DELETECHILD; + + SET_AND_CLEAR(S_IWUSR, S_IWGRP, S_IWOTH); + + INSIST(access == 0); + + if (_chmod(path, mode) < 0) + return (isc__errno2result(errno)); + + return (ISC_R_SUCCESS); +} + +isc_result_t +NTFS_Access_Control(const char *filename, const char *user, int access, + bool isdir) { + SECURITY_DESCRIPTOR sd; + BYTE aclBuffer[1024]; + PACL pacl=(PACL)&aclBuffer; + BYTE sidBuffer[100]; + PSID psid=(PSID) &sidBuffer; + DWORD sidBufferSize = sizeof(sidBuffer); + BYTE adminSidBuffer[100]; + PSID padminsid=(PSID) &adminSidBuffer; + DWORD adminSidBufferSize = sizeof(adminSidBuffer); + BYTE otherSidBuffer[100]; + PSID pothersid=(PSID) &otherSidBuffer; + DWORD otherSidBufferSize = sizeof(otherSidBuffer); + char domainBuffer[100]; + DWORD domainBufferSize = sizeof(domainBuffer); + SID_NAME_USE snu; + DWORD NTFSbits; + int caccess; + + + /* Initialize an ACL */ + if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) + return (ISC_R_NOPERM); + if (!InitializeAcl(pacl, sizeof(aclBuffer), ACL_REVISION)) + return (ISC_R_NOPERM); + if (!LookupAccountName(0, user, psid, &sidBufferSize, domainBuffer, + &domainBufferSize, &snu)) + return (ISC_R_NOPERM); + domainBufferSize = sizeof(domainBuffer); + if (!LookupAccountName(0, "Administrators", padminsid, + &adminSidBufferSize, domainBuffer, &domainBufferSize, &snu)) { + (void)GetLastError(); + return (ISC_R_NOPERM); + } + domainBufferSize = sizeof(domainBuffer); + if (!LookupAccountName(0, "Everyone", pothersid, + &otherSidBufferSize, domainBuffer, &domainBufferSize, &snu)) { + (void)GetLastError(); + return (ISC_R_NOPERM); + } + + caccess = access; + /* Owner check */ + + NTFSbits = 0; + if (caccess & ISC_FSACCESS_READ) + NTFSbits |= FILE_GENERIC_READ; + if (caccess & ISC_FSACCESS_WRITE) + NTFSbits |= FILE_GENERIC_WRITE; + if (caccess & ISC_FSACCESS_EXECUTE) + NTFSbits |= FILE_GENERIC_EXECUTE; + + /* For directories check the directory-specific bits */ + if (isdir == true) { + if (caccess & ISC_FSACCESS_CREATECHILD) + NTFSbits |= FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE; + if (caccess & ISC_FSACCESS_DELETECHILD) + NTFSbits |= FILE_DELETE_CHILD; + if (caccess & ISC_FSACCESS_LISTDIRECTORY) + NTFSbits |= FILE_LIST_DIRECTORY; + if (caccess & ISC_FSACCESS_ACCESSCHILD) + NTFSbits |= FILE_TRAVERSE; + } + + if (NTFSbits == (FILE_GENERIC_READ | FILE_GENERIC_WRITE + | FILE_GENERIC_EXECUTE)) + NTFSbits |= FILE_ALL_ACCESS; + /* + * Owner and Administrator also get STANDARD_RIGHTS_ALL + * to ensure that they have full control + */ + + NTFSbits |= STANDARD_RIGHTS_ALL; + + /* Add the ACE to the ACL */ + if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits, psid)) + return (ISC_R_NOPERM); + if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits, padminsid)) + return (ISC_R_NOPERM); + + /* + * Group is ignored since we can be in multiple groups or no group + * and its meaning is not clear on Win32 + */ + + caccess = caccess >> STEP; + + /* + * Other check. We translate this to be the same as Everyone + */ + + caccess = caccess >> STEP; + + NTFSbits = 0; + if (caccess & ISC_FSACCESS_READ) + NTFSbits |= FILE_GENERIC_READ; + if (caccess & ISC_FSACCESS_WRITE) + NTFSbits |= FILE_GENERIC_WRITE; + if (caccess & ISC_FSACCESS_EXECUTE) + NTFSbits |= FILE_GENERIC_EXECUTE; + + /* For directories check the directory-specific bits */ + if (isdir == TRUE) { + if (caccess & ISC_FSACCESS_CREATECHILD) + NTFSbits |= FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE; + if (caccess & ISC_FSACCESS_DELETECHILD) + NTFSbits |= FILE_DELETE_CHILD; + if (caccess & ISC_FSACCESS_LISTDIRECTORY) + NTFSbits |= FILE_LIST_DIRECTORY; + if (caccess & ISC_FSACCESS_ACCESSCHILD) + NTFSbits |= FILE_TRAVERSE; + } + /* Add the ACE to the ACL */ + if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits, + pothersid)) + return (ISC_R_NOPERM); + + if (!SetSecurityDescriptorDacl(&sd, TRUE, pacl, FALSE)) + return (ISC_R_NOPERM); + if (!SetFileSecurity(filename, DACL_SECURITY_INFORMATION, &sd)) { + return (ISC_R_NOPERM); + } + + return(ISC_R_SUCCESS); +} + +isc_result_t +NTFS_fsaccess_set(const char *path, isc_fsaccess_t access, + bool isdir){ + + /* + * For NTFS we first need to get the name of the account under + * which BIND is running + */ + if (namelen == 0) { + namelen = sizeof(username); + if (GetUserName(username, &namelen) == 0) + return (ISC_R_FAILURE); + } + return (NTFS_Access_Control(path, username, access, isdir)); +} + +isc_result_t +isc_fsaccess_set(const char *path, isc_fsaccess_t access) { + struct stat statb; + bool is_dir = false; + isc_result_t result; + + if (stat(path, &statb) != 0) + return (isc__errno2result(errno)); + + if ((statb.st_mode & S_IFDIR) != 0) + is_dir = true; + else if ((statb.st_mode & S_IFREG) == 0) + return (ISC_R_INVALIDFILE); + + result = check_bad_bits(access, is_dir); + if (result != ISC_R_SUCCESS) + return (result); + + /* + * Determine if this is a FAT or NTFS disk and + * call the appropriate function to set the permissions + */ + if (is_ntfs(path)) + return (NTFS_fsaccess_set(path, access, is_dir)); + else + return (FAT_fsaccess_set(path, access)); +} + +isc_result_t +isc_fsaccess_changeowner(const char *filename, const char *user) { + SECURITY_DESCRIPTOR psd; + BYTE sidBuffer[500]; + BYTE groupBuffer[500]; + PSID psid=(PSID) &sidBuffer; + DWORD sidBufferSize = sizeof(sidBuffer); + char domainBuffer[100]; + DWORD domainBufferSize = sizeof(domainBuffer); + SID_NAME_USE snu; + PSID pSidGroup = (PSID) &groupBuffer; + DWORD groupBufferSize = sizeof(groupBuffer); + + + /* + * Determine if this is a FAT or NTFS disk and + * call the appropriate function to set the ownership + * FAT disks do not have ownership attributes so it's + * a noop. + */ + if (is_ntfs(filename) == FALSE) + return (ISC_R_SUCCESS); + + if (!InitializeSecurityDescriptor(&psd, SECURITY_DESCRIPTOR_REVISION)) + return (ISC_R_NOPERM); + + if (!LookupAccountName(0, user, psid, &sidBufferSize, domainBuffer, + &domainBufferSize, &snu)) + return (ISC_R_NOPERM); + + /* Make sure administrators can get to it */ + domainBufferSize = sizeof(domainBuffer); + if (!LookupAccountName(0, "Administrators", pSidGroup, + &groupBufferSize, domainBuffer, &domainBufferSize, &snu)) + return (ISC_R_NOPERM); + + if (!SetSecurityDescriptorOwner(&psd, psid, FALSE)) + return (ISC_R_NOPERM); + + if (!SetSecurityDescriptorGroup(&psd, pSidGroup, FALSE)) + return (ISC_R_NOPERM); + + if (!SetFileSecurity(filename, + OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION, + &psd)) + return (ISC_R_NOPERM); + + return (ISC_R_SUCCESS); +} diff --git a/lib/isc/win32/include/Makefile.in b/lib/isc/win32/include/Makefile.in new file mode 100644 index 0000000..2cbf021 --- /dev/null +++ b/lib/isc/win32/include/Makefile.in @@ -0,0 +1,17 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +SUBDIRS = isc pkcs11 +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/isc/win32/include/isc/Makefile.in b/lib/isc/win32/include/isc/Makefile.in new file mode 100644 index 0000000..a7c0243 --- /dev/null +++ b/lib/isc/win32/include/isc/Makefile.in @@ -0,0 +1,30 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +VERSION=@BIND9_VERSION@ + +HEADERS = dir.h keyboard.h mutex.h net.h netdb.h once.h \ + stat.h stdtime.h thread.h time.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}\isc + +install:: installdirs + for i in $(HEADERS); do \ + $(INSTALL_DATA) $(srcdir)\$$i $(includedir)\isc || exit 1; \ + done diff --git a/lib/isc/win32/include/isc/atomic.h b/lib/isc/win32/include/isc/atomic.h new file mode 100644 index 0000000..4b3d92d --- /dev/null +++ b/lib/isc/win32/include/isc/atomic.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_ATOMIC_H +#define ISC_ATOMIC_H 1 + +#include + +#include +#include + +/* + * This routine atomically increments the value stored in 'p' by 'val', and + * returns the previous value. + */ +#ifdef ISC_PLATFORM_HAVEXADD +static __inline int32_t +isc_atomic_xadd(int32_t *p, int32_t val) { + return (int32_t) _InterlockedExchangeAdd((long *)p, (long)val); +} +#endif + +#ifdef ISC_PLATFORM_HAVEXADDQ +static __inline int64_t +isc_atomic_xaddq(int64_t *p, int64_t val) { + return (int64_t) _InterlockedExchangeAdd64((__int64 *)p, + (__int64) val); +} +#endif + +/* + * This routine atomically stores the value 'val' in 'p' (32-bit version). + */ +#ifdef ISC_PLATFORM_HAVEATOMICSTORE +static __inline void +isc_atomic_store(int32_t *p, int32_t val) { + (void) _InterlockedExchange((long *)p, (long)val); +} +#endif + +/* + * This routine atomically stores the value 'val' in 'p' (64-bit version). + */ +#ifdef ISC_PLATFORM_HAVEATOMICSTOREQ +static __inline void +isc_atomic_storeq(int64_t *p, int64_t val) { + (void) _InterlockedExchange64((__int64 *)p, (__int64)val); +} +#endif + +/* + * This routine atomically replaces the value in 'p' with 'val', if the + * original value is equal to 'cmpval'. The original value is returned in any + * case. + */ +#ifdef ISC_PLATFORM_HAVECMPXCHG +static __inline int32_t +isc_atomic_cmpxchg(int32_t *p, int32_t cmpval, int32_t val) { + /* beware: swap arguments */ + return (int32_t) _InterlockedCompareExchange((long *)p, + (long)val, + (long)cmpval); +} +#endif + +#endif /* ISC_ATOMIC_H */ diff --git a/lib/isc/win32/include/isc/bind_registry.h b/lib/isc/win32/include/isc/bind_registry.h new file mode 100644 index 0000000..57970be --- /dev/null +++ b/lib/isc/win32/include/isc/bind_registry.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_BINDREGISTRY_H +#define ISC_BINDREGISTRY_H + +/* + * BIND makes use of the following Registry keys in various places, especially + * during startup and installation + */ + +#define BIND_SUBKEY "Software\\ISC\\BIND" +#define BIND_SESSION "CurrentSession" +#define BIND_SESSION_SUBKEY "Software\\ISC\\BIND\\CurrentSession" +#define BIND_UNINSTALL_SUBKEY \ + "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ISC BIND" + +#define EVENTLOG_APP_SUBKEY \ + "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application" +#define BIND_MESSAGE_SUBKEY \ + "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\named" +#define BIND_MESSAGE_NAME "named" + +#define BIND_SERVICE_SUBKEY \ + "SYSTEM\\CurrentControlSet\\Services\\named" + + +#define BIND_CONFIGFILE 0 +#define BIND_DEBUGLEVEL 1 +#define BIND_QUERYLOG 2 +#define BIND_FOREGROUND 3 +#define BIND_PORT 4 + +#endif /* ISC_BINDREGISTRY_H */ diff --git a/lib/isc/win32/include/isc/bindevt.h b/lib/isc/win32/include/isc/bindevt.h new file mode 100644 index 0000000..d4088e8 --- /dev/null +++ b/lib/isc/win32/include/isc/bindevt.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_BINDEVT_H +#define ISC_BINDEVT_H 1 + +/* + * This is used for the event log for both logging the messages and + * later on by the event viewer when looking at the events + */ + +/* + * Values are 32 bit values layed out as follows: + * + * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +---+-+-+-----------------------+-------------------------------+ + * |Sev|C|R| Facility | Code | + * +---+-+-+-----------------------+-------------------------------+ + * + * where + * + * Sev - is the severity code + * + * 00 - Success + * 01 - Informational + * 10 - Warning + * 11 - Error + * + * C - is the Customer code flag + * + * R - is a reserved bit + * + * Facility - is the facility code + * + * Code - is the facility's status code + * + * + * Define the facility codes + */ + + +/* + * Define the severity codes + */ + + +/* + * MessageId: BIND_ERR_MSG + * + * MessageText: + * + * %1 + */ +#define BIND_ERR_MSG ((DWORD)0xC0000001L) + +/* + * MessageId: BIND_WARN_MSG + * + * MessageText: + * + * %1 + */ +#define BIND_WARN_MSG ((DWORD)0x80000002L) + +/* + * MessageId: BIND_INFO_MSG + * + * MessageText: + * + * %1 + */ +#define BIND_INFO_MSG ((DWORD)0x40000003L) + +#endif /* ISC_BINDEVT_H */ diff --git a/lib/isc/win32/include/isc/condition.h b/lib/isc/win32/include/isc/condition.h new file mode 100644 index 0000000..1f5b2d6 --- /dev/null +++ b/lib/isc/win32/include/isc/condition.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_CONDITION_H +#define ISC_CONDITION_H 1 + +#include + +#include +#include +#include +#include + +typedef struct isc_condition_thread isc_condition_thread_t; + +struct isc_condition_thread { + unsigned long th; + HANDLE handle[2]; + ISC_LINK(isc_condition_thread_t) link; + +}; + +typedef struct isc_condition { + HANDLE events[2]; + unsigned int waiters; + ISC_LIST(isc_condition_thread_t) threadlist; +} isc_condition_t; + +ISC_LANG_BEGINDECLS + +isc_result_t +isc_condition_init(isc_condition_t *); + +isc_result_t +isc_condition_wait(isc_condition_t *, isc_mutex_t *); + +isc_result_t +isc_condition_signal(isc_condition_t *); + +isc_result_t +isc_condition_broadcast(isc_condition_t *); + +isc_result_t +isc_condition_destroy(isc_condition_t *); + +isc_result_t +isc_condition_waituntil(isc_condition_t *, isc_mutex_t *, isc_time_t *); + +ISC_LANG_ENDDECLS + +#endif /* ISC_CONDITION_H */ diff --git a/lib/isc/win32/include/isc/dir.h b/lib/isc/win32/include/isc/dir.h new file mode 100644 index 0000000..7370fa6 --- /dev/null +++ b/lib/isc/win32/include/isc/dir.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef ISC_DIR_H +#define ISC_DIR_H 1 + +#include +#include +#include + +#include +#include + +#define ISC_DIR_NAMEMAX _MAX_FNAME +#define ISC_DIR_PATHMAX _MAX_PATH + +typedef struct { + char name[ISC_DIR_NAMEMAX]; + unsigned int length; + WIN32_FIND_DATA find_data; +} isc_direntry_t; + +typedef struct { + unsigned int magic; + char dirname[ISC_DIR_PATHMAX]; + isc_direntry_t entry; + bool entry_filled; + HANDLE search_handle; +} isc_dir_t; + +ISC_LANG_BEGINDECLS + +void +isc_dir_init(isc_dir_t *dir); + +isc_result_t +isc_dir_open(isc_dir_t *dir, const char *dirname); + +isc_result_t +isc_dir_read(isc_dir_t *dir); + +isc_result_t +isc_dir_reset(isc_dir_t *dir); + +void +isc_dir_close(isc_dir_t *dir); + +isc_result_t +isc_dir_chdir(const char *dirname); + +isc_result_t +isc_dir_chroot(const char *dirname); + +isc_result_t +isc_dir_createunique(char *templet); +/* + * Use a templet (such as from isc_file_mktemplate()) to create a uniquely + * named, empty directory. The templet string is modified in place. + * If result == ISC_R_SUCCESS, it is the name of the directory that was + * created. + */ + +ISC_LANG_ENDDECLS + +#endif /* ISC_DIR_H */ diff --git a/lib/isc/win32/include/isc/ipv6.h b/lib/isc/win32/include/isc/ipv6.h new file mode 100644 index 0000000..bee1bd0 --- /dev/null +++ b/lib/isc/win32/include/isc/ipv6.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_IPV6_H +#define ISC_IPV6_H 1 + +/***** + ***** Module Info + *****/ + +/* + * IPv6 definitions for systems which do not support IPv6. + * + * MP: + * No impact. + * + * Reliability: + * No anticipated impact. + * + * Resources: + * N/A. + * + * Security: + * No anticipated impact. + * + * Standards: + * RFC2553. + */ + +#if _MSC_VER < 1300 +#define in6_addr in_addr6 +#endif + +#ifndef IN6ADDR_ANY_INIT +#define IN6ADDR_ANY_INIT {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }} +#endif +#ifndef IN6ADDR_LOOPBACK_INIT +#define IN6ADDR_LOOPBACK_INIT {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }} +#endif +#ifndef IN6ADDR_V4MAPPED_INIT +#define IN6ADDR_V4MAPPED_INIT {{ 0,0,0,0,0,0,0,0,0,0,0xff,0xff,0,0,0,0 }} +#endif + +LIBISC_EXTERNAL_DATA extern const struct in6_addr isc_in6addr_any; +LIBISC_EXTERNAL_DATA extern const struct in6_addr isc_in6addr_loopback; + +/* + * Unspecified + */ +#ifndef IN6_IS_ADDR_UNSPECIFIED +#define IN6_IS_ADDR_UNSPECIFIED(a) (\ +*((u_long *)((a)->s6_addr) ) == 0 && \ +*((u_long *)((a)->s6_addr) + 1) == 0 && \ +*((u_long *)((a)->s6_addr) + 2) == 0 && \ +*((u_long *)((a)->s6_addr) + 3) == 0 \ +) +#endif + +/* + * Loopback + */ +#ifndef IN6_IS_ADDR_LOOPBACK +#define IN6_IS_ADDR_LOOPBACK(a) (\ +*((u_long *)((a)->s6_addr) ) == 0 && \ +*((u_long *)((a)->s6_addr) + 1) == 0 && \ +*((u_long *)((a)->s6_addr) + 2) == 0 && \ +*((u_long *)((a)->s6_addr) + 3) == htonl(1) \ +) +#endif + +/* + * IPv4 compatible + */ +#define IN6_IS_ADDR_V4COMPAT(a) (\ +*((u_long *)((a)->s6_addr) ) == 0 && \ +*((u_long *)((a)->s6_addr) + 1) == 0 && \ +*((u_long *)((a)->s6_addr) + 2) == 0 && \ +*((u_long *)((a)->s6_addr) + 3) != 0 && \ +*((u_long *)((a)->s6_addr) + 3) != htonl(1) \ +) + +/* + * Mapped + */ +#define IN6_IS_ADDR_V4MAPPED(a) (\ +*((u_long *)((a)->s6_addr) ) == 0 && \ +*((u_long *)((a)->s6_addr) + 1) == 0 && \ +*((u_long *)((a)->s6_addr) + 2) == htonl(0x0000ffff)) + +/* + * Multicast + */ +#define IN6_IS_ADDR_MULTICAST(a) \ + ((a)->s6_addr[0] == 0xffU) + +/* + * Unicast link / site local. + */ +#ifndef IN6_IS_ADDR_LINKLOCAL +#define IN6_IS_ADDR_LINKLOCAL(a) (\ + ((a)->s6_addr[0] == 0xfe) && \ + (((a)->s6_addr[1] & 0xc0) == 0x80)) +#endif + +#ifndef IN6_IS_ADDR_SITELOCAL +#define IN6_IS_ADDR_SITELOCAL(a) (\ + ((a)->s6_addr[0] == 0xfe) && \ + (((a)->s6_addr[1] & 0xc0) == 0xc0)) +#endif + +#endif /* ISC_IPV6_H */ diff --git a/lib/isc/win32/include/isc/keyboard.h b/lib/isc/win32/include/isc/keyboard.h new file mode 100644 index 0000000..009523a --- /dev/null +++ b/lib/isc/win32/include/isc/keyboard.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_KEYBOARD_H +#define ISC_KEYBOARD_H 1 + +#include + +#include +#include + +ISC_LANG_BEGINDECLS + +typedef struct { + int fd; + isc_result_t result; +} isc_keyboard_t; + +isc_result_t +isc_keyboard_open(isc_keyboard_t *keyboard); + +isc_result_t +isc_keyboard_close(isc_keyboard_t *keyboard, unsigned int sleepseconds); + +isc_result_t +isc_keyboard_getchar(isc_keyboard_t *keyboard, unsigned char *cp); + +bool +isc_keyboard_canceled(isc_keyboard_t *keyboard); + +ISC_LANG_ENDDECLS + +#endif /* ISC_KEYBOARD_H */ diff --git a/lib/isc/win32/include/isc/mutex.h b/lib/isc/win32/include/isc/mutex.h new file mode 100644 index 0000000..6815741 --- /dev/null +++ b/lib/isc/win32/include/isc/mutex.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_MUTEX_H +#define ISC_MUTEX_H 1 + +#include +#include + +#include + +typedef CRITICAL_SECTION isc_mutex_t; + +/* + * This definition is here since some versions of WINBASE.H + * omits it for some reason. + */ +#if (_WIN32_WINNT < 0x0400) +WINBASEAPI BOOL WINAPI +TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); +#endif /* _WIN32_WINNT < 0x0400 */ + +#define isc_mutex_init(mp) \ + (InitializeCriticalSection((mp)), ISC_R_SUCCESS) +#define isc_mutex_lock(mp) \ + (EnterCriticalSection((mp)), ISC_R_SUCCESS) +#define isc_mutex_unlock(mp) \ + (LeaveCriticalSection((mp)), ISC_R_SUCCESS) +#define isc_mutex_trylock(mp) \ + (TryEnterCriticalSection((mp)) ? ISC_R_SUCCESS : ISC_R_LOCKBUSY) +#define isc_mutex_destroy(mp) \ + (DeleteCriticalSection((mp)), ISC_R_SUCCESS) + +/* + * This is a placeholder for now since we are not keeping any mutex stats + */ +#define isc_mutex_stats(fp) do {} while (0) + +#endif /* ISC_MUTEX_H */ diff --git a/lib/isc/win32/include/isc/net.h b/lib/isc/win32/include/isc/net.h new file mode 100644 index 0000000..9712a6a --- /dev/null +++ b/lib/isc/win32/include/isc/net.h @@ -0,0 +1,431 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* $Id$ */ + +#ifndef ISC_NET_H +#define ISC_NET_H 1 + +/* + * Also define LWRES_IPV6_H to keep it from being included if liblwres is + * being used, or redefinition errors will occur. + */ +#define LWRES_IPV6_H 1 + + + +/***** + ***** Module Info + *****/ + +/* + * Basic Networking Types + * + * This module is responsible for defining the following basic networking + * types: + * + * struct in_addr + * struct in6_addr + * struct in6_pktinfo + * struct sockaddr + * struct sockaddr_in + * struct sockaddr_in6 + * in_port_t + * + * It ensures that the AF_ and PF_ macros are defined. + * + * It declares ntoh[sl]() and hton[sl](). + * + * It declares inet_aton(), inet_ntop(), and inet_pton(). + * + * It ensures that INADDR_ANY, IN6ADDR_ANY_INIT, in6addr_any, and + * in6addr_loopback are available. + * + * It ensures that IN_MULTICAST() is available to check for multicast + * addresses. + * + * MP: + * No impact. + * + * Reliability: + * No anticipated impact. + * + * Resources: + * N/A. + * + * Security: + * No anticipated impact. + * + * Standards: + * BSD Socket API + * RFC2553 + */ + +/*** + *** Imports. + ***/ +#include + +#include + +/* + * Because of some sort of problem in the MS header files, this cannot + * be simple "#include ", 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 + +#include + +#include +#include + +#include +#include + +/* + * This is here because named client, interfacemgr.c, etc. use the name as + * a variable + */ +#undef interface + +#ifndef INADDR_ANY +#define INADDR_ANY 0x00000000UL +#endif + +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK 0x7f000001UL +#endif + +#ifndef ISC_PLATFORM_HAVEIN6PKTINFO +struct in6_pktinfo { + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + unsigned int ipi6_ifindex; /* send/recv interface index */ +}; +#endif + +#if _MSC_VER < 1300 +#define in6addr_any isc_in6addr_any +#define in6addr_loopback isc_in6addr_loopback +#endif + +/* + * Ensure type in_port_t is defined. + */ +#ifdef ISC_PLATFORM_NEEDPORTT +typedef uint16_t in_port_t; +#endif + +/* + * If this system does not have MSG_TRUNC (as returned from recvmsg()) + * ISC_PLATFORM_RECVOVERFLOW will be defined. This will enable the MSG_TRUNC + * faking code in socket.c. + */ +#ifndef MSG_TRUNC +#define ISC_PLATFORM_RECVOVERFLOW +#endif + +#define ISC__IPADDR(x) ((uint32_t)htonl((uint32_t)(x))) + +#define ISC_IPADDR_ISMULTICAST(i) \ + (((uint32_t)(i) & ISC__IPADDR(0xf0000000)) \ + == ISC__IPADDR(0xe0000000)) + +#define ISC_IPADDR_ISEXPERIMENTAL(i) \ + (((uint32_t)(i) & ISC__IPADDR(0xf0000000)) \ + == ISC__IPADDR(0xf0000000)) + +/* + * Fix the FD_SET and FD_CLR Macros to properly cast + */ +#undef FD_CLR +#define FD_CLR(fd, set) do { \ + u_int __i; \ + for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count; __i++) { \ + if (((fd_set FAR *)(set))->fd_array[__i] == (SOCKET) fd) { \ + while (__i < ((fd_set FAR *)(set))->fd_count-1) { \ + ((fd_set FAR *)(set))->fd_array[__i] = \ + ((fd_set FAR *)(set))->fd_array[__i+1]; \ + __i++; \ + } \ + ((fd_set FAR *)(set))->fd_count--; \ + break; \ + } \ + } \ +} while (0) + +#undef FD_SET +#define FD_SET(fd, set) do { \ + u_int __i; \ + for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count; __i++) { \ + if (((fd_set FAR *)(set))->fd_array[__i] == (SOCKET)(fd)) { \ + break; \ + } \ + } \ + if (__i == ((fd_set FAR *)(set))->fd_count) { \ + if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) { \ + ((fd_set FAR *)(set))->fd_array[__i] = (SOCKET)(fd); \ + ((fd_set FAR *)(set))->fd_count++; \ + } \ + } \ +} while (0) + +/* + * Windows Sockets errors redefined as regular Berkeley error constants. + * These are usually commented out in Windows NT to avoid conflicts with errno.h. + * Use the WSA constants instead. + */ + +#include + +#ifndef EWOULDBLOCK +#define EWOULDBLOCK WSAEWOULDBLOCK +#endif +#ifndef EINPROGRESS +#define EINPROGRESS WSAEINPROGRESS +#endif +#ifndef EALREADY +#define EALREADY WSAEALREADY +#endif +#ifndef ENOTSOCK +#define ENOTSOCK WSAENOTSOCK +#endif +#ifndef EDESTADDRREQ +#define EDESTADDRREQ WSAEDESTADDRREQ +#endif +#ifndef EMSGSIZE +#define EMSGSIZE WSAEMSGSIZE +#endif +#ifndef EPROTOTYPE +#define EPROTOTYPE WSAEPROTOTYPE +#endif +#ifndef ENOPROTOOPT +#define ENOPROTOOPT WSAENOPROTOOPT +#endif +#ifndef EPROTONOSUPPORT +#define EPROTONOSUPPORT WSAEPROTONOSUPPORT +#endif +#ifndef ESOCKTNOSUPPORT +#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT +#endif +#ifndef EOPNOTSUPP +#define EOPNOTSUPP WSAEOPNOTSUPP +#endif +#ifndef EPFNOSUPPORT +#define EPFNOSUPPORT WSAEPFNOSUPPORT +#endif +#ifndef EAFNOSUPPORT +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#endif +#ifndef EADDRINUSE +#define EADDRINUSE WSAEADDRINUSE +#endif +#ifndef EADDRNOTAVAIL +#define EADDRNOTAVAIL WSAEADDRNOTAVAIL +#endif +#ifndef ENETDOWN +#define ENETDOWN WSAENETDOWN +#endif +#ifndef ENETUNREACH +#define ENETUNREACH WSAENETUNREACH +#endif +#ifndef ENETRESET +#define ENETRESET WSAENETRESET +#endif +#ifndef ECONNABORTED +#define ECONNABORTED WSAECONNABORTED +#endif +#ifndef ECONNRESET +#define ECONNRESET WSAECONNRESET +#endif +#ifndef ENOBUFS +#define ENOBUFS WSAENOBUFS +#endif +#ifndef EISCONN +#define EISCONN WSAEISCONN +#endif +#ifndef ENOTCONN +#define ENOTCONN WSAENOTCONN +#endif +#ifndef ESHUTDOWN +#define ESHUTDOWN WSAESHUTDOWN +#endif +#ifndef ETOOMANYREFS +#define ETOOMANYREFS WSAETOOMANYREFS +#endif +#ifndef ETIMEDOUT +#define ETIMEDOUT WSAETIMEDOUT +#endif +#ifndef ECONNREFUSED +#define ECONNREFUSED WSAECONNREFUSED +#endif +#ifndef ELOOP +#define ELOOP WSAELOOP +#endif +#ifndef EHOSTDOWN +#define EHOSTDOWN WSAEHOSTDOWN +#endif +#ifndef EHOSTUNREACH +#define EHOSTUNREACH WSAEHOSTUNREACH +#endif +#ifndef EPROCLIM +#define EPROCLIM WSAEPROCLIM +#endif +#ifndef EUSERS +#define EUSERS WSAEUSERS +#endif +#ifndef EDQUOT +#define EDQUOT WSAEDQUOT +#endif +#ifndef ESTALE +#define ESTALE WSAESTALE +#endif +#ifndef EREMOTE +#define EREMOTE WSAEREMOTE +#endif + + +/*** + *** Functions. + ***/ + +ISC_LANG_BEGINDECLS + +isc_result_t +isc_net_probeipv4(void); +/* + * Check if the system's kernel supports IPv4. + * + * Returns: + * + * ISC_R_SUCCESS IPv4 is supported. + * ISC_R_NOTFOUND IPv4 is not supported. + * ISC_R_DISABLED IPv4 is disabled. + * ISC_R_UNEXPECTED + */ + +isc_result_t +isc_net_probeipv6(void); +/* + * Check if the system's kernel supports IPv6. + * + * Returns: + * + * ISC_R_SUCCESS IPv6 is supported. + * ISC_R_NOTFOUND IPv6 is not supported. + * ISC_R_DISABLED IPv6 is disabled. + * ISC_R_UNEXPECTED + */ + +isc_result_t +isc_net_probeunix(void); +/* + * Check if UNIX domain sockets are supported. + * + * Returns: + * + * ISC_R_SUCCESS + * ISC_R_NOTFOUND + */ + +#define ISC_NET_DSCPRECVV4 0x01 /* Can receive sent DSCP value IPv4 */ +#define ISC_NET_DSCPRECVV6 0x02 /* Can receive sent DSCP value IPv6 */ +#define ISC_NET_DSCPSETV4 0x04 /* Can set DSCP on socket IPv4 */ +#define ISC_NET_DSCPSETV6 0x08 /* Can set DSCP on socket IPv6 */ +#define ISC_NET_DSCPPKTV4 0x10 /* Can set DSCP on per packet IPv4 */ +#define ISC_NET_DSCPPKTV6 0x20 /* Can set DSCP on per packet IPv6 */ +#define ISC_NET_DSCPALL 0x3f /* All valid flags */ + +unsigned int +isc_net_probedscp(void); +/*%< + * Probe the level of DSCP support. + */ + +isc_result_t +isc_net_probe_ipv6only(void); +/* + * Check if the system's kernel supports the IPV6_V6ONLY socket option. + * + * Returns: + * + * ISC_R_SUCCESS the option is supported for both TCP and UDP. + * ISC_R_NOTFOUND IPv6 itself or the option is not supported. + * ISC_R_UNEXPECTED + */ + +isc_result_t +isc_net_probe_ipv6pktinfo(void); +/* + * Check if the system's kernel supports the IPV6_(RECV)PKTINFO socket option + * for UDP sockets. + * + * Returns: + * + * ISC_R_SUCCESS the option is supported. + * ISC_R_NOTFOUND IPv6 itself or the option is not supported. + * ISC_R_UNEXPECTED + */ + +void +isc_net_disableipv4(void); + +void +isc_net_disableipv6(void); + +void +isc_net_enableipv4(void); + +void +isc_net_enableipv6(void); + +isc_result_t +isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high); +/*%< + * Returns system's default range of ephemeral UDP ports, if defined. + * If the range is not available or unknown, ISC_NET_PORTRANGELOW and + * ISC_NET_PORTRANGEHIGH will be returned. + * + * Requires: + * + *\li 'low' and 'high' must be non NULL. + * + * Returns: + * + *\li *low and *high will be the ports specifying the low and high ends of + * the range. + */ + +#ifdef ISC_PLATFORM_NEEDNTOP +const char * +isc_net_ntop(int af, const void *src, char *dst, size_t size); +#undef inet_ntop +#define inet_ntop isc_net_ntop +#endif + +#ifdef ISC_PLATFORM_NEEDPTON +int +isc_net_pton(int af, const char *src, void *dst); +#define inet_pton isc_net_pton +#endif + +int +isc_net_aton(const char *cp, struct in_addr *addr); +#define inet_aton isc_net_aton + +ISC_LANG_ENDDECLS + +#endif /* ISC_NET_H */ diff --git a/lib/isc/win32/include/isc/netdb.h b/lib/isc/win32/include/isc/netdb.h new file mode 100644 index 0000000..c07194d --- /dev/null +++ b/lib/isc/win32/include/isc/netdb.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_NETDB_H +#define ISC_NETDB_H 1 + +/***** + ***** Module Info + *****/ + +/* + * Portable netdb.h support. + * + * This module is responsible for defining the getby APIs. + * + * MP: + * No impact. + * + * Reliability: + * No anticipated impact. + * + * Resources: + * N/A. + * + * Security: + * No anticipated impact. + * + * Standards: + * BSD API + */ + +/*** + *** Imports. + ***/ + +#include + +#endif /* ISC_NETDB_H */ diff --git a/lib/isc/win32/include/isc/ntgroups.h b/lib/isc/win32/include/isc/ntgroups.h new file mode 100644 index 0000000..e8352fc --- /dev/null +++ b/lib/isc/win32/include/isc/ntgroups.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_NTGROUPS_H +#define ISC_NTGROUPS_H 1 + +#include +#include + +ISC_LANG_BEGINDECLS + + +isc_result_t +isc_ntsecurity_getaccountgroups(char *name, char **Groups, unsigned int maxgroups, + unsigned int *total); + +ISC_LANG_ENDDECLS + +#endif /* ISC_NTGROUPS_H */ diff --git a/lib/isc/win32/include/isc/ntpaths.h b/lib/isc/win32/include/isc/ntpaths.h new file mode 100644 index 0000000..c0010fc --- /dev/null +++ b/lib/isc/win32/include/isc/ntpaths.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* + * Windows-specific path definitions + * These routines are used to set up and return system-specific path + * information about the files enumerated in NtPaths + */ + +#ifndef ISC_NTPATHS_H +#define ISC_NTPATHS_H + +#include + +/* + * Index of paths needed + */ +enum NtPaths { + NAMED_CONF_PATH, + LWRES_CONF_PATH, + RESOLV_CONF_PATH, + RNDC_CONF_PATH, + NAMED_PID_PATH, + LWRESD_PID_PATH, + NAMED_LOCK_PATH, + LOCAL_STATE_DIR, + SYS_CONF_DIR, + RNDC_KEY_PATH, + SESSION_KEY_PATH +}; + +/* + * Define macros to get the path of the config files + */ +#define NAMED_CONFFILE isc_ntpaths_get(NAMED_CONF_PATH) +#define RNDC_CONFFILE isc_ntpaths_get(RNDC_CONF_PATH) +#define RNDC_KEYFILE isc_ntpaths_get(RNDC_KEY_PATH) +#define SESSION_KEYFILE isc_ntpaths_get(SESSION_KEY_PATH) +#define RESOLV_CONF isc_ntpaths_get(RESOLV_CONF_PATH) + +/* + * Information about where the files are on disk + */ +#define NS_LOCALSTATEDIR "/dns/bin" +#define NS_SYSCONFDIR "/dns/etc" + +ISC_LANG_BEGINDECLS + +void +isc_ntpaths_init(void); + +char * +isc_ntpaths_get(int); + +ISC_LANG_ENDDECLS + +#endif /* ISC_NTPATHS_H */ diff --git a/lib/isc/win32/include/isc/offset.h b/lib/isc/win32/include/isc/offset.h new file mode 100644 index 0000000..14ef06f --- /dev/null +++ b/lib/isc/win32/include/isc/offset.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_OFFSET_H +#define ISC_OFFSET_H 1 + +/* + * File offsets are operating-system dependent. + */ +#include /* Required for CHAR_BIT. */ +#include + +typedef _off_t isc_offset_t; + +#endif /* ISC_OFFSET_H */ diff --git a/lib/isc/win32/include/isc/once.h b/lib/isc/win32/include/isc/once.h new file mode 100644 index 0000000..c005b0b --- /dev/null +++ b/lib/isc/win32/include/isc/once.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_ONCE_H +#define ISC_ONCE_H 1 + +#include +#include + +ISC_LANG_BEGINDECLS + +typedef struct { + int status; + int counter; +} isc_once_t; + +#define ISC_ONCE_INIT_NEEDED 0 +#define ISC_ONCE_INIT_DONE 1 + +#define ISC_ONCE_INIT { ISC_ONCE_INIT_NEEDED, 1 } + +isc_result_t +isc_once_do(isc_once_t *controller, void(*function)(void)); + +ISC_LANG_ENDDECLS + +#endif /* ISC_ONCE_H */ diff --git a/lib/isc/win32/include/isc/platform.h.in b/lib/isc/win32/include/isc/platform.h.in new file mode 100644 index 0000000..5b8a2c9 --- /dev/null +++ b/lib/isc/win32/include/isc/platform.h.in @@ -0,0 +1,157 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef ISC_PLATFORM_H +#define ISC_PLATFORM_H 1 + +/***** + ***** Platform-dependent defines. + *****/ + +#define ISC_PLATFORM_USETHREADS 1 + +/*** + *** Network. + ***/ + +#ifndef PATH_MAX +#define PATH_MAX _MAX_PATH +#endif + +#define ISC_PLATFORM_HAVEIPV6 +#if _MSC_VER > 1200 +#define ISC_PLATFORM_HAVEIN6PKTINFO +#endif +#define ISC_PLATFORM_HAVESCOPEID +#define ISC_PLATFORM_NEEDPORTT +#undef MSG_TRUNC +#define ISC_PLATFORM_NEEDNTOP +#define ISC_PLATFORM_NEEDPTON +#define ISC_PLATFORM_HAVESOCKADDRSTORAGE + +#define ISC_PLATFORM_NEEDSTRSEP +#define ISC_PLATFORM_NEEDSTRLCPY +#define ISC_PLATFORM_NEEDSTRLCAT +#define ISC_PLATFORM_NEEDSTRLCPY + +/* + * Used to control how extern data is linked; needed for Win32 platforms. + */ +#define ISC_PLATFORM_USEDECLSPEC 1 + +/* + * Define this here for now as winsock2.h defines h_errno + * and we don't want to redeclare it. + */ +#define ISC_PLATFORM_NONSTDHERRNO + +/* + * Define if the platform has . + */ +#undef ISC_PLATFORM_HAVESYSUNH + +/* + * Define if we want to log backtrace + */ +@ISC_PLATFORM_USEBACKTRACE@ + +/* + * Defines for the noreturn attribute. + */ +#define ISC_PLATFORM_NORETURN_PRE __declspec(noreturn) +#define ISC_PLATFORM_NORETURN_POST + +/* + * Define if the hash functions must be provided by OpenSSL. + */ +@ISC_PLATFORM_OPENSSLHASH@ + +/* + * Define if AES support is wanted + */ +@ISC_PLATFORM_WANTAES@ + +/* + * If the "xadd" operation is available on this architecture, + * ISC_PLATFORM_HAVEXADD will be defined. + */ +@ISC_PLATFORM_HAVEXADD@ + +/* + * If the "xaddq" operation (64bit xadd) is available on this architecture, + * ISC_PLATFORM_HAVEXADDQ will be defined. + */ +@ISC_PLATFORM_HAVEXADDQ@ + +/* + * If the "atomic swap" operation is available on this architecture, + * ISC_PLATFORM_HAVEATOMICSTORE" will be defined. + */ +@ISC_PLATFORM_HAVEATOMICSTORE@ + +/* + * If the "compare-and-exchange" operation is available on this architecture, + * ISC_PLATFORM_HAVECMPXCHG will be defined. + */ +@ISC_PLATFORM_HAVECMPXCHG@ + +/* + * Define with the busy wait nop asm or function call. + */ +@ISC_PLATFORM_BUSYWAITNOP@ + +/* + * If the strcasestr() operation is not available on this platform, + * ISC_PLATFORM_NEEDSTRCASESTR will be defined. + */ +@ISC_PLATFORM_NEEDSTRCASESTR@ + +/* + * Set up a macro for importing and exporting from the DLL + */ + +#ifdef LIBISC_EXPORTS +#define LIBISC_EXTERNAL_DATA __declspec(dllexport) +#else +#define LIBISC_EXTERNAL_DATA __declspec(dllimport) +#endif + +#ifdef LIBDNS_EXPORTS +#define LIBDNS_EXTERNAL_DATA __declspec(dllexport) +#else +#define LIBDNS_EXTERNAL_DATA __declspec(dllimport) +#endif + +#ifdef LIBISCCC_EXPORTS +#define LIBISCCC_EXTERNAL_DATA __declspec(dllexport) +#else +#define LIBISCCC_EXTERNAL_DATA __declspec(dllimport) +#endif + +#ifdef LIBISCCFG_EXPORTS +#define LIBISCCFG_EXTERNAL_DATA __declspec(dllexport) +#else +#define LIBISCCFG_EXTERNAL_DATA __declspec(dllimport) +#endif + +#ifdef LIBBIND9_EXPORTS +#define LIBBIND9_EXTERNAL_DATA __declspec(dllexport) +#else +#define LIBBIND9_EXTERNAL_DATA __declspec(dllimport) +#endif + +#ifdef LIBTESTS_EXPORTS +#define LIBTESTS_EXTERNAL_DATA __declspec(dllexport) +#else +#define LIBTESTS_EXTERNAL_DATA __declspec(dllimport) +#endif + +#endif /* ISC_PLATFORM_H */ diff --git a/lib/isc/win32/include/isc/stat.h b/lib/isc/win32/include/isc/stat.h new file mode 100644 index 0000000..8b7d685 --- /dev/null +++ b/lib/isc/win32/include/isc/stat.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_STAT_H +#define ISC_STAT_H 1 + +#include + +/* + * Windows doesn't typedef this. + */ +typedef unsigned short mode_t; + +/* open() under unix allows setting of read/write permissions + * at the owner, group and other levels. These don't exist in NT + * We'll just map them all to the NT equivalent + */ + +#define S_IREAD _S_IREAD /* read permission, owner */ +#define S_IWRITE _S_IWRITE /* write permission, owner */ +#define S_IRUSR _S_IREAD /* Owner read permission */ +#define S_IWUSR _S_IWRITE /* Owner write permission */ +#define S_IRGRP _S_IREAD /* Group read permission */ +#define S_IWGRP _S_IWRITE /* Group write permission */ +#define S_IROTH _S_IREAD /* Other read permission */ +#define S_IWOTH _S_IWRITE /* Other write permission */ + +#ifndef S_IFMT +# define S_IFMT _S_IFMT +#endif +#ifndef S_IFDIR +# define S_IFDIR _S_IFDIR +#endif +#ifndef S_IFCHR +# define S_IFCHR _S_IFCHR +#endif +#ifndef S_IFREG +# define S_IFREG _S_IFREG +#endif + +#ifndef S_ISDIR +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif +#ifndef S_ISREG +# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#endif + +#endif /* ISC_STAT_H */ diff --git a/lib/isc/win32/include/isc/stdtime.h b/lib/isc/win32/include/isc/stdtime.h new file mode 100644 index 0000000..e11647f --- /dev/null +++ b/lib/isc/win32/include/isc/stdtime.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_STDTIME_H +#define ISC_STDTIME_H 1 + +#include +#include + +/* + * It's public information that 'isc_stdtime_t' is an unsigned integral type. + * Applications that want maximum portability should not assume anything + * about its size. + */ +typedef uint32_t isc_stdtime_t; + +/* but this flag helps... */ +#define STDTIME_ON_32BITS 1 + +/* + * isc_stdtime32_t is a 32-bit version of isc_stdtime_t. A variable of this + * type should only be used as an opaque integer (e.g.,) to compare two + * time values. + */ +typedef uint32_t isc_stdtime32_t; + +ISC_LANG_BEGINDECLS + +void +isc_stdtime_get(isc_stdtime_t *t); +/* + * Set 't' to the number of seconds since 00:00:00 UTC, January 1, 1970. + * + * Requires: + * + * 't' is a valid pointer. + */ + +#define isc_stdtime_convert32(t, t32p) (*(t32p) = t) +/* + * Convert the standard time to its 32-bit version. + */ + +ISC_LANG_ENDDECLS + +#endif /* ISC_STDTIME_H */ diff --git a/lib/isc/win32/include/isc/strerror.h b/lib/isc/win32/include/isc/strerror.h new file mode 100644 index 0000000..ae040a4 --- /dev/null +++ b/lib/isc/win32/include/isc/strerror.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_STRERROR_H +#define ISC_STRERROR_H + +#include + +#include + +ISC_LANG_BEGINDECLS + +#define ISC_STRERRORSIZE 128 + +/* + * Provide a thread safe wrapper to strerrror(). + * + * Requires: + * 'buf' to be non NULL. + */ +void +isc__strerror(int num, char *buf, size_t bufsize); + +ISC_LANG_ENDDECLS + +#endif /* ISC_STRERROR_H */ diff --git a/lib/isc/win32/include/isc/syslog.h b/lib/isc/win32/include/isc/syslog.h new file mode 100644 index 0000000..66431e5 --- /dev/null +++ b/lib/isc/win32/include/isc/syslog.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_SYSLOG_H +#define ISC_SYSLOG_H 1 + +#include +#include + +ISC_LANG_BEGINDECLS + +isc_result_t +isc_syslog_facilityfromstring(const char *str, int *facilityp); +/* + * Convert 'str' to the appropriate syslog facility constant. + * + * Requires: + * + * 'str' is not NULL + * 'facilityp' is not NULL + * + * Returns: + * ISC_R_SUCCESS + * ISC_R_NOTFOUND + */ + +ISC_LANG_ENDDECLS + +#endif /* ISC_SYSLOG_H */ diff --git a/lib/isc/win32/include/isc/thread.h b/lib/isc/win32/include/isc/thread.h new file mode 100644 index 0000000..be1343a --- /dev/null +++ b/lib/isc/win32/include/isc/thread.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_THREAD_H +#define ISC_THREAD_H 1 + +#include + +#include +#include + +/* + * Inlines to help with wait return checking + */ + +/* check handle for NULL and INVALID_HANDLE */ +inline BOOL IsValidHandle( HANDLE hHandle) { + return ((hHandle != NULL) && (hHandle != INVALID_HANDLE_VALUE)); +} + +/* validate wait return codes... */ +inline BOOL WaitSucceeded( DWORD dwWaitResult, DWORD dwHandleCount) { + return ((dwWaitResult >= WAIT_OBJECT_0) && + (dwWaitResult < WAIT_OBJECT_0 + dwHandleCount)); +} + +inline BOOL WaitAbandoned( DWORD dwWaitResult, DWORD dwHandleCount) { + return ((dwWaitResult >= WAIT_ABANDONED_0) && + (dwWaitResult < WAIT_ABANDONED_0 + dwHandleCount)); +} + +inline BOOL WaitTimeout( DWORD dwWaitResult) { + return (dwWaitResult == WAIT_TIMEOUT); +} + +inline BOOL WaitFailed( DWORD dwWaitResult) { + return (dwWaitResult == WAIT_FAILED); +} + +/* compute object indices for waits... */ +inline DWORD WaitSucceededIndex( DWORD dwWaitResult) { + return (dwWaitResult - WAIT_OBJECT_0); +} + +inline DWORD WaitAbandonedIndex( DWORD dwWaitResult) { + return (dwWaitResult - WAIT_ABANDONED_0); +} + + + +typedef HANDLE isc_thread_t; +typedef DWORD isc_threadresult_t; +typedef void * isc_threadarg_t; +typedef isc_threadresult_t (WINAPI *isc_threadfunc_t)(isc_threadarg_t); +typedef DWORD isc_thread_key_t; + +#define isc_thread_self (unsigned long)GetCurrentThreadId + +ISC_LANG_BEGINDECLS + +isc_result_t +isc_thread_create(isc_threadfunc_t, isc_threadarg_t, isc_thread_t *); + +isc_result_t +isc_thread_join(isc_thread_t, isc_threadresult_t *); + +void +isc_thread_setconcurrency(unsigned int level); + +void +isc_thread_setname(isc_thread_t, const char *); + +int +isc_thread_key_create(isc_thread_key_t *key, void (*func)(void *)); + +int +isc_thread_key_delete(isc_thread_key_t key); + +void * +isc_thread_key_getspecific(isc_thread_key_t); + +int +isc_thread_key_setspecific(isc_thread_key_t key, void *value); + +#define isc_thread_yield() Sleep(0) + +ISC_LANG_ENDDECLS + +#endif /* ISC_THREAD_H */ diff --git a/lib/isc/win32/include/isc/time.h b/lib/isc/win32/include/isc/time.h new file mode 100644 index 0000000..486f527 --- /dev/null +++ b/lib/isc/win32/include/isc/time.h @@ -0,0 +1,357 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_TIME_H +#define ISC_TIME_H 1 + +#include +#include +#include + +#include +#include + +/*** + *** Intervals + ***/ + +/* + * The contents of this structure are private, and MUST NOT be accessed + * directly by callers. + * + * The contents are exposed only to allow callers to avoid dynamic allocation. + */ +struct isc_interval { + int64_t interval; +}; + +LIBISC_EXTERNAL_DATA extern const isc_interval_t * const isc_interval_zero; + +/* + * ISC_FORMATHTTPTIMESTAMP_SIZE needs to be 30 in C locale and potentially + * more for other locales to handle longer national abbreviations when + * expanding strftime's %a and %b. + */ +#define ISC_FORMATHTTPTIMESTAMP_SIZE 50 + +ISC_LANG_BEGINDECLS + +void +isc_interval_set(isc_interval_t *i, + unsigned int seconds, unsigned int nanoseconds); +/* + * Set 'i' to a value representing an interval of 'seconds' seconds and + * 'nanoseconds' nanoseconds, suitable for use in isc_time_add() and + * isc_time_subtract(). + * + * Requires: + * + * 't' is a valid pointer. + * nanoseconds < 1000000000. + */ + +bool +isc_interval_iszero(const isc_interval_t *i); +/* + * Returns true iff. 'i' is the zero interval. + * + * Requires: + * + * 'i' is a valid pointer. + */ + +/*** + *** Absolute Times + ***/ + +/* + * The contents of this structure are private, and MUST NOT be accessed + * directly by callers. + * + * The contents are exposed only to allow callers to avoid dynamic allocation. + */ + +struct isc_time { + FILETIME absolute; +}; + +LIBISC_EXTERNAL_DATA extern const isc_time_t * const isc_time_epoch; + +void +isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds); +/*%< + * Set 't' to a value which represents the given number of seconds and + * nanoseconds since 00:00:00 January 1, 1970, UTC. + * + * Requires: + *\li 't' is a valid pointer. + *\li nanoseconds < 1000000000. + */ + +void +isc_time_settoepoch(isc_time_t *t); +/* + * Set 't' to the time of the epoch. + * + * Notes: + * The date of the epoch is platform-dependent. + * + * Requires: + * + * 't' is a valid pointer. + */ + +bool +isc_time_isepoch(const isc_time_t *t); +/* + * Returns true iff. 't' is the epoch ("time zero"). + * + * Requires: + * + * 't' is a valid pointer. + */ + +isc_result_t +isc_time_now(isc_time_t *t); +/* + * Set 't' to the current absolute time. + * + * Requires: + * + * 't' is a valid pointer. + * + * Returns: + * + * Success + * Unexpected error + * Getting the time from the system failed. + * Out of range + * The time from the system is too large to be represented + * in the current definition of isc_time_t. + */ + +isc_result_t +isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i); +/* + * Set *t to the current absolute time + i. + * + * Note: + * This call is equivalent to: + * + * isc_time_now(t); + * isc_time_add(t, i, t); + * + * Requires: + * + * 't' and 'i' are valid pointers. + * + * Returns: + * + * Success + * Unexpected error + * Getting the time from the system failed. + * Out of range + * The interval added to the time from the system is too large to + * be represented in the current definition of isc_time_t. + */ + +int +isc_time_compare(const isc_time_t *t1, const isc_time_t *t2); +/* + * Compare the times referenced by 't1' and 't2' + * + * Requires: + * + * 't1' and 't2' are valid pointers. + * + * Returns: + * + * -1 t1 < t2 (comparing times, not pointers) + * 0 t1 = t2 + * 1 t1 > t2 + */ + +isc_result_t +isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result); +/* + * Add 'i' to 't', storing the result in 'result'. + * + * Requires: + * + * 't', 'i', and 'result' are valid pointers. + * + * Returns: + * Success + * Out of range + * The interval added to the time is too large to + * be represented in the current definition of isc_time_t. + */ + +isc_result_t +isc_time_subtract(const isc_time_t *t, const isc_interval_t *i, + isc_time_t *result); +/* + * Subtract 'i' from 't', storing the result in 'result'. + * + * Requires: + * + * 't', 'i', and 'result' are valid pointers. + * + * Returns: + * Success + * Out of range + * The interval is larger than the time since the epoch. + */ + +uint64_t +isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2); +/* + * Find the difference in milliseconds between time t1 and time t2. + * t2 is the subtrahend of t1; ie, difference = t1 - t2. + * + * Requires: + * + * 't1' and 't2' are valid pointers. + * + * Returns: + * The difference of t1 - t2, or 0 if t1 <= t2. + */ + +isc_result_t +isc_time_parsehttptimestamp(char *input, isc_time_t *t); +/*%< + * Parse the time in 'input' into the isc_time_t pointed to by 't', + * expecting a format like "Mon, 30 Aug 2000 04:06:47 GMT" + * + * Requires: + *\li 'buf' and 't' are not NULL. + */ + +uint32_t +isc_time_nanoseconds(const isc_time_t *t); +/* + * Return the number of nanoseconds stored in a time structure. + * + * Notes: + * This is the number of nanoseconds in excess of the number + * of seconds since the epoch; it will always be less than one + * full second. + * + * Requires: + * 't' is a valid pointer. + * + * Ensures: + * The returned value is less than 1*10^9. + */ + +void +isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len); +/* + * Format the time 't' into the buffer 'buf' of length 'len', + * using a format like "30-Aug-2000 04:06:47.997" and the local time zone. + * If the text does not fit in the buffer, the result is indeterminate, + * but is always guaranteed to be null terminated. + * + * Requires: + * 'len' > 0 + * 'buf' points to an array of at least len chars + * + */ + +void +isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len); +/* + * Format the time 't' into the buffer 'buf' of length 'len', + * using a format like "Mon, 30 Aug 2000 04:06:47 GMT" + * If the text does not fit in the buffer, the result is indeterminate, + * but is always guaranteed to be null terminated. + * + * Requires: + * 'len' > 0 + * 'buf' points to an array of at least len chars + * + */ + +isc_result_t +isc_time_parsehttptimestamp(char *input, isc_time_t *t); +/*%< + * Parse the time in 'input' into the isc_time_t pointed to by 't', + * expecting a format like "Mon, 30 Aug 2000 04:06:47 GMT" + * + * Requires: + *\li 'buf' and 't' are not NULL. + */ + +void +isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len); +/*%< + * Format the time 't' into the buffer 'buf' of length 'len', + * using the ISO8601 format: "yyyy-mm-ddThh:mm:ssZ" + * If the text does not fit in the buffer, the result is indeterminate, + * but is always guaranteed to be null terminated. + * + * Requires: + *\li 'len' > 0 + *\li 'buf' points to an array of at least len chars + * + */ + +void +isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len); +/*%< + * Format the time 't' into the buffer 'buf' of length 'len', + * using the ISO8601 format: "yyyy-mm-ddThh:mm:ss.sssZ" + * If the text does not fit in the buffer, the result is indeterminate, + * but is always guaranteed to be null terminated. + * + * Requires: + *\li 'len' > 0 + *\li 'buf' points to an array of at least len chars + * + */ + +uint32_t +isc_time_seconds(const isc_time_t *t); +/*%< + * Return the number of seconds since the epoch stored in a time structure. + * + * Requires: + * + *\li 't' is a valid pointer. + */ + +isc_result_t +isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp); +/*%< + * Ensure the number of seconds in an isc_time_t is representable by a time_t. + * + * Notes: + *\li The number of seconds stored in an isc_time_t might be larger + * than the number of seconds a time_t is able to handle. Since + * time_t is mostly opaque according to the ANSI/ISO standard + * (essentially, all you can be sure of is that it is an arithmetic type, + * not even necessarily integral), it can be tricky to ensure that + * the isc_time_t is in the range a time_t can handle. Use this + * function in place of isc_time_seconds() any time you need to set a + * time_t from an isc_time_t. + * + * Requires: + *\li 't' is a valid pointer. + * + * Returns: + *\li Success + *\li Out of range + */ + +ISC_LANG_ENDDECLS + +#endif /* ISC_TIME_H */ diff --git a/lib/isc/win32/include/isc/win32os.h b/lib/isc/win32/include/isc/win32os.h new file mode 100644 index 0000000..bc18c40 --- /dev/null +++ b/lib/isc/win32/include/isc/win32os.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef ISC_WIN32OS_H +#define ISC_WIN32OS_H 1 + +#include + +ISC_LANG_BEGINDECLS + +/* + * Return the number of CPUs available on the system, or 1 if this cannot + * be determined. + */ + +int +isc_win32os_versioncheck(unsigned int major, unsigned int minor, + unsigned int updatemajor, unsigned int updateminor); + +/* + * Checks the current version of the operating system with the + * supplied version information. + * Returns: + * -1 if less than the version information supplied + * 0 if equal to all of the version information supplied + * +1 if greater than the version information supplied + */ + +ISC_LANG_ENDDECLS + +#endif /* ISC_WIN32OS_H */ diff --git a/lib/isc/win32/include/pkcs11/Makefile.in b/lib/isc/win32/include/pkcs11/Makefile.in new file mode 100644 index 0000000..e9a85d4 --- /dev/null +++ b/lib/isc/win32/include/pkcs11/Makefile.in @@ -0,0 +1,26 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +HEADERS = cryptoki.h +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/pkcs11 + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/pkcs11 || exit 1; \ + done diff --git a/lib/isc/win32/include/pkcs11/cryptoki.h b/lib/isc/win32/include/pkcs11/cryptoki.h new file mode 100644 index 0000000..2a681c4 --- /dev/null +++ b/lib/isc/win32/include/pkcs11/cryptoki.h @@ -0,0 +1,66 @@ +/* cryptoki.h include file for PKCS #11. */ +/* $Revision: 1.2 $ */ + +/* License to copy and use this software is granted provided that it is + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface + * (Cryptoki)" in all material mentioning or referencing this software. + + * License is also granted to make and use derivative works provided that + * such works are identified as "derived from the RSA Security Inc. PKCS #11 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or + * referencing the derived work. + + * RSA Security Inc. makes no representations concerning either the + * merchantability of this software or the suitability of this software for + * any particular purpose. It is provided "as is" without express or implied + * warranty of any kind. + */ + +/* This is a sample file containing the top level include directives + * for building Win32 Cryptoki libraries and applications. + */ + +#ifndef ___CRYPTOKI_H_INC___ +#define ___CRYPTOKI_H_INC___ + +#pragma pack(push, cryptoki, 1) + +/* Specifies that the function is a DLL entry point. */ +#define CK_IMPORT_SPEC __declspec(dllimport) + +/* Define CRYPTOKI_EXPORTS during the build of cryptoki libraries. Do + * not define it in applications. + */ +#ifdef CRYPTOKI_EXPORTS +/* Specified that the function is an exported DLL entry point. */ +#define CK_EXPORT_SPEC __declspec(dllexport) +#else +#define CK_EXPORT_SPEC CK_IMPORT_SPEC +#endif + +/* Ensures the calling convention for Win32 builds */ +#define CK_CALL_SPEC __cdecl + +#define CK_PTR * + +#define CK_DEFINE_FUNCTION(returnType, name) \ + returnType CK_EXPORT_SPEC CK_CALL_SPEC name + +#define CK_DECLARE_FUNCTION(returnType, name) \ + returnType CK_EXPORT_SPEC CK_CALL_SPEC name + +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \ + returnType CK_IMPORT_SPEC (CK_CALL_SPEC CK_PTR name) + +#define CK_CALLBACK_FUNCTION(returnType, name) \ + returnType (CK_CALL_SPEC CK_PTR name) + +#ifndef NULL_PTR +#define NULL_PTR 0 +#endif + +#include + +#pragma pack(pop, cryptoki) + +#endif /* ___CRYPTOKI_H_INC___ */ diff --git a/lib/isc/win32/interfaceiter.c b/lib/isc/win32/interfaceiter.c new file mode 100644 index 0000000..1bbd0f8 --- /dev/null +++ b/lib/isc/win32/interfaceiter.c @@ -0,0 +1,543 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* + * Note that this code will need to be revisited to support IPv6 Interfaces. + * For now we just iterate through IPv4 interfaces. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +void InitSockets(void); + +/* Common utility functions */ + +/* + * Extract the network address part from a "struct sockaddr". + * + * The address family is given explicitly + * instead of using src->sa_family, because the latter does not work + * for copying a network mask obtained by SIOCGIFNETMASK (it does + * not have a valid address family). + */ + + +#define IFITER_MAGIC 0x49464954U /* IFIT. */ +#define VALID_IFITER(t) ((t) != NULL && (t)->magic == IFITER_MAGIC) + +struct isc_interfaceiter { + unsigned int magic; /* Magic number. */ + isc_mem_t *mctx; + SOCKET socket; + INTERFACE_INFO IFData; /* Current Interface Info. */ + int numIF; /* Current Interface count. */ + int v4IF; /* Number of IPv4 Interfaces */ + INTERFACE_INFO *buf4; /* Buffer for WSAIoctl data. */ + unsigned int buf4size; /* Bytes allocated. */ + INTERFACE_INFO *pos4; /* Current offset in IF List */ + SOCKET_ADDRESS_LIST *buf6; /* Buffer for WSAIoctl data. */ + unsigned int buf6size; /* Bytes allocated. */ + unsigned int pos6; /* Which entry to process. */ + bool v6loop; /* See IPv6 loop address. */ + bool pos6zero; /* Done pos6 == 0. */ + isc_interface_t current; /* Current interface data. */ + isc_result_t result; /* Last result code. */ +}; + + +/* + * Size of buffer for SIO_GET_INTERFACE_LIST, in number of interfaces. + * We assume no sane system will have more than than 1K of IP addresses on + * all of its adapters. + */ +#define IFCONF_SIZE_INITIAL 16 +#define IFCONF_SIZE_INCREMENT 64 +#define IFCONF_SIZE_MAX 1040 + +static void +get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src) { + dst->family = family; + switch (family) { + case AF_INET: + memmove(&dst->type.in, + &((struct sockaddr_in *) src)->sin_addr, + sizeof(struct in_addr)); + break; + case AF_INET6: + memmove(&dst->type.in6, + &((struct sockaddr_in6 *) src)->sin6_addr, + sizeof(struct in6_addr)); + dst->zone = ((struct sockaddr_in6 *) src)->sin6_scope_id; + break; + default: + INSIST(0); + break; + } +} + +isc_result_t +isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { + char strbuf[ISC_STRERRORSIZE]; + isc_interfaceiter_t *iter; + isc_result_t result; + int error; + unsigned long bytesReturned = 0; + + REQUIRE(mctx != NULL); + REQUIRE(iterp != NULL); + REQUIRE(*iterp == NULL); + + iter = isc_mem_get(mctx, sizeof(*iter)); + if (iter == NULL) + return (ISC_R_NOMEMORY); + + InitSockets(); + + iter->mctx = mctx; + iter->buf4 = NULL; + iter->buf6 = NULL; + iter->pos4 = NULL; + iter->pos6 = 0; + iter->v6loop = true; + iter->pos6zero = true; + iter->buf6size = 0; + iter->buf4size = 0; + iter->result = ISC_R_FAILURE; + iter->numIF = 0; + iter->v4IF = 0; + + /* + * Create an unbound datagram socket to do the + * SIO_GET_INTERFACE_LIST WSAIoctl on. + */ + iter->socket = socket(AF_INET, SOCK_DGRAM, 0); + if (iter->socket == INVALID_SOCKET) { + error = WSAGetLastError(); + if (error == WSAEAFNOSUPPORT) + goto inet6_only; + isc__strerror(error, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "making interface scan socket: %s", + strbuf); + result = ISC_R_UNEXPECTED; + goto socket_failure; + } + + /* + * Get the interface configuration, allocating more memory if + * necessary. + */ + iter->buf4size = IFCONF_SIZE_INITIAL*sizeof(INTERFACE_INFO); + + for (;;) { + iter->buf4 = isc_mem_get(mctx, iter->buf4size); + if (iter->buf4 == NULL) { + result = ISC_R_NOMEMORY; + goto alloc_failure; + } + + if (WSAIoctl(iter->socket, SIO_GET_INTERFACE_LIST, + 0, 0, iter->buf4, iter->buf4size, + &bytesReturned, 0, 0) == SOCKET_ERROR) + { + error = WSAGetLastError(); + if (error != WSAEFAULT && error != WSAENOBUFS) { + errno = error; + isc__strerror(error, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "get interface configuration: %s", + strbuf); + result = ISC_R_UNEXPECTED; + goto ioctl_failure; + } + /* + * EINVAL. Retry with a bigger buffer. + */ + } else { + /* + * The WSAIoctl succeeded. + * If the number of the returned bytes is the same + * as the buffer size, we will grow it just in + * case and retry. + */ + if (bytesReturned > 0 && + (bytesReturned < iter->buf4size)) + break; + } + if (iter->buf4size >= IFCONF_SIZE_MAX*sizeof(INTERFACE_INFO)) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "get interface configuration: " + "maximum buffer size exceeded"); + result = ISC_R_UNEXPECTED; + goto ioctl_failure; + } + isc_mem_put(mctx, iter->buf4, iter->buf4size); + + iter->buf4size += IFCONF_SIZE_INCREMENT * + sizeof(INTERFACE_INFO); + } + + /* + * A newly created iterator has an undefined position + * until isc_interfaceiter_first() is called. + */ + iter->v4IF = bytesReturned/sizeof(INTERFACE_INFO); + + /* We don't need the socket any more, so close it */ + closesocket(iter->socket); + + inet6_only: + /* + * Create an unbound datagram socket to do the + * SIO_ADDRESS_LIST_QUERY WSAIoctl on. + */ + iter->socket = socket(AF_INET6, SOCK_DGRAM, 0); + if (iter->socket == INVALID_SOCKET) { + error = WSAGetLastError(); + if (error == WSAEAFNOSUPPORT) + goto inet_only; + isc__strerror(error, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "making interface scan socket: %s", + strbuf); + result = ISC_R_UNEXPECTED; + goto ioctl_failure; + } + + /* + * Get the interface configuration, allocating more memory if + * necessary. + */ + iter->buf6size = sizeof(SOCKET_ADDRESS_LIST) + + IFCONF_SIZE_INITIAL*sizeof(SOCKET_ADDRESS); + + for (;;) { + iter->buf6 = isc_mem_get(mctx, iter->buf6size); + if (iter->buf6 == NULL) { + result = ISC_R_NOMEMORY; + goto ioctl_failure; + } + + if (WSAIoctl(iter->socket, SIO_ADDRESS_LIST_QUERY, + 0, 0, iter->buf6, iter->buf6size, + &bytesReturned, 0, 0) == SOCKET_ERROR) + { + error = WSAGetLastError(); + if (error != WSAEFAULT && error != WSAENOBUFS) { + errno = error; + isc__strerror(error, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "sio address list query: %s", + strbuf); + result = ISC_R_UNEXPECTED; + goto ioctl6_failure; + } + /* + * EINVAL. Retry with a bigger buffer. + */ + } else + break; + + if (iter->buf6size >= IFCONF_SIZE_MAX*sizeof(SOCKET_ADDRESS)) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "get interface configuration: " + "maximum buffer size exceeded"); + result = ISC_R_UNEXPECTED; + goto ioctl6_failure; + } + isc_mem_put(mctx, iter->buf6, iter->buf6size); + + iter->buf6size += IFCONF_SIZE_INCREMENT * + sizeof(SOCKET_ADDRESS); + } + + closesocket(iter->socket); + + inet_only: + iter->magic = IFITER_MAGIC; + *iterp = iter; + return (ISC_R_SUCCESS); + + ioctl6_failure: + isc_mem_put(mctx, iter->buf6, iter->buf6size); + + ioctl_failure: + if (iter->buf4 != NULL) + isc_mem_put(mctx, iter->buf4, iter->buf4size); + + alloc_failure: + if (iter->socket != INVALID_SOCKET) + (void) closesocket(iter->socket); + + socket_failure: + isc_mem_put(mctx, iter, sizeof(*iter)); + return (result); +} + +/* + * Get information about the current interface to iter->current. + * If successful, return ISC_R_SUCCESS. + * If the interface has an unsupported address family, or if + * some operation on it fails, return ISC_R_IGNORE to make + * the higher-level iterator code ignore it. + */ + +static isc_result_t +internal_current(isc_interfaceiter_t *iter) { + BOOL ifNamed = FALSE; + unsigned long flags; + + REQUIRE(VALID_IFITER(iter)); + REQUIRE(iter->numIF >= 0); + + memset(&iter->current, 0, sizeof(iter->current)); + iter->current.af = AF_INET; + + get_addr(AF_INET, &iter->current.address, + (struct sockaddr *)&(iter->IFData.iiAddress)); + + /* + * Get interface flags. + */ + + iter->current.flags = 0; + flags = iter->IFData.iiFlags; + + if ((flags & IFF_UP) != 0) + iter->current.flags |= INTERFACE_F_UP; + + if ((flags & IFF_POINTTOPOINT) != 0) { + iter->current.flags |= INTERFACE_F_POINTTOPOINT; + snprintf(iter->current.name, sizeof(iter->current.name), + "PPP Interface %d", iter->numIF); + ifNamed = TRUE; + } + + if ((flags & IFF_LOOPBACK) != 0) { + iter->current.flags |= INTERFACE_F_LOOPBACK; + snprintf(iter->current.name, sizeof(iter->current.name), + "Loopback Interface %d", iter->numIF); + ifNamed = TRUE; + } + + /* + * If the interface is point-to-point, get the destination address. + */ + if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) { + get_addr(AF_INET, &iter->current.dstaddress, + (struct sockaddr *)&(iter->IFData.iiBroadcastAddress)); + } + + if (ifNamed == FALSE) + snprintf(iter->current.name, sizeof(iter->current.name), + "TCP/IP Interface %d", iter->numIF); + + /* + * Get the network mask. + */ + get_addr(AF_INET, &iter->current.netmask, + (struct sockaddr *)&(iter->IFData.iiNetmask)); + + return (ISC_R_SUCCESS); +} + +static isc_result_t +internal_current6(isc_interfaceiter_t *iter) { + SOCKET fd; + int i; + + REQUIRE(VALID_IFITER(iter)); + REQUIRE(iter->buf6 != NULL); + + memset(&iter->current, 0, sizeof(iter->current)); + iter->current.af = AF_INET6; + + if (!iter->pos6zero) { + if (iter->pos6 == 0U) + iter->pos6zero = true; + get_addr(AF_INET6, &iter->current.address, + iter->buf6->Address[iter->pos6].lpSockaddr); + + /* + * Set interface flags. + */ + + iter->current.flags = INTERFACE_F_UP; + + snprintf(iter->current.name, sizeof(iter->current.name), + "TCP/IPv6 Interface %u", iter->pos6 + 1); + + for (i = 0; i < 16; i++) + iter->current.netmask.type.in6.s6_addr[i] = 0xff; + iter->current.netmask.family = AF_INET6; + if (IN6_IS_ADDR_LOOPBACK(&iter->current.address.type.in6)) + iter->v6loop = true; + } else { + /* + * See if we can bind to the ::1 and if so return ::1. + */ + struct sockaddr_in6 sin6; + + iter->v6loop = true; /* So we don't loop forever. */ + + fd = socket(AF_INET6, SOCK_DGRAM, 0); + if (fd == INVALID_SOCKET) + return (ISC_R_IGNORE); + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + sin6.sin6_addr.s6_addr[15] = 1; + if (bind(fd, (struct sockaddr *)&sin6, sizeof(sin6)) < 0) { + closesocket(fd); + return (ISC_R_IGNORE); + } + closesocket(fd); + + iter->current.flags = INTERFACE_F_UP | INTERFACE_F_LOOPBACK; + snprintf(iter->current.name, sizeof(iter->current.name), + "TCP/IPv6 Loopback Interface"); + for (i = 0; i < 16; i++) { + if (i != 15) + iter->current.address.type.in6.s6_addr[i] = 0; + else + iter->current.address.type.in6.s6_addr[i] = 1; + iter->current.netmask.type.in6.s6_addr[i] = 0xff; + } + iter->current.address.family = AF_INET6; + iter->current.netmask.family = AF_INET6; + } + return (ISC_R_SUCCESS); +} + +/* + * Step the iterator to the next interface. Unlike + * isc_interfaceiter_next(), this may leave the iterator + * positioned on an interface that will ultimately + * be ignored. Return ISC_R_NOMORE if there are no more + * interfaces, otherwise ISC_R_SUCCESS. + */ +static isc_result_t +internal_next(isc_interfaceiter_t *iter) { + if (iter->numIF >= iter->v4IF) + return (ISC_R_NOMORE); + + /* + * The first one needs to be set up to point to the last + * Element of the array. Go to the end and back up + * Microsoft's implementation is peculiar for returning + * the list in reverse order + */ + + if (iter->numIF == 0) + iter->pos4 = (INTERFACE_INFO *)(iter->buf4 + (iter->v4IF)); + + iter->pos4--; + if (&(iter->pos4) < &(iter->buf4)) + return (ISC_R_NOMORE); + + memset(&(iter->IFData), 0, sizeof(INTERFACE_INFO)); + memmove(&(iter->IFData), iter->pos4, sizeof(INTERFACE_INFO)); + iter->numIF++; + + return (ISC_R_SUCCESS); +} + +static isc_result_t +internal_next6(isc_interfaceiter_t *iter) { + if (iter->pos6 == 0U && iter->v6loop) + return (ISC_R_NOMORE); + if (iter->pos6 != 0U) + iter->pos6--; + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_interfaceiter_current(isc_interfaceiter_t *iter, + isc_interface_t *ifdata) { + REQUIRE(iter->result == ISC_R_SUCCESS); + memmove(ifdata, &iter->current, sizeof(*ifdata)); + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_interfaceiter_first(isc_interfaceiter_t *iter) { + + REQUIRE(VALID_IFITER(iter)); + + if (iter->buf6 != NULL) { + iter->pos6 = iter->buf6->iAddressCount; + iter->v6loop = false; + iter->pos6zero = (iter->pos6 == 0U); + } + iter->result = ISC_R_SUCCESS; + return (isc_interfaceiter_next(iter)); +} + +isc_result_t +isc_interfaceiter_next(isc_interfaceiter_t *iter) { + isc_result_t result; + + REQUIRE(VALID_IFITER(iter)); + REQUIRE(iter->result == ISC_R_SUCCESS); + + for (;;) { + result = internal_next(iter); + if (result == ISC_R_NOMORE) { + result = internal_next6(iter); + if (result != ISC_R_SUCCESS) + break; + result = internal_current6(iter); + if (result == ISC_R_IGNORE) + continue; + break; + } else if (result != ISC_R_SUCCESS) + break; + result = internal_current(iter); + if (result != ISC_R_IGNORE) + break; + } + iter->result = result; + return (result); +} + +void +isc_interfaceiter_destroy(isc_interfaceiter_t **iterp) { + isc_interfaceiter_t *iter; + REQUIRE(iterp != NULL); + iter = *iterp; + REQUIRE(VALID_IFITER(iter)); + + if (iter->buf4 != NULL) + isc_mem_put(iter->mctx, iter->buf4, iter->buf4size); + if (iter->buf6 != NULL) + isc_mem_put(iter->mctx, iter->buf6, iter->buf6size); + + iter->magic = 0; + isc_mem_put(iter->mctx, iter, sizeof(*iter)); + *iterp = NULL; +} diff --git a/lib/isc/win32/ipv6.c b/lib/isc/win32/ipv6.c new file mode 100644 index 0000000..c2a4ac5 --- /dev/null +++ b/lib/isc/win32/ipv6.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include +#include + +LIBISC_EXTERNAL_DATA const struct in6_addr isc_in6addr_any = + IN6ADDR_ANY_INIT; + +LIBISC_EXTERNAL_DATA const struct in6_addr isc_in6addr_loopback = + IN6ADDR_LOOPBACK_INIT; diff --git a/lib/isc/win32/keyboard.c b/lib/isc/win32/keyboard.c new file mode 100644 index 0000000..6e6f800 --- /dev/null +++ b/lib/isc/win32/keyboard.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +isc_result_t +isc_keyboard_open(isc_keyboard_t *keyboard) { + int fd; + + REQUIRE(keyboard != NULL); + + fd = _fileno(stdin); + if (fd < 0) + return (ISC_R_IOERROR); + + keyboard->fd = fd; + + keyboard->result = ISC_R_SUCCESS; + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_keyboard_close(isc_keyboard_t *keyboard, unsigned int sleeptime) { + REQUIRE(keyboard != NULL); + + if (sleeptime > 0 && keyboard->result != ISC_R_CANCELED) + (void)Sleep(sleeptime*1000); + + keyboard->fd = -1; + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_keyboard_getchar(isc_keyboard_t *keyboard, unsigned char *cp) { + ssize_t cc; + unsigned char c; + + REQUIRE(keyboard != NULL); + REQUIRE(cp != NULL); + + cc = read(keyboard->fd, &c, 1); + if (cc < 0) { + keyboard->result = ISC_R_IOERROR; + return (keyboard->result); + } + + *cp = c; + + return (ISC_R_SUCCESS); +} + +bool +isc_keyboard_canceled(isc_keyboard_t *keyboard) { + return (keyboard->result == ISC_R_CANCELED); +} diff --git a/lib/isc/win32/libgen.h b/lib/isc/win32/libgen.h new file mode 100644 index 0000000..e74740f --- /dev/null +++ b/lib/isc/win32/libgen.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef LIBGEN_H +#define LIBGEN_H 1 + +char *basename(const char *); +char *dirname(const char *); + +#endif diff --git a/lib/isc/win32/libisc.def.exclude b/lib/isc/win32/libisc.def.exclude new file mode 100644 index 0000000..41e8562 --- /dev/null +++ b/lib/isc/win32/libisc.def.exclude @@ -0,0 +1,42 @@ +; These symbols are not needed by the WIN32 build, but build-tarballs +; will complain if they aren't present here. +isc_print_fprintf +isc_print_printf +isc_print_snprintf +isc_print_sprintf +isc_print_vsnprintf +isc_socket_accept +isc_socket_attach +isc_socket_bind +isc_socket_cancel +isc_socket_cleanunix +isc_socket_close +isc_socket_connect +isc_socket_create +isc_socket_detach +isc_socket_dscp +isc_socket_dup +isc_socket_fdwatchcreate +isc_socket_fdwatchpoke +isc_socket_filter +isc_socket_getpeername +isc_socket_getsockname +isc_socket_gettype +isc_socket_ipv6only +isc_socket_listen +isc_socket_open +isc_socket_permunix +isc_socket_recv +isc_socket_recv2 +isc_socket_recvv +isc_socket_register +isc_socket_send +isc_socket_sendto +isc_socket_sendto2 +isc_socket_sendtov +isc_socket_sendtov2 +isc_socket_sendv +isc_socketmgr_create +isc_socketmgr_create2 +isc_socketmgr_destroy +isc_socketmgr_setstats diff --git a/lib/isc/win32/libisc.def.in b/lib/isc/win32/libisc.def.in new file mode 100644 index 0000000..a82face --- /dev/null +++ b/lib/isc/win32/libisc.def.in @@ -0,0 +1,836 @@ +LIBRARY libisc + +; Exported Functions +EXPORTS + +NTReportError +closelog +@IF PKCS11 +getpassphrase +@END PKCS11 +isc___socketmgr_maxudp +isc__app_block +isc__app_ctxfinish +isc__app_ctxonrun +isc__app_ctxrun +isc__app_ctxshutdown +isc__app_ctxstart +isc__app_ctxsuspend +isc__app_finish +isc__app_onrun +isc__app_reload +isc__app_run +isc__app_shutdown +isc__app_start +isc__app_unblock +isc__appctx_create +isc__appctx_destroy +isc__appctx_setsocketmgr +isc__appctx_settaskmgr +isc__appctx_settimermgr +isc__buffer_activeregion +isc__buffer_add +isc__buffer_availableregion +isc__buffer_back +isc__buffer_clear +isc__buffer_consumedregion +isc__buffer_first +isc__buffer_forward +isc__buffer_init +isc__buffer_initnull +isc__buffer_invalidate +isc__buffer_putmem +isc__buffer_putstr +isc__buffer_putuint16 +isc__buffer_putuint24 +isc__buffer_putuint32 +isc__buffer_putuint48 +isc__buffer_putuint8 +isc__buffer_region +isc__buffer_remainingregion +isc__buffer_setactive +isc__buffer_subtract +isc__buffer_usedregion +isc__hash_setvec +isc__mem_allocate +isc__mem_free +isc__mem_get +isc__mem_put +isc__mem_putanddetach +isc__mem_reallocate +isc__mem_strdup +isc__mempool_get +isc__mempool_put +isc__socket_accept +isc__socket_attach +isc__socket_bind +isc__socket_cancel +isc__socket_cleanunix +isc__socket_close +isc__socket_connect +isc__socket_create +isc__socket_detach +isc__socket_dscp +isc__socket_dup +isc__socket_filter +isc__socket_getfd +isc__socket_getname +isc__socket_getpeername +isc__socket_getsockname +isc__socket_gettag +isc__socket_gettype +isc__socket_ipv6only +isc__socket_isbound +isc__socket_listen +isc__socket_open +isc__socket_permunix +isc__socket_recv +isc__socket_recv2 +isc__socket_recvv +isc__socket_register +isc__socket_send +isc__socket_sendto +isc__socket_sendto2 +isc__socket_sendtov +isc__socket_sendtov2 +isc__socket_sendv +isc__socket_setname +isc__socketmgr_create +isc__socketmgr_create2 +isc__socketmgr_destroy +isc__socketmgr_getmaxsockets +isc__socketmgr_setreserved +isc__socketmgr_setstats +isc__strerror +isc__task_getname +isc__task_gettag +isc__task_unsendrange +isc__taskmgr_mode +@IF AES +isc_aes128_crypt +isc_aes192_crypt +isc_aes256_crypt +@END AES +isc_app_block +isc_app_ctxfinish +isc_app_ctxonrun +isc_app_ctxrun +isc_app_ctxshutdown +isc_app_ctxstart +isc_app_ctxsuspend +isc_app_finish +isc_app_isrunning +isc_app_onrun +isc_app_register +isc_app_reload +isc_app_run +isc_app_shutdown +isc_app_start +isc_app_unblock +isc_appctx_create +isc_appctx_destroy +isc_appctx_setsocketmgr +isc_appctx_settaskmgr +isc_appctx_settimermgr +isc_assertion_failed +isc_assertion_setcallback +isc_assertion_typetotext +isc_backtrace_getsymbol +isc_backtrace_getsymbolfromindex +isc_backtrace_gettrace +isc_base32_decoderegion +isc_base32_decodestring +isc_base32_tobuffer +isc_base32_totext +isc_base32hex_decoderegion +isc_base32hex_decodestring +isc_base32hex_tobuffer +isc_base32hex_totext +isc_base32hexnp_decoderegion +isc_base32hexnp_decodestring +isc_base32hexnp_tobuffer +isc_base32hexnp_totext +isc_base64_decodestring +isc_base64_tobuffer +isc_base64_totext +isc_buffer_allocate +isc_buffer_compact +isc_buffer_copyregion +isc_buffer_dup +isc_buffer_free +isc_buffer_getuint16 +isc_buffer_getuint32 +isc_buffer_getuint48 +isc_buffer_getuint8 +isc_buffer_putdecint +isc_buffer_reallocate +isc_buffer_reinit +isc_buffer_reserve +isc_buffer_setautorealloc +isc_bufferlist_availablecount +isc_bufferlist_usedcount +isc_commandline_parse +isc_commandline_strtoargv +isc_condition_broadcast +isc_condition_destroy +isc_condition_init +isc_condition_signal +isc_condition_wait +isc_condition_waituntil +isc_counter_attach +isc_counter_create +isc_counter_detach +isc_counter_increment +isc_counter_setlimit +isc_counter_used +isc_crc64_final +isc_crc64_init +isc_crc64_update +isc_dir_chdir +isc_dir_chroot +isc_dir_close +isc_dir_createunique +isc_dir_init +isc_dir_open +isc_dir_read +isc_dir_reset +isc_entropy_addcallbacksample +isc_entropy_addsample +isc_entropy_attach +isc_entropy_create +isc_entropy_createcallbacksource +isc_entropy_createfilesource +isc_entropy_createsamplesource +isc_entropy_destroysource +isc_entropy_detach +isc_entropy_getdata +isc_entropy_putdata +isc_entropy_stats +isc_entropy_status +isc_entropy_stopcallbacksources +isc_entropy_usebestsource +isc_errno_toresult +isc_error_fatal +isc_error_runtimecheck +isc_error_setfatal +isc_error_setunexpected +isc_error_unexpected +isc_event_allocate +isc_event_constallocate +isc_event_free +isc_file_absolutepath +isc_file_basename +isc_file_bopenunique +isc_file_bopenuniquemode +isc_file_bopenuniqueprivate +isc_file_exists +isc_file_getmodtime +isc_file_getsize +isc_file_getsizefd +isc_file_isabsolute +isc_file_ischdiridempotent +isc_file_iscurrentdir +isc_file_isdirectory +isc_file_isdirwritable +isc_file_isplainfile +isc_file_isplainfilefd +isc_file_mktemplate +isc_file_mmap +isc_file_mode +isc_file_munmap +isc_file_openunique +isc_file_openuniquemode +isc_file_openuniqueprivate +isc_file_progname +isc_file_remove +isc_file_rename +isc_file_renameunique +isc_file_safecreate +isc_file_safemovefile +isc_file_sanitize +isc_file_settime +isc_file_splitpath +isc_file_template +isc_file_truncate +isc_fsaccess_add +isc_fsaccess_changeowner +isc_fsaccess_remove +isc_fsaccess_set +isc_hash_calc +isc_hash_create +isc_hash_ctxattach +isc_hash_ctxcalc +isc_hash_ctxcreate +isc_hash_ctxdetach +isc_hash_ctxinit +isc_hash_destroy +isc_hash_function +isc_hash_function_reverse +isc_hash_get_initializer +isc_hash_init +isc_hash_set_initializer +isc_heap_create +isc_heap_decreased +isc_heap_delete +isc_heap_destroy +isc_heap_foreach +isc_heap_element +isc_heap_increased +isc_heap_insert +isc_hex_decodestring +isc_hex_tobuffer +isc_hex_totext +isc_hmacmd5_check +isc_hmacmd5_init +isc_hmacmd5_invalidate +isc_hmacmd5_sign +isc_hmacmd5_update +isc_hmacmd5_verify +isc_hmacmd5_verify2 +isc_hmacsha1_check +isc_hmacsha1_init +isc_hmacsha1_invalidate +isc_hmacsha1_sign +isc_hmacsha1_update +isc_hmacsha1_verify +isc_hmacsha224_init +isc_hmacsha224_invalidate +isc_hmacsha224_sign +isc_hmacsha224_update +isc_hmacsha224_verify +isc_hmacsha256_init +isc_hmacsha256_invalidate +isc_hmacsha256_sign +isc_hmacsha256_update +isc_hmacsha256_verify +isc_hmacsha384_init +isc_hmacsha384_invalidate +isc_hmacsha384_sign +isc_hmacsha384_update +isc_hmacsha384_verify +isc_hmacsha512_init +isc_hmacsha512_invalidate +isc_hmacsha512_sign +isc_hmacsha512_update +isc_hmacsha512_verify +isc_ht_add +isc_ht_count +isc_ht_delete +isc_ht_destroy +isc_ht_find +isc_ht_init +isc_ht_iter_create +isc_ht_iter_current +isc_ht_iter_currentkey +isc_ht_iter_delcurrent_next +isc_ht_iter_destroy +isc_ht_iter_first +isc_ht_iter_next +isc_httpd_addheader +isc_httpd_addheaderuint +isc_httpd_response +isc_httpd_setfinishhook +isc_httpdmgr_addurl +isc_httpdmgr_addurl2 +isc_httpdmgr_create +isc_httpdmgr_shutdown +isc_interfaceiter_create +isc_interfaceiter_current +isc_interfaceiter_destroy +isc_interfaceiter_first +isc_interfaceiter_next +isc_interval_iszero +isc_interval_set +isc_iterated_hash +isc_keyboard_canceled +isc_keyboard_close +isc_keyboard_getchar +isc_keyboard_open +isc_lex_close +isc_lex_create +isc_lex_destroy +isc_lex_getcomments +isc_lex_getlasttokentext +isc_lex_getmastertoken +isc_lex_getoctaltoken +isc_lex_getsourceline +isc_lex_getsourcename +isc_lex_getspecials +isc_lex_gettoken +isc_lex_isfile +isc_lex_openbuffer +isc_lex_openfile +isc_lex_openstream +isc_lex_setcomments +isc_lex_setsourceline +isc_lex_setsourcename +isc_lex_setspecials +isc_lex_ungettoken +isc_lfsr_generate +isc_lfsr_generate32 +isc_lfsr_init +isc_lfsr_skip +isc_lib_initmsgcat +isc_lib_register +isc_log_categorybyname +isc_log_closefilelogs +isc_log_create +isc_log_createchannel +isc_log_destroy +isc_log_getdebuglevel +isc_log_getduplicateinterval +isc_log_gettag +isc_log_ivwrite +isc_log_ivwrite1 +isc_log_iwrite +isc_log_iwrite1 +isc_log_modulebyname +isc_log_opensyslog +isc_log_registercategories +isc_log_registermodules +isc_log_setcontext +isc_log_setdebuglevel +isc_log_setduplicateinterval +isc_log_settag +isc_log_usechannel +isc_log_vwrite +isc_log_vwrite1 +isc_log_wouldlog +isc_log_write +isc_log_write1 +isc_logconfig_create +isc_logconfig_destroy +isc_logconfig_get +isc_logconfig_use +isc_logfile_roll +isc_md5_check +isc_md5_final +isc_md5_init +isc_md5_invalidate +isc_md5_update +isc_mem_attach +isc_mem_checkdestroyed +isc_mem_create +isc_mem_create2 +isc_mem_createx +isc_mem_createx2 +isc_mem_destroy +isc_mem_detach +isc_mem_getname +isc_mem_getquota +isc_mem_gettag +isc_mem_inuse +isc_mem_isovermem +isc_mem_maxinuse +isc_mem_ondestroy +isc_mem_printallactive +isc_mem_references +isc_mem_register +@IF NOTYET +isc_mem_renderjson +@END NOTYET +@IF LIBXML2 +isc_mem_renderxml +@END LIBXML2 +isc_mem_setdestroycheck +isc_mem_setname +isc_mem_setquota +isc_mem_setwater +isc_mem_stats +isc_mem_total +isc_mem_waterack +isc_meminfo_totalphys +isc_mempool_associatelock +isc_mempool_create +isc_mempool_destroy +isc_mempool_getallocated +isc_mempool_getfillcount +isc_mempool_getfreecount +isc_mempool_getfreemax +isc_mempool_getmaxalloc +isc_mempool_setfillcount +isc_mempool_setfreemax +isc_mempool_setmaxalloc +isc_mempool_setname +isc_msgcat_close +isc_msgcat_get +isc_msgcat_open +isc_mutexblock_destroy +isc_mutexblock_init +isc_net_aton +isc_net_disableipv4 +isc_net_disableipv6 +isc_net_enableipv4 +isc_net_enableipv6 +isc_net_getudpportrange +isc_net_ntop +isc_net_probe_ipv6only +isc_net_probe_ipv6pktinfo +isc_net_probedscp +isc_net_probeipv4 +isc_net_probeipv6 +isc_net_probeunix +isc_net_pton +isc_netaddr_any +isc_netaddr_any6 +isc_netaddr_eqprefix +isc_netaddr_equal +isc_netaddr_format +isc_netaddr_fromin +isc_netaddr_fromin6 +isc_netaddr_frompath +isc_netaddr_fromsockaddr +isc_netaddr_fromv4mapped +isc_netaddr_getzone +isc_netaddr_isexperimental +isc_netaddr_islinklocal +isc_netaddr_isloopback +isc_netaddr_ismulticast +isc_netaddr_isnetzero +isc_netaddr_issitelocal +isc_netaddr_masktoprefixlen +isc_netaddr_prefixok +isc_netaddr_setzone +isc_netaddr_totext +isc_netscope_pton +isc_ntpaths_get +isc_ntpaths_init +isc_once_do +isc_ondestroy_init +isc_ondestroy_notify +isc_ondestroy_register +isc_os_ncpus +isc_parse_uint16 +isc_parse_uint32 +isc_parse_uint8 +isc_pool_count +isc_pool_create +isc_pool_destroy +isc_pool_expand +isc_pool_get +isc_portset_add +isc_portset_addrange +isc_portset_create +isc_portset_destroy +isc_portset_isset +isc_portset_nports +isc_portset_remove +isc_portset_removerange +isc_quota_attach +isc_quota_destroy +isc_quota_detach +isc_quota_init +isc_quota_max +isc_quota_release +isc_quota_reserve +isc_quota_soft +isc_radix_create +isc_radix_destroy +isc_radix_insert +isc_radix_process +isc_radix_remove +isc_radix_search +isc_random_get +isc_random_jitter +isc_random_seed +isc_ratelimiter_attach +isc_ratelimiter_create +isc_ratelimiter_dequeue +isc_ratelimiter_detach +isc_ratelimiter_enqueue +isc_ratelimiter_release +isc_ratelimiter_setinterval +isc_ratelimiter_setpertic +isc_ratelimiter_setpushpop +isc_ratelimiter_shutdown +isc_ratelimiter_stall +isc_refcount_init +isc_regex_validate +isc_region_compare +isc_resource_getcurlimit +isc_resource_getlimit +isc_resource_setlimit +isc_result_register +isc_result_registerids +isc_result_toid +isc_result_totext +isc_rng_attach +isc_rng_create +isc_rng_detach +isc_rng_random +isc_rng_uniformrandom +isc_rwlock_destroy +isc_rwlock_downgrade +isc_rwlock_init +isc_rwlock_lock +isc_rwlock_trylock +isc_rwlock_tryupgrade +isc_rwlock_unlock +isc_safe_memcompare +isc_safe_memequal +isc_safe_memwipe +isc_serial_eq +isc_serial_ge +isc_serial_gt +isc_serial_le +isc_serial_lt +isc_serial_ne +isc_sha1_check +isc_sha1_final +isc_sha1_init +isc_sha1_invalidate +isc_sha1_update +isc_sha224_data +isc_sha224_end +isc_sha224_final +isc_sha224_init +isc_sha224_invalidate +isc_sha224_update +isc_sha256_data +isc_sha256_end +isc_sha256_final +isc_sha256_init +isc_sha256_invalidate +isc_sha256_update +isc_sha384_data +isc_sha384_end +isc_sha384_final +isc_sha384_init +isc_sha384_invalidate +isc_sha384_update +isc_sha512_data +isc_sha512_end +isc_sha512_final +isc_sha512_init +isc_sha512_invalidate +isc_sha512_update +isc_sockaddr_any +isc_sockaddr_any6 +isc_sockaddr_anyofpf +isc_sockaddr_compare +isc_sockaddr_eqaddr +isc_sockaddr_eqaddrprefix +isc_sockaddr_equal +isc_sockaddr_format +isc_sockaddr_fromin +isc_sockaddr_fromin6 +isc_sockaddr_fromnetaddr +isc_sockaddr_frompath +isc_sockaddr_getport +isc_sockaddr_hash +isc_sockaddr_isexperimental +isc_sockaddr_islinklocal +isc_sockaddr_ismulticast +isc_sockaddr_isnetzero +isc_sockaddr_issitelocal +isc_sockaddr_pf +isc_sockaddr_setport +isc_sockaddr_totext +isc_sockaddr_v6fromin +isc_socket_socketevent +isc_socketmgr_createinctx +@IF NOTYET +isc_socketmgr_renderjson +@END NOTYET +@IF LIBXML2 +isc_socketmgr_renderxml +@END LIBXML2 +isc_stats_attach +isc_stats_create +isc_stats_decrement +isc_stats_detach +isc_stats_dump +isc_stats_increment +isc_stats_ncounters +isc_stats_set +isc_stdio_close +isc_stdio_flush +isc_stdio_open +isc_stdio_read +isc_stdio_seek +isc_stdio_sync +isc_stdio_tell +isc_stdio_write +isc_stdtime_get +isc_string_append +isc_string_append_truncate +isc_string_copy +isc_string_copy_truncate +isc_string_printf +isc_string_printf_truncate +isc_string_regiondup +isc_string_separate +isc_string_strcasestr +isc_string_strlcat +isc_string_strlcpy +isc_string_touint64 +isc_symtab_count +isc_symtab_create +isc_symtab_define +isc_symtab_destroy +isc_symtab_lookup +isc_symtab_undefine +isc_syslog_facilityfromstring +isc_task_attach +isc_task_beginexclusive +isc_task_create +isc_task_destroy +isc_task_detach +isc_task_endexclusive +isc_task_exiting +isc_task_getcurrenttime +isc_task_getcurrenttimex +isc_task_onshutdown +isc_task_privilege +isc_task_purge +isc_task_purgeevent +isc_task_purgerange +isc_task_register +isc_task_send +isc_task_sendanddetach +isc_task_setname +isc_task_setprivilege +isc_task_shutdown +isc_task_unsend +isc_taskmgr_create +isc_taskmgr_createinctx +isc_taskmgr_destroy +isc_taskmgr_excltask +isc_taskmgr_mode +@IF NOTYET +isc_taskmgr_renderjson +@END NOTYET +@IF LIBXML2 +isc_taskmgr_renderxml +@END LIBXML2 +isc_taskmgr_setexcltask +isc_taskmgr_setmode +isc_taskpool_create +isc_taskpool_destroy +isc_taskpool_expand +isc_taskpool_gettask +isc_taskpool_setprivilege +isc_taskpool_size +isc_thread_create +isc_thread_join +isc_thread_key_create +isc_thread_key_delete +isc_thread_key_getspecific +isc_thread_key_setspecific +isc_thread_setconcurrency +isc_thread_setname +isc_time_add +isc_time_compare +isc_time_formatISO8601 +isc_time_formatISO8601ms +isc_time_formathttptimestamp +isc_time_formattimestamp +isc_time_isepoch +isc_time_microdiff +isc_time_nanoseconds +isc_time_now +isc_time_nowplusinterval +isc_time_parsehttptimestamp +isc_time_secondsastimet +isc_time_seconds +isc_time_set +isc_time_settoepoch +isc_time_subtract +isc_timer_attach +isc_timer_create +isc_timer_detach +isc_timer_gettype +isc_timer_register +isc_timer_reset +isc_timer_touch +isc_timermgr_create +isc_timermgr_createinctx +isc_timermgr_destroy +isc_timermgr_poke +isc_tm_timegm +isc_tm_strptime +isc_win32os_versioncheck +openlog +@IF PKCS11 +pk11_attribute_bytype +pk11_attribute_first +pk11_attribute_next +pk11_dump_tokens +pk11_error_fatalcheck +pk11_finalize +pk11_get_best_token +pk11_get_lib_name +pk11_get_load_error_message +pk11_get_session +pk11_initialize +pk11_initmsgcat +pk11_mem_get +pk11_mem_put +pk11_numbits +pk11_parse_uri +pk11_rand_bytes +pk11_rand_seed_fromfile +pk11_result_register +pk11_result_totext +pk11_return_session +pk11_set_lib_name +pkcs_C_CloseSession +pkcs_C_CreateObject +pkcs_C_DeriveKey +pkcs_C_DestroyObject +pkcs_C_DigestFinal +pkcs_C_DigestInit +pkcs_C_DigestUpdate +pkcs_C_Encrypt +pkcs_C_EncryptInit +pkcs_C_Finalize +pkcs_C_FindObjects +pkcs_C_FindObjectsFinal +pkcs_C_FindObjectsInit +pkcs_C_GenerateKey +pkcs_C_GenerateKeyPair +pkcs_C_GenerateRandom +pkcs_C_GetAttributeValue +pkcs_C_GetMechanismInfo +pkcs_C_GetSlotList +pkcs_C_GetTokenInfo +pkcs_C_Initialize +pkcs_C_Login +pkcs_C_Logout +pkcs_C_OpenSession +pkcs_C_SeedRandom +pkcs_C_SetAttributeValue +pkcs_C_Sign +pkcs_C_SignFinal +pkcs_C_SignInit +pkcs_C_SignUpdate +pkcs_C_Verify +pkcs_C_VerifyFinal +pkcs_C_VerifyInit +pkcs_C_VerifyUpdate +@END PKCS11 +syslog + +@IF NOLONGER +; Exported Data + +EXPORTS + +isc__backtrace_nsymbols DATA +isc__backtrace_symtable DATA +isc_bind9 DATA +isc_commandline_argument DATA +isc_commandline_errprint DATA +isc_commandline_index DATA +isc_commandline_option DATA +isc_commandline_progname DATA +isc_commandline_reset DATA +isc_dscp_check_value DATA +isc_hashctx DATA +isc_mem_debugging DATA +isc_msgcat DATA +@IF PKCS11 +pk11_msgcat DATA +pk11_verbose_init DATA +@END PKCS11 +@END NOLONGER diff --git a/lib/isc/win32/libisc.dsp.in b/lib/isc/win32/libisc.dsp.in new file mode 100644 index 0000000..d21edb8 --- /dev/null +++ b/lib/isc/win32/libisc.dsp.in @@ -0,0 +1,949 @@ +# Microsoft Developer Studio Project File - Name="libisc" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "@PLATFORM@ (x86) Dynamic-Link Library" 0x0102 + +CFG=libisc - @PLATFORM@ Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libisc.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libisc.mak" CFG="libisc - @PLATFORM@ Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libisc - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Dynamic-Link Library") +!MESSAGE "libisc - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 @COPTX@ @COPTI@ /O2 /D "BIND9" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" @COPTY@ /FD /c +@IF PKCS11 +# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @ZLIB_INC@ /I "include" /I "../include" /I "win32" /I "../../isccfg/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /D "BIND9" @CRYPTO@ @PK11_LIB_LOCATION@ /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" @COPTY@ /FD /c +@ELSE PKCS11 +# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @ZLIB_INC@ /I "include" /I "../include" /I "win32" /I "../../isccfg/include" /D "BIND9" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" @COPTY@ /FD /c +@END PKCS11 +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll @MACHINE@ +# ADD LINK32 @LIBXML2_LIB@ @OPENSSL_LIB@ @ZLIB_LIB@ user32.lib advapi32.lib ws2_32.lib /nologo /dll @MACHINE@ /out:"../../../Build/Release/libisc.dll" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "BIND9" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" @COPTY@ /FD /GZ /c +@IF PKCS11 +# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @ZLIB_INC@ /I "include" /I "../include" /I "win32" /I "../../isccfg/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /D "BIND9" @CRYPTO@ @PK11_LIB_LOCATION@ /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR @COPTY@ /FD /GZ /c +@ELSE PKCS11 +# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @ZLIB_INC@ /I "include" /I "../include" /I "win32" /I "../../isccfg/include" /D "BIND9" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR @COPTY@ /FD /GZ /c +@END PKCS11 +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug @MACHINE@ /pdbtype:sept +# ADD LINK32 @LIBXML2_LIB@ @OPENSSL_LIB@ @ZLIB_LIB@ user32.lib advapi32.lib ws2_32.lib /nologo /dll /map /debug @MACHINE@ /out:"../../../Build/Debug/libisc.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "libisc - @PLATFORM@ Release" +# Name "libisc - @PLATFORM@ Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\app.c +# End Source File +# Begin Source File + +SOURCE=.\condition.c +# End Source File +# Begin Source File + +SOURCE=.\dir.c +# End Source File +# Begin Source File + +SOURCE=.\DLLMain.c +# End Source File +# Begin Source File + +SOURCE=.\entropy.c +# End Source File +# Begin Source File + +SOURCE=.\errno.c +# End Source File +# Begin Source File + +SOURCE=.\errno2result.c +# End Source File +# Begin Source File + +SOURCE=.\file.c +# End Source File +# Begin Source File + +SOURCE=.\fsaccess.c +# End Source File +# Begin Source File + +SOURCE=.\interfaceiter.c +# End Source File +# Begin Source File + +SOURCE=.\ipv6.c +# End Source File +# Begin Source File + +SOURCE=.\keyboard.c +# End Source File +# Begin Source File + +SOURCE=.\meminfo.c +# End Source File +# Begin Source File + +SOURCE=.\net.c +# End Source File +# Begin Source File + +SOURCE=.\ntpaths.c +# End Source File +# Begin Source File + +SOURCE=.\once.c +# End Source File +# Begin Source File + +SOURCE=.\os.c +# End Source File +@IF PKCS11 +# Begin Source File + +SOURCE=.\pk11_api.c +# End Source File +@END PKCS11 +# Begin Source File + +SOURCE=.\resource.c +# End Source File +# Begin Source File + +SOURCE=.\socket.c +# End Source File +# Begin Source File + +SOURCE=.\stdio.c +# End Source File +# Begin Source File + +SOURCE=.\stdtime.c +# End Source File +# Begin Source File + +SOURCE=.\strerror.c +# End Source File +# Begin Source File + +SOURCE=.\syslog.c +# End Source File +# Begin Source File + +SOURCE=.\thread.c +# End Source File +# Begin Source File + +SOURCE=.\time.c +# End Source File +# Begin Source File + +SOURCE=.\version.c +# End Source File +# Begin Source File + +SOURCE=.\win32os.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +@IF AES +# Begin Source File + +SOURCE=..\include\isc\aes.h +# End Source File +@END AES +# Begin Source File + +SOURCE=..\include\isc\app.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\assertions.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\backtrace.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\base32.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\base64.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\bind9.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\bind_registry.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\bindevt.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\boolean.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\buffer.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\bufferlist.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\commandline.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\counter.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\condition.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\config.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\crc64.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\dir.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\entropy.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\errno.h +# End Source File +# Begin Source File + +SOURCE=.\errno2result.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\error.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\event.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\eventclass.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\file.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\formatcheck.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\fsaccess.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\hash.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\heap.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\hex.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\hmacmd5.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\hmacsha.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\ht.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\httpd.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\int.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\interfaceiter.h +# End Source File +@IF PKCS11 +# Begin Source File + +SOURCE=..\include\pk11\internal.h +# End Source File +@END PKCS11 +# Begin Source File + +SOURCE=.\include\isc\ipv6.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\iterated_hash.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\keyboard.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\json.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\lang.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\lex.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\lfsr.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\lib.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\list.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\log.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\magic.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\md5.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\mem.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\meminfo.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\msgcat.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\mutex.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\mutexblock.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\net.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\netaddr.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\netscope.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\netdb.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\ntgroups.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\ntpaths.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\offset.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\once.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\ondestroy.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\os.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\parseint.h +# End Source File +@IF PKCS11 +# Begin Source File + +SOURCE=..\include\pk11\pk11.h +# End Source File +@END PKCS11 +# Begin Source File + +SOURCE=..\include\isc\pool.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\portset.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\platform.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\print.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\queue.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\quota.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\radix.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\random.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\ratelimiter.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\refcount.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\regex.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\region.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\resource.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\result.h +# End Source File +@IF PKCS11 +# Begin Source File + +SOURCE=..\include\pk11\result.h +# End Source File +@END PKCS11 +# Begin Source File + +SOURCE=..\include\isc\resultclass.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\rwlock.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\safe.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\serial.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\sha1.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\sha2.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\sockaddr.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\socket.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\stat.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\stats.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\stdio.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\stdlib.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\stdtime.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\strerror.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\string.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\symtab.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\syslog.h +# End Source File +# Begin Source File + +SOURCE=.\syslog.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\task.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\taskpool.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\thread.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\time.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\timer.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\tm.h +# End Source File +# Begin Source File + +SOURCE=.\include\isc\win32os.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\types.h +# End Source File +# Begin Source File + +SOURCE=.\unistd.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\util.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\versions.h +# End Source File +# Begin Source File + +SOURCE=..\include\isc\xml.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Group "Main Isc Lib" + +# PROP Default_Filter "c" +@IF AES +# Begin Source File + +SOURCE=..\aes.c +# End Source File +@END AES +# Begin Source File + +SOURCE=..\assertions.c +# End Source File +# Begin Source File + +SOURCE=..\backtrace.c +# End Source File +# Begin Source File + +SOURCE=..\backtrace-emptytbl.c +# End Source File +# Begin Source File + +SOURCE=..\base32.c +# End Source File +# Begin Source File + +SOURCE=..\base64.c +# End Source File +# Begin Source File + +SOURCE=..\bind9.c +# End Source File +# Begin Source File + +SOURCE=..\buffer.c +# End Source File +# Begin Source File + +SOURCE=..\bufferlist.c +# End Source File +# Begin Source File + +SOURCE=..\commandline.c +# End Source File +# Begin Source File + +SOURCE=..\counter.c +# End Source File +# Begin Source File + +SOURCE=..\crc64.c +# End Source File +# Begin Source File + +SOURCE=..\error.c +# End Source File +# Begin Source File + +SOURCE=..\event.c +# End Source File +# Begin Source File + +SOURCE=..\hash.c +# End Source File +# Begin Source File + +SOURCE=..\heap.c +# End Source File +# Begin Source File + +SOURCE=..\hex.c +# End Source File +# Begin Source File + +SOURCE=..\hmacmd5.c +# End Source File +# Begin Source File + +SOURCE=..\hmacsha.c +# End Source File +# Begin Source File + +SOURCE=..\ht.c +# End Source File +# Begin Source File + +SOURCE=..\httpd.c +# End Source File +# Begin Source File + +SOURCE=..\inet_aton.c +# End Source File +# Begin Source File + +SOURCE=..\inet_ntop.c +# End Source File +# Begin Source File + +SOURCE=..\inet_pton.c +# End Source File +# Begin Source File + +SOURCE=..\iterated_hash.c +# End Source File +# Begin Source File + +SOURCE=..\lex.c +# End Source File +# Begin Source File + +SOURCE=..\lfsr.c +# End Source File +# Begin Source File + +SOURCE=..\lib.c +# End Source File +# Begin Source File + +SOURCE=..\log.c +# End Source File +# Begin Source File + +SOURCE=..\md5.c +# End Source File +# Begin Source File + +SOURCE=..\mem.c +# End Source File +# Begin Source File + +SOURCE=..\nls\msgcat.c +# End Source File +# Begin Source File + +SOURCE=..\mutexblock.c +# End Source File +# Begin Source File + +SOURCE=..\netaddr.c +# End Source File +# Begin Source File + +SOURCE=..\netscope.c +# End Source File +# Begin Source File + +SOURCE=..\ondestroy.c +# End Source File +# Begin Source File + +SOURCE=..\parseint.c +# End Source File +@IF PKCS11 +# Begin Source File + +SOURCE=..\pk11.c +# End Source File +# Begin Source File + +SOURCE=..\pk11_result.c +# End Source File +@END PKCS11 +# Begin Source File + +SOURCE=..\pool.c +# End Source File +# Begin Source File + +SOURCE=..\portset.c +# End Source File +# Begin Source File + +SOURCE=..\quota.c +# End Source File +# Begin Source File + +SOURCE=..\radix.c +# End Source File +# Begin Source File + +SOURCE=..\random.c +# End Source File +# Begin Source File + +SOURCE=..\ratelimiter.c +# End Source File +# Begin Source File + +SOURCE=..\refcount.c +# End Source File +# Begin Source File + +SOURCE=..\regex.c +# End Source File +# Begin Source File + +SOURCE=..\region.c +# End Source File +# Begin Source File + +SOURCE=..\result.c +# End Source File +# Begin Source File + +SOURCE=..\rwlock.c +# End Source File +# Begin Source File + +SOURCE=..\safe.c +# End Source File +# Begin Source File + +SOURCE=..\serial.c +# End Source File +# Begin Source File + +SOURCE=..\sha1.c +# End Source File +# Begin Source File + +SOURCE=..\sha2.c +# End Source File +# Begin Source File + +SOURCE=..\sockaddr.c +# End Source File +# Begin Source File + +SOURCE=..\stats.c +# End Source File +# Begin Source File + +SOURCE=..\string.c +# End Source File +# Begin Source File + +SOURCE=..\symtab.c +# End Source File +# Begin Source File + +SOURCE=..\task.c +# End Source File +# Begin Source File + +SOURCE=..\taskpool.c +# End Source File +# Begin Source File + +SOURCE=..\timer.c +# End Source File +# Begin Source File + +SOURCE=..\tm.c +# End Source File +# End Group +@IF ATOMIC +# Begin Source File + +SOURCE=.\include\atomic.h +# End Source File +@ELSE ATOMIC +# Begin Source File + +SOURCE=..\noatomic\include\atomic.h +# End Source File +@END ATOMIC +# Begin Source File + +SOURCE=.\libisc.def +# End Source File +# End Target +# End Project diff --git a/lib/isc/win32/libisc.dsw b/lib/isc/win32/libisc.dsw new file mode 100644 index 0000000..49c089c --- /dev/null +++ b/lib/isc/win32/libisc.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "libisc"=".\libisc.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/lib/isc/win32/libisc.mak.in b/lib/isc/win32/libisc.mak.in new file mode 100644 index 0000000..9a6acd5 --- /dev/null +++ b/lib/isc/win32/libisc.mak.in @@ -0,0 +1,2398 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on libisc.dsp +!IF "$(CFG)" == "" +CFG=libisc - @PLATFORM@ Debug +!MESSAGE No configuration specified. Defaulting to libisc - @PLATFORM@ Debug. +!ENDIF + +!IF "$(CFG)" != "libisc - @PLATFORM@ Release" && "$(CFG)" != "libisc - @PLATFORM@ Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libisc.mak" CFG="libisc - @PLATFORM@ Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libisc - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Dynamic-Link Library") +!MESSAGE "libisc - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe +LIBXML=@LIBXML2_LIB@ + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" +_VC_MANIFEST_INC=0 +_VC_MANIFEST_BASENAME=__VC80 +!ELSE +_VC_MANIFEST_INC=1 +_VC_MANIFEST_BASENAME=__VC80.Debug +!ENDIF + +#################################################### +# Specifying name of temporary resource file used only in incremental builds: + +!if "$(_VC_MANIFEST_INC)" == "1" +_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res +!else +_VC_MANIFEST_AUTO_RES= +!endif + +#################################################### +# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: + +!if "$(_VC_MANIFEST_INC)" == "1" + +#MT_SPECIAL_RETURN=1090650113 +#MT_SPECIAL_SWITCH=-notify_resource_update +MT_SPECIAL_RETURN=0 +MT_SPECIAL_SWITCH= +_VC_MANIFEST_EMBED_EXE= \ +if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ +if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ +rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ +link $** /out:$@ $(LFLAGS) + +!else + +_VC_MANIFEST_EMBED_EXE= \ +if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 + +!endif + +#################################################### +# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: + +!if "$(_VC_MANIFEST_INC)" == "1" + +#MT_SPECIAL_RETURN=1090650113 +#MT_SPECIAL_SWITCH=-notify_resource_update +MT_SPECIAL_RETURN=0 +MT_SPECIAL_SWITCH= +_VC_MANIFEST_EMBED_EXE= \ +if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ +if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ +rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ +link $** /out:$@ $(LFLAGS) + +!else + +_VC_MANIFEST_EMBED_EXE= \ +if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 + +!endif +#################################################### +# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: + +!if "$(_VC_MANIFEST_INC)" == "1" + +_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ + $(_VC_MANIFEST_BASENAME).auto.rc \ + $(_VC_MANIFEST_BASENAME).auto.manifest + +!else + +_VC_MANIFEST_CLEAN= + +!endif + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + +OUTDIR=.\Release +INTDIR=.\Release + +ALL : "..\..\..\Build\Release\libisc.dll" + + +CLEAN : +@IF AES + -@erase "$(INTDIR)\aes.obj" +@END AES + -@erase "$(INTDIR)\app.obj" + -@erase "$(INTDIR)\assertions.obj" + -@erase "$(INTDIR)\backtrace.obj" + -@erase "$(INTDIR)\backtrace-emptytbl.obj" + -@erase "$(INTDIR)\base32.obj" + -@erase "$(INTDIR)\base64.obj" + -@erase "$(INTDIR)\bind9.obj" + -@erase "$(INTDIR)\buffer.obj" + -@erase "$(INTDIR)\bufferlist.obj" + -@erase "$(INTDIR)\commandline.obj" + -@erase "$(INTDIR)\counter.obj" + -@erase "$(INTDIR)\condition.obj" + -@erase "$(INTDIR)\crc64.obj" + -@erase "$(INTDIR)\dir.obj" + -@erase "$(INTDIR)\DLLMain.obj" + -@erase "$(INTDIR)\entropy.obj" + -@erase "$(INTDIR)\errno.obj" + -@erase "$(INTDIR)\errno2result.obj" + -@erase "$(INTDIR)\error.obj" + -@erase "$(INTDIR)\event.obj" + -@erase "$(INTDIR)\file.obj" + -@erase "$(INTDIR)\fsaccess.obj" + -@erase "$(INTDIR)\hash.obj" + -@erase "$(INTDIR)\heap.obj" + -@erase "$(INTDIR)\hex.obj" + -@erase "$(INTDIR)\hmacmd5.obj" + -@erase "$(INTDIR)\hmacsha.obj" + -@erase "$(INTDIR)\ht.obj" + -@erase "$(INTDIR)\httpd.obj" + -@erase "$(INTDIR)\inet_aton.obj" + -@erase "$(INTDIR)\inet_ntop.obj" + -@erase "$(INTDIR)\inet_pton.obj" + -@erase "$(INTDIR)\interfaceiter.obj" + -@erase "$(INTDIR)\ipv6.obj" + -@erase "$(INTDIR)\iterated_hash.obj" + -@erase "$(INTDIR)\keyboard.obj" + -@erase "$(INTDIR)\lex.obj" + -@erase "$(INTDIR)\lfsr.obj" + -@erase "$(INTDIR)\lib.obj" + -@erase "$(INTDIR)\log.obj" + -@erase "$(INTDIR)\md5.obj" + -@erase "$(INTDIR)\mem.obj" + -@erase "$(INTDIR)\msgcat.obj" + -@erase "$(INTDIR)\mutexblock.obj" + -@erase "$(INTDIR)\meminfo.obj" + -@erase "$(INTDIR)\net.obj" + -@erase "$(INTDIR)\netaddr.obj" + -@erase "$(INTDIR)\netscope.obj" + -@erase "$(INTDIR)\ntpaths.obj" + -@erase "$(INTDIR)\once.obj" + -@erase "$(INTDIR)\ondestroy.obj" + -@erase "$(INTDIR)\os.obj" + -@erase "$(INTDIR)\parseint.obj" +@IF PKCS11 + -@erase "$(INTDIR)\pk11.obj" + -@erase "$(INTDIR)\pk11_api.obj" + -@erase "$(INTDIR)\pk11_result.obj" +@END PKCS11 + -@erase "$(INTDIR)\pool.obj" + -@erase "$(INTDIR)\portset.obj" + -@erase "$(INTDIR)\quota.obj" + -@erase "$(INTDIR)\radix.obj" + -@erase "$(INTDIR)\random.obj" + -@erase "$(INTDIR)\ratelimiter.obj" + -@erase "$(INTDIR)\refcount.obj" + -@erase "$(INTDIR)\regex.obj" + -@erase "$(INTDIR)\region.obj" + -@erase "$(INTDIR)\resource.obj" + -@erase "$(INTDIR)\result.obj" + -@erase "$(INTDIR)\rwlock.obj" + -@erase "$(INTDIR)\safe.obj" + -@erase "$(INTDIR)\serial.obj" + -@erase "$(INTDIR)\sha1.obj" + -@erase "$(INTDIR)\sha2.obj" + -@erase "$(INTDIR)\sockaddr.obj" + -@erase "$(INTDIR)\socket.obj" + -@erase "$(INTDIR)\stats.obj" + -@erase "$(INTDIR)\stdio.obj" + -@erase "$(INTDIR)\stdtime.obj" + -@erase "$(INTDIR)\strerror.obj" + -@erase "$(INTDIR)\string.obj" + -@erase "$(INTDIR)\symtab.obj" + -@erase "$(INTDIR)\syslog.obj" + -@erase "$(INTDIR)\task.obj" + -@erase "$(INTDIR)\taskpool.obj" + -@erase "$(INTDIR)\thread.obj" + -@erase "$(INTDIR)\time.obj" + -@erase "$(INTDIR)\timer.obj" + -@erase "$(INTDIR)\tm.obj" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\version.obj" + -@erase "$(INTDIR)\win32os.obj" + -@erase "$(OUTDIR)\libisc.exp" + -@erase "$(OUTDIR)\libisc.lib" + -@erase "..\..\..\Build\Release\libisc.dll" + -@$(_VC_MANIFEST_CLEAN) + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +@IF PKCS11 +CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "win32" /I "../../isccfg/include" /I "../../dns/win32/include" /I "../../dns/include" @LIBXML2_INC@ @OPENSSL_INC@ @ZLIB_INC@ /D "BIND9" @CRYPTO@ @PK11_LIB_LOCATION@ /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /Fp"$(INTDIR)\libisc.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +@ELSE PKCS11 +CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "win32" /I "../../isccfg/include" @LIBXML2_INC@ @OPENSSL_INC@ @ZLIB_INC@ /D "BIND9" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /Fp"$(INTDIR)\libisc.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +@END PKCS11 +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\libisc.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib $(LIBXML) @OPENSSL_LIB@ @ZLIB_LIB@ /nologo /dll /incremental:no /pdb:"$(OUTDIR)\libisc.pdb" @MACHINE@ /def:".\libisc.def" /out:"../../../Build/Release/libisc.dll" /implib:"$(OUTDIR)\libisc.lib" +DEF_FILE= \ + ".\libisc.def" +LINK32_OBJS= \ + "$(INTDIR)\app.obj" \ + "$(INTDIR)\condition.obj" \ + "$(INTDIR)\dir.obj" \ + "$(INTDIR)\DLLMain.obj" \ + "$(INTDIR)\entropy.obj" \ + "$(INTDIR)\errno.obj" \ + "$(INTDIR)\errno2result.obj" \ + "$(INTDIR)\file.obj" \ + "$(INTDIR)\fsaccess.obj" \ + "$(INTDIR)\interfaceiter.obj" \ + "$(INTDIR)\ipv6.obj" \ + "$(INTDIR)\iterated_hash.obj" \ + "$(INTDIR)\keyboard.obj" \ + "$(INTDIR)\meminfo.obj" \ + "$(INTDIR)\net.obj" \ + "$(INTDIR)\ntpaths.obj" \ + "$(INTDIR)\once.obj" \ + "$(INTDIR)\os.obj" \ +@IF PKCS11 + "$(INTDIR)\pk11_api.obj" \ +@END PKCS11 + "$(INTDIR)\resource.obj" \ + "$(INTDIR)\socket.obj" \ + "$(INTDIR)\stdio.obj" \ + "$(INTDIR)\stdtime.obj" \ + "$(INTDIR)\strerror.obj" \ + "$(INTDIR)\syslog.obj" \ + "$(INTDIR)\thread.obj" \ + "$(INTDIR)\time.obj" \ + "$(INTDIR)\version.obj" \ + "$(INTDIR)\win32os.obj" \ +@IF AES + "$(INTDIR)\aes.obj" \ +@END AES + "$(INTDIR)\assertions.obj" \ + "$(INTDIR)\backtrace.obj" \ + "$(INTDIR)\backtrace-emptytbl.obj" \ + "$(INTDIR)\base32.obj" \ + "$(INTDIR)\base64.obj" \ + "$(INTDIR)\bind9.obj" \ + "$(INTDIR)\buffer.obj" \ + "$(INTDIR)\bufferlist.obj" \ + "$(INTDIR)\commandline.obj" \ + "$(INTDIR)\counter.obj" \ + "$(INTDIR)\crc64.obj" \ + "$(INTDIR)\error.obj" \ + "$(INTDIR)\event.obj" \ + "$(INTDIR)\hash.obj" \ + "$(INTDIR)\heap.obj" \ + "$(INTDIR)\hex.obj" \ + "$(INTDIR)\hmacmd5.obj" \ + "$(INTDIR)\hmacsha.obj" \ + "$(INTDIR)\ht.obj" \ + "$(INTDIR)\httpd.obj" \ + "$(INTDIR)\inet_aton.obj" \ + "$(INTDIR)\inet_ntop.obj" \ + "$(INTDIR)\inet_pton.obj" \ + "$(INTDIR)\lex.obj" \ + "$(INTDIR)\lfsr.obj" \ + "$(INTDIR)\lib.obj" \ + "$(INTDIR)\log.obj" \ + "$(INTDIR)\md5.obj" \ + "$(INTDIR)\mem.obj" \ + "$(INTDIR)\msgcat.obj" \ + "$(INTDIR)\mutexblock.obj" \ + "$(INTDIR)\netaddr.obj" \ + "$(INTDIR)\netscope.obj" \ + "$(INTDIR)\ondestroy.obj" \ +@IF PKCS11 + "$(INTDIR)\pk11.obj" \ + "$(INTDIR)\pk11_result.obj" \ +@END PKCS11 + "$(INTDIR)\quota.obj" \ + "$(INTDIR)\radix.obj" \ + "$(INTDIR)\random.obj" \ + "$(INTDIR)\ratelimiter.obj" \ + "$(INTDIR)\refcount.obj" \ + "$(INTDIR)\result.obj" \ + "$(INTDIR)\rwlock.obj" \ + "$(INTDIR)\safe.obj" \ + "$(INTDIR)\serial.obj" \ + "$(INTDIR)\sha1.obj" \ + "$(INTDIR)\sha2.obj" \ + "$(INTDIR)\sockaddr.obj" \ + "$(INTDIR)\stats.obj" \ + "$(INTDIR)\string.obj" \ + "$(INTDIR)\symtab.obj" \ + "$(INTDIR)\task.obj" \ + "$(INTDIR)\taskpool.obj" \ + "$(INTDIR)\timer.obj" \ + "$(INTDIR)\tm.obj" \ + "$(INTDIR)\parseint.obj" \ + "$(INTDIR)\pool.obj" \ + "$(INTDIR)\portset.obj" \ + "$(INTDIR)\regex.obj" \ + "$(INTDIR)\region.obj" + +"..\..\..\Build\Release\libisc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + $(_VC_MANIFEST_EMBED_DLL) + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +ALL : "..\..\..\Build\Debug\libisc.dll" "$(OUTDIR)\libisc.bsc" + + +CLEAN : +@IF AES + -@erase "$(INTDIR)\aes.obj" + -@erase "$(INTDIR)\aes.sbr" +@END AES + -@erase "$(INTDIR)\app.obj" + -@erase "$(INTDIR)\app.sbr" + -@erase "$(INTDIR)\assertions.obj" + -@erase "$(INTDIR)\assertions.sbr" + -@erase "$(INTDIR)\backtrace.obj" + -@erase "$(INTDIR)\backtrace-emptytbl.obj" + -@erase "$(INTDIR)\backtrace.sbr" + -@erase "$(INTDIR)\backtrace-emptytbl.sbr" + -@erase "$(INTDIR)\base32.obj" + -@erase "$(INTDIR)\base32.sbr" + -@erase "$(INTDIR)\base64.obj" + -@erase "$(INTDIR)\base64.sbr" + -@erase "$(INTDIR)\bind9.obj" + -@erase "$(INTDIR)\bind9.sbr" + -@erase "$(INTDIR)\buffer.obj" + -@erase "$(INTDIR)\buffer.sbr" + -@erase "$(INTDIR)\bufferlist.obj" + -@erase "$(INTDIR)\bufferlist.sbr" + -@erase "$(INTDIR)\commandline.obj" + -@erase "$(INTDIR)\commandline.sbr" + -@erase "$(INTDIR)\counter.obj" + -@erase "$(INTDIR)\counter.sbr" + -@erase "$(INTDIR)\condition.obj" + -@erase "$(INTDIR)\condition.sbr" + -@erase "$(INTDIR)\crc64.obj" + -@erase "$(INTDIR)\crc64.sbr" + -@erase "$(INTDIR)\dir.obj" + -@erase "$(INTDIR)\dir.sbr" + -@erase "$(INTDIR)\DLLMain.obj" + -@erase "$(INTDIR)\DLLMain.sbr" + -@erase "$(INTDIR)\entropy.obj" + -@erase "$(INTDIR)\entropy.sbr" + -@erase "$(INTDIR)\errno.obj" + -@erase "$(INTDIR)\errno.sbr" + -@erase "$(INTDIR)\errno2result.obj" + -@erase "$(INTDIR)\errno2result.sbr" + -@erase "$(INTDIR)\error.obj" + -@erase "$(INTDIR)\error.sbr" + -@erase "$(INTDIR)\event.obj" + -@erase "$(INTDIR)\event.sbr" + -@erase "$(INTDIR)\file.obj" + -@erase "$(INTDIR)\file.sbr" + -@erase "$(INTDIR)\fsaccess.obj" + -@erase "$(INTDIR)\fsaccess.sbr" + -@erase "$(INTDIR)\hash.obj" + -@erase "$(INTDIR)\hash.sbr" + -@erase "$(INTDIR)\heap.obj" + -@erase "$(INTDIR)\heap.sbr" + -@erase "$(INTDIR)\hex.obj" + -@erase "$(INTDIR)\hex.sbr" + -@erase "$(INTDIR)\hmacmd5.obj" + -@erase "$(INTDIR)\hmacmd5.sbr" + -@erase "$(INTDIR)\hmacsha.obj" + -@erase "$(INTDIR)\hmacsha.sbr" + -@erase "$(INTDIR)\ht.obj" + -@erase "$(INTDIR)\ht.sbr" + -@erase "$(INTDIR)\httpd.obj" + -@erase "$(INTDIR)\httpd.sbr" + -@erase "$(INTDIR)\inet_aton.obj" + -@erase "$(INTDIR)\inet_aton.sbr" + -@erase "$(INTDIR)\inet_ntop.obj" + -@erase "$(INTDIR)\inet_ntop.sbr" + -@erase "$(INTDIR)\inet_pton.obj" + -@erase "$(INTDIR)\inet_pton.sbr" + -@erase "$(INTDIR)\interfaceiter.obj" + -@erase "$(INTDIR)\interfaceiter.sbr" + -@erase "$(INTDIR)\ipv6.obj" + -@erase "$(INTDIR)\ipv6.sbr" + -@erase "$(INTDIR)\iterated_hash.obj" + -@erase "$(INTDIR)\iterated_hash.sbr" + -@erase "$(INTDIR)\keyboard.obj" + -@erase "$(INTDIR)\keyboard.sbr" + -@erase "$(INTDIR)\lex.obj" + -@erase "$(INTDIR)\lex.sbr" + -@erase "$(INTDIR)\lfsr.obj" + -@erase "$(INTDIR)\lfsr.sbr" + -@erase "$(INTDIR)\lib.obj" + -@erase "$(INTDIR)\lib.sbr" + -@erase "$(INTDIR)\log.obj" + -@erase "$(INTDIR)\log.sbr" + -@erase "$(INTDIR)\md5.obj" + -@erase "$(INTDIR)\md5.sbr" + -@erase "$(INTDIR)\mem.obj" + -@erase "$(INTDIR)\mem.sbr" + -@erase "$(INTDIR)\msgcat.obj" + -@erase "$(INTDIR)\msgcat.sbr" + -@erase "$(INTDIR)\mutexblock.obj" + -@erase "$(INTDIR)\mutexblock.sbr" + -@erase "$(INTDIR)\meminfo.obj" + -@erase "$(INTDIR)\meminfo.sbr" + -@erase "$(INTDIR)\net.obj" + -@erase "$(INTDIR)\net.sbr" + -@erase "$(INTDIR)\netaddr.obj" + -@erase "$(INTDIR)\netaddr.sbr" + -@erase "$(INTDIR)\netscope.obj" + -@erase "$(INTDIR)\netscope.sbr" + -@erase "$(INTDIR)\ntpaths.obj" + -@erase "$(INTDIR)\ntpaths.sbr" + -@erase "$(INTDIR)\once.obj" + -@erase "$(INTDIR)\once.sbr" + -@erase "$(INTDIR)\ondestroy.obj" + -@erase "$(INTDIR)\ondestroy.sbr" + -@erase "$(INTDIR)\os.obj" + -@erase "$(INTDIR)\os.sbr" + -@erase "$(INTDIR)\parseint.obj" + -@erase "$(INTDIR)\parseint.sbr" +@IF PKCS11 + -@erase "$(INTDIR)\pk11.obj" + -@erase "$(INTDIR)\pk11_api.obj" + -@erase "$(INTDIR)\pk11_result.obj" +@END PKCS11 + -@erase "$(INTDIR)\pool.obj" + -@erase "$(INTDIR)\pool.sbr" + -@erase "$(INTDIR)\portset.obj" + -@erase "$(INTDIR)\portset.sbr" + -@erase "$(INTDIR)\quota.obj" + -@erase "$(INTDIR)\quota.sbr" + -@erase "$(INTDIR)\radix.obj" + -@erase "$(INTDIR)\radix.sbr" + -@erase "$(INTDIR)\random.obj" + -@erase "$(INTDIR)\random.sbr" + -@erase "$(INTDIR)\ratelimiter.obj" + -@erase "$(INTDIR)\ratelimiter.sbr" + -@erase "$(INTDIR)\refcount.obj" + -@erase "$(INTDIR)\refcount.sbr" + -@erase "$(INTDIR)\regex.obj" + -@erase "$(INTDIR)\regex.sbr" + -@erase "$(INTDIR)\region.obj" + -@erase "$(INTDIR)\region.sbr" + -@erase "$(INTDIR)\resource.obj" + -@erase "$(INTDIR)\resource.sbr" + -@erase "$(INTDIR)\result.obj" + -@erase "$(INTDIR)\result.sbr" + -@erase "$(INTDIR)\rwlock.obj" + -@erase "$(INTDIR)\rwlock.sbr" + -@erase "$(INTDIR)\safe.obj" + -@erase "$(INTDIR)\safe.sbr" + -@erase "$(INTDIR)\serial.obj" + -@erase "$(INTDIR)\serial.sbr" + -@erase "$(INTDIR)\sha1.obj" + -@erase "$(INTDIR)\sha1.sbr" + -@erase "$(INTDIR)\sha2.obj" + -@erase "$(INTDIR)\sha2.sbr" + -@erase "$(INTDIR)\sockaddr.obj" + -@erase "$(INTDIR)\sockaddr.sbr" + -@erase "$(INTDIR)\socket.obj" + -@erase "$(INTDIR)\socket.sbr" + -@erase "$(INTDIR)\stats.obj" + -@erase "$(INTDIR)\stats.sbr" + -@erase "$(INTDIR)\stdio.obj" + -@erase "$(INTDIR)\stdio.sbr" + -@erase "$(INTDIR)\stdtime.obj" + -@erase "$(INTDIR)\stdtime.sbr" + -@erase "$(INTDIR)\strerror.obj" + -@erase "$(INTDIR)\strerror.sbr" + -@erase "$(INTDIR)\string.obj" + -@erase "$(INTDIR)\string.sbr" + -@erase "$(INTDIR)\symtab.obj" + -@erase "$(INTDIR)\symtab.sbr" + -@erase "$(INTDIR)\syslog.obj" + -@erase "$(INTDIR)\syslog.sbr" + -@erase "$(INTDIR)\task.obj" + -@erase "$(INTDIR)\task.sbr" + -@erase "$(INTDIR)\taskpool.obj" + -@erase "$(INTDIR)\taskpool.sbr" + -@erase "$(INTDIR)\thread.obj" + -@erase "$(INTDIR)\thread.sbr" + -@erase "$(INTDIR)\time.obj" + -@erase "$(INTDIR)\time.sbr" + -@erase "$(INTDIR)\timer.obj" + -@erase "$(INTDIR)\timer.sbr" + -@erase "$(INTDIR)\tm.obj" + -@erase "$(INTDIR)\tm.sbr" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\vc60.pdb" + -@erase "$(INTDIR)\version.obj" + -@erase "$(INTDIR)\version.sbr" + -@erase "$(INTDIR)\win32os.obj" + -@erase "$(INTDIR)\win32os.sbr" + -@erase "$(OUTDIR)\libisc.bsc" + -@erase "$(OUTDIR)\libisc.exp" + -@erase "$(OUTDIR)\libisc.lib" + -@erase "$(OUTDIR)\libisc.map" + -@erase "$(OUTDIR)\libisc.pdb" + -@erase "..\..\..\Build\Debug\libisc.dll" + -@erase "..\..\..\Build\Debug\libisc.ilk" + -@$(_VC_MANIFEST_CLEAN) + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +@IF PKCS11 +CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "win32" /I "../../isccfg/include" /I "../../dns/win32/include" /I "../../dns/include" @LIBXML2_INC@ @OPENSSL_INC@ @ZLIB_INC@ /D "BIND9" @CRYPTO@ @PK11_LIB_LOCATION@ /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\libisc.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c +@ELSE PKCS11 +CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "win32" /I "../../isccfg/include" @LIBXML2_INC@ @OPENSSL_INC@ @ZLIB_INC@ /D "BIND9" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\libisc.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c +@END PKCS11 +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\libisc.bsc" +BSC32_SBRS= \ + "$(INTDIR)\app.sbr" \ + "$(INTDIR)\condition.sbr" \ + "$(INTDIR)\dir.sbr" \ + "$(INTDIR)\DLLMain.sbr" \ + "$(INTDIR)\entropy.sbr" \ + "$(INTDIR)\errno.sbr" \ + "$(INTDIR)\errno2result.sbr" \ + "$(INTDIR)\file.sbr" \ + "$(INTDIR)\fsaccess.sbr" \ + "$(INTDIR)\interfaceiter.sbr" \ + "$(INTDIR)\ipv6.sbr" \ + "$(INTDIR)\iterated_hash.sbr" \ + "$(INTDIR)\keyboard.sbr" \ + "$(INTDIR)\meminfo.sbr" \ + "$(INTDIR)\net.sbr" \ + "$(INTDIR)\ntpaths.sbr" \ + "$(INTDIR)\once.sbr" \ + "$(INTDIR)\os.sbr" \ +@IF PKCS11 + "$(INTDIR)\pk11_api.sbr" \ +@END PKCS11 + "$(INTDIR)\resource.sbr" \ + "$(INTDIR)\socket.sbr" \ + "$(INTDIR)\stdio.sbr" \ + "$(INTDIR)\stdtime.sbr" \ + "$(INTDIR)\strerror.sbr" \ + "$(INTDIR)\syslog.sbr" \ + "$(INTDIR)\thread.sbr" \ + "$(INTDIR)\time.sbr" \ + "$(INTDIR)\version.sbr" \ + "$(INTDIR)\win32os.sbr" \ +@IF AES + "$(INTDIR)\aes.sbr" \ +@END AES + "$(INTDIR)\assertions.sbr" \ + "$(INTDIR)\backtrace.sbr" \ + "$(INTDIR)\backtrace-emptytbl.sbr" \ + "$(INTDIR)\base32.sbr" \ + "$(INTDIR)\base64.sbr" \ + "$(INTDIR)\bind9.sbr" \ + "$(INTDIR)\buffer.sbr" \ + "$(INTDIR)\bufferlist.sbr" \ + "$(INTDIR)\commandline.sbr" \ + "$(INTDIR)\counter.sbr" \ + "$(INTDIR)\crc64.sbr" \ + "$(INTDIR)\error.sbr" \ + "$(INTDIR)\event.sbr" \ + "$(INTDIR)\hash.sbr" \ + "$(INTDIR)\heap.sbr" \ + "$(INTDIR)\hex.sbr" \ + "$(INTDIR)\hmacmd5.sbr" \ + "$(INTDIR)\hmacsha.sbr" \ + "$(INTDIR)\ht.sbr" \ + "$(INTDIR)\httpd.sbr" \ + "$(INTDIR)\inet_aton.sbr" \ + "$(INTDIR)\inet_ntop.sbr" \ + "$(INTDIR)\inet_pton.sbr" \ + "$(INTDIR)\lex.sbr" \ + "$(INTDIR)\lfsr.sbr" \ + "$(INTDIR)\lib.sbr" \ + "$(INTDIR)\log.sbr" \ + "$(INTDIR)\md5.sbr" \ + "$(INTDIR)\mem.sbr" \ + "$(INTDIR)\msgcat.sbr" \ + "$(INTDIR)\mutexblock.sbr" \ + "$(INTDIR)\netaddr.sbr" \ + "$(INTDIR)\netscope.sbr" \ + "$(INTDIR)\ondestroy.sbr" \ +@IF PKCS11 + "$(INTDIR)\pk11.sbr" \ + "$(INTDIR)\pk11_result.sbr" \ +@END PKCS11 + "$(INTDIR)\quota.sbr" \ + "$(INTDIR)\radix.sbr" \ + "$(INTDIR)\random.sbr" \ + "$(INTDIR)\ratelimiter.sbr" \ + "$(INTDIR)\refcount.sbr" \ + "$(INTDIR)\result.sbr" \ + "$(INTDIR)\rwlock.sbr" \ + "$(INTDIR)\safe.sbr" \ + "$(INTDIR)\serial.sbr" \ + "$(INTDIR)\sha1.sbr" \ + "$(INTDIR)\sha2.sbr" \ + "$(INTDIR)\sockaddr.sbr" \ + "$(INTDIR)\stats.sbr" \ + "$(INTDIR)\string.sbr" \ + "$(INTDIR)\symtab.sbr" \ + "$(INTDIR)\task.sbr" \ + "$(INTDIR)\taskpool.sbr" \ + "$(INTDIR)\timer.sbr" \ + "$(INTDIR)\tm.sbr" \ + "$(INTDIR)\parseint.sbr" \ + "$(INTDIR)\pool.sbr" \ + "$(INTDIR)\portset.sbr" \ + "$(INTDIR)\regex.sbr" \ + "$(INTDIR)\region.sbr" + +"$(OUTDIR)\libisc.bsc" : "$(OUTDIR)" $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib $(LIBXML) @OPENSSL_LIB@ @ZLIB_LIB@ /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\libisc.pdb" /map:"$(INTDIR)\libisc.map" /debug @MACHINE@ /def:".\libisc.def" /out:"../../../Build/Debug/libisc.dll" /implib:"$(OUTDIR)\libisc.lib" /pdbtype:sept +DEF_FILE= \ + ".\libisc.def" +LINK32_OBJS= \ + "$(INTDIR)\app.obj" \ + "$(INTDIR)\condition.obj" \ + "$(INTDIR)\dir.obj" \ + "$(INTDIR)\DLLMain.obj" \ + "$(INTDIR)\entropy.obj" \ + "$(INTDIR)\errno.obj" \ + "$(INTDIR)\errno2result.obj" \ + "$(INTDIR)\file.obj" \ + "$(INTDIR)\fsaccess.obj" \ + "$(INTDIR)\interfaceiter.obj" \ + "$(INTDIR)\ipv6.obj" \ + "$(INTDIR)\iterated_hash.obj" \ + "$(INTDIR)\keyboard.obj" \ + "$(INTDIR)\meminfo.obj" \ + "$(INTDIR)\net.obj" \ + "$(INTDIR)\ntpaths.obj" \ + "$(INTDIR)\once.obj" \ + "$(INTDIR)\os.obj" \ +@IF PKCS11 + "$(INTDIR)\pk11_api.obj" \ +@END PKCS11 + "$(INTDIR)\resource.obj" \ + "$(INTDIR)\socket.obj" \ + "$(INTDIR)\stdio.obj" \ + "$(INTDIR)\stdtime.obj" \ + "$(INTDIR)\strerror.obj" \ + "$(INTDIR)\syslog.obj" \ + "$(INTDIR)\thread.obj" \ + "$(INTDIR)\time.obj" \ + "$(INTDIR)\version.obj" \ + "$(INTDIR)\win32os.obj" \ +@IF AES + "$(INTDIR)\aes.obj" \ +@END AES + "$(INTDIR)\assertions.obj" \ + "$(INTDIR)\backtrace.obj" \ + "$(INTDIR)\backtrace-emptytbl.obj" \ + "$(INTDIR)\base32.obj" \ + "$(INTDIR)\base64.obj" \ + "$(INTDIR)\bind9.obj" \ + "$(INTDIR)\buffer.obj" \ + "$(INTDIR)\bufferlist.obj" \ + "$(INTDIR)\commandline.obj" \ + "$(INTDIR)\counter.obj" \ + "$(INTDIR)\crc64.obj" \ + "$(INTDIR)\error.obj" \ + "$(INTDIR)\event.obj" \ + "$(INTDIR)\hash.obj" \ + "$(INTDIR)\heap.obj" \ + "$(INTDIR)\hex.obj" \ + "$(INTDIR)\hmacmd5.obj" \ + "$(INTDIR)\hmacsha.obj" \ + "$(INTDIR)\ht.obj" \ + "$(INTDIR)\httpd.obj" \ + "$(INTDIR)\inet_aton.obj" \ + "$(INTDIR)\inet_ntop.obj" \ + "$(INTDIR)\inet_pton.obj" \ + "$(INTDIR)\lex.obj" \ + "$(INTDIR)\lfsr.obj" \ + "$(INTDIR)\lib.obj" \ + "$(INTDIR)\log.obj" \ + "$(INTDIR)\md5.obj" \ + "$(INTDIR)\mem.obj" \ + "$(INTDIR)\msgcat.obj" \ + "$(INTDIR)\mutexblock.obj" \ + "$(INTDIR)\netaddr.obj" \ + "$(INTDIR)\netscope.obj" \ + "$(INTDIR)\ondestroy.obj" \ +@IF PKCS11 + "$(INTDIR)\pk11.obj" \ + "$(INTDIR)\pk11_result.obj" \ +@END PKCS11 + "$(INTDIR)\quota.obj" \ + "$(INTDIR)\radix.obj" \ + "$(INTDIR)\random.obj" \ + "$(INTDIR)\ratelimiter.obj" \ + "$(INTDIR)\refcount.obj" \ + "$(INTDIR)\result.obj" \ + "$(INTDIR)\rwlock.obj" \ + "$(INTDIR)\safe.obj" \ + "$(INTDIR)\serial.obj" \ + "$(INTDIR)\sha1.obj" \ + "$(INTDIR)\sha2.obj" \ + "$(INTDIR)\sockaddr.obj" \ + "$(INTDIR)\stats.obj" \ + "$(INTDIR)\string.obj" \ + "$(INTDIR)\symtab.obj" \ + "$(INTDIR)\task.obj" \ + "$(INTDIR)\taskpool.obj" \ + "$(INTDIR)\timer.obj" \ + "$(INTDIR)\tm.obj" \ + "$(INTDIR)\parseint.obj" \ + "$(INTDIR)\pool.obj" \ + "$(INTDIR)\portset.obj" \ + "$(INTDIR)\regex.obj" \ + "$(INTDIR)\region.obj" + +"..\..\..\Build\Debug\libisc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + $(_VC_MANIFEST_EMBED_DLL) + +!ENDIF + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("libisc.dep") +!INCLUDE "libisc.dep" +!ELSE +!MESSAGE Warning: cannot find "libisc.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" || "$(CFG)" == "libisc - @PLATFORM@ Debug" +SOURCE=.\app.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\app.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\app.obj" "$(INTDIR)\app.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\condition.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\condition.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\condition.obj" "$(INTDIR)\condition.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\dir.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\dir.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\dir.obj" "$(INTDIR)\dir.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\DLLMain.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\DLLMain.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\DLLMain.obj" "$(INTDIR)\DLLMain.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\entropy.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\entropy.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\entropy.obj" "$(INTDIR)\entropy.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\errno.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\errno.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\errno.obj" "$(INTDIR)\errno.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + + +SOURCE=.\errno2result.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\errno2result.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\errno2result.obj" "$(INTDIR)\errno2result.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\file.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\file.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\file.obj" "$(INTDIR)\file.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\fsaccess.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\fsaccess.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\fsaccess.obj" "$(INTDIR)\fsaccess.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\interfaceiter.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\interfaceiter.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\interfaceiter.obj" "$(INTDIR)\interfaceiter.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\ipv6.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\ipv6.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\ipv6.obj" "$(INTDIR)\ipv6.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + + +SOURCE=.\keyboard.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\keyboard.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\keyboard.obj" "$(INTDIR)\keyboard.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\meminfo.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\meminfo.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\meminfo.obj" "$(INTDIR)\meminfo.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\net.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\net.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\net.obj" "$(INTDIR)\net.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\ntpaths.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\ntpaths.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\ntpaths.obj" "$(INTDIR)\ntpaths.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\once.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\once.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\once.obj" "$(INTDIR)\once.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\os.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\os.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\os.obj" "$(INTDIR)\os.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\pk11_api.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\pk11_api.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\pk11_api.obj" "$(INTDIR)\pk11_api.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\resource.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\resource.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\resource.obj" "$(INTDIR)\resource.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\socket.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\socket.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\socket.obj" "$(INTDIR)\socket.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\stdio.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\stdio.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\stdio.obj" "$(INTDIR)\stdio.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\stdtime.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\stdtime.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\stdtime.obj" "$(INTDIR)\stdtime.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\strerror.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\strerror.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\strerror.obj" "$(INTDIR)\strerror.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\syslog.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\syslog.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\syslog.obj" "$(INTDIR)\syslog.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\thread.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\thread.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\thread.obj" "$(INTDIR)\thread.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\time.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\time.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\time.obj" "$(INTDIR)\time.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\version.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\version.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\version.obj" "$(INTDIR)\version.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\win32os.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\win32os.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\win32os.obj" "$(INTDIR)\win32os.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +@IF AES +SOURCE=..\aes.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\aes.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\aes.obj" "$(INTDIR)\aes.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF +@END AES + +SOURCE=..\assertions.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\assertions.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\assertions.obj" "$(INTDIR)\assertions.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\backtrace.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\backtrace.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\backtrace.obj" "$(INTDIR)\backtrace.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\backtrace-emptytbl.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\backtrace-emptytbl.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\backtrace-emptytbl.obj" "$(INTDIR)\backtrace-emptytbl.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\base32.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\base32.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\base32.obj" "$(INTDIR)\base32.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\base64.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\base64.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\base64.obj" "$(INTDIR)\base64.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\bind9.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\bind9.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\bind9.obj" "$(INTDIR)\bind9.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\buffer.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\buffer.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\buffer.obj" "$(INTDIR)\buffer.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\bufferlist.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\bufferlist.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\bufferlist.obj" "$(INTDIR)\bufferlist.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\commandline.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\commandline.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\commandline.obj" "$(INTDIR)\commandline.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\counter.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\counter.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\counter.obj" "$(INTDIR)\counter.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\crc64.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\crc64.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\crc64.obj" "$(INTDIR)\crc64.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\error.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\error.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\error.obj" "$(INTDIR)\error.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\event.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\event.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\event.obj" "$(INTDIR)\event.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\hash.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\hash.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\hash.obj" "$(INTDIR)\hash.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\heap.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\heap.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\heap.obj" "$(INTDIR)\heap.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\hex.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\hex.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\hex.obj" "$(INTDIR)\hex.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\hmacmd5.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\hmacmd5.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\hmacmd5.obj" "$(INTDIR)\hmacmd5.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\hmacsha.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\hmacsha.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\hmacsha.obj" "$(INTDIR)\hmacsha.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\ht.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\ht.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\ht.obj" "$(INTDIR)\ht.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\httpd.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\httpd.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\httpd.obj" "$(INTDIR)\httpd.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\inet_aton.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\inet_aton.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\inet_aton.obj" "$(INTDIR)\inet_aton.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\inet_ntop.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\inet_ntop.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\inet_ntop.obj" "$(INTDIR)\inet_ntop.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\inet_pton.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\inet_pton.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\inet_pton.obj" "$(INTDIR)\inet_pton.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\iterated_hash.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\iterated_hash.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\iterated_hash.obj" "$(INTDIR)\iterated_hash.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\lex.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\lex.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\lex.obj" "$(INTDIR)\lex.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\lfsr.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\lfsr.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\lfsr.obj" "$(INTDIR)\lfsr.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\lib.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\lib.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\lib.obj" "$(INTDIR)\lib.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\log.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\log.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\log.obj" "$(INTDIR)\log.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\md5.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\md5.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\md5.obj" "$(INTDIR)\md5.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\mem.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\mem.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\mem.obj" "$(INTDIR)\mem.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\nls\msgcat.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\msgcat.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\msgcat.obj" "$(INTDIR)\msgcat.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\mutexblock.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\mutexblock.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\mutexblock.obj" "$(INTDIR)\mutexblock.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\netaddr.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\netaddr.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\netaddr.obj" "$(INTDIR)\netaddr.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\netscope.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\netscope.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\netscope.obj" "$(INTDIR)\netscope.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\ondestroy.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\ondestroy.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\ondestroy.obj" "$(INTDIR)\ondestroy.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\parseint.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\parseint.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\parseint.obj" "$(INTDIR)\parseint.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\pk11.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\pk11.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\pk11.obj" "$(INTDIR)\pk11.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\pk11_result.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\pk11_result.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\pk11_result.obj" "$(INTDIR)\pk11_result.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\pool.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\pool.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\pool.obj" "$(INTDIR)\pool.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\portset.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\portset.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\portset.obj" "$(INTDIR)\portset.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\quota.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\quota.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\quota.obj" "$(INTDIR)\quota.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\radix.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\radix.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\radix.obj" "$(INTDIR)\radix.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\random.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\random.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\random.obj" "$(INTDIR)\random.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\ratelimiter.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\ratelimiter.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\ratelimiter.obj" "$(INTDIR)\ratelimiter.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\refcount.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\refcount.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\refcount.obj" "$(INTDIR)\refcount.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\regex.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\regex.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\regex.obj" "$(INTDIR)\regex.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +SOURCE=..\region.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\region.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\region.obj" "$(INTDIR)\region.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\result.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\result.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\result.obj" "$(INTDIR)\result.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\rwlock.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\rwlock.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\rwlock.obj" "$(INTDIR)\rwlock.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\safe.c + +!IF "$(CFG)" == "libisc - Win32 Release" + + +"$(INTDIR)\safe.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - Win32 Debug" + + +"$(INTDIR)\safe.obj" "$(INTDIR)\safe.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\serial.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\serial.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\serial.obj" "$(INTDIR)\serial.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\sha1.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\sha1.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\sha1.obj" "$(INTDIR)\sha1.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\sha2.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\sha2.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\sha2.obj" "$(INTDIR)\sha2.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\sockaddr.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\sockaddr.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\sockaddr.obj" "$(INTDIR)\sockaddr.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\stats.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\stats.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\stats.obj" "$(INTDIR)\stats.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\string.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\string.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\string.obj" "$(INTDIR)\string.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\symtab.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\symtab.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\symtab.obj" "$(INTDIR)\symtab.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\task.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\task.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\task.obj" "$(INTDIR)\task.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\taskpool.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\taskpool.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\taskpool.obj" "$(INTDIR)\taskpool.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\timer.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\timer.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\timer.obj" "$(INTDIR)\timer.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\tm.c + +!IF "$(CFG)" == "libisc - @PLATFORM@ Release" + + +"$(INTDIR)\tm.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libisc - @PLATFORM@ Debug" + + +"$(INTDIR)\tm.obj" "$(INTDIR)\tm.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + +#################################################### +# Commands to generate initial empty manifest file and the RC file +# that references it, and for generating the .res file: + +$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc + +$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest + type <<$@ +#include +1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" +<< KEEP + +$(_VC_MANIFEST_BASENAME).auto.manifest : + type <<$@ + + + +<< KEEP diff --git a/lib/isc/win32/libisc.vcxproj.filters.in b/lib/isc/win32/libisc.vcxproj.filters.in new file mode 100644 index 0000000..d6a5234 --- /dev/null +++ b/lib/isc/win32/libisc.vcxproj.filters.in @@ -0,0 +1,675 @@ + + + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {289562c2-1bdd-4582-b6bd-3f598ee23cbd} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {d03c3e6a-e78e-4a01-bd77-64c839b1adfe} + h;hpp;hxx;hm;inl;inc;xsd + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + +@IF AES + + Library Header Files + +@END AES + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Win32 Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Win32 Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + +@IF PKCS11 + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Library Header Files + + + Pkcs11 Header Files + + + Pkcs11 Header Files + + + Pkcs11 Header Files + +@END PKCS11 + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + + + Win32 Header Files + +@IF PKCS11 + + Win32 Header Files + +@END PKCS11 +@IF ATOMIC + +@ELSE ATOMIC + +@END ATOMIC + Library Header Files + + + Library Header Files + + + Library Header Files + + + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + + + Win32 Source Files + +@IF PKCS11 + + Win32 Source Files + +@END PKCS11 +@IF AES + + Win32 Source Files + +@END AES + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + + + Library Source Files + +@IF PKCS11 + + Library Source Files + + + Library Source Files + +@END PKCS11 + + diff --git a/lib/isc/win32/libisc.vcxproj.in b/lib/isc/win32/libisc.vcxproj.in new file mode 100644 index 0000000..fb9222a --- /dev/null +++ b/lib/isc/win32/libisc.vcxproj.in @@ -0,0 +1,530 @@ + + + + + Debug + @PLATFORM@ + + + Release + @PLATFORM@ + + + + {3840E563-D180-4761-AA9C-E6155F02EAFF} + Win32Proj + libisc + + + + DynamicLibrary + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + true + ..\..\..\Build\$(Configuration)\ + .\$(Configuration)\ + + + false + ..\..\..\Build\$(Configuration)\ + .\$(Configuration)\ + + + + + + Level3 + Disabled +@IF PKCS11 + BIND9;@CRYPTO@@PK11_LIB_LOCATION@WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBISC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions) + .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;win32;..\..\isccfg\include;..\..\dns\win32\include;..\..\dns\include;%(AdditionalIncludeDirectories) +@ELSE PKCS11 + BIND9;WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBISC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions) + .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;win32;..\..\isccfg\include;%(AdditionalIncludeDirectories) +@END PKCS11 + true + .\$(Configuration)\$(TargetName).pch + .\$(Configuration)\ + .\$(Configuration)\ + $(OutDir)$(TargetName).pdb + true + CompileAsC + + + Console + true + ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) + @LIBXML2_LIB@@OPENSSL_LIB@@ZLIB_LIB@ws2_32.lib;%(AdditionalDependencies) + $(ProjectName).def + .\$(Configuration)\$(ProjectName).lib + + + cd ..\..\..\win32utils + +if NOT Exist ..\Build mkdir ..\Build +if NOT Exist ..\Build\Debug mkdir ..\Build\Debug + +echo Copying COPYRIGHT notice. + +copy ..\COPYRIGHT ..\Build\Debug + +@IF OPENSSL +echo Copying the OpenSSL DLL and LICENSE. + +copy @OPENSSL_DLL@ ..\Build\Debug\ +copy @OPENSSL_PATH@\LICENSE ..\Build\Debug\OpenSSL-LICENSE +@END OPENSSL + +@IF LIBXML2 +echo Copying the libxml DLL. + +copy @LIBXML2_DLL@ ..\Build\Debug\ +@END LIBXML2 + +@IF GSSAPI +echo Copying the GSSAPI and KRB5 DLLs. + +copy @GSSAPI_DLL@ ..\Build\Debug\ +copy @KRB5_DLL@ ..\Build\Debug\ +copy @COMERR_DLL@ ..\Build\Debug\ +copy @K5SPRT_DLL@ ..\Build\Debug\ +copy @WSHELP_DLL@ ..\Build\Debug\ +@END GSSAPI + +@IF GEOIP +echo Copying the GeoIP DLL. + +copy @GEOIP_DLL@ ..\Build\Debug\ +@END GEOIP + +@IF IDNKIT +echo Copying the IDN kit DLL. + +copy @IDN_DLL@ ..\Build\Debug\ +copy @ICONV_DLL@ ..\Build\Debug\ +@END IDNKIT + +@IF ZLIB +echo Copying the zlib DLL. + +copy @ZLIB_DLL@ ..\Build\Debug\ +@END ZLIB + +echo Copying Visual C x86 Redistributable Installer. + +copy /Y @VCREDIST_PATH@ ..\Build\Debug\ + +echo Copying install files (flags and file list). + +copy InstallFlags ..\Build\Debug\ +copy InstallFiles ..\Build\Debug\ + + + + + + + Level3 + + + MaxSpeed + true + @INTRINSIC@ +@IF PKCS11 + BIND9;@CRYPTO@@PK11_LIB_LOCATION@WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBISC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions) + .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;win32;..\..\isccfg\include;..\..\dns\win32\include;..\..\dns\include;%(AdditionalIncludeDirectories) +@ELSE PKCS11 + BIND9;WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBISC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions) + .\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@ZLIB_INC@include;..\include;win32;..\..\isccfg\include;%(AdditionalIncludeDirectories) +@END PKCS11 + OnlyExplicitInline + false + true + .\$(Configuration)\$(TargetName).pch + .\$(Configuration)\ + .\$(Configuration)\ + $(OutDir)$(TargetName).pdb + CompileAsC + + + Console + false + true + true + ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) + @LIBXML2_LIB@@OPENSSL_LIB@@ZLIB_LIB@ws2_32.lib;%(AdditionalDependencies) + $(ProjectName).def + .\$(Configuration)\$(ProjectName).lib + Default + + + cd ..\..\..\win32utils + +if NOT Exist ..\Build mkdir ..\Build +if NOT Exist ..\Build\Release mkdir ..\Build\Release + +echo Copying the ARM and the Installation Notes. + +copy ..\COPYRIGHT ..\Build\Release +copy ..\README ..\Build\Release +copy ..\HISTORY ..\Build\Release +copy readme1st.txt ..\Build\Release +copy index.html ..\Build\Release +copy ..\doc\arm\*.html ..\Build\Release +copy ..\doc\arm\notes.pdf ..\Build\Release +copy ..\doc\arm\Bv9ARM.pdf ..\Build\Release +copy ..\CHANGES ..\Build\Release +if Exist ..\CHANGES.SE copy ..\CHANGES.SE ..\Build\Release +copy ..\FAQ ..\Build\Release + +echo Copying the standalone manual pages. + +copy ..\bin\named\named.html ..\Build\Release +copy ..\bin\named\named.conf.html ..\Build\Release +copy ..\bin\named\lwresd.html ..\Build\Release +copy ..\bin\rndc\*.html ..\Build\Release +copy ..\bin\confgen\*.html ..\Build\Release +copy ..\bin\dig\*.html ..\Build\Release +copy ..\bin\delv\*.html ..\Build\Release +copy ..\bin\nsupdate\*.html ..\Build\Release +copy ..\bin\check\*.html ..\Build\Release +copy ..\bin\dnssec\dnssec-keygen.html ..\Build\Release +copy ..\bin\dnssec\dnssec-signzone.html ..\Build\Release +copy ..\bin\dnssec\dnssec-dsfromkey.html ..\Build\Release +copy ..\bin\dnssec\dnssec-keyfromlabel.html ..\Build\Release +copy ..\bin\dnssec\dnssec-settime.html ..\Build\Release +copy ..\bin\dnssec\dnssec-revoke.html ..\Build\Release +copy ..\bin\dnssec\dnssec-verify.html ..\Build\Release +copy ..\bin\dnssec\dnssec-importkey.html ..\Build\Release +@IF PYTHON +copy ..\bin\python\dnssec-checkds.html ..\Build\Release +copy ..\bin\python\dnssec-coverage.html ..\Build\Release +copy ..\bin\python\dnssec-keymgr.html ..\Build\Release +@END PYTHON +@IF PKCS11 +copy ..\bin\pkcs11\pkcs11-keygen.html ..\Build\Release +copy ..\bin\pkcs11\pkcs11-list.html ..\Build\Release +copy ..\bin\pkcs11\pkcs11-destroy.html ..\Build\Release +copy ..\bin\pkcs11\pkcs11-tokens.html ..\Build\Release +@END PKCS11 +copy ..\bin\tools\arpaname.html ..\Build\Release +copy ..\bin\tools\genrandom.html ..\Build\Release +copy ..\bin\tools\isc-hmac-fixup.html ..\Build\Release +copy ..\bin\tools\named-journalprint.html ..\Build\Release +copy ..\bin\tools\named-rrchecker.html ..\Build\Release +copy ..\bin\tools\nsec3hash.html ..\Build\Release +copy ..\bin\tools\mdig.html ..\Build\Release + +echo Copying the migration notes. + +copy ..\doc\misc\migration ..\Build\Release +copy ..\doc\misc\migration-4to9 ..\Build\Release + +@IF OPENSSL +echo Copying the OpenSSL DLL and LICENSE. + +copy @OPENSSL_DLL@ ..\Build\Release\ +copy @OPENSSL_PATH@\LICENSE ..\Build\Release\OpenSSL-LICENSE +@END OPENSSL + +@IF LIBXML2 +echo Copying the libxml DLL. + +copy @LIBXML2_DLL@ ..\Build\Release\ +@END LIBXML2 + +@IF GSSAPI +echo Copying the GSSAPI and KRB5 DLLs. + +copy @GSSAPI_DLL@ ..\Build\Release\ +copy @KRB5_DLL@ ..\Build\Release\ +copy @COMERR_DLL@ ..\Build\Release\ +copy @K5SPRT_DLL@ ..\Build\Release\ +copy @WSHELP_DLL@ ..\Build\Release\ +@END GSSAPI + +@IF GEOIP +echo Copying the GeoIP DLL. + +copy @GEOIP_DLL@ ..\Build\Release\ +@END GEOIP + +@IF IDNKIT +echo Copying the IDN kit DLL. + +copy @IDN_DLL@ ..\Build\Release\ +copy @ICONV_DLL@ ..\Build\Release\ +@END IDNKIT + +@IF ZLIB +echo Copying the zlib DLL. + +copy @ZLIB_DLL@ ..\Build\Release\ +@END ZLIB + +echo Copying Visual C x86 Redistributable Installer. + +copy /Y @VCREDIST_PATH@ ..\Build\Release\ + +echo Copying install files (flags and file list). + +copy InstallFlags ..\Build\Release\ +copy InstallFiles ..\Build\Release\ + + + + + + + + + +@IF AES + +@END AES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@IF PKCS11 + + + + + + + +@END PKCS11 +@IF ATOMIC + +@ELSE ATOMIC + +@END ATOMIC + + + + + + + + + + + + + + + + + + + + + + + + +@IF PKCS11 + +@END PKCS11 + + + +@IF AES + +@END AES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@IF PKCS11 + + +@END PKCS11 + + + + + + + + + + + + + + + + + + + + + + + + + + + +@IF PKCS11 + +@END PKCS11 + + + + + diff --git a/lib/isc/win32/libisc.vcxproj.user b/lib/isc/win32/libisc.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/lib/isc/win32/libisc.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lib/isc/win32/meminfo.c b/lib/isc/win32/meminfo.c new file mode 100644 index 0000000..51077f6 --- /dev/null +++ b/lib/isc/win32/meminfo.c @@ -0,0 +1,26 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include + +#include +#include + +#include + +uint64_t +isc_meminfo_totalphys(void) { + MEMORYSTATUSEX statex; + + statex.dwLength = sizeof(statex); + GlobalMemoryStatusEx(&statex); + return ((uint64_t)statex.ullTotalPhys); +} diff --git a/lib/isc/win32/net.c b/lib/isc/win32/net.c new file mode 100644 index 0000000..c49bb6b --- /dev/null +++ b/lib/isc/win32/net.c @@ -0,0 +1,341 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/*% + * Definitions about UDP port range specification. This is a total mess of + * portability variants: some use sysctl (but the sysctl names vary), some use + * system-specific interfaces, some have the same interface for IPv4 and IPv6, + * some separate them, etc... + */ + +/*% + * The last resort defaults: use all non well known port space + */ +#ifndef ISC_NET_PORTRANGELOW +#define ISC_NET_PORTRANGELOW 1024 +#endif /* ISC_NET_PORTRANGELOW */ +#ifndef ISC_NET_PORTRANGEHIGH +#define ISC_NET_PORTRANGEHIGH 65535 +#endif /* ISC_NET_PORTRANGEHIGH */ + +#if defined(ISC_PLATFORM_HAVEIPV6) && defined(ISC_PLATFORM_NEEDIN6ADDRANY) +const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT; +#endif + +static isc_once_t once = ISC_ONCE_INIT; +static isc_once_t once_ipv6only = ISC_ONCE_INIT; +static isc_once_t once_ipv6pktinfo = ISC_ONCE_INIT; +static isc_result_t ipv4_result = ISC_R_NOTFOUND; +static isc_result_t ipv6_result = ISC_R_NOTFOUND; +static isc_result_t ipv6only_result = ISC_R_NOTFOUND; +static isc_result_t ipv6pktinfo_result = ISC_R_NOTFOUND; + +void InitSockets(void); + +static isc_result_t +try_proto(int domain) { + SOCKET s; + char strbuf[ISC_STRERRORSIZE]; + int errval; + + s = socket(domain, SOCK_STREAM, IPPROTO_TCP); + if (s == INVALID_SOCKET) { + errval = WSAGetLastError(); + switch (errval) { + case WSAEAFNOSUPPORT: + case WSAEPROTONOSUPPORT: + case WSAEINVAL: + return (ISC_R_NOTFOUND); + default: + isc__strerror(errval, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "socket() %s: %s", + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, + "failed"), + strbuf); + return (ISC_R_UNEXPECTED); + } + } + + closesocket(s); + + return (ISC_R_SUCCESS); +} + +static void +initialize_action(void) { + InitSockets(); + ipv4_result = try_proto(PF_INET); +#ifdef ISC_PLATFORM_HAVEIPV6 +#ifdef WANT_IPV6 +#ifdef ISC_PLATFORM_HAVEIN6PKTINFO + ipv6_result = try_proto(PF_INET6); +#endif +#endif +#endif +} + +static void +initialize(void) { + RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS); +} + +isc_result_t +isc_net_probeipv4(void) { + initialize(); + return (ipv4_result); +} + +isc_result_t +isc_net_probeipv6(void) { + initialize(); + return (ipv6_result); +} + +isc_result_t +isc_net_probeunix(void) { + return (ISC_R_NOTFOUND); +} + +#ifdef ISC_PLATFORM_HAVEIPV6 +#ifdef WANT_IPV6 +static void +try_ipv6only(void) { +#ifdef IPV6_V6ONLY + SOCKET s; + int on; + char strbuf[ISC_STRERRORSIZE]; +#endif + isc_result_t result; + + result = isc_net_probeipv6(); + if (result != ISC_R_SUCCESS) { + ipv6only_result = result; + return; + } + +#ifndef IPV6_V6ONLY + ipv6only_result = ISC_R_NOTFOUND; + return; +#else + /* check for TCP sockets */ + s = socket(PF_INET6, SOCK_STREAM, 0); + if (s == INVALID_SOCKET) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "socket() %s: %s", + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, + "failed"), + strbuf); + ipv6only_result = ISC_R_UNEXPECTED; + return; + } + + on = 1; + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&on, + sizeof(on)) < 0) { + ipv6only_result = ISC_R_NOTFOUND; + goto close; + } + + closesocket(s); + + /* check for UDP sockets */ + s = socket(PF_INET6, SOCK_DGRAM, 0); + if (s == INVALID_SOCKET) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "socket() %s: %s", + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, + "failed"), + strbuf); + ipv6only_result = ISC_R_UNEXPECTED; + return; + } + + on = 1; + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&on, + sizeof(on)) < 0) { + ipv6only_result = ISC_R_NOTFOUND; + goto close; + } + + ipv6only_result = ISC_R_SUCCESS; + +close: + closesocket(s); + return; +#endif /* IPV6_V6ONLY */ +} + +static void +initialize_ipv6only(void) { + RUNTIME_CHECK(isc_once_do(&once_ipv6only, + try_ipv6only) == ISC_R_SUCCESS); +} + +#ifdef __notyet__ +/* + * XXXMPA requires win32/socket.c to be updated to support + * WSASendMsg and WSARecvMsg which are themselves Winsock + * and compiler version dependent. + */ +static void +try_ipv6pktinfo(void) { + SOCKET s; + int on; + char strbuf[ISC_STRERRORSIZE]; + isc_result_t result; + int optname; + + result = isc_net_probeipv6(); + if (result != ISC_R_SUCCESS) { + ipv6pktinfo_result = result; + return; + } + + /* we only use this for UDP sockets */ + s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); + if (s == INVALID_SOCKET) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "socket() %s: %s", + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, + "failed"), + strbuf); + ipv6pktinfo_result = ISC_R_UNEXPECTED; + return; + } + +#ifdef IPV6_RECVPKTINFO + optname = IPV6_RECVPKTINFO; +#else + optname = IPV6_PKTINFO; +#endif + on = 1; + if (setsockopt(s, IPPROTO_IPV6, optname, (const char *) &on, + sizeof(on)) < 0) { + ipv6pktinfo_result = ISC_R_NOTFOUND; + goto close; + } + + ipv6pktinfo_result = ISC_R_SUCCESS; + +close: + closesocket(s); + return; +} + +static void +initialize_ipv6pktinfo(void) { + RUNTIME_CHECK(isc_once_do(&once_ipv6pktinfo, + try_ipv6pktinfo) == ISC_R_SUCCESS); +} +#endif /* __notyet__ */ +#endif /* WANT_IPV6 */ +#endif /* ISC_PLATFORM_HAVEIPV6 */ + +isc_result_t +isc_net_probe_ipv6only(void) { +#ifdef ISC_PLATFORM_HAVEIPV6 +#ifdef WANT_IPV6 + initialize_ipv6only(); +#else + ipv6only_result = ISC_R_NOTFOUND; +#endif +#endif + return (ipv6only_result); +} + +isc_result_t +isc_net_probe_ipv6pktinfo(void) { +#ifdef __notyet__ +#ifdef ISC_PLATFORM_HAVEIPV6 +#ifdef WANT_IPV6 + initialize_ipv6pktinfo(); +#else + ipv6pktinfo_result = ISC_R_NOTFOUND; +#endif +#endif +#endif /* __notyet__ */ + return (ipv6pktinfo_result); +} + +isc_result_t +isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high) { + int result = ISC_R_FAILURE; + + REQUIRE(low != NULL && high != NULL); + + UNUSED(af); + + if (result != ISC_R_SUCCESS) { + *low = ISC_NET_PORTRANGELOW; + *high = ISC_NET_PORTRANGEHIGH; + } + + return (ISC_R_SUCCESS); /* we currently never fail in this function */ +} + +void +isc_net_disableipv4(void) { + initialize(); + if (ipv4_result == ISC_R_SUCCESS) + ipv4_result = ISC_R_DISABLED; +} + +void +isc_net_disableipv6(void) { + initialize(); + if (ipv6_result == ISC_R_SUCCESS) + ipv6_result = ISC_R_DISABLED; +} + +void +isc_net_enableipv4(void) { + initialize(); + if (ipv4_result == ISC_R_DISABLED) + ipv4_result = ISC_R_SUCCESS; +} + +void +isc_net_enableipv6(void) { + initialize(); + if (ipv6_result == ISC_R_DISABLED) + ipv6_result = ISC_R_SUCCESS; +} + +unsigned int +isc_net_probedscp(void) { + return (0); +} diff --git a/lib/isc/win32/netdb.h b/lib/isc/win32/netdb.h new file mode 100644 index 0000000..a9398c8 --- /dev/null +++ b/lib/isc/win32/netdb.h @@ -0,0 +1,182 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef NETDB_H +#define NETDB_H 1 + +#include +#include + +/* + * Define if does not declare struct addrinfo. + */ + +#if _MSC_VER < 1600 +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* Length of ai_addr */ + char *ai_canonname; /* Canonical name for hostname */ + struct sockaddr *ai_addr; /* Binary address */ + struct addrinfo *ai_next; /* Next structure in linked list */ +}; +#endif + + +/* + * Undefine all \#defines we are interested in as may or may not have + * defined them. + */ + +/* + * Error return codes from gethostbyname() and gethostbyaddr() + * (left in extern int h_errno). + */ + +#undef NETDB_INTERNAL +#undef NETDB_SUCCESS +#undef HOST_NOT_FOUND +#undef TRY_AGAIN +#undef NO_RECOVERY +#undef NO_DATA +#undef NO_ADDRESS + +#define NETDB_INTERNAL -1 /* see errno */ +#define NETDB_SUCCESS 0 /* no problem */ +#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ +#define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL */ +#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ +#define NO_DATA 4 /* Valid name, no data record of requested type */ +#define NO_ADDRESS NO_DATA /* no address, look for MX record */ + +/* + * Error return codes from getaddrinfo() + */ + +#undef EAI_ADDRFAMILY +#undef EAI_AGAIN +#undef EAI_BADFLAGS +#undef EAI_FAIL +#undef EAI_FAMILY +#undef EAI_MEMORY +#undef EAI_NODATA +#undef EAI_NONAME +#undef EAI_SERVICE +#undef EAI_SOCKTYPE +#undef EAI_SYSTEM +#undef EAI_BADHINTS +#undef EAI_PROTOCOL +#undef EAI_MAX + +#define EAI_ADDRFAMILY 1 /* address family for hostname not supported */ +#define EAI_AGAIN 2 /* temporary failure in name resolution */ +#define EAI_BADFLAGS 3 /* invalid value for ai_flags */ +#define EAI_FAIL 4 /* non-recoverable failure in name resolution */ +#define EAI_FAMILY 5 /* ai_family not supported */ +#define EAI_MEMORY 6 /* memory allocation failure */ +#define EAI_NODATA 7 /* no address associated with hostname */ +#define EAI_NONAME 8 /* hostname nor servname provided, or not known */ +#define EAI_SERVICE 9 /* servname not supported for ai_socktype */ +#define EAI_SOCKTYPE 10 /* ai_socktype not supported */ +#define EAI_SYSTEM 11 /* system error returned in errno */ +#define EAI_BADHINTS 12 +#define EAI_PROTOCOL 13 +#define EAI_MAX 14 + +/* + * Flag values for getaddrinfo() + */ +#undef AI_PASSIVE +#undef AI_CANONNAME +#undef AI_NUMERICHOST + +#define AI_PASSIVE 0x00000001 +#define AI_CANONNAME 0x00000002 +#define AI_NUMERICHOST 0x00000004 + +/* + * Flag values for getipnodebyname() + */ +#undef AI_V4MAPPED +#undef AI_ALL +#undef AI_ADDRCONFIG +#undef AI_DEFAULT + +#define AI_V4MAPPED 0x00000008 +#define AI_ALL 0x00000010 +#define AI_ADDRCONFIG 0x00000020 +#define AI_DEFAULT (AI_V4MAPPED|AI_ADDRCONFIG) + +/* + * Constants for getnameinfo() + */ +#undef NI_MAXHOST +#undef NI_MAXSERV + +#define NI_MAXHOST 1025 +#define NI_MAXSERV 32 + +/* + * Flag values for getnameinfo() + */ +#undef NI_NOFQDN +#undef NI_NUMERICHOST +#undef NI_NAMEREQD +#undef NI_NUMERICSERV +#undef NI_DGRAM +#undef NI_NUMERICSCOPE + +#define NI_NOFQDN 0x00000001 +#define NI_NUMERICHOST 0x00000002 +#define NI_NAMEREQD 0x00000004 +#define NI_NUMERICSERV 0x00000008 +#define NI_DGRAM 0x00000010 +#define NI_NUMERICSCOPE 0x00000020 /*2553bis-00*/ + +/* + * Structures for getrrsetbyname() + */ +struct rdatainfo { + unsigned int rdi_length; + unsigned char *rdi_data; +}; + +struct rrsetinfo { + unsigned int rri_flags; + int rri_rdclass; + int rri_rdtype; + unsigned int rri_ttl; + unsigned int rri_nrdatas; + unsigned int rri_nsigs; + char *rri_name; + struct rdatainfo *rri_rdatas; + struct rdatainfo *rri_sigs; +}; + +/* + * Flags for getrrsetbyname() + */ +#define RRSET_VALIDATED 0x00000001 + /* Set was dnssec validated */ + +/* + * Return codes for getrrsetbyname() + */ +#define ERRSET_SUCCESS 0 +#define ERRSET_NOMEMORY 1 +#define ERRSET_FAIL 2 +#define ERRSET_INVAL 3 + + +#endif /* NETDB_H */ diff --git a/lib/isc/win32/ntgroups.c b/lib/isc/win32/ntgroups.c new file mode 100644 index 0000000..e3a45ca --- /dev/null +++ b/lib/isc/win32/ntgroups.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* + * The NT Groups have two groups that are not well documented and are + * not normally seen: None and Everyone. A user account belongs to + * any number of groups, but if it is not a member of any group then + * it is a member of the None Group. The None group is not listed + * anywhere. You cannot remove an account from the none group except + * by making it a member of some other group, The second group is the + * Everyone group. All accounts, no matter how many groups that they + * belong to, also belong to the Everyone group. You cannot remove an + * account from the Everyone group. + */ + +#ifndef UNICODE +#define UNICODE +#endif /* UNICODE */ + +/* + * Silence warnings. + */ +#define _CRT_SECURE_NO_DEPRECATE 1 + +#include +#include +#include + +#include +#include + +#define MAX_NAME_LENGTH 256 + +isc_result_t +isc_ntsecurity_getaccountgroups(char *username, char **GroupList, + unsigned int maxgroups, + unsigned int *totalGroups) { + LPGROUP_USERS_INFO_0 pTmpBuf; + LPLOCALGROUP_USERS_INFO_0 pTmpLBuf; + DWORD i; + LPLOCALGROUP_USERS_INFO_0 pBuf = NULL; + LPGROUP_USERS_INFO_0 pgrpBuf = NULL; + DWORD dwLevel = 0; + DWORD dwFlags = LG_INCLUDE_INDIRECT; + DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH; + DWORD dwEntriesRead = 0; + DWORD dwTotalEntries = 0; + NET_API_STATUS nStatus; + size_t retlen; + wchar_t user[MAX_NAME_LENGTH]; + + retlen = mbstowcs(user, username, MAX_NAME_LENGTH); + + *totalGroups = 0; + /* + * Call the NetUserGetLocalGroups function + * specifying information level 0. + * + * The LG_INCLUDE_INDIRECT flag specifies that the + * function should also return the names of the local + * groups in which the user is indirectly a member. + */ + nStatus = NetUserGetLocalGroups(NULL, + user, + dwLevel, + dwFlags, + (LPBYTE *) &pBuf, + dwPrefMaxLen, + &dwEntriesRead, + &dwTotalEntries); + /* + * See if the call succeeds, + */ + if (nStatus != NERR_Success) { + if (nStatus == ERROR_ACCESS_DENIED) + return (ISC_R_NOPERM); + if (nStatus == ERROR_MORE_DATA) + return (ISC_R_NOSPACE); + if (nStatus == NERR_UserNotFound) + dwEntriesRead = 0; + } + + if (pBuf != NULL) { + pTmpLBuf = pBuf; + /* + * Loop through the entries + */ + for (i = 0; + (i < dwEntriesRead && *totalGroups < maxgroups); i++) { + assert(pTmpLBuf != NULL); + if (pTmpLBuf == NULL) + break; + retlen = wcslen(pTmpLBuf->lgrui0_name); + GroupList[*totalGroups] = (char *) malloc(retlen +1); + if (GroupList[*totalGroups] == NULL) + return (ISC_R_NOMEMORY); + + retlen = wcstombs(GroupList[*totalGroups], + pTmpLBuf->lgrui0_name, retlen); + GroupList[*totalGroups][retlen] = '\0'; + if (strcmp(GroupList[*totalGroups], "None") == 0) + free(GroupList[*totalGroups]); + else + (*totalGroups)++; + pTmpLBuf++; + } + } + /* Free the allocated memory. */ + if (pBuf != NULL) + NetApiBufferFree(pBuf); + + + /* + * Call the NetUserGetGroups function, specifying level 0. + */ + nStatus = NetUserGetGroups(NULL, + user, + dwLevel, + (LPBYTE*)&pgrpBuf, + dwPrefMaxLen, + &dwEntriesRead, + &dwTotalEntries); + /* + * See if the call succeeds, + */ + if (nStatus != NERR_Success) { + if (nStatus == ERROR_ACCESS_DENIED) + return (ISC_R_NOPERM); + if (nStatus == ERROR_MORE_DATA) + return (ISC_R_NOSPACE); + if (nStatus == NERR_UserNotFound) + dwEntriesRead = 0; + } + + if (pgrpBuf != NULL) { + pTmpBuf = pgrpBuf; + /* + * Loop through the entries + */ + for (i = 0; + (i < dwEntriesRead && *totalGroups < maxgroups); i++) { + assert(pTmpBuf != NULL); + + if (pTmpBuf == NULL) + break; + retlen = wcslen(pTmpBuf->grui0_name); + GroupList[*totalGroups] = (char *) malloc(retlen +1); + if (GroupList[*totalGroups] == NULL) + return (ISC_R_NOMEMORY); + + retlen = wcstombs(GroupList[*totalGroups], + pTmpBuf->grui0_name, retlen); + GroupList[*totalGroups][retlen] = '\0'; + if (strcmp(GroupList[*totalGroups], "None") == 0) + free(GroupList[*totalGroups]); + else + (*totalGroups)++; + pTmpBuf++; + } + } + /* + * Free the allocated memory. + */ + if (pgrpBuf != NULL) + NetApiBufferFree(pgrpBuf); + + return (ISC_R_SUCCESS); +} diff --git a/lib/isc/win32/ntpaths.c b/lib/isc/win32/ntpaths.c new file mode 100644 index 0000000..df71bfa --- /dev/null +++ b/lib/isc/win32/ntpaths.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* + * This module fetches the required path information that is specific + * to NT systems which can have its configuration and system files + * almost anywhere. It can be used to override whatever the application + * had previously assigned to the pointer. Basic information about the + * file locations are stored in the registry. + */ + +#include + +#include +#include +#include + +/* + * Module Variables + */ + +static char systemDir[MAX_PATH]; +static char namedBase[MAX_PATH]; +static char ns_confFile[MAX_PATH]; +static char lwresd_confFile[MAX_PATH]; +static char lwresd_resolvconfFile[MAX_PATH]; +static char rndc_confFile[MAX_PATH]; +static char ns_defaultpidfile[MAX_PATH]; +static char lwresd_defaultpidfile[MAX_PATH]; +static char ns_lockfile[MAX_PATH]; +static char local_state_dir[MAX_PATH]; +static char sys_conf_dir[MAX_PATH]; +static char rndc_keyFile[MAX_PATH]; +static char session_keyFile[MAX_PATH]; + +static DWORD baseLen = MAX_PATH; +static BOOL Initialized = FALSE; + +void +isc_ntpaths_init(void) { + HKEY hKey; + BOOL keyFound = TRUE; + + memset(namedBase, 0, sizeof(namedBase)); + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, BIND_SUBKEY, 0, KEY_READ, &hKey) + != ERROR_SUCCESS) + keyFound = FALSE; + + if (keyFound == TRUE) { + /* Get the named directory */ + if (RegQueryValueEx(hKey, "InstallDir", NULL, NULL, + (LPBYTE)namedBase, &baseLen) != ERROR_SUCCESS) + keyFound = FALSE; + RegCloseKey(hKey); + } + + GetSystemDirectory(systemDir, MAX_PATH); + + if (keyFound == FALSE) { + /* Use the System Directory as a default */ + strlcpy(namedBase, systemDir, sizeof(namedBase)); + } + + strlcpy(lwresd_confFile, namedBase, sizeof(lwresd_confFile)) ; + strlcat(lwresd_confFile, "\\etc\\lwresd.conf", + sizeof(lwresd_confFile)); + + strlcpy(lwresd_defaultpidfile, namedBase, + sizeof(lwresd_defaultpidfile)); + strlcat(lwresd_defaultpidfile, "\\etc\\lwresd.pid", + sizeof(lwresd_defaultpidfile)); + + strlcpy(lwresd_resolvconfFile, systemDir, + sizeof(lwresd_resolvconfFile)); + strlcat(lwresd_resolvconfFile, "\\Drivers\\etc\\resolv.conf", + sizeof(lwresd_resolvconfFile)); + + strlcpy(ns_confFile, namedBase, sizeof(ns_confFile)); + strlcat(ns_confFile, "\\etc\\named.conf", sizeof(ns_confFile)); + + strlcpy(rndc_keyFile, namedBase, sizeof(rndc_keyFile)); + strlcat(rndc_keyFile, "\\etc\\rndc.key", sizeof(rndc_keyFile)); + + strlcpy(session_keyFile, namedBase, sizeof(session_keyFile)); + strlcat(session_keyFile, "\\etc\\session.key", sizeof(session_keyFile)); + + strlcpy(rndc_confFile, namedBase, sizeof(rndc_confFile)); + strlcat(rndc_confFile, "\\etc\\rndc.conf", sizeof(rndc_confFile)); + + strlcpy(ns_defaultpidfile, namedBase, sizeof(ns_defaultpidfile)); + strlcat(ns_defaultpidfile, "\\etc\\named.pid", + sizeof(ns_defaultpidfile)); + + strlcpy(ns_lockfile, namedBase, sizeof(ns_lockfile)); + strlcat(ns_lockfile, "\\etc\\named.lock", sizeof(ns_lockfile)); + + strlcpy(local_state_dir, namedBase, sizeof(local_state_dir)); + strlcat(local_state_dir, "\\bin", sizeof(local_state_dir)); + + strlcpy(sys_conf_dir, namedBase, sizeof(sys_conf_dir)); + strlcat(sys_conf_dir, "\\etc", sizeof(sys_conf_dir)); + + Initialized = TRUE; +} + +char * +isc_ntpaths_get(int ind) { + if (!Initialized) + isc_ntpaths_init(); + + switch (ind) { + case NAMED_CONF_PATH: + return (ns_confFile); + break; + case LWRES_CONF_PATH: + return (lwresd_confFile); + break; + case RESOLV_CONF_PATH: + return (lwresd_resolvconfFile); + break; + case RNDC_CONF_PATH: + return (rndc_confFile); + break; + case NAMED_PID_PATH: + return (ns_defaultpidfile); + break; + case LWRESD_PID_PATH: + return (lwresd_defaultpidfile); + break; + case NAMED_LOCK_PATH: + return (ns_lockfile); + break; + case LOCAL_STATE_DIR: + return (local_state_dir); + break; + case SYS_CONF_DIR: + return (sys_conf_dir); + break; + case RNDC_KEY_PATH: + return (rndc_keyFile); + break; + case SESSION_KEY_PATH: + return (session_keyFile); + break; + default: + return (NULL); + } +} diff --git a/lib/isc/win32/once.c b/lib/isc/win32/once.c new file mode 100644 index 0000000..baf178d --- /dev/null +++ b/lib/isc/win32/once.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include + +#include + +#include +#include +#include + +isc_result_t +isc_once_do(isc_once_t *controller, void(*function)(void)) { + REQUIRE(controller != NULL && function != NULL); + + if (controller->status == ISC_ONCE_INIT_NEEDED) { + + if (InterlockedDecrement(&controller->counter) == 0) { + if (controller->status == ISC_ONCE_INIT_NEEDED) { + function(); + controller->status = ISC_ONCE_INIT_DONE; + } + } else { + while (controller->status == ISC_ONCE_INIT_NEEDED) { + /* + * Sleep(0) indicates that this thread + * should be suspended to allow other + * waiting threads to execute. + */ + Sleep(0); + } + } + } + + return (ISC_R_SUCCESS); +} diff --git a/lib/isc/win32/os.c b/lib/isc/win32/os.c new file mode 100644 index 0000000..0f4023f --- /dev/null +++ b/lib/isc/win32/os.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include + +#include + +static BOOL bInit = FALSE; +static SYSTEM_INFO SystemInfo; + +static void +initialize_action(void) { + if (bInit) + return; + + GetSystemInfo(&SystemInfo); + bInit = TRUE; +} + +unsigned int +isc_os_ncpus(void) { + long ncpus; + initialize_action(); + ncpus = SystemInfo.dwNumberOfProcessors; + if (ncpus <= 0) + ncpus = 1; + + return ((unsigned int)ncpus); +} diff --git a/lib/isc/win32/pk11_api.c b/lib/isc/win32/pk11_api.c new file mode 100644 index 0000000..76e4abb --- /dev/null +++ b/lib/isc/win32/pk11_api.c @@ -0,0 +1,675 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +/* missing code for WIN32 */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define HAVE_GETPASSPHRASE + +char * +getpassphrase(const char *prompt) { + static char buf[128]; + HANDLE h; + DWORD cc, mode; + int cnt; + + h = GetStdHandle(STD_INPUT_HANDLE); + fputs(prompt, stderr); + fflush(stderr); + fflush(stdout); + FlushConsoleInputBuffer(h); + GetConsoleMode(h, &mode); + SetConsoleMode(h, ENABLE_PROCESSED_INPUT); + + for (cnt = 0; cnt < sizeof(buf) - 1; cnt++) + { + ReadFile(h, buf + cnt, 1, &cc, NULL); + if (buf[cnt] == '\r') + break; + fputc('*', stdout); + fflush(stderr); + fflush(stdout); + } + + SetConsoleMode(h, mode); + buf[cnt] = '\0'; + fputs("\n", stderr); + return (buf); +} + +/* load PKCS11 DLL */ + +static HINSTANCE hPK11 = NULL; +static char loaderrmsg[1024]; + +CK_RV +pkcs_C_Initialize(CK_VOID_PTR pReserved) { + CK_C_Initialize sym; + const char *lib_name = pk11_get_lib_name(); + + if (hPK11 != NULL) + return (CKR_LIBRARY_ALREADY_INITIALIZED); + + if (lib_name == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + /* Visual Studio convertion issue... */ + if (*lib_name == ' ') + lib_name++; + + hPK11 = LoadLibraryA(lib_name); + + if (hPK11 == NULL) { + const DWORD err = GetLastError(); + snprintf(loaderrmsg, sizeof(loaderrmsg), + "LoadLibraryA(\"%s\") failed with 0x%X\n", + lib_name, err); + return (CKR_LIBRARY_FAILED_TO_LOAD); + } + sym = (CK_C_Initialize)GetProcAddress(hPK11, "C_Initialize"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(pReserved); +} + +char *pk11_get_load_error_message(void) { + return (loaderrmsg); +} + +CK_RV +pkcs_C_Finalize(CK_VOID_PTR pReserved) { + CK_C_Finalize sym; + CK_RV rv; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + sym = (CK_C_Finalize)GetProcAddress(hPK11, "C_Finalize"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + rv = (*sym)(pReserved); + if ((rv == CKR_OK) && (FreeLibrary(hPK11) == 0)) + return (CKR_LIBRARY_FAILED_TO_LOAD); + hPK11 = NULL; + return (rv); +} + +CK_RV +pkcs_C_GetSlotList(CK_BBOOL tokenPresent, + CK_SLOT_ID_PTR pSlotList, + CK_ULONG_PTR pulCount) +{ + static CK_C_GetSlotList sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_GetSlotList)GetProcAddress(hPK11, "C_GetSlotList"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(tokenPresent, pSlotList, pulCount); +} + +CK_RV +pkcs_C_GetTokenInfo(CK_SLOT_ID slotID, + CK_TOKEN_INFO_PTR pInfo) +{ + static CK_C_GetTokenInfo sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_GetTokenInfo)GetProcAddress(hPK11, + "C_GetTokenInfo"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(slotID, pInfo); +} + +CK_RV +pkcs_C_GetMechanismInfo(CK_SLOT_ID slotID, + CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR pInfo) +{ + static CK_C_GetMechanismInfo sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_GetMechanismInfo)GetProcAddress(hPK11, + "C_GetMechanismInfo"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(slotID, type, pInfo); +} + +CK_RV +pkcs_C_OpenSession(CK_SLOT_ID slotID, + CK_FLAGS flags, + CK_VOID_PTR pApplication, + CK_RV (*Notify) (CK_SESSION_HANDLE hSession, + CK_NOTIFICATION event, + CK_VOID_PTR pApplication), + CK_SESSION_HANDLE_PTR phSession) +{ + static CK_C_OpenSession sym = NULL; + + if (hPK11 == NULL) + hPK11 = LoadLibraryA(pk11_get_lib_name()); + if (hPK11 == NULL) { + const DWORD err = GetLastError(); + snprintf(loaderrmsg, sizeof(loaderrmsg), + "LoadLibraryA(\"%s\") failed with 0x%X\n", + pk11_get_lib_name(), err); + return (CKR_LIBRARY_FAILED_TO_LOAD); + } + if (sym == NULL) + sym = (CK_C_OpenSession)GetProcAddress(hPK11, "C_OpenSession"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(slotID, flags, pApplication, Notify, phSession); +} + +CK_RV +pkcs_C_CloseSession(CK_SESSION_HANDLE hSession) { + static CK_C_CloseSession sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_CloseSession)GetProcAddress(hPK11, + "C_CloseSession"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession); +} + +CK_RV +pkcs_C_Login(CK_SESSION_HANDLE hSession, + CK_USER_TYPE userType, + CK_CHAR_PTR pPin, + CK_ULONG usPinLen) +{ + static CK_C_Login sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_Login)GetProcAddress(hPK11, "C_Login"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, userType, pPin, usPinLen); +} + +CK_RV +pkcs_C_Logout(CK_SESSION_HANDLE hSession) { + static CK_C_Logout sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_Logout)GetProcAddress(hPK11, "C_Logout"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession); +} + +CK_RV +pkcs_C_CreateObject(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG usCount, + CK_OBJECT_HANDLE_PTR phObject) +{ + static CK_C_CreateObject sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_CreateObject)GetProcAddress(hPK11, + "C_CreateObject"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pTemplate, usCount, phObject); +} + +CK_RV +pkcs_C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) { + static CK_C_DestroyObject sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_DestroyObject)GetProcAddress(hPK11, + "C_DestroyObject"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, hObject); +} + +CK_RV +pkcs_C_GetAttributeValue(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG usCount) +{ + static CK_C_GetAttributeValue sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_GetAttributeValue)GetProcAddress(hPK11, + "C_GetAttributeValue"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, hObject, pTemplate, usCount); +} + +CK_RV +pkcs_C_SetAttributeValue(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG usCount) +{ + static CK_C_SetAttributeValue sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_SetAttributeValue)GetProcAddress(hPK11, + "C_SetAttributeValue"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, hObject, pTemplate, usCount); +} + +CK_RV +pkcs_C_FindObjectsInit(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG usCount) +{ + static CK_C_FindObjectsInit sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_FindObjectsInit)GetProcAddress(hPK11, + "C_FindObjectsInit"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pTemplate, usCount); +} + +CK_RV +pkcs_C_FindObjects(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE_PTR phObject, + CK_ULONG usMaxObjectCount, + CK_ULONG_PTR pusObjectCount) +{ + static CK_C_FindObjects sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_FindObjects)GetProcAddress(hPK11, "C_FindObjects"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, phObject, usMaxObjectCount, pusObjectCount); +} + +CK_RV +pkcs_C_FindObjectsFinal(CK_SESSION_HANDLE hSession) { + static CK_C_FindObjectsFinal sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_FindObjectsFinal)GetProcAddress(hPK11, + "C_FindObjectsFinal"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession); +} + +CK_RV +pkcs_C_EncryptInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey) +{ + static CK_C_EncryptInit sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_EncryptInit)GetProcAddress(hPK11, "C_EncryptInit"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pMechanism, hKey); +} + +CK_RV +pkcs_C_Encrypt(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pEncryptedData, + CK_ULONG_PTR pulEncryptedDataLen) +{ + static CK_C_Encrypt sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_Encrypt)GetProcAddress(hPK11, "C_Encrypt"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pData, ulDataLen, + pEncryptedData, pulEncryptedDataLen); +} + +CK_RV +pkcs_C_DigestInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism) +{ + static CK_C_DigestInit sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_DigestInit)GetProcAddress(hPK11, "C_DigestInit"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pMechanism); +} + +CK_RV +pkcs_C_DigestUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen) +{ + static CK_C_DigestUpdate sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_DigestUpdate)GetProcAddress(hPK11, + "C_DigestUpdate"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pPart, ulPartLen); +} + +CK_RV +pkcs_C_DigestFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pDigest, + CK_ULONG_PTR pulDigestLen) +{ + static CK_C_DigestFinal sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_DigestFinal)GetProcAddress(hPK11, "C_DigestFinal"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pDigest, pulDigestLen); +} + +CK_RV +pkcs_C_SignInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey) +{ + static CK_C_SignInit sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_SignInit)GetProcAddress(hPK11, "C_SignInit"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pMechanism, hKey); +} + +CK_RV +pkcs_C_Sign(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen) +{ + static CK_C_Sign sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_Sign)GetProcAddress(hPK11, "C_Sign"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pData, ulDataLen, pSignature, pulSignatureLen); +} + +CK_RV +pkcs_C_SignUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen) +{ + static CK_C_SignUpdate sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_SignUpdate)GetProcAddress(hPK11, "C_SignUpdate"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pPart, ulPartLen); +} + +CK_RV +pkcs_C_SignFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen) +{ + static CK_C_SignFinal sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_SignFinal)GetProcAddress(hPK11, "C_SignFinal"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pSignature, pulSignatureLen); +} + +CK_RV +pkcs_C_VerifyInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey) +{ + static CK_C_VerifyInit sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_VerifyInit)GetProcAddress(hPK11, "C_VerifyInit"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pMechanism, hKey); +} + +CK_RV +pkcs_C_Verify(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen) +{ + static CK_C_Verify sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_Verify)GetProcAddress(hPK11, "C_Verify"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pData, ulDataLen, pSignature, ulSignatureLen); +} + +CK_RV +pkcs_C_VerifyUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen) +{ + static CK_C_VerifyUpdate sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_VerifyUpdate)GetProcAddress(hPK11, + "C_VerifyUpdate"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pPart, ulPartLen); +} + +CK_RV +pkcs_C_VerifyFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen) +{ + static CK_C_VerifyFinal sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_VerifyFinal)GetProcAddress(hPK11, "C_VerifyFinal"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pSignature, ulSignatureLen); +} + +CK_RV +pkcs_C_GenerateKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey) +{ + static CK_C_GenerateKey sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_GenerateKey)GetProcAddress(hPK11, "C_GenerateKey"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pMechanism, pTemplate, ulCount, phKey); +} + +CK_RV +pkcs_C_GenerateKeyPair(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pPublicKeyTemplate, + CK_ULONG usPublicKeyAttributeCount, + CK_ATTRIBUTE_PTR pPrivateKeyTemplate, + CK_ULONG usPrivateKeyAttributeCount, + CK_OBJECT_HANDLE_PTR phPrivateKey, + CK_OBJECT_HANDLE_PTR phPublicKey) +{ + static CK_C_GenerateKeyPair sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_GenerateKeyPair)GetProcAddress(hPK11, + "C_GenerateKeyPair"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, + pMechanism, + pPublicKeyTemplate, + usPublicKeyAttributeCount, + pPrivateKeyTemplate, + usPrivateKeyAttributeCount, + phPrivateKey, + phPublicKey); +} + +CK_RV +pkcs_C_DeriveKey(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hBaseKey, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_OBJECT_HANDLE_PTR phKey) +{ + static CK_C_DeriveKey sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_DeriveKey)GetProcAddress(hPK11, "C_DeriveKey"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, + pMechanism, + hBaseKey, + pTemplate, + ulAttributeCount, + phKey); +} + +CK_RV +pkcs_C_SeedRandom(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSeed, + CK_ULONG ulSeedLen) +{ + static CK_C_SeedRandom sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_SeedRandom)GetProcAddress(hPK11, "C_SeedRandom"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, pSeed, ulSeedLen); +} + +CK_RV +pkcs_C_GenerateRandom(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR RandomData, + CK_ULONG ulRandomLen) +{ + static CK_C_GenerateRandom sym = NULL; + + if (hPK11 == NULL) + return (CKR_LIBRARY_FAILED_TO_LOAD); + if (sym == NULL) + sym = (CK_C_GenerateRandom)GetProcAddress(hPK11, + "C_GenerateRandom"); + if (sym == NULL) + return (CKR_SYMBOL_RESOLUTION_FAILED); + return (*sym)(hSession, RandomData, ulRandomLen); +} diff --git a/lib/isc/win32/resource.c b/lib/isc/win32/resource.c new file mode 100644 index 0000000..0fbc9a4 --- /dev/null +++ b/lib/isc/win32/resource.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include + +#include + +#include +#include +#include +#include + +#include "errno2result.h" + +/* + * Windows limits the maximum number of open files to 2048 + */ + +#define WIN32_MAX_OPEN_FILES 2048 + +isc_result_t +isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) { + isc_resourcevalue_t rlim_value; + int wresult; + + if (resource != isc_resource_openfiles) + return (ISC_R_NOTIMPLEMENTED); + + + if (value == ISC_RESOURCE_UNLIMITED) + rlim_value = WIN32_MAX_OPEN_FILES; + else + rlim_value = min(value, WIN32_MAX_OPEN_FILES); + + wresult = _setmaxstdio((int) rlim_value); + + if (wresult > 0) + return (ISC_R_SUCCESS); + else + return (isc__errno2result(errno)); +} + +isc_result_t +isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) { + + if (resource != isc_resource_openfiles) + return (ISC_R_NOTIMPLEMENTED); + + *value = WIN32_MAX_OPEN_FILES; + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) { + return (isc_resource_getlimit(resource, value)); +} diff --git a/lib/isc/win32/socket.c b/lib/isc/win32/socket.c new file mode 100644 index 0000000..75b1c26 --- /dev/null +++ b/lib/isc/win32/socket.c @@ -0,0 +1,4277 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* This code uses functions which are only available on Server 2003 and + * higher, and Windows XP and higher. + * + * This code is by nature multithreaded and takes advantage of various + * features to pass on information through the completion port for + * when I/O is completed. All sends, receives, accepts, and connects are + * completed through the completion port. + * + * The number of Completion Port Worker threads used is the total number + * of CPU's + 1. This increases the likelihood that a Worker Thread is + * available for processing a completed request. + * + * XXXPDM 5 August, 2002 + */ + +#include + +#define MAKE_EXTERNAL 1 + +#include + +#ifndef _WINSOCKAPI_ +#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "errno2result.h" + +/* + * Set by the -T dscp option on the command line. If set to a value + * other than -1, we check to make sure DSCP values match it, and + * assert if not. + */ +LIBISC_EXTERNAL_DATA int isc_dscp_check_value = -1; + +/* + * How in the world can Microsoft exist with APIs like this? + * We can't actually call this directly, because it turns out + * no library exports this function. Instead, we need to + * issue a runtime call to get the address. + */ +LPFN_CONNECTEX ISCConnectEx; +LPFN_ACCEPTEX ISCAcceptEx; +LPFN_GETACCEPTEXSOCKADDRS ISCGetAcceptExSockaddrs; + +/* + * Run expensive internal consistency checks. + */ +#ifdef ISC_SOCKET_CONSISTENCY_CHECKS +#define CONSISTENT(sock) consistent(sock) +#else +#define CONSISTENT(sock) do {} while (0) +#endif +static void consistent(isc_socket_t *sock); + +/* + * Define this macro to control the behavior of connection + * resets on UDP sockets. See Microsoft KnowledgeBase Article Q263823 + * for details. + * NOTE: This requires that Windows 2000 systems install Service Pack 2 + * or later. + */ +#ifndef SIO_UDP_CONNRESET +#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) +#endif + +/* + * Some systems define the socket length argument as an int, some as size_t, + * some as socklen_t. This is here so it can be easily changed if needed. + */ +#ifndef ISC_SOCKADDR_LEN_T +#define ISC_SOCKADDR_LEN_T unsigned int +#endif + +/* + * Define what the possible "soft" errors can be. These are non-fatal returns + * of various network related functions, like recv() and so on. + */ +#define SOFT_ERROR(e) ((e) == WSAEINTR || \ + (e) == WSAEWOULDBLOCK || \ + (e) == EWOULDBLOCK || \ + (e) == EINTR || \ + (e) == EAGAIN || \ + (e) == 0) + +/* + * Pending errors are not really errors and should be + * kept separate + */ +#define PENDING_ERROR(e) ((e) == WSA_IO_PENDING || (e) == 0) + +#define DOIO_SUCCESS 0 /* i/o ok, event sent */ +#define DOIO_SOFT 1 /* i/o ok, soft error, no event sent */ +#define DOIO_HARD 2 /* i/o error, event sent */ +#define DOIO_EOF 3 /* EOF, no event sent */ +#define DOIO_PENDING 4 /* status when i/o is in process */ +#define DOIO_NEEDMORE 5 /* IO was processed, but we need more due to minimum */ + +#define DLVL(x) ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(x) + +/* + * DLVL(90) -- Function entry/exit and other tracing. + * DLVL(70) -- Socket "correctness" -- including returning of events, etc. + * DLVL(60) -- Socket data send/receive + * DLVL(50) -- Event tracing, including receiving/sending completion events. + * DLVL(20) -- Socket creation/destruction. + */ +#define TRACE_LEVEL 90 +#define CORRECTNESS_LEVEL 70 +#define IOEVENT_LEVEL 60 +#define EVENT_LEVEL 50 +#define CREATION_LEVEL 20 + +#define TRACE DLVL(TRACE_LEVEL) +#define CORRECTNESS DLVL(CORRECTNESS_LEVEL) +#define IOEVENT DLVL(IOEVENT_LEVEL) +#define EVENT DLVL(EVENT_LEVEL) +#define CREATION DLVL(CREATION_LEVEL) + +typedef isc_event_t intev_t; + +/* + * Socket State + */ +enum { + SOCK_INITIALIZED, /* Socket Initialized */ + SOCK_OPEN, /* Socket opened but nothing yet to do */ + SOCK_DATA, /* Socket sending or receiving data */ + SOCK_LISTEN, /* TCP Socket listening for connects */ + SOCK_ACCEPT, /* TCP socket is waiting to accept */ + SOCK_CONNECT, /* TCP Socket connecting */ + SOCK_CLOSED, /* Socket has been closed */ +}; + +#define SOCKET_MAGIC ISC_MAGIC('I', 'O', 'i', 'o') +#define VALID_SOCKET(t) ISC_MAGIC_VALID(t, SOCKET_MAGIC) + +/* + * IPv6 control information. If the socket is an IPv6 socket we want + * to collect the destination address and interface so the client can + * set them on outgoing packets. + */ +#ifdef ISC_PLATFORM_HAVEIPV6 +#ifndef USE_CMSG +#define USE_CMSG 1 +#endif +#endif + +/* + * We really don't want to try and use these control messages. Win32 + * doesn't have this mechanism before XP. + */ +#undef USE_CMSG + +/* + * Message header for recvmsg and sendmsg calls. + * Used value-result for recvmsg, value only for sendmsg. + */ +struct msghdr { + SOCKADDR_STORAGE to_addr; /* UDP send/recv address */ + int to_addr_len; /* length of the address */ + WSABUF *msg_iov; /* scatter/gather array */ + u_int msg_iovlen; /* # elements in msg_iov */ + void *msg_control; /* ancillary data, see below */ + u_int msg_controllen; /* ancillary data buffer len */ + u_int msg_totallen; /* total length of this message */ +} msghdr; + +/* + * The size to raise the receive buffer to. + */ +#define RCVBUFSIZE (32*1024) + +/* + * The number of times a send operation is repeated if the result + * is WSAEINTR. + */ +#define NRETRIES 10 + +struct isc_socket { + /* Not locked. */ + unsigned int magic; + isc_socketmgr_t *manager; + isc_mutex_t lock; + isc_sockettype_t type; + + /* Pointers to scatter/gather buffers */ + WSABUF iov[ISC_SOCKET_MAXSCATTERGATHER]; + + /* Locked by socket lock. */ + ISC_LINK(isc_socket_t) link; + unsigned int references; /* EXTERNAL references */ + SOCKET fd; /* file handle */ + int pf; /* protocol family */ + char name[16]; + void * tag; + + /* + * Each recv() call uses this buffer. It is a per-socket receive + * buffer that allows us to decouple the system recv() from the + * recv_list done events. This means the items on the recv_list + * can be removed without having to cancel pending system recv() + * calls. It also allows us to read-ahead in some cases. + */ + struct { + SOCKADDR_STORAGE from_addr; // UDP send/recv address + int from_addr_len; // length of the address + char *base; // the base of the buffer + char *consume_position; // where to start copying data from next + unsigned int len; // the actual size of this buffer + unsigned int remaining; // the number of bytes remaining + } recvbuf; + + ISC_LIST(isc_socketevent_t) send_list; + ISC_LIST(isc_socketevent_t) recv_list; + ISC_LIST(isc_socket_newconnev_t) accept_list; + ISC_LIST(isc_socket_connev_t) connect_list; + + isc_sockaddr_t address; /* remote address */ + + unsigned int listener : 1, /* listener socket */ + connected : 1, + pending_connect : 1, /* connect pending */ + bound : 1, /* bound to local addr */ + dupped : 1; /* created by isc_socket_dup() */ + unsigned int pending_iocp; /* Should equal the counters below. Debug. */ + unsigned int pending_recv; /* Number of outstanding recv() calls. */ + unsigned int pending_send; /* Number of outstanding send() calls. */ + unsigned int pending_accept; /* Number of outstanding accept() calls. */ + unsigned int state; /* Socket state. Debugging and consistency checking. */ + int state_lineno; /* line which last touched state */ +}; + +#define _set_state(sock, _state) do { (sock)->state = (_state); (sock)->state_lineno = __LINE__; } while (0) + +/* + * Buffer structure + */ +typedef struct buflist buflist_t; + +struct buflist { + void *buf; + unsigned int buflen; + ISC_LINK(buflist_t) link; +}; + +/* + * I/O Completion ports Info structures + */ + +static HANDLE hHeapHandle = NULL; +typedef struct IoCompletionInfo { + OVERLAPPED overlapped; + isc_socketevent_t *dev; /* send()/recv() done event */ + isc_socket_connev_t *cdev; /* connect() done event */ + isc_socket_newconnev_t *adev; /* accept() done event */ + void *acceptbuffer; + DWORD received_bytes; + int request_type; + struct msghdr messagehdr; + ISC_LIST(buflist_t) bufferlist; /*%< list of buffers */ +} IoCompletionInfo; + +/* + * Define a maximum number of I/O Completion Port worker threads + * to handle the load on the Completion Port. The actual number + * used is the number of CPU's + 1. + */ +#define MAX_IOCPTHREADS 20 + +#define SOCKET_MANAGER_MAGIC ISC_MAGIC('I', 'O', 'm', 'g') +#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, SOCKET_MANAGER_MAGIC) + +struct isc_socketmgr { + /* Not locked. */ + unsigned int magic; + isc_mem_t *mctx; + isc_mutex_t lock; + isc_stats_t *stats; + + /* Locked by manager lock. */ + ISC_LIST(isc_socket_t) socklist; + bool bShutdown; + isc_condition_t shutdown_ok; + HANDLE hIoCompletionPort; + int maxIOCPThreads; + HANDLE hIOCPThreads[MAX_IOCPTHREADS]; + DWORD dwIOCPThreadIds[MAX_IOCPTHREADS]; + + /* + * Debugging. + * Modified by InterlockedIncrement() and InterlockedDecrement() + */ + LONG totalSockets; + LONG iocp_total; +}; + +enum { + SOCKET_RECV, + SOCKET_SEND, + SOCKET_ACCEPT, + SOCKET_CONNECT +}; + +/* + * send() and recv() iovec counts + */ +#define MAXSCATTERGATHER_SEND (ISC_SOCKET_MAXSCATTERGATHER) +#define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER) + +static isc_result_t socket_create(isc_socketmgr_t *manager0, int pf, + isc_sockettype_t type, + isc_socket_t **socketp, + isc_socket_t *dup_socket); +static isc_threadresult_t WINAPI SocketIoThread(LPVOID ThreadContext); +static void maybe_free_socket(isc_socket_t **, int); +static void free_socket(isc_socket_t **, int); +static bool senddone_is_active(isc_socket_t *sock, isc_socketevent_t *dev); +static bool acceptdone_is_active(isc_socket_t *sock, isc_socket_newconnev_t *dev); +static bool connectdone_is_active(isc_socket_t *sock, isc_socket_connev_t *dev); +static void send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev); +static void send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev); +static void send_acceptdone_event(isc_socket_t *sock, isc_socket_newconnev_t **adev); +static void send_connectdone_event(isc_socket_t *sock, isc_socket_connev_t **cdev); +static void send_recvdone_abort(isc_socket_t *sock, isc_result_t result); +static void send_connectdone_abort(isc_socket_t *sock, isc_result_t result); +static void queue_receive_event(isc_socket_t *sock, isc_task_t *task, isc_socketevent_t *dev); +static void queue_receive_request(isc_socket_t *sock); + +/* + * This is used to dump the contents of the sock structure + * You should make sure that the sock is locked before + * dumping it. Since the code uses simple printf() statements + * it should only be used interactively. + */ +void +sock_dump(isc_socket_t *sock) { + isc_socketevent_t *ldev; + isc_socket_newconnev_t *ndev; + isc_socket_connev_t *cdev; + +#if 0 + isc_sockaddr_t addr; + char socktext[ISC_SOCKADDR_FORMATSIZE]; + isc_result_t result; + + result = isc_socket_getpeername(sock, &addr); + if (result == ISC_R_SUCCESS) { + isc_sockaddr_format(&addr, socktext, sizeof(socktext)); + printf("Remote Socket: %s\n", socktext); + } + result = isc_socket_getsockname(sock, &addr); + if (result == ISC_R_SUCCESS) { + isc_sockaddr_format(&addr, socktext, sizeof(socktext)); + printf("This Socket: %s\n", socktext); + } +#endif + + printf("\n\t\tSock Dump\n"); + printf("\t\tfd: %Iu\n", sock->fd); + printf("\t\treferences: %u\n", sock->references); + printf("\t\tpending_accept: %u\n", sock->pending_accept); + printf("\t\tconnecting: %u\n", sock->pending_connect); + printf("\t\tconnected: %u\n", sock->connected); + printf("\t\tbound: %u\n", sock->bound); + printf("\t\tpending_iocp: %u\n", sock->pending_iocp); + printf("\t\tsocket type: %d\n", sock->type); + + printf("\n\t\tSock Recv List\n"); + ldev = ISC_LIST_HEAD(sock->recv_list); + while (ldev != NULL) { + printf("\t\tdev: %p\n", ldev); + ldev = ISC_LIST_NEXT(ldev, ev_link); + } + + printf("\n\t\tSock Send List\n"); + ldev = ISC_LIST_HEAD(sock->send_list); + while (ldev != NULL) { + printf("\t\tdev: %p\n", ldev); + ldev = ISC_LIST_NEXT(ldev, ev_link); + } + + printf("\n\t\tSock Accept List\n"); + ndev = ISC_LIST_HEAD(sock->accept_list); + while (ndev != NULL) { + printf("\t\tdev: %p\n", ldev); + ndev = ISC_LIST_NEXT(ndev, ev_link); + } + + printf("\n\t\tSock Connect List\n"); + cdev = ISC_LIST_HEAD(sock->connect_list); + while (cdev != NULL) { + printf("\t\tdev: %p\n", cdev); + cdev = ISC_LIST_NEXT(cdev, ev_link); + } +} + +static void +socket_log(int lineno, isc_socket_t *sock, isc_sockaddr_t *address, + isc_logcategory_t *category, isc_logmodule_t *module, int level, + isc_msgcat_t *msgcat, int msgset, int message, + const char *fmt, ...) ISC_FORMAT_PRINTF(9, 10); + +/* This function will add an entry to the I/O completion port + * that will signal the I/O thread to exit (gracefully) + */ +static void +signal_iocompletionport_exit(isc_socketmgr_t *manager) { + int i; + int errval; + char strbuf[ISC_STRERRORSIZE]; + + REQUIRE(VALID_MANAGER(manager)); + for (i = 0; i < manager->maxIOCPThreads; i++) { + if (!PostQueuedCompletionStatus(manager->hIoCompletionPort, + 0, 0, 0)) { + errval = GetLastError(); + isc__strerror(errval, strbuf, sizeof(strbuf)); + FATAL_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_FAILED, + "Can't request service thread to exit: %s"), + strbuf); + } + } +} + +/* + * Create the worker threads for the I/O Completion Port + */ +void +iocompletionport_createthreads(int total_threads, isc_socketmgr_t *manager) { + int errval; + char strbuf[ISC_STRERRORSIZE]; + int i; + + INSIST(total_threads > 0); + REQUIRE(VALID_MANAGER(manager)); + /* + * We need at least one + */ + for (i = 0; i < total_threads; i++) { + manager->hIOCPThreads[i] = CreateThread(NULL, 0, SocketIoThread, + manager, 0, + &manager->dwIOCPThreadIds[i]); + if (manager->hIOCPThreads[i] == NULL) { + errval = GetLastError(); + isc__strerror(errval, strbuf, sizeof(strbuf)); + FATAL_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_FAILED, + "Can't create IOCP thread: %s"), + strbuf); + } + } +} + +/* + * Create/initialise the I/O completion port + */ +void +iocompletionport_init(isc_socketmgr_t *manager) { + int errval; + char strbuf[ISC_STRERRORSIZE]; + + REQUIRE(VALID_MANAGER(manager)); + /* + * Create a private heap to handle the socket overlapped structure + * The minimum number of structures is 10, there is no maximum + */ + hHeapHandle = HeapCreate(0, 10 * sizeof(IoCompletionInfo), 0); + if (hHeapHandle == NULL) { + errval = GetLastError(); + isc__strerror(errval, strbuf, sizeof(strbuf)); + FATAL_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_FAILED, + "HeapCreate() failed during " + "initialization: %s"), + strbuf); + } + + manager->maxIOCPThreads = min(isc_os_ncpus() + 1, MAX_IOCPTHREADS); + + /* Now Create the Completion Port */ + manager->hIoCompletionPort = CreateIoCompletionPort( + INVALID_HANDLE_VALUE, NULL, + 0, manager->maxIOCPThreads); + if (manager->hIoCompletionPort == NULL) { + errval = GetLastError(); + isc__strerror(errval, strbuf, sizeof(strbuf)); + FATAL_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_FAILED, + "CreateIoCompletionPort() failed " + "during initialization: %s"), + strbuf); + } + + /* + * Worker threads for servicing the I/O + */ + iocompletionport_createthreads(manager->maxIOCPThreads, manager); +} + +/* + * Associate a socket with an IO Completion Port. This allows us to queue events for it + * and have our worker pool of threads process them. + */ +void +iocompletionport_update(isc_socket_t *sock) { + HANDLE hiocp; + char strbuf[ISC_STRERRORSIZE]; + + REQUIRE(VALID_SOCKET(sock)); + + hiocp = CreateIoCompletionPort((HANDLE)sock->fd, + sock->manager->hIoCompletionPort, (ULONG_PTR)sock, 0); + + if (hiocp == NULL) { + DWORD errval = GetLastError(); + isc__strerror(errval, strbuf, sizeof(strbuf)); + isc_log_iwrite(isc_lctx, + ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, + isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_TOOMANYHANDLES, + "iocompletionport_update: failed to open" + " io completion port: %s", + strbuf); + + /* XXXMLG temporary hack to make failures detected. + * This function should return errors to the caller, not + * exit here. + */ + FATAL_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_FAILED, + "CreateIoCompletionPort() failed " + "during initialization: %s"), + strbuf); + } + + InterlockedIncrement(&sock->manager->iocp_total); +} + +/* + * Routine to cleanup and then close the socket. + * Only close the socket here if it is NOT associated + * with an event, otherwise the WSAWaitForMultipleEvents + * may fail due to the fact that the Wait should not + * be running while closing an event or a socket. + * The socket is locked before calling this function + */ +void +socket_close(isc_socket_t *sock) { + + REQUIRE(sock != NULL); + + if (sock->fd != INVALID_SOCKET) { + closesocket(sock->fd); + sock->fd = INVALID_SOCKET; + _set_state(sock, SOCK_CLOSED); + InterlockedDecrement(&sock->manager->totalSockets); + } +} + +static isc_once_t initialise_once = ISC_ONCE_INIT; +static bool initialised = false; + +static void +initialise(void) { + WORD wVersionRequested; + WSADATA wsaData; + int err; + SOCKET sock; + GUID GUIDConnectEx = WSAID_CONNECTEX; + GUID GUIDAcceptEx = WSAID_ACCEPTEX; + GUID GUIDGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS; + DWORD dwBytes; + + /* Need Winsock 2.2 or better */ + wVersionRequested = MAKEWORD(2, 2); + + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) { + char strbuf[ISC_STRERRORSIZE]; + isc__strerror(err, strbuf, sizeof(strbuf)); + FATAL_ERROR(__FILE__, __LINE__, "WSAStartup() %s: %s", + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, "failed"), + strbuf); + } + /* + * The following APIs do not exist as functions in a library, but + * we must ask winsock for them. They are "extensions" -- but why + * they cannot be actual functions is beyond me. So, ask winsock + * for the pointers to the functions we need. + */ + sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + INSIST(sock != INVALID_SOCKET); + err = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, + &GUIDConnectEx, sizeof(GUIDConnectEx), + &ISCConnectEx, sizeof(ISCConnectEx), + &dwBytes, NULL, NULL); + INSIST(err == 0); + + err = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, + &GUIDAcceptEx, sizeof(GUIDAcceptEx), + &ISCAcceptEx, sizeof(ISCAcceptEx), + &dwBytes, NULL, NULL); + INSIST(err == 0); + + err = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, + &GUIDGetAcceptExSockaddrs, sizeof(GUIDGetAcceptExSockaddrs), + &ISCGetAcceptExSockaddrs, sizeof(ISCGetAcceptExSockaddrs), + &dwBytes, NULL, NULL); + INSIST(err == 0); + + closesocket(sock); + + initialised = true; +} + +/* + * Initialize socket services + */ +void +InitSockets(void) { + RUNTIME_CHECK(isc_once_do(&initialise_once, + initialise) == ISC_R_SUCCESS); + if (!initialised) + exit(1); +} + +int +internal_sendmsg(isc_socket_t *sock, IoCompletionInfo *lpo, + struct msghdr *messagehdr, int flags, int *Error) +{ + int Result; + DWORD BytesSent; + DWORD Flags = flags; + int total_sent; + + *Error = 0; + Result = WSASendTo(sock->fd, messagehdr->msg_iov, + messagehdr->msg_iovlen, &BytesSent, + Flags, (SOCKADDR *)&messagehdr->to_addr, + messagehdr->to_addr_len, (LPWSAOVERLAPPED)lpo, + NULL); + + total_sent = (int)BytesSent; + + /* Check for errors.*/ + if (Result == SOCKET_ERROR) { + *Error = WSAGetLastError(); + + switch (*Error) { + case WSA_IO_INCOMPLETE: + case WSA_WAIT_IO_COMPLETION: + case WSA_IO_PENDING: + case NO_ERROR: /* Strange, but okay */ + sock->pending_iocp++; + sock->pending_send++; + break; + + default: + return (-1); + break; + } + } else { + sock->pending_iocp++; + sock->pending_send++; + } + + if (lpo != NULL) + return (0); + else + return (total_sent); +} + +static void +queue_receive_request(isc_socket_t *sock) { + DWORD Flags = 0; + DWORD NumBytes = 0; + int Result; + int Error; + int need_retry; + WSABUF iov[1]; + IoCompletionInfo *lpo = NULL; + isc_result_t isc_result; + + retry: + need_retry = false; + + /* + * If we already have a receive pending, do nothing. + */ + if (sock->pending_recv > 0) { + if (lpo != NULL) + HeapFree(hHeapHandle, 0, lpo); + return; + } + + /* + * If no one is waiting, do nothing. + */ + if (ISC_LIST_EMPTY(sock->recv_list)) { + if (lpo != NULL) + HeapFree(hHeapHandle, 0, lpo); + return; + } + + INSIST(sock->recvbuf.remaining == 0); + INSIST(sock->fd != INVALID_SOCKET); + + iov[0].len = sock->recvbuf.len; + iov[0].buf = sock->recvbuf.base; + + if (lpo == NULL) { + lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle, + HEAP_ZERO_MEMORY, + sizeof(IoCompletionInfo)); + RUNTIME_CHECK(lpo != NULL); + } else + ZeroMemory(lpo, sizeof(IoCompletionInfo)); + lpo->request_type = SOCKET_RECV; + + sock->recvbuf.from_addr_len = sizeof(sock->recvbuf.from_addr); + + Error = 0; + Result = WSARecvFrom((SOCKET)sock->fd, iov, 1, + &NumBytes, &Flags, + (SOCKADDR *)&sock->recvbuf.from_addr, + &sock->recvbuf.from_addr_len, + (LPWSAOVERLAPPED)lpo, NULL); + + /* Check for errors. */ + if (Result == SOCKET_ERROR) { + Error = WSAGetLastError(); + + switch (Error) { + case WSA_IO_PENDING: + sock->pending_iocp++; + sock->pending_recv++; + break; + + /* direct error: no completion event */ + case ERROR_HOST_UNREACHABLE: + case WSAENETRESET: + case WSAECONNRESET: + if (!sock->connected) { + /* soft error */ + need_retry = true; + break; + } + /* FALLTHROUGH */ + + default: + isc_result = isc__errno2result(Error); + if (isc_result == ISC_R_UNEXPECTED) + UNEXPECTED_ERROR(__FILE__, __LINE__, + "WSARecvFrom: Windows error code: %d, isc result %d", + Error, isc_result); + send_recvdone_abort(sock, isc_result); + HeapFree(hHeapHandle, 0, lpo); + lpo = NULL; + break; + } + } else { + /* + * The recv() finished immediately, but we will still get + * a completion event. Rather than duplicate code, let + * that thread handle sending the data along its way. + */ + sock->pending_iocp++; + sock->pending_recv++; + } + + socket_log(__LINE__, sock, NULL, IOEVENT, + isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_DOIORECV, + "queue_io_request: fd %d result %d error %d", + sock->fd, Result, Error); + + CONSISTENT(sock); + + if (need_retry) + goto retry; +} + +static void +manager_log(isc_socketmgr_t *sockmgr, isc_logcategory_t *category, + isc_logmodule_t *module, int level, const char *fmt, ...) +{ + char msgbuf[2048]; + va_list ap; + + if (!isc_log_wouldlog(isc_lctx, level)) + return; + + va_start(ap, fmt); + vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); + va_end(ap); + + isc_log_write(isc_lctx, category, module, level, + "sockmgr %p: %s", sockmgr, msgbuf); +} + +static void +socket_log(int lineno, isc_socket_t *sock, isc_sockaddr_t *address, + isc_logcategory_t *category, isc_logmodule_t *module, int level, + isc_msgcat_t *msgcat, int msgset, int message, + const char *fmt, ...) +{ + char msgbuf[2048]; + char peerbuf[256]; + va_list ap; + + + if (!isc_log_wouldlog(isc_lctx, level)) + return; + + va_start(ap, fmt); + vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); + va_end(ap); + + if (address == NULL) { + isc_log_iwrite(isc_lctx, category, module, level, + msgcat, msgset, message, + "socket %p line %d: %s", sock, lineno, msgbuf); + } else { + isc_sockaddr_format(address, peerbuf, sizeof(peerbuf)); + isc_log_iwrite(isc_lctx, category, module, level, + msgcat, msgset, message, + "socket %p line %d %s: %s", sock, lineno, + peerbuf, msgbuf); + } + +} + +/* + * Make an fd SOCKET non-blocking. + */ +static isc_result_t +make_nonblock(SOCKET fd) { + int ret; + unsigned long flags = 1; + char strbuf[ISC_STRERRORSIZE]; + + /* Set the socket to non-blocking */ + ret = ioctlsocket(fd, FIONBIO, &flags); + + if (ret == -1) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "ioctlsocket(%d, FIOBIO, %d): %s", + fd, flags, strbuf); + + return (ISC_R_UNEXPECTED); + } + + return (ISC_R_SUCCESS); +} + +/* + * Windows 2000 systems incorrectly cause UDP sockets using WSARecvFrom + * to not work correctly, returning a WSACONNRESET error when a WSASendTo + * fails with an "ICMP port unreachable" response and preventing the + * socket from using the WSARecvFrom in subsequent operations. + * The function below fixes this, but requires that Windows 2000 + * Service Pack 2 or later be installed on the system. NT 4.0 + * systems are not affected by this and work correctly. + * See Microsoft Knowledge Base Article Q263823 for details of this. + */ +isc_result_t +connection_reset_fix(SOCKET fd) { + DWORD dwBytesReturned = 0; + BOOL bNewBehavior = FALSE; + DWORD status; + + if (isc_win32os_versioncheck(5, 0, 0, 0) < 0) + return (ISC_R_SUCCESS); /* NT 4.0 has no problem */ + + /* disable bad behavior using IOCTL: SIO_UDP_CONNRESET */ + status = WSAIoctl(fd, SIO_UDP_CONNRESET, &bNewBehavior, + sizeof(bNewBehavior), NULL, 0, + &dwBytesReturned, NULL, NULL); + if (status != SOCKET_ERROR) + return (ISC_R_SUCCESS); + else { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "WSAIoctl(SIO_UDP_CONNRESET, oldBehaviour) %s", + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, "failed")); + return (ISC_R_UNEXPECTED); + } +} + +/* + * Construct an iov array and attach it to the msghdr passed in. This is + * the SEND constructor, which will use the used region of the buffer + * (if using a buffer list) or will use the internal region (if a single + * buffer I/O is requested). + * + * Nothing can be NULL, and the done event must list at least one buffer + * on the buffer linked list for this function to be meaningful. + */ +static void +build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev, + struct msghdr *msg, char *cmsg, WSABUF *iov, + IoCompletionInfo *lpo) +{ + unsigned int iovcount; + isc_buffer_t *buffer; + buflist_t *cpbuffer; + isc_region_t used; + size_t write_count; + size_t skip_count; + + memset(msg, 0, sizeof(*msg)); + + memmove(&msg->to_addr, &dev->address.type, dev->address.length); + msg->to_addr_len = dev->address.length; + + buffer = ISC_LIST_HEAD(dev->bufferlist); + write_count = 0; + iovcount = 0; + + /* + * Single buffer I/O? Skip what we've done so far in this region. + */ + if (buffer == NULL) { + write_count = dev->region.length - dev->n; + cpbuffer = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, sizeof(buflist_t)); + RUNTIME_CHECK(cpbuffer != NULL); + cpbuffer->buf = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, write_count); + RUNTIME_CHECK(cpbuffer->buf != NULL); + + socket_log(__LINE__, sock, NULL, TRACE, + isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK, + "alloc_buffer %p %d %p %d", cpbuffer, sizeof(buflist_t), + cpbuffer->buf, write_count); + + memmove(cpbuffer->buf,(dev->region.base + dev->n), write_count); + cpbuffer->buflen = (unsigned int)write_count; + ISC_LINK_INIT(cpbuffer, link); + ISC_LIST_ENQUEUE(lpo->bufferlist, cpbuffer, link); + iov[0].buf = cpbuffer->buf; + iov[0].len = (u_long)write_count; + iovcount = 1; + + goto config; + } + + /* + * Multibuffer I/O. + * Skip the data in the buffer list that we have already written. + */ + skip_count = dev->n; + while (buffer != NULL) { + REQUIRE(ISC_BUFFER_VALID(buffer)); + if (skip_count < isc_buffer_usedlength(buffer)) + break; + skip_count -= isc_buffer_usedlength(buffer); + buffer = ISC_LIST_NEXT(buffer, link); + } + + while (buffer != NULL) { + INSIST(iovcount < MAXSCATTERGATHER_SEND); + + isc_buffer_usedregion(buffer, &used); + + if (used.length > 0) { + int uselen = (int)(used.length - skip_count); + cpbuffer = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, sizeof(buflist_t)); + RUNTIME_CHECK(cpbuffer != NULL); + cpbuffer->buf = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, uselen); + RUNTIME_CHECK(cpbuffer->buf != NULL); + + socket_log(__LINE__, sock, NULL, TRACE, + isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK, + "alloc_buffer %p %d %p %d", cpbuffer, sizeof(buflist_t), + cpbuffer->buf, write_count); + + memmove(cpbuffer->buf,(used.base + skip_count), uselen); + cpbuffer->buflen = uselen; + iov[iovcount].buf = cpbuffer->buf; + iov[iovcount].len = (u_long)(used.length - skip_count); + write_count += uselen; + skip_count = 0; + iovcount++; + } + buffer = ISC_LIST_NEXT(buffer, link); + } + + INSIST(skip_count == 0); + + config: + msg->msg_iov = iov; + msg->msg_iovlen = iovcount; + msg->msg_totallen = (u_int)write_count; +} + +static void +set_dev_address(isc_sockaddr_t *address, isc_socket_t *sock, + isc_socketevent_t *dev) +{ + if (sock->type == isc_sockettype_udp) { + if (address != NULL) + dev->address = *address; + else + dev->address = sock->address; + } else if (sock->type == isc_sockettype_tcp) { + INSIST(address == NULL); + dev->address = sock->address; + } +} + +static void +destroy_socketevent(isc_event_t *event) { + isc_socketevent_t *ev = (isc_socketevent_t *)event; + + INSIST(ISC_LIST_EMPTY(ev->bufferlist)); + + (ev->destroy)(event); +} + +static isc_socketevent_t * +allocate_socketevent(isc_mem_t *mctx, isc_socket_t *sock, + isc_eventtype_t eventtype, isc_taskaction_t action, + void *arg) +{ + isc_socketevent_t *ev; + + ev = (isc_socketevent_t *)isc_event_allocate(mctx, sock, eventtype, + action, arg, + sizeof(*ev)); + if (ev == NULL) + return (NULL); + + ev->result = ISC_R_IOERROR; // XXXMLG temporary change to detect failure to set + ISC_LINK_INIT(ev, ev_link); + ISC_LIST_INIT(ev->bufferlist); + ev->region.base = NULL; + ev->n = 0; + ev->offset = 0; + ev->attributes = 0; + ev->destroy = ev->ev_destroy; + ev->ev_destroy = destroy_socketevent; + ev->dscp = 0; + + return (ev); +} + +#if defined(ISC_SOCKET_DEBUG) +static void +dump_msg(struct msghdr *msg, isc_socket_t *sock) { + unsigned int i; + + printf("MSGHDR %p, Socket #: %Iu\n", msg, sock->fd); + printf("\tname %p, namelen %d\n", msg->msg_name, msg->msg_namelen); + printf("\tiov %p, iovlen %d\n", msg->msg_iov, msg->msg_iovlen); + for (i = 0; i < (unsigned int)msg->msg_iovlen; i++) + printf("\t\t%u\tbase %p, len %u\n", i, + msg->msg_iov[i].buf, msg->msg_iov[i].len); +} +#endif + +/* + * map the error code + */ +int +map_socket_error(isc_socket_t *sock, int windows_errno, int *isc_errno, + char *errorstring, size_t bufsize) { + + int doreturn; + switch (windows_errno) { + case WSAECONNREFUSED: + *isc_errno = ISC_R_CONNREFUSED; + if (sock->connected) + doreturn = DOIO_HARD; + else + doreturn = DOIO_SOFT; + break; + case WSAENETUNREACH: + case ERROR_NETWORK_UNREACHABLE: + *isc_errno = ISC_R_NETUNREACH; + if (sock->connected) + doreturn = DOIO_HARD; + else + doreturn = DOIO_SOFT; + break; + case ERROR_PORT_UNREACHABLE: + case ERROR_HOST_UNREACHABLE: + case WSAEHOSTUNREACH: + *isc_errno = ISC_R_HOSTUNREACH; + if (sock->connected) + doreturn = DOIO_HARD; + else + doreturn = DOIO_SOFT; + break; + case WSAENETDOWN: + *isc_errno = ISC_R_NETDOWN; + if (sock->connected) + doreturn = DOIO_HARD; + else + doreturn = DOIO_SOFT; + break; + case WSAEHOSTDOWN: + *isc_errno = ISC_R_HOSTDOWN; + if (sock->connected) + doreturn = DOIO_HARD; + else + doreturn = DOIO_SOFT; + break; + case WSAEACCES: + *isc_errno = ISC_R_NOPERM; + if (sock->connected) + doreturn = DOIO_HARD; + else + doreturn = DOIO_SOFT; + break; + case WSAECONNRESET: + case WSAENETRESET: + case WSAECONNABORTED: + case WSAEDISCON: + *isc_errno = ISC_R_CONNECTIONRESET; + if (sock->connected) + doreturn = DOIO_HARD; + else + doreturn = DOIO_SOFT; + break; + case WSAENOTCONN: + *isc_errno = ISC_R_NOTCONNECTED; + if (sock->connected) + doreturn = DOIO_HARD; + else + doreturn = DOIO_SOFT; + break; + case ERROR_OPERATION_ABORTED: + case ERROR_CONNECTION_ABORTED: + case ERROR_REQUEST_ABORTED: + *isc_errno = ISC_R_CONNECTIONRESET; + doreturn = DOIO_HARD; + break; + case WSAENOBUFS: + *isc_errno = ISC_R_NORESOURCES; + doreturn = DOIO_HARD; + break; + case WSAEAFNOSUPPORT: + *isc_errno = ISC_R_FAMILYNOSUPPORT; + doreturn = DOIO_HARD; + break; + case WSAEADDRNOTAVAIL: + *isc_errno = ISC_R_ADDRNOTAVAIL; + doreturn = DOIO_HARD; + break; + case WSAEDESTADDRREQ: + *isc_errno = ISC_R_BADADDRESSFORM; + doreturn = DOIO_HARD; + break; + case ERROR_NETNAME_DELETED: + *isc_errno = ISC_R_NETDOWN; + doreturn = DOIO_HARD; + break; + default: + *isc_errno = ISC_R_IOERROR; + doreturn = DOIO_HARD; + break; + } + if (doreturn == DOIO_HARD) { + isc__strerror(windows_errno, errorstring, bufsize); + } + return (doreturn); +} + +static void +fill_recv(isc_socket_t *sock, isc_socketevent_t *dev) { + isc_region_t r; + int copylen; + isc_buffer_t *buffer; + + INSIST(dev->n < dev->minimum); + INSIST(sock->recvbuf.remaining > 0); + INSIST(sock->pending_recv == 0); + + if (sock->type == isc_sockettype_udp) { + dev->address.length = sock->recvbuf.from_addr_len; + memmove(&dev->address.type, &sock->recvbuf.from_addr, + sock->recvbuf.from_addr_len); + if (isc_sockaddr_getport(&dev->address) == 0) { + if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) { + socket_log(__LINE__, sock, &dev->address, IOEVENT, + isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_ZEROPORT, + "dropping source port zero packet"); + } + sock->recvbuf.remaining = 0; + return; + } + } else if (sock->type == isc_sockettype_tcp) { + dev->address = sock->address; + } + + /* + * Run through the list of buffers we were given, and find the + * first one with space. Once it is found, loop through, filling + * the buffers as much as possible. + */ + buffer = ISC_LIST_HEAD(dev->bufferlist); + if (buffer != NULL) { // Multi-buffer receive + while (buffer != NULL && sock->recvbuf.remaining > 0) { + REQUIRE(ISC_BUFFER_VALID(buffer)); + if (isc_buffer_availablelength(buffer) > 0) { + isc_buffer_availableregion(buffer, &r); + copylen = min(r.length, + sock->recvbuf.remaining); + memmove(r.base, sock->recvbuf.consume_position, + copylen); + sock->recvbuf.consume_position += copylen; + sock->recvbuf.remaining -= copylen; + isc_buffer_add(buffer, copylen); + dev->n += copylen; + } + buffer = ISC_LIST_NEXT(buffer, link); + } + } else { // Single-buffer receive + copylen = min(dev->region.length - dev->n, sock->recvbuf.remaining); + memmove(dev->region.base + dev->n, + sock->recvbuf.consume_position, copylen); + sock->recvbuf.consume_position += copylen; + sock->recvbuf.remaining -= copylen; + dev->n += copylen; + } + + /* + * UDP receives are all-consuming. That is, if we have 4k worth of + * data in our receive buffer, and the caller only gave us + * 1k of space, we will toss the remaining 3k of data. TCP + * will keep the extra data around and use it for later requests. + */ + if (sock->type == isc_sockettype_udp) + sock->recvbuf.remaining = 0; +} + +/* + * Copy out as much data from the internal buffer to done events. + * As each done event is filled, send it along its way. + */ +static void +completeio_recv(isc_socket_t *sock) +{ + isc_socketevent_t *dev; + + /* + * If we are in the process of filling our buffer, we cannot + * touch it yet, so don't. + */ + if (sock->pending_recv > 0) + return; + + while (sock->recvbuf.remaining > 0 && !ISC_LIST_EMPTY(sock->recv_list)) { + dev = ISC_LIST_HEAD(sock->recv_list); + + /* + * See if we have sufficient data in our receive buffer + * to handle this. If we do, copy out the data. + */ + fill_recv(sock, dev); + + /* + * Did we satisfy it? + */ + if (dev->n >= dev->minimum) { + dev->result = ISC_R_SUCCESS; + send_recvdone_event(sock, &dev); + } + } +} + +/* + * Returns: + * DOIO_SUCCESS The operation succeeded. dev->result contains + * ISC_R_SUCCESS. + * + * DOIO_HARD A hard or unexpected I/O error was encountered. + * dev->result contains the appropriate error. + * + * DOIO_SOFT A soft I/O error was encountered. No senddone + * event was sent. The operation should be retried. + * + * No other return values are possible. + */ +static int +completeio_send(isc_socket_t *sock, isc_socketevent_t *dev, + struct msghdr *messagehdr, int cc, int send_errno) +{ + char strbuf[ISC_STRERRORSIZE]; + + if (send_errno != 0) { + if (SOFT_ERROR(send_errno)) + return (DOIO_SOFT); + + return (map_socket_error(sock, send_errno, &dev->result, + strbuf, sizeof(strbuf))); + } + + /* + * If we write less than we expected, update counters, poke. + */ + dev->n += cc; + if (cc != messagehdr->msg_totallen) + return (DOIO_SOFT); + + /* + * Exactly what we wanted to write. We're done with this + * entry. Post its completion event. + */ + dev->result = ISC_R_SUCCESS; + return (DOIO_SUCCESS); +} + +static int +startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes, + int *send_errno) +{ + char *cmsg = NULL; + char strbuf[ISC_STRERRORSIZE]; + IoCompletionInfo *lpo; + int status; + struct msghdr *mh; + + lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle, + HEAP_ZERO_MEMORY, + sizeof(IoCompletionInfo)); + RUNTIME_CHECK(lpo != NULL); + lpo->request_type = SOCKET_SEND; + lpo->dev = dev; + mh = &lpo->messagehdr; + memset(mh, 0, sizeof(struct msghdr)); + ISC_LIST_INIT(lpo->bufferlist); + + build_msghdr_send(sock, dev, mh, cmsg, sock->iov, lpo); + + *nbytes = internal_sendmsg(sock, lpo, mh, 0, send_errno); + + if (*nbytes <= 0) { + /* + * I/O has been initiated + * completion will be through the completion port + */ + if (PENDING_ERROR(*send_errno)) { + status = DOIO_PENDING; + goto done; + } + + if (SOFT_ERROR(*send_errno)) { + status = DOIO_SOFT; + goto done; + } + + /* + * If we got this far then something is wrong + */ + if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) { + isc__strerror(*send_errno, strbuf, sizeof(strbuf)); + socket_log(__LINE__, sock, NULL, IOEVENT, + isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_INTERNALSEND, + "startio_send: internal_sendmsg(%d) %d " + "bytes, err %d/%s", + sock->fd, *nbytes, *send_errno, strbuf); + } + status = DOIO_HARD; + goto done; + } + dev->result = ISC_R_SUCCESS; + status = DOIO_SOFT; + done: + _set_state(sock, SOCK_DATA); + return (status); +} + +static void +use_min_mtu(isc_socket_t *sock) { +#ifdef IPV6_USE_MIN_MTU + /* use minimum MTU */ + if (sock->pf == AF_INET6) { + int on = 1; + (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU, + (void *)&on, sizeof(on)); + } +#else + UNUSED(sock); +#endif +} + +static isc_result_t +allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, + isc_socket_t **socketp) { + isc_socket_t *sock; + isc_result_t result; + + sock = isc_mem_get(manager->mctx, sizeof(*sock)); + + if (sock == NULL) + return (ISC_R_NOMEMORY); + + sock->magic = 0; + sock->references = 0; + + sock->manager = manager; + sock->type = type; + sock->fd = INVALID_SOCKET; + + ISC_LINK_INIT(sock, link); + + /* + * Set up list of readers and writers to be initially empty. + */ + ISC_LIST_INIT(sock->recv_list); + ISC_LIST_INIT(sock->send_list); + ISC_LIST_INIT(sock->accept_list); + ISC_LIST_INIT(sock->connect_list); + sock->pending_accept = 0; + sock->pending_recv = 0; + sock->pending_send = 0; + sock->pending_iocp = 0; + sock->listener = 0; + sock->connected = 0; + sock->pending_connect = 0; + sock->bound = 0; + sock->dupped = 0; + memset(sock->name, 0, sizeof(sock->name)); // zero the name field + _set_state(sock, SOCK_INITIALIZED); + + sock->recvbuf.len = 65536; + sock->recvbuf.consume_position = sock->recvbuf.base; + sock->recvbuf.remaining = 0; + sock->recvbuf.base = isc_mem_get(manager->mctx, sock->recvbuf.len); // max buffer size + if (sock->recvbuf.base == NULL) { + result = ISC_R_NOMEMORY; + goto error; + } + + /* + * Initialize the lock. + */ + result = isc_mutex_init(&sock->lock); + if (result != ISC_R_SUCCESS) + goto error; + + socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0, + "allocated"); + + sock->magic = SOCKET_MAGIC; + *socketp = sock; + + return (ISC_R_SUCCESS); + + error: + if (sock->recvbuf.base != NULL) + isc_mem_put(manager->mctx, sock->recvbuf.base, sock->recvbuf.len); + isc_mem_put(manager->mctx, sock, sizeof(*sock)); + + return (result); +} + +/* + * Verify that the socket state is consistent. + */ +static void +consistent(isc_socket_t *sock) { + + isc_socketevent_t *dev; + isc_socket_newconnev_t *nev; + unsigned int count; + char *crash_reason; + bool crash = false; + + REQUIRE(sock->pending_iocp == sock->pending_recv + sock->pending_send + + sock->pending_accept + sock->pending_connect); + + dev = ISC_LIST_HEAD(sock->send_list); + count = 0; + while (dev != NULL) { + count++; + dev = ISC_LIST_NEXT(dev, ev_link); + } + if (count > sock->pending_send) { + crash = true; + crash_reason = "send_list > sock->pending_send"; + } + + nev = ISC_LIST_HEAD(sock->accept_list); + count = 0; + while (nev != NULL) { + count++; + nev = ISC_LIST_NEXT(nev, ev_link); + } + if (count > sock->pending_accept) { + crash = true; + crash_reason = "accept_list > sock->pending_accept"; + } + + if (crash) { + socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_DESTROYING, "SOCKET INCONSISTENT: %s", + crash_reason); + sock_dump(sock); + INSIST(crash == false); + } +} + +/* + * Maybe free the socket. + * + * This function will verify tht the socket is no longer in use in any way, + * either internally or externally. This is the only place where this + * check is to be made; if some bit of code believes that IT is done with + * the socket (e.g., some reference counter reaches zero), it should call + * this function. + * + * When calling this function, the socket must be locked, and the manager + * must be unlocked. + * + * When this function returns, *socketp will be NULL. No tricks to try + * to hold on to this pointer are allowed. + */ +static void +maybe_free_socket(isc_socket_t **socketp, int lineno) { + isc_socket_t *sock = *socketp; + *socketp = NULL; + + INSIST(VALID_SOCKET(sock)); + CONSISTENT(sock); + + if (sock->pending_iocp > 0 + || sock->pending_recv > 0 + || sock->pending_send > 0 + || sock->pending_accept > 0 + || sock->references > 0 + || sock->pending_connect == 1 + || !ISC_LIST_EMPTY(sock->recv_list) + || !ISC_LIST_EMPTY(sock->send_list) + || !ISC_LIST_EMPTY(sock->accept_list) + || !ISC_LIST_EMPTY(sock->connect_list) + || sock->fd != INVALID_SOCKET) { + UNLOCK(&sock->lock); + return; + } + UNLOCK(&sock->lock); + + free_socket(&sock, lineno); +} + +void +free_socket(isc_socket_t **sockp, int lineno) { + isc_socketmgr_t *manager; + isc_socket_t *sock = *sockp; + *sockp = NULL; + + /* + * Seems we can free the socket after all. + */ + manager = sock->manager; + socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, + ISC_MSGSET_SOCKET, ISC_MSG_DESTROYING, + "freeing socket line %d fd %d lock %p semaphore %p", + lineno, sock->fd, &sock->lock, sock->lock.LockSemaphore); + + sock->magic = 0; + DESTROYLOCK(&sock->lock); + + if (sock->recvbuf.base != NULL) + isc_mem_put(manager->mctx, sock->recvbuf.base, + sock->recvbuf.len); + + LOCK(&manager->lock); + if (ISC_LINK_LINKED(sock, link)) + ISC_LIST_UNLINK(manager->socklist, sock, link); + isc_mem_put(manager->mctx, sock, sizeof(*sock)); + + if (ISC_LIST_EMPTY(manager->socklist)) + SIGNAL(&manager->shutdown_ok); + UNLOCK(&manager->lock); +} + +/* + * Create a new 'type' socket managed by 'manager'. Events + * will be posted to 'task' and when dispatched 'action' will be + * called with 'arg' as the arg value. The new socket is returned + * in 'socketp'. + */ +static isc_result_t +socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, + isc_socket_t **socketp, isc_socket_t *dup_socket) +{ + isc_socket_t *sock = NULL; + isc_result_t result; +#if defined(USE_CMSG) + int on = 1; +#endif +#if defined(SO_RCVBUF) + ISC_SOCKADDR_LEN_T optlen; + int size; +#endif + int socket_errno; + char strbuf[ISC_STRERRORSIZE]; + + REQUIRE(VALID_MANAGER(manager)); + REQUIRE(socketp != NULL && *socketp == NULL); + REQUIRE(type != isc_sockettype_fdwatch); + +#ifndef SOCK_RAW + if (type == isc_sockettype_raw) + return (ISC_R_NOTIMPLEMENTED); +#endif + + result = allocate_socket(manager, type, &sock); + if (result != ISC_R_SUCCESS) + return (result); + + sock->pf = pf; + switch (type) { + case isc_sockettype_udp: + sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP); + if (sock->fd != INVALID_SOCKET) { + result = connection_reset_fix(sock->fd); + if (result != ISC_R_SUCCESS) { + socket_log(__LINE__, sock, + NULL, EVENT, NULL, 0, 0, + "closed %d %d %d " + "con_reset_fix_failed", + sock->pending_recv, + sock->pending_send, + sock->references); + closesocket(sock->fd); + _set_state(sock, SOCK_CLOSED); + sock->fd = INVALID_SOCKET; + free_socket(&sock, __LINE__); + return (result); + } + } + break; + case isc_sockettype_tcp: + sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP); + break; +#ifdef SOCK_RAW + case isc_sockettype_raw: + sock->fd = socket(pf, SOCK_RAW, 0); +#ifdef PF_ROUTE + if (pf == PF_ROUTE) + sock->bound = 1; +#endif + break; +#endif + } + + if (sock->fd == INVALID_SOCKET) { + socket_errno = WSAGetLastError(); + free_socket(&sock, __LINE__); + + switch (socket_errno) { + case WSAEMFILE: + case WSAENOBUFS: + return (ISC_R_NORESOURCES); + + case WSAEPROTONOSUPPORT: + case WSAEPFNOSUPPORT: + case WSAEAFNOSUPPORT: + return (ISC_R_FAMILYNOSUPPORT); + + default: + isc__strerror(socket_errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "socket() %s: %s", + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, + "failed"), + strbuf); + return (ISC_R_UNEXPECTED); + } + } + + result = make_nonblock(sock->fd); + if (result != ISC_R_SUCCESS) { + socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0, + "closed %d %d %d make_nonblock_failed", + sock->pending_recv, sock->pending_send, + sock->references); + closesocket(sock->fd); + sock->fd = INVALID_SOCKET; + free_socket(&sock, __LINE__); + return (result); + } + + /* + * Use minimum mtu if possible. + */ + use_min_mtu(sock); + +#if defined(USE_CMSG) || defined(SO_RCVBUF) + if (type == isc_sockettype_udp) { + +#if defined(USE_CMSG) +#if defined(ISC_PLATFORM_HAVEIPV6) +#ifdef IPV6_RECVPKTINFO + /* 2292bis */ + if ((pf == AF_INET6) + && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, + (char *)&on, sizeof(on)) < 0)) { + isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "setsockopt(%d, IPV6_RECVPKTINFO) " + "%s: %s", sock->fd, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, + "failed"), + strbuf); + } +#else + /* 2292 */ + if ((pf == AF_INET6) + && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO, + (char *)&on, sizeof(on)) < 0)) { + isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "setsockopt(%d, IPV6_PKTINFO) %s: %s", + sock->fd, + isc_msgcat_get(isc_msgcat, + ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, + "failed"), + strbuf); + } +#endif /* IPV6_RECVPKTINFO */ +#endif /* ISC_PLATFORM_HAVEIPV6 */ +#endif /* defined(USE_CMSG) */ + +#if defined(SO_RCVBUF) + optlen = sizeof(size); + if (getsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF, + (char *)&size, &optlen) >= 0 && + size < RCVBUFSIZE) { + size = RCVBUFSIZE; + (void)setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF, + (char *)&size, sizeof(size)); + } +#endif + + } +#endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */ + + _set_state(sock, SOCK_OPEN); + sock->references = 1; + *socketp = sock; + + iocompletionport_update(sock); + + if (dup_socket) { +#ifndef ISC_ALLOW_MAPPED + isc__socket_ipv6only(sock, true); +#endif + + if (dup_socket->bound) { + isc_sockaddr_t local; + + result = isc__socket_getsockname(dup_socket, &local); + if (result != ISC_R_SUCCESS) { + isc_socket_close(sock); + return (result); + } + result = isc__socket_bind(sock, &local, + ISC_SOCKET_REUSEADDRESS); + if (result != ISC_R_SUCCESS) { + isc_socket_close(sock); + return (result); + } + } + sock->dupped = 1; + } + + /* + * Note we don't have to lock the socket like we normally would because + * there are no external references to it yet. + */ + LOCK(&manager->lock); + ISC_LIST_APPEND(manager->socklist, sock, link); + InterlockedIncrement(&manager->totalSockets); + UNLOCK(&manager->lock); + + socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, + ISC_MSGSET_SOCKET, ISC_MSG_CREATED, + "created %u type %u", sock->fd, type); + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, + isc_socket_t **socketp) +{ + return (socket_create(manager, pf, type, socketp, NULL)); +} + +isc_result_t +isc__socket_dup(isc_socket_t *sock, isc_socket_t **socketp) { + REQUIRE(VALID_SOCKET(sock)); + REQUIRE(socketp != NULL && *socketp == NULL); + + return (socket_create(sock->manager, sock->pf, sock->type, + socketp, sock)); +} + +isc_result_t +isc_socket_open(isc_socket_t *sock) { + REQUIRE(VALID_SOCKET(sock)); + REQUIRE(sock->type != isc_sockettype_fdwatch); + + return (ISC_R_NOTIMPLEMENTED); +} + +/* + * Attach to a socket. Caller must explicitly detach when it is done. + */ +void +isc__socket_attach(isc_socket_t *sock, isc_socket_t **socketp) { + REQUIRE(VALID_SOCKET(sock)); + REQUIRE(socketp != NULL && *socketp == NULL); + + LOCK(&sock->lock); + CONSISTENT(sock); + sock->references++; + UNLOCK(&sock->lock); + + *socketp = sock; +} + +/* + * Dereference a socket. If this is the last reference to it, clean things + * up by destroying the socket. + */ +void +isc__socket_detach(isc_socket_t **socketp) { + isc_socket_t *sock; + + REQUIRE(socketp != NULL); + sock = *socketp; + REQUIRE(VALID_SOCKET(sock)); + REQUIRE(sock->type != isc_sockettype_fdwatch); + + LOCK(&sock->lock); + CONSISTENT(sock); + REQUIRE(sock->references > 0); + sock->references--; + + socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0, + "detach_socket %d %d %d", + sock->pending_recv, sock->pending_send, + sock->references); + + if (sock->references == 0 && sock->fd != INVALID_SOCKET) { + closesocket(sock->fd); + sock->fd = INVALID_SOCKET; + _set_state(sock, SOCK_CLOSED); + } + + maybe_free_socket(&sock, __LINE__); + + *socketp = NULL; +} + +isc_result_t +isc_socket_close(isc_socket_t *sock) { + REQUIRE(VALID_SOCKET(sock)); + REQUIRE(sock->type != isc_sockettype_fdwatch); + + return (ISC_R_NOTIMPLEMENTED); +} + +/* + * Dequeue an item off the given socket's read queue, set the result code + * in the done event to the one provided, and send it to the task it was + * destined for. + * + * If the event to be sent is on a list, remove it before sending. If + * asked to, send and detach from the task as well. + * + * Caller must have the socket locked if the event is attached to the socket. + */ +static void +send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev) { + isc_task_t *task; + + task = (*dev)->ev_sender; + (*dev)->ev_sender = sock; + + if (ISC_LINK_LINKED(*dev, ev_link)) + ISC_LIST_DEQUEUE(sock->recv_list, *dev, ev_link); + + if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED) + == ISC_SOCKEVENTATTR_ATTACHED) + isc_task_sendanddetach(&task, (isc_event_t **)dev); + else + isc_task_send(task, (isc_event_t **)dev); + + CONSISTENT(sock); +} + +/* + * See comments for send_recvdone_event() above. + */ +static void +send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) { + isc_task_t *task; + + INSIST(dev != NULL && *dev != NULL); + + task = (*dev)->ev_sender; + (*dev)->ev_sender = sock; + + if (ISC_LINK_LINKED(*dev, ev_link)) + ISC_LIST_DEQUEUE(sock->send_list, *dev, ev_link); + + if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED) + == ISC_SOCKEVENTATTR_ATTACHED) + isc_task_sendanddetach(&task, (isc_event_t **)dev); + else + isc_task_send(task, (isc_event_t **)dev); + + CONSISTENT(sock); +} + +/* + * See comments for send_recvdone_event() above. + */ +static void +send_acceptdone_event(isc_socket_t *sock, isc_socket_newconnev_t **adev) { + isc_task_t *task; + + INSIST(adev != NULL && *adev != NULL); + + task = (*adev)->ev_sender; + (*adev)->ev_sender = sock; + + if (ISC_LINK_LINKED(*adev, ev_link)) + ISC_LIST_DEQUEUE(sock->accept_list, *adev, ev_link); + + isc_task_sendanddetach(&task, (isc_event_t **)adev); + + CONSISTENT(sock); +} + +/* + * See comments for send_recvdone_event() above. + */ +static void +send_connectdone_event(isc_socket_t *sock, isc_socket_connev_t **cdev) { + isc_task_t *task; + + INSIST(cdev != NULL && *cdev != NULL); + + task = (*cdev)->ev_sender; + (*cdev)->ev_sender = sock; + + if (ISC_LINK_LINKED(*cdev, ev_link)) + ISC_LIST_DEQUEUE(sock->connect_list, *cdev, ev_link); + + isc_task_sendanddetach(&task, (isc_event_t **)cdev); + + CONSISTENT(sock); +} + +/* + * On entry to this function, the event delivered is the internal + * readable event, and the first item on the accept_list should be + * the done event we want to send. If the list is empty, this is a no-op, + * so just close the new connection, unlock, and return. + * + * Note the socket is locked before entering here + */ +static void +internal_accept(isc_socket_t *sock, IoCompletionInfo *lpo, int accept_errno) { + isc_socket_newconnev_t *adev; + isc_result_t result = ISC_R_SUCCESS; + isc_socket_t *nsock; + struct sockaddr *localaddr; + int localaddr_len = sizeof(*localaddr); + struct sockaddr *remoteaddr; + int remoteaddr_len = sizeof(*remoteaddr); + + INSIST(VALID_SOCKET(sock)); + LOCK(&sock->lock); + CONSISTENT(sock); + + socket_log(__LINE__, sock, NULL, TRACE, + isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK, + "internal_accept called"); + + INSIST(sock->listener); + + INSIST(sock->pending_iocp > 0); + sock->pending_iocp--; + INSIST(sock->pending_accept > 0); + sock->pending_accept--; + + adev = lpo->adev; + + /* + * If the event is no longer in the list we can just return. + */ + if (!acceptdone_is_active(sock, adev)) + goto done; + + nsock = adev->newsocket; + + /* + * Pull off the done event. + */ + ISC_LIST_UNLINK(sock->accept_list, adev, ev_link); + + /* + * Extract the addresses from the socket, copy them into the structure, + * and return the new socket. + */ + ISCGetAcceptExSockaddrs(lpo->acceptbuffer, 0, + sizeof(SOCKADDR_STORAGE) + 16, sizeof(SOCKADDR_STORAGE) + 16, + (LPSOCKADDR *)&localaddr, &localaddr_len, + (LPSOCKADDR *)&remoteaddr, &remoteaddr_len); + memmove(&adev->address.type, remoteaddr, remoteaddr_len); + adev->address.length = remoteaddr_len; + nsock->address = adev->address; + nsock->pf = adev->address.type.sa.sa_family; + + socket_log(__LINE__, nsock, &nsock->address, TRACE, + isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK, + "internal_accept parent %p", sock); + + result = make_nonblock(adev->newsocket->fd); + INSIST(result == ISC_R_SUCCESS); + + /* + * Use minimum mtu if possible. + */ + use_min_mtu(adev->newsocket); + + INSIST(setsockopt(nsock->fd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, + (char *)&sock->fd, sizeof(sock->fd)) == 0); + + /* + * Hook it up into the manager. + */ + nsock->bound = 1; + nsock->connected = 1; + _set_state(nsock, SOCK_OPEN); + + LOCK(&nsock->manager->lock); + ISC_LIST_APPEND(nsock->manager->socklist, nsock, link); + InterlockedIncrement(&nsock->manager->totalSockets); + UNLOCK(&nsock->manager->lock); + + socket_log(__LINE__, sock, &nsock->address, CREATION, + isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN, + "accepted_connection new_socket %p fd %d", + nsock, nsock->fd); + + adev->result = result; + send_acceptdone_event(sock, &adev); + +done: + CONSISTENT(sock); + UNLOCK(&sock->lock); + + HeapFree(hHeapHandle, 0, lpo->acceptbuffer); + lpo->acceptbuffer = NULL; +} + +/* + * Called when a socket with a pending connect() finishes. + * Note that the socket is locked before entering. + */ +static void +internal_connect(isc_socket_t *sock, IoCompletionInfo *lpo, int connect_errno) { + isc_socket_connev_t *cdev; + isc_result_t result; + char strbuf[ISC_STRERRORSIZE]; + + INSIST(VALID_SOCKET(sock)); + + LOCK(&sock->lock); + + INSIST(sock->pending_iocp > 0); + sock->pending_iocp--; + INSIST(sock->pending_connect == 1); + sock->pending_connect = 0; + + /* + * If the event is no longer in the list we can just close and return. + */ + cdev = lpo->cdev; + if (!connectdone_is_active(sock, cdev)) { + sock->pending_connect = 0; + if (sock->fd != INVALID_SOCKET) { + closesocket(sock->fd); + sock->fd = INVALID_SOCKET; + _set_state(sock, SOCK_CLOSED); + } + CONSISTENT(sock); + UNLOCK(&sock->lock); + return; + } + + /* + * Check possible Windows network event error status here. + */ + if (connect_errno != 0) { + /* + * If the error is SOFT, just try again on this + * fd and pretend nothing strange happened. + */ + if (SOFT_ERROR(connect_errno) || + connect_errno == WSAEINPROGRESS) { + sock->pending_connect = 1; + CONSISTENT(sock); + UNLOCK(&sock->lock); + return; + } + + /* + * Translate other errors into ISC_R_* flavors. + */ + switch (connect_errno) { +#define ERROR_MATCH(a, b) case a: result = b; break; + ERROR_MATCH(WSAEACCES, ISC_R_NOPERM); + ERROR_MATCH(WSAEADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL); + ERROR_MATCH(WSAEAFNOSUPPORT, ISC_R_ADDRNOTAVAIL); + ERROR_MATCH(WSAECONNREFUSED, ISC_R_CONNREFUSED); + ERROR_MATCH(WSAEHOSTUNREACH, ISC_R_HOSTUNREACH); + ERROR_MATCH(WSAEHOSTDOWN, ISC_R_HOSTDOWN); + ERROR_MATCH(WSAENETUNREACH, ISC_R_NETUNREACH); + ERROR_MATCH(WSAENETDOWN, ISC_R_NETDOWN); + ERROR_MATCH(WSAENOBUFS, ISC_R_NORESOURCES); + ERROR_MATCH(WSAECONNRESET, ISC_R_CONNECTIONRESET); + ERROR_MATCH(WSAECONNABORTED, ISC_R_CONNECTIONRESET); + ERROR_MATCH(WSAETIMEDOUT, ISC_R_TIMEDOUT); +#undef ERROR_MATCH + default: + result = ISC_R_UNEXPECTED; + isc__strerror(connect_errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "internal_connect: connect() %s", + strbuf); + } + } else { + INSIST(setsockopt(sock->fd, SOL_SOCKET, + SO_UPDATE_CONNECT_CONTEXT, NULL, 0) == 0); + result = ISC_R_SUCCESS; + sock->connected = 1; + socket_log(__LINE__, sock, &sock->address, IOEVENT, + isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN, + "internal_connect: success"); + } + + do { + cdev->result = result; + send_connectdone_event(sock, &cdev); + cdev = ISC_LIST_HEAD(sock->connect_list); + } while (cdev != NULL); + + UNLOCK(&sock->lock); +} + +/* + * Loop through the socket, returning ISC_R_EOF for each done event pending. + */ +static void +send_recvdone_abort(isc_socket_t *sock, isc_result_t result) { + isc_socketevent_t *dev; + + while (!ISC_LIST_EMPTY(sock->recv_list)) { + dev = ISC_LIST_HEAD(sock->recv_list); + dev->result = result; + send_recvdone_event(sock, &dev); + } +} + +/* + * Loop through the socket, returning result for each done event pending. + */ +static void +send_connectdone_abort(isc_socket_t *sock, isc_result_t result) { + isc_socket_connev_t *dev; + + while (!ISC_LIST_EMPTY(sock->connect_list)) { + dev = ISC_LIST_HEAD(sock->connect_list); + dev->result = result; + send_connectdone_event(sock, &dev); + } +} + +/* + * Take the data we received in our private buffer, and if any recv() calls on + * our list are satisfied, send the corresponding done event. + * + * If we need more data (there are still items on the recv_list after we consume all + * our data) then arrange for another system recv() call to fill our buffers. + */ +static void +internal_recv(isc_socket_t *sock, int nbytes) +{ + INSIST(VALID_SOCKET(sock)); + + LOCK(&sock->lock); + CONSISTENT(sock); + + socket_log(__LINE__, sock, NULL, IOEVENT, + isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV, + "internal_recv: %d bytes received", nbytes); + + /* + * If we got here, the I/O operation succeeded. However, we might still have removed this + * event from our notification list (or never placed it on it due to immediate completion.) + * Handle the reference counting here, and handle the cancellation event just after. + */ + INSIST(sock->pending_iocp > 0); + sock->pending_iocp--; + INSIST(sock->pending_recv > 0); + sock->pending_recv--; + + /* + * The only way we could have gotten here is that our I/O has successfully completed. + * Update our pointers, and move on. The only odd case here is that we might not + * have received enough data on a TCP stream to satisfy the minimum requirements. If + * this is the case, we will re-issue the recv() call for what we need. + * + * We do check for a recv() of 0 bytes on a TCP stream. This means the remote end + * has closed. + */ + if (nbytes == 0 && sock->type == isc_sockettype_tcp) { + send_recvdone_abort(sock, ISC_R_EOF); + maybe_free_socket(&sock, __LINE__); + return; + } + sock->recvbuf.remaining = nbytes; + sock->recvbuf.consume_position = sock->recvbuf.base; + completeio_recv(sock); + + /* + * If there are more receivers waiting for data, queue another receive + * here. + */ + queue_receive_request(sock); + + /* + * Unlock and/or destroy if we are the last thing this socket has left to do. + */ + maybe_free_socket(&sock, __LINE__); +} + +static void +internal_send(isc_socket_t *sock, isc_socketevent_t *dev, + struct msghdr *messagehdr, int nbytes, int send_errno, IoCompletionInfo *lpo) +{ + buflist_t *buffer; + + /* + * Find out what socket this is and lock it. + */ + INSIST(VALID_SOCKET(sock)); + + LOCK(&sock->lock); + CONSISTENT(sock); + + socket_log(__LINE__, sock, NULL, IOEVENT, + isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND, + "internal_send: task got socket event %p", dev); + + buffer = ISC_LIST_HEAD(lpo->bufferlist); + while (buffer != NULL) { + ISC_LIST_DEQUEUE(lpo->bufferlist, buffer, link); + + socket_log(__LINE__, sock, NULL, TRACE, + isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK, + "free_buffer %p %p", buffer, buffer->buf); + + HeapFree(hHeapHandle, 0, buffer->buf); + HeapFree(hHeapHandle, 0, buffer); + buffer = ISC_LIST_HEAD(lpo->bufferlist); + } + + INSIST(sock->pending_iocp > 0); + sock->pending_iocp--; + INSIST(sock->pending_send > 0); + sock->pending_send--; + + /* If the event is no longer in the list we can just return */ + if (!senddone_is_active(sock, dev)) + goto done; + + /* + * Set the error code and send things on its way. + */ + switch (completeio_send(sock, dev, messagehdr, nbytes, send_errno)) { + case DOIO_SOFT: + break; + case DOIO_HARD: + case DOIO_SUCCESS: + send_senddone_event(sock, &dev); + break; + } + + done: + maybe_free_socket(&sock, __LINE__); +} + +/* + * These return if the done event passed in is on the list. + * Using these ensures we will not double-send an event. + */ +static bool +senddone_is_active(isc_socket_t *sock, isc_socketevent_t *dev) +{ + isc_socketevent_t *ldev; + + ldev = ISC_LIST_HEAD(sock->send_list); + while (ldev != NULL && ldev != dev) + ldev = ISC_LIST_NEXT(ldev, ev_link); + + return (ldev == NULL ? false : true); +} + +static bool +acceptdone_is_active(isc_socket_t *sock, isc_socket_newconnev_t *dev) +{ + isc_socket_newconnev_t *ldev; + + ldev = ISC_LIST_HEAD(sock->accept_list); + while (ldev != NULL && ldev != dev) + ldev = ISC_LIST_NEXT(ldev, ev_link); + + return (ldev == NULL ? false : true); +} + +static bool +connectdone_is_active(isc_socket_t *sock, isc_socket_connev_t *dev) +{ + isc_socket_connev_t *cdev; + + cdev = ISC_LIST_HEAD(sock->connect_list); + while (cdev != NULL && cdev != dev) + cdev = ISC_LIST_NEXT(cdev, ev_link); + + return (cdev == NULL ? false : true); +} + +// +// The Windows network stack seems to have two very distinct paths depending +// on what is installed. Specifically, if something is looking at network +// connections (like an anti-virus or anti-malware application, such as +// McAfee products) Windows may return additional error conditions which +// were not previously returned. +// +// One specific one is when a TCP SYN scan is used. In this situation, +// Windows responds with the SYN-ACK, but the scanner never responds with +// the 3rd packet, the ACK. Windows consiers this a partially open connection. +// Most Unix networking stacks, and Windows without McAfee installed, will +// not return this to the caller. However, with this product installed, +// Windows returns this as a failed status on the Accept() call. Here, we +// will just re-issue the ISCAcceptEx() call as if nothing had happened. +// +// This code should only be called when the listening socket has received +// such an error. Additionally, the "parent" socket must be locked. +// Additionally, the lpo argument is re-used here, and must not be freed +// by the caller. +// +static isc_result_t +restart_accept(isc_socket_t *parent, IoCompletionInfo *lpo) +{ + isc_socket_t *nsock = lpo->adev->newsocket; + SOCKET new_fd; + + /* + * AcceptEx() requires we pass in a socket. Note that we carefully + * do not close the previous socket in case of an error message returned by + * our new socket() call. If we return an error here, our caller will + * clean up. + */ + new_fd = socket(parent->pf, SOCK_STREAM, IPPROTO_TCP); + if (nsock->fd == INVALID_SOCKET) { + return (ISC_R_FAILURE); // parent will ask windows for error message + } + closesocket(nsock->fd); + nsock->fd = new_fd; + + memset(&lpo->overlapped, 0, sizeof(lpo->overlapped)); + + ISCAcceptEx(parent->fd, + nsock->fd, /* Accepted Socket */ + lpo->acceptbuffer, /* Buffer for initial Recv */ + 0, /* Length of Buffer */ + sizeof(SOCKADDR_STORAGE) + 16, /* Local address length + 16 */ + sizeof(SOCKADDR_STORAGE) + 16, /* Remote address lengh + 16 */ + (LPDWORD)&lpo->received_bytes, /* Bytes Recved */ + (LPOVERLAPPED)lpo /* Overlapped structure */ + ); + + InterlockedDecrement(&nsock->manager->iocp_total); + iocompletionport_update(nsock); + + return (ISC_R_SUCCESS); +} + +/* + * This is the I/O Completion Port Worker Function. It loops forever + * waiting for I/O to complete and then forwards them for further + * processing. There are a number of these in separate threads. + */ +static isc_threadresult_t WINAPI +SocketIoThread(LPVOID ThreadContext) { + isc_socketmgr_t *manager = ThreadContext; + BOOL bSuccess = FALSE; + DWORD nbytes; + IoCompletionInfo *lpo = NULL; + isc_socket_t *sock = NULL; + int request; + struct msghdr *messagehdr = NULL; + int errval; + char strbuf[ISC_STRERRORSIZE]; + int errstatus; + + REQUIRE(VALID_MANAGER(manager)); + + /* + * Set the thread priority high enough so I/O will + * preempt normal recv packet processing, but not + * higher than the timer sync thread. + */ + if (!SetThreadPriority(GetCurrentThread(), + THREAD_PRIORITY_ABOVE_NORMAL)) { + errval = GetLastError(); + isc__strerror(errval, strbuf, sizeof(strbuf)); + FATAL_ERROR(__FILE__, __LINE__, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_FAILED, + "Can't set thread priority: %s"), + strbuf); + } + + /* + * Loop forever waiting on I/O Completions and then processing them + */ + while (TRUE) { + wait_again: + bSuccess = GetQueuedCompletionStatus(manager->hIoCompletionPort, + &nbytes, + (PULONG_PTR)&sock, + (LPWSAOVERLAPPED *)&lpo, + INFINITE); + if (lpo == NULL) /* Received request to exit */ + break; + + REQUIRE(VALID_SOCKET(sock)); + + request = lpo->request_type; + + if (!bSuccess) + errstatus = GetLastError(); + else + errstatus = 0; + if (!bSuccess && errstatus != ERROR_MORE_DATA) { + isc_result_t isc_result; + + /* + * Did the I/O operation complete? + */ + isc_result = isc__errno2result(errstatus); + + LOCK(&sock->lock); + CONSISTENT(sock); + switch (request) { + case SOCKET_RECV: + INSIST(sock->pending_iocp > 0); + sock->pending_iocp--; + INSIST(sock->pending_recv > 0); + sock->pending_recv--; + if (!sock->connected && + ((errstatus == ERROR_HOST_UNREACHABLE) || + (errstatus == WSAENETRESET) || + (errstatus == WSAECONNRESET))) { + /* ignore soft errors */ + queue_receive_request(sock); + break; + } + send_recvdone_abort(sock, isc_result); + if (isc_result == ISC_R_UNEXPECTED) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "SOCKET_RECV: Windows error code: %d, returning ISC error %d", + errstatus, isc_result); + } + break; + + case SOCKET_SEND: + INSIST(sock->pending_iocp > 0); + sock->pending_iocp--; + INSIST(sock->pending_send > 0); + sock->pending_send--; + if (senddone_is_active(sock, lpo->dev)) { + lpo->dev->result = isc_result; + socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0, + "canceled_send"); + send_senddone_event(sock, &lpo->dev); + } + break; + + case SOCKET_ACCEPT: + INSIST(sock->pending_iocp > 0); + INSIST(sock->pending_accept > 0); + + socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0, + "Accept: errstatus=%d isc_result=%d", errstatus, isc_result); + + if (acceptdone_is_active(sock, lpo->adev)) { + if (restart_accept(sock, lpo) == ISC_R_SUCCESS) { + UNLOCK(&sock->lock); + goto wait_again; + } else { + errstatus = GetLastError(); + isc_result = isc__errno2result(errstatus); + socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0, + "restart_accept() failed: errstatus=%d isc_result=%d", + errstatus, isc_result); + } + } + + sock->pending_iocp--; + sock->pending_accept--; + if (acceptdone_is_active(sock, lpo->adev)) { + closesocket(lpo->adev->newsocket->fd); + lpo->adev->newsocket->fd = INVALID_SOCKET; + lpo->adev->newsocket->references--; + free_socket(&lpo->adev->newsocket, __LINE__); + lpo->adev->result = isc_result; + socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0, + "canceled_accept"); + send_acceptdone_event(sock, &lpo->adev); + } + break; + + case SOCKET_CONNECT: + INSIST(sock->pending_iocp > 0); + sock->pending_iocp--; + INSIST(sock->pending_connect == 1); + sock->pending_connect = 0; + if (connectdone_is_active(sock, lpo->cdev)) { + socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0, + "canceled_connect"); + send_connectdone_abort(sock, isc_result); + } + break; + } + maybe_free_socket(&sock, __LINE__); + + if (lpo != NULL) + HeapFree(hHeapHandle, 0, lpo); + continue; + } + + messagehdr = &lpo->messagehdr; + + switch (request) { + case SOCKET_RECV: + internal_recv(sock, nbytes); + break; + case SOCKET_SEND: + internal_send(sock, lpo->dev, messagehdr, nbytes, errstatus, lpo); + break; + case SOCKET_ACCEPT: + internal_accept(sock, lpo, errstatus); + break; + case SOCKET_CONNECT: + internal_connect(sock, lpo, errstatus); + break; + } + + if (lpo != NULL) + HeapFree(hHeapHandle, 0, lpo); + } + + /* + * Exit Completion Port Thread + */ + manager_log(manager, TRACE, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_EXITING, "SocketIoThread exiting")); + return ((isc_threadresult_t)0); +} + +/* + * Create a new socket manager. + */ +isc_result_t +isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { + return (isc_socketmgr_create2(mctx, managerp, 0)); +} + +isc_result_t +isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, + unsigned int maxsocks) +{ + isc_socketmgr_t *manager; + isc_result_t result; + + REQUIRE(managerp != NULL && *managerp == NULL); + + if (maxsocks != 0) + return (ISC_R_NOTIMPLEMENTED); + + manager = isc_mem_get(mctx, sizeof(*manager)); + if (manager == NULL) + return (ISC_R_NOMEMORY); + + InitSockets(); + + manager->magic = SOCKET_MANAGER_MAGIC; + manager->mctx = NULL; + manager->stats = NULL; + ISC_LIST_INIT(manager->socklist); + result = isc_mutex_init(&manager->lock); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, manager, sizeof(*manager)); + return (result); + } + if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) { + DESTROYLOCK(&manager->lock); + isc_mem_put(mctx, manager, sizeof(*manager)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_condition_init() %s", + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, "failed")); + return (ISC_R_UNEXPECTED); + } + + isc_mem_attach(mctx, &manager->mctx); + + iocompletionport_init(manager); /* Create the Completion Ports */ + + manager->bShutdown = false; + manager->totalSockets = 0; + manager->iocp_total = 0; + + *managerp = manager; + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) { + REQUIRE(VALID_MANAGER(manager)); + REQUIRE(nsockp != NULL); + + return (ISC_R_NOTIMPLEMENTED); +} + +void +isc_socketmgr_setstats(isc_socketmgr_t *manager, isc_stats_t *stats) { + REQUIRE(VALID_MANAGER(manager)); + REQUIRE(ISC_LIST_EMPTY(manager->socklist)); + REQUIRE(manager->stats == NULL); + REQUIRE(isc_stats_ncounters(stats) == isc_sockstatscounter_max); + + isc_stats_attach(stats, &manager->stats); +} + +void +isc__socketmgr_destroy(isc_socketmgr_t **managerp) { + isc_socketmgr_t *manager; + int i; + isc_mem_t *mctx; + + /* + * Destroy a socket manager. + */ + + REQUIRE(managerp != NULL); + manager = *managerp; + REQUIRE(VALID_MANAGER(manager)); + + LOCK(&manager->lock); + + /* + * Wait for all sockets to be destroyed. + */ + while (!ISC_LIST_EMPTY(manager->socklist)) { + manager_log(manager, CREATION, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_SOCKETSREMAIN, + "sockets exist")); + WAIT(&manager->shutdown_ok, &manager->lock); + } + + UNLOCK(&manager->lock); + + /* + * Here, we need to had some wait code for the completion port + * thread. + */ + signal_iocompletionport_exit(manager); + manager->bShutdown = true; + + /* + * Wait for threads to exit. + */ + for (i = 0; i < manager->maxIOCPThreads; i++) { + if (isc_thread_join((isc_thread_t) manager->hIOCPThreads[i], + NULL) != ISC_R_SUCCESS) + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_thread_join() for Completion Port %s", + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, "failed")); + } + /* + * Clean up. + */ + + CloseHandle(manager->hIoCompletionPort); + + (void)isc_condition_destroy(&manager->shutdown_ok); + + DESTROYLOCK(&manager->lock); + if (manager->stats != NULL) + isc_stats_detach(&manager->stats); + manager->magic = 0; + mctx= manager->mctx; + isc_mem_put(mctx, manager, sizeof(*manager)); + + isc_mem_detach(&mctx); + + *managerp = NULL; +} + +static void +queue_receive_event(isc_socket_t *sock, isc_task_t *task, isc_socketevent_t *dev) +{ + isc_task_t *ntask = NULL; + + isc_task_attach(task, &ntask); + dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED; + + /* + * Enqueue the request. + */ + INSIST(!ISC_LINK_LINKED(dev, ev_link)); + ISC_LIST_ENQUEUE(sock->recv_list, dev, ev_link); + + socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0, + "queue_receive_event: event %p -> task %p", + dev, ntask); +} + +/* + * Check the pending receive queue, and if we have data pending, give it to this + * caller. If we have none, queue an I/O request. If this caller is not the first + * on the list, then we will just queue this event and return. + * + * Caller must have the socket locked. + */ +static isc_result_t +socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, + unsigned int flags) +{ + isc_result_t result = ISC_R_SUCCESS; + + dev->ev_sender = task; + + if (sock->fd == INVALID_SOCKET) + return (ISC_R_EOF); + + /* + * Queue our event on the list of things to do. Call our function to + * attempt to fill buffers as much as possible, and return done events. + * We are going to lie about our handling of the ISC_SOCKFLAG_IMMEDIATE + * here and tell our caller that we could not satisfy it immediately. + */ + queue_receive_event(sock, task, dev); + if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0) + result = ISC_R_INPROGRESS; + + completeio_recv(sock); + + /* + * If there are more receivers waiting for data, queue another receive + * here. If the + */ + queue_receive_request(sock); + + return (result); +} + +isc_result_t +isc__socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist, + unsigned int minimum, isc_task_t *task, + isc_taskaction_t action, void *arg) +{ + isc_socketevent_t *dev; + isc_socketmgr_t *manager; + unsigned int iocount; + isc_buffer_t *buffer; + isc_result_t ret; + + REQUIRE(VALID_SOCKET(sock)); + LOCK(&sock->lock); + CONSISTENT(sock); + + /* + * Make sure that the socket is not closed. XXXMLG change error here? + */ + if (sock->fd == INVALID_SOCKET) { + UNLOCK(&sock->lock); + return (ISC_R_CONNREFUSED); + } + + REQUIRE(buflist != NULL); + REQUIRE(!ISC_LIST_EMPTY(*buflist)); + REQUIRE(task != NULL); + REQUIRE(action != NULL); + + manager = sock->manager; + REQUIRE(VALID_MANAGER(manager)); + + iocount = isc_bufferlist_availablecount(buflist); + REQUIRE(iocount > 0); + + INSIST(sock->bound); + + dev = allocate_socketevent(manager->mctx, sock, + ISC_SOCKEVENT_RECVDONE, action, arg); + if (dev == NULL) { + UNLOCK(&sock->lock); + return (ISC_R_NOMEMORY); + } + + /* + * UDP sockets are always partial read + */ + if (sock->type == isc_sockettype_udp) + dev->minimum = 1; + else { + if (minimum == 0) + dev->minimum = iocount; + else + dev->minimum = minimum; + } + + /* + * Move each buffer from the passed in list to our internal one. + */ + buffer = ISC_LIST_HEAD(*buflist); + while (buffer != NULL) { + ISC_LIST_DEQUEUE(*buflist, buffer, link); + ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link); + buffer = ISC_LIST_HEAD(*buflist); + } + + ret = socket_recv(sock, dev, task, 0); + + UNLOCK(&sock->lock); + return (ret); +} + +isc_result_t +isc__socket_recv(isc_socket_t *sock, isc_region_t *region, + unsigned int minimum, isc_task_t *task, + isc_taskaction_t action, void *arg) +{ + isc_socketevent_t *dev; + isc_socketmgr_t *manager; + isc_result_t ret; + + REQUIRE(VALID_SOCKET(sock)); + LOCK(&sock->lock); + CONSISTENT(sock); + + /* + * make sure that the socket's not closed + */ + if (sock->fd == INVALID_SOCKET) { + UNLOCK(&sock->lock); + return (ISC_R_CONNREFUSED); + } + REQUIRE(action != NULL); + + manager = sock->manager; + REQUIRE(VALID_MANAGER(manager)); + + INSIST(sock->bound); + + dev = allocate_socketevent(manager->mctx, sock, + ISC_SOCKEVENT_RECVDONE, action, arg); + if (dev == NULL) { + UNLOCK(&sock->lock); + return (ISC_R_NOMEMORY); + } + + ret = isc_socket_recv2(sock, region, minimum, task, dev, 0); + UNLOCK(&sock->lock); + return (ret); +} + +isc_result_t +isc__socket_recv2(isc_socket_t *sock, isc_region_t *region, + unsigned int minimum, isc_task_t *task, + isc_socketevent_t *event, unsigned int flags) +{ + isc_result_t ret; + + REQUIRE(VALID_SOCKET(sock)); + LOCK(&sock->lock); + CONSISTENT(sock); + + event->result = ISC_R_UNEXPECTED; + event->ev_sender = sock; + /* + * make sure that the socket's not closed + */ + if (sock->fd == INVALID_SOCKET) { + UNLOCK(&sock->lock); + return (ISC_R_CONNREFUSED); + } + + ISC_LIST_INIT(event->bufferlist); + event->region = *region; + event->n = 0; + event->offset = 0; + event->attributes = 0; + + /* + * UDP sockets are always partial read. + */ + if (sock->type == isc_sockettype_udp) + event->minimum = 1; + else { + if (minimum == 0) + event->minimum = region->length; + else + event->minimum = minimum; + } + + ret = socket_recv(sock, event, task, flags); + UNLOCK(&sock->lock); + return (ret); +} + +/* + * Caller must have the socket locked. + */ +static isc_result_t +socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, + unsigned int flags) +{ + int io_state; + int send_errno = 0; + int cc = 0; + isc_task_t *ntask = NULL; + isc_result_t result = ISC_R_SUCCESS; + + dev->ev_sender = task; + + set_dev_address(address, sock, dev); + if (pktinfo != NULL) { + socket_log(__LINE__, sock, NULL, TRACE, isc_msgcat, ISC_MSGSET_SOCKET, + ISC_MSG_PKTINFOPROVIDED, + "pktinfo structure provided, ifindex %u (set to 0)", + pktinfo->ipi6_ifindex); + + dev->attributes |= ISC_SOCKEVENTATTR_PKTINFO; + dev->pktinfo = *pktinfo; + /* + * Set the pktinfo index to 0 here, to let the kernel decide + * what interface it should send on. + */ + dev->pktinfo.ipi6_ifindex = 0; + } + + io_state = startio_send(sock, dev, &cc, &send_errno); + switch (io_state) { + case DOIO_PENDING: /* I/O started. Enqueue completion event. */ + case DOIO_SOFT: + /* + * We couldn't send all or part of the request right now, so + * queue it unless ISC_SOCKFLAG_NORETRY is set. + */ + if ((flags & ISC_SOCKFLAG_NORETRY) == 0 || + io_state == DOIO_PENDING) { + isc_task_attach(task, &ntask); + dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED; + + /* + * Enqueue the request. + */ + INSIST(!ISC_LINK_LINKED(dev, ev_link)); + ISC_LIST_ENQUEUE(sock->send_list, dev, ev_link); + + socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0, + "socket_send: event %p -> task %p", + dev, ntask); + + if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0) + result = ISC_R_INPROGRESS; + break; + } + + case DOIO_SUCCESS: + break; + } + + return (result); +} + +isc_result_t +isc__socket_send(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, isc_taskaction_t action, void *arg) +{ + /* + * REQUIRE() checking is performed in isc_socket_sendto(). + */ + return (isc_socket_sendto(sock, region, task, action, arg, NULL, + NULL)); +} + +isc_result_t +isc__socket_sendto(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, isc_taskaction_t action, void *arg, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) +{ + isc_socketevent_t *dev; + isc_socketmgr_t *manager; + isc_result_t ret; + + REQUIRE(VALID_SOCKET(sock)); + REQUIRE(sock->type != isc_sockettype_fdwatch); + + LOCK(&sock->lock); + CONSISTENT(sock); + + /* + * make sure that the socket's not closed + */ + if (sock->fd == INVALID_SOCKET) { + UNLOCK(&sock->lock); + return (ISC_R_CONNREFUSED); + } + REQUIRE(region != NULL); + REQUIRE(task != NULL); + REQUIRE(action != NULL); + + manager = sock->manager; + REQUIRE(VALID_MANAGER(manager)); + + INSIST(sock->bound); + + dev = allocate_socketevent(manager->mctx, sock, + ISC_SOCKEVENT_SENDDONE, action, arg); + if (dev == NULL) { + UNLOCK(&sock->lock); + return (ISC_R_NOMEMORY); + } + dev->region = *region; + + ret = socket_send(sock, dev, task, address, pktinfo, 0); + UNLOCK(&sock->lock); + return (ret); +} + +isc_result_t +isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist, + isc_task_t *task, isc_taskaction_t action, void *arg) +{ + return (isc_socket_sendtov2(sock, buflist, task, action, arg, NULL, + NULL, 0)); +} + +isc_result_t +isc__socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist, + isc_task_t *task, isc_taskaction_t action, void *arg, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) +{ + return (isc_socket_sendtov2(sock, buflist, task, action, arg, address, + pktinfo, 0)); +} + +isc_result_t +isc__socket_sendtov2(isc_socket_t *sock, isc_bufferlist_t *buflist, + isc_task_t *task, isc_taskaction_t action, void *arg, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, + unsigned int flags) +{ + isc_socketevent_t *dev; + isc_socketmgr_t *manager; + unsigned int iocount; + isc_buffer_t *buffer; + isc_result_t ret; + + REQUIRE(VALID_SOCKET(sock)); + + LOCK(&sock->lock); + CONSISTENT(sock); + + /* + * make sure that the socket's not closed + */ + if (sock->fd == INVALID_SOCKET) { + UNLOCK(&sock->lock); + return (ISC_R_CONNREFUSED); + } + REQUIRE(buflist != NULL); + REQUIRE(!ISC_LIST_EMPTY(*buflist)); + REQUIRE(task != NULL); + REQUIRE(action != NULL); + + manager = sock->manager; + REQUIRE(VALID_MANAGER(manager)); + + iocount = isc_bufferlist_usedcount(buflist); + REQUIRE(iocount > 0); + + dev = allocate_socketevent(manager->mctx, sock, + ISC_SOCKEVENT_SENDDONE, action, arg); + if (dev == NULL) { + UNLOCK(&sock->lock); + return (ISC_R_NOMEMORY); + } + + /* + * Move each buffer from the passed in list to our internal one. + */ + buffer = ISC_LIST_HEAD(*buflist); + while (buffer != NULL) { + ISC_LIST_DEQUEUE(*buflist, buffer, link); + ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link); + buffer = ISC_LIST_HEAD(*buflist); + } + + ret = socket_send(sock, dev, task, address, pktinfo, flags); + UNLOCK(&sock->lock); + return (ret); +} + +isc_result_t +isc__socket_sendto2(isc_socket_t *sock, isc_region_t *region, + isc_task_t *task, + isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, + isc_socketevent_t *event, unsigned int flags) +{ + isc_result_t ret; + + REQUIRE(VALID_SOCKET(sock)); + LOCK(&sock->lock); + CONSISTENT(sock); + + REQUIRE((flags & ~(ISC_SOCKFLAG_IMMEDIATE|ISC_SOCKFLAG_NORETRY)) == 0); + if ((flags & ISC_SOCKFLAG_NORETRY) != 0) + REQUIRE(sock->type == isc_sockettype_udp); + event->ev_sender = sock; + event->result = ISC_R_UNEXPECTED; + /* + * make sure that the socket's not closed + */ + if (sock->fd == INVALID_SOCKET) { + UNLOCK(&sock->lock); + return (ISC_R_CONNREFUSED); + } + ISC_LIST_INIT(event->bufferlist); + event->region = *region; + event->n = 0; + event->offset = 0; + event->attributes = 0; + + ret = socket_send(sock, event, task, address, pktinfo, flags); + UNLOCK(&sock->lock); + return (ret); +} + +isc_result_t +isc__socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr, + unsigned int options) { + int bind_errno; + char strbuf[ISC_STRERRORSIZE]; + int on = 1; + + REQUIRE(VALID_SOCKET(sock)); + LOCK(&sock->lock); + CONSISTENT(sock); + + /* + * make sure that the socket's not closed + */ + if (sock->fd == INVALID_SOCKET) { + UNLOCK(&sock->lock); + return (ISC_R_CONNREFUSED); + } + + INSIST(!sock->bound); + INSIST(!sock->dupped); + + if (sock->pf != sockaddr->type.sa.sa_family) { + UNLOCK(&sock->lock); + return (ISC_R_FAMILYMISMATCH); + } + /* + * Only set SO_REUSEADDR when we want a specific port. + */ + if ((options & ISC_SOCKET_REUSEADDRESS) != 0 && + isc_sockaddr_getport(sockaddr) != (in_port_t)0 && + setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, + sizeof(on)) < 0) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "setsockopt(%d) %s", sock->fd, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, "failed")); + /* Press on... */ + } + if (bind(sock->fd, &sockaddr->type.sa, sockaddr->length) < 0) { + bind_errno = WSAGetLastError(); + UNLOCK(&sock->lock); + switch (bind_errno) { + case WSAEACCES: + return (ISC_R_NOPERM); + case WSAEADDRNOTAVAIL: + return (ISC_R_ADDRNOTAVAIL); + case WSAEADDRINUSE: + return (ISC_R_ADDRINUSE); + case WSAEINVAL: + return (ISC_R_BOUND); + default: + isc__strerror(bind_errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, "bind: %s", + strbuf); + return (ISC_R_UNEXPECTED); + } + } + + socket_log(__LINE__, sock, sockaddr, TRACE, + isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, "bound"); + sock->bound = 1; + + UNLOCK(&sock->lock); + return (ISC_R_SUCCESS); +} + +isc_result_t +isc__socket_filter(isc_socket_t *sock, const char *filter) { + UNUSED(sock); + UNUSED(filter); + + REQUIRE(VALID_SOCKET(sock)); + return (ISC_R_NOTIMPLEMENTED); +} + +/* + * Set up to listen on a given socket. We do this by creating an internal + * event that will be dispatched when the socket has read activity. The + * watcher will send the internal event to the task when there is a new + * connection. + * + * Unlike in read, we don't preallocate a done event here. Every time there + * is a new connection we'll have to allocate a new one anyway, so we might + * as well keep things simple rather than having to track them. + */ +isc_result_t +isc__socket_listen(isc_socket_t *sock, unsigned int backlog) { + char strbuf[ISC_STRERRORSIZE]; +#if defined(ISC_PLATFORM_HAVETFO) && defined(TCP_FASTOPEN) + char on = 1; +#endif + + REQUIRE(VALID_SOCKET(sock)); + + LOCK(&sock->lock); + CONSISTENT(sock); + + /* + * make sure that the socket's not closed + */ + if (sock->fd == INVALID_SOCKET) { + UNLOCK(&sock->lock); + return (ISC_R_CONNREFUSED); + } + + REQUIRE(!sock->listener); + REQUIRE(sock->bound); + REQUIRE(sock->type == isc_sockettype_tcp); + + if (backlog == 0) + backlog = SOMAXCONN; + + if (listen(sock->fd, (int)backlog) < 0) { + UNLOCK(&sock->lock); + isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf)); + + UNEXPECTED_ERROR(__FILE__, __LINE__, "listen: %s", strbuf); + + return (ISC_R_UNEXPECTED); + } + +#if defined(ISC_PLATFORM_HAVETFO) && defined(TCP_FASTOPEN) + if (setsockopt(sock->fd, IPPROTO_TCP, TCP_FASTOPEN, + &on, sizeof(on)) < 0) { + isc__strerror(errno, strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "setsockopt(%d, TCP_FASTOPEN) failed with %s", + sock->fd, strbuf); + /* TCP_FASTOPEN is experimental so ignore failures */ + } +#endif + + socket_log(__LINE__, sock, NULL, TRACE, + isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, "listening"); + sock->listener = 1; + _set_state(sock, SOCK_LISTEN); + + UNLOCK(&sock->lock); + return (ISC_R_SUCCESS); +} + +/* + * This should try to do aggressive accept() XXXMLG + */ +isc_result_t +isc__socket_accept(isc_socket_t *sock, + isc_task_t *task, isc_taskaction_t action, void *arg) +{ + isc_socket_newconnev_t *adev; + isc_socketmgr_t *manager; + isc_task_t *ntask = NULL; + isc_socket_t *nsock; + isc_result_t result; + IoCompletionInfo *lpo; + + REQUIRE(VALID_SOCKET(sock)); + + manager = sock->manager; + REQUIRE(VALID_MANAGER(manager)); + + LOCK(&sock->lock); + CONSISTENT(sock); + + /* + * make sure that the socket's not closed + */ + if (sock->fd == INVALID_SOCKET) { + UNLOCK(&sock->lock); + return (ISC_R_CONNREFUSED); + } + + REQUIRE(sock->listener); + + /* + * Sender field is overloaded here with the task we will be sending + * this event to. Just before the actual event is delivered the + * actual ev_sender will be touched up to be the socket. + */ + adev = (isc_socket_newconnev_t *) + isc_event_allocate(manager->mctx, task, ISC_SOCKEVENT_NEWCONN, + action, arg, sizeof(*adev)); + if (adev == NULL) { + UNLOCK(&sock->lock); + return (ISC_R_NOMEMORY); + } + ISC_LINK_INIT(adev, ev_link); + + result = allocate_socket(manager, sock->type, &nsock); + if (result != ISC_R_SUCCESS) { + isc_event_free((isc_event_t **)&adev); + UNLOCK(&sock->lock); + return (result); + } + + /* + * AcceptEx() requires we pass in a socket. + */ + nsock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP); + if (nsock->fd == INVALID_SOCKET) { + free_socket(&nsock, __LINE__); + isc_event_free((isc_event_t **)&adev); + UNLOCK(&sock->lock); + return (ISC_R_FAILURE); // XXXMLG need real error message + } + + /* + * Attach to socket and to task. + */ + isc_task_attach(task, &ntask); + if (isc_task_exiting(ntask)) { + free_socket(&nsock, __LINE__); + isc_task_detach(&ntask); + isc_event_free(ISC_EVENT_PTR(&adev)); + UNLOCK(&sock->lock); + return (ISC_R_SHUTTINGDOWN); + } + nsock->references++; + + adev->ev_sender = ntask; + adev->newsocket = nsock; + _set_state(nsock, SOCK_ACCEPT); + + /* + * Queue io completion for an accept(). + */ + lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle, + HEAP_ZERO_MEMORY, + sizeof(IoCompletionInfo)); + RUNTIME_CHECK(lpo != NULL); + lpo->acceptbuffer = (void *)HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, + (sizeof(SOCKADDR_STORAGE) + 16) * 2); + RUNTIME_CHECK(lpo->acceptbuffer != NULL); + + lpo->adev = adev; + lpo->request_type = SOCKET_ACCEPT; + + ISCAcceptEx(sock->fd, + nsock->fd, /* Accepted Socket */ + lpo->acceptbuffer, /* Buffer for initial Recv */ + 0, /* Length of Buffer */ + sizeof(SOCKADDR_STORAGE) + 16, /* Local address length + 16 */ + sizeof(SOCKADDR_STORAGE) + 16, /* Remote address lengh + 16 */ + (LPDWORD)&lpo->received_bytes, /* Bytes Recved */ + (LPOVERLAPPED)lpo /* Overlapped structure */ + ); + iocompletionport_update(nsock); + + socket_log(__LINE__, sock, NULL, TRACE, + isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, + "accepting for nsock %p fd %d", nsock, nsock->fd); + + /* + * Enqueue the event + */ + ISC_LIST_ENQUEUE(sock->accept_list, adev, ev_link); + sock->pending_accept++; + sock->pending_iocp++; + + UNLOCK(&sock->lock); + return (ISC_R_SUCCESS); +} + +isc_result_t +isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, + isc_task_t *task, isc_taskaction_t action, void *arg) +{ + char strbuf[ISC_STRERRORSIZE]; + isc_socket_connev_t *cdev; + isc_task_t *ntask = NULL; + isc_socketmgr_t *manager; + IoCompletionInfo *lpo; + int bind_errno; + + REQUIRE(VALID_SOCKET(sock)); + REQUIRE(addr != NULL); + REQUIRE(task != NULL); + REQUIRE(action != NULL); + + manager = sock->manager; + REQUIRE(VALID_MANAGER(manager)); + REQUIRE(addr != NULL); + + if (isc_sockaddr_ismulticast(addr)) + return (ISC_R_MULTICAST); + + LOCK(&sock->lock); + CONSISTENT(sock); + + /* + * make sure that the socket's not closed + */ + if (sock->fd == INVALID_SOCKET) { + UNLOCK(&sock->lock); + return (ISC_R_CONNREFUSED); + } + + /* + * Windows sockets won't connect unless the socket is bound. + */ + if (!sock->bound) { + isc_sockaddr_t any; + + isc_sockaddr_anyofpf(&any, isc_sockaddr_pf(addr)); + if (bind(sock->fd, &any.type.sa, any.length) < 0) { + bind_errno = WSAGetLastError(); + UNLOCK(&sock->lock); + switch (bind_errno) { + case WSAEACCES: + return (ISC_R_NOPERM); + case WSAEADDRNOTAVAIL: + return (ISC_R_ADDRNOTAVAIL); + case WSAEADDRINUSE: + return (ISC_R_ADDRINUSE); + case WSAEINVAL: + return (ISC_R_BOUND); + default: + isc__strerror(bind_errno, strbuf, + sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "bind: %s", strbuf); + return (ISC_R_UNEXPECTED); + } + } + sock->bound = 1; + } + + cdev = (isc_socket_connev_t *)isc_event_allocate(manager->mctx, sock, + ISC_SOCKEVENT_CONNECT, + action, arg, + sizeof(*cdev)); + if (cdev == NULL) { + UNLOCK(&sock->lock); + return (ISC_R_NOMEMORY); + } + ISC_LINK_INIT(cdev, ev_link); + + if (sock->connected) { + INSIST(isc_sockaddr_equal(&sock->address, addr)); + cdev->result = ISC_R_SUCCESS; + isc_task_send(task, ISC_EVENT_PTR(&cdev)); + + UNLOCK(&sock->lock); + return (ISC_R_SUCCESS); + } + + if ((sock->type == isc_sockettype_tcp) && !sock->pending_connect) { + /* + * Queue io completion for an accept(). + */ + lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle, + HEAP_ZERO_MEMORY, + sizeof(IoCompletionInfo)); + lpo->cdev = cdev; + lpo->request_type = SOCKET_CONNECT; + + sock->address = *addr; + ISCConnectEx(sock->fd, &addr->type.sa, addr->length, + NULL, 0, NULL, (LPOVERLAPPED)lpo); + + /* + * Attach to task. + */ + isc_task_attach(task, &ntask); + cdev->ev_sender = ntask; + + sock->pending_connect = 1; + _set_state(sock, SOCK_CONNECT); + + /* + * Enqueue the request. + */ + INSIST(!ISC_LINK_LINKED(cdev, ev_link)); + ISC_LIST_ENQUEUE(sock->connect_list, cdev, ev_link); + sock->pending_iocp++; + } else if (sock->type == isc_sockettype_tcp) { + INSIST(sock->pending_connect); + INSIST(isc_sockaddr_equal(&sock->address, addr)); + isc_task_attach(task, &ntask); + cdev->ev_sender = ntask; + INSIST(!ISC_LINK_LINKED(cdev, ev_link)); + ISC_LIST_ENQUEUE(sock->connect_list, cdev, ev_link); + } else { + REQUIRE(!sock->pending_connect); + WSAConnect(sock->fd, &addr->type.sa, addr->length, NULL, NULL, NULL, NULL); + cdev->result = ISC_R_SUCCESS; + isc_task_send(task, (isc_event_t **)&cdev); + } + CONSISTENT(sock); + UNLOCK(&sock->lock); + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc__socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) { + isc_result_t result; + + REQUIRE(VALID_SOCKET(sock)); + REQUIRE(addressp != NULL); + + LOCK(&sock->lock); + CONSISTENT(sock); + + /* + * make sure that the socket's not closed + */ + if (sock->fd == INVALID_SOCKET) { + UNLOCK(&sock->lock); + return (ISC_R_CONNREFUSED); + } + + if (sock->connected) { + *addressp = sock->address; + result = ISC_R_SUCCESS; + } else { + result = ISC_R_NOTCONNECTED; + } + + UNLOCK(&sock->lock); + + return (result); +} + +isc_result_t +isc__socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) { + ISC_SOCKADDR_LEN_T len; + isc_result_t result; + char strbuf[ISC_STRERRORSIZE]; + + REQUIRE(VALID_SOCKET(sock)); + REQUIRE(addressp != NULL); + + LOCK(&sock->lock); + CONSISTENT(sock); + + /* + * make sure that the socket's not closed + */ + if (sock->fd == INVALID_SOCKET) { + UNLOCK(&sock->lock); + return (ISC_R_CONNREFUSED); + } + + if (!sock->bound) { + result = ISC_R_NOTBOUND; + goto out; + } + + result = ISC_R_SUCCESS; + + len = sizeof(addressp->type); + if (getsockname(sock->fd, &addressp->type.sa, (void *)&len) < 0) { + isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf)); + UNEXPECTED_ERROR(__FILE__, __LINE__, "getsockname: %s", + strbuf); + result = ISC_R_UNEXPECTED; + goto out; + } + addressp->length = (unsigned int)len; + + out: + UNLOCK(&sock->lock); + + return (result); +} + +/* + * Run through the list of events on this socket, and cancel the ones + * queued for task "task" of type "how". "how" is a bitmask. + */ +void +isc__socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) { + + REQUIRE(VALID_SOCKET(sock)); + + /* + * Quick exit if there is nothing to do. Don't even bother locking + * in this case. + */ + if (how == 0) + return; + + LOCK(&sock->lock); + CONSISTENT(sock); + + /* + * make sure that the socket's not closed + */ + if (sock->fd == INVALID_SOCKET) { + UNLOCK(&sock->lock); + return; + } + + /* + * All of these do the same thing, more or less. + * Each will: + * o If the internal event is marked as "posted" try to + * remove it from the task's queue. If this fails, mark it + * as canceled instead, and let the task clean it up later. + * o For each I/O request for that task of that type, post + * its done event with status of "ISC_R_CANCELED". + * o Reset any state needed. + */ + + if ((how & ISC_SOCKCANCEL_RECV) == ISC_SOCKCANCEL_RECV) { + isc_socketevent_t *dev; + isc_socketevent_t *next; + isc_task_t *current_task; + + dev = ISC_LIST_HEAD(sock->recv_list); + while (dev != NULL) { + current_task = dev->ev_sender; + next = ISC_LIST_NEXT(dev, ev_link); + if ((task == NULL) || (task == current_task)) { + dev->result = ISC_R_CANCELED; + send_recvdone_event(sock, &dev); + } + dev = next; + } + } + how &= ~ISC_SOCKCANCEL_RECV; + + if ((how & ISC_SOCKCANCEL_SEND) == ISC_SOCKCANCEL_SEND) { + isc_socketevent_t *dev; + isc_socketevent_t *next; + isc_task_t *current_task; + + dev = ISC_LIST_HEAD(sock->send_list); + + while (dev != NULL) { + current_task = dev->ev_sender; + next = ISC_LIST_NEXT(dev, ev_link); + if ((task == NULL) || (task == current_task)) { + dev->result = ISC_R_CANCELED; + send_senddone_event(sock, &dev); + } + dev = next; + } + } + how &= ~ISC_SOCKCANCEL_SEND; + + if (((how & ISC_SOCKCANCEL_ACCEPT) == ISC_SOCKCANCEL_ACCEPT) + && !ISC_LIST_EMPTY(sock->accept_list)) { + isc_socket_newconnev_t *dev; + isc_socket_newconnev_t *next; + isc_task_t *current_task; + + dev = ISC_LIST_HEAD(sock->accept_list); + while (dev != NULL) { + current_task = dev->ev_sender; + next = ISC_LIST_NEXT(dev, ev_link); + + if ((task == NULL) || (task == current_task)) { + + dev->newsocket->references--; + closesocket(dev->newsocket->fd); + dev->newsocket->fd = INVALID_SOCKET; + free_socket(&dev->newsocket, __LINE__); + + dev->result = ISC_R_CANCELED; + send_acceptdone_event(sock, &dev); + } + + dev = next; + } + } + how &= ~ISC_SOCKCANCEL_ACCEPT; + + if (((how & ISC_SOCKCANCEL_CONNECT) == ISC_SOCKCANCEL_CONNECT) + && !ISC_LIST_EMPTY(sock->connect_list)) { + isc_socket_connev_t *dev; + isc_socket_connev_t *next; + isc_task_t *current_task; + + INSIST(sock->pending_connect); + + dev = ISC_LIST_HEAD(sock->connect_list); + + while (dev != NULL) { + current_task = dev->ev_sender; + next = ISC_LIST_NEXT(dev, ev_link); + if ((task == NULL) || (task == current_task)) { + dev->result = ISC_R_CANCELED; + send_connectdone_event(sock, &dev); + } + dev = next; + } + closesocket(sock->fd); + sock->fd = INVALID_SOCKET; + _set_state(sock, SOCK_CLOSED); + } + how &= ~ISC_SOCKCANCEL_CONNECT; + + maybe_free_socket(&sock, __LINE__); +} + +isc_sockettype_t +isc__socket_gettype(isc_socket_t *sock) { + isc_sockettype_t type; + + REQUIRE(VALID_SOCKET(sock)); + + LOCK(&sock->lock); + + /* + * make sure that the socket's not closed + */ + if (sock->fd == INVALID_SOCKET) { + UNLOCK(&sock->lock); + return (ISC_R_CONNREFUSED); + } + + type = sock->type; + UNLOCK(&sock->lock); + return (type); +} + +bool +isc__socket_isbound(isc_socket_t *sock) { + bool val; + + REQUIRE(VALID_SOCKET(sock)); + + LOCK(&sock->lock); + CONSISTENT(sock); + + /* + * make sure that the socket's not closed + */ + if (sock->fd == INVALID_SOCKET) { + UNLOCK(&sock->lock); + return (false); + } + + val = ((sock->bound) ? true : false); + UNLOCK(&sock->lock); + + return (val); +} + +void +isc__socket_ipv6only(isc_socket_t *sock, bool yes) { +#if defined(IPV6_V6ONLY) + int onoff = yes ? 1 : 0; +#else + UNUSED(yes); +#endif + + REQUIRE(VALID_SOCKET(sock)); + +#ifdef IPV6_V6ONLY + if (sock->pf == AF_INET6) { + (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, + (char *)&onoff, sizeof(onoff)); + } +#endif +} + +void +isc__socket_dscp(isc_socket_t *sock, isc_dscp_t dscp) { +#if !defined(IP_TOS) && !defined(IPV6_TCLASS) + UNUSED(dscp); +#else + if (dscp < 0) + return; + + dscp <<= 2; + dscp &= 0xff; +#endif + + REQUIRE(VALID_SOCKET(sock)); + +#ifdef IP_TOS + if (sock->pf == AF_INET) { + (void)setsockopt(sock->fd, IPPROTO_IP, IP_TOS, + (char *)&dscp, sizeof(dscp)); + } +#endif +#ifdef IPV6_TCLASS + if (sock->pf == AF_INET6) { + (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_TCLASS, + (char *)&dscp, sizeof(dscp)); + } +#endif +} + +void +isc__socket_cleanunix(isc_sockaddr_t *addr, bool active) { + UNUSED(addr); + UNUSED(active); +} + +isc_result_t +isc__socket_permunix(isc_sockaddr_t *addr, uint32_t perm, + uint32_t owner, uint32_t group) +{ + UNUSED(addr); + UNUSED(perm); + UNUSED(owner); + UNUSED(group); + return (ISC_R_NOTIMPLEMENTED); +} + +void +isc__socket_setname(isc_socket_t *socket, const char *name, void *tag) { + + /* + * Name 'socket'. + */ + + REQUIRE(VALID_SOCKET(socket)); + + LOCK(&socket->lock); + strlcpy(socket->name, name, sizeof(socket->name)); + socket->tag = tag; + UNLOCK(&socket->lock); +} + +const char * +isc__socket_getname(isc_socket_t *socket) { + return (socket->name); +} + +void * +isc__socket_gettag(isc_socket_t *socket) { + return (socket->tag); +} + +int +isc__socket_getfd(isc_socket_t *socket) { + return ((short) socket->fd); +} + +void +isc__socketmgr_setreserved(isc_socketmgr_t *manager, uint32_t reserved) { + UNUSED(manager); + UNUSED(reserved); +} + +void +isc___socketmgr_maxudp(isc_socketmgr_t *manager, int maxudp) { + + UNUSED(manager); + UNUSED(maxudp); +} + +isc_socketevent_t * +isc_socket_socketevent(isc_mem_t *mctx, void *sender, + isc_eventtype_t eventtype, isc_taskaction_t action, + void *arg) +{ + return (allocate_socketevent(mctx, sender, eventtype, action, arg)); +} + +#ifdef HAVE_LIBXML2 + +static const char * +_socktype(isc_sockettype_t type) { + if (type == isc_sockettype_udp) + return ("udp"); + else if (type == isc_sockettype_tcp) + return ("tcp"); + else if (type == isc_sockettype_unix) + return ("unix"); + else if (type == isc_sockettype_fdwatch) + return ("fdwatch"); + else + return ("not-initialized"); +} + +#define TRY0(a) do { xmlrc = (a); if (xmlrc < 0) goto error; } while(0) +int +isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer) +{ + isc_socket_t *sock = NULL; + char peerbuf[ISC_SOCKADDR_FORMATSIZE]; + isc_sockaddr_t addr; + ISC_SOCKADDR_LEN_T len; + int xmlrc; + + LOCK(&mgr->lock); + +#ifndef ISC_PLATFORM_USETHREADS + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "references")); + TRY0(xmlTextWriterWriteFormatString(writer, "%d", mgr->refs)); + TRY0(xmlTextWriterEndElement(writer)); +#endif + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "sockets")); + sock = ISC_LIST_HEAD(mgr->socklist); + while (sock != NULL) { + LOCK(&sock->lock); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "socket")); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "id")); + TRY0(xmlTextWriterWriteFormatString(writer, "%p", sock)); + TRY0(xmlTextWriterEndElement(writer)); + + if (sock->name[0] != 0) { + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR "name")); + TRY0(xmlTextWriterWriteFormatString(writer, "%s", + sock->name)); + TRY0(xmlTextWriterEndElement(writer)); /* name */ + } + + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR "references")); + TRY0(xmlTextWriterWriteFormatString(writer, "%d", + sock->references)); + TRY0(xmlTextWriterEndElement(writer)); + + TRY0(xmlTextWriterWriteElement(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR _socktype(sock->type))); + + if (sock->connected) { + isc_sockaddr_format(&sock->address, peerbuf, + sizeof(peerbuf)); + TRY0(xmlTextWriterWriteElement(writer, + ISC_XMLCHAR "peer-address", + ISC_XMLCHAR peerbuf)); + } + + len = sizeof(addr); + if (getsockname(sock->fd, &addr.type.sa, (void *)&len) == 0) { + isc_sockaddr_format(&addr, peerbuf, sizeof(peerbuf)); + TRY0(xmlTextWriterWriteElement(writer, + ISC_XMLCHAR "local-address", + ISC_XMLCHAR peerbuf)); + } + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "states")); + if (sock->pending_recv) + TRY0(xmlTextWriterWriteElement(writer, + ISC_XMLCHAR "state", + ISC_XMLCHAR "pending-receive")); + if (sock->pending_send) + TRY0(xmlTextWriterWriteElement(writer, + ISC_XMLCHAR "state", + ISC_XMLCHAR "pending-send")); + if (sock->pending_accept) + TRY0(xmlTextWriterWriteElement(writer, + ISC_XMLCHAR "state", + ISC_XMLCHAR "pending_accept")); + if (sock->listener) + TRY0(xmlTextWriterWriteElement(writer, + ISC_XMLCHAR "state", + ISC_XMLCHAR "listener")); + if (sock->connected) + TRY0(xmlTextWriterWriteElement(writer, + ISC_XMLCHAR "state", + ISC_XMLCHAR "connected")); + if (sock->pending_connect) + TRY0(xmlTextWriterWriteElement(writer, + ISC_XMLCHAR "state", + ISC_XMLCHAR "connecting")); + if (sock->bound) + TRY0(xmlTextWriterWriteElement(writer, + ISC_XMLCHAR "state", + ISC_XMLCHAR "bound")); + + TRY0(xmlTextWriterEndElement(writer)); /* states */ + + TRY0(xmlTextWriterEndElement(writer)); /* socket */ + + UNLOCK(&sock->lock); + sock = ISC_LIST_NEXT(sock, link); + } + TRY0(xmlTextWriterEndElement(writer)); /* sockets */ + +error: + if (sock != NULL) + UNLOCK(&sock->lock); + + UNLOCK(&mgr->lock); + + return (xmlrc); +} +#endif /* HAVE_LIBXML2 */ + +#ifdef HAVE_JSON +#define CHECKMEM(m) do { \ + if (m == NULL) { \ + result = ISC_R_NOMEMORY;\ + goto error;\ + } \ +} while(0) + +isc_result_t +isc_socketmgr_renderjson(isc_socketmgr_t *mgr, json_object *stats) { + isc_result_t result = ISC_R_SUCCESS; + isc_socket_t *sock = NULL; + char peerbuf[ISC_SOCKADDR_FORMATSIZE]; + isc_sockaddr_t addr; + ISC_SOCKADDR_LEN_T len; + json_object *obj, *array = json_object_new_array(); + + CHECKMEM(array); + + LOCK(&mgr->lock); + +#ifdef USE_SHARED_MANAGER + obj = json_object_new_int(mgr->refs); + CHECKMEM(obj); + json_object_object_add(stats, "references", obj); +#endif /* USE_SHARED_MANAGER */ + + sock = ISC_LIST_HEAD(mgr->socklist); + while (sock != NULL) { + json_object *states, *entry = json_object_new_object(); + char buf[255]; + + CHECKMEM(entry); + json_object_array_add(array, entry); + + LOCK(&sock->lock); + + snprintf(buf, sizeof(buf), "%p", sock); + obj = json_object_new_string(buf); + CHECKMEM(obj); + json_object_object_add(entry, "id", obj); + + if (sock->name[0] != 0) { + obj = json_object_new_string(sock->name); + CHECKMEM(obj); + json_object_object_add(entry, "name", obj); + } + + obj = json_object_new_int(sock->references); + CHECKMEM(obj); + json_object_object_add(entry, "references", obj); + + obj = json_object_new_string(_socktype(sock->type)); + CHECKMEM(obj); + json_object_object_add(entry, "type", obj); + + if (sock->connected) { + isc_sockaddr_format(&sock->address, peerbuf, + sizeof(peerbuf)); + obj = json_object_new_string(peerbuf); + CHECKMEM(obj); + json_object_object_add(entry, "peer-address", obj); + } + + len = sizeof(addr); + if (getsockname(sock->fd, &addr.type.sa, (void *)&len) == 0) { + isc_sockaddr_format(&addr, peerbuf, sizeof(peerbuf)); + obj = json_object_new_string(peerbuf); + CHECKMEM(obj); + json_object_object_add(entry, "local-address", obj); + } + + states = json_object_new_array(); + CHECKMEM(states); + json_object_object_add(entry, "states", states); + + if (sock->pending_recv) { + obj = json_object_new_string("pending-receive"); + CHECKMEM(obj); + json_object_array_add(states, obj); + } + + if (sock->pending_send) { + obj = json_object_new_string("pending-send"); + CHECKMEM(obj); + json_object_array_add(states, obj); + } + + if (sock->pending_accept) { + obj = json_object_new_string("pending-accept"); + CHECKMEM(obj); + json_object_array_add(states, obj); + } + + if (sock->listener) { + obj = json_object_new_string("listener"); + CHECKMEM(obj); + json_object_array_add(states, obj); + } + + if (sock->connected) { + obj = json_object_new_string("connected"); + CHECKMEM(obj); + json_object_array_add(states, obj); + } + + if (sock->pending_connect) { + obj = json_object_new_string("connecting"); + CHECKMEM(obj); + json_object_array_add(states, obj); + } + + if (sock->bound) { + obj = json_object_new_string("bound"); + CHECKMEM(obj); + json_object_array_add(states, obj); + } + + UNLOCK(&sock->lock); + sock = ISC_LIST_NEXT(sock, link); + } + + json_object_object_add(stats, "sockets", array); + array = NULL; + result = ISC_R_SUCCESS; + + error: + if (array != NULL) + json_object_put(array); + + if (sock != NULL) + UNLOCK(&sock->lock); + + UNLOCK(&mgr->lock); + + return (result); +} +#endif /* HAVE_JSON */ + +/* + * Replace ../socket_api.c + */ + +isc_result_t +isc__socket_register(void) { + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, + isc_socketmgr_t **managerp) +{ + isc_result_t result; + + result = isc_socketmgr_create(mctx, managerp); + + if (result == ISC_R_SUCCESS) + isc_appctx_setsocketmgr(actx, *managerp); + + return (result); +} diff --git a/lib/isc/win32/stdio.c b/lib/isc/win32/stdio.c new file mode 100644 index 0000000..a4c8134 --- /dev/null +++ b/lib/isc/win32/stdio.c @@ -0,0 +1,150 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include + +#include +#include + +#include +#include + +#include +#include + +#include "errno2result.h" + +isc_result_t +isc_stdio_open(const char *filename, const char *mode, FILE **fp) { + FILE *f; + + f = fopen(filename, mode); + if (f == NULL) + return (isc__errno2result(errno)); + *fp = f; + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_stdio_close(FILE *f) { + int r; + + r = fclose(f); + if (r == 0) + return (ISC_R_SUCCESS); + else + return (isc__errno2result(errno)); +} + +isc_result_t +isc_stdio_seek(FILE *f, off_t offset, int whence) { + int r; + +#ifndef _WIN64 + r = fseek(f, offset, whence); +#else + r = _fseeki64(f, offset, whence); +#endif + if (r == 0) + return (ISC_R_SUCCESS); + else + return (isc__errno2result(errno)); +} + +isc_result_t +isc_stdio_tell(FILE *f, off_t *offsetp) { +#ifndef _WIN64 + long r; +#else + __int64 r; +#endif + + REQUIRE(offsetp != NULL); + +#ifndef _WIN64 + r = ftell(f); +#else + r = _ftelli64(f); +#endif + if (r >= 0) { + *offsetp = r; + return (ISC_R_SUCCESS); + } else + return (isc__errno2result(errno)); +} + +isc_result_t +isc_stdio_read(void *ptr, size_t size, size_t nmemb, FILE *f, size_t *nret) { + isc_result_t result = ISC_R_SUCCESS; + size_t r; + + clearerr(f); + r = fread(ptr, size, nmemb, f); + if (r != nmemb) { + if (feof(f)) + result = ISC_R_EOF; + else + result = isc__errno2result(errno); + } + if (nret != NULL) + *nret = r; + return (result); +} + +isc_result_t +isc_stdio_write(const void *ptr, size_t size, size_t nmemb, FILE *f, + size_t *nret) +{ + isc_result_t result = ISC_R_SUCCESS; + size_t r; + + clearerr(f); + r = fwrite(ptr, size, nmemb, f); + if (r != nmemb) + result = isc__errno2result(errno); + if (nret != NULL) + *nret = r; + return (result); +} + +isc_result_t +isc_stdio_flush(FILE *f) { + int r; + + r = fflush(f); + if (r == 0) + return (ISC_R_SUCCESS); + else + return (isc__errno2result(errno)); +} + +isc_result_t +isc_stdio_sync(FILE *f) { + struct _stat buf; + int r; + + if (_fstat(_fileno(f), &buf) != 0) + return (isc__errno2result(errno)); + + /* + * Only call _commit() on regular files. + */ + if ((buf.st_mode & S_IFMT) != S_IFREG) + return (ISC_R_SUCCESS); + + r = _commit(_fileno(f)); + if (r == 0) + return (ISC_R_SUCCESS); + else + return (isc__errno2result(errno)); +} + diff --git a/lib/isc/win32/stdtime.c b/lib/isc/win32/stdtime.c new file mode 100644 index 0000000..bff6fd1 --- /dev/null +++ b/lib/isc/win32/stdtime.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include + +#include + +#include +#include +#include + +void +isc_stdtime_get(isc_stdtime_t *t) { + /* + * Set 't' to the number of seconds past 00:00:00 UTC, January 1, 1970. + */ + + REQUIRE(t != NULL); + + (void)_time32(t); +} diff --git a/lib/isc/win32/strerror.c b/lib/isc/win32/strerror.c new file mode 100644 index 0000000..36c9b79 --- /dev/null +++ b/lib/isc/win32/strerror.c @@ -0,0 +1,452 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * Forward declarations + */ + +char * +FormatError(int error); + +char * +GetWSAErrorMessage(int errval); + +char * +NTstrerror(int err, BOOL *bfreebuf); + +/* + * We need to do this this way for profiled locks. + */ + +static isc_mutex_t isc_strerror_lock; +static void init_lock(void) { + RUNTIME_CHECK(isc_mutex_init(&isc_strerror_lock) == ISC_R_SUCCESS); +} + +/* + * This routine needs to free up any buffer allocated by FormatMessage + * if that routine gets used. + */ + +void +isc__strerror(int num, char *buf, size_t size) { + char *msg; + BOOL freebuf; + unsigned int unum = num; + static isc_once_t once = ISC_ONCE_INIT; + + REQUIRE(buf != NULL); + + RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS); + + LOCK(&isc_strerror_lock); + freebuf = FALSE; + msg = NTstrerror(num, &freebuf); + if (msg != NULL) + snprintf(buf, size, "%s", msg); + else + snprintf(buf, size, "Unknown error: %u", unum); + if(freebuf && msg != NULL) { + LocalFree(msg); + } + UNLOCK(&isc_strerror_lock); +} + +/* + * Note this will cause a memory leak unless the memory allocated here + * is freed by calling LocalFree. isc__strerror does this before unlocking. + * This only gets called if there is a system type of error and will likely + * be an unusual event. + */ +char * +FormatError(int error) { + LPVOID lpMsgBuf = NULL; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + error, + /* Default language */ + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, + NULL); + + return (lpMsgBuf); +} + +/* + * This routine checks the error value and calls the WSA Windows Sockets + * Error message function GetWSAErrorMessage below if it's within that range + * since those messages are not available in the system error messages. + */ +char * +NTstrerror(int err, BOOL *bfreebuf) { + char *retmsg = NULL; + + /* Copy the error value first in case of other errors */ + DWORD errval = err; + + *bfreebuf = FALSE; + + /* Get the Winsock2 error messages */ + if (errval >= WSABASEERR && errval <= (WSABASEERR + 1015)) { + retmsg = GetWSAErrorMessage(errval); + if (retmsg != NULL) + return (retmsg); + } + /* + * If it's not one of the standard Unix error codes, + * try a system error message + */ + if (errval > (DWORD) _sys_nerr) { + *bfreebuf = TRUE; + return (FormatError(errval)); + } else { + return (strerror(errval)); + } +} + +/* + * This is a replacement for perror + */ +void __cdecl +NTperror(char *errmsg) { + /* Copy the error value first in case of other errors */ + int errval = errno; + BOOL bfreebuf = FALSE; + char *msg; + + msg = NTstrerror(errval, &bfreebuf); + fprintf(stderr, "%s: %s\n", errmsg, msg); + if(bfreebuf == TRUE) { + LocalFree(msg); + } + +} + +/* + * Return the error string related to Winsock2 errors. + * This function is necessary since FormatMessage knows nothing about them + * and there is no function to get them. + */ +char * +GetWSAErrorMessage(int errval) { + char *msg; + + switch (errval) { + + case WSAEINTR: + msg = "Interrupted system call"; + break; + + case WSAEBADF: + msg = "Bad file number"; + break; + + case WSAEACCES: + msg = "Permission denied"; + break; + + case WSAEFAULT: + msg = "Bad address"; + break; + + case WSAEINVAL: + msg = "Invalid argument"; + break; + + case WSAEMFILE: + msg = "Too many open sockets"; + break; + + case WSAEWOULDBLOCK: + msg = "Operation would block"; + break; + + case WSAEINPROGRESS: + msg = "Operation now in progress"; + break; + + case WSAEALREADY: + msg = "Operation already in progress"; + break; + + case WSAENOTSOCK: + msg = "Socket operation on non-socket"; + break; + + case WSAEDESTADDRREQ: + msg = "Destination address required"; + break; + + case WSAEMSGSIZE: + msg = "Message too long"; + break; + + case WSAEPROTOTYPE: + msg = "Protocol wrong type for socket"; + break; + + case WSAENOPROTOOPT: + msg = "Bad protocol option"; + break; + + case WSAEPROTONOSUPPORT: + msg = "Protocol not supported"; + break; + + case WSAESOCKTNOSUPPORT: + msg = "Socket type not supported"; + break; + + case WSAEOPNOTSUPP: + msg = "Operation not supported on socket"; + break; + + case WSAEPFNOSUPPORT: + msg = "Protocol family not supported"; + break; + + case WSAEAFNOSUPPORT: + msg = "Address family not supported"; + break; + + case WSAEADDRINUSE: + msg = "Address already in use"; + break; + + case WSAEADDRNOTAVAIL: + msg = "Can't assign requested address"; + break; + + case WSAENETDOWN: + msg = "Network is down"; + break; + + case WSAENETUNREACH: + msg = "Network is unreachable"; + break; + + case WSAENETRESET: + msg = "Net connection reset"; + break; + + case WSAECONNABORTED: + msg = "Software caused connection abort"; + break; + + case WSAECONNRESET: + msg = "Connection reset by peer"; + break; + + case WSAENOBUFS: + msg = "No buffer space available"; + break; + + case WSAEISCONN: + msg = "Socket is already connected"; + break; + + case WSAENOTCONN: + msg = "Socket is not connected"; + break; + + case WSAESHUTDOWN: + msg = "Can't send after socket shutdown"; + break; + + case WSAETOOMANYREFS: + msg = "Too many references: can't splice"; + break; + + case WSAETIMEDOUT: + msg = "Connection timed out"; + break; + + case WSAECONNREFUSED: + msg = "Connection refused"; + break; + + case WSAELOOP: + msg = "Too many levels of symbolic links"; + break; + + case WSAENAMETOOLONG: + msg = "File name too long"; + break; + + case WSAEHOSTDOWN: + msg = "Host is down"; + break; + + case WSAEHOSTUNREACH: + msg = "No route to host"; + break; + + case WSAENOTEMPTY: + msg = "Directory not empty"; + break; + + case WSAEPROCLIM: + msg = "Too many processes"; + break; + + case WSAEUSERS: + msg = "Too many users"; + break; + + case WSAEDQUOT: + msg = "Disc quota exceeded"; + break; + + case WSAESTALE: + msg = "Stale NFS file handle"; + break; + + case WSAEREMOTE: + msg = "Too many levels of remote in path"; + break; + + case WSASYSNOTREADY: + msg = "Network system is unavailable"; + break; + + case WSAVERNOTSUPPORTED: + msg = "Winsock version out of range"; + break; + + case WSANOTINITIALISED: + msg = "WSAStartup not yet called"; + break; + + case WSAEDISCON: + msg = "Graceful shutdown in progress"; + break; +/* + case WSAHOST_NOT_FOUND: + msg = "Host not found"; + break; + + case WSANO_DATA: + msg = "No host data of that type was found"; + break; +*/ + default: + msg = NULL; + break; + } + return (msg); +} + +/* + * These error messages are more informative about CryptAPI Errors than the + * standard error messages + */ + +char * +GetCryptErrorMessage(int errval) { + char *msg; + + switch (errval) { + + case NTE_BAD_FLAGS: + msg = "The dwFlags parameter has an illegal value."; + break; + case NTE_BAD_KEYSET: + msg = "The Registry entry for the key container " + "could not be opened and may not exist."; + break; + case NTE_BAD_KEYSET_PARAM: + msg = "The pszContainer or pszProvider parameter " + "is set to an illegal value."; + break; + case NTE_BAD_PROV_TYPE: + msg = "The value of the dwProvType parameter is out " + "of range. All provider types must be from " + "1 to 999, inclusive."; + break; + case NTE_BAD_SIGNATURE: + msg = "The provider DLL signature did not verify " + "correctly. Either the DLL or the digital " + "signature has been tampered with."; + break; + case NTE_EXISTS: + msg = "The dwFlags parameter is CRYPT_NEWKEYSET, but the key" + " container already exists."; + break; + case NTE_KEYSET_ENTRY_BAD: + msg = "The Registry entry for the pszContainer key container " + "was found (in the HKEY_CURRENT_USER window), but is " + "corrupt. See the section System Administration for " + " etails about CryptoAPI's Registry usage."; + break; + case NTE_KEYSET_NOT_DEF: + msg = "No Registry entry exists in the HKEY_CURRENT_USER " + "window for the key container specified by " + "pszContainer."; + break; + case NTE_NO_MEMORY: + msg = "The CSP ran out of memory during the operation."; + break; + case NTE_PROV_DLL_NOT_FOUND: + msg = "The provider DLL file does not exist or is not on the " + "current path."; + break; + case NTE_PROV_TYPE_ENTRY_BAD: + msg = "The Registry entry for the provider type specified by " + "dwProvType is corrupt. This error may relate to " + "either the user default CSP list or the machine " + "default CSP list. See the section System " + "Administration for details about CryptoAPI's " + "Registry usage."; + break; + case NTE_PROV_TYPE_NO_MATCH: + msg = "The provider type specified by dwProvType does not " + "match the provider type found in the Registry. Note " + "that this error can only occur when pszProvider " + "specifies an actual CSP name."; + break; + case NTE_PROV_TYPE_NOT_DEF: + msg = "No Registry entry exists for the provider type " + "specified by dwProvType."; + break; + case NTE_PROVIDER_DLL_FAIL: + msg = "The provider DLL file could not be loaded, and " + "may not exist. If it exists, then the file is " + "not a valid DLL."; + break; + case NTE_SIGNATURE_FILE_BAD: + msg = "An error occurred while loading the DLL file image, " + "prior to verifying its signature."; + break; + + default: + msg = NULL; + break; + } + return msg; +} + diff --git a/lib/isc/win32/syslog.c b/lib/isc/win32/syslog.c new file mode 100644 index 0000000..071e187 --- /dev/null +++ b/lib/isc/win32/syslog.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static HANDLE hAppLog = NULL; +static FILE *log_stream; +static int debug_level = 0; + +static struct dsn_c_pvt_sfnt { + int val; + const char *strval; +} facilities[] = { + { LOG_KERN, "kern" }, + { LOG_USER, "user" }, + { LOG_MAIL, "mail" }, + { LOG_DAEMON, "daemon" }, + { LOG_AUTH, "auth" }, + { LOG_SYSLOG, "syslog" }, + { LOG_LPR, "lpr" }, +#ifdef LOG_NEWS + { LOG_NEWS, "news" }, +#endif +#ifdef LOG_UUCP + { LOG_UUCP, "uucp" }, +#endif +#ifdef LOG_CRON + { LOG_CRON, "cron" }, +#endif +#ifdef LOG_AUTHPRIV + { LOG_AUTHPRIV, "authpriv" }, +#endif +#ifdef LOG_FTP + { LOG_FTP, "ftp" }, +#endif + { LOG_LOCAL0, "local0"}, + { LOG_LOCAL1, "local1"}, + { LOG_LOCAL2, "local2"}, + { LOG_LOCAL3, "local3"}, + { LOG_LOCAL4, "local4"}, + { LOG_LOCAL5, "local5"}, + { LOG_LOCAL6, "local6"}, + { LOG_LOCAL7, "local7"}, + { 0, NULL } +}; + +isc_result_t +isc_syslog_facilityfromstring(const char *str, int *facilityp) { + int i; + + REQUIRE(str != NULL); + REQUIRE(facilityp != NULL); + + for (i = 0; facilities[i].strval != NULL; i++) { + if (strcasecmp(facilities[i].strval, str) == 0) { + *facilityp = facilities[i].val; + return (ISC_R_SUCCESS); + } + } + return (ISC_R_NOTFOUND); +} + +/* + * Log to the NT Event Log + */ +void +syslog(int level, const char *fmt, ...) { + va_list ap; + char buf[1024]; + char *str[1]; + + str[0] = buf; + + va_start(ap, fmt); + vsprintf(buf, fmt, ap); + va_end(ap); + + /* Make sure that the channel is open to write the event */ + if (hAppLog != NULL) { + switch (level) { + case LOG_INFO: + case LOG_NOTICE: + case LOG_DEBUG: + ReportEvent(hAppLog, EVENTLOG_INFORMATION_TYPE, 0, + BIND_INFO_MSG, NULL, 1, 0, str, NULL); + break; + case LOG_WARNING: + ReportEvent(hAppLog, EVENTLOG_WARNING_TYPE, 0, + BIND_WARN_MSG, NULL, 1, 0, str, NULL); + break; + default: + ReportEvent(hAppLog, EVENTLOG_ERROR_TYPE, 0, + BIND_ERR_MSG, NULL, 1, 0, str, NULL); + break; + } + } +} + +/* + * Initialize event logging + */ +void +openlog(const char *name, int flags, ...) { + /* Get a handle to the Application event log */ + hAppLog = RegisterEventSource(NULL, name); +} + +/* + * Close the Handle to the application Event Log + * We don't care whether or not we succeeded so ignore return values + * In fact if we failed then we would have nowhere to put the message + */ +void +closelog(void) { + DeregisterEventSource(hAppLog); +} + +/* + * Keep event logging synced with the current debug level + */ +void +ModifyLogLevel(int level) { + debug_level = level; +} + +/* + * Initialize logging for the port section of libbind. + * Piggyback onto stream given. + */ +void +InitNTLogging(FILE *stream, int debug) { + log_stream = stream; + ModifyLogLevel(debug); +} +/* + * This function is for reporting errors to the application + * event log in case the regular syslog is not available + * mainly during startup. It should not be used under normal + * circumstances. + */ +void +NTReportError(const char *name, const char *str) { + HANDLE hNTAppLog = NULL; + const char *buf[1]; + + buf[0] = str; + + hNTAppLog = RegisterEventSource(NULL, name); + + ReportEvent(hNTAppLog, EVENTLOG_ERROR_TYPE, 0, + BIND_ERR_MSG, NULL, 1, 0, buf, NULL); + + DeregisterEventSource(hNTAppLog); +} diff --git a/lib/isc/win32/syslog.h b/lib/isc/win32/syslog.h new file mode 100644 index 0000000..0197165 --- /dev/null +++ b/lib/isc/win32/syslog.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef _SYSLOG_H +#define _SYSLOG_H + +#include + +/* 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 + +#endif diff --git a/lib/isc/win32/thread.c b/lib/isc/win32/thread.c new file mode 100644 index 0000000..ebc2f29 --- /dev/null +++ b/lib/isc/win32/thread.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include + +#include + +#include +#include + +isc_result_t +isc_thread_create(isc_threadfunc_t start, isc_threadarg_t arg, + isc_thread_t *threadp) +{ + isc_thread_t thread; + unsigned int id; + + thread = (isc_thread_t)_beginthreadex(NULL, 0, start, arg, 0, &id); + if (thread == NULL) { + /* XXX */ + return (ISC_R_UNEXPECTED); + } + + *threadp = thread; + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_thread_join(isc_thread_t thread, isc_threadresult_t *rp) { + DWORD result; + + result = WaitForSingleObject(thread, INFINITE); + if (result != WAIT_OBJECT_0) { + /* XXX */ + return (ISC_R_UNEXPECTED); + } + if (rp != NULL && !GetExitCodeThread(thread, rp)) { + /* XXX */ + return (ISC_R_UNEXPECTED); + } + (void)CloseHandle(thread); + + return (ISC_R_SUCCESS); +} + +void +isc_thread_setconcurrency(unsigned int level) { + /* + * This is unnecessary on Win32 systems, but is here so that the + * call exists + */ +} + +void +isc_thread_setname(isc_thread_t thread, const char *name) { + UNUSED(thread); + UNUSED(name); +} + +void * +isc_thread_key_getspecific(isc_thread_key_t key) { + return(TlsGetValue(key)); +} + +int +isc_thread_key_setspecific(isc_thread_key_t key, void *value) { + return (TlsSetValue(key, value) ? 0 : GetLastError()); +} + +int +isc_thread_key_create(isc_thread_key_t *key, void (*func)(void *)) { + *key = TlsAlloc(); + + return ((*key != -1) ? 0 : GetLastError()); +} + +int +isc_thread_key_delete(isc_thread_key_t key) { + return (TlsFree(key) ? 0 : GetLastError()); +} diff --git a/lib/isc/win32/time.c b/lib/isc/win32/time.c new file mode 100644 index 0000000..a1c8a84 --- /dev/null +++ b/lib/isc/win32/time.c @@ -0,0 +1,388 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +/* + * struct FILETIME uses "100-nanoseconds intervals". + * NS / S = 1000000000 (10^9). + * While it is reasonably obvious that this makes the needed + * conversion factor 10^7, it is coded this way for additional clarity. + */ +#define NS_PER_S 1000000000 +#define NS_INTERVAL 100 +#define INTERVALS_PER_S (NS_PER_S / NS_INTERVAL) + +/*** + *** Absolute Times + ***/ + +static const isc_time_t epoch = { { 0, 0 } }; +LIBISC_EXTERNAL_DATA const isc_time_t * const isc_time_epoch = &epoch; + +/*** + *** Intervals + ***/ + +static const isc_interval_t zero_interval = { 0 }; +LIBISC_EXTERNAL_DATA const isc_interval_t * const isc_interval_zero = &zero_interval; + +void +isc_interval_set(isc_interval_t *i, unsigned int seconds, + unsigned int nanoseconds) +{ + REQUIRE(i != NULL); + REQUIRE(nanoseconds < NS_PER_S); + + /* + * This rounds nanoseconds up not down. + */ + i->interval = (LONGLONG)seconds * INTERVALS_PER_S + + (nanoseconds + NS_INTERVAL - 1) / NS_INTERVAL; +} + +bool +isc_interval_iszero(const isc_interval_t *i) { + REQUIRE(i != NULL); + if (i->interval == 0) + return (true); + + return (false); +} + +void +isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) { + SYSTEMTIME epoch1970 = { 1970, 1, 4, 1, 0, 0, 0, 0 }; + FILETIME temp; + ULARGE_INTEGER i1; + + REQUIRE(t != NULL); + REQUIRE(nanoseconds < NS_PER_S); + + SystemTimeToFileTime(&epoch1970, &temp); + + i1.LowPart = temp.dwLowDateTime; + i1.HighPart = temp.dwHighDateTime; + + i1.QuadPart += (unsigned __int64)nanoseconds/100; + i1.QuadPart += (unsigned __int64)seconds*10000000; + + t->absolute.dwLowDateTime = i1.LowPart; + t->absolute.dwHighDateTime = i1.HighPart; +} + +void +isc_time_settoepoch(isc_time_t *t) { + REQUIRE(t != NULL); + + t->absolute.dwLowDateTime = 0; + t->absolute.dwHighDateTime = 0; +} + +bool +isc_time_isepoch(const isc_time_t *t) { + REQUIRE(t != NULL); + + if (t->absolute.dwLowDateTime == 0 && + t->absolute.dwHighDateTime == 0) + return (true); + + return (false); +} + +isc_result_t +isc_time_now(isc_time_t *t) { + REQUIRE(t != NULL); + + GetSystemTimeAsFileTime(&t->absolute); + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) { + ULARGE_INTEGER i1; + + REQUIRE(t != NULL); + REQUIRE(i != NULL); + + GetSystemTimeAsFileTime(&t->absolute); + + i1.LowPart = t->absolute.dwLowDateTime; + i1.HighPart = t->absolute.dwHighDateTime; + + if (UINT64_MAX - i1.QuadPart < (unsigned __int64)i->interval) + return (ISC_R_RANGE); + + i1.QuadPart += i->interval; + + t->absolute.dwLowDateTime = i1.LowPart; + t->absolute.dwHighDateTime = i1.HighPart; + + return (ISC_R_SUCCESS); +} + +int +isc_time_compare(const isc_time_t *t1, const isc_time_t *t2) { + REQUIRE(t1 != NULL && t2 != NULL); + + return ((int)CompareFileTime(&t1->absolute, &t2->absolute)); +} + +isc_result_t +isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result) +{ + ULARGE_INTEGER i1; + + REQUIRE(t != NULL && i != NULL && result != NULL); + + i1.LowPart = t->absolute.dwLowDateTime; + i1.HighPart = t->absolute.dwHighDateTime; + + if (UINT64_MAX - i1.QuadPart < (unsigned __int64)i->interval) + return (ISC_R_RANGE); + + i1.QuadPart += i->interval; + + result->absolute.dwLowDateTime = i1.LowPart; + result->absolute.dwHighDateTime = i1.HighPart; + + return (ISC_R_SUCCESS); +} + +isc_result_t +isc_time_subtract(const isc_time_t *t, const isc_interval_t *i, + isc_time_t *result) { + ULARGE_INTEGER i1; + + REQUIRE(t != NULL && i != NULL && result != NULL); + + i1.LowPart = t->absolute.dwLowDateTime; + i1.HighPart = t->absolute.dwHighDateTime; + + if (i1.QuadPart < (unsigned __int64) i->interval) + return (ISC_R_RANGE); + + i1.QuadPart -= i->interval; + + result->absolute.dwLowDateTime = i1.LowPart; + result->absolute.dwHighDateTime = i1.HighPart; + + return (ISC_R_SUCCESS); +} + +uint64_t +isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2) { + ULARGE_INTEGER i1, i2; + LONGLONG i3; + + REQUIRE(t1 != NULL && t2 != NULL); + + i1.LowPart = t1->absolute.dwLowDateTime; + i1.HighPart = t1->absolute.dwHighDateTime; + i2.LowPart = t2->absolute.dwLowDateTime; + i2.HighPart = t2->absolute.dwHighDateTime; + + if (i1.QuadPart <= i2.QuadPart) + return (0); + + /* + * Convert to microseconds. + */ + i3 = (i1.QuadPart - i2.QuadPart) / 10; + + return (i3); +} + +uint32_t +isc_time_seconds(const isc_time_t *t) { + SYSTEMTIME epoch1970 = { 1970, 1, 4, 1, 0, 0, 0, 0 }; + FILETIME temp; + ULARGE_INTEGER i1, i2; + LONGLONG i3; + + SystemTimeToFileTime(&epoch1970, &temp); + + i1.LowPart = t->absolute.dwLowDateTime; + i1.HighPart = t->absolute.dwHighDateTime; + i2.LowPart = temp.dwLowDateTime; + i2.HighPart = temp.dwHighDateTime; + + i3 = (i1.QuadPart - i2.QuadPart) / 10000000; + + return ((uint32_t)i3); +} + +isc_result_t +isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp) { + time_t seconds; + + REQUIRE(t != NULL); + + seconds = (time_t)isc_time_seconds(t); + + INSIST(sizeof(unsigned int) == sizeof(uint32_t)); + INSIST(sizeof(time_t) >= sizeof(uint32_t)); + + if (isc_time_seconds(t) > (~0U>>1) && seconds <= (time_t)(~0U>>1)) + return (ISC_R_RANGE); + + *secondsp = seconds; + + return (ISC_R_SUCCESS); +} + + +uint32_t +isc_time_nanoseconds(const isc_time_t *t) { + ULARGE_INTEGER i; + + i.LowPart = t->absolute.dwLowDateTime; + i.HighPart = t->absolute.dwHighDateTime; + return ((uint32_t)(i.QuadPart % 10000000) * 100); +} + +void +isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) { + FILETIME localft; + SYSTEMTIME st; + char DateBuf[50]; + char TimeBuf[50]; + + REQUIRE(t != NULL); + REQUIRE(buf != NULL); + REQUIRE(len > 0); + + if (FileTimeToLocalFileTime(&t->absolute, &localft) && + FileTimeToSystemTime(&localft, &st)) { + GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, "dd-MMM-yyyy", + DateBuf, 50); + GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER| + TIME_FORCE24HOURFORMAT, &st, NULL, TimeBuf, 50); + + snprintf(buf, len, "%s %s.%03u", DateBuf, TimeBuf, + st.wMilliseconds); + + } else { + strlcpy(buf, "99-Bad-9999 99:99:99.999", len); + } +} + +void +isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) { + SYSTEMTIME st; + char DateBuf[50]; + char TimeBuf[50]; + +/* strftime() format: "%a, %d %b %Y %H:%M:%S GMT" */ + + REQUIRE(t != NULL); + REQUIRE(buf != NULL); + REQUIRE(len > 0); + + if (FileTimeToSystemTime(&t->absolute, &st)) { + GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, + "ddd',' dd MMM yyyy", DateBuf, 50); + GetTimeFormat(LOCALE_USER_DEFAULT, + TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, + &st, "hh':'mm':'ss", TimeBuf, 50); + + snprintf(buf, len, "%s %s GMT", DateBuf, TimeBuf); + } else { + buf[0] = 0; + } +} + +isc_result_t +isc_time_parsehttptimestamp(char *buf, isc_time_t *t) { + struct tm t_tm; + time_t when; + char *p; + + REQUIRE(buf != NULL); + REQUIRE(t != NULL); + + p = isc_tm_strptime(buf, "%a, %d %b %Y %H:%M:%S", &t_tm); + if (p == NULL) + return (ISC_R_UNEXPECTED); + when = isc_tm_timegm(&t_tm); + if (when == -1) + return (ISC_R_UNEXPECTED); + isc_time_set(t, (unsigned int)when, 0); + return (ISC_R_SUCCESS); +} + +void +isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) { + SYSTEMTIME st; + char DateBuf[50]; + char TimeBuf[50]; + + /* strtime() format: "%Y-%m-%dT%H:%M:%SZ" */ + + REQUIRE(t != NULL); + REQUIRE(buf != NULL); + REQUIRE(len > 0); + + if (FileTimeToSystemTime(&t->absolute, &st)) { + GetDateFormat(LOCALE_NEUTRAL, 0, &st, "yyyy-MM-dd", + DateBuf, 50); + GetTimeFormat(LOCALE_NEUTRAL, + TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, + &st, "hh':'mm':'ss", TimeBuf, 50); + snprintf(buf, len, "%sT%sZ", DateBuf, TimeBuf); + } else { + buf[0] = 0; + } +} + +void +isc_time_formatISO8601ms(const isc_time_t *t, char *buf, unsigned int len) { + SYSTEMTIME st; + char DateBuf[50]; + char TimeBuf[50]; + + /* strtime() format: "%Y-%m-%dT%H:%M:%S.SSSZ" */ + + REQUIRE(t != NULL); + REQUIRE(buf != NULL); + REQUIRE(len > 0); + + if (FileTimeToSystemTime(&t->absolute, &st)) { + GetDateFormat(LOCALE_NEUTRAL, 0, &st, "yyyy-MM-dd", + DateBuf, 50); + GetTimeFormat(LOCALE_NEUTRAL, + TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT, + &st, "hh':'mm':'ss", TimeBuf, 50); + snprintf(buf, len, "%sT%s.%03uZ", DateBuf, TimeBuf, + st.wMilliseconds); + } else { + buf[0] = 0; + } +} diff --git a/lib/isc/win32/unistd.h b/lib/isc/win32/unistd.h new file mode 100644 index 0000000..170577e --- /dev/null +++ b/lib/isc/win32/unistd.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* None of these are defined in NT, so define them for our use */ +#define O_NONBLOCK 1 +#define PORT_NONBLOCK O_NONBLOCK + +/* + * fcntl() commands + */ +#define F_SETFL 0 +#define F_GETFL 1 +#define F_SETFD 2 +#define F_GETFD 3 +/* + * Enough problems not having full fcntl() without worrying about this! + */ +#undef F_DUPFD + +int fcntl(int, int, ...); + +/* + * access() related definitions for winXP + */ +#include +#ifndef F_OK +#define F_OK 0 +#endif + +#ifndef X_OK +#define X_OK 1 +#endif + +#ifndef W_OK +#define W_OK 2 +#endif + +#ifndef R_OK +#define R_OK 4 +#endif + +#define access _access + +#include diff --git a/lib/isc/win32/version.c b/lib/isc/win32/version.c new file mode 100644 index 0000000..d86c781 --- /dev/null +++ b/lib/isc/win32/version.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include + +#include + +LIBISC_EXTERNAL_DATA const char isc_version[] = VERSION; + +LIBISC_EXTERNAL_DATA const unsigned int isc_libinterface = LIBINTERFACE; +LIBISC_EXTERNAL_DATA const unsigned int isc_librevision = LIBREVISION; +LIBISC_EXTERNAL_DATA const unsigned int isc_libage = LIBAGE; diff --git a/lib/isc/win32/win32os.c b/lib/isc/win32/win32os.c new file mode 100644 index 0000000..9af95c8 --- /dev/null +++ b/lib/isc/win32/win32os.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include + +#ifndef TESTVERSION +#include +#else +#include +#include +#endif +#include + +int +isc_win32os_versioncheck(unsigned int major, unsigned int minor, + unsigned int spmajor, unsigned int spminor) +{ + OSVERSIONINFOEX osVer; + DWORD typeMask; + ULONGLONG conditionMask; + + memset(&osVer, 0, sizeof(OSVERSIONINFOEX)); + osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + typeMask = 0; + conditionMask = 0; + + /* Optimistic: likely greater */ + osVer.dwMajorVersion = major; + typeMask |= VER_MAJORVERSION; + conditionMask = VerSetConditionMask(conditionMask, + VER_MAJORVERSION, + VER_GREATER); + osVer.dwMinorVersion = minor; + typeMask |= VER_MINORVERSION; + conditionMask = VerSetConditionMask(conditionMask, + VER_MINORVERSION, + VER_GREATER); + osVer.wServicePackMajor = spmajor; + typeMask |= VER_SERVICEPACKMAJOR; + conditionMask = VerSetConditionMask(conditionMask, + VER_SERVICEPACKMAJOR, + VER_GREATER); + osVer.wServicePackMinor = spminor; + typeMask |= VER_SERVICEPACKMINOR; + conditionMask = VerSetConditionMask(conditionMask, + VER_SERVICEPACKMINOR, + VER_GREATER); + if (VerifyVersionInfo(&osVer, typeMask, conditionMask)) + return (1); + + /* Failed: retry with equal */ + conditionMask = 0; + conditionMask = VerSetConditionMask(conditionMask, + VER_MAJORVERSION, + VER_EQUAL); + conditionMask = VerSetConditionMask(conditionMask, + VER_MINORVERSION, + VER_EQUAL); + conditionMask = VerSetConditionMask(conditionMask, + VER_SERVICEPACKMAJOR, + VER_EQUAL); + conditionMask = VerSetConditionMask(conditionMask, + VER_SERVICEPACKMINOR, + VER_EQUAL); + if (VerifyVersionInfo(&osVer, typeMask, conditionMask)) + return (0); + else + return (-1); +} + +#ifdef TESTVERSION +int +main(int argc, char **argv) { + unsigned int major = 0; + unsigned int minor = 0; + unsigned int spmajor = 0; + unsigned int spminor = 0; + int ret; + + if (argc > 1) { + --argc; + ++argv; + major = (unsigned int) atoi(argv[0]); + } + if (argc > 1) { + --argc; + ++argv; + minor = (unsigned int) atoi(argv[0]); + } + if (argc > 1) { + --argc; + ++argv; + spmajor = (unsigned int) atoi(argv[0]); + } + if (argc > 1) { + --argc; + POST(argc); + ++argv; + spminor = (unsigned int) atoi(argv[0]); + } + + ret = isc_win32os_versioncheck(major, minor, spmajor, spminor); + + printf("%s major %u minor %u SP major %u SP minor %u\n", + ret > 0 ? "greater" : (ret == 0 ? "equal" : "less"), + major, minor, spmajor, spminor); + return (ret); +} +#endif -- cgit v1.2.3