]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
sources: add require option
authorMiroslav Lichvar <mlichvar@redhat.com>
Thu, 7 Jan 2016 15:17:17 +0000 (16:17 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Fri, 8 Jan 2016 13:30:17 +0000 (14:30 +0100)
Require that at least one of the sources specified with this option is
selectable (i.e. recently reachable and not a falseticker) before
updating the clock. Together with the trust option this may be useful to
allow a trusted, but not very precise, reference clock or a trusted
authenticated NTP source to be safely combined with unauthenticated NTP
sources in order to improve the accuracy of the clock. They can be
selected and used for synchronization only if they agree with the
trusted and required source.

candm.h
chrony.texi.in
client.c
cmdmon.c
cmdparse.c
conf.c
sources.c
srcparams.h

diff --git a/candm.h b/candm.h
index 5b7c8d285223274369e54e2b08d0f199401471de..cf7c317dca9e56da81731f339e4740313aa49e51 100644 (file)
--- a/candm.h
+++ b/candm.h
@@ -244,6 +244,7 @@ typedef struct {
 #define REQ_ADDSRC_PREFER 0x8
 #define REQ_ADDSRC_NOSELECT 0x10
 #define REQ_ADDSRC_TRUST 0x20
+#define REQ_ADDSRC_REQUIRE 0x40
 
 typedef struct {
   IPAddr ip_addr;
@@ -480,6 +481,7 @@ typedef struct {
 #define RPY_SD_FLAG_NOSELECT 0x1
 #define RPY_SD_FLAG_PREFER 0x2
 #define RPY_SD_FLAG_TRUST 0x4
+#define RPY_SD_FLAG_REQUIRE 0x8
 
 typedef struct {
   IPAddr ip_addr;
index 73f90234242b47c88e977b4eac5ead41e91dafac..dc8f817377498f6629d67b62e9df83ebe031e221 100644 (file)
@@ -2724,6 +2724,14 @@ which are not very accurate, but are locked with a PPS refclock.
 Assume time from this source is always true.  It can't be rejected as a
 falseticker in the source selection if sources that are specified without this
 option don't agree with it.
+@item require
+Require that at least one of the sources specified with this option is
+selectable (i.e. recently reachable and not a falseticker) before updating the
+clock.  Together with the @code{trust} option this may be useful to allow a
+trusted, but not very precise, reference clock to be safely combined with
+unauthenticated NTP sources in order to improve the accuracy of the clock.
+They can be selected and used for synchronisation only if they agree with
+the trusted and required source.
 @item minsamples
 Set the minimum number of samples kept for this source.  This overrides the
 @code{minsamples} directive (@pxref{minsamples directive}).
@@ -3033,6 +3041,14 @@ Assume time from this source is always true.  It can't be rejected as a
 falseticker in the source selection if sources that are specified without this
 option don't agree with it.
 
+@item require
+Require that at least one of the sources specified with this option is
+selectable (i.e. recently reachable and not a falseticker) before updating the
+clock.  Together with the @code{trust} option this may be useful to allow a
+trusted authenticated source to be safely combined with unauthenticated sources
+in order to improve the accuracy of the clock.  They can be selected and used
+for synchronisation only if they agree with the trusted and required source.
+
 @item minsamples
 Set the minimum number of samples kept for this source.  This overrides the
 @code{minsamples} directive (@pxref{minsamples directive}).
index aa7271a36253291c97f6fab992ffc5a0c5f008d8..728f14e045f27c25a850e9f26421b8d6477f1a2b 100644 (file)
--- a/client.c
+++ b/client.c
@@ -1119,7 +1119,8 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
           (data.params.iburst ? REQ_ADDSRC_IBURST : 0) |
           (data.params.sel_options & SRC_SELECT_PREFER ? REQ_ADDSRC_PREFER : 0) |
           (data.params.sel_options & SRC_SELECT_NOSELECT ? REQ_ADDSRC_NOSELECT : 0) |
-          (data.params.sel_options & SRC_SELECT_TRUST ? REQ_ADDSRC_TRUST : 0));
+          (data.params.sel_options & SRC_SELECT_TRUST ? REQ_ADDSRC_TRUST : 0) |
+          (data.params.sel_options & SRC_SELECT_REQUIRE ? REQ_ADDSRC_REQUIRE : 0));
       result = 1;
 
       break;
index ae2a10c255d6a8e6ed20a4f459999b49742fe254..3322cb7ec735b17b73dd7720cc6cc0bc21a51ba4 100644 (file)
--- a/cmdmon.c
+++ b/cmdmon.c
@@ -664,7 +664,8 @@ handle_source_data(CMD_Request *rx_message, CMD_Reply *tx_message)
     tx_message->data.source_data.flags =
                   htons((report.sel_options & SRC_SELECT_PREFER ? RPY_SD_FLAG_PREFER : 0) |
                         (report.sel_options & SRC_SELECT_NOSELECT ? RPY_SD_FLAG_NOSELECT : 0) |
-                        (report.sel_options & SRC_SELECT_TRUST ? RPY_SD_FLAG_TRUST : 0));
+                        (report.sel_options & SRC_SELECT_TRUST ? RPY_SD_FLAG_TRUST : 0) |
+                        (report.sel_options & SRC_SELECT_REQUIRE ? RPY_SD_FLAG_REQUIRE : 0));
     tx_message->data.source_data.reachability = htons(report.reachability);
     tx_message->data.source_data.since_sample = htonl(report.latest_meas_ago);
     tx_message->data.source_data.orig_latest_meas = UTI_FloatHostToNetwork(report.orig_latest_meas);
@@ -760,7 +761,8 @@ handle_add_source(NTP_Source_Type type, CMD_Request *rx_message, CMD_Reply *tx_m
   params.sel_options =
     (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_PREFER ? SRC_SELECT_PREFER : 0) |
     (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_NOSELECT ? SRC_SELECT_NOSELECT : 0) |
-    (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_TRUST ? SRC_SELECT_TRUST : 0);
+    (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_TRUST ? SRC_SELECT_TRUST : 0) |
+    (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_REQUIRE ? SRC_SELECT_REQUIRE : 0);
   params.max_delay = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay);
   params.max_delay_ratio = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay_ratio);
 
index 976e69650ce19d9723826d0fc736b821c1bd79fe..591e2e46411f52049debf97411cc4b6349bcf250 100644 (file)
@@ -173,6 +173,9 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
         } else if (!strcasecmp(cmd, "trust")) {
           src->params.sel_options |= SRC_SELECT_TRUST;
 
+        } else if (!strcasecmp(cmd, "require")) {
+          src->params.sel_options |= SRC_SELECT_REQUIRE;
+
         } else if (!strcasecmp(cmd, "version")) {
           if (sscanf(line, "%d%n", &src->params.version, &n) != 1) {
             result = CPS_BadVersion;
diff --git a/conf.c b/conf.c
index 8260de622cf4472b69d402f1786a3b9b1f7cf65b..df3d0806d379e6466827e8e254ccc4484b37451d 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -746,6 +746,9 @@ parse_refclock(char *line)
     } else if (!strcasecmp(cmd, "trust")) {
       n = 0;
       sel_options |= SRC_SELECT_TRUST;
+    } else if (!strcasecmp(cmd, "require")) {
+      n = 0;
+      sel_options |= SRC_SELECT_REQUIRE;
     } else {
       other_parse_error("Invalid refclock option");
       return;
index 2e48c5fc38836c1d2f8b2509e483f788c3527783..cee2cbf2f9fff23e12655bb2f96dfaa86a01e356 100644 (file)
--- a/sources.c
+++ b/sources.c
@@ -602,7 +602,7 @@ SRC_SelectSource(SRC_Instance updated_inst)
   struct SelectInfo *si;
   struct timeval now, ref_time;
   int i, j, j1, j2, index, sel_prefer, n_endpoints, n_sel_sources;
-  int n_badstats_sources, max_sel_reach, max_badstat_reach;
+  int n_badstats_sources, max_sel_reach, max_badstat_reach, sel_req_source;
   int depth, best_depth, trust_depth, best_trust_depth;
   int combined, stratum, min_stratum, max_score_index;
   double src_offset, src_offset_sd, src_frequency, src_skew;
@@ -631,12 +631,18 @@ SRC_SelectSource(SRC_Instance updated_inst)
   n_endpoints = 0;
   n_sel_sources = 0;
   n_badstats_sources = 0;
+  sel_req_source = 0;
   max_sel_reach = max_badstat_reach = 0;
   max_reach_sample_ago = 0.0;
 
   for (i = 0; i < n_sources; i++) {
     assert(sources[i]->status != SRC_OK);
 
+    /* If some sources are specified with the require option, at least one
+       of them will have to be selectable in order to update the clock */
+    if (sources[i]->sel_options & SRC_SELECT_REQUIRE)
+      sel_req_source = 1;
+
     /* Ignore sources which were added with the noselect option */
     if (sources[i]->sel_options & SRC_SELECT_NOSELECT) {
       sources[i]->status = SRC_UNSELECTABLE;
@@ -825,15 +831,19 @@ SRC_SelectSource(SRC_Instance updated_inst)
          sources[i]->sel_info.hi_limit <= best_hi)) {
 
       sel_sources[n_sel_sources++] = i;
+
+      if (sources[i]->sel_options & SRC_SELECT_REQUIRE)
+        sel_req_source = 0;
     } else {
       sources[i]->status = SRC_FALSETICKER;
     }
   }
 
-  if (n_sel_sources == 0 || n_sel_sources < CNF_GetMinSources()) {
+  if (!n_sel_sources || sel_req_source || n_sel_sources < CNF_GetMinSources()) {
     if (selected_source_index != INVALID_SOURCE) {
       log_selection_message("Can't synchronise: %s selectable sources",
-                            n_sel_sources ? "not enough" : "no");
+                            !n_sel_sources ? "no" :
+                            sel_req_source ? "no required source in" : "not enough");
       selected_source_index = INVALID_SOURCE;
     }
     mark_ok_sources(SRC_WAITS_SOURCES);
index 15fb6f28aa670fcb3cc46dfa3c7cc92cbfcc8ba2..42a1555b0c9c3d509ef89609515bc70c642b9552 100644 (file)
@@ -67,5 +67,6 @@ typedef struct {
 #define SRC_SELECT_NOSELECT 0x1
 #define SRC_SELECT_PREFER 0x2
 #define SRC_SELECT_TRUST 0x4
+#define SRC_SELECT_REQUIRE 0x8
 
 #endif /* GOT_SRCPARAMS_H */