diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 07:24:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 07:24:22 +0000 |
commit | 45d6379135504814ab723b57f0eb8be23393a51d (patch) | |
tree | d4f2ec4acca824a8446387a758b0ce4238a4dffa /bin/named/win32 | |
parent | Initial commit. (diff) | |
download | bind9-45d6379135504814ab723b57f0eb8be23393a51d.tar.xz bind9-45d6379135504814ab723b57f0eb8be23393a51d.zip |
Adding upstream version 1:9.16.44.upstream/1%9.16.44upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'bin/named/win32')
-rw-r--r-- | bin/named/win32/dlz_dlopen_driver.c | 578 | ||||
l--------- | bin/named/win32/include/.clang-format | 1 | ||||
-rw-r--r-- | bin/named/win32/include/named/ntservice.h | 31 | ||||
-rw-r--r-- | bin/named/win32/include/named/os.h | 78 | ||||
-rw-r--r-- | bin/named/win32/named.vcxproj.filters.in | 121 | ||||
-rw-r--r-- | bin/named/win32/named.vcxproj.in | 156 | ||||
-rw-r--r-- | bin/named/win32/named.vcxproj.user | 3 | ||||
-rw-r--r-- | bin/named/win32/ntservice.c | 190 | ||||
-rw-r--r-- | bin/named/win32/os.c | 473 |
9 files changed, 1631 insertions, 0 deletions
diff --git a/bin/named/win32/dlz_dlopen_driver.c b/bin/named/win32/dlz_dlopen_driver.c new file mode 100644 index 0000000..7e41e9c --- /dev/null +++ b/bin/named/win32/dlz_dlopen_driver.c @@ -0,0 +1,578 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <inttypes.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <windows.h> + +#include <isc/mem.h> +#include <isc/print.h> +#include <isc/result.h> +#include <isc/util.h> + +#include <dns/dlz_dlopen.h> +#include <dns/log.h> +#include <dns/result.h> + +#include <dlz/dlz_dlopen_driver.h> +#include <named/globals.h> + +#ifdef ISC_DLZ_DLOPEN +static dns_sdlzimplementation_t *dlz_dlopen = NULL; + +typedef struct dlopen_data { + isc_mem_t *mctx; + char *dl_path; + char *dlzname; + HMODULE dl_handle; + void *dbdata; + unsigned int flags; + isc_mutex_t lock; + int version; + bool in_configure; + + dlz_dlopen_version_t *dlz_version; + dlz_dlopen_create_t *dlz_create; + dlz_dlopen_findzonedb_t *dlz_findzonedb; + dlz_dlopen_lookup_t *dlz_lookup; + dlz_dlopen_authority_t *dlz_authority; + dlz_dlopen_allnodes_t *dlz_allnodes; + dlz_dlopen_allowzonexfr_t *dlz_allowzonexfr; + dlz_dlopen_newversion_t *dlz_newversion; + dlz_dlopen_closeversion_t *dlz_closeversion; + dlz_dlopen_configure_t *dlz_configure; + dlz_dlopen_ssumatch_t *dlz_ssumatch; + dlz_dlopen_addrdataset_t *dlz_addrdataset; + dlz_dlopen_subrdataset_t *dlz_subrdataset; + dlz_dlopen_delrdataset_t *dlz_delrdataset; + dlz_dlopen_destroy_t *dlz_destroy; +} dlopen_data_t; + +/* Modules can choose whether they are lock-safe or not. */ +#define MAYBE_LOCK(cd) \ + do { \ + if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \ + !cd->in_configure) \ + LOCK(&cd->lock); \ + } while (0) + +#define MAYBE_UNLOCK(cd) \ + do { \ + if ((cd->flags & DNS_SDLZFLAG_THREADSAFE) == 0 && \ + !cd->in_configure) \ + UNLOCK(&cd->lock); \ + } while (0) + +/* + * Log a message at the given level. + */ +static void +dlopen_log(int level, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, + ISC_LOG_DEBUG(level), fmt, ap); + va_end(ap); +} + +/* + * SDLZ methods + */ + +static isc_result_t +dlopen_dlz_allnodes(const char *zone, void *driverarg, void *dbdata, + dns_sdlzallnodes_t *allnodes) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_allnodes == NULL) { + return (ISC_R_NOPERM); + } + + MAYBE_LOCK(cd); + result = cd->dlz_allnodes(zone, cd->dbdata, allnodes); + MAYBE_UNLOCK(cd); + return (result); +} + +static isc_result_t +dlopen_dlz_allowzonexfr(void *driverarg, void *dbdata, const char *name, + const char *client) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_allowzonexfr == NULL) { + return (ISC_R_NOPERM); + } + + MAYBE_LOCK(cd); + result = cd->dlz_allowzonexfr(cd->dbdata, name, client); + MAYBE_UNLOCK(cd); + return (result); +} + +static isc_result_t +dlopen_dlz_authority(const char *zone, void *driverarg, void *dbdata, + dns_sdlzlookup_t *lookup) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_authority == NULL) { + return (ISC_R_NOTIMPLEMENTED); + } + + MAYBE_LOCK(cd); + result = cd->dlz_authority(zone, cd->dbdata, lookup); + MAYBE_UNLOCK(cd); + return (result); +} + +static isc_result_t +dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name, + dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + MAYBE_LOCK(cd); + result = cd->dlz_findzonedb(cd->dbdata, name, methods, clientinfo); + MAYBE_UNLOCK(cd); + return (result); +} + +static isc_result_t +dlopen_dlz_lookup(const char *zone, const char *name, void *driverarg, + void *dbdata, dns_sdlzlookup_t *lookup, + dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + MAYBE_LOCK(cd); + result = cd->dlz_lookup(zone, name, cd->dbdata, lookup, methods, + clientinfo); + MAYBE_UNLOCK(cd); + return (result); +} + +/* + * Load a symbol from the library + */ +static void * +dl_load_symbol(dlopen_data_t *cd, const char *symbol, bool mandatory) { + void *ptr = GetProcAddress(cd->dl_handle, symbol); + if (ptr == NULL && mandatory) { + dlopen_log(ISC_LOG_ERROR, + "dlz_dlopen: library '%s' is missing " + "required symbol '%s'", + cd->dl_path, symbol); + } + return (ptr); +} + +/* + * Called at startup for each dlopen zone in named.conf + */ +static isc_result_t +dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[], + void *driverarg, void **dbdata) { + dlopen_data_t *cd; + isc_mem_t *mctx = NULL; + isc_result_t result = ISC_R_FAILURE; + bool triedload = false; + + UNUSED(driverarg); + + if (argc < 2) { + dlopen_log(ISC_LOG_ERROR, + "dlz_dlopen driver for '%s' needs a path to " + "the shared library", + dlzname); + return (ISC_R_FAILURE); + } + + isc_mem_create(&mctx); + + cd = isc_mem_get(mctx, sizeof(*cd)); + memset(cd, 0, sizeof(*cd)); + + cd->mctx = mctx; + + cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]); + + cd->dlzname = isc_mem_strdup(cd->mctx, dlzname); + + triedload = true; + + /* Initialize the lock */ + isc_mutex_init(&cd->lock); + + /* Open the library */ + cd->dl_handle = LoadLibraryA(cd->dl_path); + if (cd->dl_handle == NULL) { + unsigned int error = GetLastError(); + + dlopen_log(ISC_LOG_ERROR, + "dlz_dlopen failed to open library '%s' - %u", + cd->dl_path, error); + result = ISC_R_FAILURE; + goto cleanup_lock; + } + + /* Find the symbols */ + cd->dlz_version = + (dlz_dlopen_version_t *)dl_load_symbol(cd, "dlz_version", true); + cd->dlz_create = (dlz_dlopen_create_t *)dl_load_symbol(cd, "dlz_create", + true); + cd->dlz_lookup = (dlz_dlopen_lookup_t *)dl_load_symbol(cd, "dlz_lookup", + true); + cd->dlz_findzonedb = (dlz_dlopen_findzonedb_t *)dl_load_symbol( + cd, "dlz_findzonedb", true); + + if (cd->dlz_create == NULL || cd->dlz_version == NULL || + cd->dlz_lookup == NULL || cd->dlz_findzonedb == NULL) + { + /* We're missing a required symbol */ + result = ISC_R_FAILURE; + goto cleanup_lock; + } + + cd->dlz_allowzonexfr = (dlz_dlopen_allowzonexfr_t *)dl_load_symbol( + cd, "dlz_allowzonexfr", false); + cd->dlz_allnodes = (dlz_dlopen_allnodes_t *)dl_load_symbol( + cd, "dlz_allnodes", (cd->dlz_allowzonexfr != NULL)); + cd->dlz_authority = (dlz_dlopen_authority_t *)dl_load_symbol( + cd, "dlz_authority", false); + cd->dlz_newversion = (dlz_dlopen_newversion_t *)dl_load_symbol( + cd, "dlz_newversion", false); + cd->dlz_closeversion = (dlz_dlopen_closeversion_t *)dl_load_symbol( + cd, "dlz_closeversion", (cd->dlz_newversion != NULL)); + cd->dlz_configure = (dlz_dlopen_configure_t *)dl_load_symbol( + cd, "dlz_configure", false); + cd->dlz_ssumatch = (dlz_dlopen_ssumatch_t *)dl_load_symbol( + cd, "dlz_ssumatch", false); + cd->dlz_addrdataset = (dlz_dlopen_addrdataset_t *)dl_load_symbol( + cd, "dlz_addrdataset", false); + cd->dlz_subrdataset = (dlz_dlopen_subrdataset_t *)dl_load_symbol( + cd, "dlz_subrdataset", false); + cd->dlz_delrdataset = (dlz_dlopen_delrdataset_t *)dl_load_symbol( + cd, "dlz_delrdataset", false); + + /* Check the version of the API is the same */ + cd->version = cd->dlz_version(&cd->flags); + if (cd->version < (DLZ_DLOPEN_VERSION - DLZ_DLOPEN_AGE) || + cd->version > DLZ_DLOPEN_VERSION) + { + dlopen_log(ISC_LOG_ERROR, + "dlz_dlopen: %s: incorrect driver API version %d, " + "requires %d", + cd->dl_path, cd->version, DLZ_DLOPEN_VERSION); + result = ISC_R_FAILURE; + goto cleanup_lock; + } + + /* + * Call the library's create function. Note that this is an + * extended version of dlz create, with the addition of + * named function pointers for helper functions that the + * driver will need. This avoids the need for the backend to + * link the BIND9 libraries + */ + MAYBE_LOCK(cd); + result = cd->dlz_create(dlzname, argc - 1, argv + 1, &cd->dbdata, "log", + dlopen_log, "putrr", dns_sdlz_putrr, + "putnamedrr", dns_sdlz_putnamedrr, + "writeable_zone", dns_dlz_writeablezone, NULL); + MAYBE_UNLOCK(cd); + if (result != ISC_R_SUCCESS) { + goto cleanup_lock; + } + + *dbdata = cd; + + return (ISC_R_SUCCESS); + +cleanup_lock: + isc_mutex_destroy(&cd->lock); +failed: + dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname); + if (cd->dl_path) { + isc_mem_free(mctx, cd->dl_path); + } + if (cd->dlzname) { + isc_mem_free(mctx, cd->dlzname); + } + if (triedload) { + isc_mutex_destroy(&cd->lock); + } + if (cd->dl_handle) { + FreeLibrary(cd->dl_handle); + } + isc_mem_put(mctx, cd, sizeof(*cd)); + isc_mem_destroy(&mctx); + return (result); +} + +/* + * Called when bind is shutting down + */ +static void +dlopen_dlz_destroy(void *driverarg, void *dbdata) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_mem_t *mctx; + + UNUSED(driverarg); + + if (cd->dlz_destroy) { + MAYBE_LOCK(cd); + cd->dlz_destroy(cd->dbdata); + MAYBE_UNLOCK(cd); + } + + if (cd->dl_path) { + isc_mem_free(cd->mctx, cd->dl_path); + } + if (cd->dlzname) { + isc_mem_free(cd->mctx, cd->dlzname); + } + + if (cd->dl_handle) { + FreeLibrary(cd->dl_handle); + } + + isc_mutex_destroy(&cd->lock); + + mctx = cd->mctx; + isc_mem_put(mctx, cd, sizeof(*cd)); + isc_mem_destroy(&mctx); +} + +/* + * Called to start a transaction + */ +static isc_result_t +dlopen_dlz_newversion(const char *zone, void *driverarg, void *dbdata, + void **versionp) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_newversion == NULL) { + return (ISC_R_NOTIMPLEMENTED); + } + + MAYBE_LOCK(cd); + result = cd->dlz_newversion(zone, cd->dbdata, versionp); + MAYBE_UNLOCK(cd); + return (result); +} + +/* + * Called to end a transaction + */ +static void +dlopen_dlz_closeversion(const char *zone, bool commit, void *driverarg, + void *dbdata, void **versionp) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + + UNUSED(driverarg); + + if (cd->dlz_newversion == NULL) { + *versionp = NULL; + return; + } + + MAYBE_LOCK(cd); + cd->dlz_closeversion(zone, commit, cd->dbdata, versionp); + MAYBE_UNLOCK(cd); +} + +/* + * Called on startup to configure any writeable zones + */ +static isc_result_t +dlopen_dlz_configure(dns_view_t *view, dns_dlzdb_t *dlzdb, void *driverarg, + void *dbdata) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_configure == NULL) { + return (ISC_R_SUCCESS); + } + + MAYBE_LOCK(cd); + cd->in_configure = true; + result = cd->dlz_configure(view, dlzdb, cd->dbdata); + cd->in_configure = false; + MAYBE_UNLOCK(cd); + + return (result); +} + +/* + * Check for authority to change a name + */ +static bool +dlopen_dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr, + const char *type, const char *key, uint32_t keydatalen, + unsigned char *keydata, void *driverarg, void *dbdata) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + bool ret; + + UNUSED(driverarg); + + if (cd->dlz_ssumatch == NULL) { + return (false); + } + + MAYBE_LOCK(cd); + ret = cd->dlz_ssumatch(signer, name, tcpaddr, type, key, keydatalen, + keydata, cd->dbdata); + MAYBE_UNLOCK(cd); + + return (ret); +} + +/* + * Add an rdataset + */ +static isc_result_t +dlopen_dlz_addrdataset(const char *name, const char *rdatastr, void *driverarg, + void *dbdata, void *version) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_addrdataset == NULL) { + return (ISC_R_NOTIMPLEMENTED); + } + + MAYBE_LOCK(cd); + result = cd->dlz_addrdataset(name, rdatastr, cd->dbdata, version); + MAYBE_UNLOCK(cd); + + return (result); +} + +/* + * Subtract an rdataset + */ +static isc_result_t +dlopen_dlz_subrdataset(const char *name, const char *rdatastr, void *driverarg, + void *dbdata, void *version) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_subrdataset == NULL) { + return (ISC_R_NOTIMPLEMENTED); + } + + MAYBE_LOCK(cd); + result = cd->dlz_subrdataset(name, rdatastr, cd->dbdata, version); + MAYBE_UNLOCK(cd); + + return (result); +} + +/* + * delete a rdataset + */ +static isc_result_t +dlopen_dlz_delrdataset(const char *name, const char *type, void *driverarg, + void *dbdata, void *version) { + dlopen_data_t *cd = (dlopen_data_t *)dbdata; + isc_result_t result; + + UNUSED(driverarg); + + if (cd->dlz_delrdataset == NULL) { + return (ISC_R_NOTIMPLEMENTED); + } + + MAYBE_LOCK(cd); + result = cd->dlz_delrdataset(name, type, cd->dbdata, version); + MAYBE_UNLOCK(cd); + + return (result); +} + +static dns_sdlzmethods_t dlz_dlopen_methods = { + dlopen_dlz_create, dlopen_dlz_destroy, dlopen_dlz_findzonedb, + dlopen_dlz_lookup, dlopen_dlz_authority, dlopen_dlz_allnodes, + dlopen_dlz_allowzonexfr, dlopen_dlz_newversion, dlopen_dlz_closeversion, + dlopen_dlz_configure, dlopen_dlz_ssumatch, dlopen_dlz_addrdataset, + dlopen_dlz_subrdataset, dlopen_dlz_delrdataset +}; +#endif /* ifdef ISC_DLZ_DLOPEN */ + +/* + * Register driver with BIND + */ +isc_result_t +dlz_dlopen_init(isc_mem_t *mctx) { +#ifndef ISC_DLZ_DLOPEN + UNUSED(mctx); + return (ISC_R_NOTIMPLEMENTED); +#else /* ifndef ISC_DLZ_DLOPEN */ + isc_result_t result; + + dlopen_log(2, "Registering DLZ_dlopen driver"); + + result = dns_sdlzregister("dlopen", &dlz_dlopen_methods, NULL, + DNS_SDLZFLAG_RELATIVEOWNER | + DNS_SDLZFLAG_RELATIVERDATA | + DNS_SDLZFLAG_THREADSAFE, + mctx, &dlz_dlopen); + + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "dns_sdlzregister() failed: %s", + isc_result_totext(result)); + result = ISC_R_UNEXPECTED; + } + + return (result); +#endif /* ifndef ISC_DLZ_DLOPEN */ +} + +/* + * Unregister the driver + */ +void +dlz_dlopen_clear(void) { +#ifdef ISC_DLZ_DLOPEN + dlopen_log(2, "Unregistering DLZ_dlopen driver"); + if (dlz_dlopen != NULL) { + dns_sdlzunregister(&dlz_dlopen); + } +#endif /* ifdef ISC_DLZ_DLOPEN */ +} diff --git a/bin/named/win32/include/.clang-format b/bin/named/win32/include/.clang-format new file mode 120000 index 0000000..e919bba --- /dev/null +++ b/bin/named/win32/include/.clang-format @@ -0,0 +1 @@ +../../../../.clang-format.headers
\ No newline at end of file diff --git a/bin/named/win32/include/named/ntservice.h b/bin/named/win32/include/named/ntservice.h new file mode 100644 index 0000000..0b380e5 --- /dev/null +++ b/bin/named/win32/include/named/ntservice.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef NTSERVICE_H +#define NTSERVICE_H + +#include <winsvc.h> + +#define BIND_DISPLAY_NAME "ISC BIND" +#define BIND_SERVICE_NAME "named" + +void + ntservice_init(); +void UpdateSCM(DWORD); +void +ServiceControl(DWORD dwCtrlCode); +void +ntservice_shutdown(); +BOOL +ntservice_isservice(); +#endif /* ifndef NTSERVICE_H */ diff --git a/bin/named/win32/include/named/os.h b/bin/named/win32/include/named/os.h new file mode 100644 index 0000000..696465b --- /dev/null +++ b/bin/named/win32/include/named/os.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef NAMED_OS_H +#define NAMED_OS_H 1 + +#include <stdbool.h> + +#include <isc/types.h> + +void +named_os_init(const char *progname); + +void +named_os_daemonize(void); + +void +named_os_opendevnull(void); + +void +named_os_closedevnull(void); + +void +named_os_chroot(const char *root); + +void +named_os_inituserinfo(const char *username); + +void +named_os_changeuser(void); + +unsigned int +ns_os_uid(void); + +void +named_os_adjustnofile(void); + +void +named_os_minprivs(void); + +FILE * +named_os_openfile(const char *filename, int mode, bool switch_user); + +void +named_os_writepidfile(const char *filename, bool first_time); + +bool +named_os_issingleton(const char *filename); + +void +named_os_shutdown(void); + +isc_result_t +named_os_gethostname(char *buf, size_t len); + +void +named_os_shutdownmsg(char *command, isc_buffer_t *text); + +void +named_os_tzset(void); + +void +named_os_started(void); + +const char * +named_os_uname(void); + +#endif /* NAMED_OS_H */ diff --git a/bin/named/win32/named.vcxproj.filters.in b/bin/named/win32/named.vcxproj.filters.in new file mode 100644 index 0000000..60b2ec2 --- /dev/null +++ b/bin/named/win32/named.vcxproj.filters.in @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="dlz_dlopen_driver.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="ntservice.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="os.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\builtin.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\config.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\control.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\controlconf.c"> + <Filter>Source Files</Filter> + </ClCompile> +@IF GEOIP + <ClCompile Include="..\geoip.c"> + <Filter>Source Files</Filter> + </ClCompile> +@END GEOIP + <ClCompile Include="..\log.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\logconf.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\main.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\server.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\statschannel.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\tkeyconf.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\tsigconf.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\zoneconf.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="include\named\ntservice.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="include\named\os.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\named\builtin.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\named\config.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\named\control.h"> + <Filter>Header Files</Filter> + </ClInclude> +@IF GEOIP + <ClInclude Include="..\include\named\geoip.h"> + <Filter>Header Files</Filter> + </ClInclude> +@END GEOIP + <ClInclude Include="..\include\named\globals.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\named\log.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\named\logconf.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\named\main.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\named\server.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\named\statschannel.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\named\tkeyconf.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\named\tsigconf.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\named\types.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\named\zoneconf.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> +</Project> diff --git a/bin/named/win32/named.vcxproj.in b/bin/named/win32/named.vcxproj.in new file mode 100644 index 0000000..f470085 --- /dev/null +++ b/bin/named/win32/named.vcxproj.in @@ -0,0 +1,156 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="@TOOLS_VERSION@" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|@PLATFORM@"> + <Configuration>Debug</Configuration> + <Platform>@PLATFORM@</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|@PLATFORM@"> + <Configuration>Release</Configuration> + <Platform>@PLATFORM@</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{723C65DA-A96C-4BA3-A34E-44F11CA346F9}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>named</RootNamespace> + @WINDOWS_TARGET_PLATFORM_VERSION@ + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <CharacterSet>MultiByte</CharacterSet> + @PLATFORM_TOOLSET@ + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>MultiByte</CharacterSet> + @PLATFORM_TOOLSET@ + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>..\..\..\Build\$(Configuration)\</OutDir> + <IntDir>.\$(Configuration)\</IntDir> + <IntDirSharingDetected>None</IntDirSharingDetected> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>..\..\..\Build\$(Configuration)\</OutDir> + <IntDir>.\$(Configuration)\</IntDir> + <IntDirSharingDetected>None</IntDirSharingDetected> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'"> + <ClCompile> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level4</WarningLevel> + <TreatWarningAsError>false</TreatWarningAsError> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;@USE_GSSAPI@BUILDER="Visual Studio";_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <FunctionLevelLinking>true</FunctionLevelLinking> + <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile> + <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation> + <ObjectFileName>.\$(Configuration)\</ObjectFileName> + <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName> + <BrowseInformation>true</BrowseInformation> + <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles> + <AdditionalIncludeDirectories>@LIBUV_INC@@OPENSSL_INC@@GSSAPI_INC@@GEOIP_INC@.\;..\..\..\;@LIBXML2_INC@..\win32\include;..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;..\..\..\lib\bind9\include;..\..\..\lib\ns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <CompileAs>CompileAsC</CompileAs> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile> + <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\ns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>@LIBUV_LIB@@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@@LIBXML2_LIB@@GSSAPI_LIB@@GEOIP_LIB@libisc.lib;libdns.lib;libisccc.lib;libisccfg.lib;libbind9.lib;libns.lib;version.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'"> + <ClCompile> + <WarningLevel>Level1</WarningLevel> + <TreatWarningAsError>true</TreatWarningAsError> + <PrecompiledHeader> + </PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;@USE_GSSAPI@BUILDER="Visual Studio";NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion> + <WholeProgramOptimization>false</WholeProgramOptimization> + <StringPooling>true</StringPooling> + <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile> + <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation> + <ObjectFileName>.\$(Configuration)\</ObjectFileName> + <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName> + <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles> + <AdditionalIncludeDirectories>@LIBUV_INC@@OPENSSL_INC@@GSSAPI_INC@@GEOIP_INC@.\;..\..\..\;@LIBXML2_INC@..\win32\include;..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;..\..\..\lib\bind9\include;..\..\..\lib\ns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <CompileAs>CompileAsC</CompileAs> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>false</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile> + <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration> + <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\ns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>@LIBUV_LIB@@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@@LIBXML2_LIB@@GSSAPI_LIB@@GEOIP_LIB@libisc.lib;libdns.lib;libisccc.lib;libisccfg.lib;libbind9.lib;libns.lib;version.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="..\builtin.c" /> + <ClCompile Include="..\config.c" /> + <ClCompile Include="..\control.c" /> + <ClCompile Include="..\controlconf.c" /> +@IF GEOIP + <ClCompile Include="..\geoip.c" /> +@END GEOIP + <ClCompile Include="..\log.c" /> + <ClCompile Include="..\logconf.c" /> + <ClCompile Include="..\main.c" /> + <ClCompile Include="..\server.c" /> + <ClCompile Include="..\statschannel.c" /> + <ClCompile Include="..\tkeyconf.c" /> + <ClCompile Include="..\tsigconf.c" /> + <ClCompile Include="..\zoneconf.c" /> + <ClCompile Include="dlz_dlopen_driver.c" /> + <ClCompile Include="ntservice.c" /> + <ClCompile Include="os.c" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\include\named\builtin.h" /> + <ClInclude Include="..\include\named\config.h" /> + <ClInclude Include="..\include\named\control.h" /> +@IF GEOIP + <ClInclude Include="..\include\named\geoip.h" /> +@END GEOIP + <ClInclude Include="..\include\named\globals.h" /> + <ClInclude Include="..\include\named\log.h" /> + <ClInclude Include="..\include\named\logconf.h" /> + <ClInclude Include="..\include\named\main.h" /> + <ClInclude Include="..\include\named\server.h" /> + <ClInclude Include="..\include\named\statschannel.h" /> + <ClInclude Include="..\include\named\tkeyconf.h" /> + <ClInclude Include="..\include\named\tsigconf.h" /> + <ClInclude Include="..\include\named\types.h" /> + <ClInclude Include="..\include\named\zoneconf.h" /> + <ClInclude Include="include\named\ntservice.h" /> + <ClInclude Include="include\named\os.h" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> diff --git a/bin/named/win32/named.vcxproj.user b/bin/named/win32/named.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/bin/named/win32/named.vcxproj.user @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +</Project>
\ No newline at end of file diff --git a/bin/named/win32/ntservice.c b/bin/named/win32/ntservice.c new file mode 100644 index 0000000..5c5c40f --- /dev/null +++ b/bin/named/win32/ntservice.c @@ -0,0 +1,190 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <stdio.h> + +#include <isc/app.h> +#include <isc/commandline.h> +#include <isc/log.h> +#include <isc/print.h> +#include <isc/string.h> + +#include <named/globals.h> +#include <named/main.h> +#include <named/ntservice.h> +#include <named/server.h> + +/* Handle to SCM for updating service status */ +static SERVICE_STATUS_HANDLE hServiceStatus = 0; +static BOOL foreground = FALSE; +static char ConsoleTitle[128]; + +/* + * Forward declarations + */ +static int +bindmain_service_wrapper(int argc, char *argv[]); +void +ServiceControl(DWORD dwCtrlCode); +int +bindmain(int, char *[]); /* From main.c */ + +/* + * Initialize the ISC library running as a Windows Service before calling + * bindmain() + */ +static int +bindmain_service_wrapper(int argc, char *argv[]) { + return (isc_lib_ntservice(bindmain, argc, argv)); +} + +/* + * Initialize the Service by registering it. + */ +void +ntservice_init(void) { + if (!foreground) { + /* Register handler with the SCM */ + hServiceStatus = RegisterServiceCtrlHandler( + BIND_SERVICE_NAME, (LPHANDLER_FUNCTION)ServiceControl); + if (!hServiceStatus) { + named_main_earlyfatal("could not register service " + "control handler"); + } + UpdateSCM(SERVICE_RUNNING); + } else { + strlcpy(ConsoleTitle, "BIND Version ", sizeof(ConsoleTitle)); + strlcat(ConsoleTitle, VERSION, sizeof(ConsoleTitle)); + SetConsoleTitle(ConsoleTitle); + } +} + +void +ntservice_shutdown(void) { + UpdateSCM(SERVICE_STOPPED); +} + +/* + * Routine to check if this is a service or a foreground program + */ +BOOL +ntservice_isservice(void) { + return (!foreground); +} + +/* + * ServiceControl(): Handles requests from the SCM and passes them on + * to named. + */ +void +ServiceControl(DWORD dwCtrlCode) { + /* Handle the requested control code */ + switch (dwCtrlCode) { + case SERVICE_CONTROL_INTERROGATE: + UpdateSCM(0); + break; + + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + named_server_flushonshutdown(named_g_server, true); + isc_app_shutdown(); + UpdateSCM(SERVICE_STOP_PENDING); + break; + default: + break; + } +} + +/* + * Tell the Service Control Manager the state of the service. + */ +void +UpdateSCM(DWORD state) { + SERVICE_STATUS ss; + static DWORD dwState = SERVICE_STOPPED; + + if (hServiceStatus) { + if (state) { + dwState = state; + } + + memset(&ss, 0, sizeof(SERVICE_STATUS)); + ss.dwServiceType |= SERVICE_WIN32_OWN_PROCESS; + ss.dwCurrentState = dwState; + ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | + SERVICE_ACCEPT_SHUTDOWN; + ss.dwCheckPoint = 0; + ss.dwServiceSpecificExitCode = 0; + ss.dwWin32ExitCode = NO_ERROR; + ss.dwWaitHint = dwState == SERVICE_STOP_PENDING ? 10000 : 1000; + + if (!SetServiceStatus(hServiceStatus, &ss)) { + ss.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(hServiceStatus, &ss); + } + } +} + +/* unhook main */ + +#undef main + +/* + * This is the entry point for the executable + * We can now call bindmain() explicitly or via StartServiceCtrlDispatcher() + * as we need to. + */ +int +main(int argc, char *argv[]) { + int rc, ch; + + /* Command line users should put -f in the options. */ + isc_commandline_errprint = false; + while ((ch = isc_commandline_parse(argc, argv, NAMED_MAIN_ARGS)) != -1) + { + switch (ch) { + case 'f': + case 'g': + case 'v': + case 'V': + foreground = TRUE; + break; + default: + break; + } + } + isc_commandline_reset = true; + + if (foreground) { + /* run in console window */ + exit(bindmain(argc, argv)); + } else { + /* Start up as service */ + char *SERVICE_NAME = BIND_SERVICE_NAME; + + SERVICE_TABLE_ENTRY dispatchTable[] = { + { TEXT(SERVICE_NAME), + (LPSERVICE_MAIN_FUNCTION)bindmain_service_wrapper }, + { NULL, NULL } + }; + + rc = StartServiceCtrlDispatcher(dispatchTable); + if (!rc) { + fprintf(stderr, "Use -f to run from the command " + "line.\n"); + /* will be 1063 when launched as a console app */ + exit(GetLastError()); + } + } + exit(0); +} diff --git a/bin/named/win32/os.c b/bin/named/win32/os.c new file mode 100644 index 0000000..5503d95 --- /dev/null +++ b/bin/named/win32/os.c @@ -0,0 +1,473 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <io.h> +#include <process.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <syslog.h> + +#include <isc/ntpaths.h> +#include <isc/print.h> +#include <isc/result.h> +#include <isc/string.h> +#include <isc/util.h> +#include <isc/win32os.h> + +#include <named/globals.h> +#include <named/log.h> +#include <named/main.h> +#include <named/ntservice.h> +#include <named/os.h> + +static char *lockfile = NULL; +static char *pidfile = NULL; +static int devnullfd = -1; +static int lockfilefd = -1; + +static BOOL Initialized = FALSE; + +static char *version_error = "named requires Windows 2000 Service Pack 2 or " + "later to run correctly"; + +void +named_paths_init(void) { + if (!Initialized) { + isc_ntpaths_init(); + } + + named_g_conffile = isc_ntpaths_get(NAMED_CONF_PATH); + named_g_defaultpidfile = isc_ntpaths_get(NAMED_PID_PATH); + named_g_defaultlockfile = isc_ntpaths_get(NAMED_LOCK_PATH); + named_g_keyfile = isc_ntpaths_get(RNDC_KEY_PATH); + named_g_defaultsessionkeyfile = isc_ntpaths_get(SESSION_KEY_PATH); + named_g_defaultbindkeys = isc_ntpaths_get(BIND_KEYS_PATH); + + Initialized = TRUE; +} + +/* + * Due to Knowledge base article Q263823 we need to make sure that + * Windows 2000 systems have Service Pack 2 or later installed and + * warn when it isn't. + */ +static void +version_check(const char *progname) { + if ((isc_win32os_versioncheck(4, 0, 0, 0) >= 0) && + (isc_win32os_versioncheck(5, 0, 0, 0) < 0)) + { + return; /* No problem with Version 4.0 */ + } + if (isc_win32os_versioncheck(5, 0, 2, 0) < 0) { + if (ntservice_isservice()) { + NTReportError(progname, version_error); + } else { + fprintf(stderr, "%s\n", version_error); + } + } +} + +static void +setup_syslog(const char *progname) { + int options; + + options = LOG_PID; +#ifdef LOG_NDELAY + options |= LOG_NDELAY; +#endif /* ifdef LOG_NDELAY */ + + openlog(progname, options, LOG_DAEMON); +} + +void +named_os_init(const char *progname) { + named_paths_init(); + setup_syslog(progname); + /* + * XXXMPA. We may need to split ntservice_init() in two and + * just mark as running in named_os_started(). If we do that + * this is where the first part of ntservice_init() should be + * called from. + * + * XXX970 Remove comment if no problems by 9.7.0. + * + * ntservice_init(); + */ + version_check(progname); + /* + * If running in a Cygwin environment, clear the SEM_NOGPFAULTERRORBOX + * bit in the process error mode to prevent Cygwin from concealing + * non-abort() crashes, giving Windows Error Reporting a chance to + * handle such crashes. This is done to ensure all crashes triggered + * by system tests can be detected. + */ + if (getenv("CYGWIN") != NULL) { + SetErrorMode(GetErrorMode() & ~SEM_NOGPFAULTERRORBOX); + } +} + +void +named_os_daemonize(void) { + /* + * Try to set stdin, stdout, and stderr to /dev/null, but press + * on even if it fails. + */ + if (devnullfd != -1) { + if (devnullfd != _fileno(stdin)) { + close(_fileno(stdin)); + (void)_dup2(devnullfd, _fileno(stdin)); + } + if (devnullfd != _fileno(stdout)) { + close(_fileno(stdout)); + (void)_dup2(devnullfd, _fileno(stdout)); + } + if (devnullfd != _fileno(stderr)) { + close(_fileno(stderr)); + (void)_dup2(devnullfd, _fileno(stderr)); + } + } +} + +void +named_os_opendevnull(void) { + devnullfd = open("NUL", O_RDWR, 0); +} + +void +named_os_closedevnull(void) { + if (devnullfd != _fileno(stdin) && devnullfd != _fileno(stdout) && + devnullfd != _fileno(stderr)) + { + close(devnullfd); + devnullfd = -1; + } +} + +void +named_os_chroot(const char *root) { + if (root != NULL) { + named_main_earlyfatal("chroot(): isn't supported by Win32 API"); + } +} + +void +named_os_inituserinfo(const char *username) {} + +void +named_os_changeuser(void) {} + +unsigned int +ns_os_uid(void) { + return (0); +} + +void +named_os_adjustnofile(void) {} + +void +named_os_minprivs(void) {} + +static int +safe_open(const char *filename, int mode, bool append) { + int fd; + struct stat sb; + + if (stat(filename, &sb) == -1) { + if (errno != ENOENT) { + return (-1); + } + } else if ((sb.st_mode & S_IFREG) == 0) { + return (-1); + } + + if (append) { + fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, mode); + } else { + (void)unlink(filename); + fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, mode); + } + return (fd); +} + +static void +cleanup_pidfile(void) { + if (pidfile != NULL) { + (void)unlink(pidfile); + free(pidfile); + } + pidfile = NULL; +} + +static void +cleanup_lockfile(void) { + if (lockfilefd != -1) { + close(lockfilefd); + lockfilefd = -1; + } + + if (lockfile != NULL) { + int n = unlink(lockfile); + if (n == -1 && errno != ENOENT) { + named_main_earlywarning("unlink '%s': failed", + lockfile); + } + free(lockfile); + lockfile = NULL; + } +} + +FILE * +named_os_openfile(const char *filename, int mode, bool switch_user) { + char strbuf[ISC_STRERRORSIZE]; + FILE *fp; + int fd; + + UNUSED(switch_user); + fd = safe_open(filename, mode, false); + if (fd < 0) { + strerror_s(strbuf, sizeof(strbuf), errno); + named_main_earlywarning("could not open file '%s': %s", + filename, strbuf); + return (NULL); + } + + fp = fdopen(fd, "w"); + if (fp == NULL) { + strerror_s(strbuf, sizeof(strbuf), errno); + named_main_earlywarning("could not fdopen() file '%s': %s", + filename, strbuf); + close(fd); + } + + return (fp); +} + +void +named_os_writepidfile(const char *filename, bool first_time) { + FILE *pidlockfile; + pid_t pid; + char strbuf[ISC_STRERRORSIZE]; + void (*report)(const char *, ...); + + /* + * The caller must ensure any required synchronization. + */ + + report = first_time ? named_main_earlyfatal : named_main_earlywarning; + + cleanup_pidfile(); + + if (filename == NULL) { + return; + } + + pidfile = strdup(filename); + if (pidfile == NULL) { + strerror_s(strbuf, sizeof(strbuf), errno); + (*report)("couldn't strdup() '%s': %s", filename, strbuf); + return; + } + + pidlockfile = named_os_openfile( + filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, false); + if (pidlockfile == NULL) { + free(pidfile); + pidfile = NULL; + return; + } + + pid = getpid(); + + if (fprintf(pidlockfile, "%ld\n", (long)pid) < 0) { + (*report)("fprintf() to pid file '%s' failed", filename); + (void)fclose(pidlockfile); + cleanup_pidfile(); + return; + } + if (fflush(pidlockfile) == EOF) { + (*report)("fflush() to pid file '%s' failed", filename); + (void)fclose(pidlockfile); + cleanup_pidfile(); + return; + } + (void)fclose(pidlockfile); +} + +bool +named_os_issingleton(const char *filename) { + char strbuf[ISC_STRERRORSIZE]; + OVERLAPPED o; + + if (lockfilefd != -1) { + return (true); + } + + if (strcasecmp(filename, "none") == 0) { + return (true); + } + + lockfile = strdup(filename); + if (lockfile == NULL) { + strerror_s(strbuf, sizeof(strbuf), errno); + named_main_earlyfatal("couldn't allocate memory for '%s': %s", + filename, strbuf); + } + + /* + * named_os_openfile() uses safeopen() which removes any existing + * files. We can't use that here. + */ + lockfilefd = open(filename, O_WRONLY | O_CREAT, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (lockfilefd == -1) { + cleanup_lockfile(); + return (false); + } + + memset(&o, 0, sizeof(o)); + /* Expect ERROR_LOCK_VIOLATION if already locked */ + if (!LockFileEx((HANDLE)_get_osfhandle(lockfilefd), + LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, + 0, 1, &o)) + { + cleanup_lockfile(); + return (false); + } + + return (true); +} + +void +named_os_shutdown(void) { + closelog(); + cleanup_pidfile(); + + if (lockfilefd != -1) { + (void)UnlockFile((HANDLE)_get_osfhandle(lockfilefd), 0, 0, 0, + 1); + } + cleanup_lockfile(); + + ntservice_shutdown(); /* This MUST be the last thing done */ +} + +isc_result_t +named_os_gethostname(char *buf, size_t len) { + int n; + + n = gethostname(buf, (int)len); + return ((n == 0) ? ISC_R_SUCCESS : ISC_R_FAILURE); +} + +void +named_os_shutdownmsg(char *command, isc_buffer_t *text) { + UNUSED(command); + UNUSED(text); +} + +void +named_os_tzset(void) { +#ifdef HAVE_TZSET + tzset(); +#endif /* ifdef HAVE_TZSET */ +} + +void +named_os_started(void) { + ntservice_init(); +} + +static char unamebuf[BUFSIZ]; +static const char *unamep = NULL; + +static void +getuname(void) { + DWORD fvilen; + char *fvi; + VS_FIXEDFILEINFO *ffi; + UINT ffilen; + SYSTEM_INFO sysinfo; + char *arch; + + fvi = NULL; + fvilen = GetFileVersionInfoSize("kernel32.dll", 0); + if (fvilen == 0) { + goto err; + } + fvi = (char *)malloc(fvilen); + if (fvi == NULL) { + goto err; + } + memset(fvi, 0, fvilen); + if (GetFileVersionInfo("kernel32.dll", 0, fvilen, fvi) == 0) { + goto err; + } + ffi = NULL; + ffilen = 0; + if ((VerQueryValue(fvi, "\\", &ffi, &ffilen) == 0) || (ffi == NULL) || + (ffilen == 0)) + { + goto err; + } + memset(&sysinfo, 0, sizeof(sysinfo)); + GetSystemInfo(&sysinfo); + switch (sysinfo.wProcessorArchitecture) { + case PROCESSOR_ARCHITECTURE_INTEL: + arch = "x86"; + break; + case PROCESSOR_ARCHITECTURE_ARM: + arch = "arm"; + break; + case PROCESSOR_ARCHITECTURE_IA64: + arch = "ia64"; + break; + case PROCESSOR_ARCHITECTURE_AMD64: + arch = "x64"; + break; + default: + arch = "unknown architecture"; + break; + } + + snprintf(unamebuf, sizeof(unamebuf), + "Windows %d %d build %d %d for %s\n", + (ffi->dwProductVersionMS >> 16) & 0xffff, + ffi->dwProductVersionMS & 0xffff, + (ffi->dwProductVersionLS >> 16) & 0xffff, + ffi->dwProductVersionLS & 0xffff, arch); + +err: + if (fvi != NULL) { + free(fvi); + } + unamep = unamebuf; +} + +/* + * GetVersionEx() returns 6.2 (aka Windows 8.1) since it was obsoleted + * so we had to switch to the recommended way to get the Windows version. + */ +const char * +named_os_uname(void) { + if (unamep == NULL) { + getuname(); + } + return (unamep); +} |