mirror of
https://github.com/monitoring-plugins/monitoring-plugins.git
synced 2026-05-28 04:35:40 -04:00
Merge pull request #2125 from RincewindsHat/refactor/check_icmp
Refactor check_icmp: - Far less global variables - Proper IPv6/legacy IP dual stack functionality (allowed mixed v4/v6 hosts) - Improved readability/understandability - General cleanup
This commit is contained in:
commit
b8580c18e3
12 changed files with 1994 additions and 1349 deletions
|
|
@ -4,7 +4,7 @@ TabWidth: 4
|
|||
AllowShortIfStatementsOnASingleLine: false
|
||||
BreakBeforeBraces: Attach
|
||||
AlignConsecutiveMacros: true
|
||||
ColumnLimit: 140
|
||||
ColumnLimit: 100
|
||||
IndentPPDirectives: AfterHash
|
||||
SortIncludes: Never
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
|
|
|
|||
83
lib/output.c
83
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;
|
||||
}
|
||||
|
|
|
|||
31
lib/output.h
31
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;
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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@
|
||||
|
|
@ -89,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:
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
134
plugins-root/check_icmp.d/check_icmp_helpers.c
Normal file
134
plugins-root/check_icmp.d/check_icmp_helpers.c
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
#include "./config.h"
|
||||
#include <math.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#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 = {
|
||||
.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,
|
||||
.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},
|
||||
|
||||
.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,
|
||||
.need_v4 = false,
|
||||
.need_v6 = false,
|
||||
|
||||
.sender_id = 0,
|
||||
|
||||
.mode = MODE_RTA,
|
||||
|
||||
.number_of_targets = 0,
|
||||
.targets = NULL,
|
||||
|
||||
.number_of_hosts = 0,
|
||||
.hosts = NULL,
|
||||
};
|
||||
return tmp;
|
||||
}
|
||||
|
||||
ping_target ping_target_init() {
|
||||
ping_target tmp = {
|
||||
.rtmin = INFINITY,
|
||||
|
||||
.jitter_min = INFINITY,
|
||||
|
||||
.found_out_of_order_packets = false,
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 (((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;
|
||||
}
|
||||
|
||||
/* add the fresh ip */
|
||||
ping_target target = ping_target_init();
|
||||
|
||||
/* fill out the sockaddr_storage struct */
|
||||
target.address = address;
|
||||
|
||||
result.host = target;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
68
plugins-root/check_icmp.d/check_icmp_helpers.h
Normal file
68
plugins-root/check_icmp.d/check_icmp_helpers.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../lib/states.h"
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
typedef struct ping_target {
|
||||
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 */
|
||||
unsigned char icmp_type, icmp_code; /* type and code from errors */
|
||||
unsigned short flags; /* control/status flags */
|
||||
|
||||
double rtmax; /* max rtt */
|
||||
double rtmin; /* min rtt */
|
||||
|
||||
double jitter; /* measured jitter */
|
||||
double jitter_max; /* jitter rtt maximum */
|
||||
double jitter_min; /* jitter rtt minimum */
|
||||
|
||||
time_t last_tdiff;
|
||||
unsigned int last_icmp_seq; /* Last ICMP_SEQ to check out of order pkts */
|
||||
|
||||
bool found_out_of_order_packets;
|
||||
|
||||
struct ping_target *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;
|
||||
} ping_target_create_wrapper;
|
||||
|
||||
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);
|
||||
111
plugins-root/check_icmp.d/config.h
Normal file
111
plugins-root/check_icmp.d/config.h
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../config.h"
|
||||
#include "../../lib/states.h"
|
||||
#include <stddef.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdint.h>
|
||||
#include "./check_icmp_helpers.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 */
|
||||
double jitter; /* jitter time average, microseconds */
|
||||
double mos; /* MOS */
|
||||
double score; /* Score */
|
||||
} check_icmp_threshold;
|
||||
|
||||
/* 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;
|
||||
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;
|
||||
check_icmp_threshold warn;
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
|
||||
check_icmp_execution_mode mode;
|
||||
|
||||
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
|
||||
|
||||
#define DEFAULT_NUMBER_OF_PACKETS 5
|
||||
|
||||
#define PACKET_BACKOFF_FACTOR 1.5
|
||||
#define TARGET_BACKOFF_FACTOR 1.5
|
||||
|
|
@ -12,15 +12,12 @@ 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";
|
||||
}
|
||||
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" );
|
||||
|
|
@ -36,108 +33,85 @@ 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" );
|
||||
like( $res->output, $successOutput, "Output 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" );
|
||||
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"
|
||||
"$sudo ./check_icmp -H $host_nonresponsive -w 100ms,100% -c 100ms,100%"
|
||||
);
|
||||
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%"
|
||||
"$sudo ./check_icmp -w 100ms,100% -c 100ms,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"
|
||||
"$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" );
|
||||
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"
|
||||
"$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" );
|
||||
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"
|
||||
"$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" );
|
||||
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"
|
||||
"$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" );
|
||||
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"
|
||||
"$sudo ./check_icmp -H $host_responsive -R 100,100 -n 1"
|
||||
);
|
||||
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"
|
||||
"$sudo ./check_icmp -H $host_responsive -P 80,90 -n 1"
|
||||
);
|
||||
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"
|
||||
"$sudo ./check_icmp -H $host_responsive -J 80,90"
|
||||
);
|
||||
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"
|
||||
"$sudo ./check_icmp -H $host_responsive -M 4,3"
|
||||
);
|
||||
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"
|
||||
"$sudo ./check_icmp -H $host_responsive -S 80,70"
|
||||
);
|
||||
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"
|
||||
"$sudo ./check_icmp -H $host_responsive -O"
|
||||
);
|
||||
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"
|
||||
"$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" );
|
||||
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" );
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
Loading…
Reference in a new issue