summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-03-12 13:03:17 +0100
committerLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-03-12 13:03:17 +0100
commitae60d6d8d818191afba08819c5a62673b98ef29a (patch)
tree7cc25c7c80b0cc28baaf929e782b242396ecea69 /plugins
parent29c0998cdf0fdb00685df305c0d9e6fcd90eadd6 (diff)
downloadmonitoring-plugins-ae60d6d8d818191afba08819c5a62673b98ef29a.tar.gz
Refactor check_ping
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Makefile.am1
-rw-r--r--plugins/check_ping.c319
-rw-r--r--plugins/check_ping.d/config.h46
3 files changed, 218 insertions, 148 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 9ea6e85e..10a12168 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -63,6 +63,7 @@ EXTRA_DIST = t \
63 check_mrtg.d \ 63 check_mrtg.d \
64 check_apt.d \ 64 check_apt.d \
65 check_pgsql.d \ 65 check_pgsql.d \
66 check_ping.d \
66 check_by_ssh.d \ 67 check_by_ssh.d \
67 check_smtp.d \ 68 check_smtp.d \
68 check_mysql.d \ 69 check_mysql.d \
diff --git a/plugins/check_ping.c b/plugins/check_ping.c
index d79a4a61..fcf68f81 100644
--- a/plugins/check_ping.c
+++ b/plugins/check_ping.c
@@ -36,39 +36,35 @@ const char *email = "devel@monitoring-plugins.org";
36#include "netutils.h" 36#include "netutils.h"
37#include "popen.h" 37#include "popen.h"
38#include "utils.h" 38#include "utils.h"
39#include "check_ping.d/config.h"
40#include "../lib/states.h"
39 41
40#include <signal.h> 42#include <signal.h>
41 43
42#define WARN_DUPLICATES "DUPLICATES FOUND! " 44#define WARN_DUPLICATES "DUPLICATES FOUND! "
43#define UNKNOWN_TRIP_TIME -1.0 /* -1 seconds */
44 45
45enum { 46typedef struct {
46 UNKNOWN_PACKET_LOSS = 200, /* 200% */ 47 int errorcode;
47 DEFAULT_MAX_PACKETS = 5 /* default no. of ICMP ECHO packets */ 48 check_ping_config config;
48}; 49} check_ping_config_wrapper;
50static check_ping_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
51static check_ping_config_wrapper validate_arguments(check_ping_config_wrapper /*config_wrapper*/);
49 52
50static int process_arguments(int /*argc*/, char ** /*argv*/); 53static int get_threshold(char * /*arg*/, double * /*trta*/, int * /*tpl*/);
51static int get_threshold(char * /*arg*/, float * /*trta*/, int * /*tpl*/); 54
52static int validate_arguments(void); 55typedef struct {
53static int run_ping(const char *cmd, const char *addr); 56 mp_state_enum state;
54static int error_scan(char buf[MAX_INPUT_BUFFER], const char *addr); 57 double round_trip_average;
58 int packet_loss;
59} ping_result;
60static ping_result run_ping(const char *cmd, const char *addr, double /*crta*/);
61
62static mp_state_enum error_scan(char buf[MAX_INPUT_BUFFER], const char *addr);
55static void print_help(void); 63static void print_help(void);
56void print_usage(void); 64void print_usage(void);
57 65
58static bool display_html = false;
59static int wpl = UNKNOWN_PACKET_LOSS;
60static int cpl = UNKNOWN_PACKET_LOSS;
61static float wrta = UNKNOWN_TRIP_TIME;
62static float crta = UNKNOWN_TRIP_TIME;
63static char **addresses = NULL;
64static int n_addresses = 0;
65static int max_addr = 1;
66static int max_packets = -1;
67static int verbose = 0; 66static int verbose = 0;
68 67
69static float round_trip_average = UNKNOWN_TRIP_TIME;
70static int packet_loss = UNKNOWN_PACKET_LOSS;
71
72static char *warn_text; 68static char *warn_text;
73 69
74int main(int argc, char **argv) { 70int main(int argc, char **argv) {
@@ -77,16 +73,16 @@ int main(int argc, char **argv) {
77 bindtextdomain(PACKAGE, LOCALEDIR); 73 bindtextdomain(PACKAGE, LOCALEDIR);
78 textdomain(PACKAGE); 74 textdomain(PACKAGE);
79 75
80 addresses = malloc(sizeof(char *) * max_addr);
81 addresses[0] = NULL;
82
83 /* Parse extra opts if any */ 76 /* Parse extra opts if any */
84 argv = np_extra_opts(&argc, argv, progname); 77 argv = np_extra_opts(&argc, argv, progname);
85 78
86 if (process_arguments(argc, argv) == ERROR) { 79 check_ping_config_wrapper tmp_config = process_arguments(argc, argv);
80 if (tmp_config.errorcode == ERROR) {
87 usage4(_("Could not parse arguments")); 81 usage4(_("Could not parse arguments"));
88 } 82 }
89 83
84 const check_ping_config config = tmp_config.config;
85
90 /* Set signal handling and alarm */ 86 /* Set signal handling and alarm */
91 if (signal(SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) { 87 if (signal(SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
92 usage4(_("Cannot catch SIGALRM")); 88 usage4(_("Cannot catch SIGALRM"));
@@ -102,9 +98,9 @@ int main(int argc, char **argv) {
102 98
103 int result = STATE_UNKNOWN; 99 int result = STATE_UNKNOWN;
104 char *rawcmd = NULL; 100 char *rawcmd = NULL;
105 for (int i = 0; i < n_addresses; i++) { 101 for (size_t i = 0; i < config.n_addresses; i++) {
106#ifdef PING6_COMMAND 102#ifdef PING6_COMMAND
107 if (address_family != AF_INET && is_inet6_addr(addresses[i])) { 103 if (address_family != AF_INET && is_inet6_addr(config.addresses[i])) {
108 rawcmd = strdup(PING6_COMMAND); 104 rawcmd = strdup(PING6_COMMAND);
109 } else { 105 } else {
110 rawcmd = strdup(PING_COMMAND); 106 rawcmd = strdup(PING_COMMAND);
@@ -118,12 +114,12 @@ int main(int argc, char **argv) {
118 /* does the host address of number of packets argument come first? */ 114 /* does the host address of number of packets argument come first? */
119#ifdef PING_PACKETS_FIRST 115#ifdef PING_PACKETS_FIRST
120# ifdef PING_HAS_TIMEOUT 116# ifdef PING_HAS_TIMEOUT
121 xasprintf(&cmd, rawcmd, timeout_interval, max_packets, addresses[i]); 117 xasprintf(&cmd, rawcmd, timeout_interval, config.max_packets, config.addresses[i]);
122# else 118# else
123 xasprintf(&cmd, rawcmd, max_packets, addresses[i]); 119 xasprintf(&cmd, rawcmd, config.max_packets, addresses[i]);
124# endif 120# endif
125#else 121#else
126 xasprintf(&cmd, rawcmd, addresses[i], max_packets); 122 xasprintf(&cmd, rawcmd, addresses[i], config.max_packets);
127#endif 123#endif
128 124
129 if (verbose >= 2) { 125 if (verbose >= 2) {
@@ -131,53 +127,55 @@ int main(int argc, char **argv) {
131 } 127 }
132 128
133 /* run the command */ 129 /* run the command */
134 int this_result = run_ping(cmd, addresses[i]);
135 130
136 if (packet_loss == UNKNOWN_PACKET_LOSS || round_trip_average < 0.0) { 131 ping_result pinged = run_ping(cmd, config.addresses[i], config.crta);
132
133 if (pinged.packet_loss == UNKNOWN_PACKET_LOSS || pinged.round_trip_average < 0.0) {
137 printf("%s\n", cmd); 134 printf("%s\n", cmd);
138 die(STATE_UNKNOWN, _("CRITICAL - Could not interpret output from ping command\n")); 135 die(STATE_UNKNOWN, _("CRITICAL - Could not interpret output from ping command\n"));
139 } 136 }
140 137
141 if (packet_loss >= cpl || round_trip_average >= crta || round_trip_average < 0) { 138 if (pinged.packet_loss >= config.cpl || pinged.round_trip_average >= config.crta || pinged.round_trip_average < 0) {
142 this_result = STATE_CRITICAL; 139 pinged.state = STATE_CRITICAL;
143 } else if (packet_loss >= wpl || round_trip_average >= wrta) { 140 } else if (pinged.packet_loss >= config.wpl || pinged.round_trip_average >= config.wrta) {
144 this_result = STATE_WARNING; 141 pinged.state = STATE_WARNING;
145 } else if (packet_loss >= 0 && round_trip_average >= 0) { 142 } else if (pinged.packet_loss >= 0 && pinged.round_trip_average >= 0) {
146 this_result = max_state(STATE_OK, this_result); 143 pinged.state = max_state(STATE_OK, pinged.state);
147 } 144 }
148 145
149 if (n_addresses > 1 && this_result != STATE_UNKNOWN) { 146 if (config.n_addresses > 1 && pinged.state != STATE_UNKNOWN) {
150 die(STATE_OK, "%s is alive\n", addresses[i]); 147 die(STATE_OK, "%s is alive\n", config.addresses[i]);
151 } 148 }
152 149
153 if (display_html) { 150 if (config.display_html) {
154 printf("<A HREF='%s/traceroute.cgi?%s'>", CGIURL, addresses[i]); 151 printf("<A HREF='%s/traceroute.cgi?%s'>", CGIURL, config.addresses[i]);
155 } 152 }
156 if (packet_loss == 100) { 153 if (pinged.packet_loss == 100) {
157 printf(_("PING %s - %sPacket loss = %d%%"), state_text(this_result), warn_text, packet_loss); 154 printf(_("PING %s - %sPacket loss = %d%%"), state_text(pinged.state), warn_text, pinged.packet_loss);
158 } else { 155 } else {
159 printf(_("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms"), state_text(this_result), warn_text, packet_loss, 156 printf(_("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms"), state_text(pinged.state), warn_text, pinged.packet_loss,
160 round_trip_average); 157 pinged.round_trip_average);
161 } 158 }
162 if (display_html) { 159 if (config.display_html) {
163 printf("</A>"); 160 printf("</A>");
164 } 161 }
165 162
166 /* Print performance data */ 163 /* Print performance data */
167 if (packet_loss != 100) { 164 if (pinged.packet_loss != 100) {
168 printf("|%s", 165 printf("|%s", fperfdata("rta", pinged.round_trip_average, "ms", (bool)(config.wrta > 0), config.wrta,
169 fperfdata("rta", (double)round_trip_average, "ms", (bool)(wrta > 0), wrta, (bool)(crta > 0), crta, true, 0, false, 0)); 166 (bool)(config.crta > 0), config.crta, true, 0, false, 0));
170 } else { 167 } else {
171 printf("| rta=U;%f;%f;;", wrta, crta); 168 printf("| rta=U;%f;%f;;", config.wrta, config.crta);
172 } 169 }
173 170
174 printf(" %s\n", perfdata("pl", (long)packet_loss, "%", (bool)(wpl > 0), wpl, (bool)(cpl > 0), cpl, true, 0, false, 0)); 171 printf(" %s\n", perfdata("pl", (long)pinged.packet_loss, "%", (bool)(config.wpl > 0), config.wpl, (bool)(config.cpl > 0),
172 config.cpl, true, 0, false, 0));
175 173
176 if (verbose >= 2) { 174 if (verbose >= 2) {
177 printf("%f:%d%% %f:%d%%\n", wrta, wpl, crta, cpl); 175 printf("%f:%d%% %f:%d%%\n", config.wrta, config.wpl, config.crta, config.cpl);
178 } 176 }
179 177
180 result = max_state(result, this_result); 178 result = max_state(result, pinged.state);
181 free(rawcmd); 179 free(rawcmd);
182 free(cmd); 180 free(cmd);
183 } 181 }
@@ -186,7 +184,7 @@ int main(int argc, char **argv) {
186} 184}
187 185
188/* process command-line arguments */ 186/* process command-line arguments */
189int process_arguments(int argc, char **argv) { 187check_ping_config_wrapper process_arguments(int argc, char **argv) {
190 static struct option longopts[] = {STD_LONG_OPTS, 188 static struct option longopts[] = {STD_LONG_OPTS,
191 {"packets", required_argument, 0, 'p'}, 189 {"packets", required_argument, 0, 'p'},
192 {"nohtml", no_argument, 0, 'n'}, 190 {"nohtml", no_argument, 0, 'n'},
@@ -195,8 +193,14 @@ int process_arguments(int argc, char **argv) {
195 {"use-ipv6", no_argument, 0, '6'}, 193 {"use-ipv6", no_argument, 0, '6'},
196 {0, 0, 0, 0}}; 194 {0, 0, 0, 0}};
197 195
196 check_ping_config_wrapper result = {
197 .errorcode = OK,
198 .config = check_ping_config_init(),
199 };
200
198 if (argc < 2) { 201 if (argc < 2) {
199 return ERROR; 202 result.errorcode = ERROR;
203 return result;
200 } 204 }
201 205
202 for (int index = 1; index < argc; index++) { 206 for (int index = 1; index < argc; index++) {
@@ -209,6 +213,7 @@ int process_arguments(int argc, char **argv) {
209 } 213 }
210 214
211 int option = 0; 215 int option = 0;
216 size_t max_addr = MAX_ADDR_START;
212 while (true) { 217 while (true) {
213 int option_index = getopt_long(argc, argv, "VvhnL46t:c:w:H:p:", longopts, &option); 218 int option_index = getopt_long(argc, argv, "VvhnL46t:c:w:H:p:", longopts, &option);
214 219
@@ -246,15 +251,15 @@ int process_arguments(int argc, char **argv) {
246 case 'H': /* hostname */ { 251 case 'H': /* hostname */ {
247 char *ptr = optarg; 252 char *ptr = optarg;
248 while (true) { 253 while (true) {
249 n_addresses++; 254 result.config.n_addresses++;
250 if (n_addresses > max_addr) { 255 if (result.config.n_addresses > max_addr) {
251 max_addr *= 2; 256 max_addr *= 2;
252 addresses = realloc(addresses, sizeof(char *) * max_addr); 257 result.config.addresses = realloc(result.config.addresses, sizeof(char *) * max_addr);
253 if (addresses == NULL) { 258 if (result.config.addresses == NULL) {
254 die(STATE_UNKNOWN, _("Could not realloc() addresses\n")); 259 die(STATE_UNKNOWN, _("Could not realloc() addresses\n"));
255 } 260 }
256 } 261 }
257 addresses[n_addresses - 1] = ptr; 262 result.config.addresses[result.config.n_addresses - 1] = ptr;
258 if ((ptr = index(ptr, ','))) { 263 if ((ptr = index(ptr, ','))) {
259 strcpy(ptr, ""); 264 strcpy(ptr, "");
260 ptr += sizeof(char); 265 ptr += sizeof(char);
@@ -265,105 +270,110 @@ int process_arguments(int argc, char **argv) {
265 } break; 270 } break;
266 case 'p': /* number of packets to send */ 271 case 'p': /* number of packets to send */
267 if (is_intnonneg(optarg)) { 272 if (is_intnonneg(optarg)) {
268 max_packets = atoi(optarg); 273 result.config.max_packets = atoi(optarg);
269 } else { 274 } else {
270 usage2(_("<max_packets> (%s) must be a non-negative number\n"), optarg); 275 usage2(_("<max_packets> (%s) must be a non-negative number\n"), optarg);
271 } 276 }
272 break; 277 break;
273 case 'n': /* no HTML */ 278 case 'n': /* no HTML */
274 display_html = false; 279 result.config.display_html = false;
275 break; 280 break;
276 case 'L': /* show HTML */ 281 case 'L': /* show HTML */
277 display_html = true; 282 result.config.display_html = true;
278 break; 283 break;
279 case 'c': 284 case 'c':
280 get_threshold(optarg, &crta, &cpl); 285 get_threshold(optarg, &result.config.crta, &result.config.cpl);
281 break; 286 break;
282 case 'w': 287 case 'w':
283 get_threshold(optarg, &wrta, &wpl); 288 get_threshold(optarg, &result.config.wrta, &result.config.wpl);
284 break; 289 break;
285 } 290 }
286 } 291 }
287 292
288 int arg_counter = optind; 293 int arg_counter = optind;
289 if (arg_counter == argc) { 294 if (arg_counter == argc) {
290 return validate_arguments(); 295 return validate_arguments(result);
291 } 296 }
292 297
293 if (addresses[0] == NULL) { 298 if (result.config.addresses[0] == NULL) {
294 if (!is_host(argv[arg_counter])) { 299 if (!is_host(argv[arg_counter])) {
295 usage2(_("Invalid hostname/address"), argv[arg_counter]); 300 usage2(_("Invalid hostname/address"), argv[arg_counter]);
296 } else { 301 } else {
297 addresses[0] = argv[arg_counter++]; 302 result.config.addresses[0] = argv[arg_counter++];
298 n_addresses++; 303 result.config.n_addresses++;
299 if (arg_counter == argc) { 304 if (arg_counter == argc) {
300 return validate_arguments(); 305 return validate_arguments(result);
301 } 306 }
302 } 307 }
303 } 308 }
304 309
305 if (wpl == UNKNOWN_PACKET_LOSS) { 310 if (result.config.wpl == UNKNOWN_PACKET_LOSS) {
306 if (!is_intpercent(argv[arg_counter])) { 311 if (!is_intpercent(argv[arg_counter])) {
307 printf(_("<wpl> (%s) must be an integer percentage\n"), argv[arg_counter]); 312 printf(_("<wpl> (%s) must be an integer percentage\n"), argv[arg_counter]);
308 return ERROR; 313 result.errorcode = ERROR;
314 return result;
309 } 315 }
310 wpl = atoi(argv[arg_counter++]); 316 result.config.wpl = atoi(argv[arg_counter++]);
311 if (arg_counter == argc) { 317 if (arg_counter == argc) {
312 return validate_arguments(); 318 return validate_arguments(result);
313 } 319 }
314 } 320 }
315 321
316 if (cpl == UNKNOWN_PACKET_LOSS) { 322 if (result.config.cpl == UNKNOWN_PACKET_LOSS) {
317 if (!is_intpercent(argv[arg_counter])) { 323 if (!is_intpercent(argv[arg_counter])) {
318 printf(_("<cpl> (%s) must be an integer percentage\n"), argv[arg_counter]); 324 printf(_("<cpl> (%s) must be an integer percentage\n"), argv[arg_counter]);
319 return ERROR; 325 result.errorcode = ERROR;
326 return result;
320 } 327 }
321 cpl = atoi(argv[arg_counter++]); 328 result.config.cpl = atoi(argv[arg_counter++]);
322 if (arg_counter == argc) { 329 if (arg_counter == argc) {
323 return validate_arguments(); 330 return validate_arguments(result);
324 } 331 }
325 } 332 }
326 333
327 if (wrta < 0.0) { 334 if (result.config.wrta < 0.0) {
328 if (is_negative(argv[arg_counter])) { 335 if (is_negative(argv[arg_counter])) {
329 printf(_("<wrta> (%s) must be a non-negative number\n"), argv[arg_counter]); 336 printf(_("<wrta> (%s) must be a non-negative number\n"), argv[arg_counter]);
330 return ERROR; 337 result.errorcode = ERROR;
338 return result;
331 } 339 }
332 wrta = atof(argv[arg_counter++]); 340 result.config.wrta = atof(argv[arg_counter++]);
333 if (arg_counter == argc) { 341 if (arg_counter == argc) {
334 return validate_arguments(); 342 return validate_arguments(result);
335 } 343 }
336 } 344 }
337 345
338 if (crta < 0.0) { 346 if (result.config.crta < 0.0) {
339 if (is_negative(argv[arg_counter])) { 347 if (is_negative(argv[arg_counter])) {
340 printf(_("<crta> (%s) must be a non-negative number\n"), argv[arg_counter]); 348 printf(_("<crta> (%s) must be a non-negative number\n"), argv[arg_counter]);
341 return ERROR; 349 result.errorcode = ERROR;
350 return result;
342 } 351 }
343 crta = atof(argv[arg_counter++]); 352 result.config.crta = atof(argv[arg_counter++]);
344 if (arg_counter == argc) { 353 if (arg_counter == argc) {
345 return validate_arguments(); 354 return validate_arguments(result);
346 } 355 }
347 } 356 }
348 357
349 if (max_packets == -1) { 358 if (result.config.max_packets == -1) {
350 if (is_intnonneg(argv[arg_counter])) { 359 if (is_intnonneg(argv[arg_counter])) {
351 max_packets = atoi(argv[arg_counter++]); 360 result.config.max_packets = atoi(argv[arg_counter++]);
352 } else { 361 } else {
353 printf(_("<max_packets> (%s) must be a non-negative number\n"), argv[arg_counter]); 362 printf(_("<max_packets> (%s) must be a non-negative number\n"), argv[arg_counter]);
354 return ERROR; 363 result.errorcode = ERROR;
364 return result;
355 } 365 }
356 } 366 }
357 367
358 return validate_arguments(); 368 return validate_arguments(result);
359} 369}
360 370
361int get_threshold(char *arg, float *trta, int *tpl) { 371int get_threshold(char *arg, double *trta, int *tpl) {
362 if (is_intnonneg(arg) && sscanf(arg, "%f", trta) == 1) { 372 if (is_intnonneg(arg) && sscanf(arg, "%lf", trta) == 1) {
363 return OK; 373 return OK;
364 } 374 }
365 375
366 if (strpbrk(arg, ",:") && strstr(arg, "%") && sscanf(arg, "%f%*[:,]%d%%", trta, tpl) == 2) { 376 if (strpbrk(arg, ",:") && strstr(arg, "%") && sscanf(arg, "%lf%*[:,]%d%%", trta, tpl) == 2) {
367 return OK; 377 return OK;
368 } 378 }
369 379
@@ -375,60 +385,66 @@ int get_threshold(char *arg, float *trta, int *tpl) {
375 return STATE_UNKNOWN; 385 return STATE_UNKNOWN;
376} 386}
377 387
378int validate_arguments() { 388check_ping_config_wrapper validate_arguments(check_ping_config_wrapper config_wrapper) {
379 if (wrta < 0.0) { 389 if (config_wrapper.config.wrta < 0.0) {
380 printf(_("<wrta> was not set\n")); 390 printf(_("<wrta> was not set\n"));
381 return ERROR; 391 config_wrapper.errorcode = ERROR;
392 return config_wrapper;
382 } 393 }
383 394
384 if (crta < 0.0) { 395 if (config_wrapper.config.crta < 0.0) {
385 printf(_("<crta> was not set\n")); 396 printf(_("<crta> was not set\n"));
386 return ERROR; 397 config_wrapper.errorcode = ERROR;
398 return config_wrapper;
387 } 399 }
388 400
389 if (wpl == UNKNOWN_PACKET_LOSS) { 401 if (config_wrapper.config.wpl == UNKNOWN_PACKET_LOSS) {
390 printf(_("<wpl> was not set\n")); 402 printf(_("<wpl> was not set\n"));
391 return ERROR; 403 config_wrapper.errorcode = ERROR;
404 return config_wrapper;
392 } 405 }
393 406
394 if (cpl == UNKNOWN_PACKET_LOSS) { 407 if (config_wrapper.config.cpl == UNKNOWN_PACKET_LOSS) {
395 printf(_("<cpl> was not set\n")); 408 printf(_("<cpl> was not set\n"));
396 return ERROR; 409 config_wrapper.errorcode = ERROR;
410 return config_wrapper;
397 } 411 }
398 412
399 if (wrta > crta) { 413 if (config_wrapper.config.wrta > config_wrapper.config.crta) {
400 printf(_("<wrta> (%f) cannot be larger than <crta> (%f)\n"), wrta, crta); 414 printf(_("<wrta> (%f) cannot be larger than <crta> (%f)\n"), config_wrapper.config.wrta, config_wrapper.config.crta);
401 return ERROR; 415 config_wrapper.errorcode = ERROR;
416 return config_wrapper;
402 } 417 }
403 418
404 if (wpl > cpl) { 419 if (config_wrapper.config.wpl > config_wrapper.config.cpl) {
405 printf(_("<wpl> (%d) cannot be larger than <cpl> (%d)\n"), wpl, cpl); 420 printf(_("<wpl> (%d) cannot be larger than <cpl> (%d)\n"), config_wrapper.config.wpl, config_wrapper.config.cpl);
406 return ERROR; 421 config_wrapper.errorcode = ERROR;
422 return config_wrapper;
407 } 423 }
408 424
409 if (max_packets == -1) { 425 if (config_wrapper.config.max_packets == -1) {
410 max_packets = DEFAULT_MAX_PACKETS; 426 config_wrapper.config.max_packets = DEFAULT_MAX_PACKETS;
411 } 427 }
412 428
413 float max_seconds = (crta / 1000.0 * max_packets) + max_packets; 429 double max_seconds = (config_wrapper.config.crta / 1000.0 * config_wrapper.config.max_packets) + config_wrapper.config.max_packets;
414 if (max_seconds > timeout_interval) { 430 if (max_seconds > timeout_interval) {
415 timeout_interval = (unsigned int)max_seconds; 431 timeout_interval = (unsigned int)max_seconds;
416 } 432 }
417 433
418 for (int i = 0; i < n_addresses; i++) { 434 for (size_t i = 0; i < config_wrapper.config.n_addresses; i++) {
419 if (!is_host(addresses[i])) { 435 if (!is_host(config_wrapper.config.addresses[i])) {
420 usage2(_("Invalid hostname/address"), addresses[i]); 436 usage2(_("Invalid hostname/address"), config_wrapper.config.addresses[i]);
421 } 437 }
422 } 438 }
423 439
424 if (n_addresses == 0) { 440 if (config_wrapper.config.n_addresses == 0) {
425 usage(_("You must specify a server address or host name")); 441 usage(_("You must specify a server address or host name"));
426 } 442 }
427 443
428 return OK; 444 return config_wrapper;
429} 445}
430 446
431int run_ping(const char *cmd, const char *addr) { 447ping_result run_ping(const char *cmd, const char *addr, double crta) {
432 if ((child_process = spopen(cmd)) == NULL) { 448 if ((child_process = spopen(cmd)) == NULL) {
433 die(STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd); 449 die(STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd);
434 } 450 }
@@ -439,48 +455,55 @@ int run_ping(const char *cmd, const char *addr) {
439 } 455 }
440 456
441 char buf[MAX_INPUT_BUFFER]; 457 char buf[MAX_INPUT_BUFFER];
442 int result = STATE_UNKNOWN; 458 ping_result result = {
459 .state = STATE_UNKNOWN,
460 .packet_loss = UNKNOWN_PACKET_LOSS,
461 .round_trip_average = UNKNOWN_TRIP_TIME,
462 };
463
443 while (fgets(buf, MAX_INPUT_BUFFER - 1, child_process)) { 464 while (fgets(buf, MAX_INPUT_BUFFER - 1, child_process)) {
444 if (verbose >= 3) { 465 if (verbose >= 3) {
445 printf("Output: %s", buf); 466 printf("Output: %s", buf);
446 } 467 }
447 468
448 result = max_state(result, error_scan(buf, addr)); 469 result.state = max_state(result.state, error_scan(buf, addr));
449 470
450 /* get the percent loss statistics */ 471 /* get the percent loss statistics */
451 int match = 0; 472 int match = 0;
452 if ((sscanf(buf, "%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss%n", &packet_loss, &match) && 473 if ((sscanf(buf, "%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss%n", &result.packet_loss, &match) &&
474 match) ||
475 (sscanf(buf, "%*d packets transmitted, %*d packets received, +%*d duplicates, %d%% packet loss%n", &result.packet_loss,
476 &match) &&
453 match) || 477 match) ||
454 (sscanf(buf, "%*d packets transmitted, %*d packets received, +%*d duplicates, %d%% packet loss%n", &packet_loss, &match) && 478 (sscanf(buf, "%*d packets transmitted, %*d received, +%*d duplicates, %d%% packet loss%n", &result.packet_loss, &match) &&
455 match) || 479 match) ||
456 (sscanf(buf, "%*d packets transmitted, %*d received, +%*d duplicates, %d%% packet loss%n", &packet_loss, &match) && match) || 480 (sscanf(buf, "%*d packets transmitted, %*d packets received, %d%% packet loss%n", &result.packet_loss, &match) && match) ||
457 (sscanf(buf, "%*d packets transmitted, %*d packets received, %d%% packet loss%n", &packet_loss, &match) && match) || 481 (sscanf(buf, "%*d packets transmitted, %*d packets received, %d%% loss, time%n", &result.packet_loss, &match) && match) ||
458 (sscanf(buf, "%*d packets transmitted, %*d packets received, %d%% loss, time%n", &packet_loss, &match) && match) || 482 (sscanf(buf, "%*d packets transmitted, %*d received, %d%% loss, time%n", &result.packet_loss, &match) && match) ||
459 (sscanf(buf, "%*d packets transmitted, %*d received, %d%% loss, time%n", &packet_loss, &match) && match) || 483 (sscanf(buf, "%*d packets transmitted, %*d received, %d%% packet loss, time%n", &result.packet_loss, &match) && match) ||
460 (sscanf(buf, "%*d packets transmitted, %*d received, %d%% packet loss, time%n", &packet_loss, &match) && match) || 484 (sscanf(buf, "%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss%n", &result.packet_loss, &match) && match) ||
461 (sscanf(buf, "%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss%n", &packet_loss, &match) && match) || 485 (sscanf(buf, "%*d packets transmitted %*d received, +%*d errors, %d%% packet loss%n", &result.packet_loss, &match) && match) ||
462 (sscanf(buf, "%*d packets transmitted %*d received, +%*d errors, %d%% packet loss%n", &packet_loss, &match) && match) || 486 (sscanf(buf, "%*[^(](%d%% %*[^)])%n", &result.packet_loss, &match) && match)) {
463 (sscanf(buf, "%*[^(](%d%% %*[^)])%n", &packet_loss, &match) && match)) {
464 continue; 487 continue;
465 } 488 }
466 489
467 /* get the round trip average */ 490 /* get the round trip average */
468 if ((sscanf(buf, "round-trip min/avg/max = %*f/%f/%*f%n", &round_trip_average, &match) && match) || 491 if ((sscanf(buf, "round-trip min/avg/max = %*f/%lf/%*f%n", &result.round_trip_average, &match) && match) ||
469 (sscanf(buf, "round-trip min/avg/max/mdev = %*f/%f/%*f/%*f%n", &round_trip_average, &match) && match) || 492 (sscanf(buf, "round-trip min/avg/max/mdev = %*f/%lf/%*f/%*f%n", &result.round_trip_average, &match) && match) ||
470 (sscanf(buf, "round-trip min/avg/max/sdev = %*f/%f/%*f/%*f%n", &round_trip_average, &match) && match) || 493 (sscanf(buf, "round-trip min/avg/max/sdev = %*f/%lf/%*f/%*f%n", &result.round_trip_average, &match) && match) ||
471 (sscanf(buf, "round-trip min/avg/max/stddev = %*f/%f/%*f/%*f%n", &round_trip_average, &match) && match) || 494 (sscanf(buf, "round-trip min/avg/max/stddev = %*f/%lf/%*f/%*f%n", &result.round_trip_average, &match) && match) ||
472 (sscanf(buf, "round-trip min/avg/max/std-dev = %*f/%f/%*f/%*f%n", &round_trip_average, &match) && match) || 495 (sscanf(buf, "round-trip min/avg/max/std-dev = %*f/%lf/%*f/%*f%n", &result.round_trip_average, &match) && match) ||
473 (sscanf(buf, "round-trip (ms) min/avg/max = %*f/%f/%*f%n", &round_trip_average, &match) && match) || 496 (sscanf(buf, "round-trip (ms) min/avg/max = %*f/%lf/%*f%n", &result.round_trip_average, &match) && match) ||
474 (sscanf(buf, "round-trip (ms) min/avg/max/stddev = %*f/%f/%*f/%*f%n", &round_trip_average, &match) && match) || 497 (sscanf(buf, "round-trip (ms) min/avg/max/stddev = %*f/%lf/%*f/%*f%n", &result.round_trip_average, &match) && match) ||
475 (sscanf(buf, "rtt min/avg/max/mdev = %*f/%f/%*f/%*f ms%n", &round_trip_average, &match) && match) || 498 (sscanf(buf, "rtt min/avg/max/mdev = %*f/%lf/%*f/%*f ms%n", &result.round_trip_average, &match) && match) ||
476 (sscanf(buf, "%*[^=] = %*fms, %*[^=] = %*fms, %*[^=] = %fms%n", &round_trip_average, &match) && match)) { 499 (sscanf(buf, "%*[^=] = %*fms, %*[^=] = %*fms, %*[^=] = %lfms%n", &result.round_trip_average, &match) && match)) {
477 continue; 500 continue;
478 } 501 }
479 } 502 }
480 503
481 /* this is needed because there is no rta if all packets are lost */ 504 /* this is needed because there is no rta if all packets are lost */
482 if (packet_loss == 100) { 505 if (result.packet_loss == 100) {
483 round_trip_average = crta; 506 result.round_trip_average = crta;
484 } 507 }
485 508
486 /* check stderr, setting at least WARNING if there is output here */ 509 /* check stderr, setting at least WARNING if there is output here */
@@ -492,8 +515,8 @@ int run_ping(const char *cmd, const char *addr) {
492 if (verbose >= 3) { 515 if (verbose >= 3) {
493 printf("Got stderr: %s", buf); 516 printf("Got stderr: %s", buf);
494 } 517 }
495 if ((result = error_scan(buf, addr)) == STATE_OK) { 518 if ((result.state = error_scan(buf, addr)) == STATE_OK) {
496 result = STATE_WARNING; 519 result.state = STATE_WARNING;
497 if (warn_text == NULL) { 520 if (warn_text == NULL) {
498 warn_text = strdup(_("System call sent warnings to stderr ")); 521 warn_text = strdup(_("System call sent warnings to stderr "));
499 } else { 522 } else {
@@ -514,7 +537,7 @@ int run_ping(const char *cmd, const char *addr) {
514 return result; 537 return result;
515} 538}
516 539
517int error_scan(char buf[MAX_INPUT_BUFFER], const char *addr) { 540mp_state_enum error_scan(char buf[MAX_INPUT_BUFFER], const char *addr) {
518 if (strstr(buf, "Network is unreachable") || strstr(buf, "Destination Net Unreachable") || strstr(buf, "No route")) { 541 if (strstr(buf, "Network is unreachable") || strstr(buf, "Destination Net Unreachable") || strstr(buf, "No route")) {
519 die(STATE_CRITICAL, _("CRITICAL - Network Unreachable (%s)\n"), addr); 542 die(STATE_CRITICAL, _("CRITICAL - Network Unreachable (%s)\n"), addr);
520 } else if (strstr(buf, "Destination Host Unreachable") || strstr(buf, "Address unreachable")) { 543 } else if (strstr(buf, "Destination Host Unreachable") || strstr(buf, "Address unreachable")) {
@@ -543,10 +566,10 @@ int error_scan(char buf[MAX_INPUT_BUFFER], const char *addr) {
543 } else if (!strstr(warn_text, _(WARN_DUPLICATES)) && xasprintf(&warn_text, "%s %s", warn_text, _(WARN_DUPLICATES)) == -1) { 566 } else if (!strstr(warn_text, _(WARN_DUPLICATES)) && xasprintf(&warn_text, "%s %s", warn_text, _(WARN_DUPLICATES)) == -1) {
544 die(STATE_UNKNOWN, _("Unable to realloc warn_text\n")); 567 die(STATE_UNKNOWN, _("Unable to realloc warn_text\n"));
545 } 568 }
546 return (STATE_WARNING); 569 return STATE_WARNING;
547 } 570 }
548 571
549 return (STATE_OK); 572 return STATE_OK;
550} 573}
551 574
552void print_help(void) { 575void print_help(void) {
diff --git a/plugins/check_ping.d/config.h b/plugins/check_ping.d/config.h
new file mode 100644
index 00000000..eb2735a7
--- /dev/null
+++ b/plugins/check_ping.d/config.h
@@ -0,0 +1,46 @@
1#pragma once
2
3#include "../../config.h"
4#include <stddef.h>
5#include <stdlib.h>
6
7enum {
8 UNKNOWN_PACKET_LOSS = 200, /* 200% */
9 DEFAULT_MAX_PACKETS = 5 /* default no. of ICMP ECHO packets */
10};
11
12#define UNKNOWN_TRIP_TIME -1.0 /* -1 seconds */
13
14#define MAX_ADDR_START 1
15
16typedef struct {
17 bool display_html;
18 int max_packets;
19
20 char **addresses;
21 size_t n_addresses;
22
23 int wpl;
24 int cpl;
25 double wrta;
26 double crta;
27} check_ping_config;
28
29check_ping_config check_ping_config_init() {
30 check_ping_config tmp = {
31 .display_html = false,
32 .max_packets = -1,
33
34 .addresses = NULL,
35 .n_addresses = 0,
36
37 .wpl = UNKNOWN_PACKET_LOSS,
38 .cpl = UNKNOWN_PACKET_LOSS,
39 .wrta = UNKNOWN_TRIP_TIME,
40 .crta = UNKNOWN_TRIP_TIME,
41 };
42
43 tmp.addresses = calloc(MAX_ADDR_START, sizeof(char *));
44 tmp.addresses[0] = NULL;
45 return tmp;
46}