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.c903
1 files changed, 478 insertions, 425 deletions
diff --git a/plugins/check_ping.c b/plugins/check_ping.c
index 6e162e6a..61feb958 100644
--- a/plugins/check_ping.c
+++ b/plugins/check_ping.c
@@ -1,620 +1,673 @@
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 ||
139 pinged.round_trip_average < 0) {
140 pinged.state = STATE_CRITICAL;
141 } else if (pinged.packet_loss >= config.wpl || pinged.round_trip_average >= config.wrta) {
142 pinged.state = STATE_WARNING;
143 } else if (pinged.packet_loss >= 0 && pinged.round_trip_average >= 0) {
144 pinged.state = max_state(STATE_OK, pinged.state);
145 }
146
147 if (config.n_addresses > 1 && pinged.state != STATE_UNKNOWN) {
148 die(STATE_OK, "%s is alive\n", config.addresses[i]);
144 } 149 }
145 150
146 if (pl >= cpl || rta >= crta || rta < 0) 151 if (config.display_html) {
147 this_result = STATE_CRITICAL; 152 printf("<A HREF='%s/traceroute.cgi?%s'>", CGIURL, config.addresses[i]);
148 else if (pl >= wpl || rta >= wrta) 153 }
149 this_result = STATE_WARNING; 154 if (pinged.packet_loss == 100) {
150 else if (pl >= 0 && rta >= 0) 155 printf(_("PING %s - %sPacket loss = %d%%"), state_text(pinged.state), warn_text,
151 this_result = max_state (STATE_OK, this_result); 156 pinged.packet_loss);
152 157 } else {
153 if (n_addresses > 1 && this_result != STATE_UNKNOWN) 158 printf(_("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms"), state_text(pinged.state),
154 die (STATE_OK, "%s is alive\n", addresses[i]); 159 warn_text, pinged.packet_loss, pinged.round_trip_average);
155 160 }
156 if (display_html == true) 161 if (config.display_html) {
157 printf ("<A HREF='%s/traceroute.cgi?%s'>", CGIURL, addresses[i]); 162 printf("</A>");
158 if (pl == 100) 163 }
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 164
167 /* Print performance data */ 165 /* Print performance data */
168 if (pl != 100) { 166 if (pinged.packet_loss != 100) {
169 printf("|%s", fperfdata ("rta", (double) rta, "ms", 167 printf("|%s",
170 wrta>0?true:false, wrta, 168 fperfdata("rta", pinged.round_trip_average, "ms", (bool)(config.wrta > 0),
171 crta>0?true:false, crta, 169 config.wrta, (bool)(config.crta > 0), config.crta, true, 0, false, 0));
172 true, 0, false, 0));
173 } else { 170 } else {
174 printf("| rta=U;%f;%f;;", wrta, crta); 171 printf("| rta=U;%f;%f;;", config.wrta, config.crta);
175 } 172 }
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 173
181 if (verbose >= 2) 174 printf(" %s\n",
182 printf ("%f:%d%% %f:%d%%\n", wrta, wpl, crta, cpl); 175 perfdata("pl", (long)pinged.packet_loss, "%", (bool)(config.wpl > 0), config.wpl,
176 (bool)(config.cpl > 0), config.cpl, true, 0, false, 0));
177
178 if (verbose >= 2) {
179 printf("%f:%d%% %f:%d%%\n", config.wrta, config.wpl, config.crta, config.cpl);
180 }
183 181
184 result = max_state (result, this_result); 182 result = max_state(result, pinged.state);
185 free (rawcmd); 183 free(rawcmd);
186 free (cmd); 184 free(cmd);
187 } 185 }
188 186
189 return result; 187 return result;
190} 188}
191 189
192
193
194/* process command-line arguments */ 190/* process command-line arguments */
195int 191check_ping_config_wrapper process_arguments(int argc, char **argv) {
196process_arguments (int argc, char **argv) 192 static struct option longopts[] = {STD_LONG_OPTS,
197{ 193 {"packets", required_argument, 0, 'p'},
198 int c = 1; 194 {"nohtml", no_argument, 0, 'n'},
199 char *ptr; 195 {"link", no_argument, 0, 'L'},
200 196 {"use-ipv4", no_argument, 0, '4'},
201 int option = 0; 197 {"use-ipv6", no_argument, 0, '6'},
202 static struct option longopts[] = { 198 {0, 0, 0, 0}};
203 STD_LONG_OPTS, 199
204 {"packets", required_argument, 0, 'p'}, 200 check_ping_config_wrapper result = {
205 {"nohtml", no_argument, 0, 'n'}, 201 .errorcode = OK,
206 {"link", no_argument, 0, 'L'}, 202 .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 }; 203 };
211 204
212 if (argc < 2) 205 if (argc < 2) {
213 return ERROR; 206 result.errorcode = ERROR;
207 return result;
208 }
214 209
215 for (c = 1; c < argc; c++) { 210 for (int index = 1; index < argc; index++) {
216 if (strcmp ("-to", argv[c]) == 0) 211 if (strcmp("-to", argv[index]) == 0) {
217 strcpy (argv[c], "-t"); 212 strcpy(argv[index], "-t");
218 if (strcmp ("-nohtml", argv[c]) == 0) 213 }
219 strcpy (argv[c], "-n"); 214 if (strcmp("-nohtml", argv[index]) == 0) {
215 strcpy(argv[index], "-n");
216 }
220 } 217 }
221 218
222 while (1) { 219 int option = 0;
223 c = getopt_long (argc, argv, "VvhnL46t:c:w:H:p:", longopts, &option); 220 size_t max_addr = MAX_ADDR_START;
221 while (true) {
222 int option_index = getopt_long(argc, argv, "VvhnL46t:c:w:H:p:", longopts, &option);
224 223
225 if (c == -1 || c == EOF) 224 if (option_index == -1 || option_index == EOF) {
226 break; 225 break;
226 }
227 227
228 switch (c) { 228 switch (option_index) {
229 case '?': /* usage */ 229 case '?': /* usage */
230 usage5 (); 230 usage5();
231 case 'h': /* help */ 231 case 'h': /* help */
232 print_help (); 232 print_help();
233 exit (STATE_UNKNOWN); 233 exit(STATE_UNKNOWN);
234 break; 234 break;
235 case 'V': /* version */ 235 case 'V': /* version */
236 print_revision (progname, NP_VERSION); 236 print_revision(progname, NP_VERSION);
237 exit (STATE_UNKNOWN); 237 exit(STATE_UNKNOWN);
238 break; 238 break;
239 case 't': /* timeout period */ 239 case 't': /* timeout period */
240 timeout_interval = atoi (optarg); 240 timeout_interval = atoi(optarg);
241 break; 241 break;
242 case 'v': /* verbose mode */ 242 case 'v': /* verbose mode */
243 verbose++; 243 verbose++;
244 break; 244 break;
245 case '4': /* IPv4 only */ 245 case '4': /* IPv4 only */
246 address_family = AF_INET; 246 address_family = AF_INET;
247 break; 247 break;
248 case '6': /* IPv6 only */ 248 case '6': /* IPv6 only */
249#ifdef USE_IPV6 249#ifdef USE_IPV6
250 address_family = AF_INET6; 250 address_family = AF_INET6;
251#else 251#else
252 usage (_("IPv6 support not available\n")); 252 usage(_("IPv6 support not available\n"));
253#endif 253#endif
254 break; 254 break;
255 case 'H': /* hostname */ 255 case 'H': /* hostname */ {
256 ptr=optarg; 256 char *ptr = optarg;
257 while (1) { 257 while (true) {
258 n_addresses++; 258 result.config.n_addresses++;
259 if (n_addresses > max_addr) { 259 if (result.config.n_addresses > max_addr) {
260 max_addr *= 2; 260 max_addr *= 2;
261 addresses = realloc (addresses, sizeof(char*) * max_addr); 261 result.config.addresses =
262 if (addresses == NULL) 262 realloc(result.config.addresses, sizeof(char *) * max_addr);
263 die (STATE_UNKNOWN, _("Could not realloc() addresses\n")); 263 if (result.config.addresses == NULL) {
264 die(STATE_UNKNOWN, _("Could not realloc() addresses\n"));
265 }
264 } 266 }
265 addresses[n_addresses-1] = ptr; 267 result.config.addresses[result.config.n_addresses - 1] = ptr;
266 if ((ptr = index (ptr, ','))) { 268 if ((ptr = index(ptr, ','))) {
267 strcpy (ptr, ""); 269 strcpy(ptr, "");
268 ptr += sizeof(char); 270 ptr += sizeof(char);
269 } else { 271 } else {
270 break; 272 break;
271 } 273 }
272 } 274 }
275 } break;
276 case 'p': /* number of packets to send */
277 if (is_intnonneg(optarg)) {
278 result.config.max_packets = atoi(optarg);
279 } else {
280 usage2(_("<max_packets> (%s) must be a non-negative number\n"), optarg);
281 }
273 break; 282 break;
274 case 'p': /* number of packets to send */ 283 case 'n': /* no HTML */
275 if (is_intnonneg (optarg)) 284 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; 285 break;
283 case 'L': /* show HTML */ 286 case 'L': /* show HTML */
284 display_html = true; 287 result.config.display_html = true;
285 break; 288 break;
286 case 'c': 289 case 'c':
287 get_threshold (optarg, &crta, &cpl); 290 get_threshold(optarg, &result.config.crta, &result.config.cpl);
288 break; 291 break;
289 case 'w': 292 case 'w':
290 get_threshold (optarg, &wrta, &wpl); 293 get_threshold(optarg, &result.config.wrta, &result.config.wpl);
291 break; 294 break;
292 } 295 }
293 } 296 }
294 297
295 c = optind; 298 int arg_counter = optind;
296 if (c == argc) 299 if (arg_counter == argc) {
297 return validate_arguments (); 300 return validate_arguments(result);
301 }
298 302
299 if (addresses[0] == NULL) { 303 if (result.config.addresses[0] == NULL) {
300 if (!is_host (argv[c])) { 304 if (!is_host(argv[arg_counter])) {
301 usage2 (_("Invalid hostname/address"), argv[c]); 305 usage2(_("Invalid hostname/address"), argv[arg_counter]);
302 } else { 306 } else {
303 addresses[0] = argv[c++]; 307 result.config.addresses[0] = argv[arg_counter++];
304 n_addresses++; 308 result.config.n_addresses++;
305 if (c == argc) 309 if (arg_counter == argc) {
306 return validate_arguments (); 310 return validate_arguments(result);
311 }
307 } 312 }
308 } 313 }
309 314
310 if (wpl == UNKNOWN_PACKET_LOSS) { 315 if (result.config.wpl == UNKNOWN_PACKET_LOSS) {
311 if (!is_intpercent (argv[c])) { 316 if (!is_intpercent(argv[arg_counter])) {
312 printf (_("<wpl> (%s) must be an integer percentage\n"), argv[c]); 317 printf(_("<wpl> (%s) must be an integer percentage\n"), argv[arg_counter]);
313 return ERROR; 318 result.errorcode = ERROR;
314 } else { 319 return result;
315 wpl = atoi (argv[c++]); 320 }
316 if (c == argc) 321 result.config.wpl = atoi(argv[arg_counter++]);
317 return validate_arguments (); 322 if (arg_counter == argc) {
323 return validate_arguments(result);
318 } 324 }
319 } 325 }
320 326
321 if (cpl == UNKNOWN_PACKET_LOSS) { 327 if (result.config.cpl == UNKNOWN_PACKET_LOSS) {
322 if (!is_intpercent (argv[c])) { 328 if (!is_intpercent(argv[arg_counter])) {
323 printf (_("<cpl> (%s) must be an integer percentage\n"), argv[c]); 329 printf(_("<cpl> (%s) must be an integer percentage\n"), argv[arg_counter]);
324 return ERROR; 330 result.errorcode = ERROR;
325 } else { 331 return result;
326 cpl = atoi (argv[c++]); 332 }
327 if (c == argc) 333 result.config.cpl = atoi(argv[arg_counter++]);
328 return validate_arguments (); 334 if (arg_counter == argc) {
335 return validate_arguments(result);
329 } 336 }
330 } 337 }
331 338
332 if (wrta < 0.0) { 339 if (result.config.wrta < 0.0) {
333 if (is_negative (argv[c])) { 340 if (is_negative(argv[arg_counter])) {
334 printf (_("<wrta> (%s) must be a non-negative number\n"), argv[c]); 341 printf(_("<wrta> (%s) must be a non-negative number\n"), argv[arg_counter]);
335 return ERROR; 342 result.errorcode = ERROR;
336 } else { 343 return result;
337 wrta = atof (argv[c++]); 344 }
338 if (c == argc) 345 result.config.wrta = atof(argv[arg_counter++]);
339 return validate_arguments (); 346 if (arg_counter == argc) {
347 return validate_arguments(result);
340 } 348 }
341 } 349 }
342 350
343 if (crta < 0.0) { 351 if (result.config.crta < 0.0) {
344 if (is_negative (argv[c])) { 352 if (is_negative(argv[arg_counter])) {
345 printf (_("<crta> (%s) must be a non-negative number\n"), argv[c]); 353 printf(_("<crta> (%s) must be a non-negative number\n"), argv[arg_counter]);
346 return ERROR; 354 result.errorcode = ERROR;
347 } else { 355 return result;
348 crta = atof (argv[c++]); 356 }
349 if (c == argc) 357 result.config.crta = atof(argv[arg_counter++]);
350 return validate_arguments (); 358 if (arg_counter == argc) {
359 return validate_arguments(result);
351 } 360 }
352 } 361 }
353 362
354 if (max_packets == -1) { 363 if (result.config.max_packets == -1) {
355 if (is_intnonneg (argv[c])) { 364 if (is_intnonneg(argv[arg_counter])) {
356 max_packets = atoi (argv[c++]); 365 result.config.max_packets = atoi(argv[arg_counter++]);
357 } else { 366 } else {
358 printf (_("<max_packets> (%s) must be a non-negative number\n"), argv[c]); 367 printf(_("<max_packets> (%s) must be a non-negative number\n"), argv[arg_counter]);
359 return ERROR; 368 result.errorcode = ERROR;
369 return result;
360 } 370 }
361 } 371 }
362 372
363 return validate_arguments (); 373 return validate_arguments(result);
364} 374}
365 375
366 376int get_threshold(char *arg, double *trta, int *tpl) {
367 377 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; 378 return OK;
373 else if (strpbrk (arg, ",:") && strstr (arg, "%") && sscanf (arg, "%f%*[:,]%d%%", trta, tpl) == 2) 379 }
380
381 if (strpbrk(arg, ",:") && strstr(arg, "%") && sscanf(arg, "%lf%*[:,]%d%%", trta, tpl) == 2) {
374 return OK; 382 return OK;
375 else if (strstr (arg, "%") && sscanf (arg, "%d%%", tpl) == 1) 383 }
384
385 if (strstr(arg, "%") && sscanf(arg, "%d%%", tpl) == 1) {
376 return OK; 386 return OK;
387 }
377 388
378 usage2 (_("%s: Warning threshold must be integer or percentage!\n\n"), arg); 389 usage2(_("%s: Warning threshold must be integer or percentage!\n\n"), arg);
379 return STATE_UNKNOWN; 390 return STATE_UNKNOWN;
380} 391}
381 392
382 393check_ping_config_wrapper validate_arguments(check_ping_config_wrapper config_wrapper) {
383 394 if (config_wrapper.config.wrta < 0.0) {
384int 395 printf(_("<wrta> was not set\n"));
385validate_arguments () 396 config_wrapper.errorcode = ERROR;
386{ 397 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 } 398 }
394 else if (crta < 0.0) { 399
395 printf (_("<crta> was not set\n")); 400 if (config_wrapper.config.crta < 0.0) {
396 return ERROR; 401 printf(_("<crta> was not set\n"));
402 config_wrapper.errorcode = ERROR;
403 return config_wrapper;
397 } 404 }
398 else if (wpl == UNKNOWN_PACKET_LOSS) { 405
399 printf (_("<wpl> was not set\n")); 406 if (config_wrapper.config.wpl == UNKNOWN_PACKET_LOSS) {
400 return ERROR; 407 printf(_("<wpl> was not set\n"));
408 config_wrapper.errorcode = ERROR;
409 return config_wrapper;
401 } 410 }
402 else if (cpl == UNKNOWN_PACKET_LOSS) { 411
403 printf (_("<cpl> was not set\n")); 412 if (config_wrapper.config.cpl == UNKNOWN_PACKET_LOSS) {
404 return ERROR; 413 printf(_("<cpl> was not set\n"));
414 config_wrapper.errorcode = ERROR;
415 return config_wrapper;
405 } 416 }
406 else if (wrta > crta) { 417
407 printf (_("<wrta> (%f) cannot be larger than <crta> (%f)\n"), wrta, crta); 418 if (config_wrapper.config.wrta > config_wrapper.config.crta) {
408 return ERROR; 419 printf(_("<wrta> (%f) cannot be larger than <crta> (%f)\n"), config_wrapper.config.wrta,
420 config_wrapper.config.crta);
421 config_wrapper.errorcode = ERROR;
422 return config_wrapper;
409 } 423 }
410 else if (wpl > cpl) { 424
411 printf (_("<wpl> (%d) cannot be larger than <cpl> (%d)\n"), wpl, cpl); 425 if (config_wrapper.config.wpl > config_wrapper.config.cpl) {
412 return ERROR; 426 printf(_("<wpl> (%d) cannot be larger than <cpl> (%d)\n"), config_wrapper.config.wpl,
427 config_wrapper.config.cpl);
428 config_wrapper.errorcode = ERROR;
429 return config_wrapper;
413 } 430 }
414 431
415 if (max_packets == -1) 432 if (config_wrapper.config.max_packets == -1) {
416 max_packets = DEFAULT_MAX_PACKETS; 433 config_wrapper.config.max_packets = DEFAULT_MAX_PACKETS;
434 }
417 435
418 max_seconds = crta / 1000.0 * max_packets + max_packets; 436 double max_seconds = (config_wrapper.config.crta / 1000.0 * config_wrapper.config.max_packets) +
419 if (max_seconds > timeout_interval) 437 config_wrapper.config.max_packets;
420 timeout_interval = (int)max_seconds; 438 if (max_seconds > timeout_interval) {
439 timeout_interval = (unsigned int)max_seconds;
440 }
421 441
422 for (i=0; i<n_addresses; i++) { 442 for (size_t i = 0; i < config_wrapper.config.n_addresses; i++) {
423 if (!is_host(addresses[i])) 443 if (!is_host(config_wrapper.config.addresses[i])) {
424 usage2 (_("Invalid hostname/address"), addresses[i]); 444 usage2(_("Invalid hostname/address"), config_wrapper.config.addresses[i]);
445 }
425 } 446 }
426 447
427 if (n_addresses == 0) { 448 if (config_wrapper.config.n_addresses == 0) {
428 usage (_("You must specify a server address or host name")); 449 usage(_("You must specify a server address or host name"));
429 } 450 }
430 451
431 return OK; 452 return config_wrapper;
432} 453}
433 454
455ping_result run_ping(const char *cmd, const char *addr, double crta) {
456 if ((child_process = spopen(cmd)) == NULL) {
457 die(STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd);
458 }
434 459
460 child_stderr = fdopen(child_stderr_array[fileno(child_process)], "r");
461 if (child_stderr == NULL) {
462 printf(_("Cannot open stderr for %s\n"), cmd);
463 }
435 464
436int
437run_ping (const char *cmd, const char *addr)
438{
439 char buf[MAX_INPUT_BUFFER]; 465 char buf[MAX_INPUT_BUFFER];
440 int result = STATE_UNKNOWN; 466 ping_result result = {
441 int match; 467 .state = STATE_UNKNOWN,
442 468 .packet_loss = UNKNOWN_PACKET_LOSS,
443 if ((child_process = spopen (cmd)) == NULL) 469 .round_trip_average = UNKNOWN_TRIP_TIME,
444 die (STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd); 470 };
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 471
452 if (verbose >= 3) 472 while (fgets(buf, MAX_INPUT_BUFFER - 1, child_process)) {
473 if (verbose >= 3) {
453 printf("Output: %s", buf); 474 printf("Output: %s", buf);
475 }
454 476
455 result = max_state (result, error_scan (buf, addr)); 477 result.state = max_state(result.state, error_scan(buf, addr));
456 478
457 /* get the percent loss statistics */ 479 /* get the percent loss statistics */
458 match = 0; 480 int match = 0;
459 if((sscanf(buf,"%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) || 481 if ((sscanf(
460 (sscanf(buf,"%*d packets transmitted, %*d packets received, +%*d duplicates, %d%% packet loss%n",&pl,&match) && match) || 482 buf,
461 (sscanf(buf,"%*d packets transmitted, %*d received, +%*d duplicates, %d%% packet loss%n",&pl,&match) && match) || 483 "%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss%n",
462 (sscanf(buf,"%*d packets transmitted, %*d packets received, %d%% packet loss%n",&pl,&match) && match) || 484 &result.packet_loss, &match) == 1 &&
463 (sscanf(buf,"%*d packets transmitted, %*d packets received, %d%% loss, time%n",&pl,&match) && match) || 485 match) ||
464 (sscanf(buf,"%*d packets transmitted, %*d received, %d%% loss, time%n",&pl,&match) && match) || 486 (sscanf(buf,
465 (sscanf(buf,"%*d packets transmitted, %*d received, %d%% packet loss, time%n",&pl,&match) && match) || 487 "%*d packets transmitted, %*d packets received, +%*d duplicates, %d%% packet "
466 (sscanf(buf,"%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) || 488 "loss%n",
467 (sscanf(buf,"%*d packets transmitted %*d received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) || 489 &result.packet_loss, &match) == 1 &&
468 (sscanf(buf,"%*[^(](%d%% %*[^)])%n",&pl,&match) && match) 490 match) ||
469 ) 491 (sscanf(buf,
492 "%*d packets transmitted, %*d received, +%*d duplicates, %d%% packet loss%n",
493 &result.packet_loss, &match) == 1 &&
494 match) ||
495 (sscanf(buf, "%*d packets transmitted, %*d packets received, %d%% packet loss%n",
496 &result.packet_loss, &match) == 1 &&
497 match) ||
498 (sscanf(buf, "%*d packets transmitted, %*d packets received, %d%% loss, time%n",
499 &result.packet_loss, &match) == 1 &&
500 match) ||
501 (sscanf(buf, "%*d packets transmitted, %*d received, %d%% loss, time%n",
502 &result.packet_loss, &match) == 1 &&
503 match) ||
504 (sscanf(buf, "%*d packets transmitted, %*d received, %d%% packet loss, time%n",
505 &result.packet_loss, &match) == 1 &&
506 match) == 1 ||
507 (sscanf(buf, "%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss%n",
508 &result.packet_loss, &match) == 1 &&
509 match) ||
510 (sscanf(buf, "%*d packets transmitted %*d received, +%*d errors, %d%% packet loss%n",
511 &result.packet_loss, &match) == 1 &&
512 match) ||
513 (sscanf(buf, "%*[^(](%d%% %*[^)])%n", &result.packet_loss, &match) == 1 && match)) {
470 continue; 514 continue;
515 }
471 516
472 /* get the round trip average */ 517 /* get the round trip average */
473 else 518 if ((sscanf(buf, "round-trip min/avg/max = %*f/%lf/%*f%n", &result.round_trip_average,
474 if((sscanf(buf,"round-trip min/avg/max = %*f/%f/%*f%n",&rta,&match) && match) || 519 &match) == 1 &&
475 (sscanf(buf,"round-trip min/avg/max/mdev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 520 match) ||
476 (sscanf(buf,"round-trip min/avg/max/sdev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 521 (sscanf(buf, "round-trip min/avg/max/mdev = %*f/%lf/%*f/%*f%n",
477 (sscanf(buf,"round-trip min/avg/max/stddev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 522 &result.round_trip_average, &match) == 1 &&
478 (sscanf(buf,"round-trip min/avg/max/std-dev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 523 match) ||
479 (sscanf(buf,"round-trip (ms) min/avg/max = %*f/%f/%*f%n",&rta,&match) && match) || 524 (sscanf(buf, "round-trip min/avg/max/sdev = %*f/%lf/%*f/%*f%n",
480 (sscanf(buf,"round-trip (ms) min/avg/max/stddev = %*f/%f/%*f/%*f%n",&rta,&match) && match) || 525 &result.round_trip_average, &match) == 1 &&
481 (sscanf(buf,"rtt min/avg/max/mdev = %*f/%f/%*f/%*f ms%n",&rta,&match) && match) || 526 match) ||
482 (sscanf(buf, "%*[^=] = %*fms, %*[^=] = %*fms, %*[^=] = %fms%n", &rta, &match) && match) 527 (sscanf(buf, "round-trip min/avg/max/stddev = %*f/%lf/%*f/%*f%n",
483 ) 528 &result.round_trip_average, &match) == 1 &&
529 match) ||
530 (sscanf(buf, "round-trip min/avg/max/std-dev = %*f/%lf/%*f/%*f%n",
531 &result.round_trip_average, &match) == 1 &&
532 match) ||
533 (sscanf(buf, "round-trip (ms) min/avg/max = %*f/%lf/%*f%n", &result.round_trip_average,
534 &match) == 1 &&
535 match) ||
536 (sscanf(buf, "round-trip (ms) min/avg/max/stddev = %*f/%lf/%*f/%*f%n",
537 &result.round_trip_average, &match) == 1 &&
538 match) ||
539 (sscanf(buf, "rtt min/avg/max/mdev = %*f/%lf/%*f/%*f ms%n", &result.round_trip_average,
540 &match) == 1 &&
541 match) ||
542 (sscanf(buf, "%*[^=] = %*fms, %*[^=] = %*fms, %*[^=] = %lfms%n",
543 &result.round_trip_average, &match) == 1 &&
544 match)) {
484 continue; 545 continue;
546 }
485 } 547 }
486 548
487 /* this is needed because there is no rta if all packets are lost */ 549 /* this is needed because there is no rta if all packets are lost */
488 if (pl == 100) 550 if (result.packet_loss == 100) {
489 rta = crta; 551 result.round_trip_average = crta;
552 }
490 553
491 /* check stderr, setting at least WARNING if there is output here */ 554 /* check stderr, setting at least WARNING if there is output here */
492 /* Add warning into warn_text */ 555 /* Add warning into warn_text */
493 while (fgets (buf, MAX_INPUT_BUFFER - 1, child_stderr)) { 556 while (fgets(buf, MAX_INPUT_BUFFER - 1, child_stderr)) {
494 if ( 557 if (!strstr(buf, "WARNING - no SO_TIMESTAMP support, falling back to SIOCGSTAMP") &&
495 ! strstr(buf,"WARNING - no SO_TIMESTAMP support, falling back to SIOCGSTAMP") 558 !strstr(buf, "Warning: time of day goes back")
496 && ! strstr(buf,"Warning: time of day goes back")
497 559
498 ) { 560 ) {
499 if (verbose >= 3) { 561 if (verbose >= 3) {
500 printf("Got stderr: %s", buf); 562 printf("Got stderr: %s", buf);
501 } 563 }
502 if ((result=error_scan(buf, addr)) == STATE_OK) { 564 if ((result.state = error_scan(buf, addr)) == STATE_OK) {
503 result = STATE_WARNING; 565 result.state = STATE_WARNING;
504 if (warn_text == NULL) { 566 if (warn_text == NULL) {
505 warn_text = strdup(_("System call sent warnings to stderr ")); 567 warn_text = strdup(_("System call sent warnings to stderr "));
506 } else { 568 } else {
507 xasprintf(&warn_text, "%s %s", warn_text, _("System call sent warnings to stderr ")); 569 xasprintf(&warn_text, "%s %s", warn_text,
570 _("System call sent warnings to stderr "));
508 } 571 }
509 } 572 }
510 } 573 }
511 } 574 }
512 575
513 (void) fclose (child_stderr); 576 (void)fclose(child_stderr);
514 577
578 spclose(child_process);
515 579
516 spclose (child_process); 580 if (warn_text == NULL) {
517
518 if (warn_text == NULL)
519 warn_text = strdup(""); 581 warn_text = strdup("");
582 }
520 583
521 return result; 584 return result;
522} 585}
523 586
587mp_state_enum error_scan(char buf[MAX_INPUT_BUFFER], const char *addr) {
588 if (strstr(buf, "Network is unreachable") || strstr(buf, "Destination Net Unreachable") ||
589 strstr(buf, "No route")) {
590 die(STATE_CRITICAL, _("CRITICAL - Network Unreachable (%s)\n"), addr);
591 } else if (strstr(buf, "Destination Host Unreachable") || strstr(buf, "Address unreachable")) {
592 die(STATE_CRITICAL, _("CRITICAL - Host Unreachable (%s)\n"), addr);
593 } else if (strstr(buf, "Destination Port Unreachable") || strstr(buf, "Port unreachable")) {
594 die(STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Port Unreachable (%s)\n"), addr);
595 } else if (strstr(buf, "Destination Protocol Unreachable")) {
596 die(STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Protocol Unreachable (%s)\n"), addr);
597 } else if (strstr(buf, "Destination Net Prohibited")) {
598 die(STATE_CRITICAL, _("CRITICAL - Network Prohibited (%s)\n"), addr);
599 } else if (strstr(buf, "Destination Host Prohibited")) {
600 die(STATE_CRITICAL, _("CRITICAL - Host Prohibited (%s)\n"), addr);
601 } else if (strstr(buf, "Packet filtered") || strstr(buf, "Administratively prohibited")) {
602 die(STATE_CRITICAL, _("CRITICAL - Packet Filtered (%s)\n"), addr);
603 } else if (strstr(buf, "unknown host")) {
604 die(STATE_CRITICAL, _("CRITICAL - Host not found (%s)\n"), addr);
605 } else if (strstr(buf, "Time to live exceeded") || strstr(buf, "Time exceeded")) {
606 die(STATE_CRITICAL, _("CRITICAL - Time to live exceeded (%s)\n"), addr);
607 } else if (strstr(buf, "Destination unreachable: ")) {
608 die(STATE_CRITICAL, _("CRITICAL - Destination Unreachable (%s)\n"), addr);
609 }
524 610
611 if (strstr(buf, "(DUP!)") || strstr(buf, "DUPLICATES FOUND")) {
612 if (warn_text == NULL) {
613 warn_text = strdup(_(WARN_DUPLICATES));
614 } else if (!strstr(warn_text, _(WARN_DUPLICATES)) &&
615 xasprintf(&warn_text, "%s %s", warn_text, _(WARN_DUPLICATES)) == -1) {
616 die(STATE_UNKNOWN, _("Unable to realloc warn_text\n"));
617 }
618 return STATE_WARNING;
619 }
525 620
526int 621 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} 622}
564 623
624void print_help(void) {
625 print_revision(progname, NP_VERSION);
565 626
627 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
628 printf(COPYRIGHT, copyright, email);
566 629
567void 630 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 631
577 printf ("\n\n"); 632 printf("\n\n");
578 633
579 print_usage (); 634 print_usage();
580 635
581 printf (UT_HELP_VRSN); 636 printf(UT_HELP_VRSN);
582 printf (UT_EXTRA_OPTS); 637 printf(UT_EXTRA_OPTS);
583 638
584 printf (UT_IPv46); 639 printf(UT_IPv46);
585 640
586 printf (" %s\n", "-H, --hostname=HOST"); 641 printf(" %s\n", "-H, --hostname=HOST");
587 printf (" %s\n", _("host to ping")); 642 printf(" %s\n", _("host to ping"));
588 printf (" %s\n", "-w, --warning=THRESHOLD"); 643 printf(" %s\n", "-w, --warning=THRESHOLD");
589 printf (" %s\n", _("warning threshold pair")); 644 printf(" %s\n", _("warning threshold pair"));
590 printf (" %s\n", "-c, --critical=THRESHOLD"); 645 printf(" %s\n", "-c, --critical=THRESHOLD");
591 printf (" %s\n", _("critical threshold pair")); 646 printf(" %s\n", _("critical threshold pair"));
592 printf (" %s\n", "-p, --packets=INTEGER"); 647 printf(" %s\n", "-p, --packets=INTEGER");
593 printf (" %s ", _("number of ICMP ECHO packets to send")); 648 printf(" %s ", _("number of ICMP ECHO packets to send"));
594 printf (_("(Default: %d)\n"), DEFAULT_MAX_PACKETS); 649 printf(_("(Default: %d)\n"), DEFAULT_MAX_PACKETS);
595 printf (" %s\n", "-L, --link"); 650 printf(" %s\n", "-L, --link");
596 printf (" %s\n", _("show HTML in the plugin output (obsoleted by urlize)")); 651 printf(" %s\n", _("show HTML in the plugin output (obsoleted by urlize)"));
597 652
598 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 653 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
599 654
600 printf ("\n"); 655 printf("\n");
601 printf ("%s\n", _("THRESHOLD is <rta>,<pl>% where <rta> is the round trip average travel")); 656 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")); 657 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.")); 658 printf("%s\n", _("percentage of packet loss to trigger an alarm state."));
604 659
605 printf ("\n"); 660 printf("\n");
606 printf ("%s\n", _("This plugin uses the ping command to probe the specified host for packet loss")); 661 printf("%s\n",
607 printf ("%s\n", _("(percentage) and round trip average (milliseconds). It can produce HTML output")); 662 _("This plugin uses the ping command to probe the specified host for packet loss"));
608 printf ("%s\n", _("linking to a traceroute CGI contributed by Ian Cass. The CGI can be found in")); 663 printf("%s\n",
609 printf ("%s\n", _("the contrib area of the downloads section at http://www.nagios.org/")); 664 _("(percentage) and round trip average (milliseconds). It can produce HTML output."));
610 665
611 printf (UT_SUPPORT); 666 printf(UT_SUPPORT);
612} 667}
613 668
614void 669void print_usage(void) {
615print_usage (void) 670 printf("%s\n", _("Usage:"));
616{ 671 printf("%s -H <host_address> -w <wrta>,<wpl>%% -c <crta>,<cpl>%%\n", progname);
617 printf ("%s\n", _("Usage:")); 672 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} 673}