]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
cmdmon: add ntpdata command
authorMiroslav Lichvar <mlichvar@redhat.com>
Fri, 25 Nov 2016 14:02:35 +0000 (15:02 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Fri, 25 Nov 2016 16:33:43 +0000 (17:33 +0100)
candm.h
cmdmon.c
ntp_core.c
ntp_core.h
ntp_sources.c
ntp_sources.h
pktlength.c
reports.h
sourcestats.c
sourcestats.h
stubs.c

diff --git a/candm.h b/candm.h
index 19ed7c9ca054541658c2f392e56084f5f7e8ed23..5016fdb31875d1ca6c796a0202ae671bf6a2a090 100644 (file)
--- a/candm.h
+++ b/candm.h
@@ -94,7 +94,8 @@
 #define REQ_SERVER_STATS 54
 #define REQ_CLIENT_ACCESSES_BY_INDEX2 55
 #define REQ_LOCAL2 56
-#define N_REQUEST_TYPES 57
+#define REQ_NTP_DATA 57
+#define N_REQUEST_TYPES 58
 
 /* Structure used to exchange timespecs independent of time_t size */
 typedef struct {
@@ -310,6 +311,11 @@ typedef struct {
   int32_t EOR;
 } REQ_SmoothTime;
 
+typedef struct {
+  IPAddr ip_addr;
+  int32_t EOR;
+} REQ_NTPData;
+
 /* ================================================== */
 
 #define PKT_TYPE_CMD_REQUEST 1
@@ -410,6 +416,7 @@ typedef struct {
     REQ_ManualDelete manual_delete;
     REQ_ReselectDistance reselect_distance;
     REQ_SmoothTime smoothtime;
+    REQ_NTPData ntp_data;
   } data; /* Command specific parameters */
 
   /* Padding used to prevent traffic amplification.  It only defines the
@@ -443,7 +450,8 @@ typedef struct {
 #define RPY_SMOOTHING 13
 #define RPY_SERVER_STATS 14
 #define RPY_CLIENT_ACCESSES_BY_INDEX2 15
-#define N_REPLY_TYPES 16
+#define RPY_NTP_DATA 16
+#define N_REPLY_TYPES 17
 
 /* Status codes */
 #define STT_SUCCESS 0
@@ -625,6 +633,38 @@ typedef struct {
   int32_t EOR;
 } RPY_Smoothing;
 
+#define RPY_NTP_FLAGS_TESTS 0x3ff
+#define RPY_NTP_FLAG_INTERLEAVED 0x4000
+#define RPY_NTP_FLAG_AUTHENTICATED 0x8000
+
+typedef struct {
+  IPAddr remote_addr;
+  IPAddr local_addr;
+  uint16_t remote_port;
+  uint8_t leap;
+  uint8_t version;
+  uint8_t mode;
+  uint8_t stratum;
+  int8_t poll;
+  int8_t precision;
+  Float root_delay;
+  Float root_dispersion;
+  uint32_t ref_id;
+  Timespec ref_time;
+  Float offset;
+  Float peer_delay;
+  Float peer_dispersion;
+  Float response_time;
+  Float jitter_asymmetry;
+  uint16_t flags;
+  uint8_t tx_tss_char;
+  uint8_t rx_tss_char;
+  uint32_t total_tx_count;
+  uint32_t total_rx_count;
+  uint32_t total_valid_count;
+  int32_t EOR;
+} RPY_NTPData;
+
 typedef struct {
   uint8_t version;
   uint8_t pkt_type;
@@ -653,6 +693,7 @@ typedef struct {
     RPY_ManualList manual_list;
     RPY_Activity activity;
     RPY_Smoothing smoothing;
+    RPY_NTPData ntp_data;
   } data; /* Reply specific parameters */
 
 } CMD_Reply;
index ab3d8a47fb8e8e96842eb2c1cc1f212cccf43d74..3a284aa29222bc48731f212c05edc8145dd93157 100644 (file)
--- a/cmdmon.c
+++ b/cmdmon.c
@@ -133,6 +133,7 @@ static const char permissions[] = {
   PERMIT_AUTH, /* SERVER_STATS */
   PERMIT_AUTH, /* CLIENT_ACCESSES_BY_INDEX2 */
   PERMIT_AUTH, /* LOCAL2 */
+  PERMIT_AUTH, /* NTP_DATA */
 };
 
 /* ================================================== */
@@ -1186,6 +1187,49 @@ handle_server_stats(CMD_Request *rx_message, CMD_Reply *tx_message)
   tx_message->data.server_stats.log_drops = htonl(report.log_drops);
 }
 
+/* ================================================== */
+
+static void
+handle_ntp_data(CMD_Request *rx_message, CMD_Reply *tx_message)
+{
+  RPT_NTPReport report;
+
+  UTI_IPNetworkToHost(&rx_message->data.ntp_data.ip_addr, &report.remote_addr);
+
+  if (!NSR_GetNTPReport(&report)) {
+    tx_message->status = htons(STT_NOSUCHSOURCE);
+    return;
+  }
+
+  tx_message->reply = htons(RPY_NTP_DATA);
+  UTI_IPHostToNetwork(&report.remote_addr, &tx_message->data.ntp_data.remote_addr);
+  UTI_IPHostToNetwork(&report.local_addr, &tx_message->data.ntp_data.local_addr);
+  tx_message->data.ntp_data.remote_port = htons(report.remote_port);
+  tx_message->data.ntp_data.leap = report.leap;
+  tx_message->data.ntp_data.version = report.version;
+  tx_message->data.ntp_data.mode = report.mode;
+  tx_message->data.ntp_data.stratum = report.stratum;
+  tx_message->data.ntp_data.poll = report.poll;
+  tx_message->data.ntp_data.precision = report.precision;
+  tx_message->data.ntp_data.root_delay = UTI_FloatHostToNetwork(report.root_delay);
+  tx_message->data.ntp_data.root_dispersion = UTI_FloatHostToNetwork(report.root_dispersion);
+  tx_message->data.ntp_data.ref_id = htonl(report.ref_id);
+  UTI_TimespecHostToNetwork(&report.ref_time, &tx_message->data.ntp_data.ref_time);
+  tx_message->data.ntp_data.offset = UTI_FloatHostToNetwork(report.offset);
+  tx_message->data.ntp_data.peer_delay = UTI_FloatHostToNetwork(report.peer_delay);
+  tx_message->data.ntp_data.peer_dispersion = UTI_FloatHostToNetwork(report.peer_dispersion);
+  tx_message->data.ntp_data.response_time = UTI_FloatHostToNetwork(report.response_time);
+  tx_message->data.ntp_data.jitter_asymmetry = UTI_FloatHostToNetwork(report.jitter_asymmetry);
+  tx_message->data.ntp_data.flags = htons((report.tests & RPY_NTP_FLAGS_TESTS) |
+                                          (report.interleaved ? RPY_NTP_FLAG_INTERLEAVED : 0) |
+                                          (report.authenticated ? RPY_NTP_FLAG_AUTHENTICATED : 0));
+  tx_message->data.ntp_data.tx_tss_char = report.tx_tss_char;
+  tx_message->data.ntp_data.rx_tss_char = report.rx_tss_char;
+  tx_message->data.ntp_data.total_tx_count = htonl(report.total_tx_count);
+  tx_message->data.ntp_data.total_rx_count = htonl(report.total_rx_count);
+  tx_message->data.ntp_data.total_valid_count = htonl(report.total_valid_count);
+}
+
 /* ================================================== */
 /* Read a packet and process it */
 
@@ -1573,6 +1617,10 @@ read_from_cmd_socket(int sock_fd, int event, void *anything)
           handle_server_stats(&rx_message, &tx_message);
           break;
 
+        case REQ_NTP_DATA:
+          handle_ntp_data(&rx_message, &tx_message);
+          break;
+
         default:
           DEBUG_LOG(LOGF_CmdMon, "Unhandled command %d", rx_command);
           tx_message.status = htons(STT_FAILED);
index 2ee39586d214bb00bcaca9a4aab30739642259a0..a0b55df4be95465643b4d8159212e5a71c96d21b 100644 (file)
@@ -186,6 +186,8 @@ struct NCR_Instance_Record {
   int burst_good_samples_to_go;
   int burst_total_samples_to_go;
 
+  /* Report from last valid response */
+  RPT_NTPReport report;
 };
 
 typedef struct {
@@ -558,6 +560,7 @@ NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourcePar
   result->local_tx.source = NTP_TS_DAEMON;
   result->burst_good_samples_to_go = 0;
   result->burst_total_samples_to_go = 0;
+  memset(&result->report, 0, sizeof (result->report));
   
   NCR_ResetInstance(result);
 
@@ -1073,6 +1076,8 @@ transmit_timeout(void *arg)
   ++inst->tx_count;
   inst->valid_rx = 0;
   inst->updated_timestamps = 0;
+  if (sent)
+    inst->report.total_tx_count++;
 
   /* If the source loses connectivity and our packets are still being sent,
      back off the sampling rate to reduce the network traffic.  If it's the
@@ -1284,6 +1289,8 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
 
   stats = SRC_GetSourcestats(inst->source);
 
+  inst->report.total_rx_count++;
+
   pkt_leap = NTP_LVM_TO_LEAP(message->lvm);
   pkt_refid = ntohl(message->reference_id);
   pkt_root_delay = UTI_Ntp32ToDouble(message->root_delay);
@@ -1585,6 +1592,35 @@ receive_packet(NCR_Instance inst, NTP_Local_Address *local_addr,
       assert(inst->tx_timeout_id);
       restart_timeout(inst, delay_time);
     }
+
+    /* Update the NTP report */
+    inst->report.remote_addr = inst->remote_addr.ip_addr;
+    inst->report.local_addr = inst->local_addr.ip_addr;
+    inst->report.remote_port = inst->remote_addr.port;
+    inst->report.leap = NTP_LVM_TO_LEAP(message->lvm);
+    inst->report.version = NTP_LVM_TO_VERSION(message->lvm);
+    inst->report.mode = NTP_LVM_TO_MODE(message->lvm);
+    inst->report.stratum = message->stratum;
+    inst->report.poll = message->poll;
+    inst->report.precision = message->precision;
+    inst->report.root_delay = pkt_root_delay;
+    inst->report.root_dispersion = pkt_root_dispersion;
+    inst->report.ref_id = pkt_refid;
+    UTI_Ntp64ToTimespec(&message->reference_ts, &inst->report.ref_time);
+    inst->report.offset = offset;
+    inst->report.peer_delay = delay;
+    inst->report.peer_dispersion = dispersion;
+    inst->report.response_time = server_interval;
+    inst->report.jitter_asymmetry = SST_GetJitterAsymmetry(stats);
+    inst->report.tests = ((((((((test1 << 1 | test2) << 1 | test3) << 1 |
+                               test5) << 1 | test6) << 1 | test7) << 1 |
+                            testA) << 1 | testB) << 1 | testC) << 1 | testD;
+    inst->report.interleaved = interleaved_packet;
+    inst->report.authenticated = inst->auth_mode != AUTH_NONE;
+    inst->report.tx_tss_char = tss_chars[inst->local_tx.source];
+    inst->report.rx_tss_char = tss_chars[sample_rx_tss];
+
+    inst->report.total_valid_count++;
   }
 
   /* Do measurement logging */
@@ -2140,6 +2176,14 @@ NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timespec *n
 
 /* ================================================== */
 
+void
+NCR_GetNTPReport(NCR_Instance inst, RPT_NTPReport *report)
+{
+  *report = inst->report;
+}
+
+/* ================================================== */
+
 int
 NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all)
  {
index 699cb835490e2ac9f01467f55b2b24d0fe454aaf..f788d68a7f212c85bd337130cf3ade52a02eb2ff 100644 (file)
@@ -123,6 +123,7 @@ extern void NCR_ModifyPolltarget(NCR_Instance inst, int new_poll_target);
 extern void NCR_InitiateSampleBurst(NCR_Instance inst, int n_good_samples, int n_total_samples);
 
 extern void NCR_ReportSource(NCR_Instance inst, RPT_SourceReport *report, struct timespec *now);
+extern void NCR_GetNTPReport(NCR_Instance inst, RPT_NTPReport *report);
 
 extern int NCR_AddAccessRestriction(IPAddr *ip_addr, int subnet_bits, int allow, int all);
 extern int NCR_CheckAccessRestriction(IPAddr *ip_addr);
index 835599fe503f53004d61ea76e662da5fdc42f9b1..5024a423e441383dab0d8aedc16b26f26b96cb72 100644 (file)
@@ -1120,6 +1120,26 @@ NSR_ReportSource(RPT_SourceReport *report, struct timespec *now)
   }
 }
 
