diff --git a/candm.h b/candm.h index 92df80c..9d5448c 100644 --- a/candm.h +++ b/candm.h @@ -322,6 +322,7 @@ typedef struct { typedef struct { uint32_t first_index; uint32_t n_clients; + uint32_t min_hits; uint32_t reset; int32_t EOR; } REQ_ClientAccessesByIndex; diff --git a/client.c b/client.c index 34cb679..b786b58 100644 --- a/client.c +++ b/client.c @@ -1243,7 +1243,7 @@ give_help(void) "\0(e.g. Sep 25, 2015 16:30:05 or 16:30:05)\0" "\0\0NTP access:\0\0" "accheck
\0Check whether address is allowed\0" - "clients [-r]\0Report on clients that have accessed the server\0" + "clients [-p ] [-r]\0Report on clients that accessed the server\0" "serverstats\0Display statistics of the server\0" "allow []\0Allow access to subnet as a default\0" "allow all []\0Allow access to subnet and all children\0" @@ -2673,18 +2673,27 @@ process_cmd_clients(char *line) CMD_Request request; CMD_Reply reply; IPAddr ip; - uint32_t i, n_clients, next_index, n_indices, reset; + uint32_t i, n_clients, next_index, n_indices, min_hits, reset; RPY_ClientAccesses_Client *client; - char name[50], *opt; + char name[50], *opt, *arg; next_index = 0; + min_hits = 0; reset = 0; while (*line) { opt = line; line = CPS_SplitWord(line); - if (strcmp(opt, "-r") == 0) + if (strcmp(opt, "-p") == 0) { + arg = line; + line = CPS_SplitWord(line); + if (sscanf(arg, "%"SCNu32, &min_hits) != 1) { + LOG(LOGS_ERR, "Invalid syntax for clients command"); + return 0; + } + } else if (strcmp(opt, "-r") == 0) { reset = 1; + } } print_header("Hostname NTP Drop Int IntL Last Cmd Drop Int Last"); @@ -2693,6 +2702,7 @@ process_cmd_clients(char *line) request.command = htons(REQ_CLIENT_ACCESSES_BY_INDEX3); request.data.client_accesses_by_index.first_index = htonl(next_index); request.data.client_accesses_by_index.n_clients = htonl(MAX_CLIENT_ACCESSES); + request.data.client_accesses_by_index.min_hits = htonl(min_hits); request.data.client_accesses_by_index.reset = htonl(reset); if (!request_reply(&request, &reply, RPY_CLIENT_ACCESSES_BY_INDEX2, 0)) diff --git a/clientlog.c b/clientlog.c index 99a1074..aee3c18 100644 --- a/clientlog.c +++ b/clientlog.c @@ -653,11 +653,12 @@ static uint32_t get_last_ago(uint32_t x, uint32_t y) /* ================================================== */ int -CLG_GetClientAccessReportByIndex(int index, int reset, +CLG_GetClientAccessReportByIndex(int index, int reset, uint32_t min_hits, RPT_ClientAccessByIndex_Report *report, struct timespec *now) { Record *record; uint32_t now_ts; + int r; if (!active || index < 0 || index >= ARR_GetSize(records)) return 0; @@ -667,25 +668,30 @@ CLG_GetClientAccessReportByIndex(int index, int reset, if (record->ip_addr.family == IPADDR_UNSPEC) return 0; - now_ts = get_ts_from_timespec(now); + r = min_hits == 0 || + record->ntp_hits >= min_hits || record->cmd_hits >= min_hits; - 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 = get_interval(record->ntp_rate); - report->cmd_interval = get_interval(record->cmd_rate); - report->ntp_timeout_interval = get_interval(record->ntp_timeout_rate); - report->last_ntp_hit_ago = get_last_ago(now_ts, record->last_ntp_hit); - report->last_cmd_hit_ago = get_last_ago(now_ts, record->last_cmd_hit); + if (r) { + now_ts = get_ts_from_timespec(now); + + 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 = get_interval(record->ntp_rate); + report->cmd_interval = get_interval(record->cmd_rate); + report->ntp_timeout_interval = get_interval(record->ntp_timeout_rate); + report->last_ntp_hit_ago = get_last_ago(now_ts, record->last_ntp_hit); + report->last_cmd_hit_ago = get_last_ago(now_ts, record->last_cmd_hit); + } if (reset) { record->ntp_hits = record->cmd_hits = 0; record->ntp_drops = record->cmd_drops = 0; } - return 1; + return r; } /* ================================================== */ diff --git a/clientlog.h b/clientlog.h index 1d0fc6a..e297621 100644 --- a/clientlog.h +++ b/clientlog.h @@ -44,7 +44,7 @@ extern int CLG_GetNtpMinPoll(void); /* And some reporting functions, for use by chronyc. */ extern int CLG_GetNumberOfIndices(void); -extern int CLG_GetClientAccessReportByIndex(int index, int reset, +extern int CLG_GetClientAccessReportByIndex(int index, int reset, uint32_t min_hits, RPT_ClientAccessByIndex_Report *report, struct timespec *now); extern void CLG_GetServerStatsReport(RPT_ServerStatsReport *report); diff --git a/cmdmon.c b/cmdmon.c index 341cc1d..6d9962e 100644 --- a/cmdmon.c +++ b/cmdmon.c @@ -1002,7 +1002,7 @@ handle_client_accesses_by_index(CMD_Request *rx_message, CMD_Reply *tx_message) RPT_ClientAccessByIndex_Report report; RPY_ClientAccesses_Client *client; int n_indices; - uint32_t i, j, req_first_index, req_n_clients, req_reset; + uint32_t i, j, req_first_index, req_n_clients, req_min_hits, req_reset; struct timespec now; SCH_GetLastEventTime(&now, NULL, NULL); @@ -1011,6 +1011,7 @@ handle_client_accesses_by_index(CMD_Request *rx_message, CMD_Reply *tx_message) 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; + req_min_hits = ntohl(rx_message->data.client_accesses_by_index.min_hits); req_reset = ntohl(rx_message->data.client_accesses_by_index.reset); n_indices = CLG_GetNumberOfIndices(); @@ -1023,7 +1024,7 @@ handle_client_accesses_by_index(CMD_Request *rx_message, CMD_Reply *tx_message) tx_message->data.client_accesses_by_index.n_indices = htonl(n_indices); for (i = req_first_index, j = 0; i < (uint32_t)n_indices && j < req_n_clients; i++) { - if (!CLG_GetClientAccessReportByIndex(i, req_reset, &report, &now)) + if (!CLG_GetClientAccessReportByIndex(i, req_reset, req_min_hits, &report, &now)) continue; client = &tx_message->data.client_accesses_by_index.clients[j++]; diff --git a/doc/chronyc.adoc b/doc/chronyc.adoc index 3e5d3d3..0156e9d 100644 --- a/doc/chronyc.adoc +++ b/doc/chronyc.adoc @@ -954,13 +954,16 @@ This command can be used to examine the effect of a series of *allow*, *allow all*, *deny*, and *deny all* commands specified either via *chronyc*, or in *chronyd*'s configuration file. -[[clients]]*clients* [*-r*]:: +[[clients]]*clients* [*-p* _packets_] *[*-r*]:: This command shows a list of clients that have accessed the server, through either the NTP or command ports. It does not include accesses over the Unix domain command socket. + -If the *-r* option is specified, *chronyd* will reset the counters of received -and dropped packets after reporting the current values. +The *-p* option specifies the minimum number of received NTP or command +packets needed to include a client in the list. The default value is 0, i.e. +all clients are reported. If the *-r* option is specified, *chronyd* will reset +the counters of received and dropped packets after reporting the current +values. + An example of the output is: +