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