~ubuntu-branches/ubuntu/precise/nagios-plugins/precise-proposed

« back to all changes in this revision

Viewing changes to plugins/check_fping.c

  • Committer: Bazaar Package Importer
  • Author(s): Guido Trotter
  • Date: 2004-06-15 15:37:48 UTC
  • Revision ID: james.westby@ubuntu.com-20040615153748-pq7702qdzghqfcns
Tags: upstream-1.3.1.0
ImportĀ upstreamĀ versionĀ 1.3.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************************************
 
2
*
 
3
* CHECK_FPING.C
 
4
*
 
5
* Program: Fping plugin for Nagios
 
6
* License: GPL
 
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 $
 
9
*
 
10
* Modifications:
 
11
*
 
12
* 08-24-1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)
 
13
*            Intial Coding
 
14
* 09-11-1999 Karl DeBisschop (kdebiss@alum.mit.edu)
 
15
*            Change to spopen
 
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
 
22
*
 
23
* Description:
 
24
*
 
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
******************************************************************************/
 
29
 
 
30
#include "config.h"
 
31
#include "common.h"
 
32
#include "popen.h"
 
33
#include "utils.h"
 
34
 
 
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 */
 
40
 
 
41
#define PL 0
 
42
#define RTA 1
 
43
 
 
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);
 
49
 
 
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;
 
57
int verbose = FALSE;
 
58
 
 
59
int
 
60
main (int argc, char **argv)
 
61
{
 
62
        int status = STATE_UNKNOWN;
 
63
        char *server = NULL;
 
64
        char *command_line = NULL;
 
65
        char *input_buffer = NULL;
 
66
        input_buffer = malloc (MAX_INPUT_BUFFER);
 
67
 
 
68
        if (process_arguments (argc, argv) == ERROR)
 
69
                usage ("Could not parse arguments\n");
 
70
 
 
71
        server = strscpy (server, server_name);
 
72
 
 
73
        /* compose the command */
 
74
        asprintf (&command_line, "%s -b %d -c %d %s", PATH_TO_FPING,
 
75
                  packet_size, packet_count, server);
 
76
 
 
77
        if (verbose)
 
78
                printf ("%s\n", command_line);
 
79
 
 
80
        /* run the command */
 
81
        child_process = spopen (command_line);
 
82
        if (child_process == NULL) {
 
83
                printf ("Unable to open pipe: %s\n", command_line);
 
84
                return STATE_UNKNOWN;
 
85
        }
 
86
 
 
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);
 
90
        }
 
91
 
 
92
        while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
 
93
                if (verbose)
 
94
                        printf ("%s", input_buffer);
 
95
                status = max_state (status, textscan (input_buffer));
 
96
        }
 
97
 
 
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);
 
101
                if (verbose)
 
102
                        printf ("%s", input_buffer);
 
103
                status = max_state (status, textscan (input_buffer));
 
104
        }
 
105
        (void) fclose (child_stderr);
 
106
 
 
107
        /* close the pipe */
 
108
        if (spclose (child_process))
 
109
                /* need to use max_state not max */
 
110
                status = max_state (status, STATE_WARNING);
 
111
 
 
112
        printf ("FPING %s - %s\n", state_text (status), server_name);
 
113
 
 
114
        return status;
 
115
}
 
116
 
 
117
 
 
118
 
 
119
 
 
120
int
 
121
textscan (char *buf)
 
122
{
 
123
        char *rtastr = NULL;
 
124
        char *losstr = NULL;
 
125
        double loss;
 
126
        double rta;
 
127
        int status = STATE_UNKNOWN;
 
128
 
 
129
        if (strstr (buf, "not found")) {
 
130
                terminate (STATE_CRITICAL, "FPING unknown - %s not found\n", server_name);
 
131
 
 
132
        }
 
133
        else if (strstr (buf, "is unreachable") || strstr (buf, "Unreachable")) {
 
134
                terminate (STATE_CRITICAL, "FPING critical - %s is unreachable\n",
 
135
                                                         "host");
 
136
 
 
137
        }
 
138
        else if (strstr (buf, "is down")) {
 
139
                terminate (STATE_CRITICAL, "FPING critical - %s is down\n", server_name);
 
140
 
 
141
        }
 
142
        else if (strstr (buf, "is alive")) {
 
143
                status = STATE_OK;
 
144
 
 
145
        }
 
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;
 
163
                else
 
164
                        status = STATE_OK;
 
165
                terminate (status, "FPING %s - %s (loss=%f%%, rta=%f ms)\n",
 
166
                                                         state_text (status), server_name, loss, rta);
 
167
 
 
168
        }
 
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);
 
175
                if (loss == 100)
 
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;
 
181
                else
 
182
                        status = STATE_OK;
 
183
                
 
184
                terminate (status, "FPING %s - %s (loss=%f%% )\n",
 
185
                                                         state_text (status), server_name, loss );              
 
186
        
 
187
        }
 
188
        else {
 
189
                status = max_state (status, STATE_WARNING);
 
190
        }
 
191
 
 
192
        return status;
 
193
}
 
194
 
 
195
 
 
196
 
 
197
 
 
198
/* process command-line arguments */
 
199
int
 
200
process_arguments (int argc, char **argv)
 
201
{
 
202
        int c;
 
203
        char *rv[2];
 
204
 
 
205
#ifdef HAVE_GETOPT_H
 
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'},
 
216
                {0, 0, 0, 0}
 
217
        };
 
218
#endif
 
219
 
 
220
        rv[PL] = NULL;
 
221
        rv[RTA] = NULL;
 
222
 
 
223
        if (argc < 2)
 
224
                return ERROR;
 
