From 2f96b82c9b67ca1aad6cd584a9c458d060bdd4bb Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Fri, 28 Nov 2025 10:52:39 +0100 Subject: check_ntp_time/check_ntp_peer: unix socket handling (#2187) * check_ntp_time/check_ntp_peer: unix socket handling * No tests for check_ntp since it is deprecated --- plugins/check_ntp_peer.c | 2 +- plugins/check_ntp_time.c | 81 +++++++++++++++++++++++++++++++++++------------- plugins/t/check_ntp.t | 2 +- 3 files changed, 61 insertions(+), 24 deletions(-) (limited to 'plugins') diff --git a/plugins/check_ntp_peer.c b/plugins/check_ntp_peer.c index f7cad630..26f74286 100644 --- a/plugins/check_ntp_peer.c +++ b/plugins/check_ntp_peer.c @@ -625,7 +625,7 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { mp_thresholds_set_crit(result.config.truechimer_thresholds, tmp.range); } break; case 'H': - if (!is_host(optarg)) { + if (!is_host(optarg) && (optarg[0] != '/')) { usage2(_("Invalid hostname/address"), optarg); } result.config.server_address = strdup(optarg); diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c index 602b6010..1300faea 100644 --- a/plugins/check_ntp_time.c +++ b/plugins/check_ntp_time.c @@ -42,6 +42,8 @@ #include "states.h" #include "thresholds.h" #include "check_ntp_time.d/config.h" +#include +#include static int verbose = 0; @@ -336,17 +338,26 @@ static offset_request_wrapper offset_request(const char *host, const char *port, hints.ai_protocol = IPPROTO_UDP; hints.ai_socktype = SOCK_DGRAM; - /* fill in ai with the list of hosts resolved by the host name */ + bool is_socket; struct addrinfo *addresses = NULL; - int ga_result = getaddrinfo(host, port, &hints, &addresses); - if (ga_result != 0) { - die(STATE_UNKNOWN, "error getting address for %s: %s\n", host, gai_strerror(ga_result)); - } - - /* count the number of returned hosts, and allocate stuff accordingly */ size_t num_hosts = 0; - for (struct addrinfo *ai_tmp = addresses; ai_tmp != NULL; ai_tmp = ai_tmp->ai_next) { - num_hosts++; + if (host[0] == '/') { + num_hosts = 1; + is_socket = true; + } else { + is_socket = false; + + /* fill in ai with the list of hosts resolved by the host name */ + struct addrinfo *addresses = NULL; + int ga_result = getaddrinfo(host, port, &hints, &addresses); + if (ga_result != 0) { + die(STATE_UNKNOWN, "error getting address for %s: %s\n", host, gai_strerror(ga_result)); + } + + /* count the number of returned hosts, and allocate stuff accordingly */ + for (struct addrinfo *ai_tmp = addresses; ai_tmp != NULL; ai_tmp = ai_tmp->ai_next) { + num_hosts++; + } } ntp_message *req = (ntp_message *)malloc(sizeof(ntp_message) * num_hosts); @@ -374,25 +385,51 @@ static offset_request_wrapper offset_request(const char *host, const char *port, DBG(printf("Found %zu peers to check\n", num_hosts)); /* setup each socket for writing, and the corresponding struct pollfd */ - struct addrinfo *ai_tmp = addresses; - for (int i = 0; ai_tmp; i++) { - socklist[i] = socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP); - if (socklist[i] == -1) { - perror(NULL); - die(STATE_UNKNOWN, "can not create new socket"); + if (is_socket) { + socklist[0] = socket(AF_UNIX, SOCK_STREAM, 0); + if (socklist[0] == -1) { + DBG(printf("can't create socket: %s\n", strerror(errno))); + die(STATE_UNKNOWN, "can not create new socket\n"); } - if (connect(socklist[i], ai_tmp->ai_addr, ai_tmp->ai_addrlen)) { + + struct sockaddr_un unix_socket = { + .sun_family = AF_UNIX, + }; + + strncpy(unix_socket.sun_path, host, strlen(host)); + + if (connect(socklist[0], &unix_socket, sizeof(unix_socket))) { /* don't die here, because it is enough if there is one server answering in time. This also would break for dual ipv4/6 stacked ntp servers when the client only supports on of them. */ - DBG(printf("can't create socket connection on peer %i: %s\n", i, strerror(errno))); + DBG(printf("can't create socket connection on peer %i: %s\n", 0, strerror(errno))); } else { - ufds[i].fd = socklist[i]; - ufds[i].events = POLLIN; - ufds[i].revents = 0; + ufds[0].fd = socklist[0]; + ufds[0].events = POLLIN; + ufds[0].revents = 0; + } + } else { + struct addrinfo *ai_tmp = addresses; + for (int i = 0; ai_tmp; i++) { + socklist[i] = socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP); + if (socklist[i] == -1) { + perror(NULL); + die(STATE_UNKNOWN, "can not create new socket"); + } + if (connect(socklist[i], ai_tmp->ai_addr, ai_tmp->ai_addrlen)) { + /* don't die here, because it is enough if there is one server + answering in time. This also would break for dual ipv4/6 stacked + ntp servers when the client only supports on of them. + */ + DBG(printf("can't create socket connection on peer %i: %s\n", i, strerror(errno))); + } else { + ufds[i].fd = socklist[i]; + ufds[i].events = POLLIN; + ufds[i].revents = 0; + } + ai_tmp = ai_tmp->ai_next; } - ai_tmp = ai_tmp->ai_next; } /* now do AVG_NUM checks to each host. We stop before timeout/2 seconds @@ -586,7 +623,7 @@ static check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { mp_thresholds_set_crit(result.config.offset_thresholds, tmp.range); } break; case 'H': - if (!is_host(optarg)) { + if (!is_host(optarg) && (optarg[0] != '/')) { usage2(_("Invalid hostname/address"), optarg); } result.config.server_address = strdup(optarg); diff --git a/plugins/t/check_ntp.t b/plugins/t/check_ntp.t index a8ac7bb8..7703bc3b 100644 --- a/plugins/t/check_ntp.t +++ b/plugins/t/check_ntp.t @@ -8,7 +8,7 @@ use strict; use Test::More; use NPTest; -my @PLUGINS1 = ('check_ntp', 'check_ntp_peer', 'check_ntp_time'); +my @PLUGINS1 = ('check_ntp_peer', 'check_ntp_time'); my @PLUGINS2 = ('check_ntp_peer'); plan tests => (12 * scalar(@PLUGINS1)) + (6 * scalar(@PLUGINS2)); -- cgit v1.2.3-74-g34f1