summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/check_ntp_time.c109
1 files changed, 56 insertions, 53 deletions
diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c
index 85024c5..703b69d 100644
--- a/plugins/check_ntp_time.c
+++ b/plugins/check_ntp_time.c
@@ -209,17 +209,19 @@ typedef struct {
209 209
210/* calculate the offset of the local clock */ 210/* calculate the offset of the local clock */
211static inline double calc_offset(const ntp_message *m, const struct timeval *t) { 211static inline double calc_offset(const ntp_message *m, const struct timeval *t) {
212 double client_tx, peer_rx, peer_tx, client_rx; 212 double client_tx = NTP64asDOUBLE(m->origts);
213 client_tx = NTP64asDOUBLE(m->origts); 213 double peer_rx = NTP64asDOUBLE(m->rxts);
214 peer_rx = NTP64asDOUBLE(m->rxts); 214 double peer_tx = NTP64asDOUBLE(m->txts);
215 peer_tx = NTP64asDOUBLE(m->txts); 215 double client_rx = TVasDOUBLE((*t));
216 client_rx = TVasDOUBLE((*t));
217 return (.5 * ((peer_tx - client_rx) + (peer_rx - client_tx))); 216 return (.5 * ((peer_tx - client_rx) + (peer_rx - client_tx)));
218} 217}
219 218
220/* print out a ntp packet in human readable/debuggable format */ 219/* print out a ntp packet in human readable/debuggable format */
221void print_ntp_message(const ntp_message *p) { 220void print_ntp_message(const ntp_message *p) {
222 struct timeval ref, orig, rx, tx; 221 struct timeval ref;
222 struct timeval orig;
223 struct timeval rx;
224 struct timeval tx;
223 225
224 NTP64toTV(p->refts, ref); 226 NTP64toTV(p->refts, ref);
225 NTP64toTV(p->origts, orig); 227 NTP64toTV(p->origts, orig);
@@ -244,8 +246,6 @@ void print_ntp_message(const ntp_message *p) {
244} 246}
245 247
246void setup_request(ntp_message *p) { 248void setup_request(ntp_message *p) {
247 struct timeval t;
248
249 memset(p, 0, sizeof(ntp_message)); 249 memset(p, 0, sizeof(ntp_message));
250 LI_SET(p->flags, LI_ALARM); 250 LI_SET(p->flags, LI_ALARM);
251 VN_SET(p->flags, 4); 251 VN_SET(p->flags, 4);
@@ -255,6 +255,7 @@ void setup_request(ntp_message *p) {
255 L16(p->rtdelay) = htons(1); 255 L16(p->rtdelay) = htons(1);
256 L16(p->rtdisp) = htons(1); 256 L16(p->rtdisp) = htons(1);
257 257
258 struct timeval t;
258 gettimeofday(&t, NULL); 259 gettimeofday(&t, NULL);
259 TVtoNTP64(t, p->txts); 260 TVtoNTP64(t, p->txts);
260} 261}
@@ -263,10 +264,10 @@ void setup_request(ntp_message *p) {
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) { 266int best_offset_server(const ntp_server_results *slist, int nservers) {
266 int cserver = 0, best_server = -1; 267 int best_server = -1;
267 268
268 /* for each server */ 269 /* for each server */
269 for (cserver = 0; cserver < nservers; cserver++) { 270 for (int cserver = 0; cserver < nservers; cserver++) {
270 /* We don't want any servers that fails these tests */ 271 /* We don't want any servers that fails these tests */
271 /* Sort out servers that didn't respond or responede with a 0 stratum; 272 /* Sort out servers that didn't respond or responede with a 0 stratum;
272 * stratum 0 is for reference clocks so no NTP server should ever report 273 * stratum 0 is for reference clocks so no NTP server should ever report
@@ -311,10 +312,9 @@ int best_offset_server(const ntp_server_results *slist, int nservers) {
311 if (best_server >= 0) { 312 if (best_server >= 0) {
312 DBG(printf("best server selected: peer %d\n", best_server)); 313 DBG(printf("best server selected: peer %d\n", best_server));
313 return best_server; 314 return best_server;
314 } else {
315 DBG(printf("no peers meeting synchronization criteria :(\n"));
316 return -1;
317 } 315 }
316 DBG(printf("no peers meeting synchronization criteria :(\n"));
317 return -1;
318} 318}
319 319
320/* do everything we need to get the total average offset 320/* do everything we need to get the total average offset
@@ -323,50 +323,48 @@ int best_offset_server(const ntp_server_results *slist, int nservers) {
323 * - we also "manually" handle resolving host names and connecting, because 323 * - we also "manually" handle resolving host names and connecting, because
324 * we have to do it in a way that our lazy macros don't handle currently :( */ 324 * we have to do it in a way that our lazy macros don't handle currently :( */
325double offset_request(const char *host, int *status) { 325double offset_request(const char *host, int *status) {
326 int i = 0, j = 0, ga_result = 0, num_hosts = 0, *socklist = NULL, respnum = 0;
327 int servers_completed = 0, one_read = 0, servers_readable = 0, best_index = -1;
328 time_t now_time = 0, start_ts = 0;
329 ntp_message *req = NULL;
330 double avg_offset = 0.;
331 struct timeval recv_time;
332 struct addrinfo *ai = NULL, *ai_tmp = NULL, hints;
333 struct pollfd *ufds = NULL;
334 ntp_server_results *servers = NULL;
335
336 /* setup hints to only return results from getaddrinfo that we'd like */ 326 /* setup hints to only return results from getaddrinfo that we'd like */
327 struct addrinfo hints;
337 memset(&hints, 0, sizeof(struct addrinfo)); 328 memset(&hints, 0, sizeof(struct addrinfo));
338 hints.ai_family = address_family; 329 hints.ai_family = address_family;
339 hints.ai_protocol = IPPROTO_UDP; 330 hints.ai_protocol = IPPROTO_UDP;
340 hints.ai_socktype = SOCK_DGRAM; 331 hints.ai_socktype = SOCK_DGRAM;
341 332
342 /* fill in ai with the list of hosts resolved by the host name */ 333 /* fill in ai with the list of hosts resolved by the host name */
343 ga_result = getaddrinfo(host, port, &hints, &ai); 334 struct addrinfo *ai = NULL;
335 int ga_result = getaddrinfo(host, port, &hints, &ai);
344 if (ga_result != 0) { 336 if (ga_result != 0) {
345 die(STATE_UNKNOWN, "error getting address for %s: %s\n", host, gai_strerror(ga_result)); 337 die(STATE_UNKNOWN, "error getting address for %s: %s\n", host, gai_strerror(ga_result));
346 } 338 }
347 339
348 /* count the number of returned hosts, and allocate stuff accordingly */ 340 /* count the number of returned hosts, and allocate stuff accordingly */
349 for (ai_tmp = ai; ai_tmp != NULL; ai_tmp = ai_tmp->ai_next) { 341 int num_hosts = 0;
342 for (struct addrinfo *ai_tmp = ai; ai_tmp != NULL; ai_tmp = ai_tmp->ai_next) {
350 num_hosts++; 343 num_hosts++;
351 } 344 }
352 req = (ntp_message *)malloc(sizeof(ntp_message) * num_hosts); 345
346 ntp_message *req = (ntp_message *)malloc(sizeof(ntp_message) * num_hosts);
347
353 if (req == NULL) 348 if (req == NULL)
354 die(STATE_UNKNOWN, "can not allocate ntp message array"); 349 die(STATE_UNKNOWN, "can not allocate ntp message array");
355 socklist = (int *)malloc(sizeof(int) * num_hosts); 350 int *socklist = (int *)malloc(sizeof(int) * num_hosts);
351
356 if (socklist == NULL) 352 if (socklist == NULL)
357 die(STATE_UNKNOWN, "can not allocate socket array"); 353 die(STATE_UNKNOWN, "can not allocate socket array");
358 ufds = (struct pollfd *)malloc(sizeof(struct pollfd) * num_hosts); 354
355 struct pollfd *ufds = (struct pollfd *)malloc(sizeof(struct pollfd) * num_hosts);
359 if (ufds == NULL) 356 if (ufds == NULL)
360 die(STATE_UNKNOWN, "can not allocate socket array"); 357 die(STATE_UNKNOWN, "can not allocate socket array");
361 servers = (ntp_server_results *)malloc(sizeof(ntp_server_results) * num_hosts); 358
359 ntp_server_results *servers = (ntp_server_results *)malloc(sizeof(ntp_server_results) * num_hosts);
362 if (servers == NULL) 360 if (servers == NULL)
363 die(STATE_UNKNOWN, "can not allocate server array"); 361 die(STATE_UNKNOWN, "can not allocate server array");
364 memset(servers, 0, sizeof(ntp_server_results) * num_hosts); 362 memset(servers, 0, sizeof(ntp_server_results) * num_hosts);
365 DBG(printf("Found %d peers to check\n", num_hosts)); 363 DBG(printf("Found %d peers to check\n", num_hosts));
366 364
367 /* setup each socket for writing, and the corresponding struct pollfd */ 365 /* setup each socket for writing, and the corresponding struct pollfd */
368 ai_tmp = ai; 366 struct addrinfo *ai_tmp = ai;
369 for (i = 0; ai_tmp; i++) { 367 for (int i = 0; ai_tmp; i++) {
370 socklist[i] = socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP); 368 socklist[i] = socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP);
371 if (socklist[i] == -1) { 369 if (socklist[i] == -1) {
372 perror(NULL); 370 perror(NULL);
@@ -388,7 +386,11 @@ double offset_request(const char *host, int *status) {
388 386
389 /* now do AVG_NUM checks to each host. We stop before timeout/2 seconds 387 /* now do AVG_NUM checks to each host. We stop before timeout/2 seconds
390 * have passed in order to ensure post-processing and jitter time. */ 388 * have passed in order to ensure post-processing and jitter time. */
389 time_t start_ts = 0;
390 time_t now_time = 0;
391 now_time = start_ts = time(NULL); 391 now_time = start_ts = time(NULL);
392 int servers_completed = 0;
393 bool one_read = false;
392 while (servers_completed < num_hosts && now_time - start_ts <= socket_timeout / 2) { 394 while (servers_completed < num_hosts && now_time - start_ts <= socket_timeout / 2) {
393 /* loop through each server and find each one which hasn't 395 /* loop through each server and find each one which hasn't
394 * been touched in the past second or so and is still lacking 396 * been touched in the past second or so and is still lacking
@@ -396,7 +398,7 @@ double offset_request(const char *host, int *status) {
396 * and update the "waiting" timestamp with the current time. */ 398 * and update the "waiting" timestamp with the current time. */
397 now_time = time(NULL); 399 now_time = time(NULL);
398 400
399 for (i = 0; i < num_hosts; i++) { 401 for (int i = 0; i < num_hosts; i++) {
400 if (servers[i].waiting < now_time && servers[i].num_responses < AVG_NUM) { 402 if (servers[i].waiting < now_time && servers[i].num_responses < AVG_NUM) {
401 if (verbose && servers[i].waiting != 0) 403 if (verbose && servers[i].waiting != 0)
402 printf("re-"); 404 printf("re-");
@@ -410,23 +412,25 @@ double offset_request(const char *host, int *status) {
410 } 412 }
411 413
412 /* quickly poll for any sockets with pending data */ 414 /* quickly poll for any sockets with pending data */
413 servers_readable = poll(ufds, num_hosts, 100); 415 int servers_readable = poll(ufds, num_hosts, 100);
414 if (servers_readable == -1) { 416 if (servers_readable == -1) {
415 perror("polling ntp sockets"); 417 perror("polling ntp sockets");
416 die(STATE_UNKNOWN, "communication errors"); 418 die(STATE_UNKNOWN, "communication errors");
417 } 419 }
418 420
419 /* read from any sockets with pending data */ 421 /* read from any sockets with pending data */
420 for (i = 0; servers_readable && i < num_hosts; i++) { 422 for (int i = 0; servers_readable && i < num_hosts; i++) {
421 if (ufds[i].revents & POLLIN && servers[i].num_responses < AVG_NUM) { 423 if (ufds[i].revents & POLLIN && servers[i].num_responses < AVG_NUM) {
422 if (verbose) { 424 if (verbose) {
423 printf("response from peer %d: ", i); 425 printf("response from peer %d: ", i);
424 } 426 }
425 427
426 read(ufds[i].fd, &req[i], sizeof(ntp_message)); 428 read(ufds[i].fd, &req[i], sizeof(ntp_message));
429
430 struct timeval recv_time;
427 gettimeofday(&recv_time, NULL); 431 gettimeofday(&recv_time, NULL);
428 DBG(print_ntp_message(&req[i])); 432 DBG(print_ntp_message(&req[i]));
429 respnum = servers[i].num_responses++; 433 int respnum = servers[i].num_responses++;
430 servers[i].offset[respnum] = calc_offset(&req[i], &recv_time) + time_offset; 434 servers[i].offset[respnum] = calc_offset(&req[i], &recv_time) + time_offset;
431 if (verbose) { 435 if (verbose) {
432 printf("offset %.10g\n", servers[i].offset[respnum]); 436 printf("offset %.10g\n", servers[i].offset[respnum]);
@@ -437,7 +441,7 @@ double offset_request(const char *host, int *status) {
437 servers[i].waiting = 0; 441 servers[i].waiting = 0;
438 servers[i].flags = req[i].flags; 442 servers[i].flags = req[i].flags;
439 servers_readable--; 443 servers_readable--;
440 one_read = 1; 444 one_read = true;
441 if (servers[i].num_responses == AVG_NUM) 445 if (servers[i].num_responses == AVG_NUM)
442 servers_completed++; 446 servers_completed++;
443 } 447 }
@@ -445,24 +449,25 @@ double offset_request(const char *host, int *status) {
445 /* lather, rinse, repeat. */ 449 /* lather, rinse, repeat. */
446 } 450 }
447 451
448 if (one_read == 0) { 452 if (one_read == false) {
449 die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n"); 453 die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n");
450 } 454 }
451 455
452 /* now, pick the best server from the list */ 456 /* now, pick the best server from the list */
453 best_index = best_offset_server(servers, num_hosts); 457 double avg_offset = 0.;
458 int best_index = best_offset_server(servers, num_hosts);
454 if (best_index < 0) { 459 if (best_index < 0) {
455 *status = STATE_UNKNOWN; 460 *status = STATE_UNKNOWN;
456 } else { 461 } else {
457 /* finally, calculate the average offset */ 462 /* finally, calculate the average offset */
458 for (i = 0; i < servers[best_index].num_responses; i++) { 463 for (int i = 0; i < servers[best_index].num_responses; i++) {
459 avg_offset += servers[best_index].offset[i]; 464 avg_offset += servers[best_index].offset[i];
460 } 465 }
461 avg_offset /= servers[best_index].num_responses; 466 avg_offset /= servers[best_index].num_responses;
462 } 467 }
463 468
464 /* cleanup */ 469 /* cleanup */
465 for (j = 0; j < num_hosts; j++) { 470 for (int j = 0; j < num_hosts; j++) {
466 close(socklist[j]); 471 close(socklist[j]);
467 } 472 }
468 free(socklist); 473 free(socklist);
@@ -477,8 +482,6 @@ double offset_request(const char *host, int *status) {
477} 482}
478 483
479int process_arguments(int argc, char **argv) { 484int process_arguments(int argc, char **argv) {
480 int c;
481 int option = 0;
482 static struct option longopts[] = {{"version", no_argument, 0, 'V'}, 485 static struct option longopts[] = {{"version", no_argument, 0, 'V'},
483 {"help", no_argument, 0, 'h'}, 486 {"help", no_argument, 0, 'h'},
484 {"verbose", no_argument, 0, 'v'}, 487 {"verbose", no_argument, 0, 'v'},
@@ -496,12 +499,13 @@ int process_arguments(int argc, char **argv) {
496 if (argc < 2) 499 if (argc < 2)
497 usage("\n"); 500 usage("\n");
498 501
499 while (1) { 502 while (true) {
500 c = getopt_long(argc, argv, "Vhv46qw:c:t:H:p:o:", longopts, &option); 503 int option = 0;
501 if (c == -1 || c == EOF || c == 1) 504 int option_char = getopt_long(argc, argv, "Vhv46qw:c:t:H:p:o:", longopts, &option);
505 if (option_char == -1 || option_char == EOF || option_char == 1)
502 break; 506 break;
503 507
504 switch (c) { 508 switch (option_char) {
505 case 'h': 509 case 'h':
506 print_help(); 510 print_help();
507 exit(STATE_UNKNOWN); 511 exit(STATE_UNKNOWN);
@@ -566,16 +570,10 @@ char *perfd_offset(double offset) {
566} 570}
567 571
568int main(int argc, char *argv[]) { 572int main(int argc, char *argv[]) {
569 int result, offset_result;
570 double offset = 0;
571 char *result_line, *perfdata_line;
572
573 setlocale(LC_ALL, ""); 573 setlocale(LC_ALL, "");
574 bindtextdomain(PACKAGE, LOCALEDIR); 574 bindtextdomain(PACKAGE, LOCALEDIR);
575 textdomain(PACKAGE); 575 textdomain(PACKAGE);
576 576
577 result = offset_result = STATE_OK;
578
579 /* Parse extra opts if any */ 577 /* Parse extra opts if any */
580 argv = np_extra_opts(&argc, argv, progname); 578 argv = np_extra_opts(&argc, argv, progname);
581 579
@@ -590,13 +588,16 @@ int main(int argc, char *argv[]) {
590 /* set socket timeout */ 588 /* set socket timeout */
591 alarm(socket_timeout); 589 alarm(socket_timeout);
592 590
593 offset = offset_request(server_address, &offset_result); 591 int offset_result = STATE_OK;
592 int result = STATE_OK;
593 double offset = offset_request(server_address, &offset_result);
594 if (offset_result == STATE_UNKNOWN) { 594 if (offset_result == STATE_UNKNOWN) {
595 result = ((!quiet) ? STATE_UNKNOWN : STATE_CRITICAL); 595 result = ((!quiet) ? STATE_UNKNOWN : STATE_CRITICAL);
596 } else { 596 } else {
597 result = get_status(fabs(offset), offset_thresholds); 597 result = get_status(fabs(offset), offset_thresholds);
598 } 598 }
599 599
600 char *result_line;
600 switch (result) { 601 switch (result) {
601 case STATE_CRITICAL: 602 case STATE_CRITICAL:
602 xasprintf(&result_line, _("NTP CRITICAL:")); 603 xasprintf(&result_line, _("NTP CRITICAL:"));
@@ -611,6 +612,8 @@ int main(int argc, char *argv[]) {
611 xasprintf(&result_line, _("NTP UNKNOWN:")); 612 xasprintf(&result_line, _("NTP UNKNOWN:"));
612 break; 613 break;
613 } 614 }
615
616 char *perfdata_line;
614 if (offset_result == STATE_UNKNOWN) { 617 if (offset_result == STATE_UNKNOWN) {
615 xasprintf(&result_line, "%s %s", result_line, _("Offset unknown")); 618 xasprintf(&result_line, "%s %s", result_line, _("Offset unknown"));
616 xasprintf(&perfdata_line, ""); 619 xasprintf(&perfdata_line, "");