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