summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/check_curl.d/check_curl_helpers.c20
-rw-r--r--plugins/check_ntp_peer.c360
-rw-r--r--plugins/check_ntp_peer.d/config.h63
-rw-r--r--plugins/check_ntp_time.c166
-rw-r--r--plugins/check_ntp_time.d/config.h13
5 files changed, 366 insertions, 256 deletions
diff --git a/plugins/check_curl.d/check_curl_helpers.c b/plugins/check_curl.d/check_curl_helpers.c
index c3c2ba55..d49d8f07 100644
--- a/plugins/check_curl.d/check_curl_helpers.c
+++ b/plugins/check_curl.d/check_curl_helpers.c
@@ -4,6 +4,7 @@
4#include <netinet/in.h> 4#include <netinet/in.h>
5#include <netdb.h> 5#include <netdb.h>
6#include <stdlib.h> 6#include <stdlib.h>
7#include <string.h>
7#include "../utils.h" 8#include "../utils.h"
8#include "check_curl.d/config.h" 9#include "check_curl.d/config.h"
9#include "output.h" 10#include "output.h"
@@ -816,7 +817,10 @@ int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line)
816 buf = start; 817 buf = start;
817 } 818 }
818 819
819 char *first_line_end = strstr(buf, "\r\n"); 820 // Accept either LF or CRLF as end of line for the status line
821 // CRLF is the standard (RFC9112), but it is recommended to accept both
822 size_t length_of_first_line = strcspn(buf, "\r\n");
823 const char *first_line_end = &buf[length_of_first_line];
820 if (first_line_end == NULL) { 824 if (first_line_end == NULL) {
821 return -1; 825 return -1;
822 } 826 }
@@ -826,6 +830,7 @@ int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line)
826 if (status_line->first_line == NULL) { 830 if (status_line->first_line == NULL) {
827 return -1; 831 return -1;
828 } 832 }
833
829 memcpy(status_line->first_line, buf, first_line_len); 834 memcpy(status_line->first_line, buf, first_line_len);
830 status_line->first_line[first_line_len] = '\0'; 835 status_line->first_line[first_line_len] = '\0';
831 char *first_line_buf = strdup(status_line->first_line); 836 char *first_line_buf = strdup(status_line->first_line);
@@ -833,23 +838,34 @@ int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line)
833 /* protocol and version: "HTTP/x.x" SP or "HTTP/2" SP */ 838 /* protocol and version: "HTTP/x.x" SP or "HTTP/2" SP */
834 char *temp_string = strtok(first_line_buf, "/"); 839 char *temp_string = strtok(first_line_buf, "/");
835 if (temp_string == NULL) { 840 if (temp_string == NULL) {
841 if (verbose > 1) {
842 printf("%s: no / found\n", __func__);
843 }
836 free(first_line_buf); 844 free(first_line_buf);
837 return -1; 845 return -1;
838 } 846 }
847
839 if (strcmp(temp_string, "HTTP") != 0) { 848 if (strcmp(temp_string, "HTTP") != 0) {
849 if (verbose > 1) {
850 printf("%s: string 'HTTP' not found\n", __func__);
851 }
840 free(first_line_buf); 852 free(first_line_buf);
841 return -1; 853 return -1;
842 } 854 }
843 855
856 // try to find a space in the remaining string?
857 // the space after HTTP/1.1 probably
844 temp_string = strtok(NULL, " "); 858 temp_string = strtok(NULL, " ");
845 if (temp_string == NULL) { 859 if (temp_string == NULL) {
860 if (verbose > 1) {
861 printf("%s: no space after protocol definition\n", __func__);
862 }
846 free(first_line_buf); 863 free(first_line_buf);
847 return -1; 864 return -1;
848 } 865 }
849 866
850 char *temp_string_2; 867 char *temp_string_2;
851 if (strchr(temp_string, '.') != NULL) { 868 if (strchr(temp_string, '.') != NULL) {
852
853 /* HTTP 1.x case */ 869 /* HTTP 1.x case */
854 strtok(temp_string, "."); 870 strtok(temp_string, ".");
855 status_line->http_major = (int)strtol(temp_string, &temp_string_2, 10); 871 status_line->http_major = (int)strtol(temp_string, &temp_string_2, 10);
diff --git a/plugins/check_ntp_peer.c b/plugins/check_ntp_peer.c
index 24d1c9b5..f7cad630 100644
--- a/plugins/check_ntp_peer.c
+++ b/plugins/check_ntp_peer.c
@@ -35,11 +35,14 @@
35 * 35 *
36 *****************************************************************************/ 36 *****************************************************************************/
37 37
38#include "thresholds.h"
39const char *progname = "check_ntp_peer"; 38const char *progname = "check_ntp_peer";
40const char *copyright = "2006-2024"; 39const char *copyright = "2006-2024";
41const char *email = "devel@monitoring-plugins.org"; 40const char *email = "devel@monitoring-plugins.org";
42 41
42#include "output.h"
43#include "perfdata.h"
44#include <openssl/x509.h>
45#include "thresholds.h"
43#include "common.h" 46#include "common.h"
44#include "netutils.h" 47#include "netutils.h"
45#include "utils.h" 48#include "utils.h"
@@ -47,8 +50,6 @@ const char *email = "devel@monitoring-plugins.org";
47#include "check_ntp_peer.d/config.h" 50#include "check_ntp_peer.d/config.h"
48 51
49static int verbose = 0; 52static int verbose = 0;
50static bool syncsource_found = false;
51static bool li_alarm = false;
52 53
53typedef struct { 54typedef struct {
54 int errorcode; 55 int errorcode;
@@ -198,9 +199,7 @@ void setup_control_request(ntp_control_message *message, uint8_t opcode, uint16_
198 * positive value means a success retrieving the value. 199 * positive value means a success retrieving the value.
199 * - status is set to WARNING if there's no sync.peer (otherwise OK) and is 200 * - status is set to WARNING if there's no sync.peer (otherwise OK) and is
200 * the return value of the function. 201 * the return value of the function.
201 * status is pretty much useless as syncsource_found is a global variable 202 */
202 * used later in main to check is the server was synchronized. It works
203 * so I left it alone */
204typedef struct { 203typedef struct {
205 mp_state_enum state; 204 mp_state_enum state;
206 mp_state_enum offset_result; 205 mp_state_enum offset_result;
@@ -208,6 +207,8 @@ typedef struct {
208 double jitter; 207 double jitter;
209 long stratum; 208 long stratum;
210 int num_truechimers; 209 int num_truechimers;
210 bool syncsource_found;
211 bool li_alarm;
211} ntp_request_result; 212} ntp_request_result;
212ntp_request_result ntp_request(const check_ntp_peer_config config) { 213ntp_request_result ntp_request(const check_ntp_peer_config config) {
213 214
@@ -217,6 +218,8 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) {
217 .jitter = -1, 218 .jitter = -1,
218 .stratum = -1, 219 .stratum = -1,
219 .num_truechimers = 0, 220 .num_truechimers = 0,
221 .syncsource_found = false,
222 .li_alarm = false,
220 }; 223 };
221 224
222 /* Long-winded explanation: 225 /* Long-winded explanation:
@@ -235,19 +238,16 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) {
235 * 4) Extract the offset, jitter and stratum value from the data[] 238 * 4) Extract the offset, jitter and stratum value from the data[]
236 * (it's ASCII) 239 * (it's ASCII)
237 */ 240 */
238 int min_peer_sel = PEER_INCLUDED;
239 int num_candidates = 0;
240 void *tmp;
241 ntp_assoc_status_pair *peers = NULL;
242 int peer_offset = 0;
243 size_t peers_size = 0;
244 size_t npeers = 0;
245 int conn = -1; 241 int conn = -1;
246 my_udp_connect(config.server_address, config.port, &conn); 242 my_udp_connect(config.server_address, config.port, &conn);
247 243
248 /* keep sending requests until the server stops setting the 244 /* keep sending requests until the server stops setting the
249 * REM_MORE bit, though usually this is only 1 packet. */ 245 * REM_MORE bit, though usually this is only 1 packet. */
250 ntp_control_message req; 246 ntp_control_message req;
247 ntp_assoc_status_pair *peers = NULL;
248 int peer_offset = 0;
249 size_t peers_size = 0;
250 size_t npeers = 0;
251 do { 251 do {
252 setup_control_request(&req, OP_READSTAT, 1); 252 setup_control_request(&req, OP_READSTAT, 1);
253 DBG(printf("sending READSTAT request")); 253 DBG(printf("sending READSTAT request"));
@@ -269,12 +269,13 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) {
269 } while (!(req.op & OP_READSTAT && ntohs(req.seq) == 1)); 269 } while (!(req.op & OP_READSTAT && ntohs(req.seq) == 1));
270 270
271 if (LI(req.flags) == LI_ALARM) { 271 if (LI(req.flags) == LI_ALARM) {
272 li_alarm = true; 272 result.li_alarm = true;
273 } 273 }
274 /* Each peer identifier is 4 bytes in the data section, which 274 /* Each peer identifier is 4 bytes in the data section, which
275 * we represent as a ntp_assoc_status_pair datatype. 275 * we represent as a ntp_assoc_status_pair datatype.
276 */ 276 */
277 peers_size += ntohs(req.count); 277 peers_size += ntohs(req.count);
278 void *tmp;
278 if ((tmp = realloc(peers, peers_size)) == NULL) { 279 if ((tmp = realloc(peers, peers_size)) == NULL) {
279 free(peers), die(STATE_UNKNOWN, "can not (re)allocate 'peers' buffer\n"); 280 free(peers), die(STATE_UNKNOWN, "can not (re)allocate 'peers' buffer\n");
280 } 281 }
@@ -287,13 +288,15 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) {
287 /* first, let's find out if we have a sync source, or if there are 288 /* first, let's find out if we have a sync source, or if there are
288 * at least some candidates. In the latter case we'll issue 289 * at least some candidates. In the latter case we'll issue
289 * a warning but go ahead with the check on them. */ 290 * a warning but go ahead with the check on them. */
291 int min_peer_sel = PEER_INCLUDED;
292 int num_candidates = 0;
290 for (size_t i = 0; i < npeers; i++) { 293 for (size_t i = 0; i < npeers; i++) {
291 if (PEER_SEL(peers[i].status) >= PEER_TRUECHIMER) { 294 if (PEER_SEL(peers[i].status) >= PEER_TRUECHIMER) {
292 result.num_truechimers++; 295 result.num_truechimers++;
293 if (PEER_SEL(peers[i].status) >= PEER_INCLUDED) { 296 if (PEER_SEL(peers[i].status) >= PEER_INCLUDED) {
294 num_candidates++; 297 num_candidates++;
295 if (PEER_SEL(peers[i].status) >= PEER_SYNCSOURCE) { 298 if (PEER_SEL(peers[i].status) >= PEER_SYNCSOURCE) {
296 syncsource_found = true; 299 result.syncsource_found = true;
297 min_peer_sel = PEER_SYNCSOURCE; 300 min_peer_sel = PEER_SYNCSOURCE;
298 } 301 }
299 } 302 }
@@ -302,18 +305,18 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) {
302 305
303 if (verbose) { 306 if (verbose) {
304 printf("%d candidate peers available\n", num_candidates); 307 printf("%d candidate peers available\n", num_candidates);
305 } 308 if (result.syncsource_found) {
306 if (verbose && syncsource_found) { 309 printf("synchronization source found\n");
307 printf("synchronization source found\n"); 310 }
308 } 311 }
309 312
310 if (!syncsource_found) { 313 if (!result.syncsource_found) {
311 result.state = STATE_WARNING; 314 result.state = STATE_WARNING;
312 if (verbose) { 315 if (verbose) {
313 printf("warning: no synchronization source found\n"); 316 printf("warning: no synchronization source found\n");
314 } 317 }
315 } 318 }
316 if (li_alarm) { 319 if (result.li_alarm) {
317 result.state = STATE_WARNING; 320 result.state = STATE_WARNING;
318 if (verbose) { 321 if (verbose) {
319 printf("warning: LI_ALARM bit is set\n"); 322 printf("warning: LI_ALARM bit is set\n");
@@ -329,7 +332,7 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) {
329 if (verbose) { 332 if (verbose) {
330 printf("Getting offset, jitter and stratum for peer %.2x\n", ntohs(peers[i].assoc)); 333 printf("Getting offset, jitter and stratum for peer %.2x\n", ntohs(peers[i].assoc));
331 } 334 }
332 xasprintf(&data, ""); 335 data = strdup("");
333 do { 336 do {
334 setup_control_request(&req, OP_READVAR, 2); 337 setup_control_request(&req, OP_READVAR, 2);
335 req.assoc = peers[i].assoc; 338 req.assoc = peers[i].assoc;
@@ -475,16 +478,30 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) {
475} 478}
476 479
477check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { 480check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) {
478 static struct option longopts[] = { 481
479 {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, 482 enum {
480 {"verbose", no_argument, 0, 'v'}, {"use-ipv4", no_argument, 0, '4'}, 483 output_format_index = CHAR_MAX + 1,
481 {"use-ipv6", no_argument, 0, '6'}, {"quiet", no_argument, 0, 'q'}, 484 };
482 {"warning", required_argument, 0, 'w'}, {"critical", required_argument, 0, 'c'}, 485
483 {"swarn", required_argument, 0, 'W'}, {"scrit", required_argument, 0, 'C'}, 486 static struct option longopts[] = {{"version", no_argument, 0, 'V'},
484 {"jwarn", required_argument, 0, 'j'}, {"jcrit", required_argument, 0, 'k'}, 487 {"help", no_argument, 0, 'h'},
485 {"twarn", required_argument, 0, 'm'}, {"tcrit", required_argument, 0, 'n'}, 488 {"verbose", no_argument, 0, 'v'},
486 {"timeout", required_argument, 0, 't'}, {"hostname", required_argument, 0, 'H'}, 489 {"use-ipv4", no_argument, 0, '4'},
487 {"port", required_argument, 0, 'p'}, {0, 0, 0, 0}}; 490 {"use-ipv6", no_argument, 0, '6'},
491 {"quiet", no_argument, 0, 'q'},
492 {"warning", required_argument, 0, 'w'},
493 {"critical", required_argument, 0, 'c'},
494 {"swarn", required_argument, 0, 'W'},
495 {"scrit", required_argument, 0, 'C'},
496 {"jwarn", required_argument, 0, 'j'},
497 {"jcrit", required_argument, 0, 'k'},
498 {"twarn", required_argument, 0, 'm'},
499 {"tcrit", required_argument, 0, 'n'},
500 {"timeout", required_argument, 0, 't'},
501 {"hostname", required_argument, 0, 'H'},
502 {"port", required_argument, 0, 'p'},
503 {"output-format", required_argument, 0, output_format_index},
504 {0, 0, 0, 0}};
488 505
489 if (argc < 2) { 506 if (argc < 2) {
490 usage("\n"); 507 usage("\n");
@@ -504,6 +521,17 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) {
504 } 521 }
505 522
506 switch (option_char) { 523 switch (option_char) {
524 case output_format_index: {
525 parsed_output_format parser = mp_parse_output_format(optarg);
526 if (!parser.parsing_success) {
527 printf("Invalid output format: %s\n", optarg);
528 exit(STATE_UNKNOWN);
529 }
530
531 result.config.output_format_is_set = true;
532 result.config.output_format = parser.output_format;
533 break;
534 }
507 case 'h': 535 case 'h':
508 print_help(); 536 print_help();
509 exit(STATE_UNKNOWN); 537 exit(STATE_UNKNOWN);
@@ -518,36 +546,84 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) {
518 case 'q': 546 case 'q':
519 result.config.quiet = true; 547 result.config.quiet = true;
520 break; 548 break;
521 case 'w': 549 case 'w': {
522 result.config.owarn = optarg; 550 mp_range_parsed tmp = mp_parse_range_string(optarg);
523 break; 551 if (tmp.error != MP_PARSING_SUCCES) {
524 case 'c': 552 die(STATE_UNKNOWN, "failed to parse warning offset threshold");
525 result.config.ocrit = optarg; 553 }
526 break; 554
527 case 'W': 555 result.config.offset_thresholds =
556 mp_thresholds_set_warn(result.config.offset_thresholds, tmp.range);
557 } break;
558 case 'c': {
559 mp_range_parsed tmp = mp_parse_range_string(optarg);
560 if (tmp.error != MP_PARSING_SUCCES) {
561 die(STATE_UNKNOWN, "failed to parse critical offset threshold");
562 }
563
564 result.config.offset_thresholds =
565 mp_thresholds_set_crit(result.config.offset_thresholds, tmp.range);
566 } break;
567 case 'W': {
528 result.config.do_stratum = true; 568 result.config.do_stratum = true;
529 result.config.swarn = optarg; 569 mp_range_parsed tmp = mp_parse_range_string(optarg);
530 break; 570 if (tmp.error != MP_PARSING_SUCCES) {
531 case 'C': 571 die(STATE_UNKNOWN, "failed to parse warning stratum threshold");
572 }
573
574 result.config.stratum_thresholds =
575 mp_thresholds_set_warn(result.config.stratum_thresholds, tmp.range);
576 } break;
577 case 'C': {
532 result.config.do_stratum = true; 578 result.config.do_stratum = true;
533 result.config.scrit = optarg; 579 mp_range_parsed tmp = mp_parse_range_string(optarg);
534 break; 580 if (tmp.error != MP_PARSING_SUCCES) {
535 case 'j': 581 die(STATE_UNKNOWN, "failed to parse critical stratum threshold");
582 }
583
584 result.config.stratum_thresholds =
585 mp_thresholds_set_crit(result.config.stratum_thresholds, tmp.range);
586 } break;
587 case 'j': {
536 result.config.do_jitter = true; 588 result.config.do_jitter = true;
537 result.config.jwarn = optarg; 589 mp_range_parsed tmp = mp_parse_range_string(optarg);
538 break; 590 if (tmp.error != MP_PARSING_SUCCES) {
539 case 'k': 591 die(STATE_UNKNOWN, "failed to parse warning jitter threshold");
592 }
593
594 result.config.jitter_thresholds =
595 mp_thresholds_set_warn(result.config.jitter_thresholds, tmp.range);
596 } break;
597 case 'k': {
540 result.config.do_jitter = true; 598 result.config.do_jitter = true;
541 result.config.jcrit = optarg; 599 mp_range_parsed tmp = mp_parse_range_string(optarg);
542 break; 600 if (tmp.error != MP_PARSING_SUCCES) {
543 case 'm': 601 die(STATE_UNKNOWN, "failed to parse critical jitter threshold");
602 }
603
604 result.config.jitter_thresholds =
605 mp_thresholds_set_crit(result.config.jitter_thresholds, tmp.range);
606 } break;
607 case 'm': {
544 result.config.do_truechimers = true; 608 result.config.do_truechimers = true;
545 result.config.twarn = optarg; 609 mp_range_parsed tmp = mp_parse_range_string(optarg);
546 break; 610 if (tmp.error != MP_PARSING_SUCCES) {
547 case 'n': 611 die(STATE_UNKNOWN, "failed to parse warning truechimer threshold");
612 }
613
614 result.config.truechimer_thresholds =
615 mp_thresholds_set_warn(result.config.truechimer_thresholds, tmp.range);
616 } break;
617 case 'n': {
548 result.config.do_truechimers = true; 618 result.config.do_truechimers = true;
549 result.config.tcrit = optarg; 619 mp_range_parsed tmp = mp_parse_range_string(optarg);
550 break; 620 if (tmp.error != MP_PARSING_SUCCES) {
621 die(STATE_UNKNOWN, "failed to parse critical truechimer threshold");
622 }
623
624 result.config.truechimer_thresholds =
625 mp_thresholds_set_crit(result.config.truechimer_thresholds, tmp.range);
626 } break;
551 case 'H': 627 case 'H':
552 if (!is_host(optarg)) { 628 if (!is_host(optarg)) {
553 usage2(_("Invalid hostname/address"), optarg); 629 usage2(_("Invalid hostname/address"), optarg);
@@ -581,11 +657,6 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) {
581 usage4(_("Hostname was not supplied")); 657 usage4(_("Hostname was not supplied"));
582 } 658 }
583 659
584 set_thresholds(&result.config.offset_thresholds, result.config.owarn, result.config.ocrit);
585 set_thresholds(&result.config.jitter_thresholds, result.config.jwarn, result.config.jcrit);
586 set_thresholds(&result.config.stratum_thresholds, result.config.swarn, result.config.scrit);
587 set_thresholds(&result.config.truechimer_thresholds, result.config.twarn, result.config.tcrit);
588
589 return result; 660 return result;
590} 661}
591 662
@@ -627,6 +698,10 @@ int main(int argc, char *argv[]) {
627 698
628 const check_ntp_peer_config config = tmp_config.config; 699 const check_ntp_peer_config config = tmp_config.config;
629 700
701 if (config.output_format_is_set) {
702 mp_set_format(config.output_format);
703 }
704
630 /* initialize alarm signal handling */ 705 /* initialize alarm signal handling */
631 signal(SIGALRM, socket_timeout_alarm_handler); 706 signal(SIGALRM, socket_timeout_alarm_handler);
632 707
@@ -634,125 +709,113 @@ int main(int argc, char *argv[]) {
634 alarm(socket_timeout); 709 alarm(socket_timeout);
635 710
636 /* This returns either OK or WARNING (See comment preceding ntp_request) */ 711 /* This returns either OK or WARNING (See comment preceding ntp_request) */
637 ntp_request_result ntp_res = ntp_request(config); 712 const ntp_request_result ntp_res = ntp_request(config);
638 mp_state_enum result = STATE_UNKNOWN; 713 mp_check overall = mp_check_init();
639 714
715 mp_subcheck sc_offset = mp_subcheck_init();
716 xasprintf(&sc_offset.output, "offset");
640 if (ntp_res.offset_result == STATE_UNKNOWN) { 717 if (ntp_res.offset_result == STATE_UNKNOWN) {
641 /* if there's no sync peer (this overrides ntp_request output): */ 718 /* if there's no sync peer (this overrides ntp_request output): */
642 result = (config.quiet ? STATE_UNKNOWN : STATE_CRITICAL); 719 sc_offset =
720 mp_set_subcheck_state(sc_offset, (config.quiet ? STATE_UNKNOWN : STATE_CRITICAL));
721 xasprintf(&sc_offset.output, "%s unknown", sc_offset.output);
643 } else { 722 } else {
644 /* Be quiet if there's no candidates either */ 723 /* Be quiet if there's no candidates either */
645 if (config.quiet && result == STATE_WARNING) { 724 mp_state_enum tmp = STATE_OK;
646 result = STATE_UNKNOWN; 725 if (config.quiet && ntp_res.state == STATE_WARNING) {
726 tmp = STATE_UNKNOWN;
647 } 727 }
648 result = max_state_alt(result, get_status(fabs(ntp_res.offset), config.offset_thresholds)); 728
729 xasprintf(&sc_offset.output, "%s: %.6fs", sc_offset.output, ntp_res.offset);
730
731 mp_perfdata pd_offset = perfdata_init();
732 pd_offset.value = mp_create_pd_value(fabs(ntp_res.offset));
733 pd_offset = mp_pd_set_thresholds(pd_offset, config.offset_thresholds);
734 pd_offset.label = "offset";
735 pd_offset.uom = "s";
736 mp_add_perfdata_to_subcheck(&sc_offset, pd_offset);
737
738 tmp = max_state_alt(tmp, mp_get_pd_status(pd_offset));
739 sc_offset = mp_set_subcheck_state(sc_offset, tmp);
649 } 740 }
650 741
651 mp_state_enum oresult = result; 742 mp_add_subcheck_to_check(&overall, sc_offset);
652 mp_state_enum tresult = STATE_UNKNOWN;
653 743
744 // truechimers
654 if (config.do_truechimers) { 745 if (config.do_truechimers) {
655 tresult = get_status(ntp_res.num_truechimers, config.truechimer_thresholds); 746 mp_subcheck sc_truechimers = mp_subcheck_init();
656 result = max_state_alt(result, tresult); 747 xasprintf(&sc_truechimers.output, "truechimers: %i", ntp_res.num_truechimers);
657 }
658 748
659 mp_state_enum sresult = STATE_UNKNOWN; 749 mp_perfdata pd_truechimers = perfdata_init();
750 pd_truechimers.value = mp_create_pd_value(ntp_res.num_truechimers);
751 pd_truechimers.label = "truechimers";
752 pd_truechimers = mp_pd_set_thresholds(pd_truechimers, config.truechimer_thresholds);
660 753
661 if (config.do_stratum) { 754 mp_add_perfdata_to_subcheck(&sc_truechimers, pd_truechimers);
662 sresult = get_status((double)ntp_res.stratum, config.stratum_thresholds);
663 result = max_state_alt(result, sresult);
664 }
665 755
666 mp_state_enum jresult = STATE_UNKNOWN; 756 sc_truechimers = mp_set_subcheck_state(sc_truechimers, mp_get_pd_status(pd_truechimers));
667 757
668 if (config.do_jitter) { 758 mp_add_subcheck_to_check(&overall, sc_truechimers);
669 jresult = get_status(ntp_res.jitter, config.jitter_thresholds);
670 result = max_state_alt(result, jresult);
671 } 759 }
672 760
673 char *result_line; 761 if (config.do_stratum) {
674 switch (result) { 762 mp_subcheck sc_stratum = mp_subcheck_init();
675 case STATE_CRITICAL: 763 xasprintf(&sc_stratum.output, "stratum: %li", ntp_res.stratum);
676 xasprintf(&result_line, _("NTP CRITICAL:"));
677 break;
678 case STATE_WARNING:
679 xasprintf(&result_line, _("NTP WARNING:"));
680 break;
681 case STATE_OK:
682 xasprintf(&result_line, _("NTP OK:"));
683 break;
684 default:
685 xasprintf(&result_line, _("NTP UNKNOWN:"));
686 break;
687 }
688 764
689 if (!syncsource_found) { 765 mp_perfdata pd_stratum = perfdata_init();
690 xasprintf(&result_line, "%s %s,", result_line, _("Server not synchronized")); 766 pd_stratum.value = mp_create_pd_value(ntp_res.stratum);
691 } else if (li_alarm) { 767 pd_stratum = mp_pd_set_thresholds(pd_stratum, config.stratum_thresholds);
692 xasprintf(&result_line, "%s %s,", result_line, _("Server has the LI_ALARM bit set")); 768 pd_stratum.label = "stratum";
693 }
694 769
695 char *perfdata_line; 770 mp_add_perfdata_to_subcheck(&sc_stratum, pd_stratum);
696 if (ntp_res.offset_result == STATE_UNKNOWN) { 771
697 xasprintf(&result_line, "%s %s", result_line, _("Offset unknown")); 772 sc_stratum = mp_set_subcheck_state(sc_stratum, mp_get_pd_status(pd_stratum));
698 xasprintf(&perfdata_line, ""); 773
699 } else if (oresult == STATE_WARNING) { 774 mp_add_subcheck_to_check(&overall, sc_stratum);
700 xasprintf(&result_line, "%s %s %.10g secs (WARNING)", result_line, _("Offset"),
701 ntp_res.offset);
702 } else if (oresult == STATE_CRITICAL) {
703 xasprintf(&result_line, "%s %s %.10g secs (CRITICAL)", result_line, _("Offset"),
704 ntp_res.offset);
705 } else {
706 xasprintf(&result_line, "%s %s %.10g secs", result_line, _("Offset"), ntp_res.offset);
707 } 775 }
708 xasprintf(&perfdata_line, "%s", perfd_offset(ntp_res.offset, config.offset_thresholds));
709 776
710 if (config.do_jitter) { 777 if (config.do_jitter) {
711 if (jresult == STATE_WARNING) { 778 mp_subcheck sc_jitter = mp_subcheck_init();
712 xasprintf(&result_line, "%s, jitter=%f (WARNING)", result_line, ntp_res.jitter); 779 xasprintf(&sc_jitter.output, "jitter: %f", ntp_res.jitter);
713 } else if (jresult == STATE_CRITICAL) {
714 xasprintf(&result_line, "%s, jitter=%f (CRITICAL)", result_line, ntp_res.jitter);
715 } else {
716 xasprintf(&result_line, "%s, jitter=%f", result_line, ntp_res.jitter);
717 }
718 xasprintf(&perfdata_line, "%s %s", perfdata_line,
719 perfd_jitter(ntp_res.jitter, config.do_jitter, config.jitter_thresholds));
720 }
721 780
722 if (config.do_stratum) { 781 mp_perfdata pd_jitter = perfdata_init();
723 if (sresult == STATE_WARNING) { 782 pd_jitter.value = mp_create_pd_value(ntp_res.jitter);
724 xasprintf(&result_line, "%s, stratum=%li (WARNING)", result_line, ntp_res.stratum); 783 pd_jitter = mp_pd_set_thresholds(pd_jitter, config.jitter_thresholds);
725 } else if (sresult == STATE_CRITICAL) { 784 pd_jitter.label = "jitter";
726 xasprintf(&result_line, "%s, stratum=%li (CRITICAL)", result_line, ntp_res.stratum); 785
727 } else { 786 mp_add_perfdata_to_subcheck(&sc_jitter, pd_jitter);
728 xasprintf(&result_line, "%s, stratum=%li", result_line, ntp_res.stratum); 787
729 } 788 sc_jitter = mp_set_subcheck_state(sc_jitter, mp_get_pd_status(pd_jitter));
730 xasprintf(&perfdata_line, "%s %s", perfdata_line, 789 mp_add_subcheck_to_check(&overall, sc_jitter);
731 perfd_stratum(ntp_res.stratum, config.do_stratum, config.stratum_thresholds));
732 } 790 }
733 791
734 if (config.do_truechimers) { 792 mp_subcheck sc_other_info = mp_subcheck_init();
735 if (tresult == STATE_WARNING) { 793 sc_other_info = mp_set_subcheck_default_state(sc_other_info, STATE_OK);
736 xasprintf(&result_line, "%s, truechimers=%i (WARNING)", result_line, 794 if (!ntp_res.syncsource_found) {
737 ntp_res.num_truechimers); 795 xasprintf(&sc_other_info.output, "%s", _("Server not synchronized"));
738 } else if (tresult == STATE_CRITICAL) { 796 mp_add_subcheck_to_check(&overall, sc_other_info);
739 xasprintf(&result_line, "%s, truechimers=%i (CRITICAL)", result_line, 797 } else if (ntp_res.li_alarm) {
740 ntp_res.num_truechimers); 798 xasprintf(&sc_other_info.output, "%s", _("Server has the LI_ALARM bit set"));
741 } else { 799 mp_add_subcheck_to_check(&overall, sc_other_info);
742 xasprintf(&result_line, "%s, truechimers=%i", result_line, ntp_res.num_truechimers);
743 }
744 xasprintf(&perfdata_line, "%s %s", perfdata_line,
745 perfd_truechimers(ntp_res.num_truechimers, config.do_truechimers,
746 config.truechimer_thresholds));
747 } 800 }
748 801
749 printf("%s|%s\n", result_line, perfdata_line); 802 {
803 mp_subcheck sc_offset = mp_subcheck_init();
804 sc_offset = mp_set_subcheck_default_state(sc_offset, STATE_OK);
805 xasprintf(&sc_offset.output, "offset: %.10gs", ntp_res.offset);
806
807 mp_perfdata pd_offset = perfdata_init();
808 pd_offset.value = mp_create_pd_value(ntp_res.offset);
809 pd_offset = mp_pd_set_thresholds(pd_offset, config.offset_thresholds);
810
811 sc_offset = mp_set_subcheck_state(sc_offset, ntp_res.offset_result);
812 }
750 813
751 if (config.server_address != NULL) { 814 if (config.server_address != NULL) {
752 free(config.server_address); 815 free(config.server_address);
753 } 816 }
754 817
755 exit(result); 818 mp_exit(overall);
756} 819}
757 820
758void print_help(void) { 821void print_help(void) {
@@ -791,6 +854,7 @@ void print_help(void) {
791 printf(" %s\n", _("Critical threshold for number of usable time sources (\"truechimers\")")); 854 printf(" %s\n", _("Critical threshold for number of usable time sources (\"truechimers\")"));
792 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 855 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
793 printf(UT_VERBOSE); 856 printf(UT_VERBOSE);
857 printf(UT_OUTPUT_FORMAT);
794 858
795 printf("\n"); 859 printf("\n");
796 printf("%s\n", _("This plugin checks an NTP server independent of any commandline")); 860 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 00e6b05d..488d936c 100644
--- a/plugins/check_ntp_peer.d/config.h
+++ b/plugins/check_ntp_peer.d/config.h
@@ -1,6 +1,8 @@
1#pragma once 1#pragma once
2 2
3#include "../../config.h" 3#include "../../config.h"
4#include "output.h"
5#include "perfdata.h"
4#include "thresholds.h" 6#include "thresholds.h"
5#include <stddef.h> 7#include <stddef.h>
6 8
@@ -16,26 +18,21 @@ typedef struct {
16 18
17 // truechimer stuff 19 // truechimer stuff
18 bool do_truechimers; 20 bool do_truechimers;
19 char *twarn; 21 mp_thresholds truechimer_thresholds;
20 char *tcrit;
21 thresholds *truechimer_thresholds;
22 22
23 char *owarn; 23 // offset thresholds
24 char *ocrit; 24 mp_thresholds offset_thresholds;
25 thresholds *offset_thresholds;
26 25
27 // stratum stuff 26 // stratum stuff
28 bool do_stratum; 27 bool do_stratum;
29 char *swarn; 28 mp_thresholds stratum_thresholds;
30 char *scrit;
31 thresholds *stratum_thresholds;
32 29
33 // jitter stuff 30 // jitter stuff
34 bool do_jitter; 31 bool do_jitter;
35 char *jwarn; 32 mp_thresholds jitter_thresholds;
36 char *jcrit;
37 thresholds *jitter_thresholds;
38 33
34 bool output_format_is_set;
35 mp_output_format output_format;
39} check_ntp_peer_config; 36} check_ntp_peer_config;
40 37
41check_ntp_peer_config check_ntp_peer_config_init() { 38check_ntp_peer_config check_ntp_peer_config_init() {
@@ -45,23 +42,41 @@ check_ntp_peer_config check_ntp_peer_config_init() {
45 42
46 .quiet = false, 43 .quiet = false,
47 .do_truechimers = false, 44 .do_truechimers = false,
48 .twarn = "0:", 45 .truechimer_thresholds = mp_thresholds_init(),
49 .tcrit = "0:",
50 .truechimer_thresholds = NULL,
51 46
52 .owarn = "60", 47 .offset_thresholds = mp_thresholds_init(),
53 .ocrit = "120",
54 .offset_thresholds = NULL,
55 48
56 .do_stratum = false, 49 .do_stratum = false,
57 .swarn = "-1:16", 50 .stratum_thresholds = mp_thresholds_init(),
58 .scrit = "-1:16",
59 .stratum_thresholds = NULL,
60 51
61 .do_jitter = false, 52 .do_jitter = false,
62 .jwarn = "-1:5000", 53 .jitter_thresholds = mp_thresholds_init(),
63 .jcrit = "-1:10000", 54
64 .jitter_thresholds = NULL, 55 .output_format_is_set = false,
65 }; 56 };
57
58 mp_range stratum_default = mp_range_init();
59 stratum_default = mp_range_set_start(stratum_default, mp_create_pd_value(-1));
60 stratum_default = mp_range_set_end(stratum_default, mp_create_pd_value(16));
61 tmp.stratum_thresholds = mp_thresholds_set_warn(tmp.stratum_thresholds, stratum_default);
62 tmp.stratum_thresholds = mp_thresholds_set_crit(tmp.stratum_thresholds, stratum_default);
63
64 mp_range jitter_w_default = mp_range_init();
65 jitter_w_default = mp_range_set_start(jitter_w_default, mp_create_pd_value(-1));
66 jitter_w_default = mp_range_set_end(jitter_w_default, mp_create_pd_value(5000));
67 tmp.jitter_thresholds = mp_thresholds_set_warn(tmp.jitter_thresholds, jitter_w_default);
68
69 mp_range jitter_c_default = mp_range_init();
70 jitter_c_default = mp_range_set_start(jitter_c_default, mp_create_pd_value(-1));
71 jitter_c_default = mp_range_set_end(jitter_c_default, mp_create_pd_value(10000));
72 tmp.jitter_thresholds = mp_thresholds_set_crit(tmp.jitter_thresholds, jitter_c_default);
73
74 mp_range offset_w_default = mp_range_init();
75 offset_w_default = mp_range_set_end(offset_w_default, mp_create_pd_value(60));
76 tmp.offset_thresholds = mp_thresholds_set_warn(tmp.offset_thresholds, offset_w_default);
77
78 mp_range offset_c_default = mp_range_init();
79 offset_c_default = mp_range_set_end(offset_c_default, mp_create_pd_value(120));
80 tmp.offset_thresholds = mp_thresholds_set_crit(tmp.offset_thresholds, offset_c_default);
66 return tmp; 81 return tmp;
67} 82}
diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c
index ad69b804..7c3fc24d 100644
--- a/plugins/check_ntp_time.c
+++ b/plugins/check_ntp_time.c
@@ -34,12 +34,10 @@
34 * 34 *
35 *****************************************************************************/ 35 *****************************************************************************/
36 36
37const char *progname = "check_ntp_time"; 37#include "output.h"
38const char *copyright = "2006-2024";
39const char *email = "devel@monitoring-plugins.org";
40
41#include "common.h" 38#include "common.h"
42#include "netutils.h" 39#include "netutils.h"
40#include "perfdata.h"
43#include "utils.h" 41#include "utils.h"
44#include "states.h" 42#include "states.h"
45#include "thresholds.h" 43#include "thresholds.h"
@@ -47,6 +45,10 @@ const char *email = "devel@monitoring-plugins.org";
47 45
48static int verbose = 0; 46static int verbose = 0;
49 47
48const char *progname = "check_ntp_time";
49const char *copyright = "2006-2024";
50const char *email = "devel@monitoring-plugins.org";
51
50typedef struct { 52typedef struct {
51 int errorcode; 53 int errorcode;
52 check_ntp_time_config config; 54 check_ntp_time_config config;
@@ -61,9 +63,6 @@ void print_usage(void);
61# define AVG_NUM 4 63# define AVG_NUM 4
62#endif 64#endif
63 65
64/* max size of control message data */
65#define MAX_CM_SIZE 468
66
67/* this structure holds everything in an ntp request/response as per rfc1305 */ 66/* this structure holds everything in an ntp request/response as per rfc1305 */
68typedef struct { 67typedef struct {
69 uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ 68 uint8_t flags; /* byte with leapindicator,vers,mode. see macros */
@@ -169,7 +168,9 @@ typedef struct {
169 : 0) 168 : 0)
170 169
171/* convert a struct timeval to a double */ 170/* convert a struct timeval to a double */
172#define TVasDOUBLE(x) (double)(x.tv_sec + (0.000001 * x.tv_usec)) 171static double TVasDOUBLE(struct timeval time) {
172 return ((double)time.tv_sec + (0.000001 * (double)time.tv_usec));
173}
173 174
174/* convert an ntp 64-bit fp number to a struct timeval */ 175/* convert an ntp 64-bit fp number to a struct timeval */
175#define NTP64toTV(n, t) \ 176#define NTP64toTV(n, t) \
@@ -262,8 +263,8 @@ void setup_request(ntp_message *message) {
262/* select the "best" server from a list of servers, and return its index. 263/* select the "best" server from a list of servers, and return its index.
263 * this is done by filtering servers based on stratum, dispersion, and 264 * this is done by filtering servers based on stratum, dispersion, and
264 * finally round-trip delay. */ 265 * finally round-trip delay. */
265int best_offset_server(const ntp_server_results *slist, int nservers) { 266static int best_offset_server(const ntp_server_results *slist, int nservers) {
266 int best_server = -1; 267 int best_server_index = -1;
267 268
268 /* for each server */ 269 /* for each server */
269 for (int cserver = 0; cserver < nservers; cserver++) { 270 for (int cserver = 0; cserver < nservers; cserver++) {
@@ -286,33 +287,33 @@ int best_offset_server(const ntp_server_results *slist, int nservers) {
286 } 287 }
287 288
288 /* If we don't have a server yet, use the first one */ 289 /* If we don't have a server yet, use the first one */
289 if (best_server == -1) { 290 if (best_server_index == -1) {
290 best_server = cserver; 291 best_server_index = cserver;
291 DBG(printf("using peer %d as our first candidate\n", best_server)); 292 DBG(printf("using peer %d as our first candidate\n", best_server_index));
292 continue; 293 continue;
293 } 294 }
294 295
295 /* compare the server to the best one we've seen so far */ 296 /* compare the server to the best one we've seen so far */
296 /* does it have an equal or better stratum? */ 297 /* does it have an equal or better stratum? */
297 DBG(printf("comparing peer %d with peer %d\n", cserver, best_server)); 298 DBG(printf("comparing peer %d with peer %d\n", cserver, best_server_index));
298 if (slist[cserver].stratum <= slist[best_server].stratum) { 299 if (slist[cserver].stratum <= slist[best_server_index].stratum) {
299 DBG(printf("stratum for peer %d <= peer %d\n", cserver, best_server)); 300 DBG(printf("stratum for peer %d <= peer %d\n", cserver, best_server_index));
300 /* does it have an equal or better dispersion? */ 301 /* does it have an equal or better dispersion? */
301 if (slist[cserver].rtdisp <= slist[best_server].rtdisp) { 302 if (slist[cserver].rtdisp <= slist[best_server_index].rtdisp) {
302 DBG(printf("dispersion for peer %d <= peer %d\n", cserver, best_server)); 303 DBG(printf("dispersion for peer %d <= peer %d\n", cserver, best_server_index));
303 /* does it have a better rtdelay? */ 304 /* does it have a better rtdelay? */
304 if (slist[cserver].rtdelay < slist[best_server].rtdelay) { 305 if (slist[cserver].rtdelay < slist[best_server_index].rtdelay) {
305 DBG(printf("rtdelay for peer %d < peer %d\n", cserver, best_server)); 306 DBG(printf("rtdelay for peer %d < peer %d\n", cserver, best_server_index));
306 best_server = cserver; 307 best_server_index = cserver;
307 DBG(printf("peer %d is now our best candidate\n", best_server)); 308 DBG(printf("peer %d is now our best candidate\n", best_server_index));
308 } 309 }
309 } 310 }
310 } 311 }
311 } 312 }
312 313
313 if (best_server >= 0) { 314 if (best_server_index >= 0) {
314 DBG(printf("best server selected: peer %d\n", best_server)); 315 DBG(printf("best server selected: peer %d\n", best_server_index));
315 return best_server; 316 return best_server_index;
316 } 317 }
317 DBG(printf("no peers meeting synchronization criteria :(\n")); 318 DBG(printf("no peers meeting synchronization criteria :(\n"));
318 return -1; 319 return -1;
@@ -323,7 +324,11 @@ int best_offset_server(const ntp_server_results *slist, int nservers) {
323 * we don't waste time sitting around waiting for single packets. 324 * we don't waste time sitting around waiting for single packets.
324 * - we also "manually" handle resolving host names and connecting, because 325 * - we also "manually" handle resolving host names and connecting, because
325 * we have to do it in a way that our lazy macros don't handle currently :( */ 326 * we have to do it in a way that our lazy macros don't handle currently :( */
326double offset_request(const char *host, const char *port, mp_state_enum *status, int time_offset) { 327typedef struct {
328 mp_state_enum offset_result;
329 double offset;
330} offset_request_wrapper;
331static offset_request_wrapper offset_request(const char *host, const char *port, int time_offset) {
327 /* setup hints to only return results from getaddrinfo that we'd like */ 332 /* setup hints to only return results from getaddrinfo that we'd like */
328 struct addrinfo hints; 333 struct addrinfo hints;
329 memset(&hints, 0, sizeof(struct addrinfo)); 334 memset(&hints, 0, sizeof(struct addrinfo));
@@ -462,12 +467,18 @@ double offset_request(const char *host, const char *port, mp_state_enum *status,
462 die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n"); 467 die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n");
463 } 468 }
464 469
470 offset_request_wrapper result = {
471 .offset = 0,
472 .offset_result = STATE_UNKNOWN,
473 };
474
465 /* now, pick the best server from the list */ 475 /* now, pick the best server from the list */
466 double avg_offset = 0.; 476 double avg_offset = 0.;
467 int best_index = best_offset_server(servers, num_hosts); 477 int best_index = best_offset_server(servers, num_hosts);
468 if (best_index < 0) { 478 if (best_index < 0) {
469 *status = STATE_UNKNOWN; 479 result.offset_result = STATE_UNKNOWN;
470 } else { 480 } else {
481 result.offset_result = STATE_OK;
471 /* finally, calculate the average offset */ 482 /* finally, calculate the average offset */
472 for (int i = 0; i < servers[best_index].num_responses; i++) { 483 for (int i = 0; i < servers[best_index].num_responses; i++) {
473 avg_offset += servers[best_index].offset[i]; 484 avg_offset += servers[best_index].offset[i];
@@ -488,17 +499,19 @@ double offset_request(const char *host, const char *port, mp_state_enum *status,
488 if (verbose) { 499 if (verbose) {
489 printf("overall average offset: %.10g\n", avg_offset); 500 printf("overall average offset: %.10g\n", avg_offset);
490 } 501 }
491 return avg_offset; 502
503 result.offset = avg_offset;
504 return result;
492} 505}
493 506
494check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { 507static check_ntp_time_config_wrapper process_arguments(int argc, char **argv) {
495 static struct option longopts[] = {{"version", no_argument, 0, 'V'}, 508 static struct option longopts[] = {{"version", no_argument, 0, 'V'},
496 {"help", no_argument, 0, 'h'}, 509 {"help", no_argument, 0, 'h'},
497 {"verbose", no_argument, 0, 'v'}, 510 {"verbose", no_argument, 0, 'v'},
498 {"use-ipv4", no_argument, 0, '4'}, 511 {"use-ipv4", no_argument, 0, '4'},
499 {"use-ipv6", no_argument, 0, '6'}, 512 {"use-ipv6", no_argument, 0, '6'},
500 {"quiet", no_argument, 0, 'q'}, 513 {"quiet", no_argument, 0, 'q'},
501 {"time-offset", optional_argument, 0, 'o'}, 514 {"time-offset", required_argument, 0, 'o'},
502 {"warning", required_argument, 0, 'w'}, 515 {"warning", required_argument, 0, 'w'},
503 {"critical", required_argument, 0, 'c'}, 516 {"critical", required_argument, 0, 'c'},
504 {"timeout", required_argument, 0, 't'}, 517 {"timeout", required_argument, 0, 't'},
@@ -515,9 +528,6 @@ check_ntp_time_config_wrapper process_arguments(int argc, char **argv) {
515 .config = check_ntp_time_config_init(), 528 .config = check_ntp_time_config_init(),
516 }; 529 };
517 530
518 char *owarn = "60";
519 char *ocrit = "120";
520
521 while (true) { 531 while (true) {
522 int option = 0; 532 int option = 0;
523 int option_char = getopt_long(argc, argv, "Vhv46qw:c:t:H:p:o:", longopts, &option); 533 int option_char = getopt_long(argc, argv, "Vhv46qw:c:t:H:p:o:", longopts, &option);
@@ -540,12 +550,24 @@ check_ntp_time_config_wrapper process_arguments(int argc, char **argv) {
540 case 'q': 550 case 'q':
541 result.config.quiet = true; 551 result.config.quiet = true;
542 break; 552 break;
543 case 'w': 553 case 'w': {
544 owarn = optarg; 554 mp_range_parsed tmp = mp_parse_range_string(optarg);
545 break; 555 if (tmp.error != MP_PARSING_SUCCES) {
546 case 'c': 556 die(STATE_UNKNOWN, "failed to parse warning threshold");
547 ocrit = optarg; 557 }
548 break; 558
559 result.config.offset_thresholds =
560 mp_thresholds_set_warn(result.config.offset_thresholds, tmp.range);
561 } break;
562 case 'c': {
563 mp_range_parsed tmp = mp_parse_range_string(optarg);
564 if (tmp.error != MP_PARSING_SUCCES) {
565 die(STATE_UNKNOWN, "failed to parse crit threshold");
566 }
567
568 result.config.offset_thresholds =
569 mp_thresholds_set_crit(result.config.offset_thresholds, tmp.range);
570 } break;
549 case 'H': 571 case 'H':
550 if (!is_host(optarg)) { 572 if (!is_host(optarg)) {
551 usage2(_("Invalid hostname/address"), optarg); 573 usage2(_("Invalid hostname/address"), optarg);
@@ -582,16 +604,9 @@ check_ntp_time_config_wrapper process_arguments(int argc, char **argv) {
582 usage4(_("Hostname was not supplied")); 604 usage4(_("Hostname was not supplied"));
583 } 605 }
584 606
585 set_thresholds(&result.config.offset_thresholds, owarn, ocrit);
586
587 return result; 607 return result;
588} 608}
589 609
590char *perfd_offset(double offset, thresholds *offset_thresholds) {
591 return fperfdata("offset", offset, "s", true, offset_thresholds->warning->end, true,
592 offset_thresholds->critical->end, false, 0, false, 0);
593}
594
595int main(int argc, char *argv[]) { 610int main(int argc, char *argv[]) {
596 setlocale(LC_ALL, ""); 611 setlocale(LC_ALL, "");
597 bindtextdomain(PACKAGE, LOCALEDIR); 612 bindtextdomain(PACKAGE, LOCALEDIR);
@@ -614,46 +629,37 @@ int main(int argc, char *argv[]) {
614 /* set socket timeout */ 629 /* set socket timeout */
615 alarm(socket_timeout); 630 alarm(socket_timeout);
616 631
617 mp_state_enum offset_result = STATE_OK; 632 mp_check overall = mp_check_init();
618 mp_state_enum result = STATE_OK;
619 double offset =
620 offset_request(config.server_address, config.port, &offset_result, config.time_offset);
621 if (offset_result == STATE_UNKNOWN) {
622 result = ((!config.quiet) ? STATE_UNKNOWN : STATE_CRITICAL);
623 } else {
624 result = get_status(fabs(offset), config.offset_thresholds);
625 }
626 633
627 char *result_line; 634 mp_subcheck sc_offset = mp_subcheck_init();
628 switch (result) { 635 offset_request_wrapper offset_result =
629 case STATE_CRITICAL: 636 offset_request(config.server_address, config.port, config.time_offset);
630 xasprintf(&result_line, _("NTP CRITICAL:"));
631 break;
632 case STATE_WARNING:
633 xasprintf(&result_line, _("NTP WARNING:"));
634 break;
635 case STATE_OK:
636 xasprintf(&result_line, _("NTP OK:"));
637 break;
638 default:
639 xasprintf(&result_line, _("NTP UNKNOWN:"));
640 break;
641 }
642 637
643 char *perfdata_line; 638 if (offset_result.offset_result == STATE_UNKNOWN) {
644 if (offset_result == STATE_UNKNOWN) { 639 sc_offset =
645 xasprintf(&result_line, "%s %s", result_line, _("Offset unknown")); 640 mp_set_subcheck_state(sc_offset, (!config.quiet) ? STATE_UNKNOWN : STATE_CRITICAL);
646 xasprintf(&perfdata_line, ""); 641 xasprintf(&sc_offset.output, "Offset unknown");
647 } else { 642 mp_add_subcheck_to_check(&overall, sc_offset);
648 xasprintf(&result_line, "%s %s %.10g secs", result_line, _("Offset"), offset); 643 mp_exit(overall);
649 xasprintf(&perfdata_line, "%s", perfd_offset(offset, config.offset_thresholds));
650 } 644 }
651 printf("%s|%s\n", result_line, perfdata_line); 645
646 xasprintf(&sc_offset.output, "Offset: %.6fs", offset_result.offset);
647
648 mp_perfdata pd_offset = perfdata_init();
649 pd_offset = mp_set_pd_value(pd_offset, fabs(offset_result.offset));
650 pd_offset.label = "offset";
651 pd_offset.uom = "s";
652 pd_offset = mp_pd_set_thresholds(pd_offset, config.offset_thresholds);
653
654 sc_offset = mp_set_subcheck_state(sc_offset, mp_get_pd_status(pd_offset));
655
656 mp_add_perfdata_to_subcheck(&sc_offset, pd_offset);
657 mp_add_subcheck_to_check(&overall, sc_offset);
652 658
653 if (config.server_address != NULL) { 659 if (config.server_address != NULL) {
654 free(config.server_address); 660 free(config.server_address);
655 } 661 }
656 exit(result); 662 mp_exit(overall);
657} 663}
658 664
659void print_help(void) { 665void print_help(void) {
@@ -677,7 +683,7 @@ void print_help(void) {
677 printf(" %s\n", _("Offset to result in warning status (seconds)")); 683 printf(" %s\n", _("Offset to result in warning status (seconds)"));
678 printf(" %s\n", "-c, --critical=THRESHOLD"); 684 printf(" %s\n", "-c, --critical=THRESHOLD");
679 printf(" %s\n", _("Offset to result in critical status (seconds)")); 685 printf(" %s\n", _("Offset to result in critical status (seconds)"));
680 printf(" %s\n", "-o, --time_offset=INTEGER"); 686 printf(" %s\n", "-o, --time-offset=INTEGER");
681 printf(" %s\n", _("Expected offset of the ntp server relative to local server (seconds)")); 687 printf(" %s\n", _("Expected offset of the ntp server relative to local server (seconds)"));
682 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 688 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
683 printf(UT_VERBOSE); 689 printf(UT_VERBOSE);
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 {
11 bool quiet; 11 bool quiet;
12 int time_offset; 12 int time_offset;
13 13
14 thresholds *offset_thresholds; 14 mp_thresholds offset_thresholds;
15} check_ntp_time_config; 15} check_ntp_time_config;
16 16
17check_ntp_time_config check_ntp_time_config_init() { 17check_ntp_time_config check_ntp_time_config_init() {
@@ -22,7 +22,16 @@ check_ntp_time_config check_ntp_time_config_init() {
22 .quiet = false, 22 .quiet = false,
23 .time_offset = 0, 23 .time_offset = 0,
24 24
25 .offset_thresholds = NULL, 25 .offset_thresholds = mp_thresholds_init(),
26 }; 26 };
27
28 mp_range warning = mp_range_init();
29 warning = mp_range_set_end(warning, mp_create_pd_value(60));
30 tmp.offset_thresholds = mp_thresholds_set_warn(tmp.offset_thresholds, warning);
31
32 mp_range critical = mp_range_init();
33 critical = mp_range_set_end(warning, mp_create_pd_value(120));
34 tmp.offset_thresholds = mp_thresholds_set_crit(tmp.offset_thresholds, critical);
35
27 return tmp; 36 return tmp;
28} 37}