]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
cmdmon: update CLIENT_ACCESSES_BY_INDEX command
authorMiroslav Lichvar <mlichvar@redhat.com>
Fri, 27 Nov 2015 14:25:24 +0000 (15:25 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Mon, 30 Nov 2015 16:50:55 +0000 (17:50 +0100)
Add new fields from clientlog to the report and print them in chronyc.
Rework the code to skip empty records in the hash table. The reply no
longer has variable length, all client fields are filled even if some
are empty. Reply with RPY_NULL when the facility is disabled.

candm.h
client.c
clientlog.c
clientlog.h
cmdmon.c
pktlength.c
reports.h

diff --git a/candm.h b/candm.h
index e4eafb73365983a8df92aa232b5398f593442ec3..a740aa22d04aacb6cb3efdf770491ed758676b52 100644 (file)
--- a/candm.h
+++ b/candm.h
@@ -284,7 +284,7 @@ typedef struct {
 
 typedef struct {
   uint32_t first_index;
-  uint32_t n_indices;
+  uint32_t n_clients;
   int32_t EOR;
 } REQ_ClientAccessesByIndex;
 
@@ -351,7 +351,7 @@ typedef struct {
 #define PROTO_VERSION_PADDING 6
 
 /* The maximum length of padding in request packet, currently
-   defined by CLIENT_ACCESSES_BY_INDEX and MANUAL_LIST */
+   defined by MANUAL_LIST */
 #define MAX_PADDING_LENGTH 396
 
 /* ================================================== */
@@ -545,11 +545,14 @@ typedef struct {
 
 typedef struct {
   IPAddr ip;
-  uint32_t client_hits;
-  uint32_t peer_hits;
-  uint32_t cmd_hits_auth;
-  uint32_t cmd_hits_normal;
-  uint32_t cmd_hits_bad;
+  uint32_t ntp_hits;
+  uint32_t cmd_hits;
+  uint16_t ntp_drops;
+  uint16_t cmd_drops;
+  int8_t ntp_interval;
+  int8_t cmd_interval;
+  int8_t ntp_timeout_interval;
+  int8_t pad;
   uint32_t last_ntp_hit_ago;
   uint32_t last_cmd_hit_ago;
 } RPY_ClientAccesses_Client;
index cd0977c746b0ab4b3eb67ef4131110bc12699bb5..f8f2ecfd9568bcb0faa0202930b7ecc2a1bfe154 100644 (file)
--- a/client.c
+++ b/client.c
@@ -2047,87 +2047,61 @@ process_cmd_clients(char *line)
 {
   CMD_Request request;
   CMD_Reply reply;
-  unsigned long next_index;
-  int j;
   IPAddr ip;
-  unsigned long client_hits;
-  unsigned long peer_hits;
-  unsigned long cmd_hits_auth;
-  unsigned long cmd_hits_normal;
-  unsigned long cmd_hits_bad;
-  unsigned long last_ntp_hit_ago;
-  unsigned long last_cmd_hit_ago;
-  char hostname_buf[50];
-
-  int n_replies;
-  int n_indices_in_table;
+  uint32_t i, n_clients, next_index, n_indices;
+  RPY_ClientAccesses_Client *client;
+  char hostname[26];
 
   next_index = 0;
 
-  printf("Hostname                   Client    Peer CmdAuth CmdNorm  CmdBad  LstN  LstC\n"
-         "=========================  ======  ======  ======  ======  ======  ====  ====\n");
-
-  do {
+  printf("Hostname                      NTP   Drop Int IntL Last     Cmd   Drop Int  Last\n"
+         "===============================================================================\n");
 
+  while (1) {
     request.command = htons(REQ_CLIENT_ACCESSES_BY_INDEX);
     request.data.client_accesses_by_index.first_index = htonl(next_index);
-    request.data.client_accesses_by_index.n_indices = htonl(MAX_CLIENT_ACCESSES);
+    request.data.client_accesses_by_index.n_clients = htonl(MAX_CLIENT_ACCESSES);
 
-    if (request_reply(&request, &reply, RPY_CLIENT_ACCESSES_BY_INDEX, 0)) {
-          n_replies = ntohl(reply.data.client_accesses_by_index.n_clients);
-          n_indices_in_table = ntohl(reply.data.client_accesses_by_index.n_indices);
-          if (n_replies == 0) {
-            goto finished;
-          }
-          for (j=0; j<n_replies; j++) {
-            UTI_IPNetworkToHost(&reply.data.client_accesses_by_index.clients[j].ip, &ip);
-            if (ip.family != IPADDR_UNSPEC) {
-              /* UNSPEC implies that the node could not be found in
-                 the daemon's tables; we shouldn't ever generate this
-                 case, but ignore it if we do.  (In future there might
-                 be a protocol to reset the client logging; if another
-                 administrator runs that while we're doing the clients
-                 command, there will be a race condition that could
-                 cause this). */
-              
-              client_hits = ntohl(reply.data.client_accesses_by_index.clients[j].client_hits);
-              peer_hits = ntohl(reply.data.client_accesses_by_index.clients[j].peer_hits);
-              cmd_hits_auth = ntohl(reply.data.client_accesses_by_index.clients[j].cmd_hits_auth);
-              cmd_hits_normal = ntohl(reply.data.client_accesses_by_index.clients[j].cmd_hits_normal);
-              cmd_hits_bad = ntohl(reply.data.client_accesses_by_index.clients[j].cmd_hits_bad);
-              last_ntp_hit_ago = ntohl(reply.data.client_accesses_by_index.clients[j].last_ntp_hit_ago);
-              last_cmd_hit_ago = ntohl(reply.data.client_accesses_by_index.clients[j].last_cmd_hit_ago);
-
-              if (no_dns) {
-                snprintf(hostname_buf, sizeof(hostname_buf),
-                         "%s", UTI_IPToString(&ip));
-              } else {
-                DNS_IPAddress2Name(&ip, hostname_buf, sizeof(hostname_buf));
-                hostname_buf[25] = 0;
-              }
-              printf("%-25s  %6ld  %6ld  %6ld  %6ld  %6ld  ",
-                     hostname_buf,
-                     client_hits, peer_hits,
-                     cmd_hits_auth, cmd_hits_normal, cmd_hits_bad);
-              print_seconds(last_ntp_hit_ago);
-              printf("  ");
-              print_seconds(last_cmd_hit_ago);
-              printf("\n");
-            }
-          }              
-
-          /* Set the next index to probe based on what the server tells us */
-          next_index = ntohl(reply.data.client_accesses_by_index.next_index);
-          if (next_index >= n_indices_in_table) {
-            goto finished;
-          }
-    } else {
+    if (!request_reply(&request, &reply, RPY_CLIENT_ACCESSES_BY_INDEX, 0))
       return 0;
+
+    n_clients = ntohl(reply.data.client_accesses_by_index.n_clients);
+    n_indices = ntohl(reply.data.client_accesses_by_index.n_indices);
+
+    for (i = 0; i < n_clients && i < MAX_CLIENT_ACCESSES; i++) {
+      client = &reply.data.client_accesses_by_index.clients[i];
+
+      UTI_IPNetworkToHost(&client->ip, &ip);
+
+      /* UNSPEC means the record could not be found in the daemon's tables.
+         We shouldn't ever generate this case, but ignore it if we do. */
+      if (ip.family == IPADDR_UNSPEC)
+        continue;
+
+      if (no_dns)
+        snprintf(hostname, sizeof (hostname), "%s", UTI_IPToString(&ip));
+      else
+        DNS_IPAddress2Name(&ip, hostname, sizeof (hostname));
+
+      printf("%-25s", hostname);
+      printf("  %6"PRIu32"  %5"PRIu16"  %2d  %2d  ",
+             ntohl(client->ntp_hits), ntohs(client->ntp_drops),
+             client->ntp_interval, client->ntp_timeout_interval);
+      print_seconds(ntohl(client->last_ntp_hit_ago));
+      printf("  %6"PRIu32"  %5"PRIu16"  %2d  ",
+             ntohl(client->cmd_hits), ntohs(client->cmd_drops),
+             client->cmd_interval);
+      print_seconds(ntohl(client->last_cmd_hit_ago));
+      printf("\n");
     }
-  } while (1); /* keep going until all subnets have been expanded,
-                  down to single nodes */
 
-finished:
+    /* Set the next index to probe based on what the server tells us */
+    next_index = ntohl(reply.data.client_accesses_by_index.next_index);
+
+    if (next_index >= n_indices || n_clients < MAX_CLIENT_ACCESSES)
+      break;
+  }
+
   return 1;
 }
 
index 6f66738a50770b0797580ea7560a1d18253ed832..66da722dbcfd49c9d73960c9c1c80c88f9365ff5 100644 (file)
@@ -481,26 +481,41 @@ CLG_LimitCommandResponseRate(int index)
 
 /* ================================================== */
 
-CLG_Status
-CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *report,
-                                 time_t now, unsigned long *n_indices)
+extern int
+CLG_GetNumberOfIndices(void)
+{
+  if (!active)
+    return -1;
+
+  return ARR_GetSize(records);
+}
+
+/* ================================================== */
+
+int
+CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *report, time_t now)
 {
   Record *record;
 
-  if (!active)
-    return CLG_INACTIVE;
+  if (!active || index < 0 || index >= ARR_GetSize(records))
+    return 0;
 
-  *n_indices = ARR_GetSize(records);
-  if (index < 0 || index >= *n_indices)
-    return CLG_INDEXTOOLARGE;
-    
   record = ARR_GetElement(records, index);
 
+  if (record->ip_addr.family == IPADDR_UNSPEC)
+    return 0;
+
   report->ip_addr = record->ip_addr;
   report->ntp_hits = record->ntp_hits;
   report->cmd_hits = record->cmd_hits;
+  report->ntp_drops = record->ntp_drops;
+  report->cmd_drops = record->cmd_drops;
+  report->ntp_interval = (record->ntp_rate - RATE_SCALE / 2) / -RATE_SCALE;
+  report->cmd_interval = (record->cmd_rate - RATE_SCALE / 2) / -RATE_SCALE;
+  report->ntp_timeout_interval =
+                 (record->ntp_timeout_rate - RATE_SCALE / 2) / -RATE_SCALE;
   report->last_ntp_hit_ago = now - record->last_ntp_hit;
   report->last_cmd_hit_ago = now - record->last_cmd_hit;
 
-  return CLG_SUCCESS;
+  return 1;
 }
index a4a429fb6f4bf5636e03242cc2653eb27b2d3365..f6046763e5268bdb0e38d2f723ee5d936db31720 100644 (file)
@@ -39,18 +39,8 @@ extern int CLG_LimitNTPResponseRate(int index);
 extern int CLG_LimitCommandResponseRate(int index);
 
 /* And some reporting functions, for use by chronyc. */
-/* TBD */
-
-typedef enum {
-  CLG_SUCCESS,                  /* All is well */
-  CLG_EMPTYSUBNET,              /* No hosts logged in requested subnet */
-  CLG_BADSUBNET,                /* Subnet requested is not 0, 8, 16 or 24 bits */
-  CLG_INACTIVE,                 /* Facility not active */
-  CLG_INDEXTOOLARGE             /* Node index is higher than number of nodes present */
-} CLG_Status;
-
-CLG_Status
-CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *report,
-                                 time_t now, unsigned long *n_indices);
+
+extern int CLG_GetNumberOfIndices(void);
+extern int CLG_GetClientAccessReportByIndex(int index, RPT_ClientAccessByIndex_Report *report, time_t now);
 
 #endif /* GOT_CLIENTLOG_H */
index b71b65786cb92356deef7ecb7418b13d526a6c3e..b246900c0b7b5f6e0be01e0be3ef6f2fbd1f3576 100644 (file)
--- a/cmdmon.c
+++ b/cmdmon.c
@@ -1017,50 +1017,50 @@ handle_cyclelogs(CMD_Request *rx_message, CMD_Reply *tx_message)
 static void
 handle_client_accesses_by_index(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
-  CLG_Status result;
   RPT_ClientAccessByIndex_Report report;
-  unsigned long first_index, n_indices, n_indices_in_table;
-  int i, j;
+  RPY_ClientAccesses_Client *client;
+  int n_indices;
+  uint32_t i, j, req_first_index, req_n_clients;
   struct timeval now;
 
   SCH_GetLastEventTime(&now, NULL, NULL);
 
-  first_index = ntohl(rx_message->data.client_accesses_by_index.first_index);
-  n_indices = ntohl(rx_message->data.client_accesses_by_index.n_indices);
-  if (n_indices > MAX_CLIENT_ACCESSES)
-    n_indices = MAX_CLIENT_ACCESSES;
+  req_first_index = ntohl(rx_message->data.client_accesses_by_index.first_index);
+  req_n_clients = ntohl(rx_message->data.client_accesses_by_index.n_clients);
+  if (req_n_clients > MAX_CLIENT_ACCESSES)
+    req_n_clients = MAX_CLIENT_ACCESSES;
 
-  tx_message->reply = htons(RPY_CLIENT_ACCESSES_BY_INDEX);
+  n_indices = CLG_GetNumberOfIndices();
+  if (n_indices < 0) {
+    tx_message->status = htons(STT_INACTIVE);
+    return;
+  }
 
-  for (i = 0, j = 0; i < n_indices; i++) {
-    result = CLG_GetClientAccessReportByIndex(first_index + i, &report,
-                                              now.tv_sec, &n_indices_in_table);
-    tx_message->data.client_accesses_by_index.n_indices = htonl(n_indices_in_table);
-
-    switch (result) {
-      case CLG_SUCCESS:
-        UTI_IPHostToNetwork(&report.ip_addr, &tx_message->data.client_accesses_by_index.clients[j].ip);
-        tx_message->data.client_accesses_by_index.clients[j].client_hits = htonl(report.ntp_hits);
-        tx_message->data.client_accesses_by_index.clients[j].peer_hits = htonl(0);
-        tx_message->data.client_accesses_by_index.clients[j].cmd_hits_auth = htonl(0);
-        tx_message->data.client_accesses_by_index.clients[j].cmd_hits_normal = htonl(report.cmd_hits);
-        tx_message->data.client_accesses_by_index.clients[j].cmd_hits_bad = htonl(0);
-        tx_message->data.client_accesses_by_index.clients[j].last_ntp_hit_ago = htonl(report.last_ntp_hit_ago);
-        tx_message->data.client_accesses_by_index.clients[j].last_cmd_hit_ago = htonl(report.last_cmd_hit_ago);
-        j++;
-        break;
-      case CLG_INDEXTOOLARGE:
-        break; /* ignore this index */
-      case CLG_INACTIVE:
-        tx_message->status = htons(STT_INACTIVE);
-        return;
-      default:
-        assert(0);
-        break;
-    }
+  tx_message->reply = htons(RPY_CLIENT_ACCESSES_BY_INDEX);
+  tx_message->data.client_accesses_by_index.n_indices = htonl(n_indices);
+
+  memset(tx_message->data.client_accesses_by_index.clients, 0,
+         sizeof (tx_message->data.client_accesses_by_index.clients));
+
+  for (i = req_first_index, j = 0; i < (uint32_t)n_indices && j < req_n_clients; i++) {
+    if (!CLG_GetClientAccessReportByIndex(i, &report, now.tv_sec))
+      continue;
+
+    client = &tx_message->data.client_accesses_by_index.clients[j++];
+
+    UTI_IPHostToNetwork(&report.ip_addr, &client->ip);
+    client->ntp_hits = htonl(report.ntp_hits);
+    client->cmd_hits = htonl(report.cmd_hits);
+    client->ntp_drops = htons(report.ntp_drops);
+    client->cmd_drops = htons(report.cmd_drops);
+    client->ntp_interval = report.ntp_interval;
+    client->cmd_interval = report.cmd_interval;
+    client->ntp_timeout_interval = report.ntp_timeout_interval;
+    client->last_ntp_hit_ago = htonl(report.last_ntp_hit_ago);
+    client->last_cmd_hit_ago = htonl(report.last_cmd_hit_ago);
   }
 
-  tx_message->data.client_accesses_by_index.next_index = htonl(first_index + i);
+  tx_message->data.client_accesses_by_index.next_index = htonl(i);
   tx_message->data.client_accesses_by_index.n_clients = htonl(j);
 }
 
index e123ef452fb0f378eae7ed537f23616b459ded60..a853465f56d47f066e0b372ba530d95dd601290b 100644 (file)
@@ -346,17 +346,7 @@ PKL_ReplyLength(CMD_Reply *r)
         /* No longer supported */
         return 0;
       case RPY_CLIENT_ACCESSES_BY_INDEX:
-        {
-          unsigned long nc = ntohl(r->data.client_accesses_by_index.n_clients);
-          if (r->status == htons(STT_SUCCESS)) {
-            if (nc > MAX_CLIENT_ACCESSES)
-              return 0;
-            return (offsetof(CMD_Reply, data.client_accesses_by_index.clients) +
-                    nc * sizeof(RPY_ClientAccesses_Client));
-          } else {
-            return offsetof(CMD_Reply, data);
-          }
-        }
+        return offsetof(CMD_Reply, data.client_accesses_by_index.EOR);
       case RPY_MANUAL_LIST:
         {
           unsigned long ns = ntohl(r->data.manual_list.n_samples);
index b124083be858136a0d5c7e9fdd8c76298df25604..24881dfd74f924f5c6fe896765fe70d435e77dfb 100644 (file)
--- a/reports.h
+++ b/reports.h
@@ -88,10 +88,15 @@ typedef struct {
 
 typedef struct {
   IPAddr ip_addr;
-  unsigned long ntp_hits;
-  unsigned long cmd_hits;
-  unsigned long last_ntp_hit_ago;
-  unsigned long last_cmd_hit_ago;
+  uint32_t ntp_hits;
+  uint32_t cmd_hits;
+  uint16_t ntp_drops;
+  uint16_t cmd_drops;
+  int8_t ntp_interval;
+  int8_t cmd_interval;
+  int8_t ntp_timeout_interval;
+  uint32_t last_ntp_hit_ago;
+  uint32_t last_cmd_hit_ago;
 } RPT_ClientAccessByIndex_Report;
 
 typedef struct {