summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/check_ntp_peer.c72
-rw-r--r--plugins/t/check_ntp.t24
2 files changed, 69 insertions, 27 deletions
diff --git a/plugins/check_ntp_peer.c b/plugins/check_ntp_peer.c
index e8325bc..d4689bc 100644
--- a/plugins/check_ntp_peer.c
+++ b/plugins/check_ntp_peer.c
@@ -56,6 +56,9 @@ static char *scrit="-1:16";
56static short do_jitter=0; 56static short do_jitter=0;
57static char *jwarn="-1:5000"; 57static char *jwarn="-1:5000";
58static char *jcrit="-1:10000"; 58static char *jcrit="-1:10000";
59static short do_truechimers=0;
60static char *twarn="0:";
61static char *tcrit="0:";
59static int syncsource_found=0; 62static int syncsource_found=0;
60static int li_alarm=0; 63static int li_alarm=0;
61 64
@@ -63,6 +66,7 @@ int process_arguments (int, char **);
63thresholds *offset_thresholds = NULL; 66thresholds *offset_thresholds = NULL;
64thresholds *jitter_thresholds = NULL; 67thresholds *jitter_thresholds = NULL;
65thresholds *stratum_thresholds = NULL; 68thresholds *stratum_thresholds = NULL;
69thresholds *truechimer_thresholds = NULL;
66void print_help (void); 70void print_help (void);
67void print_usage (void); 71void 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 */
197int ntp_request(const char *host, double *offset, int *offset_result, double *jitter, int *stratum){ 202int 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
548char *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
529int main(int argc, char *argv[]){ 556int 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 b71c863..3eee6e1 100644
--- a/plugins/t/check_ntp.t
+++ b/plugins/t/check_ntp.t
@@ -34,9 +34,9 @@ my $hostname_invalid = getTestParameter( "NP_HOSTNAME_INVALID",
34my $ntp_okmatch1 = '/^NTP\sOK:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/'; 34my $ntp_okmatch1 = '/^NTP\sOK:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/';
35my $ntp_warnmatch1 = '/^NTP\sWARNING:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/'; 35my $ntp_warnmatch1 = '/^NTP\sWARNING:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/';
36my $ntp_critmatch1 = '/^NTP\sCRITICAL:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/'; 36my $ntp_critmatch1 = '/^NTP\sCRITICAL:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/';
37my $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}/'; 37my $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]+/';
38my $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}/'; 38my $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]+/';
39my $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}/'; 39my $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]+/';
40my $ntp_noresponse = '/^(CRITICAL - Socket timeout after 3 seconds)|(NTP CRITICAL: No response from NTP server)$/'; 40my $ntp_noresponse = '/^(CRITICAL - Socket timeout after 3 seconds)|(NTP CRITICAL: No response from NTP server)$/';
41my $ntp_nosuchhost = '/^check_ntp.*: Invalid hostname/address - ' . $hostname_invalid . '/'; 41my $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}