summaryrefslogtreecommitdiffstats
path: root/plugins/check_ping.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_ping.c')
-rw-r--r--plugins/check_ping.c854
1 files changed, 430 insertions, 424 deletions
diff --git a/plugins/check_ping.c b/plugins/check_ping.c
index 6e162e6a..6bcdeaad 100644
--- a/plugins/check_ping.c
+++ b/plugins/check_ping.c
@@ -1,506 +1,526 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_ping plugin 3 * Monitoring check_ping 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_ping plugin 10 * This file contains the check_ping plugin
11* 11 *
12* Use the ping program to check connection statistics for a remote host. 12 * Use the ping program to check connection statistics for a remote host.
13* 13 *
14* 14 *
15* This program is free software: you can redistribute it and/or modify 15 * This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17 * the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18 * (at your option) any later version.
19* 19 *
20* This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23 * GNU General Public License for more details.
24* 24 *
25* You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27 *
28* 28 *
29*****************************************************************************/ 29 *****************************************************************************/
30 30
31const char *progname = "check_ping"; 31const char *progname = "check_ping";
32const char *copyright = "2000-2007"; 32const char *copyright = "2000-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
36#include "netutils.h" 36#include "netutils.h"
37#include "popen.h" 37#include "popen.h"
38#include "utils.h" 38#include "utils.h"
39#include "check_ping.d/config.h"
40#include "../lib/states.h"
39 41
40#include <signal.h> 42#include <signal.h>
41 43
42#define WARN_DUPLICATES "DUPLICATES FOUND! " 44#define WARN_DUPLICATES "DUPLICATES FOUND! "
43#define UNKNOWN_TRIP_TIME -1.0 /* -1 seconds */
44
45enum {
46 UNKNOWN_PACKET_LOSS = 200, /* 200% */
47 DEFAULT_MAX_PACKETS = 5 /* default no. of ICMP ECHO packets */
48};
49
50int process_arguments (int, char **);
51int get_threshold (char *, float *, int *);
52int validate_arguments (void);
53int run_ping (const char *cmd, const char *addr);
54int error_scan (char buf[MAX_INPUT_BUFFER], const char *addr);
55void print_usage (void);
56void print_help (void);
57
58bool display_html = false;
59int wpl = UNKNOWN_PACKET_LOSS;
60int cpl = UNKNOWN_PACKET_LOSS;
61float wrta = UNKNOWN_TRIP_TIME;
62float crta = UNKNOWN_TRIP_TIME;
63char **addresses = NULL;
64int n_addresses = 0;
65int max_addr = 1;
66int max_packets = -1;
67int verbose = 0;
68
69float rta = UNKNOWN_TRIP_TIME;
70int pl = UNKNOWN_PACKET_LOSS;
71
72char *warn_text;
73
74
75
76int
77main (int argc, char **argv)
78{
79 char *cmd = NULL;
80 char *rawcmd = NULL;
81 int result = STATE_UNKNOWN;
82 int this_result = STATE_UNKNOWN;
83 int i;
84 45
85 setlocale (LC_ALL, ""); 46typedef struct {
86 setlocale (LC_NUMERIC, "C"); 47 int errorcode;
87 bindtextdomain (PACKAGE, LOCALEDIR); 48 check_ping_config config;
88 textdomain (PACKAGE); 49} check_ping_config_wrapper;
50static check_ping_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
51static check_ping_config_wrapper validate_arguments(check_ping_config_wrapper /*config_wrapper*/);
52
53static int get_threshold(char * /*arg*/, double * /*trta*/, int * /*tpl*/);
54
55typedef struct {
56 mp_state_enum state;
57 double round_trip_average;
58 int packet_loss;
59} ping_result;
60static ping_result run_ping(const char *cmd, const char *addr, double /*crta*/);
61
62static mp_state_enum error_scan(char buf[MAX_INPUT_BUFFER], const char *addr);
63static void print_help(void);
64void print_usage(void);
65
66static int verbose = 0;
89 67
90 addresses = malloc (sizeof(char*) * max_addr); 68static char *warn_text;
91 addresses[0] = NULL; 69
70int main(int argc, char **argv) {
71 setlocale(LC_ALL, "");
72 setlocale(LC_NUMERIC, "C");
73 bindtextdomain(PACKAGE, LOCALEDIR);
74 textdomain(PACKAGE);
92 75
93 /* Parse extra opts if any */ 76 /* Parse extra opts if any */
94 argv=np_extra_opts (&argc, argv, progname); 77 argv = np_extra_opts(&argc, argv, progname);
78
79 check_ping_config_wrapper tmp_config = process_arguments(argc, argv);
80 if (tmp_config.errorcode == ERROR) {
81 usage4(_("Could not parse arguments"));
82 }
95 83
96 if (process_arguments (argc, argv) == ERROR) 84 const check_ping_config config = tmp_config.config;
97 usage4 (_("Could not parse arguments"));
98 85
99 /* Set signal handling and alarm */ 86 /* Set signal handling and alarm */
100 if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) { 87 if (signal(SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
101 usage4 (_("Cannot catch SIGALRM")); 88 usage4(_("Cannot catch SIGALRM"));
102 } 89 }
103 90
104 /* If ./configure finds ping has timeout values, set plugin alarm slightly 91 /* If ./configure finds ping has timeout values, set plugin alarm slightly
105 * higher so that we can use response from command line ping */ 92 * higher so that we can use response from command line ping */
106#if defined(PING_PACKETS_FIRST) && defined(PING_HAS_TIMEOUT) 93#if defined(PING_PACKETS_FIRST) && defined(PING_HAS_TIMEOUT)
107 alarm (timeout_interval + 1); 94 alarm(timeout_interval + 1);
108#else 95#else
109 alarm (timeout_interval); 96 alarm(timeout_interval);
110#endif 97#endif
111 98
112 for (i = 0 ; i < n_addresses ; i++) { 99 int result = STATE_UNKNOWN;
113 100 char *rawcmd = NULL;
101 for (size_t i = 0; i < config.n_addresses; i++) {
114#ifdef PING6_COMMAND 102#ifdef PING6_COMMAND
115 if (address_family != AF_INET && is_inet6_addr(addresses[i])) 103 if (address_family != AF_INET && is_inet6_addr(config.addresses[i])) {
116 rawcmd = strdup(PING6_COMMAND); 104 rawcmd = strdup(PING6_COMMAND);
117 else 105 } else {
118 rawcmd = strdup(PING_COMMAND); 106 rawcmd = strdup(PING_COMMAND);
107 }
119#else 108#else
120 rawcmd = strdup(PING_COMMAND); 109 rawcmd = strdup(PING_COMMAND);
121#endif 110#endif
122 111
112 char *cmd = NULL;
113
123 /* does the host address of number of packets argument come first? */ 114 /* does the host address of number of packets argument come first? */
124#ifdef PING_PACKETS_FIRST 115#ifdef PING_PACKETS_FIRST
125# ifdef PING_HAS_TIMEOUT 116# ifdef PING_HAS_TIMEOUT
126 xasprintf (&cmd, rawcmd, timeout_interval, max_packets, addresses[i]); 117 xasprintf(&cmd, rawcmd, timeout_interval, config.max_packets, config.addresses[i]);
127# else 118# else
128 xasprintf (&cmd, rawcmd, max_packets, addresses[i]); 119 xasprintf(&cmd, rawcmd, config.max_packets, config.addresses[i]);
129# endif 120# endif
130#else 121#else
131 xasprintf (&cmd, rawcmd, addresses[i], max_packets); 122 xasprintf(&cmd, rawcmd, config.addresses[i], config.max_packets);
132#endif 123#endif
133 124
134 if (verbose >= 2) 125 if (verbose >= 2) {
135 printf ("CMD: %s\n", cmd); 126 printf("CMD: %s\n", cmd);
127 }
136 128
137 /* run the command */ 129 /* run the command */
138 this_result = run_ping (cmd, addresses[i]);
139 130
140 if (pl == UNKNOWN_PACKET_LOSS || rta < 0.0) { 131 ping_result pinged = run_ping(cmd, config.addresses[i], config.crta);
141 printf ("%s\n", cmd); 132
142 die (STATE_UNKNOWN, 133 if (pinged.packet_loss == UNKNOWN_PACKET_LOSS || pinged.round_trip_average < 0.0) {
143 _("CRITICAL - Could not interpret output from ping command\n")); 134 printf("%s\n", cmd);
135 die(STATE_UNKNOWN, _("CRITICAL - Could not interpret output from ping command\n"));
136 }
137
138 if (pinged.packet_loss >= config.cpl || pinged.round_trip_average >= config.crta || pinged.round_trip_average < 0) {
139 pinged.state = STATE_CRITICAL;
140 } else if (pinged.packet_loss >= config.wpl || pinged.round_trip_average >= config.wrta) {
141 pinged.state = STATE_WARNING;
142 } else if (pinged.packet_loss >= 0 && pinged.round_trip_average >= 0) {
143 pinged.state = max_state(STATE_OK, pinged.state);
144 }
145
146 if (config.n_addresses > 1 && pinged.state != STATE_UNKNOWN) {
147 die(STATE_OK, "%s is alive\n", config.addresses[i]);
144 } 148 }
145 149
146 if (pl >= cpl || rta >= crta || rta < 0) 150 if (config.display_html) {
147 this_result = STATE_CRITICAL; 151 printf("<A HREF='%s/traceroute.cgi?%s'>", CGIURL, config.addresses[i]);
148 else if (pl >= wpl || rta >= wrta) 152 }
149 this_result = STATE_WARNING; 153 if (pinged.packet_loss == 100) {
150 else if (pl >= 0 && rta >= 0) 154 printf(_("PING %s - %sPacket loss = %d%%"), state_text(pinged.state), warn_text, pinged.packet_loss);
151 this_result = max_state (STATE_OK, this_result); 155 } else {
152 156 printf(_("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms"), state_text(pinged.state), warn_text, pinged.packet_loss,
153 if (n_addresses > 1 && this_result != STATE_UNKNOWN) 157 pinged.round_trip_average);
154 die (STATE_OK, "%s is alive\n", addresses[i]); 158 }
155 159 if (config.display_html) {
156 if (display_html == true) 160 printf("</A>");
157 printf ("<A HREF='%s/traceroute.cgi?%s'>", CGIURL, addresses[i]); 161 }
158 if (pl == 100)
159 printf (_("PING %s - %sPacket loss = %d%%"), state_text (this_result), warn_text,
160 pl);
161 else
162 printf (_("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms"),
163 state_text (this_result), warn_text, pl, rta);
164 if (display_html == true)
165 printf ("</A>");
166 162
167 /* Print performance data */ 163 /* Print performance data */
168 if (pl != 100) { 164 if (pinged.packet_loss != 100) {
169 printf("|%s", fperfdata ("rta", (double) rta, "ms", 165 printf("|%s", fperfdata("rta", pinged.round_trip_average, "ms", (bool)(config.wrta > 0), config.wrta, (bool)(config.crta > 0),
170 wrta>0?true:false, wrta, 166 config.crta, true, 0, false, 0));
171 crta>0?true:false, crta,
172 true, 0, false, 0));
173 } else { 167 } else {
174 printf("| rta=U;%f;%f;;", wrta, crta); 168 printf("| rta=U;%f;%f;;", config.wrta, config.crta);
175 } 169 }
176 printf(" %s\n", perfdata ("pl", (long) pl, "%",
177 wpl>0?true:false, wpl,
178 cpl>0?true:false, cpl,
179 true, 0, false, 0));
180 170
181 if (verbose >= 2) 171 printf(" %s\n", perfdata("pl", (long)pinged.packet_loss, "%", (bool)(config.wpl > 0), config.wpl, (bool)(config.cpl > 0),
182 printf ("%f:%d%% %f:%d%%\n", wrta, wpl, crta, cpl); 172 config.cpl, true, 0, false, 0));
173
174 if (verbose >= 2) {
175 printf("%f:%d%% %f:%d%%\n", config.wrta, config.wpl, config.crta, config.cpl);
176 }
183 177
184 result = max_state (result, this_result); 178 result = max_state(result, pinged.state);
185 free (rawcmd); 179 free(rawcmd);
186 free (cmd); 180 free(cmd);
187 } 181 }
188 182
189 return result; 183 return result;
190} 184}
191 185
192
193
194/* process command-line arguments */ 186/* process command-line arguments */
195int 187check_ping_config_wrapper process_arguments(int argc, char **argv) {
196process_arguments (int argc, char **argv) 188 static struct option longopts[] = {STD_LONG_OPTS,
197{ 189 {"packets", required_argument, 0, 'p'},
198 int c = 1; 190 {"nohtml", no_argument, 0, 'n'},
199 char *ptr; 191 {"link", no_argument, 0, 'L'},
200 192 {"use-ipv4", no_argument, 0, '4'},
201 int option = 0; 193 {"use-ipv6", no_argument, 0, '6'},
202 static struct option longopts[] = { 194 {0, 0, 0, 0}};
203 STD_LONG_OPTS, 195
204 {"packets", required_argument, 0, 'p'}, 196 check_ping_config_wrapper result = {
205 {"nohtml", no_argument, 0, 'n'}, 197 .errorcode = OK,
206 {"link", no_argument, 0, 'L'}, 198 .config = check_ping_config_init(),
207 {"use-ipv4", no_argument, 0, '4'},
208 {"use-ipv6", no_argument, 0, '6'},
209 {0, 0, 0, 0}
210 }; 199 };
211 200
212 if (argc < 2) 201 if (argc < 2) {
213 return ERROR; 202 result.errorcode = ERROR;
203 return result;
204 }
214 205
215 for (c = 1; c < argc; c++) { 206 for (int index = 1; index < argc; index++) {
216 if (strcmp ("-to", argv[c]) == 0) 207 if (strcmp("-to", argv[index]) == 0) {
217 strcpy (argv[c], "-t"); 208 strcpy(argv[index], "-t");
218 if (strcmp ("-nohtml", argv[c]) == 0) 209 }
219 strcpy (argv[c], "-n"); 210 if (strcmp("-nohtml", argv[index]) == 0) {
211 strcpy(argv[index], "-n");
212 }
220 } 213 }
221 214
222 while (1) { 215 int option = 0;
223 c = getopt_long (argc, argv, "VvhnL46t:c:w:H:p:", longopts, &option); 216 size_t max_addr = MAX_ADDR_START;
217 while (true) {
218 int option_index = getopt_long(argc, argv, "VvhnL46t:c:w:H:p:", longopts, &option);
224 219
225 if (c == -1 || c == EOF) 220 if (option_index == -1 || option_index == EOF) {
226 break; 221 break;
222 }
227 223
228 switch (c) { 224 switch (option_index) {
229 case '?': /* usage */ 225 case '?': /* usage */
230 usage5 (); 226 usage5();
231 case 'h': /* help */ 227 case 'h': /* help */
232 print_help (); 228 print_help();
233 exit (STATE_UNKNOWN); 229 exit(STATE_UNKNOWN);
234 break; 230 break;
235 case 'V': /* version */ 231 case 'V': /* version */
236 print_revision (progname, NP_VERSION); 232 print_revision(progname, NP_VERSION);
237 exit (STATE_UNKNOWN); 233 exit(STATE_UNKNOWN);
238 break; 234 break;
239 case 't': /* timeout period */ 235 case 't': /* timeout period */
240 timeout_interval = atoi (optarg); 236 timeout_interval = atoi(optarg);
241 break; 237 break;
242 case 'v': /* verbose mode */ 238 case 'v': /* verbose mode */
243 verbose++; 239 verbose++;
244 break; 240 break;
245 case '4': /* IPv4 only */ 241 case '4': /* IPv4 only */
246 address_family = AF_INET; 242 address_family = AF_INET;
247 break; 243 break;
248 case '6': /* IPv6 only */ 244 case '6': /* IPv6 only */
249#ifdef USE_IPV6 245#ifdef USE_IPV6
250 address_family = AF_INET6; 246 address_family = AF_INET6;
251#else 247#else
252 usage (_("IPv6 support not available\n")); 248 usage(_("IPv6 support not available\n"));
253#endif 249#endif
254 break; 250 break;
255 case 'H': /* hostname */ 251 case 'H': /* hostname */ {
256 ptr=optarg; 252 char *ptr = optarg;
257 while (1) { 253 while (true) {
258 n_addresses++; 254 result.config.n_addresses++;
259 if (n_addresses > max_addr) { 255 if (result.config.n_addresses > max_addr) {
260 max_addr *= 2; 256 max_addr *= 2;
261 addresses = realloc (addresses, sizeof(char*) * max_addr); 257 result.config.addresses = realloc(result.config.addresses, sizeof(char *) * max_addr);
262 if (addresses == NULL) 258 if (result.config.addresses == NULL) {
263 die (STATE_UNKNOWN, _("Could not realloc() addresses\n")); 259 die(STATE_UNKNOWN, _("Could not realloc() addresses\n"));
260 }
264 } 261 }
265 addresses[n_addresses-1] = ptr; 262 result.config.addresses[result.config.n_addresses - 1] = ptr;
266 if ((ptr = index (ptr, ','))) { 263 if ((ptr = index(ptr, ','))) {
267 strcpy (ptr, ""); 264 strcpy(ptr, "");
268 ptr += sizeof(char); 265 ptr += sizeof(char);
269 } else { 266 } else {
270 break; 267 break;
271 } 268 }
272 } 269 }
270 } break;
271 case 'p': /* number of packets to send */
272 if (is_intnonneg(optarg)) {
273 result.config.max_packets = atoi(optarg);
274 } else {
275 usage2(_("<max_packets> (%s) must be a non-negative number\n"), optarg);
276 }
273 break; 277 break;
274 case 'p': /* number of packets to send */ 278 case 'n': /* no HTML */
275 if (is_intnonneg (optarg)) 279 result.config.display_html = false;
276 max_packets = atoi (optarg);
277 else
278 usage2 (_("<max_packets> (%s) must be a non-negative number\n"), optarg);
279 break;
280 case 'n': /* no HTML */
281 display_html = false;
282 break; 280 break;
283 case 'L': /* show HTML */ 281 case 'L': /* show HTML */
284 display_html = true; 282 result.config.display_html = true;
285 break; 283 break;
286 case 'c': 284 case 'c':
287 get_threshold (optarg, &crta, &cpl); 285 get_threshold(optarg, &result.config.crta, &result.config.cpl);
288 break; 286 break;
289 case 'w': 287 case 'w':
290 get_threshold (optarg, &wrta, &wpl); 288 get_threshold(optarg, &result.config.wrta, &result.config.wpl);
291 break; 289 break;
292 } 290 }
293 } 291 }
294 292
295 c = optind; 293 int arg_counter = optind;
296 if (c == argc) 294 if (arg_counter == argc) {
297 return validate_arguments (); 295 return validate_arguments(result);
296 }
298 297
299 if (addresses[0] == NULL) { 298 if (result.config.addresses[0] == NULL) {
300 if (!is_host (argv[c])) { 299 if (!is_host(argv[arg_counter])) {
301 usage2 (_("Invalid hostname/address"), argv[c]); 300 usage2(_("Invalid hostname/address"), argv[arg_counter]);
302 } else { 301 } else {
303 addresses[0] = argv[c++]; 302 result.config.addresses[0] = argv[arg_counter++];
304 n_addresses++; 303 result.config.n_addresses++;
305 if (c == argc) 304 if (arg_counter == argc) {
306 return validate_arguments (); 305 return validate_arguments(result);
306 }
307 } 307 }
308 } 308 }
309 309
310 if (wpl == UNKNOWN_PACKET_LOSS) { 310 if (result.config.wpl == UNKNOWN_PACKET_LOSS) {
311 if (!is_intpercent (argv[c])) { 311 if (!is_intpercent(argv[arg_counter])) {
312 printf (_("<wpl> (%s) must be an integer percentage\n"), argv[c]); 312 printf(_("<wpl> (%s) must be an integer percentage\n"), argv[arg_counter]);
313 return ERROR; 313 result.errorcode = ERROR;
314 } else { 314 return result;
315 wpl = atoi (argv[c++]); 315 }
316 if (c == argc) 316 result.config.wpl = atoi(argv[arg_counter++]);
317 return validate_arguments (); 317 if (arg_counter == argc) {
318 return validate_arguments(result);
318 } 319 }
319 } 320 }
320 321
321 if (cpl == UNKNOWN_PACKET_LOSS) { 322 if (result.config.cpl == UNKNOWN_PACKET_LOSS) {
322 if (!is_intpercent (argv[c])) { 323 if (!is_intpercent(argv[arg_counter])) {
323 printf (_("<cpl> (%s) must be an integer percentage\n"), argv[c]); 324 printf(_("<cpl> (%s) must be an integer percentage\n"), argv[arg_counter]);
324 return ERROR; 325 result.errorcode = ERROR;
325 } else { 326 return result;
326 cpl = atoi (argv[c++]); 327 }
327 if (c == argc) 328 result.config.cpl = atoi(argv[arg_counter++]);
328 return validate_arguments (); 329 if (arg_counter == argc) {
330 return validate_arguments(result);
329 } 331 }
330 } 332 }
331 333
332 if (wrta < 0.0) { 334 if (result.config.wrta < 0.0) {
333 if (is_negative (argv[c])) { 335 if (is_negative(argv[arg_counter])) {
334 printf (_("<wrta> (%s) must be a non-negative number\n"), argv[c]); 336 printf(_("<wrta> (%s) must be a non-negative number\n"), argv[arg_counter]);
335 return ERROR; 337 result.errorcode = ERROR;
336 } else { 338 return result;
337 wrta = atof (argv[c++]); 339 }
338 if (c == argc) 340 result.config.wrta = atof(argv[arg_counter++]);
339 return validate_arguments (); 341 if (arg_counter == argc) {
342 return validate_arguments(result);
340 } 343 }
341 } 344 }
342 345
343 if (crta < 0.0) { 346 if (result.config.crta < 0.0) {
344 if (is_negative (argv[c])) { 347 if (is_negative(argv[arg_counter])) {
345 printf (_("<crta> (%s) must be a non-negative number\n"), argv[c]); 348 printf(_("<crta> (%s) must be a non-negative number\n"), argv[arg_counter]);
346 return ERROR; 349 result.errorcode = ERROR;
347 } else { 350 return result;
348 crta = atof (argv[c++]); 351 }
349 if (c == argc) 352 result.config.crta = atof(argv[arg_counter++]);
350 return validate_arguments (); 353 if (arg_counter == argc) {
354 return validate_arguments(result);
351 } 355 }
352 } 356 }
353 357
354 if (max_packets == -1) { 358 if (result.config.max_packets == -1) {
355 if (is_intnonneg (argv[c])) { 359 if (is_intnonneg(argv[arg_counter])) {
356 max_packets = atoi (argv[c++]); 360 result.config.max_packets = atoi(argv[arg_counter++]);
357 } else { 361 } else {
358 printf (_("<max_packets> (%s) must be a non-negative number\n"), argv[c]); 362 printf(_("<max_packets> (%s) must be a non-negative number\n"), argv[arg_counter]);
359 return ERROR; 363 result.errorcode = ERROR;
364 return result;
360 } 365 }
361 } 366 }
362 367
363 return validate_arguments (); 368 return validate_arguments(result);
364} 369}
365 370
366 371int get_threshold(char *arg, double *trta, int *tpl) {
367 372 if (is_intnonneg(arg) && sscanf(arg, "%lf", trta) == 1) {
368int
369get_threshold (char *arg, float *trta, int *tpl)
370{
371 if (is_intnonneg (arg) && sscanf (arg, "%f", trta) == 1)
372 return OK; 373 return OK;
373 else if (strpbrk (arg, ",:") && strstr (arg, "%") && sscanf (arg, "%f%*[:,]%d%%", trta, tpl) == 2) 374 }
375
376 if (strpbrk(arg, ",:") && strstr(arg, "%") && sscanf(arg, "%lf%*[:,]%d%%", trta, tpl) == 2) {
374 return OK; 377 return OK;
375 else if (strstr (arg, "%") && sscanf (arg, "%d%%", tpl) == 1) 378 }
379
380 if (strstr(arg, "%") && sscanf(arg, "%d%%", tpl) == 1) {
376 return OK; 381 return OK;
382 }
377 383
378 usage2 (_("%s: Warning threshold must be integer or percentage!\n\n"), arg); 384 usage2(_("%s: Warning threshold must be integer or percentage!\n\n"), arg);
379 return STATE_UNKNOWN; 385 return STATE_UNKNOWN;
380} 386}
381 387
382 388check_ping_config_wrapper validate_arguments(check_ping_config_wrapper config_wrapper) {
383 389 if (config_wrapper.config.wrta < 0.0) {
384int 390 printf(_("<wrta> was not set\n"));
385validate_arguments () 391 config_wrapper.errorcode = ERROR;
386{ 392 return config_wrapper;
387 float max_seconds;
388 int i;
389
390 if (wrta < 0.0) {
391 printf (_("<wrta> was not set\n"));
392 return ERROR;
393 } 393 }
394 else if (crta < 0.0) { 394
395 printf (_("<crta> was not set\n")); 395 if (config_wrapper.config.crta < 0.0) {
396 return ERROR; 396 printf(_("<crta> was not set\n"));
397 config_wrapper.errorcode = ERROR;
398 return config_wrapper;
397 } 399 }
398 else if (wpl == UNKNOWN_PACKET_LOSS) { 400
399 printf (_("<wpl> was not set\n")); 401 if (config_wrapper.config.wpl == UNKNOWN_PACKET_LOSS) {
400 return ERROR; 402 printf(_("<wpl> was not set\n"));
403 config_wrapper.errorcode = ERROR;
404 return config_wrapper;
401 } 405 }
402 else if (cpl == UNKNOWN_PACKET_LOSS) { 406
403 printf (_("<cpl> was not set\n")); 407 if (config_wrapper.config.cpl == UNKNOWN_PACKET_LOSS) {
404 return ERROR; 408 printf(_("<cpl> was not set\n"));
409 config_wrapper.errorcode = ERROR;
410 return config_wrapper;
405 } 411 }
406 else if (wrta > crta) { 412
407 printf (_("<wrta> (%f) cannot be larger than <crta> (%f)\n"), wrta, crta); 413 if (config_wrapper.config.wrta > config_wrapper.config.crta) {
408 return ERROR; 414 printf(_("<wrta> (%f) cannot be larger than <crta> (%f)\n"), config_wrapper.config.wrta, config_wrapper.config.crta);
415 config_wrapper.errorcode = ERROR;
416 return config_wrapper;
409 } 417 }
410 else if (wpl > cpl) { 418
411 printf (_("<wpl> (%d) cannot be larger than <cpl> (%d)\n"), wpl, cpl); 419 if (config_wrapper.config.wpl > config_wrapper.config.cpl) {
412 return ERROR; 420 printf(_("<wpl> (%d) cannot be larger than <cpl> (%d)\n"), config_wrapper.config.wpl, config_wrapper.config.cpl);
421 config_wrapper.errorcode = ERROR;
422 return config_wrapper;
413 } 423 }
414 424
415 if (max_packets == -1) 425 if (config_wrapper.config.max_packets == -1) {
416 max_packets = DEFAULT_MAX_PACKETS; 426 config_wrapper.config.max_packets = DEFAULT_MAX_PACKETS;
427 }
417 428
418 max_seconds = crta / 1000.0 * max_packets + max_packets; 429 double max_seconds = (config_wrapper.config.crta / 1000.0 * config_wrapper.config.max_packets) + config_wrapper.config.max_packets;
419 if (max_seconds > timeout_interval) 430 if (max_seconds > timeout_interval) {
420 timeout_interval = (int)max_seconds; 431 timeout_interval = (unsigned int)max_seconds;
432 }
421 433
422 for (i=0; i<n_addresses; i++) { 434 for (size_t i = 0; i < config_wrapper.config.n_addresses; i++) {
423 if (!is_host(addresses[i])) 435 if (!is_host(config_wrapper.config.addresses[i])) {
424 usage2 (_("Invalid hostname/address"), addresses[i]); 436 usage2(_("Invalid hostname/address"), config_wrapper.config.addresses[i]);
437 }
425 } 438 }
426 439
427 if (n_addresses == 0) { 440 if (config_wrapper.config.n_addresses == 0) {
428 usage (_("You must specify a server address or host name")); 441 usage(_("You must specify a server address or host name"));
429 } 442 }
430 443
431 return OK; 444 return config_wrapper;
432} 445}
433 446
447ping_result run_ping(const char *cmd, const char *addr, double crta) {
448 if ((child_process = spopen(cmd)) == NULL) {
449 die(STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd);
450 }
434 451
452 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r");
453 if (child_stderr == NULL) {
454 printf(_("Cannot open stderr for %s\n"), cmd);
455 }
435 456
436int
437run_ping (const char *cmd, const char *addr)
438{
439 char buf[MAX_INPUT_BUFFER]; 457 char buf[MAX_INPUT_BUFFER];
440 int result = STATE_UNKNOWN; 458 ping_result result = {
441 int match; 459 .state = STATE_UNKNOWN,
442 460 .packet_loss = UNKNOWN_PACKET_LOSS,
443 if ((child_process = spopen (cmd)) == NULL) 461 .round_trip_average = UNKNOWN_TRIP_TIME,
444 die (STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd); 462 };
445
446 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
447 if (child_stderr == NULL)
448 printf (_("Cannot open stderr for %s\n"), cmd);
449
450 while (fgets (buf, MAX_INPUT_BUFFER - 1, child_process)) {
451 463
452 if (verbose >= 3) 464 while (fgets(buf, MAX_INPUT_BUFFER - 1, child_process)) {
465 if (verbose >= 3) {
453 printf("Output: %s", buf); 466 printf("Output: %s", buf);
467 }
454 468
455 result = max_state (result, error_scan (buf, addr)); 469 result.state = max_state(result.state, error_scan(buf, addr));
456 470
457 /* get the percent loss statistics */ 471 /* get the percent loss statistics */
458 match = 0; 472 int match = 0;
459 if((sscanf(buf,"%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) || 473 if ((sscanf(buf, "%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss%n", &result.packet_loss, &match) ==
460 (sscanf(buf,"%*d packets transmitted, %*d packets received, +%*d duplicates, %d%% packet loss%n",&pl,&match) && match) || 474 1 &&
461 (sscanf(buf,"%*d packets transmitted, %*d received, +%*d duplicates, %d%% packet loss%n",&pl,&match) && match) || 475 match) ||
462 (sscanf(buf,"%*d packets transmitted, %*d packets received, %d%% packet loss%n",&pl,&match) && match) || 476 (sscanf(buf, "%*d packets transmitted, %*d packets received, +%*d duplicates, %d%% packet loss%n", &result.packet_loss,
463 (sscanf(buf,"%*d packets transmitted, %*d packets received, %d%% loss, time%n",&pl,&match) && match) || 477 &match) == 1 &&
464 (sscanf(buf,"%*d packets transmitted, %*d received, %d%% loss, time%n",&pl,&match) && match) || 478 match) ||
465 (sscanf(buf,"%*d packets transmitted, %*d received, %d%% packet loss, time%n",&pl,&match) && match) || 479 (sscanf(buf, "%*d packets transmitted, %*d received, +%*d duplicates, %d%% packet loss%n", &result.packet_loss, &match) == 1 &&
466 (sscanf(buf,"%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) || 480 match) ||
467 (sscanf(buf,"%*d packets transmitted %*d received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) || 481 (sscanf(buf, "%*d packets transmitted, %*d packets received, %d%% packet loss%n", &result.packet_loss, &match) == 1 && match) ||
468 (sscanf(buf,"%*[^(](%d%% %*[^)])%n",&pl,&match) && match) 482 (sscanf(buf, "%*d packets transmitted, %*d packets received, %d%% loss, time%n", &result.packet_loss, &match) == 1 && match) ||
469 ) 483 (sscanf(buf, "%*d packets transmitted, %*d received, %d%% loss, time%n", &result.packet_loss, &match) == 1 && match) ||
484 (sscanf(buf, "%*d packets transmitted, %*d received, %d%% packet loss, time%n", &result.packet_loss, &match) == 1 && match) ==
485 1 ||
486 (sscanf(buf, "%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss%n", &result.packet_loss, &match) == 1 &&
487 match) ||
488 (sscanf(buf, "%*d packets transmitted %*d received, +%*d errors, %d%% packet loss%n", &result.packet_loss, &match) == 1 &&
489 match) ||
490 (sscanf(buf, "%*[^(](%d%% %*[^)])%n", &result.packet_loss, &match) == 1 && match)) {
470 continue; 491 continue;
492 }
471 493
472 /* get the round trip average */ 494 /* get the round trip average */
473 else 495 if ((sscanf(buf, "round-trip min/avg/max = %*f/%lf/%*f%n", &result.round_trip_average, &match) == 1 && match) ||
474 if((sscanf(buf,"round-trip min/avg/max = %*f/%f/%*f%n",&rta,&match) && match) || 496 (sscanf(buf, "round-trip min/avg/max/mdev = %*f/%lf/%*f/%*f%n", &result.round_trip_average, &match) == 1 && match) ||
475 (sscanf(buf,"round-trip min/avg/max/mdev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 497 (sscanf(buf, "round-trip min/avg/max/sdev = %*f/%lf/%*f/%*f%n", &result.round_trip_average, &match) == 1 && match) ||
476 (sscanf(buf,"round-trip min/avg/max/sdev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 498 (sscanf(buf, "round-trip min/avg/max/stddev = %*f/%lf/%*f/%*f%n", &result.round_trip_average, &match) == 1 && match) ||
477 (sscanf(buf,"round-trip min/avg/max/stddev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 499 (sscanf(buf, "round-trip min/avg/max/std-dev = %*f/%lf/%*f/%*f%n", &result.round_trip_average, &match) == 1 && match) ||
478 (sscanf(buf,"round-trip min/avg/max/std-dev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 500 (sscanf(buf, "round-trip (ms) min/avg/max = %*f/%lf/%*f%n", &result.round_trip_average, &match) == 1 && match) ||
479 (sscanf(buf,"round-trip (ms) min/avg/max = %*f/%f/%*f%n",&rta,&match) && match) || 501 (sscanf(buf, "round-trip (ms) min/avg/max/stddev = %*f/%lf/%*f/%*f%n", &result.round_trip_average, &match) == 1 && match) ||
480 (sscanf(buf,"round-trip (ms) min/avg/max/stddev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 502 (sscanf(buf, "rtt min/avg/max/mdev = %*f/%lf/%*f/%*f ms%n", &result.round_trip_average, &match) == 1 && match) ||
481 (sscanf(buf,"rtt min/avg/max/mdev = %*f/%f/%*f/%*f ms%n",&rta,&match) && match) || 503 (sscanf(buf, "%*[^=] = %*fms, %*[^=] = %*fms, %*[^=] = %lfms%n", &result.round_trip_average, &match) == 1 && match)) {
482 (sscanf(buf, "%*[^=] = %*fms, %*[^=] = %*fms, %*[^=] = %fms%n", &rta, &match) && match)
483 )
484 continue; 504 continue;
505 }
485 } 506 }
486 507
487 /* this is needed because there is no rta if all packets are lost */ 508 /* this is needed because there is no rta if all packets are lost */
488 if (pl == 100) 509 if (result.packet_loss == 100) {
489 rta = crta; 510 result.round_trip_average = crta;
511 }
490 512
491 /* check stderr, setting at least WARNING if there is output here */ 513 /* check stderr, setting at least WARNING if there is output here */
492 /* Add warning into warn_text */ 514 /* Add warning into warn_text */
493 while (fgets (buf, MAX_INPUT_BUFFER - 1, child_stderr)) { 515 while (fgets(buf, MAX_INPUT_BUFFER - 1, child_stderr)) {
494 if ( 516 if (!strstr(buf, "WARNING - no SO_TIMESTAMP support, falling back to SIOCGSTAMP") && !strstr(buf, "Warning: time of day goes back")
495 ! strstr(buf,"WARNING - no SO_TIMESTAMP support, falling back to SIOCGSTAMP")
496 && ! strstr(buf,"Warning: time of day goes back")
497 517
498 ) { 518 ) {
499 if (verbose >= 3) { 519 if (verbose >= 3) {
500 printf("Got stderr: %s", buf); 520 printf("Got stderr: %s", buf);
501 } 521 }
502 if ((result=error_scan(buf, addr)) == STATE_OK) { 522 if ((result.state = error_scan(buf, addr)) == STATE_OK) {
503 result = STATE_WARNING; 523 result.state = STATE_WARNING;
504 if (warn_text == NULL) { 524 if (warn_text == NULL) {
505 warn_text = strdup(_("System call sent warnings to stderr ")); 525 warn_text = strdup(_("System call sent warnings to stderr "));
506 } else { 526 } else {
@@ -510,111 +530,97 @@ run_ping (const char *cmd, const char *addr)
510 } 530 }
511 } 531 }
512 532
513 (void) fclose (child_stderr); 533 (void)fclose(child_stderr);
514 534
535 spclose(child_process);
515 536
516 spclose (child_process); 537 if (warn_text == NULL) {
517
518 if (warn_text == NULL)
519 warn_text = strdup(""); 538 warn_text = strdup("");
539 }
520 540
521 return result; 541 return result;
522} 542}
523 543
544mp_state_enum error_scan(char buf[MAX_INPUT_BUFFER], const char *addr) {
545 if (strstr(buf, "Network is unreachable") || strstr(buf, "Destination Net Unreachable") || strstr(buf, "No route")) {
546 die(STATE_CRITICAL, _("CRITICAL - Network Unreachable (%s)\n"), addr);
547 } else if (strstr(buf, "Destination Host Unreachable") || strstr(buf, "Address unreachable")) {
548 die(STATE_CRITICAL, _("CRITICAL - Host Unreachable (%s)\n"), addr);
549 } else if (strstr(buf, "Destination Port Unreachable") || strstr(buf, "Port unreachable")) {
550 die(STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Port Unreachable (%s)\n"), addr);
551 } else if (strstr(buf, "Destination Protocol Unreachable")) {
552 die(STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Protocol Unreachable (%s)\n"), addr);
553 } else if (strstr(buf, "Destination Net Prohibited")) {
554 die(STATE_CRITICAL, _("CRITICAL - Network Prohibited (%s)\n"), addr);
555 } else if (strstr(buf, "Destination Host Prohibited")) {
556 die(STATE_CRITICAL, _("CRITICAL - Host Prohibited (%s)\n"), addr);
557 } else if (strstr(buf, "Packet filtered") || strstr(buf, "Administratively prohibited")) {
558 die(STATE_CRITICAL, _("CRITICAL - Packet Filtered (%s)\n"), addr);
559 } else if (strstr(buf, "unknown host")) {
560 die(STATE_CRITICAL, _("CRITICAL - Host not found (%s)\n"), addr);
561 } else if (strstr(buf, "Time to live exceeded") || strstr(buf, "Time exceeded")) {
562 die(STATE_CRITICAL, _("CRITICAL - Time to live exceeded (%s)\n"), addr);
563 } else if (strstr(buf, "Destination unreachable: ")) {
564 die(STATE_CRITICAL, _("CRITICAL - Destination Unreachable (%s)\n"), addr);
565 }
524 566
567 if (strstr(buf, "(DUP!)") || strstr(buf, "DUPLICATES FOUND")) {
568 if (warn_text == NULL) {
569 warn_text = strdup(_(WARN_DUPLICATES));
570 } else if (!strstr(warn_text, _(WARN_DUPLICATES)) && xasprintf(&warn_text, "%s %s", warn_text, _(WARN_DUPLICATES)) == -1) {
571 die(STATE_UNKNOWN, _("Unable to realloc warn_text\n"));
572 }
573 return STATE_WARNING;
574 }
525 575
526int 576 return STATE_OK;
527error_scan (char buf[MAX_INPUT_BUFFER], const char *addr)
528{
529 if (strstr (buf, "Network is unreachable") ||
530 strstr (buf, "Destination Net Unreachable") ||
531 strstr (buf, "No route")
532 )
533 die (STATE_CRITICAL, _("CRITICAL - Network Unreachable (%s)\n"), addr);
534 else if (strstr (buf, "Destination Host Unreachable") || strstr(buf, "Address unreachable"))
535 die (STATE_CRITICAL, _("CRITICAL - Host Unreachable (%s)\n"), addr);
536 else if (strstr (buf, "Destination Port Unreachable") || strstr(buf, "Port unreachable"))
537 die (STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Port Unreachable (%s)\n"), addr);
538 else if (strstr (buf, "Destination Protocol Unreachable"))
539 die (STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Protocol Unreachable (%s)\n"), addr);
540 else if (strstr (buf, "Destination Net Prohibited"))
541 die (STATE_CRITICAL, _("CRITICAL - Network Prohibited (%s)\n"), addr);
542 else if (strstr (buf, "Destination Host Prohibited"))
543 die (STATE_CRITICAL, _("CRITICAL - Host Prohibited (%s)\n"), addr);
544 else if (strstr (buf, "Packet filtered") || strstr(buf, "Administratively prohibited"))
545 die (STATE_CRITICAL, _("CRITICAL - Packet Filtered (%s)\n"), addr);
546 else if (strstr (buf, "unknown host" ))
547 die (STATE_CRITICAL, _("CRITICAL - Host not found (%s)\n"), addr);
548 else if (strstr (buf, "Time to live exceeded") || strstr(buf, "Time exceeded"))
549 die (STATE_CRITICAL, _("CRITICAL - Time to live exceeded (%s)\n"), addr);
550 else if (strstr (buf, "Destination unreachable: "))
551 die (STATE_CRITICAL, _("CRITICAL - Destination Unreachable (%s)\n"), addr);
552
553 if (strstr (buf, "(DUP!)") || strstr (buf, "DUPLICATES FOUND")) {
554 if (warn_text == NULL)
555 warn_text = strdup (_(WARN_DUPLICATES));
556 else if (! strstr (warn_text, _(WARN_DUPLICATES)) &&
557 xasprintf (&warn_text, "%s %s", warn_text, _(WARN_DUPLICATES)) == -1)
558 die (STATE_UNKNOWN, _("Unable to realloc warn_text\n"));
559 return (STATE_WARNING);
560 }
561
562 return (STATE_OK);
563} 577}
564 578
579void print_help(void) {
580 print_revision(progname, NP_VERSION);
565 581
582 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
583 printf(COPYRIGHT, copyright, email);
566 584
567void 585 printf(_("Use ping to check connection statistics for a remote host."));
568print_help (void)
569{
570 print_revision (progname, NP_VERSION);
571
572 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
573 printf (COPYRIGHT, copyright, email);
574
575 printf (_("Use ping to check connection statistics for a remote host."));
576 586
577 printf ("\n\n"); 587 printf("\n\n");
578 588
579 print_usage (); 589 print_usage();
580 590
581 printf (UT_HELP_VRSN); 591 printf(UT_HELP_VRSN);
582 printf (UT_EXTRA_OPTS); 592 printf(UT_EXTRA_OPTS);
583 593
584 printf (UT_IPv46); 594 printf(UT_IPv46);
585 595
586 printf (" %s\n", "-H, --hostname=HOST"); 596 printf(" %s\n", "-H, --hostname=HOST");
587 printf (" %s\n", _("host to ping")); 597 printf(" %s\n", _("host to ping"));
588 printf (" %s\n", "-w, --warning=THRESHOLD"); 598 printf(" %s\n", "-w, --warning=THRESHOLD");
589 printf (" %s\n", _("warning threshold pair")); 599 printf(" %s\n", _("warning threshold pair"));
590 printf (" %s\n", "-c, --critical=THRESHOLD"); 600 printf(" %s\n", "-c, --critical=THRESHOLD");
591 printf (" %s\n", _("critical threshold pair")); 601 printf(" %s\n", _("critical threshold pair"));
592 printf (" %s\n", "-p, --packets=INTEGER"); 602 printf(" %s\n", "-p, --packets=INTEGER");
593 printf (" %s ", _("number of ICMP ECHO packets to send")); 603 printf(" %s ", _("number of ICMP ECHO packets to send"));
594 printf (_("(Default: %d)\n"), DEFAULT_MAX_PACKETS); 604 printf(_("(Default: %d)\n"), DEFAULT_MAX_PACKETS);
595 printf (" %s\n", "-L, --link"); 605 printf(" %s\n", "-L, --link");
596 printf (" %s\n", _("show HTML in the plugin output (obsoleted by urlize)")); 606 printf(" %s\n", _("show HTML in the plugin output (obsoleted by urlize)"));
597 607
598 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 608 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
599 609
600 printf ("\n"); 610 printf("\n");
601 printf ("%s\n", _("THRESHOLD is <rta>,<pl>% where <rta> is the round trip average travel")); 611 printf("%s\n", _("THRESHOLD is <rta>,<pl>% where <rta> is the round trip average travel"));
602 printf ("%s\n", _("time (ms) which triggers a WARNING or CRITICAL state, and <pl> is the")); 612 printf("%s\n", _("time (ms) which triggers a WARNING or CRITICAL state, and <pl> is the"));
603 printf ("%s\n", _("percentage of packet loss to trigger an alarm state.")); 613 printf("%s\n", _("percentage of packet loss to trigger an alarm state."));
604 614
605 printf ("\n"); 615 printf("\n");
606 printf ("%s\n", _("This plugin uses the ping command to probe the specified host for packet loss")); 616 printf("%s\n", _("This plugin uses the ping command to probe the specified host for packet loss"));
607 printf ("%s\n", _("(percentage) and round trip average (milliseconds). It can produce HTML output")); 617 printf("%s\n", _("(percentage) and round trip average (milliseconds). It can produce HTML output."));
608 printf ("%s\n", _("linking to a traceroute CGI contributed by Ian Cass. The CGI can be found in"));
609 printf ("%s\n", _("the contrib area of the downloads section at http://www.nagios.org/"));
610 618
611 printf (UT_SUPPORT); 619 printf(UT_SUPPORT);
612} 620}
613 621
614void 622void print_usage(void) {
615print_usage (void) 623 printf("%s\n", _("Usage:"));
616{ 624 printf("%s -H <host_address> -w <wrta>,<wpl>%% -c <crta>,<cpl>%%\n", progname);
617 printf ("%s\n", _("Usage:")); 625 printf(" [-p packets] [-t timeout] [-4|-6]\n");
618 printf ("%s -H <host_address> -w <wrta>,<wpl>%% -c <crta>,<cpl>%%\n", progname);
619 printf (" [-p packets] [-t timeout] [-4|-6]\n");
620} 626}