1*eabc0478Schristos /* $NetBSD: ntpd.c,v 1.19 2024/08/18 20:47:18 christos Exp $ */ 2abb0f93cSkardel 3abb0f93cSkardel /* 4abb0f93cSkardel * ntpd.c - main program for the fixed point NTP daemon 5abb0f93cSkardel */ 6abb0f93cSkardel 7abb0f93cSkardel #ifdef HAVE_CONFIG_H 8abb0f93cSkardel # include <config.h> 9abb0f93cSkardel #endif 10abb0f93cSkardel 11abb0f93cSkardel #include "ntp_machine.h" 12abb0f93cSkardel #include "ntpd.h" 13abb0f93cSkardel #include "ntp_io.h" 14abb0f93cSkardel #include "ntp_stdlib.h" 15abb0f93cSkardel #include <ntp_random.h> 16abb0f93cSkardel 172950cc38Schristos #include "ntp_config.h" 18abb0f93cSkardel #include "ntp_syslog.h" 192950cc38Schristos #include "ntp_assert.h" 20abb0f93cSkardel #include "isc/error.h" 21abb0f93cSkardel #include "isc/strerror.h" 22abb0f93cSkardel #include "isc/formatcheck.h" 232950cc38Schristos #include "iosignal.h" 24abb0f93cSkardel 25abb0f93cSkardel #ifdef SIM 26abb0f93cSkardel # include "ntpsim.h" 27abb0f93cSkardel #endif 28abb0f93cSkardel 293123f114Skardel #include "ntp_libopts.h" 30abb0f93cSkardel #include "ntpd-opts.h" 31abb0f93cSkardel 328b8da087Schristos /* there's a short treatise below what the thread stuff is for. 338b8da087Schristos * [Bug 2954] enable the threading warm-up only for Linux. 348b8da087Schristos */ 35af12ab5eSchristos #if defined(HAVE_PTHREADS) && HAVE_PTHREADS && !defined(NO_THREADS) 36af12ab5eSchristos # ifdef HAVE_PTHREAD_H 37af12ab5eSchristos # include <pthread.h> 38af12ab5eSchristos # endif 398b8da087Schristos # if defined(linux) 40af12ab5eSchristos # define NEED_PTHREAD_WARMUP 41af12ab5eSchristos # endif 42af12ab5eSchristos #endif 43af12ab5eSchristos 44abb0f93cSkardel #ifdef HAVE_UNISTD_H 45abb0f93cSkardel # include <unistd.h> 46abb0f93cSkardel #endif 47abb0f93cSkardel #ifdef HAVE_SYS_STAT_H 48abb0f93cSkardel # include <sys/stat.h> 49abb0f93cSkardel #endif 50cdfa2a7eSchristos #ifdef HAVE_SYS_WAIT_H 51cdfa2a7eSchristos # include <sys/wait.h> 52cdfa2a7eSchristos #endif 53abb0f93cSkardel #include <stdio.h> 54abb0f93cSkardel #ifdef HAVE_SYS_PARAM_H 55abb0f93cSkardel # include <sys/param.h> 56abb0f93cSkardel #endif 57abb0f93cSkardel #ifdef HAVE_SYS_SIGNAL_H 58abb0f93cSkardel # include <sys/signal.h> 59abb0f93cSkardel #else 60abb0f93cSkardel # include <signal.h> 61abb0f93cSkardel #endif 62abb0f93cSkardel #ifdef HAVE_SYS_IOCTL_H 63abb0f93cSkardel # include <sys/ioctl.h> 64abb0f93cSkardel #endif /* HAVE_SYS_IOCTL_H */ 65abb0f93cSkardel #if defined(HAVE_RTPRIO) 66abb0f93cSkardel # ifdef HAVE_SYS_LOCK_H 67abb0f93cSkardel # include <sys/lock.h> 68abb0f93cSkardel # endif 69abb0f93cSkardel # include <sys/rtprio.h> 70abb0f93cSkardel #else 71abb0f93cSkardel # ifdef HAVE_PLOCK 72abb0f93cSkardel # ifdef HAVE_SYS_LOCK_H 73abb0f93cSkardel # include <sys/lock.h> 74abb0f93cSkardel # endif 75abb0f93cSkardel # endif 76abb0f93cSkardel #endif 77abb0f93cSkardel #if defined(HAVE_SCHED_SETSCHEDULER) 78abb0f93cSkardel # ifdef HAVE_SCHED_H 79abb0f93cSkardel # include <sched.h> 80abb0f93cSkardel # else 81abb0f93cSkardel # ifdef HAVE_SYS_SCHED_H 82abb0f93cSkardel # include <sys/sched.h> 83abb0f93cSkardel # endif 84abb0f93cSkardel # endif 85abb0f93cSkardel #endif 86abb0f93cSkardel #if defined(HAVE_SYS_MMAN_H) 87abb0f93cSkardel # include <sys/mman.h> 88abb0f93cSkardel #endif 89abb0f93cSkardel 90cdfa2a7eSchristos #ifdef HAVE_SYSEXITS_H 91cdfa2a7eSchristos # include <sysexits.h> 92cdfa2a7eSchristos #endif 93cdfa2a7eSchristos 94abb0f93cSkardel #ifdef HAVE_TERMIOS_H 95abb0f93cSkardel # include <termios.h> 96abb0f93cSkardel #endif 97abb0f93cSkardel 98abb0f93cSkardel #ifdef SYS_DOMAINOS 99abb0f93cSkardel # include <apollo/base.h> 100abb0f93cSkardel #endif /* SYS_DOMAINOS */ 101abb0f93cSkardel 1022950cc38Schristos 103abb0f93cSkardel #include "recvbuff.h" 104abb0f93cSkardel #include "ntp_cmdargs.h" 105abb0f93cSkardel 10679045f13Schristos #ifdef SYS_WINNT 10779045f13Schristos # include "ntservice.h" 10879045f13Schristos #endif 10979045f13Schristos 110abb0f93cSkardel #ifdef _AIX 111abb0f93cSkardel # include <ulimit.h> 112abb0f93cSkardel #endif /* _AIX */ 113abb0f93cSkardel 114abb0f93cSkardel #ifdef SCO5_CLOCK 115abb0f93cSkardel # include <sys/ci/ciioctl.h> 116abb0f93cSkardel #endif 117abb0f93cSkardel 118abb0f93cSkardel #ifdef HAVE_DROPROOT 119abb0f93cSkardel # include <ctype.h> 120abb0f93cSkardel # include <grp.h> 121abb0f93cSkardel # include <pwd.h> 122abb0f93cSkardel #ifdef HAVE_LINUX_CAPABILITIES 123abb0f93cSkardel # include <sys/capability.h> 124abb0f93cSkardel # include <sys/prctl.h> 1252950cc38Schristos #endif /* HAVE_LINUX_CAPABILITIES */ 1262950cc38Schristos #if defined(HAVE_PRIV_H) && defined(HAVE_SOLARIS_PRIVS) 1272950cc38Schristos # include <priv.h> 1282950cc38Schristos #endif /* HAVE_PRIV_H */ 12979045f13Schristos #if defined(HAVE_TRUSTEDBSD_MAC) 13079045f13Schristos # include <sys/mac.h> 13179045f13Schristos #endif /* HAVE_TRUSTEDBSD_MAC */ 1322950cc38Schristos #endif /* HAVE_DROPROOT */ 133abb0f93cSkardel 134ea66d795Schristos #if defined (LIBSECCOMP) && (KERN_SECCOMP) 135ea66d795Schristos /* # include <sys/types.h> */ 136ea66d795Schristos # include <sys/resource.h> 137ea66d795Schristos # include <seccomp.h> 138ea66d795Schristos #endif /* LIBSECCOMP and KERN_SECCOMP */ 139ea66d795Schristos 140*eabc0478Schristos #if defined(__FreeBSD__) && __FreeBSD_version < 1400037 && defined(HAVE_SYS_PROCCTL_H) 141cdfa2a7eSchristos # include <sys/procctl.h> 142*eabc0478Schristos # ifdef PROC_STACKGAP_DISABLE 143*eabc0478Schristos # define DISABLE_FREEBSD_STACKGAP 144cdfa2a7eSchristos # endif 145cdfa2a7eSchristos #endif 146cdfa2a7eSchristos 147abb0f93cSkardel #ifdef HAVE_DNSREGISTRATION 148abb0f93cSkardel # include <dns_sd.h> 149abb0f93cSkardel DNSServiceRef mdns; 150abb0f93cSkardel #endif 151abb0f93cSkardel 152cdfa2a7eSchristos /* In case 'sysexits.h' is unavailable, define some exit codes here: */ 153cdfa2a7eSchristos #ifndef EX_SOFTWARE 154cdfa2a7eSchristos # define EX_SOFTWARE 70 155cdfa2a7eSchristos #endif 156cdfa2a7eSchristos #ifndef EX_OSERR 157cdfa2a7eSchristos # define EX_OSERR 71 158cdfa2a7eSchristos #endif 159cdfa2a7eSchristos #ifndef EX_IOERR 160cdfa2a7eSchristos # define EX_IOERR 74 161cdfa2a7eSchristos #endif 162cdfa2a7eSchristos #ifndef EX_PROTOCOL 163cdfa2a7eSchristos #define EX_PROTOCOL 76 164cdfa2a7eSchristos #endif 165cdfa2a7eSchristos 166cdfa2a7eSchristos 1672950cc38Schristos #ifdef HAVE_SETPGRP_0 1682950cc38Schristos # define ntp_setpgrp(x, y) setpgrp() 1692950cc38Schristos #else 1702950cc38Schristos # define ntp_setpgrp(x, y) setpgrp(x, y) 1712950cc38Schristos #endif 1722950cc38Schristos 1732950cc38Schristos #ifdef HAVE_SOLARIS_PRIVS 1742950cc38Schristos # define LOWPRIVS "basic,sys_time,net_privaddr,proc_setid,!proc_info,!proc_session,!proc_exec" 1752950cc38Schristos static priv_set_t *lowprivs = NULL; 1762950cc38Schristos static priv_set_t *highprivs = NULL; 1772950cc38Schristos #endif /* HAVE_SOLARIS_PRIVS */ 178abb0f93cSkardel /* 179abb0f93cSkardel * Scheduling priority we run at 180abb0f93cSkardel */ 181abb0f93cSkardel #define NTPD_PRIO (-12) 182abb0f93cSkardel 183abb0f93cSkardel int priority_done = 2; /* 0 - Set priority */ 184abb0f93cSkardel /* 1 - priority is OK where it is */ 185abb0f93cSkardel /* 2 - Don't set priority */ 186abb0f93cSkardel /* 1 and 2 are pretty much the same */ 187abb0f93cSkardel 1882950cc38Schristos int listen_to_virtual_ips = TRUE; 189abb0f93cSkardel 190abb0f93cSkardel /* 191abb0f93cSkardel * No-fork flag. If set, we do not become a background daemon. 192abb0f93cSkardel */ 1932950cc38Schristos int nofork; /* Fork by default */ 194abb0f93cSkardel 195abb0f93cSkardel #ifdef HAVE_DNSREGISTRATION 196abb0f93cSkardel /* 197abb0f93cSkardel * mDNS registration flag. If set, we attempt to register with the mDNS system, but only 198abb0f93cSkardel * after we have synched the first time. If the attempt fails, then try again once per 199abb0f93cSkardel * minute for up to 5 times. After all, we may be starting before mDNS. 200abb0f93cSkardel */ 2012950cc38Schristos int mdnsreg = FALSE; 2022950cc38Schristos int mdnstries = 5; 203abb0f93cSkardel #endif /* HAVE_DNSREGISTRATION */ 204abb0f93cSkardel 205cdfa2a7eSchristos #ifdef HAVE_LINUX_CAPABILITIES 206cdfa2a7eSchristos int have_caps; /* runtime check whether capabilities work */ 207cdfa2a7eSchristos #endif /* HAVE_LINUX_CAPABILITIES */ 208cdfa2a7eSchristos 209abb0f93cSkardel #ifdef HAVE_DROPROOT 2102950cc38Schristos int droproot; 2112950cc38Schristos int root_dropped; 2122950cc38Schristos char *user; /* User to switch to */ 2132950cc38Schristos char *group; /* group to switch to */ 2142950cc38Schristos const char *chrootdir; /* directory to chroot to */ 215e589aa51Schristos uid_t sw_uid; 216e589aa51Schristos gid_t sw_gid; 217abb0f93cSkardel struct group *gr; 218abb0f93cSkardel struct passwd *pw; 219abb0f93cSkardel #endif /* HAVE_DROPROOT */ 220abb0f93cSkardel 2212950cc38Schristos #ifdef HAVE_WORKING_FORK 222cdfa2a7eSchristos int daemon_pipe[2] = { -1, -1 }; 2232950cc38Schristos #endif 2242950cc38Schristos 225abb0f93cSkardel /* 226abb0f93cSkardel * Version declaration 227abb0f93cSkardel */ 228abb0f93cSkardel extern const char *Version; 229abb0f93cSkardel 230abb0f93cSkardel char const *progname; 231abb0f93cSkardel 232abb0f93cSkardel int was_alarmed; 233abb0f93cSkardel 234abb0f93cSkardel #ifdef DECL_SYSCALL 235abb0f93cSkardel /* 236abb0f93cSkardel * We put this here, since the argument profile is syscall-specific 237abb0f93cSkardel */ 238abb0f93cSkardel extern int syscall (int, ...); 239abb0f93cSkardel #endif /* DECL_SYSCALL */ 240abb0f93cSkardel 241abb0f93cSkardel 2422950cc38Schristos #if !defined(SIM) && defined(SIGDIE1) 24368dbbb44Schristos static volatile int signalled = 0; 24468dbbb44Schristos static volatile int signo = 0; 24568dbbb44Schristos 24668dbbb44Schristos /* In an ideal world, 'finish_safe()' would declared as noreturn... */ 24768dbbb44Schristos static void finish_safe (int); 248abb0f93cSkardel static RETSIGTYPE finish (int); 2492950cc38Schristos #endif 250abb0f93cSkardel 2512950cc38Schristos #if !defined(SIM) && defined(HAVE_WORKING_FORK) 252cdfa2a7eSchristos static int wait_child_sync_if (int, unsigned long); 253cdfa2a7eSchristos static int wait_child_exit_if (pid_t, int); 2542950cc38Schristos #endif 2552950cc38Schristos 2562950cc38Schristos #if !defined(SIM) && !defined(SYS_WINNT) 257abb0f93cSkardel # ifdef DEBUG 258abb0f93cSkardel static RETSIGTYPE moredebug (int); 259abb0f93cSkardel static RETSIGTYPE lessdebug (int); 2602950cc38Schristos # else /* !DEBUG follows */ 261abb0f93cSkardel static RETSIGTYPE no_debug (int); 2622950cc38Schristos # endif /* !DEBUG */ 2632950cc38Schristos #endif /* !SIM && !SYS_WINNT */ 264abb0f93cSkardel 265ccc794f0Schristos #ifndef WORK_FORK 2662950cc38Schristos int saved_argc; 2672950cc38Schristos char ** saved_argv; 268ccc794f0Schristos #endif 2692950cc38Schristos 2702950cc38Schristos #ifndef SIM 271abb0f93cSkardel int ntpdmain (int, char **); 272abb0f93cSkardel static void set_process_priority (void); 2732950cc38Schristos static void assertion_failed (const char *, int, 2742950cc38Schristos isc_assertiontype_t, 2752950cc38Schristos const char *) 2762950cc38Schristos __attribute__ ((__noreturn__)); 2772950cc38Schristos static void library_fatal_error (const char *, int, 2782950cc38Schristos const char *, va_list) 2792950cc38Schristos ISC_FORMAT_PRINTF(3, 0); 2802950cc38Schristos static void library_unexpected_error(const char *, int, 2812950cc38Schristos const char *, va_list) 2822950cc38Schristos ISC_FORMAT_PRINTF(3, 0); 2832950cc38Schristos #endif /* !SIM */ 284abb0f93cSkardel 285abb0f93cSkardel 286af12ab5eSchristos /* Bug2332 unearthed a problem in the interaction of reduced user 287af12ab5eSchristos * privileges, the limits on memory usage and some versions of the 288af12ab5eSchristos * pthread library on Linux systems. The 'pthread_cancel()' function and 289af12ab5eSchristos * likely some others need to track the stack of the thread involved, 290af12ab5eSchristos * and uses a function that comes from GCC (--> libgcc_s.so) to do 291af12ab5eSchristos * this. Unfortunately the developers of glibc decided to load the 292af12ab5eSchristos * library on demand, which speeds up program start but can cause 293af12ab5eSchristos * trouble here: Due to all the things NTPD does to limit its resource 294af12ab5eSchristos * usage, this deferred load of libgcc_s does not always work once the 295af12ab5eSchristos * restrictions are in effect. 296af12ab5eSchristos * 297af12ab5eSchristos * One way out of this was attempting a forced link against libgcc_s 298af12ab5eSchristos * when possible because it makes the library available immediately 299af12ab5eSchristos * without deferred load. (The symbol resolution would still be dynamic 300af12ab5eSchristos * and on demand, but the code would already be in the process image.) 301af12ab5eSchristos * 302af12ab5eSchristos * This is a tricky thing to do, since it's not necessary everywhere, 303af12ab5eSchristos * not possible everywhere, has shown to break the build of other 304af12ab5eSchristos * programs in the NTP suite and is now generally frowned upon. 305af12ab5eSchristos * 306af12ab5eSchristos * So we take a different approach here: We creat a worker thread that does 307af12ab5eSchristos * actually nothing except waiting for cancellation and cancel it. If 308af12ab5eSchristos * this is done before all the limitations are put in place, the 309af12ab5eSchristos * machinery is pre-heated and all the runtime stuff should be in place 310af12ab5eSchristos * and useable when needed. 311af12ab5eSchristos * 312af12ab5eSchristos * This uses only the standard pthread API and should work with all 313af12ab5eSchristos * implementations of pthreads. It is not necessary everywhere, but it's 314af12ab5eSchristos * cheap enough to go on nearly unnoticed. 3158b8da087Schristos * 3168b8da087Schristos * Addendum: Bug 2954 showed that the assumption that this should work 3178b8da087Schristos * with all OS is wrong -- at least FreeBSD bombs heavily. 318af12ab5eSchristos */ 319af12ab5eSchristos #ifdef NEED_PTHREAD_WARMUP 320af12ab5eSchristos 321af12ab5eSchristos /* simple thread function: sleep until cancelled, just to exercise 322af12ab5eSchristos * thread cancellation. 323af12ab5eSchristos */ 324af12ab5eSchristos static void* 325af12ab5eSchristos my_pthread_warmup_worker( 326af12ab5eSchristos void *thread_args) 327af12ab5eSchristos { 328af12ab5eSchristos (void)thread_args; 329af12ab5eSchristos for (;;) 330af12ab5eSchristos sleep(10); 331af12ab5eSchristos return NULL; 332af12ab5eSchristos } 333af12ab5eSchristos 334af12ab5eSchristos /* pre-heat threading: create a thread and cancel it, just to exercise 335af12ab5eSchristos * thread cancellation. 336af12ab5eSchristos */ 337af12ab5eSchristos static void 338af12ab5eSchristos my_pthread_warmup(void) 339af12ab5eSchristos { 340af12ab5eSchristos pthread_t thread; 34168dbbb44Schristos pthread_attr_t thr_attr; 342af12ab5eSchristos int rc; 34368dbbb44Schristos 34468dbbb44Schristos pthread_attr_init(&thr_attr); 34568dbbb44Schristos #if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \ 34668dbbb44Schristos defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) && \ 34768dbbb44Schristos defined(PTHREAD_STACK_MIN) 3484eea345dSchristos { 3494eea345dSchristos size_t ssmin = 32*1024; /* 32kB should be minimum */ 3504eea345dSchristos if (ssmin < PTHREAD_STACK_MIN) 3514eea345dSchristos ssmin = PTHREAD_STACK_MIN; 3524eea345dSchristos rc = pthread_attr_setstacksize(&thr_attr, ssmin); 35368dbbb44Schristos if (0 != rc) 35468dbbb44Schristos msyslog(LOG_ERR, 35568dbbb44Schristos "my_pthread_warmup: pthread_attr_setstacksize() -> %s", 35668dbbb44Schristos strerror(rc)); 3574eea345dSchristos } 35868dbbb44Schristos #endif 359af12ab5eSchristos rc = pthread_create( 36068dbbb44Schristos &thread, &thr_attr, my_pthread_warmup_worker, NULL); 36168dbbb44Schristos pthread_attr_destroy(&thr_attr); 36268dbbb44Schristos if (0 != rc) { 36368dbbb44Schristos msyslog(LOG_ERR, 36468dbbb44Schristos "my_pthread_warmup: pthread_create() -> %s", 36568dbbb44Schristos strerror(rc)); 36668dbbb44Schristos } else { 367af12ab5eSchristos pthread_cancel(thread); 368af12ab5eSchristos pthread_join(thread, NULL); 369af12ab5eSchristos } 370af12ab5eSchristos } 371af12ab5eSchristos 372af12ab5eSchristos #endif /*defined(NEED_PTHREAD_WARMUP)*/ 3732950cc38Schristos 37468dbbb44Schristos #ifdef NEED_EARLY_FORK 37568dbbb44Schristos static void 37668dbbb44Schristos dummy_callback(void) { return; } 37768dbbb44Schristos 37868dbbb44Schristos static void 37968dbbb44Schristos fork_nonchroot_worker(void) { 38068dbbb44Schristos getaddrinfo_sometime("localhost", "ntp", NULL, INITIAL_DNS_RETRY, 38168dbbb44Schristos (gai_sometime_callback)&dummy_callback, NULL); 38268dbbb44Schristos } 38368dbbb44Schristos #endif /* NEED_EARLY_FORK */ 3842950cc38Schristos 385abb0f93cSkardel void 3862950cc38Schristos parse_cmdline_opts( 387abb0f93cSkardel int * pargc, 388abb0f93cSkardel char ***pargv 389abb0f93cSkardel ) 390abb0f93cSkardel { 3912950cc38Schristos static int parsed; 3922950cc38Schristos static int optct; 393abb0f93cSkardel 3942950cc38Schristos if (!parsed) 3953123f114Skardel optct = ntpOptionProcess(&ntpdOptions, *pargc, *pargv); 3962950cc38Schristos 3972950cc38Schristos parsed = 1; 3982950cc38Schristos 399abb0f93cSkardel *pargc -= optct; 400abb0f93cSkardel *pargv += optct; 401abb0f93cSkardel } 402abb0f93cSkardel 403abb0f93cSkardel 404abb0f93cSkardel #ifdef SIM 405abb0f93cSkardel int 406abb0f93cSkardel main( 407abb0f93cSkardel int argc, 408abb0f93cSkardel char *argv[] 409abb0f93cSkardel ) 410abb0f93cSkardel { 4112950cc38Schristos progname = argv[0]; 4122950cc38Schristos parse_cmdline_opts(&argc, &argv); 4132950cc38Schristos #ifdef DEBUG 4142950cc38Schristos debug = OPT_VALUE_SET_DEBUG_LEVEL; 4152950cc38Schristos DPRINTF(1, ("%s\n", Version)); 4162950cc38Schristos #endif 417abb0f93cSkardel 418abb0f93cSkardel return ntpsim(argc, argv); 419abb0f93cSkardel } 420cdfa2a7eSchristos #elif defined(NO_MAIN_ALLOWED) 421abb0f93cSkardel CALL(ntpd,"ntpd",ntpdmain); 422cdfa2a7eSchristos #elif !defined(SYS_WINNT) 423abb0f93cSkardel int 424abb0f93cSkardel main( 425abb0f93cSkardel int argc, 426abb0f93cSkardel char *argv[] 427abb0f93cSkardel ) 428abb0f93cSkardel { 429*eabc0478Schristos # ifdef DISABLE_FREEBSD_STACKGAP 430cdfa2a7eSchristos /* 431*eabc0478Schristos * We must disable ASLR stack gap on FreeBSD that has 432*eabc0478Schristos * PROC_STACKGAP_DISABLE up through early FreeBSD 14 433*eabc0478Schristos * versions to avoid a segfault. See: 434*eabc0478Schristos * 435*eabc0478Schristos * https://bugs.ntp.org/3627 436*eabc0478Schristos * https://cgit.freebsd.org/src/commit/?id=889b56c8cd84c9a9f2d9e3b019c154d6f14d9021 437*eabc0478Schristos * https://cgit.freebsd.org/src/commit/?id=fc393054398ea50fb0cee52704e9385afe888b48 438*eabc0478Schristos * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=253208 439*eabc0478Schristos * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=241421 440*eabc0478Schristos * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=241960 441cdfa2a7eSchristos */ 442cdfa2a7eSchristos int aslr_var = PROC_STACKGAP_DISABLE; 443cdfa2a7eSchristos 444*eabc0478Schristos procctl(P_PID, getpid(), PROC_STACKGAP_CTL, &aslr_var); 445*eabc0478Schristos # endif /* DISABLE_FREEBSD_STACKGAP */ 446*eabc0478Schristos 447abb0f93cSkardel return ntpdmain(argc, argv); 448abb0f93cSkardel } 4492950cc38Schristos #endif /* !SYS_WINNT */ 450abb0f93cSkardel 451abb0f93cSkardel #ifdef _AIX 452abb0f93cSkardel /* 453abb0f93cSkardel * OK. AIX is different than solaris in how it implements plock(). 454abb0f93cSkardel * If you do NOT adjust the stack limit, you will get the MAXIMUM 455abb0f93cSkardel * stack size allocated and PINNED with you program. To check the 456abb0f93cSkardel * value, use ulimit -a. 457abb0f93cSkardel * 458abb0f93cSkardel * To fix this, we create an automatic variable and set our stack limit 459abb0f93cSkardel * to that PLUS 32KB of extra space (we need some headroom). 460abb0f93cSkardel * 461abb0f93cSkardel * This subroutine gets the stack address. 462abb0f93cSkardel * 463abb0f93cSkardel * Grover Davidson and Matt Ladendorf 464abb0f93cSkardel * 465abb0f93cSkardel */ 466abb0f93cSkardel static char * 467abb0f93cSkardel get_aix_stack(void) 468abb0f93cSkardel { 469abb0f93cSkardel char ch; 470abb0f93cSkardel return (&ch); 471abb0f93cSkardel } 472abb0f93cSkardel 473abb0f93cSkardel /* 474abb0f93cSkardel * Signal handler for SIGDANGER. 475abb0f93cSkardel */ 476abb0f93cSkardel static void 477abb0f93cSkardel catch_danger(int signo) 478abb0f93cSkardel { 479abb0f93cSkardel msyslog(LOG_INFO, "ntpd: setpgid(): %m"); 480abb0f93cSkardel /* Make the system believe we'll free something, but don't do it! */ 481abb0f93cSkardel return; 482abb0f93cSkardel } 483abb0f93cSkardel #endif /* _AIX */ 484abb0f93cSkardel 485abb0f93cSkardel /* 486abb0f93cSkardel * Set the process priority 487abb0f93cSkardel */ 4882950cc38Schristos #ifndef SIM 489abb0f93cSkardel static void 490abb0f93cSkardel set_process_priority(void) 491abb0f93cSkardel { 492abb0f93cSkardel 493abb0f93cSkardel # ifdef DEBUG 494abb0f93cSkardel if (debug > 1) 495abb0f93cSkardel msyslog(LOG_DEBUG, "set_process_priority: %s: priority_done is <%d>", 496abb0f93cSkardel ((priority_done) 497abb0f93cSkardel ? "Leave priority alone" 498abb0f93cSkardel : "Attempt to set priority" 499abb0f93cSkardel ), 500abb0f93cSkardel priority_done); 501abb0f93cSkardel # endif /* DEBUG */ 502abb0f93cSkardel 503abb0f93cSkardel # if defined(HAVE_SCHED_SETSCHEDULER) 504abb0f93cSkardel if (!priority_done) { 505abb0f93cSkardel extern int config_priority_override, config_priority; 506abb0f93cSkardel int pmax, pmin; 507abb0f93cSkardel struct sched_param sched; 508abb0f93cSkardel 509abb0f93cSkardel pmax = sched_get_priority_max(SCHED_FIFO); 510abb0f93cSkardel sched.sched_priority = pmax; 511abb0f93cSkardel if ( config_priority_override ) { 512abb0f93cSkardel pmin = sched_get_priority_min(SCHED_FIFO); 513abb0f93cSkardel if ( config_priority > pmax ) 514abb0f93cSkardel sched.sched_priority = pmax; 515abb0f93cSkardel else if ( config_priority < pmin ) 516abb0f93cSkardel sched.sched_priority = pmin; 517abb0f93cSkardel else 518abb0f93cSkardel sched.sched_priority = config_priority; 519abb0f93cSkardel } 520abb0f93cSkardel if ( sched_setscheduler(0, SCHED_FIFO, &sched) == -1 ) 521abb0f93cSkardel msyslog(LOG_ERR, "sched_setscheduler(): %m"); 522abb0f93cSkardel else 523abb0f93cSkardel ++priority_done; 524abb0f93cSkardel } 525abb0f93cSkardel # endif /* HAVE_SCHED_SETSCHEDULER */ 5262950cc38Schristos # ifdef HAVE_RTPRIO 527abb0f93cSkardel # ifdef RTP_SET 528abb0f93cSkardel if (!priority_done) { 529abb0f93cSkardel struct rtprio srtp; 530abb0f93cSkardel 531abb0f93cSkardel srtp.type = RTP_PRIO_REALTIME; /* was: RTP_PRIO_NORMAL */ 532abb0f93cSkardel srtp.prio = 0; /* 0 (hi) -> RTP_PRIO_MAX (31,lo) */ 533abb0f93cSkardel 534abb0f93cSkardel if (rtprio(RTP_SET, getpid(), &srtp) < 0) 535abb0f93cSkardel msyslog(LOG_ERR, "rtprio() error: %m"); 536abb0f93cSkardel else 537abb0f93cSkardel ++priority_done; 538abb0f93cSkardel } 5392950cc38Schristos # else /* !RTP_SET follows */ 540abb0f93cSkardel if (!priority_done) { 541abb0f93cSkardel if (rtprio(0, 120) < 0) 542abb0f93cSkardel msyslog(LOG_ERR, "rtprio() error: %m"); 543abb0f93cSkardel else 544abb0f93cSkardel ++priority_done; 545abb0f93cSkardel } 5462950cc38Schristos # endif /* !RTP_SET */ 547abb0f93cSkardel # endif /* HAVE_RTPRIO */ 548abb0f93cSkardel # if defined(NTPD_PRIO) && NTPD_PRIO != 0 549abb0f93cSkardel # ifdef HAVE_ATT_NICE 550abb0f93cSkardel if (!priority_done) { 551abb0f93cSkardel errno = 0; 552abb0f93cSkardel if (-1 == nice (NTPD_PRIO) && errno != 0) 553abb0f93cSkardel msyslog(LOG_ERR, "nice() error: %m"); 554abb0f93cSkardel else 555abb0f93cSkardel ++priority_done; 556abb0f93cSkardel } 557abb0f93cSkardel # endif /* HAVE_ATT_NICE */ 558abb0f93cSkardel # ifdef HAVE_BSD_NICE 559abb0f93cSkardel if (!priority_done) { 560abb0f93cSkardel if (-1 == setpriority(PRIO_PROCESS, 0, NTPD_PRIO)) 561abb0f93cSkardel msyslog(LOG_ERR, "setpriority() error: %m"); 562abb0f93cSkardel else 563abb0f93cSkardel ++priority_done; 564abb0f93cSkardel } 565abb0f93cSkardel # endif /* HAVE_BSD_NICE */ 566abb0f93cSkardel # endif /* NTPD_PRIO && NTPD_PRIO != 0 */ 567abb0f93cSkardel if (!priority_done) 568abb0f93cSkardel msyslog(LOG_ERR, "set_process_priority: No way found to improve our priority"); 569abb0f93cSkardel } 5702950cc38Schristos #endif /* !SIM */ 571abb0f93cSkardel 57279045f13Schristos #if !defined(SIM) && !defined(SYS_WINNT) 57379045f13Schristos /* 57479045f13Schristos * Detach from terminal (much like daemon()) 57579045f13Schristos * Nothe that this function calls exit() 57679045f13Schristos */ 577cdfa2a7eSchristos # ifdef HAVE_WORKING_FORK 57879045f13Schristos static void 57979045f13Schristos detach_from_terminal( 580*eabc0478Schristos int pipes[2], 58179045f13Schristos long wait_sync, 58279045f13Schristos const char *logfilename 58379045f13Schristos ) 58479045f13Schristos { 585cdfa2a7eSchristos pid_t cpid; 58679045f13Schristos int exit_code; 58779045f13Schristos # if !defined(HAVE_SETSID) && !defined (HAVE_SETPGID) && defined(TIOCNOTTY) 58879045f13Schristos int fid; 58979045f13Schristos # endif 59079045f13Schristos # ifdef _AIX 59179045f13Schristos struct sigaction sa; 59279045f13Schristos # endif 59379045f13Schristos 594cdfa2a7eSchristos cpid = fork(); 595cdfa2a7eSchristos if (0 != cpid) { 59679045f13Schristos /* parent */ 597cdfa2a7eSchristos if (-1 == cpid) { 598cdfa2a7eSchristos msyslog(LOG_ERR, "fork: %m"); 599cdfa2a7eSchristos exit_code = EX_OSERR; 600cdfa2a7eSchristos } else { 601*eabc0478Schristos close(pipes[1]); 602*eabc0478Schristos pipes[1] = -1; 603cdfa2a7eSchristos exit_code = wait_child_sync_if( 604*eabc0478Schristos pipes[0], wait_sync); 605cdfa2a7eSchristos if (exit_code <= 0) { 606cdfa2a7eSchristos /* probe daemon exit code -- wait for 607cdfa2a7eSchristos * child process if we have an unexpected 608cdfa2a7eSchristos * EOF on the monitor pipe. 609cdfa2a7eSchristos */ 610cdfa2a7eSchristos exit_code = wait_child_exit_if( 611cdfa2a7eSchristos cpid, (exit_code < 0)); 612cdfa2a7eSchristos } 613cdfa2a7eSchristos } 61479045f13Schristos exit(exit_code); 61579045f13Schristos } 61679045f13Schristos 61779045f13Schristos /* 61879045f13Schristos * child/daemon 61979045f13Schristos * close all open files excepting waitsync_fd_to_close. 62079045f13Schristos * msyslog() unreliable until after init_logging(). 62179045f13Schristos */ 62279045f13Schristos closelog(); 62379045f13Schristos if (syslog_file != NULL) { 62479045f13Schristos fclose(syslog_file); 62579045f13Schristos syslog_file = NULL; 62679045f13Schristos syslogit = TRUE; 62779045f13Schristos } 628*eabc0478Schristos close_all_except(pipes[1]); 629*eabc0478Schristos pipes[0] = -1; 63079045f13Schristos INSIST(0 == open("/dev/null", 0) && 1 == dup2(0, 1) \ 63179045f13Schristos && 2 == dup2(0, 2)); 63279045f13Schristos 63379045f13Schristos init_logging(progname, 0, TRUE); 63479045f13Schristos /* we lost our logfile (if any) daemonizing */ 63579045f13Schristos setup_logfile(logfilename); 63679045f13Schristos 63779045f13Schristos # ifdef SYS_DOMAINOS 63879045f13Schristos { 63979045f13Schristos uid_$t puid; 64079045f13Schristos status_$t st; 64179045f13Schristos 64279045f13Schristos proc2_$who_am_i(&puid); 64379045f13Schristos proc2_$make_server(&puid, &st); 64479045f13Schristos } 64579045f13Schristos # endif /* SYS_DOMAINOS */ 64679045f13Schristos # ifdef HAVE_SETSID 64779045f13Schristos if (setsid() == (pid_t)-1) 64879045f13Schristos msyslog(LOG_ERR, "setsid(): %m"); 64979045f13Schristos # elif defined(HAVE_SETPGID) 65079045f13Schristos if (setpgid(0, 0) == -1) 65179045f13Schristos msyslog(LOG_ERR, "setpgid(): %m"); 65279045f13Schristos # else /* !HAVE_SETSID && !HAVE_SETPGID follows */ 65379045f13Schristos # ifdef TIOCNOTTY 65479045f13Schristos fid = open("/dev/tty", 2); 65579045f13Schristos if (fid >= 0) { 65679045f13Schristos ioctl(fid, (u_long)TIOCNOTTY, NULL); 65779045f13Schristos close(fid); 65879045f13Schristos } 65979045f13Schristos # endif /* TIOCNOTTY */ 66079045f13Schristos ntp_setpgrp(0, getpid()); 66179045f13Schristos # endif /* !HAVE_SETSID && !HAVE_SETPGID */ 66279045f13Schristos # ifdef _AIX 66379045f13Schristos /* Don't get killed by low-on-memory signal. */ 66479045f13Schristos sa.sa_handler = catch_danger; 66579045f13Schristos sigemptyset(&sa.sa_mask); 66679045f13Schristos sa.sa_flags = SA_RESTART; 66779045f13Schristos sigaction(SIGDANGER, &sa, NULL); 66879045f13Schristos # endif /* _AIX */ 66979045f13Schristos 67079045f13Schristos return; 67179045f13Schristos } 672cdfa2a7eSchristos # endif /* HAVE_WORKING_FORK */ 673*eabc0478Schristos #endif /* !SIM && !SYS_WINNT */ 67479045f13Schristos 67579045f13Schristos #ifdef HAVE_DROPROOT 67679045f13Schristos /* 67779045f13Schristos * Map user name/number to user ID 67879045f13Schristos */ 67979045f13Schristos static int 68079045f13Schristos map_user(void) 68179045f13Schristos { 68279045f13Schristos char *endp; 68379045f13Schristos 68479045f13Schristos if (isdigit((unsigned char)*user)) { 68579045f13Schristos sw_uid = (uid_t)strtoul(user, &endp, 0); 68679045f13Schristos if (*endp != '\0') 68779045f13Schristos goto getuser; 68879045f13Schristos 68979045f13Schristos if ((pw = getpwuid(sw_uid)) != NULL) { 69079045f13Schristos free(user); 69179045f13Schristos user = estrdup(pw->pw_name); 69279045f13Schristos sw_gid = pw->pw_gid; 69379045f13Schristos } else { 69479045f13Schristos errno = 0; 69579045f13Schristos msyslog(LOG_ERR, "Cannot find user ID %s", user); 69679045f13Schristos return 0; 69779045f13Schristos } 69879045f13Schristos 69979045f13Schristos } else { 70079045f13Schristos getuser: 70179045f13Schristos errno = 0; 70279045f13Schristos if ((pw = getpwnam(user)) != NULL) { 70379045f13Schristos sw_uid = pw->pw_uid; 70479045f13Schristos sw_gid = pw->pw_gid; 70579045f13Schristos } else { 70679045f13Schristos if (errno) 70779045f13Schristos msyslog(LOG_ERR, "getpwnam(%s) failed: %m", user); 70879045f13Schristos else 70979045f13Schristos msyslog(LOG_ERR, "Cannot find user `%s'", user); 71079045f13Schristos return 0; 71179045f13Schristos } 71279045f13Schristos } 71379045f13Schristos 71479045f13Schristos return 1; 71579045f13Schristos } 71679045f13Schristos 71779045f13Schristos /* 71879045f13Schristos * Map group name/number to group ID 71979045f13Schristos */ 72079045f13Schristos static int 72179045f13Schristos map_group(void) 72279045f13Schristos { 72379045f13Schristos char *endp; 72479045f13Schristos 72579045f13Schristos if (isdigit((unsigned char)*group)) { 72679045f13Schristos sw_gid = (gid_t)strtoul(group, &endp, 0); 72779045f13Schristos if (*endp != '\0') 72879045f13Schristos goto getgroup; 72979045f13Schristos } else { 73079045f13Schristos getgroup: 73179045f13Schristos if ((gr = getgrnam(group)) != NULL) { 73279045f13Schristos sw_gid = gr->gr_gid; 73379045f13Schristos } else { 73479045f13Schristos errno = 0; 73579045f13Schristos msyslog(LOG_ERR, "Cannot find group `%s'", group); 73679045f13Schristos return 0; 73779045f13Schristos } 73879045f13Schristos } 73979045f13Schristos 74079045f13Schristos return 1; 74179045f13Schristos } 74279045f13Schristos 7431f68464dSchristos static int 7441f68464dSchristos set_group_ids(void) 74579045f13Schristos { 74679045f13Schristos if (user && initgroups(user, sw_gid)) { 74779045f13Schristos msyslog(LOG_ERR, "Cannot initgroups() to user `%s': %m", user); 74879045f13Schristos return 0; 74979045f13Schristos } 75079045f13Schristos if (group && setgid(sw_gid)) { 75179045f13Schristos msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group); 75279045f13Schristos return 0; 75379045f13Schristos } 75479045f13Schristos if (group && setegid(sw_gid)) { 75579045f13Schristos msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group); 75679045f13Schristos return 0; 75779045f13Schristos } 75879045f13Schristos if (group) { 75979045f13Schristos if (0 != setgroups(1, &sw_gid)) { 76079045f13Schristos msyslog(LOG_ERR, "setgroups(1, %d) failed: %m", sw_gid); 76179045f13Schristos return 0; 76279045f13Schristos } 76379045f13Schristos } 76479045f13Schristos else if (pw) 76579045f13Schristos if (0 != initgroups(pw->pw_name, pw->pw_gid)) { 76679045f13Schristos msyslog(LOG_ERR, "initgroups(<%s>, %d) filed: %m", pw->pw_name, pw->pw_gid); 76779045f13Schristos return 0; 76879045f13Schristos } 7691f68464dSchristos return 1; 7701f68464dSchristos } 7711f68464dSchristos 7721f68464dSchristos static int 7731f68464dSchristos set_user_ids(void) 7741f68464dSchristos { 77579045f13Schristos if (user && setuid(sw_uid)) { 77679045f13Schristos msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user); 77779045f13Schristos return 0; 77879045f13Schristos } 77979045f13Schristos if (user && seteuid(sw_uid)) { 78079045f13Schristos msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user); 78179045f13Schristos return 0; 78279045f13Schristos } 7831f68464dSchristos return 1; 7841f68464dSchristos } 7851f68464dSchristos 7861f68464dSchristos /* 7871f68464dSchristos * Change (effective) user and group IDs, also initialize the supplementary group access list 7881f68464dSchristos */ 7891f68464dSchristos int set_user_group_ids(void); 7901f68464dSchristos int 7911f68464dSchristos set_user_group_ids(void) 7921f68464dSchristos { 7931f68464dSchristos /* If the the user was already mapped, no need to map it again */ 7941f68464dSchristos if ((NULL != user) && (0 == sw_uid)) { 7951f68464dSchristos if (0 == map_user()) 7961f68464dSchristos exit (-1); 7971f68464dSchristos } 7981f68464dSchristos /* same applies for the group */ 7991f68464dSchristos if ((NULL != group) && (0 == sw_gid)) { 8001f68464dSchristos if (0 == map_group()) 8011f68464dSchristos exit (-1); 8021f68464dSchristos } 8031f68464dSchristos 8041f68464dSchristos if (getegid() != sw_gid && 0 == set_group_ids()) 8051f68464dSchristos return 0; 8061f68464dSchristos if (geteuid() != sw_uid && 0 == set_user_ids()) 8071f68464dSchristos return 0; 80879045f13Schristos 80979045f13Schristos return 1; 81079045f13Schristos } 81179045f13Schristos #endif /* HAVE_DROPROOT */ 812abb0f93cSkardel 813abb0f93cSkardel /* 814abb0f93cSkardel * Main program. Initialize us, disconnect us from the tty if necessary, 815abb0f93cSkardel * and loop waiting for I/O and/or timer expiries. 816abb0f93cSkardel */ 8172950cc38Schristos #ifndef SIM 818abb0f93cSkardel int 819abb0f93cSkardel ntpdmain( 820abb0f93cSkardel int argc, 821abb0f93cSkardel char *argv[] 822abb0f93cSkardel ) 823abb0f93cSkardel { 824abb0f93cSkardel l_fp now; 825abb0f93cSkardel struct recvbuf *rbuf; 8262950cc38Schristos const char * logfilename; 8272950cc38Schristos # ifdef HAVE_UMASK 8282950cc38Schristos mode_t uv; 8292950cc38Schristos # endif 8302950cc38Schristos # if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */ 8312950cc38Schristos uid_t uid; 8322950cc38Schristos # endif 8332950cc38Schristos # if defined(HAVE_WORKING_FORK) 8342950cc38Schristos long wait_sync = 0; 8352950cc38Schristos # endif /* HAVE_WORKING_FORK*/ 8362950cc38Schristos # ifdef SCO5_CLOCK 8372950cc38Schristos int fd; 8382950cc38Schristos int zero; 8392950cc38Schristos # endif 840abb0f93cSkardel 841af12ab5eSchristos # ifdef NEED_PTHREAD_WARMUP 842af12ab5eSchristos my_pthread_warmup(); 843af12ab5eSchristos # endif 844af12ab5eSchristos 845abb0f93cSkardel # ifdef HAVE_UMASK 846abb0f93cSkardel uv = umask(0); 847abb0f93cSkardel if (uv) 8482950cc38Schristos umask(uv); 849abb0f93cSkardel else 8502950cc38Schristos umask(022); 8512950cc38Schristos # endif 8522950cc38Schristos saved_argc = argc; 8532950cc38Schristos saved_argv = argv; 8542950cc38Schristos progname = argv[0]; 8552950cc38Schristos initializing = TRUE; /* mark that we are initializing */ 8562950cc38Schristos parse_cmdline_opts(&argc, &argv); 8572950cc38Schristos # ifdef DEBUG 8582950cc38Schristos debug = OPT_VALUE_SET_DEBUG_LEVEL; 8592950cc38Schristos # ifdef HAVE_SETLINEBUF 8602950cc38Schristos setlinebuf(stdout); 8612950cc38Schristos # endif 862abb0f93cSkardel # endif 863abb0f93cSkardel 8642950cc38Schristos if (HAVE_OPT(NOFORK) || HAVE_OPT(QUIT) 8652950cc38Schristos # ifdef DEBUG 8662950cc38Schristos || debug 8672950cc38Schristos # endif 8682950cc38Schristos || HAVE_OPT(SAVECONFIGQUIT)) 8692950cc38Schristos nofork = TRUE; 870abb0f93cSkardel 8712950cc38Schristos init_logging(progname, NLOG_SYNCMASK, TRUE); 8722950cc38Schristos /* honor -l/--logfile option to log to a file */ 8732950cc38Schristos if (HAVE_OPT(LOGFILE)) { 8742950cc38Schristos logfilename = OPT_ARG(LOGFILE); 8752950cc38Schristos syslogit = FALSE; 8762950cc38Schristos change_logfile(logfilename, FALSE); 8772950cc38Schristos } else { 8782950cc38Schristos logfilename = NULL; 8792950cc38Schristos if (nofork) 8802950cc38Schristos msyslog_term = TRUE; 8812950cc38Schristos if (HAVE_OPT(SAVECONFIGQUIT)) 8822950cc38Schristos syslogit = FALSE; 8832950cc38Schristos } 8842950cc38Schristos msyslog(LOG_NOTICE, "%s: Starting", Version); 8852950cc38Schristos 8862950cc38Schristos { 8872950cc38Schristos int i; 8882950cc38Schristos char buf[1024]; /* Secret knowledge of msyslog buf length */ 8892950cc38Schristos char *cp = buf; 8902950cc38Schristos 8912950cc38Schristos /* Note that every arg has an initial space character */ 8922950cc38Schristos snprintf(cp, sizeof(buf), "Command line:"); 8932950cc38Schristos cp += strlen(cp); 8942950cc38Schristos 8952950cc38Schristos for (i = 0; i < saved_argc ; ++i) { 8962950cc38Schristos snprintf(cp, sizeof(buf) - (cp - buf), 8972950cc38Schristos " %s", saved_argv[i]); 8982950cc38Schristos cp += strlen(cp); 8992950cc38Schristos } 900cdfa2a7eSchristos msyslog(LOG_NOTICE, "%s", buf); 9012950cc38Schristos } 9022950cc38Schristos 903cdfa2a7eSchristos msyslog(LOG_NOTICE, "----------------------------------------------------"); 904cdfa2a7eSchristos msyslog(LOG_NOTICE, "ntp-4 is maintained by Network Time Foundation,"); 905cdfa2a7eSchristos msyslog(LOG_NOTICE, "Inc. (NTF), a non-profit 501(c)(3) public-benefit"); 906cdfa2a7eSchristos msyslog(LOG_NOTICE, "corporation. Support and training for ntp-4 are"); 907cdfa2a7eSchristos msyslog(LOG_NOTICE, "available at https://www.nwtime.org/support"); 908cdfa2a7eSchristos msyslog(LOG_NOTICE, "----------------------------------------------------"); 909*eabc0478Schristos #ifdef DEBUG 910*eabc0478Schristos msyslog(LOG_NOTICE, "DEBUG behavior is enabled - a violation of any" 911*eabc0478Schristos " diagnostic assertion will cause %s to abort", 912*eabc0478Schristos progname); 913*eabc0478Schristos #endif 914*eabc0478Schristos 915*eabc0478Schristos ssl_check_version(); 916cdfa2a7eSchristos 9172950cc38Schristos /* 9182950cc38Schristos * Install trap handlers to log errors and assertion failures. 9192950cc38Schristos * Default handlers print to stderr which doesn't work if detached. 9202950cc38Schristos */ 9212950cc38Schristos isc_assertion_setcallback(assertion_failed); 9222950cc38Schristos isc_error_setfatal(library_fatal_error); 9232950cc38Schristos isc_error_setunexpected(library_unexpected_error); 9242950cc38Schristos 9252950cc38Schristos /* MPE lacks the concept of root */ 9262950cc38Schristos # if defined(HAVE_GETUID) && !defined(MPE) 927abb0f93cSkardel uid = getuid(); 92879045f13Schristos if (uid && !HAVE_OPT( SAVECONFIGQUIT ) 92979045f13Schristos # if defined(HAVE_TRUSTEDBSD_MAC) 93079045f13Schristos /* We can run as non-root if the mac_ntpd policy is enabled. */ 93179045f13Schristos && mac_is_present("ntpd") != 1 93279045f13Schristos # endif 93379045f13Schristos ) { 9342950cc38Schristos msyslog_term = TRUE; 9352950cc38Schristos msyslog(LOG_ERR, 9362950cc38Schristos "must be run as root, not uid %ld", (long)uid); 937abb0f93cSkardel exit(1); 938abb0f93cSkardel } 939abb0f93cSkardel # endif 940abb0f93cSkardel 941abb0f93cSkardel /* 942abb0f93cSkardel * Enable the Multi-Media Timer for Windows? 943abb0f93cSkardel */ 944abb0f93cSkardel # ifdef SYS_WINNT 945abb0f93cSkardel if (HAVE_OPT( MODIFYMMTIMER )) 946abb0f93cSkardel set_mm_timer(MM_TIMER_HIRES); 947abb0f93cSkardel # endif 948abb0f93cSkardel 9492950cc38Schristos #ifdef HAVE_DNSREGISTRATION 9502950cc38Schristos /* 9512950cc38Schristos * Enable mDNS registrations? 9522950cc38Schristos */ 9532950cc38Schristos if (HAVE_OPT( MDNS )) { 9542950cc38Schristos mdnsreg = TRUE; 9552950cc38Schristos } 9562950cc38Schristos #endif /* HAVE_DNSREGISTRATION */ 957abb0f93cSkardel 958abb0f93cSkardel if (HAVE_OPT( NOVIRTUALIPS )) 959abb0f93cSkardel listen_to_virtual_ips = 0; 960abb0f93cSkardel 961abb0f93cSkardel /* 962abb0f93cSkardel * --interface, listen on specified interfaces 963abb0f93cSkardel */ 964abb0f93cSkardel if (HAVE_OPT( INTERFACE )) { 965abb0f93cSkardel int ifacect = STACKCT_OPT( INTERFACE ); 966abb0f93cSkardel const char** ifaces = STACKLST_OPT( INTERFACE ); 9673123f114Skardel sockaddr_u addr; 968abb0f93cSkardel 969abb0f93cSkardel while (ifacect-- > 0) { 970abb0f93cSkardel add_nic_rule( 9712950cc38Schristos is_ip_address(*ifaces, AF_UNSPEC, &addr) 972abb0f93cSkardel ? MATCH_IFADDR 973abb0f93cSkardel : MATCH_IFNAME, 974abb0f93cSkardel *ifaces, -1, ACTION_LISTEN); 975abb0f93cSkardel ifaces++; 976abb0f93cSkardel } 977abb0f93cSkardel } 978abb0f93cSkardel 979abb0f93cSkardel if (HAVE_OPT( NICE )) 980abb0f93cSkardel priority_done = 0; 981abb0f93cSkardel 9822950cc38Schristos # ifdef HAVE_SCHED_SETSCHEDULER 983abb0f93cSkardel if (HAVE_OPT( PRIORITY )) { 984abb0f93cSkardel config_priority = OPT_VALUE_PRIORITY; 985abb0f93cSkardel config_priority_override = 1; 986abb0f93cSkardel priority_done = 0; 987abb0f93cSkardel } 988abb0f93cSkardel # endif 989abb0f93cSkardel 9902950cc38Schristos # ifdef HAVE_WORKING_FORK 991cdfa2a7eSchristos /* make sure the FDs are initialised 992cdfa2a7eSchristos * 993cdfa2a7eSchristos * note: if WAIT_SYNC is requested, we *have* to fork. This will 994cdfa2a7eSchristos * overide any '-n' (nofork) or '-d' (debug) option presented on 995cdfa2a7eSchristos * the command line! 996cdfa2a7eSchristos */ 997cdfa2a7eSchristos if (HAVE_OPT(WAIT_SYNC)) { 9982950cc38Schristos wait_sync = OPT_VALUE_WAIT_SYNC; 999cdfa2a7eSchristos if (wait_sync <= 0) 10002950cc38Schristos wait_sync = 0; 1001cdfa2a7eSchristos else 10022950cc38Schristos nofork = FALSE; 10032950cc38Schristos } 1004cdfa2a7eSchristos if ( !nofork && pipe(daemon_pipe)) { 1005cdfa2a7eSchristos msyslog(LOG_ERR, 1006cdfa2a7eSchristos "Pipe creation failed for --wait-sync/daemon: %m"); 1007cdfa2a7eSchristos exit(EX_OSERR); 1008cdfa2a7eSchristos } 10092950cc38Schristos # endif /* HAVE_WORKING_FORK */ 10102950cc38Schristos 10112950cc38Schristos init_lib(); 1012abb0f93cSkardel # ifdef SYS_WINNT 1013abb0f93cSkardel /* 101479045f13Schristos * Make sure the service is initialized before we do anything else 101579045f13Schristos */ 101679045f13Schristos ntservice_init(); 101779045f13Schristos 101879045f13Schristos /* 1019abb0f93cSkardel * Start interpolation thread, must occur before first 1020abb0f93cSkardel * get_systime() 1021abb0f93cSkardel */ 1022abb0f93cSkardel init_winnt_time(); 1023abb0f93cSkardel # endif 1024abb0f93cSkardel /* 1025abb0f93cSkardel * Initialize random generator and public key pair 1026abb0f93cSkardel */ 1027abb0f93cSkardel get_systime(&now); 1028abb0f93cSkardel 1029abb0f93cSkardel ntp_srandom((int)(now.l_i * now.l_uf)); 1030abb0f93cSkardel 1031abb0f93cSkardel /* 1032abb0f93cSkardel * Detach us from the terminal. May need an #ifndef GIZMO. 1033abb0f93cSkardel */ 10342950cc38Schristos # ifdef HAVE_WORKING_FORK 1035cdfa2a7eSchristos if (!nofork) { 1036cdfa2a7eSchristos detach_from_terminal(daemon_pipe, wait_sync, logfilename); 1037abb0f93cSkardel } 1038cdfa2a7eSchristos # endif /* HAVE_WORKING_FORK */ 1039abb0f93cSkardel 1040abb0f93cSkardel # ifdef SCO5_CLOCK 1041abb0f93cSkardel /* 1042abb0f93cSkardel * SCO OpenServer's system clock offers much more precise timekeeping 1043abb0f93cSkardel * on the base CPU than the other CPUs (for multiprocessor systems), 1044abb0f93cSkardel * so we must lock to the base CPU. 1045abb0f93cSkardel */ 10462950cc38Schristos fd = open("/dev/at1", O_RDONLY); 1047abb0f93cSkardel if (fd >= 0) { 10482950cc38Schristos zero = 0; 1049abb0f93cSkardel if (ioctl(fd, ACPU_LOCK, &zero) < 0) 1050abb0f93cSkardel msyslog(LOG_ERR, "cannot lock to base CPU: %m"); 1051abb0f93cSkardel close(fd); 1052abb0f93cSkardel } 1053abb0f93cSkardel # endif 1054abb0f93cSkardel 10552950cc38Schristos /* Setup stack size in preparation for locking pages in memory. */ 10562950cc38Schristos # if defined(HAVE_MLOCKALL) 1057abb0f93cSkardel # ifdef HAVE_SETRLIMIT 10582950cc38Schristos ntp_rlimit(RLIMIT_STACK, DFLT_RLIMIT_STACK * 4096, 4096, "4k"); 1059abb0f93cSkardel # ifdef RLIMIT_MEMLOCK 1060abb0f93cSkardel /* 1061abb0f93cSkardel * The default RLIMIT_MEMLOCK is very low on Linux systems. 1062abb0f93cSkardel * Unless we increase this limit malloc calls are likely to 10632950cc38Schristos * fail if we drop root privilege. To be useful the value 1064abb0f93cSkardel * has to be larger than the largest ntpd resident set size. 1065abb0f93cSkardel */ 10662950cc38Schristos ntp_rlimit(RLIMIT_MEMLOCK, DFLT_RLIMIT_MEMLOCK * 1024 * 1024, 1024 * 1024, "MB"); 1067abb0f93cSkardel # endif /* RLIMIT_MEMLOCK */ 1068abb0f93cSkardel # endif /* HAVE_SETRLIMIT */ 10692950cc38Schristos # else /* !HAVE_MLOCKALL follows */ 1070abb0f93cSkardel # ifdef HAVE_PLOCK 1071abb0f93cSkardel # ifdef PROCLOCK 1072abb0f93cSkardel # ifdef _AIX 1073abb0f93cSkardel /* 1074abb0f93cSkardel * set the stack limit for AIX for plock(). 1075abb0f93cSkardel * see get_aix_stack() for more info. 1076abb0f93cSkardel */ 1077abb0f93cSkardel if (ulimit(SET_STACKLIM, (get_aix_stack() - 8 * 4096)) < 0) 10782950cc38Schristos msyslog(LOG_ERR, 10792950cc38Schristos "Cannot adjust stack limit for plock: %m"); 1080abb0f93cSkardel # endif /* _AIX */ 10812950cc38Schristos # endif /* PROCLOCK */ 1082abb0f93cSkardel # endif /* HAVE_PLOCK */ 10832950cc38Schristos # endif /* !HAVE_MLOCKALL */ 1084abb0f93cSkardel 1085abb0f93cSkardel /* 1086abb0f93cSkardel * Set up signals we pay attention to locally. 1087abb0f93cSkardel */ 1088abb0f93cSkardel # ifdef SIGDIE1 10892950cc38Schristos signal_no_reset(SIGDIE1, finish); 10902950cc38Schristos signal_no_reset(SIGDIE2, finish); 10912950cc38Schristos signal_no_reset(SIGDIE3, finish); 10922950cc38Schristos signal_no_reset(SIGDIE4, finish); 10932950cc38Schristos # endif 1094abb0f93cSkardel # ifdef SIGBUS 10952950cc38Schristos signal_no_reset(SIGBUS, finish); 10962950cc38Schristos # endif 1097abb0f93cSkardel 1098abb0f93cSkardel # if !defined(SYS_WINNT) && !defined(VMS) 1099abb0f93cSkardel # ifdef DEBUG 1100abb0f93cSkardel (void) signal_no_reset(MOREDEBUGSIG, moredebug); 1101abb0f93cSkardel (void) signal_no_reset(LESSDEBUGSIG, lessdebug); 1102abb0f93cSkardel # else 1103abb0f93cSkardel (void) signal_no_reset(MOREDEBUGSIG, no_debug); 1104abb0f93cSkardel (void) signal_no_reset(LESSDEBUGSIG, no_debug); 1105abb0f93cSkardel # endif /* DEBUG */ 1106abb0f93cSkardel # endif /* !SYS_WINNT && !VMS */ 1107abb0f93cSkardel 1108abb0f93cSkardel /* 1109abb0f93cSkardel * Set up signals we should never pay attention to. 1110abb0f93cSkardel */ 11112950cc38Schristos # ifdef SIGPIPE 11122950cc38Schristos signal_no_reset(SIGPIPE, SIG_IGN); 11132950cc38Schristos # endif 1114abb0f93cSkardel 1115abb0f93cSkardel /* 1116abb0f93cSkardel * Call the init_ routines to initialize the data structures. 1117abb0f93cSkardel * 1118abb0f93cSkardel * Exactly what command-line options are we expecting here? 1119abb0f93cSkardel */ 11202950cc38Schristos INIT_SSL(); 1121abb0f93cSkardel init_auth(); 1122abb0f93cSkardel init_util(); 1123abb0f93cSkardel init_restrict(); 1124abb0f93cSkardel init_mon(); 1125abb0f93cSkardel init_timer(); 1126abb0f93cSkardel init_request(); 1127abb0f93cSkardel init_control(); 1128abb0f93cSkardel init_peer(); 1129abb0f93cSkardel # ifdef REFCLOCK 1130abb0f93cSkardel init_refclock(); 1131abb0f93cSkardel # endif 1132abb0f93cSkardel set_process_priority(); 1133abb0f93cSkardel init_proto(); /* Call at high priority */ 1134abb0f93cSkardel init_io(); 1135abb0f93cSkardel init_loopfilter(); 1136abb0f93cSkardel mon_start(MON_ON); /* monitor on by default now */ 1137abb0f93cSkardel /* turn off in config if unwanted */ 1138abb0f93cSkardel 1139abb0f93cSkardel /* 1140abb0f93cSkardel * Get the configuration. This is done in a separate module 1141abb0f93cSkardel * since this will definitely be different for the gizmo board. 1142abb0f93cSkardel */ 1143abb0f93cSkardel getconfig(argc, argv); 11442950cc38Schristos 1145af12ab5eSchristos if (-1 == cur_memlock) { 11462950cc38Schristos # if defined(HAVE_MLOCKALL) 11472950cc38Schristos /* 11482950cc38Schristos * lock the process into memory 11492950cc38Schristos */ 1150af12ab5eSchristos if ( !HAVE_OPT(SAVECONFIGQUIT) 1151af12ab5eSchristos # ifdef RLIMIT_MEMLOCK 1152af12ab5eSchristos && -1 != DFLT_RLIMIT_MEMLOCK 1153af12ab5eSchristos # endif 1154af12ab5eSchristos && 0 != mlockall(MCL_CURRENT|MCL_FUTURE)) 11552950cc38Schristos msyslog(LOG_ERR, "mlockall(): %m"); 11562950cc38Schristos # else /* !HAVE_MLOCKALL follows */ 11572950cc38Schristos # ifdef HAVE_PLOCK 11582950cc38Schristos # ifdef PROCLOCK 11592950cc38Schristos /* 11602950cc38Schristos * lock the process into memory 11612950cc38Schristos */ 11622950cc38Schristos if (!HAVE_OPT(SAVECONFIGQUIT) && 0 != plock(PROCLOCK)) 11632950cc38Schristos msyslog(LOG_ERR, "plock(PROCLOCK): %m"); 11642950cc38Schristos # else /* !PROCLOCK follows */ 11652950cc38Schristos # ifdef TXTLOCK 11662950cc38Schristos /* 11672950cc38Schristos * Lock text into ram 11682950cc38Schristos */ 11692950cc38Schristos if (!HAVE_OPT(SAVECONFIGQUIT) && 0 != plock(TXTLOCK)) 11702950cc38Schristos msyslog(LOG_ERR, "plock(TXTLOCK) error: %m"); 11712950cc38Schristos # else /* !TXTLOCK follows */ 11722950cc38Schristos msyslog(LOG_ERR, "plock() - don't know what to lock!"); 11732950cc38Schristos # endif /* !TXTLOCK */ 11742950cc38Schristos # endif /* !PROCLOCK */ 11752950cc38Schristos # endif /* HAVE_PLOCK */ 11762950cc38Schristos # endif /* !HAVE_MLOCKALL */ 11772950cc38Schristos } 11782950cc38Schristos 11792950cc38Schristos loop_config(LOOP_DRIFTINIT, 0); 1180abb0f93cSkardel report_event(EVNT_SYSRESTART, NULL, NULL); 11812950cc38Schristos initializing = FALSE; 1182abb0f93cSkardel 1183cdfa2a7eSchristos # ifdef HAVE_LINUX_CAPABILITIES 1184cdfa2a7eSchristos { 1185cdfa2a7eSchristos /* Check that setting capabilities actually works; we might be 1186cdfa2a7eSchristos * run on a kernel with disabled capabilities. We must not 1187cdfa2a7eSchristos * drop privileges in this case. 1188cdfa2a7eSchristos */ 1189cdfa2a7eSchristos cap_t caps; 1190cdfa2a7eSchristos caps = cap_from_text("cap_sys_time,cap_setuid,cap_setgid,cap_sys_chroot,cap_net_bind_service=pe"); 1191cdfa2a7eSchristos if ( ! caps) { 1192cdfa2a7eSchristos msyslog( LOG_ERR, "cap_from_text() failed: %m" ); 1193cdfa2a7eSchristos exit(-1); 1194cdfa2a7eSchristos } 1195cdfa2a7eSchristos have_caps = (cap_set_proc(caps) == 0); 1196cdfa2a7eSchristos cap_free(caps); /* caps not NULL here! */ 1197cdfa2a7eSchristos } 1198cdfa2a7eSchristos # endif /* HAVE_LINUX_CAPABILITIES */ 1199cdfa2a7eSchristos 1200abb0f93cSkardel # ifdef HAVE_DROPROOT 1201cdfa2a7eSchristos # ifdef HAVE_LINUX_CAPABILITIES 1202cdfa2a7eSchristos if (droproot && have_caps) { 1203cdfa2a7eSchristos # else 1204abb0f93cSkardel if (droproot) { 1205cdfa2a7eSchristos # endif /*HAVE_LINUX_CAPABILITIES*/ 120668dbbb44Schristos 120768dbbb44Schristos # ifdef NEED_EARLY_FORK 120868dbbb44Schristos fork_nonchroot_worker(); 120968dbbb44Schristos # endif 121068dbbb44Schristos 1211abb0f93cSkardel /* Drop super-user privileges and chroot now if the OS supports this */ 1212abb0f93cSkardel 1213abb0f93cSkardel # ifdef HAVE_LINUX_CAPABILITIES 1214abb0f93cSkardel /* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */ 1215abb0f93cSkardel if (prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1) { 1216abb0f93cSkardel msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" ); 1217abb0f93cSkardel exit(-1); 1218abb0f93cSkardel } 12192950cc38Schristos # elif HAVE_SOLARIS_PRIVS 12202950cc38Schristos /* Nothing to do here */ 1221abb0f93cSkardel # else 1222abb0f93cSkardel /* we need a user to switch to */ 1223abb0f93cSkardel if (user == NULL) { 1224abb0f93cSkardel msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" ); 1225abb0f93cSkardel exit(-1); 1226abb0f93cSkardel } 12272950cc38Schristos # endif /* HAVE_LINUX_CAPABILITIES || HAVE_SOLARIS_PRIVS */ 1228abb0f93cSkardel 1229abb0f93cSkardel if (user != NULL) { 123079045f13Schristos if (0 == map_user()) 1231abb0f93cSkardel exit (-1); 1232abb0f93cSkardel } 1233abb0f93cSkardel if (group != NULL) { 123479045f13Schristos if (0 == map_group()) 1235abb0f93cSkardel exit (-1); 1236abb0f93cSkardel } 1237abb0f93cSkardel 1238abb0f93cSkardel if (chrootdir ) { 1239abb0f93cSkardel /* make sure cwd is inside the jail: */ 1240abb0f93cSkardel if (chdir(chrootdir)) { 1241abb0f93cSkardel msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir); 1242abb0f93cSkardel exit (-1); 1243abb0f93cSkardel } 1244abb0f93cSkardel if (chroot(chrootdir)) { 1245abb0f93cSkardel msyslog(LOG_ERR, "Cannot chroot() to `%s': %m", chrootdir); 1246abb0f93cSkardel exit (-1); 1247abb0f93cSkardel } 1248abb0f93cSkardel if (chdir("/")) { 1249abb0f93cSkardel msyslog(LOG_ERR, "Cannot chdir() to`root after chroot(): %m"); 1250abb0f93cSkardel exit (-1); 1251abb0f93cSkardel } 1252abb0f93cSkardel } 12532950cc38Schristos # ifdef HAVE_SOLARIS_PRIVS 12542950cc38Schristos if ((lowprivs = priv_str_to_set(LOWPRIVS, ",", NULL)) == NULL) { 12552950cc38Schristos msyslog(LOG_ERR, "priv_str_to_set() failed:%m"); 12562950cc38Schristos exit(-1); 12572950cc38Schristos } 12582950cc38Schristos if ((highprivs = priv_allocset()) == NULL) { 12592950cc38Schristos msyslog(LOG_ERR, "priv_allocset() failed:%m"); 12602950cc38Schristos exit(-1); 12612950cc38Schristos } 12622950cc38Schristos (void) getppriv(PRIV_PERMITTED, highprivs); 12632950cc38Schristos (void) priv_intersect(highprivs, lowprivs); 12642950cc38Schristos if (setppriv(PRIV_SET, PRIV_PERMITTED, lowprivs) == -1) { 12652950cc38Schristos msyslog(LOG_ERR, "setppriv() failed:%m"); 12662950cc38Schristos exit(-1); 12672950cc38Schristos } 12682950cc38Schristos # endif /* HAVE_SOLARIS_PRIVS */ 126979045f13Schristos if (0 == set_user_group_ids()) 1270abb0f93cSkardel exit(-1); 1271abb0f93cSkardel 127279045f13Schristos # if defined(HAVE_TRUSTEDBSD_MAC) 127379045f13Schristos /* 127479045f13Schristos * To manipulate system time and (re-)bind to NTP_PORT as needed 127579045f13Schristos * following interface changes, we must either run as uid 0 or 127679045f13Schristos * the mac_ntpd policy module must be enabled. 127779045f13Schristos */ 127879045f13Schristos if (sw_uid != 0 && mac_is_present("ntpd") != 1) { 127979045f13Schristos msyslog(LOG_ERR, "Need MAC 'ntpd' policy enabled to drop root privileges"); 128079045f13Schristos exit (-1); 128179045f13Schristos } 128279045f13Schristos # elif !defined(HAVE_LINUX_CAPABILITIES) && !defined(HAVE_SOLARIS_PRIVS) 1283abb0f93cSkardel /* 1284abb0f93cSkardel * for now assume that the privilege to bind to privileged ports 1285abb0f93cSkardel * is associated with running with uid 0 - should be refined on 1286abb0f93cSkardel * ports that allow binding to NTP_PORT with uid != 0 1287abb0f93cSkardel */ 1288*eabc0478Schristos scan_addrs_once |= (sw_uid != 0); /* used by routing socket code */ 12892950cc38Schristos # endif /* !HAVE_LINUX_CAPABILITIES && !HAVE_SOLARIS_PRIVS */ 1290abb0f93cSkardel 1291*eabc0478Schristos if (scan_addrs_once) { 12922950cc38Schristos msyslog(LOG_INFO, "running as non-root disables dynamic interface tracking"); 1293abb0f93cSkardel } 1294abb0f93cSkardel 1295abb0f93cSkardel # ifdef HAVE_LINUX_CAPABILITIES 12962950cc38Schristos { 1297abb0f93cSkardel /* 1298abb0f93cSkardel * We may be running under non-root uid now, but we still hold full root privileges! 1299abb0f93cSkardel * We drop all of them, except for the crucial one or two: cap_sys_time and 1300abb0f93cSkardel * cap_net_bind_service if doing dynamic interface tracking. 1301abb0f93cSkardel */ 1302abb0f93cSkardel cap_t caps; 13032950cc38Schristos char *captext; 13042950cc38Schristos 1305*eabc0478Schristos captext = (scan_addrs_once) 1306*eabc0478Schristos ? "cap_sys_time=pe" 1307*eabc0478Schristos : "cap_sys_time,cap_net_bind_service=pe"; 13082950cc38Schristos caps = cap_from_text(captext); 13092950cc38Schristos if (!caps) { 13102950cc38Schristos msyslog(LOG_ERR, 13112950cc38Schristos "cap_from_text(%s) failed: %m", 13122950cc38Schristos captext); 1313abb0f93cSkardel exit(-1); 1314abb0f93cSkardel } 13152950cc38Schristos if (-1 == cap_set_proc(caps)) { 13162950cc38Schristos msyslog(LOG_ERR, 13172950cc38Schristos "cap_set_proc() failed to drop root privs: %m"); 1318abb0f93cSkardel exit(-1); 1319abb0f93cSkardel } 1320abb0f93cSkardel cap_free(caps); 13212950cc38Schristos } 1322abb0f93cSkardel # endif /* HAVE_LINUX_CAPABILITIES */ 13232950cc38Schristos # ifdef HAVE_SOLARIS_PRIVS 13242950cc38Schristos if (priv_delset(lowprivs, "proc_setid") == -1) { 13252950cc38Schristos msyslog(LOG_ERR, "priv_delset() failed:%m"); 13262950cc38Schristos exit(-1); 13272950cc38Schristos } 13282950cc38Schristos if (setppriv(PRIV_SET, PRIV_PERMITTED, lowprivs) == -1) { 13292950cc38Schristos msyslog(LOG_ERR, "setppriv() failed:%m"); 13302950cc38Schristos exit(-1); 13312950cc38Schristos } 13322950cc38Schristos priv_freeset(lowprivs); 13332950cc38Schristos priv_freeset(highprivs); 13342950cc38Schristos # endif /* HAVE_SOLARIS_PRIVS */ 13352950cc38Schristos root_dropped = TRUE; 13362950cc38Schristos fork_deferred_worker(); 1337abb0f93cSkardel } /* if (droproot) */ 1338abb0f93cSkardel # endif /* HAVE_DROPROOT */ 1339abb0f93cSkardel 1340ea66d795Schristos /* libssecomp sandboxing */ 1341ea66d795Schristos #if defined (LIBSECCOMP) && (KERN_SECCOMP) 1342ea66d795Schristos scmp_filter_ctx ctx; 1343ea66d795Schristos 1344ea66d795Schristos if ((ctx = seccomp_init(SCMP_ACT_KILL)) < 0) 1345ea66d795Schristos msyslog(LOG_ERR, "%s: seccomp_init(SCMP_ACT_KILL) failed: %m", __func__); 1346ea66d795Schristos else { 1347ea66d795Schristos msyslog(LOG_DEBUG, "%s: seccomp_init(SCMP_ACT_KILL) succeeded", __func__); 1348ea66d795Schristos } 1349ea66d795Schristos 1350ea66d795Schristos #ifdef __x86_64__ 1351ea66d795Schristos int scmp_sc[] = { 1352ea66d795Schristos SCMP_SYS(adjtimex), 1353ea66d795Schristos SCMP_SYS(bind), 1354ea66d795Schristos SCMP_SYS(brk), 1355ea66d795Schristos SCMP_SYS(chdir), 1356ea66d795Schristos SCMP_SYS(clock_gettime), 1357ea66d795Schristos SCMP_SYS(clock_settime), 1358ea66d795Schristos SCMP_SYS(close), 1359ea66d795Schristos SCMP_SYS(connect), 1360ea66d795Schristos SCMP_SYS(exit_group), 1361ea66d795Schristos SCMP_SYS(fstat), 1362ea66d795Schristos SCMP_SYS(fsync), 1363ea66d795Schristos SCMP_SYS(futex), 1364ea66d795Schristos SCMP_SYS(getitimer), 1365ea66d795Schristos SCMP_SYS(getsockname), 1366ea66d795Schristos SCMP_SYS(ioctl), 1367ea66d795Schristos SCMP_SYS(lseek), 1368ea66d795Schristos SCMP_SYS(madvise), 1369ea66d795Schristos SCMP_SYS(mmap), 1370ea66d795Schristos SCMP_SYS(munmap), 1371ea66d795Schristos SCMP_SYS(open), 1372ea66d795Schristos SCMP_SYS(poll), 1373ea66d795Schristos SCMP_SYS(read), 1374ea66d795Schristos SCMP_SYS(recvmsg), 1375ea66d795Schristos SCMP_SYS(rename), 1376ea66d795Schristos SCMP_SYS(rt_sigaction), 1377ea66d795Schristos SCMP_SYS(rt_sigprocmask), 1378ea66d795Schristos SCMP_SYS(rt_sigreturn), 1379ea66d795Schristos SCMP_SYS(select), 1380ea66d795Schristos SCMP_SYS(sendto), 1381ea66d795Schristos SCMP_SYS(setitimer), 1382ea66d795Schristos SCMP_SYS(setsid), 1383ea66d795Schristos SCMP_SYS(socket), 1384ea66d795Schristos SCMP_SYS(stat), 1385ea66d795Schristos SCMP_SYS(time), 1386ea66d795Schristos SCMP_SYS(write), 1387ea66d795Schristos }; 1388ea66d795Schristos #endif 1389ea66d795Schristos #ifdef __i386__ 1390ea66d795Schristos int scmp_sc[] = { 1391ea66d795Schristos SCMP_SYS(_newselect), 1392ea66d795Schristos SCMP_SYS(adjtimex), 1393ea66d795Schristos SCMP_SYS(brk), 1394ea66d795Schristos SCMP_SYS(chdir), 1395ea66d795Schristos SCMP_SYS(clock_gettime), 1396ea66d795Schristos SCMP_SYS(clock_settime), 1397ea66d795Schristos SCMP_SYS(close), 1398ea66d795Schristos SCMP_SYS(exit_group), 1399ea66d795Schristos SCMP_SYS(fsync), 1400ea66d795Schristos SCMP_SYS(futex), 1401ea66d795Schristos SCMP_SYS(getitimer), 1402ea66d795Schristos SCMP_SYS(madvise), 1403ea66d795Schristos SCMP_SYS(mmap), 1404ea66d795Schristos SCMP_SYS(mmap2), 1405ea66d795Schristos SCMP_SYS(munmap), 1406ea66d795Schristos SCMP_SYS(open), 1407ea66d795Schristos SCMP_SYS(poll), 1408ea66d795Schristos SCMP_SYS(read), 1409ea66d795Schristos SCMP_SYS(rename), 1410ea66d795Schristos SCMP_SYS(rt_sigaction), 1411ea66d795Schristos SCMP_SYS(rt_sigprocmask), 1412ea66d795Schristos SCMP_SYS(select), 1413ea66d795Schristos SCMP_SYS(setitimer), 1414ea66d795Schristos SCMP_SYS(setsid), 1415ea66d795Schristos SCMP_SYS(sigprocmask), 1416ea66d795Schristos SCMP_SYS(sigreturn), 1417ea66d795Schristos SCMP_SYS(socketcall), 1418ea66d795Schristos SCMP_SYS(stat64), 1419ea66d795Schristos SCMP_SYS(time), 1420ea66d795Schristos SCMP_SYS(write), 1421ea66d795Schristos }; 1422ea66d795Schristos #endif 1423ea66d795Schristos { 1424ea66d795Schristos int i; 1425ea66d795Schristos 1426ea66d795Schristos for (i = 0; i < COUNTOF(scmp_sc); i++) { 1427ea66d795Schristos if (seccomp_rule_add(ctx, 1428ea66d795Schristos SCMP_ACT_ALLOW, scmp_sc[i], 0) < 0) { 1429ea66d795Schristos msyslog(LOG_ERR, 1430ea66d795Schristos "%s: seccomp_rule_add() failed: %m", 1431ea66d795Schristos __func__); 1432ea66d795Schristos } 1433ea66d795Schristos } 1434ea66d795Schristos } 1435ea66d795Schristos 1436ea66d795Schristos if (seccomp_load(ctx) < 0) 1437ea66d795Schristos msyslog(LOG_ERR, "%s: seccomp_load() failed: %m", 1438ea66d795Schristos __func__); 1439ea66d795Schristos else { 1440ea66d795Schristos msyslog(LOG_DEBUG, "%s: seccomp_load() succeeded", __func__); 1441ea66d795Schristos } 1442ea66d795Schristos #endif /* LIBSECCOMP and KERN_SECCOMP */ 1443ea66d795Schristos 144479045f13Schristos ntservice_isup(); 1445*eabc0478Schristos #if defined(HAVE_WORKING_FORK) 1446*eabc0478Schristos if (daemon_pipe[1] != -1 && 0 == wait_sync) { 1447*eabc0478Schristos if (2 != write(daemon_pipe[1], "R\n", 2)) { 1448*eabc0478Schristos msyslog(LOG_ERR, "daemon failed to notify parent ntpd after init"); 1449*eabc0478Schristos } 1450*eabc0478Schristos close(daemon_pipe[1]); 1451*eabc0478Schristos daemon_pipe[1] = -1; 1452cdfa2a7eSchristos } 1453cdfa2a7eSchristos #endif /* HAVE_WORKING_FORK */ 145479045f13Schristos 1455*eabc0478Schristos if (scan_addrs_once || no_periodic_scan) { 1456*eabc0478Schristos endpt_scan_timer = 0; 1457*eabc0478Schristos } 1458*eabc0478Schristos 1459cdfa2a7eSchristos # ifndef HAVE_IO_COMPLETION_PORT 1460abb0f93cSkardel BLOCK_IO_AND_ALARM(); 14612950cc38Schristos was_alarmed = FALSE; 1462cdfa2a7eSchristos # endif 1463abb0f93cSkardel 14642950cc38Schristos for (;;) { 146568dbbb44Schristos #if !defined(SIM) && defined(SIGDIE1) 146668dbbb44Schristos if (signalled) 146768dbbb44Schristos finish_safe(signo); 146868dbbb44Schristos #endif 1469cdfa2a7eSchristos # ifdef HAVE_IO_COMPLETION_PORT 1470cdfa2a7eSchristos GetReceivedBuffers(); 1471cdfa2a7eSchristos 1472cdfa2a7eSchristos # else /* normal I/O */ 14732950cc38Schristos if (alarm_flag) { /* alarmed? */ 14742950cc38Schristos was_alarmed = TRUE; 14752950cc38Schristos alarm_flag = FALSE; 1476abb0f93cSkardel } 1477abb0f93cSkardel 147868dbbb44Schristos /* collect async name/addr results */ 147968dbbb44Schristos if (!was_alarmed) 148068dbbb44Schristos harvest_blocking_responses(); 148168dbbb44Schristos 14822950cc38Schristos if (!was_alarmed && !has_full_recv_buffer()) { 1483abb0f93cSkardel /* 1484abb0f93cSkardel * Nothing to do. Wait for something. 1485abb0f93cSkardel */ 14862950cc38Schristos io_handler(); 1487abb0f93cSkardel } 1488abb0f93cSkardel 14892950cc38Schristos if (alarm_flag) { /* alarmed? */ 14902950cc38Schristos was_alarmed = TRUE; 14912950cc38Schristos alarm_flag = FALSE; 14922950cc38Schristos } 14932950cc38Schristos 14942950cc38Schristos if (was_alarmed) { 1495abb0f93cSkardel UNBLOCK_IO_AND_ALARM(); 1496abb0f93cSkardel /* 1497abb0f93cSkardel * Out here, signals are unblocked. Call timer routine 1498abb0f93cSkardel * to process expiry. 1499abb0f93cSkardel */ 1500abb0f93cSkardel timer(); 15012950cc38Schristos was_alarmed = FALSE; 1502abb0f93cSkardel BLOCK_IO_AND_ALARM(); 1503abb0f93cSkardel } 1504abb0f93cSkardel 1505abb0f93cSkardel # endif /* !HAVE_IO_COMPLETION_PORT */ 1506abb0f93cSkardel 1507abb0f93cSkardel # ifdef DEBUG_TIMING 1508abb0f93cSkardel { 1509abb0f93cSkardel l_fp pts; 1510abb0f93cSkardel l_fp tsa, tsb; 1511abb0f93cSkardel int bufcount = 0; 1512abb0f93cSkardel 1513abb0f93cSkardel get_systime(&pts); 1514abb0f93cSkardel tsa = pts; 1515abb0f93cSkardel # endif 1516abb0f93cSkardel rbuf = get_full_recv_buffer(); 15172950cc38Schristos while (rbuf != NULL) { 15182950cc38Schristos if (alarm_flag) { 15192950cc38Schristos was_alarmed = TRUE; 15202950cc38Schristos alarm_flag = FALSE; 1521abb0f93cSkardel } 1522abb0f93cSkardel UNBLOCK_IO_AND_ALARM(); 1523abb0f93cSkardel 15242950cc38Schristos if (was_alarmed) { 15252950cc38Schristos /* avoid timer starvation during lengthy I/O handling */ 1526abb0f93cSkardel timer(); 15272950cc38Schristos was_alarmed = FALSE; 1528abb0f93cSkardel } 1529abb0f93cSkardel 1530abb0f93cSkardel /* 1531abb0f93cSkardel * Call the data procedure to handle each received 1532abb0f93cSkardel * packet. 1533abb0f93cSkardel */ 15342950cc38Schristos if (rbuf->receiver != NULL) { 1535abb0f93cSkardel # ifdef DEBUG_TIMING 1536abb0f93cSkardel l_fp dts = pts; 1537abb0f93cSkardel 1538abb0f93cSkardel L_SUB(&dts, &rbuf->recv_time); 1539abb0f93cSkardel DPRINTF(2, ("processing timestamp delta %s (with prec. fuzz)\n", lfptoa(&dts, 9))); 1540abb0f93cSkardel collect_timing(rbuf, "buffer processing delay", 1, &dts); 1541abb0f93cSkardel bufcount++; 1542abb0f93cSkardel # endif 15432950cc38Schristos (*rbuf->receiver)(rbuf); 1544abb0f93cSkardel } else { 15452950cc38Schristos msyslog(LOG_ERR, "fatal: receive buffer callback NULL"); 1546abb0f93cSkardel abort(); 1547abb0f93cSkardel } 1548abb0f93cSkardel 1549abb0f93cSkardel BLOCK_IO_AND_ALARM(); 1550abb0f93cSkardel freerecvbuf(rbuf); 1551abb0f93cSkardel rbuf = get_full_recv_buffer(); 1552abb0f93cSkardel } 1553abb0f93cSkardel # ifdef DEBUG_TIMING 1554abb0f93cSkardel get_systime(&tsb); 1555abb0f93cSkardel L_SUB(&tsb, &tsa); 1556abb0f93cSkardel if (bufcount) { 1557abb0f93cSkardel collect_timing(NULL, "processing", bufcount, &tsb); 1558abb0f93cSkardel DPRINTF(2, ("processing time for %d buffers %s\n", bufcount, lfptoa(&tsb, 9))); 1559abb0f93cSkardel } 1560abb0f93cSkardel } 1561abb0f93cSkardel # endif 1562abb0f93cSkardel 1563abb0f93cSkardel /* 1564abb0f93cSkardel * Go around again 1565abb0f93cSkardel */ 1566abb0f93cSkardel 1567abb0f93cSkardel # ifdef HAVE_DNSREGISTRATION 1568abb0f93cSkardel if (mdnsreg && (current_time - mdnsreg ) > 60 && mdnstries && sys_leap != LEAP_NOTINSYNC) { 1569abb0f93cSkardel mdnsreg = current_time; 15703b2862d1Schristos msyslog(LOG_INFO, "Attempting to register mDNS"); 1571abb0f93cSkardel if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL, 1572abb0f93cSkardel htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) { 1573abb0f93cSkardel if (!--mdnstries) { 1574abb0f93cSkardel msyslog(LOG_ERR, "Unable to register mDNS, giving up."); 1575abb0f93cSkardel } else { 1576abb0f93cSkardel msyslog(LOG_INFO, "Unable to register mDNS, will try later."); 1577abb0f93cSkardel } 1578abb0f93cSkardel } else { 1579abb0f93cSkardel msyslog(LOG_INFO, "mDNS service registered."); 15802950cc38Schristos mdnsreg = FALSE; 1581abb0f93cSkardel } 1582abb0f93cSkardel } 1583abb0f93cSkardel # endif /* HAVE_DNSREGISTRATION */ 1584abb0f93cSkardel 1585abb0f93cSkardel } 1586abb0f93cSkardel UNBLOCK_IO_AND_ALARM(); 1587abb0f93cSkardel return 1; 1588abb0f93cSkardel } 15892950cc38Schristos #endif /* !SIM */ 1590abb0f93cSkardel 1591abb0f93cSkardel 15922950cc38Schristos #if !defined(SIM) && defined(SIGDIE1) 1593abb0f93cSkardel /* 1594abb0f93cSkardel * finish - exit gracefully 1595abb0f93cSkardel */ 159668dbbb44Schristos static void 159768dbbb44Schristos finish_safe( 1598abb0f93cSkardel int sig 1599abb0f93cSkardel ) 1600abb0f93cSkardel { 16012950cc38Schristos const char *sig_desc; 16022950cc38Schristos 16032950cc38Schristos sig_desc = NULL; 16042950cc38Schristos #ifdef HAVE_STRSIGNAL 16052950cc38Schristos sig_desc = strsignal(sig); 16062950cc38Schristos #endif 16072950cc38Schristos if (sig_desc == NULL) 16082950cc38Schristos sig_desc = ""; 16092950cc38Schristos msyslog(LOG_NOTICE, "%s exiting on signal %d (%s)", progname, 16102950cc38Schristos sig, sig_desc); 1611ea66d795Schristos /* See Bug 2513 and Bug 2522 re the unlink of PIDFILE */ 1612abb0f93cSkardel # ifdef HAVE_DNSREGISTRATION 1613abb0f93cSkardel if (mdns != NULL) 1614abb0f93cSkardel DNSServiceRefDeallocate(mdns); 1615abb0f93cSkardel # endif 16167476e6e4Schristos peer_cleanup(); 1617abb0f93cSkardel exit(0); 1618abb0f93cSkardel } 161968dbbb44Schristos 162068dbbb44Schristos static RETSIGTYPE 162168dbbb44Schristos finish( 162268dbbb44Schristos int sig 162368dbbb44Schristos ) 162468dbbb44Schristos { 162568dbbb44Schristos signalled = 1; 162668dbbb44Schristos signo = sig; 162768dbbb44Schristos } 162868dbbb44Schristos 16292950cc38Schristos #endif /* !SIM && SIGDIE1 */ 1630abb0f93cSkardel 1631abb0f93cSkardel 16322950cc38Schristos #ifndef SIM 16332950cc38Schristos /* 16342950cc38Schristos * wait_child_sync_if - implements parent side of -w/--wait-sync 1635abb0f93cSkardel */ 16362950cc38Schristos # ifdef HAVE_WORKING_FORK 1637cdfa2a7eSchristos 16382950cc38Schristos static int 16392950cc38Schristos wait_child_sync_if( 16402950cc38Schristos int pipe_read_fd, 1641cdfa2a7eSchristos unsigned long wait_sync 16422950cc38Schristos ) 16432950cc38Schristos { 16442950cc38Schristos int rc; 1645cdfa2a7eSchristos char ch; 16462950cc38Schristos time_t wait_end_time; 16472950cc38Schristos time_t cur_time; 16482950cc38Schristos time_t wait_rem; 16492950cc38Schristos fd_set readset; 16502950cc38Schristos struct timeval wtimeout; 16512950cc38Schristos 1652cdfa2a7eSchristos /* we wait a bit for the child in *any* case, because on failure 1653cdfa2a7eSchristos * of the child we have to get and inspect the exit code! 1654cdfa2a7eSchristos */ 1655cdfa2a7eSchristos wait_end_time = time(NULL); 1656cdfa2a7eSchristos if (wait_sync) 1657cdfa2a7eSchristos wait_end_time += wait_sync; 1658cdfa2a7eSchristos else 1659cdfa2a7eSchristos wait_end_time += 30; 16602950cc38Schristos 16612950cc38Schristos do { 16622950cc38Schristos cur_time = time(NULL); 16632950cc38Schristos wait_rem = (wait_end_time > cur_time) 16642950cc38Schristos ? (wait_end_time - cur_time) 16652950cc38Schristos : 0; 16662950cc38Schristos wtimeout.tv_sec = wait_rem; 16672950cc38Schristos wtimeout.tv_usec = 0; 16682950cc38Schristos FD_ZERO(&readset); 16692950cc38Schristos FD_SET(pipe_read_fd, &readset); 16702950cc38Schristos rc = select(pipe_read_fd + 1, &readset, NULL, NULL, 16712950cc38Schristos &wtimeout); 16722950cc38Schristos if (-1 == rc) { 16732950cc38Schristos if (EINTR == errno) 16742950cc38Schristos continue; 16752950cc38Schristos msyslog(LOG_ERR, 1676cdfa2a7eSchristos "daemon startup: select failed: %m"); 1677cdfa2a7eSchristos return EX_IOERR; 16782950cc38Schristos } 16792950cc38Schristos if (0 == rc) { 16802950cc38Schristos /* 16812950cc38Schristos * select() indicated a timeout, but in case 16822950cc38Schristos * its timeouts are affected by a step of the 16832950cc38Schristos * system clock, select() again with a zero 16842950cc38Schristos * timeout to confirm. 16852950cc38Schristos */ 16862950cc38Schristos FD_ZERO(&readset); 16872950cc38Schristos FD_SET(pipe_read_fd, &readset); 16882950cc38Schristos wtimeout.tv_sec = 0; 16892950cc38Schristos wtimeout.tv_usec = 0; 16902950cc38Schristos rc = select(pipe_read_fd + 1, &readset, NULL, 16912950cc38Schristos NULL, &wtimeout); 16922950cc38Schristos if (0 == rc) /* select() timeout */ 16932950cc38Schristos break; 1694cdfa2a7eSchristos } 1695cdfa2a7eSchristos rc = read(pipe_read_fd, &ch, 1); 1696cdfa2a7eSchristos if (rc == 0) { 1697*eabc0478Schristos /* DPRINTF is useless here as -d/-D disable forking */ 1698*eabc0478Schristos fprintf(stderr, "daemon control: got EOF\n"); 1699cdfa2a7eSchristos return -1; /* unexpected EOF, check daemon */ 1700cdfa2a7eSchristos } else if (rc == 1) { 1701*eabc0478Schristos if ( ('S' == ch && wait_sync > 0) 1702*eabc0478Schristos || ('R' == ch && 0 == wait_sync)) { 17032950cc38Schristos return 0; 1704*eabc0478Schristos } 1705cdfa2a7eSchristos } else { 1706*eabc0478Schristos mfprintf(stderr, "%s: daemon control: read 1 char failed: %m\n", 1707*eabc0478Schristos progname); 1708*eabc0478Schristos msyslog(LOG_ERR, "daemon control: read 1 char failed: %m"); 1709cdfa2a7eSchristos return EX_IOERR; 1710cdfa2a7eSchristos } 17112950cc38Schristos } while (wait_rem > 0); 17122950cc38Schristos 1713*eabc0478Schristos if (wait_sync > 0) { 17142950cc38Schristos fprintf(stderr, "%s: -w/--wait-sync %ld timed out.\n", 17152950cc38Schristos progname, wait_sync); 1716*eabc0478Schristos msyslog(LOG_ERR, "-w/--wait-sync %ld timed out.", wait_sync); 1717cdfa2a7eSchristos return EX_PROTOCOL; 1718cdfa2a7eSchristos } else { 1719cdfa2a7eSchristos fprintf(stderr, "%s: daemon startup monitoring timed out.\n", 1720cdfa2a7eSchristos progname); 1721*eabc0478Schristos msyslog(LOG_ERR, "daemon startup monitoring timed out."); 1722cdfa2a7eSchristos return 0; 17232950cc38Schristos } 1724cdfa2a7eSchristos } 1725cdfa2a7eSchristos 1726cdfa2a7eSchristos 1727cdfa2a7eSchristos static int 1728cdfa2a7eSchristos wait_child_exit_if( 1729cdfa2a7eSchristos pid_t cpid, 1730cdfa2a7eSchristos int blocking 1731cdfa2a7eSchristos ) 1732cdfa2a7eSchristos { 1733cdfa2a7eSchristos # ifdef HAVE_WAITPID 1734cdfa2a7eSchristos int rc = 0; 1735cdfa2a7eSchristos int wstatus; 1736cdfa2a7eSchristos if (cpid == waitpid(cpid, &wstatus, (blocking ? 0 : WNOHANG))) { 1737cdfa2a7eSchristos if (WIFEXITED(wstatus)) { 1738cdfa2a7eSchristos rc = WEXITSTATUS(wstatus); 1739cdfa2a7eSchristos msyslog(LOG_ERR, "daemon child exited with code %d", 1740cdfa2a7eSchristos rc); 1741cdfa2a7eSchristos } else if (WIFSIGNALED(wstatus)) { 1742cdfa2a7eSchristos rc = EX_SOFTWARE; 1743cdfa2a7eSchristos msyslog(LOG_ERR, "daemon child died with signal %d", 1744cdfa2a7eSchristos WTERMSIG(wstatus)); 1745cdfa2a7eSchristos } else { 1746cdfa2a7eSchristos rc = EX_SOFTWARE; 1747cdfa2a7eSchristos msyslog(LOG_ERR, "daemon child died with unknown cause"); 1748cdfa2a7eSchristos } 1749cdfa2a7eSchristos } 1750cdfa2a7eSchristos return rc; 1751cdfa2a7eSchristos # else 1752cdfa2a7eSchristos UNUSED_ARG(cpid); 1753cdfa2a7eSchristos return 0; 1754cdfa2a7eSchristos # endif 1755cdfa2a7eSchristos } 1756cdfa2a7eSchristos 17572950cc38Schristos # endif /* HAVE_WORKING_FORK */ 17582950cc38Schristos 1759abb0f93cSkardel 1760abb0f93cSkardel /* 17612950cc38Schristos * assertion_failed - Redirect assertion failures to msyslog(). 1762abb0f93cSkardel */ 1763abb0f93cSkardel static void 17642950cc38Schristos assertion_failed( 17652950cc38Schristos const char *file, 17662950cc38Schristos int line, 17672950cc38Schristos isc_assertiontype_t type, 17682950cc38Schristos const char *cond 17692950cc38Schristos ) 1770abb0f93cSkardel { 1771abb0f93cSkardel isc_assertion_setcallback(NULL); /* Avoid recursion */ 1772abb0f93cSkardel 1773abb0f93cSkardel msyslog(LOG_ERR, "%s:%d: %s(%s) failed", 1774abb0f93cSkardel file, line, isc_assertion_typetotext(type), cond); 1775abb0f93cSkardel msyslog(LOG_ERR, "exiting (due to assertion failure)"); 1776abb0f93cSkardel 17772950cc38Schristos #if defined(DEBUG) && defined(SYS_WINNT) 17782950cc38Schristos if (debug) 17792950cc38Schristos DebugBreak(); 17802950cc38Schristos #endif 17812950cc38Schristos 1782abb0f93cSkardel abort(); 1783abb0f93cSkardel } 1784abb0f93cSkardel 17852950cc38Schristos 1786abb0f93cSkardel /* 1787abb0f93cSkardel * library_fatal_error - Handle fatal errors from our libraries. 1788abb0f93cSkardel */ 1789abb0f93cSkardel static void 17902950cc38Schristos library_fatal_error( 17912950cc38Schristos const char *file, 17922950cc38Schristos int line, 17932950cc38Schristos const char *format, 17942950cc38Schristos va_list args 17952950cc38Schristos ) 1796abb0f93cSkardel { 1797abb0f93cSkardel char errbuf[256]; 1798abb0f93cSkardel 1799abb0f93cSkardel isc_error_setfatal(NULL); /* Avoid recursion */ 1800abb0f93cSkardel 1801abb0f93cSkardel msyslog(LOG_ERR, "%s:%d: fatal error:", file, line); 1802abb0f93cSkardel vsnprintf(errbuf, sizeof(errbuf), format, args); 18037fdb569fSchristos msyslog(LOG_ERR, "%s", errbuf); 1804abb0f93cSkardel msyslog(LOG_ERR, "exiting (due to fatal error in library)"); 1805abb0f93cSkardel 18062950cc38Schristos #if defined(DEBUG) && defined(SYS_WINNT) 18072950cc38Schristos if (debug) 18082950cc38Schristos DebugBreak(); 18092950cc38Schristos #endif 18102950cc38Schristos 1811abb0f93cSkardel abort(); 1812abb0f93cSkardel } 1813abb0f93cSkardel 18142950cc38Schristos 1815abb0f93cSkardel /* 1816abb0f93cSkardel * library_unexpected_error - Handle non fatal errors from our libraries. 1817abb0f93cSkardel */ 1818abb0f93cSkardel # define MAX_UNEXPECTED_ERRORS 100 1819abb0f93cSkardel int unexpected_error_cnt = 0; 1820abb0f93cSkardel static void 18212950cc38Schristos library_unexpected_error( 18222950cc38Schristos const char *file, 18232950cc38Schristos int line, 18242950cc38Schristos const char *format, 18252950cc38Schristos va_list args 18262950cc38Schristos ) 1827abb0f93cSkardel { 1828abb0f93cSkardel char errbuf[256]; 1829abb0f93cSkardel 1830abb0f93cSkardel if (unexpected_error_cnt >= MAX_UNEXPECTED_ERRORS) 1831abb0f93cSkardel return; /* avoid clutter in log */ 1832abb0f93cSkardel 1833abb0f93cSkardel msyslog(LOG_ERR, "%s:%d: unexpected error:", file, line); 1834abb0f93cSkardel vsnprintf(errbuf, sizeof(errbuf), format, args); 18357fdb569fSchristos msyslog(LOG_ERR, "%s", errbuf); 1836abb0f93cSkardel 1837abb0f93cSkardel if (++unexpected_error_cnt == MAX_UNEXPECTED_ERRORS) 1838abb0f93cSkardel msyslog(LOG_ERR, "Too many errors. Shutting up."); 1839abb0f93cSkardel 1840abb0f93cSkardel } 18412950cc38Schristos #endif /* !SIM */ 1842abb0f93cSkardel 18432950cc38Schristos #if !defined(SIM) && !defined(SYS_WINNT) 1844abb0f93cSkardel # ifdef DEBUG 18452950cc38Schristos 1846abb0f93cSkardel /* 1847abb0f93cSkardel * moredebug - increase debugging verbosity 1848abb0f93cSkardel */ 1849abb0f93cSkardel static RETSIGTYPE 1850abb0f93cSkardel moredebug( 1851abb0f93cSkardel int sig 1852abb0f93cSkardel ) 1853abb0f93cSkardel { 1854abb0f93cSkardel int saved_errno = errno; 1855abb0f93cSkardel 1856abb0f93cSkardel if (debug < 255) 1857abb0f93cSkardel { 1858abb0f93cSkardel debug++; 1859abb0f93cSkardel msyslog(LOG_DEBUG, "debug raised to %d", debug); 1860abb0f93cSkardel } 1861abb0f93cSkardel errno = saved_errno; 1862abb0f93cSkardel } 1863abb0f93cSkardel 18642950cc38Schristos 1865abb0f93cSkardel /* 1866abb0f93cSkardel * lessdebug - decrease debugging verbosity 1867abb0f93cSkardel */ 1868abb0f93cSkardel static RETSIGTYPE 1869abb0f93cSkardel lessdebug( 1870abb0f93cSkardel int sig 1871abb0f93cSkardel ) 1872abb0f93cSkardel { 1873abb0f93cSkardel int saved_errno = errno; 1874abb0f93cSkardel 1875abb0f93cSkardel if (debug > 0) 1876abb0f93cSkardel { 1877abb0f93cSkardel debug--; 1878abb0f93cSkardel msyslog(LOG_DEBUG, "debug lowered to %d", debug); 1879abb0f93cSkardel } 1880abb0f93cSkardel errno = saved_errno; 1881abb0f93cSkardel } 18822950cc38Schristos 18832950cc38Schristos # else /* !DEBUG follows */ 18842950cc38Schristos 18852950cc38Schristos 1886abb0f93cSkardel /* 1887abb0f93cSkardel * no_debug - We don't do the debug here. 1888abb0f93cSkardel */ 1889abb0f93cSkardel static RETSIGTYPE 1890abb0f93cSkardel no_debug( 1891abb0f93cSkardel int sig 1892abb0f93cSkardel ) 1893abb0f93cSkardel { 1894abb0f93cSkardel int saved_errno = errno; 1895abb0f93cSkardel 1896abb0f93cSkardel msyslog(LOG_DEBUG, "ntpd not compiled for debugging (signal %d)", sig); 1897abb0f93cSkardel errno = saved_errno; 1898abb0f93cSkardel } 18992950cc38Schristos # endif /* !DEBUG */ 19002950cc38Schristos #endif /* !SIM && !SYS_WINNT */ 1901