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.c340
1 files changed, 207 insertions, 133 deletions
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
index c1d03ece..8018e06d 100644
--- a/plugins/check_fping.c
+++ b/plugins/check_fping.c
@@ -38,52 +38,29 @@ 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,
44 PACKET_SIZE = 56,
45 PL = 0, 45 PL = 0,
46 RTA = 1 46 RTA = 1
47}; 47};
48 48
49static int textscan(char *buf); 49static mp_state_enum textscan(char *buf, const char * /*server_name*/, bool /*crta_p*/, double /*crta*/, bool /*wrta_p*/, double /*wrta*/,
50static int process_arguments(int /*argc*/, char ** /*argv*/); 50 bool /*cpl_p*/, int /*cpl*/, bool /*wpl_p*/, int /*wpl*/, bool /*alive_p*/);
51
52typedef struct {
53 int errorcode;
54 check_fping_config config;
55} check_fping_config_wrapper;
56static check_fping_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
51static int get_threshold(char *arg, char *rv[2]); 57static int get_threshold(char *arg, char *rv[2]);
52static void print_help(void); 58static void print_help(void);
53void print_usage(void); 59void print_usage(void);
54 60
55static char *server_name = NULL;
56static char *sourceip = NULL;
57static char *sourceif = NULL;
58static int packet_size = PACKET_SIZE;
59static int packet_count = PACKET_COUNT;
60static int target_timeout = 0;
61static int packet_interval = 0;
62static bool verbose = false; 61static bool verbose = false;
63static bool dontfrag = false;
64static bool randomize_packet_data = false;
65static int cpl;
66static int wpl;
67static double crta;
68static double wrta;
69static bool cpl_p = false;
70static bool wpl_p = false;
71static bool alive_p = false;
72static bool crta_p = false;
73static bool wrta_p = false;
74 62
75int main(int argc, char **argv) { 63int main(int argc, char **argv) {
76 /* normally should be int result = STATE_UNKNOWN; */
77
78 int status = STATE_UNKNOWN;
79 int result = 0;
80 char *fping_prog = NULL;
81 char *server = NULL;
82 char *command_line = NULL;
83 char *input_buffer = NULL;
84 char *option_string = "";
85 input_buffer = malloc(MAX_INPUT_BUFFER);
86
87 setlocale(LC_ALL, ""); 64 setlocale(LC_ALL, "");
88 bindtextdomain(PACKAGE, LOCALEDIR); 65 bindtextdomain(PACKAGE, LOCALEDIR);
89 textdomain(PACKAGE); 66 textdomain(PACKAGE);
@@ -91,39 +68,79 @@ int main(int argc, char **argv) {
91 /* Parse extra opts if any */ 68 /* Parse extra opts if any */
92 argv = np_extra_opts(&argc, argv, progname); 69 argv = np_extra_opts(&argc, argv, progname);
93 70
94 if (process_arguments(argc, argv) == ERROR) 71 check_fping_config_wrapper tmp_config = process_arguments(argc, argv);
72 if (tmp_config.errorcode == ERROR) {
95 usage4(_("Could not parse arguments")); 73 usage4(_("Could not parse arguments"));
74 }
75
76 const check_fping_config config = tmp_config.config;
77
78 char *server = NULL;
79 server = strscpy(server, config.server_name);
96 80
97 server = strscpy(server, server_name); 81 char *option_string = "";
82 char *fping_prog = NULL;
83
84 /* First determine if the target is dualstack or ipv6 only. */
85 bool server_is_inet6_addr = is_inet6_addr(server);
86
87 /*
88 * If the user requested -6 OR the user made no assertion and the address is v6 or dualstack
89 * -> we use ipv6
90 * If the user requested -4 OR the user made no assertion and the address is v4 ONLY
91 * -> we use ipv4
92 */
93 if (address_family == AF_INET6 || (address_family == AF_UNSPEC && server_is_inet6_addr)) {
94 xasprintf(&option_string, "%s-6 ", option_string);
95 } else {
96 xasprintf(&option_string, "%s-4 ", option_string);
97 }
98 fping_prog = strdup(PATH_TO_FPING);
98 99
99 /* compose the command */ 100 /* compose the command */
100 if (target_timeout) 101 if (config.target_timeout) {
101 xasprintf(&option_string, "%s-t %d ", option_string, target_timeout); 102 xasprintf(&option_string, "%s-t %d ", option_string, config.target_timeout);
102 if (packet_interval) 103 }
103 xasprintf(&option_string, "%s-p %d ", option_string, packet_interval); 104 if (config.packet_interval) {
104 if (sourceip) 105 xasprintf(&option_string, "%s-p %d ", option_string, config.packet_interval);
105 xasprintf(&option_string, "%s-S %s ", option_string, sourceip); 106 }
106 if (sourceif) 107 if (config.sourceip) {
107 xasprintf(&option_string, "%s-I %s ", option_string, sourceif); 108 xasprintf(&option_string, "%s-S %s ", option_string, config.sourceip);
108 if (dontfrag) 109 }
110 if (config.sourceif) {
111 xasprintf(&option_string, "%s-I %s ", option_string, config.sourceif);
112 }
113 if (config.dontfrag) {
109 xasprintf(&option_string, "%s-M ", option_string); 114 xasprintf(&option_string, "%s-M ", option_string);
110 if (randomize_packet_data) 115 }
116 if (config.randomize_packet_data) {
111 xasprintf(&option_string, "%s-R ", option_string); 117 xasprintf(&option_string, "%s-R ", option_string);
118 }
112 119
120 if (config.fwmark_set) {
121 xasprintf(&option_string, "%s--fwmark %u ", option_string, config.fwmark);
122 }
113 123
114#ifdef PATH_TO_FPING6 124 if (config.icmp_timestamp) {
115 if (address_family != AF_INET && is_inet6_addr(server)) 125 xasprintf(&option_string, "%s--icmp-timestamp ", option_string);
116 fping_prog = strdup(PATH_TO_FPING6); 126 }
117 else
118 fping_prog = strdup(PATH_TO_FPING);
119#else
120 fping_prog = strdup(PATH_TO_FPING);
121#endif
122 127
123 xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string, packet_size, packet_count, server); 128 if (config.check_source) {
129 xasprintf(&option_string, "%s--check-source ", option_string);
130 }
131
132 char *command_line = NULL;
124 133
125 if (verbose) 134 if (config.icmp_timestamp) {
135 // no packet size settable for ICMP timestamp
136 xasprintf(&command_line, "%s %s -c %d %s", fping_prog, option_string, config.packet_count, server);
137 } else {
138 xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string, config.packet_size, config.packet_count, server);
139 }
140
141 if (verbose) {
126 printf("%s\n", command_line); 142 printf("%s\n", command_line);
143 }
127 144
128 /* run the command */ 145 /* run the command */
129 child_process = spopen(command_line); 146 child_process = spopen(command_line);
@@ -137,23 +154,29 @@ int main(int argc, char **argv) {
137 printf(_("Could not open stderr for %s\n"), command_line); 154 printf(_("Could not open stderr for %s\n"), command_line);
138 } 155 }
139 156
157 char *input_buffer = malloc(MAX_INPUT_BUFFER);
158 mp_state_enum status = STATE_UNKNOWN;
140 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { 159 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
141 if (verbose) 160 if (verbose) {
142 printf("%s", input_buffer); 161 printf("%s", input_buffer);
143 status = max_state(status, textscan(input_buffer)); 162 }
163 status = max_state(status, textscan(input_buffer, config.server_name, config.crta_p, config.crta, config.wrta_p, config.wrta,
164 config.cpl_p, config.cpl, config.wpl_p, config.wpl, config.alive_p));
144 } 165 }
145 166
146 /* If we get anything on STDERR, at least set warning */ 167 /* If we get anything on STDERR, at least set warning */
147 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { 168 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
148 status = max_state(status, STATE_WARNING); 169 status = max_state(status, STATE_WARNING);
149 if (verbose) 170 if (verbose) {
150 printf("%s", input_buffer); 171 printf("%s", input_buffer);
151 status = max_state(status, textscan(input_buffer)); 172 }
173 status = max_state(status, textscan(input_buffer, config.server_name, config.crta_p, config.crta, config.wrta_p, config.wrta,
174 config.cpl_p, config.cpl, config.wpl_p, config.wpl, config.alive_p));
152 } 175 }
153 (void)fclose(child_stderr); 176 (void)fclose(child_stderr);
154 177
155 /* close the pipe */ 178 /* close the pipe */
156 result = spclose(child_process); 179 int result = spclose(child_process);
157 if (result) { 180 if (result) {
158 /* need to use max_state not max */ 181 /* need to use max_state not max */
159 status = max_state(status, STATE_WARNING); 182 status = max_state(status, STATE_WARNING);
@@ -172,21 +195,17 @@ int main(int argc, char **argv) {
172 } 195 }
173 } 196 }
174 197
175 printf("FPING %s - %s\n", state_text(status), server_name); 198 printf("FPING %s - %s\n", state_text(status), config.server_name);
176 199
177 return status; 200 return status;
178} 201}
179 202
180int textscan(char *buf) { 203mp_state_enum textscan(char *buf, const char *server_name, bool crta_p, double crta, bool wrta_p, double wrta, bool cpl_p, int cpl,
181 char *rtastr = NULL; 204 bool wpl_p, int wpl, bool alive_p) {
182 char *losstr = NULL;
183 char *xmtstr = NULL;
184 double loss;
185 double rta;
186 double xmt;
187 int status = STATE_UNKNOWN;
188
189 /* stops testing after the first successful reply. */ 205 /* stops testing after the first successful reply. */
206 double rta;
207 double loss;
208 char *rtastr = NULL;
190 if (alive_p && strstr(buf, "avg, 0% loss)")) { 209 if (alive_p && strstr(buf, "avg, 0% loss)")) {
191 rtastr = strstr(buf, "ms ("); 210 rtastr = strstr(buf, "ms (");
192 rtastr = 1 + index(rtastr, '('); 211 rtastr = 1 + index(rtastr, '(');
@@ -198,6 +217,10 @@ int textscan(char *buf) {
198 fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, false, 0)); 217 fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, false, 0));
199 } 218 }
200 219
220 mp_state_enum status = STATE_UNKNOWN;
221 char *xmtstr = NULL;
222 double xmt;
223 char *losstr = NULL;
201 if (strstr(buf, "not found")) { 224 if (strstr(buf, "not found")) {
202 die(STATE_CRITICAL, _("FPING UNKNOWN - %s not found\n"), server_name); 225 die(STATE_CRITICAL, _("FPING UNKNOWN - %s not found\n"), server_name);
203 226
@@ -221,18 +244,19 @@ int textscan(char *buf) {
221 rtastr = 1 + index(rtastr, '/'); 244 rtastr = 1 + index(rtastr, '/');
222 loss = strtod(losstr, NULL); 245 loss = strtod(losstr, NULL);
223 rta = strtod(rtastr, NULL); 246 rta = strtod(rtastr, NULL);
224 if (cpl_p && loss > cpl) 247 if (cpl_p && loss > cpl) {
225 status = STATE_CRITICAL; 248 status = STATE_CRITICAL;
226 else if (crta_p && rta > crta) 249 } else if (crta_p && rta > crta) {
227 status = STATE_CRITICAL; 250 status = STATE_CRITICAL;
228 else if (wpl_p && loss > wpl) 251 } else if (wpl_p && loss > wpl) {
229 status = STATE_WARNING; 252 status = STATE_WARNING;
230 else if (wrta_p && rta > wrta) 253 } else if (wrta_p && rta > wrta) {
231 status = STATE_WARNING; 254 status = STATE_WARNING;
232 else 255 } else {
233 status = STATE_OK; 256 status = STATE_OK;
257 }
234 die(status, _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), state_text(status), server_name, loss, rta, 258 die(status, _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), state_text(status), server_name, loss, rta,
235 perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100), 259 perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, false, 0, false, 0),
236 fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, false, 0)); 260 fperfdata("rta", rta / 1.0e3, "s", wrta_p, wrta / 1.0e3, crta_p, crta / 1.0e3, true, 0, false, 0));
237 261
238 } else if (strstr(buf, "xmt/rcv/%loss")) { 262 } else if (strstr(buf, "xmt/rcv/%loss")) {
@@ -241,22 +265,24 @@ int textscan(char *buf) {
241 losstr = strstr(buf, "="); 265 losstr = strstr(buf, "=");
242 xmtstr = 1 + losstr; 266 xmtstr = 1 + losstr;
243 xmt = strtod(xmtstr, NULL); 267 xmt = strtod(xmtstr, NULL);
244 if (xmt == 0) 268 if (xmt == 0) {
245 die(STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name); 269 die(STATE_CRITICAL, _("FPING CRITICAL - %s is down\n"), server_name);
270 }
246 losstr = 1 + strstr(losstr, "/"); 271 losstr = 1 + strstr(losstr, "/");
247 losstr = 1 + strstr(losstr, "/"); 272 losstr = 1 + strstr(losstr, "/");
248 loss = strtod(losstr, NULL); 273 loss = strtod(losstr, NULL);
249 if (atoi(losstr) == 100) 274 if (atoi(losstr) == 100) {
250 status = STATE_CRITICAL; 275 status = STATE_CRITICAL;
251 else if (cpl_p && loss > cpl) 276 } else if (cpl_p && loss > cpl) {
252 status = STATE_CRITICAL; 277 status = STATE_CRITICAL;
253 else if (wpl_p && loss > wpl) 278 } else if (wpl_p && loss > wpl) {
254 status = STATE_WARNING; 279 status = STATE_WARNING;
255 else 280 } else {
256 status = STATE_OK; 281 status = STATE_OK;
282 }
257 /* loss=%.0f%%;%d;%d;0;100 */ 283 /* loss=%.0f%%;%d;%d;0;100 */
258 die(status, _("FPING %s - %s (loss=%.0f%% )|%s\n"), state_text(status), server_name, loss, 284 die(status, _("FPING %s - %s (loss=%.0f%% )|%s\n"), state_text(status), server_name, loss,
259 perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, true, 0, true, 100)); 285 perfdata("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, false, 0, false, 0));
260 286
261 } else { 287 } else {
262 status = max_state(status, STATE_WARNING); 288 status = max_state(status, STATE_WARNING);
@@ -266,11 +292,12 @@ int textscan(char *buf) {
266} 292}
267 293
268/* process command-line arguments */ 294/* process command-line arguments */
269int process_arguments(int argc, char **argv) { 295check_fping_config_wrapper process_arguments(int argc, char **argv) {
270 int c; 296 enum {
271 char *rv[2]; 297 FWMARK_OPT = CHAR_MAX + 1,
272 298 ICMP_TIMESTAMP_OPT,
273 int option = 0; 299 CHECK_SOURCE_OPT,
300 };
274 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'}, 301 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
275 {"sourceip", required_argument, 0, 'S'}, 302 {"sourceip", required_argument, 0, 'S'},
276 {"sourceif", required_argument, 0, 'I'}, 303 {"sourceif", required_argument, 0, 'I'},
@@ -288,32 +315,52 @@ int process_arguments(int argc, char **argv) {
288 {"use-ipv6", no_argument, 0, '6'}, 315 {"use-ipv6", no_argument, 0, '6'},
289 {"dontfrag", no_argument, 0, 'M'}, 316 {"dontfrag", no_argument, 0, 'M'},
290 {"random", no_argument, 0, 'R'}, 317 {"random", no_argument, 0, 'R'},
318#ifdef FPING_VERSION_5_2_OR_HIGHER
319 // only available with fping version >= 5.2
320 {"fwmark", required_argument, NULL, FWMARK_OPT},
321# ifdef FPING_VERSION_5_3_OR_HIGHER
322 // only available with fping version >= 5.3
323 {"icmp-timestamp", no_argument, NULL, ICMP_TIMESTAMP_OPT},
324 {"check-source", no_argument, NULL, CHECK_SOURCE_OPT},
325# endif
326#endif
291 {0, 0, 0, 0}}; 327 {0, 0, 0, 0}};
292 328
329 char *rv[2];
293 rv[PL] = NULL; 330 rv[PL] = NULL;
294 rv[RTA] = NULL; 331 rv[RTA] = NULL;
295 332
296 if (argc < 2) 333 int option = 0;
297 return ERROR; 334
335 check_fping_config_wrapper result = {
336 .errorcode = OK,
337 .config = check_fping_config_init(),
338 };
339
340 if (argc < 2) {
341 result.errorcode = ERROR;
342 return result;
343 }
298 344
299 if (!is_option(argv[1])) { 345 if (!is_option(argv[1])) {
300 server_name = argv[1]; 346 result.config.server_name = argv[1];
301 argv[1] = argv[0]; 347 argv[1] = argv[0];
302 argv = &argv[1]; 348 argv = &argv[1];
303 argc--; 349 argc--;
304 } 350 }
305 351
306 while (1) { 352 while (true) {
307 c = getopt_long(argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:M:R:46", longopts, &option); 353 int option_index = getopt_long(argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:M:R:46", longopts, &option);
308 354
309 if (c == -1 || c == EOF || c == 1) 355 if (option_index == -1 || option_index == EOF || option_index == 1) {
310 break; 356 break;
357 }
311 358
312 switch (c) { 359 switch (option_index) {
313 case '?': /* print short usage statement if args not parsable */ 360 case '?': /* print short usage statement if args not parsable */
314 usage5(); 361 usage5();
315 case 'a': /* host alive mode */ 362 case 'a': /* host alive mode */
316 alive_p = true; 363 result.config.alive_p = true;
317 break; 364 break;
318 case 'h': /* help */ 365 case 'h': /* help */
319 print_help(); 366 print_help();
@@ -325,109 +372,126 @@ int process_arguments(int argc, char **argv) {
325 verbose = true; 372 verbose = true;
326 break; 373 break;
327 case 'H': /* hostname */ 374 case 'H': /* hostname */
328 if (is_host(optarg) == false) { 375 if (!is_host(optarg)) {
329 usage2(_("Invalid hostname/address"), optarg); 376 usage2(_("Invalid hostname/address"), optarg);
330 } 377 }
331 server_name = strscpy(server_name, optarg); 378 result.config.server_name = optarg;
332 break; 379 break;
333 case 'S': /* sourceip */ 380 case 'S': /* sourceip */
334 if (is_host(optarg) == false) { 381 if (!is_host(optarg)) {
335 usage2(_("Invalid hostname/address"), optarg); 382 usage2(_("Invalid hostname/address"), optarg);
336 } 383 }
337 sourceip = strscpy(sourceip, optarg); 384 result.config.sourceip = optarg;
338 break; 385 break;
339 case 'I': /* sourceip */ 386 case 'I': /* sourceip */
340 sourceif = strscpy(sourceif, optarg); 387 result.config.sourceif = optarg;
341 break; 388 break;
342 case '4': /* IPv4 only */ 389 case '4': /* IPv4 only */
343 address_family = AF_INET; 390 address_family = AF_INET;
344 break; 391 break;
345 case '6': /* IPv6 only */ 392 case '6': /* IPv6 only */
346#ifdef USE_IPV6
347 address_family = AF_INET6; 393 address_family = AF_INET6;
348#else
349 usage(_("IPv6 support not available\n"));
350#endif
351 break; 394 break;
352 case 'c': 395 case 'c':
353 get_threshold(optarg, rv); 396 get_threshold(optarg, rv);
354 if (rv[RTA]) { 397 if (rv[RTA]) {
355 crta = strtod(rv[RTA], NULL); 398 result.config.crta = strtod(rv[RTA], NULL);
356 crta_p = true; 399 result.config.crta_p = true;
357 rv[RTA] = NULL; 400 rv[RTA] = NULL;
358 } 401 }
359 if (rv[PL]) { 402 if (rv[PL]) {
360 cpl = atoi(rv[PL]); 403 result.config.cpl = atoi(rv[PL]);
361 cpl_p = true; 404 result.config.cpl_p = true;
362 rv[PL] = NULL; 405 rv[PL] = NULL;
363 } 406 }
364 break; 407 break;
365 case 'w': 408 case 'w':
366 get_threshold(optarg, rv); 409 get_threshold(optarg, rv);
367 if (rv[RTA]) { 410 if (rv[RTA]) {
368 wrta = strtod(rv[RTA], NULL); 411 result.config.wrta = strtod(rv[RTA], NULL);
369 wrta_p = true; 412 result.config.wrta_p = true;
370 rv[RTA] = NULL; 413 rv[RTA] = NULL;
371 } 414 }
372 if (rv[PL]) { 415 if (rv[PL]) {
373 wpl = atoi(rv[PL]); 416 result.config.wpl = atoi(rv[PL]);
374 wpl_p = true; 417 result.config.wpl_p = true;
375 rv[PL] = NULL; 418 rv[PL] = NULL;
376 } 419 }
377 break; 420 break;
378 case 'b': /* bytes per packet */ 421 case 'b': /* bytes per packet */
379 if (is_intpos(optarg)) 422 if (is_intpos(optarg)) {
380 packet_size = atoi(optarg); 423 result.config.packet_size = atoi(optarg);
381 else 424 } else {
382 usage(_("Packet size must be a positive integer")); 425 usage(_("Packet size must be a positive integer"));
426 }
383 break; 427 break;
384 case 'n': /* number of packets */ 428 case 'n': /* number of packets */
385 if (is_intpos(optarg)) 429 if (is_intpos(optarg)) {
386 packet_count = atoi(optarg); 430 result.config.packet_count = atoi(optarg);
387 else 431 } else {
388 usage(_("Packet count must be a positive integer")); 432 usage(_("Packet count must be a positive integer"));
433 }
389 break; 434 break;
390 case 'T': /* timeout in msec */ 435 case 'T': /* timeout in msec */
391 if (is_intpos(optarg)) 436 if (is_intpos(optarg)) {
392 target_timeout = atoi(optarg); 437 result.config.target_timeout = atoi(optarg);
393 else 438 } else {
394 usage(_("Target timeout must be a positive integer")); 439 usage(_("Target timeout must be a positive integer"));
440 }
395 break; 441 break;
396 case 'i': /* interval in msec */ 442 case 'i': /* interval in msec */
397 if (is_intpos(optarg)) 443 if (is_intpos(optarg)) {
398 packet_interval = atoi(optarg); 444 result.config.packet_interval = atoi(optarg);
399 else 445 } else {
400 usage(_("Interval must be a positive integer")); 446 usage(_("Interval must be a positive integer"));
447 }
401 break; 448 break;
402 case 'R': 449 case 'R':
403 randomize_packet_data = true; 450 result.config.randomize_packet_data = true;
404 break; 451 break;
405 case 'M': 452 case 'M':
406 dontfrag = true; 453 result.config.dontfrag = true;
454 break;
455 case FWMARK_OPT:
456 if (is_intpos(optarg)) {
457 result.config.fwmark = (unsigned int)atol(optarg);
458 result.config.fwmark_set = true;
459 } else {
460 usage(_("fwmark must be a positive integer"));
461 }
462 break;
463 case ICMP_TIMESTAMP_OPT:
464 result.config.icmp_timestamp = true;
465 break;
466 case CHECK_SOURCE_OPT:
467 result.config.check_source = true;
407 break; 468 break;
408 } 469 }
409 } 470 }
410 471
411 if (server_name == NULL) 472 if (result.config.server_name == NULL) {
412 usage4(_("Hostname was not supplied")); 473 usage4(_("Hostname was not supplied"));
474 }
413 475
414 return OK; 476 return result;
415} 477}
416 478
417int get_threshold(char *arg, char *rv[2]) { 479int get_threshold(char *arg, char *rv[2]) {
418 char *arg1 = NULL;
419 char *arg2 = NULL; 480 char *arg2 = NULL;
420 481
421 arg1 = strscpy(arg1, arg); 482 char *arg1 = strdup(arg);
422 if (strpbrk(arg1, ",:")) 483 if (strpbrk(arg1, ",:")) {
423 arg2 = 1 + strpbrk(arg1, ",:"); 484 arg2 = 1 + strpbrk(arg1, ",:");
485 }
424 486
425 if (arg2) { 487 if (arg2) {
426 arg1[strcspn(arg1, ",:")] = 0; 488 arg1[strcspn(arg1, ",:")] = 0;
427 if (strstr(arg1, "%") && strstr(arg2, "%")) 489 if (strstr(arg1, "%") && strstr(arg2, "%")) {
428 die(STATE_UNKNOWN, _("%s: Only one threshold may be packet loss (%s)\n"), progname, arg); 490 die(STATE_UNKNOWN, _("%s: Only one threshold may be packet loss (%s)\n"), progname, arg);
429 if (!strstr(arg1, "%") && !strstr(arg2, "%")) 491 }
492 if (!strstr(arg1, "%") && !strstr(arg2, "%")) {
430 die(STATE_UNKNOWN, _("%s: Only one threshold must be packet loss (%s)\n"), progname, arg); 493 die(STATE_UNKNOWN, _("%s: Only one threshold must be packet loss (%s)\n"), progname, arg);
494 }
431 } 495 }
432 496
433 if (arg2 && strstr(arg2, "%")) { 497 if (arg2 && strstr(arg2, "%")) {
@@ -489,6 +553,16 @@ void print_help(void) {
489 printf(" %s\n", _("set the Don't Fragment flag")); 553 printf(" %s\n", _("set the Don't Fragment flag"));
490 printf(" %s\n", "-R, --random"); 554 printf(" %s\n", "-R, --random");
491 printf(" %s\n", _("random packet data (to foil link data compression)")); 555 printf(" %s\n", _("random packet data (to foil link data compression)"));
556#ifdef FPING_VERSION_5_2_OR_HIGHER
557 printf(" %s\n", "--fwmark=INTEGER");
558 printf(" %s\n", _("set the routing mark to INTEGER (fping option)"));
559# ifdef FPING_VERSION_5_3_OR_HIGHER
560 printf(" %s\n", "--icmp-timestamp");
561 printf(" %s\n", _("use ICMP Timestamp instead of ICMP Echo (fping option)"));
562 printf(" %s\n", "--check-source");
563 printf(" %s\n", _("discard replies not from target address (fping option)"));
564# endif
565#endif
492 printf(UT_VERBOSE); 566 printf(UT_VERBOSE);
493 printf("\n"); 567 printf("\n");
494 printf(" %s\n", _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)")); 568 printf(" %s\n", _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)"));