summaryrefslogtreecommitdiffstats
path: root/reference.c
diff options
context:
space:
mode:
Diffstat (limited to 'reference.c')
-rw-r--r--reference.c122
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;
}