ntpd.c revision 272461
1231990Smp/* 259243Sobrien * ntpd.c - main program for the fixed point NTP daemon 359243Sobrien */ 459243Sobrien 559243Sobrien#ifdef HAVE_CONFIG_H 659243Sobrien# include <config.h> 759243Sobrien#endif 859243Sobrien 959243Sobrien#include "ntp_machine.h" 1059243Sobrien#include "ntpd.h" 1159243Sobrien#include "ntp_io.h" 1259243Sobrien#include "ntp_stdlib.h" 1359243Sobrien#include <ntp_random.h> 1459243Sobrien 1559243Sobrien#ifdef SIM 1659243Sobrien# include "ntpsim.h" 17100616Smp# include "ntpdsim-opts.h" 1859243Sobrien#else 1959243Sobrien# include "ntpd-opts.h" 2059243Sobrien#endif 2159243Sobrien 2259243Sobrien#ifdef HAVE_UNISTD_H 2359243Sobrien# include <unistd.h> 2459243Sobrien#endif 2559243Sobrien#ifdef HAVE_SYS_STAT_H 2659243Sobrien# include <sys/stat.h> 2759243Sobrien#endif 2859243Sobrien#include <stdio.h> 2959243Sobrien#if !defined(VMS) /*wjm*/ 3059243Sobrien# ifdef HAVE_SYS_PARAM_H 3159243Sobrien# include <sys/param.h> 3259243Sobrien# endif 3359243Sobrien#endif /* VMS */ 3459243Sobrien#ifdef HAVE_SYS_SIGNAL_H 35231990Smp# include <sys/signal.h> 3659243Sobrien#else 37231990Smp# include <signal.h> 3859243Sobrien#endif 3959243Sobrien#ifdef HAVE_SYS_IOCTL_H 40145479Smp# include <sys/ioctl.h> 41167465Smp#endif /* HAVE_SYS_IOCTL_H */ 4259243Sobrien#ifdef HAVE_SYS_RESOURCE_H 4359243Sobrien# include <sys/resource.h> 44167465Smp#endif /* HAVE_SYS_RESOURCE_H */ 45167465Smp#if defined(HAVE_RTPRIO) 4659243Sobrien# ifdef HAVE_SYS_RESOURCE_H 4759243Sobrien# include <sys/resource.h> 4859243Sobrien# endif 4959243Sobrien# ifdef HAVE_SYS_LOCK_H 5059243Sobrien# include <sys/lock.h> 5159243Sobrien# endif 5259243Sobrien# include <sys/rtprio.h> 5359243Sobrien#else 5459243Sobrien# ifdef HAVE_PLOCK 5559243Sobrien# ifdef HAVE_SYS_LOCK_H 5659243Sobrien# include <sys/lock.h> 5759243Sobrien# endif 5859243Sobrien# endif 59231990Smp#endif 60231990Smp#if defined(HAVE_SCHED_SETSCHEDULER) 61231990Smp# ifdef HAVE_SCHED_H 62231990Smp# include <sched.h> 63231990Smp# else 64231990Smp# ifdef HAVE_SYS_SCHED_H 65231990Smp# include <sys/sched.h> 66231990Smp# endif 67231990Smp# endif 68231990Smp#endif 69231990Smp#if defined(HAVE_SYS_MMAN_H) 70231990Smp# include <sys/mman.h> 71231990Smp#endif 72231990Smp 73231990Smp#ifdef HAVE_TERMIOS_H 74231990Smp# include <termios.h> 75231990Smp#endif 76231990Smp 77231990Smp#ifdef SYS_DOMAINOS 78231990Smp# include <apollo/base.h> 79231990Smp#endif /* SYS_DOMAINOS */ 80231990Smp 81231990Smp#include "recvbuff.h" 82231990Smp#include "ntp_cmdargs.h" 83231990Smp 84231990Smp#if 0 /* HMS: I don't think we need this. 961223 */ 85231990Smp#ifdef LOCK_PROCESS 86231990Smp# ifdef SYS_SOLARIS 87231990Smp# include <sys/mman.h> 88231990Smp# else 89231990Smp# include <sys/lock.h> 90231990Smp# endif 91231990Smp#endif 92231990Smp#endif 93231990Smp 94231990Smp#ifdef _AIX 95231990Smp# include <ulimit.h> 96231990Smp#endif /* _AIX */ 97231990Smp 98231990Smp#ifdef SCO5_CLOCK 99231990Smp# include <sys/ci/ciioctl.h> 100231990Smp#endif 101231990Smp 102231990Smp#ifdef HAVE_DROPROOT 103231990Smp# include <ctype.h> 104231990Smp# include <grp.h> 105231990Smp# include <pwd.h> 106231990Smp#ifdef HAVE_LINUX_CAPABILITIES 107231990Smp# include <sys/capability.h> 108231990Smp# include <sys/prctl.h> 109231990Smp#endif 110231990Smp#endif 111231990Smp 112231990Smp/* 113231990Smp * Signals we catch for debugging. If not debugging we ignore them. 114231990Smp */ 115231990Smp#define MOREDEBUGSIG SIGUSR1 116231990Smp#define LESSDEBUGSIG SIGUSR2 117231990Smp 118231990Smp/* 119231990Smp * Signals which terminate us gracefully. 120231990Smp */ 121231990Smp#ifndef SYS_WINNT 122231990Smp# define SIGDIE1 SIGHUP 123231990Smp# define SIGDIE3 SIGQUIT 124231990Smp# define SIGDIE2 SIGINT 125231990Smp# define SIGDIE4 SIGTERM 126231990Smp#endif /* SYS_WINNT */ 127231990Smp 128231990Smp#ifdef HAVE_DNSREGISTRATION 129231990Smp#include <dns_sd.h> 130231990SmpDNSServiceRef mdns; 131231990Smp#endif 132231990Smp 133231990Smp/* 134231990Smp * Scheduling priority we run at 135231990Smp */ 136231990Smp#define NTPD_PRIO (-12) 137231990Smp 138231990Smpint priority_done = 2; /* 0 - Set priority */ 139231990Smp /* 1 - priority is OK where it is */ 140231990Smp /* 2 - Don't set priority */ 141231990Smp /* 1 and 2 are pretty much the same */ 142231990Smp 14359243Sobrien#ifdef DEBUG 144231990Smp/* 145231990Smp * Debugging flag 146231990Smp */ 14759243Sobrienvolatile int debug = 0; /* No debugging by default */ 148145479Smp#endif 14959243Sobrien 15059243Sobrienint listen_to_virtual_ips = 1; 15159243Sobrienconst char *specific_interface = NULL; /* interface name or IP address to bind to */ 15259243Sobrien 15359243Sobrien/* 15459243Sobrien * No-fork flag. If set, we do not become a background daemon. 155167465Smp */ 156167465Smpint nofork = 0; /* Fork by default */ 157167465Smp 158167465Smp#ifdef HAVE_DROPROOT 15959243Sobrienint droproot = 0; 160167465Smpchar *user = NULL; /* User to switch to */ 16159243Sobrienchar *group = NULL; /* group to switch to */ 16259243Sobrienchar *chrootdir = NULL; /* directory to chroot to */ 163231990Smpint sw_uid; 164231990Smpint sw_gid; 16559243Sobrienchar *endp; 16659243Sobrienstruct group *gr; 167231990Smpstruct passwd *pw; 168231990Smp#endif /* HAVE_DROPROOT */ 169231990Smp 170231990Smp/* 171231990Smp * Initializing flag. All async routines watch this and only do their 172231990Smp * thing when it is clear. 173231990Smp */ 174231990Smpint initializing; 175231990Smp 176231990Smp/* 177231990Smp * Version declaration 178231990Smp */ 179231990Smpextern const char *Version; 180231990Smp 181231990Smpchar const *progname; 182231990Smp 183231990Smpint was_alarmed; 184231990Smp 185231990Smp#ifdef DECL_SYSCALL 186231990Smp/* 187231990Smp * We put this here, since the argument profile is syscall-specific 188231990Smp */ 189231990Smpextern int syscall P((int, ...)); 190231990Smp#endif /* DECL_SYSCALL */ 191231990Smp 192231990Smp 193231990Smp#ifdef SIGDIE2 194231990Smpstatic RETSIGTYPE finish P((int)); 195231990Smp#endif /* SIGDIE2 */ 196231990Smp 197231990Smp#ifdef DEBUG 198231990Smp#ifndef SYS_WINNT 199231990Smpstatic RETSIGTYPE moredebug P((int)); 200231990Smpstatic RETSIGTYPE lessdebug P((int)); 201231990Smp#endif 202231990Smp#else /* not DEBUG */ 203231990Smpstatic RETSIGTYPE no_debug P((int)); 204231990Smp#endif /* not DEBUG */ 205231990Smp 206231990Smpint ntpdmain P((int, char **)); 207231990Smpstatic void set_process_priority P((void)); 208231990Smpstatic void init_logging P((char const *)); 209231990Smpstatic void setup_logfile P((void)); 210231990Smp 211231990Smp/* 212231990Smp * Initialize the logging 213231990Smp */ 214231990Smpvoid 215231990Smpinit_logging(char const *name) 216231990Smp{ 217231990Smp const char *cp; 218231990Smp 219231990Smp /* 220231990Smp * Logging. This may actually work on the gizmo board. Find a name 221231990Smp * to log with by using the basename 222231990Smp */ 223231990Smp cp = strrchr(name, '/'); 224231990Smp if (cp == 0) 225231990Smp cp = name; 226231990Smp else 227231990Smp cp++; 228231990Smp 229231990Smp#if !defined(VMS) 230231990Smp 231231990Smp# ifndef LOG_DAEMON 232231990Smp openlog(cp, LOG_PID); 233231990Smp# else /* LOG_DAEMON */ 234231990Smp 235231990Smp# ifndef LOG_NTP 236231990Smp# define LOG_NTP LOG_DAEMON 237231990Smp# endif 238231990Smp openlog(cp, LOG_PID | LOG_NDELAY, LOG_NTP); 239231990Smp# ifdef DEBUG 240231990Smp if (debug) 241231990Smp setlogmask(LOG_UPTO(LOG_DEBUG)); 242231990Smp else 243231990Smp# endif /* DEBUG */ 244231990Smp setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */ 245231990Smp# endif /* LOG_DAEMON */ 246231990Smp#endif /* !SYS_WINNT && !VMS */ 247231990Smp 248231990Smp NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */ 249231990Smp msyslog(LOG_NOTICE, "%s", Version); 250231990Smp} 251231990Smp 252231990Smp 253231990Smp/* 254231990Smp * See if we should redirect the logfile 255231990Smp */ 256231990Smp 257231990Smpvoid 258231990Smpsetup_logfile( 259231990Smp void 260231990Smp ) 261231990Smp{ 262231990Smp if (HAVE_OPT( LOGFILE )) { 263231990Smp const char *my_optarg = OPT_ARG( LOGFILE ); 264231990Smp FILE *new_file; 265231990Smp 266231990Smp if(strcmp(my_optarg, "stderr") == 0) 267231990Smp new_file = stderr; 268231990Smp else if(strcmp(my_optarg, "stdout") == 0) 269231990Smp new_file = stdout; 270231990Smp else 271231990Smp new_file = fopen(my_optarg, "a"); 272231990Smp if (new_file != NULL) { 273231990Smp NLOG(NLOG_SYSINFO) 274231990Smp msyslog(LOG_NOTICE, "logging to file %s", my_optarg); 275231990Smp if (syslog_file != NULL && 276231990Smp fileno(syslog_file) != fileno(new_file)) 277231990Smp (void)fclose(syslog_file); 278231990Smp 279231990Smp syslog_file = new_file; 280231990Smp syslogit = 0; 281231990Smp } 282231990Smp else 283231990Smp msyslog(LOG_ERR, 284231990Smp "Cannot open log file %s", 285231990Smp my_optarg); 286231990Smp } 287231990Smp} 288231990Smp 289231990Smp#ifdef SIM 290231990Smpint 291231990Smpmain( 292231990Smp int argc, 293231990Smp char *argv[] 294231990Smp ) 295231990Smp{ 296231990Smp return ntpsim(argc, argv); 297231990Smp} 298231990Smp#else /* SIM */ 299231990Smp#ifdef NO_MAIN_ALLOWED 300231990SmpCALL(ntpd,"ntpd",ntpdmain); 301231990Smp#else 302231990Smp#ifndef SYS_WINNT 303231990Smpint 304231990Smpmain( 305231990Smp int argc, 306231990Smp char *argv[] 307231990Smp ) 308231990Smp{ 309231990Smp return ntpdmain(argc, argv); 310231990Smp} 311231990Smp#endif /* SYS_WINNT */ 312231990Smp#endif /* NO_MAIN_ALLOWED */ 313231990Smp#endif /* SIM */ 314231990Smp 315231990Smp#ifdef _AIX 316231990Smp/* 317231990Smp * OK. AIX is different than solaris in how it implements plock(). 318231990Smp * If you do NOT adjust the stack limit, you will get the MAXIMUM 319231990Smp * stack size allocated and PINNED with you program. To check the 320231990Smp * value, use ulimit -a. 321231990Smp * 322231990Smp * To fix this, we create an automatic variable and set our stack limit 323231990Smp * to that PLUS 32KB of extra space (we need some headroom). 324231990Smp * 325231990Smp * This subroutine gets the stack address. 326231990Smp * 327231990Smp * Grover Davidson and Matt Ladendorf 328231990Smp * 329231990Smp */ 330231990Smpstatic char * 331231990Smpget_aix_stack(void) 332231990Smp{ 333231990Smp char ch; 334231990Smp return (&ch); 335231990Smp} 336231990Smp 337231990Smp/* 338231990Smp * Signal handler for SIGDANGER. 339231990Smp */ 340231990Smpstatic void 341231990Smpcatch_danger(int signo) 342231990Smp{ 343231990Smp msyslog(LOG_INFO, "ntpd: setpgid(): %m"); 344231990Smp /* Make the system believe we'll free something, but don't do it! */ 345231990Smp return; 346231990Smp} 347231990Smp#endif /* _AIX */ 348231990Smp 349231990Smp/* 350231990Smp * Set the process priority 351231990Smp */ 352231990Smpstatic void 353231990Smpset_process_priority(void) 354231990Smp{ 355231990Smp 356231990Smp#ifdef DEBUG 357231990Smp if (debug > 1) 358231990Smp msyslog(LOG_DEBUG, "set_process_priority: %s: priority_done is <%d>", 359231990Smp ((priority_done) 360231990Smp ? "Leave priority alone" 361231990Smp : "Attempt to set priority" 362231990Smp ), 363231990Smp priority_done); 364231990Smp#endif /* DEBUG */ 365231990Smp 366231990Smp#ifdef SYS_WINNT 367231990Smp priority_done += NT_set_process_priority(); 368231990Smp#endif 369231990Smp 370231990Smp#if defined(HAVE_SCHED_SETSCHEDULER) 371231990Smp if (!priority_done) { 372231990Smp extern int config_priority_override, config_priority; 373231990Smp int pmax, pmin; 374231990Smp struct sched_param sched; 375231990Smp 376231990Smp pmax = sched_get_priority_max(SCHED_FIFO); 377231990Smp sched.sched_priority = pmax; 378231990Smp if ( config_priority_override ) { 379231990Smp pmin = sched_get_priority_min(SCHED_FIFO); 380231990Smp if ( config_priority > pmax ) 381231990Smp sched.sched_priority = pmax; 382231990Smp else if ( config_priority < pmin ) 383231990Smp sched.sched_priority = pmin; 384231990Smp else 385231990Smp sched.sched_priority = config_priority; 386231990Smp } 387231990Smp if ( sched_setscheduler(0, SCHED_FIFO, &sched) == -1 ) 388231990Smp msyslog(LOG_ERR, "sched_setscheduler(): %m"); 389231990Smp else 390231990Smp ++priority_done; 391231990Smp } 392231990Smp#endif /* HAVE_SCHED_SETSCHEDULER */ 393231990Smp#if defined(HAVE_RTPRIO) 394231990Smp# ifdef RTP_SET 395231990Smp if (!priority_done) { 396231990Smp struct rtprio srtp; 397231990Smp 398231990Smp srtp.type = RTP_PRIO_REALTIME; /* was: RTP_PRIO_NORMAL */ 399231990Smp srtp.prio = 0; /* 0 (hi) -> RTP_PRIO_MAX (31,lo) */ 400231990Smp 401231990Smp if (rtprio(RTP_SET, getpid(), &srtp) < 0) 402231990Smp msyslog(LOG_ERR, "rtprio() error: %m"); 403231990Smp else 404231990Smp ++priority_done; 405231990Smp } 406231990Smp# else /* not RTP_SET */ 407231990Smp if (!priority_done) { 408231990Smp if (rtprio(0, 120) < 0) 409231990Smp msyslog(LOG_ERR, "rtprio() error: %m"); 410231990Smp else 411231990Smp ++priority_done; 412231990Smp } 413231990Smp# endif /* not RTP_SET */ 414231990Smp#endif /* HAVE_RTPRIO */ 415231990Smp#if defined(NTPD_PRIO) && NTPD_PRIO != 0 416231990Smp# ifdef HAVE_ATT_NICE 417231990Smp if (!priority_done) { 418231990Smp errno = 0; 419231990Smp if (-1 == nice (NTPD_PRIO) && errno != 0) 420231990Smp msyslog(LOG_ERR, "nice() error: %m"); 421231990Smp else 422231990Smp ++priority_done; 423231990Smp } 424231990Smp# endif /* HAVE_ATT_NICE */ 425231990Smp# ifdef HAVE_BSD_NICE 426231990Smp if (!priority_done) { 427231990Smp if (-1 == setpriority(PRIO_PROCESS, 0, NTPD_PRIO)) 428231990Smp msyslog(LOG_ERR, "setpriority() error: %m"); 429231990Smp else 430231990Smp ++priority_done; 431231990Smp } 432231990Smp# endif /* HAVE_BSD_NICE */ 433231990Smp#endif /* NTPD_PRIO && NTPD_PRIO != 0 */ 434231990Smp if (!priority_done) 435231990Smp msyslog(LOG_ERR, "set_process_priority: No way found to improve our priority"); 436231990Smp} 437231990Smp 438231990Smp 439231990Smp/* 440231990Smp * Main program. Initialize us, disconnect us from the tty if necessary, 441231990Smp * and loop waiting for I/O and/or timer expiries. 442231990Smp */ 443231990Smpint 444231990Smpntpdmain( 445231990Smp int argc, 446231990Smp char *argv[] 447231990Smp ) 448231990Smp{ 449231990Smp l_fp now; 450231990Smp struct recvbuf *rbuf; 451231990Smp#ifdef _AIX /* HMS: ifdef SIGDANGER? */ 452231990Smp struct sigaction sa; 453231990Smp#endif 454231990Smp 455231990Smp progname = argv[0]; 456231990Smp 457231990Smp initializing = 1; /* mark that we are initializing */ 458231990Smp 459231990Smp { 460231990Smp int optct = optionProcess( 461231990Smp#ifdef SIM 462231990Smp &ntpdsimOptions 463231990Smp#else 464231990Smp &ntpdOptions 465231990Smp#endif 466231990Smp , argc, argv); 467231990Smp argc -= optct; 468231990Smp argv += optct; 469231990Smp } 470231990Smp 471231990Smp /* HMS: is this lame? Should we process -l first? */ 472231990Smp 473231990Smp init_logging(progname); /* Open the log file */ 474231990Smp 475231990Smp#ifdef HAVE_UMASK 476231990Smp { 477231990Smp mode_t uv; 478231990Smp 479231990Smp uv = umask(0); 480231990Smp if(uv) 481231990Smp (void) umask(uv); 482231990Smp else 483231990Smp (void) umask(022); 484231990Smp } 485231990Smp#endif 486231990Smp 487231990Smp#if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */ 488231990Smp { 489231990Smp uid_t uid; 490231990Smp 491231990Smp uid = getuid(); 492231990Smp if (uid) 493231990Smp { 494231990Smp msyslog(LOG_ERR, "ntpd: must be run as root, not uid %ld", (long)uid); 495231990Smp printf("must be run as root, not uid %ld", (long)uid); 496231990Smp exit(1); 497231990Smp } 498231990Smp } 499231990Smp#endif 500231990Smp 501231990Smp#ifdef OPENSSL 502231990Smp if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) { 503231990Smp msyslog(LOG_ERR, 504231990Smp "ntpd: OpenSSL version mismatch. Built against %lx, you have %lx\n", 505231990Smp OPENSSL_VERSION_NUMBER, SSLeay()); 506231990Smp exit(1); 507231990Smp } 508231990Smp#endif 509231990Smp 510231990Smp /* getstartup(argc, argv); / * startup configuration, may set debug */ 511231990Smp 512231990Smp#ifdef DEBUG 513231990Smp debug = DESC(DEBUG_LEVEL).optOccCt; 514231990Smp if (debug) 515231990Smp printf("%s\n", Version); 516231990Smp#endif 517231990Smp 518231990Smp/* 519231990Smp * Enable the Multi-Media Timer for Windows? 520231990Smp */ 521231990Smp#ifdef SYS_WINNT 522231990Smp if (HAVE_OPT( MODIFYMMTIMER )) 523231990Smp set_mm_timer(MM_TIMER_HIRES); 524231990Smp#endif 525231990Smp 526231990Smp if (HAVE_OPT( NOFORK ) || HAVE_OPT( QUIT )) 527231990Smp nofork = 1; 528231990Smp 529231990Smp if (HAVE_OPT( NOVIRTUALIPS )) 530231990Smp listen_to_virtual_ips = 0; 531231990Smp 532231990Smp if (HAVE_OPT( INTERFACE )) { 533231990Smp#if 0 534231990Smp int ifacect = STACKCT_OPT( INTERFACE ); 535231990Smp char** ifaces = STACKLST_OPT( INTERFACE ); 536231990Smp 537231990Smp /* malloc space for the array of names */ 538231990Smp while (ifacect-- > 0) { 539231990Smp next_iface = *ifaces++; 540231990Smp } 541231990Smp#else 542231990Smp specific_interface = OPT_ARG( INTERFACE ); 543231990Smp#endif 544231990Smp } 545231990Smp 546231990Smp if (HAVE_OPT( NICE )) 547231990Smp priority_done = 0; 548231990Smp 549231990Smp#if defined(HAVE_SCHED_SETSCHEDULER) 550231990Smp if (HAVE_OPT( PRIORITY )) { 551231990Smp config_priority = OPT_VALUE_PRIORITY; 552231990Smp config_priority_override = 1; 553231990Smp priority_done = 0; 554231990Smp } 555231990Smp#endif 556231990Smp 557231990Smp#ifdef SYS_WINNT 558231990Smp /* 559231990Smp * Initialize the time structures and variables 560231990Smp */ 561231990Smp init_winnt_time(); 562231990Smp#endif 563231990Smp 564231990Smp setup_logfile(); 565231990Smp 566231990Smp /* 567231990Smp * Initialize random generator and public key pair 568231990Smp */ 569231990Smp get_systime(&now); 570231990Smp 571231990Smp ntp_srandom((int)(now.l_i * now.l_uf)); 572231990Smp 573231990Smp#ifdef HAVE_DNSREGISTRATION 574231990Smp /* HMS: does this have to happen this early? */ 575231990Smp msyslog(LOG_INFO, "Attemping to register mDNS"); 576231990Smp if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL, htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) { 577231990Smp msyslog(LOG_ERR, "Unable to register mDNS"); 578231990Smp } 579231990Smp#endif 580231990Smp 581231990Smp#if !defined(VMS) 582231990Smp# ifndef NODETACH 583231990Smp /* 584231990Smp * Detach us from the terminal. May need an #ifndef GIZMO. 585231990Smp */ 586231990Smp if ( 587231990Smp# ifdef DEBUG 588231990Smp !debug && 589231990Smp# endif /* DEBUG */ 590231990Smp !nofork) 591231990Smp { 592231990Smp# ifndef SYS_WINNT 593231990Smp# ifdef HAVE_DAEMON 594231990Smp daemon(0, 0); 595231990Smp# else /* not HAVE_DAEMON */ 596231990Smp if (fork()) /* HMS: What about a -1? */ 597231990Smp exit(0); 598231990Smp 599231990Smp { 600231990Smp#if !defined(F_CLOSEM) 601231990Smp u_long s; 602145479Smp int max_fd; 603167465Smp#endif /* not F_CLOSEM */ 60459243Sobrien 605167465Smp#if defined(F_CLOSEM) 60659243Sobrien /* 60759243Sobrien * From 'Writing Reliable AIX Daemons,' SG24-4946-00, 60859243Sobrien * by Eric Agar (saves us from doing 32767 system 60959243Sobrien * calls) 61059243Sobrien */ 61159243Sobrien if (fcntl(0, F_CLOSEM, 0) == -1) 61259243Sobrien msyslog(LOG_ERR, "ntpd: failed to close open files(): %m"); 61359243Sobrien#else /* not F_CLOSEM */ 61459243Sobrien 61559243Sobrien# if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX) 616231990Smp max_fd = sysconf(_SC_OPEN_MAX); 61759243Sobrien# else /* HAVE_SYSCONF && _SC_OPEN_MAX */ 61859243Sobrien max_fd = getdtablesize(); 619231990Smp# endif /* HAVE_SYSCONF && _SC_OPEN_MAX */ 620231990Smp for (s = 0; s < max_fd; s++) 621231990Smp (void) close((int)s); 622231990Smp#endif /* not F_CLOSEM */ 623231990Smp (void) open("/", 0); 624231990Smp (void) dup2(0, 1); 625231990Smp (void) dup2(0, 2); 626231990Smp#ifdef SYS_DOMAINOS 62759243Sobrien { 628231990Smp uid_$t puid; 629231990Smp status_$t st; 630231990Smp 631231990Smp proc2_$who_am_i(&puid); 632231990Smp proc2_$make_server(&puid, &st); 633231990Smp } 634231990Smp#endif /* SYS_DOMAINOS */ 635231990Smp#if defined(HAVE_SETPGID) || defined(HAVE_SETSID) 636231990Smp# ifdef HAVE_SETSID 637231990Smp if (setsid() == (pid_t)-1) 638231990Smp msyslog(LOG_ERR, "ntpd: setsid(): %m"); 639231990Smp# else 640231990Smp if (setpgid(0, 0) == -1) 641231990Smp msyslog(LOG_ERR, "ntpd: setpgid(): %m"); 642231990Smp# endif 643231990Smp#else /* HAVE_SETPGID || HAVE_SETSID */ 644231990Smp { 645231990Smp# if defined(TIOCNOTTY) 646231990Smp int fid; 647231990Smp 648231990Smp fid = open("/dev/tty", 2); 649231990Smp if (fid >= 0) 650231990Smp { 651231990Smp (void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0); 652231990Smp (void) close(fid); 653231990Smp } 654231990Smp# endif /* defined(TIOCNOTTY) */ 655231990Smp# ifdef HAVE_SETPGRP_0 656231990Smp (void) setpgrp(); 657231990Smp# else /* HAVE_SETPGRP_0 */ 658231990Smp (void) setpgrp(0, getpid()); 659231990Smp# endif /* HAVE_SETPGRP_0 */ 660231990Smp } 661231990Smp#endif /* HAVE_SETPGID || HAVE_SETSID */ 662231990Smp#ifdef _AIX 663231990Smp /* Don't get killed by low-on-memory signal. */ 664231990Smp sa.sa_handler = catch_danger; 665231990Smp sigemptyset(&sa.sa_mask); 666231990Smp sa.sa_flags = SA_RESTART; 667231990Smp 668231990Smp (void) sigaction(SIGDANGER, &sa, NULL); 669231990Smp#endif /* _AIX */ 670231990Smp } 671231990Smp# endif /* not HAVE_DAEMON */ 672231990Smp# endif /* SYS_WINNT */ 673231990Smp } 674231990Smp# endif /* NODETACH */ 675231990Smp#endif /* VMS */ 676231990Smp 677231990Smp setup_logfile(); /* We lost any redirect when we daemonized */ 678231990Smp 679231990Smp#ifdef SCO5_CLOCK 680231990Smp /* 681231990Smp * SCO OpenServer's system clock offers much more precise timekeeping 682231990Smp * on the base CPU than the other CPUs (for multiprocessor systems), 683231990Smp * so we must lock to the base CPU. 684231990Smp */ 685231990Smp { 686231990Smp int fd = open("/dev/at1", O_RDONLY); 687231990Smp if (fd >= 0) { 688231990Smp int zero = 0; 689231990Smp if (ioctl(fd, ACPU_LOCK, &zero) < 0) 690231990Smp msyslog(LOG_ERR, "cannot lock to base CPU: %m"); 691231990Smp close( fd ); 692231990Smp } /* else ... 693231990Smp * If we can't open the device, this probably just isn't 694231990Smp * a multiprocessor system, so we're A-OK. 695231990Smp */ 696231990Smp } 697231990Smp#endif 698231990Smp 699231990Smp#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && defined(MCL_FUTURE) 700231990Smp# ifdef HAVE_SETRLIMIT 701231990Smp /* 702231990Smp * Set the stack limit to something smaller, so that we don't lock a lot 703231990Smp * of unused stack memory. 704231990Smp */ 705231990Smp { 706231990Smp struct rlimit rl; 707231990Smp 708231990Smp /* HMS: must make the rlim_cur amount configurable */ 709231990Smp if (getrlimit(RLIMIT_STACK, &rl) != -1 710231990Smp && (rl.rlim_cur = 50 * 4096) < rl.rlim_max) 711231990Smp { 712231990Smp if (setrlimit(RLIMIT_STACK, &rl) == -1) 713231990Smp { 714231990Smp msyslog(LOG_ERR, 715231990Smp "Cannot adjust stack limit for mlockall: %m"); 716231990Smp } 717231990Smp } 718231990Smp# ifdef RLIMIT_MEMLOCK 719231990Smp /* 720231990Smp * The default RLIMIT_MEMLOCK is very low on Linux systems. 721231990Smp * Unless we increase this limit malloc calls are likely to 722231990Smp * fail if we drop root privlege. To be useful the value 723231990Smp * has to be larger than the largest ntpd resident set size. 724231990Smp */ 725231990Smp rl.rlim_cur = rl.rlim_max = 32*1024*1024; 726231990Smp if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) { 727231990Smp msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m"); 728231990Smp } 729231990Smp# endif /* RLIMIT_MEMLOCK */ 730231990Smp } 731231990Smp# endif /* HAVE_SETRLIMIT */ 732231990Smp /* 733231990Smp * lock the process into memory 734231990Smp */ 735231990Smp if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0) 736231990Smp msyslog(LOG_ERR, "mlockall(): %m"); 737231990Smp#else /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */ 738231990Smp# ifdef HAVE_PLOCK 739231990Smp# ifdef PROCLOCK 740231990Smp# ifdef _AIX 741231990Smp /* 742231990Smp * set the stack limit for AIX for plock(). 743231990Smp * see get_aix_stack() for more info. 744231990Smp */ 745231990Smp if (ulimit(SET_STACKLIM, (get_aix_stack() - 8*4096)) < 0) 746231990Smp { 747231990Smp msyslog(LOG_ERR,"Cannot adjust stack limit for plock on AIX: %m"); 748231990Smp } 749231990Smp# endif /* _AIX */ 750231990Smp /* 751231990Smp * lock the process into memory 752231990Smp */ 753231990Smp if (plock(PROCLOCK) < 0) 754231990Smp msyslog(LOG_ERR, "plock(PROCLOCK): %m"); 755231990Smp# else /* not PROCLOCK */ 756231990Smp# ifdef TXTLOCK 757231990Smp /* 758231990Smp * Lock text into ram 759231990Smp */ 760231990Smp if (plock(TXTLOCK) < 0) 761231990Smp msyslog(LOG_ERR, "plock(TXTLOCK) error: %m"); 762231990Smp# else /* not TXTLOCK */ 763231990Smp msyslog(LOG_ERR, "plock() - don't know what to lock!"); 764231990Smp# endif /* not TXTLOCK */ 765231990Smp# endif /* not PROCLOCK */ 766231990Smp# endif /* HAVE_PLOCK */ 767231990Smp#endif /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */ 768231990Smp 769231990Smp /* 770231990Smp * Set up signals we pay attention to locally. 771231990Smp */ 772231990Smp#ifdef SIGDIE1 773231990Smp (void) signal_no_reset(SIGDIE1, finish); 774231990Smp#endif /* SIGDIE1 */ 775231990Smp#ifdef SIGDIE2 776231990Smp (void) signal_no_reset(SIGDIE2, finish); 777231990Smp#endif /* SIGDIE2 */ 778231990Smp#ifdef SIGDIE3 779231990Smp (void) signal_no_reset(SIGDIE3, finish); 780231990Smp#endif /* SIGDIE3 */ 781231990Smp#ifdef SIGDIE4 782231990Smp (void) signal_no_reset(SIGDIE4, finish); 783231990Smp#endif /* SIGDIE4 */ 784231990Smp 785231990Smp#ifdef SIGBUS 786231990Smp (void) signal_no_reset(SIGBUS, finish); 787231990Smp#endif /* SIGBUS */ 788231990Smp 789231990Smp#if !defined(SYS_WINNT) && !defined(VMS) 790231990Smp# ifdef DEBUG 791231990Smp (void) signal_no_reset(MOREDEBUGSIG, moredebug); 792231990Smp (void) signal_no_reset(LESSDEBUGSIG, lessdebug); 793231990Smp# else 794231990Smp (void) signal_no_reset(MOREDEBUGSIG, no_debug); 795231990Smp (void) signal_no_reset(LESSDEBUGSIG, no_debug); 796231990Smp# endif /* DEBUG */ 797231990Smp#endif /* !SYS_WINNT && !VMS */ 798231990Smp 799231990Smp /* 800231990Smp * Set up signals we should never pay attention to. 801231990Smp */ 802231990Smp#if defined SIGPIPE 803231990Smp (void) signal_no_reset(SIGPIPE, SIG_IGN); 804231990Smp#endif /* SIGPIPE */ 805231990Smp 806231990Smp /* 807231990Smp * Call the init_ routines to initialize the data structures. 808231990Smp * 809231990Smp * Exactly what command-line options are we expecting here? 810231990Smp */ 811231990Smp init_auth(); 812231990Smp init_util(); 813231990Smp init_restrict(); 814231990Smp init_mon(); 815231990Smp init_timer(); 816231990Smp init_lib(); 817231990Smp init_request(); 818231990Smp init_control(); 819231990Smp init_peer(); 820231990Smp#ifdef REFCLOCK 821231990Smp init_refclock(); 822231990Smp#endif 823231990Smp set_process_priority(); 824231990Smp init_proto(); /* Call at high priority */ 825231990Smp init_io(); 826231990Smp init_loopfilter(); 827231990Smp mon_start(MON_ON); /* monitor on by default now */ 828231990Smp /* turn off in config if unwanted */ 829231990Smp 830231990Smp /* 831231990Smp * Get the configuration. This is done in a separate module 832231990Smp * since this will definitely be different for the gizmo board. 833231990Smp */ 834231990Smp 835231990Smp getconfig(argc, argv); 836231990Smp 837231990Smp loop_config(LOOP_DRIFTCOMP, old_drift / 1e6); 838231990Smp#ifdef OPENSSL 839231990Smp crypto_setup(); 840231990Smp#endif /* OPENSSL */ 841231990Smp initializing = 0; 842231990Smp 843231990Smp#ifdef HAVE_DROPROOT 844231990Smp if( droproot ) { 845231990Smp /* Drop super-user privileges and chroot now if the OS supports this */ 846231990Smp 847231990Smp#ifdef HAVE_LINUX_CAPABILITIES 848231990Smp /* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */ 849231990Smp if( prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1 ) { 850231990Smp msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" ); 851231990Smp exit(-1); 852231990Smp } 853231990Smp#else 854231990Smp /* we need a user to switch to */ 855231990Smp if( user == NULL ) { 856231990Smp msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" ); 857231990Smp exit(-1); 858231990Smp } 859231990Smp#endif /* HAVE_LINUX_CAPABILITIES */ 860231990Smp 861231990Smp if (user != NULL) { 862231990Smp if (isdigit((unsigned char)*user)) { 863231990Smp sw_uid = (uid_t)strtoul(user, &endp, 0); 864231990Smp if (*endp != '\0') 865231990Smp goto getuser; 866231990Smp } else { 867231990Smpgetuser: 868231990Smp if ((pw = getpwnam(user)) != NULL) { 869231990Smp sw_uid = pw->pw_uid; 870231990Smp } else { 871231990Smp errno = 0; 872231990Smp msyslog(LOG_ERR, "Cannot find user `%s'", user); 873231990Smp exit (-1); 874231990Smp } 875231990Smp } 876231990Smp } 877231990Smp if (group != NULL) { 878231990Smp if (isdigit((unsigned char)*group)) { 879231990Smp sw_gid = (gid_t)strtoul(group, &endp, 0); 880231990Smp if (*endp != '\0') 881231990Smp goto getgroup; 882231990Smp } else { 883231990Smpgetgroup: 884231990Smp if ((gr = getgrnam(group)) != NULL) { 885231990Smp sw_gid = gr->gr_gid; 886231990Smp } else { 887231990Smp errno = 0; 888231990Smp msyslog(LOG_ERR, "Cannot find group `%s'", group); 889231990Smp exit (-1); 890231990Smp } 891231990Smp } 892231990Smp } 893231990Smp 894231990Smp if( chrootdir ) { 895231990Smp /* make sure cwd is inside the jail: */ 896231990Smp if( chdir(chrootdir) ) { 897231990Smp msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir); 898231990Smp exit (-1); 899231990Smp } 900231990Smp if( chroot(chrootdir) ) { 901231990Smp msyslog(LOG_ERR, "Cannot chroot() to `%s': %m", chrootdir); 902231990Smp exit (-1); 903231990Smp } 904231990Smp } 905231990Smp if (group && setgid(sw_gid)) { 906231990Smp msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group); 907231990Smp exit (-1); 908231990Smp } 909231990Smp if (group && setegid(sw_gid)) { 910231990Smp msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group); 911231990Smp exit (-1); 912231990Smp } 913231990Smp if (user && setuid(sw_uid)) { 914231990Smp msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user); 915231990Smp exit (-1); 916231990Smp } 917231990Smp if (user && seteuid(sw_uid)) { 918231990Smp msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user); 919231990Smp exit (-1); 920231990Smp } 921231990Smp 922231990Smp#ifndef HAVE_LINUX_CAPABILITIES 923231990Smp /* 924231990Smp * for now assume that the privilege to bind to privileged ports 925231990Smp * is associated with running with uid 0 - should be refined on 926231990Smp * ports that allow binding to NTP_PORT with uid != 0 927231990Smp */ 928231990Smp disable_dynamic_updates |= (sw_uid != 0); /* also notifies routing message listener */ 929231990Smp#endif 930231990Smp 93159243Sobrien if (disable_dynamic_updates && interface_interval) { 932231990Smp interface_interval = 0; 933231990Smp msyslog(LOG_INFO, "running in unprivileged mode disables dynamic interface tracking"); 934231990Smp } 935231990Smp 936231990Smp#ifdef HAVE_LINUX_CAPABILITIES 937231990Smp do { 93859243Sobrien /* 939231990Smp * We may be running under non-root uid now, but we still hold full root privileges! 940145479Smp * We drop all of them, except for the crucial one or two: cap_sys_time and 941167465Smp * cap_net_bind_service if doing dynamic interface tracking. 942231990Smp */ 943231990Smp cap_t caps; 94459243Sobrien char *captext = interface_interval ? 94559243Sobrien "cap_sys_time,cap_net_bind_service=ipe" : 94659243Sobrien "cap_sys_time=ipe"; 947231990Smp if( ! ( caps = cap_from_text( captext ) ) ) { 948231990Smp msyslog( LOG_ERR, "cap_from_text() failed: %m" ); 949231990Smp exit(-1); 950231990Smp } 951231990Smp if( cap_set_proc( caps ) == -1 ) { 952231990Smp msyslog( LOG_ERR, "cap_set_proc() failed to drop root privileges: %m" ); 953231990Smp exit(-1); 954231990Smp } 955231990Smp cap_free( caps ); 956231990Smp } while(0); 957231990Smp#endif /* HAVE_LINUX_CAPABILITIES */ 958231990Smp 959231990Smp } /* if( droproot ) */ 960231990Smp#endif /* HAVE_DROPROOT */ 961231990Smp 962231990Smp /* 963231990Smp * Report that we're up to any trappers 96459243Sobrien */ 96559243Sobrien report_event(EVNT_SYSRESTART, (struct peer *)0); 966231990Smp 967231990Smp /* 968231990Smp * Use select() on all on all input fd's for unlimited 969231990Smp * time. select() will terminate on SIGALARM or on the 970231990Smp * reception of input. Using select() means we can't do 971231990Smp * robust signal handling and we get a potential race 97259243Sobrien * between checking for alarms and doing the select(). 97359243Sobrien * Mostly harmless, I think. 97459243Sobrien */ 97559243Sobrien /* On VMS, I suspect that select() can't be interrupted 97659243Sobrien * by a "signal" either, so I take the easy way out and 97759243Sobrien * have select() time out after one second. 97859243Sobrien * System clock updates really aren't time-critical, 97959243Sobrien * and - lacking a hardware reference clock - I have 98059243Sobrien * yet to learn about anything else that is. 981167465Smp */ 98259243Sobrien#if defined(HAVE_IO_COMPLETION_PORT) 98359243Sobrien 984167465Smp for (;;) { 98559243Sobrien GetReceivedBuffers(); 98659243Sobrien#else /* normal I/O */ 98759243Sobrien 98859243Sobrien BLOCK_IO_AND_ALARM(); 989231990Smp was_alarmed = 0; 99059243Sobrien for (;;) 99159243Sobrien { 992231990Smp# if !defined(HAVE_SIGNALED_IO) 99359243Sobrien extern fd_set activefds; 994231990Smp extern int maxactivefd; 99559243Sobrien 99659243Sobrien fd_set rdfdes; 997231990Smp int nfound; 99859243Sobrien# endif 999167465Smp 100059243Sobrien if (alarm_flag) /* alarmed? */ 100159243Sobrien { 100259243Sobrien was_alarmed = 1; 100359243Sobrien alarm_flag = 0; 100459243Sobrien } 100559243Sobrien 100659243Sobrien if (!was_alarmed && has_full_recv_buffer() == ISC_FALSE) 1007231990Smp { 1008231990Smp /* 100959243Sobrien * Nothing to do. Wait for something. 1010231990Smp */ 1011231990Smp# ifndef HAVE_SIGNALED_IO 1012231990Smp rdfdes = activefds; 1013231990Smp# if defined(VMS) || defined(SYS_VXWORKS) 1014231990Smp /* make select() wake up after one second */ 1015231990Smp { 1016231990Smp struct timeval t1; 1017231990Smp 1018231990Smp t1.tv_sec = 1; t1.tv_usec = 0; 1019231990Smp nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0, 1020231990Smp (fd_set *)0, &t1); 1021231990Smp } 1022231990Smp# else 1023231990Smp nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0, 1024231990Smp (fd_set *)0, (struct timeval *)0); 1025231990Smp# endif /* VMS */ 1026231990Smp if (nfound > 0) 1027231990Smp { 1028231990Smp l_fp ts; 1029231990Smp 1030231990Smp get_systime(&ts); 1031231990Smp 1032231990Smp (void)input_handler(&ts); 1033231990Smp } 1034231990Smp else if (nfound == -1 && errno != EINTR) 1035231990Smp netsyslog(LOG_ERR, "select() error: %m"); 1036231990Smp# ifdef DEBUG 1037231990Smp else if (debug > 5) 103859243Sobrien netsyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound); 103959243Sobrien# endif /* DEBUG */ 104059243Sobrien# else /* HAVE_SIGNALED_IO */ 104159243Sobrien 1042167465Smp wait_for_signal(); 104359243Sobrien# endif /* HAVE_SIGNALED_IO */ 1044231990Smp if (alarm_flag) /* alarmed? */ 1045231990Smp { 1046231990Smp was_alarmed = 1; 104759243Sobrien alarm_flag = 0; 104859243Sobrien } 1049231990Smp } 1050167465Smp 105159243Sobrien if (was_alarmed) 105259243Sobrien { 1053231990Smp UNBLOCK_IO_AND_ALARM(); 1054231990Smp /* 1055231990Smp * Out here, signals are unblocked. Call timer routine 1056231990Smp * to process expiry. 1057231990Smp */ 105859243Sobrien timer(); 1059231990Smp was_alarmed = 0; 1060231990Smp BLOCK_IO_AND_ALARM(); 1061231990Smp } 1062231990Smp 1063231990Smp#endif /* HAVE_IO_COMPLETION_PORT */ 1064231990Smp 1065231990Smp#ifdef DEBUG_TIMING 1066231990Smp { 1067231990Smp l_fp pts; 1068231990Smp l_fp tsa, tsb; 1069231990Smp int bufcount = 0; 1070231990Smp 1071231990Smp get_systime(&pts); 1072231990Smp tsa = pts; 1073231990Smp#endif 1074231990Smp rbuf = get_full_recv_buffer(); 1075231990Smp while (rbuf != NULL) 1076231990Smp { 1077231990Smp if (alarm_flag) 1078231990Smp { 1079231990Smp was_alarmed = 1; 1080231990Smp alarm_flag = 0; 1081231990Smp } 1082231990Smp UNBLOCK_IO_AND_ALARM(); 1083231990Smp 1084231990Smp if (was_alarmed) 1085231990Smp { /* avoid timer starvation during lengthy I/O handling */ 1086231990Smp timer(); 1087231990Smp was_alarmed = 0; 1088231990Smp } 1089231990Smp 1090231990Smp /* 1091231990Smp * Call the data procedure to handle each received 1092231990Smp * packet. 1093231990Smp */ 1094231990Smp if (rbuf->receiver != NULL) /* This should always be true */ 1095231990Smp { 1096231990Smp#ifdef DEBUG_TIMING 1097231990Smp l_fp dts = pts; 1098231990Smp 1099231990Smp L_SUB(&dts, &rbuf->recv_time); 1100231990Smp DPRINTF(2, ("processing timestamp delta %s (with prec. fuzz)\n", lfptoa(&dts, 9))); 1101231990Smp collect_timing(rbuf, "buffer processing delay", 1, &dts); 1102231990Smp bufcount++; 1103231990Smp#endif 1104231990Smp (rbuf->receiver)(rbuf); 1105231990Smp } else { 1106231990Smp msyslog(LOG_ERR, "receive buffer corruption - receiver found to be NULL - ABORTING"); 1107231990Smp abort(); 1108231990Smp } 1109231990Smp 1110231990Smp BLOCK_IO_AND_ALARM(); 1111231990Smp freerecvbuf(rbuf); 1112231990Smp rbuf = get_full_recv_buffer(); 1113231990Smp } 1114231990Smp#ifdef DEBUG_TIMING 1115231990Smp get_systime(&tsb); 1116231990Smp L_SUB(&tsb, &tsa); 1117231990Smp if (bufcount) { 1118231990Smp collect_timing(NULL, "processing", bufcount, &tsb); 1119231990Smp DPRINTF(2, ("processing time for %d buffers %s\n", bufcount, lfptoa(&tsb, 9))); 1120231990Smp } 1121231990Smp } 1122231990Smp#endif 1123231990Smp 1124231990Smp /* 1125231990Smp * Go around again 1126231990Smp */ 1127231990Smp } 1128231990Smp UNBLOCK_IO_AND_ALARM(); 112959243Sobrien return 1; 113059243Sobrien} 1131167465Smp 113259243Sobrien 113359243Sobrien#ifdef SIGDIE2 113459243Sobrien/* 113559243Sobrien * finish - exit gracefully 113659243Sobrien */ 113759243Sobrienstatic RETSIGTYPE 113859243Sobrienfinish( 113959243Sobrien int sig 114059243Sobrien ) 114159243Sobrien{ 114259243Sobrien 114359243Sobrien msyslog(LOG_NOTICE, "ntpd exiting on signal %d", sig); 114459243Sobrien write_stats(); 114559243Sobrien#ifdef HAVE_DNSREGISTRATION 114659243Sobrien if (mdns != NULL) 114759243Sobrien DNSServiceRefDeallocate(mdns); 114859243Sobrien#endif 114959243Sobrien 115059243Sobrien switch (sig) 115159243Sobrien { 115259243Sobrien# ifdef SIGBUS 115359243Sobrien case SIGBUS: 115459243Sobrien printf("\nfinish(SIGBUS)\n"); 115559243Sobrien exit(0); 115659243Sobrien# endif 115759243Sobrien case 0: /* Should never happen... */ 115859243Sobrien return; 115959243Sobrien default: 116059243Sobrien exit(0); 116159243Sobrien } 116259243Sobrien} 116359243Sobrien#endif /* SIGDIE2 */ 116459243Sobrien 116559243Sobrien 116659243Sobrien#ifdef DEBUG 116759243Sobrien#ifndef SYS_WINNT 116859243Sobrien/* 116959243Sobrien * moredebug - increase debugging verbosity 1170231990Smp */ 1171231990Smpstatic RETSIGTYPE 1172231990Smpmoredebug( 117359243Sobrien int sig 117459243Sobrien ) 1175167465Smp{ 117659243Sobrien int saved_errno = errno; 1177167465Smp 117859243Sobrien if (debug < 255) 117959243Sobrien { 1180167465Smp debug++; 1181167465Smp msyslog(LOG_DEBUG, "debug raised to %d", debug); 1182167465Smp } 1183167465Smp errno = saved_errno; 1184167465Smp} 1185231990Smp 118659243Sobrien/* 118759243Sobrien * lessdebug - decrease debugging verbosity 118859243Sobrien */ 118959243Sobrienstatic RETSIGTYPE 1190167465Smplessdebug( 1191167465Smp int sig 1192167465Smp ) 1193167465Smp{ 119459243Sobrien int saved_errno = errno; 1195167465Smp 119659243Sobrien if (debug > 0) 119759243Sobrien { 1198167465Smp debug--; 119959243Sobrien msyslog(LOG_DEBUG, "debug lowered to %d", debug); 120059243Sobrien } 1201167465Smp errno = saved_errno; 120259243Sobrien} 1203167465Smp#endif 120459243Sobrien#else /* not DEBUG */ 1205145479Smp#ifndef SYS_WINNT 1206167465Smp/* 1207167465Smp * no_debug - We don't do the debug here. 1208167465Smp */ 1209167465Smpstatic RETSIGTYPE 1210167465Smpno_debug( 1211167465Smp int sig 1212167465Smp ) 1213167465Smp{ 1214167465Smp int saved_errno = errno; 121559243Sobrien 121659243Sobrien msyslog(LOG_DEBUG, "ntpd not compiled for debugging (signal %d)", sig); 1217167465Smp errno = saved_errno; 121859243Sobrien} 1219167465Smp#endif /* not SYS_WINNT */ 122059243Sobrien#endif /* not DEBUG */ 122159243Sobrien