commit 5c54abe6e7f5f95d5b4ec0ba2201ee8759a3bc03 Author: Paul Crawford Date: Mon Jun 8 17:39:17 2026 +0100 Add delay to polling to avoid blocking behaviour - Many NTP servers will block/KOD respond if polled too quickly so delay typically 0.5 second between calls - Those servers might not permit querying either, so the check_ntp_peer cannot be used as an alternative diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c index 984e86f0..9c61c26a 100644 --- a/plugins/check_ntp_time.c +++ b/plugins/check_ntp_time.c @@ -330,7 +330,7 @@ typedef struct { mp_state_enum offset_result; double offset; } offset_request_wrapper; -static offset_request_wrapper offset_request(const char *host, const char *port, int time_offset) { +static offset_request_wrapper offset_request(const char *host, const char *port, int time_offset, long poll_delay) { /* setup hints to only return results from getaddrinfo that we'd like */ struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); @@ -475,7 +475,6 @@ static offset_request_wrapper offset_request(const char *host, const char *port, if (verbose) { printf("response from peer %zu: ", i); } - read(ufds[i].fd, &req[i], sizeof(ntp_message)); struct timeval recv_time; @@ -486,6 +485,7 @@ static offset_request_wrapper offset_request(const char *host, const char *port, if (verbose) { printf("offset %.10g\n", servers[i].offset[respnum]); } + usleep(poll_delay); servers[i].stratum = req[i].stratum; servers[i].rtdisp = NTP32asDOUBLE(req[i].rtdisp); servers[i].rtdelay = NTP32asDOUBLE(req[i].rtdelay); @@ -560,6 +560,7 @@ static check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { {"timeout", required_argument, 0, 't'}, {"hostname", required_argument, 0, 'H'}, {"port", required_argument, 0, 'p'}, + {"poll-delay", required_argument, 0, 'd'}, {"output-format", required_argument, 0, output_format_index}, {0, 0, 0, 0}}; @@ -574,7 +575,7 @@ static check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { while (true) { int option = 0; - int option_char = getopt_long(argc, argv, "Vhv46qw:c:t:H:p:o:", longopts, &option); + int option_char = getopt_long(argc, argv, "Vhv46qw:c:t:H:p:o:d:", longopts, &option); if (option_char == -1 || option_char == EOF || option_char == 1) { break; } @@ -638,6 +639,12 @@ static check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { case 'o': result.config.time_offset = atoi(optarg); break; + case 'd': + result.config.poll_delay = (long)(0.5 + 1.0e6 * atof(optarg)); + if (result.config.poll_delay < 0 || result.config.poll_delay > MAX_POLL) { + usage2(_("Invalid time"), optarg); + } + break; case '4': address_family = AF_INET; break; @@ -702,7 +709,7 @@ int main(int argc, char *argv[]) { mp_subcheck sc_offset = mp_subcheck_init(); offset_request_wrapper offset_result = - offset_request(config.server_address, config.port, config.time_offset); + offset_request(config.server_address, config.port, config.time_offset, config.poll_delay); if (offset_result.offset_result == STATE_UNKNOWN) { sc_offset = @@ -754,6 +761,8 @@ void print_help(void) { printf(" %s\n", _("Offset to result in critical status (seconds)")); printf(" %s\n", "-o, --time-offset=INTEGER"); printf(" %s\n", _("Expected offset of the ntp server relative to local server (seconds)")); + printf(" %s\n", "-d, --poll-delay=DELAY"); + printf(" %s\n", _("Delay between polling to avoid KOD response (seconds, 0.0 to 5.0)")); printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); printf(UT_VERBOSE); printf(UT_OUTPUT_FORMAT); diff --git a/plugins/check_ntp_time.d/config.h b/plugins/check_ntp_time.d/config.h index 9bbd82aa..13e3e658 100644 --- a/plugins/check_ntp_time.d/config.h +++ b/plugins/check_ntp_time.d/config.h @@ -5,6 +5,12 @@ #include "thresholds.h" #include +/* Time in microseconds to delay between polling to avoid a blocking response. */ +#ifndef MAX_POLL +# define MAX_POLL (5000000L) +# define DEF_POLL (500000L) +#endif + typedef struct { char *server_address; char *port; @@ -15,6 +21,7 @@ typedef struct { mp_thresholds offset_thresholds; bool output_format_is_set; + long poll_delay; mp_output_format output_format; } check_ntp_time_config; @@ -29,6 +36,7 @@ check_ntp_time_config check_ntp_time_config_init() { .offset_thresholds = mp_thresholds_init(), .output_format_is_set = false, + .poll_delay = DEF_POLL, }; mp_range warning = mp_range_init();