cmdmon: update CLIENT_ACCESSES_BY_INDEX command
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.
This commit is contained in:
parent
b506594c2d
commit
657929f8ec
7 changed files with 128 additions and 151 deletions
17
candm.h
17
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;
|
||||
|
|
104
client.c
104
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). */
|
||||
if (!request_reply(&request, &reply, RPY_CLIENT_ACCESSES_BY_INDEX, 0))
|
||||
return 0;
|
||||
|
||||
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);
|
||||
n_clients = ntohl(reply.data.client_accesses_by_index.n_clients);
|
||||
n_indices = ntohl(reply.data.client_accesses_by_index.n_indices);
|
||||
|
||||
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);
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 {
|
||||
return 0;
|
||||
}
|
||||
} while (1); /* keep going until all subnets have been expanded,
|
||||
down to single nodes */
|
||||
|
||||
finished:
|
||||
if (next_index >= n_indices || n_clients < MAX_CLIENT_ACCESSES)
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
35
clientlog.c
35
clientlog.c
|
@ -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;
|
||||
|
||||
*n_indices = ARR_GetSize(records);
|
||||
if (index < 0 || index >= *n_indices)
|
||||
return CLG_INDEXTOOLARGE;
|
||||
if (!active || index < 0 || index >= ARR_GetSize(records))
|
||||
return 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
14
clientlog.h
14
clientlog.h
|
@ -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 */
|
||||
|
|
68
cmdmon.c
68
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);
|
||||
|
||||
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:
|
||||
n_indices = CLG_GetNumberOfIndices();
|
||||
if (n_indices < 0) {
|
||||
tx_message->status = htons(STT_INACTIVE);
|
||||
return;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tx_message->data.client_accesses_by_index.next_index = htonl(first_index + i);
|
||||
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(i);
|
||||
tx_message->data.client_accesses_by_index.n_clients = htonl(j);
|
||||
}
|
||||
|
||||
|
|
12
pktlength.c
12
pktlength.c
|
@ -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);
|
||||
|
|
13
reports.h
13
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 {
|
||||
|
|
Loading…
Reference in a new issue