+/* ================================================== */
+/* The ip address is assumed to be completed on input, that is how we
+   identify the source record. */
+
+int
+NSR_GetNTPReport(RPT_NTPReport *report)
+{
+  NTP_Remote_Address rem_addr;
+  int slot, found;
+
+  rem_addr.ip_addr = report->remote_addr;
+  rem_addr.port = 0;
+  find_slot(&rem_addr, &slot, &found);
+  if (!found)
+    return 0;
+
+  NCR_GetNTPReport(get_record(slot)->data, report);
+  return 1;
+}
+
 /* ================================================== */
 
 void
index 424eab64933d17f2c7d1afc5f5208263c748ff0f..23e9612373056d56f3aee68a2ea5050c6454c392 100644 (file)
@@ -129,6 +129,8 @@ extern int NSR_InitiateSampleBurst(int n_good_samples, int n_total_samples, IPAd
 
 extern void NSR_ReportSource(RPT_SourceReport *report, struct timespec *now);
 
+extern int NSR_GetNTPReport(RPT_NTPReport *report);
+
 extern void NSR_GetActivityReport(RPT_ActivityReport *report);
 
 #endif /* GOT_NTP_SOURCES_H */
index 7366e5119e2d1bafcd5c71a0adb4aceeb0511327..459b79c37268ca9df35f6e9f1aadf752c20720e9 100644 (file)
@@ -113,6 +113,7 @@ static const struct request_length request_lengths[] = {
   REQ_LENGTH_ENTRY(client_accesses_by_index,
                    client_accesses_by_index),   /* CLIENT_ACCESSES_BY_INDEX2 */
   REQ_LENGTH_ENTRY(local, null),                /* LOCAL2 */
+  REQ_LENGTH_ENTRY(ntp_data, ntp_data),         /* NTP_DATA */
 };
 
 static const uint16_t reply_lengths[] = {
@@ -132,6 +133,7 @@ static const uint16_t reply_lengths[] = {
   RPY_LENGTH_ENTRY(smoothing),                  /* SMOOTHING */
   RPY_LENGTH_ENTRY(server_stats),               /* SERVER_STATS */
   RPY_LENGTH_ENTRY(client_accesses_by_index),   /* CLIENT_ACCESSES_BY_INDEX2 */
+  RPY_LENGTH_ENTRY(ntp_data),                   /* NTP_DATA */
 };
 
 /* ================================================== */
index 20fd32cab0521dcf0985201d282624c42e286086..6a2467014dd26c7d850f4460ded0b0f2ab51e33b 100644 (file)
--- a/reports.h
+++ b/reports.h
@@ -131,4 +131,33 @@ typedef struct {
   double remaining_time;
 } RPT_SmoothingReport;
 
+typedef struct {
+  IPAddr remote_addr;
+  IPAddr local_addr;
+  uint16_t remote_port;
+  uint8_t leap;
+  uint8_t version;
+  uint8_t mode;
+  uint8_t stratum;
+  int8_t poll;
+  int8_t precision;
+  double root_delay;
+  double root_dispersion;
+  uint32_t ref_id;
+  struct timespec ref_time;
+  double offset;
+  double peer_delay;
+  double peer_dispersion;
+  double response_time;
+  double jitter_asymmetry;
+  uint16_t tests;
+  int interleaved;
+  int authenticated;
+  char tx_tss_char;
+  char rx_tss_char;
+  uint32_t total_tx_count;
+  uint32_t total_rx_count;
+  uint32_t total_valid_count;
+} RPT_NTPReport;
+
 #endif /* GOT_REPORTS_H */
index d8a6987837de27de3d9a13a8c4b180e3643d5fdc..09f1aefbdf29aa147be945d11997601755c332ed 100644 (file)
@@ -994,3 +994,11 @@ SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *report, struct ti
 }
 
 /* ================================================== */
+
+double
+SST_GetJitterAsymmetry(SST_Stats inst)
+{
+  return inst->asymmetry;
+}
+
+/* ================================================== */
index 0c1f209de953748e3a9269e8d44ddcd779421cf3..48f73b3b26feea2125a9ba7fe3136eb00483ee68 100644 (file)
@@ -139,5 +139,7 @@ extern void SST_DoSourcestatsReport(SST_Stats inst, RPT_SourcestatsReport *repor
 
 extern int SST_Samples(SST_Stats inst);
 
+extern double SST_GetJitterAsymmetry(SST_Stats inst);
+
 #endif /* GOT_SOURCESTATS_H */
 
diff --git a/stubs.c b/stubs.c
index 1479117a03d1bbde3cbee95f8ffcdfb94c9e3811..9bc127cb8a3d5c727c3306afeb47c21675426505 100644 (file)
--- a/stubs.c
+++ b/stubs.c
@@ -297,6 +297,12 @@ NSR_ReportSource(RPT_SourceReport *report, struct timespec *now)
   memset(report, 0, sizeof (*report));
 }
   
+int
+NSR_GetNTPReport(RPT_NTPReport *report)
+{
+  return 0;
+}
+
 void
 NSR_GetActivityReport(RPT_ActivityReport *report)
 {