]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
cmdmon+client: add selectopts command
authorMiroslav Lichvar <mlichvar@redhat.com>
Wed, 14 Dec 2022 15:04:43 +0000 (16:04 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Wed, 14 Dec 2022 16:04:49 +0000 (17:04 +0100)
This command uses the new source function to modify configured selection
options of an NTP source or reference clock.

candm.h
client.c
cmdmon.c
doc/chronyc.adoc
pktlength.c
test/simulation/110-chronyc
test/system/007-cmdmon

diff --git a/candm.h b/candm.h
index 30718282f3e443bc8647926397ff25c3258509e5..e7423233e5c9f2b10c03acc9a33ab0ff74d01f9e 100644 (file)
--- a/candm.h
+++ b/candm.h
 #define REQ_SELECT_DATA 69
 #define REQ_RELOAD_SOURCES 70
 #define REQ_DOFFSET2 71
-#define N_REQUEST_TYPES 72
+#define REQ_MODIFY_SELECTOPTS 72
+#define N_REQUEST_TYPES 73
 
 /* Structure used to exchange timespecs independent of time_t size */
 typedef struct {
@@ -371,6 +372,15 @@ typedef struct {
   int32_t EOR;
 } REQ_SelectData;
 
+/* Mask and options reuse the REQ_ADDSRC flags */
+typedef struct {
+  IPAddr address;
+  uint32_t ref_id;
+  uint32_t mask;
+  uint32_t options;
+  int32_t EOR;
+} REQ_Modify_SelectOpts;
+
 /* ================================================== */
 
 #define PKT_TYPE_CMD_REQUEST 1
@@ -477,6 +487,7 @@ typedef struct {
     REQ_NTPSourceName ntp_source_name;
     REQ_AuthData auth_data;
     REQ_SelectData select_data;
+    REQ_Modify_SelectOpts modify_select_opts;
   } data; /* Command specific parameters */
 
   /* Padding used to prevent traffic amplification.  It only defines the
index e15747d32a387aae965f3ff50429ef0f0946f23a..ad731b05412422c0400c4bad9d65218a1c3315d7 100644 (file)
--- a/client.c
+++ b/client.c
@@ -1021,6 +1021,7 @@ give_help(void)
     "sources [-a] [-v]\0Display information about current sources\0"
     "sourcestats [-a] [-v]\0Display statistics about collected measurements\0"
     "selectdata [-a] [-v]\0Display information about source selection\0"
+    "selectopts <address|refid> <+|-options>\0Modify selection options\0"
     "reselect\0Force reselecting synchronisation source\0"
     "reselectdist <dist>\0Modify reselection distance\0"
     "\0\0"
@@ -1135,8 +1136,8 @@ command_name_generator(const char *text, int state)
     "manual", "maxdelay", "maxdelaydevratio", "maxdelayratio", "maxpoll",
     "maxupdateskew", "minpoll", "minstratum", "ntpdata", "offline", "online", "onoffline",
     "polltarget", "quit", "refresh", "rekey", "reload", "reselect", "reselectdist", "reset",
-    "retries", "rtcdata", "selectdata", "serverstats", "settime", "shutdown", "smoothing",
-    "smoothtime", "sourcename", "sources", "sourcestats",
+    "retries", "rtcdata", "selectdata", "selectopts", "serverstats", "settime",
+    "shutdown", "smoothing", "smoothtime", "sourcename", "sources", "sourcestats",
     "timeout", "tracking", "trimrtc", "waitsync", "writertc",
     NULL
   };
@@ -2899,6 +2900,55 @@ process_cmd_reset(CMD_Request *msg, char *line)
 
 /* ================================================== */
 
+static int
+process_cmd_selectopts(CMD_Request *msg, char *line)
+{
+  int mask, options, option;
+  uint32_t ref_id;
+  IPAddr ip_addr;
+  char *src, *opt;
+
+  src = line;
+  line = CPS_SplitWord(line);
+  ref_id = 0;
+
+  /* Don't allow hostnames to avoid conflicts with reference IDs */
+  if (!UTI_StringToIdIP(src, &ip_addr) && !UTI_StringToIP(src, &ip_addr)) {
+    ip_addr.family = IPADDR_UNSPEC;
+    if (CPS_ParseRefid(src, &ref_id) == 0) {
+      LOG(LOGS_ERR, "Invalid syntax for selectopts command");
+      return 0;
+    }
+  }
+
+  mask = options = 0;
+
+  while (*line != '\0') {
+    opt = line;
+    line = CPS_SplitWord(line);
+
+    if ((opt[0] != '+' && opt[0] != '-') || (option = CPS_GetSelectOption(opt + 1)) == 0) {
+      LOG(LOGS_ERR, "Invalid syntax for selectopts command");
+      return 0;
+    }
+
+    mask |= option;
+    if (opt[0] == '+')
+      options |= option;
+  }
+
+  UTI_IPHostToNetwork(&ip_addr, &msg->data.modify_select_opts.address);
+  msg->data.modify_select_opts.ref_id = htonl(ref_id);
+  msg->data.modify_select_opts.mask = htonl(mask);
+  msg->data.modify_select_opts.options = htonl(convert_addsrc_sel_options(options));
+
+  msg->command = htons(REQ_MODIFY_SELECTOPTS);
+
+  return 1;
+}
+
+/* ================================================== */
+
 static int
 process_cmd_waitsync(char *line)
 {
@@ -3201,6 +3251,8 @@ process_line(char *line)
   } else if (!strcmp(command, "selectdata")) {
     do_normal_submit = 0;
     ret = process_cmd_selectdata(line);
+  } else if (!strcmp(command, "selectopts")) {
+    do_normal_submit = process_cmd_selectopts(&tx_message, line);
   } else if (!strcmp(command, "serverstats")) {
     do_normal_submit = 0;
     ret = process_cmd_serverstats(line);
index d513cabddda59e3c66b0d2dfc0b264328e9bc8a6..cdb1d861892dfc4e7ad86b0f86e4083e3044ca05 100644 (file)
--- a/cmdmon.c
+++ b/cmdmon.c
@@ -144,6 +144,7 @@ static const char permissions[] = {
   PERMIT_AUTH, /* SELECT_DATA */
   PERMIT_AUTH, /* RELOAD_SOURCES */
   PERMIT_AUTH, /* DOFFSET2 */
+  PERMIT_AUTH, /* MODIFY_SELECTOPTS */
 };
 
 /* ================================================== */
@@ -1370,6 +1371,24 @@ handle_select_data(CMD_Request *rx_message, CMD_Reply *tx_message)
   tx_message->data.select_data.lo_limit = UTI_FloatHostToNetwork(report.lo_limit);
 }
 
+/* ================================================== */
+
+static void
+handle_modify_selectopts(CMD_Request *rx_message, CMD_Reply *tx_message)
+{
+  int mask, options;
+  uint32_t ref_id;
+  IPAddr ip_addr;
+
+  UTI_IPNetworkToHost(&rx_message->data.modify_select_opts.address, &ip_addr);
+  ref_id = ntohl(rx_message->data.modify_select_opts.ref_id);
+  mask = ntohl(rx_message->data.modify_select_opts.mask);
+  options = convert_addsrc_select_options(ntohl(rx_message->data.modify_select_opts.options));
+
+  if (!SRC_ModifySelectOptions(&ip_addr, ref_id, options, mask))
+    tx_message->status = htons(STT_NOSUCHSOURCE);
+}
+
 /* ================================================== */
 /* Read a packet and process it */
 
@@ -1766,6 +1785,10 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
           handle_reload_sources(&rx_message, &tx_message);
           break;
 
+        case REQ_MODIFY_SELECTOPTS:
+          handle_modify_selectopts(&rx_message, &tx_message);
+          break;
+
         default:
           DEBUG_LOG("Unhandled command %d", rx_command);
           tx_message.status = htons(STT_FAILED);
index 57300eeca8e38e8e64cc932cbcef39d74dbf056f..ca261c724ae2026d950bf2b4b38a42a37cc99c80 100644 (file)
@@ -522,6 +522,23 @@ This column displays the current leap status of the source.
 * _-_ indicates that a leap second will be deleted at the end of the month.
 * _?_ indicates the unknown status (i.e. no valid measurement was made).
 
+[[selectopts]]*selectopts* _address|refid_ [_+|-option_]...::
+The *selectopts* command modifies the configured selection options of an NTP
+source specified by IP address (or the _ID#XXXXXXXXXX_ identifier used for
+unknown addresses), or a reference clock specified by reference ID as a string.
++
+The selection options can be added with the *+* symbol or removed with the *-*
+symbol. The *selectdata* command can be used to verify the configuration. The
+modified options will be applied in the next source selection, e.g. when a new
+measurement is made, or the *reselect* command is executed.
++
+An example of using this command is shown below.
++
+----
+selectopts 1.2.3.4 -noselect +prefer
+selectopts GPS +trust
+----
+
 [[reselect]]*reselect*::
 To avoid excessive switching between sources, *chronyd* can stay synchronised
 to a source even when it is not currently the best one among the available
index 642e47757c903dc7b2d666d5ddca80cf0ec289e7..263b16dcdaf84f79145f8be2e77feed84f513dec 100644 (file)
@@ -129,6 +129,7 @@ static const struct request_length request_lengths[] = {
   REQ_LENGTH_ENTRY(select_data, select_data),   /* SELECT_DATA */
   REQ_LENGTH_ENTRY(null, null),                 /* RELOAD_SOURCES */
   REQ_LENGTH_ENTRY(doffset, null),              /* DOFFSET2 */
+  REQ_LENGTH_ENTRY(modify_select_opts, null),   /* MODIFY_SELECTOPTS */
 };
 
 static const uint16_t reply_lengths[] = {
index b78f0d84561dddafbb5ee84e7d769983a5e50a3e..7ecfcb57fd9ac5106a4b324188bfd87a21ca9dca 100755 (executable)
@@ -164,6 +164,9 @@ for chronyc_conf in \
        "reselectdist 1e-3" \
        "reset sources" \
        "selectdata" \
+       "selectopts 1.2.3.4 -noselect +trust +require +prefer" \
+       "selectopts ID#0000000001 +prefer" \
+       "selectopts PPS0 +prefer" \
        "settime 16:30" \
        "settime 16:30:05" \
        "settime Nov 21, 2015 16:30:05" \
@@ -327,6 +330,8 @@ maxupdateskew 192.168.123.1 10.0
 minpoll 192.168.123.1 3
 minstratum 192.168.123.1 1
 polltarget 192.168.123.1 10
+selectopts 192.168.123.1 +trust +prefer -require
+selectdata
 delete 192.168.123.1"
 
 run_test || test_fail
@@ -345,6 +350,10 @@ check_chronyc_output "^200 OK
 200 OK
 200 OK
 200 OK
+200 OK
+S Name/IP Address        Auth COpts EOpts Last Score     Interval  Leap
+=======================================================================
+M node1\.net1\.clk            N \-PT\-\- \-PT\-\-    0   1\.0    \+0ns    \+0ns  \?
 200 OK$" || test_fail
 
 chronyc_conf="
index 04d14c2dcee9b30abf6b06d08f2c551c65ce5d45..301d01ceb694e27fb9f3097e480589d73a045e50 100755 (executable)
@@ -42,6 +42,7 @@ for command in \
        "reselect" \
        "reselectdist 1e-3" \
        "reset sources" \
+       "selectopts $server -noselect +trust +prefer +require" \
        "smoothtime reset" \
        "smoothtime activate" \
 ; do
@@ -101,7 +102,7 @@ Total good RX   : [0-9]+$" || test_fail
 run_chronyc "selectdata" || test_fail
 check_chronyc_output "^S Name/IP Address        Auth COpts EOpts Last Score     Interval  Leap
 =======================================================================
-s 127\.0\.0\.1                 N ----- -----    0   1\.0    \+0ns    \+0ns  \?$" || test_fail
+s 127\.0\.0\.1                 N -PTR- -PTR-    0   1\.0    \+0ns    \+0ns  \?$" || test_fail
 
 run_chronyc "serverstats" || test_fail
 check_chronyc_output "^NTP packets received       : [0-9]+