2001-07-18 03:43:18 +00:00
|
|
|
/*
|
2014-03-04 23:46:15 +00:00
|
|
|
* Copyright (C) 2004, 2005, 2007-2009, 2012-2014 Internet Systems Consortium, Inc. ("ISC")
|
2004-03-05 05:14:21 +00:00
|
|
|
* Copyright (C) 1999-2002 Internet Software Consortium.
|
2001-07-18 03:43:18 +00:00
|
|
|
*
|
2007-06-18 23:47:57 +00:00
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
2001-07-18 03:43:18 +00:00
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
2004-03-05 05:14:21 +00:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
|
|
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
|
|
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
|
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
|
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
|
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
2001-07-18 03:43:18 +00:00
|
|
|
*/
|
|
|
|
|
2012-02-06 23:46:49 +00:00
|
|
|
/* $Id: os.c,v 1.39 2012/02/06 23:46:44 tbox Exp $ */
|
2001-07-18 03:43:18 +00:00
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
2009-08-05 18:43:37 +00:00
|
|
|
#include <sys/types.h>
|
2001-07-18 03:43:18 +00:00
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <io.h>
|
|
|
|
#include <process.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <syslog.h>
|
|
|
|
|
|
|
|
#include <isc/print.h>
|
|
|
|
#include <isc/result.h>
|
2001-11-21 05:07:25 +00:00
|
|
|
#include <isc/strerror.h>
|
2001-07-18 03:43:18 +00:00
|
|
|
#include <isc/string.h>
|
|
|
|
#include <isc/ntpaths.h>
|
2002-08-01 03:25:34 +00:00
|
|
|
#include <isc/util.h>
|
2002-08-03 01:31:48 +00:00
|
|
|
#include <isc/win32os.h>
|
2001-07-18 03:43:18 +00:00
|
|
|
|
|
|
|
#include <named/main.h>
|
2002-08-03 01:31:48 +00:00
|
|
|
#include <named/log.h>
|
2001-07-18 03:43:18 +00:00
|
|
|
#include <named/os.h>
|
|
|
|
#include <named/globals.h>
|
|
|
|
#include <named/ntservice.h>
|
|
|
|
|
|
|
|
|
|
|
|
static char *pidfile = NULL;
|
2004-01-07 06:17:04 +00:00
|
|
|
static int devnullfd = -1;
|
2014-12-18 11:58:50 +05:30
|
|
|
static int singletonfd = -1;
|
2001-07-18 03:43:18 +00:00
|
|
|
|
|
|
|
static BOOL Initialized = FALSE;
|
|
|
|
|
2008-01-18 23:46:58 +00:00
|
|
|
static char *version_error =
|
2002-08-03 01:31:48 +00:00
|
|
|
"named requires Windows 2000 Service Pack 2 or later to run correctly";
|
|
|
|
|
2001-07-18 03:43:18 +00:00
|
|
|
void
|
2014-03-04 10:42:25 -08:00
|
|
|
ns_paths_init(void) {
|
2001-07-18 18:42:13 +00:00
|
|
|
if (!Initialized)
|
2001-07-18 03:43:18 +00:00
|
|
|
isc_ntpaths_init();
|
2001-07-18 18:42:13 +00:00
|
|
|
|
2001-07-18 03:43:18 +00:00
|
|
|
ns_g_conffile = isc_ntpaths_get(NAMED_CONF_PATH);
|
|
|
|
lwresd_g_conffile = isc_ntpaths_get(LWRES_CONF_PATH);
|
|
|
|
lwresd_g_resolvconffile = isc_ntpaths_get(RESOLV_CONF_PATH);
|
|
|
|
ns_g_conffile = isc_ntpaths_get(NAMED_CONF_PATH);
|
|
|
|
ns_g_defaultpidfile = isc_ntpaths_get(NAMED_PID_PATH);
|
|
|
|
lwresd_g_defaultpidfile = isc_ntpaths_get(LWRESD_PID_PATH);
|
2001-08-09 23:44:13 +00:00
|
|
|
ns_g_keyfile = isc_ntpaths_get(RNDC_KEY_PATH);
|
2009-07-14 22:54:57 +00:00
|
|
|
ns_g_defaultsessionkeyfile = isc_ntpaths_get(SESSION_KEY_PATH);
|
2001-07-18 03:43:18 +00:00
|
|
|
|
|
|
|
Initialized = TRUE;
|
|
|
|
}
|
|
|
|
|
2002-08-03 01:31:48 +00:00
|
|
|
/*
|
|
|
|
* 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_majorversion() < 5)
|
|
|
|
return; /* No problem with Version 4.0 */
|
|
|
|
if(isc_win32os_versioncheck(5, 0, 2, 0) < 0)
|
|
|
|
if (ntservice_isservice())
|
|
|
|
NTReportError(progname, version_error);
|
2008-01-18 23:46:58 +00:00
|
|
|
else
|
2002-08-03 01:31:48 +00:00
|
|
|
fprintf(stderr, "%s\n", version_error);
|
|
|
|
}
|
2001-07-18 03:43:18 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
setup_syslog(const char *progname) {
|
|
|
|
int options;
|
|
|
|
|
|
|
|
options = LOG_PID;
|
|
|
|
#ifdef LOG_NDELAY
|
|
|
|
options |= LOG_NDELAY;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
openlog(progname, options, LOG_DAEMON);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ns_os_init(const char *progname) {
|
|
|
|
ns_paths_init();
|
|
|
|
setup_syslog(progname);
|
2008-01-09 02:35:10 +00:00
|
|
|
/*
|
|
|
|
* XXXMPA. We may need to split ntservice_init() in two and
|
|
|
|
* just mark as running in ns_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();
|
|
|
|
*/
|
2002-08-03 01:31:48 +00:00
|
|
|
version_check(progname);
|
2001-07-18 03:43:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ns_os_daemonize(void) {
|
|
|
|
/*
|
|
|
|
* Try to set stdin, stdout, and stderr to /dev/null, but press
|
|
|
|
* on even if it fails.
|
|
|
|
*/
|
2004-01-07 06:17:04 +00:00
|
|
|
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
|
|
|
|
ns_os_opendevnull(void) {
|
|
|
|
devnullfd = open("NUL", O_RDWR, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ns_os_closedevnull(void) {
|
|
|
|
if (devnullfd != _fileno(stdin) &&
|
|
|
|
devnullfd != _fileno(stdout) &&
|
|
|
|
devnullfd != _fileno(stderr)) {
|
|
|
|
close(devnullfd);
|
|
|
|
devnullfd = -1;
|
2001-07-18 03:43:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ns_os_chroot(const char *root) {
|
2008-11-17 05:41:10 +00:00
|
|
|
if (root != NULL)
|
|
|
|
ns_main_earlyfatal("chroot(): isn't supported by Win32 API");
|
2001-07-18 03:43:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ns_os_inituserinfo(const char *username) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ns_os_changeuser(void) {
|
|
|
|
}
|
|
|
|
|
2008-10-24 01:24:54 +00:00
|
|
|
void
|
|
|
|
ns_os_adjustnofile(void) {
|
|
|
|
}
|
|
|
|
|
2001-07-18 03:43:18 +00:00
|
|
|
void
|
|
|
|
ns_os_minprivs(void) {
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2009-08-05 18:43:37 +00:00
|
|
|
safe_open(const char *filename, int mode, isc_boolean_t append) {
|
2001-07-18 03:43:18 +00:00
|
|
|
int fd;
|
2002-07-10 01:13:44 +00:00
|
|
|
struct stat sb;
|
2001-07-18 03:43:18 +00:00
|
|
|
|
2002-07-10 01:13:44 +00:00
|
|
|
if (stat(filename, &sb) == -1) {
|
|
|
|
if (errno != ENOENT)
|
2001-07-18 03:43:18 +00:00
|
|
|
return (-1);
|
2002-07-10 01:13:44 +00:00
|
|
|
} else if ((sb.st_mode & S_IFREG) == 0)
|
2001-07-18 03:43:18 +00:00
|
|
|
return (-1);
|
|
|
|
|
|
|
|
if (append)
|
2009-08-05 17:35:33 +00:00
|
|
|
fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, mode);
|
2001-07-18 03:43:18 +00:00
|
|
|
else {
|
|
|
|
(void)unlink(filename);
|
2009-08-05 17:35:33 +00:00
|
|
|
fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
|
2001-07-18 03:43:18 +00:00
|
|
|
}
|
|
|
|
return (fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cleanup_pidfile(void) {
|
|
|
|
if (pidfile != NULL) {
|
|
|
|
(void)unlink(pidfile);
|
|
|
|
free(pidfile);
|
|
|
|
}
|
|
|
|
pidfile = NULL;
|
|
|
|
}
|
|
|
|
|
2009-08-05 17:35:33 +00:00
|
|
|
FILE *
|
2009-08-05 18:43:37 +00:00
|
|
|
ns_os_openfile(const char *filename, int mode, isc_boolean_t switch_user) {
|
2009-08-05 17:35:33 +00:00
|
|
|
char strbuf[ISC_STRERRORSIZE];
|
|
|
|
FILE *fp;
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
UNUSED(switch_user);
|
|
|
|
fd = safe_open(filename, mode, ISC_FALSE);
|
|
|
|
if (fd < 0) {
|
|
|
|
isc__strerror(errno, strbuf, sizeof(strbuf));
|
|
|
|
ns_main_earlywarning("could not open file '%s': %s",
|
|
|
|
filename, strbuf);
|
2012-02-06 04:19:33 +00:00
|
|
|
return (NULL);
|
2009-08-05 17:35:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fp = fdopen(fd, "w");
|
2009-08-05 18:43:37 +00:00
|
|
|
if (fp == NULL) {
|
2009-08-05 17:35:33 +00:00
|
|
|
isc__strerror(errno, strbuf, sizeof(strbuf));
|
|
|
|
ns_main_earlywarning("could not fdopen() file '%s': %s",
|
|
|
|
filename, strbuf);
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (fp);
|
|
|
|
}
|
|
|
|
|
2001-07-18 03:43:18 +00:00
|
|
|
void
|
2002-05-03 05:28:29 +00:00
|
|
|
ns_os_writepidfile(const char *filename, isc_boolean_t first_time) {
|
2001-07-18 03:43:18 +00:00
|
|
|
FILE *lockfile;
|
|
|
|
pid_t pid;
|
2001-11-21 05:07:25 +00:00
|
|
|
char strbuf[ISC_STRERRORSIZE];
|
2002-05-03 05:28:29 +00:00
|
|
|
void (*report)(const char *, ...);
|
2001-07-18 03:43:18 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The caller must ensure any required synchronization.
|
|
|
|
*/
|
|
|
|
|
2002-05-03 05:28:29 +00:00
|
|
|
report = first_time ? ns_main_earlyfatal : ns_main_earlywarning;
|
|
|
|
|
2001-07-18 03:43:18 +00:00
|
|
|
cleanup_pidfile();
|
|
|
|
|
2005-03-15 23:16:53 +00:00
|
|
|
if (filename == NULL)
|
2001-10-12 05:40:41 +00:00
|
|
|
return;
|
2009-08-05 17:35:33 +00:00
|
|
|
|
2009-08-05 18:43:37 +00:00
|
|
|
pidfile = strdup(filename);
|
2001-11-22 03:11:01 +00:00
|
|
|
if (pidfile == NULL) {
|
2001-11-21 05:07:25 +00:00
|
|
|
isc__strerror(errno, strbuf, sizeof(strbuf));
|
2009-08-05 17:35:33 +00:00
|
|
|
(*report)("couldn't strdup() '%s': %s", filename, strbuf);
|
2002-05-03 05:28:29 +00:00
|
|
|
return;
|
2001-11-22 03:11:01 +00:00
|
|
|
}
|
2001-07-18 03:43:18 +00:00
|
|
|
|
2009-08-05 17:35:33 +00:00
|
|
|
lockfile = ns_os_openfile(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
|
|
|
|
ISC_FALSE);
|
|
|
|
if (lockfile == NULL) {
|
2002-05-03 05:28:29 +00:00
|
|
|
free(pidfile);
|
|
|
|
pidfile = NULL;
|
|
|
|
return;
|
2001-11-22 03:11:01 +00:00
|
|
|
}
|
2001-07-18 03:43:18 +00:00
|
|
|
|
2002-05-03 05:28:29 +00:00
|
|
|
pid = getpid();
|
|
|
|
|
2002-07-10 01:13:44 +00:00
|
|
|
if (fprintf(lockfile, "%ld\n", (long)pid) < 0) {
|
|
|
|
(*report)("fprintf() to pid file '%s' failed", filename);
|
2002-08-01 03:25:34 +00:00
|
|
|
(void)fclose(lockfile);
|
2002-05-03 05:28:29 +00:00
|
|
|
cleanup_pidfile();
|
|
|
|
return;
|
|
|
|
}
|
2002-07-10 01:13:44 +00:00
|
|
|
if (fflush(lockfile) == EOF) {
|
|
|
|
(*report)("fflush() to pid file '%s' failed", filename);
|
2002-08-01 03:25:34 +00:00
|
|
|
(void)fclose(lockfile);
|
2002-05-03 05:28:29 +00:00
|
|
|
cleanup_pidfile();
|
|
|
|
return;
|
|
|
|
}
|
2001-07-18 03:43:18 +00:00
|
|
|
(void)fclose(lockfile);
|
|
|
|
}
|
|
|
|
|
2014-12-18 11:58:50 +05:30
|
|
|
isc_boolean_t
|
|
|
|
ns_os_issingleton(const char *filename) {
|
|
|
|
OVERLAPPED o;
|
|
|
|
|
|
|
|
if (singletonfd != -1)
|
|
|
|
return (ISC_TRUE);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ns_os_openfile() uses safeopen() which removes any existing
|
|
|
|
* files. We can't use that here.
|
|
|
|
*/
|
|
|
|
singletonfd = open(filename, O_WRONLY | O_CREAT,
|
|
|
|
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
|
|
|
|
if (singletonfd == -1)
|
|
|
|
return (ISC_FALSE);
|
|
|
|
|
|
|
|
memset(&o, 0, sizeof(o));
|
|
|
|
/* Expect ERROR_LOCK_VIOLATION if already locked */
|
|
|
|
if (!LockFileEx((HANDLE) _get_osfhandle(singletonfd),
|
|
|
|
LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY,
|
|
|
|
0, 0, 1, &o)) {
|
|
|
|
close(singletonfd);
|
|
|
|
singletonfd = -1;
|
|
|
|
return (ISC_FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ISC_TRUE);
|
|
|
|
}
|
|
|
|
|
2001-07-18 03:43:18 +00:00
|
|
|
void
|
|
|
|
ns_os_shutdown(void) {
|
|
|
|
closelog();
|
|
|
|
cleanup_pidfile();
|
2014-12-18 11:58:50 +05:30
|
|
|
|
|
|
|
if (singletonfd != -1) {
|
|
|
|
(void) UnlockFile((HANDLE) _get_osfhandle(singletonfd),
|
|
|
|
0, 0, 0, 1);
|
|
|
|
close(singletonfd);
|
|
|
|
singletonfd = -1;
|
|
|
|
}
|
2001-07-18 03:43:18 +00:00
|
|
|
ntservice_shutdown(); /* This MUST be the last thing done */
|
|
|
|
}
|
2001-10-08 07:46:11 +00:00
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
ns_os_gethostname(char *buf, size_t len) {
|
2002-07-10 01:13:44 +00:00
|
|
|
int n;
|
2001-11-18 03:03:42 +00:00
|
|
|
|
2013-12-04 12:47:23 +11:00
|
|
|
n = gethostname(buf, (int)len);
|
2001-11-18 03:03:42 +00:00
|
|
|
return ((n == 0) ? ISC_R_SUCCESS : ISC_R_FAILURE);
|
2001-10-08 07:46:11 +00:00
|
|
|
}
|
2001-11-18 03:03:42 +00:00
|
|
|
|
2001-12-01 00:34:27 +00:00
|
|
|
void
|
|
|
|
ns_os_shutdownmsg(char *command, isc_buffer_t *text) {
|
|
|
|
UNUSED(command);
|
|
|
|
UNUSED(text);
|
|
|
|
}
|
2004-01-07 05:48:15 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
ns_os_tzset(void) {
|
|
|
|
#ifdef HAVE_TZSET
|
|
|
|
tzset();
|
|
|
|
#endif
|
|
|
|
}
|
2004-09-29 06:45:38 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
ns_os_started(void) {
|
2008-01-09 02:35:10 +00:00
|
|
|
ntservice_init();
|
2004-09-29 06:45:38 +00:00
|
|
|
}
|