Module: monitoring-plugins
 Branch: master
 Commit: 6392a0f77635d82b9b68bcbd1be4c6acc478767f
 Author: Lorenz Kästle <[email protected]>
   Date: Tue Nov  4 10:13:39 2025 +0100
    URL: 
https://www.monitoring-plugins.org/repositories/monitoring-plugins/commit/?id=6392a0f7

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(-)

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 = "[email protected]";
 
+#include "output.h"
+#include "perfdata.h"
+#include <openssl/x509.h>
 #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 <stddef.h>
 
@@ -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;
 }

Reply via email to