]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Add maxchange directive
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 21 Feb 2012 13:34:09 +0000 (14:34 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 21 Feb 2012 13:34:09 +0000 (14:34 +0100)
This directive sets the maximum allowed offset corrected on a clock
update.  The check is performed only after the specified number of
updates to allow a large initial adjustment of the system clock.  When
an offset larger than the specified maximum occurs, it will be ignored
for the specified number of times and then chronyd will give up
and exit (a negative value can be used to never exit).  In both cases
a message is sent to syslog.

chrony.texi
conf.c
conf.h
reference.c

index f45cdde8e308054c21ec0c4580c8ffafd4db745a..9b75eff6fefc04e5dfe750a499e4d9faf01fa5ae 100644 (file)
@@ -1192,6 +1192,7 @@ directives can occur in any order in the file.
 * logdir directive::            Specify directory for logging
 * mailonchange directive::      Send email if a clock correction above a threshold occurs
 * makestep directive::          Step system clock if large correction is needed
+* maxchange directive::         Set maximum allowed offset
 * manual directive::            Allow manual entry using chronyc's settime cmd.
 * maxclockerror directive::     Set maximum frequency error of local clock
 * maxupdateskew directive::     Stop bad estimates upsetting machine clock
@@ -2244,6 +2245,27 @@ makestep 1000 10
 This would step system clock if the adjustment is larger than 1000
 seconds, but only in the first ten clock updates.
 @c }}}
