Module: monitoring-plugins
    Branch: master
    Commit: 2f96b82c9b67ca1aad6cd584a9c458d060bdd4bb
    Author: Lorenz Kästle <[email protected]>
 Committer: GitHub <[email protected]>
      Date: Fri Nov 28 10:52:39 2025 +0100
       URL: 
https://www.monitoring-plugins.org/repositories/monitoring-plugins/commit/?id=2f96b82c

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(-)

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 <netinet/in.h>
+#include <sys/socket.h>
 
 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));

Reply via email to