diff options
Diffstat (limited to 'reference.c')
-rw-r--r-- | reference.c | 122 |
1 files changed, 23 insertions, 99 deletions
diff --git a/reference.c b/reference.c index 97dfbe9..bb2c48a 100644 --- a/reference.c +++ b/reference.c @@ -4,6 +4,7 @@ ********************************************************************** * Copyright (C) Richard P. Curnow 1997-2003 * Copyright (C) Miroslav Lichvar 2009-2018, 2020, 2022 + * Copyright (C) Andy Fiddaman 2024 * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -33,6 +34,7 @@ #include "reference.h" #include "util.h" #include "conf.h" +#include "leapdb.h" #include "logging.h" #include "local.h" #include "sched.h" @@ -53,6 +55,8 @@ static int enable_local_stratum; static int local_stratum; static int local_orphan; static double local_distance; +static int local_activate_ok; +static double local_activate; static struct timespec local_ref_time; static NTP_Leap our_leap_status; static int our_leap_sec; @@ -122,9 +126,6 @@ static int leap_in_progress; /* Timer for the leap second handler */ static SCH_TimeoutID leap_timeout_id; -/* Name of a system timezone containing leap seconds occuring at midnight */ -static char *leap_tzname; - /* ================================================== */ static LOG_FileID logfileid; @@ -155,7 +156,6 @@ static int ref_adjustments; /* ================================================== */ -static NTP_Leap get_tz_leap(time_t when, int *tai_offset); static void update_leap_status(NTP_Leap leap, time_t now, int reset); /* ================================================== */ @@ -195,7 +195,6 @@ REF_Initialise(void) FILE *in; double file_freq_ppm, file_skew_ppm; double our_frequency_ppm; - int tai_offset; mode = REF_ModeNormal; are_we_synchronised = 0; @@ -211,6 +210,7 @@ REF_Initialise(void) our_frequency_sd = 0.0; our_offset_sd = 0.0; drift_file_age = 0.0; + local_activate_ok = 0; /* Now see if we can get the drift file opened */ drift_file = CNF_GetDriftFile(); @@ -249,7 +249,8 @@ REF_Initialise(void) correction_time_ratio = CNF_GetCorrectionTimeRatio(); - enable_local_stratum = CNF_AllowLocalReference(&local_stratum, &local_orphan, &local_distance); + enable_local_stratum = CNF_AllowLocalReference(&local_stratum, &local_orphan, + &local_distance, &local_activate); UTI_ZeroTimespec(&local_ref_time); leap_when = 0; @@ -260,18 +261,6 @@ REF_Initialise(void) if (leap_mode == REF_LeapModeSystem && !LCL_CanSystemLeap()) leap_mode = REF_LeapModeStep; - leap_tzname = CNF_GetLeapSecTimezone(); - if (leap_tzname) { - /* Check that the timezone has good data for Jun 30 2012 and Dec 31 2012 */ - if (get_tz_leap(1341014400, &tai_offset) == LEAP_InsertSecond && tai_offset == 34 && - get_tz_leap(1356912000, &tai_offset) == LEAP_Normal && tai_offset == 35) { - LOG(LOGS_INFO, "Using %s timezone to obtain leap second data", leap_tzname); - } else { - LOG(LOGS_WARN, "Timezone %s failed leap second check, ignoring", leap_tzname); - leap_tzname = NULL; - } - } - CNF_GetMakeStep(&make_step_limit, &make_step_threshold); CNF_GetMaxChange(&max_offset_delay, &max_offset_ignore, &max_offset); CNF_GetMailOnChange(&do_mail_change, &mail_change_threshold, &mail_change_user); @@ -593,77 +582,6 @@ is_leap_second_day(time_t when) /* ================================================== */ -static NTP_Leap -get_tz_leap(time_t when, int *tai_offset) -{ - static time_t last_tz_leap_check; - static NTP_Leap tz_leap; - static int tz_tai_offset; - - struct tm stm, *tm; - time_t t; - char *tz_env, tz_orig[128]; - - *tai_offset = tz_tai_offset; - - /* Do this check at most twice a day */ - when = when / (12 * 3600) * (12 * 3600); - if (last_tz_leap_check == when) - return tz_leap; - - last_tz_leap_check = when; - tz_leap = LEAP_Normal; - tz_tai_offset = 0; - - tm = gmtime(&when); - if (!tm) - return tz_leap; - - stm = *tm; - - /* Temporarily switch to the timezone containing leap seconds */ - tz_env = getenv("TZ"); - if (tz_env) { - if (strlen(tz_env) >= sizeof (tz_orig)) - return tz_leap; - strcpy(tz_orig, tz_env); - } - setenv("TZ", leap_tzname, 1); - tzset(); - - /* Get the TAI-UTC offset, which started at the epoch at 10 seconds */ - t = mktime(&stm); - if (t != -1) - tz_tai_offset = t - when + 10; - - /* Set the time to 23:59:60 and see how it overflows in mktime() */ - stm.tm_sec = 60; - stm.tm_min = 59; - stm.tm_hour = 23; - - t = mktime(&stm); - - if (tz_env) - setenv("TZ", tz_orig, 1); - else - unsetenv("TZ"); - tzset(); - - if (t == -1) - return tz_leap; - - if (stm.tm_sec == 60) - tz_leap = LEAP_InsertSecond; - else if (stm.tm_sec == 1) - tz_leap = LEAP_DeleteSecond; - - *tai_offset = tz_tai_offset; - - return tz_leap; -} - -/* ================================================== */ - static void leap_end_timeout(void *arg) { @@ -751,16 +669,16 @@ set_leap_timeout(time_t now) static void update_leap_status(NTP_Leap leap, time_t now, int reset) { - NTP_Leap tz_leap; + NTP_Leap ldb_leap; int leap_sec, tai_offset; leap_sec = 0; tai_offset = 0; - if (leap_tzname && now) { - tz_leap = get_tz_leap(now, &tai_offset); + if (now) { + ldb_leap = LDB_GetLeap(now, &tai_offset); if (leap == LEAP_Normal) - leap = tz_leap; + leap = ldb_leap; } if (leap == LEAP_InsertSecond || leap == LEAP_DeleteSecond) { @@ -1219,7 +1137,7 @@ REF_GetReferenceParams double *root_dispersion ) { - double dispersion, delta; + double dispersion, delta, distance; assert(initialised); @@ -1229,11 +1147,16 @@ REF_GetReferenceParams dispersion = 0.0; } + distance = our_root_delay / 2 + dispersion; + + if (local_activate == 0.0 || (are_we_synchronised && distance < local_activate)) + local_activate_ok = 1; + /* Local reference is active when enabled and the clock is not synchronised or the root distance exceeds the threshold */ if (are_we_synchronised && - !(enable_local_stratum && our_root_delay / 2 + dispersion > local_distance)) { + !(enable_local_stratum && local_activate_ok && distance > local_distance)) { *is_synchronised = 1; @@ -1245,7 +1168,7 @@ REF_GetReferenceParams *root_delay = our_root_delay; *root_dispersion = dispersion; - } else if (enable_local_stratum) { + } else if (enable_local_stratum && local_activate_ok) { *is_synchronised = 0; @@ -1345,12 +1268,13 @@ REF_ModifyMakestep(int limit, double threshold) /* ================================================== */ void -REF_EnableLocal(int stratum, double distance, int orphan) +REF_EnableLocal(int stratum, double distance, int orphan, double activate) { enable_local_stratum = 1; local_stratum = CLAMP(1, stratum, NTP_MAX_STRATUM - 1); local_distance = distance; local_orphan = !!orphan; + local_activate = activate; LOG(LOGS_INFO, "%s local reference mode", "Enabled"); } @@ -1368,7 +1292,7 @@ REF_DisableLocal(void) #define LEAP_SECOND_CLOSE 5 static int -is_leap_close(time_t t) +is_leap_close(double t) { return leap_when != 0 && t >= leap_when - LEAP_SECOND_CLOSE && t < leap_when + LEAP_SECOND_CLOSE; @@ -1398,7 +1322,7 @@ REF_GetTaiOffset(struct timespec *ts) { int tai_offset; - get_tz_leap(ts->tv_sec, &tai_offset); + LDB_GetLeap(ts->tv_sec, &tai_offset); return tai_offset; } |