Please review and test.
-- 
                <a href="http://www.catb.org/~esr/";>Eric S. Raymond</a>

My work is funded by the Internet Civil Engineering Institute: https://icei.org
Please visit their site and donate: the civilization you save might be your own.


>From d244049234e3ae7ed7fcde9f19ac0447cc231e9b Mon Sep 17 00:00:00 2001
From: "Eric S. Raymond" <e...@thyrsus.com>
Date: Sat, 12 Jan 2019 09:04:16 -0500
Subject: [PATCH] Change NIST lockclock enable from a compile-time option to a
 tinker flag.

Heads off a problem with distro packagers carelessly enabling all compile-time
options.  This locks the clock and disables frequency adjustment; hilarity
ensues.
---
 devel/ifdex-ignores            |  1 -
 docs/includes/misc-options.txt |  7 +++-
 docs/ntpsec.txt                |  4 +++
 include/ntpd.h                 |  1 +
 ntpd/keyword-gen.c             |  1 +
 ntpd/ntp_loopfilter.c          | 62 +++++++++-------------------------
 ntpd/ntp_parser.y              |  2 ++
 ntpd/ntp_proto.c               | 20 +++++------
 ntpd/refclock_local.c          | 59 ++++++++++++++++----------------
 wafhelpers/options.py          |  2 --
 wscript                        |  9 -----
 11 files changed, 70 insertions(+), 98 deletions(-)

diff --git a/devel/ifdex-ignores b/devel/ifdex-ignores
index 4226fdcdf..7e5cff953 100644
--- a/devel/ifdex-ignores
+++ b/devel/ifdex-ignores
@@ -64,7 +64,6 @@ LIBRESSL_VERSION_NUMBER
 # Things WAF sets that don't get #undefs if they're not set
 ENABLE_EARLY_DROPROOT
 ENABLE_LEAP_SMEAR
-ENABLE_LOCKCLOCK
 ENABLE_MSSNTP
 ENABLE_LEAP_TESTING
 HAVE_LINUX_CAPABILITY
diff --git a/docs/includes/misc-options.txt b/docs/includes/misc-options.txt
index 2a94974e4..e93df0ab3 100644
--- a/docs/includes/misc-options.txt
+++ b/docs/includes/misc-options.txt
@@ -230,7 +230,8 @@ the log file.
   clock variables.
 
 [[tinker]]
-+tinker+ [+allan+ _allan_ | +dispersion+ _dispersion_ | +freq+ _freq_ | +huffpuff+ _huffpuff_ | +panic+ _panic_ | +step+ _step_ | +stepback+ _stepback_ | +stepfwd+ _stepfwd_ | +stepout+ _stepout_]::
++tinker+ [+allan+ _allan_ | +dispersion+ _dispersion_ | +freq+ _freq_
+| +huffpuff+ _huffpuff_ | lockclock | +panic+ _panic_ | +step+ _step_ | +stepback+ _stepback_ | +stepfwd+ _stepfwd_ | +stepout+ _stepout_]::
   This command can be used to alter several system variables in very
   exceptional circumstances. It should occur in the configuration file
   before any other configuration options. The default values of these
@@ -262,6 +263,10 @@ The variables operate as follows:
     will search for a minimum delay. The lower limit is 900 s (15 m),
     but a more reasonable value is 7200 (2 hours). There is no default
     since the filter is not enabled unless this command is given.
+  +lockclock;;
+    NIST lockclock mode. If this flag is set, absolutely trust the
+    system clock - it's being disciplined in some way external to to
+    ntpd. Only makes sense in conjunction with the localclock driver.
   +panic+ _panic_;;
     The argument is the panic threshold, normally 1000 s. If set to
     zero, the panic sanity check is disabled, and a clock offset of any
