]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 47] Debugging and logging do not work after a fork.
authorDave Hart <hart@ntp.org>
Wed, 27 Jan 2010 18:45:33 +0000 (18:45 +0000)
committerDave Hart <hart@ntp.org>
Wed, 27 Jan 2010 18:45:33 +0000 (18:45 +0000)
[Bug 1010] getaddrinfo() could block and thus should not be called by
  the main thread/process.
#include <config.h> from all .c files and do not include it
  from any .h files.  Previously config.h appeared a dozen times in
  preprocessed output of some .c files.
handle relative path to logfile correctly despite re-opening
  after fork() with a different curdir.
eliminate hand-crafted byte-swapping code from refclock_palisade.c in
  preference to using htonl(), htons().  Tested by Fernando Hauscarriaga.

bk: 4b6089cdjX3Zx7Mvzyik8kkO9L7RTA

115 files changed:
ChangeLog
configure.ac
include/Makefile.am
include/iosignal.h
include/l_stdlib.h
include/ntp_data_structures.h
include/ntp_fp.h
include/ntp_intres.h
include/ntp_io.h
include/ntp_lists.h
include/ntp_machine.h
include/ntp_malloc.h
include/ntp_proto.h
include/ntp_rfc2553.h
include/ntp_select.h
include/ntp_stdlib.h
include/ntp_string.h
include/ntp_syscall.h
include/ntp_syslog.h
include/ntp_types.h
include/ntp_worker.h [new file with mode: 0644]
include/ntp_workimpl.h [new file with mode: 0644]
include/ntpd.h
include/recvbuff.h
libntp/atoint.c
libntp/atolfp.c
libntp/atouint.c
libntp/authusekey.c
libntp/caljulian.c
libntp/caltontp.c
libntp/calyearstart.c
libntp/clocktime.c
libntp/clocktypes.c
libntp/dofptoa.c
libntp/dolfptoa.c
libntp/emalloc.c
libntp/fptoa.c
libntp/fptoms.c
libntp/getopt.c
libntp/hextoint.c
libntp/hextolfp.c
libntp/humandate.c
libntp/icom.c
libntp/iosignal.c
libntp/mfptoa.c
libntp/mfptoms.c
libntp/mktime.c
libntp/modetoa.c
libntp/mstolfp.c
libntp/msutotsf.c
libntp/msyslog.c
libntp/netof.c
libntp/octtoint.c
libntp/prettydate.c
libntp/refnumtoa.c
libntp/socktohost.c
libntp/strdup.c
libntp/syssignal.c
libntp/systime.c
libntp/tsftomsu.c
libntp/tstotv.c
libntp/tvtots.c
libntp/uglydate.c
libntp/uinttoa.c
libntp/ymd2yd.c
libparse/Makefile.am
libparse/binio.c
libparse/data_mbg.c
libparse/gpstolfp.c
libparse/info_trimble.c
libparse/mfp_mul.c
libparse/mkinfo_rcmd.sed
libparse/mkinfo_scmd.sed
libparse/parsesolaris.c
libparse/trim_info.c
ntpd/Makefile.am
ntpd/cmd_args.c
ntpd/ntp_config.c
ntpd/ntp_control.c
ntpd/ntp_data_structures.c
ntpd/ntp_intres.c
ntpd/ntp_io.c
ntpd/ntp_timer.c
ntpd/ntp_worker.c [new file with mode: 0644]
ntpd/ntpd.c
ntpd/ntpsim.c
ntpd/refclock_jupiter.c
ntpd/refclock_palisade.c
ntpd/refclock_palisade.h
ntpd/work_fork.c [new file with mode: 0644]
ntpd/work_thread.c [new file with mode: 0644]
ntpdc/ntpdc-layout.c
ntpdc/ntpdc.c
ntpq/ntpq-subs.c
ntpq/ntpq.c
ntpsnmpd/ntpSnmpSubagentObject.c
ntpsnmpd/ntpsnmpd.c
parseutil/testdcf.c
ports/winnt/include/config.h
ports/winnt/include/sys/time.h
ports/winnt/include/win32_io.h
ports/winnt/libntp/SetSystemTime.c
ports/winnt/ntpd/nt_clockstuff.c
ports/winnt/ntpd/ntp_iocompletionport.c
ports/winnt/vc6/ntpd.dsp
ports/winnt/vs2003/ntpd.vcproj
ports/winnt/vs2005/ntpd.vcproj
ports/winnt/vs2008/libntp/libntp.vcproj
ports/winnt/vs2008/ntpd/ntpd.vcproj
sntp/crypto.c
sntp/kod_management.c
sntp/log.c
sntp/main.c
sntp/networking.c
sntp/utilities.c

index b35a251d6e361c6a7e65f89503d9c3464c5fc688..ef4bcb925d087c42529b4bcb3cc981eb49b46202 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+* [Bug 47] Debugging and logging do not work after a fork.
+* [Bug 1010] getaddrinfo() could block and thus should not be called by
+  the main thread/process.
 (4.2.7p10) 2010/01/24 Released by Harlan Stenn <stenn@ntp.org>
 * [Bug 1140] Clean up debug.html, decode.html, and ntpq.html.
 * Include (4.2.6p1-RC3) - Use TZ=UTC instead of TZ= when calling date in
index 392b5c36c664055dc54818591ed97921ecea77c4..a09ec3394c2979c6859ab7bbaee921fe57a617f4 100644 (file)
@@ -128,6 +128,7 @@ esac
 LIBOPTS_CHECK(libopts)
 
 AC_FUNC_FORK
+AC_FUNC_ALLOCA
 
 AC_CACHE_CHECK(
     [if $CC can handle @%:@warning],
@@ -1168,7 +1169,7 @@ case "$host" in
     AC_CHECK_FUNCS([clock_gettime clock_settime])
     ;;
 esac
-AC_CHECK_FUNCS(daemon)
+AC_CHECK_FUNCS(closefrom daemon)
 AC_CHECK_FUNCS(finite, ,
   [AC_CHECK_FUNCS(isfinite, ,
     [AC_MSG_CHECKING([for isfinite with <math.h>])
@@ -1366,9 +1367,24 @@ case "$host" in
  *-*-openbsd*)
     # Just stubs.  Idiots.
     ;;
- *) AC_CHECK_FUNCS(timer_create timer_settime)
+ *) AC_CHECK_FUNCS(timer_create)
     ;;
 esac
+
+# some OSes prefer _exit() in forked children to exit()
+AC_CHECK_FUNCS(_exit)
+ntp_worker_child_exit=exit
+case "$ac_cv_func__exit::$host_os" in
+ yes::netbsd*)
+    ntp_worker_child_exit=_exit
+    ;;
+ yes::openbsd*)
+    ntp_worker_child_exit=_exit
+    ;;
+esac
+AC_DEFINE_UNQUOTED([WORKER_CHILD_EXIT], [$ntp_worker_child_exit],
+                  [routine worker child proc uses to exit.])
+
 case "$host" in
  *-pc-cygwin*)
     # I have no idea...
@@ -2114,22 +2130,6 @@ case "$ans" in
 esac
 AC_MSG_RESULT([$ans])
 
