1/*
2 * systime -- routines to fiddle a UNIX clock.
3 *
4 * ATTENTION: Get approval from Dave Mills on all changes to this file!
5 *
6 */
7#include <config.h>
8#include <math.h>
9
10#include "ntp.h"
11#include "ntpd.h"
12#include "ntp_syslog.h"
13#include "ntp_stdlib.h"
14#include "ntp_random.h"
15#include "iosignal.h"
16#include "timevalops.h"
17#include "timespecops.h"
18#include "ntp_calendar.h"
19
20#ifdef HAVE_SYS_PARAM_H
21# include <sys/param.h>
22#endif
23#ifdef HAVE_UTMP_H
24# include <utmp.h>
25#endif /* HAVE_UTMP_H */
26#ifdef HAVE_UTMPX_H
27# include <utmpx.h>
28#endif /* HAVE_UTMPX_H */
29
30int	allow_panic = FALSE;		/* allow panic correction (-g) */
31int	enable_panic_check = TRUE;	/* Can we check allow_panic's state? */
32
33u_long	sys_lamport;			/* Lamport violation */
34u_long	sys_tsrounding;			/* timestamp rounding errors */
35
36#ifndef USE_COMPILETIME_PIVOT
37# define USE_COMPILETIME_PIVOT 1
38#endif
39
40/*
41 * These routines (get_systime, step_systime, adj_systime) implement an
42 * interface between the system independent NTP clock and the Unix
43 * system clock in various architectures and operating systems. Time is
44 * a precious quantity in these routines and every effort is made to
45 * minimize errors by unbiased rounding and amortizing adjustment
46 * residues.
47 *
48 * In order to improve the apparent resolution, provide unbiased
49 * rounding and most importantly ensure that the readings cannot be
50 * predicted, the low-order unused portion of the time below the minimum
51 * time to read the clock is filled with an unbiased random fuzz.
52 *
53 * The sys_tick variable specifies the system clock tick interval in
54 * seconds, for stepping clocks, defined as those which return times
55 * less than MINSTEP greater than the previous reading. For systems that
56 * use a high-resolution counter such that each clock reading is always
57 * at least MINSTEP greater than the prior, sys_tick is the time to read
58 * the system clock.
59 *
60 * The sys_fuzz variable measures the minimum time to read the system
61 * clock, regardless of its precision.  When reading the system clock
62 * using get_systime() after sys_tick and sys_fuzz have been determined,
63 * ntpd ensures each unprocessed clock reading is no less than sys_fuzz
64 * later than the prior unprocessed reading, and then fuzzes the bits
65 * below sys_fuzz in the timestamp returned, ensuring each of its
66 * resulting readings is strictly later than the previous.
67 *
68 * When slewing the system clock using adj_systime() (with the kernel
69 * loop discipline unavailable or disabled), adjtime() offsets are
70 * quantized to sys_tick, if sys_tick is greater than sys_fuzz, which
71 * is to say if the OS presents a stepping clock.  Otherwise, offsets
72 * are quantized to the microsecond resolution of adjtime()'s timeval
73 * input.  The remaining correction sys_residual is carried into the
74 * next adjtime() and meanwhile is also factored into get_systime()
75 * readings.
76 */
77double	sys_tick = 0;		/* tick size or time to read (s) */
78double	sys_fuzz = 0;		/* min. time to read the clock (s) */
79long	sys_fuzz_nsec = 0;	/* min. time to read the clock (ns) */
80double	measured_tick;		/* non-overridable sys_tick (s) */
81double	sys_residual = 0;	/* adjustment residue (s) */
82int	trunc_os_clock;		/* sys_tick > measured_tick */
83time_stepped_callback	step_callback;
84
85#ifndef SIM
86/* perlinger@ntp.org: As 'get_sysime()' does it's own check for clock
87 * backstepping, this could probably become a local variable in
88 * 'get_systime()' and the cruft associated with communicating via a
89 * static value could be removed after the v4.2.8 release.
90 */
91static int lamport_violated;	/* clock was stepped back */
92#endif	/* !SIM */
93
94#ifdef DEBUG
95static int systime_init_done;
96# define DONE_SYSTIME_INIT()	systime_init_done = TRUE
97#else
98# define DONE_SYSTIME_INIT()	do {} while (FALSE)
99#endif
100
101#ifdef HAVE_SIGNALED_IO
102int using_sigio;
103#endif
104
105#ifdef SYS_WINNT
106CRITICAL_SECTION get_systime_cs;
107#endif
108
109
110void
111set_sys_fuzz(
112	double	fuzz_val
113	)
114{
115	sys_fuzz = fuzz_val;
116	INSIST(sys_fuzz >= 0);
117	INSIST(sys_fuzz <= 1.0);
118	/* [Bug 3450] ensure nsec fuzz >= sys_fuzz to reduce chance of
119	 * short-falling fuzz advance
120	 */
121	sys_fuzz_nsec = (long)ceil(sys_fuzz * 1e9);
122}
123
124
125void
126init_systime(void)
127{
128	INIT_GET_SYSTIME_CRITSEC();
129	INIT_WIN_PRECISE_TIME();
130	DONE_SYSTIME_INIT();
131}
132
133
134#ifndef SIM	/* ntpsim.c has get_systime() and friends for sim */
135
136static inline void
137get_ostime(
138	struct timespec *	tsp
139	)
140{
141	int	rc;
142	long	ticks;
143
144#if defined(HAVE_CLOCK_GETTIME)
145	rc = clock_gettime(CLOCK_REALTIME, tsp);
146#elif defined(HAVE_GETCLOCK)
147	rc = getclock(TIMEOFDAY, tsp);
148#else
149	struct timeval		tv;
150
151	rc = GETTIMEOFDAY(&tv, NULL);
152	tsp->tv_sec = tv.tv_sec;
153	tsp->tv_nsec = tv.tv_usec * 1000;
154#endif
155	if (rc < 0) {
156		msyslog(LOG_ERR, "read system clock failed: %m (%d)",
157			errno);
158		exit(1);
159	}
160
161	if (trunc_os_clock) {
162		ticks = (long)((tsp->tv_nsec * 1e-9) / sys_tick);
163		tsp->tv_nsec = (long)(ticks * 1e9 * sys_tick);
164	}
165}
166
167
168/*
169 * get_systime - return system time in NTP timestamp format.
170 */
171void
172get_systime(
173	l_fp *now		/* system time */
174	)
175{
176        static struct timespec  ts_last;        /* last sampled os time */
177	static struct timespec	ts_prev;	/* prior os time */
178	static l_fp		lfp_prev;	/* prior result */
179	struct timespec ts;	/* seconds and nanoseconds */
180	struct timespec ts_min;	/* earliest permissible */
181	struct timespec ts_lam;	/* lamport fictional increment */
182	double	dfuzz;
183	l_fp	result;
184	l_fp	lfpfuzz;
185	l_fp	lfpdelta;
186
187	get_ostime(&ts);
188	DEBUG_REQUIRE(systime_init_done);
189	ENTER_GET_SYSTIME_CRITSEC();
190
191        /* First check if here was a Lamport violation, that is, two
192         * successive calls to 'get_ostime()' resulted in negative
193         * time difference. Use a few milliseconds of permissible
194         * tolerance -- being too sharp can hurt here. (This is intented
195         * for the Win32 target, where the HPC interpolation might
196         * introduce small steps backward. It should not be an issue on
197         * systems where get_ostime() results in a true syscall.)
198         */
199        if (cmp_tspec(add_tspec_ns(ts, 50000000), ts_last) < 0) {
200                lamport_violated = 1;
201                sys_lamport++;
202	}
203        ts_last = ts;
204
205	/*
206	 * After default_get_precision() has set a nonzero sys_fuzz,
207	 * ensure every reading of the OS clock advances by at least
208	 * sys_fuzz over the prior reading, thereby assuring each
209	 * fuzzed result is strictly later than the prior.  Limit the
210	 * necessary fiction to 1 second.
211	 */
212	if (!USING_SIGIO()) {
213		ts_min = add_tspec_ns(ts_prev, sys_fuzz_nsec);
214		if (cmp_tspec(ts, ts_min) < 0) {
215			ts_lam = sub_tspec(ts_min, ts);
216			if (ts_lam.tv_sec > 0 && !lamport_violated) {
217				msyslog(LOG_ERR,
218					"get_systime Lamport advance exceeds one second (%.9f)",
219					ts_lam.tv_sec +
220					    1e-9 * ts_lam.tv_nsec);
221				exit(1);
222			}
223			if (!lamport_violated)
224				ts = ts_min;
225		}
226		ts_prev = ts;
227	}
228
229	/* convert from timespec to l_fp fixed-point */
230	result = tspec_stamp_to_lfp(ts);
231
232	/*
233	 * Add in the fuzz. 'ntp_random()' returns [0..2**31-1] so we
234	 * must scale up the result by 2.0 to cover the full fractional
235	 * range.
236	 */
237	dfuzz = ntp_uurandom() * sys_fuzz;
238	DTOLFP(dfuzz, &lfpfuzz);
239	L_ADD(&result, &lfpfuzz);
240
241	/*
242	 * Ensure result is strictly greater than prior result (ignoring
243	 * sys_residual's effect for now) once sys_fuzz has been
244	 * determined.
245	 *
246	 * [Bug 3450] Rounding errors and time slew can lead to a
247	 * violation of the expected postcondition. This is bound to
248	 * happen from time to time (depending on state of the random
249	 * generator, the current slew and the closeness of system time
250	 * stamps drawn) and does not warrant a syslog entry. Instead it
251	 * makes much more sense to ensure the postcondition and hop
252	 * along silently.
253	 */
254	if (!USING_SIGIO()) {
255		if (   !L_ISZERO(&lfp_prev)
256		    && !lamport_violated
257		    && (sys_fuzz > 0.0)
258		   ) {
259			lfpdelta = result;
260			L_SUB(&lfpdelta, &lfp_prev);
261			L_SUBUF(&lfpdelta, 1);
262			if (lfpdelta.l_i < 0)
263			{
264				L_NEG(&lfpdelta);
265				DPRINTF(1, ("get_systime: postcond failed by %s secs, fixed\n",
266					    lfptoa(&lfpdelta, 9)));
267				result = lfp_prev;
268				L_ADDUF(&result, 1);
269				sys_tsrounding++;
270			}
271		}
272		lfp_prev = result;
273		if (lamport_violated)
274			lamport_violated = FALSE;
275	}
276	LEAVE_GET_SYSTIME_CRITSEC();
277	*now = result;
278}
279
280
281/*
282 * adj_systime - adjust system time by the argument.
283 */
284#if !defined SYS_WINNT
285int				/* 0 okay, 1 error */
286adj_systime(
287	double now		/* adjustment (s) */
288	)
289{
290	struct timeval adjtv;	/* new adjustment */
291	struct timeval oadjtv;	/* residual adjustment */
292	double	quant;		/* quantize to multiples of */
293	double	dtemp;
294	long	ticks;
295	int	isneg = 0;
296
297	/*
298	 * The Windows port adj_systime() depends on being called each
299	 * second even when there's no additional correction, to allow
300	 * emulation of adjtime() behavior on top of an API that simply
301	 * sets the current rate.  This POSIX implementation needs to
302	 * ignore invocations with zero correction, otherwise ongoing
303	 * EVNT_NSET adjtime() can be aborted by a tiny adjtime()
304	 * triggered by sys_residual.
305	 */
306	if (0. == now) {
307		if (enable_panic_check && allow_panic) {
308			msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!");
309			INSIST(!allow_panic);
310		}
311		return TRUE;
312	}
313
314	/*
315	 * Most Unix adjtime() implementations adjust the system clock
316	 * in microsecond quanta, but some adjust in 10-ms quanta. We
317	 * carefully round the adjustment to the nearest quantum, then
318	 * adjust in quanta and keep the residue for later.
319	 */
320	dtemp = now + sys_residual;
321	if (dtemp < 0) {
322		isneg = 1;
323		dtemp = -dtemp;
324	}
325	adjtv.tv_sec = (long)dtemp;
326	dtemp -= adjtv.tv_sec;
327	if (sys_tick > sys_fuzz)
328		quant = sys_tick;
329	else
330		quant = 1e-6;
331	ticks = (long)(dtemp / quant + .5);
332	adjtv.tv_usec = (long)(ticks * quant * 1.e6 + .5);
333	/* The rounding in the conversions could us push over the
334	 * limits: make sure the result is properly normalised!
335	 * note: sign comes later, all numbers non-negative here.
336	 */
337	if (adjtv.tv_usec >= 1000000) {
338		adjtv.tv_sec  += 1;
339		adjtv.tv_usec -= 1000000;
340		dtemp         -= 1.;
341	}
342	/* set the new residual with leftover from correction */
343	sys_residual = dtemp - adjtv.tv_usec * 1.e-6;
344
345	/*
346	 * Convert to signed seconds and microseconds for the Unix
347	 * adjtime() system call. Note we purposely lose the adjtime()
348	 * leftover.
349	 */
350	if (isneg) {
351		adjtv.tv_sec = -adjtv.tv_sec;
352		adjtv.tv_usec = -adjtv.tv_usec;
353		sys_residual = -sys_residual;
354	}
355	if (adjtv.tv_sec != 0 || adjtv.tv_usec != 0) {
356		if (adjtime(&adjtv, &oadjtv) < 0) {
357			msyslog(LOG_ERR, "adj_systime: %m");
358			if (enable_panic_check && allow_panic) {
359				msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!");
360			}
361			return FALSE;
362		}
363	}
364	if (enable_panic_check && allow_panic) {
365		msyslog(LOG_ERR, "adj_systime: allow_panic is TRUE!");
366	}
367	return TRUE;
368}
369#endif
370
371/*
372 * helper to keep utmp/wtmp up to date
373 */
374static void
375update_uwtmp(
376	struct timeval timetv,
377	struct timeval tvlast
378	)
379{
380	struct timeval tvdiff;
381	/*
382	 * FreeBSD, for example, has:
383	 * struct utmp {
384	 *	   char    ut_line[UT_LINESIZE];
385	 *	   char    ut_name[UT_NAMESIZE];
386	 *	   char    ut_host[UT_HOSTSIZE];
387	 *	   long    ut_time;
388	 * };
389	 * and appends line="|", name="date", host="", time for the OLD
390	 * and appends line="{", name="date", host="", time for the NEW // }
391	 * to _PATH_WTMP .
392	 *
393	 * Some OSes have utmp, some have utmpx.
394	 */
395
396	/*
397	 * Write old and new time entries in utmp and wtmp if step
398	 * adjustment is greater than one second.
399	 *
400	 * This might become even Uglier...
401	 */
402	tvdiff = abs_tval(sub_tval(timetv, tvlast));
403	if (tvdiff.tv_sec > 0) {
404#ifdef HAVE_UTMP_H
405		struct utmp ut;
406#endif
407#ifdef HAVE_UTMPX_H
408		struct utmpx utx;
409#endif
410
411#ifdef HAVE_UTMP_H
412		ZERO(ut);
413#endif
414#ifdef HAVE_UTMPX_H
415		ZERO(utx);
416#endif
417
418		/* UTMP */
419
420#ifdef UPDATE_UTMP
421# ifdef HAVE_PUTUTLINE
422#  ifndef _PATH_UTMP
423#   define _PATH_UTMP UTMP_FILE
424#  endif
425		utmpname(_PATH_UTMP);
426		ut.ut_type = OLD_TIME;
427		strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line));
428		ut.ut_time = tvlast.tv_sec;
429		setutent();
430		pututline(&ut);
431		ut.ut_type = NEW_TIME;
432		strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line));
433		ut.ut_time = timetv.tv_sec;
434		setutent();
435		pututline(&ut);
436		endutent();
437# else /* not HAVE_PUTUTLINE */
438# endif /* not HAVE_PUTUTLINE */
439#endif /* UPDATE_UTMP */
440
441		/* UTMPX */
442
443#ifdef UPDATE_UTMPX
444# ifdef HAVE_PUTUTXLINE
445		utx.ut_type = OLD_TIME;
446		strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line));
447		utx.ut_tv = tvlast;
448		setutxent();
449		pututxline(&utx);
450		utx.ut_type = NEW_TIME;
451		strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line));
452		utx.ut_tv = timetv;
453		setutxent();
454		pututxline(&utx);
455		endutxent();
456# else /* not HAVE_PUTUTXLINE */
457# endif /* not HAVE_PUTUTXLINE */
458#endif /* UPDATE_UTMPX */
459
460		/* WTMP */
461
462#ifdef UPDATE_WTMP
463# ifdef HAVE_PUTUTLINE
464#  ifndef _PATH_WTMP
465#   define _PATH_WTMP WTMP_FILE
466#  endif
467		utmpname(_PATH_WTMP);
468		ut.ut_type = OLD_TIME;
469		strlcpy(ut.ut_line, OTIME_MSG, sizeof(ut.ut_line));
470		ut.ut_time = tvlast.tv_sec;
471		setutent();
472		pututline(&ut);
473		ut.ut_type = NEW_TIME;
474		strlcpy(ut.ut_line, NTIME_MSG, sizeof(ut.ut_line));
475		ut.ut_time = timetv.tv_sec;
476		setutent();
477		pututline(&ut);
478		endutent();
479# else /* not HAVE_PUTUTLINE */
480# endif /* not HAVE_PUTUTLINE */
481#endif /* UPDATE_WTMP */
482
483		/* WTMPX */
484
485#ifdef UPDATE_WTMPX
486# ifdef HAVE_PUTUTXLINE
487		utx.ut_type = OLD_TIME;
488		utx.ut_tv = tvlast;
489		strlcpy(utx.ut_line, OTIME_MSG, sizeof(utx.ut_line));
490#  ifdef HAVE_UPDWTMPX
491		updwtmpx(WTMPX_FILE, &utx);
492#  else /* not HAVE_UPDWTMPX */
493#  endif /* not HAVE_UPDWTMPX */
494# else /* not HAVE_PUTUTXLINE */
495# endif /* not HAVE_PUTUTXLINE */
496# ifdef HAVE_PUTUTXLINE
497		utx.ut_type = NEW_TIME;
498		utx.ut_tv = timetv;
499		strlcpy(utx.ut_line, NTIME_MSG, sizeof(utx.ut_line));
500#  ifdef HAVE_UPDWTMPX
501		updwtmpx(WTMPX_FILE, &utx);
502#  else /* not HAVE_UPDWTMPX */
503#  endif /* not HAVE_UPDWTMPX */
504# else /* not HAVE_PUTUTXLINE */
505# endif /* not HAVE_PUTUTXLINE */
506#endif /* UPDATE_WTMPX */
507
508	}
509}
510
511/*
512 * step_systime - step the system clock.
513 */
514
515int
516step_systime(
517	double step
518	)
519{
520	time_t pivot; /* for ntp era unfolding */
521	struct timeval timetv, tvlast;
522	struct timespec timets;
523	l_fp fp_ofs, fp_sys; /* offset and target system time in FP */
524
525	/*
526	 * Get pivot time for NTP era unfolding. Since we don't step
527	 * very often, we can afford to do the whole calculation from
528	 * scratch. And we're not in the time-critical path yet.
529	 */
530#if SIZEOF_TIME_T > 4
531	pivot = basedate_get_eracenter();
532#else
533	/* This makes sure the resulting time stamp is on or after
534	 * 1969-12-31/23:59:59 UTC and gives us additional two years,
535	 * from the change of NTP era in 2036 to the UNIX rollover in
536	 * 2038. (Minus one second, but that won't hurt.) We *really*
537	 * need a longer 'time_t' after that!  Or a different baseline,
538	 * but that would cause other serious trouble, too.
539	 */
540	pivot = 0x7FFFFFFF;
541#endif
542
543	/* get the complete jump distance as l_fp */
544	DTOLFP(sys_residual, &fp_sys);
545	DTOLFP(step,         &fp_ofs);
546	L_ADD(&fp_ofs, &fp_sys);
547
548	/* ---> time-critical path starts ---> */
549
550	/* get the current time as l_fp (without fuzz) and as struct timeval */
551	get_ostime(&timets);
552	fp_sys = tspec_stamp_to_lfp(timets);
553	tvlast.tv_sec = timets.tv_sec;
554	tvlast.tv_usec = (timets.tv_nsec + 500) / 1000;
555
556	/* get the target time as l_fp */
557	L_ADD(&fp_sys, &fp_ofs);
558
559	/* unfold the new system time */
560	timetv = lfp_stamp_to_tval(fp_sys, &pivot);
561
562	/* now set new system time */
563	if (ntp_set_tod(&timetv, NULL) != 0) {
564		msyslog(LOG_ERR, "step-systime: %m");
565		if (enable_panic_check && allow_panic) {
566			msyslog(LOG_ERR, "step_systime: allow_panic is TRUE!");
567		}
568		return FALSE;
569	}
570
571	/* <--- time-critical path ended with 'ntp_set_tod()' <--- */
572
573	sys_residual = 0;
574	lamport_violated = (step < 0);
575	if (step_callback)
576		(*step_callback)();
577
578#ifdef NEED_HPUX_ADJTIME
579	/*
580	 * CHECKME: is this correct when called by ntpdate?????
581	 */
582	_clear_adjtime();
583#endif
584
585	update_uwtmp(timetv, tvlast);
586	if (enable_panic_check && allow_panic) {
587		msyslog(LOG_ERR, "step_systime: allow_panic is TRUE!");
588		INSIST(!allow_panic);
589	}
590	return TRUE;
591}
592
593
594#if SIZEOF_TIME_T > 4
595static const char *
596tv_fmt_libbuf(
597	const struct timeval * ptv
598	)
599{
600	char *		retv;
601	vint64		secs;
602	ntpcal_split	dds;
603	struct calendar	jd;
604
605	secs = time_to_vint64(&ptv->tv_sec);
606	dds  = ntpcal_daysplit(&secs);
607	ntpcal_daysplit_to_date(&jd, &dds, DAY_UNIX_STARTS);
608	LIB_GETBUF(retv);
609	snprintf(retv, LIB_BUFLENGTH,
610		 "%04hu-%02hu-%02hu/%02hu:%02hu:%02hu.%06u",
611		 jd.year, (u_short)jd.month, (u_short)jd.monthday,
612		 (u_short)jd.hour, (u_short)jd.minute, (u_short)jd.second,
613		 (u_int)ptv->tv_usec);
614	return retv;
615}
616#endif	/* SIZEOF_TIME_T > 4 */
617
618
619int /*BOOL*/
620clamp_systime(void)
621{
622#if SIZEOF_TIME_T > 4
623
624	struct timeval  tvbase, tvlast;
625	struct timespec timets;
626
627	tvbase.tv_sec  = basedate_get_erabase();
628	tvbase.tv_usec = 0;
629
630	/* ---> time-critical path starts ---> */
631
632	/* get the current time as l_fp (without fuzz) and as struct timeval */
633	get_ostime(&timets);
634	tvlast.tv_sec = timets.tv_sec;
635	tvlast.tv_usec = (timets.tv_nsec + 500) / 1000;
636	if (tvlast.tv_usec >= 1000000) {
637		tvlast.tv_usec -= 1000000;
638		tvlast.tv_sec  += 1;
639	}
640
641	if (tvbase.tv_sec > tvlast.tv_sec) {
642		/* now set new system time */
643		if (ntp_set_tod(&tvbase, NULL) != 0) {
644			msyslog(LOG_ERR, "clamp-systime: %m");
645			return FALSE;
646		}
647	} else {
648		msyslog(LOG_INFO,
649			"clamp-systime: clock (%s) in allowed range",
650			tv_fmt_libbuf(&tvlast));
651		return FALSE;
652	}
653
654	/* <--- time-critical path ended with 'ntp_set_tod()' <--- */
655
656	sys_residual = 0;
657	lamport_violated = (tvbase.tv_sec < tvlast.tv_sec);
658	if (step_callback)
659		(*step_callback)();
660
661#   ifdef NEED_HPUX_ADJTIME
662	/*
663	 * CHECKME: is this correct when called by ntpdate?????
664	 */
665	_clear_adjtime();
666#   endif
667
668	update_uwtmp(tvbase, tvlast);
669	msyslog(LOG_WARNING,
670		"clamp-systime: clock stepped from %s to %s!",
671		tv_fmt_libbuf(&tvlast), tv_fmt_libbuf(&tvbase));
672	return TRUE;
673
674#else
675
676	return FALSE;
677
678#endif
679}
680
681#endif	/* !SIM */
682