1 /* 2 * ntpd.c - main program for the fixed point NTP daemon 3 */ 4 5 #ifdef HAVE_CONFIG_H 6 # include <config.h> 7 #endif 8 9 #include "ntp_machine.h" 10 #include "ntpd.h" 11 #include "ntp_io.h" 12 #include "ntp_stdlib.h" 13 14 #ifdef HAVE_UNISTD_H 15 # include <unistd.h> 16 #endif 17 #ifdef HAVE_SYS_STAT_H 18 # include <sys/stat.h> 19 #endif 20 #include <stdio.h> 21 #ifndef SYS_WINNT 22 # if !defined(VMS) /*wjm*/ 23 # ifdef HAVE_SYS_PARAM_H 24 # include <sys/param.h> 25 # endif 26 # endif /* VMS */ 27 # ifdef HAVE_SYS_SIGNAL_H 28 # include <sys/signal.h> 29 # else 30 # include <signal.h> 31 # endif 32 # ifdef HAVE_SYS_IOCTL_H 33 # include <sys/ioctl.h> 34 # endif /* HAVE_SYS_IOCTL_H */ 35 # ifdef HAVE_SYS_RESOURCE_H 36 # include <sys/resource.h> 37 # endif /* HAVE_SYS_RESOURCE_H */ 38 #else 39 # include <signal.h> 40 # include <process.h> 41 # include <io.h> 42 # include "../libntp/log.h" 43 # include <crtdbg.h> 44 #endif /* SYS_WINNT */ 45 #if defined(HAVE_RTPRIO) 46 # ifdef HAVE_SYS_RESOURCE_H 47 # include <sys/resource.h> 48 # endif 49 # ifdef HAVE_SYS_LOCK_H 50 # include <sys/lock.h> 51 # endif 52 # include <sys/rtprio.h> 53 #else 54 # ifdef HAVE_PLOCK 55 # ifdef HAVE_SYS_LOCK_H 56 # include <sys/lock.h> 57 # endif 58 # endif 59 #endif 60 #if defined(HAVE_SCHED_SETSCHEDULER) 61 # ifdef HAVE_SCHED_H 62 # include <sched.h> 63 # else 64 # ifdef HAVE_SYS_SCHED_H 65 # include <sys/sched.h> 66 # endif 67 # endif 68 #endif 69 #if defined(HAVE_SYS_MMAN_H) 70 # include <sys/mman.h> 71 #endif 72 73 #ifdef HAVE_TERMIOS_H 74 # include <termios.h> 75 #endif 76 77 #ifdef SYS_DOMAINOS 78 # include <apollo/base.h> 79 #endif /* SYS_DOMAINOS */ 80 81 #include "recvbuff.h" 82 #include "ntp_cmdargs.h" 83 84 #if 0 /* HMS: I don't think we need this. 961223 */ 85 #ifdef LOCK_PROCESS 86 # ifdef SYS_SOLARIS 87 # include <sys/mman.h> 88 # else 89 # include <sys/lock.h> 90 # endif 91 #endif 92 #endif 93 94 #ifdef _AIX 95 # include <ulimit.h> 96 #endif /* _AIX */ 97 98 #ifdef SCO5_CLOCK 99 # include <sys/ci/ciioctl.h> 100 #endif 101 102 #ifdef PUBKEY 103 #include "ntp_crypto.h" 104 #endif /* PUBKEY */ 105 106 /* 107 * Signals we catch for debugging. If not debugging we ignore them. 108 */ 109 #define MOREDEBUGSIG SIGUSR1 110 #define LESSDEBUGSIG SIGUSR2 111 112 /* 113 * Signals which terminate us gracefully. 114 */ 115 #ifndef SYS_WINNT 116 # define SIGDIE1 SIGHUP 117 # define SIGDIE3 SIGQUIT 118 # define SIGDIE2 SIGINT 119 # define SIGDIE4 SIGTERM 120 #endif /* SYS_WINNT */ 121 122 #if defined SYS_WINNT 123 /* handles for various threads, process, and objects */ 124 HANDLE ResolverThreadHandle = NULL; 125 /* variables used to inform the Service Control Manager of our current state */ 126 SERVICE_STATUS ssStatus; 127 SERVICE_STATUS_HANDLE sshStatusHandle; 128 HANDLE WaitHandles[3] = { NULL, NULL, NULL }; 129 char szMsgPath[255]; 130 static BOOL WINAPI OnConsoleEvent(DWORD dwCtrlType); 131 #endif /* SYS_WINNT */ 132 133 /* 134 * Scheduling priority we run at 135 */ 136 #define NTPD_PRIO (-12) 137 138 int priority_done = 2; /* 0 - Set priority */ 139 /* 1 - priority is OK where it is */ 140 /* 2 - Don't set priority */ 141 /* 1 and 2 are pretty much the same */ 142 143 /* 144 * Debugging flag 145 */ 146 volatile int debug; 147 148 /* 149 * No-fork flag. If set, we do not become a background daemon. 150 */ 151 int nofork; 152 153 /* 154 * Initializing flag. All async routines watch this and only do their 155 * thing when it is clear. 156 */ 157 int initializing; 158 159 /* 160 * Version declaration 161 */ 162 extern const char *Version; 163 164 int was_alarmed; 165 166 #ifdef DECL_SYSCALL 167 /* 168 * We put this here, since the argument profile is syscall-specific 169 */ 170 extern int syscall P((int, ...)); 171 #endif /* DECL_SYSCALL */ 172 173 174 #ifdef SIGDIE2 175 static RETSIGTYPE finish P((int)); 176 #endif /* SIGDIE2 */ 177 178 #ifdef DEBUG 179 static RETSIGTYPE moredebug P((int)); 180 static RETSIGTYPE lessdebug P((int)); 181 #else /* not DEBUG */ 182 static RETSIGTYPE no_debug P((int)); 183 #endif /* not DEBUG */ 184 185 int ntpdmain P((int, char **)); 186 static void set_process_priority P((void)); 187 188 189 #ifdef NO_MAIN_ALLOWED 190 CALL(ntpd,"ntpd",ntpdmain); 191 #else 192 int 193 main( 194 int argc, 195 char *argv[] 196 ) 197 { 198 return ntpdmain(argc, argv); 199 } 200 #endif 201 202 #ifdef _AIX 203 /* 204 * OK. AIX is different than solaris in how it implements plock(). 205 * If you do NOT adjust the stack limit, you will get the MAXIMUM 206 * stack size allocated and PINNED with you program. To check the 207 * value, use ulimit -a. 208 * 209 * To fix this, we create an automatic variable and set our stack limit 210 * to that PLUS 32KB of extra space (we need some headroom). 211 * 212 * This subroutine gets the stack address. 213 * 214 * Grover Davidson and Matt Ladendorf 215 * 216 */ 217 static char * 218 get_aix_stack(void) 219 { 220 char ch; 221 return (&ch); 222 } 223 224 /* 225 * Signal handler for SIGDANGER. 226 */ 227 static void 228 catch_danger(int signo) 229 { 230 msyslog(LOG_INFO, "ntpd: setpgid(): %m"); 231 /* Make the system believe we'll free something, but don't do it! */ 232 return; 233 } 234 #endif /* _AIX */ 235 236 /* 237 * Set the process priority 238 */ 239 static void 240 set_process_priority(void) 241 { 242 243 #ifdef DEBUG 244 if (debug > 1) 245 msyslog(LOG_DEBUG, "set_process_priority: %s: priority_done is <%d>", 246 ((priority_done) 247 ? "Leave priority alone" 248 : "Attempt to set priority" 249 ), 250 priority_done); 251 #endif /* DEBUG */ 252 253 #ifdef SYS_WINNT 254 priority_done += NT_set_process_priority(); 255 #endif 256 257 #if defined(HAVE_SCHED_SETSCHEDULER) 258 if (!priority_done) { 259 extern int config_priority_override, config_priority; 260 int pmax, pmin; 261 struct sched_param sched; 262 263 pmax = sched_get_priority_max(SCHED_FIFO); 264 sched.sched_priority = pmax; 265 if ( config_priority_override ) { 266 pmin = sched_get_priority_min(SCHED_FIFO); 267 if ( config_priority > pmax ) 268 sched.sched_priority = pmax; 269 else if ( config_priority < pmin ) 270 sched.sched_priority = pmin; 271 else 272 sched.sched_priority = config_priority; 273 } 274 if ( sched_setscheduler(0, SCHED_FIFO, &sched) == -1 ) 275 msyslog(LOG_ERR, "sched_setscheduler(): %m"); 276 else 277 ++priority_done; 278 } 279 #endif /* HAVE_SCHED_SETSCHEDULER */ 280 #if defined(HAVE_RTPRIO) 281 # ifdef RTP_SET 282 if (!priority_done) { 283 struct rtprio srtp; 284 285 srtp.type = RTP_PRIO_REALTIME; /* was: RTP_PRIO_NORMAL */ 286 srtp.prio = 0; /* 0 (hi) -> RTP_PRIO_MAX (31,lo) */ 287 288 if (rtprio(RTP_SET, getpid(), &srtp) < 0) 289 msyslog(LOG_ERR, "rtprio() error: %m"); 290 else 291 ++priority_done; 292 } 293 # else /* not RTP_SET */ 294 if (!priority_done) { 295 if (rtprio(0, 120) < 0) 296 msyslog(LOG_ERR, "rtprio() error: %m"); 297 else 298 ++priority_done; 299 } 300 # endif /* not RTP_SET */ 301 #endif /* HAVE_RTPRIO */ 302 #if defined(NTPD_PRIO) && NTPD_PRIO != 0 303 # ifdef HAVE_ATT_NICE 304 if (!priority_done) { 305 errno = 0; 306 if (-1 == nice (NTPD_PRIO) && errno != 0) 307 msyslog(LOG_ERR, "nice() error: %m"); 308 else 309 ++priority_done; 310 } 311 # endif /* HAVE_ATT_NICE */ 312 # ifdef HAVE_BSD_NICE 313 if (!priority_done) { 314 if (-1 == setpriority(PRIO_PROCESS, 0, NTPD_PRIO)) 315 msyslog(LOG_ERR, "setpriority() error: %m"); 316 else 317 ++priority_done; 318 } 319 # endif /* HAVE_BSD_NICE */ 320 #endif /* NTPD_PRIO && NTPD_PRIO != 0 */ 321 if (!priority_done) 322 msyslog(LOG_ERR, "set_process_priority: No way found to improve our priority"); 323 } 324 325 326 /* 327 * Main program. Initialize us, disconnect us from the tty if necessary, 328 * and loop waiting for I/O and/or timer expiries. 329 */ 330 int 331 ntpdmain( 332 int argc, 333 char *argv[] 334 ) 335 { 336 l_fp now; 337 char *cp; 338 #ifdef AUTOKEY 339 u_int n; 340 char hostname[MAXFILENAME]; 341 #endif /* AUTOKEY */ 342 struct recvbuf *rbuflist; 343 struct recvbuf *rbuf; 344 #ifdef _AIX /* HMS: ifdef SIGDANGER? */ 345 struct sigaction sa; 346 #endif 347 348 initializing = 1; /* mark that we are initializing */ 349 debug = 0; /* no debugging by default */ 350 nofork = 0; /* will fork by default */ 351 352 #ifdef HAVE_UMASK 353 { 354 mode_t uv; 355 356 uv = umask(0); 357 if(uv) 358 (void) umask(uv); 359 else 360 (void) umask(022); 361 } 362 #endif 363 364 #if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */ 365 { 366 uid_t uid; 367 368 uid = getuid(); 369 if (uid) 370 { 371 msyslog(LOG_ERR, "ntpd: must be run as root, not uid %ld", (long)uid); 372 exit(1); 373 } 374 } 375 #endif 376 377 #ifdef SYS_WINNT 378 /* Set the Event-ID message-file name. */ 379 if (!GetModuleFileName(NULL, szMsgPath, sizeof(szMsgPath))) { 380 msyslog(LOG_ERR, "GetModuleFileName(PGM_EXE_FILE) failed: %m\n"); 381 exit(1); 382 } 383 addSourceToRegistry("NTP", szMsgPath); 384 #endif 385 getstartup(argc, argv); /* startup configuration, may set debug */ 386 387 /* 388 * Initialize random generator and public key pair 389 */ 390 get_systime(&now); 391 SRANDOM((int)(now.l_i * now.l_uf)); 392 393 #if !defined(VMS) 394 # ifndef NODETACH 395 /* 396 * Detach us from the terminal. May need an #ifndef GIZMO. 397 */ 398 # ifdef DEBUG 399 if (!debug && !nofork) 400 # else /* DEBUG */ 401 if (!nofork) 402 # endif /* DEBUG */ 403 { 404 # ifndef SYS_WINNT 405 # ifdef HAVE_DAEMON 406 daemon(0, 0); 407 # else /* not HAVE_DAEMON */ 408 if (fork()) /* HMS: What about a -1? */ 409 exit(0); 410 411 { 412 #if !defined(F_CLOSEM) 413 u_long s; 414 int max_fd; 415 #endif /* not F_CLOSEM */ 416 417 /* 418 * From 'Writing Reliable AIX Daemons,' SG24-4946-00, 419 * by Eric Agar (saves us from doing 32767 system 420 * calls) 421 */ 422 #if defined(F_CLOSEM) 423 if (fcntl(0, F_CLOSEM, 0) == -1) 424 msyslog(LOG_ERR, "ntpd: failed to close open files(): %m"); 425 #else /* not F_CLOSEM */ 426 427 # if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX) 428 max_fd = sysconf(_SC_OPEN_MAX); 429 # else /* HAVE_SYSCONF && _SC_OPEN_MAX */ 430 max_fd = getdtablesize(); 431 # endif /* HAVE_SYSCONF && _SC_OPEN_MAX */ 432 for (s = 0; s < max_fd; s++) 433 (void) close((int)s); 434 #endif /* not F_CLOSEM */ 435 (void) open("/", 0); 436 (void) dup2(0, 1); 437 (void) dup2(0, 2); 438 #ifdef SYS_DOMAINOS 439 { 440 uid_$t puid; 441 status_$t st; 442 443 proc2_$who_am_i(&puid); 444 proc2_$make_server(&puid, &st); 445 } 446 #endif /* SYS_DOMAINOS */ 447 #if defined(HAVE_SETPGID) || defined(HAVE_SETSID) 448 # ifdef HAVE_SETSID 449 if (setsid() == (pid_t)-1) 450 msyslog(LOG_ERR, "ntpd: setsid(): %m"); 451 # else 452 if (setpgid(0, 0) == -1) 453 msyslog(LOG_ERR, "ntpd: setpgid(): %m"); 454 # endif 455 #else /* HAVE_SETPGID || HAVE_SETSID */ 456 { 457 # if defined(TIOCNOTTY) 458 int fid; 459 460 fid = open("/dev/tty", 2); 461 if (fid >= 0) 462 { 463 (void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0); 464 (void) close(fid); 465 } 466 # endif /* defined(TIOCNOTTY) */ 467 # ifdef HAVE_SETPGRP_0 468 (void) setpgrp(); 469 # else /* HAVE_SETPGRP_0 */ 470 (void) setpgrp(0, getpid()); 471 # endif /* HAVE_SETPGRP_0 */ 472 } 473 #endif /* HAVE_SETPGID || HAVE_SETSID */ 474 #ifdef _AIX 475 /* Don't get killed by low-on-memory signal. */ 476 sa.sa_handler = catch_danger; 477 sigemptyset(&sa.sa_mask); 478 sa.sa_flags = SA_RESTART; 479 480 (void) sigaction(SIGDANGER, &sa, NULL); 481 #endif /* _AIX */ 482 } 483 # endif /* not HAVE_DAEMON */ 484 # else /* SYS_WINNT */ 485 486 { 487 SERVICE_TABLE_ENTRY dispatchTable[] = { 488 { TEXT("NetworkTimeProtocol"), (LPSERVICE_MAIN_FUNCTION)service_main }, 489 { NULL, NULL } 490 }; 491 492 /* daemonize */ 493 if (!StartServiceCtrlDispatcher(dispatchTable)) 494 { 495 msyslog(LOG_ERR, "StartServiceCtrlDispatcher: %m"); 496 ExitProcess(2); 497 } 498 } 499 # endif /* SYS_WINNT */ 500 } 501 # endif /* NODETACH */ 502 # if defined(SYS_WINNT) && !defined(NODETACH) 503 else 504 service_main(argc, argv); 505 return 0; /* must return a value */ 506 } /* end main */ 507 508 /* 509 * If this runs as a service under NT, the main thread will block at 510 * StartServiceCtrlDispatcher() and another thread will be started by the 511 * Service Control Dispatcher which will begin execution at the routine 512 * specified in that call (viz. service_main) 513 */ 514 void 515 service_main( 516 DWORD argc, 517 LPTSTR *argv 518 ) 519 { 520 char *cp; 521 struct recvbuf *rbuflist; 522 struct recvbuf *rbuf; 523 #ifdef AUTOKEY 524 u_int n; 525 char hostname[MAXFILENAME]; 526 #endif /* AUTOKEY */ 527 if(!debug) 528 { 529 /* register our service control handler */ 530 if (!(sshStatusHandle = RegisterServiceCtrlHandler( TEXT("NetworkTimeProtocol"), 531 (LPHANDLER_FUNCTION)service_ctrl))) 532 { 533 msyslog(LOG_ERR, "RegisterServiceCtrlHandler failed: %m"); 534 return; 535 } 536 537 /* report pending status to Service Control Manager */ 538 ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 539 ssStatus.dwCurrentState = SERVICE_START_PENDING; 540 ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; 541 ssStatus.dwWin32ExitCode = NO_ERROR; 542 ssStatus.dwServiceSpecificExitCode = 0; 543 ssStatus.dwCheckPoint = 1; 544 ssStatus.dwWaitHint = 5000; 545 if (!SetServiceStatus(sshStatusHandle, &ssStatus)) 546 { 547 msyslog(LOG_ERR, "SetServiceStatus: %m"); 548 ssStatus.dwCurrentState = SERVICE_STOPPED; 549 SetServiceStatus(sshStatusHandle, &ssStatus); 550 return; 551 } 552 553 } /* debug */ 554 # endif /* defined(SYS_WINNT) && !defined(NODETACH) */ 555 #endif /* VMS */ 556 557 /* 558 * Logging. This may actually work on the gizmo board. Find a name 559 * to log with by using the basename of argv[0] 560 */ 561 cp = strrchr(argv[0], '/'); 562 if (cp == 0) 563 cp = argv[0]; 564 else 565 cp++; 566 567 debug = 0; /* will be immediately re-initialized 8-( */ 568 getstartup(argc, argv); /* startup configuration, catch logfile this time */ 569 570 #if !defined(SYS_WINNT) && !defined(VMS) 571 572 # ifndef LOG_DAEMON 573 openlog(cp, LOG_PID); 574 # else /* LOG_DAEMON */ 575 576 # ifndef LOG_NTP 577 # define LOG_NTP LOG_DAEMON 578 # endif 579 openlog(cp, LOG_PID | LOG_NDELAY, LOG_NTP); 580 # ifdef DEBUG 581 if (debug) 582 setlogmask(LOG_UPTO(LOG_DEBUG)); 583 else 584 # endif /* DEBUG */ 585 setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */ 586 # endif /* LOG_DAEMON */ 587 #endif /* !SYS_WINNT && !VMS */ 588 589 NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */ 590 msyslog(LOG_NOTICE, "%s", Version); 591 592 #ifdef SYS_WINNT 593 /* GMS 1/18/1997 594 * TODO: lock the process in memory using SetProcessWorkingSetSize() and VirtualLock() functions 595 * 596 process_handle = GetCurrentProcess(); 597 if (SetProcessWorkingSetSize(process_handle, 2097152 , 4194304 ) == TRUE) { 598 if (VirtualLock(0 , 4194304) == FALSE) 599 msyslog(LOG_ERR, "VirtualLock() failed: %m"); 600 } else { 601 msyslog(LOG_ERR, "SetProcessWorkingSetSize() failed: %m"); 602 } 603 */ 604 #endif /* SYS_WINNT */ 605 606 #ifdef SCO5_CLOCK 607 /* 608 * SCO OpenServer's system clock offers much more precise timekeeping 609 * on the base CPU than the other CPUs (for multiprocessor systems), 610 * so we must lock to the base CPU. 611 */ 612 { 613 int fd = open("/dev/at1", O_RDONLY); 614 if (fd >= 0) { 615 int zero = 0; 616 if (ioctl(fd, ACPU_LOCK, &zero) < 0) 617 msyslog(LOG_ERR, "cannot lock to base CPU: %m\n"); 618 close( fd ); 619 } /* else ... 620 * If we can't open the device, this probably just isn't 621 * a multiprocessor system, so we're A-OK. 622 */ 623 } 624 #endif 625 626 #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && defined(MCL_FUTURE) 627 /* 628 * lock the process into memory 629 */ 630 if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0) 631 msyslog(LOG_ERR, "mlockall(): %m"); 632 #else /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */ 633 # ifdef HAVE_PLOCK 634 # ifdef PROCLOCK 635 # ifdef _AIX 636 /* 637 * set the stack limit for AIX for plock(). 638 * see get_aix_stack for more info. 639 */ 640 if (ulimit(SET_STACKLIM, (get_aix_stack() - 8*4096)) < 0) 641 { 642 msyslog(LOG_ERR,"Cannot adjust stack limit for plock on AIX: %m"); 643 } 644 # endif /* _AIX */ 645 /* 646 * lock the process into memory 647 */ 648 if (plock(PROCLOCK) < 0) 649 msyslog(LOG_ERR, "plock(PROCLOCK): %m"); 650 # else /* not PROCLOCK */ 651 # ifdef TXTLOCK 652 /* 653 * Lock text into ram 654 */ 655 if (plock(TXTLOCK) < 0) 656 msyslog(LOG_ERR, "plock(TXTLOCK) error: %m"); 657 # else /* not TXTLOCK */ 658 msyslog(LOG_ERR, "plock() - don't know what to lock!"); 659 # endif /* not TXTLOCK */ 660 # endif /* not PROCLOCK */ 661 # endif /* HAVE_PLOCK */ 662 #endif /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */ 663 664 /* 665 * Set up signals we pay attention to locally. 666 */ 667 #ifdef SIGDIE1 668 (void) signal_no_reset(SIGDIE1, finish); 669 #endif /* SIGDIE1 */ 670 #ifdef SIGDIE2 671 (void) signal_no_reset(SIGDIE2, finish); 672 #endif /* SIGDIE2 */ 673 #ifdef SIGDIE3 674 (void) signal_no_reset(SIGDIE3, finish); 675 #endif /* SIGDIE3 */ 676 #ifdef SIGDIE4 677 (void) signal_no_reset(SIGDIE4, finish); 678 #endif /* SIGDIE4 */ 679 680 #ifdef SIGBUS 681 (void) signal_no_reset(SIGBUS, finish); 682 #endif /* SIGBUS */ 683 684 #if !defined(SYS_WINNT) && !defined(VMS) 685 # ifdef DEBUG 686 (void) signal_no_reset(MOREDEBUGSIG, moredebug); 687 (void) signal_no_reset(LESSDEBUGSIG, lessdebug); 688 # else 689 (void) signal_no_reset(MOREDEBUGSIG, no_debug); 690 (void) signal_no_reset(LESSDEBUGSIG, no_debug); 691 # endif /* DEBUG */ 692 #endif /* !SYS_WINNT && !VMS */ 693 694 /* 695 * Set up signals we should never pay attention to. 696 */ 697 #if defined SIGPIPE 698 (void) signal_no_reset(SIGPIPE, SIG_IGN); 699 #endif /* SIGPIPE */ 700 701 #if defined SYS_WINNT 702 if (!SetConsoleCtrlHandler(OnConsoleEvent, TRUE)) { 703 msyslog(LOG_ERR, "Can't set console control handler: %m"); 704 } 705 #endif 706 707 /* 708 * Call the init_ routines to initialize the data structures. 709 */ 710 #if defined (HAVE_IO_COMPLETION_PORT) 711 init_io_completion_port(); 712 init_winnt_time(); 713 #endif 714 init_auth(); 715 init_util(); 716 init_restrict(); 717 init_mon(); 718 init_timer(); 719 init_lib(); 720 init_random(); 721 init_request(); 722 init_control(); 723 init_peer(); 724 #ifdef REFCLOCK 725 init_refclock(); 726 #endif 727 set_process_priority(); 728 init_proto(); /* Call at high priority */ 729 init_io(); 730 init_loopfilter(); 731 mon_start(MON_ON); /* monitor on by default now */ 732 /* turn off in config if unwanted */ 733 734 /* 735 * Get configuration. This (including argument list parsing) is 736 * done in a separate module since this will definitely be different 737 * for the gizmo board. While at it, save the host name for later 738 * along with the length. The crypto needs this. 739 */ 740 #ifdef DEBUG 741 debug = 0; 742 #endif 743 getconfig(argc, argv); 744 #ifdef AUTOKEY 745 gethostname(hostname, MAXFILENAME); 746 n = strlen(hostname) + 1; 747 sys_hostname = emalloc(n); 748 memcpy(sys_hostname, hostname, n); 749 #ifdef PUBKEY 750 crypto_setup(); 751 #endif /* PUBKEY */ 752 #endif /* AUTOKEY */ 753 initializing = 0; 754 755 #if defined(SYS_WINNT) && !defined(NODETACH) 756 # if defined(DEBUG) 757 if(!debug) 758 { 759 # endif 760 /* report to the service control manager that the service is running */ 761 ssStatus.dwCurrentState = SERVICE_RUNNING; 762 ssStatus.dwWin32ExitCode = NO_ERROR; 763 if (!SetServiceStatus(sshStatusHandle, &ssStatus)) 764 { 765 msyslog(LOG_ERR, "SetServiceStatus: %m"); 766 if (ResolverThreadHandle != NULL) 767 CloseHandle(ResolverThreadHandle); 768 ssStatus.dwCurrentState = SERVICE_STOPPED; 769 SetServiceStatus(sshStatusHandle, &ssStatus); 770 return; 771 } 772 # if defined(DEBUG) 773 } 774 # endif 775 #endif 776 777 /* 778 * Report that we're up to any trappers 779 */ 780 report_event(EVNT_SYSRESTART, (struct peer *)0); 781 782 /* 783 * Use select() on all on all input fd's for unlimited 784 * time. select() will terminate on SIGALARM or on the 785 * reception of input. Using select() means we can't do 786 * robust signal handling and we get a potential race 787 * between checking for alarms and doing the select(). 788 * Mostly harmless, I think. 789 */ 790 /* On VMS, I suspect that select() can't be interrupted 791 * by a "signal" either, so I take the easy way out and 792 * have select() time out after one second. 793 * System clock updates really aren't time-critical, 794 * and - lacking a hardware reference clock - I have 795 * yet to learn about anything else that is. 796 */ 797 #if defined(HAVE_IO_COMPLETION_PORT) 798 WaitHandles[0] = CreateEvent(NULL, FALSE, FALSE, NULL); /* exit reques */ 799 WaitHandles[1] = get_timer_handle(); 800 WaitHandles[2] = get_io_event(); 801 802 for (;;) { 803 DWORD Index = WaitForMultipleObjectsEx(sizeof(WaitHandles)/sizeof(WaitHandles[0]), WaitHandles, FALSE, 1000, MWMO_ALERTABLE); 804 switch (Index) { 805 case WAIT_OBJECT_0 + 0 : /* exit request */ 806 exit(0); 807 break; 808 809 case WAIT_OBJECT_0 + 1 : /* timer */ 810 timer(); 811 break; 812 813 case WAIT_OBJECT_0 + 2 : /* Io event */ 814 # ifdef DEBUG 815 if ( debug > 3 ) 816 { 817 printf( "IoEvent occurred\n" ); 818 } 819 # endif 820 break; 821 822 # if 1 823 /* 824 * FIXME: According to the documentation for WaitForMultipleObjectsEx 825 * this is not possible. This may be a vestigial from when this was 826 * MsgWaitForMultipleObjects, maybe it should be removed? 827 */ 828 case WAIT_OBJECT_0 + 3 : /* windows message */ 829 { 830 MSG msg; 831 while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) 832 { 833 if ( msg.message == WM_QUIT ) 834 { 835 exit( 0 ); 836 } 837 DispatchMessage( &msg ); 838 } 839 } 840 break; 841 # endif 842 843 case WAIT_IO_COMPLETION : /* loop */ 844 case WAIT_TIMEOUT : 845 break; 846 847 } /* switch */ 848 rbuflist = getrecvbufs(); /* get received buffers */ 849 850 #else /* normal I/O */ 851 852 was_alarmed = 0; 853 rbuflist = (struct recvbuf *)0; 854 for (;;) 855 { 856 # if !defined(HAVE_SIGNALED_IO) 857 extern fd_set activefds; 858 extern int maxactivefd; 859 860 fd_set rdfdes; 861 int nfound; 862 # elif defined(HAVE_SIGNALED_IO) 863 block_io_and_alarm(); 864 # endif 865 866 rbuflist = getrecvbufs(); /* get received buffers */ 867 if (alarm_flag) /* alarmed? */ 868 { 869 was_alarmed = 1; 870 alarm_flag = 0; 871 } 872 873 if (!was_alarmed && rbuflist == (struct recvbuf *)0) 874 { 875 /* 876 * Nothing to do. Wait for something. 877 */ 878 # ifndef HAVE_SIGNALED_IO 879 rdfdes = activefds; 880 # if defined(VMS) || defined(SYS_VXWORKS) 881 /* make select() wake up after one second */ 882 { 883 struct timeval t1; 884 885 t1.tv_sec = 1; t1.tv_usec = 0; 886 nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0, 887 (fd_set *)0, &t1); 888 } 889 # else 890 nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0, 891 (fd_set *)0, (struct timeval *)0); 892 # endif /* VMS */ 893 if (nfound > 0) 894 { 895 l_fp ts; 896 897 get_systime(&ts); 898 899 (void)input_handler(&ts); 900 } 901 else if (nfound == -1 && errno != EINTR) 902 msyslog(LOG_ERR, "select() error: %m"); 903 else if (debug > 2) { 904 msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound); 905 } 906 # else /* HAVE_SIGNALED_IO */ 907 908 wait_for_signal(); 909 # endif /* HAVE_SIGNALED_IO */ 910 if (alarm_flag) /* alarmed? */ 911 { 912 was_alarmed = 1; 913 alarm_flag = 0; 914 } 915 rbuflist = getrecvbufs(); /* get received buffers */ 916 } 917 # ifdef HAVE_SIGNALED_IO 918 unblock_io_and_alarm(); 919 # endif /* HAVE_SIGNALED_IO */ 920 921 /* 922 * Out here, signals are unblocked. Call timer routine 923 * to process expiry. 924 */ 925 if (was_alarmed) 926 { 927 timer(); 928 was_alarmed = 0; 929 } 930 931 #endif /* HAVE_IO_COMPLETION_PORT */ 932 /* 933 * Call the data procedure to handle each received 934 * packet. 935 */ 936 while (rbuflist != (struct recvbuf *)0) 937 { 938 rbuf = rbuflist; 939 rbuflist = rbuf->next; 940 (rbuf->receiver)(rbuf); 941 freerecvbuf(rbuf); 942 } 943 #if defined DEBUG && defined SYS_WINNT 944 if (debug > 4) 945 printf("getrecvbufs: %ld handler interrupts, %ld frames\n", 946 handler_calls, handler_pkts); 947 #endif 948 949 /* 950 * Go around again 951 */ 952 } 953 exit(1); /* unreachable */ 954 return 1; /* DEC OSF cc braindamage */ 955 } 956 957 958 #ifdef SIGDIE2 959 /* 960 * finish - exit gracefully 961 */ 962 static RETSIGTYPE 963 finish( 964 int sig 965 ) 966 { 967 968 msyslog(LOG_NOTICE, "ntpd exiting on signal %d", sig); 969 970 switch (sig) 971 { 972 # ifdef SIGBUS 973 case SIGBUS: 974 printf("\nfinish(SIGBUS)\n"); 975 exit(0); 976 # endif 977 case 0: /* Should never happen... */ 978 return; 979 default: 980 exit(0); 981 } 982 } 983 #endif /* SIGDIE2 */ 984 985 986 #ifdef DEBUG 987 /* 988 * moredebug - increase debugging verbosity 989 */ 990 static RETSIGTYPE 991 moredebug( 992 int sig 993 ) 994 { 995 int saved_errno = errno; 996 997 if (debug < 255) 998 { 999 debug++; 1000 msyslog(LOG_DEBUG, "debug raised to %d", debug); 1001 } 1002 errno = saved_errno; 1003 } 1004 1005 /* 1006 * lessdebug - decrease debugging verbosity 1007 */ 1008 static RETSIGTYPE 1009 lessdebug( 1010 int sig 1011 ) 1012 { 1013 int saved_errno = errno; 1014 1015 if (debug > 0) 1016 { 1017 debug--; 1018 msyslog(LOG_DEBUG, "debug lowered to %d", debug); 1019 } 1020 errno = saved_errno; 1021 } 1022 #else /* not DEBUG */ 1023 /* 1024 * no_debug - We don't do the debug here. 1025 */ 1026 static RETSIGTYPE 1027 no_debug( 1028 int sig 1029 ) 1030 { 1031 int saved_errno = errno; 1032 1033 msyslog(LOG_DEBUG, "ntpd not compiled for debugging (signal %d)", sig); 1034 errno = saved_errno; 1035 } 1036 #endif /* not DEBUG */ 1037 1038 #ifdef SYS_WINNT 1039 /* service_ctrl - control handler for NTP service 1040 * signals the service_main routine of start/stop requests 1041 * from the control panel or other applications making 1042 * win32API calls 1043 */ 1044 void 1045 service_ctrl( 1046 DWORD dwCtrlCode 1047 ) 1048 { 1049 DWORD dwState = SERVICE_RUNNING; 1050 1051 /* Handle the requested control code */ 1052 switch(dwCtrlCode) 1053 { 1054 case SERVICE_CONTROL_PAUSE: 1055 /* see no reason to support this */ 1056 break; 1057 1058 case SERVICE_CONTROL_CONTINUE: 1059 /* see no reason to support this */ 1060 break; 1061 1062 case SERVICE_CONTROL_STOP: 1063 dwState = SERVICE_STOP_PENDING; 1064 /* 1065 * Report the status, specifying the checkpoint and waithint, 1066 * before setting the termination event. 1067 */ 1068 ssStatus.dwCurrentState = dwState; 1069 ssStatus.dwWin32ExitCode = NO_ERROR; 1070 ssStatus.dwWaitHint = 3000; 1071 if (!SetServiceStatus(sshStatusHandle, &ssStatus)) 1072 { 1073 msyslog(LOG_ERR, "SetServiceStatus: %m"); 1074 } 1075 if (WaitHandles[0] != NULL) { 1076 SetEvent(WaitHandles[0]); 1077 } 1078 return; 1079 1080 case SERVICE_CONTROL_INTERROGATE: 1081 /* Update the service status */ 1082 break; 1083 1084 default: 1085 /* invalid control code */ 1086 break; 1087 1088 } 1089 1090 ssStatus.dwCurrentState = dwState; 1091 ssStatus.dwWin32ExitCode = NO_ERROR; 1092 if (!SetServiceStatus(sshStatusHandle, &ssStatus)) 1093 { 1094 msyslog(LOG_ERR, "SetServiceStatus: %m"); 1095 } 1096 } 1097 1098 static BOOL WINAPI 1099 OnConsoleEvent( 1100 DWORD dwCtrlType 1101 ) 1102 { 1103 switch (dwCtrlType) { 1104 case CTRL_BREAK_EVENT : 1105 if (debug > 0) { 1106 debug <<= 1; 1107 } 1108 else { 1109 debug = 1; 1110 } 1111 if (debug > 8) { 1112 debug = 0; 1113 } 1114 printf("debug level %d\n", debug); 1115 break ; 1116 1117 case CTRL_C_EVENT : 1118 case CTRL_CLOSE_EVENT : 1119 case CTRL_SHUTDOWN_EVENT : 1120 if (WaitHandles[0] != NULL) { 1121 SetEvent(WaitHandles[0]); 1122 } 1123 break; 1124 1125 default : 1126 return FALSE; 1127 1128 1129 } 1130 return TRUE;; 1131 } 1132 1133 1134 /* 1135 * NT version of exit() - all calls to exit() should be routed to 1136 * this function. 1137 */ 1138 void 1139 service_exit( 1140 int status 1141 ) 1142 { 1143 if (!debug) { /* did not become a service, simply exit */ 1144 /* service mode, need to have the service_main routine 1145 * register with the service control manager that the 1146 * service has stopped running, before exiting 1147 */ 1148 ssStatus.dwCurrentState = SERVICE_STOPPED; 1149 SetServiceStatus(sshStatusHandle, &ssStatus); 1150 1151 } 1152 uninit_io_completion_port(); 1153 reset_winnt_time(); 1154 1155 # if defined _MSC_VER 1156 _CrtDumpMemoryLeaks(); 1157 # endif 1158 #undef exit 1159 exit(status); 1160 } 1161 1162 #endif /* SYS_WINNT */ 1163