From 669edf2afca4d3674019bceb037b0ccc2d938b2a Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Thu, 30 Oct 2025 21:34:50 +0100 Subject: check_curl: accept non standard compliant status line If the status line from a server ended with '\n' instead of '\r\n' (defined by RFC 9112), check_curl failed to parse it and exited with an alarm. The RFC recommends to be lenient here and this change follows that suggestion. --- plugins/check_curl.d/check_curl_helpers.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/check_curl.d/check_curl_helpers.c b/plugins/check_curl.d/check_curl_helpers.c index c3c2ba55..d1d282be 100644 --- a/plugins/check_curl.d/check_curl_helpers.c +++ b/plugins/check_curl.d/check_curl_helpers.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "../utils.h" #include "check_curl.d/config.h" #include "output.h" @@ -816,7 +817,8 @@ int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line) buf = start; } - char *first_line_end = strstr(buf, "\r\n"); + size_t length_of_first_line = strcspn(buf, "\r\n"); + const char *first_line_end = &buf[length_of_first_line]; if (first_line_end == NULL) { return -1; } @@ -826,6 +828,7 @@ int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line) if (status_line->first_line == NULL) { return -1; } + memcpy(status_line->first_line, buf, first_line_len); status_line->first_line[first_line_len] = '\0'; char *first_line_buf = strdup(status_line->first_line); @@ -833,23 +836,34 @@ int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line) /* protocol and version: "HTTP/x.x" SP or "HTTP/2" SP */ char *temp_string = strtok(first_line_buf, "/"); if (temp_string == NULL) { + if (verbose > 1) { + printf("%s: no / found\n", __func__); + } free(first_line_buf); return -1; } + if (strcmp(temp_string, "HTTP") != 0) { + if (verbose > 1) { + printf("%s: string 'HTTP' not found\n", __func__); + } free(first_line_buf); return -1; } + // try to find a space in the remaining string? + // the space after HTTP/1.1 probably temp_string = strtok(NULL, " "); if (temp_string == NULL) { + if (verbose > 1) { + printf("%s: no space after protocol definition\n", __func__); + } free(first_line_buf); return -1; } char *temp_string_2; if (strchr(temp_string, '.') != NULL) { - /* HTTP 1.x case */ strtok(temp_string, "."); status_line->http_major = (int)strtol(temp_string, &temp_string_2, 10); -- cgit v1.2.3-74-g34f1 From 6abf609ed91ab9b8e2c1fac0058d034ceef5f0e8 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Thu, 30 Oct 2025 22:23:51 +0100 Subject: add some comments to explain changed code --- plugins/check_curl.d/check_curl_helpers.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'plugins') diff --git a/plugins/check_curl.d/check_curl_helpers.c b/plugins/check_curl.d/check_curl_helpers.c index d1d282be..d49d8f07 100644 --- a/plugins/check_curl.d/check_curl_helpers.c +++ b/plugins/check_curl.d/check_curl_helpers.c @@ -817,6 +817,8 @@ int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line) buf = start; } + // Accept either LF or CRLF as end of line for the status line + // CRLF is the standard (RFC9112), but it is recommended to accept both size_t length_of_first_line = strcspn(buf, "\r\n"); const char *first_line_end = &buf[length_of_first_line]; if (first_line_end == NULL) { -- cgit v1.2.3-74-g34f1 From e867c2ebd3eeea5726136dc8e7227b256b5e117d Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Fri, 31 Oct 2025 18:13:32 +0100 Subject: check_ntp_peer: small refactoring --- plugins/check_ntp_peer.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'plugins') diff --git a/plugins/check_ntp_peer.c b/plugins/check_ntp_peer.c index 24d1c9b5..37e481c7 100644 --- a/plugins/check_ntp_peer.c +++ b/plugins/check_ntp_peer.c @@ -35,11 +35,11 @@ * *****************************************************************************/ -#include "thresholds.h" const char *progname = "check_ntp_peer"; const char *copyright = "2006-2024"; const char *email = "devel@monitoring-plugins.org"; +#include "thresholds.h" #include "common.h" #include "netutils.h" #include "utils.h" @@ -47,8 +47,6 @@ const char *email = "devel@monitoring-plugins.org"; #include "check_ntp_peer.d/config.h" static int verbose = 0; -static bool syncsource_found = false; -static bool li_alarm = false; typedef struct { int errorcode; @@ -198,9 +196,7 @@ void setup_control_request(ntp_control_message *message, uint8_t opcode, uint16_ * positive value means a success retrieving the value. * - status is set to WARNING if there's no sync.peer (otherwise OK) and is * the return value of the function. - * status is pretty much useless as syncsource_found is a global variable - * used later in main to check is the server was synchronized. It works - * so I left it alone */ + */ typedef struct { mp_state_enum state; mp_state_enum offset_result; @@ -208,6 +204,8 @@ typedef struct { double jitter; long stratum; int num_truechimers; + bool syncsource_found; + bool li_alarm; } ntp_request_result; ntp_request_result ntp_request(const check_ntp_peer_config config) { @@ -217,6 +215,8 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { .jitter = -1, .stratum = -1, .num_truechimers = 0, + .syncsource_found = false, + .li_alarm = false, }; /* Long-winded explanation: @@ -235,19 +235,16 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { * 4) Extract the offset, jitter and stratum value from the data[] * (it's ASCII) */ - int min_peer_sel = PEER_INCLUDED; - int num_candidates = 0; - void *tmp; - ntp_assoc_status_pair *peers = NULL; - int peer_offset = 0; - size_t peers_size = 0; - size_t npeers = 0; int conn = -1; my_udp_connect(config.server_address, config.port, &conn); /* keep sending requests until the server stops setting the * REM_MORE bit, though usually this is only 1 packet. */ ntp_control_message req; + ntp_assoc_status_pair *peers = NULL; + int peer_offset = 0; + size_t peers_size = 0; + size_t npeers = 0; do { setup_control_request(&req, OP_READSTAT, 1); DBG(printf("sending READSTAT request")); @@ -269,12 +266,13 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { } while (!(req.op & OP_READSTAT && ntohs(req.seq) == 1)); if (LI(req.flags) == LI_ALARM) { - li_alarm = true; + result.li_alarm = true; } /* Each peer identifier is 4 bytes in the data section, which * we represent as a ntp_assoc_status_pair datatype. */ peers_size += ntohs(req.count); + void *tmp; if ((tmp = realloc(peers, peers_size)) == NULL) { free(peers), die(STATE_UNKNOWN, "can not (re)allocate 'peers' buffer\n"); } @@ -287,13 +285,15 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { /* first, let's find out if we have a sync source, or if there are * at least some candidates. In the latter case we'll issue * a warning but go ahead with the check on them. */ + int min_peer_sel = PEER_INCLUDED; + int num_candidates = 0; for (size_t i = 0; i < npeers; i++) { if (PEER_SEL(peers[i].status) >= PEER_TRUECHIMER) { result.num_truechimers++; if (PEER_SEL(peers[i].status) >= PEER_INCLUDED) { num_candidates++; if (PEER_SEL(peers[i].status) >= PEER_SYNCSOURCE) { - syncsource_found = true; + result.syncsource_found = true; min_peer_sel = PEER_SYNCSOURCE; } } @@ -302,18 +302,18 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { if (verbose) { printf("%d candidate peers available\n", num_candidates); - } - if (verbose && syncsource_found) { - printf("synchronization source found\n"); + if (result.syncsource_found) { + printf("synchronization source found\n"); + } } - if (!syncsource_found) { + if (!result.syncsource_found) { result.state = STATE_WARNING; if (verbose) { printf("warning: no synchronization source found\n"); } } - if (li_alarm) { + if (result.li_alarm) { result.state = STATE_WARNING; if (verbose) { printf("warning: LI_ALARM bit is set\n"); @@ -634,7 +634,7 @@ int main(int argc, char *argv[]) { alarm(socket_timeout); /* This returns either OK or WARNING (See comment preceding ntp_request) */ - ntp_request_result ntp_res = ntp_request(config); + const ntp_request_result ntp_res = ntp_request(config); mp_state_enum result = STATE_UNKNOWN; if (ntp_res.offset_result == STATE_UNKNOWN) { @@ -686,9 +686,9 @@ int main(int argc, char *argv[]) { break; } - if (!syncsource_found) { + if (!ntp_res.syncsource_found) { xasprintf(&result_line, "%s %s,", result_line, _("Server not synchronized")); - } else if (li_alarm) { + } else if (ntp_res.li_alarm) { xasprintf(&result_line, "%s %s,", result_line, _("Server has the LI_ALARM bit set")); } -- cgit v1.2.3-74-g34f1 From 6392a0f77635d82b9b68bcbd1be4c6acc478767f Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Tue, 4 Nov 2025 10:13:39 +0100 Subject: check_ntp_peer: implement new output functionality --- plugins/check_ntp_peer.c | 248 ++++++++++++++++++++------------------ plugins/check_ntp_peer.d/config.h | 58 +++++---- 2 files changed, 164 insertions(+), 142 deletions(-) (limited to 'plugins') diff --git a/plugins/check_ntp_peer.c b/plugins/check_ntp_peer.c index 37e481c7..0498a7d4 100644 --- a/plugins/check_ntp_peer.c +++ b/plugins/check_ntp_peer.c @@ -39,6 +39,9 @@ const char *progname = "check_ntp_peer"; const char *copyright = "2006-2024"; const char *email = "devel@monitoring-plugins.org"; +#include "output.h" +#include "perfdata.h" +#include #include "thresholds.h" #include "common.h" #include "netutils.h" @@ -329,7 +332,7 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { if (verbose) { printf("Getting offset, jitter and stratum for peer %.2x\n", ntohs(peers[i].assoc)); } - xasprintf(&data, ""); + data = strdup(""); do { setup_control_request(&req, OP_READVAR, 2); req.assoc = peers[i].assoc; @@ -518,36 +521,76 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { case 'q': result.config.quiet = true; break; - case 'w': - result.config.owarn = optarg; - break; - case 'c': - result.config.ocrit = optarg; - break; - case 'W': + case 'w': { + mp_range_parsed tmp = mp_parse_range_string(optarg); + if (tmp.error != MP_PARSING_SUCCES) { + die(STATE_UNKNOWN, "failed to parse warning offset threshold"); + } + + mp_thresholds_set_warn(result.config.offset_thresholds, tmp.range); + } break; + case 'c': { + mp_range_parsed tmp = mp_parse_range_string(optarg); + if (tmp.error != MP_PARSING_SUCCES) { + die(STATE_UNKNOWN, "failed to parse critical offset threshold"); + } + + mp_thresholds_set_crit(result.config.offset_thresholds, tmp.range); + } break; + case 'W': { result.config.do_stratum = true; - result.config.swarn = optarg; - break; - case 'C': + mp_range_parsed tmp = mp_parse_range_string(optarg); + if (tmp.error != MP_PARSING_SUCCES) { + die(STATE_UNKNOWN, "failed to parse warning stratum threshold"); + } + + mp_thresholds_set_warn(result.config.stratum_thresholds, tmp.range); + } break; + case 'C': { result.config.do_stratum = true; - result.config.scrit = optarg; - break; - case 'j': + mp_range_parsed tmp = mp_parse_range_string(optarg); + if (tmp.error != MP_PARSING_SUCCES) { + die(STATE_UNKNOWN, "failed to parse critical stratum threshold"); + } + + mp_thresholds_set_crit(result.config.stratum_thresholds, tmp.range); + } break; + case 'j': { result.config.do_jitter = true; - result.config.jwarn = optarg; - break; - case 'k': + mp_range_parsed tmp = mp_parse_range_string(optarg); + if (tmp.error != MP_PARSING_SUCCES) { + die(STATE_UNKNOWN, "failed to parse warning jitter threshold"); + } + + mp_thresholds_set_warn(result.config.jitter_thresholds, tmp.range); + } break; + case 'k': { result.config.do_jitter = true; - result.config.jcrit = optarg; - break; - case 'm': + mp_range_parsed tmp = mp_parse_range_string(optarg); + if (tmp.error != MP_PARSING_SUCCES) { + die(STATE_UNKNOWN, "failed to parse critical jitter threshold"); + } + + mp_thresholds_set_crit(result.config.jitter_thresholds, tmp.range); + } break; + case 'm': { result.config.do_truechimers = true; - result.config.twarn = optarg; - break; - case 'n': + mp_range_parsed tmp = mp_parse_range_string(optarg); + if (tmp.error != MP_PARSING_SUCCES) { + die(STATE_UNKNOWN, "failed to parse warning truechimer threshold"); + } + + mp_thresholds_set_warn(result.config.truechimer_thresholds, tmp.range); + } break; + case 'n': { result.config.do_truechimers = true; - result.config.tcrit = optarg; - break; + mp_range_parsed tmp = mp_parse_range_string(optarg); + if (tmp.error != MP_PARSING_SUCCES) { + die(STATE_UNKNOWN, "failed to parse critical truechimer threshold"); + } + + mp_thresholds_set_crit(result.config.truechimer_thresholds, tmp.range); + } break; case 'H': if (!is_host(optarg)) { usage2(_("Invalid hostname/address"), optarg); @@ -581,11 +624,6 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { usage4(_("Hostname was not supplied")); } - set_thresholds(&result.config.offset_thresholds, result.config.owarn, result.config.ocrit); - set_thresholds(&result.config.jitter_thresholds, result.config.jwarn, result.config.jcrit); - set_thresholds(&result.config.stratum_thresholds, result.config.swarn, result.config.scrit); - set_thresholds(&result.config.truechimer_thresholds, result.config.twarn, result.config.tcrit); - return result; } @@ -635,124 +673,100 @@ int main(int argc, char *argv[]) { /* This returns either OK or WARNING (See comment preceding ntp_request) */ const ntp_request_result ntp_res = ntp_request(config); - mp_state_enum result = STATE_UNKNOWN; + mp_check overall = mp_check_init(); + mp_subcheck sc_offset = mp_subcheck_init(); + xasprintf(&sc_offset.output, "offset"); if (ntp_res.offset_result == STATE_UNKNOWN) { /* if there's no sync peer (this overrides ntp_request output): */ - result = (config.quiet ? STATE_UNKNOWN : STATE_CRITICAL); + sc_offset = + mp_set_subcheck_state(sc_offset, (config.quiet ? STATE_UNKNOWN : STATE_CRITICAL)); } else { /* Be quiet if there's no candidates either */ - if (config.quiet && result == STATE_WARNING) { - result = STATE_UNKNOWN; + mp_state_enum tmp = STATE_OK; + if (config.quiet && ntp_res.state == STATE_WARNING) { + tmp = STATE_UNKNOWN; } - result = max_state_alt(result, get_status(fabs(ntp_res.offset), config.offset_thresholds)); + + mp_perfdata pd_offset = perfdata_init(); + pd_offset.value = mp_create_pd_value(fabs(ntp_res.offset)); + pd_offset = mp_pd_set_thresholds(pd_offset, config.offset_thresholds); + + tmp = max_state_alt(tmp, mp_get_pd_status(pd_offset)); + sc_offset = mp_set_subcheck_state(sc_offset, tmp); } - mp_state_enum oresult = result; - mp_state_enum tresult = STATE_UNKNOWN; + mp_add_subcheck_to_check(&overall, sc_offset); + // truechimers if (config.do_truechimers) { - tresult = get_status(ntp_res.num_truechimers, config.truechimer_thresholds); - result = max_state_alt(result, tresult); - } + mp_subcheck sc_truechimers; + xasprintf(&sc_truechimers.output, "truechimers: %i", ntp_res.num_truechimers); - mp_state_enum sresult = STATE_UNKNOWN; + mp_perfdata pd_truechimers = perfdata_init(); + pd_truechimers.value = mp_create_pd_value(ntp_res.num_truechimers); + mp_pd_set_thresholds(pd_truechimers, config.truechimer_thresholds); + mp_add_perfdata_to_subcheck(&sc_truechimers, pd_truechimers); - if (config.do_stratum) { - sresult = get_status((double)ntp_res.stratum, config.stratum_thresholds); - result = max_state_alt(result, sresult); + sc_truechimers = mp_set_subcheck_state(sc_truechimers, mp_get_pd_status(pd_truechimers)); + + mp_add_subcheck_to_check(&overall, sc_truechimers); } - mp_state_enum jresult = STATE_UNKNOWN; + if (config.do_stratum) { + mp_subcheck sc_stratum = mp_subcheck_init(); + xasprintf(&sc_stratum.output, "stratum: %li", ntp_res.stratum); - if (config.do_jitter) { - jresult = get_status(ntp_res.jitter, config.jitter_thresholds); - result = max_state_alt(result, jresult); + mp_perfdata pd_stratum = perfdata_init(); + pd_stratum.value = mp_create_pd_value(ntp_res.stratum); + pd_stratum = mp_pd_set_thresholds(pd_stratum, config.stratum_thresholds); + mp_add_perfdata_to_subcheck(&sc_stratum, pd_stratum); + + sc_stratum = mp_set_subcheck_state(sc_stratum, mp_get_pd_status(pd_stratum)); + + mp_add_subcheck_to_check(&overall, sc_stratum); } - char *result_line; - switch (result) { - case STATE_CRITICAL: - xasprintf(&result_line, _("NTP CRITICAL:")); - break; - case STATE_WARNING: - xasprintf(&result_line, _("NTP WARNING:")); - break; - case STATE_OK: - xasprintf(&result_line, _("NTP OK:")); - break; - default: - xasprintf(&result_line, _("NTP UNKNOWN:")); - break; + if (config.do_jitter) { + mp_subcheck sc_jitter = mp_subcheck_init(); + xasprintf(&sc_jitter.output, "jitter: %f", ntp_res.jitter); + + mp_perfdata pd_jitter = perfdata_init(); + pd_jitter.value = mp_create_pd_value(ntp_res.jitter); + pd_jitter = mp_pd_set_thresholds(pd_jitter, config.jitter_thresholds); + mp_add_perfdata_to_subcheck(&sc_jitter, pd_jitter); + + sc_jitter = mp_set_subcheck_state(sc_jitter, mp_get_pd_status(pd_jitter)); + mp_add_subcheck_to_check(&overall, sc_jitter); } + mp_subcheck sc_other_info = mp_subcheck_init(); + sc_other_info = mp_set_subcheck_default_state(sc_other_info, STATE_OK); if (!ntp_res.syncsource_found) { - xasprintf(&result_line, "%s %s,", result_line, _("Server not synchronized")); + xasprintf(&sc_other_info.output, "%s", _("Server not synchronized")); + mp_add_subcheck_to_check(&overall, sc_other_info); } else if (ntp_res.li_alarm) { - xasprintf(&result_line, "%s %s,", result_line, _("Server has the LI_ALARM bit set")); + xasprintf(&sc_other_info.output, "%s", _("Server has the LI_ALARM bit set")); + mp_add_subcheck_to_check(&overall, sc_other_info); } - char *perfdata_line; - if (ntp_res.offset_result == STATE_UNKNOWN) { - xasprintf(&result_line, "%s %s", result_line, _("Offset unknown")); - xasprintf(&perfdata_line, ""); - } else if (oresult == STATE_WARNING) { - xasprintf(&result_line, "%s %s %.10g secs (WARNING)", result_line, _("Offset"), - ntp_res.offset); - } else if (oresult == STATE_CRITICAL) { - xasprintf(&result_line, "%s %s %.10g secs (CRITICAL)", result_line, _("Offset"), - ntp_res.offset); - } else { - xasprintf(&result_line, "%s %s %.10g secs", result_line, _("Offset"), ntp_res.offset); - } - xasprintf(&perfdata_line, "%s", perfd_offset(ntp_res.offset, config.offset_thresholds)); - - if (config.do_jitter) { - if (jresult == STATE_WARNING) { - xasprintf(&result_line, "%s, jitter=%f (WARNING)", result_line, ntp_res.jitter); - } else if (jresult == STATE_CRITICAL) { - xasprintf(&result_line, "%s, jitter=%f (CRITICAL)", result_line, ntp_res.jitter); - } else { - xasprintf(&result_line, "%s, jitter=%f", result_line, ntp_res.jitter); - } - xasprintf(&perfdata_line, "%s %s", perfdata_line, - perfd_jitter(ntp_res.jitter, config.do_jitter, config.jitter_thresholds)); - } + { + mp_subcheck sc_offset = mp_subcheck_init(); + sc_offset = mp_set_subcheck_default_state(sc_offset, STATE_OK); + xasprintf(&sc_offset.output, "offset: %.10gs", ntp_res.offset); - if (config.do_stratum) { - if (sresult == STATE_WARNING) { - xasprintf(&result_line, "%s, stratum=%li (WARNING)", result_line, ntp_res.stratum); - } else if (sresult == STATE_CRITICAL) { - xasprintf(&result_line, "%s, stratum=%li (CRITICAL)", result_line, ntp_res.stratum); - } else { - xasprintf(&result_line, "%s, stratum=%li", result_line, ntp_res.stratum); - } - xasprintf(&perfdata_line, "%s %s", perfdata_line, - perfd_stratum(ntp_res.stratum, config.do_stratum, config.stratum_thresholds)); - } + mp_perfdata pd_offset = perfdata_init(); + pd_offset.value = mp_create_pd_value(ntp_res.offset); + pd_offset = mp_pd_set_thresholds(pd_offset, config.offset_thresholds); - if (config.do_truechimers) { - if (tresult == STATE_WARNING) { - xasprintf(&result_line, "%s, truechimers=%i (WARNING)", result_line, - ntp_res.num_truechimers); - } else if (tresult == STATE_CRITICAL) { - xasprintf(&result_line, "%s, truechimers=%i (CRITICAL)", result_line, - ntp_res.num_truechimers); - } else { - xasprintf(&result_line, "%s, truechimers=%i", result_line, ntp_res.num_truechimers); - } - xasprintf(&perfdata_line, "%s %s", perfdata_line, - perfd_truechimers(ntp_res.num_truechimers, config.do_truechimers, - config.truechimer_thresholds)); + sc_offset = mp_set_subcheck_state(sc_offset, ntp_res.offset_result); } - printf("%s|%s\n", result_line, perfdata_line); - if (config.server_address != NULL) { free(config.server_address); } - exit(result); + mp_exit(overall); } void print_help(void) { diff --git a/plugins/check_ntp_peer.d/config.h b/plugins/check_ntp_peer.d/config.h index 00e6b05d..396edea6 100644 --- a/plugins/check_ntp_peer.d/config.h +++ b/plugins/check_ntp_peer.d/config.h @@ -1,6 +1,7 @@ #pragma once #include "../../config.h" +#include "perfdata.h" #include "thresholds.h" #include @@ -16,26 +17,18 @@ typedef struct { // truechimer stuff bool do_truechimers; - char *twarn; - char *tcrit; - thresholds *truechimer_thresholds; + mp_thresholds truechimer_thresholds; - char *owarn; - char *ocrit; - thresholds *offset_thresholds; + // offset thresholds + mp_thresholds offset_thresholds; // stratum stuff bool do_stratum; - char *swarn; - char *scrit; - thresholds *stratum_thresholds; + mp_thresholds stratum_thresholds; // jitter stuff bool do_jitter; - char *jwarn; - char *jcrit; - thresholds *jitter_thresholds; - + mp_thresholds jitter_thresholds; } check_ntp_peer_config; check_ntp_peer_config check_ntp_peer_config_init() { @@ -45,23 +38,38 @@ check_ntp_peer_config check_ntp_peer_config_init() { .quiet = false, .do_truechimers = false, - .twarn = "0:", - .tcrit = "0:", - .truechimer_thresholds = NULL, + .truechimer_thresholds = mp_thresholds_init(), - .owarn = "60", - .ocrit = "120", - .offset_thresholds = NULL, + .offset_thresholds = mp_thresholds_init(), .do_stratum = false, - .swarn = "-1:16", - .scrit = "-1:16", - .stratum_thresholds = NULL, + .stratum_thresholds = mp_thresholds_init(), .do_jitter = false, - .jwarn = "-1:5000", - .jcrit = "-1:10000", - .jitter_thresholds = NULL, + .jitter_thresholds = mp_thresholds_init(), }; + + mp_range stratum_default = mp_range_init(); + stratum_default = mp_range_set_start(stratum_default, mp_create_pd_value(-1)); + stratum_default = mp_range_set_end(stratum_default, mp_create_pd_value(16)); + tmp.stratum_thresholds = mp_thresholds_set_warn(tmp.stratum_thresholds, stratum_default); + tmp.stratum_thresholds = mp_thresholds_set_crit(tmp.stratum_thresholds, stratum_default); + + mp_range jitter_w_default = mp_range_init(); + jitter_w_default = mp_range_set_start(jitter_w_default, mp_create_pd_value(-1)); + jitter_w_default = mp_range_set_end(jitter_w_default, mp_create_pd_value(5000)); + tmp.jitter_thresholds = mp_thresholds_set_warn(tmp.jitter_thresholds, jitter_w_default); + + mp_range jitter_c_default = mp_range_init(); + jitter_c_default = mp_range_set_start(jitter_c_default, mp_create_pd_value(-1)); + jitter_c_default = mp_range_set_end(jitter_c_default, mp_create_pd_value(10000)); + tmp.jitter_thresholds = mp_thresholds_set_crit(tmp.jitter_thresholds, jitter_c_default); + + mp_range offset_w_default = mp_range_init(); + offset_w_default = mp_range_set_start(offset_w_default, mp_create_pd_value(60)); + tmp.offset_thresholds = mp_thresholds_set_warn(tmp.offset_thresholds, offset_w_default); + mp_range offset_c_default = mp_range_init(); + offset_c_default = mp_range_set_start(offset_c_default, mp_create_pd_value(120)); + tmp.offset_thresholds = mp_thresholds_set_crit(tmp.offset_thresholds, offset_c_default); return tmp; } -- cgit v1.2.3-74-g34f1 From b35853ee4e10c4485a9521d77c95aecae6573e64 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Tue, 4 Nov 2025 12:08:59 +0100 Subject: check_ntp_time: implement modern output --- plugins/check_ntp_time.c | 160 +++++++++++++++++++------------------- plugins/check_ntp_time.d/config.h | 13 +++- 2 files changed, 93 insertions(+), 80 deletions(-) (limited to 'plugins') diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c index ad69b804..eee9c298 100644 --- a/plugins/check_ntp_time.c +++ b/plugins/check_ntp_time.c @@ -34,12 +34,10 @@ * *****************************************************************************/ -const char *progname = "check_ntp_time"; -const char *copyright = "2006-2024"; -const char *email = "devel@monitoring-plugins.org"; - +#include "output.h" #include "common.h" #include "netutils.h" +#include "perfdata.h" #include "utils.h" #include "states.h" #include "thresholds.h" @@ -47,6 +45,10 @@ const char *email = "devel@monitoring-plugins.org"; static int verbose = 0; +const char *progname = "check_ntp_time"; +const char *copyright = "2006-2024"; +const char *email = "devel@monitoring-plugins.org"; + typedef struct { int errorcode; check_ntp_time_config config; @@ -61,9 +63,6 @@ void print_usage(void); # define AVG_NUM 4 #endif -/* max size of control message data */ -#define MAX_CM_SIZE 468 - /* this structure holds everything in an ntp request/response as per rfc1305 */ typedef struct { uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ @@ -169,7 +168,9 @@ typedef struct { : 0) /* convert a struct timeval to a double */ -#define TVasDOUBLE(x) (double)(x.tv_sec + (0.000001 * x.tv_usec)) +static double TVasDOUBLE(struct timeval time) { + return ((double)time.tv_sec + (0.000001 * (double)time.tv_usec)); +} /* convert an ntp 64-bit fp number to a struct timeval */ #define NTP64toTV(n, t) \ @@ -262,8 +263,8 @@ void setup_request(ntp_message *message) { /* select the "best" server from a list of servers, and return its index. * this is done by filtering servers based on stratum, dispersion, and * finally round-trip delay. */ -int best_offset_server(const ntp_server_results *slist, int nservers) { - int best_server = -1; +static int best_offset_server(const ntp_server_results *slist, int nservers) { + int best_server_index = -1; /* for each server */ for (int cserver = 0; cserver < nservers; cserver++) { @@ -286,33 +287,33 @@ int best_offset_server(const ntp_server_results *slist, int nservers) { } /* If we don't have a server yet, use the first one */ - if (best_server == -1) { - best_server = cserver; - DBG(printf("using peer %d as our first candidate\n", best_server)); + if (best_server_index == -1) { + best_server_index = cserver; + DBG(printf("using peer %d as our first candidate\n", best_server_index)); continue; } /* compare the server to the best one we've seen so far */ /* does it have an equal or better stratum? */ - DBG(printf("comparing peer %d with peer %d\n", cserver, best_server)); - if (slist[cserver].stratum <= slist[best_server].stratum) { - DBG(printf("stratum for peer %d <= peer %d\n", cserver, best_server)); + DBG(printf("comparing peer %d with peer %d\n", cserver, best_server_index)); + if (slist[cserver].stratum <= slist[best_server_index].stratum) { + DBG(printf("stratum for peer %d <= peer %d\n", cserver, best_server_index)); /* does it have an equal or better dispersion? */ - if (slist[cserver].rtdisp <= slist[best_server].rtdisp) { - DBG(printf("dispersion for peer %d <= peer %d\n", cserver, best_server)); + if (slist[cserver].rtdisp <= slist[best_server_index].rtdisp) { + DBG(printf("dispersion for peer %d <= peer %d\n", cserver, best_server_index)); /* does it have a better rtdelay? */ - if (slist[cserver].rtdelay < slist[best_server].rtdelay) { - DBG(printf("rtdelay for peer %d < peer %d\n", cserver, best_server)); - best_server = cserver; - DBG(printf("peer %d is now our best candidate\n", best_server)); + if (slist[cserver].rtdelay < slist[best_server_index].rtdelay) { + DBG(printf("rtdelay for peer %d < peer %d\n", cserver, best_server_index)); + best_server_index = cserver; + DBG(printf("peer %d is now our best candidate\n", best_server_index)); } } } } - if (best_server >= 0) { - DBG(printf("best server selected: peer %d\n", best_server)); - return best_server; + if (best_server_index >= 0) { + DBG(printf("best server selected: peer %d\n", best_server_index)); + return best_server_index; } DBG(printf("no peers meeting synchronization criteria :(\n")); return -1; @@ -323,7 +324,11 @@ int best_offset_server(const ntp_server_results *slist, int nservers) { * we don't waste time sitting around waiting for single packets. * - we also "manually" handle resolving host names and connecting, because * we have to do it in a way that our lazy macros don't handle currently :( */ -double offset_request(const char *host, const char *port, mp_state_enum *status, int time_offset) { +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) { /* setup hints to only return results from getaddrinfo that we'd like */ struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); @@ -462,11 +467,16 @@ double offset_request(const char *host, const char *port, mp_state_enum *status, die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n"); } + offset_request_wrapper result = { + .offset = 0, + .offset_result = STATE_UNKNOWN, + }; + /* now, pick the best server from the list */ double avg_offset = 0.; int best_index = best_offset_server(servers, num_hosts); if (best_index < 0) { - *status = STATE_UNKNOWN; + result.offset_result = STATE_UNKNOWN; } else { /* finally, calculate the average offset */ for (int i = 0; i < servers[best_index].num_responses; i++) { @@ -488,10 +498,12 @@ double offset_request(const char *host, const char *port, mp_state_enum *status, if (verbose) { printf("overall average offset: %.10g\n", avg_offset); } - return avg_offset; + + result.offset = avg_offset; + return result; } -check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { +static check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { static struct option longopts[] = {{"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, 'v'}, @@ -515,9 +527,6 @@ check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { .config = check_ntp_time_config_init(), }; - char *owarn = "60"; - char *ocrit = "120"; - while (true) { int option = 0; int option_char = getopt_long(argc, argv, "Vhv46qw:c:t:H:p:o:", longopts, &option); @@ -540,12 +549,24 @@ check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { case 'q': result.config.quiet = true; break; - case 'w': - owarn = optarg; - break; - case 'c': - ocrit = optarg; - break; + case 'w': { + mp_range_parsed tmp = mp_parse_range_string(optarg); + if (tmp.error != MP_PARSING_SUCCES) { + die(STATE_UNKNOWN, "failed to parse warning threshold"); + } + + result.config.offset_thresholds = + mp_thresholds_set_warn(result.config.offset_thresholds, tmp.range); + } break; + case 'c': { + mp_range_parsed tmp = mp_parse_range_string(optarg); + if (tmp.error != MP_PARSING_SUCCES) { + die(STATE_UNKNOWN, "failed to parse crit threshold"); + } + + result.config.offset_thresholds = + mp_thresholds_set_crit(result.config.offset_thresholds, tmp.range); + } break; case 'H': if (!is_host(optarg)) { usage2(_("Invalid hostname/address"), optarg); @@ -582,16 +603,9 @@ check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { usage4(_("Hostname was not supplied")); } - set_thresholds(&result.config.offset_thresholds, owarn, ocrit); - return result; } -char *perfd_offset(double offset, thresholds *offset_thresholds) { - return fperfdata("offset", offset, "s", true, offset_thresholds->warning->end, true, - offset_thresholds->critical->end, false, 0, false, 0); -} - int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); @@ -614,46 +628,36 @@ int main(int argc, char *argv[]) { /* set socket timeout */ alarm(socket_timeout); - mp_state_enum offset_result = STATE_OK; - mp_state_enum result = STATE_OK; - double offset = - offset_request(config.server_address, config.port, &offset_result, config.time_offset); - if (offset_result == STATE_UNKNOWN) { - result = ((!config.quiet) ? STATE_UNKNOWN : STATE_CRITICAL); - } else { - result = get_status(fabs(offset), config.offset_thresholds); - } + mp_check overall = mp_check_init(); - char *result_line; - switch (result) { - case STATE_CRITICAL: - xasprintf(&result_line, _("NTP CRITICAL:")); - break; - case STATE_WARNING: - xasprintf(&result_line, _("NTP WARNING:")); - break; - case STATE_OK: - xasprintf(&result_line, _("NTP OK:")); - break; - default: - xasprintf(&result_line, _("NTP UNKNOWN:")); - break; - } + mp_subcheck sc_offset = mp_subcheck_init(); + offset_request_wrapper offset_result = + offset_request(config.server_address, config.port, config.time_offset); - char *perfdata_line; - if (offset_result == STATE_UNKNOWN) { - xasprintf(&result_line, "%s %s", result_line, _("Offset unknown")); - xasprintf(&perfdata_line, ""); - } else { - xasprintf(&result_line, "%s %s %.10g secs", result_line, _("Offset"), offset); - xasprintf(&perfdata_line, "%s", perfd_offset(offset, config.offset_thresholds)); + if (offset_result.offset_result == STATE_UNKNOWN) { + sc_offset = + mp_set_subcheck_state(sc_offset, (!config.quiet) ? STATE_UNKNOWN : STATE_CRITICAL); + xasprintf(&sc_offset.output, "Offset unknown"); + mp_add_subcheck_to_check(&overall, sc_offset); + mp_exit(overall); } - printf("%s|%s\n", result_line, perfdata_line); + + xasprintf(&sc_offset.output, "Offset: %.10g s", offset_result.offset); + + mp_perfdata pd_offset = perfdata_init(); + pd_offset = mp_set_pd_value(pd_offset, fabs(offset_result.offset)); + pd_offset.label = "offset"; + pd_offset = mp_pd_set_thresholds(pd_offset, config.offset_thresholds); + + sc_offset = mp_set_subcheck_state(sc_offset, mp_get_pd_status(pd_offset)); + + mp_add_perfdata_to_subcheck(&sc_offset, pd_offset); + mp_add_subcheck_to_check(&overall, sc_offset); if (config.server_address != NULL) { free(config.server_address); } - exit(result); + mp_exit(overall); } void print_help(void) { diff --git a/plugins/check_ntp_time.d/config.h b/plugins/check_ntp_time.d/config.h index 99dabbbd..a62e4ceb 100644 --- a/plugins/check_ntp_time.d/config.h +++ b/plugins/check_ntp_time.d/config.h @@ -11,7 +11,7 @@ typedef struct { bool quiet; int time_offset; - thresholds *offset_thresholds; + mp_thresholds offset_thresholds; } check_ntp_time_config; check_ntp_time_config check_ntp_time_config_init() { @@ -22,7 +22,16 @@ check_ntp_time_config check_ntp_time_config_init() { .quiet = false, .time_offset = 0, - .offset_thresholds = NULL, + .offset_thresholds = mp_thresholds_init(), }; + + mp_range warning = mp_range_init(); + warning = mp_range_set_end(warning, mp_create_pd_value(60)); + tmp.offset_thresholds = mp_thresholds_set_warn(tmp.offset_thresholds, warning); + + mp_range critical = mp_range_init(); + critical = mp_range_set_end(warning, mp_create_pd_value(120)); + tmp.offset_thresholds = mp_thresholds_set_crit(tmp.offset_thresholds, critical); + return tmp; } -- cgit v1.2.3-74-g34f1 From 697374af93322fdd584a219e0cf45021b463404e Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Tue, 4 Nov 2025 12:11:24 +0100 Subject: Forgot to actually set thresholds --- plugins/check_ntp_peer.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'plugins') diff --git a/plugins/check_ntp_peer.c b/plugins/check_ntp_peer.c index 0498a7d4..68b2fa9c 100644 --- a/plugins/check_ntp_peer.c +++ b/plugins/check_ntp_peer.c @@ -527,7 +527,8 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { die(STATE_UNKNOWN, "failed to parse warning offset threshold"); } - mp_thresholds_set_warn(result.config.offset_thresholds, tmp.range); + result.config.offset_thresholds = + mp_thresholds_set_warn(result.config.offset_thresholds, tmp.range); } break; case 'c': { mp_range_parsed tmp = mp_parse_range_string(optarg); @@ -535,7 +536,8 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { die(STATE_UNKNOWN, "failed to parse critical offset threshold"); } - mp_thresholds_set_crit(result.config.offset_thresholds, tmp.range); + result.config.offset_thresholds = + mp_thresholds_set_crit(result.config.offset_thresholds, tmp.range); } break; case 'W': { result.config.do_stratum = true; @@ -544,7 +546,8 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { die(STATE_UNKNOWN, "failed to parse warning stratum threshold"); } - mp_thresholds_set_warn(result.config.stratum_thresholds, tmp.range); + result.config.stratum_thresholds = + mp_thresholds_set_warn(result.config.stratum_thresholds, tmp.range); } break; case 'C': { result.config.do_stratum = true; @@ -553,7 +556,8 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { die(STATE_UNKNOWN, "failed to parse critical stratum threshold"); } - mp_thresholds_set_crit(result.config.stratum_thresholds, tmp.range); + result.config.stratum_thresholds = + mp_thresholds_set_crit(result.config.stratum_thresholds, tmp.range); } break; case 'j': { result.config.do_jitter = true; @@ -562,7 +566,8 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { die(STATE_UNKNOWN, "failed to parse warning jitter threshold"); } - mp_thresholds_set_warn(result.config.jitter_thresholds, tmp.range); + result.config.jitter_thresholds = + mp_thresholds_set_warn(result.config.jitter_thresholds, tmp.range); } break; case 'k': { result.config.do_jitter = true; @@ -571,7 +576,8 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { die(STATE_UNKNOWN, "failed to parse critical jitter threshold"); } - mp_thresholds_set_crit(result.config.jitter_thresholds, tmp.range); + result.config.jitter_thresholds = + mp_thresholds_set_crit(result.config.jitter_thresholds, tmp.range); } break; case 'm': { result.config.do_truechimers = true; @@ -580,7 +586,8 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { die(STATE_UNKNOWN, "failed to parse warning truechimer threshold"); } - mp_thresholds_set_warn(result.config.truechimer_thresholds, tmp.range); + result.config.truechimer_thresholds = + mp_thresholds_set_warn(result.config.truechimer_thresholds, tmp.range); } break; case 'n': { result.config.do_truechimers = true; @@ -589,7 +596,8 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { die(STATE_UNKNOWN, "failed to parse critical truechimer threshold"); } - mp_thresholds_set_crit(result.config.truechimer_thresholds, tmp.range); + result.config.truechimer_thresholds = + mp_thresholds_set_crit(result.config.truechimer_thresholds, tmp.range); } break; case 'H': if (!is_host(optarg)) { -- cgit v1.2.3-74-g34f1 From 16daa06e439da1541cbcb4e0622131838b21ba0f Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Wed, 5 Nov 2025 10:41:34 +0100 Subject: check_ntp_time: actually accept offset if known --- plugins/check_ntp_time.c | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins') diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c index eee9c298..d554089d 100644 --- a/plugins/check_ntp_time.c +++ b/plugins/check_ntp_time.c @@ -478,6 +478,7 @@ static offset_request_wrapper offset_request(const char *host, const char *port, if (best_index < 0) { result.offset_result = STATE_UNKNOWN; } else { + result.offset_result = STATE_OK; /* finally, calculate the average offset */ for (int i = 0; i < servers[best_index].num_responses; i++) { avg_offset += servers[best_index].offset[i]; -- cgit v1.2.3-74-g34f1 From cadcfaecbec56d2ecf44bb33bb394ca815240127 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Wed, 5 Nov 2025 10:42:12 +0100 Subject: check_ntp_time: fix time-offset argument and description --- plugins/check_ntp_time.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c index d554089d..8d97f2b9 100644 --- a/plugins/check_ntp_time.c +++ b/plugins/check_ntp_time.c @@ -511,7 +511,7 @@ static check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { {"use-ipv4", no_argument, 0, '4'}, {"use-ipv6", no_argument, 0, '6'}, {"quiet", no_argument, 0, 'q'}, - {"time-offset", optional_argument, 0, 'o'}, + {"time-offset", required_argument, 0, 'o'}, {"warning", required_argument, 0, 'w'}, {"critical", required_argument, 0, 'c'}, {"timeout", required_argument, 0, 't'}, @@ -682,7 +682,7 @@ void print_help(void) { printf(" %s\n", _("Offset to result in warning status (seconds)")); printf(" %s\n", "-c, --critical=THRESHOLD"); printf(" %s\n", _("Offset to result in critical status (seconds)")); - printf(" %s\n", "-o, --time_offset=INTEGER"); + printf(" %s\n", "-o, --time-offset=INTEGER"); printf(" %s\n", _("Expected offset of the ntp server relative to local server (seconds)")); printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); printf(UT_VERBOSE); -- cgit v1.2.3-74-g34f1 From 7b226257b7df01dd80af07c39e0f49fdcf84cee4 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Wed, 5 Nov 2025 10:42:43 +0100 Subject: check_ntp_time: reduce number of significant bits a bit --- plugins/check_ntp_time.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c index 8d97f2b9..7c3fc24d 100644 --- a/plugins/check_ntp_time.c +++ b/plugins/check_ntp_time.c @@ -643,11 +643,12 @@ int main(int argc, char *argv[]) { mp_exit(overall); } - xasprintf(&sc_offset.output, "Offset: %.10g s", offset_result.offset); + xasprintf(&sc_offset.output, "Offset: %.6fs", offset_result.offset); mp_perfdata pd_offset = perfdata_init(); pd_offset = mp_set_pd_value(pd_offset, fabs(offset_result.offset)); pd_offset.label = "offset"; + pd_offset.uom = "s"; pd_offset = mp_pd_set_thresholds(pd_offset, config.offset_thresholds); sc_offset = mp_set_subcheck_state(sc_offset, mp_get_pd_status(pd_offset)); -- cgit v1.2.3-74-g34f1 From 99351f0560a5f457e499417366bdfdec0172a428 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Wed, 5 Nov 2025 11:54:34 +0100 Subject: check_ntp_peer: fix several missing things and errors --- plugins/check_ntp_peer.c | 16 ++++++++++++++-- plugins/check_ntp_peer.d/config.h | 5 +++-- 2 files changed, 17 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/check_ntp_peer.c b/plugins/check_ntp_peer.c index 68b2fa9c..032f8ea4 100644 --- a/plugins/check_ntp_peer.c +++ b/plugins/check_ntp_peer.c @@ -689,6 +689,7 @@ int main(int argc, char *argv[]) { /* if there's no sync peer (this overrides ntp_request output): */ sc_offset = mp_set_subcheck_state(sc_offset, (config.quiet ? STATE_UNKNOWN : STATE_CRITICAL)); + xasprintf(&sc_offset.output, "%s unknown", sc_offset.output); } else { /* Be quiet if there's no candidates either */ mp_state_enum tmp = STATE_OK; @@ -696,9 +697,14 @@ int main(int argc, char *argv[]) { tmp = STATE_UNKNOWN; } + xasprintf(&sc_offset.output, "%s: %.6fs", sc_offset.output, ntp_res.offset); + mp_perfdata pd_offset = perfdata_init(); pd_offset.value = mp_create_pd_value(fabs(ntp_res.offset)); pd_offset = mp_pd_set_thresholds(pd_offset, config.offset_thresholds); + pd_offset.label = "offset"; + pd_offset.uom = "s"; + mp_add_perfdata_to_subcheck(&sc_offset, pd_offset); tmp = max_state_alt(tmp, mp_get_pd_status(pd_offset)); sc_offset = mp_set_subcheck_state(sc_offset, tmp); @@ -708,12 +714,14 @@ int main(int argc, char *argv[]) { // truechimers if (config.do_truechimers) { - mp_subcheck sc_truechimers; + mp_subcheck sc_truechimers = mp_subcheck_init(); xasprintf(&sc_truechimers.output, "truechimers: %i", ntp_res.num_truechimers); mp_perfdata pd_truechimers = perfdata_init(); pd_truechimers.value = mp_create_pd_value(ntp_res.num_truechimers); - mp_pd_set_thresholds(pd_truechimers, config.truechimer_thresholds); + pd_truechimers.label = "truechimers"; + pd_truechimers = mp_pd_set_thresholds(pd_truechimers, config.truechimer_thresholds); + mp_add_perfdata_to_subcheck(&sc_truechimers, pd_truechimers); sc_truechimers = mp_set_subcheck_state(sc_truechimers, mp_get_pd_status(pd_truechimers)); @@ -728,6 +736,8 @@ int main(int argc, char *argv[]) { mp_perfdata pd_stratum = perfdata_init(); pd_stratum.value = mp_create_pd_value(ntp_res.stratum); pd_stratum = mp_pd_set_thresholds(pd_stratum, config.stratum_thresholds); + pd_stratum.label = "stratum"; + mp_add_perfdata_to_subcheck(&sc_stratum, pd_stratum); sc_stratum = mp_set_subcheck_state(sc_stratum, mp_get_pd_status(pd_stratum)); @@ -742,6 +752,8 @@ int main(int argc, char *argv[]) { mp_perfdata pd_jitter = perfdata_init(); pd_jitter.value = mp_create_pd_value(ntp_res.jitter); pd_jitter = mp_pd_set_thresholds(pd_jitter, config.jitter_thresholds); + pd_jitter.label = "jitter"; + mp_add_perfdata_to_subcheck(&sc_jitter, pd_jitter); sc_jitter = mp_set_subcheck_state(sc_jitter, mp_get_pd_status(pd_jitter)); diff --git a/plugins/check_ntp_peer.d/config.h b/plugins/check_ntp_peer.d/config.h index 396edea6..a6dd5c4c 100644 --- a/plugins/check_ntp_peer.d/config.h +++ b/plugins/check_ntp_peer.d/config.h @@ -66,10 +66,11 @@ check_ntp_peer_config check_ntp_peer_config_init() { tmp.jitter_thresholds = mp_thresholds_set_crit(tmp.jitter_thresholds, jitter_c_default); mp_range offset_w_default = mp_range_init(); - offset_w_default = mp_range_set_start(offset_w_default, mp_create_pd_value(60)); + offset_w_default = mp_range_set_end(offset_w_default, mp_create_pd_value(60)); tmp.offset_thresholds = mp_thresholds_set_warn(tmp.offset_thresholds, offset_w_default); + mp_range offset_c_default = mp_range_init(); - offset_c_default = mp_range_set_start(offset_c_default, mp_create_pd_value(120)); + offset_c_default = mp_range_set_end(offset_c_default, mp_create_pd_value(120)); tmp.offset_thresholds = mp_thresholds_set_crit(tmp.offset_thresholds, offset_c_default); return tmp; } -- cgit v1.2.3-74-g34f1 From a9b63deedb1775271fa1335a5d3eb034d0628e91 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Wed, 5 Nov 2025 12:04:30 +0100 Subject: check_ntp_peer: add cli param to set output format --- plugins/check_ntp_peer.c | 50 +++++++++++++++++++++++++++++++-------- plugins/check_ntp_peer.d/config.h | 6 +++++ 2 files changed, 46 insertions(+), 10 deletions(-) (limited to 'plugins') diff --git a/plugins/check_ntp_peer.c b/plugins/check_ntp_peer.c index 032f8ea4..f7cad630 100644 --- a/plugins/check_ntp_peer.c +++ b/plugins/check_ntp_peer.c @@ -478,16 +478,30 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { } check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { - static struct option longopts[] = { - {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, - {"verbose", no_argument, 0, 'v'}, {"use-ipv4", no_argument, 0, '4'}, - {"use-ipv6", no_argument, 0, '6'}, {"quiet", no_argument, 0, 'q'}, - {"warning", required_argument, 0, 'w'}, {"critical", required_argument, 0, 'c'}, - {"swarn", required_argument, 0, 'W'}, {"scrit", required_argument, 0, 'C'}, - {"jwarn", required_argument, 0, 'j'}, {"jcrit", required_argument, 0, 'k'}, - {"twarn", required_argument, 0, 'm'}, {"tcrit", required_argument, 0, 'n'}, - {"timeout", required_argument, 0, 't'}, {"hostname", required_argument, 0, 'H'}, - {"port", required_argument, 0, 'p'}, {0, 0, 0, 0}}; + + enum { + output_format_index = CHAR_MAX + 1, + }; + + static struct option longopts[] = {{"version", no_argument, 0, 'V'}, + {"help", no_argument, 0, 'h'}, + {"verbose", no_argument, 0, 'v'}, + {"use-ipv4", no_argument, 0, '4'}, + {"use-ipv6", no_argument, 0, '6'}, + {"quiet", no_argument, 0, 'q'}, + {"warning", required_argument, 0, 'w'}, + {"critical", required_argument, 0, 'c'}, + {"swarn", required_argument, 0, 'W'}, + {"scrit", required_argument, 0, 'C'}, + {"jwarn", required_argument, 0, 'j'}, + {"jcrit", required_argument, 0, 'k'}, + {"twarn", required_argument, 0, 'm'}, + {"tcrit", required_argument, 0, 'n'}, + {"timeout", required_argument, 0, 't'}, + {"hostname", required_argument, 0, 'H'}, + {"port", required_argument, 0, 'p'}, + {"output-format", required_argument, 0, output_format_index}, + {0, 0, 0, 0}}; if (argc < 2) { usage("\n"); @@ -507,6 +521,17 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { } switch (option_char) { + case output_format_index: { + parsed_output_format parser = mp_parse_output_format(optarg); + if (!parser.parsing_success) { + printf("Invalid output format: %s\n", optarg); + exit(STATE_UNKNOWN); + } + + result.config.output_format_is_set = true; + result.config.output_format = parser.output_format; + break; + } case 'h': print_help(); exit(STATE_UNKNOWN); @@ -673,6 +698,10 @@ int main(int argc, char *argv[]) { const check_ntp_peer_config config = tmp_config.config; + if (config.output_format_is_set) { + mp_set_format(config.output_format); + } + /* initialize alarm signal handling */ signal(SIGALRM, socket_timeout_alarm_handler); @@ -825,6 +854,7 @@ void print_help(void) { printf(" %s\n", _("Critical threshold for number of usable time sources (\"truechimers\")")); printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); printf(UT_VERBOSE); + printf(UT_OUTPUT_FORMAT); printf("\n"); printf("%s\n", _("This plugin checks an NTP server independent of any commandline")); diff --git a/plugins/check_ntp_peer.d/config.h b/plugins/check_ntp_peer.d/config.h index a6dd5c4c..488d936c 100644 --- a/plugins/check_ntp_peer.d/config.h +++ b/plugins/check_ntp_peer.d/config.h @@ -1,6 +1,7 @@ #pragma once #include "../../config.h" +#include "output.h" #include "perfdata.h" #include "thresholds.h" #include @@ -29,6 +30,9 @@ typedef struct { // jitter stuff bool do_jitter; mp_thresholds jitter_thresholds; + + bool output_format_is_set; + mp_output_format output_format; } check_ntp_peer_config; check_ntp_peer_config check_ntp_peer_config_init() { @@ -47,6 +51,8 @@ check_ntp_peer_config check_ntp_peer_config_init() { .do_jitter = false, .jitter_thresholds = mp_thresholds_init(), + + .output_format_is_set = false, }; mp_range stratum_default = mp_range_init(); -- cgit v1.2.3-74-g34f1 From 71e0d5e0732225e95affbacd1a08f2a8513d2802 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Wed, 5 Nov 2025 12:19:20 +0100 Subject: check_ntp_time: add cli option for output format --- plugins/check_ntp_time.c | 22 ++++++++++++++++++++++ plugins/check_ntp_time.d/config.h | 6 ++++++ 2 files changed, 28 insertions(+) (limited to 'plugins') diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c index 7c3fc24d..602b6010 100644 --- a/plugins/check_ntp_time.c +++ b/plugins/check_ntp_time.c @@ -505,6 +505,11 @@ static offset_request_wrapper offset_request(const char *host, const char *port, } static check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { + + enum { + output_format_index = CHAR_MAX + 1, + }; + static struct option longopts[] = {{"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, 'v'}, @@ -517,6 +522,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'}, + {"output-format", required_argument, 0, output_format_index}, {0, 0, 0, 0}}; if (argc < 2) { @@ -536,6 +542,17 @@ static check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { } switch (option_char) { + case output_format_index: { + parsed_output_format parser = mp_parse_output_format(optarg); + if (!parser.parsing_success) { + printf("Invalid output format: %s\n", optarg); + exit(STATE_UNKNOWN); + } + + result.config.output_format_is_set = true; + result.config.output_format = parser.output_format; + break; + } case 'h': print_help(); exit(STATE_UNKNOWN); @@ -623,6 +640,10 @@ int main(int argc, char *argv[]) { const check_ntp_time_config config = tmp_config.config; + if (config.output_format_is_set) { + mp_set_format(config.output_format); + } + /* initialize alarm signal handling */ signal(SIGALRM, socket_timeout_alarm_handler); @@ -687,6 +708,7 @@ void print_help(void) { printf(" %s\n", _("Expected offset of the ntp server relative to local server (seconds)")); printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); printf(UT_VERBOSE); + printf(UT_OUTPUT_FORMAT); printf("\n"); printf("%s\n", _("This plugin checks the clock offset between the local host and a")); diff --git a/plugins/check_ntp_time.d/config.h b/plugins/check_ntp_time.d/config.h index a62e4ceb..9bbd82aa 100644 --- a/plugins/check_ntp_time.d/config.h +++ b/plugins/check_ntp_time.d/config.h @@ -1,6 +1,7 @@ #pragma once #include "../../config.h" +#include "output.h" #include "thresholds.h" #include @@ -12,6 +13,9 @@ typedef struct { int time_offset; mp_thresholds offset_thresholds; + + bool output_format_is_set; + mp_output_format output_format; } check_ntp_time_config; check_ntp_time_config check_ntp_time_config_init() { @@ -23,6 +27,8 @@ check_ntp_time_config check_ntp_time_config_init() { .time_offset = 0, .offset_thresholds = mp_thresholds_init(), + + .output_format_is_set = false, }; mp_range warning = mp_range_init(); -- cgit v1.2.3-74-g34f1