Hi,I'm not really a software developer so not completely up to speed with sensing git pull requests, etc, the correct way.
I was trying to use the check_ntp_time plug-in with Nagios to check some servers that may, or may not, allow querying (as check_ntp_perr needs) and I found that some simply did not yield a sensible answer with check_ntp_time.
It seems the very rapid pooling to get the average time difference of client and host time was causing the server to block after the first one or two responses. So I thought it worth trying to add some delay so they don't block the query and that seems to work (at least in my case) if the delay is around 0.5 seconds.
While compiling the code I saw a warning about the use of strncpy() so that is also fixed. It would cause the plugin to segfault if you told it the host was a socket such as /very...very...long...path that was over something like 108 bytes.
Attached are the diffs from my local git clone for the strncpy() bug-fix, and for the added polling delay, in case they are of use to improve the code base.
Regards, Paul
commit 86be489f12669f3547fce77622fd609498037294 Author: Paul Crawford <[email protected]> Date: Mon Jun 8 17:36:41 2026 +0100 Fix safe copy of socket path - strncpy should be given size of destination, not source length - enforce null termination even if too long diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c index 3e23d0bf..984e86f0 100644 --- a/plugins/check_ntp_time.c +++ b/plugins/check_ntp_time.c @@ -394,8 +394,10 @@ static offset_request_wrapper offset_request(const char *host, const char *port, struct sockaddr_un unix_socket = { .sun_family = AF_UNIX, }; + const size_t n = sizeof(unix_socket.sun_path); - strncpy(unix_socket.sun_path, host, strlen(host)); + strncpy(unix_socket.sun_path, host, n); + unix_socket.sun_path[n - 1] = 0; /* NULL terminate always. */ if (connect(socklist[0], &unix_socket, sizeof(unix_socket))) { /* don't die here, because it is enough if there is one server
commit 5c54abe6e7f5f95d5b4ec0ba2201ee8759a3bc03 Author: Paul Crawford <[email protected]> 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 <stddef.h> +/* 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();
