Annotation of embedaddon/ntp/ntpd/ntpd.c, revision 1.1.1.1
1.1 misho 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: #include <ntp_random.h>
14:
15: #include "ntp_syslog.h"
16: #include "isc/assertions.h"
17: #include "isc/error.h"
18: #include "isc/strerror.h"
19: #include "isc/formatcheck.h"
20:
21: #ifdef SIM
22: # include "ntpsim.h"
23: #endif
24:
25: #include "ntp_libopts.h"
26: #include "ntpd-opts.h"
27:
28: #ifdef HAVE_UNISTD_H
29: # include <unistd.h>
30: #endif
31: #ifdef HAVE_SYS_STAT_H
32: # include <sys/stat.h>
33: #endif
34: #include <stdio.h>
35: #if !defined(VMS) /*wjm*/
36: # ifdef HAVE_SYS_PARAM_H
37: # include <sys/param.h>
38: # endif
39: #endif /* VMS */
40: #ifdef HAVE_SYS_SIGNAL_H
41: # include <sys/signal.h>
42: #else
43: # include <signal.h>
44: #endif
45: #ifdef HAVE_SYS_IOCTL_H
46: # include <sys/ioctl.h>
47: #endif /* HAVE_SYS_IOCTL_H */
48: #ifdef HAVE_SYS_RESOURCE_H
49: # include <sys/resource.h>
50: #endif /* HAVE_SYS_RESOURCE_H */
51: #if defined(HAVE_RTPRIO)
52: # ifdef HAVE_SYS_RESOURCE_H
53: # include <sys/resource.h>
54: # endif
55: # ifdef HAVE_SYS_LOCK_H
56: # include <sys/lock.h>
57: # endif
58: # include <sys/rtprio.h>
59: #else
60: # ifdef HAVE_PLOCK
61: # ifdef HAVE_SYS_LOCK_H
62: # include <sys/lock.h>
63: # endif
64: # endif
65: #endif
66: #if defined(HAVE_SCHED_SETSCHEDULER)
67: # ifdef HAVE_SCHED_H
68: # include <sched.h>
69: # else
70: # ifdef HAVE_SYS_SCHED_H
71: # include <sys/sched.h>
72: # endif
73: # endif
74: #endif
75: #if defined(HAVE_SYS_MMAN_H)
76: # include <sys/mman.h>
77: #endif
78:
79: #ifdef HAVE_TERMIOS_H
80: # include <termios.h>
81: #endif
82:
83: #ifdef SYS_DOMAINOS
84: # include <apollo/base.h>
85: #endif /* SYS_DOMAINOS */
86:
87: #include "recvbuff.h"
88: #include "ntp_cmdargs.h"
89:
90: #if 0 /* HMS: I don't think we need this. 961223 */
91: #ifdef LOCK_PROCESS
92: # ifdef SYS_SOLARIS
93: # include <sys/mman.h>
94: # else
95: # include <sys/lock.h>
96: # endif
97: #endif
98: #endif
99:
100: #ifdef _AIX
101: # include <ulimit.h>
102: #endif /* _AIX */
103:
104: #ifdef SCO5_CLOCK
105: # include <sys/ci/ciioctl.h>
106: #endif
107:
108: #ifdef HAVE_DROPROOT
109: # include <ctype.h>
110: # include <grp.h>
111: # include <pwd.h>
112: #ifdef HAVE_LINUX_CAPABILITIES
113: # include <sys/capability.h>
114: # include <sys/prctl.h>
115: #endif
116: #endif
117:
118: /*
119: * Signals we catch for debugging. If not debugging we ignore them.
120: */
121: #define MOREDEBUGSIG SIGUSR1
122: #define LESSDEBUGSIG SIGUSR2
123:
124: /*
125: * Signals which terminate us gracefully.
126: */
127: #ifndef SYS_WINNT
128: # define SIGDIE1 SIGHUP
129: # define SIGDIE3 SIGQUIT
130: # define SIGDIE2 SIGINT
131: # define SIGDIE4 SIGTERM
132: #endif /* SYS_WINNT */
133:
134: #ifdef HAVE_DNSREGISTRATION
135: #include <dns_sd.h>
136: DNSServiceRef mdns;
137: #endif
138:
139: /*
140: * Scheduling priority we run at
141: */
142: #define NTPD_PRIO (-12)
143:
144: int priority_done = 2; /* 0 - Set priority */
145: /* 1 - priority is OK where it is */
146: /* 2 - Don't set priority */
147: /* 1 and 2 are pretty much the same */
148:
149: #ifdef DEBUG
150: /*
151: * Debugging flag
152: */
153: volatile int debug = 0; /* No debugging by default */
154: #endif
155:
156: int listen_to_virtual_ips = 1;
157: const char *specific_interface = NULL; /* interface name or IP address to bind to */
158:
159: /*
160: * No-fork flag. If set, we do not become a background daemon.
161: */
162: int nofork = 0; /* Fork by default */
163:
164: #ifdef HAVE_DNSREGISTRATION
165: /*
166: * mDNS registration flag. If set, we attempt to register with the mDNS system, but only
167: * after we have synched the first time. If the attempt fails, then try again once per
168: * minute for up to 5 times. After all, we may be starting before mDNS.
169: */
170: int mdnsreg = 1;
171: int mdnstries = 5;
172: #endif /* HAVE_DNSREGISTRATION */
173:
174: #ifdef HAVE_DROPROOT
175: int droproot = 0;
176: char *user = NULL; /* User to switch to */
177: char *group = NULL; /* group to switch to */
178: const char *chrootdir = NULL; /* directory to chroot to */
179: int sw_uid;
180: int sw_gid;
181: char *endp;
182: struct group *gr;
183: struct passwd *pw;
184: #endif /* HAVE_DROPROOT */
185:
186: /*
187: * Initializing flag. All async routines watch this and only do their
188: * thing when it is clear.
189: */
190: int initializing;
191:
192: /*
193: * Version declaration
194: */
195: extern const char *Version;
196:
197: char const *progname;
198:
199: int was_alarmed;
200:
201: #ifdef DECL_SYSCALL
202: /*
203: * We put this here, since the argument profile is syscall-specific
204: */
205: extern int syscall (int, ...);
206: #endif /* DECL_SYSCALL */
207:
208:
209: #ifdef SIGDIE2
210: static RETSIGTYPE finish (int);
211: #endif /* SIGDIE2 */
212:
213: #ifdef DEBUG
214: #ifndef SYS_WINNT
215: static RETSIGTYPE moredebug (int);
216: static RETSIGTYPE lessdebug (int);
217: #endif
218: #else /* not DEBUG */
219: static RETSIGTYPE no_debug (int);
220: #endif /* not DEBUG */
221:
222: int ntpdmain (int, char **);
223: static void set_process_priority (void);
224: void init_logging (char const *, int);
225: void setup_logfile (void);
226: static void process_commandline_opts(int *, char ***);
227:
228: static void assertion_failed (const char *file, int line,
229: isc_assertiontype_t type, const char *cond);
230: static void library_fatal_error (const char *file, int line,
231: const char *format, va_list args) ISC_FORMAT_PRINTF(3, 0);
232: static void library_unexpected_error(const char *file, int line,
233: const char *format, va_list args) ISC_FORMAT_PRINTF(3, 0);
234:
235:
236: /*
237: * Initialize the logging
238: */
239: void
240: init_logging(
241: char const *name,
242: int log_version
243: )
244: {
245: const char *cp;
246:
247: /*
248: * Logging. This may actually work on the gizmo board. Find a name
249: * to log with by using the basename
250: */
251: cp = strrchr(name, '/');
252: if (cp == 0)
253: cp = name;
254: else
255: cp++;
256:
257: #if !defined(VMS)
258:
259: # ifndef LOG_DAEMON
260: openlog(cp, LOG_PID);
261: # else /* LOG_DAEMON */
262:
263: # ifndef LOG_NTP
264: # define LOG_NTP LOG_DAEMON
265: # endif
266: openlog(cp, LOG_PID | LOG_NDELAY, LOG_NTP);
267: # ifdef DEBUG
268: if (debug)
269: setlogmask(LOG_UPTO(LOG_DEBUG));
270: else
271: # endif /* DEBUG */
272: setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
273: # endif /* LOG_DAEMON */
274: #endif /* !VMS */
275:
276: if (log_version)
277: NLOG(NLOG_SYSINFO) /* 'if' clause for syslog */
278: msyslog(LOG_NOTICE, "%s", Version);
279: }
280:
281:
282: /*
283: * Redirect logging to a file if requested with -l.
284: * The ntp.conf logfile directive does not use this code, see
285: * config_vars() in ntp_config.c.
286: */
287: void
288: setup_logfile(
289: void
290: )
291: {
292: if (HAVE_OPT( LOGFILE )) {
293: const char *my_optarg = OPT_ARG( LOGFILE );
294: FILE *new_file;
295:
296: if(strcmp(my_optarg, "stderr") == 0)
297: new_file = stderr;
298: else if(strcmp(my_optarg, "stdout") == 0)
299: new_file = stdout;
300: else
301: new_file = fopen(my_optarg, "a");
302: if (new_file != NULL) {
303: NLOG(NLOG_SYSINFO)
304: msyslog(LOG_NOTICE, "logging to file %s", my_optarg);
305: if (syslog_file != NULL &&
306: fileno(syslog_file) != fileno(new_file))
307: (void)fclose(syslog_file);
308:
309: syslog_file = new_file;
310: syslogit = 0;
311: }
312: else
313: msyslog(LOG_ERR,
314: "Cannot open log file %s",
315: my_optarg);
316: }
317: }
318:
319:
320: static void
321: process_commandline_opts(
322: int *pargc,
323: char ***pargv
324: )
325: {
326: int optct;
327:
328: optct = ntpOptionProcess(&ntpdOptions, *pargc, *pargv);
329: *pargc -= optct;
330: *pargv += optct;
331: }
332:
333:
334: #ifdef SIM
335: int
336: main(
337: int argc,
338: char *argv[]
339: )
340: {
341: process_commandline_opts(&argc, &argv);
342:
343: return ntpsim(argc, argv);
344: }
345: #else /* SIM */
346: #ifdef NO_MAIN_ALLOWED
347: CALL(ntpd,"ntpd",ntpdmain);
348: #else
349: #ifndef SYS_WINNT
350: int
351: main(
352: int argc,
353: char *argv[]
354: )
355: {
356: return ntpdmain(argc, argv);
357: }
358: #endif /* SYS_WINNT */
359: #endif /* NO_MAIN_ALLOWED */
360: #endif /* SIM */
361:
362: #ifdef _AIX
363: /*
364: * OK. AIX is different than solaris in how it implements plock().
365: * If you do NOT adjust the stack limit, you will get the MAXIMUM
366: * stack size allocated and PINNED with you program. To check the
367: * value, use ulimit -a.
368: *
369: * To fix this, we create an automatic variable and set our stack limit
370: * to that PLUS 32KB of extra space (we need some headroom).
371: *
372: * This subroutine gets the stack address.
373: *
374: * Grover Davidson and Matt Ladendorf
375: *
376: */
377: static char *
378: get_aix_stack(void)
379: {
380: char ch;
381: return (&ch);
382: }
383:
384: /*
385: * Signal handler for SIGDANGER.
386: */
387: static void
388: catch_danger(int signo)
389: {
390: msyslog(LOG_INFO, "ntpd: setpgid(): %m");
391: /* Make the system believe we'll free something, but don't do it! */
392: return;
393: }
394: #endif /* _AIX */
395:
396: /*
397: * Set the process priority
398: */
399: static void
400: set_process_priority(void)
401: {
402:
403: #ifdef DEBUG
404: if (debug > 1)
405: msyslog(LOG_DEBUG, "set_process_priority: %s: priority_done is <%d>",
406: ((priority_done)
407: ? "Leave priority alone"
408: : "Attempt to set priority"
409: ),
410: priority_done);
411: #endif /* DEBUG */
412:
413: #if defined(HAVE_SCHED_SETSCHEDULER)
414: if (!priority_done) {
415: extern int config_priority_override, config_priority;
416: int pmax, pmin;
417: struct sched_param sched;
418:
419: pmax = sched_get_priority_max(SCHED_FIFO);
420: sched.sched_priority = pmax;
421: if ( config_priority_override ) {
422: pmin = sched_get_priority_min(SCHED_FIFO);
423: if ( config_priority > pmax )
424: sched.sched_priority = pmax;
425: else if ( config_priority < pmin )
426: sched.sched_priority = pmin;
427: else
428: sched.sched_priority = config_priority;
429: }
430: if ( sched_setscheduler(0, SCHED_FIFO, &sched) == -1 )
431: msyslog(LOG_ERR, "sched_setscheduler(): %m");
432: else
433: ++priority_done;
434: }
435: #endif /* HAVE_SCHED_SETSCHEDULER */
436: #if defined(HAVE_RTPRIO)
437: # ifdef RTP_SET
438: if (!priority_done) {
439: struct rtprio srtp;
440:
441: srtp.type = RTP_PRIO_REALTIME; /* was: RTP_PRIO_NORMAL */
442: srtp.prio = 0; /* 0 (hi) -> RTP_PRIO_MAX (31,lo) */
443:
444: if (rtprio(RTP_SET, getpid(), &srtp) < 0)
445: msyslog(LOG_ERR, "rtprio() error: %m");
446: else
447: ++priority_done;
448: }
449: # else /* not RTP_SET */
450: if (!priority_done) {
451: if (rtprio(0, 120) < 0)
452: msyslog(LOG_ERR, "rtprio() error: %m");
453: else
454: ++priority_done;
455: }
456: # endif /* not RTP_SET */
457: #endif /* HAVE_RTPRIO */
458: #if defined(NTPD_PRIO) && NTPD_PRIO != 0
459: # ifdef HAVE_ATT_NICE
460: if (!priority_done) {
461: errno = 0;
462: if (-1 == nice (NTPD_PRIO) && errno != 0)
463: msyslog(LOG_ERR, "nice() error: %m");
464: else
465: ++priority_done;
466: }
467: # endif /* HAVE_ATT_NICE */
468: # ifdef HAVE_BSD_NICE
469: if (!priority_done) {
470: if (-1 == setpriority(PRIO_PROCESS, 0, NTPD_PRIO))
471: msyslog(LOG_ERR, "setpriority() error: %m");
472: else
473: ++priority_done;
474: }
475: # endif /* HAVE_BSD_NICE */
476: #endif /* NTPD_PRIO && NTPD_PRIO != 0 */
477: if (!priority_done)
478: msyslog(LOG_ERR, "set_process_priority: No way found to improve our priority");
479: }
480:
481:
482: /*
483: * Main program. Initialize us, disconnect us from the tty if necessary,
484: * and loop waiting for I/O and/or timer expiries.
485: */
486: int
487: ntpdmain(
488: int argc,
489: char *argv[]
490: )
491: {
492: l_fp now;
493: struct recvbuf *rbuf;
494: #ifdef _AIX /* HMS: ifdef SIGDANGER? */
495: struct sigaction sa;
496: #endif
497:
498: progname = argv[0];
499: initializing = 1; /* mark that we are initializing */
500: process_commandline_opts(&argc, &argv);
501: init_logging(progname, 1); /* Open the log file */
502:
503: #ifdef HAVE_UMASK
504: {
505: mode_t uv;
506:
507: uv = umask(0);
508: if(uv)
509: (void) umask(uv);
510: else
511: (void) umask(022);
512: }
513: #endif
514:
515: #if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */
516: {
517: uid_t uid;
518:
519: uid = getuid();
520: if (uid && !HAVE_OPT( SAVECONFIGQUIT )) {
521: msyslog(LOG_ERR, "ntpd: must be run as root, not uid %ld", (long)uid);
522: printf("must be run as root, not uid %ld\n", (long)uid);
523: exit(1);
524: }
525: }
526: #endif
527:
528: /* getstartup(argc, argv); / * startup configuration, may set debug */
529:
530: #ifdef DEBUG
531: debug = DESC(DEBUG_LEVEL).optOccCt;
532: DPRINTF(1, ("%s\n", Version));
533: #endif
534:
535: /* honor -l/--logfile option to log to a file */
536: setup_logfile();
537:
538: /*
539: * Enable the Multi-Media Timer for Windows?
540: */
541: #ifdef SYS_WINNT
542: if (HAVE_OPT( MODIFYMMTIMER ))
543: set_mm_timer(MM_TIMER_HIRES);
544: #endif
545:
546: if (HAVE_OPT( NOFORK ) || HAVE_OPT( QUIT )
547: #ifdef DEBUG
548: || debug
549: #endif
550: || HAVE_OPT( SAVECONFIGQUIT ))
551: nofork = 1;
552:
553: if (HAVE_OPT( NOVIRTUALIPS ))
554: listen_to_virtual_ips = 0;
555:
556: /*
557: * --interface, listen on specified interfaces
558: */
559: if (HAVE_OPT( INTERFACE )) {
560: int ifacect = STACKCT_OPT( INTERFACE );
561: const char** ifaces = STACKLST_OPT( INTERFACE );
562: sockaddr_u addr;
563:
564: while (ifacect-- > 0) {
565: add_nic_rule(
566: is_ip_address(*ifaces, &addr)
567: ? MATCH_IFADDR
568: : MATCH_IFNAME,
569: *ifaces, -1, ACTION_LISTEN);
570: ifaces++;
571: }
572: }
573:
574: if (HAVE_OPT( NICE ))
575: priority_done = 0;
576:
577: #if defined(HAVE_SCHED_SETSCHEDULER)
578: if (HAVE_OPT( PRIORITY )) {
579: config_priority = OPT_VALUE_PRIORITY;
580: config_priority_override = 1;
581: priority_done = 0;
582: }
583: #endif
584:
585: #ifdef SYS_WINNT
586: /*
587: * Start interpolation thread, must occur before first
588: * get_systime()
589: */
590: init_winnt_time();
591: #endif
592: /*
593: * Initialize random generator and public key pair
594: */
595: get_systime(&now);
596:
597: ntp_srandom((int)(now.l_i * now.l_uf));
598:
599: #if !defined(VMS)
600: # ifndef NODETACH
601: /*
602: * Detach us from the terminal. May need an #ifndef GIZMO.
603: */
604: if (!nofork) {
605:
606: /*
607: * Install trap handlers to log errors and assertion
608: * failures. Default handlers print to stderr which
609: * doesn't work if detached.
610: */
611: isc_assertion_setcallback(assertion_failed);
612: isc_error_setfatal(library_fatal_error);
613: isc_error_setunexpected(library_unexpected_error);
614:
615: # ifndef SYS_WINNT
616: # ifdef HAVE_DAEMON
617: daemon(0, 0);
618: # else /* not HAVE_DAEMON */
619: if (fork()) /* HMS: What about a -1? */
620: exit(0);
621:
622: {
623: #if !defined(F_CLOSEM)
624: u_long s;
625: int max_fd;
626: #endif /* !FCLOSEM */
627: if (syslog_file != NULL) {
628: fclose(syslog_file);
629: syslog_file = NULL;
630: }
631: #if defined(F_CLOSEM)
632: /*
633: * From 'Writing Reliable AIX Daemons,' SG24-4946-00,
634: * by Eric Agar (saves us from doing 32767 system
635: * calls)
636: */
637: if (fcntl(0, F_CLOSEM, 0) == -1)
638: msyslog(LOG_ERR, "ntpd: failed to close open files(): %m");
639: #else /* not F_CLOSEM */
640:
641: # if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
642: max_fd = sysconf(_SC_OPEN_MAX);
643: # else /* HAVE_SYSCONF && _SC_OPEN_MAX */
644: max_fd = getdtablesize();
645: # endif /* HAVE_SYSCONF && _SC_OPEN_MAX */
646: for (s = 0; s < max_fd; s++)
647: (void) close((int)s);
648: #endif /* not F_CLOSEM */
649: (void) open("/", 0);
650: (void) dup2(0, 1);
651: (void) dup2(0, 2);
652:
653: init_logging(progname, 0);
654: /* we lost our logfile (if any) daemonizing */
655: setup_logfile();
656:
657: #ifdef SYS_DOMAINOS
658: {
659: uid_$t puid;
660: status_$t st;
661:
662: proc2_$who_am_i(&puid);
663: proc2_$make_server(&puid, &st);
664: }
665: #endif /* SYS_DOMAINOS */
666: #if defined(HAVE_SETPGID) || defined(HAVE_SETSID)
667: # ifdef HAVE_SETSID
668: if (setsid() == (pid_t)-1)
669: msyslog(LOG_ERR, "ntpd: setsid(): %m");
670: # else
671: if (setpgid(0, 0) == -1)
672: msyslog(LOG_ERR, "ntpd: setpgid(): %m");
673: # endif
674: #else /* HAVE_SETPGID || HAVE_SETSID */
675: {
676: # if defined(TIOCNOTTY)
677: int fid;
678:
679: fid = open("/dev/tty", 2);
680: if (fid >= 0)
681: {
682: (void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0);
683: (void) close(fid);
684: }
685: # endif /* defined(TIOCNOTTY) */
686: # ifdef HAVE_SETPGRP_0
687: (void) setpgrp();
688: # else /* HAVE_SETPGRP_0 */
689: (void) setpgrp(0, getpid());
690: # endif /* HAVE_SETPGRP_0 */
691: }
692: #endif /* HAVE_SETPGID || HAVE_SETSID */
693: #ifdef _AIX
694: /* Don't get killed by low-on-memory signal. */
695: sa.sa_handler = catch_danger;
696: sigemptyset(&sa.sa_mask);
697: sa.sa_flags = SA_RESTART;
698:
699: (void) sigaction(SIGDANGER, &sa, NULL);
700: #endif /* _AIX */
701: }
702: # endif /* not HAVE_DAEMON */
703: # endif /* SYS_WINNT */
704: }
705: # endif /* NODETACH */
706: #endif /* VMS */
707:
708: #ifdef SCO5_CLOCK
709: /*
710: * SCO OpenServer's system clock offers much more precise timekeeping
711: * on the base CPU than the other CPUs (for multiprocessor systems),
712: * so we must lock to the base CPU.
713: */
714: {
715: int fd = open("/dev/at1", O_RDONLY);
716: if (fd >= 0) {
717: int zero = 0;
718: if (ioctl(fd, ACPU_LOCK, &zero) < 0)
719: msyslog(LOG_ERR, "cannot lock to base CPU: %m");
720: close( fd );
721: } /* else ...
722: * If we can't open the device, this probably just isn't
723: * a multiprocessor system, so we're A-OK.
724: */
725: }
726: #endif
727:
728: #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && defined(MCL_FUTURE)
729: # ifdef HAVE_SETRLIMIT
730: /*
731: * Set the stack limit to something smaller, so that we don't lock a lot
732: * of unused stack memory.
733: */
734: {
735: struct rlimit rl;
736:
737: /* HMS: must make the rlim_cur amount configurable */
738: if (getrlimit(RLIMIT_STACK, &rl) != -1
739: && (rl.rlim_cur = 50 * 4096) < rl.rlim_max)
740: {
741: if (setrlimit(RLIMIT_STACK, &rl) == -1)
742: {
743: msyslog(LOG_ERR,
744: "Cannot adjust stack limit for mlockall: %m");
745: }
746: }
747: # ifdef RLIMIT_MEMLOCK
748: /*
749: * The default RLIMIT_MEMLOCK is very low on Linux systems.
750: * Unless we increase this limit malloc calls are likely to
751: * fail if we drop root privlege. To be useful the value
752: * has to be larger than the largest ntpd resident set size.
753: */
754: rl.rlim_cur = rl.rlim_max = 32*1024*1024;
755: if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) {
756: msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
757: }
758: # endif /* RLIMIT_MEMLOCK */
759: }
760: # endif /* HAVE_SETRLIMIT */
761: /*
762: * lock the process into memory
763: */
764: if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0)
765: msyslog(LOG_ERR, "mlockall(): %m");
766: #else /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */
767: # ifdef HAVE_PLOCK
768: # ifdef PROCLOCK
769: # ifdef _AIX
770: /*
771: * set the stack limit for AIX for plock().
772: * see get_aix_stack() for more info.
773: */
774: if (ulimit(SET_STACKLIM, (get_aix_stack() - 8*4096)) < 0)
775: {
776: msyslog(LOG_ERR,"Cannot adjust stack limit for plock on AIX: %m");
777: }
778: # endif /* _AIX */
779: /*
780: * lock the process into memory
781: */
782: if (plock(PROCLOCK) < 0)
783: msyslog(LOG_ERR, "plock(PROCLOCK): %m");
784: # else /* not PROCLOCK */
785: # ifdef TXTLOCK
786: /*
787: * Lock text into ram
788: */
789: if (plock(TXTLOCK) < 0)
790: msyslog(LOG_ERR, "plock(TXTLOCK) error: %m");
791: # else /* not TXTLOCK */
792: msyslog(LOG_ERR, "plock() - don't know what to lock!");
793: # endif /* not TXTLOCK */
794: # endif /* not PROCLOCK */
795: # endif /* HAVE_PLOCK */
796: #endif /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */
797:
798: /*
799: * Set up signals we pay attention to locally.
800: */
801: #ifdef SIGDIE1
802: (void) signal_no_reset(SIGDIE1, finish);
803: #endif /* SIGDIE1 */
804: #ifdef SIGDIE2
805: (void) signal_no_reset(SIGDIE2, finish);
806: #endif /* SIGDIE2 */
807: #ifdef SIGDIE3
808: (void) signal_no_reset(SIGDIE3, finish);
809: #endif /* SIGDIE3 */
810: #ifdef SIGDIE4
811: (void) signal_no_reset(SIGDIE4, finish);
812: #endif /* SIGDIE4 */
813:
814: #ifdef SIGBUS
815: (void) signal_no_reset(SIGBUS, finish);
816: #endif /* SIGBUS */
817:
818: #if !defined(SYS_WINNT) && !defined(VMS)
819: # ifdef DEBUG
820: (void) signal_no_reset(MOREDEBUGSIG, moredebug);
821: (void) signal_no_reset(LESSDEBUGSIG, lessdebug);
822: # else
823: (void) signal_no_reset(MOREDEBUGSIG, no_debug);
824: (void) signal_no_reset(LESSDEBUGSIG, no_debug);
825: # endif /* DEBUG */
826: #endif /* !SYS_WINNT && !VMS */
827:
828: /*
829: * Set up signals we should never pay attention to.
830: */
831: #if defined SIGPIPE
832: (void) signal_no_reset(SIGPIPE, SIG_IGN);
833: #endif /* SIGPIPE */
834:
835: /*
836: * Call the init_ routines to initialize the data structures.
837: *
838: * Exactly what command-line options are we expecting here?
839: */
840: init_auth();
841: init_util();
842: init_restrict();
843: init_mon();
844: init_timer();
845: init_lib();
846: init_request();
847: init_control();
848: init_peer();
849: #ifdef REFCLOCK
850: init_refclock();
851: #endif
852: set_process_priority();
853: init_proto(); /* Call at high priority */
854: init_io();
855: init_loopfilter();
856: mon_start(MON_ON); /* monitor on by default now */
857: /* turn off in config if unwanted */
858:
859: /*
860: * Get the configuration. This is done in a separate module
861: * since this will definitely be different for the gizmo board.
862: */
863: getconfig(argc, argv);
864: report_event(EVNT_SYSRESTART, NULL, NULL);
865: loop_config(LOOP_DRIFTCOMP, old_drift);
866: initializing = 0;
867:
868: #ifdef HAVE_DROPROOT
869: if( droproot ) {
870: /* Drop super-user privileges and chroot now if the OS supports this */
871:
872: #ifdef HAVE_LINUX_CAPABILITIES
873: /* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */
874: if (prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1) {
875: msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" );
876: exit(-1);
877: }
878: #else
879: /* we need a user to switch to */
880: if (user == NULL) {
881: msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" );
882: exit(-1);
883: }
884: #endif /* HAVE_LINUX_CAPABILITIES */
885:
886: if (user != NULL) {
887: if (isdigit((unsigned char)*user)) {
888: sw_uid = (uid_t)strtoul(user, &endp, 0);
889: if (*endp != '\0')
890: goto getuser;
891:
892: if ((pw = getpwuid(sw_uid)) != NULL) {
893: user = strdup(pw->pw_name);
894: if (NULL == user) {
895: msyslog(LOG_ERR, "strdup() failed: %m");
896: exit (-1);
897: }
898: sw_gid = pw->pw_gid;
899: } else {
900: errno = 0;
901: msyslog(LOG_ERR, "Cannot find user ID %s", user);
902: exit (-1);
903: }
904:
905: } else {
906: getuser:
907: errno = 0;
908: if ((pw = getpwnam(user)) != NULL) {
909: sw_uid = pw->pw_uid;
910: sw_gid = pw->pw_gid;
911: } else {
912: if (errno)
913: msyslog(LOG_ERR, "getpwnam(%s) failed: %m", user);
914: else
915: msyslog(LOG_ERR, "Cannot find user `%s'", user);
916: exit (-1);
917: }
918: }
919: }
920: if (group != NULL) {
921: if (isdigit((unsigned char)*group)) {
922: sw_gid = (gid_t)strtoul(group, &endp, 0);
923: if (*endp != '\0')
924: goto getgroup;
925: } else {
926: getgroup:
927: if ((gr = getgrnam(group)) != NULL) {
928: sw_gid = gr->gr_gid;
929: } else {
930: errno = 0;
931: msyslog(LOG_ERR, "Cannot find group `%s'", group);
932: exit (-1);
933: }
934: }
935: }
936:
937: if (chrootdir ) {
938: /* make sure cwd is inside the jail: */
939: if (chdir(chrootdir)) {
940: msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir);
941: exit (-1);
942: }
943: if (chroot(chrootdir)) {
944: msyslog(LOG_ERR, "Cannot chroot() to `%s': %m", chrootdir);
945: exit (-1);
946: }
947: if (chdir("/")) {
948: msyslog(LOG_ERR, "Cannot chdir() to`root after chroot(): %m");
949: exit (-1);
950: }
951: }
952: if (user && initgroups(user, sw_gid)) {
953: msyslog(LOG_ERR, "Cannot initgroups() to user `%s': %m", user);
954: exit (-1);
955: }
956: if (group && setgid(sw_gid)) {
957: msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group);
958: exit (-1);
959: }
960: if (group && setegid(sw_gid)) {
961: msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group);
962: exit (-1);
963: }
964: if (user && setuid(sw_uid)) {
965: msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user);
966: exit (-1);
967: }
968: if (user && seteuid(sw_uid)) {
969: msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user);
970: exit (-1);
971: }
972:
973: #ifndef HAVE_LINUX_CAPABILITIES
974: /*
975: * for now assume that the privilege to bind to privileged ports
976: * is associated with running with uid 0 - should be refined on
977: * ports that allow binding to NTP_PORT with uid != 0
978: */
979: disable_dynamic_updates |= (sw_uid != 0); /* also notifies routing message listener */
980: #endif
981:
982: if (disable_dynamic_updates && interface_interval) {
983: interface_interval = 0;
984: msyslog(LOG_INFO, "running in unprivileged mode disables dynamic interface tracking");
985: }
986:
987: #ifdef HAVE_LINUX_CAPABILITIES
988: do {
989: /*
990: * We may be running under non-root uid now, but we still hold full root privileges!
991: * We drop all of them, except for the crucial one or two: cap_sys_time and
992: * cap_net_bind_service if doing dynamic interface tracking.
993: */
994: cap_t caps;
995: char *captext = (interface_interval)
996: ? "cap_sys_time,cap_net_bind_service=ipe"
997: : "cap_sys_time=ipe";
998: if( ! ( caps = cap_from_text( captext ) ) ) {
999: msyslog( LOG_ERR, "cap_from_text() failed: %m" );
1000: exit(-1);
1001: }
1002: if( cap_set_proc( caps ) == -1 ) {
1003: msyslog( LOG_ERR, "cap_set_proc() failed to drop root privileges: %m" );
1004: exit(-1);
1005: }
1006: cap_free( caps );
1007: } while(0);
1008: #endif /* HAVE_LINUX_CAPABILITIES */
1009:
1010: } /* if( droproot ) */
1011: #endif /* HAVE_DROPROOT */
1012:
1013: /*
1014: * Use select() on all on all input fd's for unlimited
1015: * time. select() will terminate on SIGALARM or on the
1016: * reception of input. Using select() means we can't do
1017: * robust signal handling and we get a potential race
1018: * between checking for alarms and doing the select().
1019: * Mostly harmless, I think.
1020: */
1021: /* On VMS, I suspect that select() can't be interrupted
1022: * by a "signal" either, so I take the easy way out and
1023: * have select() time out after one second.
1024: * System clock updates really aren't time-critical,
1025: * and - lacking a hardware reference clock - I have
1026: * yet to learn about anything else that is.
1027: */
1028: #if defined(HAVE_IO_COMPLETION_PORT)
1029:
1030: for (;;) {
1031: GetReceivedBuffers();
1032: #else /* normal I/O */
1033:
1034: BLOCK_IO_AND_ALARM();
1035: was_alarmed = 0;
1036: for (;;)
1037: {
1038: # if !defined(HAVE_SIGNALED_IO)
1039: extern fd_set activefds;
1040: extern int maxactivefd;
1041:
1042: fd_set rdfdes;
1043: int nfound;
1044: # endif
1045:
1046: if (alarm_flag) /* alarmed? */
1047: {
1048: was_alarmed = 1;
1049: alarm_flag = 0;
1050: }
1051:
1052: if (!was_alarmed && has_full_recv_buffer() == ISC_FALSE)
1053: {
1054: /*
1055: * Nothing to do. Wait for something.
1056: */
1057: # ifndef HAVE_SIGNALED_IO
1058: rdfdes = activefds;
1059: # if defined(VMS) || defined(SYS_VXWORKS)
1060: /* make select() wake up after one second */
1061: {
1062: struct timeval t1;
1063:
1064: t1.tv_sec = 1; t1.tv_usec = 0;
1065: nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
1066: (fd_set *)0, &t1);
1067: }
1068: # else
1069: nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
1070: (fd_set *)0, (struct timeval *)0);
1071: # endif /* VMS */
1072: if (nfound > 0)
1073: {
1074: l_fp ts;
1075:
1076: get_systime(&ts);
1077:
1078: (void)input_handler(&ts);
1079: }
1080: else if (nfound == -1 && errno != EINTR)
1081: msyslog(LOG_ERR, "select() error: %m");
1082: # ifdef DEBUG
1083: else if (debug > 5)
1084: msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
1085: # endif /* DEBUG */
1086: # else /* HAVE_SIGNALED_IO */
1087:
1088: wait_for_signal();
1089: # endif /* HAVE_SIGNALED_IO */
1090: if (alarm_flag) /* alarmed? */
1091: {
1092: was_alarmed = 1;
1093: alarm_flag = 0;
1094: }
1095: }
1096:
1097: if (was_alarmed)
1098: {
1099: UNBLOCK_IO_AND_ALARM();
1100: /*
1101: * Out here, signals are unblocked. Call timer routine
1102: * to process expiry.
1103: */
1104: timer();
1105: was_alarmed = 0;
1106: BLOCK_IO_AND_ALARM();
1107: }
1108:
1109: #endif /* ! HAVE_IO_COMPLETION_PORT */
1110:
1111: #ifdef DEBUG_TIMING
1112: {
1113: l_fp pts;
1114: l_fp tsa, tsb;
1115: int bufcount = 0;
1116:
1117: get_systime(&pts);
1118: tsa = pts;
1119: #endif
1120: rbuf = get_full_recv_buffer();
1121: while (rbuf != NULL)
1122: {
1123: if (alarm_flag)
1124: {
1125: was_alarmed = 1;
1126: alarm_flag = 0;
1127: }
1128: UNBLOCK_IO_AND_ALARM();
1129:
1130: if (was_alarmed)
1131: { /* avoid timer starvation during lengthy I/O handling */
1132: timer();
1133: was_alarmed = 0;
1134: }
1135:
1136: /*
1137: * Call the data procedure to handle each received
1138: * packet.
1139: */
1140: if (rbuf->receiver != NULL) /* This should always be true */
1141: {
1142: #ifdef DEBUG_TIMING
1143: l_fp dts = pts;
1144:
1145: L_SUB(&dts, &rbuf->recv_time);
1146: DPRINTF(2, ("processing timestamp delta %s (with prec. fuzz)\n", lfptoa(&dts, 9)));
1147: collect_timing(rbuf, "buffer processing delay", 1, &dts);
1148: bufcount++;
1149: #endif
1150: (rbuf->receiver)(rbuf);
1151: } else {
1152: msyslog(LOG_ERR, "receive buffer corruption - receiver found to be NULL - ABORTING");
1153: abort();
1154: }
1155:
1156: BLOCK_IO_AND_ALARM();
1157: freerecvbuf(rbuf);
1158: rbuf = get_full_recv_buffer();
1159: }
1160: #ifdef DEBUG_TIMING
1161: get_systime(&tsb);
1162: L_SUB(&tsb, &tsa);
1163: if (bufcount) {
1164: collect_timing(NULL, "processing", bufcount, &tsb);
1165: DPRINTF(2, ("processing time for %d buffers %s\n", bufcount, lfptoa(&tsb, 9)));
1166: }
1167: }
1168: #endif
1169:
1170: /*
1171: * Go around again
1172: */
1173:
1174: #ifdef HAVE_DNSREGISTRATION
1175: if (mdnsreg && (current_time - mdnsreg ) > 60 && mdnstries && sys_leap != LEAP_NOTINSYNC) {
1176: mdnsreg = current_time;
1177: msyslog(LOG_INFO, "Attempting to register mDNS");
1178: if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL,
1179: htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) {
1180: if (!--mdnstries) {
1181: msyslog(LOG_ERR, "Unable to register mDNS, giving up.");
1182: } else {
1183: msyslog(LOG_INFO, "Unable to register mDNS, will try later.");
1184: }
1185: } else {
1186: msyslog(LOG_INFO, "mDNS service registered.");
1187: mdnsreg = 0;
1188: }
1189: }
1190: #endif /* HAVE_DNSREGISTRATION */
1191:
1192: }
1193: UNBLOCK_IO_AND_ALARM();
1194: return 1;
1195: }
1196:
1197:
1198: #ifdef SIGDIE2
1199: /*
1200: * finish - exit gracefully
1201: */
1202: static RETSIGTYPE
1203: finish(
1204: int sig
1205: )
1206: {
1207: msyslog(LOG_NOTICE, "ntpd exiting on signal %d", sig);
1208: #ifdef HAVE_DNSREGISTRATION
1209: if (mdns != NULL)
1210: DNSServiceRefDeallocate(mdns);
1211: #endif
1212: switch (sig) {
1213: # ifdef SIGBUS
1214: case SIGBUS:
1215: printf("\nfinish(SIGBUS)\n");
1216: exit(0);
1217: # endif
1218: case 0: /* Should never happen... */
1219: return;
1220:
1221: default:
1222: exit(0);
1223: }
1224: }
1225: #endif /* SIGDIE2 */
1226:
1227:
1228: /* assertion_failed
1229: * Redirect trap messages from ISC libraries to syslog.
1230: * This code was cloned and simplified from BIND.
1231: */
1232:
1233: /*
1234: * assertion_failed - Handle assertion failures.
1235: */
1236:
1237: static void
1238: assertion_failed(const char *file, int line, isc_assertiontype_t type,
1239: const char *cond)
1240: {
1241: isc_assertion_setcallback(NULL); /* Avoid recursion */
1242:
1243: msyslog(LOG_ERR, "%s:%d: %s(%s) failed",
1244: file, line, isc_assertion_typetotext(type), cond);
1245: msyslog(LOG_ERR, "exiting (due to assertion failure)");
1246:
1247: abort();
1248: }
1249:
1250: /*
1251: * library_fatal_error - Handle fatal errors from our libraries.
1252: */
1253:
1254: static void
1255: library_fatal_error(const char *file, int line, const char *format,
1256: va_list args)
1257: {
1258: char errbuf[256];
1259:
1260: isc_error_setfatal(NULL); /* Avoid recursion */
1261:
1262: msyslog(LOG_ERR, "%s:%d: fatal error:", file, line);
1263: vsnprintf(errbuf, sizeof(errbuf), format, args);
1264: msyslog(LOG_ERR, errbuf);
1265: msyslog(LOG_ERR, "exiting (due to fatal error in library)");
1266:
1267: abort();
1268: }
1269:
1270: /*
1271: * library_unexpected_error - Handle non fatal errors from our libraries.
1272: */
1273: #define MAX_UNEXPECTED_ERRORS 100
1274: int unexpected_error_cnt = 0;
1275: static void
1276: library_unexpected_error(const char *file, int line, const char *format,
1277: va_list args)
1278: {
1279: char errbuf[256];
1280:
1281: if (unexpected_error_cnt >= MAX_UNEXPECTED_ERRORS)
1282: return; /* avoid clutter in log */
1283:
1284: msyslog(LOG_ERR, "%s:%d: unexpected error:", file, line);
1285: vsnprintf(errbuf, sizeof(errbuf), format, args);
1286: msyslog(LOG_ERR, errbuf);
1287:
1288: if (++unexpected_error_cnt == MAX_UNEXPECTED_ERRORS)
1289: {
1290: msyslog(LOG_ERR, "Too many errors. Shutting up.");
1291: }
1292:
1293: }
1294:
1295:
1296: #ifdef DEBUG
1297: #ifndef SYS_WINNT
1298: /*
1299: * moredebug - increase debugging verbosity
1300: */
1301: static RETSIGTYPE
1302: moredebug(
1303: int sig
1304: )
1305: {
1306: int saved_errno = errno;
1307:
1308: if (debug < 255)
1309: {
1310: debug++;
1311: msyslog(LOG_DEBUG, "debug raised to %d", debug);
1312: }
1313: errno = saved_errno;
1314: }
1315:
1316: /*
1317: * lessdebug - decrease debugging verbosity
1318: */
1319: static RETSIGTYPE
1320: lessdebug(
1321: int sig
1322: )
1323: {
1324: int saved_errno = errno;
1325:
1326: if (debug > 0)
1327: {
1328: debug--;
1329: msyslog(LOG_DEBUG, "debug lowered to %d", debug);
1330: }
1331: errno = saved_errno;
1332: }
1333: #endif
1334: #else /* not DEBUG */
1335: #ifndef SYS_WINNT
1336: /*
1337: * no_debug - We don't do the debug here.
1338: */
1339: static RETSIGTYPE
1340: no_debug(
1341: int sig
1342: )
1343: {
1344: int saved_errno = errno;
1345:
1346: msyslog(LOG_DEBUG, "ntpd not compiled for debugging (signal %d)", sig);
1347: errno = saved_errno;
1348: }
1349: #endif /* not SYS_WINNT */
1350: #endif /* not DEBUG */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>