From 4ab8a54c52fa78c1d8d757bcb75a8e5d4b3e560f Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Wed, 2 Apr 2025 00:13:20 +0200 Subject: check_icmp: linter fixes --- plugins-root/check_icmp.c | 131 ++++++++++++++++++++++++++-------------------- 1 file changed, 74 insertions(+), 57 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index dcaceddb..6a4239a8 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -208,29 +208,25 @@ typedef enum enum_threshold_mode threshold_mode; /** prototypes **/ void print_help(void); void print_usage(void); -static u_int get_timevar(const char *); -static u_int get_timevaldiff(struct timeval *, struct timeval *); -static in_addr_t get_ip_address(const char *); -static int wait_for_reply(int, u_int); -static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval *); -static int send_icmp_ping(int, struct rta_host *); +static u_int get_timevar(const char * /*str*/); +static u_int get_timevaldiff(struct timeval * /*early*/, struct timeval * /*later*/); +static in_addr_t get_ip_address(const char * /*ifname*/); +static int wait_for_reply(int /*sock*/, u_int /*t*/); +static int recvfrom_wto(int /*sock*/, void * /*buf*/, unsigned int /*len*/, struct sockaddr * /*saddr*/, u_int * /*timo*/, + struct timeval * /*tv*/); +static int send_icmp_ping(int /*sock*/, struct rta_host * /*host*/); static int get_threshold(char *str, threshold *th); -static bool get_threshold2(char *str, size_t length, threshold *, threshold *, threshold_mode mode); +static bool get_threshold2(char *str, size_t length, threshold * /*warn*/, threshold * /*crit*/, threshold_mode mode); static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, threshold_mode mode); static void run_checks(void); -static void set_source_ip(char *); -static int add_target(char *); -static int add_target_ip(char *, struct sockaddr_storage *); -static int handle_random_icmp(unsigned char *, struct sockaddr_storage *); -static void parse_address(struct sockaddr_storage *, char *, int); -static unsigned short icmp_checksum(uint16_t *, size_t); -static void finish(int); -static void crash(const char *, ...); - -/** external **/ -extern int optind; -extern char *optarg; -extern char **environ; +static void set_source_ip(char * /*arg*/); +static int add_target(char * /*arg*/); +static int add_target_ip(char * /*arg*/, struct sockaddr_storage * /*in*/); +static int handle_random_icmp(unsigned char * /*packet*/, struct sockaddr_storage * /*addr*/); +static void parse_address(struct sockaddr_storage * /*addr*/, char * /*address*/, int /*size*/); +static unsigned short icmp_checksum(uint16_t * /*p*/, size_t /*n*/); +static void finish(int /*sig*/); +static void crash(const char * /*fmt*/, ...); /** global variables **/ static struct rta_host **table, *cursor, *list; @@ -386,7 +382,8 @@ static const char *get_icmp_error_msg(unsigned char icmp_type, unsigned char icm } static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr) { - struct icmp p, sent_icmp; + struct icmp p; + struct icmp sent_icmp; struct rta_host *host = NULL; memcpy(&p, packet, sizeof(p)); @@ -469,7 +466,9 @@ int main(int argc, char **argv) { int i; char *ptr; long int arg; - int icmp_sockerrno, udp_sockerrno, tcp_sockerrno; + int icmp_sockerrno; + int udp_sockerrno; + int tcp_sockerrno; int result; struct rta_host *host; #ifdef HAVE_SIGACTION @@ -880,8 +879,10 @@ int main(int argc, char **argv) { } static void run_checks(void) { - u_int i, t; - u_int final_wait, time_passed; + u_int i; + u_int t; + u_int final_wait; + u_int time_passed; /* this loop might actually violate the pkt_interval or target_interval * settings, but only if there aren't any packets on the wire which @@ -940,15 +941,19 @@ static void run_checks(void) { * icmp echo reply : the rest */ static int wait_for_reply(int sock, u_int t) { - int n, hlen; + int n; + int hlen; static unsigned char buf[65536]; struct sockaddr_storage resp_addr; union ip_hdr *ip; union icmp_packet packet; struct rta_host *host; struct icmp_ping_data data; - struct timeval wait_start, now; - u_int tdiff, i, per_pkt_wait; + struct timeval wait_start; + struct timeval now; + u_int tdiff; + u_int i; + u_int per_pkt_wait; double jitter_tmp; if (!(packet.buf = malloc(icmp_pkt_size))) { @@ -1045,14 +1050,14 @@ static int wait_for_reply(int sock, u_int t) { if (address_family == PF_INET) { memcpy(&data, packet.icp->icmp_data, sizeof(data)); if (debug > 2) { - printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", (unsigned long)sizeof(data), ntohs(packet.icp->icmp_id), + printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", sizeof(data), ntohs(packet.icp->icmp_id), ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum); } host = table[ntohs(packet.icp->icmp_seq) / packets]; } else { memcpy(&data, &packet.icp6->icmp6_dataun.icmp6_un_data8[4], sizeof(data)); if (debug > 2) { - printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", (unsigned long)sizeof(data), ntohs(packet.icp6->icmp6_id), + printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", sizeof(data), ntohs(packet.icp6->icmp6_id), ntohs(packet.icp6->icmp6_seq), packet.icp6->icmp6_cksum); } host = table[ntohs(packet.icp6->icmp6_seq) / packets]; @@ -1182,8 +1187,8 @@ static int send_icmp_ping(int sock, struct rta_host *host) { icp->icmp_cksum = icmp_checksum((uint16_t *)buf, (size_t)icmp_pkt_size); if (debug > 2) { - printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", (unsigned long)sizeof(data), - ntohs(icp->icmp_id), ntohs(icp->icmp_seq), icp->icmp_cksum, host->name); + printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", sizeof(data), ntohs(icp->icmp_id), + ntohs(icp->icmp_seq), icp->icmp_cksum, host->name); } } else { struct icmp6_hdr *icp6 = (struct icmp6_hdr *)buf; @@ -1199,8 +1204,8 @@ static int send_icmp_ping(int sock, struct rta_host *host) { // let checksum be calculated automatically if (debug > 2) { - printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", (unsigned long)sizeof(data), - ntohs(icp6->icmp6_id), ntohs(icp6->icmp6_seq), icp6->icmp6_cksum, host->name); + printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", sizeof(data), ntohs(icp6->icmp6_id), + ntohs(icp6->icmp6_seq), icp6->icmp6_cksum, host->name); } } @@ -1228,7 +1233,7 @@ static int send_icmp_ping(int sock, struct rta_host *host) { if (len < 0 || (unsigned int)len != icmp_pkt_size) { if (debug) { char address[INET6_ADDRSTRLEN]; - parse_address((struct sockaddr_storage *)&host->saddr_in, address, sizeof(address)); + parse_address((&host->saddr_in), address, sizeof(address)); printf("Failed to send ping to %s: %s\n", address, strerror(errno)); } errno = 0; @@ -1243,9 +1248,13 @@ static int send_icmp_ping(int sock, struct rta_host *host) { static int recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, u_int *timo, struct timeval *tv) { u_int slen; - int n, ret; - struct timeval to, then, now; - fd_set rd, wr; + int n; + int ret; + struct timeval to; + struct timeval then; + struct timeval now; + fd_set rd; + fd_set wr; #ifdef HAVE_MSGHDR_MSG_CONTROL char ans_data[4096]; #endif // HAVE_MSGHDR_MSG_CONTROL @@ -1701,8 +1710,10 @@ static u_int get_timevaldiff(struct timeval *early, struct timeval *later) { static int add_target_ip(char *arg, struct sockaddr_storage *in) { struct rta_host *host; - struct sockaddr_in *sin, *host_sin; - struct sockaddr_in6 *sin6, *host_sin6; + struct sockaddr_in *sin; + struct sockaddr_in *host_sin; + struct sockaddr_in6 *sin6; + struct sockaddr_in6 *host_sin6; if (address_family == AF_INET) { sin = (struct sockaddr_in *)in; @@ -1786,9 +1797,12 @@ static int add_target_ip(char *arg, struct sockaddr_storage *in) { /* wrapper for add_target_ip */ static int add_target(char *arg) { - int error, result = -1; + int error; + int result = -1; struct sockaddr_storage ip; - struct addrinfo hints, *res, *p; + struct addrinfo hints; + struct addrinfo *res; + struct addrinfo *p; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; @@ -1826,22 +1840,21 @@ static int add_target(char *arg) { if (result == 1) { /* don't add all ip's if we were given a specific one */ return add_target_ip(arg, &ip); + } + errno = 0; + memset(&hints, 0, sizeof(hints)); + if (address_family == -1) { + hints.ai_family = AF_UNSPEC; } else { + hints.ai_family = address_family == AF_INET ? PF_INET : PF_INET6; + } + hints.ai_socktype = SOCK_RAW; + if ((error = getaddrinfo(arg, NULL, &hints, &res)) != 0) { errno = 0; - memset(&hints, 0, sizeof(hints)); - if (address_family == -1) { - hints.ai_family = AF_UNSPEC; - } else { - hints.ai_family = address_family == AF_INET ? PF_INET : PF_INET6; - } - hints.ai_socktype = SOCK_RAW; - if ((error = getaddrinfo(arg, NULL, &hints, &res)) != 0) { - errno = 0; - crash("Failed to resolve %s: %s", arg, gai_strerror(error)); - return -1; - } - address_family = res->ai_family; + crash("Failed to resolve %s: %s", arg, gai_strerror(error)); + return -1; } + address_family = res->ai_family; /* possibly add all the IP's as targets */ for (p = res; p != NULL; p = p->ai_next) { @@ -1907,9 +1920,12 @@ static in_addr_t get_ip_address(const char *ifname) { * return value is in microseconds */ static u_int get_timevar(const char *str) { - char p, u, *ptr; + char p; + char u; + char *ptr; size_t len; - u_int i, d; /* integer and decimal, respectively */ + u_int i; + u_int d; /* integer and decimal, respectively */ u_int factor = 1000; /* default to milliseconds */ if (!str) { @@ -1970,7 +1986,8 @@ static u_int get_timevar(const char *str) { /* not too good at checking errors, but it'll do (main() should barfe on -1) */ static int get_threshold(char *str, threshold *th) { - char *p = NULL, i = 0; + char *p = NULL; + char i = 0; if (!str || !strlen(str) || !th) { return -1; -- cgit v1.2.3-74-g34f1 From f62f182653650f274be0018d7a8f166aa99719d7 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Wed, 2 Apr 2025 01:04:25 +0200 Subject: check_icmp: localise variables --- plugins-root/check_icmp.c | 208 ++++++++++++++++++++-------------------------- 1 file changed, 89 insertions(+), 119 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 6a4239a8..061e7d82 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -65,6 +65,7 @@ const char *email = "devel@monitoring-plugins.org"; #include #include #include +#include /** sometimes undefined system macros (quite a few, actually) **/ #ifndef MAXTTL @@ -261,10 +262,10 @@ static bool order_mode = false; /** code start **/ static void crash(const char *fmt, ...) { - va_list ap; printf("%s: ", progname); + va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); @@ -383,9 +384,6 @@ static const char *get_icmp_error_msg(unsigned char icmp_type, unsigned char icm static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr) { struct icmp p; - struct icmp sent_icmp; - struct rta_host *host = NULL; - memcpy(&p, packet, sizeof(p)); if (p.icmp_type == ICMP_ECHO && ntohs(p.icmp_id) == pid) { /* echo request from us to us (pinging localhost) */ @@ -412,6 +410,7 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad /* might be for us. At least it holds the original package (according * to RFC 792). If it isn't, just ignore it */ + struct icmp sent_icmp; memcpy(&sent_icmp, packet + 28, sizeof(sent_icmp)); if (sent_icmp.icmp_type != ICMP_ECHO || ntohs(sent_icmp.icmp_id) != pid || ntohs(sent_icmp.icmp_seq) >= targets * packets) { if (debug) { @@ -421,7 +420,7 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad } /* it is indeed a response for us */ - host = table[ntohs(sent_icmp.icmp_seq) / packets]; + struct rta_host *host = table[ntohs(sent_icmp.icmp_seq) / packets]; if (debug) { char address[INET6_ADDRSTRLEN]; parse_address(addr, address, sizeof(address)); @@ -463,28 +462,15 @@ void parse_address(struct sockaddr_storage *addr, char *address, int size) { } int main(int argc, char **argv) { - int i; - char *ptr; - long int arg; - int icmp_sockerrno; - int udp_sockerrno; - int tcp_sockerrno; - int result; - struct rta_host *host; -#ifdef HAVE_SIGACTION - struct sigaction sig_action; -#endif -#ifdef SO_TIMESTAMP - int on = 1; -#endif - char *source_ip = NULL; - char *opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64"; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); /* we only need to be setsuid when we get the sockets, so do * that before pointer magic (esp. on network data) */ + int icmp_sockerrno; + int udp_sockerrno; + int tcp_sockerrno; icmp_sockerrno = udp_sockerrno = tcp_sockerrno = sockets = 0; address_family = -1; @@ -492,7 +478,7 @@ int main(int argc, char **argv) { /* get calling name the old-fashioned way for portability instead * of relying on the glibc-ism __progname */ - ptr = strrchr(argv[0], '/'); + char *ptr = strrchr(argv[0], '/'); if (ptr) { progname = &ptr[1]; } else { @@ -549,7 +535,9 @@ int main(int argc, char **argv) { } /* Parse protocol arguments first */ - for (i = 1; i < argc; i++) { + char *opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64"; + for (int i = 1; i < argc; i++) { + long int arg; while ((arg = getopt(argc, argv, opts_str)) != EOF) { switch (arg) { case '4': @@ -578,7 +566,9 @@ int main(int argc, char **argv) { unsigned long size; bool err; /* parse the arguments */ - for (i = 1; i < argc; i++) { + char *source_ip = NULL; + for (int i = 1; i < argc; i++) { + long int arg; while ((arg = getopt(argc, argv, opts_str)) != EOF) { switch (arg) { case 'v': @@ -732,6 +722,7 @@ int main(int argc, char **argv) { } #ifdef SO_TIMESTAMP + int on = 1; if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) { if (debug) { printf("Warning: no SO_TIMESTAMP support\n"); @@ -767,7 +758,7 @@ int main(int argc, char **argv) { } if (icmp_sock) { - result = setsockopt(icmp_sock, SOL_IP, IP_TTL, &ttl, sizeof(ttl)); + int result = setsockopt(icmp_sock, SOL_IP, IP_TTL, &ttl, sizeof(ttl)); if (debug) { if (result == -1) { printf("setsockopt failed\n"); @@ -801,6 +792,7 @@ int main(int argc, char **argv) { } #ifdef HAVE_SIGACTION + struct sigaction sig_action; sig_action.sa_sigaction = NULL; sig_action.sa_handler = finish; sigfillset(&sig_action.sa_mask); @@ -856,13 +848,13 @@ int main(int argc, char **argv) { crash("minimum alive hosts is negative (%i)", min_hosts_alive); } - host = list; + struct rta_host *host = list; table = malloc(sizeof(struct rta_host *) * targets); if (!table) { crash("main(): malloc failed for host table"); } - i = 0; + int i = 0; while (host) { host->id = i * packets; table[i] = host; @@ -879,16 +871,11 @@ int main(int argc, char **argv) { } static void run_checks(void) { - u_int i; - u_int t; - u_int final_wait; - u_int time_passed; - /* this loop might actually violate the pkt_interval or target_interval * settings, but only if there aren't any packets on the wire which * indicates that the target can handle an increased packet rate */ - for (i = 0; i < packets; i++) { - for (t = 0; t < targets; t++) { + for (u_int i = 0; i < packets; i++) { + for (u_int t = 0; t < targets; t++) { /* don't send useless packets */ if (!targets_alive) { finish(0); @@ -908,8 +895,8 @@ static void run_checks(void) { } if (icmp_pkts_en_route && targets_alive) { - time_passed = get_timevaldiff(NULL, NULL); - final_wait = max_completion_time - time_passed; + u_int time_passed = get_timevaldiff(NULL, NULL); + u_int final_wait = max_completion_time - time_passed; if (debug) { printf("time_passed: %u final_wait: %u max_completion_time: %llu\n", time_passed, final_wait, max_completion_time); @@ -941,21 +928,7 @@ static void run_checks(void) { * icmp echo reply : the rest */ static int wait_for_reply(int sock, u_int t) { - int n; - int hlen; - static unsigned char buf[65536]; - struct sockaddr_storage resp_addr; - union ip_hdr *ip; union icmp_packet packet; - struct rta_host *host; - struct icmp_ping_data data; - struct timeval wait_start; - struct timeval now; - u_int tdiff; - u_int i; - u_int per_pkt_wait; - double jitter_tmp; - if (!(packet.buf = malloc(icmp_pkt_size))) { crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size); return -1; /* might be reached if we're in debug mode */ @@ -969,10 +942,15 @@ static int wait_for_reply(int sock, u_int t) { return 0; } + struct timeval wait_start; gettimeofday(&wait_start, &tz); - i = t; - per_pkt_wait = t / icmp_pkts_en_route; + u_int i = t; + struct sockaddr_storage resp_addr; + u_int per_pkt_wait = t / icmp_pkts_en_route; + static unsigned char buf[65536]; + union ip_hdr *ip; + struct timeval now; while (icmp_pkts_en_route && get_timevaldiff(&wait_start, NULL) < i) { t = per_pkt_wait; @@ -982,7 +960,7 @@ static int wait_for_reply(int sock, u_int t) { } /* reap responses until we hit a timeout */ - n = recvfrom_wto(sock, buf, sizeof(buf), (struct sockaddr *)&resp_addr, &t, &now); + int n = recvfrom_wto(sock, buf, sizeof(buf), (struct sockaddr *)&resp_addr, &t, &now); if (!n) { if (debug > 1) { printf("recvfrom_wto() timed out during a %u usecs wait\n", per_pkt_wait); @@ -1015,7 +993,7 @@ static int wait_for_reply(int sock, u_int t) { * off the bottom 4 bits */ /* hlen = (ip->ip_vhl & 0x0f) << 2; */ /* #else */ - hlen = (address_family == AF_INET6) ? 0 : ip->ip.ip_hl << 2; + int hlen = (address_family == AF_INET6) ? 0 : ip->ip.ip_hl << 2; /* #endif */ if (n < (hlen + ICMP_MINLEN)) { @@ -1047,6 +1025,8 @@ static int wait_for_reply(int sock, u_int t) { } /* this is indeed a valid response */ + struct rta_host *host; + struct icmp_ping_data data; if (address_family == PF_INET) { memcpy(&data, packet.icp->icmp_data, sizeof(data)); if (debug > 2) { @@ -1063,10 +1043,11 @@ static int wait_for_reply(int sock, u_int t) { host = table[ntohs(packet.icp6->icmp6_seq) / packets]; } - tdiff = get_timevaldiff(&data.stime, &now); + u_int tdiff = get_timevaldiff(&data.stime, &now); if (host->last_tdiff > 0) { /* Calculate jitter */ + double jitter_tmp; if (host->last_tdiff > tdiff) { jitter_tmp = host->last_tdiff - tdiff; } else { @@ -1143,20 +1124,14 @@ static int wait_for_reply(int sock, u_int t) { /* the ping functions */ static int send_icmp_ping(int sock, struct rta_host *host) { - long int len; - size_t addrlen; - struct icmp_ping_data data; - struct msghdr hdr; - struct iovec iov; - struct timeval tv; - void *buf = NULL; - if (sock == -1) { errno = 0; crash("Attempt to send on bogus socket"); return -1; } + void *buf = NULL; + if (!buf) { if (!(buf = malloc(icmp_pkt_size))) { crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size); @@ -1165,14 +1140,18 @@ static int send_icmp_ping(int sock, struct rta_host *host) { } memset(buf, 0, icmp_pkt_size); + struct timeval tv; if ((gettimeofday(&tv, &tz)) == -1) { free(buf); return -1; } + struct icmp_ping_data data; data.ping_id = 10; /* host->icmp.icmp_sent; */ memcpy(&data.stime, &tv, sizeof(tv)); + size_t addrlen; + if (address_family == AF_INET) { struct icmp *icp = (struct icmp *)buf; addrlen = sizeof(struct sockaddr_in); @@ -1209,10 +1188,12 @@ static int send_icmp_ping(int sock, struct rta_host *host) { } } + struct iovec iov; memset(&iov, 0, sizeof(iov)); iov.iov_base = buf; iov.iov_len = icmp_pkt_size; + struct msghdr hdr; memset(&hdr, 0, sizeof(hdr)); hdr.msg_name = (struct sockaddr *)&host->saddr_in; hdr.msg_namelen = addrlen; @@ -1221,6 +1202,7 @@ static int send_icmp_ping(int sock, struct rta_host *host) { errno = 0; + long int len; /* MSG_CONFIRM is a linux thing and only available on linux kernels >= 2.3.15, see send(2) */ #ifdef MSG_CONFIRM len = sendmsg(sock, &hdr, MSG_CONFIRM); @@ -1247,19 +1229,9 @@ static int send_icmp_ping(int sock, struct rta_host *host) { } static int recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, u_int *timo, struct timeval *tv) { - u_int slen; - int n; - int ret; - struct timeval to; - struct timeval then; - struct timeval now; - fd_set rd; - fd_set wr; #ifdef HAVE_MSGHDR_MSG_CONTROL char ans_data[4096]; #endif // HAVE_MSGHDR_MSG_CONTROL - struct msghdr hdr; - struct iovec iov; #ifdef SO_TIMESTAMP struct cmsghdr *chdr; #endif @@ -1271,18 +1243,24 @@ static int recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr * return 0; } + struct timeval to; to.tv_sec = *timo / 1000000; to.tv_usec = (*timo - (to.tv_sec * 1000000)); + fd_set rd; + fd_set wr; FD_ZERO(&rd); FD_ZERO(&wr); FD_SET(sock, &rd); errno = 0; + + struct timeval then; gettimeofday(&then, &tz); - n = select(sock + 1, &rd, &wr, NULL, &to); + int n = select(sock + 1, &rd, &wr, NULL, &to); if (n < 0) { crash("select() in recvfrom_wto"); } + struct timeval now; gettimeofday(&now, &tz); *timo = get_timevaldiff(&then, &now); @@ -1290,12 +1268,14 @@ static int recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr * return 0; /* timeout */ } - slen = sizeof(struct sockaddr_storage); + u_int slen = sizeof(struct sockaddr_storage); + struct iovec iov; memset(&iov, 0, sizeof(iov)); iov.iov_base = buf; iov.iov_len = len; + struct msghdr hdr; memset(&hdr, 0, sizeof(hdr)); hdr.msg_name = saddr; hdr.msg_namelen = slen; @@ -1306,7 +1286,7 @@ static int recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr * hdr.msg_controllen = sizeof(ans_data); #endif - ret = recvmsg(sock, &hdr, 0); + int ret = recvmsg(sock, &hdr, 0); #ifdef SO_TIMESTAMP for (chdr = CMSG_FIRSTHDR(&hdr); chdr; chdr = CMSG_NXTHDR(&hdr, chdr)) { if (chdr->cmsg_level == SOL_SOCKET && chdr->cmsg_type == SO_TIMESTAMP && chdr->cmsg_len >= CMSG_LEN(sizeof(struct timeval))) { @@ -1322,16 +1302,6 @@ static int recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr * } static void finish(int sig) { - u_int i = 0; - unsigned char pl; - double rta; - struct rta_host *host; - const char *status_string[] = {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"}; - int hosts_ok = 0; - int hosts_warn = 0; - int this_status; - double R; - alarm(0); if (debug > 1) { printf("finish(%d) called\n", sig); @@ -1354,11 +1324,17 @@ static void finish(int sig) { /* iterate thrice to calculate values, give output, and print perfparse */ status = STATE_OK; - host = list; + struct rta_host *host = list; + u_int i = 0; + const char *status_string[] = {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"}; + int hosts_ok = 0; + int hosts_warn = 0; while (host) { - this_status = STATE_OK; + int this_status = STATE_OK; + unsigned char pl; + double rta; if (!host->icmp_recv) { /* rta 0 is ofcourse not entirely correct, but will still show up * conspicuously as missing entries in perfparse and cacti */ @@ -1398,6 +1374,7 @@ static void finish(int sig) { */ host->EffectiveLatency = (rta / 1000) + host->jitter * 2 + 10; + double R; if (host->EffectiveLatency < 160) { R = 93.2 - (host->EffectiveLatency / 40); } else { @@ -1687,7 +1664,6 @@ static void finish(int sig) { } static u_int get_timevaldiff(struct timeval *early, struct timeval *later) { - u_int ret; struct timeval now; if (!later) { @@ -1702,19 +1678,15 @@ static u_int get_timevaldiff(struct timeval *early, struct timeval *later) { if (early->tv_sec > later->tv_sec || (early->tv_sec == later->tv_sec && early->tv_usec > later->tv_usec)) { return 0; } - ret = (later->tv_sec - early->tv_sec) * 1000000; + u_int ret = (later->tv_sec - early->tv_sec) * 1000000; ret += later->tv_usec - early->tv_usec; return ret; } static int add_target_ip(char *arg, struct sockaddr_storage *in) { - struct rta_host *host; struct sockaddr_in *sin; - struct sockaddr_in *host_sin; struct sockaddr_in6 *sin6; - struct sockaddr_in6 *host_sin6; - if (address_family == AF_INET) { sin = (struct sockaddr_in *)in; } else { @@ -1729,7 +1701,9 @@ static int add_target_ip(char *arg, struct sockaddr_storage *in) { } /* no point in adding two identical IP's, so don't. ;) */ - host = list; + struct sockaddr_in *host_sin; + struct sockaddr_in6 *host_sin6; + struct rta_host *host = list; while (host) { host_sin = (struct sockaddr_in *)&host->saddr_in; host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; @@ -1797,14 +1771,10 @@ static int add_target_ip(char *arg, struct sockaddr_storage *in) { /* wrapper for add_target_ip */ static int add_target(char *arg) { - int error; - int result = -1; struct sockaddr_storage ip; - struct addrinfo hints; - struct addrinfo *res; - struct addrinfo *p; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; + int result = -1; switch (address_family) { case -1: @@ -1841,6 +1811,8 @@ static int add_target(char *arg) { /* don't add all ip's if we were given a specific one */ return add_target_ip(arg, &ip); } + + struct addrinfo hints; errno = 0; memset(&hints, 0, sizeof(hints)); if (address_family == -1) { @@ -1849,6 +1821,9 @@ static int add_target(char *arg) { hints.ai_family = address_family == AF_INET ? PF_INET : PF_INET6; } hints.ai_socktype = SOCK_RAW; + + int error; + struct addrinfo *res; if ((error = getaddrinfo(arg, NULL, &hints, &res)) != 0) { errno = 0; crash("Failed to resolve %s: %s", arg, gai_strerror(error)); @@ -1857,7 +1832,7 @@ static int add_target(char *arg) { address_family = res->ai_family; /* possibly add all the IP's as targets */ - for (p = res; p != NULL; p = p->ai_next) { + for (struct addrinfo *p = res; p != NULL; p = p->ai_next) { memcpy(&ip, p->ai_addr, p->ai_addrlen); add_target_ip(arg, &ip); @@ -1920,26 +1895,19 @@ static in_addr_t get_ip_address(const char *ifname) { * return value is in microseconds */ static u_int get_timevar(const char *str) { - char p; - char u; - char *ptr; - size_t len; - u_int i; - u_int d; /* integer and decimal, respectively */ - u_int factor = 1000; /* default to milliseconds */ - if (!str) { return 0; } - len = strlen(str); + + size_t len = strlen(str); if (!len) { return 0; } /* unit might be given as ms|m (millisec), * us|u (microsec) or just plain s, for seconds */ - p = '\0'; - u = str[len - 1]; + char p = '\0'; + char u = str[len - 1]; if (len >= 2 && !isdigit((int)str[len - 2])) { p = str[len - 2]; } @@ -1952,6 +1920,7 @@ static u_int get_timevar(const char *str) { printf("evaluating %s, u: %c, p: %c\n", str, u, p); } + u_int factor = 1000; /* default to milliseconds */ if (u == 'u') { factor = 1; /* microseconds */ } else if (u == 'm') { @@ -1963,6 +1932,8 @@ static u_int get_timevar(const char *str) { printf("factor is %u\n", factor); } + char *ptr; + u_int i; i = strtoul(str, &ptr, 0); if (!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1) { return i * factor; @@ -1973,7 +1944,8 @@ static u_int get_timevar(const char *str) { return i; } - d = strtoul(ptr + 1, NULL, 0); + /* integer and decimal, respectively */ + u_int d = strtoul(ptr + 1, NULL, 0); /* d is decimal, so get rid of excess digits */ while (d >= factor) { @@ -1986,15 +1958,13 @@ static u_int get_timevar(const char *str) { /* not too good at checking errors, but it'll do (main() should barfe on -1) */ static int get_threshold(char *str, threshold *th) { - char *p = NULL; - char i = 0; - if (!str || !strlen(str) || !th) { return -1; } /* pointer magic slims code by 10 lines. i is bof-stop on stupid libc's */ - p = &str[strlen(str) - 1]; + char i = 0; + char *p = &str[strlen(str) - 1]; while (p != &str[1]) { if (*p == '%') { *p = '\0'; @@ -2098,7 +2068,6 @@ static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, thre } unsigned short icmp_checksum(uint16_t *p, size_t n) { - unsigned short cksum; long sum = 0; /* sizeof(uint16_t) == 2 */ @@ -2114,7 +2083,8 @@ unsigned short icmp_checksum(uint16_t *p, size_t n) { sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ - cksum = ~sum; /* ones-complement, trunc to 16 bits */ + unsigned short cksum; + cksum = ~sum; /* ones-complement, trunc to 16 bits */ return cksum; } -- cgit v1.2.3-74-g34f1 From eafee9c3f91879afa82749fa1d8cd2b0b53a5d5c Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 28 Apr 2025 22:01:01 +0200 Subject: WIP: check_icmp refactor --- plugins-root/Makefile.am | 4 +- plugins-root/check_icmp.c | 1287 ++++++++++++------------ plugins-root/check_icmp.d/check_icmp_helpers.c | 142 +++ plugins-root/check_icmp.d/check_icmp_helpers.h | 73 ++ 4 files changed, 877 insertions(+), 629 deletions(-) create mode 100644 plugins-root/check_icmp.d/check_icmp_helpers.c create mode 100644 plugins-root/check_icmp.d/check_icmp_helpers.h (limited to 'plugins-root') diff --git a/plugins-root/Makefile.am b/plugins-root/Makefile.am index a80229e2..f09f5e07 100644 --- a/plugins-root/Makefile.am +++ b/plugins-root/Makefile.am @@ -24,7 +24,8 @@ noinst_PROGRAMS = check_dhcp check_icmp @EXTRAS_ROOT@ EXTRA_PROGRAMS = pst3 -EXTRA_DIST = t pst3.c +EXTRA_DIST = t pst3.c \ + check_icmp.d BASEOBJS = ../plugins/utils.o ../lib/libmonitoringplug.a ../gl/libgnu.a NETOBJS = ../plugins/netutils.o $(BASEOBJS) $(EXTRA_NETOBJS) @@ -82,6 +83,7 @@ install-exec-local: $(noinst_PROGRAMS) # the actual targets check_dhcp_LDADD = @LTLIBINTL@ $(NETLIBS) $(LIB_CRYPTO) check_icmp_LDADD = @LTLIBINTL@ $(NETLIBS) $(SOCKETLIBS) $(LIB_CRYPTO) +check_icmp_SOURCES = check_icmp.c check_icmp.d/check_icmp_helpers.c # -m64 needed at compiler and linker phase pst3_CFLAGS = @PST3CFLAGS@ diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 061e7d82..87dac21d 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -67,6 +67,10 @@ const char *email = "devel@monitoring-plugins.org"; #include #include +#include "../lib/states.h" +#include "./check_icmp.d/config.h" +#include "./check_icmp.d/check_icmp_helpers.h" + /** sometimes undefined system macros (quite a few, actually) **/ #ifndef MAXTTL # define MAXTTL 255 @@ -97,56 +101,8 @@ const char *email = "devel@monitoring-plugins.org"; # define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 #endif -typedef unsigned short range_t; /* type for get_range() -- unimplemented */ - -typedef struct rta_host { - unsigned short id; /* id in **table, and icmp pkts */ - char *name; /* arg used for adding this host */ - char *msg; /* icmp error message, if any */ - struct sockaddr_storage saddr_in; /* the address of this host */ - struct sockaddr_storage error_addr; /* stores address of error replies */ - unsigned long long time_waited; /* total time waited, in usecs */ - unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */ - unsigned char icmp_type, icmp_code; /* type and code from errors */ - unsigned short flags; /* control/status flags */ - double rta; /* measured RTA */ - int rta_status; // check result for RTA checks - double rtmax; /* max rtt */ - double rtmin; /* min rtt */ - double jitter; /* measured jitter */ - int jitter_status; // check result for Jitter checks - double jitter_max; /* jitter rtt maximum */ - double jitter_min; /* jitter rtt minimum */ - double EffectiveLatency; - double mos; /* Mean opnion score */ - int mos_status; // check result for MOS checks - double score; /* score */ - int score_status; // check result for score checks - u_int last_tdiff; - u_int last_icmp_seq; /* Last ICMP_SEQ to check out of order pkts */ - unsigned char pl; /* measured packet loss */ - int pl_status; // check result for packet loss checks - struct rta_host *next; /* linked list */ - int order_status; // check result for packet order checks -} rta_host; - #define FLAG_LOST_CAUSE 0x01 /* decidedly dead target. */ -/* threshold structure. all values are maximum allowed, exclusive */ -typedef struct threshold { - unsigned char pl; /* max allowed packet loss in percent */ - unsigned int rta; /* roundtrip time average, microseconds */ - double jitter; /* jitter time average, microseconds */ - double mos; /* MOS */ - double score; /* Score */ -} threshold; - -/* the data structure */ -typedef struct icmp_ping_data { - struct timeval stime; /* timestamp (saved in protocol struct as well) */ - unsigned short ping_id; -} icmp_ping_data; - typedef union ip_hdr { struct ip ip; struct ip6_hdr ip6; @@ -159,24 +115,6 @@ typedef union icmp_packet { u_short *cksum_in; } icmp_packet; -/* the different modes of this program are as follows: - * MODE_RTA: send all packets no matter what (mimic check_icmp and check_ping) - * MODE_HOSTCHECK: Return immediately upon any sign of life - * In addition, sends packets to ALL addresses assigned - * to this host (as returned by gethostbyname() or - * gethostbyaddr() and expects one host only to be checked at - * a time. Therefore, any packet response what so ever will - * count as a sign of life, even when received outside - * crit.rta limit. Do not misspell any additional IP's. - * MODE_ALL: Requires packets from ALL requested IP to return OK (default). - * MODE_ICMP: implement something similar to check_icmp (MODE_RTA without - * tcp and udp args does this) - */ -#define MODE_RTA 0 -#define MODE_HOSTCHECK 1 -#define MODE_ALL 2 -#define MODE_ICMP 3 - enum enum_threshold_mode { const_rta_mode, const_packet_loss_mode, @@ -187,78 +125,325 @@ enum enum_threshold_mode { typedef enum enum_threshold_mode threshold_mode; -/* the different ping types we can do - * TODO: investigate ARP ping as well */ -#define HAVE_ICMP 1 -#define HAVE_UDP 2 -#define HAVE_TCP 4 -#define HAVE_ARP 8 - -#define MIN_PING_DATA_SIZE sizeof(struct icmp_ping_data) -#define MAX_IP_PKT_SIZE 65536 /* (theoretical) max IP packet size */ -#define IP_HDR_SIZE 20 -#define MAX_PING_DATA (MAX_IP_PKT_SIZE - IP_HDR_SIZE - ICMP_MINLEN) -#define DEFAULT_PING_DATA_SIZE (MIN_PING_DATA_SIZE + 44) - -/* various target states */ -#define TSTATE_INACTIVE 0x01 /* don't ping this host anymore */ -#define TSTATE_WAITING 0x02 /* unanswered packets on the wire */ -#define TSTATE_ALIVE 0x04 /* target is alive (has answered something) */ -#define TSTATE_UNREACH 0x08 - /** prototypes **/ -void print_help(void); +void print_help(); void print_usage(void); -static u_int get_timevar(const char * /*str*/); -static u_int get_timevaldiff(struct timeval * /*early*/, struct timeval * /*later*/); + +/* Time related */ +static unsigned int get_timevar(const char * /*str*/); +static time_t get_timevaldiff(struct timeval * /*early*/, struct timeval * /*later*/, + struct timeval *prog_start); + static in_addr_t get_ip_address(const char * /*ifname*/); -static int wait_for_reply(int /*sock*/, u_int /*t*/); -static int recvfrom_wto(int /*sock*/, void * /*buf*/, unsigned int /*len*/, struct sockaddr * /*saddr*/, u_int * /*timo*/, - struct timeval * /*tv*/); -static int send_icmp_ping(int /*sock*/, struct rta_host * /*host*/); +static void set_source_ip(char * /*arg*/, const int icmp_sock); + +/* Receiving data */ +static int wait_for_reply(int /*sock*/, unsigned int /*t*/, bool order_mode, bool mos_mode, + bool rta_mode, bool pl_mode, bool jitter_mode, bool score_mode, + int min_hosts_alive, unsigned short icmp_pkt_size, + unsigned int *pkt_interval, unsigned int *target_interval, threshold warn, + threshold crit, pid_t pid, int mode, + unsigned long long max_completion_time, struct timeval *prog_start, + struct rta_host **table, const unsigned short packets, + const int icmp_sock, const unsigned short number_of_targets, + check_icmp_state *program_state); + +static int recvfrom_wto(int /*sock*/, void * /*buf*/, unsigned int /*len*/, + struct sockaddr * /*saddr*/, unsigned int * /*timo*/, + struct timeval * /*tv*/, struct timeval *prog_start); +static int handle_random_icmp(unsigned char * /*packet*/, struct sockaddr_storage * /*addr*/, + unsigned int *pkt_interval, unsigned int *target_interval, pid_t pid, + struct rta_host **table, unsigned short packets, + const unsigned short number_of_targets, + check_icmp_state *program_state); + +/* Sending data */ +static int send_icmp_ping(int /*sock*/, struct rta_host * /*host*/, unsigned short icmp_pkt_size, + pid_t pid, check_icmp_state *program_state); + +/* Threshold related */ static int get_threshold(char *str, threshold *th); -static bool get_threshold2(char *str, size_t length, threshold * /*warn*/, threshold * /*crit*/, threshold_mode mode); +static bool get_threshold2(char *str, size_t length, threshold * /*warn*/, threshold * /*crit*/, + threshold_mode mode); static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, threshold_mode mode); -static void run_checks(void); -static void set_source_ip(char * /*arg*/); -static int add_target(char * /*arg*/); + +/* main test function */ +static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, + bool jitter_mode, bool score_mode, int min_hosts_alive, + unsigned short icmp_pkt_size, unsigned int *pkt_interval, + unsigned int *target_interval, threshold warn, threshold crit, pid_t pid, + int mode, unsigned int max_completion_time, const struct timeval *prog_start, + struct rta_host **table, const unsigned short packets, const int icmp_sock, + const unsigned short number_of_targets, check_icmp_state *program_state); + +/* Target aquisition */ +static int add_target(char * /*arg*/, int mode); static int add_target_ip(char * /*arg*/, struct sockaddr_storage * /*in*/); -static int handle_random_icmp(unsigned char * /*packet*/, struct sockaddr_storage * /*addr*/); + static void parse_address(struct sockaddr_storage * /*addr*/, char * /*address*/, int /*size*/); + static unsigned short icmp_checksum(uint16_t * /*p*/, size_t /*n*/); -static void finish(int /*sig*/); + +/* End of run function */ +static void finish(int /*sig*/, bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, + bool jitter_mode, bool score_mode, int min_hosts_alive, threshold warn, + threshold crit, const int icmp_sock, const unsigned short number_of_targets, + check_icmp_state *program_state); + +/* Error exit */ static void crash(const char * /*fmt*/, ...); /** global variables **/ -static struct rta_host **table, *cursor, *list; - -static threshold crit = {.pl = 80, .rta = 500000, .jitter = 0.0, .mos = 0.0, .score = 0.0}; -static threshold warn = {.pl = 40, .rta = 200000, .jitter = 0.0, .mos = 0.0, .score = 0.0}; - -static int mode, protocols, sockets, debug = 0, timeout = 10; -static unsigned short icmp_data_size = DEFAULT_PING_DATA_SIZE; -static unsigned short icmp_pkt_size = DEFAULT_PING_DATA_SIZE + ICMP_MINLEN; - -static unsigned int icmp_sent = 0, icmp_recv = 0, icmp_lost = 0, ttl = 0; -#define icmp_pkts_en_route (icmp_sent - (icmp_recv + icmp_lost)) -static unsigned short targets_down = 0, targets = 0, packets = 0; -#define targets_alive (targets - targets_down) -static unsigned int retry_interval, pkt_interval, target_interval; -static int icmp_sock, tcp_sock, udp_sock, status = STATE_OK; -static pid_t pid; -static struct timezone tz; -static struct timeval prog_start; -static unsigned long long max_completion_time = 0; -static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values */ -static int min_hosts_alive = -1; -static float pkt_backoff_factor = 1.5; -static float target_backoff_factor = 1.5; -static bool rta_mode = false; -static bool pl_mode = false; -static bool jitter_mode = false; -static bool score_mode = false; -static bool mos_mode = false; -static bool order_mode = false; +static struct rta_host *cursor = NULL; +static struct rta_host *host_list = NULL; + +static int debug = 0; + +/** the working code **/ + +static inline unsigned short targets_alive(unsigned short targets, unsigned short targets_down) { + return targets - targets_down; +} +static inline unsigned int icmp_pkts_en_route(unsigned int icmp_sent, unsigned int icmp_recv, + unsigned int icmp_lost) { + return icmp_sent - (icmp_recv + icmp_lost); +} + +// Create configuration from cli parameters +typedef struct { + int errorcode; + check_icmp_config config; +} check_icmp_config_wrapper; +check_icmp_config_wrapper process_arguments(int argc, char **argv); + +check_icmp_config_wrapper process_arguments(int argc, char **argv) { + /* get calling name the old-fashioned way for portability instead + * of relying on the glibc-ism __progname */ + char *ptr = strrchr(argv[0], '/'); + if (ptr) { + progname = &ptr[1]; + } else { + progname = argv[0]; + } + + check_icmp_config_wrapper result = { + .errorcode = OK, + .config = check_icmp_config_init(), + }; + + /* use the pid to mark packets as ours */ + /* Some systems have 32-bit pid_t so mask off only 16 bits */ + result.config.pid = getpid() & 0xffff; + + if (!strcmp(progname, "check_icmp") || !strcmp(progname, "check_ping")) { + result.config.mode = MODE_ICMP; + } else if (!strcmp(progname, "check_host")) { + result.config.mode = MODE_HOSTCHECK; + result.config.pkt_interval = 1000000; + result.config.packets = 5; + result.config.crit.rta = result.config.warn.rta = 1000000; + result.config.crit.pl = result.config.warn.pl = 100; + } else if (!strcmp(progname, "check_rta_multi")) { + result.config.mode = MODE_ALL; + result.config.target_interval = 0; + result.config.pkt_interval = 50000; + result.config.packets = 5; + } + /* support "--help" and "--version" */ + if (argc == 2) { + if (!strcmp(argv[1], "--help")) { + strcpy(argv[1], "-h"); + } + if (!strcmp(argv[1], "--version")) { + strcpy(argv[1], "-V"); + } + } + + /* Parse protocol arguments first */ + char *opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64"; + for (int i = 1; i < argc; i++) { + long int arg; + while ((arg = getopt(argc, argv, opts_str)) != EOF) { + switch (arg) { + case '4': + if (address_family != -1) { + crash("Multiple protocol versions not supported"); + } + address_family = AF_INET; + break; + case '6': +#ifdef USE_IPV6 + if (address_family != -1) { + crash("Multiple protocol versions not supported"); + } + address_family = AF_INET6; +#else + usage(_("IPv6 support not available\n")); +#endif + break; + } + } + } + + /* Reset argument scanning */ + optind = 1; + + bool err; + /* parse the arguments */ + for (int i = 1; i < argc; i++) { + long int arg; + while ((arg = getopt(argc, argv, opts_str)) != EOF) { + switch (arg) { + case 'v': + debug++; + break; + case 'b': { + long size = strtol(optarg, NULL, 0); + if ((unsigned long)size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && + size < MAX_PING_DATA) { + result.config.icmp_data_size = size; + result.config.icmp_pkt_size = size + ICMP_MINLEN; + } else { + usage_va("ICMP data length must be between: %lu and %lu", + sizeof(struct icmp) + sizeof(struct icmp_ping_data), + MAX_PING_DATA - 1); + } + } break; + case 'i': + result.config.pkt_interval = get_timevar(optarg); + break; + case 'I': + result.config.target_interval = get_timevar(optarg); + break; + case 'w': + get_threshold(optarg, &result.config.warn); + break; + case 'c': + get_threshold(optarg, &result.config.crit); + break; + case 'n': + case 'p': + result.config.packets = strtoul(optarg, NULL, 0); + if (result.config.packets > 20) { + errno = 0; + crash("packets is > 20 (%d)", result.config.packets); + } + break; + case 't': + result.config.timeout = strtoul(optarg, NULL, 0); + // TODO die here and complain about wrong input + // instead of: + if (!result.config.timeout) { + result.config.timeout = 10; + } + break; + case 'H': { + int add_result = add_target(optarg, result.config.mode); + if (add_result == 0) { + result.config.number_of_targets++; + } + } break; + case 'l': + result.config.ttl = strtoul(optarg, NULL, 0); + break; + case 'm': + result.config.min_hosts_alive = (int)strtoul(optarg, NULL, 0); + break; + case 's': /* specify source IP address */ + result.config.source_ip = optarg; + break; + case 'V': /* version */ + print_revision(progname, NP_VERSION); + exit(STATE_UNKNOWN); + case 'h': /* help */ + print_help(); + exit(STATE_UNKNOWN); + break; + case 'R': /* RTA mode */ + err = get_threshold2(optarg, strlen(optarg), &result.config.warn, + &result.config.crit, const_rta_mode); + if (!err) { + crash("Failed to parse RTA threshold"); + } + + result.config.rta_mode = true; + break; + case 'P': /* packet loss mode */ + err = get_threshold2(optarg, strlen(optarg), &result.config.warn, + &result.config.crit, const_packet_loss_mode); + if (!err) { + crash("Failed to parse packet loss threshold"); + } + + result.config.pl_mode = true; + break; + case 'J': /* jitter mode */ + err = get_threshold2(optarg, strlen(optarg), &result.config.warn, + &result.config.crit, const_jitter_mode); + if (!err) { + crash("Failed to parse jitter threshold"); + } + + result.config.jitter_mode = true; + break; + case 'M': /* MOS mode */ + err = get_threshold2(optarg, strlen(optarg), &result.config.warn, + &result.config.crit, const_mos_mode); + if (!err) { + crash("Failed to parse MOS threshold"); + } + + result.config.mos_mode = true; + break; + case 'S': /* score mode */ + err = get_threshold2(optarg, strlen(optarg), &result.config.warn, + &result.config.crit, const_score_mode); + if (!err) { + crash("Failed to parse score threshold"); + } + + result.config.score_mode = true; + break; + case 'O': /* out of order mode */ + result.config.order_mode = true; + break; + } + } + } + + argv = &argv[optind]; + while (*argv) { + add_target(*argv, result.config.mode); + argv++; + } + + if (!result.config.number_of_targets) { + errno = 0; + crash("No hosts to check"); + } + + /* stupid users should be able to give whatever thresholds they want + * (nothing will break if they do), but some anal plugin maintainer + * will probably add some printf() thing here later, so it might be + * best to at least show them where to do it. ;) */ + if (result.config.warn.pl > result.config.crit.pl) { + result.config.warn.pl = result.config.crit.pl; + } + if (result.config.warn.rta > result.config.crit.rta) { + result.config.warn.rta = result.config.crit.rta; + } + if (result.config.warn.jitter > result.config.crit.jitter) { + result.config.crit.jitter = result.config.warn.jitter; + } + if (result.config.warn.mos < result.config.crit.mos) { + result.config.warn.mos = result.config.crit.mos; + } + if (result.config.warn.score < result.config.crit.score) { + result.config.warn.score = result.config.crit.score; + } + + return result; +} /** code start **/ static void crash(const char *fmt, ...) { @@ -382,7 +567,11 @@ static const char *get_icmp_error_msg(unsigned char icmp_type, unsigned char icm return msg; } -static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr) { +static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr, + unsigned int *pkt_interval, unsigned int *target_interval, + const pid_t pid, struct rta_host **table, unsigned short packets, + const unsigned short number_of_targets, + check_icmp_state *program_state) { struct icmp p; memcpy(&p, packet, sizeof(p)); if (p.icmp_type == ICMP_ECHO && ntohs(p.icmp_id) == pid) { @@ -404,7 +593,8 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad * TIMXCEED actually sends a proper icmp response we will have passed * too many hops to have a hope of reaching it later, in which case it * indicates overconfidence in the network, poor routing or both. */ - if (p.icmp_type != ICMP_UNREACH && p.icmp_type != ICMP_TIMXCEED && p.icmp_type != ICMP_SOURCEQUENCH && p.icmp_type != ICMP_PARAMPROB) { + if (p.icmp_type != ICMP_UNREACH && p.icmp_type != ICMP_TIMXCEED && + p.icmp_type != ICMP_SOURCEQUENCH && p.icmp_type != ICMP_PARAMPROB) { return 0; } @@ -412,7 +602,8 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad * to RFC 792). If it isn't, just ignore it */ struct icmp sent_icmp; memcpy(&sent_icmp, packet + 28, sizeof(sent_icmp)); - if (sent_icmp.icmp_type != ICMP_ECHO || ntohs(sent_icmp.icmp_id) != pid || ntohs(sent_icmp.icmp_seq) >= targets * packets) { + if (sent_icmp.icmp_type != ICMP_ECHO || ntohs(sent_icmp.icmp_id) != pid || + ntohs(sent_icmp.icmp_seq) >= number_of_targets * packets) { if (debug) { printf("Packet is no response to a packet we sent\n"); } @@ -424,10 +615,11 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad if (debug) { char address[INET6_ADDRSTRLEN]; parse_address(addr, address, sizeof(address)); - printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n", get_icmp_error_msg(p.icmp_type, p.icmp_code), address, host->name); + printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n", + get_icmp_error_msg(p.icmp_type, p.icmp_code), address, host->name); } - icmp_lost++; + program_state->icmp_lost++; host->icmp_lost++; /* don't spend time on lost hosts any more */ if (host->flags & FLAG_LOST_CAUSE) { @@ -437,10 +629,10 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad /* source quench means we're sending too fast, so increase the * interval and mark this packet lost */ if (p.icmp_type == ICMP_SOURCEQUENCH) { - pkt_interval *= pkt_backoff_factor; - target_interval *= target_backoff_factor; + *pkt_interval *= PACKET_BACKOFF_FACTOR; + *target_interval *= TARGET_BACKOFF_FACTOR; } else { - targets_down++; + program_state->targets_down++; host->flags |= FLAG_LOST_CAUSE; } host->icmp_type = p.icmp_type; @@ -466,240 +658,23 @@ int main(int argc, char **argv) { bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - /* we only need to be setsuid when we get the sockets, so do - * that before pointer magic (esp. on network data) */ - int icmp_sockerrno; - int udp_sockerrno; - int tcp_sockerrno; - icmp_sockerrno = udp_sockerrno = tcp_sockerrno = sockets = 0; - address_family = -1; int icmp_proto = IPPROTO_ICMP; - /* get calling name the old-fashioned way for portability instead - * of relying on the glibc-ism __progname */ - char *ptr = strrchr(argv[0], '/'); - if (ptr) { - progname = &ptr[1]; - } else { - progname = argv[0]; - } - - /* now set defaults. Use progname to set them initially (allows for - * superfast check_host program when target host is up */ - cursor = list = NULL; - table = NULL; - - mode = MODE_RTA; - /* Default critical thresholds */ - crit.rta = 500000; - crit.pl = 80; - crit.jitter = 50; - crit.mos = 3; - crit.score = 70; - /* Default warning thresholds */ - warn.rta = 200000; - warn.pl = 40; - warn.jitter = 40; - warn.mos = 3.5; - warn.score = 80; - - protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP; - pkt_interval = 80000; /* 80 msec packet interval by default */ - packets = 5; - - if (!strcmp(progname, "check_icmp") || !strcmp(progname, "check_ping")) { - mode = MODE_ICMP; - protocols = HAVE_ICMP; - } else if (!strcmp(progname, "check_host")) { - mode = MODE_HOSTCHECK; - pkt_interval = 1000000; - packets = 5; - crit.rta = warn.rta = 1000000; - crit.pl = warn.pl = 100; - } else if (!strcmp(progname, "check_rta_multi")) { - mode = MODE_ALL; - target_interval = 0; - pkt_interval = 50000; - packets = 5; - } - - /* support "--help" and "--version" */ - if (argc == 2) { - if (!strcmp(argv[1], "--help")) { - strcpy(argv[1], "-h"); - } - if (!strcmp(argv[1], "--version")) { - strcpy(argv[1], "-V"); - } - } - - /* Parse protocol arguments first */ - char *opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64"; - for (int i = 1; i < argc; i++) { - long int arg; - while ((arg = getopt(argc, argv, opts_str)) != EOF) { - switch (arg) { - case '4': - if (address_family != -1) { - crash("Multiple protocol versions not supported"); - } - address_family = AF_INET; - break; - case '6': -#ifdef USE_IPV6 - if (address_family != -1) { - crash("Multiple protocol versions not supported"); - } - address_family = AF_INET6; -#else - usage(_("IPv6 support not available\n")); -#endif - break; - } - } - } - - /* Reset argument scanning */ - optind = 1; - - unsigned long size; - bool err; - /* parse the arguments */ - char *source_ip = NULL; - for (int i = 1; i < argc; i++) { - long int arg; - while ((arg = getopt(argc, argv, opts_str)) != EOF) { - switch (arg) { - case 'v': - debug++; - break; - case 'b': - size = strtol(optarg, NULL, 0); - if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && size < MAX_PING_DATA) { - icmp_data_size = size; - icmp_pkt_size = size + ICMP_MINLEN; - } else { - usage_va("ICMP data length must be between: %lu and %lu", sizeof(struct icmp) + sizeof(struct icmp_ping_data), - MAX_PING_DATA - 1); - } - break; - case 'i': - pkt_interval = get_timevar(optarg); - break; - case 'I': - target_interval = get_timevar(optarg); - break; - case 'w': - get_threshold(optarg, &warn); - break; - case 'c': - get_threshold(optarg, &crit); - break; - case 'n': - case 'p': - packets = strtoul(optarg, NULL, 0); - break; - case 't': - timeout = strtoul(optarg, NULL, 0); - if (!timeout) { - timeout = 10; - } - break; - case 'H': - add_target(optarg); - break; - case 'l': - ttl = (int)strtoul(optarg, NULL, 0); - break; - case 'm': - min_hosts_alive = (int)strtoul(optarg, NULL, 0); - break; - case 'd': /* implement later, for cluster checks */ - warn_down = (unsigned char)strtoul(optarg, &ptr, 0); - if (ptr) { - crit_down = (unsigned char)strtoul(ptr + 1, NULL, 0); - } - break; - case 's': /* specify source IP address */ - source_ip = optarg; - break; - case 'V': /* version */ - print_revision(progname, NP_VERSION); - exit(STATE_UNKNOWN); - case 'h': /* help */ - print_help(); - exit(STATE_UNKNOWN); - break; - case 'R': /* RTA mode */ - err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_rta_mode); - if (!err) { - crash("Failed to parse RTA threshold"); - } - - rta_mode = true; - break; - case 'P': /* packet loss mode */ - err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_packet_loss_mode); - if (!err) { - crash("Failed to parse packet loss threshold"); - } - - pl_mode = true; - break; - case 'J': /* jitter mode */ - err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_jitter_mode); - if (!err) { - crash("Failed to parse jitter threshold"); - } - - jitter_mode = true; - break; - case 'M': /* MOS mode */ - err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_mos_mode); - if (!err) { - crash("Failed to parse MOS threshold"); - } - - mos_mode = true; - break; - case 'S': /* score mode */ - err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_score_mode); - if (!err) { - crash("Failed to parse score threshold"); - } - - score_mode = true; - break; - case 'O': /* out of order mode */ - order_mode = true; - break; - } - } - } - /* POSIXLY_CORRECT might break things, so unset it (the portable way) */ environ = NULL; - /* use the pid to mark packets as ours */ - /* Some systems have 32-bit pid_t so mask off only 16 bits */ - pid = getpid() & 0xffff; - /* printf("pid = %u\n", pid); */ - /* Parse extra opts if any */ argv = np_extra_opts(&argc, argv, progname); - argv = &argv[optind]; - while (*argv) { - add_target(*argv); - argv++; - } + check_icmp_config_wrapper tmp_config = process_arguments(argc, argv); - if (!targets) { - errno = 0; - crash("No hosts to check"); + if (tmp_config.errorcode != OK) { + crash("failed to parse config"); } + const check_icmp_config config = tmp_config.config; + // add_target might change address_family switch (address_family) { case AF_INET: @@ -711,14 +686,14 @@ int main(int argc, char **argv) { default: crash("Address family not supported"); } - if ((icmp_sock = socket(address_family, SOCK_RAW, icmp_proto)) != -1) { - sockets |= HAVE_ICMP; - } else { - icmp_sockerrno = errno; + + int icmp_sock = socket(address_family, SOCK_RAW, icmp_proto); + if (icmp_sock == -1) { + crash("Failed to obtain ICMP socket"); } - if (source_ip) { - set_source_ip(source_ip); + if (config.source_ip) { + set_source_ip(config.source_ip, icmp_sock); } #ifdef SO_TIMESTAMP @@ -736,184 +711,179 @@ int main(int argc, char **argv) { return 1; } - if (!sockets) { - if (icmp_sock == -1) { - errno = icmp_sockerrno; - crash("Failed to obtain ICMP socket"); - return -1; - } - /* if(udp_sock == -1) { */ - /* errno = icmp_sockerrno; */ - /* crash("Failed to obtain UDP socket"); */ - /* return -1; */ - /* } */ - /* if(tcp_sock == -1) { */ - /* errno = icmp_sockerrno; */ - /* crash("Failed to obtain TCP socker"); */ - /* return -1; */ - /* } */ - } - if (!ttl) { - ttl = 64; - } - if (icmp_sock) { - int result = setsockopt(icmp_sock, SOL_IP, IP_TTL, &ttl, sizeof(ttl)); + int result = setsockopt(icmp_sock, SOL_IP, IP_TTL, &config.ttl, sizeof(config.ttl)); if (debug) { if (result == -1) { printf("setsockopt failed\n"); } else { - printf("ttl set to %u\n", ttl); + printf("ttl set to %lu\n", config.ttl); } } } - /* stupid users should be able to give whatever thresholds they want - * (nothing will break if they do), but some anal plugin maintainer - * will probably add some printf() thing here later, so it might be - * best to at least show them where to do it. ;) */ - if (warn.pl > crit.pl) { - warn.pl = crit.pl; - } - if (warn.rta > crit.rta) { - warn.rta = crit.rta; - } - if (warn_down > crit_down) { - crit_down = warn_down; - } - if (warn.jitter > crit.jitter) { - crit.jitter = warn.jitter; - } - if (warn.mos < crit.mos) { - warn.mos = crit.mos; - } - if (warn.score < crit.score) { - warn.score = crit.score; - } - #ifdef HAVE_SIGACTION struct sigaction sig_action; sig_action.sa_sigaction = NULL; sig_action.sa_handler = finish; sigfillset(&sig_action.sa_mask); sig_action.sa_flags = SA_NODEFER | SA_RESTART; + sigaction(SIGINT, &sig_action, NULL); sigaction(SIGHUP, &sig_action, NULL); sigaction(SIGTERM, &sig_action, NULL); sigaction(SIGALRM, &sig_action, NULL); #else /* HAVE_SIGACTION */ - signal(SIGINT, finish); - signal(SIGHUP, finish); - signal(SIGTERM, finish); - signal(SIGALRM, finish); + // signal(SIGINT, finish); + // signal(SIGHUP, finish); + // signal(SIGTERM, finish); + // signal(SIGALRM, finish); #endif /* HAVE_SIGACTION */ if (debug) { - printf("Setting alarm timeout to %u seconds\n", timeout); + printf("Setting alarm timeout to %u seconds\n", config.timeout); } - alarm(timeout); + alarm(config.timeout); /* make sure we don't wait any longer than necessary */ - gettimeofday(&prog_start, &tz); - max_completion_time = ((targets * packets * pkt_interval) + (targets * target_interval)) + (targets * packets * crit.rta) + crit.rta; + struct timezone time_zone_dummy; + struct timeval prog_start; + gettimeofday(&prog_start, &time_zone_dummy); + + unsigned int max_completion_time = + ((config.number_of_targets * config.packets * config.pkt_interval) + + (config.number_of_targets * config.target_interval)) + + (config.number_of_targets * config.packets * config.crit.rta) + config.crit.rta; if (debug) { printf("packets: %u, targets: %u\n" "target_interval: %0.3f, pkt_interval %0.3f\n" "crit.rta: %0.3f\n" "max_completion_time: %0.3f\n", - packets, targets, (float)target_interval / 1000, (float)pkt_interval / 1000, (float)crit.rta / 1000, + config.packets, config.number_of_targets, (float)config.target_interval / 1000, + (float)config.pkt_interval / 1000, (float)config.crit.rta / 1000, (float)max_completion_time / 1000); } if (debug) { - if (max_completion_time > (u_int)timeout * 1000000) { - printf("max_completion_time: %llu timeout: %u\n", max_completion_time, timeout); - printf("Timeout must be at least %llu\n", max_completion_time / 1000000 + 1); + if (max_completion_time > (unsigned int)config.timeout * 1000000) { + printf("max_completion_time: %u timeout: %u\n", max_completion_time, config.timeout); + printf("Timeout must be at least %u\n", (max_completion_time / 1000000) + 1); } } if (debug) { - printf("crit = {%u, %u%%}, warn = {%u, %u%%}\n", crit.rta, crit.pl, warn.rta, warn.pl); - printf("pkt_interval: %u target_interval: %u retry_interval: %u\n", pkt_interval, target_interval, retry_interval); - printf("icmp_pkt_size: %u timeout: %u\n", icmp_pkt_size, timeout); + printf("crit = {%u, %u%%}, warn = {%u, %u%%}\n", config.crit.rta, config.crit.pl, + config.warn.rta, config.warn.pl); + printf("pkt_interval: %u target_interval: %u\n", config.pkt_interval, + config.target_interval); + printf("icmp_pkt_size: %u timeout: %u\n", config.icmp_pkt_size, config.timeout); } - if (packets > 20) { + if (config.min_hosts_alive < -1) { errno = 0; - crash("packets is > 20 (%d)", packets); + crash("minimum alive hosts is negative (%i)", config.min_hosts_alive); } - if (min_hosts_alive < -1) { - errno = 0; - crash("minimum alive hosts is negative (%i)", min_hosts_alive); - } - - struct rta_host *host = list; - table = malloc(sizeof(struct rta_host *) * targets); + struct rta_host *host = host_list; + struct rta_host **table = malloc(sizeof(struct rta_host *) * config.number_of_targets); if (!table) { crash("main(): malloc failed for host table"); } - int i = 0; + unsigned short i = 0; while (host) { - host->id = i * packets; + host->id = i * config.packets; table[i] = host; host = host->next; i++; } - run_checks(); + unsigned int pkt_interval = config.pkt_interval; + unsigned int target_interval = config.target_interval; + + check_icmp_state program_state = check_icmp_state_init(); + + run_checks(config.order_mode, config.mos_mode, config.rta_mode, config.pl_mode, + config.jitter_mode, config.score_mode, config.min_hosts_alive, config.icmp_data_size, + &pkt_interval, &target_interval, config.warn, config.crit, config.pid, config.mode, + max_completion_time, &prog_start, table, config.packets, icmp_sock, + config.number_of_targets, &program_state); errno = 0; - finish(0); + finish(0, config.order_mode, config.mos_mode, config.rta_mode, config.pl_mode, + config.jitter_mode, config.score_mode, config.min_hosts_alive, config.warn, config.crit, + icmp_sock, config.number_of_targets, &program_state); return (0); } -static void run_checks(void) { +static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, + bool jitter_mode, bool score_mode, int min_hosts_alive, + unsigned short icmp_pkt_size, unsigned int *pkt_interval, + unsigned int *target_interval, threshold warn, threshold crit, + const pid_t pid, const int mode, const unsigned int max_completion_time, + const struct timeval *prog_start, struct rta_host **table, + const unsigned short packets, const int icmp_sock, + const unsigned short number_of_targets, check_icmp_state *program_state) { /* this loop might actually violate the pkt_interval or target_interval * settings, but only if there aren't any packets on the wire which * indicates that the target can handle an increased packet rate */ - for (u_int i = 0; i < packets; i++) { - for (u_int t = 0; t < targets; t++) { + for (unsigned int packet_index = 0; packet_index < packets; packet_index++) { + for (unsigned int target_index = 0; target_index < number_of_targets; target_index++) { /* don't send useless packets */ - if (!targets_alive) { - finish(0); + if (!targets_alive(number_of_targets, program_state->targets_down)) { + finish(0, order_mode, mos_mode, rta_mode, pl_mode, jitter_mode, score_mode, + min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state); } - if (table[t]->flags & FLAG_LOST_CAUSE) { + if (table[target_index]->flags & FLAG_LOST_CAUSE) { if (debug) { - printf("%s is a lost cause. not sending any more\n", table[t]->name); + printf("%s is a lost cause. not sending any more\n", table[target_index]->name); } continue; } /* we're still in the game, so send next packet */ - (void)send_icmp_ping(icmp_sock, table[t]); - wait_for_reply(icmp_sock, target_interval); + (void)send_icmp_ping(icmp_sock, table[target_index], icmp_pkt_size, pid, program_state); + + wait_for_reply(icmp_sock, *target_interval, order_mode, mos_mode, rta_mode, pl_mode, + jitter_mode, score_mode, min_hosts_alive, icmp_pkt_size, pkt_interval, + target_interval, warn, crit, pid, mode, max_completion_time, prog_start, + table, packets, icmp_sock, number_of_targets, program_state); } - wait_for_reply(icmp_sock, pkt_interval * targets); + wait_for_reply(icmp_sock, *pkt_interval * number_of_targets, order_mode, mos_mode, rta_mode, + pl_mode, jitter_mode, score_mode, min_hosts_alive, icmp_pkt_size, + pkt_interval, target_interval, warn, crit, pid, mode, max_completion_time, + prog_start, table, packets, icmp_sock, number_of_targets, program_state); } - if (icmp_pkts_en_route && targets_alive) { - u_int time_passed = get_timevaldiff(NULL, NULL); - u_int final_wait = max_completion_time - time_passed; + if (icmp_pkts_en_route(program_state->icmp_sent, program_state->icmp_recv, + program_state->icmp_lost) && + targets_alive(number_of_targets, program_state->targets_down)) { + unsigned int time_passed = get_timevaldiff(NULL, NULL, prog_start); + unsigned int final_wait = max_completion_time - time_passed; if (debug) { - printf("time_passed: %u final_wait: %u max_completion_time: %llu\n", time_passed, final_wait, max_completion_time); + printf("time_passed: %u final_wait: %u max_completion_time: %u\n", time_passed, + final_wait, max_completion_time); } if (time_passed > max_completion_time) { if (debug) { printf("Time passed. Finishing up\n"); } - finish(0); + finish(0, order_mode, mos_mode, rta_mode, pl_mode, jitter_mode, score_mode, + min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state); } /* catch the packets that might come in within the timeframe, but * haven't yet */ if (debug) { - printf("Waiting for %u micro-seconds (%0.3f msecs)\n", final_wait, (float)final_wait / 1000); + printf("Waiting for %u micro-seconds (%0.3f msecs)\n", final_wait, + (float)final_wait / 1000); } - wait_for_reply(icmp_sock, final_wait); + wait_for_reply(icmp_sock, final_wait, order_mode, mos_mode, rta_mode, pl_mode, jitter_mode, + score_mode, min_hosts_alive, icmp_pkt_size, pkt_interval, target_interval, + warn, crit, pid, mode, max_completion_time, prog_start, table, packets, + icmp_sock, number_of_targets, program_state); } } @@ -927,7 +897,15 @@ static void run_checks(void) { * both: * icmp echo reply : the rest */ -static int wait_for_reply(int sock, u_int t) { +static int wait_for_reply(int sock, const unsigned int time_interval, bool order_mode, + bool mos_mode, bool rta_mode, bool pl_mode, bool jitter_mode, + bool score_mode, int min_hosts_alive, unsigned short icmp_pkt_size, + unsigned int *pkt_interval, unsigned int *target_interval, threshold warn, + threshold crit, const pid_t pid, const int mode, + const unsigned long long max_completion_time, struct timeval *prog_start, + struct rta_host **table, const unsigned short packets, + const int icmp_sock, const unsigned short number_of_targets, + check_icmp_state *program_state) { union icmp_packet packet; if (!(packet.buf = malloc(icmp_pkt_size))) { crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size); @@ -937,30 +915,39 @@ static int wait_for_reply(int sock, u_int t) { memset(packet.buf, 0, icmp_pkt_size); /* if we can't listen or don't have anything to listen to, just return */ - if (!t || !icmp_pkts_en_route) { + if (!time_interval || !icmp_pkts_en_route(program_state->icmp_sent, program_state->icmp_recv, + program_state->icmp_lost)) { free(packet.buf); return 0; } struct timeval wait_start; - gettimeofday(&wait_start, &tz); + struct timezone time_zone_dummy; + gettimeofday(&wait_start, &time_zone_dummy); - u_int i = t; struct sockaddr_storage resp_addr; - u_int per_pkt_wait = t / icmp_pkts_en_route; + unsigned int per_pkt_wait = + time_interval / icmp_pkts_en_route(program_state->icmp_sent, program_state->icmp_recv, + program_state->icmp_lost); static unsigned char buf[65536]; union ip_hdr *ip; struct timeval now; - while (icmp_pkts_en_route && get_timevaldiff(&wait_start, NULL) < i) { - t = per_pkt_wait; + while (icmp_pkts_en_route(program_state->icmp_sent, program_state->icmp_recv, + program_state->icmp_lost) && + get_timevaldiff(&wait_start, NULL, prog_start) < time_interval) { + unsigned int loop_time_interval = per_pkt_wait; /* wrap up if all targets are declared dead */ - if (!targets_alive || get_timevaldiff(&prog_start, NULL) >= max_completion_time || (mode == MODE_HOSTCHECK && targets_down)) { - finish(0); + if (!targets_alive(number_of_targets, program_state->targets_down) || + get_timevaldiff(prog_start, NULL, prog_start) >= max_completion_time || + (mode == MODE_HOSTCHECK && program_state->targets_down)) { + finish(0, order_mode, mos_mode, rta_mode, pl_mode, jitter_mode, score_mode, + min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state); } /* reap responses until we hit a timeout */ - int n = recvfrom_wto(sock, buf, sizeof(buf), (struct sockaddr *)&resp_addr, &t, &now); + int n = recvfrom_wto(sock, buf, sizeof(buf), (struct sockaddr *)&resp_addr, + &loop_time_interval, &now, prog_start); if (!n) { if (debug > 1) { printf("recvfrom_wto() timed out during a %u usecs wait\n", per_pkt_wait); @@ -982,7 +969,9 @@ static int wait_for_reply(int sock, u_int t) { if (debug > 1) { char address[INET6_ADDRSTRLEN]; parse_address(&resp_addr, address, sizeof(address)); - printf("received %u bytes from %s\n", address_family == AF_INET6 ? ntohs(ip->ip6.ip6_plen) : ntohs(ip->ip.ip_len), address); + printf("received %u bytes from %s\n", + address_family == AF_INET6 ? ntohs(ip->ip6.ip6_plen) : ntohs(ip->ip.ip_len), + address); } } @@ -999,7 +988,8 @@ static int wait_for_reply(int sock, u_int t) { if (n < (hlen + ICMP_MINLEN)) { char address[INET6_ADDRSTRLEN]; parse_address(&resp_addr, address, sizeof(address)); - crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n", n, hlen + icmp_pkt_size, address); + crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n", n, + hlen + icmp_pkt_size, address); } /* else if(debug) { */ /* printf("ip header size: %u, packet size: %u (expected %u, %u)\n", */ @@ -1013,14 +1003,19 @@ static int wait_for_reply(int sock, u_int t) { /* address_family == AF_INET6 ? sizeof(struct icmp6_hdr) : sizeof(struct icmp));*/ - if ((address_family == PF_INET && (ntohs(packet.icp->icmp_id) != pid || packet.icp->icmp_type != ICMP_ECHOREPLY || - ntohs(packet.icp->icmp_seq) >= targets * packets)) || - (address_family == PF_INET6 && (ntohs(packet.icp6->icmp6_id) != pid || packet.icp6->icmp6_type != ICMP6_ECHO_REPLY || - ntohs(packet.icp6->icmp6_seq) >= targets * packets))) { + if ((address_family == PF_INET && + (ntohs(packet.icp->icmp_id) != pid || packet.icp->icmp_type != ICMP_ECHOREPLY || + ntohs(packet.icp->icmp_seq) >= number_of_targets * packets)) || + (address_family == PF_INET6 && + (ntohs(packet.icp6->icmp6_id) != pid || packet.icp6->icmp6_type != ICMP6_ECHO_REPLY || + ntohs(packet.icp6->icmp6_seq) >= number_of_targets * packets))) { if (debug > 2) { printf("not a proper ICMP_ECHOREPLY\n"); } - handle_random_icmp(buf + hlen, &resp_addr); + + handle_random_icmp(buf + hlen, &resp_addr, pkt_interval, target_interval, pid, table, + packets, number_of_targets, program_state); + continue; } @@ -1030,20 +1025,22 @@ static int wait_for_reply(int sock, u_int t) { if (address_family == PF_INET) { memcpy(&data, packet.icp->icmp_data, sizeof(data)); if (debug > 2) { - printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", sizeof(data), ntohs(packet.icp->icmp_id), - ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum); + printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", sizeof(data), + ntohs(packet.icp->icmp_id), ntohs(packet.icp->icmp_seq), + packet.icp->icmp_cksum); } host = table[ntohs(packet.icp->icmp_seq) / packets]; } else { memcpy(&data, &packet.icp6->icmp6_dataun.icmp6_un_data8[4], sizeof(data)); if (debug > 2) { - printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", sizeof(data), ntohs(packet.icp6->icmp6_id), - ntohs(packet.icp6->icmp6_seq), packet.icp6->icmp6_cksum); + printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", sizeof(data), + ntohs(packet.icp6->icmp6_id), ntohs(packet.icp6->icmp6_seq), + packet.icp6->icmp6_cksum); } host = table[ntohs(packet.icp6->icmp6_seq) / packets]; } - u_int tdiff = get_timevaldiff(&data.stime, &now); + unsigned int tdiff = get_timevaldiff(&data.stime, &now, prog_start); if (host->last_tdiff > 0) { /* Calculate jitter */ @@ -1081,7 +1078,7 @@ static int wait_for_reply(int sock, u_int t) { host->time_waited += tdiff; host->icmp_recv++; - icmp_recv++; + program_state->icmp_recv++; if (tdiff > (unsigned int)host->rtmax) { host->rtmax = tdiff; @@ -1097,13 +1094,14 @@ static int wait_for_reply(int sock, u_int t) { switch (address_family) { case AF_INET: { - printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u, max: %0.3f, min: %0.3f\n", (float)tdiff / 1000, address, - ttl, ip->ip.ip_ttl, (float)host->rtmax / 1000, (float)host->rtmin / 1000); + printf("%0.3f ms rtt from %s, incoming ttl: %u, max: %0.3f, min: %0.3f\n", + (float)tdiff / 1000, address, ip->ip.ip_ttl, (float)host->rtmax / 1000, + (float)host->rtmin / 1000); break; }; case AF_INET6: { - printf("%0.3f ms rtt from %s, outgoing ttl: %u, max: %0.3f, min: %0.3f\n", (float)tdiff / 1000, address, ttl, - (float)host->rtmax / 1000, (float)host->rtmin / 1000); + printf("%0.3f ms rtt from %s, max: %0.3f, min: %0.3f\n", (float)tdiff / 1000, + address, (float)host->rtmax / 1000, (float)host->rtmin / 1000); }; } } @@ -1112,7 +1110,8 @@ static int wait_for_reply(int sock, u_int t) { if (mode == MODE_HOSTCHECK) { printf("OK - %s responds to ICMP. Packet %u, rta %0.3fms|" "pkt=%u;;;0;%u rta=%0.3f;%0.3f;%0.3f;;\n", - host->name, icmp_recv, (float)tdiff / 1000, icmp_recv, packets, (float)tdiff / 1000, (float)warn.rta / 1000, + host->name, program_state->icmp_recv, (float)tdiff / 1000, + program_state->icmp_recv, packets, (float)tdiff / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000); exit(STATE_OK); } @@ -1123,7 +1122,8 @@ static int wait_for_reply(int sock, u_int t) { } /* the ping functions */ -static int send_icmp_ping(int sock, struct rta_host *host) { +static int send_icmp_ping(const int sock, struct rta_host *host, const unsigned short icmp_pkt_size, + const pid_t pid, check_icmp_state *program_state) { if (sock == -1) { errno = 0; crash("Attempt to send on bogus socket"); @@ -1141,6 +1141,7 @@ static int send_icmp_ping(int sock, struct rta_host *host) { memset(buf, 0, icmp_pkt_size); struct timeval tv; + struct timezone tz; if ((gettimeofday(&tv, &tz)) == -1) { free(buf); return -1; @@ -1166,8 +1167,9 @@ static int send_icmp_ping(int sock, struct rta_host *host) { icp->icmp_cksum = icmp_checksum((uint16_t *)buf, (size_t)icmp_pkt_size); if (debug > 2) { - printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", sizeof(data), ntohs(icp->icmp_id), - ntohs(icp->icmp_seq), icp->icmp_cksum, host->name); + printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", + sizeof(data), ntohs(icp->icmp_id), ntohs(icp->icmp_seq), icp->icmp_cksum, + host->name); } } else { struct icmp6_hdr *icp6 = (struct icmp6_hdr *)buf; @@ -1183,8 +1185,9 @@ static int send_icmp_ping(int sock, struct rta_host *host) { // let checksum be calculated automatically if (debug > 2) { - printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", sizeof(data), ntohs(icp6->icmp6_id), - ntohs(icp6->icmp6_seq), icp6->icmp6_cksum, host->name); + printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", + sizeof(data), ntohs(icp6->icmp6_id), ntohs(icp6->icmp6_seq), icp6->icmp6_cksum, + host->name); } } @@ -1222,13 +1225,14 @@ static int send_icmp_ping(int sock, struct rta_host *host) { return -1; } - icmp_sent++; + program_state->icmp_sent++; host->icmp_sent++; return 0; } -static int recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, u_int *timo, struct timeval *tv) { +static int recvfrom_wto(const int sock, void *buf, const unsigned int len, struct sockaddr *saddr, + unsigned int *timeout, struct timeval *tv, struct timeval *prog_start) { #ifdef HAVE_MSGHDR_MSG_CONTROL char ans_data[4096]; #endif // HAVE_MSGHDR_MSG_CONTROL @@ -1236,16 +1240,16 @@ static int recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr * struct cmsghdr *chdr; #endif - if (!*timo) { + if (!*timeout) { if (debug) { - printf("*timo is not\n"); + printf("*timeout is not\n"); } return 0; } struct timeval to; - to.tv_sec = *timo / 1000000; - to.tv_usec = (*timo - (to.tv_sec * 1000000)); + to.tv_sec = *timeout / 1000000; + to.tv_usec = (*timeout - (to.tv_sec * 1000000)); fd_set rd; fd_set wr; @@ -1255,54 +1259,68 @@ static int recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr * errno = 0; struct timeval then; - gettimeofday(&then, &tz); + struct timezone time_zone_dummy; + gettimeofday(&then, &time_zone_dummy); + int n = select(sock + 1, &rd, &wr, NULL, &to); if (n < 0) { crash("select() in recvfrom_wto"); } + struct timeval now; - gettimeofday(&now, &tz); - *timo = get_timevaldiff(&then, &now); + gettimeofday(&now, &time_zone_dummy); + *timeout = get_timevaldiff(&then, &now, prog_start); if (!n) { return 0; /* timeout */ } - u_int slen = sizeof(struct sockaddr_storage); + unsigned int slen = sizeof(struct sockaddr_storage); - struct iovec iov; - memset(&iov, 0, sizeof(iov)); - iov.iov_base = buf; - iov.iov_len = len; + struct iovec iov = { + .iov_base = buf, + .iov_len = len, + }; - struct msghdr hdr; - memset(&hdr, 0, sizeof(hdr)); - hdr.msg_name = saddr; - hdr.msg_namelen = slen; - hdr.msg_iov = &iov; - hdr.msg_iovlen = 1; + struct msghdr hdr = { + .msg_name = saddr, + .msg_namelen = slen, + .msg_iov = &iov, + .msg_iovlen = 1, #ifdef HAVE_MSGHDR_MSG_CONTROL - hdr.msg_control = ans_data; - hdr.msg_controllen = sizeof(ans_data); + .msg_control = ans_data, + .msg_controllen = sizeof(ans_data), #endif + }; + + ssize_t ret = recvmsg(sock, &hdr, 0); - int ret = recvmsg(sock, &hdr, 0); #ifdef SO_TIMESTAMP for (chdr = CMSG_FIRSTHDR(&hdr); chdr; chdr = CMSG_NXTHDR(&hdr, chdr)) { - if (chdr->cmsg_level == SOL_SOCKET && chdr->cmsg_type == SO_TIMESTAMP && chdr->cmsg_len >= CMSG_LEN(sizeof(struct timeval))) { + if (chdr->cmsg_level == SOL_SOCKET && chdr->cmsg_type == SO_TIMESTAMP && + chdr->cmsg_len >= CMSG_LEN(sizeof(struct timeval))) { memcpy(tv, CMSG_DATA(chdr), sizeof(*tv)); break; } } - if (!chdr) + if (!chdr) { + gettimeofday(tv, &time_zone_dummy); + } +#else + gettimeofday(tv, &time_zone_dummy); #endif // SO_TIMESTAMP - gettimeofday(tv, &tz); + return (ret); } -static void finish(int sig) { +static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, + bool jitter_mode, bool score_mode, int min_hosts_alive, threshold warn, + threshold crit, const int icmp_sock, const unsigned short number_of_targets, + check_icmp_state *program_state) { + // Deactivate alarm alarm(0); + if (debug > 1) { printf("finish(%d) called\n", sig); } @@ -1310,57 +1328,56 @@ static void finish(int sig) { if (icmp_sock != -1) { close(icmp_sock); } - if (udp_sock != -1) { - close(udp_sock); - } - if (tcp_sock != -1) { - close(tcp_sock); - } if (debug) { - printf("icmp_sent: %u icmp_recv: %u icmp_lost: %u\n", icmp_sent, icmp_recv, icmp_lost); - printf("targets: %u targets_alive: %u\n", targets, targets_alive); + printf("icmp_sent: %u icmp_recv: %u icmp_lost: %u\n", program_state->icmp_sent, + program_state->icmp_recv, program_state->icmp_lost); + printf("targets: %u targets_alive: %u\n", number_of_targets, + targets_alive(number_of_targets, program_state->targets_down)); } /* iterate thrice to calculate values, give output, and print perfparse */ - status = STATE_OK; - struct rta_host *host = list; + mp_state_enum status = STATE_OK; + struct rta_host *host = host_list; - u_int i = 0; + unsigned int target_counter = 0; const char *status_string[] = {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"}; int hosts_ok = 0; int hosts_warn = 0; while (host) { - int this_status = STATE_OK; + mp_state_enum this_status = STATE_OK; - unsigned char pl; + unsigned char packet_loss; double rta; if (!host->icmp_recv) { /* rta 0 is ofcourse not entirely correct, but will still show up * conspicuously as missing entries in perfparse and cacti */ - pl = 100; + packet_loss = 100; rta = 0; status = STATE_CRITICAL; /* up the down counter if not already counted */ - if (!(host->flags & FLAG_LOST_CAUSE) && targets_alive) { - targets_down++; + if (!(host->flags & FLAG_LOST_CAUSE) && + targets_alive(number_of_targets, program_state->targets_down)) { + program_state->targets_down++; } } else { - pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent; + packet_loss = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent; rta = (double)host->time_waited / host->icmp_recv; } if (host->icmp_recv > 1) { /* * This algorithm is probably pretty much blindly copied from - * locations like this one: https://www.slac.stanford.edu/comp/net/wan-mon/tutorial.html#mos - * It calculates a MOS value (range of 1 to 5, where 1 is bad and 5 really good). - * According to some quick research MOS originates from the Audio/Video transport network area. - * Whether it can and should be computed from ICMP data, I can not say. + * locations like this one: + * https://www.slac.stanford.edu/comp/net/wan-mon/tutorial.html#mos It calculates a MOS + * value (range of 1 to 5, where 1 is bad and 5 really good). According to some quick + * research MOS originates from the Audio/Video transport network area. Whether it can + * and should be computed from ICMP data, I can not say. * * Anyway the basic idea is to map a value "R" with a range of 0-100 to the MOS value * - * MOS stands likely for Mean Opinion Score ( https://en.wikipedia.org/wiki/Mean_Opinion_Score ) + * MOS stands likely for Mean Opinion Score ( + * https://en.wikipedia.org/wiki/Mean_Opinion_Score ) * * More links: * - https://confluence.slac.stanford.edu/display/IEPM/MOS @@ -1383,7 +1400,7 @@ static void finish(int sig) { // Now, let us deduct 2.5 R values per percentage of packet loss (i.e. a // loss of 5% will be entered as 5). - R = R - (pl * 2.5); + R = R - (packet_loss * 2.5); if (R < 0) { R = 0; @@ -1398,7 +1415,7 @@ static void finish(int sig) { host->mos = 0; } - host->pl = pl; + host->pl = packet_loss; host->rta = rta; /* if no new mode selected, use old schema */ @@ -1421,11 +1438,11 @@ static void finish(int sig) { } if (pl_mode) { - if (pl >= crit.pl) { + if (packet_loss >= crit.pl) { this_status = STATE_CRITICAL; status = STATE_CRITICAL; host->pl_status = STATE_CRITICAL; - } else if (status != STATE_CRITICAL && (pl >= warn.pl)) { + } else if (status != STATE_CRITICAL && (packet_loss >= warn.pl)) { this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status); status = STATE_WARNING; host->pl_status = STATE_WARNING; @@ -1478,7 +1495,7 @@ static void finish(int sig) { } /* this is inevitable */ - if (!targets_alive) { + if (!targets_alive(number_of_targets, program_state->targets_down)) { status = STATE_CRITICAL; } if (min_hosts_alive > -1) { @@ -1490,21 +1507,21 @@ static void finish(int sig) { } printf("%s - ", status_string[status]); - host = list; + host = host_list; while (host) { if (debug) { puts(""); } - if (i) { - if (i < targets) { + if (target_counter) { + if (target_counter < number_of_targets) { printf(" :: "); } else { printf("\n"); } } - i++; + target_counter++; if (!host->icmp_recv) { status = STATE_CRITICAL; @@ -1514,7 +1531,8 @@ static void finish(int sig) { if (host->flags & FLAG_LOST_CAUSE) { char address[INET6_ADDRSTRLEN]; parse_address(&host->error_addr, address, sizeof(address)); - printf("%s: %s @ %s. rta nan, lost %d%%", host->name, get_icmp_error_msg(host->icmp_type, host->icmp_code), address, 100); + printf("%s: %s @ %s. rta nan, lost %d%%", host->name, + get_icmp_error_msg(host->icmp_type, host->icmp_code), address, 100); } else { /* not marked as lost cause, so we have no flags for it */ printf("%s: rta nan, lost 100%%", host->name); } @@ -1525,9 +1543,11 @@ static void finish(int sig) { if (status == STATE_OK) { printf(" rta %0.3fms", host->rta / 1000); } else if (status == STATE_WARNING && host->rta_status == status) { - printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)warn.rta / 1000); + printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, + (float)warn.rta / 1000); } else if (status == STATE_CRITICAL && host->rta_status == status) { - printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)crit.rta / 1000); + printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, + (float)crit.rta / 1000); } } @@ -1591,8 +1611,8 @@ static void finish(int sig) { if (!(!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && order_mode)) { printf("|"); } - i = 0; - host = list; + target_counter = 0; + host = host_list; while (host) { if (debug) { puts(""); @@ -1600,45 +1620,56 @@ static void finish(int sig) { if (rta_mode) { if (host->pl < 100) { - printf("%srta=%0.3fms;%0.3f;%0.3f;0; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ", (targets > 1) ? host->name : "", - host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000, (targets > 1) ? host->name : "", - (float)host->rtmax / 1000, (targets > 1) ? host->name : "", + printf("%srta=%0.3fms;%0.3f;%0.3f;0; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ", + (number_of_targets > 1) ? host->name : "", host->rta / 1000, + (float)warn.rta / 1000, (float)crit.rta / 1000, + (number_of_targets > 1) ? host->name : "", (float)host->rtmax / 1000, + (number_of_targets > 1) ? host->name : "", (host->rtmin < INFINITY) ? (float)host->rtmin / 1000 : (float)0); } else { - printf("%srta=U;;;; %srtmax=U;;;; %srtmin=U;;;; ", (targets > 1) ? host->name : "", (targets > 1) ? host->name : "", - (targets > 1) ? host->name : ""); + printf("%srta=U;;;; %srtmax=U;;;; %srtmin=U;;;; ", + (number_of_targets > 1) ? host->name : "", + (number_of_targets > 1) ? host->name : "", + (number_of_targets > 1) ? host->name : ""); } } if (pl_mode) { - printf("%spl=%u%%;%u;%u;0;100 ", (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl); + printf("%spl=%u%%;%u;%u;0;100 ", (number_of_targets > 1) ? host->name : "", host->pl, + warn.pl, crit.pl); } if (jitter_mode) { if (host->pl < 100) { - printf("%sjitter_avg=%0.3fms;%0.3f;%0.3f;0; %sjitter_max=%0.3fms;;;; %sjitter_min=%0.3fms;;;; ", - (targets > 1) ? host->name : "", (float)host->jitter, (float)warn.jitter, (float)crit.jitter, - (targets > 1) ? host->name : "", (float)host->jitter_max / 1000, (targets > 1) ? host->name : "", - (float)host->jitter_min / 1000); + printf("%sjitter_avg=%0.3fms;%0.3f;%0.3f;0; %sjitter_max=%0.3fms;;;; " + "%sjitter_min=%0.3fms;;;; ", + (number_of_targets > 1) ? host->name : "", (float)host->jitter, + (float)warn.jitter, (float)crit.jitter, + (number_of_targets > 1) ? host->name : "", (float)host->jitter_max / 1000, + (number_of_targets > 1) ? host->name : "", (float)host->jitter_min / 1000); } else { - printf("%sjitter_avg=U;;;; %sjitter_max=U;;;; %sjitter_min=U;;;; ", (targets > 1) ? host->name : "", - (targets > 1) ? host->name : "", (targets > 1) ? host->name : ""); + printf("%sjitter_avg=U;;;; %sjitter_max=U;;;; %sjitter_min=U;;;; ", + (number_of_targets > 1) ? host->name : "", + (number_of_targets > 1) ? host->name : "", + (number_of_targets > 1) ? host->name : ""); } } if (mos_mode) { if (host->pl < 100) { - printf("%smos=%0.1f;%0.1f;%0.1f;0;5 ", (targets > 1) ? host->name : "", (float)host->mos, (float)warn.mos, (float)crit.mos); + printf("%smos=%0.1f;%0.1f;%0.1f;0;5 ", (number_of_targets > 1) ? host->name : "", + (float)host->mos, (float)warn.mos, (float)crit.mos); } else { - printf("%smos=U;;;; ", (targets > 1) ? host->name : ""); + printf("%smos=U;;;; ", (number_of_targets > 1) ? host->name : ""); } } if (score_mode) { if (host->pl < 100) { - printf("%sscore=%u;%u;%u;0;100 ", (targets > 1) ? host->name : "", (int)host->score, (int)warn.score, (int)crit.score); + printf("%sscore=%u;%u;%u;0;100 ", (number_of_targets > 1) ? host->name : "", + (int)host->score, (int)warn.score, (int)crit.score); } else { - printf("%sscore=U;;;; ", (targets > 1) ? host->name : ""); + printf("%sscore=U;;;; ", (number_of_targets > 1) ? host->name : ""); } } @@ -1656,46 +1687,53 @@ static void finish(int sig) { /* finish with an empty line */ puts(""); if (debug) { - printf("targets: %u, targets_alive: %u, hosts_ok: %u, hosts_warn: %u, min_hosts_alive: %i\n", targets, targets_alive, hosts_ok, - hosts_warn, min_hosts_alive); + printf( + "targets: %u, targets_alive: %u, hosts_ok: %u, hosts_warn: %u, min_hosts_alive: %i\n", + number_of_targets, targets_alive(number_of_targets, program_state->targets_down), + hosts_ok, hosts_warn, min_hosts_alive); } exit(status); } -static u_int get_timevaldiff(struct timeval *early, struct timeval *later) { +static time_t get_timevaldiff(struct timeval *earlier, struct timeval *later, + struct timeval *prog_start) { struct timeval now; if (!later) { - gettimeofday(&now, &tz); + struct timezone time_zone_dummy; + gettimeofday(&now, &time_zone_dummy); later = &now; } - if (!early) { - early = &prog_start; + if (!earlier) { + earlier = prog_start; } /* if early > later we return 0 so as to indicate a timeout */ - if (early->tv_sec > later->tv_sec || (early->tv_sec == later->tv_sec && early->tv_usec > later->tv_usec)) { + if (earlier->tv_sec > later->tv_sec || + (earlier->tv_sec == later->tv_sec && earlier->tv_usec > later->tv_usec)) { return 0; } - u_int ret = (later->tv_sec - early->tv_sec) * 1000000; - ret += later->tv_usec - early->tv_usec; + + time_t ret = (later->tv_sec - earlier->tv_sec) * 1000000; + ret += later->tv_usec - earlier->tv_usec; return ret; } -static int add_target_ip(char *arg, struct sockaddr_storage *in) { +static int add_target_ip(char *arg, struct sockaddr_storage *address) { struct sockaddr_in *sin; struct sockaddr_in6 *sin6; if (address_family == AF_INET) { - sin = (struct sockaddr_in *)in; + sin = (struct sockaddr_in *)address; } else { - sin6 = (struct sockaddr_in6 *)in; + sin6 = (struct sockaddr_in6 *)address; } /* disregard obviously stupid addresses * (I didn't find an ipv6 equivalent to INADDR_NONE) */ - if (((address_family == AF_INET && (sin->sin_addr.s_addr == INADDR_NONE || sin->sin_addr.s_addr == INADDR_ANY))) || + if (((address_family == AF_INET && + (sin->sin_addr.s_addr == INADDR_NONE || sin->sin_addr.s_addr == INADDR_ANY))) || (address_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) { return -1; } @@ -1703,13 +1741,14 @@ static int add_target_ip(char *arg, struct sockaddr_storage *in) { /* no point in adding two identical IP's, so don't. ;) */ struct sockaddr_in *host_sin; struct sockaddr_in6 *host_sin6; - struct rta_host *host = list; + struct rta_host *host = host_list; while (host) { host_sin = (struct sockaddr_in *)&host->saddr_in; host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; if ((address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr) || - (address_family == AF_INET6 && host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) { + (address_family == AF_INET6 && + host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) { if (debug) { printf("Identical IP already exists. Not adding %s\n", arg); } @@ -1722,10 +1761,11 @@ static int add_target_ip(char *arg, struct sockaddr_storage *in) { host = (struct rta_host *)malloc(sizeof(struct rta_host)); if (!host) { char straddr[INET6_ADDRSTRLEN]; - parse_address((struct sockaddr_storage *)&in, straddr, sizeof(straddr)); + parse_address((struct sockaddr_storage *)&address, straddr, sizeof(straddr)); crash("add_target_ip(%s, %s): malloc(%lu) failed", arg, straddr, sizeof(struct rta_host)); } - memset(host, 0, sizeof(struct rta_host)); + + *host = ping_target_init(); /* set the values. use calling name for output */ host->name = strdup(arg); @@ -1738,39 +1778,23 @@ static int add_target_ip(char *arg, struct sockaddr_storage *in) { } else { host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; host_sin6->sin6_family = AF_INET6; - memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr); - } - - /* fill out the sockaddr_in struct */ - host->rtmin = INFINITY; - host->rtmax = 0; - host->jitter = 0; - host->jitter_max = 0; - host->jitter_min = INFINITY; - host->last_tdiff = 0; - host->order_status = STATE_OK; - host->last_icmp_seq = 0; - host->rta_status = 0; - host->pl_status = 0; - host->jitter_status = 0; - host->mos_status = 0; - host->score_status = 0; - host->pl_status = 0; - - if (!list) { - list = cursor = host; + memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, + sizeof host_sin6->sin6_addr.s6_addr); + } + + if (!host_list) { + host_list = cursor = host; } else { cursor->next = host; } cursor = host; - targets++; return 0; } /* wrapper for add_target_ip */ -static int add_target(char *arg) { +static int add_target(char *arg, const int mode) { struct sockaddr_storage ip; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; @@ -1850,7 +1874,7 @@ static int add_target(char *arg) { return 0; } -static void set_source_ip(char *arg) { +static void set_source_ip(char *arg, const int icmp_sock) { struct sockaddr_in src; memset(&src, 0, sizeof(src)); @@ -1894,7 +1918,7 @@ static in_addr_t get_ip_address(const char *ifname) { * s = seconds * return value is in microseconds */ -static u_int get_timevar(const char *str) { +static unsigned int get_timevar(const char *str) { if (!str) { return 0; } @@ -1920,7 +1944,7 @@ static u_int get_timevar(const char *str) { printf("evaluating %s, u: %c, p: %c\n", str, u, p); } - u_int factor = 1000; /* default to milliseconds */ + unsigned int factor = 1000; /* default to milliseconds */ if (u == 'u') { factor = 1; /* microseconds */ } else if (u == 'm') { @@ -1933,7 +1957,7 @@ static u_int get_timevar(const char *str) { } char *ptr; - u_int i; + unsigned int i; i = strtoul(str, &ptr, 0); if (!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1) { return i * factor; @@ -1945,7 +1969,7 @@ static u_int get_timevar(const char *str) { } /* integer and decimal, respectively */ - u_int d = strtoul(ptr + 1, NULL, 0); + unsigned int d = strtoul(ptr + 1, NULL, 0); /* d is decimal, so get rid of excess digits */ while (d >= factor) { @@ -2000,9 +2024,11 @@ static int get_threshold(char *str, threshold *th) { * @param[in] length strlen(str) * @param[out] warn Pointer to the warn threshold struct to which the values should be assigned * @param[out] crit Pointer to the crit threshold struct to which the values should be assigned - * @param[in] mode Determines whether this a threshold for rta, packet_loss, jitter, mos or score (exclusively) + * @param[in] mode Determines whether this a threshold for rta, packet_loss, jitter, mos or score + * (exclusively) */ -static bool get_threshold2(char *str, size_t length, threshold *warn, threshold *crit, threshold_mode mode) { +static bool get_threshold2(char *str, size_t length, threshold *warn, threshold *crit, + threshold_mode mode) { if (!str || !length || !warn || !crit) { return false; } @@ -2108,13 +2134,14 @@ void print_help(void) { printf(" %s\n", _("Use IPv4 (default) or IPv6 to communicate with the targets")); printf(" %s\n", "-w"); printf(" %s", _("warning threshold (currently ")); - printf("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl); + printf("%0.3fms,%u%%)\n", (float)DEFAULT_WARN_RTA / 1000, DEFAULT_WARN_PL); printf(" %s\n", "-c"); printf(" %s", _("critical threshold (currently ")); - printf("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl); + printf("%0.3fms,%u%%)\n", (float)DEFAULT_CRIT_RTA / 1000, DEFAULT_CRIT_PL); printf(" %s\n", "-R"); - printf(" %s\n", _("RTA, round trip average, mode warning,critical, ex. 100ms,200ms unit in ms")); + printf(" %s\n", + _("RTA, round trip average, mode warning,critical, ex. 100ms,200ms unit in ms")); printf(" %s\n", "-P"); printf(" %s\n", _("packet loss mode, ex. 40%,50% , unit in %")); printf(" %s\n", "-J"); @@ -2131,28 +2158,29 @@ void print_help(void) { printf(" %s\n", _("specify a source IP address or device name")); printf(" %s\n", "-n"); printf(" %s", _("number of packets to send (currently ")); - printf("%u)\n", packets); + printf("%u)\n", DEFAULT_NUMBER_OF_PACKETS); printf(" %s\n", "-p"); printf(" %s", _("number of packets to send (currently ")); - printf("%u)\n", packets); + printf("%u)\n", DEFAULT_NUMBER_OF_PACKETS); printf(" %s\n", "-i"); printf(" %s", _("max packet interval (currently ")); - printf("%0.3fms)\n", (float)pkt_interval / 1000); + printf("%0.3fms)\n", (float)DEFAULT_PKT_INTERVAL / 1000); printf(" %s\n", "-I"); printf(" %s", _("max target interval (currently ")); - printf("%0.3fms)\n", (float)target_interval / 1000); + printf("%0.3fms)\n", (float)DEFAULT_TARGET_INTERVAL / 1000); printf(" %s\n", "-m"); printf(" %s", _("number of alive hosts required for success")); printf("\n"); printf(" %s\n", "-l"); printf(" %s", _("TTL on outgoing packets (currently ")); - printf("%u)\n", ttl); + printf("%u)\n", DEFAULT_TTL); printf(" %s\n", "-t"); printf(" %s", _("timeout value (seconds, currently ")); - printf("%u)\n", timeout); + printf("%u)\n", DEFAULT_TIMEOUT); printf(" %s\n", "-b"); printf(" %s\n", _("Number of icmp data bytes to send")); - printf(" %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"), icmp_data_size, ICMP_MINLEN); + printf(" %s %lu + %d)\n", _("Packet size will be data bytes + icmp header (currently"), + DEFAULT_PING_DATA_SIZE, ICMP_MINLEN); printf(" %s\n", "-v"); printf(" %s\n", _("verbose")); printf("\n"); @@ -2162,12 +2190,15 @@ void print_help(void) { printf("\n"); printf(" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%")); printf(" %s\n", _("packet loss. The default values should work well for most users.")); - printf(" %s\n", _("You can specify different RTA factors using the standardized abbreviations")); - printf(" %s\n", _("us (microseconds), ms (milliseconds, default) or just plain s for seconds.")); + printf(" %s\n", + _("You can specify different RTA factors using the standardized abbreviations")); + printf(" %s\n", + _("us (microseconds), ms (milliseconds, default) or just plain s for seconds.")); /* -d not yet implemented */ - /* printf ("%s\n", _("Threshold format for -d is warn,crit. 12,14 means WARNING if >= 12 hops")); - printf ("%s\n", _("are spent and CRITICAL if >= 14 hops are spent.")); - printf ("%s\n\n", _("NOTE: Some systems decrease TTL when forming ICMP_ECHOREPLY, others do not."));*/ + /* printf ("%s\n", _("Threshold format for -d is warn,crit. 12,14 means WARNING if >= 12 + hops")); printf ("%s\n", _("are spent and CRITICAL if >= 14 hops are spent.")); printf + ("%s\n\n", _("NOTE: Some systems decrease TTL when forming ICMP_ECHOREPLY, others do + not."));*/ printf("\n"); printf(" %s\n", _("The -v switch can be specified several times for increased verbosity.")); /* printf ("%s\n", _("Long options are currently unsupported.")); diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.c b/plugins-root/check_icmp.d/check_icmp_helpers.c new file mode 100644 index 00000000..8f6d7362 --- /dev/null +++ b/plugins-root/check_icmp.d/check_icmp_helpers.c @@ -0,0 +1,142 @@ +#include "./config.h" +#include "states.h" +#include +#include +#include "./check_icmp_helpers.h" +#include "../../plugins/netutils.h" + +check_icmp_config check_icmp_config_init() { + check_icmp_config tmp = { + .source_ip = NULL, + + .order_mode = false, + .mos_mode = false, + .rta_mode = false, + .pl_mode = false, + .jitter_mode = false, + .score_mode = false, + + .min_hosts_alive = -1, + .icmp_data_size = DEFAULT_PING_DATA_SIZE, + .icmp_pkt_size = DEFAULT_PING_DATA_SIZE + ICMP_MINLEN, + .pkt_interval = DEFAULT_PKT_INTERVAL, + .target_interval = 0, + .crit = {.pl = DEFAULT_CRIT_PL, + .rta = DEFAULT_CRIT_RTA, + .jitter = 50.0, + .mos = 3.0, + .score = 70.0}, + .warn = {.pl = DEFAULT_WARN_PL, + .rta = DEFAULT_WARN_RTA, + .jitter = 40.0, + .mos = 3.5, + .score = 80.0}, + .pid = {}, + .mode = MODE_RTA, + .timeout = DEFAULT_TIMEOUT, + .ttl = DEFAULT_TTL, + + .packets = DEFAULT_NUMBER_OF_PACKETS, + .number_of_targets = 0, + .hosts = NULL, + }; + return tmp; +} + +ping_target ping_target_init() { + ping_target tmp = { + .rtmin = INFINITY, + + .jitter_min = INFINITY, + + .rta_status = STATE_OK, + .jitter_status = STATE_OK, + .mos_status = STATE_OK, + .score_status = STATE_OK, + .pl_status = STATE_OK, + .order_status = STATE_OK, + }; + + return tmp; +} + +check_icmp_state check_icmp_state_init() { + check_icmp_state tmp = {.icmp_sent = 0, .icmp_lost = 0, .icmp_recv = 0, .targets_down = 0}; + + return tmp; +} + +rta_host_create_wrapper rta_host_create(char *name, struct sockaddr_storage *address) { + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + if (address_family == AF_INET) { + sin = (struct sockaddr_in *)address; + } else { + sin6 = (struct sockaddr_in6 *)address; + } + + rta_host_create_wrapper result = { + .errorcode = OK, + }; + + /* disregard obviously stupid addresses + * (I didn't find an ipv6 equivalent to INADDR_NONE) */ + if (((address_family == AF_INET && + (sin->sin_addr.s_addr == INADDR_NONE || sin->sin_addr.s_addr == INADDR_ANY))) || + (address_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) { + result.errorcode = ERROR; + return result; + } + + // TODO: Maybe add the following back in as a sanity check for the config + // /* no point in adding two identical IP's, so don't. ;) */ + // struct sockaddr_in *host_sin; + // struct sockaddr_in6 *host_sin6; + // struct rta_host *host = host_list; + + // while (host) { + // host_sin = (struct sockaddr_in *)&host->saddr_in; + // host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; + + // if ((address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr) || + // (address_family == AF_INET6 && + // host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) { + // if (debug) { + // printf("Identical IP already exists. Not adding %s\n", name); + // } + // return -1; + // } + // host = host->next; + // } + + /* add the fresh ip */ + ping_target host = ping_target_init(); + + /* set the values. use calling name for output */ + host.name = strdup(name); + + /* fill out the sockaddr_storage struct */ + if (address_family == AF_INET) { + struct sockaddr_in *host_sin = (struct sockaddr_in *)&host.saddr_in; + host_sin->sin_family = AF_INET; + host_sin->sin_addr.s_addr = sin->sin_addr.s_addr; + } else { + struct sockaddr_in6 *host_sin6 = (struct sockaddr_in6 *)&host.saddr_in; + host_sin6->sin6_family = AF_INET6; + memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, + sizeof host_sin6->sin6_addr.s6_addr); + } + + result.host = host; + + return result; +} + +check_icmp_target_container check_icmp_target_container_init() { + check_icmp_target_container tmp = { + .name = NULL, + .number_of_targets = 0, + .target_list = NULL, + }; + return tmp; +} diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.h b/plugins-root/check_icmp.d/check_icmp_helpers.h new file mode 100644 index 00000000..49f720ec --- /dev/null +++ b/plugins-root/check_icmp.d/check_icmp_helpers.h @@ -0,0 +1,73 @@ +#pragma once + +#include "../../lib/states.h" +#include +#include +#include +#include +#include +#include +#include + +typedef struct rta_host { + unsigned short id; /* id in **table, and icmp pkts */ + char *name; /* arg used for adding this host */ + char *msg; /* icmp error message, if any */ + struct sockaddr_storage saddr_in; /* the address of this host */ + struct sockaddr_storage error_addr; /* stores address of error replies */ + unsigned long long time_waited; /* total time waited, in usecs */ + unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */ + unsigned char icmp_type, icmp_code; /* type and code from errors */ + unsigned short flags; /* control/status flags */ + + double rta; /* measured RTA */ + double rtmax; /* max rtt */ + double rtmin; /* min rtt */ + + double jitter; /* measured jitter */ + double jitter_max; /* jitter rtt maximum */ + double jitter_min; /* jitter rtt minimum */ + + double EffectiveLatency; + double mos; /* Mean opinion score */ + double score; /* score */ + + unsigned int last_tdiff; + unsigned int last_icmp_seq; /* Last ICMP_SEQ to check out of order pkts */ + unsigned char pl; /* measured packet loss */ + + mp_state_enum rta_status; // check result for RTA checks + mp_state_enum jitter_status; // check result for Jitter checks + mp_state_enum mos_status; // check result for MOS checks + mp_state_enum score_status; // check result for score checks + mp_state_enum pl_status; // check result for packet loss checks + mp_state_enum order_status; // check result for packet order checks + + struct rta_host *next; +} ping_target; + +ping_target ping_target_init(); + +typedef struct { + char *name; + ping_target *target_list; + unsigned int number_of_targets; +} check_icmp_target_container; + +check_icmp_target_container check_icmp_target_container_init(); + +typedef struct { + unsigned int icmp_sent; + unsigned int icmp_recv; + unsigned int icmp_lost; + unsigned short targets_down; +} check_icmp_state; + +check_icmp_state check_icmp_state_init(); + +typedef struct { + int errorcode; + ping_target host; +} rta_host_create_wrapper; + +rta_host_create_wrapper rta_host_create(char *name, struct sockaddr_storage *address); -- cgit v1.2.3-74-g34f1 From 5a6adcb7db497fba7b89471a6d58dba80330ff4a Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Sun, 4 May 2025 01:42:52 +0200 Subject: WIP - check_icmp refactor 2 --- plugins-root/check_icmp.c | 724 +++++++++++++------------ plugins-root/check_icmp.d/check_icmp_helpers.c | 48 +- plugins-root/check_icmp.d/check_icmp_helpers.h | 7 +- plugins-root/check_icmp.d/config.h | 102 ++++ 4 files changed, 540 insertions(+), 341 deletions(-) create mode 100644 plugins-root/check_icmp.d/config.h (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 87dac21d..99414014 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -66,6 +66,9 @@ const char *email = "devel@monitoring-plugins.org"; #include #include #include +#include +#include +#include #include "../lib/states.h" #include "./check_icmp.d/config.h" @@ -131,76 +134,79 @@ void print_usage(void); /* Time related */ static unsigned int get_timevar(const char * /*str*/); -static time_t get_timevaldiff(struct timeval * /*early*/, struct timeval * /*later*/, - struct timeval *prog_start); +static time_t get_timevaldiff(struct timeval earlier, struct timeval later); +static time_t get_timevaldiff_to_now(struct timeval earlier); static in_addr_t get_ip_address(const char * /*ifname*/); -static void set_source_ip(char * /*arg*/, const int icmp_sock); +static void set_source_ip(char * /*arg*/, int icmp_sock); /* Receiving data */ -static int wait_for_reply(int /*sock*/, unsigned int /*t*/, bool order_mode, bool mos_mode, - bool rta_mode, bool pl_mode, bool jitter_mode, bool score_mode, - int min_hosts_alive, unsigned short icmp_pkt_size, - unsigned int *pkt_interval, unsigned int *target_interval, threshold warn, - threshold crit, pid_t pid, int mode, - unsigned long long max_completion_time, struct timeval *prog_start, - struct rta_host **table, const unsigned short packets, - const int icmp_sock, const unsigned short number_of_targets, - check_icmp_state *program_state); - -static int recvfrom_wto(int /*sock*/, void * /*buf*/, unsigned int /*len*/, - struct sockaddr * /*saddr*/, unsigned int * /*timo*/, - struct timeval * /*tv*/, struct timeval *prog_start); +static int wait_for_reply(int socket, time_t time_interval, unsigned short icmp_pkt_size, + unsigned int *pkt_interval, unsigned int *target_interval, pid_t pid, + ping_target **table, unsigned short packets, + unsigned short number_of_targets, check_icmp_state *program_state); + +static ssize_t recvfrom_wto(int /*sock*/, void * /*buf*/, unsigned int /*len*/, + struct sockaddr * /*saddr*/, time_t *timeout, struct timeval * /*tv*/); static int handle_random_icmp(unsigned char * /*packet*/, struct sockaddr_storage * /*addr*/, unsigned int *pkt_interval, unsigned int *target_interval, pid_t pid, - struct rta_host **table, unsigned short packets, - const unsigned short number_of_targets, - check_icmp_state *program_state); + ping_target **table, unsigned short packets, + unsigned short number_of_targets, check_icmp_state *program_state); /* Sending data */ -static int send_icmp_ping(int /*sock*/, struct rta_host * /*host*/, unsigned short icmp_pkt_size, +static int send_icmp_ping(int /*sock*/, ping_target * /*host*/, unsigned short icmp_pkt_size, pid_t pid, check_icmp_state *program_state); /* Threshold related */ -static int get_threshold(char *str, threshold *th); +static int get_threshold(char *str, threshold *threshold); static bool get_threshold2(char *str, size_t length, threshold * /*warn*/, threshold * /*crit*/, threshold_mode mode); -static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, threshold_mode mode); +static bool parse_threshold2_helper(char *threshold_string, size_t length, threshold *thr, + threshold_mode mode); /* main test function */ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, bool jitter_mode, bool score_mode, int min_hosts_alive, unsigned short icmp_pkt_size, unsigned int *pkt_interval, unsigned int *target_interval, threshold warn, threshold crit, pid_t pid, - int mode, unsigned int max_completion_time, const struct timeval *prog_start, - struct rta_host **table, const unsigned short packets, const int icmp_sock, - const unsigned short number_of_targets, check_icmp_state *program_state); + int mode, unsigned int max_completion_time, struct timeval prog_start, + ping_target **table, unsigned short packets, int icmp_sock, + unsigned short number_of_targets, check_icmp_state *program_state, + ping_target *target_list); /* Target aquisition */ -static int add_target(char * /*arg*/, int mode); -static int add_target_ip(char * /*arg*/, struct sockaddr_storage * /*in*/); +typedef struct { + int error_code; + ping_target *targets; + unsigned int number_of_targets; +} add_target_wrapper; +static add_target_wrapper add_target(char * /*arg*/, int mode); + +typedef struct { + int error_code; + ping_target *target; +} add_target_ip_wrapper; +static add_target_ip_wrapper add_target_ip(char * /*arg*/, struct sockaddr_storage * /*in*/); -static void parse_address(struct sockaddr_storage * /*addr*/, char * /*address*/, int /*size*/); +static void parse_address(struct sockaddr_storage * /*addr*/, char * /*address*/, socklen_t size); static unsigned short icmp_checksum(uint16_t * /*p*/, size_t /*n*/); /* End of run function */ static void finish(int /*sig*/, bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, bool jitter_mode, bool score_mode, int min_hosts_alive, threshold warn, - threshold crit, const int icmp_sock, const unsigned short number_of_targets, - check_icmp_state *program_state); + threshold crit, int icmp_sock, unsigned short number_of_targets, + check_icmp_state *program_state, ping_target *target_list); /* Error exit */ static void crash(const char * /*fmt*/, ...); /** global variables **/ -static struct rta_host *cursor = NULL; -static struct rta_host *host_list = NULL; - static int debug = 0; -/** the working code **/ +extern unsigned int timeout; +/** the working code **/ static inline unsigned short targets_alive(unsigned short targets, unsigned short targets_down) { return targets - targets_down; } @@ -259,7 +265,8 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { } } - /* Parse protocol arguments first */ + // Parse protocol arguments first + // and count hosts here char *opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64"; for (int i = 1; i < argc; i++) { long int arg; @@ -281,10 +288,31 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { usage(_("IPv6 support not available\n")); #endif break; + case 'H': { + result.config.number_of_hosts++; + } } } } + char **tmp = &argv[optind]; + while (*tmp) { + result.config.number_of_hosts++; + tmp++; + } + + // Sanity check: if hostmode is selected,only a single host is allowed + if (result.config.mode == MODE_HOSTCHECK && result.config.number_of_hosts > 1) { + usage("check_host only allows a single host"); + } + + // Allocate hosts + result.config.hosts = + calloc(result.config.number_of_hosts, sizeof(check_icmp_target_container)); + if (result.config.hosts == NULL) { + crash("failed to allocate memory"); + } + /* Reset argument scanning */ optind = 1; @@ -301,8 +329,8 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { long size = strtol(optarg, NULL, 0); if ((unsigned long)size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && size < MAX_PING_DATA) { - result.config.icmp_data_size = size; - result.config.icmp_pkt_size = size + ICMP_MINLEN; + result.config.icmp_data_size = (unsigned short)size; + result.config.icmp_pkt_size = (unsigned short)(size + ICMP_MINLEN); } else { usage_va("ICMP data length must be between: %lu and %lu", sizeof(struct icmp) + sizeof(struct icmp_ping_data), @@ -323,24 +351,26 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { break; case 'n': case 'p': - result.config.packets = strtoul(optarg, NULL, 0); + result.config.packets = (unsigned short)strtoul(optarg, NULL, 0); if (result.config.packets > 20) { errno = 0; crash("packets is > 20 (%d)", result.config.packets); } break; case 't': - result.config.timeout = strtoul(optarg, NULL, 0); + timeout = (unsigned int)strtoul(optarg, NULL, 0); // TODO die here and complain about wrong input - // instead of: - if (!result.config.timeout) { - result.config.timeout = 10; - } break; case 'H': { - int add_result = add_target(optarg, result.config.mode); - if (add_result == 0) { - result.config.number_of_targets++; + add_target_wrapper add_result = add_target(optarg, result.config.mode); + if (add_result.error_code == OK) { + if (result.config.targets != NULL) { + result.config.number_of_targets += + ping_target_list_append(result.config.targets, add_result.targets); + } else { + result.config.targets = add_result.targets; + result.config.number_of_targets += add_result.number_of_targets; + } } } break; case 'l': @@ -569,7 +599,7 @@ static const char *get_icmp_error_msg(unsigned char icmp_type, unsigned char icm static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr, unsigned int *pkt_interval, unsigned int *target_interval, - const pid_t pid, struct rta_host **table, unsigned short packets, + const pid_t pid, ping_target **table, unsigned short packets, const unsigned short number_of_targets, check_icmp_state *program_state) { struct icmp p; @@ -611,7 +641,7 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad } /* it is indeed a response for us */ - struct rta_host *host = table[ntohs(sent_icmp.icmp_seq) / packets]; + ping_target *host = table[ntohs(sent_icmp.icmp_seq) / packets]; if (debug) { char address[INET6_ADDRSTRLEN]; parse_address(addr, address, sizeof(address)); @@ -629,8 +659,8 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad /* source quench means we're sending too fast, so increase the * interval and mark this packet lost */ if (p.icmp_type == ICMP_SOURCEQUENCH) { - *pkt_interval *= PACKET_BACKOFF_FACTOR; - *target_interval *= TARGET_BACKOFF_FACTOR; + *pkt_interval = (unsigned int)(*pkt_interval * PACKET_BACKOFF_FACTOR); + *target_interval = (unsigned int)(*target_interval * TARGET_BACKOFF_FACTOR); } else { program_state->targets_down++; host->flags |= FLAG_LOST_CAUSE; @@ -642,7 +672,7 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad return 0; } -void parse_address(struct sockaddr_storage *addr, char *address, int size) { +void parse_address(struct sockaddr_storage *addr, char *address, socklen_t size) { switch (address_family) { case AF_INET: inet_ntop(address_family, &((struct sockaddr_in *)addr)->sin_addr, address, size); @@ -722,32 +752,24 @@ int main(int argc, char **argv) { } } -#ifdef HAVE_SIGACTION struct sigaction sig_action; - sig_action.sa_sigaction = NULL; - sig_action.sa_handler = finish; + sig_action.sa_handler = NULL; + sig_action.sa_sigaction = check_icmp_timeout_handler; sigfillset(&sig_action.sa_mask); - sig_action.sa_flags = SA_NODEFER | SA_RESTART; + sig_action.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO; sigaction(SIGINT, &sig_action, NULL); sigaction(SIGHUP, &sig_action, NULL); sigaction(SIGTERM, &sig_action, NULL); sigaction(SIGALRM, &sig_action, NULL); -#else /* HAVE_SIGACTION */ - // signal(SIGINT, finish); - // signal(SIGHUP, finish); - // signal(SIGTERM, finish); - // signal(SIGALRM, finish); -#endif /* HAVE_SIGACTION */ if (debug) { - printf("Setting alarm timeout to %u seconds\n", config.timeout); + printf("Setting alarm timeout to %u seconds\n", timeout); } - alarm(config.timeout); + alarm(timeout); /* make sure we don't wait any longer than necessary */ - struct timezone time_zone_dummy; struct timeval prog_start; - gettimeofday(&prog_start, &time_zone_dummy); + gettimeofday(&prog_start, NULL); unsigned int max_completion_time = ((config.number_of_targets * config.packets * config.pkt_interval) + @@ -765,8 +787,8 @@ int main(int argc, char **argv) { } if (debug) { - if (max_completion_time > (unsigned int)config.timeout * 1000000) { - printf("max_completion_time: %u timeout: %u\n", max_completion_time, config.timeout); + if (max_completion_time > (timeout * 1000000)) { + printf("max_completion_time: %u timeout: %u\n", max_completion_time, timeout); printf("Timeout must be at least %u\n", (max_completion_time / 1000000) + 1); } } @@ -776,7 +798,7 @@ int main(int argc, char **argv) { config.warn.rta, config.warn.pl); printf("pkt_interval: %u target_interval: %u\n", config.pkt_interval, config.target_interval); - printf("icmp_pkt_size: %u timeout: %u\n", config.icmp_pkt_size, config.timeout); + printf("icmp_pkt_size: %u timeout: %u\n", config.icmp_pkt_size, timeout); } if (config.min_hosts_alive < -1) { @@ -784,18 +806,18 @@ int main(int argc, char **argv) { crash("minimum alive hosts is negative (%i)", config.min_hosts_alive); } - struct rta_host *host = host_list; - struct rta_host **table = malloc(sizeof(struct rta_host *) * config.number_of_targets); + ping_target *host = config.targets; + ping_target **table = malloc(sizeof(ping_target *) * config.number_of_targets); if (!table) { crash("main(): malloc failed for host table"); } - unsigned short i = 0; + unsigned short target_index = 0; while (host) { - host->id = i * config.packets; - table[i] = host; + host->id = target_index * config.packets; + table[target_index] = host; host = host->next; - i++; + target_index++; } unsigned int pkt_interval = config.pkt_interval; @@ -806,13 +828,13 @@ int main(int argc, char **argv) { run_checks(config.order_mode, config.mos_mode, config.rta_mode, config.pl_mode, config.jitter_mode, config.score_mode, config.min_hosts_alive, config.icmp_data_size, &pkt_interval, &target_interval, config.warn, config.crit, config.pid, config.mode, - max_completion_time, &prog_start, table, config.packets, icmp_sock, - config.number_of_targets, &program_state); + max_completion_time, prog_start, table, config.packets, icmp_sock, + config.number_of_targets, &program_state, config.targets); errno = 0; finish(0, config.order_mode, config.mos_mode, config.rta_mode, config.pl_mode, config.jitter_mode, config.score_mode, config.min_hosts_alive, config.warn, config.crit, - icmp_sock, config.number_of_targets, &program_state); + icmp_sock, config.number_of_targets, &program_state, config.targets); return (0); } @@ -822,9 +844,10 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo unsigned short icmp_pkt_size, unsigned int *pkt_interval, unsigned int *target_interval, threshold warn, threshold crit, const pid_t pid, const int mode, const unsigned int max_completion_time, - const struct timeval *prog_start, struct rta_host **table, + const struct timeval prog_start, ping_target **table, const unsigned short packets, const int icmp_sock, - const unsigned short number_of_targets, check_icmp_state *program_state) { + const unsigned short number_of_targets, check_icmp_state *program_state, + ping_target *target_list) { /* this loop might actually violate the pkt_interval or target_interval * settings, but only if there aren't any packets on the wire which * indicates that the target can handle an increased packet rate */ @@ -833,7 +856,8 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo /* don't send useless packets */ if (!targets_alive(number_of_targets, program_state->targets_down)) { finish(0, order_mode, mos_mode, rta_mode, pl_mode, jitter_mode, score_mode, - min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state); + min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state, + target_list); } if (table[target_index]->flags & FLAG_LOST_CAUSE) { if (debug) { @@ -845,25 +869,32 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo /* we're still in the game, so send next packet */ (void)send_icmp_ping(icmp_sock, table[target_index], icmp_pkt_size, pid, program_state); - wait_for_reply(icmp_sock, *target_interval, order_mode, mos_mode, rta_mode, pl_mode, - jitter_mode, score_mode, min_hosts_alive, icmp_pkt_size, pkt_interval, - target_interval, warn, crit, pid, mode, max_completion_time, prog_start, - table, packets, icmp_sock, number_of_targets, program_state); + /* wrap up if all targets are declared dead */ + if (targets_alive(number_of_targets, program_state->targets_down) || + get_timevaldiff(prog_start, prog_start) < max_completion_time || + !(mode == MODE_HOSTCHECK && program_state->targets_down)) { + wait_for_reply(icmp_sock, *target_interval, icmp_pkt_size, pkt_interval, + target_interval, pid, table, packets, number_of_targets, + program_state); + } + } + if (targets_alive(number_of_targets, program_state->targets_down) || + get_timevaldiff_to_now(prog_start) < max_completion_time || + !(mode == MODE_HOSTCHECK && program_state->targets_down)) { + wait_for_reply(icmp_sock, *pkt_interval * number_of_targets, icmp_pkt_size, + pkt_interval, target_interval, pid, table, packets, number_of_targets, + program_state); } - wait_for_reply(icmp_sock, *pkt_interval * number_of_targets, order_mode, mos_mode, rta_mode, - pl_mode, jitter_mode, score_mode, min_hosts_alive, icmp_pkt_size, - pkt_interval, target_interval, warn, crit, pid, mode, max_completion_time, - prog_start, table, packets, icmp_sock, number_of_targets, program_state); } if (icmp_pkts_en_route(program_state->icmp_sent, program_state->icmp_recv, program_state->icmp_lost) && targets_alive(number_of_targets, program_state->targets_down)) { - unsigned int time_passed = get_timevaldiff(NULL, NULL, prog_start); - unsigned int final_wait = max_completion_time - time_passed; + time_t time_passed = get_timevaldiff_to_now(prog_start); + time_t final_wait = max_completion_time - time_passed; if (debug) { - printf("time_passed: %u final_wait: %u max_completion_time: %u\n", time_passed, + printf("time_passed: %ld final_wait: %ld max_completion_time: %u\n", time_passed, final_wait, max_completion_time); } if (time_passed > max_completion_time) { @@ -871,19 +902,22 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo printf("Time passed. Finishing up\n"); } finish(0, order_mode, mos_mode, rta_mode, pl_mode, jitter_mode, score_mode, - min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state); + min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state, + target_list); } /* catch the packets that might come in within the timeframe, but * haven't yet */ if (debug) { - printf("Waiting for %u micro-seconds (%0.3f msecs)\n", final_wait, + printf("Waiting for %ld micro-seconds (%0.3f msecs)\n", final_wait, (float)final_wait / 1000); } - wait_for_reply(icmp_sock, final_wait, order_mode, mos_mode, rta_mode, pl_mode, jitter_mode, - score_mode, min_hosts_alive, icmp_pkt_size, pkt_interval, target_interval, - warn, crit, pid, mode, max_completion_time, prog_start, table, packets, - icmp_sock, number_of_targets, program_state); + if (targets_alive(number_of_targets, program_state->targets_down) || + get_timevaldiff_to_now(prog_start) < max_completion_time || + !(mode == MODE_HOSTCHECK && program_state->targets_down)) { + wait_for_reply(icmp_sock, final_wait, icmp_pkt_size, pkt_interval, target_interval, pid, + table, packets, number_of_targets, program_state); + } } } @@ -897,15 +931,10 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo * both: * icmp echo reply : the rest */ -static int wait_for_reply(int sock, const unsigned int time_interval, bool order_mode, - bool mos_mode, bool rta_mode, bool pl_mode, bool jitter_mode, - bool score_mode, int min_hosts_alive, unsigned short icmp_pkt_size, - unsigned int *pkt_interval, unsigned int *target_interval, threshold warn, - threshold crit, const pid_t pid, const int mode, - const unsigned long long max_completion_time, struct timeval *prog_start, - struct rta_host **table, const unsigned short packets, - const int icmp_sock, const unsigned short number_of_targets, - check_icmp_state *program_state) { +static int wait_for_reply(int sock, const time_t time_interval, unsigned short icmp_pkt_size, + unsigned int *pkt_interval, unsigned int *target_interval, pid_t pid, + ping_target **table, const unsigned short packets, + const unsigned short number_of_targets, check_icmp_state *program_state) { union icmp_packet packet; if (!(packet.buf = malloc(icmp_pkt_size))) { crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size); @@ -921,56 +950,50 @@ static int wait_for_reply(int sock, const unsigned int time_interval, bool order return 0; } + // Get current time stamp struct timeval wait_start; - struct timezone time_zone_dummy; - gettimeofday(&wait_start, &time_zone_dummy); + gettimeofday(&wait_start, NULL); struct sockaddr_storage resp_addr; - unsigned int per_pkt_wait = + time_t per_pkt_wait = time_interval / icmp_pkts_en_route(program_state->icmp_sent, program_state->icmp_recv, program_state->icmp_lost); static unsigned char buf[65536]; - union ip_hdr *ip; - struct timeval now; + union ip_hdr *ip_header; + struct timeval packet_received_timestamp; while (icmp_pkts_en_route(program_state->icmp_sent, program_state->icmp_recv, program_state->icmp_lost) && - get_timevaldiff(&wait_start, NULL, prog_start) < time_interval) { - unsigned int loop_time_interval = per_pkt_wait; - - /* wrap up if all targets are declared dead */ - if (!targets_alive(number_of_targets, program_state->targets_down) || - get_timevaldiff(prog_start, NULL, prog_start) >= max_completion_time || - (mode == MODE_HOSTCHECK && program_state->targets_down)) { - finish(0, order_mode, mos_mode, rta_mode, pl_mode, jitter_mode, score_mode, - min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state); - } + get_timevaldiff_to_now(wait_start) < time_interval) { + time_t loop_time_interval = per_pkt_wait; /* reap responses until we hit a timeout */ - int n = recvfrom_wto(sock, buf, sizeof(buf), (struct sockaddr *)&resp_addr, - &loop_time_interval, &now, prog_start); + ssize_t n = recvfrom_wto(sock, buf, sizeof(buf), (struct sockaddr *)&resp_addr, + &loop_time_interval, &packet_received_timestamp); if (!n) { if (debug > 1) { - printf("recvfrom_wto() timed out during a %u usecs wait\n", per_pkt_wait); + printf("recvfrom_wto() timed out during a %ld usecs wait\n", per_pkt_wait); } continue; /* timeout for this one, so keep trying */ } + if (n < 0) { if (debug) { printf("recvfrom_wto() returned errors\n"); } free(packet.buf); - return n; + return (int)n; } // FIXME: with ipv6 we don't have an ip header here if (address_family != AF_INET6) { - ip = (union ip_hdr *)buf; + ip_header = (union ip_hdr *)buf; if (debug > 1) { char address[INET6_ADDRSTRLEN]; parse_address(&resp_addr, address, sizeof(address)); printf("received %u bytes from %s\n", - address_family == AF_INET6 ? ntohs(ip->ip6.ip6_plen) : ntohs(ip->ip.ip_len), + address_family == AF_INET6 ? ntohs(ip_header->ip6.ip6_plen) + : ntohs(ip_header->ip.ip_len), address); } } @@ -982,7 +1005,7 @@ static int wait_for_reply(int sock, const unsigned int time_interval, bool order * off the bottom 4 bits */ /* hlen = (ip->ip_vhl & 0x0f) << 2; */ /* #else */ - int hlen = (address_family == AF_INET6) ? 0 : ip->ip.ip_hl << 2; + int hlen = (address_family == AF_INET6) ? 0 : ip_header->ip.ip_hl << 2; /* #endif */ if (n < (hlen + ICMP_MINLEN)) { @@ -1020,7 +1043,7 @@ static int wait_for_reply(int sock, const unsigned int time_interval, bool order } /* this is indeed a valid response */ - struct rta_host *host; + ping_target *target; struct icmp_ping_data data; if (address_family == PF_INET) { memcpy(&data, packet.icp->icmp_data, sizeof(data)); @@ -1029,7 +1052,7 @@ static int wait_for_reply(int sock, const unsigned int time_interval, bool order ntohs(packet.icp->icmp_id), ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum); } - host = table[ntohs(packet.icp->icmp_seq) / packets]; + target = table[ntohs(packet.icp->icmp_seq) / packets]; } else { memcpy(&data, &packet.icp6->icmp6_dataun.icmp6_un_data8[4], sizeof(data)); if (debug > 2) { @@ -1037,55 +1060,55 @@ static int wait_for_reply(int sock, const unsigned int time_interval, bool order ntohs(packet.icp6->icmp6_id), ntohs(packet.icp6->icmp6_seq), packet.icp6->icmp6_cksum); } - host = table[ntohs(packet.icp6->icmp6_seq) / packets]; + target = table[ntohs(packet.icp6->icmp6_seq) / packets]; } - unsigned int tdiff = get_timevaldiff(&data.stime, &now, prog_start); + time_t tdiff = get_timevaldiff(data.stime, packet_received_timestamp); - if (host->last_tdiff > 0) { + if (target->last_tdiff > 0) { /* Calculate jitter */ double jitter_tmp; - if (host->last_tdiff > tdiff) { - jitter_tmp = host->last_tdiff - tdiff; + if (target->last_tdiff > tdiff) { + jitter_tmp = (double)(target->last_tdiff - tdiff); } else { - jitter_tmp = tdiff - host->last_tdiff; + jitter_tmp = (double)(tdiff - target->last_tdiff); } - if (host->jitter == 0) { - host->jitter = jitter_tmp; - host->jitter_max = jitter_tmp; - host->jitter_min = jitter_tmp; + if (target->jitter == 0) { + target->jitter = jitter_tmp; + target->jitter_max = jitter_tmp; + target->jitter_min = jitter_tmp; } else { - host->jitter += jitter_tmp; + target->jitter += jitter_tmp; - if (jitter_tmp < host->jitter_min) { - host->jitter_min = jitter_tmp; + if (jitter_tmp < target->jitter_min) { + target->jitter_min = jitter_tmp; } - if (jitter_tmp > host->jitter_max) { - host->jitter_max = jitter_tmp; + if (jitter_tmp > target->jitter_max) { + target->jitter_max = jitter_tmp; } } /* Check if packets in order */ - if (host->last_icmp_seq >= packet.icp->icmp_seq) { - host->order_status = STATE_CRITICAL; + if (target->last_icmp_seq >= packet.icp->icmp_seq) { + target->order_status = STATE_CRITICAL; } } - host->last_tdiff = tdiff; + target->last_tdiff = tdiff; - host->last_icmp_seq = packet.icp->icmp_seq; + target->last_icmp_seq = packet.icp->icmp_seq; - host->time_waited += tdiff; - host->icmp_recv++; + target->time_waited += tdiff; + target->icmp_recv++; program_state->icmp_recv++; - if (tdiff > (unsigned int)host->rtmax) { - host->rtmax = tdiff; + if (tdiff > (unsigned int)target->rtmax) { + target->rtmax = (double)tdiff; } - if ((host->rtmin == INFINITY) || (tdiff < (unsigned int)host->rtmin)) { - host->rtmin = tdiff; + if ((target->rtmin == INFINITY) || (tdiff < (unsigned int)target->rtmin)) { + target->rtmin = (double)tdiff; } if (debug) { @@ -1095,26 +1118,16 @@ static int wait_for_reply(int sock, const unsigned int time_interval, bool order switch (address_family) { case AF_INET: { printf("%0.3f ms rtt from %s, incoming ttl: %u, max: %0.3f, min: %0.3f\n", - (float)tdiff / 1000, address, ip->ip.ip_ttl, (float)host->rtmax / 1000, - (float)host->rtmin / 1000); + (float)tdiff / 1000, address, ip_header->ip.ip_ttl, + (float)target->rtmax / 1000, (float)target->rtmin / 1000); break; }; case AF_INET6: { printf("%0.3f ms rtt from %s, max: %0.3f, min: %0.3f\n", (float)tdiff / 1000, - address, (float)host->rtmax / 1000, (float)host->rtmin / 1000); + address, (float)target->rtmax / 1000, (float)target->rtmin / 1000); }; } } - - /* if we're in hostcheck mode, exit with limited printouts */ - if (mode == MODE_HOSTCHECK) { - printf("OK - %s responds to ICMP. Packet %u, rta %0.3fms|" - "pkt=%u;;;0;%u rta=%0.3f;%0.3f;%0.3f;;\n", - host->name, program_state->icmp_recv, (float)tdiff / 1000, - program_state->icmp_recv, packets, (float)tdiff / 1000, (float)warn.rta / 1000, - (float)crit.rta / 1000); - exit(STATE_OK); - } } free(packet.buf); @@ -1122,7 +1135,7 @@ static int wait_for_reply(int sock, const unsigned int time_interval, bool order } /* the ping functions */ -static int send_icmp_ping(const int sock, struct rta_host *host, const unsigned short icmp_pkt_size, +static int send_icmp_ping(const int sock, ping_target *host, const unsigned short icmp_pkt_size, const pid_t pid, check_icmp_state *program_state) { if (sock == -1) { errno = 0; @@ -1140,18 +1153,17 @@ static int send_icmp_ping(const int sock, struct rta_host *host, const unsigned } memset(buf, 0, icmp_pkt_size); - struct timeval tv; - struct timezone tz; - if ((gettimeofday(&tv, &tz)) == -1) { + struct timeval current_time; + if ((gettimeofday(¤t_time, NULL)) == -1) { free(buf); return -1; } struct icmp_ping_data data; data.ping_id = 10; /* host->icmp.icmp_sent; */ - memcpy(&data.stime, &tv, sizeof(tv)); + memcpy(&data.stime, ¤t_time, sizeof(current_time)); - size_t addrlen; + socklen_t addrlen; if (address_family == AF_INET) { struct icmp *icp = (struct icmp *)buf; @@ -1162,7 +1174,7 @@ static int send_icmp_ping(const int sock, struct rta_host *host, const unsigned icp->icmp_type = ICMP_ECHO; icp->icmp_code = 0; icp->icmp_cksum = 0; - icp->icmp_id = htons(pid); + icp->icmp_id = htons((uint16_t)pid); icp->icmp_seq = htons(host->id++); icp->icmp_cksum = icmp_checksum((uint16_t *)buf, (size_t)icmp_pkt_size); @@ -1180,7 +1192,7 @@ static int send_icmp_ping(const int sock, struct rta_host *host, const unsigned icp6->icmp6_type = ICMP6_ECHO_REQUEST; icp6->icmp6_code = 0; icp6->icmp6_cksum = 0; - icp6->icmp6_id = htons(pid); + icp6->icmp6_id = htons((uint16_t)pid); icp6->icmp6_seq = htons(host->id++); // let checksum be calculated automatically @@ -1231,8 +1243,9 @@ static int send_icmp_ping(const int sock, struct rta_host *host, const unsigned return 0; } -static int recvfrom_wto(const int sock, void *buf, const unsigned int len, struct sockaddr *saddr, - unsigned int *timeout, struct timeval *tv, struct timeval *prog_start) { +static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len, + struct sockaddr *saddr, time_t *timeout, + struct timeval *received_timestamp) { #ifdef HAVE_MSGHDR_MSG_CONTROL char ans_data[4096]; #endif // HAVE_MSGHDR_MSG_CONTROL @@ -1247,31 +1260,33 @@ static int recvfrom_wto(const int sock, void *buf, const unsigned int len, struc return 0; } - struct timeval to; - to.tv_sec = *timeout / 1000000; - to.tv_usec = (*timeout - (to.tv_sec * 1000000)); + struct timeval real_timeout; + real_timeout.tv_sec = *timeout / 1000000; + real_timeout.tv_usec = (*timeout - (real_timeout.tv_sec * 1000000)); - fd_set rd; - fd_set wr; - FD_ZERO(&rd); - FD_ZERO(&wr); - FD_SET(sock, &rd); - errno = 0; + // Dummy fds for select + fd_set dummy_write_fds; + FD_ZERO(&dummy_write_fds); + + // Read fds for select with the socket + fd_set read_fds; + FD_ZERO(&read_fds); + FD_SET(sock, &read_fds); struct timeval then; - struct timezone time_zone_dummy; - gettimeofday(&then, &time_zone_dummy); + gettimeofday(&then, NULL); - int n = select(sock + 1, &rd, &wr, NULL, &to); - if (n < 0) { + errno = 0; + int select_return = select(sock + 1, &read_fds, &dummy_write_fds, NULL, &real_timeout); + if (select_return < 0) { crash("select() in recvfrom_wto"); } struct timeval now; - gettimeofday(&now, &time_zone_dummy); - *timeout = get_timevaldiff(&then, &now, prog_start); + gettimeofday(&now, NULL); + *timeout = get_timevaldiff(then, now); - if (!n) { + if (!select_return) { return 0; /* timeout */ } @@ -1299,16 +1314,16 @@ static int recvfrom_wto(const int sock, void *buf, const unsigned int len, struc for (chdr = CMSG_FIRSTHDR(&hdr); chdr; chdr = CMSG_NXTHDR(&hdr, chdr)) { if (chdr->cmsg_level == SOL_SOCKET && chdr->cmsg_type == SO_TIMESTAMP && chdr->cmsg_len >= CMSG_LEN(sizeof(struct timeval))) { - memcpy(tv, CMSG_DATA(chdr), sizeof(*tv)); + memcpy(received_timestamp, CMSG_DATA(chdr), sizeof(*received_timestamp)); break; } } if (!chdr) { - gettimeofday(tv, &time_zone_dummy); + gettimeofday(received_timestamp, NULL); } #else - gettimeofday(tv, &time_zone_dummy); + gettimeofday(tv, NULL); #endif // SO_TIMESTAMP return (ret); @@ -1317,7 +1332,7 @@ static int recvfrom_wto(const int sock, void *buf, const unsigned int len, struc static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, bool jitter_mode, bool score_mode, int min_hosts_alive, threshold warn, threshold crit, const int icmp_sock, const unsigned short number_of_targets, - check_icmp_state *program_state) { + check_icmp_state *program_state, ping_target *target_list) { // Deactivate alarm alarm(0); @@ -1338,7 +1353,7 @@ static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool /* iterate thrice to calculate values, give output, and print perfparse */ mp_state_enum status = STATE_OK; - struct rta_host *host = host_list; + ping_target *host = target_list; unsigned int target_counter = 0; const char *status_string[] = {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"}; @@ -1361,7 +1376,8 @@ static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool program_state->targets_down++; } } else { - packet_loss = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent; + packet_loss = + (unsigned char)((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent; rta = (double)host->time_waited / host->icmp_recv; } @@ -1507,7 +1523,7 @@ static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool } printf("%s - ", status_string[status]); - host = host_list; + host = target_list; while (host) { if (debug) { puts(""); @@ -1611,8 +1627,9 @@ static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool if (!(!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && order_mode)) { printf("|"); } + target_counter = 0; - host = host_list; + host = target_list; while (host) { if (debug) { puts(""); @@ -1696,32 +1713,27 @@ static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool exit(status); } -static time_t get_timevaldiff(struct timeval *earlier, struct timeval *later, - struct timeval *prog_start) { - struct timeval now; - - if (!later) { - struct timezone time_zone_dummy; - gettimeofday(&now, &time_zone_dummy); - later = &now; - } - if (!earlier) { - earlier = prog_start; - } - +static time_t get_timevaldiff(const struct timeval earlier, const struct timeval later) { /* if early > later we return 0 so as to indicate a timeout */ - if (earlier->tv_sec > later->tv_sec || - (earlier->tv_sec == later->tv_sec && earlier->tv_usec > later->tv_usec)) { + if (earlier.tv_sec > later.tv_sec || + (earlier.tv_sec == later.tv_sec && earlier.tv_usec > later.tv_usec)) { return 0; } - time_t ret = (later->tv_sec - earlier->tv_sec) * 1000000; - ret += later->tv_usec - earlier->tv_usec; + time_t ret = (later.tv_sec - earlier.tv_sec) * 1000000; + ret += later.tv_usec - earlier.tv_usec; return ret; } -static int add_target_ip(char *arg, struct sockaddr_storage *address) { +static time_t get_timevaldiff_to_now(struct timeval earlier) { + struct timeval now; + gettimeofday(&now, NULL); + + return get_timevaldiff(earlier, now); +} + +static add_target_ip_wrapper add_target_ip(char *arg, struct sockaddr_storage *address) { struct sockaddr_in *sin; struct sockaddr_in6 *sin6; if (address_family == AF_INET) { @@ -1730,110 +1742,127 @@ static int add_target_ip(char *arg, struct sockaddr_storage *address) { sin6 = (struct sockaddr_in6 *)address; } + add_target_ip_wrapper result = { + .error_code = OK, + .target = NULL, + }; + /* disregard obviously stupid addresses * (I didn't find an ipv6 equivalent to INADDR_NONE) */ if (((address_family == AF_INET && (sin->sin_addr.s_addr == INADDR_NONE || sin->sin_addr.s_addr == INADDR_ANY))) || (address_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) { - return -1; + result.error_code = ERROR; + return result; } + // TODO: allow duplicate targets for now, might be on purpose /* no point in adding two identical IP's, so don't. ;) */ - struct sockaddr_in *host_sin; - struct sockaddr_in6 *host_sin6; - struct rta_host *host = host_list; - while (host) { - host_sin = (struct sockaddr_in *)&host->saddr_in; - host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; - - if ((address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr) || - (address_family == AF_INET6 && - host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) { - if (debug) { - printf("Identical IP already exists. Not adding %s\n", arg); - } - return -1; - } - host = host->next; - } + // struct sockaddr_in *host_sin; + // struct sockaddr_in6 *host_sin6; + // ping_target *host = host_list; + // while (host) { + // host_sin = (struct sockaddr_in *)&host->saddr_in; + // host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; + + // if ((address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr) || + // (address_family == AF_INET6 && + // host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) { + // if (debug) { + // printf("Identical IP already exists. Not adding %s\n", arg); + // } + // return -1; + // } + // host = host->next; + // } /* add the fresh ip */ - host = (struct rta_host *)malloc(sizeof(struct rta_host)); - if (!host) { + ping_target *target = (ping_target *)malloc(sizeof(ping_target)); + if (!target) { char straddr[INET6_ADDRSTRLEN]; parse_address((struct sockaddr_storage *)&address, straddr, sizeof(straddr)); - crash("add_target_ip(%s, %s): malloc(%lu) failed", arg, straddr, sizeof(struct rta_host)); + crash("add_target_ip(%s, %s): malloc(%lu) failed", arg, straddr, sizeof(ping_target)); } - *host = ping_target_init(); + *target = ping_target_init(); /* set the values. use calling name for output */ - host->name = strdup(arg); + target->name = strdup(arg); /* fill out the sockaddr_storage struct */ + struct sockaddr_in *host_sin; + struct sockaddr_in6 *host_sin6; if (address_family == AF_INET) { - host_sin = (struct sockaddr_in *)&host->saddr_in; + host_sin = (struct sockaddr_in *)&target->saddr_in; host_sin->sin_family = AF_INET; host_sin->sin_addr.s_addr = sin->sin_addr.s_addr; } else { - host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; + host_sin6 = (struct sockaddr_in6 *)&target->saddr_in; host_sin6->sin6_family = AF_INET6; memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr); } - if (!host_list) { - host_list = cursor = host; - } else { - cursor->next = host; - } - - cursor = host; + result.target = target; - return 0; + return result; } /* wrapper for add_target_ip */ -static int add_target(char *arg, const int mode) { - struct sockaddr_storage ip; +static add_target_wrapper add_target(char *arg, const int mode) { + struct sockaddr_storage address_storage; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; - int result = -1; + int error_code = -1; switch (address_family) { case -1: /* -4 and -6 are not specified on cmdline */ address_family = AF_INET; - sin = (struct sockaddr_in *)&ip; - result = inet_pton(address_family, arg, &sin->sin_addr); + sin = (struct sockaddr_in *)&address_storage; + error_code = inet_pton(address_family, arg, &sin->sin_addr); #ifdef USE_IPV6 - if (result != 1) { + if (error_code != 1) { address_family = AF_INET6; - sin6 = (struct sockaddr_in6 *)&ip; - result = inet_pton(address_family, arg, &sin6->sin6_addr); + sin6 = (struct sockaddr_in6 *)&address_storage; + error_code = inet_pton(address_family, arg, &sin6->sin6_addr); } #endif /* If we don't find any valid addresses, we still don't know the address_family */ - if (result != 1) { + if (error_code != 1) { address_family = -1; } break; case AF_INET: - sin = (struct sockaddr_in *)&ip; - result = inet_pton(address_family, arg, &sin->sin_addr); + sin = (struct sockaddr_in *)&address_storage; + error_code = inet_pton(address_family, arg, &sin->sin_addr); break; case AF_INET6: - sin6 = (struct sockaddr_in6 *)&ip; - result = inet_pton(address_family, arg, &sin6->sin6_addr); + sin6 = (struct sockaddr_in6 *)&address_storage; + error_code = inet_pton(address_family, arg, &sin6->sin6_addr); break; default: crash("Address family not supported"); } + add_target_wrapper result = { + .error_code = OK, + .targets = NULL, + }; + /* don't resolve if we don't have to */ - if (result == 1) { + if (error_code == 1) { /* don't add all ip's if we were given a specific one */ - return add_target_ip(arg, &ip); + add_target_ip_wrapper targeted = add_target_ip(arg, &address_storage); + + if (targeted.error_code != OK) { + result.error_code = ERROR; + return result; + } + + result.targets = targeted.target; + result.number_of_targets = 1; + return result; } struct addrinfo hints; @@ -1851,14 +1880,28 @@ static int add_target(char *arg, const int mode) { if ((error = getaddrinfo(arg, NULL, &hints, &res)) != 0) { errno = 0; crash("Failed to resolve %s: %s", arg, gai_strerror(error)); - return -1; + result.error_code = ERROR; + return result; } address_family = res->ai_family; /* possibly add all the IP's as targets */ - for (struct addrinfo *p = res; p != NULL; p = p->ai_next) { - memcpy(&ip, p->ai_addr, p->ai_addrlen); - add_target_ip(arg, &ip); + for (struct addrinfo *address = res; address != NULL; address = address->ai_next) { + struct sockaddr_storage temporary_ip_address; + memcpy(&temporary_ip_address, address->ai_addr, address->ai_addrlen); + add_target_ip_wrapper tmp = add_target_ip(arg, &temporary_ip_address); + + if (tmp.error_code != OK) { + // No proper error handling + // What to do? + } else { + if (result.targets == NULL) { + result.targets = tmp.target; + result.number_of_targets = 1; + } else { + result.number_of_targets += ping_target_list_append(result.targets, tmp.target); + } + } /* this is silly, but it works */ if (mode == MODE_HOSTCHECK || mode == MODE_ALL) { @@ -1867,11 +1910,13 @@ static int add_target(char *arg, const int mode) { } continue; } + + // Abort after first hit if not in of the modes above break; } freeaddrinfo(res); - return 0; + return result; } static void set_source_ip(char *arg, const int icmp_sock) { @@ -1890,8 +1935,8 @@ static void set_source_ip(char *arg, const int icmp_sock) { /* TODO: Move this to netutils.c and also change check_dhcp to use that. */ static in_addr_t get_ip_address(const char *ifname) { // TODO: Rewrite this so the function return an error and we exit somewhere else - struct sockaddr_in ip; - ip.sin_addr.s_addr = 0; // Fake initialization to make compiler happy + struct sockaddr_in ip_address; + ip_address.sin_addr.s_addr = 0; // Fake initialization to make compiler happy #if defined(SIOCGIFADDR) struct ifreq ifr; @@ -1909,7 +1954,7 @@ static in_addr_t get_ip_address(const char *ifname) { errno = 0; crash("Cannot get interface IP address on this platform."); #endif - return ip.sin_addr.s_addr; + return ip_address.sin_addr.s_addr; } /* @@ -1930,87 +1975,90 @@ static unsigned int get_timevar(const char *str) { /* unit might be given as ms|m (millisec), * us|u (microsec) or just plain s, for seconds */ - char p = '\0'; - char u = str[len - 1]; + char tmp = '\0'; + char unit = str[len - 1]; if (len >= 2 && !isdigit((int)str[len - 2])) { - p = str[len - 2]; + tmp = str[len - 2]; } - if (p && u == 's') { - u = p; - } else if (!p) { - p = u; + + if (tmp && unit == 's') { + unit = tmp; + } else if (!tmp) { + tmp = unit; } + if (debug > 2) { - printf("evaluating %s, u: %c, p: %c\n", str, u, p); + printf("evaluating %s, u: %c, p: %c\n", str, unit, tmp); } unsigned int factor = 1000; /* default to milliseconds */ - if (u == 'u') { + if (unit == 'u') { factor = 1; /* microseconds */ - } else if (u == 'm') { + } else if (unit == 'm') { factor = 1000; /* milliseconds */ - } else if (u == 's') { + } else if (unit == 's') { factor = 1000000; /* seconds */ } + if (debug > 2) { printf("factor is %u\n", factor); } char *ptr; - unsigned int i; - i = strtoul(str, &ptr, 0); + unsigned long pre_radix; + pre_radix = strtoul(str, &ptr, 0); if (!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1) { - return i * factor; + return (unsigned int)(pre_radix * factor); } /* time specified in usecs can't have decimal points, so ignore them */ if (factor == 1) { - return i; + return (unsigned int)pre_radix; } /* integer and decimal, respectively */ - unsigned int d = strtoul(ptr + 1, NULL, 0); + unsigned int post_radix = (unsigned int)strtoul(ptr + 1, NULL, 0); /* d is decimal, so get rid of excess digits */ - while (d >= factor) { - d /= 10; + while (post_radix >= factor) { + post_radix /= 10; } /* the last parenthesis avoids floating point exceptions. */ - return ((i * factor) + (d * (factor / 10))); + return (unsigned int)((pre_radix * factor) + (post_radix * (factor / 10))); } /* not too good at checking errors, but it'll do (main() should barfe on -1) */ -static int get_threshold(char *str, threshold *th) { - if (!str || !strlen(str) || !th) { +static int get_threshold(char *str, threshold *threshold) { + if (!str || !strlen(str) || !threshold) { return -1; } /* pointer magic slims code by 10 lines. i is bof-stop on stupid libc's */ - char i = 0; - char *p = &str[strlen(str) - 1]; - while (p != &str[1]) { - if (*p == '%') { - *p = '\0'; - } else if (*p == ',' && i) { - *p = '\0'; /* reset it so get_timevar(str) works nicely later */ - th->pl = (unsigned char)strtoul(p + 1, NULL, 0); + bool is_at_last_char = false; + char *tmp = &str[strlen(str) - 1]; + while (tmp != &str[1]) { + if (*tmp == '%') { + *tmp = '\0'; + } else if (*tmp == ',' && is_at_last_char) { + *tmp = '\0'; /* reset it so get_timevar(str) works nicely later */ + threshold->pl = (unsigned char)strtoul(tmp + 1, NULL, 0); break; } - i = 1; - p--; + is_at_last_char = true; + tmp--; } - th->rta = get_timevar(str); + threshold->rta = get_timevar(str); - if (!th->rta) { + if (!threshold->rta) { return -1; } - if (th->rta > MAXTTL * 1000000) { - th->rta = MAXTTL * 1000000; + if (threshold->rta > MAXTTL * 1000000) { + threshold->rta = MAXTTL * 1000000; } - if (th->pl > 100) { - th->pl = 100; + if (threshold->pl > 100) { + threshold->pl = 100; } return 0; @@ -2034,58 +2082,58 @@ static bool get_threshold2(char *str, size_t length, threshold *warn, threshold } // p points to the last char in str - char *p = &str[length - 1]; + char *work_pointer = &str[length - 1]; // first_iteration is bof-stop on stupid libc's bool first_iteration = true; - while (p != &str[0]) { - if ((*p == 'm') || (*p == '%')) { - *p = '\0'; - } else if (*p == ',' && !first_iteration) { - *p = '\0'; /* reset it so get_timevar(str) works nicely later */ + while (work_pointer != &str[0]) { + if ((*work_pointer == 'm') || (*work_pointer == '%')) { + *work_pointer = '\0'; + } else if (*work_pointer == ',' && !first_iteration) { + *work_pointer = '\0'; /* reset it so get_timevar(str) works nicely later */ - char *start_of_value = p + 1; + char *start_of_value = work_pointer + 1; if (!parse_threshold2_helper(start_of_value, strlen(start_of_value), crit, mode)) { return false; } } first_iteration = false; - p--; + work_pointer--; } - return parse_threshold2_helper(p, strlen(p), warn, mode); + return parse_threshold2_helper(work_pointer, strlen(work_pointer), warn, mode); } -static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, threshold_mode mode) { +static bool parse_threshold2_helper(char *threshold_string, size_t length, threshold *thr, + threshold_mode mode) { char *resultChecker = {0}; switch (mode) { case const_rta_mode: - thr->rta = strtod(s, &resultChecker) * 1000; + thr->rta = (unsigned int)(strtod(threshold_string, &resultChecker) * 1000); break; case const_packet_loss_mode: - thr->pl = (unsigned char)strtoul(s, &resultChecker, 0); + thr->pl = (unsigned char)strtoul(threshold_string, &resultChecker, 0); break; case const_jitter_mode: - thr->jitter = strtod(s, &resultChecker); - + thr->jitter = strtod(threshold_string, &resultChecker); break; case const_mos_mode: - thr->mos = strtod(s, &resultChecker); + thr->mos = strtod(threshold_string, &resultChecker); break; case const_score_mode: - thr->score = strtod(s, &resultChecker); + thr->score = strtod(threshold_string, &resultChecker); break; } - if (resultChecker == s) { + if (resultChecker == threshold_string) { // Failed to parse return false; } - if (resultChecker != (s + length)) { + if (resultChecker != (threshold_string + length)) { // Trailing symbols return false; } @@ -2093,24 +2141,24 @@ static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, thre return true; } -unsigned short icmp_checksum(uint16_t *p, size_t n) { +unsigned short icmp_checksum(uint16_t *packet, size_t packet_size) { long sum = 0; /* sizeof(uint16_t) == 2 */ - while (n >= 2) { - sum += *(p++); - n -= 2; + while (packet_size >= 2) { + sum += *(packet++); + packet_size -= 2; } /* mop up the occasional odd byte */ - if (n == 1) { - sum += *((uint8_t *)p - 1); + if (packet_size == 1) { + sum += *((uint8_t *)packet - 1); } sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ unsigned short cksum; - cksum = ~sum; /* ones-complement, trunc to 16 bits */ + cksum = (unsigned short)~sum; /* ones-complement, trunc to 16 bits */ return cksum; } diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.c b/plugins-root/check_icmp.d/check_icmp_helpers.c index 8f6d7362..2efe6e59 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.c +++ b/plugins-root/check_icmp.d/check_icmp_helpers.c @@ -5,6 +5,9 @@ #include "./check_icmp_helpers.h" #include "../../plugins/netutils.h" +// timeout as a global variable to make it available to the timeout handler +unsigned int timeout = DEFAULT_TIMEOUT; + check_icmp_config check_icmp_config_init() { check_icmp_config tmp = { .source_ip = NULL, @@ -33,11 +36,14 @@ check_icmp_config check_icmp_config_init() { .score = 80.0}, .pid = {}, .mode = MODE_RTA, - .timeout = DEFAULT_TIMEOUT, .ttl = DEFAULT_TTL, .packets = DEFAULT_NUMBER_OF_PACKETS, + .number_of_targets = 0, + .targets = NULL, + + .number_of_hosts = 0, .hosts = NULL, }; return tmp; @@ -140,3 +146,43 @@ check_icmp_target_container check_icmp_target_container_init() { }; return tmp; } + +unsigned int ping_target_list_append(ping_target *list, ping_target *elem) { + if (elem == NULL || list == NULL) { + return 0; + } + + while (list->next != NULL) { + list = list->next; + } + + list->next = elem; + + unsigned int result = 1; + + while (elem->next != NULL) { + result++; + elem = elem->next; + } + + return result; +} + +void check_icmp_timeout_handler(int signal, siginfo_t * info, void *ucontext) { + // Ignore unused arguments + (void) info; + (void) ucontext; + mp_subcheck timeout_sc = mp_subcheck_init(); + timeout_sc = mp_set_subcheck_state(timeout_sc, socket_timeout_state); + + if (signal == SIGALRM) { + xasprintf(&timeout_sc.output, _("timeout after %d seconds\n"), timeout); + } else { + xasprintf(&timeout_sc.output, _("timeout after %d seconds\n"), timeout); + } + + mp_check overall = mp_check_init(); + mp_add_subcheck_to_check(&overall, timeout_sc); + + mp_exit(overall); +} diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.h b/plugins-root/check_icmp.d/check_icmp_helpers.h index 49f720ec..7e8a4d9f 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.h +++ b/plugins-root/check_icmp.d/check_icmp_helpers.h @@ -15,7 +15,7 @@ typedef struct rta_host { char *msg; /* icmp error message, if any */ struct sockaddr_storage saddr_in; /* the address of this host */ struct sockaddr_storage error_addr; /* stores address of error replies */ - unsigned long long time_waited; /* total time waited, in usecs */ + time_t time_waited; /* total time waited, in usecs */ unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */ unsigned char icmp_type, icmp_code; /* type and code from errors */ unsigned short flags; /* control/status flags */ @@ -32,7 +32,7 @@ typedef struct rta_host { double mos; /* Mean opinion score */ double score; /* score */ - unsigned int last_tdiff; + time_t last_tdiff; unsigned int last_icmp_seq; /* Last ICMP_SEQ to check out of order pkts */ unsigned char pl; /* measured packet loss */ @@ -71,3 +71,6 @@ typedef struct { } rta_host_create_wrapper; rta_host_create_wrapper rta_host_create(char *name, struct sockaddr_storage *address); +unsigned int ping_target_list_append(ping_target *list, ping_target *elem); + +void check_icmp_timeout_handler(int, siginfo_t *, void *); diff --git a/plugins-root/check_icmp.d/config.h b/plugins-root/check_icmp.d/config.h new file mode 100644 index 00000000..deae9bec --- /dev/null +++ b/plugins-root/check_icmp.d/config.h @@ -0,0 +1,102 @@ +#pragma once + +#include "../../config.h" +#include "../../lib/states.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "./check_icmp_helpers.h" + +/* threshold structure. all values are maximum allowed, exclusive */ +typedef struct threshold { + unsigned char pl; /* max allowed packet loss in percent */ + unsigned int rta; /* roundtrip time average, microseconds */ + double jitter; /* jitter time average, microseconds */ + double mos; /* MOS */ + double score; /* Score */ +} threshold; + +typedef struct { + char *source_ip; + + bool order_mode; + bool mos_mode; + bool rta_mode; + bool pl_mode; + bool jitter_mode; + bool score_mode; + + int min_hosts_alive; + unsigned short icmp_data_size; + unsigned short icmp_pkt_size; + unsigned int pkt_interval; + unsigned int target_interval; + threshold crit; + threshold warn; + pid_t pid; + + int mode; + unsigned long ttl; + + unsigned short packets; + + unsigned short number_of_targets; + ping_target *targets; + + unsigned short number_of_hosts; + check_icmp_target_container *hosts; +} check_icmp_config; + +check_icmp_config check_icmp_config_init(); + +/* the data structure */ +typedef struct icmp_ping_data { + struct timeval stime; /* timestamp (saved in protocol struct as well) */ + unsigned short ping_id; +} icmp_ping_data; + +#define MAX_IP_PKT_SIZE 65536 /* (theoretical) max IP packet size */ +#define IP_HDR_SIZE 20 +#define MAX_PING_DATA (MAX_IP_PKT_SIZE - IP_HDR_SIZE - ICMP_MINLEN) +#define MIN_PING_DATA_SIZE sizeof(struct icmp_ping_data) +#define DEFAULT_PING_DATA_SIZE (MIN_PING_DATA_SIZE + 44) + +/* 80 msec packet interval by default */ +#define DEFAULT_PKT_INTERVAL 80000 +#define DEFAULT_TARGET_INTERVAL 0 + +#define DEFAULT_WARN_RTA 200000 +#define DEFAULT_CRIT_RTA 500000 +#define DEFAULT_WARN_PL 40 +#define DEFAULT_CRIT_PL 80 + +#define DEFAULT_TIMEOUT 10 +#define DEFAULT_TTL 64 + +/* the different modes of this program are as follows: + * MODE_RTA: send all packets no matter what (mimic check_icmp and check_ping) + * MODE_HOSTCHECK: Return immediately upon any sign of life + * In addition, sends packets to ALL addresses assigned + * to this host (as returned by gethostbyname() or + * gethostbyaddr() and expects one host only to be checked at + * a time. Therefore, any packet response what so ever will + * count as a sign of life, even when received outside + * crit.rta limit. Do not misspell any additional IP's. + * MODE_ALL: Requires packets from ALL requested IP to return OK (default). + * MODE_ICMP: implement something similar to check_icmp (MODE_RTA without + * tcp and udp args does this) + */ +#define MODE_RTA 0 +#define MODE_HOSTCHECK 1 +#define MODE_ALL 2 +#define MODE_ICMP 3 + +#define DEFAULT_NUMBER_OF_PACKETS 5 + +#define PACKET_BACKOFF_FACTOR 1.5 +#define TARGET_BACKOFF_FACTOR 1.5 -- cgit v1.2.3-74-g34f1 From 5fd8191a50df6be712c9143ca6d73de7878f57d1 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 5 May 2025 22:52:56 +0200 Subject: WIP - check_icmp refactor 3 --- plugins-root/check_icmp.c | 150 ++++++++++++------------- plugins-root/check_icmp.d/check_icmp_helpers.c | 25 +++-- plugins-root/check_icmp.d/config.h | 58 +++++----- 3 files changed, 118 insertions(+), 115 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 99414014..9d163678 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -142,37 +142,38 @@ static void set_source_ip(char * /*arg*/, int icmp_sock); /* Receiving data */ static int wait_for_reply(int socket, time_t time_interval, unsigned short icmp_pkt_size, - unsigned int *pkt_interval, unsigned int *target_interval, pid_t pid, - ping_target **table, unsigned short packets, + unsigned int *pkt_interval, unsigned int *target_interval, + uint16_t sender_id, ping_target **table, unsigned short packets, unsigned short number_of_targets, check_icmp_state *program_state); static ssize_t recvfrom_wto(int /*sock*/, void * /*buf*/, unsigned int /*len*/, struct sockaddr * /*saddr*/, time_t *timeout, struct timeval * /*tv*/); static int handle_random_icmp(unsigned char * /*packet*/, struct sockaddr_storage * /*addr*/, - unsigned int *pkt_interval, unsigned int *target_interval, pid_t pid, + unsigned int *pkt_interval, unsigned int *target_interval, uint16_t sender_id, ping_target **table, unsigned short packets, unsigned short number_of_targets, check_icmp_state *program_state); /* Sending data */ static int send_icmp_ping(int /*sock*/, ping_target * /*host*/, unsigned short icmp_pkt_size, - pid_t pid, check_icmp_state *program_state); + uint16_t sender_id, check_icmp_state *program_state); /* Threshold related */ -static int get_threshold(char *str, threshold *threshold); -static bool get_threshold2(char *str, size_t length, threshold * /*warn*/, threshold * /*crit*/, - threshold_mode mode); -static bool parse_threshold2_helper(char *threshold_string, size_t length, threshold *thr, - threshold_mode mode); +static int get_threshold(char *str, check_icmp_threshold *threshold); +static bool get_threshold2(char *str, size_t length, check_icmp_threshold * /*warn*/, + check_icmp_threshold * /*crit*/, threshold_mode mode); +static bool parse_threshold2_helper(char *threshold_string, size_t length, + check_icmp_threshold *thr, threshold_mode mode); /* main test function */ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, bool jitter_mode, bool score_mode, int min_hosts_alive, unsigned short icmp_pkt_size, unsigned int *pkt_interval, - unsigned int *target_interval, threshold warn, threshold crit, pid_t pid, - int mode, unsigned int max_completion_time, struct timeval prog_start, - ping_target **table, unsigned short packets, int icmp_sock, - unsigned short number_of_targets, check_icmp_state *program_state, - ping_target *target_list); + unsigned int *target_interval, check_icmp_threshold warn, + check_icmp_threshold crit, uint16_t sender_id, + check_icmp_execution_mode mode, unsigned int max_completion_time, + struct timeval prog_start, ping_target **table, unsigned short packets, + int icmp_sock, unsigned short number_of_targets, + check_icmp_state *program_state, ping_target *target_list); /* Target aquisition */ typedef struct { @@ -190,13 +191,14 @@ static add_target_ip_wrapper add_target_ip(char * /*arg*/, struct sockaddr_stora static void parse_address(struct sockaddr_storage * /*addr*/, char * /*address*/, socklen_t size); -static unsigned short icmp_checksum(uint16_t * /*p*/, size_t /*n*/); +static unsigned short icmp_checksum(uint16_t *packet, size_t packet_size); /* End of run function */ static void finish(int /*sig*/, bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, - bool jitter_mode, bool score_mode, int min_hosts_alive, threshold warn, - threshold crit, int icmp_sock, unsigned short number_of_targets, - check_icmp_state *program_state, ping_target *target_list); + bool jitter_mode, bool score_mode, int min_hosts_alive, + check_icmp_threshold warn, check_icmp_threshold crit, int icmp_sock, + unsigned short number_of_targets, check_icmp_state *program_state, + ping_target *target_list); /* Error exit */ static void crash(const char * /*fmt*/, ...); @@ -239,21 +241,21 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { /* use the pid to mark packets as ours */ /* Some systems have 32-bit pid_t so mask off only 16 bits */ - result.config.pid = getpid() & 0xffff; + result.config.sender_id = getpid() & 0xffff; if (!strcmp(progname, "check_icmp") || !strcmp(progname, "check_ping")) { result.config.mode = MODE_ICMP; } else if (!strcmp(progname, "check_host")) { result.config.mode = MODE_HOSTCHECK; result.config.pkt_interval = 1000000; - result.config.packets = 5; + result.config.number_of_packets = 5; result.config.crit.rta = result.config.warn.rta = 1000000; result.config.crit.pl = result.config.warn.pl = 100; } else if (!strcmp(progname, "check_rta_multi")) { result.config.mode = MODE_ALL; result.config.target_interval = 0; result.config.pkt_interval = 50000; - result.config.packets = 5; + result.config.number_of_packets = 5; } /* support "--help" and "--version" */ if (argc == 2) { @@ -279,14 +281,10 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { address_family = AF_INET; break; case '6': -#ifdef USE_IPV6 if (address_family != -1) { crash("Multiple protocol versions not supported"); } address_family = AF_INET6; -#else - usage(_("IPv6 support not available\n")); -#endif break; case 'H': { result.config.number_of_hosts++; @@ -351,10 +349,10 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { break; case 'n': case 'p': - result.config.packets = (unsigned short)strtoul(optarg, NULL, 0); - if (result.config.packets > 20) { + result.config.number_of_packets = (unsigned short)strtoul(optarg, NULL, 0); + if (result.config.number_of_packets > 20) { errno = 0; - crash("packets is > 20 (%d)", result.config.packets); + crash("packets is > 20 (%d)", result.config.number_of_packets); } break; case 't': @@ -599,18 +597,18 @@ static const char *get_icmp_error_msg(unsigned char icmp_type, unsigned char icm static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr, unsigned int *pkt_interval, unsigned int *target_interval, - const pid_t pid, ping_target **table, unsigned short packets, + const uint16_t sender_id, ping_target **table, unsigned short packets, const unsigned short number_of_targets, check_icmp_state *program_state) { - struct icmp p; - memcpy(&p, packet, sizeof(p)); - if (p.icmp_type == ICMP_ECHO && ntohs(p.icmp_id) == pid) { + struct icmp icmp_packet; + memcpy(&icmp_packet, packet, sizeof(icmp_packet)); + if (icmp_packet.icmp_type == ICMP_ECHO && ntohs(icmp_packet.icmp_id) == sender_id) { /* echo request from us to us (pinging localhost) */ return 0; } if (debug) { - printf("handle_random_icmp(%p, %p)\n", (void *)&p, (void *)addr); + printf("handle_random_icmp(%p, %p)\n", (void *)&icmp_packet, (void *)addr); } /* only handle a few types, since others can't possibly be replies to @@ -623,8 +621,8 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad * TIMXCEED actually sends a proper icmp response we will have passed * too many hops to have a hope of reaching it later, in which case it * indicates overconfidence in the network, poor routing or both. */ - if (p.icmp_type != ICMP_UNREACH && p.icmp_type != ICMP_TIMXCEED && - p.icmp_type != ICMP_SOURCEQUENCH && p.icmp_type != ICMP_PARAMPROB) { + if (icmp_packet.icmp_type != ICMP_UNREACH && icmp_packet.icmp_type != ICMP_TIMXCEED && + icmp_packet.icmp_type != ICMP_SOURCEQUENCH && icmp_packet.icmp_type != ICMP_PARAMPROB) { return 0; } @@ -632,7 +630,7 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad * to RFC 792). If it isn't, just ignore it */ struct icmp sent_icmp; memcpy(&sent_icmp, packet + 28, sizeof(sent_icmp)); - if (sent_icmp.icmp_type != ICMP_ECHO || ntohs(sent_icmp.icmp_id) != pid || + if (sent_icmp.icmp_type != ICMP_ECHO || ntohs(sent_icmp.icmp_id) != sender_id || ntohs(sent_icmp.icmp_seq) >= number_of_targets * packets) { if (debug) { printf("Packet is no response to a packet we sent\n"); @@ -646,7 +644,7 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad char address[INET6_ADDRSTRLEN]; parse_address(addr, address, sizeof(address)); printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n", - get_icmp_error_msg(p.icmp_type, p.icmp_code), address, host->name); + get_icmp_error_msg(icmp_packet.icmp_type, icmp_packet.icmp_code), address, host->name); } program_state->icmp_lost++; @@ -658,15 +656,15 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad /* source quench means we're sending too fast, so increase the * interval and mark this packet lost */ - if (p.icmp_type == ICMP_SOURCEQUENCH) { + if (icmp_packet.icmp_type == ICMP_SOURCEQUENCH) { *pkt_interval = (unsigned int)(*pkt_interval * PACKET_BACKOFF_FACTOR); *target_interval = (unsigned int)(*target_interval * TARGET_BACKOFF_FACTOR); } else { program_state->targets_down++; host->flags |= FLAG_LOST_CAUSE; } - host->icmp_type = p.icmp_type; - host->icmp_code = p.icmp_code; + host->icmp_type = icmp_packet.icmp_type; + host->icmp_code = icmp_packet.icmp_code; host->error_addr = *addr; return 0; @@ -772,18 +770,18 @@ int main(int argc, char **argv) { gettimeofday(&prog_start, NULL); unsigned int max_completion_time = - ((config.number_of_targets * config.packets * config.pkt_interval) + + ((config.number_of_targets * config.number_of_packets * config.pkt_interval) + (config.number_of_targets * config.target_interval)) + - (config.number_of_targets * config.packets * config.crit.rta) + config.crit.rta; + (config.number_of_targets * config.number_of_packets * config.crit.rta) + config.crit.rta; if (debug) { printf("packets: %u, targets: %u\n" "target_interval: %0.3f, pkt_interval %0.3f\n" "crit.rta: %0.3f\n" "max_completion_time: %0.3f\n", - config.packets, config.number_of_targets, (float)config.target_interval / 1000, - (float)config.pkt_interval / 1000, (float)config.crit.rta / 1000, - (float)max_completion_time / 1000); + config.number_of_packets, config.number_of_targets, + (float)config.target_interval / 1000, (float)config.pkt_interval / 1000, + (float)config.crit.rta / 1000, (float)max_completion_time / 1000); } if (debug) { @@ -814,7 +812,7 @@ int main(int argc, char **argv) { unsigned short target_index = 0; while (host) { - host->id = target_index * config.packets; + host->id = target_index * config.number_of_packets; table[target_index] = host; host = host->next; target_index++; @@ -827,9 +825,9 @@ int main(int argc, char **argv) { run_checks(config.order_mode, config.mos_mode, config.rta_mode, config.pl_mode, config.jitter_mode, config.score_mode, config.min_hosts_alive, config.icmp_data_size, - &pkt_interval, &target_interval, config.warn, config.crit, config.pid, config.mode, - max_completion_time, prog_start, table, config.packets, icmp_sock, - config.number_of_targets, &program_state, config.targets); + &pkt_interval, &target_interval, config.warn, config.crit, config.sender_id, + config.mode, max_completion_time, prog_start, table, config.number_of_packets, + icmp_sock, config.number_of_targets, &program_state, config.targets); errno = 0; finish(0, config.order_mode, config.mos_mode, config.rta_mode, config.pl_mode, @@ -842,8 +840,9 @@ int main(int argc, char **argv) { static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, bool jitter_mode, bool score_mode, int min_hosts_alive, unsigned short icmp_pkt_size, unsigned int *pkt_interval, - unsigned int *target_interval, threshold warn, threshold crit, - const pid_t pid, const int mode, const unsigned int max_completion_time, + unsigned int *target_interval, check_icmp_threshold warn, + check_icmp_threshold crit, const uint16_t sender_id, + const check_icmp_execution_mode mode, const unsigned int max_completion_time, const struct timeval prog_start, ping_target **table, const unsigned short packets, const int icmp_sock, const unsigned short number_of_targets, check_icmp_state *program_state, @@ -867,14 +866,15 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo } /* we're still in the game, so send next packet */ - (void)send_icmp_ping(icmp_sock, table[target_index], icmp_pkt_size, pid, program_state); + (void)send_icmp_ping(icmp_sock, table[target_index], icmp_pkt_size, sender_id, + program_state); /* wrap up if all targets are declared dead */ if (targets_alive(number_of_targets, program_state->targets_down) || get_timevaldiff(prog_start, prog_start) < max_completion_time || !(mode == MODE_HOSTCHECK && program_state->targets_down)) { wait_for_reply(icmp_sock, *target_interval, icmp_pkt_size, pkt_interval, - target_interval, pid, table, packets, number_of_targets, + target_interval, sender_id, table, packets, number_of_targets, program_state); } } @@ -882,8 +882,8 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo get_timevaldiff_to_now(prog_start) < max_completion_time || !(mode == MODE_HOSTCHECK && program_state->targets_down)) { wait_for_reply(icmp_sock, *pkt_interval * number_of_targets, icmp_pkt_size, - pkt_interval, target_interval, pid, table, packets, number_of_targets, - program_state); + pkt_interval, target_interval, sender_id, table, packets, + number_of_targets, program_state); } } @@ -915,8 +915,8 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo if (targets_alive(number_of_targets, program_state->targets_down) || get_timevaldiff_to_now(prog_start) < max_completion_time || !(mode == MODE_HOSTCHECK && program_state->targets_down)) { - wait_for_reply(icmp_sock, final_wait, icmp_pkt_size, pkt_interval, target_interval, pid, - table, packets, number_of_targets, program_state); + wait_for_reply(icmp_sock, final_wait, icmp_pkt_size, pkt_interval, target_interval, + sender_id, table, packets, number_of_targets, program_state); } } } @@ -932,8 +932,8 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo * icmp echo reply : the rest */ static int wait_for_reply(int sock, const time_t time_interval, unsigned short icmp_pkt_size, - unsigned int *pkt_interval, unsigned int *target_interval, pid_t pid, - ping_target **table, const unsigned short packets, + unsigned int *pkt_interval, unsigned int *target_interval, + uint16_t sender_id, ping_target **table, const unsigned short packets, const unsigned short number_of_targets, check_icmp_state *program_state) { union icmp_packet packet; if (!(packet.buf = malloc(icmp_pkt_size))) { @@ -1027,16 +1027,16 @@ static int wait_for_reply(int sock, const time_t time_interval, unsigned short i : sizeof(struct icmp));*/ if ((address_family == PF_INET && - (ntohs(packet.icp->icmp_id) != pid || packet.icp->icmp_type != ICMP_ECHOREPLY || + (ntohs(packet.icp->icmp_id) != sender_id || packet.icp->icmp_type != ICMP_ECHOREPLY || ntohs(packet.icp->icmp_seq) >= number_of_targets * packets)) || (address_family == PF_INET6 && - (ntohs(packet.icp6->icmp6_id) != pid || packet.icp6->icmp6_type != ICMP6_ECHO_REPLY || + (ntohs(packet.icp6->icmp6_id) != sender_id || packet.icp6->icmp6_type != ICMP6_ECHO_REPLY || ntohs(packet.icp6->icmp6_seq) >= number_of_targets * packets))) { if (debug > 2) { printf("not a proper ICMP_ECHOREPLY\n"); } - handle_random_icmp(buf + hlen, &resp_addr, pkt_interval, target_interval, pid, table, + handle_random_icmp(buf + hlen, &resp_addr, pkt_interval, target_interval, sender_id, table, packets, number_of_targets, program_state); continue; @@ -1136,7 +1136,7 @@ static int wait_for_reply(int sock, const time_t time_interval, unsigned short i /* the ping functions */ static int send_icmp_ping(const int sock, ping_target *host, const unsigned short icmp_pkt_size, - const pid_t pid, check_icmp_state *program_state) { + const uint16_t sender_id, check_icmp_state *program_state) { if (sock == -1) { errno = 0; crash("Attempt to send on bogus socket"); @@ -1174,7 +1174,7 @@ static int send_icmp_ping(const int sock, ping_target *host, const unsigned shor icp->icmp_type = ICMP_ECHO; icp->icmp_code = 0; icp->icmp_cksum = 0; - icp->icmp_id = htons((uint16_t)pid); + icp->icmp_id = htons((uint16_t)sender_id); icp->icmp_seq = htons(host->id++); icp->icmp_cksum = icmp_checksum((uint16_t *)buf, (size_t)icmp_pkt_size); @@ -1192,7 +1192,7 @@ static int send_icmp_ping(const int sock, ping_target *host, const unsigned shor icp6->icmp6_type = ICMP6_ECHO_REQUEST; icp6->icmp6_code = 0; icp6->icmp6_cksum = 0; - icp6->icmp6_id = htons((uint16_t)pid); + icp6->icmp6_id = htons((uint16_t)sender_id); icp6->icmp6_seq = htons(host->id++); // let checksum be calculated automatically @@ -1330,9 +1330,10 @@ static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len, } static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, - bool jitter_mode, bool score_mode, int min_hosts_alive, threshold warn, - threshold crit, const int icmp_sock, const unsigned short number_of_targets, - check_icmp_state *program_state, ping_target *target_list) { + bool jitter_mode, bool score_mode, int min_hosts_alive, + check_icmp_threshold warn, check_icmp_threshold crit, const int icmp_sock, + const unsigned short number_of_targets, check_icmp_state *program_state, + ping_target *target_list) { // Deactivate alarm alarm(0); @@ -1821,13 +1822,12 @@ static add_target_wrapper add_target(char *arg, const int mode) { address_family = AF_INET; sin = (struct sockaddr_in *)&address_storage; error_code = inet_pton(address_family, arg, &sin->sin_addr); -#ifdef USE_IPV6 + if (error_code != 1) { address_family = AF_INET6; sin6 = (struct sockaddr_in6 *)&address_storage; error_code = inet_pton(address_family, arg, &sin6->sin6_addr); } -#endif /* If we don't find any valid addresses, we still don't know the address_family */ if (error_code != 1) { address_family = -1; @@ -2029,7 +2029,7 @@ static unsigned int get_timevar(const char *str) { } /* not too good at checking errors, but it'll do (main() should barfe on -1) */ -static int get_threshold(char *str, threshold *threshold) { +static int get_threshold(char *str, check_icmp_threshold *threshold) { if (!str || !strlen(str) || !threshold) { return -1; } @@ -2075,8 +2075,8 @@ static int get_threshold(char *str, threshold *threshold) { * @param[in] mode Determines whether this a threshold for rta, packet_loss, jitter, mos or score * (exclusively) */ -static bool get_threshold2(char *str, size_t length, threshold *warn, threshold *crit, - threshold_mode mode) { +static bool get_threshold2(char *str, size_t length, check_icmp_threshold *warn, + check_icmp_threshold *crit, threshold_mode mode) { if (!str || !length || !warn || !crit) { return false; } @@ -2106,8 +2106,8 @@ static bool get_threshold2(char *str, size_t length, threshold *warn, threshold return parse_threshold2_helper(work_pointer, strlen(work_pointer), warn, mode); } -static bool parse_threshold2_helper(char *threshold_string, size_t length, threshold *thr, - threshold_mode mode) { +static bool parse_threshold2_helper(char *threshold_string, size_t length, + check_icmp_threshold *thr, threshold_mode mode) { char *resultChecker = {0}; switch (mode) { diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.c b/plugins-root/check_icmp.d/check_icmp_helpers.c index 2efe6e59..2a521b04 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.c +++ b/plugins-root/check_icmp.d/check_icmp_helpers.c @@ -10,8 +10,6 @@ unsigned int timeout = DEFAULT_TIMEOUT; check_icmp_config check_icmp_config_init() { check_icmp_config tmp = { - .source_ip = NULL, - .order_mode = false, .mos_mode = false, .rta_mode = false, @@ -20,10 +18,6 @@ check_icmp_config check_icmp_config_init() { .score_mode = false, .min_hosts_alive = -1, - .icmp_data_size = DEFAULT_PING_DATA_SIZE, - .icmp_pkt_size = DEFAULT_PING_DATA_SIZE + ICMP_MINLEN, - .pkt_interval = DEFAULT_PKT_INTERVAL, - .target_interval = 0, .crit = {.pl = DEFAULT_CRIT_PL, .rta = DEFAULT_CRIT_RTA, .jitter = 50.0, @@ -34,11 +28,18 @@ check_icmp_config check_icmp_config_init() { .jitter = 40.0, .mos = 3.5, .score = 80.0}, - .pid = {}, - .mode = MODE_RTA, + .ttl = DEFAULT_TTL, + .icmp_data_size = DEFAULT_PING_DATA_SIZE, + .icmp_pkt_size = DEFAULT_PING_DATA_SIZE + ICMP_MINLEN, + .pkt_interval = DEFAULT_PKT_INTERVAL, + .target_interval = 0, + .number_of_packets = DEFAULT_NUMBER_OF_PACKETS, + .source_ip = NULL, + + .sender_id = {}, - .packets = DEFAULT_NUMBER_OF_PACKETS, + .mode = MODE_RTA, .number_of_targets = 0, .targets = NULL, @@ -168,10 +169,10 @@ unsigned int ping_target_list_append(ping_target *list, ping_target *elem) { return result; } -void check_icmp_timeout_handler(int signal, siginfo_t * info, void *ucontext) { +void check_icmp_timeout_handler(int signal, siginfo_t *info, void *ucontext) { // Ignore unused arguments - (void) info; - (void) ucontext; + (void)info; + (void)ucontext; mp_subcheck timeout_sc = mp_subcheck_init(); timeout_sc = mp_set_subcheck_state(timeout_sc, socket_timeout_state); diff --git a/plugins-root/check_icmp.d/config.h b/plugins-root/check_icmp.d/config.h index deae9bec..3599c0f0 100644 --- a/plugins-root/check_icmp.d/config.h +++ b/plugins-root/check_icmp.d/config.h @@ -10,20 +10,38 @@ #include #include #include +#include #include "./check_icmp_helpers.h" /* threshold structure. all values are maximum allowed, exclusive */ -typedef struct threshold { +typedef struct { unsigned char pl; /* max allowed packet loss in percent */ unsigned int rta; /* roundtrip time average, microseconds */ double jitter; /* jitter time average, microseconds */ double mos; /* MOS */ double score; /* Score */ -} threshold; +} check_icmp_threshold; -typedef struct { - char *source_ip; +/* the different modes of this program are as follows: + * MODE_RTA: send all packets no matter what (mimic check_icmp and check_ping) + * MODE_HOSTCHECK: Return immediately upon any sign of life + * In addition, sends packets to ALL addresses assigned + * to this host (as returned by gethostbyname() or + * gethostbyaddr() and expects one host only to be checked at + * a time. Therefore, any packet response what so ever will + * count as a sign of life, even when received outside + * crit.rta limit. Do not misspell any additional IP's. + * MODE_ALL: Requires packets from ALL requested IP to return OK (default). + * MODE_ICMP: Default Mode + */ +typedef enum { + MODE_RTA, + MODE_HOSTCHECK, + MODE_ALL, + MODE_ICMP, +} check_icmp_execution_mode; +typedef struct { bool order_mode; bool mos_mode; bool rta_mode; @@ -32,18 +50,20 @@ typedef struct { bool score_mode; int min_hosts_alive; + check_icmp_threshold crit; + check_icmp_threshold warn; + + unsigned long ttl; unsigned short icmp_data_size; unsigned short icmp_pkt_size; unsigned int pkt_interval; unsigned int target_interval; - threshold crit; - threshold warn; - pid_t pid; + unsigned short number_of_packets; + char *source_ip; - int mode; - unsigned long ttl; + uint16_t sender_id; // PID of the main process, which is used as an ID in packets - unsigned short packets; + check_icmp_execution_mode mode; unsigned short number_of_targets; ping_target *targets; @@ -78,24 +98,6 @@ typedef struct icmp_ping_data { #define DEFAULT_TIMEOUT 10 #define DEFAULT_TTL 64 -/* the different modes of this program are as follows: - * MODE_RTA: send all packets no matter what (mimic check_icmp and check_ping) - * MODE_HOSTCHECK: Return immediately upon any sign of life - * In addition, sends packets to ALL addresses assigned - * to this host (as returned by gethostbyname() or - * gethostbyaddr() and expects one host only to be checked at - * a time. Therefore, any packet response what so ever will - * count as a sign of life, even when received outside - * crit.rta limit. Do not misspell any additional IP's. - * MODE_ALL: Requires packets from ALL requested IP to return OK (default). - * MODE_ICMP: implement something similar to check_icmp (MODE_RTA without - * tcp and udp args does this) - */ -#define MODE_RTA 0 -#define MODE_HOSTCHECK 1 -#define MODE_ALL 2 -#define MODE_ICMP 3 - #define DEFAULT_NUMBER_OF_PACKETS 5 #define PACKET_BACKOFF_FACTOR 1.5 -- cgit v1.2.3-74-g34f1 From 9ebde5eb09dbf4b869ffd6f501d007b9b264e1a9 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Tue, 6 May 2025 00:01:42 +0200 Subject: WIP - check_icmp refactor 4 --- plugins-root/check_icmp.c | 220 +++++++++++++++++++++++++++++++--------------- 1 file changed, 147 insertions(+), 73 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 9d163678..94f20eec 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -149,20 +149,37 @@ static int wait_for_reply(int socket, time_t time_interval, unsigned short icmp_ static ssize_t recvfrom_wto(int /*sock*/, void * /*buf*/, unsigned int /*len*/, struct sockaddr * /*saddr*/, time_t *timeout, struct timeval * /*tv*/); static int handle_random_icmp(unsigned char * /*packet*/, struct sockaddr_storage * /*addr*/, - unsigned int *pkt_interval, unsigned int *target_interval, uint16_t sender_id, - ping_target **table, unsigned short packets, + unsigned int *pkt_interval, unsigned int *target_interval, + uint16_t sender_id, ping_target **table, unsigned short packets, unsigned short number_of_targets, check_icmp_state *program_state); /* Sending data */ -static int send_icmp_ping(int /*sock*/, ping_target * /*host*/, unsigned short icmp_pkt_size, +static int send_icmp_ping(int socket, ping_target *host, unsigned short icmp_pkt_size, uint16_t sender_id, check_icmp_state *program_state); /* Threshold related */ -static int get_threshold(char *str, check_icmp_threshold *threshold); -static bool get_threshold2(char *str, size_t length, check_icmp_threshold * /*warn*/, - check_icmp_threshold * /*crit*/, threshold_mode mode); -static bool parse_threshold2_helper(char *threshold_string, size_t length, - check_icmp_threshold *thr, threshold_mode mode); +typedef struct { + int errorcode; + check_icmp_threshold threshold; +} get_threshold_wrapper; +static get_threshold_wrapper get_threshold(char *str, check_icmp_threshold threshold); + +typedef struct { + int errorcode; + check_icmp_threshold warn; + check_icmp_threshold crit; +} get_threshold2_wrapper; +static get_threshold2_wrapper get_threshold2(char *str, size_t length, check_icmp_threshold warn, + check_icmp_threshold crit, threshold_mode mode); + +typedef struct { + int errorcode; + check_icmp_threshold result; +} parse_threshold2_helper_wrapper; +static parse_threshold2_helper_wrapper parse_threshold2_helper(char *threshold_string, + size_t length, + check_icmp_threshold thr, + threshold_mode mode); /* main test function */ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, @@ -314,7 +331,6 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { /* Reset argument scanning */ optind = 1; - bool err; /* parse the arguments */ for (int i = 1; i < argc; i++) { long int arg; @@ -341,12 +357,22 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { case 'I': result.config.target_interval = get_timevar(optarg); break; - case 'w': - get_threshold(optarg, &result.config.warn); - break; - case 'c': - get_threshold(optarg, &result.config.crit); - break; + case 'w': { + get_threshold_wrapper warn = get_threshold(optarg, result.config.warn); + if (warn.errorcode == OK) { + result.config.warn = warn.threshold; + } else { + crash("failed to parse warning threshold"); + } + } break; + case 'c': { + get_threshold_wrapper crit = get_threshold(optarg, result.config.crit); + if (crit.errorcode == OK) { + result.config.crit = crit.threshold; + } else { + crash("failed to parse critical threshold"); + } + } break; case 'n': case 'p': result.config.number_of_packets = (unsigned short)strtoul(optarg, NULL, 0); @@ -387,51 +413,65 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { print_help(); exit(STATE_UNKNOWN); break; - case 'R': /* RTA mode */ - err = get_threshold2(optarg, strlen(optarg), &result.config.warn, - &result.config.crit, const_rta_mode); - if (!err) { + case 'R': /* RTA mode */ { + get_threshold2_wrapper rta_th = get_threshold2( + optarg, strlen(optarg), result.config.warn, result.config.crit, const_rta_mode); + + if (rta_th.errorcode != OK) { crash("Failed to parse RTA threshold"); } + result.config.warn = rta_th.warn; + result.config.crit = rta_th.crit; result.config.rta_mode = true; - break; - case 'P': /* packet loss mode */ - err = get_threshold2(optarg, strlen(optarg), &result.config.warn, - &result.config.crit, const_packet_loss_mode); - if (!err) { + } break; + case 'P': /* packet loss mode */ { + get_threshold2_wrapper pl_th = + get_threshold2(optarg, strlen(optarg), result.config.warn, result.config.crit, + const_packet_loss_mode); + if (pl_th.errorcode != OK) { crash("Failed to parse packet loss threshold"); } + result.config.warn = pl_th.warn; + result.config.crit = pl_th.crit; result.config.pl_mode = true; - break; - case 'J': /* jitter mode */ - err = get_threshold2(optarg, strlen(optarg), &result.config.warn, - &result.config.crit, const_jitter_mode); - if (!err) { + } break; + case 'J': /* jitter mode */ { + get_threshold2_wrapper jitter_th = + get_threshold2(optarg, strlen(optarg), result.config.warn, result.config.crit, + const_jitter_mode); + if (jitter_th.errorcode != OK) { crash("Failed to parse jitter threshold"); } + result.config.warn = jitter_th.warn; + result.config.crit = jitter_th.crit; result.config.jitter_mode = true; - break; - case 'M': /* MOS mode */ - err = get_threshold2(optarg, strlen(optarg), &result.config.warn, - &result.config.crit, const_mos_mode); - if (!err) { + } break; + case 'M': /* MOS mode */ { + get_threshold2_wrapper mos_th = get_threshold2( + optarg, strlen(optarg), result.config.warn, result.config.crit, const_mos_mode); + if (mos_th.errorcode != OK) { crash("Failed to parse MOS threshold"); } + result.config.warn = mos_th.warn; + result.config.crit = mos_th.crit; result.config.mos_mode = true; - break; - case 'S': /* score mode */ - err = get_threshold2(optarg, strlen(optarg), &result.config.warn, - &result.config.crit, const_score_mode); - if (!err) { + } break; + case 'S': /* score mode */ { + get_threshold2_wrapper score_th = + get_threshold2(optarg, strlen(optarg), result.config.warn, result.config.crit, + const_score_mode); + if (score_th.errorcode != OK) { crash("Failed to parse score threshold"); } + result.config.warn = score_th.warn; + result.config.crit = score_th.crit; result.config.score_mode = true; - break; + } break; case 'O': /* out of order mode */ result.config.order_mode = true; break; @@ -644,7 +684,8 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad char address[INET6_ADDRSTRLEN]; parse_address(addr, address, sizeof(address)); printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n", - get_icmp_error_msg(icmp_packet.icmp_type, icmp_packet.icmp_code), address, host->name); + get_icmp_error_msg(icmp_packet.icmp_type, icmp_packet.icmp_code), address, + host->name); } program_state->icmp_lost++; @@ -1030,14 +1071,15 @@ static int wait_for_reply(int sock, const time_t time_interval, unsigned short i (ntohs(packet.icp->icmp_id) != sender_id || packet.icp->icmp_type != ICMP_ECHOREPLY || ntohs(packet.icp->icmp_seq) >= number_of_targets * packets)) || (address_family == PF_INET6 && - (ntohs(packet.icp6->icmp6_id) != sender_id || packet.icp6->icmp6_type != ICMP6_ECHO_REPLY || + (ntohs(packet.icp6->icmp6_id) != sender_id || + packet.icp6->icmp6_type != ICMP6_ECHO_REPLY || ntohs(packet.icp6->icmp6_seq) >= number_of_targets * packets))) { if (debug > 2) { printf("not a proper ICMP_ECHOREPLY\n"); } - handle_random_icmp(buf + hlen, &resp_addr, pkt_interval, target_interval, sender_id, table, - packets, number_of_targets, program_state); + handle_random_icmp(buf + hlen, &resp_addr, pkt_interval, target_interval, sender_id, + table, packets, number_of_targets, program_state); continue; } @@ -2029,9 +2071,15 @@ static unsigned int get_timevar(const char *str) { } /* not too good at checking errors, but it'll do (main() should barfe on -1) */ -static int get_threshold(char *str, check_icmp_threshold *threshold) { - if (!str || !strlen(str) || !threshold) { - return -1; +static get_threshold_wrapper get_threshold(char *str, check_icmp_threshold threshold) { + get_threshold_wrapper result = { + .errorcode = OK, + .threshold = threshold, + }; + + if (!str || !strlen(str)) { + result.errorcode = ERROR; + return result; } /* pointer magic slims code by 10 lines. i is bof-stop on stupid libc's */ @@ -2042,26 +2090,27 @@ static int get_threshold(char *str, check_icmp_threshold *threshold) { *tmp = '\0'; } else if (*tmp == ',' && is_at_last_char) { *tmp = '\0'; /* reset it so get_timevar(str) works nicely later */ - threshold->pl = (unsigned char)strtoul(tmp + 1, NULL, 0); + result.threshold.pl = (unsigned char)strtoul(tmp + 1, NULL, 0); break; } is_at_last_char = true; tmp--; } - threshold->rta = get_timevar(str); + result.threshold.rta = get_timevar(str); - if (!threshold->rta) { - return -1; + if (!result.threshold.rta) { + result.errorcode = ERROR; + return result; } - if (threshold->rta > MAXTTL * 1000000) { - threshold->rta = MAXTTL * 1000000; + if (result.threshold.rta > MAXTTL * 1000000) { + result.threshold.rta = MAXTTL * 1000000; } - if (threshold->pl > 100) { - threshold->pl = 100; + if (result.threshold.pl > 100) { + result.threshold.pl = 100; } - return 0; + return result; } /* @@ -2075,10 +2124,17 @@ static int get_threshold(char *str, check_icmp_threshold *threshold) { * @param[in] mode Determines whether this a threshold for rta, packet_loss, jitter, mos or score * (exclusively) */ -static bool get_threshold2(char *str, size_t length, check_icmp_threshold *warn, - check_icmp_threshold *crit, threshold_mode mode) { - if (!str || !length || !warn || !crit) { - return false; +static get_threshold2_wrapper get_threshold2(char *str, size_t length, check_icmp_threshold warn, + check_icmp_threshold crit, threshold_mode mode) { + get_threshold2_wrapper result = { + .errorcode = OK, + .warn = warn, + .crit = crit, + }; + + if (!str || !length) { + result.errorcode = ERROR; + return result; } // p points to the last char in str @@ -2095,50 +2151,68 @@ static bool get_threshold2(char *str, size_t length, check_icmp_threshold *warn, char *start_of_value = work_pointer + 1; - if (!parse_threshold2_helper(start_of_value, strlen(start_of_value), crit, mode)) { - return false; + parse_threshold2_helper_wrapper tmp = + parse_threshold2_helper(start_of_value, strlen(start_of_value), result.crit, mode); + if (tmp.errorcode != OK) { + result.errorcode = ERROR; + return result; } + result.crit = tmp.result; } first_iteration = false; work_pointer--; } - return parse_threshold2_helper(work_pointer, strlen(work_pointer), warn, mode); + parse_threshold2_helper_wrapper tmp = + parse_threshold2_helper(work_pointer, strlen(work_pointer), result.warn, mode); + if (tmp.errorcode != OK) { + result.errorcode = ERROR; + } else { + result.warn = tmp.result; + } + return result; } -static bool parse_threshold2_helper(char *threshold_string, size_t length, - check_icmp_threshold *thr, threshold_mode mode) { +static parse_threshold2_helper_wrapper parse_threshold2_helper(char *threshold_string, + size_t length, + check_icmp_threshold thr, + threshold_mode mode) { char *resultChecker = {0}; + parse_threshold2_helper_wrapper result = { + .result = thr, + .errorcode = OK, + }; switch (mode) { case const_rta_mode: - thr->rta = (unsigned int)(strtod(threshold_string, &resultChecker) * 1000); + result.result.rta = (unsigned int)(strtod(threshold_string, &resultChecker) * 1000); break; case const_packet_loss_mode: - thr->pl = (unsigned char)strtoul(threshold_string, &resultChecker, 0); + result.result.pl = (unsigned char)strtoul(threshold_string, &resultChecker, 0); break; case const_jitter_mode: - thr->jitter = strtod(threshold_string, &resultChecker); + result.result.jitter = strtod(threshold_string, &resultChecker); break; case const_mos_mode: - thr->mos = strtod(threshold_string, &resultChecker); + result.result.mos = strtod(threshold_string, &resultChecker); break; case const_score_mode: - thr->score = strtod(threshold_string, &resultChecker); + result.result.score = strtod(threshold_string, &resultChecker); break; } if (resultChecker == threshold_string) { // Failed to parse - return false; + result.errorcode = ERROR; + return result; } if (resultChecker != (threshold_string + length)) { // Trailing symbols - return false; + result.errorcode = ERROR; } - return true; + return result; } unsigned short icmp_checksum(uint16_t *packet, size_t packet_size) { -- cgit v1.2.3-74-g34f1 From 6b86583e0d3db92cc5e87af97f4d204bc0e797f3 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Fri, 16 May 2025 09:07:35 +0200 Subject: WIP - check_icmp refactor 5 --- plugins-root/check_icmp.c | 27 +++++++++++++++----------- plugins-root/check_icmp.d/check_icmp_helpers.c | 4 ++-- plugins-root/check_icmp.d/check_icmp_helpers.h | 4 ++-- 3 files changed, 20 insertions(+), 15 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 94f20eec..8565f32d 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -133,12 +133,12 @@ void print_help(); void print_usage(void); /* Time related */ -static unsigned int get_timevar(const char * /*str*/); +static unsigned int get_timevar(const char *str); static time_t get_timevaldiff(struct timeval earlier, struct timeval later); static time_t get_timevaldiff_to_now(struct timeval earlier); -static in_addr_t get_ip_address(const char * /*ifname*/); -static void set_source_ip(char * /*arg*/, int icmp_sock); +static in_addr_t get_ip_address(const char *ifname); +static void set_source_ip(char *arg, int icmp_sock); /* Receiving data */ static int wait_for_reply(int socket, time_t time_interval, unsigned short icmp_pkt_size, @@ -146,9 +146,9 @@ static int wait_for_reply(int socket, time_t time_interval, unsigned short icmp_ uint16_t sender_id, ping_target **table, unsigned short packets, unsigned short number_of_targets, check_icmp_state *program_state); -static ssize_t recvfrom_wto(int /*sock*/, void * /*buf*/, unsigned int /*len*/, - struct sockaddr * /*saddr*/, time_t *timeout, struct timeval * /*tv*/); -static int handle_random_icmp(unsigned char * /*packet*/, struct sockaddr_storage * /*addr*/, +static ssize_t recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, + time_t *timeout, struct timeval *received_timestamp); +static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr, unsigned int *pkt_interval, unsigned int *target_interval, uint16_t sender_id, ping_target **table, unsigned short packets, unsigned short number_of_targets, check_icmp_state *program_state); @@ -193,20 +193,25 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo check_icmp_state *program_state, ping_target *target_list); /* Target aquisition */ +typedef struct { + int error_code; + check_icmp_target_container host; +} add_host_wrapper; +static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode); typedef struct { int error_code; ping_target *targets; unsigned int number_of_targets; } add_target_wrapper; -static add_target_wrapper add_target(char * /*arg*/, int mode); +static add_target_wrapper add_target(char *arg, check_icmp_execution_mode mode); typedef struct { int error_code; ping_target *target; } add_target_ip_wrapper; -static add_target_ip_wrapper add_target_ip(char * /*arg*/, struct sockaddr_storage * /*in*/); +static add_target_ip_wrapper add_target_ip(char *arg, struct sockaddr_storage *address); -static void parse_address(struct sockaddr_storage * /*addr*/, char * /*address*/, socklen_t size); +static void parse_address(struct sockaddr_storage *addr, char *address, socklen_t size); static unsigned short icmp_checksum(uint16_t *packet, size_t packet_size); @@ -218,7 +223,7 @@ static void finish(int /*sig*/, bool order_mode, bool mos_mode, bool rta_mode, b ping_target *target_list); /* Error exit */ -static void crash(const char * /*fmt*/, ...); +static void crash(const char *fmt, ...); /** global variables **/ static int debug = 0; @@ -1852,7 +1857,7 @@ static add_target_ip_wrapper add_target_ip(char *arg, struct sockaddr_storage *a } /* wrapper for add_target_ip */ -static add_target_wrapper add_target(char *arg, const int mode) { +static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode mode) { struct sockaddr_storage address_storage; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.c b/plugins-root/check_icmp.d/check_icmp_helpers.c index 2a521b04..58e13581 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.c +++ b/plugins-root/check_icmp.d/check_icmp_helpers.c @@ -73,7 +73,7 @@ check_icmp_state check_icmp_state_init() { return tmp; } -rta_host_create_wrapper rta_host_create(char *name, struct sockaddr_storage *address) { +ping_target_create_wrapper ping_target_create(char *name, struct sockaddr_storage *address) { struct sockaddr_in *sin; struct sockaddr_in6 *sin6; if (address_family == AF_INET) { @@ -82,7 +82,7 @@ rta_host_create_wrapper rta_host_create(char *name, struct sockaddr_storage *add sin6 = (struct sockaddr_in6 *)address; } - rta_host_create_wrapper result = { + ping_target_create_wrapper result = { .errorcode = OK, }; diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.h b/plugins-root/check_icmp.d/check_icmp_helpers.h index 7e8a4d9f..3e798f72 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.h +++ b/plugins-root/check_icmp.d/check_icmp_helpers.h @@ -68,9 +68,9 @@ check_icmp_state check_icmp_state_init(); typedef struct { int errorcode; ping_target host; -} rta_host_create_wrapper; +} ping_target_create_wrapper; -rta_host_create_wrapper rta_host_create(char *name, struct sockaddr_storage *address); +ping_target_create_wrapper ping_target_create(char *name, struct sockaddr_storage *address); unsigned int ping_target_list_append(ping_target *list, ping_target *elem); void check_icmp_timeout_handler(int, siginfo_t *, void *); -- cgit v1.2.3-74-g34f1 From 322cd6f829e55a91edbfc42201775afb552b5660 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Sat, 17 May 2025 11:26:27 +0200 Subject: Lib: Add perfdata for char and unsigned char --- lib/perfdata.c | 8 ++++++++ lib/perfdata.h | 4 ++++ plugins-root/Makefile.am | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'plugins-root') diff --git a/lib/perfdata.c b/lib/perfdata.c index f425ffcf..b87de7e0 100644 --- a/lib/perfdata.c +++ b/lib/perfdata.c @@ -257,6 +257,10 @@ mp_perfdata mp_set_pd_value_double(mp_perfdata pd, double value) { return pd; } +mp_perfdata mp_set_pd_value_char(mp_perfdata pd, char value) { return mp_set_pd_value_long_long(pd, (long long)value); } + +mp_perfdata mp_set_pd_value_u_char(mp_perfdata pd, unsigned char value) { return mp_set_pd_value_u_long_long(pd, (unsigned long long)value); } + mp_perfdata mp_set_pd_value_int(mp_perfdata pd, int value) { return mp_set_pd_value_long_long(pd, (long long)value); } mp_perfdata mp_set_pd_value_u_int(mp_perfdata pd, unsigned int value) { return mp_set_pd_value_u_long_long(pd, (unsigned long long)value); } @@ -288,6 +292,10 @@ mp_perfdata_value mp_create_pd_value_double(double value) { mp_perfdata_value mp_create_pd_value_float(float value) { return mp_create_pd_value_double((double)value); } +mp_perfdata_value mp_create_pd_value_char(char value) { return mp_create_pd_value_long_long((long long)value); } + +mp_perfdata_value mp_create_pd_value_u_char(unsigned char value) { return mp_create_pd_value_u_long_long((unsigned long long)value); } + mp_perfdata_value mp_create_pd_value_int(int value) { return mp_create_pd_value_long_long((long long)value); } mp_perfdata_value mp_create_pd_value_u_int(unsigned int value) { return mp_create_pd_value_u_long_long((unsigned long long)value); } diff --git a/lib/perfdata.h b/lib/perfdata.h index cb552678..7fd908a9 100644 --- a/lib/perfdata.h +++ b/lib/perfdata.h @@ -155,6 +155,8 @@ mp_perfdata mp_set_pd_value_u_long_long(mp_perfdata, unsigned long long); _Generic((V), \ float: mp_create_pd_value_float, \ double: mp_create_pd_value_double, \ + char: mp_create_pd_value_char, \ + unsigned char: mp_create_pd_value_u_char, \ int: mp_create_pd_value_int, \ unsigned int: mp_create_pd_value_u_int, \ long: mp_create_pd_value_long, \ @@ -164,6 +166,8 @@ mp_perfdata mp_set_pd_value_u_long_long(mp_perfdata, unsigned long long); mp_perfdata_value mp_create_pd_value_float(float); mp_perfdata_value mp_create_pd_value_double(double); +mp_perfdata_value mp_create_pd_value_char(char); +mp_perfdata_value mp_create_pd_value_u_char(unsigned char); mp_perfdata_value mp_create_pd_value_int(int); mp_perfdata_value mp_create_pd_value_u_int(unsigned int); mp_perfdata_value mp_create_pd_value_long(long); diff --git a/plugins-root/Makefile.am b/plugins-root/Makefile.am index f09f5e07..fffc0575 100644 --- a/plugins-root/Makefile.am +++ b/plugins-root/Makefile.am @@ -91,7 +91,7 @@ pst3_LDFLAGS = @PST3CFLAGS@ # pst3 must not use monitoringplug/gnulib includes! pst3_CPPFLAGS = -check_dhcp_DEPENDENCIES = check_dhcp.c $(NETOBJS) $(DEPLIBS) +check_dhcp_DEPENDENCIES = check_dhcp.c $(NETOBJS) $(DEPLIBS) check_icmp_DEPENDENCIES = check_icmp.c $(NETOBJS) clean-local: -- cgit v1.2.3-74-g34f1 From a01d522c4cac11eb31510758d42fe744eb21471d Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Sat, 17 May 2025 11:26:54 +0200 Subject: WIP - check_icmp refactor 6 --- plugins-root/check_icmp.c | 704 ++++++++++++------------- plugins-root/check_icmp.d/check_icmp_helpers.c | 22 +- plugins-root/check_icmp.d/check_icmp_helpers.h | 13 +- plugins-root/check_icmp.d/config.h | 4 + 4 files changed, 360 insertions(+), 383 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 8565f32d..34adf6fe 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -46,6 +46,8 @@ const char *email = "devel@monitoring-plugins.org"; #include "../plugins/common.h" #include "netutils.h" #include "utils.h" +#include "output.h" +#include "perfdata.h" #if HAVE_SYS_SOCKIO_H # include @@ -182,8 +184,7 @@ static parse_threshold2_helper_wrapper parse_threshold2_helper(char *threshold_s threshold_mode mode); /* main test function */ -static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, - bool jitter_mode, bool score_mode, int min_hosts_alive, +static void run_checks(check_icmp_mode_switches modes, int min_hosts_alive, unsigned short icmp_pkt_size, unsigned int *pkt_interval, unsigned int *target_interval, check_icmp_threshold warn, check_icmp_threshold crit, uint16_t sender_id, @@ -191,6 +192,8 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo struct timeval prog_start, ping_target **table, unsigned short packets, int icmp_sock, unsigned short number_of_targets, check_icmp_state *program_state, ping_target *target_list); +mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, + check_icmp_threshold warn, check_icmp_threshold crit); /* Target aquisition */ typedef struct { @@ -198,6 +201,7 @@ typedef struct { check_icmp_target_container host; } add_host_wrapper; static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode); + typedef struct { int error_code; ping_target *targets; @@ -216,11 +220,10 @@ static void parse_address(struct sockaddr_storage *addr, char *address, socklen_ static unsigned short icmp_checksum(uint16_t *packet, size_t packet_size); /* End of run function */ -static void finish(int /*sig*/, bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, - bool jitter_mode, bool score_mode, int min_hosts_alive, +static void finish(int sign, check_icmp_mode_switches modes, int min_hosts_alive, check_icmp_threshold warn, check_icmp_threshold crit, int icmp_sock, unsigned short number_of_targets, check_icmp_state *program_state, - ping_target *target_list); + ping_target *target_list) __attribute__((noreturn)); /* Error exit */ static void crash(const char *fmt, ...); @@ -336,6 +339,7 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { /* Reset argument scanning */ optind = 1; + int host_counter = 0; /* parse the arguments */ for (int i = 1; i < argc; i++) { long int arg; @@ -391,15 +395,20 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { // TODO die here and complain about wrong input break; case 'H': { - add_target_wrapper add_result = add_target(optarg, result.config.mode); - if (add_result.error_code == OK) { + add_host_wrapper host_add_result = add_host(optarg, result.config.mode); + if (host_add_result.error_code == OK) { + result.config.hosts[host_counter] = host_add_result.host; + host_counter++; + if (result.config.targets != NULL) { - result.config.number_of_targets += - ping_target_list_append(result.config.targets, add_result.targets); + result.config.number_of_targets += ping_target_list_append( + result.config.targets, host_add_result.host.target_list); } else { - result.config.targets = add_result.targets; - result.config.number_of_targets += add_result.number_of_targets; + result.config.targets = host_add_result.host.target_list; + result.config.number_of_targets += host_add_result.host.number_of_targets; } + } else { + // TODO adding host failed, crash here } } break; case 'l': @@ -428,7 +437,7 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { result.config.warn = rta_th.warn; result.config.crit = rta_th.crit; - result.config.rta_mode = true; + result.config.modes.rta_mode = true; } break; case 'P': /* packet loss mode */ { get_threshold2_wrapper pl_th = @@ -440,7 +449,7 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { result.config.warn = pl_th.warn; result.config.crit = pl_th.crit; - result.config.pl_mode = true; + result.config.modes.pl_mode = true; } break; case 'J': /* jitter mode */ { get_threshold2_wrapper jitter_th = @@ -452,7 +461,7 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { result.config.warn = jitter_th.warn; result.config.crit = jitter_th.crit; - result.config.jitter_mode = true; + result.config.modes.jitter_mode = true; } break; case 'M': /* MOS mode */ { get_threshold2_wrapper mos_th = get_threshold2( @@ -463,7 +472,7 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { result.config.warn = mos_th.warn; result.config.crit = mos_th.crit; - result.config.mos_mode = true; + result.config.modes.mos_mode = true; } break; case 'S': /* score mode */ { get_threshold2_wrapper score_th = @@ -475,10 +484,10 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { result.config.warn = score_th.warn; result.config.crit = score_th.crit; - result.config.score_mode = true; + result.config.modes.score_mode = true; } break; case 'O': /* out of order mode */ - result.config.order_mode = true; + result.config.modes.order_mode = true; break; } } @@ -869,22 +878,19 @@ int main(int argc, char **argv) { check_icmp_state program_state = check_icmp_state_init(); - run_checks(config.order_mode, config.mos_mode, config.rta_mode, config.pl_mode, - config.jitter_mode, config.score_mode, config.min_hosts_alive, config.icmp_data_size, + run_checks(config.modes, config.min_hosts_alive, config.icmp_data_size, &pkt_interval, &target_interval, config.warn, config.crit, config.sender_id, config.mode, max_completion_time, prog_start, table, config.number_of_packets, icmp_sock, config.number_of_targets, &program_state, config.targets); errno = 0; - finish(0, config.order_mode, config.mos_mode, config.rta_mode, config.pl_mode, - config.jitter_mode, config.score_mode, config.min_hosts_alive, config.warn, config.crit, + finish(0, config.modes, config.min_hosts_alive, config.warn, config.crit, icmp_sock, config.number_of_targets, &program_state, config.targets); return (0); } -static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, - bool jitter_mode, bool score_mode, int min_hosts_alive, +static void run_checks(check_icmp_mode_switches modes, int min_hosts_alive, unsigned short icmp_pkt_size, unsigned int *pkt_interval, unsigned int *target_interval, check_icmp_threshold warn, check_icmp_threshold crit, const uint16_t sender_id, @@ -900,7 +906,7 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo for (unsigned int target_index = 0; target_index < number_of_targets; target_index++) { /* don't send useless packets */ if (!targets_alive(number_of_targets, program_state->targets_down)) { - finish(0, order_mode, mos_mode, rta_mode, pl_mode, jitter_mode, score_mode, + finish(0, modes, min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state, target_list); } @@ -947,7 +953,7 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo if (debug) { printf("Time passed. Finishing up\n"); } - finish(0, order_mode, mos_mode, rta_mode, pl_mode, jitter_mode, score_mode, + finish(0, modes, min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state, target_list); } @@ -1139,7 +1145,7 @@ static int wait_for_reply(int sock, const time_t time_interval, unsigned short i /* Check if packets in order */ if (target->last_icmp_seq >= packet.icp->icmp_seq) { - target->order_status = STATE_CRITICAL; + target->found_out_of_order_packets = true; } } target->last_tdiff = tdiff; @@ -1376,8 +1382,7 @@ static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len, return (ret); } -static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, - bool jitter_mode, bool score_mode, int min_hosts_alive, +static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, check_icmp_threshold warn, check_icmp_threshold crit, const int icmp_sock, const unsigned short number_of_targets, check_icmp_state *program_state, ping_target *target_list) { @@ -1399,358 +1404,53 @@ static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool targets_alive(number_of_targets, program_state->targets_down)); } - /* iterate thrice to calculate values, give output, and print perfparse */ - mp_state_enum status = STATE_OK; - ping_target *host = target_list; + mp_check overall = mp_check_init(); - unsigned int target_counter = 0; - const char *status_string[] = {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"}; + // loop over targets to evaluate each one + ping_target *host = target_list; int hosts_ok = 0; int hosts_warn = 0; while (host) { - mp_state_enum this_status = STATE_OK; - - unsigned char packet_loss; - double rta; - if (!host->icmp_recv) { - /* rta 0 is ofcourse not entirely correct, but will still show up - * conspicuously as missing entries in perfparse and cacti */ - packet_loss = 100; - rta = 0; - status = STATE_CRITICAL; - /* up the down counter if not already counted */ - if (!(host->flags & FLAG_LOST_CAUSE) && - targets_alive(number_of_targets, program_state->targets_down)) { - program_state->targets_down++; - } - } else { - packet_loss = - (unsigned char)((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent; - rta = (double)host->time_waited / host->icmp_recv; - } - - if (host->icmp_recv > 1) { - /* - * This algorithm is probably pretty much blindly copied from - * locations like this one: - * https://www.slac.stanford.edu/comp/net/wan-mon/tutorial.html#mos It calculates a MOS - * value (range of 1 to 5, where 1 is bad and 5 really good). According to some quick - * research MOS originates from the Audio/Video transport network area. Whether it can - * and should be computed from ICMP data, I can not say. - * - * Anyway the basic idea is to map a value "R" with a range of 0-100 to the MOS value - * - * MOS stands likely for Mean Opinion Score ( - * https://en.wikipedia.org/wiki/Mean_Opinion_Score ) - * - * More links: - * - https://confluence.slac.stanford.edu/display/IEPM/MOS - */ - host->jitter = (host->jitter / (host->icmp_recv - 1) / 1000); - - /* - * Take the average round trip latency (in milliseconds), add - * round trip jitter, but double the impact to latency - * then add 10 for protocol latencies (in milliseconds). - */ - host->EffectiveLatency = (rta / 1000) + host->jitter * 2 + 10; - - double R; - if (host->EffectiveLatency < 160) { - R = 93.2 - (host->EffectiveLatency / 40); - } else { - R = 93.2 - ((host->EffectiveLatency - 120) / 10); - } - - // Now, let us deduct 2.5 R values per percentage of packet loss (i.e. a - // loss of 5% will be entered as 5). - R = R - (packet_loss * 2.5); - - if (R < 0) { - R = 0; - } - - host->score = R; - host->mos = 1 + ((0.035) * R) + ((.000007) * R * (R - 60) * (100 - R)); - } else { - host->jitter = 0; - host->jitter_min = 0; - host->jitter_max = 0; - host->mos = 0; - } - - host->pl = packet_loss; - host->rta = rta; - - /* if no new mode selected, use old schema */ - if (!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && !order_mode) { - rta_mode = true; - pl_mode = true; - } - - /* Check which mode is on and do the warn / Crit stuff */ - if (rta_mode) { - if (rta >= crit.rta) { - this_status = STATE_CRITICAL; - status = STATE_CRITICAL; - host->rta_status = STATE_CRITICAL; - } else if (status != STATE_CRITICAL && (rta >= warn.rta)) { - this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status); - status = STATE_WARNING; - host->rta_status = STATE_WARNING; - } - } - - if (pl_mode) { - if (packet_loss >= crit.pl) { - this_status = STATE_CRITICAL; - status = STATE_CRITICAL; - host->pl_status = STATE_CRITICAL; - } else if (status != STATE_CRITICAL && (packet_loss >= warn.pl)) { - this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status); - status = STATE_WARNING; - host->pl_status = STATE_WARNING; - } + if (host->flags & FLAG_LOST_CAUSE) { + program_state->targets_down++; } + // TODO call evaluate here + mp_subcheck sc_target = evaluate_target(*host, modes, warn, crit); - if (jitter_mode) { - if (host->jitter >= crit.jitter) { - this_status = STATE_CRITICAL; - status = STATE_CRITICAL; - host->jitter_status = STATE_CRITICAL; - } else if (status != STATE_CRITICAL && (host->jitter >= warn.jitter)) { - this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status); - status = STATE_WARNING; - host->jitter_status = STATE_WARNING; - } - } + mp_add_subcheck_to_check(&overall, sc_target); - if (mos_mode) { - if (host->mos <= crit.mos) { - this_status = STATE_CRITICAL; - status = STATE_CRITICAL; - host->mos_status = STATE_CRITICAL; - } else if (status != STATE_CRITICAL && (host->mos <= warn.mos)) { - this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status); - status = STATE_WARNING; - host->mos_status = STATE_WARNING; - } - } - - if (score_mode) { - if (host->score <= crit.score) { - this_status = STATE_CRITICAL; - status = STATE_CRITICAL; - host->score_status = STATE_CRITICAL; - } else if (status != STATE_CRITICAL && (host->score <= warn.score)) { - this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status); - status = STATE_WARNING; - host->score_status = STATE_WARNING; - } - } - - if (this_status == STATE_WARNING) { - hosts_warn++; - } else if (this_status == STATE_OK) { + mp_state_enum target_state = mp_compute_subcheck_state(sc_target); + if (target_state == STATE_OK) { hosts_ok++; + } else if (target_state == STATE_WARNING) { + hosts_warn++; } host = host->next; } /* this is inevitable */ - if (!targets_alive(number_of_targets, program_state->targets_down)) { - status = STATE_CRITICAL; - } - if (min_hosts_alive > -1) { - if (hosts_ok >= min_hosts_alive) { - status = STATE_OK; - } else if ((hosts_ok + hosts_warn) >= min_hosts_alive) { - status = STATE_WARNING; - } - } - printf("%s - ", status_string[status]); - - host = target_list; - while (host) { - if (debug) { - puts(""); - } - - if (target_counter) { - if (target_counter < number_of_targets) { - printf(" :: "); - } else { - printf("\n"); - } - } - - target_counter++; - - if (!host->icmp_recv) { - status = STATE_CRITICAL; - host->rtmin = 0; - host->jitter_min = 0; - - if (host->flags & FLAG_LOST_CAUSE) { - char address[INET6_ADDRSTRLEN]; - parse_address(&host->error_addr, address, sizeof(address)); - printf("%s: %s @ %s. rta nan, lost %d%%", host->name, - get_icmp_error_msg(host->icmp_type, host->icmp_code), address, 100); - } else { /* not marked as lost cause, so we have no flags for it */ - printf("%s: rta nan, lost 100%%", host->name); - } - } else { /* !icmp_recv */ - printf("%s", host->name); - /* rta text output */ - if (rta_mode) { - if (status == STATE_OK) { - printf(" rta %0.3fms", host->rta / 1000); - } else if (status == STATE_WARNING && host->rta_status == status) { - printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, - (float)warn.rta / 1000); - } else if (status == STATE_CRITICAL && host->rta_status == status) { - printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, - (float)crit.rta / 1000); - } - } - - /* pl text output */ - if (pl_mode) { - if (status == STATE_OK) { - printf(" lost %u%%", host->pl); - } else if (status == STATE_WARNING && host->pl_status == status) { - printf(" lost %u%% > %u%%", host->pl, warn.pl); - } else if (status == STATE_CRITICAL && host->pl_status == status) { - printf(" lost %u%% > %u%%", host->pl, crit.pl); - } - } - - /* jitter text output */ - if (jitter_mode) { - if (status == STATE_OK) { - printf(" jitter %0.3fms", (float)host->jitter); - } else if (status == STATE_WARNING && host->jitter_status == status) { - printf(" jitter %0.3fms > %0.3fms", (float)host->jitter, warn.jitter); - } else if (status == STATE_CRITICAL && host->jitter_status == status) { - printf(" jitter %0.3fms > %0.3fms", (float)host->jitter, crit.jitter); - } - } - - /* mos text output */ - if (mos_mode) { - if (status == STATE_OK) { - printf(" MOS %0.1f", (float)host->mos); - } else if (status == STATE_WARNING && host->mos_status == status) { - printf(" MOS %0.1f < %0.1f", (float)host->mos, (float)warn.mos); - } else if (status == STATE_CRITICAL && host->mos_status == status) { - printf(" MOS %0.1f < %0.1f", (float)host->mos, (float)crit.mos); - } - } - - /* score text output */ - if (score_mode) { - if (status == STATE_OK) { - printf(" Score %u", (int)host->score); - } else if (status == STATE_WARNING && host->score_status == status) { - printf(" Score %u < %u", (int)host->score, (int)warn.score); - } else if (status == STATE_CRITICAL && host->score_status == status) { - printf(" Score %u < %u", (int)host->score, (int)crit.score); - } - } - - /* order statis text output */ - if (order_mode) { - if (status == STATE_OK) { - printf(" Packets in order"); - } else if (status == STATE_CRITICAL && host->order_status == status) { - printf(" Packets out of order"); - } - } - } - host = host->next; - } - - /* iterate once more for pretty perfparse output */ - if (!(!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && order_mode)) { - printf("|"); - } - - target_counter = 0; - host = target_list; - while (host) { - if (debug) { - puts(""); - } - - if (rta_mode) { - if (host->pl < 100) { - printf("%srta=%0.3fms;%0.3f;%0.3f;0; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ", - (number_of_targets > 1) ? host->name : "", host->rta / 1000, - (float)warn.rta / 1000, (float)crit.rta / 1000, - (number_of_targets > 1) ? host->name : "", (float)host->rtmax / 1000, - (number_of_targets > 1) ? host->name : "", - (host->rtmin < INFINITY) ? (float)host->rtmin / 1000 : (float)0); - } else { - printf("%srta=U;;;; %srtmax=U;;;; %srtmin=U;;;; ", - (number_of_targets > 1) ? host->name : "", - (number_of_targets > 1) ? host->name : "", - (number_of_targets > 1) ? host->name : ""); - } - } - - if (pl_mode) { - printf("%spl=%u%%;%u;%u;0;100 ", (number_of_targets > 1) ? host->name : "", host->pl, - warn.pl, crit.pl); - } - - if (jitter_mode) { - if (host->pl < 100) { - printf("%sjitter_avg=%0.3fms;%0.3f;%0.3f;0; %sjitter_max=%0.3fms;;;; " - "%sjitter_min=%0.3fms;;;; ", - (number_of_targets > 1) ? host->name : "", (float)host->jitter, - (float)warn.jitter, (float)crit.jitter, - (number_of_targets > 1) ? host->name : "", (float)host->jitter_max / 1000, - (number_of_targets > 1) ? host->name : "", (float)host->jitter_min / 1000); - } else { - printf("%sjitter_avg=U;;;; %sjitter_max=U;;;; %sjitter_min=U;;;; ", - (number_of_targets > 1) ? host->name : "", - (number_of_targets > 1) ? host->name : "", - (number_of_targets > 1) ? host->name : ""); - } - } - - if (mos_mode) { - if (host->pl < 100) { - printf("%smos=%0.1f;%0.1f;%0.1f;0;5 ", (number_of_targets > 1) ? host->name : "", - (float)host->mos, (float)warn.mos, (float)crit.mos); - } else { - printf("%smos=U;;;; ", (number_of_targets > 1) ? host->name : ""); - } - } - - if (score_mode) { - if (host->pl < 100) { - printf("%sscore=%u;%u;%u;0;100 ", (number_of_targets > 1) ? host->name : "", - (int)host->score, (int)warn.score, (int)crit.score); - } else { - printf("%sscore=U;;;; ", (number_of_targets > 1) ? host->name : ""); - } - } - - host = host->next; + if (targets_alive(number_of_targets, program_state->targets_down) == 0) { + mp_subcheck sc_no_target_alive = mp_subcheck_init(); + sc_no_target_alive = mp_set_subcheck_state(sc_no_target_alive, STATE_CRITICAL); + sc_no_target_alive.output = strdup("No target is alive!"); + mp_add_subcheck_to_check(&overall, sc_no_target_alive); } if (min_hosts_alive > -1) { + mp_subcheck sc_min_targets_alive = mp_subcheck_init(); + sc_min_targets_alive = mp_set_subcheck_default_state(sc_min_targets_alive, STATE_OK); + + // TODO problably broken now if (hosts_ok >= min_hosts_alive) { - status = STATE_OK; + // TODO this should overwrite the main state + sc_min_targets_alive = mp_set_subcheck_state(sc_min_targets_alive, STATE_OK); } else if ((hosts_ok + hosts_warn) >= min_hosts_alive) { - status = STATE_WARNING; + sc_min_targets_alive = mp_set_subcheck_state(sc_min_targets_alive, STATE_WARNING); } } /* finish with an empty line */ - puts(""); if (debug) { printf( "targets: %u, targets_alive: %u, hosts_ok: %u, hosts_warn: %u, min_hosts_alive: %i\n", @@ -1758,7 +1458,7 @@ static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool hosts_ok, hosts_warn, min_hosts_alive); } - exit(status); + mp_exit(overall); } static time_t get_timevaldiff(const struct timeval earlier, const struct timeval later) { @@ -1825,7 +1525,7 @@ static add_target_ip_wrapper add_target_ip(char *arg, struct sockaddr_storage *a // } /* add the fresh ip */ - ping_target *target = (ping_target *)malloc(sizeof(ping_target)); + ping_target *target = (ping_target *)calloc(1, sizeof(ping_target)); if (!target) { char straddr[INET6_ADDRSTRLEN]; parse_address((struct sockaddr_storage *)&address, straddr, sizeof(straddr)); @@ -2339,3 +2039,289 @@ void print_usage(void) { printf("%s\n", _("Usage:")); printf(" %s [options] [-H] host1 host2 hostN\n", progname); } + +static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode) { + add_host_wrapper result = { + .error_code = OK, + .host = check_icmp_target_container_init(), + }; + + add_target_wrapper targets = add_target(arg, mode); + + if (targets.error_code != OK) { + result.error_code = targets.error_code; + return result; + } + + result.host = check_icmp_target_container_init(); + + result.host.name = strdup(arg); + result.host.target_list = targets.targets; + result.host.number_of_targets = targets.number_of_targets; + + return result; +} + +mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, + check_icmp_threshold warn, check_icmp_threshold crit) { + /* if no new mode selected, use old schema */ + if (!modes.rta_mode && !modes.pl_mode && !modes.jitter_mode && !modes.score_mode && !modes.mos_mode && !modes.order_mode) { + modes.rta_mode = true; + modes.pl_mode = true; + } + + mp_subcheck result = mp_subcheck_init(); + result = mp_set_subcheck_default_state(result, STATE_OK); + xasprintf(&result.output, "%s", target.name); + + double packet_loss; + double rta; + if (!target.icmp_recv) { + /* rta 0 is of course not entirely correct, but will still show up + * conspicuously as missing entries in perfparse and cacti */ + packet_loss = 100; + rta = 0; + result = mp_set_subcheck_state(result, STATE_CRITICAL); + /* up the down counter if not already counted */ + + if (target.flags & FLAG_LOST_CAUSE) { + char address[INET6_ADDRSTRLEN]; + parse_address(&target.error_addr, address, sizeof(address)); + xasprintf(&result.output, "%s: %s @ %s", result.output, + get_icmp_error_msg(target.icmp_type, target.icmp_code), address); + } else { /* not marked as lost cause, so we have no flags for it */ + xasprintf(&result.output, "%s", result.output); + } + } else { + packet_loss = + (unsigned char)((target.icmp_sent - target.icmp_recv) * 100) / target.icmp_sent; + rta = (double)target.time_waited / target.icmp_recv; + } + + double EffectiveLatency; + double mos; /* Mean opinion score */ + double score; /* score */ + + if (target.icmp_recv > 1) { + /* + * This algorithm is probably pretty much blindly copied from + * locations like this one: + * https://www.slac.stanford.edu/comp/net/wan-mon/tutorial.html#mos It calculates a MOS + * value (range of 1 to 5, where 1 is bad and 5 really good). According to some quick + * research MOS originates from the Audio/Video transport network area. Whether it can + * and should be computed from ICMP data, I can not say. + * + * Anyway the basic idea is to map a value "R" with a range of 0-100 to the MOS value + * + * MOS stands likely for Mean Opinion Score ( + * https://en.wikipedia.org/wiki/Mean_Opinion_Score ) + * + * More links: + * - https://confluence.slac.stanford.edu/display/IEPM/MOS + */ + target.jitter = (target.jitter / (target.icmp_recv - 1) / 1000); + + /* + * Take the average round trip latency (in milliseconds), add + * round trip jitter, but double the impact to latency + * then add 10 for protocol latencies (in milliseconds). + */ + EffectiveLatency = (rta / 1000) + target.jitter * 2 + 10; + + double R; + if (EffectiveLatency < 160) { + R = 93.2 - (EffectiveLatency / 40); + } else { + R = 93.2 - ((EffectiveLatency - 120) / 10); + } + + // Now, let us deduct 2.5 R values per percentage of packet loss (i.e. a + // loss of 5% will be entered as 5). + R = R - (packet_loss * 2.5); + + if (R < 0) { + R = 0; + } + + score = R; + mos = 1 + ((0.035) * R) + ((.000007) * R * (R - 60) * (100 - R)); + } else { + target.jitter = 0; + target.jitter_min = 0; + target.jitter_max = 0; + mos = 0; + } + + /* Check which mode is on and do the warn / Crit stuff */ + if (modes.rta_mode) { + mp_subcheck sc_rta = mp_subcheck_init(); + sc_rta = mp_set_subcheck_default_state(sc_rta, STATE_OK); + xasprintf(&sc_rta.output, "rta %0.3fms", rta / 1000); + + if (rta >= crit.rta) { + sc_rta = mp_set_subcheck_state(sc_rta, STATE_CRITICAL); + xasprintf(&sc_rta.output, "%s > %0.3fms", sc_rta.output, crit.rta / 1000); + } else if (rta >= warn.rta) { + sc_rta = mp_set_subcheck_state(sc_rta, STATE_WARNING); + xasprintf(&sc_rta.output, "%s > %0.3fms", sc_rta.output, warn.rta / 1000); + } + + if (packet_loss < 100) { + mp_perfdata pd_rta = perfdata_init(); + xasprintf(&pd_rta.label, "%srta", target.name); + pd_rta.uom = strdup("ms"); + pd_rta.value = mp_create_pd_value(rta / 1000); + pd_rta.min = mp_create_pd_value(0); + + pd_rta.warn = mp_range_set_end(pd_rta.warn, mp_create_pd_value(warn.rta)); + pd_rta.crit = mp_range_set_end(pd_rta.crit, mp_create_pd_value(crit.rta)); + mp_add_perfdata_to_subcheck(&sc_rta, pd_rta); + + mp_perfdata pd_rt_min = perfdata_init(); + xasprintf(&pd_rt_min.label, "%srtmin", target.name); + pd_rt_min.value = mp_create_pd_value(target.rtmin / 1000); + pd_rt_min.uom = strdup("ms"); + mp_add_perfdata_to_subcheck(&sc_rta, pd_rt_min); + + mp_perfdata pd_rt_max = perfdata_init(); + xasprintf(&pd_rt_max.label, "%srtmax", target.name); + pd_rt_max.value = mp_create_pd_value(target.rtmax / 1000); + pd_rt_max.uom = strdup("ms"); + mp_add_perfdata_to_subcheck(&sc_rta, pd_rt_max); + } + + mp_add_subcheck_to_subcheck(&result, sc_rta); + } + + if (modes.pl_mode) { + mp_subcheck sc_pl = mp_subcheck_init(); + sc_pl = mp_set_subcheck_default_state(sc_pl, STATE_OK); + xasprintf(&sc_pl.output, "packet loss %.1f%%", packet_loss); + + if (packet_loss >= crit.pl) { + sc_pl = mp_set_subcheck_state(sc_pl, STATE_CRITICAL); + xasprintf(&sc_pl.output, "%s > %u%%", sc_pl.output, crit.pl); + } else if (packet_loss >= warn.pl) { + sc_pl = mp_set_subcheck_state(sc_pl, STATE_WARNING); + xasprintf(&sc_pl.output, "%s > %u%%", sc_pl.output, crit.pl); + } + + mp_perfdata pd_pl = perfdata_init(); + xasprintf(&pd_pl.label, "%spl", target.name); + pd_pl.uom = strdup("%"); + + pd_pl.warn = mp_range_set_end(pd_pl.warn, mp_create_pd_value(warn.pl)); + pd_pl.crit = mp_range_set_end(pd_pl.crit, mp_create_pd_value(crit.pl)); + pd_pl.value = mp_create_pd_value(packet_loss); + + mp_add_perfdata_to_subcheck(&sc_pl, pd_pl); + + mp_add_subcheck_to_subcheck(&result, sc_pl); + } + + if (modes.jitter_mode) { + mp_subcheck sc_jitter = mp_subcheck_init(); + sc_jitter = mp_set_subcheck_default_state(sc_jitter, STATE_OK); + xasprintf(&sc_jitter.output, "jitter %0.3fms", target.jitter); + + if (target.jitter >= crit.jitter) { + sc_jitter = mp_set_subcheck_state(sc_jitter, STATE_CRITICAL); + xasprintf(&sc_jitter.output, "%s > %0.3fms", sc_jitter.output, crit.jitter); + } else if (target.jitter >= warn.jitter) { + sc_jitter = mp_set_subcheck_state(sc_jitter, STATE_WARNING); + xasprintf(&sc_jitter.output, "%s > %0.3fms", sc_jitter.output, warn.jitter); + } + + if (packet_loss < 100) { + mp_perfdata pd_jitter = perfdata_init(); + pd_jitter.uom = strdup("ms"); + xasprintf(&pd_jitter.label, "%sjitter_avg", target.name); + pd_jitter.value = mp_create_pd_value(target.jitter); + pd_jitter.warn = mp_range_set_end(pd_jitter.warn, mp_create_pd_value(warn.jitter)); + pd_jitter.crit = mp_range_set_end(pd_jitter.crit, mp_create_pd_value(crit.jitter)); + mp_add_perfdata_to_subcheck(&sc_jitter, pd_jitter); + + mp_perfdata pd_jitter_min = perfdata_init(); + pd_jitter_min.uom = strdup("ms"); + xasprintf(&pd_jitter_min.label, "%sjitter_min", target.name); + pd_jitter_min.value = mp_create_pd_value(target.jitter_min); + mp_add_perfdata_to_subcheck(&sc_jitter, pd_jitter_min); + + mp_perfdata pd_jitter_max = perfdata_init(); + pd_jitter_max.uom = strdup("ms"); + xasprintf(&pd_jitter_max.label, "%sjitter_max", target.name); + pd_jitter_max.value = mp_create_pd_value(target.jitter_max); + mp_add_perfdata_to_subcheck(&sc_jitter, pd_jitter_max); + } + mp_add_subcheck_to_subcheck(&result, sc_jitter); + } + + if (modes.mos_mode) { + mp_subcheck sc_mos = mp_subcheck_init(); + sc_mos = mp_set_subcheck_default_state(sc_mos, STATE_OK); + xasprintf(&sc_mos.output, "MOS %0.1f", mos); + + if (mos <= crit.mos) { + sc_mos = mp_set_subcheck_state(sc_mos, STATE_CRITICAL); + xasprintf(&sc_mos.output, "%s < %0.1f", sc_mos.output, crit.mos); + } else if (mos <= warn.mos) { + sc_mos = mp_set_subcheck_state(sc_mos, STATE_WARNING); + xasprintf(&sc_mos.output, "%s < %0.1f", sc_mos.output, warn.mos); + } + + if (packet_loss < 100) { + mp_perfdata pd_mos = perfdata_init(); + xasprintf(&pd_mos.label, "%smos", target.name); + pd_mos.value = mp_create_pd_value(mos); + pd_mos.warn = mp_range_set_end(pd_mos.warn, mp_create_pd_value(warn.mos)); + pd_mos.crit = mp_range_set_end(pd_mos.crit, mp_create_pd_value(crit.mos)); + pd_mos.min = mp_create_pd_value(0); + pd_mos.max = mp_create_pd_value(5); + mp_add_perfdata_to_subcheck(&sc_mos, pd_mos); + } + mp_add_subcheck_to_subcheck(&result, sc_mos); + } + + if (modes.score_mode) { + mp_subcheck sc_score = mp_subcheck_init(); + sc_score = mp_set_subcheck_default_state(sc_score, STATE_OK); + xasprintf(&sc_score.output, "Score %u", score); + + if (score <= crit.score) { + sc_score = mp_set_subcheck_state(sc_score, STATE_CRITICAL); + xasprintf(&sc_score.output, "%s < %u", sc_score.output, crit.score); + } else if (score <= warn.score) { + sc_score = mp_set_subcheck_state(sc_score, STATE_WARNING); + xasprintf(&sc_score.output, "%s < %u", sc_score.output, warn.score); + } + + if (packet_loss < 100) { + mp_perfdata pd_score = perfdata_init(); + xasprintf(&pd_score.label, "%sscore", target.name); + pd_score.value = mp_create_pd_value(score); + pd_score.warn = mp_range_set_end(pd_score.warn, mp_create_pd_value(warn.score)); + pd_score.crit = mp_range_set_end(pd_score.crit, mp_create_pd_value(crit.score)); + pd_score.min = mp_create_pd_value(0); + pd_score.max = mp_create_pd_value(100); + mp_add_perfdata_to_subcheck(&sc_score, pd_score); + } + + mp_add_subcheck_to_subcheck(&result, sc_score); + } + + if (modes.order_mode) { + mp_subcheck sc_order = mp_subcheck_init(); + sc_order = mp_set_subcheck_default_state(sc_order, STATE_OK); + + if (target.found_out_of_order_packets) { + mp_set_subcheck_state(sc_order, STATE_CRITICAL); + xasprintf(&sc_order.output, "Packets out of order"); + } else { + xasprintf(&sc_order.output, "Packets in order"); + } + + mp_add_subcheck_to_subcheck(&result, sc_order); + } + + return result; +} diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.c b/plugins-root/check_icmp.d/check_icmp_helpers.c index 58e13581..a2b54c6a 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.c +++ b/plugins-root/check_icmp.d/check_icmp_helpers.c @@ -10,12 +10,15 @@ unsigned int timeout = DEFAULT_TIMEOUT; check_icmp_config check_icmp_config_init() { check_icmp_config tmp = { - .order_mode = false, - .mos_mode = false, - .rta_mode = false, - .pl_mode = false, - .jitter_mode = false, - .score_mode = false, + .modes = + { + .order_mode = false, + .mos_mode = false, + .rta_mode = false, + .pl_mode = false, + .jitter_mode = false, + .score_mode = false, + }, .min_hosts_alive = -1, .crit = {.pl = DEFAULT_CRIT_PL, @@ -56,12 +59,7 @@ ping_target ping_target_init() { .jitter_min = INFINITY, - .rta_status = STATE_OK, - .jitter_status = STATE_OK, - .mos_status = STATE_OK, - .score_status = STATE_OK, - .pl_status = STATE_OK, - .order_status = STATE_OK, + .found_out_of_order_packets = false, }; return tmp; diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.h b/plugins-root/check_icmp.d/check_icmp_helpers.h index 3e798f72..68c39b4a 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.h +++ b/plugins-root/check_icmp.d/check_icmp_helpers.h @@ -20,7 +20,6 @@ typedef struct rta_host { unsigned char icmp_type, icmp_code; /* type and code from errors */ unsigned short flags; /* control/status flags */ - double rta; /* measured RTA */ double rtmax; /* max rtt */ double rtmin; /* min rtt */ @@ -28,20 +27,10 @@ typedef struct rta_host { double jitter_max; /* jitter rtt maximum */ double jitter_min; /* jitter rtt minimum */ - double EffectiveLatency; - double mos; /* Mean opinion score */ - double score; /* score */ - time_t last_tdiff; unsigned int last_icmp_seq; /* Last ICMP_SEQ to check out of order pkts */ - unsigned char pl; /* measured packet loss */ - mp_state_enum rta_status; // check result for RTA checks - mp_state_enum jitter_status; // check result for Jitter checks - mp_state_enum mos_status; // check result for MOS checks - mp_state_enum score_status; // check result for score checks - mp_state_enum pl_status; // check result for packet loss checks - mp_state_enum order_status; // check result for packet order checks + bool found_out_of_order_packets; struct rta_host *next; } ping_target; diff --git a/plugins-root/check_icmp.d/config.h b/plugins-root/check_icmp.d/config.h index 3599c0f0..aa33c991 100644 --- a/plugins-root/check_icmp.d/config.h +++ b/plugins-root/check_icmp.d/config.h @@ -48,6 +48,10 @@ typedef struct { bool pl_mode; bool jitter_mode; bool score_mode; +} check_icmp_mode_switches; + +typedef struct { + check_icmp_mode_switches modes; int min_hosts_alive; check_icmp_threshold crit; -- cgit v1.2.3-74-g34f1 From fbcd11acb7ae098db28a778c84756a49b36f83ef Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Sun, 18 May 2025 00:20:36 +0200 Subject: Clang-format --- plugins-root/check_icmp.c | 25 ++++++++++++------------- plugins-root/check_icmp.d/check_icmp_helpers.h | 2 +- 2 files changed, 13 insertions(+), 14 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 34adf6fe..58f5ae70 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -878,14 +878,14 @@ int main(int argc, char **argv) { check_icmp_state program_state = check_icmp_state_init(); - run_checks(config.modes, config.min_hosts_alive, config.icmp_data_size, - &pkt_interval, &target_interval, config.warn, config.crit, config.sender_id, - config.mode, max_completion_time, prog_start, table, config.number_of_packets, - icmp_sock, config.number_of_targets, &program_state, config.targets); + run_checks(config.modes, config.min_hosts_alive, config.icmp_data_size, &pkt_interval, + &target_interval, config.warn, config.crit, config.sender_id, config.mode, + max_completion_time, prog_start, table, config.number_of_packets, icmp_sock, + config.number_of_targets, &program_state, config.targets); errno = 0; - finish(0, config.modes, config.min_hosts_alive, config.warn, config.crit, - icmp_sock, config.number_of_targets, &program_state, config.targets); + finish(0, config.modes, config.min_hosts_alive, config.warn, config.crit, icmp_sock, + config.number_of_targets, &program_state, config.targets); return (0); } @@ -906,9 +906,8 @@ static void run_checks(check_icmp_mode_switches modes, int min_hosts_alive, for (unsigned int target_index = 0; target_index < number_of_targets; target_index++) { /* don't send useless packets */ if (!targets_alive(number_of_targets, program_state->targets_down)) { - finish(0, modes, - min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state, - target_list); + finish(0, modes, min_hosts_alive, warn, crit, icmp_sock, number_of_targets, + program_state, target_list); } if (table[target_index]->flags & FLAG_LOST_CAUSE) { if (debug) { @@ -953,9 +952,8 @@ static void run_checks(check_icmp_mode_switches modes, int min_hosts_alive, if (debug) { printf("Time passed. Finishing up\n"); } - finish(0, modes, - min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state, - target_list); + finish(0, modes, min_hosts_alive, warn, crit, icmp_sock, number_of_targets, + program_state, target_list); } /* catch the packets that might come in within the timeframe, but @@ -2065,7 +2063,8 @@ static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode) { mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, check_icmp_threshold warn, check_icmp_threshold crit) { /* if no new mode selected, use old schema */ - if (!modes.rta_mode && !modes.pl_mode && !modes.jitter_mode && !modes.score_mode && !modes.mos_mode && !modes.order_mode) { + if (!modes.rta_mode && !modes.pl_mode && !modes.jitter_mode && !modes.score_mode && + !modes.mos_mode && !modes.order_mode) { modes.rta_mode = true; modes.pl_mode = true; } diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.h b/plugins-root/check_icmp.d/check_icmp_helpers.h index 68c39b4a..5f771635 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.h +++ b/plugins-root/check_icmp.d/check_icmp_helpers.h @@ -15,7 +15,7 @@ typedef struct rta_host { char *msg; /* icmp error message, if any */ struct sockaddr_storage saddr_in; /* the address of this host */ struct sockaddr_storage error_addr; /* stores address of error replies */ - time_t time_waited; /* total time waited, in usecs */ + time_t time_waited; /* total time waited, in usecs */ unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */ unsigned char icmp_type, icmp_code; /* type and code from errors */ unsigned short flags; /* control/status flags */ -- cgit v1.2.3-74-g34f1 From 8f08e7ab3ecc03ea38062fe4442668fbea30bb73 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Sun, 18 May 2025 14:00:55 +0200 Subject: WIP - check_icmp refactor 7 --- plugins-root/check_icmp.c | 193 ++++++++++++++++++++++++++-------------------- 1 file changed, 108 insertions(+), 85 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 58f5ae70..0614d6aa 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -184,17 +184,24 @@ static parse_threshold2_helper_wrapper parse_threshold2_helper(char *threshold_s threshold_mode mode); /* main test function */ -static void run_checks(check_icmp_mode_switches modes, int min_hosts_alive, - unsigned short icmp_pkt_size, unsigned int *pkt_interval, - unsigned int *target_interval, check_icmp_threshold warn, - check_icmp_threshold crit, uint16_t sender_id, +static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval, + unsigned int *target_interval, uint16_t sender_id, check_icmp_execution_mode mode, unsigned int max_completion_time, struct timeval prog_start, ping_target **table, unsigned short packets, int icmp_sock, unsigned short number_of_targets, - check_icmp_state *program_state, ping_target *target_list); + check_icmp_state *program_state); mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, check_icmp_threshold warn, check_icmp_threshold crit); +typedef struct { + int targets_ok; + int targets_warn; + mp_subcheck sc_host; +} evaluate_host_wrapper; +evaluate_host_wrapper evaluate_host(check_icmp_target_container host, + check_icmp_mode_switches modes, check_icmp_threshold warn, + check_icmp_threshold crit); + /* Target aquisition */ typedef struct { int error_code; @@ -213,7 +220,7 @@ typedef struct { int error_code; ping_target *target; } add_target_ip_wrapper; -static add_target_ip_wrapper add_target_ip(char *arg, struct sockaddr_storage *address); +static add_target_ip_wrapper add_target_ip(struct sockaddr_storage address); static void parse_address(struct sockaddr_storage *addr, char *address, socklen_t size); @@ -223,7 +230,8 @@ static unsigned short icmp_checksum(uint16_t *packet, size_t packet_size); static void finish(int sign, check_icmp_mode_switches modes, int min_hosts_alive, check_icmp_threshold warn, check_icmp_threshold crit, int icmp_sock, unsigned short number_of_targets, check_icmp_state *program_state, - ping_target *target_list) __attribute__((noreturn)); + check_icmp_target_container host_list[], unsigned short number_of_hosts, + mp_check overall[static 1]); /* Error exit */ static void crash(const char *fmt, ...); @@ -247,8 +255,6 @@ typedef struct { int errorcode; check_icmp_config config; } check_icmp_config_wrapper; -check_icmp_config_wrapper process_arguments(int argc, char **argv); - check_icmp_config_wrapper process_arguments(int argc, char **argv) { /* get calling name the old-fashioned way for portability instead * of relying on the glibc-ism __progname */ @@ -313,7 +319,11 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { break; case 'H': { result.config.number_of_hosts++; + break; } + case 'v': + debug++; + break; } } } @@ -345,9 +355,6 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { long int arg; while ((arg = getopt(argc, argv, opts_str)) != EOF) { switch (arg) { - case 'v': - debug++; - break; case 'b': { long size = strtol(optarg, NULL, 0); if ((unsigned long)size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && @@ -859,6 +866,7 @@ int main(int argc, char **argv) { crash("minimum alive hosts is negative (%i)", config.min_hosts_alive); } + // Build an index table of all targets ping_target *host = config.targets; ping_target **table = malloc(sizeof(ping_target *) * config.number_of_targets); if (!table) { @@ -878,27 +886,26 @@ int main(int argc, char **argv) { check_icmp_state program_state = check_icmp_state_init(); - run_checks(config.modes, config.min_hosts_alive, config.icmp_data_size, &pkt_interval, - &target_interval, config.warn, config.crit, config.sender_id, config.mode, - max_completion_time, prog_start, table, config.number_of_packets, icmp_sock, - config.number_of_targets, &program_state, config.targets); + run_checks(config.icmp_data_size, &pkt_interval, &target_interval, config.sender_id, + config.mode, max_completion_time, prog_start, table, config.number_of_packets, + icmp_sock, config.number_of_targets, &program_state); errno = 0; + + mp_check overall = mp_check_init(); finish(0, config.modes, config.min_hosts_alive, config.warn, config.crit, icmp_sock, - config.number_of_targets, &program_state, config.targets); + config.number_of_targets, &program_state, config.hosts, config.number_of_hosts, + &overall); - return (0); + mp_exit(overall); } -static void run_checks(check_icmp_mode_switches modes, int min_hosts_alive, - unsigned short icmp_pkt_size, unsigned int *pkt_interval, - unsigned int *target_interval, check_icmp_threshold warn, - check_icmp_threshold crit, const uint16_t sender_id, +static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval, + unsigned int *target_interval, const uint16_t sender_id, const check_icmp_execution_mode mode, const unsigned int max_completion_time, const struct timeval prog_start, ping_target **table, const unsigned short packets, const int icmp_sock, - const unsigned short number_of_targets, check_icmp_state *program_state, - ping_target *target_list) { + const unsigned short number_of_targets, check_icmp_state *program_state) { /* this loop might actually violate the pkt_interval or target_interval * settings, but only if there aren't any packets on the wire which * indicates that the target can handle an increased packet rate */ @@ -906,8 +913,7 @@ static void run_checks(check_icmp_mode_switches modes, int min_hosts_alive, for (unsigned int target_index = 0; target_index < number_of_targets; target_index++) { /* don't send useless packets */ if (!targets_alive(number_of_targets, program_state->targets_down)) { - finish(0, modes, min_hosts_alive, warn, crit, icmp_sock, number_of_targets, - program_state, target_list); + return; } if (table[target_index]->flags & FLAG_LOST_CAUSE) { if (debug) { @@ -952,8 +958,7 @@ static void run_checks(check_icmp_mode_switches modes, int min_hosts_alive, if (debug) { printf("Time passed. Finishing up\n"); } - finish(0, modes, min_hosts_alive, warn, crit, icmp_sock, number_of_targets, - program_state, target_list); + return; } /* catch the packets that might come in within the timeframe, but @@ -1383,7 +1388,8 @@ static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len, static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, check_icmp_threshold warn, check_icmp_threshold crit, const int icmp_sock, const unsigned short number_of_targets, check_icmp_state *program_state, - ping_target *target_list) { + check_icmp_target_container host_list[], unsigned short number_of_hosts, + mp_check overall[static 1]) { // Deactivate alarm alarm(0); @@ -1402,29 +1408,21 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, targets_alive(number_of_targets, program_state->targets_down)); } - mp_check overall = mp_check_init(); - // loop over targets to evaluate each one - ping_target *host = target_list; - int hosts_ok = 0; - int hosts_warn = 0; - while (host) { - if (host->flags & FLAG_LOST_CAUSE) { - program_state->targets_down++; - } - // TODO call evaluate here - mp_subcheck sc_target = evaluate_target(*host, modes, warn, crit); + int targets_ok = 0; + int targets_warn = 0; + for (unsigned short i = 0; i < number_of_hosts; i++) { + evaluate_host_wrapper host_check = evaluate_host(host_list[i], modes, warn, crit); - mp_add_subcheck_to_check(&overall, sc_target); + targets_ok += host_check.targets_ok; + targets_warn += host_check.targets_warn; - mp_state_enum target_state = mp_compute_subcheck_state(sc_target); - if (target_state == STATE_OK) { - hosts_ok++; - } else if (target_state == STATE_WARNING) { - hosts_warn++; - } + mp_add_subcheck_to_check(overall, host_check.sc_host); + } - host = host->next; + if (number_of_hosts == 1) { + // Exit early here, since the other checks only make sense for multiple hosts + return; } /* this is inevitable */ @@ -1432,7 +1430,7 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, mp_subcheck sc_no_target_alive = mp_subcheck_init(); sc_no_target_alive = mp_set_subcheck_state(sc_no_target_alive, STATE_CRITICAL); sc_no_target_alive.output = strdup("No target is alive!"); - mp_add_subcheck_to_check(&overall, sc_no_target_alive); + mp_add_subcheck_to_check(overall, sc_no_target_alive); } if (min_hosts_alive > -1) { @@ -1440,10 +1438,10 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, sc_min_targets_alive = mp_set_subcheck_default_state(sc_min_targets_alive, STATE_OK); // TODO problably broken now - if (hosts_ok >= min_hosts_alive) { + if (targets_ok >= min_hosts_alive) { // TODO this should overwrite the main state sc_min_targets_alive = mp_set_subcheck_state(sc_min_targets_alive, STATE_OK); - } else if ((hosts_ok + hosts_warn) >= min_hosts_alive) { + } else if ((targets_ok + targets_warn) >= min_hosts_alive) { sc_min_targets_alive = mp_set_subcheck_state(sc_min_targets_alive, STATE_WARNING); } } @@ -1453,10 +1451,8 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, printf( "targets: %u, targets_alive: %u, hosts_ok: %u, hosts_warn: %u, min_hosts_alive: %i\n", number_of_targets, targets_alive(number_of_targets, program_state->targets_down), - hosts_ok, hosts_warn, min_hosts_alive); + targets_ok, targets_warn, min_hosts_alive); } - - mp_exit(overall); } static time_t get_timevaldiff(const struct timeval earlier, const struct timeval later) { @@ -1479,13 +1475,18 @@ static time_t get_timevaldiff_to_now(struct timeval earlier) { return get_timevaldiff(earlier, now); } -static add_target_ip_wrapper add_target_ip(char *arg, struct sockaddr_storage *address) { +static add_target_ip_wrapper add_target_ip(struct sockaddr_storage address) { + if (debug) { + char straddr[INET6_ADDRSTRLEN]; + parse_address((struct sockaddr_storage *)&address, straddr, sizeof(straddr)); + printf("add_target_ip called with: %s\n", straddr); + } struct sockaddr_in *sin; struct sockaddr_in6 *sin6; if (address_family == AF_INET) { - sin = (struct sockaddr_in *)address; + sin = (struct sockaddr_in *)&address; } else { - sin6 = (struct sockaddr_in6 *)address; + sin6 = (struct sockaddr_in6 *)&address; } add_target_ip_wrapper result = { @@ -1502,38 +1503,20 @@ static add_target_ip_wrapper add_target_ip(char *arg, struct sockaddr_storage *a return result; } - // TODO: allow duplicate targets for now, might be on purpose - /* no point in adding two identical IP's, so don't. ;) */ - // struct sockaddr_in *host_sin; - // struct sockaddr_in6 *host_sin6; - // ping_target *host = host_list; - // while (host) { - // host_sin = (struct sockaddr_in *)&host->saddr_in; - // host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; - - // if ((address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr) || - // (address_family == AF_INET6 && - // host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) { - // if (debug) { - // printf("Identical IP already exists. Not adding %s\n", arg); - // } - // return -1; - // } - // host = host->next; - // } + // get string representation of address + char straddr[INET6_ADDRSTRLEN]; + parse_address((&address), straddr, sizeof(straddr)); /* add the fresh ip */ ping_target *target = (ping_target *)calloc(1, sizeof(ping_target)); if (!target) { - char straddr[INET6_ADDRSTRLEN]; - parse_address((struct sockaddr_storage *)&address, straddr, sizeof(straddr)); - crash("add_target_ip(%s, %s): malloc(%lu) failed", arg, straddr, sizeof(ping_target)); + crash("add_target_ip(%s): malloc(%lu) failed", straddr, sizeof(ping_target)); } *target = ping_target_init(); /* set the values. use calling name for output */ - target->name = strdup(arg); + target->name = strdup(straddr); /* fill out the sockaddr_storage struct */ struct sockaddr_in *host_sin; @@ -1556,9 +1539,13 @@ static add_target_ip_wrapper add_target_ip(char *arg, struct sockaddr_storage *a /* wrapper for add_target_ip */ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode mode) { - struct sockaddr_storage address_storage; - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; + if (debug > 0) { + printf("add_target called with argument %s\n", arg); + } + + struct sockaddr_storage address_storage = {}; + struct sockaddr_in *sin = NULL; + struct sockaddr_in6 *sin6 = NULL; int error_code = -1; switch (address_family) { @@ -1598,7 +1585,7 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode /* don't resolve if we don't have to */ if (error_code == 1) { /* don't add all ip's if we were given a specific one */ - add_target_ip_wrapper targeted = add_target_ip(arg, &address_storage); + add_target_ip_wrapper targeted = add_target_ip(address_storage); if (targeted.error_code != OK) { result.error_code = ERROR; @@ -1634,7 +1621,8 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode for (struct addrinfo *address = res; address != NULL; address = address->ai_next) { struct sockaddr_storage temporary_ip_address; memcpy(&temporary_ip_address, address->ai_addr, address->ai_addrlen); - add_target_ip_wrapper tmp = add_target_ip(arg, &temporary_ip_address); + + add_target_ip_wrapper tmp = add_target_ip(temporary_ip_address); if (tmp.error_code != OK) { // No proper error handling @@ -2039,6 +2027,10 @@ void print_usage(void) { } static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode) { + if (debug) { + printf("add_host called with argument %s\n", arg); + } + add_host_wrapper result = { .error_code = OK, .host = check_icmp_target_container_init(), @@ -2324,3 +2316,34 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, return result; } + +evaluate_host_wrapper evaluate_host(check_icmp_target_container host, + check_icmp_mode_switches modes, check_icmp_threshold warn, + check_icmp_threshold crit) { + evaluate_host_wrapper result = { + .targets_warn = 0, + .targets_ok = 0, + .sc_host = mp_subcheck_init(), + }; + result.sc_host = mp_set_subcheck_default_state(result.sc_host, STATE_OK); + + result.sc_host.output = strdup(host.name); + + ping_target *target = host.target_list; + for (unsigned int i = 0; i < host.number_of_targets; i++) { + mp_subcheck sc_target = evaluate_target(*target, modes, warn, crit); + + mp_state_enum target_state = mp_compute_subcheck_state(sc_target); + + if (target_state == STATE_WARNING) { + result.targets_warn++; + } else if (target_state == STATE_OK) { + result.targets_ok++; + } + mp_add_subcheck_to_subcheck(&result.sc_host, sc_target); + + target = target->next; + } + + return result; +} -- cgit v1.2.3-74-g34f1 From b5de682309589ddb230e04beaaa54d74f2fe70d5 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Sun, 18 May 2025 18:10:25 +0200 Subject: WIP - check_icmp refactor 8 --- plugins-root/check_icmp.c | 505 +++++++++++++++---------- plugins-root/check_icmp.d/check_icmp_helpers.c | 64 +--- plugins-root/check_icmp.d/check_icmp_helpers.h | 15 +- plugins-root/check_icmp.d/config.h | 3 + 4 files changed, 332 insertions(+), 255 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 0614d6aa..d4e55b0d 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -71,6 +71,9 @@ const char *email = "devel@monitoring-plugins.org"; #include #include #include +#include +#include +#include #include "../lib/states.h" #include "./check_icmp.d/config.h" @@ -140,24 +143,31 @@ static time_t get_timevaldiff(struct timeval earlier, struct timeval later); static time_t get_timevaldiff_to_now(struct timeval earlier); static in_addr_t get_ip_address(const char *ifname); -static void set_source_ip(char *arg, int icmp_sock); +static void set_source_ip(char *arg, int icmp_sock, sa_family_t addr_family); /* Receiving data */ -static int wait_for_reply(int socket, time_t time_interval, unsigned short icmp_pkt_size, - unsigned int *pkt_interval, unsigned int *target_interval, - uint16_t sender_id, ping_target **table, unsigned short packets, - unsigned short number_of_targets, check_icmp_state *program_state); +static int wait_for_reply(check_icmp_socket_set sockset, time_t time_interval, + unsigned short icmp_pkt_size, unsigned int *pkt_interval, + unsigned int *target_interval, uint16_t sender_id, ping_target **table, + unsigned short packets, unsigned short number_of_targets, + check_icmp_state *program_state); -static ssize_t recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, - time_t *timeout, struct timeval *received_timestamp); +typedef struct { + sa_family_t recv_proto; + ssize_t received; +} recvfrom_wto_wrapper; +static recvfrom_wto_wrapper recvfrom_wto(check_icmp_socket_set sockset, void *buf, unsigned int len, + struct sockaddr *saddr, time_t *timeout, + struct timeval *received_timestamp); static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr, unsigned int *pkt_interval, unsigned int *target_interval, uint16_t sender_id, ping_target **table, unsigned short packets, unsigned short number_of_targets, check_icmp_state *program_state); /* Sending data */ -static int send_icmp_ping(int socket, ping_target *host, unsigned short icmp_pkt_size, - uint16_t sender_id, check_icmp_state *program_state); +static int send_icmp_ping(check_icmp_socket_set socket, ping_target *host, + unsigned short icmp_pkt_size, uint16_t sender_id, + check_icmp_state *program_state); /* Threshold related */ typedef struct { @@ -188,7 +198,7 @@ static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval, unsigned int *target_interval, uint16_t sender_id, check_icmp_execution_mode mode, unsigned int max_completion_time, struct timeval prog_start, ping_target **table, unsigned short packets, - int icmp_sock, unsigned short number_of_targets, + check_icmp_socket_set sockset, unsigned short number_of_targets, check_icmp_state *program_state); mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, check_icmp_threshold warn, check_icmp_threshold crit); @@ -206,15 +216,21 @@ evaluate_host_wrapper evaluate_host(check_icmp_target_container host, typedef struct { int error_code; check_icmp_target_container host; + bool has_v4; + bool has_v6; } add_host_wrapper; -static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode); +static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode, + sa_family_t enforced_proto); typedef struct { int error_code; ping_target *targets; unsigned int number_of_targets; + bool has_v4; + bool has_v6; } add_target_wrapper; -static add_target_wrapper add_target(char *arg, check_icmp_execution_mode mode); +static add_target_wrapper add_target(char *arg, check_icmp_execution_mode mode, + sa_family_t enforced_proto); typedef struct { int error_code; @@ -222,13 +238,13 @@ typedef struct { } add_target_ip_wrapper; static add_target_ip_wrapper add_target_ip(struct sockaddr_storage address); -static void parse_address(struct sockaddr_storage *addr, char *address, socklen_t size); +static void parse_address(const struct sockaddr_storage *addr, char *dst, socklen_t size); static unsigned short icmp_checksum(uint16_t *packet, size_t packet_size); /* End of run function */ static void finish(int sign, check_icmp_mode_switches modes, int min_hosts_alive, - check_icmp_threshold warn, check_icmp_threshold crit, int icmp_sock, + check_icmp_threshold warn, check_icmp_threshold crit, unsigned short number_of_targets, check_icmp_state *program_state, check_icmp_target_container host_list[], unsigned short number_of_hosts, mp_check overall[static 1]); @@ -298,6 +314,8 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { } } + sa_family_t enforced_ai_family = AF_UNSPEC; + // Parse protocol arguments first // and count hosts here char *opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64"; @@ -306,16 +324,16 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { while ((arg = getopt(argc, argv, opts_str)) != EOF) { switch (arg) { case '4': - if (address_family != -1) { + if (enforced_ai_family != AF_UNSPEC) { crash("Multiple protocol versions not supported"); } - address_family = AF_INET; + enforced_ai_family = AF_INET; break; case '6': - if (address_family != -1) { + if (enforced_ai_family != AF_UNSPEC) { crash("Multiple protocol versions not supported"); } - address_family = AF_INET6; + enforced_ai_family = AF_INET6; break; case 'H': { result.config.number_of_hosts++; @@ -402,7 +420,8 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { // TODO die here and complain about wrong input break; case 'H': { - add_host_wrapper host_add_result = add_host(optarg, result.config.mode); + add_host_wrapper host_add_result = + add_host(optarg, result.config.mode, enforced_ai_family); if (host_add_result.error_code == OK) { result.config.hosts[host_counter] = host_add_result.host; host_counter++; @@ -414,6 +433,13 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { result.config.targets = host_add_result.host.target_list; result.config.number_of_targets += host_add_result.host.number_of_targets; } + + if (host_add_result.has_v4) { + result.config.need_v4 = true; + } + if (host_add_result.has_v6) { + result.config.need_v6 = true; + } } else { // TODO adding host failed, crash here } @@ -502,7 +528,7 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { argv = &argv[optind]; while (*argv) { - add_target(*argv, result.config.mode); + add_target(*argv, result.config.mode, enforced_ai_family); argv++; } @@ -704,9 +730,8 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad if (debug) { char address[INET6_ADDRSTRLEN]; parse_address(addr, address, sizeof(address)); - printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n", - get_icmp_error_msg(icmp_packet.icmp_type, icmp_packet.icmp_code), address, - host->name); + printf("Received \"%s\" from %s for ICMP ECHO sent.\n", + get_icmp_error_msg(icmp_packet.icmp_type, icmp_packet.icmp_code), address); } program_state->icmp_lost++; @@ -732,14 +757,16 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad return 0; } -void parse_address(struct sockaddr_storage *addr, char *address, socklen_t size) { - switch (address_family) { +void parse_address(const struct sockaddr_storage *addr, char *dst, socklen_t size) { + switch (addr->ss_family) { case AF_INET: - inet_ntop(address_family, &((struct sockaddr_in *)addr)->sin_addr, address, size); + inet_ntop(AF_INET, &((struct sockaddr_in *)addr)->sin_addr, dst, size); break; case AF_INET6: - inet_ntop(address_family, &((struct sockaddr_in6 *)addr)->sin6_addr, address, size); + inet_ntop(AF_INET6, &((struct sockaddr_in6 *)addr)->sin6_addr, dst, size); break; + default: + assert(false); } } @@ -748,9 +775,6 @@ int main(int argc, char **argv) { bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - address_family = -1; - int icmp_proto = IPPROTO_ICMP; - /* POSIXLY_CORRECT might break things, so unset it (the portable way) */ environ = NULL; @@ -765,35 +789,68 @@ int main(int argc, char **argv) { const check_icmp_config config = tmp_config.config; + // int icmp_proto = IPPROTO_ICMP; // add_target might change address_family - switch (address_family) { - case AF_INET: - icmp_proto = IPPROTO_ICMP; - break; - case AF_INET6: - icmp_proto = IPPROTO_ICMPV6; - break; - default: - crash("Address family not supported"); - } + // switch (address_family) { + // case AF_INET: + // icmp_proto = IPPROTO_ICMP; + // break; + // case AF_INET6: + // icmp_proto = IPPROTO_ICMPV6; + // break; + // default: + // crash("Address family not supported"); + // } + + check_icmp_socket_set sockset = { + .socket4 = -1, + .socket6 = -1, + }; - int icmp_sock = socket(address_family, SOCK_RAW, icmp_proto); - if (icmp_sock == -1) { - crash("Failed to obtain ICMP socket"); - } + if (config.need_v4) { + sockset.socket4 = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + if (sockset.socket4 == -1) { + crash("Failed to obtain ICMP v4 socket"); + } - if (config.source_ip) { - set_source_ip(config.source_ip, icmp_sock); - } + if (config.source_ip) { + + struct in_addr tmp = {}; + int error_code = inet_pton(AF_INET, config.source_ip, &tmp); + if (error_code == 1) { + set_source_ip(config.source_ip, sockset.socket4, AF_INET); + } else { + // just try this mindlessly if it's not a v4 address + set_source_ip(config.source_ip, sockset.socket6, AF_INET6); + } + } #ifdef SO_TIMESTAMP - int on = 1; - if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) { - if (debug) { - printf("Warning: no SO_TIMESTAMP support\n"); + if (sockset.socket4 != -1) { + int on = 1; + if (setsockopt(sockset.socket4, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) { + if (debug) { + printf("Warning: no SO_TIMESTAMP support\n"); + } + } + } + if (sockset.socket6 != -1) { + int on = 1; + if (setsockopt(sockset.socket6, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) { + if (debug) { + printf("Warning: no SO_TIMESTAMP support\n"); + } + } } - } #endif // SO_TIMESTAMP + } + + if (config.need_v6) { + sockset.socket6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); + if (sockset.socket6 == -1) { + crash("Failed to obtain ICMP v6 socket"); + } + } /* now drop privileges (no effect if not setsuid or geteuid() == 0) */ if (setuid(getuid()) == -1) { @@ -801,8 +858,19 @@ int main(int argc, char **argv) { return 1; } - if (icmp_sock) { - int result = setsockopt(icmp_sock, SOL_IP, IP_TTL, &config.ttl, sizeof(config.ttl)); + if (sockset.socket4) { + int result = setsockopt(sockset.socket4, SOL_IP, IP_TTL, &config.ttl, sizeof(config.ttl)); + if (debug) { + if (result == -1) { + printf("setsockopt failed\n"); + } else { + printf("ttl set to %lu\n", config.ttl); + } + } + } + + if (sockset.socket6) { + int result = setsockopt(sockset.socket6, SOL_IP, IP_TTL, &config.ttl, sizeof(config.ttl)); if (debug) { if (result == -1) { printf("setsockopt failed\n"); @@ -888,15 +956,22 @@ int main(int argc, char **argv) { run_checks(config.icmp_data_size, &pkt_interval, &target_interval, config.sender_id, config.mode, max_completion_time, prog_start, table, config.number_of_packets, - icmp_sock, config.number_of_targets, &program_state); + sockset, config.number_of_targets, &program_state); errno = 0; mp_check overall = mp_check_init(); - finish(0, config.modes, config.min_hosts_alive, config.warn, config.crit, icmp_sock, + finish(0, config.modes, config.min_hosts_alive, config.warn, config.crit, config.number_of_targets, &program_state, config.hosts, config.number_of_hosts, &overall); + if (sockset.socket4) { + close(sockset.socket4); + } + if (sockset.socket6) { + close(sockset.socket6); + } + mp_exit(overall); } @@ -904,7 +979,7 @@ static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval, unsigned int *target_interval, const uint16_t sender_id, const check_icmp_execution_mode mode, const unsigned int max_completion_time, const struct timeval prog_start, ping_target **table, - const unsigned short packets, const int icmp_sock, + const unsigned short packets, const check_icmp_socket_set sockset, const unsigned short number_of_targets, check_icmp_state *program_state) { /* this loop might actually violate the pkt_interval or target_interval * settings, but only if there aren't any packets on the wire which @@ -917,20 +992,23 @@ static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval, } if (table[target_index]->flags & FLAG_LOST_CAUSE) { if (debug) { - printf("%s is a lost cause. not sending any more\n", table[target_index]->name); + + char address[INET6_ADDRSTRLEN]; + parse_address(&table[target_index]->address, address, sizeof(address)); + printf("%s is a lost cause. not sending any more\n", address); } continue; } /* we're still in the game, so send next packet */ - (void)send_icmp_ping(icmp_sock, table[target_index], icmp_pkt_size, sender_id, + (void)send_icmp_ping(sockset, table[target_index], icmp_pkt_size, sender_id, program_state); /* wrap up if all targets are declared dead */ if (targets_alive(number_of_targets, program_state->targets_down) || get_timevaldiff(prog_start, prog_start) < max_completion_time || !(mode == MODE_HOSTCHECK && program_state->targets_down)) { - wait_for_reply(icmp_sock, *target_interval, icmp_pkt_size, pkt_interval, + wait_for_reply(sockset, *target_interval, icmp_pkt_size, pkt_interval, target_interval, sender_id, table, packets, number_of_targets, program_state); } @@ -938,9 +1016,9 @@ static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval, if (targets_alive(number_of_targets, program_state->targets_down) || get_timevaldiff_to_now(prog_start) < max_completion_time || !(mode == MODE_HOSTCHECK && program_state->targets_down)) { - wait_for_reply(icmp_sock, *pkt_interval * number_of_targets, icmp_pkt_size, - pkt_interval, target_interval, sender_id, table, packets, - number_of_targets, program_state); + wait_for_reply(sockset, *pkt_interval * number_of_targets, icmp_pkt_size, pkt_interval, + target_interval, sender_id, table, packets, number_of_targets, + program_state); } } @@ -970,7 +1048,7 @@ static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval, if (targets_alive(number_of_targets, program_state->targets_down) || get_timevaldiff_to_now(prog_start) < max_completion_time || !(mode == MODE_HOSTCHECK && program_state->targets_down)) { - wait_for_reply(icmp_sock, final_wait, icmp_pkt_size, pkt_interval, target_interval, + wait_for_reply(sockset, final_wait, icmp_pkt_size, pkt_interval, target_interval, sender_id, table, packets, number_of_targets, program_state); } } @@ -986,10 +1064,11 @@ static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval, * both: * icmp echo reply : the rest */ -static int wait_for_reply(int sock, const time_t time_interval, unsigned short icmp_pkt_size, - unsigned int *pkt_interval, unsigned int *target_interval, - uint16_t sender_id, ping_target **table, const unsigned short packets, - const unsigned short number_of_targets, check_icmp_state *program_state) { +static int wait_for_reply(check_icmp_socket_set sockset, const time_t time_interval, + unsigned short icmp_pkt_size, unsigned int *pkt_interval, + unsigned int *target_interval, uint16_t sender_id, ping_target **table, + const unsigned short packets, const unsigned short number_of_targets, + check_icmp_state *program_state) { union icmp_packet packet; if (!(packet.buf = malloc(icmp_pkt_size))) { crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size); @@ -1022,25 +1101,25 @@ static int wait_for_reply(int sock, const time_t time_interval, unsigned short i time_t loop_time_interval = per_pkt_wait; /* reap responses until we hit a timeout */ - ssize_t n = recvfrom_wto(sock, buf, sizeof(buf), (struct sockaddr *)&resp_addr, - &loop_time_interval, &packet_received_timestamp); - if (!n) { + recvfrom_wto_wrapper recv_foo = + recvfrom_wto(sockset, buf, sizeof(buf), (struct sockaddr *)&resp_addr, + &loop_time_interval, &packet_received_timestamp); + if (!recv_foo.received) { if (debug > 1) { printf("recvfrom_wto() timed out during a %ld usecs wait\n", per_pkt_wait); } continue; /* timeout for this one, so keep trying */ } - if (n < 0) { + if (recv_foo.received < 0) { if (debug) { printf("recvfrom_wto() returned errors\n"); } free(packet.buf); - return (int)n; + return (int)recv_foo.received; } - // FIXME: with ipv6 we don't have an ip header here - if (address_family != AF_INET6) { + if (recv_foo.recv_proto != AF_INET6) { ip_header = (union ip_hdr *)buf; if (debug > 1) { @@ -1053,38 +1132,21 @@ static int wait_for_reply(int sock, const time_t time_interval, unsigned short i } } - /* obsolete. alpha on tru64 provides the necessary defines, but isn't broken */ - /* #if defined( __alpha__ ) && __STDC__ && !defined( __GLIBC__ ) */ - /* alpha headers are decidedly broken. Using an ansi compiler, - * they provide ip_vhl instead of ip_hl and ip_v, so we mask - * off the bottom 4 bits */ - /* hlen = (ip->ip_vhl & 0x0f) << 2; */ - /* #else */ - int hlen = (address_family == AF_INET6) ? 0 : ip_header->ip.ip_hl << 2; - /* #endif */ - - if (n < (hlen + ICMP_MINLEN)) { + int hlen = (recv_foo.recv_proto == AF_INET6) ? 0 : ip_header->ip.ip_hl << 2; + + if (recv_foo.received < (hlen + ICMP_MINLEN)) { char address[INET6_ADDRSTRLEN]; parse_address(&resp_addr, address, sizeof(address)); - crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n", n, - hlen + icmp_pkt_size, address); + crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n", + recv_foo.received, hlen + icmp_pkt_size, address); } - /* else if(debug) { */ - /* printf("ip header size: %u, packet size: %u (expected %u, %u)\n", */ - /* hlen, ntohs(ip->ip_len) - hlen, */ - /* sizeof(struct ip), icmp_pkt_size); */ - /* } */ - /* check the response */ - memcpy(packet.buf, buf + hlen, icmp_pkt_size); - /* address_family == AF_INET6 ? sizeof(struct icmp6_hdr) - : sizeof(struct icmp));*/ - if ((address_family == PF_INET && + if ((recv_foo.recv_proto == AF_INET && (ntohs(packet.icp->icmp_id) != sender_id || packet.icp->icmp_type != ICMP_ECHOREPLY || ntohs(packet.icp->icmp_seq) >= number_of_targets * packets)) || - (address_family == PF_INET6 && + (recv_foo.recv_proto == AF_INET6 && (ntohs(packet.icp6->icmp6_id) != sender_id || packet.icp6->icmp6_type != ICMP6_ECHO_REPLY || ntohs(packet.icp6->icmp6_seq) >= number_of_targets * packets))) { @@ -1101,7 +1163,7 @@ static int wait_for_reply(int sock, const time_t time_interval, unsigned short i /* this is indeed a valid response */ ping_target *target; struct icmp_ping_data data; - if (address_family == PF_INET) { + if (address_family == AF_INET) { memcpy(&data, packet.icp->icmp_data, sizeof(data)); if (debug > 2) { printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", sizeof(data), @@ -1171,7 +1233,7 @@ static int wait_for_reply(int sock, const time_t time_interval, unsigned short i char address[INET6_ADDRSTRLEN]; parse_address(&resp_addr, address, sizeof(address)); - switch (address_family) { + switch (recv_foo.recv_proto) { case AF_INET: { printf("%0.3f ms rtt from %s, incoming ttl: %u, max: %0.3f, min: %0.3f\n", (float)tdiff / 1000, address, ip_header->ip.ip_ttl, @@ -1191,23 +1253,14 @@ static int wait_for_reply(int sock, const time_t time_interval, unsigned short i } /* the ping functions */ -static int send_icmp_ping(const int sock, ping_target *host, const unsigned short icmp_pkt_size, - const uint16_t sender_id, check_icmp_state *program_state) { - if (sock == -1) { - errno = 0; - crash("Attempt to send on bogus socket"); - return -1; - } - - void *buf = NULL; - +static int send_icmp_ping(const check_icmp_socket_set sockset, ping_target *host, + const unsigned short icmp_pkt_size, const uint16_t sender_id, + check_icmp_state *program_state) { + void *buf = calloc(1, icmp_pkt_size); if (!buf) { - if (!(buf = malloc(icmp_pkt_size))) { - crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size); - return -1; /* might be reached if we're in debug mode */ - } + crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size); + return -1; /* might be reached if we're in debug mode */ } - memset(buf, 0, icmp_pkt_size); struct timeval current_time; if ((gettimeofday(¤t_time, NULL)) == -1) { @@ -1221,7 +1274,7 @@ static int send_icmp_ping(const int sock, ping_target *host, const unsigned shor socklen_t addrlen; - if (address_family == AF_INET) { + if (host->address.ss_family == AF_INET) { struct icmp *icp = (struct icmp *)buf; addrlen = sizeof(struct sockaddr_in); @@ -1235,11 +1288,14 @@ static int send_icmp_ping(const int sock, ping_target *host, const unsigned shor icp->icmp_cksum = icmp_checksum((uint16_t *)buf, (size_t)icmp_pkt_size); if (debug > 2) { + char address[INET6_ADDRSTRLEN]; + parse_address((&host->address), address, sizeof(address)); + printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", sizeof(data), ntohs(icp->icmp_id), ntohs(icp->icmp_seq), icp->icmp_cksum, - host->name); + address); } - } else { + } else if (host->address.ss_family == AF_INET6) { struct icmp6_hdr *icp6 = (struct icmp6_hdr *)buf; addrlen = sizeof(struct sockaddr_in6); @@ -1253,10 +1309,16 @@ static int send_icmp_ping(const int sock, ping_target *host, const unsigned shor // let checksum be calculated automatically if (debug > 2) { - printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", + char address[INET6_ADDRSTRLEN]; + parse_address((&host->address), address, sizeof(address)); + + printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to target %s\n", sizeof(data), ntohs(icp6->icmp6_id), ntohs(icp6->icmp6_seq), icp6->icmp6_cksum, - host->name); + address); } + } else { + // unknown address family + crash("unknown address family in ", __func__); } struct iovec iov; @@ -1266,7 +1328,7 @@ static int send_icmp_ping(const int sock, ping_target *host, const unsigned shor struct msghdr hdr; memset(&hdr, 0, sizeof(hdr)); - hdr.msg_name = (struct sockaddr *)&host->saddr_in; + hdr.msg_name = (struct sockaddr *)&host->address; hdr.msg_namelen = addrlen; hdr.msg_iov = &iov; hdr.msg_iovlen = 1; @@ -1274,19 +1336,29 @@ static int send_icmp_ping(const int sock, ping_target *host, const unsigned shor errno = 0; long int len; -/* MSG_CONFIRM is a linux thing and only available on linux kernels >= 2.3.15, see send(2) */ + /* MSG_CONFIRM is a linux thing and only available on linux kernels >= 2.3.15, see send(2) */ + if (host->address.ss_family == AF_INET) { #ifdef MSG_CONFIRM - len = sendmsg(sock, &hdr, MSG_CONFIRM); + len = sendmsg(sockset.socket4, &hdr, MSG_CONFIRM); #else - len = sendmsg(sock, &hdr, 0); + len = sendmsg(sockset.socket4, &hdr, 0); #endif + } else if (host->address.ss_family == AF_INET6) { +#ifdef MSG_CONFIRM + len = sendmsg(sockset.socket6, &hdr, MSG_CONFIRM); +#else + len = sendmsg(sockset.socket6, &hdr, 0); +#endif + } else { + assert(false); + } free(buf); if (len < 0 || (unsigned int)len != icmp_pkt_size) { if (debug) { char address[INET6_ADDRSTRLEN]; - parse_address((&host->saddr_in), address, sizeof(address)); + parse_address((&host->address), address, sizeof(address)); printf("Failed to send ping to %s: %s\n", address, strerror(errno)); } errno = 0; @@ -1299,9 +1371,9 @@ static int send_icmp_ping(const int sock, ping_target *host, const unsigned shor return 0; } -static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len, - struct sockaddr *saddr, time_t *timeout, - struct timeval *received_timestamp) { +static recvfrom_wto_wrapper recvfrom_wto(const check_icmp_socket_set sockset, void *buf, + const unsigned int len, struct sockaddr *saddr, + time_t *timeout, struct timeval *received_timestamp) { #ifdef HAVE_MSGHDR_MSG_CONTROL char ans_data[4096]; #endif // HAVE_MSGHDR_MSG_CONTROL @@ -1309,11 +1381,16 @@ static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len, struct cmsghdr *chdr; #endif + recvfrom_wto_wrapper result = { + .received = 0, + .recv_proto = AF_UNSPEC, + }; + if (!*timeout) { if (debug) { printf("*timeout is not\n"); } - return 0; + return result; } struct timeval real_timeout; @@ -1327,13 +1404,21 @@ static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len, // Read fds for select with the socket fd_set read_fds; FD_ZERO(&read_fds); - FD_SET(sock, &read_fds); + + if (sockset.socket4 != -1) { + FD_SET(sockset.socket4, &read_fds); + } + if (sockset.socket6 != -1) { + FD_SET(sockset.socket6, &read_fds); + } + + int nfds = (sockset.socket4 > sockset.socket6 ? sockset.socket4 : sockset.socket6) + 1; struct timeval then; gettimeofday(&then, NULL); errno = 0; - int select_return = select(sock + 1, &read_fds, &dummy_write_fds, NULL, &real_timeout); + int select_return = select(nfds, &read_fds, &dummy_write_fds, NULL, &real_timeout); if (select_return < 0) { crash("select() in recvfrom_wto"); } @@ -1343,7 +1428,7 @@ static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len, *timeout = get_timevaldiff(then, now); if (!select_return) { - return 0; /* timeout */ + return result; /* timeout */ } unsigned int slen = sizeof(struct sockaddr_storage); @@ -1364,7 +1449,18 @@ static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len, #endif }; - ssize_t ret = recvmsg(sock, &hdr, 0); + ssize_t ret; + if (FD_ISSET(sockset.socket4, &read_fds)) { + ret = recvmsg(sockset.socket4, &hdr, 0); + result.recv_proto = AF_INET; + } else if (FD_ISSET(sockset.socket6, &read_fds)) { + ret = recvmsg(sockset.socket6, &hdr, 0); + result.recv_proto = AF_INET6; + } else { + assert(false); + } + + result.received = ret; #ifdef SO_TIMESTAMP for (chdr = CMSG_FIRSTHDR(&hdr); chdr; chdr = CMSG_NXTHDR(&hdr, chdr)) { @@ -1382,11 +1478,11 @@ static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len, gettimeofday(tv, NULL); #endif // SO_TIMESTAMP - return (ret); + return (result); } static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, - check_icmp_threshold warn, check_icmp_threshold crit, const int icmp_sock, + check_icmp_threshold warn, check_icmp_threshold crit, const unsigned short number_of_targets, check_icmp_state *program_state, check_icmp_target_container host_list[], unsigned short number_of_hosts, mp_check overall[static 1]) { @@ -1397,10 +1493,6 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, printf("finish(%d) called\n", sig); } - if (icmp_sock != -1) { - close(icmp_sock); - } - if (debug) { printf("icmp_sent: %u icmp_recv: %u icmp_lost: %u\n", program_state->icmp_sent, program_state->icmp_recv, program_state->icmp_lost); @@ -1476,17 +1568,21 @@ static time_t get_timevaldiff_to_now(struct timeval earlier) { } static add_target_ip_wrapper add_target_ip(struct sockaddr_storage address) { + assert((address.ss_family == AF_INET) || (address.ss_family == AF_INET6)); + if (debug) { char straddr[INET6_ADDRSTRLEN]; - parse_address((struct sockaddr_storage *)&address, straddr, sizeof(straddr)); + parse_address((&address), straddr, sizeof(straddr)); printf("add_target_ip called with: %s\n", straddr); } struct sockaddr_in *sin; struct sockaddr_in6 *sin6; - if (address_family == AF_INET) { + if (address.ss_family == AF_INET) { sin = (struct sockaddr_in *)&address; - } else { + } else if (address.ss_family == AF_INET6) { sin6 = (struct sockaddr_in6 *)&address; + } else { + assert(false); } add_target_ip_wrapper result = { @@ -1496,9 +1592,9 @@ static add_target_ip_wrapper add_target_ip(struct sockaddr_storage address) { /* disregard obviously stupid addresses * (I didn't find an ipv6 equivalent to INADDR_NONE) */ - if (((address_family == AF_INET && + if (((address.ss_family == AF_INET && (sin->sin_addr.s_addr == INADDR_NONE || sin->sin_addr.s_addr == INADDR_ANY))) || - (address_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) { + (address.ss_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) { result.error_code = ERROR; return result; } @@ -1513,32 +1609,21 @@ static add_target_ip_wrapper add_target_ip(struct sockaddr_storage address) { crash("add_target_ip(%s): malloc(%lu) failed", straddr, sizeof(ping_target)); } - *target = ping_target_init(); + ping_target_create_wrapper target_wrapper = ping_target_create(address); - /* set the values. use calling name for output */ - target->name = strdup(straddr); - - /* fill out the sockaddr_storage struct */ - struct sockaddr_in *host_sin; - struct sockaddr_in6 *host_sin6; - if (address_family == AF_INET) { - host_sin = (struct sockaddr_in *)&target->saddr_in; - host_sin->sin_family = AF_INET; - host_sin->sin_addr.s_addr = sin->sin_addr.s_addr; + if (target_wrapper.errorcode == OK) { + *target = target_wrapper.host; + result.target = target; } else { - host_sin6 = (struct sockaddr_in6 *)&target->saddr_in; - host_sin6->sin6_family = AF_INET6; - memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, - sizeof host_sin6->sin6_addr.s6_addr); + result.error_code = target_wrapper.errorcode; } - result.target = target; - return result; } /* wrapper for add_target_ip */ -static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode mode) { +static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode mode, + sa_family_t enforced_proto) { if (debug > 0) { printf("add_target called with argument %s\n", arg); } @@ -1548,30 +1633,31 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode struct sockaddr_in6 *sin6 = NULL; int error_code = -1; - switch (address_family) { - case -1: - /* -4 and -6 are not specified on cmdline */ - address_family = AF_INET; + switch (enforced_proto) { + case AF_UNSPEC: + /* + * no enforced protocoll family + * try to parse the address with each one + */ sin = (struct sockaddr_in *)&address_storage; - error_code = inet_pton(address_family, arg, &sin->sin_addr); + error_code = inet_pton(AF_INET, arg, &sin->sin_addr); + address_storage.ss_family = AF_INET; if (error_code != 1) { - address_family = AF_INET6; sin6 = (struct sockaddr_in6 *)&address_storage; - error_code = inet_pton(address_family, arg, &sin6->sin6_addr); - } - /* If we don't find any valid addresses, we still don't know the address_family */ - if (error_code != 1) { - address_family = -1; + error_code = inet_pton(AF_INET6, arg, &sin6->sin6_addr); + address_storage.ss_family = AF_INET6; } break; case AF_INET: sin = (struct sockaddr_in *)&address_storage; - error_code = inet_pton(address_family, arg, &sin->sin_addr); + error_code = inet_pton(AF_INET, arg, &sin->sin_addr); + address_storage.ss_family = AF_INET; break; case AF_INET6: sin6 = (struct sockaddr_in6 *)&address_storage; - error_code = inet_pton(address_family, arg, &sin6->sin6_addr); + error_code = inet_pton(AF_INET, arg, &sin6->sin6_addr); + address_storage.ss_family = AF_INET6; break; default: crash("Address family not supported"); @@ -1580,9 +1666,11 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode add_target_wrapper result = { .error_code = OK, .targets = NULL, + .has_v4 = false, + .has_v6 = false, }; - /* don't resolve if we don't have to */ + // if error_code == 1 the address was a valid address parsed above if (error_code == 1) { /* don't add all ip's if we were given a specific one */ add_target_ip_wrapper targeted = add_target_ip(address_storage); @@ -1592,19 +1680,21 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode return result; } + if (targeted.target->address.ss_family == AF_INET) { + result.has_v4 = true; + } else if (targeted.target->address.ss_family == AF_INET6) { + result.has_v6 = true; + } else { + assert(false); + } result.targets = targeted.target; result.number_of_targets = 1; return result; } - struct addrinfo hints; + struct addrinfo hints = {}; errno = 0; - memset(&hints, 0, sizeof(hints)); - if (address_family == -1) { - hints.ai_family = AF_UNSPEC; - } else { - hints.ai_family = address_family == AF_INET ? PF_INET : PF_INET6; - } + hints.ai_family = enforced_proto; hints.ai_socktype = SOCK_RAW; int error; @@ -1615,7 +1705,6 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode result.error_code = ERROR; return result; } - address_family = res->ai_family; /* possibly add all the IP's as targets */ for (struct addrinfo *address = res; address != NULL; address = address->ai_next) { @@ -1634,6 +1723,11 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode } else { result.number_of_targets += ping_target_list_append(result.targets, tmp.target); } + if (address->ai_family == AF_INET) { + result.has_v4 = true; + } else if (address->ai_family == AF_INET6) { + result.has_v6 = true; + } } /* this is silly, but it works */ @@ -1652,11 +1746,11 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode return result; } -static void set_source_ip(char *arg, const int icmp_sock) { +static void set_source_ip(char *arg, const int icmp_sock, sa_family_t addr_family) { struct sockaddr_in src; memset(&src, 0, sizeof(src)); - src.sin_family = address_family; + src.sin_family = addr_family; if ((src.sin_addr.s_addr = inet_addr(arg)) == INADDR_NONE) { src.sin_addr.s_addr = get_ip_address(arg); } @@ -2026,7 +2120,8 @@ void print_usage(void) { printf(" %s [options] [-H] host1 host2 hostN\n", progname); } -static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode) { +static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode, + sa_family_t enforced_proto) { if (debug) { printf("add_host called with argument %s\n", arg); } @@ -2034,15 +2129,20 @@ static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode) { add_host_wrapper result = { .error_code = OK, .host = check_icmp_target_container_init(), + .has_v4 = false, + .has_v6 = false, }; - add_target_wrapper targets = add_target(arg, mode); + add_target_wrapper targets = add_target(arg, mode, enforced_proto); if (targets.error_code != OK) { result.error_code = targets.error_code; return result; } + result.has_v4 = targets.has_v4; + result.has_v6 = targets.has_v6; + result.host = check_icmp_target_container_init(); result.host.name = strdup(arg); @@ -2063,7 +2163,12 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, mp_subcheck result = mp_subcheck_init(); result = mp_set_subcheck_default_state(result, STATE_OK); - xasprintf(&result.output, "%s", target.name); + + char address[INET6_ADDRSTRLEN]; + memset(address, 0, INET6_ADDRSTRLEN); + parse_address(&target.address, address, sizeof(address)); + + xasprintf(&result.output, "%s", address); double packet_loss; double rta; @@ -2076,8 +2181,6 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, /* up the down counter if not already counted */ if (target.flags & FLAG_LOST_CAUSE) { - char address[INET6_ADDRSTRLEN]; - parse_address(&target.error_addr, address, sizeof(address)); xasprintf(&result.output, "%s: %s @ %s", result.output, get_icmp_error_msg(target.icmp_type, target.icmp_code), address); } else { /* not marked as lost cause, so we have no flags for it */ @@ -2159,7 +2262,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, if (packet_loss < 100) { mp_perfdata pd_rta = perfdata_init(); - xasprintf(&pd_rta.label, "%srta", target.name); + xasprintf(&pd_rta.label, "%srta", address); pd_rta.uom = strdup("ms"); pd_rta.value = mp_create_pd_value(rta / 1000); pd_rta.min = mp_create_pd_value(0); @@ -2169,13 +2272,13 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, mp_add_perfdata_to_subcheck(&sc_rta, pd_rta); mp_perfdata pd_rt_min = perfdata_init(); - xasprintf(&pd_rt_min.label, "%srtmin", target.name); + xasprintf(&pd_rt_min.label, "%srtmin", address); pd_rt_min.value = mp_create_pd_value(target.rtmin / 1000); pd_rt_min.uom = strdup("ms"); mp_add_perfdata_to_subcheck(&sc_rta, pd_rt_min); mp_perfdata pd_rt_max = perfdata_init(); - xasprintf(&pd_rt_max.label, "%srtmax", target.name); + xasprintf(&pd_rt_max.label, "%srtmax", address); pd_rt_max.value = mp_create_pd_value(target.rtmax / 1000); pd_rt_max.uom = strdup("ms"); mp_add_perfdata_to_subcheck(&sc_rta, pd_rt_max); @@ -2198,7 +2301,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, } mp_perfdata pd_pl = perfdata_init(); - xasprintf(&pd_pl.label, "%spl", target.name); + xasprintf(&pd_pl.label, "%spl", address); pd_pl.uom = strdup("%"); pd_pl.warn = mp_range_set_end(pd_pl.warn, mp_create_pd_value(warn.pl)); @@ -2226,7 +2329,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, if (packet_loss < 100) { mp_perfdata pd_jitter = perfdata_init(); pd_jitter.uom = strdup("ms"); - xasprintf(&pd_jitter.label, "%sjitter_avg", target.name); + xasprintf(&pd_jitter.label, "%sjitter_avg", address); pd_jitter.value = mp_create_pd_value(target.jitter); pd_jitter.warn = mp_range_set_end(pd_jitter.warn, mp_create_pd_value(warn.jitter)); pd_jitter.crit = mp_range_set_end(pd_jitter.crit, mp_create_pd_value(crit.jitter)); @@ -2234,13 +2337,13 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, mp_perfdata pd_jitter_min = perfdata_init(); pd_jitter_min.uom = strdup("ms"); - xasprintf(&pd_jitter_min.label, "%sjitter_min", target.name); + xasprintf(&pd_jitter_min.label, "%sjitter_min", address); pd_jitter_min.value = mp_create_pd_value(target.jitter_min); mp_add_perfdata_to_subcheck(&sc_jitter, pd_jitter_min); mp_perfdata pd_jitter_max = perfdata_init(); pd_jitter_max.uom = strdup("ms"); - xasprintf(&pd_jitter_max.label, "%sjitter_max", target.name); + xasprintf(&pd_jitter_max.label, "%sjitter_max", address); pd_jitter_max.value = mp_create_pd_value(target.jitter_max); mp_add_perfdata_to_subcheck(&sc_jitter, pd_jitter_max); } @@ -2262,7 +2365,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, if (packet_loss < 100) { mp_perfdata pd_mos = perfdata_init(); - xasprintf(&pd_mos.label, "%smos", target.name); + xasprintf(&pd_mos.label, "%smos", address); pd_mos.value = mp_create_pd_value(mos); pd_mos.warn = mp_range_set_end(pd_mos.warn, mp_create_pd_value(warn.mos)); pd_mos.crit = mp_range_set_end(pd_mos.crit, mp_create_pd_value(crit.mos)); @@ -2288,7 +2391,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, if (packet_loss < 100) { mp_perfdata pd_score = perfdata_init(); - xasprintf(&pd_score.label, "%sscore", target.name); + xasprintf(&pd_score.label, "%sscore", address); pd_score.value = mp_create_pd_value(score); pd_score.warn = mp_range_set_end(pd_score.warn, mp_create_pd_value(warn.score)); pd_score.crit = mp_range_set_end(pd_score.crit, mp_create_pd_value(crit.score)); diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.c b/plugins-root/check_icmp.d/check_icmp_helpers.c index a2b54c6a..47604952 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.c +++ b/plugins-root/check_icmp.d/check_icmp_helpers.c @@ -1,7 +1,7 @@ #include "./config.h" -#include "states.h" #include #include +#include #include "./check_icmp_helpers.h" #include "../../plugins/netutils.h" @@ -38,7 +38,10 @@ check_icmp_config check_icmp_config_init() { .pkt_interval = DEFAULT_PKT_INTERVAL, .target_interval = 0, .number_of_packets = DEFAULT_NUMBER_OF_PACKETS, + .source_ip = NULL, + .need_v4 = false, + .need_v6 = false, .sender_id = {}, @@ -71,68 +74,31 @@ check_icmp_state check_icmp_state_init() { return tmp; } -ping_target_create_wrapper ping_target_create(char *name, struct sockaddr_storage *address) { - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; - if (address_family == AF_INET) { - sin = (struct sockaddr_in *)address; - } else { - sin6 = (struct sockaddr_in6 *)address; - } - +ping_target_create_wrapper ping_target_create(struct sockaddr_storage address) { ping_target_create_wrapper result = { .errorcode = OK, }; + struct sockaddr_storage *tmp_addr = &address; + /* disregard obviously stupid addresses * (I didn't find an ipv6 equivalent to INADDR_NONE) */ - if (((address_family == AF_INET && - (sin->sin_addr.s_addr == INADDR_NONE || sin->sin_addr.s_addr == INADDR_ANY))) || - (address_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) { + if (((tmp_addr->ss_family == AF_INET && + (((struct sockaddr_in *)tmp_addr)->sin_addr.s_addr == INADDR_NONE || + ((struct sockaddr_in *)tmp_addr)->sin_addr.s_addr == INADDR_ANY))) || + (tmp_addr->ss_family == AF_INET6 && + (((struct sockaddr_in6 *)tmp_addr)->sin6_addr.s6_addr == in6addr_any.s6_addr))) { result.errorcode = ERROR; return result; } - // TODO: Maybe add the following back in as a sanity check for the config - // /* no point in adding two identical IP's, so don't. ;) */ - // struct sockaddr_in *host_sin; - // struct sockaddr_in6 *host_sin6; - // struct rta_host *host = host_list; - - // while (host) { - // host_sin = (struct sockaddr_in *)&host->saddr_in; - // host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; - - // if ((address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr) || - // (address_family == AF_INET6 && - // host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) { - // if (debug) { - // printf("Identical IP already exists. Not adding %s\n", name); - // } - // return -1; - // } - // host = host->next; - // } - /* add the fresh ip */ - ping_target host = ping_target_init(); - - /* set the values. use calling name for output */ - host.name = strdup(name); + ping_target target = ping_target_init(); /* fill out the sockaddr_storage struct */ - if (address_family == AF_INET) { - struct sockaddr_in *host_sin = (struct sockaddr_in *)&host.saddr_in; - host_sin->sin_family = AF_INET; - host_sin->sin_addr.s_addr = sin->sin_addr.s_addr; - } else { - struct sockaddr_in6 *host_sin6 = (struct sockaddr_in6 *)&host.saddr_in; - host_sin6->sin6_family = AF_INET6; - memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, - sizeof host_sin6->sin6_addr.s6_addr); - } + target.address = address; - result.host = host; + result.host = target; return result; } diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.h b/plugins-root/check_icmp.d/check_icmp_helpers.h index 5f771635..713dd8ce 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.h +++ b/plugins-root/check_icmp.d/check_icmp_helpers.h @@ -10,10 +10,10 @@ #include typedef struct rta_host { - unsigned short id; /* id in **table, and icmp pkts */ - char *name; /* arg used for adding this host */ - char *msg; /* icmp error message, if any */ - struct sockaddr_storage saddr_in; /* the address of this host */ + unsigned short id; /* id in **table, and icmp pkts */ + char *msg; /* icmp error message, if any */ + + struct sockaddr_storage address; /* the address of this host */ struct sockaddr_storage error_addr; /* stores address of error replies */ time_t time_waited; /* total time waited, in usecs */ unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */ @@ -59,7 +59,12 @@ typedef struct { ping_target host; } ping_target_create_wrapper; -ping_target_create_wrapper ping_target_create(char *name, struct sockaddr_storage *address); +typedef struct { + int socket4; + int socket6; +} check_icmp_socket_set; + +ping_target_create_wrapper ping_target_create(struct sockaddr_storage address); unsigned int ping_target_list_append(ping_target *list, ping_target *elem); void check_icmp_timeout_handler(int, siginfo_t *, void *); diff --git a/plugins-root/check_icmp.d/config.h b/plugins-root/check_icmp.d/config.h index aa33c991..8e9c96b2 100644 --- a/plugins-root/check_icmp.d/config.h +++ b/plugins-root/check_icmp.d/config.h @@ -63,7 +63,10 @@ typedef struct { unsigned int pkt_interval; unsigned int target_interval; unsigned short number_of_packets; + char *source_ip; + bool need_v4; + bool need_v6; uint16_t sender_id; // PID of the main process, which is used as an ID in packets -- cgit v1.2.3-74-g34f1 From d92bbaef8386e77c00ecdeab9fc722fa4b9106b0 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Sun, 18 May 2025 18:46:30 +0200 Subject: Some more fixes --- plugins-root/check_icmp.c | 53 +++++++++++++------------- plugins-root/check_icmp.d/check_icmp_helpers.c | 2 +- plugins-root/check_icmp.d/check_icmp_helpers.h | 4 +- plugins-root/check_icmp.d/config.h | 4 +- 4 files changed, 31 insertions(+), 32 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index d4e55b0d..43eae276 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -147,8 +147,8 @@ static void set_source_ip(char *arg, int icmp_sock, sa_family_t addr_family); /* Receiving data */ static int wait_for_reply(check_icmp_socket_set sockset, time_t time_interval, - unsigned short icmp_pkt_size, unsigned int *pkt_interval, - unsigned int *target_interval, uint16_t sender_id, ping_target **table, + unsigned short icmp_pkt_size, time_t *pkt_interval, + time_t *target_interval, uint16_t sender_id, ping_target **table, unsigned short packets, unsigned short number_of_targets, check_icmp_state *program_state); @@ -160,12 +160,12 @@ static recvfrom_wto_wrapper recvfrom_wto(check_icmp_socket_set sockset, void *bu struct sockaddr *saddr, time_t *timeout, struct timeval *received_timestamp); static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr, - unsigned int *pkt_interval, unsigned int *target_interval, - uint16_t sender_id, ping_target **table, unsigned short packets, + time_t *pkt_interval, time_t *target_interval, uint16_t sender_id, + ping_target **table, unsigned short packets, unsigned short number_of_targets, check_icmp_state *program_state); /* Sending data */ -static int send_icmp_ping(check_icmp_socket_set socket, ping_target *host, +static int send_icmp_ping(check_icmp_socket_set sockset, ping_target *host, unsigned short icmp_pkt_size, uint16_t sender_id, check_icmp_state *program_state); @@ -194,12 +194,11 @@ static parse_threshold2_helper_wrapper parse_threshold2_helper(char *threshold_s threshold_mode mode); /* main test function */ -static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval, - unsigned int *target_interval, uint16_t sender_id, - check_icmp_execution_mode mode, unsigned int max_completion_time, - struct timeval prog_start, ping_target **table, unsigned short packets, - check_icmp_socket_set sockset, unsigned short number_of_targets, - check_icmp_state *program_state); +static void run_checks(unsigned short icmp_pkt_size, time_t *pkt_interval, time_t *target_interval, + uint16_t sender_id, check_icmp_execution_mode mode, + unsigned int max_completion_time, struct timeval prog_start, + ping_target **table, unsigned short packets, check_icmp_socket_set sockset, + unsigned short number_of_targets, check_icmp_state *program_state); mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, check_icmp_threshold warn, check_icmp_threshold crit); @@ -683,7 +682,7 @@ static const char *get_icmp_error_msg(unsigned char icmp_type, unsigned char icm } static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr, - unsigned int *pkt_interval, unsigned int *target_interval, + time_t *pkt_interval, time_t *target_interval, const uint16_t sender_id, ping_target **table, unsigned short packets, const unsigned short number_of_targets, check_icmp_state *program_state) { @@ -899,7 +898,7 @@ int main(int argc, char **argv) { struct timeval prog_start; gettimeofday(&prog_start, NULL); - unsigned int max_completion_time = + time_t max_completion_time = ((config.number_of_targets * config.number_of_packets * config.pkt_interval) + (config.number_of_targets * config.target_interval)) + (config.number_of_targets * config.number_of_packets * config.crit.rta) + config.crit.rta; @@ -916,15 +915,15 @@ int main(int argc, char **argv) { if (debug) { if (max_completion_time > (timeout * 1000000)) { - printf("max_completion_time: %u timeout: %u\n", max_completion_time, timeout); - printf("Timeout must be at least %u\n", (max_completion_time / 1000000) + 1); + printf("max_completion_time: %ld timeout: %u\n", max_completion_time, timeout); + printf("Timeout must be at least %ld\n", (max_completion_time / 1000000) + 1); } } if (debug) { printf("crit = {%u, %u%%}, warn = {%u, %u%%}\n", config.crit.rta, config.crit.pl, config.warn.rta, config.warn.pl); - printf("pkt_interval: %u target_interval: %u\n", config.pkt_interval, + printf("pkt_interval: %ld target_interval: %ld\n", config.pkt_interval, config.target_interval); printf("icmp_pkt_size: %u timeout: %u\n", config.icmp_pkt_size, timeout); } @@ -949,8 +948,8 @@ int main(int argc, char **argv) { target_index++; } - unsigned int pkt_interval = config.pkt_interval; - unsigned int target_interval = config.target_interval; + time_t pkt_interval = config.pkt_interval; + time_t target_interval = config.target_interval; check_icmp_state program_state = check_icmp_state_init(); @@ -975,12 +974,12 @@ int main(int argc, char **argv) { mp_exit(overall); } -static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval, - unsigned int *target_interval, const uint16_t sender_id, - const check_icmp_execution_mode mode, const unsigned int max_completion_time, - const struct timeval prog_start, ping_target **table, - const unsigned short packets, const check_icmp_socket_set sockset, - const unsigned short number_of_targets, check_icmp_state *program_state) { +static void run_checks(unsigned short icmp_pkt_size, time_t *pkt_interval, time_t *target_interval, + const uint16_t sender_id, const check_icmp_execution_mode mode, + const unsigned int max_completion_time, const struct timeval prog_start, + ping_target **table, const unsigned short packets, + const check_icmp_socket_set sockset, const unsigned short number_of_targets, + check_icmp_state *program_state) { /* this loop might actually violate the pkt_interval or target_interval * settings, but only if there aren't any packets on the wire which * indicates that the target can handle an increased packet rate */ @@ -1065,8 +1064,8 @@ static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval, * icmp echo reply : the rest */ static int wait_for_reply(check_icmp_socket_set sockset, const time_t time_interval, - unsigned short icmp_pkt_size, unsigned int *pkt_interval, - unsigned int *target_interval, uint16_t sender_id, ping_target **table, + unsigned short icmp_pkt_size, time_t *pkt_interval, + time_t *target_interval, uint16_t sender_id, ping_target **table, const unsigned short packets, const unsigned short number_of_targets, check_icmp_state *program_state) { union icmp_packet packet; @@ -1568,7 +1567,7 @@ static time_t get_timevaldiff_to_now(struct timeval earlier) { } static add_target_ip_wrapper add_target_ip(struct sockaddr_storage address) { - assert((address.ss_family == AF_INET) || (address.ss_family == AF_INET6)); + assert((address.ss_family == AF_INET) || (address.ss_family == AF_INET6)); if (debug) { char straddr[INET6_ADDRSTRLEN]; diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.c b/plugins-root/check_icmp.d/check_icmp_helpers.c index 47604952..7a936cc9 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.c +++ b/plugins-root/check_icmp.d/check_icmp_helpers.c @@ -43,7 +43,7 @@ check_icmp_config check_icmp_config_init() { .need_v4 = false, .need_v6 = false, - .sender_id = {}, + .sender_id = 0, .mode = MODE_RTA, diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.h b/plugins-root/check_icmp.d/check_icmp_helpers.h index 713dd8ce..1b9372ce 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.h +++ b/plugins-root/check_icmp.d/check_icmp_helpers.h @@ -9,7 +9,7 @@ #include #include -typedef struct rta_host { +typedef struct ping_target { unsigned short id; /* id in **table, and icmp pkts */ char *msg; /* icmp error message, if any */ @@ -32,7 +32,7 @@ typedef struct rta_host { bool found_out_of_order_packets; - struct rta_host *next; + struct ping_target *next; } ping_target; ping_target ping_target_init(); diff --git a/plugins-root/check_icmp.d/config.h b/plugins-root/check_icmp.d/config.h index 8e9c96b2..97be7fc1 100644 --- a/plugins-root/check_icmp.d/config.h +++ b/plugins-root/check_icmp.d/config.h @@ -60,8 +60,8 @@ typedef struct { unsigned long ttl; unsigned short icmp_data_size; unsigned short icmp_pkt_size; - unsigned int pkt_interval; - unsigned int target_interval; + time_t pkt_interval; + time_t target_interval; unsigned short number_of_packets; char *source_ip; -- cgit v1.2.3-74-g34f1 From 3b76fdc8405c4bd9ee5b1d798831a44e811c2fd6 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Sun, 18 May 2025 18:48:49 +0200 Subject: Fix typos --- plugins-root/check_icmp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 43eae276..937bc102 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -211,7 +211,7 @@ evaluate_host_wrapper evaluate_host(check_icmp_target_container host, check_icmp_mode_switches modes, check_icmp_threshold warn, check_icmp_threshold crit); -/* Target aquisition */ +/* Target acquisition */ typedef struct { int error_code; check_icmp_target_container host; @@ -1528,7 +1528,6 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, mp_subcheck sc_min_targets_alive = mp_subcheck_init(); sc_min_targets_alive = mp_set_subcheck_default_state(sc_min_targets_alive, STATE_OK); - // TODO problably broken now if (targets_ok >= min_hosts_alive) { // TODO this should overwrite the main state sc_min_targets_alive = mp_set_subcheck_state(sc_min_targets_alive, STATE_OK); @@ -1635,7 +1634,7 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode switch (enforced_proto) { case AF_UNSPEC: /* - * no enforced protocoll family + * no enforced protocol family * try to parse the address with each one */ sin = (struct sockaddr_in *)&address_storage; -- cgit v1.2.3-74-g34f1 From 738d58714d3845252e210e342e19ae2cec02c5a6 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Sun, 18 May 2025 19:11:14 +0200 Subject: some more fixes --- plugins-root/check_icmp.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 937bc102..139aeff3 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -249,7 +249,7 @@ static void finish(int sign, check_icmp_mode_switches modes, int min_hosts_alive mp_check overall[static 1]); /* Error exit */ -static void crash(const char *fmt, ...); +static void crash(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); /** global variables **/ static int debug = 0; @@ -575,7 +575,7 @@ static void crash(const char *fmt, ...) { puts(""); exit(3); -} +} static const char *get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code) { const char *msg = "unreachable"; @@ -899,8 +899,8 @@ int main(int argc, char **argv) { gettimeofday(&prog_start, NULL); time_t max_completion_time = - ((config.number_of_targets * config.number_of_packets * config.pkt_interval) + - (config.number_of_targets * config.target_interval)) + + ((config.pkt_interval *config.number_of_targets * config.number_of_packets) + + (config.target_interval * config.number_of_targets)) + (config.number_of_targets * config.number_of_packets * config.crit.rta) + config.crit.rta; if (debug) { @@ -1136,8 +1136,9 @@ static int wait_for_reply(check_icmp_socket_set sockset, const time_t time_inter if (recv_foo.received < (hlen + ICMP_MINLEN)) { char address[INET6_ADDRSTRLEN]; parse_address(&resp_addr, address, sizeof(address)); - crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n", + crash("received packet too short for ICMP (%ld bytes, expected %d) from %s\n", recv_foo.received, hlen + icmp_pkt_size, address); + } /* check the response */ memcpy(packet.buf, buf + hlen, icmp_pkt_size); @@ -1271,7 +1272,7 @@ static int send_icmp_ping(const check_icmp_socket_set sockset, ping_target *host data.ping_id = 10; /* host->icmp.icmp_sent; */ memcpy(&data.stime, ¤t_time, sizeof(current_time)); - socklen_t addrlen; + socklen_t addrlen = 0; if (host->address.ss_family == AF_INET) { struct icmp *icp = (struct icmp *)buf; @@ -1317,7 +1318,7 @@ static int send_icmp_ping(const check_icmp_socket_set sockset, ping_target *host } } else { // unknown address family - crash("unknown address family in ", __func__); + crash("unknown address family in %s", __func__); } struct iovec iov; -- cgit v1.2.3-74-g34f1 From 906e895c72fdb29c2ccb1d9665ae416c6e005ae4 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Sun, 18 May 2025 19:19:07 +0200 Subject: Format specifier fixes --- plugins-root/check_icmp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 139aeff3..a57edef4 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -1272,7 +1272,7 @@ static int send_icmp_ping(const check_icmp_socket_set sockset, ping_target *host data.ping_id = 10; /* host->icmp.icmp_sent; */ memcpy(&data.stime, ¤t_time, sizeof(current_time)); - socklen_t addrlen = 0; + socklen_t addrlen; if (host->address.ss_family == AF_INET) { struct icmp *icp = (struct icmp *)buf; @@ -2253,10 +2253,10 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, if (rta >= crit.rta) { sc_rta = mp_set_subcheck_state(sc_rta, STATE_CRITICAL); - xasprintf(&sc_rta.output, "%s > %0.3fms", sc_rta.output, crit.rta / 1000); + xasprintf(&sc_rta.output, "%s > %0.3fms", sc_rta.output, (double) crit.rta / 1000); } else if (rta >= warn.rta) { sc_rta = mp_set_subcheck_state(sc_rta, STATE_WARNING); - xasprintf(&sc_rta.output, "%s > %0.3fms", sc_rta.output, warn.rta / 1000); + xasprintf(&sc_rta.output, "%s > %0.3fms", sc_rta.output, (double) warn.rta / 1000); } if (packet_loss < 100) { @@ -2378,14 +2378,14 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, if (modes.score_mode) { mp_subcheck sc_score = mp_subcheck_init(); sc_score = mp_set_subcheck_default_state(sc_score, STATE_OK); - xasprintf(&sc_score.output, "Score %u", score); + xasprintf(&sc_score.output, "Score %f", score); if (score <= crit.score) { sc_score = mp_set_subcheck_state(sc_score, STATE_CRITICAL); - xasprintf(&sc_score.output, "%s < %u", sc_score.output, crit.score); + xasprintf(&sc_score.output, "%s < %f", sc_score.output, crit.score); } else if (score <= warn.score) { sc_score = mp_set_subcheck_state(sc_score, STATE_WARNING); - xasprintf(&sc_score.output, "%s < %u", sc_score.output, warn.score); + xasprintf(&sc_score.output, "%s < %f", sc_score.output, warn.score); } if (packet_loss < 100) { -- cgit v1.2.3-74-g34f1 From 0f8690c19b352549961c46c75c7307814e255db0 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 9 Jun 2025 12:33:15 +0200 Subject: Remove check_icmp text regex tests --- plugins-root/t/check_icmp.t | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/t/check_icmp.t b/plugins-root/t/check_icmp.t index de1d88d2..2c1d12e6 100644 --- a/plugins-root/t/check_icmp.t +++ b/plugins-root/t/check_icmp.t @@ -18,9 +18,6 @@ if ($allow_sudo eq "yes" or $> == 0) { } my $sudo = $> == 0 ? '' : 'sudo'; -my $successOutput = '/OK - .*? rta (?:[\d\.]+ms)|(?:nan), lost \d+%/'; -my $failureOutput = '/(WARNING|CRITICAL) - .*? rta (?:[\d\.]+ms > [\d\.]+ms|nan)/'; - my $host_responsive = getTestParameter( "NP_HOST_RESPONSIVE", "The hostname of system responsive to network requests", "localhost" ); @@ -39,105 +36,82 @@ $res = NPTest->testCmd( "$sudo ./check_icmp -H $host_responsive -w 10000ms,100% -c 10000ms,100%" ); is( $res->return_code, 0, "Syntax ok" ); -like( $res->output, $successOutput, "Output OK" ); $res = NPTest->testCmd( "$sudo ./check_icmp -H $host_responsive -w 0ms,0% -c 10000ms,100%" ); is( $res->return_code, 1, "Syntax ok, with forced warning" ); -like( $res->output, $failureOutput, "Output OK" ); $res = NPTest->testCmd( "$sudo ./check_icmp -H $host_responsive -w 0,0% -c 0,0%" ); is( $res->return_code, 2, "Syntax ok, with forced critical" ); -like( $res->output, $failureOutput, "Output OK" ); $res = NPTest->testCmd( "$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -t 2" ); is( $res->return_code, 2, "Timeout - host nonresponsive" ); -like( $res->output, '/pl=100%/', "Error contains 'pl=100%' string (for 100% packet loss)" ); -like( $res->output, '/rta=U/', "Error contains 'rta=U' string" ); $res = NPTest->testCmd( "$sudo ./check_icmp -w 10000ms,100% -c 10000ms,100%" ); is( $res->return_code, 3, "No hostname" ); -like( $res->output, '/No hosts to check/', "Output with appropriate error message"); $res = NPTest->testCmd( "$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 0 -t 2" ); is( $res->return_code, 0, "One host nonresponsive - zero required" ); -like( $res->output, $successOutput, "Output OK" ); $res = NPTest->testCmd( "$sudo ./check_icmp -H $host_responsive -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 1 -t 2" ); is( $res->return_code, 0, "One of two host nonresponsive - one required" ); -like( $res->output, $successOutput, "Output OK" ); $res = NPTest->testCmd( "$sudo ./check_icmp -H $host_responsive -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 2" ); is( $res->return_code, 2, "One of two host nonresponsive - two required" ); -like( $res->output, $failureOutput, "Output OK" ); $res = NPTest->testCmd( "$sudo ./check_icmp -H $host_responsive -s 127.0.15.15 -w 10000ms,100% -c 10000ms,100% -n 1 -m 2" ); is( $res->return_code, 0, "IPv4 source_ip accepted" ); -like( $res->output, $successOutput, "Output OK" ); $res = NPTest->testCmd( "$sudo ./check_icmp -H $host_responsive -b 65507" ); is( $res->return_code, 0, "Try max packet size" ); -like( $res->output, $successOutput, "Output OK - Didn't overflow" ); $res = NPTest->testCmd( "$sudo ./check_icmp -H $host_responsive -R 100,100 -n 1 -t 2" ); is( $res->return_code, 0, "rta works" ); -like( $res->output, $successOutput, "Output OK" ); $res = NPTest->testCmd( "$sudo ./check_icmp -H $host_responsive -P 80,90 -n 1 -t 2" ); is( $res->return_code, 0, "pl works" ); -like( $res->output, '/lost 0%/', "Output OK" ); $res = NPTest->testCmd( "$sudo ./check_icmp -H $host_responsive -J 80,90 -t 2" ); is( $res->return_code, 0, "jitter works" ); -like( $res->output, '/jitter \d/', "Output OK" ); $res = NPTest->testCmd( "$sudo ./check_icmp -H $host_responsive -M 4,3 -t 2" ); is( $res->return_code, 0, "mos works" ); -like( $res->output, '/MOS \d/', "Output OK" ); $res = NPTest->testCmd( "$sudo ./check_icmp -H $host_responsive -S 80,70 -t 2" ); is( $res->return_code, 0, "score works" ); -like( $res->output, '/Score \d/', "Output OK" ); $res = NPTest->testCmd( "$sudo ./check_icmp -H $host_responsive -O -t 2" ); is( $res->return_code, 0, "order works" ); -like( $res->output, '/Packets in order/', "Output OK" ); $res = NPTest->testCmd( "$sudo ./check_icmp -H $host_responsive -O -S 80,70 -M 4,3 -J 80,90 -P 80,90 -R 100,100 -t 2" ); is( $res->return_code, 0, "order works" ); -like( $res->output, '/Packets in order/', "Output OK" ); -like( $res->output, '/Score \d/', "Output OK" ); -like( $res->output, '/MOS \d/', "Output OK" ); -like( $res->output, '/jitter \d/', "Output OK" ); -like( $res->output, '/lost 0%/', "Output OK" ); -like( $res->output, $successOutput, "Output OK" ); -- cgit v1.2.3-74-g34f1 From f680cd7b88aef2ff4ef8c4d336ee14269bea65bc Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Tue, 17 Jun 2025 15:19:30 +0200 Subject: Improve error detection for threshold parsers --- plugins-root/check_icmp.c | 98 +++++++++++++++++++++++++------------- plugins-root/check_icmp.d/config.h | 2 +- 2 files changed, 65 insertions(+), 35 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index a57edef4..dad03ffa 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -138,7 +138,11 @@ void print_help(); void print_usage(void); /* Time related */ -static unsigned int get_timevar(const char *str); +typedef struct { + int error_code; + time_t time_range; +} get_timevar_wrapper; +static get_timevar_wrapper get_timevar(const char *str); static time_t get_timevaldiff(struct timeval earlier, struct timeval later); static time_t get_timevaldiff_to_now(struct timeval earlier); @@ -196,8 +200,8 @@ static parse_threshold2_helper_wrapper parse_threshold2_helper(char *threshold_s /* main test function */ static void run_checks(unsigned short icmp_pkt_size, time_t *pkt_interval, time_t *target_interval, uint16_t sender_id, check_icmp_execution_mode mode, - unsigned int max_completion_time, struct timeval prog_start, - ping_target **table, unsigned short packets, check_icmp_socket_set sockset, + time_t max_completion_time, struct timeval prog_start, ping_target **table, + unsigned short packets, check_icmp_socket_set sockset, unsigned short number_of_targets, check_icmp_state *program_state); mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, check_icmp_threshold warn, check_icmp_threshold crit); @@ -249,7 +253,7 @@ static void finish(int sign, check_icmp_mode_switches modes, int min_hosts_alive mp_check overall[static 1]); /* Error exit */ -static void crash(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +static void crash(const char *fmt, ...) __attribute__((format(printf, 1, 2))); /** global variables **/ static int debug = 0; @@ -384,12 +388,24 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { MAX_PING_DATA - 1); } } break; - case 'i': - result.config.pkt_interval = get_timevar(optarg); - break; - case 'I': - result.config.target_interval = get_timevar(optarg); - break; + case 'i': { + get_timevar_wrapper parsed_time = get_timevar(optarg); + + if (parsed_time.error_code == OK) { + result.config.pkt_interval = parsed_time.time_range; + } else { + crash("failed to parse packet interval"); + } + } break; + case 'I': { + get_timevar_wrapper parsed_time = get_timevar(optarg); + + if (parsed_time.error_code == OK) { + result.config.target_interval = parsed_time.time_range; + } else { + crash("failed to parse target interval"); + } + } break; case 'w': { get_threshold_wrapper warn = get_threshold(optarg, result.config.warn); if (warn.errorcode == OK) { @@ -575,7 +591,7 @@ static void crash(const char *fmt, ...) { puts(""); exit(3); -} +} static const char *get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code) { const char *msg = "unreachable"; @@ -743,8 +759,8 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad /* source quench means we're sending too fast, so increase the * interval and mark this packet lost */ if (icmp_packet.icmp_type == ICMP_SOURCEQUENCH) { - *pkt_interval = (unsigned int)(*pkt_interval * PACKET_BACKOFF_FACTOR); - *target_interval = (unsigned int)(*target_interval * TARGET_BACKOFF_FACTOR); + *pkt_interval = (unsigned int)((double)*pkt_interval * PACKET_BACKOFF_FACTOR); + *target_interval = (unsigned int)((double)*target_interval * TARGET_BACKOFF_FACTOR); } else { program_state->targets_down++; host->flags |= FLAG_LOST_CAUSE; @@ -899,7 +915,7 @@ int main(int argc, char **argv) { gettimeofday(&prog_start, NULL); time_t max_completion_time = - ((config.pkt_interval *config.number_of_targets * config.number_of_packets) + + ((config.pkt_interval * config.number_of_targets * config.number_of_packets) + (config.target_interval * config.number_of_targets)) + (config.number_of_targets * config.number_of_packets * config.crit.rta) + config.crit.rta; @@ -921,7 +937,7 @@ int main(int argc, char **argv) { } if (debug) { - printf("crit = {%u, %u%%}, warn = {%u, %u%%}\n", config.crit.rta, config.crit.pl, + printf("crit = {%ld, %u%%}, warn = {%ld, %u%%}\n", config.crit.rta, config.crit.pl, config.warn.rta, config.warn.pl); printf("pkt_interval: %ld target_interval: %ld\n", config.pkt_interval, config.target_interval); @@ -976,7 +992,7 @@ int main(int argc, char **argv) { static void run_checks(unsigned short icmp_pkt_size, time_t *pkt_interval, time_t *target_interval, const uint16_t sender_id, const check_icmp_execution_mode mode, - const unsigned int max_completion_time, const struct timeval prog_start, + const time_t max_completion_time, const struct timeval prog_start, ping_target **table, const unsigned short packets, const check_icmp_socket_set sockset, const unsigned short number_of_targets, check_icmp_state *program_state) { @@ -1028,7 +1044,7 @@ static void run_checks(unsigned short icmp_pkt_size, time_t *pkt_interval, time_ time_t final_wait = max_completion_time - time_passed; if (debug) { - printf("time_passed: %ld final_wait: %ld max_completion_time: %u\n", time_passed, + printf("time_passed: %ld final_wait: %ld max_completion_time: %ld\n", time_passed, final_wait, max_completion_time); } if (time_passed > max_completion_time) { @@ -1138,7 +1154,6 @@ static int wait_for_reply(check_icmp_socket_set sockset, const time_t time_inter parse_address(&resp_addr, address, sizeof(address)); crash("received packet too short for ICMP (%ld bytes, expected %d) from %s\n", recv_foo.received, hlen + icmp_pkt_size, address); - } /* check the response */ memcpy(packet.buf, buf + hlen, icmp_pkt_size); @@ -1272,7 +1287,7 @@ static int send_icmp_ping(const check_icmp_socket_set sockset, ping_target *host data.ping_id = 10; /* host->icmp.icmp_sent; */ memcpy(&data.stime, ¤t_time, sizeof(current_time)); - socklen_t addrlen; + socklen_t addrlen = 0; if (host->address.ss_family == AF_INET) { struct icmp *icp = (struct icmp *)buf; @@ -1789,14 +1804,21 @@ static in_addr_t get_ip_address(const char *ifname) { * s = seconds * return value is in microseconds */ -static unsigned int get_timevar(const char *str) { +static get_timevar_wrapper get_timevar(const char *str) { + get_timevar_wrapper result = { + .error_code = OK, + .time_range = 0, + }; + if (!str) { - return 0; + result.error_code = ERROR; + return result; } size_t len = strlen(str); if (!len) { - return 0; + result.error_code = ERROR; + return result; } /* unit might be given as ms|m (millisec), @@ -1834,12 +1856,14 @@ static unsigned int get_timevar(const char *str) { unsigned long pre_radix; pre_radix = strtoul(str, &ptr, 0); if (!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1) { - return (unsigned int)(pre_radix * factor); + result.time_range = (unsigned int)(pre_radix * factor); + return result; } /* time specified in usecs can't have decimal points, so ignore them */ if (factor == 1) { - return (unsigned int)pre_radix; + result.time_range = (unsigned int)pre_radix; + return result; } /* integer and decimal, respectively */ @@ -1851,10 +1875,10 @@ static unsigned int get_timevar(const char *str) { } /* the last parenthesis avoids floating point exceptions. */ - return (unsigned int)((pre_radix * factor) + (post_radix * (factor / 10))); + result.time_range = (unsigned int)((pre_radix * factor) + (post_radix * (factor / 10))); + return result; } -/* not too good at checking errors, but it'll do (main() should barfe on -1) */ static get_threshold_wrapper get_threshold(char *str, check_icmp_threshold threshold) { get_threshold_wrapper result = { .errorcode = OK, @@ -1880,9 +1904,15 @@ static get_threshold_wrapper get_threshold(char *str, check_icmp_threshold thres is_at_last_char = true; tmp--; } - result.threshold.rta = get_timevar(str); - if (!result.threshold.rta) { + get_timevar_wrapper parsed_time = get_timevar(str); + + if (parsed_time.error_code == OK) { + result.threshold.rta = parsed_time.time_range; + } else { + if (debug > 1) { + printf("%s: failed to parse rta threshold\n", __FUNCTION__); + } result.errorcode = ERROR; return result; } @@ -2170,7 +2200,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, xasprintf(&result.output, "%s", address); double packet_loss; - double rta; + time_t rta; if (!target.icmp_recv) { /* rta 0 is of course not entirely correct, but will still show up * conspicuously as missing entries in perfparse and cacti */ @@ -2188,7 +2218,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, } else { packet_loss = (unsigned char)((target.icmp_sent - target.icmp_recv) * 100) / target.icmp_sent; - rta = (double)target.time_waited / target.icmp_recv; + rta = target.time_waited / target.icmp_recv; } double EffectiveLatency; @@ -2219,7 +2249,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, * round trip jitter, but double the impact to latency * then add 10 for protocol latencies (in milliseconds). */ - EffectiveLatency = (rta / 1000) + target.jitter * 2 + 10; + EffectiveLatency = ((double)rta / 1000) + target.jitter * 2 + 10; double R; if (EffectiveLatency < 160) { @@ -2249,14 +2279,14 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, if (modes.rta_mode) { mp_subcheck sc_rta = mp_subcheck_init(); sc_rta = mp_set_subcheck_default_state(sc_rta, STATE_OK); - xasprintf(&sc_rta.output, "rta %0.3fms", rta / 1000); + xasprintf(&sc_rta.output, "rta %0.3fms", (double)rta / 1000); if (rta >= crit.rta) { sc_rta = mp_set_subcheck_state(sc_rta, STATE_CRITICAL); - xasprintf(&sc_rta.output, "%s > %0.3fms", sc_rta.output, (double) crit.rta / 1000); + xasprintf(&sc_rta.output, "%s > %0.3fms", sc_rta.output, (double)crit.rta / 1000); } else if (rta >= warn.rta) { sc_rta = mp_set_subcheck_state(sc_rta, STATE_WARNING); - xasprintf(&sc_rta.output, "%s > %0.3fms", sc_rta.output, (double) warn.rta / 1000); + xasprintf(&sc_rta.output, "%s > %0.3fms", sc_rta.output, (double)warn.rta / 1000); } if (packet_loss < 100) { diff --git a/plugins-root/check_icmp.d/config.h b/plugins-root/check_icmp.d/config.h index 97be7fc1..fc9dd5a6 100644 --- a/plugins-root/check_icmp.d/config.h +++ b/plugins-root/check_icmp.d/config.h @@ -16,7 +16,7 @@ /* threshold structure. all values are maximum allowed, exclusive */ typedef struct { unsigned char pl; /* max allowed packet loss in percent */ - unsigned int rta; /* roundtrip time average, microseconds */ + time_t rta; /* roundtrip time average, microseconds */ double jitter; /* jitter time average, microseconds */ double mos; /* MOS */ double score; /* Score */ -- cgit v1.2.3-74-g34f1 From 43ae5fbe2df66c6c3169528431b6b0c9c6bfd67c Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Tue, 17 Jun 2025 15:44:35 +0200 Subject: Fix possible multiplication overflow? --- plugins-root/check_icmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index dad03ffa..7ee08ad9 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -917,7 +917,7 @@ int main(int argc, char **argv) { time_t max_completion_time = ((config.pkt_interval * config.number_of_targets * config.number_of_packets) + (config.target_interval * config.number_of_targets)) + - (config.number_of_targets * config.number_of_packets * config.crit.rta) + config.crit.rta; + (config.crit.rta * config.number_of_targets * config.number_of_packets) + config.crit.rta; if (debug) { printf("packets: %u, targets: %u\n" -- cgit v1.2.3-74-g34f1 From ca954e4f765ea336e4aef633b38c31a7c6a99d75 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Thu, 19 Jun 2025 00:55:41 +0200 Subject: Reintroduce min_hosts_alive --- plugins-root/check_icmp.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 7ee08ad9..b97a68ed 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -1515,6 +1515,9 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, targets_alive(number_of_targets, program_state->targets_down)); } + mp_subcheck sc_single_targets = mp_subcheck_init(); + xasprintf(&sc_single_targets.output, "Individual Hosts"); + // loop over targets to evaluate each one int targets_ok = 0; int targets_warn = 0; @@ -1524,7 +1527,15 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, targets_ok += host_check.targets_ok; targets_warn += host_check.targets_warn; - mp_add_subcheck_to_check(overall, host_check.sc_host); + if (min_hosts_alive > -1) { + mp_add_subcheck_to_subcheck(&sc_single_targets, host_check.sc_host); + } else { + mp_add_subcheck_to_check(overall, host_check.sc_host); + } + } + + if (min_hosts_alive > -1) { + mp_add_subcheck_to_check(overall, sc_single_targets); } if (number_of_hosts == 1) { @@ -1545,11 +1556,20 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, sc_min_targets_alive = mp_set_subcheck_default_state(sc_min_targets_alive, STATE_OK); if (targets_ok >= min_hosts_alive) { - // TODO this should overwrite the main state sc_min_targets_alive = mp_set_subcheck_state(sc_min_targets_alive, STATE_OK); + xasprintf(&sc_min_targets_alive.output, "%u targets OK of a minimum of %u", + targets_ok, min_hosts_alive); } else if ((targets_ok + targets_warn) >= min_hosts_alive) { sc_min_targets_alive = mp_set_subcheck_state(sc_min_targets_alive, STATE_WARNING); + xasprintf(&sc_min_targets_alive.output, "%u targets OK or Warning of a minimum of %u", + targets_ok + targets_warn, min_hosts_alive); + } else { + sc_min_targets_alive = mp_set_subcheck_state(sc_min_targets_alive, STATE_CRITICAL); + xasprintf(&sc_min_targets_alive.output, "%u targets OK or Warning of a minimum of %u", + targets_ok + targets_warn, min_hosts_alive); } + + mp_add_subcheck_to_check(overall, sc_min_targets_alive); } /* finish with an empty line */ -- cgit v1.2.3-74-g34f1 From 20e938bb542d361ad1468ab24330f554445aefb1 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Thu, 19 Jun 2025 01:15:37 +0200 Subject: Override state with min_hosts_alive --- plugins-root/check_icmp.c | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index b97a68ed..7360b435 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -1515,9 +1515,6 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, targets_alive(number_of_targets, program_state->targets_down)); } - mp_subcheck sc_single_targets = mp_subcheck_init(); - xasprintf(&sc_single_targets.output, "Individual Hosts"); - // loop over targets to evaluate each one int targets_ok = 0; int targets_warn = 0; @@ -1527,29 +1524,16 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, targets_ok += host_check.targets_ok; targets_warn += host_check.targets_warn; - if (min_hosts_alive > -1) { - mp_add_subcheck_to_subcheck(&sc_single_targets, host_check.sc_host); - } else { - mp_add_subcheck_to_check(overall, host_check.sc_host); - } - } - - if (min_hosts_alive > -1) { - mp_add_subcheck_to_check(overall, sc_single_targets); - } - - if (number_of_hosts == 1) { - // Exit early here, since the other checks only make sense for multiple hosts - return; + mp_add_subcheck_to_check(overall, host_check.sc_host); } /* this is inevitable */ - if (targets_alive(number_of_targets, program_state->targets_down) == 0) { - mp_subcheck sc_no_target_alive = mp_subcheck_init(); - sc_no_target_alive = mp_set_subcheck_state(sc_no_target_alive, STATE_CRITICAL); - sc_no_target_alive.output = strdup("No target is alive!"); - mp_add_subcheck_to_check(overall, sc_no_target_alive); - } + // if (targets_alive(number_of_targets, program_state->targets_down) == 0) { + // mp_subcheck sc_no_target_alive = mp_subcheck_init(); + // sc_no_target_alive = mp_set_subcheck_state(sc_no_target_alive, STATE_CRITICAL); + // sc_no_target_alive.output = strdup("No target is alive!"); + // mp_add_subcheck_to_check(overall, sc_no_target_alive); + // } if (min_hosts_alive > -1) { mp_subcheck sc_min_targets_alive = mp_subcheck_init(); @@ -1557,16 +1541,21 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, if (targets_ok >= min_hosts_alive) { sc_min_targets_alive = mp_set_subcheck_state(sc_min_targets_alive, STATE_OK); - xasprintf(&sc_min_targets_alive.output, "%u targets OK of a minimum of %u", - targets_ok, min_hosts_alive); + xasprintf(&sc_min_targets_alive.output, "%u targets OK of a minimum of %u", targets_ok, + min_hosts_alive); + + // Overwrite main state here + overall->evaluation_function = &mp_eval_ok; } else if ((targets_ok + targets_warn) >= min_hosts_alive) { sc_min_targets_alive = mp_set_subcheck_state(sc_min_targets_alive, STATE_WARNING); xasprintf(&sc_min_targets_alive.output, "%u targets OK or Warning of a minimum of %u", targets_ok + targets_warn, min_hosts_alive); + overall->evaluation_function = &mp_eval_warning; } else { sc_min_targets_alive = mp_set_subcheck_state(sc_min_targets_alive, STATE_CRITICAL); xasprintf(&sc_min_targets_alive.output, "%u targets OK or Warning of a minimum of %u", targets_ok + targets_warn, min_hosts_alive); + overall->evaluation_function = &mp_eval_critical; } mp_add_subcheck_to_check(overall, sc_min_targets_alive); -- cgit v1.2.3-74-g34f1 From 2bea8e9522af1c454d1a6a618402f9f342730406 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Fri, 20 Jun 2025 10:04:34 +0200 Subject: check_icmp: Remove signal handling and timeouts The timeout option was redundant in that the runtime of check_icmp was always limited by the input parameters and therefore timeout gets removed with this commit to avoid that confusion. The rest of the signal handlings was removed too, since the added complexity does not provide sufficient returns. If check_icmp gets a signal, it now dies like most other programs instead of trying to save some things and return a (arguably wrong) result. --- plugins-root/check_icmp.c | 18 +--------------- plugins-root/check_icmp.d/check_icmp_helpers.c | 19 ---------------- plugins-root/check_icmp.d/check_icmp_helpers.h | 2 -- plugins-root/t/check_icmp.t | 30 +++++++++++++------------- 4 files changed, 16 insertions(+), 53 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 7360b435..55405b8a 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -431,8 +431,7 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { } break; case 't': - timeout = (unsigned int)strtoul(optarg, NULL, 0); - // TODO die here and complain about wrong input + // WARNING Deprecated since execution time is determined by the other factors break; case 'H': { add_host_wrapper host_add_result = @@ -895,21 +894,6 @@ int main(int argc, char **argv) { } } - struct sigaction sig_action; - sig_action.sa_handler = NULL; - sig_action.sa_sigaction = check_icmp_timeout_handler; - sigfillset(&sig_action.sa_mask); - sig_action.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO; - - sigaction(SIGINT, &sig_action, NULL); - sigaction(SIGHUP, &sig_action, NULL); - sigaction(SIGTERM, &sig_action, NULL); - sigaction(SIGALRM, &sig_action, NULL); - if (debug) { - printf("Setting alarm timeout to %u seconds\n", timeout); - } - alarm(timeout); - /* make sure we don't wait any longer than necessary */ struct timeval prog_start; gettimeofday(&prog_start, NULL); diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.c b/plugins-root/check_icmp.d/check_icmp_helpers.c index 7a936cc9..ec786305 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.c +++ b/plugins-root/check_icmp.d/check_icmp_helpers.c @@ -132,22 +132,3 @@ unsigned int ping_target_list_append(ping_target *list, ping_target *elem) { return result; } - -void check_icmp_timeout_handler(int signal, siginfo_t *info, void *ucontext) { - // Ignore unused arguments - (void)info; - (void)ucontext; - mp_subcheck timeout_sc = mp_subcheck_init(); - timeout_sc = mp_set_subcheck_state(timeout_sc, socket_timeout_state); - - if (signal == SIGALRM) { - xasprintf(&timeout_sc.output, _("timeout after %d seconds\n"), timeout); - } else { - xasprintf(&timeout_sc.output, _("timeout after %d seconds\n"), timeout); - } - - mp_check overall = mp_check_init(); - mp_add_subcheck_to_check(&overall, timeout_sc); - - mp_exit(overall); -} diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.h b/plugins-root/check_icmp.d/check_icmp_helpers.h index 1b9372ce..dc6ea40b 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.h +++ b/plugins-root/check_icmp.d/check_icmp_helpers.h @@ -66,5 +66,3 @@ typedef struct { ping_target_create_wrapper ping_target_create(struct sockaddr_storage address); unsigned int ping_target_list_append(ping_target *list, ping_target *elem); - -void check_icmp_timeout_handler(int, siginfo_t *, void *); diff --git a/plugins-root/t/check_icmp.t b/plugins-root/t/check_icmp.t index 2c1d12e6..e68617cd 100644 --- a/plugins-root/t/check_icmp.t +++ b/plugins-root/t/check_icmp.t @@ -33,12 +33,12 @@ my $hostname_invalid = getTestParameter( "NP_HOSTNAME_INVALID", my $res; $res = NPTest->testCmd( - "$sudo ./check_icmp -H $host_responsive -w 10000ms,100% -c 10000ms,100%" + "$sudo ./check_icmp -H $host_responsive -w 100ms,100% -c 100ms,100%" ); is( $res->return_code, 0, "Syntax ok" ); $res = NPTest->testCmd( - "$sudo ./check_icmp -H $host_responsive -w 0ms,0% -c 10000ms,100%" + "$sudo ./check_icmp -H $host_responsive -w 0ms,0% -c 100ms,100%" ); is( $res->return_code, 1, "Syntax ok, with forced warning" ); @@ -48,32 +48,32 @@ $res = NPTest->testCmd( is( $res->return_code, 2, "Syntax ok, with forced critical" ); $res = NPTest->testCmd( - "$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -t 2" + "$sudo ./check_icmp -H $host_nonresponsive -w 100ms,100% -c 100ms,100%" ); is( $res->return_code, 2, "Timeout - host nonresponsive" ); $res = NPTest->testCmd( - "$sudo ./check_icmp -w 10000ms,100% -c 10000ms,100%" + "$sudo ./check_icmp -w 100ms,100% -c 100ms,100%" ); is( $res->return_code, 3, "No hostname" ); $res = NPTest->testCmd( - "$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 0 -t 2" + "$sudo ./check_icmp -H $host_nonresponsive -w 100ms,100% -c 100ms,100% -n 1 -m 0" ); is( $res->return_code, 0, "One host nonresponsive - zero required" ); $res = NPTest->testCmd( - "$sudo ./check_icmp -H $host_responsive -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 1 -t 2" + "$sudo ./check_icmp -H $host_responsive -H $host_nonresponsive -w 100ms,100% -c 100ms,100% -n 1 -m 1" ); is( $res->return_code, 0, "One of two host nonresponsive - one required" ); $res = NPTest->testCmd( - "$sudo ./check_icmp -H $host_responsive -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 2" + "$sudo ./check_icmp -H $host_responsive -H $host_nonresponsive -w 100ms,100% -c 100ms,100% -n 1 -m 2" ); is( $res->return_code, 2, "One of two host nonresponsive - two required" ); $res = NPTest->testCmd( - "$sudo ./check_icmp -H $host_responsive -s 127.0.15.15 -w 10000ms,100% -c 10000ms,100% -n 1 -m 2" + "$sudo ./check_icmp -H $host_responsive -s 127.0.15.15 -w 100ms,100% -c 100ms,100% -n 1 -m 2" ); is( $res->return_code, 0, "IPv4 source_ip accepted" ); @@ -83,35 +83,35 @@ $res = NPTest->testCmd( is( $res->return_code, 0, "Try max packet size" ); $res = NPTest->testCmd( - "$sudo ./check_icmp -H $host_responsive -R 100,100 -n 1 -t 2" + "$sudo ./check_icmp -H $host_responsive -R 100,100 -n 1" ); is( $res->return_code, 0, "rta works" ); $res = NPTest->testCmd( - "$sudo ./check_icmp -H $host_responsive -P 80,90 -n 1 -t 2" + "$sudo ./check_icmp -H $host_responsive -P 80,90 -n 1" ); is( $res->return_code, 0, "pl works" ); $res = NPTest->testCmd( - "$sudo ./check_icmp -H $host_responsive -J 80,90 -t 2" + "$sudo ./check_icmp -H $host_responsive -J 80,90" ); is( $res->return_code, 0, "jitter works" ); $res = NPTest->testCmd( - "$sudo ./check_icmp -H $host_responsive -M 4,3 -t 2" + "$sudo ./check_icmp -H $host_responsive -M 4,3" ); is( $res->return_code, 0, "mos works" ); $res = NPTest->testCmd( - "$sudo ./check_icmp -H $host_responsive -S 80,70 -t 2" + "$sudo ./check_icmp -H $host_responsive -S 80,70" ); is( $res->return_code, 0, "score works" ); $res = NPTest->testCmd( - "$sudo ./check_icmp -H $host_responsive -O -t 2" + "$sudo ./check_icmp -H $host_responsive -O" ); is( $res->return_code, 0, "order works" ); $res = NPTest->testCmd( - "$sudo ./check_icmp -H $host_responsive -O -S 80,70 -M 4,3 -J 80,90 -P 80,90 -R 100,100 -t 2" + "$sudo ./check_icmp -H $host_responsive -O -S 80,70 -M 4,3 -J 80,90 -P 80,90 -R 100,100" ); is( $res->return_code, 0, "order works" ); -- cgit v1.2.3-74-g34f1 From 6bc2e75199519d0a7677dff09137558ef6eb761c Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Fri, 20 Jun 2025 10:28:45 +0200 Subject: Fix test with weird arguments --- plugins-root/t/check_icmp.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins-root') diff --git a/plugins-root/t/check_icmp.t b/plugins-root/t/check_icmp.t index e68617cd..cbf3dda5 100644 --- a/plugins-root/t/check_icmp.t +++ b/plugins-root/t/check_icmp.t @@ -73,7 +73,7 @@ $res = NPTest->testCmd( is( $res->return_code, 2, "One of two host nonresponsive - two required" ); $res = NPTest->testCmd( - "$sudo ./check_icmp -H $host_responsive -s 127.0.15.15 -w 100ms,100% -c 100ms,100% -n 1 -m 2" + "$sudo ./check_icmp -H $host_responsive -s 127.0.15.15 -w 100ms,100% -c 100ms,100% -n 1" ); is( $res->return_code, 0, "IPv4 source_ip accepted" ); -- cgit v1.2.3-74-g34f1 From d2735eecd4c44ba4a2504304963e861a427e393e Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Fri, 20 Jun 2025 10:53:46 +0200 Subject: Fix number of tests --- plugins-root/t/check_icmp.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins-root') diff --git a/plugins-root/t/check_icmp.t b/plugins-root/t/check_icmp.t index cbf3dda5..d414c3c7 100644 --- a/plugins-root/t/check_icmp.t +++ b/plugins-root/t/check_icmp.t @@ -12,7 +12,7 @@ my $allow_sudo = getTestParameter( "NP_ALLOW_SUDO", "no" ); if ($allow_sudo eq "yes" or $> == 0) { - plan tests => 40; + plan tests => 17; } else { plan skip_all => "Need sudo to test check_icmp"; } -- cgit v1.2.3-74-g34f1 From 8ae415ee4ceddeed1c1a1e0e6e64175cff6731c3 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 23 Jun 2025 09:26:13 +0200 Subject: Improve check_icmp help output --- plugins-root/check_icmp.c | 48 +++++++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 29 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 55405b8a..0c69d31c 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -2045,32 +2045,32 @@ unsigned short icmp_checksum(uint16_t *packet, size_t packet_size) { } void print_help(void) { - /*print_revision (progname);*/ /* FIXME: Why? */ + // print_revision (progname); /* FIXME: Why? */ printf("Copyright (c) 2005 Andreas Ericsson \n"); printf(COPYRIGHT, copyright, email); - printf("\n\n"); - print_usage(); printf(UT_HELP_VRSN); printf(UT_EXTRA_OPTS); printf(" %s\n", "-H"); - printf(" %s\n", _("specify a target")); + printf(" %s\n", + _("specify a target, might be one of: resolveable name, IPv6 address, IPv4 address " + "(necessary, can be given multiple times)")); printf(" %s\n", "[-4|-6]"); - printf(" %s\n", _("Use IPv4 (default) or IPv6 to communicate with the targets")); + printf(" %s\n", _("Use IPv4 or IPv6 only to communicate with the targets")); printf(" %s\n", "-w"); - printf(" %s", _("warning threshold (currently ")); + printf(" %s", _("warning threshold (default ")); printf("%0.3fms,%u%%)\n", (float)DEFAULT_WARN_RTA / 1000, DEFAULT_WARN_PL); printf(" %s\n", "-c"); - printf(" %s", _("critical threshold (currently ")); + printf(" %s", _("critical threshold (default ")); printf("%0.3fms,%u%%)\n", (float)DEFAULT_CRIT_RTA / 1000, DEFAULT_CRIT_PL); printf(" %s\n", "-R"); printf(" %s\n", - _("RTA, round trip average, mode warning,critical, ex. 100ms,200ms unit in ms")); + _("RTA (round trip average) mode warning,critical, ex. 100ms,200ms unit in ms")); printf(" %s\n", "-P"); printf(" %s\n", _("packet loss mode, ex. 40%,50% , unit in %")); printf(" %s\n", "-J"); @@ -2080,42 +2080,34 @@ void print_help(void) { printf(" %s\n", "-S"); printf(" %s\n", _("score mode, max value 100 warning,critical, ex. 80,70 ")); printf(" %s\n", "-O"); - printf(" %s\n", _("detect out of order ICMP packts ")); - printf(" %s\n", "-H"); - printf(" %s\n", _("specify a target")); - printf(" %s\n", "-s"); - printf(" %s\n", _("specify a source IP address or device name")); + printf(" %s\n", + _("detect out of order ICMP packts, if such packets are found, the result is CRITICAL")); printf(" %s\n", "-n"); - printf(" %s", _("number of packets to send (currently ")); - printf("%u)\n", DEFAULT_NUMBER_OF_PACKETS); printf(" %s\n", "-p"); - printf(" %s", _("number of packets to send (currently ")); + printf(" %s", _("number of packets to send (default ")); printf("%u)\n", DEFAULT_NUMBER_OF_PACKETS); printf(" %s\n", "-i"); - printf(" %s", _("max packet interval (currently ")); + printf(" %s", _("max packet interval (default ")); printf("%0.3fms)\n", (float)DEFAULT_PKT_INTERVAL / 1000); printf(" %s\n", "-I"); - printf(" %s", _("max target interval (currently ")); - printf("%0.3fms)\n", (float)DEFAULT_TARGET_INTERVAL / 1000); + printf(" %s%0.3fms)\n The time intervall to wait in between one target and the next", + _("max target interval (default "), (float)DEFAULT_TARGET_INTERVAL / 1000); printf(" %s\n", "-m"); printf(" %s", _("number of alive hosts required for success")); printf("\n"); printf(" %s\n", "-l"); - printf(" %s", _("TTL on outgoing packets (currently ")); + printf(" %s", _("TTL on outgoing packets (default ")); printf("%u)\n", DEFAULT_TTL); - printf(" %s\n", "-t"); - printf(" %s", _("timeout value (seconds, currently ")); - printf("%u)\n", DEFAULT_TIMEOUT); printf(" %s\n", "-b"); printf(" %s\n", _("Number of icmp data bytes to send")); - printf(" %s %lu + %d)\n", _("Packet size will be data bytes + icmp header (currently"), + printf(" %s %lu + %d)\n", _("Packet size will be data bytes + icmp header (default"), DEFAULT_PING_DATA_SIZE, ICMP_MINLEN); printf(" %s\n", "-v"); - printf(" %s\n", _("verbose")); + printf(" %s\n", _("Verbosity, can be given multiple times (for debugging)")); printf("\n"); printf("%s\n", _("Notes:")); printf(" %s\n", _("If none of R,P,J,M,S or O is specified, default behavior is -R -P")); - printf(" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not.")); + printf(" %s\n", _("Naming a host (or several) to check is not.")); printf("\n"); printf(" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%")); printf(" %s\n", _("packet loss. The default values should work well for most users.")); @@ -2128,8 +2120,6 @@ void print_help(void) { hops")); printf ("%s\n", _("are spent and CRITICAL if >= 14 hops are spent.")); printf ("%s\n\n", _("NOTE: Some systems decrease TTL when forming ICMP_ECHOREPLY, others do not."));*/ - printf("\n"); - printf(" %s\n", _("The -v switch can be specified several times for increased verbosity.")); /* printf ("%s\n", _("Long options are currently unsupported.")); printf ("%s\n", _("Options marked with * require an argument")); */ @@ -2139,7 +2129,7 @@ void print_help(void) { void print_usage(void) { printf("%s\n", _("Usage:")); - printf(" %s [options] [-H] host1 host2 hostN\n", progname); + printf(" %s [options] [-H host1 [-H host2 [-H hostN]]]\n", progname); } static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode, -- cgit v1.2.3-74-g34f1 From cd20cc063245523d51013849fa28eb0cac013171 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 23 Jun 2025 10:17:28 +0200 Subject: check_icmp: add long options, add output format option This commit switches check_icmp from getopt to getopt_long to provide long options too and (most importantly) homogenize option parsing between the different plugins. --- plugins-root/check_icmp.c | 52 +++++++++++++++++++++++++- plugins-root/check_icmp.d/check_icmp_helpers.c | 2 + plugins-root/check_icmp.d/config.h | 6 ++- 3 files changed, 57 insertions(+), 3 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 0c69d31c..bad73cc4 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -319,12 +319,41 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { sa_family_t enforced_ai_family = AF_UNSPEC; + enum { + output_format_index = CHAR_MAX + 1, + }; + + struct option longopts[] = { + {"version", no_argument, 0, 'V'}, + {"help", no_argument, 0, 'h'}, + {"verbose", no_argument, 0, 'v'}, + {"Host", required_argument, 0, 'H'}, + {"ipv4-only", no_argument, 0, '4'}, + {"ipv6-only", no_argument, 0, '6'}, + {"warning", required_argument, 0, 'w'}, + {"critical", required_argument, 0, 'c'}, + {"rta-mode-thresholds", required_argument, 0, 'R'}, + {"packet-loss-mode-thresholds", required_argument, 0, 'P'}, + {"jitter-mode-thresholds", required_argument, 0, 'J'}, + {"mos-mode-thresholds", required_argument, 0, 'M'}, + {"score-mode-thresholds", required_argument, 0, 'S'}, + {"out-of-order-packets", no_argument, 0, 'O'}, + {"number-of-packets", required_argument, 0, 'n'}, + {"number-of-packets", required_argument, 0, 'p'}, + {"packet-interval", required_argument, 0, 'i'}, + {"target-interval", required_argument, 0, 'I'}, + {"outgoing-ttl", required_argument, 0, 'l'}, + {"packet_payload_size", required_argument, 0, 'b'}, + {"output-format", required_argument, 0, output_format_index}, + {}, + }; + // Parse protocol arguments first // and count hosts here char *opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64"; for (int i = 1; i < argc; i++) { long int arg; - while ((arg = getopt(argc, argv, opts_str)) != EOF) { + while ((arg = getopt_long(argc, argv, opts_str, longopts, NULL)) != EOF) { switch (arg) { case '4': if (enforced_ai_family != AF_UNSPEC) { @@ -374,7 +403,7 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { /* parse the arguments */ for (int i = 1; i < argc; i++) { long int arg; - while ((arg = getopt(argc, argv, opts_str)) != EOF) { + while ((arg = getopt_long(argc, argv, opts_str, longopts, NULL)) != EOF) { switch (arg) { case 'b': { long size = strtol(optarg, NULL, 0); @@ -536,6 +565,18 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { case 'O': /* out of order mode */ result.config.modes.order_mode = true; break; + case output_format_index: { + parsed_output_format parser = mp_parse_output_format(optarg); + if (!parser.parsing_success) { + // TODO List all available formats here, maybe add anothoer usage function + printf("Invalid output format: %s\n", optarg); + exit(STATE_UNKNOWN); + } + + result.config.output_format_is_set = true; + result.config.output_format = parser.output_format; + break; + } } } } @@ -803,6 +844,10 @@ int main(int argc, char **argv) { const check_icmp_config config = tmp_config.config; + if (config.output_format_is_set) { + mp_set_format(config.output_format); + } + // int icmp_proto = IPPROTO_ICMP; // add_target might change address_family // switch (address_family) { @@ -2104,6 +2149,9 @@ void print_help(void) { DEFAULT_PING_DATA_SIZE, ICMP_MINLEN); printf(" %s\n", "-v"); printf(" %s\n", _("Verbosity, can be given multiple times (for debugging)")); + + printf(UT_OUTPUT_FORMAT); + printf("\n"); printf("%s\n", _("Notes:")); printf(" %s\n", _("If none of R,P,J,M,S or O is specified, default behavior is -R -P")); diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.c b/plugins-root/check_icmp.d/check_icmp_helpers.c index ec786305..9acc96fd 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.c +++ b/plugins-root/check_icmp.d/check_icmp_helpers.c @@ -52,6 +52,8 @@ check_icmp_config check_icmp_config_init() { .number_of_hosts = 0, .hosts = NULL, + + .output_format_is_set = false, }; return tmp; } diff --git a/plugins-root/check_icmp.d/config.h b/plugins-root/check_icmp.d/config.h index fc9dd5a6..8092e343 100644 --- a/plugins-root/check_icmp.d/config.h +++ b/plugins-root/check_icmp.d/config.h @@ -12,11 +12,12 @@ #include #include #include "./check_icmp_helpers.h" +#include "output.h" /* threshold structure. all values are maximum allowed, exclusive */ typedef struct { unsigned char pl; /* max allowed packet loss in percent */ - time_t rta; /* roundtrip time average, microseconds */ + time_t rta; /* roundtrip time average, microseconds */ double jitter; /* jitter time average, microseconds */ double mos; /* MOS */ double score; /* Score */ @@ -77,6 +78,9 @@ typedef struct { unsigned short number_of_hosts; check_icmp_target_container *hosts; + + mp_output_format output_format; + bool output_format_is_set; } check_icmp_config; check_icmp_config check_icmp_config_init(); -- cgit v1.2.3-74-g34f1 From efba4f76545fe03aa9b9af35f23e6f7aad5aabcd Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 23 Jun 2025 10:32:24 +0200 Subject: check_icmp: cleanup some leftover comments --- plugins-root/check_icmp.c | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index bad73cc4..7f01e1b6 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -484,7 +484,7 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { result.config.need_v6 = true; } } else { - // TODO adding host failed, crash here + crash("Failed to add host, unable to parse it correctly"); } } break; case 'l': @@ -848,19 +848,6 @@ int main(int argc, char **argv) { mp_set_format(config.output_format); } - // int icmp_proto = IPPROTO_ICMP; - // add_target might change address_family - // switch (address_family) { - // case AF_INET: - // icmp_proto = IPPROTO_ICMP; - // break; - // case AF_INET6: - // icmp_proto = IPPROTO_ICMPV6; - // break; - // default: - // crash("Address family not supported"); - // } - check_icmp_socket_set sockset = { .socket4 = -1, .socket6 = -1, @@ -1556,14 +1543,6 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, mp_add_subcheck_to_check(overall, host_check.sc_host); } - /* this is inevitable */ - // if (targets_alive(number_of_targets, program_state->targets_down) == 0) { - // mp_subcheck sc_no_target_alive = mp_subcheck_init(); - // sc_no_target_alive = mp_set_subcheck_state(sc_no_target_alive, STATE_CRITICAL); - // sc_no_target_alive.output = strdup("No target is alive!"); - // mp_add_subcheck_to_check(overall, sc_no_target_alive); - // } - if (min_hosts_alive > -1) { mp_subcheck sc_min_targets_alive = mp_subcheck_init(); sc_min_targets_alive = mp_set_subcheck_default_state(sc_min_targets_alive, STATE_OK); -- cgit v1.2.3-74-g34f1 From 27d30c3df0904ef4c81ad5adc50fa451777693a9 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 23 Jun 2025 10:34:12 +0200 Subject: Fix typo --- plugins-root/check_icmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 7f01e1b6..d181af56 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -2114,7 +2114,7 @@ void print_help(void) { printf(" %s", _("max packet interval (default ")); printf("%0.3fms)\n", (float)DEFAULT_PKT_INTERVAL / 1000); printf(" %s\n", "-I"); - printf(" %s%0.3fms)\n The time intervall to wait in between one target and the next", + printf(" %s%0.3fms)\n The time interval to wait in between one target and the next", _("max target interval (default "), (float)DEFAULT_TARGET_INTERVAL / 1000); printf(" %s\n", "-m"); printf(" %s", _("number of alive hosts required for success")); -- cgit v1.2.3-74-g34f1 From b08bafc45cea008abb46e0891c55e7745e117aae Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 23 Jun 2025 10:52:56 +0200 Subject: check_icmp: remove paket_interval, was never used anyway --- plugins-root/check_icmp.c | 88 +++++++++++--------------- plugins-root/check_icmp.d/check_icmp_helpers.c | 1 - plugins-root/check_icmp.d/config.h | 1 - 3 files changed, 37 insertions(+), 53 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index d181af56..524e1fb9 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -151,10 +151,9 @@ static void set_source_ip(char *arg, int icmp_sock, sa_family_t addr_family); /* Receiving data */ static int wait_for_reply(check_icmp_socket_set sockset, time_t time_interval, - unsigned short icmp_pkt_size, time_t *pkt_interval, - time_t *target_interval, uint16_t sender_id, ping_target **table, - unsigned short packets, unsigned short number_of_targets, - check_icmp_state *program_state); + unsigned short icmp_pkt_size, time_t *target_interval, uint16_t sender_id, + ping_target **table, unsigned short packets, + unsigned short number_of_targets, check_icmp_state *program_state); typedef struct { sa_family_t recv_proto; @@ -164,9 +163,9 @@ static recvfrom_wto_wrapper recvfrom_wto(check_icmp_socket_set sockset, void *bu struct sockaddr *saddr, time_t *timeout, struct timeval *received_timestamp); static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr, - time_t *pkt_interval, time_t *target_interval, uint16_t sender_id, - ping_target **table, unsigned short packets, - unsigned short number_of_targets, check_icmp_state *program_state); + time_t *target_interval, uint16_t sender_id, ping_target **table, + unsigned short packets, unsigned short number_of_targets, + check_icmp_state *program_state); /* Sending data */ static int send_icmp_ping(check_icmp_socket_set sockset, ping_target *host, @@ -198,11 +197,11 @@ static parse_threshold2_helper_wrapper parse_threshold2_helper(char *threshold_s threshold_mode mode); /* main test function */ -static void run_checks(unsigned short icmp_pkt_size, time_t *pkt_interval, time_t *target_interval, - uint16_t sender_id, check_icmp_execution_mode mode, - time_t max_completion_time, struct timeval prog_start, ping_target **table, - unsigned short packets, check_icmp_socket_set sockset, - unsigned short number_of_targets, check_icmp_state *program_state); +static void run_checks(unsigned short icmp_pkt_size, time_t *target_interval, uint16_t sender_id, + check_icmp_execution_mode mode, time_t max_completion_time, + struct timeval prog_start, ping_target **table, unsigned short packets, + check_icmp_socket_set sockset, unsigned short number_of_targets, + check_icmp_state *program_state); mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, check_icmp_threshold warn, check_icmp_threshold crit); @@ -297,14 +296,12 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { result.config.mode = MODE_ICMP; } else if (!strcmp(progname, "check_host")) { result.config.mode = MODE_HOSTCHECK; - result.config.pkt_interval = 1000000; result.config.number_of_packets = 5; result.config.crit.rta = result.config.warn.rta = 1000000; result.config.crit.pl = result.config.warn.pl = 100; } else if (!strcmp(progname, "check_rta_multi")) { result.config.mode = MODE_ALL; result.config.target_interval = 0; - result.config.pkt_interval = 50000; result.config.number_of_packets = 5; } /* support "--help" and "--version" */ @@ -418,13 +415,7 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { } } break; case 'i': { - get_timevar_wrapper parsed_time = get_timevar(optarg); - - if (parsed_time.error_code == OK) { - result.config.pkt_interval = parsed_time.time_range; - } else { - crash("failed to parse packet interval"); - } + // packet_interval was unused and is now removed } break; case 'I': { get_timevar_wrapper parsed_time = get_timevar(optarg); @@ -738,8 +729,8 @@ static const char *get_icmp_error_msg(unsigned char icmp_type, unsigned char icm } static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr, - time_t *pkt_interval, time_t *target_interval, - const uint16_t sender_id, ping_target **table, unsigned short packets, + time_t *target_interval, const uint16_t sender_id, + ping_target **table, unsigned short packets, const unsigned short number_of_targets, check_icmp_state *program_state) { struct icmp icmp_packet; @@ -799,7 +790,6 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad /* source quench means we're sending too fast, so increase the * interval and mark this packet lost */ if (icmp_packet.icmp_type == ICMP_SOURCEQUENCH) { - *pkt_interval = (unsigned int)((double)*pkt_interval * PACKET_BACKOFF_FACTOR); *target_interval = (unsigned int)((double)*target_interval * TARGET_BACKOFF_FACTOR); } else { program_state->targets_down++; @@ -931,18 +921,17 @@ int main(int argc, char **argv) { gettimeofday(&prog_start, NULL); time_t max_completion_time = - ((config.pkt_interval * config.number_of_targets * config.number_of_packets) + - (config.target_interval * config.number_of_targets)) + + (config.target_interval * config.number_of_targets) + (config.crit.rta * config.number_of_targets * config.number_of_packets) + config.crit.rta; if (debug) { printf("packets: %u, targets: %u\n" - "target_interval: %0.3f, pkt_interval %0.3f\n" + "target_interval: %0.3f\n" "crit.rta: %0.3f\n" "max_completion_time: %0.3f\n", config.number_of_packets, config.number_of_targets, - (float)config.target_interval / 1000, (float)config.pkt_interval / 1000, - (float)config.crit.rta / 1000, (float)max_completion_time / 1000); + (float)config.target_interval / 1000, (float)config.crit.rta / 1000, + (float)max_completion_time / 1000); } if (debug) { @@ -955,8 +944,7 @@ int main(int argc, char **argv) { if (debug) { printf("crit = {%ld, %u%%}, warn = {%ld, %u%%}\n", config.crit.rta, config.crit.pl, config.warn.rta, config.warn.pl); - printf("pkt_interval: %ld target_interval: %ld\n", config.pkt_interval, - config.target_interval); + printf("target_interval: %ld\n", config.target_interval); printf("icmp_pkt_size: %u timeout: %u\n", config.icmp_pkt_size, timeout); } @@ -980,14 +968,13 @@ int main(int argc, char **argv) { target_index++; } - time_t pkt_interval = config.pkt_interval; time_t target_interval = config.target_interval; check_icmp_state program_state = check_icmp_state_init(); - run_checks(config.icmp_data_size, &pkt_interval, &target_interval, config.sender_id, - config.mode, max_completion_time, prog_start, table, config.number_of_packets, - sockset, config.number_of_targets, &program_state); + run_checks(config.icmp_data_size, &target_interval, config.sender_id, config.mode, + max_completion_time, prog_start, table, config.number_of_packets, sockset, + config.number_of_targets, &program_state); errno = 0; @@ -1006,7 +993,7 @@ int main(int argc, char **argv) { mp_exit(overall); } -static void run_checks(unsigned short icmp_pkt_size, time_t *pkt_interval, time_t *target_interval, +static void run_checks(unsigned short icmp_pkt_size, time_t *target_interval, const uint16_t sender_id, const check_icmp_execution_mode mode, const time_t max_completion_time, const struct timeval prog_start, ping_target **table, const unsigned short packets, @@ -1039,17 +1026,15 @@ static void run_checks(unsigned short icmp_pkt_size, time_t *pkt_interval, time_ if (targets_alive(number_of_targets, program_state->targets_down) || get_timevaldiff(prog_start, prog_start) < max_completion_time || !(mode == MODE_HOSTCHECK && program_state->targets_down)) { - wait_for_reply(sockset, *target_interval, icmp_pkt_size, pkt_interval, - target_interval, sender_id, table, packets, number_of_targets, - program_state); + wait_for_reply(sockset, *target_interval, icmp_pkt_size, target_interval, sender_id, + table, packets, number_of_targets, program_state); } } if (targets_alive(number_of_targets, program_state->targets_down) || get_timevaldiff_to_now(prog_start) < max_completion_time || !(mode == MODE_HOSTCHECK && program_state->targets_down)) { - wait_for_reply(sockset, *pkt_interval * number_of_targets, icmp_pkt_size, pkt_interval, - target_interval, sender_id, table, packets, number_of_targets, - program_state); + wait_for_reply(sockset, number_of_targets, icmp_pkt_size, target_interval, sender_id, + table, packets, number_of_targets, program_state); } } @@ -1079,8 +1064,8 @@ static void run_checks(unsigned short icmp_pkt_size, time_t *pkt_interval, time_ if (targets_alive(number_of_targets, program_state->targets_down) || get_timevaldiff_to_now(prog_start) < max_completion_time || !(mode == MODE_HOSTCHECK && program_state->targets_down)) { - wait_for_reply(sockset, final_wait, icmp_pkt_size, pkt_interval, target_interval, - sender_id, table, packets, number_of_targets, program_state); + wait_for_reply(sockset, final_wait, icmp_pkt_size, target_interval, sender_id, table, + packets, number_of_targets, program_state); } } } @@ -1096,10 +1081,9 @@ static void run_checks(unsigned short icmp_pkt_size, time_t *pkt_interval, time_ * icmp echo reply : the rest */ static int wait_for_reply(check_icmp_socket_set sockset, const time_t time_interval, - unsigned short icmp_pkt_size, time_t *pkt_interval, - time_t *target_interval, uint16_t sender_id, ping_target **table, - const unsigned short packets, const unsigned short number_of_targets, - check_icmp_state *program_state) { + unsigned short icmp_pkt_size, time_t *target_interval, uint16_t sender_id, + ping_target **table, const unsigned short packets, + const unsigned short number_of_targets, check_icmp_state *program_state) { union icmp_packet packet; if (!(packet.buf = malloc(icmp_pkt_size))) { crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size); @@ -1185,8 +1169,8 @@ static int wait_for_reply(check_icmp_socket_set sockset, const time_t time_inter printf("not a proper ICMP_ECHOREPLY\n"); } - handle_random_icmp(buf + hlen, &resp_addr, pkt_interval, target_interval, sender_id, - table, packets, number_of_targets, program_state); + handle_random_icmp(buf + hlen, &resp_addr, target_interval, sender_id, table, packets, + number_of_targets, program_state); continue; } @@ -2111,8 +2095,10 @@ void print_help(void) { printf(" %s", _("number of packets to send (default ")); printf("%u)\n", DEFAULT_NUMBER_OF_PACKETS); printf(" %s\n", "-i"); - printf(" %s", _("max packet interval (default ")); + printf(" %s", _("[DEPRECATED] packet interval (default ")); printf("%0.3fms)\n", (float)DEFAULT_PKT_INTERVAL / 1000); + printf(" %s", _("This option was never actually used and is just mentioned here for " + "historical purposes")); printf(" %s\n", "-I"); printf(" %s%0.3fms)\n The time interval to wait in between one target and the next", _("max target interval (default "), (float)DEFAULT_TARGET_INTERVAL / 1000); diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.c b/plugins-root/check_icmp.d/check_icmp_helpers.c index 9acc96fd..0be0f2dc 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.c +++ b/plugins-root/check_icmp.d/check_icmp_helpers.c @@ -35,7 +35,6 @@ check_icmp_config check_icmp_config_init() { .ttl = DEFAULT_TTL, .icmp_data_size = DEFAULT_PING_DATA_SIZE, .icmp_pkt_size = DEFAULT_PING_DATA_SIZE + ICMP_MINLEN, - .pkt_interval = DEFAULT_PKT_INTERVAL, .target_interval = 0, .number_of_packets = DEFAULT_NUMBER_OF_PACKETS, diff --git a/plugins-root/check_icmp.d/config.h b/plugins-root/check_icmp.d/config.h index 8092e343..1568d6c3 100644 --- a/plugins-root/check_icmp.d/config.h +++ b/plugins-root/check_icmp.d/config.h @@ -61,7 +61,6 @@ typedef struct { unsigned long ttl; unsigned short icmp_data_size; unsigned short icmp_pkt_size; - time_t pkt_interval; time_t target_interval; unsigned short number_of_packets; -- cgit v1.2.3-74-g34f1 From 7e9519e0ad730ede8fad0503102e1373b8999be2 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 23 Jun 2025 10:59:21 +0200 Subject: check_icmp: correct output strings --- plugins-root/check_icmp.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 524e1fb9..3edfffa2 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -2279,10 +2279,10 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, if (rta >= crit.rta) { sc_rta = mp_set_subcheck_state(sc_rta, STATE_CRITICAL); - xasprintf(&sc_rta.output, "%s > %0.3fms", sc_rta.output, (double)crit.rta / 1000); + xasprintf(&sc_rta.output, "%s >= %0.3fms", sc_rta.output, (double)crit.rta / 1000); } else if (rta >= warn.rta) { sc_rta = mp_set_subcheck_state(sc_rta, STATE_WARNING); - xasprintf(&sc_rta.output, "%s > %0.3fms", sc_rta.output, (double)warn.rta / 1000); + xasprintf(&sc_rta.output, "%s >= %0.3fms", sc_rta.output, (double)warn.rta / 1000); } if (packet_loss < 100) { @@ -2319,10 +2319,10 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, if (packet_loss >= crit.pl) { sc_pl = mp_set_subcheck_state(sc_pl, STATE_CRITICAL); - xasprintf(&sc_pl.output, "%s > %u%%", sc_pl.output, crit.pl); + xasprintf(&sc_pl.output, "%s >= %u%%", sc_pl.output, crit.pl); } else if (packet_loss >= warn.pl) { sc_pl = mp_set_subcheck_state(sc_pl, STATE_WARNING); - xasprintf(&sc_pl.output, "%s > %u%%", sc_pl.output, crit.pl); + xasprintf(&sc_pl.output, "%s >= %u%%", sc_pl.output, warn.pl); } mp_perfdata pd_pl = perfdata_init(); @@ -2345,10 +2345,10 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, if (target.jitter >= crit.jitter) { sc_jitter = mp_set_subcheck_state(sc_jitter, STATE_CRITICAL); - xasprintf(&sc_jitter.output, "%s > %0.3fms", sc_jitter.output, crit.jitter); + xasprintf(&sc_jitter.output, "%s >= %0.3fms", sc_jitter.output, crit.jitter); } else if (target.jitter >= warn.jitter) { sc_jitter = mp_set_subcheck_state(sc_jitter, STATE_WARNING); - xasprintf(&sc_jitter.output, "%s > %0.3fms", sc_jitter.output, warn.jitter); + xasprintf(&sc_jitter.output, "%s >= %0.3fms", sc_jitter.output, warn.jitter); } if (packet_loss < 100) { @@ -2382,10 +2382,10 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, if (mos <= crit.mos) { sc_mos = mp_set_subcheck_state(sc_mos, STATE_CRITICAL); - xasprintf(&sc_mos.output, "%s < %0.1f", sc_mos.output, crit.mos); + xasprintf(&sc_mos.output, "%s <= %0.1f", sc_mos.output, crit.mos); } else if (mos <= warn.mos) { sc_mos = mp_set_subcheck_state(sc_mos, STATE_WARNING); - xasprintf(&sc_mos.output, "%s < %0.1f", sc_mos.output, warn.mos); + xasprintf(&sc_mos.output, "%s <= %0.1f", sc_mos.output, warn.mos); } if (packet_loss < 100) { @@ -2394,8 +2394,8 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, pd_mos.value = mp_create_pd_value(mos); pd_mos.warn = mp_range_set_end(pd_mos.warn, mp_create_pd_value(warn.mos)); pd_mos.crit = mp_range_set_end(pd_mos.crit, mp_create_pd_value(crit.mos)); - pd_mos.min = mp_create_pd_value(0); - pd_mos.max = mp_create_pd_value(5); + pd_mos.min = mp_create_pd_value(0); // MOS starts at 0 + pd_mos.max = mp_create_pd_value(5); // MOS max is 5, by definition mp_add_perfdata_to_subcheck(&sc_mos, pd_mos); } mp_add_subcheck_to_subcheck(&result, sc_mos); @@ -2408,10 +2408,10 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, if (score <= crit.score) { sc_score = mp_set_subcheck_state(sc_score, STATE_CRITICAL); - xasprintf(&sc_score.output, "%s < %f", sc_score.output, crit.score); + xasprintf(&sc_score.output, "%s <= %f", sc_score.output, crit.score); } else if (score <= warn.score) { sc_score = mp_set_subcheck_state(sc_score, STATE_WARNING); - xasprintf(&sc_score.output, "%s < %f", sc_score.output, warn.score); + xasprintf(&sc_score.output, "%s <= %f", sc_score.output, warn.score); } if (packet_loss < 100) { -- cgit v1.2.3-74-g34f1 From 771ccfa52691e591be3736b6d03f36e69d82e464 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 23 Jun 2025 11:41:24 +0200 Subject: check_icmp: remove unnecessary variable --- plugins-root/check_icmp.c | 3 +-- plugins-root/check_icmp.d/check_icmp_helpers.c | 1 - plugins-root/check_icmp.d/config.h | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 3edfffa2..be686ee3 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -407,7 +407,6 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { if ((unsigned long)size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && size < MAX_PING_DATA) { result.config.icmp_data_size = (unsigned short)size; - result.config.icmp_pkt_size = (unsigned short)(size + ICMP_MINLEN); } else { usage_va("ICMP data length must be between: %lu and %lu", sizeof(struct icmp) + sizeof(struct icmp_ping_data), @@ -945,7 +944,7 @@ int main(int argc, char **argv) { printf("crit = {%ld, %u%%}, warn = {%ld, %u%%}\n", config.crit.rta, config.crit.pl, config.warn.rta, config.warn.pl); printf("target_interval: %ld\n", config.target_interval); - printf("icmp_pkt_size: %u timeout: %u\n", config.icmp_pkt_size, timeout); + printf("icmp_pkt_size: %u timeout: %u\n", config.icmp_data_size + ICMP_MINLEN, timeout); } if (config.min_hosts_alive < -1) { diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.c b/plugins-root/check_icmp.d/check_icmp_helpers.c index 0be0f2dc..d56fbd8b 100644 --- a/plugins-root/check_icmp.d/check_icmp_helpers.c +++ b/plugins-root/check_icmp.d/check_icmp_helpers.c @@ -34,7 +34,6 @@ check_icmp_config check_icmp_config_init() { .ttl = DEFAULT_TTL, .icmp_data_size = DEFAULT_PING_DATA_SIZE, - .icmp_pkt_size = DEFAULT_PING_DATA_SIZE + ICMP_MINLEN, .target_interval = 0, .number_of_packets = DEFAULT_NUMBER_OF_PACKETS, diff --git a/plugins-root/check_icmp.d/config.h b/plugins-root/check_icmp.d/config.h index 1568d6c3..ab578ba5 100644 --- a/plugins-root/check_icmp.d/config.h +++ b/plugins-root/check_icmp.d/config.h @@ -60,7 +60,6 @@ typedef struct { unsigned long ttl; unsigned short icmp_data_size; - unsigned short icmp_pkt_size; time_t target_interval; unsigned short number_of_packets; -- cgit v1.2.3-74-g34f1 From bf67d5cb53e1810cb083ca72943375cbbc941acf Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 23 Jun 2025 11:41:41 +0200 Subject: check_icmp: remove dead comment --- plugins-root/check_icmp.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index be686ee3..ca12b466 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -2127,14 +2127,6 @@ void print_help(void) { _("You can specify different RTA factors using the standardized abbreviations")); printf(" %s\n", _("us (microseconds), ms (milliseconds, default) or just plain s for seconds.")); - /* -d not yet implemented */ - /* printf ("%s\n", _("Threshold format for -d is warn,crit. 12,14 means WARNING if >= 12 - hops")); printf ("%s\n", _("are spent and CRITICAL if >= 14 hops are spent.")); printf - ("%s\n\n", _("NOTE: Some systems decrease TTL when forming ICMP_ECHOREPLY, others do - not."));*/ - /* printf ("%s\n", _("Long options are currently unsupported.")); - printf ("%s\n", _("Options marked with * require an argument")); - */ printf(UT_SUPPORT); } -- cgit v1.2.3-74-g34f1 From 622d7f4c89cdc76f23a5981590e306ebc0ae395f Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 23 Jun 2025 11:41:56 +0200 Subject: check_icmp: add long options to help --- plugins-root/check_icmp.c | 58 +++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 27 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index ca12b466..8feeb853 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -339,8 +339,9 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { {"number-of-packets", required_argument, 0, 'p'}, {"packet-interval", required_argument, 0, 'i'}, {"target-interval", required_argument, 0, 'I'}, + {"minimal-host-alive", required_argument, 0, 'm'}, {"outgoing-ttl", required_argument, 0, 'l'}, - {"packet_payload_size", required_argument, 0, 'b'}, + {"size", required_argument, 0, 'b'}, {"output-format", required_argument, 0, output_format_index}, {}, }; @@ -2062,56 +2063,59 @@ void print_help(void) { printf(UT_HELP_VRSN); printf(UT_EXTRA_OPTS); - printf(" %s\n", "-H"); + printf(" -H, --Host=HOST\n"); printf(" %s\n", - _("specify a target, might be one of: resolveable name, IPv6 address, IPv4 address " - "(necessary, can be given multiple times)")); - printf(" %s\n", "[-4|-6]"); + _("specify a target, might be one of: resolveable name | IPv6 address | IPv4 address\n" + " (required, can be given multiple times)")); + printf(" %s\n", "[-4|-6], [--ipv4-only|--ipv6-only]"); printf(" %s\n", _("Use IPv4 or IPv6 only to communicate with the targets")); - printf(" %s\n", "-w"); + printf(" %s\n", "-w, --warning=WARN_VALUE"); printf(" %s", _("warning threshold (default ")); printf("%0.3fms,%u%%)\n", (float)DEFAULT_WARN_RTA / 1000, DEFAULT_WARN_PL); - printf(" %s\n", "-c"); + printf(" %s\n", "-c, --critical=CRIT_VALUE"); printf(" %s", _("critical threshold (default ")); printf("%0.3fms,%u%%)\n", (float)DEFAULT_CRIT_RTA / 1000, DEFAULT_CRIT_PL); - printf(" %s\n", "-R"); + printf(" %s\n", "-R, --rta-mode-thresholds=RTA_THRESHOLDS"); printf(" %s\n", - _("RTA (round trip average) mode warning,critical, ex. 100ms,200ms unit in ms")); - printf(" %s\n", "-P"); + _("RTA (round trip average) mode warning,critical, ex. 100ms,200ms unit in ms")); + printf(" %s\n", "-P, --packet-loss-mode-thresholds=PACKET_LOSS_THRESHOLD"); printf(" %s\n", _("packet loss mode, ex. 40%,50% , unit in %")); - printf(" %s\n", "-J"); + printf(" %s\n", "-J, --jitter-mode-thresholds=JITTER_MODE_THRESHOLD"); printf(" %s\n", _("jitter mode warning,critical, ex. 40.000ms,50.000ms , unit in ms ")); - printf(" %s\n", "-M"); + printf(" %s\n", "-M, --mos-mode-thresholds=MOS_MODE_THRESHOLD"); printf(" %s\n", _("MOS mode, between 0 and 4.4 warning,critical, ex. 3.5,3.0")); - printf(" %s\n", "-S"); + printf(" %s\n", "-S, --score-mode-thresholds=SCORE_MODE_THRESHOLD"); printf(" %s\n", _("score mode, max value 100 warning,critical, ex. 80,70 ")); - printf(" %s\n", "-O"); - printf(" %s\n", - _("detect out of order ICMP packts, if such packets are found, the result is CRITICAL")); - printf(" %s\n", "-n"); - printf(" %s\n", "-p"); + printf(" %s\n", "-O, --out-of-order-packets"); + printf( + " %s\n", + _("detect out of order ICMP packets, if such packets are found, the result is CRITICAL")); + printf(" %s\n", "[-n|-p], --number-of-packets=NUMBER_OF_PACKETS"); printf(" %s", _("number of packets to send (default ")); printf("%u)\n", DEFAULT_NUMBER_OF_PACKETS); + printf(" %s\n", "-i"); printf(" %s", _("[DEPRECATED] packet interval (default ")); printf("%0.3fms)\n", (float)DEFAULT_PKT_INTERVAL / 1000); printf(" %s", _("This option was never actually used and is just mentioned here for " - "historical purposes")); - printf(" %s\n", "-I"); + "historical purposes\n")); + + printf(" %s\n", "-I, --target-interval=TARGET_INTERVAL"); printf(" %s%0.3fms)\n The time interval to wait in between one target and the next", _("max target interval (default "), (float)DEFAULT_TARGET_INTERVAL / 1000); - printf(" %s\n", "-m"); - printf(" %s", _("number of alive hosts required for success")); + printf(" %s\n", "-m, --minimal-host-alive=MIN_ALIVE"); + printf(" %s", _("number of alive hosts required for success. If less than MIN_ALIVE hosts " + "are OK, but MIN_ALIVE hosts are WARNING or OK, WARNING, else CRITICAL")); printf("\n"); - printf(" %s\n", "-l"); + printf(" %s\n", "-l, --outgoing-ttl=OUTGOING_TTL"); printf(" %s", _("TTL on outgoing packets (default ")); printf("%u)\n", DEFAULT_TTL); - printf(" %s\n", "-b"); - printf(" %s\n", _("Number of icmp data bytes to send")); - printf(" %s %lu + %d)\n", _("Packet size will be data bytes + icmp header (default"), + printf(" %s\n", "-b, --size=SIZE"); + printf(" %s\n", _("Number of icmp ping data bytes to send")); + printf(" %s %lu + %d)\n", _("Packet size will be SIZE + icmp header (default"), DEFAULT_PING_DATA_SIZE, ICMP_MINLEN); - printf(" %s\n", "-v"); + printf(" %s\n", "-v, --verbose"); printf(" %s\n", _("Verbosity, can be given multiple times (for debugging)")); printf(UT_OUTPUT_FORMAT); -- cgit v1.2.3-74-g34f1 From 6ac0580a10e5dcbda79ac8959a3b52f5217e877e Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 23 Jun 2025 11:42:25 +0200 Subject: check_icmp: Add comment to config --- plugins-root/check_icmp.d/config.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.d/config.h b/plugins-root/check_icmp.d/config.h index ab578ba5..c348bef5 100644 --- a/plugins-root/check_icmp.d/config.h +++ b/plugins-root/check_icmp.d/config.h @@ -96,7 +96,9 @@ typedef struct icmp_ping_data { #define DEFAULT_PING_DATA_SIZE (MIN_PING_DATA_SIZE + 44) /* 80 msec packet interval by default */ -#define DEFAULT_PKT_INTERVAL 80000 +// DEPRECATED, remove when removing the option +#define DEFAULT_PKT_INTERVAL 80000 + #define DEFAULT_TARGET_INTERVAL 0 #define DEFAULT_WARN_RTA 200000 -- cgit v1.2.3-74-g34f1 From 8626d22fc5df98d73b36eedb01cb4ed02908ea18 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 23 Jun 2025 11:44:46 +0200 Subject: check_icmp: trigger help before anything important --- plugins-root/check_icmp.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 8feeb853..03924a7e 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -353,6 +353,7 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { long int arg; while ((arg = getopt_long(argc, argv, opts_str, longopts, NULL)) != EOF) { switch (arg) { + case '4': if (enforced_ai_family != AF_UNSPEC) { crash("Multiple protocol versions not supported"); @@ -369,6 +370,11 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { result.config.number_of_hosts++; break; } + case 'h': /* help */ + // Trigger help here to avoid adding hosts before that (and doing DNS queries) + print_help(); + exit(STATE_UNKNOWN); + break; case 'v': debug++; break; @@ -490,10 +496,6 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) { case 'V': /* version */ print_revision(progname, NP_VERSION); exit(STATE_UNKNOWN); - case 'h': /* help */ - print_help(); - exit(STATE_UNKNOWN); - break; case 'R': /* RTA mode */ { get_threshold2_wrapper rta_th = get_threshold2( optarg, strlen(optarg), result.config.warn, result.config.crit, const_rta_mode); -- cgit v1.2.3-74-g34f1 From bd55d9cd2d30deb2146d63af0c6ac1daa79cc496 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 23 Jun 2025 11:46:45 +0200 Subject: check_icmp: Add missing line ending in help --- plugins-root/check_icmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins-root') diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 03924a7e..d46d2ccc 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c @@ -2104,7 +2104,7 @@ void print_help(void) { "historical purposes\n")); printf(" %s\n", "-I, --target-interval=TARGET_INTERVAL"); - printf(" %s%0.3fms)\n The time interval to wait in between one target and the next", + printf(" %s%0.3fms)\n The time interval to wait in between one target and the next\n", _("max target interval (default "), (float)DEFAULT_TARGET_INTERVAL / 1000); printf(" %s\n", "-m, --minimal-host-alive=MIN_ALIVE"); printf(" %s", _("number of alive hosts required for success. If less than MIN_ALIVE hosts " -- cgit v1.2.3-74-g34f1 From a0d3493f9dbe02f4cf1d578129581c4b45994ca2 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Tue, 1 Apr 2025 00:05:18 +0200 Subject: check_dhcp: clang-format --- plugins-root/check_dhcp.c | 184 ++++++++++++++++++++++++++++++---------------- 1 file changed, 119 insertions(+), 65 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/check_dhcp.c b/plugins-root/check_dhcp.c index 6802232e..70809956 100644 --- a/plugins-root/check_dhcp.c +++ b/plugins-root/check_dhcp.c @@ -260,13 +260,15 @@ int main(int argc, char **argv) { dhcp_socket = create_dhcp_socket(); /* get hardware address of client machine */ - if (user_specified_mac != NULL) + if (user_specified_mac != NULL) { memcpy(client_hardware_address, user_specified_mac, 6); - else + } else { get_hardware_address(dhcp_socket, network_interface_name); + } - if (unicast) /* get IP address of client machine */ + if (unicast) { /* get IP address of client machine */ get_ip_address(dhcp_socket, network_interface_name); + } /* send DHCPDISCOVER packet */ send_dhcp_discover(dhcp_socket); @@ -358,8 +360,9 @@ static int get_hardware_address(int sock, char *interface_name) { int i; p = interface_name + strlen(interface_name) - 1; for (i = strlen(interface_name) - 1; i > 0; p--) { - if (isalpha(*p)) + if (isalpha(*p)) { break; + } } p++; if (p != interface_name) { @@ -393,8 +396,9 @@ static int get_hardware_address(int sock, char *interface_name) { exit(STATE_UNKNOWN); #endif - if (verbose) + if (verbose) { print_hardware_address(client_hardware_address); + } return OK; } @@ -419,8 +423,9 @@ static int get_ip_address(int sock, char *interface_name) { exit(STATE_UNKNOWN); #endif - if (verbose) + if (verbose) { printf(_("Pretending to be relay client %s\n"), inet_ntoa(my_ip)); + } return OK; } @@ -484,8 +489,9 @@ static int send_dhcp_discover(int sock) { discover_packet.options[opts++] = (char)DHCP_OPTION_END; /* unicast fields */ - if (unicast) + if (unicast) { discover_packet.giaddr.s_addr = my_ip.s_addr; + } /* see RFC 1542, 4.1.1 */ discover_packet.hops = unicast ? 1 : 0; @@ -508,8 +514,9 @@ static int send_dhcp_discover(int sock) { /* send the DHCPDISCOVER packet out */ send_dhcp_packet(&discover_packet, sizeof(discover_packet), sock, &sockaddr_broadcast); - if (verbose) + if (verbose) { printf("\n\n"); + } return OK; } @@ -531,11 +538,13 @@ static int get_dhcp_offer(int sock) { for (responses = 0, valid_responses = 0;;) { time(¤t_time); - if ((current_time - start_time) >= dhcpoffer_timeout) + if ((current_time - start_time) >= dhcpoffer_timeout) { break; + } - if (verbose) + if (verbose) { printf("\n\n"); + } bzero(&source, sizeof(source)); bzero(&via, sizeof(via)); @@ -545,13 +554,15 @@ static int get_dhcp_offer(int sock) { result = receive_dhcp_packet(&offer_packet, sizeof(offer_packet), sock, dhcpoffer_timeout, &source); if (result != OK) { - if (verbose) + if (verbose) { printf(_("Result=ERROR\n")); + } continue; } else { - if (verbose) + if (verbose) { printf(_("Result=OK\n")); + } responses++; } @@ -568,30 +579,37 @@ static int get_dhcp_offer(int sock) { /* check packet xid to see if its the same as the one we used in the discover packet */ if (ntohl(offer_packet.xid) != packet_xid) { - if (verbose) - printf(_("DHCPOFFER XID (%u) did not match DHCPDISCOVER XID (%u) - ignoring packet\n"), ntohl(offer_packet.xid), packet_xid); + if (verbose) { + printf(_("DHCPOFFER XID (%u) did not match DHCPDISCOVER XID (%u) - ignoring packet\n"), ntohl(offer_packet.xid), + packet_xid); + } continue; } /* check hardware address */ result = OK; - if (verbose) + if (verbose) { printf("DHCPOFFER chaddr: "); + } for (x = 0; x < ETHERNET_HARDWARE_ADDRESS_LENGTH; x++) { - if (verbose) + if (verbose) { printf("%02X", (unsigned char)offer_packet.chaddr[x]); + } - if (offer_packet.chaddr[x] != client_hardware_address[x]) + if (offer_packet.chaddr[x] != client_hardware_address[x]) { result = ERROR; + } } - if (verbose) + if (verbose) { printf("\n"); + } if (result == ERROR) { - if (verbose) + if (verbose) { printf(_("DHCPOFFER hardware address did not match our own - ignoring packet\n")); + } continue; } @@ -622,11 +640,13 @@ static int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sock result = sendto(sock, (char *)buffer, buffer_size, 0, (struct sockaddr *)dest, sizeof(*dest)); - if (verbose) + if (verbose) { printf(_("send_dhcp_packet result: %d\n"), result); + } - if (result < 0) + if (result < 0) { return ERROR; + } return OK; } @@ -652,8 +672,9 @@ static int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int time /* make sure some data has arrived */ if (!FD_ISSET(sock, &readfds)) { - if (verbose) + if (verbose) { printf(_("No (more) data received (nfound: %d)\n"), nfound); + } return ERROR; } @@ -661,8 +682,9 @@ static int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int time bzero(&source_address, sizeof(source_address)); address_size = sizeof(source_address); recv_result = recvfrom(sock, (char *)buffer, buffer_size, 0, (struct sockaddr *)&source_address, &address_size); - if (verbose) + if (verbose) { printf("recv_result: %d\n", recv_result); + } if (recv_result == -1) { if (verbose) { @@ -706,8 +728,9 @@ static int create_dhcp_socket(void) { exit(STATE_UNKNOWN); } - if (verbose) + if (verbose) { printf("DHCP socket: %d\n", sock); + } /* set the reuse address flag so we don't get errors when restarting */ flag = 1; @@ -758,8 +781,9 @@ static int add_requested_server(struct in_addr server_address) { requested_server *new_server; new_server = (requested_server *)malloc(sizeof(requested_server)); - if (new_server == NULL) + if (new_server == NULL) { return ERROR; + } new_server->server_address = server_address; new_server->answered = false; @@ -769,8 +793,9 @@ static int add_requested_server(struct in_addr server_address) { requested_servers++; - if (verbose) + if (verbose) { printf(_("Requested server address: %s\n"), inet_ntoa(new_server->server_address)); + } return OK; } @@ -783,14 +808,16 @@ static int add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet) { unsigned option_length; struct in_addr serv_ident = {0}; - if (offer_packet == NULL) + if (offer_packet == NULL) { return ERROR; + } /* process all DHCP options present in the packet */ for (x = 4; x < MAX_DHCP_OPTIONS_LENGTH - 1;) { - if ((int)offer_packet->options[x] == -1) + if ((int)offer_packet->options[x] == -1) { break; + } /* get option type */ option_type = offer_packet->options[x++]; @@ -798,8 +825,9 @@ static int add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet) { /* get option length */ option_length = offer_packet->options[x++]; - if (verbose) + if (verbose) { printf("Option: %d (0x%02X)\n", option_type, option_length); + } /* get option data */ switch (option_type) { @@ -821,30 +849,35 @@ static int add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet) { } /* skip option data we're ignoring */ - if (option_type == 0) /* "pad" option, see RFC 2132 (3.1) */ + if (option_type == 0) { /* "pad" option, see RFC 2132 (3.1) */ x += 1; - else + } else { x += option_length; + } } if (verbose) { - if (dhcp_lease_time == DHCP_INFINITE_TIME) + if (dhcp_lease_time == DHCP_INFINITE_TIME) { printf(_("Lease Time: Infinite\n")); - else + } else { printf(_("Lease Time: %lu seconds\n"), (unsigned long)dhcp_lease_time); - if (dhcp_renewal_time == DHCP_INFINITE_TIME) + } + if (dhcp_renewal_time == DHCP_INFINITE_TIME) { printf(_("Renewal Time: Infinite\n")); - else + } else { printf(_("Renewal Time: %lu seconds\n"), (unsigned long)dhcp_renewal_time); - if (dhcp_rebinding_time == DHCP_INFINITE_TIME) + } + if (dhcp_rebinding_time == DHCP_INFINITE_TIME) { printf(_("Rebinding Time: Infinite\n")); + } printf(_("Rebinding Time: %lu seconds\n"), (unsigned long)dhcp_rebinding_time); } new_offer = (dhcp_offer *)malloc(sizeof(dhcp_offer)); - if (new_offer == NULL) + if (new_offer == NULL) { return ERROR; + } /* * RFC 2131 (2.) says: "DHCP clarifies the interpretation of the @@ -921,20 +954,23 @@ static int get_results(void) { for (temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) { /* get max lease time we were offered */ - if (temp_offer->lease_time > max_lease_time || temp_offer->lease_time == DHCP_INFINITE_TIME) + if (temp_offer->lease_time > max_lease_time || temp_offer->lease_time == DHCP_INFINITE_TIME) { max_lease_time = temp_offer->lease_time; + } /* see if we got the address we requested */ - if (!memcmp(&requested_address, &temp_offer->offered_address, sizeof(requested_address))) + if (!memcmp(&requested_address, &temp_offer->offered_address, sizeof(requested_address))) { received_requested_address = true; + } /* see if the servers we wanted a response from talked to us or not */ if (!memcmp(&temp_offer->server_address, &temp_server->server_address, sizeof(temp_server->server_address))) { if (verbose) { printf(_("DHCP Server Match: Offerer=%s"), inet_ntoa(temp_offer->server_address)); printf(_(" Requested=%s"), inet_ntoa(temp_server->server_address)); - if (temp_server->answered) + if (temp_server->answered) { printf(_(" (duplicate)")); + } printf(_("\n")); } if (!temp_server->answered) { @@ -961,36 +997,41 @@ static int get_results(void) { for (temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) { /* get max lease time we were offered */ - if (temp_offer->lease_time > max_lease_time || temp_offer->lease_time == DHCP_INFINITE_TIME) + if (temp_offer->lease_time > max_lease_time || temp_offer->lease_time == DHCP_INFINITE_TIME) { max_lease_time = temp_offer->lease_time; + } /* see if we got the address we requested */ - if (!memcmp(&requested_address, &temp_offer->offered_address, sizeof(requested_address))) + if (!memcmp(&requested_address, &temp_offer->offered_address, sizeof(requested_address))) { received_requested_address = true; + } } } result = STATE_OK; - if (valid_responses == 0) + if (valid_responses == 0) { result = STATE_CRITICAL; - else if (requested_servers > 0 && requested_responses == 0) + } else if (requested_servers > 0 && requested_responses == 0) { result = STATE_CRITICAL; - else if (requested_responses < requested_servers) + } else if (requested_responses < requested_servers) { result = STATE_WARNING; - else if (request_specific_address && !received_requested_address) + } else if (request_specific_address && !received_requested_address) { result = STATE_WARNING; + } - if (exclusive && undesired_offer) + if (exclusive && undesired_offer) { result = STATE_CRITICAL; + } - if (result == 0) /* garrett honeycutt 2005 */ + if (result == 0) { /* garrett honeycutt 2005 */ printf("OK: "); - else if (result == 1) + } else if (result == 1) { printf("WARNING: "); - else if (result == 2) + } else if (result == 2) { printf("CRITICAL: "); - else if (result == 3) + } else if (result == 3) { printf("UNKNOWN: "); + } /* we didn't receive any DHCPOFFERs */ if (dhcp_offer_list == NULL) { @@ -1006,18 +1047,22 @@ static int get_results(void) { return result; } - if (requested_servers > 0) - printf(_(", %s%d of %d requested servers responded"), ((requested_responses < requested_servers) && requested_responses > 0) ? "only " : "", requested_responses, + if (requested_servers > 0) { + printf(_(", %s%d of %d requested servers responded"), + ((requested_responses < requested_servers) && requested_responses > 0) ? "only " : "", requested_responses, requested_servers); + } - if (request_specific_address) + if (request_specific_address) { printf(_(", requested address (%s) was %soffered"), inet_ntoa(requested_address), (received_requested_address) ? "" : _("not ")); + } printf(_(", max lease time = ")); - if (max_lease_time == DHCP_INFINITE_TIME) + if (max_lease_time == DHCP_INFINITE_TIME) { printf(_("Infinity")); - else + } else { printf("%lu sec", (unsigned long)max_lease_time); + } printf(".\n"); @@ -1026,8 +1071,9 @@ static int get_results(void) { /* process command-line arguments */ static int process_arguments(int argc, char **argv) { - if (argc < 1) + if (argc < 1) { return ERROR; + } call_getopt(argc, argv); return validate_arguments(argc); @@ -1052,8 +1098,9 @@ static int call_getopt(int argc, char **argv) { while (true) { c = getopt_long(argc, argv, "+hVvxt:s:r:t:i:m:u", long_options, &option_index); - if (c == -1 || c == EOF || c == 1) + if (c == -1 || c == EOF || c == 1) { break; + } switch (c) { @@ -1072,8 +1119,9 @@ static int call_getopt(int argc, char **argv) { /* if(is_intnonneg(optarg)) */ - if (atoi(optarg) > 0) + if (atoi(optarg) > 0) { dhcpoffer_timeout = atoi(optarg); + } /* else usage("Time interval must be a nonnegative integer\n"); @@ -1082,10 +1130,12 @@ static int call_getopt(int argc, char **argv) { case 'm': /* MAC address */ - if ((user_specified_mac = mac_aton(optarg)) == NULL) + if ((user_specified_mac = mac_aton(optarg)) == NULL) { usage("Cannot parse MAC address.\n"); - if (verbose) + } + if (verbose) { print_hardware_address(user_specified_mac); + } break; @@ -1127,8 +1177,9 @@ static int call_getopt(int argc, char **argv) { static int validate_arguments(int argc) { - if (argc - optind > 0) + if (argc - optind > 0) { usage(_("Got unexpected non-option argument")); + } return OK; } @@ -1273,8 +1324,9 @@ static void resolve_host(const char *in, struct in_addr *out) { memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_INET; - if (getaddrinfo(in, NULL, &hints, &ai) != 0) + if (getaddrinfo(in, NULL, &hints, &ai) != 0) { usage_va(_("Invalid hostname/address - %s"), optarg); + } memcpy(out, &((struct sockaddr_in *)ai->ai_addr)->sin_addr, sizeof(*out)); freeaddrinfo(ai); @@ -1288,8 +1340,9 @@ static unsigned char *mac_aton(const char *string) { for (i = 0, j = 0; string[i] != '\0' && j < sizeof(result); i++) { /* ignore ':' and any other non-hex character */ - if (!isxdigit(string[i]) || !isxdigit(string[i + 1])) + if (!isxdigit(string[i]) || !isxdigit(string[i + 1])) { continue; + } tmp[0] = string[i]; tmp[1] = string[i + 1]; tmp[2] = '\0'; @@ -1305,8 +1358,9 @@ static void print_hardware_address(const unsigned char *address) { int i; printf(_("Hardware address: ")); - for (i = 0; i < 5; i++) + for (i = 0; i < 5; i++) { printf("%2.2x:", address[i]); + } printf("%2.2x", address[i]); putchar('\n'); } -- cgit v1.2.3-74-g34f1 From 0453d6d1e206c1f4c156bf73c473608a8c0da4f5 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Tue, 1 Apr 2025 00:44:26 +0200 Subject: Refactor check_dhcp --- plugins-root/check_dhcp.c | 741 ++++++++++++++++++++----------------- plugins-root/check_dhcp.d/config.h | 50 +++ 2 files changed, 448 insertions(+), 343 deletions(-) create mode 100644 plugins-root/check_dhcp.d/config.h (limited to 'plugins-root') diff --git a/plugins-root/check_dhcp.c b/plugins-root/check_dhcp.c index 70809956..3732d970 100644 --- a/plugins-root/check_dhcp.c +++ b/plugins-root/check_dhcp.c @@ -4,7 +4,7 @@ * * License: GPL * Copyright (c) 2001-2004 Ethan Galstad (nagios@nagios.org) - * Copyright (c) 2001-2023 Monitoring Plugins Development Team + * Copyright (c) 2001-2025 Monitoring Plugins Development Team * * Description: * @@ -34,13 +34,17 @@ *****************************************************************************/ const char *progname = "check_dhcp"; -const char *copyright = "2001-2024"; +const char *copyright = "2001-2025"; const char *email = "devel@monitoring-plugins.org"; -#include "common.h" -#include "netutils.h" -#include "utils.h" +#include "../plugins/common.h" +#include "../plugins/utils.h" +#include "./check_dhcp.d/config.h" +#include "../lib/output.h" +#include "../lib/utils_base.h" +#include "states.h" +#include #include #include #include @@ -111,8 +115,9 @@ static long mac_addr_dlpi(const char *, int, u_char *); /**** Common definitions ****/ -#define OK 0 -#define ERROR -1 +#define OK 0 +#define ERROR -1 +#define MAC_ADDR_LEN 6 /**** DHCP definitions ****/ @@ -149,12 +154,6 @@ typedef struct dhcp_offer_struct { struct dhcp_offer_struct *next; } dhcp_offer; -typedef struct requested_server_struct { - struct in_addr server_address; - bool answered; - struct requested_server_struct *next; -} requested_server; - #define BOOTREQUEST 1 #define BOOTREPLY 2 @@ -186,65 +185,60 @@ typedef struct requested_server_struct { #define ETHERNET_HARDWARE_ADDRESS 1 /* used in htype field of dhcp packet */ #define ETHERNET_HARDWARE_ADDRESS_LENGTH 6 /* length of Ethernet hardware addresses */ -static bool unicast = false; /* unicast mode: mimic a DHCP relay */ -static bool exclusive = false; /* exclusive mode aka "rogue DHCP server detection" */ -static struct in_addr my_ip; /* our address (required for relay) */ -static struct in_addr dhcp_ip; /* server to query (if in unicast mode) */ -static unsigned char client_hardware_address[MAX_DHCP_CHADDR_LENGTH] = ""; -static unsigned char *user_specified_mac = NULL; - -static char network_interface_name[IFNAMSIZ] = "eth0"; - -static uint32_t packet_xid = 0; - -static uint32_t dhcp_lease_time = 0; -static uint32_t dhcp_renewal_time = 0; -static uint32_t dhcp_rebinding_time = 0; - -static int dhcpoffer_timeout = 2; - -static dhcp_offer *dhcp_offer_list = NULL; -static requested_server *requested_server_list = NULL; - -static int valid_responses = 0; /* number of valid DHCPOFFERs we received */ -static int requested_servers = 0; -static int requested_responses = 0; - -static bool request_specific_address = false; -static bool received_requested_address = false; static int verbose = 0; -static struct in_addr requested_address; -static int process_arguments(int, char **); -static int call_getopt(int, char **); -static int validate_arguments(int); +typedef struct process_arguments_wrapper { + int error; + check_dhcp_config config; +} process_arguments_wrapper; + +static process_arguments_wrapper process_arguments(int /*argc*/, char ** /*argv*/); void print_usage(void); static void print_help(void); -static void resolve_host(const char *in, struct in_addr *out); -static unsigned char *mac_aton(const char *); -static void print_hardware_address(const unsigned char *); -static int get_hardware_address(int, char *); -static int get_ip_address(int, char *); - -static int send_dhcp_discover(int); -static int get_dhcp_offer(int); - -static int get_results(void); - -static int add_dhcp_offer(struct in_addr, dhcp_packet *); -static int free_dhcp_offer_list(void); -static int free_requested_server_list(void); - -static int create_dhcp_socket(void); -static int close_dhcp_socket(int); -static int send_dhcp_packet(void *, int, int, struct sockaddr_in *); -static int receive_dhcp_packet(void *, int, int, int, struct sockaddr_in *); +static void resolve_host(const char * /*in*/, struct in_addr * /*out*/); +static unsigned char *mac_aton(const char * /*string*/); +static void print_hardware_address(const unsigned char * /*address*/); +static int get_hardware_address(int /*sock*/, char * /*interface_name*/, unsigned char *client_hardware_address); + +typedef struct get_ip_address_wrapper { + int error; + struct in_addr my_ip; +} get_ip_address_wrapper; +static get_ip_address_wrapper get_ip_address(int /*sock*/, char * /*interface_name*/); + +typedef struct send_dhcp_discover_wrapper { + int error; + uint32_t packet_xid; +} send_dhcp_discover_wrapper; +static send_dhcp_discover_wrapper send_dhcp_discover(int socket, bool unicast, struct in_addr dhcp_ip, struct in_addr requested_address, + bool request_specific_address, struct in_addr my_ip, + unsigned char *client_hardware_address); +typedef struct get_dhcp_offer_wrapper { + int error; + int valid_responses; + dhcp_offer *dhcp_offer_list; +} get_dhcp_offer_wrapper; +static get_dhcp_offer_wrapper get_dhcp_offer(int /*sock*/, int dhcpoffer_timeout, uint32_t packet_xid, dhcp_offer *dhcp_offer_list, + const unsigned char *client_hardware_address); + +static mp_subcheck get_results(bool exclusive, int requested_servers, struct in_addr requested_address, bool request_specific_address, + requested_server *requested_server_list, int valid_responses, dhcp_offer *dhcp_offer_list); + +typedef struct add_dhcp_offer_wrapper { + int error; + dhcp_offer *dhcp_offer_list; +} add_dhcp_offer_wrapper; +static add_dhcp_offer_wrapper add_dhcp_offer(struct in_addr /*source*/, dhcp_packet * /*offer_packet*/, dhcp_offer *dhcp_offer_list); +static int free_dhcp_offer_list(dhcp_offer *dhcp_offer_list); +static int free_requested_server_list(requested_server *requested_server_list); + +static int create_dhcp_socket(bool /*unicast*/, char *network_interface_name); +static int close_dhcp_socket(int /*sock*/); +static int send_dhcp_packet(void * /*buffer*/, int /*buffer_size*/, int /*sock*/, struct sockaddr_in * /*dest*/); +static int receive_dhcp_packet(void * /*buffer*/, int /*buffer_size*/, int /*sock*/, int /*timeout*/, struct sockaddr_in * /*address*/); int main(int argc, char **argv) { - int dhcp_socket; - int result = STATE_UNKNOWN; - setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); @@ -252,45 +246,80 @@ int main(int argc, char **argv) { /* Parse extra opts if any */ argv = np_extra_opts(&argc, argv, progname); - if (process_arguments(argc, argv) != OK) { + process_arguments_wrapper tmp = process_arguments(argc, argv); + + if (tmp.error != OK) { usage4(_("Could not parse arguments")); } + check_dhcp_config config = tmp.config; + if (config.output_format_is_set) { + mp_set_format(config.output_format); + } + /* create socket for DHCP communications */ - dhcp_socket = create_dhcp_socket(); + int dhcp_socket = create_dhcp_socket(config.unicast_mode, config.network_interface_name); /* get hardware address of client machine */ - if (user_specified_mac != NULL) { - memcpy(client_hardware_address, user_specified_mac, 6); + unsigned char client_hardware_address[MAX_DHCP_CHADDR_LENGTH] = ""; + if (config.user_specified_mac != NULL) { + memcpy(client_hardware_address, config.user_specified_mac, MAC_ADDR_LEN); } else { - get_hardware_address(dhcp_socket, network_interface_name); + get_hardware_address(dhcp_socket, config.network_interface_name, client_hardware_address); } - if (unicast) { /* get IP address of client machine */ - get_ip_address(dhcp_socket, network_interface_name); + struct in_addr my_ip = {0}; + + if (config.unicast_mode) { /* get IP address of client machine */ + get_ip_address_wrapper tmp_get_ip = get_ip_address(dhcp_socket, config.network_interface_name); + if (tmp_get_ip.error == OK) { + my_ip = tmp_get_ip.my_ip; + } else { + // TODO failed to get own IP + die(STATE_UNKNOWN, "Failed to retrieve my own IP address in unicast mode"); + } } /* send DHCPDISCOVER packet */ - send_dhcp_discover(dhcp_socket); + send_dhcp_discover_wrapper disco_res = send_dhcp_discover(dhcp_socket, config.unicast_mode, config.dhcp_ip, config.requested_address, + config.request_specific_address, my_ip, client_hardware_address); + + if (disco_res.error != OK) { + // DO something? + die(STATE_UNKNOWN, "Failed to send DHCP discover"); + } /* wait for a DHCPOFFER packet */ - get_dhcp_offer(dhcp_socket); + get_dhcp_offer_wrapper offer_res = + get_dhcp_offer(dhcp_socket, config.dhcpoffer_timeout, disco_res.packet_xid, NULL, client_hardware_address); + + int valid_responses = 0; + dhcp_offer *dhcp_offer_list = NULL; + if (offer_res.error == OK) { + valid_responses = offer_res.valid_responses; + dhcp_offer_list = offer_res.dhcp_offer_list; + } else { + die(STATE_UNKNOWN, "Failed to get DHCP offers"); + } /* close socket we created */ close_dhcp_socket(dhcp_socket); - /* determine state/plugin output to return */ - result = get_results(); + mp_check overall = mp_check_init(); + /* determine state/plugin output to return */ + mp_subcheck sc_res = get_results(config.exclusive_mode, config.num_of_requested_servers, config.requested_address, + config.request_specific_address, config.requested_server_list, valid_responses, dhcp_offer_list); + mp_add_subcheck_to_check(&overall, sc_res); /* free allocated memory */ - free_dhcp_offer_list(); - free_requested_server_list(); + free_dhcp_offer_list(dhcp_offer_list); + free_requested_server_list(config.requested_server_list); - return result; + mp_exit(overall); } /* determines hardware address on client machine */ -static int get_hardware_address(int sock, char *interface_name) { +int get_hardware_address(int sock, char *interface_name, unsigned char *client_hardware_address) { #if defined(__linux__) struct ifreq ifr; @@ -304,7 +333,7 @@ static int get_hardware_address(int sock, char *interface_name) { exit(STATE_UNKNOWN); } - memcpy(&client_hardware_address[0], &ifr.ifr_hwaddr.sa_data, 6); + memcpy(&client_hardware_address[0], &ifr.ifr_hwaddr.sa_data, MAC_ADDR_LEN); #elif defined(__bsd__) /* King 2004 see ACKNOWLEDGEMENTS */ @@ -404,7 +433,7 @@ static int get_hardware_address(int sock, char *interface_name) { } /* determines IP address of the client interface */ -static int get_ip_address(int sock, char *interface_name) { +get_ip_address_wrapper get_ip_address(int sock, char *interface_name) { #if defined(SIOCGIFADDR) struct ifreq ifr; @@ -416,29 +445,28 @@ static int get_ip_address(int sock, char *interface_name) { exit(STATE_UNKNOWN); } - my_ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; - #else printf(_("Error: Cannot get interface IP address on this platform.\n")); exit(STATE_UNKNOWN); #endif + get_ip_address_wrapper result = { + .error = OK, + .my_ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr, + }; + if (verbose) { - printf(_("Pretending to be relay client %s\n"), inet_ntoa(my_ip)); + printf(_("Pretending to be relay client %s\n"), inet_ntoa(result.my_ip)); } - return OK; + return result; } /* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */ -static int send_dhcp_discover(int sock) { - dhcp_packet discover_packet; - struct sockaddr_in sockaddr_broadcast; - unsigned short opts; - - /* clear the packet data structure */ - bzero(&discover_packet, sizeof(discover_packet)); - +static send_dhcp_discover_wrapper send_dhcp_discover(int sock, bool unicast, struct in_addr dhcp_ip, struct in_addr requested_address, + bool request_specific_address, struct in_addr my_ip, + unsigned char *client_hardware_address) { + dhcp_packet discover_packet = {0}; /* boot request flag (backward compatible with BOOTP servers) */ discover_packet.op = BOOTREQUEST; @@ -448,12 +476,15 @@ static int send_dhcp_discover(int sock) { /* length of our hardware address */ discover_packet.hlen = ETHERNET_HARDWARE_ADDRESS_LENGTH; + send_dhcp_discover_wrapper result = { + .error = OK, + }; /* * transaction ID is supposed to be random. */ srand(time(NULL) ^ getpid()); - packet_xid = random(); - discover_packet.xid = htonl(packet_xid); + result.packet_xid = random(); + discover_packet.xid = htonl(result.packet_xid); /*discover_packet.secs=htons(65535);*/ discover_packet.secs = 0xFF; @@ -473,7 +504,7 @@ static int send_dhcp_discover(int sock) { discover_packet.options[2] = '\x53'; discover_packet.options[3] = '\x63'; - opts = 4; + unsigned short opts = 4; /* DHCP message type is embedded in options field */ discover_packet.options[opts++] = DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */ discover_packet.options[opts++] = '\x01'; /* DHCP message option length in bytes */ @@ -497,10 +528,11 @@ static int send_dhcp_discover(int sock) { discover_packet.hops = unicast ? 1 : 0; /* send the DHCPDISCOVER packet to broadcast address */ - sockaddr_broadcast.sin_family = AF_INET; - sockaddr_broadcast.sin_port = htons(DHCP_SERVER_PORT); - sockaddr_broadcast.sin_addr.s_addr = unicast ? dhcp_ip.s_addr : INADDR_BROADCAST; - bzero(&sockaddr_broadcast.sin_zero, sizeof(sockaddr_broadcast.sin_zero)); + struct sockaddr_in sockaddr_broadcast = { + .sin_family = AF_INET, + .sin_port = htons(DHCP_SERVER_PORT), + .sin_addr.s_addr = unicast ? dhcp_ip.s_addr : INADDR_BROADCAST, + }; if (verbose) { printf(_("DHCPDISCOVER to %s port %d\n"), inet_ntoa(sockaddr_broadcast.sin_addr), ntohs(sockaddr_broadcast.sin_port)); @@ -518,25 +550,21 @@ static int send_dhcp_discover(int sock) { printf("\n\n"); } - return OK; + return result; } /* waits for a DHCPOFFER message from one or more DHCP servers */ -static int get_dhcp_offer(int sock) { - dhcp_packet offer_packet; - struct sockaddr_in source; - struct sockaddr_in via; - int result = OK; - int responses = 0; - int x; +get_dhcp_offer_wrapper get_dhcp_offer(int sock, int dhcpoffer_timeout, uint32_t packet_xid, dhcp_offer *dhcp_offer_list, + const unsigned char *client_hardware_address) { time_t start_time; - time_t current_time; - time(&start_time); + int result = OK; + int responses = 0; + int valid_responses = 0; /* receive as many responses as we can */ - for (responses = 0, valid_responses = 0;;) { - + for (;;) { + time_t current_time; time(¤t_time); if ((current_time - start_time) >= dhcpoffer_timeout) { break; @@ -546,9 +574,8 @@ static int get_dhcp_offer(int sock) { printf("\n\n"); } - bzero(&source, sizeof(source)); - bzero(&via, sizeof(via)); - bzero(&offer_packet, sizeof(offer_packet)); + struct sockaddr_in source = {0}; + dhcp_packet offer_packet = {0}; result = OK; result = receive_dhcp_packet(&offer_packet, sizeof(offer_packet), sock, dhcpoffer_timeout, &source); @@ -559,16 +586,16 @@ static int get_dhcp_offer(int sock) { } continue; - } else { - if (verbose) { - printf(_("Result=OK\n")); - } - - responses++; } + if (verbose) { + printf(_("Result=OK\n")); + } + + responses++; /* The "source" is either a server or a relay. */ /* Save a copy of "source" into "via" even if it's via itself */ + struct sockaddr_in via = {0}; memcpy(&via, &source, sizeof(source)); if (verbose) { @@ -593,12 +620,12 @@ static int get_dhcp_offer(int sock) { printf("DHCPOFFER chaddr: "); } - for (x = 0; x < ETHERNET_HARDWARE_ADDRESS_LENGTH; x++) { + for (int i = 0; i < ETHERNET_HARDWARE_ADDRESS_LENGTH; i++) { if (verbose) { - printf("%02X", (unsigned char)offer_packet.chaddr[x]); + printf("%02X", offer_packet.chaddr[i]); } - if (offer_packet.chaddr[x] != client_hardware_address[x]) { + if (offer_packet.chaddr[i] != client_hardware_address[i]) { result = ERROR; } } @@ -621,7 +648,12 @@ static int get_dhcp_offer(int sock) { printf("DHCPOFFER giaddr: %s\n", inet_ntoa(offer_packet.giaddr)); } - add_dhcp_offer(source.sin_addr, &offer_packet); + add_dhcp_offer_wrapper add_res = add_dhcp_offer(source.sin_addr, &offer_packet, dhcp_offer_list); + if (add_res.error != OK) { + // TODO + } else { + dhcp_offer_list = add_res.dhcp_offer_list; + } valid_responses++; } @@ -631,14 +663,17 @@ static int get_dhcp_offer(int sock) { printf(_("Valid responses for this machine: %d\n"), valid_responses); } - return OK; + get_dhcp_offer_wrapper ret_val = { + .error = OK, + .valid_responses = valid_responses, + .dhcp_offer_list = dhcp_offer_list, + }; + return ret_val; } /* sends a DHCP packet */ -static int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in *dest) { - int result; - - result = sendto(sock, (char *)buffer, buffer_size, 0, (struct sockaddr *)dest, sizeof(*dest)); +int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in *dest) { + int result = sendto(sock, (char *)buffer, buffer_size, 0, (struct sockaddr *)dest, sizeof(*dest)); if (verbose) { printf(_("send_dhcp_packet result: %d\n"), result); @@ -652,23 +687,19 @@ static int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sock } /* receives a DHCP packet */ -static int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address) { - struct timeval tv; - fd_set readfds; - fd_set oobfds; - int recv_result; - socklen_t address_size; - struct sockaddr_in source_address; - int nfound; - +int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address) { /* wait for data to arrive (up time timeout) */ - tv.tv_sec = timeout; - tv.tv_usec = 0; + struct timeval timeout_val = { + .tv_sec = timeout, + .tv_usec = 0, + }; + fd_set readfds; FD_ZERO(&readfds); + fd_set oobfds; FD_ZERO(&oobfds); FD_SET(sock, &readfds); FD_SET(sock, &oobfds); - nfound = select(sock + 1, &readfds, NULL, &oobfds, &tv); + int nfound = select(sock + 1, &readfds, NULL, &oobfds, &timeout_val); /* make sure some data has arrived */ if (!FD_ISSET(sock, &readfds)) { @@ -678,51 +709,44 @@ static int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int time return ERROR; } - else { - bzero(&source_address, sizeof(source_address)); - address_size = sizeof(source_address); - recv_result = recvfrom(sock, (char *)buffer, buffer_size, 0, (struct sockaddr *)&source_address, &address_size); - if (verbose) { - printf("recv_result: %d\n", recv_result); - } - - if (recv_result == -1) { - if (verbose) { - printf(_("recvfrom() failed, ")); - printf("errno: (%d) -> %s\n", errno, strerror(errno)); - } - return ERROR; - } else { - if (verbose) { - printf(_("receive_dhcp_packet() result: %d\n"), recv_result); - printf(_("receive_dhcp_packet() source: %s\n"), inet_ntoa(source_address.sin_addr)); - } + struct sockaddr_in source_address = {0}; + socklen_t address_size = sizeof(source_address); + int recv_result = recvfrom(sock, (char *)buffer, buffer_size, 0, (struct sockaddr *)&source_address, &address_size); + if (verbose) { + printf("recv_result: %d\n", recv_result); + } - memcpy(address, &source_address, sizeof(source_address)); - return OK; + if (recv_result == -1) { + if (verbose) { + printf(_("recvfrom() failed, ")); + printf("errno: (%d) -> %s\n", errno, strerror(errno)); } + return ERROR; + } + if (verbose) { + printf(_("receive_dhcp_packet() result: %d\n"), recv_result); + printf(_("receive_dhcp_packet() source: %s\n"), inet_ntoa(source_address.sin_addr)); } + memcpy(address, &source_address, sizeof(source_address)); return OK; } /* creates a socket for DHCP communication */ -static int create_dhcp_socket(void) { - struct sockaddr_in myname; - struct ifreq interface; - int sock; - int flag = 1; - +int create_dhcp_socket(bool unicast, char *network_interface_name) { /* Set up the address we're going to bind to. */ - bzero(&myname, sizeof(myname)); - myname.sin_family = AF_INET; /* listen to DHCP server port if we're in unicast mode */ - myname.sin_port = htons(unicast ? DHCP_SERVER_PORT : DHCP_CLIENT_PORT); - myname.sin_addr.s_addr = unicast ? my_ip.s_addr : INADDR_ANY; - bzero(&myname.sin_zero, sizeof(myname.sin_zero)); + struct sockaddr_in myname = { + .sin_family = AF_INET, + .sin_port = htons(unicast ? DHCP_SERVER_PORT : DHCP_CLIENT_PORT), + // TODO previously the next line was trying to use our own IP, we was not set + // until some point later, so it was removed. Recheck whether it is actually + // necessary/useful + .sin_addr.s_addr = INADDR_ANY, + }; /* create a socket for DHCP communications */ - sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock < 0) { printf(_("Error: Could not create socket!\n")); exit(STATE_UNKNOWN); @@ -733,7 +757,7 @@ static int create_dhcp_socket(void) { } /* set the reuse address flag so we don't get errors when restarting */ - flag = 1; + int flag = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof(flag)) < 0) { printf(_("Error: Could not set reuse address option on DHCP socket!\n")); exit(STATE_UNKNOWN); @@ -745,6 +769,7 @@ static int create_dhcp_socket(void) { exit(STATE_UNKNOWN); } + struct ifreq interface; /* bind socket to interface */ #if defined(__linux__) strncpy(interface.ifr_ifrn.ifrn_name, network_interface_name, IFNAMSIZ - 1); @@ -769,18 +794,14 @@ static int create_dhcp_socket(void) { } /* closes DHCP socket */ -static int close_dhcp_socket(int sock) { - +int close_dhcp_socket(int sock) { close(sock); - return OK; } /* adds a requested server address to list in memory */ -static int add_requested_server(struct in_addr server_address) { - requested_server *new_server; - - new_server = (requested_server *)malloc(sizeof(requested_server)); +int add_requested_server(struct in_addr server_address, int *requested_servers, requested_server **requested_server_list) { + requested_server *new_server = (requested_server *)malloc(sizeof(requested_server)); if (new_server == NULL) { return ERROR; } @@ -788,10 +809,10 @@ static int add_requested_server(struct in_addr server_address) { new_server->server_address = server_address; new_server->answered = false; - new_server->next = requested_server_list; - requested_server_list = new_server; + new_server->next = *requested_server_list; + *requested_server_list = new_server; - requested_servers++; + *requested_servers += 1; if (verbose) { printf(_("Requested server address: %s\n"), inet_ntoa(new_server->server_address)); @@ -801,29 +822,31 @@ static int add_requested_server(struct in_addr server_address) { } /* adds a DHCP OFFER to list in memory */ -static int add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet) { - dhcp_offer *new_offer; - int x; - unsigned option_type; - unsigned option_length; - struct in_addr serv_ident = {0}; - +add_dhcp_offer_wrapper add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet, dhcp_offer *dhcp_offer_list) { if (offer_packet == NULL) { - return ERROR; + add_dhcp_offer_wrapper tmp = { + .error = ERROR, + }; + return tmp; } + uint32_t dhcp_lease_time = 0; + uint32_t dhcp_renewal_time = 0; + uint32_t dhcp_rebinding_time = 0; + dhcp_offer *new_offer; + struct in_addr serv_ident = {0}; /* process all DHCP options present in the packet */ - for (x = 4; x < MAX_DHCP_OPTIONS_LENGTH - 1;) { + for (int dchp_opt_idx = 4; dchp_opt_idx < MAX_DHCP_OPTIONS_LENGTH - 1;) { - if ((int)offer_packet->options[x] == -1) { + if ((int)offer_packet->options[dchp_opt_idx] == -1) { break; } /* get option type */ - option_type = offer_packet->options[x++]; + unsigned option_type = offer_packet->options[dchp_opt_idx++]; /* get option length */ - option_length = offer_packet->options[x++]; + unsigned option_length = offer_packet->options[dchp_opt_idx++]; if (verbose) { printf("Option: %d (0x%02X)\n", option_type, option_length); @@ -832,27 +855,27 @@ static int add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet) { /* get option data */ switch (option_type) { case DHCP_OPTION_LEASE_TIME: - memcpy(&dhcp_lease_time, &offer_packet->options[x], sizeof(dhcp_lease_time)); + memcpy(&dhcp_lease_time, &offer_packet->options[dchp_opt_idx], sizeof(dhcp_lease_time)); dhcp_lease_time = ntohl(dhcp_lease_time); break; case DHCP_OPTION_RENEWAL_TIME: - memcpy(&dhcp_renewal_time, &offer_packet->options[x], sizeof(dhcp_renewal_time)); + memcpy(&dhcp_renewal_time, &offer_packet->options[dchp_opt_idx], sizeof(dhcp_renewal_time)); dhcp_renewal_time = ntohl(dhcp_renewal_time); break; case DHCP_OPTION_REBINDING_TIME: - memcpy(&dhcp_rebinding_time, &offer_packet->options[x], sizeof(dhcp_rebinding_time)); + memcpy(&dhcp_rebinding_time, &offer_packet->options[dchp_opt_idx], sizeof(dhcp_rebinding_time)); dhcp_rebinding_time = ntohl(dhcp_rebinding_time); break; case DHCP_OPTION_SERVER_IDENTIFIER: - memcpy(&serv_ident.s_addr, &offer_packet->options[x], sizeof(serv_ident.s_addr)); + memcpy(&serv_ident.s_addr, &offer_packet->options[dchp_opt_idx], sizeof(serv_ident.s_addr)); break; } /* skip option data we're ignoring */ if (option_type == 0) { /* "pad" option, see RFC 2132 (3.1) */ - x += 1; + dchp_opt_idx += 1; } else { - x += option_length; + dchp_opt_idx += option_length; } } @@ -876,7 +899,10 @@ static int add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet) { new_offer = (dhcp_offer *)malloc(sizeof(dhcp_offer)); if (new_offer == NULL) { - return ERROR; + add_dhcp_offer_wrapper tmp = { + .error = ERROR, + }; + return tmp; } /* @@ -907,15 +933,18 @@ static int add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet) { new_offer->next = dhcp_offer_list; dhcp_offer_list = new_offer; - return OK; + add_dhcp_offer_wrapper result = { + .error = OK, + .dhcp_offer_list = dhcp_offer_list, + }; + + return result; } /* frees memory allocated to DHCP OFFER list */ -static int free_dhcp_offer_list(void) { - dhcp_offer *this_offer; +int free_dhcp_offer_list(dhcp_offer *dhcp_offer_list) { dhcp_offer *next_offer; - - for (this_offer = dhcp_offer_list; this_offer != NULL; this_offer = next_offer) { + for (dhcp_offer *this_offer = dhcp_offer_list; this_offer != NULL; this_offer = next_offer) { next_offer = this_offer->next; free(this_offer); } @@ -924,11 +953,9 @@ static int free_dhcp_offer_list(void) { } /* frees memory allocated to requested server list */ -static int free_requested_server_list(void) { - requested_server *this_server; +int free_requested_server_list(requested_server *requested_server_list) { requested_server *next_server; - - for (this_server = requested_server_list; this_server != NULL; this_server = next_server) { + for (requested_server *this_server = requested_server_list; this_server != NULL; this_server = next_server) { next_server = this_server->next; free(this_server); } @@ -937,22 +964,39 @@ static int free_requested_server_list(void) { } /* gets state and plugin output to return */ -static int get_results(void) { - dhcp_offer *temp_offer, *undesired_offer = NULL; - requested_server *temp_server; - int result; - uint32_t max_lease_time = 0; - - received_requested_address = false; +mp_subcheck get_results(bool exclusive, const int requested_servers, const struct in_addr requested_address, bool request_specific_address, + requested_server *requested_server_list, int valid_responses, dhcp_offer *dhcp_offer_list) { + mp_subcheck sc_dhcp_results = mp_subcheck_init(); + sc_dhcp_results = mp_set_subcheck_default_state(sc_dhcp_results, STATE_OK); - /* checks responses from requested servers */ - requested_responses = 0; - if (requested_servers > 0) { + /* we didn't receive any DHCPOFFERs */ + if (dhcp_offer_list == NULL) { + sc_dhcp_results = mp_set_subcheck_state(sc_dhcp_results, STATE_CRITICAL); + xasprintf(&sc_dhcp_results.output, "%s", "No DHCP offers were received"); + return sc_dhcp_results; + } - for (temp_server = requested_server_list; temp_server != NULL; temp_server = temp_server->next) { + if (valid_responses == 0) { + // No valid responses at all, so early exit here + sc_dhcp_results = mp_set_subcheck_state(sc_dhcp_results, STATE_CRITICAL); + xasprintf(&sc_dhcp_results.output, "No valid responses received"); + return sc_dhcp_results; + } - for (temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) { + if (valid_responses == 1) { + xasprintf(&sc_dhcp_results.output, "Received %d DHCPOFFER", valid_responses); + } else { + xasprintf(&sc_dhcp_results.output, "Received %d DHCPOFFERs", valid_responses); + } + bool received_requested_address = false; + dhcp_offer *undesired_offer = NULL; + uint32_t max_lease_time = 0; + /* checks responses from requested servers */ + int requested_responses = 0; + if (requested_servers > 0) { + for (requested_server *temp_server = requested_server_list; temp_server != NULL; temp_server = temp_server->next) { + for (dhcp_offer *temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) { /* get max lease time we were offered */ if (temp_offer->lease_time > max_lease_time || temp_offer->lease_time == DHCP_INFINITE_TIME) { max_lease_time = temp_offer->lease_time; @@ -963,7 +1007,7 @@ static int get_results(void) { received_requested_address = true; } - /* see if the servers we wanted a response from talked to us or not */ + /* see if the servers we wanted a response from, talked to us or not */ if (!memcmp(&temp_offer->server_address, &temp_server->server_address, sizeof(temp_server->server_address))) { if (verbose) { printf(_("DHCP Server Match: Offerer=%s"), inet_ntoa(temp_offer->server_address)); @@ -973,6 +1017,7 @@ static int get_results(void) { } printf(_("\n")); } + if (!temp_server->answered) { requested_responses++; temp_server->answered = true; @@ -983,19 +1028,32 @@ static int get_results(void) { } /* exclusive mode: check for undesired offers */ - for (temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) { + for (dhcp_offer *temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) { if (!temp_offer->desired) { undesired_offer = temp_offer; /* Checks only for the first undesired offer */ break; /* no further checks needed */ } } - } - /* else check and see if we got our requested address from any server */ - else { + mp_subcheck sc_rqust_srvs = mp_subcheck_init(); + xasprintf(&sc_rqust_srvs.output, "%d of %d requested servers responded", requested_responses, requested_servers); - for (temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) { + if (requested_responses == requested_servers) { + sc_rqust_srvs = mp_set_subcheck_state(sc_rqust_srvs, STATE_OK); + } else if (requested_responses == 0) { + sc_rqust_srvs = mp_set_subcheck_state(sc_rqust_srvs, STATE_CRITICAL); + } else if (requested_responses < requested_servers) { + sc_rqust_srvs = mp_set_subcheck_state(sc_rqust_srvs, STATE_WARNING); + } else { + // We received more(!) responses than we asked for? + // This case shouldn't happen, but is here for completion + sc_rqust_srvs = mp_set_subcheck_state(sc_rqust_srvs, STATE_WARNING); + } + mp_add_subcheck_to_subcheck(&sc_dhcp_results, sc_rqust_srvs); + } else { + /* else check and see if we got our requested address from any server */ + for (dhcp_offer *temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) { /* get max lease time we were offered */ if (temp_offer->lease_time > max_lease_time || temp_offer->lease_time == DHCP_INFINITE_TIME) { max_lease_time = temp_offer->lease_time; @@ -1008,79 +1066,77 @@ static int get_results(void) { } } - result = STATE_OK; - if (valid_responses == 0) { - result = STATE_CRITICAL; - } else if (requested_servers > 0 && requested_responses == 0) { - result = STATE_CRITICAL; - } else if (requested_responses < requested_servers) { - result = STATE_WARNING; - } else if (request_specific_address && !received_requested_address) { - result = STATE_WARNING; + if (max_lease_time == DHCP_INFINITE_TIME) { + xasprintf(&sc_dhcp_results.output, "%s, max lease time = Infinity", sc_dhcp_results.output); + } else { + xasprintf(&sc_dhcp_results.output, "%s, max lease time = %" PRIu32 " seconds", sc_dhcp_results.output, max_lease_time); } - if (exclusive && undesired_offer) { - result = STATE_CRITICAL; - } + if (exclusive) { + mp_subcheck sc_rogue_server = mp_subcheck_init(); - if (result == 0) { /* garrett honeycutt 2005 */ - printf("OK: "); - } else if (result == 1) { - printf("WARNING: "); - } else if (result == 2) { - printf("CRITICAL: "); - } else if (result == 3) { - printf("UNKNOWN: "); - } + if (undesired_offer != NULL) { + // We wanted to get a DHCPOFFER exclusively from one machine, but another one + // sent one (too) + sc_rogue_server = mp_set_subcheck_state(sc_rogue_server, STATE_CRITICAL); - /* we didn't receive any DHCPOFFERs */ - if (dhcp_offer_list == NULL) { - printf(_("No DHCPOFFERs were received.\n")); - return result; - } + // Get the addresses for printout + // 1.address of the sending server + char server_address[INET_ADDRSTRLEN]; + const char *server_address_transformed = + inet_ntop(AF_INET, &undesired_offer->server_address, server_address, sizeof(server_address)); + + if (server_address != server_address_transformed) { + die(STATE_UNKNOWN, "inet_ntop failed"); + } - printf(_("Received %d DHCPOFFER(s)"), valid_responses); + // 2.address offered + char offered_address[INET_ADDRSTRLEN]; + const char *offered_address_transformed = + inet_ntop(AF_INET, &undesired_offer->offered_address, offered_address, sizeof(offered_address)); - if (exclusive && undesired_offer) { - printf(_(", Rogue DHCP Server detected! Server %s"), inet_ntoa(undesired_offer->server_address)); - printf(_(" offered %s \n"), inet_ntoa(undesired_offer->offered_address)); - return result; - } + if (offered_address != offered_address_transformed) { + die(STATE_UNKNOWN, "inet_ntop failed"); + } - if (requested_servers > 0) { - printf(_(", %s%d of %d requested servers responded"), - ((requested_responses < requested_servers) && requested_responses > 0) ? "only " : "", requested_responses, - requested_servers); + xasprintf(&sc_rogue_server.output, "Rogue DHCP Server detected! Server %s offered %s", server_address, offered_address); + } else { + sc_rogue_server = mp_set_subcheck_state(sc_rogue_server, STATE_OK); + xasprintf(&sc_rogue_server.output, "No Rogue DHCP Server detected"); + } + mp_add_subcheck_to_subcheck(&sc_dhcp_results, sc_rogue_server); } if (request_specific_address) { - printf(_(", requested address (%s) was %soffered"), inet_ntoa(requested_address), (received_requested_address) ? "" : _("not ")); - } + mp_subcheck sc_rqustd_addr = mp_subcheck_init(); - printf(_(", max lease time = ")); - if (max_lease_time == DHCP_INFINITE_TIME) { - printf(_("Infinity")); - } else { - printf("%lu sec", (unsigned long)max_lease_time); - } + if (received_requested_address) { + sc_rqustd_addr = mp_set_subcheck_state(sc_rqustd_addr, STATE_OK); + xasprintf(&sc_rqustd_addr.output, "Requested address (%s) was offered", inet_ntoa(requested_address)); + } else { + sc_rqustd_addr = mp_set_subcheck_state(sc_rqustd_addr, STATE_WARNING); + xasprintf(&sc_rqustd_addr.output, "Requested address (%s) was NOT offered", inet_ntoa(requested_address)); + } - printf(".\n"); + mp_add_subcheck_to_subcheck(&sc_dhcp_results, sc_rqustd_addr); + } - return result; + return sc_dhcp_results; } /* process command-line arguments */ -static int process_arguments(int argc, char **argv) { +process_arguments_wrapper process_arguments(int argc, char **argv) { if (argc < 1) { - return ERROR; + process_arguments_wrapper tmp = { + .error = ERROR, + }; + return tmp; } - call_getopt(argc, argv); - return validate_arguments(argc); -} + enum { + output_format_index = CHAR_MAX + 1, + }; -static int call_getopt(int argc, char **argv) { - extern int optind; int option_index = 0; static struct option long_options[] = {{"serverip", required_argument, 0, 's'}, {"requestedip", required_argument, 0, 'r'}, @@ -1092,65 +1148,55 @@ static int call_getopt(int argc, char **argv) { {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, + {"output-format", required_argument, 0, output_format_index}, {0, 0, 0, 0}}; - int c = 0; + check_dhcp_config config = check_dhcp_config_init(); + int option_char = 0; while (true) { - c = getopt_long(argc, argv, "+hVvxt:s:r:t:i:m:u", long_options, &option_index); + option_char = getopt_long(argc, argv, "+hVvxt:s:r:t:i:m:u", long_options, &option_index); - if (c == -1 || c == EOF || c == 1) { + if (option_char == -1 || option_char == EOF || option_char == 1) { break; } - switch (c) { - + switch (option_char) { case 's': /* DHCP server address */ - resolve_host(optarg, &dhcp_ip); - add_requested_server(dhcp_ip); + resolve_host(optarg, &config.dhcp_ip); + add_requested_server(config.dhcp_ip, &config.num_of_requested_servers, &config.requested_server_list); break; case 'r': /* address we are requested from DHCP servers */ - resolve_host(optarg, &requested_address); - request_specific_address = true; + resolve_host(optarg, &config.requested_address); + config.request_specific_address = true; break; case 't': /* timeout */ - - /* - if(is_intnonneg(optarg)) - */ if (atoi(optarg) > 0) { - dhcpoffer_timeout = atoi(optarg); + config.dhcpoffer_timeout = atoi(optarg); } - /* - else - usage("Time interval must be a nonnegative integer\n"); - */ break; case 'm': /* MAC address */ - - if ((user_specified_mac = mac_aton(optarg)) == NULL) { + if ((config.user_specified_mac = mac_aton(optarg)) == NULL) { usage("Cannot parse MAC address.\n"); } if (verbose) { - print_hardware_address(user_specified_mac); + print_hardware_address(config.user_specified_mac); } - break; case 'i': /* interface name */ - - strncpy(network_interface_name, optarg, sizeof(network_interface_name) - 1); - network_interface_name[sizeof(network_interface_name) - 1] = '\x0'; - + strncpy(config.network_interface_name, optarg, sizeof(config.network_interface_name) - 1); + config.network_interface_name[sizeof(config.network_interface_name) - 1] = '\x0'; break; case 'u': /* unicast testing */ - unicast = true; + config.unicast_mode = true; break; + case 'x': /* exclusive testing aka "rogue DHCP server detection" */ - exclusive = true; + config.exclusive_mode = true; break; case 'V': /* version */ @@ -1164,6 +1210,18 @@ static int call_getopt(int argc, char **argv) { case 'v': /* verbose */ verbose = 1; break; + case output_format_index: { + parsed_output_format parser = mp_parse_output_format(optarg); + if (!parser.parsing_success) { + // TODO List all available formats here, maybe add anothoer usage function + printf("Invalid output format: %s\n", optarg); + exit(STATE_UNKNOWN); + } + + config.output_format_is_set = true; + config.output_format = parser.output_format; + break; + } case '?': /* help */ usage5(); break; @@ -1172,16 +1230,16 @@ static int call_getopt(int argc, char **argv) { break; } } - return optind; -} - -static int validate_arguments(int argc) { if (argc - optind > 0) { usage(_("Got unexpected non-option argument")); } - return OK; + process_arguments_wrapper result = { + .config = config, + .error = OK, + }; + return result; } #if defined(__sun__) || defined(__solaris__) || defined(__hpux__) @@ -1300,7 +1358,7 @@ static int dl_bind(int fd, int sap, u_char *addr) { * ***********************************************************************/ -static long mac_addr_dlpi(const char *dev, int unit, u_char *addr) { +long mac_addr_dlpi(const char *dev, int unit, u_char *addr) { int fd; u_char mac_addr[25]; @@ -1319,26 +1377,27 @@ static long mac_addr_dlpi(const char *dev, int unit, u_char *addr) { #endif /* resolve host name or die (TODO: move this to netutils.c!) */ -static void resolve_host(const char *in, struct in_addr *out) { - struct addrinfo hints, *ai; +void resolve_host(const char *name, struct in_addr *out) { + struct addrinfo hints = { + .ai_family = PF_INET, + }; + struct addrinfo *addr_info; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_INET; - if (getaddrinfo(in, NULL, &hints, &ai) != 0) { + if (getaddrinfo(name, NULL, &hints, &addr_info) != 0) { usage_va(_("Invalid hostname/address - %s"), optarg); } - memcpy(out, &((struct sockaddr_in *)ai->ai_addr)->sin_addr, sizeof(*out)); - freeaddrinfo(ai); + memcpy(out, &((struct sockaddr_in *)addr_info->ai_addr)->sin_addr, sizeof(*out)); + freeaddrinfo(addr_info); } /* parse MAC address string, return 6 bytes (unterminated) or NULL */ -static unsigned char *mac_aton(const char *string) { - static unsigned char result[6]; +unsigned char *mac_aton(const char *string) { + static unsigned char result[MAC_ADDR_LEN]; char tmp[3]; - unsigned i, j; + unsigned byte_counter = 0; - for (i = 0, j = 0; string[i] != '\0' && j < sizeof(result); i++) { + for (int i = 0; string[i] != '\0' && byte_counter < sizeof(result); i++) { /* ignore ':' and any other non-hex character */ if (!isxdigit(string[i]) || !isxdigit(string[i + 1])) { continue; @@ -1346,27 +1405,25 @@ static unsigned char *mac_aton(const char *string) { tmp[0] = string[i]; tmp[1] = string[i + 1]; tmp[2] = '\0'; - result[j] = strtol(tmp, (char **)NULL, 16); + result[byte_counter] = strtol(tmp, (char **)NULL, 16); i++; - j++; + byte_counter++; } - return (j == 6) ? result : NULL; + return (byte_counter == MAC_ADDR_LEN) ? result : NULL; } -static void print_hardware_address(const unsigned char *address) { - int i; +void print_hardware_address(const unsigned char *address) { printf(_("Hardware address: ")); - for (i = 0; i < 5; i++) { - printf("%2.2x:", address[i]); + for (int addr_idx = 0; addr_idx < MAC_ADDR_LEN; addr_idx++) { + printf("%2.2x:", address[addr_idx]); } - printf("%2.2x", address[i]); putchar('\n'); } /* print usage help */ -static void print_help(void) { +void print_help(void) { print_revision(progname, NP_VERSION); @@ -1382,6 +1439,7 @@ static void print_help(void) { printf(UT_HELP_VRSN); printf(UT_EXTRA_OPTS); + printf(UT_OUTPUT_FORMAT); printf(UT_VERBOSE); printf(" %s\n", "-s, --serverip=IPADDRESS"); @@ -1400,7 +1458,6 @@ static void print_help(void) { printf(" %s\n", _("Only requested DHCP server may response (rogue DHCP server detection), requires -s")); printf(UT_SUPPORT); - return; } void print_usage(void) { @@ -1408,6 +1465,4 @@ void print_usage(void) { printf("%s\n", _("Usage:")); printf(" %s [-v] [-u] [-x] [-s serverip] [-r requestedip] [-t timeout]\n", progname); printf(" [-i interface] [-m mac]\n"); - - return; } diff --git a/plugins-root/check_dhcp.d/config.h b/plugins-root/check_dhcp.d/config.h new file mode 100644 index 00000000..f189068b --- /dev/null +++ b/plugins-root/check_dhcp.d/config.h @@ -0,0 +1,50 @@ +#pragma once + +#include "../../config.h" +#include "../lib/states.h" +#include +#include +#include "net/if.h" +#include "output.h" + +typedef struct requested_server_struct { + struct in_addr server_address; + bool answered; + struct requested_server_struct *next; +} requested_server; + +typedef struct check_dhcp_config { + bool unicast_mode; /* unicast mode: mimic a DHCP relay */ + bool exclusive_mode; /* exclusive mode aka "rogue DHCP server detection" */ + int num_of_requested_servers; + struct in_addr dhcp_ip; /* server to query (if in unicast mode) */ + struct in_addr requested_address; + bool request_specific_address; + + int dhcpoffer_timeout; + unsigned char *user_specified_mac; + char network_interface_name[IFNAMSIZ]; + requested_server *requested_server_list; + + mp_output_format output_format; + bool output_format_is_set; +} check_dhcp_config; + +check_dhcp_config check_dhcp_config_init(void) { + check_dhcp_config tmp = { + .unicast_mode = false, + .exclusive_mode = false, + .num_of_requested_servers = 0, + .dhcp_ip = {0}, + .requested_address = {0}, + .request_specific_address = false, + + .dhcpoffer_timeout = 2, + .user_specified_mac = NULL, + .network_interface_name = "eth0", + .requested_server_list = NULL, + + .output_format_is_set = false, + }; + return tmp; +} -- cgit v1.2.3-74-g34f1 From d3f22c96bbfa8f31a6d795387f10a825f78c7aef Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Tue, 1 Apr 2025 01:18:23 +0200 Subject: check_dhcp: little fix to output --- plugins-root/check_dhcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins-root') diff --git a/plugins-root/check_dhcp.c b/plugins-root/check_dhcp.c index 3732d970..daed9cb0 100644 --- a/plugins-root/check_dhcp.c +++ b/plugins-root/check_dhcp.c @@ -972,7 +972,7 @@ mp_subcheck get_results(bool exclusive, const int requested_servers, const struc /* we didn't receive any DHCPOFFERs */ if (dhcp_offer_list == NULL) { sc_dhcp_results = mp_set_subcheck_state(sc_dhcp_results, STATE_CRITICAL); - xasprintf(&sc_dhcp_results.output, "%s", "No DHCP offers were received"); + xasprintf(&sc_dhcp_results.output, "%s", "No DHCPOFFERs were received"); return sc_dhcp_results; } -- cgit v1.2.3-74-g34f1 From bf0b389381dce2c950834a847db2933196111310 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Tue, 1 Apr 2025 01:18:44 +0200 Subject: Adapt tests --- plugins-root/t/check_dhcp.t | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'plugins-root') diff --git a/plugins-root/t/check_dhcp.t b/plugins-root/t/check_dhcp.t index ce627736..54949612 100644 --- a/plugins-root/t/check_dhcp.t +++ b/plugins-root/t/check_dhcp.t @@ -12,14 +12,14 @@ my $allow_sudo = getTestParameter( "NP_ALLOW_SUDO", "no" ); if ($allow_sudo eq "yes" or $> == 0) { - plan tests => 6; + plan tests => 8; } else { plan skip_all => "Need sudo to test check_dhcp"; } my $sudo = $> == 0 ? '' : 'sudo'; -my $successOutput = '/OK: Received \d+ DHCPOFFER\(s\), \d+ of 1 requested servers responded, max lease time = \d+ sec\./'; -my $failureOutput = '/CRITICAL: (No DHCPOFFERs were received|Received \d+ DHCPOFFER\(s\), 0 of 1 requested servers responded, max lease time = \d+ sec\.)/'; +my $successOutput = '/Received \d+ DHCPOFFER(s)*, max lease time = \d+ seconds/'; +my $failureOutput = '/(No DHCPOFFERs were received|Received \d+ DHCPOFFER\(s\), 0 of 1 requested servers responded, max lease time = \d+ sec\.)/'; my $invalidOutput = '/Invalid hostname/'; my $host_responsive = getTestParameter( "NP_HOST_DHCP_RESPONSIVE", @@ -34,6 +34,8 @@ my $hostname_invalid = getTestParameter( "NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost" ); +my $output_format = "--output-format mp-test-json"; + # try to determince interface my $interface = ''; @@ -49,19 +51,21 @@ my $res; SKIP: { skip('need responsive test host', 2) unless $host_responsive; $res = NPTest->testCmd( - "$sudo ./check_dhcp $interface -u -s $host_responsive" + "$sudo ./check_dhcp $interface -u -s $host_responsive $output_format" ); - is( $res->return_code, 0, "Syntax ok" ); - like( $res->output, $successOutput, "Output OK" ); + is( $res->return_code, 0, "with JSON test format result should always be OK" ); + like( $res->{'mp_test_result'}->{'state'}, "/OK/", "Output OK" ); + like( $res->{'mp_test_result'}->{'checks'}->[0]->{'output'}, $successOutput, "Output OK" ); }; SKIP: { skip('need nonresponsive test host', 2) unless $host_nonresponsive; $res = NPTest->testCmd( - "$sudo ./check_dhcp $interface -u -s $host_nonresponsive" + "$sudo ./check_dhcp $interface -u -s $host_nonresponsive $output_format" ); - is( $res->return_code, 2, "Exit code - host nonresponsive" ); - like( $res->output, $failureOutput, "Output OK" ); + is( $res->return_code, 0, "with JSON test format result should always be OK" ); + like( $res->{'mp_test_result'}->{'state'}, "/CRITICAL/", "Exit code - host nonresponsive" ); + like( $res->{'mp_test_result'}->{'checks'}->[0]->{'output'}, $failureOutput, "Output OK" ); }; SKIP: { @@ -69,6 +73,6 @@ SKIP: { $res = NPTest->testCmd( "$sudo ./check_dhcp $interface -u -s $hostname_invalid" ); - is( $res->return_code, 3, "Exit code - host invalid" ); + is( $res->return_code, 3, "invalid hostname/address should return UNKNOWN" ); like( $res->output, $invalidOutput, "Output OK" ); }; -- cgit v1.2.3-74-g34f1 From 52338c3423d4b10d2bbeec7a120c7dd2a98fa092 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 23 Jun 2025 12:33:28 +0200 Subject: check_dhcp: reduce number of tests for weird reasons --- plugins-root/t/check_dhcp.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins-root') diff --git a/plugins-root/t/check_dhcp.t b/plugins-root/t/check_dhcp.t index 54949612..70392154 100644 --- a/plugins-root/t/check_dhcp.t +++ b/plugins-root/t/check_dhcp.t @@ -12,7 +12,7 @@ my $allow_sudo = getTestParameter( "NP_ALLOW_SUDO", "no" ); if ($allow_sudo eq "yes" or $> == 0) { - plan tests => 8; + plan tests => 7; } else { plan skip_all => "Need sudo to test check_dhcp"; } -- cgit v1.2.3-74-g34f1 From 528d2015d0e5c7fcdd7e11029758bafa63086ed2 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 23 Jun 2025 13:02:41 +0200 Subject: Add check_dhcp related files to Makefile --- plugins-root/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'plugins-root') diff --git a/plugins-root/Makefile.am b/plugins-root/Makefile.am index fffc0575..b6342909 100644 --- a/plugins-root/Makefile.am +++ b/plugins-root/Makefile.am @@ -25,7 +25,8 @@ noinst_PROGRAMS = check_dhcp check_icmp @EXTRAS_ROOT@ EXTRA_PROGRAMS = pst3 EXTRA_DIST = t pst3.c \ - check_icmp.d + check_icmp.d \ + check_dhcp.d BASEOBJS = ../plugins/utils.o ../lib/libmonitoringplug.a ../gl/libgnu.a NETOBJS = ../plugins/netutils.o $(BASEOBJS) $(EXTRA_NETOBJS) -- cgit v1.2.3-74-g34f1 From 612d261cbf467c82f0dcc0ed63e7584d91f194c4 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 23 Jun 2025 13:02:52 +0200 Subject: Revert "check_dhcp: reduce number of tests for weird reasons" This reverts commit 52338c3423d4b10d2bbeec7a120c7dd2a98fa092. --- plugins-root/t/check_dhcp.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins-root') diff --git a/plugins-root/t/check_dhcp.t b/plugins-root/t/check_dhcp.t index 70392154..54949612 100644 --- a/plugins-root/t/check_dhcp.t +++ b/plugins-root/t/check_dhcp.t @@ -12,7 +12,7 @@ my $allow_sudo = getTestParameter( "NP_ALLOW_SUDO", "no" ); if ($allow_sudo eq "yes" or $> == 0) { - plan tests => 7; + plan tests => 8; } else { plan skip_all => "Need sudo to test check_dhcp"; } -- cgit v1.2.3-74-g34f1 From 9f776105d44190587a587b7398f5d907611a20b0 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 23 Jun 2025 13:21:25 +0200 Subject: Reapply "check_dhcp: reduce number of tests for weird reasons" This reverts commit 612d261cbf467c82f0dcc0ed63e7584d91f194c4. --- plugins-root/t/check_dhcp.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins-root') diff --git a/plugins-root/t/check_dhcp.t b/plugins-root/t/check_dhcp.t index 54949612..70392154 100644 --- a/plugins-root/t/check_dhcp.t +++ b/plugins-root/t/check_dhcp.t @@ -12,7 +12,7 @@ my $allow_sudo = getTestParameter( "NP_ALLOW_SUDO", "no" ); if ($allow_sudo eq "yes" or $> == 0) { - plan tests => 8; + plan tests => 7; } else { plan skip_all => "Need sudo to test check_dhcp"; } -- cgit v1.2.3-74-g34f1 From 802e46f8ea36c344f112d7e1dd8d64d17a4cc939 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Mon, 15 Sep 2025 12:59:37 +0200 Subject: Run clang-format again --- lib/extra_opts.c | 28 +- lib/maxfd.c | 5 +- lib/output.c | 11 +- lib/parse_ini.c | 112 +++-- lib/tests/test_base64.c | 271 +++++++----- lib/tests/test_cmd.c | 27 +- lib/tests/test_generic_output.c | 6 +- lib/tests/test_ini1.c | 51 ++- lib/tests/test_opts1.c | 34 +- lib/tests/test_opts2.c | 69 +-- lib/tests/test_tcp.c | 23 +- lib/utils_base.c | 4 +- lib/utils_cmd.c | 95 ++-- lib/utils_tcp.c | 25 +- lib/utils_tcp.h | 3 +- plugins-root/check_dhcp.c | 258 +++++++---- plugins-root/check_icmp.d/config.h | 2 +- plugins-root/pst3.c | 441 +++++++++---------- plugins/check_by_ssh.c | 108 +++-- plugins/check_cluster.c | 26 +- plugins/check_dbi.c | 108 +++-- plugins/check_dig.c | 18 +- plugins/check_disk.c | 288 +++++++----- plugins/check_disk.d/utils_disk.c | 35 +- plugins/check_disk.d/utils_disk.h | 9 +- plugins/check_dns.c | 133 ++++-- plugins/check_dummy.c | 15 +- plugins/check_fping.c | 58 ++- plugins/check_fping.d/config.h | 1 - plugins/check_game.c | 68 +-- plugins/check_hpjd.c | 14 +- plugins/check_ldap.c | 50 ++- plugins/check_load.c | 24 +- plugins/check_mrtg.c | 53 ++- plugins/check_mrtgtraf.c | 32 +- plugins/check_mysql.c | 88 ++-- plugins/check_mysql_query.c | 37 +- plugins/check_nt.c | 115 +++-- plugins/check_ntp.c | 756 +++++++++++++++++--------------- plugins/check_ntp_peer.c | 118 ++--- plugins/check_ntp_time.c | 91 ++-- plugins/check_pgsql.c | 77 ++-- plugins/check_ping.c | 125 ++++-- plugins/check_procs.c | 93 ++-- plugins/check_radius.c | 36 +- plugins/check_real.c | 28 +- plugins/check_smtp.c | 119 +++-- plugins/check_swap.c | 23 +- plugins/check_swap.d/check_swap.h | 3 +- plugins/check_swap.d/swap.c | 18 +- plugins/check_tcp.c | 147 ++++--- plugins/check_time.c | 25 +- plugins/check_ups.c | 47 +- plugins/check_ups.d/config.h | 1 - plugins/check_users.c | 19 +- plugins/check_users.d/users.c | 6 +- plugins/common.h | 175 ++++---- plugins/negate.c | 44 +- plugins/netutils.c | 12 +- plugins/picohttpparser/picohttpparser.c | 243 +++++----- plugins/picohttpparser/picohttpparser.h | 31 +- plugins/popen.c | 68 ++- plugins/popen.h | 20 +- plugins/runcmd.c | 77 ++-- plugins/runcmd.h | 47 +- plugins/sslutils.c | 6 +- plugins/tests/test_check_disk.c | 48 +- plugins/tests/test_check_swap.c | 4 +- plugins/urlize.c | 36 +- plugins/utils.c | 35 +- plugins/utils.h | 51 ++- tap/tap.c | 25 +- tap/tap.h | 43 +- tools/mini_epn.c | 96 ++-- 74 files changed, 3290 insertions(+), 2248 deletions(-) (limited to 'plugins-root') diff --git a/lib/extra_opts.c b/lib/extra_opts.c index 88787336..857b34b4 100644 --- a/lib/extra_opts.c +++ b/lib/extra_opts.c @@ -27,12 +27,13 @@ /* FIXME: copied from utils.h; we should move a bunch of libs! */ bool is_option2(char *str) { - if (!str) + if (!str) { return false; - else if (strspn(str, "-") == 1 || strspn(str, "-") == 2) + } else if (strspn(str, "-") == 1 || strspn(str, "-") == 2) { return true; - else + } else { return false; + } } /* this is the externally visible function used by plugins */ @@ -56,8 +57,9 @@ char **np_extra_opts(int *argc, char **argv, const char *plugin_name) { /* It is a single argument with value */ argptr = argv[i] + 13; /* Delete the extra opts argument */ - for (j = i; j < *argc; j++) + for (j = i; j < *argc; j++) { argv[j] = argv[j + 1]; + } i--; *argc -= 1; } else if (strcmp(argv[i], "--extra-opts") == 0) { @@ -65,8 +67,9 @@ char **np_extra_opts(int *argc, char **argv, const char *plugin_name) { /* It is a argument with separate value */ argptr = argv[i + 1]; /* Delete the extra-opts argument/value */ - for (j = i; j < *argc - 1; j++) + for (j = i; j < *argc - 1; j++) { argv[j] = argv[j + 2]; + } i -= 2; *argc -= 2; ea_num--; @@ -74,8 +77,9 @@ char **np_extra_opts(int *argc, char **argv, const char *plugin_name) { /* It has no value */ optfound = 1; /* Delete the extra opts argument */ - for (j = i; j < *argc; j++) + for (j = i; j < *argc; j++) { argv[j] = argv[j + 1]; + } i--; *argc -= 1; } @@ -94,16 +98,18 @@ char **np_extra_opts(int *argc, char **argv, const char *plugin_name) { /* append the list to extra_args */ if (extra_args == NULL) { extra_args = ea1; - while ((ea1 = ea1->next)) + while ((ea1 = ea1->next)) { ea_num++; + } } else { ea_tmp = extra_args; while (ea_tmp->next) { ea_tmp = ea_tmp->next; } ea_tmp->next = ea1; - while ((ea1 = ea1->next)) + while ((ea1 = ea1->next)) { ea_num++; + } } ea1 = ea_tmp = NULL; } @@ -116,8 +122,9 @@ char **np_extra_opts(int *argc, char **argv, const char *plugin_name) { /* done processing arguments. now create a new argv array... */ argv_new = (char **)malloc((ea_num + 1) * sizeof(char **)); - if (argv_new == NULL) + if (argv_new == NULL) { die(STATE_UNKNOWN, _("malloc() failed!\n")); + } /* starting with program name */ argv_new[0] = argv[0]; @@ -130,8 +137,9 @@ char **np_extra_opts(int *argc, char **argv, const char *plugin_name) { free(ea1); } /* finally the rest of the argv array */ - for (i = 1; i < *argc; i++) + for (i = 1; i < *argc; i++) { argv_new[argc_new++] = argv[i]; + } *argc = argc_new; /* and terminate. */ argv_new[argc_new] = NULL; diff --git a/lib/maxfd.c b/lib/maxfd.c index ca5b6e54..9b58d8e3 100644 --- a/lib/maxfd.c +++ b/lib/maxfd.c @@ -31,10 +31,11 @@ long mp_open_max(void) { #ifdef _SC_OPEN_MAX errno = 0; if ((maxfd = sysconf(_SC_OPEN_MAX)) < 0) { - if (errno == 0) + if (errno == 0) { maxfd = DEFAULT_MAXFD; /* it's indeterminate */ - else + } else { die(STATE_UNKNOWN, _("sysconf error for _SC_OPEN_MAX\n")); + } } #elif defined(OPEN_MAX) return OPEN_MAX diff --git a/lib/output.c b/lib/output.c index 34ff7dab..f283969f 100644 --- a/lib/output.c +++ b/lib/output.c @@ -377,7 +377,9 @@ static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subch while (tmp_string != NULL) { *tmp_string = '\0'; - asprintf(&intermediate_string, "%s%s\n%s", intermediate_string,check.output, generate_indentation_string(indentation+1)); // one more indentation to make it look better + asprintf(&intermediate_string, "%s%s\n%s", intermediate_string, check.output, + generate_indentation_string( + indentation + 1)); // one more indentation to make it look better if (*(tmp_string + 1) != '\0') { check.output = tmp_string + 1; @@ -394,13 +396,14 @@ static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subch // add the rest (if any) if (have_residual_chars) { char *tmp = check.output; - xasprintf(&check.output, "%s\n%s%s", intermediate_string, generate_indentation_string(indentation+1), tmp); + xasprintf(&check.output, "%s\n%s%s", intermediate_string, + generate_indentation_string(indentation + 1), tmp); } else { check.output = intermediate_string; } } - asprintf(&result, "%s\\_[%s] - %s", generate_indentation_string(indentation), state_text(mp_compute_subcheck_state(check)), - check.output); + asprintf(&result, "%s\\_[%s] - %s", generate_indentation_string(indentation), + state_text(mp_compute_subcheck_state(check)), check.output); subchecks = check.subchecks; diff --git a/lib/parse_ini.c b/lib/parse_ini.c index 1289aae2..4c3c1b93 100644 --- a/lib/parse_ini.c +++ b/lib/parse_ini.c @@ -40,19 +40,22 @@ typedef struct { char *stanza; } np_ini_info; -static char *default_ini_file_names[] = {"monitoring-plugins.ini", "plugins.ini", "nagios-plugins.ini", NULL}; +static char *default_ini_file_names[] = {"monitoring-plugins.ini", "plugins.ini", + "nagios-plugins.ini", NULL}; static char *default_ini_path_names[] = { - "/usr/local/etc/monitoring-plugins/monitoring-plugins.ini", "/usr/local/etc/monitoring-plugins.ini", - "/etc/monitoring-plugins/monitoring-plugins.ini", "/etc/monitoring-plugins.ini", + "/usr/local/etc/monitoring-plugins/monitoring-plugins.ini", + "/usr/local/etc/monitoring-plugins.ini", "/etc/monitoring-plugins/monitoring-plugins.ini", + "/etc/monitoring-plugins.ini", /* deprecated path names (for backward compatibility): */ - "/etc/nagios/plugins.ini", "/usr/local/nagios/etc/plugins.ini", "/usr/local/etc/nagios/plugins.ini", "/etc/opt/nagios/plugins.ini", - "/etc/nagios-plugins.ini", "/usr/local/etc/nagios-plugins.ini", "/etc/opt/nagios-plugins.ini", NULL}; + "/etc/nagios/plugins.ini", "/usr/local/nagios/etc/plugins.ini", + "/usr/local/etc/nagios/plugins.ini", "/etc/opt/nagios/plugins.ini", "/etc/nagios-plugins.ini", + "/usr/local/etc/nagios-plugins.ini", "/etc/opt/nagios-plugins.ini", NULL}; /* eat all characters from a FILE pointer until n is encountered */ -#define GOBBLE_TO(f, c, n) \ - do { \ - (c) = fgetc((f)); \ +#define GOBBLE_TO(f, c, n) \ + do { \ + (c) = fgetc((f)); \ } while ((c) != EOF && (c) != (n)) /* internal function that returns the constructed defaults options */ @@ -87,8 +90,9 @@ static void parse_locator(const char *locator, const char *def_stanza, np_ini_in i->stanza = strdup(def_stanza); } - if (i->stanza == NULL) + if (i->stanza == NULL) { die(STATE_UNKNOWN, _("malloc() failed!\n")); + } /* check whether there's an @file part */ if (stanza_len == locator_len) { @@ -99,8 +103,9 @@ static void parse_locator(const char *locator, const char *def_stanza, np_ini_in i->file_string_on_heap = true; } - if (i->file == NULL || i->file[0] == '\0') + if (i->file == NULL || i->file[0] == '\0') { die(STATE_UNKNOWN, _("Cannot find config file in any standard location.\n")); + } } /* @@ -112,26 +117,31 @@ np_arg_list *np_get_defaults(const char *locator, const char *default_section) { np_ini_info i; int is_suid_plugin = mp_suid(); - if (is_suid_plugin && idpriv_temp_drop() == -1) + if (is_suid_plugin && idpriv_temp_drop() == -1) { die(STATE_UNKNOWN, _("Cannot drop privileges: %s\n"), strerror(errno)); + } parse_locator(locator, default_section, &i); inifile = strcmp(i.file, "-") == 0 ? stdin : fopen(i.file, "r"); - if (inifile == NULL) + if (inifile == NULL) { die(STATE_UNKNOWN, _("Can't read config file: %s\n"), strerror(errno)); - if (!read_defaults(inifile, i.stanza, &defaults)) + } + if (!read_defaults(inifile, i.stanza, &defaults)) { die(STATE_UNKNOWN, _("Invalid section '%s' in config file '%s'\n"), i.stanza, i.file); + } if (i.file_string_on_heap) { free(i.file); } - if (inifile != stdin) + if (inifile != stdin) { fclose(inifile); + } free(i.stanza); - if (is_suid_plugin && idpriv_temp_restore() == -1) + if (is_suid_plugin && idpriv_temp_restore() == -1) { die(STATE_UNKNOWN, _("Cannot restore privileges: %s\n"), strerror(errno)); + } return defaults; } @@ -158,8 +168,9 @@ static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts) { /* our little stanza-parsing state machine */ while ((c = fgetc(f)) != EOF) { /* gobble up leading whitespace */ - if (isspace(c)) + if (isspace(c)) { continue; + } switch (c) { /* globble up comment lines */ case ';': @@ -172,9 +183,11 @@ static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts) { for (i = 0; i < stanza_len; i++) { c = fgetc(f); /* strip leading whitespace */ - if (i == 0) - for (; isspace(c); c = fgetc(f)) + if (i == 0) { + for (; isspace(c); c = fgetc(f)) { continue; + } + } /* nope, read to the end of the line */ if (c != stanza[i]) { GOBBLE_TO(f, c, '\n'); @@ -185,10 +198,12 @@ static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts) { if (i == stanza_len) { c = fgetc(f); /* strip trailing whitespace */ - for (; isspace(c); c = fgetc(f)) + for (; isspace(c); c = fgetc(f)) { continue; - if (c == ']') + } + if (c == ']') { stanzastate = RIGHTSTANZA; + } } break; /* otherwise, we're in the body of a stanza or a parse error */ @@ -239,12 +254,13 @@ static int add_option(FILE *f, np_arg_list **optlst) { if (linebuf == NULL || read_pos + read_sz >= linebuf_sz) { linebuf_sz = linebuf_sz > 0 ? linebuf_sz << 1 : read_sz; linebuf = realloc(linebuf, linebuf_sz); - if (linebuf == NULL) + if (linebuf == NULL) { die(STATE_UNKNOWN, _("malloc() failed!\n")); + } } - if (fgets(&linebuf[read_pos], (int)read_sz, f) == NULL) + if (fgets(&linebuf[read_pos], (int)read_sz, f) == NULL) { done_reading = 1; - else { + } else { read_pos = strlen(linebuf); if (linebuf[read_pos - 1] == '\n') { linebuf[--read_pos] = '\0'; @@ -256,38 +272,46 @@ static int add_option(FILE *f, np_arg_list **optlst) { /* all that to read one line, isn't C fun? :) now comes the parsing :/ */ /* skip leading whitespace */ - for (optptr = linebuf; optptr < lineend && isspace(*optptr); optptr++) + for (optptr = linebuf; optptr < lineend && isspace(*optptr); optptr++) { continue; + } /* continue to '=' or EOL, watching for spaces that might precede it */ for (eqptr = optptr; eqptr < lineend && *eqptr != '='; eqptr++) { - if (isspace(*eqptr) && optend == NULL) + if (isspace(*eqptr) && optend == NULL) { optend = eqptr; - else + } else { optend = NULL; + } } - if (optend == NULL) + if (optend == NULL) { optend = eqptr; + } --optend; /* ^[[:space:]]*=foo is a syntax error */ - if (optptr == eqptr) + if (optptr == eqptr) { die(STATE_UNKNOWN, "%s\n", _("Config file error")); + } /* continue from '=' to start of value or EOL */ - for (valptr = eqptr + 1; valptr < lineend && isspace(*valptr); valptr++) + for (valptr = eqptr + 1; valptr < lineend && isspace(*valptr); valptr++) { continue; + } /* continue to the end of value */ - for (valend = valptr; valend < lineend; valend++) + for (valend = valptr; valend < lineend; valend++) { continue; + } --valend; /* finally trim off trailing spaces */ - for (; isspace(*valend); valend--) + for (; isspace(*valend); valend--) { continue; + } /* calculate the length of "--foo" */ opt_len = (size_t)(1 + optend - optptr); /* 1-character params needs only one dash */ - if (opt_len == 1) + if (opt_len == 1) { cfg_len = 1 + (opt_len); - else + } else { cfg_len = 2 + (opt_len); + } /* if valptrarg[read_pos] = '\0'; /* ...and put that to the end of the list */ - if (*optlst == NULL) + if (*optlst == NULL) { *optlst = optnew; - else { - while (opttmp->next != NULL) + } else { + while (opttmp->next != NULL) { opttmp = opttmp->next; + } opttmp->next = optnew; } @@ -344,7 +370,8 @@ static int add_option(FILE *f, np_arg_list **optlst) { static char *default_file(void) { char *ini_file; - if ((ini_file = getenv("MP_CONFIG_FILE")) != NULL || (ini_file = default_file_in_path()) != NULL) { + if ((ini_file = getenv("MP_CONFIG_FILE")) != NULL || + (ini_file = default_file_in_path()) != NULL) { return ini_file; } @@ -360,16 +387,19 @@ static char *default_file_in_path(void) { char *config_path, **file; char *dir, *ini_file, *tokens; - if ((config_path = getenv("NAGIOS_CONFIG_PATH")) == NULL) + if ((config_path = getenv("NAGIOS_CONFIG_PATH")) == NULL) { return NULL; + } /* shall we spit out a warning that NAGIOS_CONFIG_PATH is deprecated? */ - if ((tokens = strdup(config_path)) == NULL) + if ((tokens = strdup(config_path)) == NULL) { die(STATE_UNKNOWN, "%s\n", _("Insufficient Memory")); + } for (dir = strtok(tokens, ":"); dir != NULL; dir = strtok(NULL, ":")) { for (file = default_ini_file_names; *file != NULL; file++) { - if ((asprintf(&ini_file, "%s/%s", dir, *file)) < 0) + if ((asprintf(&ini_file, "%s/%s", dir, *file)) < 0) { die(STATE_UNKNOWN, "%s\n", _("Insufficient Memory")); + } if (access(ini_file, F_OK) == 0) { free(tokens); return ini_file; diff --git a/lib/tests/test_base64.c b/lib/tests/test_base64.c index 94cb5aa9..798244da 100644 --- a/lib/tests/test_base64.c +++ b/lib/tests/test_base64.c @@ -180,117 +180,168 @@ int main(int argc, char **argv) { #endif char random[1024] = { - 0x0b, 0x30, 0x44, 0x62, 0x7c, 0x22, 0x1f, 0x0d, 0x05, 0x67, 0x2c, 0x2a, 0x39, 0x21, 0x46, 0x08, 0x50, 0x66, 0x34, 0x37, 0x0b, 0x45, - 0x4b, 0x38, 0x32, 0x06, 0x7a, 0x3e, 0x7f, 0x0c, 0x40, 0x18, 0x6b, 0x2d, 0x60, 0x4c, 0x60, 0x0c, 0x23, 0x43, 0x3b, 0x3e, 0x1b, 0x16, - 0x04, 0x46, 0x58, 0x3f, 0x40, 0x6a, 0x11, 0x05, 0x63, 0x71, 0x14, 0x35, 0x47, 0x79, 0x13, 0x6f, 0x6b, 0x27, 0x18, 0x5b, 0x48, 0x27, - 0x3e, 0x6f, 0x15, 0x33, 0x4f, 0x3e, 0x5e, 0x51, 0x73, 0x68, 0x25, 0x0f, 0x06, 0x5b, 0x7c, 0x72, 0x75, 0x3e, 0x3f, 0x1b, 0x5c, 0x6d, - 0x6a, 0x39, 0x7c, 0x63, 0x63, 0x60, 0x6c, 0x7a, 0x33, 0x76, 0x52, 0x13, 0x25, 0x33, 0x7d, 0x65, 0x23, 0x27, 0x11, 0x06, 0x06, 0x47, - 0x71, 0x1e, 0x14, 0x74, 0x63, 0x70, 0x2d, 0x15, 0x27, 0x18, 0x51, 0x06, 0x05, 0x33, 0x11, 0x2c, 0x6b, 0x00, 0x2d, 0x77, 0x20, 0x48, - 0x0d, 0x73, 0x51, 0x45, 0x25, 0x7f, 0x7f, 0x35, 0x26, 0x2e, 0x26, 0x53, 0x24, 0x68, 0x1e, 0x0e, 0x58, 0x3a, 0x59, 0x50, 0x56, 0x37, - 0x5f, 0x66, 0x01, 0x4c, 0x5a, 0x64, 0x32, 0x50, 0x7b, 0x6a, 0x20, 0x72, 0x2b, 0x1d, 0x7e, 0x43, 0x7b, 0x61, 0x42, 0x0b, 0x61, 0x73, - 0x24, 0x79, 0x3a, 0x6b, 0x4a, 0x79, 0x6e, 0x09, 0x0f, 0x27, 0x2d, 0x0c, 0x5e, 0x32, 0x4b, 0x0d, 0x79, 0x46, 0x39, 0x21, 0x0a, 0x26, - 0x5f, 0x3a, 0x00, 0x26, 0x3f, 0x13, 0x2e, 0x7e, 0x50, 0x2b, 0x67, 0x46, 0x72, 0x3f, 0x3b, 0x01, 0x46, 0x1b, 0x0b, 0x35, 0x49, 0x39, - 0x19, 0x70, 0x3d, 0x02, 0x41, 0x0e, 0x38, 0x05, 0x76, 0x65, 0x4f, 0x31, 0x6c, 0x5e, 0x17, 0x04, 0x15, 0x36, 0x26, 0x64, 0x34, 0x14, - 0x17, 0x7c, 0x0e, 0x0b, 0x5b, 0x55, 0x53, 0x6b, 0x00, 0x42, 0x41, 0x4f, 0x02, 0x5c, 0x13, 0x0a, 0x2c, 0x2c, 0x3e, 0x10, 0x14, 0x33, - 0x45, 0x7c, 0x7a, 0x5a, 0x31, 0x61, 0x39, 0x08, 0x22, 0x6a, 0x1e, 0x0f, 0x6f, 0x1b, 0x6c, 0x13, 0x5e, 0x79, 0x20, 0x79, 0x50, 0x62, - 0x06, 0x2c, 0x76, 0x17, 0x04, 0x2b, 0x2a, 0x75, 0x1f, 0x0c, 0x37, 0x4e, 0x0f, 0x7b, 0x2d, 0x34, 0x75, 0x60, 0x31, 0x74, 0x2e, 0x0a, - 0x4a, 0x11, 0x6c, 0x49, 0x25, 0x01, 0x3a, 0x3d, 0x22, 0x1e, 0x6d, 0x18, 0x51, 0x78, 0x2d, 0x62, 0x31, 0x4c, 0x50, 0x40, 0x17, 0x4b, - 0x6f, 0x22, 0x00, 0x7f, 0x61, 0x2a, 0x34, 0x3e, 0x00, 0x5f, 0x2f, 0x5f, 0x2f, 0x14, 0x2a, 0x55, 0x27, 0x1f, 0x46, 0x1f, 0x12, 0x46, - 0x5e, 0x1e, 0x0c, 0x7c, 0x38, 0x01, 0x61, 0x64, 0x76, 0x22, 0x6e, 0x08, 0x20, 0x38, 0x4f, 0x73, 0x72, 0x55, 0x12, 0x42, 0x19, 0x50, - 0x61, 0x43, 0x77, 0x7d, 0x41, 0x2e, 0x35, 0x4f, 0x3d, 0x31, 0x28, 0x58, 0x67, 0x1b, 0x03, 0x51, 0x20, 0x32, 0x1c, 0x08, 0x6e, 0x37, - 0x75, 0x37, 0x44, 0x4f, 0x68, 0x19, 0x07, 0x64, 0x14, 0x28, 0x25, 0x2b, 0x69, 0x35, 0x18, 0x27, 0x26, 0x14, 0x13, 0x70, 0x42, 0x19, - 0x12, 0x75, 0x3e, 0x02, 0x5d, 0x7c, 0x13, 0x1f, 0x16, 0x53, 0x3b, 0x74, 0x48, 0x3c, 0x5e, 0x39, 0x6c, 0x1c, 0x1c, 0x74, 0x39, 0x1f, - 0x00, 0x1b, 0x06, 0x0a, 0x68, 0x3b, 0x52, 0x4f, 0x1e, 0x6e, 0x3c, 0x35, 0x0c, 0x38, 0x0e, 0x0b, 0x3b, 0x1a, 0x76, 0x23, 0x29, 0x53, - 0x1e, 0x5f, 0x41, 0x0c, 0x4b, 0x0a, 0x65, 0x28, 0x78, 0x67, 0x48, 0x59, 0x26, 0x6d, 0x31, 0x76, 0x23, 0x70, 0x61, 0x64, 0x3b, 0x38, - 0x79, 0x66, 0x74, 0x53, 0x2c, 0x64, 0x64, 0x54, 0x03, 0x54, 0x65, 0x44, 0x4c, 0x18, 0x4f, 0x48, 0x20, 0x4f, 0x72, 0x10, 0x3f, 0x0c, - 0x52, 0x2d, 0x03, 0x14, 0x03, 0x51, 0x42, 0x10, 0x77, 0x6a, 0x34, 0x06, 0x32, 0x03, 0x72, 0x14, 0x7c, 0x08, 0x5d, 0x52, 0x1a, 0x62, - 0x7c, 0x3e, 0x30, 0x7e, 0x5f, 0x7f, 0x54, 0x0f, 0x44, 0x49, 0x5d, 0x5e, 0x10, 0x6a, 0x06, 0x2b, 0x06, 0x53, 0x10, 0x39, 0x37, 0x32, - 0x4a, 0x4e, 0x3d, 0x2b, 0x65, 0x38, 0x39, 0x07, 0x72, 0x54, 0x64, 0x4d, 0x56, 0x6a, 0x03, 0x22, 0x70, 0x7b, 0x5f, 0x60, 0x0b, 0x2a, - 0x0b, 0x6b, 0x10, 0x64, 0x14, 0x05, 0x22, 0x00, 0x73, 0x40, 0x23, 0x5b, 0x51, 0x1f, 0x2b, 0x1a, 0x5d, 0x69, 0x7a, 0x46, 0x0c, 0x5f, - 0x32, 0x4b, 0x4a, 0x28, 0x52, 0x79, 0x5b, 0x12, 0x42, 0x18, 0x00, 0x5d, 0x27, 0x31, 0x53, 0x3c, 0x4c, 0x36, 0x4e, 0x38, 0x3f, 0x72, - 0x03, 0x71, 0x02, 0x5b, 0x36, 0x59, 0x7f, 0x75, 0x6e, 0x08, 0x54, 0x0d, 0x34, 0x1c, 0x34, 0x57, 0x5d, 0x69, 0x48, 0x00, 0x3b, 0x05, - 0x07, 0x6e, 0x27, 0x65, 0x6e, 0x40, 0x3d, 0x3a, 0x4f, 0x72, 0x5d, 0x39, 0x16, 0x0f, 0x63, 0x12, 0x12, 0x15, 0x3a, 0x70, 0x0d, 0x57, - 0x18, 0x0d, 0x5e, 0x3d, 0x22, 0x68, 0x68, 0x7c, 0x6d, 0x4f, 0x0c, 0x7b, 0x09, 0x2d, 0x4a, 0x73, 0x20, 0x47, 0x07, 0x57, 0x75, 0x5d, - 0x53, 0x70, 0x34, 0x21, 0x40, 0x57, 0x51, 0x5e, 0x49, 0x44, 0x00, 0x54, 0x27, 0x04, 0x68, 0x7e, 0x59, 0x56, 0x58, 0x74, 0x14, 0x3c, - 0x16, 0x33, 0x41, 0x16, 0x4b, 0x2f, 0x49, 0x37, 0x0a, 0x54, 0x08, 0x08, 0x1f, 0x39, 0x67, 0x76, 0x28, 0x28, 0x07, 0x1d, 0x61, 0x47, - 0x51, 0x4d, 0x75, 0x26, 0x52, 0x47, 0x47, 0x0c, 0x57, 0x58, 0x74, 0x3e, 0x62, 0x6c, 0x58, 0x3a, 0x44, 0x1e, 0x16, 0x2e, 0x21, 0x1c, - 0x73, 0x45, 0x67, 0x74, 0x4f, 0x33, 0x66, 0x0e, 0x74, 0x66, 0x26, 0x1f, 0x2e, 0x38, 0x44, 0x40, 0x7e, 0x2a, 0x50, 0x52, 0x5e, 0x43, - 0x01, 0x7a, 0x38, 0x49, 0x3c, 0x55, 0x4d, 0x5a, 0x44, 0x08, 0x26, 0x59, 0x4d, 0x45, 0x0b, 0x48, 0x0a, 0x33, 0x5e, 0x4a, 0x4d, 0x75, - 0x16, 0x17, 0x63, 0x46, 0x01, 0x2a, 0x55, 0x7b, 0x0f, 0x02, 0x73, 0x6a, 0x4b, 0x7f, 0x75, 0x65, 0x3c, 0x4c, 0x33, 0x39, 0x6c, 0x74, - 0x05, 0x60, 0x0f, 0x7f, 0x2d, 0x41, 0x4d, 0x4d, 0x46, 0x71, 0x09, 0x6f, 0x4f, 0x60, 0x15, 0x0f, 0x46, 0x73, 0x63, 0x4c, 0x5e, 0x74, - 0x30, 0x0d, 0x28, 0x43, 0x08, 0x72, 0x32, 0x04, 0x2e, 0x31, 0x29, 0x27, 0x44, 0x6d, 0x13, 0x17, 0x48, 0x0f, 0x49, 0x52, 0x10, 0x13, - 0x7f, 0x17, 0x16, 0x62, 0x79, 0x35, 0x78, 0x3e, 0x01, 0x7c, 0x2e, 0x0f, 0x76, 0x3e, 0x5e, 0x53, 0x6c, 0x5b, 0x5f, 0x7c, 0x19, 0x41, - 0x02, 0x2f, 0x17, 0x64, 0x41, 0x75, 0x10, 0x04, 0x47, 0x7c, 0x3d, 0x4b, 0x52, 0x00, 0x10, 0x5d, 0x51, 0x4e, 0x7a, 0x27, 0x25, 0x55, - 0x40, 0x12, 0x35, 0x60, 0x05, 0x1b, 0x34, 0x2d, 0x04, 0x7a, 0x6a, 0x69, 0x02, 0x79, 0x03, 0x3a, 0x2f, 0x06, 0x0a, 0x79, 0x7b, 0x12, - 0x5d, 0x7c, 0x52, 0x29, 0x47, 0x58, 0x12, 0x73, 0x3f, 0x27, 0x56, 0x05, 0x0c, 0x48, 0x32, 0x58, 0x6b, 0x57, 0x5c, 0x03, 0x64, 0x56, - 0x11, 0x52, 0x7a, 0x30, 0x36, 0x29, 0x17, 0x3b, 0x68, 0x7a, 0x7c, 0x05, 0x6b, 0x6b, 0x13, 0x6a, 0x24, 0x5c, 0x68, 0x42, 0x18, 0x32, - 0x03, 0x73, 0x6e, 0x04, 0x21, 0x2e, 0x01, 0x04, 0x63, 0x7d, 0x44, 0x41, 0x12, 0x31, 0x0b, 0x15, 0x1f, 0x70, 0x00, 0x2e, 0x66, 0x14, - 0x3c, 0x7f, 0x2b, 0x00, 0x1f, 0x0c, 0x28, 0x59, 0x0a, 0x16, 0x49, 0x5a, 0x5c, 0x64, 0x65, 0x4b, 0x11, 0x29, 0x15, 0x36, 0x5a, 0x65, - 0x19, 0x4f, 0x60, 0x23, 0x3a, 0x3a, 0x13, 0x25, 0x02, 0x78, 0x4c, 0x54}; + 0x0b, 0x30, 0x44, 0x62, 0x7c, 0x22, 0x1f, 0x0d, 0x05, 0x67, 0x2c, 0x2a, 0x39, 0x21, 0x46, + 0x08, 0x50, 0x66, 0x34, 0x37, 0x0b, 0x45, 0x4b, 0x38, 0x32, 0x06, 0x7a, 0x3e, 0x7f, 0x0c, + 0x40, 0x18, 0x6b, 0x2d, 0x60, 0x4c, 0x60, 0x0c, 0x23, 0x43, 0x3b, 0x3e, 0x1b, 0x16, 0x04, + 0x46, 0x58, 0x3f, 0x40, 0x6a, 0x11, 0x05, 0x63, 0x71, 0x14, 0x35, 0x47, 0x79, 0x13, 0x6f, + 0x6b, 0x27, 0x18, 0x5b, 0x48, 0x27, 0x3e, 0x6f, 0x15, 0x33, 0x4f, 0x3e, 0x5e, 0x51, 0x73, + 0x68, 0x25, 0x0f, 0x06, 0x5b, 0x7c, 0x72, 0x75, 0x3e, 0x3f, 0x1b, 0x5c, 0x6d, 0x6a, 0x39, + 0x7c, 0x63, 0x63, 0x60, 0x6c, 0x7a, 0x33, 0x76, 0x52, 0x13, 0x25, 0x33, 0x7d, 0x65, 0x23, + 0x27, 0x11, 0x06, 0x06, 0x47, 0x71, 0x1e, 0x14, 0x74, 0x63, 0x70, 0x2d, 0x15, 0x27, 0x18, + 0x51, 0x06, 0x05, 0x33, 0x11, 0x2c, 0x6b, 0x00, 0x2d, 0x77, 0x20, 0x48, 0x0d, 0x73, 0x51, + 0x45, 0x25, 0x7f, 0x7f, 0x35, 0x26, 0x2e, 0x26, 0x53, 0x24, 0x68, 0x1e, 0x0e, 0x58, 0x3a, + 0x59, 0x50, 0x56, 0x37, 0x5f, 0x66, 0x01, 0x4c, 0x5a, 0x64, 0x32, 0x50, 0x7b, 0x6a, 0x20, + 0x72, 0x2b, 0x1d, 0x7e, 0x43, 0x7b, 0x61, 0x42, 0x0b, 0x61, 0x73, 0x24, 0x79, 0x3a, 0x6b, + 0x4a, 0x79, 0x6e, 0x09, 0x0f, 0x27, 0x2d, 0x0c, 0x5e, 0x32, 0x4b, 0x0d, 0x79, 0x46, 0x39, + 0x21, 0x0a, 0x26, 0x5f, 0x3a, 0x00, 0x26, 0x3f, 0x13, 0x2e, 0x7e, 0x50, 0x2b, 0x67, 0x46, + 0x72, 0x3f, 0x3b, 0x01, 0x46, 0x1b, 0x0b, 0x35, 0x49, 0x39, 0x19, 0x70, 0x3d, 0x02, 0x41, + 0x0e, 0x38, 0x05, 0x76, 0x65, 0x4f, 0x31, 0x6c, 0x5e, 0x17, 0x04, 0x15, 0x36, 0x26, 0x64, + 0x34, 0x14, 0x17, 0x7c, 0x0e, 0x0b, 0x5b, 0x55, 0x53, 0x6b, 0x00, 0x42, 0x41, 0x4f, 0x02, + 0x5c, 0x13, 0x0a, 0x2c, 0x2c, 0x3e, 0x10, 0x14, 0x33, 0x45, 0x7c, 0x7a, 0x5a, 0x31, 0x61, + 0x39, 0x08, 0x22, 0x6a, 0x1e, 0x0f, 0x6f, 0x1b, 0x6c, 0x13, 0x5e, 0x79, 0x20, 0x79, 0x50, + 0x62, 0x06, 0x2c, 0x76, 0x17, 0x04, 0x2b, 0x2a, 0x75, 0x1f, 0x0c, 0x37, 0x4e, 0x0f, 0x7b, + 0x2d, 0x34, 0x75, 0x60, 0x31, 0x74, 0x2e, 0x0a, 0x4a, 0x11, 0x6c, 0x49, 0x25, 0x01, 0x3a, + 0x3d, 0x22, 0x1e, 0x6d, 0x18, 0x51, 0x78, 0x2d, 0x62, 0x31, 0x4c, 0x50, 0x40, 0x17, 0x4b, + 0x6f, 0x22, 0x00, 0x7f, 0x61, 0x2a, 0x34, 0x3e, 0x00, 0x5f, 0x2f, 0x5f, 0x2f, 0x14, 0x2a, + 0x55, 0x27, 0x1f, 0x46, 0x1f, 0x12, 0x46, 0x5e, 0x1e, 0x0c, 0x7c, 0x38, 0x01, 0x61, 0x64, + 0x76, 0x22, 0x6e, 0x08, 0x20, 0x38, 0x4f, 0x73, 0x72, 0x55, 0x12, 0x42, 0x19, 0x50, 0x61, + 0x43, 0x77, 0x7d, 0x41, 0x2e, 0x35, 0x4f, 0x3d, 0x31, 0x28, 0x58, 0x67, 0x1b, 0x03, 0x51, + 0x20, 0x32, 0x1c, 0x08, 0x6e, 0x37, 0x75, 0x37, 0x44, 0x4f, 0x68, 0x19, 0x07, 0x64, 0x14, + 0x28, 0x25, 0x2b, 0x69, 0x35, 0x18, 0x27, 0x26, 0x14, 0x13, 0x70, 0x42, 0x19, 0x12, 0x75, + 0x3e, 0x02, 0x5d, 0x7c, 0x13, 0x1f, 0x16, 0x53, 0x3b, 0x74, 0x48, 0x3c, 0x5e, 0x39, 0x6c, + 0x1c, 0x1c, 0x74, 0x39, 0x1f, 0x00, 0x1b, 0x06, 0x0a, 0x68, 0x3b, 0x52, 0x4f, 0x1e, 0x6e, + 0x3c, 0x35, 0x0c, 0x38, 0x0e, 0x0b, 0x3b, 0x1a, 0x76, 0x23, 0x29, 0x53, 0x1e, 0x5f, 0x41, + 0x0c, 0x4b, 0x0a, 0x65, 0x28, 0x78, 0x67, 0x48, 0x59, 0x26, 0x6d, 0x31, 0x76, 0x23, 0x70, + 0x61, 0x64, 0x3b, 0x38, 0x79, 0x66, 0x74, 0x53, 0x2c, 0x64, 0x64, 0x54, 0x03, 0x54, 0x65, + 0x44, 0x4c, 0x18, 0x4f, 0x48, 0x20, 0x4f, 0x72, 0x10, 0x3f, 0x0c, 0x52, 0x2d, 0x03, 0x14, + 0x03, 0x51, 0x42, 0x10, 0x77, 0x6a, 0x34, 0x06, 0x32, 0x03, 0x72, 0x14, 0x7c, 0x08, 0x5d, + 0x52, 0x1a, 0x62, 0x7c, 0x3e, 0x30, 0x7e, 0x5f, 0x7f, 0x54, 0x0f, 0x44, 0x49, 0x5d, 0x5e, + 0x10, 0x6a, 0x06, 0x2b, 0x06, 0x53, 0x10, 0x39, 0x37, 0x32, 0x4a, 0x4e, 0x3d, 0x2b, 0x65, + 0x38, 0x39, 0x07, 0x72, 0x54, 0x64, 0x4d, 0x56, 0x6a, 0x03, 0x22, 0x70, 0x7b, 0x5f, 0x60, + 0x0b, 0x2a, 0x0b, 0x6b, 0x10, 0x64, 0x14, 0x05, 0x22, 0x00, 0x73, 0x40, 0x23, 0x5b, 0x51, + 0x1f, 0x2b, 0x1a, 0x5d, 0x69, 0x7a, 0x46, 0x0c, 0x5f, 0x32, 0x4b, 0x4a, 0x28, 0x52, 0x79, + 0x5b, 0x12, 0x42, 0x18, 0x00, 0x5d, 0x27, 0x31, 0x53, 0x3c, 0x4c, 0x36, 0x4e, 0x38, 0x3f, + 0x72, 0x03, 0x71, 0x02, 0x5b, 0x36, 0x59, 0x7f, 0x75, 0x6e, 0x08, 0x54, 0x0d, 0x34, 0x1c, + 0x34, 0x57, 0x5d, 0x69, 0x48, 0x00, 0x3b, 0x05, 0x07, 0x6e, 0x27, 0x65, 0x6e, 0x40, 0x3d, + 0x3a, 0x4f, 0x72, 0x5d, 0x39, 0x16, 0x0f, 0x63, 0x12, 0x12, 0x15, 0x3a, 0x70, 0x0d, 0x57, + 0x18, 0x0d, 0x5e, 0x3d, 0x22, 0x68, 0x68, 0x7c, 0x6d, 0x4f, 0x0c, 0x7b, 0x09, 0x2d, 0x4a, + 0x73, 0x20, 0x47, 0x07, 0x57, 0x75, 0x5d, 0x53, 0x70, 0x34, 0x21, 0x40, 0x57, 0x51, 0x5e, + 0x49, 0x44, 0x00, 0x54, 0x27, 0x04, 0x68, 0x7e, 0x59, 0x56, 0x58, 0x74, 0x14, 0x3c, 0x16, + 0x33, 0x41, 0x16, 0x4b, 0x2f, 0x49, 0x37, 0x0a, 0x54, 0x08, 0x08, 0x1f, 0x39, 0x67, 0x76, + 0x28, 0x28, 0x07, 0x1d, 0x61, 0x47, 0x51, 0x4d, 0x75, 0x26, 0x52, 0x47, 0x47, 0x0c, 0x57, + 0x58, 0x74, 0x3e, 0x62, 0x6c, 0x58, 0x3a, 0x44, 0x1e, 0x16, 0x2e, 0x21, 0x1c, 0x73, 0x45, + 0x67, 0x74, 0x4f, 0x33, 0x66, 0x0e, 0x74, 0x66, 0x26, 0x1f, 0x2e, 0x38, 0x44, 0x40, 0x7e, + 0x2a, 0x50, 0x52, 0x5e, 0x43, 0x01, 0x7a, 0x38, 0x49, 0x3c, 0x55, 0x4d, 0x5a, 0x44, 0x08, + 0x26, 0x59, 0x4d, 0x45, 0x0b, 0x48, 0x0a, 0x33, 0x5e, 0x4a, 0x4d, 0x75, 0x16, 0x17, 0x63, + 0x46, 0x01, 0x2a, 0x55, 0x7b, 0x0f, 0x02, 0x73, 0x6a, 0x4b, 0x7f, 0x75, 0x65, 0x3c, 0x4c, + 0x33, 0x39, 0x6c, 0x74, 0x05, 0x60, 0x0f, 0x7f, 0x2d, 0x41, 0x4d, 0x4d, 0x46, 0x71, 0x09, + 0x6f, 0x4f, 0x60, 0x15, 0x0f, 0x46, 0x73, 0x63, 0x4c, 0x5e, 0x74, 0x30, 0x0d, 0x28, 0x43, + 0x08, 0x72, 0x32, 0x04, 0x2e, 0x31, 0x29, 0x27, 0x44, 0x6d, 0x13, 0x17, 0x48, 0x0f, 0x49, + 0x52, 0x10, 0x13, 0x7f, 0x17, 0x16, 0x62, 0x79, 0x35, 0x78, 0x3e, 0x01, 0x7c, 0x2e, 0x0f, + 0x76, 0x3e, 0x5e, 0x53, 0x6c, 0x5b, 0x5f, 0x7c, 0x19, 0x41, 0x02, 0x2f, 0x17, 0x64, 0x41, + 0x75, 0x10, 0x04, 0x47, 0x7c, 0x3d, 0x4b, 0x52, 0x00, 0x10, 0x5d, 0x51, 0x4e, 0x7a, 0x27, + 0x25, 0x55, 0x40, 0x12, 0x35, 0x60, 0x05, 0x1b, 0x34, 0x2d, 0x04, 0x7a, 0x6a, 0x69, 0x02, + 0x79, 0x03, 0x3a, 0x2f, 0x06, 0x0a, 0x79, 0x7b, 0x12, 0x5d, 0x7c, 0x52, 0x29, 0x47, 0x58, + 0x12, 0x73, 0x3f, 0x27, 0x56, 0x05, 0x0c, 0x48, 0x32, 0x58, 0x6b, 0x57, 0x5c, 0x03, 0x64, + 0x56, 0x11, 0x52, 0x7a, 0x30, 0x36, 0x29, 0x17, 0x3b, 0x68, 0x7a, 0x7c, 0x05, 0x6b, 0x6b, + 0x13, 0x6a, 0x24, 0x5c, 0x68, 0x42, 0x18, 0x32, 0x03, 0x73, 0x6e, 0x04, 0x21, 0x2e, 0x01, + 0x04, 0x63, 0x7d, 0x44, 0x41, 0x12, 0x31, 0x0b, 0x15, 0x1f, 0x70, 0x00, 0x2e, 0x66, 0x14, + 0x3c, 0x7f, 0x2b, 0x00, 0x1f, 0x0c, 0x28, 0x59, 0x0a, 0x16, 0x49, 0x5a, 0x5c, 0x64, 0x65, + 0x4b, 0x11, 0x29, 0x15, 0x36, 0x5a, 0x65, 0x19, 0x4f, 0x60, 0x23, 0x3a, 0x3a, 0x13, 0x25, + 0x02, 0x78, 0x4c, 0x54}; char b64_known[1369] = { - 0x43, 0x7a, 0x42, 0x45, 0x59, 0x6e, 0x77, 0x69, 0x48, 0x77, 0x30, 0x46, 0x5a, 0x79, 0x77, 0x71, 0x4f, 0x53, 0x46, 0x47, 0x43, 0x46, - 0x42, 0x6d, 0x4e, 0x44, 0x63, 0x4c, 0x52, 0x55, 0x73, 0x34, 0x4d, 0x67, 0x5a, 0x36, 0x50, 0x6e, 0x38, 0x4d, 0x51, 0x42, 0x68, 0x72, - 0x4c, 0x57, 0x42, 0x4d, 0x59, 0x41, 0x77, 0x6a, 0x51, 0x7a, 0x73, 0x2b, 0x47, 0x78, 0x59, 0x45, 0x52, 0x6c, 0x67, 0x2f, 0x51, 0x47, - 0x6f, 0x52, 0x42, 0x57, 0x4e, 0x78, 0x46, 0x44, 0x56, 0x48, 0x65, 0x52, 0x4e, 0x76, 0x61, 0x79, 0x63, 0x59, 0x57, 0x30, 0x67, 0x6e, - 0x50, 0x6d, 0x38, 0x56, 0x4d, 0x30, 0x38, 0x2b, 0x58, 0x6c, 0x46, 0x7a, 0x61, 0x43, 0x55, 0x50, 0x42, 0x6c, 0x74, 0x38, 0x63, 0x6e, - 0x55, 0x2b, 0x50, 0x78, 0x74, 0x63, 0x62, 0x57, 0x6f, 0x35, 0x66, 0x47, 0x4e, 0x6a, 0x59, 0x47, 0x78, 0x36, 0x4d, 0x33, 0x5a, 0x53, - 0x45, 0x79, 0x55, 0x7a, 0x66, 0x57, 0x55, 0x6a, 0x4a, 0x78, 0x45, 0x47, 0x42, 0x6b, 0x64, 0x78, 0x48, 0x68, 0x52, 0x30, 0x59, 0x33, - 0x41, 0x74, 0x46, 0x53, 0x63, 0x59, 0x55, 0x51, 0x59, 0x46, 0x4d, 0x78, 0x45, 0x73, 0x61, 0x77, 0x41, 0x74, 0x64, 0x79, 0x42, 0x49, - 0x44, 0x58, 0x4e, 0x52, 0x52, 0x53, 0x56, 0x2f, 0x66, 0x7a, 0x55, 0x6d, 0x4c, 0x69, 0x5a, 0x54, 0x4a, 0x47, 0x67, 0x65, 0x44, 0x6c, - 0x67, 0x36, 0x57, 0x56, 0x42, 0x57, 0x4e, 0x31, 0x39, 0x6d, 0x41, 0x55, 0x78, 0x61, 0x5a, 0x44, 0x4a, 0x51, 0x65, 0x32, 0x6f, 0x67, - 0x63, 0x69, 0x73, 0x64, 0x66, 0x6b, 0x4e, 0x37, 0x59, 0x55, 0x49, 0x4c, 0x59, 0x58, 0x4d, 0x6b, 0x65, 0x54, 0x70, 0x72, 0x53, 0x6e, - 0x6c, 0x75, 0x43, 0x51, 0x38, 0x6e, 0x4c, 0x51, 0x78, 0x65, 0x4d, 0x6b, 0x73, 0x4e, 0x65, 0x55, 0x59, 0x35, 0x49, 0x51, 0x6f, 0x6d, - 0x58, 0x7a, 0x6f, 0x41, 0x4a, 0x6a, 0x38, 0x54, 0x4c, 0x6e, 0x35, 0x51, 0x4b, 0x32, 0x64, 0x47, 0x63, 0x6a, 0x38, 0x37, 0x41, 0x55, - 0x59, 0x62, 0x43, 0x7a, 0x56, 0x4a, 0x4f, 0x52, 0x6c, 0x77, 0x50, 0x51, 0x4a, 0x42, 0x44, 0x6a, 0x67, 0x46, 0x64, 0x6d, 0x56, 0x50, - 0x4d, 0x57, 0x78, 0x65, 0x46, 0x77, 0x51, 0x56, 0x4e, 0x69, 0x5a, 0x6b, 0x4e, 0x42, 0x51, 0x58, 0x66, 0x41, 0x34, 0x4c, 0x57, 0x31, - 0x56, 0x54, 0x61, 0x77, 0x42, 0x43, 0x51, 0x55, 0x38, 0x43, 0x58, 0x42, 0x4d, 0x4b, 0x4c, 0x43, 0x77, 0x2b, 0x45, 0x42, 0x51, 0x7a, - 0x52, 0x58, 0x78, 0x36, 0x57, 0x6a, 0x46, 0x68, 0x4f, 0x51, 0x67, 0x69, 0x61, 0x68, 0x34, 0x50, 0x62, 0x78, 0x74, 0x73, 0x45, 0x31, - 0x35, 0x35, 0x49, 0x48, 0x6c, 0x51, 0x59, 0x67, 0x59, 0x73, 0x64, 0x68, 0x63, 0x45, 0x4b, 0x79, 0x70, 0x31, 0x48, 0x77, 0x77, 0x33, - 0x54, 0x67, 0x39, 0x37, 0x4c, 0x54, 0x52, 0x31, 0x59, 0x44, 0x46, 0x30, 0x4c, 0x67, 0x70, 0x4b, 0x45, 0x57, 0x78, 0x4a, 0x4a, 0x51, - 0x45, 0x36, 0x50, 0x53, 0x49, 0x65, 0x62, 0x52, 0x68, 0x52, 0x65, 0x43, 0x31, 0x69, 0x4d, 0x55, 0x78, 0x51, 0x51, 0x42, 0x64, 0x4c, - 0x62, 0x79, 0x49, 0x41, 0x66, 0x32, 0x45, 0x71, 0x4e, 0x44, 0x34, 0x41, 0x58, 0x79, 0x39, 0x66, 0x4c, 0x78, 0x51, 0x71, 0x56, 0x53, - 0x63, 0x66, 0x52, 0x68, 0x38, 0x53, 0x52, 0x6c, 0x34, 0x65, 0x44, 0x48, 0x77, 0x34, 0x41, 0x57, 0x46, 0x6b, 0x64, 0x69, 0x4a, 0x75, - 0x43, 0x43, 0x41, 0x34, 0x54, 0x33, 0x4e, 0x79, 0x56, 0x52, 0x4a, 0x43, 0x47, 0x56, 0x42, 0x68, 0x51, 0x33, 0x64, 0x39, 0x51, 0x53, - 0x34, 0x31, 0x54, 0x7a, 0x30, 0x78, 0x4b, 0x46, 0x68, 0x6e, 0x47, 0x77, 0x4e, 0x52, 0x49, 0x44, 0x49, 0x63, 0x43, 0x47, 0x34, 0x33, - 0x64, 0x54, 0x64, 0x45, 0x54, 0x32, 0x67, 0x5a, 0x42, 0x32, 0x51, 0x55, 0x4b, 0x43, 0x55, 0x72, 0x61, 0x54, 0x55, 0x59, 0x4a, 0x79, - 0x59, 0x55, 0x45, 0x33, 0x42, 0x43, 0x47, 0x52, 0x4a, 0x31, 0x50, 0x67, 0x4a, 0x64, 0x66, 0x42, 0x4d, 0x66, 0x46, 0x6c, 0x4d, 0x37, - 0x64, 0x45, 0x67, 0x38, 0x58, 0x6a, 0x6c, 0x73, 0x48, 0x42, 0x78, 0x30, 0x4f, 0x52, 0x38, 0x41, 0x47, 0x77, 0x59, 0x4b, 0x61, 0x44, - 0x74, 0x53, 0x54, 0x78, 0x35, 0x75, 0x50, 0x44, 0x55, 0x4d, 0x4f, 0x41, 0x34, 0x4c, 0x4f, 0x78, 0x70, 0x32, 0x49, 0x79, 0x6c, 0x54, - 0x48, 0x6c, 0x39, 0x42, 0x44, 0x45, 0x73, 0x4b, 0x5a, 0x53, 0x68, 0x34, 0x5a, 0x30, 0x68, 0x5a, 0x4a, 0x6d, 0x30, 0x78, 0x64, 0x69, - 0x4e, 0x77, 0x59, 0x57, 0x51, 0x37, 0x4f, 0x48, 0x6c, 0x6d, 0x64, 0x46, 0x4d, 0x73, 0x5a, 0x47, 0x52, 0x55, 0x41, 0x31, 0x52, 0x6c, - 0x52, 0x45, 0x77, 0x59, 0x54, 0x30, 0x67, 0x67, 0x54, 0x33, 0x49, 0x51, 0x50, 0x77, 0x78, 0x53, 0x4c, 0x51, 0x4d, 0x55, 0x41, 0x31, - 0x46, 0x43, 0x45, 0x48, 0x64, 0x71, 0x4e, 0x41, 0x59, 0x79, 0x41, 0x33, 0x49, 0x55, 0x66, 0x41, 0x68, 0x64, 0x55, 0x68, 0x70, 0x69, - 0x66, 0x44, 0x34, 0x77, 0x66, 0x6c, 0x39, 0x2f, 0x56, 0x41, 0x39, 0x45, 0x53, 0x56, 0x31, 0x65, 0x45, 0x47, 0x6f, 0x47, 0x4b, 0x77, - 0x5a, 0x54, 0x45, 0x44, 0x6b, 0x33, 0x4d, 0x6b, 0x70, 0x4f, 0x50, 0x53, 0x74, 0x6c, 0x4f, 0x44, 0x6b, 0x48, 0x63, 0x6c, 0x52, 0x6b, - 0x54, 0x56, 0x5a, 0x71, 0x41, 0x79, 0x4a, 0x77, 0x65, 0x31, 0x39, 0x67, 0x43, 0x79, 0x6f, 0x4c, 0x61, 0x78, 0x42, 0x6b, 0x46, 0x41, - 0x55, 0x69, 0x41, 0x48, 0x4e, 0x41, 0x49, 0x31, 0x74, 0x52, 0x48, 0x79, 0x73, 0x61, 0x58, 0x57, 0x6c, 0x36, 0x52, 0x67, 0x78, 0x66, - 0x4d, 0x6b, 0x74, 0x4b, 0x4b, 0x46, 0x4a, 0x35, 0x57, 0x78, 0x4a, 0x43, 0x47, 0x41, 0x42, 0x64, 0x4a, 0x7a, 0x46, 0x54, 0x50, 0x45, - 0x77, 0x32, 0x54, 0x6a, 0x67, 0x2f, 0x63, 0x67, 0x4e, 0x78, 0x41, 0x6c, 0x73, 0x32, 0x57, 0x58, 0x39, 0x31, 0x62, 0x67, 0x68, 0x55, - 0x44, 0x54, 0x51, 0x63, 0x4e, 0x46, 0x64, 0x64, 0x61, 0x55, 0x67, 0x41, 0x4f, 0x77, 0x55, 0x48, 0x62, 0x69, 0x64, 0x6c, 0x62, 0x6b, - 0x41, 0x39, 0x4f, 0x6b, 0x39, 0x79, 0x58, 0x54, 0x6b, 0x57, 0x44, 0x32, 0x4d, 0x53, 0x45, 0x68, 0x55, 0x36, 0x63, 0x41, 0x31, 0x58, - 0x47, 0x41, 0x31, 0x65, 0x50, 0x53, 0x4a, 0x6f, 0x61, 0x48, 0x78, 0x74, 0x54, 0x77, 0x78, 0x37, 0x43, 0x53, 0x31, 0x4b, 0x63, 0x79, - 0x42, 0x48, 0x42, 0x31, 0x64, 0x31, 0x58, 0x56, 0x4e, 0x77, 0x4e, 0x43, 0x46, 0x41, 0x56, 0x31, 0x46, 0x65, 0x53, 0x55, 0x51, 0x41, - 0x56, 0x43, 0x63, 0x45, 0x61, 0x48, 0x35, 0x5a, 0x56, 0x6c, 0x68, 0x30, 0x46, 0x44, 0x77, 0x57, 0x4d, 0x30, 0x45, 0x57, 0x53, 0x79, - 0x39, 0x4a, 0x4e, 0x77, 0x70, 0x55, 0x43, 0x41, 0x67, 0x66, 0x4f, 0x57, 0x64, 0x32, 0x4b, 0x43, 0x67, 0x48, 0x48, 0x57, 0x46, 0x48, - 0x55, 0x55, 0x31, 0x31, 0x4a, 0x6c, 0x4a, 0x48, 0x52, 0x77, 0x78, 0x58, 0x57, 0x48, 0x51, 0x2b, 0x59, 0x6d, 0x78, 0x59, 0x4f, 0x6b, - 0x51, 0x65, 0x46, 0x69, 0x34, 0x68, 0x48, 0x48, 0x4e, 0x46, 0x5a, 0x33, 0x52, 0x50, 0x4d, 0x32, 0x59, 0x4f, 0x64, 0x47, 0x59, 0x6d, - 0x48, 0x79, 0x34, 0x34, 0x52, 0x45, 0x42, 0x2b, 0x4b, 0x6c, 0x42, 0x53, 0x58, 0x6b, 0x4d, 0x42, 0x65, 0x6a, 0x68, 0x4a, 0x50, 0x46, - 0x56, 0x4e, 0x57, 0x6b, 0x51, 0x49, 0x4a, 0x6c, 0x6c, 0x4e, 0x52, 0x51, 0x74, 0x49, 0x43, 0x6a, 0x4e, 0x65, 0x53, 0x6b, 0x31, 0x31, - 0x46, 0x68, 0x64, 0x6a, 0x52, 0x67, 0x45, 0x71, 0x56, 0x58, 0x73, 0x50, 0x41, 0x6e, 0x4e, 0x71, 0x53, 0x33, 0x39, 0x31, 0x5a, 0x54, - 0x78, 0x4d, 0x4d, 0x7a, 0x6c, 0x73, 0x64, 0x41, 0x56, 0x67, 0x44, 0x33, 0x38, 0x74, 0x51, 0x55, 0x31, 0x4e, 0x52, 0x6e, 0x45, 0x4a, - 0x62, 0x30, 0x39, 0x67, 0x46, 0x51, 0x39, 0x47, 0x63, 0x32, 0x4e, 0x4d, 0x58, 0x6e, 0x51, 0x77, 0x44, 0x53, 0x68, 0x44, 0x43, 0x48, - 0x49, 0x79, 0x42, 0x43, 0x34, 0x78, 0x4b, 0x53, 0x64, 0x45, 0x62, 0x52, 0x4d, 0x58, 0x53, 0x41, 0x39, 0x4a, 0x55, 0x68, 0x41, 0x54, - 0x66, 0x78, 0x63, 0x57, 0x59, 0x6e, 0x6b, 0x31, 0x65, 0x44, 0x34, 0x42, 0x66, 0x43, 0x34, 0x50, 0x64, 0x6a, 0x35, 0x65, 0x55, 0x32, - 0x78, 0x62, 0x58, 0x33, 0x77, 0x5a, 0x51, 0x51, 0x49, 0x76, 0x46, 0x32, 0x52, 0x42, 0x64, 0x52, 0x41, 0x45, 0x52, 0x33, 0x77, 0x39, - 0x53, 0x31, 0x49, 0x41, 0x45, 0x46, 0x31, 0x52, 0x54, 0x6e, 0x6f, 0x6e, 0x4a, 0x56, 0x56, 0x41, 0x45, 0x6a, 0x56, 0x67, 0x42, 0x52, - 0x73, 0x30, 0x4c, 0x51, 0x52, 0x36, 0x61, 0x6d, 0x6b, 0x43, 0x65, 0x51, 0x4d, 0x36, 0x4c, 0x77, 0x59, 0x4b, 0x65, 0x58, 0x73, 0x53, - 0x58, 0x58, 0x78, 0x53, 0x4b, 0x55, 0x64, 0x59, 0x45, 0x6e, 0x4d, 0x2f, 0x4a, 0x31, 0x59, 0x46, 0x44, 0x45, 0x67, 0x79, 0x57, 0x47, - 0x74, 0x58, 0x58, 0x41, 0x4e, 0x6b, 0x56, 0x68, 0x46, 0x53, 0x65, 0x6a, 0x41, 0x32, 0x4b, 0x52, 0x63, 0x37, 0x61, 0x48, 0x70, 0x38, - 0x42, 0x57, 0x74, 0x72, 0x45, 0x32, 0x6f, 0x6b, 0x58, 0x47, 0x68, 0x43, 0x47, 0x44, 0x49, 0x44, 0x63, 0x32, 0x34, 0x45, 0x49, 0x53, - 0x34, 0x42, 0x42, 0x47, 0x4e, 0x39, 0x52, 0x45, 0x45, 0x53, 0x4d, 0x51, 0x73, 0x56, 0x48, 0x33, 0x41, 0x41, 0x4c, 0x6d, 0x59, 0x55, - 0x50, 0x48, 0x38, 0x72, 0x41, 0x42, 0x38, 0x4d, 0x4b, 0x46, 0x6b, 0x4b, 0x46, 0x6b, 0x6c, 0x61, 0x58, 0x47, 0x52, 0x6c, 0x53, 0x78, - 0x45, 0x70, 0x46, 0x54, 0x5a, 0x61, 0x5a, 0x52, 0x6c, 0x50, 0x59, 0x43, 0x4d, 0x36, 0x4f, 0x68, 0x4d, 0x6c, 0x41, 0x6e, 0x68, 0x4d, - 0x56, 0x41, 0x3d, 0x3d, 0x00}; + 0x43, 0x7a, 0x42, 0x45, 0x59, 0x6e, 0x77, 0x69, 0x48, 0x77, 0x30, 0x46, 0x5a, 0x79, 0x77, + 0x71, 0x4f, 0x53, 0x46, 0x47, 0x43, 0x46, 0x42, 0x6d, 0x4e, 0x44, 0x63, 0x4c, 0x52, 0x55, + 0x73, 0x34, 0x4d, 0x67, 0x5a, 0x36, 0x50, 0x6e, 0x38, 0x4d, 0x51, 0x42, 0x68, 0x72, 0x4c, + 0x57, 0x42, 0x4d, 0x59, 0x41, 0x77, 0x6a, 0x51, 0x7a, 0x73, 0x2b, 0x47, 0x78, 0x59, 0x45, + 0x52, 0x6c, 0x67, 0x2f, 0x51, 0x47, 0x6f, 0x52, 0x42, 0x57, 0x4e, 0x78, 0x46, 0x44, 0x56, + 0x48, 0x65, 0x52, 0x4e, 0x76, 0x61, 0x79, 0x63, 0x59, 0x57, 0x30, 0x67, 0x6e, 0x50, 0x6d, + 0x38, 0x56, 0x4d, 0x30, 0x38, 0x2b, 0x58, 0x6c, 0x46, 0x7a, 0x61, 0x43, 0x55, 0x50, 0x42, + 0x6c, 0x74, 0x38, 0x63, 0x6e, 0x55, 0x2b, 0x50, 0x78, 0x74, 0x63, 0x62, 0x57, 0x6f, 0x35, + 0x66, 0x47, 0x4e, 0x6a, 0x59, 0x47, 0x78, 0x36, 0x4d, 0x33, 0x5a, 0x53, 0x45, 0x79, 0x55, + 0x7a, 0x66, 0x57, 0x55, 0x6a, 0x4a, 0x78, 0x45, 0x47, 0x42, 0x6b, 0x64, 0x78, 0x48, 0x68, + 0x52, 0x30, 0x59, 0x33, 0x41, 0x74, 0x46, 0x53, 0x63, 0x59, 0x55, 0x51, 0x59, 0x46, 0x4d, + 0x78, 0x45, 0x73, 0x61, 0x77, 0x41, 0x74, 0x64, 0x79, 0x42, 0x49, 0x44, 0x58, 0x4e, 0x52, + 0x52, 0x53, 0x56, 0x2f, 0x66, 0x7a, 0x55, 0x6d, 0x4c, 0x69, 0x5a, 0x54, 0x4a, 0x47, 0x67, + 0x65, 0x44, 0x6c, 0x67, 0x36, 0x57, 0x56, 0x42, 0x57, 0x4e, 0x31, 0x39, 0x6d, 0x41, 0x55, + 0x78, 0x61, 0x5a, 0x44, 0x4a, 0x51, 0x65, 0x32, 0x6f, 0x67, 0x63, 0x69, 0x73, 0x64, 0x66, + 0x6b, 0x4e, 0x37, 0x59, 0x55, 0x49, 0x4c, 0x59, 0x58, 0x4d, 0x6b, 0x65, 0x54, 0x70, 0x72, + 0x53, 0x6e, 0x6c, 0x75, 0x43, 0x51, 0x38, 0x6e, 0x4c, 0x51, 0x78, 0x65, 0x4d, 0x6b, 0x73, + 0x4e, 0x65, 0x55, 0x59, 0x35, 0x49, 0x51, 0x6f, 0x6d, 0x58, 0x7a, 0x6f, 0x41, 0x4a, 0x6a, + 0x38, 0x54, 0x4c, 0x6e, 0x35, 0x51, 0x4b, 0x32, 0x64, 0x47, 0x63, 0x6a, 0x38, 0x37, 0x41, + 0x55, 0x59, 0x62, 0x43, 0x7a, 0x56, 0x4a, 0x4f, 0x52, 0x6c, 0x77, 0x50, 0x51, 0x4a, 0x42, + 0x44, 0x6a, 0x67, 0x46, 0x64, 0x6d, 0x56, 0x50, 0x4d, 0x57, 0x78, 0x65, 0x46, 0x77, 0x51, + 0x56, 0x4e, 0x69, 0x5a, 0x6b, 0x4e, 0x42, 0x51, 0x58, 0x66, 0x41, 0x34, 0x4c, 0x57, 0x31, + 0x56, 0x54, 0x61, 0x77, 0x42, 0x43, 0x51, 0x55, 0x38, 0x43, 0x58, 0x42, 0x4d, 0x4b, 0x4c, + 0x43, 0x77, 0x2b, 0x45, 0x42, 0x51, 0x7a, 0x52, 0x58, 0x78, 0x36, 0x57, 0x6a, 0x46, 0x68, + 0x4f, 0x51, 0x67, 0x69, 0x61, 0x68, 0x34, 0x50, 0x62, 0x78, 0x74, 0x73, 0x45, 0x31, 0x35, + 0x35, 0x49, 0x48, 0x6c, 0x51, 0x59, 0x67, 0x59, 0x73, 0x64, 0x68, 0x63, 0x45, 0x4b, 0x79, + 0x70, 0x31, 0x48, 0x77, 0x77, 0x33, 0x54, 0x67, 0x39, 0x37, 0x4c, 0x54, 0x52, 0x31, 0x59, + 0x44, 0x46, 0x30, 0x4c, 0x67, 0x70, 0x4b, 0x45, 0x57, 0x78, 0x4a, 0x4a, 0x51, 0x45, 0x36, + 0x50, 0x53, 0x49, 0x65, 0x62, 0x52, 0x68, 0x52, 0x65, 0x43, 0x31, 0x69, 0x4d, 0x55, 0x78, + 0x51, 0x51, 0x42, 0x64, 0x4c, 0x62, 0x79, 0x49, 0x41, 0x66, 0x32, 0x45, 0x71, 0x4e, 0x44, + 0x34, 0x41, 0x58, 0x79, 0x39, 0x66, 0x4c, 0x78, 0x51, 0x71, 0x56, 0x53, 0x63, 0x66, 0x52, + 0x68, 0x38, 0x53, 0x52, 0x6c, 0x34, 0x65, 0x44, 0x48, 0x77, 0x34, 0x41, 0x57, 0x46, 0x6b, + 0x64, 0x69, 0x4a, 0x75, 0x43, 0x43, 0x41, 0x34, 0x54, 0x33, 0x4e, 0x79, 0x56, 0x52, 0x4a, + 0x43, 0x47, 0x56, 0x42, 0x68, 0x51, 0x33, 0x64, 0x39, 0x51, 0x53, 0x34, 0x31, 0x54, 0x7a, + 0x30, 0x78, 0x4b, 0x46, 0x68, 0x6e, 0x47, 0x77, 0x4e, 0x52, 0x49, 0x44, 0x49, 0x63, 0x43, + 0x47, 0x34, 0x33, 0x64, 0x54, 0x64, 0x45, 0x54, 0x32, 0x67, 0x5a, 0x42, 0x32, 0x51, 0x55, + 0x4b, 0x43, 0x55, 0x72, 0x61, 0x54, 0x55, 0x59, 0x4a, 0x79, 0x59, 0x55, 0x45, 0x33, 0x42, + 0x43, 0x47, 0x52, 0x4a, 0x31, 0x50, 0x67, 0x4a, 0x64, 0x66, 0x42, 0x4d, 0x66, 0x46, 0x6c, + 0x4d, 0x37, 0x64, 0x45, 0x67, 0x38, 0x58, 0x6a, 0x6c, 0x73, 0x48, 0x42, 0x78, 0x30, 0x4f, + 0x52, 0x38, 0x41, 0x47, 0x77, 0x59, 0x4b, 0x61, 0x44, 0x74, 0x53, 0x54, 0x78, 0x35, 0x75, + 0x50, 0x44, 0x55, 0x4d, 0x4f, 0x41, 0x34, 0x4c, 0x4f, 0x78, 0x70, 0x32, 0x49, 0x79, 0x6c, + 0x54, 0x48, 0x6c, 0x39, 0x42, 0x44, 0x45, 0x73, 0x4b, 0x5a, 0x53, 0x68, 0x34, 0x5a, 0x30, + 0x68, 0x5a, 0x4a, 0x6d, 0x30, 0x78, 0x64, 0x69, 0x4e, 0x77, 0x59, 0x57, 0x51, 0x37, 0x4f, + 0x48, 0x6c, 0x6d, 0x64, 0x46, 0x4d, 0x73, 0x5a, 0x47, 0x52, 0x55, 0x41, 0x31, 0x52, 0x6c, + 0x52, 0x45, 0x77, 0x59, 0x54, 0x30, 0x67, 0x67, 0x54, 0x33, 0x49, 0x51, 0x50, 0x77, 0x78, + 0x53, 0x4c, 0x51, 0x4d, 0x55, 0x41, 0x31, 0x46, 0x43, 0x45, 0x48, 0x64, 0x71, 0x4e, 0x41, + 0x59, 0x79, 0x41, 0x33, 0x49, 0x55, 0x66, 0x41, 0x68, 0x64, 0x55, 0x68, 0x70, 0x69, 0x66, + 0x44, 0x34, 0x77, 0x66, 0x6c, 0x39, 0x2f, 0x56, 0x41, 0x39, 0x45, 0x53, 0x56, 0x31, 0x65, + 0x45, 0x47, 0x6f, 0x47, 0x4b, 0x77, 0x5a, 0x54, 0x45, 0x44, 0x6b, 0x33, 0x4d, 0x6b, 0x70, + 0x4f, 0x50, 0x53, 0x74, 0x6c, 0x4f, 0x44, 0x6b, 0x48, 0x63, 0x6c, 0x52, 0x6b, 0x54, 0x56, + 0x5a, 0x71, 0x41, 0x79, 0x4a, 0x77, 0x65, 0x31, 0x39, 0x67, 0x43, 0x79, 0x6f, 0x4c, 0x61, + 0x78, 0x42, 0x6b, 0x46, 0x41, 0x55, 0x69, 0x41, 0x48, 0x4e, 0x41, 0x49, 0x31, 0x74, 0x52, + 0x48, 0x79, 0x73, 0x61, 0x58, 0x57, 0x6c, 0x36, 0x52, 0x67, 0x78, 0x66, 0x4d, 0x6b, 0x74, + 0x4b, 0x4b, 0x46, 0x4a, 0x35, 0x57, 0x78, 0x4a, 0x43, 0x47, 0x41, 0x42, 0x64, 0x4a, 0x7a, + 0x46, 0x54, 0x50, 0x45, 0x77, 0x32, 0x54, 0x6a, 0x67, 0x2f, 0x63, 0x67, 0x4e, 0x78, 0x41, + 0x6c, 0x73, 0x32, 0x57, 0x58, 0x39, 0x31, 0x62, 0x67, 0x68, 0x55, 0x44, 0x54, 0x51, 0x63, + 0x4e, 0x46, 0x64, 0x64, 0x61, 0x55, 0x67, 0x41, 0x4f, 0x77, 0x55, 0x48, 0x62, 0x69, 0x64, + 0x6c, 0x62, 0x6b, 0x41, 0x39, 0x4f, 0x6b, 0x39, 0x79, 0x58, 0x54, 0x6b, 0x57, 0x44, 0x32, + 0x4d, 0x53, 0x45, 0x68, 0x55, 0x36, 0x63, 0x41, 0x31, 0x58, 0x47, 0x41, 0x31, 0x65, 0x50, + 0x53, 0x4a, 0x6f, 0x61, 0x48, 0x78, 0x74, 0x54, 0x77, 0x78, 0x37, 0x43, 0x53, 0x31, 0x4b, + 0x63, 0x79, 0x42, 0x48, 0x42, 0x31, 0x64, 0x31, 0x58, 0x56, 0x4e, 0x77, 0x4e, 0x43, 0x46, + 0x41, 0x56, 0x31, 0x46, 0x65, 0x53, 0x55, 0x51, 0x41, 0x56, 0x43, 0x63, 0x45, 0x61, 0x48, + 0x35, 0x5a, 0x56, 0x6c, 0x68, 0x30, 0x46, 0x44, 0x77, 0x57, 0x4d, 0x30, 0x45, 0x57, 0x53, + 0x79, 0x39, 0x4a, 0x4e, 0x77, 0x70, 0x55, 0x43, 0x41, 0x67, 0x66, 0x4f, 0x57, 0x64, 0x32, + 0x4b, 0x43, 0x67, 0x48, 0x48, 0x57, 0x46, 0x48, 0x55, 0x55, 0x31, 0x31, 0x4a, 0x6c, 0x4a, + 0x48, 0x52, 0x77, 0x78, 0x58, 0x57, 0x48, 0x51, 0x2b, 0x59, 0x6d, 0x78, 0x59, 0x4f, 0x6b, + 0x51, 0x65, 0x46, 0x69, 0x34, 0x68, 0x48, 0x48, 0x4e, 0x46, 0x5a, 0x33, 0x52, 0x50, 0x4d, + 0x32, 0x59, 0x4f, 0x64, 0x47, 0x59, 0x6d, 0x48, 0x79, 0x34, 0x34, 0x52, 0x45, 0x42, 0x2b, + 0x4b, 0x6c, 0x42, 0x53, 0x58, 0x6b, 0x4d, 0x42, 0x65, 0x6a, 0x68, 0x4a, 0x50, 0x46, 0x56, + 0x4e, 0x57, 0x6b, 0x51, 0x49, 0x4a, 0x6c, 0x6c, 0x4e, 0x52, 0x51, 0x74, 0x49, 0x43, 0x6a, + 0x4e, 0x65, 0x53, 0x6b, 0x31, 0x31, 0x46, 0x68, 0x64, 0x6a, 0x52, 0x67, 0x45, 0x71, 0x56, + 0x58, 0x73, 0x50, 0x41, 0x6e, 0x4e, 0x71, 0x53, 0x33, 0x39, 0x31, 0x5a, 0x54, 0x78, 0x4d, + 0x4d, 0x7a, 0x6c, 0x73, 0x64, 0x41, 0x56, 0x67, 0x44, 0x33, 0x38, 0x74, 0x51, 0x55, 0x31, + 0x4e, 0x52, 0x6e, 0x45, 0x4a, 0x62, 0x30, 0x39, 0x67, 0x46, 0x51, 0x39, 0x47, 0x63, 0x32, + 0x4e, 0x4d, 0x58, 0x6e, 0x51, 0x77, 0x44, 0x53, 0x68, 0x44, 0x43, 0x48, 0x49, 0x79, 0x42, + 0x43, 0x34, 0x78, 0x4b, 0x53, 0x64, 0x45, 0x62, 0x52, 0x4d, 0x58, 0x53, 0x41, 0x39, 0x4a, + 0x55, 0x68, 0x41, 0x54, 0x66, 0x78, 0x63, 0x57, 0x59, 0x6e, 0x6b, 0x31, 0x65, 0x44, 0x34, + 0x42, 0x66, 0x43, 0x34, 0x50, 0x64, 0x6a, 0x35, 0x65, 0x55, 0x32, 0x78, 0x62, 0x58, 0x33, + 0x77, 0x5a, 0x51, 0x51, 0x49, 0x76, 0x46, 0x32, 0x52, 0x42, 0x64, 0x52, 0x41, 0x45, 0x52, + 0x33, 0x77, 0x39, 0x53, 0x31, 0x49, 0x41, 0x45, 0x46, 0x31, 0x52, 0x54, 0x6e, 0x6f, 0x6e, + 0x4a, 0x56, 0x56, 0x41, 0x45, 0x6a, 0x56, 0x67, 0x42, 0x52, 0x73, 0x30, 0x4c, 0x51, 0x52, + 0x36, 0x61, 0x6d, 0x6b, 0x43, 0x65, 0x51, 0x4d, 0x36, 0x4c, 0x77, 0x59, 0x4b, 0x65, 0x58, + 0x73, 0x53, 0x58, 0x58, 0x78, 0x53, 0x4b, 0x55, 0x64, 0x59, 0x45, 0x6e, 0x4d, 0x2f, 0x4a, + 0x31, 0x59, 0x46, 0x44, 0x45, 0x67, 0x79, 0x57, 0x47, 0x74, 0x58, 0x58, 0x41, 0x4e, 0x6b, + 0x56, 0x68, 0x46, 0x53, 0x65, 0x6a, 0x41, 0x32, 0x4b, 0x52, 0x63, 0x37, 0x61, 0x48, 0x70, + 0x38, 0x42, 0x57, 0x74, 0x72, 0x45, 0x32, 0x6f, 0x6b, 0x58, 0x47, 0x68, 0x43, 0x47, 0x44, + 0x49, 0x44, 0x63, 0x32, 0x34, 0x45, 0x49, 0x53, 0x34, 0x42, 0x42, 0x47, 0x4e, 0x39, 0x52, + 0x45, 0x45, 0x53, 0x4d, 0x51, 0x73, 0x56, 0x48, 0x33, 0x41, 0x41, 0x4c, 0x6d, 0x59, 0x55, + 0x50, 0x48, 0x38, 0x72, 0x41, 0x42, 0x38, 0x4d, 0x4b, 0x46, 0x6b, 0x4b, 0x46, 0x6b, 0x6c, + 0x61, 0x58, 0x47, 0x52, 0x6c, 0x53, 0x78, 0x45, 0x70, 0x46, 0x54, 0x5a, 0x61, 0x5a, 0x52, + 0x6c, 0x50, 0x59, 0x43, 0x4d, 0x36, 0x4f, 0x68, 0x4d, 0x6c, 0x41, 0x6e, 0x68, 0x4d, 0x56, + 0x41, 0x3d, 0x3d, 0x00}; char *b64_test; plan_tests(1); diff --git a/lib/tests/test_cmd.c b/lib/tests/test_cmd.c index c8867dfb..ade0da90 100644 --- a/lib/tests/test_cmd.c +++ b/lib/tests/test_cmd.c @@ -67,7 +67,8 @@ int main(int argc, char **argv) { result = cmd_run_array(command_line, &chld_out, &chld_err, 0); ok(chld_out.lines == 1, "(array) Check for expected number of stdout lines"); ok(chld_err.lines == 0, "(array) Check for expected number of stderr lines"); - ok(strcmp(chld_out.line[0], "this is test one") == 0, "(array) Check for expected stdout output"); + ok(strcmp(chld_out.line[0], "this is test one") == 0, + "(array) Check for expected stdout output"); ok(result == 0, "(array) Checking exit code"); /* ensure everything is empty again */ @@ -82,7 +83,8 @@ int main(int argc, char **argv) { ok(chld_out.lines == 1, "(string) Check for expected number of stdout lines"); ok(chld_err.lines == 0, "(string) Check for expected number of stderr lines"); - ok(strcmp(chld_out.line[0], "this is test one") == 0, "(string) Check for expected stdout output"); + ok(strcmp(chld_out.line[0], "this is test one") == 0, + "(string) Check for expected stdout output"); ok(result == 0, "(string) Checking exit code"); diag("Running plain echo command, set two"); @@ -104,7 +106,8 @@ int main(int argc, char **argv) { result = cmd_run_array(command_line, &chld_out, &chld_err, 0); ok(chld_out.lines == 1, "(array) Check for expected number of stdout lines"); ok(chld_err.lines == 0, "(array) Check for expected number of stderr lines"); - ok(strcmp(chld_out.line[0], "this is test two") == 0, "(array) Check for expected stdout output"); + ok(strcmp(chld_out.line[0], "this is test two") == 0, + "(array) Check for expected stdout output"); ok(result == 0, "(array) Checking exit code"); /* ensure everything is empty again */ @@ -119,7 +122,8 @@ int main(int argc, char **argv) { ok(chld_out.lines == 1, "(string) Check for expected number of stdout lines"); ok(chld_err.lines == 0, "(string) Check for expected number of stderr lines"); - ok(strcmp(chld_out.line[0], "this is test one") == 0, "(string) Check for expected stdout output"); + ok(strcmp(chld_out.line[0], "this is test one") == 0, + "(string) Check for expected stdout output"); ok(result == 0, "(string) Checking exit code"); /* ensure everything is empty again */ @@ -130,7 +134,8 @@ int main(int argc, char **argv) { ok(chld_err.lines == 0, "(initialised) Checking stderr is reset"); ok(result == UNSET, "(initialised) Checking exit code is reset"); - /* Pass linefeeds via parameters through - those should be evaluated by echo to give multi line output */ + /* Pass linefeeds via parameters through - those should be evaluated by echo to give multi line + * output */ command_line[0] = strdup("/bin/echo"); command_line[1] = strdup("this is a test via echo\nline two\nit's line 3"); command_line[2] = strdup("and (note space between '3' and 'and') $$ will not get evaluated"); @@ -138,9 +143,12 @@ int main(int argc, char **argv) { result = cmd_run_array(command_line, &chld_out, &chld_err, 0); ok(chld_out.lines == 3, "(array) Check for expected number of stdout lines"); ok(chld_err.lines == 0, "(array) Check for expected number of stderr lines"); - ok(strcmp(chld_out.line[0], "this is a test via echo") == 0, "(array) Check line 1 for expected stdout output"); - ok(strcmp(chld_out.line[1], "line two") == 0, "(array) Check line 2 for expected stdout output"); - ok(strcmp(chld_out.line[2], "it's line 3 and (note space between '3' and 'and') $$ will not get evaluated") == 0, + ok(strcmp(chld_out.line[0], "this is a test via echo") == 0, + "(array) Check line 1 for expected stdout output"); + ok(strcmp(chld_out.line[1], "line two") == 0, + "(array) Check line 2 for expected stdout output"); + ok(strcmp(chld_out.line[2], + "it's line 3 and (note space between '3' and 'and') $$ will not get evaluated") == 0, "(array) Check line 3 for expected stdout output"); ok(result == 0, "(array) Checking exit code"); @@ -171,7 +179,8 @@ int main(int argc, char **argv) { ok(chld_out.lines == 0, "/bin/sh returns no stdout when file is missing..."); ok(chld_err.lines == 1, "...but does give an error line"); - ok(strstr(chld_err.line[0], "non-existent-file") != NULL, "And missing filename is in error message"); + ok(strstr(chld_err.line[0], "non-existent-file") != NULL, + "And missing filename is in error message"); ok(result != 0, "Get non-zero return code from /bin/sh"); /* ensure everything is empty again */ diff --git a/lib/tests/test_generic_output.c b/lib/tests/test_generic_output.c index e67aefc9..e4a78bcd 100644 --- a/lib/tests/test_generic_output.c +++ b/lib/tests/test_generic_output.c @@ -110,7 +110,8 @@ void test_two_subchecks(void) { sc1.output = "foobar"; sc1 = mp_set_subcheck_state(sc1, STATE_WARNING); - ok(mp_compute_subcheck_state(sc1) == STATE_WARNING, "Test subcheck state directly after setting it"); + ok(mp_compute_subcheck_state(sc1) == STATE_WARNING, + "Test subcheck state directly after setting it"); mp_perfdata pd1 = perfdata_init(); @@ -129,7 +130,8 @@ void test_two_subchecks(void) { mp_add_subcheck_to_subcheck(&sc1, sc2); - ok(mp_compute_subcheck_state(sc1) == STATE_WARNING, "Test subcheck state after adding a subcheck"); + ok(mp_compute_subcheck_state(sc1) == STATE_WARNING, + "Test subcheck state after adding a subcheck"); mp_check check = mp_check_init(); mp_add_subcheck_to_check(&check, sc1); diff --git a/lib/tests/test_ini1.c b/lib/tests/test_ini1.c index 246c1250..3792d142 100644 --- a/lib/tests/test_ini1.c +++ b/lib/tests/test_ini1.c @@ -42,8 +42,9 @@ char *list2str(np_arg_list *optlst) { free(optltmp); } /* Strip last whitespace */ - if (strlen(optstr) > 1) + if (strlen(optstr) > 1) { optstr[strlen(optstr) - 1] = '\0'; + } return optstr; } @@ -54,15 +55,18 @@ int main(int argc, char **argv) { plan_tests(12); optstr = list2str(np_get_defaults("section@./config-tiny.ini", "check_disk")); - ok(!strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank"), "config-tiny.ini's section as expected"); + ok(!strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank"), + "config-tiny.ini's section as expected"); my_free(optstr); optstr = list2str(np_get_defaults("@./config-tiny.ini", "section")); - ok(!strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank"), "Used default section name, without specific"); + ok(!strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank"), + "Used default section name, without specific"); my_free(optstr); optstr = list2str(np_get_defaults("Section Two@./config-tiny.ini", "check_disk")); - ok(!strcmp(optstr, "--something else=blah --remove=whitespace"), "config-tiny.ini's Section Two as expected"); + ok(!strcmp(optstr, "--something else=blah --remove=whitespace"), + "config-tiny.ini's Section Two as expected"); my_free(optstr); optstr = list2str(np_get_defaults("/path/to/file.txt@./config-tiny.ini", "check_disk")); @@ -70,15 +74,18 @@ int main(int argc, char **argv) { my_free(optstr); optstr = list2str(np_get_defaults("section2@./config-tiny.ini", "check_disk")); - ok(!strcmp(optstr, "--this=that"), "config-tiny.ini's section2 with whitespace before section name"); + ok(!strcmp(optstr, "--this=that"), + "config-tiny.ini's section2 with whitespace before section name"); my_free(optstr); optstr = list2str(np_get_defaults("section3@./config-tiny.ini", "check_disk")); - ok(!strcmp(optstr, "--this=that"), "config-tiny.ini's section3 with whitespace after section name"); + ok(!strcmp(optstr, "--this=that"), + "config-tiny.ini's section3 with whitespace after section name"); my_free(optstr); optstr = list2str(np_get_defaults("check_mysql@./plugin.ini", "check_disk")); - ok(!strcmp(optstr, "--username=operator --password=secret"), "plugin.ini's check_mysql as expected"); + ok(!strcmp(optstr, "--username=operator --password=secret"), + "plugin.ini's check_mysql as expected"); my_free(optstr); optstr = list2str(np_get_defaults("check_mysql2@./plugin.ini", "check_disk")); @@ -90,29 +97,39 @@ int main(int argc, char **argv) { my_free(optstr); optstr = list2str(np_get_defaults("Section Two@./config-dos.ini", "check_disk")); - ok(!strcmp(optstr, "--something else=blah --remove=whitespace"), "config-dos.ini's Section Two as expected"); + ok(!strcmp(optstr, "--something else=blah --remove=whitespace"), + "config-dos.ini's Section Two as expected"); my_free(optstr); optstr = list2str(np_get_defaults("section_twice@./plugin.ini", "check_disk")); - ok(!strcmp(optstr, "--foo=bar --bar=foo"), "plugin.ini's section_twice defined twice in the file"); + ok(!strcmp(optstr, "--foo=bar --bar=foo"), + "plugin.ini's section_twice defined twice in the file"); my_free(optstr); optstr = list2str(np_get_defaults("tcp_long_lines@plugins.ini", "check_tcp")); - ok(!strcmp(optstr, "--escape --send=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar " + ok(!strcmp(optstr, "--escape --send=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " + "yadda Foo bar BAZ yadda yadda yadda Foo bar " "BAZ yadda yadda yadda Foo bar BAZ yadda yadda " - "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda " + "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar " + "BAZ yadda yadda yadda Foo bar BAZ yadda " "yadda yadda Foo bar BAZ yadda yadda yadda Foo " - "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " + "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda " + "yadda yadda Foo bar BAZ yadda yadda " "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ " - "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda --expect=Foo bar BAZ yadda yadda " + "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " + "yadda --expect=Foo bar BAZ yadda yadda " "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ " - "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo " + "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " + "yadda Foo bar BAZ yadda yadda yadda Foo " "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " - "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda " + "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar " + "BAZ yadda yadda yadda Foo bar BAZ yadda " "yadda yadda Foo bar BAZ yadda yadda yadda Foo " - "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " + "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda " + "yadda yadda Foo bar BAZ yadda yadda " "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ " - "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo " + "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " + "yadda Foo bar BAZ yadda yadda yadda Foo " "bar BAZ yadda yadda yadda --jail"), "Long options"); my_free(optstr); diff --git a/lib/tests/test_opts1.c b/lib/tests/test_opts1.c index 984183d3..99da5596 100644 --- a/lib/tests/test_opts1.c +++ b/lib/tests/test_opts1.c @@ -47,16 +47,18 @@ void my_free(int *argc, char **newargv, char **argv) { printf("'%s' ", newargv[i]); /* Stop freeing when we get to the start of the original array */ if (freeflag) { - if (newargv[i] == argv[1]) + if (newargv[i] == argv[1]) { freeflag = 0; - else + } else { free(newargv[i]); + } } } printf("\n"); /* Free only if it's a different array */ - if (newargv != argv) + if (newargv != argv) { free(newargv); + } *argc = 0; } #endif @@ -69,8 +71,9 @@ int array_diff(int i1, char **a1, int i2, char **a2) { return 0; } for (i = 0; i <= i1; i++) { - if (a1[i] == NULL && a2[i] == NULL) + if (a1[i] == NULL && a2[i] == NULL) { continue; + } if (a1[i] == NULL || a2[i] == NULL) { printf(" Argument # %i null in one array!\n", i); return 0; @@ -110,27 +113,36 @@ int main(int argc, char **argv) { { char *argv_test[] = {"prog_name", "--extra-opts=@./config-opts.ini", (char *)NULL}; argc_test = 2; - char *argv_known[] = {"prog_name", "--foo=Bar", "--this=Your Mother!", "--blank", (char *)NULL}; + char *argv_known[] = {"prog_name", "--foo=Bar", "--this=Your Mother!", "--blank", + (char *)NULL}; argv_new = np_extra_opts(&argc_test, argv_test, "check_disk"); ok(array_diff(argc_test, argv_new, 4, argv_known), "Only extra opts using default section"); my_free(&argc_test, argv_new, argv_test); } { - char *argv_test[] = {"prog_name", "--extra-opts=sect1@./config-opts.ini", "--extra-opts", "sect2@./config-opts.ini", (char *)NULL}; + char *argv_test[] = {"prog_name", "--extra-opts=sect1@./config-opts.ini", "--extra-opts", + "sect2@./config-opts.ini", (char *)NULL}; argc_test = 4; - char *argv_known[] = {"prog_name", "--one=two", "--something else=oops", "--this=that", (char *)NULL}; + char *argv_known[] = {"prog_name", "--one=two", "--something else=oops", "--this=that", + (char *)NULL}; argv_new = np_extra_opts(&argc_test, argv_test, "check_disk"); ok(array_diff(argc_test, argv_new, 4, argv_known), "Only extra opts specified twice"); my_free(&argc_test, argv_new, argv_test); } { - char *argv_test[] = {"prog_name", "--arg1=val1", "--extra-opts=@./config-opts.ini", "--extra-opts", "sect1@./config-opts.ini", - "--arg2", (char *)NULL}; + char *argv_test[] = {"prog_name", + "--arg1=val1", + "--extra-opts=@./config-opts.ini", + "--extra-opts", + "sect1@./config-opts.ini", + "--arg2", + (char *)NULL}; argc_test = 6; - char *argv_known[] = {"prog_name", "--foo=Bar", "--this=Your Mother!", "--blank", "--one=two", - "--arg1=val1", "--arg2", (char *)NULL}; + char *argv_known[] = {"prog_name", "--foo=Bar", "--this=Your Mother!", + "--blank", "--one=two", "--arg1=val1", + "--arg2", (char *)NULL}; argv_new = np_extra_opts(&argc_test, argv_test, "check_disk"); ok(array_diff(argc_test, argv_new, 7, argv_known), "twice extra opts using two sections"); my_free(&argc_test, argv_new, argv_test); diff --git a/lib/tests/test_opts2.c b/lib/tests/test_opts2.c index 23496617..d1b0aca3 100644 --- a/lib/tests/test_opts2.c +++ b/lib/tests/test_opts2.c @@ -30,16 +30,18 @@ void my_free(int *argc, char **newargv, char **argv) { printf("'%s' ", newargv[i]); /* Stop freeing when we get to the start of the original array */ if (freeflag) { - if (newargv[i] == argv[1]) + if (newargv[i] == argv[1]) { freeflag = 0; - else + } else { free(newargv[i]); + } } } printf("\n"); /* Free only if it's a different array */ - if (newargv != argv) + if (newargv != argv) { free(newargv); + } *argc = 0; } @@ -51,8 +53,9 @@ int array_diff(int i1, char **a1, int i2, char **a2) { return 0; } for (i = 0; i <= i1; i++) { - if (a1[i] == NULL && a2[i] == NULL) + if (a1[i] == NULL && a2[i] == NULL) { continue; + } if (a1[i] == NULL || a2[i] == NULL) { printf(" Argument # %i null in one array!\n", i); return 0; @@ -90,7 +93,8 @@ int main(int argc, char **argv) { } { - char *argv_test[] = {"prog_name", "arg1", "--extra-opts=section1", "--arg3", "val2", (char *)NULL}; + char *argv_test[] = {"prog_name", "arg1", "--extra-opts=section1", + "--arg3", "val2", (char *)NULL}; argc_test = 5; char *argv_known[] = {"prog_name", "--foobar=baz", "arg1", "--arg3", "val2", (char *)NULL}; argv_new = np_extra_opts(&argc_test, argv_test, "check_disk"); @@ -108,30 +112,39 @@ int main(int argc, char **argv) { } { - char *argv_test[] = {"check_tcp", "--extra-opts", "--extra-opts=tcp_long_lines", (char *)NULL}; + char *argv_test[] = {"check_tcp", "--extra-opts", "--extra-opts=tcp_long_lines", + (char *)NULL}; argc_test = 3; - char *argv_known[] = { - "check_tcp", - "--timeout=10", - "--escape", - "--send=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " - "yadda Foo bar BAZ yadda " - "yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " - "yadda Foo bar BAZ " - "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda " - "yadda yadda Foo bar " - "BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda", - "--expect=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " - "yadda Foo bar BAZ yadda " - "yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " - "yadda Foo bar BAZ " - "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda " - "yadda yadda Foo bar " - "BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ " - "yadda yadda yadda Foo " - "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda", - "--jail", - (char *)NULL}; + char *argv_known[] = {"check_tcp", + "--timeout=10", + "--escape", + "--send=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda " + "Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " + "yadda Foo bar BAZ yadda " + "yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " + "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " + "yadda Foo bar BAZ " + "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda " + "yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda " + "yadda yadda Foo bar " + "BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ " + "yadda yadda yadda Foo bar BAZ yadda yadda yadda", + "--expect=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " + "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " + "yadda Foo bar BAZ yadda " + "yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " + "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " + "yadda Foo bar BAZ " + "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda " + "yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda " + "yadda yadda Foo bar " + "BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ " + "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ " + "yadda yadda yadda Foo " + "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ " + "yadda yadda yadda Foo bar BAZ yadda yadda yadda", + "--jail", + (char *)NULL}; argv_new = np_extra_opts(&argc_test, argv_test, "check_tcp"); ok(array_diff(argc_test, argv_new, 6, argv_known), "Long lines test"); my_free(&argc_test, argv_new, argv_test); diff --git a/lib/tests/test_tcp.c b/lib/tests/test_tcp.c index 1b3003e9..de3a2102 100644 --- a/lib/tests/test_tcp.c +++ b/lib/tests/test_tcp.c @@ -32,19 +32,28 @@ int main(void) { server_expect[1] = strdup("bb"); server_expect[2] = strdup("CC"); - ok(np_expect_match("AA bb CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) == NP_MATCH_SUCCESS, + ok(np_expect_match("AA bb CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) == + NP_MATCH_SUCCESS, "Test matching any string at the beginning (first expect string)"); - ok(np_expect_match("bb AA CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) == NP_MATCH_SUCCESS, + ok(np_expect_match("bb AA CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) == + NP_MATCH_SUCCESS, "Test matching any string at the beginning (second expect string)"); ok(np_expect_match("b", server_expect, server_expect_count, NP_MATCH_EXACT) == NP_MATCH_RETRY, "Test matching any string at the beginning (substring match)"); - ok(np_expect_match("XX bb AA CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) == NP_MATCH_FAILURE, + ok(np_expect_match("XX bb AA CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) == + NP_MATCH_FAILURE, "Test with strings not matching at the beginning"); - ok(np_expect_match("XX CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) == NP_MATCH_FAILURE, "Test matching any string"); - ok(np_expect_match("XX", server_expect, server_expect_count, 0) == NP_MATCH_RETRY, "Test not matching any string"); - ok(np_expect_match("XX AA bb CC XX", server_expect, server_expect_count, NP_MATCH_ALL) == NP_MATCH_SUCCESS, + ok(np_expect_match("XX CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) == + NP_MATCH_FAILURE, + "Test matching any string"); + ok(np_expect_match("XX", server_expect, server_expect_count, 0) == NP_MATCH_RETRY, + "Test not matching any string"); + ok(np_expect_match("XX AA bb CC XX", server_expect, server_expect_count, NP_MATCH_ALL) == + NP_MATCH_SUCCESS, "Test matching all strings"); - ok(np_expect_match("XX bb CC XX", server_expect, server_expect_count, NP_MATCH_ALL) == NP_MATCH_RETRY, "Test not matching all strings"); + ok(np_expect_match("XX bb CC XX", server_expect, server_expect_count, NP_MATCH_ALL) == + NP_MATCH_RETRY, + "Test not matching all strings"); ok(np_expect_match("XX XX", server_expect, server_expect_count, NP_MATCH_ALL) == NP_MATCH_RETRY, "Test not matching any string (testing all)"); diff --git a/lib/utils_base.c b/lib/utils_base.c index e95eeaf0..69024bc9 100644 --- a/lib/utils_base.c +++ b/lib/utils_base.c @@ -254,7 +254,7 @@ bool check_range(double value, range *my_range) { yes = false; } - if (!my_range->end_infinity&& !my_range->start_infinity) { + if (!my_range->end_infinity && !my_range->start_infinity) { if ((my_range->start <= value) && (value <= my_range->end)) { return no; } @@ -268,7 +268,7 @@ bool check_range(double value, range *my_range) { return yes; } - if (my_range->start_infinity && !my_range->end_infinity ) { + if (my_range->start_infinity && !my_range->end_infinity) { if (value <= my_range->end) { return no; } diff --git a/lib/utils_cmd.c b/lib/utils_cmd.c index 9b222409..d1feaa33 100644 --- a/lib/utils_cmd.c +++ b/lib/utils_cmd.c @@ -71,7 +71,7 @@ extern char **environ; #endif #ifndef WIFEXITED -# define WIFEXITED(stat_val) (((stat_val)&255) == 0) +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif /* 4.3BSD Reno doesn't define SIG_ERR */ @@ -103,8 +103,9 @@ void cmd_init(void) { maxfd = MAXFD_LIMIT; } - if (!_cmd_pids) + if (!_cmd_pids) { _cmd_pids = calloc(maxfd, sizeof(pid_t)); + } } /* Start running a command, array style */ @@ -116,13 +117,15 @@ static int _cmd_open(char *const *argv, int *pfd, int *pfderr) { int i = 0; - if (!_cmd_pids) + if (!_cmd_pids) { CMD_INIT; + } setenv("LC_ALL", "C", 1); - if (pipe(pfd) < 0 || pipe(pfderr) < 0 || (pid = fork()) < 0) + if (pipe(pfd) < 0 || pipe(pfderr) < 0 || (pid = fork()) < 0) { return -1; /* errno set by the failing function */ + } /* child runs exceve() and _exit. */ if (pid == 0) { @@ -147,9 +150,11 @@ static int _cmd_open(char *const *argv, int *pfd, int *pfderr) { * This is executed in a separate address space (pure child), * so we don't have to worry about async safety */ long maxfd = mp_open_max(); - for (i = 0; i < maxfd; i++) - if (_cmd_pids[i] > 0) + for (i = 0; i < maxfd; i++) { + if (_cmd_pids[i] > 0) { close(i); + } + } execve(argv[0], argv, environ); _exit(STATE_UNKNOWN); @@ -172,17 +177,21 @@ static int _cmd_close(int fd) { /* make sure the provided fd was opened */ long maxfd = mp_open_max(); - if (fd < 0 || fd > maxfd || !_cmd_pids || (pid = _cmd_pids[fd]) == 0) + if (fd < 0 || fd > maxfd || !_cmd_pids || (pid = _cmd_pids[fd]) == 0) { return -1; + } _cmd_pids[fd] = 0; - if (close(fd) == -1) + if (close(fd) == -1) { return -1; + } /* EINTR is ok (sort of), everything else is bad */ - while (waitpid(pid, &status, 0) < 0) - if (errno != EINTR) + while (waitpid(pid, &status, 0) < 0) { + if (errno != EINTR) { return -1; + } + } /* return child's termination status */ return (WIFEXITED(status)) ? WEXITSTATUS(status) : -1; @@ -212,15 +221,17 @@ static int _cmd_fetch_output(int fd, output *op, int flags) { /* some plugins may want to keep output unbroken, and some commands * will yield no output, so return here for those */ - if (flags & CMD_NO_ARRAYS || !op->buf || !op->buflen) + if (flags & CMD_NO_ARRAYS || !op->buf || !op->buflen) { return op->buflen; + } /* and some may want both */ if (flags & CMD_NO_ASSOC) { buf = malloc(op->buflen); memcpy(buf, op->buf, op->buflen); - } else + } else { buf = op->buf; + } op->line = NULL; op->lens = NULL; @@ -241,8 +252,9 @@ static int _cmd_fetch_output(int fd, output *op, int flags) { op->line[lineno] = &buf[i]; /* hop to next newline or end of buffer */ - while (buf[i] != '\n' && i < op->buflen) + while (buf[i] != '\n' && i < op->buflen) { i++; + } buf[i] = '\0'; /* calculate the string length using pointer difference */ @@ -262,30 +274,36 @@ int cmd_run(const char *cmdstring, output *out, output *err, int flags) { char *cmd = NULL; char *str = NULL; - if (cmdstring == NULL) + if (cmdstring == NULL) { return -1; + } /* initialize the structs */ - if (out) + if (out) { memset(out, 0, sizeof(output)); - if (err) + } + if (err) { memset(err, 0, sizeof(output)); + } /* make copy of command string so strtok() doesn't silently modify it */ /* (the calling program may want to access it later) */ cmdlen = strlen(cmdstring); - if ((cmd = malloc(cmdlen + 1)) == NULL) + if ((cmd = malloc(cmdlen + 1)) == NULL) { return -1; + } memcpy(cmd, cmdstring, cmdlen); cmd[cmdlen] = '\0'; /* This is not a shell, so we don't handle "???" */ - if (strstr(cmdstring, "\"")) + if (strstr(cmdstring, "\"")) { return -1; + } /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */ - if (strstr(cmdstring, " ' ") || strstr(cmdstring, "'''")) + if (strstr(cmdstring, " ' ") || strstr(cmdstring, "'''")) { return -1; + } /* each arg must be whitespace-separated, so args can be a maximum * of (len / 2) + 1. We add 1 extra to the mix for NULL termination */ @@ -304,8 +322,9 @@ int cmd_run(const char *cmdstring, output *out, output *err, int flags) { if (strstr(str, "'") == str) { /* handle SIMPLE quoted strings */ str++; - if (!strstr(str, "'")) + if (!strstr(str, "'")) { return -1; /* balanced? */ + } cmd = 1 + strstr(str, "'"); str[strcspn(str, "'")] = 0; } else { @@ -317,8 +336,9 @@ int cmd_run(const char *cmdstring, output *out, output *err, int flags) { } } - if (cmd && strlen(cmd) == strspn(cmd, " \t\r\n")) + if (cmd && strlen(cmd) == strspn(cmd, " \t\r\n")) { cmd = NULL; + } argv[i++] = str; } @@ -330,50 +350,61 @@ int cmd_run_array(char *const *argv, output *out, output *err, int flags) { int fd, pfd_out[2], pfd_err[2]; /* initialize the structs */ - if (out) + if (out) { memset(out, 0, sizeof(output)); - if (err) + } + if (err) { memset(err, 0, sizeof(output)); + } - if ((fd = _cmd_open(argv, pfd_out, pfd_err)) == -1) + if ((fd = _cmd_open(argv, pfd_out, pfd_err)) == -1) { die(STATE_UNKNOWN, _("Could not open pipe: %s\n"), argv[0]); + } - if (out) + if (out) { out->lines = _cmd_fetch_output(pfd_out[0], out, flags); - if (err) + } + if (err) { err->lines = _cmd_fetch_output(pfd_err[0], err, flags); + } return _cmd_close(fd); } int cmd_file_read(const char *filename, output *out, int flags) { int fd; - if (out) + if (out) { memset(out, 0, sizeof(output)); + } if ((fd = open(filename, O_RDONLY)) == -1) { die(STATE_UNKNOWN, _("Error opening %s: %s"), filename, strerror(errno)); } - if (out) + if (out) { out->lines = _cmd_fetch_output(fd, out, flags); + } - if (close(fd) == -1) + if (close(fd) == -1) { die(STATE_UNKNOWN, _("Error closing %s: %s"), filename, strerror(errno)); + } return 0; } void timeout_alarm_handler(int signo) { if (signo == SIGALRM) { - printf(_("%s - Plugin timed out after %d seconds\n"), state_text(timeout_state), timeout_interval); + printf(_("%s - Plugin timed out after %d seconds\n"), state_text(timeout_state), + timeout_interval); long maxfd = mp_open_max(); - if (_cmd_pids) + if (_cmd_pids) { for (long int i = 0; i < maxfd; i++) { - if (_cmd_pids[i] != 0) + if (_cmd_pids[i] != 0) { kill(_cmd_pids[i], SIGKILL); + } } + } exit(timeout_state); } diff --git a/lib/utils_tcp.c b/lib/utils_tcp.c index daae1d54..1482458b 100644 --- a/lib/utils_tcp.c +++ b/lib/utils_tcp.c @@ -29,18 +29,21 @@ #include "common.h" #include "utils_tcp.h" -#define VERBOSE(message) \ - do { \ - if (flags & NP_MATCH_VERBOSE) \ - puts(message); \ +#define VERBOSE(message) \ + do { \ + if (flags & NP_MATCH_VERBOSE) \ + puts(message); \ } while (0) -enum np_match_result np_expect_match(char *status, char **server_expect, int expect_count, int flags) { +enum np_match_result np_expect_match(char *status, char **server_expect, int expect_count, + int flags) { int i, match = 0, partial = 0; for (i = 0; i < expect_count; i++) { - if (flags & NP_MATCH_VERBOSE) - printf("looking for [%s] %s [%s]\n", server_expect[i], (flags & NP_MATCH_EXACT) ? "in beginning of" : "anywhere in", status); + if (flags & NP_MATCH_VERBOSE) { + printf("looking for [%s] %s [%s]\n", server_expect[i], + (flags & NP_MATCH_EXACT) ? "in beginning of" : "anywhere in", status); + } if (flags & NP_MATCH_EXACT) { if (strncmp(status, server_expect[i], strlen(server_expect[i])) == 0) { @@ -60,10 +63,12 @@ enum np_match_result np_expect_match(char *status, char **server_expect, int exp VERBOSE("couldn't find it"); } - if ((flags & NP_MATCH_ALL && match == expect_count) || (!(flags & NP_MATCH_ALL) && match >= 1)) + if ((flags & NP_MATCH_ALL && match == expect_count) || + (!(flags & NP_MATCH_ALL) && match >= 1)) { return NP_MATCH_SUCCESS; - else if (partial > 0 || !(flags & NP_MATCH_EXACT)) + } else if (partial > 0 || !(flags & NP_MATCH_EXACT)) { return NP_MATCH_RETRY; - else + } else { return NP_MATCH_FAILURE; + } } diff --git a/lib/utils_tcp.h b/lib/utils_tcp.h index a7d83c59..e5cdbb82 100644 --- a/lib/utils_tcp.h +++ b/lib/utils_tcp.h @@ -17,4 +17,5 @@ enum np_match_result { NP_MATCH_RETRY }; -enum np_match_result np_expect_match(char *status, char **server_expect, int server_expect_count, int flags); +enum np_match_result np_expect_match(char *status, char **server_expect, int server_expect_count, + int flags); diff --git a/plugins-root/check_dhcp.c b/plugins-root/check_dhcp.c index daed9cb0..9a96547f 100644 --- a/plugins-root/check_dhcp.c +++ b/plugins-root/check_dhcp.c @@ -127,17 +127,17 @@ static long mac_addr_dlpi(const char *, int, u_char *); #define MAX_DHCP_OPTIONS_LENGTH 312 typedef struct dhcp_packet_struct { - uint8_t op; /* packet type */ - uint8_t htype; /* type of hardware address for this machine (Ethernet, etc) */ - uint8_t hlen; /* length of hardware address (of this machine) */ - uint8_t hops; /* hops */ - uint32_t xid; /* random transaction id number - chosen by this machine */ - uint16_t secs; /* seconds used in timing */ - uint16_t flags; /* flags */ - struct in_addr ciaddr; /* IP address of this machine (if we already have one) */ - struct in_addr yiaddr; /* IP address of this machine (offered by the DHCP server) */ - struct in_addr siaddr; /* IP address of next server */ - struct in_addr giaddr; /* IP address of DHCP relay */ + uint8_t op; /* packet type */ + uint8_t htype; /* type of hardware address for this machine (Ethernet, etc) */ + uint8_t hlen; /* length of hardware address (of this machine) */ + uint8_t hops; /* hops */ + uint32_t xid; /* random transaction id number - chosen by this machine */ + uint16_t secs; /* seconds used in timing */ + uint16_t flags; /* flags */ + struct in_addr ciaddr; /* IP address of this machine (if we already have one) */ + struct in_addr yiaddr; /* IP address of this machine (offered by the DHCP server) */ + struct in_addr siaddr; /* IP address of next server */ + struct in_addr giaddr; /* IP address of DHCP relay */ unsigned char chaddr[MAX_DHCP_CHADDR_LENGTH]; /* hardware address of this machine */ char sname[MAX_DHCP_SNAME_LENGTH]; /* name of DHCP server */ char file[MAX_DHCP_FILE_LENGTH]; /* boot file name (used for diskless booting?) */ @@ -199,7 +199,8 @@ static void print_help(void); static void resolve_host(const char * /*in*/, struct in_addr * /*out*/); static unsigned char *mac_aton(const char * /*string*/); static void print_hardware_address(const unsigned char * /*address*/); -static int get_hardware_address(int /*sock*/, char * /*interface_name*/, unsigned char *client_hardware_address); +static int get_hardware_address(int /*sock*/, char * /*interface_name*/, + unsigned char *client_hardware_address); typedef struct get_ip_address_wrapper { int error; @@ -211,32 +212,40 @@ typedef struct send_dhcp_discover_wrapper { int error; uint32_t packet_xid; } send_dhcp_discover_wrapper; -static send_dhcp_discover_wrapper send_dhcp_discover(int socket, bool unicast, struct in_addr dhcp_ip, struct in_addr requested_address, - bool request_specific_address, struct in_addr my_ip, - unsigned char *client_hardware_address); +static send_dhcp_discover_wrapper +send_dhcp_discover(int socket, bool unicast, struct in_addr dhcp_ip, + struct in_addr requested_address, bool request_specific_address, + struct in_addr my_ip, unsigned char *client_hardware_address); typedef struct get_dhcp_offer_wrapper { int error; int valid_responses; dhcp_offer *dhcp_offer_list; } get_dhcp_offer_wrapper; -static get_dhcp_offer_wrapper get_dhcp_offer(int /*sock*/, int dhcpoffer_timeout, uint32_t packet_xid, dhcp_offer *dhcp_offer_list, +static get_dhcp_offer_wrapper get_dhcp_offer(int /*sock*/, int dhcpoffer_timeout, + uint32_t packet_xid, dhcp_offer *dhcp_offer_list, const unsigned char *client_hardware_address); -static mp_subcheck get_results(bool exclusive, int requested_servers, struct in_addr requested_address, bool request_specific_address, - requested_server *requested_server_list, int valid_responses, dhcp_offer *dhcp_offer_list); +static mp_subcheck get_results(bool exclusive, int requested_servers, + struct in_addr requested_address, bool request_specific_address, + requested_server *requested_server_list, int valid_responses, + dhcp_offer *dhcp_offer_list); typedef struct add_dhcp_offer_wrapper { int error; dhcp_offer *dhcp_offer_list; } add_dhcp_offer_wrapper; -static add_dhcp_offer_wrapper add_dhcp_offer(struct in_addr /*source*/, dhcp_packet * /*offer_packet*/, dhcp_offer *dhcp_offer_list); +static add_dhcp_offer_wrapper add_dhcp_offer(struct in_addr /*source*/, + dhcp_packet * /*offer_packet*/, + dhcp_offer *dhcp_offer_list); static int free_dhcp_offer_list(dhcp_offer *dhcp_offer_list); static int free_requested_server_list(requested_server *requested_server_list); static int create_dhcp_socket(bool /*unicast*/, char *network_interface_name); static int close_dhcp_socket(int /*sock*/); -static int send_dhcp_packet(void * /*buffer*/, int /*buffer_size*/, int /*sock*/, struct sockaddr_in * /*dest*/); -static int receive_dhcp_packet(void * /*buffer*/, int /*buffer_size*/, int /*sock*/, int /*timeout*/, struct sockaddr_in * /*address*/); +static int send_dhcp_packet(void * /*buffer*/, int /*buffer_size*/, int /*sock*/, + struct sockaddr_in * /*dest*/); +static int receive_dhcp_packet(void * /*buffer*/, int /*buffer_size*/, int /*sock*/, + int /*timeout*/, struct sockaddr_in * /*address*/); int main(int argc, char **argv) { setlocale(LC_ALL, ""); @@ -271,7 +280,8 @@ int main(int argc, char **argv) { struct in_addr my_ip = {0}; if (config.unicast_mode) { /* get IP address of client machine */ - get_ip_address_wrapper tmp_get_ip = get_ip_address(dhcp_socket, config.network_interface_name); + get_ip_address_wrapper tmp_get_ip = + get_ip_address(dhcp_socket, config.network_interface_name); if (tmp_get_ip.error == OK) { my_ip = tmp_get_ip.my_ip; } else { @@ -281,8 +291,9 @@ int main(int argc, char **argv) { } /* send DHCPDISCOVER packet */ - send_dhcp_discover_wrapper disco_res = send_dhcp_discover(dhcp_socket, config.unicast_mode, config.dhcp_ip, config.requested_address, - config.request_specific_address, my_ip, client_hardware_address); + send_dhcp_discover_wrapper disco_res = send_dhcp_discover( + dhcp_socket, config.unicast_mode, config.dhcp_ip, config.requested_address, + config.request_specific_address, my_ip, client_hardware_address); if (disco_res.error != OK) { // DO something? @@ -290,8 +301,8 @@ int main(int argc, char **argv) { } /* wait for a DHCPOFFER packet */ - get_dhcp_offer_wrapper offer_res = - get_dhcp_offer(dhcp_socket, config.dhcpoffer_timeout, disco_res.packet_xid, NULL, client_hardware_address); + get_dhcp_offer_wrapper offer_res = get_dhcp_offer( + dhcp_socket, config.dhcpoffer_timeout, disco_res.packet_xid, NULL, client_hardware_address); int valid_responses = 0; dhcp_offer *dhcp_offer_list = NULL; @@ -308,8 +319,10 @@ int main(int argc, char **argv) { mp_check overall = mp_check_init(); /* determine state/plugin output to return */ - mp_subcheck sc_res = get_results(config.exclusive_mode, config.num_of_requested_servers, config.requested_address, - config.request_specific_address, config.requested_server_list, valid_responses, dhcp_offer_list); + mp_subcheck sc_res = + get_results(config.exclusive_mode, config.num_of_requested_servers, + config.requested_address, config.request_specific_address, + config.requested_server_list, valid_responses, dhcp_offer_list); mp_add_subcheck_to_check(&overall, sc_res); /* free allocated memory */ free_dhcp_offer_list(dhcp_offer_list); @@ -357,17 +370,20 @@ int get_hardware_address(int sock, char *interface_name, unsigned char *client_h } if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { - printf(_("Error: Couldn't get hardware address from %s. sysctl 1 error - %s.\n"), interface_name, strerror(errno)); + printf(_("Error: Couldn't get hardware address from %s. sysctl 1 error - %s.\n"), + interface_name, strerror(errno)); exit(STATE_UNKNOWN); } if ((buf = malloc(len)) == NULL) { - printf(_("Error: Couldn't get hardware address from interface %s. malloc error - %s.\n"), interface_name, strerror(errno)); + printf(_("Error: Couldn't get hardware address from interface %s. malloc error - %s.\n"), + interface_name, strerror(errno)); exit(4); } if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { - printf(_("Error: Couldn't get hardware address from %s. sysctl 2 error - %s.\n"), interface_name, strerror(errno)); + printf(_("Error: Couldn't get hardware address from %s. sysctl 2 error - %s.\n"), + interface_name, strerror(errno)); exit(STATE_UNKNOWN); } @@ -398,12 +414,16 @@ int get_hardware_address(int sock, char *interface_name, unsigned char *client_h unit = atoi(p); strncat(dev, interface_name, 6); } else { - printf(_("Error: can't find unit number in interface_name (%s) - expecting TypeNumber eg lnc0.\n"), interface_name); + printf(_("Error: can't find unit number in interface_name (%s) - expecting TypeNumber eg " + "lnc0.\n"), + interface_name); exit(STATE_UNKNOWN); } stat = mac_addr_dlpi(dev, unit, client_hardware_address); if (stat != 0) { - printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit); + printf( + _("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), + dev, unit); exit(STATE_UNKNOWN); } @@ -415,7 +435,9 @@ int get_hardware_address(int sock, char *interface_name, unsigned char *client_h stat = mac_addr_dlpi(dev, unit, client_hardware_address); if (stat != 0) { - printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit); + printf( + _("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), + dev, unit); exit(STATE_UNKNOWN); } /* Kompf 2000-2003 */ @@ -463,8 +485,10 @@ get_ip_address_wrapper get_ip_address(int sock, char *interface_name) { } /* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */ -static send_dhcp_discover_wrapper send_dhcp_discover(int sock, bool unicast, struct in_addr dhcp_ip, struct in_addr requested_address, - bool request_specific_address, struct in_addr my_ip, +static send_dhcp_discover_wrapper send_dhcp_discover(int sock, bool unicast, struct in_addr dhcp_ip, + struct in_addr requested_address, + bool request_specific_address, + struct in_addr my_ip, unsigned char *client_hardware_address) { dhcp_packet discover_packet = {0}; /* boot request flag (backward compatible with BOOTP servers) */ @@ -506,8 +530,9 @@ static send_dhcp_discover_wrapper send_dhcp_discover(int sock, bool unicast, str unsigned short opts = 4; /* DHCP message type is embedded in options field */ - discover_packet.options[opts++] = DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */ - discover_packet.options[opts++] = '\x01'; /* DHCP message option length in bytes */ + discover_packet.options[opts++] = + DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */ + discover_packet.options[opts++] = '\x01'; /* DHCP message option length in bytes */ discover_packet.options[opts++] = DHCPDISCOVER; /* the IP address we're requesting */ @@ -535,8 +560,10 @@ static send_dhcp_discover_wrapper send_dhcp_discover(int sock, bool unicast, str }; if (verbose) { - printf(_("DHCPDISCOVER to %s port %d\n"), inet_ntoa(sockaddr_broadcast.sin_addr), ntohs(sockaddr_broadcast.sin_port)); - printf("DHCPDISCOVER XID: %u (0x%X)\n", ntohl(discover_packet.xid), ntohl(discover_packet.xid)); + printf(_("DHCPDISCOVER to %s port %d\n"), inet_ntoa(sockaddr_broadcast.sin_addr), + ntohs(sockaddr_broadcast.sin_port)); + printf("DHCPDISCOVER XID: %u (0x%X)\n", ntohl(discover_packet.xid), + ntohl(discover_packet.xid)); printf("DHCDISCOVER ciaddr: %s\n", inet_ntoa(discover_packet.ciaddr)); printf("DHCDISCOVER yiaddr: %s\n", inet_ntoa(discover_packet.yiaddr)); printf("DHCDISCOVER siaddr: %s\n", inet_ntoa(discover_packet.siaddr)); @@ -554,7 +581,8 @@ static send_dhcp_discover_wrapper send_dhcp_discover(int sock, bool unicast, str } /* waits for a DHCPOFFER message from one or more DHCP servers */ -get_dhcp_offer_wrapper get_dhcp_offer(int sock, int dhcpoffer_timeout, uint32_t packet_xid, dhcp_offer *dhcp_offer_list, +get_dhcp_offer_wrapper get_dhcp_offer(int sock, int dhcpoffer_timeout, uint32_t packet_xid, + dhcp_offer *dhcp_offer_list, const unsigned char *client_hardware_address) { time_t start_time; time(&start_time); @@ -578,7 +606,8 @@ get_dhcp_offer_wrapper get_dhcp_offer(int sock, int dhcpoffer_timeout, uint32_t dhcp_packet offer_packet = {0}; result = OK; - result = receive_dhcp_packet(&offer_packet, sizeof(offer_packet), sock, dhcpoffer_timeout, &source); + result = receive_dhcp_packet(&offer_packet, sizeof(offer_packet), sock, dhcpoffer_timeout, + &source); if (result != OK) { if (verbose) { @@ -607,8 +636,9 @@ get_dhcp_offer_wrapper get_dhcp_offer(int sock, int dhcpoffer_timeout, uint32_t /* check packet xid to see if its the same as the one we used in the discover packet */ if (ntohl(offer_packet.xid) != packet_xid) { if (verbose) { - printf(_("DHCPOFFER XID (%u) did not match DHCPDISCOVER XID (%u) - ignoring packet\n"), ntohl(offer_packet.xid), - packet_xid); + printf( + _("DHCPOFFER XID (%u) did not match DHCPDISCOVER XID (%u) - ignoring packet\n"), + ntohl(offer_packet.xid), packet_xid); } continue; @@ -648,7 +678,8 @@ get_dhcp_offer_wrapper get_dhcp_offer(int sock, int dhcpoffer_timeout, uint32_t printf("DHCPOFFER giaddr: %s\n", inet_ntoa(offer_packet.giaddr)); } - add_dhcp_offer_wrapper add_res = add_dhcp_offer(source.sin_addr, &offer_packet, dhcp_offer_list); + add_dhcp_offer_wrapper add_res = + add_dhcp_offer(source.sin_addr, &offer_packet, dhcp_offer_list); if (add_res.error != OK) { // TODO } else { @@ -673,7 +704,8 @@ get_dhcp_offer_wrapper get_dhcp_offer(int sock, int dhcpoffer_timeout, uint32_t /* sends a DHCP packet */ int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in *dest) { - int result = sendto(sock, (char *)buffer, buffer_size, 0, (struct sockaddr *)dest, sizeof(*dest)); + int result = + sendto(sock, (char *)buffer, buffer_size, 0, (struct sockaddr *)dest, sizeof(*dest)); if (verbose) { printf(_("send_dhcp_packet result: %d\n"), result); @@ -687,7 +719,8 @@ int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in } /* receives a DHCP packet */ -int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address) { +int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, + struct sockaddr_in *address) { /* wait for data to arrive (up time timeout) */ struct timeval timeout_val = { .tv_sec = timeout, @@ -711,7 +744,8 @@ int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, st struct sockaddr_in source_address = {0}; socklen_t address_size = sizeof(source_address); - int recv_result = recvfrom(sock, (char *)buffer, buffer_size, 0, (struct sockaddr *)&source_address, &address_size); + int recv_result = recvfrom(sock, (char *)buffer, buffer_size, 0, + (struct sockaddr *)&source_address, &address_size); if (verbose) { printf("recv_result: %d\n", recv_result); } @@ -775,7 +809,8 @@ int create_dhcp_socket(bool unicast, char *network_interface_name) { strncpy(interface.ifr_ifrn.ifrn_name, network_interface_name, IFNAMSIZ - 1); interface.ifr_ifrn.ifrn_name[IFNAMSIZ - 1] = '\0'; if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (char *)&interface, sizeof(interface)) < 0) { - printf(_("Error: Could not bind socket to interface %s. Check your privileges...\n"), network_interface_name); + printf(_("Error: Could not bind socket to interface %s. Check your privileges...\n"), + network_interface_name); exit(STATE_UNKNOWN); } @@ -786,7 +821,8 @@ int create_dhcp_socket(bool unicast, char *network_interface_name) { /* bind the socket */ if (bind(sock, (struct sockaddr *)&myname, sizeof(myname)) < 0) { - printf(_("Error: Could not bind to DHCP socket (port %d)! Check your privileges...\n"), DHCP_CLIENT_PORT); + printf(_("Error: Could not bind to DHCP socket (port %d)! Check your privileges...\n"), + DHCP_CLIENT_PORT); exit(STATE_UNKNOWN); } @@ -800,7 +836,8 @@ int close_dhcp_socket(int sock) { } /* adds a requested server address to list in memory */ -int add_requested_server(struct in_addr server_address, int *requested_servers, requested_server **requested_server_list) { +int add_requested_server(struct in_addr server_address, int *requested_servers, + requested_server **requested_server_list) { requested_server *new_server = (requested_server *)malloc(sizeof(requested_server)); if (new_server == NULL) { return ERROR; @@ -822,7 +859,8 @@ int add_requested_server(struct in_addr server_address, int *requested_servers, } /* adds a DHCP OFFER to list in memory */ -add_dhcp_offer_wrapper add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet, dhcp_offer *dhcp_offer_list) { +add_dhcp_offer_wrapper add_dhcp_offer(struct in_addr source, dhcp_packet *offer_packet, + dhcp_offer *dhcp_offer_list) { if (offer_packet == NULL) { add_dhcp_offer_wrapper tmp = { .error = ERROR, @@ -859,15 +897,18 @@ add_dhcp_offer_wrapper add_dhcp_offer(struct in_addr source, dhcp_packet *offer_ dhcp_lease_time = ntohl(dhcp_lease_time); break; case DHCP_OPTION_RENEWAL_TIME: - memcpy(&dhcp_renewal_time, &offer_packet->options[dchp_opt_idx], sizeof(dhcp_renewal_time)); + memcpy(&dhcp_renewal_time, &offer_packet->options[dchp_opt_idx], + sizeof(dhcp_renewal_time)); dhcp_renewal_time = ntohl(dhcp_renewal_time); break; case DHCP_OPTION_REBINDING_TIME: - memcpy(&dhcp_rebinding_time, &offer_packet->options[dchp_opt_idx], sizeof(dhcp_rebinding_time)); + memcpy(&dhcp_rebinding_time, &offer_packet->options[dchp_opt_idx], + sizeof(dhcp_rebinding_time)); dhcp_rebinding_time = ntohl(dhcp_rebinding_time); break; case DHCP_OPTION_SERVER_IDENTIFIER: - memcpy(&serv_ident.s_addr, &offer_packet->options[dchp_opt_idx], sizeof(serv_ident.s_addr)); + memcpy(&serv_ident.s_addr, &offer_packet->options[dchp_opt_idx], + sizeof(serv_ident.s_addr)); break; } @@ -955,7 +996,8 @@ int free_dhcp_offer_list(dhcp_offer *dhcp_offer_list) { /* frees memory allocated to requested server list */ int free_requested_server_list(requested_server *requested_server_list) { requested_server *next_server; - for (requested_server *this_server = requested_server_list; this_server != NULL; this_server = next_server) { + for (requested_server *this_server = requested_server_list; this_server != NULL; + this_server = next_server) { next_server = this_server->next; free(this_server); } @@ -964,8 +1006,10 @@ int free_requested_server_list(requested_server *requested_server_list) { } /* gets state and plugin output to return */ -mp_subcheck get_results(bool exclusive, const int requested_servers, const struct in_addr requested_address, bool request_specific_address, - requested_server *requested_server_list, int valid_responses, dhcp_offer *dhcp_offer_list) { +mp_subcheck get_results(bool exclusive, const int requested_servers, + const struct in_addr requested_address, bool request_specific_address, + requested_server *requested_server_list, int valid_responses, + dhcp_offer *dhcp_offer_list) { mp_subcheck sc_dhcp_results = mp_subcheck_init(); sc_dhcp_results = mp_set_subcheck_default_state(sc_dhcp_results, STATE_OK); @@ -995,22 +1039,28 @@ mp_subcheck get_results(bool exclusive, const int requested_servers, const struc /* checks responses from requested servers */ int requested_responses = 0; if (requested_servers > 0) { - for (requested_server *temp_server = requested_server_list; temp_server != NULL; temp_server = temp_server->next) { - for (dhcp_offer *temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) { + for (requested_server *temp_server = requested_server_list; temp_server != NULL; + temp_server = temp_server->next) { + for (dhcp_offer *temp_offer = dhcp_offer_list; temp_offer != NULL; + temp_offer = temp_offer->next) { /* get max lease time we were offered */ - if (temp_offer->lease_time > max_lease_time || temp_offer->lease_time == DHCP_INFINITE_TIME) { + if (temp_offer->lease_time > max_lease_time || + temp_offer->lease_time == DHCP_INFINITE_TIME) { max_lease_time = temp_offer->lease_time; } /* see if we got the address we requested */ - if (!memcmp(&requested_address, &temp_offer->offered_address, sizeof(requested_address))) { + if (!memcmp(&requested_address, &temp_offer->offered_address, + sizeof(requested_address))) { received_requested_address = true; } /* see if the servers we wanted a response from, talked to us or not */ - if (!memcmp(&temp_offer->server_address, &temp_server->server_address, sizeof(temp_server->server_address))) { + if (!memcmp(&temp_offer->server_address, &temp_server->server_address, + sizeof(temp_server->server_address))) { if (verbose) { - printf(_("DHCP Server Match: Offerer=%s"), inet_ntoa(temp_offer->server_address)); + printf(_("DHCP Server Match: Offerer=%s"), + inet_ntoa(temp_offer->server_address)); printf(_(" Requested=%s"), inet_ntoa(temp_server->server_address)); if (temp_server->answered) { printf(_(" (duplicate)")); @@ -1028,7 +1078,8 @@ mp_subcheck get_results(bool exclusive, const int requested_servers, const struc } /* exclusive mode: check for undesired offers */ - for (dhcp_offer *temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) { + for (dhcp_offer *temp_offer = dhcp_offer_list; temp_offer != NULL; + temp_offer = temp_offer->next) { if (!temp_offer->desired) { undesired_offer = temp_offer; /* Checks only for the first undesired offer */ break; /* no further checks needed */ @@ -1036,7 +1087,8 @@ mp_subcheck get_results(bool exclusive, const int requested_servers, const struc } mp_subcheck sc_rqust_srvs = mp_subcheck_init(); - xasprintf(&sc_rqust_srvs.output, "%d of %d requested servers responded", requested_responses, requested_servers); + xasprintf(&sc_rqust_srvs.output, "%d of %d requested servers responded", + requested_responses, requested_servers); if (requested_responses == requested_servers) { sc_rqust_srvs = mp_set_subcheck_state(sc_rqust_srvs, STATE_OK); @@ -1053,14 +1105,17 @@ mp_subcheck get_results(bool exclusive, const int requested_servers, const struc } else { /* else check and see if we got our requested address from any server */ - for (dhcp_offer *temp_offer = dhcp_offer_list; temp_offer != NULL; temp_offer = temp_offer->next) { + for (dhcp_offer *temp_offer = dhcp_offer_list; temp_offer != NULL; + temp_offer = temp_offer->next) { /* get max lease time we were offered */ - if (temp_offer->lease_time > max_lease_time || temp_offer->lease_time == DHCP_INFINITE_TIME) { + if (temp_offer->lease_time > max_lease_time || + temp_offer->lease_time == DHCP_INFINITE_TIME) { max_lease_time = temp_offer->lease_time; } /* see if we got the address we requested */ - if (!memcmp(&requested_address, &temp_offer->offered_address, sizeof(requested_address))) { + if (!memcmp(&requested_address, &temp_offer->offered_address, + sizeof(requested_address))) { received_requested_address = true; } } @@ -1069,7 +1124,8 @@ mp_subcheck get_results(bool exclusive, const int requested_servers, const struc if (max_lease_time == DHCP_INFINITE_TIME) { xasprintf(&sc_dhcp_results.output, "%s, max lease time = Infinity", sc_dhcp_results.output); } else { - xasprintf(&sc_dhcp_results.output, "%s, max lease time = %" PRIu32 " seconds", sc_dhcp_results.output, max_lease_time); + xasprintf(&sc_dhcp_results.output, "%s, max lease time = %" PRIu32 " seconds", + sc_dhcp_results.output, max_lease_time); } if (exclusive) { @@ -1083,8 +1139,8 @@ mp_subcheck get_results(bool exclusive, const int requested_servers, const struc // Get the addresses for printout // 1.address of the sending server char server_address[INET_ADDRSTRLEN]; - const char *server_address_transformed = - inet_ntop(AF_INET, &undesired_offer->server_address, server_address, sizeof(server_address)); + const char *server_address_transformed = inet_ntop( + AF_INET, &undesired_offer->server_address, server_address, sizeof(server_address)); if (server_address != server_address_transformed) { die(STATE_UNKNOWN, "inet_ntop failed"); @@ -1093,13 +1149,15 @@ mp_subcheck get_results(bool exclusive, const int requested_servers, const struc // 2.address offered char offered_address[INET_ADDRSTRLEN]; const char *offered_address_transformed = - inet_ntop(AF_INET, &undesired_offer->offered_address, offered_address, sizeof(offered_address)); + inet_ntop(AF_INET, &undesired_offer->offered_address, offered_address, + sizeof(offered_address)); if (offered_address != offered_address_transformed) { die(STATE_UNKNOWN, "inet_ntop failed"); } - xasprintf(&sc_rogue_server.output, "Rogue DHCP Server detected! Server %s offered %s", server_address, offered_address); + xasprintf(&sc_rogue_server.output, "Rogue DHCP Server detected! Server %s offered %s", + server_address, offered_address); } else { sc_rogue_server = mp_set_subcheck_state(sc_rogue_server, STATE_OK); xasprintf(&sc_rogue_server.output, "No Rogue DHCP Server detected"); @@ -1112,10 +1170,12 @@ mp_subcheck get_results(bool exclusive, const int requested_servers, const struc if (received_requested_address) { sc_rqustd_addr = mp_set_subcheck_state(sc_rqustd_addr, STATE_OK); - xasprintf(&sc_rqustd_addr.output, "Requested address (%s) was offered", inet_ntoa(requested_address)); + xasprintf(&sc_rqustd_addr.output, "Requested address (%s) was offered", + inet_ntoa(requested_address)); } else { sc_rqustd_addr = mp_set_subcheck_state(sc_rqustd_addr, STATE_WARNING); - xasprintf(&sc_rqustd_addr.output, "Requested address (%s) was NOT offered", inet_ntoa(requested_address)); + xasprintf(&sc_rqustd_addr.output, "Requested address (%s) was NOT offered", + inet_ntoa(requested_address)); } mp_add_subcheck_to_subcheck(&sc_dhcp_results, sc_rqustd_addr); @@ -1138,18 +1198,19 @@ process_arguments_wrapper process_arguments(int argc, char **argv) { }; int option_index = 0; - static struct option long_options[] = {{"serverip", required_argument, 0, 's'}, - {"requestedip", required_argument, 0, 'r'}, - {"timeout", required_argument, 0, 't'}, - {"interface", required_argument, 0, 'i'}, - {"mac", required_argument, 0, 'm'}, - {"unicast", no_argument, 0, 'u'}, - {"exclusive", no_argument, 0, 'x'}, - {"verbose", no_argument, 0, 'v'}, - {"version", no_argument, 0, 'V'}, - {"help", no_argument, 0, 'h'}, - {"output-format", required_argument, 0, output_format_index}, - {0, 0, 0, 0}}; + static struct option long_options[] = { + {"serverip", required_argument, 0, 's'}, + {"requestedip", required_argument, 0, 'r'}, + {"timeout", required_argument, 0, 't'}, + {"interface", required_argument, 0, 'i'}, + {"mac", required_argument, 0, 'm'}, + {"unicast", no_argument, 0, 'u'}, + {"exclusive", no_argument, 0, 'x'}, + {"verbose", no_argument, 0, 'v'}, + {"version", no_argument, 0, 'V'}, + {"help", no_argument, 0, 'h'}, + {"output-format", required_argument, 0, output_format_index}, + {0, 0, 0, 0}}; check_dhcp_config config = check_dhcp_config_init(); int option_char = 0; @@ -1163,7 +1224,8 @@ process_arguments_wrapper process_arguments(int argc, char **argv) { switch (option_char) { case 's': /* DHCP server address */ resolve_host(optarg, &config.dhcp_ip); - add_requested_server(config.dhcp_ip, &config.num_of_requested_servers, &config.requested_server_list); + add_requested_server(config.dhcp_ip, &config.num_of_requested_servers, + &config.requested_server_list); break; case 'r': /* address we are requested from DHCP servers */ @@ -1187,7 +1249,8 @@ process_arguments_wrapper process_arguments(int argc, char **argv) { break; case 'i': /* interface name */ - strncpy(config.network_interface_name, optarg, sizeof(config.network_interface_name) - 1); + strncpy(config.network_interface_name, optarg, + sizeof(config.network_interface_name) - 1); config.network_interface_name[sizeof(config.network_interface_name) - 1] = '\x0'; break; @@ -1289,7 +1352,8 @@ static int put_ctrl(int fd, int len, int pri) { ctl.len = len; if (putmsg(fd, &ctl, 0, pri) < 0) { - printf(_("Error: DLPI stream API failed to get MAC in put_ctrl/putmsg(): %s.\n"), strerror(errno)); + printf(_("Error: DLPI stream API failed to get MAC in put_ctrl/putmsg(): %s.\n"), + strerror(errno)); exit(STATE_UNKNOWN); } @@ -1302,7 +1366,8 @@ static int put_both(int fd, int clen, int dlen, int pri) { ctl.len = clen; dat.len = dlen; if (putmsg(fd, &ctl, &dat, pri) < 0) { - printf(_("Error: DLPI stream API failed to get MAC in put_both/putmsg().\n"), strerror(errno)); + printf(_("Error: DLPI stream API failed to get MAC in put_both/putmsg().\n"), + strerror(errno)); exit(STATE_UNKNOWN); } @@ -1314,7 +1379,8 @@ static int dl_open(const char *dev, int unit, int *fd) { dl_attach_req_t *attach_req = (dl_attach_req_t *)ctl_area; if ((*fd = open(dev, O_RDWR)) == -1) { - printf(_("Error: DLPI stream API failed to get MAC in dl_attach_req/open(%s..): %s.\n"), dev, strerror(errno)); + printf(_("Error: DLPI stream API failed to get MAC in dl_attach_req/open(%s..): %s.\n"), + dev, strerror(errno)); exit(STATE_UNKNOWN); } attach_req->dl_primitive = DL_ATTACH_REQ; @@ -1338,7 +1404,8 @@ static int dl_bind(int fd, int sap, u_char *addr) { put_ctrl(fd, sizeof(dl_bind_req_t), 0); get_msg(fd); if (GOT_ERR == check_ctrl(DL_BIND_ACK)) { - printf(_("Error: DLPI stream API failed to get MAC in dl_bind/check_ctrl(): %s.\n"), strerror(errno)); + printf(_("Error: DLPI stream API failed to get MAC in dl_bind/check_ctrl(): %s.\n"), + strerror(errno)); exit(STATE_UNKNOWN); } bcopy((u_char *)bind_ack + bind_ack->dl_addr_offset, addr, bind_ack->dl_addr_length); @@ -1455,7 +1522,8 @@ void print_help(void) { printf(" %s\n", "-u, --unicast"); printf(" %s\n", _("Unicast testing: mimic a DHCP relay, requires -s")); printf(" %s\n", "-x, --exclusive"); - printf(" %s\n", _("Only requested DHCP server may response (rogue DHCP server detection), requires -s")); + printf(" %s\n", + _("Only requested DHCP server may response (rogue DHCP server detection), requires -s")); printf(UT_SUPPORT); } diff --git a/plugins-root/check_icmp.d/config.h b/plugins-root/check_icmp.d/config.h index c348bef5..be388d0a 100644 --- a/plugins-root/check_icmp.d/config.h +++ b/plugins-root/check_icmp.d/config.h @@ -97,7 +97,7 @@ typedef struct icmp_ping_data { /* 80 msec packet interval by default */ // DEPRECATED, remove when removing the option -#define DEFAULT_PKT_INTERVAL 80000 +#define DEFAULT_PKT_INTERVAL 80000 #define DEFAULT_TARGET_INTERVAL 0 diff --git a/plugins-root/pst3.c b/plugins-root/pst3.c index 1f69f3a6..1bfe3d35 100644 --- a/plugins-root/pst3.c +++ b/plugins-root/pst3.c @@ -1,45 +1,45 @@ /***************************************************************************** -* -* pst3 -* -* License: GPL -* Copyright (c) 2008 Monitoring Plugins Development Team -* -* Description: -* -* This file contains the pst3 executable. This is a replacement ps command -* for Solaris to get output which provides a long argument listing, which -* is not possible with the standard ps command (due to truncation). /usr/ucb/ps -* also has issues where some fields run into each other. -* -* This executable works by reading process address structures, so needs -* to be executed as root -* -* Originally written by R.W.Ingraham -* Rewritten by Duncan Ferguson (Altinity Ltd, June 2008) -* The rewrite was necessary as /dev/kmem is not available within -* non-global zones on Solaris 10 -* -* Details for rewrite came from -* source of /usr/ucb/ps on Solaris: -* http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/ucbcmd/ps/ps.c#argvoff -* usenet group posting -* http://groups.google.com/group/comp.unix.solaris/tree/browse_frm/month/2001-09/bfa40c08bac819a2?rnum=141&_done=%2Fgroup%2Fcomp.unix.solaris%2Fbrowse_frm%2Fmonth%2F2001-09%3F -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -*****************************************************************************/ + * + * pst3 + * + * License: GPL + * Copyright (c) 2008 Monitoring Plugins Development Team + * + * Description: + * + * This file contains the pst3 executable. This is a replacement ps command + * for Solaris to get output which provides a long argument listing, which + * is not possible with the standard ps command (due to truncation). /usr/ucb/ps + * also has issues where some fields run into each other. + * + * This executable works by reading process address structures, so needs + * to be executed as root + * + * Originally written by R.W.Ingraham + * Rewritten by Duncan Ferguson (Altinity Ltd, June 2008) + * The rewrite was necessary as /dev/kmem is not available within + * non-global zones on Solaris 10 + * + * Details for rewrite came from + * source of /usr/ucb/ps on Solaris: + * http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/ucbcmd/ps/ps.c#argvoff + * usenet group posting + * http://groups.google.com/group/comp.unix.solaris/tree/browse_frm/month/2001-09/bfa40c08bac819a2?rnum=141&_done=%2Fgroup%2Fcomp.unix.solaris%2Fbrowse_frm%2Fmonth%2F2001-09%3F + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *****************************************************************************/ #include #include @@ -55,14 +55,14 @@ * Constants */ -#define PROC_DIR "/proc" -#define ARGS 30 +#define PROC_DIR "/proc" +#define ARGS 30 /* * Globals */ -static char * szProg; +static char *szProg; /* * Prototypes @@ -71,192 +71,179 @@ void usage(); /*----------------------------------------------------------------------------*/ -int main (int argc, char **argv) -{ - DIR *procdir; - struct dirent *proc; - char ps_name[ARGS]; - char as_name[ARGS]; - psinfo_t psinfo; - - /* Set our program name global */ - if ((szProg = strrchr(argv[0], '/')) != NULL) - szProg++; - else - szProg = argv[0]; - - /* if given any parameters, print out help */ - if(argc > 1) { - (void)usage(); - exit(1); - } - - /* Make sure that our euid is root */ - if (geteuid() != 0) - { - fprintf(stderr, "%s: This program can only be run by the root user!\n", szProg); - exit(1); - } - - if ((procdir = opendir(PROC_DIR)) == NULL) { - fprintf(stderr, "%s: cannot open PROC directory %s\n", szProg, PROC_DIR); - exit(1); - } - - /* Display column headings */ - printf("%c %5s %5s %5s %6s %6s %4s %s %s\n", - 'S', - "UID", - "PID", - "PPID", - "VSZ", - "RSS", - "%CPU", - "COMMAND", - "ARGS" - ); - - /* Zip through all of the process entries */ - while((proc = readdir(procdir))) { - int ps_fd; - int as_fd; - off_t argoff; - int i; - char *args; - char *procname; - char *ptr; - int argslen; - uintptr_t args_addr;; - uintptr_t *args_vecs;; - int args_count; - - if(proc->d_name[0] == '.') - continue; - - sprintf(ps_name,"%s/%s/%s",PROC_DIR,proc->d_name,"psinfo"); - sprintf(as_name,"%s/%s/%s",PROC_DIR,proc->d_name,"as"); -try_again: - if((ps_fd = open(ps_name, O_RDONLY)) == -1) - continue; - - if((as_fd = open(as_name, O_RDONLY)) == -1) { - close(ps_fd); - continue; - } - - if(read(ps_fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo)) { - int err = errno; - close(ps_fd); - close(as_fd); - if(err == EAGAIN) goto try_again; - if(err != ENOENT) - fprintf(stderr, "%s: read() on %s: %s\n", szProg, - ps_name, strerror(err)); - continue; - } - close(ps_fd); - - /* system process, ignore since the previous version did */ - if( - psinfo.pr_nlwp == 0 || - strcmp(psinfo.pr_lwp.pr_clname, "SYS") == 0 - ) { - continue; - } - - /* get the procname to match previous versions */ - procname = strdup(psinfo.pr_psargs); - if((ptr = strchr(procname, ' ')) != NULL) - *ptr = '\0'; - if((ptr = strrchr(procname, '/')) != NULL) - ptr++; - else - ptr = procname; - - /* - * print out what we currently know - */ - printf("%c %5d %5d %5d %6lu %6lu %4.1f %s ", - psinfo.pr_lwp.pr_sname, - psinfo.pr_euid, - psinfo.pr_pid, - psinfo.pr_ppid, - psinfo.pr_size, - psinfo.pr_rssize, - ((float)(psinfo.pr_pctcpu) / 0x8000 * 100.0), - ptr - ); - free(procname); - - /* - * and now for the command line stuff - */ - - args_addr = psinfo.pr_argv; - args_count = psinfo.pr_argc; - args_vecs = malloc(args_count * sizeof(uintptr_t)); - - if(psinfo.pr_dmodel == PR_MODEL_NATIVE) { - /* this process matches target process */ - pread(as_fd,args_vecs, args_count * sizeof(uintptr_t), - args_addr); - } else { - /* this process is 64bit, target process is 32 bit*/ - caddr32_t *args_vecs32 = (caddr32_t *)args_vecs; - pread(as_fd,args_vecs32,args_count * sizeof(caddr32_t), - args_addr); - for (i=args_count-1;i>=0;--i) - args_vecs[i]=args_vecs32[i]; - } - - /* - * now read in the args - if what we read in fills buffer - * resize buffer and reread that bit again - */ - argslen=ARGS; - args=malloc(argslen+1); - for(i=0;i 1) { + (void)usage(); + exit(1); + } + + /* Make sure that our euid is root */ + if (geteuid() != 0) { + fprintf(stderr, "%s: This program can only be run by the root user!\n", szProg); + exit(1); + } + + if ((procdir = opendir(PROC_DIR)) == NULL) { + fprintf(stderr, "%s: cannot open PROC directory %s\n", szProg, PROC_DIR); + exit(1); + } + + /* Display column headings */ + printf("%c %5s %5s %5s %6s %6s %4s %s %s\n", 'S', "UID", "PID", "PPID", "VSZ", "RSS", "%CPU", + "COMMAND", "ARGS"); + + /* Zip through all of the process entries */ + while ((proc = readdir(procdir))) { + int ps_fd; + int as_fd; + off_t argoff; + int i; + char *args; + char *procname; + char *ptr; + int argslen; + uintptr_t args_addr; + ; + uintptr_t *args_vecs; + ; + int args_count; + + if (proc->d_name[0] == '.') { + continue; + } + + sprintf(ps_name, "%s/%s/%s", PROC_DIR, proc->d_name, "psinfo"); + sprintf(as_name, "%s/%s/%s", PROC_DIR, proc->d_name, "as"); + try_again: + if ((ps_fd = open(ps_name, O_RDONLY)) == -1) { + continue; + } + + if ((as_fd = open(as_name, O_RDONLY)) == -1) { + close(ps_fd); + continue; + } + + if (read(ps_fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo)) { + int err = errno; + close(ps_fd); + close(as_fd); + if (err == EAGAIN) { + goto try_again; + } + if (err != ENOENT) { + fprintf(stderr, "%s: read() on %s: %s\n", szProg, ps_name, strerror(err)); + } + continue; + } + close(ps_fd); + + /* system process, ignore since the previous version did */ + if (psinfo.pr_nlwp == 0 || strcmp(psinfo.pr_lwp.pr_clname, "SYS") == 0) { + continue; + } + + /* get the procname to match previous versions */ + procname = strdup(psinfo.pr_psargs); + if ((ptr = strchr(procname, ' ')) != NULL) { + *ptr = '\0'; + } + if ((ptr = strrchr(procname, '/')) != NULL) { + ptr++; + } else { + ptr = procname; + } + + /* + * print out what we currently know + */ + printf("%c %5d %5d %5d %6lu %6lu %4.1f %s ", psinfo.pr_lwp.pr_sname, psinfo.pr_euid, + psinfo.pr_pid, psinfo.pr_ppid, psinfo.pr_size, psinfo.pr_rssize, + ((float)(psinfo.pr_pctcpu) / 0x8000 * 100.0), ptr); + free(procname); + + /* + * and now for the command line stuff + */ + + args_addr = psinfo.pr_argv; + args_count = psinfo.pr_argc; + args_vecs = malloc(args_count * sizeof(uintptr_t)); + + if (psinfo.pr_dmodel == PR_MODEL_NATIVE) { + /* this process matches target process */ + pread(as_fd, args_vecs, args_count * sizeof(uintptr_t), args_addr); + } else { + /* this process is 64bit, target process is 32 bit*/ + caddr32_t *args_vecs32 = (caddr32_t *)args_vecs; + pread(as_fd, args_vecs32, args_count * sizeof(caddr32_t), args_addr); + for (i = args_count - 1; i >= 0; --i) { + args_vecs[i] = args_vecs32[i]; + } + } + + /* + * now read in the args - if what we read in fills buffer + * resize buffer and reread that bit again + */ + argslen = ARGS; + args = malloc(argslen + 1); + for (i = 0; i < args_count; i++) { + memset(args, '\0', argslen + 1); + if (pread(as_fd, args, argslen, args_vecs[i]) <= 0) { + break; + } + args[argslen] = '\0'; + if (strlen(args) == argslen) { + argslen += ARGS; + args = realloc(args, argslen + 1); + i--; + continue; + } + printf(" %s", args); + } + free(args_vecs); + free(args); + close(as_fd); + printf("\n"); + } + + (void)closedir(procdir); + + return (0); } /*----------------------------------------------------------------------------*/ void usage() { - printf("%s: Help output\n\n", szProg); - printf("If this program is given any arguments, this help is displayed.\n"); - printf("This command is used to print out the full command line for all\n"); - printf("running processes because /usr/bin/ps is limited to 80 chars and\n"); - printf("/usr/ucb/ps can merge columns together.\n\n"); - printf("Columns are:\n"); - printf("\tS - State of process - see 'ps' man page\n"); - printf("\tUID - UID of the process owner\n"); - printf("\tPID - PID of the process\n"); - printf("\tPPID - PID of the parent process\n"); - printf("\tVSZ - Virtual memory usage (kilobytes)\n"); - printf("\tRSS - Real memory usage (kilobytes)\n"); - printf("\t%%CPU - CPU usage\n"); - printf("\tCOMMAND - Command being run\n"); - printf("\tARGS - Full command line with arguments\n"); - return; + printf("%s: Help output\n\n", szProg); + printf("If this program is given any arguments, this help is displayed.\n"); + printf("This command is used to print out the full command line for all\n"); + printf("running processes because /usr/bin/ps is limited to 80 chars and\n"); + printf("/usr/ucb/ps can merge columns together.\n\n"); + printf("Columns are:\n"); + printf("\tS - State of process - see 'ps' man page\n"); + printf("\tUID - UID of the process owner\n"); + printf("\tPID - PID of the process\n"); + printf("\tPPID - PID of the parent process\n"); + printf("\tVSZ - Virtual memory usage (kilobytes)\n"); + printf("\tRSS - Real memory usage (kilobytes)\n"); + printf("\t%%CPU - CPU usage\n"); + printf("\tCOMMAND - Command being run\n"); + printf("\tARGS - Full command line with arguments\n"); + return; } diff --git a/plugins/check_by_ssh.c b/plugins/check_by_ssh.c index 2bc38d49..74b7a46f 100644 --- a/plugins/check_by_ssh.c +++ b/plugins/check_by_ssh.c @@ -45,7 +45,8 @@ typedef struct { check_by_ssh_config config; } check_by_ssh_config_wrapper; static check_by_ssh_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); -static check_by_ssh_config_wrapper validate_arguments(check_by_ssh_config_wrapper /*config_wrapper*/); +static check_by_ssh_config_wrapper + validate_arguments(check_by_ssh_config_wrapper /*config_wrapper*/); static command_construct comm_append(command_construct /*cmd*/, const char * /*str*/); static void print_help(void); @@ -90,7 +91,8 @@ int main(int argc, char **argv) { /* SSH returns 255 if connection attempt fails; include the first line of error output */ if (result == 255 && config.unknown_timeout) { - printf(_("SSH connection failed: %s\n"), chld_err.lines > 0 ? chld_err.line[0] : "(no error output)"); + printf(_("SSH connection failed: %s\n"), + chld_err.lines > 0 ? chld_err.line[0] : "(no error output)"); return STATE_UNKNOWN; } @@ -134,7 +136,8 @@ int main(int argc, char **argv) { puts(chld_out.line[i]); } } else { - printf(_("%s - check_by_ssh: Remote command '%s' returned status %d\n"), state_text(result), config.remotecmd, result); + printf(_("%s - check_by_ssh: Remote command '%s' returned status %d\n"), + state_text(result), config.remotecmd, result); } return result; /* return error status from remote command */ } @@ -160,9 +163,11 @@ int main(int argc, char **argv) { die(STATE_UNKNOWN, _("%s: Error parsing output\n"), progname); } - if (config.service[commands] && status_text && sscanf(chld_out.line[i], "STATUS CODE: %d", &cresult) == 1) { - fprintf(file_pointer, "[%d] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n", (int)local_time, config.host_shortname, - config.service[commands++], cresult, status_text); + if (config.service[commands] && status_text && + sscanf(chld_out.line[i], "STATUS CODE: %d", &cresult) == 1) { + fprintf(file_pointer, "[%d] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n", + (int)local_time, config.host_shortname, config.service[commands++], cresult, + status_text); } } @@ -172,34 +177,35 @@ int main(int argc, char **argv) { /* process command-line arguments */ check_by_ssh_config_wrapper process_arguments(int argc, char **argv) { - static struct option longopts[] = {{"version", no_argument, 0, 'V'}, - {"help", no_argument, 0, 'h'}, - {"verbose", no_argument, 0, 'v'}, - {"fork", no_argument, 0, 'f'}, - {"timeout", required_argument, 0, 't'}, - {"unknown-timeout", no_argument, 0, 'U'}, - {"host", required_argument, 0, 'H'}, /* backward compatibility */ - {"hostname", required_argument, 0, 'H'}, - {"port", required_argument, 0, 'p'}, - {"output", required_argument, 0, 'O'}, - {"name", required_argument, 0, 'n'}, - {"services", required_argument, 0, 's'}, - {"identity", required_argument, 0, 'i'}, - {"user", required_argument, 0, 'u'}, - {"logname", required_argument, 0, 'l'}, - {"command", required_argument, 0, 'C'}, - {"skip", optional_argument, 0, 'S'}, /* backwards compatibility */ - {"skip-stdout", optional_argument, 0, 'S'}, - {"skip-stderr", optional_argument, 0, 'E'}, - {"warn-on-stderr", no_argument, 0, 'W'}, - {"proto1", no_argument, 0, '1'}, - {"proto2", no_argument, 0, '2'}, - {"use-ipv4", no_argument, 0, '4'}, - {"use-ipv6", no_argument, 0, '6'}, - {"ssh-option", required_argument, 0, 'o'}, - {"quiet", no_argument, 0, 'q'}, - {"configfile", optional_argument, 0, 'F'}, - {0, 0, 0, 0}}; + static struct option longopts[] = { + {"version", no_argument, 0, 'V'}, + {"help", no_argument, 0, 'h'}, + {"verbose", no_argument, 0, 'v'}, + {"fork", no_argument, 0, 'f'}, + {"timeout", required_argument, 0, 't'}, + {"unknown-timeout", no_argument, 0, 'U'}, + {"host", required_argument, 0, 'H'}, /* backward compatibility */ + {"hostname", required_argument, 0, 'H'}, + {"port", required_argument, 0, 'p'}, + {"output", required_argument, 0, 'O'}, + {"name", required_argument, 0, 'n'}, + {"services", required_argument, 0, 's'}, + {"identity", required_argument, 0, 'i'}, + {"user", required_argument, 0, 'u'}, + {"logname", required_argument, 0, 'l'}, + {"command", required_argument, 0, 'C'}, + {"skip", optional_argument, 0, 'S'}, /* backwards compatibility */ + {"skip-stdout", optional_argument, 0, 'S'}, + {"skip-stderr", optional_argument, 0, 'E'}, + {"warn-on-stderr", no_argument, 0, 'W'}, + {"proto1", no_argument, 0, '1'}, + {"proto2", no_argument, 0, '2'}, + {"use-ipv4", no_argument, 0, '4'}, + {"use-ipv6", no_argument, 0, '6'}, + {"ssh-option", required_argument, 0, 'o'}, + {"quiet", no_argument, 0, 'q'}, + {"configfile", optional_argument, 0, 'F'}, + {0, 0, 0, 0}}; check_by_ssh_config_wrapper result = { .errorcode = OK, @@ -221,7 +227,8 @@ check_by_ssh_config_wrapper process_arguments(int argc, char **argv) { int option = 0; while (true) { - int opt_index = getopt_long(argc, argv, "Vvh1246fqt:UH:O:p:i:u:l:C:S::E::n:s:o:F:", longopts, &option); + int opt_index = + getopt_long(argc, argv, "Vvh1246fqt:UH:O:p:i:u:l:C:S::E::n:s:o:F:", longopts, &option); if (opt_index == -1 || opt_index == EOF) { break; @@ -266,11 +273,13 @@ check_by_ssh_config_wrapper process_arguments(int argc, char **argv) { char *p2; p1 = optarg; - result.config.service = realloc(result.config.service, (++result.config.number_of_services) * sizeof(char *)); + result.config.service = realloc(result.config.service, + (++result.config.number_of_services) * sizeof(char *)); while ((p2 = index(p1, ':'))) { *p2 = '\0'; result.config.service[result.config.number_of_services - 1] = p1; - result.config.service = realloc(result.config.service, (++result.config.number_of_services) * sizeof(char *)); + result.config.service = realloc( + result.config.service, (++result.config.number_of_services) * sizeof(char *)); p1 = p2 + 1; } result.config.service[result.config.number_of_services - 1] = p1; @@ -309,7 +318,8 @@ check_by_ssh_config_wrapper process_arguments(int argc, char **argv) { case 'C': /* Command for remote machine */ result.config.commands++; if (result.config.commands > 1) { - xasprintf(&result.config.remotecmd, "%s;echo STATUS CODE: $?;", result.config.remotecmd); + xasprintf(&result.config.remotecmd, "%s;echo STATUS CODE: $?;", + result.config.remotecmd); } xasprintf(&result.config.remotecmd, "%s%s", result.config.remotecmd, optarg); break; @@ -396,7 +406,8 @@ command_construct comm_append(command_construct cmd, const char *str) { die(STATE_UNKNOWN, _("%s: Argument limit of %d exceeded\n"), progname, NP_MAXARGS); } - if ((cmd.commargv = (char **)realloc(cmd.commargv, (cmd.commargc + 1) * sizeof(char *))) == NULL) { + if ((cmd.commargv = (char **)realloc(cmd.commargv, (cmd.commargc + 1) * sizeof(char *))) == + NULL) { die(STATE_UNKNOWN, _("Can not (re)allocate 'commargv' buffer\n")); } @@ -412,12 +423,18 @@ check_by_ssh_config_wrapper validate_arguments(check_by_ssh_config_wrapper confi return config_wrapper; } - if (config_wrapper.config.passive && config_wrapper.config.commands != config_wrapper.config.number_of_services) { - die(STATE_UNKNOWN, _("%s: In passive mode, you must provide a service name for each command.\n"), progname); + if (config_wrapper.config.passive && + config_wrapper.config.commands != config_wrapper.config.number_of_services) { + die(STATE_UNKNOWN, + _("%s: In passive mode, you must provide a service name for each command.\n"), + progname); } if (config_wrapper.config.passive && config_wrapper.config.host_shortname == NULL) { - die(STATE_UNKNOWN, _("%s: In passive mode, you must provide the host short name from the monitoring configs.\n"), progname); + die(STATE_UNKNOWN, + _("%s: In passive mode, you must provide the host short name from the monitoring " + "configs.\n"), + progname); } return config_wrapper; @@ -454,7 +471,8 @@ void print_help(void) { printf(" %s\n", "-W, --warn-on-stderr]"); printf(" %s\n", _("Exit with an warning, if there is an output on STDERR")); printf(" %s\n", "-f"); - printf(" %s\n", _("tells ssh to fork rather than create a tty [optional]. This will always return OK if ssh is executed")); + printf(" %s\n", _("tells ssh to fork rather than create a tty [optional]. This will always " + "return OK if ssh is executed")); printf(" %s\n", "-C, --command='COMMAND STRING'"); printf(" %s\n", _("command to execute on the remote machine")); printf(" %s\n", "-l, --logname=USERNAME"); @@ -490,7 +508,9 @@ void print_help(void) { printf(" %s\n", _("all of -O, -s, and -n options (servicelist order must match '-C'options)")); printf("\n"); printf("%s\n", _("Examples:")); - printf(" %s\n", "$ check_by_ssh -H localhost -n lh -s c1:c2:c3 -C uptime -C uptime -C uptime -O /tmp/foo"); + printf( + " %s\n", + "$ check_by_ssh -H localhost -n lh -s c1:c2:c3 -C uptime -C uptime -C uptime -O /tmp/foo"); printf(" %s\n", "$ cat /tmp/foo"); printf(" %s\n", "[1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c1;0; up 2 days"); printf(" %s\n", "[1080933700] PROCESS_SERVICE_CHECK_RESULT;flint;c2;0; up 2 days"); diff --git a/plugins/check_cluster.c b/plugins/check_cluster.c index 9b695499..373520ee 100644 --- a/plugins/check_cluster.c +++ b/plugins/check_cluster.c @@ -112,25 +112,30 @@ int main(int argc, char **argv) { int return_code = STATE_OK; /* return the status of the cluster */ if (config.check_type == CHECK_SERVICES) { - return_code = get_status(total_services_warning + total_services_unknown + total_services_critical, config.thresholds); - printf("CLUSTER %s: %s: %d ok, %d warning, %d unknown, %d critical\n", state_text(return_code), - (config.label == NULL) ? "Service cluster" : config.label, total_services_ok, total_services_warning, total_services_unknown, + return_code = + get_status(total_services_warning + total_services_unknown + total_services_critical, + config.thresholds); + printf("CLUSTER %s: %s: %d ok, %d warning, %d unknown, %d critical\n", + state_text(return_code), (config.label == NULL) ? "Service cluster" : config.label, + total_services_ok, total_services_warning, total_services_unknown, total_services_critical); } else { return_code = get_status(total_hosts_down + total_hosts_unreachable, config.thresholds); printf("CLUSTER %s: %s: %d up, %d down, %d unreachable\n", state_text(return_code), - (config.label == NULL) ? "Host cluster" : config.label, total_hosts_up, total_hosts_down, total_hosts_unreachable); + (config.label == NULL) ? "Host cluster" : config.label, total_hosts_up, + total_hosts_down, total_hosts_unreachable); } exit(return_code); } check_cluster_config_wrapper process_arguments(int argc, char **argv) { - static struct option longopts[] = {{"data", required_argument, 0, 'd'}, {"warning", required_argument, 0, 'w'}, - {"critical", required_argument, 0, 'c'}, {"label", required_argument, 0, 'l'}, - {"host", no_argument, 0, 'h'}, {"service", no_argument, 0, 's'}, - {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, - {"help", no_argument, 0, 'H'}, {0, 0, 0, 0}}; + static struct option longopts[] = { + {"data", required_argument, 0, 'd'}, {"warning", required_argument, 0, 'w'}, + {"critical", required_argument, 0, 'c'}, {"label", required_argument, 0, 'l'}, + {"host", no_argument, 0, 'h'}, {"service", no_argument, 0, 's'}, + {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, + {"help", no_argument, 0, 'H'}, {0, 0, 0, 0}}; check_cluster_config_wrapper result = { .errorcode = OK, @@ -251,7 +256,8 @@ void print_help(void) { printf("\n"); printf("%s\n", _("Examples:")); printf(" %s\n", "check_cluster -s -d 2,0,2,0 -c @3:"); - printf(" %s\n", _("Will alert critical if there are 3 or more service data points in a non-OK")); + printf(" %s\n", + _("Will alert critical if there are 3 or more service data points in a non-OK")); printf(" %s\n", _("state.")); printf(UT_SUPPORT); diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c index 9efcd1cb..468ded31 100644 --- a/plugins/check_dbi.c +++ b/plugins/check_dbi.c @@ -71,8 +71,9 @@ static double timediff(struct timeval /*start*/, struct timeval /*end*/); static void np_dbi_print_error(dbi_conn /*conn*/, char * /*fmt*/, ...); -static mp_state_enum do_query(dbi_conn /*conn*/, const char ** /*res_val_str*/, double * /*res_val*/, double * /*res_time*/, mp_dbi_metric /*metric*/, - mp_dbi_type /*type*/, char * /*np_dbi_query*/); +static mp_state_enum do_query(dbi_conn /*conn*/, const char ** /*res_val_str*/, + double * /*res_val*/, double * /*res_time*/, mp_dbi_metric /*metric*/, + mp_dbi_type /*type*/, char * /*np_dbi_query*/); int main(int argc, char **argv) { int status = STATE_UNKNOWN; @@ -118,7 +119,8 @@ int main(int argc, char **argv) { dbi_inst *instance_p = {0}; if (dbi_initialize_r(NULL, instance_p) < 0) { - printf("UNKNOWN - failed to initialize DBI; possibly you don't have any drivers installed.\n"); + printf( + "UNKNOWN - failed to initialize DBI; possibly you don't have any drivers installed.\n"); return STATE_UNKNOWN; } @@ -133,10 +135,12 @@ int main(int argc, char **argv) { driver = dbi_driver_open_r(config.dbi_driver, instance_p); if (!driver) { - printf("UNKNOWN - failed to open DBI driver '%s'; possibly it's not installed.\n", config.dbi_driver); + printf("UNKNOWN - failed to open DBI driver '%s'; possibly it's not installed.\n", + config.dbi_driver); printf("Known drivers:\n"); - for (driver = dbi_driver_list_r(NULL, instance_p); driver; driver = dbi_driver_list_r(driver, instance_p)) { + for (driver = dbi_driver_list_r(NULL, instance_p); driver; + driver = dbi_driver_list_r(driver, instance_p)) { printf(" - %s\n", dbi_driver_get_name(driver)); } return STATE_UNKNOWN; @@ -156,7 +160,8 @@ int main(int argc, char **argv) { const char *opt; if (verbose > 1) { - printf("Setting DBI driver option '%s' to '%s'\n", config.dbi_options[i].key, config.dbi_options[i].value); + printf("Setting DBI driver option '%s' to '%s'\n", config.dbi_options[i].key, + config.dbi_options[i].value); } if (!dbi_conn_set_option(conn, config.dbi_options[i].key, config.dbi_options[i].value)) { @@ -164,10 +169,12 @@ int main(int argc, char **argv) { } /* else: status != 0 */ - np_dbi_print_error(conn, "UNKNOWN - failed to set option '%s' to '%s'", config.dbi_options[i].key, config.dbi_options[i].value); + np_dbi_print_error(conn, "UNKNOWN - failed to set option '%s' to '%s'", + config.dbi_options[i].key, config.dbi_options[i].value); printf("Known driver options:\n"); - for (opt = dbi_conn_get_option_list(conn, NULL); opt; opt = dbi_conn_get_option_list(conn, opt)) { + for (opt = dbi_conn_get_option_list(conn, NULL); opt; + opt = dbi_conn_get_option_list(conn, opt)) { printf(" - %s\n", opt); } dbi_conn_close(conn); @@ -230,14 +237,16 @@ int main(int argc, char **argv) { } if (dbi_conn_select_db(conn, config.dbi_database)) { - np_dbi_print_error(conn, "UNKNOWN - failed to select database '%s'", config.dbi_database); + np_dbi_print_error(conn, "UNKNOWN - failed to select database '%s'", + config.dbi_database); return STATE_UNKNOWN; } } if (config.dbi_query) { /* execute query */ - status = do_query(conn, &query_val_str, &query_val, &query_time, config.metric, config.type, config.dbi_query); + status = do_query(conn, &query_val_str, &query_val, &query_time, config.metric, config.type, + config.dbi_query); if (status != STATE_OK) { /* do_query prints an error message in this case */ return status; @@ -281,7 +290,8 @@ int main(int argc, char **argv) { /* In case of METRIC_QUERY_RESULT, isnan(query_val) indicates an error * which should have been reported and handled (abort) before * ... unless we expected a string to be returned */ - assert((config.metric != METRIC_QUERY_RESULT) || (!isnan(query_val)) || (config.type == TYPE_STRING)); + assert((config.metric != METRIC_QUERY_RESULT) || (!isnan(query_val)) || + (config.type == TYPE_STRING)); assert((config.type != TYPE_STRING) || (config.expect || config.expect_re_str)); @@ -289,12 +299,14 @@ int main(int argc, char **argv) { if (config.dbi_query) { if (config.type == TYPE_STRING) { assert(config.expect || config.expect_re_str); - printf(", '%s' returned '%s' in %fs", config.dbi_query, query_val_str ? query_val_str : "", query_time); + printf(", '%s' returned '%s' in %fs", config.dbi_query, + query_val_str ? query_val_str : "", query_time); if (status != STATE_OK) { if (config.expect) { printf(" (expected '%s')", config.expect); } else if (config.expect_re_str) { - printf(" (expected regex /%s/%s)", config.expect_re_str, ((config.expect_re_cflags & REG_ICASE) ? "i" : "")); + printf(" (expected regex /%s/%s)", config.expect_re_str, + ((config.expect_re_cflags & REG_ICASE) ? "i" : "")); } } } else if (isnan(query_val)) { @@ -304,18 +316,31 @@ int main(int argc, char **argv) { } } - printf(" | conntime=%fs;%s;%s;0; server_version=%u;%s;%s;0;", conn_time, - ((config.metric == METRIC_CONN_TIME) && config.warning_range) ? config.warning_range : "", - ((config.metric == METRIC_CONN_TIME) && config.critical_range) ? config.critical_range : "", server_version, - ((config.metric == METRIC_SERVER_VERSION) && config.warning_range) ? config.warning_range : "", - ((config.metric == METRIC_SERVER_VERSION) && config.critical_range) ? config.critical_range : ""); + printf( + " | conntime=%fs;%s;%s;0; server_version=%u;%s;%s;0;", conn_time, + ((config.metric == METRIC_CONN_TIME) && config.warning_range) ? config.warning_range : "", + ((config.metric == METRIC_CONN_TIME) && config.critical_range) ? config.critical_range : "", + server_version, + ((config.metric == METRIC_SERVER_VERSION) && config.warning_range) ? config.warning_range + : "", + ((config.metric == METRIC_SERVER_VERSION) && config.critical_range) ? config.critical_range + : ""); if (config.dbi_query) { if (!isnan(query_val)) { /* this is also true when -e is used */ - printf(" query=%f;%s;%s;;", query_val, ((config.metric == METRIC_QUERY_RESULT) && config.warning_range) ? config.warning_range : "", - ((config.metric == METRIC_QUERY_RESULT) && config.critical_range) ? config.critical_range : ""); + printf(" query=%f;%s;%s;;", query_val, + ((config.metric == METRIC_QUERY_RESULT) && config.warning_range) + ? config.warning_range + : "", + ((config.metric == METRIC_QUERY_RESULT) && config.critical_range) + ? config.critical_range + : ""); } - printf(" querytime=%fs;%s;%s;0;", query_time, ((config.metric == METRIC_QUERY_TIME) && config.warning_range) ? config.warning_range : "", - ((config.metric == METRIC_QUERY_TIME) && config.critical_range) ? config.critical_range : ""); + printf(" querytime=%fs;%s;%s;0;", query_time, + ((config.metric == METRIC_QUERY_TIME) && config.warning_range) ? config.warning_range + : "", + ((config.metric == METRIC_QUERY_TIME) && config.critical_range) + ? config.critical_range + : ""); } printf("\n"); return status; @@ -442,7 +467,8 @@ check_dbi_config_wrapper process_arguments(int argc, char **argv) { *value = '\0'; ++value; - new = realloc(result.config.dbi_options, (result.config.dbi_options_num + 1) * sizeof(*new)); + new = realloc(result.config.dbi_options, + (result.config.dbi_options_num + 1) * sizeof(*new)); if (!new) { printf("UNKNOWN - failed to reallocate memory\n"); exit(STATE_UNKNOWN); @@ -464,7 +490,8 @@ check_dbi_config_wrapper process_arguments(int argc, char **argv) { } } - set_thresholds(&result.config.dbi_thresholds, result.config.warning_range, result.config.critical_range); + set_thresholds(&result.config.dbi_thresholds, result.config.warning_range, + result.config.critical_range); return validate_arguments(result); } @@ -474,21 +501,28 @@ check_dbi_config_wrapper validate_arguments(check_dbi_config_wrapper config_wrap usage("Must specify a DBI driver"); } - if (((config_wrapper.config.metric == METRIC_QUERY_RESULT) || (config_wrapper.config.metric == METRIC_QUERY_TIME)) && + if (((config_wrapper.config.metric == METRIC_QUERY_RESULT) || + (config_wrapper.config.metric == METRIC_QUERY_TIME)) && (!config_wrapper.config.dbi_query)) { usage("Must specify a query to execute (metric == QUERY_RESULT)"); } - if ((config_wrapper.config.metric != METRIC_CONN_TIME) && (config_wrapper.config.metric != METRIC_SERVER_VERSION) && - (config_wrapper.config.metric != METRIC_QUERY_RESULT) && (config_wrapper.config.metric != METRIC_QUERY_TIME)) { + if ((config_wrapper.config.metric != METRIC_CONN_TIME) && + (config_wrapper.config.metric != METRIC_SERVER_VERSION) && + (config_wrapper.config.metric != METRIC_QUERY_RESULT) && + (config_wrapper.config.metric != METRIC_QUERY_TIME)) { usage("Invalid metric specified"); } - if (config_wrapper.config.expect && (config_wrapper.config.warning_range || config_wrapper.config.critical_range || config_wrapper.config.expect_re_str)) { + if (config_wrapper.config.expect && + (config_wrapper.config.warning_range || config_wrapper.config.critical_range || + config_wrapper.config.expect_re_str)) { usage("Do not mix -e and -w/-c/-r/-R"); } - if (config_wrapper.config.expect_re_str && (config_wrapper.config.warning_range || config_wrapper.config.critical_range || config_wrapper.config.expect)) { + if (config_wrapper.config.expect_re_str && + (config_wrapper.config.warning_range || config_wrapper.config.critical_range || + config_wrapper.config.expect)) { usage("Do not mix -r/-R and -w/-c/-e"); } @@ -496,7 +530,8 @@ check_dbi_config_wrapper validate_arguments(check_dbi_config_wrapper config_wrap usage("Option -e requires metric QUERY_RESULT"); } - if (config_wrapper.config.expect_re_str && (config_wrapper.config.metric != METRIC_QUERY_RESULT)) { + if (config_wrapper.config.expect_re_str && + (config_wrapper.config.metric != METRIC_QUERY_RESULT)) { usage("Options -r/-R require metric QUERY_RESULT"); } @@ -607,7 +642,8 @@ void print_usage(void) { printf(" [-e ] [-r|-R ]\n"); } -const char *get_field_str(dbi_conn conn, dbi_result res, unsigned short field_type, mp_dbi_metric metric, mp_dbi_type type) { +const char *get_field_str(dbi_conn conn, dbi_result res, unsigned short field_type, + mp_dbi_metric metric, mp_dbi_type type) { const char *str; if (field_type != DBI_TYPE_STRING) { @@ -630,7 +666,8 @@ const char *get_field_str(dbi_conn conn, dbi_result res, unsigned short field_ty return str; } -double get_field(dbi_conn conn, dbi_result res, unsigned short *field_type, mp_dbi_metric metric, mp_dbi_type type) { +double get_field(dbi_conn conn, dbi_result res, unsigned short *field_type, mp_dbi_metric metric, + mp_dbi_type type) { double val = NAN; if (*field_type == DBI_TYPE_INTEGER) { @@ -679,7 +716,8 @@ double get_field(dbi_conn conn, dbi_result res, unsigned short *field_type, mp_d return val; } -mp_state_enum get_query_result(dbi_conn conn, dbi_result res, const char **res_val_str, double *res_val, mp_dbi_metric metric, mp_dbi_type type) { +mp_state_enum get_query_result(dbi_conn conn, dbi_result res, const char **res_val_str, + double *res_val, mp_dbi_metric metric, mp_dbi_type type) { unsigned short field_type; double val = NAN; @@ -747,8 +785,8 @@ mp_state_enum get_query_result(dbi_conn conn, dbi_result res, const char **res_v return STATE_OK; } -mp_state_enum do_query(dbi_conn conn, const char **res_val_str, double *res_val, double *res_time, mp_dbi_metric metric, mp_dbi_type type, - char *np_dbi_query) { +mp_state_enum do_query(dbi_conn conn, const char **res_val_str, double *res_val, double *res_time, + mp_dbi_metric metric, mp_dbi_type type, char *np_dbi_query) { dbi_result res; struct timeval timeval_start; diff --git a/plugins/check_dig.c b/plugins/check_dig.c index d0903be2..c27e5f13 100644 --- a/plugins/check_dig.c +++ b/plugins/check_dig.c @@ -81,8 +81,9 @@ int main(int argc, char **argv) { char *command_line; /* get the command to run */ - xasprintf(&command_line, "%s %s %s -p %d @%s %s %s +retry=%d +time=%d", PATH_TO_DIG, config.dig_args, config.query_transport, - config.server_port, config.dns_server, config.query_address, config.record_type, config.number_tries, timeout_interval_dig); + xasprintf(&command_line, "%s %s %s -p %d @%s %s %s +retry=%d +time=%d", PATH_TO_DIG, + config.dig_args, config.query_transport, config.server_port, config.dns_server, + config.query_address, config.record_type, config.number_tries, timeout_interval_dig); alarm(timeout_interval); struct timeval start_time; @@ -118,8 +119,9 @@ int main(int argc, char **argv) { printf("%s\n", chld_out.line[i]); } - if (strcasestr(chld_out.line[i], (config.expected_address == NULL ? config.query_address : config.expected_address)) != - NULL) { + if (strcasestr(chld_out.line[i], (config.expected_address == NULL + ? config.query_address + : config.expected_address)) != NULL) { msg = chld_out.line[i]; result = STATE_OK; @@ -174,8 +176,9 @@ int main(int argc, char **argv) { printf("DNS %s - %.3f seconds response time (%s)|%s\n", state_text(result), elapsed_time, msg ? msg : _("Probably a non-existent host/domain"), - fperfdata("time", elapsed_time, "s", (config.warning_interval > UNDEFINED), config.warning_interval, - (config.critical_interval > UNDEFINED), config.critical_interval, true, 0, false, 0)); + fperfdata("time", elapsed_time, "s", (config.warning_interval > UNDEFINED), + config.warning_interval, (config.critical_interval > UNDEFINED), + config.critical_interval, true, 0, false, 0)); exit(result); } @@ -335,7 +338,8 @@ void print_help(void) { printf(" %s\n", "-T, --record_type=STRING"); printf(" %s\n", _("Record type to lookup (default: A)")); printf(" %s\n", "-a, --expected_address=STRING"); - printf(" %s\n", _("An address expected to be in the answer section. If not set, uses whatever")); + printf(" %s\n", + _("An address expected to be in the answer section. If not set, uses whatever")); printf(" %s\n", _("was in -l")); printf(" %s\n", "-A, --dig-arguments=STRING"); printf(" %s\n", _("Pass STRING as argument(s) to dig")); diff --git a/plugins/check_disk.c b/plugins/check_disk.c index 515ddff0..d42b5486 100644 --- a/plugins/check_disk.c +++ b/plugins/check_disk.c @@ -78,18 +78,21 @@ typedef struct { } check_disk_config_wrapper; static check_disk_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); -static void set_all_thresholds(parameter_list_elem *path, char *warn_freespace_units, char *crit_freespace_units, - char *warn_freespace_percent, char *crit_freespace_percent, char *warn_freeinodes_percent, +static void set_all_thresholds(parameter_list_elem *path, char *warn_freespace_units, + char *crit_freespace_units, char *warn_freespace_percent, + char *crit_freespace_percent, char *warn_freeinodes_percent, char *crit_freeinodes_percent); static double calculate_percent(uintmax_t /*value*/, uintmax_t /*total*/); static bool stat_path(parameter_list_elem * /*parameters*/, bool /*ignore_missing*/); /* - * Puts the values from a struct fs_usage into a parameter_list with an additional flag to control how reserved - * and inodes should be judged (ignored or not) + * Puts the values from a struct fs_usage into a parameter_list with an additional flag to control + * how reserved and inodes should be judged (ignored or not) */ -static parameter_list_elem get_path_stats(parameter_list_elem parameters, struct fs_usage fsp, bool freespace_ignore_reserved); -static mp_subcheck evaluate_filesystem(measurement_unit measurement_unit, bool display_inodes_perfdata, byte_unit unit); +static parameter_list_elem get_path_stats(parameter_list_elem parameters, struct fs_usage fsp, + bool freespace_ignore_reserved); +static mp_subcheck evaluate_filesystem(measurement_unit measurement_unit, + bool display_inodes_perfdata, byte_unit unit); void print_usage(void); static void print_help(void); @@ -111,7 +114,6 @@ const byte_unit TeraBytes_factor = 1000000000000; const byte_unit PetaBytes_factor = 1000000000000000; const byte_unit ExaBytes_factor = 1000000000000000000; - int main(int argc, char **argv) { setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); @@ -140,7 +142,8 @@ int main(int argc, char **argv) { } if (!config.path_ignored) { - mp_int_fs_list_set_best_match(config.path_select_list, config.mount_list, config.exact_match); + mp_int_fs_list_set_best_match(config.path_select_list, config.mount_list, + config.exact_match); } // Error if no match found for specified paths @@ -203,20 +206,23 @@ int main(int argc, char **argv) { } if (path->group == NULL) { - if (config.fs_exclude_list && np_find_regmatch(config.fs_exclude_list, mount_entry->me_type)) { + if (config.fs_exclude_list && + np_find_regmatch(config.fs_exclude_list, mount_entry->me_type)) { // Skip excluded fs's path = mp_int_fs_list_del(&config.path_select_list, path); continue; } - if (config.device_path_exclude_list && (np_find_name(config.device_path_exclude_list, mount_entry->me_devname) || - np_find_name(config.device_path_exclude_list, mount_entry->me_mountdir))) { + if (config.device_path_exclude_list && + (np_find_name(config.device_path_exclude_list, mount_entry->me_devname) || + np_find_name(config.device_path_exclude_list, mount_entry->me_mountdir))) { // Skip excluded device or mount paths path = mp_int_fs_list_del(&config.path_select_list, path); continue; } - if (config.fs_include_list && !np_find_regmatch(config.fs_include_list, mount_entry->me_type)) { + if (config.fs_include_list && + !np_find_regmatch(config.fs_include_list, mount_entry->me_type)) { // Skip not included fstypes path = mp_int_fs_list_del(&config.path_select_list, path); continue; @@ -259,8 +265,8 @@ int main(int argc, char **argv) { if (verbose >= 3) { printf("For %s, used_units=%lu free_units=%lu total_units=%lu " "fsp.fsu_blocksize=%lu\n", - mount_entry->me_mountdir, filesystem->used_bytes, filesystem->free_bytes, filesystem->total_bytes, - fsp.fsu_blocksize); + mount_entry->me_mountdir, filesystem->used_bytes, filesystem->free_bytes, + filesystem->total_bytes, fsp.fsu_blocksize); } } else { // failed to retrieve file system data or not mounted? @@ -285,12 +291,14 @@ int main(int argc, char **argv) { measurement_unit_list *measurements = NULL; measurement_unit_list *current = NULL; // create measuring units, because of groups - for (parameter_list_elem *filesystem = config.path_select_list.first; filesystem; filesystem = mp_int_fs_list_get_next(filesystem)) { + for (parameter_list_elem *filesystem = config.path_select_list.first; filesystem; + filesystem = mp_int_fs_list_get_next(filesystem)) { assert(filesystem->best_match != NULL); if (filesystem->group == NULL) { // create a measurement unit for the fs - measurement_unit unit = create_measurement_unit_from_filesystem(*filesystem, config.display_mntp); + measurement_unit unit = + create_measurement_unit_from_filesystem(*filesystem, config.display_mntp); if (measurements == NULL) { measurements = current = add_measurement_list(NULL, unit); } else { @@ -300,14 +308,17 @@ int main(int argc, char **argv) { // Grouped elements are consecutive if (measurements == NULL) { // first entry - measurement_unit unit = create_measurement_unit_from_filesystem(*filesystem, config.display_mntp); + measurement_unit unit = + create_measurement_unit_from_filesystem(*filesystem, config.display_mntp); unit.name = strdup(filesystem->group); measurements = current = add_measurement_list(NULL, unit); } else { - // if this is the first element of a group, the name of the previous entry is different + // if this is the first element of a group, the name of the previous entry is + // different if (strcmp(filesystem->group, current->unit.name) != 0) { // so, this must be the first element of a group - measurement_unit unit = create_measurement_unit_from_filesystem(*filesystem, config.display_mntp); + measurement_unit unit = + create_measurement_unit_from_filesystem(*filesystem, config.display_mntp); unit.name = filesystem->group; current = add_measurement_list(measurements, unit); @@ -322,7 +333,8 @@ int main(int argc, char **argv) { /* Process for every path in list */ if (measurements != NULL) { for (measurement_unit_list *unit = measurements; unit; unit = unit->next) { - mp_subcheck unit_sc = evaluate_filesystem(unit->unit, config.display_inodes_perfdata, config.display_unit); + mp_subcheck unit_sc = evaluate_filesystem(unit->unit, config.display_inodes_perfdata, + config.display_unit); mp_add_subcheck_to_check(&overall, unit_sc); } } else { @@ -433,7 +445,8 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { while (true) { int option = 0; - int option_index = getopt_long(argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLPg:R:r:i:I:MEAn", longopts, &option); + int option_index = getopt_long( + argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLPg:R:r:i:I:MEAn", longopts, &option); if (option_index == -1 || option_index == EOF) { break; @@ -578,9 +591,10 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { result.config.display_inodes_perfdata = true; break; case 'p': /* select path */ { - if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || crit_freespace_percent || - warn_freeinodes_percent || crit_freeinodes_percent)) { - die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set a threshold value before using -p\n")); + if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || + crit_freespace_percent || warn_freeinodes_percent || crit_freeinodes_percent)) { + die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), + _("Must set a threshold value before using -p\n")); } /* add parameter if not found. overwrite thresholds if path has already been added */ @@ -595,7 +609,8 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { // } } search_entry->group = group; - set_all_thresholds(search_entry, warn_freespace_units, crit_freespace_units, warn_freespace_percent, crit_freespace_percent, + set_all_thresholds(search_entry, warn_freespace_units, crit_freespace_units, + warn_freespace_percent, crit_freespace_percent, warn_freeinodes_percent, crit_freeinodes_percent); @@ -603,7 +618,8 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { // if (!stat_path(se, result.config.ignore_missing)) { // break; // } - mp_int_fs_list_set_best_match(result.config.path_select_list, result.config.mount_list, result.config.exact_match); + mp_int_fs_list_set_best_match(result.config.path_select_list, result.config.mount_list, + result.config.exact_match); path_selected = true; } break; @@ -615,7 +631,8 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { if (err != 0) { char errbuf[MAX_INPUT_BUFFER]; regerror(err, &result.config.fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER); - die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf); + die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), + _("Could not compile regular expression"), errbuf); } break; case 'N': /* include file system type */ @@ -623,7 +640,8 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { if (err != 0) { char errbuf[MAX_INPUT_BUFFER]; regerror(err, &result.config.fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER); - die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf); + die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), + _("Could not compile regular expression"), errbuf); } } break; case 'v': /* verbose */ @@ -638,7 +656,8 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { break; case 'E': if (path_selected) { - die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n")); + die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), + _("Must set -E before selecting paths\n")); } result.config.exact_match = true; break; @@ -647,7 +666,8 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { break; case 'g': if (path_selected) { - die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n")); + die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), + _("Must set group value before selecting paths\n")); } group = optarg; break; @@ -657,14 +677,16 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { case 'i': { if (!path_selected) { die(STATE_UNKNOWN, "DISK %s: %s\n", _("UNKNOWN"), - _("Paths need to be selected before using -i/-I. Use -A to select all paths explicitly")); + _("Paths need to be selected before using -i/-I. Use -A to select all paths " + "explicitly")); } regex_t regex; int err = regcomp(®ex, optarg, cflags); if (err != 0) { char errbuf[MAX_INPUT_BUFFER]; regerror(err, ®ex, errbuf, MAX_INPUT_BUFFER); - die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf); + die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), + _("Could not compile regular expression"), errbuf); } for (parameter_list_elem *elem = result.config.path_select_list.first; elem;) { @@ -695,10 +717,11 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { cflags |= REG_ICASE; // Intentional fallthrough case 'r': { - if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || crit_freespace_percent || - warn_freeinodes_percent || crit_freeinodes_percent)) { + if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || + crit_freespace_percent || warn_freeinodes_percent || crit_freeinodes_percent)) { die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), - _("Must set a threshold value before using -r/-R/-A (--ereg-path/--eregi-path/--all)\n")); + _("Must set a threshold value before using -r/-R/-A " + "(--ereg-path/--eregi-path/--all)\n")); } regex_t regex; @@ -706,7 +729,8 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { if (err != 0) { char errbuf[MAX_INPUT_BUFFER]; regerror(err, ®ex, errbuf, MAX_INPUT_BUFFER); - die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf); + die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), + _("Could not compile regular expression"), errbuf); } bool found = false; @@ -714,16 +738,21 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { if (np_regex_match_mount_entry(me, ®ex)) { found = true; if (verbose >= 3) { - printf("%s %s matching expression %s\n", me->me_devname, me->me_mountdir, optarg); + printf("%s %s matching expression %s\n", me->me_devname, me->me_mountdir, + optarg); } - /* add parameter if not found. overwrite thresholds if path has already been added */ + /* add parameter if not found. overwrite thresholds if path has already been + * added */ parameter_list_elem *se = NULL; - if (!(se = mp_int_fs_list_find(result.config.path_select_list, me->me_mountdir))) { - se = mp_int_fs_list_append(&result.config.path_select_list, me->me_mountdir); + if (!(se = mp_int_fs_list_find(result.config.path_select_list, + me->me_mountdir))) { + se = + mp_int_fs_list_append(&result.config.path_select_list, me->me_mountdir); } se->group = group; - set_all_thresholds(se, warn_freespace_units, crit_freespace_units, warn_freespace_percent, crit_freespace_percent, + set_all_thresholds(se, warn_freespace_units, crit_freespace_units, + warn_freespace_percent, crit_freespace_percent, warn_freeinodes_percent, crit_freeinodes_percent); } } @@ -735,11 +764,13 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { break; } - die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Regular expression did not match any path or disk"), optarg); + die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), + _("Regular expression did not match any path or disk"), optarg); } path_selected = true; - mp_int_fs_list_set_best_match(result.config.path_select_list, result.config.mount_list, result.config.exact_match); + mp_int_fs_list_set_best_match(result.config.path_select_list, result.config.mount_list, + result.config.exact_match); cflags = default_cflags; } break; @@ -747,16 +778,20 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { result.config.display_mntp = true; break; case 'C': { - /* add all mount entries to path_select list if no partitions have been explicitly defined using -p */ + /* add all mount entries to path_select list if no partitions have been explicitly + * defined using -p */ if (!path_selected) { parameter_list_elem *path; for (struct mount_entry *me = result.config.mount_list; me; me = me->me_next) { - if (!(path = mp_int_fs_list_find(result.config.path_select_list, me->me_mountdir))) { - path = mp_int_fs_list_append(&result.config.path_select_list, me->me_mountdir); + if (!(path = mp_int_fs_list_find(result.config.path_select_list, + me->me_mountdir))) { + path = + mp_int_fs_list_append(&result.config.path_select_list, me->me_mountdir); } path->best_match = me; path->group = group; - set_all_thresholds(path, warn_freespace_units, crit_freespace_units, warn_freespace_percent, crit_freespace_percent, + set_all_thresholds(path, warn_freespace_units, crit_freespace_units, + warn_freespace_percent, crit_freespace_percent, warn_freeinodes_percent, crit_freeinodes_percent); } } @@ -843,10 +878,12 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { if (verbose > 0) { printf("Got an positional filesystem: %s\n", argv[index]); } - struct parameter_list *se = mp_int_fs_list_append(&result.config.path_select_list, strdup(argv[index++])); + struct parameter_list *se = + mp_int_fs_list_append(&result.config.path_select_list, strdup(argv[index++])); path_selected = true; - set_all_thresholds(se, warn_freespace_units, crit_freespace_units, warn_freespace_percent, crit_freespace_percent, - warn_freeinodes_percent, crit_freeinodes_percent); + set_all_thresholds(se, warn_freespace_units, crit_freespace_units, warn_freespace_percent, + crit_freespace_percent, warn_freeinodes_percent, + crit_freeinodes_percent); } // If a list of paths has not been explicitly selected, find entire @@ -864,18 +901,21 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { } path->best_match = me; path->group = group; - set_all_thresholds(path, warn_freespace_units, crit_freespace_units, warn_freespace_percent, crit_freespace_percent, + set_all_thresholds(path, warn_freespace_units, crit_freespace_units, + warn_freespace_percent, crit_freespace_percent, warn_freeinodes_percent, crit_freeinodes_percent); } } // Set thresholds to the appropriate unit - for (parameter_list_elem *tmp = result.config.path_select_list.first; tmp; tmp = mp_int_fs_list_get_next(tmp)) { + for (parameter_list_elem *tmp = result.config.path_select_list.first; tmp; + tmp = mp_int_fs_list_get_next(tmp)) { mp_perfdata_value factor = mp_create_pd_value(unit); if (tmp->freespace_units.critical_is_set) { - tmp->freespace_units.critical = mp_range_multiply(tmp->freespace_units.critical, factor); + tmp->freespace_units.critical = + mp_range_multiply(tmp->freespace_units.critical, factor); } if (tmp->freespace_units.warning_is_set) { tmp->freespace_units.warning = mp_range_multiply(tmp->freespace_units.warning, factor); @@ -885,8 +925,10 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) { return result; } -void set_all_thresholds(parameter_list_elem *path, char *warn_freespace_units, char *crit_freespace_units, char *warn_freespace_percent, - char *crit_freespace_percent, char *warn_freeinodes_percent, char *crit_freeinodes_percent) { +void set_all_thresholds(parameter_list_elem *path, char *warn_freespace_units, + char *crit_freespace_units, char *warn_freespace_percent, + char *crit_freespace_percent, char *warn_freeinodes_percent, + char *crit_freeinodes_percent) { mp_range_parsed tmp; if (warn_freespace_units) { @@ -927,7 +969,8 @@ void print_help(void) { printf(COPYRIGHT, copyright, email); printf("%s\n", _("This plugin checks the amount of used disk space on a mounted file system")); - printf("%s\n", _("and generates an alert if free space is less than one of the threshold values")); + printf("%s\n", + _("and generates an alert if free space is less than one of the threshold values")); printf("\n\n"); @@ -949,7 +992,8 @@ void print_help(void) { printf(" %s\n", "-K, --icritical=PERCENT%"); printf(" %s\n", _("Exit with CRITICAL status if less than PERCENT of inode space is free")); printf(" %s\n", "-p, --path=PATH, --partition=PARTITION"); - printf(" %s\n", _("Mount point or block device as emitted by the mount(8) command (may be repeated)")); + printf(" %s\n", + _("Mount point or block device as emitted by the mount(8) command (may be repeated)")); printf(" %s\n", "-x, --exclude_device=PATH "); printf(" %s\n", _("Ignore device (only works if -p unspecified)")); printf(" %s\n", "-C, --clear"); @@ -963,71 +1007,88 @@ void print_help(void) { printf(" %s\n", "-P, --iperfdata"); printf(" %s\n", _("Display inode usage in perfdata")); printf(" %s\n", "-g, --group=NAME"); - printf(" %s\n", _("Group paths. Thresholds apply to (free-)space of all partitions together")); + printf(" %s\n", + _("Group paths. Thresholds apply to (free-)space of all partitions together")); printf(" %s\n", "-l, --local"); printf(" %s\n", _("Only check local filesystems")); printf(" %s\n", "-L, --stat-remote-fs"); - printf(" %s\n", _("Only check local filesystems against thresholds. Yet call stat on remote filesystems")); + printf( + " %s\n", + _("Only check local filesystems against thresholds. Yet call stat on remote filesystems")); printf(" %s\n", _("to test if they are accessible (e.g. to detect Stale NFS Handles)")); printf(" %s\n", "-M, --mountpoint"); printf(" %s\n", _("Display the (block) device instead of the mount point")); printf(" %s\n", "-A, --all"); printf(" %s\n", _("Explicitly select all paths. This is equivalent to -R '.*'")); printf(" %s\n", "-R, --eregi-path=PATH, --eregi-partition=PARTITION"); - printf(" %s\n", _("Case insensitive regular expression for path/partition (may be repeated)")); + printf(" %s\n", + _("Case insensitive regular expression for path/partition (may be repeated)")); printf(" %s\n", "-r, --ereg-path=PATH, --ereg-partition=PARTITION"); printf(" %s\n", _("Regular expression for path or partition (may be repeated)")); printf(" %s\n", "-I, --ignore-eregi-path=PATH, --ignore-eregi-partition=PARTITION"); - printf(" %s\n", _("Regular expression to ignore selected path/partition (case insensitive) (may be repeated)")); + printf(" %s\n", _("Regular expression to ignore selected path/partition (case insensitive) " + "(may be repeated)")); printf(" %s\n", "-i, --ignore-ereg-path=PATH, --ignore-ereg-partition=PARTITION"); - printf(" %s\n", _("Regular expression to ignore selected path or partition (may be repeated)")); + printf(" %s\n", + _("Regular expression to ignore selected path or partition (may be repeated)")); printf(" %s\n", "-n, --ignore-missing"); - printf(" %s\n", _("Return OK if no filesystem matches, filesystem does not exist or is inaccessible.")); + printf(" %s\n", + _("Return OK if no filesystem matches, filesystem does not exist or is inaccessible.")); printf(" %s\n", _("(Provide this option before -p / -r / --ereg-path if used)")); printf(UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); printf(" %s\n", "-u, --units=STRING"); printf(" %s\n", _("Select the unit used for the absolute value thresholds")); - printf( - " %s\n", - _("Choose one of \"bytes\", \"KiB\", \"kB\", \"MiB\", \"MB\", \"GiB\", \"GB\", \"TiB\", \"TB\", \"PiB\", \"PB\" (default: MiB)")); + printf(" %s\n", _("Choose one of \"bytes\", \"KiB\", \"kB\", \"MiB\", \"MB\", \"GiB\", " + "\"GB\", \"TiB\", \"TB\", \"PiB\", \"PB\" (default: MiB)")); printf(" %s\n", "-k, --kilobytes"); printf(" %s\n", _("Same as '--units kB'")); printf(" %s\n", "--display-unit"); printf(" %s\n", _("Select the unit used for in the output")); - printf( - " %s\n", - _("Choose one of \"bytes\", \"KiB\", \"kB\", \"MiB\", \"MB\", \"GiB\", \"GB\", \"TiB\", \"TB\", \"PiB\", \"PB\" (default: MiB)")); + printf(" %s\n", _("Choose one of \"bytes\", \"KiB\", \"kB\", \"MiB\", \"MB\", \"GiB\", " + "\"GB\", \"TiB\", \"TB\", \"PiB\", \"PB\" (default: MiB)")); printf(" %s\n", "-m, --megabytes"); printf(" %s\n", _("Same as '--units MB'")); printf(UT_VERBOSE); printf(" %s\n", "-X, --exclude-type=TYPE_REGEX"); - printf(" %s\n", _("Ignore all filesystems of types matching given regex(7) (may be repeated)")); + printf(" %s\n", + _("Ignore all filesystems of types matching given regex(7) (may be repeated)")); printf(" %s\n", "-N, --include-type=TYPE_REGEX"); - printf(" %s\n", _("Check only filesystems where the type matches this given regex(7) (may be repeated)")); + printf( + " %s\n", + _("Check only filesystems where the type matches this given regex(7) (may be repeated)")); printf(UT_OUTPUT_FORMAT); printf("\n"); printf("%s\n", _("General usage hints:")); - printf(" %s\n", _("- Arguments are positional! \"-w 5 -c 1 -p /foo -w6 -c2 -p /bar\" is not the same as")); + printf( + " %s\n", + _("- Arguments are positional! \"-w 5 -c 1 -p /foo -w6 -c2 -p /bar\" is not the same as")); printf(" %s\n", _("\"-w 5 -c 1 -p /bar w6 -c2 -p /foo\".")); - printf(" %s\n", _("- The syntax is broadly: \"{thresholds a} {paths a} -C {thresholds b} {thresholds b} ...\"")); + printf(" %s\n", _("- The syntax is broadly: \"{thresholds a} {paths a} -C {thresholds b} " + "{thresholds b} ...\"")); printf("\n"); printf("%s\n", _("Examples:")); printf(" %s\n", "check_disk -w 10% -c 5% -p /tmp -p /var -C -w 100000 -c 50000 -p /"); printf(" %s\n\n", _("Checks /tmp and /var at 10% and 5%, and / at 100MB and 50MB")); - printf(" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -g sidDATA -r '^/oracle/SID/data.*$'"); - printf(" %s\n", _("Checks all filesystems not matching -r at 100M and 50M. The fs matching the -r regex")); - printf(" %s\n\n", _("are grouped which means the freespace thresholds are applied to all disks together")); + printf(" %s\n", + "check_disk -w 100 -c 50 -C -w 1000 -c 500 -g sidDATA -r '^/oracle/SID/data.*$'"); + printf( + " %s\n", + _("Checks all filesystems not matching -r at 100M and 50M. The fs matching the -r regex")); + printf(" %s\n\n", + _("are grouped which means the freespace thresholds are applied to all disks together")); printf(" %s\n", "check_disk -w 100 -c 50 -C -w 1000 -c 500 -p /foo -C -w 5% -c 3% -p /bar"); - printf(" %s\n", _("Checks /foo for 1000M/500M and /bar for 5/3%. All remaining volumes use 100M/50M")); + printf(" %s\n", + _("Checks /foo for 1000M/500M and /bar for 5/3%. All remaining volumes use 100M/50M")); printf(UT_SUPPORT); } void print_usage(void) { printf("%s\n", _("Usage:")); - printf(" %s {-w absolute_limit |-w percentage_limit%% | -W inode_percentage_limit } {-c absolute_limit|-c percentage_limit%% | -K " + printf(" %s {-w absolute_limit |-w percentage_limit%% | -W inode_percentage_limit } {-c " + "absolute_limit|-c percentage_limit%% | -K " "inode_percentage_limit } {-p path | -x device}\n", progname); printf("[-C] [-E] [-e] [-f] [-g group ] [-k] [-l] [-M] [-m] [-R path ] [-r path ]\n"); @@ -1049,13 +1110,15 @@ bool stat_path(parameter_list_elem *parameters, bool ignore_missing) { return false; } printf("DISK %s - ", _("CRITICAL")); - die(STATE_CRITICAL, _("%s %s: %s\n"), parameters->name, _("is not accessible"), strerror(errno)); + die(STATE_CRITICAL, _("%s %s: %s\n"), parameters->name, _("is not accessible"), + strerror(errno)); } return true; } -static parameter_list_elem get_path_stats(parameter_list_elem parameters, const struct fs_usage fsp, bool freespace_ignore_reserved) { +static parameter_list_elem get_path_stats(parameter_list_elem parameters, const struct fs_usage fsp, + bool freespace_ignore_reserved) { uintmax_t available = fsp.fsu_bavail; uintmax_t available_to_root = fsp.fsu_bfree; uintmax_t used = fsp.fsu_blocks - fsp.fsu_bfree; @@ -1082,7 +1145,8 @@ static parameter_list_elem get_path_stats(parameter_list_elem parameters, const /* option activated : we subtract the root-reserved inodes from the total */ /* not all OS report fsp->fsu_favail, only the ones with statvfs syscall */ /* for others, fsp->fsu_ffree == fsp->fsu_favail */ - parameters.inodes_total = fsp.fsu_files - parameters.inodes_free_to_root + parameters.inodes_free; + parameters.inodes_total = + fsp.fsu_files - parameters.inodes_free_to_root + parameters.inodes_free; } else { /* default behaviour : take all the inodes into account */ parameters.inodes_total = fsp.fsu_files; @@ -1091,7 +1155,8 @@ static parameter_list_elem get_path_stats(parameter_list_elem parameters, const return parameters; } -mp_subcheck evaluate_filesystem(measurement_unit measurement_unit, bool display_inodes_perfdata, byte_unit unit) { +mp_subcheck evaluate_filesystem(measurement_unit measurement_unit, bool display_inodes_perfdata, + byte_unit unit) { mp_subcheck result = mp_subcheck_init(); result = mp_set_subcheck_default_state(result, STATE_UNKNOWN); xasprintf(&result.output, "%s", measurement_unit.name); @@ -1108,10 +1173,12 @@ mp_subcheck evaluate_filesystem(measurement_unit measurement_unit, bool display_ freespace_bytes_sc = mp_set_subcheck_default_state(freespace_bytes_sc, STATE_OK); if (unit != Humanized) { - xasprintf(&freespace_bytes_sc.output, "Free space absolute: %ju%s (of %ju%s)", (uintmax_t)(measurement_unit.free_bytes / unit), - get_unit_string(unit), (uintmax_t)(measurement_unit.total_bytes / unit), get_unit_string(unit)); + xasprintf(&freespace_bytes_sc.output, "Free space absolute: %ju%s (of %ju%s)", + (uintmax_t)(measurement_unit.free_bytes / unit), get_unit_string(unit), + (uintmax_t)(measurement_unit.total_bytes / unit), get_unit_string(unit)); } else { - xasprintf(&freespace_bytes_sc.output, "Free space absolute: %s (of %s)", humanize_byte_value(measurement_unit.free_bytes, false), + xasprintf(&freespace_bytes_sc.output, "Free space absolute: %s (of %s)", + humanize_byte_value(measurement_unit.free_bytes, false), humanize_byte_value((unsigned long long)measurement_unit.total_bytes, false)); } @@ -1127,29 +1194,37 @@ mp_subcheck evaluate_filesystem(measurement_unit measurement_unit, bool display_ // special case for absolute space thresholds here: // if absolute values are not set, compute the thresholds from percentage thresholds mp_thresholds temp_thlds = measurement_unit.freespace_bytes_thresholds; - if (!temp_thlds.critical_is_set && measurement_unit.freespace_percent_thresholds.critical_is_set) { + if (!temp_thlds.critical_is_set && + measurement_unit.freespace_percent_thresholds.critical_is_set) { mp_range tmp_range = measurement_unit.freespace_percent_thresholds.critical; if (!tmp_range.end_infinity) { - tmp_range.end = mp_create_pd_value(mp_get_pd_value(tmp_range.end) / 100 * measurement_unit.total_bytes); + tmp_range.end = mp_create_pd_value(mp_get_pd_value(tmp_range.end) / 100 * + measurement_unit.total_bytes); } if (!tmp_range.start_infinity) { - tmp_range.start = mp_create_pd_value(mp_get_pd_value(tmp_range.start) / 100 * measurement_unit.total_bytes); + tmp_range.start = mp_create_pd_value(mp_get_pd_value(tmp_range.start) / 100 * + measurement_unit.total_bytes); } - measurement_unit.freespace_bytes_thresholds = mp_thresholds_set_crit(measurement_unit.freespace_bytes_thresholds, tmp_range); + measurement_unit.freespace_bytes_thresholds = + mp_thresholds_set_crit(measurement_unit.freespace_bytes_thresholds, tmp_range); used_space = mp_pd_set_thresholds(used_space, measurement_unit.freespace_bytes_thresholds); } - if (!temp_thlds.warning_is_set && measurement_unit.freespace_percent_thresholds.warning_is_set) { + if (!temp_thlds.warning_is_set && + measurement_unit.freespace_percent_thresholds.warning_is_set) { mp_range tmp_range = measurement_unit.freespace_percent_thresholds.warning; if (!tmp_range.end_infinity) { - tmp_range.end = mp_create_pd_value(mp_get_pd_value(tmp_range.end) / 100 * measurement_unit.total_bytes); + tmp_range.end = mp_create_pd_value(mp_get_pd_value(tmp_range.end) / 100 * + measurement_unit.total_bytes); } if (!tmp_range.start_infinity) { - tmp_range.start = mp_create_pd_value(mp_get_pd_value(tmp_range.start) / 100 * measurement_unit.total_bytes); + tmp_range.start = mp_create_pd_value(mp_get_pd_value(tmp_range.start) / 100 * + measurement_unit.total_bytes); } - measurement_unit.freespace_bytes_thresholds = mp_thresholds_set_warn(measurement_unit.freespace_bytes_thresholds, tmp_range); + measurement_unit.freespace_bytes_thresholds = + mp_thresholds_set_warn(measurement_unit.freespace_bytes_thresholds, tmp_range); used_space = mp_pd_set_thresholds(used_space, measurement_unit.freespace_bytes_thresholds); } @@ -1161,15 +1236,18 @@ mp_subcheck evaluate_filesystem(measurement_unit measurement_unit, bool display_ mp_subcheck freespace_percent_sc = mp_subcheck_init(); freespace_percent_sc = mp_set_subcheck_default_state(freespace_percent_sc, STATE_OK); - double free_percentage = calculate_percent(measurement_unit.free_bytes, measurement_unit.total_bytes); + double free_percentage = + calculate_percent(measurement_unit.free_bytes, measurement_unit.total_bytes); xasprintf(&freespace_percent_sc.output, "Free space percentage: %g%%", free_percentage); // Using perfdata here just to get to the test result mp_perfdata free_space_percent_pd = perfdata_init(); free_space_percent_pd.value = mp_create_pd_value(free_percentage); - free_space_percent_pd = mp_pd_set_thresholds(free_space_percent_pd, measurement_unit.freespace_percent_thresholds); + free_space_percent_pd = + mp_pd_set_thresholds(free_space_percent_pd, measurement_unit.freespace_percent_thresholds); - freespace_percent_sc = mp_set_subcheck_state(freespace_percent_sc, mp_get_pd_status(free_space_percent_pd)); + freespace_percent_sc = + mp_set_subcheck_state(freespace_percent_sc, mp_get_pd_status(free_space_percent_pd)); mp_add_subcheck_to_subcheck(&result, freespace_percent_sc); // ================ @@ -1181,35 +1259,41 @@ mp_subcheck evaluate_filesystem(measurement_unit measurement_unit, bool display_ mp_subcheck freeindodes_percent_sc = mp_subcheck_init(); freeindodes_percent_sc = mp_set_subcheck_default_state(freeindodes_percent_sc, STATE_OK); - double free_inode_percentage = calculate_percent(measurement_unit.inodes_free, measurement_unit.inodes_total); + double free_inode_percentage = + calculate_percent(measurement_unit.inodes_free, measurement_unit.inodes_total); if (verbose > 0) { printf("free inode percentage computed: %g\n", free_inode_percentage); } - xasprintf(&freeindodes_percent_sc.output, "Inodes free: %g%% (%ju of %ju)", free_inode_percentage, measurement_unit.inodes_free, + xasprintf(&freeindodes_percent_sc.output, "Inodes free: %g%% (%ju of %ju)", + free_inode_percentage, measurement_unit.inodes_free, measurement_unit.inodes_total); mp_perfdata inodes_pd = perfdata_init(); xasprintf(&inodes_pd.label, "%s (inodes)", measurement_unit.name); inodes_pd = mp_set_pd_value(inodes_pd, measurement_unit.inodes_used); - inodes_pd = mp_set_pd_max_value(inodes_pd, mp_create_pd_value(measurement_unit.inodes_total)); + inodes_pd = + mp_set_pd_max_value(inodes_pd, mp_create_pd_value(measurement_unit.inodes_total)); inodes_pd = mp_set_pd_min_value(inodes_pd, mp_create_pd_value(0)); mp_thresholds absolut_inode_thresholds = measurement_unit.freeinodes_percent_thresholds; if (absolut_inode_thresholds.critical_is_set) { absolut_inode_thresholds.critical = - mp_range_multiply(absolut_inode_thresholds.critical, mp_create_pd_value(measurement_unit.inodes_total / 100)); + mp_range_multiply(absolut_inode_thresholds.critical, + mp_create_pd_value(measurement_unit.inodes_total / 100)); } if (absolut_inode_thresholds.warning_is_set) { absolut_inode_thresholds.warning = - mp_range_multiply(absolut_inode_thresholds.warning, mp_create_pd_value(measurement_unit.inodes_total / 100)); + mp_range_multiply(absolut_inode_thresholds.warning, + mp_create_pd_value(measurement_unit.inodes_total / 100)); } inodes_pd = mp_pd_set_thresholds(inodes_pd, absolut_inode_thresholds); - freeindodes_percent_sc = mp_set_subcheck_state(freeindodes_percent_sc, mp_get_pd_status(inodes_pd)); + freeindodes_percent_sc = + mp_set_subcheck_state(freeindodes_percent_sc, mp_get_pd_status(inodes_pd)); if (display_inodes_perfdata) { mp_add_perfdata_to_subcheck(&freeindodes_percent_sc, inodes_pd); } diff --git a/plugins/check_disk.d/utils_disk.c b/plugins/check_disk.d/utils_disk.c index eec1282b..0b89018d 100644 --- a/plugins/check_disk.d/utils_disk.c +++ b/plugins/check_disk.d/utils_disk.c @@ -126,7 +126,8 @@ bool np_find_regmatch(struct regex_list *list, const char *name) { /* Emulate a full match as if surrounded with ^( )$ by checking whether the match spans the whole name */ regmatch_t dummy_match; - if (!regexec(&list->regex, name, 1, &dummy_match, 0) && dummy_match.rm_so == 0 && dummy_match.rm_eo == len) { + if (!regexec(&list->regex, name, 1, &dummy_match, 0) && dummy_match.rm_so == 0 && + dummy_match.rm_eo == len) { return true; } } @@ -144,7 +145,8 @@ bool np_seen_name(struct name_list *list, const char *name) { } bool np_regex_match_mount_entry(struct mount_entry *me, regex_t *re) { - return ((regexec(re, me->me_devname, (size_t)0, NULL, 0) == 0) || (regexec(re, me->me_mountdir, (size_t)0, NULL, 0) == 0)); + return ((regexec(re, me->me_devname, (size_t)0, NULL, 0) == 0) || + (regexec(re, me->me_mountdir, (size_t)0, NULL, 0) == 0)); } check_disk_config check_disk_config_init() { @@ -264,7 +266,8 @@ measurement_unit_list *add_measurement_list(measurement_unit_list *list, measure return new; } -measurement_unit add_filesystem_to_measurement_unit(measurement_unit unit, parameter_list_elem filesystem) { +measurement_unit add_filesystem_to_measurement_unit(measurement_unit unit, + parameter_list_elem filesystem) { unit.free_bytes += filesystem.free_bytes; unit.used_bytes += filesystem.used_bytes; @@ -277,7 +280,8 @@ measurement_unit add_filesystem_to_measurement_unit(measurement_unit unit, param return unit; } -measurement_unit create_measurement_unit_from_filesystem(parameter_list_elem filesystem, bool display_mntp) { +measurement_unit create_measurement_unit_from_filesystem(parameter_list_elem filesystem, + bool display_mntp) { measurement_unit result = measurement_unit_init(); if (!display_mntp) { result.name = strdup(filesystem.best_match->me_mountdir); @@ -469,17 +473,20 @@ parameter_list_elem *mp_int_fs_list_get_next(parameter_list_elem *current) { return current->next; } -void mp_int_fs_list_set_best_match(filesystem_list list, struct mount_entry *mount_list, bool exact) { +void mp_int_fs_list_set_best_match(filesystem_list list, struct mount_entry *mount_list, + bool exact) { for (parameter_list_elem *elem = list.first; elem; elem = mp_int_fs_list_get_next(elem)) { if (!elem->best_match) { size_t name_len = strlen(elem->name); struct mount_entry *best_match = NULL; /* set best match if path name exactly matches a mounted device name */ - for (struct mount_entry *mount_entry = mount_list; mount_entry; mount_entry = mount_entry->me_next) { + for (struct mount_entry *mount_entry = mount_list; mount_entry; + mount_entry = mount_entry->me_next) { if (strcmp(mount_entry->me_devname, elem->name) == 0) { struct fs_usage fsp; - if (get_fs_usage(mount_entry->me_mountdir, mount_entry->me_devname, &fsp) >= 0) { + if (get_fs_usage(mount_entry->me_mountdir, mount_entry->me_devname, &fsp) >= + 0) { best_match = mount_entry; } } @@ -488,15 +495,18 @@ void mp_int_fs_list_set_best_match(filesystem_list list, struct mount_entry *mou /* set best match by directory name if no match was found by devname */ if (!best_match) { size_t best_match_len = 0; - for (struct mount_entry *mount_entry = mount_list; mount_entry; mount_entry = mount_entry->me_next) { + for (struct mount_entry *mount_entry = mount_list; mount_entry; + mount_entry = mount_entry->me_next) { size_t len = strlen(mount_entry->me_mountdir); - if ((!exact && (best_match_len <= len && len <= name_len && - (len == 1 || strncmp(mount_entry->me_mountdir, elem->name, len) == 0))) || + if ((!exact && + (best_match_len <= len && len <= name_len && + (len == 1 || strncmp(mount_entry->me_mountdir, elem->name, len) == 0))) || (exact && strcmp(mount_entry->me_mountdir, elem->name) == 0)) { struct fs_usage fsp; - if (get_fs_usage(mount_entry->me_mountdir, mount_entry->me_devname, &fsp) >= 0) { + if (get_fs_usage(mount_entry->me_mountdir, mount_entry->me_devname, &fsp) >= + 0) { best_match = mount_entry; best_match_len = len; } @@ -507,7 +517,8 @@ void mp_int_fs_list_set_best_match(filesystem_list list, struct mount_entry *mou if (best_match) { elem->best_match = best_match; } else { - elem->best_match = NULL; /* Not sure why this is needed as it should be null on initialisation */ + elem->best_match = + NULL; /* Not sure why this is needed as it should be null on initialisation */ } // No filesystem without a mount_entry! diff --git a/plugins/check_disk.d/utils_disk.h b/plugins/check_disk.d/utils_disk.h index 6831d1fd..c96d4296 100644 --- a/plugins/check_disk.d/utils_disk.h +++ b/plugins/check_disk.d/utils_disk.h @@ -141,12 +141,15 @@ parameter_list_elem *mp_int_fs_list_append(filesystem_list *list, const char *na parameter_list_elem *mp_int_fs_list_find(filesystem_list list, const char *name); parameter_list_elem *mp_int_fs_list_del(filesystem_list *list, parameter_list_elem *item); parameter_list_elem *mp_int_fs_list_get_next(parameter_list_elem *current); -void mp_int_fs_list_set_best_match(filesystem_list list, struct mount_entry *mount_list, bool exact); +void mp_int_fs_list_set_best_match(filesystem_list list, struct mount_entry *mount_list, + bool exact); measurement_unit measurement_unit_init(); measurement_unit_list *add_measurement_list(measurement_unit_list *list, measurement_unit elem); -measurement_unit add_filesystem_to_measurement_unit(measurement_unit unit, parameter_list_elem filesystem); -measurement_unit create_measurement_unit_from_filesystem(parameter_list_elem filesystem, bool display_mntp); +measurement_unit add_filesystem_to_measurement_unit(measurement_unit unit, + parameter_list_elem filesystem); +measurement_unit create_measurement_unit_from_filesystem(parameter_list_elem filesystem, + bool display_mntp); int search_parameter_list(parameter_list_elem *list, const char *name); bool np_regex_match_mount_entry(struct mount_entry *, regex_t *); diff --git a/plugins/check_dns.c b/plugins/check_dns.c index 95f33083..56f91dae 100644 --- a/plugins/check_dns.c +++ b/plugins/check_dns.c @@ -48,7 +48,8 @@ typedef struct { } check_dns_config_wrapper; static check_dns_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); static check_dns_config_wrapper validate_arguments(check_dns_config_wrapper /*config_wrapper*/); -static mp_state_enum error_scan(char * /*input_buffer*/, bool * /*is_nxdomain*/, const char /*dns_server*/[ADDRESS_LENGTH]); +static mp_state_enum error_scan(char * /*input_buffer*/, bool * /*is_nxdomain*/, + const char /*dns_server*/[ADDRESS_LENGTH]); static bool ip_match_cidr(const char * /*addr*/, const char * /*cidr_ro*/); static unsigned long ip2long(const char * /*src*/); static void print_help(void); @@ -127,7 +128,8 @@ int main(int argc, char **argv) { puts(chld_out.line[i]); } - if (strcasestr(chld_out.line[i], ".in-addr.arpa") || strcasestr(chld_out.line[i], ".ip6.arpa")) { + if (strcasestr(chld_out.line[i], ".in-addr.arpa") || + strcasestr(chld_out.line[i], ".ip6.arpa")) { if ((strstr(chld_out.line[i], "canonical name = ") != NULL)) { continue; } @@ -145,7 +147,8 @@ int main(int argc, char **argv) { if (strstr(chld_out.line[i], "Server:") && strlen(config.dns_server) > 0) { char *temp_buffer = strchr(chld_out.line[i], ':'); if (temp_buffer == NULL) { - die(STATE_UNKNOWN, _("'%s' returned a weirdly formatted Server line\n"), NSLOOKUP_COMMAND); + die(STATE_UNKNOWN, _("'%s' returned a weirdly formatted Server line\n"), + NSLOOKUP_COMMAND); } temp_buffer++; @@ -157,21 +160,25 @@ int main(int argc, char **argv) { strip(temp_buffer); if (strlen(temp_buffer) == 0) { - die(STATE_CRITICAL, _("DNS CRITICAL - '%s' returned empty server string\n"), NSLOOKUP_COMMAND); + die(STATE_CRITICAL, _("DNS CRITICAL - '%s' returned empty server string\n"), + NSLOOKUP_COMMAND); } if (strcmp(temp_buffer, config.dns_server) != 0) { - die(STATE_CRITICAL, _("DNS CRITICAL - No response from DNS %s\n"), config.dns_server); + die(STATE_CRITICAL, _("DNS CRITICAL - No response from DNS %s\n"), + config.dns_server); } } /* the server is responding, we just got the host name... */ if (strstr(chld_out.line[i], "Name:")) { parse_address = true; - } else if (parse_address && (strstr(chld_out.line[i], "Address:") || strstr(chld_out.line[i], "Addresses:"))) { + } else if (parse_address && (strstr(chld_out.line[i], "Address:") || + strstr(chld_out.line[i], "Addresses:"))) { char *temp_buffer = strchr(chld_out.line[i], ':'); if (temp_buffer == NULL) { - die(STATE_UNKNOWN, _("'%s' returned a weirdly formatted Address line\n"), NSLOOKUP_COMMAND); + die(STATE_UNKNOWN, _("'%s' returned a weirdly formatted Address line\n"), + NSLOOKUP_COMMAND); } temp_buffer++; @@ -183,7 +190,8 @@ int main(int argc, char **argv) { strip(temp_buffer); if (strlen(temp_buffer) == 0) { - die(STATE_CRITICAL, _("DNS CRITICAL - '%s' returned empty host name string\n"), NSLOOKUP_COMMAND); + die(STATE_CRITICAL, _("DNS CRITICAL - '%s' returned empty host name string\n"), + NSLOOKUP_COMMAND); } addresses[n_addresses++] = strdup(temp_buffer); @@ -209,7 +217,8 @@ int main(int argc, char **argv) { } if (error_scan(chld_err.line[i], &is_nxdomain, config.dns_server) != STATE_OK) { - result = max_state(result, error_scan(chld_err.line[i], &is_nxdomain, config.dns_server)); + result = + max_state(result, error_scan(chld_err.line[i], &is_nxdomain, config.dns_server)); msg = strchr(input_buffer, ':'); if (msg) { msg++; @@ -242,7 +251,8 @@ int main(int argc, char **argv) { } *adrp = 0; } else { - die(STATE_CRITICAL, _("DNS CRITICAL - '%s' msg parsing exited with no address\n"), NSLOOKUP_COMMAND); + die(STATE_CRITICAL, _("DNS CRITICAL - '%s' msg parsing exited with no address\n"), + NSLOOKUP_COMMAND); } /* compare to expected address */ @@ -255,7 +265,8 @@ int main(int argc, char **argv) { for (size_t i = 0; i < config.expected_address_cnt; i++) { /* check if we get a match on 'raw' ip or cidr */ for (size_t j = 0; j < n_addresses; j++) { - if (strcmp(addresses[j], config.expected_address[i]) == 0 || ip_match_cidr(addresses[j], config.expected_address[i])) { + if (strcmp(addresses[j], config.expected_address[i]) == 0 || + ip_match_cidr(addresses[j], config.expected_address[i])) { result = STATE_OK; addr_match &= ~(1 << j); expect_match &= ~(1 << i); @@ -279,7 +290,8 @@ int main(int argc, char **argv) { if (config.expect_nxdomain) { if (!is_nxdomain) { result = STATE_CRITICAL; - xasprintf(&msg, _("Domain '%s' was found by the server: '%s'\n"), config.query_address, address); + xasprintf(&msg, _("Domain '%s' was found by the server: '%s'\n"), config.query_address, + address); } else { if (address != NULL) { free(address); @@ -291,7 +303,8 @@ int main(int argc, char **argv) { /* check if authoritative */ if (result == STATE_OK && config.expect_authority && non_authoritative) { result = STATE_CRITICAL; - xasprintf(&msg, _("server %s is not authoritative for %s"), config.dns_server, config.query_address); + xasprintf(&msg, _("server %s is not authoritative for %s"), config.dns_server, + config.query_address); } long microsec = deltime(tv); @@ -306,24 +319,36 @@ int main(int argc, char **argv) { } else if (result == STATE_CRITICAL) { printf("DNS %s: ", _("CRITICAL")); } - printf(ngettext("%.3f second response time", "%.3f seconds response time", elapsed_time), elapsed_time); + printf(ngettext("%.3f second response time", "%.3f seconds response time", elapsed_time), + elapsed_time); printf(_(". %s returns %s"), config.query_address, address); - if ((config.time_thresholds->warning != NULL) && (config.time_thresholds->critical != NULL)) { - printf("|%s\n", fperfdata("time", elapsed_time, "s", true, config.time_thresholds->warning->end, true, + if ((config.time_thresholds->warning != NULL) && + (config.time_thresholds->critical != NULL)) { + printf("|%s\n", + fperfdata("time", elapsed_time, "s", true, config.time_thresholds->warning->end, + true, config.time_thresholds->critical->end, true, 0, false, 0)); + } else if ((config.time_thresholds->warning == NULL) && + (config.time_thresholds->critical != NULL)) { + printf("|%s\n", fperfdata("time", elapsed_time, "s", false, 0, true, config.time_thresholds->critical->end, true, 0, false, 0)); - } else if ((config.time_thresholds->warning == NULL) && (config.time_thresholds->critical != NULL)) { - printf("|%s\n", fperfdata("time", elapsed_time, "s", false, 0, true, config.time_thresholds->critical->end, true, 0, false, 0)); - } else if ((config.time_thresholds->warning != NULL) && (config.time_thresholds->critical == NULL)) { - printf("|%s\n", fperfdata("time", elapsed_time, "s", true, config.time_thresholds->warning->end, false, 0, true, 0, false, 0)); + } else if ((config.time_thresholds->warning != NULL) && + (config.time_thresholds->critical == NULL)) { + printf("|%s\n", + fperfdata("time", elapsed_time, "s", true, config.time_thresholds->warning->end, + false, 0, true, 0, false, 0)); } else { - printf("|%s\n", fperfdata("time", elapsed_time, "s", false, 0, false, 0, true, 0, false, 0)); + printf("|%s\n", + fperfdata("time", elapsed_time, "s", false, 0, false, 0, true, 0, false, 0)); } } else if (result == STATE_WARNING) { - printf(_("DNS WARNING - %s\n"), !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg); + printf(_("DNS WARNING - %s\n"), + !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg); } else if (result == STATE_CRITICAL) { - printf(_("DNS CRITICAL - %s\n"), !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg); + printf(_("DNS CRITICAL - %s\n"), + !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg); } else { - printf(_("DNS UNKNOWN - %s\n"), !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg); + printf(_("DNS UNKNOWN - %s\n"), + !strcmp(msg, "") ? _(" Probably a non-existent host/domain") : msg); } exit(result); @@ -342,29 +367,34 @@ bool ip_match_cidr(const char *addr, const char *cidr_ro) { mask = atoi(mask_c); /* https://www.cryptobells.com/verifying-ips-in-a-subnet-in-php/ */ - return (ip2long(addr) & ~((1 << (32 - mask)) - 1)) == (ip2long(subnet) >> (32 - mask)) << (32 - mask); + return (ip2long(addr) & ~((1 << (32 - mask)) - 1)) == (ip2long(subnet) >> (32 - mask)) + << (32 - mask); } unsigned long ip2long(const char *src) { unsigned long ip[4]; /* http://computer-programming-forum.com/47-c-language/1376ffb92a12c471.htm */ - return (sscanf(src, "%3lu.%3lu.%3lu.%3lu", &ip[0], &ip[1], &ip[2], &ip[3]) == 4 && ip[0] < 256 && ip[1] < 256 && ip[2] < 256 && - ip[3] < 256) + return (sscanf(src, "%3lu.%3lu.%3lu.%3lu", &ip[0], &ip[1], &ip[2], &ip[3]) == 4 && + ip[0] < 256 && ip[1] < 256 && ip[2] < 256 && ip[3] < 256) ? ip[0] << 24 | ip[1] << 16 | ip[2] << 8 | ip[3] : 0; } -mp_state_enum error_scan(char *input_buffer, bool *is_nxdomain, const char dns_server[ADDRESS_LENGTH]) { +mp_state_enum error_scan(char *input_buffer, bool *is_nxdomain, + const char dns_server[ADDRESS_LENGTH]) { - const int nxdomain = strstr(input_buffer, "Non-existent") || strstr(input_buffer, "** server can't find") || + const int nxdomain = strstr(input_buffer, "Non-existent") || + strstr(input_buffer, "** server can't find") || strstr(input_buffer, "** Can't find") || strstr(input_buffer, "NXDOMAIN"); if (nxdomain) { *is_nxdomain = true; } /* the DNS lookup timed out */ - if (strstr(input_buffer, _("Note: nslookup is deprecated and may be removed from future releases.")) || - strstr(input_buffer, _("Consider using the `dig' or `host' programs instead. Run nslookup with")) || + if (strstr(input_buffer, + _("Note: nslookup is deprecated and may be removed from future releases.")) || + strstr(input_buffer, + _("Consider using the `dig' or `host' programs instead. Run nslookup with")) || strstr(input_buffer, _("the `-sil[ent]' option to prevent this message from appearing."))) { return STATE_OK; } @@ -382,8 +412,9 @@ mp_state_enum error_scan(char *input_buffer, bool *is_nxdomain, const char dns_s } /* Connection was refused */ - else if (strstr(input_buffer, "Connection refused") || strstr(input_buffer, "Couldn't find server") || - strstr(input_buffer, "Refused") || (strstr(input_buffer, "** server can't find") && strstr(input_buffer, ": REFUSED"))) { + else if (strstr(input_buffer, "Connection refused") || + strstr(input_buffer, "Couldn't find server") || strstr(input_buffer, "Refused") || + (strstr(input_buffer, "** server can't find") && strstr(input_buffer, ": REFUSED"))) { die(STATE_CRITICAL, _("Connection to DNS %s was refused\n"), dns_server); } @@ -504,20 +535,24 @@ check_dns_config_wrapper process_arguments(int argc, char **argv) { if (strchr(optarg, ',') != NULL) { char *comma = strchr(optarg, ','); while (comma != NULL) { - result.config.expected_address = - (char **)realloc(result.config.expected_address, (result.config.expected_address_cnt + 1) * sizeof(char **)); - result.config.expected_address[result.config.expected_address_cnt] = strndup(optarg, comma - optarg); + result.config.expected_address = (char **)realloc( + result.config.expected_address, + (result.config.expected_address_cnt + 1) * sizeof(char **)); + result.config.expected_address[result.config.expected_address_cnt] = + strndup(optarg, comma - optarg); result.config.expected_address_cnt++; optarg = comma + 1; comma = strchr(optarg, ','); } result.config.expected_address = - (char **)realloc(result.config.expected_address, (result.config.expected_address_cnt + 1) * sizeof(char **)); + (char **)realloc(result.config.expected_address, + (result.config.expected_address_cnt + 1) * sizeof(char **)); result.config.expected_address[result.config.expected_address_cnt] = strdup(optarg); result.config.expected_address_cnt++; } else { result.config.expected_address = - (char **)realloc(result.config.expected_address, (result.config.expected_address_cnt + 1) * sizeof(char **)); + (char **)realloc(result.config.expected_address, + (result.config.expected_address_cnt + 1) * sizeof(char **)); result.config.expected_address[result.config.expected_address_cnt] = strdup(optarg); result.config.expected_address_cnt++; } @@ -586,9 +621,11 @@ void print_help(void) { printf("Copyright (c) 1999 Ethan Galstad \n"); printf(COPYRIGHT, copyright, email); - printf("%s\n", _("This plugin uses the nslookup program to obtain the IP address for the given host/domain query.")); + printf("%s\n", _("This plugin uses the nslookup program to obtain the IP address for the given " + "host/domain query.")); printf("%s\n", _("An optional DNS server to use may be specified.")); - printf("%s\n", _("If no DNS server is specified, the default server(s) specified in /etc/resolv.conf will be used.")); + printf("%s\n", _("If no DNS server is specified, the default server(s) specified in " + "/etc/resolv.conf will be used.")); printf("\n\n"); @@ -602,11 +639,14 @@ void print_help(void) { printf(" -s, --server=HOST\n"); printf(" %s\n", _("Optional DNS server you want to use for the lookup")); printf(" -a, --expected-address=IP-ADDRESS|CIDR|HOST\n"); - printf(" %s\n", _("Optional IP-ADDRESS/CIDR you expect the DNS server to return. HOST must end")); - printf(" %s\n", _("with a dot (.). This option can be repeated multiple times (Returns OK if any")); + printf(" %s\n", + _("Optional IP-ADDRESS/CIDR you expect the DNS server to return. HOST must end")); + printf(" %s\n", + _("with a dot (.). This option can be repeated multiple times (Returns OK if any")); printf(" %s\n", _("value matches).")); printf(" -n, --expect-nxdomain\n"); - printf(" %s\n", _("Expect the DNS server to return NXDOMAIN (i.e. the domain was not found)")); + printf(" %s\n", + _("Expect the DNS server to return NXDOMAIN (i.e. the domain was not found)")); printf(" %s\n", _("Cannot be used together with -a")); printf(" -A, --expect-authority\n"); printf(" %s\n", _("Optionally expect the DNS server to be authoritative for the lookup")); @@ -615,7 +655,8 @@ void print_help(void) { printf(" -c, --critical=seconds\n"); printf(" %s\n", _("Return critical if elapsed time exceeds value. Default off")); printf(" -L, --all\n"); - printf(" %s\n", _("Return critical if the list of expected addresses does not match all addresses")); + printf(" %s\n", + _("Return critical if the list of expected addresses does not match all addresses")); printf(" %s\n", _("returned. Default off")); printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); @@ -625,5 +666,7 @@ void print_help(void) { void print_usage(void) { printf("%s\n", _("Usage:")); - printf("%s -H host [-s server] [-a expected-address] [-n] [-A] [-t timeout] [-w warn] [-c crit] [-L]\n", progname); + printf("%s -H host [-s server] [-a expected-address] [-n] [-A] [-t timeout] [-w warn] [-c " + "crit] [-L]\n", + progname); } diff --git a/plugins/check_dummy.c b/plugins/check_dummy.c index 19f6c046..602d5868 100644 --- a/plugins/check_dummy.c +++ b/plugins/check_dummy.c @@ -45,18 +45,19 @@ int main(int argc, char **argv) { bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - if (argc < 2) + if (argc < 2) { usage4(_("Could not parse arguments")); - else if (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "--version") == 0) { + } else if (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "--version") == 0) { print_revision(progname, NP_VERSION); exit(STATE_UNKNOWN); } else if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) { print_help(); exit(STATE_UNKNOWN); - } else if (!is_integer(argv[1])) + } else if (!is_integer(argv[1])) { usage4(_("Arguments to check_dummy must be an integer")); - else + } else { result = atoi(argv[1]); + } switch (result) { case STATE_OK: @@ -78,8 +79,9 @@ int main(int argc, char **argv) { return STATE_UNKNOWN; } - if (argc >= 3) + if (argc >= 3) { printf(": %s", argv[2]); + } printf("\n"); @@ -92,7 +94,8 @@ void print_help(void) { printf("Copyright (c) 1999 Ethan Galstad \n"); printf(COPYRIGHT, copyright, email); - printf("%s\n", _("This plugin will simply return the state corresponding to the numeric value")); + printf("%s\n", + _("This plugin will simply return the state corresponding to the numeric value")); printf("%s\n", _("of the argument with optional text")); diff --git a/plugins/check_fping.c b/plugins/check_fping.c index 8018e06d..6160c2cb 100644 --- a/plugins/check_fping.c +++ b/plugins/check_fping.c @@ -46,8 +46,9 @@ enum { RTA = 1 }; -static mp_state_enum textscan(char *buf, const char * /*server_name*/, bool /*crta_p*/, double /*crta*/, bool /*wrta_p*/, double /*wrta*/, - bool /*cpl_p*/, int /*cpl*/, bool /*wpl_p*/, int /*wpl*/, bool /*alive_p*/); +static mp_state_enum textscan(char *buf, const char * /*server_name*/, bool /*crta_p*/, + double /*crta*/, bool /*wrta_p*/, double /*wrta*/, bool /*cpl_p*/, + int /*cpl*/, bool /*wpl_p*/, int /*wpl*/, bool /*alive_p*/); typedef struct { int errorcode; @@ -133,9 +134,11 @@ int main(int argc, char **argv) { if (config.icmp_timestamp) { // no packet size settable for ICMP timestamp - xasprintf(&command_line, "%s %s -c %d %s", fping_prog, option_string, config.packet_count, server); + xasprintf(&command_line, "%s %s -c %d %s", fping_prog, option_string, config.packet_count, + server); } else { - xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string, config.packet_size, config.packet_count, server); + xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string, + config.packet_size, config.packet_count, server); } if (verbose) { @@ -160,8 +163,9 @@ int main(int argc, char **argv) { if (verbose) { printf("%s", input_buffer); } - status = max_state(status, textscan(input_buffer, config.server_name, config.crta_p, config.crta, config.wrta_p, config.wrta, - config.cpl_p, config.cpl, config.wpl_p, config.wpl, config.alive_p)); + status = max_state(status, textscan(input_buffer, config.server_name, config.crta_p, + config.crta, config.wrta_p, config.wrta, config.cpl_p, + config.cpl, config.wpl_p, config.wpl, config.alive_p)); } /* If we get anything on STDERR, at least set warning */ @@ -170,8 +174,9 @@ int main(int argc, char **argv) { if (verbose) { printf("%s", input_buffer); } - status = max_state(status, textscan(input_buffer, config.server_name, config.crta_p, config.crta, config.wrta_p, config.wrta, - config.cpl_p, config.cpl, config.wpl_p, config.wpl, config.alive_p)); + status = max_state(status, textscan(input_buffer, config.server_name, config.crta_p, + config.crta, config.wrta_p, config.wrta, config.cpl_p, + config.cpl, config.wpl_p, config.wpl, config.alive_p)); } (void)fclose(child_stderr); @@ -200,8 +205,8 @@ int main(int argc, char **argv) { return status; } -mp_state_enum textscan(char *buf, const char *server_name, bool crta_p, double crta, bool wrta_p, double wrta, bool cpl_p, int cpl, - bool wpl_p, int wpl, bool alive_p) { +mp_state_enum textscan(char *buf, const char *server_name, bool crta_p, double crta, bool wrta_p, + double wrta, bool cpl_p, int cpl, bool wpl_p, int wpl, bool alive_p) { /* stops testing after the first successful reply. */ double rta; double loss; @@ -214,7 +219,8 @@ mp_state_enum textscan(char *buf, const char *server_name, bool crta_p, double c die(STATE_OK, _("FPING %s - %s (rta=%f ms)|%s\n"), state_text(STATE_OK), server_name, rta, /* No loss since we only waited for the first reply perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), */ - fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, false, 0)); + fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, + false, 0)); } mp_state_enum status = STATE_UNKNOWN; @@ -255,9 +261,11 @@ mp_state_enum textscan(char *buf, const char *server_name, bool crta_p, double c } else { status = STATE_OK; } - die(status, _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), state_text(status), server_name, loss, rta, + die(status, _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), state_text(status), + server_name, loss, rta, perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, false, 0, false, 0), - fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, false, 0)); + fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, + false, 0)); } else if (strstr(buf, "xmt/rcv/%loss")) { /* no min/max/avg if host was unreachable in fping v2.2.b1 */ @@ -350,7 +358,8 @@ check_fping_config_wrapper process_arguments(int argc, char **argv) { } while (true) { - int option_index = getopt_long(argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:M:R:46", longopts, &option); + int option_index = + getopt_long(argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:M:R:46", longopts, &option); if (option_index == -1 || option_index == EOF || option_index == 1) { break; @@ -487,10 +496,12 @@ int get_threshold(char *arg, char *rv[2]) { if (arg2) { arg1[strcspn(arg1, ",:")] = 0; if (strstr(arg1, "%") && strstr(arg2, "%")) { - die(STATE_UNKNOWN, _("%s: Only one threshold may be packet loss (%s)\n"), progname, arg); + die(STATE_UNKNOWN, _("%s: Only one threshold may be packet loss (%s)\n"), progname, + arg); } if (!strstr(arg1, "%") && !strstr(arg2, "%")) { - die(STATE_UNKNOWN, _("%s: Only one threshold must be packet loss (%s)\n"), progname, arg); + die(STATE_UNKNOWN, _("%s: Only one threshold must be packet loss (%s)\n"), progname, + arg); } } @@ -516,7 +527,8 @@ void print_help(void) { printf("Copyright (c) 1999 Didi Rieder \n"); printf(COPYRIGHT, copyright, email); - printf("%s\n", _("This plugin will use the fping command to ping the specified host for a fast check")); + printf("%s\n", + _("This plugin will use the fping command to ping the specified host for a fast check")); printf("%s\n", _("Note that it is necessary to set the suid flag on fping.")); @@ -530,7 +542,8 @@ void print_help(void) { printf(UT_IPv46); printf(" %s\n", "-H, --hostname=HOST"); - printf(" %s\n", _("name or IP Address of host to ping (IP Address bypasses name lookup, reducing system load)")); + printf(" %s\n", _("name or IP Address of host to ping (IP Address bypasses name lookup, " + "reducing system load)")); printf(" %s\n", "-w, --warning=THRESHOLD"); printf(" %s\n", _("warning threshold pair")); printf(" %s\n", "-c, --critical=THRESHOLD"); @@ -544,7 +557,8 @@ void print_help(void) { printf(" %s\n", "-T, --target-timeout=INTEGER"); printf(" %s (default: fping's default for -t)\n", _("Target timeout (ms)")); printf(" %s\n", "-i, --interval=INTEGER"); - printf(" %s (default: fping's default for -p)\n", _("Interval (ms) between sending packets")); + printf(" %s (default: fping's default for -p)\n", + _("Interval (ms) between sending packets")); printf(" %s\n", "-S, --sourceip=HOST"); printf(" %s\n", _("name or IP Address of sourceip")); printf(" %s\n", "-I, --sourceif=IF"); @@ -565,7 +579,8 @@ void print_help(void) { #endif printf(UT_VERBOSE); printf("\n"); - printf(" %s\n", _("THRESHOLD is ,%% where is the round trip average travel time (ms)")); + printf(" %s\n", + _("THRESHOLD is ,%% where is the round trip average travel time (ms)")); printf(" %s\n", _("which triggers a WARNING or CRITICAL state, and is the percentage of")); printf(" %s\n", _("packet loss to trigger an alarm state.")); @@ -577,5 +592,6 @@ void print_help(void) { void print_usage(void) { printf("%s\n", _("Usage:")); - printf(" %s -w limit -c limit [-b size] [-n number] [-T number] [-i number]\n", progname); + printf(" %s -w limit -c limit [-b size] [-n number] [-T number] [-i number]\n", + progname); } diff --git a/plugins/check_fping.d/config.h b/plugins/check_fping.d/config.h index d95e9ded..d3e50565 100644 --- a/plugins/check_fping.d/config.h +++ b/plugins/check_fping.d/config.h @@ -36,7 +36,6 @@ typedef struct { unsigned int fwmark; bool fwmark_set; - // only available with fping version >= 5.3 // Setting icmp_timestamp tells fping to use ICMP Timestamp (ICMP type 13) instead // of ICMP Echo diff --git a/plugins/check_game.c b/plugins/check_game.c index c0193b03..974a7253 100644 --- a/plugins/check_game.c +++ b/plugins/check_game.c @@ -77,7 +77,8 @@ int main(int argc, char **argv) { /* create the command line to execute */ char *command_line = NULL; - xasprintf(&command_line, "%s -raw %s -%s %s", PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, config.game_type, config.server_ip); + xasprintf(&command_line, "%s -raw %s -%s %s", PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, + config.game_type, config.server_ip); if (config.port) { xasprintf(&command_line, "%s:%-d", command_line, config.port); @@ -130,11 +131,13 @@ int main(int argc, char **argv) { printf(_("CRITICAL - Game server timeout\n")); result = STATE_CRITICAL; } else { - printf("OK: %s/%s %s (%s), Ping: %s ms|%s %s\n", ret[config.qstat_game_players], ret[config.qstat_game_players_max], - ret[config.qstat_game_field], ret[config.qstat_map_field], ret[config.qstat_ping_field], - perfdata("players", atol(ret[config.qstat_game_players]), "", false, 0, false, 0, true, 0, true, - atol(ret[config.qstat_game_players_max])), - fperfdata("ping", strtod(ret[config.qstat_ping_field], NULL), "", false, 0, false, 0, true, 0, false, 0)); + printf("OK: %s/%s %s (%s), Ping: %s ms|%s %s\n", ret[config.qstat_game_players], + ret[config.qstat_game_players_max], ret[config.qstat_game_field], + ret[config.qstat_map_field], ret[config.qstat_ping_field], + perfdata("players", atol(ret[config.qstat_game_players]), "", false, 0, false, 0, + true, 0, true, atol(ret[config.qstat_game_players_max])), + fperfdata("ping", strtod(ret[config.qstat_ping_field], NULL), "", false, 0, false, 0, + true, 0, false, 0)); } exit(result); @@ -144,19 +147,20 @@ int main(int argc, char **argv) { #define max_players_field_index 130 check_game_config_wrapper process_arguments(int argc, char **argv) { - static struct option long_opts[] = {{"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"verbose", no_argument, 0, 'v'}, - {"timeout", required_argument, 0, 't'}, - {"hostname", required_argument, 0, 'H'}, - {"port", required_argument, 0, 'P'}, - {"game-type", required_argument, 0, 'G'}, - {"map-field", required_argument, 0, 'm'}, - {"ping-field", required_argument, 0, 'p'}, - {"game-field", required_argument, 0, 'g'}, - {"players-field", required_argument, 0, players_field_index}, - {"max-players-field", required_argument, 0, max_players_field_index}, - {0, 0, 0, 0}}; + static struct option long_opts[] = { + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {"verbose", no_argument, 0, 'v'}, + {"timeout", required_argument, 0, 't'}, + {"hostname", required_argument, 0, 'H'}, + {"port", required_argument, 0, 'P'}, + {"game-type", required_argument, 0, 'G'}, + {"map-field", required_argument, 0, 'm'}, + {"ping-field", required_argument, 0, 'p'}, + {"game-field", required_argument, 0, 'g'}, + {"players-field", required_argument, 0, players_field_index}, + {"max-players-field", required_argument, 0, max_players_field_index}, + {0, 0, 0, 0}}; check_game_config_wrapper result = { .config = check_game_config_init(), @@ -216,21 +220,24 @@ check_game_config_wrapper process_arguments(int argc, char **argv) { break; case 'p': /* index of ping field */ result.config.qstat_ping_field = atoi(optarg); - if (result.config.qstat_ping_field < 0 || result.config.qstat_ping_field > QSTAT_MAX_RETURN_ARGS) { + if (result.config.qstat_ping_field < 0 || + result.config.qstat_ping_field > QSTAT_MAX_RETURN_ARGS) { result.errorcode = ERROR; return result; } break; case 'm': /* index on map field */ result.config.qstat_map_field = atoi(optarg); - if (result.config.qstat_map_field < 0 || result.config.qstat_map_field > QSTAT_MAX_RETURN_ARGS) { + if (result.config.qstat_map_field < 0 || + result.config.qstat_map_field > QSTAT_MAX_RETURN_ARGS) { result.errorcode = ERROR; return result; } break; case 'g': /* index of game field */ result.config.qstat_game_field = atoi(optarg); - if (result.config.qstat_game_field < 0 || result.config.qstat_game_field > QSTAT_MAX_RETURN_ARGS) { + if (result.config.qstat_game_field < 0 || + result.config.qstat_game_field > QSTAT_MAX_RETURN_ARGS) { result.errorcode = ERROR; return result; } @@ -240,14 +247,16 @@ check_game_config_wrapper process_arguments(int argc, char **argv) { if (result.config.qstat_game_players_max == 0) { result.config.qstat_game_players_max = result.config.qstat_game_players - 1; } - if (result.config.qstat_game_players < 0 || result.config.qstat_game_players > QSTAT_MAX_RETURN_ARGS) { + if (result.config.qstat_game_players < 0 || + result.config.qstat_game_players > QSTAT_MAX_RETURN_ARGS) { result.errorcode = ERROR; return result; } break; case max_players_field_index: /* index of max players field */ result.config.qstat_game_players_max = atoi(optarg); - if (result.config.qstat_game_players_max < 0 || result.config.qstat_game_players_max > QSTAT_MAX_RETURN_ARGS) { + if (result.config.qstat_game_players_max < 0 || + result.config.qstat_game_players_max > QSTAT_MAX_RETURN_ARGS) { result.errorcode = ERROR; return result; } @@ -286,7 +295,7 @@ void print_help(void) { printf(UT_HELP_VRSN); printf(UT_EXTRA_OPTS); printf(" -H, --hostname=ADDRESS\n" - " Host name, IP Address, or unix socket (must be an absolute path)\n"); + " Host name, IP Address, or unix socket (must be an absolute path)\n"); printf(" %s\n", "-P"); printf(" %s\n", _("Optional port to connect to")); printf(" %s\n", "-g"); @@ -300,8 +309,10 @@ void print_help(void) { printf("\n"); printf("%s\n", _("Notes:")); - printf(" %s\n", _("This plugin uses the 'qstat' command, the popular game server status query tool.")); - printf(" %s\n", _("If you don't have the package installed, you will need to download it from")); + printf(" %s\n", + _("This plugin uses the 'qstat' command, the popular game server status query tool.")); + printf(" %s\n", + _("If you don't have the package installed, you will need to download it from")); printf(" %s\n", _("https://github.com/multiplay/qstat before you can use this plugin.")); printf(UT_SUPPORT); @@ -309,7 +320,8 @@ void print_help(void) { void print_usage(void) { printf("%s\n", _("Usage:")); - printf(" %s [-hvV] [-P port] [-t timeout] [-g game_field] [-m map_field] [-p ping_field] [-G game-time] [-H hostname] " + printf(" %s [-hvV] [-P port] [-t timeout] [-g game_field] [-m map_field] [-p ping_field] [-G " + "game-time] [-H hostname] " "\n", progname); } diff --git a/plugins/check_hpjd.c b/plugins/check_hpjd.c index 62417fd6..9907abc5 100644 --- a/plugins/check_hpjd.c +++ b/plugins/check_hpjd.c @@ -85,13 +85,16 @@ int main(int argc, char **argv) { char query_string[512]; /* removed ' 2>1' at end of command 10/27/1999 - EG */ /* create the query string */ - sprintf(query_string, "%s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0", HPJD_LINE_STATUS, HPJD_PAPER_STATUS, - HPJD_INTERVENTION_REQUIRED, HPJD_GD_PERIPHERAL_ERROR, HPJD_GD_PAPER_JAM, HPJD_GD_PAPER_OUT, HPJD_GD_TONER_LOW, - HPJD_GD_PAGE_PUNT, HPJD_GD_MEMORY_OUT, HPJD_GD_DOOR_OPEN, HPJD_GD_PAPER_OUTPUT, HPJD_GD_STATUS_DISPLAY); + sprintf(query_string, "%s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0", + HPJD_LINE_STATUS, HPJD_PAPER_STATUS, HPJD_INTERVENTION_REQUIRED, + HPJD_GD_PERIPHERAL_ERROR, HPJD_GD_PAPER_JAM, HPJD_GD_PAPER_OUT, HPJD_GD_TONER_LOW, + HPJD_GD_PAGE_PUNT, HPJD_GD_MEMORY_OUT, HPJD_GD_DOOR_OPEN, HPJD_GD_PAPER_OUTPUT, + HPJD_GD_STATUS_DISPLAY); /* get the command to run */ char command_line[1024]; - sprintf(command_line, "%s -OQa -m : -v 1 -c %s %s:%u %s", PATH_TO_SNMPGET, config.community, config.address, config.port, query_string); + sprintf(command_line, "%s -OQa -m : -v 1 -c %s %s:%u %s", PATH_TO_SNMPGET, config.community, + config.address, config.port, query_string); /* run the command */ child_process = spopen(command_line); @@ -177,7 +180,8 @@ int main(int argc, char **argv) { strcpy(display_message, temp_buffer + 1); break; default: /* fold multiline message */ - strncat(display_message, input_buffer, sizeof(display_message) - strlen(display_message) - 1); + strncat(display_message, input_buffer, + sizeof(display_message) - strlen(display_message) - 1); } } diff --git a/plugins/check_ldap.c b/plugins/check_ldap.c index 597644bd..77a33304 100644 --- a/plugins/check_ldap.c +++ b/plugins/check_ldap.c @@ -108,7 +108,8 @@ int main(int argc, char *argv[]) { #ifdef HAVE_LDAP_SET_OPTION /* set ldap options */ - if (ldap_set_option(ldap_connection, LDAP_OPT_PROTOCOL_VERSION, &config.ld_protocol) != LDAP_OPT_SUCCESS) { + if (ldap_set_option(ldap_connection, LDAP_OPT_PROTOCOL_VERSION, &config.ld_protocol) != + LDAP_OPT_SUCCESS) { printf(_("Could not set protocol version %d\n"), config.ld_protocol); return STATE_CRITICAL; } @@ -135,7 +136,8 @@ int main(int argc, char *argv[]) { } else if (config.starttls) { #if defined(HAVE_LDAP_SET_OPTION) && defined(HAVE_LDAP_START_TLS_S) /* ldap with startTLS: set option version */ - if (ldap_get_option(ldap_connection, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) { + if (ldap_get_option(ldap_connection, LDAP_OPT_PROTOCOL_VERSION, &version) == + LDAP_OPT_SUCCESS) { if (version < LDAP_VERSION3) { version = LDAP_VERSION3; ldap_set_option(ldap_connection, LDAP_OPT_PROTOCOL_VERSION, &version); @@ -156,7 +158,8 @@ int main(int argc, char *argv[]) { } /* bind to the ldap server */ - if (ldap_bind_s(ldap_connection, config.ld_binddn, config.ld_passwd, LDAP_AUTH_SIMPLE) != LDAP_SUCCESS) { + if (ldap_bind_s(ldap_connection, config.ld_binddn, config.ld_passwd, LDAP_AUTH_SIMPLE) != + LDAP_SUCCESS) { if (verbose) { ldap_perror(ldap_connection, "ldap_bind"); } @@ -168,8 +171,10 @@ int main(int argc, char *argv[]) { int num_entries = 0; /* do a search of all objectclasses in the base dn */ if (ldap_search_s(ldap_connection, config.ld_base, - (config.crit_entries != NULL || config.warn_entries != NULL) ? LDAP_SCOPE_SUBTREE : LDAP_SCOPE_BASE, config.ld_attr, - NULL, 0, &result) != LDAP_SUCCESS) { + (config.crit_entries != NULL || config.warn_entries != NULL) + ? LDAP_SCOPE_SUBTREE + : LDAP_SCOPE_BASE, + config.ld_attr, NULL, 0, &result) != LDAP_SUCCESS) { if (verbose) { ldap_perror(ldap_connection, "ldap_search"); } @@ -215,14 +220,16 @@ int main(int argc, char *argv[]) { /* print out the result */ if (config.crit_entries != NULL || config.warn_entries != NULL) { - printf(_("LDAP %s - found %d entries in %.3f seconds|%s %s\n"), state_text(status), num_entries, elapsed_time, - fperfdata("time", elapsed_time, "s", config.warn_time_set, config.warn_time, config.crit_time_set, config.crit_time, true, 0, - false, 0), - sperfdata("entries", (double)num_entries, "", config.warn_entries, config.crit_entries, true, 0.0, false, 0.0)); + printf(_("LDAP %s - found %d entries in %.3f seconds|%s %s\n"), state_text(status), + num_entries, elapsed_time, + fperfdata("time", elapsed_time, "s", config.warn_time_set, config.warn_time, + config.crit_time_set, config.crit_time, true, 0, false, 0), + sperfdata("entries", (double)num_entries, "", config.warn_entries, + config.crit_entries, true, 0.0, false, 0.0)); } else { printf(_("LDAP %s - %.3f seconds response time|%s\n"), state_text(status), elapsed_time, - fperfdata("time", elapsed_time, "s", config.warn_time_set, config.warn_time, config.crit_time_set, config.crit_time, true, 0, - false, 0)); + fperfdata("time", elapsed_time, "s", config.warn_time_set, config.warn_time, + config.crit_time_set, config.crit_time, true, 0, false, 0)); } exit(status); @@ -273,7 +280,8 @@ check_ldap_config_wrapper process_arguments(int argc, char **argv) { int option = 0; while (true) { - int option_index = getopt_long(argc, argv, "hvV234TS6t:c:w:H:b:p:a:D:P:C:W:", longopts, &option); + int option_index = + getopt_long(argc, argv, "hvV234TS6t:c:w:H:b:p:a:D:P:C:W:", longopts, &option); if (option_index == -1 || option_index == EOF) { break; @@ -381,7 +389,8 @@ check_ldap_config_wrapper process_arguments(int argc, char **argv) { result.config.ld_port = DEFAULT_PORT; } - if (strstr(argv[0], "check_ldaps") && !result.config.starttls && !result.config.ssl_on_connect) { + if (strstr(argv[0], "check_ldaps") && !result.config.starttls && + !result.config.ssl_on_connect) { result.config.starttls = true; } @@ -398,7 +407,8 @@ check_ldap_config_wrapper validate_arguments(check_ldap_config_wrapper config_wr } if (config_wrapper.config.crit_entries != NULL || config_wrapper.config.warn_entries != NULL) { - set_thresholds(&config_wrapper.config.entries_thresholds, config_wrapper.config.warn_entries, config_wrapper.config.crit_entries); + set_thresholds(&config_wrapper.config.entries_thresholds, + config_wrapper.config.warn_entries, config_wrapper.config.crit_entries); } if (config_wrapper.config.ld_passwd == NULL) { @@ -435,11 +445,13 @@ void print_help(void) { printf(" %s\n", "-D [--bind]"); printf(" %s\n", _("ldap bind DN (if required)")); printf(" %s\n", "-P [--pass]"); - printf(" %s\n", _("ldap password (if required, or set the password through environment variable 'LDAP_PASSWORD')")); + printf(" %s\n", _("ldap password (if required, or set the password through environment " + "variable 'LDAP_PASSWORD')")); printf(" %s\n", "-T [--starttls]"); printf(" %s\n", _("use starttls mechanism introduced in protocol version 3")); printf(" %s\n", "-S [--ssl]"); - printf(" %s %i\n", _("use ldaps (ldap v2 ssl method). this also sets the default port to"), LDAPS_PORT); + printf(" %s %i\n", _("use ldaps (ldap v2 ssl method). this also sets the default port to"), + LDAPS_PORT); #ifdef HAVE_LDAP_SET_OPTION printf(" %s\n", "-2 [--ver2]"); @@ -463,9 +475,11 @@ void print_help(void) { printf("\n"); printf("%s\n", _("Notes:")); printf(" %s\n", _("If this plugin is called via 'check_ldaps', method 'STARTTLS' will be")); - printf(_(" implied (using default port %i) unless --port=636 is specified. In that case\n"), DEFAULT_PORT); + printf(_(" implied (using default port %i) unless --port=636 is specified. In that case\n"), + DEFAULT_PORT); printf(" %s\n", _("'SSL on connect' will be used no matter how the plugin was called.")); - printf(" %s\n", _("This detection is deprecated, please use 'check_ldap' with the '--starttls' or '--ssl' flags")); + printf(" %s\n", _("This detection is deprecated, please use 'check_ldap' with the '--starttls' " + "or '--ssl' flags")); printf(" %s\n", _("to define the behaviour explicitly instead.")); printf(" %s\n", _("The parameters --warn-entries and --crit-entries are optional.")); diff --git a/plugins/check_load.c b/plugins/check_load.c index 2925bff3..f7a6f7fd 100644 --- a/plugins/check_load.c +++ b/plugins/check_load.c @@ -168,7 +168,8 @@ int main(int argc, char **argv) { mp_subcheck scaled_load_sc1 = mp_subcheck_init(); scaled_load_sc1 = mp_set_subcheck_state(scaled_load_sc1, mp_get_pd_status(pd_scaled_load1)); mp_add_perfdata_to_subcheck(&scaled_load_sc1, pd_scaled_load1); - xasprintf(&scaled_load_sc1.output, "1 Minute: %s", pd_value_to_string(pd_scaled_load1.value)); + xasprintf(&scaled_load_sc1.output, "1 Minute: %s", + pd_value_to_string(pd_scaled_load1.value)); mp_add_subcheck_to_subcheck(&scaled_load_sc, scaled_load_sc1); mp_perfdata pd_scaled_load5 = perfdata_init(); @@ -179,7 +180,8 @@ int main(int argc, char **argv) { mp_subcheck scaled_load_sc5 = mp_subcheck_init(); scaled_load_sc5 = mp_set_subcheck_state(scaled_load_sc5, mp_get_pd_status(pd_scaled_load5)); mp_add_perfdata_to_subcheck(&scaled_load_sc5, pd_scaled_load5); - xasprintf(&scaled_load_sc5.output, "5 Minutes: %s", pd_value_to_string(pd_scaled_load5.value)); + xasprintf(&scaled_load_sc5.output, "5 Minutes: %s", + pd_value_to_string(pd_scaled_load5.value)); mp_add_subcheck_to_subcheck(&scaled_load_sc, scaled_load_sc5); mp_perfdata pd_scaled_load15 = perfdata_init(); @@ -188,9 +190,11 @@ int main(int argc, char **argv) { pd_scaled_load15 = mp_pd_set_thresholds(pd_scaled_load15, config.th_load[2]); mp_subcheck scaled_load_sc15 = mp_subcheck_init(); - scaled_load_sc15 = mp_set_subcheck_state(scaled_load_sc15, mp_get_pd_status(pd_scaled_load15)); + scaled_load_sc15 = + mp_set_subcheck_state(scaled_load_sc15, mp_get_pd_status(pd_scaled_load15)); mp_add_perfdata_to_subcheck(&scaled_load_sc15, pd_scaled_load15); - xasprintf(&scaled_load_sc15.output, "15 Minutes: %s", pd_value_to_string(pd_scaled_load15.value)); + xasprintf(&scaled_load_sc15.output, "15 Minutes: %s", + pd_value_to_string(pd_scaled_load15.value)); mp_add_subcheck_to_subcheck(&scaled_load_sc, scaled_load_sc15); mp_add_subcheck_to_check(&overall, scaled_load_sc); @@ -245,11 +249,13 @@ int main(int argc, char **argv) { mp_subcheck top_proc_sc = mp_subcheck_init(); top_proc_sc = mp_set_subcheck_state(top_proc_sc, STATE_OK); top_processes_result top_proc = print_top_consuming_processes(config.n_procs_to_show); - xasprintf(&top_proc_sc.output, "Top %lu CPU time consuming processes", config.n_procs_to_show); + xasprintf(&top_proc_sc.output, "Top %lu CPU time consuming processes", + config.n_procs_to_show); if (top_proc.errorcode == OK) { for (unsigned long i = 0; i < config.n_procs_to_show; i++) { - xasprintf(&top_proc_sc.output, "%s\n%s", top_proc_sc.output, top_proc.top_processes[i]); + xasprintf(&top_proc_sc.output, "%s\n%s", top_proc_sc.output, + top_proc.top_processes[i]); } } @@ -417,7 +423,8 @@ void print_help(void) { void print_usage(void) { printf("%s\n", _("Usage:")); - printf("%s [-r] -w WLOAD1,WLOAD5,WLOAD15 -c CLOAD1,CLOAD5,CLOAD15 [-n NUMBER_OF_PROCS]\n", progname); + printf("%s [-r] -w WLOAD1,WLOAD5,WLOAD15 -c CLOAD1,CLOAD5,CLOAD15 [-n NUMBER_OF_PROCS]\n", + progname); } #ifdef PS_USES_PROCPCPU @@ -462,7 +469,8 @@ static top_processes_result print_top_consuming_processes(unsigned long n_procs_ #ifdef PS_USES_PROCPCPU qsort(chld_out.line + 1, chld_out.lines - 1, sizeof(char *), cmpstringp); #endif /* PS_USES_PROCPCPU */ - unsigned long lines_to_show = chld_out.lines < (size_t)(n_procs_to_show + 1) ? chld_out.lines : n_procs_to_show + 1; + unsigned long lines_to_show = + chld_out.lines < (size_t)(n_procs_to_show + 1) ? chld_out.lines : n_procs_to_show + 1; result.top_processes = calloc(lines_to_show, sizeof(char *)); if (result.top_processes == NULL) { diff --git a/plugins/check_mrtg.c b/plugins/check_mrtg.c index 5bd276dc..4a17049a 100644 --- a/plugins/check_mrtg.c +++ b/plugins/check_mrtg.c @@ -129,7 +129,8 @@ int main(int argc, char **argv) { time_t current_time; time(¤t_time); if (config.expire_minutes > 0 && (current_time - timestamp) > (config.expire_minutes * 60)) { - printf(_("MRTG data has expired (%d minutes old)\n"), (int)((current_time - timestamp) / 60)); + printf(_("MRTG data has expired (%d minutes old)\n"), + (int)((current_time - timestamp) / 60)); return STATE_WARNING; } @@ -148,20 +149,29 @@ int main(int argc, char **argv) { result = STATE_WARNING; } - printf("%s. %s = %lu %s|%s\n", (config.use_average) ? _("Avg") : _("Max"), config.label, rate, config.units, - perfdata(config.label, (long)rate, config.units, config.value_warning_threshold_set, (long)config.value_warning_threshold, - config.value_critical_threshold_set, (long)config.value_critical_threshold, 0, 0, 0, 0)); + printf("%s. %s = %lu %s|%s\n", (config.use_average) ? _("Avg") : _("Max"), config.label, rate, + config.units, + perfdata(config.label, (long)rate, config.units, config.value_warning_threshold_set, + (long)config.value_warning_threshold, config.value_critical_threshold_set, + (long)config.value_critical_threshold, 0, 0, 0, 0)); return result; } /* process command-line arguments */ check_mrtg_config_wrapper process_arguments(int argc, char **argv) { - static struct option longopts[] = { - {"logfile", required_argument, 0, 'F'}, {"expires", required_argument, 0, 'e'}, {"aggregation", required_argument, 0, 'a'}, - {"variable", required_argument, 0, 'v'}, {"critical", required_argument, 0, 'c'}, {"warning", required_argument, 0, 'w'}, - {"label", required_argument, 0, 'l'}, {"units", required_argument, 0, 'u'}, {"variable", required_argument, 0, 'v'}, - {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}}; + static struct option longopts[] = {{"logfile", required_argument, 0, 'F'}, + {"expires", required_argument, 0, 'e'}, + {"aggregation", required_argument, 0, 'a'}, + {"variable", required_argument, 0, 'v'}, + {"critical", required_argument, 0, 'c'}, + {"warning", required_argument, 0, 'w'}, + {"label", required_argument, 0, 'l'}, + {"units", required_argument, 0, 'u'}, + {"variable", required_argument, 0, 'v'}, + {"version", no_argument, 0, 'V'}, + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0}}; check_mrtg_config_wrapper result = { .errorcode = OK, @@ -242,7 +252,9 @@ check_mrtg_config_wrapper process_arguments(int argc, char **argv) { if (is_intpos(argv[option_char])) { result.config.expire_minutes = atoi(argv[option_char++]); } else { - die(STATE_UNKNOWN, _("%s is not a valid expiration time\nUse '%s -h' for additional help\n"), argv[option_char], progname); + die(STATE_UNKNOWN, + _("%s is not a valid expiration time\nUse '%s -h' for additional help\n"), + argv[option_char], progname); } } @@ -334,25 +346,32 @@ void print_help(void) { printf(" %s\n", _("\"Bytes Per Second\", \"%% Utilization\")")); printf("\n"); - printf(" %s\n", _("If the value exceeds the threshold, a WARNING status is returned. If")); + printf(" %s\n", + _("If the value exceeds the threshold, a WARNING status is returned. If")); printf(" %s\n", _("the value exceeds the threshold, a CRITICAL status is returned. If")); printf(" %s\n", _("the data in the log file is older than old, a WARNING")); printf(" %s\n", _("status is returned and a warning message is printed.")); printf("\n"); - printf(" %s\n", _("This plugin is useful for monitoring MRTG data that does not correspond to")); - printf(" %s\n", _("bandwidth usage. (Use the check_mrtgtraf plugin for monitoring bandwidth).")); - printf(" %s\n", _("It can be used to monitor any kind of data that MRTG is monitoring - errors,")); - printf(" %s\n", _("packets/sec, etc. I use MRTG in conjunction with the Novell NLM that allows")); + printf(" %s\n", + _("This plugin is useful for monitoring MRTG data that does not correspond to")); + printf(" %s\n", + _("bandwidth usage. (Use the check_mrtgtraf plugin for monitoring bandwidth).")); + printf(" %s\n", + _("It can be used to monitor any kind of data that MRTG is monitoring - errors,")); + printf(" %s\n", + _("packets/sec, etc. I use MRTG in conjunction with the Novell NLM that allows")); printf(" %s\n", _("me to track processor utilization, user connections, drive space, etc and")); printf(" %s\n\n", _("this plugin works well for monitoring that kind of data as well.")); printf("%s\n", _("Notes:")); - printf(" %s\n", _("- This plugin only monitors one of the two variables stored in the MRTG log")); + printf(" %s\n", + _("- This plugin only monitors one of the two variables stored in the MRTG log")); printf(" %s\n", _("file. If you want to monitor both values you will have to define two")); printf(" %s\n", _("commands with different values for the argument. Of course,")); printf(" %s\n", _("you can always hack the code to make this plugin work for you...")); - printf(" %s\n", _("- MRTG stands for the Multi Router Traffic Grapher. It can be downloaded from")); + printf(" %s\n", + _("- MRTG stands for the Multi Router Traffic Grapher. It can be downloaded from")); printf(" %s\n", "http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html"); printf(UT_SUPPORT); diff --git a/plugins/check_mrtgtraf.c b/plugins/check_mrtgtraf.c index 8c7cf8aa..10ce936f 100644 --- a/plugins/check_mrtgtraf.c +++ b/plugins/check_mrtgtraf.c @@ -122,7 +122,8 @@ int main(int argc, char **argv) { time_t current_time; time(¤t_time); if ((config.expire_minutes > 0) && (current_time - timestamp) > (config.expire_minutes * 60)) { - die(STATE_WARNING, _("MRTG data has expired (%d minutes old)\n"), (int)((current_time - timestamp) / 60)); + die(STATE_WARNING, _("MRTG data has expired (%d minutes old)\n"), + (int)((current_time - timestamp) / 60)); } unsigned long incoming_rate = 0L; @@ -177,21 +178,26 @@ int main(int argc, char **argv) { } int result = STATE_OK; - if (incoming_rate > config.incoming_critical_threshold || outgoing_rate > config.outgoing_critical_threshold) { + if (incoming_rate > config.incoming_critical_threshold || + outgoing_rate > config.outgoing_critical_threshold) { result = STATE_CRITICAL; - } else if (incoming_rate > config.incoming_warning_threshold || outgoing_rate > config.outgoing_warning_threshold) { + } else if (incoming_rate > config.incoming_warning_threshold || + outgoing_rate > config.outgoing_warning_threshold) { result = STATE_WARNING; } char *error_message; - xasprintf(&error_message, _("%s. In = %0.1f %s/s, %s. Out = %0.1f %s/s|%s %s\n"), (config.use_average) ? _("Avg") : _("Max"), - adjusted_incoming_rate, incoming_speed_rating, (config.use_average) ? _("Avg") : _("Max"), adjusted_outgoing_rate, - outgoing_speed_rating, - fperfdata("in", adjusted_incoming_rate, incoming_speed_rating, (int)config.incoming_warning_threshold, - config.incoming_warning_threshold, (int)config.incoming_critical_threshold, config.incoming_critical_threshold, + xasprintf(&error_message, _("%s. In = %0.1f %s/s, %s. Out = %0.1f %s/s|%s %s\n"), + (config.use_average) ? _("Avg") : _("Max"), adjusted_incoming_rate, + incoming_speed_rating, (config.use_average) ? _("Avg") : _("Max"), + adjusted_outgoing_rate, outgoing_speed_rating, + fperfdata("in", adjusted_incoming_rate, incoming_speed_rating, + (int)config.incoming_warning_threshold, config.incoming_warning_threshold, + (int)config.incoming_critical_threshold, config.incoming_critical_threshold, true, 0, false, 0), - fperfdata("out", adjusted_outgoing_rate, outgoing_speed_rating, (int)config.outgoing_warning_threshold, - config.outgoing_warning_threshold, (int)config.outgoing_critical_threshold, config.outgoing_critical_threshold, + fperfdata("out", adjusted_outgoing_rate, outgoing_speed_rating, + (int)config.outgoing_warning_threshold, config.outgoing_warning_threshold, + (int)config.outgoing_critical_threshold, config.outgoing_critical_threshold, true, 0, false, 0)); printf(_("Traffic %s - %s\n"), state_text(result), error_message); @@ -249,10 +255,12 @@ check_mrtgtraf_config_wrapper process_arguments(int argc, char **argv) { result.config.use_average = (bool)(strcmp(optarg, "MAX")); break; case 'c': /* warning threshold */ - sscanf(optarg, "%lu,%lu", &result.config.incoming_critical_threshold, &result.config.outgoing_critical_threshold); + sscanf(optarg, "%lu,%lu", &result.config.incoming_critical_threshold, + &result.config.outgoing_critical_threshold); break; case 'w': /* critical threshold */ - sscanf(optarg, "%lu,%lu", &result.config.incoming_warning_threshold, &result.config.outgoing_warning_threshold); + sscanf(optarg, "%lu,%lu", &result.config.incoming_warning_threshold, + &result.config.outgoing_warning_threshold); break; case 'V': /* version */ print_revision(progname, NP_VERSION); diff --git a/plugins/check_mysql.c b/plugins/check_mysql.c index ca3422b5..3d7ec4cd 100644 --- a/plugins/check_mysql.c +++ b/plugins/check_mysql.c @@ -50,15 +50,23 @@ static int verbose = 0; #define LENGTH_METRIC_UNIT 6 static const char *metric_unit[LENGTH_METRIC_UNIT] = { - "Open_files", "Open_tables", "Qcache_free_memory", "Qcache_queries_in_cache", "Threads_connected", "Threads_running"}; + "Open_files", "Open_tables", "Qcache_free_memory", "Qcache_queries_in_cache", + "Threads_connected", "Threads_running"}; #define LENGTH_METRIC_COUNTER 9 -static const char *metric_counter[LENGTH_METRIC_COUNTER] = { - "Connections", "Qcache_hits", "Qcache_inserts", "Qcache_lowmem_prunes", "Qcache_not_cached", "Queries", - "Questions", "Table_locks_waited", "Uptime"}; - -#define MYSQLDUMP_THREADS_QUERY \ - "SELECT COUNT(1) mysqldumpThreads FROM information_schema.processlist WHERE info LIKE 'SELECT /*!40001 SQL_NO_CACHE */%'" +static const char *metric_counter[LENGTH_METRIC_COUNTER] = {"Connections", + "Qcache_hits", + "Qcache_inserts", + "Qcache_lowmem_prunes", + "Qcache_not_cached", + "Queries", + "Questions", + "Table_locks_waited", + "Uptime"}; + +#define MYSQLDUMP_THREADS_QUERY \ + "SELECT COUNT(1) mysqldumpThreads FROM information_schema.processlist WHERE info LIKE " \ + "'SELECT /*!40001 SQL_NO_CACHE */%'" typedef struct { int errorcode; @@ -99,16 +107,19 @@ int main(int argc, char **argv) { } if (config.ssl) { - mysql_ssl_set(&mysql, config.key, config.cert, config.ca_cert, config.ca_dir, config.ciphers); + mysql_ssl_set(&mysql, config.key, config.cert, config.ca_cert, config.ca_dir, + config.ciphers); } /* establish a connection to the server and error checking */ - if (!mysql_real_connect(&mysql, config.db_host, config.db_user, config.db_pass, config.db, config.db_port, config.db_socket, 0)) { + if (!mysql_real_connect(&mysql, config.db_host, config.db_user, config.db_pass, config.db, + config.db_port, config.db_socket, 0)) { /* Depending on internally-selected auth plugin MySQL might return */ /* ER_ACCESS_DENIED_NO_PASSWORD_ERROR or ER_ACCESS_DENIED_ERROR. */ /* Semantically these errors are the same. */ - if (config.ignore_auth && - (mysql_errno(&mysql) == ER_ACCESS_DENIED_ERROR || mysql_errno(&mysql) == ER_ACCESS_DENIED_NO_PASSWORD_ERROR)) { - printf("MySQL OK - Version: %s (protocol %d)\n", mysql_get_server_info(&mysql), mysql_get_proto_info(&mysql)); + if (config.ignore_auth && (mysql_errno(&mysql) == ER_ACCESS_DENIED_ERROR || + mysql_errno(&mysql) == ER_ACCESS_DENIED_NO_PASSWORD_ERROR)) { + printf("MySQL OK - Version: %s (protocol %d)\n", mysql_get_server_info(&mysql), + mysql_get_proto_info(&mysql)); mysql_close(&mysql); return STATE_OK; } @@ -157,13 +168,17 @@ int main(int argc, char **argv) { while ((row = mysql_fetch_row(res)) != NULL) { for (int i = 0; i < LENGTH_METRIC_UNIT; i++) { if (strcmp(row[0], metric_unit[i]) == 0) { - xasprintf(&perf, "%s%s ", perf, perfdata(metric_unit[i], atol(row[1]), "", false, 0, false, 0, false, 0, false, 0)); + xasprintf(&perf, "%s%s ", perf, + perfdata(metric_unit[i], atol(row[1]), "", false, 0, false, 0, false, + 0, false, 0)); continue; } } for (int i = 0; i < LENGTH_METRIC_COUNTER; i++) { if (strcmp(row[0], metric_counter[i]) == 0) { - xasprintf(&perf, "%s%s ", perf, perfdata(metric_counter[i], atol(row[1]), "c", false, 0, false, 0, false, 0, false, 0)); + xasprintf(&perf, "%s%s ", perf, + perfdata(metric_counter[i], atol(row[1]), "c", false, 0, false, 0, + false, 0, false, 0)); continue; } } @@ -189,8 +204,8 @@ int main(int argc, char **argv) { unsigned long minor_version = (server_verion_int % 10000) / 100; unsigned long patch_version = (server_verion_int % 100); if (verbose) { - printf("Found MariaDB: %s, main version: %lu, minor version: %lu, patch version: %lu\n", server_version, major_version, - minor_version, patch_version); + printf("Found MariaDB: %s, main version: %lu, minor version: %lu, patch version: %lu\n", + server_version, major_version, minor_version, patch_version); } if (strstr(server_version, "MariaDB") != NULL) { @@ -292,11 +307,15 @@ int main(int argc, char **argv) { } /* Save replica status in replica_result */ - snprintf(replica_result, REPLICA_RESULTSIZE, "Replica IO: %s Replica SQL: %s Seconds Behind Master: %s", row[replica_io_field], - row[replica_sql_field], seconds_behind_field != -1 ? row[seconds_behind_field] : "Unknown"); - - /* Raise critical error if SQL THREAD or IO THREAD are stopped, but only if there are no mysqldump threads running */ - if (strcmp(row[replica_io_field], "Yes") != 0 || strcmp(row[replica_sql_field], "Yes") != 0) { + snprintf(replica_result, REPLICA_RESULTSIZE, + "Replica IO: %s Replica SQL: %s Seconds Behind Master: %s", + row[replica_io_field], row[replica_sql_field], + seconds_behind_field != -1 ? row[seconds_behind_field] : "Unknown"); + + /* Raise critical error if SQL THREAD or IO THREAD are stopped, but only if there are no + * mysqldump threads running */ + if (strcmp(row[replica_io_field], "Yes") != 0 || + strcmp(row[replica_sql_field], "Yes") != 0) { MYSQL_RES *res_mysqldump; MYSQL_ROW row_mysqldump; unsigned int mysqldump_threads = 0; @@ -325,20 +344,23 @@ int main(int argc, char **argv) { if (seconds_behind_field == -1) { printf("seconds_behind_field not found\n"); } else { - printf("seconds_behind_field(index %d)=%s\n", seconds_behind_field, row[seconds_behind_field]); + printf("seconds_behind_field(index %d)=%s\n", seconds_behind_field, + row[seconds_behind_field]); } } /* Check Seconds Behind against threshold */ - if ((seconds_behind_field != -1) && (row[seconds_behind_field] != NULL && strcmp(row[seconds_behind_field], "NULL") != 0)) { + if ((seconds_behind_field != -1) && (row[seconds_behind_field] != NULL && + strcmp(row[seconds_behind_field], "NULL") != 0)) { double value = atof(row[seconds_behind_field]); int status; status = get_status(value, config.my_threshold); xasprintf(&perf, "%s %s", perf, - fperfdata("seconds behind master", value, "s", true, (double)config.warning_time, true, - (double)config.critical_time, false, 0, false, 0)); + fperfdata("seconds behind master", value, "s", true, + (double)config.warning_time, true, (double)config.critical_time, + false, 0, false, 0)); if (status == STATE_WARNING) { printf("SLOW_REPLICA %s: %s|%s\n", _("WARNING"), replica_result, perf); @@ -410,7 +432,8 @@ check_mysql_config_wrapper process_arguments(int argc, char **argv) { int option = 0; while (true) { - int option_index = getopt_long(argc, argv, "hlvVnSP:p:u:d:H:s:c:w:a:k:C:D:L:f:g:", longopts, &option); + int option_index = + getopt_long(argc, argv, "hlvVnSP:p:u:d:H:s:c:w:a:k:C:D:L:f:g:", longopts, &option); if (option_index == -1 || option_index == EOF) { break; @@ -580,15 +603,17 @@ void print_help(void) { printf(" ==> %s <==\n", _("IMPORTANT: THIS FORM OF AUTHENTICATION IS NOT SECURE!!!")); printf(" %s\n", _("Your clear-text password could be visible as a process table entry")); printf(" %s\n", "-S, --check-slave"); - printf(" %s\n", - _("Check if the slave thread is running properly. This option is deprecated in favour of check-replica, which does the same")); + printf(" %s\n", _("Check if the slave thread is running properly. This option is deprecated " + "in favour of check-replica, which does the same")); printf(" %s\n", "--check-replica"); printf(" %s\n", _("Check if the replica thread is running properly.")); printf(" %s\n", "-w, --warning"); - printf(" %s\n", _("Exit with WARNING status if replica server is more than INTEGER seconds")); + printf(" %s\n", + _("Exit with WARNING status if replica server is more than INTEGER seconds")); printf(" %s\n", _("behind master")); printf(" %s\n", "-c, --critical"); - printf(" %s\n", _("Exit with CRITICAL status if replica server is more then INTEGER seconds")); + printf(" %s\n", + _("Exit with CRITICAL status if replica server is more then INTEGER seconds")); printf(" %s\n", _("behind master")); printf(" %s\n", "-l, --ssl"); printf(" %s\n", _("Use ssl encryption")); @@ -604,7 +629,8 @@ void print_help(void) { printf(" %s\n", _("List of valid SSL ciphers")); printf("\n"); - printf(" %s\n", _("There are no required arguments. By default, the local database is checked")); + printf(" %s\n", + _("There are no required arguments. By default, the local database is checked")); printf(" %s\n", _("using the default unix socket. You can force TCP on localhost by using an")); printf(" %s\n", _("IP address or FQDN ('localhost' will use the socket as well).")); diff --git a/plugins/check_mysql_query.c b/plugins/check_mysql_query.c index 5e04a94b..c7e84deb 100644 --- a/plugins/check_mysql_query.c +++ b/plugins/check_mysql_query.c @@ -47,7 +47,8 @@ typedef struct { check_mysql_query_config config; } check_mysql_query_config_wrapper; static check_mysql_query_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); -static check_mysql_query_config_wrapper validate_arguments(check_mysql_query_config_wrapper /*config_wrapper*/); +static check_mysql_query_config_wrapper + validate_arguments(check_mysql_query_config_wrapper /*config_wrapper*/); static void print_help(void); void print_usage(void); @@ -83,7 +84,8 @@ int main(int argc, char **argv) { } /* establish a connection to the server and error checking */ - if (!mysql_real_connect(&mysql, config.db_host, config.db_user, config.db_pass, config.db, config.db_port, config.db_socket, 0)) { + if (!mysql_real_connect(&mysql, config.db_host, config.db_user, config.db_pass, config.db, + config.db_port, config.db_socket, 0)) { if (mysql_errno(&mysql) == CR_UNKNOWN_HOST) { die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql)); } else if (mysql_errno(&mysql) == CR_VERSION_ERROR) { @@ -155,8 +157,11 @@ int main(int argc, char **argv) { printf("QUERY %s: ", _("CRITICAL")); } printf(_("'%s' returned %f | %s"), config.sql_query, value, - fperfdata("result", value, "", config.my_thresholds->warning, config.my_thresholds->warning ? config.my_thresholds->warning->end : 0, - config.my_thresholds->critical, config.my_thresholds->critical ? config.my_thresholds->critical->end : 0, false, 0, false, 0)); + fperfdata("result", value, "", config.my_thresholds->warning, + config.my_thresholds->warning ? config.my_thresholds->warning->end : 0, + config.my_thresholds->critical, + config.my_thresholds->critical ? config.my_thresholds->critical->end : 0, + false, 0, false, 0)); printf("\n"); return status; @@ -164,12 +169,21 @@ int main(int argc, char **argv) { /* process command-line arguments */ check_mysql_query_config_wrapper process_arguments(int argc, char **argv) { - static struct option longopts[] = { - {"hostname", required_argument, 0, 'H'}, {"socket", required_argument, 0, 's'}, {"database", required_argument, 0, 'd'}, - {"username", required_argument, 0, 'u'}, {"password", required_argument, 0, 'p'}, {"file", required_argument, 0, 'f'}, - {"group", required_argument, 0, 'g'}, {"port", required_argument, 0, 'P'}, {"verbose", no_argument, 0, 'v'}, - {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {"query", required_argument, 0, 'q'}, - {"warning", required_argument, 0, 'w'}, {"critical", required_argument, 0, 'c'}, {0, 0, 0, 0}}; + static struct option longopts[] = {{"hostname", required_argument, 0, 'H'}, + {"socket", required_argument, 0, 's'}, + {"database", required_argument, 0, 'd'}, + {"username", required_argument, 0, 'u'}, + {"password", required_argument, 0, 'p'}, + {"file", required_argument, 0, 'f'}, + {"group", required_argument, 0, 'g'}, + {"port", required_argument, 0, 'P'}, + {"verbose", no_argument, 0, 'v'}, + {"version", no_argument, 0, 'V'}, + {"help", no_argument, 0, 'h'}, + {"query", required_argument, 0, 'q'}, + {"warning", required_argument, 0, 'w'}, + {"critical", required_argument, 0, 'c'}, + {0, 0, 0, 0}}; check_mysql_query_config_wrapper result = { .errorcode = OK, @@ -255,7 +269,8 @@ check_mysql_query_config_wrapper process_arguments(int argc, char **argv) { return validate_arguments(result); } -check_mysql_query_config_wrapper validate_arguments(check_mysql_query_config_wrapper config_wrapper) { +check_mysql_query_config_wrapper +validate_arguments(check_mysql_query_config_wrapper config_wrapper) { if (config_wrapper.config.sql_query == NULL) { usage("Must specify a SQL query to run"); } diff --git a/plugins/check_nt.c b/plugins/check_nt.c index 7dd23e5c..35ca92cd 100644 --- a/plugins/check_nt.c +++ b/plugins/check_nt.c @@ -96,7 +96,8 @@ int main(int argc, char **argv) { xasprintf(&send_buffer, "%s&1", config.req_password); fetch_data(config.server_address, config.server_port, send_buffer); if (config.value_list != NULL && strcmp(recv_buffer, config.value_list) != 0) { - xasprintf(&output_message, _("Wrong client version - running: %s, required: %s"), recv_buffer, config.value_list); + xasprintf(&output_message, _("Wrong client version - running: %s, required: %s"), + recv_buffer, config.value_list); return_code = STATE_WARNING; } else { xasprintf(&output_message, "%s", recv_buffer); @@ -116,9 +117,12 @@ int main(int argc, char **argv) { /* loop until one of the parameters is wrong or not present */ int offset = 0; - while (lvalue_list[0 + offset] > (unsigned long)0 && lvalue_list[0 + offset] <= (unsigned long)17280 && - lvalue_list[1 + offset] > (unsigned long)0 && lvalue_list[1 + offset] <= (unsigned long)100 && - lvalue_list[2 + offset] > (unsigned long)0 && lvalue_list[2 + offset] <= (unsigned long)100) { + while (lvalue_list[0 + offset] > (unsigned long)0 && + lvalue_list[0 + offset] <= (unsigned long)17280 && + lvalue_list[1 + offset] > (unsigned long)0 && + lvalue_list[1 + offset] <= (unsigned long)100 && + lvalue_list[2 + offset] > (unsigned long)0 && + lvalue_list[2 + offset] <= (unsigned long)100) { /* Send request and retrieve data */ xasprintf(&send_buffer, "%s&2&%lu", config.req_password, lvalue_list[0 + offset]); @@ -133,10 +137,12 @@ int main(int argc, char **argv) { return_code = STATE_WARNING; } - xasprintf(&output_message, _(" %lu%% (%lu min average)"), utilization, lvalue_list[0 + offset]); + xasprintf(&output_message, _(" %lu%% (%lu min average)"), utilization, + lvalue_list[0 + offset]); xasprintf(&temp_string, "%s%s", temp_string, output_message); - xasprintf(&perfdata, _(" '%lu min avg Load'=%lu%%;%lu;%lu;0;100"), lvalue_list[0 + offset], utilization, - lvalue_list[1 + offset], lvalue_list[2 + offset]); + xasprintf(&perfdata, _(" '%lu min avg Load'=%lu%%;%lu;%lu;0;100"), + lvalue_list[0 + offset], utilization, lvalue_list[1 + offset], + lvalue_list[2 + offset]); xasprintf(&temp_string_perf, "%s%s", temp_string_perf, perfdata); offset += 3; /* move across the array */ } @@ -154,8 +160,10 @@ int main(int argc, char **argv) { if (config.value_list == NULL) { tmp_value_list = "minutes"; } - if (strncmp(tmp_value_list, "seconds", strlen("seconds") + 1) && strncmp(tmp_value_list, "minutes", strlen("minutes") + 1) && - strncmp(config.value_list, "hours", strlen("hours") + 1) && strncmp(tmp_value_list, "days", strlen("days") + 1)) { + if (strncmp(tmp_value_list, "seconds", strlen("seconds") + 1) && + strncmp(tmp_value_list, "minutes", strlen("minutes") + 1) && + strncmp(config.value_list, "hours", strlen("hours") + 1) && + strncmp(tmp_value_list, "days", strlen("days") + 1)) { output_message = strdup(_("wrong -l argument")); } else { @@ -175,8 +183,9 @@ int main(int argc, char **argv) { } /* else uptime in seconds, nothing to do */ - xasprintf(&output_message, _("System Uptime - %u day(s) %u hour(s) %u minute(s) |uptime=%lu"), updays, uphours, upminutes, - uptime); + xasprintf(&output_message, + _("System Uptime - %u day(s) %u hour(s) %u minute(s) |uptime=%lu"), updays, + uphours, upminutes, uptime); if (config.check_critical_value && uptime <= config.critical_value) { return_code = STATE_CRITICAL; @@ -207,20 +216,27 @@ int main(int argc, char **argv) { } if (total_disk_space > 0 && free_disk_space >= 0) { - double percent_used_space = ((total_disk_space - free_disk_space) / total_disk_space) * 100; + double percent_used_space = + ((total_disk_space - free_disk_space) / total_disk_space) * 100; double warning_used_space = ((float)config.warning_value / 100) * total_disk_space; - double critical_used_space = ((float)config.critical_value / 100) * total_disk_space; - - xasprintf(&temp_string, _("%s:\\ - total: %.2f Gb - used: %.2f Gb (%.0f%%) - free %.2f Gb (%.0f%%)"), config.value_list, - total_disk_space / 1073741824, (total_disk_space - free_disk_space) / 1073741824, percent_used_space, - free_disk_space / 1073741824, (free_disk_space / total_disk_space) * 100); - xasprintf(&temp_string_perf, _("'%s:\\ Used Space'=%.2fGb;%.2f;%.2f;0.00;%.2f"), config.value_list, - (total_disk_space - free_disk_space) / 1073741824, warning_used_space / 1073741824, - critical_used_space / 1073741824, total_disk_space / 1073741824); + double critical_used_space = + ((float)config.critical_value / 100) * total_disk_space; + + xasprintf( + &temp_string, + _("%s:\\ - total: %.2f Gb - used: %.2f Gb (%.0f%%) - free %.2f Gb (%.0f%%)"), + config.value_list, total_disk_space / 1073741824, + (total_disk_space - free_disk_space) / 1073741824, percent_used_space, + free_disk_space / 1073741824, (free_disk_space / total_disk_space) * 100); + xasprintf(&temp_string_perf, _("'%s:\\ Used Space'=%.2fGb;%.2f;%.2f;0.00;%.2f"), + config.value_list, (total_disk_space - free_disk_space) / 1073741824, + warning_used_space / 1073741824, critical_used_space / 1073741824, + total_disk_space / 1073741824); if (config.check_critical_value && percent_used_space >= config.critical_value) { return_code = STATE_CRITICAL; - } else if (config.check_warning_value && percent_used_space >= config.warning_value) { + } else if (config.check_warning_value && + percent_used_space >= config.warning_value) { return_code = STATE_WARNING; } else { return_code = STATE_OK; @@ -239,8 +255,10 @@ int main(int argc, char **argv) { if (config.value_list == NULL) { output_message = strdup(_("No service/process specified")); } else { - preparelist(config.value_list); /* replace , between services with & to send the request */ - xasprintf(&send_buffer, "%s&%u&%s&%s", config.req_password, (config.vars_to_check == CHECK_SERVICESTATE) ? 5 : 6, + preparelist( + config.value_list); /* replace , between services with & to send the request */ + xasprintf(&send_buffer, "%s&%u&%s&%s", config.req_password, + (config.vars_to_check == CHECK_SERVICESTATE) ? 5 : 6, (config.show_all) ? "ShowAll" : "ShowFail", config.value_list); fetch_data(config.server_address, config.server_port, send_buffer); char *numstr = strtok(recv_buffer, "&"); @@ -271,10 +289,14 @@ int main(int argc, char **argv) { /* Divisor should be 1048567, not 3044515, as we are measuring "Commit Charge" here, which equals RAM + Pagefiles. */ - xasprintf(&output_message, _("Memory usage: total:%.2f MB - used: %.2f MB (%.0f%%) - free: %.2f MB (%.0f%%)"), - mem_commitLimit / 1048567, mem_commitByte / 1048567, percent_used_space, (mem_commitLimit - mem_commitByte) / 1048567, - (mem_commitLimit - mem_commitByte) / mem_commitLimit * 100); - xasprintf(&perfdata, _("'Memory usage'=%.2fMB;%.2f;%.2f;0.00;%.2f"), mem_commitByte / 1048567, warning_used_space / 1048567, + xasprintf( + &output_message, + _("Memory usage: total:%.2f MB - used: %.2f MB (%.0f%%) - free: %.2f MB (%.0f%%)"), + mem_commitLimit / 1048567, mem_commitByte / 1048567, percent_used_space, + (mem_commitLimit - mem_commitByte) / 1048567, + (mem_commitLimit - mem_commitByte) / mem_commitLimit * 100); + xasprintf(&perfdata, _("'Memory usage'=%.2fMB;%.2f;%.2f;0.00;%.2f"), + mem_commitByte / 1048567, warning_used_space / 1048567, critical_used_space / 1048567, mem_commitLimit / 1048567); return_code = STATE_OK; @@ -302,16 +324,17 @@ int main(int argc, char **argv) { the counter unit - that is, the dimensions of the counter you're getting. Examples: pages/s, packets transferred, etc. - 4) If you want, you may provide the minimum and maximum values to expect. They aren't mandatory, - but once specified they MUST have the same order of magnitude and units of -w and -c; otherwise. - strange things will happen when you make graphs of your data. + 4) If you want, you may provide the minimum and maximum values to expect. They aren't + mandatory, but once specified they MUST have the same order of magnitude and units of -w and + -c; otherwise. strange things will happen when you make graphs of your data. */ double counter_value = 0.0; if (config.value_list == NULL) { output_message = strdup(_("No counter specified")); } else { - preparelist(config.value_list); /* replace , between services with & to send the request */ + preparelist( + config.value_list); /* replace , between services with & to send the request */ bool isPercent = (strchr(config.value_list, '%') != NULL); strtok(config.value_list, "&"); /* burn the first parameters */ @@ -358,15 +381,18 @@ int main(int argc, char **argv) { if (allRight) { /* Let's format the output string, finally... */ if (strstr(description, "%") == NULL) { - xasprintf(&output_message, "%s = %.2f %s", description, counter_value, counter_unit); + xasprintf(&output_message, "%s = %.2f %s", description, counter_value, + counter_unit); } else { /* has formatting, will segv if wrong */ xasprintf(&output_message, description, counter_value); } xasprintf(&output_message, "%s |", output_message); xasprintf(&output_message, "%s %s", output_message, - fperfdata(description, counter_value, counter_unit, 1, config.warning_value, 1, config.critical_value, - (!(isPercent) && (minval != NULL)), fminval, (!(isPercent) && (minval != NULL)), fmaxval)); + fperfdata(description, counter_value, counter_unit, 1, + config.warning_value, 1, config.critical_value, + (!(isPercent) && (minval != NULL)), fminval, + (!(isPercent) && (minval != NULL)), fmaxval)); } } @@ -391,7 +417,8 @@ int main(int argc, char **argv) { if (config.value_list == NULL) { output_message = strdup(_("No counter specified")); } else { - preparelist(config.value_list); /* replace , between services with & to send the request */ + preparelist( + config.value_list); /* replace , between services with & to send the request */ xasprintf(&send_buffer, "%s&9&%s", config.req_password, config.value_list); fetch_data(config.server_address, config.server_port, send_buffer); unsigned long age_in_minutes = atoi(strtok(recv_buffer, "&")); @@ -724,25 +751,31 @@ void print_help(void) { printf(" %s\n", "\"%%.f %%%% paging file used.\""); printf(" %s\n", "INSTANCES ="); printf(" %s\n", _("Check any performance counter object of Windows NT/2000.")); - printf(" %s\n", _("Syntax: check_nt -H -p -v INSTANCES -l ")); + printf(" %s\n", + _("Syntax: check_nt -H -p -v INSTANCES -l ")); printf(" %s\n", _(" is a Windows Perfmon Counter object (eg. Process),")); printf(" %s\n", _("if it is two words, it should be enclosed in quotes")); printf(" %s\n", _("The returned results will be a comma-separated list of instances on ")); printf(" %s\n", _(" the selected computer for that object.")); - printf(" %s\n", _("The purpose of this is to be run from command line to determine what instances")); - printf(" %s\n", _(" are available for monitoring without having to log onto the Windows server")); + printf(" %s\n", + _("The purpose of this is to be run from command line to determine what instances")); + printf(" %s\n", + _(" are available for monitoring without having to log onto the Windows server")); printf(" %s\n", _(" to run Perfmon directly.")); - printf(" %s\n", _("It can also be used in scripts that automatically create the monitoring service")); + printf(" %s\n", + _("It can also be used in scripts that automatically create the monitoring service")); printf(" %s\n", _(" configuration files.")); printf(" %s\n", _("Some examples:")); printf(" %s\n\n", _("check_nt -H 192.168.1.1 -p 1248 -v INSTANCES -l Process")); printf("%s\n", _("Notes:")); - printf(" %s\n", _("- The NSClient service should be running on the server to get any information")); + printf(" %s\n", + _("- The NSClient service should be running on the server to get any information")); printf(" %s\n", "(http://nsclient.ready2run.nl)."); printf(" %s\n", _("- Critical thresholds should be lower than warning thresholds")); printf(" %s\n", _("- Default port 1248 is sometimes in use by other services. The error")); - printf(" %s\n", _("output when this happens contains \"Cannot map xxxxx to protocol number\".")); + printf(" %s\n", + _("output when this happens contains \"Cannot map xxxxx to protocol number\".")); printf(" %s\n", _("One fix for this is to change the port to something else on check_nt ")); printf(" %s\n", _("and on the client service it\'s connecting to.")); diff --git a/plugins/check_ntp.c b/plugins/check_ntp.c index d33f8786..b22cc3c1 100644 --- a/plugins/check_ntp.c +++ b/plugins/check_ntp.c @@ -1,34 +1,34 @@ /***************************************************************************** -* -* Monitoring check_ntp plugin -* -* License: GPL -* Copyright (c) 2006 Sean Finney -* Copyright (c) 2006-2024 Monitoring Plugins Development Team -* -* Description: -* -* This file contains the check_ntp plugin -* -* This plugin to check ntp servers independent of any commandline -* programs or external libraries. -* -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* -*****************************************************************************/ + * + * Monitoring check_ntp plugin + * + * License: GPL + * Copyright (c) 2006 Sean Finney + * Copyright (c) 2006-2024 Monitoring Plugins Development Team + * + * Description: + * + * This file contains the check_ntp plugin + * + * This plugin to check ntp servers independent of any commandline + * programs or external libraries. + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + *****************************************************************************/ const char *progname = "check_ntp"; const char *copyright = "2006-2024"; @@ -38,24 +38,24 @@ const char *email = "devel@monitoring-plugins.org"; #include "netutils.h" #include "utils.h" -static char *server_address=NULL; -static int verbose=0; +static char *server_address = NULL; +static int verbose = 0; static bool do_offset = false; -static char *owarn="60"; -static char *ocrit="120"; +static char *owarn = "60"; +static char *ocrit = "120"; static bool do_jitter = false; -static char *jwarn="5000"; -static char *jcrit="10000"; +static char *jwarn = "5000"; +static char *jcrit = "10000"; -static int process_arguments (int /*argc*/, char ** /*argv*/); +static int process_arguments(int /*argc*/, char ** /*argv*/); static thresholds *offset_thresholds = NULL; static thresholds *jitter_thresholds = NULL; -static void print_help (void); -void print_usage (void); +static void print_help(void); +void print_usage(void); /* number of times to perform each request to get a good average. */ #ifndef AVG_NUM -#define AVG_NUM 4 +# define AVG_NUM 4 #endif /* max size of control message data */ @@ -63,17 +63,17 @@ void print_usage (void); /* this structure holds everything in an ntp request/response as per rfc1305 */ typedef struct { - uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ - uint8_t stratum; /* clock stratum */ - int8_t poll; /* polling interval */ - int8_t precision; /* precision of the local clock */ - int32_t rtdelay; /* total rt delay, as a fixed point num. see macros */ - uint32_t rtdisp; /* like above, but for max err to primary src */ - uint32_t refid; /* ref clock identifier */ - uint64_t refts; /* reference timestamp. local time local clock */ - uint64_t origts; /* time at which request departed client */ - uint64_t rxts; /* time at which request arrived at server */ - uint64_t txts; /* time at which request departed server */ + uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ + uint8_t stratum; /* clock stratum */ + int8_t poll; /* polling interval */ + int8_t precision; /* precision of the local clock */ + int32_t rtdelay; /* total rt delay, as a fixed point num. see macros */ + uint32_t rtdisp; /* like above, but for max err to primary src */ + uint32_t refid; /* ref clock identifier */ + uint64_t refts; /* reference timestamp. local time local clock */ + uint64_t origts; /* time at which request departed client */ + uint64_t rxts; /* time at which request arrived at server */ + uint64_t txts; /* time at which request departed server */ } ntp_message; /* this structure holds data about results from querying offset from a peer */ @@ -84,20 +84,20 @@ typedef struct { double rtdelay; /* converted from the ntp_message */ double rtdisp; /* converted from the ntp_message */ double offset[AVG_NUM]; /* offsets from each response */ - uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ + uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ } ntp_server_results; /* this structure holds everything in an ntp control message as per rfc1305 */ typedef struct { - uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ - uint8_t op; /* R,E,M bits and Opcode */ - uint16_t seq; /* Packet sequence */ - uint16_t status; /* Clock status */ - uint16_t assoc; /* Association */ - uint16_t offset; /* Similar to TCP sequence # */ - uint16_t count; /* # bytes of data */ + uint8_t flags; /* byte with leapindicator,vers,mode. see macros */ + uint8_t op; /* R,E,M bits and Opcode */ + uint16_t seq; /* Packet sequence */ + uint16_t status; /* Clock status */ + uint16_t assoc; /* Association */ + uint16_t offset; /* Similar to TCP sequence # */ + uint16_t count; /* # bytes of data */ char data[MAX_CM_SIZE]; /* ASCII data of the request */ - /* NB: not necessarily NULL terminated! */ + /* NB: not necessarily NULL terminated! */ } ntp_control_message; /* this is an association/status-word pair found in control packet responses */ @@ -108,38 +108,50 @@ typedef struct { /* bits 1,2 are the leap indicator */ #define LI_MASK 0xc0 -#define LI(x) ((x&LI_MASK)>>6) -#define LI_SET(x,y) do{ x |= ((y<<6)&LI_MASK); }while(0) +#define LI(x) ((x & LI_MASK) >> 6) +#define LI_SET(x, y) \ + do { \ + x |= ((y << 6) & LI_MASK); \ + } while (0) /* and these are the values of the leap indicator */ -#define LI_NOWARNING 0x00 -#define LI_EXTRASEC 0x01 +#define LI_NOWARNING 0x00 +#define LI_EXTRASEC 0x01 #define LI_MISSINGSEC 0x02 -#define LI_ALARM 0x03 +#define LI_ALARM 0x03 /* bits 3,4,5 are the ntp version */ #define VN_MASK 0x38 -#define VN(x) ((x&VN_MASK)>>3) -#define VN_SET(x,y) do{ x |= ((y<<3)&VN_MASK); }while(0) +#define VN(x) ((x & VN_MASK) >> 3) +#define VN_SET(x, y) \ + do { \ + x |= ((y << 3) & VN_MASK); \ + } while (0) #define VN_RESERVED 0x02 /* bits 6,7,8 are the ntp mode */ #define MODE_MASK 0x07 -#define MODE(x) (x&MODE_MASK) -#define MODE_SET(x,y) do{ x |= (y&MODE_MASK); }while(0) +#define MODE(x) (x & MODE_MASK) +#define MODE_SET(x, y) \ + do { \ + x |= (y & MODE_MASK); \ + } while (0) /* here are some values */ -#define MODE_CLIENT 0x03 +#define MODE_CLIENT 0x03 #define MODE_CONTROLMSG 0x06 /* In control message, bits 8-10 are R,E,M bits */ -#define REM_MASK 0xe0 -#define REM_RESP 0x80 +#define REM_MASK 0xe0 +#define REM_RESP 0x80 #define REM_ERROR 0x40 -#define REM_MORE 0x20 +#define REM_MORE 0x20 /* In control message, bits 11 - 15 are opcode */ #define OP_MASK 0x1f -#define OP_SET(x,y) do{ x |= (y&OP_MASK); }while(0) +#define OP_SET(x, y) \ + do { \ + x |= (y & OP_MASK); \ + } while (0) #define OP_READSTAT 0x01 #define OP_READVAR 0x02 /* In peer status bytes, bits 6,7,8 determine clock selection status */ -#define PEER_SEL(x) ((ntohs(x)>>8)&0x07) -#define PEER_INCLUDED 0x04 +#define PEER_SEL(x) ((ntohs(x) >> 8) & 0x07) +#define PEER_INCLUDED 0x04 #define PEER_SYNCSOURCE 0x06 /** @@ -153,82 +165,92 @@ typedef struct { /* macros to access the left/right 16 bits of a 32-bit ntp "fixed point" number. note that these can be used as lvalues too */ -#define L16(x) (((uint16_t*)&x)[0]) -#define R16(x) (((uint16_t*)&x)[1]) +#define L16(x) (((uint16_t *)&x)[0]) +#define R16(x) (((uint16_t *)&x)[1]) /* macros to access the left/right 32 bits of a 64-bit ntp "fixed point" number. these too can be used as lvalues */ -#define L32(x) (((uint32_t*)&x)[0]) -#define R32(x) (((uint32_t*)&x)[1]) +#define L32(x) (((uint32_t *)&x)[0]) +#define R32(x) (((uint32_t *)&x)[1]) /* ntp wants seconds since 1/1/00, epoch is 1/1/70. this is the difference */ #define EPOCHDIFF 0x83aa7e80UL /* extract a 32-bit ntp fixed point number into a double */ -#define NTP32asDOUBLE(x) (ntohs(L16(x)) + (double)ntohs(R16(x))/65536.0) +#define NTP32asDOUBLE(x) (ntohs(L16(x)) + (double)ntohs(R16(x)) / 65536.0) /* likewise for a 64-bit ntp fp number */ -#define NTP64asDOUBLE(n) (double)(((uint64_t)n)?\ - (ntohl(L32(n))-EPOCHDIFF) + \ - (.00000001*(0.5+(double)(ntohl(R32(n))/42.94967296))):\ - 0) +#define NTP64asDOUBLE(n) \ + (double)(((uint64_t)n) ? (ntohl(L32(n)) - EPOCHDIFF) + \ + (.00000001 * (0.5 + (double)(ntohl(R32(n)) / 42.94967296))) \ + : 0) /* convert a struct timeval to a double */ -#define TVasDOUBLE(x) (double)(x.tv_sec+(0.000001*x.tv_usec)) +#define TVasDOUBLE(x) (double)(x.tv_sec + (0.000001 * x.tv_usec)) /* convert an ntp 64-bit fp number to a struct timeval */ -#define NTP64toTV(n,t) \ - do{ if(!n) t.tv_sec = t.tv_usec = 0; \ - else { \ - t.tv_sec=ntohl(L32(n))-EPOCHDIFF; \ - t.tv_usec=(int)(0.5+(double)(ntohl(R32(n))/4294.967296)); \ - } \ - }while(0) +#define NTP64toTV(n, t) \ + do { \ + if (!n) \ + t.tv_sec = t.tv_usec = 0; \ + else { \ + t.tv_sec = ntohl(L32(n)) - EPOCHDIFF; \ + t.tv_usec = (int)(0.5 + (double)(ntohl(R32(n)) / 4294.967296)); \ + } \ + } while (0) /* convert a struct timeval to an ntp 64-bit fp number */ -#define TVtoNTP64(t,n) \ - do{ if(!t.tv_usec && !t.tv_sec) n=0x0UL; \ - else { \ - L32(n)=htonl(t.tv_sec + EPOCHDIFF); \ - R32(n)=htonl((uint64_t)((4294.967296*t.tv_usec)+.5)); \ - } \ - } while(0) +#define TVtoNTP64(t, n) \ + do { \ + if (!t.tv_usec && !t.tv_sec) \ + n = 0x0UL; \ + else { \ + L32(n) = htonl(t.tv_sec + EPOCHDIFF); \ + R32(n) = htonl((uint64_t)((4294.967296 * t.tv_usec) + .5)); \ + } \ + } while (0) /* NTP control message header is 12 bytes, plus any data in the data * field, plus null padding to the nearest 32-bit boundary per rfc. */ -#define SIZEOF_NTPCM(m) (12+ntohs(m.count)+((ntohs(m.count)%4)?4-(ntohs(m.count)%4):0)) +#define SIZEOF_NTPCM(m) \ + (12 + ntohs(m.count) + ((ntohs(m.count) % 4) ? 4 - (ntohs(m.count) % 4) : 0)) /* finally, a little helper or two for debugging: */ -#define DBG(x) do{if(verbose>1){ x; }}while(0); -#define PRINTSOCKADDR(x) \ - do{ \ - printf("%u.%u.%u.%u", (x>>24)&0xff, (x>>16)&0xff, (x>>8)&0xff, x&0xff);\ - }while(0); +#define DBG(x) \ + do { \ + if (verbose > 1) { \ + x; \ + } \ + } while (0); +#define PRINTSOCKADDR(x) \ + do { \ + printf("%u.%u.%u.%u", (x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff); \ + } while (0); /* calculate the offset of the local clock */ -static inline double calc_offset(const ntp_message *m, const struct timeval *t){ +static inline double calc_offset(const ntp_message *m, const struct timeval *t) { double client_tx, peer_rx, peer_tx, client_rx; client_tx = NTP64asDOUBLE(m->origts); peer_rx = NTP64asDOUBLE(m->rxts); peer_tx = NTP64asDOUBLE(m->txts); - client_rx=TVasDOUBLE((*t)); - return (.5*((peer_tx-client_rx)+(peer_rx-client_tx))); + client_rx = TVasDOUBLE((*t)); + return (.5 * ((peer_tx - client_rx) + (peer_rx - client_tx))); } /* print out a ntp packet in human readable/debuggable format */ -void print_ntp_message(const ntp_message *p){ +void print_ntp_message(const ntp_message *p) { struct timeval ref, orig, rx, tx; - NTP64toTV(p->refts,ref); - NTP64toTV(p->origts,orig); - NTP64toTV(p->rxts,rx); - NTP64toTV(p->txts,tx); + NTP64toTV(p->refts, ref); + NTP64toTV(p->origts, orig); + NTP64toTV(p->rxts, rx); + NTP64toTV(p->txts, tx); printf("packet contents:\n"); printf("\tflags: 0x%.2x\n", p->flags); - printf("\t li=%d (0x%.2x)\n", LI(p->flags), p->flags&LI_MASK); - printf("\t vn=%d (0x%.2x)\n", VN(p->flags), p->flags&VN_MASK); - printf("\t mode=%d (0x%.2x)\n", MODE(p->flags), p->flags&MODE_MASK); + printf("\t li=%d (0x%.2x)\n", LI(p->flags), p->flags & LI_MASK); + printf("\t vn=%d (0x%.2x)\n", VN(p->flags), p->flags & VN_MASK); + printf("\t mode=%d (0x%.2x)\n", MODE(p->flags), p->flags & MODE_MASK); printf("\tstratum = %d\n", p->stratum); printf("\tpoll = %g\n", pow(2, p->poll)); printf("\tprecision = %g\n", pow(2, p->precision)); @@ -241,32 +263,31 @@ void print_ntp_message(const ntp_message *p){ printf("\ttxts = %-.16g\n", NTP64asDOUBLE(p->txts)); } -void print_ntp_control_message(const ntp_control_message *p){ - int i=0, numpeers=0; - const ntp_assoc_status_pair *peer=NULL; +void print_ntp_control_message(const ntp_control_message *p) { + int i = 0, numpeers = 0; + const ntp_assoc_status_pair *peer = NULL; printf("control packet contents:\n"); printf("\tflags: 0x%.2x , 0x%.2x\n", p->flags, p->op); - printf("\t li=%d (0x%.2x)\n", LI(p->flags), p->flags&LI_MASK); - printf("\t vn=%d (0x%.2x)\n", VN(p->flags), p->flags&VN_MASK); - printf("\t mode=%d (0x%.2x)\n", MODE(p->flags), p->flags&MODE_MASK); - printf("\t response=%d (0x%.2x)\n", (p->op&REM_RESP)>0, p->op&REM_RESP); - printf("\t more=%d (0x%.2x)\n", (p->op&REM_MORE)>0, p->op&REM_MORE); - printf("\t error=%d (0x%.2x)\n", (p->op&REM_ERROR)>0, p->op&REM_ERROR); - printf("\t op=%d (0x%.2x)\n", p->op&OP_MASK, p->op&OP_MASK); + printf("\t li=%d (0x%.2x)\n", LI(p->flags), p->flags & LI_MASK); + printf("\t vn=%d (0x%.2x)\n", VN(p->flags), p->flags & VN_MASK); + printf("\t mode=%d (0x%.2x)\n", MODE(p->flags), p->flags & MODE_MASK); + printf("\t response=%d (0x%.2x)\n", (p->op & REM_RESP) > 0, p->op & REM_RESP); + printf("\t more=%d (0x%.2x)\n", (p->op & REM_MORE) > 0, p->op & REM_MORE); + printf("\t error=%d (0x%.2x)\n", (p->op & REM_ERROR) > 0, p->op & REM_ERROR); + printf("\t op=%d (0x%.2x)\n", p->op & OP_MASK, p->op & OP_MASK); printf("\tsequence: %d (0x%.2x)\n", ntohs(p->seq), ntohs(p->seq)); printf("\tstatus: %d (0x%.2x)\n", ntohs(p->status), ntohs(p->status)); printf("\tassoc: %d (0x%.2x)\n", ntohs(p->assoc), ntohs(p->assoc)); printf("\toffset: %d (0x%.2x)\n", ntohs(p->offset), ntohs(p->offset)); printf("\tcount: %d (0x%.2x)\n", ntohs(p->count), ntohs(p->count)); - numpeers=ntohs(p->count)/(sizeof(ntp_assoc_status_pair)); - if(p->op&REM_RESP && p->op&OP_READSTAT){ - peer=(ntp_assoc_status_pair*)p->data; - for(i=0;i= PEER_INCLUDED){ - if(PEER_SEL(peer[i].status) >= PEER_SYNCSOURCE){ + numpeers = ntohs(p->count) / (sizeof(ntp_assoc_status_pair)); + if (p->op & REM_RESP && p->op & OP_READSTAT) { + peer = (ntp_assoc_status_pair *)p->data; + for (i = 0; i < numpeers; i++) { + printf("\tpeer id %.2x status %.2x", ntohs(peer[i].assoc), ntohs(peer[i].status)); + if (PEER_SEL(peer[i].status) >= PEER_INCLUDED) { + if (PEER_SEL(peer[i].status) >= PEER_SYNCSOURCE) { printf(" <-- current sync source"); } else { printf(" <-- current sync candidate"); @@ -277,41 +298,45 @@ void print_ntp_control_message(const ntp_control_message *p){ } } -void setup_request(ntp_message *p){ +void setup_request(ntp_message *p) { struct timeval t; memset(p, 0, sizeof(ntp_message)); LI_SET(p->flags, LI_ALARM); VN_SET(p->flags, 4); MODE_SET(p->flags, MODE_CLIENT); - p->poll=4; - p->precision=(int8_t)0xfa; - L16(p->rtdelay)=htons(1); - L16(p->rtdisp)=htons(1); + p->poll = 4; + p->precision = (int8_t)0xfa; + L16(p->rtdelay) = htons(1); + L16(p->rtdisp) = htons(1); gettimeofday(&t, NULL); - TVtoNTP64(t,p->txts); + TVtoNTP64(t, p->txts); } /* select the "best" server from a list of servers, and return its index. * this is done by filtering servers based on stratum, dispersion, and * finally round-trip delay. */ -int best_offset_server(const ntp_server_results *slist, int nservers){ - int cserver=0, best_server=-1; +int best_offset_server(const ntp_server_results *slist, int nservers) { + int cserver = 0, best_server = -1; /* for each server */ - for(cserver=0; cserver= 0) { + if (best_server >= 0) { DBG(printf("best server selected: peer %d\n", best_server)); return best_server; } else { @@ -354,16 +379,16 @@ int best_offset_server(const ntp_server_results *slist, int nservers){ * we don't waste time sitting around waiting for single packets. * - we also "manually" handle resolving host names and connecting, because * we have to do it in a way that our lazy macros don't handle currently :( */ -double offset_request(const char *host, int *status){ - int i=0, ga_result=0, num_hosts=0, *socklist=NULL, respnum=0; - int servers_completed=0, one_read=0, servers_readable=0, best_index=-1; - time_t now_time=0, start_ts=0; - ntp_message *req=NULL; - double avg_offset=0.; +double offset_request(const char *host, int *status) { + int i = 0, ga_result = 0, num_hosts = 0, *socklist = NULL, respnum = 0; + int servers_completed = 0, one_read = 0, servers_readable = 0, best_index = -1; + time_t now_time = 0, start_ts = 0; + ntp_message *req = NULL; + double avg_offset = 0.; struct timeval recv_time; - struct addrinfo *ai=NULL, *ai_tmp=NULL, hints; - struct pollfd *ufds=NULL; - ntp_server_results *servers=NULL; + struct addrinfo *ai = NULL, *ai_tmp = NULL, hints; + struct pollfd *ufds = NULL; + ntp_server_results *servers = NULL; /* setup hints to only return results from getaddrinfo that we'd like */ memset(&hints, 0, sizeof(struct addrinfo)); @@ -373,97 +398,112 @@ double offset_request(const char *host, int *status){ /* fill in ai with the list of hosts resolved by the host name */ ga_result = getaddrinfo(host, "123", &hints, &ai); - if(ga_result!=0){ - die(STATE_UNKNOWN, "error getting address for %s: %s\n", - host, gai_strerror(ga_result)); + 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(ai_tmp=ai; ai_tmp!=NULL; ai_tmp=ai_tmp->ai_next){ num_hosts++; } - req=(ntp_message*)malloc(sizeof(ntp_message)*num_hosts); - if(req==NULL) die(STATE_UNKNOWN, "can not allocate ntp message array"); - socklist=(int*)malloc(sizeof(int)*num_hosts); - if(socklist==NULL) die(STATE_UNKNOWN, "can not allocate socket array"); - ufds=(struct pollfd*)malloc(sizeof(struct pollfd)*num_hosts); - if(ufds==NULL) die(STATE_UNKNOWN, "can not allocate socket array"); - servers=(ntp_server_results*)malloc(sizeof(ntp_server_results)*num_hosts); - if(servers==NULL) die(STATE_UNKNOWN, "can not allocate server array"); - memset(servers, 0, sizeof(ntp_server_results)*num_hosts); + for (ai_tmp = ai; ai_tmp != NULL; ai_tmp = ai_tmp->ai_next) { + num_hosts++; + } + req = (ntp_message *)malloc(sizeof(ntp_message) * num_hosts); + if (req == NULL) { + die(STATE_UNKNOWN, "can not allocate ntp message array"); + } + socklist = (int *)malloc(sizeof(int) * num_hosts); + if (socklist == NULL) { + die(STATE_UNKNOWN, "can not allocate socket array"); + } + ufds = (struct pollfd *)malloc(sizeof(struct pollfd) * num_hosts); + if (ufds == NULL) { + die(STATE_UNKNOWN, "can not allocate socket array"); + } + servers = (ntp_server_results *)malloc(sizeof(ntp_server_results) * num_hosts); + if (servers == NULL) { + die(STATE_UNKNOWN, "can not allocate server array"); + } + memset(servers, 0, sizeof(ntp_server_results) * num_hosts); DBG(printf("Found %d peers to check\n", num_hosts)); /* setup each socket for writing, and the corresponding struct pollfd */ - ai_tmp=ai; - for(i=0;ai_tmp;i++){ - socklist[i]=socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP); - if(socklist[i] == -1) { + ai_tmp = ai; + for (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)){ + 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; + ufds[i].fd = socklist[i]; + ufds[i].events = POLLIN; + ufds[i].revents = 0; } ai_tmp = ai_tmp->ai_next; } /* now do AVG_NUM checks to each host. we stop before timeout/2 seconds * have passed in order to ensure post-processing and jitter time. */ - now_time=start_ts=time(NULL); - while(servers_completedflags, LI_NOWARNING); VN_SET(p->flags, VN_RESERVED); @@ -512,16 +553,16 @@ setup_control_request(ntp_control_message *p, uint8_t opcode, uint16_t seq){ } /* XXX handle responses with the error bit set */ -double jitter_request(int *status){ - int conn=-1, i, npeers=0, num_candidates=0; +double jitter_request(int *status) { + int conn = -1, i, npeers = 0, num_candidates = 0; bool syncsource_found = false; - int run=0, min_peer_sel=PEER_INCLUDED, num_selected=0, num_valid=0; - int peers_size=0, peer_offset=0; - ntp_assoc_status_pair *peers=NULL; + int run = 0, min_peer_sel = PEER_INCLUDED, num_selected = 0, num_valid = 0; + int peers_size = 0, peer_offset = 0; + ntp_assoc_status_pair *peers = NULL; ntp_control_message req; const char *getvar = "jitter"; double rval = 0.0, jitter = -1.0; - char *startofvalue=NULL, *nptr=NULL; + char *startofvalue = NULL, *nptr = NULL; void *tmp; /* Long-winded explanation: @@ -542,54 +583,62 @@ double jitter_request(int *status){ /* keep sending requests until the server stops setting the * REM_MORE bit, though usually this is only 1 packet. */ - do{ + do { setup_control_request(&req, OP_READSTAT, 1); DBG(printf("sending READSTAT request")); write(conn, &req, SIZEOF_NTPCM(req)); DBG(print_ntp_control_message(&req)); /* Attempt to read the largest size packet possible */ - req.count=htons(MAX_CM_SIZE); + req.count = htons(MAX_CM_SIZE); DBG(printf("receiving READSTAT response")) read(conn, &req, SIZEOF_NTPCM(req)); DBG(print_ntp_control_message(&req)); /* Each peer identifier is 4 bytes in the data section, which - * we represent as a ntp_assoc_status_pair datatype. - */ - peers_size+=ntohs(req.count); - if((tmp=realloc(peers, peers_size)) == NULL) + * we represent as a ntp_assoc_status_pair datatype. + */ + peers_size += ntohs(req.count); + if ((tmp = realloc(peers, peers_size)) == NULL) { free(peers), die(STATE_UNKNOWN, "can not (re)allocate 'peers' buffer\n"); - peers=tmp; - memcpy((void*)((ptrdiff_t)peers+peer_offset), (void*)req.data, ntohs(req.count)); - npeers=peers_size/sizeof(ntp_assoc_status_pair); - peer_offset+=ntohs(req.count); - } while(req.op&REM_MORE); + } + peers = tmp; + memcpy((void *)((ptrdiff_t)peers + peer_offset), (void *)req.data, ntohs(req.count)); + npeers = peers_size / sizeof(ntp_assoc_status_pair); + peer_offset += ntohs(req.count); + } while (req.op & REM_MORE); /* first, let's find out if we have a sync source, or if there are * at least some candidates. in the case of the latter we'll issue * a warning but go ahead with the check on them. */ - for (i = 0; i < npeers; i++){ - if (PEER_SEL(peers[i].status) >= PEER_INCLUDED){ + for (i = 0; i < npeers; i++) { + if (PEER_SEL(peers[i].status) >= PEER_INCLUDED) { num_candidates++; - if(PEER_SEL(peers[i].status) >= PEER_SYNCSOURCE){ + if (PEER_SEL(peers[i].status) >= PEER_SYNCSOURCE) { syncsource_found = true; - min_peer_sel=PEER_SYNCSOURCE; + min_peer_sel = PEER_SYNCSOURCE; } } } - if(verbose) printf("%d candidate peers available\n", num_candidates); - if(verbose && syncsource_found) printf("synchronization source found\n"); - if(! syncsource_found){ + if (verbose) { + printf("%d candidate peers available\n", num_candidates); + } + if (verbose && syncsource_found) { + printf("synchronization source found\n"); + } + if (!syncsource_found) { *status = STATE_UNKNOWN; - if(verbose) printf("warning: no synchronization source found\n"); + if (verbose) { + printf("warning: no synchronization source found\n"); + } } - - for (run=0; run= min_peer_sel){ - char jitter_data[MAX_CM_SIZE+1]; + if (PEER_SEL(peers[i].status) >= min_peer_sel) { + char jitter_data[MAX_CM_SIZE + 1]; size_t jitter_data_count; num_selected++; @@ -602,7 +651,7 @@ double jitter_request(int *status){ */ /* Older servers doesn't know what jitter is, so if we get an * error on the first pass we redo it with "dispersion" */ - strncpy(req.data, getvar, MAX_CM_SIZE-1); + strncpy(req.data, getvar, MAX_CM_SIZE - 1); req.count = htons(strlen(getvar)); DBG(printf("sending READVAR request...\n")); write(conn, &req, SIZEOF_NTPCM(req)); @@ -613,8 +662,11 @@ double jitter_request(int *status){ read(conn, &req, SIZEOF_NTPCM(req)); DBG(print_ntp_control_message(&req)); - if(req.op&REM_ERROR && strstr(getvar, "jitter")) { - if(verbose) printf("The 'jitter' command failed (old ntp server?)\nRestarting with 'dispersion'...\n"); + if (req.op & REM_ERROR && strstr(getvar, "jitter")) { + if (verbose) { + printf("The 'jitter' command failed (old ntp server?)\nRestarting with " + "'dispersion'...\n"); + } getvar = "dispersion"; num_selected--; i--; @@ -622,32 +674,33 @@ double jitter_request(int *status){ } /* get to the float value */ - if(verbose) { + if (verbose) { printf("parsing jitter from peer %.2x: ", ntohs(peers[i].assoc)); } - if((jitter_data_count = ntohs(req.count)) >= sizeof(jitter_data)){ - die(STATE_UNKNOWN, - _("jitter response too large (%lu bytes)\n"), - (unsigned long)jitter_data_count); + if ((jitter_data_count = ntohs(req.count)) >= sizeof(jitter_data)) { + die(STATE_UNKNOWN, _("jitter response too large (%lu bytes)\n"), + (unsigned long)jitter_data_count); } memcpy(jitter_data, req.data, jitter_data_count); jitter_data[jitter_data_count] = '\0'; startofvalue = strchr(jitter_data, '='); - if(startofvalue != NULL) { + if (startofvalue != NULL) { startofvalue++; jitter = strtod(startofvalue, &nptr); } - if(startofvalue == NULL || startofvalue==nptr){ + if (startofvalue == NULL || startofvalue == nptr) { printf("warning: unable to read server jitter response.\n"); *status = STATE_UNKNOWN; } else { - if(verbose) printf("%g\n", jitter); + if (verbose) { + printf("%g\n", jitter); + } num_valid++; rval += jitter; } } } - if(verbose){ + if (verbose) { printf("jitter parsed from %d/%d peers\n", num_valid, num_selected); } } @@ -655,37 +708,33 @@ double jitter_request(int *status){ rval = num_valid ? rval / num_valid : -1.0; close(conn); - if(peers!=NULL) free(peers); + if (peers != NULL) { + free(peers); + } /* If we return -1.0, it means no synchronization source was found */ return rval; } -int process_arguments(int argc, char **argv){ +int process_arguments(int argc, char **argv) { int c; - int option=0; + int option = 0; static struct option longopts[] = { - {"version", no_argument, 0, 'V'}, - {"help", no_argument, 0, 'h'}, - {"verbose", no_argument, 0, 'v'}, - {"use-ipv4", no_argument, 0, '4'}, - {"use-ipv6", no_argument, 0, '6'}, - {"warning", required_argument, 0, 'w'}, - {"critical", required_argument, 0, 'c'}, - {"jwarn", required_argument, 0, 'j'}, - {"jcrit", required_argument, 0, 'k'}, - {"timeout", required_argument, 0, 't'}, - {"hostname", required_argument, 0, 'H'}, - {0, 0, 0, 0} - }; - - - if (argc < 2) - usage ("\n"); + {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, + {"verbose", no_argument, 0, 'v'}, {"use-ipv4", no_argument, 0, '4'}, + {"use-ipv6", no_argument, 0, '6'}, {"warning", required_argument, 0, 'w'}, + {"critical", required_argument, 0, 'c'}, {"jwarn", required_argument, 0, 'j'}, + {"jcrit", required_argument, 0, 'k'}, {"timeout", required_argument, 0, 't'}, + {"hostname", required_argument, 0, 'H'}, {0, 0, 0, 0}}; + + if (argc < 2) { + usage("\n"); + } while (1) { - c = getopt_long (argc, argv, "Vhv46w:c:j:k:t:H:", longopts, &option); - if (c == -1 || c == EOF || c == 1) + c = getopt_long(argc, argv, "Vhv46w:c:j:k:t:H:", longopts, &option); + if (c == -1 || c == EOF || c == 1) { break; + } switch (c) { case 'h': @@ -716,12 +765,13 @@ int process_arguments(int argc, char **argv){ jcrit = optarg; break; case 'H': - if(!is_host(optarg)) + if (!is_host(optarg)) { usage2(_("Invalid hostname/address"), optarg); + } server_address = strdup(optarg); break; case 't': - socket_timeout=atoi(optarg); + socket_timeout = atoi(optarg); break; case '4': address_family = AF_INET; @@ -730,64 +780,59 @@ int process_arguments(int argc, char **argv){ #ifdef USE_IPV6 address_family = AF_INET6; #else - usage4 (_("IPv6 support not available")); + usage4(_("IPv6 support not available")); #endif break; case '?': /* print short usage statement if args not parsable */ - usage5 (); + usage5(); break; } } - if(server_address == NULL){ + if (server_address == NULL) { usage4(_("Hostname was not supplied")); } return 0; } -char *perfd_offset (double offset) -{ - return fperfdata ("offset", offset, "s", - true, offset_thresholds->warning->end, - true, offset_thresholds->critical->end, - false, 0, false, 0); +char *perfd_offset(double offset) { + return fperfdata("offset", offset, "s", true, offset_thresholds->warning->end, true, + offset_thresholds->critical->end, false, 0, false, 0); } -char *perfd_jitter (double jitter) -{ - return fperfdata ("jitter", jitter, "s", - do_jitter, jitter_thresholds->warning->end, - do_jitter, jitter_thresholds->critical->end, - true, 0, false, 0); +char *perfd_jitter(double jitter) { + return fperfdata("jitter", jitter, "s", do_jitter, jitter_thresholds->warning->end, do_jitter, + jitter_thresholds->critical->end, true, 0, false, 0); } -int main(int argc, char *argv[]){ +int main(int argc, char *argv[]) { int result, offset_result, jitter_result; - double offset=0, jitter=0; + double offset = 0, jitter = 0; char *result_line, *perfdata_line; - setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); result = offset_result = jitter_result = STATE_OK; /* Parse extra opts if any */ - argv=np_extra_opts (&argc, argv, progname); + argv = np_extra_opts(&argc, argv, progname); - if (process_arguments (argc, argv) == ERROR) - usage4 (_("Could not parse arguments")); + if (process_arguments(argc, argv) == ERROR) { + usage4(_("Could not parse arguments")); + } set_thresholds(&offset_thresholds, owarn, ocrit); set_thresholds(&jitter_thresholds, jwarn, jcrit); /* initialize alarm signal handling */ - signal (SIGALRM, socket_timeout_alarm_handler); + signal(SIGALRM, socket_timeout_alarm_handler); /* set socket timeout */ - alarm (socket_timeout); + alarm(socket_timeout); offset = offset_request(server_address, &offset_result); /* check_ntp used to always return CRITICAL if offset_result == STATE_UNKNOWN. @@ -803,31 +848,32 @@ int main(int argc, char *argv[]){ * servers recognize. Trying to check the jitter on OpenNTPD * (for example) will result in an error */ - if(do_jitter){ - jitter=jitter_request(&jitter_result); + if (do_jitter) { + jitter = jitter_request(&jitter_result); result = max_state_alt(result, get_status(jitter, jitter_thresholds)); /* -1 indicates that we couldn't calculate the jitter * Only overrides STATE_OK from the offset */ - if(jitter == -1.0 && result == STATE_OK) + if (jitter == -1.0 && result == STATE_OK) { result = STATE_UNKNOWN; + } } result = max_state_alt(result, jitter_result); switch (result) { - case STATE_CRITICAL : - xasprintf(&result_line, _("NTP CRITICAL:")); - break; - case STATE_WARNING : - xasprintf(&result_line, _("NTP WARNING:")); - break; - case STATE_OK : - xasprintf(&result_line, _("NTP OK:")); - break; - default : - xasprintf(&result_line, _("NTP UNKNOWN:")); - break; + case STATE_CRITICAL: + xasprintf(&result_line, _("NTP CRITICAL:")); + break; + case STATE_WARNING: + xasprintf(&result_line, _("NTP WARNING:")); + break; + case STATE_OK: + xasprintf(&result_line, _("NTP OK:")); + break; + default: + xasprintf(&result_line, _("NTP UNKNOWN:")); + break; } - if(offset_result == STATE_UNKNOWN){ + if (offset_result == STATE_UNKNOWN) { xasprintf(&result_line, "%s %s", result_line, _("Offset unknown")); xasprintf(&perfdata_line, ""); } else { @@ -836,41 +882,41 @@ int main(int argc, char *argv[]){ } if (do_jitter) { xasprintf(&result_line, "%s, jitter=%f", result_line, jitter); - xasprintf(&perfdata_line, "%s %s", perfdata_line, perfd_jitter(jitter)); + xasprintf(&perfdata_line, "%s %s", perfdata_line, perfd_jitter(jitter)); } printf("%s|%s\n", result_line, perfdata_line); - if(server_address!=NULL) free(server_address); + if (server_address != NULL) { + free(server_address); + } return result; } - - -void print_help(void){ +void print_help(void) { print_revision(progname, NP_VERSION); - printf ("Copyright (c) 2006 Sean Finney\n"); - printf (COPYRIGHT, copyright, email); + printf("Copyright (c) 2006 Sean Finney\n"); + printf(COPYRIGHT, copyright, email); - printf ("%s\n", _("This plugin checks the selected ntp server")); + printf("%s\n", _("This plugin checks the selected ntp server")); - printf ("\n\n"); + printf("\n\n"); print_usage(); - printf (UT_HELP_VRSN); - printf (UT_EXTRA_OPTS); - printf (UT_HOST_PORT, 'p', "123"); - printf (UT_IPv46); - printf (" %s\n", "-w, --warning=THRESHOLD"); - printf (" %s\n", _("Offset to result in warning status (seconds)")); - printf (" %s\n", "-c, --critical=THRESHOLD"); - printf (" %s\n", _("Offset to result in critical status (seconds)")); - printf (" %s\n", "-j, --jwarn=THRESHOLD"); - printf (" %s\n", _("Warning threshold for jitter")); - printf (" %s\n", "-k, --jcrit=THRESHOLD"); - printf (" %s\n", _("Critical threshold for jitter")); - printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); - printf (UT_VERBOSE); + printf(UT_HELP_VRSN); + printf(UT_EXTRA_OPTS); + printf(UT_HOST_PORT, 'p', "123"); + printf(UT_IPv46); + printf(" %s\n", "-w, --warning=THRESHOLD"); + printf(" %s\n", _("Offset to result in warning status (seconds)")); + printf(" %s\n", "-c, --critical=THRESHOLD"); + printf(" %s\n", _("Offset to result in critical status (seconds)")); + printf(" %s\n", "-j, --jwarn=THRESHOLD"); + printf(" %s\n", _("Warning threshold for jitter")); + printf(" %s\n", "-k, --jcrit=THRESHOLD"); + printf(" %s\n", _("Critical threshold for jitter")); + printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); + printf(UT_VERBOSE); printf("\n"); printf("%s\n", _("Notes:")); @@ -881,21 +927,21 @@ void print_help(void){ printf(" %s\n", _("Normal offset check:")); printf(" %s\n", ("./check_ntp -H ntpserv -w 0.5 -c 1")); printf("\n"); - printf(" %s\n", _("Check jitter too, avoiding critical notifications if jitter isn't available")); + printf(" %s\n", + _("Check jitter too, avoiding critical notifications if jitter isn't available")); printf(" %s\n", _("(See Notes above for more details on thresholds formats):")); printf(" %s\n", ("./check_ntp -H ntpserv -w 0.5 -c 1 -j -1:100 -k -1:200")); - printf (UT_SUPPORT); + printf(UT_SUPPORT); - printf ("%s\n", _("WARNING: check_ntp is deprecated. Please use check_ntp_peer or")); - printf ("%s\n\n", _("check_ntp_time instead.")); + printf("%s\n", _("WARNING: check_ntp is deprecated. Please use check_ntp_peer or")); + printf("%s\n\n", _("check_ntp_time instead.")); } -void -print_usage(void) -{ - printf ("%s\n", _("WARNING: check_ntp is deprecated. Please use check_ntp_peer or")); - printf ("%s\n\n", _("check_ntp_time instead.")); - printf ("%s\n", _("Usage:")); - printf(" %s -H [-w ] [-c ] [-j ] [-k ] [-4|-6] [-v verbose]\n", progname); +void print_usage(void) { + printf("%s\n", _("WARNING: check_ntp is deprecated. Please use check_ntp_peer or")); + printf("%s\n\n", _("check_ntp_time instead.")); + printf("%s\n", _("Usage:")); + printf(" %s -H [-w ] [-c ] [-j ] [-k ] [-4|-6] [-v verbose]\n", + progname); } diff --git a/plugins/check_ntp_peer.c b/plugins/check_ntp_peer.c index 5c4ff386..24d1c9b5 100644 --- a/plugins/check_ntp_peer.c +++ b/plugins/check_ntp_peer.c @@ -83,9 +83,9 @@ typedef struct { /* bits 1,2 are the leap indicator */ #define LI_MASK 0xc0 #define LI(x) ((x & LI_MASK) >> 6) -#define LI_SET(x, y) \ - do { \ - x |= ((y << 6) & LI_MASK); \ +#define LI_SET(x, y) \ + do { \ + x |= ((y << 6) & LI_MASK); \ } while (0) /* and these are the values of the leap indicator */ #define LI_NOWARNING 0x00 @@ -95,17 +95,17 @@ typedef struct { /* bits 3,4,5 are the ntp version */ #define VN_MASK 0x38 #define VN(x) ((x & VN_MASK) >> 3) -#define VN_SET(x, y) \ - do { \ - x |= ((y << 3) & VN_MASK); \ +#define VN_SET(x, y) \ + do { \ + x |= ((y << 3) & VN_MASK); \ } while (0) #define VN_RESERVED 0x02 /* bits 6,7,8 are the ntp mode */ #define MODE_MASK 0x07 #define MODE(x) (x & MODE_MASK) -#define MODE_SET(x, y) \ - do { \ - x |= (y & MODE_MASK); \ +#define MODE_SET(x, y) \ + do { \ + x |= (y & MODE_MASK); \ } while (0) /* here are some values */ #define MODE_CLIENT 0x03 @@ -117,9 +117,9 @@ typedef struct { #define REM_MORE 0x20 /* In control message, bits 11 - 15 are opcode */ #define OP_MASK 0x1f -#define OP_SET(x, y) \ - do { \ - x |= (y & OP_MASK); \ +#define OP_SET(x, y) \ + do { \ + x |= (y & OP_MASK); \ } while (0) #define OP_READSTAT 0x01 #define OP_READVAR 0x02 @@ -132,18 +132,19 @@ typedef struct { /* NTP control message header is 12 bytes, plus any data in the data * field, plus null padding to the nearest 32-bit boundary per rfc. */ -#define SIZEOF_NTPCM(m) (12 + ntohs(m.count) + ((ntohs(m.count) % 4) ? 4 - (ntohs(m.count) % 4) : 0)) +#define SIZEOF_NTPCM(m) \ + (12 + ntohs(m.count) + ((ntohs(m.count) % 4) ? 4 - (ntohs(m.count) % 4) : 0)) /* finally, a little helper or two for debugging: */ -#define DBG(x) \ - do { \ - if (verbose > 1) { \ - x; \ - } \ +#define DBG(x) \ + do { \ + if (verbose > 1) { \ + x; \ + } \ } while (0); -#define PRINTSOCKADDR(x) \ - do { \ - printf("%u.%u.%u.%u", (x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff); \ +#define PRINTSOCKADDR(x) \ + do { \ + printf("%u.%u.%u.%u", (x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff); \ } while (0); void print_ntp_control_message(const ntp_control_message *message) { @@ -360,7 +361,8 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { if (req.op & REM_ERROR) { if (strstr(getvar, "jitter")) { if (verbose) { - printf("The command failed. This is usually caused by servers refusing the 'jitter'\nvariable. Restarting with " + printf("The command failed. This is usually caused by servers refusing the " + "'jitter'\nvariable. Restarting with " "'dispersion'...\n"); } getvar = "stratum,offset,dispersion"; @@ -404,7 +406,8 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { if (verbose) { printf("%.10g\n", tmp_offset); } - if (result.offset_result == STATE_UNKNOWN || fabs(tmp_offset) < fabs(result.offset)) { + if (result.offset_result == STATE_UNKNOWN || + fabs(tmp_offset) < fabs(result.offset)) { result.offset = tmp_offset; result.offset_result = STATE_OK; } else { @@ -416,10 +419,12 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { if (config.do_jitter) { /* get the jitter */ if (verbose) { - printf("parsing %s from peer %.2x: ", strstr(getvar, "dispersion") != NULL ? "dispersion" : "jitter", + printf("parsing %s from peer %.2x: ", + strstr(getvar, "dispersion") != NULL ? "dispersion" : "jitter", ntohs(peers[i].assoc)); } - value = np_extract_ntpvar(data, strstr(getvar, "dispersion") != NULL ? "dispersion" : "jitter"); + value = np_extract_ntpvar(data, strstr(getvar, "dispersion") != NULL ? "dispersion" + : "jitter"); nptr = NULL; /* Convert the value if we have one */ if (value != NULL) { @@ -471,12 +476,15 @@ ntp_request_result ntp_request(const check_ntp_peer_config config) { check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { static struct option longopts[] = { - {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, 'v'}, - {"use-ipv4", no_argument, 0, '4'}, {"use-ipv6", no_argument, 0, '6'}, {"quiet", no_argument, 0, 'q'}, - {"warning", required_argument, 0, 'w'}, {"critical", required_argument, 0, 'c'}, {"swarn", required_argument, 0, 'W'}, - {"scrit", required_argument, 0, 'C'}, {"jwarn", required_argument, 0, 'j'}, {"jcrit", required_argument, 0, 'k'}, - {"twarn", required_argument, 0, 'm'}, {"tcrit", required_argument, 0, 'n'}, {"timeout", required_argument, 0, 't'}, - {"hostname", required_argument, 0, 'H'}, {"port", required_argument, 0, 'p'}, {0, 0, 0, 0}}; + {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, + {"verbose", no_argument, 0, 'v'}, {"use-ipv4", no_argument, 0, '4'}, + {"use-ipv6", no_argument, 0, '6'}, {"quiet", no_argument, 0, 'q'}, + {"warning", required_argument, 0, 'w'}, {"critical", required_argument, 0, 'c'}, + {"swarn", required_argument, 0, 'W'}, {"scrit", required_argument, 0, 'C'}, + {"jwarn", required_argument, 0, 'j'}, {"jcrit", required_argument, 0, 'k'}, + {"twarn", required_argument, 0, 'm'}, {"tcrit", required_argument, 0, 'n'}, + {"timeout", required_argument, 0, 't'}, {"hostname", required_argument, 0, 'H'}, + {"port", required_argument, 0, 'p'}, {0, 0, 0, 0}}; if (argc < 2) { usage("\n"); @@ -489,7 +497,8 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { while (true) { int option = 0; - int option_char = getopt_long(argc, argv, "Vhv46qw:c:W:C:j:k:m:n:t:H:p:", longopts, &option); + int option_char = + getopt_long(argc, argv, "Vhv46qw:c:W:C:j:k:m:n:t:H:p:", longopts, &option); if (option_char == -1 || option_char == EOF || option_char == 1) { break; } @@ -581,22 +590,24 @@ check_ntp_peer_config_wrapper process_arguments(int argc, char **argv) { } char *perfd_offset(double offset, thresholds *offset_thresholds) { - return fperfdata("offset", offset, "s", true, offset_thresholds->warning->end, true, offset_thresholds->critical->end, false, 0, false, - 0); + return fperfdata("offset", offset, "s", true, offset_thresholds->warning->end, true, + offset_thresholds->critical->end, false, 0, false, 0); } char *perfd_jitter(double jitter, bool do_jitter, thresholds *jitter_thresholds) { - return fperfdata("jitter", jitter, "", do_jitter, jitter_thresholds->warning->end, do_jitter, jitter_thresholds->critical->end, true, 0, - false, 0); + return fperfdata("jitter", jitter, "", do_jitter, jitter_thresholds->warning->end, do_jitter, + jitter_thresholds->critical->end, true, 0, false, 0); } char *perfd_stratum(int stratum, bool do_stratum, thresholds *stratum_thresholds) { - return perfdata("stratum", stratum, "", do_stratum, (int)stratum_thresholds->warning->end, do_stratum, - (int)stratum_thresholds->critical->end, true, 0, true, 16); + return perfdata("stratum", stratum, "", do_stratum, (int)stratum_thresholds->warning->end, + do_stratum, (int)stratum_thresholds->critical->end, true, 0, true, 16); } -char *perfd_truechimers(int num_truechimers, const bool do_truechimers, thresholds *truechimer_thresholds) { - return perfdata("truechimers", num_truechimers, "", do_truechimers, (int)truechimer_thresholds->warning->end, do_truechimers, +char *perfd_truechimers(int num_truechimers, const bool do_truechimers, + thresholds *truechimer_thresholds) { + return perfdata("truechimers", num_truechimers, "", do_truechimers, + (int)truechimer_thresholds->warning->end, do_truechimers, (int)truechimer_thresholds->critical->end, true, 0, false, 0); } @@ -686,9 +697,11 @@ int main(int argc, char *argv[]) { xasprintf(&result_line, "%s %s", result_line, _("Offset unknown")); xasprintf(&perfdata_line, ""); } else if (oresult == STATE_WARNING) { - xasprintf(&result_line, "%s %s %.10g secs (WARNING)", result_line, _("Offset"), ntp_res.offset); + xasprintf(&result_line, "%s %s %.10g secs (WARNING)", result_line, _("Offset"), + ntp_res.offset); } else if (oresult == STATE_CRITICAL) { - xasprintf(&result_line, "%s %s %.10g secs (CRITICAL)", result_line, _("Offset"), ntp_res.offset); + xasprintf(&result_line, "%s %s %.10g secs (CRITICAL)", result_line, _("Offset"), + ntp_res.offset); } else { xasprintf(&result_line, "%s %s %.10g secs", result_line, _("Offset"), ntp_res.offset); } @@ -702,7 +715,8 @@ int main(int argc, char *argv[]) { } else { xasprintf(&result_line, "%s, jitter=%f", result_line, ntp_res.jitter); } - xasprintf(&perfdata_line, "%s %s", perfdata_line, perfd_jitter(ntp_res.jitter, config.do_jitter, config.jitter_thresholds)); + xasprintf(&perfdata_line, "%s %s", perfdata_line, + perfd_jitter(ntp_res.jitter, config.do_jitter, config.jitter_thresholds)); } if (config.do_stratum) { @@ -713,19 +727,23 @@ int main(int argc, char *argv[]) { } else { xasprintf(&result_line, "%s, stratum=%li", result_line, ntp_res.stratum); } - xasprintf(&perfdata_line, "%s %s", perfdata_line, perfd_stratum(ntp_res.stratum, config.do_stratum, config.stratum_thresholds)); + xasprintf(&perfdata_line, "%s %s", perfdata_line, + perfd_stratum(ntp_res.stratum, config.do_stratum, config.stratum_thresholds)); } if (config.do_truechimers) { if (tresult == STATE_WARNING) { - xasprintf(&result_line, "%s, truechimers=%i (WARNING)", result_line, ntp_res.num_truechimers); + xasprintf(&result_line, "%s, truechimers=%i (WARNING)", result_line, + ntp_res.num_truechimers); } else if (tresult == STATE_CRITICAL) { - xasprintf(&result_line, "%s, truechimers=%i (CRITICAL)", result_line, ntp_res.num_truechimers); + xasprintf(&result_line, "%s, truechimers=%i (CRITICAL)", result_line, + ntp_res.num_truechimers); } else { xasprintf(&result_line, "%s, truechimers=%i", result_line, ntp_res.num_truechimers); } xasprintf(&perfdata_line, "%s %s", perfdata_line, - perfd_truechimers(ntp_res.num_truechimers, config.do_truechimers, config.truechimer_thresholds)); + perfd_truechimers(ntp_res.num_truechimers, config.do_truechimers, + config.truechimer_thresholds)); } printf("%s|%s\n", result_line, perfdata_line); @@ -753,7 +771,8 @@ void print_help(void) { printf(UT_IPv46); printf(UT_HOST_PORT, 'p', "123"); printf(" %s\n", "-q, --quiet"); - printf(" %s\n", _("Returns UNKNOWN instead of CRITICAL or WARNING if server isn't synchronized")); + printf(" %s\n", + _("Returns UNKNOWN instead of CRITICAL or WARNING if server isn't synchronized")); printf(" %s\n", "-w, --warning=THRESHOLD"); printf(" %s\n", _("Offset to result in warning status (seconds)")); printf(" %s\n", "-c, --critical=THRESHOLD"); @@ -790,7 +809,8 @@ void print_help(void) { printf(" %s\n", _("Simple NTP server check:")); printf(" %s\n", ("./check_ntp_peer -H ntpserv -w 0.5 -c 1")); printf("\n"); - printf(" %s\n", _("Check jitter too, avoiding critical notifications if jitter isn't available")); + printf(" %s\n", + _("Check jitter too, avoiding critical notifications if jitter isn't available")); printf(" %s\n", _("(See Notes above for more details on thresholds formats):")); printf(" %s\n", ("./check_ntp_peer -H ntpserv -w 0.5 -c 1 -j -1:100 -k -1:200")); printf("\n"); diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c index 31162883..ad69b804 100644 --- a/plugins/check_ntp_time.c +++ b/plugins/check_ntp_time.c @@ -93,9 +93,9 @@ typedef struct { /* bits 1,2 are the leap indicator */ #define LI_MASK 0xc0 #define LI(x) ((x & LI_MASK) >> 6) -#define LI_SET(x, y) \ - do { \ - x |= ((y << 6) & LI_MASK); \ +#define LI_SET(x, y) \ + do { \ + x |= ((y << 6) & LI_MASK); \ } while (0) /* and these are the values of the leap indicator */ #define LI_NOWARNING 0x00 @@ -105,17 +105,17 @@ typedef struct { /* bits 3,4,5 are the ntp version */ #define VN_MASK 0x38 #define VN(x) ((x & VN_MASK) >> 3) -#define VN_SET(x, y) \ - do { \ - x |= ((y << 3) & VN_MASK); \ +#define VN_SET(x, y) \ + do { \ + x |= ((y << 3) & VN_MASK); \ } while (0) #define VN_RESERVED 0x02 /* bits 6,7,8 are the ntp mode */ #define MODE_MASK 0x07 #define MODE(x) (x & MODE_MASK) -#define MODE_SET(x, y) \ - do { \ - x |= (y & MODE_MASK); \ +#define MODE_SET(x, y) \ + do { \ + x |= (y & MODE_MASK); \ } while (0) /* here are some values */ #define MODE_CLIENT 0x03 @@ -127,9 +127,9 @@ typedef struct { #define REM_MORE 0x20 /* In control message, bits 11 - 15 are opcode */ #define OP_MASK 0x1f -#define OP_SET(x, y) \ - do { \ - x |= (y & OP_MASK); \ +#define OP_SET(x, y) \ + do { \ + x |= (y & OP_MASK); \ } while (0) #define OP_READSTAT 0x01 #define OP_READVAR 0x02 @@ -163,32 +163,34 @@ typedef struct { #define NTP32asDOUBLE(x) (ntohs(L16(x)) + ((double)ntohs(R16(x)) / 65536.0)) /* likewise for a 64-bit ntp fp number */ -#define NTP64asDOUBLE(n) \ - (double)(((uint64_t)n) ? (ntohl(L32(n)) - EPOCHDIFF) + (.00000001 * (0.5 + (double)(ntohl(R32(n)) / 42.94967296))) : 0) +#define NTP64asDOUBLE(n) \ + (double)(((uint64_t)n) ? (ntohl(L32(n)) - EPOCHDIFF) + \ + (.00000001 * (0.5 + (double)(ntohl(R32(n)) / 42.94967296))) \ + : 0) /* convert a struct timeval to a double */ #define TVasDOUBLE(x) (double)(x.tv_sec + (0.000001 * x.tv_usec)) /* convert an ntp 64-bit fp number to a struct timeval */ -#define NTP64toTV(n, t) \ - do { \ - if (!n) \ - t.tv_sec = t.tv_usec = 0; \ - else { \ - t.tv_sec = ntohl(L32(n)) - EPOCHDIFF; \ - t.tv_usec = (int)(0.5 + (double)(ntohl(R32(n)) / 4294.967296)); \ - } \ +#define NTP64toTV(n, t) \ + do { \ + if (!n) \ + t.tv_sec = t.tv_usec = 0; \ + else { \ + t.tv_sec = ntohl(L32(n)) - EPOCHDIFF; \ + t.tv_usec = (int)(0.5 + (double)(ntohl(R32(n)) / 4294.967296)); \ + } \ } while (0) /* convert a struct timeval to an ntp 64-bit fp number */ -#define TVtoNTP64(t, n) \ - do { \ - if (!t.tv_usec && !t.tv_sec) \ - n = 0x0UL; \ - else { \ - L32(n) = htonl(t.tv_sec + EPOCHDIFF); \ - R32(n) = htonl((uint64_t)((4294.967296 * t.tv_usec) + .5)); \ - } \ +#define TVtoNTP64(t, n) \ + do { \ + if (!t.tv_usec && !t.tv_sec) \ + n = 0x0UL; \ + else { \ + L32(n) = htonl(t.tv_sec + EPOCHDIFF); \ + R32(n) = htonl((uint64_t)((4294.967296 * t.tv_usec) + .5)); \ + } \ } while (0) /* NTP control message header is 12 bytes, plus any data in the data @@ -197,15 +199,15 @@ typedef struct { #define SIZEOF_NTPCM(m) (12 + ntohs(m.count) + ((m.count) ? 4 - (ntohs(m.count) % 4) : 0)) /* finally, a little helper or two for debugging: */ -#define DBG(x) \ - do { \ - if (verbose > 1) { \ - x; \ - } \ +#define DBG(x) \ + do { \ + if (verbose > 1) { \ + x; \ + } \ } while (0); -#define PRINTSOCKADDR(x) \ - do { \ - printf("%u.%u.%u.%u", (x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff); \ +#define PRINTSOCKADDR(x) \ + do { \ + printf("%u.%u.%u.%u", (x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff); \ } while (0); /* calculate the offset of the local clock */ @@ -358,7 +360,8 @@ double offset_request(const char *host, const char *port, mp_state_enum *status, die(STATE_UNKNOWN, "can not allocate socket array"); } - ntp_server_results *servers = (ntp_server_results *)malloc(sizeof(ntp_server_results) * num_hosts); + ntp_server_results *servers = + (ntp_server_results *)malloc(sizeof(ntp_server_results) * num_hosts); if (servers == NULL) { die(STATE_UNKNOWN, "can not allocate server array"); } @@ -585,8 +588,8 @@ check_ntp_time_config_wrapper process_arguments(int argc, char **argv) { } char *perfd_offset(double offset, thresholds *offset_thresholds) { - return fperfdata("offset", offset, "s", true, offset_thresholds->warning->end, true, offset_thresholds->critical->end, false, 0, false, - 0); + return fperfdata("offset", offset, "s", true, offset_thresholds->warning->end, true, + offset_thresholds->critical->end, false, 0, false, 0); } int main(int argc, char *argv[]) { @@ -613,7 +616,8 @@ int main(int argc, char *argv[]) { mp_state_enum offset_result = STATE_OK; mp_state_enum result = STATE_OK; - double offset = offset_request(config.server_address, config.port, &offset_result, config.time_offset); + double offset = + offset_request(config.server_address, config.port, &offset_result, config.time_offset); if (offset_result == STATE_UNKNOWN) { result = ((!config.quiet) ? STATE_UNKNOWN : STATE_CRITICAL); } else { @@ -701,5 +705,6 @@ void print_help(void) { void print_usage(void) { printf("%s\n", _("Usage:")); - printf(" %s -H [-4|-6] [-w ] [-c ] [-v verbose] [-o