summaryrefslogtreecommitdiffstats
path: root/plugins/check_fping.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_fping.c')
-rw-r--r--plugins/check_fping.c168
1 files changed, 127 insertions, 41 deletions
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
index ec7abb67..6160c2cb 100644
--- a/plugins/check_fping.c
+++ b/plugins/check_fping.c
@@ -46,8 +46,9 @@ enum {
46 RTA = 1 46 RTA = 1
47}; 47};
48 48
49static mp_state_enum textscan(char *buf, const char * /*server_name*/, bool /*crta_p*/, double /*crta*/, bool /*wrta_p*/, double /*wrta*/, 49static mp_state_enum textscan(char *buf, const char * /*server_name*/, bool /*crta_p*/,
50 bool /*cpl_p*/, int /*cpl*/, bool /*wpl_p*/, int /*wpl*/, bool /*alive_p*/); 50 double /*crta*/, bool /*wrta_p*/, double /*wrta*/, bool /*cpl_p*/,
51 int /*cpl*/, bool /*wpl_p*/, int /*wpl*/, bool /*alive_p*/);
51 52
52typedef struct { 53typedef struct {
53 int errorcode; 54 int errorcode;
@@ -79,6 +80,24 @@ int main(int argc, char **argv) {
79 server = strscpy(server, config.server_name); 80 server = strscpy(server, config.server_name);
80 81
81 char *option_string = ""; 82 char *option_string = "";
83 char *fping_prog = NULL;
84
85 /* First determine if the target is dualstack or ipv6 only. */
86 bool server_is_inet6_addr = is_inet6_addr(server);
87
88 /*
89 * If the user requested -6 OR the user made no assertion and the address is v6 or dualstack
90 * -> we use ipv6
91 * If the user requested -4 OR the user made no assertion and the address is v4 ONLY
92 * -> we use ipv4
93 */
94 if (address_family == AF_INET6 || (address_family == AF_UNSPEC && server_is_inet6_addr)) {
95 xasprintf(&option_string, "%s-6 ", option_string);
96 } else {
97 xasprintf(&option_string, "%s-4 ", option_string);
98 }
99 fping_prog = strdup(PATH_TO_FPING);
100
82 /* compose the command */ 101 /* compose the command */
83 if (config.target_timeout) { 102 if (config.target_timeout) {
84 xasprintf(&option_string, "%s-t %d ", option_string, config.target_timeout); 103 xasprintf(&option_string, "%s-t %d ", option_string, config.target_timeout);
@@ -99,19 +118,28 @@ int main(int argc, char **argv) {
99 xasprintf(&option_string, "%s-R ", option_string); 118 xasprintf(&option_string, "%s-R ", option_string);
100 } 119 }
101 120
102 char *fping_prog = NULL; 121 if (config.fwmark_set) {
103#ifdef PATH_TO_FPING6 122 xasprintf(&option_string, "%s--fwmark %u ", option_string, config.fwmark);
104 if (address_family != AF_INET && is_inet6_addr(server)) { 123 }
105 fping_prog = strdup(PATH_TO_FPING6); 124
106 } else { 125 if (config.icmp_timestamp) {
107 fping_prog = strdup(PATH_TO_FPING); 126 xasprintf(&option_string, "%s--icmp-timestamp ", option_string);
127 }
128
129 if (config.check_source) {
130 xasprintf(&option_string, "%s--check-source ", option_string);
108 } 131 }
109#else
110 fping_prog = strdup(PATH_TO_FPING);
111#endif
112 132
113 char *command_line = NULL; 133 char *command_line = NULL;
114 xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string, config.packet_size, config.packet_count, server); 134
135 if (config.icmp_timestamp) {
136 // no packet size settable for ICMP timestamp
137 xasprintf(&command_line, "%s %s -c %d %s", fping_prog, option_string, config.packet_count,
138 server);
139 } else {
140 xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string,
141 config.packet_size, config.packet_count, server);
142 }
115 143
116 if (verbose) { 144 if (verbose) {
117 printf("%s\n", command_line); 145 printf("%s\n", command_line);
@@ -135,8 +163,9 @@ int main(int argc, char **argv) {
135 if (verbose) { 163 if (verbose) {
136 printf("%s", input_buffer); 164 printf("%s", input_buffer);
137 } 165 }
138 status = max_state(status, textscan(input_buffer, config.server_name, config.crta_p, config.crta, config.wrta_p, config.wrta, 166 status = max_state(status, textscan(input_buffer, config.server_name, config.crta_p,
139 config.cpl_p, config.cpl, config.wpl_p, config.wpl, config.alive_p)); 167 config.crta, config.wrta_p, config.wrta, config.cpl_p,
168 config.cpl, config.wpl_p, config.wpl, config.alive_p));
140 } 169 }
141 170
142 /* If we get anything on STDERR, at least set warning */ 171 /* If we get anything on STDERR, at least set warning */
@@ -145,8 +174,9 @@ int main(int argc, char **argv) {
145 if (verbose) { 174 if (verbose) {
146 printf("%s", input_buffer); 175 printf("%s", input_buffer);
147 } 176 }
148 status = max_state(status, textscan(input_buffer, config.server_name, config.crta_p, config.crta, config.wrta_p, config.wrta, 177 status = max_state(status, textscan(input_buffer, config.server_name, config.crta_p,
149 config.cpl_p, config.cpl, config.wpl_p, config.wpl, config.alive_p)); 178 config.crta, config.wrta_p, config.wrta, config.cpl_p,
179 config.cpl, config.wpl_p, config.wpl, config.alive_p));
150 } 180 }
151 (void)fclose(child_stderr); 181 (void)fclose(child_stderr);
152 182
@@ -175,8 +205,8 @@ int main(int argc, char **argv) {
175 return status; 205 return status;
176} 206}
177 207
178mp_state_enum textscan(char *buf, const char *server_name, bool crta_p, double crta, bool wrta_p, double wrta, bool cpl_p, int cpl, 208mp_state_enum textscan(char *buf, const char *server_name, bool crta_p, double crta, bool wrta_p,
179 bool wpl_p, int wpl, bool alive_p) { 209 double wrta, bool cpl_p, int cpl, bool wpl_p, int wpl, bool alive_p) {
180 /* stops testing after the first successful reply. */ 210 /* stops testing after the first successful reply. */
181 double rta; 211 double rta;
182 double loss; 212 double loss;
@@ -189,7 +219,8 @@ mp_state_enum textscan(char *buf, const char *server_name, bool crta_p, double c
189 die(STATE_OK, _("FPING %s - %s (rta=%f ms)|%s\n"), state_text(STATE_OK), server_name, rta, 219 die(STATE_OK, _("FPING %s - %s (rta=%f ms)|%s\n"), state_text(STATE_OK), server_name, rta,
190 /* No loss since we only waited for the first reply 220 /* No loss since we only waited for the first reply
191 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), */ 221 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), */
192 fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, false, 0)); 222 fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0,
223 false, 0));
193 } 224 }
194 225
195 mp_state_enum status = STATE_UNKNOWN; 226 mp_state_enum status = STATE_UNKNOWN;
@@ -230,9 +261,11 @@ mp_state_enum textscan(char *buf, const char *server_name, bool crta_p, double c
230 } else { 261 } else {
231 status = STATE_OK; 262 status = STATE_OK;
232 } 263 }
233 die(status, _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), state_text(status), server_name, loss, rta, 264 die(status, _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), state_text(status),
265 server_name, loss, rta,
234 perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, false, 0, false, 0), 266 perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, false, 0, false, 0),
235 fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, false, 0)); 267 fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0,
268 false, 0));
236 269
237 } else if (strstr(buf, "xmt/rcv/%loss")) { 270 } else if (strstr(buf, "xmt/rcv/%loss")) {
238 /* no min/max/avg if host was unreachable in fping v2.2.b1 */ 271 /* no min/max/avg if host was unreachable in fping v2.2.b1 */
@@ -268,13 +301,38 @@ mp_state_enum textscan(char *buf, const char *server_name, bool crta_p, double c
268 301
269/* process command-line arguments */ 302/* process command-line arguments */
270check_fping_config_wrapper process_arguments(int argc, char **argv) { 303check_fping_config_wrapper process_arguments(int argc, char **argv) {
271 static struct option longopts[] = { 304 enum {
272 {"hostname", required_argument, 0, 'H'}, {"sourceip", required_argument, 0, 'S'}, {"sourceif", required_argument, 0, 'I'}, 305 FWMARK_OPT = CHAR_MAX + 1,
273 {"critical", required_argument, 0, 'c'}, {"warning", required_argument, 0, 'w'}, {"alive", no_argument, 0, 'a'}, 306 ICMP_TIMESTAMP_OPT,
274 {"bytes", required_argument, 0, 'b'}, {"number", required_argument, 0, 'n'}, {"target-timeout", required_argument, 0, 'T'}, 307 CHECK_SOURCE_OPT,
275 {"interval", required_argument, 0, 'i'}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, 308 };
276 {"help", no_argument, 0, 'h'}, {"use-ipv4", no_argument, 0, '4'}, {"use-ipv6", no_argument, 0, '6'}, 309 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
277 {"dontfrag", no_argument, 0, 'M'}, {"random", no_argument, 0, 'R'}, {0, 0, 0, 0}}; 310 {"sourceip", required_argument, 0, 'S'},
311 {"sourceif", required_argument, 0, 'I'},
312 {"critical", required_argument, 0, 'c'},
313 {"warning", required_argument, 0, 'w'},
314 {"alive", no_argument, 0, 'a'},
315 {"bytes", required_argument, 0, 'b'},
316 {"number", required_argument, 0, 'n'},
317 {"target-timeout", required_argument, 0, 'T'},
318 {"interval", required_argument, 0, 'i'},
319 {"verbose", no_argument, 0, 'v'},
320 {"version", no_argument, 0, 'V'},
321 {"help", no_argument, 0, 'h'},
322 {"use-ipv4", no_argument, 0, '4'},
323 {"use-ipv6", no_argument, 0, '6'},
324 {"dontfrag", no_argument, 0, 'M'},
325 {"random", no_argument, 0, 'R'},
326#ifdef FPING_VERSION_5_2_OR_HIGHER
327 // only available with fping version >= 5.2
328 {"fwmark", required_argument, NULL, FWMARK_OPT},
329# ifdef FPING_VERSION_5_3_OR_HIGHER
330 // only available with fping version >= 5.3
331 {"icmp-timestamp", no_argument, NULL, ICMP_TIMESTAMP_OPT},
332 {"check-source", no_argument, NULL, CHECK_SOURCE_OPT},
333# endif
334#endif
335 {0, 0, 0, 0}};
278 336
279 char *rv[2]; 337 char *rv[2];
280 rv[PL] = NULL; 338 rv[PL] = NULL;
@@ -299,8 +357,9 @@ check_fping_config_wrapper process_arguments(int argc, char **argv) {
299 argc--; 357 argc--;
300 } 358 }
301 359
302 while (1) { 360 while (true) {
303 int option_index = getopt_long(argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:M:R:46", longopts, &option); 361 int option_index =
362 getopt_long(argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:M:R:46", longopts, &option);
304 363
305 if (option_index == -1 || option_index == EOF || option_index == 1) { 364 if (option_index == -1 || option_index == EOF || option_index == 1) {
306 break; 365 break;
@@ -340,11 +399,7 @@ check_fping_config_wrapper process_arguments(int argc, char **argv) {
340 address_family = AF_INET; 399 address_family = AF_INET;
341 break; 400 break;
342 case '6': /* IPv6 only */ 401 case '6': /* IPv6 only */
343#ifdef USE_IPV6
344 address_family = AF_INET6; 402 address_family = AF_INET6;
345#else
346 usage(_("IPv6 support not available\n"));
347#endif
348 break; 403 break;
349 case 'c': 404 case 'c':
350 get_threshold(optarg, rv); 405 get_threshold(optarg, rv);
@@ -406,6 +461,20 @@ check_fping_config_wrapper process_arguments(int argc, char **argv) {
406 case 'M': 461 case 'M':
407 result.config.dontfrag = true; 462 result.config.dontfrag = true;
408 break; 463 break;
464 case FWMARK_OPT:
465 if (is_intpos(optarg)) {
466 result.config.fwmark = (unsigned int)atol(optarg);
467 result.config.fwmark_set = true;
468 } else {
469 usage(_("fwmark must be a positive integer"));
470 }
471 break;
472 case ICMP_TIMESTAMP_OPT:
473 result.config.icmp_timestamp = true;
474 break;
475 case CHECK_SOURCE_OPT:
476 result.config.check_source = true;
477 break;
409 } 478 }
410 } 479 }
411 480
@@ -427,10 +496,12 @@ int get_threshold(char *arg, char *rv[2]) {
427 if (arg2) { 496 if (arg2) {
428 arg1[strcspn(arg1, ",:")] = 0; 497 arg1[strcspn(arg1, ",:")] = 0;
429 if (strstr(arg1, "%") && strstr(arg2, "%")) { 498 if (strstr(arg1, "%") && strstr(arg2, "%")) {
430 die(STATE_UNKNOWN, _("%s: Only one threshold may be packet loss (%s)\n"), progname, arg); 499 die(STATE_UNKNOWN, _("%s: Only one threshold may be packet loss (%s)\n"), progname,
500 arg);
431 } 501 }
432 if (!strstr(arg1, "%") && !strstr(arg2, "%")) { 502 if (!strstr(arg1, "%") && !strstr(arg2, "%")) {
433 die(STATE_UNKNOWN, _("%s: Only one threshold must be packet loss (%s)\n"), progname, arg); 503 die(STATE_UNKNOWN, _("%s: Only one threshold must be packet loss (%s)\n"), progname,
504 arg);
434 } 505 }
435 } 506 }
436 507
@@ -456,7 +527,8 @@ void print_help(void) {
456 printf("Copyright (c) 1999 Didi Rieder <adrieder@sbox.tu-graz.ac.at>\n"); 527 printf("Copyright (c) 1999 Didi Rieder <adrieder@sbox.tu-graz.ac.at>\n");
457 printf(COPYRIGHT, copyright, email); 528 printf(COPYRIGHT, copyright, email);
458 529
459 printf("%s\n", _("This plugin will use the fping command to ping the specified host for a fast check")); 530 printf("%s\n",
531 _("This plugin will use the fping command to ping the specified host for a fast check"));
460 532
461 printf("%s\n", _("Note that it is necessary to set the suid flag on fping.")); 533 printf("%s\n", _("Note that it is necessary to set the suid flag on fping."));
462 534
@@ -470,7 +542,8 @@ void print_help(void) {
470 printf(UT_IPv46); 542 printf(UT_IPv46);
471 543
472 printf(" %s\n", "-H, --hostname=HOST"); 544 printf(" %s\n", "-H, --hostname=HOST");
473 printf(" %s\n", _("name or IP Address of host to ping (IP Address bypasses name lookup, reducing system load)")); 545 printf(" %s\n", _("name or IP Address of host to ping (IP Address bypasses name lookup, "
546 "reducing system load)"));
474 printf(" %s\n", "-w, --warning=THRESHOLD"); 547 printf(" %s\n", "-w, --warning=THRESHOLD");
475 printf(" %s\n", _("warning threshold pair")); 548 printf(" %s\n", _("warning threshold pair"));
476 printf(" %s\n", "-c, --critical=THRESHOLD"); 549 printf(" %s\n", "-c, --critical=THRESHOLD");
@@ -484,7 +557,8 @@ void print_help(void) {
484 printf(" %s\n", "-T, --target-timeout=INTEGER"); 557 printf(" %s\n", "-T, --target-timeout=INTEGER");
485 printf(" %s (default: fping's default for -t)\n", _("Target timeout (ms)")); 558 printf(" %s (default: fping's default for -t)\n", _("Target timeout (ms)"));
486 printf(" %s\n", "-i, --interval=INTEGER"); 559 printf(" %s\n", "-i, --interval=INTEGER");
487 printf(" %s (default: fping's default for -p)\n", _("Interval (ms) between sending packets")); 560 printf(" %s (default: fping's default for -p)\n",
561 _("Interval (ms) between sending packets"));
488 printf(" %s\n", "-S, --sourceip=HOST"); 562 printf(" %s\n", "-S, --sourceip=HOST");
489 printf(" %s\n", _("name or IP Address of sourceip")); 563 printf(" %s\n", _("name or IP Address of sourceip"));
490 printf(" %s\n", "-I, --sourceif=IF"); 564 printf(" %s\n", "-I, --sourceif=IF");
@@ -493,9 +567,20 @@ void print_help(void) {
493 printf(" %s\n", _("set the Don't Fragment flag")); 567 printf(" %s\n", _("set the Don't Fragment flag"));
494 printf(" %s\n", "-R, --random"); 568 printf(" %s\n", "-R, --random");
495 printf(" %s\n", _("random packet data (to foil link data compression)")); 569 printf(" %s\n", _("random packet data (to foil link data compression)"));
570#ifdef FPING_VERSION_5_2_OR_HIGHER
571 printf(" %s\n", "--fwmark=INTEGER");
572 printf(" %s\n", _("set the routing mark to INTEGER (fping option)"));
573# ifdef FPING_VERSION_5_3_OR_HIGHER
574 printf(" %s\n", "--icmp-timestamp");
575 printf(" %s\n", _("use ICMP Timestamp instead of ICMP Echo (fping option)"));
576 printf(" %s\n", "--check-source");
577 printf(" %s\n", _("discard replies not from target address (fping option)"));
578# endif
579#endif
496 printf(UT_VERBOSE); 580 printf(UT_VERBOSE);
497 printf("\n"); 581 printf("\n");
498 printf(" %s\n", _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)")); 582 printf(" %s\n",
583 _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)"));
499 printf(" %s\n", _("which triggers a WARNING or CRITICAL state, and <pl> is the percentage of")); 584 printf(" %s\n", _("which triggers a WARNING or CRITICAL state, and <pl> is the percentage of"));
500 printf(" %s\n", _("packet loss to trigger an alarm state.")); 585 printf(" %s\n", _("packet loss to trigger an alarm state."));
501 586
@@ -507,5 +592,6 @@ void print_help(void) {
507 592
508void print_usage(void) { 593void print_usage(void) {
509 printf("%s\n", _("Usage:")); 594 printf("%s\n", _("Usage:"));
510 printf(" %s <host_address> -w limit -c limit [-b size] [-n number] [-T number] [-i number]\n", progname); 595 printf(" %s <host_address> -w limit -c limit [-b size] [-n number] [-T number] [-i number]\n",
596 progname);
511} 597}