diff options
Diffstat (limited to 'plugins/check_ntp_time.c')
| -rw-r--r-- | plugins/check_ntp_time.c | 80 |
1 files changed, 58 insertions, 22 deletions
diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c index 602b6010..9e0beb9c 100644 --- a/plugins/check_ntp_time.c +++ b/plugins/check_ntp_time.c | |||
| @@ -42,6 +42,8 @@ | |||
| 42 | #include "states.h" | 42 | #include "states.h" |
| 43 | #include "thresholds.h" | 43 | #include "thresholds.h" |
| 44 | #include "check_ntp_time.d/config.h" | 44 | #include "check_ntp_time.d/config.h" |
| 45 | #include <netinet/in.h> | ||
| 46 | #include <sys/socket.h> | ||
| 45 | 47 | ||
| 46 | static int verbose = 0; | 48 | static int verbose = 0; |
| 47 | 49 | ||
| @@ -336,17 +338,25 @@ static offset_request_wrapper offset_request(const char *host, const char *port, | |||
| 336 | hints.ai_protocol = IPPROTO_UDP; | 338 | hints.ai_protocol = IPPROTO_UDP; |
| 337 | hints.ai_socktype = SOCK_DGRAM; | 339 | hints.ai_socktype = SOCK_DGRAM; |
| 338 | 340 | ||
| 339 | /* fill in ai with the list of hosts resolved by the host name */ | 341 | bool is_socket; |
| 340 | struct addrinfo *addresses = NULL; | 342 | struct addrinfo *addresses = NULL; |
| 341 | int ga_result = getaddrinfo(host, port, &hints, &addresses); | ||
| 342 | if (ga_result != 0) { | ||
| 343 | die(STATE_UNKNOWN, "error getting address for %s: %s\n", host, gai_strerror(ga_result)); | ||
| 344 | } | ||
| 345 | |||
| 346 | /* count the number of returned hosts, and allocate stuff accordingly */ | ||
| 347 | size_t num_hosts = 0; | 343 | size_t num_hosts = 0; |
| 348 | for (struct addrinfo *ai_tmp = addresses; ai_tmp != NULL; ai_tmp = ai_tmp->ai_next) { | 344 | if (host[0] == '/') { |
| 349 | num_hosts++; | 345 | num_hosts = 1; |
| 346 | is_socket = true; | ||
| 347 | } else { | ||
| 348 | is_socket = false; | ||
| 349 | |||
| 350 | /* fill in ai with the list of hosts resolved by the host name */ | ||
| 351 | int ga_result = getaddrinfo(host, port, &hints, &addresses); | ||
| 352 | if (ga_result != 0) { | ||
| 353 | die(STATE_UNKNOWN, "error getting address for %s: %s\n", host, gai_strerror(ga_result)); | ||
| 354 | } | ||
| 355 | |||
| 356 | /* count the number of returned hosts, and allocate stuff accordingly */ | ||
| 357 | for (struct addrinfo *ai_tmp = addresses; ai_tmp != NULL; ai_tmp = ai_tmp->ai_next) { | ||
| 358 | num_hosts++; | ||
| 359 | } | ||
| 350 | } | 360 | } |
| 351 | 361 | ||
| 352 | ntp_message *req = (ntp_message *)malloc(sizeof(ntp_message) * num_hosts); | 362 | ntp_message *req = (ntp_message *)malloc(sizeof(ntp_message) * num_hosts); |
| @@ -374,25 +384,51 @@ static offset_request_wrapper offset_request(const char *host, const char *port, | |||
| 374 | DBG(printf("Found %zu peers to check\n", num_hosts)); | 384 | DBG(printf("Found %zu peers to check\n", num_hosts)); |
| 375 | 385 | ||
| 376 | /* setup each socket for writing, and the corresponding struct pollfd */ | 386 | /* setup each socket for writing, and the corresponding struct pollfd */ |
| 377 | struct addrinfo *ai_tmp = addresses; | 387 | if (is_socket) { |
| 378 | for (int i = 0; ai_tmp; i++) { | 388 | socklist[0] = socket(AF_UNIX, SOCK_STREAM, 0); |
| 379 | socklist[i] = socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP); | 389 | if (socklist[0] == -1) { |
| 380 | if (socklist[i] == -1) { | 390 | DBG(printf("can't create socket: %s\n", strerror(errno))); |
| 381 | perror(NULL); | 391 | die(STATE_UNKNOWN, "can not create new socket\n"); |
| 382 | die(STATE_UNKNOWN, "can not create new socket"); | ||
| 383 | } | 392 | } |
| 384 | if (connect(socklist[i], ai_tmp->ai_addr, ai_tmp->ai_addrlen)) { | 393 | |
| 394 | struct sockaddr_un unix_socket = { | ||
| 395 | .sun_family = AF_UNIX, | ||
| 396 | }; | ||
| 397 | |||
| 398 | strncpy(unix_socket.sun_path, host, strlen(host)); | ||
| 399 | |||
| 400 | if (connect(socklist[0], &unix_socket, sizeof(unix_socket))) { | ||
| 385 | /* don't die here, because it is enough if there is one server | 401 | /* don't die here, because it is enough if there is one server |
| 386 | answering in time. This also would break for dual ipv4/6 stacked | 402 | answering in time. This also would break for dual ipv4/6 stacked |
| 387 | ntp servers when the client only supports on of them. | 403 | ntp servers when the client only supports on of them. |
| 388 | */ | 404 | */ |
| 389 | DBG(printf("can't create socket connection on peer %i: %s\n", i, strerror(errno))); | 405 | DBG(printf("can't create socket connection on peer %i: %s\n", 0, strerror(errno))); |
| 390 | } else { | 406 | } else { |
| 391 | ufds[i].fd = socklist[i]; | 407 | ufds[0].fd = socklist[0]; |
| 392 | ufds[i].events = POLLIN; | 408 | ufds[0].events = POLLIN; |
| 393 | ufds[i].revents = 0; | 409 | ufds[0].revents = 0; |
| 410 | } | ||
| 411 | } else { | ||
| 412 | struct addrinfo *ai_tmp = addresses; | ||
| 413 | for (int i = 0; ai_tmp; i++) { | ||
| 414 | socklist[i] = socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP); | ||
| 415 | if (socklist[i] == -1) { | ||
| 416 | perror(NULL); | ||
| 417 | die(STATE_UNKNOWN, "can not create new socket"); | ||
| 418 | } | ||
| 419 | if (connect(socklist[i], ai_tmp->ai_addr, ai_tmp->ai_addrlen)) { | ||
| 420 | /* don't die here, because it is enough if there is one server | ||
| 421 | answering in time. This also would break for dual ipv4/6 stacked | ||
| 422 | ntp servers when the client only supports on of them. | ||
| 423 | */ | ||
| 424 | DBG(printf("can't create socket connection on peer %i: %s\n", i, strerror(errno))); | ||
| 425 | } else { | ||
| 426 | ufds[i].fd = socklist[i]; | ||
| 427 | ufds[i].events = POLLIN; | ||
| 428 | ufds[i].revents = 0; | ||
| 429 | } | ||
| 430 | ai_tmp = ai_tmp->ai_next; | ||
| 394 | } | 431 | } |
| 395 | ai_tmp = ai_tmp->ai_next; | ||
| 396 | } | 432 | } |
| 397 | 433 | ||
| 398 | /* now do AVG_NUM checks to each host. We stop before timeout/2 seconds | 434 | /* now do AVG_NUM checks to each host. We stop before timeout/2 seconds |
| @@ -586,7 +622,7 @@ static check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { | |||
| 586 | mp_thresholds_set_crit(result.config.offset_thresholds, tmp.range); | 622 | mp_thresholds_set_crit(result.config.offset_thresholds, tmp.range); |
| 587 | } break; | 623 | } break; |
| 588 | case 'H': | 624 | case 'H': |
| 589 | if (!is_host(optarg)) { | 625 | if (!is_host(optarg) && (optarg[0] != '/')) { |
| 590 | usage2(_("Invalid hostname/address"), optarg); | 626 | usage2(_("Invalid hostname/address"), optarg); |
| 591 | } | 627 | } |
| 592 | result.config.server_address = strdup(optarg); | 628 | result.config.server_address = strdup(optarg); |
