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.c1050
1 files changed, 560 insertions, 490 deletions
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
index 70d6f9fc..6160c2cb 100644
--- a/plugins/check_fping.c
+++ b/plugins/check_fping.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_fping plugin 3 * Monitoring check_fping plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2007 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_disk plugin 10 * This file contains the check_fping plugin
11* 11 *
12* This plugin will use the fping command to ping the specified host for a 12 * This plugin will use the fping command to ping the specified host for a
13* fast check 13 * fast check
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 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 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 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 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/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_fping"; 32const char *progname = "check_fping";
33const char *copyright = "2000-2007"; 33const char *copyright = "2000-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
@@ -38,490 +38,560 @@ const char *email = "devel@monitoring-plugins.org";
38#include "netutils.h" 38#include "netutils.h"
39#include "utils.h" 39#include "utils.h"
40#include <stdbool.h> 40#include <stdbool.h>
41#include "check_fping.d/config.h"
42#include "states.h"
41 43
42enum { 44enum {
43 PACKET_COUNT = 1, 45 PL = 0,
44 PACKET_SIZE = 56, 46 RTA = 1
45 PL = 0,
46 RTA = 1
47}; 47};
48 48
49int textscan (char *buf); 49static mp_state_enum textscan(char *buf, const char * /*server_name*/, bool /*crta_p*/,
50int process_arguments (int, char **); 50 double /*crta*/, bool /*wrta_p*/, double /*wrta*/, bool /*cpl_p*/,
51int get_threshold (char *arg, char *rv[2]); 51 int /*cpl*/, bool /*wpl_p*/, int /*wpl*/, bool /*alive_p*/);
52void print_help (void); 52
53void print_usage (void); 53typedef struct {
54 54 int errorcode;
55char *server_name = NULL; 55 check_fping_config config;
56char *sourceip = NULL; 56} check_fping_config_wrapper;
57char *sourceif = NULL; 57static check_fping_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
58int packet_size = PACKET_SIZE; 58static int get_threshold(char *arg, char *rv[2]);
59int packet_count = PACKET_COUNT; 59static void print_help(void);
60int target_timeout = 0; 60void print_usage(void);
61int packet_interval = 0; 61
62bool verbose = false; 62static bool verbose = false;
63int cpl; 63
64int wpl; 64int main(int argc, char **argv) {
65double crta; 65 setlocale(LC_ALL, "");
66double wrta; 66 bindtextdomain(PACKAGE, LOCALEDIR);
67bool cpl_p = false; 67 textdomain(PACKAGE);
68bool wpl_p = false; 68
69bool alive_p = false; 69 /* Parse extra opts if any */
70bool crta_p = false; 70 argv = np_extra_opts(&argc, argv, progname);
71bool wrta_p = false; 71
72 72 check_fping_config_wrapper tmp_config = process_arguments(argc, argv);
73int 73 if (tmp_config.errorcode == ERROR) {
74main (int argc, char **argv) 74 usage4(_("Could not parse arguments"));
75{ 75 }
76/* normally should be int result = STATE_UNKNOWN; */ 76
77 77 const check_fping_config config = tmp_config.config;
78 int status = STATE_UNKNOWN; 78
79 int result = 0; 79 char *server = NULL;
80 char *fping_prog = NULL; 80 server = strscpy(server, config.server_name);
81 char *server = NULL; 81
82 char *command_line = NULL; 82 char *option_string = "";
83 char *input_buffer = NULL; 83 char *fping_prog = NULL;
84 char *option_string = ""; 84
85 input_buffer = malloc (MAX_INPUT_BUFFER); 85 /* First determine if the target is dualstack or ipv6 only. */
86 86 bool server_is_inet6_addr = is_inet6_addr(server);
87 setlocale (LC_ALL, ""); 87
88 bindtextdomain (PACKAGE, LOCALEDIR); 88 /*
89 textdomain (PACKAGE); 89 * If the user requested -6 OR the user made no assertion and the address is v6 or dualstack
90 90 * -> we use ipv6
91 /* Parse extra opts if any */ 91 * If the user requested -4 OR the user made no assertion and the address is v4 ONLY
92 argv=np_extra_opts (&argc, argv, progname); 92 * -> we use ipv4
93 93 */
94 if (process_arguments (argc, argv) == ERROR) 94 if (address_family == AF_INET6 || (address_family == AF_UNSPEC && server_is_inet6_addr)) {
95 usage4 (_("Could not parse arguments")); 95 xasprintf(&option_string, "%s-6 ", option_string);
96 96 } else {
97 server = strscpy (server, server_name); 97 xasprintf(&option_string, "%s-4 ", option_string);
98 98 }
99 /* compose the command */ 99 fping_prog = strdup(PATH_TO_FPING);
100 if (target_timeout) 100
101 xasprintf(&option_string, "%s-t %d ", option_string, target_timeout); 101 /* compose the command */
102 if (packet_interval) 102 if (config.target_timeout) {
103 xasprintf(&option_string, "%s-p %d ", option_string, packet_interval); 103 xasprintf(&option_string, "%s-t %d ", option_string, config.target_timeout);
104 if (sourceip) 104 }
105 xasprintf(&option_string, "%s-S %s ", option_string, sourceip); 105 if (config.packet_interval) {
106 if (sourceif) 106 xasprintf(&option_string, "%s-p %d ", option_string, config.packet_interval);
107 xasprintf(&option_string, "%s-I %s ", option_string, sourceif); 107 }
108 108 if (config.sourceip) {
109#ifdef PATH_TO_FPING6 109 xasprintf(&option_string, "%s-S %s ", option_string, config.sourceip);
110 if (address_family != AF_INET && is_inet6_addr(server)) 110 }
111 fping_prog = strdup(PATH_TO_FPING6); 111 if (config.sourceif) {
112 else 112 xasprintf(&option_string, "%s-I %s ", option_string, config.sourceif);
113 fping_prog = strdup(PATH_TO_FPING); 113 }
114#else 114 if (config.dontfrag) {
115 fping_prog = strdup(PATH_TO_FPING); 115 xasprintf(&option_string, "%s-M ", option_string);
116#endif 116 }
117 117 if (config.randomize_packet_data) {
118 xasprintf (&command_line, "%s %s-b %d -c %d %s", fping_prog, 118 xasprintf(&option_string, "%s-R ", option_string);
119 option_string, packet_size, packet_count, server); 119 }
120 120
121 if (verbose) 121 if (config.fwmark_set) {
122 printf ("%s\n", command_line); 122 xasprintf(&option_string, "%s--fwmark %u ", option_string, config.fwmark);
123 123 }
124 /* run the command */ 124
125 child_process = spopen (command_line); 125 if (config.icmp_timestamp) {
126 if (child_process == NULL) { 126 xasprintf(&option_string, "%s--icmp-timestamp ", option_string);
127 printf (_("Could not open pipe: %s\n"), command_line); 127 }
128 return STATE_UNKNOWN; 128
129 } 129 if (config.check_source) {
130 130 xasprintf(&option_string, "%s--check-source ", option_string);
131 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); 131 }
132 if (child_stderr == NULL) { 132
133 printf (_("Could not open stderr for %s\n"), command_line); 133 char *command_line = NULL;
134 } 134
135 135 if (config.icmp_timestamp) {
136 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { 136 // no packet size settable for ICMP timestamp
137 if (verbose) 137 xasprintf(&command_line, "%s %s -c %d %s", fping_prog, option_string, config.packet_count,
138 printf ("%s", input_buffer); 138 server);
139 status = max_state (status, textscan (input_buffer)); 139 } else {
140 } 140 xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string,
141 141 config.packet_size, config.packet_count, server);
142 /* If we get anything on STDERR, at least set warning */ 142 }
143 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { 143
144 status = max_state (status, STATE_WARNING); 144 if (verbose) {
145 if (verbose) 145 printf("%s\n", command_line);
146 printf ("%s", input_buffer); 146 }
147 status = max_state (status, textscan (input_buffer)); 147
148 } 148 /* run the command */
149 (void) fclose (child_stderr); 149 child_process = spopen(command_line);
150 150 if (child_process == NULL) {
151 /* close the pipe */ 151 printf(_("Could not open pipe: %s\n"), command_line);
152 result = spclose (child_process); 152 return STATE_UNKNOWN;
153 if (result) { 153 }
154 /* need to use max_state not max */ 154
155 status = max_state (status, STATE_WARNING); 155 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r");
156 } 156 if (child_stderr == NULL) {
157 157 printf(_("Could not open stderr for %s\n"), command_line);
158 if (result > 1 ) { 158 }
159 status = max_state (status, STATE_UNKNOWN); 159
160 if (result == 2) { 160 char *input_buffer = malloc(MAX_INPUT_BUFFER);
161 die (STATE_UNKNOWN, _("FPING UNKNOWN - IP address not found\n")); 161 mp_state_enum status = STATE_UNKNOWN;
162 } 162 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
163 if (result == 3) { 163 if (verbose) {
164 die (STATE_UNKNOWN, _("FPING UNKNOWN - invalid commandline argument\n")); 164 printf("%s", input_buffer);
165 } 165 }
166 if (result == 4) { 166 status = max_state(status, textscan(input_buffer, config.server_name, config.crta_p,
167 die (STATE_UNKNOWN, _("FPING UNKNOWN - failed system call\n")); 167 config.crta, config.wrta_p, config.wrta, config.cpl_p,
168 } 168 config.cpl, config.wpl_p, config.wpl, config.alive_p));
169 169 }
170 } 170
171 171 /* If we get anything on STDERR, at least set warning */
172 printf ("FPING %s - %s\n", state_text (status), server_name); 172 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
173 173 status = max_state(status, STATE_WARNING);
174 return status; 174 if (verbose) {
175 printf("%s", input_buffer);
176 }
177 status = max_state(status, textscan(input_buffer, config.server_name, config.crta_p,
178 config.crta, config.wrta_p, config.wrta, config.cpl_p,
179 config.cpl, config.wpl_p, config.wpl, config.alive_p));
180 }
181 (void)fclose(child_stderr);
182
183 /* close the pipe */
184 int result = spclose(child_process);
185 if (result) {
186 /* need to use max_state not max */
187 status = max_state(status, STATE_WARNING);
188 }
189
190 if (result > 1) {
191 status = max_state(status, STATE_UNKNOWN);
192 if (result == 2) {
193 die(STATE_UNKNOWN, _("FPING UNKNOWN - IP address not found\n"));
194 }
195 if (result == 3) {
196 die(STATE_UNKNOWN, _("FPING UNKNOWN - invalid commandline argument\n"));
197 }
198 if (result == 4) {
199 die(STATE_UNKNOWN, _("FPING UNKNOWN - failed system call\n"));
200 }
201 }
202
203 printf("FPING %s - %s\n", state_text(status), config.server_name);
204
205 return status;
175} 206}
176 207
177 208mp_state_enum textscan(char *buf, const char *server_name, bool crta_p, double crta, bool wrta_p,
178int textscan (char *buf) { 209 double wrta, bool cpl_p, int cpl, bool wpl_p, int wpl, bool alive_p) {
179 char *rtastr = NULL; 210 /* stops testing after the first successful reply. */
180 char *losstr = NULL; 211 double rta;
181 char *xmtstr = NULL; 212 double loss;
182 double loss; 213 char *rtastr = NULL;
183 double rta; 214 if (alive_p && strstr(buf, "avg, 0% loss)")) {
184 double xmt; 215 rtastr = strstr(buf, "ms (");
185 int status = STATE_UNKNOWN; 216 rtastr = 1 + index(rtastr, '(');
186 217 rta = strtod(rtastr, NULL);
187 /* stops testing after the first successful reply. */ 218 loss = strtod("0", NULL);
188 if (alive_p && strstr(buf, "avg, 0% loss)")) { 219 die(STATE_OK, _("FPING %s - %s (rta=%f ms)|%s\n"), state_text(STATE_OK), server_name, rta,
189 rtastr = strstr (buf, "ms ("); 220 /* No loss since we only waited for the first reply
190 rtastr = 1 + index(rtastr, '('); 221 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), */
191 rta = strtod(rtastr, NULL); 222 fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0,
192 loss=strtod("0",NULL); 223 false, 0));
193 die (STATE_OK, 224 }
194 _("FPING %s - %s (rta=%f ms)|%s\n"), 225
195 state_text (STATE_OK), server_name,rta, 226 mp_state_enum status = STATE_UNKNOWN;
196 /* No loss since we only waited for the first reply 227 char *xmtstr = NULL;
197 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), */ 228 double xmt;
198 fperfdata ("rta", rta/1.0e3, "s", wrta_p, wrta/1.0e3, crta_p, crta/1.0e3, true, 0, false, 0)); 229 char *losstr = NULL;
199 } 230 if (strstr(buf, "not found")) {
200 231 die(STATE_CRITICAL, _("FPING UNKNOWN - %s not found\n"), server_name);
201 if (strstr (buf, "not found")) { 232
202 die (STATE_CRITICAL, _("FPING UNKNOWN - %s not found\n"), server_name); 233 } else if (strstr(buf, "is unreachable") || strstr(buf, "Unreachable")) {
203 234 die(STATE_CRITICAL, _("FPING CRITICAL - %s is unreachable\n"), "host");
204 } 235
205 else if (strstr (buf, "is unreachable") || strstr (buf, "Unreachable")) { 236 } else if (strstr(buf, "Operation not permitted") || strstr(buf, "No such device")) {
206 die (STATE_CRITICAL, _("FPING CRITICAL - %s is unreachable\n"), 237 die(STATE_UNKNOWN, _("FPING UNKNOWN - %s parameter error\n"), "host");
207 "host"); 238 } else if (strstr(buf, "is down")) {
208 239 die(STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name);
209 } 240
210 else if (strstr (buf, "Operation not permitted") || strstr (buf, "No such device") ) { 241 } else if (strstr(buf, "is alive")) {
211 die (STATE_UNKNOWN, _("FPING UNKNOWN - %s parameter error\n"), 242 status = STATE_OK;
212 "host"); 243
213 } 244 } else if (strstr(buf, "xmt/rcv/%loss") && strstr(buf, "min/avg/max")) {
214 else if (strstr (buf, "is down")) { 245 losstr = strstr(buf, "=");
215 die (STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name); 246 losstr = 1 + strstr(losstr, "/");
216 247 losstr = 1 + strstr(losstr, "/");
217 } 248 rtastr = strstr(buf, "min/avg/max");
218 else if (strstr (buf, "is alive")) { 249 rtastr = strstr(rtastr, "=");
219 status = STATE_OK; 250 rtastr = 1 + index(rtastr, '/');
220 251 loss = strtod(losstr, NULL);
221 } 252 rta = strtod(rtastr, NULL);
222 else if (strstr (buf, "xmt/rcv/%loss") && strstr (buf, "min/avg/max")) { 253 if (cpl_p && loss > cpl) {
223 losstr = strstr (buf, "="); 254 status = STATE_CRITICAL;
224 losstr = 1 + strstr (losstr, "/"); 255 } else if (crta_p && rta > crta) {
225 losstr = 1 + strstr (losstr, "/"); 256 status = STATE_CRITICAL;
226 rtastr = strstr (buf, "min/avg/max"); 257 } else if (wpl_p && loss > wpl) {
227 rtastr = strstr (rtastr, "="); 258 status = STATE_WARNING;
228 rtastr = 1 + index (rtastr, '/'); 259 } else if (wrta_p && rta > wrta) {
229 loss = strtod (losstr, NULL); 260 status = STATE_WARNING;
230 rta = strtod (rtastr, NULL); 261 } else {
231 if (cpl_p && loss > cpl) 262 status = STATE_OK;
232 status = STATE_CRITICAL; 263 }
233 else if (crta_p && rta > crta) 264 die(status, _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), state_text(status),
234 status = STATE_CRITICAL; 265 server_name, loss, rta,
235 else if (wpl_p && loss > wpl) 266 perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, false, 0, false, 0),
236 status = STATE_WARNING; 267 fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0,
237 else if (wrta_p && rta > wrta) 268 false, 0));
238 status = STATE_WARNING; 269
239 else 270 } else if (strstr(buf, "xmt/rcv/%loss")) {
240 status = STATE_OK; 271 /* no min/max/avg if host was unreachable in fping v2.2.b1 */
241 die (status, 272 /* in v2.4b2: 10.99.0.1 : xmt/rcv/%loss = 0/0/0% */
242 _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), 273 losstr = strstr(buf, "=");
243 state_text (status), server_name, loss, rta, 274 xmtstr = 1 + losstr;
244 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), 275 xmt = strtod(xmtstr, NULL);
245 fperfdata ("rta", rta/1.0e3, "s", wrta_p, wrta/1.0e3, crta_p, crta/1.0e3, true, 0, false, 0)); 276 if (xmt == 0) {
246 277 die(STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name);
247 } 278 }
248 else if(strstr (buf, "xmt/rcv/%loss") ) { 279 losstr = 1 + strstr(losstr, "/");
249 /* no min/max/avg if host was unreachable in fping v2.2.b1 */ 280 losstr = 1 + strstr(losstr, "/");
250 /* in v2.4b2: 10.99.0.1 : xmt/rcv/%loss = 0/0/0% */ 281 loss = strtod(losstr, NULL);
251 losstr = strstr (buf, "="); 282 if (atoi(losstr) == 100) {
252 xmtstr = 1 + losstr; 283 status = STATE_CRITICAL;
253 xmt = strtod (xmtstr, NULL); 284 } else if (cpl_p && loss > cpl) {
254 if(xmt == 0) 285 status = STATE_CRITICAL;
255 die (STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name); 286 } else if (wpl_p && loss > wpl) {
256 losstr = 1 + strstr (losstr, "/"); 287 status = STATE_WARNING;
257 losstr = 1 + strstr (losstr, "/"); 288 } else {
258 loss = strtod (losstr, NULL); 289 status = STATE_OK;
259 if (atoi(losstr) == 100) 290 }
260 status = STATE_CRITICAL; 291 /* loss=%.0f%%;%d;%d;0;100 */
261 else if (cpl_p && loss > cpl) 292 die(status, _("FPING %s - %s (loss=%.0f%% )|%s\n"), state_text(status), server_name, loss,
262 status = STATE_CRITICAL; 293 perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, false, 0, false, 0));
263 else if (wpl_p && loss > wpl) 294
264 status = STATE_WARNING; 295 } else {
265 else 296 status = max_state(status, STATE_WARNING);
266 status = STATE_OK; 297 }
267 /* loss=%.0f%%;%d;%d;0;100 */ 298
268 die (status, _("FPING %s - %s (loss=%.0f%% )|%s\n"), 299 return status;
269 state_text (status), server_name, loss ,
270 perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100));
271
272 }
273 else {
274 status = max_state (status, STATE_WARNING);
275 }
276
277 return status;
278} 300}
279 301
280
281
282/* process command-line arguments */ 302/* process command-line arguments */
283int 303check_fping_config_wrapper process_arguments(int argc, char **argv) {
284process_arguments (int argc, char **argv) 304 enum {
285{ 305 FWMARK_OPT = CHAR_MAX + 1,
286 int c; 306 ICMP_TIMESTAMP_OPT,
287 char *rv[2]; 307 CHECK_SOURCE_OPT,
288 308 };
289 int option = 0; 309 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
290 static struct option longopts[] = { 310 {"sourceip", required_argument, 0, 'S'},
291 {"hostname", required_argument, 0, 'H'}, 311 {"sourceif", required_argument, 0, 'I'},
292 {"sourceip", required_argument, 0, 'S'}, 312 {"critical", required_argument, 0, 'c'},
293 {"sourceif", required_argument, 0, 'I'}, 313 {"warning", required_argument, 0, 'w'},
294 {"critical", required_argument, 0, 'c'}, 314 {"alive", no_argument, 0, 'a'},
295 {"warning", required_argument, 0, 'w'}, 315 {"bytes", required_argument, 0, 'b'},
296 {"alive", no_argument, 0, 'a'}, 316 {"number", required_argument, 0, 'n'},
297 {"bytes", required_argument, 0, 'b'}, 317 {"target-timeout", required_argument, 0, 'T'},
298 {"number", required_argument, 0, 'n'}, 318 {"interval", required_argument, 0, 'i'},
299 {"target-timeout", required_argument, 0, 'T'}, 319 {"verbose", no_argument, 0, 'v'},
300 {"interval", required_argument, 0, 'i'}, 320 {"version", no_argument, 0, 'V'},
301 {"verbose", no_argument, 0, 'v'}, 321 {"help", no_argument, 0, 'h'},
302 {"version", no_argument, 0, 'V'}, 322 {"use-ipv4", no_argument, 0, '4'},
303 {"help", no_argument, 0, 'h'}, 323 {"use-ipv6", no_argument, 0, '6'},
304 {"use-ipv4", no_argument, 0, '4'}, 324 {"dontfrag", no_argument, 0, 'M'},
305 {"use-ipv6", no_argument, 0, '6'}, 325 {"random", no_argument, 0, 'R'},
306 {0, 0, 0, 0} 326#ifdef FPING_VERSION_5_2_OR_HIGHER
307 }; 327 // only available with fping version >= 5.2
308 328 {"fwmark", required_argument, NULL, FWMARK_OPT},
309 rv[PL] = NULL; 329# ifdef FPING_VERSION_5_3_OR_HIGHER
310 rv[RTA] = NULL; 330 // only available with fping version >= 5.3
311 331 {"icmp-timestamp", no_argument, NULL, ICMP_TIMESTAMP_OPT},
312 if (argc < 2) 332 {"check-source", no_argument, NULL, CHECK_SOURCE_OPT},
313 return ERROR; 333# endif
314
315 if (!is_option (argv[1])) {
316 server_name = argv[1];
317 argv[1] = argv[0];
318 argv = &argv[1];
319 argc--;
320 }
321
322 while (1) {
323 c = getopt_long (argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:46", longopts, &option);
324
325 if (c == -1 || c == EOF || c == 1)
326 break;
327
328 switch (c) {
329 case '?': /* print short usage statement if args not parsable */
330 usage5 ();
331 case 'a': /* host alive mode */
332 alive_p = true;
333 break;
334 case 'h': /* help */
335 print_help ();
336 exit (STATE_UNKNOWN);
337 case 'V': /* version */
338 print_revision (progname, NP_VERSION);
339 exit (STATE_UNKNOWN);
340 case 'v': /* verbose mode */
341 verbose = true;
342 break;
343 case 'H': /* hostname */
344 if (is_host (optarg) == false) {
345 usage2 (_("Invalid hostname/address"), optarg);
346 }
347 server_name = strscpy (server_name, optarg);
348 break;
349 case 'S': /* sourceip */
350 if (is_host (optarg) == false) {
351 usage2 (_("Invalid hostname/address"), optarg);
352 }
353 sourceip = strscpy (sourceip, optarg);
354 break;
355 case 'I': /* sourceip */
356 sourceif = strscpy (sourceif, optarg);
357 break;
358 case '4': /* IPv4 only */
359 address_family = AF_INET;
360 break;
361 case '6': /* IPv6 only */
362#ifdef USE_IPV6
363 address_family = AF_INET6;
364#else
365 usage (_("IPv6 support not available\n"));
366#endif 334#endif
367 break; 335 {0, 0, 0, 0}};
368 case 'c':
369 get_threshold (optarg, rv);
370 if (rv[RTA]) {
371 crta = strtod (rv[RTA], NULL);
372 crta_p = true;
373 rv[RTA] = NULL;
374 }
375 if (rv[PL]) {
376 cpl = atoi (rv[PL]);
377 cpl_p = true;
378 rv[PL] = NULL;
379 }
380 break;
381 case 'w':
382 get_threshold (optarg, rv);
383 if (rv[RTA]) {
384 wrta = strtod (rv[RTA], NULL);
385 wrta_p = true;
386 rv[RTA] = NULL;
387 }
388 if (rv[PL]) {
389 wpl = atoi (rv[PL]);
390 wpl_p = true;
391 rv[PL] = NULL;
392 }
393 break;
394 case 'b': /* bytes per packet */
395 if (is_intpos (optarg))
396 packet_size = atoi (optarg);
397 else
398 usage (_("Packet size must be a positive integer"));
399 break;
400 case 'n': /* number of packets */
401 if (is_intpos (optarg))
402 packet_count = atoi (optarg);
403 else
404 usage (_("Packet count must be a positive integer"));
405 break;
406 case 'T': /* timeout in msec */
407 if (is_intpos (optarg))
408 target_timeout = atoi (optarg);
409 else
410 usage (_("Target timeout must be a positive integer"));
411 break;
412 case 'i': /* interval in msec */
413 if (is_intpos (optarg))
414 packet_interval = atoi (optarg);
415 else
416 usage (_("Interval must be a positive integer"));
417 break;
418 }
419 }
420
421 if (server_name == NULL)
422 usage4 (_("Hostname was not supplied"));
423
424 return OK;
425}
426
427 336
428int 337 char *rv[2];
429get_threshold (char *arg, char *rv[2]) 338 rv[PL] = NULL;
430{ 339 rv[RTA] = NULL;
431 char *arg1 = NULL;
432 char *arg2 = NULL;
433
434 arg1 = strscpy (arg1, arg);
435 if (strpbrk (arg1, ",:"))
436 arg2 = 1 + strpbrk (arg1, ",:");
437
438 if (arg2) {
439 arg1[strcspn (arg1, ",:")] = 0;
440 if (strstr (arg1, "%") && strstr (arg2, "%"))
441 die (STATE_UNKNOWN,
442 _("%s: Only one threshold may be packet loss (%s)\n"), progname,
443 arg);
444 if (!strstr (arg1, "%") && !strstr (arg2, "%"))
445 die (STATE_UNKNOWN,
446 _("%s: Only one threshold must be packet loss (%s)\n"),
447 progname, arg);
448 }
449
450 if (arg2 && strstr (arg2, "%")) {
451 rv[PL] = arg2;
452 rv[RTA] = arg1;
453 }
454 else if (arg2) {
455 rv[PL] = arg1;
456 rv[RTA] = arg2;
457 }
458 else if (strstr (arg1, "%")) {
459 rv[PL] = arg1;
460 }
461 else {
462 rv[RTA] = arg1;
463 }
464
465 return OK;
466}
467 340
341 int option = 0;
468 342
469void print_help (void) { 343 check_fping_config_wrapper result = {
344 .errorcode = OK,
345 .config = check_fping_config_init(),
346 };
470 347
471 print_revision (progname, NP_VERSION); 348 if (argc < 2) {
349 result.errorcode = ERROR;
350 return result;
351 }
472 352
473 printf ("Copyright (c) 1999 Didi Rieder <adrieder@sbox.tu-graz.ac.at>\n"); 353 if (!is_option(argv[1])) {
474 printf (COPYRIGHT, copyright, email); 354 result.config.server_name = argv[1];
355 argv[1] = argv[0];
356 argv = &argv[1];
357 argc--;
358 }
475 359
476 printf ("%s\n", _("This plugin will use the fping command to ping the specified host for a fast check")); 360 while (true) {
361 int option_index =
362 getopt_long(argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:M:R:46", longopts, &option);
477 363
478 printf ("%s\n", _("Note that it is necessary to set the suid flag on fping.")); 364 if (option_index == -1 || option_index == EOF || option_index == 1) {
365 break;
366 }
479 367
480 printf ("\n\n"); 368 switch (option_index) {
369 case '?': /* print short usage statement if args not parsable */
370 usage5();
371 case 'a': /* host alive mode */
372 result.config.alive_p = true;
373 break;
374 case 'h': /* help */
375 print_help();
376 exit(STATE_UNKNOWN);
377 case 'V': /* version */
378 print_revision(progname, NP_VERSION);
379 exit(STATE_UNKNOWN);
380 case 'v': /* verbose mode */
381 verbose = true;
382 break;
383 case 'H': /* hostname */
384 if (!is_host(optarg)) {
385 usage2(_("Invalid hostname/address"), optarg);
386 }
387 result.config.server_name = optarg;
388 break;
389 case 'S': /* sourceip */
390 if (!is_host(optarg)) {
391 usage2(_("Invalid hostname/address"), optarg);
392 }
393 result.config.sourceip = optarg;
394 break;
395 case 'I': /* sourceip */
396 result.config.sourceif = optarg;
397 break;
398 case '4': /* IPv4 only */
399 address_family = AF_INET;
400 break;
401 case '6': /* IPv6 only */
402 address_family = AF_INET6;
403 break;
404 case 'c':
405 get_threshold(optarg, rv);
406 if (rv[RTA]) {
407 result.config.crta = strtod(rv[RTA], NULL);
408 result.config.crta_p = true;
409 rv[RTA] = NULL;
410 }
411 if (rv[PL]) {
412 result.config.cpl = atoi(rv[PL]);
413 result.config.cpl_p = true;
414 rv[PL] = NULL;
415 }
416 break;
417 case 'w':
418 get_threshold(optarg, rv);
419 if (rv[RTA]) {
420 result.config.wrta = strtod(rv[RTA], NULL);
421 result.config.wrta_p = true;
422 rv[RTA] = NULL;
423 }
424 if (rv[PL]) {
425 result.config.wpl = atoi(rv[PL]);
426 result.config.wpl_p = true;
427 rv[PL] = NULL;
428 }
429 break;
430 case 'b': /* bytes per packet */
431 if (is_intpos(optarg)) {
432 result.config.packet_size = atoi(optarg);
433 } else {
434 usage(_("Packet size must be a positive integer"));
435 }
436 break;
437 case 'n': /* number of packets */
438 if (is_intpos(optarg)) {
439 result.config.packet_count = atoi(optarg);
440 } else {
441 usage(_("Packet count must be a positive integer"));
442 }
443 break;
444 case 'T': /* timeout in msec */
445 if (is_intpos(optarg)) {
446 result.config.target_timeout = atoi(optarg);
447 } else {
448 usage(_("Target timeout must be a positive integer"));
449 }
450 break;
451 case 'i': /* interval in msec */
452 if (is_intpos(optarg)) {
453 result.config.packet_interval = atoi(optarg);
454 } else {
455 usage(_("Interval must be a positive integer"));
456 }
457 break;
458 case 'R':
459 result.config.randomize_packet_data = true;
460 break;
461 case 'M':
462 result.config.dontfrag = true;
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;
478 }
479 }
481 480
482 print_usage (); 481 if (result.config.server_name == NULL) {
482 usage4(_("Hostname was not supplied"));
483 }
483 484
484 printf (UT_HELP_VRSN); 485 return result;
485 printf (UT_EXTRA_OPTS); 486}
486 487
487 printf (UT_IPv46); 488int get_threshold(char *arg, char *rv[2]) {
489 char *arg2 = NULL;
490
491 char *arg1 = strdup(arg);
492 if (strpbrk(arg1, ",:")) {
493 arg2 = 1 + strpbrk(arg1, ",:");
494 }
495
496 if (arg2) {
497 arg1[strcspn(arg1, ",:")] = 0;
498 if (strstr(arg1, "%") && strstr(arg2, "%")) {
499 die(STATE_UNKNOWN, _("%s: Only one threshold may be packet loss (%s)\n"), progname,
500 arg);
501 }
502 if (!strstr(arg1, "%") && !strstr(arg2, "%")) {
503 die(STATE_UNKNOWN, _("%s: Only one threshold must be packet loss (%s)\n"), progname,
504 arg);
505 }
506 }
507
508 if (arg2 && strstr(arg2, "%")) {
509 rv[PL] = arg2;
510 rv[RTA] = arg1;
511 } else if (arg2) {
512 rv[PL] = arg1;
513 rv[RTA] = arg2;
514 } else if (strstr(arg1, "%")) {
515 rv[PL] = arg1;
516 } else {
517 rv[RTA] = arg1;
518 }
519
520 return OK;
521}
488 522
489 printf (" %s\n", "-H, --hostname=HOST"); 523void print_help(void) {
490 printf (" %s\n", _("name or IP Address of host to ping (IP Address bypasses name lookup, reducing system load)")); 524
491 printf (" %s\n", "-w, --warning=THRESHOLD"); 525 print_revision(progname, NP_VERSION);
492 printf (" %s\n", _("warning threshold pair")); 526
493 printf (" %s\n", "-c, --critical=THRESHOLD"); 527 printf("Copyright (c) 1999 Didi Rieder <adrieder@sbox.tu-graz.ac.at>\n");
494 printf (" %s\n", _("critical threshold pair")); 528 printf(COPYRIGHT, copyright, email);
495 printf (" %s\n", "-a, --alive"); 529
496 printf (" %s\n", _("Return OK after first successful reply")); 530 printf("%s\n",
497 printf (" %s\n", "-b, --bytes=INTEGER"); 531 _("This plugin will use the fping command to ping the specified host for a fast check"));
498 printf (" %s (default: %d)\n", _("size of ICMP packet"),PACKET_SIZE); 532
499 printf (" %s\n", "-n, --number=INTEGER"); 533 printf("%s\n", _("Note that it is necessary to set the suid flag on fping."));
500 printf (" %s (default: %d)\n", _("number of ICMP packets to send"),PACKET_COUNT); 534
501 printf (" %s\n", "-T, --target-timeout=INTEGER"); 535 printf("\n\n");
502 printf (" %s (default: fping's default for -t)\n", _("Target timeout (ms)")); 536
503 printf (" %s\n", "-i, --interval=INTEGER"); 537 print_usage();
504 printf (" %s (default: fping's default for -p)\n", _("Interval (ms) between sending packets")); 538
505 printf (" %s\n", "-S, --sourceip=HOST"); 539 printf(UT_HELP_VRSN);
506 printf (" %s\n", _("name or IP Address of sourceip")); 540 printf(UT_EXTRA_OPTS);
507 printf (" %s\n", "-I, --sourceif=IF"); 541
508 printf (" %s\n", _("source interface name")); 542 printf(UT_IPv46);
509 printf (UT_VERBOSE); 543
510 printf ("\n"); 544 printf(" %s\n", "-H, --hostname=HOST");
511 printf (" %s\n", _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)")); 545 printf(" %s\n", _("name or IP Address of host to ping (IP Address bypasses name lookup, "
512 printf (" %s\n", _("which triggers a WARNING or CRITICAL state, and <pl> is the percentage of")); 546 "reducing system load)"));
513 printf (" %s\n", _("packet loss to trigger an alarm state.")); 547 printf(" %s\n", "-w, --warning=THRESHOLD");
548 printf(" %s\n", _("warning threshold pair"));
549 printf(" %s\n", "-c, --critical=THRESHOLD");
550 printf(" %s\n", _("critical threshold pair"));
551 printf(" %s\n", "-a, --alive");
552 printf(" %s\n", _("Return OK after first successful reply"));
553 printf(" %s\n", "-b, --bytes=INTEGER");
554 printf(" %s (default: %d)\n", _("size of ICMP packet"), PACKET_SIZE);
555 printf(" %s\n", "-n, --number=INTEGER");
556 printf(" %s (default: %d)\n", _("number of ICMP packets to send"), PACKET_COUNT);
557 printf(" %s\n", "-T, --target-timeout=INTEGER");
558 printf(" %s (default: fping's default for -t)\n", _("Target timeout (ms)"));
559 printf(" %s\n", "-i, --interval=INTEGER");
560 printf(" %s (default: fping's default for -p)\n",
561 _("Interval (ms) between sending packets"));
562 printf(" %s\n", "-S, --sourceip=HOST");
563 printf(" %s\n", _("name or IP Address of sourceip"));
564 printf(" %s\n", "-I, --sourceif=IF");
565 printf(" %s\n", _("source interface name"));
566 printf(" %s\n", "-M, --dontfrag");
567 printf(" %s\n", _("set the Don't Fragment flag"));
568 printf(" %s\n", "-R, --random");
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
580 printf(UT_VERBOSE);
581 printf("\n");
582 printf(" %s\n",
583 _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)"));
584 printf(" %s\n", _("which triggers a WARNING or CRITICAL state, and <pl> is the percentage of"));
585 printf(" %s\n", _("packet loss to trigger an alarm state."));
514 586
515 printf ("\n"); 587 printf("\n");
516 printf (" %s\n", _("IPv4 is used by default. Specify -6 to use IPv6.")); 588 printf(" %s\n", _("IPv4 is used by default. Specify -6 to use IPv6."));
517 589
518 printf (UT_SUPPORT); 590 printf(UT_SUPPORT);
519} 591}
520 592
521 593void print_usage(void) {
522void 594 printf("%s\n", _("Usage:"));
523print_usage (void) 595 printf(" %s <host_address> -w limit -c limit [-b size] [-n number] [-T number] [-i number]\n",
524{ 596 progname);
525 printf ("%s\n", _("Usage:"));
526 printf (" %s <host_address> -w limit -c limit [-b size] [-n number] [-T number] [-i number]\n", progname);
527} 597}