154359Sroberto/* 254359Sroberto * ntpd.c - main program for the fixed point NTP daemon 354359Sroberto */ 482498Sroberto 554359Sroberto#ifdef HAVE_CONFIG_H 654359Sroberto# include <config.h> 754359Sroberto#endif 854359Sroberto 9106163Sroberto#include "ntp_machine.h" 1082498Sroberto#include "ntpd.h" 1182498Sroberto#include "ntp_io.h" 1282498Sroberto#include "ntp_stdlib.h" 13182007Sroberto#include <ntp_random.h> 1482498Sroberto 15132451Sroberto#ifdef SIM 16182007Sroberto# include "ntpsim.h" 17182007Sroberto# include "ntpdsim-opts.h" 18182007Sroberto#else 19182007Sroberto# include "ntpd-opts.h" 20132451Sroberto#endif 21132451Sroberto 2254359Sroberto#ifdef HAVE_UNISTD_H 2354359Sroberto# include <unistd.h> 2454359Sroberto#endif 2554359Sroberto#ifdef HAVE_SYS_STAT_H 2654359Sroberto# include <sys/stat.h> 2754359Sroberto#endif 2854359Sroberto#include <stdio.h> 29200576Sroberto#if !defined(VMS) /*wjm*/ 30200576Sroberto# ifdef HAVE_SYS_PARAM_H 31200576Sroberto# include <sys/param.h> 32106163Sroberto# endif 33200576Sroberto#endif /* VMS */ 34200576Sroberto#ifdef HAVE_SYS_SIGNAL_H 35200576Sroberto# include <sys/signal.h> 3654359Sroberto#else 3754359Sroberto# include <signal.h> 38200576Sroberto#endif 39200576Sroberto#ifdef HAVE_SYS_IOCTL_H 40200576Sroberto# include <sys/ioctl.h> 41200576Sroberto#endif /* HAVE_SYS_IOCTL_H */ 42200576Sroberto#ifdef HAVE_SYS_RESOURCE_H 43200576Sroberto# include <sys/resource.h> 44200576Sroberto#endif /* HAVE_SYS_RESOURCE_H */ 4554359Sroberto#if defined(HAVE_RTPRIO) 4654359Sroberto# ifdef HAVE_SYS_RESOURCE_H 4754359Sroberto# include <sys/resource.h> 4854359Sroberto# endif 4954359Sroberto# ifdef HAVE_SYS_LOCK_H 5054359Sroberto# include <sys/lock.h> 5154359Sroberto# endif 5254359Sroberto# include <sys/rtprio.h> 5354359Sroberto#else 5454359Sroberto# ifdef HAVE_PLOCK 5554359Sroberto# ifdef HAVE_SYS_LOCK_H 5654359Sroberto# include <sys/lock.h> 5754359Sroberto# endif 5854359Sroberto# endif 5954359Sroberto#endif 6054359Sroberto#if defined(HAVE_SCHED_SETSCHEDULER) 6154359Sroberto# ifdef HAVE_SCHED_H 6254359Sroberto# include <sched.h> 6354359Sroberto# else 6454359Sroberto# ifdef HAVE_SYS_SCHED_H 6554359Sroberto# include <sys/sched.h> 6654359Sroberto# endif 6754359Sroberto# endif 6854359Sroberto#endif 6954359Sroberto#if defined(HAVE_SYS_MMAN_H) 7054359Sroberto# include <sys/mman.h> 7154359Sroberto#endif 7254359Sroberto 7354359Sroberto#ifdef HAVE_TERMIOS_H 7454359Sroberto# include <termios.h> 7554359Sroberto#endif 7654359Sroberto 7754359Sroberto#ifdef SYS_DOMAINOS 7854359Sroberto# include <apollo/base.h> 7954359Sroberto#endif /* SYS_DOMAINOS */ 8054359Sroberto 8154359Sroberto#include "recvbuff.h" 8282498Sroberto#include "ntp_cmdargs.h" 8354359Sroberto 8454359Sroberto#if 0 /* HMS: I don't think we need this. 961223 */ 8554359Sroberto#ifdef LOCK_PROCESS 8654359Sroberto# ifdef SYS_SOLARIS 8754359Sroberto# include <sys/mman.h> 8854359Sroberto# else 8954359Sroberto# include <sys/lock.h> 9054359Sroberto# endif 9154359Sroberto#endif 9254359Sroberto#endif 9354359Sroberto 9454359Sroberto#ifdef _AIX 9582498Sroberto# include <ulimit.h> 9654359Sroberto#endif /* _AIX */ 9754359Sroberto 9854359Sroberto#ifdef SCO5_CLOCK 9982498Sroberto# include <sys/ci/ciioctl.h> 10054359Sroberto#endif 10154359Sroberto 102182007Sroberto#ifdef HAVE_DROPROOT 103132451Sroberto# include <ctype.h> 104132451Sroberto# include <grp.h> 105132451Sroberto# include <pwd.h> 106182007Sroberto#ifdef HAVE_LINUX_CAPABILITIES 107182007Sroberto# include <sys/capability.h> 108182007Sroberto# include <sys/prctl.h> 109132451Sroberto#endif 110182007Sroberto#endif 11182498Sroberto 11254359Sroberto/* 11354359Sroberto * Signals we catch for debugging. If not debugging we ignore them. 11454359Sroberto */ 11554359Sroberto#define MOREDEBUGSIG SIGUSR1 11654359Sroberto#define LESSDEBUGSIG SIGUSR2 11754359Sroberto 11854359Sroberto/* 11954359Sroberto * Signals which terminate us gracefully. 12054359Sroberto */ 12154359Sroberto#ifndef SYS_WINNT 12282498Sroberto# define SIGDIE1 SIGHUP 12382498Sroberto# define SIGDIE3 SIGQUIT 12482498Sroberto# define SIGDIE2 SIGINT 12582498Sroberto# define SIGDIE4 SIGTERM 12654359Sroberto#endif /* SYS_WINNT */ 12754359Sroberto 128182007Sroberto#ifdef HAVE_DNSREGISTRATION 129182007Sroberto#include <dns_sd.h> 130182007SrobertoDNSServiceRef mdns; 131182007Sroberto#endif 13254359Sroberto 13354359Sroberto/* 13454359Sroberto * Scheduling priority we run at 13554359Sroberto */ 13682498Sroberto#define NTPD_PRIO (-12) 13754359Sroberto 13882498Srobertoint priority_done = 2; /* 0 - Set priority */ 13982498Sroberto /* 1 - priority is OK where it is */ 14082498Sroberto /* 2 - Don't set priority */ 14182498Sroberto /* 1 and 2 are pretty much the same */ 14282498Sroberto 143182007Sroberto#ifdef DEBUG 14454359Sroberto/* 14554359Sroberto * Debugging flag 14654359Sroberto */ 147182007Srobertovolatile int debug = 0; /* No debugging by default */ 148182007Sroberto#endif 14954359Sroberto 150182007Srobertoint listen_to_virtual_ips = 1; 151182007Srobertoconst char *specific_interface = NULL; /* interface name or IP address to bind to */ 152132451Sroberto 153132451Sroberto/* 15454359Sroberto * No-fork flag. If set, we do not become a background daemon. 15554359Sroberto */ 156182007Srobertoint nofork = 0; /* Fork by default */ 15754359Sroberto 158182007Sroberto#ifdef HAVE_DROPROOT 159182007Srobertoint droproot = 0; 160132451Srobertochar *user = NULL; /* User to switch to */ 161132451Srobertochar *group = NULL; /* group to switch to */ 162132451Srobertochar *chrootdir = NULL; /* directory to chroot to */ 163132451Srobertoint sw_uid; 164132451Srobertoint sw_gid; 165132451Srobertochar *endp; 166132451Srobertostruct group *gr; 167132451Srobertostruct passwd *pw; 168182007Sroberto#endif /* HAVE_DROPROOT */ 169132451Sroberto 17054359Sroberto/* 17154359Sroberto * Initializing flag. All async routines watch this and only do their 17254359Sroberto * thing when it is clear. 17354359Sroberto */ 17454359Srobertoint initializing; 17554359Sroberto 17654359Sroberto/* 17754359Sroberto * Version declaration 17854359Sroberto */ 17954359Srobertoextern const char *Version; 18054359Sroberto 181182007Srobertochar const *progname; 182182007Sroberto 18354359Srobertoint was_alarmed; 18454359Sroberto 18554359Sroberto#ifdef DECL_SYSCALL 18654359Sroberto/* 18754359Sroberto * We put this here, since the argument profile is syscall-specific 18854359Sroberto */ 18954359Srobertoextern int syscall P((int, ...)); 19054359Sroberto#endif /* DECL_SYSCALL */ 19154359Sroberto 19254359Sroberto 19354359Sroberto#ifdef SIGDIE2 19454359Srobertostatic RETSIGTYPE finish P((int)); 19554359Sroberto#endif /* SIGDIE2 */ 19654359Sroberto 19754359Sroberto#ifdef DEBUG 198132451Sroberto#ifndef SYS_WINNT 19954359Srobertostatic RETSIGTYPE moredebug P((int)); 20054359Srobertostatic RETSIGTYPE lessdebug P((int)); 201132451Sroberto#endif 20254359Sroberto#else /* not DEBUG */ 20354359Srobertostatic RETSIGTYPE no_debug P((int)); 20454359Sroberto#endif /* not DEBUG */ 20554359Sroberto 20654359Srobertoint ntpdmain P((int, char **)); 20754359Srobertostatic void set_process_priority P((void)); 208182007Srobertostatic void init_logging P((char const *)); 209182007Srobertostatic void setup_logfile P((void)); 21054359Sroberto 211182007Sroberto/* 212182007Sroberto * Initialize the logging 213182007Sroberto */ 214182007Srobertovoid 215182007Srobertoinit_logging(char const *name) 216182007Sroberto{ 217182007Sroberto const char *cp; 218182007Sroberto 219182007Sroberto /* 220182007Sroberto * Logging. This may actually work on the gizmo board. Find a name 221182007Sroberto * to log with by using the basename 222182007Sroberto */ 223182007Sroberto cp = strrchr(name, '/'); 224182007Sroberto if (cp == 0) 225182007Sroberto cp = name; 226182007Sroberto else 227182007Sroberto cp++; 228182007Sroberto 229182007Sroberto#if !defined(VMS) 230182007Sroberto 231182007Sroberto# ifndef LOG_DAEMON 232182007Sroberto openlog(cp, LOG_PID); 233182007Sroberto# else /* LOG_DAEMON */ 234182007Sroberto 235182007Sroberto# ifndef LOG_NTP 236182007Sroberto# define LOG_NTP LOG_DAEMON 237182007Sroberto# endif 238182007Sroberto openlog(cp, LOG_PID | LOG_NDELAY, LOG_NTP); 239182007Sroberto# ifdef DEBUG 240182007Sroberto if (debug) 241182007Sroberto setlogmask(LOG_UPTO(LOG_DEBUG)); 242182007Sroberto else 243182007Sroberto# endif /* DEBUG */ 244182007Sroberto setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */ 245182007Sroberto# endif /* LOG_DAEMON */ 246182007Sroberto#endif /* !SYS_WINNT && !VMS */ 247182007Sroberto 248182007Sroberto NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */ 249182007Sroberto msyslog(LOG_NOTICE, "%s", Version); 250182007Sroberto} 251182007Sroberto 252182007Sroberto 253182007Sroberto/* 254182007Sroberto * See if we should redirect the logfile 255182007Sroberto */ 256182007Sroberto 257182007Srobertovoid 258182007Srobertosetup_logfile( 259182007Sroberto void 260182007Sroberto ) 261182007Sroberto{ 262182007Sroberto if (HAVE_OPT( LOGFILE )) { 263182007Sroberto const char *my_optarg = OPT_ARG( LOGFILE ); 264182007Sroberto FILE *new_file; 265182007Sroberto 266182007Sroberto if(strcmp(my_optarg, "stderr") == 0) 267182007Sroberto new_file = stderr; 268182007Sroberto else if(strcmp(my_optarg, "stdout") == 0) 269182007Sroberto new_file = stdout; 270182007Sroberto else 271182007Sroberto new_file = fopen(my_optarg, "a"); 272182007Sroberto if (new_file != NULL) { 273182007Sroberto NLOG(NLOG_SYSINFO) 274182007Sroberto msyslog(LOG_NOTICE, "logging to file %s", my_optarg); 275182007Sroberto if (syslog_file != NULL && 276182007Sroberto fileno(syslog_file) != fileno(new_file)) 277182007Sroberto (void)fclose(syslog_file); 278182007Sroberto 279182007Sroberto syslog_file = new_file; 280182007Sroberto syslogit = 0; 281182007Sroberto } 282182007Sroberto else 283182007Sroberto msyslog(LOG_ERR, 284182007Sroberto "Cannot open log file %s", 285182007Sroberto my_optarg); 286182007Sroberto } 287182007Sroberto} 288182007Sroberto 289132451Sroberto#ifdef SIM 290132451Srobertoint 291132451Srobertomain( 292132451Sroberto int argc, 293132451Sroberto char *argv[] 294132451Sroberto ) 295132451Sroberto{ 296132451Sroberto return ntpsim(argc, argv); 297132451Sroberto} 298132451Sroberto#else /* SIM */ 29954359Sroberto#ifdef NO_MAIN_ALLOWED 30054359SrobertoCALL(ntpd,"ntpd",ntpdmain); 30154359Sroberto#else 302182007Sroberto#ifndef SYS_WINNT 30354359Srobertoint 30454359Srobertomain( 30554359Sroberto int argc, 30654359Sroberto char *argv[] 30754359Sroberto ) 30854359Sroberto{ 30954359Sroberto return ntpdmain(argc, argv); 31054359Sroberto} 311182007Sroberto#endif /* SYS_WINNT */ 312182007Sroberto#endif /* NO_MAIN_ALLOWED */ 313132451Sroberto#endif /* SIM */ 31454359Sroberto 31554359Sroberto#ifdef _AIX 31654359Sroberto/* 31754359Sroberto * OK. AIX is different than solaris in how it implements plock(). 31854359Sroberto * If you do NOT adjust the stack limit, you will get the MAXIMUM 31954359Sroberto * stack size allocated and PINNED with you program. To check the 32054359Sroberto * value, use ulimit -a. 32154359Sroberto * 32254359Sroberto * To fix this, we create an automatic variable and set our stack limit 32354359Sroberto * to that PLUS 32KB of extra space (we need some headroom). 32454359Sroberto * 32554359Sroberto * This subroutine gets the stack address. 32654359Sroberto * 32754359Sroberto * Grover Davidson and Matt Ladendorf 32854359Sroberto * 32954359Sroberto */ 33054359Srobertostatic char * 33154359Srobertoget_aix_stack(void) 33254359Sroberto{ 33354359Sroberto char ch; 33454359Sroberto return (&ch); 33554359Sroberto} 33654359Sroberto 33754359Sroberto/* 33854359Sroberto * Signal handler for SIGDANGER. 33954359Sroberto */ 34054359Srobertostatic void 34154359Srobertocatch_danger(int signo) 34254359Sroberto{ 34354359Sroberto msyslog(LOG_INFO, "ntpd: setpgid(): %m"); 34454359Sroberto /* Make the system believe we'll free something, but don't do it! */ 34554359Sroberto return; 34654359Sroberto} 34754359Sroberto#endif /* _AIX */ 34854359Sroberto 34954359Sroberto/* 35054359Sroberto * Set the process priority 35154359Sroberto */ 35254359Srobertostatic void 35354359Srobertoset_process_priority(void) 35454359Sroberto{ 35554359Sroberto 35682498Sroberto#ifdef DEBUG 35782498Sroberto if (debug > 1) 35882498Sroberto msyslog(LOG_DEBUG, "set_process_priority: %s: priority_done is <%d>", 35982498Sroberto ((priority_done) 36082498Sroberto ? "Leave priority alone" 36182498Sroberto : "Attempt to set priority" 36282498Sroberto ), 36382498Sroberto priority_done); 36482498Sroberto#endif /* DEBUG */ 36582498Sroberto 36654359Sroberto#ifdef SYS_WINNT 36782498Sroberto priority_done += NT_set_process_priority(); 36856746Sroberto#endif 36956746Sroberto 37082498Sroberto#if defined(HAVE_SCHED_SETSCHEDULER) 37182498Sroberto if (!priority_done) { 37254359Sroberto extern int config_priority_override, config_priority; 37354359Sroberto int pmax, pmin; 37454359Sroberto struct sched_param sched; 37554359Sroberto 37654359Sroberto pmax = sched_get_priority_max(SCHED_FIFO); 37754359Sroberto sched.sched_priority = pmax; 37854359Sroberto if ( config_priority_override ) { 37954359Sroberto pmin = sched_get_priority_min(SCHED_FIFO); 38054359Sroberto if ( config_priority > pmax ) 38154359Sroberto sched.sched_priority = pmax; 38254359Sroberto else if ( config_priority < pmin ) 38354359Sroberto sched.sched_priority = pmin; 38454359Sroberto else 38554359Sroberto sched.sched_priority = config_priority; 38654359Sroberto } 38754359Sroberto if ( sched_setscheduler(0, SCHED_FIFO, &sched) == -1 ) 38854359Sroberto msyslog(LOG_ERR, "sched_setscheduler(): %m"); 38954359Sroberto else 39082498Sroberto ++priority_done; 39154359Sroberto } 39282498Sroberto#endif /* HAVE_SCHED_SETSCHEDULER */ 39382498Sroberto#if defined(HAVE_RTPRIO) 39482498Sroberto# ifdef RTP_SET 39582498Sroberto if (!priority_done) { 39654359Sroberto struct rtprio srtp; 39754359Sroberto 39854359Sroberto srtp.type = RTP_PRIO_REALTIME; /* was: RTP_PRIO_NORMAL */ 39954359Sroberto srtp.prio = 0; /* 0 (hi) -> RTP_PRIO_MAX (31,lo) */ 40054359Sroberto 40154359Sroberto if (rtprio(RTP_SET, getpid(), &srtp) < 0) 40254359Sroberto msyslog(LOG_ERR, "rtprio() error: %m"); 40354359Sroberto else 40482498Sroberto ++priority_done; 40554359Sroberto } 40682498Sroberto# else /* not RTP_SET */ 40782498Sroberto if (!priority_done) { 40854359Sroberto if (rtprio(0, 120) < 0) 40954359Sroberto msyslog(LOG_ERR, "rtprio() error: %m"); 41054359Sroberto else 41182498Sroberto ++priority_done; 41254359Sroberto } 41382498Sroberto# endif /* not RTP_SET */ 41482498Sroberto#endif /* HAVE_RTPRIO */ 41582498Sroberto#if defined(NTPD_PRIO) && NTPD_PRIO != 0 41682498Sroberto# ifdef HAVE_ATT_NICE 41782498Sroberto if (!priority_done) { 41854359Sroberto errno = 0; 41954359Sroberto if (-1 == nice (NTPD_PRIO) && errno != 0) 42054359Sroberto msyslog(LOG_ERR, "nice() error: %m"); 42154359Sroberto else 42282498Sroberto ++priority_done; 42354359Sroberto } 42482498Sroberto# endif /* HAVE_ATT_NICE */ 42582498Sroberto# ifdef HAVE_BSD_NICE 42682498Sroberto if (!priority_done) { 42754359Sroberto if (-1 == setpriority(PRIO_PROCESS, 0, NTPD_PRIO)) 42854359Sroberto msyslog(LOG_ERR, "setpriority() error: %m"); 42954359Sroberto else 43082498Sroberto ++priority_done; 43154359Sroberto } 43282498Sroberto# endif /* HAVE_BSD_NICE */ 43382498Sroberto#endif /* NTPD_PRIO && NTPD_PRIO != 0 */ 43482498Sroberto if (!priority_done) 43554359Sroberto msyslog(LOG_ERR, "set_process_priority: No way found to improve our priority"); 43654359Sroberto} 43754359Sroberto 43856746Sroberto 43954359Sroberto/* 44054359Sroberto * Main program. Initialize us, disconnect us from the tty if necessary, 44154359Sroberto * and loop waiting for I/O and/or timer expiries. 44254359Sroberto */ 44354359Srobertoint 44454359Srobertontpdmain( 44554359Sroberto int argc, 44654359Sroberto char *argv[] 44754359Sroberto ) 44854359Sroberto{ 44954359Sroberto l_fp now; 45054359Sroberto struct recvbuf *rbuf; 45154359Sroberto#ifdef _AIX /* HMS: ifdef SIGDANGER? */ 45254359Sroberto struct sigaction sa; 45354359Sroberto#endif 45454359Sroberto 455182007Sroberto progname = argv[0]; 456182007Sroberto 45754359Sroberto initializing = 1; /* mark that we are initializing */ 45854359Sroberto 459182007Sroberto { 460182007Sroberto int optct = optionProcess( 461182007Sroberto#ifdef SIM 462182007Sroberto &ntpdsimOptions 463182007Sroberto#else 464182007Sroberto &ntpdOptions 465182007Sroberto#endif 466182007Sroberto , argc, argv); 467182007Sroberto argc -= optct; 468182007Sroberto argv += optct; 469182007Sroberto } 470182007Sroberto 471182007Sroberto /* HMS: is this lame? Should we process -l first? */ 472182007Sroberto 473182007Sroberto init_logging(progname); /* Open the log file */ 474182007Sroberto 47554359Sroberto#ifdef HAVE_UMASK 47654359Sroberto { 47782498Sroberto mode_t uv; 47854359Sroberto 47954359Sroberto uv = umask(0); 48054359Sroberto if(uv) 48154359Sroberto (void) umask(uv); 48254359Sroberto else 48354359Sroberto (void) umask(022); 48454359Sroberto } 48554359Sroberto#endif 48654359Sroberto 487106163Sroberto#if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */ 48854359Sroberto { 48954359Sroberto uid_t uid; 49054359Sroberto 49154359Sroberto uid = getuid(); 49254359Sroberto if (uid) 49354359Sroberto { 49454359Sroberto msyslog(LOG_ERR, "ntpd: must be run as root, not uid %ld", (long)uid); 495182007Sroberto printf("must be run as root, not uid %ld", (long)uid); 49654359Sroberto exit(1); 49754359Sroberto } 49854359Sroberto } 49954359Sroberto#endif 50054359Sroberto 501182007Sroberto#ifdef OPENSSL 502182007Sroberto if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) { 503182007Sroberto msyslog(LOG_ERR, 504182007Sroberto "ntpd: OpenSSL version mismatch. Built against %lx, you have %lx\n", 505182007Sroberto OPENSSL_VERSION_NUMBER, SSLeay()); 50654359Sroberto exit(1); 50754359Sroberto } 50854359Sroberto#endif 50954359Sroberto 510182007Sroberto /* getstartup(argc, argv); / * startup configuration, may set debug */ 511182007Sroberto 512182007Sroberto#ifdef DEBUG 513182007Sroberto debug = DESC(DEBUG_LEVEL).optOccCt; 514132451Sroberto if (debug) 515132451Sroberto printf("%s\n", Version); 516182007Sroberto#endif 517132451Sroberto 518182007Sroberto/* 519182007Sroberto * Enable the Multi-Media Timer for Windows? 520182007Sroberto */ 521182007Sroberto#ifdef SYS_WINNT 522182007Sroberto if (HAVE_OPT( MODIFYMMTIMER )) 523182007Sroberto set_mm_timer(MM_TIMER_HIRES); 524182007Sroberto#endif 525182007Sroberto 526182007Sroberto if (HAVE_OPT( NOFORK ) || HAVE_OPT( QUIT )) 527182007Sroberto nofork = 1; 528182007Sroberto 529182007Sroberto if (HAVE_OPT( NOVIRTUALIPS )) 530182007Sroberto listen_to_virtual_ips = 0; 531182007Sroberto 532182007Sroberto if (HAVE_OPT( INTERFACE )) { 533182007Sroberto#if 0 534182007Sroberto int ifacect = STACKCT_OPT( INTERFACE ); 535182007Sroberto char** ifaces = STACKLST_OPT( INTERFACE ); 536182007Sroberto 537182007Sroberto /* malloc space for the array of names */ 538182007Sroberto while (ifacect-- > 0) { 539182007Sroberto next_iface = *ifaces++; 540182007Sroberto } 541182007Sroberto#else 542182007Sroberto specific_interface = OPT_ARG( INTERFACE ); 543182007Sroberto#endif 544182007Sroberto } 545182007Sroberto 546182007Sroberto if (HAVE_OPT( NICE )) 547182007Sroberto priority_done = 0; 548182007Sroberto 549182007Sroberto#if defined(HAVE_SCHED_SETSCHEDULER) 550182007Sroberto if (HAVE_OPT( PRIORITY )) { 551182007Sroberto config_priority = OPT_VALUE_PRIORITY; 552182007Sroberto config_priority_override = 1; 553182007Sroberto priority_done = 0; 554182007Sroberto } 555182007Sroberto#endif 556182007Sroberto 557182007Sroberto#ifdef SYS_WINNT 55882498Sroberto /* 559182007Sroberto * Initialize the time structures and variables 560182007Sroberto */ 561182007Sroberto init_winnt_time(); 562182007Sroberto#endif 563182007Sroberto 564182007Sroberto setup_logfile(); 565182007Sroberto 566182007Sroberto /* 56782498Sroberto * Initialize random generator and public key pair 56882498Sroberto */ 56954359Sroberto get_systime(&now); 57054359Sroberto 571182007Sroberto ntp_srandom((int)(now.l_i * now.l_uf)); 572182007Sroberto 573182007Sroberto#ifdef HAVE_DNSREGISTRATION 574182007Sroberto /* HMS: does this have to happen this early? */ 575182007Sroberto msyslog(LOG_INFO, "Attemping to register mDNS"); 576182007Sroberto if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL, htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) { 577182007Sroberto msyslog(LOG_ERR, "Unable to register mDNS"); 578182007Sroberto } 579182007Sroberto#endif 580182007Sroberto 58154359Sroberto#if !defined(VMS) 58254359Sroberto# ifndef NODETACH 58354359Sroberto /* 58454359Sroberto * Detach us from the terminal. May need an #ifndef GIZMO. 58554359Sroberto */ 586182007Sroberto if ( 58754359Sroberto# ifdef DEBUG 588182007Sroberto !debug && 58954359Sroberto# endif /* DEBUG */ 590182007Sroberto !nofork) 59154359Sroberto { 59254359Sroberto# ifndef SYS_WINNT 59382498Sroberto# ifdef HAVE_DAEMON 59454359Sroberto daemon(0, 0); 59582498Sroberto# else /* not HAVE_DAEMON */ 59654359Sroberto if (fork()) /* HMS: What about a -1? */ 59754359Sroberto exit(0); 59854359Sroberto 59954359Sroberto { 60054359Sroberto#if !defined(F_CLOSEM) 60154359Sroberto u_long s; 60254359Sroberto int max_fd; 60354359Sroberto#endif /* not F_CLOSEM */ 60454359Sroberto 605132451Sroberto#if defined(F_CLOSEM) 60654359Sroberto /* 60754359Sroberto * From 'Writing Reliable AIX Daemons,' SG24-4946-00, 60854359Sroberto * by Eric Agar (saves us from doing 32767 system 60954359Sroberto * calls) 61054359Sroberto */ 61154359Sroberto if (fcntl(0, F_CLOSEM, 0) == -1) 61254359Sroberto msyslog(LOG_ERR, "ntpd: failed to close open files(): %m"); 61354359Sroberto#else /* not F_CLOSEM */ 61454359Sroberto 61582498Sroberto# if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX) 61654359Sroberto max_fd = sysconf(_SC_OPEN_MAX); 61782498Sroberto# else /* HAVE_SYSCONF && _SC_OPEN_MAX */ 61854359Sroberto max_fd = getdtablesize(); 61982498Sroberto# endif /* HAVE_SYSCONF && _SC_OPEN_MAX */ 62054359Sroberto for (s = 0; s < max_fd; s++) 62154359Sroberto (void) close((int)s); 62254359Sroberto#endif /* not F_CLOSEM */ 62354359Sroberto (void) open("/", 0); 62454359Sroberto (void) dup2(0, 1); 62554359Sroberto (void) dup2(0, 2); 62654359Sroberto#ifdef SYS_DOMAINOS 62754359Sroberto { 62854359Sroberto uid_$t puid; 62954359Sroberto status_$t st; 63054359Sroberto 63154359Sroberto proc2_$who_am_i(&puid); 63254359Sroberto proc2_$make_server(&puid, &st); 63354359Sroberto } 63454359Sroberto#endif /* SYS_DOMAINOS */ 63554359Sroberto#if defined(HAVE_SETPGID) || defined(HAVE_SETSID) 63654359Sroberto# ifdef HAVE_SETSID 63754359Sroberto if (setsid() == (pid_t)-1) 63854359Sroberto msyslog(LOG_ERR, "ntpd: setsid(): %m"); 63954359Sroberto# else 64054359Sroberto if (setpgid(0, 0) == -1) 64154359Sroberto msyslog(LOG_ERR, "ntpd: setpgid(): %m"); 64254359Sroberto# endif 64354359Sroberto#else /* HAVE_SETPGID || HAVE_SETSID */ 64454359Sroberto { 64554359Sroberto# if defined(TIOCNOTTY) 64654359Sroberto int fid; 64754359Sroberto 64854359Sroberto fid = open("/dev/tty", 2); 64954359Sroberto if (fid >= 0) 65054359Sroberto { 65154359Sroberto (void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0); 65254359Sroberto (void) close(fid); 65354359Sroberto } 65454359Sroberto# endif /* defined(TIOCNOTTY) */ 65554359Sroberto# ifdef HAVE_SETPGRP_0 65654359Sroberto (void) setpgrp(); 65754359Sroberto# else /* HAVE_SETPGRP_0 */ 65854359Sroberto (void) setpgrp(0, getpid()); 65954359Sroberto# endif /* HAVE_SETPGRP_0 */ 66054359Sroberto } 66154359Sroberto#endif /* HAVE_SETPGID || HAVE_SETSID */ 66254359Sroberto#ifdef _AIX 66354359Sroberto /* Don't get killed by low-on-memory signal. */ 66454359Sroberto sa.sa_handler = catch_danger; 66554359Sroberto sigemptyset(&sa.sa_mask); 66654359Sroberto sa.sa_flags = SA_RESTART; 66754359Sroberto 66854359Sroberto (void) sigaction(SIGDANGER, &sa, NULL); 66954359Sroberto#endif /* _AIX */ 67054359Sroberto } 67182498Sroberto# endif /* not HAVE_DAEMON */ 67282498Sroberto# endif /* SYS_WINNT */ 67354359Sroberto } 67482498Sroberto# endif /* NODETACH */ 67554359Sroberto#endif /* VMS */ 67654359Sroberto 677182007Sroberto setup_logfile(); /* We lost any redirect when we daemonized */ 67854359Sroberto 67954359Sroberto#ifdef SCO5_CLOCK 68054359Sroberto /* 68154359Sroberto * SCO OpenServer's system clock offers much more precise timekeeping 68254359Sroberto * on the base CPU than the other CPUs (for multiprocessor systems), 68354359Sroberto * so we must lock to the base CPU. 68454359Sroberto */ 68554359Sroberto { 68654359Sroberto int fd = open("/dev/at1", O_RDONLY); 68754359Sroberto if (fd >= 0) { 68854359Sroberto int zero = 0; 68954359Sroberto if (ioctl(fd, ACPU_LOCK, &zero) < 0) 690182007Sroberto msyslog(LOG_ERR, "cannot lock to base CPU: %m"); 69154359Sroberto close( fd ); 69254359Sroberto } /* else ... 69354359Sroberto * If we can't open the device, this probably just isn't 69454359Sroberto * a multiprocessor system, so we're A-OK. 69554359Sroberto */ 69654359Sroberto } 69754359Sroberto#endif 69854359Sroberto 69954359Sroberto#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && defined(MCL_FUTURE) 700132451Sroberto# ifdef HAVE_SETRLIMIT 70154359Sroberto /* 702132451Sroberto * Set the stack limit to something smaller, so that we don't lock a lot 703132451Sroberto * of unused stack memory. 704132451Sroberto */ 705132451Sroberto { 706132451Sroberto struct rlimit rl; 707132451Sroberto 708182007Sroberto /* HMS: must make the rlim_cur amount configurable */ 709132451Sroberto if (getrlimit(RLIMIT_STACK, &rl) != -1 710182007Sroberto && (rl.rlim_cur = 50 * 4096) < rl.rlim_max) 711132451Sroberto { 712132451Sroberto if (setrlimit(RLIMIT_STACK, &rl) == -1) 713132451Sroberto { 714132451Sroberto msyslog(LOG_ERR, 715132451Sroberto "Cannot adjust stack limit for mlockall: %m"); 716132451Sroberto } 717132451Sroberto } 718182007Sroberto# ifdef RLIMIT_MEMLOCK 719182007Sroberto /* 720182007Sroberto * The default RLIMIT_MEMLOCK is very low on Linux systems. 721182007Sroberto * Unless we increase this limit malloc calls are likely to 722182007Sroberto * fail if we drop root privlege. To be useful the value 723182007Sroberto * has to be larger than the largest ntpd resident set size. 724182007Sroberto */ 725182007Sroberto rl.rlim_cur = rl.rlim_max = 32*1024*1024; 726182007Sroberto if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) { 727182007Sroberto msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m"); 728182007Sroberto } 729182007Sroberto# endif /* RLIMIT_MEMLOCK */ 730132451Sroberto } 731132451Sroberto# endif /* HAVE_SETRLIMIT */ 732132451Sroberto /* 73354359Sroberto * lock the process into memory 73454359Sroberto */ 73554359Sroberto if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0) 73654359Sroberto msyslog(LOG_ERR, "mlockall(): %m"); 73754359Sroberto#else /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */ 73854359Sroberto# ifdef HAVE_PLOCK 73954359Sroberto# ifdef PROCLOCK 74054359Sroberto# ifdef _AIX 74154359Sroberto /* 74254359Sroberto * set the stack limit for AIX for plock(). 743182007Sroberto * see get_aix_stack() for more info. 74454359Sroberto */ 74554359Sroberto if (ulimit(SET_STACKLIM, (get_aix_stack() - 8*4096)) < 0) 74654359Sroberto { 74754359Sroberto msyslog(LOG_ERR,"Cannot adjust stack limit for plock on AIX: %m"); 74854359Sroberto } 74954359Sroberto# endif /* _AIX */ 75054359Sroberto /* 75154359Sroberto * lock the process into memory 75254359Sroberto */ 75354359Sroberto if (plock(PROCLOCK) < 0) 75454359Sroberto msyslog(LOG_ERR, "plock(PROCLOCK): %m"); 75554359Sroberto# else /* not PROCLOCK */ 75682498Sroberto# ifdef TXTLOCK 75754359Sroberto /* 75854359Sroberto * Lock text into ram 75954359Sroberto */ 76054359Sroberto if (plock(TXTLOCK) < 0) 76154359Sroberto msyslog(LOG_ERR, "plock(TXTLOCK) error: %m"); 76282498Sroberto# else /* not TXTLOCK */ 76354359Sroberto msyslog(LOG_ERR, "plock() - don't know what to lock!"); 76482498Sroberto# endif /* not TXTLOCK */ 76554359Sroberto# endif /* not PROCLOCK */ 76654359Sroberto# endif /* HAVE_PLOCK */ 76754359Sroberto#endif /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */ 76854359Sroberto 76954359Sroberto /* 77054359Sroberto * Set up signals we pay attention to locally. 77154359Sroberto */ 77254359Sroberto#ifdef SIGDIE1 77354359Sroberto (void) signal_no_reset(SIGDIE1, finish); 77454359Sroberto#endif /* SIGDIE1 */ 77554359Sroberto#ifdef SIGDIE2 77654359Sroberto (void) signal_no_reset(SIGDIE2, finish); 77754359Sroberto#endif /* SIGDIE2 */ 77854359Sroberto#ifdef SIGDIE3 77954359Sroberto (void) signal_no_reset(SIGDIE3, finish); 78054359Sroberto#endif /* SIGDIE3 */ 78154359Sroberto#ifdef SIGDIE4 78254359Sroberto (void) signal_no_reset(SIGDIE4, finish); 78354359Sroberto#endif /* SIGDIE4 */ 78454359Sroberto 78554359Sroberto#ifdef SIGBUS 78654359Sroberto (void) signal_no_reset(SIGBUS, finish); 78754359Sroberto#endif /* SIGBUS */ 78854359Sroberto 78954359Sroberto#if !defined(SYS_WINNT) && !defined(VMS) 79054359Sroberto# ifdef DEBUG 79154359Sroberto (void) signal_no_reset(MOREDEBUGSIG, moredebug); 79254359Sroberto (void) signal_no_reset(LESSDEBUGSIG, lessdebug); 79354359Sroberto# else 79454359Sroberto (void) signal_no_reset(MOREDEBUGSIG, no_debug); 79554359Sroberto (void) signal_no_reset(LESSDEBUGSIG, no_debug); 79654359Sroberto# endif /* DEBUG */ 79754359Sroberto#endif /* !SYS_WINNT && !VMS */ 79854359Sroberto 79954359Sroberto /* 80054359Sroberto * Set up signals we should never pay attention to. 80154359Sroberto */ 80256746Sroberto#if defined SIGPIPE 80354359Sroberto (void) signal_no_reset(SIGPIPE, SIG_IGN); 80454359Sroberto#endif /* SIGPIPE */ 80554359Sroberto 80654359Sroberto /* 80754359Sroberto * Call the init_ routines to initialize the data structures. 808182007Sroberto * 809182007Sroberto * Exactly what command-line options are we expecting here? 81054359Sroberto */ 81154359Sroberto init_auth(); 81254359Sroberto init_util(); 81354359Sroberto init_restrict(); 81454359Sroberto init_mon(); 81554359Sroberto init_timer(); 81654359Sroberto init_lib(); 81754359Sroberto init_request(); 81854359Sroberto init_control(); 81954359Sroberto init_peer(); 82054359Sroberto#ifdef REFCLOCK 82154359Sroberto init_refclock(); 82254359Sroberto#endif 82354359Sroberto set_process_priority(); 82482498Sroberto init_proto(); /* Call at high priority */ 82554359Sroberto init_io(); 82654359Sroberto init_loopfilter(); 82782498Sroberto mon_start(MON_ON); /* monitor on by default now */ 82854359Sroberto /* turn off in config if unwanted */ 82954359Sroberto 83054359Sroberto /* 831182007Sroberto * Get the configuration. This is done in a separate module 832182007Sroberto * since this will definitely be different for the gizmo board. 83354359Sroberto */ 834182007Sroberto 83554359Sroberto getconfig(argc, argv); 836182007Sroberto 837182007Sroberto loop_config(LOOP_DRIFTCOMP, old_drift / 1e6); 838132451Sroberto#ifdef OPENSSL 83982498Sroberto crypto_setup(); 840132451Sroberto#endif /* OPENSSL */ 84154359Sroberto initializing = 0; 84254359Sroberto 843182007Sroberto#ifdef HAVE_DROPROOT 844182007Sroberto if( droproot ) { 845182007Sroberto /* Drop super-user privileges and chroot now if the OS supports this */ 846182007Sroberto 847182007Sroberto#ifdef HAVE_LINUX_CAPABILITIES 848182007Sroberto /* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */ 849182007Sroberto if( prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1 ) { 850182007Sroberto msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" ); 851182007Sroberto exit(-1); 852182007Sroberto } 853182007Sroberto#else 854182007Sroberto /* we need a user to switch to */ 855182007Sroberto if( user == NULL ) { 856182007Sroberto msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" ); 857182007Sroberto exit(-1); 858182007Sroberto } 859182007Sroberto#endif /* HAVE_LINUX_CAPABILITIES */ 860182007Sroberto 861182007Sroberto if (user != NULL) { 862182007Sroberto if (isdigit((unsigned char)*user)) { 863182007Sroberto sw_uid = (uid_t)strtoul(user, &endp, 0); 864182007Sroberto if (*endp != '\0') 865182007Sroberto goto getuser; 866182007Sroberto } else { 867182007Srobertogetuser: 868182007Sroberto if ((pw = getpwnam(user)) != NULL) { 869182007Sroberto sw_uid = pw->pw_uid; 870182007Sroberto } else { 871182007Sroberto errno = 0; 872182007Sroberto msyslog(LOG_ERR, "Cannot find user `%s'", user); 873182007Sroberto exit (-1); 874182007Sroberto } 875132451Sroberto } 87654359Sroberto } 877182007Sroberto if (group != NULL) { 878182007Sroberto if (isdigit((unsigned char)*group)) { 879182007Sroberto sw_gid = (gid_t)strtoul(group, &endp, 0); 880182007Sroberto if (*endp != '\0') 881182007Sroberto goto getgroup; 882182007Sroberto } else { 883182007Srobertogetgroup: 884182007Sroberto if ((gr = getgrnam(group)) != NULL) { 885182007Sroberto sw_gid = gr->gr_gid; 886182007Sroberto } else { 887182007Sroberto errno = 0; 888182007Sroberto msyslog(LOG_ERR, "Cannot find group `%s'", group); 889182007Sroberto exit (-1); 890182007Sroberto } 891182007Sroberto } 892182007Sroberto } 893182007Sroberto 894182007Sroberto if( chrootdir ) { 895182007Sroberto /* make sure cwd is inside the jail: */ 896182007Sroberto if( chdir(chrootdir) ) { 897182007Sroberto msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir); 898182007Sroberto exit (-1); 899182007Sroberto } 900182007Sroberto if( chroot(chrootdir) ) { 901182007Sroberto msyslog(LOG_ERR, "Cannot chroot() to `%s': %m", chrootdir); 902182007Sroberto exit (-1); 903182007Sroberto } 904182007Sroberto } 905182007Sroberto if (group && setgid(sw_gid)) { 906182007Sroberto msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group); 907182007Sroberto exit (-1); 908182007Sroberto } 909182007Sroberto if (group && setegid(sw_gid)) { 910182007Sroberto msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group); 911182007Sroberto exit (-1); 912182007Sroberto } 913182007Sroberto if (user && setuid(sw_uid)) { 914182007Sroberto msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user); 915182007Sroberto exit (-1); 916182007Sroberto } 917182007Sroberto if (user && seteuid(sw_uid)) { 918182007Sroberto msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user); 919182007Sroberto exit (-1); 920182007Sroberto } 921182007Sroberto 922182007Sroberto#ifndef HAVE_LINUX_CAPABILITIES 923182007Sroberto /* 924182007Sroberto * for now assume that the privilege to bind to privileged ports 925182007Sroberto * is associated with running with uid 0 - should be refined on 926182007Sroberto * ports that allow binding to NTP_PORT with uid != 0 927182007Sroberto */ 928182007Sroberto disable_dynamic_updates |= (sw_uid != 0); /* also notifies routing message listener */ 92954359Sroberto#endif 93054359Sroberto 931182007Sroberto if (disable_dynamic_updates && interface_interval) { 932182007Sroberto interface_interval = 0; 933182007Sroberto msyslog(LOG_INFO, "running in unprivileged mode disables dynamic interface tracking"); 934182007Sroberto } 935182007Sroberto 936182007Sroberto#ifdef HAVE_LINUX_CAPABILITIES 937182007Sroberto do { 938182007Sroberto /* 939182007Sroberto * We may be running under non-root uid now, but we still hold full root privileges! 940182007Sroberto * We drop all of them, except for the crucial one or two: cap_sys_time and 941182007Sroberto * cap_net_bind_service if doing dynamic interface tracking. 942182007Sroberto */ 943182007Sroberto cap_t caps; 944182007Sroberto char *captext = interface_interval ? 945182007Sroberto "cap_sys_time,cap_net_bind_service=ipe" : 946182007Sroberto "cap_sys_time=ipe"; 947182007Sroberto if( ! ( caps = cap_from_text( captext ) ) ) { 948182007Sroberto msyslog( LOG_ERR, "cap_from_text() failed: %m" ); 949182007Sroberto exit(-1); 950182007Sroberto } 951182007Sroberto if( cap_set_proc( caps ) == -1 ) { 952182007Sroberto msyslog( LOG_ERR, "cap_set_proc() failed to drop root privileges: %m" ); 953182007Sroberto exit(-1); 954182007Sroberto } 955182007Sroberto cap_free( caps ); 956182007Sroberto } while(0); 957182007Sroberto#endif /* HAVE_LINUX_CAPABILITIES */ 958182007Sroberto 959182007Sroberto } /* if( droproot ) */ 960182007Sroberto#endif /* HAVE_DROPROOT */ 961182007Sroberto 96254359Sroberto /* 96354359Sroberto * Report that we're up to any trappers 96454359Sroberto */ 96554359Sroberto report_event(EVNT_SYSRESTART, (struct peer *)0); 96654359Sroberto 96754359Sroberto /* 96854359Sroberto * Use select() on all on all input fd's for unlimited 96954359Sroberto * time. select() will terminate on SIGALARM or on the 97054359Sroberto * reception of input. Using select() means we can't do 97154359Sroberto * robust signal handling and we get a potential race 97254359Sroberto * between checking for alarms and doing the select(). 97354359Sroberto * Mostly harmless, I think. 97454359Sroberto */ 97554359Sroberto /* On VMS, I suspect that select() can't be interrupted 97654359Sroberto * by a "signal" either, so I take the easy way out and 97754359Sroberto * have select() time out after one second. 97854359Sroberto * System clock updates really aren't time-critical, 97954359Sroberto * and - lacking a hardware reference clock - I have 98054359Sroberto * yet to learn about anything else that is. 98154359Sroberto */ 98282498Sroberto#if defined(HAVE_IO_COMPLETION_PORT) 98354359Sroberto 984182007Sroberto for (;;) { 985200576Sroberto GetReceivedBuffers(); 98682498Sroberto#else /* normal I/O */ 98754359Sroberto 988182007Sroberto BLOCK_IO_AND_ALARM(); 98954359Sroberto was_alarmed = 0; 99054359Sroberto for (;;) 99154359Sroberto { 99282498Sroberto# if !defined(HAVE_SIGNALED_IO) 99354359Sroberto extern fd_set activefds; 99454359Sroberto extern int maxactivefd; 99554359Sroberto 99654359Sroberto fd_set rdfdes; 99754359Sroberto int nfound; 99882498Sroberto# endif 99954359Sroberto 100054359Sroberto if (alarm_flag) /* alarmed? */ 100154359Sroberto { 100254359Sroberto was_alarmed = 1; 100354359Sroberto alarm_flag = 0; 100454359Sroberto } 100554359Sroberto 1006182007Sroberto if (!was_alarmed && has_full_recv_buffer() == ISC_FALSE) 100754359Sroberto { 100854359Sroberto /* 100954359Sroberto * Nothing to do. Wait for something. 101054359Sroberto */ 101182498Sroberto# ifndef HAVE_SIGNALED_IO 101254359Sroberto rdfdes = activefds; 101382498Sroberto# if defined(VMS) || defined(SYS_VXWORKS) 101454359Sroberto /* make select() wake up after one second */ 101554359Sroberto { 101654359Sroberto struct timeval t1; 101754359Sroberto 101854359Sroberto t1.tv_sec = 1; t1.tv_usec = 0; 101954359Sroberto nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0, 102054359Sroberto (fd_set *)0, &t1); 102154359Sroberto } 102282498Sroberto# else 102354359Sroberto nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0, 102454359Sroberto (fd_set *)0, (struct timeval *)0); 102582498Sroberto# endif /* VMS */ 102654359Sroberto if (nfound > 0) 102754359Sroberto { 102854359Sroberto l_fp ts; 102954359Sroberto 103054359Sroberto get_systime(&ts); 103154359Sroberto 103254359Sroberto (void)input_handler(&ts); 103354359Sroberto } 103454359Sroberto else if (nfound == -1 && errno != EINTR) 1035182007Sroberto netsyslog(LOG_ERR, "select() error: %m"); 1036132451Sroberto# ifdef DEBUG 1037182007Sroberto else if (debug > 5) 1038182007Sroberto netsyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound); 1039132451Sroberto# endif /* DEBUG */ 104082498Sroberto# else /* HAVE_SIGNALED_IO */ 104154359Sroberto 104254359Sroberto wait_for_signal(); 104382498Sroberto# endif /* HAVE_SIGNALED_IO */ 104454359Sroberto if (alarm_flag) /* alarmed? */ 104554359Sroberto { 104654359Sroberto was_alarmed = 1; 104754359Sroberto alarm_flag = 0; 104854359Sroberto } 104954359Sroberto } 105054359Sroberto 105154359Sroberto if (was_alarmed) 105254359Sroberto { 1053182007Sroberto UNBLOCK_IO_AND_ALARM(); 1054182007Sroberto /* 1055182007Sroberto * Out here, signals are unblocked. Call timer routine 1056182007Sroberto * to process expiry. 1057182007Sroberto */ 105854359Sroberto timer(); 105954359Sroberto was_alarmed = 0; 1060182007Sroberto BLOCK_IO_AND_ALARM(); 106154359Sroberto } 106254359Sroberto 106382498Sroberto#endif /* HAVE_IO_COMPLETION_PORT */ 1064182007Sroberto 1065182007Sroberto#ifdef DEBUG_TIMING 106654359Sroberto { 1067182007Sroberto l_fp pts; 1068182007Sroberto l_fp tsa, tsb; 1069182007Sroberto int bufcount = 0; 1070182007Sroberto 1071182007Sroberto get_systime(&pts); 1072182007Sroberto tsa = pts; 1073182007Sroberto#endif 1074182007Sroberto rbuf = get_full_recv_buffer(); 1075182007Sroberto while (rbuf != NULL) 1076182007Sroberto { 1077182007Sroberto if (alarm_flag) 1078182007Sroberto { 1079182007Sroberto was_alarmed = 1; 1080182007Sroberto alarm_flag = 0; 1081182007Sroberto } 1082182007Sroberto UNBLOCK_IO_AND_ALARM(); 1083182007Sroberto 1084182007Sroberto if (was_alarmed) 1085182007Sroberto { /* avoid timer starvation during lengthy I/O handling */ 1086182007Sroberto timer(); 1087182007Sroberto was_alarmed = 0; 1088182007Sroberto } 1089182007Sroberto 1090182007Sroberto /* 1091182007Sroberto * Call the data procedure to handle each received 1092182007Sroberto * packet. 1093182007Sroberto */ 1094182007Sroberto if (rbuf->receiver != NULL) /* This should always be true */ 1095182007Sroberto { 1096182007Sroberto#ifdef DEBUG_TIMING 1097182007Sroberto l_fp dts = pts; 1098182007Sroberto 1099182007Sroberto L_SUB(&dts, &rbuf->recv_time); 1100182007Sroberto DPRINTF(2, ("processing timestamp delta %s (with prec. fuzz)\n", lfptoa(&dts, 9))); 1101182007Sroberto collect_timing(rbuf, "buffer processing delay", 1, &dts); 1102182007Sroberto bufcount++; 1103182007Sroberto#endif 1104182007Sroberto (rbuf->receiver)(rbuf); 1105182007Sroberto } else { 1106182007Sroberto msyslog(LOG_ERR, "receive buffer corruption - receiver found to be NULL - ABORTING"); 1107182007Sroberto abort(); 1108182007Sroberto } 1109182007Sroberto 1110182007Sroberto BLOCK_IO_AND_ALARM(); 1111182007Sroberto freerecvbuf(rbuf); 1112182007Sroberto rbuf = get_full_recv_buffer(); 1113182007Sroberto } 1114182007Sroberto#ifdef DEBUG_TIMING 1115182007Sroberto get_systime(&tsb); 1116182007Sroberto L_SUB(&tsb, &tsa); 1117182007Sroberto if (bufcount) { 1118182007Sroberto collect_timing(NULL, "processing", bufcount, &tsb); 1119182007Sroberto DPRINTF(2, ("processing time for %d buffers %s\n", bufcount, lfptoa(&tsb, 9))); 1120182007Sroberto } 112154359Sroberto } 112282498Sroberto#endif 112354359Sroberto 112454359Sroberto /* 112554359Sroberto * Go around again 112654359Sroberto */ 112754359Sroberto } 1128182007Sroberto UNBLOCK_IO_AND_ALARM(); 1129182007Sroberto return 1; 113054359Sroberto} 113154359Sroberto 113254359Sroberto 113354359Sroberto#ifdef SIGDIE2 113454359Sroberto/* 113554359Sroberto * finish - exit gracefully 113654359Sroberto */ 113754359Srobertostatic RETSIGTYPE 113854359Srobertofinish( 113954359Sroberto int sig 114054359Sroberto ) 114154359Sroberto{ 114254359Sroberto 114354359Sroberto msyslog(LOG_NOTICE, "ntpd exiting on signal %d", sig); 1144182007Sroberto write_stats(); 1145182007Sroberto#ifdef HAVE_DNSREGISTRATION 1146182007Sroberto if (mdns != NULL) 1147182007Sroberto DNSServiceRefDeallocate(mdns); 1148182007Sroberto#endif 114954359Sroberto 115054359Sroberto switch (sig) 115154359Sroberto { 115282498Sroberto# ifdef SIGBUS 115354359Sroberto case SIGBUS: 115454359Sroberto printf("\nfinish(SIGBUS)\n"); 115554359Sroberto exit(0); 115682498Sroberto# endif 115754359Sroberto case 0: /* Should never happen... */ 115854359Sroberto return; 115954359Sroberto default: 116054359Sroberto exit(0); 116154359Sroberto } 116254359Sroberto} 116354359Sroberto#endif /* SIGDIE2 */ 116454359Sroberto 116554359Sroberto 116654359Sroberto#ifdef DEBUG 1167132451Sroberto#ifndef SYS_WINNT 116854359Sroberto/* 116954359Sroberto * moredebug - increase debugging verbosity 117054359Sroberto */ 117154359Srobertostatic RETSIGTYPE 117254359Srobertomoredebug( 117354359Sroberto int sig 117454359Sroberto ) 117554359Sroberto{ 117654359Sroberto int saved_errno = errno; 117754359Sroberto 117854359Sroberto if (debug < 255) 117954359Sroberto { 118054359Sroberto debug++; 118154359Sroberto msyslog(LOG_DEBUG, "debug raised to %d", debug); 118254359Sroberto } 118354359Sroberto errno = saved_errno; 118454359Sroberto} 118554359Sroberto 118654359Sroberto/* 118754359Sroberto * lessdebug - decrease debugging verbosity 118854359Sroberto */ 118954359Srobertostatic RETSIGTYPE 119054359Srobertolessdebug( 119154359Sroberto int sig 119254359Sroberto ) 119354359Sroberto{ 119454359Sroberto int saved_errno = errno; 119554359Sroberto 119654359Sroberto if (debug > 0) 119754359Sroberto { 119854359Sroberto debug--; 119954359Sroberto msyslog(LOG_DEBUG, "debug lowered to %d", debug); 120054359Sroberto } 120154359Sroberto errno = saved_errno; 120254359Sroberto} 1203132451Sroberto#endif 120454359Sroberto#else /* not DEBUG */ 1205182007Sroberto#ifndef SYS_WINNT 1206182007Sroberto/* 120754359Sroberto * no_debug - We don't do the debug here. 120854359Sroberto */ 120954359Srobertostatic RETSIGTYPE 121054359Srobertono_debug( 121154359Sroberto int sig 121254359Sroberto ) 121354359Sroberto{ 121454359Sroberto int saved_errno = errno; 121554359Sroberto 121654359Sroberto msyslog(LOG_DEBUG, "ntpd not compiled for debugging (signal %d)", sig); 121754359Sroberto errno = saved_errno; 121854359Sroberto} 1219132451Sroberto#endif /* not SYS_WINNT */ 122054359Sroberto#endif /* not DEBUG */ 1221