diff options
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/check_ntp_peer.c | 72 | ||||
| -rw-r--r-- | plugins/t/check_ntp.t | 24 |
2 files changed, 69 insertions, 27 deletions
diff --git a/plugins/check_ntp_peer.c b/plugins/check_ntp_peer.c index e8325bc8..d4689bc7 100644 --- a/plugins/check_ntp_peer.c +++ b/plugins/check_ntp_peer.c | |||
| @@ -56,6 +56,9 @@ static char *scrit="-1:16"; | |||
| 56 | static short do_jitter=0; | 56 | static short do_jitter=0; |
| 57 | static char *jwarn="-1:5000"; | 57 | static char *jwarn="-1:5000"; |
| 58 | static char *jcrit="-1:10000"; | 58 | static char *jcrit="-1:10000"; |
| 59 | static short do_truechimers=0; | ||
| 60 | static char *twarn="0:"; | ||
| 61 | static char *tcrit="0:"; | ||
| 59 | static int syncsource_found=0; | 62 | static int syncsource_found=0; |
| 60 | static int li_alarm=0; | 63 | static int li_alarm=0; |
| 61 | 64 | ||
| @@ -63,6 +66,7 @@ int process_arguments (int, char **); | |||
| 63 | thresholds *offset_thresholds = NULL; | 66 | thresholds *offset_thresholds = NULL; |
| 64 | thresholds *jitter_thresholds = NULL; | 67 | thresholds *jitter_thresholds = NULL; |
| 65 | thresholds *stratum_thresholds = NULL; | 68 | thresholds *stratum_thresholds = NULL; |
| 69 | thresholds *truechimer_thresholds = NULL; | ||
| 66 | void print_help (void); | 70 | void print_help (void); |
| 67 | void print_usage (void); | 71 | void print_usage (void); |
| 68 | 72 | ||
| @@ -121,6 +125,7 @@ typedef struct { | |||
| 121 | #define OP_READVAR 0x02 | 125 | #define OP_READVAR 0x02 |
| 122 | /* In peer status bytes, bits 6,7,8 determine clock selection status */ | 126 | /* In peer status bytes, bits 6,7,8 determine clock selection status */ |
| 123 | #define PEER_SEL(x) ((ntohs(x)>>8)&0x07) | 127 | #define PEER_SEL(x) ((ntohs(x)>>8)&0x07) |
| 128 | #define PEER_TRUECHIMER 0x02 | ||
| 124 | #define PEER_INCLUDED 0x04 | 129 | #define PEER_INCLUDED 0x04 |
| 125 | #define PEER_SYNCSOURCE 0x06 | 130 | #define PEER_SYNCSOURCE 0x06 |
| 126 | 131 | ||
| @@ -160,12 +165,12 @@ void print_ntp_control_message(const ntp_control_message *p){ | |||
| 160 | for(i=0;i<numpeers;i++){ | 165 | for(i=0;i<numpeers;i++){ |
| 161 | printf("\tpeer id %.2x status %.2x", | 166 | printf("\tpeer id %.2x status %.2x", |
| 162 | ntohs(peer[i].assoc), ntohs(peer[i].status)); | 167 | ntohs(peer[i].assoc), ntohs(peer[i].status)); |
| 163 | if (PEER_SEL(peer[i].status) >= PEER_INCLUDED){ | 168 | if(PEER_SEL(peer[i].status) >= PEER_SYNCSOURCE){ |
| 164 | if(PEER_SEL(peer[i].status) >= PEER_SYNCSOURCE){ | 169 | printf(" <-- current sync source"); |
| 165 | printf(" <-- current sync source"); | 170 | } else if(PEER_SEL(peer[i].status) >= PEER_INCLUDED){ |
| 166 | } else { | 171 | printf(" <-- current sync candidate"); |
| 167 | printf(" <-- current sync candidate"); | 172 | } else if(PEER_SEL(peer[i].status) >= PEER_TRUECHIMER){ |
| 168 | } | 173 | printf(" <-- outlyer, but truechimer"); |
| 169 | } | 174 | } |
| 170 | printf("\n"); | 175 | printf("\n"); |
| 171 | } | 176 | } |
| @@ -194,7 +199,7 @@ setup_control_request(ntp_control_message *p, uint8_t opcode, uint16_t seq){ | |||
| 194 | * status is pretty much useless as syncsource_found is a global variable | 199 | * status is pretty much useless as syncsource_found is a global variable |
| 195 | * used later in main to check is the server was synchronized. It works | 200 | * used later in main to check is the server was synchronized. It works |
| 196 | * so I left it alone */ | 201 | * so I left it alone */ |
| 197 | int ntp_request(const char *host, double *offset, int *offset_result, double *jitter, int *stratum){ | 202 | int ntp_request(const char *host, double *offset, int *offset_result, double *jitter, int *stratum, int *num_truechimers){ |
| 198 | int conn=-1, i, npeers=0, num_candidates=0; | 203 | int conn=-1, i, npeers=0, num_candidates=0; |
| 199 | double tmp_offset = 0; | 204 | double tmp_offset = 0; |
| 200 | int min_peer_sel=PEER_INCLUDED; | 205 | int min_peer_sel=PEER_INCLUDED; |
| @@ -209,6 +214,7 @@ int ntp_request(const char *host, double *offset, int *offset_result, double *ji | |||
| 209 | status = STATE_OK; | 214 | status = STATE_OK; |
| 210 | *offset_result = STATE_UNKNOWN; | 215 | *offset_result = STATE_UNKNOWN; |
| 211 | *jitter = *stratum = -1; | 216 | *jitter = *stratum = -1; |
| 217 | *num_truechimers = 0; | ||
| 212 | 218 | ||
| 213 | /* Long-winded explanation: | 219 | /* Long-winded explanation: |
| 214 | * Getting the sync peer offset, jitter and stratum requires a number of | 220 | * Getting the sync peer offset, jitter and stratum requires a number of |
| @@ -261,11 +267,14 @@ int ntp_request(const char *host, double *offset, int *offset_result, double *ji | |||
| 261 | * at least some candidates. In the latter case we'll issue | 267 | * at least some candidates. In the latter case we'll issue |
| 262 | * a warning but go ahead with the check on them. */ | 268 | * a warning but go ahead with the check on them. */ |
| 263 | for (i = 0; i < npeers; i++){ | 269 | for (i = 0; i < npeers; i++){ |
| 264 | if (PEER_SEL(peers[i].status) >= PEER_INCLUDED){ | 270 | if(PEER_SEL(peers[i].status) >= PEER_TRUECHIMER){ |
| 265 | num_candidates++; | 271 | (*num_truechimers)++; |
| 266 | if(PEER_SEL(peers[i].status) >= PEER_SYNCSOURCE){ | 272 | if(PEER_SEL(peers[i].status) >= PEER_INCLUDED){ |
| 267 | syncsource_found=1; | 273 | num_candidates++; |
| 268 | min_peer_sel=PEER_SYNCSOURCE; | 274 | if(PEER_SEL(peers[i].status) >= PEER_SYNCSOURCE){ |
| 275 | syncsource_found=1; | ||
| 276 | min_peer_sel=PEER_SYNCSOURCE; | ||
| 277 | } | ||
| 269 | } | 278 | } |
| 270 | } | 279 | } |
| 271 | } | 280 | } |
| @@ -413,6 +422,8 @@ int process_arguments(int argc, char **argv){ | |||
| 413 | {"scrit", required_argument, 0, 'C'}, | 422 | {"scrit", required_argument, 0, 'C'}, |
| 414 | {"jwarn", required_argument, 0, 'j'}, | 423 | {"jwarn", required_argument, 0, 'j'}, |
| 415 | {"jcrit", required_argument, 0, 'k'}, | 424 | {"jcrit", required_argument, 0, 'k'}, |
| 425 | {"twarn", required_argument, 0, 'm'}, | ||
| 426 | {"tcrit", required_argument, 0, 'n'}, | ||
| 416 | {"timeout", required_argument, 0, 't'}, | 427 | {"timeout", required_argument, 0, 't'}, |
| 417 | {"hostname", required_argument, 0, 'H'}, | 428 | {"hostname", required_argument, 0, 'H'}, |
| 418 | {"port", required_argument, 0, 'p'}, | 429 | {"port", required_argument, 0, 'p'}, |
| @@ -424,7 +435,7 @@ int process_arguments(int argc, char **argv){ | |||
| 424 | usage ("\n"); | 435 | usage ("\n"); |
| 425 | 436 | ||
| 426 | while (1) { | 437 | while (1) { |
| 427 | c = getopt_long (argc, argv, "Vhv46qw:c:W:C:j:k:t:H:p:", longopts, &option); | 438 | c = getopt_long (argc, argv, "Vhv46qw:c:W:C:j:k:m:n:t:H:p:", longopts, &option); |
| 428 | if (c == -1 || c == EOF || c == 1) | 439 | if (c == -1 || c == EOF || c == 1) |
| 429 | break; | 440 | break; |
| 430 | 441 | ||
| @@ -467,6 +478,14 @@ int process_arguments(int argc, char **argv){ | |||
| 467 | do_jitter=1; | 478 | do_jitter=1; |
| 468 | jcrit = optarg; | 479 | jcrit = optarg; |
| 469 | break; | 480 | break; |
| 481 | case 'm': | ||
| 482 | do_truechimers=1; | ||
| 483 | twarn = optarg; | ||
| 484 | break; | ||
| 485 | case 'n': | ||
| 486 | do_truechimers=1; | ||
| 487 | tcrit = optarg; | ||
| 488 | break; | ||
| 470 | case 'H': | 489 | case 'H': |
| 471 | if(is_host(optarg) == FALSE) | 490 | if(is_host(optarg) == FALSE) |
| 472 | usage2(_("Invalid hostname/address"), optarg); | 491 | usage2(_("Invalid hostname/address"), optarg); |
| @@ -526,8 +545,16 @@ char *perfd_stratum (int stratum) | |||
| 526 | TRUE, 0, TRUE, 16); | 545 | TRUE, 0, TRUE, 16); |
| 527 | } | 546 | } |
| 528 | 547 | ||
| 548 | char *perfd_truechimers (int num_truechimers) | ||
| 549 | { | ||
| 550 | return perfdata ("truechimers", num_truechimers, "", | ||
| 551 | do_truechimers, (int)truechimer_thresholds->warning->end, | ||
| 552 | do_truechimers, (int)truechimer_thresholds->critical->end, | ||
| 553 | TRUE, 0, FALSE, 0); | ||
| 554 | } | ||
| 555 | |||
| 529 | int main(int argc, char *argv[]){ | 556 | int main(int argc, char *argv[]){ |
| 530 | int result, offset_result, stratum; | 557 | int result, offset_result, stratum, num_truechimers; |
| 531 | double offset=0, jitter=0; | 558 | double offset=0, jitter=0; |
| 532 | char *result_line, *perfdata_line; | 559 | char *result_line, *perfdata_line; |
| 533 | 560 | ||
| @@ -544,6 +571,7 @@ int main(int argc, char *argv[]){ | |||
| 544 | set_thresholds(&offset_thresholds, owarn, ocrit); | 571 | set_thresholds(&offset_thresholds, owarn, ocrit); |
| 545 | set_thresholds(&jitter_thresholds, jwarn, jcrit); | 572 | set_thresholds(&jitter_thresholds, jwarn, jcrit); |
| 546 | set_thresholds(&stratum_thresholds, swarn, scrit); | 573 | set_thresholds(&stratum_thresholds, swarn, scrit); |
| 574 | set_thresholds(&truechimer_thresholds, twarn, tcrit); | ||
| 547 | 575 | ||
| 548 | /* initialize alarm signal handling */ | 576 | /* initialize alarm signal handling */ |
| 549 | signal (SIGALRM, socket_timeout_alarm_handler); | 577 | signal (SIGALRM, socket_timeout_alarm_handler); |
| @@ -552,7 +580,7 @@ int main(int argc, char *argv[]){ | |||
| 552 | alarm (socket_timeout); | 580 | alarm (socket_timeout); |
| 553 | 581 | ||
| 554 | /* This returns either OK or WARNING (See comment preceeding ntp_request) */ | 582 | /* This returns either OK or WARNING (See comment preceeding ntp_request) */ |
| 555 | result = ntp_request(server_address, &offset, &offset_result, &jitter, &stratum); | 583 | result = ntp_request(server_address, &offset, &offset_result, &jitter, &stratum, &num_truechimers); |
| 556 | 584 | ||
| 557 | if(offset_result == STATE_UNKNOWN) { | 585 | if(offset_result == STATE_UNKNOWN) { |
| 558 | /* if there's no sync peer (this overrides ntp_request output): */ | 586 | /* if there's no sync peer (this overrides ntp_request output): */ |
| @@ -564,6 +592,9 @@ int main(int argc, char *argv[]){ | |||
| 564 | result = max_state_alt(result, get_status(fabs(offset), offset_thresholds)); | 592 | result = max_state_alt(result, get_status(fabs(offset), offset_thresholds)); |
| 565 | } | 593 | } |
| 566 | 594 | ||
| 595 | if(do_truechimers) | ||
| 596 | result = max_state_alt(result, get_status(num_truechimers, truechimer_thresholds)); | ||
| 597 | |||
| 567 | if(do_stratum) | 598 | if(do_stratum) |
| 568 | result = max_state_alt(result, get_status(stratum, stratum_thresholds)); | 599 | result = max_state_alt(result, get_status(stratum, stratum_thresholds)); |
| 569 | 600 | ||
| @@ -604,6 +635,10 @@ int main(int argc, char *argv[]){ | |||
| 604 | asprintf(&result_line, "%s, stratum=%i", result_line, stratum); | 635 | asprintf(&result_line, "%s, stratum=%i", result_line, stratum); |
| 605 | asprintf(&perfdata_line, "%s %s", perfdata_line, perfd_stratum(stratum)); | 636 | asprintf(&perfdata_line, "%s %s", perfdata_line, perfd_stratum(stratum)); |
| 606 | } | 637 | } |
| 638 | if (do_truechimers) { | ||
| 639 | asprintf(&result_line, "%s, truechimers=%i", result_line, num_truechimers); | ||
| 640 | asprintf(&perfdata_line, "%s %s", perfdata_line, perfd_truechimers(num_truechimers)); | ||
| 641 | } | ||
| 607 | printf("%s|%s\n", result_line, perfdata_line); | 642 | printf("%s|%s\n", result_line, perfdata_line); |
| 608 | 643 | ||
| 609 | if(server_address!=NULL) free(server_address); | 644 | if(server_address!=NULL) free(server_address); |
| @@ -640,6 +675,10 @@ void print_help(void){ | |||
| 640 | printf (" %s\n", _("Warning threshold for jitter")); | 675 | printf (" %s\n", _("Warning threshold for jitter")); |
| 641 | printf (" %s\n", "-k, --jcrit=THRESHOLD"); | 676 | printf (" %s\n", "-k, --jcrit=THRESHOLD"); |
| 642 | printf (" %s\n", _("Critical threshold for jitter")); | 677 | printf (" %s\n", _("Critical threshold for jitter")); |
| 678 | printf (" %s\n", "-m, --twarn=THRESHOLD"); | ||
| 679 | printf (" %s\n", _("Warning threshold for number of usable time sources (\"truechimers\")")); | ||
| 680 | printf (" %s\n", "-n, --tcrit=THRESHOLD"); | ||
| 681 | printf (" %s\n", _("Critical threshold for number of usable time sources (\"truechimers\")")); | ||
| 643 | printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT); | 682 | printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT); |
| 644 | printf (_(UT_VERBOSE)); | 683 | printf (_(UT_VERBOSE)); |
| 645 | 684 | ||
| @@ -668,6 +707,9 @@ void print_help(void){ | |||
| 668 | printf(" %s\n", _("(See Notes above for more details on thresholds formats):")); | 707 | printf(" %s\n", _("(See Notes above for more details on thresholds formats):")); |
| 669 | printf(" %s\n", ("./check_ntp_peer -H ntpserv -w 0.5 -c 1 -j -1:100 -k -1:200")); | 708 | printf(" %s\n", ("./check_ntp_peer -H ntpserv -w 0.5 -c 1 -j -1:100 -k -1:200")); |
| 670 | printf("\n"); | 709 | printf("\n"); |
| 710 | printf(" %s\n", _("Only check the number of usable time sources (\"truechimers\"):")); | ||
| 711 | printf(" %s\n", ("./check_ntp_peer -H ntpserv -m :5 -n :3")); | ||
| 712 | printf("\n"); | ||
| 671 | printf(" %s\n", _("Check only stratum:")); | 713 | printf(" %s\n", _("Check only stratum:")); |
| 672 | printf(" %s\n", ("./check_ntp_peer -H ntpserv -W 4 -C 6")); | 714 | printf(" %s\n", ("./check_ntp_peer -H ntpserv -W 4 -C 6")); |
| 673 | 715 | ||
diff --git a/plugins/t/check_ntp.t b/plugins/t/check_ntp.t index b71c8631..3eee6e17 100644 --- a/plugins/t/check_ntp.t +++ b/plugins/t/check_ntp.t | |||
| @@ -34,9 +34,9 @@ my $hostname_invalid = getTestParameter( "NP_HOSTNAME_INVALID", | |||
| 34 | my $ntp_okmatch1 = '/^NTP\sOK:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/'; | 34 | my $ntp_okmatch1 = '/^NTP\sOK:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/'; |
| 35 | my $ntp_warnmatch1 = '/^NTP\sWARNING:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/'; | 35 | my $ntp_warnmatch1 = '/^NTP\sWARNING:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/'; |
| 36 | my $ntp_critmatch1 = '/^NTP\sCRITICAL:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/'; | 36 | my $ntp_critmatch1 = '/^NTP\sCRITICAL:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/'; |
| 37 | my $ntp_okmatch2 = '/^NTP\sOK:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2}/'; | 37 | my $ntp_okmatch2 = '/^NTP\sOK:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2},\struechimers=[0-9]+/'; |
| 38 | my $ntp_warnmatch2 = '/^NTP\sWARNING:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2}/'; | 38 | my $ntp_warnmatch2 = '/^NTP\sWARNING:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2},\struechimers=[0-9]+/'; |
| 39 | my $ntp_critmatch2 = '/^NTP\sCRITICAL:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2}/'; | 39 | my $ntp_critmatch2 = '/^NTP\sCRITICAL:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2},\struechimers=[0-9]+/'; |
| 40 | my $ntp_noresponse = '/^(CRITICAL - Socket timeout after 3 seconds)|(NTP CRITICAL: No response from NTP server)$/'; | 40 | my $ntp_noresponse = '/^(CRITICAL - Socket timeout after 3 seconds)|(NTP CRITICAL: No response from NTP server)$/'; |
| 41 | my $ntp_nosuchhost = '/^check_ntp.*: Invalid hostname/address - ' . $hostname_invalid . '/'; | 41 | my $ntp_nosuchhost = '/^check_ntp.*: Invalid hostname/address - ' . $hostname_invalid . '/'; |
| 42 | 42 | ||
| @@ -90,21 +90,21 @@ foreach my $plugin (@PLUGINS2) { | |||
| 90 | SKIP: { | 90 | SKIP: { |
| 91 | skip "No NTP server defined", 1 unless $ntp_service; | 91 | skip "No NTP server defined", 1 unless $ntp_service; |
| 92 | $res = NPTest->testCmd( | 92 | $res = NPTest->testCmd( |
| 93 | "./$plugin -H $ntp_service -w 1000 -c 2000 -W 20 -C 21 -j 100000 -k 200000" | 93 | "./$plugin -H $ntp_service -w 1000 -c 2000 -W 20 -C 21 -j 100000 -k 200000 -m 1: -n 0:" |
| 94 | ); | 94 | ); |
| 95 | cmp_ok( $res->return_code, '==', 0, "$plugin: Good NTP result with jitter and stratum check" ); | 95 | cmp_ok( $res->return_code, '==', 0, "$plugin: Good NTP result with jitter, stratum, and truechimers check" ); |
| 96 | like( $res->output, $ntp_okmatch2, "$plugin: Output match OK with jitter and stratum" ); | 96 | like( $res->output, $ntp_okmatch2, "$plugin: Output match OK with jitter, stratum, and truechimers" ); |
| 97 | 97 | ||
| 98 | $res = NPTest->testCmd( | 98 | $res = NPTest->testCmd( |
| 99 | "./$plugin -H $ntp_service -w 1000 -c 2000 -W \\~:-1 -C 21 -j 100000 -k 200000" | 99 | "./$plugin -H $ntp_service -w 1000 -c 2000 -W \\~:-1 -C 21 -j 100000 -k 200000 -m 1: -n 0:" |
| 100 | ); | 100 | ); |
| 101 | cmp_ok( $res->return_code, '==', 1, "$plugin: Warning NTP result with jitter and stratum check" ); | 101 | cmp_ok( $res->return_code, '==', 1, "$plugin: Warning NTP result with jitter, stratum, and truechimers check" ); |
| 102 | like( $res->output, $ntp_warnmatch2, "$plugin: Output match WARNING with jitter and stratum" ); | 102 | like( $res->output, $ntp_warnmatch2, "$plugin: Output match WARNING with jitter, stratum, and truechimers" ); |
| 103 | 103 | ||
| 104 | $res = NPTest->testCmd( | 104 | $res = NPTest->testCmd( |
| 105 | "./$plugin -H $ntp_service -w 1000 -c 2000 -W 20 -C 21 -j 100000 -k \\~:-1" | 105 | "./$plugin -H $ntp_service -w 1000 -c 2000 -W 20 -C 21 -j 100000 -k \\~:-1 -m 1: -n 0:" |
| 106 | ); | 106 | ); |
| 107 | cmp_ok( $res->return_code, '==', 2, "$plugin: Critical NTP result with jitter and stratum check" ); | 107 | cmp_ok( $res->return_code, '==', 2, "$plugin: Critical NTP result with jitter, stratum, and truechimers check" ); |
| 108 | like( $res->output, $ntp_critmatch2, "$plugin: Output match CRITICAL with jitter and stratum" ); | 108 | like( $res->output, $ntp_critmatch2, "$plugin: Output match CRITICAL with jitter, stratum, and truechimers" ); |
| 109 | } | 109 | } |
| 110 | } | 110 | } |