-AC_MSG_CHECKING([if ntpd will use the deferred DNS lookup path])
-AC_ARG_ENABLE(
-    [force-defer-DNS],
-    AS_HELP_STRING(
-       [--enable-force-defer-DNS],
-       [- force all DNS lookups to take the deferred path]
-    ),
-    [ans=$enableval],
-    [ans=no]
-)
-case "$ans" in
- yes)
-    AC_DEFINE(FORCE_DEFER_DNS, 1, [Force deferred DNS lookups?])
-esac
-AC_MSG_RESULT([$ans])
-
 AC_CACHE_CHECK([if we have the tty_clk line discipline/streams module],
  ac_cv_var_tty_clk,
  [case "$ac_cv_header_sys_clkdefs_h$ac_cv_hdr_def_tiocdcdtimestamp" in
index 80113226c07a8be667251863f5e645e8e22913a3..949d6920e1ddcb8009bde9be6f9b9e529abd6873 100644 (file)
@@ -56,6 +56,8 @@ noinst_HEADERS =      \
        ntp_tty.h       \
        ntp_types.h     \
        ntp_unixtime.h  \
+       ntp_worker.h    \
+       ntp_workimpl.h  \
        ntpd.h          \
        ntpsim.h        \
        parse.h         \
index 6c4052b7f049ede1b29b5a860781531367969081..632ae7e023c95895ef61fcacdde70be8b89663a5 100644 (file)
@@ -1,9 +1,38 @@
-#if !defined _ntp_iosignaled_h
-#define _ntp_iosignaled_h
+#ifndef IOSIGNAL_H
+#define IOSIGNAL_H
 
 #include "ntp_refclock.h"
 
+ /*
+ * Some systems (MOST) define SIGPOLL == SIGIO, others SIGIO == SIGPOLL, and
+ * a few have separate SIGIO and SIGPOLL signals.  This code checks for the
+ * SIGIO == SIGPOLL case at compile time.
+ * Do not define USE_SIGPOLL or USE_SIGIO.
+ * these are interal only to iosignal.c and ntpd/work_fork.c!
+ */
+#if defined(USE_SIGPOLL)
+# undef USE_SIGPOLL
+#endif
+#if defined(USE_SIGIO)
+# undef USE_SIGIO
+#endif
+
 #if defined(HAVE_SIGNALED_IO)
+# if defined(USE_TTY_SIGPOLL) || defined(USE_UDP_SIGPOLL)
+#  define USE_SIGPOLL
+# endif
+
+# if !defined(USE_TTY_SIGPOLL) || !defined(USE_UDP_SIGPOLL)
+#  define USE_SIGIO
+# endif
+
+# if defined(USE_SIGIO) && defined(USE_SIGPOLL)
+#  if SIGIO == SIGPOLL
+#   define USE_SIGIO
+#   undef USE_SIGPOLL
+#  endif       /* SIGIO == SIGPOLL */
+# endif                /* USE_SIGIO && USE_SIGPOLL */
+
 extern void            block_sigio     (void);
 extern void            unblock_sigio   (void);
 extern int             init_clock_sig  (struct refclockio *);
@@ -14,10 +43,9 @@ RETSIGTYPE           sigio_handler   (int);
 # define BLOCKIO()     block_sigio()
 # define UNBLOCKIO()   unblock_sigio()
 
-#else
-
-# define BLOCKIO()
-# define UNBLOCKIO()
-#endif /* HAVE_SIGNALED_IO */
-
+#else  /* !HAVE_SIGNALED_IO follows */
+# define BLOCKIO()     do {} while (0)
+# define UNBLOCKIO()   do {} while (0)
 #endif
+
+#endif /* IOSIGNAL_H */
index 0213d23c1c4f78856acfda3d96d5407d25270b51..81e8f9e776b118a43545d03efeb1278afe5a3e85 100644 (file)
@@ -3,12 +3,8 @@
  * This is optional
  */
 
-#ifndef _l_stdlib_h
-#define _l_stdlib_h
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#ifndef L_STDLIB_H
+#define L_STDLIB_H
 
 #ifdef HAVE_STDLIB_H
 # include <stdlib.h>
@@ -111,7 +107,7 @@ extern      int     rename          (const char *, const char *);
 #endif
 
 #ifdef DECL_SELECT_0
-#ifdef _ntp_select_h
+#ifdef NTP_SELECT_H
 extern int     select          (int, fd_set *, fd_set *, fd_set *, struct timeval *);
 #endif
 #endif
@@ -235,4 +231,4 @@ extern      int     errno;
 extern int     h_errno;
 #endif
 
-#endif /* l_stdlib_h */
+#endif /* L_STDLIB_H */
index 363e0b47a4e9b3987bc9eb43a98fa51f3e4e67e5..bf970a23a27c8b1b3d4238505893e0963f50171c 100644 (file)
@@ -4,14 +4,14 @@
  * structures used by the ntp configuration code and the discrete event 
  * simulator.
  *
- * Written By: Sachin Kamboj
- *             University of Delaware
- *             Newark, DE 19711
+ * Written By: Sachin Kamboj
+ *             University of Delaware
+ *             Newark, DE 19711
  * Copyright (c) 2006
  */
 
-#ifndef __NTP_DATA_STRUCTURES_H__
-#define __NTP_DATA_STRUCTURES_H__
+#ifndef NTP_DATA_STRUCTURES_H
+#define NTP_DATA_STRUCTURES_H
 
 
 /* Structures for storing a priority queue 
@@ -25,29 +25,55 @@ typedef struct node {
        } nodeu;
 } node;
 #define node_next nodeu.next
-    
+
 typedef struct Queue {
-    int (*get_order)(void *, void *);
-    node *front;
-    int no_of_elements;
+       int (*get_order)(void *, void *);
+       node *front;
+       int no_of_elements;
 } queue;
 
 
 /* FUNCTION PROTOTYPES
  * -------------------
  */
-queue *create_priority_queue(int (*get_order)(void *, void *));
+/* Define a function to create a FIFO queue */
+#define create_queue() create_priority_queue(&get_fifo_order)
+
 void destroy_queue(queue *my_queue);
-void *get_node(size_t size);
 void free_node(void *my_node);
 void *next_node(void *my_node);
 int empty(queue *my_queue);
 void *queue_head(queue *my_queue);
 queue *enqueue(queue *my_queue, void *my_node);
+void append_queue(queue *q1, queue *q2);
 void *dequeue(queue *my_queue);
 int get_no_of_elements(queue *my_queue);
-void append_queue(queue *q1, queue *q2);
 int get_fifo_order(void *el1, void *el2);
-queue *create_queue(void);
 
+/*
+ * Preserve original callsite __FILE__ and __LINE__ for these 
+ * malloc-like funcs when using MS C runtime debug heap.
+ */
+#ifdef _CRTDBG_MAP_ALLOC
+# define create_priority_queue(order)  debug_create_priority_queue(order, __FILE__, __LINE__)
+# define get_node(size)                        debug_get_node(size, __FILE__, __LINE__)
+#else
+# define create_priority_queue(order)  debug_create_priority_queue(order)
+# define get_node(size)                        debug_get_node(size)
+#endif
+
+queue *debug_create_priority_queue(
+       int (*get_order)(void *, void *)
+#ifdef _CRTDBG_MAP_ALLOC
+       , const char *, int     /* __FILE__, __LINE__ */
 #endif
+       );
+
+void *debug_get_node(
+       size_t
+#ifdef _CRTDBG_MAP_ALLOC
+       , const char *, int     /* __FILE__, __LINE__ */
+#endif
+       );
+
+#endif /* NTP_DATA_STRUCTURES_H */
index 63b0f5dfb4e2070d88685a789214cffcdd39f257..de0919e7440705b1de79cfea01d667c340a6639c 100644 (file)
@@ -342,12 +342,12 @@ extern    int     buftvtots       (const char *, l_fp *);
 extern char *  fptoa           (s_fp, short);
 extern char *  fptoms          (s_fp, short);
 extern int     hextolfp        (const char *, l_fp *);
-extern  void    gpstolfp        (int, int, unsigned long, l_fp *);
+extern  void    gpstolfp       (int, int, unsigned long, l_fp *);
 extern int     mstolfp         (const char *, l_fp *);
 extern char *  prettydate      (l_fp *);
 extern char *  gmprettydate    (l_fp *);
 extern char *  uglydate        (l_fp *);
-extern  void    mfp_mul         (int32 *, u_int32 *, int32, u_int32, int32, u_int32);
+extern  void    mfp_mul                (int32 *, u_int32 *, int32, u_int32, int32, u_int32);
 
 extern void    get_systime     (l_fp *);
 extern int     step_systime    (double);
index 53c8a63a40764a7e7350e688f6801ddd93c5ee66..fe63409a39dc05c67d90618fbcc7d8b9286329b7 100644 (file)
@@ -1,14 +1,23 @@
 #ifndef NTP_INTRES_H
 #define NTP_INTRES_H
 
-/*
- * Some systems do not support fork() and don't have an alternate
- * threads implementation of ntp_intres.  Such systems are limited
- * to using numeric IP addresses.
- */
-#if defined(VMS) || defined (SYS_VXWORKS) || \
-    (!defined(HAVE_WORKING_FORK) && !defined(SYS_WINNT))
-#define NO_INTRES
-#endif
-
-#endif /* !defined(NTP_INTRES_H) */
+#include "ntp_worker.h"
+
+#ifdef WORKER
+
+extern int blocking_getaddrinfo(blocking_pipe_header *);
+extern int blocking_getnameinfo(blocking_pipe_header *);
+
+#ifdef TEST_BLOCKING_WORKER
+extern void gai_test_callback(int rescode, int gai_errno,
+                             void *context, const char *name,
+                             const char *service,
+                             const struct addrinfo *hints,
+                             const struct addrinfo *ai_res);
+extern void gni_test_callback(int rescode, int gni_errno,
+                             sockaddr_u *psau, int flags,
+                             const char *host,
+                             const char *service, void *context);
+#endif /* TEST_BLOCKING_WORKER */
+#endif /* WORKER */
+#endif /* !NTP_INTRES_H */
index 692d4440fc04e74634ac5eece7efa58f0c679b22..685524895355e32e03ce7c86500a25ca89e5dca5 100644 (file)
@@ -1,13 +1,12 @@
 #ifndef NTP_IO_H
 #define NTP_IO_H
+
+#include "ntp_workimpl.h"
+
 /*
  * POSIX says use <fnct.h> to get O_* symbols and 
  * SEEK_SET symbol form <unistd.h>.
  */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include <sys/types.h>
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
@@ -69,7 +68,6 @@ typedef enum {
        MATCH_IFADDR
 } nic_rule_match;
 
-
 /*
  * NIC rule actions
  */
@@ -80,10 +78,18 @@ typedef enum {
 } nic_rule_action;
 
 
+SOCKET         move_fd(SOCKET fd);
 isc_boolean_t  get_broadcastclient_flag(void);
 isc_boolean_t  is_ip_address(const char *, isc_netaddr_t *);
 extern void    sau_from_netaddr(sockaddr_u *, const isc_netaddr_t *);
-extern void add_nic_rule(nic_rule_match match_type, const char *if_name,
-                        int prefixlen, nic_rule_action action);
+extern void    add_nic_rule(nic_rule_match match_type,
+                            const char *if_name, int prefixlen,
+                            nic_rule_action action);
+#ifndef HAVE_IO_COMPLETION_PORT
+extern void    close_all_beyond(int);
+#endif
+#ifdef WORK_FORK
+extern void    update_resp_pipe_fd(int, int);
+#endif
 
 #endif /* NTP_IO_H */
index 2bac38a52cbab1df9e67b5c3f87d1dea80f33a04..218b8fe40d994cc4720507677e2346344eacc086 100644 (file)
 #ifndef NTP_LISTS_H
 #define NTP_LISTS_H
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include <isc/list.h>
 
 
index 73fd172a2ef628d8b4fd0b93d8e298fe77e37a61..4e4e4b15ac0cc675d04fe740de20f9e98f345871 100644 (file)
@@ -1,14 +1,15 @@
 /*
+ * ntp_machine.h
+ *
  * Collect all machine dependent idiosyncrasies in one place.
+ *
+ * The functionality formerly in this file is mostly handled by
+ * Autoconf these days.
  */
 
 #ifndef NTP_MACHINE_H
 #define NTP_MACHINE_H
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #ifdef TIME_WITH_SYS_TIME
 # include <sys/time.h>
 # include <time.h>
@@ -26,9 +27,6 @@
 
                         HEY!  CHECK THIS OUT!
 
-  The first half of this file is obsolete, and is only there to help
-  reconcile "what went before" with "current behavior".
-
   The per-system SYS_* #defins ARE NO LONGER USED, with the temporary
   exception of SYS_WINNT.
 
@@ -84,141 +82,6 @@ MISC
 # define ntp_adjtime __adjtimex
 #endif
 
-#if 0
-
-/*
- * IRIX 4.X and IRIX 5.x
- */
-#if defined(SYS_IRIX4)||defined(SYS_IRIX5)
-# define ADJTIME_IS_ACCURATE
-# define LOCK_PROCESS
-#endif
-
-/*
- * Ultrix
- * Note: posix version has NTP_POSIX_SOURCE and HAVE_SIGNALED_IO
- */
-#if defined(SYS_ULTRIX)
-# define S_CHAR_DEFINED
-# define NTP_SYSCALLS_STD
-# define HAVE_MODEM_CONTROL
-#endif
-
-/*
- * AUX
- */
-#if defined(SYS_AUX2) || defined(SYS_AUX3)
-# define NO_SIGNED_CHAR_DECL
-# define LOCK_PROCESS
-# define NTP_POSIX_SOURCE
-/*
- * This requires that _POSIX_SOURCE be forced on the
- * compiler command flag. We can't do it here since this
- * file is included _after_ the system header files and we
- * need to let _them_ know we're POSIX. We do this in
- * compilers/aux3.gcc...
- */
-# define LOG_NTP LOG_LOCAL1
-#endif
-
-/*
- * HPUX
- */
-#if defined(SYS_HPUX)
-# define getdtablesize() sysconf(_SC_OPEN_MAX)
-# define setlinebuf(f) setvbuf(f, NULL, _IOLBF, 0)
-# define NO_SIGNED_CHAR_DECL
-# define LOCK_PROCESS
-#endif
-
-/*
- * BSD/OS 2.0 and above
- */
-#if defined(SYS_BSDI)
-# define USE_FSETOWNCTTY       /* this funny system demands a CTTY for FSETOWN */
-#endif
-
-/*
- * FreeBSD 2.0 and above
- */
-#ifdef SYS_FREEBSD
-# define KERNEL_PLL
-#endif
-
-/*
- * Linux
- */
-#if defined(SYS_LINUX)
-# define ntp_adjtime __adjtimex
-#endif
-
-/*
- * PTX
- */
-#if defined(SYS_PTX)
-# define LOCK_PROCESS
-struct timezone { int __0; };  /* unused placebo */
-/*
- * no comment !@!
- */
-typedef unsigned int u_int;
-# ifndef       _NETINET_IN_SYSTM_INCLUDED      /* i am about to comment... */
-typedef unsigned char u_char;
-typedef unsigned short u_short;
-typedef unsigned long u_long;
-# endif
-#endif
-
-/*
- * UNIX V.4 on and NCR 3000
- */
-#if defined(SYS_SVR4)
-# define STREAM
-# define LOCK_PROCESS
-# define SIZE_RETURNED_IN_BUFFER
-#endif
-
-/*
- * (Univel/Novell) Unixware1 SVR4 on intel x86 processor
- */
-#if defined(SYS_UNIXWARE1)
-/* #define _POSIX_SOURCE */
-# define STREAM
-# define STREAMS
-# undef STEP_SLEW              /* TWO step */
-# define LOCK_PROCESS
-# define SIZE_RETURNED_IN_BUFFER
-# include <sys/sockio.h>
-# include <sys/types.h>
-# include <netinet/in_systm.h>
-#endif
-
-/*
- * DomainOS
- */
-#if defined(SYS_DOMAINOS)
-# define NTP_SYSCALLS_STD
-/* older versions of domain/os don't have class D */
-# ifndef IN_CLASSD
-#  define IN_CLASSD(i)         (((long)(i) & 0xf0000000) == 0xe0000000)
-#  define IN_CLASSD_NET        0xf0000000
-#  define IN_CLASSD_NSHIFT     28
-#  define IN_CLASSD_HOST       0xfffffff
-#  define IN_MULTICAST(i)      IN_CLASSD(i)
-# endif
-#endif
-
-/*
- * Fujitsu UXP/V
- */
-#if defined(SYS_UXPV)
-# define LOCK_PROCESS
-# define SIZE_RETURNED_IN_BUFFER
-#endif
-
-
-#endif /* 0 */
-
 /*
  * Define these here for non-Windows NT systems
  * SOCKET and INVALID_SOCKET are native macros
@@ -502,34 +365,7 @@ extern time_t      timegm          (struct tm *);
        && !defined(HAVE_TERMIOS)
 #include "ERROR: no tty type defined!"
 # endif
-#endif /* SYS_WINNT || VMS     || SYS_VXWORKS*/
+#endif /* !SYS_WINNT && !VMS && !SYS_VXWORKS*/
 
-#ifdef WORDS_BIGENDIAN
-# define       XNTP_BIG_ENDIAN 1
-#else
-# define       XNTP_LITTLE_ENDIAN      1
-#endif
-
-/*
- * Byte order woes.
- * This used to be resolved by calling ntohl() and htonl() to swap things
- * around, but this turned out to be quite costly on Vaxes where those
- * things are actual functions.  The code now straightens out byte
- * order troubles on its own, with no performance penalty for little
- * end first machines, but at great expense to cleanliness.
- */
-#if !defined(XNTP_BIG_ENDIAN) && !defined(XNTP_LITTLE_ENDIAN)
-       /*
-        * Pick one or the other.
-        */
-       BYTE_ORDER_NOT_DEFINED_FOR_AUTHENTICATION
-#endif
-
-#if defined(XNTP_BIG_ENDIAN) && defined(XNTP_LITTLE_ENDIAN)
-       /*
-        * Pick one or the other.
-        */
-       BYTE_ORDER_NOT_DEFINED_FOR_AUTHENTICATION
-#endif
 
 #endif /* NTP_MACHINE_H */
index 0dbcbeed448301f7f67aece5b7de1cbd389edc83..9203c53f0fdee7586314b6a06c44643c7ea7e95a 100644 (file)
@@ -4,10 +4,6 @@
 #ifndef NTP_MALLOC_H
 #define NTP_MALLOC_H
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #ifdef HAVE_STDLIB_H
 # include <stdlib.h>
 #else
 # endif
 #endif
 
+/*
+ * Deal with platform differences declaring alloca()
+ * This comes nearly verbatim from:
+ *
+ * http://www.gnu.org/software/autoconf/manual/autoconf.html#Particular-Functions
+ *
+ * The only modifications were to remove C++ support and guard against
+ * redefining alloca.
+ */
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#elif defined __GNUC__
+# ifndef alloca
+#  define alloca __builtin_alloca
+# endif
+#elif defined _AIX
+# ifndef alloca
+#  define alloca __alloca
+# endif
+#elif defined _MSC_VER
+# include <malloc.h>
+# ifndef alloca
+#  define alloca _alloca
+# endif
+#else
+# include <stddef.h>
+void * alloca(size_t);
+#endif
+
 #endif /* NTP_MALLOC_H */
index e6e78553305be423aa711ceec0f30a1fe5fd9971..1d04b78ab4b23d93cf1ecd44ca6ab966180399f4 100644 (file)
@@ -1,10 +1,6 @@
-#ifndef __ntp_proto_h
-#define __ntp_proto_h
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#ifndef NTP_PROTO_H
+#define NTP_PROTO_H
 
 #define NTP_MAXFREQ    500e-6
  
-#endif /* __ntp_proto_h */
+#endif /* NTP_PROTO_H */
index 4ed1b657cbe4f0f46338f100098e05dabf6c1ba4..703e972a9f49fb55db2c95c5b22f5e5277a7d0f3 100644 (file)
 #ifndef NTP_RFC2553_H
 #define NTP_RFC2553_H
 
-/*
- * Ensure that we include the configuration file before we check
- * for IPV6
- */
-#include <config.h>
 #include <netdb.h>
 #include <isc/net.h>
 
index dc60f70b3ae0e1e449112f70555e8c986b85f5b8..2c0fbeec980f7f48fc7dd7fce8c3f60086e97e94 100644 (file)
@@ -2,39 +2,34 @@
  * Not all machines define FD_SET in sys/types.h
  */ 
 #ifndef NTP_SELECT_H
-#define NTP_SELECT_H
+#define NTP_SELECT_H   /* note: tested by include/l_stdlib.h */
 
 /* Was: (defined(RS6000)||defined(SYS_PTX))&&!defined(_BSD) */
 /* Could say: !defined(FD_SET) && defined(HAVE_SYS_SELECT_H) */
+/* except FD_SET can legitimately be a typedef... */
 #if defined(HAVE_SYS_SELECT_H) && !defined(_BSD)
-#ifndef SYS_VXWORKS
-#include <sys/select.h>
-#else
-#include <sockLib.h>
-extern int  select (int width, fd_set *pReadFds, fd_set *pWriteFds,
-                   fd_set *pExceptFds, struct timeval *pTimeOut);
-
-#endif
+# ifndef SYS_VXWORKS
+#  include <sys/select.h>
+# else
+#  include <sockLib.h>
+extern int     select(int width, fd_set *pReadFds, fd_set *pWriteFds,
+                      fd_set *pExceptFds, struct timeval *pTimeOut);
+# endif
 #endif
 
 #if !defined(FD_SET)
-#define NFDBITS         32
-#define FD_SETSIZE      32
-#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
-#define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
-#define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
-#define FD_ZERO(p)      memset((char *)(p), 0, sizeof(*(p)))
+# define NFDBITS       32
+# define FD_SETSIZE    32
+# define FD_SET(n, p)  ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+# define FD_CLR(n, p)  ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+# define FD_ISSET(n, p)        ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+# define FD_ZERO(p)    memset((p), 0, sizeof(*(p)))
 #endif
 
 #if defined(VMS)
 typedef struct {
-    unsigned int fds_bits[1];
+       unsigned int fds_bits[1];
 } fd_set;
 #endif
 
-#ifdef SYS_WINNT
-/* ports/winnt/libntp/setpriority.c */
-extern void    InitSockets(void);
-#endif
-
 #endif /* NTP_SELECT_H */
index f2024fb16cf3500a90c7c9882e5a50fc0167f4c5..f88965eb0bb67607985c2fa822126362b2df7fc2 100644 (file)
@@ -10,7 +10,6 @@
 #endif
 
 #include "l_stdlib.h"
-#include "ntp_rfc2553.h"
 #include "ntp_types.h"
 #include "ntp_string.h"
 #include "ntp_net.h"
@@ -88,6 +87,7 @@ extern        int     atoint          (const char *, long *);
 extern int     atouint         (const char *, u_long *);
 extern int     hextoint        (const char *, u_long *);
 extern char *  humanlogtime    (void);
+extern char *  humantime       (time_t);
 extern char *  inttoa          (long);
 extern char *  mfptoa          (u_long, u_long, short);
 extern char *  mfptoms         (u_long, u_long, short);
index aab7084b0536e5f6b8403def021a79376527ad9b..b96802437866257d9a9edc0f027fc0136bdb8f91 100644 (file)
@@ -2,12 +2,8 @@
  * Define string ops: strchr strrchr memcmp memmove memset 
  */
 
-#ifndef  _ntp_string_h
-#define  _ntp_string_h
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#ifndef NTP_STRING_H
+#define NTP_STRING_H
 
 #ifdef HAVE_MEMORY_H
 # include <memory.h>
@@ -52,4 +48,4 @@ void  ntp_memset      (char *, int, int);
                                        ntp_memset((char *)(a), x, c)
 #endif /*  NTP_NEED_BOPS */
 
-#endif /* _ntp_string_h */
+#endif /* NTP_STRING_H */
index c255cee46b5fc60b87dec6fac5219a56e72e3eeb..df2452caae9f4b682be0f6091ace9caa2360c7f2 100644 (file)
@@ -6,10 +6,6 @@
 #ifndef NTP_SYSCALL_H
 #define NTP_SYSCALL_H
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #ifdef HAVE_SYS_TIMEX_H
 # include <sys/timex.h>
 #endif
index 38021e2516821db63dbd4e2d01803d242ce3cb75..3e486b5179b24333bf8a3072541db4b5bba27d76 100644 (file)
@@ -5,17 +5,19 @@
 #ifndef NTP_SYSLOG_H
 #define NTP_SYSLOG_H
 
-# ifdef VMS
+#ifdef VMS
 extern void msyslog();
-# else
-#   ifndef SYS_VXWORKS
-#   include <syslog.h>
-#   endif
-# endif /* VMS */
-# include <stdio.h>
+#else
+# ifndef SYS_VXWORKS
+#  include <syslog.h>
+# endif
+#endif /* VMS */
+#include <stdio.h>
 
-extern int syslogit;
-extern FILE *syslog_file;
+extern int     syslogit;
+extern FILE *  syslog_file;
+extern char *  syslog_fname;
+extern char *  syslog_abs_fname;
 
 #if defined(VMS) || defined (SYS_VXWORKS)
 #define        LOG_EMERG       0       /* system is unusable */
index ed6a2ca4b4800411dc2c007999f6d42e316d6000..c526df0af649c1ccdd80d0ebc1c43854587853eb 100644 (file)
@@ -49,23 +49,23 @@ typedef unsigned int u_int;
 
 #if (SIZEOF_INT == 4)
 # ifndef int32
-#  define int32 int
+   typedef     int             int32;
 # endif
 # ifndef u_int32
-#  define u_int32 unsigned int
+   typedef     unsigned        u_int32;
 # endif
-#else /* not sizeof(int) == 4 */
+#else  /* SIZEOF_INT != 4 */
 # if (SIZEOF_LONG == 4)
 #  ifndef int32
-#   define int32 long
+    typedef    long            int32;
 #  endif
 #  ifndef u_int32
-#   define u_int32 unsigned long
+    typedef    unsigned long   u_int32;
 #  endif
-# else /* not sizeof(long) == 4 */
+# else /* SIZEOF_LONG != 4 */
 #  include "Bletch: what's 32 bits on this machine?"
-# endif /* not sizeof(long) == 4 */
-#endif /* not sizeof(int) == 4 */
+# endif
+#endif /* SIZEOF_INT != 4 */
 
 typedef u_char         ntp_u_int8_t;
 typedef u_short                ntp_u_int16_t;
diff --git a/include/ntp_worker.h b/include/ntp_worker.h
new file mode 100644 (file)
index 0000000..2303258
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * ntp_worker.h
+ */
+
+#ifndef NTP_WORKER_H
+#define NTP_WORKER_H
+
+#include "ntp_workimpl.h"
+
+#ifdef WORKER
+
+/* #define TEST_BLOCKING_WORKER */     /* ntp_config.c ntp_intres.c */
+
+typedef enum blocking_work_req_tag {
+       BLOCKING_GETNAMEINFO,
+       BLOCKING_GETADDRINFO,
+} blocking_work_req;
+
+typedef void (*blocking_work_callback)(blocking_work_req, void *, size_t, void *);
+
+typedef enum blocking_magic_sig_e {
+       BLOCKING_REQ_MAGIC  = 0xb10c7ecf,
+       BLOCKING_RESP_MAGIC = 0xb10c7e54,
+} blocking_magic_sig;
+
+/*
+ * The same header is used for both requests to and responses from
+ * the child.  In the child, done_func and context are opaque.
+ */
+typedef struct blocking_pipe_header_tag {
+       size_t                  octets;
+       blocking_magic_sig      magic_sig;
+       blocking_work_req       rtype;
+       blocking_work_callback  done_func;
+       void *                  context;
+} blocking_pipe_header;
+
+extern int     intres_req_pending;
+
+extern int queue_blocking_request(blocking_work_req, void *, size_t, blocking_work_callback, void *);
+extern int queue_blocking_response(blocking_pipe_header *, size_t, const blocking_pipe_header *);
+extern int send_blocking_req_internal(blocking_pipe_header *, void *);
+extern int send_blocking_resp_internal(blocking_pipe_header *);
+extern blocking_pipe_header *receive_blocking_req_internal(void);
+extern blocking_pipe_header *receive_blocking_resp_internal(void);
+extern int blocking_child_common (void);
+extern void exit_worker(int);
+extern int worker_sleep(time_t);
+
+#endif /* WORKER */
+
+#endif /* !NTP_WORKER_H */
diff --git a/include/ntp_workimpl.h b/include/ntp_workimpl.h
new file mode 100644 (file)
index 0000000..ddba76a
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * ntp_workimpl.h - selects worker child implementation
+ */
+#ifndef NTP_WORKIMPL_H
+#define NTP_WORKIMPL_H
+
+/*
+ * Some systems do not support fork() and don't have an alternate
+ * threads implementation of ntp_intres.  Such systems are limited
+ * to using numeric IP addresses.
+ */
+#if defined(SYS_WINNT)
+# define WORK_THREAD
+#elif defined(VMS) || defined(SYS_VXWORKS)
+  /* empty */
+#elif defined(HAVE_WORKING_FORK)
+# define WORK_FORK
+#endif
+
+#if defined(WORK_FORK) || defined(WORK_THREAD)
+# define WORKER
+#endif
+
+
+#endif /* !NTP_WORKIMPL_H */
index 10fb7d057aba65272e7423a5d2f5c10779692fc9..3c5e4a6175c930e444958af0453a2a3e34c0d7e0 100644 (file)
@@ -9,6 +9,7 @@
 #include "ntp_select.h"
 #include "ntp_malloc.h"
 #include "ntp_refclock.h"
+#include "ntp_workimpl.h"
 #include "recvbuff.h"
 
 /* ntp_config.c */
@@ -24,8 +25,9 @@ extern        u_short ctlpeerstatus   (struct peer *);
 extern int     ctlsettrap      (sockaddr_u *, struct interface *, int, int);
 extern u_short ctlsysstatus    (void);
 extern void    init_control    (void);
-extern void    init_logging    (char const *, int);
-extern void    setup_logfile   (void);
+extern void    init_logging    (const char *, int);
+extern int     change_logfile  (const char *, int);
+extern void    setup_logfile   (int);
 extern void    process_control (struct recvbuf *, int);
 extern void    report_event    (int, struct peer *, const char *);
 
@@ -53,18 +55,33 @@ struct ctl_var {
 #define        WO      (CAN_WRITE)
 #define        RW      (CAN_READ|CAN_WRITE)
 
-extern  char *  add_var (struct ctl_var **, u_long, u_short);
-extern  void    free_varlist (struct ctl_var *);
-extern  void    set_var (struct ctl_var **, const char *, u_long, u_short);
-extern  void    set_sys_var (const char *, u_long, u_short);
+extern char *  add_var (struct ctl_var **, u_long, u_short);
+extern void    free_varlist (struct ctl_var *);
+extern void    set_var (struct ctl_var **, const char *, u_long, u_short);
+extern void    set_sys_var (const char *, u_long, u_short);
 
 /* ntp_intres.c */
-extern void    ntp_res_name    (sockaddr_u, u_short);
-extern void    ntp_res_recv    (void);
-extern void    ntp_intres      (void);
-#ifdef SYS_WINNT
-extern unsigned WINAPI ntp_intres_thread       (void *);
-#endif
+#ifdef WORKER
+typedef void   (*gai_sometime_callback)
+                   (int, int, void *, const char *, const char *,
+                    const struct addrinfo *, const struct addrinfo *);
+/*
+ * you call getaddrinfo_sometime(name, service, &hints, callback_func, context);
+ * later (*callback_func)(rescode, gai_errno, context, name, service, hints, ai_result) is called.
+ */
+extern int     getaddrinfo_sometime(const char *, const char *,
+                                    const struct addrinfo *,
+                                    gai_sometime_callback, void *);
+typedef void   (*gni_sometime_callback)
+                   (int, int, sockaddr_u *, int, const char *,
+                    const char *, void *);
+/*
+ * you call getnameinfo_sometime(sockaddr, namelen, servlen, flags, callback_func, context);
+ * later (*callback_func)(rescode, gni_errno, sockaddr, flags, name, service, context) is called.
+ */
+extern int getnameinfo_sometime(sockaddr_u *, size_t, size_t, int,
+                               gni_sometime_callback, void *);
+#endif /* WORKER */
 
 /* ntp_io.c */
 typedef struct interface_info {
@@ -221,14 +238,15 @@ extern    void    init_timer      (void);
 extern void    reinit_timer    (void);
 extern void    timer           (void);
 extern void    timer_clr_stats (void);
-extern  void    timer_interfacetimeout (u_long);
-extern  volatile int interface_interval;
+extern void    timer_interfacetimeout (u_long);
+extern volatile int interface_interval;
+extern u_long  worker_idle_timer;      /* next check current_time */
 #ifdef OPENSSL
 extern char    *sys_hostname;  /* host name */
 extern char    *sys_groupname; /* group name */
 extern char    *group_name;    /* group name */
-extern u_long  sys_revoke;     /* keys revoke timeout */
-extern u_long  sys_automax;    /* session key timeout */
+extern u_long  sys_revoke;     /* keys revoke timeout */
+extern u_long  sys_automax;    /* session key timeout */
 #endif /* OPENSSL */
 
 /* ntp_util.c */
@@ -247,10 +265,22 @@ extern    void    record_timing_stats (const char *);
 #endif
 extern  u_short        sock_hash (sockaddr_u *);
 extern char *  fstostr(time_t);        /* NTP timescale seconds */
-extern double  old_drift;
-extern int     drift_file_sw;
-extern double  wander_threshold;
-extern double  wander_resid;
+
+/* ntp_worker.c */
+#ifdef WORKER
+extern void    process_blocking_response(void);
+extern void    worker_idle_timer_fired(void);
+extern void    interrupt_worker_sleep(void);
+#endif /* WORKER */
+#if defined(HAVE_DROPROOT) && defined(WORK_FORK)
+extern void    fork_deferred_worker(void);
+#else
+# define       fork_deferred_worker()  do {} while (0)
+#endif
+
+/* ntpd.c */
+extern void    parse_cmdline_opts(int *, char ***);
+
 
 /*
  * Variable declarations for ntpd.
@@ -300,17 +330,6 @@ extern u_long      numctldatatooshort;     /* data too short for count */
 extern u_long  numctlbadop;            /* bad op code found in packet */
 extern u_long  numasyncmsgs;           /* number of async messages we've sent */
 
-/* ntp_intres.c */
-extern keyid_t req_keyid;              /* request keyid */
-extern int     req_keytype;            /* OpenSSL NID such as NID_md5 */
-extern size_t  req_hashlen;            /* digest size for req_keytype */
-extern char *  req_file;               /* name of the file with configuration info */
-#ifdef SYS_WINNT
-extern HANDLE ResolverEventHandle;
-#else
-extern int resolver_pipe_fd[2];  /* used to let the resolver process alert the parent process */
-#endif /* SYS_WINNT */
-
 /*
  * Other statistics of possible interest
  */
@@ -470,20 +489,31 @@ extern u_long     timer_overflows;
 extern u_long  timer_xmtcalls;
 
 /* ntp_util.c */
-extern int     stats_control;          /* write stats to fileset? */
-extern int     stats_write_period;     /* # of seconds between writes. */
-extern double  stats_write_tolerance;
+extern int     stats_control;          /* write stats to fileset? */
+extern int     stats_write_period;     /* # of seconds between writes. */
+extern double  stats_write_tolerance;
+extern double  old_drift;
+extern int     drift_file_sw;
+extern double  wander_threshold;
+extern double  wander_resid;
+
+/* ntp_worker.c */
+#if defined(WORK_FORK)
+extern int     parent_resp_read_pipe;
+#elif defined (WORK_THREAD)
+extern HANDLE  blocking_response_ready;
+#endif
 
 /* ntpd.c */
-extern void    parse_cmdline_opts(int *, char ***);
-extern volatile int debug;             /* debugging flag */
-extern int     nofork;                 /* no-fork flag */
-extern int     initializing;           /* initializing flag */
+extern volatile int debug;     /* debugging flag */
+extern int     nofork;         /* no-fork flag */
+extern int     initializing;   /* initializing flag */
 #ifdef HAVE_DROPROOT
-extern int droproot;                   /* flag: try to drop root privileges after startup */
-extern char *user;                     /* user to switch to */
-extern char *group;                    /* group to switch to */
-extern const char *chrootdir;          /* directory to chroot to */
+extern int     droproot;       /* flag: try to drop root privileges after startup */
+extern int     root_dropped;   /* root has been dropped */
+extern char *user;             /* user to switch to */
+extern char *group;            /* group to switch to */
+extern const char *chrootdir;  /* directory to chroot() to */
 #endif
 
 /* refclock_conf.c */
index 1fdc54a4d7ebd3591524e2697b401b14df7c9a17..efb637fdbe727e4d0077adf1b5a1e6f501662d7f 100644 (file)
@@ -1,10 +1,6 @@
 #ifndef RECVBUFF_H
 #define RECVBUFF_H
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
 #include "ntp.h"
 #include "ntp_fp.h"
 #include "ntp_lists.h"
@@ -21,7 +17,7 @@
 
 #if defined HAVE_IO_COMPLETION_PORT
 # include "ntp_iocompletionport.h"
-#include "ntp_timer.h"
+# include "ntp_timer.h"
 
 # define RECV_BLOCK_IO()       EnterCriticalSection(&RecvCritSection)
 # define RECV_UNBLOCK_IO()     LeaveCriticalSection(&RecvCritSection)
index 46cd96d19cf730b0f7d507b871d79f6ed26a8ca6..1064b366af1696329c05abc9570d7d693b27c9a5 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * atoint - convert an ascii string to a signed long, with error checking
  */
+#include <config.h>
 #include <sys/types.h>
 #include <ctype.h>
 
index adb67936fe44466179a1344694b84b2e10a7dc39..4afeb23d33aa94a707c054625de359807e34a4d0 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * atolfp - convert an ascii string to an l_fp number
  */
+#include <config.h>
 #include <stdio.h>
 #include <ctype.h>
 
index c25e3a0c51a736380c3c3e82f9c40c8ae5eceba6..98f6671d9e9e3ac441454f1cfd8d75231d3ea74a 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * atouint - convert an ascii string to an unsigned long, with error checking
  */
+#include <config.h>
 #include <sys/types.h>
 #include <ctype.h>
 
index bef7b847324894486b00583443b7c30654735c26..ba7a0a18d90094c57be54b84dcacba9ae3fd97e1 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * authusekey - decode a key from ascii and use it
  */
+#include <config.h>
 #include <stdio.h>
 #include <ctype.h>
 
index 7673061b57ce8df9339e16c7e6de0280914711a7..9c44277a1baeea458f51aa67c3c0ef9517b4358f 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * caljulian - determine the Julian date from an NTP time.
  */
+#include <config.h>
 #include <sys/types.h>
 
 #include "ntp_types.h"
index 9c4136842d9db71846f1e14ebefb4d1cb1dee1b5..9e7aa99e28a2aa69c2b0b06d02dfe3281311f661 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * caltontp - convert a date to an NTP time
  */
+#include <config.h>
 #include <sys/types.h>
 
 #include "ntp_types.h"
index c5a63f729b399f38f9f7c5b017200700eff425eb..c0925c1498277ae9e135948c3ec53eeffba9885f 100644 (file)
@@ -2,6 +2,7 @@
  * calyearstart - determine the NTP time at midnight of January 1 in
  *               the year of the given date.
  */
+#include <config.h>
 #include <sys/types.h>
 
 #include "ntp_types.h"
index 371859cda21cc9522e42a43f95b203f1c0780e74..6133f000391a286f4ec9b6ba48172129e16545d3 100644 (file)
@@ -2,6 +2,7 @@
  * clocktime - compute the NTP date from a day of year, hour, minute
  *            and second.
  */
+#include <config.h>
 #include "ntp_fp.h"
 #include "ntp_unixtime.h"
 #include "ntp_stdlib.h"
index 4459830ed19de39b1f4a78b2be00165318b523d8..c9e242e675fc674bc662e789a1447d441a25a9d2 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Data for pretty printing clock types
  */
+#include <config.h>
 #include <stdio.h>
 
 #include "ntp_fp.h"
index 0f96909f11751a9ddbd62a73011711c3ddb4871a..1d60fe9397bf24b4e76f3445e3069816b81265ec 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * dofptoa - do the grunge work to convert an fp number to ascii
  */
+#include <config.h>
 #include <stdio.h>
 
 #include "ntp_fp.h"
index f68679cf000bbf2c569fb0ab95b744743a312b2c..865da915914554fab90131160cd0983338a5650f 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * dolfptoa - do the grunge work of converting an l_fp number to decimal
  */
+#include <config.h>
 #include <stdio.h>
 
 #include "ntp_fp.h"
index 5c40f4ee041017bb2e513c226886634f39b3e65e..63761305cb7ea2bd65a6113bcd75daa8382b704f 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * emalloc - return new memory obtained from the system.  Belch if none.
  */
+#include <config.h>
 #include "ntp_types.h"
 #include "ntp_malloc.h"
 #include "ntp_syslog.h"
index 025ad21e55b4b05b8f0e6a799f3c6c834cb33f44..771c6dfceef93b869e62e7d26cf764efcddf4b46 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * fptoa - return an asciized representation of an s_fp number
  */
+#include <config.h>
 #include "ntp_fp.h"
 #include "ntp_stdlib.h"
 
index 0bfca55561604f113faee6059097980595455805..9a1ab77acda0e7ec7beec01b540ff4d77bc2e4ea 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * fptoms - return an asciized s_fp number in milliseconds
  */
+#include <config.h>
 #include "ntp_fp.h"
 
 char *
index 7b344f0dc6f4cbd14cd4b5e526c5b1825fba9c8d..63c82faa6f774e40cafd7af7f9e25595131273ec 100644 (file)
@@ -13,6 +13,7 @@
 
 /*LINTLIBRARY*/
 
+#include <config.h>
 #include <stdio.h>
 
 #include "ntp_stdlib.h"
index a2e8c043fb35027b4d75505863ee883d53638b76..d24b5a0bf8a53ff0dbfff105ae3b6a5523738cb5 100644 (file)
@@ -2,6 +2,7 @@
  * hextoint - convert an ascii string in hex to an unsigned
  *           long, with error checking
  */
+#include <config.h>
 #include <ctype.h>
 
 #include "ntp_stdlib.h"
index d0b624340d93b63f604dec5442aa2b5e3b76f117..8fbce2e5b86339f4377202f810b37a7b093bada7 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * hextolfp - convert an ascii hex string to an l_fp number
  */
+#include <config.h>
 #include <stdio.h>
 #include <ctype.h>
 
index e3614cf20a18c784c0383128f9e1809b2b558d0c..0081522630c228888d70794cadd0fe0906dc814a 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * humandate - convert an NTP (or the current) time to something readable
  */
+#include <config.h>
 #include <stdio.h>
 #include "ntp_fp.h"
 #include "ntp_unixtime.h"      /* includes <sys/time.h> and <time.h> */
@@ -15,19 +16,45 @@ extern const char *months[];        /* prettydate.c */
 char *
 humanlogtime(void)
 {
-       char *bp;
-       time_t cursec = time((time_t *) 0);
-       struct tm *tm;
+       char *          bp;
+       time_t          cursec;
+       struct tm *     tm;
        
+       cursec = time(NULL);
        tm = localtime(&cursec);
        if (!tm)
                return "-- --- --:--:--";
 
        LIB_GETBUF(bp);
        
-       (void) sprintf(bp, "%2d %s %02d:%02d:%02d",
-                      tm->tm_mday, months[tm->tm_mon],
-                      tm->tm_hour, tm->tm_min, tm->tm_sec);
+       snprintf(bp, LIB_BUFLENGTH, "%2d %s %02d:%02d:%02d",
+                tm->tm_mday, months[tm->tm_mon],
+                tm->tm_hour, tm->tm_min, tm->tm_sec);
+               
+       return bp;
+}
+
+
+/*
+ * humantime() -- like humanlogtime() but without date, and with the
+ *               time to display given as an argument.
+ */
+char *
+humantime(
+       time_t cursec
+       )
+{
+       char *          bp;
+       struct tm *     tm;
+       
+       tm = localtime(&cursec);
+       if (!tm)
+               return "--:--:--";
+
+       LIB_GETBUF(bp);
+       
+       snprintf(bp, LIB_BUFLENGTH, "%02d:%02d:%02d",
+                tm->tm_hour, tm->tm_min, tm->tm_sec);
                
        return bp;
 }
index 557fc06ae87921c90b9eecf7261bb376a0781236..f45a591fedd986daa130b76994cde00e5a77728c 100644 (file)
@@ -5,6 +5,7 @@
  * distribution. The only function provided is to load the radio
  * frequency. All other parameters must be manually set before use.
  */
+#include <config.h>
 #include "icom.h"
 #include <unistd.h>
 #include <stdio.h>
index 5859e40e0e7830be846066a4afbc9b9d00d7c2ff..b10a161e9ee9370295e6e2ab0efb3df3c58c7a00 100644 (file)
@@ -65,34 +65,6 @@ extern       void    input_handler   (l_fp *);
  * SIGPOLL and SIGIO ROUTINES.
  */
 
- /*
- * Some systems (MOST) define SIGPOLL == SIGIO, others SIGIO == SIGPOLL, and
- * a few have separate SIGIO and SIGPOLL signals.  This code checks for the
- * SIGIO == SIGPOLL case at compile time.
- * Do not define USE_SIGPOLL or USE_SIGIO.
- * these are interal only to iosignal.c!
- */
-# if defined(USE_SIGPOLL)
-#  undef USE_SIGPOLL
-# endif
-# if defined(USE_SIGIO)
-#  undef USE_SIGIO
-# endif
-
-# if defined(USE_TTY_SIGPOLL) || defined(USE_UDP_SIGPOLL)
-#  define USE_SIGPOLL
-# endif
-
-# if !defined(USE_TTY_SIGPOLL) || !defined(USE_UDP_SIGPOLL)
-#  define USE_SIGIO
-# endif
-
-# if defined(USE_SIGIO) && defined(USE_SIGPOLL)
-#  if SIGIO == SIGPOLL
-#      define USE_SIGIO
-#      undef USE_SIGPOLL
-#  endif /* SIGIO == SIGPOLL */
-# endif /* USE_SIGIO && USE_SIGIO */
 
 
 /*
index 6450b2c136be668c4d05de326490a6776d408f39..af83d00be6d593e4b73cc67bb24ffc2c8051ca29 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * mfptoa - Return an asciized representation of a signed long fp number
  */
+#include <config.h>
 #include "ntp_fp.h"
 #include "ntp_stdlib.h"
 
index d2bfd71eeceedb660ac1042af07470b95a223090..678eacc1147ba72c9cf4a95bfe522a9b41faa4a4 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * mfptoms - Return an asciized signed long fp number in milliseconds
  */
+#include <config.h>
 #include "ntp_fp.h"
 #include "ntp_stdlib.h"
 
index 91be60015b007668bedf01e9600fc321871a5a80..2ba9ed85a1a28987e89e9d1de2eb80b4a3d32c88 100644 (file)
@@ -59,6 +59,7 @@
  * by hand.  Sorry about that.
  */
 
+#include <config.h>
 #include "ntp_machine.h"
 
 #if !defined(HAVE_MKTIME) || !defined(HAVE_TIMEGM)
index 405aef8550c152d0ce41478e7b46da199459f497..6515880f4fee61e24255cf5de5f22a092f6d03f1 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * modetoa - return an asciized mode
  */
+#include <config.h>
 #include <stdio.h>
 
 #include "lib_strbuf.h"
index e4e909df7dbeb7b0de976bebf99b71348ec29a69..1a1a02b5fc463f639b69765d2b59391755976583 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * mstolfp - convert an ascii string in milliseconds to an l_fp number
  */
+#include <config.h>
 #include <stdio.h>
 #include <ctype.h>
 
index eb3babe9cd1aa4ce132d2a9101d5ed399a29b0a2..2182d9f26b1b29db12a30068d09397b9944c7f16 100644 (file)
@@ -2,6 +2,7 @@
  * msutotsf - tables for converting from a subsecond millisecond value
  *           to a time stamp fraction.
  */
+#include <config.h>
 #include <sys/types.h>
 
 #include "ntp_types.h"
index 43466b81c93126f0e07d8ed64d515bd432bb3914..78a0f67fa8b358e09684628ca340bc0251c96b53 100644 (file)
 
 int syslogit = 1;
 
-FILE *syslog_file = NULL;
+FILE * syslog_file;
+char * syslog_fname;
+char * syslog_abs_fname;
 
-u_long ntp_syslogmask =  ~ (u_long) 0;
+u_long ntp_syslogmask =  ~(u_long)0;   /* libntp default is all lit */
 
-#ifdef SYS_WINNT
-static char separator = '\\';
-#else
-static char separator = '/';
-#endif /* SYS_WINNT */
 extern char *progname;
 
 /* Declare the local functions */
@@ -50,32 +47,45 @@ void        format_errmsg   (char *, int, const char *, int);
 void
 addto_syslog(int level, char * buf)
 {
-       char *prog;
-       FILE *out_file = syslog_file;
+       static const char *     last_progname;
+       static const char *     prog;
+       FILE *                  out_file;
 
 #if !defined(VMS) && !defined (SYS_VXWORKS)
-       if (syslogit)
-           syslog(level, "%s", buf);
-       else
+       if (syslogit) {
+               syslog(level, "%s", buf);
+               out_file = NULL;
+       } else
 #endif /* VMS  && SYS_VXWORKS*/
        {
-               out_file = syslog_file ? syslog_file: level <= LOG_ERR ? stderr : stdout;
-               /* syslog() provides the timestamp, so if we're not using
-                  syslog, we must provide it. */
-               prog = strrchr(progname, separator);
-               if (prog == NULL)
-                   prog = progname;
-               else
-                   prog++;
-               (void) fprintf(out_file, "%s ", humanlogtime ());
-               (void) fprintf(out_file, "%s[%d]: %s", prog, (int)getpid(), buf);
+               out_file = (syslog_file) 
+                              ? syslog_file
+                              : (level <= LOG_ERR)
+                                    ? stderr 
+                                    : stdout;
+               if (last_progname != progname) {
+                       last_progname = progname;
+                       prog = strrchr(progname, DIR_SEP);
+                       if (NULL == prog)
+                               prog = progname;
+                       else
+                               prog++;
+               }
+               /* 
+                * syslog() provides the timestamp, so if we're not
+                * using syslog, we must provide it.
+                */
+               fprintf(out_file, "%s %s[%d]: %s", humanlogtime(),
+                                 prog, (int)getpid(), buf);
                fflush (out_file);
        }
 #if DEBUG
        if (debug && out_file != stdout && out_file != stderr)
-               printf("addto_syslog: %s\n", buf);
+               printf("addto_syslog: %s", buf);
 #endif
 }
+
+
 void
 format_errmsg(char *nfmt, int lennfmt, const char *fmt, int errval)
 {
@@ -106,26 +116,18 @@ format_errmsg(char *nfmt, int lennfmt, const char *fmt, int errval)
                        n += len;
                }
        }
-#if !defined(VMS)
-       if (!syslogit)
-#endif /* VMS */
-           *n++ = '\n';
+       /*
+        * syslog adds a trailing \n if not present, do the same so we
+        * have the same behavior with syslog and a log file.
+        */
+       if (n > nfmt && '\n' != n[-1])
+               *n++ = '\n';
        *n = '\0';
 }
 
-#if defined(__STDC__) || defined(HAVE_STDARG_H)
+
 void msyslog(int level, const char *fmt, ...)
-#else /* defined(__STDC__) || defined(HAVE_STDARG_H) */
-     /*VARARGS*/
-     void msyslog(va_alist)
-     va_dcl
-#endif /* defined(__STDC__) || defined(HAVE_STDARG_H) */
 {
-#if defined(__STDC__) || defined(HAVE_STDARG_H)
-#else
-       int level;
-       const char *fmt;
-#endif
        va_list ap;
        char buf[1025], nfmt[256];
        int errval;
index 55a4092befe16a44795afdcc4a10cf03168d5799..edd65c93177e95e8ac6916780dce55b6ddae9067 100644 (file)
@@ -2,6 +2,7 @@
  * netof - return the net address part of an ip address in a sockaddr_storage structure
  *         (zero out host part)
  */
+#include <config.h>
 #include <stdio.h>
 #include <syslog.h>
 
index f792b2bd6184964490eaea30953e86cfea0b1b37..d189e40c494d10c0ad871a6cc2d2d03abd6dc616 100644 (file)
@@ -2,6 +2,7 @@
  * octtoint - convert an ascii string in octal to an unsigned
  *           long, with error checking
  */
+#include <config.h>
 #include <stdio.h>
 #include <ctype.h>
 
index 09f358fe53ca226b0c344cd3b7532665675044e4..806bffb9c44570b028b06604d94d1fca5509e593 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * prettydate - convert a time stamp to something readable
  */
+#include <config.h>
 #include <stdio.h>
 
 #include "ntp_fp.h"
index c52bc28b6389cdbb595a490c7a9325502e5a5bfd..32bdc69793514c61d3d4ab5b86b2a96ea4373a1c 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * refnumtoa - return asciized refclock addresses stored in local array space
  */
+#include <config.h>
 #include <stdio.h>
 
 #include "ntp_net.h"
index 325eea40da4a33e9c4e0ee79e0b200d9b427c469..8120b91fa01b1a17548c73d57eb6819f89fb0aeb 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * socktoa - return a numeric host name from a sockaddr_storage structure
  */
+#include <config.h>
 #include <sys/types.h>
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
index 2e26ba7a51e40cb2c930e694b3fe33bfa7cedef7..7d23d7e5d7364d200038d8555148cb521ecc3594 100644 (file)
@@ -1,3 +1,4 @@
+#include <config.h>
 #include "ntp_malloc.h"
 
 #if !HAVE_STRDUP
index 68099f5fb3f26d5116dbf4f562f28b79a3d7eca9..983e930abdd823fa845ff3ac6486a2f6c0d1fcb1 100644 (file)
@@ -9,67 +9,59 @@
 #include "ntp_syslog.h"
 #include "ntp_stdlib.h"
 
+
 #ifdef HAVE_SIGACTION
 
+#ifdef SA_RESTART
+# define Z_SA_RESTART  SA_RESTART
+#else
+# define Z_SA_RESTART  0
+#endif
+
+# ifdef SA_SIGINFO
+#  define Z_SA_SIGINFO SA_SIGINFO
+# else
+#  define Z_SA_SIGINFO 0
+# endif
+
+# define IGNORED_SA_FLAGS      (Z_SA_RESTART | Z_SA_SIGINFO)
+
+
 void
 signal_no_reset(
-#if defined(__STDC__) || defined(HAVE_STDARG_H)
        int sig,
-       void (*func) (int)
-#else
-       sig, func
-#endif
+       void (*func)(int)
        )
-#if defined(__STDC__) || defined(HAVE_STDARG_H)
-#else
-        int sig;
-        void (*func) (int);
-#endif
 {
        int n;
        struct sigaction vec;
+       struct sigaction ovec;
 
        vec.sa_handler = func;
        sigemptyset(&vec.sa_mask);
-#if 0
-#ifdef SA_RESTART
-       vec.sa_flags = SA_RESTART;
-#else
-       vec.sa_flags = 0;
-#endif
-#else
-       vec.sa_flags = 0;
-#endif
 
-#ifdef SA_RESTART
-/* Added for PPS clocks on Solaris 7 which get EINTR errors */
+       vec.sa_flags = 0;
+       /* Added for PPS clocks on Solaris 7 which get EINTR errors */
 # ifdef SIGPOLL
-       if (sig == SIGPOLL) vec.sa_flags = SA_RESTART;
+       if (SIGPOLL == sig)
+               vec.sa_flags = Z_SA_RESTART;
 # endif
 # ifdef SIGIO
-       if (sig == SIGIO)   vec.sa_flags = SA_RESTART;
+       if (SIGIO == sig)
+               vec.sa_flags = Z_SA_RESTART;
 # endif
-#endif
-
-       while (1)
-       {
-               struct sigaction ovec;
 
+       do
                n = sigaction(sig, &vec, &ovec);
-               if (n == -1 && errno == EINTR) continue;
-               if (ovec.sa_flags
-#ifdef SA_RESTART
-                   && ovec.sa_flags != SA_RESTART
-#endif
-                   )
-                       msyslog(LOG_DEBUG, "signal_no_reset: signal %d had flags %x",
-                               sig, ovec.sa_flags);
-               break;
-       }
-       if (n == -1) {
+       while (-1 == n && EINTR == errno);
+       if (-1 == n) {
                perror("sigaction");
                exit(1);
        }
+       if (ovec.sa_flags & ~IGNORED_SA_FLAGS)
+               msyslog(LOG_DEBUG,
+                       "signal_no_reset: signal %d had flags %x",
+                       sig, ovec.sa_flags);
 }
 
 #elif  HAVE_SIGVEC
@@ -77,16 +69,16 @@ signal_no_reset(
 void
 signal_no_reset(
        int sig,
-       RETSIGTYPE (*func) (int)
+       RETSIGTYPE (*func)(int)
        )
 {
        struct sigvec sv;
        int n;
 
-       bzero((char *) &sv, sizeof(sv));
+       memset(&sv, 0, sizeof(sv));
        sv.sv_handler = func;
        n = sigvec(sig, &sv, (struct sigvec *)NULL);
-       if (n == -1) {
+       if (-1 == n) {
                perror("sigvec");
                exit(1);
        }
@@ -97,13 +89,13 @@ signal_no_reset(
 void
 signal_no_reset(
        int sig,
-       RETSIGTYPE (*func) (int)
+       RETSIGTYPE (*func)(int)
        )
 {
        int n;
 
        n = sigset(sig, func);
-       if (n == -1) {
+       if (-1 == n) {
                perror("sigset");
                exit(1);
        }
@@ -115,16 +107,13 @@ signal_no_reset(
 void
 signal_no_reset(
        int sig,
-       RETSIGTYPE (*func) (int)
+       RETSIGTYPE (*func)(int)
        )
 {
-#ifdef SIG_ERR
-       if (SIG_ERR == signal(sig, func)) {
-#else
-       int n;
-       n = signal(sig, func);
-       if (n == -1) {
+#ifndef SIG_ERR
+# define SIG_ERR       (-1)
 #endif
+       if (SIG_ERR == signal(sig, func)) {
                perror("signal");
                exit(1);
        }
index e45c4d626b870703808cbf7ddcb618fac0d2899a..da5a54c3ba510e54baf2a2788e0b3bdc161fe653 100644 (file)
@@ -4,6 +4,7 @@
  * ATTENTION: Get approval from Dave Mills on all changes to this file!
  *
  */
+#include <config.h>
 #include "ntp_machine.h"
 #include "ntp_fp.h"
 #include "ntp_syslog.h"
index 5926aabc77a6ea8e85c787a8e566f1b03d88311a..2d8c6084ad110b23fb3d1efef8c3182345851009 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * tsftomsu - convert from a time stamp fraction to milliseconds
  */
+#include <config.h>
 #include "ntp_fp.h"
 #include "ntp_stdlib.h"
 
index be4bdd44155dc3cbed5fea10679947c9efa7abf2..278dadfd00ea373be97ccca543e6e004c82ae918 100644 (file)
@@ -2,6 +2,7 @@
  * tstotv - tables for converting from NTP time stamps to struct timeval
  */
 
+#include <config.h>
 #include "ntp_types.h"
 
 /*
index 0bd2b6911472917dd847ebcf571bb08d41bf1734..3983e28f143c5c321f0df6cc452686cc5ed7bc80 100644 (file)
@@ -2,6 +2,7 @@
  * tvtots - tables for converting from Unix struct timeval's to
  *         NTP time stamp format.
  */
+#include <config.h>
 #include <sys/types.h>
 
 #include "ntp_types.h"
index 676a5fdde786005e36e474b5ab7b7697a58b1347..ce21be6219dda5570de9d0716f8626c72769e990 100644 (file)
@@ -2,6 +2,7 @@
  * uglydate - convert a time stamp to something barely readable
  *           The string returned is 37 characters long.
  */
+#include <config.h>
 #include <stdio.h>
 
 #include "ntp_fp.h"
index be48ea5146a6a83f261d07ea5c8f6da2092e7775..f1925f4bff6cbd3f741f23ec9c729b7aa11f9843 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * uinttoa - return an asciized unsigned integer
  */
+#include <config.h>
 #include <stdio.h>
 
 #include "lib_strbuf.h"
@@ -14,7 +15,7 @@ uinttoa(
        register char *buf;
 
        LIB_GETBUF(buf);
+       snprintf(buf, LIB_BUFLENGTH, "%lu", uval);
 
-       (void) sprintf(buf, "%lu", (u_long)uval);
        return buf;
 }
index 796ce40948bdb7ab5eda1919d4858d8109f11f7d..5a9d4c3e35ff247e44b33816c646b03eac2ca1b1 100644 (file)
@@ -2,6 +2,7 @@
  * ymd2yd - compute the date in the year from y/m/d
  */
 
+#include <config.h>
 #include "ntp_fp.h"
 #include "ntp_unixtime.h"
 #include "ntp_stdlib.h"
index 12b47967de75bbf0f425dff62fbf350f0bfc2cfa..d18c61f26695588e3cd2a00ab6a86fb38e452122 100644 (file)
@@ -1,15 +1,37 @@
 NULL=
-#AUTOMAKE_OPTIONS = ../util/ansi2knr no-dependencies
-AUTOMAKE_OPTIONS = 
-BUILT_SOURCES =
+AUTOMAKE_OPTIONS =
+BUILT_SOURCES = info_trimble.c
 noinst_LIBRARIES = @MAKE_LIBPARSE@ @MAKE_LIBPARSE_KERNEL@
 EXTRA_LIBRARIES = libparse.a libparse_kernel.a
 EXTRA_PROGRAMS = parsestreams parsesolaris
 noinst_PROGRAMS = @MAKE_PARSEKMODULE@
-CLEANFILES = libparse.a libparse_kernel.a info_trimble.c
+CLEANFILES = 
 
 K_CFLAGS = -DPARSESTREAM -DNTP_NEED_BOPS
 
+# info_trimble.c was mistakenly created in the build directory
+# previously.  Without special steps, building an updated tree from
+# outside the source directory (a VPATH build) would break trying to
+# update info_trimble.c in the build dir using the default SCCS get
+# action.
+# As a transitional measure, info_trimble.c is listed in
+# libparse_a_SOURCES prefixed by "$(srcdir)/".
+# This prevents attempting to update or use an old leftover
+# info_trimble.c in the build directory, when building outside
+# the source directory.  At the same time, the rule to generate
+# info_trimble.c (now in the source directory) has been updated
+# to delete any leftover info_trimble.c in the build directory.  To
+# ensure that fires in all build trees sharing a common source tree,
+# $(srcdir)/info_trimble.c now depends on Makefile, and has been added
+# temporarily to BUILT_SOURCES.  This causes builds of updated trees to
+# get rid of the troublesome leftover info_trimble.c files in the build
+# directories.
+# After a month or so, this comment block should be removed, the
+# reference to info_trimble.c in libparse_a_SOURCES simplified to
+# filename only again, info_trimble.c be removed from BUILT_SOURCES,
+# and the commented-out $(srcdir)/info_trimble.c rule should replace
+# the info_trimble.c rule.
+
 libparse_a_SOURCES = parse.c \
                     parse_conf.c \
                     clk_meinberg.c \
@@ -24,7 +46,7 @@ libparse_a_SOURCES = parse.c \
                     clk_wharton.c \
                     clk_varitext.c \
                     data_mbg.c \
-                    info_trimble.c \
+                    $(srcdir)/info_trimble.c \
                     trim_info.c \
                     binio.c \
                     ieee754io.c \
@@ -62,104 +84,74 @@ ETAGS_ARGS = Makefile.am
 
 EXTRA_DIST = parsesolaris.c parsestreams.c mkinfo_scmd.sed mkinfo_rcmd.sed info_trimble.c
 
-#
-# create info_trimble.c
-#
-info_trimble.c: $(top_srcdir)/include/trimble.h mkinfo_rcmd.sed mkinfo_scmd.sed
-       @rm -f $@
-       sed -n -f $(srcdir)/mkinfo_scmd.sed $(top_srcdir)/include/trimble.h  > $@ || rm -f $@
-       sed -n -f $(srcdir)/mkinfo_rcmd.sed $(top_srcdir)/include/trimble.h >> $@ || rm -f $@
-
-kieee754io.o: ieee754io.c
+info_trimble.c: Makefile $(top_srcdir)/include/trimble.h $(srcdir)/Makefile.am $(srcdir)/mkinfo_scmd.sed $(srcdir)/mkinfo_rcmd.sed
+       [ "$(srcdir)" != "." ] && rm -f info_trimble.c  # rid ourselves of leftover from old way
+       sed -n -f $(srcdir)/mkinfo_scmd.sed $(top_srcdir)/include/trimble.h  > info_trimble.new
+       sed -n -f $(srcdir)/mkinfo_rcmd.sed $(top_srcdir)/include/trimble.h >> info_trimble.new
+       cmp info_trimble.new $(srcdir)/info_trimble.c || mv -f info_trimble.new $(srcdir)/info_trimble.c
+       rm -f info_trimble.new
+       
+# the workaround form above fires too much, such as during
+# "make install", due to the incorrect info_trimble.c target
+# rather than $(srcdir)/info_trimble.c.  That's why it verifies
+# the file contents have changed before modifying it.
+# post-workaround version:
+# $(srcdir)/info_trimble.c: $(top_srcdir)/include/trimble.h $(srcdir)/Makefile.am $(srcdir)/mkinfo_scmd.sed $(srcdir)/mkinfo_rcmd.sed
+#      sed -n -f $(srcdir)/mkinfo_scmd.sed $(top_srcdir)/include/trimble.h  > info_trimble.new
+#      sed -n -f $(srcdir)/mkinfo_rcmd.sed $(top_srcdir)/include/trimble.h >> info_trimble.new
+#      mv -f info_trimble.new $@
+
+kieee754io.o: $(srcdir)/ieee754io.c
         $(COMPILE) $(K_CFLAGS) -c $(srcdir)/ieee754io.c -o $@
 
-kmfp_mul.o: mfp_mul.c
+kmfp_mul.o: $(srcdir)/mfp_mul.c
         $(COMPILE) $(K_CFLAGS) -c $(srcdir)/mfp_mul.c -o $@
 
-kgpstolfp.o: gpstolfp.c
+kgpstolfp.o: $(srcdir)/gpstolfp.c
         $(COMPILE) $(K_CFLAGS) -c $(srcdir)/gpstolfp.c -o $@
 
-kbinio.o: binio.c
+kbinio.o: $(srcdir)/binio.c
         $(COMPILE) $(K_CFLAGS) -c $(srcdir)/binio.c -o $@
 
-kclk_computime.o: clk_computime.c
+kclk_computime.o: $(srcdir)/clk_computime.c
        $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_computime.c -o $@
 
-kclk_computime_.o: clk_computime_.c
-       $(COMPILE) $(K_CFLAGS) -c clk_computime_.c -o $@
-
-kclk_dcf7000.o: clk_dcf7000.c
+kclk_dcf7000.o: $(srcdir)/clk_dcf7000.c
        $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_dcf7000.c -o $@
 
-kclk_dcf7000_.o: clk_dcf7000_.c
-       $(COMPILE) $(K_CFLAGS) -c clk_dcf7000_.c -o $@
-
-kclk_hopf6021.o: clk_hopf6021.c
+kclk_hopf6021.o: $(srcdir)/clk_hopf6021.c
        $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_hopf6021.c -o $@
 
-kclk_hopf6021_.o: clk_hopf6021_.c
-       $(COMPILE) $(K_CFLAGS) -c clk_hopf6021_.c -o $@
-
-kclk_meinberg.o: clk_meinberg.c
+kclk_meinberg.o: $(srcdir)/clk_meinberg.c
        $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_meinberg.c -o $@
 
-kclk_meinberg_.o: clk_meinberg_.c
-       $(COMPILE) $(K_CFLAGS) -c clk_meinberg_.c -o $@
-
-kclk_rawdcf.o: clk_rawdcf.c
+kclk_rawdcf.o: $(srcdir)/clk_rawdcf.c
        $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_rawdcf.c -o $@
 
-kclk_rawdcf_.o: clk_rawdcf_.c
-       $(COMPILE) $(K_CFLAGS) -c clk_rawdcf_.c -o $@
-
-kclk_rcc8000.o: clk_rcc8000.c
+kclk_rcc8000.o: $(srcdir)/clk_rcc8000.c
        $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_rcc8000.c -o $@
 
-kclk_rcc8000_.o: clk_rcc8000_.c
-       $(COMPILE) $(K_CFLAGS) -c clk_rcc8000_.c -o $@
-
-kclk_schmid.o: clk_schmid.c
+kclk_schmid.o: $(srcdir)/clk_schmid.c
        $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_schmid.c -o $@
 
-kclk_schmid_.o: clk_schmid_.c
-       $(COMPILE) $(K_CFLAGS) -c clk_schmid_.c -o $@
-
-kclk_trimtaip.o: clk_trimtaip.c
+kclk_trimtaip.o: $(srcdir)/clk_trimtaip.c
        $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_trimtaip.c -o $@
 
-kclk_trimtaip_.o: clk_trimtaip_.c
-       $(COMPILE) $(K_CFLAGS) -c clk_trimtaip_.c -o $@
-
-kclk_trimtsip.o: clk_trimtsip.c
+kclk_trimtsip.o: $(srcdir)/clk_trimtsip.c
        $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_trimtsip.c -o $@
 
-kclk_trimtsip_.o: clk_trimtsip_.c
-       $(COMPILE) $(K_CFLAGS) -c clk_trimtsip_.c -o $@
-
-kclk_varitext.o: clk_varitext.c
+kclk_varitext.o: $(srcdir)/clk_varitext.c
        $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_varitext.c -o $@
 
-kclk_varitext_.o: clk_varitext_.c
-       $(COMPILE) $(K_CFLAGS) -c clk_varitext_.c -o $@
-
-kclk_wharton.o: clk_wharton.c
+kclk_wharton.o: $(srcdir)/clk_wharton.c
        $(COMPILE) $(K_CFLAGS) -c $(srcdir)/clk_wharton.c -o $@
 
-kclk_wharton_.o: clk_wharton_.c
-       $(COMPILE) $(K_CFLAGS) -c clk_wharton_.c -o $@
-
-kparse.o: parse.c
+kparse.o: $(srcdir)/parse.c
        $(COMPILE) $(K_CFLAGS) -c $(srcdir)/parse.c -o $@
 
-kparse_.o: parse_.c
-       $(COMPILE) $(K_CFLAGS) -c parse_.c -o $@
-
-kparse_conf.o: parse_conf.c
+kparse_conf.o: $(srcdir)/parse_conf.c
        $(COMPILE) $(K_CFLAGS) -c $(srcdir)/parse_conf.c -o $@
 
-kparse_conf_.o: parse_conf_.c
-       $(COMPILE) $(K_CFLAGS) -c parse_conf_.c -o $@
-
 parsestreams.loadable_module.o: $(parsestreams_OBJECTS) libparse_kernel.a ../libntp/libntp.a
        $(LD) -r -o $@ $(parsestreams_OBJECTS) libparse_kernel.a ../libntp/libntp.a
 
@@ -172,7 +164,7 @@ parse: $(parsesolaris_OBJECTS) libparse_kernel.a ../libntp/libntp.a
 parsesolaris.o: sys/systm.h
 
 sys/systm.h:
-       mkdir sys && \
+       -mkdir sys
        sed -e '/ffs(.*)/d' < /usr/include/sys/systm.h > sys/systm.h
 
 include $(top_srcdir)/depsver.mf
index 2f8546b4adbe3959da8c472ca877cfeddf278fae..1d3ea2c7909b4cdddec284c45c9d92175ed7cb14 100644 (file)
@@ -33,6 +33,7 @@
  *
  */
 
+#include <config.h>
 #include "binio.h"
 
 long
index 991f1e90e2b478a08299de326505a94bdce54ee3..65534b05c89d030c749e59fcebc93ede8a0f643d 100644 (file)
@@ -33,6 +33,7 @@
  *
  */
 
+#include <config.h>
 #ifdef PARSESTREAM
 #define NEED_BOPS
 #include "ntp_string.h"
index 9f1a9bfd601dd9ec28c5addaa1484b72cfc7cc3e..5354dd3223aa2c37f99cad6764ebe606b468434a 100644 (file)
@@ -32,6 +32,7 @@
  * SUCH DAMAGE.
  *
  */
+#include <config.h>
 #include "ntp_fp.h"
 
 #define GPSORIGIN      2524953600UL    /* NTP origin - GPS origin in seconds */
index eea6cbd3f52ce808cefe76bc40c1d49b9d056aa4..6456e0f9f7f6b679ed2ca321aade9e41e9384da0 100644 (file)
@@ -2,6 +2,7 @@
  * Automatically generated - do not modify
  */
 
+#include <config.h>
 #include "ntp_types.h"
 #include "ntpd.h"
 #include "trimble.h"
@@ -91,4 +92,3 @@ cmd_info_t trimble_rcmds[] = {
        { CMD_RSUPER, "CMD_RSUPER", "super paket (0x8F)", "", 0 },
        { 0xFF, "", "" }
 };
-
index 677ed181fc8b3fde8d169b407419d7af80027598..43c1e39faa3f739086ff193f7a0b14698c8f1226 100644 (file)
@@ -32,6 +32,7 @@
  * SUCH DAMAGE.
  *
  */
+#include <config.h>
 #include <stdio.h>
 #include "ntp_stdlib.h"
 #include "ntp_types.h"
index 570c7a0b81e22dcac8a8bc019c867636f5c6d1b8..5238d5c4eb13db698db6ec8d407b2f41abc24d9f 100644 (file)
@@ -1,8 +1,8 @@
 1i\
 \
+\
 cmd_info_t trimble_rcmds[] = {
-s!^#define[    ][      ]*\(CMD_R[^     ]*\)[   ][      ]*\([^  ]*\)[   ][      ]*/\*[  ][      ]*\(.*\)[       ]*:\([^:]*\):\([^:]*\)[         ][      ]*\*/!  { \1, "\1", "\3 (\2)", "\4", \5 },!p
+s!^#define[ \  ][ \    ]*\(CMD_R[^ \   ]*\)[ \ ][ \    ]*\([^ \        ]*\)[ \ ][ \    ]*/\*[ \        ][ \    ]*\(.*\)[ \     ]*:\([^:]*\):\([^:]*\)[ \       ][ \    ]*\*/!\ { \1, "\1", "\3 (\2)", "\4", \5 },!p
 $a\
-       { 0xFF, "", "" }\
-};\
-
+\      { 0xFF, "", "" }\
+};
index cabe0654588d6c2b54ecaf4d20731e6e9bbc07c9..9c17f39ed703eee70f9da3890f3b7e1c009c981e 100644 (file)
@@ -1,8 +1,9 @@
 1i\
 /*\
- * Automatically generated - do not modify\
- */\
+\ * Automatically generated - do not modify\
+\ */\
 \
+#include <config.h>\
 #include "ntp_types.h"\
 #include "ntpd.h"\
 #include "trimble.h"\
@@ -10,7 +11,5 @@
 cmd_info_t trimble_scmds[] = {
 s!^#define[    ][      ]*\(CMD_C[^     ]*\)[   ][      ]*\([^  ]*\)[   ][      ]*/\*[  ][      ]*\(.*\)[       ][      ]*\*/!  { \1, "\1", "\3 (\2)", "", 0 },!p
 $a\
-       { 0xFF, "", "" }\
-};\
-
-
+\      { 0xFF, "", "" }\
+};
index 2d499f0f68cef69aca17922c6990499d98fa5911..aa3572d60c96b94d5952b1657539eb18778c67de 100644 (file)
@@ -40,6 +40,7 @@
 static char rcsid[] = "parsesolaris.c,v 4.11 2005/04/16 17:32:10 kardel RELEASE_20050508_A";
 #endif
 
+#include <config.h>
 #include <sys/types.h>
 #include <sys/conf.h>
 #include <sys/errno.h>
index 8fdc4f61e21cc6e2dd7500498f4efcfdc079a074..619e23861aef3074d7309664c98438736d86c2e5 100644 (file)
@@ -33,6 +33,7 @@
  * SUCH DAMAGE.
  *
  */
+#include <config.h>
 #include "ntp_types.h"
 #include "trimble.h"
 
index b0bc10c24eac2b58a535b89828a8189c9c7f9cd2..479ce526ab9fab5bba92d3e729e836ccaca34d13 100644 (file)
@@ -36,7 +36,7 @@ endif
 #
 # VPHACK and VPHACK_AFTER are enabled on non-GNU makes (such as 
 # BSD make) to work around issues specific to compiling
-# ntp_parser.y into ntp_parser.h and ntp_parser.c in a vPATH
+# ntp_parser.y into ntp_parser.h and ntp_parser.c in a VPATH
 # configuration where we would like (for a change) the output
 # files ntp_parser.[ch] to be placed in the source directory,
 # as opposed to the build directory.  This allows a single
@@ -165,6 +165,7 @@ libntpd_a_SOURCES =         \
        ntp_signd.c             \
        ntp_timer.c             \
        ntp_util.c              \
+       ntp_worker.c            \
        ppsapi_timepps.h        \
        refclock_acts.c         \
        refclock_arbiter.c      \
@@ -206,6 +207,8 @@ libntpd_a_SOURCES =         \
        refclock_wwv.c          \
        refclock_wwvb.c         \
        refclock_zyfer.c        \
+       work_fork.c             \
+       work_thread.c           \
        $(NULL)
 
 ntp_keyword.out: keyword-gen
index 98236f9444237b1b7eeb1aa244868dbb40aa8fdc..71374de3d3ef0ff90e9b0298dcc04f373712872e 100644 (file)
@@ -15,7 +15,6 @@
  * Definitions of things either imported from or exported to outside
  */
 extern char const *progname;
-extern const char *specific_interface;
 
 #ifdef HAVE_NETINFO
 extern int     check_netinfo;
@@ -133,8 +132,8 @@ getCmdOpts(
        if (HAVE_OPT( USER )) {
                droproot = 1;
                user = estrdup(OPT_ARG( USER ));
-               group = rindex(user, ':');
-               if (group)
+               group = strrchr(user, ':');
+               if (group != NULL)
                        *group++ = '\0'; /* get rid of the ':' */
        }
 #endif
index 1ab1e4174ee566c79eb00e5f895068dcbb6cc2f0..859ae597cf849f7dfc8716f54833d4bf0fd3c460 100644 (file)
 # include <netinfo/ni.h>
 #endif
 
+#include <stdio.h>
+#include <ctype.h>
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+#include <signal.h>
+#ifndef SIGCHLD
+# define SIGCHLD SIGCLD
+#endif
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+
 #include "ntp.h"
 #include "ntpd.h"
 #include "ntp_io.h"
 #include "ntp_stdlib.h"
 #include "ntp_assert.h"
 #include "ntpd-opts.h"
-/*
- * Sim header. Currently unconditionally included
- * PDMXXX This needs to be a conditional include
- */
-#include "ntpsim.h"
-
-#include <ntp_random.h>
-#include "ntp_intres.h"
+#include "ntp_random.h"
+#include "ntp_workimpl.h"
 #include <isc/net.h>
 #include <isc/result.h>
 
-#include <stdio.h>
-#include <ctype.h>
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif
-#include <signal.h>
-#ifndef SIGCHLD
-# define SIGCHLD SIGCLD
-#endif
-#if !defined(VMS)
-# ifdef HAVE_SYS_WAIT_H
-#  include <sys/wait.h>
-# endif
-#endif /* VMS */
-
-#ifdef SYS_WINNT
-# include <io.h>
-HANDLE ResolverEventHandle;
-#else
-int resolver_pipe_fd[2];  /* used to let the resolver process alert the parent process */
-#endif /* SYS_WINNT */
 
 /*
  * [Bug 467]: Some linux headers collide with CONFIG_PHONE and CONFIG_KEYS
@@ -76,16 +62,16 @@ int resolver_pipe_fd[2];  /* used to let the resolver process alert the parent p
  * "logconfig" building blocks
  */
 struct masks {
-       const char        *name;
-       unsigned long mask;
+       const char *    name;
+       unsigned long   mask;
 };
 
 static struct masks logcfg_class[] = {
-       { "clock",              NLOG_OCLOCK },
-       { "peer",               NLOG_OPEER },
-       { "sync",               NLOG_OSYNC },
-       { "sys",                NLOG_OSYS },
-       { (char *)0,    0 }
+       { "clock",      NLOG_OCLOCK },
+       { "peer",       NLOG_OPEER },
+       { "sync",       NLOG_OSYNC },
+       { "sys",        NLOG_OSYS },
+       { NULL,         0 }
 };
 
 static struct masks logcfg_item[] = {
@@ -102,7 +88,7 @@ static struct masks logcfg_item[] = {
        { "allsys",             (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OSYS },
        { "allsync",            (NLOG_INFO|NLOG_STATIST|NLOG_EVENT|NLOG_STATUS)<<NLOG_OSYNC },
        { "all",                NLOG_SYSMASK|NLOG_PEERMASK|NLOG_CLOCKMASK|NLOG_SYNCMASK },
-       { (char *)0,    0 }
+       { NULL,                 0 }
 };
 
 /* Limits */
@@ -117,27 +103,14 @@ static struct masks logcfg_item[] = {
 #define ISSPACE(c)     ((c) == ' ' || (c) == '\t')
 #define STREQ(a, b)    (*(a) == *(b) && strcmp((a), (b)) == 0)
 
-/*
- * File descriptor used by the resolver save routines, and temporary file
- * name.
- */
-int call_resolver = 1;         /* ntp-genkeys sets this to 0, for example */
-#ifndef SYS_WINNT
-static char res_file[20];      /* enough for /tmp/ntpXXXXXX\0 */
-#define RES_TEMPFILE   "/tmp/ntpXXXXXX"
-#else
-static char res_file[MAX_PATH];
-#endif /* SYS_WINNT */
-
 /*
  * Definitions of things either imported from or exported to outside
  */
 extern int yydebug;                    /* ntp_parser.c (.y) */
 int curr_include_level;                        /* The current include level */
 struct FILE_INFO *fp[MAXINCLUDELEVEL+1];
-FILE *res_fp;
 struct config_tree cfgt;               /* Parser output stored here */
-struct config_tree *cfg_tree_history = NULL;   /* History of configs */
+struct config_tree *cfg_tree_history;  /* History of configs */
 char   *sys_phone[MAXPHONE] = {NULL};  /* ACTS phone numbers */
 char   default_keysdir[] = NTP_KEYSDIR;
 char   *keysdir = default_keysdir;     /* crypto keys directory */
@@ -256,6 +229,7 @@ double *create_dval(double val);
 void destroy_restrict_node(struct restrict_node *my_node);
 static int is_sane_resolved_address(sockaddr_u *peeraddr, int hmode);
 static int get_correct_host_mode(int hmode);
+static int peerflag_bits(struct peer_node *);
 static void save_and_apply_config_tree(void);
 void getconfig(int, char **);
 #if !defined(SIM)
@@ -288,6 +262,15 @@ static void config_ntpdsim(struct config_tree *);
 static void config_ntpd(struct config_tree *);
 #endif
 
+#ifdef WORKER
+void peer_name_resolved(int, int, void *, const char *, const char *,
+                       const struct addrinfo *,
+                       const struct addrinfo *);
+void unpeer_name_resolved(int, int, void *, const char *, const char *,
+                         const struct addrinfo *,
+                         const struct addrinfo *);
+#endif
+
 enum gnn_type {
        t_UNK,          /* Unknown */
        t_REF,          /* Refclock */
@@ -311,11 +294,6 @@ static int getnetnum(const char *num,sockaddr_u *addr, int complain,
 static int get_multiple_netnums(const char *num, sockaddr_u *addr,
                                struct addrinfo **res, int complain,
                                enum gnn_type a_type);
-static void save_resolve(char *name, int no_needed, int type,
-                        int mode, int version, int minpoll, int maxpoll,
-                        u_int flags, int ttl, keyid_t keyid, u_char *keystr);
-static void abort_resolve(void);
-static void do_resolve_internal(void);
 
 
 
@@ -1708,13 +1686,7 @@ config_auth(
        struct config_tree *ptree
        )
 {
-       extern int      cache_type;     /* authkeys.c */
 #ifdef OPENSSL
-#ifndef NO_INTRES
-       u_char          digest[EVP_MAX_MD_SIZE];
-       u_int           digest_len;
-       EVP_MD_CTX      ctx;
-#endif
        struct attr_val *my_val;
        int             item;
 #endif
@@ -1809,39 +1781,6 @@ config_auth(
        if (ptree->auth.revoke)
                sys_revoke = ptree->auth.revoke;
 #endif /* OPENSSL */
-
-#ifndef NO_INTRES
-       /* find a keyid */
-       if (info_auth_keyid == 0)
-               req_keyid = 65535;
-       else
-               req_keyid = info_auth_keyid;
-
-       /* if doesn't exist, make up one at random */
-       if (authhavekey(req_keyid)) {
-               req_keytype = cache_type;
-#ifndef OPENSSL
-               req_hashlen = 16;
-#else  /* OPENSSL follows */
-               EVP_DigestInit(&ctx, EVP_get_digestbynid(req_keytype));
-               EVP_DigestFinal(&ctx, digest, &digest_len);
-               req_hashlen = digest_len;
-#endif
-       } else {
-               int     rankey;
-
-               rankey = ntp_random();
-               req_keytype = NID_md5;
-               req_hashlen = 16;
-               MD5auth_setkey(req_keyid, req_keytype,
-                   (u_char *)&rankey, sizeof(rankey));
-               authtrust(req_keyid, 1);
-       }
-
-       /* save keyid so we will accept config requests with it */
-       info_auth_keyid = req_keyid;
-#endif /* !NO_INTRES */
-
 }
 
 
@@ -3126,7 +3065,6 @@ config_vars(
        )
 {
        struct attr_val *curr_var;
-       FILE *new_file;
        int len;
 
        curr_var = queue_head(ptree->vars);
@@ -3159,20 +3097,9 @@ config_vars(
                        stats_config(STATS_PID_FILE, curr_var->value.s);
                        break;
                case T_Logfile:
-                       new_file = fopen(curr_var->value.s, "a");
-                       if (new_file != NULL) {
-                               NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
-                                   msyslog(LOG_NOTICE, "logging to file %s", curr_var->value.s);
-                               if (syslog_file != NULL &&
-                                   fileno(syslog_file) != fileno(new_file))
-                                       (void)fclose(syslog_file);
-
-                               syslog_file = new_file;
-                               syslogit = 0;
-                       }
-                       else
+                       if (-1 == change_logfile(curr_var->value.s, 0))
                                msyslog(LOG_ERR,
-                                       "Cannot open log file %s",
+                                       "Cannot open logfile %s: %m",
                                        curr_var->value.s);
                        break;
 
@@ -3278,12 +3205,13 @@ is_sane_resolved_address(
        return 1;
 }
 
+
 static int
 get_correct_host_mode(
-       int hmode
+       int token
        )
 {
-       switch (hmode) {
+       switch (token) {
            case T_Server:
            case T_Pool:
            case T_Manycastclient:
@@ -3300,166 +3228,229 @@ get_correct_host_mode(
        }
 }
 
-static void
-config_peers(
-       struct config_tree *ptree
+
+/*
+ * peerflag_bits()     get config_peers() peerflags value from a
+ *                     peer_node's queue of flag attr_val entries.
+ */
+static int
+peerflag_bits(
+       struct peer_node *pn
        )
 {
-       struct addrinfo *res, *res_bak;
-       sockaddr_u peeraddr;
-       struct peer_node *curr_peer;
-       struct attr_val *option;
-       int hmode;
        int peerflags;
-       int status;
-       int no_needed;
-       int i;
+       struct attr_val *option;
 
-       curr_peer = queue_head(ptree->peers);
-       while (curr_peer != NULL) {
-               /* Find the number of associations needed.
-                * If a pool coomand is specified, then sys_maxclock needed
-                * else, only one is needed
-                */
-               no_needed = (T_Pool == curr_peer->host_mode)
-                               ? sys_maxclock
-                               : 1;
+       /* translate peerflags options to bits */
+       peerflags = 0;
+       option = queue_head(pn->peerflags);
+       for (;  option != NULL; option = next_node(option))
+               switch (option->value.i) {
 
-               /* Find the correct host-mode */
-               hmode = get_correct_host_mode(curr_peer->host_mode);
-               NTP_INSIST(hmode != -1);
+               default:
+                       NTP_INSIST(0);
+                       break;
 
-               /* translate peerflags options to bits */
-               peerflags = 0;
-               option = queue_head(curr_peer->peerflags);
-               for (;  option != NULL; option = next_node(option))
-                       switch (option->value.i) {
+               case T_Autokey:
+                       peerflags |= FLAG_SKEY;
+                       break;
 
-                       default:
-                               NTP_INSIST(0);
-                               break;
+               case T_Burst:
+                       peerflags |= FLAG_BURST;
+                       break;
 
-                       case T_Autokey:
-                               peerflags |= FLAG_SKEY;
-                               break;
+               case T_Iburst:
+                       peerflags |= FLAG_IBURST;
+                       break;
 
-                       case T_Burst:
-                               peerflags |= FLAG_BURST;
-                               break;
+               case T_Noselect:
+                       peerflags |= FLAG_NOSELECT;
+                       break;
 
-                       case T_Iburst:
-                               peerflags |= FLAG_IBURST;
-                               break;
+               case T_Preempt:
+                       peerflags |= FLAG_PREEMPT;
+                       break;
 
-                       case T_Noselect:
-                               peerflags |= FLAG_NOSELECT;
-                               break;
+               case T_Prefer:
+                       peerflags |= FLAG_PREFER;
+                       break;
 
-                       case T_Preempt:
-                               peerflags |= FLAG_PREEMPT;
-                               break;
+               case T_True:
+                       peerflags |= FLAG_TRUE;
+                       break;
 
-                       case T_Prefer:
-                               peerflags |= FLAG_PREFER;
-                               break;
+               case T_Xleave:
+                       peerflags |= FLAG_XLEAVE;
+                       break;
+               }
 
-                       case T_True:
-                               peerflags |= FLAG_TRUE;
-                               break;
+       return peerflags;
+}
 
-                       case T_Xleave:
-                               peerflags |= FLAG_XLEAVE;
-                               break;
-                       }
 
-               /* Attempt to resolve the address */
-               ZERO_SOCK(&peeraddr);
-               AF(&peeraddr) = (u_short)curr_peer->addr->type;
+static void
+config_peers(
+       struct config_tree *ptree
+       )
+{
+       sockaddr_u peeraddr;
+       isc_netaddr_t   i_netaddr;
+       struct addrinfo hints;
+       struct peer_node *curr_peer;
+       int hmode;
+       int num_needed;
 
-               status = get_multiple_netnums(curr_peer->addr->address,
-                   &peeraddr, &res, 0, t_UNK);
+       for (curr_peer = queue_head(ptree->peers);
+            curr_peer != NULL;
+            curr_peer = next_node(curr_peer)) {
 
-#ifdef FORCE_DEFER_DNS
-               /* Hack for debugging Deferred DNS
-                * Pretend working names didn't work.
-                */
-               if (status == 1) {
-                       /* Deferring everything breaks refclocks. */
-                       memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
-                       if (!ISREFCLOCKADR(&peeraddr)) {
-                               status = 0;  /* force deferred DNS path */
-                               msyslog(LOG_INFO, "Forcing Deferred DNS for %s, %s",
-                                       curr_peer->addr->address, stoa(&peeraddr));
-                       } else {
-                               msyslog(LOG_INFO, "NOT Deferring DNS for %s, %s",
-                                       curr_peer->addr->address, stoa(&peeraddr));
-                       }
-               }
-#endif
+               /* Find the correct host-mode */
+               hmode = get_correct_host_mode(curr_peer->host_mode);
+               NTP_INSIST(hmode != -1);
 
-               /* I don't know why getnetnum would return -1.
-                * The old code had this test, so I guess it must be
-                * useful
+               /* Find the number of associations needed.
+                * If a pool coomand is specified, then sys_maxclock needed
+                * else, only one is needed
                 */
-               if (status == -1) {
-                       /* Do nothing, apparently we found an IPv6
-                        * address and can't do anything about it */
-               }
-               /* Check if name resolution failed. If yes, store the
-                * peer information in a file for asynchronous
-                * resolution later
+               num_needed = (T_Pool == curr_peer->host_mode)
+                               ? sys_maxclock
+                               : 1;
+
+               /*
+                * If we have a numeric address, we can safely use
+                * getaddrinfo in the mainline with it.  Otherwise
+                * hand it off to the blocking child.
                 */
-               else if (status != 1) {
-                       msyslog(LOG_INFO, "Deferring DNS for %s %d", curr_peer->addr->address, no_needed);
-                       save_resolve(curr_peer->addr->address,
-                                    no_needed,
-                                    curr_peer->addr->type,
-                                    hmode,
-                                    curr_peer->peerversion,
-                                    curr_peer->minpoll,
-                                    curr_peer->maxpoll,
-                                    peerflags,
-                                    curr_peer->ttl,
-                                    curr_peer->peerkey,
-                                    (u_char *)"*");
+               memset(&i_netaddr, 0, sizeof(i_netaddr));
+               i_netaddr.family = (u_short)curr_peer->addr->type;
+
+               if (1 == num_needed
+                   && is_ip_address(curr_peer->addr->address,
+                                    &i_netaddr)) {
+
+                       AF(&peeraddr) = (u_short)i_netaddr.family;
+                       SET_PORT(&peeraddr, NTP_PORT);
+                       if (AF_INET6 == i_netaddr.family)
+                               SET_ADDR6N(&peeraddr,
+                                          i_netaddr.type.in6);
+                       else
+                               SET_ADDR4N(&peeraddr,
+                                          i_netaddr.type.in.s_addr);
+
+                       if (is_sane_resolved_address(&peeraddr,
+                           curr_peer->host_mode))
+                               peer_config(&peeraddr,
+                                   NULL,
+                                   hmode,
+                                   curr_peer->peerversion,
+                                   curr_peer->minpoll,
+                                   curr_peer->maxpoll,
+                                   peerflag_bits(curr_peer),
+                                   curr_peer->ttl,
+                                   curr_peer->peerkey,
+                                   (u_char *)"*");
+               } else {
+                       /* we have a hostname to resolve */
+#ifdef WORKER
+                       memset(&hints, 0, sizeof(hints));
+                       hints.ai_family = (u_short)curr_peer->addr->type;
+                       hints.ai_socktype = SOCK_DGRAM;
+                       hints.ai_protocol = IPPROTO_UDP;
+                       getaddrinfo_sometime(curr_peer->addr->address, "ntp",
+                                            &hints, &peer_name_resolved, 
+                                            (void *)curr_peer);
+#else  /* !WORKER follows */
+                       msyslog(LOG_ERR,
+                               "hostname %s can not be used, please use address\n",
+                               curr_peer->addr->address);
+#endif
                }
-               /* Yippie!! Name resolution has succeeded!!!
-                * Now we can proceed to some more sanity checks on
-                * the resolved address before we start to configure
-                * the peer
-                */
-               else {
-                       res_bak = res;
+       }
+}
 
-                       /*
-                        * Loop to configure the desired number of
-                        * associations
-                        */
-                       for (i = 0; (i < no_needed) && res; res =
-                           res->ai_next) {
-                               ++i;
-                               memcpy(&peeraddr, res->ai_addr,
-                                   res->ai_addrlen);
-                               if (is_sane_resolved_address(
-                                       &peeraddr,
-                                       curr_peer->host_mode))
-
-                                       peer_config(&peeraddr,
-                                           NULL,
-                                           hmode,
-                                           curr_peer->peerversion,
-                                           curr_peer->minpoll,
-                                           curr_peer->maxpoll,
-                                           peerflags,
-                                           curr_peer->ttl,
-                                           curr_peer->peerkey,
-                                           (u_char *)"*");
+
+/*
+ * peer_name_resolved()
+ *
+ * Callback invoked when config_peers()'s DNS lookup completes.
+ */
+#ifdef WORKER
+void
+peer_name_resolved(
+       int                     rescode,
+       int                     gai_errno,
+       void *                  context,
+       const char *            name,
+       const char *            service,
+       const struct addrinfo * hints,
+       const struct addrinfo * res
+       )
+{
+       sockaddr_u              peeraddr;
+       struct peer_node *      curr_peer;
+       int                     num_needed;
+       int                     hmode;
+       int                     i;
+       int                     af;
+       const char *            fam_spec;
+
+       curr_peer = context;
+
+       DPRINTF(1, ("peer_name_resolved(%s) rescode %d\n", name, rescode));
+
+       if (rescode) {
+#ifndef IGNORE_DNS_ERRORS
+               msyslog(LOG_ERR,
+                       "giving up resolving host %s: %s (%d)",
+                       name, gai_strerror(rescode), rescode);
+#else  /* IGNORE_DNS_ERRORS follows */
+               getaddrinfo_sometime(name, service, hints,
+                                    &peer_name_resolved, context);
+#endif
+               return;
+       }
+
+       hmode = get_correct_host_mode(curr_peer->host_mode);
+       NTP_INSIST(hmode != -1);
+       num_needed = (T_Pool == curr_peer->host_mode) 
+                       ? sys_maxclock 
+                       : 1;
+
+       /* Loop to configure the desired number of associations */
+       for (i = 0; 
+            res != NULL && i < num_needed; 
+            res = res->ai_next) {
+
+               memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
+
+               if (is_sane_resolved_address(&peeraddr,
+                                            curr_peer->host_mode)) {
+                       i++;
+                       NLOG(NLOG_SYSINFO) {
+                               af = curr_peer->addr->type;
+                               fam_spec = (AF_INET6 == af)
+                                              ? "(AAAA) "
+                                              : (AF_INET == af)
+                                                    ? "(A) "
+                                                    : "";
+                               msyslog(LOG_INFO, "DNS %s %s-> %s",
+                                       name, fam_spec,
+                                       stoa(&peeraddr));
                        }
-                       freeaddrinfo(res_bak);
+                       peer_config(&peeraddr,
+                               NULL,
+                               hmode,
+                               curr_peer->peerversion,
+                               curr_peer->minpoll,
+                               curr_peer->maxpoll,
+                               peerflag_bits(curr_peer),
+                               curr_peer->ttl,
+                               curr_peer->peerkey,
+                               (u_char *)"*");
                }
-               curr_peer = next_node(curr_peer);
        }
 }
+#endif /* WORKER */
 
 
 #ifdef FREE_CFG_T
@@ -3484,11 +3475,11 @@ config_unpeers(
        struct config_tree *ptree
        )
 {
-       struct addrinfo *res, *res_bak;
        sockaddr_u peeraddr;
+       struct addrinfo         hints;
+       isc_netaddr_t           i_netaddr;
        struct unpeer_node *curr_unpeer;
        struct peer *peer;
-       int status;
        int found;
 
        for (curr_unpeer = queue_head(ptree->unpeers);
@@ -3509,63 +3500,128 @@ config_unpeers(
                        continue;
                }
 
-               /* Attempt to resolve the name or address */
-               ZERO_SOCK(&peeraddr);
-               AF(&peeraddr) = (u_short)curr_unpeer->addr->type;
+               /*
+                * If we have a numeric address, we can safely use
+                * getaddrinfo in the mainline with it.  Otherwise
+                * hand it off to the blocking child.
+                */
+               memset(&i_netaddr, 0, sizeof(i_netaddr));
+               i_netaddr.family = (u_short)curr_unpeer->addr->type;
 
-               status = get_multiple_netnums(
-                       curr_unpeer->addr->address, &peeraddr, &res, 0,
-                       t_UNK);
+               if (is_ip_address(curr_unpeer->addr->address, &i_netaddr)) {
 
-               /* I don't know why getnetnum would return -1.
-                * The old code had this test, so I guess it must be
-                * useful
-                */
-               if (status == -1) {
-                       /* Do nothing, apparently we found an IPv6
-                        * address and can't do anything about it */
-               }
-               /* Check if name resolution failed. If yes, throw
-                * up our hands.
-                */
-               else if (status != 1) {
-                       /* Do nothing */
+                       AF(&peeraddr) = (u_short)i_netaddr.family;
+                       if (AF_INET6 == i_netaddr.family)
+                               SET_ADDR6N(&peeraddr,
+                                          i_netaddr.type.in6);
+                       else
+                               SET_ADDR4N(&peeraddr,
+                                          i_netaddr.type.in.s_addr);
+
+                       found = 0;
+                       peer = NULL;
+
+                       DPRINTF(1, ("searching for %s\n", stoa(&peeraddr)));
+
+                       do {
+                               peer = findexistingpeer(&peeraddr, peer, -1);
+                               if (NULL != peer && (FLAG_CONFIG & peer->flags))
+                                       found = 1;
+                       } while (!found && NULL != peer);
+
+                       if (found) {
+                               msyslog(LOG_INFO, "unpeered %s",
+                                       stoa(&peeraddr));
+                               peer_clear(peer, "GONE");
+                               unpeer(peer);
+                       }
+               } else {
+                       /* we have a hostname to resolve */
+#ifdef WORKER
+                       memset(&hints, 0, sizeof(hints));
+                       hints.ai_family = (u_short)curr_unpeer->addr->type;
+                       hints.ai_socktype = SOCK_DGRAM;
+                       hints.ai_protocol = IPPROTO_UDP;
+                       getaddrinfo_sometime(curr_unpeer->addr->address, "ntp",
+                                            &hints, &unpeer_name_resolved, 
+                                            (void *)curr_unpeer);
+#else  /* !WORKER follows */
+                       msyslog(LOG_ERR,
+                               "hostname %s can not be used, please use address\n",
+                               curr_unpeer->addr->address);
+#endif
                }
-               /* Yippie!! Name resolution has succeeded!!!
-                */
-               else {
-                       res_bak = res;
+       }
+}
 
-                       /*
-                        * Loop through the addresses found
-                        */
-                       while (res) {
-                               memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
 
-                               found = 0;
-                               peer = NULL;
+/*
+ * unpeer_name_resolved()
+ *
+ * Callback invoked when config_unpeers()'s DNS lookup completes.
+ */
+#ifdef WORKER
+void
+unpeer_name_resolved(
+       int                     rescode,
+       int                     gai_errno,
+       void *                  context,
+       const char *            name,
+       const char *            service,
+       const struct addrinfo * hints,
+       const struct addrinfo * res
+       )
+{
+       sockaddr_u              peeraddr;
+       struct unpeer_node *    curr_unpeer;
+       struct peer *           peer;
+       int                     found;
+       int                     af;
+       const char *            fam_spec;
 
-                               DPRINTF(1, ("searching for %s\n", stoa(&peeraddr)));
+       DPRINTF(1, ("unpeer_name_resolved(%s) rescode %d\n", name, rescode));
 
-                               while (!found) {
-                                       peer = findexistingpeer(&peeraddr, peer, -1);
-                                       if (!peer)
-                                               break;
-                                       if (peer->flags & FLAG_CONFIG)
-                                               found = 1;
-                               }
+       curr_unpeer = context;
 
-                               if (found) {
-                                       peer_clear(peer, "GONE");
-                                       unpeer(peer);
-                               }
+       if (rescode)
+               msyslog(LOG_ERR, "giving up resolving unpeer %s: %s (%d)", 
+                       name, gai_strerror(rescode), rescode);
+       else {
+               /*
+                * Loop through the addresses found
+                */
+               while (res) {
+                       found = 0;
+                       peer = NULL;
 
-                               res = res->ai_next;
+                       memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
+                       DPRINTF(1, ("searching for peer %s\n", stoa(&peeraddr)));
+
+                       do {
+                               peer = findexistingpeer(&peeraddr, peer, -1);
+                               if (NULL != peer && (FLAG_CONFIG & peer->flags))
+                                       found = 1;
+                       } while (!found && NULL != peer);
+
+                       if (found) {
+                               af = curr_unpeer->addr->type;
+                               fam_spec = (AF_INET6 == af)
+                                              ? "(AAAA) "
+                                              : (AF_INET == af)
+                                                    ? "(A) "
+                                                    : "";
+                               msyslog(LOG_INFO, "unpeered %s %s-> %s",
+                                       name, fam_spec,
+                                       stoa(&peeraddr));
+                               peer_clear(peer, "GONE");
+                               unpeer(peer);
                        }
-                       freeaddrinfo(res_bak);
+
+                       res = res->ai_next;
                }
        }
 }
+#endif /* WORKER */
 
 
 #ifdef FREE_CFG_T
@@ -3703,6 +3759,19 @@ config_ntpd(
        config_unpeers(ptree);
        config_fudge(ptree);
        config_qos(ptree);
+
+#ifdef TEST_BLOCKING_WORKER
+       {
+               struct addrinfo hints;
+
+               memset(&hints, 0, sizeof(hints));
+               hints.ai_socktype = SOCK_STREAM;
+               hints.ai_protocol = IPPROTO_TCP;
+               getaddrinfo_sometime("www.cnn.com", "ntp", &hints, gai_test_callback, (void *)1);
+               hints.ai_family = AF_INET6;
+               getaddrinfo_sometime("ipv6.google.com", "ntp", &hints, gai_test_callback, (void *)0x600);
+       }
+#endif
 }
 #endif /* !SIM */
 
@@ -3791,10 +3860,7 @@ getconfig(
                exit(1);
        }
        alt_config_file = alt_config_file_storage;
-
 #endif /* SYS_WINNT */
-       res_fp = NULL;
-       ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */
 
        /*
         * install a non default variable with this daemon version
@@ -3880,19 +3946,6 @@ getconfig(
        if (config_netinfo)
                free_netinfo_config(config_netinfo);
 #endif /* HAVE_NETINFO */
-
-       /*
-       printf("getconfig: res_fp <%p> call_resolver: %d", res_fp, call_resolver);
-       */
-
-       if (res_fp != NULL) {
-               if (call_resolver) {
-                       /*
-                        * Need name resolution
-                        */
-                       do_resolve_internal();
-               }
-       }
 }
 
 
@@ -4362,286 +4415,3 @@ get_multiple_netnums(
 }
 
 
-#if !defined(VMS) && !defined(SYS_WINNT)
-/*
- * catchchild - receive the resolver's exit status
- */
-static RETSIGTYPE
-catchchild(
-       int sig
-       )
-{
-       /*
-        * We only start up one child, and if we're here
-        * it should have already exited.  Hence the following
-        * shouldn't hang.  If it does, please tell me.
-        */
-#if !defined (SYS_WINNT) && !defined(SYS_VXWORKS)
-       (void) wait(0);
-#endif /* SYS_WINNT  && VXWORKS*/
-}
-#endif /* VMS */
-
-
-/*
- * save_resolve - save configuration info into a file for later name resolution
- */
-static void
-save_resolve(
-       char *name,
-       int no_needed,
-       int type,
-       int mode,
-       int version,
-       int minpoll,
-       int maxpoll,
-       u_int flags,
-       int ttl,
-       keyid_t keyid,
-       u_char *keystr
-       )
-{
-#ifndef SYS_VXWORKS
-       if (res_fp == NULL) {
-#ifndef SYS_WINNT
-               strcpy(res_file, RES_TEMPFILE);
-#else
-               int len;
-
-               /* no /tmp directory under NT */
-               if (!GetTempPath(sizeof res_file, res_file)) {
-                       msyslog(LOG_ERR, "can not get temp dir: %m");
-                       exit(1);
-               }
-               
-               len = strlen(res_file);
-               if (sizeof res_file < len + sizeof "ntpdXXXXXX") {
-                       msyslog(LOG_ERR,
-                               "temporary directory path %s too long",
-                               res_file);
-                       exit(1);
-               }
-
-               memmove(res_file + len, "ntpdXXXXXX",
-                       sizeof "ntpdXXXXXX");
-#endif /* SYS_WINNT */
-#ifdef HAVE_MKSTEMP
-               {
-                       int fd;
-
-                       res_fp = NULL;
-                       if ((fd = mkstemp(res_file)) != -1)
-                               res_fp = fdopen(fd, "r+");
-               }
-#else
-               mktemp(res_file);
-               res_fp = fopen(res_file, "w");
-#endif
-               if (res_fp == NULL) {
-                       msyslog(LOG_ERR, "open failed for %s: %m", res_file);
-                       return;
-               }
-       }
-#ifdef DEBUG
-       if (debug) {
-               printf("resolving %s\n", name);
-       }
-#endif
-
-       (void)fprintf(res_fp, "%s %d %d %d %d %d %d %d %d %u %s\n",
-               name, no_needed, type,
-               mode, version, minpoll, maxpoll, flags, ttl, keyid, keystr);
-#ifdef DEBUG
-       if (debug > 1)
-               printf("config: %s %d %d %d %d %d %d %x %d %u %s\n",
-                       name, no_needed, type,
-                       mode, version, minpoll, maxpoll, flags,
-                       ttl, keyid, keystr);
-#endif
-
-#else  /* SYS_VXWORKS */
-       /* save resolve info to a struct */
-#endif /* SYS_VXWORKS */
-}
-
-
-/*
- * abort_resolve - terminate the resolver stuff and delete the file
- */
-static void
-abort_resolve(void)
-{
-       /*
-        * In an ideal world we would might reread the file and
-        * log the hosts which aren't getting configured.  Since
-        * this is too much work, however, just close and delete
-        * the temp file.
-        */
-       if (res_fp != NULL)
-               (void) fclose(res_fp);
-       res_fp = NULL;
-
-#ifndef SYS_VXWORKS            /* we don't open the file to begin with */
-#if !defined(VMS)
-       if (unlink(res_file))
-               msyslog(LOG_WARNING, 
-                       "Unable to remove temporary resolver file %s, %m",
-                       res_file);
-#else
-       (void) delete(res_file);
-#endif /* VMS */
-#endif /* SYS_VXWORKS */
-}
-
-
-/*
- * do_resolve_internal - start up the resolver function (not program)
- *
- * On VMS, VxWorks, and Unix-like systems lacking fork(), this routine
- * will simply refuse to resolve anything.
- *
- * Possible implementation: keep `res_file' in memory, do async
- * name resolution via QIO, update from within completion AST.
- * I'm unlikely to find the time for doing this, though. -wjm
- */
-static void
-do_resolve_internal(void)
-{
-#ifndef SYS_WINNT
-       int i;
-#endif
-
-       if (res_fp == NULL) {
-               /* belch */
-               msyslog(LOG_ERR,
-                       "do_resolve_internal: Fatal: res_fp == NULL");
-               exit(1);
-       }
-
-       /* we are done with this now */
-       (void) fclose(res_fp);
-       res_fp = NULL;
-
-#ifndef NO_INTRES
-       req_file = res_file;    /* set up pointer to res file */
-#ifndef SYS_WINNT
-       (void) signal_no_reset(SIGCHLD, catchchild);
-
-       /* the parent process will write to the pipe
-        * in order to wake up to child process
-        * which may be waiting in a select() call
-        * on the read fd */
-       if (pipe(resolver_pipe_fd) < 0) {
-               msyslog(LOG_ERR,
-                       "unable to open resolver pipe");
-               exit(1);
-       }
-
-       i = fork();
-       /* Shouldn't the code below be re-ordered?
-        * I.e. first check if the fork() returned an error, then
-        * check whether we're parent or child.
-        *     Martin Burnicki
-        */
-       if (i == 0) {
-               /*
-                * this used to close everything
-                * I don't think this is necessary
-                */
-               /*
-                * To the unknown commenter above:
-                * Well, I think it's better to clean up
-                * after oneself. I have had problems with
-                * refclock-io when intres was running - things
-                * where fine again when ntpintres was gone.
-                * So some systems react erratic at least.
-                *
-                *                      Frank Kardel
-                *
-                * 94-11-16:
-                * Further debugging has proven that the above is
-                * absolutely harmful. The internal resolver
-                * is still in the SIGIO process group and the lingering
-                * async io information causes it to process requests from
-                * all file decriptor causing a race between the NTP daemon
-                * and the resolver. which then eats data when it wins 8-(.
-                * It is absolutly necessary to kill any IO associations
-                * shared with the NTP daemon.
-                *
-                * We also block SIGIO (currently no ports means to
-                * disable the signal handle for IO).
-                *
-                * Thanks to wgstuken@informatik.uni-erlangen.de to notice
-                * that it is the ntp-resolver child running into trouble.
-                *
-                * THUS:
-                */
-
-               /*
-               msyslog(LOG_INFO, "do_resolve_internal: pre-closelog");
-               */
-               closelog();
-               kill_asyncio(0);
-
-               (void) signal_no_reset(SIGCHLD, SIG_DFL);
-
-               init_logging("ntpd_intres", 0);
-               setup_logfile();
-               /*
-               msyslog(LOG_INFO, "do_resolve_internal: post-closelog");
-               */
-
-               ntp_intres();
-
-               /*
-                * If we got here, the intres code screwed up.
-                * Print something so we don't die without complaint
-                */
-               msyslog(LOG_ERR, "call to ntp_intres lost");
-               abort_resolve();
-               exit(1);
-       }
-       if (i == -1) {
-               msyslog(LOG_ERR, "fork() failed, can't start ntp_intres: %m");
-               (void) signal_no_reset(SIGCHLD, SIG_DFL);
-               abort_resolve();
-       } else
-               /* This is the parent process who will write to the pipe,
-                * so we close the read fd */
-               close(resolver_pipe_fd[0]);
-#else /* SYS_WINNT */
-       {
-               /* NT's equivalent of fork() is _spawn(), but the start point
-                * of the new process is an executable filename rather than
-                * a function name as desired here.
-                */
-               unsigned thread_id;
-               uintptr_t res_thd_handle;
-
-               fflush(stdout);
-               ResolverEventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
-               if (ResolverEventHandle == NULL) {
-                       msyslog(LOG_ERR, "Unable to create resolver event object, can't start ntp_intres");
-                       abort_resolve();
-               }
-               res_thd_handle = _beginthreadex(
-                       NULL,                   /* no security attributes       */
-                       0,                      /* use default stack size       */
-                       ntp_intres_thread,      /* thread function              */
-                       NULL,                   /* argument to thread function  */
-                       0,                      /* use default creation flags   */
-                       &thread_id);            /* receives thread identifier   */
-               if (!res_thd_handle) {
-                       msyslog(LOG_ERR, "_beginthreadex ntp_intres_thread failed %m");
-                       CloseHandle(ResolverEventHandle);
-                       ResolverEventHandle = NULL;
-                       abort_resolve();
-               }
-       }
-#endif /* SYS_WINNT */
-#else /* NO_INTRES follows */
-       msyslog(LOG_ERR,
-               "Deferred DNS not implemented - use numeric addresses");
-       abort_resolve();
-#endif
-}
index 7a32ddc3840a7edc82a58335f809b6f287d25760..43a68fc77c746d15fd5481326e08577cc20f6443 100644 (file)
@@ -770,7 +770,6 @@ process_control(
                res_authenticate = 1;
                res_keyid = ntohl(*(u_int32 *)((u_char *)pkt +
                                               properlen));
-
                DPRINTF(3, ("recv_len %d, properlen %d, wants auth with keyid %08x, MAC length=%d\n",
                            rbufp->recv_length, properlen, res_keyid,
                            maclen));
@@ -780,11 +779,11 @@ process_control(
                else if (authdecrypt(res_keyid, (u_int32 *)pkt,
                                     rbufp->recv_length - maclen,
                                     maclen)) {
-                       DPRINTF(3, ("authenticated okay\n"));
                        res_authokay = 1;
+                       DPRINTF(3, ("authenticated okay\n"));
                } else {
-                       DPRINTF(3, ("authentication failed\n"));
                        res_keyid = 0;
+                       DPRINTF(3, ("authentication failed\n"));
                }
        }
 
index fb21529be56b0f74427d82f9718a7cc857688ed7..be55b429a6ab3e12d9a965b8bf59d6bafc0d15d7 100644 (file)
@@ -3,14 +3,15 @@
  * This file contains the data structures used by the ntp configuration
  * code and the discrete event simulator.
  *
- * Written By: Sachin Kamboj
- *             University of Delaware
- *             Newark, DE 19711
+ * Written By: Sachin Kamboj
+ *             University of Delaware
+ *             Newark, DE 19711
  * Copyright (c) 2006
  */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
 
-
-#include <stdlib.h>    /* Needed for malloc */
 #include "ntp_data_structures.h"
 #include "ntp_stdlib.h"
 
  */
 
 
-queue *create_priority_queue(int (*get_order)(void *, void *))
+queue *debug_create_priority_queue(
+       int (*get_order)(void *, void *) 
+#ifdef _CRTDBG_MAP_ALLOC
+       , const char *sourcefile
+       , int line_num
+#endif 
+       )
 {
-    queue *my_queue = (queue *) emalloc(sizeof(queue));
-    my_queue->get_order = get_order;
-    my_queue->front = NULL;
-    my_queue->no_of_elements = 0;
-    return my_queue;
+       queue *my_queue;
+
+#ifndef _CRTDBG_MAP_ALLOC
+       my_queue = emalloc(sizeof(queue));
+#else
+       /* preserve original callsite __FILE__ and __LINE__ for leak report */
+       my_queue = debug_erealloc(NULL, sizeof(queue), sourcefile, line_num);
+#endif
+       my_queue->get_order = get_order;
+       my_queue->front = NULL;
+       my_queue->no_of_elements = 0;
+
+       return my_queue;
 }
 
 
@@ -36,7 +51,9 @@ queue *create_priority_queue(int (*get_order)(void *, void *))
  * all the allocated resources in the process 
  */
 
-void destroy_queue(queue *my_queue)
+void destroy_queue(
+       queue *my_queue
+       )
 {
     node *temp = NULL;
 
@@ -57,18 +74,35 @@ void destroy_queue(queue *my_queue)
  * bytes plus the number of bytes needed for bookkeeping
  */
 
-void *get_node(size_t size)
+void *debug_get_node(
+       size_t          size
+#ifdef _CRTDBG_MAP_ALLOC
+       , const char *  sourcefile
+       , int           line_num
+#endif
+       )
 {
-    node *new_node = emalloc(sizeof(*new_node) + size);
-    new_node->node_next = NULL; 
-    return new_node + 1;
+       node *new_node;
+
+#ifndef _CRTDBG_MAP_ALLOC
+       new_node = emalloc(sizeof(*new_node) + size);
+#else
+       new_node = debug_erealloc(NULL, sizeof(*new_node) + size,
+                                 sourcefile, line_num);
+#endif
+       new_node->node_next = NULL; 
+
+       return new_node + 1;
 }
 
 /* Define a function to free the allocated memory for a queue node */
-void free_node(void *my_node)
+void free_node(
+       void *my_node
+       )
 {
-    node *old_node = my_node;
-    free(old_node - 1);
+       node *old_node = my_node;
+
+       free(old_node - 1);
 }
 
 
@@ -90,9 +124,11 @@ next_node(
 
 
 /* Define a function to check if the queue is empty. */
-int empty(queue *my_queue)
+int empty(
+       queue *my_queue
+       )
 {
-    return (!my_queue || !my_queue->front);
+       return (!my_queue || !my_queue->front);
 }
 
 
@@ -112,55 +148,63 @@ queue_head(
  * The element is added according to its priority - 
  * relative priority is given by the get_order function
  */
-queue *enqueue(queue *my_queue, void *my_node)
+queue *enqueue(
+       queue * my_queue,
+       void *  my_node
+       )
 {
-    node *new_node = ((node *) my_node) - 1;
-    node *i = NULL;
-    node *j = my_queue->front;
-
-    while (j != NULL && ((*my_queue->get_order)(new_node + 1, j + 1) > 0)) {
-        i = j;
-        j = j->node_next;
-    }
-    
-    if (i == NULL) {       /* Insert at beginning of the queue */
-        new_node->node_next = my_queue->front;
-        my_queue->front = new_node;
-    }
-    else {                /* Insert Elsewhere, including the end */
-        new_node->node_next = i->node_next;
-        i->node_next = new_node;
-    }
-
-    ++my_queue->no_of_elements;    
-    return my_queue;
+       node *new_node = (node *)my_node - 1;
+       node *i = NULL;
+       node *j = my_queue->front;
+
+       while (j != NULL && 
+              (*my_queue->get_order)(new_node + 1, j + 1) > 0) {
+               i = j;
+               j = j->node_next;
+       }
+
+       if (i == NULL) {        /* Insert at beginning of the queue */
+               new_node->node_next = my_queue->front;
+               my_queue->front = new_node;
+       } else {                /* Insert Elsewhere, including the end */
+               new_node->node_next = i->node_next;
+               i->node_next = new_node;
+       }
+
+       ++my_queue->no_of_elements;    
+       return my_queue;
 }
 
 
 /* Define a function to dequeue the first element from the priority
  * queue and return it
  */
-
-void *dequeue(queue *my_queue)
+void *dequeue(
+       queue *my_queue
+       )
 {
-    node *my_node = my_queue->front;
-    if (my_node != NULL) {
-        my_queue->front = my_node->node_next;
-        --my_queue->no_of_elements;    
-        return (void *)(my_node + 1);
-    }
-    else
-        return NULL;
+       node *my_node = my_queue->front;
+
+       if (my_node != NULL) {
+               my_queue->front = my_node->node_next;
+               --my_queue->no_of_elements;    
+               return my_node + 1;
+       } else
+               return NULL;
 }
 
+
 /* Define a function that returns the number of elements in the 
  * priority queue
  */
-int get_no_of_elements(queue *my_queue)
+int get_no_of_elements(
+       queue *my_queue
+       )
 {
-    return my_queue->no_of_elements;
+       return my_queue->no_of_elements;
 }
 
+
 /* Define a function to append a queue onto another.
  * Note: there is a faster way (O(1) as opposed to O(n))
  * to do this for simple (FIFO) queues, but we can't rely on
@@ -170,14 +214,17 @@ int get_no_of_elements(queue *my_queue)
  * out to be a bottleneck, I will consider replacing the 
  * current implementation with a binomial or fibonacci heap.
  */
-
-void append_queue(queue *q1, queue *q2) 
+void append_queue(
+       queue *q1,
+       queue *q2
+       ) 
 {
-    while (!empty(q2))
-        enqueue(q1, dequeue(q2));
-    destroy_queue(q2);
+       while (!empty(q2))
+               enqueue(q1, dequeue(q2));
+       destroy_queue(q2);
 }
 
+
 /* FIFO Queue
  * ----------
  * Use the priority queue to create a traditional FIFO queue.
@@ -187,13 +234,7 @@ void append_queue(queue *q1, queue *q2)
 /* C is not Lisp and does not allow anonymous lambda functions :-(. 
  * So define a get_fifo_order function here
  */
-
 int get_fifo_order(void *el1, void *el2)
-{   return 1;
-}
-
-/* Define a function to create a FIFO queue */
-
-queue *create_queue()
-{    return create_priority_queue(get_fifo_order);
+{
+       return 1;
 }
index a3c66117ddc9577ca21359cf6248d82d614a5d06..df30a3e0667e61051545bad26230aa5b7b4c608a 100644 (file)
@@ -1,28 +1,56 @@
 /*
- * ripped off from ../ntpres/ntpres.c by Greg Troxel 4/2/92
- * routine callable from ntpd, rather than separate program
- * also, key info passed in via a global, so no key file needed.
- */
-
-/*
- * ntpres - process configuration entries which require use of the resolver
+ * ntp_intres.c - Implements a generic blocking worker child or thread,
+ *               initially to provide a nonblocking solution for DNS
+ *               name to address lookups available with getaddrinfo().
+ *
+ * This is a new implementation as of 2009 sharing the filename and
+ * very little else with the prior implementation, which used a
+ * temporary file to receive a single set of requests from the parent,
+ * and a NTP mode 7 authenticated request to push back responses.
+ *
+ * A primary goal in rewriting this code was the need to support the
+ * pool configuration directive's requirement to retrieve multiple
+ * addresses resolving a single name, which has previously been
+ * satisfied with blocking resolver calls from the ntpd mainline code.
+ *
+ * A secondary goal is to provide a generic mechanism for other
+ * blocking operations to be delegated to a worker using a common
+ * model for both Unix and Windows ntpd.  ntp_worker.c, work_fork.c,
+ * and work_thread.c implement the generic mechanism.  This file
+ * implements the two current consumers, getaddrinfo_sometime() and the
+ * presently unused getnameinfo_sometime().
+ *
+ * Both routines deliver results to a callback and manage memory
+ * allocation, meaning there is no freeaddrinfo_sometime().
+ *
+ * The initial implementation for Unix uses a pair of unidirectional
+ * pipes, one each for requests and responses, connecting the forked
+ * blocking child worker with the ntpd mainline.  The threaded code
+ * uses arrays of pointers to queue requests and responses.
+ *
+ * Memory is managed differently for a child process, which mallocs
+ * request buffers to read from the pipe into, whereas the threaded
+ * code mallocs a copy of the request to hand off to the worker via
+ * the queueing array.  The resulting request buffer is free()d by
+ * platform-independent code.  A wrinkle is the request needs to be
+ * available to the requestor during response processing.
+ *
+ * Response memory allocation is also platform-dependent.  With a
+ * separate process and pipes, the response is free()d after being
+ * written to the pipe.  With threads, the same memory is handed
+ * over and the requestor frees it after processing is completed.
  *
- * This is meant to be run by ntpd on the fly.  It is not guaranteed
- * to work properly if run by hand.  This is actually a quick hack to
- * stave off violence from people who hate using numbers in the
- * configuration file (at least I hope the rest of the daemon is
- * better than this).  Also might provide some ideas about how one
- * might go about autoconfiguring an NTP distribution network.
+ * The code should be generalized to support threads on Unix using
+ * much of the same code used for Windows initially.
  *
  */
-
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 
-#include "ntp_intres.h"
+#include "ntp_workimpl.h"
 
-#ifndef NO_INTRES
+#ifdef WORKER
 
 #include <stdio.h>
 #include <ctype.h>
 #  include <netdb.h>
 # endif
 # include <resolv.h>
+# ifdef RES_TIMEOUT
+#  undef RES_TIMEOUT   /* resolv.h has one, we want ours */
+# endif
 #endif
 
-#ifdef RES_TIMEOUT
-#undef RES_TIMEOUT     /* resolv.h has one, we want ours */
-#endif
-
-#include "ntp_machine.h"
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_request.h"
 #include "ntp_stdlib.h"
+#include "ntp_malloc.h"
 #include "ntp_syslog.h"
-#include "ntp_config.h"
-
-#include <isc/net.h>
-#include <isc/result.h>
-
-#define        STREQ(a, b)     (*(a) == *(b) && strcmp((a), (b)) == 0)
-
-/*
- * Each item we are to resolve and configure gets one of these
- * structures defined for it.
- */
-struct conf_entry {
-       struct conf_entry *ce_next;
-       char *ce_name;                  /* name to resolve */
-       struct conf_peer ce_config;     /* config info for peer */
-       int no_needed;                  /* number of addresses needed (pool) */
-       /*  no_needed isn't used yet: It's needed to fix bug-975 */
-       int type;                       /* -4 and -6 flags */
-       sockaddr_u peer_store;          /* address info for both fams */
-};
-#define        ce_peeraddr     ce_config.peeraddr
-#define        ce_peeraddr6    ce_config.peeraddr6
-#define        ce_hmode        ce_config.hmode
-#define        ce_version      ce_config.version
-#define ce_minpoll     ce_config.minpoll
-#define ce_maxpoll     ce_config.maxpoll
-#define        ce_flags        ce_config.flags
-#define ce_ttl         ce_config.ttl
-#define        ce_keyid        ce_config.keyid
-#define ce_keystr      ce_config.keystr
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_assert.h"
+#include "ntp_unixtime.h"
+#include "ntp_intres.h"
 
-/*
- * confentries is a pointer to the list of configuration entries
- * we have left to do.
- */
-static struct conf_entry *confentries = NULL;
 
 /*
- * We take an interrupt every thirty seconds, at which time we decrement
- * config_timer and resolve_timer.  The former is set to 2, so we retry
- * unsucessful reconfigurations every minute.  The latter is set to
- * an exponentially increasing value which starts at 2 and increases to
- * 32.  When this expires we retry failed name resolutions.
+ * Following are implementations of getaddrinfo_sometime() and
+ * getnameinfo_sometime().  Each is implemented in three routines:
+ *
+ * getaddrinfo_sometime()              getnameinfo_sometime()
+ * blocking_getaddrinfo()              blocking_getnameinfo()
+ * getaddrinfo_sometime_complete()     getnameinfo_sometime_complete()
  *
- * We sleep SLEEPTIME seconds before doing anything, to give the server
- * time to arrange itself.
+ * The first runs in the parent and marshalls (or serializes) request
+ * parameters into a request blob which is processed in the child by
+ * the second routine, blocking_*(), which serializes the results into
+ * a response blob unpacked by the third routine, *_complete(), which
+ * calls the callback routine provided with the request and frees
+ * _request_ memory allocated by the first routine.  Response memory
+ * is managed by the code which calls the *_complete routines.
  */
-#define        MINRESOLVE      2
-#define        MAXRESOLVE      32
-#define        CONFIG_TIME     2
-#define        ALARM_TIME      30
-#define        SLEEPTIME       2
 
-static volatile int config_timer = 0;
-static volatile int resolve_timer = 0;
+#define        INITIAL_DNS_RETRY       2       /* seconds between queries */
+
+typedef struct blocking_gai_req_tag {
+       size_t                  octets;
+       time_t                  scheduled;
+       time_t                  earliest;
+       struct addrinfo         hints;
+       int                     retry;
+       gai_sometime_callback   callback;
+       void *                  context;
+       size_t                  nodesize;
+       size_t                  servsize;
+} blocking_gai_req;
+
+typedef struct blocking_gai_resp_tag {
+       size_t                  octets;
+       int                     retcode;
+       int                     gai_errno; /* for EAI_SYSTEM case */
+       int                     ai_count;
+       /*
+        * Followed by ai_count struct addrinfo and then ai_count
+        * sockaddr_u and finally the canonical name strings.
+        */
+} blocking_gai_resp;
+
+typedef struct blocking_gni_req_tag {
+       size_t                  octets;
+       time_t                  scheduled;
+       time_t                  earliest;
+       int                     retry;
+       size_t                  hostoctets;
+       size_t                  servoctets;
+       int                     flags;
+       gni_sometime_callback   callback;
+       void *                  context;
+       sockaddr_u              socku;
+} blocking_gni_req;
+
+typedef struct blocking_gni_resp_tag {
+       size_t                  octets;
+       int                     retcode;
+       int                     gni_errno; /* for EAI_SYSTEM case */
+       size_t                  hostoctets;
+       size_t                  servoctets;
+       /*
+        * Followed by hostoctets bytes of null-terminated host,
+        * then servoctets bytes of null-terminated service.
+        */
+} blocking_gni_resp;
 
-static int resolve_value;      /* next value of resolve timer */
+static time_t  next_dns_timeslot;
+static time_t  ignore_scheduled_before;
+#ifdef HAVE_RES_INIT
+static time_t  next_res_init;
+#endif
 
-/*
- * Big hack attack
- */
-#define        SKEWTIME        0x08000000      /* 0.03125 seconds as a l_fp fraction */
+static void    scheduled_sleep(time_t, time_t);
+static void    manage_dns_retry_interval(time_t *, time_t *, int *);
+static int     should_retry_dns(int, int);
+static void    getaddrinfo_sometime_complete(blocking_work_req, void *,
+                                             size_t, void *);
+static void    getnameinfo_sometime_complete(blocking_work_req, void *,
+                                             size_t, void *);
 
-/*
- * Select time out.  Set to 2 seconds.  The server is on the local machine,
- * after all.
- */
-#define        TIMEOUT_SEC     2
-#define        TIMEOUT_USEC    0
 
 
 /*
- * Input processing.  The data on each line in the configuration file
- * is supposed to consist of entries in the following order
+ * getaddrinfo_sometime - uses blocking child to call getaddrinfo then
+ *                       invokes provided callback completion function.
  */
-#define        TOK_HOSTNAME    0
-#define        TOK_NEEDED      1
-#define        TOK_TYPE        2
-#define        TOK_HMODE       3
-#define        TOK_VERSION     4
-#define        TOK_MINPOLL     5
-#define        TOK_MAXPOLL     6
-#define        TOK_FLAGS       7
-#define        TOK_TTL         8
-#define        TOK_KEYID       9
-#define        TOK_KEYSTR      10
-#define        NUMTOK          11
-
-#define        MAXLINESIZE     512
-
+int
+getaddrinfo_sometime(
+       const char *            node,
+       const char *            service,
+       const struct addrinfo * hints,
+       gai_sometime_callback   callback,
+       void *                  context
+       )
+{
+       blocking_gai_req *      gai_req;
+       size_t                  req_size;
+       size_t                  nodesize;
+       size_t                  servsize;
+       time_t                  now;
+       
+       NTP_REQUIRE(NULL != node);
+       if (NULL != hints) {
+               NTP_REQUIRE(0 == hints->ai_addrlen);
+               NTP_REQUIRE(NULL == hints->ai_addr);
+               NTP_REQUIRE(NULL == hints->ai_canonname);
+               NTP_REQUIRE(NULL == hints->ai_next);
+       }
 
-/*
- * File descriptor for ntp request code.
- */
-static SOCKET sockfd = INVALID_SOCKET; /* NT uses SOCKET */
-
-/* stuff to be filled in by caller */
-
-keyid_t req_keyid;     /* request keyid */
-int    req_keytype;    /* OpenSSL NID such as NID_md5 */
-size_t req_hashlen;    /* digest size for req_keytype */
-char *req_file;                /* name of the file with configuration info */
-
-/* end stuff to be filled in */
-
-
-static void    checkparent     (void);
-static struct conf_entry *
-               removeentry     (struct conf_entry *);
-static void    addentry        (char *, int, int, int, int, int, int, u_int,
-                                  int, keyid_t, char *);
-static int     findhostaddr    (struct conf_entry *);
-static void    openntp         (void);
-static int     request         (struct conf_peer *);
-static char *  nexttoken       (char **);
-static void    readconf        (FILE *, char *);
-static void    doconfigure     (int);
-
-struct ntp_res_t_pkt {         /* Tagged packet: */
-       void *tag;              /* For the caller */
-       u_int32 paddr;          /* IP to look up, or 0 */
-       char name[MAXHOSTNAMELEN]; /* Name to look up (if 1st byte is not 0) */
-};
-
-struct ntp_res_c_pkt {         /* Control packet: */
-       char name[MAXHOSTNAMELEN];
-       u_int32 paddr;
-       int mode;
-       int version;
-       int minpoll;
-       int maxpoll;
-       u_int flags;
-       int ttl;
-       keyid_t keyid;
-       u_char keystr[MAXFILENAME];
-};
-
-
-static void    resolver_exit (int);
+       nodesize = strlen(node) + 1;
+       servsize = strlen(service) + 1;
+       req_size = sizeof(*gai_req) + nodesize + servsize;
+
+       gai_req = emalloc(req_size);
+
+       gai_req->octets = req_size;
+       now = time(NULL);
+       next_dns_timeslot = max(now, next_dns_timeslot);
+       gai_req->scheduled = now;
+       gai_req->earliest = next_dns_timeslot;
+       gai_req->hints = *hints;
+       gai_req->retry = INITIAL_DNS_RETRY;
+       gai_req->callback = callback;
+       gai_req->context = context;
+       gai_req->nodesize = nodesize;
+       gai_req->servsize = servsize;
+
+       memcpy((char *)gai_req + sizeof(*gai_req), node, nodesize);
+       memcpy((char *)gai_req + sizeof(*gai_req) + nodesize, service,
+              servsize);
+
+       if (queue_blocking_request(
+               BLOCKING_GETADDRINFO,
+               gai_req,
+               req_size, 
+               &getaddrinfo_sometime_complete, 
+               gai_req)) {
+
+               msyslog(LOG_ERR, "unable to queue getaddrinfo request");
+               errno = EFAULT;
+               return -1;
+       }
 
-/*
- * Call here instead of just exiting
- */
+       return 0;
+}
 
-static void resolver_exit (int code)
+int
+blocking_getaddrinfo(
+       blocking_pipe_header *  req
+       )
 {
-#ifdef SYS_WINNT
-       CloseHandle(ResolverEventHandle);
-       ResolverEventHandle = NULL;
-       _endthreadex(code);     /* Just to kill the thread not the process */
-#else
-       exit(code);             /* kill the forked process */
+       blocking_gai_req *      gai_req;
+       blocking_pipe_header *  resp;
+       blocking_gai_resp *     gai_resp;
+       char *                  node;
+       char *                  service;
+       struct addrinfo *       ai_res;
+       struct addrinfo *       ai;
+       struct addrinfo *       serialized_ai;
+       size_t                  canons_octets;
+       size_t                  this_octets;
+       size_t                  resp_octets;
+       char *                  cp;
+       time_t                  time_now;
+
+       gai_req = (void *)((char *)req + sizeof(*req));
+       node = (char *)gai_req + sizeof(*gai_req);
+       service = node + gai_req->nodesize;
+
+       scheduled_sleep(gai_req->scheduled, gai_req->earliest);
+
+#ifdef HAVE_RES_INIT
+       /*
+        * This is ad-hoc.  Reload /etc/resolv.conf once per minute
+        * to pick up on changes from the DHCP client.  [Bug 1226]
+        */
+       time_now = time(NULL);
+       if (next_res_init <= time_now) {
+               if (next_res_init)
+                       res_init();
+               next_res_init = time_now + 60;
+       }
 #endif
-}
 
-/*
- * ntp_res_recv: Process an answer from the resolver
- */
-
-void
-ntp_res_recv(void)
-{
        /*
-         We have data ready on our descriptor.
-         It may be an EOF, meaning the resolver process went away.
-         Otherwise, it will be an "answer".
-       */
-}
+        * Take a shot at the final size, better to overestimate
+        * at first and then realloc to a smaller size.
+        */
 
+       resp = emalloc(sizeof(*resp) + sizeof(*gai_resp) 
+                          + 16 * (sizeof(struct addrinfo)
+                                  + sizeof(sockaddr_u))
+                          + 256);
+       gai_resp = (void *)(resp + 1);
 
-/*
- * ntp_intres needs;
- *
- *     req_key(???), req_keyid, req_file valid
- *     syslog still open
- */
+       DPRINTF(2, ("blocking_getaddrinfo given node %s serv %s fam %d flags %x\n", 
+                   node, service, gai_req->hints.ai_family,
+                   gai_req->hints.ai_flags));
+       
+       ai_res = NULL;
+       gai_resp->retcode = getaddrinfo(node, service, &gai_req->hints, &ai_res);
 
-void
-ntp_intres(void)
-{
-       FILE *in;
-#ifdef SYS_WINNT
-       DWORD rc;
-#else
-       int     rc;
-       struct  timeval tv;
-       fd_set  fdset;
-       int     time_left;
+       switch (gai_resp->retcode) {
+#ifdef EAI_SYSTEM
+       case EAI_SYSTEM:
+               gai_resp->gai_errno = errno;
+               break;
 #endif
-
-#ifdef DEBUG
-       if (debug > 1) {
-               msyslog(LOG_INFO, "NTP_INTRES running");
+       default:
+               gai_resp->gai_errno = 0;
        }
-#endif
 
-       /* check out auth stuff */
-       if (sys_authenticate) {
-               if (!authistrusted(req_keyid)) {
-                       msyslog(LOG_ERR, "invalid request keyid %08x",
-                           req_keyid );
-                       resolver_exit(1);
+       gai_resp->ai_count = canons_octets = 0;
+
+       if (!gai_resp->retcode) {
+               ai = ai_res;
+               while (NULL != ai) {
+                       gai_resp->ai_count++;
+                       if (ai->ai_canonname)
+                               canons_octets += strlen(ai->ai_canonname) + 1;
+                       ai = ai->ai_next;
+               }
+               /*
+                * If this query succeeded only after retrying, DNS may have
+                * just become responsive.  Ignore previously-scheduled
+                * retry sleeps once for each pending request, similar to
+                * the way scheduled_sleep() does when its worker_sleep()
+                * is interrupted.
+                */
+               if (gai_req->retry > INITIAL_DNS_RETRY) {
+                       time_now = time(NULL);
+                       ignore_scheduled_before = time_now;
+                       next_dns_timeslot = time_now;
+                       DPRINTF(1, ("DNS success after retry, ignoring sleeps scheduled before now (%s)",
+                               humantime(time_now)));
                }
        }
 
        /*
-        * Read the configuration info
-        * {this is bogus, since we are forked, but it is easier
-        * to keep this code - gdt}
+        * Our response consists of a header, followed by ai_count 
+        * addrinfo structs followed by ai_count sockaddr_storage 
+        * structs followed by the canonical names.
         */
-       if ((in = fopen(req_file, "r")) == NULL) {
-               msyslog(LOG_ERR, "can't open configuration file %s: %m",
-                       req_file);
-               resolver_exit(1);
-       }
-       readconf(in, req_file);
-       (void) fclose(in);
+       gai_resp->octets = sizeof(*gai_resp)
+                           + gai_resp->ai_count
+                               * (sizeof(gai_req->hints)
+                                  + sizeof(sockaddr_u))
+                           + canons_octets;
 
-#ifdef DEBUG
-       if (!debug)
-#endif
-               if (unlink(req_file))
-                       msyslog(LOG_WARNING,
-                               "unable to remove intres request file %s, %m",
-                               req_file);
+       resp_octets = sizeof(*resp) + gai_resp->octets;
+       resp =  erealloc(resp, resp_octets);
+       gai_resp = (void *)(resp + 1);
 
-       /*
-        * Set up the timers to do first shot immediately.
-        */
-       resolve_timer = 0;
-       resolve_value = MINRESOLVE;
-       config_timer = CONFIG_TIME;
-
-       for (;;) {
-               checkparent();
-
-               if (resolve_timer == 0) {
-                       /*
-                        * Sleep a little to make sure the network is completely up
-                        */
-                       sleep(SLEEPTIME);
-                       doconfigure(1);
-
-                       /* prepare retry, in case there's more work to do */
-                       resolve_timer = resolve_value;
-#ifdef DEBUG
-                       if (debug > 2)
-                               msyslog(LOG_INFO, "resolve_timer: 0->%d", resolve_timer);
-#endif
-                       if (resolve_value < MAXRESOLVE)
-                               resolve_value <<= 1;
-
-                       config_timer = CONFIG_TIME;
-               } else if (config_timer == 0) {  /* MB: in which case would this be required ? */
-                       doconfigure(0);
-                       /* MB: should we check now if we could exit, similar to the code above? */
-                       config_timer = CONFIG_TIME;
-#ifdef DEBUG
-                       if (debug > 2)
-                               msyslog(LOG_INFO, "config_timer: 0->%d", config_timer);
-#endif
-               }
+       /* cp serves as our current pointer while serializing */
+       cp = (void *)(gai_resp + 1);
+       canons_octets = 0;
+
+       if (!gai_resp->retcode) {
+               
+               ai = ai_res;
+               while (NULL != ai) {
+                       memcpy(cp, ai, sizeof(*ai));
+                       serialized_ai = (void *)cp;
+                       cp += sizeof(*ai);
+
+                       /* transform ai_canonname into offset */
+                       if (NULL != serialized_ai->ai_canonname) {
+                               serialized_ai->ai_canonname = (char *)canons_octets;
+                               canons_octets += strlen(ai->ai_canonname) + 1;
+                       }
+                       
+                       /* leave fixup of ai_addr pointer for receiver */
 
-               if (confentries == NULL)
-                       resolver_exit(0);   /* done */
+                       ai = ai->ai_next;
+               }
 
-#ifdef SYS_WINNT
-               rc = WaitForSingleObject(ResolverEventHandle, 1000 * ALARM_TIME);  /* in milliseconds */
+               ai = ai_res;
+               while (NULL != ai) {
+                       NTP_INSIST(ai->ai_addrlen <= sizeof(sockaddr_u));
+                       memcpy(cp, ai->ai_addr, ai->ai_addrlen);
+                       cp += sizeof(sockaddr_u);
 
-               if ( rc == WAIT_OBJECT_0 ) { /* signaled by the main thread */
-                       resolve_timer = 0;         /* retry resolving immediately */
-                       continue;
+                       ai = ai->ai_next;
                }
 
-               if ( rc != WAIT_TIMEOUT ) /* not timeout: error */
-                       resolver_exit(1);
-
-#else  /* not SYS_WINNT */
-               /* Bug 1386: fork() in NetBSD leaves timers running. */
-               /* So we need to retry select on EINTR */
-               time_left = ALARM_TIME;
-               while (time_left > 0) {
-                   tv.tv_sec = time_left;
-                   tv.tv_usec = 0;
-                   FD_ZERO(&fdset);
-                   FD_SET(resolver_pipe_fd[0], &fdset);
-                   rc = select(resolver_pipe_fd[0] + 1, &fdset, (fd_set *)0, (fd_set *)0, &tv);
-
-                   if (rc == 0)                /* normal timeout */
-                       break;
-
-                   if (rc > 0) {  /* parent process has written to the pipe */
-                       read(resolver_pipe_fd[0], (char *)&rc, sizeof(rc));  /* make pipe empty */
-                       resolve_timer = 0;   /* retry resolving immediately */
-                       break;
-                   }
-
-                   if ( rc < 0 ) {             /* select() returned error */
-                       if (errno == EINTR) {   /* Timer went off */
-                           time_left -= (1<<EVENT_TIMEOUT);
-                           continue;           /* try again */
+               ai = ai_res;
+               while (NULL != ai) {
+                       if (NULL != ai->ai_canonname) {
+                               this_octets = strlen(ai->ai_canonname) + 1;
+                               memcpy(cp, ai->ai_canonname, this_octets);
+                               cp += this_octets;
                        }
-                       msyslog(LOG_ERR, "ntp_intres: Error from select: %s",
-                           strerror(errno));
-                       resolver_exit(1);
-                   }
-               }
-#endif
 
-               /* normal timeout, keep on waiting */
-               if (config_timer > 0)
-                       config_timer--;
-               if (resolve_timer > 0)
-                       resolve_timer--;
+                       ai = ai->ai_next;
+               }
        }
-}
 
+       /*
+        * make sure our walk and earlier calc match
+        */
+       NTP_INSIST((size_t)(cp - (char *)resp) == resp_octets);
 
-#ifdef SYS_WINNT
-/*
- * ntp_intres_thread wraps the slightly different interface of Windows
- * thread functions and ntp_intres
- */
-unsigned WINAPI
-ntp_intres_thread(void *UnusedThreadArg)
-{
-       UNUSED_ARG(UnusedThreadArg);
+       if (queue_blocking_response(resp, resp_octets, req)) {
+               DPRINTF(1, ("blocking_getaddrinfo unable to queue response"));
+               return -1;
+       }
 
-       ntp_intres();
        return 0;
 }
-#endif /* SYS_WINNT */
-
 
-/*
- * checkparent - see if our parent process is still running
- *
- * No need to worry in the Windows NT environment whether the
- * main thread is still running, because if it goes
- * down it takes the whole process down with it (in
- * which case we won't be running this thread either)
- * Turn function into NOP;
- */
 
 static void
-checkparent(void)
+getaddrinfo_sometime_complete(
+       blocking_work_req       rtype,
+       void *                  context,
+       size_t                  respsize,
+       void *                  resp
+       )
 {
-#if !defined (SYS_WINNT) && !defined (SYS_VXWORKS)
+       blocking_gai_req *              gai_req;
+       blocking_gai_resp *             gai_resp;
+       struct addrinfo *               ai;
+       struct addrinfo *               next_ai;
+       sockaddr_u *                    psau;
+       char *                          node;
+       char *                          service;
+       char *                          canon_start;
+       int                             again;
+       int                             af;
+       const char *                    fam_spec;
+       int                             i;
+
+       gai_req = context;
+       gai_resp = resp;
+
+       NTP_REQUIRE(BLOCKING_GETADDRINFO == rtype);
+       NTP_REQUIRE(respsize == gai_resp->octets);
+
+       node = (char *)gai_req + sizeof(*gai_req);
+       service = node + gai_req->nodesize;
+
+       if (gai_resp->retcode) {
+               again = should_retry_dns(gai_resp->retcode, gai_resp->gai_errno);
+               /*
+                * exponential backoff of DNS retries to 64s
+                */
+               if (gai_req->retry && again) {
+                       /* log the first retry only */
+                       if (INITIAL_DNS_RETRY == gai_req->retry)
+                               NLOG(NLOG_SYSINFO) {
+                                       af = gai_req->hints.ai_family;
+                                       fam_spec = (AF_INET6 == af)
+                                                      ? " (AAAA)"
+                                                      : (AF_INET == af)
+                                                            ? " (A)"
+                                                            : "";
+#ifdef EAI_SYSTEM
+                                       if (EAI_SYSTEM == gai_resp->retcode)
+                                               msyslog(LOG_INFO,
+                                                       "retrying DNS %s%s: EAI_SYSTEM %s (%d)",
+                                                       node, fam_spec,
+                                                       strerror(gai_resp->gai_errno),
+                                                       gai_resp->gai_errno);
+                                       else
+#endif
+                                               msyslog(LOG_INFO,
+                                                       "retrying DNS %s%s: %s (%d)",
+                                                       node, fam_spec,
+                                                       gai_strerror(gai_resp->retcode),
+                                                       gai_resp->retcode);
+                               }
+                       manage_dns_retry_interval(&gai_req->scheduled,
+                           &gai_req->earliest, &gai_req->retry);
+                       if (!queue_blocking_request(
+                                       BLOCKING_GETADDRINFO,
+                                       gai_req,
+                                       gai_req->octets,
+                                       &getaddrinfo_sometime_complete,
+                                       gai_req))
+                               return;
+                       else
+                               msyslog(LOG_ERR, "unable to retry hostname %s", node);
+               }
+       }
 
        /*
-        * If our parent (the server) has died we will have been
-        * inherited by init.  If so, exit.
+        * fixup pointers in returned addrinfo array
         */
-       if (getppid() == 1) {
-               msyslog(LOG_INFO, "parent died before we finished, exiting");
-               resolver_exit(0);
+       ai = (void *)((char *)gai_resp + sizeof(*gai_resp));
+       next_ai = NULL;
+       for (i = gai_resp->ai_count - 1; i >= 0; i--) {
+               ai[i].ai_next = next_ai;
+               next_ai = &ai[i];
        }
-#endif /* SYS_WINNT && SYS_VXWORKS*/
-}
-
 
+       psau = (void *)((char *)ai + gai_resp->ai_count * sizeof(*ai));
+       canon_start = (char *)psau + gai_resp->ai_count * sizeof(*psau);
 
-/*
- * removeentry - we are done with an entry, remove it from the list
- */
-static struct conf_entry *
-removeentry(
-       struct conf_entry *entry
-       )
-{
-       register struct conf_entry *ce;
-       struct conf_entry *next_ce;
+       for (i = 0; i < gai_resp->ai_count; i++) {
+               if (NULL != ai[i].ai_addr)
+                       ai[i].ai_addr = &psau->sa;
+               psau++;
+               if (NULL != ai[i].ai_canonname)
+                       ai[i].ai_canonname += (size_t)canon_start;
+       }
 
-       ce = confentries;
-       if (ce == entry)
-               confentries = ce->ce_next;
-       else
-               while (ce != NULL) {
-                       if (ce->ce_next == entry) {
-                               ce->ce_next = entry->ce_next;
-                               break;
-                       }
-                       ce = ce->ce_next;
-               }
+       NTP_ENSURE((char *)psau == canon_start);
 
-       next_ce = entry->ce_next;
-       if (entry->ce_name != NULL)
-               free(entry->ce_name);
-       free(entry);
+       if (!gai_resp->ai_count)
+               ai = NULL;
+       
+       (*gai_req->callback)(gai_resp->retcode, gai_resp->gai_errno,
+                            gai_req->context, node, service, 
+                            &gai_req->hints, ai);
 
-       return next_ce;
+       free(gai_req);
+       /* gai_resp is part of block freed by process_blocking_response() */
 }
 
 
-/*
- * addentry - add an entry to the configuration list
- */
-static void
-addentry(
-       char *name,
-       int no_needed,
-       int type,
-       int mode,
-       int version,
-       int minpoll,
-       int maxpoll,
-       u_int flags,
-       int ttl,
-       keyid_t keyid,
-       char *keystr
-       )
+#ifdef TEST_BLOCKING_WORKER
+void gai_test_callback(int rescode, int gai_errno, void *context, const char *name, const char *service, const struct addrinfo *hints, const struct addrinfo *ai_res)
 {
-       register struct conf_entry *ce;
-
-#ifdef DEBUG
-       if (debug > 1)
-               msyslog(LOG_INFO, 
-                   "intres: <%s> %d %d %d %d %d %d %x %d %x %s",
-                   name, no_needed, type, mode, version,
-                   minpoll, maxpoll, flags, ttl, keyid, keystr);
-#endif
-       ce = emalloc(sizeof(*ce));
-       ce->ce_name = estrdup(name);
-       ce->ce_peeraddr = 0;
-#ifdef ISC_PLATFORM_HAVEIPV6
-       ce->ce_peeraddr6 = in6addr_any;
-#endif
-       ZERO_SOCK(&ce->peer_store);
-       ce->ce_hmode = (u_char)mode;
-       ce->ce_version = (u_char)version;
-       ce->ce_minpoll = (u_char)minpoll;
-       ce->ce_maxpoll = (u_char)maxpoll;
-       ce->no_needed = no_needed;      /* Not used after here. */
-                                       /* Start of fixing bug-975 */
-       ce->type = type;
-       ce->ce_flags = (u_char)flags;
-       ce->ce_ttl = (u_char)ttl;
-       ce->ce_keyid = keyid;
-       strncpy(ce->ce_keystr, keystr, sizeof(ce->ce_keystr) - 1);
-       ce->ce_keystr[sizeof(ce->ce_keystr) - 1] = 0;
-       ce->ce_next = NULL;
-
-       if (confentries == NULL) {
-               confentries = ce;
-       } else {
-               register struct conf_entry *cep;
+       sockaddr_u addr;
 
-               for (cep = confentries; cep->ce_next != NULL;
-                    cep = cep->ce_next)
-                   /* nothing */;
-               cep->ce_next = ce;
+       if (rescode) {
+               DPRINTF(1, ("gai_test_callback context %p error rescode %d %s serv %s\n",
+                           context, rescode, name, service));
+               return;
+       }
+       while (!rescode && NULL != ai_res) {
+               ZERO_SOCK(&addr);
+               memcpy(&addr, ai_res->ai_addr, ai_res->ai_addrlen);
+               DPRINTF(1, ("ctx %p fam %d addr %s canon '%s' type %s at %p ai_addr %p ai_next %p\n", 
+                           context,
+                           AF(&addr),
+                           stoa(&addr), 
+                           (ai_res->ai_canonname)
+                               ? ai_res->ai_canonname
+                               : "",
+                           (SOCK_DGRAM == ai_res->ai_socktype) 
+                               ? "DGRAM" 
+                               : (SOCK_STREAM == ai_res->ai_socktype) 
+                                       ? "STREAM" 
+                                       : "(other)",
+                           ai_res,
+                           ai_res->ai_addr,
+                           ai_res->ai_next));
+
+               getnameinfo_sometime((sockaddr_u *)ai_res->ai_addr, 128, 32, 0, gni_test_callback, context);
+
+               ai_res = ai_res->ai_next;
        }
 }
+#endif /* TEST_BLOCKING_WORKER */
 
 
-/*
- * findhostaddr - resolve a host name into an address (Or vice-versa)
- *
- * Given one of {ce_peeraddr,ce_name}, find the other one.
- * It returns 1 for "success" and 0 for an uncorrectable failure.
- * Note that "success" includes try again errors.  You can tell that you
- *  got a "try again" since {ce_peeraddr,ce_name} will still be zero.
- */
-static int
-findhostaddr(
-       struct conf_entry *entry
+int
+getnameinfo_sometime(
+       sockaddr_u *            psau,
+       size_t                  hostoctets,
+       size_t                  servoctets,
+       int                     flags,
+       gni_sometime_callback   callback,
+       void *                  context
        )
 {
-       static int eai_again_seen = 0;
-       struct addrinfo *addr;
-       struct addrinfo hints;
-       int again;
-       int error;
-
-       checkparent();          /* make sure our guy is still running */
-
-       if (entry->ce_name != NULL && !SOCK_UNSPEC(&entry->peer_store)) {
-               /* HMS: Squawk? */
-               msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are defined...");
-               return 1;
-       }
-
-       if (entry->ce_name == NULL && SOCK_UNSPEC(&entry->peer_store)) {
-               msyslog(LOG_ERR, "findhostaddr: both ce_name and ce_peeraddr are undefined!");
-               return 0;
-       }
-
-       if (entry->ce_name) {
-               DPRINTF(2, ("findhostaddr: Resolving <%s>\n",
-                       entry->ce_name));
-
-               memset(&hints, 0, sizeof(hints));
-               hints.ai_family = entry->type;
-               hints.ai_socktype = SOCK_DGRAM;
-               hints.ai_protocol = IPPROTO_UDP;
-               /*
-                * If IPv6 is not available look only for v4 addresses
-                */
-               if (!ipv6_works)
-                       hints.ai_family = AF_INET;
-               error = getaddrinfo(entry->ce_name, NULL, &hints, &addr);
-               if (error == 0) {
-                       entry->peer_store = *((sockaddr_u *)(addr->ai_addr));
-                       if (IS_IPV4(&entry->peer_store)) {
-                               entry->ce_peeraddr =
-                                   NSRCADR(&entry->peer_store);
-                               entry->ce_config.v6_flag = 0;
-                       } else {
-                               entry->ce_peeraddr6 =
-                                   SOCK_ADDR6(&entry->peer_store);
-                               entry->ce_config.v6_flag = 1;
-                       }
-                       freeaddrinfo(addr);
-               }
-       } else {
-               DPRINTF(2, ("findhostaddr: Resolving <%s>\n",
-                       stoa(&entry->peer_store)));
-
-               entry->ce_name = emalloc(MAXHOSTNAMELEN);
-               error = getnameinfo((const struct sockaddr *)&entry->peer_store,
-                                  SOCKLEN(&entry->peer_store),
-                                  (char *)&entry->ce_name, MAXHOSTNAMELEN,
-                                  NULL, 0, 0);
-       }
-
-       if (0 == error) {
-
-               /* again is our return value, for success it is 1 */
-               again = 1;
-
-               DPRINTF(2, ("findhostaddr: %s resolved.\n", 
-                       (entry->ce_name) ? "name" : "address"));
-       } else {
-               /*
-                * If the resolver failed, see if the failure is
-                * temporary. If so, return success.
-                */
-               again = 0;
-
-               switch (error) {
-
-               case EAI_FAIL:
-                       again = 1;
-                       break;
-
-               case EAI_AGAIN:
-                       again = 1;
-                       eai_again_seen = 1;
-                       break;
-
-               case EAI_NONAME:
-#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
-               case EAI_NODATA:
-#endif
-                       msyslog(LOG_ERR, "host name not found%s%s: %s",
-                               (EAI_NONAME == error) ? "" : " EAI_NODATA",
-                               (eai_again_seen) ? " (permanent)" : "",
-                               entry->ce_name);
-                       again = !eai_again_seen;
-                       break;
-
-#ifdef EAI_SYSTEM
-               case EAI_SYSTEM:
-                       /* 
-                        * EAI_SYSTEM means the real error is in errno.  We should be more
-                        * discriminating about which errno values require retrying, but
-                        * this matches existing behavior.
-                        */
-                       again = 1;
-                       DPRINTF(1, ("intres: EAI_SYSTEM errno %d (%s) means try again, right?\n",
-                               errno, strerror(errno)));
-                       break;
-#endif
-               }
-
-               /* do this here to avoid perturbing errno earlier */
-               DPRINTF(2, ("intres: got error status of: %d\n", error));
+       blocking_gni_req *      gni_req;
+       time_t                  time_now;
+       
+       NTP_REQUIRE(hostoctets);
+       NTP_REQUIRE(hostoctets + servoctets < 1024);
+
+       gni_req = emalloc(sizeof(*gni_req));
+       memset(gni_req, 0, sizeof(*gni_req));
+
+       gni_req->octets = sizeof(*gni_req);
+       time_now = time(NULL);
+       next_dns_timeslot = max(time_now, next_dns_timeslot);
+       gni_req->scheduled = time_now;
+       gni_req->earliest = next_dns_timeslot;
+       memcpy(&gni_req->socku, psau, SOCKLEN(psau));
+       gni_req->hostoctets = hostoctets;
+       gni_req->servoctets = servoctets;
+       gni_req->flags = flags;
+       gni_req->retry = INITIAL_DNS_RETRY;
+       gni_req->callback = callback;
+       gni_req->context = context;
+
+       if (queue_blocking_request(
+               BLOCKING_GETNAMEINFO,
+               gni_req,
+               sizeof(*gni_req), 
+               &getnameinfo_sometime_complete, 
+               gni_req)) {
+
+               msyslog(LOG_ERR, "unable to queue getnameinfo request");
+               errno = EFAULT;
+               return -1;
        }
 
-       return again;
+       return 0;
 }
 
 
-/*
- * openntp - open a socket to the ntp server
- */
-static void
-openntp(void)
+int
+blocking_getnameinfo(
+       blocking_pipe_header *  req
+       )
 {
-       const char      *localhost = "127.0.0.1";       /* Use IPv4 loopback */
-       struct addrinfo hints;
-       struct addrinfo *addr;
-       u_long          on;
-       int             err;
+       blocking_gni_req *      gni_req;
+       blocking_pipe_header *  resp;
+       blocking_gni_resp *     gni_resp;
+       size_t                  octets;
+       size_t                  resp_octets;
+       char *                  host;
+       char *                  service;
+       char *                  cp;
+       int                     rc;
+       time_t                  time_now;
 
-       if (sockfd != INVALID_SOCKET)
-               return;
+       gni_req = (void *)((char *)req + sizeof(*req));
 
-       memset(&hints, 0, sizeof(hints));
+       octets = gni_req->hostoctets + gni_req->servoctets;
 
        /*
-        * For now only bother with IPv4
+        * Some alloca() implementations are fragile regarding
+        * large allocations.  We only need room for the host
+        * and service names.
         */
-       hints.ai_family = AF_INET;
-       hints.ai_socktype = SOCK_DGRAM;
+       NTP_REQUIRE(octets < 1024);
 
-       err = getaddrinfo(localhost, "ntp", &hints, &addr);
-
-       if (err) {
-#ifdef EAI_SYSTEM
-               if (EAI_SYSTEM == err)
-                       msyslog(LOG_ERR, "getaddrinfo(%s) failed: %m",
-                               localhost);
-               else
-#endif
-                       msyslog(LOG_ERR, "getaddrinfo(%s) failed: %s",
-                               localhost, gai_strerror(err));
-               resolver_exit(1);
+#ifndef HAVE_ALLOCA
+       host = emalloc(octets);
+#else
+       host = alloca(octets);
+       if (NULL == host) {
+               msyslog(LOG_ERR,
+                       "blocking_getnameinfo unable to allocate %d octets on stack",
+                       octets);
+               exit(1);
        }
+#endif
+       service = host + gni_req->hostoctets;
 
-       sockfd = socket(addr->ai_family, addr->ai_socktype, 0);
-
-       if (INVALID_SOCKET == sockfd) {
-               msyslog(LOG_ERR, "socket() failed: %m");
-               resolver_exit(1);
-       }
+       scheduled_sleep(gni_req->scheduled, gni_req->earliest);
 
-#ifndef SYS_WINNT
+#ifdef HAVE_RES_INIT
        /*
-        * On Windows only the count of sockets must be less than
-        * FD_SETSIZE. On Unix each descriptor's value must be less
-        * than FD_SETSIZE, as fd_set is a bit array.
+        * This is ad-hoc.  Reload /etc/resolv.conf once per minute
+        * to pick up on changes from the DHCP client.  [Bug 1226]
         */
-       if (sockfd >= FD_SETSIZE) {
-               msyslog(LOG_ERR, "socket fd %d too large, FD_SETSIZE %d",
-                       (int)sockfd, FD_SETSIZE);
-               resolver_exit(1);
+       time_now = time(NULL);
+       if (next_res_init <= time_now) {
+               if (next_res_init)
+                       res_init();
+               next_res_init = time_now + 60;
        }
+#endif
 
        /*
-        * Make the socket non-blocking.  We'll wait with select()
-        * Unix: fcntl(O_NONBLOCK) or fcntl(FNDELAY)
-        */
-# ifdef O_NONBLOCK
-       if (fcntl(sockfd, F_SETFL, O_NONBLOCK) == -1) {
-               msyslog(LOG_ERR, "fcntl(O_NONBLOCK) failed: %m");
-               resolver_exit(1);
-       }
-# else
-#  ifdef FNDELAY
-       if (fcntl(sockfd, F_SETFL, FNDELAY) == -1) {
-               msyslog(LOG_ERR, "fcntl(FNDELAY) failed: %m");
-               resolver_exit(1);
-       }
-#  else
-#   include "Bletch: NEED NON BLOCKING IO"
-#  endif       /* FNDDELAY */
-# endif        /* O_NONBLOCK */
-       (void)on;       /* quiet unused warning */
-#else  /* !SYS_WINNT above */
-       /*
-        * Make the socket non-blocking.  We'll wait with select()
-        * Windows: ioctlsocket(FIONBIO)
+        * Take a shot at the final size, better to overestimate
+        * then realloc to a smaller size.
         */
-       on = 1;
-       err = ioctlsocket(sockfd, FIONBIO, &on);
-       if (SOCKET_ERROR == err) {
-               msyslog(LOG_ERR, "ioctlsocket(FIONBIO) fails: %m");
-               resolver_exit(1);
-       }
-#endif /* SYS_WINNT */
-
-       err = connect(sockfd, addr->ai_addr, addr->ai_addrlen);
-       if (SOCKET_ERROR == err) {
-               msyslog(LOG_ERR, "openntp: connect() failed: %m");
-               resolver_exit(1);
-       }
-
-       freeaddrinfo(addr);
-}
 
+       resp_octets = sizeof(*resp) + sizeof(*gni_resp) + octets;
+       resp = emalloc(resp_octets);
+       gni_resp = (void *)((char *)resp + sizeof(*resp));
 
-/*
- * request - send a configuration request to the server, wait for a response
- */
-static int
-request(
-       struct conf_peer *conf
-       )
-{
-       struct sock_timeval tvout;
-       struct req_pkt reqpkt;
-       size_t  req_len;
-       size_t  total_len;      /* req_len plus keyid & digest */
-       fd_set  fdset;
-       l_fp    ts;
-       char *  pch;
-       char *  pchEnd;
-       l_fp *  pts;
-       keyid_t *pkeyid;
-       int n;
-#ifdef SYS_WINNT
-       HANDLE  hReadWriteEvent = NULL;
-       BOOL    ret;
-       DWORD   NumberOfBytesWritten, NumberOfBytesRead, dwWait;
-       OVERLAPPED overlap;
-#endif /* SYS_WINNT */
-
-       checkparent();          /* make sure our guy is still running */
-
-       if (sockfd == INVALID_SOCKET)
-               openntp();
+       DPRINTF(2, ("blocking_getnameinfo given addr %s flags 0x%x hostlen %d servlen %d\n",
+                   stoa(&gni_req->socku), gni_req->flags,
+                   gni_req->hostoctets, gni_req->servoctets));
        
-#ifdef SYS_WINNT
-       hReadWriteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-#endif /* SYS_WINNT */
-
-       /*
-        * Try to clear out any previously received traffic so it
-        * doesn't fool us.  Note the socket is nonblocking.
-        */
-       tvout.tv_sec =  0;
-       tvout.tv_usec = 0;
-       FD_ZERO(&fdset);
-       FD_SET(sockfd, &fdset);
-       while (select(sockfd + 1, &fdset, (fd_set *)0, (fd_set *)0, &tvout) >
-              0) {
-               recv(sockfd, (char *)&reqpkt, sizeof(reqpkt), 0);
-               FD_ZERO(&fdset);
-               FD_SET(sockfd, &fdset);
+       gni_resp->retcode = getnameinfo(&gni_req->socku.sa,
+                                       SOCKLEN(&gni_req->socku),
+                                       host,
+                                       gni_req->hostoctets,
+                                       service,
+                                       gni_req->servoctets,
+                                       gni_req->flags);
+
+       switch (gni_resp->retcode) {
+#ifdef EAI_SYSTEM
+       case EAI_SYSTEM:
+               gni_resp->gni_errno = errno;
+               break;
+#endif
+       default:
+               gni_resp->gni_errno = 0;
        }
 
-       /*
-        * Make up a request packet with the configuration info
-        */
-       memset(&reqpkt, 0, sizeof(reqpkt));
-
-       reqpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0);
-       reqpkt.auth_seq = AUTH_SEQ(1, 0);       /* authenticated, no seq */
-       reqpkt.implementation = IMPL_XNTPD;     /* local implementation */
-       reqpkt.request = REQ_CONFIG;            /* configure a new peer */
-       reqpkt.err_nitems = ERR_NITEMS(0, 1);   /* one item */
-       reqpkt.mbz_itemsize = MBZ_ITEMSIZE(sizeof(*conf));
-       /* Make sure mbz_itemsize <= sizeof reqpkt.data */
-       if (sizeof(*conf) > sizeof(reqpkt.data)) {
-               msyslog(LOG_ERR,
-                       "Bletch: conf_peer is too big for reqpkt.data!");
-               resolver_exit(1);
-       }
-       memcpy(reqpkt.data, conf, sizeof(*conf));
-
-       if (sys_authenticate && req_hashlen > 16) {
-               pch = reqpkt.data; 
-               /* 32-bit alignment */
-               pch += (sizeof(*conf) + 3) & ~3;
-               pts = (void *)pch;
-               pkeyid = (void *)(pts + 1);
-               pchEnd = (void *)pkeyid;
-               req_len = pchEnd - (char *)&reqpkt;
-               pchEnd = (void *)(pkeyid + 1);
-               pchEnd += req_hashlen;
-               total_len = pchEnd - (char *)&reqpkt;
-               if (total_len > sizeof(reqpkt)) {
-                       msyslog(LOG_ERR,
-                               "intres total_len %u limit is %u (%u octet digest)\n",
-                               total_len, sizeof(reqpkt),
-                               req_hashlen);
-                       resolver_exit(1);
-               }
+       if (gni_resp->retcode) {
+               gni_resp->hostoctets = 0;
+               gni_resp->servoctets = 0;
        } else {
-               pts = &reqpkt.tstamp;
-               pkeyid = &reqpkt.keyid;
-               req_len = REQ_LEN_NOMAC;
-       }
-
-       *pkeyid = htonl(req_keyid);
-       get_systime(&ts);
-       L_ADDUF(&ts, SKEWTIME);
-       HTONL_FP(&ts, pts);
-       if (sys_authenticate) {
-               n = authencrypt(req_keyid, (void *)&reqpkt, req_len);
-               if ((size_t)n != req_hashlen + sizeof(reqpkt.keyid)) {
-                       msyslog(LOG_ERR,
-                               "intres maclen %d expected %u\n",
-                               n, req_hashlen + sizeof(reqpkt.keyid));
-                       resolver_exit(1);
+               gni_resp->hostoctets = strlen(host) + 1;
+               gni_resp->servoctets = strlen(service) + 1;
+               /*
+                * If this query succeeded only after retrying, DNS may have
+                * just become responsive.  Ignore previously-scheduled
+                * retry sleeps once for each pending request, similar to
+                * the way scheduled_sleep() does when its worker_sleep()
+                * is interrupted.
+                */
+               if (gni_req->retry > INITIAL_DNS_RETRY) {
+                       time_now = time(NULL);
+                       ignore_scheduled_before = time_now;
+                       next_dns_timeslot = time_now;
+                       DPRINTF(1, ("DNS success after retrying, ignoring sleeps scheduled before now (%s)",
+                               humantime(time_now)));
                }
-               req_len += n;
        }
-
+       octets = gni_resp->hostoctets + gni_resp->servoctets;
        /*
-        * Done.  Send it.
+        * Our response consists of a header, followed by the host and
+        * service strings, each null-terminated.
         */
-#ifndef SYS_WINNT
-       n = send(sockfd, (char *)&reqpkt, req_len, 0);
-       if (n < 0) {
-               msyslog(LOG_ERR, "send to NTP server failed: %m");
-               return 0;       /* maybe should exit */
-       }
-#else
-       /* In the NT world, documentation seems to indicate that there
-        * exist _write and _read routines that can be used to do blocking
-        * I/O on sockets. Problem is these routines require a socket
-        * handle obtained through the _open_osf_handle C run-time API
-        * of which there is no explanation in the documentation. We need
-        * nonblocking write's and read's anyway for our purpose here.
-        * We're therefore forced to deviate a little bit from the Unix
-        * model here and use the ReadFile and WriteFile Win32 I/O API's
-        * on the socket
-        */
-       overlap.Offset = overlap.OffsetHigh = (DWORD)0;
-       overlap.hEvent = hReadWriteEvent;
-       ret = WriteFile((HANDLE)sockfd, (char *)&reqpkt, req_len,
-                       NULL, (LPOVERLAPPED)&overlap);
-       if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) {
-               msyslog(LOG_ERR, "send to NTP server failed: %m");
-               return 0;
-       }
-       dwWait = WaitForSingleObject(hReadWriteEvent, (DWORD) TIMEOUT_SEC * 1000);
-       if ((dwWait == WAIT_FAILED) || (dwWait == WAIT_TIMEOUT)) {
-               if (dwWait == WAIT_FAILED)
-                   msyslog(LOG_ERR, "WaitForSingleObject failed: %m");
-               return 0;
-       }
-       if (!GetOverlappedResult((HANDLE)sockfd, (LPOVERLAPPED)&overlap,
-                               (LPDWORD)&NumberOfBytesWritten, FALSE)) {
-               msyslog(LOG_ERR, "GetOverlappedResult for WriteFile fails: %m");
-               return 0;
-       }
-#endif /* SYS_WINNT */
+       resp_octets = sizeof(*resp) + sizeof(*gni_resp) + octets;
 
+       resp = erealloc(resp, resp_octets);
+       gni_resp = (void *)(resp + 1);
 
-       /*
-        * Wait for a response.  A weakness of the mode 7 protocol used
-        * is that there is no way to associate a response with a
-        * particular request, i.e. the response to this configuration
-        * request is indistinguishable from that to any other.  I should
-        * fix this some day.  In any event, the time out is fairly
-        * pessimistic to make sure that if an answer is coming back
-        * at all, we get it.
-        */
-       for (;;) {
-               FD_ZERO(&fdset);
-               FD_SET(sockfd, &fdset);
-               tvout.tv_sec = TIMEOUT_SEC;
-               tvout.tv_usec = TIMEOUT_USEC;
-
-               n = select(sockfd + 1, &fdset, (fd_set *)0,
-                          (fd_set *)0, &tvout);
-
-               if (n < 0) {
-                       if (errno != EINTR)
-                               msyslog(LOG_ERR, "select() fails: %m");
-                       return 0;
-               } else if (n == 0) {
-#ifdef DEBUG
-                       if (debug)
-                               msyslog(LOG_INFO, "ntp_intres select() returned 0.");
-#endif
-                       return 0;
-               }
+       gni_resp->octets = sizeof(*gni_resp) + octets;
 
-#ifndef SYS_WINNT
-               n = recv(sockfd, (char *)&reqpkt, sizeof(reqpkt), 0);
-               if (n <= 0) {
-                       if (n < 0) {
-                               msyslog(LOG_ERR, "recv() fails: %m");
-                               return 0;
-                       }
-                       continue;
-               }
-#else /* Overlapped I/O used on non-blocking sockets on Windows NT */
-               ret = ReadFile((HANDLE)sockfd, (char *)&reqpkt, sizeof(reqpkt),
-                              NULL, (LPOVERLAPPED)&overlap);
-               if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) {
-                       msyslog(LOG_ERR, "ReadFile() fails: %m");
-                       return 0;
-               }
-               dwWait = WaitForSingleObject(hReadWriteEvent, (DWORD) TIMEOUT_SEC * 1000);
-               if ((dwWait == WAIT_FAILED) || (dwWait == WAIT_TIMEOUT)) {
-                       if (dwWait == WAIT_FAILED) {
-                               msyslog(LOG_ERR, "WaitForSingleObject for ReadFile fails: %m");
-                               return 0;
-                       }
-                       continue;
-               }
-               if (!GetOverlappedResult((HANDLE)sockfd, (LPOVERLAPPED)&overlap,
-                                       (LPDWORD)&NumberOfBytesRead, FALSE)) {
-                       msyslog(LOG_ERR, "GetOverlappedResult fails: %m");
-                       return 0;
-               }
-               n = NumberOfBytesRead;
-#endif /* SYS_WINNT */
+       /* cp serves as our current pointer while serializing */
+       cp = (void *)(gni_resp + 1);
 
-               /*
-                * Got one.  Check through to make sure it is what
-                * we expect.
-                */
-               if (n < RESP_HEADER_SIZE) {
-                       msyslog(LOG_ERR, "received runt response (%d octets)",
-                               n);
-                       continue;
-               }
+       if (!gni_resp->retcode) {
+               memcpy(cp, host, gni_resp->hostoctets);
+               cp += gni_resp->hostoctets;
+               memcpy(cp, service, gni_resp->servoctets);
+               cp += gni_resp->servoctets;
+       }
 
-               if (!ISRESPONSE(reqpkt.rm_vn_mode)) {
-#ifdef DEBUG
-                       if (debug > 1)
-                           msyslog(LOG_INFO, "received non-response packet");
-#endif
-                       continue;
-               }
+       NTP_INSIST((size_t)(cp - (char *)resp) == resp_octets);
+       NTP_INSIST(resp_octets - sizeof(*resp) == gni_resp->octets);
 
-               if (ISMORE(reqpkt.rm_vn_mode)) {
-#ifdef DEBUG
-                       if (debug > 1)
-                           msyslog(LOG_INFO, "received fragmented packet");
+       rc = queue_blocking_response(resp, resp_octets, req);
+       if (rc)
+               msyslog(LOG_ERR, "blocking_getnameinfo unable to queue response");
+#ifndef HAVE_ALLOCA
+       free(host);
 #endif
-                       continue;
-               }
+       return rc;
+}
 
-               if ( ( (INFO_VERSION(reqpkt.rm_vn_mode) < 2)
-                      || (INFO_VERSION(reqpkt.rm_vn_mode) > NTP_VERSION))
-                    || INFO_MODE(reqpkt.rm_vn_mode) != MODE_PRIVATE) {
-#ifdef DEBUG
-                       if (debug > 1)
-                           msyslog(LOG_INFO,
-                                   "version (%d/%d) or mode (%d/%d) incorrect",
-                                   INFO_VERSION(reqpkt.rm_vn_mode),
-                                   NTP_VERSION,
-                                   INFO_MODE(reqpkt.rm_vn_mode),
-                                   MODE_PRIVATE);
-#endif
-                       continue;
-               }
 
-               if (INFO_SEQ(reqpkt.auth_seq) != 0) {
-#ifdef DEBUG
-                       if (debug > 1)
-                           msyslog(LOG_INFO,
-                                   "nonzero sequence number (%d)",
-                                   INFO_SEQ(reqpkt.auth_seq));
-#endif
-                       continue;
-               }
+static void
+getnameinfo_sometime_complete(
+       blocking_work_req       rtype,
+       void *                  context,
+       size_t                  respsize,
+       void *                  resp
+       )
+{
+       blocking_gni_req *      gni_req;
+       blocking_gni_resp *     gni_resp;
+       char *                  host;
+       char *                  service;
+       int                     again;
 
-               if (reqpkt.implementation != IMPL_XNTPD ||
-                   reqpkt.request != REQ_CONFIG) {
-#ifdef DEBUG
-                       if (debug > 1)
-                           msyslog(LOG_INFO,
-                                   "implementation (%d) or request (%d) incorrect",
-                                   reqpkt.implementation, reqpkt.request);
-#endif
-                       continue;
-               }
+       gni_req = context;
+       gni_resp = resp;
 
-               if (INFO_NITEMS(reqpkt.err_nitems) != 0 ||
-                   INFO_MBZ(reqpkt.mbz_itemsize) != 0 ||
-                   INFO_ITEMSIZE(reqpkt.mbz_itemsize) != 0) {
-#ifdef DEBUG
-                       if (debug > 1)
-                           msyslog(LOG_INFO,
-                                   "nitems (%d) mbz (%d) or itemsize (%d) nonzero",
-                                   INFO_NITEMS(reqpkt.err_nitems),
-                                   INFO_MBZ(reqpkt.mbz_itemsize),
-                                   INFO_ITEMSIZE(reqpkt.mbz_itemsize));
-#endif
-                       continue;
-               }
+       NTP_REQUIRE(BLOCKING_GETNAMEINFO == rtype);
+       NTP_REQUIRE(respsize == gni_resp->octets);
 
-               n = INFO_ERR(reqpkt.err_nitems);
-               switch (n) {
-                   case INFO_OKAY:
-                       /* success */
-                       return 1;
-               
-                   case INFO_ERR_NODATA:
-                       /*
-                        * newpeer() refused duplicate association, no
-                        * point in retrying so call it success.
-                        */
-                       return 1;
-               
-                   case INFO_ERR_IMPL:
-                       msyslog(LOG_ERR,
-                               "ntp_intres.request: implementation mismatch");
-                       return 0;
-               
-                   case INFO_ERR_REQ:
-                       msyslog(LOG_ERR,
-                               "ntp_intres.request: request unknown");
-                       return 0;
-               
-                   case INFO_ERR_FMT:
-                       msyslog(LOG_ERR,
-                               "ntp_intres.request: format error");
-                       return 0;
-
-                   case INFO_ERR_AUTH:
-                       msyslog(LOG_ERR,
-                               "ntp_intres.request: permission denied");
-                       return 0;
-
-                   default:
-                       msyslog(LOG_ERR,
-                               "ntp_intres.request: unknown error code %d", n);
-                       return 0;
+       if (gni_resp->retcode) {
+               again = should_retry_dns(gni_resp->retcode, gni_resp->gni_errno);
+               /*
+                * exponential backoff of DNS retries to 64s
+                */
+               if (gni_req->retry)
+                       manage_dns_retry_interval(&gni_req->scheduled,
+                           &gni_req->earliest, &gni_req->retry);
+
+               if (gni_req->retry && again) {
+                       if (!queue_blocking_request(
+                               BLOCKING_GETNAMEINFO,
+                               gni_req,
+                               gni_req->octets, 
+                               &getnameinfo_sometime_complete, 
+                               gni_req))
+                               return;
+
+                       msyslog(LOG_ERR, "unable to retry reverse lookup of %s", stoa(&gni_req->socku));
                }
        }
-}
 
+       if (!gni_resp->hostoctets) {
+               host = NULL;
+               service = NULL;
+       } else {
+               host = (char *)gni_resp + sizeof(*gni_resp);
+               service = (gni_resp->servoctets) 
+                             ? host + gni_resp->hostoctets
+                             : NULL;
+       }
 
-/*
- * nexttoken - return the next token from a line
- */
-static char *
-nexttoken(
-       char **lptr
-       )
-{
-       register char *cp;
-       register char *tstart;
+       (*gni_req->callback)(gni_resp->retcode, gni_resp->gni_errno,
+                            &gni_req->socku, gni_req->flags, host,
+                            service, gni_req->context);
 
-       cp = *lptr;
+       free(gni_req);
+       /* gni_resp is part of block freed by process_blocking_response() */
+}
 
-       /*
-        * Skip leading white space
-        */
-       while (*cp == ' ' || *cp == '\t')
-           cp++;
-       
-       /*
-        * If this is the end of the line, return nothing.
-        */
-       if (*cp == '\n' || *cp == '\0') {
-               *lptr = cp;
-               return NULL;
-       }
-       
-       /*
-        * Must be the start of a token.  Record the pointer and look
-        * for the end.
-        */
-       tstart = cp++;
-       while (*cp != ' ' && *cp != '\t' && *cp != '\n' && *cp != '\0')
-           cp++;
-       
-       /*
-        * Terminate the token with a \0.  If this isn't the end of the
-        * line, space to the next character.
-        */
-       if (*cp == '\n' || *cp == '\0')
-           *cp = '\0';
-       else
-           *cp++ = '\0';
 
-       *lptr = cp;
-       return tstart;
+#ifdef TEST_BLOCKING_WORKER
+void gni_test_callback(int rescode, int gni_errno, sockaddr_u *psau, int flags, const char *host, const char *service, void *context)
+{
+       if (!rescode)
+               DPRINTF(1, ("gni_test_callback got host '%s' serv '%s' for addr %s context %p\n", 
+                           host, service, stoa(psau), context));
+       else
+               DPRINTF(1, ("gni_test_callback context %p rescode %d gni_errno %d flags 0x%x addr %s\n",
+                           context, rescode, gni_errno, flags, stoa(psau)));
 }
+#endif /* TEST_BLOCKING_WORKER */
 
 
-/*
- * readconf - read the configuration information out of the file we
- *           were passed.  Note that since the file is supposed to be
- *           machine generated, we bail out at the first sign of trouble.
- */
 static void
-readconf(
-       FILE *fp,
-       char *name
+scheduled_sleep(
+       time_t scheduled,
+       time_t earliest
        )
 {
-       register int i;
-       char *token[NUMTOK];
-       u_long intval[NUMTOK];
-       u_int flags;
-       char buf[MAXLINESIZE];
-       char *bp;
-
-       while (fgets(buf, MAXLINESIZE, fp) != NULL) {
-
-               bp = buf;
-               for (i = 0; i < NUMTOK; i++) {
-                       if ((token[i] = nexttoken(&bp)) == NULL) {
-                               msyslog(LOG_ERR,
-                                       "tokenizing error in file `%s', quitting",
-                                       name);
-                               resolver_exit(1);
-                       }
-               }
-
-               for (i = 1; i < NUMTOK - 1; i++) {
-                       if (!atouint(token[i], &intval[i])) {
-                               msyslog(LOG_ERR,
-                                       "format error for integer token `%s', file `%s', quitting",
-                                       token[i], name);
-                               resolver_exit(1);
-                       }
-               }
-
-#if 0 /* paranoid checking - these are done in newpeer() */
-               if (intval[TOK_HMODE] != MODE_ACTIVE &&
-                   intval[TOK_HMODE] != MODE_CLIENT &&
-                   intval[TOK_HMODE] != MODE_BROADCAST) {
-                       msyslog(LOG_ERR, "invalid mode (%ld) in file %s",
-                               intval[TOK_HMODE], name);
-                       resolver_exit(1);
-               }
+       time_t now;
 
-               if (intval[TOK_VERSION] > NTP_VERSION ||
-                   intval[TOK_VERSION] < NTP_OLDVERSION) {
-                       msyslog(LOG_ERR, "invalid version (%ld) in file %s",
-                               intval[TOK_VERSION], name);
-                       resolver_exit(1);
-               }
-               if (intval[TOK_MINPOLL] < ntp_minpoll ||
-                   intval[TOK_MINPOLL] > NTP_MAXPOLL) {
-
-                       msyslog(LOG_ERR, "invalid MINPOLL value (%ld) in file %s",
-                               intval[TOK_MINPOLL], name);
-                       resolver_exit(1);
-               }
-
-               if (intval[TOK_MAXPOLL] < ntp_minpoll ||
-                   intval[TOK_MAXPOLL] > NTP_MAXPOLL) {
-                       msyslog(LOG_ERR, "invalid MAXPOLL value (%ld) in file %s",
-                               intval[TOK_MAXPOLL], name);
-                       resolver_exit(1);
-               }
+       if (scheduled < ignore_scheduled_before) {
+               DPRINTF(1, ("ignoring sleep until %s scheduled at %s (before %s)",
+                       humantime(earliest), humantime(scheduled),
+                       humantime(ignore_scheduled_before)));
+               return;
+       }
 
-               if ((intval[TOK_FLAGS] & ~(FLAG_PREFER | FLAG_NOSELECT |
-                   FLAG_BURST | FLAG_IBURST | FLAG_SKEY)) != 0) {
-                       msyslog(LOG_ERR, "invalid flags (%ld) in file %s",
-                               intval[TOK_FLAGS], name);
-                       resolver_exit(1);
+       now = time(NULL);
+
+       if (now < earliest) {
+               DPRINTF(1, ("sleep until %s scheduled at %s (>= %s)",
+                       humantime(earliest), humantime(scheduled),
+                       humantime(ignore_scheduled_before)));
+               if (-1 == worker_sleep(earliest - now)) {
+                       /* our sleep was interrupted */
+                       now = time(NULL);
+                       ignore_scheduled_before = now;
+                       next_dns_timeslot = now;
+#ifdef HAVE_RES_INIT
+                       next_res_init = now + 60;
+                       res_init();
+#endif
+                       DPRINTF(1, ("sleep interrupted by daemon, ignoring sleeps scheduled before now (%s)",
+                               humantime(ignore_scheduled_before)));
                }
-#endif /* end paranoid checking */
-
-               flags = 0;
-               if (intval[TOK_FLAGS] & FLAG_PREFER)
-                   flags |= CONF_FLAG_PREFER;
-               if (intval[TOK_FLAGS] & FLAG_NOSELECT)
-                   flags |= CONF_FLAG_NOSELECT;
-               if (intval[TOK_FLAGS] & FLAG_BURST)
-                   flags |= CONF_FLAG_BURST;
-               if (intval[TOK_FLAGS] & FLAG_IBURST)
-                   flags |= CONF_FLAG_IBURST;
-
-#ifdef OPENSSL
-               if (intval[TOK_FLAGS] & FLAG_SKEY)
-                   flags |= CONF_FLAG_SKEY;
-#endif /* OPENSSL */
-
-               /*
-                * This is as good as we can check it.  Add it in.
-                */
-               addentry(token[TOK_HOSTNAME],
-                        (int)intval[TOK_NEEDED], (int)intval[TOK_TYPE],
-                        (int)intval[TOK_HMODE], (int)intval[TOK_VERSION],
-                        (int)intval[TOK_MINPOLL], (int)intval[TOK_MAXPOLL],
-                        flags, (int)intval[TOK_TTL],
-                        intval[TOK_KEYID], token[TOK_KEYSTR]);
        }
 }
 
 
 /*
- * doconfigure - attempt to resolve names and configure the server
+ * manage_dns_retry_interval is a helper used by
+ * getaddrinfo_sometime_complete and getnameinfo_sometime_complete
+ * to calculate the new retry interval and schedule the next query.
  */
 static void
-doconfigure(
-       int dores
+manage_dns_retry_interval(
+       time_t *        pscheduled,
+       time_t *        pwhen,
+       int *           pretry
        )
 {
-       register struct conf_entry *ce;
+       time_t  now;
+       time_t  when;
+       int     retry;
+               
+       now = time(NULL);
+       retry = *pretry;
+       when = max(now + retry, next_dns_timeslot);
+       next_dns_timeslot = when;
+       retry = min(64, retry << 1);
+
+       *pscheduled = now;
+       *pwhen = when;
+       *pretry = retry;
+}
 
-#ifdef DEBUG
-               if (debug > 1)
-                       msyslog(LOG_INFO, "Running doconfigure %s DNS",
-                           dores ? "with" : "without" );
-#endif
+/*
+ * should_retry_dns is a helper used by getaddrinfo_sometime_complete
+ * and getnameinfo_sometime_complete which implements ntpd's DNS retry
+ * policy.
+ */
+static int
+should_retry_dns(
+       int     rescode,
+       int     res_errno
+       )
+{
+       static int      eai_again_seen;
+       int             again;
 
-#if defined(HAVE_RES_INIT)
-       if (dores)         /* Reload /etc/resolv.conf - bug 1226 */
-               res_init();
-#endif
-       ce = confentries;
-       while (ce != NULL) {
-#ifdef DEBUG
-               if (debug > 1)
-                       msyslog(LOG_INFO,
-                           "doconfigure: <%s> has peeraddr %s",
-                           ce->ce_name, stoa(&ce->peer_store));
-#endif
-               if (dores && SOCK_UNSPEC(&ce->peer_store)) {
-                       if (!findhostaddr(ce)) {
-#ifndef IGNORE_DNS_ERRORS
-                               msyslog(LOG_ERR,
-                                       "couldn't resolve `%s', giving up on it",
-                                       ce->ce_name);
-                               ce = removeentry(ce);
-                               continue;
+       /*
+        * If the resolver failed, see if the failure is
+        * temporary. If so, return success.
+        */
+       again = 0;
+
+       switch (rescode) {
+
+       case EAI_FAIL:
+               again = 1;
+               break;
+
+       case EAI_AGAIN:
+               again = 1;
+               eai_again_seen = 1;             /* [Bug 1178] */
+               break;
+
+       case EAI_NONAME:
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+       case EAI_NODATA:
 #endif
-                       } else if (!SOCK_UNSPEC(&ce->peer_store))
-                               msyslog(LOG_INFO,
-                                       "DNS %s -> %s", ce->ce_name,
-                                       stoa(&ce->peer_store));
-               }
+               again = !eai_again_seen;        /* [Bug 1178] */
+               break;
 
-               if (!SOCK_UNSPEC(&ce->peer_store)) {
-                       if (request(&ce->ce_config)) {
-                               ce = removeentry(ce);
-                               continue;
-                       }
-                       /* 
-                        * Failed case.  Should bump counter and give 
-                        * up.
-                        */
-#ifdef DEBUG
-                       if (debug > 1) {
-                               msyslog(LOG_INFO,
-                                   "doconfigure: request() FAILED, maybe next time.");
-                       }
+#ifdef EAI_SYSTEM
+       case EAI_SYSTEM:
+               /* 
+                * EAI_SYSTEM means the real error is in errno.  We should be more
+                * discriminating about which errno values require retrying, but
+                * this matches existing behavior.
+                */
+               again = 1;
+               DPRINTF(1, ("intres: EAI_SYSTEM errno %d (%s) means try again, right?\n",
+                           res_errno, strerror(res_errno)));
+               break;
 #endif
-               }
-               ce = ce->ce_next;
        }
+
+       DPRINTF(2, ("intres: resolver returned: %s (%d), %sretrying\n",
+               gai_strerror(rescode), rescode, again ? "" : "not "));
+
+       return again;
 }
 
-#else  /* NO_INTRES follows */
+#else  /* !WORKER follows */
 int ntp_intres_nonempty_compilation_unit;
 #endif
index f15783951c685e1e102d5e390e1e78e90421e213..ba64bcc36c25a3233150832620d57dfe25f28e09 100644 (file)
@@ -174,6 +174,13 @@ static     struct refclockio *refio;
  */
 fd_set activefds;
 int maxactivefd;
+
+#ifndef HAVE_IO_COMPLETION_PORT
+static void    maintain_activefds(int fd, int closing);
+#else
+#define                maintain_activefds(fd, closing) do {} while (0)
+#endif
+
 /*
  * bit alternating value to detect verified interfaces during an update cycle
  */
@@ -185,7 +192,6 @@ static int          update_interfaces(u_short, interface_receiver_t, void *);
 static void            remove_interface(struct interface *);
 static struct interface *create_interface(u_short, struct interface *);
 
-static int     move_fd                 (SOCKET);
 static int     is_wildcard_addr        (sockaddr_u *);
 static int     is_wildcard_netaddr     (const isc_netaddr_t *);
 
@@ -301,6 +307,53 @@ static inline int     read_refclock_packet (SOCKET, struct refclockio *, l_fp);
 #endif
 
 
+
+#ifndef HAVE_IO_COMPLETION_PORT
+static void
+maintain_activefds(
+       int fd,
+       int closing
+       )
+{
+       int i;
+
+       if (fd < 0 || fd >= FD_SETSIZE) {
+               msyslog(LOG_ERR,
+                       "Too many sockets in use, FD_SETSIZE %d exceeded by fd %d",
+                       FD_SETSIZE, fd);
+               exit(1);
+       }
+
+       if (!closing) {
+               FD_SET(fd, &activefds);
+               maxactivefd = max(fd, maxactivefd);
+       } else {
+               FD_CLR(fd, &activefds);
+               if (maxactivefd && fd == maxactivefd) {
+                       for (i = maxactivefd - 1; i >= 0; i--)
+                               if (FD_ISSET(i, &activefds)) {
+                                       maxactivefd = i;
+                                       break;
+                               }
+                       NTP_INSIST(fd != maxactivefd);
+               }
+       }
+}
+#endif /* !HAVE_IO_COMPLETION_PORT */
+
+
+#ifdef WORK_FORK
+void
+update_resp_pipe_fd(
+       int resp_pipe_fd,
+       int closing
+       )
+{
+       maintain_activefds(resp_pipe_fd, closing);
+}
+#endif
+
+
 /*
  * on Unix systems the stdio library typically
  * makes use of file descriptors in the lower
@@ -314,7 +367,7 @@ static inline int     read_refclock_packet  (SOCKET, struct refclockio *, l_fp);
  * and may exceed to current file decriptor limits.
  * We are using following strategy:
  * - keep a current socket fd boundary initialized with
- *   max(0, min(getdtablesize() - FD_CHUNK, FOPEN_MAX))
+ *   max(0, min(GETDTABLESIZE() - FD_CHUNK, FOPEN_MAX))
  * - attempt to move the descriptor to the boundary or
  *   above.
  *   - if that fails and boundary > 0 set boundary
@@ -330,7 +383,7 @@ static inline int     read_refclock_packet  (SOCKET, struct refclockio *, l_fp);
  *     allocation is possible or 0 is reached - at this
  *     point the algrithm will be disabled
  */
-static int
+SOCKET
 move_fd(
        SOCKET fd
        )
@@ -339,6 +392,9 @@ move_fd(
 #ifndef FD_CHUNK
 #define FD_CHUNK       10
 #endif
+#ifndef FOPEN_MAX
+#define FOPEN_MAX      20
+#endif
 /*
  * number of fds we would like to have for
  * stdio FILE* available.
@@ -352,17 +408,16 @@ move_fd(
 #define FD_PREFERRED_SOCKBOUNDARY 48
 #endif
 
-#ifndef HAVE_GETDTABLESIZE
+#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
+#define GETDTABLESIZE()        ((int)sysconf(_SC_OPEN_MAX))
+#elif !defined(HAVE_GETDTABLESIZE)
 /*
  * if we have no idea about the max fd value set up things
  * so we will start at FOPEN_MAX
  */
-#define getdtablesize() (FOPEN_MAX+FD_CHUNK)
+#define GETDTABLESIZE()        (FOPEN_MAX + FD_CHUNK)
 #endif
 
-#ifndef FOPEN_MAX
-#define FOPEN_MAX      20      /* assume that for the lack of anything better */
-#endif
        static SOCKET socket_boundary = -1;
        SOCKET newfd;
 
@@ -373,12 +428,12 @@ move_fd(
         * already
         */
        if (socket_boundary == -1) {
-               socket_boundary = max(0, min(getdtablesize() - FD_CHUNK, 
+               socket_boundary = max(0, min(GETDTABLESIZE() - FD_CHUNK, 
                                             min(FOPEN_MAX, FD_PREFERRED_SOCKBOUNDARY)));
 #ifdef DEBUG
                msyslog(LOG_DEBUG,
                        "ntp_io: estimated max descriptors: %d, initial socket boundary: %d",
-                       getdtablesize(), socket_boundary);
+                       GETDTABLESIZE(), socket_boundary);
 #endif
        }
 
@@ -413,10 +468,45 @@ move_fd(
        return fd;
 }
 
+
+#ifndef HAVE_IO_COMPLETION_PORT
+/*
+ * close_all_beyond()
+ *
+ * Close all file descriptors after the given keep_fd, which is the
+ * highest fd to keep open.
+ */
+void
+close_all_beyond(
+       int keep_fd
+       )
+{
+# ifdef HAVE_CLOSEFROM
+       closefrom(keep_fd + 1);
+# elif defined(F_CLOSEM)
+       /*
+        * From 'Writing Reliable AIX Daemons,' SG24-4946-00,
+        * by Eric Agar (saves us from doing 32767 system
+        * calls)
+        */
+       if (fcntl(keep_fd + 1, F_CLOSEM, 0) == -1)
+               msyslog(LOG_ERR, "F_CLOSEM(%d): %m", keep_fd + 1);
+# else /* !HAVE_CLOSEFROM && !F_CLOSEM follows */
+       int fd;
+       int max_fd;
+
+       max_fd = GETDTABLESIZE();
+       for (fd = keep_fd + 1; fd < max_fd; fd++)
+               close(fd);
+# endif        /* !HAVE_CLOSEFROM && !F_CLOSEM */
+}
+#endif /* HAVE_IO_COMPLETION_PORT */
+
+
 #ifdef DEBUG_TIMING
 /*
  * collect timing information for various processing
- * paths. currently we only pass then on to the file
+ * paths. currently we only pass them on to the file
  * for later processing. this could also do histogram
  * based analysis in other to reduce the load (and skew)
  * dur to the file output
@@ -487,7 +577,7 @@ init_io(void)
 
 #ifdef SYS_WINNT
        init_io_completion_port();
-#endif /* SYS_WINNT */
+#endif
 
 #if defined(HAVE_SIGNALED_IO)
        (void) set_signal();
@@ -691,26 +781,30 @@ is_ip_address(
         * addresses (up to 46 bytes), the delimiter character and the
         * terminating NULL character.
         */
-       if (inet_pton(AF_INET, host, &in4) == 1) {
-               isc_netaddr_fromin(addr, &in4);
-               return (ISC_TRUE);
-       } else if (sizeof(tmpbuf) > strlen(host)) {
-               if ('[' == host[0]) {
-                       strncpy(tmpbuf, &host[1], sizeof(tmpbuf));
-                       pch = strchr(tmpbuf, ']');
+       if (AF_UNSPEC == addr->family || AF_INET == addr->family)
+               if (inet_pton(AF_INET, host, &in4) == 1) {
+                       isc_netaddr_fromin(addr, &in4);
+                       return (ISC_TRUE);
+               }
+
+       if (AF_UNSPEC == addr->family || AF_INET6 == addr->family)
+               if (sizeof(tmpbuf) > strlen(host)) {
+                       if ('[' == host[0]) {
+                               strncpy(tmpbuf, &host[1], sizeof(tmpbuf));
+                               pch = strchr(tmpbuf, ']');
+                               if (pch != NULL)
+                                       *pch = '\0';
+                       } else
+                               strncpy(tmpbuf, host, sizeof(tmpbuf));
+                       pch = strchr(tmpbuf, '%');
                        if (pch != NULL)
                                *pch = '\0';
-               } else
-                       strncpy(tmpbuf, host, sizeof(tmpbuf));
-               pch = strchr(tmpbuf, '%');
-               if (pch != NULL)
-                       *pch = '\0';
-
-               if (inet_pton(AF_INET6, tmpbuf, &in6) == 1) {
-                       isc_netaddr_fromin6(addr, &in6);
-                       return (ISC_TRUE);
+
+                       if (inet_pton(AF_INET6, tmpbuf, &in6) == 1) {
+                               isc_netaddr_fromin6(addr, &in6);
+                               return (ISC_TRUE);
+                       }
                }
-       }
        /*
         * If we got here it was not an IP address
         */
@@ -1334,14 +1428,7 @@ interface_update(
 #ifdef DEBUG
        msyslog(LOG_DEBUG, "new interface(s) found: waking up resolver");
 #endif
-#ifdef SYS_WINNT
-       /* wake up the resolver thread */
-       if (ResolverEventHandle != NULL)
-               SetEvent(ResolverEventHandle);
-#else
-       /* write any single byte to the pipe to wake up the resolver process */
-       write( resolver_pipe_fd[1], &new_interface_found, 1 );
-#endif
+       interrupt_worker_sleep();
 }
 
 
@@ -3323,6 +3410,15 @@ input_handler(
        }
 #endif /* HAS_ROUTING_SOCKET */
        
+       /*
+        * Check for a response from the blocking child
+        */
+       if (parent_resp_read_pipe &&
+           FD_ISSET(parent_resp_read_pipe, &fds)) {
+               select_count++;
+               process_blocking_response();
+       }
+
        /*
         * Done everything from that select.
         */
@@ -3831,23 +3927,7 @@ add_fd_to_list(
        lsock->type = type;
 
        LINK_SLIST(fd_list, lsock, link);
-       /*
-        * I/O Completion Ports don't care about the select and FD_SET
-        */
-#ifndef HAVE_IO_COMPLETION_PORT
-       if (fd < 0 || fd >= FD_SETSIZE) {
-               msyslog(LOG_ERR,
-                       "Too many sockets in use, FD_SETSIZE %d exceeded",
-                       FD_SETSIZE);
-               exit(1);
-       }
-       /*
-        * keep activefds in sync
-        */
-       maxactivefd = max(fd, maxactivefd);
-
-       FD_SET(fd, &activefds);
-#endif
+       maintain_activefds(fd, 0);
 }
 
 static void
@@ -3878,26 +3958,10 @@ close_and_delete_fd_from_list(
                }
 
                free(lsock);
-               /*
-                * I/O Completion Ports don't care about select and fd_set
-                */
-#ifndef HAVE_IO_COMPLETION_PORT
                /*
                 * remove from activefds
                 */
-               FD_CLR(fd, &activefds);
-               
-               if (fd == maxactivefd && maxactivefd) {
-                       int i;
-                       NTP_INSIST(maxactivefd - 1 < FD_SETSIZE);
-                       for (i = maxactivefd - 1; i >= 0; i--)
-                               if (FD_ISSET(i, &activefds)) {
-                                       maxactivefd = i;
-                                       break;
-                               }
-                       NTP_INSIST(fd != maxactivefd);
-               }
-#endif
+               maintain_activefds(fd, 1);
        }
 }
 
index d5a1206d06a24218df4b85ba1b9c16f521763132..626ea3ddef2283fa279a9f97ae23846b349c5a0d 100644 (file)
 #include <openssl/rand.h>
 #endif /* OPENSSL */
 
+
+/* TC_ERR represents the timer_create() error return value. */
+#ifdef SYS_VXWORKS
+#define        TC_ERR  ERROR
+#else
+#define        TC_ERR  (-1)
+#endif
+
 /*
- * These routines provide support for the event timer. The timer is
+ * These routines provide support for the event timer.  The timer is
  * implemented by an interrupt routine which sets a flag once every
- * 2**EVENT_TIMEOUT seconds (currently 4), and a timer routine which
- * is called when the mainline code gets around to seeing the flag.
- * The timer routine dispatches the clock adjustment code if its time
- * has come, then searches the timer queue for expiries which are
- * dispatched to the transmit procedure.  Finally, we call the hourly
- * procedure to do cleanup and print a message.
+ * second, and a timer routine which is called when the mainline code
+ * gets around to seeing the flag.  The timer routine dispatches the
+ * clock adjustment code if its time has come, then searches the timer
+ * queue for expiries which are dispatched to the transmit procedure.
+ * Finally, we call the hourly procedure to do cleanup and print a
+ * message.
  */
 volatile int interface_interval = 300;     /* update interface every 5 minutes as default */
          
@@ -56,7 +64,7 @@ static        u_long adjust_timer;    /* second timer */
 static u_long stats_timer;     /* stats timer */
 static u_long huffpuff_timer;  /* huff-n'-puff timer */
 u_long leapsec;                /* leapseconds countdown */
-l_fp   sys_time;               /* current system time */
+u_long worker_idle_timer;      /* next check for idle intres */
 #ifdef OPENSSL
 static u_long revoke_timer;    /* keys revoke timer */
 static u_long keys_timer;      /* session key timer */
@@ -95,24 +103,24 @@ static     RETSIGTYPE alarming (int);
 
 #if !defined(VMS)
 # if !defined SYS_WINNT || defined(SYS_CYGWIN32)
-#  ifndef HAVE_TIMER_SETTIME
-       struct itimerval itimer;
-#  else 
-       static timer_t ntpd_timerid;
+#  ifdef HAVE_TIMER_CREATE
+       static timer_t timer_id;
        struct itimerspec itimer;
-#  endif /* HAVE_TIMER_SETTIME */
-# endif /* SYS_WINNT */
-#endif /* VMS */
+#  else 
+       struct itimerval itimer;
+#  endif
+# endif
+#endif
 
 /*
- * reinit_timer - reinitialize interval timer.
+ * reinit_timer - reinitialize interval timer after a clock step.
  */
 void 
 reinit_timer(void)
 {
 #if !defined(SYS_WINNT) && !defined(VMS)
-#  if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME)
-       timer_gettime(ntpd_timerid, &itimer);
+#  ifdef HAVE_TIMER_CREATE
+       timer_gettime(timer_id, &itimer);
        if (itimer.it_value.tv_sec < 0 || itimer.it_value.tv_sec > (1<<EVENT_TIMEOUT)) {
                itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
        }
@@ -125,7 +133,7 @@ reinit_timer(void)
        }
        itimer.it_interval.tv_sec = (1<<EVENT_TIMEOUT);
        itimer.it_interval.tv_nsec = 0;
-       timer_settime(ntpd_timerid, 0 /*!TIMER_ABSTIME*/, &itimer, NULL);
+       timer_settime(timer_id, 0 /*!TIMER_ABSTIME*/, &itimer, NULL);
 #  else
        getitimer(ITIMER_REAL, &itimer);
        if (itimer.it_value.tv_sec < 0 || itimer.it_value.tv_sec > (1<<EVENT_TIMEOUT)) {
@@ -165,36 +173,29 @@ init_timer(void)
        timer_xmtcalls = 0;
        timer_timereset = 0;
 
-#if !defined(SYS_WINNT)
+#ifndef SYS_WINNT
        /*
         * Set up the alarm interrupt.  The first comes 2**EVENT_TIMEOUT
         * seconds from now and they continue on every 2**EVENT_TIMEOUT
         * seconds.
         */
-# if !defined(VMS)
-#  if defined(HAVE_TIMER_CREATE) && defined(HAVE_TIMER_SETTIME)
-       if (timer_create (CLOCK_REALTIME, NULL, &ntpd_timerid) ==
-#      ifdef SYS_VXWORKS
-               ERROR
-#      else
-               -1
-#      endif
-          )
-       {
+# ifndef VMS
+#  ifdef HAVE_TIMER_CREATE
+       if (timer_create(CLOCK_REALTIME, NULL, &timer_id) == TC_ERR) {
                fprintf (stderr, "timer create FAILED\n");
                exit (0);
        }
        (void) signal_no_reset(SIGALRM, alarming);
        itimer.it_interval.tv_sec = itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
        itimer.it_interval.tv_nsec = itimer.it_value.tv_nsec = 0;
-       timer_settime(ntpd_timerid, 0 /*!TIMER_ABSTIME*/, &itimer, NULL);
+       timer_settime(timer_id, 0 /*!TIMER_ABSTIME*/, &itimer, NULL);
 #  else
        (void) signal_no_reset(SIGALRM, alarming);
        itimer.it_interval.tv_sec = itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
        itimer.it_interval.tv_usec = itimer.it_value.tv_usec = 0;
        setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
 #  endif
-# else /* VMS */
+# else /* VMS follows */
        vmsinc[0] = 10000000;           /* 1 sec */
        vmsinc[1] = 0;
        lib$emul(&(1<<EVENT_TIMEOUT), &vmsinc, &0, &vmsinc);
@@ -203,8 +204,8 @@ init_timer(void)
 
        lib$addx(&vmsinc, &vmstimer, &vmstimer);
        sys$setimr(0, &vmstimer, alarming, alarming, 0);
-# endif /* VMS */
-#else /* SYS_WINNT */
+# endif        /* VMS */
+#else  /* SYS_WINNT follows */
        /*
         * Set up timer interrupts for every 2**EVENT_TIMEOUT seconds
         * Under Windows/NT, 
@@ -225,9 +226,10 @@ init_timer(void)
                }
        }
 
-#endif /* SYS_WINNT */
+#endif /* SYS_WINNT */
 }
 
+
 #if defined(SYS_WINNT)
 extern HANDLE 
 get_timer_handle(void)
@@ -236,6 +238,7 @@ get_timer_handle(void)
 }
 #endif
 
+
 /*
  * timer - event timer
  */
@@ -244,15 +247,14 @@ timer(void)
 {
        register struct peer *peer, *next_peer;
        u_int   n;
+       l_fp    now;
 
        /*
-        * The basic timerevent is one second. This is used to adjust
-        * the system clock in time and frequency, implement the
-        * kiss-o'-deatch function and implement the association
-        * polling function..
+        * The basic timerevent is one second.  This is used to adjust the
+        * system clock in time and frequency, implement the kiss-o'-death
+        * function and the association polling function.
         */
        current_time++;
-       get_systime(&sys_time);
        if (adjust_timer <= current_time) {
                adjust_timer += 1;
                adj_host_clock();
@@ -372,9 +374,8 @@ timer(void)
        }
 
        /*
-        * Garbage collect key list and generate new private value. The
-        * timer runs only after initial synchronization and fires about
-        * once per day.
+        * Generate new private value. The timer runs only after
+        * initial synchronization and fires about once per day.
         */
        if (revoke_timer <= current_time && sys_leap !=
            LEAP_NOTINSYNC) {
@@ -393,15 +394,21 @@ timer(void)
                DPRINTF(2, ("timer: interface update\n"));
                interface_update(NULL, NULL);
        }
-       
+
+       if (worker_idle_timer && worker_idle_timer <= current_time)
+               worker_idle_timer_fired();
+
        /*
         * Finally, write hourly stats.
         */
        if (stats_timer <= current_time) {
                stats_timer += HOUR;
                write_stats();
-               if (sys_tai != 0 && sys_time.l_ui > leap_expire)
-                       report_event(EVNT_LEAPVAL, NULL, NULL);
+               if (sys_tai != 0) {
+                       get_systime(&now);
+                       if (now.l_ui > leap_expire)
+                               report_event(EVNT_LEAPVAL, NULL, NULL);
+               }
        }
 }
 
diff --git a/ntpd/ntp_worker.c b/ntpd/ntp_worker.c
new file mode 100644 (file)
index 0000000..b4d8168
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * ntp_worker.c
+ */
+#include <config.h>
+#include "ntp_workimpl.h"
+
+#ifdef WORKER
+
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include "iosignal.h"
+#include "ntp_stdlib.h"
+#include "ntp_malloc.h"
+#include "ntp_syslog.h"
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_assert.h"
+#include "ntp_unixtime.h"
+#include "ntp_intres.h"
+
+
+#define CHILD_MAX_IDLE 15      /* seconds, idle worker limit */
+
+int    intres_req_pending;
+
+
+int
+queue_blocking_request(
+       blocking_work_req       rtype,
+       void *                  req,
+       size_t                  reqsize,
+       blocking_work_callback  done_func,
+       void *                  context
+       )
+{
+       blocking_pipe_header req_hdr;
+
+       req_hdr.octets = sizeof(req_hdr) + reqsize;
+       req_hdr.magic_sig = BLOCKING_REQ_MAGIC;
+       req_hdr.rtype = rtype;
+       req_hdr.done_func = done_func;
+       req_hdr.context = context;
+
+       if (0 == intres_req_pending)
+               worker_idle_timer = 0;
+       intres_req_pending++;
+
+       return send_blocking_req_internal(&req_hdr, req);
+}
+
+int queue_blocking_response(
+       blocking_pipe_header *          resp,
+       size_t                          respsize,
+       const blocking_pipe_header *    req
+       )
+{
+       resp->octets = respsize;
+       resp->magic_sig = BLOCKING_RESP_MAGIC;
+       resp->rtype = req->rtype;
+       resp->context = req->context;
+       resp->done_func = req->done_func;
+
+       return send_blocking_resp_internal(resp);
+}
+
+
+void
+process_blocking_response(
+       void
+       )
+{
+       blocking_pipe_header *  resp;
+       void *                  data;
+
+       /*
+        * On Windows send_blocking_resp_internal() may signal the
+        * blocking_response_ready event multiple times while we're
+        * processing a response, so always consume all available
+        * responses before returning to test the event again.
+        */
+#ifdef SYS_WINNT
+       do {
+#endif
+               resp = receive_blocking_resp_internal();
+               if (NULL != resp) {
+                       NTP_REQUIRE(BLOCKING_RESP_MAGIC == resp->magic_sig);
+                       data = (char *)resp + sizeof(*resp);
+                       intres_req_pending--;
+                       (*resp->done_func)(resp->rtype, resp->context, resp->octets - sizeof(*resp), data);
+                       free(resp);
+                       if (0 == intres_req_pending)
+                               worker_idle_timer = current_time 
+                                                   + CHILD_MAX_IDLE;
+               }
+#ifdef SYS_WINNT
+       } while (NULL != resp);
+#endif
+}
+
+
+/*
+ * blocking_child_common runs as a forked child or thread
+ */
+int
+blocking_child_common (
+       void
+       )
+{
+       int say_bye;
+       blocking_pipe_header *req;
+
+       NLOG(NLOG_SYSEVENT)
+               msyslog(LOG_NOTICE, "DNS worker started");
+
+       say_bye = 0;
+       while (!say_bye) {
+               req = receive_blocking_req_internal();
+               if (NULL == req) {
+                       say_bye = 1;
+                       break;
+               }
+
+               NTP_REQUIRE(BLOCKING_REQ_MAGIC == req->magic_sig);
+
+               switch (req->rtype) {
+               case BLOCKING_GETADDRINFO:
+                       if (blocking_getaddrinfo(req))
+                               say_bye = 1;
+                       break;
+
+               case BLOCKING_GETNAMEINFO:
+                       if (blocking_getnameinfo(req))
+                               say_bye = 1;
+                       break;
+
+               default:
+                       msyslog(LOG_ERR, "unknown req %d to blocking worker", req->rtype);
+                       say_bye = 1;
+               }
+               
+               free(req);
+       }
+
+       NLOG(NLOG_SYSEVENT)
+               msyslog(LOG_NOTICE, "DNS worker finished");
+
+       return 0;
+}
+
+
+#else  /* !WORKER follows */
+int ntp_worker_nonempty_compilation_unit;
+#endif
index 040a48a0dbafe2d60cbc56875b0a2b46a8c6506f..1f33dcb984708219f1a438702db7d947c5627a8e 100644 (file)
@@ -13,7 +13,7 @@
 #include <ntp_random.h>
 
 #include "ntp_syslog.h"
-#include "isc/assertions.h"
+#include "ntp_assert.h"
 #include "isc/error.h"
 #include "isc/strerror.h"
 #include "isc/formatcheck.h"
@@ -153,7 +153,6 @@ volatile int debug = 0;             /* No debugging by default */
 #endif
 
 int    listen_to_virtual_ips = 1;
-const char *specific_interface = NULL;        /* interface name or IP address to bind to */
 
 /*
  * No-fork flag.  If set, we do not become a background daemon.
@@ -171,7 +170,8 @@ int mdnstries = 5;
 #endif  /* HAVE_DNSREGISTRATION */
 
 #ifdef HAVE_DROPROOT
-int droproot = 0;
+int droproot;
+int root_dropped;
 char *user = NULL;             /* User to switch to */
 char *group = NULL;            /* group to switch to */
 const char *chrootdir = NULL;  /* directory to chroot to */
@@ -221,7 +221,7 @@ static      RETSIGTYPE      no_debug        (int);
 int            ntpdmain                (int, char **);
 static void    set_process_priority    (void);
 void           init_logging            (char const *, int);
-void           setup_logfile           (void);
+void           setup_logfile           (int);
 
 static void    assertion_failed        (const char *file, int line,
        isc_assertiontype_t type, const char *cond);
@@ -233,15 +233,30 @@ static void       library_unexpected_error(const char *file, int line,
 
 /*
  * Initialize the logging
+ *
+ * Called once per process, including forked children.
  */
 void
 init_logging(
-       char const *name,
+       const char *name,
        int log_version
        )
 {
        const char *cp;
 
+       /*
+        * ntpd defaults to only logging sync-category events, when
+        * NLOG() is used to conditionalize.  Other libntp clients
+        * leave it alone so that all NLOG() conditionals will fire.
+        * This presumes all bits lit in ntp_syslogmask can't be
+        * configured via logconfig and all lit is thereby a sentinel
+        * that ntp_syslogmask is still at its default from libntp,
+        * keeping in mind this function is called in forked children
+        * where it has already been called in the parent earlier.
+        */
+       if (~(u_long)0 == ntp_syslogmask)
+               ntp_syslogmask = NLOG_SYNCMASK; /* set more via logconfig */
+
        /*
         * Logging.  This may actually work on the gizmo board.  Find a name
         * to log with by using the basename
@@ -251,17 +266,18 @@ init_logging(
                cp = name;
        else
                cp++;
+       progname = cp;
 
 #if !defined(VMS)
 
 # ifndef LOG_DAEMON
-       openlog(cp, LOG_PID);
+       openlog(progname, LOG_PID);
 # else /* LOG_DAEMON */
 
 #  ifndef LOG_NTP
 #      define  LOG_NTP LOG_DAEMON
 #  endif
-       openlog(cp, LOG_PID | LOG_NDELAY, LOG_NTP);
+       openlog(progname, LOG_PID | LOG_NDELAY, LOG_NTP);
 #  ifdef DEBUG
        if (debug)
                setlogmask(LOG_UPTO(LOG_DEBUG));
@@ -272,45 +288,144 @@ init_logging(
 #endif /* !VMS */
 
        if (log_version)
-           NLOG(NLOG_SYSINFO) /* 'if' clause for syslog */
                msyslog(LOG_NOTICE, "%s", Version);
 }
 
 
 /*
- * Redirect logging to a file if requested with -l.
- * The ntp.conf logfile directive does not use this code, see
- * config_vars() in ntp_config.c.
+ * change_logfile()
+ *
+ * Used to change from syslog to a logfile, or from one logfile to
+ * another, and to reopen logfiles after forking.  On systems where
+ * ntpd forks, deals with converting relative logfile paths to
+ * absolute (root-based) because we reopen logfiles after the current
+ * directory has changed.
+ */
+int
+change_logfile(
+       const char *fname,
+       int log_version
+       )
+{
+       FILE *          new_file;
+       const char *    log_fname;
+       char *          abs_fname;
+#if !defined(SYS_WINNT) && !defined(SYS_VXWORKS) && !defined(VMS)
+       char            curdir[512];
+       size_t          cd_octets;
+       size_t          octets;
+#endif /* POSIX */
+
+       NTP_REQUIRE(fname != NULL);
+       log_fname = fname;
+
+       /*
+        * In a forked child of a parent which is logging to a file
+        * instead of syslog, syslog_file will be NULL and both
+        * syslog_fname and syslog_abs_fname will be non-NULL.
+        * If we are given the same filename previously opened
+        * and it's still open, there's nothing to do here.
+        */
+       if (syslog_file != NULL && syslog_fname != NULL &&
+           (log_fname == syslog_fname ||
+            0 == strcmp(syslog_fname, log_fname)))
+               return 0;
+
+       if (0 == strcmp(log_fname, "stderr")) {
+               new_file = stderr;
+               abs_fname = estrdup(log_fname);
+       } else if (0 == strcmp(log_fname, "stdout")) {
+               new_file = stdout;
+               abs_fname = estrdup(log_fname);
+       } else {
+               if (syslog_fname != NULL &&
+                   0 == strcmp(log_fname, syslog_fname))
+                       log_fname = syslog_abs_fname;
+#if !defined(SYS_WINNT) && !defined(SYS_VXWORKS) && !defined(VMS)
+               if (log_fname != syslog_abs_fname &&
+                   DIR_SEP != log_fname[0] &&
+                   0 != strcmp(log_fname, "stderr") &&
+                   0 != strcmp(log_fname, "stdout") &&
+                   NULL != getcwd(curdir, sizeof(curdir))) {
+                       cd_octets = strlen(curdir);
+                       /* trim any trailing '/' */
+                       if (cd_octets > 1 &&
+                           DIR_SEP == curdir[cd_octets - 1])
+                               cd_octets--;
+                       octets = cd_octets;
+                       octets += 1;    /* separator '/' */
+                       octets += strlen(syslog_fname);
+                       octets += 1;    /* NUL terminator */
+                       abs_fname = emalloc(octets);
+                       snprintf(abs_fname, octets, "%.*s%c%s",
+                                cd_octets, curdir, DIR_SEP,
+                                syslog_fname);
+               } else
+#endif
+                       abs_fname = estrdup(log_fname);
+               msyslog(LOG_INFO, "attempting to open log %s", abs_fname);
+               new_file = fopen(abs_fname, "a");
+       }
+
+       if (NULL == new_file)
+               return -1;
+
+       /* leave a pointer in the old log */
+       if (log_fname != syslog_abs_fname)
+               msyslog(LOG_NOTICE, "switching logging to file %s",
+                       abs_fname);
+
+       if (syslog_file != NULL &&
+           syslog_file != stderr && syslog_file != stdout &&
+           fileno(syslog_file) != fileno(new_file))
+               fclose(syslog_file);
+       syslog_file = new_file;
+       if (log_fname != syslog_abs_fname) {
+               if (syslog_abs_fname != NULL &&
+                   syslog_abs_fname != syslog_fname)
+                       free(syslog_abs_fname);
+               if (syslog_fname != NULL)
+                       free(syslog_fname);
+               syslog_fname = estrdup(log_fname);
+               syslog_abs_fname = abs_fname;
+       }
+       syslogit = 0;
+       if (log_version)
+               msyslog(LOG_NOTICE, "%s", Version);
+
+       return 0;
+}
+
+
+/*
+ * setup_logfile()
+ *
+ * Redirect logging to a file if requested with -l/--logfile or via
+ * ntp.conf logfile directive.
+ *
+ * This routine is invoked three different times in the sequence of a
+ * typical daemon ntpd with DNS lookups to do.  First it is invoked in
+ * the original ntpd process, then again in the daemon after closing
+ * all descriptors.  In both of those cases, ntp.conf has not been
+ * processed, so only -l/--logfile will trigger logfile redirection in
+ * those invocations.  Finally, if DNS names are resolved, the worker
+ * child invokes this routine after its fork and close of all
+ * descriptors.  In this case, ntp.conf has been processed and any
+ * "logfile" directive needs to be honored in the child as well.
  */
 void
 setup_logfile(
-       void
+       int log_version
        )
 {
-       if (HAVE_OPT( LOGFILE )) {
-               const char *my_optarg = OPT_ARG( LOGFILE );
-               FILE *new_file;
-
-               if(strcmp(my_optarg, "stderr") == 0)
-                       new_file = stderr;
-               else if(strcmp(my_optarg, "stdout") == 0)
-                       new_file = stdout;
-               else
-                       new_file = fopen(my_optarg, "a");
-               if (new_file != NULL) {
-                       NLOG(NLOG_SYSINFO)
-                               msyslog(LOG_NOTICE, "logging to file %s", my_optarg);
-                       if (syslog_file != NULL &&
-                               fileno(syslog_file) != fileno(new_file))
-                               (void)fclose(syslog_file);
-
-                       syslog_file = new_file;
-                       syslogit = 0;
-               }
-               else
-                       msyslog(LOG_ERR,
-                               "Cannot open log file %s",
-                               my_optarg);
+       if (NULL == syslog_fname && HAVE_OPT(LOGFILE)) {
+               if (-1 == change_logfile(OPT_ARG(LOGFILE), log_version))
+                       msyslog(LOG_ERR, "Cannot open log file %s, %m",
+                               OPT_ARG(LOGFILE));
+       } else if (NULL != syslog_fname) {
+               if (-1 == change_logfile(syslog_fname, log_version))
+                       msyslog(LOG_ERR, "Cannot reopen log file %s, %m",
+                               syslog_fname);
        }
 }
 
@@ -503,6 +618,14 @@ ntpdmain(
        parse_cmdline_opts(&argc, &argv);
        init_logging(progname, 1);      /* Open the log file */
 
+       /*
+        * Install trap handlers to log errors and assertion failures.
+        * Default handlers print to stderr which doesn't work if detached.
+        */
+       isc_assertion_setcallback(assertion_failed);
+       isc_error_setfatal(library_fatal_error);
+       isc_error_setunexpected(library_unexpected_error);
+
 #ifdef HAVE_UMASK
        {
                mode_t uv;
@@ -534,7 +657,7 @@ ntpdmain(
 #endif
 
        /* honor -l/--logfile option to log to a file */
-       setup_logfile();
+       setup_logfile(1);
 
 /*
  * Enable the Multi-Media Timer for Windows?
@@ -604,15 +727,6 @@ ntpdmain(
         */
        if (!nofork) {
 
-               /*
-                * Install trap handlers to log errors and assertion
-                * failures.  Default handlers print to stderr which 
-                * doesn't work if detached.
-                */
-               isc_assertion_setcallback(assertion_failed);
-               isc_error_setfatal(library_fatal_error);
-               isc_error_setunexpected(library_unexpected_error);
-
 #  ifndef SYS_WINNT
 #   ifdef HAVE_DAEMON
                daemon(0, 0);
@@ -620,86 +734,63 @@ ntpdmain(
                if (fork())     /* HMS: What about a -1? */
                        exit(0);
 
-               {
-#if !defined(F_CLOSEM)
-                       u_long s;
-                       int max_fd;
-#endif /* !FCLOSEM */
-                       if (syslog_file != NULL) {
-                               fclose(syslog_file);
-                               syslog_file = NULL;
-                       }
-#if defined(F_CLOSEM)
-                       /*
-                        * From 'Writing Reliable AIX Daemons,' SG24-4946-00,
-                        * by Eric Agar (saves us from doing 32767 system
-                        * calls)
-                        */
-                       if (fcntl(0, F_CLOSEM, 0) == -1)
-                           msyslog(LOG_ERR, "ntpd: failed to close open files(): %m");
-#else  /* not F_CLOSEM */
-
-# if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
-                       max_fd = sysconf(_SC_OPEN_MAX);
-# else /* HAVE_SYSCONF && _SC_OPEN_MAX */
-                       max_fd = getdtablesize();
-# endif /* HAVE_SYSCONF && _SC_OPEN_MAX */
-                       for (s = 0; s < max_fd; s++)
-                               (void) close((int)s);
-#endif /* not F_CLOSEM */
-                       (void) open("/", 0);
-                       (void) dup2(0, 1);
-                       (void) dup2(0, 2);
-
-                       init_logging(progname, 0);
-                       /* we lost our logfile (if any) daemonizing */
-                       setup_logfile();
+               if (syslog_file != NULL) {
+                       fclose(syslog_file);
+                       syslog_file = NULL;
+                       syslogit = 1;
+               }
+               close_all_beyond(-1);
+               open("/", 0);
+               dup2(0, 1);
+               dup2(0, 2);
+
+               init_logging(progname, 0);
+               /* we lost our logfile (if any) daemonizing */
+               setup_logfile(0);
 
 #ifdef SYS_DOMAINOS
-                       {
-                               uid_$t puid;
-                               status_$t st;
+               {
+                       uid_$t puid;
+                       status_$t st;
 
-                               proc2_$who_am_i(&puid);
-                               proc2_$make_server(&puid, &st);
-                       }
+                       proc2_$who_am_i(&puid);
+                       proc2_$make_server(&puid, &st);
+               }
 #endif /* SYS_DOMAINOS */
 #if defined(HAVE_SETPGID) || defined(HAVE_SETSID)
 # ifdef HAVE_SETSID
-                       if (setsid() == (pid_t)-1)
-                               msyslog(LOG_ERR, "ntpd: setsid(): %m");
+               if (setsid() == (pid_t)-1)
+                       msyslog(LOG_ERR, "ntpd: setsid(): %m");
 # else
-                       if (setpgid(0, 0) == -1)
-                               msyslog(LOG_ERR, "ntpd: setpgid(): %m");
+               if (setpgid(0, 0) == -1)
+                       msyslog(LOG_ERR, "ntpd: setpgid(): %m");
 # endif
 #else /* HAVE_SETPGID || HAVE_SETSID */
-                       {
+               {
 # if defined(TIOCNOTTY)
-                               int fid;
+                       int fid;
 
-                               fid = open("/dev/tty", 2);
-                               if (fid >= 0)
-                               {
-                                       (void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0);
-                                       (void) close(fid);
-                               }
+                       fid = open("/dev/tty", 2);
+                       if (fid >= 0) {
+                               ioctl(fid, (u_long) TIOCNOTTY, (char *) 0);
+                               close(fid);
+                       }
 # endif /* defined(TIOCNOTTY) */
 # ifdef HAVE_SETPGRP_0
-                               (void) setpgrp();
+                       setpgrp();
 # else /* HAVE_SETPGRP_0 */
-                               (void) setpgrp(0, getpid());
+                       setpgrp(0, getpid());
 # endif /* HAVE_SETPGRP_0 */
-                       }
+               }
 #endif /* HAVE_SETPGID || HAVE_SETSID */
 #ifdef _AIX
-                       /* Don't get killed by low-on-memory signal. */
-                       sa.sa_handler = catch_danger;
-                       sigemptyset(&sa.sa_mask);
-                       sa.sa_flags = SA_RESTART;
+               /* Don't get killed by low-on-memory signal. */
+               sa.sa_handler = catch_danger;
+               sigemptyset(&sa.sa_mask);
+               sa.sa_flags = SA_RESTART;
 
-                       (void) sigaction(SIGDANGER, &sa, NULL);
+               sigaction(SIGDANGER, &sa, NULL);
 #endif /* _AIX */
-               }
 #   endif /* not HAVE_DAEMON */
 #  endif /* SYS_WINNT */
        }
@@ -867,7 +958,7 @@ ntpdmain(
        initializing = 0;
 
 #ifdef HAVE_DROPROOT
-       if( droproot ) {
+       if (droproot) {
                /* Drop super-user privileges and chroot now if the OS supports this */
 
 #ifdef HAVE_LINUX_CAPABILITIES
@@ -982,33 +1073,40 @@ getgroup:
 
                if (disable_dynamic_updates && interface_interval) {
                        interface_interval = 0;
-                       msyslog(LOG_INFO, "running in unprivileged mode disables dynamic interface tracking");
+                       msyslog(LOG_INFO, "running as non-root disables dynamic interface tracking");
                }
 
 #ifdef HAVE_LINUX_CAPABILITIES
-               do {
+               {
                        /*
                         *  We may be running under non-root uid now, but we still hold full root privileges!
                         *  We drop all of them, except for the crucial one or two: cap_sys_time and
                         *  cap_net_bind_service if doing dynamic interface tracking.
                         */
                        cap_t caps;
-                       char *captext = (interface_interval)
-                               ? "cap_sys_time,cap_net_bind_service=ipe"
-                               : "cap_sys_time=ipe";
-                       if( ! ( caps = cap_from_text( captext ) ) ) {
-                               msyslog( LOG_ERR, "cap_from_text() failed: %m" );
+                       char *captext;
+                       
+                       captext = (interface_interval)
+                                     ? "cap_sys_time,cap_net_bind_service=ipe"
+                                     : "cap_sys_time=ipe";
+                       caps = cap_from_text(captext);
+                       if (!caps) {
+                               msyslog(LOG_ERR,
+                                       "cap_from_text(%s) failed: %m",
+                                       captext);
                                exit(-1);
                        }
-                       if( cap_set_proc( caps ) == -1 ) {
-                               msyslog( LOG_ERR, "cap_set_proc() failed to drop root privileges: %m" );
+                       if (-1 == cap_set_proc(caps)) {
+                               msyslog(LOG_ERR,
+                                       "cap_set_proc() failed to drop root privs: %m");
                                exit(-1);
                        }
-                       cap_free( caps );
-               } while(0);
+                       cap_free(caps);
+               }
 #endif /* HAVE_LINUX_CAPABILITIES */
-
-       }    /* if( droproot ) */
+               root_dropped = 1;
+               fork_deferred_worker();
+       }       /* if (droproot) */
 #endif /* HAVE_DROPROOT */
 
        /*
@@ -1237,7 +1335,7 @@ finish(
 
 static void
 assertion_failed(const char *file, int line, isc_assertiontype_t type,
-                 const char *cond)
+                const char *cond)
 {
        isc_assertion_setcallback(NULL);    /* Avoid recursion */
 
@@ -1245,6 +1343,11 @@ assertion_failed(const char *file, int line, isc_assertiontype_t type,
                file, line, isc_assertion_typetotext(type), cond);
        msyslog(LOG_ERR, "exiting (due to assertion failure)");
 
+#if defined(DEBUG) && defined(SYS_WINNT)
+       if (debug)
+               DebugBreak();
+#endif
+
        abort();
 }
 
@@ -1254,7 +1357,7 @@ assertion_failed(const char *file, int line, isc_assertiontype_t type,
 
 static void
 library_fatal_error(const char *file, int line, const char *format,
-                    va_list args)
+                   va_list args)
 {
        char errbuf[256];
 
@@ -1265,6 +1368,11 @@ library_fatal_error(const char *file, int line, const char *format,
        msyslog(LOG_ERR, errbuf);
        msyslog(LOG_ERR, "exiting (due to fatal error in library)");
 
+#if defined(DEBUG) && defined(SYS_WINNT)
+       if (debug)
+               DebugBreak();
+#endif
+
        abort();
 }
 
index e7c0d9a583c94c7acf904b99fcd0aebc82c7798e..01500c519c5cdd55dfeb48d3104a44d0791394a2 100644 (file)
@@ -9,6 +9,7 @@
  * (Some code shamelessly based on the original NTP discrete event simulator)
  */
 
+#include <config.h>
 #ifdef SIM
 #include "ntpd.h"
 #include "ntpsim.h"
index 583e31bc014c3225749464adb1e74cb49e47e8f9..2e0bf8c63f0e7333410be5e7dac087bbcf946ff9 100644 (file)
@@ -52,7 +52,7 @@
 # include "ppsapi_timepps.h"
 #endif
 
-#ifdef XNTP_BIG_ENDIAN
+#ifdef WORDS_BIGENDIAN
 #define getshort(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
 #define putshort(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
 #else
index ff7ab8badd00290f19733cf689cdb02ca4105002..3fe5290c377c8c23421b00b9d72e8d3b3f4a8f5e 100644 (file)
@@ -786,9 +786,9 @@ TSIP_decode (
        }
        else if ((up->rpt_buf[0] == PACKET_41A) & (up->type == CLK_ACUTIME)) {
 #ifdef DEBUG
-               printf("GPS TOW: %ld\n", getlong((u_char *) &mb(0)));
+               printf("GPS TOW: %ld\n", (long)getlong((u_char *) &mb(0)));
                printf("GPS WN: %d\n", getint((u_char *) &mb(4)));
-               printf("GPS UTC-GPS Offser: %ld\n", getlong((u_char *) &mb(6)));
+               printf("GPS UTC-GPS Offser: %ld\n", (long)getlong((u_char *) &mb(6)));
 #endif
                return 0;
        }
@@ -1185,85 +1185,60 @@ HW_poll (
        return 0;
 }
 
-#if 0 /* unused */
 /*
- * this 'casts' a character array into a float
+ * copy/swap a big-endian palisade double into a host double
  */
-float
-getfloat (
-       u_char *bp
-       )
-{
-       float sval;
-#ifdef WORDS_BIGENDIAN 
-       ((char *) &sval)[0] = *bp++;
-       ((char *) &sval)[1] = *bp++;
-       ((char *) &sval)[2] = *bp++;
-       ((char *) &sval)[3] = *bp++;
-#else
-       ((char *) &sval)[3] = *bp++;
-       ((char *) &sval)[2] = *bp++;
-       ((char *) &sval)[1] = *bp++;
-       ((char *) &sval)[0] = *bp;
-#endif  /* ! XNTP_BIG_ENDIAN */ 
-       return sval;
-}
-#endif
-
-/*
- * this 'casts' a character array into a double
- */
-double
+static double
 getdbl (
        u_char *bp
        )
 {
-       double dval;
-#ifdef WORDS_BIGENDIAN 
-       ((char *) &dval)[0] = *bp++;
-       ((char *) &dval)[1] = *bp++;
-       ((char *) &dval)[2] = *bp++;
-       ((char *) &dval)[3] = *bp++;
-       ((char *) &dval)[4] = *bp++;
-       ((char *) &dval)[5] = *bp++;
-       ((char *) &dval)[6] = *bp++;
-       ((char *) &dval)[7] = *bp;
+#ifdef WORDS_BIGENDIAN
+       double out;
+
+       memcpy(&out, bp, sizeof(out));
+       return out;
 #else
-       ((char *) &dval)[7] = *bp++;
-       ((char *) &dval)[6] = *bp++;
-       ((char *) &dval)[5] = *bp++;
-       ((char *) &dval)[4] = *bp++;
-       ((char *) &dval)[3] = *bp++;
-       ((char *) &dval)[2] = *bp++;
-       ((char *) &dval)[1] = *bp++;
-       ((char *) &dval)[0] = *bp;
-#endif  /* ! XNTP_BIG_ENDIAN */ 
-       return dval;
+       union {
+               u_char ch[8];
+               u_int32 u32[2];
+       } ui;
+               
+       union {
+               double out;
+               u_int32 u32[2];
+       } uo;
+
+       memcpy(ui.ch, bp, sizeof(ui.ch));
+       /* least-significant 32 bits of double from swapped bp[4] to bp[7] */
+       uo.u32[0] = ntohl(ui.u32[1]);
+       /* most-significant 32 bits from swapped bp[0] to bp[3] */
+       uo.u32[1] = ntohl(ui.u32[0]);
+
+       return uo.out;
+#endif
 }
 
 /*
- * cast a 16 bit character array into a short (16 bit) int
+ * copy/swap a big-endian palisade short into a host short
  */
-short
+static short
 getint (
        u_char *bp
        )
 {
-       return (short) (bp[1] + (bp[0] << 8));
+       return (short)ntohs(*(u_short *)bp);
 }
 
 /*
- * cast a 32 bit character array into a long (32 bit) int
+ * copy/swap a big-endian palisade 32-bit int into a host 32-bit int
  */
-long
+static int32
 getlong(
        u_char *bp
        )
 {
-       return (long) (bp[0] << 24) | 
-           (bp[1] << 16) |
-           (bp[2] << 8) |
-           bp[3];
+       return (int32)(u_int32)ntohl(*(u_int32 *)bp);
 }
 
 int refclock_palisade_bs;
index c2d4476a9833aef3c99a4f62a9c3f19b8353ed33..4f1ab266eef34f6728d9b9e626e92e8219db0f0e 100644 (file)
  *
  */
 
-#ifndef _REFCLOCK_PALISADE_H
-#define _REFCLOCK_PALISADE_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#ifndef REFCLOCK_PALISADE_H
+#define REFCLOCK_PALISADE_H
 
 #if defined HAVE_SYS_MODEM_H
 #include <sys/modem.h>
@@ -183,14 +179,13 @@ static    int     palisade_start          (int, struct peer *);
 static void    palisade_shutdown       (int, struct peer *);
 static void    palisade_receive        (struct peer *);
 static void    palisade_poll           (int, struct peer *);
-static  void   palisade_io             (struct recvbuf *);
+static void    palisade_io             (struct recvbuf *);
 int            palisade_configure      (int, struct peer *);
 int            TSIP_decode             (struct peer *);
 long           HW_poll                 (struct refclockproc *);
-float          getfloat                (u_char *); 
-double                 getdbl                  (u_char *);
-short                  getint                  (u_char *);
-long           getlong                 (u_char *);
+static double  getdbl                  (u_char *);
+static short   getint                  (u_char *);
+static int32   getlong                 (u_char *);
 
 
 #ifdef PALISADE_SENDCMD_RESURRECTED
@@ -202,4 +197,5 @@ static  void        sendint                 (struct packettx *buffer, int a);
 static  int    sendetx                 (struct packettx *buffer, int fd);
 static  void   init_thunderbolt        (int fd);
 static  void   init_acutime            (int fd);
-#endif /* PALISADE_H */
+
+#endif /* REFCLOCK_PALISADE_H */
diff --git a/ntpd/work_fork.c b/ntpd/work_fork.c
new file mode 100644 (file)
index 0000000..ba93550
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+ * work_fork.c - fork implementation for blocking worker child.
+ */
+#include <config.h>
+#include "ntp_workimpl.h"
+
+#ifdef WORK_FORK
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include "iosignal.h"
+#include "ntp_stdlib.h"
+#include "ntp_malloc.h"
+#include "ntp_syslog.h"
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_assert.h"
+#include "ntp_unixtime.h"
+#include "ntp_worker.h"
+
+/* 
+ * pipe descriptors for both directions
+ * 0 indicates invalid/unopened, not descriptor 0.
+ */
+static int     parent_req_write_pipe;
+       int     parent_resp_read_pipe;
+static int     child_req_read_pipe;
+static int     child_resp_write_pipe;
+static int     blocking_worker_pid;
+static volatile int worker_sighup_received;
+
+static void            fork_blocking_child(void);
+static RETSIGTYPE      worker_sighup(int);
+static void            send_worker_home_atexit(void);
+
+
+/*
+ * exit_worker()
+ *
+ * On some systems _exit() is preferred to exit() for forked children.
+ * For example, http://netbsd.gw.com/cgi-bin/man-cgi?fork++NetBSD-5.0
+ * recommends _exit() to avoid double-flushing C runtime stream buffers
+ * and also to avoid calling the parent's atexit() routines in the
+ * child.  On those systems WORKER_CHILD_EXIT is _exit.  Since _exit
+ * bypasses CRT cleanup, fflush() files we know might have output
+ * buffered.
+ */
+void
+exit_worker(
+       int     exitcode
+       )
+{
+       if (syslog_file != NULL)
+               fflush(syslog_file);
+       fflush(stdout);
+       fflush(stderr);
+       WORKER_CHILD_EXIT (exitcode);   /* space before ( required */
+}
+
+
+static RETSIGTYPE
+worker_sighup(
+       int sig
+       )
+{
+       if (SIGHUP == sig)
+               worker_sighup_received = 1;
+}
+
+
+int
+worker_sleep(
+       time_t  seconds
+       )
+{
+       u_int sleep_remain;
+
+       sleep_remain = (u_int)seconds;
+       do {
+               if (!worker_sighup_received)
+                       sleep_remain = sleep(sleep_remain);
+               if (worker_sighup_received) {
+                       DPRINTF(1, ("worker SIGHUP with %us left to sleep",
+                                   sleep_remain));
+                       worker_sighup_received = 0;
+                       return -1;
+               }
+       } while (sleep_remain);
+
+       return 0;
+}
+
+
+void
+interrupt_worker_sleep(void)
+{
+       if (blocking_worker_pid != 0 &&
+           -1 == kill(blocking_worker_pid, SIGHUP))
+               msyslog(LOG_ERR,
+                       "Unable to signal HUP to wake child pid %d: %m",
+                       blocking_worker_pid);
+}
+
+
+static void
+send_worker_home_atexit(void)
+{
+       if (!parent_req_write_pipe)
+               return;
+
+       close(parent_req_write_pipe);
+       parent_req_write_pipe = 0;
+       close(parent_resp_read_pipe);
+       parent_resp_read_pipe = 0;
+       interrupt_worker_sleep();
+       blocking_worker_pid = 0;
+}
+
+
+int
+send_blocking_req_internal(
+       blocking_pipe_header *  hdr,
+       void *                  data
+       )
+{
+       int octets;
+       int rc;
+
+       NTP_REQUIRE(hdr != NULL);
+       NTP_REQUIRE(data != NULL);
+       NTP_REQUIRE(BLOCKING_REQ_MAGIC == hdr->magic_sig);
+
+       if (!parent_req_write_pipe) {
+               fork_blocking_child();
+               NTP_INSIST(parent_req_write_pipe);
+       }
+
+       octets = sizeof(*hdr);
+       rc = write(parent_req_write_pipe, hdr, octets);
+
+       if (rc == octets) {
+               octets = hdr->octets - sizeof(*hdr);
+               rc = write(parent_req_write_pipe, data,
+                          octets);
+
+               if (rc == octets)
+                       return 0;
+       }
+
+       if (rc < 0)
+               msyslog(LOG_ERR, "send_blocking_req_internal: pipe write: %m");
+       else
+               msyslog(LOG_ERR, "send_blocking_req_internal: short write %d of %d\n", rc, octets);
+
+       exit(1);        /* otherwise would be return -1 */
+}
+
+
+blocking_pipe_header *
+receive_blocking_req_internal(
+       void
+       )
+{
+       blocking_pipe_header hdr;
+       blocking_pipe_header *req;
+       int trycount;
+       int rc;
+
+       NTP_REQUIRE(child_req_read_pipe);
+
+       req = NULL;
+
+       trycount = 3;
+       do
+               rc = read(child_req_read_pipe, &hdr, sizeof(hdr));
+       while (--trycount && !rc);
+
+       if (rc < 0)
+               msyslog(LOG_ERR,
+                       "receive_blocking_req_internal: pipe read %m\n");
+       else if (0 == rc)
+               DPRINTF(1, ("parent closed request pipe\n"));
+       else if (rc != sizeof(hdr))
+               msyslog(LOG_ERR,
+                       "receive_blocking_req_internal: short header read %d of %d\n",
+                       rc, sizeof(hdr));
+       else {
+               req = emalloc(hdr.octets);
+               memcpy(req, &hdr, sizeof(*req));
+
+               rc = read(child_req_read_pipe,
+                         (char *)req + sizeof(*req),
+                         hdr.octets - sizeof(hdr));
+
+               if (rc < 0)
+                       msyslog(LOG_ERR,
+                               "receive_blocking_req_internal: pipe data read %m\n");
+               else if (rc != hdr.octets - sizeof(hdr))
+                       msyslog(LOG_ERR,
+                               "receive_blocking_req_internal: short read %d of %d\n",
+                               rc, hdr.octets - sizeof(hdr));
+               else if (BLOCKING_REQ_MAGIC != req->magic_sig)
+                       msyslog(LOG_ERR,
+                               "receive_blocking_req_internal: packet header mismatch (0x%x)",
+                               req->magic_sig);
+               else
+                       return req;
+       }
+
+       if (req)
+               free(req);
+
+       return NULL;
+}
+
+
+int
+send_blocking_resp_internal(
+       blocking_pipe_header *resp
+       )
+{
+       int octets;
+       int rc;
+
+       NTP_REQUIRE(child_resp_write_pipe);
+
+       octets = resp->octets;
+       rc = write(child_resp_write_pipe, resp, octets);
+       free(resp);
+
+       if (octets == rc)
+               return 0;
+
+       if (rc < 0)
+               DPRINTF(1, ("send_blocking_resp_internal: pipe write %m\n"));
+       else
+               DPRINTF(1, ("send_blocking_resp_internal: short write %d of %d\n", rc, octets));
+
+       return -1;
+}
+
+
+blocking_pipe_header *
+receive_blocking_resp_internal(
+       void
+       )
+{
+       blocking_pipe_header hdr;
+       blocking_pipe_header *resp;
+       int rc;
+
+       NTP_REQUIRE(parent_resp_read_pipe);
+
+       resp = NULL;
+
+       rc = read(parent_resp_read_pipe, &hdr, sizeof(hdr));
+
+       if (rc < 0)
+               DPRINTF(1, ("receive_blocking_resp_internal: pipe read %m\n"));
+       else if (rc != sizeof(hdr))
+               DPRINTF(1, ("receive_blocking_resp_internal: short header read %d of %d\n",
+                           rc, sizeof(hdr)));
+       else if (BLOCKING_RESP_MAGIC != hdr.magic_sig)
+               DPRINTF(1, ("receive_blocking_resp_internal: header mismatch (0x%x)\n",
+                           hdr.magic_sig));
+       else {
+               resp = emalloc(hdr.octets);
+               memcpy(resp, &hdr, sizeof(*resp));
+
+               rc = read(parent_resp_read_pipe,
+                         (char *)resp + sizeof(*resp),
+                         hdr.octets - sizeof(hdr));
+
+               if (rc < 0)
+                       DPRINTF(1, ("receive_blocking_resp_internal: pipe data read %m\n"));
+               else if (rc < hdr.octets - sizeof(hdr))
+                       DPRINTF(1, ("receive_blocking_resp_internal: short read %d of %d\n",
+                                   rc, hdr.octets - sizeof(hdr)));
+               else
+                       return resp;
+       }
+
+       if (resp)
+               free(resp);
+
+       return NULL;
+}
+
+
+#if defined(HAVE_DROPROOT) && defined(WORK_FORK)
+void
+fork_deferred_worker(void)
+{
+       NTP_REQUIRE(droproot);
+       NTP_REQUIRE(root_dropped);
+
+       if (parent_req_write_pipe && !blocking_worker_pid)
+               fork_blocking_child();
+}
+#endif
+
+
+static void
+fork_blocking_child(
+       void
+       )
+{
+       static int atexit_installed;
+       static int blocking_pipes[4];
+       int childpid;
+       int keep_fd;
+       int fd;
+
+       /*
+        * parent and child communicate via a pair of pipes.
+        * 
+        * 0 child read request
+        * 1 parent write request
+        * 2 parent read response
+        * 3 child write response
+        */
+       if (!parent_req_write_pipe) {
+               if (pipe(&blocking_pipes[0]) < 0 ||
+                   pipe(&blocking_pipes[2]) < 0) {
+                       msyslog(LOG_ERR, "unable to create worker pipes: %m");
+                       exit(1);
+               }
+
+               /*
+                * Move the descriptors the parent will keep open out of the
+                * low descriptors preferred by C runtime buffered FILE *.
+                */
+               parent_req_write_pipe = move_fd(blocking_pipes[1]);
+               parent_resp_read_pipe = move_fd(blocking_pipes[2]);
+               /* zero is reserved to mean invalid/not open */
+               NTP_INSIST(parent_req_write_pipe != 0);
+               NTP_INSIST(parent_resp_read_pipe != 0);
+               /*
+                * wake any worker child on orderly shutdown of the
+                * daemon so that it can notice the broken pipes and
+                * go away promptly.
+                */
+               if (!atexit_installed) {
+                       atexit(&send_worker_home_atexit);
+                       atexit_installed = 1;
+               }
+       }
+
+#ifdef HAVE_DROPROOT
+       /* defer the fork until after root is dropped */
+       if (droproot && !root_dropped)
+               return;
+#endif
+       if (syslog_file != NULL)
+               fflush(syslog_file);
+       fflush(stdout);
+       fflush(stderr);
+
+       signal_no_reset(SIGCHLD, SIG_IGN);
+
+       childpid = fork();
+       if (-1 == childpid) {
+               msyslog(LOG_ERR, "unable to fork worker: %m");
+               exit(1);
+       }
+
+       if (childpid) {
+               /* this is the parent */
+               NLOG(NLOG_SYSEVENT)
+                       msyslog(LOG_INFO,
+                               "forked worker child (pid %d)",
+                               childpid);
+               blocking_worker_pid = childpid;
+
+               /* close the child's pipe descriptors. */
+               close(blocking_pipes[0]);
+               close(blocking_pipes[3]);
+
+               /* wire into I/O loop */
+               update_resp_pipe_fd(parent_resp_read_pipe, 0);
+
+               return;         /* parent returns */
+       }
+
+       /*
+        * In the child, close all files except stdin, stdout, stderr,
+        * and the two child ends of the pipes.
+        */
+       child_req_read_pipe = blocking_pipes[0];
+       child_resp_write_pipe = blocking_pipes[3];
+
+       kill_asyncio(0);
+       if (syslog_file != NULL) {
+               fclose(syslog_file);
+               syslog_file = NULL;
+               syslogit = 1;
+       }
+       keep_fd = max(child_req_read_pipe, child_resp_write_pipe);
+       for (fd = 3; fd < keep_fd; fd++)
+               if (fd != child_req_read_pipe && 
+                   fd != child_resp_write_pipe)
+                   close(fd);
+       close_all_beyond(keep_fd);
+       /*
+        * We get signals from refclock serial I/O on NetBSD in the
+        * worker if we do not reset SIGIO's handler to the default.
+        * It is not conditionalized for NetBSD alone because on
+        * systems where it is not needed, it is harmless, and that
+        * allows us to handle unknown others with NetBSD behavior.
+        * [Bug 1386]
+        */
+#if defined(USE_SIGIO)
+       signal_no_reset(SIGIO, SIG_DFL);
+#elif defined(USE_SIGPOLL)
+       signal_no_reset(SIGPOLL, SIG_DFL);
+#endif
+       signal_no_reset(SIGHUP, worker_sighup);
+       init_logging("ntpd_intres", 0);
+       setup_logfile(0);
+
+       /*
+        * And now back to the portable code
+        */
+       exit_worker(blocking_child_common());
+}
+
+/*
+ * worker_idle_timer_fired()
+ *
+ * The parent starts this timer when the last pending response has been
+ * received from the child, making it idle, and clears the timer when a
+ * request is dispatched to the child.  Once the timer expires, the
+ * child is sent packing.
+ *
+ * This is called when worker_idle_timer is nonzero and less than or
+ * equal to current_time, and is responsible for resetting
+ * worker_idle_timer.
+ *
+ * Note there are implementations in both work_fork.c and work_thread.c
+ * that should remain in sync.
+ */
+void
+worker_idle_timer_fired(void)
+{
+       NTP_REQUIRE(0 == intres_req_pending);
+
+       worker_idle_timer = 0;
+       blocking_worker_pid = 0;
+       close(parent_req_write_pipe);
+       parent_req_write_pipe = 0;
+       update_resp_pipe_fd(parent_resp_read_pipe, 1);
+       close(parent_resp_read_pipe);
+       parent_resp_read_pipe = 0;
+}
+
+
+#else  /* !WORK_FORK follows */
+char work_fork_nonempty_compilation_unit;
+#endif
diff --git a/ntpd/work_thread.c b/ntpd/work_thread.c
new file mode 100644 (file)
index 0000000..cef6244
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * work_thread.c - threads implementation for blocking worker child.
+ */
+#include <config.h>
+#include "ntp_workimpl.h"
+
+#ifdef WORK_THREAD
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "ntp_stdlib.h"
+#include "ntp_malloc.h"
+#include "ntp_syslog.h"
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_assert.h"
+#include "ntp_unixtime.h"
+#include "ntp_worker.h"
+
+#define CHILD_EXIT_REQ ((blocking_pipe_header *)(intptr_t)-1)
+
+blocking_pipe_header *blocking_workitems[24];
+blocking_pipe_header *blocking_responses[8];
+HANDLE blocking_child_thread;
+HANDLE child_is_blocking;
+HANDLE wake_blocking_child;
+HANDLE blocking_response_ready;
+HANDLE wake_scheduled_sleep;
+
+static void    start_blocking_thread(void);
+unsigned WINAPI        blocking_thread(void *);
+static int     queue_req_pointer(blocking_pipe_header *);
+
+
+void
+exit_worker(
+       int     exitcode
+       )
+{
+       _endthreadex(exitcode);
+}
+
+
+int
+worker_sleep(
+       time_t  seconds
+       )
+{
+       DWORD rc;
+
+       NTP_REQUIRE(seconds * 1000 < MAXDWORD);
+       rc = WaitForSingleObject(wake_scheduled_sleep, (DWORD)seconds * 1000);
+       NTP_INSIST(WAIT_FAILED != rc);
+       return (WAIT_TIMEOUT == rc)
+                  ? 0
+                  : -1;
+}
+
+
+void
+interrupt_worker_sleep(void)
+{
+       SetEvent(wake_scheduled_sleep);
+}
+
+
+/*
+ * queue_req_pointer() - append a work item or idle exit request to
+ *                      blocking_workitems[].
+ */
+static int
+queue_req_pointer(
+       blocking_pipe_header *  hdr
+       )
+{
+       static int next_workitem;
+
+       if (NULL != blocking_workitems[next_workitem]) {
+               DPRINTF(1, ("blocking_workitems full, max %d items\n",
+                           COUNTOF(blocking_workitems)));
+               return -1;
+       }
+
+       blocking_workitems[next_workitem++] = hdr;
+       if (COUNTOF(blocking_workitems) == next_workitem)
+               next_workitem = 0;
+
+       /*
+        * We only want to signal the wakeup event if the child is
+        * blocking on it, which is indicated by setting the blocking
+        * event.  Wait with zero timeout to test.
+        */
+       if (WAIT_OBJECT_0 == WaitForSingleObject(child_is_blocking, 0))
+               SetEvent(wake_blocking_child);
+
+       return 0;
+}
+
+
+int
+send_blocking_req_internal(
+       blocking_pipe_header *  hdr,
+       void *                  data
+       )
+{
+       blocking_pipe_header *  threadcopy;
+
+       NTP_REQUIRE(hdr != NULL);
+       NTP_REQUIRE(data != NULL);
+       NTP_REQUIRE(BLOCKING_REQ_MAGIC == hdr->magic_sig);
+
+       if (NULL == blocking_child_thread)
+               start_blocking_thread();
+
+       threadcopy = emalloc(hdr->octets);
+       memcpy(threadcopy, hdr, sizeof(*hdr));
+       memcpy((char *)threadcopy + sizeof(*hdr),
+              data, hdr->octets - sizeof(*hdr));
+
+       return queue_req_pointer(threadcopy);
+}
+
+
+blocking_pipe_header *
+receive_blocking_req_internal(
+       void
+       )
+{
+       static int next_workitem;
+       blocking_pipe_header *req;
+       int once;
+
+       once = 1;
+
+       /* we block here when idle */
+       if (NULL == blocking_workitems[next_workitem]) {
+               SetEvent(child_is_blocking);
+               while (NULL == blocking_workitems[next_workitem])
+                       if (WAIT_OBJECT_0 != 
+                           WaitForSingleObject(wake_blocking_child, INFINITE)) {
+                               DPRINTF(1, ("fatal receive_blocking_req_internal wait code\n"));
+                               exit(-1);
+                       }
+               ResetEvent(child_is_blocking);
+       }
+
+       req = blocking_workitems[next_workitem];
+       blocking_workitems[next_workitem] = NULL;
+       next_workitem++;
+       if (next_workitem >= COUNTOF(blocking_workitems))
+               next_workitem = 0;
+
+       if (CHILD_EXIT_REQ == req)      /* idled out */
+               req = NULL;
+
+       return req;
+}
+
+
+int
+send_blocking_resp_internal(
+       blocking_pipe_header *resp
+       )
+{
+       static int next_blocking_response;
+
+       if (NULL != blocking_responses[next_blocking_response]) {
+               DPRINTF(1, ("blocking_responses full, max %d items\n",
+                           COUNTOF(blocking_workitems)));
+               return -1;
+       }
+
+       blocking_responses[next_blocking_response] = resp;
+       next_blocking_response++;
+       if (COUNTOF(blocking_responses) == next_blocking_response)
+               next_blocking_response = 0;
+
+       SetEvent(blocking_response_ready);
+
+       return 0;
+}
+
+
+blocking_pipe_header *
+receive_blocking_resp_internal(
+       void
+       )
+{
+       static int              next_blocking_response;
+       blocking_pipe_header *  retval;
+
+       retval = blocking_responses[next_blocking_response];
+
+       if (NULL != retval) {
+               blocking_responses[next_blocking_response] = NULL;
+               next_blocking_response++;
+               if (next_blocking_response == COUNTOF(blocking_responses))
+                       next_blocking_response = 0;
+               NTP_ENSURE(BLOCKING_RESP_MAGIC == retval->magic_sig);
+       }
+
+       return retval;
+}
+
+
+static void
+start_blocking_thread(
+       void
+       )
+{
+       unsigned blocking_thread_id;
+
+       /*
+        * create sync events (semaphores)
+        * child_is_blocking initially unset
+        * wake_blocking_child initially unset
+        *
+        * Child waits for wake_blocking_child to be set after
+        * setting child_is_blocking.  wake_blocking_child and
+        * blocking_response_ready are auto-reset, so wake one
+        * waiter and become unset (unsignalled) in one operation.
+        * blocking_response_ready is created by the IO
+        * completion port initialization code and used before
+        * any blocking requests are made.
+        */
+       if (NULL == child_is_blocking) {
+               /* manual reset using ResetEvent() */
+               child_is_blocking = CreateEvent(NULL, TRUE, FALSE, NULL);
+               /* auto reset - release from wait resets it */
+               wake_blocking_child = CreateEvent(NULL, FALSE, FALSE, NULL);
+               wake_scheduled_sleep = CreateEvent(NULL, FALSE, FALSE, NULL);
+               /*
+                * blocking_response_ready event is created in
+                * init_io_completion_port(), so it can be waited on
+                * before any blocking worker is started.
+                */
+       } else {
+               ResetEvent(child_is_blocking);
+               ResetEvent(wake_scheduled_sleep);
+               ResetEvent(wake_blocking_child);
+               ResetEvent(blocking_response_ready);
+       }
+
+       blocking_child_thread =
+               (HANDLE)_beginthreadex(
+                       NULL, 
+                       0, 
+                       blocking_thread, 
+                       NULL, 
+                       CREATE_SUSPENDED, 
+                       &blocking_thread_id);
+
+       if (NULL == blocking_child_thread) {
+               DPRINTF(1, ("fatal can not start blocking thread\n"));
+               exit(-1);
+       }
+       /* remember the thread priority is only within the process class */
+       if (!SetThreadPriority(blocking_child_thread,
+                              THREAD_PRIORITY_BELOW_NORMAL)) {
+               DPRINTF(1, ("Error setting blocking thread priority\n"));
+       }
+
+       ResumeThread(blocking_child_thread);
+
+       /* wait for the child to set child_is_blocking the first time */
+       while (WAIT_OBJECT_0 != WaitForSingleObject(child_is_blocking, INFINITE))
+               /* null stmt */;
+}
+
+/*
+ * blocking_thread - thread functions have WINAPI calling convention
+ */
+unsigned WINAPI
+blocking_thread(
+       void *UnusedThreadArg
+       )
+{
+       UNUSED_ARG(UnusedThreadArg);
+
+       return blocking_child_common();
+}
+
+/*
+ * worker_idle_timer_fired()
+ *
+ * The parent starts this timer when the last pending response has been
+ * received from the child, making it idle, and clears the timer when a
+ * request is dispatched to the child.  Once the timer expires, the
+ * child is sent packing.
+ *
+ * This is called when worker_idle_timer is nonzero and less than or
+ * equal to current_time, and is responsible for resetting
+ * worker_idle_timer.
+ *
+ * Note there are implementations in both work_fork.c and work_thread.c
+ * that should remain in sync.
+ */
+void
+worker_idle_timer_fired(void)
+{
+       NTP_REQUIRE(0 == intres_req_pending);
+
+       worker_idle_timer = 0;
+       if (NULL != blocking_child_thread) {
+               queue_req_pointer(CHILD_EXIT_REQ);
+               blocking_child_thread = NULL;
+       }
+}
+
+
+#else  /* !WORK_THREAD follows */
+char work_thread_nonempty_compilation_unit;
+#endif
index b05fbf3848e7f9b2ca047a8bd3a14c74f3bd483c..01714888416c3af0d887c3bc1214e1dc1f04b352 100644 (file)
@@ -2,6 +2,7 @@
  * ntpdc-layout - print layout of NTP mode 7 request/response packets
  */
 
+#include <config.h>
 #include <stdio.h>
 #include <stddef.h>
 
index bbab73cce4b39cccc1318116cb66a12c084c8ac3..66e50991c2b83fc7f82ca4b19e78af2bd2643307 100644 (file)
@@ -2,6 +2,7 @@
  * ntpdc - control and monitor your ntpd daemon
  */
 
+#include <config.h>
 #include <stdio.h>
 #include <stddef.h>
 #include <ctype.h>
index c016c79a7bea7d425a0613bc91b250c3f33b35cc..11a79f57e02b86100cc86dabab61ef46eb6fb708 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * ntpq_ops.c - subroutines which are called to perform operations by ntpq
+ * ntpq-subs.c - subroutines which are called to perform operations by ntpq
  */
-
+#include <config.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <sys/types.h>
@@ -907,10 +907,14 @@ dogetassoc(
                datap += sizeof(u_short);
                assoc_cache[numassoc].status = ntohs(*((u_short *)datap));
                datap += sizeof(u_short);
+               if (debug)
+                       fprintf(stderr, "[%u] ", assoc_cache[numassoc].assid);
                if (++numassoc >= MAXASSOC)
                        break;
                dsize -= sizeof(u_short) + sizeof(u_short);
        }
+       if (debug)
+               fprintf(stderr, "\n%d associations total\n", numassoc);
        sortassoc();
        return 1;
 }
@@ -1451,17 +1455,17 @@ doprintpeers(
        char whenbuf[8], pollbuf[8];
        char clock_name[LENHOSTNAME];
 
-       memset((char *)havevar, 0, sizeof(havevar));
        get_systime(&ts);
        
+       memset(havevar, 0, sizeof(havevar));
        ZERO_SOCK(&srcadr);
        ZERO_SOCK(&dstadr);
 
        /* Initialize by zeroing out estimate variables */
-       memset((char *)&estoffset, 0, sizeof(l_fp));
-       memset((char *)&estdelay, 0, sizeof(l_fp));
-       memset((char *)&estjitter, 0, sizeof(l_fp));
-       memset((char *)&estdisp, 0, sizeof(l_fp));
+       memset(&estoffset, 0, sizeof(estoffset));
+       memset(&estdelay, 0, sizeof(estdelay));
+       memset(&estjitter, 0, sizeof(estjitter));
+       memset(&estdisp, 0, sizeof(estdisp));
 
        while (nextvar(&datalen, &data, &name, &value)) {
                sockaddr_u dum_store;
@@ -1470,12 +1474,12 @@ doprintpeers(
                if (i == 0)
                        continue;       /* don't know this one */
                switch (i) {
-                       case CP_SRCADR:
+               case CP_SRCADR:
                        if (decodenetnum(value, &srcadr)) {
                                havevar[HAVE_SRCADR] = 1;
                        }
                        break;
-                       case CP_DSTADR:
+               case CP_DSTADR:
                        if (decodenetnum(value, &dum_store)) {
                                type = decodeaddrtype(&dum_store);
                                if (pvl == opeervarlist) {
@@ -1485,7 +1489,7 @@ doprintpeers(
                                }
                        }
                        break;
-                       case CP_REFID:
+               case CP_REFID:
                        if (pvl == peervarlist) {
                                havevar[HAVE_REFID] = 1;
                                if (*value == '\0') {
@@ -1511,70 +1515,63 @@ doprintpeers(
                                }
                        }
                        break;
-                       case CP_STRATUM:
+               case CP_STRATUM:
                        if (decodeuint(value, &stratum))
                                havevar[HAVE_STRATUM] = 1;
                        break;
-                       case CP_HPOLL:
+               case CP_HPOLL:
                        if (decodeint(value, &hpoll)) {
                                havevar[HAVE_HPOLL] = 1;
                                if (hpoll < 0)
                                        hpoll = NTP_MINPOLL;
                        }
                        break;
-                       case CP_PPOLL:
+               case CP_PPOLL:
                        if (decodeint(value, &ppoll)) {
                                havevar[HAVE_PPOLL] = 1;
                                if (ppoll < 0)
                                        ppoll = NTP_MINPOLL;
                        }
                        break;
-                       case CP_REACH:
+               case CP_REACH:
                        if (decodeuint(value, &reach))
                                havevar[HAVE_REACH] = 1;
                        break;
-                       case CP_DELAY:
+               case CP_DELAY:
                        if (decodetime(value, &estdelay))
                                havevar[HAVE_DELAY] = 1;
                        break;
-                       case CP_OFFSET:
+               case CP_OFFSET:
                        if (decodetime(value, &estoffset))
                                havevar[HAVE_OFFSET] = 1;
                        break;
-                       case CP_JITTER:
+               case CP_JITTER:
                        if (pvl == peervarlist)
                                if (decodetime(value, &estjitter))
                                        havevar[HAVE_JITTER] = 1;
                        break;
-                       case CP_DISPERSION:
+               case CP_DISPERSION:
                        if (decodetime(value, &estdisp))
                                havevar[HAVE_DISPERSION] = 1;
                        break;
-                       case CP_REC:
+               case CP_REC:
                        if (decodets(value, &rec))
                                havevar[HAVE_REC] = 1;
                        break;
-                       case CP_SRCPORT:
+               case CP_SRCPORT:
                        if (decodeuint(value, &srcport))
                                havevar[HAVE_SRCPORT] = 1;
                        break;
-                       case CP_REFTIME:
+               case CP_REFTIME:
                        havevar[HAVE_REFTIME] = 1;
                        if (!decodets(value, &reftime))
                                L_CLR(&reftime);
                        break;
-                       default:
+               default:
                        break;
                }
        }
 
-       /*
-        * Check to see if the srcport is NTP's port.  If not this probably
-        * isn't a valid peer association.
-        */
-       if (havevar[HAVE_SRCPORT] && srcport != NTP_PORT)
-               return (1);
-
        /*
         * Got everything, format the line
         */
@@ -1584,11 +1581,11 @@ doprintpeers(
        else
                c = flash2[CTL_PEER_STATVAL(rstatus) & 0x3];
        if (numhosts > 1)
-               (void) fprintf(fp, "%-*s ", maxhostlen, currenthost);
+               fprintf(fp, "%-*s ", maxhostlen, currenthost);
        if (af == 0 || AF(&srcadr) == af) {
-               strcpy(clock_name, nntohost(&srcadr));
+               strncpy(clock_name, nntohost(&srcadr), sizeof(clock_name));
                
-               (void) fprintf(fp,
+               fprintf(fp,
                        "%c%-15.15s %-15.15s %2ld %c %4.4s %4.4s  %3lo  %7.7s %8.7s %7.7s\n",
                        c, clock_name, dstadr_refid, stratum, type,
                        prettyinterval(whenbuf, when(&ts, &rec, &reftime)),
@@ -1686,20 +1683,23 @@ dopeers(
                                maxhostlen = strlen(fullname);
        }
        if (numhosts > 1)
-               (void) fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, "server");
-       (void) fprintf(fp,
-                          "     remote           refid      st t when poll reach   delay   offset  jitter\n");
+               fprintf(fp, "%-*.*s ", maxhostlen, maxhostlen, "server");
+       fprintf(fp,
+               "     remote           refid      st t when poll reach   delay   offset  jitter\n");
        if (numhosts > 1)
                for (i = 0; i <= maxhostlen; ++i)
-               (void) fprintf(fp, "=");
-       (void) fprintf(fp,
-                          "==============================================================================\n");
+                       fprintf(fp, "=");
+       fprintf(fp,
+               "==============================================================================\n");
 
        for (i = 0; i < numassoc; i++) {
                if (!showall &&
-                       !(CTL_PEER_STATVAL(assoc_cache[i].status)
-                         & (CTL_PST_CONFIG|CTL_PST_REACH)))
+                   !(CTL_PEER_STATVAL(assoc_cache[i].status)
+                     & (CTL_PST_CONFIG|CTL_PST_REACH))) {
+                       if (debug)
+                               fprintf(stderr, "eliding [%d]\n", assoc_cache[i].assid);
                        continue;
+               }
                if (!dogetpeers(peervarlist, (int)assoc_cache[i].assid, fp, af)) {
                        return;
                }
index 03a3af7f181f59a91919e59bda8b9e37ea19f02c..1f3525685b868bad7790c425d65d1e964308fc62 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ntpq - query an NTP server using mode 6 commands
  */
-
+#include <config.h>
 #include <stdio.h>
 
 #include <ctype.h>
index 3a5815a457e45edba69fbb2e737b543b89b2fdda..7b94286ca1c58d108955e2f85b8ed8ef2b7a5645 100644 (file)
 #include <net-snmp/net-snmp-config.h>
 #include <net-snmp/net-snmp-includes.h>
 #include <net-snmp/agent/net-snmp-agent-includes.h>
+#undef PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#undef PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+#include <config.h>
 #include "ntpSnmpSubagentObject.h"
 #include <libntpq.h>
 
index 449631b47c1288dc4fe6b24ac1de95635f4f5eff..9c2d49847e69819eaab76f6285bd355a7611ff97 100644 (file)
@@ -20,6 +20,7 @@
  *
  ****************************************************************************/
 
+#include <config.h>
 #include <signal.h>
 #include <sys/time.h>
 
index 223ab30838f24c09c560367ac9d9cf3ab25813e1..c78c2424eb2fd7602ed58a2a64f0b424b62b10a7 100644 (file)
@@ -34,6 +34,7 @@
  *
  */
 
+#include <config.h>
 #include "ntp_stdlib.h"
 
 #include <sys/ioctl.h>
index 43ad004c6a330ff2ada85cdb14b6ade46018d9ad..f75ee0b578eeaa3ea6d7f7a37f269bc5a1d105df 100644 (file)
@@ -1,14 +1,29 @@
-/* config.h for Windows NT */
+/* 
+ * ports/winnt/include/config.h - static Windows config.h
+ *
+ * On most systems config.h is generated by the configure script.
+ * For the Windows port, it's hand-maintained.
+ */
 
 #ifndef CONFIG_H
 #define CONFIG_H
 
 /*
- * For newer compilers we may we want newer prototypes from Windows
- * so we target _WIN32_WINNT at WINXP, but we also want our binary to
- * run on NT 4, so newer functions are runtime linked and the linker
- * /version:0x0400 * switch is used to override the .exe file minimum
- * version. For older compilers we leave it at NT 4.0.
+ * For newer compilers we want structures and prototypes added after
+ * Windows NT 4.0 exposed by Windows header files, so we define
+ * _WIN32_WINNT to target Windows XP (version 5.1).  By default,
+ * _WIN32_WINNT also controls the minimum required Windows version to
+ * launch the .exe.  As we want a single binary to work on all
+ * supported Windows versions, we runtime link newer functions, and use
+ * the linker /version:0x0400 option to override the .EXE header
+ * minimum Windows version.
+ *
+ * For compilers older than VS 2005, we assume the headers will not
+ * have what we need and leave _WIN32_WINNT targetting Windows NT 4.0.
+ * This could be modified to change #if _MSC_VER > 1400 to #ifdef _W64
+ * and achieve the same result with the default SDK headers and libs
+ * included with earlier compilers, while taking advantage of newer
+ * functions if an updated SDK is installed.
  */
 #ifndef _WIN32_WINNT
 #if _MSC_VER > 1400            /* At least VS 2005 */
@@ -110,6 +125,25 @@ struct timeval {
        long    tv_usec;
 };
 
+/*
+ * ntohl and friends are actual functions on Windows, use our own
+ * macros instead to save the function call overhead.  All releases
+ * of Windows are little-endian.
+ */
+#ifdef ntohl
+#error ntohl is already defined in ports/winnt/include/config.h
+#else
+#define ntohl(ul)      (((u_long)(ul) & 0xff) << 24 |          \
+                        ((u_long)(ul) & 0xff00) << 8 |         \
+                        ((u_long)(ul) & 0xff0000) >> 8 |       \
+                        ((u_long)(ul) & 0xff000000) >> 24)
+#define htonl(ul)      ntohl(ul)
+#define ntohs(us)      ((u_short)                              \
+                        (((u_short)(us) & 0xff) << 8 |         \
+                         ((u_short)(us) & 0xff00) >> 8))
+#define htons(us)      ntohs(us)
+#endif
+
 /*
  * On Unix open() works for tty (serial) devices just fine, while on
  * Windows refclock serial devices are opened using CreateFile, a lower
@@ -241,6 +275,7 @@ typedef int socklen_t;
 #endif
 #define write          _write
 #define strdup         _strdup
+#define alloca         _alloca
 #define stat           _stat           /*struct stat from  <sys/stat.h> */
 #define fstat          _fstat
 #define unlink         _unlink
@@ -331,7 +366,7 @@ typedef __int32 int32_t;    /* define a typedef for int32_t */
 # define HAVE_NO_NICE
 # define HAVE_MKTIME
 # define HAVE_STRUCT_TIMESPEC
-# define TIME_WITH_SYS_TIME
+# define HAVE_SYS_TIME_H
 # define HAVE_IO_COMPLETION_PORT
 # define ISC_PLATFORM_NEEDNTOP
 # define ISC_PLATFORM_NEEDPTON
@@ -437,4 +472,4 @@ typedef unsigned long uintptr_t;
  */
 #include <isc/stat.h>
 
-#endif /* CONFIG_H */
+#endif /* CONFIG_H */
index d8f734c76980813e8007b74d56d3dd1c2446b73b..3152470350fe50f1ec14d6b4cf983fd093b1bb52 100644 (file)
@@ -7,8 +7,6 @@
 #ifndef SYS_TIME_H
 #define SYS_TIME_H
 
-#include <config.h>
-#include <windows.h>
 #include "ntp_types.h"
 #include <time.h>
 #include <sys/timeb.h>
index 129c8ff2ae115b1f6e393546d7320051665d563d..8f67ca1d18961a7101df0a448fa499339931c2a5 100644 (file)
@@ -2,7 +2,6 @@
 #define WIN32_IO_H
 
 extern void    InitSockets(void);
-void connection_reset_fix(SOCKET fd, sockaddr_u *addr)
+extern void    connection_reset_fix(SOCKET fd, sockaddr_u *addr);
 
-#endif /* defined WIN32_IO_H */
-;
+#endif /* WIN32_IO_H */
index 3bc99382a5ce8ba851fcb4115aca69da828b534f..6b5444f3937877ef51ba68e8877c5a4eba166580 100644 (file)
@@ -1,4 +1,5 @@
 
+#include <config.h>
 #include "clockstuff.h"
 #include "ntp_stdlib.h"
 
index b0e298e4b8c89d213a2d14d0fc41c0fa4886226a..21c3fb0131e04c8f4eaec7fd1a19ce641138ed8d 100644 (file)
@@ -35,7 +35,7 @@
 #include "clockstuff.h"
 #include "ntservice.h"
 #include "ntpd.h"
-#include "../../../ntpd/ntpd-opts.h"
+#include "ntpd-opts.h"
 
 extern double sys_residual;    /* residual from previous adjustment */
 
index 8680ee5b8d15d5fa0c783e429c7a1d7907055dc2..5323acdbb1b735b444771fe28956593fdff5d52a 100644 (file)
@@ -91,8 +91,8 @@ static HANDLE WaitableExitEventHandle = NULL;
 #define WAITABLEIOEVENTHANDLE NULL
 #endif
 
-#define MAXHANDLES 3
-HANDLE WaitHandles[MAXHANDLES] = { NULL, NULL, NULL };
+#define MAXHANDLES 4
+HANDLE WaitHandles[MAXHANDLES];
 
 IoCompletionInfo *
 GetHeapAlloc(char *fromfunc)
@@ -294,12 +294,15 @@ init_io_completion_port(
                exit(1);
        }
 
+       blocking_response_ready = CreateEvent(NULL, FALSE, FALSE, NULL);
+
        /*
         * Initialize the Wait Handles
         */
        WaitHandles[0] = WaitableIoEventHandle;
        WaitHandles[1] = WaitableExitEventHandle; /* exit request */
        WaitHandles[2] = get_timer_handle();
+       WaitHandles[3] = blocking_response_ready;
 
        /* Have one thread servicing I/O - there were 4, but this would 
         * somehow cause NTP to stop replying to ntpq requests; TODO
@@ -888,26 +891,28 @@ int GetReceivedBuffers()
        while (!have_packet) {
                DWORD Index = WaitForMultipleObjects(MAXHANDLES, WaitHandles, FALSE, INFINITE);
                switch (Index) {
-               case WAIT_OBJECT_0 + 0 : /* Io event */
-# ifdef DEBUG
-                       if ( debug > 3 )
-                       {
-                               printf( "IoEvent occurred\n" );
-                       }
-# endif
+               case WAIT_OBJECT_0 + 0: /* Io event */
+                       DPRINTF(4, ("IoEvent occurred\n"));
                        have_packet = ISC_TRUE;
                        break;
-               case WAIT_OBJECT_0 + 1 : /* exit request */
+               case WAIT_OBJECT_0 + 1: /* exit request */
                        exit(0);
                        break;
-               case WAIT_OBJECT_0 + 2 : /* timer */
+               case WAIT_OBJECT_0 + 2: /* timer */
                        timer();
                        break;
-               case WAIT_IO_COMPLETION : /* loop */
-               case WAIT_TIMEOUT :
+               case WAIT_OBJECT_0 + 3: /* blocking response */
+                       process_blocking_response();
+                       break;
+               case WAIT_IO_COMPLETION: /* loop */
+                       break;
+               case WAIT_TIMEOUT:
+                       msyslog(LOG_ERR, "ntpd: WaitForMultipleObjects INFINITE timed out.");
+                       exit(1);
                        break;
                case WAIT_FAILED:
                        msyslog(LOG_ERR, "ntpd: WaitForMultipleObjects Failed: Error: %m");
+                       exit(1);
                        break;
 
                        /* For now do nothing if not expected */
index 0328732785afa0ff74e99154ee8f736e5f2d4732..f99e019962361e5627f0131b7720a3da6bf73265 100644 (file)
@@ -190,6 +190,11 @@ SOURCE=..\..\..\ntpd\ntp_util.c
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=..\..\..\ntpd\ntp_worker.c\r
+# SUBTRACT CPP /YX\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE="..\..\..\ntpd\ntpd-opts.c"\r
 # End Source File\r
 # Begin Source File\r
@@ -200,9 +205,19 @@ SOURCE=..\..\..\ntpd\ntpd.c
 # Begin Source File\r
 \r
 SOURCE=..\ntpd\ntservice.c\r
+# SUBTRACT CPP /YX\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\ntpd\work_fork.c\r
+# SUBTRACT CPP /YX\r
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=..\..\..\ntpd\work_thread.c\r
+# SUBTRACT CPP /YX\r
+# End Source File\r
+\r
 # PROP Default_Filter "h;hpp;hxx;hm;inl"\r
 # Begin Source File\r
 \r
@@ -394,6 +409,14 @@ SOURCE=..\..\..\include\ntp_unixtime.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=..\..\..\include\ntp_worker.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\..\include\ntp_workimpl.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE="..\..\..\ntpd\ntpd-opts.h"\r
 # End Source File\r
 # Begin Source File\r
index 975297aa30772ddf3c4f07e849ec7622f612f367..599c36a04f6a7b9c56c7375f8ccff66a38188c70 100644 (file)
                                                BrowseInformation="1"/>
                                </FileConfiguration>
                        </File>
+                       <File
+                               RelativePath="..\..\..\ntpd\ntp_worker.c">
+                       </File>
                        <File
                                RelativePath="..\..\..\ntpd\ntpd-opts.c">
                                <FileConfiguration
                                                BrowseInformation="1"/>
                                </FileConfiguration>
                        </File>
+                       <File
+                               RelativePath="..\..\..\ntpd\work_fork.c">
+                       </File>
+                       <File
+                               RelativePath="..\..\..\ntpd\work_thread.c">
+                       </File>
                </Filter>
                <Filter
                        Name="Header Files"
                        <File
                                RelativePath="..\..\..\include\ntp_unixtime.h">
                        </File>
+                       <File
+                               RelativePath="..\..\..\include\ntp_worker.h">
+                       </File>
+                       <File
+                               RelativePath="..\..\..\include\ntp_workimpl.h">
+                       </File>
                        <File
                                RelativePath="..\..\..\ntpd\ntpd-opts.h">
                        </File>
index f1f3abeb2ef6f06ebebe5fceba8383758cac8123..2803d8f733b35d50d63f3252bffdc2c095a86b24 100644 (file)
                                        />
                                </FileConfiguration>
                        </File>
+                       <File
+                               RelativePath="..\..\..\ntpd\ntp_worker.c"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\..\ntpd\ntpd-opts.c"
                                >
                                        />
                                </FileConfiguration>
                        </File>
+                       <File
+                               RelativePath="..\..\..\ntpd\work_fork.c"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\..\ntpd\work_thread.c"
+                               >
+                       </File>
                </Filter>
                <Filter
                        Name="Header Files"
                                RelativePath="..\..\..\include\ntp_unixtime.h"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\..\include\ntp_worker.h"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\..\include\ntp_workimpl.h"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\..\ntpd\ntpd-opts.h"
                                >
index 49f5327e115407776b4bd0f663a45dfd21cc870f..b0c61783a014266e33b344e1833554854d09abbb 100644 (file)
                                RelativePath="..\..\..\..\libntp\humandate.c"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\..\..\libntp\icom.c"
+                               >
+                               <FileConfiguration
+                                       Name="Debug|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Release|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                       </File>
                        <File
                                RelativePath="..\..\..\..\lib\isc\inet_aton.c"
                                >
                                RelativePath="..\..\..\..\lib\isc\win32\stdtime.c"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\..\..\libntp\strdup.c"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\..\..\lib\isc\win32\strerror.c"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\..\..\libntp\strstr.c"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\libntp\syslog.c"
                                >
index 8c3f0c5e75f38275aa2f73bf0193508df08ee9c0..d7aa513b43d2df0fc6133ff526ec078e4aa50c5a 100644 (file)
                                        />
                                </FileConfiguration>
                        </File>
+                       <File
+                               RelativePath="..\..\..\..\ntpd\ntp_worker.c"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\..\..\ntpd\ntpd-opts.c"
                                >
                                        />
                                </FileConfiguration>
                        </File>
+                       <File
+                               RelativePath="..\..\..\..\ntpd\ntpsim.c"
+                               >
+                               <FileConfiguration
+                                       Name="Release|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                       </File>
                        <File
                                RelativePath="..\..\ntpd\ntservice.c"
                                >
                                        />
                                </FileConfiguration>
                        </File>
+                       <File
+                               RelativePath="..\..\..\..\ntpd\work_fork.c"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\..\..\ntpd\work_thread.c"
+                               >
+                       </File>
                </Filter>
                <Filter
                        Name="Header Files"
                                RelativePath="..\..\..\..\include\ntp_control.h"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\..\..\include\ntp_data_structures.h"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\..\..\include\ntp_debug.h"
                                >
                                RelativePath="..\..\..\..\include\ntp_unixtime.h"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\..\..\include\ntp_worker.h"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\..\..\include\ntp_workimpl.h"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\..\..\ntpd\ntpd-opts.h"
                                >
                                        />
                                </FileConfiguration>
                        </File>
+                       <File
+                               RelativePath="..\..\..\..\ntpd\refclock_ripencc.c"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\..\..\ntpd\refclock_shm.c"
                                >
                <Filter
                        Name="Parse Lib"
                        >
+                       <File
+                               RelativePath="..\..\..\..\libparse\binio.c"
+                               >
+                               <FileConfiguration
+                                       Name="Debug|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                       </File>
                        <File
                                RelativePath="..\..\..\..\libparse\clk_computime.c"
                                >
                                        />
                                </FileConfiguration>
                        </File>
+                       <File
+                               RelativePath="..\..\..\..\libparse\gpstolfp.c"
+                               >
+                               <FileConfiguration
+                                       Name="Release|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                       </File>
+                       <File
+                               RelativePath="..\..\..\..\libparse\ieee754io.c"
+                               >
+                               <FileConfiguration
+                                       Name="Release|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                       </File>
+                       <File
+                               RelativePath="..\..\..\..\libparse\info_trimble.c"
+                               >
+                               <FileConfiguration
+                                       Name="Release|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                       </File>
+                       <File
+                               RelativePath="..\..\..\..\libparse\mfp_mul.c"
+                               >
+                               <FileConfiguration
+                                       Name="Release|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                       </File>
                        <File
                                RelativePath="..\..\..\..\libparse\parse.c"
                                >
                                        />
                                </FileConfiguration>
                        </File>
+                       <File
+                               RelativePath="..\..\..\..\libparse\parsesolaris.c"
+                               >
+                               <FileConfiguration
+                                       Name="Release|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                       </File>
+                       <File
+                               RelativePath="..\..\..\..\libparse\parsestreams.c"
+                               >
+                               <FileConfiguration
+                                       Name="Release|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                       </File>
+                       <File
+                               RelativePath="..\..\..\..\libparse\trim_info.c"
+                               >
+                               <FileConfiguration
+                                       Name="Release|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                       </File>
                </Filter>
                <File
                        RelativePath="..\..\scripts\mkver.bat"
index 3a795ce3648530ec23d8546cbfb6c5c14254a3f3..dfcb34f99579e7a65ca0e8729de161dd55225184 100644 (file)
@@ -1,3 +1,4 @@
+#include <config.h>
 #include "crypto.h"
 
 struct key *key_ptr;
index 878a2a0c1d98670e77f014918dc3c061ffc1f187..12bc1562c0b03ca3b67702695525ab77a972fb76 100644 (file)
@@ -1,3 +1,4 @@
+#include <config.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
index c6bfe222885fdbd714d75162cf77a65ef137ac20..ec3c5388b5dbd479a03a5d8326b2b0883e244225 100644 (file)
@@ -1,3 +1,4 @@
+#include <config.h>
 #include "log.h"
 #include "sntp-opts.h"
 
index 3348f79d7c5138654735df41b5e875065b96d63c..1a14b6c96f09e89ec70607c2669e2f7e0ad32c86 100644 (file)
@@ -1,3 +1,4 @@
+#include <config.h>
 #include <l_stdlib.h>
 #include <ntp_fp.h>
 #include <ntp.h>
index 9aaff7a1b524290ae5548596ac3497bbaeb7260c..a37eb6c411f19bf928b93d0c9ac152482c78650f 100644 (file)
@@ -1,3 +1,4 @@
+#include <config.h>
 #include "networking.h"
 
 char adr_buf[INET6_ADDRSTRLEN];
index 23d957f3c0115ca83127f336089809f3dcb2bdce..8039bac042b2a5a7de23d5fe9e1258547776e60c 100644 (file)
@@ -1,3 +1,4 @@
+#include <config.h>
 #include "utilities.h"
 
 /* Display a NTP packet in hex with leading address offset