1
/******************************************************************************
5
* Program: Fping plugin for Nagios
7
* Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)
8
* $Id: check_fping.c,v 1.4 2003/01/13 12:15:15 kdebisschop Exp $
12
* 08-24-1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)
14
* 09-11-1999 Karl DeBisschop (kdebiss@alum.mit.edu)
16
* Fix so that state unknown is returned by default
17
* (formerly would give state ok if no fping specified)
18
* Add server_name to output
19
* Reformat to 80-character standard screen
20
* 11-18-1999 Karl DeBisschop (kdebiss@alum.mit.edu)
21
* set STATE_WARNING of stderr written or nonzero status returned
25
* This plugin will use the /bin/fping command (form saint) to ping
26
* the specified host for a fast check if the host is alive. Note that
27
* it is necessary to set the suid flag on fping.
28
******************************************************************************/
35
const char *progname = "check_fping";
36
#define PACKET_COUNT 1
37
#define PACKET_SIZE 56
38
#define UNKNOWN_PACKET_LOSS 200 /* 200% */
39
#define UNKNOWN_TRIP_TIME -1.0 /* -1 seconds */
44
int textscan (char *buf);
45
int process_arguments (int, char **);
46
int get_threshold (char *arg, char *rv[2]);
47
void print_usage (void);
48
void print_help (void);
50
char *server_name = NULL;
51
int cpl = UNKNOWN_PACKET_LOSS;
52
int wpl = UNKNOWN_PACKET_LOSS;
53
double crta = UNKNOWN_TRIP_TIME;
54
double wrta = UNKNOWN_TRIP_TIME;
55
int packet_size = PACKET_SIZE;
56
int packet_count = PACKET_COUNT;
60
main (int argc, char **argv)
62
int status = STATE_UNKNOWN;
64
char *command_line = NULL;
65
char *input_buffer = NULL;
66
input_buffer = malloc (MAX_INPUT_BUFFER);
68
if (process_arguments (argc, argv) == ERROR)
69
usage ("Could not parse arguments\n");
71
server = strscpy (server, server_name);
73
/* compose the command */
74
asprintf (&command_line, "%s -b %d -c %d %s", PATH_TO_FPING,
75
packet_size, packet_count, server);
78
printf ("%s\n", command_line);
81
child_process = spopen (command_line);
82
if (child_process == NULL) {
83
printf ("Unable to open pipe: %s\n", command_line);
87
child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
88
if (child_stderr == NULL) {
89
printf ("Could not open stderr for %s\n", command_line);
92
while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
94
printf ("%s", input_buffer);
95
status = max_state (status, textscan (input_buffer));
98
/* If we get anything on STDERR, at least set warning */
99
while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
100
status = max_state (status, STATE_WARNING);
102
printf ("%s", input_buffer);
103
status = max_state (status, textscan (input_buffer));
105
(void) fclose (child_stderr);
108
if (spclose (child_process))
109
/* need to use max_state not max */
110
status = max_state (status, STATE_WARNING);
112
printf ("FPING %s - %s\n", state_text (status), server_name);
127
int status = STATE_UNKNOWN;
129
if (strstr (buf, "not found")) {
130
terminate (STATE_CRITICAL, "FPING unknown - %s not found\n", server_name);
133
else if (strstr (buf, "is unreachable") || strstr (buf, "Unreachable")) {
134
terminate (STATE_CRITICAL, "FPING critical - %s is unreachable\n",
138
else if (strstr (buf, "is down")) {
139
terminate (STATE_CRITICAL, "FPING critical - %s is down\n", server_name);
142
else if (strstr (buf, "is alive")) {
146
else if (strstr (buf, "xmt/rcv/%loss") && strstr (buf, "min/avg/max")) {
147
losstr = strstr (buf, "=");
148
losstr = 1 + strstr (losstr, "/");
149
losstr = 1 + strstr (losstr, "/");
150
rtastr = strstr (buf, "min/avg/max");
151
rtastr = strstr (rtastr, "=");
152
rtastr = 1 + index (rtastr, '/');
153
loss = strtod (losstr, NULL);
154
rta = strtod (rtastr, NULL);
155
if (cpl != UNKNOWN_PACKET_LOSS && loss > cpl)
156
status = STATE_CRITICAL;
157
else if (crta != UNKNOWN_TRIP_TIME && rta > crta)
158
status = STATE_CRITICAL;
159
else if (wpl != UNKNOWN_PACKET_LOSS && loss > wpl)
160
status = STATE_WARNING;
161
else if (wrta != UNKNOWN_TRIP_TIME && rta > wrta)
162
status = STATE_WARNING;
165
terminate (status, "FPING %s - %s (loss=%f%%, rta=%f ms)\n",
166
state_text (status), server_name, loss, rta);
169
else if(strstr (buf, "xmt/rcv/%loss") ) {
170
/* no min/max/avg if host was unreachable in fping v2.2.b1 */
171
losstr = strstr (buf, "=");
172
losstr = 1 + strstr (losstr, "/");
173
losstr = 1 + strstr (losstr, "/");
174
loss = strtod (losstr, NULL);
176
status = STATE_CRITICAL;
177
else if (cpl != UNKNOWN_PACKET_LOSS && loss > cpl)
178
status = STATE_CRITICAL;
179
else if (wpl != UNKNOWN_PACKET_LOSS && loss > wpl)
180
status = STATE_WARNING;
184
terminate (status, "FPING %s - %s (loss=%f%% )\n",
185
state_text (status), server_name, loss );
189
status = max_state (status, STATE_WARNING);
198
/* process command-line arguments */
200
process_arguments (int argc, char **argv)
206
int option_index = 0;
207
static struct option long_options[] = {
208
{"hostname", required_argument, 0, 'H'},
209
{"critical", required_argument, 0, 'c'},
210
{"warning", required_argument, 0, 'w'},
211
{"bytes", required_argument, 0, 'b'},
212
{"number", required_argument, 0, 'n'},
213
{"verbose", no_argument, 0, 'v'},
214
{"version", no_argument, 0, 'V'},
215
{"help", no_argument, 0, 'h'},
226
if (!is_option (argv[1])) {
227
server_name = argv[1];
236
getopt_long (argc, argv, "+hVvH:c:w:b:n:", long_options, &option_index);
238
c = getopt (argc, argv, "+hVvH:c:w:b:n:");
241
if (c == -1 || c == EOF || c == 1)
245
case '?': /* print short usage statement if args not parsable */
246
printf ("%s: Unknown argument: %s\n\n", progname, optarg);
248
exit (STATE_UNKNOWN);
252
case 'V': /* version */
253
print_revision (progname, "$Revision: 1.4 $");
255
case 'v': /* verbose mode */
258
case 'H': /* hostname */
259
if (is_host (optarg) == FALSE) {
260
printf ("Invalid host name/address\n\n");
262
exit (STATE_UNKNOWN);
264
server_name = strscpy (server_name, optarg);
267
get_threshold (optarg, rv);
269
crta = strtod (rv[RTA], NULL);
278
get_threshold (optarg, rv);
280
wrta = strtod (rv[RTA], NULL);
288
case 'b': /* bytes per packet */
289
if (is_intpos (optarg))
290
packet_size = atoi (optarg);
292
usage ("Packet size must be a positive integer");
294
case 'n': /* number of packets */
295
if (is_intpos (optarg))
296
packet_count = atoi (optarg);
298
usage ("Packet count must be a positive integer");
304
if (server_name == NULL)
305
usage ("Host name was not supplied\n\n");
315
get_threshold (char *arg, char *rv[2])
320
arg1 = strscpy (arg1, arg);
321
if (strpbrk (arg1, ",:"))
322
arg2 = 1 + strpbrk (arg1, ",:");
325
arg1[strcspn (arg1, ",:")] = 0;
326
if (strstr (arg1, "%") && strstr (arg2, "%"))
327
terminate (STATE_UNKNOWN,
328
"%s: Only one threshold may be packet loss (%s)\n", progname,
330
if (!strstr (arg1, "%") && !strstr (arg2, "%"))
331
terminate (STATE_UNKNOWN,
332
"%s: Only one threshold must be packet loss (%s)\n",
336
if (arg2 && strstr (arg2, "%")) {
344
else if (strstr (arg1, "%")) {
361
printf ("Usage: %s <host_address>\n", progname);
372
print_revision (progname, "$Revision: 1.4 $");
375
("Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)\n\n"
376
"This plugin will use the /bin/fping command (from saint) to ping the\n"
377
"specified host for a fast check if the host is alive. Note that it is\n"
378
"necessary to set the suid flag on fping.\n\n");
384
"-H, --hostname=HOST\n"
385
" Name or IP Address of host to ping (IP Address bypasses name lookup,\n"
386
" reducing system load)\n"
387
"-w, --warning=THRESHOLD\n"
388
" warning threshold pair\n"
389
"-c, --critical=THRESHOLD\n"
390
" critical threshold pair\n"
391
"-b, --bytes=INTEGER\n"
392
" Size of ICMP packet (default: %d)\n"
393
"-n, --number=INTEGER\n"
394
" Number of ICMP packets to send (default: %d)\n"
396
" Show details for command-line debugging (do not use with nagios server)\n"
398
" Print this help screen\n"
400
" Print version information\n"
401
"THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel\n"
402
"time (ms) which triggers a WARNING or CRITICAL state, and <pl> is the\n"
403
"percentage of packet loss to trigger an alarm state.\n",
404
PACKET_SIZE, PACKET_COUNT);