diff --git a/docs/ntpsec.txt b/docs/ntpsec.txt
index 53cd13bf5..c6ee0f146 100644
--- a/docs/ntpsec.txt
+++ b/docs/ntpsec.txt
@@ -278,6 +278,10 @@ codebase has been outright removed, with less than 5% new code added.
   default device path, the default PPS device path (if any) and the
   serial baud rate.
 
+* NIST lockclock mode is now a tinker flag rather than a compile-time
+  option, heading off bad things that can occur if a distro packager
+  gets careless and enables every compile-time option by default.
+
 [[other]]
 == Other user-visible changes ==
 
diff --git a/include/ntpd.h b/include/ntpd.h
index 25ff83e0d..1f86ba8e6 100644
--- a/include/ntpd.h
+++ b/include/ntpd.h
@@ -247,6 +247,7 @@ extern endpt *	loopback_interface;	/* IPv4 loopback for refclocks */
 extern endpt *	ep_list;		/* linked list */
 
 /* ntp_loopfilter.c */
+extern bool	lockclock;		/* lock to the system clock? */
 extern double	drift_comp;		/* clock frequency (s/s) */
 extern double	clock_stability;	/* clock stability (s/s) */
 extern double	clock_max_back;		/* max backward offset before step (s) */
diff --git a/ntpd/keyword-gen.c b/ntpd/keyword-gen.c
index 041d07562..4597e154f 100644
--- a/ntpd/keyword-gen.c
+++ b/ntpd/keyword-gen.c
@@ -176,6 +176,7 @@ struct key_tok ntp_keywords[] = {
 { "stacksize",		T_Stacksize,		FOLLBY_TOKEN },
 { "filenum",		T_Filenum,		FOLLBY_TOKEN },
 /* tinker_option */
+{ "lockclock",		T_Lockclock,		FOLLBY_TOKEN },
 { "step",		T_Step,			FOLLBY_TOKEN },
 { "stepback",		T_Stepback,		FOLLBY_TOKEN },
 { "stepfwd",		T_Stepfwd,		FOLLBY_TOKEN },
diff --git a/ntpd/ntp_loopfilter.c b/ntpd/ntp_loopfilter.c
index efd5a5c73..117473c77 100644
--- a/ntpd/ntp_loopfilter.c
+++ b/ntpd/ntp_loopfilter.c
@@ -109,25 +109,23 @@ static double	clock_minstep = CLOCK_MINSTEP; /* stepout threshold */
 static double	clock_panic = CLOCK_PANIC; /* panic threshold */
 double	clock_phi = CLOCK_PHI;	/* dispersion rate (s/s) */
 uint8_t	allan_xpt = CLOCK_ALLAN; /* Allan intercept (log2 s) */
+bool lockclock;		/* absolutely trust the hardware clock? */
 
 /*
  * Program variables
  */
-#ifndef ENABLE_LOCKCLOCK
-static double clock_offset;	/* offset */
-static uptime_t clock_epoch;	/* last update */
-#endif /* ENABLE_LOCKCLOCK */
+static double clock_offset;	/* offset (lockclock case only) */
+static uptime_t clock_epoch;	/* last update (lockclock case only) */
 double	clock_jitter;		/* offset jitter */
 double	drift_comp;		/* frequency (s/s) */
 static double init_drift_comp; /* initial frequency (PPM) */
 double	clock_stability;	/* frequency stability (wander) (s/s) */
 unsigned int	sys_tai;		/* TAI offset from UTC */
-#ifndef ENABLE_LOCKCLOCK
+/* following variables are non-locjclock case only */
 static bool loop_started;	/* true after LOOP_DRIFTINIT */
 static void rstclock (int, double); /* transition function */
 static double direct_freq(double); /* direct set frequency */
 static void set_freq(double);	/* set frequency */
-#endif /* ENABLE_LOCKCLOCK */
 
 #ifndef PATH_MAX
 # define PATH_MAX MAX_PATH
@@ -137,11 +135,9 @@ static char *this_file = NULL;
 
 static struct timex ntv;	/* ntp_adjtime() parameters */
 static int	pll_status;	/* last kernel status bits */
-#ifndef ENABLE_LOCKCLOCK
 #if defined(STA_NANO) && defined(NTP_API) && NTP_API == 4
-static unsigned int loop_tai;		/* last TAI offset */
+static unsigned int loop_tai;	/* last TAI offset (non-lockclock case only) */
 #endif /* STA_NANO */
-#endif /* ENABLE_LOCKCLOCK */
 static	void	start_kern_loop(void);
 static	void	stop_kern_loop(void);
 
@@ -165,9 +161,7 @@ static bool	ext_enable;	/* external clock enabled */
 /*
  * Clock state machine variables
  */
-#ifndef ENABLE_LOCKCLOCK
-static int	state = 0;	/* clock discipline state */
-#endif /* ENABLE_LOCKCLOCK */
+static int	state = 0;	/* clock discipline state (non-lockclock only) */
 uint8_t	sys_poll;		/* time constant/poll (log2 s) */
 int	tc_counter;		/* jiggle counter */
 double	last_offset;		/* last offset (s) */
@@ -190,17 +184,16 @@ static struct sigaction newsigsys; /* new sigaction status */
 static sigjmp_buf env;		/* environment var. for pll_trap() */
 #endif /* SIGSYS */
 
-#ifndef ENABLE_LOCKCLOCK
 static void
 sync_status(const char *what, int ostatus, int nstatus)
 {
+	/* only used in non-lockclock case */
 	char obuf[256], nbuf[256], tbuf[1024];
 	snprintf(obuf, sizeof(obuf), "%04x", (unsigned)ostatus);
 	snprintf(nbuf, sizeof(nbuf), "%04x", (unsigned)nstatus);
 	snprintf(tbuf, sizeof(tbuf), "%s status: %s -> %s", what, obuf, nbuf);
 	report_event(EVNT_KERN, NULL, tbuf);
 }
-#endif /* ENABLE_LOCKCLOCK */
 
 /*
  * file_name - return pointer to non-relative portion of this C file pathname
@@ -438,7 +431,7 @@ or, from ntp_adjtime():
  * 1	clock was slewed
  * 2	clock was stepped
  *
- * ENABLE_LOCKCLOCK: The only thing this routine does is set the
+ * If lockclock is on, the only thing this routine does is set the
  * sys_rootdisp variable equal to the peer dispersion.
  */
 int
@@ -447,10 +440,6 @@ local_clock(
 	double	fp_offset	/* clock offset (s) */
 	)
 {
-#ifdef ENABLE_LOCKCLOCK
-	UNUSED_ARG(peer);
-	UNUSED_ARG(fp_offset);
-#else
 	int	rval;		/* return code */
 	int	osys_poll;	/* old system poll */
 	int	ntp_adj_ret;	/* returned by ntp_adjtime */
@@ -458,24 +447,18 @@ local_clock(
 	double	clock_frequency; /* clock frequency */
 	double	dtemp, etemp;	/* double temps */
 	char	tbuf[80];	/* report buffer */
-#endif /* ENABLE_LOCKCLOCK */
 
 	/*
 	 * If the loop is opened or the NIST lockclock scheme is in use,
 	 * monitor and record the offsets anyway in order to determine
 	 * the open-loop response and then go home.
 	 */
-#ifdef ENABLE_LOCKCLOCK
-	{
-#else
-	if (!clock_ctl.ntp_enable) {
-#endif /* ENABLE_LOCKCLOCK */
+	if (lockclock || !clock_ctl.ntp_enable) {
 		record_loop_stats(fp_offset, drift_comp, clock_jitter,
 		    clock_stability, sys_poll);
 		return (0);
 	}
 
-#ifndef ENABLE_LOCKCLOCK
 	/*
 	 * If the clock is way off, panic is declared. The clock_panic
 	 * defaults to 1000 s; if set to zero, the panic will never
@@ -907,14 +890,13 @@ local_clock(
 		   clock_offset, clock_jitter, drift_comp * US_PER_S,
 		   clock_stability * US_PER_S, sys_poll));
 	return (rval);
-#endif /* ENABLE_LOCKCLOCK */
 }
 
 
 /*
  * adj_host_clock - Called once every second to update the local clock.
  *
- * ENABLE_LOCKCLOCK: The only thing this routine does is increment the
+ * If lockclock is on the only thing this routine does is increment the
  * sys_rootdisp variable.
  */
 void
@@ -922,10 +904,8 @@ adj_host_clock(
 	void
 	)
 {
-#ifndef ENABLE_LOCKCLOCK
 	double	offset_adj;
 	double	freq_adj;
-#endif /* ENABLE_LOCKCLOCK */
 
 	/*
 	 * Update the dispersion since the last update. In contrast to
@@ -936,7 +916,8 @@ adj_host_clock(
 	 * time constant is clamped at 2.
 	 */
 	sys_vars.sys_rootdisp += clock_phi;
-#ifndef ENABLE_LOCKCLOCK
+	if (lockclock)
+	    return;
 	if (!clock_ctl.ntp_enable || clock_ctl.mode_ntpdate)
 		return;
 	/*
@@ -987,11 +968,9 @@ adj_host_clock(
 	 * has decayed to zero.
 	 */
 	adj_systime(offset_adj + freq_adj, adjtime);
-#endif /* ENABLE_LOCKCLOCK */
 }
 
 
-#ifndef ENABLE_LOCKCLOCK
 /*
  * Clock state machine. Enter new state and set state variables.
  */
@@ -1032,9 +1011,7 @@ direct_freq(
 
 	return drift_comp;
 }
-#endif /* ENABLE_LOCKCLOCK */
 
-#ifndef ENABLE_LOCKCLOCK
 /*
  * set_freq - set clock frequency correction
  *
@@ -1071,7 +1048,6 @@ set_freq(
 	mprintf_event(EVNT_FSET, NULL, "%s %.6f PPM", loop_desc,
 	    drift_comp * US_PER_S);
 }
-#endif /* HAVE_LOCKCLOCK */
 
 static void
 start_kern_loop(void)
@@ -1164,10 +1140,8 @@ select_loop(
 	 * call set_freq() to switch the frequency compensation to or
 	 * from the kernel loop.
 	 */
-#if !defined(ENABLE_LOCKCLOCK)
-	if (clock_ctl.pll_control && loop_started)
+	if (!lockclock && clock_ctl.pll_control && loop_started)
 		set_freq(drift_comp);
-#endif
 }
 
 
@@ -1195,7 +1169,7 @@ huffpuff(void)
 /*
  * loop_config - configure the loop filter
  *
- * ENABLE_LOCKCLOCK: The LOOP_DRIFTINIT and LOOP_DRIFTCOMP cases are no-ops.
+ * If lockclock is on, the LOOP_DRIFTINIT and LOOP_DRIFTCOMP cases are no-ops.
  */
 void
 loop_config(
@@ -1214,8 +1188,7 @@ loop_config(
 	 * variables. Otherwise, continue leaving no harm behind.
 	 */
 	case LOOP_DRIFTINIT:
-#ifndef ENABLE_LOCKCLOCK
-		if (clock_ctl.mode_ntpdate)
+		if (lockclock || clock_ctl.mode_ntpdate)
 			break;
 
 		start_kern_loop();
@@ -1237,13 +1210,11 @@ loop_config(
 		else
 			rstclock(EVNT_NSET, 0);
 		loop_started = true;
-#endif /* !ENABLE_LOCKCLOCK */
 		break;
 
 	case LOOP_KERN_CLEAR:
 #if 0		/* XXX: needs more review, and how can we get here? */
-#ifndef ENABLE_LOCKCLOCK
-		if (clock_ctl.pll_control && clock_ctl.kern_enable) {
+		if (!lockclock && (clock_ctl.pll_control && clock_ctl.kern_enable)) {
 			memset((char *)&ntv, 0, sizeof(ntv));
 			ntv.modes = MOD_STATUS;
 			ntv.status = STA_UNSYNC;
@@ -1252,7 +1223,6 @@ loop_config(
 				pll_status,
 				ntv.status);
 		   }
-#endif /* ENABLE_LOCKCLOCK */
 #endif
 		break;
 
diff --git a/ntpd/ntp_parser.y b/ntpd/ntp_parser.y
index 3794e03b3..66651c08c 100644
--- a/ntpd/ntp_parser.y
+++ b/ntpd/ntp_parser.y
@@ -117,6 +117,7 @@
 %token	<Integer>	T_Limited
 %token	<Integer>	T_Link
 %token	<Integer>	T_Listen
+%token	<Integer>	T_Lockclock
 %token	<Integer>	T_Logconfig
 %token	<Integer>	T_Logfile
 %token	<Integer>	T_Loopstats
@@ -1063,6 +1064,7 @@ tinker_option_keyword
 	|	T_Dispersion
 	|	T_Freq
 	|	T_Huffpuff
+	|	T_Lockclock
 	|	T_Panic
 	|	T_Step
 	|	T_Stepback
diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c
index 42173b73d..d6eabdfee 100644
--- a/ntpd/ntp_proto.c
+++ b/ntpd/ntp_proto.c
@@ -1442,11 +1442,11 @@ clock_filter(
 /*
  * clock_select - find the pick-of-the-litter clock
  *
- * ENABLE_LOCKCLOCK: (1) If the local clock is the prefer peer, it will always
- * be enabled, even if declared falseticker, (2) only the prefer peer
- * can be selected as the system peer, (3) if the external source is
- * down, the system leap bits are set to 11 and the stratum set to
- * infinity.
+ * When lockclock is on: (1) If the local clock is the prefer peer, it
+ * will always be enabled, even if declared falseticker, (2) only the
+ * prefer peer can be selected as the system peer, (3) if the external
+ * source is down, the system leap bits are set to 11 and the stratum
+ * set to infinity.
  */
 void
 clock_select(void)
@@ -1484,11 +1484,11 @@ clock_select(void)
 	 */
 	osys_peer = sys_vars.sys_peer;
 	sys_survivors = 0;
-#ifdef ENABLE_LOCKCLOCK
-	set_sys_leap(LEAP_NOTINSYNC);
-	sys_vars.sys_stratum = STRATUM_UNSPEC;
-	memcpy(&sys_vars.sys_refid, "DOWN", REFIDLEN);
-#endif /* ENABLE_LOCKCLOCK */
+	if (lockclock) {
+		set_sys_leap(LEAP_NOTINSYNC);
+		sys_vars.sys_stratum = STRATUM_UNSPEC;
+		memcpy(&sys_vars.sys_refid, "DOWN", REFIDLEN);
+	}
 
 	/*
 	 * Allocate dynamic space depending on the number of
diff --git a/ntpd/refclock_local.c b/ntpd/refclock_local.c
index 68550e312..277b7ed02 100644
--- a/ntpd/refclock_local.c
+++ b/ntpd/refclock_local.c
@@ -68,6 +68,7 @@ static	void	local_poll	(int, struct peer *);
  */
 static	unsigned long poll_time;	/* last time polled */
 
+
 /*
  * Transfer vector
  */
@@ -116,7 +117,7 @@ local_start(
 /*
  * local_poll - called by the transmit procedure
  *
- * ENABLE_LOCKCLOCK: If the kernel supports the nanokernel or microkernel
+ * If lockclock is on: If the kernel supports the nanokernel or microkernel
  * system calls, the leap bits are extracted from the kernel. If there
  * is a kernel error or the kernel leap bits are set to 11, the NTP leap
  * bits are set to 11 and the stratum is set to infinity. Otherwise, the
@@ -156,36 +157,36 @@ local_poll(
 	 * If another process is disciplining the system clock, we set
 	 * the leap bits and quality indicators from the kernel.
 	 */
-#if defined(ENABLE_LOCKCLOCK)
-	struct timex ntv;
-	memset(&ntv,  0, sizeof ntv);
-	switch (ntp_adjtime(&ntv)) {
-	case TIME_OK:
+	if (lockclock) {
+		struct timex ntv;
+		memset(&ntv,  0, sizeof ntv);
+		switch (ntp_adjtime(&ntv)) {
+		case TIME_OK:
+		    pp->leap = LEAP_NOWARNING;
+		    peer->stratum = pp->stratum;
+		    break;
+
+		case TIME_INS:
+		    pp->leap = LEAP_ADDSECOND;
+		    peer->stratum = pp->stratum;
+		    break;
+
+		case TIME_DEL:
+		    pp->leap = LEAP_DELSECOND;
+		    peer->stratum = pp->stratum;
+		    break;
+
+		default:
+		    pp->leap = LEAP_NOTINSYNC;
+		    peer->stratum = STRATUM_UNSPEC;
+		}
+		pp->disp = 0;
+		pp->jitter = 0;
+	} else {
 		pp->leap = LEAP_NOWARNING;
-		peer->stratum = pp->stratum;
-		break;
-
-	case TIME_INS:
-		pp->leap = LEAP_ADDSECOND;
-		peer->stratum = pp->stratum;
-		break;
-
-	case TIME_DEL:
-		pp->leap = LEAP_DELSECOND;
-		peer->stratum = pp->stratum;
-		break;
-
-	default:
-		pp->leap = LEAP_NOTINSYNC;
-		peer->stratum = STRATUM_UNSPEC;
+		pp->disp = DISPERSION;
+		pp->jitter = 0;
 	}
-	pp->disp = 0;
-	pp->jitter = 0;
-#else /* ENABLE_LOCKCLOCK */
-	pp->leap = LEAP_NOWARNING;
-	pp->disp = DISPERSION;
-	pp->jitter = 0;
-#endif /* ENABLE_LOCKCLOCK */
 	pp->lastref = pp->lastrec;
 	refclock_receive(peer);
 }
diff --git a/wafhelpers/options.py b/wafhelpers/options.py
index 0e77ee8ca..fbbbdbe48 100644
--- a/wafhelpers/options.py
+++ b/wafhelpers/options.py
@@ -48,8 +48,6 @@ def options_cmd(ctx, config):
                    help="Enable leaps on other than 1st of month.")
     grp.add_option('--enable-mssntp', action='store_true',
                    default=False, help="Enable Samba MS SNTP support.")
-    grp.add_option('--enable-lockclock', action='store_true',
-                   default=False, help="Enable NIST lockclock scheme.")
 
     grp = ctx.add_option_group("Refclock configure options")
     grp.add_option(
diff --git a/wscript b/wscript
index d37775669..c7c3ecaea 100644
--- a/wscript
+++ b/wscript
@@ -741,15 +741,6 @@ int main(int argc, char **argv) {
                    comment="Enable MS-SNTP extensions "
                    " https://msdn.microsoft.com/en-us/library/cc212930.aspx";)
 
-    if ctx.options.enable_lockclock:
-        if ctx.env.REFCLOCK_LOCAL:
-            ctx.define("ENABLE_LOCKCLOCK", 1,
-                       comment="Enable NIST 'lockclock'")
-        else:
-            import waflib.Errors
-            raise waflib.Errors.WafError(
-                "NIST 'lockclock' requires refclock 'local'")
-
     if not ctx.options.disable_droproot:
         ctx.define("ENABLE_DROPROOT", 1,
                    comment="Drop root after initialising")
-- 
2.17.1

_______________________________________________
devel mailing list
devel@ntpsec.org
http://lists.ntpsec.org/mailman/listinfo/devel

Reply via email to