* 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
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
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 *);
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;
{"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},
/* ================================================== */
+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)
{
/* ================================================== */
+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)
{
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);
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;
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);
/* ================================================== */
+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)
{
}
}
+ 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;
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) {