diff options
Diffstat (limited to 'ports/winnt/libntp')
-rw-r--r-- | ports/winnt/libntp/MSG00001.bin | bin | 0 -> 104 bytes | |||
-rw-r--r-- | ports/winnt/libntp/SetSystemTime.c | 34 | ||||
-rw-r--r-- | ports/winnt/libntp/getclock.c | 63 | ||||
-rw-r--r-- | ports/winnt/libntp/messages.h | 199 | ||||
-rw-r--r-- | ports/winnt/libntp/messages.mc | 161 | ||||
-rw-r--r-- | ports/winnt/libntp/messages.rc | 2 | ||||
-rw-r--r-- | ports/winnt/libntp/randfile.c | 109 | ||||
-rw-r--r-- | ports/winnt/libntp/setpriority.c | 76 | ||||
-rw-r--r-- | ports/winnt/libntp/syslog.c | 219 | ||||
-rw-r--r-- | ports/winnt/libntp/termios.c | 789 | ||||
-rw-r--r-- | ports/winnt/libntp/util_clockstuff.c | 26 | ||||
-rw-r--r-- | ports/winnt/libntp/win32_io.c | 81 |
12 files changed, 1759 insertions, 0 deletions
diff --git a/ports/winnt/libntp/MSG00001.bin b/ports/winnt/libntp/MSG00001.bin Binary files differnew file mode 100644 index 0000000..320ee54 --- /dev/null +++ b/ports/winnt/libntp/MSG00001.bin diff --git a/ports/winnt/libntp/SetSystemTime.c b/ports/winnt/libntp/SetSystemTime.c new file mode 100644 index 0000000..8cb4317 --- /dev/null +++ b/ports/winnt/libntp/SetSystemTime.c @@ -0,0 +1,34 @@ + +#include <config.h> + +#include "clockstuff.h" +#include "ntp_stdlib.h" +#include "ntp_unixtime.h" + +pset_tod_using set_tod_using = NULL; + +int +ntp_set_tod( + struct timeval *tv, + void *tzp + ) +{ + SYSTEMTIME st; + union { + FILETIME ft; + ULONGLONG ull; + } t; + + UNUSED_ARG(tzp); + + t.ull = FILETIME_1970 + + (ULONGLONG)tv->tv_sec * 10 * 1000 * 1000 + + (ULONGLONG)tv->tv_usec * 10; + + if (!FileTimeToSystemTime(&t.ft, &st) || !SetSystemTime(&st)) { + msyslog(LOG_ERR, "SetSystemTime failed: %m"); + return -1; + } + + return 0; +} diff --git a/ports/winnt/libntp/getclock.c b/ports/winnt/libntp/getclock.c new file mode 100644 index 0000000..68496bd --- /dev/null +++ b/ports/winnt/libntp/getclock.c @@ -0,0 +1,63 @@ +/* + * getclock.c - Emulate Unix getclock(3) nanosecond interface for libntp/ntpd + */ +#include "config.h" + +#include "ntp_unixtime.h" +#include "clockstuff.h" +#include "ntp_stdlib.h" + +/* + * getclock() is in libntp. To use interpolation, + * ports/winnt/ntpd/nt_clockstuff.c overrides GetSystemTimeAsFileTime + * via the pointer get_sys_time_as_filetime. + */ +PGSTAFT get_sys_time_as_filetime; +PGSTAFT pGetSystemTimePreciseAsFileTime; + + +int +getclock( + int clktyp, + struct timespec *ts + ) +{ + union { + FILETIME ft; + ULONGLONG ull; + } uNow; + + if (clktyp != TIMEOFDAY) { + TRACE(1, ("getclock() supports only TIMEOFDAY clktyp\n")); + errno = EINVAL; + return -1; + } + + (*get_sys_time_as_filetime)(&uNow.ft); + + /* + * Convert the hecto-nano second time to timespec format + */ + uNow.ull -= FILETIME_1970; + ts->tv_sec = (time_t)( uNow.ull / HECTONANOSECONDS); + ts->tv_nsec = (long)(( uNow.ull % HECTONANOSECONDS) * 100); + + return 0; +} + + +void +init_win_precise_time(void) +{ + HANDLE hDll; + FARPROC pfn; + + hDll = LoadLibrary("kernel32"); + pfn = GetProcAddress(hDll, "GetSystemTimePreciseAsFileTime"); + if (NULL != pfn) { + pGetSystemTimePreciseAsFileTime = (PGSTAFT)pfn; + get_sys_time_as_filetime = pGetSystemTimePreciseAsFileTime; + } else { + get_sys_time_as_filetime = &GetSystemTimeAsFileTime; + } +} diff --git a/ports/winnt/libntp/messages.h b/ports/winnt/libntp/messages.h new file mode 100644 index 0000000..4753711 --- /dev/null +++ b/ports/winnt/libntp/messages.h @@ -0,0 +1,199 @@ + /* + Microsoft Developer Support + Copyright (c) 1992 Microsoft Corporation + + This file contains the message definitions for the Win32 + syslog support messages for the nntp firewall +------------------------------------------------------------------------- + HEADER SECTION + + The header section defines names and language identifiers for use + by the message definitions later in this file. The MessageIdTypedef, + SeverityNames, FacilityNames, and LanguageNames keywords are + optional and not required. + + + + The MessageIdTypedef keyword gives a typedef name that is used in a + type cast for each message code in the generated include file. Each + message code appears in the include file with the format: #define + name ((type) 0xnnnnnnnn) The default value for type is empty, and no + type cast is generated. It is the programmer's responsibility to + specify a typedef statement in the application source code to define + the type. The type used in the typedef must be large enough to + accomodate the entire 32-bit message code. + + + + The SeverityNames keyword defines the set of names that are allowed + as the value of the Severity keyword in the message definition. The + set is delimited by left and right parentheses. Associated with each + severity name is a number that, when shifted left by 30, gives the + bit pattern to logical-OR with the Facility value and MessageId + value to form the full 32-bit message code. The default value of + this keyword is: + + SeverityNames=( + Success=0x0 + Informational=0x1 + Warning=0x2 + Error=0x3 + ) + + Severity values occupy the high two bits of a 32-bit message code. + Any severity value that does not fit in two bits is an error. The + severity codes can be given symbolic names by following each value + with :name + + +FacilityNames=(System=0x0:FACILITY_SYSTEM + Runtime=0x2:FACILITY_RUNTIME + Stubs=0x3:FACILITY_STUBS + Io=0x4:FACILITY_IO_ERROR_CODE + ) + + The FacilityNames keyword defines the set of names that are allowed + as the value of the Facility keyword in the message definition. The + set is delimited by left and right parentheses. Associated with each + facility name is a number that, when shift it left by 16 bits, gives + the bit pattern to logical-OR with the Severity value and MessageId + value to form the full 32-bit message code. The default value of + this keyword is: + + FacilityNames=( + System=0x0FF + Application=0xFFF + ) + + Facility codes occupy the low order 12 bits of the high order + 16-bits of a 32-bit message code. Any facility code that does not + fit in 12 bits is an error. This allows for 4,096 facility codes. + The first 256 codes are reserved for use by the system software. The + facility codes can be given symbolic names by following each value + with :name + + + The LanguageNames keyword defines the set of names that are allowed + as the value of the Language keyword in the message definition. The + set is delimited by left and right parentheses. Associated with each + language name is a number and a file name that are used to name the + generated resource file that contains the messages for that + language. The number corresponds to the language identifier to use + in the resource table. The number is separated from the file name + with a colon. The initial value of LanguageNames is: + + LanguageNames=(English=1:MSG00001) + + Any new names in the source file which don't override the built-in + names are added to the list of valid languages. This allows an + application to support private languages with descriptive names. + + +------------------------------------------------------------------------- + MESSAGE DEFINITION SECTION + + Following the header section is the body of the Message Compiler + source file. The body consists of zero or more message definitions. + Each message definition begins with one or more of the following + statements: + + MessageId = [number|+number] + Severity = severity_name + Facility = facility_name + SymbolicName = name + + The MessageId statement marks the beginning of the message + definition. A MessageID statement is required for each message, + although the value is optional. If no value is specified, the value + used is the previous value for the facility plus one. If the value + is specified as +number then the value used is the previous value + for the facility, plus the number after the plus sign. Otherwise, if + a numeric value is given, that value is used. Any MessageId value + that does not fit in 16 bits is an error. + + The Severity and Facility statements are optional. These statements + specify additional bits to OR into the final 32-bit message code. If + not specified they default to the value last specified for a message + definition. The initial values prior to processing the first message + definition are: + + Severity=Success + Facility=Application + + The value associated with Severity and Facility must match one of + the names given in the FacilityNames and SeverityNames statements in + the header section. The SymbolicName statement allows you to + associate a C/C++ symbolic constant with the final 32-bit message + code. + */ +// +// Values are 32 bit values laid 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 +// +#define STATUS_SEVERITY_WARNING 0x2 +#define STATUS_SEVERITY_SUCCESS 0x0 +#define STATUS_SEVERITY_INFORMATIONAL 0x1 +#define STATUS_SEVERITY_ERROR 0x3 + + +// +// MessageId: NTP_ERROR +// +// MessageText: +// +// %1 +// +#define NTP_ERROR ((DWORD)0xC0000001L) + +// +// MessageId: NTP_WARNING +// +// MessageText: +// +// %1 +// +// +#define NTP_WARNING ((DWORD)0x80000002L) + +// +// MessageId: NTP_INFO +// +// MessageText: +// +// %1 +// +// +// +// +#define NTP_INFO ((DWORD)0x40000003L) + diff --git a/ports/winnt/libntp/messages.mc b/ports/winnt/libntp/messages.mc new file mode 100644 index 0000000..3a6bc7d --- /dev/null +++ b/ports/winnt/libntp/messages.mc @@ -0,0 +1,161 @@ +; /* +; Microsoft Developer Support +; Copyright (c) 1992 Microsoft Corporation +; +; This file contains the message definitions for the Win32 +; syslog support messages for the nntp firewall + +;------------------------------------------------------------------------- +; HEADER SECTION +; +; The header section defines names and language identifiers for use +; by the message definitions later in this file. The MessageIdTypedef, +; SeverityNames, FacilityNames, and LanguageNames keywords are +; optional and not required. +; +; +MessageIdTypedef=DWORD +; +; The MessageIdTypedef keyword gives a typedef name that is used in a +; type cast for each message code in the generated include file. Each +; message code appears in the include file with the format: #define +; name ((type) 0xnnnnnnnn) The default value for type is empty, and no +; type cast is generated. It is the programmer's responsibility to +; specify a typedef statement in the application source code to define +; the type. The type used in the typedef must be large enough to +; accomodate the entire 32-bit message code. +; +; +SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS + Informational=0x1:STATUS_SEVERITY_INFORMATIONAL + Warning=0x2:STATUS_SEVERITY_WARNING + Error=0x3:STATUS_SEVERITY_ERROR + ) +; +; The SeverityNames keyword defines the set of names that are allowed +; as the value of the Severity keyword in the message definition. The +; set is delimited by left and right parentheses. Associated with each +; severity name is a number that, when shifted left by 30, gives the +; bit pattern to logical-OR with the Facility value and MessageId +; value to form the full 32-bit message code. The default value of +; this keyword is: +; +; SeverityNames=( +; Success=0x0 +; Informational=0x1 +; Warning=0x2 +; Error=0x3 +; ) +; +; Severity values occupy the high two bits of a 32-bit message code. +; Any severity value that does not fit in two bits is an error. The +; severity codes can be given symbolic names by following each value +; with :name +; +; +;FacilityNames=(System=0x0:FACILITY_SYSTEM +; Runtime=0x2:FACILITY_RUNTIME +; Stubs=0x3:FACILITY_STUBS +; Io=0x4:FACILITY_IO_ERROR_CODE +; ) +; +; The FacilityNames keyword defines the set of names that are allowed +; as the value of the Facility keyword in the message definition. The +; set is delimited by left and right parentheses. Associated with each +; facility name is a number that, when shift it left by 16 bits, gives +; the bit pattern to logical-OR with the Severity value and MessageId +; value to form the full 32-bit message code. The default value of +; this keyword is: +; +; FacilityNames=( +; System=0x0FF +; Application=0xFFF +; ) +; +; Facility codes occupy the low order 12 bits of the high order +; 16-bits of a 32-bit message code. Any facility code that does not +; fit in 12 bits is an error. This allows for 4,096 facility codes. +; The first 256 codes are reserved for use by the system software. The +; facility codes can be given symbolic names by following each value +; with :name +; +; +; The LanguageNames keyword defines the set of names that are allowed +; as the value of the Language keyword in the message definition. The +; set is delimited by left and right parentheses. Associated with each +; language name is a number and a file name that are used to name the +; generated resource file that contains the messages for that +; language. The number corresponds to the language identifier to use +; in the resource table. The number is separated from the file name +; with a colon. The initial value of LanguageNames is: +; +; LanguageNames=(English=1:MSG00001) +; +; Any new names in the source file which don't override the built-in +; names are added to the list of valid languages. This allows an +; application to support private languages with descriptive names. +; +; +;------------------------------------------------------------------------- +; MESSAGE DEFINITION SECTION +; +; Following the header section is the body of the Message Compiler +; source file. The body consists of zero or more message definitions. +; Each message definition begins with one or more of the following +; statements: +; +; MessageId = [number|+number] +; Severity = severity_name +; Facility = facility_name +; SymbolicName = name +; +; The MessageId statement marks the beginning of the message +; definition. A MessageID statement is required for each message, +; although the value is optional. If no value is specified, the value +; used is the previous value for the facility plus one. If the value +; is specified as +number then the value used is the previous value +; for the facility, plus the number after the plus sign. Otherwise, if +; a numeric value is given, that value is used. Any MessageId value +; that does not fit in 16 bits is an error. +; +; The Severity and Facility statements are optional. These statements +; specify additional bits to OR into the final 32-bit message code. If +; not specified they default to the value last specified for a message +; definition. The initial values prior to processing the first message +; definition are: +; +; Severity=Success +; Facility=Application +; +; The value associated with Severity and Facility must match one of +; the names given in the FacilityNames and SeverityNames statements in +; the header section. The SymbolicName statement allows you to +; associate a C/C++ symbolic constant with the final 32-bit message +; code. +; */ + +MessageId=0x1 +Severity=Error +Facility=Application +SymbolicName=NTP_ERROR +Language=English +%1 +. + +MessageId=0x2 +Severity=Warning +Facility=Application +SymbolicName=NTP_WARNING +Language=English +%1 + +. +MessageId=0x3 +Severity=Informational +Facility=Application +SymbolicName=NTP_INFO +Language=English +%1 + + + diff --git a/ports/winnt/libntp/messages.rc b/ports/winnt/libntp/messages.rc new file mode 100644 index 0000000..0abcb0f --- /dev/null +++ b/ports/winnt/libntp/messages.rc @@ -0,0 +1,2 @@ +LANGUAGE 0x9,0x1 +1 11 "MSG00001.bin" diff --git a/ports/winnt/libntp/randfile.c b/ports/winnt/libntp/randfile.c new file mode 100644 index 0000000..7de80b8 --- /dev/null +++ b/ports/winnt/libntp/randfile.c @@ -0,0 +1,109 @@ +/* + * Make sure that there is a good source of random characters + * so that OpenSSL can work properly and securely. + */ + +#include <config.h> +#include <wincrypt.h> + +#include <stdio.h> + +unsigned int getrandom_chars(int desired, unsigned char *buf, int lenbuf); +BOOL create_random_file(char *filename); + +BOOL +init_randfile() +{ + FILE *rf; + char *randfile; + char *homedir; + char tmp[256]; + /* See if the environmental variable RANDFILE is defined + * and the file exists + */ + randfile = getenv("RANDFILE"); + if (randfile != NULL) { + rf = fopen(randfile, "rb"); + if (rf != NULL) { + fclose(rf); + return (TRUE); + } + else { + /* The environmental variable exists but not the file */ + return (create_random_file(randfile)); + } + } + /* + * If the RANDFILE environmental variable does not exist, + * see if the HOME enviromental variable exists and + * a .rnd file is in there. + */ + homedir = getenv("HOME"); + if (homedir != NULL && + (strlen(homedir) + 5 /* \.rnd */) < sizeof(tmp)) { + snprintf(tmp, sizeof(tmp), "%s\\.rnd", homedir); + rf = fopen(tmp, "rb"); + if (rf != NULL) { + fclose(rf); + return (TRUE); + } + else { + /* The HOME environmental variable exists but not the file */ + return (create_random_file(tmp)); + } + } + /* + * Final try. Look for it on the C:\ directory + * NOTE: This is a really bad place for it security-wise + * However, OpenSSL looks for it there if it can't find it elsewhere + */ + rf = fopen("C:\\.rnd", "rb"); + if (rf != NULL) { + fclose(rf); + return (TRUE); + } + /* The file does not exist */ + return (create_random_file("C:\\.rnd")); +} +/* + * Routine to create the random file with 1024 random characters + */ +BOOL +create_random_file(char *filename) { + FILE *rf; + int nchars; + unsigned char buf[1025]; + + nchars = getrandom_chars(1024, buf, sizeof(buf)); + rf = fopen(filename, "wb"); + if (rf == NULL) + return (FALSE); + fwrite(buf, sizeof(unsigned char), nchars, rf); + fclose(rf); + return (TRUE); +} + +unsigned int +getrandom_chars(int desired, unsigned char *buf, int lenbuf) { + HCRYPTPROV hcryptprov; + BOOL err; + + if (buf == NULL || lenbuf <= 0 || desired > lenbuf) + return (0); + /* + * The first time we just try to acquire the context + */ + err = CryptAcquireContext(&hcryptprov, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT); + if (!err){ + return (0); + } + if (!CryptGenRandom(hcryptprov, desired, buf)) { + CryptReleaseContext(hcryptprov, 0); + return (0); + } + + CryptReleaseContext(hcryptprov, 0); + return (desired); +} + diff --git a/ports/winnt/libntp/setpriority.c b/ports/winnt/libntp/setpriority.c new file mode 100644 index 0000000..52ab785 --- /dev/null +++ b/ports/winnt/libntp/setpriority.c @@ -0,0 +1,76 @@ +#include <config.h> +#include <stdio.h> +#include <sys/resource.h> /* our private version */ +#include "ntp_stdlib.h" +#include "ntp_syslog.h" +#include "ntp_debug.h" +#include "ntp_fp.h" +#include "ntp.h" +#include "clockstuff.h" + + +/* + * setpriority + * + * to reduce the #ifdef forest in the portable code, + * we emulate the BSD setpriority interface: + * + * if (-1 == setpriority(PRIO_PROCESS, 0, NTP_PRIO)) + * msyslog(LOG_ERR, "setpriority() error: %m"); + * + * However, since the Windows port of ntpd has always raised its + * priority (to realtime if allowed, or silently downgraded to + * high by the system if not) with or without -N. Changing that + * now would endanger users who upgrade the binary without adding + * -N to its invocation. Instsrv assumes ntpd.exe is installed + * with no command-line arguments. + * + * This routine is used by utilities as well as ntpd itself, so + * it checks if the priority is already high or realtime and + * logs no complaints in that case, to avoid duplicating. ntpd + * will have raised the priority to one of those in + * init_winnt_time, while the utilities will rely on this + * code. + * + */ + +int setpriority( + int which, + int who, + int prio + ) +{ + BOOL success; + DWORD prio_class; + + if (PRIO_PROCESS != which || who || NTP_PRIO != prio) + TRACE(1, ("windows setpriority() clone needs work.\n")); + + prio_class = GetPriorityClass(GetCurrentProcess()); + + if (HIGH_PRIORITY_CLASS == prio_class || + REALTIME_PRIORITY_CLASS == prio_class) + return 0; + + success = SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); + + if (!success) { + msyslog(LOG_ERR, "Unable to raise priority: %m"); + errno = EPERM; + return -1; + } + + prio_class = GetPriorityClass(GetCurrentProcess()); + + if (REALTIME_PRIORITY_CLASS == prio_class) + msyslog(LOG_INFO, "Raised to realtime priority class"); + else if (HIGH_PRIORITY_CLASS == prio_class) + msyslog(LOG_ERR, "Raised to high priority class, realtime " + "requires Increase Scheduling Priority " + "privilege (enabled with secpol.msc)."); + else + msyslog(LOG_ERR, "Unexpected process priority class %d", + prio_class); + + return 0; +} diff --git a/ports/winnt/libntp/syslog.c b/ports/winnt/libntp/syslog.c new file mode 100644 index 0000000..71c90c2 --- /dev/null +++ b/ports/winnt/libntp/syslog.c @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM 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. + */ + +/* From BIND 9 lib/isc/win32/: syslog.c,v 1.6 2002/08/03 01:34:14 mayer */ + +#include <config.h> + +#include <stdio.h> +#include <windows.h> +#include <string.h> +#include <stdlib.h> +#include <syslog.h> + +#include <isc/strerror.h> +#include <lib_strbuf.h> + +#include "ntp_stdlib.h" + +#include "messages.h" + +static HANDLE hAppLog = NULL; +static FILE *log_stream; +static int debug_level = 0; +static char progname[51] = "NTP"; +static int logmask = 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 } +}; + +#if 0 +BOOL +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 (TRUE); + } + } + return (FALSE); +} +#endif +/* + * 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); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + /* Make sure that the channel is open to write the event */ + if (hAppLog == NULL) { + openlog(progname, LOG_PID); + } + switch (level) { + case LOG_INFO: + case LOG_NOTICE: + case LOG_DEBUG: + ReportEvent(hAppLog, EVENTLOG_INFORMATION_TYPE, 0, + NTP_INFO, NULL, 1, 0, str, NULL); + break; + case LOG_WARNING: + ReportEvent(hAppLog, EVENTLOG_WARNING_TYPE, 0, + NTP_WARNING, NULL, 1, 0, str, NULL); + break; + default: + ReportEvent(hAppLog, EVENTLOG_ERROR_TYPE, 0, + NTP_ERROR, 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, progname); + strlcpy(progname, name, sizeof(progname)); +} + +/* + * Close the Handle to the application Event Log + * We don't care whether or not we succeeded so ignore return values + * In fact if we failed then we would have nowhere to put the message + */ +void +closelog() { + DeregisterEventSource(hAppLog); +} + +/* + * Keep event logging synced with the current debug level + */ +void +ModifyLogLevel(int level) { + debug_level = level; +} +/* + * Set the log priority mask to the given value. + * Return the previous priority mask + * Note that this setting is ignored in Win32 + */ +int +setlogmask(int maskpri) { + int temp = logmask; + logmask = maskpri; + return (temp); +} + +/* + * 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, + NTP_ERROR, NULL, 1, 0, buf, NULL); + + DeregisterEventSource(hNTAppLog); +} + + +/* + * ntp_strerror() - provide strerror()-compatible wrapper for libisc's + * isc__strerror(), which knows about Windows as well as + * C runtime error messages. + */ + +char * +ntp_strerror( + int code + ) +{ + char * buf; + + LIB_GETBUF(buf); + isc__strerror(code, buf, LIB_BUFLENGTH); + + return buf; +} diff --git a/ports/winnt/libntp/termios.c b/ports/winnt/libntp/termios.c new file mode 100644 index 0000000..3fe4e48 --- /dev/null +++ b/ports/winnt/libntp/termios.c @@ -0,0 +1,789 @@ +/* This file implements system calls that are not compatible with UNIX */ +/* Moved to libntp/termios.c */ + +#include <config.h> +#include <io.h> +#include <stdio.h> + +#include "ntp.h" +#include "ntp_tty.h" +#include "lib_strbuf.h" +#include "ntp_assert.h" +#include "win32_io.h" + +#define MAX_SERIAL 255 /* COM1: - COM255: */ + +typedef struct comhandles_tag { + HANDLE h; + size_t opens; + HANDLE * dupes; +} comhandles; + +comhandles * hnds; /* handle/dupes array */ +size_t c_hnds; /* current array size */ + +/* + * common_serial_open ensures duplicate opens of the same port + * work by duplicating the handle for the 2nd open, allowing + * refclock_atom to share a GPS refclock's comm port. + */ +HANDLE common_serial_open( + char * dev, + char ** pwindev + ) +{ + char * windev; + HANDLE handle; + size_t unit; + size_t prev_c_hnds; + size_t opens; + char * pch; + + /* + * This is odd, but we'll take any unix device path + * by looking for the initial '/' and strip off everything + * before the final digits, then translate that to COM__: + * maintaining backward compatibility with NTP practice of + * mapping unit 0 to the nonfunctional COM0: + * + * To ease the job of taking the windows COMx: device names + * out of reference clocks, we'll also work with those + * equanimously. + */ + + TRACE(1, ("common_serial_open given %s\n", dev)); + + pch = NULL; + if ('/' == dev[0]) { + pch = dev + strlen(dev) - 1; + + if (isdigit(pch[0])) { + while (isdigit(pch[0])) { + pch--; + } + pch++; + } + TRACE(1, ("common_serial_open skipped to ending digits leaving %s\n", pch)); + } else if ('c' == tolower(dev[0]) + && 'o' == tolower(dev[1]) + && 'm' == tolower(dev[2])) { + pch = dev + 3; + TRACE(1, ("common_serial_open skipped COM leaving %s\n", pch)); + } + + if (!pch || !isdigit(pch[0])) { + TRACE(1, ("not a digit: %s\n", pch ? pch : "[NULL]")); + return INVALID_HANDLE_VALUE; + } + + if (1 != sscanf(pch, "%d", &unit) + || unit > MAX_SERIAL + || unit < 0) { + TRACE(1, ("sscanf failure of %s\n", pch)); + return INVALID_HANDLE_VALUE; + } + + + if (c_hnds < unit + 1) { + prev_c_hnds = c_hnds; + c_hnds = unit + 1; + /* round up to closest multiple of 4 to avoid churn */ + c_hnds = (c_hnds + 3) & ~3; + hnds = erealloc_zero(hnds, c_hnds * sizeof(hnds[0]), + prev_c_hnds * sizeof(hnds[0])); + } + + if (NULL == hnds[unit].h) { + NTP_ENSURE(0 == hnds[unit].opens); + LIB_GETBUF(windev); + snprintf(windev, LIB_BUFLENGTH, "\\\\.\\COM%d", unit); + TRACE(1, ("windows device %s\n", windev)); + *pwindev = windev; + hnds[unit].h = + CreateFile( + windev, + GENERIC_READ | GENERIC_WRITE, + 0, /* sharing prohibited */ + NULL, /* default security */ + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + NULL); + if (INVALID_HANDLE_VALUE == hnds[unit].h) + hnds[unit].h = NULL; + } + + if (NULL != hnds[unit].h) { + /* think handle = dup(hnds[unit].h); */ + DuplicateHandle( + GetCurrentProcess(), + hnds[unit].h, + GetCurrentProcess(), + &handle, + 0, + FALSE, + DUPLICATE_SAME_ACCESS + ); + hnds[unit].opens++; + opens = hnds[unit].opens; + hnds[unit].dupes = erealloc(hnds[unit].dupes, opens * + sizeof(hnds[unit].dupes[0])); + hnds[unit].dupes[opens - 1] = handle; + return handle; + } + + return INVALID_HANDLE_VALUE; +} + + +/* + * closeserial() is used in place of close by ntpd refclock I/O for ttys + */ +int +closeserial(int fd) +{ + HANDLE h; + BOOL found; + size_t u; + size_t d; + + h = (HANDLE)_get_osfhandle(fd); + if (INVALID_HANDLE_VALUE == h) { + errno = EBADF; + return -1; + } + + d = 0; /* silence potent. uninit. warning */ + found = FALSE; + for (u = 0; u < c_hnds; u++) { + for (d = 0; d < hnds[u].opens; d++) { + if (hnds[u].dupes[d] == h) { + found = TRUE; + break; + } + } + if (found) + break; + } + if (found) { + hnds[u].opens--; + if (d < hnds[u].opens) + memmove(&hnds[u].dupes[d], + &hnds[u].dupes[d + 1], + hnds[u].opens - d * + sizeof(hnds[u].dupes[d])); + if (0 == hnds[u].opens) { + CloseHandle(hnds[u].h); + hnds[u].h = NULL; + } + } + + return close(fd); +} + +/* + * isserialhandle() -- check if a handle is a COM port handle + */ +int isserialhandle( + HANDLE h + ) +{ + size_t u; + size_t d; + + + for (u = 0; u < c_hnds; u++) + for (d = 0; d < hnds[u].opens; d++) + if (hnds[u].dupes[d] == h) + return TRUE; + return FALSE; +} + + +/* + * tty_open - open serial port for refclock special uses + * + * This routine opens a serial port for and returns the + * file descriptor if success and -1 if failure. + */ +int tty_open( + char *dev, /* device name pointer */ + int access, /* O_RDWR */ + int mode /* unused */ + ) +{ + HANDLE Handle; + char * windev; + + /* + * open communication port handle + */ + windev = NULL; + Handle = common_serial_open(dev, &windev); + windev = (windev) + ? windev + : dev; + + if (Handle == INVALID_HANDLE_VALUE) { + msyslog(LOG_ERR, "tty_open: device %s CreateFile error: %m", windev); + errno = EMFILE; /* lie, lacking conversion from GetLastError() */ + return -1; + } + + return (int)_open_osfhandle((int)Handle, _O_TEXT); +} + + +/* + * refclock_open - open serial port for reference clock + * + * This routine opens a serial port for I/O and sets default options. It + * returns the file descriptor or -1 indicating failure. + */ +int refclock_open( + char * dev, /* device name pointer */ + u_int speed, /* serial port speed (code) */ + u_int flags /* line discipline flags */ + ) +{ + char * windev; + HANDLE h; + COMMTIMEOUTS timeouts; + DCB dcb; + DWORD dwEvtMask; + int fd; + int translate; + + /* + * open communication port handle + */ + windev = NULL; + h = common_serial_open(dev, &windev); + windev = (windev) ? windev : dev; + + if (INVALID_HANDLE_VALUE == h) { + SAVE_ERRNO( + msyslog(LOG_ERR, "CreateFile(%s) error: %m", + windev); + ) + return -1; + } + + /* Change the input/output buffers to be large. */ + if (!SetupComm(h, 1024, 1024)) { + SAVE_ERRNO( + msyslog(LOG_ERR, "SetupComm(%s) error: %m", + windev); + ) + return -1; + } + + dcb.DCBlength = sizeof(dcb); + + if (!GetCommState(h, &dcb)) { + SAVE_ERRNO( + msyslog(LOG_ERR, + "GetCommState(%s) error: %m", + windev); + ) + return -1; + } + + switch (speed) { + + case B300: + dcb.BaudRate = 300; + break; + + case B1200: + dcb.BaudRate = 1200; + break; + + case B2400: + dcb.BaudRate = 2400; + break; + + case B4800: + dcb.BaudRate = 4800; + break; + + case B9600: + dcb.BaudRate = 9600; + break; + + case B19200: + dcb.BaudRate = 19200; + break; + + case B38400: + dcb.BaudRate = 38400; + break; + + case B57600: + dcb.BaudRate = 57600; + break; + + case B115200: + dcb.BaudRate = 115200; + break; + + default: + msyslog(LOG_ERR, "%s unsupported bps code %u", windev, + speed); + SetLastError(ERROR_INVALID_PARAMETER); + return -1; + } + + dcb.fBinary = TRUE; + dcb.fParity = TRUE; + dcb.fOutxCtsFlow = 0; + dcb.fOutxDsrFlow = 0; + dcb.fDtrControl = DTR_CONTROL_ENABLE; + dcb.fDsrSensitivity = 0; + dcb.fTXContinueOnXoff = TRUE; + dcb.fOutX = 0; + dcb.fInX = 0; + dcb.fErrorChar = 0; + dcb.fNull = 0; + dcb.fRtsControl = RTS_CONTROL_DISABLE; + dcb.fAbortOnError = 0; + dcb.ByteSize = 8; + dcb.StopBits = ONESTOPBIT; + dcb.Parity = NOPARITY; + dcb.ErrorChar = 0; + dcb.EofChar = 0; + if (LDISC_RAW & flags) + dcb.EvtChar = 0; + else + dcb.EvtChar = '\r'; + + if (!SetCommState(h, &dcb)) { + SAVE_ERRNO( + msyslog(LOG_ERR, "SetCommState(%s) error: %m", + windev); + ) + return -1; + } + + /* watch out for CR (dcb.EvtChar) as well as the CD line */ + dwEvtMask = EV_RLSD; + if (LDISC_RAW & flags) + dwEvtMask |= EV_RXCHAR; + else + dwEvtMask |= EV_RXFLAG; + if (!SetCommMask(h, dwEvtMask)) { + SAVE_ERRNO( + msyslog(LOG_ERR, "SetCommMask(%s) error: %m", + windev); + ) + return -1; + } + + /* configure the handle to never block */ + timeouts.ReadIntervalTimeout = MAXDWORD; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.ReadTotalTimeoutConstant = 0; + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + + if (!SetCommTimeouts(h, &timeouts)) { + SAVE_ERRNO( + msyslog(LOG_ERR, + "Device %s SetCommTimeouts error: %m", + windev); + ) + return -1; + } + + translate = (LDISC_RAW & flags) + ? 0 + : _O_TEXT; + fd = _open_osfhandle((int)h, translate); + /* refclock_open() long returned 0 on failure, avoid it. */ + if (0 == fd) { + fd = _dup(0); + _close(0); + } + + return fd; +} + + +int +ioctl_tiocmget( + HANDLE h, + int *pi + ) +{ + DWORD dw; + + if (!GetCommModemStatus(h, &dw)) { + errno = ENOTTY; + return -1; + } + + *pi = ((dw & MS_CTS_ON) ? TIOCM_CTS : 0) + | ((dw & MS_DSR_ON) ? TIOCM_DSR : 0) + | ((dw & MS_RLSD_ON) ? TIOCM_CAR : 0) + | ((dw & MS_RING_ON) ? TIOCM_RI : 0); + + return 0; +} + + +int +ioctl_tiocmset( + HANDLE h, + int *pi + ) +{ + BOOL failed; + int result; + + failed = !EscapeCommFunction( + h, + (*pi & TIOCM_RTS) + ? SETRTS + : CLRRTS + ); + + if (!failed) + failed = !EscapeCommFunction( + h, + (*pi & TIOCM_DTR) + ? SETDTR + : CLRDTR + ); + + if (failed) { + errno = ENOTTY; + result = -1; + } else + result = 0; + + return result; +} + + +int +ioctl( + int fd, + int op, + int *pi + ) +{ + HANDLE h; + int result; + int modctl; + + h = (HANDLE)_get_osfhandle(fd); + + if (INVALID_HANDLE_VALUE == h) { + /* errno already set */ + return -1; + } + + switch (op) { + + case TIOCMGET: + result = ioctl_tiocmget(h, pi); + break; + + case TIOCMSET: + result = ioctl_tiocmset(h, pi); + break; + + case TIOCMBIC: + result = ioctl_tiocmget(h, &modctl); + if (result < 0) + return result; + modctl &= ~(*pi); + result = ioctl_tiocmset(h, &modctl); + break; + + case TIOCMBIS: + result = ioctl_tiocmget(h, &modctl); + if (result < 0) + return result; + modctl |= *pi; + result = ioctl_tiocmset(h, &modctl); + break; + + default: + errno = EINVAL; + result = -1; + } + + return result; +} + + +int +tcsetattr( + int fd, + int optional_actions, + const struct termios * tios + ) +{ + DCB dcb; + HANDLE h; + + UNUSED_ARG(optional_actions); + + h = (HANDLE)_get_osfhandle(fd); + + if (INVALID_HANDLE_VALUE == h) { + /* errno already set */ + return -1; + } + + dcb.DCBlength = sizeof(dcb); + if (!GetCommState(h, &dcb)) { + errno = ENOTTY; + return -1; + } + + switch (max(tios->c_ospeed, tios->c_ispeed)) { + + case B300: + dcb.BaudRate = 300; + break; + + case B1200: + dcb.BaudRate = 1200; + break; + + case B2400: + dcb.BaudRate = 2400; + break; + + case B4800: + dcb.BaudRate = 4800; + break; + + case B9600: + dcb.BaudRate = 9600; + break; + + case B19200: + dcb.BaudRate = 19200; + break; + + case B38400: + dcb.BaudRate = 38400; + break; + + case B57600: + dcb.BaudRate = 57600; + break; + + case B115200: + dcb.BaudRate = 115200; + break; + + default: + msyslog(LOG_ERR, "unsupported serial baud rate"); + errno = EINVAL; + return -1; + } + + switch (tios->c_cflag & CSIZE) { + + case CS5: + dcb.ByteSize = 5; + break; + + case CS6: + dcb.ByteSize = 6; + break; + + case CS7: + dcb.ByteSize = 7; + break; + + case CS8: + dcb.ByteSize = 8; + break; + + default: + msyslog(LOG_ERR, "unsupported serial word size"); + errno = EINVAL; + return FALSE; + } + + if (PARENB & tios->c_cflag) { + dcb.fParity = TRUE; + dcb.Parity = (tios->c_cflag & PARODD) + ? ODDPARITY + : EVENPARITY; + } else { + dcb.fParity = FALSE; + dcb.Parity = NOPARITY; + } + + dcb.StopBits = (CSTOPB & tios->c_cflag) + ? TWOSTOPBITS + : ONESTOPBIT; + + if (!SetCommState(h, &dcb)) { + errno = ENOTTY; + return -1; + } + + return 0; +} + + +int +tcgetattr( + int fd, + struct termios *tios + ) +{ + DCB dcb; + HANDLE h; + + h = (HANDLE)_get_osfhandle(fd); + + if (INVALID_HANDLE_VALUE == h) { + /* errno already set */ + return -1; + } + + dcb.DCBlength = sizeof(dcb); + + if (!GetCommState(h, &dcb)) { + errno = ENOTTY; + return -1; + } + + /* Set c_ispeed & c_ospeed */ + + switch (dcb.BaudRate) { + + case 300: + tios->c_ispeed = tios->c_ospeed = B300; + break; + + case 1200: + tios->c_ispeed = tios->c_ospeed = B1200; + break; + + case 2400: + tios->c_ispeed = tios->c_ospeed = B2400; + break; + + case 4800: + tios->c_ispeed = tios->c_ospeed = B4800; + break; + + case 9600: + tios->c_ispeed = tios->c_ospeed = B9600; + break; + + case 19200: + tios->c_ispeed = tios->c_ospeed = B19200; + break; + + case 38400: + tios->c_ispeed = tios->c_ospeed = B38400; + break; + + case 57600: + tios->c_ispeed = tios->c_ospeed = B57600; + break; + + case 115200: + tios->c_ispeed = tios->c_ospeed = B115200; + break; + + default: + tios->c_ispeed = tios->c_ospeed = B9600; + } + + + switch (dcb.ByteSize) { + case 5: + tios->c_cflag = CS5; + break; + + case 6: + tios->c_cflag = CS6; + break; + + case 7: + tios->c_cflag = CS7; + break; + + case 8: + default: + tios->c_cflag = CS8; + } + + if (dcb.fParity) { + tios->c_cflag |= PARENB; + + if (ODDPARITY == dcb.Parity) + tios->c_cflag |= PARODD; + } + + if (TWOSTOPBITS == dcb.StopBits) + tios->c_cflag |= CSTOPB; + + tios->c_iflag = 0; + tios->c_lflag = 0; + tios->c_line = 0; + tios->c_oflag = 0; + + return 0; +} + + +int +tcflush( + int fd, + int mode + ) +{ + HANDLE h; + BOOL success; + DWORD flags; + int result; + + h = (HANDLE)_get_osfhandle(fd); + + if (INVALID_HANDLE_VALUE == h) { + /* errno already set */ + return -1; + } + + switch (mode) { + + case TCIFLUSH: + flags = PURGE_RXCLEAR; + break; + + case TCOFLUSH: + flags = PURGE_TXABORT; + break; + + case TCIOFLUSH: + flags = PURGE_RXCLEAR | PURGE_TXABORT; + break; + + default: + errno = EINVAL; + return -1; + } + + success = PurgeComm(h, flags); + + if (success) + result = 0; + else { + errno = ENOTTY; + result = -1; + } + + return result; +} + diff --git a/ports/winnt/libntp/util_clockstuff.c b/ports/winnt/libntp/util_clockstuff.c new file mode 100644 index 0000000..e4bd0de --- /dev/null +++ b/ports/winnt/libntp/util_clockstuff.c @@ -0,0 +1,26 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ntp_syslog.h" +#include "ntp_stdlib.h" +#include "ntp_unixtime.h" +#include "clockstuff.h" + +int +gettimeofday( + struct timeval * tv, + void * ignored + ) +{ + struct timespec ts; + + UNUSED_ARG(ignored); + + getclock(TIMEOFDAY, &ts); + + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 10; + + return 0; +} diff --git a/ports/winnt/libntp/win32_io.c b/ports/winnt/libntp/win32_io.c new file mode 100644 index 0000000..9e7a861 --- /dev/null +++ b/ports/winnt/libntp/win32_io.c @@ -0,0 +1,81 @@ +/* This file implements i/o calls that are specific to Windows */ + +#include <config.h> +#include <stdio.h> +#include "ntp_fp.h" +#include "ntp_net.h" +#include "ntp_stdlib.h" +#include "ntp_syslog.h" +#include "win32_io.h" +#include <isc/win32os.h> + +/* + * Define this macro to control the behavior of connection + * resets on UDP sockets. See Microsoft KnowledgeBase Article Q263823 + * for details. + * Based on that article, it is surprising that a much newer winsock2.h + * does not define SIO_UDP_CONNRESET (the one that comes with VS 2008). + * 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 + +void +InitSockets( + void + ) +{ + WORD wVersionRequested; + WSADATA wsaData; + int err; + + /* Need Winsock 2.0 or better */ + wVersionRequested = MAKEWORD(2, 0); + + err = WSAStartup(wVersionRequested, &wsaData); + if ( err != 0 ) { + SetLastError(err); + mfprintf(stderr, "No usable winsock: %m\n"); + SetLastError(err); + msyslog(LOG_ERR, "No usable winsock: %m"); + exit(1); + } +} + +/* + * Windows 2000 systems incorrectly cause UDP sockets using WASRecvFrom + * to not work correctly, returning a WSACONNRESET error when a WSASendTo + * fails with an "ICMP port unreachable" response and preventing the + * socket from using the WSARecvFrom in subsequent operations. + * The function below fixes this, but requires that Windows 2000 + * Service Pack 2 or later be installed on the system. NT 4.0 + * systems are not affected by this and work correctly. + * See Microsoft Knowledge Base Article Q263823 for details of this. + */ +void +connection_reset_fix( + SOCKET fd, + sockaddr_u * addr + ) +{ + DWORD dw; + BOOL bNewBehavior = FALSE; + DWORD status; + + /* + * disable bad behavior using IOCTL: SIO_UDP_CONNRESET + * NT 4.0 has no problem + */ + if (isc_win32os_majorversion() >= 5) { + status = WSAIoctl(fd, SIO_UDP_CONNRESET, &bNewBehavior, + sizeof(bNewBehavior), NULL, 0, + &dw, NULL, NULL); + if (SOCKET_ERROR == status) + msyslog(LOG_ERR, + "connection_reset_fix() failed for address %s: %m", + stoa(addr)); + } +} + |