+@c {{{ maxchange
+@node maxchange directive
+@subsection maxchange
+This directive sets the maximum allowed offset corrected on a clock
+update.  The check is performed only after the specified number of
+updates to allow a large initial adjustment of the system clock.  When
+an offset larger than the specified maximum occurs, it will be ignored
+for the specified number of times and then @code{chronyd} will give up
+and exit (a negative value can be used to never exit).  In both cases
+a message is sent to syslog.
+
+An example of the use of this directive is
+
+@example
+maxchange 1000 1 2
+@end example
+
+After the first clock update, @code{chronyd} will check the offset on
+every clock update, it will ignore two adjustments larger than 1000
+seconds and exit on another one.
+@c }}}
 @c {{{ manual
 @node manual directive
 @subsection manual
diff --git a/conf.c b/conf.c
index c8df69e85a239c95fa4f281fa1292711023152e9..bbd890c417bb2a6953fced393b3890060efd55e2 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -98,6 +98,7 @@ static void parse_noclientlog(const char *);
 static void parse_clientloglimit(const char *);
 static void parse_fallbackdrift(const char *);
 static void parse_makestep(const char *);
+static void parse_maxchange(const char *);
 static void parse_logchange(const char *);
 static void parse_mailonchange(const char *);
 static void parse_bindaddress(const char *);
@@ -168,6 +169,12 @@ static int rtc_sync = 0;
 static int make_step_limit = 0;
 static double make_step_threshold = 0.0;
 
+/* Number of updates before offset checking, number of ignored updates
+   before exiting and the maximum allowed offset */
+static int max_offset_delay = -1;
+static int max_offset_ignore;
+static double max_offset;
+
 /* Flag set if we should log to syslog when a time adjustment
    exceeding the threshold is initiated */
 static int do_log_change = 0;
@@ -257,6 +264,7 @@ static const Command commands[] = {
   {"clientloglimit", 14, parse_clientloglimit},
   {"fallbackdrift", 13, parse_fallbackdrift},
   {"makestep", 8, parse_makestep},
+  {"maxchange", 9, parse_maxchange},
   {"logchange", 9, parse_logchange},
   {"mailonchange", 12, parse_mailonchange},
   {"bindaddress", 11, parse_bindaddress},
@@ -943,6 +951,19 @@ parse_makestep(const char *line)
 
 /* ================================================== */
 
+static void
+parse_maxchange(const char *line)
+{
+  if (sscanf(line, "%lf %d %d", &max_offset, &max_offset_delay, &max_offset_ignore) != 3) {
+    max_offset_delay = -1;
+    LOG(LOGS_WARN, LOGF_Configure,
+        "Could not read offset, check delay or ignore limit for maximum change at line %d\n",
+        line_number);
+  }
+}
+
+/* ================================================== */
+
 static void
 parse_logchange(const char *line)
 {
@@ -1567,6 +1588,16 @@ CNF_GetMakeStep(int *limit, double *threshold)
 
 /* ================================================== */
 
+void
+CNF_GetMaxChange(int *delay, int *ignore, double *offset)
+{
+  *delay = max_offset_delay;
+  *ignore = max_offset_ignore;
+  *offset = max_offset;
+}
+
+/* ================================================== */
+
 void
 CNF_GetLogChange(int *enabled, double *threshold)
 {
diff --git a/conf.h b/conf.h
index 4c208c75c93a74e4342098056adf76ef55613a45..7f0f6b3e9f35ec126f8ea90bce8e33534ad2d4c1 100644 (file)
--- a/conf.h
+++ b/conf.h
@@ -60,6 +60,7 @@ extern int CNF_GetCommandPort(void);
 extern int CNF_GetRTCOnUTC(void);
 extern int CNF_GetRTCSync(void);
 extern void CNF_GetMakeStep(int *limit, double *threshold);
+extern void CNF_GetMaxChange(int *delay, int *ignore, double *offset);
 extern void CNF_GetLogChange(int *enabled, double *threshold);
 extern void CNF_GetMailOnChange(int *enabled, double *threshold, char **user);
 extern int CNF_GetNoClientLog(void);
index 7c8f5d0247a37f76c301ca5e61b8791ca44c6dff..7bf8ec7c9ab1df4342917c6d2fbe8de0dcfe0460 100644 (file)
@@ -68,6 +68,12 @@ static int initialised = 0;
 static int make_step_limit;
 static double make_step_threshold;
 
+/* Number of updates before offset checking, number of ignored updates
+   before exiting and the maximum allowed offset */
+static int max_offset_delay;
+static int max_offset_ignore;
+static double max_offset;
+
 /* Flag and threshold for logging clock changes to syslog */
 static int do_log_change;
 static double log_change_threshold;
@@ -191,6 +197,7 @@ REF_Initialise(void)
   enable_local_stratum = CNF_AllowLocalReference(&local_stratum);
 
   CNF_GetMakeStep(&make_step_limit, &make_step_threshold);
+  CNF_GetMaxChange(&max_offset_delay, &max_offset_ignore, &max_offset);
   CNF_GetLogChange(&do_log_change, &log_change_threshold);
   CNF_GetMailOnChange(&do_mail_change, &mail_change_threshold, &mail_change_user);
 
@@ -492,6 +499,33 @@ maybe_make_step()
 
 /* ================================================== */
 
+static int
+is_offset_ok(double offset)
+{
+  if (max_offset_delay < 0)
+    return 1;
+
+  if (max_offset_delay > 0) {
+    max_offset_delay--;
+    return 1;
+  }
+
+  offset = fabs(offset);
+  if (offset > max_offset) {
+    LOG(LOGS_WARN, LOGF_Reference,
+        "Adjustment of %.3f seconds exceeds the allowed maximum of %.3f seconds (%s) ",
+        offset, max_offset, !max_offset_ignore ? "exiting" : "ignored");
+    if (!max_offset_ignore)
+      SCH_QuitProgram();
+    else if (max_offset_ignore > 0)
+      max_offset_ignore--;
+    return 0;
+  }
+  return 1;
+}
+
+/* ================================================== */
+
 static void
 update_leap_status(NTP_Leap leap)
 {
@@ -594,6 +628,12 @@ REF_SetReference(int stratum,
     }
   }
     
+  LCL_ReadCookedTime(&now, NULL);
+  UTI_DiffTimevalsToDouble(&elapsed, &now, ref_time);
+  our_offset = offset + elapsed * frequency;
+
+  if (!is_offset_ok(offset))
+    return;
 
   are_we_synchronised = 1;
   our_stratum = stratum + 1;
@@ -606,10 +646,6 @@ REF_SetReference(int stratum,
   our_root_delay = root_delay;
   our_root_dispersion = root_dispersion;
 
-  LCL_ReadCookedTime(&now, NULL);
-  UTI_DiffTimevalsToDouble(&elapsed, &now, ref_time);
-  our_offset = offset + elapsed * frequency;
-
   update_leap_status(leap);
 
   if (last_ref_update.tv_sec) {