Merge branch 'collectd-5.8'
[collectd.git] / src / chrony.c
index 835c425..913aab9 100644 (file)
 #include <arpa/inet.h> /* ntohs/ntohl */
 #endif
 
+/* AIX doesn't have MSG_DONTWAIT */
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT MSG_NONBLOCK
+#endif
+
 #define CONFIG_KEY_HOST "Host"
 #define CONFIG_KEY_PORT "Port"
 #define CONFIG_KEY_TIMEOUT "Timeout"
@@ -186,13 +191,11 @@ typedef struct ATTRIB_PACKED {
     uint8_t ip6[16];
   } addr;
   uint16_t f_family;
+  uint16_t padding;
 } tChrony_IPAddr;
 
 typedef struct ATTRIB_PACKED {
   tChrony_IPAddr addr;
-  uint16_t
-      dummy; /* FIXME: Strange dummy space. Needed on gcc 4.8.3/clang 3.4.1 on
-                x86_64 */
   int16_t f_poll;     /* 2^f_poll = Time between polls (s) */
   uint16_t f_stratum; /* Remote clock stratum */
   uint16_t f_state;   /* 0 = RPY_SD_ST_SYNC,    1 = RPY_SD_ST_UNREACH,   2 =
@@ -213,9 +216,6 @@ typedef struct ATTRIB_PACKED {
 typedef struct ATTRIB_PACKED {
   uint32_t f_ref_id;
   tChrony_IPAddr addr;
-  uint16_t
-      dummy; /* FIXME: Strange dummy space. Needed on gcc 4.8.3/clang 3.4.1 on
-                x86_64 */
   uint32_t f_n_samples;       /* Number of measurements done   */
   uint32_t f_n_runs;          /* How many measurements to come */
   uint32_t f_span_seconds;    /* For how long we're measuring  */
@@ -230,9 +230,6 @@ typedef struct ATTRIB_PACKED {
 typedef struct ATTRIB_PACKED {
   uint32_t f_ref_id;
   tChrony_IPAddr addr;
-  uint16_t
-      dummy; /* FIXME: Strange dummy space. Needed on gcc 4.8.3/clang 3.4.1 on
-                x86_64 */
   uint16_t f_stratum;
   uint16_t f_leap_status;
   tTimeval f_ref_time;
@@ -356,10 +353,10 @@ static char *niptoha(const tChrony_IPAddr *addr, char *p_buf,
 }
 
 static void nreftostr(uint32_t nrefid, char *p_buf, size_t p_buf_size) {
-  int i, j, c;
+  size_t j = 0;
 
-  for (i = j = 0; i < 4; i++) {
-    c = ntohl(nrefid) << i * 8 >> 24;
+  for (int i = 0; i < 4; i++) {
+    int c = ntohl(nrefid) << i * 8 >> 24;
     if (!isalnum(c) || j + 1 >= p_buf_size)
       continue;
     p_buf[j++] = c;
@@ -448,6 +445,15 @@ static int chrony_recv_response(tChrony_Response *p_resp,
   }
 }
 
+static void chrony_flush_recv_queue(void) {
+  char buf[1];
+
+  if (g_chrony_is_connected) {
+    while (recv(g_chrony_socket, buf, sizeof(buf), MSG_DONTWAIT) > 0)
+      ;
+  }
+}
+
 static int chrony_query(const int p_command, tChrony_Request *p_req,
                         tChrony_Response *p_resp, size_t *p_resp_size) {
   /* Check connection. We simply perform one try as collectd already handles
@@ -900,6 +906,9 @@ static int chrony_request_source_data(int p_src_idx, char *src_addr,
                          ntohs(chrony_resp.body.source_data.f_reachability));
   chrony_push_data_valid("clock_last_meas", src_addr, is_reachable,
                          ntohl(chrony_resp.body.source_data.f_since_sample));
+  chrony_push_data_valid(
+      "time_offset", src_addr, is_reachable,
+      ntohf(chrony_resp.body.source_data.f_origin_latest_meas));
 
   return CHRONY_RC_OK;
 }
@@ -911,12 +920,11 @@ static int chrony_request_source_stats(int p_src_idx, const char *src_addr,
   size_t chrony_resp_size;
   tChrony_Request chrony_req;
   tChrony_Response chrony_resp;
-  double skew_ppm, frequency_error, time_offset;
+  double skew_ppm, frequency_error;
 
   if (*p_is_reachable == 0) {
     skew_ppm = 0;
     frequency_error = 0;
-    time_offset = 0;
   } else {
     chrony_init_req(&chrony_req);
     chrony_req.body.source_stats.f_index = htonl(p_src_idx);
@@ -931,7 +939,6 @@ static int chrony_request_source_stats(int p_src_idx, const char *src_addr,
 
     skew_ppm = ntohf(chrony_resp.body.source_stats.f_skew_ppm);
     frequency_error = ntohf(chrony_resp.body.source_stats.f_rtc_gain_rate_ppm);
-    time_offset = ntohf(chrony_resp.body.source_stats.f_est_offset);
 
     DEBUG(PLUGIN_NAME
           ": Source[%d] stat: .addr = %s, .ref_id= %u, .n_samples = %u, "
@@ -943,7 +950,8 @@ static int chrony_request_source_stats(int p_src_idx, const char *src_addr,
           ntohl(chrony_resp.body.source_stats.f_n_runs),
           ntohl(chrony_resp.body.source_stats.f_span_seconds),
           ntohf(chrony_resp.body.source_stats.f_rtc_seconds_fast),
-          frequency_error, skew_ppm, time_offset,
+          frequency_error, skew_ppm,
+          ntohf(chrony_resp.body.source_stats.f_est_offset),
           ntohf(chrony_resp.body.source_stats.f_est_offset_err));
 
   } /* if (*is_reachable) */
@@ -952,8 +960,6 @@ static int chrony_request_source_stats(int p_src_idx, const char *src_addr,
   chrony_push_data_valid("clock_skew_ppm", src_addr, *p_is_reachable, skew_ppm);
   chrony_push_data_valid("frequency_error", src_addr, *p_is_reachable,
                          frequency_error); /* unit: ppm */
-  chrony_push_data_valid("time_offset", src_addr, *p_is_reachable,
-                         time_offset); /* unit: s */
 
   return CHRONY_RC_OK;
 }
@@ -972,6 +978,9 @@ static int chrony_read(void) {
     g_chrony_seq_is_initialized = 1;
   }
 
+  /* Ignore late responses that may have been received */
+  chrony_flush_recv_queue();
+
   /* Get daemon stats */
   rc = chrony_request_daemon_stats();
   if (rc != CHRONY_RC_OK)