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