From 37c543e2b20657a8f4c120ba6b52e8e605a417bb Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Wed, 12 Mar 2025 13:50:39 +0100
Subject: Remove check_nwstat
check_nwstat is a plugin which was used to determine the health
of things on Novel machines.
Since Novel is quite dead (even more so the product, this can be
removed and this commit does just that to reduce ressource usage.
---
.github/monitoring-plugins.spec | 14 -
.gitignore | 1 -
REQUIREMENTS | 4 -
plugins/Makefile.am | 3 +-
plugins/check_nwstat.c | 1527 ---------------------------------------
5 files changed, 1 insertion(+), 1548 deletions(-)
delete mode 100644 plugins/check_nwstat.c
diff --git a/.github/monitoring-plugins.spec b/.github/monitoring-plugins.spec
index 64ee34f2..10799128 100644
--- a/.github/monitoring-plugins.spec
+++ b/.github/monitoring-plugins.spec
@@ -191,7 +191,6 @@ Requires: %{name}-nt
Requires: %{name}-ntp
Requires: %{name}-ntp_peer
Requires: %{name}-ntp_time
-Requires: %{name}-nwstat
Requires: %{name}-oracle
Requires: %{name}-pgsql
Requires: %{name}-ping
@@ -702,19 +701,6 @@ Provides check_ntp_time of the Monitoring Plugins.
-# check_nwstat
-%package nwstat
-Summary: Monitoring Plugins - check_nwstat
-Requires: %{name} = %{version}-%{release}
-
-%description nwstat
-Provides check_nwstat of the Monitoring Plugins.
-
-%files nwstat
-%{plugindir}/check_nwstat
-
-
-
# check_oracle
%package oracle
Summary: Monitoring Plugins - check_oracle
diff --git a/.gitignore b/.gitignore
index f9cb37e4..7f79265f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -177,7 +177,6 @@ NP-VERSION-FILE
/plugins/check_ntp
/plugins/check_ntp_peer
/plugins/check_ntp_time
-/plugins/check_nwstat
/plugins/check_pgsql
/plugins/check_ping
/plugins/check_pop
diff --git a/REQUIREMENTS b/REQUIREMENTS
index f3b1c01d..551fdb1a 100644
--- a/REQUIREMENTS
+++ b/REQUIREMENTS
@@ -87,10 +87,6 @@ check_ifstatus/check_ifoperstatus
- Requires Net::SNMP perl module
http://www.perl.com/CPAN/modules/by-authors/id/D/DT/DTOWN/
-check_nwstat:
- - Requires MRTGEXT NLM for Novell Servers
- http://forge.novell.com/modules/xfmod/project/?mrtgext
-
check_nt:
- Requires NSClient to run on the NT server to monitor
http://nsclient.ready2run.nl/
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 6c582a15..7c404a3b 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -27,7 +27,7 @@ MATHLIBS = @MATHLIBS@
#AM_CFLAGS = -Wall
libexec_PROGRAMS = check_apt check_cluster check_disk check_dummy check_http check_load \
- check_mrtg check_mrtgtraf check_ntp check_ntp_peer check_nwstat check_ping \
+ check_mrtg check_mrtgtraf check_ntp check_ntp_peer check_ping \
check_real check_smtp check_ssh check_tcp check_time check_ntp_time \
check_ups check_users negate \
urlize @EXTRAS@
@@ -131,7 +131,6 @@ check_nagios_LDADD = $(BASEOBJS)
check_nt_LDADD = $(NETLIBS)
check_ntp_LDADD = $(NETLIBS) $(MATHLIBS)
check_ntp_peer_LDADD = $(NETLIBS) $(MATHLIBS)
-check_nwstat_LDADD = $(NETLIBS)
check_pgsql_LDADD = $(NETLIBS) $(PGLIBS)
check_ping_LDADD = $(NETLIBS)
check_procs_LDADD = $(BASEOBJS)
diff --git a/plugins/check_nwstat.c b/plugins/check_nwstat.c
deleted file mode 100644
index 176dfbc8..00000000
--- a/plugins/check_nwstat.c
+++ /dev/null
@@ -1,1527 +0,0 @@
-/*****************************************************************************
- *
- * Monitoring check_nwstat plugin
- *
- * License: GPL
- * Copyright (c) 2000-2024 Monitoring Plugins Development Team
- *
- * Description:
- *
- * This file contains the check_nwstat plugin
- *
- * This plugin attempts to contact the MRTGEXT NLM running on a
- * Novell server to gather the requested system information.
- *
- *
- * 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_nwstat";
-const char *copyright = "2000-2024";
-const char *email = "devel@monitoring-plugins.org";
-
-#include "common.h"
-#include "netutils.h"
-#include "utils.h"
-
-enum checkvar {
- NONE,
- LOAD1, /* check 1 minute CPU load */
- LOAD5, /* check 5 minute CPU load */
- LOAD15, /* check 15 minute CPU load */
- CONNS, /* check number of connections */
- VPF, /* check % free space on volume */
- VMF, /* check MB free space on volume */
- VMU, /* check MB used space on volume */
- VPU, /* check % used space on volume */
- VMP, /* check MB purgeable space on volume */
- VKF, /* check KB free space on volume */
- LTCH, /* check long-term cache hit percentage */
- CBUFF, /* check total cache buffers */
- CDBUFF, /* check dirty cache buffers */
- LRUM, /* check LRU sitting time in minutes */
- DSDB, /* check to see if DS Database is open */
- LOGINS, /* check to see if logins are enabled */
- NRMH, /* check to see NRM Health Status */
- PUPRB, /* check % of used packet receive buffers */
- UPRB, /* check used packet receive buffers */
- SAPENTRIES, /* check SAP entries */
- OFILES, /* check number of open files */
- VKP, /* check KB purgeable space on volume */
- VPP, /* check % purgeable space on volume */
- VKNP, /* check KB not yet purgeable space on volume */
- VPNP, /* check % not yet purgeable space on volume */
- ABENDS, /* check abended thread count */
- CSPROCS, /* check number of current service processes */
- TSYNC, /* check timesync status 0=no 1=yes in sync to the network */
- LRUS, /* check LRU sitting time in seconds */
- DCB, /* check dirty cache buffers as a percentage of the total */
- TCB, /* check total cache buffers as a percentage of the original */
- DSVER, /* check NDS version */
- UPTIME, /* check server uptime */
- NLM, /* check NLM loaded */
- NRMP, /* check NRM Process Values */
- NRMM, /* check NRM Memory Values */
- NRMS, /* check NRM Values */
- NSS1, /* check Statistics from _Admin:Manage_NSS\GeneralStats.xml */
- NSS2, /* check Statistics from _Admin:Manage_NSS\BufferCache.xml */
- NSS3, /* check statistics from _Admin:Manage_NSS\NameCache.xml */
- NSS4, /* check statistics from _Admin:Manage_NSS\FileStats.xml */
- NSS5, /* check statistics from _Admin:Manage_NSS\ObjectCache.xml */
- NSS6, /* check statistics from _Admin:Manage_NSS\Thread.xml */
- NSS7 /* check statistics from _Admin:Manage_NSS\AuthorizationCache.xml */
-};
-
-enum {
- PORT = 9999
-};
-
-static char *server_address = NULL;
-static char *volume_name = NULL;
-static char *nlm_name = NULL;
-static char *nrmp_name = NULL;
-static char *nrmm_name = NULL;
-static char *nrms_name = NULL;
-static char *nss1_name = NULL;
-static char *nss2_name = NULL;
-static char *nss3_name = NULL;
-static char *nss4_name = NULL;
-static char *nss5_name = NULL;
-static char *nss6_name = NULL;
-static char *nss7_name = NULL;
-static int server_port = PORT;
-static unsigned long warning_value = 0L;
-static unsigned long critical_value = 0L;
-static bool check_warning_value = false;
-static bool check_critical_value = false;
-static bool check_netware_version = false;
-static enum checkvar vars_to_check = NONE;
-static int sap_number = -1;
-
-static int process_arguments(int /*argc*/, char ** /*argv*/);
-static void print_help(void);
-void print_usage(void);
-
-int main(int argc, char **argv) {
- int result = STATE_UNKNOWN;
- int sd;
- char *send_buffer = NULL;
- char recv_buffer[MAX_INPUT_BUFFER];
- char *output_message = NULL;
- char *temp_buffer = NULL;
- char *netware_version = NULL;
-
- int time_sync_status = 0;
- int nrm_health_status = 0;
- unsigned long total_cache_buffers = 0;
- unsigned long dirty_cache_buffers = 0;
- unsigned long open_files = 0;
- unsigned long abended_threads = 0;
- unsigned long max_service_processes = 0;
- unsigned long current_service_processes = 0;
- unsigned long free_disk_space = 0L;
- unsigned long nrmp_value = 0L;
- unsigned long nrmm_value = 0L;
- unsigned long nrms_value = 0L;
- unsigned long nss1_value = 0L;
- unsigned long nss2_value = 0L;
- unsigned long nss3_value = 0L;
- unsigned long nss4_value = 0L;
- unsigned long nss5_value = 0L;
- unsigned long nss6_value = 0L;
- unsigned long nss7_value = 0L;
- unsigned long total_disk_space = 0L;
- unsigned long used_disk_space = 0L;
- unsigned long percent_used_disk_space = 0L;
- unsigned long purgeable_disk_space = 0L;
- unsigned long non_purgeable_disk_space = 0L;
- unsigned long percent_free_space = 0;
- unsigned long percent_purgeable_space = 0;
- unsigned long percent_non_purgeable_space = 0;
- unsigned long current_connections = 0L;
- unsigned long utilization = 0L;
- unsigned long cache_hits = 0;
- unsigned long cache_buffers = 0L;
- unsigned long lru_time = 0L;
- unsigned long max_packet_receive_buffers = 0;
- unsigned long used_packet_receive_buffers = 0;
- unsigned long percent_used_packet_receive_buffers = 0L;
- unsigned long sap_entries = 0;
- char uptime[MAX_INPUT_BUFFER];
-
- setlocale(LC_ALL, "");
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
-
- /* Parse extra opts if any */
- argv = np_extra_opts(&argc, argv, progname);
-
- if (process_arguments(argc, argv) == ERROR)
- usage4(_("Could not parse arguments"));
-
- /* initialize alarm signal handling */
- signal(SIGALRM, socket_timeout_alarm_handler);
-
- /* set socket timeout */
- alarm(socket_timeout);
-
- /* open connection */
- my_tcp_connect(server_address, server_port, &sd);
-
- /* get OS version string */
- if (check_netware_version) {
- send_buffer = strdup("S19\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- if (!strcmp(recv_buffer, "-1\n"))
- netware_version = strdup("");
- else {
- recv_buffer[strlen(recv_buffer) - 1] = 0;
- xasprintf(&netware_version, _("NetWare %s: "), recv_buffer);
- }
- } else
- netware_version = strdup("");
-
- /* check CPU load */
- if (vars_to_check == LOAD1 || vars_to_check == LOAD5 || vars_to_check == LOAD15) {
-
- switch (vars_to_check) {
- case LOAD1:
- temp_buffer = strdup("1");
- break;
- case LOAD5:
- temp_buffer = strdup("5");
- break;
- default:
- temp_buffer = strdup("15");
- break;
- }
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "UTIL%s\r\n", temp_buffer);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- utilization = strtoul(recv_buffer, NULL, 10);
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- send_buffer = strdup("UPTIME\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- recv_buffer[strlen(recv_buffer) - 1] = 0;
- sprintf(uptime, _("Up %s,"), recv_buffer);
-
- if (check_critical_value && utilization >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && utilization >= warning_value)
- result = STATE_WARNING;
-
- xasprintf(&output_message, _("Load %s - %s %s-min load average = %lu%%|load%s=%lu;%lu;%lu;0;100"), state_text(result), uptime,
- temp_buffer, utilization, temp_buffer, utilization, warning_value, critical_value);
-
- /* check number of user connections */
- } else if (vars_to_check == CONNS) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- send_buffer = strdup("CONNECT\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- current_connections = strtoul(recv_buffer, NULL, 10);
-
- if (check_critical_value && current_connections >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && current_connections >= warning_value)
- result = STATE_WARNING;
-
- xasprintf(&output_message, _("Conns %s - %lu current connections|Conns=%lu;%lu;%lu;;"), state_text(result), current_connections,
- current_connections, warning_value, critical_value);
-
- /* check % long term cache hits */
- } else if (vars_to_check == LTCH) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- send_buffer = strdup("S1\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- cache_hits = atoi(recv_buffer);
-
- if (check_critical_value && cache_hits <= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && cache_hits <= warning_value)
- result = STATE_WARNING;
-
- xasprintf(&output_message, _("%s: Long term cache hits = %lu%%"), state_text(result), cache_hits);
-
- /* check cache buffers */
- } else if (vars_to_check == CBUFF) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- send_buffer = strdup("S2\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- cache_buffers = strtoul(recv_buffer, NULL, 10);
-
- if (check_critical_value && cache_buffers <= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && cache_buffers <= warning_value)
- result = STATE_WARNING;
-
- xasprintf(&output_message, _("%s: Total cache buffers = %lu|Cachebuffers=%lu;%lu;%lu;;"), state_text(result), cache_buffers,
- cache_buffers, warning_value, critical_value);
-
- /* check dirty cache buffers */
- } else if (vars_to_check == CDBUFF) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- send_buffer = strdup("S3\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- cache_buffers = strtoul(recv_buffer, NULL, 10);
-
- if (check_critical_value && cache_buffers >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && cache_buffers >= warning_value)
- result = STATE_WARNING;
-
- xasprintf(&output_message, _("%s: Dirty cache buffers = %lu|Dirty-Cache-Buffers=%lu;%lu;%lu;;"), state_text(result), cache_buffers,
- cache_buffers, warning_value, critical_value);
-
- /* check LRU sitting time in minutes */
- } else if (vars_to_check == LRUM) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- send_buffer = strdup("S5\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- lru_time = strtoul(recv_buffer, NULL, 10);
-
- if (check_critical_value && lru_time <= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && lru_time <= warning_value)
- result = STATE_WARNING;
-
- xasprintf(&output_message, _("%s: LRU sitting time = %lu minutes"), state_text(result), lru_time);
-
- /* check KB free space on volume */
- } else if (vars_to_check == VKF) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "VKF%s\r\n", volume_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
- result = STATE_CRITICAL;
- } else {
- free_disk_space = strtoul(recv_buffer, NULL, 10);
- if (check_critical_value && free_disk_space <= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && free_disk_space <= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("%s%lu KB free on volume %s|KBFree%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
- free_disk_space, volume_name, volume_name, free_disk_space, warning_value, critical_value);
- }
-
- /* check MB free space on volume */
- } else if (vars_to_check == VMF) {
-
- xasprintf(&send_buffer, "VMF%s\r\n", volume_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
- result = STATE_CRITICAL;
- } else {
- free_disk_space = strtoul(recv_buffer, NULL, 10);
- if (check_critical_value && free_disk_space <= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && free_disk_space <= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("%s%lu MB free on volume %s|MBFree%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
- free_disk_space, volume_name, volume_name, free_disk_space, warning_value, critical_value);
- }
- /* check MB used space on volume */
- } else if (vars_to_check == VMU) {
-
- xasprintf(&send_buffer, "VMU%s\r\n", volume_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
- result = STATE_CRITICAL;
- } else {
- free_disk_space = strtoul(recv_buffer, NULL, 10);
- if (check_critical_value && free_disk_space <= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && free_disk_space <= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("%s%lu MB used on volume %s|MBUsed%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
- free_disk_space, volume_name, volume_name, free_disk_space, warning_value, critical_value);
- }
- /* check % used space on volume */
- } else if (vars_to_check == VPU) {
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- asprintf(&send_buffer, "VMU%s\r\n", volume_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
-
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- asprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
- result = STATE_CRITICAL;
-
- } else {
- used_disk_space = strtoul(recv_buffer, NULL, 10);
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
- /* get total volume in MB */
- asprintf(&send_buffer, "VMS%s\r\n", volume_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- total_disk_space = strtoul(recv_buffer, NULL, 10);
- /* calculate percent used on volume */
- percent_used_disk_space = (unsigned long)(((double)used_disk_space / (double)total_disk_space) * 100.0);
-
- if (check_critical_value && percent_used_disk_space >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && percent_used_disk_space >= warning_value)
- result = STATE_WARNING;
-
- asprintf(&output_message, _("%lu MB (%lu%%) used on volume %s - total %lu MB|Used space in percent on %s=%lu;%lu;%lu;0;100"),
- used_disk_space, percent_used_disk_space, volume_name, total_disk_space, volume_name, percent_used_disk_space,
- warning_value, critical_value);
- }
-
- /* check % free space on volume */
- } else if (vars_to_check == VPF) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "VKF%s\r\n", volume_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
-
- xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
- result = STATE_CRITICAL;
-
- } else {
-
- free_disk_space = strtoul(recv_buffer, NULL, 10);
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "VKS%s\r\n", volume_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- total_disk_space = strtoul(recv_buffer, NULL, 10);
-
- percent_free_space = (unsigned long)(((double)free_disk_space / (double)total_disk_space) * 100.0);
-
- if (check_critical_value && percent_free_space <= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && percent_free_space <= warning_value)
- result = STATE_WARNING;
- free_disk_space /= 1024;
- total_disk_space /= 1024;
- xasprintf(&output_message, _("%lu MB (%lu%%) free on volume %s - total %lu MB|FreeMB%s=%lu;%lu;%lu;0;100"), free_disk_space,
- percent_free_space, volume_name, total_disk_space, volume_name, percent_free_space, warning_value, critical_value);
- }
-
- /* check to see if DS Database is open or closed */
- } else if (vars_to_check == DSDB) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- send_buffer = strdup("S11\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- if (atoi(recv_buffer) == 1)
- result = STATE_OK;
- else
- result = STATE_WARNING;
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- send_buffer = strdup("S13\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- temp_buffer = strtok(recv_buffer, "\r\n");
-
- xasprintf(&output_message, _("Directory Services Database is %s (DS version %s)"), (result == STATE_OK) ? "open" : "closed",
- temp_buffer);
-
- /* check to see if logins are enabled */
- } else if (vars_to_check == LOGINS) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- send_buffer = strdup("S12\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- if (atoi(recv_buffer) == 1)
- result = STATE_OK;
- else
- result = STATE_WARNING;
-
- xasprintf(&output_message, _("Logins are %s"), (result == STATE_OK) ? _("enabled") : _("disabled"));
-
- /* check NRM Health Status Summary*/
- } else if (vars_to_check == NRMH) {
-
- xasprintf(&send_buffer, "NRMH\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- nrm_health_status = atoi(recv_buffer);
-
- if (nrm_health_status == 2) {
- result = STATE_OK;
- xasprintf(&output_message, _("CRITICAL - NRM Status is bad!"));
- } else {
- if (nrm_health_status == 1) {
- result = STATE_WARNING;
- xasprintf(&output_message, _("Warning - NRM Status is suspect!"));
- }
-
- xasprintf(&output_message, _("OK - NRM Status is good!"));
- }
-
- /* check packet receive buffers */
- } else if (vars_to_check == UPRB || vars_to_check == PUPRB) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "S15\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- used_packet_receive_buffers = atoi(recv_buffer);
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "S16\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- max_packet_receive_buffers = atoi(recv_buffer);
-
- percent_used_packet_receive_buffers =
- (unsigned long)(((double)used_packet_receive_buffers / (double)max_packet_receive_buffers) * 100.0);
-
- if (vars_to_check == UPRB) {
- if (check_critical_value && used_packet_receive_buffers >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && used_packet_receive_buffers >= warning_value)
- result = STATE_WARNING;
- } else {
- if (check_critical_value && percent_used_packet_receive_buffers >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && percent_used_packet_receive_buffers >= warning_value)
- result = STATE_WARNING;
- }
-
- xasprintf(&output_message, _("%lu of %lu (%lu%%) packet receive buffers used"), used_packet_receive_buffers,
- max_packet_receive_buffers, percent_used_packet_receive_buffers);
-
- /* check SAP table entries */
- } else if (vars_to_check == SAPENTRIES) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- if (sap_number == -1)
- xasprintf(&send_buffer, "S9\r\n");
- else
- xasprintf(&send_buffer, "S9.%d\r\n", sap_number);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- sap_entries = atoi(recv_buffer);
-
- if (check_critical_value && sap_entries >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && sap_entries >= warning_value)
- result = STATE_WARNING;
-
- if (sap_number == -1)
- xasprintf(&output_message, _("%lu entries in SAP table"), sap_entries);
- else
- xasprintf(&output_message, _("%lu entries in SAP table for SAP type %d"), sap_entries, sap_number);
-
- /* check KB purgeable space on volume */
- } else if (vars_to_check == VKP) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "VKP%s\r\n", volume_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
- result = STATE_CRITICAL;
- } else {
- purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
- if (check_critical_value && purgeable_disk_space >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && purgeable_disk_space >= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("%s%lu KB purgeable on volume %s|Purge%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
- purgeable_disk_space, volume_name, volume_name, purgeable_disk_space, warning_value, critical_value);
- }
- /* check MB purgeable space on volume */
- } else if (vars_to_check == VMP) {
-
- xasprintf(&send_buffer, "VMP%s\r\n", volume_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
- result = STATE_CRITICAL;
- } else {
- purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
- if (check_critical_value && purgeable_disk_space >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && purgeable_disk_space >= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("%s%lu MB purgeable on volume %s|Purge%s=%lu;%lu;%lu;;"), (result == STATE_OK) ? "" : _("Only "),
- purgeable_disk_space, volume_name, volume_name, purgeable_disk_space, warning_value, critical_value);
- }
-
- /* check % purgeable space on volume */
- } else if (vars_to_check == VPP) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "VKP%s\r\n", volume_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
-
- xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
- result = STATE_CRITICAL;
-
- } else {
-
- purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "VKS%s\r\n", volume_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- total_disk_space = strtoul(recv_buffer, NULL, 10);
-
- percent_purgeable_space = (unsigned long)(((double)purgeable_disk_space / (double)total_disk_space) * 100.0);
-
- if (check_critical_value && percent_purgeable_space >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && percent_purgeable_space >= warning_value)
- result = STATE_WARNING;
- purgeable_disk_space /= 1024;
- xasprintf(&output_message, _("%lu MB (%lu%%) purgeable on volume %s|Purgeable%s=%lu;%lu;%lu;0;100"), purgeable_disk_space,
- percent_purgeable_space, volume_name, volume_name, percent_purgeable_space, warning_value, critical_value);
- }
-
- /* check KB not yet purgeable space on volume */
- } else if (vars_to_check == VKNP) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "VKNP%s\r\n", volume_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
- result = STATE_CRITICAL;
- } else {
- non_purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
- if (check_critical_value && non_purgeable_disk_space >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && non_purgeable_disk_space >= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("%s%lu KB not yet purgeable on volume %s"), (result == STATE_OK) ? "" : _("Only "),
- non_purgeable_disk_space, volume_name);
- }
-
- /* check % not yet purgeable space on volume */
- } else if (vars_to_check == VPNP) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "VKNP%s\r\n", volume_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
-
- xasprintf(&output_message, _("CRITICAL - Volume '%s' does not exist!"), volume_name);
- result = STATE_CRITICAL;
-
- } else {
-
- non_purgeable_disk_space = strtoul(recv_buffer, NULL, 10);
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "VKS%s\r\n", volume_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- total_disk_space = strtoul(recv_buffer, NULL, 10);
-
- percent_non_purgeable_space = (unsigned long)(((double)non_purgeable_disk_space / (double)total_disk_space) * 100.0);
-
- if (check_critical_value && percent_non_purgeable_space >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && percent_non_purgeable_space >= warning_value)
- result = STATE_WARNING;
- purgeable_disk_space /= 1024;
- xasprintf(&output_message, _("%lu MB (%lu%%) not yet purgeable on volume %s"), non_purgeable_disk_space,
- percent_non_purgeable_space, volume_name);
- }
-
- /* check # of open files */
- } else if (vars_to_check == OFILES) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "S18\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- open_files = atoi(recv_buffer);
-
- if (check_critical_value && open_files >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && open_files >= warning_value)
- result = STATE_WARNING;
-
- xasprintf(&output_message, _("%lu open files|Openfiles=%lu;%lu;%lu;0,0"), open_files, open_files, warning_value, critical_value);
-
- /* check # of abended threads (Netware > 5.x only) */
- } else if (vars_to_check == ABENDS) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "S17\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- abended_threads = atoi(recv_buffer);
-
- if (check_critical_value && abended_threads >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && abended_threads >= warning_value)
- result = STATE_WARNING;
-
- xasprintf(&output_message, _("%lu abended threads|Abends=%lu;%lu;%lu;;"), abended_threads, abended_threads, warning_value,
- critical_value);
-
- /* check # of current service processes (Netware 5.x only) */
- } else if (vars_to_check == CSPROCS) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "S20\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- max_service_processes = atoi(recv_buffer);
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "S21\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- current_service_processes = atoi(recv_buffer);
-
- if (check_critical_value && current_service_processes >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && current_service_processes >= warning_value)
- result = STATE_WARNING;
-
- xasprintf(&output_message, _("%lu current service processes (%lu max)|Processes=%lu;%lu;%lu;0;%lu"), current_service_processes,
- max_service_processes, current_service_processes, warning_value, critical_value, max_service_processes);
-
- /* check # Timesync Status */
- } else if (vars_to_check == TSYNC) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "S22\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- time_sync_status = atoi(recv_buffer);
-
- if (time_sync_status == 0) {
- result = STATE_CRITICAL;
- xasprintf(&output_message, _("CRITICAL - Time not in sync with network!"));
- } else {
- xasprintf(&output_message, _("OK - Time in sync with network!"));
- }
-
- /* check LRU sitting time in secondss */
- } else if (vars_to_check == LRUS) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- send_buffer = strdup("S4\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- lru_time = strtoul(recv_buffer, NULL, 10);
-
- if (check_critical_value && lru_time <= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && lru_time <= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("LRU sitting time = %lu seconds"), lru_time);
-
- /* check % dirty cacheobuffers as a percentage of the total*/
- } else if (vars_to_check == DCB) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- send_buffer = strdup("S6\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- dirty_cache_buffers = atoi(recv_buffer);
-
- if (check_critical_value && dirty_cache_buffers <= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && dirty_cache_buffers <= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("Dirty cache buffers = %lu%% of the total|DCB=%lu;%lu;%lu;0;100"), dirty_cache_buffers,
- dirty_cache_buffers, warning_value, critical_value);
-
- /* check % total cache buffers as a percentage of the original*/
- } else if (vars_to_check == TCB) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- send_buffer = strdup("S7\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
- total_cache_buffers = atoi(recv_buffer);
-
- if (check_critical_value && total_cache_buffers <= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && total_cache_buffers <= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("Total cache buffers = %lu%% of the original|TCB=%lu;%lu;%lu;0;100"), total_cache_buffers,
- total_cache_buffers, warning_value, critical_value);
-
- } else if (vars_to_check == DSVER) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "S13\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- recv_buffer[strlen(recv_buffer) - 1] = 0;
-
- xasprintf(&output_message, _("NDS Version %s"), recv_buffer);
-
- } else if (vars_to_check == UPTIME) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "UPTIME\r\n");
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- recv_buffer[sizeof(recv_buffer) - 1] = 0;
- recv_buffer[strlen(recv_buffer) - 1] = 0;
-
- xasprintf(&output_message, _("Up %s"), recv_buffer);
-
- } else if (vars_to_check == NLM) {
-
- close(sd);
- my_tcp_connect(server_address, server_port, &sd);
-
- xasprintf(&send_buffer, "S24:%s\r\n", nlm_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- recv_buffer[strlen(recv_buffer) - 1] = 0;
- if (strcmp(recv_buffer, "-1")) {
- xasprintf(&output_message, _("Module %s version %s is loaded"), nlm_name, recv_buffer);
- } else {
- result = STATE_CRITICAL;
- xasprintf(&output_message, _("Module %s is not loaded"), nlm_name);
- }
- } else if (vars_to_check == NRMP) {
-
- xasprintf(&send_buffer, "NRMP:%s\r\n", nrmp_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nrmp_name);
- result = STATE_CRITICAL;
- } else {
- nrmp_value = strtoul(recv_buffer, NULL, 10);
- if (check_critical_value && nrmp_value <= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && nrmp_value <= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nrmp_name, nrmp_value, nrmp_name, nrmp_value, warning_value,
- critical_value);
- }
-
- } else if (vars_to_check == NRMM) {
-
- xasprintf(&send_buffer, "NRMM:%s\r\n", nrmm_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nrmm_name);
- result = STATE_CRITICAL;
- } else {
- nrmm_value = strtoul(recv_buffer, NULL, 10);
- if (check_critical_value && nrmm_value <= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && nrmm_value <= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nrmm_name, nrmm_value, nrmm_name, nrmm_value, warning_value,
- critical_value);
- }
-
- } else if (vars_to_check == NRMS) {
-
- xasprintf(&send_buffer, "NRMS:%s\r\n", nrms_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nrms_name);
- result = STATE_CRITICAL;
- } else {
- nrms_value = strtoul(recv_buffer, NULL, 10);
- if (check_critical_value && nrms_value >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && nrms_value >= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nrms_name, nrms_value, nrms_name, nrms_value, warning_value,
- critical_value);
- }
-
- } else if (vars_to_check == NSS1) {
-
- xasprintf(&send_buffer, "NSS1:%s\r\n", nss1_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss1_name);
- result = STATE_CRITICAL;
- } else {
- nss1_value = strtoul(recv_buffer, NULL, 10);
- if (check_critical_value && nss1_value >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && nss1_value >= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss1_name, nss1_value, nss1_name, nss1_value, warning_value,
- critical_value);
- }
-
- } else if (vars_to_check == NSS2) {
-
- xasprintf(&send_buffer, "NSS2:%s\r\n", nss2_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss2_name);
- result = STATE_CRITICAL;
- } else {
- nss2_value = strtoul(recv_buffer, NULL, 10);
- if (check_critical_value && nss2_value >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && nss2_value >= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss2_name, nss2_value, nss2_name, nss2_value, warning_value,
- critical_value);
- }
-
- } else if (vars_to_check == NSS3) {
-
- xasprintf(&send_buffer, "NSS3:%s\r\n", nss3_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss3_name);
- result = STATE_CRITICAL;
- } else {
- nss3_value = strtoul(recv_buffer, NULL, 10);
- if (check_critical_value && nss3_value >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && nss3_value >= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss3_name, nss3_value, nss3_name, nss3_value, warning_value,
- critical_value);
- }
-
- } else if (vars_to_check == NSS4) {
-
- xasprintf(&send_buffer, "NSS4:%s\r\n", nss4_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss4_name);
- result = STATE_CRITICAL;
- } else {
- nss4_value = strtoul(recv_buffer, NULL, 10);
- if (check_critical_value && nss4_value >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && nss4_value >= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss4_name, nss4_value, nss4_name, nss4_value, warning_value,
- critical_value);
- }
-
- } else if (vars_to_check == NSS5) {
-
- xasprintf(&send_buffer, "NSS5:%s\r\n", nss5_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss5_name);
- result = STATE_CRITICAL;
- } else {
- nss5_value = strtoul(recv_buffer, NULL, 10);
- if (check_critical_value && nss5_value >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && nss5_value >= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss5_name, nss5_value, nss5_name, nss5_value, warning_value,
- critical_value);
- }
-
- } else if (vars_to_check == NSS6) {
-
- xasprintf(&send_buffer, "NSS6:%s\r\n", nss6_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss6_name);
- result = STATE_CRITICAL;
- } else {
- nss6_value = strtoul(recv_buffer, NULL, 10);
- if (check_critical_value && nss6_value >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && nss6_value >= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss6_name, nss6_value, nss6_name, nss6_value, warning_value,
- critical_value);
- }
-
- } else if (vars_to_check == NSS7) {
-
- xasprintf(&send_buffer, "NSS7:%s\r\n", nss7_name);
- result = send_tcp_request(sd, send_buffer, recv_buffer, sizeof(recv_buffer));
- if (result != STATE_OK)
- return result;
-
- if (!strcmp(recv_buffer, "-1\n")) {
- xasprintf(&output_message, _("CRITICAL - Value '%s' does not exist!"), nss7_name);
- result = STATE_CRITICAL;
- } else {
- nss7_value = strtoul(recv_buffer, NULL, 10);
- if (check_critical_value && nss7_value >= critical_value)
- result = STATE_CRITICAL;
- else if (check_warning_value && nss7_value >= warning_value)
- result = STATE_WARNING;
- xasprintf(&output_message, _("%s is %lu|%s=%lu;%lu;%lu;;"), nss7_name, nss7_value, nss7_name, nss7_value, warning_value,
- critical_value);
- }
-
- } else {
-
- output_message = strdup(_("Nothing to check!\n"));
- result = STATE_UNKNOWN;
- }
-
- close(sd);
-
- /* reset timeout */
- alarm(0);
-
- printf("%s%s\n", netware_version, output_message);
-
- return result;
-}
-
-/* process command-line arguments */
-int process_arguments(int argc, char **argv) {
- int c;
-
- int option = 0;
- static struct option longopts[] = {{"port", required_argument, 0, 'p'}, {"timeout", required_argument, 0, 't'},
- {"critical", required_argument, 0, 'c'}, {"warning", required_argument, 0, 'w'},
- {"variable", required_argument, 0, 'v'}, {"hostname", required_argument, 0, 'H'},
- {"osversion", no_argument, 0, 'o'}, {"version", no_argument, 0, 'V'},
- {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}};
-
- /* no options were supplied */
- if (argc < 2)
- return ERROR;
-
- /* backwards compatibility */
- if (!is_option(argv[1])) {
- server_address = argv[1];
- argv[1] = argv[0];
- argv = &argv[1];
- argc--;
- }
-
- for (c = 1; c < argc; c++) {
- if (strcmp("-to", argv[c]) == 0)
- strcpy(argv[c], "-t");
- else if (strcmp("-wv", argv[c]) == 0)
- strcpy(argv[c], "-w");
- else if (strcmp("-cv", argv[c]) == 0)
- strcpy(argv[c], "-c");
- }
-
- while (1) {
- c = getopt_long(argc, argv, "+hoVH:t:c:w:p:v:", longopts, &option);
-
- if (c == -1 || c == EOF || c == 1)
- break;
-
- switch (c) {
- case '?': /* print short usage statement if args not parsable */
- usage5();
- case 'h': /* help */
- print_help();
- exit(STATE_UNKNOWN);
- case 'V': /* version */
- print_revision(progname, NP_VERSION);
- exit(STATE_UNKNOWN);
- case 'H': /* hostname */
- server_address = optarg;
- break;
- case 'o': /* display nos version */
- check_netware_version = true;
- break;
- case 'p': /* port */
- if (is_intnonneg(optarg))
- server_port = atoi(optarg);
- else
- die(STATE_UNKNOWN, _("Server port an integer\n"));
- break;
- case 'v':
- if (strlen(optarg) < 3)
- return ERROR;
- if (!strcmp(optarg, "LOAD1"))
- vars_to_check = LOAD1;
- else if (!strcmp(optarg, "LOAD5"))
- vars_to_check = LOAD5;
- else if (!strcmp(optarg, "LOAD15"))
- vars_to_check = LOAD15;
- else if (!strcmp(optarg, "CONNS"))
- vars_to_check = CONNS;
- else if (!strcmp(optarg, "LTCH"))
- vars_to_check = LTCH;
- else if (!strcmp(optarg, "DCB"))
- vars_to_check = DCB;
- else if (!strcmp(optarg, "TCB"))
- vars_to_check = TCB;
- else if (!strcmp(optarg, "CBUFF"))
- vars_to_check = CBUFF;
- else if (!strcmp(optarg, "CDBUFF"))
- vars_to_check = CDBUFF;
- else if (!strcmp(optarg, "LRUM"))
- vars_to_check = LRUM;
- else if (!strcmp(optarg, "LRUS"))
- vars_to_check = LRUS;
- else if (strncmp(optarg, "VPF", 3) == 0) {
- vars_to_check = VPF;
- volume_name = strdup(optarg + 3);
- if (!strcmp(volume_name, ""))
- volume_name = strdup("SYS");
- } else if (strncmp(optarg, "VKF", 3) == 0) {
- vars_to_check = VKF;
- volume_name = strdup(optarg + 3);
- if (!strcmp(volume_name, ""))
- volume_name = strdup("SYS");
- } else if (strncmp(optarg, "VMF", 3) == 0) {
- vars_to_check = VMF;
- volume_name = strdup(optarg + 3);
- if (!strcmp(volume_name, ""))
- volume_name = strdup("SYS");
- } else if (!strcmp(optarg, "DSDB"))
- vars_to_check = DSDB;
- else if (!strcmp(optarg, "LOGINS"))
- vars_to_check = LOGINS;
- else if (!strcmp(optarg, "NRMH"))
- vars_to_check = NRMH;
- else if (!strcmp(optarg, "UPRB"))
- vars_to_check = UPRB;
- else if (!strcmp(optarg, "PUPRB"))
- vars_to_check = PUPRB;
- else if (!strncmp(optarg, "SAPENTRIES", 10)) {
- vars_to_check = SAPENTRIES;
- if (strlen(optarg) > 10)
- sap_number = atoi(optarg + 10);
- else
- sap_number = -1;
- } else if (!strcmp(optarg, "OFILES"))
- vars_to_check = OFILES;
- else if (strncmp(optarg, "VKP", 3) == 0) {
- vars_to_check = VKP;
- volume_name = strdup(optarg + 3);
- if (!strcmp(volume_name, ""))
- volume_name = strdup("SYS");
- } else if (strncmp(optarg, "VMP", 3) == 0) {
- vars_to_check = VMP;
- volume_name = strdup(optarg + 3);
- if (!strcmp(volume_name, ""))
- volume_name = strdup("SYS");
- } else if (strncmp(optarg, "VMU", 3) == 0) {
- vars_to_check = VMU;
- volume_name = strdup(optarg + 3);
- if (!strcmp(volume_name, ""))
- volume_name = strdup("SYS");
- } else if (strncmp(optarg, "VPU", 3) == 0) {
- vars_to_check = VPU;
- volume_name = strdup(optarg + 3);
- if (!strcmp(volume_name, ""))
- volume_name = strdup("SYS");
- } else if (strncmp(optarg, "VPP", 3) == 0) {
- vars_to_check = VPP;
- volume_name = strdup(optarg + 3);
- if (!strcmp(volume_name, ""))
- volume_name = strdup("SYS");
- } else if (strncmp(optarg, "VKNP", 4) == 0) {
- vars_to_check = VKNP;
- volume_name = strdup(optarg + 4);
- if (!strcmp(volume_name, ""))
- volume_name = strdup("SYS");
- } else if (strncmp(optarg, "VPNP", 4) == 0) {
- vars_to_check = VPNP;
- volume_name = strdup(optarg + 4);
- if (!strcmp(volume_name, ""))
- volume_name = strdup("SYS");
- } else if (!strcmp(optarg, "ABENDS"))
- vars_to_check = ABENDS;
- else if (!strcmp(optarg, "CSPROCS"))
- vars_to_check = CSPROCS;
- else if (!strcmp(optarg, "TSYNC"))
- vars_to_check = TSYNC;
- else if (!strcmp(optarg, "DSVER"))
- vars_to_check = DSVER;
- else if (!strcmp(optarg, "UPTIME")) {
- vars_to_check = UPTIME;
- } else if (strncmp(optarg, "NLM:", 4) == 0) {
- vars_to_check = NLM;
- nlm_name = strdup(optarg + 4);
- } else if (strncmp(optarg, "NRMP", 4) == 0) {
- vars_to_check = NRMP;
- nrmp_name = strdup(optarg + 4);
- if (!strcmp(nrmp_name, ""))
- nrmp_name = strdup("AVAILABLE_MEMORY");
- } else if (strncmp(optarg, "NRMM", 4) == 0) {
- vars_to_check = NRMM;
- nrmm_name = strdup(optarg + 4);
- if (!strcmp(nrmm_name, ""))
- nrmm_name = strdup("AVAILABLE_CACHE_MEMORY");
-
- }
-
- else if (strncmp(optarg, "NRMS", 4) == 0) {
- vars_to_check = NRMS;
- nrms_name = strdup(optarg + 4);
- if (!strcmp(nrms_name, ""))
- nrms_name = strdup("USED_SWAP_SPACE");
-
- }
-
- else if (strncmp(optarg, "NSS1", 4) == 0) {
- vars_to_check = NSS1;
- nss1_name = strdup(optarg + 4);
- if (!strcmp(nss1_name, ""))
- nss1_name = strdup("CURRENTBUFFERCACHESIZE");
-
- }
-
- else if (strncmp(optarg, "NSS2", 4) == 0) {
- vars_to_check = NSS2;
- nss2_name = strdup(optarg + 4);
- if (!strcmp(nss2_name, ""))
- nss2_name = strdup("CACHEHITS");
-
- }
-
- else if (strncmp(optarg, "NSS3", 4) == 0) {
- vars_to_check = NSS3;
- nss3_name = strdup(optarg + 4);
- if (!strcmp(nss3_name, ""))
- nss3_name = strdup("CACHEGITPERCENT");
-
- }
-
- else if (strncmp(optarg, "NSS4", 4) == 0) {
- vars_to_check = NSS4;
- nss4_name = strdup(optarg + 4);
- if (!strcmp(nss4_name, ""))
- nss4_name = strdup("CURRENTOPENCOUNT");
-
- }
-
- else if (strncmp(optarg, "NSS5", 4) == 0) {
- vars_to_check = NSS5;
- nss5_name = strdup(optarg + 4);
- if (!strcmp(nss5_name, ""))
- nss5_name = strdup("CACHEMISSES");
-
- }
-
- else if (strncmp(optarg, "NSS6", 4) == 0) {
- vars_to_check = NSS6;
- nss6_name = strdup(optarg + 4);
- if (!strcmp(nss6_name, ""))
- nss6_name = strdup("PENDINGWORKSCOUNT");
-
- }
-
- else if (strncmp(optarg, "NSS7", 4) == 0) {
- vars_to_check = NSS7;
- nss7_name = strdup(optarg + 4);
- if (!strcmp(nss7_name, ""))
- nss7_name = strdup("CACHESIZE");
-
- }
-
- else
- return ERROR;
- break;
- case 'w': /* warning threshold */
- warning_value = strtoul(optarg, NULL, 10);
- check_warning_value = true;
- break;
- case 'c': /* critical threshold */
- critical_value = strtoul(optarg, NULL, 10);
- check_critical_value = true;
- break;
- case 't': /* timeout */
- socket_timeout = atoi(optarg);
- if (socket_timeout <= 0)
- return ERROR;
- }
- }
-
- return OK;
-}
-
-void print_help(void) {
- char *myport;
- xasprintf(&myport, "%d", PORT);
-
- print_revision(progname, NP_VERSION);
-
- printf("Copyright (c) 1999 Ethan Galstad \n");
- printf(COPYRIGHT, copyright, email);
-
- printf("%s\n", _("This plugin attempts to contact the MRTGEXT NLM running on a"));
- printf("%s\n", _("Novell server to gather the requested system information."));
-
- printf("\n\n");
-
- print_usage();
-
- printf(UT_HELP_VRSN);
- printf(UT_EXTRA_OPTS);
-
- printf(UT_HOST_PORT, 'p', myport);
-
- printf(" %s\n", "-v, --variable=STRING");
- printf(" %s\n", _("Variable to check. Valid variables include:"));
- printf(" %s\n", _("LOAD1 = 1 minute average CPU load"));
- printf(" %s\n", _("LOAD5 = 5 minute average CPU load"));
- printf(" %s\n", _("LOAD15 = 15 minute average CPU load"));
- printf(" %s\n", _("CSPROCS = number of current service processes (NW 5.x only)"));
- printf(" %s\n", _("ABENDS = number of abended threads (NW 5.x only)"));
- printf(" %s\n", _("UPTIME = server uptime"));
- printf(" %s\n", _("LTCH = percent long term cache hits"));
- printf(" %s\n", _("CBUFF = current number of cache buffers"));
- printf(" %s\n", _("CDBUFF = current number of dirty cache buffers"));
- printf(" %s\n", _("DCB = dirty cache buffers as a percentage of the total"));
- printf(" %s\n", _("TCB = dirty cache buffers as a percentage of the original"));
- printf(" %s\n", _("OFILES = number of open files"));
- printf(" %s\n", _(" VMF = MB of free space on Volume "));
- printf(" %s\n", _(" VMU = MB used space on Volume "));
- printf(" %s\n", _(" VPU = percent used space on Volume "));
- printf(" %s\n", _(" VMP = MB of purgeable space on Volume "));
- printf(" %s\n", _(" VPF = percent free space on volume "));
- printf(" %s\n", _(" VKF = KB of free space on volume "));
- printf(" %s\n", _(" VPP = percent purgeable space on volume "));
- printf(" %s\n", _(" VKP = KB of purgeable space on volume "));
- printf(" %s\n", _(" VPNP = percent not yet purgeable space on volume "));
- printf(" %s\n", _(" VKNP = KB of not yet purgeable space on volume "));
- printf(" %s\n", _(" LRUM = LRU sitting time in minutes"));
- printf(" %s\n", _(" LRUS = LRU sitting time in seconds"));
- printf(" %s\n", _(" DSDB = check to see if DS Database is open"));
- printf(" %s\n", _(" DSVER = NDS version"));
- printf(" %s\n", _(" UPRB = used packet receive buffers"));
- printf(" %s\n", _(" PUPRB = percent (of max) used packet receive buffers"));
- printf(" %s\n", _(" SAPENTRIES = number of entries in the SAP table"));
- printf(" %s\n", _(" SAPENTRIES = number of entries in the SAP table for SAP type "));
- printf(" %s\n", _(" TSYNC = timesync status"));
- printf(" %s\n", _(" LOGINS = check to see if logins are enabled"));
- printf(" %s\n", _(" CONNS = number of currently licensed connections"));
- printf(" %s\n", _(" NRMH = NRM Summary Status"));
- printf(" %s\n", _(" NRMP = Returns the current value for a NRM health item"));
- printf(" %s\n", _(" NRMM = Returns the current memory stats from NRM"));
- printf(" %s\n", _(" NRMS = Returns the current Swapfile stats from NRM"));
- printf(" %s\n", _(" NSS1 = Statistics from _Admin:Manage_NSS\\GeneralStats.xml"));
- printf(" %s\n", _(" NSS3 = Statistics from _Admin:Manage_NSS\\NameCache.xml"));
- printf(" %s\n", _(" NSS4 = Statistics from _Admin:Manage_NSS\\FileStats.xml"));
- printf(" %s\n", _(" NSS5 = Statistics from _Admin:Manage_NSS\\ObjectCache.xml"));
- printf(" %s\n", _(" NSS6 = Statistics from _Admin:Manage_NSS\\Thread.xml"));
- printf(" %s\n", _(" NSS7 = Statistics from _Admin:Manage_NSS\\AuthorizationCache.xml"));
- printf(" %s\n", _(" NLM: = check if NLM is loaded and report version"));
- printf(" %s\n", _(" (e.g. NLM:TSANDS.NLM)"));
- printf("\n");
- printf(" %s\n", "-w, --warning=INTEGER");
- printf(" %s\n", _("Threshold which will result in a warning status"));
- printf(" %s\n", "-c, --critical=INTEGER");
- printf(" %s\n", _("Threshold which will result in a critical status"));
- printf(" %s\n", "-o, --osversion");
- printf(" %s\n", _("Include server version string in results"));
-
- printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
-
- printf("\n");
- printf("%s\n", _("Notes:"));
- printf(" %s\n", _("- This plugin requires that the MRTGEXT.NLM file from James Drews' MRTG"));
- printf(" %s\n", _(" extension for NetWare be loaded on the Novell servers you wish to check."));
- printf(" %s\n", _(" (available from http://www.engr.wisc.edu/~drews/mrtg/)"));
- printf(" %s\n", _("- Values for critical thresholds should be lower than warning thresholds"));
- printf(" %s\n", _(" when the following variables are checked: VPF, VKF, LTCH, CBUFF, DCB, "));
- printf(" %s\n", _(" TCB, LRUS and LRUM."));
-
- printf(UT_SUPPORT);
-}
-
-void print_usage(void) {
- printf("%s\n", _("Usage:"));
- printf("%s -H host [-p port] [-v variable] [-w warning] [-c critical] [-t timeout]\n", progname);
-}
--
cgit v1.2.3-74-g34f1
From c71a2e414ff3716325a6f4ce715e4a3037d52c0e Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Wed, 12 Mar 2025 13:54:00 +0100
Subject: check_procs: clang-format
---
plugins/check_procs.c | 843 +++++++++++++++++++++++++-------------------------
1 file changed, 422 insertions(+), 421 deletions(-)
diff --git a/plugins/check_procs.c b/plugins/check_procs.c
index 1d78ccee..69b424dc 100644
--- a/plugins/check_procs.c
+++ b/plugins/check_procs.c
@@ -1,41 +1,41 @@
/*****************************************************************************
-*
-* Monitoring check_procs plugin
-*
-* License: GPL
-* Copyright (c) 2000-2024 Monitoring Plugins Development Team
-*
-* Description:
-*
-* This file contains the check_procs plugin
-*
-* Checks all processes and generates WARNING or CRITICAL states if the
-* specified metric is outside the required threshold ranges. The metric
-* defaults to number of processes. Search filters can be applied to limit
-* the processes to check.
-*
-* The parent process, check_procs itself and any child process of
-* check_procs (ps) are excluded from any checks to prevent false positives.
-*
-*
-* 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_procs plugin
+ *
+ * License: GPL
+ * Copyright (c) 2000-2024 Monitoring Plugins Development Team
+ *
+ * Description:
+ *
+ * This file contains the check_procs plugin
+ *
+ * Checks all processes and generates WARNING or CRITICAL states if the
+ * specified metric is outside the required threshold ranges. The metric
+ * defaults to number of processes. Search filters can be applied to limit
+ * the processes to check.
+ *
+ * The parent process, check_procs itself and any child process of
+ * check_procs (ps) are excluded from any checks to prevent false positives.
+ *
+ *
+ * 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_procs";
-const char *program_name = "check_procs"; /* Required for coreutils libs */
+const char *program_name = "check_procs"; /* Required for coreutils libs */
const char *copyright = "2000-2024";
const char *email = "devel@monitoring-plugins.org";
@@ -48,35 +48,36 @@ const char *email = "devel@monitoring-plugins.org";
#include
#ifdef HAVE_SYS_STAT_H
-#include
+# include
#endif
-static int process_arguments (int /*argc*/, char ** /*argv*/);
-static int validate_arguments (void);
-static int convert_to_seconds (char * /*etime*/);
-static void print_help (void);
-void print_usage (void);
+static int process_arguments(int /*argc*/, char ** /*argv*/);
+static int validate_arguments(void);
+static int convert_to_seconds(char * /*etime*/);
+static void print_help(void);
+void print_usage(void);
static char *warning_range = NULL;
static char *critical_range = NULL;
static thresholds *procs_thresholds = NULL;
static int options = 0; /* bitmask of filter criteria to test against */
-#define ALL 1
-#define STAT 2
-#define PPID 4
-#define USER 8
-#define PROG 16
-#define ARGS 32
-#define VSZ 64
-#define RSS 128
-#define PCPU 256
-#define ELAPSED 512
-#define EREG_ARGS 1024
+#define ALL 1
+#define STAT 2
+#define PPID 4
+#define USER 8
+#define PROG 16
+#define ARGS 32
+#define VSZ 64
+#define RSS 128
+#define PCPU 256
+#define ELAPSED 512
+#define EREG_ARGS 1024
#define EXCLUDE_PROGS 2048
-#define KTHREAD_PARENT "kthreadd" /* the parent process of kernel threads:
- ppid of procs are compared to pid of this proc*/
+#define KTHREAD_PARENT \
+ "kthreadd" /* the parent process of kernel threads: \
+ ppid of procs are compared to pid of this proc*/
/* Different metrics */
char *metric_name;
@@ -109,8 +110,7 @@ static char tmp[MAX_INPUT_BUFFER];
static int kthread_filter = 0;
static int usepid = 0; /* whether to test for pid or /proc/pid/exe */
-static int
-stat_exe (const pid_t pid, struct stat *buf) {
+static int stat_exe(const pid_t pid, struct stat *buf) {
char *path;
int ret;
xasprintf(&path, "/proc/%d/exe", pid);
@@ -119,10 +119,7 @@ stat_exe (const pid_t pid, struct stat *buf) {
return ret;
}
-
-int
-main (int argc, char **argv)
-{
+int main(int argc, char **argv) {
char *input_buffer;
char *input_line;
char *procprog;
@@ -141,16 +138,16 @@ main (int argc, char **argv)
int procseconds = 0;
float procpcpu = 0;
char procstat[8];
- char procetime[MAX_INPUT_BUFFER] = { '\0' };
+ char procetime[MAX_INPUT_BUFFER] = {'\0'};
char *procargs;
const char *zombie = "Z";
int resultsum = 0; /* bitmask of the filter criteria met by a process */
- int found = 0; /* counter for number of lines returned in `ps` output */
- int procs = 0; /* counter for number of processes meeting filter criteria */
- int pos; /* number of spaces before 'args' in `ps` output */
- int cols; /* number of columns in ps output */
+ int found = 0; /* counter for number of lines returned in `ps` output */
+ int procs = 0; /* counter for number of processes meeting filter criteria */
+ int pos; /* number of spaces before 'args' in `ps` output */
+ int cols; /* number of columns in ps output */
int expected_cols = PS_COLS - 1;
int warn = 0; /* number of processes in warn state */
int crit = 0; /* number of processes in crit state */
@@ -159,22 +156,23 @@ main (int argc, char **argv)
int ret = 0;
output chld_out, chld_err;
- setlocale (LC_ALL, "");
- bindtextdomain (PACKAGE, LOCALEDIR);
- textdomain (PACKAGE);
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
setlocale(LC_NUMERIC, "POSIX");
- input_buffer = malloc (MAX_INPUT_BUFFER);
- procprog = malloc (MAX_INPUT_BUFFER);
+ input_buffer = malloc(MAX_INPUT_BUFFER);
+ procprog = malloc(MAX_INPUT_BUFFER);
- xasprintf (&metric_name, "PROCS");
+ xasprintf(&metric_name, "PROCS");
metric = METRIC_PROCS;
/* 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"));
+ }
/* find ourself */
mypid = getpid();
@@ -189,44 +187,46 @@ main (int argc, char **argv)
}
/* Set signal handling and alarm timeout */
- if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
- die (STATE_UNKNOWN, _("Cannot catch SIGALRM"));
+ if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
+ die(STATE_UNKNOWN, _("Cannot catch SIGALRM"));
}
- (void) alarm ((unsigned) timeout_interval);
+ (void)alarm((unsigned)timeout_interval);
- if (verbose >= 2)
- printf (_("CMD: %s\n"), PS_COMMAND);
+ if (verbose >= 2) {
+ printf(_("CMD: %s\n"), PS_COMMAND);
+ }
if (input_filename == NULL) {
- result = cmd_run( PS_COMMAND, &chld_out, &chld_err, 0);
+ result = cmd_run(PS_COMMAND, &chld_out, &chld_err, 0);
if (chld_err.lines > 0) {
- printf ("%s: %s", _("System call sent warnings to stderr"), chld_err.line[0]);
+ printf("%s: %s", _("System call sent warnings to stderr"), chld_err.line[0]);
exit(STATE_WARNING);
}
} else {
- result = cmd_file_read( input_filename, &chld_out, 0);
+ result = cmd_file_read(input_filename, &chld_out, 0);
}
/* flush first line: j starts at 1 */
for (size_t j = 1; j < chld_out.lines; j++) {
input_line = chld_out.line[j];
- if (verbose >= 3)
- printf ("%s", input_line);
+ if (verbose >= 3) {
+ printf("%s", input_line);
+ }
- strcpy (procprog, "");
- xasprintf (&procargs, "%s", "");
+ strcpy(procprog, "");
+ xasprintf(&procargs, "%s", "");
- cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
+ cols = sscanf(input_line, PS_FORMAT, PS_VARLIST);
/* Zombie processes do not give a procprog command */
- if ( cols < expected_cols && strstr(procstat, zombie) ) {
+ if (cols < expected_cols && strstr(procstat, zombie)) {
cols = expected_cols;
}
- if ( cols >= expected_cols ) {
+ if (cols >= expected_cols) {
resultsum = 0;
- xasprintf (&procargs, "%s", input_line + pos);
- strip (procargs);
+ xasprintf(&procargs, "%s", input_line + pos);
+ strip(procargs);
/* Some ps return full pathname for command. This removes path */
strcpy(procprog, base_name(procprog));
@@ -234,52 +234,53 @@ main (int argc, char **argv)
/* we need to convert the elapsed time to seconds */
procseconds = convert_to_seconds(procetime);
- if (verbose >= 3)
- printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
- procs, procuid, procvsz, procrss,
- procpid, procppid, procpcpu, procstat,
- procetime, procprog, procargs);
+ if (verbose >= 3) {
+ printf("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", procs, procuid, procvsz,
+ procrss, procpid, procppid, procpcpu, procstat, procetime, procprog, procargs);
+ }
/* Ignore self */
if ((usepid && mypid == procpid) ||
- ( ((!usepid) && ((ret = stat_exe(procpid, &statbuf) != -1) && statbuf.st_dev == mydev && statbuf.st_ino == myino)) ||
- (ret == -1 && errno == ENOENT))
- ) {
- if (verbose >= 3)
- printf("not considering - is myself or gone\n");
+ (((!usepid) && ((ret = stat_exe(procpid, &statbuf) != -1) && statbuf.st_dev == mydev && statbuf.st_ino == myino)) ||
+ (ret == -1 && errno == ENOENT))) {
+ if (verbose >= 3) {
+ printf("not considering - is myself or gone\n");
+ }
continue;
}
/* Ignore parent*/
else if (myppid == procpid) {
- if (verbose >= 3)
- printf("not considering - is parent\n");
+ if (verbose >= 3) {
+ printf("not considering - is parent\n");
+ }
continue;
}
/* Ignore our own children */
if (procppid == mypid) {
- if (verbose >= 3)
- printf("not considering - is our child\n");
+ if (verbose >= 3) {
+ printf("not considering - is our child\n");
+ }
continue;
}
/* Ignore excluded processes by name */
- if(options & EXCLUDE_PROGS) {
- int found = 0;
- int i = 0;
-
- for(i=0; i < (exclude_progs_counter); i++) {
- if(!strcmp(procprog, exclude_progs_arr[i])) {
- found = 1;
- }
- }
- if(found == 0) {
- resultsum |= EXCLUDE_PROGS;
- } else
- {
- if(verbose >= 3)
- printf("excluding - by ignorelist\n");
- }
+ if (options & EXCLUDE_PROGS) {
+ int found = 0;
+ int i = 0;
+
+ for (i = 0; i < (exclude_progs_counter); i++) {
+ if (!strcmp(procprog, exclude_progs_arr[i])) {
+ found = 1;
+ }
+ }
+ if (found == 0) {
+ resultsum |= EXCLUDE_PROGS;
+ } else {
+ if (verbose >= 3) {
+ printf("excluding - by ignorelist\n");
+ }
+ }
}
/* filter kernel threads (children of KTHREAD_PARENT)*/
@@ -287,69 +288,81 @@ main (int argc, char **argv)
sorry for not doing that, but I've no other OSes to test :-( */
if (kthread_filter == 1) {
/* get pid KTHREAD_PARENT */
- if (kthread_ppid == 0 && !strcmp(procprog, KTHREAD_PARENT) )
+ if (kthread_ppid == 0 && !strcmp(procprog, KTHREAD_PARENT)) {
kthread_ppid = procpid;
+ }
if (kthread_ppid == procppid) {
- if (verbose >= 2)
- printf ("Ignore kernel thread: pid=%d ppid=%d prog=%s args=%s\n", procpid, procppid, procprog, procargs);
+ if (verbose >= 2) {
+ printf("Ignore kernel thread: pid=%d ppid=%d prog=%s args=%s\n", procpid, procppid, procprog, procargs);
+ }
continue;
}
}
- if ((options & STAT) && (strstr (procstat, statopts)))
+ if ((options & STAT) && (strstr(procstat, statopts))) {
resultsum |= STAT;
- if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
+ }
+ if ((options & ARGS) && procargs && (strstr(procargs, args) != NULL)) {
resultsum |= ARGS;
- if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t) 0, NULL, 0) == 0))
+ }
+ if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t)0, NULL, 0) == 0)) {
resultsum |= EREG_ARGS;
- if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
+ }
+ if ((options & PROG) && procprog && (strcmp(prog, procprog) == 0)) {
resultsum |= PROG;
- if ((options & PPID) && (procppid == ppid))
+ }
+ if ((options & PPID) && (procppid == ppid)) {
resultsum |= PPID;
- if ((options & USER) && (procuid == uid))
+ }
+ if ((options & USER) && (procuid == uid)) {
resultsum |= USER;
- if ((options & VSZ) && (procvsz >= vsz))
+ }
+ if ((options & VSZ) && (procvsz >= vsz)) {
resultsum |= VSZ;
- if ((options & RSS) && (procrss >= rss))
+ }
+ if ((options & RSS) && (procrss >= rss)) {
resultsum |= RSS;
- if ((options & PCPU) && (procpcpu >= pcpu))
+ }
+ if ((options & PCPU) && (procpcpu >= pcpu)) {
resultsum |= PCPU;
+ }
found++;
/* Next line if filters not matched */
- if (!(options == resultsum || options == ALL))
+ if (!(options == resultsum || options == ALL)) {
continue;
+ }
procs++;
if (verbose >= 2) {
- printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
- procuid, procvsz, procrss,
- procpid, procppid, procpcpu, procstat,
- procetime, procprog, procargs);
+ printf("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", procuid, procvsz,
+ procrss, procpid, procppid, procpcpu, procstat, procetime, procprog, procargs);
}
- if (metric == METRIC_VSZ)
- i = get_status ((double)procvsz, procs_thresholds);
- else if (metric == METRIC_RSS)
- i = get_status ((double)procrss, procs_thresholds);
+ if (metric == METRIC_VSZ) {
+ i = get_status((double)procvsz, procs_thresholds);
+ } else if (metric == METRIC_RSS) {
+ i = get_status((double)procrss, procs_thresholds);
+ }
/* TODO? float thresholds for --metric=CPU */
- else if (metric == METRIC_CPU)
- i = get_status (procpcpu, procs_thresholds);
- else if (metric == METRIC_ELAPSED)
- i = get_status ((double)procseconds, procs_thresholds);
+ else if (metric == METRIC_CPU) {
+ i = get_status(procpcpu, procs_thresholds);
+ } else if (metric == METRIC_ELAPSED) {
+ i = get_status((double)procseconds, procs_thresholds);
+ }
if (metric != METRIC_PROCS) {
if (i == STATE_WARNING) {
warn++;
- xasprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
- result = max_state (result, i);
+ xasprintf(&fails, "%s%s%s", fails, (strcmp(fails, "") ? ", " : ""), procprog);
+ result = max_state(result, i);
}
if (i == STATE_CRITICAL) {
crit++;
- xasprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
- result = max_state (result, i);
+ xasprintf(&fails, "%s%s%s", fails, (strcmp(fails, "") ? ", " : ""), procprog);
+ result = max_state(result, i);
}
}
}
@@ -359,58 +372,55 @@ main (int argc, char **argv)
}
}
- if (found == 0) { /* no process lines parsed so return STATE_UNKNOWN */
- printf (_("Unable to read output\n"));
+ if (found == 0) { /* no process lines parsed so return STATE_UNKNOWN */
+ printf(_("Unable to read output\n"));
return STATE_UNKNOWN;
}
- if ( result == STATE_UNKNOWN )
+ if (result == STATE_UNKNOWN) {
result = STATE_OK;
+ }
/* Needed if procs found, but none match filter */
- if ( metric == METRIC_PROCS ) {
- result = max_state (result, get_status ((double)procs, procs_thresholds) );
+ if (metric == METRIC_PROCS) {
+ result = max_state(result, get_status((double)procs, procs_thresholds));
}
- if ( result == STATE_OK ) {
- printf ("%s %s: ", metric_name, _("OK"));
+ if (result == STATE_OK) {
+ printf("%s %s: ", metric_name, _("OK"));
} else if (result == STATE_WARNING) {
- printf ("%s %s: ", metric_name, _("WARNING"));
- if ( metric != METRIC_PROCS ) {
- printf (_("%d warn out of "), warn);
+ printf("%s %s: ", metric_name, _("WARNING"));
+ if (metric != METRIC_PROCS) {
+ printf(_("%d warn out of "), warn);
}
} else if (result == STATE_CRITICAL) {
- printf ("%s %s: ", metric_name, _("CRITICAL"));
+ printf("%s %s: ", metric_name, _("CRITICAL"));
if (metric != METRIC_PROCS) {
- printf (_("%d crit, %d warn out of "), crit, warn);
+ printf(_("%d crit, %d warn out of "), crit, warn);
}
}
- printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs);
+ printf(ngettext("%d process", "%d processes", (unsigned long)procs), procs);
- if (strcmp(fmt,"") != 0) {
- printf (_(" with %s"), fmt);
+ if (strcmp(fmt, "") != 0) {
+ printf(_(" with %s"), fmt);
}
- if ( verbose >= 1 && strcmp(fails,"") )
- printf (" [%s]", fails);
+ if (verbose >= 1 && strcmp(fails, "")) {
+ printf(" [%s]", fails);
+ }
- if (metric == METRIC_PROCS)
- printf (" | procs=%d;%s;%s;0;", procs,
- warning_range ? warning_range : "",
- critical_range ? critical_range : "");
- else
- printf (" | procs=%d;;;0; procs_warn=%d;;;0; procs_crit=%d;;;0;", procs, warn, crit);
+ if (metric == METRIC_PROCS) {
+ printf(" | procs=%d;%s;%s;0;", procs, warning_range ? warning_range : "", critical_range ? critical_range : "");
+ } else {
+ printf(" | procs=%d;;;0; procs_warn=%d;;;0; procs_crit=%d;;;0;", procs, warn, crit);
+ }
- printf ("\n");
+ printf("\n");
return result;
}
-
-
/* process command-line arguments */
-int
-process_arguments (int argc, char **argv)
-{
+int process_arguments(int argc, char **argv) {
int c = 1;
char *user;
struct passwd *pw;
@@ -419,260 +429,262 @@ process_arguments (int argc, char **argv)
int cflags = REG_NOSUB | REG_EXTENDED;
char errbuf[MAX_INPUT_BUFFER];
char *temp_string;
- int i=0;
- static struct option longopts[] = {
- {"warning", required_argument, 0, 'w'},
- {"critical", required_argument, 0, 'c'},
- {"metric", required_argument, 0, 'm'},
- {"timeout", required_argument, 0, 't'},
- {"status", required_argument, 0, 's'},
- {"ppid", required_argument, 0, 'p'},
- {"user", required_argument, 0, 'u'},
- {"command", required_argument, 0, 'C'},
- {"vsz", required_argument, 0, 'z'},
- {"rss", required_argument, 0, 'r'},
- {"pcpu", required_argument, 0, 'P'},
- {"elapsed", required_argument, 0, 'e'},
- {"argument-array", required_argument, 0, 'a'},
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
- {"verbose", no_argument, 0, 'v'},
- {"ereg-argument-array", required_argument, 0, CHAR_MAX+1},
- {"input-file", required_argument, 0, CHAR_MAX+2},
- {"no-kthreads", required_argument, 0, 'k'},
- {"traditional-filter", no_argument, 0, 'T'},
- {"exclude-process", required_argument, 0, 'X'},
- {0, 0, 0, 0}
- };
-
- for (c = 1; c < argc; c++)
- if (strcmp ("-to", argv[c]) == 0)
- strcpy (argv[c], "-t");
+ int i = 0;
+ static struct option longopts[] = {{"warning", required_argument, 0, 'w'},
+ {"critical", required_argument, 0, 'c'},
+ {"metric", required_argument, 0, 'm'},
+ {"timeout", required_argument, 0, 't'},
+ {"status", required_argument, 0, 's'},
+ {"ppid", required_argument, 0, 'p'},
+ {"user", required_argument, 0, 'u'},
+ {"command", required_argument, 0, 'C'},
+ {"vsz", required_argument, 0, 'z'},
+ {"rss", required_argument, 0, 'r'},
+ {"pcpu", required_argument, 0, 'P'},
+ {"elapsed", required_argument, 0, 'e'},
+ {"argument-array", required_argument, 0, 'a'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
+ {"verbose", no_argument, 0, 'v'},
+ {"ereg-argument-array", required_argument, 0, CHAR_MAX + 1},
+ {"input-file", required_argument, 0, CHAR_MAX + 2},
+ {"no-kthreads", required_argument, 0, 'k'},
+ {"traditional-filter", no_argument, 0, 'T'},
+ {"exclude-process", required_argument, 0, 'X'},
+ {0, 0, 0, 0}};
+
+ for (c = 1; c < argc; c++) {
+ if (strcmp("-to", argv[c]) == 0) {
+ strcpy(argv[c], "-t");
+ }
+ }
while (1) {
- c = getopt_long (argc, argv, "Vvhkt:c:w:p:s:u:C:a:z:r:m:P:T:X:",
- longopts, &option);
+ c = getopt_long(argc, argv, "Vvhkt:c:w:p:s:u:C:a:z:r:m:P:T:X:", longopts, &option);
- if (c == -1 || c == EOF)
+ if (c == -1 || c == EOF) {
break;
+ }
switch (c) {
- case '?': /* help */
- usage5 ();
- case 'h': /* help */
- print_help ();
- exit (STATE_UNKNOWN);
- case 'V': /* version */
- print_revision (progname, NP_VERSION);
- exit (STATE_UNKNOWN);
- case 't': /* timeout period */
- if (!is_integer (optarg))
- usage2 (_("Timeout interval must be a positive integer"), optarg);
- else
- timeout_interval = atoi (optarg);
+ case '?': /* help */
+ usage5();
+ case 'h': /* help */
+ print_help();
+ exit(STATE_UNKNOWN);
+ case 'V': /* version */
+ print_revision(progname, NP_VERSION);
+ exit(STATE_UNKNOWN);
+ case 't': /* timeout period */
+ if (!is_integer(optarg)) {
+ usage2(_("Timeout interval must be a positive integer"), optarg);
+ } else {
+ timeout_interval = atoi(optarg);
+ }
break;
- case 'c': /* critical threshold */
+ case 'c': /* critical threshold */
critical_range = optarg;
break;
- case 'w': /* warning threshold */
+ case 'w': /* warning threshold */
warning_range = optarg;
break;
- case 'p': /* process id */
- if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
- xasprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid);
+ case 'p': /* process id */
+ if (sscanf(optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
+ xasprintf(&fmt, "%s%sPPID = %d", (fmt ? fmt : ""), (options ? ", " : ""), ppid);
options |= PPID;
break;
}
- usage4 (_("Parent Process ID must be an integer!"));
- case 's': /* status */
- if (statopts)
+ usage4(_("Parent Process ID must be an integer!"));
+ case 's': /* status */
+ if (statopts) {
break;
- else
+ } else {
statopts = optarg;
- xasprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
+ }
+ xasprintf(&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
options |= STAT;
break;
- case 'u': /* user or user id */
- if (is_integer (optarg)) {
- uid = atoi (optarg);
- pw = getpwuid ((uid_t) uid);
+ case 'u': /* user or user id */
+ if (is_integer(optarg)) {
+ uid = atoi(optarg);
+ pw = getpwuid((uid_t)uid);
/* check to be sure user exists */
- if (pw == NULL)
- usage2 (_("UID was not found"), optarg);
- }
- else {
- pw = getpwnam (optarg);
+ if (pw == NULL) {
+ usage2(_("UID was not found"), optarg);
+ }
+ } else {
+ pw = getpwnam(optarg);
/* check to be sure user exists */
- if (pw == NULL)
- usage2 (_("User name was not found"), optarg);
+ if (pw == NULL) {
+ usage2(_("User name was not found"), optarg);
+ }
/* then get uid */
uid = pw->pw_uid;
}
user = pw->pw_name;
- xasprintf (&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""),
- uid, user);
+ xasprintf(&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""), uid, user);
options |= USER;
break;
- case 'C': /* command */
+ case 'C': /* command */
/* TODO: allow this to be passed in with --metric */
- if (prog)
+ if (prog) {
break;
- else
+ } else {
prog = optarg;
- xasprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
- prog);
+ }
+ xasprintf(&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""), prog);
options |= PROG;
break;
case 'X':
- if(exclude_progs)
- break;
- else
- exclude_progs = optarg;
- xasprintf (&fmt, _("%s%sexclude progs '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
- exclude_progs);
+ if (exclude_progs) {
+ break;
+ } else {
+ exclude_progs = optarg;
+ }
+ xasprintf(&fmt, _("%s%sexclude progs '%s'"), (fmt ? fmt : ""), (options ? ", " : ""), exclude_progs);
char *p = strtok(exclude_progs, ",");
- while(p){
- exclude_progs_arr = realloc(exclude_progs_arr, sizeof(char*) * ++exclude_progs_counter);
- exclude_progs_arr[exclude_progs_counter-1] = p;
- p = strtok(NULL, ",");
+ while (p) {
+ exclude_progs_arr = realloc(exclude_progs_arr, sizeof(char *) * ++exclude_progs_counter);
+ exclude_progs_arr[exclude_progs_counter - 1] = p;
+ p = strtok(NULL, ",");
}
options |= EXCLUDE_PROGS;
break;
- case 'a': /* args (full path name with args) */
+ case 'a': /* args (full path name with args) */
/* TODO: allow this to be passed in with --metric */
- if (args)
+ if (args) {
break;
- else
+ } else {
args = optarg;
- xasprintf (&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
+ }
+ xasprintf(&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
options |= ARGS;
break;
- case CHAR_MAX+1:
+ case CHAR_MAX + 1:
err = regcomp(&re_args, optarg, cflags);
if (err != 0) {
- regerror (err, &re_args, errbuf, MAX_INPUT_BUFFER);
- die (STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
+ regerror(err, &re_args, errbuf, MAX_INPUT_BUFFER);
+ die(STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
}
/* Strip off any | within the regex optarg */
temp_string = strdup(optarg);
- while(temp_string[i]!='\0'){
- if(temp_string[i]=='|')
- temp_string[i]=',';
+ while (temp_string[i] != '\0') {
+ if (temp_string[i] == '|') {
+ temp_string[i] = ',';
+ }
i++;
}
- xasprintf (&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), temp_string);
+ xasprintf(&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), temp_string);
options |= EREG_ARGS;
break;
- case 'r': /* RSS */
- if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
- xasprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
+ case 'r': /* RSS */
+ if (sscanf(optarg, "%d%[^0-9]", &rss, tmp) == 1) {
+ xasprintf(&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
options |= RSS;
break;
}
- usage4 (_("RSS must be an integer!"));
- case 'z': /* VSZ */
- if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
- xasprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
+ usage4(_("RSS must be an integer!"));
+ case 'z': /* VSZ */
+ if (sscanf(optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
+ xasprintf(&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
options |= VSZ;
break;
}
- usage4 (_("VSZ must be an integer!"));
- case 'P': /* PCPU */
+ usage4(_("VSZ must be an integer!"));
+ case 'P': /* PCPU */
/* TODO: -P 1.5.5 is accepted */
- if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
- xasprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
+ if (sscanf(optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
+ xasprintf(&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
options |= PCPU;
break;
}
- usage4 (_("PCPU must be a float!"));
+ usage4(_("PCPU must be a float!"));
case 'm':
- xasprintf (&metric_name, "%s", optarg);
- if ( strcmp(optarg, "PROCS") == 0) {
+ xasprintf(&metric_name, "%s", optarg);
+ if (strcmp(optarg, "PROCS") == 0) {
metric = METRIC_PROCS;
break;
- }
- else if ( strcmp(optarg, "VSZ") == 0) {
+ } else if (strcmp(optarg, "VSZ") == 0) {
metric = METRIC_VSZ;
break;
- }
- else if ( strcmp(optarg, "RSS") == 0 ) {
+ } else if (strcmp(optarg, "RSS") == 0) {
metric = METRIC_RSS;
break;
- }
- else if ( strcmp(optarg, "CPU") == 0 ) {
+ } else if (strcmp(optarg, "CPU") == 0) {
metric = METRIC_CPU;
break;
- }
- else if ( strcmp(optarg, "ELAPSED") == 0) {
+ } else if (strcmp(optarg, "ELAPSED") == 0) {
metric = METRIC_ELAPSED;
break;
}
- usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
- case 'k': /* linux kernel thread filter */
+ usage4(_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
+ case 'k': /* linux kernel thread filter */
kthread_filter = 1;
break;
- case 'v': /* command */
+ case 'v': /* command */
verbose++;
break;
case 'T':
usepid = 1;
break;
- case CHAR_MAX+2:
+ case CHAR_MAX + 2:
input_filename = optarg;
break;
}
}
c = optind;
- if ((! warning_range) && argv[c])
+ if ((!warning_range) && argv[c]) {
warning_range = argv[c++];
- if ((! critical_range) && argv[c])
+ }
+ if ((!critical_range) && argv[c]) {
critical_range = argv[c++];
+ }
if (statopts == NULL && argv[c]) {
- xasprintf (&statopts, "%s", argv[c++]);
- xasprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
+ xasprintf(&statopts, "%s", argv[c++]);
+ xasprintf(&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
options |= STAT;
}
/* this will abort in case of invalid ranges */
- set_thresholds (&procs_thresholds, warning_range, critical_range);
+ set_thresholds(&procs_thresholds, warning_range, critical_range);
- return validate_arguments ();
+ return validate_arguments();
}
-
-
-int
-validate_arguments ()
-{
- if (options == 0)
+int validate_arguments() {
+ if (options == 0) {
options = ALL;
+ }
- if (statopts==NULL)
+ if (statopts == NULL) {
statopts = strdup("");
+ }
- if (prog==NULL)
+ if (prog == NULL) {
prog = strdup("");
+ }
- if (args==NULL)
+ if (args == NULL) {
args = strdup("");
+ }
- if (fmt==NULL)
+ if (fmt == NULL) {
fmt = strdup("");
+ }
- if (fails==NULL)
+ if (fails == NULL) {
fails = strdup("");
+ }
return options;
}
-
/* convert the elapsed time to seconds */
-int
-convert_to_seconds(char *etime) {
+int convert_to_seconds(char *etime) {
char *ptr;
int total;
@@ -704,8 +716,7 @@ convert_to_seconds(char *etime) {
}
if (hyphcnt > 0) {
- sscanf(etime, "%d-%d:%d:%d",
- &days, &hours, &minutes, &seconds);
+ sscanf(etime, "%d-%d:%d:%d", &days, &hours, &minutes, &seconds);
/* linux 2.6.5/2.6.6 reporting some processes with infinite
* elapsed times for some reason */
if (days == 49710) {
@@ -713,135 +724,125 @@ convert_to_seconds(char *etime) {
}
} else {
if (coloncnt == 2) {
- sscanf(etime, "%d:%d:%d",
- &hours, &minutes, &seconds);
+ sscanf(etime, "%d:%d:%d", &hours, &minutes, &seconds);
} else if (coloncnt == 1) {
- sscanf(etime, "%d:%d",
- &minutes, &seconds);
+ sscanf(etime, "%d:%d", &minutes, &seconds);
}
}
- total = (days * 86400) +
- (hours * 3600) +
- (minutes * 60) +
- seconds;
+ total = (days * 86400) + (hours * 3600) + (minutes * 60) + seconds;
if (verbose >= 3 && metric == METRIC_ELAPSED) {
- printf("seconds: %d\n", total);
+ printf("seconds: %d\n", total);
}
return total;
}
+void print_help(void) {
+ print_revision(progname, NP_VERSION);
-void
-print_help (void)
-{
- print_revision (progname, NP_VERSION);
-
- printf ("Copyright (c) 1999 Ethan Galstad \n");
- printf (COPYRIGHT, copyright, email);
+ printf("Copyright (c) 1999 Ethan Galstad \n");
+ printf(COPYRIGHT, copyright, email);
- printf ("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified"));
- printf ("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number"));
- printf ("%s\n", _("of processes. Search filters can be applied to limit the processes to check."));
+ printf("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified"));
+ printf("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number"));
+ printf("%s\n", _("of processes. Search filters can be applied to limit the processes to check."));
- printf ("\n\n");
+ printf("\n\n");
- printf ("%s\n", _("The parent process, check_procs itself and any child process of check_procs (ps)"));
- printf ("%s\n", _("are excluded from any checks to prevent false positives."));
+ printf("%s\n", _("The parent process, check_procs itself and any child process of check_procs (ps)"));
+ printf("%s\n", _("are excluded from any checks to prevent false positives."));
- printf ("\n\n");
+ printf("\n\n");
- print_usage ();
+ print_usage();
- printf (UT_HELP_VRSN);
- printf (UT_EXTRA_OPTS);
- printf (" %s\n", "-w, --warning=RANGE");
- printf (" %s\n", _("Generate warning state if metric is outside this range"));
- printf (" %s\n", "-c, --critical=RANGE");
- printf (" %s\n", _("Generate critical state if metric is outside this range"));
- printf (" %s\n", "-m, --metric=TYPE");
- printf (" %s\n", _("Check thresholds against metric. Valid types:"));
- printf (" %s\n", _("PROCS - number of processes (default)"));
- printf (" %s\n", _("VSZ - virtual memory size"));
- printf (" %s\n", _("RSS - resident set memory size"));
- printf (" %s\n", _("CPU - percentage CPU"));
+ printf(UT_HELP_VRSN);
+ printf(UT_EXTRA_OPTS);
+ printf(" %s\n", "-w, --warning=RANGE");
+ printf(" %s\n", _("Generate warning state if metric is outside this range"));
+ printf(" %s\n", "-c, --critical=RANGE");
+ printf(" %s\n", _("Generate critical state if metric is outside this range"));
+ printf(" %s\n", "-m, --metric=TYPE");
+ printf(" %s\n", _("Check thresholds against metric. Valid types:"));
+ printf(" %s\n", _("PROCS - number of processes (default)"));
+ printf(" %s\n", _("VSZ - virtual memory size"));
+ printf(" %s\n", _("RSS - resident set memory size"));
+ printf(" %s\n", _("CPU - percentage CPU"));
/* only linux etime is support currently */
-#if defined( __linux__ )
- printf (" %s\n", _("ELAPSED - time elapsed in seconds"));
+#if defined(__linux__)
+ printf(" %s\n", _("ELAPSED - time elapsed in seconds"));
#endif /* defined(__linux__) */
- printf (UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
-
- printf (" %s\n", "-v, --verbose");
- printf (" %s\n", _("Extra information. Up to 3 verbosity levels"));
-
- printf (" %s\n", "-T, --traditional");
- printf (" %s\n", _("Filter own process the traditional way by PID instead of /proc/pid/exe"));
-
- printf ("\n");
- printf ("%s\n", "Filters:");
- printf (" %s\n", "-s, --state=STATUSFLAGS");
- printf (" %s\n", _("Only scan for processes that have, in the output of `ps`, one or"));
- printf (" %s\n", _("more of the status flags you specify (for example R, Z, S, RS,"));
- printf (" %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
- printf (" %s\n", "-p, --ppid=PPID");
- printf (" %s\n", _("Only scan for children of the parent process ID indicated."));
- printf (" %s\n", "-z, --vsz=VSZ");
- printf (" %s\n", _("Only scan for processes with VSZ higher than indicated."));
- printf (" %s\n", "-r, --rss=RSS");
- printf (" %s\n", _("Only scan for processes with RSS higher than indicated."));
- printf (" %s\n", "-P, --pcpu=PCPU");
- printf (" %s\n", _("Only scan for processes with PCPU higher than indicated."));
- printf (" %s\n", "-u, --user=USER");
- printf (" %s\n", _("Only scan for processes with user name or ID indicated."));
- printf (" %s\n", "-a, --argument-array=STRING");
- printf (" %s\n", _("Only scan for processes with args that contain STRING."));
- printf (" %s\n", "--ereg-argument-array=STRING");
- printf (" %s\n", _("Only scan for processes with args that contain the regex STRING."));
- printf (" %s\n", "-C, --command=COMMAND");
- printf (" %s\n", _("Only scan for exact matches of COMMAND (without path)."));
- printf (" %s\n", "-X, --exclude-process");
- printf (" %s\n", _("Exclude processes which match this comma separated list"));
- printf (" %s\n", "-k, --no-kthreads");
- printf (" %s\n", _("Only scan for non kernel threads (works on Linux only)."));
-
- printf(_("\n\
+ printf(UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
+
+ printf(" %s\n", "-v, --verbose");
+ printf(" %s\n", _("Extra information. Up to 3 verbosity levels"));
+
+ printf(" %s\n", "-T, --traditional");
+ printf(" %s\n", _("Filter own process the traditional way by PID instead of /proc/pid/exe"));
+
+ printf("\n");
+ printf("%s\n", "Filters:");
+ printf(" %s\n", "-s, --state=STATUSFLAGS");
+ printf(" %s\n", _("Only scan for processes that have, in the output of `ps`, one or"));
+ printf(" %s\n", _("more of the status flags you specify (for example R, Z, S, RS,"));
+ printf(" %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
+ printf(" %s\n", "-p, --ppid=PPID");
+ printf(" %s\n", _("Only scan for children of the parent process ID indicated."));
+ printf(" %s\n", "-z, --vsz=VSZ");
+ printf(" %s\n", _("Only scan for processes with VSZ higher than indicated."));
+ printf(" %s\n", "-r, --rss=RSS");
+ printf(" %s\n", _("Only scan for processes with RSS higher than indicated."));
+ printf(" %s\n", "-P, --pcpu=PCPU");
+ printf(" %s\n", _("Only scan for processes with PCPU higher than indicated."));
+ printf(" %s\n", "-u, --user=USER");
+ printf(" %s\n", _("Only scan for processes with user name or ID indicated."));
+ printf(" %s\n", "-a, --argument-array=STRING");
+ printf(" %s\n", _("Only scan for processes with args that contain STRING."));
+ printf(" %s\n", "--ereg-argument-array=STRING");
+ printf(" %s\n", _("Only scan for processes with args that contain the regex STRING."));
+ printf(" %s\n", "-C, --command=COMMAND");
+ printf(" %s\n", _("Only scan for exact matches of COMMAND (without path)."));
+ printf(" %s\n", "-X, --exclude-process");
+ printf(" %s\n", _("Exclude processes which match this comma separated list"));
+ printf(" %s\n", "-k, --no-kthreads");
+ printf(" %s\n", _("Only scan for non kernel threads (works on Linux only)."));
+
+ printf(_("\n\
RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
specified 'max:min', a warning status will be generated if the\n\
count is inside the specified range\n\n"));
- printf(_("\
+ printf(_("\
This plugin checks the number of currently running processes and\n\
generates WARNING or CRITICAL states if the process count is outside\n\
the specified threshold ranges. The process count can be filtered by\n\
process owner, parent process PID, current state (e.g., 'Z'), or may\n\
be the total number of running processes\n\n"));
- printf ("%s\n", _("Examples:"));
- printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
- printf (" %s\n", _("Warning if not two processes with command name portsentry."));
- printf (" %s\n\n", _("Critical if < 2 or > 1024 processes"));
- printf (" %s\n", "check_procs -c 1: -C sshd");
- printf (" %s\n", _("Critical if not at least 1 process with command sshd"));
- printf (" %s\n", "check_procs -w 1024 -c 1: -C sshd");
- printf (" %s\n", _("Warning if > 1024 processes with command name sshd."));
- printf (" %s\n\n", _("Critical if < 1 processes with command name sshd."));
- printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
- printf (" %s\n", _("Warning alert if > 10 processes with command arguments containing"));
- printf (" %s\n\n", _("'/usr/local/bin/perl' and owned by root"));
- printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
- printf (" %s\n\n", _("Alert if VSZ of any processes over 50K or 100K"));
- printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
- printf (" %s\n", _("Alert if CPU of any processes over 10%% or 20%%"));
-
- printf (UT_SUPPORT);
+ printf("%s\n", _("Examples:"));
+ printf(" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
+ printf(" %s\n", _("Warning if not two processes with command name portsentry."));
+ printf(" %s\n\n", _("Critical if < 2 or > 1024 processes"));
+ printf(" %s\n", "check_procs -c 1: -C sshd");
+ printf(" %s\n", _("Critical if not at least 1 process with command sshd"));
+ printf(" %s\n", "check_procs -w 1024 -c 1: -C sshd");
+ printf(" %s\n", _("Warning if > 1024 processes with command name sshd."));
+ printf(" %s\n\n", _("Critical if < 1 processes with command name sshd."));
+ printf(" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
+ printf(" %s\n", _("Warning alert if > 10 processes with command arguments containing"));
+ printf(" %s\n\n", _("'/usr/local/bin/perl' and owned by root"));
+ printf(" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
+ printf(" %s\n\n", _("Alert if VSZ of any processes over 50K or 100K"));
+ printf(" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
+ printf(" %s\n", _("Alert if CPU of any processes over 10%% or 20%%"));
+
+ printf(UT_SUPPORT);
}
-void
-print_usage (void)
-{
- printf ("%s\n", _("Usage:"));
- printf ("%s -w -c [-m metric] [-s state] [-p ppid]\n", progname);
- printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
- printf (" [-C command] [-X process_to_exclude] [-k] [-t timeout] [-v]\n");
+void print_usage(void) {
+ printf("%s\n", _("Usage:"));
+ printf("%s -w -c [-m metric] [-s state] [-p ppid]\n", progname);
+ printf(" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
+ printf(" [-C command] [-X process_to_exclude] [-k] [-t timeout] [-v]\n");
}
--
cgit v1.2.3-74-g34f1
From 16c3e2499309af654bcf92a4cc516521122e8d66 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Wed, 12 Mar 2025 14:53:54 +0100
Subject: check_procs: general refactoring
---
configure.ac | 2 +-
plugins/check_procs.c | 247 +++++++++++++++++++++++---------------------------
2 files changed, 114 insertions(+), 135 deletions(-)
diff --git a/configure.ac b/configure.ac
index 204fc6e3..c66f9b2f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -796,7 +796,7 @@ elif ps axwo 'stat comm vsz rss user uid pid ppid etime args' 2>/dev/null | \
then
ac_cv_ps_varlist="[procstat,&procuid,&procpid,&procppid,&procvsz,&procrss,&procpcpu,procetime,procprog,&pos]"
ac_cv_ps_command="$PATH_TO_PS axwo 'stat uid pid ppid vsz rss pcpu etime comm args'"
- ac_cv_ps_format="%s %d %d %d %d %d %f %s %s %n"
+ ac_cv_ps_format="%s %u %d %d %d %d %f %s %s %n"
ac_cv_ps_cols=10
AC_MSG_RESULT([$ac_cv_ps_command])
diff --git a/plugins/check_procs.c b/plugins/check_procs.c
index 69b424dc..da2198a7 100644
--- a/plugins/check_procs.c
+++ b/plugins/check_procs.c
@@ -43,6 +43,7 @@ const char *email = "devel@monitoring-plugins.org";
#include "utils.h"
#include "utils_cmd.h"
#include "regex.h"
+#include "states.h"
#include
#include
@@ -91,7 +92,7 @@ enum metric {
enum metric metric = METRIC_PROCS;
static int verbose = 0;
-static int uid;
+static uid_t uid;
static pid_t ppid;
static int vsz;
static int rss;
@@ -107,62 +108,22 @@ static regex_t re_args;
static char *fmt;
static char *fails;
static char tmp[MAX_INPUT_BUFFER];
-static int kthread_filter = 0;
-static int usepid = 0; /* whether to test for pid or /proc/pid/exe */
+static bool kthread_filter = false;
+static bool usepid = false; /* whether to test for pid or /proc/pid/exe */
static int stat_exe(const pid_t pid, struct stat *buf) {
char *path;
- int ret;
xasprintf(&path, "/proc/%d/exe", pid);
- ret = stat(path, buf);
+ int ret = stat(path, buf);
free(path);
return ret;
}
int main(int argc, char **argv) {
- char *input_buffer;
- char *input_line;
- char *procprog;
-
- pid_t mypid = 0;
- pid_t myppid = 0;
- struct stat statbuf;
- dev_t mydev = 0;
- ino_t myino = 0;
- int procuid = 0;
- pid_t procpid = 0;
- pid_t procppid = 0;
- pid_t kthread_ppid = 0;
- int procvsz = 0;
- int procrss = 0;
- int procseconds = 0;
- float procpcpu = 0;
- char procstat[8];
- char procetime[MAX_INPUT_BUFFER] = {'\0'};
- char *procargs;
-
- const char *zombie = "Z";
-
- int resultsum = 0; /* bitmask of the filter criteria met by a process */
- int found = 0; /* counter for number of lines returned in `ps` output */
- int procs = 0; /* counter for number of processes meeting filter criteria */
- int pos; /* number of spaces before 'args' in `ps` output */
- int cols; /* number of columns in ps output */
- int expected_cols = PS_COLS - 1;
- int warn = 0; /* number of processes in warn state */
- int crit = 0; /* number of processes in crit state */
- int i = 0;
- int result = STATE_UNKNOWN;
- int ret = 0;
- output chld_out, chld_err;
-
setlocale(LC_ALL, "");
+ setlocale(LC_NUMERIC, "POSIX");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- setlocale(LC_NUMERIC, "POSIX");
-
- input_buffer = malloc(MAX_INPUT_BUFFER);
- procprog = malloc(MAX_INPUT_BUFFER);
xasprintf(&metric_name, "PROCS");
metric = METRIC_PROCS;
@@ -175,13 +136,16 @@ int main(int argc, char **argv) {
}
/* find ourself */
- mypid = getpid();
- myppid = getppid();
+ pid_t mypid = getpid();
+ pid_t myppid = getppid();
+ dev_t mydev = 0;
+ ino_t myino = 0;
+ struct stat statbuf;
if (usepid || stat_exe(mypid, &statbuf) == -1) {
/* usepid might have been set by -T */
- usepid = 1;
+ usepid = true;
} else {
- usepid = 0;
+ usepid = false;
mydev = statbuf.st_dev;
myino = statbuf.st_ino;
}
@@ -190,12 +154,15 @@ int main(int argc, char **argv) {
if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
die(STATE_UNKNOWN, _("Cannot catch SIGALRM"));
}
- (void)alarm((unsigned)timeout_interval);
+ (void)alarm(timeout_interval);
if (verbose >= 2) {
printf(_("CMD: %s\n"), PS_COMMAND);
}
+ output chld_out;
+ output chld_err;
+ mp_state_enum result = STATE_UNKNOWN;
if (input_filename == NULL) {
result = cmd_run(PS_COMMAND, &chld_out, &chld_err, 0);
if (chld_err.lines > 0) {
@@ -206,20 +173,43 @@ int main(int argc, char **argv) {
result = cmd_file_read(input_filename, &chld_out, 0);
}
+ int pos; /* number of spaces before 'args' in `ps` output */
+ uid_t procuid = 0;
+ pid_t procpid = 0;
+ pid_t procppid = 0;
+ pid_t kthread_ppid = 0;
+ int warn = 0; /* number of processes in warn state */
+ int crit = 0; /* number of processes in crit state */
+ int procvsz = 0;
+ int procrss = 0;
+ int procseconds = 0;
+ float procpcpu = 0;
+ char procstat[8];
+ char procetime[MAX_INPUT_BUFFER] = {'\0'};
+ int resultsum = 0; /* bitmask of the filter criteria met by a process */
+ int found = 0; /* counter for number of lines returned in `ps` output */
+ int procs = 0; /* counter for number of processes meeting filter criteria */
+ char *input_buffer = malloc(MAX_INPUT_BUFFER);
+ char *procprog = malloc(MAX_INPUT_BUFFER);
+ const int expected_cols = PS_COLS - 1;
+
/* flush first line: j starts at 1 */
for (size_t j = 1; j < chld_out.lines; j++) {
- input_line = chld_out.line[j];
+ char *input_line = chld_out.line[j];
if (verbose >= 3) {
printf("%s", input_line);
}
strcpy(procprog, "");
+ char *procargs;
xasprintf(&procargs, "%s", "");
- cols = sscanf(input_line, PS_FORMAT, PS_VARLIST);
+ /* number of columns in ps output */
+ int cols = sscanf(input_line, PS_FORMAT, PS_VARLIST);
/* Zombie processes do not give a procprog command */
+ const char *zombie = "Z";
if (cols < expected_cols && strstr(procstat, zombie)) {
cols = expected_cols;
}
@@ -240,6 +230,7 @@ int main(int argc, char **argv) {
}
/* Ignore self */
+ int ret = 0;
if ((usepid && mypid == procpid) ||
(((!usepid) && ((ret = stat_exe(procpid, &statbuf) != -1) && statbuf.st_dev == mydev && statbuf.st_ino == myino)) ||
(ret == -1 && errno == ENOENT))) {
@@ -249,7 +240,7 @@ int main(int argc, char **argv) {
continue;
}
/* Ignore parent*/
- else if (myppid == procpid) {
+ if (myppid == procpid) {
if (verbose >= 3) {
printf("not considering - is parent\n");
}
@@ -266,15 +257,13 @@ int main(int argc, char **argv) {
/* Ignore excluded processes by name */
if (options & EXCLUDE_PROGS) {
- int found = 0;
- int i = 0;
-
- for (i = 0; i < (exclude_progs_counter); i++) {
+ bool found = false;
+ for (int i = 0; i < (exclude_progs_counter); i++) {
if (!strcmp(procprog, exclude_progs_arr[i])) {
- found = 1;
+ found = true;
}
}
- if (found == 0) {
+ if (!found) {
resultsum |= EXCLUDE_PROGS;
} else {
if (verbose >= 3) {
@@ -286,7 +275,7 @@ int main(int argc, char **argv) {
/* filter kernel threads (children of KTHREAD_PARENT)*/
/* TODO adapt for other OSes than GNU/Linux
sorry for not doing that, but I've no other OSes to test :-( */
- if (kthread_filter == 1) {
+ if (kthread_filter) {
/* get pid KTHREAD_PARENT */
if (kthread_ppid == 0 && !strcmp(procprog, KTHREAD_PARENT)) {
kthread_ppid = procpid;
@@ -341,28 +330,29 @@ int main(int argc, char **argv) {
procrss, procpid, procppid, procpcpu, procstat, procetime, procprog, procargs);
}
+ mp_state_enum temporary_result = STATE_OK;
if (metric == METRIC_VSZ) {
- i = get_status((double)procvsz, procs_thresholds);
+ temporary_result = get_status((double)procvsz, procs_thresholds);
} else if (metric == METRIC_RSS) {
- i = get_status((double)procrss, procs_thresholds);
+ temporary_result = get_status((double)procrss, procs_thresholds);
}
/* TODO? float thresholds for --metric=CPU */
else if (metric == METRIC_CPU) {
- i = get_status(procpcpu, procs_thresholds);
+ temporary_result = get_status(procpcpu, procs_thresholds);
} else if (metric == METRIC_ELAPSED) {
- i = get_status((double)procseconds, procs_thresholds);
+ temporary_result = get_status((double)procseconds, procs_thresholds);
}
if (metric != METRIC_PROCS) {
- if (i == STATE_WARNING) {
+ if (temporary_result == STATE_WARNING) {
warn++;
xasprintf(&fails, "%s%s%s", fails, (strcmp(fails, "") ? ", " : ""), procprog);
- result = max_state(result, i);
+ result = max_state(result, temporary_result);
}
- if (i == STATE_CRITICAL) {
+ if (temporary_result == STATE_CRITICAL) {
crit++;
xasprintf(&fails, "%s%s%s", fails, (strcmp(fails, "") ? ", " : ""), procprog);
- result = max_state(result, i);
+ result = max_state(result, temporary_result);
}
}
}
@@ -416,20 +406,11 @@ int main(int argc, char **argv) {
}
printf("\n");
- return result;
+ exit(result);
}
/* process command-line arguments */
int process_arguments(int argc, char **argv) {
- int c = 1;
- char *user;
- struct passwd *pw;
- int option = 0;
- int err;
- int cflags = REG_NOSUB | REG_EXTENDED;
- char errbuf[MAX_INPUT_BUFFER];
- char *temp_string;
- int i = 0;
static struct option longopts[] = {{"warning", required_argument, 0, 'w'},
{"critical", required_argument, 0, 'c'},
{"metric", required_argument, 0, 'm'},
@@ -453,20 +434,21 @@ int process_arguments(int argc, char **argv) {
{"exclude-process", required_argument, 0, 'X'},
{0, 0, 0, 0}};
- for (c = 1; c < argc; c++) {
- if (strcmp("-to", argv[c]) == 0) {
- strcpy(argv[c], "-t");
+ for (int index = 1; index < argc; index++) {
+ if (strcmp("-to", argv[index]) == 0) {
+ strcpy(argv[index], "-t");
}
}
- while (1) {
- c = getopt_long(argc, argv, "Vvhkt:c:w:p:s:u:C:a:z:r:m:P:T:X:", longopts, &option);
+ while (true) {
+ int option = 0;
+ int option_index = getopt_long(argc, argv, "Vvhkt:c:w:p:s:u:C:a:z:r:m:P:T:X:", longopts, &option);
- if (c == -1 || c == EOF) {
+ if (option_index == -1 || option_index == EOF) {
break;
}
- switch (c) {
+ switch (option_index) {
case '?': /* help */
usage5();
case 'h': /* help */
@@ -504,10 +486,11 @@ int process_arguments(int argc, char **argv) {
xasprintf(&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
options |= STAT;
break;
- case 'u': /* user or user id */
+ case 'u': /* user or user id */ {
+ struct passwd *pw;
if (is_integer(optarg)) {
uid = atoi(optarg);
- pw = getpwuid((uid_t)uid);
+ pw = getpwuid(uid);
/* check to be sure user exists */
if (pw == NULL) {
usage2(_("UID was not found"), optarg);
@@ -521,10 +504,11 @@ int process_arguments(int argc, char **argv) {
/* then get uid */
uid = pw->pw_uid;
}
- user = pw->pw_name;
+
+ char *user = pw->pw_name;
xasprintf(&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""), uid, user);
options |= USER;
- break;
+ } break;
case 'C': /* command */
/* TODO: allow this to be passed in with --metric */
if (prog) {
@@ -542,12 +526,12 @@ int process_arguments(int argc, char **argv) {
exclude_progs = optarg;
}
xasprintf(&fmt, _("%s%sexclude progs '%s'"), (fmt ? fmt : ""), (options ? ", " : ""), exclude_progs);
- char *p = strtok(exclude_progs, ",");
+ char *tmp_pointer = strtok(exclude_progs, ",");
- while (p) {
+ while (tmp_pointer) {
exclude_progs_arr = realloc(exclude_progs_arr, sizeof(char *) * ++exclude_progs_counter);
- exclude_progs_arr[exclude_progs_counter - 1] = p;
- p = strtok(NULL, ",");
+ exclude_progs_arr[exclude_progs_counter - 1] = tmp_pointer;
+ tmp_pointer = strtok(NULL, ",");
}
options |= EXCLUDE_PROGS;
@@ -562,23 +546,26 @@ int process_arguments(int argc, char **argv) {
xasprintf(&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
options |= ARGS;
break;
- case CHAR_MAX + 1:
- err = regcomp(&re_args, optarg, cflags);
+ case CHAR_MAX + 1: {
+ int cflags = REG_NOSUB | REG_EXTENDED;
+ int err = regcomp(&re_args, optarg, cflags);
if (err != 0) {
+ char errbuf[MAX_INPUT_BUFFER];
regerror(err, &re_args, errbuf, MAX_INPUT_BUFFER);
die(STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
}
/* Strip off any | within the regex optarg */
- temp_string = strdup(optarg);
- while (temp_string[i] != '\0') {
- if (temp_string[i] == '|') {
- temp_string[i] = ',';
+ char *temp_string = strdup(optarg);
+ int index = 0;
+ while (temp_string[index] != '\0') {
+ if (temp_string[index] == '|') {
+ temp_string[index] = ',';
}
- i++;
+ index++;
}
xasprintf(&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), temp_string);
options |= EREG_ARGS;
- break;
+ } break;
case 'r': /* RSS */
if (sscanf(optarg, "%d%[^0-9]", &rss, tmp) == 1) {
xasprintf(&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
@@ -606,29 +593,33 @@ int process_arguments(int argc, char **argv) {
if (strcmp(optarg, "PROCS") == 0) {
metric = METRIC_PROCS;
break;
- } else if (strcmp(optarg, "VSZ") == 0) {
+ }
+ if (strcmp(optarg, "VSZ") == 0) {
metric = METRIC_VSZ;
break;
- } else if (strcmp(optarg, "RSS") == 0) {
+ }
+ if (strcmp(optarg, "RSS") == 0) {
metric = METRIC_RSS;
break;
- } else if (strcmp(optarg, "CPU") == 0) {
+ }
+ if (strcmp(optarg, "CPU") == 0) {
metric = METRIC_CPU;
break;
- } else if (strcmp(optarg, "ELAPSED") == 0) {
+ }
+ if (strcmp(optarg, "ELAPSED") == 0) {
metric = METRIC_ELAPSED;
break;
}
usage4(_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
case 'k': /* linux kernel thread filter */
- kthread_filter = 1;
+ kthread_filter = true;
break;
case 'v': /* command */
verbose++;
break;
case 'T':
- usepid = 1;
+ usepid = true;
break;
case CHAR_MAX + 2:
input_filename = optarg;
@@ -636,15 +627,15 @@ int process_arguments(int argc, char **argv) {
}
}
- c = optind;
- if ((!warning_range) && argv[c]) {
- warning_range = argv[c++];
+ int index = optind;
+ if ((!warning_range) && argv[index]) {
+ warning_range = argv[index++];
}
- if ((!critical_range) && argv[c]) {
- critical_range = argv[c++];
+ if ((!critical_range) && argv[index]) {
+ critical_range = argv[index++];
}
- if (statopts == NULL && argv[c]) {
- xasprintf(&statopts, "%s", argv[c++]);
+ if (statopts == NULL && argv[index]) {
+ xasprintf(&statopts, "%s", argv[index++]);
xasprintf(&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
options |= STAT;
}
@@ -685,25 +676,9 @@ int validate_arguments() {
/* convert the elapsed time to seconds */
int convert_to_seconds(char *etime) {
-
- char *ptr;
- int total;
-
- int hyphcnt;
- int coloncnt;
- int days;
- int hours;
- int minutes;
- int seconds;
-
- hyphcnt = 0;
- coloncnt = 0;
- days = 0;
- hours = 0;
- minutes = 0;
- seconds = 0;
-
- for (ptr = etime; *ptr != '\0'; ptr++) {
+ int hyphcnt = 0;
+ int coloncnt = 0;
+ for (char *ptr = etime; *ptr != '\0'; ptr++) {
if (*ptr == '-') {
hyphcnt++;
@@ -715,6 +690,10 @@ int convert_to_seconds(char *etime) {
}
}
+ int days = 0;
+ int hours = 0;
+ int minutes = 0;
+ int seconds = 0;
if (hyphcnt > 0) {
sscanf(etime, "%d-%d:%d:%d", &days, &hours, &minutes, &seconds);
/* linux 2.6.5/2.6.6 reporting some processes with infinite
@@ -730,7 +709,7 @@ int convert_to_seconds(char *etime) {
}
}
- total = (days * 86400) + (hours * 3600) + (minutes * 60) + seconds;
+ int total = (days * 86400) + (hours * 3600) + (minutes * 60) + seconds;
if (verbose >= 3 && metric == METRIC_ELAPSED) {
printf("seconds: %d\n", total);
--
cgit v1.2.3-74-g34f1
From a14b2b35776c7550123ce58af571913eb9d7819f Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Wed, 12 Mar 2025 15:29:36 +0100
Subject: Refactor check_procs
---
plugins/Makefile.am | 1 +
plugins/check_procs.c | 335 ++++++++++++++++++++---------------------
plugins/check_procs.d/config.h | 75 +++++++++
3 files changed, 243 insertions(+), 168 deletions(-)
create mode 100644 plugins/check_procs.d/config.h
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 6c582a15..0920adce 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -63,6 +63,7 @@ EXTRA_DIST = t \
check_mrtg.d \
check_apt.d \
check_pgsql.d \
+ check_procs.d \
check_by_ssh.d \
check_smtp.d \
check_mysql.d \
diff --git a/plugins/check_procs.c b/plugins/check_procs.c
index da2198a7..83e6864e 100644
--- a/plugins/check_procs.c
+++ b/plugins/check_procs.c
@@ -44,6 +44,7 @@ const char *email = "devel@monitoring-plugins.org";
#include "utils_cmd.h"
#include "regex.h"
#include "states.h"
+#include "check_procs.d/config.h"
#include
#include
@@ -52,17 +53,17 @@ const char *email = "devel@monitoring-plugins.org";
# include
#endif
-static int process_arguments(int /*argc*/, char ** /*argv*/);
-static int validate_arguments(void);
-static int convert_to_seconds(char * /*etime*/);
+typedef struct {
+ int errorcode;
+ check_procs_config config;
+} check_procs_config_wrapper;
+static check_procs_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
+static check_procs_config_wrapper validate_arguments(check_procs_config_wrapper /*config_wrapper*/);
+
+static int convert_to_seconds(char * /*etime*/, enum metric /*metric*/);
static void print_help(void);
void print_usage(void);
-static char *warning_range = NULL;
-static char *critical_range = NULL;
-static thresholds *procs_thresholds = NULL;
-
-static int options = 0; /* bitmask of filter criteria to test against */
#define ALL 1
#define STAT 2
#define PPID 4
@@ -80,36 +81,7 @@ static int options = 0; /* bitmask of filter criteria to test against */
"kthreadd" /* the parent process of kernel threads: \
ppid of procs are compared to pid of this proc*/
-/* Different metrics */
-char *metric_name;
-enum metric {
- METRIC_PROCS,
- METRIC_VSZ,
- METRIC_RSS,
- METRIC_CPU,
- METRIC_ELAPSED
-};
-enum metric metric = METRIC_PROCS;
-
static int verbose = 0;
-static uid_t uid;
-static pid_t ppid;
-static int vsz;
-static int rss;
-static float pcpu;
-static char *statopts;
-static char *prog;
-static char *exclude_progs;
-static char **exclude_progs_arr = NULL;
-static char exclude_progs_counter = 0;
-static char *args;
-static char *input_filename = NULL;
-static regex_t re_args;
-static char *fmt;
-static char *fails;
-static char tmp[MAX_INPUT_BUFFER];
-static bool kthread_filter = false;
-static bool usepid = false; /* whether to test for pid or /proc/pid/exe */
static int stat_exe(const pid_t pid, struct stat *buf) {
char *path;
@@ -125,27 +97,27 @@ int main(int argc, char **argv) {
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- xasprintf(&metric_name, "PROCS");
- metric = METRIC_PROCS;
-
/* Parse extra opts if any */
argv = np_extra_opts(&argc, argv, progname);
- if (process_arguments(argc, argv) == ERROR) {
+ check_procs_config_wrapper tmp_config = process_arguments(argc, argv);
+ if (tmp_config.errorcode == ERROR) {
usage4(_("Could not parse arguments"));
}
+ check_procs_config config = tmp_config.config;
+
/* find ourself */
pid_t mypid = getpid();
pid_t myppid = getppid();
dev_t mydev = 0;
ino_t myino = 0;
struct stat statbuf;
- if (usepid || stat_exe(mypid, &statbuf) == -1) {
+ if (config.usepid || stat_exe(mypid, &statbuf) == -1) {
/* usepid might have been set by -T */
- usepid = true;
+ config.usepid = true;
} else {
- usepid = false;
+ config.usepid = false;
mydev = statbuf.st_dev;
myino = statbuf.st_ino;
}
@@ -163,14 +135,14 @@ int main(int argc, char **argv) {
output chld_out;
output chld_err;
mp_state_enum result = STATE_UNKNOWN;
- if (input_filename == NULL) {
+ if (config.input_filename == NULL) {
result = cmd_run(PS_COMMAND, &chld_out, &chld_err, 0);
if (chld_err.lines > 0) {
printf("%s: %s", _("System call sent warnings to stderr"), chld_err.line[0]);
exit(STATE_WARNING);
}
} else {
- result = cmd_file_read(input_filename, &chld_out, 0);
+ result = cmd_file_read(config.input_filename, &chld_out, 0);
}
int pos; /* number of spaces before 'args' in `ps` output */
@@ -222,7 +194,7 @@ int main(int argc, char **argv) {
strcpy(procprog, base_name(procprog));
/* we need to convert the elapsed time to seconds */
- procseconds = convert_to_seconds(procetime);
+ procseconds = convert_to_seconds(procetime, config.metric);
if (verbose >= 3) {
printf("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", procs, procuid, procvsz,
@@ -231,8 +203,8 @@ int main(int argc, char **argv) {
/* Ignore self */
int ret = 0;
- if ((usepid && mypid == procpid) ||
- (((!usepid) && ((ret = stat_exe(procpid, &statbuf) != -1) && statbuf.st_dev == mydev && statbuf.st_ino == myino)) ||
+ if ((config.usepid && mypid == procpid) ||
+ (((!config.usepid) && ((ret = stat_exe(procpid, &statbuf) != -1) && statbuf.st_dev == mydev && statbuf.st_ino == myino)) ||
(ret == -1 && errno == ENOENT))) {
if (verbose >= 3) {
printf("not considering - is myself or gone\n");
@@ -256,10 +228,10 @@ int main(int argc, char **argv) {
}
/* Ignore excluded processes by name */
- if (options & EXCLUDE_PROGS) {
+ if (config.options & EXCLUDE_PROGS) {
bool found = false;
- for (int i = 0; i < (exclude_progs_counter); i++) {
- if (!strcmp(procprog, exclude_progs_arr[i])) {
+ for (int i = 0; i < (config.exclude_progs_counter); i++) {
+ if (!strcmp(procprog, config.exclude_progs_arr[i])) {
found = true;
}
}
@@ -275,7 +247,7 @@ int main(int argc, char **argv) {
/* filter kernel threads (children of KTHREAD_PARENT)*/
/* TODO adapt for other OSes than GNU/Linux
sorry for not doing that, but I've no other OSes to test :-( */
- if (kthread_filter) {
+ if (config.kthread_filter) {
/* get pid KTHREAD_PARENT */
if (kthread_ppid == 0 && !strcmp(procprog, KTHREAD_PARENT)) {
kthread_ppid = procpid;
@@ -289,38 +261,38 @@ int main(int argc, char **argv) {
}
}
- if ((options & STAT) && (strstr(procstat, statopts))) {
+ if ((config.options & STAT) && (strstr(procstat, config.statopts))) {
resultsum |= STAT;
}
- if ((options & ARGS) && procargs && (strstr(procargs, args) != NULL)) {
+ if ((config.options & ARGS) && procargs && (strstr(procargs, config.args) != NULL)) {
resultsum |= ARGS;
}
- if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t)0, NULL, 0) == 0)) {
+ if ((config.options & EREG_ARGS) && procargs && (regexec(&config.re_args, procargs, (size_t)0, NULL, 0) == 0)) {
resultsum |= EREG_ARGS;
}
- if ((options & PROG) && procprog && (strcmp(prog, procprog) == 0)) {
+ if ((config.options & PROG) && procprog && (strcmp(config.prog, procprog) == 0)) {
resultsum |= PROG;
}
- if ((options & PPID) && (procppid == ppid)) {
+ if ((config.options & PPID) && (procppid == config.ppid)) {
resultsum |= PPID;
}
- if ((options & USER) && (procuid == uid)) {
+ if ((config.options & USER) && (procuid == config.uid)) {
resultsum |= USER;
}
- if ((options & VSZ) && (procvsz >= vsz)) {
+ if ((config.options & VSZ) && (procvsz >= config.vsz)) {
resultsum |= VSZ;
}
- if ((options & RSS) && (procrss >= rss)) {
+ if ((config.options & RSS) && (procrss >= config.rss)) {
resultsum |= RSS;
}
- if ((options & PCPU) && (procpcpu >= pcpu)) {
+ if ((config.options & PCPU) && (procpcpu >= config.pcpu)) {
resultsum |= PCPU;
}
found++;
/* Next line if filters not matched */
- if (!(options == resultsum || options == ALL)) {
+ if (!(config.options == resultsum || config.options == ALL)) {
continue;
}
@@ -331,27 +303,27 @@ int main(int argc, char **argv) {
}
mp_state_enum temporary_result = STATE_OK;
- if (metric == METRIC_VSZ) {
- temporary_result = get_status((double)procvsz, procs_thresholds);
- } else if (metric == METRIC_RSS) {
- temporary_result = get_status((double)procrss, procs_thresholds);
+ if (config.metric == METRIC_VSZ) {
+ temporary_result = get_status((double)procvsz, config.procs_thresholds);
+ } else if (config.metric == METRIC_RSS) {
+ temporary_result = get_status((double)procrss, config.procs_thresholds);
}
/* TODO? float thresholds for --metric=CPU */
- else if (metric == METRIC_CPU) {
- temporary_result = get_status(procpcpu, procs_thresholds);
- } else if (metric == METRIC_ELAPSED) {
- temporary_result = get_status((double)procseconds, procs_thresholds);
+ else if (config.metric == METRIC_CPU) {
+ temporary_result = get_status(procpcpu, config.procs_thresholds);
+ } else if (config.metric == METRIC_ELAPSED) {
+ temporary_result = get_status((double)procseconds, config.procs_thresholds);
}
- if (metric != METRIC_PROCS) {
+ if (config.metric != METRIC_PROCS) {
if (temporary_result == STATE_WARNING) {
warn++;
- xasprintf(&fails, "%s%s%s", fails, (strcmp(fails, "") ? ", " : ""), procprog);
+ xasprintf(&config.fails, "%s%s%s", config.fails, (strcmp(config.fails, "") ? ", " : ""), procprog);
result = max_state(result, temporary_result);
}
if (temporary_result == STATE_CRITICAL) {
crit++;
- xasprintf(&fails, "%s%s%s", fails, (strcmp(fails, "") ? ", " : ""), procprog);
+ xasprintf(&config.fails, "%s%s%s", config.fails, (strcmp(config.fails, "") ? ", " : ""), procprog);
result = max_state(result, temporary_result);
}
}
@@ -372,35 +344,36 @@ int main(int argc, char **argv) {
}
/* Needed if procs found, but none match filter */
- if (metric == METRIC_PROCS) {
- result = max_state(result, get_status((double)procs, procs_thresholds));
+ if (config.metric == METRIC_PROCS) {
+ result = max_state(result, get_status((double)procs, config.procs_thresholds));
}
if (result == STATE_OK) {
- printf("%s %s: ", metric_name, _("OK"));
+ printf("%s %s: ", config.metric_name, _("OK"));
} else if (result == STATE_WARNING) {
- printf("%s %s: ", metric_name, _("WARNING"));
- if (metric != METRIC_PROCS) {
+ printf("%s %s: ", config.metric_name, _("WARNING"));
+ if (config.metric != METRIC_PROCS) {
printf(_("%d warn out of "), warn);
}
} else if (result == STATE_CRITICAL) {
- printf("%s %s: ", metric_name, _("CRITICAL"));
- if (metric != METRIC_PROCS) {
+ printf("%s %s: ", config.metric_name, _("CRITICAL"));
+ if (config.metric != METRIC_PROCS) {
printf(_("%d crit, %d warn out of "), crit, warn);
}
}
printf(ngettext("%d process", "%d processes", (unsigned long)procs), procs);
- if (strcmp(fmt, "") != 0) {
- printf(_(" with %s"), fmt);
+ if (strcmp(config.fmt, "") != 0) {
+ printf(_(" with %s"), config.fmt);
}
- if (verbose >= 1 && strcmp(fails, "")) {
- printf(" [%s]", fails);
+ if (verbose >= 1 && strcmp(config.fails, "")) {
+ printf(" [%s]", config.fails);
}
- if (metric == METRIC_PROCS) {
- printf(" | procs=%d;%s;%s;0;", procs, warning_range ? warning_range : "", critical_range ? critical_range : "");
+ if (config.metric == METRIC_PROCS) {
+ printf(" | procs=%d;%s;%s;0;", procs, config.warning_range ? config.warning_range : "",
+ config.critical_range ? config.critical_range : "");
} else {
printf(" | procs=%d;;;0; procs_warn=%d;;;0; procs_crit=%d;;;0;", procs, warn, crit);
}
@@ -410,7 +383,7 @@ int main(int argc, char **argv) {
}
/* process command-line arguments */
-int process_arguments(int argc, char **argv) {
+check_procs_config_wrapper process_arguments(int argc, char **argv) {
static struct option longopts[] = {{"warning", required_argument, 0, 'w'},
{"critical", required_argument, 0, 'c'},
{"metric", required_argument, 0, 'm'},
@@ -440,6 +413,11 @@ int process_arguments(int argc, char **argv) {
}
}
+ check_procs_config_wrapper result = {
+ .errorcode = OK,
+ .config = check_procs_config_init(),
+ };
+
while (true) {
int option = 0;
int option_index = getopt_long(argc, argv, "Vvhkt:c:w:p:s:u:C:a:z:r:m:P:T:X:", longopts, &option);
@@ -465,32 +443,36 @@ int process_arguments(int argc, char **argv) {
}
break;
case 'c': /* critical threshold */
- critical_range = optarg;
+ result.config.critical_range = optarg;
break;
case 'w': /* warning threshold */
- warning_range = optarg;
+ result.config.warning_range = optarg;
break;
- case 'p': /* process id */
- if (sscanf(optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
- xasprintf(&fmt, "%s%sPPID = %d", (fmt ? fmt : ""), (options ? ", " : ""), ppid);
- options |= PPID;
+ case 'p': { /* process id */
+ static char tmp[MAX_INPUT_BUFFER];
+ if (sscanf(optarg, "%d%[^0-9]", &result.config.ppid, tmp) == 1) {
+ xasprintf(&result.config.fmt, "%s%sPPID = %d", (result.config.fmt ? result.config.fmt : ""),
+ (result.config.options ? ", " : ""), result.config.ppid);
+ result.config.options |= PPID;
break;
}
usage4(_("Parent Process ID must be an integer!"));
+ }
case 's': /* status */
- if (statopts) {
+ if (result.config.statopts) {
break;
} else {
- statopts = optarg;
+ result.config.statopts = optarg;
}
- xasprintf(&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
- options |= STAT;
+ xasprintf(&result.config.fmt, _("%s%sSTATE = %s"), (result.config.fmt ? result.config.fmt : ""),
+ (result.config.options ? ", " : ""), result.config.statopts);
+ result.config.options |= STAT;
break;
case 'u': /* user or user id */ {
struct passwd *pw;
if (is_integer(optarg)) {
- uid = atoi(optarg);
- pw = getpwuid(uid);
+ result.config.uid = atoi(optarg);
+ pw = getpwuid(result.config.uid);
/* check to be sure user exists */
if (pw == NULL) {
usage2(_("UID was not found"), optarg);
@@ -502,56 +484,61 @@ int process_arguments(int argc, char **argv) {
usage2(_("User name was not found"), optarg);
}
/* then get uid */
- uid = pw->pw_uid;
+ result.config.uid = pw->pw_uid;
}
char *user = pw->pw_name;
- xasprintf(&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""), uid, user);
- options |= USER;
+ xasprintf(&result.config.fmt, "%s%sUID = %d (%s)", (result.config.fmt ? result.config.fmt : ""),
+ (result.config.options ? ", " : ""), result.config.uid, user);
+ result.config.options |= USER;
} break;
case 'C': /* command */
/* TODO: allow this to be passed in with --metric */
- if (prog) {
+ if (result.config.prog) {
break;
} else {
- prog = optarg;
+ result.config.prog = optarg;
}
- xasprintf(&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""), prog);
- options |= PROG;
+ xasprintf(&result.config.fmt, _("%s%scommand name '%s'"), (result.config.fmt ? result.config.fmt : ""),
+ (result.config.options ? ", " : ""), result.config.prog);
+ result.config.options |= PROG;
break;
case 'X':
- if (exclude_progs) {
+ if (result.config.exclude_progs) {
break;
} else {
- exclude_progs = optarg;
+ result.config.exclude_progs = optarg;
}
- xasprintf(&fmt, _("%s%sexclude progs '%s'"), (fmt ? fmt : ""), (options ? ", " : ""), exclude_progs);
- char *tmp_pointer = strtok(exclude_progs, ",");
+ xasprintf(&result.config.fmt, _("%s%sexclude progs '%s'"), (result.config.fmt ? result.config.fmt : ""),
+ (result.config.options ? ", " : ""), result.config.exclude_progs);
+ char *tmp_pointer = strtok(result.config.exclude_progs, ",");
while (tmp_pointer) {
- exclude_progs_arr = realloc(exclude_progs_arr, sizeof(char *) * ++exclude_progs_counter);
- exclude_progs_arr[exclude_progs_counter - 1] = tmp_pointer;
+ result.config.exclude_progs_arr =
+ realloc(result.config.exclude_progs_arr, sizeof(char *) * ++result.config.exclude_progs_counter);
+ result.config.exclude_progs_arr[result.config.exclude_progs_counter - 1] = tmp_pointer;
tmp_pointer = strtok(NULL, ",");
}
- options |= EXCLUDE_PROGS;
+ result.config.options |= EXCLUDE_PROGS;
break;
case 'a': /* args (full path name with args) */
/* TODO: allow this to be passed in with --metric */
- if (args) {
+ if (result.config.args) {
break;
} else {
- args = optarg;
+ result.config.args = optarg;
}
- xasprintf(&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
- options |= ARGS;
+ xasprintf(&result.config.fmt, "%s%sargs '%s'", (result.config.fmt ? result.config.fmt : ""),
+ (result.config.options ? ", " : ""), result.config.args);
+ result.config.options |= ARGS;
break;
case CHAR_MAX + 1: {
int cflags = REG_NOSUB | REG_EXTENDED;
- int err = regcomp(&re_args, optarg, cflags);
+ int err = regcomp(&result.config.re_args, optarg, cflags);
if (err != 0) {
char errbuf[MAX_INPUT_BUFFER];
- regerror(err, &re_args, errbuf, MAX_INPUT_BUFFER);
+ regerror(err, &result.config.re_args, errbuf, MAX_INPUT_BUFFER);
die(STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
}
/* Strip off any | within the regex optarg */
@@ -563,119 +550,131 @@ int process_arguments(int argc, char **argv) {
}
index++;
}
- xasprintf(&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), temp_string);
- options |= EREG_ARGS;
+ xasprintf(&result.config.fmt, "%s%sregex args '%s'", (result.config.fmt ? result.config.fmt : ""),
+ (result.config.options ? ", " : ""), temp_string);
+ result.config.options |= EREG_ARGS;
} break;
- case 'r': /* RSS */
- if (sscanf(optarg, "%d%[^0-9]", &rss, tmp) == 1) {
- xasprintf(&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
- options |= RSS;
+ case 'r': { /* RSS */
+ static char tmp[MAX_INPUT_BUFFER];
+ if (sscanf(optarg, "%d%[^0-9]", &result.config.rss, tmp) == 1) {
+ xasprintf(&result.config.fmt, "%s%sRSS >= %d", (result.config.fmt ? result.config.fmt : ""),
+ (result.config.options ? ", " : ""), result.config.rss);
+ result.config.options |= RSS;
break;
}
usage4(_("RSS must be an integer!"));
- case 'z': /* VSZ */
- if (sscanf(optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
- xasprintf(&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
- options |= VSZ;
+ }
+ case 'z': { /* VSZ */
+ static char tmp[MAX_INPUT_BUFFER];
+ if (sscanf(optarg, "%d%[^0-9]", &result.config.vsz, tmp) == 1) {
+ xasprintf(&result.config.fmt, "%s%sVSZ >= %d", (result.config.fmt ? result.config.fmt : ""),
+ (result.config.options ? ", " : ""), result.config.vsz);
+ result.config.options |= VSZ;
break;
}
usage4(_("VSZ must be an integer!"));
- case 'P': /* PCPU */
+ }
+ case 'P': { /* PCPU */
/* TODO: -P 1.5.5 is accepted */
- if (sscanf(optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
- xasprintf(&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
- options |= PCPU;
+ static char tmp[MAX_INPUT_BUFFER];
+ if (sscanf(optarg, "%f%[^0-9.]", &result.config.pcpu, tmp) == 1) {
+ xasprintf(&result.config.fmt, "%s%sPCPU >= %.2f", (result.config.fmt ? result.config.fmt : ""),
+ (result.config.options ? ", " : ""), result.config.pcpu);
+ result.config.options |= PCPU;
break;
}
usage4(_("PCPU must be a float!"));
+ }
case 'm':
- xasprintf(&metric_name, "%s", optarg);
+ xasprintf(&result.config.metric_name, "%s", optarg);
if (strcmp(optarg, "PROCS") == 0) {
- metric = METRIC_PROCS;
+ result.config.metric = METRIC_PROCS;
break;
}
if (strcmp(optarg, "VSZ") == 0) {
- metric = METRIC_VSZ;
+ result.config.metric = METRIC_VSZ;
break;
}
if (strcmp(optarg, "RSS") == 0) {
- metric = METRIC_RSS;
+ result.config.metric = METRIC_RSS;
break;
}
if (strcmp(optarg, "CPU") == 0) {
- metric = METRIC_CPU;
+ result.config.metric = METRIC_CPU;
break;
}
if (strcmp(optarg, "ELAPSED") == 0) {
- metric = METRIC_ELAPSED;
+ result.config.metric = METRIC_ELAPSED;
break;
}
usage4(_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
case 'k': /* linux kernel thread filter */
- kthread_filter = true;
+ result.config.kthread_filter = true;
break;
case 'v': /* command */
verbose++;
break;
case 'T':
- usepid = true;
+ result.config.usepid = true;
break;
case CHAR_MAX + 2:
- input_filename = optarg;
+ result.config.input_filename = optarg;
break;
}
}
int index = optind;
- if ((!warning_range) && argv[index]) {
- warning_range = argv[index++];
+ if ((!result.config.warning_range) && argv[index]) {
+ result.config.warning_range = argv[index++];
}
- if ((!critical_range) && argv[index]) {
- critical_range = argv[index++];
+ if ((!result.config.critical_range) && argv[index]) {
+ result.config.critical_range = argv[index++];
}
- if (statopts == NULL && argv[index]) {
- xasprintf(&statopts, "%s", argv[index++]);
- xasprintf(&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
- options |= STAT;
+ if (result.config.statopts == NULL && argv[index]) {
+ xasprintf(&result.config.statopts, "%s", argv[index++]);
+ xasprintf(&result.config.fmt, _("%s%sSTATE = %s"), (result.config.fmt ? result.config.fmt : ""),
+ (result.config.options ? ", " : ""), result.config.statopts);
+ result.config.options |= STAT;
}
/* this will abort in case of invalid ranges */
- set_thresholds(&procs_thresholds, warning_range, critical_range);
+ set_thresholds(&result.config.procs_thresholds, result.config.warning_range, result.config.critical_range);
- return validate_arguments();
+ return validate_arguments(result);
}
-int validate_arguments() {
- if (options == 0) {
- options = ALL;
+check_procs_config_wrapper validate_arguments(check_procs_config_wrapper config_wrapper) {
+ if (config_wrapper.config.options == 0) {
+ config_wrapper.config.options = ALL;
}
- if (statopts == NULL) {
- statopts = strdup("");
+ if (config_wrapper.config.statopts == NULL) {
+ config_wrapper.config.statopts = strdup("");
}
- if (prog == NULL) {
- prog = strdup("");
+ if (config_wrapper.config.prog == NULL) {
+ config_wrapper.config.prog = strdup("");
}
- if (args == NULL) {
- args = strdup("");
+ if (config_wrapper.config.args == NULL) {
+ config_wrapper.config.args = strdup("");
}
- if (fmt == NULL) {
- fmt = strdup("");
+ if (config_wrapper.config.fmt == NULL) {
+ config_wrapper.config.fmt = strdup("");
}
- if (fails == NULL) {
- fails = strdup("");
+ if (config_wrapper.config.fails == NULL) {
+ config_wrapper.config.fails = strdup("");
}
- return options;
+ // return options;
+ return config_wrapper;
}
/* convert the elapsed time to seconds */
-int convert_to_seconds(char *etime) {
+int convert_to_seconds(char *etime, enum metric metric) {
int hyphcnt = 0;
int coloncnt = 0;
for (char *ptr = etime; *ptr != '\0'; ptr++) {
diff --git a/plugins/check_procs.d/config.h b/plugins/check_procs.d/config.h
new file mode 100644
index 00000000..815809d4
--- /dev/null
+++ b/plugins/check_procs.d/config.h
@@ -0,0 +1,75 @@
+#pragma once
+
+#include "../../config.h"
+#include "regex.h"
+#include "thresholds.h"
+#include
+#include
+#include
+
+enum metric {
+ METRIC_PROCS,
+ METRIC_VSZ,
+ METRIC_RSS,
+ METRIC_CPU,
+ METRIC_ELAPSED
+};
+
+typedef struct {
+ int options; /* bitmask of filter criteria to test against */
+ enum metric metric;
+ char *metric_name;
+ char *input_filename;
+ char *prog;
+ char *args;
+ char *fmt;
+ char *fails;
+ char *exclude_progs;
+ char **exclude_progs_arr;
+ char exclude_progs_counter;
+ regex_t re_args;
+
+ bool kthread_filter;
+ bool usepid; /* whether to test for pid or /proc/pid/exe */
+ uid_t uid;
+ pid_t ppid;
+ int vsz;
+ int rss;
+ float pcpu;
+ char *statopts;
+
+ char *warning_range;
+ char *critical_range;
+ thresholds *procs_thresholds;
+} check_procs_config;
+
+check_procs_config check_procs_config_init() {
+ check_procs_config tmp = {
+ .options = 0,
+ .metric = METRIC_PROCS,
+ .metric_name = strdup("PROCS"),
+ .input_filename = NULL,
+ .prog = NULL,
+ .args = NULL,
+ .fmt = NULL,
+ .fails = NULL,
+ .exclude_progs = NULL,
+ .exclude_progs_arr = NULL,
+ .exclude_progs_counter = 0,
+ .re_args = {},
+
+ .kthread_filter = false,
+ .usepid = false,
+ .uid = {},
+ .ppid = {},
+ .vsz = 0,
+ .rss = 0,
+ .pcpu = 0,
+ .statopts = NULL,
+
+ .warning_range = NULL,
+ .critical_range = NULL,
+ .procs_thresholds = NULL,
+ };
+ return tmp;
+}
--
cgit v1.2.3-74-g34f1
From a746576b8cb72a3233caf5ac852b2679cc98d80c Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Wed, 12 Mar 2025 15:50:50 +0100
Subject: Fix initialisers for old compilers
---
plugins/check_procs.d/config.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/plugins/check_procs.d/config.h b/plugins/check_procs.d/config.h
index 815809d4..e32ca066 100644
--- a/plugins/check_procs.d/config.h
+++ b/plugins/check_procs.d/config.h
@@ -56,12 +56,12 @@ check_procs_config check_procs_config_init() {
.exclude_progs = NULL,
.exclude_progs_arr = NULL,
.exclude_progs_counter = 0,
- .re_args = {},
+ .re_args = {0},
.kthread_filter = false,
.usepid = false,
- .uid = {},
- .ppid = {},
+ .uid = 0,
+ .ppid = 0,
.vsz = 0,
.rss = 0,
.pcpu = 0,
--
cgit v1.2.3-74-g34f1
From 7a5fa0cc5c3c725ddb990fa97ee52652397f1787 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Mon, 17 Mar 2025 12:56:42 +0100
Subject: check_ide_smart: use the more common C90 fixed width integers
---
plugins/check_ide_smart.c | 90 ++++++++++++++++++++++++++---------------------
1 file changed, 49 insertions(+), 41 deletions(-)
diff --git a/plugins/check_ide_smart.c b/plugins/check_ide_smart.c
index 9640ef70..16fe3d01 100644
--- a/plugins/check_ide_smart.c
+++ b/plugins/check_ide_smart.c
@@ -56,7 +56,6 @@ void print_usage(void);
# include
# include
# include
-# include /* for __u8 and friends */
# include
# include
# include
@@ -79,48 +78,47 @@ void print_usage(void);
#define UNKNOWN -1
typedef struct threshold_s {
- __u8 id;
- __u8 threshold;
- __u8 reserved[10];
+ uint8_t id;
+ uint8_t threshold;
+ uint8_t reserved[10];
} __attribute__((packed)) threshold_t;
typedef struct thresholds_s {
- __u16 revision;
+ uint16_t revision;
threshold_t thresholds[NR_ATTRIBUTES];
- __u8 reserved[18];
- __u8 vendor[131];
- __u8 checksum;
+ uint8_t reserved[18];
+ uint8_t vendor[131];
+ uint8_t checksum;
} __attribute__((packed)) thresholds_t;
typedef struct value_s {
- __u8 id;
- __u16 status;
- __u8 value;
- __u8 vendor[8];
+ uint8_t id;
+ uint16_t status;
+ uint8_t value;
+ uint8_t vendor[8];
} __attribute__((packed)) value_t;
typedef struct values_s {
- __u16 revision;
+ uint16_t revision;
value_t values[NR_ATTRIBUTES];
- __u8 offline_status;
- __u8 vendor1;
- __u16 offline_timeout;
- __u8 vendor2;
- __u8 offline_capability;
- __u16 smart_capability;
- __u8 reserved[16];
- __u8 vendor[125];
- __u8 checksum;
+ uint8_t offline_status;
+ uint8_t vendor1;
+ uint16_t offline_timeout;
+ uint8_t vendor2;
+ uint8_t offline_capability;
+ uint16_t smart_capability;
+ uint8_t reserved[16];
+ uint8_t vendor[125];
+ uint8_t checksum;
} __attribute__((packed)) values_t;
static struct {
- __u8 value;
+ uint8_t value;
char *text;
-} offline_status_text[] = {{0x00, "NeverStarted"}, {0x02, "Completed"}, {0x04, "Suspended"},
- {0x05, "Aborted"}, {0x06, "Failed"}, {0, 0}};
+} offline_status_text[] = {{0x00, "NeverStarted"}, {0x02, "Completed"}, {0x04, "Suspended"}, {0x05, "Aborted"}, {0x06, "Failed"}, {0, 0}};
static struct {
- __u8 value;
+ uint8_t value;
char *text;
} smart_command[] = {{SMART_ENABLE, "SMART_ENABLE"},
{SMART_DISABLE, "SMART_DISABLE"},
@@ -140,7 +138,7 @@ static int smart_read_values(int, values_t *);
static int nagios(values_t *, thresholds_t *);
static void print_value(value_t *, threshold_t *);
static void print_values(values_t *, thresholds_t *);
-static int smart_cmd_simple(int, enum SmartCommand, __u8, bool);
+static int smart_cmd_simple(int, enum SmartCommand, uint8_t, bool);
static int smart_read_thresholds(int, thresholds_t *);
static bool verbose = false;
@@ -175,8 +173,9 @@ int main(int argc, char *argv[]) {
o = getopt_long(argc, argv, "+d:iq10nhVv", longopts, &longindex);
- if (o == -1 || o == EOF || o == 1)
+ if (o == -1 || o == EOF || o == 1) {
break;
+ }
switch (o) {
case 'd':
@@ -234,8 +233,9 @@ int main(int argc, char *argv[]) {
smart_read_values(fd, &values);
smart_read_thresholds(fd, &thresholds);
retval = nagios(&values, &thresholds);
- if (verbose)
+ if (verbose) {
print_values(&values, &thresholds);
+ }
close(fd);
return retval;
@@ -254,7 +254,7 @@ char *get_offline_text(int status) {
int smart_read_values(int fd, values_t *values) {
#ifdef __linux__
int e;
- __u8 args[4 + 512];
+ uint8_t args[4 + 512];
args[0] = WIN_SMART;
args[1] = 0;
args[2] = SMART_READ_VALUES;
@@ -282,8 +282,9 @@ int smart_read_values(int fd, values_t *values) {
req.cylinder = WDSMART_CYL;
if (ioctl(fd, ATAIOCCOMMAND, &req) == 0) {
- if (req.retsts != ATACMD_OK)
+ if (req.retsts != ATACMD_OK) {
errno = ENODEV;
+ }
}
if (errno != 0) {
@@ -370,22 +371,24 @@ void print_values(values_t *p, thresholds_t *t) {
p->smart_capability & 1 ? "SaveOnStandBy" : "", p->smart_capability & 2 ? "AutoSave" : "");
}
-int smart_cmd_simple(int fd, enum SmartCommand command, __u8 val0, bool show_error) {
+int smart_cmd_simple(int fd, enum SmartCommand command, uint8_t val0, bool show_error) {
int e = STATE_UNKNOWN;
#ifdef __linux__
- __u8 args[4];
+ uint8_t args[4];
args[0] = WIN_SMART;
args[1] = val0;
args[2] = smart_command[command].value;
args[3] = 0;
if (ioctl(fd, HDIO_DRIVE_CMD, &args)) {
e = STATE_CRITICAL;
- if (show_error)
+ if (show_error) {
printf(_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror(errno));
+ }
} else {
e = STATE_OK;
- if (show_error)
+ if (show_error) {
printf(_("OK - Command sent (%s)\n"), smart_command[command].text);
+ }
}
#endif /* __linux__ */
@@ -401,20 +404,24 @@ int smart_cmd_simple(int fd, enum SmartCommand command, __u8 val0, bool show_err
req.sec_count = val0;
if (ioctl(fd, ATAIOCCOMMAND, &req) == 0) {
- if (req.retsts != ATACMD_OK)
+ if (req.retsts != ATACMD_OK) {
errno = ENODEV;
- if (req.cylinder != WDSMART_CYL)
+ }
+ if (req.cylinder != WDSMART_CYL) {
errno = ENODEV;
+ }
}
if (errno != 0) {
e = STATE_CRITICAL;
- if (show_error)
+ if (show_error) {
printf(_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror(errno));
+ }
} else {
e = STATE_OK;
- if (show_error)
+ if (show_error) {
printf(_("OK - Command sent (%s)\n"), smart_command[command].text);
+ }
}
#endif /* __NetBSD__ */
@@ -424,7 +431,7 @@ int smart_cmd_simple(int fd, enum SmartCommand command, __u8 val0, bool show_err
int smart_read_thresholds(int fd, thresholds_t *thresholds) {
#ifdef __linux__
int e;
- __u8 args[4 + 512];
+ uint8_t args[4 + 512];
args[0] = WIN_SMART;
args[1] = 0;
args[2] = SMART_READ_THRESHOLDS;
@@ -452,8 +459,9 @@ int smart_read_thresholds(int fd, thresholds_t *thresholds) {
req.cylinder = WDSMART_CYL;
if (ioctl(fd, ATAIOCCOMMAND, &req) == 0) {
- if (req.retsts != ATACMD_OK)
+ if (req.retsts != ATACMD_OK) {
errno = ENODEV;
+ }
}
if (errno != 0) {
--
cgit v1.2.3-74-g34f1
From abc87a3d6d3ded76f44b87f28604db8a220fc9ba Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Mon, 17 Mar 2025 12:57:21 +0100
Subject: check_ping: fix some variables forgotten during refactoring
---
plugins/check_ping.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/plugins/check_ping.c b/plugins/check_ping.c
index 940b9475..6bcdeaad 100644
--- a/plugins/check_ping.c
+++ b/plugins/check_ping.c
@@ -116,10 +116,10 @@ int main(int argc, char **argv) {
# ifdef PING_HAS_TIMEOUT
xasprintf(&cmd, rawcmd, timeout_interval, config.max_packets, config.addresses[i]);
# else
- xasprintf(&cmd, rawcmd, config.max_packets, addresses[i]);
+ xasprintf(&cmd, rawcmd, config.max_packets, config.addresses[i]);
# endif
#else
- xasprintf(&cmd, rawcmd, addresses[i], config.max_packets);
+ xasprintf(&cmd, rawcmd, config.addresses[i], config.max_packets);
#endif
if (verbose >= 2) {
--
cgit v1.2.3-74-g34f1
From e04d2ec8c6014eaeb3c5ca51ff2dcb0f340a3a22 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Mon, 17 Mar 2025 12:58:12 +0100
Subject: check_swap: Fixes on NetBSD
---
plugins/check_swap.c | 8 +++
plugins/check_swap.d/check_swap.h | 5 +-
plugins/check_swap.d/swap.c | 102 ++++++++++++++++++--------------------
3 files changed, 59 insertions(+), 56 deletions(-)
diff --git a/plugins/check_swap.c b/plugins/check_swap.c
index cb95949a..435a104e 100644
--- a/plugins/check_swap.c
+++ b/plugins/check_swap.c
@@ -90,6 +90,14 @@ int main(int argc, char **argv) {
exit(STATE_UNKNOWN);
}
+ if (verbose) {
+ printf("Swap retrieval result:\n"
+ "\tFree: %llu\n"
+ "\tUsed: %llu\n"
+ "\tTotal: %llu\n",
+ data.metrics.free, data.metrics.used, data.metrics.total);
+ }
+
double percent_used;
mp_check overall = mp_check_init();
if (config.output_format_is_set) {
diff --git a/plugins/check_swap.d/check_swap.h b/plugins/check_swap.d/check_swap.h
index 1000fc9e..da08d65a 100644
--- a/plugins/check_swap.d/check_swap.h
+++ b/plugins/check_swap.d/check_swap.h
@@ -1,7 +1,8 @@
#pragma once
#include "../common.h"
-#include "output.h"
+#include "../../lib/output.h"
+#include "../../lib/states.h"
#ifndef SWAP_CONVERSION
# define SWAP_CONVERSION 1
@@ -26,7 +27,7 @@ typedef struct {
typedef struct {
bool allswaps;
- int no_swap_state;
+ mp_state_enum no_swap_state;
bool warn_is_set;
check_swap_threshold warn;
bool crit_is_set;
diff --git a/plugins/check_swap.d/swap.c b/plugins/check_swap.d/swap.c
index 180d5037..634f80d9 100644
--- a/plugins/check_swap.d/swap.c
+++ b/plugins/check_swap.d/swap.c
@@ -68,7 +68,7 @@ swap_result getSwapFromProcMeminfo(char proc_meminfo[]) {
FILE *meminfo_file_ptr;
meminfo_file_ptr = fopen(proc_meminfo, "r");
- swap_result result = {0};
+ swap_result result = {};
result.errorcode = STATE_UNKNOWN;
if (meminfo_file_ptr == NULL) {
@@ -78,83 +78,71 @@ swap_result getSwapFromProcMeminfo(char proc_meminfo[]) {
return result;
}
- uint64_t swap_total = 0;
- uint64_t swap_used = 0;
- uint64_t swap_free = 0;
+ unsigned long swap_total = 0;
+ unsigned long swap_used = 0;
+ unsigned long swap_free = 0;
bool found_total = false;
- bool found_used = false;
bool found_free = false;
char input_buffer[MAX_INPUT_BUFFER];
char str[32];
while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, meminfo_file_ptr)) {
- uint64_t tmp_KB = 0;
/*
* The following sscanf call looks for a line looking like: "Swap: 123
- * 123 123" On which kind of system this format exists, I can not say,
- * but I wanted to document this for people who are not adapt with
- * sscanf anymore, like me
- * Also the units used here are unclear and probably wrong
+ * 123 123" which exists on NetBSD (at least),
+ * The unit should be Bytes
*/
if (sscanf(input_buffer, "%*[S]%*[w]%*[a]%*[p]%*[:] %lu %lu %lu", &swap_total, &swap_used, &swap_free) == 3) {
-
- result.metrics.total += swap_total;
- result.metrics.used += swap_used;
- result.metrics.free += swap_free;
-
found_total = true;
found_free = true;
- found_used = true;
-
// Set error
result.errorcode = STATE_OK;
+ // Break out of fgets here, since both scanf expressions might match (NetBSD for example)
+ break;
+ }
+
+ /*
+ * The following sscanf call looks for lines looking like:
+ * "SwapTotal: 123" and "SwapFree: 123" This format exists at least
+ * on Debian Linux with a 5.* kernel
+ */
+ unsigned long tmp_KB = 0;
+ int sscanf_result = sscanf(input_buffer,
+ "%*[S]%*[w]%*[a]%*[p]%[TotalFreCchd]%*[:] %lu "
+ "%*[k]%*[B]",
+ str, &tmp_KB);
+
+ if (sscanf_result == 2) {
+
+ if (verbose >= 3) {
+ printf("Got %s with %lu\n", str, tmp_KB);
+ }
- /*
- * The following sscanf call looks for lines looking like:
- * "SwapTotal: 123" and "SwapFree: 123" This format exists at least
- * on Debian Linux with a 5.* kernel
- */
- } else {
- int sscanf_result = sscanf(input_buffer,
- "%*[S]%*[w]%*[a]%*[p]%[TotalFreCchd]%*[:] %lu "
- "%*[k]%*[B]",
- str, &tmp_KB);
-
- if (sscanf_result == 2) {
-
- if (verbose >= 3) {
- printf("Got %s with %lu\n", str, tmp_KB);
- }
-
- /* I think this part is always in Kb, so convert to bytes */
- if (strcmp("Total", str) == 0) {
- swap_total = tmp_KB * 1000;
- found_total = true;
- } else if (strcmp("Free", str) == 0) {
- swap_free = swap_free + tmp_KB * 1000;
- found_free = true;
- found_used = true; // No explicit used metric available
- } else if (strcmp("Cached", str) == 0) {
- swap_free = swap_free + tmp_KB * 1000;
- found_free = true;
- found_used = true; // No explicit used metric available
- }
-
- result.errorcode = STATE_OK;
+ /* I think this part is always in Kb, so convert to bytes */
+ if (strcmp("Total", str) == 0) {
+ swap_total = tmp_KB * 1000;
+ found_total = true;
+ } else if (strcmp("Free", str) == 0) {
+ swap_free += tmp_KB * 1000;
+ found_free = true;
+ } else if (strcmp("Cached", str) == 0) {
+ swap_free += tmp_KB * 1000;
}
+
+ result.errorcode = STATE_OK;
}
}
fclose(meminfo_file_ptr);
result.metrics.total = swap_total;
- result.metrics.used = swap_total - swap_free;
result.metrics.free = swap_free;
+ result.metrics.used = swap_total - swap_free;
- if (!found_free || !found_total || !found_used) {
+ if (!found_free || !found_total) {
result.errorcode = STATE_UNKNOWN;
}
@@ -297,8 +285,14 @@ struct swapent {
};
#else
+
+// Includes for NetBSD
+# include
+# include
+
# define bsd_swapctl swapctl
-#endif
+
+#endif // CHECK_SWAP_SWAPCTL_BSD
swap_result getSwapFromSwapctl_BSD(swap_config config) {
/* get the number of active swap devices */
@@ -322,8 +316,8 @@ swap_result getSwapFromSwapctl_BSD(swap_config config) {
unsigned long long used_swap_mb = 0;
for (int i = 0; i < nswaps; i++) {
- dsktotal_mb = (float)ent[i].se_nblks / (float)config.conversion_factor;
- dskused_mb = (float)ent[i].se_inuse / (float)config.conversion_factor;
+ dsktotal_mb = (double)ent[i].se_nblks / (double)config.conversion_factor;
+ dskused_mb = (double)ent[i].se_inuse / (double)config.conversion_factor;
dskfree_mb = (dsktotal_mb - dskused_mb);
if (config.allswaps && dsktotal_mb > 0) {
--
cgit v1.2.3-74-g34f1
From d24316a6b41305f91346e0115ae1f9fe38bff2ce Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Mon, 17 Mar 2025 17:40:29 +0100
Subject: check_disk: clang-format
---
plugins/check_disk.c | 129 ++++++++++++++++++++++++++++++++++-----------------
1 file changed, 86 insertions(+), 43 deletions(-)
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index 037a6f7a..c3534060 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -191,8 +191,9 @@ int main(int argc, char **argv) {
/* Parse extra opts if any */
argv = np_extra_opts(&argc, argv, progname);
- if (process_arguments(argc, argv) == ERROR)
+ if (process_arguments(argc, argv) == ERROR) {
usage4(_("Could not parse arguments"));
+ }
/* If a list of paths has not been selected, find entire
mount list and create list of paths
@@ -245,12 +246,14 @@ int main(int argc, char **argv) {
/* Process for every path in list */
for (path = path_select_list; path; path = path->name_next) {
- if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL)
+ if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL) {
printf("Thresholds(pct) for %s warn: %f crit %f\n", path->name, path->freespace_percent->warning->end,
path->freespace_percent->critical->end);
+ }
- if (verbose >= 3 && path->group != NULL)
+ if (verbose >= 3 && path->group != NULL) {
printf("Group of %s: %s\n", path->name, path->group);
+ }
/* reset disk result */
disk_result = STATE_UNKNOWN;
@@ -262,11 +265,13 @@ int main(int argc, char **argv) {
}
#ifdef __CYGWIN__
- if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11)
+ if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11) {
continue;
+ }
snprintf(mountdir, sizeof(mountdir), "%s:\\", me->me_mountdir + 10);
- if (GetDriveType(mountdir) != DRIVE_FIXED)
+ if (GetDriveType(mountdir) != DRIVE_FIXED) {
me->me_remote = 1;
+ }
#endif
/* Filters */
@@ -327,33 +332,39 @@ int main(int argc, char **argv) {
/* Threshold comparisons */
temp_result = get_status(path->dfree_units, path->freespace_units);
- if (verbose >= 3)
+ if (verbose >= 3) {
printf("Freespace_units result=%d\n", temp_result);
+ }
disk_result = max_state(disk_result, temp_result);
temp_result = get_status(path->dfree_pct, path->freespace_percent);
- if (verbose >= 3)
+ if (verbose >= 3) {
printf("Freespace%% result=%d\n", temp_result);
+ }
disk_result = max_state(disk_result, temp_result);
temp_result = get_status(path->dused_units, path->usedspace_units);
- if (verbose >= 3)
+ if (verbose >= 3) {
printf("Usedspace_units result=%d\n", temp_result);
+ }
disk_result = max_state(disk_result, temp_result);
temp_result = get_status(path->dused_pct, path->usedspace_percent);
- if (verbose >= 3)
+ if (verbose >= 3) {
printf("Usedspace_percent result=%d\n", temp_result);
+ }
disk_result = max_state(disk_result, temp_result);
temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent);
- if (verbose >= 3)
+ if (verbose >= 3) {
printf("Usedinodes_percent result=%d\n", temp_result);
+ }
disk_result = max_state(disk_result, temp_result);
temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent);
- if (verbose >= 3)
+ if (verbose >= 3) {
printf("Freeinodes_percent result=%d\n", temp_result);
+ }
disk_result = max_state(disk_result, temp_result);
result = max_state(result, disk_result);
@@ -414,8 +425,9 @@ int main(int argc, char **argv) {
true, path->inodes_total));
}
- if (disk_result == STATE_OK && erronly && !verbose)
+ if (disk_result == STATE_OK && erronly && !verbose) {
continue;
+ }
if (disk_result && verbose >= 1) {
xasprintf(&flag_header, " %s [", state_text(disk_result));
@@ -434,8 +446,9 @@ int main(int argc, char **argv) {
}
}
- if (verbose >= 2)
+ if (verbose >= 2) {
xasprintf(&output, "%s%s", output, details);
+ }
if (strcmp(output, "") == 0 && !erronly) {
preamble = "";
@@ -509,20 +522,24 @@ int process_arguments(int argc, char **argv) {
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}};
- if (argc < 2)
+ if (argc < 2) {
return ERROR;
+ }
np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED);
- for (c = 1; c < argc; c++)
- if (strcmp("-to", argv[c]) == 0)
+ for (c = 1; c < argc; c++) {
+ if (strcmp("-to", argv[c]) == 0) {
strcpy(argv[c], "-t");
+ }
+ }
while (1) {
c = getopt_long(argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLPg:R:r:i:I:MEAn", longopts, &option);
- if (c == -1 || c == EOF)
+ if (c == -1 || c == EOF) {
break;
+ }
switch (c) {
case 't': /* timeout period */
@@ -594,8 +611,9 @@ int process_arguments(int argc, char **argv) {
}
break;
case 'u':
- if (units)
+ if (units) {
free(units);
+ }
if (!strcasecmp(optarg, "bytes")) {
mult = (uintmax_t)1;
units = strdup("B");
@@ -632,19 +650,22 @@ int process_arguments(int argc, char **argv) {
} else {
die(STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
}
- if (units == NULL)
+ if (units == NULL) {
die(STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units");
+ }
break;
case 'k': /* display mountpoint */
mult = 1024;
- if (units)
+ if (units) {
free(units);
+ }
units = strdup("kiB");
break;
case 'm': /* display mountpoint */
mult = 1024 * 1024;
- if (units)
+ if (units) {
free(units);
+ }
units = strdup("MiB");
break;
case 'L':
@@ -715,25 +736,28 @@ int process_arguments(int argc, char **argv) {
erronly = true;
break;
case 'E':
- if (path_selected)
+ if (path_selected) {
die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n"));
+ }
exact_match = true;
break;
case 'f':
freespace_ignore_reserved = true;
break;
case 'g':
- if (path_selected)
+ if (path_selected) {
die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n"));
+ }
group = optarg;
break;
case 'I':
cflags |= REG_ICASE;
// Intentional fallthrough
case 'i':
- if (!path_selected)
+ 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"));
+ }
err = regcomp(&re, optarg, cflags);
if (err != 0) {
regerror(err, &re, errbuf, MAX_INPUT_BUFFER);
@@ -747,13 +771,15 @@ int process_arguments(int argc, char **argv) {
if (temp_list->best_match) {
if (np_regex_match_mount_entry(temp_list->best_match, &re)) {
- if (verbose >= 3)
+ if (verbose >= 3) {
printf("ignoring %s matching regex\n", temp_list->name);
+ }
temp_list = np_del_parameter(temp_list, previous);
/* pointer to first element needs to be updated if first item gets deleted */
- if (previous == NULL)
+ if (previous == NULL) {
path_select_list = temp_list;
+ }
} else {
previous = temp_list;
temp_list = temp_list->name_next;
@@ -793,8 +819,9 @@ int process_arguments(int argc, char **argv) {
for (me = mount_list; me; me = me->me_next) {
if (np_regex_match_mount_entry(me, &re)) {
fnd = true;
- if (verbose >= 3)
+ if (verbose >= 3) {
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 */
if (!(se = np_find_parameter(path_select_list, me->me_mountdir))) {
@@ -810,8 +837,9 @@ int process_arguments(int argc, char **argv) {
path_selected = true;
break;
}
- if (!fnd)
+ if (!fnd) {
die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Regular expression did not match any path or disk"), optarg);
+ }
fnd = false;
path_selected = true;
@@ -827,8 +855,9 @@ int process_arguments(int argc, char **argv) {
if (path_selected == false) {
struct parameter_list *path;
for (me = mount_list; me; me = me->me_next) {
- if (!(path = np_find_parameter(path_select_list, me->me_mountdir)))
+ if (!(path = np_find_parameter(path_select_list, me->me_mountdir))) {
path = np_add_parameter(&path_select_list, me->me_mountdir);
+ }
path->best_match = me;
path->group = group;
set_all_thresholds(path);
@@ -863,11 +892,13 @@ int process_arguments(int argc, char **argv) {
/* Support for "check_disk warn crit [fs]" with thresholds at used% level */
c = optind;
- if (warn_usedspace_percent == NULL && argc > c && is_intnonneg(argv[c]))
+ if (warn_usedspace_percent == NULL && argc > c && is_intnonneg(argv[c])) {
warn_usedspace_percent = argv[c++];
+ }
- if (crit_usedspace_percent == NULL && argc > c && is_intnonneg(argv[c]))
+ if (crit_usedspace_percent == NULL && argc > c && is_intnonneg(argv[c])) {
crit_usedspace_percent = argv[c++];
+ }
if (argc > c) {
se = np_add_parameter(&path_select_list, strdup(argv[c++]));
@@ -884,23 +915,29 @@ int process_arguments(int argc, char **argv) {
}
void set_all_thresholds(struct parameter_list *path) {
- if (path->freespace_units != NULL)
+ if (path->freespace_units != NULL) {
free(path->freespace_units);
+ }
set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units);
- if (path->freespace_percent != NULL)
+ if (path->freespace_percent != NULL) {
free(path->freespace_percent);
+ }
set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent);
- if (path->usedspace_units != NULL)
+ if (path->usedspace_units != NULL) {
free(path->usedspace_units);
+ }
set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units);
- if (path->usedspace_percent != NULL)
+ if (path->usedspace_percent != NULL) {
free(path->usedspace_percent);
+ }
set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent);
- if (path->usedinodes_percent != NULL)
+ if (path->usedinodes_percent != NULL) {
free(path->usedinodes_percent);
+ }
set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent);
- if (path->freeinodes_percent != NULL)
+ if (path->freeinodes_percent != NULL) {
free(path->freeinodes_percent);
+ }
set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent);
}
@@ -1011,11 +1048,13 @@ void print_usage(void) {
bool stat_path(struct parameter_list *p) {
/* Stat entry to check that dir exists and is accessible */
- if (verbose >= 3)
+ if (verbose >= 3) {
printf("calling stat on %s\n", p->name);
+ }
if (stat(p->name, &stat_buf[0])) {
- if (verbose >= 3)
+ if (verbose >= 3) {
printf("stat failed on %s\n", p->name);
+ }
if (ignore_missing == true) {
return false;
}
@@ -1036,18 +1075,21 @@ void get_stats(struct parameter_list *p, struct fs_usage *fsp) {
/* find all group members */
for (p_list = path_select_list; p_list; p_list = p_list->name_next) {
#ifdef __CYGWIN__
- if (strncmp(p_list->name, "/cygdrive/", 10) != 0)
+ if (strncmp(p_list->name, "/cygdrive/", 10) != 0) {
continue;
+ }
#endif
if (p_list->group && !(strcmp(p_list->group, p->group))) {
- if (!stat_path(p_list))
+ if (!stat_path(p_list)) {
continue;
+ }
get_fs_usage(p_list->best_match->me_mountdir, p_list->best_match->me_devname, &tmpfsp);
get_path_stats(p_list, &tmpfsp);
- if (verbose >= 3)
+ if (verbose >= 3) {
printf("Group %s: adding %lu blocks sized %lu, (%s) used_units=%lu free_units=%lu total_units=%lu mult=%lu\n",
p_list->group, tmpfsp.fsu_blocks, tmpfsp.fsu_blocksize, p_list->best_match->me_mountdir, p_list->dused_units,
p_list->dfree_units, p_list->dtotal_units, mult);
+ }
/* prevent counting the first FS of a group twice since its parameter_list entry
* is used to carry the information of all file systems of the entire group */
@@ -1067,9 +1109,10 @@ void get_stats(struct parameter_list *p, struct fs_usage *fsp) {
}
first = 0;
}
- if (verbose >= 3)
+ if (verbose >= 3) {
printf("Group %s now has: used_units=%lu free_units=%lu total_units=%lu fsu_blocksize=%lu mult=%lu\n", p->group,
p->dused_units, p->dfree_units, p->dtotal_units, tmpfsp.fsu_blocksize, mult);
+ }
}
/* modify devname and mountdir for output */
p->best_match->me_mountdir = p->best_match->me_devname = p->group;
--
cgit v1.2.3-74-g34f1
From 969f40c2a083b4e0654a46e6b9e37a0378a4f332 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Mon, 17 Mar 2025 17:44:28 +0100
Subject: check_disk: boolean type and linter fixes
---
plugins/check_disk.c | 40 ++++++++++++++++++++--------------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index c3534060..b5a375d0 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -62,10 +62,10 @@ const char *email = "devel@monitoring-plugins.org";
static int show_all_fs = 1;
/* If nonzero, show only local filesystems. */
-static int show_local_fs = 0;
+static bool show_local_fs = false;
/* If nonzero, show only local filesystems but call stat() on remote ones. */
-static int stat_remote_fs = 0;
+static bool stat_remote_fs = false;
/* If positive, the units to use when printing sizes;
if negative, the human-readable base. */
@@ -121,7 +121,7 @@ static int process_arguments(int /*argc*/, char ** /*argv*/);
static void set_all_thresholds(struct parameter_list *path);
static void print_help(void);
void print_usage(void);
-static double calculate_percent(uintmax_t, uintmax_t);
+static double calculate_percent(uintmax_t /*value*/, uintmax_t /*total*/);
static bool stat_path(struct parameter_list *p);
static void get_stats(struct parameter_list *p, struct fs_usage *fsp);
static void get_path_stats(struct parameter_list *p, struct fs_usage *fsp);
@@ -198,7 +198,7 @@ int main(int argc, char **argv) {
/* If a list of paths has not been selected, find entire
mount list and create list of paths
*/
- if (path_selected == false && path_ignored == false) {
+ if (!path_selected && !path_ignored) {
for (me = mount_list; me; me = me->me_next) {
if (!(path = np_find_parameter(path_select_list, me->me_mountdir))) {
path = np_add_parameter(&path_select_list, me->me_mountdir);
@@ -209,7 +209,7 @@ int main(int argc, char **argv) {
}
}
- if (path_ignored == false) {
+ if (!path_ignored) {
np_set_best_match(path_select_list, mount_list, exact_match);
}
@@ -217,7 +217,7 @@ int main(int argc, char **argv) {
temp_list = path_select_list;
while (path_select_list) {
- if (!path_select_list->best_match && ignore_missing == true) {
+ if (!path_select_list->best_match && ignore_missing) {
/* If the first element will be deleted, the temp_list must be updated with the new start address as well */
if (path_select_list == temp_list) {
temp_list = path_select_list->name_next;
@@ -237,7 +237,7 @@ int main(int argc, char **argv) {
path_select_list = temp_list;
- if (!path_select_list && ignore_missing == true) {
+ if (!path_select_list && ignore_missing) {
result = STATE_OK;
if (verbose >= 2) {
printf("None of the provided paths were found\n");
@@ -285,7 +285,7 @@ int main(int argc, char **argv) {
/* Skip remote filesystems if we're not interested in them */
if (me->me_remote && show_local_fs) {
if (stat_remote_fs) {
- if (!stat_path(path) && ignore_missing == true) {
+ if (!stat_path(path) && ignore_missing) {
result = STATE_OK;
xasprintf(&ignored, "%s %s;", ignored, path->name);
}
@@ -311,7 +311,7 @@ int main(int argc, char **argv) {
}
if (!stat_path(path)) {
- if (ignore_missing == true) {
+ if (ignore_missing) {
result = STATE_OK;
xasprintf(&ignored, "%s %s;", ignored, path->name);
}
@@ -398,8 +398,8 @@ int main(int argc, char **argv) {
/* Nb: *_high_tide are unset when == UINT64_MAX */
xasprintf(&perf, "%s %s", perf,
perfdata_uint64((!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
- path->dused_units * mult, "B", (warning_high_tide == UINT64_MAX ? false : true), warning_high_tide,
- (critical_high_tide == UINT64_MAX ? false : true), critical_high_tide, true, 0, true,
+ path->dused_units * mult, "B", (warning_high_tide != UINT64_MAX ), warning_high_tide,
+ (critical_high_tide != UINT64_MAX ), critical_high_tide, true, 0, true,
path->dtotal_units * mult));
if (display_inodes_perfdata) {
@@ -420,8 +420,8 @@ int main(int argc, char **argv) {
(!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir);
/* Nb: *_high_tide are unset when == UINT64_MAX */
xasprintf(&perf, "%s %s", perf,
- perfdata_uint64(perf_ilabel, path->inodes_used, "", (warning_high_tide != UINT64_MAX ? true : false),
- warning_high_tide, (critical_high_tide != UINT64_MAX ? true : false), critical_high_tide, true, 0,
+ perfdata_uint64(perf_ilabel, path->inodes_used, "", (warning_high_tide != UINT64_MAX),
+ warning_high_tide, (critical_high_tide != UINT64_MAX), critical_high_tide, true, 0,
true, path->inodes_total));
}
@@ -669,13 +669,13 @@ int process_arguments(int argc, char **argv) {
units = strdup("MiB");
break;
case 'L':
- stat_remote_fs = 1;
+ stat_remote_fs = true;
/* fallthrough */
case 'l':
- show_local_fs = 1;
+ show_local_fs = true;
break;
case 'P':
- display_inodes_perfdata = 1;
+ display_inodes_perfdata = true;
break;
case 'p': /* select path */
if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || crit_freespace_percent ||
@@ -688,7 +688,7 @@ int process_arguments(int argc, char **argv) {
if (!(se = np_find_parameter(path_select_list, optarg))) {
se = np_add_parameter(&path_select_list, optarg);
- if (stat(optarg, &stat_buf[0]) && ignore_missing == true) {
+ if (stat(optarg, &stat_buf[0]) && ignore_missing) {
path_ignored = true;
break;
}
@@ -832,7 +832,7 @@ int process_arguments(int argc, char **argv) {
}
}
- if (!fnd && ignore_missing == true) {
+ if (!fnd && ignore_missing) {
path_ignored = true;
path_selected = true;
break;
@@ -852,7 +852,7 @@ int process_arguments(int argc, char **argv) {
break;
case 'C':
/* add all mount entries to path_select list if no partitions have been explicitly defined using -p */
- if (path_selected == false) {
+ if (!path_selected) {
struct parameter_list *path;
for (me = mount_list; me; me = me->me_next) {
if (!(path = np_find_parameter(path_select_list, me->me_mountdir))) {
@@ -1055,7 +1055,7 @@ bool stat_path(struct parameter_list *p) {
if (verbose >= 3) {
printf("stat failed on %s\n", p->name);
}
- if (ignore_missing == true) {
+ if (ignore_missing) {
return false;
}
printf("DISK %s - ", _("CRITICAL"));
--
cgit v1.2.3-74-g34f1
From 4fb7fb05b672febfdfa69381f7f403dc872c7aa6 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Mon, 17 Mar 2025 19:36:11 +0100
Subject: check_disk: General refactoring
---
plugins/check_disk.c | 353 +++++++++++++++++++++++----------------------------
1 file changed, 158 insertions(+), 195 deletions(-)
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index b5a375d0..e16c453d 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -31,13 +31,17 @@ const char *program_name = "check_disk"; /* Required for coreutils libs */
const char *copyright = "1999-2024";
const char *email = "devel@monitoring-plugins.org";
+#include "states.h"
#include "common.h"
+
#ifdef HAVE_SYS_STAT_H
# include
#endif
+
#if HAVE_INTTYPES_H
# include
#endif
+
#include
#include "popen.h"
#include "utils.h"
@@ -46,9 +50,11 @@ const char *email = "devel@monitoring-plugins.org";
#include "fsusage.h"
#include "mountlist.h"
#include
+
#if HAVE_LIMITS_H
# include
#endif
+
#include "regex.h"
#ifdef __CYGWIN__
@@ -57,39 +63,12 @@ const char *email = "devel@monitoring-plugins.org";
# define ERROR -1
#endif
-/* If nonzero, show even filesystems with zero size or
- uninteresting types. */
-static int show_all_fs = 1;
-
/* If nonzero, show only local filesystems. */
static bool show_local_fs = false;
/* If nonzero, show only local filesystems but call stat() on remote ones. */
static bool stat_remote_fs = false;
-/* If positive, the units to use when printing sizes;
- if negative, the human-readable base. */
-/* static int output_block_size; */
-
-/* If nonzero, invoke the `sync' system call before getting any usage data.
- Using this option can make df very slow, especially with many or very
- busy disks. Note that this may make a difference on some systems --
- SunOs4.1.3, for one. It is *not* necessary on Linux. */
-/* static int require_sync = 0; */
-
-/* Linked list of filesystem types to display.
- If `fs_select_list' is NULL, list all types.
- This table is generated dynamically from command-line options,
- rather than hardcoding into the program what it thinks are the
- valid filesystem types; let the user specify any filesystem type
- they want to, and if there are any filesystems of that type, they
- will be shown.
-
- Some filesystem types:
- 4.2 4.3 ufs nfs swap ignore io vm efs dbg */
-
-/* static struct parameter_list *fs_select_list; */
-
/* Linked list of filesystem types to omit.
If the list is empty, don't exclude any types. */
static struct regex_list *fs_exclude_list = NULL;
@@ -150,43 +129,18 @@ static char *crit_freeinodes_percent = NULL;
static bool path_selected = false;
static bool path_ignored = false;
static char *group = NULL;
-static struct stat *stat_buf;
static struct name_list *seen = NULL;
int main(int argc, char **argv) {
- int result = STATE_UNKNOWN;
- int disk_result = STATE_UNKNOWN;
- char *output = NULL;
- char *ignored = NULL;
- char *details = NULL;
- char *perf = NULL;
- char *perf_ilabel = NULL;
- char *preamble = " - free space:";
- char *ignored_preamble = " - ignored paths:";
- char *flag_header = NULL;
- int temp_result = STATE_UNKNOWN;
-
- struct mount_entry *me = NULL;
- struct fs_usage fsp = {0};
- struct parameter_list *temp_list = NULL;
- struct parameter_list *path = NULL;
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
#ifdef __CYGWIN__
char mountdir[32];
#endif
- output = strdup("");
- ignored = strdup("");
- details = strdup("");
- perf = strdup("");
- perf_ilabel = strdup("");
- stat_buf = malloc(sizeof *stat_buf);
-
- setlocale(LC_ALL, "");
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
-
- mount_list = read_file_system_list(0);
+ mount_list = read_file_system_list(false);
/* Parse extra opts if any */
argv = np_extra_opts(&argc, argv, progname);
@@ -199,7 +153,8 @@ int main(int argc, char **argv) {
mount list and create list of paths
*/
if (!path_selected && !path_ignored) {
- for (me = mount_list; me; me = me->me_next) {
+ for (struct mount_entry *me = mount_list; me; me = me->me_next) {
+ struct parameter_list *path = NULL;
if (!(path = np_find_parameter(path_select_list, me->me_mountdir))) {
path = np_add_parameter(&path_select_list, me->me_mountdir);
}
@@ -214,8 +169,9 @@ int main(int argc, char **argv) {
}
/* Error if no match found for specified paths */
- temp_list = path_select_list;
+ struct parameter_list *temp_list = path_select_list;
+ char *ignored = strdup("");
while (path_select_list) {
if (!path_select_list->best_match && ignore_missing) {
/* If the first element will be deleted, the temp_list must be updated with the new start address as well */
@@ -237,6 +193,7 @@ int main(int argc, char **argv) {
path_select_list = temp_list;
+ int result = STATE_UNKNOWN;
if (!path_select_list && ignore_missing) {
result = STATE_OK;
if (verbose >= 2) {
@@ -244,6 +201,11 @@ int main(int argc, char **argv) {
}
}
+ mp_state_enum disk_result = STATE_UNKNOWN;
+ char *perf = strdup("");
+ char *perf_ilabel = strdup("");
+ char *output = strdup("");
+ struct parameter_list *path = NULL;
/* Process for every path in list */
for (path = path_select_list; path; path = path->name_next) {
if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL) {
@@ -255,12 +217,9 @@ int main(int argc, char **argv) {
printf("Group of %s: %s\n", path->name, path->group);
}
- /* reset disk result */
- disk_result = STATE_UNKNOWN;
+ struct mount_entry *mount_entry = path->best_match;
- me = path->best_match;
-
- if (!me) {
+ if (!mount_entry) {
continue;
}
@@ -276,14 +235,14 @@ int main(int argc, char **argv) {
/* Filters */
/* Remove filesystems already seen */
- if (np_seen_name(seen, me->me_mountdir)) {
+ if (np_seen_name(seen, mount_entry->me_mountdir)) {
continue;
}
- np_add_name(&seen, me->me_mountdir);
+ np_add_name(&seen, mount_entry->me_mountdir);
if (path->group == NULL) {
/* Skip remote filesystems if we're not interested in them */
- if (me->me_remote && show_local_fs) {
+ if (mount_entry->me_remote && show_local_fs) {
if (stat_remote_fs) {
if (!stat_path(path) && ignore_missing) {
result = STATE_OK;
@@ -293,19 +252,16 @@ int main(int argc, char **argv) {
continue;
/* Skip pseudo fs's if we haven't asked for all fs's */
}
- if (me->me_dummy && !show_all_fs) {
- continue;
- /* Skip excluded fstypes */
- }
- if (fs_exclude_list && np_find_regmatch(fs_exclude_list, me->me_type)) {
+ if (fs_exclude_list && np_find_regmatch(fs_exclude_list, mount_entry->me_type)) {
continue;
/* Skip excluded fs's */
}
- if (dp_exclude_list && (np_find_name(dp_exclude_list, me->me_devname) || np_find_name(dp_exclude_list, me->me_mountdir))) {
+ if (dp_exclude_list &&
+ (np_find_name(dp_exclude_list, mount_entry->me_devname) || np_find_name(dp_exclude_list, mount_entry->me_mountdir))) {
continue;
/* Skip not included fstypes */
}
- if (fs_include_list && !np_find_regmatch(fs_include_list, me->me_type)) {
+ if (fs_include_list && !np_find_regmatch(fs_include_list, mount_entry->me_type)) {
continue;
}
}
@@ -317,21 +273,23 @@ int main(int argc, char **argv) {
}
continue;
}
- get_fs_usage(me->me_mountdir, me->me_devname, &fsp);
- if (fsp.fsu_blocks && strcmp("none", me->me_mountdir)) {
+ struct fs_usage fsp = {0};
+ get_fs_usage(mount_entry->me_mountdir, mount_entry->me_devname, &fsp);
+
+ if (fsp.fsu_blocks && strcmp("none", mount_entry->me_mountdir)) {
get_stats(path, &fsp);
if (verbose >= 3) {
printf("For %s, used_pct=%f free_pct=%f used_units=%lu free_units=%lu total_units=%lu used_inodes_pct=%f "
"free_inodes_pct=%f fsp.fsu_blocksize=%lu mult=%lu\n",
- me->me_mountdir, path->dused_pct, path->dfree_pct, path->dused_units, path->dfree_units, path->dtotal_units,
+ mount_entry->me_mountdir, path->dused_pct, path->dfree_pct, path->dused_units, path->dfree_units, path->dtotal_units,
path->dused_inodes_percent, path->dfree_inodes_percent, fsp.fsu_blocksize, mult);
}
/* Threshold comparisons */
- temp_result = get_status(path->dfree_units, path->freespace_units);
+ mp_state_enum temp_result = get_status(path->dfree_units, path->freespace_units);
if (verbose >= 3) {
printf("Freespace_units result=%d\n", temp_result);
}
@@ -397,10 +355,10 @@ int main(int argc, char **argv) {
/* Nb: *_high_tide are unset when == UINT64_MAX */
xasprintf(&perf, "%s %s", perf,
- perfdata_uint64((!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir,
- path->dused_units * mult, "B", (warning_high_tide != UINT64_MAX ), warning_high_tide,
- (critical_high_tide != UINT64_MAX ), critical_high_tide, true, 0, true,
- path->dtotal_units * mult));
+ perfdata_uint64((!strcmp(mount_entry->me_mountdir, "none") || display_mntp) ? mount_entry->me_devname
+ : mount_entry->me_mountdir,
+ path->dused_units * mult, "B", (warning_high_tide != UINT64_MAX), warning_high_tide,
+ (critical_high_tide != UINT64_MAX), critical_high_tide, true, 0, true, path->dtotal_units * mult));
if (display_inodes_perfdata) {
/* *_high_tide must be reinitialized at each run */
@@ -417,26 +375,26 @@ int main(int argc, char **argv) {
}
xasprintf(&perf_ilabel, "%s (inodes)",
- (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir);
+ (!strcmp(mount_entry->me_mountdir, "none") || display_mntp) ? mount_entry->me_devname : mount_entry->me_mountdir);
/* Nb: *_high_tide are unset when == UINT64_MAX */
xasprintf(&perf, "%s %s", perf,
- perfdata_uint64(perf_ilabel, path->inodes_used, "", (warning_high_tide != UINT64_MAX),
- warning_high_tide, (critical_high_tide != UINT64_MAX), critical_high_tide, true, 0,
- true, path->inodes_total));
+ perfdata_uint64(perf_ilabel, path->inodes_used, "", (warning_high_tide != UINT64_MAX), warning_high_tide,
+ (critical_high_tide != UINT64_MAX), critical_high_tide, true, 0, true, path->inodes_total));
}
if (disk_result == STATE_OK && erronly && !verbose) {
continue;
}
+ char *flag_header = NULL;
if (disk_result && verbose >= 1) {
xasprintf(&flag_header, " %s [", state_text(disk_result));
} else {
xasprintf(&flag_header, "");
}
xasprintf(&output, "%s%s %s %llu%s (%.1f%%", output, flag_header,
- (!strcmp(me->me_mountdir, "none") || display_mntp) ? me->me_devname : me->me_mountdir, path->dfree_units, units,
- path->dfree_pct);
+ (!strcmp(mount_entry->me_mountdir, "none") || display_mntp) ? mount_entry->me_devname : mount_entry->me_mountdir,
+ path->dfree_units, units, path->dfree_pct);
if (path->dused_inodes_percent < 0) {
xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : ""));
} else {
@@ -446,15 +404,13 @@ int main(int argc, char **argv) {
}
}
- if (verbose >= 2) {
- xasprintf(&output, "%s%s", output, details);
- }
-
+ char *preamble = " - free space:";
if (strcmp(output, "") == 0 && !erronly) {
preamble = "";
xasprintf(&output, " - No disks were found for provided parameters");
}
+ char *ignored_preamble = " - ignored paths:";
printf("DISK %s%s%s%s%s|%s\n", state_text(result), ((erronly && result == STATE_OK)) ? "" : preamble, output,
(strcmp(ignored, "") == 0) ? "" : ignored_preamble, ignored, perf);
return result;
@@ -470,19 +426,10 @@ double calculate_percent(uintmax_t value, uintmax_t total) {
/* process command-line arguments */
int process_arguments(int argc, char **argv) {
- int c;
- int err;
- struct parameter_list *se;
- struct parameter_list *temp_list = NULL;
- struct parameter_list *previous = NULL;
- struct mount_entry *me;
- regex_t re;
- int cflags = REG_NOSUB | REG_EXTENDED;
- int default_cflags = cflags;
- char errbuf[MAX_INPUT_BUFFER];
- int fnd = 0;
+ if (argc < 2) {
+ return ERROR;
+ }
- int option = 0;
static struct option longopts[] = {{"timeout", required_argument, 0, 't'},
{"warning", required_argument, 0, 'w'},
{"critical", required_argument, 0, 'c'},
@@ -522,26 +469,26 @@ int process_arguments(int argc, char **argv) {
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}};
- if (argc < 2) {
- return ERROR;
+ for (int index = 1; index < argc; index++) {
+ if (strcmp("-to", argv[index]) == 0) {
+ strcpy(argv[index], "-t");
+ }
}
- np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED);
+ int cflags = REG_NOSUB | REG_EXTENDED;
+ int default_cflags = cflags;
- for (c = 1; c < argc; c++) {
- if (strcmp("-to", argv[c]) == 0) {
- strcpy(argv[c], "-t");
- }
- }
+ np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED);
- while (1) {
- c = getopt_long(argc, argv, "+?VqhvefCt:c:w:K:W:u:p:x:X:N:mklLPg:R:r:i:I:MEAn", longopts, &option);
+ 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);
- if (c == -1 || c == EOF) {
+ if (option_index == -1 || option_index == EOF) {
break;
}
- switch (c) {
+ switch (option_index) {
case 't': /* timeout period */
if (is_integer(optarg)) {
timeout_interval = atoi(optarg);
@@ -685,10 +632,12 @@ int process_arguments(int argc, char **argv) {
}
/* add parameter if not found. overwrite thresholds if path has already been added */
+ struct parameter_list *se;
if (!(se = np_find_parameter(path_select_list, optarg))) {
se = np_add_parameter(&path_select_list, optarg);
- if (stat(optarg, &stat_buf[0]) && ignore_missing) {
+ struct stat stat_buf = {};
+ if (stat(optarg, &stat_buf) && ignore_missing) {
path_ignored = true;
break;
}
@@ -703,7 +652,7 @@ int process_arguments(int argc, char **argv) {
/* NB: We can't free the old mount_list "just like that": both list pointers and struct
* pointers are copied around. One of the reason it wasn't done yet is that other parts
* of check_disk need the same kind of cleanup so it'd better be done as a whole */
- mount_list = read_file_system_list(0);
+ mount_list = read_file_system_list(false);
np_set_best_match(se, mount_list, exact_match);
path_selected = true;
@@ -711,9 +660,10 @@ int process_arguments(int argc, char **argv) {
case 'x': /* exclude path or partition */
np_add_name(&dp_exclude_list, optarg);
break;
- case 'X': /* exclude file system type */
- err = np_add_regex(&fs_exclude_list, optarg, REG_EXTENDED);
+ case 'X': /* exclude file system type */ {
+ int err = np_add_regex(&fs_exclude_list, optarg, REG_EXTENDED);
if (err != 0) {
+ char errbuf[MAX_INPUT_BUFFER];
regerror(err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
}
@@ -721,10 +671,11 @@ int process_arguments(int argc, char **argv) {
case 'N': /* include file system type */
err = np_add_regex(&fs_include_list, optarg, REG_EXTENDED);
if (err != 0) {
+ char errbuf[MAX_INPUT_BUFFER];
regerror(err, &fs_exclude_list->regex, errbuf, MAX_INPUT_BUFFER);
die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
}
- break;
+ } break;
case 'v': /* verbose */
verbose++;
break;
@@ -753,23 +704,24 @@ int process_arguments(int argc, char **argv) {
case 'I':
cflags |= REG_ICASE;
// Intentional fallthrough
- case 'i':
+ 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"));
}
- err = regcomp(&re, optarg, cflags);
+ regex_t regex;
+ int err = regcomp(®ex, optarg, cflags);
if (err != 0) {
- regerror(err, &re, errbuf, MAX_INPUT_BUFFER);
+ 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);
}
- temp_list = path_select_list;
-
- previous = NULL;
+ struct parameter_list *temp_list = path_select_list;
+ struct parameter_list *previous = NULL;
while (temp_list) {
if (temp_list->best_match) {
- if (np_regex_match_mount_entry(temp_list->best_match, &re)) {
+ if (np_regex_match_mount_entry(temp_list->best_match, ®ex)) {
if (verbose >= 3) {
printf("ignoring %s matching regex\n", temp_list->name);
@@ -791,8 +743,7 @@ int process_arguments(int argc, char **argv) {
}
cflags = default_cflags;
- break;
-
+ } break;
case 'n':
ignore_missing = true;
break;
@@ -802,7 +753,7 @@ int process_arguments(int argc, char **argv) {
case 'R':
cflags |= REG_ICASE;
// Intentional fallthrough
- case 'r':
+ case 'r': {
if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || crit_freespace_percent ||
warn_usedspace_units || crit_usedspace_units || warn_usedspace_percent || crit_usedspace_percent ||
warn_usedinodes_percent || crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent)) {
@@ -810,15 +761,18 @@ int process_arguments(int argc, char **argv) {
_("Must set a threshold value before using -r/-R/-A (--ereg-path/--eregi-path/--all)\n"));
}
- err = regcomp(&re, optarg, cflags);
+ regex_t regex;
+ int err = regcomp(®ex, optarg, cflags);
if (err != 0) {
- regerror(err, &re, errbuf, MAX_INPUT_BUFFER);
+ 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);
}
- for (me = mount_list; me; me = me->me_next) {
- if (np_regex_match_mount_entry(me, &re)) {
- fnd = true;
+ bool found = false;
+ for (struct mount_entry *me = mount_list; me; me = me->me_next) {
+ 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);
}
@@ -832,21 +786,21 @@ int process_arguments(int argc, char **argv) {
}
}
- if (!fnd && ignore_missing) {
+ if (!found && ignore_missing) {
path_ignored = true;
path_selected = true;
break;
}
- if (!fnd) {
+ if (!found) {
die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Regular expression did not match any path or disk"), optarg);
}
- fnd = false;
+ found = false;
path_selected = true;
np_set_best_match(path_select_list, mount_list, exact_match);
cflags = default_cflags;
- break;
+ } break;
case 'M': /* display mountpoint */
display_mntp = true;
break;
@@ -854,7 +808,7 @@ int process_arguments(int argc, char **argv) {
/* add all mount entries to path_select list if no partitions have been explicitly defined using -p */
if (!path_selected) {
struct parameter_list *path;
- for (me = mount_list; me; me = me->me_next) {
+ for (struct mount_entry *me = mount_list; me; me = me->me_next) {
if (!(path = np_find_parameter(path_select_list, me->me_mountdir))) {
path = np_add_parameter(&path_select_list, me->me_mountdir);
}
@@ -891,17 +845,17 @@ int process_arguments(int argc, char **argv) {
}
/* Support for "check_disk warn crit [fs]" with thresholds at used% level */
- c = optind;
- if (warn_usedspace_percent == NULL && argc > c && is_intnonneg(argv[c])) {
- warn_usedspace_percent = argv[c++];
+ int index = optind;
+ if (warn_usedspace_percent == NULL && argc > index && is_intnonneg(argv[index])) {
+ warn_usedspace_percent = argv[index++];
}
- if (crit_usedspace_percent == NULL && argc > c && is_intnonneg(argv[c])) {
- crit_usedspace_percent = argv[c++];
+ if (crit_usedspace_percent == NULL && argc > index && is_intnonneg(argv[index])) {
+ crit_usedspace_percent = argv[index++];
}
- if (argc > c) {
- se = np_add_parameter(&path_select_list, strdup(argv[c++]));
+ if (argc > index) {
+ struct parameter_list *se = np_add_parameter(&path_select_list, strdup(argv[index++]));
path_selected = true;
set_all_thresholds(se);
}
@@ -911,7 +865,7 @@ int process_arguments(int argc, char **argv) {
mult = (uintmax_t)1024 * 1024;
}
- return true;
+ return 0;
}
void set_all_thresholds(struct parameter_list *path) {
@@ -919,22 +873,27 @@ void set_all_thresholds(struct parameter_list *path) {
free(path->freespace_units);
}
set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units);
+
if (path->freespace_percent != NULL) {
free(path->freespace_percent);
}
set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent);
+
if (path->usedspace_units != NULL) {
free(path->usedspace_units);
}
set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units);
+
if (path->usedspace_percent != NULL) {
free(path->usedspace_percent);
}
set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent);
+
if (path->usedinodes_percent != NULL) {
free(path->usedinodes_percent);
}
set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent);
+
if (path->freeinodes_percent != NULL) {
free(path->freeinodes_percent);
}
@@ -1046,40 +1005,44 @@ void print_usage(void) {
printf("[-t timeout] [-u unit] [-v] [-X type_regex] [-N type]\n");
}
-bool stat_path(struct parameter_list *p) {
+bool stat_path(struct parameter_list *parameters) {
/* Stat entry to check that dir exists and is accessible */
if (verbose >= 3) {
- printf("calling stat on %s\n", p->name);
+ printf("calling stat on %s\n", parameters->name);
}
- if (stat(p->name, &stat_buf[0])) {
+
+ struct stat stat_buf = {0};
+ if (stat(parameters->name, &stat_buf)) {
if (verbose >= 3) {
- printf("stat failed on %s\n", p->name);
+ printf("stat failed on %s\n", parameters->name);
}
if (ignore_missing) {
return false;
}
printf("DISK %s - ", _("CRITICAL"));
- die(STATE_CRITICAL, _("%s %s: %s\n"), p->name, _("is not accessible"), strerror(errno));
+ die(STATE_CRITICAL, _("%s %s: %s\n"), parameters->name, _("is not accessible"), strerror(errno));
}
+
return true;
}
-void get_stats(struct parameter_list *p, struct fs_usage *fsp) {
- struct parameter_list *p_list;
+void get_stats(struct parameter_list *parameters, struct fs_usage *fsp) {
struct fs_usage tmpfsp;
- int first = 1;
+ bool first = true;
- if (p->group == NULL) {
- get_path_stats(p, fsp);
+ if (parameters->group == NULL) {
+ get_path_stats(parameters, fsp);
} else {
/* find all group members */
- for (p_list = path_select_list; p_list; p_list = p_list->name_next) {
+ for (struct parameter_list *p_list = path_select_list; p_list; p_list = p_list->name_next) {
+
#ifdef __CYGWIN__
if (strncmp(p_list->name, "/cygdrive/", 10) != 0) {
continue;
}
#endif
- if (p_list->group && !(strcmp(p_list->group, p->group))) {
+
+ if (p_list->group && !(strcmp(p_list->group, parameters->group))) {
if (!stat_path(p_list)) {
continue;
}
@@ -1094,63 +1057,63 @@ void get_stats(struct parameter_list *p, struct fs_usage *fsp) {
/* prevent counting the first FS of a group twice since its parameter_list entry
* is used to carry the information of all file systems of the entire group */
if (!first) {
- p->total += p_list->total;
- p->available += p_list->available;
- p->available_to_root += p_list->available_to_root;
- p->used += p_list->used;
-
- p->dused_units += p_list->dused_units;
- p->dfree_units += p_list->dfree_units;
- p->dtotal_units += p_list->dtotal_units;
- p->inodes_total += p_list->inodes_total;
- p->inodes_free += p_list->inodes_free;
- p->inodes_free_to_root += p_list->inodes_free_to_root;
- p->inodes_used += p_list->inodes_used;
+ parameters->total += p_list->total;
+ parameters->available += p_list->available;
+ parameters->available_to_root += p_list->available_to_root;
+ parameters->used += p_list->used;
+
+ parameters->dused_units += p_list->dused_units;
+ parameters->dfree_units += p_list->dfree_units;
+ parameters->dtotal_units += p_list->dtotal_units;
+ parameters->inodes_total += p_list->inodes_total;
+ parameters->inodes_free += p_list->inodes_free;
+ parameters->inodes_free_to_root += p_list->inodes_free_to_root;
+ parameters->inodes_used += p_list->inodes_used;
}
- first = 0;
+ first = false;
}
if (verbose >= 3) {
- printf("Group %s now has: used_units=%lu free_units=%lu total_units=%lu fsu_blocksize=%lu mult=%lu\n", p->group,
- p->dused_units, p->dfree_units, p->dtotal_units, tmpfsp.fsu_blocksize, mult);
+ printf("Group %s now has: used_units=%lu free_units=%lu total_units=%lu fsu_blocksize=%lu mult=%lu\n", parameters->group,
+ parameters->dused_units, parameters->dfree_units, parameters->dtotal_units, tmpfsp.fsu_blocksize, mult);
}
}
/* modify devname and mountdir for output */
- p->best_match->me_mountdir = p->best_match->me_devname = p->group;
+ parameters->best_match->me_mountdir = parameters->best_match->me_devname = parameters->group;
}
/* finally calculate percentages for either plain FS or summed up group */
- p->dused_pct = calculate_percent(p->used, p->used + p->available); /* used + available can never be > uintmax */
- p->dfree_pct = 100.0 - p->dused_pct;
- p->dused_inodes_percent = calculate_percent(p->inodes_total - p->inodes_free, p->inodes_total);
- p->dfree_inodes_percent = 100 - p->dused_inodes_percent;
+ parameters->dused_pct = calculate_percent(parameters->used, parameters->used + parameters->available); /* used + available can never be > uintmax */
+ parameters->dfree_pct = 100.0 - parameters->dused_pct;
+ parameters->dused_inodes_percent = calculate_percent(parameters->inodes_total - parameters->inodes_free, parameters->inodes_total);
+ parameters->dfree_inodes_percent = 100 - parameters->dused_inodes_percent;
}
-void get_path_stats(struct parameter_list *p, struct fs_usage *fsp) {
- p->available = fsp->fsu_bavail;
- p->available_to_root = fsp->fsu_bfree;
- p->used = fsp->fsu_blocks - fsp->fsu_bfree;
+void get_path_stats(struct parameter_list *parameters, struct fs_usage *fsp) {
+ parameters->available = fsp->fsu_bavail;
+ parameters->available_to_root = fsp->fsu_bfree;
+ parameters->used = fsp->fsu_blocks - fsp->fsu_bfree;
if (freespace_ignore_reserved) {
/* option activated : we subtract the root-reserved space from the total */
- p->total = fsp->fsu_blocks - p->available_to_root + p->available;
+ parameters->total = fsp->fsu_blocks - parameters->available_to_root + parameters->available;
} else {
/* default behaviour : take all the blocks into account */
- p->total = fsp->fsu_blocks;
+ parameters->total = fsp->fsu_blocks;
}
- p->dused_units = p->used * fsp->fsu_blocksize / mult;
- p->dfree_units = p->available * fsp->fsu_blocksize / mult;
- p->dtotal_units = p->total * fsp->fsu_blocksize / mult;
+ parameters->dused_units = parameters->used * fsp->fsu_blocksize / mult;
+ parameters->dfree_units = parameters->available * fsp->fsu_blocksize / mult;
+ parameters->dtotal_units = parameters->total * fsp->fsu_blocksize / mult;
/* Free file nodes. Not sure the workaround is required, but in case...*/
- p->inodes_free = fsp->fsu_ffree;
- p->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */
- p->inodes_used = fsp->fsu_files - fsp->fsu_ffree;
+ parameters->inodes_free = fsp->fsu_ffree;
+ parameters->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */
+ parameters->inodes_used = fsp->fsu_files - fsp->fsu_ffree;
if (freespace_ignore_reserved) {
/* 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 */
- p->inodes_total = fsp->fsu_files - p->inodes_free_to_root + p->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 */
- p->inodes_total = fsp->fsu_files;
+ parameters->inodes_total = fsp->fsu_files;
}
- np_add_name(&seen, p->best_match->me_mountdir);
+ np_add_name(&seen, parameters->best_match->me_mountdir);
}
--
cgit v1.2.3-74-g34f1
From ef3045b97eea23a4dec3197277e5ff4e5afc5c71 Mon Sep 17 00:00:00 2001
From: Andre Klärner
Date: Mon, 17 Mar 2025 16:13:46 +0100
Subject: change error message for missing certificate
The old error message is quite similar to the openssl `failed to retrieve issuer certificate` and can mislead users to troubleshooting certificate stores.
The new message should be distinct enough to make it clear to users that this is not a problem raised by the underlying SSL implementation, but a problem inside monitoring-plugins.
---
plugins/sslutils.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/sslutils.c b/plugins/sslutils.c
index 719de575..96740b3a 100644
--- a/plugins/sslutils.c
+++ b/plugins/sslutils.c
@@ -201,7 +201,7 @@ int np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, int
time_t tm_t;
if (!certificate) {
- printf("%s\n", _("CRITICAL - Cannot retrieve server certificate."));
+ printf("%s\n", _("CRITICAL - No server certificate present to inspect."));
return STATE_CRITICAL;
}
--
cgit v1.2.3-74-g34f1
From 7b53cbbd265ed135941bf59da77ed22b8664b6eb Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Mon, 17 Mar 2025 20:21:58 +0100
Subject: check_disk: Little fixes and improvements
---
plugins/check_disk.c | 31 +++++++++++++++++++++++--------
1 file changed, 23 insertions(+), 8 deletions(-)
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index e16c453d..a333a8b5 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -101,9 +101,9 @@ static void set_all_thresholds(struct parameter_list *path);
static void print_help(void);
void print_usage(void);
static double calculate_percent(uintmax_t /*value*/, uintmax_t /*total*/);
-static bool stat_path(struct parameter_list *p);
-static void get_stats(struct parameter_list *p, struct fs_usage *fsp);
-static void get_path_stats(struct parameter_list *p, struct fs_usage *fsp);
+static bool stat_path(struct parameter_list * /*parameters*/);
+static void get_stats(struct parameter_list * /*parameters*/, struct fs_usage *fsp);
+static void get_path_stats(struct parameter_list * /*parameters*/, struct fs_usage *fsp);
static char *units;
static uintmax_t mult = 1024 * 1024;
@@ -624,7 +624,7 @@ int process_arguments(int argc, char **argv) {
case 'P':
display_inodes_perfdata = true;
break;
- case 'p': /* select path */
+ case 'p': /* select path */ {
if (!(warn_freespace_units || crit_freespace_units || warn_freespace_percent || crit_freespace_percent ||
warn_usedspace_units || crit_usedspace_units || warn_usedspace_percent || crit_usedspace_percent ||
warn_usedinodes_percent || crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent)) {
@@ -656,7 +656,7 @@ int process_arguments(int argc, char **argv) {
np_set_best_match(se, mount_list, exact_match);
path_selected = true;
- break;
+ } break;
case 'x': /* exclude path or partition */
np_add_name(&dp_exclude_list, optarg);
break;
@@ -778,6 +778,7 @@ int process_arguments(int argc, char **argv) {
}
/* add parameter if not found. overwrite thresholds if path has already been added */
+ struct parameter_list *se = NULL;
if (!(se = np_find_parameter(path_select_list, me->me_mountdir))) {
se = np_add_parameter(&path_select_list, me->me_mountdir);
}
@@ -804,7 +805,7 @@ int process_arguments(int argc, char **argv) {
case 'M': /* display mountpoint */
display_mntp = true;
break;
- case 'C':
+ case 'C': {
/* add all mount entries to path_select list if no partitions have been explicitly defined using -p */
if (!path_selected) {
struct parameter_list *path;
@@ -832,7 +833,7 @@ int process_arguments(int argc, char **argv) {
path_selected = false;
group = NULL;
- break;
+ } break;
case 'V': /* version */
print_revision(progname, NP_VERSION);
exit(STATE_UNKNOWN);
@@ -843,18 +844,31 @@ int process_arguments(int argc, char **argv) {
usage(_("Unknown argument"));
}
}
+ if (verbose > 0) {
+ printf("ping\n");
+ }
/* Support for "check_disk warn crit [fs]" with thresholds at used% level */
int index = optind;
+
if (warn_usedspace_percent == NULL && argc > index && is_intnonneg(argv[index])) {
+ if (verbose > 0) {
+ printf("Got an positional warn threshold: %s\n", argv[index]);
+ }
warn_usedspace_percent = argv[index++];
}
if (crit_usedspace_percent == NULL && argc > index && is_intnonneg(argv[index])) {
+ if (verbose > 0) {
+ printf("Got an positional crit threshold: %s\n", argv[index]);
+ }
crit_usedspace_percent = argv[index++];
}
if (argc > index) {
+ if (verbose > 0) {
+ printf("Got an positional filesystem: %s\n", argv[index]);
+ }
struct parameter_list *se = np_add_parameter(&path_select_list, strdup(argv[index++]));
path_selected = true;
set_all_thresholds(se);
@@ -1081,7 +1095,8 @@ void get_stats(struct parameter_list *parameters, struct fs_usage *fsp) {
parameters->best_match->me_mountdir = parameters->best_match->me_devname = parameters->group;
}
/* finally calculate percentages for either plain FS or summed up group */
- parameters->dused_pct = calculate_percent(parameters->used, parameters->used + parameters->available); /* used + available can never be > uintmax */
+ parameters->dused_pct =
+ calculate_percent(parameters->used, parameters->used + parameters->available); /* used + available can never be > uintmax */
parameters->dfree_pct = 100.0 - parameters->dused_pct;
parameters->dused_inodes_percent = calculate_percent(parameters->inodes_total - parameters->inodes_free, parameters->inodes_total);
parameters->dfree_inodes_percent = 100 - parameters->dused_inodes_percent;
--
cgit v1.2.3-74-g34f1
From 096afc90a79f462e6c705764451273a887fd8c0e Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Mon, 17 Mar 2025 20:37:28 +0100
Subject: check_disk: reset single file system result in between checks
---
plugins/check_disk.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index a333a8b5..f67f3d57 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -217,6 +217,9 @@ int main(int argc, char **argv) {
printf("Group of %s: %s\n", path->name, path->group);
}
+ // reset disk result
+ disk_result = STATE_UNKNOWN;
+
struct mount_entry *mount_entry = path->best_match;
if (!mount_entry) {
--
cgit v1.2.3-74-g34f1
From 285db2a9fa25519cacd48a76347ae2dee0c06605 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Tue, 18 Mar 2025 14:36:20 +0100
Subject: Move disk specific stuff from lib to plugin specific directory
---
lib/Makefile.am | 3 +-
lib/utils_disk.c | 255 --------------------------------------
lib/utils_disk.h | 48 -------
plugins/Makefile.am | 2 +
plugins/check_disk.d/utils_disk.c | 255 ++++++++++++++++++++++++++++++++++++++
plugins/check_disk.d/utils_disk.h | 48 +++++++
6 files changed, 306 insertions(+), 305 deletions(-)
delete mode 100644 lib/utils_disk.c
delete mode 100644 lib/utils_disk.h
create mode 100644 plugins/check_disk.d/utils_disk.c
create mode 100644 plugins/check_disk.d/utils_disk.h
diff --git a/lib/Makefile.am b/lib/Makefile.am
index e41201c4..a9f3ff40 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -7,10 +7,9 @@ noinst_LIBRARIES = libmonitoringplug.a
AM_CPPFLAGS = -DNP_STATE_DIR_PREFIX=\"$(localstatedir)\" \
-I$(srcdir) -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/plugins
-libmonitoringplug_a_SOURCES = utils_base.c utils_disk.c utils_tcp.c utils_cmd.c maxfd.c output.c perfdata.c output.c thresholds.c vendor/cJSON/cJSON.c
+libmonitoringplug_a_SOURCES = utils_base.c utils_tcp.c utils_cmd.c maxfd.c output.c perfdata.c output.c thresholds.c vendor/cJSON/cJSON.c
EXTRA_DIST = utils_base.h \
- utils_disk.h \
utils_tcp.h \
utils_cmd.h \
parse_ini.h \
diff --git a/lib/utils_disk.c b/lib/utils_disk.c
deleted file mode 100644
index 2b761f5e..00000000
--- a/lib/utils_disk.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*****************************************************************************
- *
- * Library for check_disk
- *
- * License: GPL
- * Copyright (c) 1999-2024 Monitoring Plugins Development Team
- *
- * Description:
- *
- * This file contains utilities for check_disk. These are tested by libtap
- *
- *
- * 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 "common.h"
-#include "utils_disk.h"
-#include "gl/fsusage.h"
-#include
-
-void np_add_name(struct name_list **list, const char *name) {
- struct name_list *new_entry;
- new_entry = (struct name_list *)malloc(sizeof *new_entry);
- new_entry->name = (char *)name;
- new_entry->next = *list;
- *list = new_entry;
-}
-
-/* @brief Initialises a new regex at the begin of list via regcomp(3)
- *
- * @details if the regex fails to compile the error code of regcomp(3) is returned
- * and list is not modified, otherwise list is modified to point to the new
- * element
- * @param list Pointer to a linked list of regex_list elements
- * @param regex the string containing the regex which should be inserted into the list
- * @param clags the cflags parameter for regcomp(3)
- */
-int np_add_regex(struct regex_list **list, const char *regex, int cflags) {
- struct regex_list *new_entry = (struct regex_list *)malloc(sizeof *new_entry);
-
- if (new_entry == NULL) {
- die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
- }
-
- int regcomp_result = regcomp(&new_entry->regex, regex, cflags);
-
- if (!regcomp_result) {
- // regcomp succeeded
- new_entry->next = *list;
- *list = new_entry;
-
- return 0;
- } else {
- // regcomp failed
- free(new_entry);
-
- return regcomp_result;
- }
-}
-
-/* Initialises a new parameter at the end of list */
-struct parameter_list *np_add_parameter(struct parameter_list **list, const char *name) {
- struct parameter_list *current = *list;
- struct parameter_list *new_path;
- new_path = (struct parameter_list *)malloc(sizeof *new_path);
- new_path->name = (char *)malloc(strlen(name) + 1);
- new_path->best_match = NULL;
- new_path->name_next = NULL;
- new_path->name_prev = NULL;
- new_path->freespace_bytes = NULL;
- new_path->freespace_units = NULL;
- new_path->freespace_percent = NULL;
- new_path->usedspace_bytes = NULL;
- new_path->usedspace_units = NULL;
- new_path->usedspace_percent = NULL;
- new_path->usedinodes_percent = NULL;
- new_path->freeinodes_percent = NULL;
- new_path->group = NULL;
- new_path->dfree_pct = -1;
- new_path->dused_pct = -1;
- new_path->total = 0;
- new_path->available = 0;
- new_path->available_to_root = 0;
- new_path->used = 0;
- new_path->dused_units = 0;
- new_path->dfree_units = 0;
- new_path->dtotal_units = 0;
- new_path->inodes_total = 0;
- new_path->inodes_free = 0;
- new_path->inodes_free_to_root = 0;
- new_path->inodes_used = 0;
- new_path->dused_inodes_percent = 0;
- new_path->dfree_inodes_percent = 0;
-
- strcpy(new_path->name, name);
-
- if (current == NULL) {
- *list = new_path;
- new_path->name_prev = NULL;
- } else {
- while (current->name_next) {
- current = current->name_next;
- }
- current->name_next = new_path;
- new_path->name_prev = current;
- }
- return new_path;
-}
-
-/* Delete a given parameter from list and return pointer to next element*/
-struct parameter_list *np_del_parameter(struct parameter_list *item, struct parameter_list *prev) {
- if (item == NULL) {
- return NULL;
- }
- struct parameter_list *next;
-
- if (item->name_next)
- next = item->name_next;
- else
- next = NULL;
-
- if (next)
- next->name_prev = prev;
-
- if (prev)
- prev->name_next = next;
-
- if (item->name) {
- free(item->name);
- }
- free(item);
-
- return next;
-}
-
-/* returns a pointer to the struct found in the list */
-struct parameter_list *np_find_parameter(struct parameter_list *list, const char *name) {
- struct parameter_list *temp_list;
- for (temp_list = list; temp_list; temp_list = temp_list->name_next) {
- if (!strcmp(temp_list->name, name))
- return temp_list;
- }
-
- return NULL;
-}
-
-void np_set_best_match(struct parameter_list *desired, struct mount_entry *mount_list, bool exact) {
- struct parameter_list *d;
- for (d = desired; d; d = d->name_next) {
- if (!d->best_match) {
- struct mount_entry *me;
- size_t name_len = strlen(d->name);
- size_t best_match_len = 0;
- struct mount_entry *best_match = NULL;
- struct fs_usage fsp;
-
- /* set best match if path name exactly matches a mounted device name */
- for (me = mount_list; me; me = me->me_next) {
- if (strcmp(me->me_devname, d->name) == 0) {
- if (get_fs_usage(me->me_mountdir, me->me_devname, &fsp) >= 0) {
- best_match = me;
- }
- }
- }
-
- /* set best match by directory name if no match was found by devname */
- if (!best_match) {
- for (me = mount_list; me; me = me->me_next) {
- size_t len = strlen(me->me_mountdir);
- if ((!exact &&
- (best_match_len <= len && len <= name_len && (len == 1 || strncmp(me->me_mountdir, d->name, len) == 0))) ||
- (exact && strcmp(me->me_mountdir, d->name) == 0)) {
- if (get_fs_usage(me->me_mountdir, me->me_devname, &fsp) >= 0) {
- best_match = me;
- best_match_len = len;
- }
- }
- }
- }
-
- if (best_match) {
- d->best_match = best_match;
- } else {
- d->best_match = NULL; /* Not sure why this is needed as it should be null on initialisation */
- }
- }
- }
-}
-
-/* Returns true if name is in list */
-bool np_find_name(struct name_list *list, const char *name) {
- const struct name_list *n;
-
- if (list == NULL || name == NULL) {
- return false;
- }
- for (n = list; n; n = n->next) {
- if (!strcmp(name, n->name)) {
- return true;
- }
- }
- return false;
-}
-
-/* Returns true if name is in list */
-bool np_find_regmatch(struct regex_list *list, const char *name) {
- int len;
- regmatch_t m;
-
- if (name == NULL) {
- return false;
- }
-
- len = strlen(name);
-
- for (; list; list = list->next) {
- /* Emulate a full match as if surrounded with ^( )$
- by checking whether the match spans the whole name */
- if (!regexec(&list->regex, name, 1, &m, 0) && m.rm_so == 0 && m.rm_eo == len) {
- return true;
- }
- }
-
- return false;
-}
-
-bool np_seen_name(struct name_list *list, const char *name) {
- const struct name_list *s;
- for (s = list; s; s = s->next) {
- if (!strcmp(s->name, name)) {
- return true;
- }
- }
- return false;
-}
-
-bool np_regex_match_mount_entry(struct mount_entry *me, regex_t *re) {
- if (regexec(re, me->me_devname, (size_t)0, NULL, 0) == 0 || regexec(re, me->me_mountdir, (size_t)0, NULL, 0) == 0) {
- return true;
- }
- return false;
-}
diff --git a/lib/utils_disk.h b/lib/utils_disk.h
deleted file mode 100644
index c5e81dc1..00000000
--- a/lib/utils_disk.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* Header file for utils_disk */
-
-#include "mountlist.h"
-#include "utils_base.h"
-#include "regex.h"
-
-struct name_list {
- char *name;
- struct name_list *next;
-};
-
-struct regex_list {
- regex_t regex;
- struct regex_list *next;
-};
-
-struct parameter_list {
- char *name;
- thresholds *freespace_bytes;
- thresholds *freespace_units;
- thresholds *freespace_percent;
- thresholds *usedspace_bytes;
- thresholds *usedspace_units;
- thresholds *usedspace_percent;
- thresholds *usedinodes_percent;
- thresholds *freeinodes_percent;
- char *group;
- struct mount_entry *best_match;
- struct parameter_list *name_next;
- struct parameter_list *name_prev;
- uintmax_t total, available, available_to_root, used, inodes_free, inodes_free_to_root, inodes_used, inodes_total;
- double dfree_pct, dused_pct;
- uint64_t dused_units, dfree_units, dtotal_units;
- double dused_inodes_percent, dfree_inodes_percent;
-};
-
-void np_add_name(struct name_list **list, const char *name);
-bool np_find_name(struct name_list *list, const char *name);
-bool np_seen_name(struct name_list *list, const char *name);
-int np_add_regex(struct regex_list **list, const char *regex, int cflags);
-bool np_find_regmatch(struct regex_list *list, const char *name);
-struct parameter_list *np_add_parameter(struct parameter_list **list, const char *name);
-struct parameter_list *np_find_parameter(struct parameter_list *list, const char *name);
-struct parameter_list *np_del_parameter(struct parameter_list *item, struct parameter_list *prev);
-
-int search_parameter_list(struct parameter_list *list, const char *name);
-void np_set_best_match(struct parameter_list *desired, struct mount_entry *mount_list, bool exact);
-bool np_regex_match_mount_entry(struct mount_entry *me, regex_t *re);
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index e2bed4c3..30283cb4 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -55,6 +55,7 @@ EXTRA_DIST = t \
check_hpjd.d \
check_game.d \
check_radius.d \
+ check_disk.d \
check_time.d \
check_nagios.d \
check_dbi.d \
@@ -119,6 +120,7 @@ check_curl_LDADD = $(NETLIBS) $(LIBCURLLIBS) $(SSLOBJS) $(URIPARSERLIBS) picohtt
check_dbi_LDADD = $(NETLIBS) $(DBILIBS)
check_dig_LDADD = $(NETLIBS)
check_disk_LDADD = $(BASEOBJS)
+check_disk_SOURCES = check_disk.c check_disk.d/utils_disk.c
check_dns_LDADD = $(NETLIBS)
check_dummy_LDADD = $(BASEOBJS)
check_fping_LDADD = $(NETLIBS)
diff --git a/plugins/check_disk.d/utils_disk.c b/plugins/check_disk.d/utils_disk.c
new file mode 100644
index 00000000..2b761f5e
--- /dev/null
+++ b/plugins/check_disk.d/utils_disk.c
@@ -0,0 +1,255 @@
+/*****************************************************************************
+ *
+ * Library for check_disk
+ *
+ * License: GPL
+ * Copyright (c) 1999-2024 Monitoring Plugins Development Team
+ *
+ * Description:
+ *
+ * This file contains utilities for check_disk. These are tested by libtap
+ *
+ *
+ * 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 "common.h"
+#include "utils_disk.h"
+#include "gl/fsusage.h"
+#include
+
+void np_add_name(struct name_list **list, const char *name) {
+ struct name_list *new_entry;
+ new_entry = (struct name_list *)malloc(sizeof *new_entry);
+ new_entry->name = (char *)name;
+ new_entry->next = *list;
+ *list = new_entry;
+}
+
+/* @brief Initialises a new regex at the begin of list via regcomp(3)
+ *
+ * @details if the regex fails to compile the error code of regcomp(3) is returned
+ * and list is not modified, otherwise list is modified to point to the new
+ * element
+ * @param list Pointer to a linked list of regex_list elements
+ * @param regex the string containing the regex which should be inserted into the list
+ * @param clags the cflags parameter for regcomp(3)
+ */
+int np_add_regex(struct regex_list **list, const char *regex, int cflags) {
+ struct regex_list *new_entry = (struct regex_list *)malloc(sizeof *new_entry);
+
+ if (new_entry == NULL) {
+ die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
+ }
+
+ int regcomp_result = regcomp(&new_entry->regex, regex, cflags);
+
+ if (!regcomp_result) {
+ // regcomp succeeded
+ new_entry->next = *list;
+ *list = new_entry;
+
+ return 0;
+ } else {
+ // regcomp failed
+ free(new_entry);
+
+ return regcomp_result;
+ }
+}
+
+/* Initialises a new parameter at the end of list */
+struct parameter_list *np_add_parameter(struct parameter_list **list, const char *name) {
+ struct parameter_list *current = *list;
+ struct parameter_list *new_path;
+ new_path = (struct parameter_list *)malloc(sizeof *new_path);
+ new_path->name = (char *)malloc(strlen(name) + 1);
+ new_path->best_match = NULL;
+ new_path->name_next = NULL;
+ new_path->name_prev = NULL;
+ new_path->freespace_bytes = NULL;
+ new_path->freespace_units = NULL;
+ new_path->freespace_percent = NULL;
+ new_path->usedspace_bytes = NULL;
+ new_path->usedspace_units = NULL;
+ new_path->usedspace_percent = NULL;
+ new_path->usedinodes_percent = NULL;
+ new_path->freeinodes_percent = NULL;
+ new_path->group = NULL;
+ new_path->dfree_pct = -1;
+ new_path->dused_pct = -1;
+ new_path->total = 0;
+ new_path->available = 0;
+ new_path->available_to_root = 0;
+ new_path->used = 0;
+ new_path->dused_units = 0;
+ new_path->dfree_units = 0;
+ new_path->dtotal_units = 0;
+ new_path->inodes_total = 0;
+ new_path->inodes_free = 0;
+ new_path->inodes_free_to_root = 0;
+ new_path->inodes_used = 0;
+ new_path->dused_inodes_percent = 0;
+ new_path->dfree_inodes_percent = 0;
+
+ strcpy(new_path->name, name);
+
+ if (current == NULL) {
+ *list = new_path;
+ new_path->name_prev = NULL;
+ } else {
+ while (current->name_next) {
+ current = current->name_next;
+ }
+ current->name_next = new_path;
+ new_path->name_prev = current;
+ }
+ return new_path;
+}
+
+/* Delete a given parameter from list and return pointer to next element*/
+struct parameter_list *np_del_parameter(struct parameter_list *item, struct parameter_list *prev) {
+ if (item == NULL) {
+ return NULL;
+ }
+ struct parameter_list *next;
+
+ if (item->name_next)
+ next = item->name_next;
+ else
+ next = NULL;
+
+ if (next)
+ next->name_prev = prev;
+
+ if (prev)
+ prev->name_next = next;
+
+ if (item->name) {
+ free(item->name);
+ }
+ free(item);
+
+ return next;
+}
+
+/* returns a pointer to the struct found in the list */
+struct parameter_list *np_find_parameter(struct parameter_list *list, const char *name) {
+ struct parameter_list *temp_list;
+ for (temp_list = list; temp_list; temp_list = temp_list->name_next) {
+ if (!strcmp(temp_list->name, name))
+ return temp_list;
+ }
+
+ return NULL;
+}
+
+void np_set_best_match(struct parameter_list *desired, struct mount_entry *mount_list, bool exact) {
+ struct parameter_list *d;
+ for (d = desired; d; d = d->name_next) {
+ if (!d->best_match) {
+ struct mount_entry *me;
+ size_t name_len = strlen(d->name);
+ size_t best_match_len = 0;
+ struct mount_entry *best_match = NULL;
+ struct fs_usage fsp;
+
+ /* set best match if path name exactly matches a mounted device name */
+ for (me = mount_list; me; me = me->me_next) {
+ if (strcmp(me->me_devname, d->name) == 0) {
+ if (get_fs_usage(me->me_mountdir, me->me_devname, &fsp) >= 0) {
+ best_match = me;
+ }
+ }
+ }
+
+ /* set best match by directory name if no match was found by devname */
+ if (!best_match) {
+ for (me = mount_list; me; me = me->me_next) {
+ size_t len = strlen(me->me_mountdir);
+ if ((!exact &&
+ (best_match_len <= len && len <= name_len && (len == 1 || strncmp(me->me_mountdir, d->name, len) == 0))) ||
+ (exact && strcmp(me->me_mountdir, d->name) == 0)) {
+ if (get_fs_usage(me->me_mountdir, me->me_devname, &fsp) >= 0) {
+ best_match = me;
+ best_match_len = len;
+ }
+ }
+ }
+ }
+
+ if (best_match) {
+ d->best_match = best_match;
+ } else {
+ d->best_match = NULL; /* Not sure why this is needed as it should be null on initialisation */
+ }
+ }
+ }
+}
+
+/* Returns true if name is in list */
+bool np_find_name(struct name_list *list, const char *name) {
+ const struct name_list *n;
+
+ if (list == NULL || name == NULL) {
+ return false;
+ }
+ for (n = list; n; n = n->next) {
+ if (!strcmp(name, n->name)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Returns true if name is in list */
+bool np_find_regmatch(struct regex_list *list, const char *name) {
+ int len;
+ regmatch_t m;
+
+ if (name == NULL) {
+ return false;
+ }
+
+ len = strlen(name);
+
+ for (; list; list = list->next) {
+ /* Emulate a full match as if surrounded with ^( )$
+ by checking whether the match spans the whole name */
+ if (!regexec(&list->regex, name, 1, &m, 0) && m.rm_so == 0 && m.rm_eo == len) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool np_seen_name(struct name_list *list, const char *name) {
+ const struct name_list *s;
+ for (s = list; s; s = s->next) {
+ if (!strcmp(s->name, name)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool np_regex_match_mount_entry(struct mount_entry *me, regex_t *re) {
+ if (regexec(re, me->me_devname, (size_t)0, NULL, 0) == 0 || regexec(re, me->me_mountdir, (size_t)0, NULL, 0) == 0) {
+ return true;
+ }
+ return false;
+}
diff --git a/plugins/check_disk.d/utils_disk.h b/plugins/check_disk.d/utils_disk.h
new file mode 100644
index 00000000..c5e81dc1
--- /dev/null
+++ b/plugins/check_disk.d/utils_disk.h
@@ -0,0 +1,48 @@
+/* Header file for utils_disk */
+
+#include "mountlist.h"
+#include "utils_base.h"
+#include "regex.h"
+
+struct name_list {
+ char *name;
+ struct name_list *next;
+};
+
+struct regex_list {
+ regex_t regex;
+ struct regex_list *next;
+};
+
+struct parameter_list {
+ char *name;
+ thresholds *freespace_bytes;
+ thresholds *freespace_units;
+ thresholds *freespace_percent;
+ thresholds *usedspace_bytes;
+ thresholds *usedspace_units;
+ thresholds *usedspace_percent;
+ thresholds *usedinodes_percent;
+ thresholds *freeinodes_percent;
+ char *group;
+ struct mount_entry *best_match;
+ struct parameter_list *name_next;
+ struct parameter_list *name_prev;
+ uintmax_t total, available, available_to_root, used, inodes_free, inodes_free_to_root, inodes_used, inodes_total;
+ double dfree_pct, dused_pct;
+ uint64_t dused_units, dfree_units, dtotal_units;
+ double dused_inodes_percent, dfree_inodes_percent;
+};
+
+void np_add_name(struct name_list **list, const char *name);
+bool np_find_name(struct name_list *list, const char *name);
+bool np_seen_name(struct name_list *list, const char *name);
+int np_add_regex(struct regex_list **list, const char *regex, int cflags);
+bool np_find_regmatch(struct regex_list *list, const char *name);
+struct parameter_list *np_add_parameter(struct parameter_list **list, const char *name);
+struct parameter_list *np_find_parameter(struct parameter_list *list, const char *name);
+struct parameter_list *np_del_parameter(struct parameter_list *item, struct parameter_list *prev);
+
+int search_parameter_list(struct parameter_list *list, const char *name);
+void np_set_best_match(struct parameter_list *desired, struct mount_entry *mount_list, bool exact);
+bool np_regex_match_mount_entry(struct mount_entry *me, regex_t *re);
--
cgit v1.2.3-74-g34f1
From 8ccff07bed03046a97637a54d45a9ffe77edc235 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Tue, 18 Mar 2025 14:37:02 +0100
Subject: refactor check_disk.d code a bit
---
plugins/check_disk.d/utils_disk.c | 139 +++++++++++++++++++-------------------
plugins/check_disk.d/utils_disk.h | 39 ++++++++---
2 files changed, 100 insertions(+), 78 deletions(-)
diff --git a/plugins/check_disk.d/utils_disk.c b/plugins/check_disk.d/utils_disk.c
index 2b761f5e..1d806715 100644
--- a/plugins/check_disk.d/utils_disk.c
+++ b/plugins/check_disk.d/utils_disk.c
@@ -63,12 +63,46 @@ int np_add_regex(struct regex_list **list, const char *regex, int cflags) {
*list = new_entry;
return 0;
- } else {
- // regcomp failed
- free(new_entry);
-
- return regcomp_result;
}
+ // regcomp failed
+ free(new_entry);
+
+ return regcomp_result;
+}
+
+struct parameter_list parameter_list_init(const char *name) {
+ struct parameter_list result = {
+ .name = strdup(name),
+ .best_match = NULL,
+
+ .name_next = NULL,
+ .name_prev = NULL,
+
+ .freespace_units = NULL,
+ .freespace_percent = NULL,
+ .usedspace_units = NULL,
+ .usedspace_percent = NULL,
+ .usedinodes_percent = NULL,
+ .freeinodes_percent = NULL,
+
+ .group = NULL,
+ .dfree_pct = -1,
+ .dused_pct = -1,
+ .total = 0,
+ .available = 0,
+ .available_to_root = 0,
+ .used = 0,
+ .dused_units = 0,
+ .dfree_units = 0,
+ .dtotal_units = 0,
+ .inodes_total = 0,
+ .inodes_free = 0,
+ .inodes_free_to_root = 0,
+ .inodes_used = 0,
+ .dused_inodes_percent = 0,
+ .dfree_inodes_percent = 0,
+ };
+ return result;
}
/* Initialises a new parameter at the end of list */
@@ -76,36 +110,8 @@ struct parameter_list *np_add_parameter(struct parameter_list **list, const char
struct parameter_list *current = *list;
struct parameter_list *new_path;
new_path = (struct parameter_list *)malloc(sizeof *new_path);
- new_path->name = (char *)malloc(strlen(name) + 1);
- new_path->best_match = NULL;
- new_path->name_next = NULL;
- new_path->name_prev = NULL;
- new_path->freespace_bytes = NULL;
- new_path->freespace_units = NULL;
- new_path->freespace_percent = NULL;
- new_path->usedspace_bytes = NULL;
- new_path->usedspace_units = NULL;
- new_path->usedspace_percent = NULL;
- new_path->usedinodes_percent = NULL;
- new_path->freeinodes_percent = NULL;
- new_path->group = NULL;
- new_path->dfree_pct = -1;
- new_path->dused_pct = -1;
- new_path->total = 0;
- new_path->available = 0;
- new_path->available_to_root = 0;
- new_path->used = 0;
- new_path->dused_units = 0;
- new_path->dfree_units = 0;
- new_path->dtotal_units = 0;
- new_path->inodes_total = 0;
- new_path->inodes_free = 0;
- new_path->inodes_free_to_root = 0;
- new_path->inodes_used = 0;
- new_path->dused_inodes_percent = 0;
- new_path->dfree_inodes_percent = 0;
-
- strcpy(new_path->name, name);
+
+ *new_path = parameter_list_init(name);
if (current == NULL) {
*list = new_path;
@@ -125,18 +131,22 @@ struct parameter_list *np_del_parameter(struct parameter_list *item, struct para
if (item == NULL) {
return NULL;
}
+
struct parameter_list *next;
- if (item->name_next)
+ if (item->name_next) {
next = item->name_next;
- else
+ } else {
next = NULL;
+ }
- if (next)
+ if (next) {
next->name_prev = prev;
+ }
- if (prev)
+ if (prev) {
prev->name_next = next;
+ }
if (item->name) {
free(item->name);
@@ -148,43 +158,42 @@ struct parameter_list *np_del_parameter(struct parameter_list *item, struct para
/* returns a pointer to the struct found in the list */
struct parameter_list *np_find_parameter(struct parameter_list *list, const char *name) {
- struct parameter_list *temp_list;
- for (temp_list = list; temp_list; temp_list = temp_list->name_next) {
- if (!strcmp(temp_list->name, name))
+ for (struct parameter_list *temp_list = list; temp_list; temp_list = temp_list->name_next) {
+ if (!strcmp(temp_list->name, name)) {
return temp_list;
+ }
}
return NULL;
}
void np_set_best_match(struct parameter_list *desired, struct mount_entry *mount_list, bool exact) {
- struct parameter_list *d;
- for (d = desired; d; d = d->name_next) {
+ for (struct parameter_list *d = desired; d; d = d->name_next) {
if (!d->best_match) {
- struct mount_entry *me;
+ struct mount_entry *mount_entry;
size_t name_len = strlen(d->name);
size_t best_match_len = 0;
struct mount_entry *best_match = NULL;
struct fs_usage fsp;
/* set best match if path name exactly matches a mounted device name */
- for (me = mount_list; me; me = me->me_next) {
- if (strcmp(me->me_devname, d->name) == 0) {
- if (get_fs_usage(me->me_mountdir, me->me_devname, &fsp) >= 0) {
- best_match = me;
+ for (mount_entry = mount_list; mount_entry; mount_entry = mount_entry->me_next) {
+ if (strcmp(mount_entry->me_devname, d->name) == 0) {
+ if (get_fs_usage(mount_entry->me_mountdir, mount_entry->me_devname, &fsp) >= 0) {
+ best_match = mount_entry;
}
}
}
/* set best match by directory name if no match was found by devname */
if (!best_match) {
- for (me = mount_list; me; me = me->me_next) {
- size_t len = strlen(me->me_mountdir);
- if ((!exact &&
- (best_match_len <= len && len <= name_len && (len == 1 || strncmp(me->me_mountdir, d->name, len) == 0))) ||
- (exact && strcmp(me->me_mountdir, d->name) == 0)) {
- if (get_fs_usage(me->me_mountdir, me->me_devname, &fsp) >= 0) {
- best_match = me;
+ for (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, d->name, len) == 0))) ||
+ (exact && strcmp(mount_entry->me_mountdir, d->name) == 0)) {
+ if (get_fs_usage(mount_entry->me_mountdir, mount_entry->me_devname, &fsp) >= 0) {
+ best_match = mount_entry;
best_match_len = len;
}
}
@@ -202,12 +211,10 @@ void np_set_best_match(struct parameter_list *desired, struct mount_entry *mount
/* Returns true if name is in list */
bool np_find_name(struct name_list *list, const char *name) {
- const struct name_list *n;
-
if (list == NULL || name == NULL) {
return false;
}
- for (n = list; n; n = n->next) {
+ for (struct name_list *n = list; n; n = n->next) {
if (!strcmp(name, n->name)) {
return true;
}
@@ -217,18 +224,16 @@ bool np_find_name(struct name_list *list, const char *name) {
/* Returns true if name is in list */
bool np_find_regmatch(struct regex_list *list, const char *name) {
- int len;
- regmatch_t m;
-
if (name == NULL) {
return false;
}
- len = strlen(name);
+ int len = strlen(name);
for (; list; list = list->next) {
/* Emulate a full match as if surrounded with ^( )$
by checking whether the match spans the whole name */
+ regmatch_t m;
if (!regexec(&list->regex, name, 1, &m, 0) && m.rm_so == 0 && m.rm_eo == len) {
return true;
}
@@ -238,8 +243,7 @@ bool np_find_regmatch(struct regex_list *list, const char *name) {
}
bool np_seen_name(struct name_list *list, const char *name) {
- const struct name_list *s;
- for (s = list; s; s = s->next) {
+ for (struct name_list *s = list; s; s = s->next) {
if (!strcmp(s->name, name)) {
return true;
}
@@ -248,8 +252,5 @@ bool np_seen_name(struct name_list *list, const char *name) {
}
bool np_regex_match_mount_entry(struct mount_entry *me, regex_t *re) {
- if (regexec(re, me->me_devname, (size_t)0, NULL, 0) == 0 || regexec(re, me->me_mountdir, (size_t)0, NULL, 0) == 0) {
- return true;
- }
- return false;
+ return ((regexec(re, me->me_devname, (size_t)0, NULL, 0) == 0) || (regexec(re, me->me_mountdir, (size_t)0, NULL, 0) == 0));
}
diff --git a/plugins/check_disk.d/utils_disk.h b/plugins/check_disk.d/utils_disk.h
index c5e81dc1..1c68fed9 100644
--- a/plugins/check_disk.d/utils_disk.h
+++ b/plugins/check_disk.d/utils_disk.h
@@ -1,8 +1,10 @@
/* Header file for utils_disk */
-#include "mountlist.h"
+#include "../../config.h"
+#include "../../gl/mountlist.h"
#include "utils_base.h"
#include "regex.h"
+#include
struct name_list {
char *name;
@@ -16,22 +18,39 @@ struct regex_list {
struct parameter_list {
char *name;
- thresholds *freespace_bytes;
+ char *group;
+
thresholds *freespace_units;
thresholds *freespace_percent;
- thresholds *usedspace_bytes;
thresholds *usedspace_units;
thresholds *usedspace_percent;
+
thresholds *usedinodes_percent;
thresholds *freeinodes_percent;
- char *group;
+
struct mount_entry *best_match;
+
+ uintmax_t total;
+ uintmax_t available;
+ uintmax_t available_to_root;
+ uintmax_t used;
+ uintmax_t inodes_free;
+ uintmax_t inodes_free_to_root;
+ uintmax_t inodes_used;
+ uintmax_t inodes_total;
+
+ double dfree_pct;
+ double dused_pct;
+
+ uint64_t dused_units;
+ uint64_t dfree_units;
+ uint64_t dtotal_units;
+
+ double dused_inodes_percent;
+ double dfree_inodes_percent;
+
struct parameter_list *name_next;
struct parameter_list *name_prev;
- uintmax_t total, available, available_to_root, used, inodes_free, inodes_free_to_root, inodes_used, inodes_total;
- double dfree_pct, dused_pct;
- uint64_t dused_units, dfree_units, dtotal_units;
- double dused_inodes_percent, dfree_inodes_percent;
};
void np_add_name(struct name_list **list, const char *name);
@@ -39,10 +58,12 @@ bool np_find_name(struct name_list *list, const char *name);
bool np_seen_name(struct name_list *list, const char *name);
int np_add_regex(struct regex_list **list, const char *regex, int cflags);
bool np_find_regmatch(struct regex_list *list, const char *name);
+
struct parameter_list *np_add_parameter(struct parameter_list **list, const char *name);
struct parameter_list *np_find_parameter(struct parameter_list *list, const char *name);
struct parameter_list *np_del_parameter(struct parameter_list *item, struct parameter_list *prev);
+struct parameter_list parameter_list_init(const char *);
int search_parameter_list(struct parameter_list *list, const char *name);
void np_set_best_match(struct parameter_list *desired, struct mount_entry *mount_list, bool exact);
-bool np_regex_match_mount_entry(struct mount_entry *me, regex_t *re);
+bool np_regex_match_mount_entry(struct mount_entry *, regex_t *);
--
cgit v1.2.3-74-g34f1
From 29d946b9b516662a0f625b7d229ee41962cac264 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Tue, 18 Mar 2025 14:37:49 +0100
Subject: Refactor check_disk, no more global variables
---
plugins/check_disk.c | 530 +++++++++++++++++++++---------------------
plugins/check_disk.d/config.h | 92 ++++++++
2 files changed, 358 insertions(+), 264 deletions(-)
create mode 100644 plugins/check_disk.d/config.h
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index f67f3d57..2df89aa3 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -43,13 +43,15 @@ const char *email = "devel@monitoring-plugins.org";
#endif
#include
-#include "popen.h"
-#include "utils.h"
-#include "utils_disk.h"
#include
-#include "fsusage.h"
-#include "mountlist.h"
+#include
#include
+#include "./popen.h"
+#include "./utils.h"
+#include "./check_disk.d/utils_disk.h"
+#include "../gl/fsusage.h"
+#include "../gl/mountlist.h"
+#include "check_disk.d/config.h"
#if HAVE_LIMITS_H
# include
@@ -63,27 +65,6 @@ const char *email = "devel@monitoring-plugins.org";
# define ERROR -1
#endif
-/* If nonzero, show only local filesystems. */
-static bool show_local_fs = false;
-
-/* If nonzero, show only local filesystems but call stat() on remote ones. */
-static bool stat_remote_fs = false;
-
-/* Linked list of filesystem types to omit.
- If the list is empty, don't exclude any types. */
-static struct regex_list *fs_exclude_list = NULL;
-
-/* Linked list of filesystem types to check.
- If the list is empty, include all types. */
-static struct regex_list *fs_include_list;
-
-static struct name_list *dp_exclude_list;
-
-static struct parameter_list *path_select_list = NULL;
-
-/* Linked list of mounted filesystems. */
-static struct mount_entry *mount_list;
-
/* For long options that have no equivalent short option, use a
non-character as a pseudo short option, starting with CHAR_MAX + 1. */
enum {
@@ -96,40 +77,27 @@ enum {
# pragma alloca
#endif
-static int process_arguments(int /*argc*/, char ** /*argv*/);
-static void set_all_thresholds(struct parameter_list *path);
+typedef struct {
+ int errorcode;
+ check_disk_config config;
+} check_disk_config_wrapper;
+static check_disk_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
+static void set_all_thresholds(struct parameter_list *path, char * /*warn_freespace_units*/, char * /*crit_freespace_units*/,
+ char * /*warn_freespace_percent*/, char * /*crit_freespace_percent*/, char * /*warn_usedspace_units*/,
+ char * /*crit_usedspace_units*/, char * /*warn_usedspace_percent*/, char * /*crit_usedspace_percent*/,
+ char * /*warn_usedinodes_percent*/, char * /*crit_usedinodes_percent*/, char * /*warn_freeinodes_percent*/,
+ char * /*crit_freeinodes_percent*/);
static void print_help(void);
void print_usage(void);
static double calculate_percent(uintmax_t /*value*/, uintmax_t /*total*/);
-static bool stat_path(struct parameter_list * /*parameters*/);
-static void get_stats(struct parameter_list * /*parameters*/, struct fs_usage *fsp);
-static void get_path_stats(struct parameter_list * /*parameters*/, struct fs_usage *fsp);
+static bool stat_path(struct parameter_list * /*parameters*/, bool /*ignore_missing*/);
+static void get_stats(struct parameter_list * /*parameters*/, struct fs_usage *fsp, bool /*ignore_missing*/,
+ bool /*freespace_ignore_reserved*/, uintmax_t /*mult*/, struct parameter_list * /*path_select_list*/,
+ struct name_list * /*seen*/);
+static void get_path_stats(struct parameter_list * /*parameters*/, struct fs_usage *fsp, bool /*freespace_ignore_reserved*/,
+ uintmax_t /*mult*/, struct name_list * /*seen*/);
-static char *units;
-static uintmax_t mult = 1024 * 1024;
static int verbose = 0;
-static bool erronly = false;
-static bool display_mntp = false;
-static bool exact_match = false;
-static bool ignore_missing = false;
-static bool freespace_ignore_reserved = false;
-static bool display_inodes_perfdata = false;
-static char *warn_freespace_units = NULL;
-static char *crit_freespace_units = NULL;
-static char *warn_freespace_percent = NULL;
-static char *crit_freespace_percent = NULL;
-static char *warn_usedspace_units = NULL;
-static char *crit_usedspace_units = NULL;
-static char *warn_usedspace_percent = NULL;
-static char *crit_usedspace_percent = NULL;
-static char *warn_usedinodes_percent = NULL;
-static char *crit_usedinodes_percent = NULL;
-static char *warn_freeinodes_percent = NULL;
-static char *crit_freeinodes_percent = NULL;
-static bool path_selected = false;
-static bool path_ignored = false;
-static char *group = NULL;
-static struct name_list *seen = NULL;
int main(int argc, char **argv) {
setlocale(LC_ALL, "");
@@ -140,74 +108,78 @@ int main(int argc, char **argv) {
char mountdir[32];
#endif
- mount_list = read_file_system_list(false);
-
/* Parse extra opts if any */
argv = np_extra_opts(&argc, argv, progname);
- if (process_arguments(argc, argv) == ERROR) {
+ check_disk_config_wrapper tmp_config = process_arguments(argc, argv);
+ if (tmp_config.errorcode == ERROR) {
usage4(_("Could not parse arguments"));
}
+ check_disk_config config = tmp_config.config;
+
/* If a list of paths has not been selected, find entire
mount list and create list of paths
*/
- if (!path_selected && !path_ignored) {
- for (struct mount_entry *me = mount_list; me; me = me->me_next) {
+ if (!config.path_selected && !config.path_ignored) {
+ for (struct mount_entry *me = config.mount_list; me; me = me->me_next) {
struct parameter_list *path = NULL;
- if (!(path = np_find_parameter(path_select_list, me->me_mountdir))) {
- path = np_add_parameter(&path_select_list, me->me_mountdir);
+ if (!(path = np_find_parameter(config.path_select_list, me->me_mountdir))) {
+ path = np_add_parameter(&config.path_select_list, me->me_mountdir);
}
path->best_match = me;
- path->group = group;
- set_all_thresholds(path);
+ path->group = config.group;
+ set_all_thresholds(path, config.warn_freespace_units, config.crit_freespace_units, config.warn_freespace_percent,
+ config.crit_freespace_percent, config.warn_usedspace_units, config.crit_usedspace_units,
+ config.warn_usedspace_percent, config.crit_usedspace_percent, config.warn_usedinodes_percent,
+ config.crit_usedinodes_percent, config.warn_freeinodes_percent, config.crit_freeinodes_percent);
}
}
- if (!path_ignored) {
- np_set_best_match(path_select_list, mount_list, exact_match);
+ if (!config.path_ignored) {
+ np_set_best_match(config.path_select_list, config.mount_list, config.exact_match);
}
/* Error if no match found for specified paths */
- struct parameter_list *temp_list = path_select_list;
+ struct parameter_list *temp_list = config.path_select_list;
char *ignored = strdup("");
- while (path_select_list) {
- if (!path_select_list->best_match && ignore_missing) {
+ while (config.path_select_list) {
+ if (!config.path_select_list->best_match && config.ignore_missing) {
/* If the first element will be deleted, the temp_list must be updated with the new start address as well */
- if (path_select_list == temp_list) {
- temp_list = path_select_list->name_next;
+ if (config.path_select_list == temp_list) {
+ temp_list = config.path_select_list->name_next;
}
/* Add path argument to list of ignored paths to inform about missing paths being ignored and not alerted */
- xasprintf(&ignored, "%s %s;", ignored, path_select_list->name);
+ xasprintf(&ignored, "%s %s;", ignored, config.path_select_list->name);
/* Delete the path from the list so that it is not stat-checked later in the code. */
- path_select_list = np_del_parameter(path_select_list, path_select_list->name_prev);
- } else if (!path_select_list->best_match) {
+ config.path_select_list = np_del_parameter(config.path_select_list, config.path_select_list->name_prev);
+ } else if (!config.path_select_list->best_match) {
/* Without --ignore-missing option, exit with Critical state. */
- die(STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), path_select_list->name);
+ die(STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), config.path_select_list->name);
} else {
/* Continue jumping through the list */
- path_select_list = path_select_list->name_next;
+ config.path_select_list = config.path_select_list->name_next;
}
}
- path_select_list = temp_list;
+ config.path_select_list = temp_list;
- int result = STATE_UNKNOWN;
- if (!path_select_list && ignore_missing) {
+ mp_state_enum result = STATE_UNKNOWN;
+ if (!config.path_select_list && config.ignore_missing) {
result = STATE_OK;
if (verbose >= 2) {
printf("None of the provided paths were found\n");
}
}
- mp_state_enum disk_result = STATE_UNKNOWN;
+ mp_state_enum filesystem_result = STATE_UNKNOWN;
char *perf = strdup("");
char *perf_ilabel = strdup("");
char *output = strdup("");
struct parameter_list *path = NULL;
/* Process for every path in list */
- for (path = path_select_list; path; path = path->name_next) {
+ for (path = config.path_select_list; path; path = path->name_next) {
if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL) {
printf("Thresholds(pct) for %s warn: %f crit %f\n", path->name, path->freespace_percent->warning->end,
path->freespace_percent->critical->end);
@@ -217,8 +189,8 @@ int main(int argc, char **argv) {
printf("Group of %s: %s\n", path->name, path->group);
}
- // reset disk result
- disk_result = STATE_UNKNOWN;
+ // reset filesystem result
+ filesystem_result = STATE_UNKNOWN;
struct mount_entry *mount_entry = path->best_match;
@@ -238,16 +210,16 @@ int main(int argc, char **argv) {
/* Filters */
/* Remove filesystems already seen */
- if (np_seen_name(seen, mount_entry->me_mountdir)) {
+ if (np_seen_name(config.seen, mount_entry->me_mountdir)) {
continue;
}
- np_add_name(&seen, mount_entry->me_mountdir);
+ np_add_name(&config.seen, mount_entry->me_mountdir);
if (path->group == NULL) {
/* Skip remote filesystems if we're not interested in them */
- if (mount_entry->me_remote && show_local_fs) {
- if (stat_remote_fs) {
- if (!stat_path(path) && ignore_missing) {
+ if (mount_entry->me_remote && config.show_local_fs) {
+ if (config.stat_remote_fs) {
+ if (!stat_path(path, config.ignore_missing) && config.ignore_missing) {
result = STATE_OK;
xasprintf(&ignored, "%s %s;", ignored, path->name);
}
@@ -255,22 +227,22 @@ int main(int argc, char **argv) {
continue;
/* Skip pseudo fs's if we haven't asked for all fs's */
}
- if (fs_exclude_list && np_find_regmatch(fs_exclude_list, mount_entry->me_type)) {
+ if (config.fs_exclude_list && np_find_regmatch(config.fs_exclude_list, mount_entry->me_type)) {
continue;
/* Skip excluded fs's */
}
- if (dp_exclude_list &&
- (np_find_name(dp_exclude_list, mount_entry->me_devname) || np_find_name(dp_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))) {
continue;
/* Skip not included fstypes */
}
- if (fs_include_list && !np_find_regmatch(fs_include_list, mount_entry->me_type)) {
+ if (config.fs_include_list && !np_find_regmatch(config.fs_include_list, mount_entry->me_type)) {
continue;
}
}
- if (!stat_path(path)) {
- if (ignore_missing) {
+ if (!stat_path(path, config.ignore_missing)) {
+ if (config.ignore_missing) {
result = STATE_OK;
xasprintf(&ignored, "%s %s;", ignored, path->name);
}
@@ -281,13 +253,14 @@ int main(int argc, char **argv) {
get_fs_usage(mount_entry->me_mountdir, mount_entry->me_devname, &fsp);
if (fsp.fsu_blocks && strcmp("none", mount_entry->me_mountdir)) {
- get_stats(path, &fsp);
+ get_stats(path, &fsp, config.ignore_missing, config.freespace_ignore_reserved, config.mult, config.path_select_list,
+ config.seen);
if (verbose >= 3) {
printf("For %s, used_pct=%f free_pct=%f used_units=%lu free_units=%lu total_units=%lu used_inodes_pct=%f "
"free_inodes_pct=%f fsp.fsu_blocksize=%lu mult=%lu\n",
mount_entry->me_mountdir, path->dused_pct, path->dfree_pct, path->dused_units, path->dfree_units, path->dtotal_units,
- path->dused_inodes_percent, path->dfree_inodes_percent, fsp.fsu_blocksize, mult);
+ path->dused_inodes_percent, path->dfree_inodes_percent, fsp.fsu_blocksize, config.mult);
}
/* Threshold comparisons */
@@ -296,39 +269,39 @@ int main(int argc, char **argv) {
if (verbose >= 3) {
printf("Freespace_units result=%d\n", temp_result);
}
- disk_result = max_state(disk_result, temp_result);
+ filesystem_result = max_state(filesystem_result, temp_result);
temp_result = get_status(path->dfree_pct, path->freespace_percent);
if (verbose >= 3) {
printf("Freespace%% result=%d\n", temp_result);
}
- disk_result = max_state(disk_result, temp_result);
+ filesystem_result = max_state(filesystem_result, temp_result);
temp_result = get_status(path->dused_units, path->usedspace_units);
if (verbose >= 3) {
printf("Usedspace_units result=%d\n", temp_result);
}
- disk_result = max_state(disk_result, temp_result);
+ filesystem_result = max_state(filesystem_result, temp_result);
temp_result = get_status(path->dused_pct, path->usedspace_percent);
if (verbose >= 3) {
printf("Usedspace_percent result=%d\n", temp_result);
}
- disk_result = max_state(disk_result, temp_result);
+ filesystem_result = max_state(filesystem_result, temp_result);
temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent);
if (verbose >= 3) {
printf("Usedinodes_percent result=%d\n", temp_result);
}
- disk_result = max_state(disk_result, temp_result);
+ filesystem_result = max_state(filesystem_result, temp_result);
temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent);
if (verbose >= 3) {
printf("Freeinodes_percent result=%d\n", temp_result);
}
- disk_result = max_state(disk_result, temp_result);
+ filesystem_result = max_state(filesystem_result, temp_result);
- result = max_state(result, disk_result);
+ result = max_state(result, filesystem_result);
/* What a mess of units. The output shows free space, the perf data shows used space. Yikes!
Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf
@@ -339,31 +312,32 @@ int main(int argc, char **argv) {
uint64_t warning_high_tide = UINT64_MAX;
if (path->freespace_units->warning != NULL) {
- warning_high_tide = (path->dtotal_units - path->freespace_units->warning->end) * mult;
+ warning_high_tide = (path->dtotal_units - path->freespace_units->warning->end) * config.mult;
}
if (path->freespace_percent->warning != NULL) {
- warning_high_tide =
- min(warning_high_tide, (uint64_t)((1.0 - path->freespace_percent->warning->end / 100) * (path->dtotal_units * mult)));
+ warning_high_tide = min(warning_high_tide, (uint64_t)((1.0 - path->freespace_percent->warning->end / 100) *
+ (path->dtotal_units * config.mult)));
}
uint64_t critical_high_tide = UINT64_MAX;
if (path->freespace_units->critical != NULL) {
- critical_high_tide = (path->dtotal_units - path->freespace_units->critical->end) * mult;
+ critical_high_tide = (path->dtotal_units - path->freespace_units->critical->end) * config.mult;
}
if (path->freespace_percent->critical != NULL) {
- critical_high_tide =
- min(critical_high_tide, (uint64_t)((1.0 - path->freespace_percent->critical->end / 100) * (path->dtotal_units * mult)));
+ critical_high_tide = min(critical_high_tide, (uint64_t)((1.0 - path->freespace_percent->critical->end / 100) *
+ (path->dtotal_units * config.mult)));
}
/* Nb: *_high_tide are unset when == UINT64_MAX */
xasprintf(&perf, "%s %s", perf,
- perfdata_uint64((!strcmp(mount_entry->me_mountdir, "none") || display_mntp) ? mount_entry->me_devname
- : mount_entry->me_mountdir,
- path->dused_units * mult, "B", (warning_high_tide != UINT64_MAX), warning_high_tide,
- (critical_high_tide != UINT64_MAX), critical_high_tide, true, 0, true, path->dtotal_units * mult));
+ perfdata_uint64((!strcmp(mount_entry->me_mountdir, "none") || config.display_mntp) ? mount_entry->me_devname
+ : mount_entry->me_mountdir,
+ path->dused_units * config.mult, "B", (warning_high_tide != UINT64_MAX), warning_high_tide,
+ (critical_high_tide != UINT64_MAX), critical_high_tide, true, 0, true,
+ path->dtotal_units * config.mult));
- if (display_inodes_perfdata) {
+ if (config.display_inodes_perfdata) {
/* *_high_tide must be reinitialized at each run */
warning_high_tide = UINT64_MAX;
critical_high_tide = UINT64_MAX;
@@ -378,43 +352,46 @@ int main(int argc, char **argv) {
}
xasprintf(&perf_ilabel, "%s (inodes)",
- (!strcmp(mount_entry->me_mountdir, "none") || display_mntp) ? mount_entry->me_devname : mount_entry->me_mountdir);
+ (!strcmp(mount_entry->me_mountdir, "none") || config.display_mntp) ? mount_entry->me_devname
+ : mount_entry->me_mountdir);
/* Nb: *_high_tide are unset when == UINT64_MAX */
xasprintf(&perf, "%s %s", perf,
perfdata_uint64(perf_ilabel, path->inodes_used, "", (warning_high_tide != UINT64_MAX), warning_high_tide,
(critical_high_tide != UINT64_MAX), critical_high_tide, true, 0, true, path->inodes_total));
}
- if (disk_result == STATE_OK && erronly && !verbose) {
+ if (filesystem_result == STATE_OK && config.erronly && !verbose) {
continue;
}
char *flag_header = NULL;
- if (disk_result && verbose >= 1) {
- xasprintf(&flag_header, " %s [", state_text(disk_result));
+ if (filesystem_result && verbose >= 1) {
+ xasprintf(&flag_header, " %s [", state_text(filesystem_result));
} else {
xasprintf(&flag_header, "");
}
xasprintf(&output, "%s%s %s %llu%s (%.1f%%", output, flag_header,
- (!strcmp(mount_entry->me_mountdir, "none") || display_mntp) ? mount_entry->me_devname : mount_entry->me_mountdir,
- path->dfree_units, units, path->dfree_pct);
+ (!strcmp(mount_entry->me_mountdir, "none") || config.display_mntp) ? mount_entry->me_devname
+ : mount_entry->me_mountdir,
+ path->dfree_units, config.units, path->dfree_pct);
if (path->dused_inodes_percent < 0) {
- xasprintf(&output, "%s inode=-)%s;", output, (disk_result ? "]" : ""));
+ xasprintf(&output, "%s inode=-)%s;", output, (filesystem_result ? "]" : ""));
} else {
- xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent, ((disk_result && verbose >= 1) ? "]" : ""));
+ xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent,
+ ((filesystem_result && verbose >= 1) ? "]" : ""));
}
free(flag_header);
}
}
char *preamble = " - free space:";
- if (strcmp(output, "") == 0 && !erronly) {
+ if (strcmp(output, "") == 0 && !config.erronly) {
preamble = "";
xasprintf(&output, " - No disks were found for provided parameters");
}
char *ignored_preamble = " - ignored paths:";
- printf("DISK %s%s%s%s%s|%s\n", state_text(result), ((erronly && result == STATE_OK)) ? "" : preamble, output,
+ printf("DISK %s%s%s%s%s|%s\n", state_text(result), (config.erronly && (result == STATE_OK)) ? "" : preamble, output,
(strcmp(ignored, "") == 0) ? "" : ignored_preamble, ignored, perf);
return result;
}
@@ -428,9 +405,16 @@ double calculate_percent(uintmax_t value, uintmax_t total) {
}
/* process command-line arguments */
-int process_arguments(int argc, char **argv) {
+check_disk_config_wrapper process_arguments(int argc, char **argv) {
+
+ check_disk_config_wrapper result = {
+ .errorcode = OK,
+ .config = check_disk_config_init(),
+ };
+
if (argc < 2) {
- return ERROR;
+ result.errorcode = ERROR;
+ return result;
}
static struct option longopts[] = {{"timeout", required_argument, 0, 't'},
@@ -480,8 +464,9 @@ int process_arguments(int argc, char **argv) {
int cflags = REG_NOSUB | REG_EXTENDED;
int default_cflags = cflags;
+ result.config.mount_list = read_file_system_list(false);
- np_add_regex(&fs_exclude_list, "iso9660", REG_EXTENDED);
+ np_add_regex(&result.config.fs_exclude_list, "iso9660", REG_EXTENDED);
while (true) {
int option = 0;
@@ -508,15 +493,15 @@ int process_arguments(int argc, char **argv) {
if (strstr(optarg, "%")) {
if (*optarg == '@') {
- warn_freespace_percent = optarg;
+ result.config.warn_freespace_percent = optarg;
} else {
- xasprintf(&warn_freespace_percent, "@%s", optarg);
+ xasprintf(&result.config.warn_freespace_percent, "@%s", optarg);
}
} else {
if (*optarg == '@') {
- warn_freespace_units = optarg;
+ result.config.warn_freespace_units = optarg;
} else {
- xasprintf(&warn_freespace_units, "@%s", optarg);
+ xasprintf(&result.config.warn_freespace_units, "@%s", optarg);
}
}
break;
@@ -533,149 +518,149 @@ int process_arguments(int argc, char **argv) {
if (strstr(optarg, "%")) {
if (*optarg == '@') {
- crit_freespace_percent = optarg;
+ result.config.crit_freespace_percent = optarg;
} else {
- xasprintf(&crit_freespace_percent, "@%s", optarg);
+ xasprintf(&result.config.crit_freespace_percent, "@%s", optarg);
}
} else {
if (*optarg == '@') {
- crit_freespace_units = optarg;
+ result.config.crit_freespace_units = optarg;
} else {
- xasprintf(&crit_freespace_units, "@%s", optarg);
+ xasprintf(&result.config.crit_freespace_units, "@%s", optarg);
}
}
break;
case 'W': /* warning inode threshold */
if (*optarg == '@') {
- warn_freeinodes_percent = optarg;
+ result.config.warn_freeinodes_percent = optarg;
} else {
- xasprintf(&warn_freeinodes_percent, "@%s", optarg);
+ xasprintf(&result.config.warn_freeinodes_percent, "@%s", optarg);
}
break;
case 'K': /* critical inode threshold */
if (*optarg == '@') {
- crit_freeinodes_percent = optarg;
+ result.config.crit_freeinodes_percent = optarg;
} else {
- xasprintf(&crit_freeinodes_percent, "@%s", optarg);
+ xasprintf(&result.config.crit_freeinodes_percent, "@%s", optarg);
}
break;
case 'u':
- if (units) {
- free(units);
- }
+ free(result.config.units);
if (!strcasecmp(optarg, "bytes")) {
- mult = (uintmax_t)1;
- units = strdup("B");
+ result.config.mult = (uintmax_t)1;
+ result.config.units = strdup("B");
} else if (!strcmp(optarg, "KiB")) {
- mult = (uintmax_t)1024;
- units = strdup("KiB");
+ result.config.mult = (uintmax_t)1024;
+ result.config.units = strdup("KiB");
} else if (!strcmp(optarg, "kB")) {
- mult = (uintmax_t)1000;
- units = strdup("kB");
+ result.config.mult = (uintmax_t)1000;
+ result.config.units = strdup("kB");
} else if (!strcmp(optarg, "MiB")) {
- mult = (uintmax_t)1024 * 1024;
- units = strdup("MiB");
+ result.config.mult = (uintmax_t)1024 * 1024;
+ result.config.units = strdup("MiB");
} else if (!strcmp(optarg, "MB")) {
- mult = (uintmax_t)1000 * 1000;
- units = strdup("MB");
+ result.config.mult = (uintmax_t)1000 * 1000;
+ result.config.units = strdup("MB");
} else if (!strcmp(optarg, "GiB")) {
- mult = (uintmax_t)1024 * 1024 * 1024;
- units = strdup("GiB");
+ result.config.mult = (uintmax_t)1024 * 1024 * 1024;
+ result.config.units = strdup("GiB");
} else if (!strcmp(optarg, "GB")) {
- mult = (uintmax_t)1000 * 1000 * 1000;
- units = strdup("GB");
+ result.config.mult = (uintmax_t)1000 * 1000 * 1000;
+ result.config.units = strdup("GB");
} else if (!strcmp(optarg, "TiB")) {
- mult = (uintmax_t)1024 * 1024 * 1024 * 1024;
- units = strdup("TiB");
+ result.config.mult = (uintmax_t)1024 * 1024 * 1024 * 1024;
+ result.config.units = strdup("TiB");
} else if (!strcmp(optarg, "TB")) {
- mult = (uintmax_t)1000 * 1000 * 1000 * 1000;
- units = strdup("TB");
+ result.config.mult = (uintmax_t)1000 * 1000 * 1000 * 1000;
+ result.config.units = strdup("TB");
} else if (!strcmp(optarg, "PiB")) {
- mult = (uintmax_t)1024 * 1024 * 1024 * 1024 * 1024;
- units = strdup("PiB");
+ result.config.mult = (uintmax_t)1024 * 1024 * 1024 * 1024 * 1024;
+ result.config.units = strdup("PiB");
} else if (!strcmp(optarg, "PB")) {
- mult = (uintmax_t)1000 * 1000 * 1000 * 1000 * 1000;
- units = strdup("PB");
+ result.config.mult = (uintmax_t)1000 * 1000 * 1000 * 1000 * 1000;
+ result.config.units = strdup("PB");
} else {
die(STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
}
- if (units == NULL) {
+ if (result.config.units == NULL) {
die(STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units");
}
break;
case 'k': /* display mountpoint */
- mult = 1024;
- if (units) {
- free(units);
- }
- units = strdup("kiB");
+ result.config.mult = 1024;
+ free(result.config.units);
+ result.config.units = strdup("kiB");
break;
case 'm': /* display mountpoint */
- mult = 1024 * 1024;
- if (units) {
- free(units);
- }
- units = strdup("MiB");
+ result.config.mult = 1024 * 1024;
+ free(result.config.units);
+ result.config.units = strdup("MiB");
break;
case 'L':
- stat_remote_fs = true;
+ result.config.stat_remote_fs = true;
/* fallthrough */
case 'l':
- show_local_fs = true;
+ result.config.show_local_fs = true;
break;
case 'P':
- display_inodes_perfdata = true;
+ 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_usedspace_units || crit_usedspace_units || warn_usedspace_percent || crit_usedspace_percent ||
- warn_usedinodes_percent || crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent)) {
+ if (!(result.config.warn_freespace_units || result.config.crit_freespace_units || result.config.warn_freespace_percent ||
+ result.config.crit_freespace_percent || result.config.warn_usedspace_units || result.config.crit_usedspace_units ||
+ result.config.warn_usedspace_percent || result.config.crit_usedspace_percent || result.config.warn_usedinodes_percent ||
+ result.config.crit_usedinodes_percent || result.config.warn_freeinodes_percent ||
+ result.config.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 */
struct parameter_list *se;
- if (!(se = np_find_parameter(path_select_list, optarg))) {
- se = np_add_parameter(&path_select_list, optarg);
+ if (!(se = np_find_parameter(result.config.path_select_list, optarg))) {
+ se = np_add_parameter(&result.config.path_select_list, optarg);
struct stat stat_buf = {};
- if (stat(optarg, &stat_buf) && ignore_missing) {
- path_ignored = true;
+ if (stat(optarg, &stat_buf) && result.config.ignore_missing) {
+ result.config.path_ignored = true;
break;
}
}
- se->group = group;
- set_all_thresholds(se);
+ se->group = result.config.group;
+ set_all_thresholds(
+ se, result.config.warn_freespace_units, result.config.crit_freespace_units, result.config.warn_freespace_percent,
+ result.config.crit_freespace_percent, result.config.warn_usedspace_units, result.config.crit_usedspace_units,
+ result.config.warn_usedspace_percent, result.config.crit_usedspace_percent, result.config.warn_usedinodes_percent,
+ result.config.crit_usedinodes_percent, result.config.warn_freeinodes_percent, result.config.crit_freeinodes_percent);
/* With autofs, it is required to stat() the path before re-populating the mount_list */
- if (!stat_path(se)) {
+ if (!stat_path(se, result.config.ignore_missing)) {
break;
}
/* NB: We can't free the old mount_list "just like that": both list pointers and struct
* pointers are copied around. One of the reason it wasn't done yet is that other parts
* of check_disk need the same kind of cleanup so it'd better be done as a whole */
- mount_list = read_file_system_list(false);
- np_set_best_match(se, mount_list, exact_match);
+ result.config.mount_list = read_file_system_list(false);
+ np_set_best_match(se, result.config.mount_list, result.config.exact_match);
- path_selected = true;
+ result.config.path_selected = true;
} break;
case 'x': /* exclude path or partition */
- np_add_name(&dp_exclude_list, optarg);
+ np_add_name(&result.config.device_path_exclude_list, optarg);
break;
case 'X': /* exclude file system type */ {
- int err = np_add_regex(&fs_exclude_list, optarg, REG_EXTENDED);
+ int err = np_add_regex(&result.config.fs_exclude_list, optarg, REG_EXTENDED);
if (err != 0) {
char errbuf[MAX_INPUT_BUFFER];
- regerror(err, &fs_exclude_list->regex, 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);
}
break;
case 'N': /* include file system type */
- err = np_add_regex(&fs_include_list, optarg, REG_EXTENDED);
+ err = np_add_regex(&result.config.fs_include_list, optarg, REG_EXTENDED);
if (err != 0) {
char errbuf[MAX_INPUT_BUFFER];
- regerror(err, &fs_exclude_list->regex, 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);
}
} break;
@@ -684,31 +669,31 @@ int process_arguments(int argc, char **argv) {
break;
case 'q': /* TODO: this function should eventually go away (removed 2007-09-20) */
/* verbose--; **replaced by line below**. -q was only a broken way of implementing -e */
- erronly = true;
+ result.config.erronly = true;
break;
case 'e':
- erronly = true;
+ result.config.erronly = true;
break;
case 'E':
- if (path_selected) {
+ if (result.config.path_selected) {
die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n"));
}
- exact_match = true;
+ result.config.exact_match = true;
break;
case 'f':
- freespace_ignore_reserved = true;
+ result.config.freespace_ignore_reserved = true;
break;
case 'g':
- if (path_selected) {
+ if (result.config.path_selected) {
die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n"));
}
- group = optarg;
+ result.config.group = optarg;
break;
case 'I':
cflags |= REG_ICASE;
// Intentional fallthrough
case 'i': {
- if (!path_selected) {
+ if (!result.config.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"));
}
@@ -720,7 +705,7 @@ int process_arguments(int argc, char **argv) {
die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
}
- struct parameter_list *temp_list = path_select_list;
+ struct parameter_list *temp_list = result.config.path_select_list;
struct parameter_list *previous = NULL;
while (temp_list) {
if (temp_list->best_match) {
@@ -733,7 +718,7 @@ int process_arguments(int argc, char **argv) {
temp_list = np_del_parameter(temp_list, previous);
/* pointer to first element needs to be updated if first item gets deleted */
if (previous == NULL) {
- path_select_list = temp_list;
+ result.config.path_select_list = temp_list;
}
} else {
previous = temp_list;
@@ -748,7 +733,7 @@ int process_arguments(int argc, char **argv) {
cflags = default_cflags;
} break;
case 'n':
- ignore_missing = true;
+ result.config.ignore_missing = true;
break;
case 'A':
optarg = strdup(".*");
@@ -757,9 +742,11 @@ int 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_usedspace_units || crit_usedspace_units || warn_usedspace_percent || crit_usedspace_percent ||
- warn_usedinodes_percent || crit_usedinodes_percent || warn_freeinodes_percent || crit_freeinodes_percent)) {
+ if (!(result.config.warn_freespace_units || result.config.crit_freespace_units || result.config.warn_freespace_percent ||
+ result.config.crit_freespace_percent || result.config.warn_usedspace_units || result.config.crit_usedspace_units ||
+ result.config.warn_usedspace_percent || result.config.crit_usedspace_percent || result.config.warn_usedinodes_percent ||
+ result.config.crit_usedinodes_percent || result.config.warn_freeinodes_percent ||
+ result.config.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"));
}
@@ -773,7 +760,7 @@ int process_arguments(int argc, char **argv) {
}
bool found = false;
- for (struct mount_entry *me = mount_list; me; me = me->me_next) {
+ for (struct mount_entry *me = result.config.mount_list; me; me = me->me_next) {
if (np_regex_match_mount_entry(me, ®ex)) {
found = true;
if (verbose >= 3) {
@@ -782,60 +769,69 @@ int process_arguments(int argc, char **argv) {
/* add parameter if not found. overwrite thresholds if path has already been added */
struct parameter_list *se = NULL;
- if (!(se = np_find_parameter(path_select_list, me->me_mountdir))) {
- se = np_add_parameter(&path_select_list, me->me_mountdir);
+ if (!(se = np_find_parameter(result.config.path_select_list, me->me_mountdir))) {
+ se = np_add_parameter(&result.config.path_select_list, me->me_mountdir);
}
- se->group = group;
- set_all_thresholds(se);
+ se->group = result.config.group;
+ set_all_thresholds(se, result.config.warn_freespace_units, result.config.crit_freespace_units,
+ result.config.warn_freespace_percent, result.config.crit_freespace_percent,
+ result.config.warn_usedspace_units, result.config.crit_usedspace_units,
+ result.config.warn_usedspace_percent, result.config.crit_usedspace_percent,
+ result.config.warn_usedinodes_percent, result.config.crit_usedinodes_percent,
+ result.config.warn_freeinodes_percent, result.config.crit_freeinodes_percent);
}
}
- if (!found && ignore_missing) {
- path_ignored = true;
- path_selected = true;
+ if (!found && result.config.ignore_missing) {
+ result.config.path_ignored = true;
+ result.config.path_selected = true;
break;
}
if (!found) {
die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Regular expression did not match any path or disk"), optarg);
}
- found = false;
- path_selected = true;
- np_set_best_match(path_select_list, mount_list, exact_match);
+ result.config.path_selected = true;
+ np_set_best_match(result.config.path_select_list, result.config.mount_list, result.config.exact_match);
cflags = default_cflags;
} break;
case 'M': /* display mountpoint */
- display_mntp = true;
+ 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 */
- if (!path_selected) {
+ if (!result.config.path_selected) {
struct parameter_list *path;
- for (struct mount_entry *me = mount_list; me; me = me->me_next) {
- if (!(path = np_find_parameter(path_select_list, me->me_mountdir))) {
- path = np_add_parameter(&path_select_list, me->me_mountdir);
+ for (struct mount_entry *me = result.config.mount_list; me; me = me->me_next) {
+ if (!(path = np_find_parameter(result.config.path_select_list, me->me_mountdir))) {
+ path = np_add_parameter(&result.config.path_select_list, me->me_mountdir);
}
path->best_match = me;
- path->group = group;
- set_all_thresholds(path);
+ path->group = result.config.group;
+ set_all_thresholds(path, result.config.warn_freespace_units, result.config.crit_freespace_units,
+ result.config.warn_freespace_percent, result.config.crit_freespace_percent,
+ result.config.warn_usedspace_units, result.config.crit_usedspace_units,
+ result.config.warn_usedspace_percent, result.config.crit_usedspace_percent,
+ result.config.warn_usedinodes_percent, result.config.crit_usedinodes_percent,
+ result.config.warn_freeinodes_percent, result.config.crit_freeinodes_percent);
}
}
- warn_freespace_units = NULL;
- crit_freespace_units = NULL;
- warn_usedspace_units = NULL;
- crit_usedspace_units = NULL;
- warn_freespace_percent = NULL;
- crit_freespace_percent = NULL;
- warn_usedspace_percent = NULL;
- crit_usedspace_percent = NULL;
- warn_usedinodes_percent = NULL;
- crit_usedinodes_percent = NULL;
- warn_freeinodes_percent = NULL;
- crit_freeinodes_percent = NULL;
-
- path_selected = false;
- group = NULL;
+ result.config.warn_freespace_units = NULL;
+ result.config.crit_freespace_units = NULL;
+ result.config.warn_usedspace_units = NULL;
+ result.config.crit_usedspace_units = NULL;
+ result.config.warn_freespace_percent = NULL;
+ result.config.crit_freespace_percent = NULL;
+ result.config.warn_usedspace_percent = NULL;
+ result.config.crit_usedspace_percent = NULL;
+ result.config.warn_usedinodes_percent = NULL;
+ result.config.crit_usedinodes_percent = NULL;
+ result.config.warn_freeinodes_percent = NULL;
+ result.config.crit_freeinodes_percent = NULL;
+
+ result.config.path_selected = false;
+ result.config.group = NULL;
} break;
case 'V': /* version */
print_revision(progname, NP_VERSION);
@@ -847,45 +843,49 @@ int process_arguments(int argc, char **argv) {
usage(_("Unknown argument"));
}
}
- if (verbose > 0) {
- printf("ping\n");
- }
/* Support for "check_disk warn crit [fs]" with thresholds at used% level */
int index = optind;
- if (warn_usedspace_percent == NULL && argc > index && is_intnonneg(argv[index])) {
+ if (result.config.warn_usedspace_percent == NULL && argc > index && is_intnonneg(argv[index])) {
if (verbose > 0) {
printf("Got an positional warn threshold: %s\n", argv[index]);
}
- warn_usedspace_percent = argv[index++];
+ result.config.warn_usedspace_percent = argv[index++];
}
- if (crit_usedspace_percent == NULL && argc > index && is_intnonneg(argv[index])) {
+ if (result.config.crit_usedspace_percent == NULL && argc > index && is_intnonneg(argv[index])) {
if (verbose > 0) {
printf("Got an positional crit threshold: %s\n", argv[index]);
}
- crit_usedspace_percent = argv[index++];
+ result.config.crit_usedspace_percent = argv[index++];
}
if (argc > index) {
if (verbose > 0) {
printf("Got an positional filesystem: %s\n", argv[index]);
}
- struct parameter_list *se = np_add_parameter(&path_select_list, strdup(argv[index++]));
- path_selected = true;
- set_all_thresholds(se);
+ struct parameter_list *se = np_add_parameter(&result.config.path_select_list, strdup(argv[index++]));
+ result.config.path_selected = true;
+ set_all_thresholds(se, result.config.warn_freespace_units, result.config.crit_freespace_units, result.config.warn_freespace_percent,
+ result.config.crit_freespace_percent, result.config.warn_usedspace_units, result.config.crit_usedspace_units,
+ result.config.warn_usedspace_percent, result.config.crit_usedspace_percent,
+ result.config.warn_usedinodes_percent, result.config.crit_usedinodes_percent,
+ result.config.warn_freeinodes_percent, result.config.crit_freeinodes_percent);
}
- if (units == NULL) {
- units = strdup("MiB");
- mult = (uintmax_t)1024 * 1024;
+ if (result.config.units == NULL) {
+ result.config.units = strdup("MiB");
+ result.config.mult = (uintmax_t)1024 * 1024;
}
- return 0;
+ return result;
}
-void set_all_thresholds(struct parameter_list *path) {
+void set_all_thresholds(struct parameter_list *path, char *warn_freespace_units, char *crit_freespace_units, char *warn_freespace_percent,
+ char *crit_freespace_percent, char *warn_usedspace_units, char *crit_usedspace_units, char *warn_usedspace_percent,
+ char *crit_usedspace_percent, char *warn_usedinodes_percent, char *crit_usedinodes_percent,
+ char *warn_freeinodes_percent, char *crit_freeinodes_percent) {
if (path->freespace_units != NULL) {
free(path->freespace_units);
}
@@ -1022,7 +1022,7 @@ void print_usage(void) {
printf("[-t timeout] [-u unit] [-v] [-X type_regex] [-N type]\n");
}
-bool stat_path(struct parameter_list *parameters) {
+bool stat_path(struct parameter_list *parameters, bool ignore_missing) {
/* Stat entry to check that dir exists and is accessible */
if (verbose >= 3) {
printf("calling stat on %s\n", parameters->name);
@@ -1043,12 +1043,13 @@ bool stat_path(struct parameter_list *parameters) {
return true;
}
-void get_stats(struct parameter_list *parameters, struct fs_usage *fsp) {
+void get_stats(struct parameter_list *parameters, struct fs_usage *fsp, bool ignore_missing, bool freespace_ignore_reserved, uintmax_t mult,
+ struct parameter_list *path_select_list, struct name_list *seen) {
struct fs_usage tmpfsp;
bool first = true;
if (parameters->group == NULL) {
- get_path_stats(parameters, fsp);
+ get_path_stats(parameters, fsp, freespace_ignore_reserved, mult, seen);
} else {
/* find all group members */
for (struct parameter_list *p_list = path_select_list; p_list; p_list = p_list->name_next) {
@@ -1060,11 +1061,11 @@ void get_stats(struct parameter_list *parameters, struct fs_usage *fsp) {
#endif
if (p_list->group && !(strcmp(p_list->group, parameters->group))) {
- if (!stat_path(p_list)) {
+ if (!stat_path(p_list, ignore_missing)) {
continue;
}
get_fs_usage(p_list->best_match->me_mountdir, p_list->best_match->me_devname, &tmpfsp);
- get_path_stats(p_list, &tmpfsp);
+ get_path_stats(p_list, &tmpfsp, freespace_ignore_reserved, mult, seen);
if (verbose >= 3) {
printf("Group %s: adding %lu blocks sized %lu, (%s) used_units=%lu free_units=%lu total_units=%lu mult=%lu\n",
p_list->group, tmpfsp.fsu_blocks, tmpfsp.fsu_blocksize, p_list->best_match->me_mountdir, p_list->dused_units,
@@ -1105,7 +1106,8 @@ void get_stats(struct parameter_list *parameters, struct fs_usage *fsp) {
parameters->dfree_inodes_percent = 100 - parameters->dused_inodes_percent;
}
-void get_path_stats(struct parameter_list *parameters, struct fs_usage *fsp) {
+void get_path_stats(struct parameter_list *parameters, struct fs_usage *fsp, bool freespace_ignore_reserved, uintmax_t mult,
+ struct name_list *seen) {
parameters->available = fsp->fsu_bavail;
parameters->available_to_root = fsp->fsu_bfree;
parameters->used = fsp->fsu_blocks - fsp->fsu_bfree;
diff --git a/plugins/check_disk.d/config.h b/plugins/check_disk.d/config.h
new file mode 100644
index 00000000..d890fc1a
--- /dev/null
+++ b/plugins/check_disk.d/config.h
@@ -0,0 +1,92 @@
+#pragma once
+
+#include "../../config.h"
+#include
+#include
+
+typedef struct {
+ // Output options
+ bool erronly;
+ bool display_mntp;
+ /* show only local filesystems. */
+ bool show_local_fs;
+ /* show only local filesystems but call stat() on remote ones. */
+ bool stat_remote_fs;
+ bool display_inodes_perfdata;
+
+ bool exact_match;
+ bool ignore_missing;
+ bool path_ignored;
+ bool path_selected;
+ bool freespace_ignore_reserved;
+
+ char *warn_freespace_units;
+ char *crit_freespace_units;
+ char *warn_freespace_percent;
+ char *crit_freespace_percent;
+ char *warn_usedspace_units;
+ char *crit_usedspace_units;
+ char *warn_usedspace_percent;
+ char *crit_usedspace_percent;
+ char *warn_usedinodes_percent;
+ char *crit_usedinodes_percent;
+ char *warn_freeinodes_percent;
+ char *crit_freeinodes_percent;
+
+ /* Linked list of filesystem types to omit.
+ If the list is empty, don't exclude any types. */
+ struct regex_list *fs_exclude_list;
+ /* Linked list of filesystem types to check.
+ If the list is empty, include all types. */
+ struct regex_list *fs_include_list;
+ struct name_list *device_path_exclude_list;
+ struct parameter_list *path_select_list;
+ /* Linked list of mounted filesystems. */
+ struct mount_entry *mount_list;
+ struct name_list *seen;
+
+ char *units;
+ uintmax_t mult;
+ char *group;
+} check_disk_config;
+
+check_disk_config check_disk_config_init() {
+ check_disk_config tmp = {
+ .erronly = false,
+ .display_mntp = false,
+ .show_local_fs = false,
+ .stat_remote_fs = false,
+ .display_inodes_perfdata = false,
+
+ .exact_match = false,
+ .ignore_missing = false,
+ .path_ignored = false,
+ .path_selected = false,
+ .freespace_ignore_reserved = false,
+
+ .warn_freespace_units = NULL,
+ .crit_freespace_units = NULL,
+ .warn_freespace_percent = NULL,
+ .crit_freespace_percent = NULL,
+ .warn_usedspace_units = NULL,
+ .crit_usedspace_units = NULL,
+ .warn_usedspace_percent = NULL,
+ .crit_usedspace_percent = NULL,
+ .warn_usedinodes_percent = NULL,
+ .crit_usedinodes_percent = NULL,
+ .warn_freeinodes_percent = NULL,
+ .crit_freeinodes_percent = NULL,
+
+ .fs_exclude_list = NULL,
+ .fs_include_list = NULL,
+ .device_path_exclude_list = NULL,
+ .path_select_list = NULL,
+ .mount_list = NULL,
+ .seen = NULL,
+
+ .units = NULL,
+ .mult = 1024 * 1024,
+ .group = NULL,
+ };
+ return tmp;
+}
--
cgit v1.2.3-74-g34f1
From 7994b478187d38c04dd2d7d9241d237875589738 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Tue, 18 Mar 2025 14:38:27 +0100
Subject: Adapt .gitignore
---
.gitignore | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.gitignore b/.gitignore
index 7f79265f..5245495e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -153,6 +153,8 @@ NP-VERSION-FILE
/plugins/check_dbi
/plugins/check_dig
/plugins/check_disk
+plugins/check_disk.d/.deps/
+plugins/check_disk.d/.dirstamp
/plugins/check_dns
/plugins/check_dummy
/plugins/check_fping
--
cgit v1.2.3-74-g34f1
From 59e0a258f9c0f393bf29cced1f35743f74e7b10c Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Tue, 18 Mar 2025 15:57:44 +0100
Subject: Migrate disk tests from lib, tool
---
.gitignore | 3 +-
configure.ac | 4 +-
lib/tests/Makefile.am | 6 +-
lib/tests/test_disk.c | 192 --------------------------------------
lib/tests/test_disk.t | 6 --
plugins/Makefile.am | 8 +-
plugins/check_disk.d/utils_disk.c | 4 +-
plugins/check_disk.d/utils_disk.h | 2 +-
plugins/common.h | 6 +-
plugins/tests/test_check_disk.c | 192 ++++++++++++++++++++++++++++++++++++++
plugins/tests/test_check_disk.t | 6 ++
11 files changed, 216 insertions(+), 213 deletions(-)
delete mode 100644 lib/tests/test_disk.c
delete mode 100755 lib/tests/test_disk.t
create mode 100644 plugins/tests/test_check_disk.c
create mode 100755 plugins/tests/test_check_disk.t
diff --git a/.gitignore b/.gitignore
index 5245495e..8b14f429 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,7 +114,6 @@ NP-VERSION-FILE
/lib/tests/Makefile.in
/lib/tests/test_base64
/lib/tests/test_cmd
-/lib/tests/test_disk
/lib/tests/test_tcp
/lib/tests/test_utils
/lib/tests/utils_base.Po
@@ -223,7 +222,7 @@ plugins/check_disk.d/.dirstamp
/plugins/tests/Makefile
/plugins/tests/Makefile.in
/plugins/tests/test_utils
-/plugins/tests/test_disk
+/plugins/tests/test_check_disk
/plugins/tests/test_check_swap
/plugins/tests/.deps
/plugins/tests/.dirstamp
diff --git a/configure.ac b/configure.ac
index 204fc6e3..fdc9b699 100644
--- a/configure.ac
+++ b/configure.ac
@@ -181,10 +181,10 @@ fi
# Finally, define tests if we use libtap
if test "$enable_libtap" = "yes" ; then
- EXTRA_TEST="test_utils test_disk test_tcp test_cmd test_base64"
+ EXTRA_TEST="test_utils test_tcp test_cmd test_base64"
AC_SUBST(EXTRA_TEST)
- EXTRA_PLUGIN_TESTS="tests/test_check_swap"
+ EXTRA_PLUGIN_TESTS="tests/test_check_swap tests/test_check_disk"
AC_SUBST(EXTRA_PLUGIN_TESTS)
fi
diff --git a/lib/tests/Makefile.am b/lib/tests/Makefile.am
index 9be94f6d..7798a72e 100644
--- a/lib/tests/Makefile.am
+++ b/lib/tests/Makefile.am
@@ -8,9 +8,9 @@ check_PROGRAMS = @EXTRA_TEST@
AM_CPPFLAGS = -DNP_STATE_DIR_PREFIX=\"$(localstatedir)\" \
-I$(top_srcdir)/lib -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/plugins
-EXTRA_PROGRAMS = test_utils test_disk test_tcp test_cmd test_base64 test_ini1 test_ini3 test_opts1 test_opts2 test_opts3 test_generic_output
+EXTRA_PROGRAMS = test_utils test_tcp test_cmd test_base64 test_ini1 test_ini3 test_opts1 test_opts2 test_opts3 test_generic_output
-np_test_scripts = test_base64.t test_cmd.t test_disk.t test_ini1.t test_ini3.t test_opts1.t test_opts2.t test_opts3.t test_tcp.t test_utils.t test_generic_output.t
+np_test_scripts = test_base64.t test_cmd.t test_ini1.t test_ini3.t test_opts1.t test_opts2.t test_opts3.t test_tcp.t test_utils.t test_generic_output.t
np_test_files = config-dos.ini config-opts.ini config-tiny.ini plugin.ini plugins.ini
EXTRA_DIST = $(np_test_scripts) $(np_test_files) var
@@ -29,7 +29,7 @@ AM_CFLAGS = -g -I$(top_srcdir)/lib -I$(top_srcdir)/gl $(tap_cflags)
AM_LDFLAGS = $(tap_ldflags) -ltap
LDADD = $(top_srcdir)/lib/libmonitoringplug.a $(top_srcdir)/gl/libgnu.a $(LIB_CRYPTO)
-SOURCES = test_utils.c test_disk.c test_tcp.c test_cmd.c test_base64.c test_ini1.c test_ini3.c test_opts1.c test_opts2.c test_opts3.c test_generic_output.c
+SOURCES = test_utils.c test_tcp.c test_cmd.c test_base64.c test_ini1.c test_ini3.c test_opts1.c test_opts2.c test_opts3.c test_generic_output.c
test: ${noinst_PROGRAMS}
perl -MTest::Harness -e '$$Test::Harness::switches=""; runtests(map {$$_ .= ".t"} @ARGV)' $(EXTRA_PROGRAMS)
diff --git a/lib/tests/test_disk.c b/lib/tests/test_disk.c
deleted file mode 100644
index c18db7a4..00000000
--- a/lib/tests/test_disk.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*****************************************************************************
- *
- * 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 "common.h"
-#include "utils_disk.h"
-#include "tap.h"
-#include "regex.h"
-
-void np_test_mount_entry_regex(struct mount_entry *dummy_mount_list, char *regstr, int cflags, int expect, char *desc);
-
-int main(int argc, char **argv) {
- struct name_list *exclude_filesystem = NULL;
- struct name_list *exclude_fstype = NULL;
- struct name_list *dummy_mountlist = NULL;
- struct name_list *temp_name;
- struct parameter_list *paths = NULL;
- struct parameter_list *p, *prev = NULL, *last = NULL;
-
- struct mount_entry *dummy_mount_list;
- struct mount_entry *me;
- struct mount_entry **mtail = &dummy_mount_list;
- int cflags = REG_NOSUB | REG_EXTENDED;
- int found = 0, count = 0;
-
- plan_tests(33);
-
- ok(np_find_name(exclude_filesystem, "/var/log") == false, "/var/log not in list");
- np_add_name(&exclude_filesystem, "/var/log");
- ok(np_find_name(exclude_filesystem, "/var/log") == true, "is in list now");
- ok(np_find_name(exclude_filesystem, "/home") == false, "/home not in list");
- np_add_name(&exclude_filesystem, "/home");
- ok(np_find_name(exclude_filesystem, "/home") == true, "is in list now");
- ok(np_find_name(exclude_filesystem, "/var/log") == true, "/var/log still in list");
-
- ok(np_find_name(exclude_fstype, "iso9660") == false, "iso9660 not in list");
- np_add_name(&exclude_fstype, "iso9660");
- ok(np_find_name(exclude_fstype, "iso9660") == true, "is in list now");
-
- ok(np_find_name(exclude_filesystem, "iso9660") == false, "Make sure no clashing in variables");
-
- /*
- for (temp_name = exclude_filesystem; temp_name; temp_name = temp_name->next) {
- printf("Name: %s\n", temp_name->name);
- }
- */
-
- me = (struct mount_entry *)malloc(sizeof *me);
- me->me_devname = strdup("/dev/c0t0d0s0");
- me->me_mountdir = strdup("/");
- *mtail = me;
- mtail = &me->me_next;
-
- me = (struct mount_entry *)malloc(sizeof *me);
- me->me_devname = strdup("/dev/c1t0d1s0");
- me->me_mountdir = strdup("/var");
- *mtail = me;
- mtail = &me->me_next;
-
- me = (struct mount_entry *)malloc(sizeof *me);
- me->me_devname = strdup("/dev/c2t0d0s0");
- me->me_mountdir = strdup("/home");
- *mtail = me;
- mtail = &me->me_next;
-
- np_test_mount_entry_regex(dummy_mount_list, strdup("/"), cflags, 3, strdup("a"));
- np_test_mount_entry_regex(dummy_mount_list, strdup("/dev"), cflags, 3, strdup("regex on dev names:"));
- np_test_mount_entry_regex(dummy_mount_list, strdup("/foo"), cflags, 0, strdup("regex on non existent dev/path:"));
- np_test_mount_entry_regex(dummy_mount_list, strdup("/Foo"), cflags | REG_ICASE, 0, strdup("regi on non existent dev/path:"));
- np_test_mount_entry_regex(dummy_mount_list, strdup("/c.t0"), cflags, 3, strdup("partial devname regex match:"));
- np_test_mount_entry_regex(dummy_mount_list, strdup("c0t0"), cflags, 1, strdup("partial devname regex match:"));
- np_test_mount_entry_regex(dummy_mount_list, strdup("C0t0"), cflags | REG_ICASE, 1, strdup("partial devname regi match:"));
- np_test_mount_entry_regex(dummy_mount_list, strdup("home"), cflags, 1, strdup("partial pathname regex match:"));
- np_test_mount_entry_regex(dummy_mount_list, strdup("hOme"), cflags | REG_ICASE, 1, strdup("partial pathname regi match:"));
- np_test_mount_entry_regex(dummy_mount_list, strdup("(/home)|(/var)"), cflags, 2, strdup("grouped regex pathname match:"));
- np_test_mount_entry_regex(dummy_mount_list, strdup("(/homE)|(/Var)"), cflags | REG_ICASE, 2, strdup("grouped regi pathname match:"));
-
- np_add_parameter(&paths, "/home/groups");
- np_add_parameter(&paths, "/var");
- np_add_parameter(&paths, "/tmp");
- np_add_parameter(&paths, "/home/tonvoon");
- np_add_parameter(&paths, "/dev/c2t0d0s0");
-
- np_set_best_match(paths, dummy_mount_list, false);
- for (p = paths; p; p = p->name_next) {
- struct mount_entry *temp_me;
- temp_me = p->best_match;
- if (!strcmp(p->name, "/home/groups")) {
- ok(temp_me && !strcmp(temp_me->me_mountdir, "/home"), "/home/groups got right best match: /home");
- } else if (!strcmp(p->name, "/var")) {
- ok(temp_me && !strcmp(temp_me->me_mountdir, "/var"), "/var got right best match: /var");
- } else if (!strcmp(p->name, "/tmp")) {
- ok(temp_me && !strcmp(temp_me->me_mountdir, "/"), "/tmp got right best match: /");
- } else if (!strcmp(p->name, "/home/tonvoon")) {
- ok(temp_me && !strcmp(temp_me->me_mountdir, "/home"), "/home/tonvoon got right best match: /home");
- } else if (!strcmp(p->name, "/dev/c2t0d0s0")) {
- ok(temp_me && !strcmp(temp_me->me_devname, "/dev/c2t0d0s0"), "/dev/c2t0d0s0 got right best match: /dev/c2t0d0s0");
- }
- }
-
- paths = NULL; /* Bad boy - should free, but this is a test suite */
- np_add_parameter(&paths, "/home/groups");
- np_add_parameter(&paths, "/var");
- np_add_parameter(&paths, "/tmp");
- np_add_parameter(&paths, "/home/tonvoon");
- np_add_parameter(&paths, "/home");
-
- np_set_best_match(paths, dummy_mount_list, true);
- for (p = paths; p; p = p->name_next) {
- if (!strcmp(p->name, "/home/groups")) {
- ok(!p->best_match, "/home/groups correctly not found");
- } else if (!strcmp(p->name, "/var")) {
- ok(p->best_match, "/var found");
- } else if (!strcmp(p->name, "/tmp")) {
- ok(!p->best_match, "/tmp correctly not found");
- } else if (!strcmp(p->name, "/home/tonvoon")) {
- ok(!p->best_match, "/home/tonvoon not found");
- } else if (!strcmp(p->name, "/home")) {
- ok(p->best_match, "/home found");
- }
- }
-
- /* test deleting first element in paths */
- paths = np_del_parameter(paths, NULL);
- for (p = paths; p; p = p->name_next) {
- if (!strcmp(p->name, "/home/groups"))
- found = 1;
- }
- ok(found == 0, "first element successfully deleted");
- found = 0;
-
- p = paths;
- while (p) {
- if (!strcmp(p->name, "/tmp"))
- p = np_del_parameter(p, prev);
- else {
- prev = p;
- p = p->name_next;
- }
- }
-
- for (p = paths; p; p = p->name_next) {
- if (!strcmp(p->name, "/tmp"))
- found = 1;
- if (p->name_next)
- prev = p;
- else
- last = p;
- }
- ok(found == 0, "/tmp element successfully deleted");
-
- p = np_del_parameter(last, prev);
- for (p = paths; p; p = p->name_next) {
- if (!strcmp(p->name, "/home"))
- found = 1;
- last = p;
- count++;
- }
- ok(found == 0, "last (/home) element successfully deleted");
- ok(count == 2, "two elements remaining");
-
- return exit_status();
-}
-
-void np_test_mount_entry_regex(struct mount_entry *dummy_mount_list, char *regstr, int cflags, int expect, char *desc) {
- int matches = 0;
- regex_t re;
- struct mount_entry *me;
- if (regcomp(&re, regstr, cflags) == 0) {
- for (me = dummy_mount_list; me; me = me->me_next) {
- if (np_regex_match_mount_entry(me, &re))
- matches++;
- }
- ok(matches == expect, "%s '%s' matched %i/3 entries. ok: %i/3", desc, regstr, expect, matches);
-
- } else
- ok(false, "regex '%s' not compilable", regstr);
-}
diff --git a/lib/tests/test_disk.t b/lib/tests/test_disk.t
deleted file mode 100755
index da84dfdf..00000000
--- a/lib/tests/test_disk.t
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/perl
-use Test::More;
-if (! -e "./test_disk") {
- plan skip_all => "./test_disk not compiled - please enable libtap library to test";
-}
-exec "./test_disk";
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 30283cb4..04fb7ed2 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -40,11 +40,13 @@ EXTRA_PROGRAMS = check_mysql check_radius check_pgsql check_snmp check_hpjd \
check_nagios check_by_ssh check_dns check_nt check_ide_smart \
check_procs check_mysql_query check_apt check_dbi check_curl \
\
- tests/test_check_swap
+ tests/test_check_swap \
+ tests/test_check_disk
SUBDIRS = picohttpparser
-np_test_scripts = tests/test_check_swap.t
+np_test_scripts = tests/test_check_swap.t \
+ tests/test_check_disk.t
EXTRA_DIST = t \
tests \
@@ -167,6 +169,8 @@ endif
tests_test_check_swap_LDADD = $(BASEOBJS) $(tap_ldflags) -ltap
tests_test_check_swap_SOURCES = tests/test_check_swap.c check_swap.d/swap.c
+tests_test_check_disk_LDADD = $(BASEOBJS) $(tap_ldflags) check_disk.d/utils_disk.c -ltap
+tests_test_check_disk_SOURCES = tests/test_check_disk.c
##############################################################################
# secondary dependencies
diff --git a/plugins/check_disk.d/utils_disk.c b/plugins/check_disk.d/utils_disk.c
index 1d806715..369c85d5 100644
--- a/plugins/check_disk.d/utils_disk.c
+++ b/plugins/check_disk.d/utils_disk.c
@@ -26,9 +26,9 @@
*
*****************************************************************************/
-#include "common.h"
+#include "../common.h"
#include "utils_disk.h"
-#include "gl/fsusage.h"
+#include "../../gl/fsusage.h"
#include
void np_add_name(struct name_list **list, const char *name) {
diff --git a/plugins/check_disk.d/utils_disk.h b/plugins/check_disk.d/utils_disk.h
index 1c68fed9..0c69f987 100644
--- a/plugins/check_disk.d/utils_disk.h
+++ b/plugins/check_disk.d/utils_disk.h
@@ -2,7 +2,7 @@
#include "../../config.h"
#include "../../gl/mountlist.h"
-#include "utils_base.h"
+#include "../../lib/utils_base.h"
#include "regex.h"
#include
diff --git a/plugins/common.h b/plugins/common.h
index 603bae55..35d1e549 100644
--- a/plugins/common.h
+++ b/plugins/common.h
@@ -31,7 +31,7 @@
#ifndef _COMMON_H_
#define _COMMON_H_
-#include "config.h"
+#include "../config.h"
#include "../lib/monitoringplug.h"
#ifdef HAVE_FEATURES_H
@@ -110,7 +110,7 @@
/* GNU Libraries */
#include
-#include "dirname.h"
+#include "../gl/dirname.h"
#include
@@ -190,7 +190,7 @@ enum {
* Internationalization
*
*/
-#include "gettext.h"
+#include "../gl/gettext.h"
#define _(String) gettext (String)
#if ! ENABLE_NLS
# undef textdomain
diff --git a/plugins/tests/test_check_disk.c b/plugins/tests/test_check_disk.c
new file mode 100644
index 00000000..92d0d270
--- /dev/null
+++ b/plugins/tests/test_check_disk.c
@@ -0,0 +1,192 @@
+/*****************************************************************************
+ *
+ * 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 "common.h"
+#include "../check_disk.d/utils_disk.h"
+#include "../../tap/tap.h"
+#include "regex.h"
+
+void np_test_mount_entry_regex(struct mount_entry *dummy_mount_list, char *regstr, int cflags, int expect, char *desc);
+
+int main(int argc, char **argv) {
+ struct name_list *exclude_filesystem = NULL;
+ struct name_list *exclude_fstype = NULL;
+ struct name_list *dummy_mountlist = NULL;
+ struct name_list *temp_name;
+ struct parameter_list *paths = NULL;
+ struct parameter_list *p, *prev = NULL, *last = NULL;
+
+ struct mount_entry *dummy_mount_list;
+ struct mount_entry *me;
+ struct mount_entry **mtail = &dummy_mount_list;
+ int cflags = REG_NOSUB | REG_EXTENDED;
+ int found = 0, count = 0;
+
+ plan_tests(33);
+
+ ok(np_find_name(exclude_filesystem, "/var/log") == false, "/var/log not in list");
+ np_add_name(&exclude_filesystem, "/var/log");
+ ok(np_find_name(exclude_filesystem, "/var/log") == true, "is in list now");
+ ok(np_find_name(exclude_filesystem, "/home") == false, "/home not in list");
+ np_add_name(&exclude_filesystem, "/home");
+ ok(np_find_name(exclude_filesystem, "/home") == true, "is in list now");
+ ok(np_find_name(exclude_filesystem, "/var/log") == true, "/var/log still in list");
+
+ ok(np_find_name(exclude_fstype, "iso9660") == false, "iso9660 not in list");
+ np_add_name(&exclude_fstype, "iso9660");
+ ok(np_find_name(exclude_fstype, "iso9660") == true, "is in list now");
+
+ ok(np_find_name(exclude_filesystem, "iso9660") == false, "Make sure no clashing in variables");
+
+ /*
+ for (temp_name = exclude_filesystem; temp_name; temp_name = temp_name->next) {
+ printf("Name: %s\n", temp_name->name);
+ }
+ */
+
+ me = (struct mount_entry *)malloc(sizeof *me);
+ me->me_devname = strdup("/dev/c0t0d0s0");
+ me->me_mountdir = strdup("/");
+ *mtail = me;
+ mtail = &me->me_next;
+
+ me = (struct mount_entry *)malloc(sizeof *me);
+ me->me_devname = strdup("/dev/c1t0d1s0");
+ me->me_mountdir = strdup("/var");
+ *mtail = me;
+ mtail = &me->me_next;
+
+ me = (struct mount_entry *)malloc(sizeof *me);
+ me->me_devname = strdup("/dev/c2t0d0s0");
+ me->me_mountdir = strdup("/home");
+ *mtail = me;
+ mtail = &me->me_next;
+
+ np_test_mount_entry_regex(dummy_mount_list, strdup("/"), cflags, 3, strdup("a"));
+ np_test_mount_entry_regex(dummy_mount_list, strdup("/dev"), cflags, 3, strdup("regex on dev names:"));
+ np_test_mount_entry_regex(dummy_mount_list, strdup("/foo"), cflags, 0, strdup("regex on non existent dev/path:"));
+ np_test_mount_entry_regex(dummy_mount_list, strdup("/Foo"), cflags | REG_ICASE, 0, strdup("regi on non existent dev/path:"));
+ np_test_mount_entry_regex(dummy_mount_list, strdup("/c.t0"), cflags, 3, strdup("partial devname regex match:"));
+ np_test_mount_entry_regex(dummy_mount_list, strdup("c0t0"), cflags, 1, strdup("partial devname regex match:"));
+ np_test_mount_entry_regex(dummy_mount_list, strdup("C0t0"), cflags | REG_ICASE, 1, strdup("partial devname regi match:"));
+ np_test_mount_entry_regex(dummy_mount_list, strdup("home"), cflags, 1, strdup("partial pathname regex match:"));
+ np_test_mount_entry_regex(dummy_mount_list, strdup("hOme"), cflags | REG_ICASE, 1, strdup("partial pathname regi match:"));
+ np_test_mount_entry_regex(dummy_mount_list, strdup("(/home)|(/var)"), cflags, 2, strdup("grouped regex pathname match:"));
+ np_test_mount_entry_regex(dummy_mount_list, strdup("(/homE)|(/Var)"), cflags | REG_ICASE, 2, strdup("grouped regi pathname match:"));
+
+ np_add_parameter(&paths, "/home/groups");
+ np_add_parameter(&paths, "/var");
+ np_add_parameter(&paths, "/tmp");
+ np_add_parameter(&paths, "/home/tonvoon");
+ np_add_parameter(&paths, "/dev/c2t0d0s0");
+
+ np_set_best_match(paths, dummy_mount_list, false);
+ for (p = paths; p; p = p->name_next) {
+ struct mount_entry *temp_me;
+ temp_me = p->best_match;
+ if (!strcmp(p->name, "/home/groups")) {
+ ok(temp_me && !strcmp(temp_me->me_mountdir, "/home"), "/home/groups got right best match: /home");
+ } else if (!strcmp(p->name, "/var")) {
+ ok(temp_me && !strcmp(temp_me->me_mountdir, "/var"), "/var got right best match: /var");
+ } else if (!strcmp(p->name, "/tmp")) {
+ ok(temp_me && !strcmp(temp_me->me_mountdir, "/"), "/tmp got right best match: /");
+ } else if (!strcmp(p->name, "/home/tonvoon")) {
+ ok(temp_me && !strcmp(temp_me->me_mountdir, "/home"), "/home/tonvoon got right best match: /home");
+ } else if (!strcmp(p->name, "/dev/c2t0d0s0")) {
+ ok(temp_me && !strcmp(temp_me->me_devname, "/dev/c2t0d0s0"), "/dev/c2t0d0s0 got right best match: /dev/c2t0d0s0");
+ }
+ }
+
+ paths = NULL; /* Bad boy - should free, but this is a test suite */
+ np_add_parameter(&paths, "/home/groups");
+ np_add_parameter(&paths, "/var");
+ np_add_parameter(&paths, "/tmp");
+ np_add_parameter(&paths, "/home/tonvoon");
+ np_add_parameter(&paths, "/home");
+
+ np_set_best_match(paths, dummy_mount_list, true);
+ for (p = paths; p; p = p->name_next) {
+ if (!strcmp(p->name, "/home/groups")) {
+ ok(!p->best_match, "/home/groups correctly not found");
+ } else if (!strcmp(p->name, "/var")) {
+ ok(p->best_match, "/var found");
+ } else if (!strcmp(p->name, "/tmp")) {
+ ok(!p->best_match, "/tmp correctly not found");
+ } else if (!strcmp(p->name, "/home/tonvoon")) {
+ ok(!p->best_match, "/home/tonvoon not found");
+ } else if (!strcmp(p->name, "/home")) {
+ ok(p->best_match, "/home found");
+ }
+ }
+
+ /* test deleting first element in paths */
+ paths = np_del_parameter(paths, NULL);
+ for (p = paths; p; p = p->name_next) {
+ if (!strcmp(p->name, "/home/groups"))
+ found = 1;
+ }
+ ok(found == 0, "first element successfully deleted");
+ found = 0;
+
+ p = paths;
+ while (p) {
+ if (!strcmp(p->name, "/tmp"))
+ p = np_del_parameter(p, prev);
+ else {
+ prev = p;
+ p = p->name_next;
+ }
+ }
+
+ for (p = paths; p; p = p->name_next) {
+ if (!strcmp(p->name, "/tmp"))
+ found = 1;
+ if (p->name_next)
+ prev = p;
+ else
+ last = p;
+ }
+ ok(found == 0, "/tmp element successfully deleted");
+
+ p = np_del_parameter(last, prev);
+ for (p = paths; p; p = p->name_next) {
+ if (!strcmp(p->name, "/home"))
+ found = 1;
+ last = p;
+ count++;
+ }
+ ok(found == 0, "last (/home) element successfully deleted");
+ ok(count == 2, "two elements remaining");
+
+ return exit_status();
+}
+
+void np_test_mount_entry_regex(struct mount_entry *dummy_mount_list, char *regstr, int cflags, int expect, char *desc) {
+ int matches = 0;
+ regex_t re;
+ struct mount_entry *me;
+ if (regcomp(&re, regstr, cflags) == 0) {
+ for (me = dummy_mount_list; me; me = me->me_next) {
+ if (np_regex_match_mount_entry(me, &re))
+ matches++;
+ }
+ ok(matches == expect, "%s '%s' matched %i/3 entries. ok: %i/3", desc, regstr, expect, matches);
+
+ } else
+ ok(false, "regex '%s' not compilable", regstr);
+}
diff --git a/plugins/tests/test_check_disk.t b/plugins/tests/test_check_disk.t
new file mode 100755
index 00000000..56354650
--- /dev/null
+++ b/plugins/tests/test_check_disk.t
@@ -0,0 +1,6 @@
+#!/usr/bin/perl
+use Test::More;
+if (! -e "./test_check_disk") {
+ plan skip_all => "./test_check_disk not compiled - please enable libtap library to test";
+}
+exec "./test_check_disk";
--
cgit v1.2.3-74-g34f1
From 75cf0d307285c413d5547662e5ba677e1f70de62 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Tue, 18 Mar 2025 16:23:06 +0100
Subject: Remove some unused code
---
plugins/check_disk.c | 8 --------
1 file changed, 8 deletions(-)
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index 2df89aa3..15ec06cd 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -65,14 +65,6 @@ const char *email = "devel@monitoring-plugins.org";
# define ERROR -1
#endif
-/* For long options that have no equivalent short option, use a
- non-character as a pseudo short option, starting with CHAR_MAX + 1. */
-enum {
- SYNC_OPTION = CHAR_MAX + 1,
- NO_SYNC_OPTION,
- BLOCK_SIZE_OPTION
-};
-
#ifdef _AIX
# pragma alloca
#endif
--
cgit v1.2.3-74-g34f1
From 42531fa92a97318f2b96265f501f37e7fd96ea4c Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Tue, 18 Mar 2025 16:23:33 +0100
Subject: Refactor test_check_disk.c
---
plugins/tests/test_check_disk.c | 86 +++++++++++++++++++++--------------------
1 file changed, 44 insertions(+), 42 deletions(-)
diff --git a/plugins/tests/test_check_disk.c b/plugins/tests/test_check_disk.c
index 92d0d270..963a9413 100644
--- a/plugins/tests/test_check_disk.c
+++ b/plugins/tests/test_check_disk.c
@@ -24,21 +24,9 @@
void np_test_mount_entry_regex(struct mount_entry *dummy_mount_list, char *regstr, int cflags, int expect, char *desc);
int main(int argc, char **argv) {
- struct name_list *exclude_filesystem = NULL;
- struct name_list *exclude_fstype = NULL;
- struct name_list *dummy_mountlist = NULL;
- struct name_list *temp_name;
- struct parameter_list *paths = NULL;
- struct parameter_list *p, *prev = NULL, *last = NULL;
-
- struct mount_entry *dummy_mount_list;
- struct mount_entry *me;
- struct mount_entry **mtail = &dummy_mount_list;
- int cflags = REG_NOSUB | REG_EXTENDED;
- int found = 0, count = 0;
-
plan_tests(33);
+ struct name_list *exclude_filesystem = NULL;
ok(np_find_name(exclude_filesystem, "/var/log") == false, "/var/log not in list");
np_add_name(&exclude_filesystem, "/var/log");
ok(np_find_name(exclude_filesystem, "/var/log") == true, "is in list now");
@@ -47,6 +35,7 @@ int main(int argc, char **argv) {
ok(np_find_name(exclude_filesystem, "/home") == true, "is in list now");
ok(np_find_name(exclude_filesystem, "/var/log") == true, "/var/log still in list");
+ struct name_list *exclude_fstype = NULL;
ok(np_find_name(exclude_fstype, "iso9660") == false, "iso9660 not in list");
np_add_name(&exclude_fstype, "iso9660");
ok(np_find_name(exclude_fstype, "iso9660") == true, "is in list now");
@@ -59,7 +48,9 @@ int main(int argc, char **argv) {
}
*/
- me = (struct mount_entry *)malloc(sizeof *me);
+ struct mount_entry *dummy_mount_list;
+ struct mount_entry **mtail = &dummy_mount_list;
+ struct mount_entry *me = (struct mount_entry *)malloc(sizeof *me);
me->me_devname = strdup("/dev/c0t0d0s0");
me->me_mountdir = strdup("/");
*mtail = me;
@@ -77,6 +68,7 @@ int main(int argc, char **argv) {
*mtail = me;
mtail = &me->me_next;
+ int cflags = REG_NOSUB | REG_EXTENDED;
np_test_mount_entry_regex(dummy_mount_list, strdup("/"), cflags, 3, strdup("a"));
np_test_mount_entry_regex(dummy_mount_list, strdup("/dev"), cflags, 3, strdup("regex on dev names:"));
np_test_mount_entry_regex(dummy_mount_list, strdup("/foo"), cflags, 0, strdup("regex on non existent dev/path:"));
@@ -89,6 +81,7 @@ int main(int argc, char **argv) {
np_test_mount_entry_regex(dummy_mount_list, strdup("(/home)|(/var)"), cflags, 2, strdup("grouped regex pathname match:"));
np_test_mount_entry_regex(dummy_mount_list, strdup("(/homE)|(/Var)"), cflags | REG_ICASE, 2, strdup("grouped regi pathname match:"));
+ struct parameter_list *paths = NULL;
np_add_parameter(&paths, "/home/groups");
np_add_parameter(&paths, "/var");
np_add_parameter(&paths, "/tmp");
@@ -96,7 +89,7 @@ int main(int argc, char **argv) {
np_add_parameter(&paths, "/dev/c2t0d0s0");
np_set_best_match(paths, dummy_mount_list, false);
- for (p = paths; p; p = p->name_next) {
+ for (struct parameter_list *p = paths; p; p = p->name_next) {
struct mount_entry *temp_me;
temp_me = p->best_match;
if (!strcmp(p->name, "/home/groups")) {
@@ -120,7 +113,7 @@ int main(int argc, char **argv) {
np_add_parameter(&paths, "/home");
np_set_best_match(paths, dummy_mount_list, true);
- for (p = paths; p; p = p->name_next) {
+ for (struct parameter_list *p = paths; p; p = p->name_next) {
if (!strcmp(p->name, "/home/groups")) {
ok(!p->best_match, "/home/groups correctly not found");
} else if (!strcmp(p->name, "/var")) {
@@ -134,59 +127,68 @@ int main(int argc, char **argv) {
}
}
+ bool found = false;
/* test deleting first element in paths */
paths = np_del_parameter(paths, NULL);
- for (p = paths; p; p = p->name_next) {
- if (!strcmp(p->name, "/home/groups"))
- found = 1;
+ for (struct parameter_list *p = paths; p; p = p->name_next) {
+ if (!strcmp(p->name, "/home/groups")) {
+ found = true;
+ }
}
- ok(found == 0, "first element successfully deleted");
- found = 0;
+ ok(!found, "first element successfully deleted");
+ found = false;
- p = paths;
+ struct parameter_list *prev = NULL;
+ struct parameter_list *p = paths;
while (p) {
- if (!strcmp(p->name, "/tmp"))
+ if (!strcmp(p->name, "/tmp")) {
p = np_del_parameter(p, prev);
- else {
+ } else {
prev = p;
p = p->name_next;
}
}
- for (p = paths; p; p = p->name_next) {
- if (!strcmp(p->name, "/tmp"))
- found = 1;
- if (p->name_next)
- prev = p;
- else
- last = p;
+ struct parameter_list *last = NULL;
+ for (struct parameter_list *path = paths; path; path = path->name_next) {
+ if (!strcmp(path->name, "/tmp")) {
+ found = true;
+ }
+ if (path->name_next) {
+ prev = path;
+ } else {
+ last = path;
+ }
}
- ok(found == 0, "/tmp element successfully deleted");
+ ok(!found, "/tmp element successfully deleted");
+ int count = 0;
p = np_del_parameter(last, prev);
for (p = paths; p; p = p->name_next) {
- if (!strcmp(p->name, "/home"))
- found = 1;
+ if (!strcmp(p->name, "/home")) {
+ found = true;
+ }
last = p;
count++;
}
- ok(found == 0, "last (/home) element successfully deleted");
+ ok(!found, "last (/home) element successfully deleted");
ok(count == 2, "two elements remaining");
return exit_status();
}
void np_test_mount_entry_regex(struct mount_entry *dummy_mount_list, char *regstr, int cflags, int expect, char *desc) {
- int matches = 0;
- regex_t re;
- struct mount_entry *me;
- if (regcomp(&re, regstr, cflags) == 0) {
- for (me = dummy_mount_list; me; me = me->me_next) {
- if (np_regex_match_mount_entry(me, &re))
+ regex_t regex;
+ if (regcomp(®ex, regstr, cflags) == 0) {
+ int matches = 0;
+ for (struct mount_entry *me = dummy_mount_list; me; me = me->me_next) {
+ if (np_regex_match_mount_entry(me, ®ex)) {
matches++;
+ }
}
ok(matches == expect, "%s '%s' matched %i/3 entries. ok: %i/3", desc, regstr, expect, matches);
- } else
+ } else {
ok(false, "regex '%s' not compilable", regstr);
+ }
}
--
cgit v1.2.3-74-g34f1
From a0710dbd72ea6314cf6a1ec50d2fa3c3c0543748 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Tue, 18 Mar 2025 16:26:14 +0100
Subject: check_disk: Remove unnecessary NULL checks
---
plugins/check_disk.c | 24 ++++++------------------
1 file changed, 6 insertions(+), 18 deletions(-)
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index 15ec06cd..050298d6 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -878,34 +878,22 @@ void set_all_thresholds(struct parameter_list *path, char *warn_freespace_units,
char *crit_freespace_percent, char *warn_usedspace_units, char *crit_usedspace_units, char *warn_usedspace_percent,
char *crit_usedspace_percent, char *warn_usedinodes_percent, char *crit_usedinodes_percent,
char *warn_freeinodes_percent, char *crit_freeinodes_percent) {
- if (path->freespace_units != NULL) {
- free(path->freespace_units);
- }
+ free(path->freespace_units);
set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units);
- if (path->freespace_percent != NULL) {
- free(path->freespace_percent);
- }
+ free(path->freespace_percent);
set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent);
- if (path->usedspace_units != NULL) {
- free(path->usedspace_units);
- }
+ free(path->usedspace_units);
set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units);
- if (path->usedspace_percent != NULL) {
- free(path->usedspace_percent);
- }
+ free(path->usedspace_percent);
set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent);
- if (path->usedinodes_percent != NULL) {
- free(path->usedinodes_percent);
- }
+ free(path->usedinodes_percent);
set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent);
- if (path->freeinodes_percent != NULL) {
- free(path->freeinodes_percent);
- }
+ free(path->freeinodes_percent);
set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent);
}
--
cgit v1.2.3-74-g34f1
From f84f614f219b395810e4ca35d5eb5f5a8d2f1d5b Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Sun, 30 Mar 2025 22:34:20 +0200
Subject: Bugfix in output
---
lib/output.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/lib/output.c b/lib/output.c
index 61fbf832..01e50770 100644
--- a/lib/output.c
+++ b/lib/output.c
@@ -13,6 +13,7 @@
// == Global variables
static mp_output_format output_format = MP_FORMAT_DEFAULT;
+static mp_output_detail_level level_of_detail = MP_DETAIL_ALL;
// == Prototypes ==
static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation);
@@ -202,7 +203,12 @@ mp_state_enum mp_compute_subcheck_state(const mp_subcheck check) {
}
mp_subcheck_list *scl = check.subchecks;
- mp_state_enum result = check.default_state;
+
+ if (scl == NULL) {
+ return check.default_state;
+ }
+
+ mp_state_enum result = STATE_OK;
while (scl != NULL) {
result = max_state_alt(result, mp_compute_subcheck_state(scl->subcheck));
--
cgit v1.2.3-74-g34f1
From f413ac38e30e606beda4ef7f6bf1db40b49682d3 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Sun, 30 Mar 2025 22:34:42 +0200
Subject: Add selectable level of detail for output
---
lib/output.c | 8 +++++++-
lib/output.h | 16 +++++++++++++---
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/lib/output.c b/lib/output.c
index 01e50770..c408a2f5 100644
--- a/lib/output.c
+++ b/lib/output.c
@@ -253,7 +253,9 @@ char *mp_fmt_output(mp_check check) {
mp_subcheck_list *subchecks = check.subchecks;
while (subchecks != NULL) {
- asprintf(&result, "%s\n%s", result, fmt_subcheck_output(MP_FORMAT_MULTI_LINE, subchecks->subcheck, 1));
+ if (level_of_detail == MP_DETAIL_ALL || mp_compute_subcheck_state(subchecks->subcheck) != STATE_OK) {
+ asprintf(&result, "%s\n%s", result, fmt_subcheck_output(MP_FORMAT_MULTI_LINE, subchecks->subcheck, 1));
+ }
subchecks = subchecks->next;
}
@@ -545,3 +547,7 @@ parsed_output_format mp_parse_output_format(char *format_string) {
void mp_set_format(mp_output_format format) { output_format = format; }
mp_output_format mp_get_format(void) { return output_format; }
+
+void mp_set_level_of_detail(mp_output_detail_level level) { level_of_detail = level; }
+
+mp_output_detail_level mp_get_level_of_detail(void) { return level_of_detail; }
diff --git a/lib/output.h b/lib/output.h
index 2bdfa074..3bd91f90 100644
--- a/lib/output.h
+++ b/lib/output.h
@@ -38,8 +38,18 @@ typedef enum output_format {
/*
* Format related functions
*/
- void mp_set_format(mp_output_format format);
- mp_output_format mp_get_format(void);
+void mp_set_format(mp_output_format format);
+mp_output_format mp_get_format(void);
+
+// Output detail level
+
+typedef enum output_detail_level {
+ MP_DETAIL_ALL,
+ MP_DETAIL_NON_OK_ONLY,
+} mp_output_detail_level;
+
+void mp_set_level_of_detail(mp_output_detail_level level);
+mp_output_detail_level mp_get_level_of_detail(void);
/*
* The main state object of a plugin. Exists only ONCE per plugin.
@@ -48,7 +58,7 @@ typedef enum output_format {
* in the first layer of subchecks
*/
typedef struct {
- char *summary; // Overall summary, if not set a summary will be automatically generated
+ char *summary; // Overall summary, if not set a summary will be automatically generated
mp_subcheck_list *subchecks;
} mp_check;
--
cgit v1.2.3-74-g34f1
From 1921cfccd6d83edb15a04fdb143a3176fb96dd22 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Sun, 30 Mar 2025 22:35:29 +0200
Subject: Always quote perfdata labels
---
lib/perfdata.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/perfdata.c b/lib/perfdata.c
index 661756c5..4f9c9558 100644
--- a/lib/perfdata.c
+++ b/lib/perfdata.c
@@ -33,7 +33,7 @@ char *pd_value_to_string(const mp_perfdata_value pd) {
char *pd_to_string(mp_perfdata pd) {
assert(pd.label != NULL);
char *result = NULL;
- asprintf(&result, "%s=", pd.label);
+ asprintf(&result, "'%s'=", pd.label);
asprintf(&result, "%s%s", result, pd_value_to_string(pd.value));
--
cgit v1.2.3-74-g34f1
From 6e108cc25e75ec74013838620b26dabdd480718a Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Sun, 30 Mar 2025 22:36:07 +0200
Subject: Add more helpers to perfdata functions
---
lib/perfdata.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/perfdata.h | 12 ++++++++
2 files changed, 99 insertions(+)
diff --git a/lib/perfdata.c b/lib/perfdata.c
index 4f9c9558..1742342e 100644
--- a/lib/perfdata.c
+++ b/lib/perfdata.c
@@ -514,3 +514,90 @@ perfdata_value_parser_wrapper parse_pd_value(const char *input) {
}
return result;
}
+
+mp_perfdata mp_set_pd_max_value(mp_perfdata perfdata, mp_perfdata_value value) {
+ perfdata.max = value;
+ perfdata.max_present = true;
+ return perfdata;
+}
+
+mp_perfdata mp_set_pd_min_value(mp_perfdata perfdata, mp_perfdata_value value) {
+ perfdata.min = value;
+ perfdata.min_present = true;
+ return perfdata;
+}
+
+double mp_get_pd_value(mp_perfdata_value value) {
+ assert(value.type != PD_TYPE_NONE);
+ switch (value.type) {
+ case PD_TYPE_DOUBLE:
+ return value.pd_double;
+ case PD_TYPE_INT:
+ return (double)value.pd_int;
+ case PD_TYPE_UINT:
+ return (double)value.pd_uint;
+ default:
+ return 0; // just to make the compiler happy
+ }
+}
+
+mp_perfdata_value mp_pd_value_multiply(mp_perfdata_value left, mp_perfdata_value right) {
+ if (left.type == right.type) {
+ switch (left.type) {
+ case PD_TYPE_DOUBLE:
+ left.pd_double *= right.pd_double;
+ return left;
+ case PD_TYPE_INT:
+ left.pd_int *= right.pd_int;
+ return left;
+ case PD_TYPE_UINT:
+ left.pd_uint *= right.pd_uint;
+ return left;
+ default:
+ // what to here?
+ return left;
+ }
+ }
+
+ // Different types, oh boy, just do the lazy thing for now and switch to double
+ switch (left.type) {
+ case PD_TYPE_INT:
+ left.pd_double = (double)left.pd_int;
+ left.type = PD_TYPE_DOUBLE;
+ break;
+ case PD_TYPE_UINT:
+ left.pd_double = (double)left.pd_uint;
+ left.type = PD_TYPE_DOUBLE;
+ break;
+ case PD_TYPE_DOUBLE:
+ default:
+ // already there
+ }
+
+ switch (right.type) {
+ case PD_TYPE_INT:
+ right.pd_double = (double)right.pd_int;
+ right.type = PD_TYPE_DOUBLE;
+ break;
+ case PD_TYPE_UINT:
+ right.pd_double = (double)right.pd_uint;
+ right.type = PD_TYPE_DOUBLE;
+ break;
+ case PD_TYPE_DOUBLE:
+ default:
+ // already there
+ }
+
+ left.pd_double *= right.pd_double;
+ return left;
+}
+
+mp_range mp_range_multiply(mp_range range, mp_perfdata_value factor) {
+ if (!range.end_infinity) {
+ range.end = mp_pd_value_multiply(range.end, factor);
+ }
+ if (!range.start_infinity) {
+ range.start = mp_pd_value_multiply(range.start, factor);
+ }
+ return range;
+}
diff --git a/lib/perfdata.h b/lib/perfdata.h
index 74583ee5..cb552678 100644
--- a/lib/perfdata.h
+++ b/lib/perfdata.h
@@ -171,6 +171,11 @@ mp_perfdata_value mp_create_pd_value_u_long(unsigned long);
mp_perfdata_value mp_create_pd_value_long_long(long long);
mp_perfdata_value mp_create_pd_value_u_long_long(unsigned long long);
+mp_perfdata mp_set_pd_max_value(mp_perfdata perfdata, mp_perfdata_value value);
+mp_perfdata mp_set_pd_min_value(mp_perfdata perfdata, mp_perfdata_value value);
+
+double mp_get_pd_value(mp_perfdata_value value);
+
/*
* Free the memory used by a pd_list
*/
@@ -178,6 +183,13 @@ void pd_list_free(pd_list[1]);
int cmp_perfdata_value(mp_perfdata_value, mp_perfdata_value);
+// ================
+// Helper functions
+// ================
+
+mp_perfdata_value mp_pd_value_multiply(mp_perfdata_value left, mp_perfdata_value right);
+mp_range mp_range_multiply(mp_range range, mp_perfdata_value factor);
+
// =================
// String formatters
// =================
--
cgit v1.2.3-74-g34f1
From 0205694ce977af97a71c58e0ae3c431299ceb7bb Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Sun, 30 Mar 2025 22:36:38 +0200
Subject: Fix wrong return state in threshold function
---
lib/thresholds.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/thresholds.c b/lib/thresholds.c
index ddefae37..171f5093 100644
--- a/lib/thresholds.c
+++ b/lib/thresholds.c
@@ -51,7 +51,7 @@ mp_state_enum mp_get_pd_status(mp_perfdata perfdata) {
}
if (perfdata.warn_present) {
if (mp_check_range(perfdata.value, perfdata.warn)) {
- return STATE_CRITICAL;
+ return STATE_WARNING;
}
}
--
cgit v1.2.3-74-g34f1
From 0bca1d1aa36b13723e77672eae162352e9be99c9 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Sun, 30 Mar 2025 22:36:55 +0200
Subject: Implement some helper functions for thresholds
---
lib/thresholds.c | 12 ++++++++++++
lib/thresholds.h | 3 +++
2 files changed, 15 insertions(+)
diff --git a/lib/thresholds.c b/lib/thresholds.c
index 171f5093..de2b9315 100644
--- a/lib/thresholds.c
+++ b/lib/thresholds.c
@@ -57,3 +57,15 @@ mp_state_enum mp_get_pd_status(mp_perfdata perfdata) {
return STATE_OK;
}
+
+mp_thresholds mp_thresholds_set_warn(mp_thresholds thlds, mp_range warn) {
+ thlds.warning = warn;
+ thlds.warning_is_set = true;
+ return thlds;
+}
+
+mp_thresholds mp_thresholds_set_crit(mp_thresholds thlds, mp_range crit) {
+ thlds.critical = crit;
+ thlds.critical_is_set = true;
+ return thlds;
+}
diff --git a/lib/thresholds.h b/lib/thresholds.h
index 4e7defee..5f9f9247 100644
--- a/lib/thresholds.h
+++ b/lib/thresholds.h
@@ -24,5 +24,8 @@ mp_perfdata mp_pd_set_thresholds(mp_perfdata /* pd */, mp_thresholds /* th */);
mp_state_enum mp_get_pd_status(mp_perfdata /* pd */);
+mp_thresholds mp_thresholds_set_warn(mp_thresholds thlds, mp_range warn);
+mp_thresholds mp_thresholds_set_crit(mp_thresholds thlds, mp_range crit);
+
char *fmt_threshold_warning(thresholds th);
char *fmt_threshold_critical(thresholds th);
--
cgit v1.2.3-74-g34f1
From 908aed4e6f9072e601a189d4ceff3152bdecc49d Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Sun, 30 Mar 2025 22:37:48 +0200
Subject: Refactor check_disk and library functions
---
plugins/check_disk.c | 1069 ++++++++++++++++++++-----------------
plugins/check_disk.d/config.h | 92 ----
plugins/check_disk.d/utils_disk.c | 469 ++++++++++++----
plugins/check_disk.d/utils_disk.h | 142 ++++-
4 files changed, 1048 insertions(+), 724 deletions(-)
delete mode 100644 plugins/check_disk.d/config.h
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index 050298d6..3cab816d 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -33,6 +33,10 @@ const char *email = "devel@monitoring-plugins.org";
#include "states.h"
#include "common.h"
+#include "output.h"
+#include "perfdata.h"
+#include "utils_base.h"
+#include "lib/thresholds.h"
#ifdef HAVE_SYS_STAT_H
# include
@@ -48,10 +52,9 @@ const char *email = "devel@monitoring-plugins.org";
#include
#include "./popen.h"
#include "./utils.h"
-#include "./check_disk.d/utils_disk.h"
#include "../gl/fsusage.h"
#include "../gl/mountlist.h"
-#include "check_disk.d/config.h"
+#include "./check_disk.d/utils_disk.h"
#if HAVE_LIMITS_H
# include
@@ -74,20 +77,22 @@ typedef struct {
check_disk_config config;
} check_disk_config_wrapper;
static check_disk_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
-static void set_all_thresholds(struct parameter_list *path, char * /*warn_freespace_units*/, char * /*crit_freespace_units*/,
- char * /*warn_freespace_percent*/, char * /*crit_freespace_percent*/, char * /*warn_usedspace_units*/,
- char * /*crit_usedspace_units*/, char * /*warn_usedspace_percent*/, char * /*crit_usedspace_percent*/,
- char * /*warn_usedinodes_percent*/, char * /*crit_usedinodes_percent*/, char * /*warn_freeinodes_percent*/,
- char * /*crit_freeinodes_percent*/);
-static void print_help(void);
-void print_usage(void);
+
+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(struct parameter_list * /*parameters*/, bool /*ignore_missing*/);
-static void get_stats(struct parameter_list * /*parameters*/, struct fs_usage *fsp, bool /*ignore_missing*/,
- bool /*freespace_ignore_reserved*/, uintmax_t /*mult*/, struct parameter_list * /*path_select_list*/,
- struct name_list * /*seen*/);
-static void get_path_stats(struct parameter_list * /*parameters*/, struct fs_usage *fsp, bool /*freespace_ignore_reserved*/,
- uintmax_t /*mult*/, struct name_list * /*seen*/);
+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)
+ */
+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);
static int verbose = 0;
@@ -100,7 +105,7 @@ int main(int argc, char **argv) {
char mountdir[32];
#endif
- /* Parse extra opts if any */
+ // Parse extra opts if any
argv = np_extra_opts(&argc, argv, progname);
check_disk_config_wrapper tmp_config = process_arguments(argc, argv);
@@ -110,289 +115,222 @@ int main(int argc, char **argv) {
check_disk_config config = tmp_config.config;
- /* If a list of paths has not been selected, find entire
- mount list and create list of paths
- */
- if (!config.path_selected && !config.path_ignored) {
- for (struct mount_entry *me = config.mount_list; me; me = me->me_next) {
- struct parameter_list *path = NULL;
- if (!(path = np_find_parameter(config.path_select_list, me->me_mountdir))) {
- path = np_add_parameter(&config.path_select_list, me->me_mountdir);
- }
- path->best_match = me;
- path->group = config.group;
- set_all_thresholds(path, config.warn_freespace_units, config.crit_freespace_units, config.warn_freespace_percent,
- config.crit_freespace_percent, config.warn_usedspace_units, config.crit_usedspace_units,
- config.warn_usedspace_percent, config.crit_usedspace_percent, config.warn_usedinodes_percent,
- config.crit_usedinodes_percent, config.warn_freeinodes_percent, config.crit_freeinodes_percent);
- }
+ if (config.output_format_is_set) {
+ mp_set_format(config.output_format);
}
- if (!config.path_ignored) {
- np_set_best_match(config.path_select_list, config.mount_list, config.exact_match);
+ if (config.erronly) {
+ mp_set_level_of_detail(MP_DETAIL_NON_OK_ONLY);
}
- /* Error if no match found for specified paths */
- struct parameter_list *temp_list = config.path_select_list;
+ if (!config.path_ignored) {
+ mp_int_fs_list_set_best_match(config.path_select_list, config.mount_list, config.exact_match);
+ }
- char *ignored = strdup("");
- while (config.path_select_list) {
- if (!config.path_select_list->best_match && config.ignore_missing) {
- /* If the first element will be deleted, the temp_list must be updated with the new start address as well */
- if (config.path_select_list == temp_list) {
- temp_list = config.path_select_list->name_next;
- }
- /* Add path argument to list of ignored paths to inform about missing paths being ignored and not alerted */
- xasprintf(&ignored, "%s %s;", ignored, config.path_select_list->name);
+ // Error if no match found for specified paths
+ for (parameter_list_elem *elem = config.path_select_list.first; elem;) {
+ if (!elem->best_match && config.ignore_missing) {
/* Delete the path from the list so that it is not stat-checked later in the code. */
- config.path_select_list = np_del_parameter(config.path_select_list, config.path_select_list->name_prev);
- } else if (!config.path_select_list->best_match) {
+ elem = mp_int_fs_list_del(&config.path_select_list, elem);
+ continue;
+ }
+ if (!elem->best_match) {
/* Without --ignore-missing option, exit with Critical state. */
- die(STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), config.path_select_list->name);
- } else {
- /* Continue jumping through the list */
- config.path_select_list = config.path_select_list->name_next;
+ die(STATE_CRITICAL, _("DISK %s: %s not found\n"), _("CRITICAL"), elem->name);
}
- }
- config.path_select_list = temp_list;
-
- mp_state_enum result = STATE_UNKNOWN;
- if (!config.path_select_list && config.ignore_missing) {
- result = STATE_OK;
- if (verbose >= 2) {
- printf("None of the provided paths were found\n");
- }
+ elem = mp_int_fs_list_get_next(elem);
}
- mp_state_enum filesystem_result = STATE_UNKNOWN;
- char *perf = strdup("");
- char *perf_ilabel = strdup("");
- char *output = strdup("");
- struct parameter_list *path = NULL;
- /* Process for every path in list */
- for (path = config.path_select_list; path; path = path->name_next) {
- if (verbose >= 3 && path->freespace_percent->warning != NULL && path->freespace_percent->critical != NULL) {
- printf("Thresholds(pct) for %s warn: %f crit %f\n", path->name, path->freespace_percent->warning->end,
- path->freespace_percent->critical->end);
+ mp_check overall = mp_check_init();
+ if (config.path_select_list.length == 0) {
+ mp_subcheck none_sc = mp_subcheck_init();
+ xasprintf(&none_sc.output, "No filesystems were found for the provided parameters");
+ if (config.ignore_missing) {
+ none_sc = mp_set_subcheck_state(none_sc, STATE_OK);
+ } else {
+ none_sc = mp_set_subcheck_state(none_sc, STATE_UNKNOWN);
+ if (verbose >= 2) {
+ printf("None of the provided paths were found\n");
+ }
}
+ mp_add_subcheck_to_check(&overall, none_sc);
+ mp_exit(overall);
+ }
- if (verbose >= 3 && path->group != NULL) {
- printf("Group of %s: %s\n", path->name, path->group);
+ // Filter list first
+ for (parameter_list_elem *path = config.path_select_list.first; path;) {
+ if (!path->best_match) {
+ path = mp_int_fs_list_del(&config.path_select_list, path);
+ continue;
}
- // reset filesystem result
- filesystem_result = STATE_UNKNOWN;
-
struct mount_entry *mount_entry = path->best_match;
- if (!mount_entry) {
- continue;
- }
-
#ifdef __CYGWIN__
if (strncmp(path->name, "/cygdrive/", 10) != 0 || strlen(path->name) > 11) {
+ path = mp_int_fs_list_del(&config.path_select_list, path);
continue;
}
+
+ char *mountdir = NULL;
snprintf(mountdir, sizeof(mountdir), "%s:\\", me->me_mountdir + 10);
if (GetDriveType(mountdir) != DRIVE_FIXED) {
- me->me_remote = 1;
+ mount_entry->me_remote = 1;
}
#endif
- /* Filters */
/* Remove filesystems already seen */
if (np_seen_name(config.seen, mount_entry->me_mountdir)) {
+ path = mp_int_fs_list_del(&config.path_select_list, path);
continue;
}
- np_add_name(&config.seen, mount_entry->me_mountdir);
if (path->group == NULL) {
- /* Skip remote filesystems if we're not interested in them */
- if (mount_entry->me_remote && config.show_local_fs) {
- if (config.stat_remote_fs) {
- if (!stat_path(path, config.ignore_missing) && config.ignore_missing) {
- result = STATE_OK;
- xasprintf(&ignored, "%s %s;", ignored, path->name);
- }
- }
- continue;
- /* Skip pseudo fs's if we haven't asked for all fs's */
- }
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;
- /* Skip excluded fs's */
}
+
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;
- /* Skip not included fstypes */
}
+
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;
}
- }
-
- if (!stat_path(path, config.ignore_missing)) {
- if (config.ignore_missing) {
- result = STATE_OK;
- xasprintf(&ignored, "%s %s;", ignored, path->name);
- }
- continue;
- }
- struct fs_usage fsp = {0};
- get_fs_usage(mount_entry->me_mountdir, mount_entry->me_devname, &fsp);
-
- if (fsp.fsu_blocks && strcmp("none", mount_entry->me_mountdir)) {
- get_stats(path, &fsp, config.ignore_missing, config.freespace_ignore_reserved, config.mult, config.path_select_list,
- config.seen);
-
- if (verbose >= 3) {
- printf("For %s, used_pct=%f free_pct=%f used_units=%lu free_units=%lu total_units=%lu used_inodes_pct=%f "
- "free_inodes_pct=%f fsp.fsu_blocksize=%lu mult=%lu\n",
- mount_entry->me_mountdir, path->dused_pct, path->dfree_pct, path->dused_units, path->dfree_units, path->dtotal_units,
- path->dused_inodes_percent, path->dfree_inodes_percent, fsp.fsu_blocksize, config.mult);
- }
-
- /* Threshold comparisons */
-
- mp_state_enum temp_result = get_status(path->dfree_units, path->freespace_units);
- if (verbose >= 3) {
- printf("Freespace_units result=%d\n", temp_result);
+ /* Skip remote filesystems if we're not interested in them */
+ if (mount_entry->me_remote && config.show_local_fs) {
+ if (config.stat_remote_fs) {
+ // TODO Stat here
+ if (!stat_path(path, config.ignore_missing) && config.ignore_missing) {
+ }
+ }
+ continue;
}
- filesystem_result = max_state(filesystem_result, temp_result);
- temp_result = get_status(path->dfree_pct, path->freespace_percent);
- if (verbose >= 3) {
- printf("Freespace%% result=%d\n", temp_result);
+ // TODO why stat here? remove unstatable fs?
+ if (!stat_path(path, config.ignore_missing)) {
+ // if (config.ignore_missing) {
+ // xasprintf(&ignored, "%s %s;", ignored, path->name);
+ // }
+ // not accessible, remove from list
+ path = mp_int_fs_list_del(&config.path_select_list, path);
+ continue;
}
- filesystem_result = max_state(filesystem_result, temp_result);
+ }
- temp_result = get_status(path->dused_units, path->usedspace_units);
- if (verbose >= 3) {
- printf("Usedspace_units result=%d\n", temp_result);
- }
- filesystem_result = max_state(filesystem_result, temp_result);
+ path = mp_int_fs_list_get_next(path);
+ }
- temp_result = get_status(path->dused_pct, path->usedspace_percent);
- if (verbose >= 3) {
- printf("Usedspace_percent result=%d\n", temp_result);
- }
- filesystem_result = max_state(filesystem_result, temp_result);
+ // now get the actual measurements
+ for (parameter_list_elem *filesystem = config.path_select_list.first; filesystem;) {
+ // Get actual metrics here
+ struct mount_entry *mount_entry = filesystem->best_match;
+ struct fs_usage fsp = {0};
+ get_fs_usage(mount_entry->me_mountdir, mount_entry->me_devname, &fsp);
- temp_result = get_status(path->dused_inodes_percent, path->usedinodes_percent);
- if (verbose >= 3) {
- printf("Usedinodes_percent result=%d\n", temp_result);
- }
- filesystem_result = max_state(filesystem_result, temp_result);
+ if (fsp.fsu_blocks != 0 && strcmp("none", mount_entry->me_mountdir) != 0) {
+ *filesystem = get_path_stats(*filesystem, fsp, config.freespace_ignore_reserved);
- temp_result = get_status(path->dfree_inodes_percent, path->freeinodes_percent);
if (verbose >= 3) {
- printf("Freeinodes_percent result=%d\n", temp_result);
- }
- filesystem_result = max_state(filesystem_result, temp_result);
-
- result = max_state(result, filesystem_result);
-
- /* What a mess of units. The output shows free space, the perf data shows used space. Yikes!
- Hack here. Trying to get warn/crit levels from freespace_(units|percent) for perf
- data. Assumption that start=0. Roll on new syntax...
- */
-
- /* *_high_tide must be reinitialized at each run */
- uint64_t warning_high_tide = UINT64_MAX;
-
- if (path->freespace_units->warning != NULL) {
- warning_high_tide = (path->dtotal_units - path->freespace_units->warning->end) * config.mult;
- }
- if (path->freespace_percent->warning != NULL) {
- warning_high_tide = min(warning_high_tide, (uint64_t)((1.0 - path->freespace_percent->warning->end / 100) *
- (path->dtotal_units * config.mult)));
- }
-
- uint64_t critical_high_tide = UINT64_MAX;
-
- if (path->freespace_units->critical != NULL) {
- critical_high_tide = (path->dtotal_units - path->freespace_units->critical->end) * config.mult;
- }
- if (path->freespace_percent->critical != NULL) {
- critical_high_tide = min(critical_high_tide, (uint64_t)((1.0 - path->freespace_percent->critical->end / 100) *
- (path->dtotal_units * config.mult)));
- }
-
- /* Nb: *_high_tide are unset when == UINT64_MAX */
- xasprintf(&perf, "%s %s", perf,
- perfdata_uint64((!strcmp(mount_entry->me_mountdir, "none") || config.display_mntp) ? mount_entry->me_devname
- : mount_entry->me_mountdir,
- path->dused_units * config.mult, "B", (warning_high_tide != UINT64_MAX), warning_high_tide,
- (critical_high_tide != UINT64_MAX), critical_high_tide, true, 0, true,
- path->dtotal_units * config.mult));
-
- if (config.display_inodes_perfdata) {
- /* *_high_tide must be reinitialized at each run */
- warning_high_tide = UINT64_MAX;
- critical_high_tide = UINT64_MAX;
-
- if (path->freeinodes_percent->warning != NULL) {
- warning_high_tide = (uint64_t)fabs(
- min((double)warning_high_tide, (double)(1.0 - path->freeinodes_percent->warning->end / 100) * path->inodes_total));
- }
- if (path->freeinodes_percent->critical != NULL) {
- critical_high_tide = (uint64_t)fabs(min(
- (double)critical_high_tide, (double)(1.0 - path->freeinodes_percent->critical->end / 100) * path->inodes_total));
- }
-
- xasprintf(&perf_ilabel, "%s (inodes)",
- (!strcmp(mount_entry->me_mountdir, "none") || config.display_mntp) ? mount_entry->me_devname
- : mount_entry->me_mountdir);
- /* Nb: *_high_tide are unset when == UINT64_MAX */
- xasprintf(&perf, "%s %s", perf,
- perfdata_uint64(perf_ilabel, path->inodes_used, "", (warning_high_tide != UINT64_MAX), warning_high_tide,
- (critical_high_tide != UINT64_MAX), critical_high_tide, true, 0, true, path->inodes_total));
+ 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);
}
+ } else {
+ // failed to retrieve file system data or not mounted?
+ filesystem = mp_int_fs_list_del(&config.path_select_list, filesystem);
+ continue;
+ }
+ filesystem = mp_int_fs_list_get_next(filesystem);
+ }
- if (filesystem_result == STATE_OK && config.erronly && !verbose) {
- continue;
+ if (verbose > 2) {
+ 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->best_match == NULL) {
+ printf("Filesystem path %s has no mount_entry!\n", filesystem->name);
+ } else {
+ // printf("Filesystem path %s has a mount_entry!\n", filesystem->name);
}
+ }
+ }
- char *flag_header = NULL;
- if (filesystem_result && verbose >= 1) {
- xasprintf(&flag_header, " %s [", state_text(filesystem_result));
+ 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)) {
+ 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);
+ if (measurements == NULL) {
+ measurements = current = add_measurement_list(NULL, unit);
} else {
- xasprintf(&flag_header, "");
+ current = add_measurement_list(measurements, unit);
}
- xasprintf(&output, "%s%s %s %llu%s (%.1f%%", output, flag_header,
- (!strcmp(mount_entry->me_mountdir, "none") || config.display_mntp) ? mount_entry->me_devname
- : mount_entry->me_mountdir,
- path->dfree_units, config.units, path->dfree_pct);
- if (path->dused_inodes_percent < 0) {
- xasprintf(&output, "%s inode=-)%s;", output, (filesystem_result ? "]" : ""));
+ } else {
+ // Grouped elements are consecutive
+ if (measurements == NULL) {
+ // first entry
+ 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 {
- xasprintf(&output, "%s inode=%.0f%%)%s;", output, path->dfree_inodes_percent,
- ((filesystem_result && verbose >= 1) ? "]" : ""));
+ // if this is the first element of a group, the name of the previos 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);
+ unit.name = filesystem->group;
+ current = add_measurement_list(measurements, unit);
+
+ } else {
+ // NOT the first entry of a group, add info to the other one
+ current->unit = add_filesystem_to_measurement_unit(current->unit, *filesystem);
+ }
}
- free(flag_header);
}
}
- char *preamble = " - free space:";
- if (strcmp(output, "") == 0 && !config.erronly) {
- preamble = "";
- xasprintf(&output, " - No disks were found for provided parameters");
+ /* 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_add_subcheck_to_check(&overall, unit_sc);
+ }
+ } else {
+ // Aparently no machting fs found
+ mp_subcheck none_sc = mp_subcheck_init();
+ xasprintf(&none_sc.output, "No filesystems were found for the provided parameters");
+
+ if (config.ignore_missing) {
+ none_sc = mp_set_subcheck_state(none_sc, STATE_OK);
+ } else {
+ none_sc = mp_set_subcheck_state(none_sc, STATE_UNKNOWN);
+ }
+ mp_add_subcheck_to_check(&overall, none_sc);
}
- char *ignored_preamble = " - ignored paths:";
- printf("DISK %s%s%s%s%s|%s\n", state_text(result), (config.erronly && (result == STATE_OK)) ? "" : preamble, output,
- (strcmp(ignored, "") == 0) ? "" : ignored_preamble, ignored, perf);
- return result;
+ mp_exit(overall);
}
double calculate_percent(uintmax_t value, uintmax_t total) {
double pct = -1;
if (value <= DBL_MAX && total != 0) {
- pct = (double)value / total * 100.0;
+ pct = (double)value / (double)total * 100.0;
}
+
return pct;
}
@@ -409,11 +347,15 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
return result;
}
+ enum {
+ output_format_index = CHAR_MAX + 1,
+ display_unit_index,
+ };
+
static struct option longopts[] = {{"timeout", required_argument, 0, 't'},
{"warning", required_argument, 0, 'w'},
{"critical", required_argument, 0, 'c'},
{"iwarning", required_argument, 0, 'W'},
- /* Dang, -C is taken. We might want to reshuffle this. */
{"icritical", required_argument, 0, 'K'},
{"kilobytes", no_argument, 0, 'k'},
{"megabytes", no_argument, 0, 'm'},
@@ -446,6 +388,8 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
{"clear", no_argument, 0, 'C'},
{"version", no_argument, 0, 'V'},
{"help", no_argument, 0, 'h'},
+ {"output-format", required_argument, 0, output_format_index},
+ {"display-unit", required_argument, 0, display_unit_index},
{0, 0, 0, 0}};
for (int index = 1; index < argc; index++) {
@@ -456,6 +400,17 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
int cflags = REG_NOSUB | REG_EXTENDED;
int default_cflags = cflags;
+ char *warn_freespace_units = NULL;
+ char *crit_freespace_units = NULL;
+ char *warn_freespace_percent = NULL;
+ char *crit_freespace_percent = NULL;
+ char *warn_freeinodes_percent = NULL;
+ char *crit_freeinodes_percent = NULL;
+
+ bool path_selected = false;
+ char *group = NULL;
+ byte_unit unit = MebiBytes;
+
result.config.mount_list = read_file_system_list(false);
np_add_regex(&result.config.fs_exclude_list, "iso9660", REG_EXTENDED);
@@ -485,24 +440,24 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
if (strstr(optarg, "%")) {
if (*optarg == '@') {
- result.config.warn_freespace_percent = optarg;
+ warn_freespace_percent = optarg;
} else {
- xasprintf(&result.config.warn_freespace_percent, "@%s", optarg);
+ xasprintf(&warn_freespace_percent, "@%s", optarg);
}
} else {
if (*optarg == '@') {
- result.config.warn_freespace_units = optarg;
+ warn_freespace_units = optarg;
} else {
- xasprintf(&result.config.warn_freespace_units, "@%s", optarg);
+ xasprintf(&warn_freespace_units, "@%s", optarg);
}
}
break;
/* Awful mistake where the range values do not make sense. Normally,
- you alert if the value is within the range, but since we are using
- freespace, we have to alert if outside the range. Thus we artificially
- force @ at the beginning of the range, so that it is backwards compatible
- */
+ * you alert if the value is within the range, but since we are using
+ * freespace, we have to alert if outside the range. Thus we artificially
+ * force @ at the beginning of the range, so that it is backwards compatible
+ */
case 'c': /* critical threshold */
if (!is_percentage_expression(optarg) && !is_numeric(optarg)) {
die(STATE_UNKNOWN, "Argument for --critical invalid or missing: %s\n", optarg);
@@ -510,84 +465,92 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
if (strstr(optarg, "%")) {
if (*optarg == '@') {
- result.config.crit_freespace_percent = optarg;
+ crit_freespace_percent = optarg;
} else {
- xasprintf(&result.config.crit_freespace_percent, "@%s", optarg);
+ xasprintf(&crit_freespace_percent, "@%s", optarg);
}
} else {
if (*optarg == '@') {
- result.config.crit_freespace_units = optarg;
+ crit_freespace_units = optarg;
} else {
- xasprintf(&result.config.crit_freespace_units, "@%s", optarg);
+ xasprintf(&crit_freespace_units, "@%s", optarg);
}
}
break;
case 'W': /* warning inode threshold */
if (*optarg == '@') {
- result.config.warn_freeinodes_percent = optarg;
+ warn_freeinodes_percent = optarg;
} else {
- xasprintf(&result.config.warn_freeinodes_percent, "@%s", optarg);
+ xasprintf(&warn_freeinodes_percent, "@%s", optarg);
}
break;
case 'K': /* critical inode threshold */
if (*optarg == '@') {
- result.config.crit_freeinodes_percent = optarg;
+ crit_freeinodes_percent = optarg;
} else {
- xasprintf(&result.config.crit_freeinodes_percent, "@%s", optarg);
+ xasprintf(&crit_freeinodes_percent, "@%s", optarg);
}
break;
case 'u':
- free(result.config.units);
if (!strcasecmp(optarg, "bytes")) {
- result.config.mult = (uintmax_t)1;
- result.config.units = strdup("B");
+ unit = Bytes;
} else if (!strcmp(optarg, "KiB")) {
- result.config.mult = (uintmax_t)1024;
- result.config.units = strdup("KiB");
+ unit = KibiBytes;
} else if (!strcmp(optarg, "kB")) {
- result.config.mult = (uintmax_t)1000;
- result.config.units = strdup("kB");
+ unit = KiloBytes;
} else if (!strcmp(optarg, "MiB")) {
- result.config.mult = (uintmax_t)1024 * 1024;
- result.config.units = strdup("MiB");
+ unit = MebiBytes;
} else if (!strcmp(optarg, "MB")) {
- result.config.mult = (uintmax_t)1000 * 1000;
- result.config.units = strdup("MB");
+ unit = MegaBytes;
} else if (!strcmp(optarg, "GiB")) {
- result.config.mult = (uintmax_t)1024 * 1024 * 1024;
- result.config.units = strdup("GiB");
+ unit = GibiBytes;
} else if (!strcmp(optarg, "GB")) {
- result.config.mult = (uintmax_t)1000 * 1000 * 1000;
- result.config.units = strdup("GB");
+ unit = GigaBytes;
} else if (!strcmp(optarg, "TiB")) {
- result.config.mult = (uintmax_t)1024 * 1024 * 1024 * 1024;
- result.config.units = strdup("TiB");
+ unit = TebiBytes;
} else if (!strcmp(optarg, "TB")) {
- result.config.mult = (uintmax_t)1000 * 1000 * 1000 * 1000;
- result.config.units = strdup("TB");
+ unit = TeraBytes;
} else if (!strcmp(optarg, "PiB")) {
- result.config.mult = (uintmax_t)1024 * 1024 * 1024 * 1024 * 1024;
- result.config.units = strdup("PiB");
+ unit = PebiBytes;
} else if (!strcmp(optarg, "PB")) {
- result.config.mult = (uintmax_t)1000 * 1000 * 1000 * 1000 * 1000;
- result.config.units = strdup("PB");
+ unit = PetaBytes;
} else {
die(STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
}
- if (result.config.units == NULL) {
- die(STATE_UNKNOWN, _("failed allocating storage for '%s'\n"), "units");
- }
break;
- case 'k': /* display mountpoint */
- result.config.mult = 1024;
- free(result.config.units);
- result.config.units = strdup("kiB");
+ case 'k':
+ unit = KibiBytes;
break;
- case 'm': /* display mountpoint */
- result.config.mult = 1024 * 1024;
- free(result.config.units);
- result.config.units = strdup("MiB");
+ case 'm':
+ unit = MebiBytes;
+ break;
+ case display_unit_index:
+ if (!strcasecmp(optarg, "bytes")) {
+ result.config.display_unit = Bytes;
+ } else if (!strcmp(optarg, "KiB")) {
+ result.config.display_unit = KibiBytes;
+ } else if (!strcmp(optarg, "kB")) {
+ result.config.display_unit = KiloBytes;
+ } else if (!strcmp(optarg, "MiB")) {
+ result.config.display_unit = MebiBytes;
+ } else if (!strcmp(optarg, "MB")) {
+ result.config.display_unit = MegaBytes;
+ } else if (!strcmp(optarg, "GiB")) {
+ result.config.display_unit = GibiBytes;
+ } else if (!strcmp(optarg, "GB")) {
+ result.config.display_unit = GigaBytes;
+ } else if (!strcmp(optarg, "TiB")) {
+ result.config.display_unit = TebiBytes;
+ } else if (!strcmp(optarg, "TB")) {
+ result.config.display_unit = TeraBytes;
+ } else if (!strcmp(optarg, "PiB")) {
+ result.config.display_unit = PebiBytes;
+ } else if (!strcmp(optarg, "PB")) {
+ result.config.display_unit = PetaBytes;
+ } else {
+ die(STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
+ }
break;
case 'L':
result.config.stat_remote_fs = true;
@@ -599,43 +562,34 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
result.config.display_inodes_perfdata = true;
break;
case 'p': /* select path */ {
- if (!(result.config.warn_freespace_units || result.config.crit_freespace_units || result.config.warn_freespace_percent ||
- result.config.crit_freespace_percent || result.config.warn_usedspace_units || result.config.crit_usedspace_units ||
- result.config.warn_usedspace_percent || result.config.crit_usedspace_percent || result.config.warn_usedinodes_percent ||
- result.config.crit_usedinodes_percent || result.config.warn_freeinodes_percent ||
- result.config.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 -p\n"));
}
/* add parameter if not found. overwrite thresholds if path has already been added */
- struct parameter_list *se;
- if (!(se = np_find_parameter(result.config.path_select_list, optarg))) {
- se = np_add_parameter(&result.config.path_select_list, optarg);
-
- struct stat stat_buf = {};
- if (stat(optarg, &stat_buf) && result.config.ignore_missing) {
- result.config.path_ignored = true;
- break;
- }
+ parameter_list_elem *search_entry;
+ if (!(search_entry = mp_int_fs_list_find(result.config.path_select_list, optarg))) {
+ search_entry = mp_int_fs_list_append(&result.config.path_select_list, optarg);
+
+ // struct stat stat_buf = {};
+ // if (stat(optarg, &stat_buf) && result.config.ignore_missing) {
+ // result.config.path_ignored = true;
+ // break;
+ // }
}
- se->group = result.config.group;
- set_all_thresholds(
- se, result.config.warn_freespace_units, result.config.crit_freespace_units, result.config.warn_freespace_percent,
- result.config.crit_freespace_percent, result.config.warn_usedspace_units, result.config.crit_usedspace_units,
- result.config.warn_usedspace_percent, result.config.crit_usedspace_percent, result.config.warn_usedinodes_percent,
- result.config.crit_usedinodes_percent, result.config.warn_freeinodes_percent, result.config.crit_freeinodes_percent);
+ search_entry->group = group;
+ set_all_thresholds(search_entry, warn_freespace_units, crit_freespace_units, warn_freespace_percent, crit_freespace_percent,
+
+ warn_freeinodes_percent, crit_freeinodes_percent);
/* With autofs, it is required to stat() the path before re-populating the mount_list */
- if (!stat_path(se, result.config.ignore_missing)) {
- break;
- }
- /* NB: We can't free the old mount_list "just like that": both list pointers and struct
- * pointers are copied around. One of the reason it wasn't done yet is that other parts
- * of check_disk need the same kind of cleanup so it'd better be done as a whole */
- result.config.mount_list = read_file_system_list(false);
- np_set_best_match(se, result.config.mount_list, result.config.exact_match);
+ // 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);
- result.config.path_selected = true;
+ path_selected = true;
} break;
case 'x': /* exclude path or partition */
np_add_name(&result.config.device_path_exclude_list, optarg);
@@ -667,7 +621,7 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
result.config.erronly = true;
break;
case 'E':
- if (result.config.path_selected) {
+ if (path_selected) {
die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set -E before selecting paths\n"));
}
result.config.exact_match = true;
@@ -676,16 +630,16 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
result.config.freespace_ignore_reserved = true;
break;
case 'g':
- if (result.config.path_selected) {
+ if (path_selected) {
die(STATE_UNKNOWN, "DISK %s: %s", _("UNKNOWN"), _("Must set group value before selecting paths\n"));
}
- result.config.group = optarg;
+ group = optarg;
break;
case 'I':
cflags |= REG_ICASE;
// Intentional fallthrough
case 'i': {
- if (!result.config.path_selected) {
+ 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"));
}
@@ -697,29 +651,20 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
}
- struct parameter_list *temp_list = result.config.path_select_list;
- struct parameter_list *previous = NULL;
- while (temp_list) {
- if (temp_list->best_match) {
- if (np_regex_match_mount_entry(temp_list->best_match, ®ex)) {
+ for (parameter_list_elem *elem = result.config.path_select_list.first; elem;) {
+ if (elem->best_match) {
+ if (np_regex_match_mount_entry(elem->best_match, ®ex)) {
if (verbose >= 3) {
- printf("ignoring %s matching regex\n", temp_list->name);
+ printf("ignoring %s matching regex\n", elem->name);
}
- temp_list = np_del_parameter(temp_list, previous);
- /* pointer to first element needs to be updated if first item gets deleted */
- if (previous == NULL) {
- result.config.path_select_list = temp_list;
- }
- } else {
- previous = temp_list;
- temp_list = temp_list->name_next;
+ elem = mp_int_fs_list_del(&result.config.path_select_list, elem);
+ continue;
}
- } else {
- previous = temp_list;
- temp_list = temp_list->name_next;
}
+
+ elem = mp_int_fs_list_get_next(elem);
}
cflags = default_cflags;
@@ -734,11 +679,8 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
cflags |= REG_ICASE;
// Intentional fallthrough
case 'r': {
- if (!(result.config.warn_freespace_units || result.config.crit_freespace_units || result.config.warn_freespace_percent ||
- result.config.crit_freespace_percent || result.config.warn_usedspace_units || result.config.crit_usedspace_units ||
- result.config.warn_usedspace_percent || result.config.crit_usedspace_percent || result.config.warn_usedinodes_percent ||
- result.config.crit_usedinodes_percent || result.config.warn_freeinodes_percent ||
- result.config.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"));
}
@@ -760,31 +702,28 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
}
/* add parameter if not found. overwrite thresholds if path has already been added */
- struct parameter_list *se = NULL;
- if (!(se = np_find_parameter(result.config.path_select_list, me->me_mountdir))) {
- se = np_add_parameter(&result.config.path_select_list, me->me_mountdir);
+ 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);
}
- se->group = result.config.group;
- set_all_thresholds(se, result.config.warn_freespace_units, result.config.crit_freespace_units,
- result.config.warn_freespace_percent, result.config.crit_freespace_percent,
- result.config.warn_usedspace_units, result.config.crit_usedspace_units,
- result.config.warn_usedspace_percent, result.config.crit_usedspace_percent,
- result.config.warn_usedinodes_percent, result.config.crit_usedinodes_percent,
- result.config.warn_freeinodes_percent, result.config.crit_freeinodes_percent);
+ se->group = group;
+ set_all_thresholds(se, warn_freespace_units, crit_freespace_units, warn_freespace_percent, crit_freespace_percent,
+ warn_freeinodes_percent, crit_freeinodes_percent);
}
}
- if (!found && result.config.ignore_missing) {
- result.config.path_ignored = true;
- result.config.path_selected = true;
- break;
- }
if (!found) {
+ if (result.config.ignore_missing) {
+ result.config.path_ignored = true;
+ path_selected = true;
+ break;
+ }
+
die(STATE_UNKNOWN, "DISK %s: %s - %s\n", _("UNKNOWN"), _("Regular expression did not match any path or disk"), optarg);
}
- result.config.path_selected = true;
- np_set_best_match(result.config.path_select_list, result.config.mount_list, result.config.exact_match);
+ path_selected = true;
+ mp_int_fs_list_set_best_match(result.config.path_select_list, result.config.mount_list, result.config.exact_match);
cflags = default_cflags;
} break;
@@ -793,37 +732,28 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
break;
case 'C': {
/* add all mount entries to path_select list if no partitions have been explicitly defined using -p */
- if (!result.config.path_selected) {
- struct parameter_list *path;
+ if (!path_selected) {
+ parameter_list_elem *path;
for (struct mount_entry *me = result.config.mount_list; me; me = me->me_next) {
- if (!(path = np_find_parameter(result.config.path_select_list, me->me_mountdir))) {
- path = np_add_parameter(&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 = result.config.group;
- set_all_thresholds(path, result.config.warn_freespace_units, result.config.crit_freespace_units,
- result.config.warn_freespace_percent, result.config.crit_freespace_percent,
- result.config.warn_usedspace_units, result.config.crit_usedspace_units,
- result.config.warn_usedspace_percent, result.config.crit_usedspace_percent,
- result.config.warn_usedinodes_percent, result.config.crit_usedinodes_percent,
- result.config.warn_freeinodes_percent, result.config.crit_freeinodes_percent);
+ path->group = group;
+ set_all_thresholds(path, warn_freespace_units, crit_freespace_units, warn_freespace_percent, crit_freespace_percent,
+ warn_freeinodes_percent, crit_freeinodes_percent);
}
}
- result.config.warn_freespace_units = NULL;
- result.config.crit_freespace_units = NULL;
- result.config.warn_usedspace_units = NULL;
- result.config.crit_usedspace_units = NULL;
- result.config.warn_freespace_percent = NULL;
- result.config.crit_freespace_percent = NULL;
- result.config.warn_usedspace_percent = NULL;
- result.config.crit_usedspace_percent = NULL;
- result.config.warn_usedinodes_percent = NULL;
- result.config.crit_usedinodes_percent = NULL;
- result.config.warn_freeinodes_percent = NULL;
- result.config.crit_freeinodes_percent = NULL;
-
- result.config.path_selected = false;
- result.config.group = NULL;
+
+ warn_freespace_units = NULL;
+ crit_freespace_units = NULL;
+ warn_freespace_percent = NULL;
+ crit_freespace_percent = NULL;
+ warn_freeinodes_percent = NULL;
+ crit_freeinodes_percent = NULL;
+
+ path_selected = false;
+ group = NULL;
} break;
case 'V': /* version */
print_revision(progname, NP_VERSION);
@@ -833,68 +763,145 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
exit(STATE_UNKNOWN);
case '?': /* help */
usage(_("Unknown argument"));
+ 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;
+ }
}
}
/* Support for "check_disk warn crit [fs]" with thresholds at used% level */
int index = optind;
- if (result.config.warn_usedspace_percent == NULL && argc > index && is_intnonneg(argv[index])) {
+ if (argc > index && is_intnonneg(argv[index])) {
if (verbose > 0) {
printf("Got an positional warn threshold: %s\n", argv[index]);
}
- result.config.warn_usedspace_percent = argv[index++];
+ char *range = argv[index++];
+ mp_range_parsed tmp = mp_parse_range_string(range);
+ if (tmp.error != MP_PARSING_SUCCES) {
+ die(STATE_UNKNOWN, "failed to parse warning threshold");
+ }
+
+ mp_range tmp_range = tmp.range;
+ // Invert range to use it for free instead of used
+ // tmp_range.alert_on_inside_range = !tmp_range.alert_on_inside_range;
+
+ warn_freespace_percent = mp_range_to_string(tmp_range);
+
+ if (verbose > 0) {
+ printf("Positional warning threshold transformed to: %s\n", warn_freespace_percent);
+ }
}
- if (result.config.crit_usedspace_percent == NULL && argc > index && is_intnonneg(argv[index])) {
+ if (argc > index && is_intnonneg(argv[index])) {
if (verbose > 0) {
printf("Got an positional crit threshold: %s\n", argv[index]);
}
- result.config.crit_usedspace_percent = argv[index++];
+ char *range = argv[index++];
+ mp_range_parsed tmp = mp_parse_range_string(range);
+ if (tmp.error != MP_PARSING_SUCCES) {
+ die(STATE_UNKNOWN, "failed to parse warning threshold");
+ }
+
+ mp_range tmp_range = tmp.range;
+ // Invert range to use it for free instead of used
+ // tmp_range.alert_on_inside_range = !tmp_range.alert_on_inside_range;
+
+ crit_freespace_percent = mp_range_to_string(tmp_range);
+
+ if (verbose > 0) {
+ printf("Positional critical threshold transformed to: %s\n", crit_freespace_percent);
+ }
}
if (argc > index) {
if (verbose > 0) {
printf("Got an positional filesystem: %s\n", argv[index]);
}
- struct parameter_list *se = np_add_parameter(&result.config.path_select_list, strdup(argv[index++]));
- result.config.path_selected = true;
- set_all_thresholds(se, result.config.warn_freespace_units, result.config.crit_freespace_units, result.config.warn_freespace_percent,
- result.config.crit_freespace_percent, result.config.warn_usedspace_units, result.config.crit_usedspace_units,
- result.config.warn_usedspace_percent, result.config.crit_usedspace_percent,
- result.config.warn_usedinodes_percent, result.config.crit_usedinodes_percent,
- result.config.warn_freeinodes_percent, result.config.crit_freeinodes_percent);
+ 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);
}
- if (result.config.units == NULL) {
- result.config.units = strdup("MiB");
- result.config.mult = (uintmax_t)1024 * 1024;
+ // If a list of paths has not been explicitely selected, find entire
+ // mount list and create list of paths
+ if (!path_selected && !result.config.path_ignored) {
+ for (struct mount_entry *me = result.config.mount_list; me; me = me->me_next) {
+ if (me->me_dummy != 0) {
+ // just do not add dummy filesystems
+ continue;
+ }
+
+ parameter_list_elem *path = NULL;
+ 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,
+ 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)) {
+
+ 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);
+ }
+ if (tmp->freespace_units.warning_is_set) {
+ tmp->freespace_units.warning = mp_range_multiply(tmp->freespace_units.warning, factor);
+ }
}
return result;
}
-void set_all_thresholds(struct parameter_list *path, char *warn_freespace_units, char *crit_freespace_units, char *warn_freespace_percent,
- char *crit_freespace_percent, char *warn_usedspace_units, char *crit_usedspace_units, char *warn_usedspace_percent,
- char *crit_usedspace_percent, char *warn_usedinodes_percent, char *crit_usedinodes_percent,
- char *warn_freeinodes_percent, char *crit_freeinodes_percent) {
- free(path->freespace_units);
- set_thresholds(&path->freespace_units, warn_freespace_units, crit_freespace_units);
+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) {
+ tmp = mp_parse_range_string(warn_freespace_units);
+ path->freespace_units = mp_thresholds_set_warn(path->freespace_units, tmp.range);
+ }
- free(path->freespace_percent);
- set_thresholds(&path->freespace_percent, warn_freespace_percent, crit_freespace_percent);
+ if (crit_freespace_units) {
+ tmp = mp_parse_range_string(crit_freespace_units);
+ path->freespace_units = mp_thresholds_set_crit(path->freespace_units, tmp.range);
+ }
- free(path->usedspace_units);
- set_thresholds(&path->usedspace_units, warn_usedspace_units, crit_usedspace_units);
+ if (warn_freespace_percent) {
+ tmp = mp_parse_range_string(warn_freespace_percent);
+ path->freespace_percent = mp_thresholds_set_warn(path->freespace_percent, tmp.range);
+ }
- free(path->usedspace_percent);
- set_thresholds(&path->usedspace_percent, warn_usedspace_percent, crit_usedspace_percent);
+ if (crit_freespace_percent) {
+ tmp = mp_parse_range_string(crit_freespace_percent);
+ path->freespace_percent = mp_thresholds_set_crit(path->freespace_percent, tmp.range);
+ }
- free(path->usedinodes_percent);
- set_thresholds(&path->usedinodes_percent, warn_usedinodes_percent, crit_usedinodes_percent);
+ if (warn_freeinodes_percent) {
+ tmp = mp_parse_range_string(warn_freeinodes_percent);
+ path->freeinodes_percent = mp_thresholds_set_warn(path->freeinodes_percent, tmp.range);
+ }
- free(path->freeinodes_percent);
- set_thresholds(&path->freeinodes_percent, warn_freeinodes_percent, crit_freeinodes_percent);
+ if (crit_freeinodes_percent) {
+ tmp = mp_parse_range_string(crit_freeinodes_percent);
+ path->freeinodes_percent = mp_thresholds_set_crit(path->freeinodes_percent, tmp.range);
+ }
}
void print_help(void) {
@@ -941,8 +948,6 @@ void print_help(void) {
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", "-k, --kilobytes");
- printf(" %s\n", _("Same as '--units kB'"));
printf(" %s\n", "-l, --local");
printf(" %s\n", _("Only check local filesystems"));
printf(" %s\n", "-L, --stat-remote-fs");
@@ -950,8 +955,6 @@ void print_help(void) {
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", "-m, --megabytes");
- printf(" %s\n", _("Same as '--units MB'"));
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");
@@ -967,12 +970,25 @@ void print_help(void) {
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", _("Choose bytes, kB, MB, GB, TB (default: MB)"));
+ 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", "-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", "-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", "-N, --include-type=TYPE_REGEX");
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:"));
@@ -1002,7 +1018,7 @@ void print_usage(void) {
printf("[-t timeout] [-u unit] [-v] [-X type_regex] [-N type]\n");
}
-bool stat_path(struct parameter_list *parameters, bool ignore_missing) {
+bool stat_path(parameter_list_elem *parameters, bool ignore_missing) {
/* Stat entry to check that dir exists and is accessible */
if (verbose >= 3) {
printf("calling stat on %s\n", parameters->name);
@@ -1023,97 +1039,166 @@ bool stat_path(struct parameter_list *parameters, bool ignore_missing) {
return true;
}
-void get_stats(struct parameter_list *parameters, struct fs_usage *fsp, bool ignore_missing, bool freespace_ignore_reserved, uintmax_t mult,
- struct parameter_list *path_select_list, struct name_list *seen) {
- struct fs_usage tmpfsp;
- bool first = true;
-
- if (parameters->group == NULL) {
- get_path_stats(parameters, fsp, freespace_ignore_reserved, mult, seen);
- } else {
- /* find all group members */
- for (struct parameter_list *p_list = path_select_list; p_list; p_list = p_list->name_next) {
-
-#ifdef __CYGWIN__
- if (strncmp(p_list->name, "/cygdrive/", 10) != 0) {
- continue;
- }
-#endif
-
- if (p_list->group && !(strcmp(p_list->group, parameters->group))) {
- if (!stat_path(p_list, ignore_missing)) {
- continue;
- }
- get_fs_usage(p_list->best_match->me_mountdir, p_list->best_match->me_devname, &tmpfsp);
- get_path_stats(p_list, &tmpfsp, freespace_ignore_reserved, mult, seen);
- if (verbose >= 3) {
- printf("Group %s: adding %lu blocks sized %lu, (%s) used_units=%lu free_units=%lu total_units=%lu mult=%lu\n",
- p_list->group, tmpfsp.fsu_blocks, tmpfsp.fsu_blocksize, p_list->best_match->me_mountdir, p_list->dused_units,
- p_list->dfree_units, p_list->dtotal_units, mult);
- }
-
- /* prevent counting the first FS of a group twice since its parameter_list entry
- * is used to carry the information of all file systems of the entire group */
- if (!first) {
- parameters->total += p_list->total;
- parameters->available += p_list->available;
- parameters->available_to_root += p_list->available_to_root;
- parameters->used += p_list->used;
-
- parameters->dused_units += p_list->dused_units;
- parameters->dfree_units += p_list->dfree_units;
- parameters->dtotal_units += p_list->dtotal_units;
- parameters->inodes_total += p_list->inodes_total;
- parameters->inodes_free += p_list->inodes_free;
- parameters->inodes_free_to_root += p_list->inodes_free_to_root;
- parameters->inodes_used += p_list->inodes_used;
- }
- first = false;
- }
- if (verbose >= 3) {
- printf("Group %s now has: used_units=%lu free_units=%lu total_units=%lu fsu_blocksize=%lu mult=%lu\n", parameters->group,
- parameters->dused_units, parameters->dfree_units, parameters->dtotal_units, tmpfsp.fsu_blocksize, mult);
- }
- }
- /* modify devname and mountdir for output */
- parameters->best_match->me_mountdir = parameters->best_match->me_devname = parameters->group;
- }
- /* finally calculate percentages for either plain FS or summed up group */
- parameters->dused_pct =
- calculate_percent(parameters->used, parameters->used + parameters->available); /* used + available can never be > uintmax */
- parameters->dfree_pct = 100.0 - parameters->dused_pct;
- parameters->dused_inodes_percent = calculate_percent(parameters->inodes_total - parameters->inodes_free, parameters->inodes_total);
- parameters->dfree_inodes_percent = 100 - parameters->dused_inodes_percent;
-}
+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;
+ uintmax_t total;
-void get_path_stats(struct parameter_list *parameters, struct fs_usage *fsp, bool freespace_ignore_reserved, uintmax_t mult,
- struct name_list *seen) {
- parameters->available = fsp->fsu_bavail;
- parameters->available_to_root = fsp->fsu_bfree;
- parameters->used = fsp->fsu_blocks - fsp->fsu_bfree;
if (freespace_ignore_reserved) {
/* option activated : we subtract the root-reserved space from the total */
- parameters->total = fsp->fsu_blocks - parameters->available_to_root + parameters->available;
+ total = fsp.fsu_blocks - available_to_root + available;
} else {
/* default behaviour : take all the blocks into account */
- parameters->total = fsp->fsu_blocks;
+ total = fsp.fsu_blocks;
}
- parameters->dused_units = parameters->used * fsp->fsu_blocksize / mult;
- parameters->dfree_units = parameters->available * fsp->fsu_blocksize / mult;
- parameters->dtotal_units = parameters->total * fsp->fsu_blocksize / mult;
+ parameters.used_bytes = used * fsp.fsu_blocksize;
+ parameters.free_bytes = available * fsp.fsu_blocksize;
+ parameters.total_bytes = total * fsp.fsu_blocksize;
+
/* Free file nodes. Not sure the workaround is required, but in case...*/
- parameters->inodes_free = fsp->fsu_ffree;
- parameters->inodes_free_to_root = fsp->fsu_ffree; /* Free file nodes for root. */
- parameters->inodes_used = fsp->fsu_files - fsp->fsu_ffree;
+ parameters.inodes_free = fsp.fsu_ffree;
+ parameters.inodes_free_to_root = fsp.fsu_ffree; /* Free file nodes for root. */
+ parameters.inodes_used = fsp.fsu_files - fsp.fsu_ffree;
+
if (freespace_ignore_reserved) {
/* 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;
+ parameters.inodes_total = fsp.fsu_files;
+ }
+
+ return parameters;
+}
+
+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);
+
+ if (!measurement_unit.is_group && measurement_unit.filesystem_type) {
+ xasprintf(&result.output, "%s (%s)", result.output, measurement_unit.filesystem_type);
+ }
+
+ /* Threshold comparisons */
+
+ // ===============================
+ // Free space absolute values test
+ mp_subcheck freespace_bytes_sc = mp_subcheck_init();
+ 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));
+ } else {
+ xasprintf(&freespace_bytes_sc.output, "Free space absolute: %s (of %s)", humanize_byte_value(measurement_unit.free_bytes, false),
+ humanize_byte_value(measurement_unit.total_bytes, false));
}
- np_add_name(&seen, parameters->best_match->me_mountdir);
+
+ mp_perfdata used_space = perfdata_init();
+ used_space.label = measurement_unit.name;
+ used_space.value = mp_create_pd_value(measurement_unit.free_bytes);
+ used_space = mp_set_pd_max_value(used_space, mp_create_pd_value(measurement_unit.total_bytes));
+ used_space = mp_set_pd_min_value(used_space, mp_create_pd_value(0));
+ used_space.uom = "B";
+ used_space = mp_pd_set_thresholds(used_space, measurement_unit.freespace_bytes_thresholds);
+ freespace_bytes_sc = mp_set_subcheck_state(freespace_bytes_sc, mp_get_pd_status(used_space));
+
+ // 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) {
+ 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);
+ }
+
+ if (!tmp_range.start_infinity) {
+ 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);
+ 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) {
+ 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);
+ }
+ if (!tmp_range.start_infinity) {
+ 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);
+ used_space = mp_pd_set_thresholds(used_space, measurement_unit.freespace_bytes_thresholds);
+ }
+
+ mp_add_perfdata_to_subcheck(&freespace_bytes_sc, used_space);
+ mp_add_subcheck_to_subcheck(&result, freespace_bytes_sc);
+
+ // ==========================
+ // Free space percentage test
+ 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);
+ 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);
+
+ 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);
+
+ // ================
+ // Free inodes test
+ // Only ever useful if the number of inodes is static (e.g. ext4),
+ // not when it is dynamic (e.g btrfs)
+ // Assumption: if the total number of inodes == 0, we have such a case and just skip the test
+ if (measurement_unit.inodes_total > 0) {
+ 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);
+
+ 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,
+ 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_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));
+ }
+ 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));
+ }
+
+ 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));
+ if (display_inodes_perfdata) {
+ mp_add_perfdata_to_subcheck(&freeindodes_percent_sc, inodes_pd);
+ }
+ mp_add_subcheck_to_subcheck(&result, freeindodes_percent_sc);
+ }
+
+ return result;
}
diff --git a/plugins/check_disk.d/config.h b/plugins/check_disk.d/config.h
deleted file mode 100644
index d890fc1a..00000000
--- a/plugins/check_disk.d/config.h
+++ /dev/null
@@ -1,92 +0,0 @@
-#pragma once
-
-#include "../../config.h"
-#include
-#include
-
-typedef struct {
- // Output options
- bool erronly;
- bool display_mntp;
- /* show only local filesystems. */
- bool show_local_fs;
- /* show only local filesystems but call stat() on remote ones. */
- bool stat_remote_fs;
- bool display_inodes_perfdata;
-
- bool exact_match;
- bool ignore_missing;
- bool path_ignored;
- bool path_selected;
- bool freespace_ignore_reserved;
-
- char *warn_freespace_units;
- char *crit_freespace_units;
- char *warn_freespace_percent;
- char *crit_freespace_percent;
- char *warn_usedspace_units;
- char *crit_usedspace_units;
- char *warn_usedspace_percent;
- char *crit_usedspace_percent;
- char *warn_usedinodes_percent;
- char *crit_usedinodes_percent;
- char *warn_freeinodes_percent;
- char *crit_freeinodes_percent;
-
- /* Linked list of filesystem types to omit.
- If the list is empty, don't exclude any types. */
- struct regex_list *fs_exclude_list;
- /* Linked list of filesystem types to check.
- If the list is empty, include all types. */
- struct regex_list *fs_include_list;
- struct name_list *device_path_exclude_list;
- struct parameter_list *path_select_list;
- /* Linked list of mounted filesystems. */
- struct mount_entry *mount_list;
- struct name_list *seen;
-
- char *units;
- uintmax_t mult;
- char *group;
-} check_disk_config;
-
-check_disk_config check_disk_config_init() {
- check_disk_config tmp = {
- .erronly = false,
- .display_mntp = false,
- .show_local_fs = false,
- .stat_remote_fs = false,
- .display_inodes_perfdata = false,
-
- .exact_match = false,
- .ignore_missing = false,
- .path_ignored = false,
- .path_selected = false,
- .freespace_ignore_reserved = false,
-
- .warn_freespace_units = NULL,
- .crit_freespace_units = NULL,
- .warn_freespace_percent = NULL,
- .crit_freespace_percent = NULL,
- .warn_usedspace_units = NULL,
- .crit_usedspace_units = NULL,
- .warn_usedspace_percent = NULL,
- .crit_usedspace_percent = NULL,
- .warn_usedinodes_percent = NULL,
- .crit_usedinodes_percent = NULL,
- .warn_freeinodes_percent = NULL,
- .crit_freeinodes_percent = NULL,
-
- .fs_exclude_list = NULL,
- .fs_include_list = NULL,
- .device_path_exclude_list = NULL,
- .path_select_list = NULL,
- .mount_list = NULL,
- .seen = NULL,
-
- .units = NULL,
- .mult = 1024 * 1024,
- .group = NULL,
- };
- return tmp;
-}
diff --git a/plugins/check_disk.d/utils_disk.c b/plugins/check_disk.d/utils_disk.c
index 369c85d5..3986a8a8 100644
--- a/plugins/check_disk.d/utils_disk.c
+++ b/plugins/check_disk.d/utils_disk.c
@@ -29,7 +29,12 @@
#include "../common.h"
#include "utils_disk.h"
#include "../../gl/fsusage.h"
+#include "../../lib/thresholds.h"
+#include "../../lib/states.h"
+#include
+#include
#include
+#include
void np_add_name(struct name_list **list, const char *name) {
struct name_list *new_entry;
@@ -70,82 +75,367 @@ int np_add_regex(struct regex_list **list, const char *regex, int cflags) {
return regcomp_result;
}
-struct parameter_list parameter_list_init(const char *name) {
- struct parameter_list result = {
+parameter_list_elem parameter_list_init(const char *name) {
+ parameter_list_elem result = {
.name = strdup(name),
.best_match = NULL,
- .name_next = NULL,
- .name_prev = NULL,
-
- .freespace_units = NULL,
- .freespace_percent = NULL,
- .usedspace_units = NULL,
- .usedspace_percent = NULL,
- .usedinodes_percent = NULL,
- .freeinodes_percent = NULL,
+ .freespace_units = mp_thresholds_init(),
+ .freespace_percent = mp_thresholds_init(),
+ .freeinodes_percent = mp_thresholds_init(),
.group = NULL,
- .dfree_pct = -1,
- .dused_pct = -1,
- .total = 0,
- .available = 0,
- .available_to_root = 0,
- .used = 0,
- .dused_units = 0,
- .dfree_units = 0,
- .dtotal_units = 0,
+
.inodes_total = 0,
.inodes_free = 0,
.inodes_free_to_root = 0,
.inodes_used = 0,
- .dused_inodes_percent = 0,
- .dfree_inodes_percent = 0,
+
+ .used_bytes = 0,
+ .free_bytes = 0,
+ .total_bytes = 0,
+
+ .next = NULL,
+ .prev = NULL,
};
return result;
}
-/* Initialises a new parameter at the end of list */
-struct parameter_list *np_add_parameter(struct parameter_list **list, const char *name) {
- struct parameter_list *current = *list;
- struct parameter_list *new_path;
- new_path = (struct parameter_list *)malloc(sizeof *new_path);
+/* Returns true if name is in list */
+bool np_find_name(struct name_list *list, const char *name) {
+ if (list == NULL || name == NULL) {
+ return false;
+ }
+ for (struct name_list *iterator = list; iterator; iterator = iterator->next) {
+ if (!strcmp(name, iterator->name)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Returns true if name is in list */
+bool np_find_regmatch(struct regex_list *list, const char *name) {
+ if (name == NULL) {
+ return false;
+ }
+
+ size_t len = strlen(name);
+
+ for (; list; list = list->next) {
+ /* 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) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool np_seen_name(struct name_list *list, const char *name) {
+ for (struct name_list *iterator = list; iterator; iterator = iterator->next) {
+ if (!strcmp(iterator->name, name)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+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));
+}
+
+check_disk_config check_disk_config_init() {
+ check_disk_config tmp = {
+ .erronly = false,
+ .display_mntp = false,
+ .show_local_fs = false,
+ .stat_remote_fs = false,
+ .display_inodes_perfdata = false,
+
+ .exact_match = false,
+ .freespace_ignore_reserved = false,
+ .ignore_missing = false,
+ .path_ignored = false,
+
+ // FS Filters
+ .fs_exclude_list = NULL,
+ .fs_include_list = NULL,
+ .device_path_exclude_list = NULL,
+
+ // Actual filesystems paths to investigate
+ .path_select_list = filesystem_list_init(),
+
+ .mount_list = NULL,
+ .seen = NULL,
+
+ .display_unit = Humanized,
+ // .unit = MebiBytes,
+
+ .output_format_is_set = false,
+ };
+ return tmp;
+}
+
+char *get_unit_string(byte_unit unit) {
+ switch (unit) {
+ case Bytes:
+ return "Bytes";
+ case KibiBytes:
+ return "KiB";
+ case MebiBytes:
+ return "MiB";
+ case GibiBytes:
+ return "GiB";
+ case TebiBytes:
+ return "TiB";
+ case PebiBytes:
+ return "PiB";
+ case ExbiBytes:
+ return "EiB";
+ case KiloBytes:
+ return "KB";
+ case MegaBytes:
+ return "MB";
+ case GigaBytes:
+ return "GB";
+ case TeraBytes:
+ return "TB";
+ case PetaBytes:
+ return "PB";
+ case ExaBytes:
+ return "EB";
+ default:
+ assert(false);
+ }
+}
+
+measurement_unit measurement_unit_init() {
+ measurement_unit tmp = {
+ .name = NULL,
+ .filesystem_type = NULL,
+ .is_group = false,
+
+ .freeinodes_percent_thresholds = mp_thresholds_init(),
+ .freespace_percent_thresholds = mp_thresholds_init(),
+ .freespace_bytes_thresholds = mp_thresholds_init(),
+
+ .free_bytes = 0,
+ .used_bytes = 0,
+ .total_bytes = 0,
+
+ .inodes_total = 0,
+ .inodes_free = 0,
+ .inodes_free_to_root = 0,
+ .inodes_used = 0,
+ };
+ return tmp;
+}
+
+// Add a given element to the list, memory for the new element is freshly allocated
+// Returns a pointer to new element
+measurement_unit_list *add_measurement_list(measurement_unit_list *list, measurement_unit elem) {
+ // find last element
+ measurement_unit_list *new = NULL;
+ if (list == NULL) {
+ new = calloc(1, sizeof(measurement_unit_list));
+ if (new == NULL) {
+ die(STATE_UNKNOWN, _("allocation failed"));
+ }
+ } else {
+ measurement_unit_list *list_elem = list;
+ while (list_elem->next != NULL) {
+ list_elem = list_elem->next;
+ }
+
+ new = calloc(1, sizeof(measurement_unit_list));
+ if (new == NULL) {
+ die(STATE_UNKNOWN, _("allocation failed"));
+ }
+
+ list_elem->next = new;
+ }
+
+ new->unit = elem;
+ new->next = NULL;
+ return new;
+}
+
+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;
+ unit.total_bytes += filesystem.total_bytes;
+
+ unit.inodes_total += filesystem.inodes_total;
+ unit.inodes_free += filesystem.inodes_free;
+ unit.inodes_free_to_root += filesystem.inodes_free_to_root;
+ unit.inodes_used += filesystem.inodes_used;
+ return unit;
+}
+
+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);
+ } else {
+ result.name = strdup(filesystem.best_match->me_devname);
+ }
+
+ if (filesystem.group) {
+ result.is_group = true;
+ } else {
+ result.is_group = false;
+ if (filesystem.best_match) {
+ result.filesystem_type = filesystem.best_match->me_type;
+ }
+ }
+
+ result.freeinodes_percent_thresholds = filesystem.freeinodes_percent;
+ result.freespace_percent_thresholds = filesystem.freespace_percent;
+ result.freespace_bytes_thresholds = filesystem.freespace_units;
+ result.free_bytes = filesystem.free_bytes;
+ result.total_bytes = filesystem.total_bytes;
+ result.used_bytes = filesystem.used_bytes;
+ result.inodes_total = filesystem.inodes_total;
+ result.inodes_used = filesystem.inodes_used;
+ result.inodes_free = filesystem.inodes_free;
+ result.inodes_free_to_root = filesystem.inodes_free_to_root;
+ return result;
+}
+
+#define RANDOM_STRING_LENGTH 64
+
+char *humanize_byte_value(uintmax_t value, bool use_si_units) {
+ // Idea: A reasonable output should have at most 3 orders of magnitude
+ // before the decimal separator
+ // 353GiB is ok, 2444 GiB should be 2.386 TiB
+ char *result = calloc(RANDOM_STRING_LENGTH, sizeof(char));
+ if (result == NULL) {
+ die(STATE_UNKNOWN, _("allocation failed"));
+ }
+
+ if (use_si_units) {
+ // SI units, powers of 10
+ if (value < KiloBytes) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%ju B", value);
+ } else if (value < MegaBytes) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%ju KB", value / KiloBytes);
+ } else if (value < GigaBytes) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%ju MB", value / MegaBytes);
+ } else if (value < TeraBytes) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%ju GB", value / GigaBytes);
+ } else if (value < PetaBytes) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%ju TB", value / TeraBytes);
+ } else {
+ snprintf(result, RANDOM_STRING_LENGTH, "%ju PB", value / PetaBytes);
+ }
+ } else {
+ // IEC units, powers of 2 ^ 10
+ if (value < KibiBytes) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%ju B", value);
+ } else if (value < MebiBytes) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%ju KiB", value / KibiBytes);
+ } else if (value < GibiBytes) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%ju MiB", value / MebiBytes);
+ } else if (value < TebiBytes) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%ju GiB", value / GibiBytes);
+ } else if (value < PebiBytes) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%ju TiB", value / TebiBytes);
+ } else {
+ snprintf(result, RANDOM_STRING_LENGTH, "%ju PiB", value / PebiBytes);
+ }
+ }
+
+ return result;
+}
+
+filesystem_list filesystem_list_init() {
+ filesystem_list tmp = {
+ .length = 0,
+ .first = NULL,
+ };
+ return tmp;
+}
+
+parameter_list_elem *mp_int_fs_list_append(filesystem_list *list, const char *name) {
+ parameter_list_elem *current = list->first;
+ parameter_list_elem *new_path = (struct parameter_list *)malloc(sizeof *new_path);
*new_path = parameter_list_init(name);
if (current == NULL) {
- *list = new_path;
- new_path->name_prev = NULL;
+ list->first = new_path;
+ new_path->prev = NULL;
+ list->length = 1;
} else {
- while (current->name_next) {
- current = current->name_next;
+ while (current->next) {
+ current = current->next;
}
- current->name_next = new_path;
- new_path->name_prev = current;
+ current->next = new_path;
+ new_path->prev = current;
+ list->length++;
}
return new_path;
}
-/* Delete a given parameter from list and return pointer to next element*/
-struct parameter_list *np_del_parameter(struct parameter_list *item, struct parameter_list *prev) {
- if (item == NULL) {
+parameter_list_elem *mp_int_fs_list_find(filesystem_list list, const char *name) {
+ if (list.length == 0) {
return NULL;
}
- struct parameter_list *next;
+ for (parameter_list_elem *temp_list = list.first; temp_list; temp_list = temp_list->next) {
+ if (!strcmp(temp_list->name, name)) {
+ return temp_list;
+ }
+ }
- if (item->name_next) {
- next = item->name_next;
- } else {
- next = NULL;
+ return NULL;
+}
+
+parameter_list_elem *mp_int_fs_list_del(filesystem_list *list, parameter_list_elem *item) {
+ if (list->length == 0) {
+ return NULL;
}
- if (next) {
- next->name_prev = prev;
+ if (item == NULL) {
+ // Got NULL for item, interpret this as "delete first element"
+ // as a kind of compatibility to the old function
+ item = list->first;
}
- if (prev) {
- prev->name_next = next;
+ if (list->first == item) {
+ list->length--;
+
+ list->first = item->next;
+ if (list->first) {
+ list->first->prev = NULL;
+ }
+ return list->first;
+ }
+
+ // Was not the first element, continue
+ parameter_list_elem *prev = list->first;
+ parameter_list_elem *current = list->first->next;
+
+ while (current != item && current != NULL) {
+ prev = current;
+ current = current->next;
+ }
+
+ if (current == NULL) {
+ // didn't find that element ....
+ return NULL;
+ }
+
+ // remove the element
+ parameter_list_elem *next = current->next;
+ prev->next = next;
+ list->length--;
+ if (next) {
+ next->prev = prev;
}
if (item->name) {
@@ -156,29 +446,23 @@ struct parameter_list *np_del_parameter(struct parameter_list *item, struct para
return next;
}
-/* returns a pointer to the struct found in the list */
-struct parameter_list *np_find_parameter(struct parameter_list *list, const char *name) {
- for (struct parameter_list *temp_list = list; temp_list; temp_list = temp_list->name_next) {
- if (!strcmp(temp_list->name, name)) {
- return temp_list;
- }
+parameter_list_elem *mp_int_fs_list_get_next(parameter_list_elem *current) {
+ if (!current) {
+ return NULL;
}
-
- return NULL;
+ return current->next;
}
-void np_set_best_match(struct parameter_list *desired, struct mount_entry *mount_list, bool exact) {
- for (struct parameter_list *d = desired; d; d = d->name_next) {
- if (!d->best_match) {
- struct mount_entry *mount_entry;
- size_t name_len = strlen(d->name);
- size_t best_match_len = 0;
+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;
- struct fs_usage fsp;
/* set best match if path name exactly matches a mounted device name */
- for (mount_entry = mount_list; mount_entry; mount_entry = mount_entry->me_next) {
- if (strcmp(mount_entry->me_devname, d->name) == 0) {
+ 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) {
best_match = mount_entry;
}
@@ -187,11 +471,15 @@ void np_set_best_match(struct parameter_list *desired, struct mount_entry *mount
/* set best match by directory name if no match was found by devname */
if (!best_match) {
- for (mount_entry = mount_list; mount_entry; mount_entry = mount_entry->me_next) {
+ size_t best_match_len = 0;
+ 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, d->name, len) == 0))) ||
- (exact && strcmp(mount_entry->me_mountdir, d->name) == 0)) {
+ (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) {
best_match = mount_entry;
best_match_len = len;
@@ -201,56 +489,13 @@ void np_set_best_match(struct parameter_list *desired, struct mount_entry *mount
}
if (best_match) {
- d->best_match = best_match;
+ elem->best_match = best_match;
} else {
- d->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 */
}
- }
- }
-}
-/* Returns true if name is in list */
-bool np_find_name(struct name_list *list, const char *name) {
- if (list == NULL || name == NULL) {
- return false;
- }
- for (struct name_list *n = list; n; n = n->next) {
- if (!strcmp(name, n->name)) {
- return true;
+ // No filesystem without a mount_entry!
+ // assert(elem->best_match != NULL);
}
}
- return false;
-}
-
-/* Returns true if name is in list */
-bool np_find_regmatch(struct regex_list *list, const char *name) {
- if (name == NULL) {
- return false;
- }
-
- int len = strlen(name);
-
- for (; list; list = list->next) {
- /* Emulate a full match as if surrounded with ^( )$
- by checking whether the match spans the whole name */
- regmatch_t m;
- if (!regexec(&list->regex, name, 1, &m, 0) && m.rm_so == 0 && m.rm_eo == len) {
- return true;
- }
- }
-
- return false;
-}
-
-bool np_seen_name(struct name_list *list, const char *name) {
- for (struct name_list *s = list; s; s = s->next) {
- if (!strcmp(s->name, name)) {
- return true;
- }
- }
- return false;
-}
-
-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));
}
diff --git a/plugins/check_disk.d/utils_disk.h b/plugins/check_disk.d/utils_disk.h
index 0c69f987..a66453ea 100644
--- a/plugins/check_disk.d/utils_disk.h
+++ b/plugins/check_disk.d/utils_disk.h
@@ -1,14 +1,34 @@
+#pragma once
/* Header file for utils_disk */
#include "../../config.h"
#include "../../gl/mountlist.h"
#include "../../lib/utils_base.h"
+#include "../../lib/output.h"
#include "regex.h"
#include
+typedef enum : unsigned long {
+ Humanized = 0,
+ Bytes = 1,
+ KibiBytes = 1024,
+ MebiBytes = 1024 * KibiBytes,
+ GibiBytes = 1024 * MebiBytes,
+ TebiBytes = 1024 * GibiBytes,
+ PebiBytes = 1024 * TebiBytes,
+ ExbiBytes = 1024 * PebiBytes,
+ KiloBytes = 1000,
+ MegaBytes = 1000 * KiloBytes,
+ GigaBytes = 1000 * MegaBytes,
+ TeraBytes = 1000 * GigaBytes,
+ PetaBytes = 1000 * TeraBytes,
+ ExaBytes = 1000 * PetaBytes
+} byte_unit;
+
+typedef struct name_list string_list;
struct name_list {
char *name;
- struct name_list *next;
+ string_list *next;
};
struct regex_list {
@@ -16,54 +36,120 @@ struct regex_list {
struct regex_list *next;
};
+typedef struct parameter_list parameter_list_elem;
struct parameter_list {
char *name;
char *group;
- thresholds *freespace_units;
- thresholds *freespace_percent;
- thresholds *usedspace_units;
- thresholds *usedspace_percent;
-
- thresholds *usedinodes_percent;
- thresholds *freeinodes_percent;
+ mp_thresholds freespace_units;
+ mp_thresholds freespace_percent;
+ mp_thresholds freeinodes_percent;
struct mount_entry *best_match;
- uintmax_t total;
- uintmax_t available;
- uintmax_t available_to_root;
- uintmax_t used;
- uintmax_t inodes_free;
uintmax_t inodes_free_to_root;
+ uintmax_t inodes_free;
uintmax_t inodes_used;
uintmax_t inodes_total;
- double dfree_pct;
- double dused_pct;
+ uint64_t used_bytes;
+ uint64_t free_bytes;
+ uint64_t total_bytes;
- uint64_t dused_units;
- uint64_t dfree_units;
- uint64_t dtotal_units;
+ parameter_list_elem *next;
+ parameter_list_elem *prev;
+};
+
+typedef struct {
+ size_t length;
+ parameter_list_elem *first;
+} filesystem_list;
- double dused_inodes_percent;
- double dfree_inodes_percent;
+filesystem_list filesystem_list_init();
- struct parameter_list *name_next;
- struct parameter_list *name_prev;
+typedef struct {
+ char *name;
+ char *filesystem_type;
+ bool is_group;
+
+ mp_thresholds freespace_bytes_thresholds;
+ mp_thresholds freespace_percent_thresholds;
+ mp_thresholds freeinodes_percent_thresholds;
+
+ uintmax_t inodes_free_to_root;
+ uintmax_t inodes_free;
+ uintmax_t inodes_used;
+ uintmax_t inodes_total;
+
+ uintmax_t used_bytes;
+ uintmax_t free_bytes;
+ uintmax_t total_bytes;
+} measurement_unit;
+
+typedef struct measurement_unit_list measurement_unit_list;
+struct measurement_unit_list {
+ measurement_unit unit;
+ measurement_unit_list *next;
};
+typedef struct {
+ // Output options
+ bool erronly;
+ bool display_mntp;
+ /* show only local filesystems. */
+ bool show_local_fs;
+ /* show only local filesystems but call stat() on remote ones. */
+ bool stat_remote_fs;
+ bool display_inodes_perfdata;
+
+ bool exact_match;
+ bool freespace_ignore_reserved;
+
+ bool ignore_missing;
+ bool path_ignored;
+
+ /* Linked list of filesystem types to omit.
+ If the list is empty, don't exclude any types. */
+ struct regex_list *fs_exclude_list;
+ /* Linked list of filesystem types to check.
+ If the list is empty, include all types. */
+ struct regex_list *fs_include_list;
+ struct name_list *device_path_exclude_list;
+ filesystem_list path_select_list;
+ /* Linked list of mounted filesystems. */
+ struct mount_entry *mount_list;
+ struct name_list *seen;
+
+ byte_unit display_unit;
+ // byte_unit unit;
+
+ bool output_format_is_set;
+ mp_output_format output_format;
+} check_disk_config;
+
void np_add_name(struct name_list **list, const char *name);
bool np_find_name(struct name_list *list, const char *name);
bool np_seen_name(struct name_list *list, const char *name);
int np_add_regex(struct regex_list **list, const char *regex, int cflags);
bool np_find_regmatch(struct regex_list *list, const char *name);
-struct parameter_list *np_add_parameter(struct parameter_list **list, const char *name);
-struct parameter_list *np_find_parameter(struct parameter_list *list, const char *name);
-struct parameter_list *np_del_parameter(struct parameter_list *item, struct parameter_list *prev);
-struct parameter_list parameter_list_init(const char *);
+parameter_list_elem parameter_list_init(const char *);
+
+parameter_list_elem *mp_int_fs_list_append(filesystem_list *list, const char *name);
+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);
-int search_parameter_list(struct parameter_list *list, const char *name);
-void np_set_best_match(struct parameter_list *desired, 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);
+
+int search_parameter_list(parameter_list_elem *list, const char *name);
bool np_regex_match_mount_entry(struct mount_entry *, regex_t *);
+
+char *get_unit_string(byte_unit);
+check_disk_config check_disk_config_init();
+
+char *humanize_byte_value(uintmax_t value, bool use_si_units);
--
cgit v1.2.3-74-g34f1
From 76971dea753d52d3e177aa84605d9b239a3a793e Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Sun, 30 Mar 2025 22:38:12 +0200
Subject: Address check_disk changes in tests
---
plugins/t/check_disk.t | 205 +++++++++++++++++++++++-----------------
plugins/tests/test_check_disk.c | 67 ++++++-------
2 files changed, 154 insertions(+), 118 deletions(-)
diff --git a/plugins/t/check_disk.t b/plugins/t/check_disk.t
index 9eb77ce4..16daee9a 100644
--- a/plugins/t/check_disk.t
+++ b/plugins/t/check_disk.t
@@ -10,6 +10,7 @@ use strict;
use Test::More;
use NPTest;
use POSIX qw(ceil floor);
+use Data::Dumper;
my $successOutput = '/^DISK OK/';
my $failureOutput = '/^DISK CRITICAL/';
@@ -20,117 +21,148 @@ my $result;
my $mountpoint_valid = getTestParameter( "NP_MOUNTPOINT_VALID", "Path to valid mountpoint", "/");
my $mountpoint2_valid = getTestParameter( "NP_MOUNTPOINT2_VALID", "Path to another valid mountpoint. Must be different from 1st one", "/var");
+my $output_format = "--output-format mp-test-json";
+
if ($mountpoint_valid eq "" or $mountpoint2_valid eq "") {
plan skip_all => "Need 2 mountpoints to test";
} else {
- plan tests => 94;
+ plan tests => 96;
}
$result = NPTest->testCmd(
- "./check_disk -w 1% -c 1% -p $mountpoint_valid -w 1% -c 1% -p $mountpoint2_valid"
+ "./check_disk -w 1% -c 1% -p $mountpoint_valid -w 1% -c 1% -P -p $mountpoint2_valid $output_format"
);
cmp_ok( $result->return_code, "==", 0, "Checking two mountpoints (must have at least 1% free in space and inodes)");
-my $c = 0;
-$_ = $result->output;
-$c++ while /\(/g; # counts number of "(" - should be two
-cmp_ok( $c, '==', 2, "Got two mountpoints in output");
+like($result->{'mp_test_result'}->{'state'}, "/OK/", "Main result is OK");
+like($result->{'mp_test_result'}->{'checks'}->[0]->{'state'}, "/OK/", "First sub result is OK");
+like($result->{'mp_test_result'}->{'checks'}->[1]->{'state'}, "/OK/", "Second sub result is OK");
+
+my $absolut_space_mp1 = $result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}->[0]->{'perfdata'}->[0]->{'max'}->{'value'};
+# print("absolut space on mp1: ". $absolut_space_mp1 . "\n");
+
+my $free_percent_on_mp1 = ($result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}->[0]->{'perfdata'}->[0]->{'value'}->{'value'} / ($absolut_space_mp1/100));
+print("free percent on mp1: ". $free_percent_on_mp1 . "\n");
+
+my $absolut_space_mp2 = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}->[0]->{'perfdata'}->[0]->{'max'}->{'value'};
+# print("absolut space on mp2: ". $absolut_space_mp2 . "\n");
-# Get perf data
-# Should use Monitoring::Plugin
-my @perf_data = sort(split(/ /, $result->perf_output));
+my $free_percent_on_mp2 = ($result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}->[0]->{'perfdata'}->[0]->{'value'}->{'value'}/ ($absolut_space_mp2/100));
+print("free percent on mp2: ". $free_percent_on_mp2 . "\n");
+my @perfdata;
+@perfdata[0] = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}->[0]->{'perfdata'}->[0];
+@perfdata[1] = $result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}->[0]->{'perfdata'}->[0];
# Calculate avg_free free on mountpoint1 and mountpoint2
# because if you check in the middle, you should get different errors
-$_ = $result->output;
-my ($free_on_mp1, $free_on_mp2) = (m/\((\d+\.\d+)%.*\((\d+\.\d+)%/);
-die "Cannot parse output: $_" unless ($free_on_mp1 && $free_on_mp2);
-my $avg_free = ceil(($free_on_mp1+$free_on_mp2)/2);
+my $avg_free_percent = ceil(($free_percent_on_mp1+$free_percent_on_mp2)/2);
+# print("avg_free: " . $avg_free_percent . "\n");
my ($more_free, $less_free);
-if ($free_on_mp1 > $free_on_mp2) {
+if ($free_percent_on_mp1 > $free_percent_on_mp2) {
$more_free = $mountpoint_valid;
$less_free = $mountpoint2_valid;
-} elsif ($free_on_mp1 < $free_on_mp2) {
+} elsif ($free_percent_on_mp1 < $free_percent_on_mp2) {
$more_free = $mountpoint2_valid;
$less_free = $mountpoint_valid;
} else {
die "Two mountpoints are the same - cannot do rest of test";
}
-if($free_on_mp1 == $avg_free || $free_on_mp2 == $avg_free) {
+
+print("less free: " . $less_free . "\n");
+print("more free: " . $more_free . "\n");
+
+if($free_percent_on_mp1 == $avg_free_percent || $free_percent_on_mp2 == $avg_free_percent) {
die "One mountpoints has average space free - cannot do rest of test";
}
+my $free_inodes_on_mp1 = $result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}[2]->{'perfdata'}->[0]->{'value'}->{'value'};
+my $total_inodes_on_mp1 = $result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}[2]->{'perfdata'}->[0]->{'max'}->{'value'};
+my $free_inode_percentage_on_mp1 = $free_inodes_on_mp1 / ($total_inodes_on_mp1 / 100);
-# Do same for inodes
-$_ = $result->output;
-my ($free_inode_on_mp1, $free_inode_on_mp2) = (m/inode=(\d+)%.*inode=(\d+)%/);
-die "Cannot parse free inodes: $_" unless ($free_inode_on_mp1 && $free_inode_on_mp2);
-my $avg_inode_free = ceil(($free_inode_on_mp1 + $free_inode_on_mp2)/2);
+my $free_inodes_on_mp2 = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[2]->{'perfdata'}->[0]->{'value'}->{'value'};
+my $total_inodes_on_mp2 = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[2]->{'perfdata'}->[0]->{'max'}->{'value'};
+my $free_inode_percentage_on_mp2 = $free_inodes_on_mp2 / ($total_inodes_on_mp2 / 100);
+
+my $avg_inode_free_percentage = ceil(($free_inode_percentage_on_mp1 + $free_inode_percentage_on_mp2)/2);
my ($more_inode_free, $less_inode_free);
-if ($free_inode_on_mp1 > $free_inode_on_mp2) {
+if ($free_inode_percentage_on_mp1 > $free_inode_percentage_on_mp2) {
$more_inode_free = $mountpoint_valid;
$less_inode_free = $mountpoint2_valid;
-} elsif ($free_inode_on_mp1 < $free_inode_on_mp2) {
+} elsif ($free_inode_percentage_on_mp1 < $free_inode_percentage_on_mp2) {
$more_inode_free = $mountpoint2_valid;
$less_inode_free = $mountpoint_valid;
} else {
die "Two mountpoints with same inodes free - cannot do rest of test";
}
-if($free_inode_on_mp1 == $avg_inode_free || $free_inode_on_mp2 == $avg_inode_free) {
+if($free_inode_percentage_on_mp1 == $avg_inode_free_percentage || $free_inode_percentage_on_mp2 == $avg_inode_free_percentage) {
die "One mountpoints has average inodes free - cannot do rest of test";
}
# Verify performance data
# First check absolute thresholds...
$result = NPTest->testCmd(
- "./check_disk -w 20 -c 10 -p $mountpoint_valid"
+ "./check_disk -w 20 -c 10 -p $mountpoint_valid $output_format"
);
-$_ = $result->perf_output;
-my ($warn_absth_data, $crit_absth_data, $total_absth_data) = (m/=.[^;]*;(\d+);(\d+);\d+;(\d+)/);
-# default unit is MiB, but perfdata is always bytes
-is ($warn_absth_data, $total_absth_data - (20 * (2 ** 20)), "Wrong warning in perf data using absolute thresholds");
-is ($crit_absth_data, $total_absth_data - (10 * (2 ** 20)), "Wrong critical in perf data using absolute thresholds");
+
+cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
+
+my $warn_absth_data = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[0]->{'perfdata'}->[0]->{'warn'}->{'end'}->{'value'};
+my $crit_absth_data = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[0]->{'perfdata'}->[0]->{'crit'}->{'end'}->{'value'};
+my $total_absth_data= $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[0]->{'perfdata'}->[0]->{'max'}->{'value'};
+
+# print("warn: " .$warn_absth_data . "\n");
+# print("crit: " .$crit_absth_data . "\n");
+# print("total: " .$total_absth_data . "\n");
+
+is ($warn_absth_data <=> (20 * (2 ** 20)), 0, "Wrong warning in perf data using absolute thresholds");
+is ($crit_absth_data <=> (10 * (2 ** 20)), 0, "Wrong critical in perf data using absolute thresholds");
# Then check percent thresholds.
$result = NPTest->testCmd(
- "./check_disk -w 20% -c 10% -p $mountpoint_valid"
+ "./check_disk -w 20% -c 10% -p $mountpoint_valid $output_format"
);
-$_ = $result->perf_output;
-my ($warn_percth_data, $crit_percth_data, $total_percth_data) = (m/=.[^;]*;(\d+);(\d+);\d+;(\d+)/);
-is ($warn_percth_data, int((1-20/100)*$total_percth_data), "Wrong warning in perf data using percent thresholds");
-is ($crit_percth_data, int((1-10/100)*$total_percth_data), "Wrong critical in perf data using percent thresholds");
+
+cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
+
+my $warn_percth_data = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[0]->{'perfdata'}->[0]->{'warn'}->{'end'}->{'value'};
+my $crit_percth_data = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[0]->{'perfdata'}->[0]->{'crit'}->{'end'}->{'value'};
+my $total_percth_data = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[0]->{'perfdata'}->[0]->{'max'}->{'value'};
+
+is ($warn_percth_data <=> int((20/100)*$total_percth_data), 0, "Wrong warning in perf data using percent thresholds");
+is ($crit_percth_data <=> int((10/100)*$total_percth_data), 0, "Wrong critical in perf data using percent thresholds");
# Check when order of mount points are reversed, that perf data remains same
$result = NPTest->testCmd(
- "./check_disk -w 1% -c 1% -p $mountpoint2_valid -w 1% -c 1% -p $mountpoint_valid"
+ "./check_disk -w 1% -c 1% -p $mountpoint2_valid -w 1% -c 1% -p $mountpoint_valid $output_format"
);
-@_ = sort(split(/ /, $result->perf_output));
-is_deeply( \@perf_data, \@_, "perf data for both filesystems same when reversed");
+cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
+# write comparison set for perfdata here, but in reversed order, maybe there is a smarter way
+my @perfdata2;
+@perfdata2[1] = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}->[0]->{'perfdata'}->[0];
+@perfdata2[0] = $result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}->[0]->{'perfdata'}->[0];
+is_deeply(\@perfdata, \@perfdata2, "perf data for both filesystems same when reversed");
# Basic filesystem checks for sizes
-$result = NPTest->testCmd( "./check_disk -w 1 -c 1 -p $more_free" );
-cmp_ok( $result->return_code, '==', 0, "At least 1 MB available on $more_free");
-like ( $result->output, $successOutput, "OK output" );
-like ( $result->only_output, qr/free space/, "Have free space text");
-like ( $result->only_output, qr/$more_free/, "Have disk name in text");
+$result = NPTest->testCmd( "./check_disk -w 1 -c 1 -p $more_free $output_format");
+cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
+like($result->{'mp_test_result'}->{'state'}, "/OK/", "At least 1 MB available on $more_free");
-$result = NPTest->testCmd( "./check_disk -w 1 -c 1 -p $more_free -p $less_free" );
-cmp_ok( $result->return_code, '==', 0, "At least 1 MB available on $more_free and $less_free");
+$result = NPTest->testCmd( "./check_disk -w 1 -c 1 -p $more_free -p $less_free $output_format" );
+cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
+like($result->{'mp_test_result'}->{'state'}, "/OK/", "At least 1 MB available on $more_free and $less_free");
-$_ = $result->output;
-
-my ($free_mb_on_mp1, $free_mb_on_mp2) = (m/(\d+)MiB .* (\d+)MiB /g);
+my $free_mb_on_mp1 =$result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}->[0]->{'perfdata'}->[0]->{'value'}->{'value'} / (1024 * 1024);
+my $free_mb_on_mp2 = $result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}->[0]->{'perfdata'}->[0]->{'value'}->{'value'}/ (1024 * 1024);
die "Cannot parse output: $_" unless ($free_mb_on_mp1 && $free_mb_on_mp2);
my $free_mb_on_all = $free_mb_on_mp1 + $free_mb_on_mp2;
-
-$result = NPTest->testCmd( "./check_disk -e -w 1 -c 1 -p $more_free" );
-is( $result->only_output, "DISK OK", "No print out of disks with -e for OKs");
+$result = NPTest->testCmd( "./check_disk -e -w 1 -c 1 -p $more_free $output_format" );
+cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
$result = NPTest->testCmd( "./check_disk 100 100 $more_free" );
cmp_ok( $result->return_code, '==', 0, "Old syntax okay" );
@@ -139,54 +171,55 @@ $result = NPTest->testCmd( "./check_disk -w 1% -c 1% -p $more_free" );
cmp_ok( $result->return_code, "==", 0, "At least 1% free" );
$result = NPTest->testCmd(
- "./check_disk -w 1% -c 1% -p $more_free -w 100% -c 100% -p $less_free"
+ "./check_disk -w 1% -c 1% -p $more_free -w 100% -c 100% -p $less_free $output_format"
);
-cmp_ok( $result->return_code, "==", 2, "Get critical on less_free mountpoint $less_free" );
-like( $result->output, $failureOutput, "Right output" );
+cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
+like($result->{'mp_test_result'}->{'state'}, "/CRITICAL/", "Get critical on less_free mountpoint $less_free");
$result = NPTest->testCmd(
- "./check_disk -w $avg_free% -c 0% -p $less_free"
+ "./check_disk -w $avg_free_percent% -c 0% -p $less_free $output_format"
);
-cmp_ok( $result->return_code, '==', 1, "Get warning on less_free mountpoint, when checking avg_free");
+cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
+like($result->{'mp_test_result'}->{'state'}, "/WARNING/", "Get warning on less_free mountpoint, when checking avg_free");
$result = NPTest->testCmd(
- "./check_disk -w $avg_free% -c $avg_free% -p $more_free"
+ "./check_disk -w $avg_free_percent% -c $avg_free_percent% -p $more_free"
);
cmp_ok( $result->return_code, '==', 0, "Get ok on more_free mountpoint, when checking avg_free");
$result = NPTest->testCmd(
- "./check_disk -w $avg_free% -c 0% -p $less_free -w $avg_free% -c $avg_free% -p $more_free"
+ "./check_disk -w $avg_free_percent% -c 0% -p $less_free -w $avg_free_percent% -c $avg_free_percent% -p $more_free"
);
cmp_ok( $result->return_code, "==", 1, "Combining above two tests, get warning");
my $all_disks = $result->output;
$result = NPTest->testCmd(
- "./check_disk -e -w $avg_free% -c 0% -p $less_free -w $avg_free% -c $avg_free% -p $more_free"
+ "./check_disk -e -w $avg_free_percent% -c 0% -p $less_free -w $avg_free_percent% -c $avg_free_percent% -p $more_free"
);
isnt( $result->output, $all_disks, "-e gives different output");
# Need spaces around filesystem name in case less_free and more_free are nested
like( $result->output, qr/ $less_free /, "Found problem $less_free");
unlike( $result->only_output, qr/ $more_free /, "Has ignored $more_free as not a problem");
-like( $result->perf_output, qr/ $more_free=/, "But $more_free is still in perf data");
+like( $result->perf_output, qr/'$more_free'=/, "But $more_free is still in perf data");
$result = NPTest->testCmd(
- "./check_disk -w $avg_free% -c 0% -p $more_free"
+ "./check_disk -w $avg_free_percent% -c 0% -p $more_free"
);
cmp_ok( $result->return_code, '==', 0, "Get ok on more_free mountpoint, checking avg_free");
$result = NPTest->testCmd(
- "./check_disk -w $avg_free% -c $avg_free% -p $less_free"
+ "./check_disk -w $avg_free_percent% -c $avg_free_percent% -p $less_free"
);
cmp_ok( $result->return_code, '==', 2, "Get critical on less_free, checking avg_free");
$result = NPTest->testCmd(
- "./check_disk -w $avg_free% -c 0% -p $more_free -w $avg_free% -c $avg_free% -p $less_free"
+ "./check_disk -w $avg_free_percent% -c 0% -p $more_free -w $avg_free_percent% -c $avg_free_percent% -p $less_free"
);
cmp_ok( $result->return_code, '==', 2, "Combining above two tests, get critical");
$result = NPTest->testCmd(
- "./check_disk -w $avg_free% -c $avg_free% -p $less_free -w $avg_free% -c 0% -p $more_free"
+ "./check_disk -w $avg_free_percent% -c $avg_free_percent% -p $less_free -w $avg_free_percent% -c 0% -p $more_free"
);
cmp_ok( $result->return_code, '==', 2, "And reversing arguments should not make a difference");
@@ -203,32 +236,32 @@ is( $result->return_code, 2, "Critical requesting 100% free inodes for both moun
$result = NPTest->testCmd( "./check_disk --iwarning 1% --icritical 1% -p $more_inode_free -K 100% -W 100% -p $less_inode_free" );
is( $result->return_code, 2, "Get critical on less_inode_free mountpoint $less_inode_free");
-$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K 0% -p $less_inode_free" );
+$result = NPTest->testCmd( "./check_disk -W $avg_inode_free_percentage% -K 0% -p $less_inode_free" );
is( $result->return_code, 1, "Get warning on less_inode_free, when checking average");
-$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K $avg_inode_free% -p $more_inode_free ");
+$result = NPTest->testCmd( "./check_disk -W $avg_inode_free_percentage% -K $avg_inode_free_percentage% -p $more_inode_free ");
is( $result->return_code, 0, "Get ok on more_inode_free when checking average");
-$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K 0% -p $less_inode_free -W $avg_inode_free% -K $avg_inode_free% -p $more_inode_free" );
+$result = NPTest->testCmd( "./check_disk -W $avg_inode_free_percentage% -K 0% -p $less_inode_free -W $avg_inode_free_percentage% -K $avg_inode_free_percentage% -p $more_inode_free" );
is ($result->return_code, 1, "Combine above two tests, get warning");
$all_disks = $result->output;
-$result = NPTest->testCmd( "./check_disk -e -W $avg_inode_free% -K 0% -p $less_inode_free -W $avg_inode_free% -K $avg_inode_free% -p $more_inode_free" );
+$result = NPTest->testCmd( "./check_disk -e -W $avg_inode_free_percentage% -K 0% -p $less_inode_free -W $avg_inode_free_percentage% -K $avg_inode_free_percentage% -p $more_inode_free" );
isnt( $result->output, $all_disks, "-e gives different output");
like( $result->output, qr/$less_inode_free/, "Found problem $less_inode_free");
unlike( $result->only_output, qr/$more_inode_free\s/, "Has ignored $more_inode_free as not a problem");
like( $result->perf_output, qr/$more_inode_free/, "But $more_inode_free is still in perf data");
-$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K 0% -p $more_inode_free" );
+$result = NPTest->testCmd( "./check_disk -W $avg_inode_free_percentage% -K 0% -p $more_inode_free" );
is( $result->return_code, 0, "Get ok on more_inode_free mountpoint, checking average");
-$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K $avg_inode_free% -p $less_inode_free" );
+$result = NPTest->testCmd( "./check_disk -W $avg_inode_free_percentage% -K $avg_inode_free_percentage% -p $less_inode_free" );
is( $result->return_code, 2, "Get critical on less_inode_free, checking average");
-$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K 0% -p $more_inode_free -W $avg_inode_free% -K $avg_inode_free% -p $less_inode_free" );
+$result = NPTest->testCmd( "./check_disk -W $avg_inode_free_percentage% -K 0% -p $more_inode_free -W $avg_inode_free_percentage% -K $avg_inode_free_percentage% -p $less_inode_free" );
is( $result->return_code, 2, "Combining above two tests, get critical");
-$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K $avg_inode_free% -p $less_inode_free -W $avg_inode_free% -K 0% -p $more_inode_free" );
+$result = NPTest->testCmd( "./check_disk -W $avg_inode_free_percentage% -K $avg_inode_free_percentage% -p $less_inode_free -W $avg_inode_free_percentage% -K 0% -p $more_inode_free" );
cmp_ok( $result->return_code, '==', 2, "And reversing arguments should not make a difference");
@@ -249,9 +282,9 @@ $result = NPTest->testCmd(
);
cmp_ok( $result->return_code, "==", 3, "Invalid options: -p must come after thresholds" );
-$result = NPTest->testCmd( "./check_disk -w 100% -c 100% ".${mountpoint_valid} ); # 100% empty
-cmp_ok( $result->return_code, "==", 2, "100% empty" );
-like( $result->output, $failureOutput, "Right output" );
+$result = NPTest->testCmd( "./check_disk -w 100% -c 100% $output_format ".${mountpoint_valid} ); # 100% empty
+cmp_ok( $result->return_code, "==", 0, "100% empty" );
+like($result->{'mp_test_result'}->{'state'}, "/CRITICAL/", "100% empty");
$result = NPTest->testCmd( "./check_disk -w 100000000 -c 100000000 $mountpoint_valid" );
cmp_ok( $result->return_code, '==', 2, "Check for 100TB free" );
@@ -263,7 +296,8 @@ cmp_ok( $result->return_code, "==", 2, "100 TB empty" );
# Checking old syntax of check_disk warn crit [fs], with warn/crit at USED% thresholds
$result = NPTest->testCmd( "./check_disk 0 0 ".${mountpoint_valid} );
cmp_ok( $result->return_code, "==", 2, "Old syntax: 0% used");
-like ( $result->only_output, qr(^[^;]*;[^;]*$), "Select only one path with positional arguments");
+# like ( $result->only_output, qr(^[^;]*;[^;]*$), "Select only one path with positional arguments");
+# TODO not sure what the above should test, taking it out
$result = NPTest->testCmd( "./check_disk 100 100 $mountpoint_valid" );
cmp_ok( $result->return_code, '==', 0, "Old syntax: 100% used" );
@@ -311,8 +345,9 @@ $result = NPTest->testCmd( "./check_disk -w 0% -c 0% -p / -p /" );
unlike( $result->output, '/ \/ .* \/ /', "Should not show same filesystem twice");
# are partitions added if -C is given without path selection -p ?
-$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -C -w 0% -c 0% -p $mountpoint_valid" );
-like( $result->output, '/;.*;\|/', "-C selects partitions if -p is not given");
+$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -C -w 0% -c 0% -p $mountpoint_valid $output_format" );
+cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
+cmp_ok(scalar $result->{'mp_test_result'}->{'checks'}, '>', 1, "-C invokes matchall logic again");
# grouping: exit crit if the sum of free megs on mp1+mp2 is less than warn/crit
$result = NPTest->testCmd( "./check_disk -w ". ($free_mb_on_all + 1) ." -c ". ($free_mb_on_all + 1) ." -g group -p $mountpoint_valid -p $mountpoint2_valid" );
@@ -359,39 +394,37 @@ like( $result->output, qr/$mountpoint2_valid/,"ignore: output data does have $mo
# ignore-missing: exit okay, when fs is not accessible
$result = NPTest->testCmd( "./check_disk --ignore-missing -w 0% -c 0% -p /bob");
cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for not existing filesystem /bob");
-like( $result->output, '/^DISK OK - No disks were found for provided parameters - ignored paths: /bob;.*$/', 'Output OK');
+like( $result->output, '/No filesystems were found for the provided parameters.*$/', 'Output OK');
# ignore-missing: exit okay, when regex does not match
$result = NPTest->testCmd( "./check_disk --ignore-missing -w 0% -c 0% -r /bob");
cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for regular expression not matching");
-like( $result->output, '/^DISK OK - No disks were found for provided parameters.*$/', 'Output OK');
+like( $result->output, '/No filesystems were found for the provided parameters.*$/', 'Output OK');
# ignore-missing: exit okay, when fs with exact match (-E) is not found
$result = NPTest->testCmd( "./check_disk --ignore-missing -w 0% -c 0% -E -p /etc");
cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay when exact match does not find fs");
-like( $result->output, '/^DISK OK - No disks were found for provided parameters - ignored paths: /etc;.*$/', 'Output OK');
+like( $result->output, '/No filesystems were found for the provided parameters.*$/', 'Output OK');
# ignore-missing: exit okay, when checking one existing fs and one non-existing fs (regex)
$result = NPTest->testCmd( "./check_disk --ignore-missing -w 0% -c 0% -r '/bob' -r '^/\$'");
cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for regular expression not matching");
-like( $result->output, '/^DISK OK - free space: \/ .*$/', 'Output OK');
# ignore-missing: exit okay, when checking one existing fs and one non-existing fs (path)
$result = NPTest->testCmd( "./check_disk --ignore-missing -w 0% -c 0% -p '/bob' -p '/'");
cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for regular expression not matching");
-like( $result->output, '/^DISK OK - free space: / .*; - ignored paths: /bob;.*$/', 'Output OK');
+# like( $result->output, '/^DISK OK - free space: / .*; - ignored paths: /bob;.*$/', 'Output OK');
# ignore-missing: exit okay, when checking one non-existing fs (path) and one ignored
$result = NPTest->testCmd( "./check_disk -n -w 0% -c 0% -r /dummy -i /dummy2");
cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for regular expression not matching");
-like( $result->output, '/^DISK OK - No disks were found for provided parameters\|$/', 'Output OK');
+like( $result->output, '/No filesystems were found for the provided parameters.*$/', 'Output OK');
# ignore-missing: exit okay, when regex match does not find anything
$result = NPTest->testCmd( "./check_disk -n -e -l -w 10% -c 5% -W 10% -K 5% -r /dummy");
cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for regular expression not matching");
-like( $result->output, '/^DISK OK\|$/', 'Output OK');
# ignore-missing: exit okay, when regex match does not find anything
$result = NPTest->testCmd( "./check_disk -n -l -w 10% -c 5% -W 10% -K 5% -r /dummy");
cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for regular expression not matching");
-like( $result->output, '/^DISK OK - No disks were found for provided parameters\|$/', 'Output OK');
+like( $result->output, '/No filesystems were found for the provided parameters.*$/', 'Output OK');
diff --git a/plugins/tests/test_check_disk.c b/plugins/tests/test_check_disk.c
index 963a9413..35c57bce 100644
--- a/plugins/tests/test_check_disk.c
+++ b/plugins/tests/test_check_disk.c
@@ -24,7 +24,7 @@
void np_test_mount_entry_regex(struct mount_entry *dummy_mount_list, char *regstr, int cflags, int expect, char *desc);
int main(int argc, char **argv) {
- plan_tests(33);
+ plan_tests(35);
struct name_list *exclude_filesystem = NULL;
ok(np_find_name(exclude_filesystem, "/var/log") == false, "/var/log not in list");
@@ -81,15 +81,16 @@ int main(int argc, char **argv) {
np_test_mount_entry_regex(dummy_mount_list, strdup("(/home)|(/var)"), cflags, 2, strdup("grouped regex pathname match:"));
np_test_mount_entry_regex(dummy_mount_list, strdup("(/homE)|(/Var)"), cflags | REG_ICASE, 2, strdup("grouped regi pathname match:"));
- struct parameter_list *paths = NULL;
- np_add_parameter(&paths, "/home/groups");
- np_add_parameter(&paths, "/var");
- np_add_parameter(&paths, "/tmp");
- np_add_parameter(&paths, "/home/tonvoon");
- np_add_parameter(&paths, "/dev/c2t0d0s0");
+ filesystem_list test_paths = filesystem_list_init();
+ mp_int_fs_list_append(&test_paths, "/home/groups");
+ mp_int_fs_list_append(&test_paths, "/var");
+ mp_int_fs_list_append(&test_paths, "/tmp");
+ mp_int_fs_list_append(&test_paths, "/home/tonvoon");
+ mp_int_fs_list_append(&test_paths, "/dev/c2t0d0s0");
+ ok(test_paths.length == 5, "List counter works correctly with appends");
- np_set_best_match(paths, dummy_mount_list, false);
- for (struct parameter_list *p = paths; p; p = p->name_next) {
+ mp_int_fs_list_set_best_match(test_paths, dummy_mount_list, false);
+ for (parameter_list_elem *p = test_paths.first; p; p = mp_int_fs_list_get_next(p)) {
struct mount_entry *temp_me;
temp_me = p->best_match;
if (!strcmp(p->name, "/home/groups")) {
@@ -105,15 +106,19 @@ int main(int argc, char **argv) {
}
}
- paths = NULL; /* Bad boy - should free, but this is a test suite */
- np_add_parameter(&paths, "/home/groups");
- np_add_parameter(&paths, "/var");
- np_add_parameter(&paths, "/tmp");
- np_add_parameter(&paths, "/home/tonvoon");
- np_add_parameter(&paths, "/home");
+ for (parameter_list_elem *p = test_paths.first; p; p = mp_int_fs_list_get_next(p)) {
+ mp_int_fs_list_del(&test_paths, p);
+ }
+ ok(test_paths.length == 0, "List delete sets counter properly");
+
+ mp_int_fs_list_append(&test_paths, "/home/groups");
+ mp_int_fs_list_append(&test_paths, "/var");
+ mp_int_fs_list_append(&test_paths, "/tmp");
+ mp_int_fs_list_append(&test_paths, "/home/tonvoon");
+ mp_int_fs_list_append(&test_paths, "/home");
- np_set_best_match(paths, dummy_mount_list, true);
- for (struct parameter_list *p = paths; p; p = p->name_next) {
+ mp_int_fs_list_set_best_match(test_paths, dummy_mount_list, true);
+ for (parameter_list_elem *p = test_paths.first; p; p = mp_int_fs_list_get_next(p)) {
if (!strcmp(p->name, "/home/groups")) {
ok(!p->best_match, "/home/groups correctly not found");
} else if (!strcmp(p->name, "/var")) {
@@ -129,8 +134,8 @@ int main(int argc, char **argv) {
bool found = false;
/* test deleting first element in paths */
- paths = np_del_parameter(paths, NULL);
- for (struct parameter_list *p = paths; p; p = p->name_next) {
+ mp_int_fs_list_del(&test_paths, NULL);
+ for (parameter_list_elem *p = test_paths.first; p; p = mp_int_fs_list_get_next(p)) {
if (!strcmp(p->name, "/home/groups")) {
found = true;
}
@@ -138,23 +143,21 @@ int main(int argc, char **argv) {
ok(!found, "first element successfully deleted");
found = false;
- struct parameter_list *prev = NULL;
- struct parameter_list *p = paths;
- while (p) {
- if (!strcmp(p->name, "/tmp")) {
- p = np_del_parameter(p, prev);
- } else {
- prev = p;
- p = p->name_next;
+ parameter_list_elem *prev = NULL;
+ parameter_list_elem *p = NULL;
+ for (parameter_list_elem *path = test_paths.first; path; path = mp_int_fs_list_get_next(path)) {
+ if (!strcmp(path->name, "/tmp")) {
+ mp_int_fs_list_del(&test_paths, path);
}
+ p = path;
}
- struct parameter_list *last = NULL;
- for (struct parameter_list *path = paths; path; path = path->name_next) {
+ parameter_list_elem *last = NULL;
+ for (parameter_list_elem *path = test_paths.first; path; path = mp_int_fs_list_get_next(path)) {
if (!strcmp(path->name, "/tmp")) {
found = true;
}
- if (path->name_next) {
+ if (path->next) {
prev = path;
} else {
last = path;
@@ -163,8 +166,8 @@ int main(int argc, char **argv) {
ok(!found, "/tmp element successfully deleted");
int count = 0;
- p = np_del_parameter(last, prev);
- for (p = paths; p; p = p->name_next) {
+ mp_int_fs_list_del(&test_paths, p);
+ for (p = test_paths.first; p; p = p->next) {
if (!strcmp(p->name, "/home")) {
found = true;
}
--
cgit v1.2.3-74-g34f1
From c4fd34ed7966a197e596f3e766f58423fe9c5ddc Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Sun, 30 Mar 2025 22:46:09 +0200
Subject: Codespell fixes
---
plugins/check_disk.c | 6 +++---
plugins/t/check_disk.t | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index 3cab816d..ddb9ee49 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -288,7 +288,7 @@ int main(int argc, char **argv) {
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 previos 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);
@@ -310,7 +310,7 @@ int main(int argc, char **argv) {
mp_add_subcheck_to_check(&overall, unit_sc);
}
} else {
- // Aparently no machting fs found
+ // Apparently no machting fs found
mp_subcheck none_sc = mp_subcheck_init();
xasprintf(&none_sc.output, "No filesystems were found for the provided parameters");
@@ -833,7 +833,7 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
warn_freeinodes_percent, crit_freeinodes_percent);
}
- // If a list of paths has not been explicitely selected, find entire
+ // If a list of paths has not been explicitly selected, find entire
// mount list and create list of paths
if (!path_selected && !result.config.path_ignored) {
for (struct mount_entry *me = result.config.mount_list; me; me = me->me_next) {
diff --git a/plugins/t/check_disk.t b/plugins/t/check_disk.t
index 16daee9a..019cc9fe 100644
--- a/plugins/t/check_disk.t
+++ b/plugins/t/check_disk.t
@@ -39,13 +39,13 @@ like($result->{'mp_test_result'}->{'checks'}->[0]->{'state'}, "/OK/", "First sub
like($result->{'mp_test_result'}->{'checks'}->[1]->{'state'}, "/OK/", "Second sub result is OK");
my $absolut_space_mp1 = $result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}->[0]->{'perfdata'}->[0]->{'max'}->{'value'};
-# print("absolut space on mp1: ". $absolut_space_mp1 . "\n");
+# print("absolute space on mp1: ". $absolut_space_mp1 . "\n");
my $free_percent_on_mp1 = ($result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}->[0]->{'perfdata'}->[0]->{'value'}->{'value'} / ($absolut_space_mp1/100));
print("free percent on mp1: ". $free_percent_on_mp1 . "\n");
my $absolut_space_mp2 = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}->[0]->{'perfdata'}->[0]->{'max'}->{'value'};
-# print("absolut space on mp2: ". $absolut_space_mp2 . "\n");
+# print("absolute space on mp2: ". $absolut_space_mp2 . "\n");
my $free_percent_on_mp2 = ($result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}->[0]->{'perfdata'}->[0]->{'value'}->{'value'}/ ($absolut_space_mp2/100));
print("free percent on mp2: ". $free_percent_on_mp2 . "\n");
--
cgit v1.2.3-74-g34f1
From a4cf2e79f75dce3828be21726f10c755f652f710 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Sun, 30 Mar 2025 23:30:51 +0200
Subject: Remove cool, comfy c23 functionality for some dirty old hacks
---
plugins/check_disk.c | 42 +++++++++++++++++++++++++++------------
plugins/check_disk.d/utils_disk.c | 2 +-
plugins/check_disk.d/utils_disk.h | 38 ++++++++++++++++++-----------------
3 files changed, 50 insertions(+), 32 deletions(-)
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index ddb9ee49..ac3933a6 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -96,6 +96,22 @@ static void print_help(void);
static int verbose = 0;
+// This would not be necessary in C23!!
+const byte_unit Bytes_Factor = 1;
+const byte_unit KibiBytes_factor = 1024;
+const byte_unit MebiBytes_factor = 1048576;
+const byte_unit GibiBytes_factor = 1073741824;
+const byte_unit TebiBytes_factor = 1099511627776;
+const byte_unit PebiBytes_factor = 1125899906842624;
+const byte_unit ExbiBytes_factor = 1152921504606846976;
+const byte_unit KiloBytes_factor = 1000;
+const byte_unit MegaBytes_factor = 1000000;
+const byte_unit GigaBytes_factor = 1000000000;
+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);
@@ -409,7 +425,7 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
bool path_selected = false;
char *group = NULL;
- byte_unit unit = MebiBytes;
+ byte_unit unit = MebiBytes_factor;
result.config.mount_list = read_file_system_list(false);
@@ -494,25 +510,25 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
break;
case 'u':
if (!strcasecmp(optarg, "bytes")) {
- unit = Bytes;
+ unit = Bytes_Factor;
} else if (!strcmp(optarg, "KiB")) {
- unit = KibiBytes;
+ unit = KibiBytes_factor;
} else if (!strcmp(optarg, "kB")) {
- unit = KiloBytes;
+ unit = KiloBytes_factor;
} else if (!strcmp(optarg, "MiB")) {
- unit = MebiBytes;
+ unit = MebiBytes_factor;
} else if (!strcmp(optarg, "MB")) {
- unit = MegaBytes;
+ unit = MegaBytes_factor;
} else if (!strcmp(optarg, "GiB")) {
- unit = GibiBytes;
+ unit = MegaBytes_factor;
} else if (!strcmp(optarg, "GB")) {
- unit = GigaBytes;
+ unit = MegaBytes_factor;
} else if (!strcmp(optarg, "TiB")) {
- unit = TebiBytes;
+ unit = MegaBytes_factor;
} else if (!strcmp(optarg, "TB")) {
- unit = TeraBytes;
+ unit = MegaBytes_factor;
} else if (!strcmp(optarg, "PiB")) {
- unit = PebiBytes;
+ unit = MegaBytes_factor;
} else if (!strcmp(optarg, "PB")) {
unit = PetaBytes;
} else {
@@ -520,10 +536,10 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
}
break;
case 'k':
- unit = KibiBytes;
+ unit = KibiBytes_factor;
break;
case 'm':
- unit = MebiBytes;
+ unit = MebiBytes_factor;
break;
case display_unit_index:
if (!strcasecmp(optarg, "bytes")) {
diff --git a/plugins/check_disk.d/utils_disk.c b/plugins/check_disk.d/utils_disk.c
index 3986a8a8..a78b4eae 100644
--- a/plugins/check_disk.d/utils_disk.c
+++ b/plugins/check_disk.d/utils_disk.c
@@ -180,7 +180,7 @@ check_disk_config check_disk_config_init() {
return tmp;
}
-char *get_unit_string(byte_unit unit) {
+char *get_unit_string(byte_unit_enum unit) {
switch (unit) {
case Bytes:
return "Bytes";
diff --git a/plugins/check_disk.d/utils_disk.h b/plugins/check_disk.d/utils_disk.h
index a66453ea..1f574695 100644
--- a/plugins/check_disk.d/utils_disk.h
+++ b/plugins/check_disk.d/utils_disk.h
@@ -8,22 +8,24 @@
#include "regex.h"
#include
-typedef enum : unsigned long {
- Humanized = 0,
- Bytes = 1,
- KibiBytes = 1024,
- MebiBytes = 1024 * KibiBytes,
- GibiBytes = 1024 * MebiBytes,
- TebiBytes = 1024 * GibiBytes,
- PebiBytes = 1024 * TebiBytes,
- ExbiBytes = 1024 * PebiBytes,
- KiloBytes = 1000,
- MegaBytes = 1000 * KiloBytes,
- GigaBytes = 1000 * MegaBytes,
- TeraBytes = 1000 * GigaBytes,
- PetaBytes = 1000 * TeraBytes,
- ExaBytes = 1000 * PetaBytes
-} byte_unit;
+typedef unsigned long long byte_unit;
+
+typedef enum {
+ Humanized,
+ Bytes,
+ KibiBytes,
+ MebiBytes,
+ GibiBytes,
+ TebiBytes,
+ PebiBytes,
+ ExbiBytes,
+ KiloBytes,
+ MegaBytes,
+ GigaBytes,
+ TeraBytes,
+ PetaBytes,
+ ExaBytes,
+} byte_unit_enum;
typedef struct name_list string_list;
struct name_list {
@@ -120,7 +122,7 @@ typedef struct {
struct mount_entry *mount_list;
struct name_list *seen;
- byte_unit display_unit;
+ byte_unit_enum display_unit;
// byte_unit unit;
bool output_format_is_set;
@@ -149,7 +151,7 @@ measurement_unit create_measurement_unit_from_filesystem(parameter_list_elem fil
int search_parameter_list(parameter_list_elem *list, const char *name);
bool np_regex_match_mount_entry(struct mount_entry *, regex_t *);
-char *get_unit_string(byte_unit);
+char *get_unit_string(byte_unit_enum);
check_disk_config check_disk_config_init();
char *humanize_byte_value(uintmax_t value, bool use_si_units);
--
cgit v1.2.3-74-g34f1
From d1d6ba67065c0b1a8a61d59522e19a94eb647c94 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Sun, 30 Mar 2025 23:42:50 +0200
Subject: Add debugging to tests for CI
---
plugins/t/check_disk.t | 3 +++
1 file changed, 3 insertions(+)
diff --git a/plugins/t/check_disk.t b/plugins/t/check_disk.t
index 019cc9fe..1d0b9838 100644
--- a/plugins/t/check_disk.t
+++ b/plugins/t/check_disk.t
@@ -129,6 +129,9 @@ my $warn_percth_data = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[
my $crit_percth_data = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[0]->{'perfdata'}->[0]->{'crit'}->{'end'}->{'value'};
my $total_percth_data = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}[0]->{'perfdata'}->[0]->{'max'}->{'value'};
+print("warn_percth_data: " . $warn_percth_data . "\n");
+print("crit_percth_data: " . $crit_percth_data . "\n");
+
is ($warn_percth_data <=> int((20/100)*$total_percth_data), 0, "Wrong warning in perf data using percent thresholds");
is ($crit_percth_data <=> int((10/100)*$total_percth_data), 0, "Wrong critical in perf data using percent thresholds");
--
cgit v1.2.3-74-g34f1
From 430c641d9c6c3efb3fb0493b35e11dbc6ede2faa Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Sun, 30 Mar 2025 23:55:16 +0200
Subject: Try to circumvent some old compiler errors
---
lib/perfdata.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/lib/perfdata.c b/lib/perfdata.c
index 1742342e..f425ffcf 100644
--- a/lib/perfdata.c
+++ b/lib/perfdata.c
@@ -569,9 +569,6 @@ mp_perfdata_value mp_pd_value_multiply(mp_perfdata_value left, mp_perfdata_value
left.pd_double = (double)left.pd_uint;
left.type = PD_TYPE_DOUBLE;
break;
- case PD_TYPE_DOUBLE:
- default:
- // already there
}
switch (right.type) {
@@ -583,9 +580,6 @@ mp_perfdata_value mp_pd_value_multiply(mp_perfdata_value left, mp_perfdata_value
right.pd_double = (double)right.pd_uint;
right.type = PD_TYPE_DOUBLE;
break;
- case PD_TYPE_DOUBLE:
- default:
- // already there
}
left.pd_double *= right.pd_double;
--
cgit v1.2.3-74-g34f1
From d6d394fb0e1d04bbdb9304dcedad933878846266 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Mon, 31 Mar 2025 00:10:56 +0200
Subject: Fix some typos with units
---
plugins/check_disk.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index ac3933a6..e53ec87f 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -520,17 +520,17 @@ check_disk_config_wrapper process_arguments(int argc, char **argv) {
} else if (!strcmp(optarg, "MB")) {
unit = MegaBytes_factor;
} else if (!strcmp(optarg, "GiB")) {
- unit = MegaBytes_factor;
+ unit = GibiBytes_factor;
} else if (!strcmp(optarg, "GB")) {
- unit = MegaBytes_factor;
+ unit = GigaBytes_factor;
} else if (!strcmp(optarg, "TiB")) {
- unit = MegaBytes_factor;
+ unit = TebiBytes_factor;
} else if (!strcmp(optarg, "TB")) {
- unit = MegaBytes_factor;
+ unit = TeraBytes_factor;
} else if (!strcmp(optarg, "PiB")) {
- unit = MegaBytes_factor;
+ unit = PebiBytes_factor;
} else if (!strcmp(optarg, "PB")) {
- unit = PetaBytes;
+ unit = PetaBytes_factor;
} else {
die(STATE_UNKNOWN, _("unit type %s not known\n"), optarg);
}
--
cgit v1.2.3-74-g34f1
From 1b0085c2e7196aa77d605e8cb1863064a8e5189c Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Mon, 31 Mar 2025 00:46:10 +0200
Subject: Fixes problems after a4cf2e79f75dce3828be21726f10c755f652f710
---
plugins/check_disk.c | 2 +-
plugins/check_disk.d/utils_disk.c | 62 ++++++++++++++++++++++++---------------
plugins/check_disk.d/utils_disk.h | 2 +-
3 files changed, 41 insertions(+), 25 deletions(-)
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
index e53ec87f..515ddff0 100644
--- a/plugins/check_disk.c
+++ b/plugins/check_disk.c
@@ -1112,7 +1112,7 @@ mp_subcheck evaluate_filesystem(measurement_unit measurement_unit, bool display_
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),
- humanize_byte_value(measurement_unit.total_bytes, false));
+ humanize_byte_value((unsigned long long)measurement_unit.total_bytes, false));
}
mp_perfdata used_space = perfdata_init();
diff --git a/plugins/check_disk.d/utils_disk.c b/plugins/check_disk.d/utils_disk.c
index a78b4eae..eec1282b 100644
--- a/plugins/check_disk.d/utils_disk.c
+++ b/plugins/check_disk.d/utils_disk.c
@@ -309,7 +309,7 @@ measurement_unit create_measurement_unit_from_filesystem(parameter_list_elem fil
#define RANDOM_STRING_LENGTH 64
-char *humanize_byte_value(uintmax_t value, bool use_si_units) {
+char *humanize_byte_value(unsigned long long value, bool use_si_units) {
// Idea: A reasonable output should have at most 3 orders of magnitude
// before the decimal separator
// 353GiB is ok, 2444 GiB should be 2.386 TiB
@@ -317,36 +317,52 @@ char *humanize_byte_value(uintmax_t value, bool use_si_units) {
if (result == NULL) {
die(STATE_UNKNOWN, _("allocation failed"));
}
+ const byte_unit KibiBytes_factor = 1024;
+ const byte_unit MebiBytes_factor = 1048576;
+ const byte_unit GibiBytes_factor = 1073741824;
+ const byte_unit TebiBytes_factor = 1099511627776;
+ const byte_unit PebiBytes_factor = 1125899906842624;
+ const byte_unit ExbiBytes_factor = 1152921504606846976;
+ const byte_unit KiloBytes_factor = 1000;
+ const byte_unit MegaBytes_factor = 1000000;
+ const byte_unit GigaBytes_factor = 1000000000;
+ const byte_unit TeraBytes_factor = 1000000000000;
+ const byte_unit PetaBytes_factor = 1000000000000000;
+ const byte_unit ExaBytes_factor = 1000000000000000000;
if (use_si_units) {
// SI units, powers of 10
- if (value < KiloBytes) {
- snprintf(result, RANDOM_STRING_LENGTH, "%ju B", value);
- } else if (value < MegaBytes) {
- snprintf(result, RANDOM_STRING_LENGTH, "%ju KB", value / KiloBytes);
- } else if (value < GigaBytes) {
- snprintf(result, RANDOM_STRING_LENGTH, "%ju MB", value / MegaBytes);
- } else if (value < TeraBytes) {
- snprintf(result, RANDOM_STRING_LENGTH, "%ju GB", value / GigaBytes);
- } else if (value < PetaBytes) {
- snprintf(result, RANDOM_STRING_LENGTH, "%ju TB", value / TeraBytes);
+ if (value < KiloBytes_factor) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%llu B", value);
+ } else if (value < MegaBytes_factor) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%llu KB", value / KiloBytes_factor);
+ } else if (value < GigaBytes_factor) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%llu MB", value / MegaBytes_factor);
+ } else if (value < TeraBytes_factor) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%llu GB", value / GigaBytes_factor);
+ } else if (value < PetaBytes_factor) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%llu TB", value / TeraBytes_factor);
+ } else if (value < ExaBytes_factor) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%llu PB", value / PetaBytes_factor);
} else {
- snprintf(result, RANDOM_STRING_LENGTH, "%ju PB", value / PetaBytes);
+ snprintf(result, RANDOM_STRING_LENGTH, "%llu EB", value / ExaBytes_factor);
}
} else {
// IEC units, powers of 2 ^ 10
- if (value < KibiBytes) {
- snprintf(result, RANDOM_STRING_LENGTH, "%ju B", value);
- } else if (value < MebiBytes) {
- snprintf(result, RANDOM_STRING_LENGTH, "%ju KiB", value / KibiBytes);
- } else if (value < GibiBytes) {
- snprintf(result, RANDOM_STRING_LENGTH, "%ju MiB", value / MebiBytes);
- } else if (value < TebiBytes) {
- snprintf(result, RANDOM_STRING_LENGTH, "%ju GiB", value / GibiBytes);
- } else if (value < PebiBytes) {
- snprintf(result, RANDOM_STRING_LENGTH, "%ju TiB", value / TebiBytes);
+ if (value < KibiBytes_factor) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%llu B", value);
+ } else if (value < MebiBytes_factor) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%llu KiB", value / KibiBytes_factor);
+ } else if (value < GibiBytes_factor) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%llu MiB", value / MebiBytes_factor);
+ } else if (value < TebiBytes_factor) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%llu GiB", value / GibiBytes_factor);
+ } else if (value < PebiBytes_factor) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%llu TiB", value / TebiBytes_factor);
+ } else if (value < ExbiBytes_factor) {
+ snprintf(result, RANDOM_STRING_LENGTH, "%llu PiB", value / PebiBytes_factor);
} else {
- snprintf(result, RANDOM_STRING_LENGTH, "%ju PiB", value / PebiBytes);
+ snprintf(result, RANDOM_STRING_LENGTH, "%llu EiB", value / ExbiBytes_factor);
}
}
diff --git a/plugins/check_disk.d/utils_disk.h b/plugins/check_disk.d/utils_disk.h
index 1f574695..6831d1fd 100644
--- a/plugins/check_disk.d/utils_disk.h
+++ b/plugins/check_disk.d/utils_disk.h
@@ -154,4 +154,4 @@ bool np_regex_match_mount_entry(struct mount_entry *, regex_t *);
char *get_unit_string(byte_unit_enum);
check_disk_config check_disk_config_init();
-char *humanize_byte_value(uintmax_t value, bool use_si_units);
+char *humanize_byte_value(unsigned long long value, bool use_si_units);
--
cgit v1.2.3-74-g34f1
From 24a50b9421050b3c49dd07eddc942934f66685ca Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Mon, 31 Mar 2025 22:18:19 +0200
Subject: check_disk: decrease precision to avoid false negatives with small
measurement changes
---
plugins/t/check_disk.t | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/plugins/t/check_disk.t b/plugins/t/check_disk.t
index 1d0b9838..f07b2303 100644
--- a/plugins/t/check_disk.t
+++ b/plugins/t/check_disk.t
@@ -54,6 +54,10 @@ my @perfdata;
@perfdata[0] = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}->[0]->{'perfdata'}->[0];
@perfdata[1] = $result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}->[0]->{'perfdata'}->[0];
+# Decrease precision of numbers since the the fs might be modified between the two runs
+$perfdata[0]->{'value'}->{'value'} = int($perfdata[0]->{'value'}->{'value'} / 1000000);
+$perfdata[0]->{'value'}->{'value'} = int($perfdata[0]->{'value'}->{'value'} / 1000000);
+
# Calculate avg_free free on mountpoint1 and mountpoint2
# because if you check in the middle, you should get different errors
my $avg_free_percent = ceil(($free_percent_on_mp1+$free_percent_on_mp2)/2);
@@ -144,8 +148,11 @@ cmp_ok( $result->return_code, "==", 0, "with JSON test format result should alwa
# write comparison set for perfdata here, but in reversed order, maybe there is a smarter way
my @perfdata2;
-@perfdata2[1] = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}->[0]->{'perfdata'}->[0];
@perfdata2[0] = $result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}->[0]->{'perfdata'}->[0];
+@perfdata2[1] = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}->[0]->{'perfdata'}->[0];
+# Decrease precision of numbers since the the fs might be modified between the two runs
+$perfdata2[0]->{'value'}->{'value'} = int($perfdata[0]->{'value'}->{'value'} / 1000000);
+$perfdata2[0]->{'value'}->{'value'} = int($perfdata[0]->{'value'}->{'value'} / 1000000);
is_deeply(\@perfdata, \@perfdata2, "perf data for both filesystems same when reversed");
# Basic filesystem checks for sizes
--
cgit v1.2.3-74-g34f1
From 13c9de8c77477e78014622f5c4ff31226aeb286d Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Mon, 31 Mar 2025 22:29:49 +0200
Subject: Try fixing some tests
---
plugins/t/check_disk.t | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/plugins/t/check_disk.t b/plugins/t/check_disk.t
index f07b2303..0f62fb2b 100644
--- a/plugins/t/check_disk.t
+++ b/plugins/t/check_disk.t
@@ -26,7 +26,7 @@ my $output_format = "--output-format mp-test-json";
if ($mountpoint_valid eq "" or $mountpoint2_valid eq "") {
plan skip_all => "Need 2 mountpoints to test";
} else {
- plan tests => 96;
+ plan tests => 97;
}
$result = NPTest->testCmd(
@@ -56,7 +56,7 @@ my @perfdata;
# Decrease precision of numbers since the the fs might be modified between the two runs
$perfdata[0]->{'value'}->{'value'} = int($perfdata[0]->{'value'}->{'value'} / 1000000);
-$perfdata[0]->{'value'}->{'value'} = int($perfdata[0]->{'value'}->{'value'} / 1000000);
+$perfdata[1]->{'value'}->{'value'} = int($perfdata[1]->{'value'}->{'value'} / 1000000);
# Calculate avg_free free on mountpoint1 and mountpoint2
# because if you check in the middle, you should get different errors
@@ -136,8 +136,8 @@ my $total_percth_data = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}
print("warn_percth_data: " . $warn_percth_data . "\n");
print("crit_percth_data: " . $crit_percth_data . "\n");
-is ($warn_percth_data <=> int((20/100)*$total_percth_data), 0, "Wrong warning in perf data using percent thresholds");
-is ($crit_percth_data <=> int((10/100)*$total_percth_data), 0, "Wrong critical in perf data using percent thresholds");
+is (int($warn_percth_data), int((20/100)*$total_percth_data), "Wrong warning in perf data using percent thresholds. Got " . $warn_percth_data . " with total " . $total_percth_data);
+is (int($crit_percth_data), int((10/100)*$total_percth_data), "Wrong critical in perf data using percent thresholds. Got " . $crit_percth_data . " with total " . $total_percth_data);
# Check when order of mount points are reversed, that perf data remains same
@@ -151,8 +151,8 @@ my @perfdata2;
@perfdata2[0] = $result->{'mp_test_result'}->{'checks'}->[1]->{'checks'}->[0]->{'perfdata'}->[0];
@perfdata2[1] = $result->{'mp_test_result'}->{'checks'}->[0]->{'checks'}->[0]->{'perfdata'}->[0];
# Decrease precision of numbers since the the fs might be modified between the two runs
-$perfdata2[0]->{'value'}->{'value'} = int($perfdata[0]->{'value'}->{'value'} / 1000000);
-$perfdata2[0]->{'value'}->{'value'} = int($perfdata[0]->{'value'}->{'value'} / 1000000);
+$perfdata2[0]->{'value'}->{'value'} = int($perfdata2[0]->{'value'}->{'value'} / 1000000);
+$perfdata2[1]->{'value'}->{'value'} = int($perfdata2[1]->{'value'}->{'value'} / 1000000);
is_deeply(\@perfdata, \@perfdata2, "perf data for both filesystems same when reversed");
# Basic filesystem checks for sizes
@@ -174,8 +174,9 @@ my $free_mb_on_all = $free_mb_on_mp1 + $free_mb_on_mp2;
$result = NPTest->testCmd( "./check_disk -e -w 1 -c 1 -p $more_free $output_format" );
cmp_ok( $result->return_code, "==", 0, "with JSON test format result should always be OK");
-$result = NPTest->testCmd( "./check_disk 100 100 $more_free" );
-cmp_ok( $result->return_code, '==', 0, "Old syntax okay" );
+$result = NPTest->testCmd( "./check_disk 101 101 $more_free" );
+like($result->output, "/OK/", "OK in Output");
+cmp_ok( $result->return_code, '==', 0, "Old syntax okay, output was: ". $result->output . "\n" );
$result = NPTest->testCmd( "./check_disk -w 1% -c 1% -p $more_free" );
cmp_ok( $result->return_code, "==", 0, "At least 1% free" );
--
cgit v1.2.3-74-g34f1
From d0647ec7e1500c0e6164ac9820a7d623582bdde2 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Mon, 31 Mar 2025 23:41:51 +0200
Subject: Some code simplifications
---
lib/utils_base.c | 18 +++---------------
1 file changed, 3 insertions(+), 15 deletions(-)
diff --git a/lib/utils_base.c b/lib/utils_base.c
index ff9540c7..c49a473f 100644
--- a/lib/utils_base.c
+++ b/lib/utils_base.c
@@ -225,27 +225,15 @@ bool mp_check_range(const mp_perfdata_value value, const mp_range my_range) {
if (my_range.end_infinity == false && my_range.start_infinity == false) {
// range: .........|---inside---|...........
// value
- if ((cmp_perfdata_value(my_range.start, value) < 1) && (cmp_perfdata_value(value, my_range.end) <= 0)) {
- is_inside = true;
- } else {
- is_inside = false;
- }
+ is_inside = ((cmp_perfdata_value(my_range.start, value) < 1) && (cmp_perfdata_value(value, my_range.end) <= 0));
} else if (my_range.start_infinity == false && my_range.end_infinity == true) {
// range: .........|---inside---------
// value
- if (cmp_perfdata_value(my_range.start, value) < 0) {
- is_inside = true;
- } else {
- is_inside = false;
- }
+ is_inside = (cmp_perfdata_value(my_range.start, value) < 0);
} else if (my_range.start_infinity == true && my_range.end_infinity == false) {
// range: -inside--------|....................
// value
- if (cmp_perfdata_value(value, my_range.end) == -1) {
- is_inside = true;
- } else {
- is_inside = false;
- }
+ is_inside = (cmp_perfdata_value(value, my_range.end) == -1);
} else {
// range from -inf to inf, so always inside
is_inside = true;
--
cgit v1.2.3-74-g34f1
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(-)
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(-)
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 73b42dd08b11be79bbeb4a09910bbe37699ff3b9 Mon Sep 17 00:00:00 2001
From: Jan Wagner
Date: Mon, 21 Apr 2025 00:44:41 +0200
Subject: CI: Install gawk on fedora > 41
---
.github/os_detect.sh | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/.github/os_detect.sh b/.github/os_detect.sh
index ee9c145d..47c762d3 100644
--- a/.github/os_detect.sh
+++ b/.github/os_detect.sh
@@ -1,10 +1,17 @@
#!/bin/sh -e
+
+. /etc/os-release
+
# workaround for really bare-bones Archlinux containers:
if [ -x "$(command -v pacman)" ]; then
pacman --noconfirm -Sy
pacman --noconfirm -S grep gawk sed
fi
+if [ ${ID} == "fedora" -a ${VERSION_ID} -gt 41 ]; then
+ dnf install -y gawk
+fi
+
os_release_file=
if [ -s "/etc/os-release" ]; then
os_release_file="/etc/os-release"
--
cgit v1.2.3-74-g34f1
From 14169fe5a11b94a9f9ab44336fdb5170ee98be66 Mon Sep 17 00:00:00 2001
From: Jan Wagner
Date: Sat, 19 Apr 2025 14:37:46 +0200
Subject: check_http: Adding deprecation text
---
plugins/check_http.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/plugins/check_http.c b/plugins/check_http.c
index baff682a..8e0c15ec 100644
--- a/plugins/check_http.c
+++ b/plugins/check_http.c
@@ -1724,6 +1724,16 @@ print_help (void)
printf ("%s\n", _("strings and regular expressions, check connection times, and report on"));
printf ("%s\n", _("certificate expiration times."));
+ printf ("\n");
+ printf ("%s\n", _("ATTENTION!"));
+ printf ("\n");
+ printf ("%s\n", _("THIS PLUGIN IS DEPRECATED. The functionality was reimplemented by the"));
+ printf ("%s\n", _("check_curl plugin, which can be used as a drop-in replacement. You should"));
+ printf ("%s\n", _("migrate your checks over to check_curl, because check_http is going to be"));
+ printf ("%s\n", _("removed sooner than later. Just replace check_http with check_curl in your"));
+ printf ("%s\n", _("check command definitions."));
+ printf ("%s\n", _("Report issues to: https://github.com/monitoring-plugins/monitoring-plugins/issues"));
+
printf ("\n\n");
print_usage ();
--
cgit v1.2.3-74-g34f1
From c975182145939e0f4e1c1b35c415c3451dd83d7d Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Sun, 27 Apr 2025 17:50:59 +0200
Subject: clang-format: reduce line lenght to 100 char, it's easier to read
---
.clang-format | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.clang-format b/.clang-format
index ca411edd..0ff68114 100644
--- a/.clang-format
+++ b/.clang-format
@@ -4,7 +4,7 @@ TabWidth: 4
AllowShortIfStatementsOnASingleLine: false
BreakBeforeBraces: Attach
AlignConsecutiveMacros: true
-ColumnLimit: 140
+ColumnLimit: 100
IndentPPDirectives: AfterHash
SortIncludes: Never
AllowShortEnumsOnASingleLine: false
--
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
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
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(-)
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(-)
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 4acba2b3ecef7c1482b3cd25e35773947d80e2c6 Mon Sep 17 00:00:00 2001
From: William
Date: Thu, 27 Mar 2025 11:20:36 +1000
Subject: Improve handling of -4/-6
If fping is used with a target that has dual stack v4/v6, then due to
the logic during command construction, ipv4 will never be checked as v6
is preferred by fping.
This explicitly flags -4/-6 when it is requested by the user.
---
plugins/check_fping.c | 33 ++++++++++++++++++++++-----------
1 file changed, 22 insertions(+), 11 deletions(-)
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
index ec7abb67..1c2b7689 100644
--- a/plugins/check_fping.c
+++ b/plugins/check_fping.c
@@ -79,7 +79,29 @@ int main(int argc, char **argv) {
server = strscpy(server, config.server_name);
char *option_string = "";
+ char *fping_prog = NULL;
+
/* compose the command */
+#ifdef PATH_TO_FPING6
+ if (address_family != AF_INET && is_inet6_addr(server)) {
+ fping_prog = strdup(PATH_TO_FPING6);
+ } else {
+ xasprintf(&option_string, "%s-4 ", option_string);
+ fping_prog = strdup(PATH_TO_FPING);
+ }
+#else
+ if (address_family != AF_INET) {
+ // -4 / -6 must be set explicitly as when a host has dual stack
+ // if we don't specify -4 then fping selects ipv6 which can mess
+ // with some checks.
+ xasprintf(&option_string, "%s-6 ", option_string);
+ } else {
+ xasprintf(&option_string, "%s-4 ", option_string);
+ }
+
+ fping_prog = strdup(PATH_TO_FPING);
+#endif
+
if (config.target_timeout) {
xasprintf(&option_string, "%s-t %d ", option_string, config.target_timeout);
}
@@ -99,17 +121,6 @@ int main(int argc, char **argv) {
xasprintf(&option_string, "%s-R ", option_string);
}
- char *fping_prog = NULL;
-#ifdef PATH_TO_FPING6
- if (address_family != AF_INET && is_inet6_addr(server)) {
- fping_prog = strdup(PATH_TO_FPING6);
- } else {
- fping_prog = strdup(PATH_TO_FPING);
- }
-#else
- fping_prog = strdup(PATH_TO_FPING);
-#endif
-
char *command_line = NULL;
xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string, config.packet_size, config.packet_count, server);
--
cgit v1.2.3-74-g34f1
From a1472be88322140cf1f2fc39b9e1b654a86f8155 Mon Sep 17 00:00:00 2001
From: William
Date: Fri, 28 Mar 2025 12:40:35 +1000
Subject: Harden check with unspec
---
plugins/check_fping.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
index 1c2b7689..cf9c2d1c 100644
--- a/plugins/check_fping.c
+++ b/plugins/check_fping.c
@@ -83,14 +83,14 @@ int main(int argc, char **argv) {
/* compose the command */
#ifdef PATH_TO_FPING6
- if (address_family != AF_INET && is_inet6_addr(server)) {
+ if (address_family == AF_INET6 || (address_family == AF_UNSPEC && is_inet6_addr(server))) {
fping_prog = strdup(PATH_TO_FPING6);
} else {
xasprintf(&option_string, "%s-4 ", option_string);
fping_prog = strdup(PATH_TO_FPING);
}
#else
- if (address_family != AF_INET) {
+ if (address_family == AF_INET6 || (address_family == AF_UNSPEC && is_inet6_addr(server))) {
// -4 / -6 must be set explicitly as when a host has dual stack
// if we don't specify -4 then fping selects ipv6 which can mess
// with some checks.
--
cgit v1.2.3-74-g34f1
From 58a34245110f12192d3b3e99198086c119a57418 Mon Sep 17 00:00:00 2001
From: William
Date: Wed, 2 Apr 2025 10:50:56 +1000
Subject: Improve logic
---
plugins/check_fping.c | 48 +++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 41 insertions(+), 7 deletions(-)
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
index cf9c2d1c..9dadcec7 100644
--- a/plugins/check_fping.c
+++ b/plugins/check_fping.c
@@ -81,27 +81,61 @@ int main(int argc, char **argv) {
char *option_string = "";
char *fping_prog = NULL;
- /* compose the command */
+ /* First determine if the target is dualstack or ipv6 only. */
+#ifdef USE_IPV6
+ bool server_is_inet6_addr = is_inet6_addr(server);
+#else
+ bool server_is_inet6_addr = false;
+#endif
+
+ /* PATH_TO_FPING6 implies USE_IPV6 */
#ifdef PATH_TO_FPING6
- if (address_family == AF_INET6 || (address_family == AF_UNSPEC && is_inet6_addr(server))) {
+ /*
+ * If the user requested -6 OR the user made no assertion and the address is v6 or dualstack
+ * -> we use ipv6
+ * If the user requested -4 OR the user made no assertion and the address is v4 ONLY
+ * -> we use ipv4
+ */
+ if (address_family == AF_INET6 || (address_family == AF_UNSPEC && server_is_inet6_addr)) {
fping_prog = strdup(PATH_TO_FPING6);
} else {
xasprintf(&option_string, "%s-4 ", option_string);
fping_prog = strdup(PATH_TO_FPING);
}
#else
- if (address_family == AF_INET6 || (address_family == AF_UNSPEC && is_inet6_addr(server))) {
- // -4 / -6 must be set explicitly as when a host has dual stack
- // if we don't specify -4 then fping selects ipv6 which can mess
- // with some checks.
+#ifdef USE_IPV6
+ /*
+ * If the user requested -6 OR the user made no assertion and the address is v6 or dualstack
+ * -> we use ipv6
+ * If the user requested -4 OR the user made no assertion and the address is v4 ONLY
+ * -> we use ipv4
+ */
+ if (address_family == AF_INET6 || (address_family == AF_UNSPEC && server_is_inet6_addr)) {
xasprintf(&option_string, "%s-6 ", option_string);
} else {
xasprintf(&option_string, "%s-4 ", option_string);
}
-
+#else
+ /*
+ * If the user requested -6
+ * -> warn that v6 is not available
+ * -> we use ipv4
+ */
+ if (address_family == AF_INET6) {
+ usage4(_("IPv6 support not available"));
+ }
+ /*
+ * Note here we still have to call with -4, else in the case of a dual stacked target
+ * we could potentially silently use ipv6 despite having just warned that it is not available
+ */
+ xasprintf(&option_string, "%s-4 ", option_string);
+ /* end USE_IPV6 */
+#endif
fping_prog = strdup(PATH_TO_FPING);
+ /* end PATH_TO_FPING6 */
#endif
+ /* compose the command */
if (config.target_timeout) {
xasprintf(&option_string, "%s-t %d ", option_string, config.target_timeout);
}
--
cgit v1.2.3-74-g34f1
From 1fb9300a2f10d5c649df484e1b8d7550f9a5f846 Mon Sep 17 00:00:00 2001
From: William
Date: Wed, 7 May 2025 13:17:47 +1000
Subject: Remove un-needed flags
---
configure.ac | 7 -------
plugins/check_fping.c | 42 ------------------------------------------
2 files changed, 49 deletions(-)
diff --git a/configure.ac b/configure.ac
index fdc9b699..bd3de196 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1524,17 +1524,10 @@ AC_PATH_PROG(PATH_TO_FPING6,fping6)
AC_ARG_WITH(fping_command,
ACX_HELP_STRING([--with-fping-command=PATH],
[Path to fping command]), PATH_TO_FPING=$withval)
-AC_ARG_WITH(fping6_command,
- ACX_HELP_STRING([--with-fping6-command=PATH],
- [Path to fping6 command]), PATH_TO_FPING6=$withval)
-
if test -n "$PATH_TO_FPING"
then
AC_DEFINE_UNQUOTED(PATH_TO_FPING,"$PATH_TO_FPING",[path to fping])
EXTRAS="$EXTRAS check_fping\$(EXEEXT)"
- if test x"$with_ipv6" != xno && test -n "$PATH_TO_FPING6"; then
- AC_DEFINE_UNQUOTED(PATH_TO_FPING6,"$PATH_TO_FPING6",[path to fping6])
- fi
else
AC_MSG_WARN([Get fping from http://www.fping.com in order to make check_fping plugin])
fi
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
index 9dadcec7..e05056b2 100644
--- a/plugins/check_fping.c
+++ b/plugins/check_fping.c
@@ -82,28 +82,8 @@ int main(int argc, char **argv) {
char *fping_prog = NULL;
/* First determine if the target is dualstack or ipv6 only. */
-#ifdef USE_IPV6
bool server_is_inet6_addr = is_inet6_addr(server);
-#else
- bool server_is_inet6_addr = false;
-#endif
- /* PATH_TO_FPING6 implies USE_IPV6 */
-#ifdef PATH_TO_FPING6
- /*
- * If the user requested -6 OR the user made no assertion and the address is v6 or dualstack
- * -> we use ipv6
- * If the user requested -4 OR the user made no assertion and the address is v4 ONLY
- * -> we use ipv4
- */
- if (address_family == AF_INET6 || (address_family == AF_UNSPEC && server_is_inet6_addr)) {
- fping_prog = strdup(PATH_TO_FPING6);
- } else {
- xasprintf(&option_string, "%s-4 ", option_string);
- fping_prog = strdup(PATH_TO_FPING);
- }
-#else
-#ifdef USE_IPV6
/*
* If the user requested -6 OR the user made no assertion and the address is v6 or dualstack
* -> we use ipv6
@@ -115,25 +95,7 @@ int main(int argc, char **argv) {
} else {
xasprintf(&option_string, "%s-4 ", option_string);
}
-#else
- /*
- * If the user requested -6
- * -> warn that v6 is not available
- * -> we use ipv4
- */
- if (address_family == AF_INET6) {
- usage4(_("IPv6 support not available"));
- }
- /*
- * Note here we still have to call with -4, else in the case of a dual stacked target
- * we could potentially silently use ipv6 despite having just warned that it is not available
- */
- xasprintf(&option_string, "%s-4 ", option_string);
- /* end USE_IPV6 */
-#endif
fping_prog = strdup(PATH_TO_FPING);
- /* end PATH_TO_FPING6 */
-#endif
/* compose the command */
if (config.target_timeout) {
@@ -385,11 +347,7 @@ check_fping_config_wrapper process_arguments(int argc, char **argv) {
address_family = AF_INET;
break;
case '6': /* IPv6 only */
-#ifdef USE_IPV6
address_family = AF_INET6;
-#else
- usage(_("IPv6 support not available\n"));
-#endif
break;
case 'c':
get_threshold(optarg, rv);
--
cgit v1.2.3-74-g34f1
From 236188e92fbc81e0d05f79ee1688daedbaf204dc Mon Sep 17 00:00:00 2001
From: Lorenz Kästle
Date: Thu, 8 May 2025 08:59:36 +0200
Subject: Do not explicitely disable IPv6 in the CI
---
.github/workflows/test-next.yml | 2 +-
.github/workflows/test.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/test-next.yml b/.github/workflows/test-next.yml
index 81240759..fd59e85d 100644
--- a/.github/workflows/test-next.yml
+++ b/.github/workflows/test-next.yml
@@ -38,7 +38,7 @@ jobs:
${{ matrix.distro }} \
/bin/sh -c '${{ matrix.prepare }} && \
tools/setup && \
- ./configure --enable-libtap --with-ipv6=no && \
+ ./configure --enable-libtap && \
make && \
make test && \
make dist && \
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 77ca6585..ce0ec547 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -35,7 +35,7 @@ jobs:
${{ matrix.distro }} \
/bin/sh -c '${{ matrix.prepare }} && \
tools/setup && \
- ./configure --enable-libtap --with-ipv6=no && \
+ ./configure --enable-libtap && \
make && \
make test && \
make dist && \
--
cgit v1.2.3-74-g34f1
From ec47bbbda6b99f0efc1801a424812a4dd457f9b6 Mon Sep 17 00:00:00 2001
From: Andreas Baumann
Date: Fri, 9 May 2025 10:49:02 +0200
Subject: changed filename in cmd_file_read to const char * (check_apt warning)
---
lib/utils_cmd.c | 2 +-
lib/utils_cmd.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/utils_cmd.c b/lib/utils_cmd.c
index 18350ac0..9b222409 100644
--- a/lib/utils_cmd.c
+++ b/lib/utils_cmd.c
@@ -346,7 +346,7 @@ int cmd_run_array(char *const *argv, output *out, output *err, int flags) {
return _cmd_close(fd);
}
-int cmd_file_read(char *filename, output *out, int flags) {
+int cmd_file_read(const char *filename, output *out, int flags) {
int fd;
if (out)
memset(out, 0, sizeof(output));
diff --git a/lib/utils_cmd.h b/lib/utils_cmd.h
index d00069c9..728ece23 100644
--- a/lib/utils_cmd.h
+++ b/lib/utils_cmd.h
@@ -20,7 +20,7 @@ typedef struct output output;
/** prototypes **/
int cmd_run(const char *, output *, output *, int);
int cmd_run_array(char *const *, output *, output *, int);
-int cmd_file_read(char *, output *, int);
+int cmd_file_read(const char *, output *, int);
/* only multi-threaded plugins need to bother with this */
void cmd_init(void);
--
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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 dd93b1403ad28064b0d444189d8aa938dc25365d Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Sun, 18 May 2025 19:19:23 +0200
Subject: utils: Make fmt function for compiler
---
plugins/utils.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/utils.h b/plugins/utils.h
index 92a6c115..1d3c153c 100644
--- a/plugins/utils.h
+++ b/plugins/utils.h
@@ -76,7 +76,7 @@ char *strnl(char *);
char *strpcpy(char *, const char *, const char *);
char *strpcat(char *, const char *, const char *);
int xvasprintf(char **strp, const char *fmt, va_list ap);
-int xasprintf(char **strp, const char *fmt, ...);
+int xasprintf(char **strp, const char *fmt, ...)__attribute__ ((format (printf, 2, 3)));
void usage(const char *) __attribute__((noreturn));
void usage2(const char *, const char *) __attribute__((noreturn));
--
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(-)
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 1187374e745af310a2e346ab1df5250d07c65a69 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle
Date: Wed, 11 Jun 2025 13:11:04 +0200
Subject: Remove unused FPING6 variable
---
configure.ac | 1 -
1 file changed, 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index bd3de196..ae704361 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1519,7 +1519,6 @@ then
fi
AC_PATH_PROG(PATH_TO_FPING,fping)
-AC_PATH_PROG(PATH_TO_FPING6,fping6)
AC_ARG_WITH(fping_command,
ACX_HELP_STRING([--with-fping-command=PATH],
--
cgit v1.2.3-74-g34f1
From 88683af1da8baae6b252795ab5d85a48e9cd3e63 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle
Date: Wed, 11 Jun 2025 17:09:27 +0200
Subject: Implement autoconf logic for fping version detection
---
configure.ac | 38 ++++++++++++++++++++++++++++++++++++--
1 file changed, 36 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index ae704361..bec50cb4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1523,10 +1523,44 @@ AC_PATH_PROG(PATH_TO_FPING,fping)
AC_ARG_WITH(fping_command,
ACX_HELP_STRING([--with-fping-command=PATH],
[Path to fping command]), PATH_TO_FPING=$withval)
-if test -n "$PATH_TO_FPING"
-then
+if test -n "$PATH_TO_FPING"; then
AC_DEFINE_UNQUOTED(PATH_TO_FPING,"$PATH_TO_FPING",[path to fping])
EXTRAS="$EXTRAS check_fping\$(EXEEXT)"
+
+ if test -z "$($PATH_TO_FPING --version)" ; then
+ AC_MSG_NOTICE([failed to get version of fping])
+ else
+ FPING_MAJOR_VERSION="$($PATH_TO_FPING --version | sed 's/.*fping: Version //' | sed 's/\..*//')"
+ FPING_MINOR_VERSION="$($PATH_TO_FPING --version | sed 's/.*fping: Version //' | sed 's/.*\.//')"
+
+ if test $FPING_MAJOR_VERSION -eq 5 ; then
+ if test $FPING_MINOR_VERSION -ge 3 ; then
+ AC_DEFINE(FPING_VERSION_5_3_OR_HIGHER, "true", [fping is of version 5.3 or higher])
+ AC_MSG_NOTICE([fping is of version 5.3 or higher])
+ AC_DEFINE(FPING_VERSION_5_2_OR_HIGHER, "true", [fping is of version 5.2 or higher])
+ AC_MSG_NOTICE([fping is of version 5.2 or higher])
+ elif test $FPING_MINOR_VERSION -ge 2 ; then
+ AC_DEFINE(FPING_VERSION_5_2_OR_HIGHER, "true", [fping is of version 5.2 or higher])
+ AC_MSG_NOTICE([fping is of version 5.2 or higher])
+ else
+ AC_MSG_NOTICE([fping is of a version lower then 5.2])
+ fi
+
+ elif $FPING_MAJOR_VERSION > 5 ; then
+ AC_DEFINE(FPING_VERSION_5_2_OR_HIGHER, "true", [fping is of version 5.2 or higher])
+ AC_MSG_NOTICE([fping is of version 5.2 or higher])
+ AC_DEFINE(FPING_VERSION_5_3_OR_HIGHER, "true", [fping is of version 5.2 or higher])
+ AC_MSG_NOTICE([fping is of version 5.3 or higher])
+ fi
+
+ if test "`fping --version | sed 's/.*fping: Version //'`" = "5.2" ; then
+ AC_DEFINE(FPING_VERSION, "5.2", [the version of fping available])
+ AC_MSG_NOTICE([fping version: 5.2])
+ elif test "`fping --version | sed 's/.*fping: Version //'`" = "5.3"; then
+ AC_DEFINE(FPING_VERSION, "5.3", [the version of fping available])
+ AC_MSG_NOTICE([fping version: 5.3])
+ fi
+ fi
else
AC_MSG_WARN([Get fping from http://www.fping.com in order to make check_fping plugin])
fi
--
cgit v1.2.3-74-g34f1
From 7247fc656a1f475159b7879cc3c3b798e03c1a33 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle
Date: Thu, 12 Jun 2025 11:13:59 +0200
Subject: Implement new fping options for fping 5.2 and 5.3
fping 5.2 and 5.3 add some new useful command line options
which this commit add to check_fping.
These are:
* --fwmark - sets a firewall mark in the packages to make them
identifiable (fping 5.2)
* --icmp-timestamp - fping uses ICMP timestamp instead of ICMP
Echo (fping 5.2)
* --check-source - fping discards replies which originate not from
the target address (fping 5.2)
The fping release notes describe theses options ( https://github.com/schweikert/fping/releases )
in a little bit more detail.
Currently the help display for those options is only shown
when fping was available in the appropriate version during
compilation.
---
plugins/check_fping.c | 80 +++++++++++++++++++++++++++++++++++++-----
plugins/check_fping.d/config.h | 24 +++++++++++++
2 files changed, 96 insertions(+), 8 deletions(-)
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
index e05056b2..4d328a01 100644
--- a/plugins/check_fping.c
+++ b/plugins/check_fping.c
@@ -117,8 +117,26 @@ int main(int argc, char **argv) {
xasprintf(&option_string, "%s-R ", option_string);
}
+ if (config.fwmark_set) {
+ xasprintf(&option_string, "%s--fwmark %u ", option_string, config.fwmark);
+ }
+
+ if (config.icmp_timestamp) {
+ xasprintf(&option_string, "%s--icmp-timestamp ", option_string);
+ }
+
+ if (config.check_source) {
+ xasprintf(&option_string, "%s--check-source ", option_string);
+ }
+
char *command_line = NULL;
- xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string, config.packet_size, config.packet_count, server);
+
+ if (config.icmp_timestamp) {
+ // no paket size settable for ICMP timestamp
+ 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);
+ }
if (verbose) {
printf("%s\n", command_line);
@@ -275,13 +293,35 @@ mp_state_enum textscan(char *buf, const char *server_name, bool crta_p, double c
/* process command-line arguments */
check_fping_config_wrapper process_arguments(int argc, char **argv) {
- static struct option longopts[] = {
- {"hostname", required_argument, 0, 'H'}, {"sourceip", required_argument, 0, 'S'}, {"sourceif", required_argument, 0, 'I'},
- {"critical", required_argument, 0, 'c'}, {"warning", required_argument, 0, 'w'}, {"alive", no_argument, 0, 'a'},
- {"bytes", required_argument, 0, 'b'}, {"number", required_argument, 0, 'n'}, {"target-timeout", required_argument, 0, 'T'},
- {"interval", required_argument, 0, 'i'}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'},
- {"help", no_argument, 0, 'h'}, {"use-ipv4", no_argument, 0, '4'}, {"use-ipv6", no_argument, 0, '6'},
- {"dontfrag", no_argument, 0, 'M'}, {"random", no_argument, 0, 'R'}, {0, 0, 0, 0}};
+ enum {
+ FWMARK_OPT = CHAR_MAX + 1,
+ ICMP_TIMESTAMP_OPT,
+ CHECK_SOURCE_OPT,
+ };
+ static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
+ {"sourceip", required_argument, 0, 'S'},
+ {"sourceif", required_argument, 0, 'I'},
+ {"critical", required_argument, 0, 'c'},
+ {"warning", required_argument, 0, 'w'},
+ {"alive", no_argument, 0, 'a'},
+ {"bytes", required_argument, 0, 'b'},
+ {"number", required_argument, 0, 'n'},
+ {"target-timeout", required_argument, 0, 'T'},
+ {"interval", required_argument, 0, 'i'},
+ {"verbose", no_argument, 0, 'v'},
+ {"version", no_argument, 0, 'V'},
+ {"help", no_argument, 0, 'h'},
+ {"use-ipv4", no_argument, 0, '4'},
+ {"use-ipv6", no_argument, 0, '6'},
+ {"dontfrag", no_argument, 0, 'M'},
+ {"random", no_argument, 0, 'R'},
+ // only available with fping version >= 5.3
+ {"fwmark", required_argument, NULL, FWMARK_OPT},
+ // only available with fping version >= 5.3
+ {"icmp-timestamp", no_argument, NULL, ICMP_TIMESTAMP_OPT},
+ {"check-source", no_argument, NULL, CHECK_SOURCE_OPT},
+
+ {0, 0, 0, 0}};
char *rv[2];
rv[PL] = NULL;
@@ -409,6 +449,20 @@ check_fping_config_wrapper process_arguments(int argc, char **argv) {
case 'M':
result.config.dontfrag = true;
break;
+ case FWMARK_OPT:
+ if (is_intpos(optarg)) {
+ result.config.fwmark = (unsigned int)atol(optarg);
+ result.config.fwmark_set = true;
+ } else {
+ usage(_("fwmark must be a positive integer"));
+ }
+ break;
+ case ICMP_TIMESTAMP_OPT:
+ result.config.icmp_timestamp = true;
+ break;
+ case CHECK_SOURCE_OPT:
+ result.config.check_source = true;
+ break;
}
}
@@ -496,6 +550,16 @@ void print_help(void) {
printf(" %s\n", _("set the Don't Fragment flag"));
printf(" %s\n", "-R, --random");
printf(" %s\n", _("random packet data (to foil link data compression)"));
+#ifdef FPING_VERSION_5_2_OR_HIGHER
+ printf(" %s\n", "--fwmark=INTEGER");
+ printf(" %s\n", _("set the routing mark to INTEGER (fping option)"));
+# ifdef FPING_VERSION_5_3_OR_HIGHER
+ printf(" %s\n", "--icmp-timestamp");
+ printf(" %s\n", _("use ICMP Timestamp instead of ICMP Echo (fping option)"));
+ printf(" %s\n", "--check-source");
+ printf(" %s\n", _("discard replies not from target address (fping option)"));
+# endif
+#endif
printf(UT_VERBOSE);
printf("\n");
printf(" %s\n", _("THRESHOLD is ,%% where is the round trip average travel time (ms)"));
diff --git a/plugins/check_fping.d/config.h b/plugins/check_fping.d/config.h
index a0697bf3..6d28382a 100644
--- a/plugins/check_fping.d/config.h
+++ b/plugins/check_fping.d/config.h
@@ -29,6 +29,21 @@ typedef struct {
bool cpl_p;
int wpl;
bool wpl_p;
+
+ // only available with fping version >= 5.2
+ // for a given uint _fwmark_ fping sets _fwmark_ as a firewall mark
+ // in the pakets
+ 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
+ bool icmp_timestamp;
+
+ // Setting check_source lets fping discard replies which are not from the target address
+ bool check_source;
} check_fping_config;
check_fping_config check_fping_config_init() {
@@ -53,6 +68,15 @@ check_fping_config check_fping_config_init() {
.cpl_p = false,
.wpl = 0,
.wpl_p = false,
+
+ // only available with fping version >= 5.2
+ .fwmark = 0,
+ .fwmark_set = false, // just to be deterministic
+
+ // only available with fping version >= 5.3
+ .icmp_timestamp = false,
+ .check_source = false,
+
};
return tmp;
}
--
cgit v1.2.3-74-g34f1
From f2c6ce08e3da320d044564352faedd78eb76f1a1 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle
Date: Thu, 12 Jun 2025 11:19:42 +0200
Subject: check_fping: small style improvement
---
plugins/check_fping.c | 4 ++--
plugins/check_fping.d/config.h | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
index 4d328a01..c1e7dd17 100644
--- a/plugins/check_fping.c
+++ b/plugins/check_fping.c
@@ -132,7 +132,7 @@ int main(int argc, char **argv) {
char *command_line = NULL;
if (config.icmp_timestamp) {
- // no paket size settable for 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);
} else {
xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string, config.packet_size, config.packet_count, server);
@@ -346,7 +346,7 @@ check_fping_config_wrapper process_arguments(int argc, char **argv) {
argc--;
}
- while (1) {
+ while (true) {
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) {
diff --git a/plugins/check_fping.d/config.h b/plugins/check_fping.d/config.h
index 6d28382a..d95e9ded 100644
--- a/plugins/check_fping.d/config.h
+++ b/plugins/check_fping.d/config.h
@@ -32,7 +32,7 @@ typedef struct {
// only available with fping version >= 5.2
// for a given uint _fwmark_ fping sets _fwmark_ as a firewall mark
- // in the pakets
+ // in the packets
unsigned int fwmark;
bool fwmark_set;
--
cgit v1.2.3-74-g34f1
From 19f409ac559278cd8623e2d5875818938f648996 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle
Date: Thu, 12 Jun 2025 13:26:55 +0200
Subject: Remove unnecessary newline
---
plugins/check_fping.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
index c1e7dd17..5db6b9aa 100644
--- a/plugins/check_fping.c
+++ b/plugins/check_fping.c
@@ -320,7 +320,6 @@ check_fping_config_wrapper process_arguments(int argc, char **argv) {
// only available with fping version >= 5.3
{"icmp-timestamp", no_argument, NULL, ICMP_TIMESTAMP_OPT},
{"check-source", no_argument, NULL, CHECK_SOURCE_OPT},
-
{0, 0, 0, 0}};
char *rv[2];
--
cgit v1.2.3-74-g34f1
From a669b2531d3b01aeb5b3e39c28bf2e6816fb14af Mon Sep 17 00:00:00 2001
From: Lorenz Kästle
Date: Thu, 12 Jun 2025 13:33:50 +0200
Subject: Remove options if fping version is too low and die directly
---
plugins/check_fping.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
index 5db6b9aa..8018e06d 100644
--- a/plugins/check_fping.c
+++ b/plugins/check_fping.c
@@ -315,11 +315,15 @@ check_fping_config_wrapper process_arguments(int argc, char **argv) {
{"use-ipv6", no_argument, 0, '6'},
{"dontfrag", no_argument, 0, 'M'},
{"random", no_argument, 0, 'R'},
- // only available with fping version >= 5.3
+#ifdef FPING_VERSION_5_2_OR_HIGHER
+ // only available with fping version >= 5.2
{"fwmark", required_argument, NULL, FWMARK_OPT},
+# ifdef FPING_VERSION_5_3_OR_HIGHER
// only available with fping version >= 5.3
{"icmp-timestamp", no_argument, NULL, ICMP_TIMESTAMP_OPT},
{"check-source", no_argument, NULL, CHECK_SOURCE_OPT},
+# endif
+#endif
{0, 0, 0, 0}};
char *rv[2];
--
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(-)
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(-)
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(-)
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 b71cb430cb79e89b5d8bf56990919b6c753cd271 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Thu, 19 Jun 2025 01:15:11 +0200
Subject: Implement flexible state override functions
---
lib/output.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++-------------
lib/output.h | 31 ++++++++++++++++++-----
2 files changed, 90 insertions(+), 24 deletions(-)
diff --git a/lib/output.c b/lib/output.c
index c408a2f5..b398c2ad 100644
--- a/lib/output.c
+++ b/lib/output.c
@@ -16,7 +16,8 @@ static mp_output_format output_format = MP_FORMAT_DEFAULT;
static mp_output_detail_level level_of_detail = MP_DETAIL_ALL;
// == Prototypes ==
-static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation);
+static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check,
+ unsigned int indentation);
static inline cJSON *json_serialize_subcheck(mp_subcheck subcheck);
// == Implementation ==
@@ -58,7 +59,9 @@ static inline char *fmt_subcheck_perfdata(mp_subcheck check) {
* It sets useful defaults
*/
mp_check mp_check_init(void) {
- mp_check check = {0};
+ mp_check check = {
+ .evaluation_function = &mp_eval_check_default,
+ };
return check;
}
@@ -121,7 +124,8 @@ void mp_add_perfdata_to_subcheck(mp_subcheck check[static 1], const mp_perfdata
*/
int mp_add_subcheck_to_subcheck(mp_subcheck check[static 1], mp_subcheck subcheck) {
if (subcheck.output == NULL) {
- die(STATE_UNKNOWN, "%s - %s #%d: %s", __FILE__, __func__, __LINE__, "Sub check output is NULL");
+ die(STATE_UNKNOWN, "%s - %s #%d: %s", __FILE__, __func__, __LINE__,
+ "Sub check output is NULL");
}
mp_subcheck_list *tmp = NULL;
@@ -194,18 +198,30 @@ char *get_subcheck_summary(mp_check check) {
return result;
}
+mp_state_enum mp_compute_subcheck_state(const mp_subcheck subcheck) {
+ if (subcheck.evaluation_function == NULL) {
+ return mp_eval_subcheck_default(subcheck);
+ }
+ return subcheck.evaluation_function(subcheck);
+}
+
/*
- * Generate the result state of a mp_subcheck object based on it's own state and it's subchecks states
+ * Generate the result state of a mp_subcheck object based on its own state and its subchecks
+ * states
*/
-mp_state_enum mp_compute_subcheck_state(const mp_subcheck check) {
- if (check.state_set_explicitly) {
- return check.state;
+mp_state_enum mp_eval_subcheck_default(mp_subcheck subcheck) {
+ if (subcheck.evaluation_function != NULL) {
+ return subcheck.evaluation_function(subcheck);
}
- mp_subcheck_list *scl = check.subchecks;
+ if (subcheck.state_set_explicitly) {
+ return subcheck.state;
+ }
+
+ mp_subcheck_list *scl = subcheck.subchecks;
if (scl == NULL) {
- return check.default_state;
+ return subcheck.default_state;
}
mp_state_enum result = STATE_OK;
@@ -218,10 +234,18 @@ mp_state_enum mp_compute_subcheck_state(const mp_subcheck check) {
return result;
}
+mp_state_enum mp_compute_check_state(const mp_check check) {
+ // just a safety check
+ if (check.evaluation_function == NULL) {
+ return mp_eval_check_default(check);
+ }
+ return check.evaluation_function(check);
+}
+
/*
* Generate the result state of a mp_check object based on it's own state and it's subchecks states
*/
-mp_state_enum mp_compute_check_state(const mp_check check) {
+mp_state_enum mp_eval_check_default(const mp_check check) {
assert(check.subchecks != NULL); // a mp_check without subchecks is invalid, die here
mp_subcheck_list *scl = check.subchecks;
@@ -253,8 +277,10 @@ char *mp_fmt_output(mp_check check) {
mp_subcheck_list *subchecks = check.subchecks;
while (subchecks != NULL) {
- if (level_of_detail == MP_DETAIL_ALL || mp_compute_subcheck_state(subchecks->subcheck) != STATE_OK) {
- asprintf(&result, "%s\n%s", result, fmt_subcheck_output(MP_FORMAT_MULTI_LINE, subchecks->subcheck, 1));
+ if (level_of_detail == MP_DETAIL_ALL ||
+ mp_compute_subcheck_state(subchecks->subcheck) != STATE_OK) {
+ asprintf(&result, "%s\n%s", result,
+ fmt_subcheck_output(MP_FORMAT_MULTI_LINE, subchecks->subcheck, 1));
}
subchecks = subchecks->next;
}
@@ -266,7 +292,8 @@ char *mp_fmt_output(mp_check check) {
if (pd_string == NULL) {
asprintf(&pd_string, "%s", fmt_subcheck_perfdata(subchecks->subcheck));
} else {
- asprintf(&pd_string, "%s %s", pd_string, fmt_subcheck_perfdata(subchecks->subcheck));
+ asprintf(&pd_string, "%s %s", pd_string,
+ fmt_subcheck_perfdata(subchecks->subcheck));
}
subchecks = subchecks->next;
@@ -335,19 +362,21 @@ static char *generate_indentation_string(unsigned int indentation) {
/*
* Helper function to generate the output string of mp_subcheck
*/
-static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation) {
+static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check,
+ unsigned int indentation) {
char *result = NULL;
mp_subcheck_list *subchecks = NULL;
switch (output_format) {
case MP_FORMAT_MULTI_LINE:
- 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;
while (subchecks != NULL) {
- asprintf(&result, "%s\n%s", result, fmt_subcheck_output(output_format, subchecks->subcheck, indentation + 1));
+ asprintf(&result, "%s\n%s", result,
+ fmt_subcheck_output(output_format, subchecks->subcheck, indentation + 1));
subchecks = subchecks->next;
}
return result;
@@ -551,3 +580,23 @@ mp_output_format mp_get_format(void) { return output_format; }
void mp_set_level_of_detail(mp_output_detail_level level) { level_of_detail = level; }
mp_output_detail_level mp_get_level_of_detail(void) { return level_of_detail; }
+
+mp_state_enum mp_eval_ok(mp_check overall) {
+ (void)overall;
+ return STATE_OK;
+}
+
+mp_state_enum mp_eval_warning(mp_check overall) {
+ (void)overall;
+ return STATE_WARNING;
+}
+
+mp_state_enum mp_eval_critical(mp_check overall) {
+ (void)overall;
+ return STATE_CRITICAL;
+}
+
+mp_state_enum mp_eval_unknown(mp_check overall) {
+ (void)overall;
+ return STATE_UNKNOWN;
+}
diff --git a/lib/output.h b/lib/output.h
index 3bd91f90..c63c8e3f 100644
--- a/lib/output.h
+++ b/lib/output.h
@@ -7,15 +7,21 @@
/*
* A partial check result
*/
-typedef struct {
+typedef struct mp_subcheck mp_subcheck;
+struct mp_subcheck {
mp_state_enum state; // OK, Warning, Critical ... set explicitly
mp_state_enum default_state; // OK, Warning, Critical .. if not set explicitly
- bool state_set_explicitly; // was the state set explicitly (or should it be derived from subchecks)
+ bool state_set_explicitly; // was the state set explicitly (or should it be derived from
+ // subchecks)
- char *output; // Text output for humans ("Filesystem xyz is fine", "Could not create TCP connection to..")
- pd_list *perfdata; // Performance data for this check
+ char *output; // Text output for humans ("Filesystem xyz is fine", "Could not create TCP
+ // connection to..")
+ pd_list *perfdata; // Performance data for this check
struct subcheck_list *subchecks; // subchecks deeper in the hierarchy
-} mp_subcheck;
+
+ // the evaluation_functions computes the state of subcheck
+ mp_state_enum (*evaluation_function)(mp_subcheck);
+};
/*
* A list of subchecks, used in subchecks and the main check
@@ -57,10 +63,14 @@ mp_output_detail_level mp_get_level_of_detail(void);
* The final result is always derived from the children and the "worst" state
* in the first layer of subchecks
*/
-typedef struct {
+typedef struct mp_check mp_check;
+struct mp_check {
char *summary; // Overall summary, if not set a summary will be automatically generated
mp_subcheck_list *subchecks;
-} mp_check;
+
+ // the evaluation_functions computes the state of check
+ mp_state_enum (*evaluation_function)(mp_check);
+};
mp_check mp_check_init(void);
mp_subcheck mp_subcheck_init(void);
@@ -78,6 +88,13 @@ void mp_add_summary(mp_check check[static 1], char *summary);
mp_state_enum mp_compute_check_state(mp_check);
mp_state_enum mp_compute_subcheck_state(mp_subcheck);
+mp_state_enum mp_eval_ok(mp_check overall);
+mp_state_enum mp_eval_warning(mp_check overall);
+mp_state_enum mp_eval_critical(mp_check overall);
+mp_state_enum mp_eval_unknown(mp_check overall);
+mp_state_enum mp_eval_check_default(mp_check check);
+mp_state_enum mp_eval_subcheck_default(mp_subcheck subcheck);
+
typedef struct {
bool parsing_success;
mp_output_format output_format;
--
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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
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(-)
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(-)
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(-)
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(-)
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(-)
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(-)
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