225
 
 
226
        if (!is_option (argv[1])) {
 
227
                server_name = argv[1];
 
228
                argv[1] = argv[0];
 
229
                argv = &argv[1];
 
230
                argc--;
 
231
        }
 
232
 
 
233
        while (1) {
 
234
#ifdef HAVE_GETOPT_H
 
235
                c =
 
236
                        getopt_long (argc, argv, "+hVvH:c:w:b:n:", long_options, &option_index);
 
237
#else
 
238
                c = getopt (argc, argv, "+hVvH:c:w:b:n:");
 
239
#endif
 
240
 
 
241
                if (c == -1 || c == EOF || c == 1)
 
242
                        break;
 
243
 
 
244
                switch (c) {
 
245
                case '?':                                                                       /* print short usage statement if args not parsable */
 
246
                        printf ("%s: Unknown argument: %s\n\n", progname, optarg);
 
247
                        print_usage ();
 
248
                        exit (STATE_UNKNOWN);
 
249
                case 'h':                                                                       /* help */
 
250
                        print_help ();
 
251
                        exit (STATE_OK);
 
252
                case 'V':                                                                       /* version */
 
253
                        print_revision (progname, "$Revision: 1.4 $");
 
254
                        exit (STATE_OK);
 
255
                case 'v':                                                                       /* verbose mode */
 
256
                        verbose = TRUE;
 
257
                        break;
 
258
                case 'H':                                                                       /* hostname */
 
259
                        if (is_host (optarg) == FALSE) {
 
260
                                printf ("Invalid host name/address\n\n");
 
261
                                print_usage ();
 
262
                                exit (STATE_UNKNOWN);
 
263
                        }
 
264
                        server_name = strscpy (server_name, optarg);
 
265
                        break;
 
266
                case 'c':
 
267
                        get_threshold (optarg, rv);
 
268
                        if (rv[RTA]) {
 
269
                                crta = strtod (rv[RTA], NULL);
 
270
                                rv[RTA] = NULL;
 
271
                        }
 
272
                        if (rv[PL]) {
 
273
                                cpl = atoi (rv[PL]);
 
274
                                rv[PL] = NULL;
 
275
                        }
 
276
                        break;
 
277
                case 'w':
 
278
                        get_threshold (optarg, rv);
 
279
                        if (rv[RTA]) {
 
280
                                wrta = strtod (rv[RTA], NULL);
 
281
                                rv[RTA] = NULL;
 
282
                        }
 
283
                        if (rv[PL]) {
 
284
                                wpl = atoi (rv[PL]);
 
285
                                rv[PL] = NULL;
 
286
                        }
 
287
                        break;
 
288
                case 'b':                                                                       /* bytes per packet */
 
289
                        if (is_intpos (optarg))
 
290
                                packet_size = atoi (optarg);
 
291
                        else
 
292
                                usage ("Packet size must be a positive integer");
 
293
                        break;
 
294
                case 'n':                                                                       /* number of packets */
 
295
                        if (is_intpos (optarg))
 
296
                                packet_count = atoi (optarg);
 
297
                        else
 
298
                                usage ("Packet count must be a positive integer");
 
299
                        break;
 
300
                }
 
301
        }
 
302
 
 
303
 
 
304
        if (server_name == NULL)
 
305
                usage ("Host name was not supplied\n\n");
 
306
 
 
307
        return OK;
 
308
}
 
309
 
 
310
 
 
311
 
 
312
 
 
313
 
 
314
int
 
315
get_threshold (char *arg, char *rv[2])
 
316
{
 
317
        char *arg1 = NULL;
 
318
        char *arg2 = NULL;
 
319
 
 
320
        arg1 = strscpy (arg1, arg);
 
321
        if (strpbrk (arg1, ",:"))
 
322
                arg2 = 1 + strpbrk (arg1, ",:");
 
323
 
 
324
        if (arg2) {
 
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,
 
329
                                                                 arg);
 
330
                if (!strstr (arg1, "%") && !strstr (arg2, "%"))
 
331
                        terminate (STATE_UNKNOWN,
 
332
                                                                 "%s: Only one threshold must be packet loss (%s)\n",
 
333
                                                                 progname, arg);
 
334
        }
 
335
 
 
336
        if (arg2 && strstr (arg2, "%")) {
 
337
                rv[PL] = arg2;
 
338
                rv[RTA] = arg1;
 
339
        }
 
340
        else if (arg2) {
 
341
                rv[PL] = arg1;
 
342
                rv[RTA] = arg2;
 
343
        }
 
344
        else if (strstr (arg1, "%")) {
 
345
                rv[PL] = arg1;
 
346
        }
 
347
        else {
 
348
                rv[RTA] = arg1;
 
349
        }
 
350
 
 
351
        return OK;
 
352
}
 
353
 
 
354
 
 
355
 
 
356
 
 
357
 
 
358
void
 
359
print_usage (void)
 
360
{
 
361
        printf ("Usage: %s <host_address>\n", progname);
 
362
}
 
363
 
 
364
 
 
365
 
 
366
 
 
367
 
 
368
void
 
369
print_help (void)
 
370
{
 
371
 
 
372
        print_revision (progname, "$Revision: 1.4 $");
 
373
 
 
374
        printf
 
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");
 
379
 
 
380
        print_usage ();
 
381
 
 
382
        printf
 
383
                ("\nOptions:\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"
 
395
                 "-v, --verbose\n"
 
396
                 "   Show details for command-line debugging (do not use with nagios server)\n"
 
397
                 "-h, --help\n"
 
398
                 "   Print this help screen\n"
 
399
                 "-V, --version\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);
 
405
}