1 /*****************************************************************************
3 * Monitoring check_fping plugin
6 * Copyright (c) 2000-2007 Monitoring Plugins Development Team
10 * This file contains the check_disk plugin
12 * This plugin will use the fping command to ping the specified host for a
16 * This program is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, either version 3 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30 *****************************************************************************/
32 const char *progname
= "check_fping";
33 const char *copyright
= "2000-2007";
34 const char *email
= "devel@monitoring-plugins.org";
48 int textscan (char *buf
);
49 int process_arguments (int, char **);
50 int get_threshold (char *arg
, char *rv
[2]);
51 void print_help (void);
52 void print_usage (void);
54 char *server_name
= NULL
;
55 char *sourceip
= NULL
;
56 char *sourceif
= NULL
;
57 int packet_size
= PACKET_SIZE
;
58 int packet_count
= PACKET_COUNT
;
59 int target_timeout
= 0;
60 int packet_interval
= 0;
72 main (int argc
, char **argv
)
74 /* normaly should be int result = STATE_UNKNOWN; */
76 int status
= STATE_UNKNOWN
;
78 char *fping_prog
= NULL
;
80 char *command_line
= NULL
;
81 char *input_buffer
= NULL
;
82 char *option_string
= "";
83 input_buffer
= malloc (MAX_INPUT_BUFFER
);
85 setlocale (LC_ALL
, "");
86 bindtextdomain (PACKAGE
, LOCALEDIR
);
89 /* Parse extra opts if any */
90 argv
=np_extra_opts (&argc
, argv
, progname
);
92 if (process_arguments (argc
, argv
) == ERROR
)
93 usage4 (_("Could not parse arguments"));
95 server
= strscpy (server
, server_name
);
97 /* compose the command */
99 xasprintf(&option_string
, "%s-t %d ", option_string
, target_timeout
);
101 xasprintf(&option_string
, "%s-p %d ", option_string
, packet_interval
);
103 xasprintf(&option_string
, "%s-S %s ", option_string
, sourceip
);
105 xasprintf(&option_string
, "%s-I %s ", option_string
, sourceif
);
107 #ifdef PATH_TO_FPING6
108 if (address_family
!= AF_INET
&& is_inet6_addr(server
))
109 fping_prog
= strdup(PATH_TO_FPING6
);
111 fping_prog
= strdup(PATH_TO_FPING
);
113 fping_prog
= strdup(PATH_TO_FPING
);
116 xasprintf (&command_line
, "%s %s-b %d -c %d %s", fping_prog
,
117 option_string
, packet_size
, packet_count
, server
);
120 printf ("%s\n", command_line
);
122 /* run the command */
123 child_process
= spopen (command_line
);
124 if (child_process
== NULL
) {
125 printf (_("Could not open pipe: %s\n"), command_line
);
126 return STATE_UNKNOWN
;
129 child_stderr
= fdopen (child_stderr_array
[fileno (child_process
)], "r");
130 if (child_stderr
== NULL
) {
131 printf (_("Could not open stderr for %s\n"), command_line
);
134 while (fgets (input_buffer
, MAX_INPUT_BUFFER
- 1, child_process
)) {
136 printf ("%s", input_buffer
);
137 status
= max_state (status
, textscan (input_buffer
));
140 /* If we get anything on STDERR, at least set warning */
141 while (fgets (input_buffer
, MAX_INPUT_BUFFER
- 1, child_stderr
)) {
142 status
= max_state (status
, STATE_WARNING
);
144 printf ("%s", input_buffer
);
145 status
= max_state (status
, textscan (input_buffer
));
147 (void) fclose (child_stderr
);
150 if (result
= spclose (child_process
))
151 /* need to use max_state not max */
152 status
= max_state (status
, STATE_WARNING
);
155 status
= max_state (status
, STATE_UNKNOWN
);
157 die (STATE_UNKNOWN
, _("FPING UNKNOWN - IP address not found\n"));
160 die (STATE_UNKNOWN
, _("FPING UNKNOWN - invalid commandline argument\n"));
163 die (STATE_UNKNOWN
, _("FPING UNKNOWN - failed system call\n"));
168 printf ("FPING %s - %s\n", state_text (status
), server_name
);
184 int status
= STATE_UNKNOWN
;
186 if (strstr (buf
, "not found")) {
187 die (STATE_CRITICAL
, _("FPING UNKNOW - %s not found\n"), server_name
);
190 else if (strstr (buf
, "is unreachable") || strstr (buf
, "Unreachable")) {
191 die (STATE_CRITICAL
, _("FPING CRITICAL - %s is unreachable\n"),
195 else if (strstr (buf
, "Operation not permitted") || strstr (buf
, "No such device") ) {
196 die (STATE_UNKNOWN
, _("FPING UNKNOWN - %s parameter error\n"),
199 else if (strstr (buf
, "is down")) {
200 die (STATE_CRITICAL
, _("FPING CRITICAL - %s is down\n"), server_name
);
203 else if (strstr (buf
, "is alive")) {
207 else if (strstr (buf
, "xmt/rcv/%loss") && strstr (buf
, "min/avg/max")) {
208 losstr
= strstr (buf
, "=");
209 losstr
= 1 + strstr (losstr
, "/");
210 losstr
= 1 + strstr (losstr
, "/");
211 rtastr
= strstr (buf
, "min/avg/max");
212 rtastr
= strstr (rtastr
, "=");
213 rtastr
= 1 + index (rtastr
, '/');
214 loss
= strtod (losstr
, NULL
);
215 rta
= strtod (rtastr
, NULL
);
216 if (cpl_p
== TRUE
&& loss
> cpl
)
217 status
= STATE_CRITICAL
;
218 else if (crta_p
== TRUE
&& rta
> crta
)
219 status
= STATE_CRITICAL
;
220 else if (wpl_p
== TRUE
&& loss
> wpl
)
221 status
= STATE_WARNING
;
222 else if (wrta_p
== TRUE
&& rta
> wrta
)
223 status
= STATE_WARNING
;
227 _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"),
228 state_text (status
), server_name
, loss
, rta
,
229 perfdata ("loss", (long int)loss
, "%", wpl_p
, wpl
, cpl_p
, cpl
, TRUE
, 0, TRUE
, 100),
230 fperfdata ("rta", rta
/1.0e3
, "s", wrta_p
, wrta
/1.0e3
, crta_p
, crta
/1.0e3
, TRUE
, 0, FALSE
, 0));
233 else if(strstr (buf
, "xmt/rcv/%loss") ) {
234 /* no min/max/avg if host was unreachable in fping v2.2.b1 */
235 /* in v2.4b2: 10.99.0.1 : xmt/rcv/%loss = 0/0/0% */
236 losstr
= strstr (buf
, "=");
238 xmt
= strtod (xmtstr
, NULL
);
240 die (STATE_CRITICAL
, _("FPING CRITICAL - %s is down\n"), server_name
);
241 losstr
= 1 + strstr (losstr
, "/");
242 losstr
= 1 + strstr (losstr
, "/");
243 loss
= strtod (losstr
, NULL
);
244 if (atoi(losstr
) == 100)
245 status
= STATE_CRITICAL
;
246 else if (cpl_p
== TRUE
&& loss
> cpl
)
247 status
= STATE_CRITICAL
;
248 else if (wpl_p
== TRUE
&& loss
> wpl
)
249 status
= STATE_WARNING
;
252 /* loss=%.0f%%;%d;%d;0;100 */
253 die (status
, _("FPING %s - %s (loss=%.0f%% )|%s\n"),
254 state_text (status
), server_name
, loss
,
255 perfdata ("loss", (long int)loss
, "%", wpl_p
, wpl
, cpl_p
, cpl
, TRUE
, 0, TRUE
, 100));
259 status
= max_state (status
, STATE_WARNING
);
267 /* process command-line arguments */
269 process_arguments (int argc
, char **argv
)
275 static struct option longopts
[] = {
276 {"hostname", required_argument
, 0, 'H'},
277 {"sourceip", required_argument
, 0, 'S'},
278 {"sourceif", required_argument
, 0, 'I'},
279 {"critical", required_argument
, 0, 'c'},
280 {"warning", required_argument
, 0, 'w'},
281 {"bytes", required_argument
, 0, 'b'},
282 {"number", required_argument
, 0, 'n'},
283 {"target-timeout", required_argument
, 0, 'T'},
284 {"interval", required_argument
, 0, 'i'},
285 {"verbose", no_argument
, 0, 'v'},
286 {"version", no_argument
, 0, 'V'},
287 {"help", no_argument
, 0, 'h'},
288 {"use-ipv4", no_argument
, 0, '4'},
289 {"use-ipv6", no_argument
, 0, '6'},
299 if (!is_option (argv
[1])) {
300 server_name
= argv
[1];
307 c
= getopt_long (argc
, argv
, "+hVvH:S:c:w:b:n:T:i:I:46", longopts
, &option
);
309 if (c
== -1 || c
== EOF
|| c
== 1)
313 case '?': /* print short usage statement if args not parsable */
317 exit (STATE_UNKNOWN
);
318 case 'V': /* version */
319 print_revision (progname
, NP_VERSION
);
320 exit (STATE_UNKNOWN
);
321 case 'v': /* verbose mode */
324 case 'H': /* hostname */
325 if (is_host (optarg
) == FALSE
) {
326 usage2 (_("Invalid hostname/address"), optarg
);
328 server_name
= strscpy (server_name
, optarg
);
330 case 'S': /* sourceip */
331 if (is_host (optarg
) == FALSE
) {
332 usage2 (_("Invalid hostname/address"), optarg
);
334 sourceip
= strscpy (sourceip
, optarg
);
336 case 'I': /* sourceip */
337 sourceif
= strscpy (sourceif
, optarg
);
338 case '4': /* IPv4 only */
339 address_family
= AF_INET
;
341 case '6': /* IPv6 only */
343 address_family
= AF_INET6
;
345 usage (_("IPv6 support not available\n"));
349 get_threshold (optarg
, rv
);
351 crta
= strtod (rv
[RTA
], NULL
);
362 get_threshold (optarg
, rv
);
364 wrta
= strtod (rv
[RTA
], NULL
);
374 case 'b': /* bytes per packet */
375 if (is_intpos (optarg
))
376 packet_size
= atoi (optarg
);
378 usage (_("Packet size must be a positive integer"));
380 case 'n': /* number of packets */
381 if (is_intpos (optarg
))
382 packet_count
= atoi (optarg
);
384 usage (_("Packet count must be a positive integer"));
386 case 'T': /* timeout in msec */
387 if (is_intpos (optarg
))
388 target_timeout
= atoi (optarg
);
390 usage (_("Target timeout must be a positive integer"));
392 case 'i': /* interval in msec */
393 if (is_intpos (optarg
))
394 packet_interval
= atoi (optarg
);
396 usage (_("Interval must be a positive integer"));
401 if (server_name
== NULL
)
402 usage4 (_("Hostname was not supplied"));
409 get_threshold (char *arg
, char *rv
[2])
414 arg1
= strscpy (arg1
, arg
);
415 if (strpbrk (arg1
, ",:"))
416 arg2
= 1 + strpbrk (arg1
, ",:");
419 arg1
[strcspn (arg1
, ",:")] = 0;
420 if (strstr (arg1
, "%") && strstr (arg2
, "%"))
422 _("%s: Only one threshold may be packet loss (%s)\n"), progname
,
424 if (!strstr (arg1
, "%") && !strstr (arg2
, "%"))
426 _("%s: Only one threshold must be packet loss (%s)\n"),
430 if (arg2
&& strstr (arg2
, "%")) {
438 else if (strstr (arg1
, "%")) {
453 print_revision (progname
, NP_VERSION
);
455 printf ("Copyright (c) 1999 Didi Rieder <adrieder@sbox.tu-graz.ac.at>\n");
456 printf (COPYRIGHT
, copyright
, email
);
458 printf ("%s\n", _("This plugin will use the fping command to ping the specified host for a fast check"));
460 printf ("%s\n", _("Note that it is necessary to set the suid flag on fping."));
466 printf (UT_HELP_VRSN
);
467 printf (UT_EXTRA_OPTS
);
471 printf (" %s\n", "-H, --hostname=HOST");
472 printf (" %s\n", _("name or IP Address of host to ping (IP Address bypasses name lookup, reducing system load)"));
473 printf (" %s\n", "-w, --warning=THRESHOLD");
474 printf (" %s\n", _("warning threshold pair"));
475 printf (" %s\n", "-c, --critical=THRESHOLD");
476 printf (" %s\n", _("critical threshold pair"));
477 printf (" %s\n", "-b, --bytes=INTEGER");
478 printf (" %s (default: %d)\n", _("size of ICMP packet"),PACKET_SIZE
);
479 printf (" %s\n", "-n, --number=INTEGER");
480 printf (" %s (default: %d)\n", _("number of ICMP packets to send"),PACKET_COUNT
);
481 printf (" %s\n", "-T, --target-timeout=INTEGER");
482 printf (" %s (default: fping's default for -t)\n", _("Target timeout (ms)"));
483 printf (" %s\n", "-i, --interval=INTEGER");
484 printf (" %s (default: fping's default for -p)\n", _("Interval (ms) between sending packets"));
485 printf (" %s\n", "-S, --sourceip=HOST");
486 printf (" %s\n", _("name or IP Address of sourceip"));
487 printf (" %s\n", "-I, --sourceif=IF");
488 printf (" %s\n", _("source interface name"));
491 printf (" %s\n", _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)"));
492 printf (" %s\n", _("which triggers a WARNING or CRITICAL state, and <pl> is the percentage of"));
493 printf (" %s\n", _("packet loss to trigger an alarm state."));
496 printf (" %s\n", _("IPv4 is used by default. Specify -6 to use IPv6."));
505 printf ("%s\n", _("Usage:"));
506 printf (" %s <host_address> -w limit -c limit [-b size] [-n number] [-T number] [-i number]\n", progname
);