diff options
Diffstat (limited to 'plugins/check_ping.c')
-rw-r--r-- | plugins/check_ping.c | 319 |
1 files changed, 171 insertions, 148 deletions
diff --git a/plugins/check_ping.c b/plugins/check_ping.c index d79a4a61..fcf68f81 100644 --- a/plugins/check_ping.c +++ b/plugins/check_ping.c | |||
@@ -36,39 +36,35 @@ const char *email = "devel@monitoring-plugins.org"; | |||
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 | 45 | ||
45 | enum { | 46 | typedef struct { |
46 | UNKNOWN_PACKET_LOSS = 200, /* 200% */ | 47 | int errorcode; |
47 | DEFAULT_MAX_PACKETS = 5 /* default no. of ICMP ECHO packets */ | 48 | check_ping_config config; |
48 | }; | 49 | } check_ping_config_wrapper; |
50 | static check_ping_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); | ||
51 | static check_ping_config_wrapper validate_arguments(check_ping_config_wrapper /*config_wrapper*/); | ||
49 | 52 | ||
50 | static int process_arguments(int /*argc*/, char ** /*argv*/); | 53 | static int get_threshold(char * /*arg*/, double * /*trta*/, int * /*tpl*/); |
51 | static int get_threshold(char * /*arg*/, float * /*trta*/, int * /*tpl*/); | 54 | |
52 | static int validate_arguments(void); | 55 | typedef struct { |
53 | static int run_ping(const char *cmd, const char *addr); | 56 | mp_state_enum state; |
54 | static int error_scan(char buf[MAX_INPUT_BUFFER], const char *addr); | 57 | double round_trip_average; |
58 | int packet_loss; | ||
59 | } ping_result; | ||
60 | static ping_result run_ping(const char *cmd, const char *addr, double /*crta*/); | ||
61 | |||
62 | static mp_state_enum error_scan(char buf[MAX_INPUT_BUFFER], const char *addr); | ||
55 | static void print_help(void); | 63 | static void print_help(void); |
56 | void print_usage(void); | 64 | void print_usage(void); |
57 | 65 | ||
58 | static bool display_html = false; | ||
59 | static int wpl = UNKNOWN_PACKET_LOSS; | ||
60 | static int cpl = UNKNOWN_PACKET_LOSS; | ||
61 | static float wrta = UNKNOWN_TRIP_TIME; | ||
62 | static float crta = UNKNOWN_TRIP_TIME; | ||
63 | static char **addresses = NULL; | ||
64 | static int n_addresses = 0; | ||
65 | static int max_addr = 1; | ||
66 | static int max_packets = -1; | ||
67 | static int verbose = 0; | 66 | static int verbose = 0; |
68 | 67 | ||
69 | static float round_trip_average = UNKNOWN_TRIP_TIME; | ||
70 | static int packet_loss = UNKNOWN_PACKET_LOSS; | ||
71 | |||
72 | static char *warn_text; | 68 | static char *warn_text; |
73 | 69 | ||
74 | int main(int argc, char **argv) { | 70 | int main(int argc, char **argv) { |
@@ -77,16 +73,16 @@ int main(int argc, char **argv) { | |||
77 | bindtextdomain(PACKAGE, LOCALEDIR); | 73 | bindtextdomain(PACKAGE, LOCALEDIR); |
78 | textdomain(PACKAGE); | 74 | textdomain(PACKAGE); |
79 | 75 | ||
80 | addresses = malloc(sizeof(char *) * max_addr); | ||
81 | addresses[0] = NULL; | ||
82 | |||
83 | /* Parse extra opts if any */ | 76 | /* Parse extra opts if any */ |
84 | argv = np_extra_opts(&argc, argv, progname); | 77 | argv = np_extra_opts(&argc, argv, progname); |
85 | 78 | ||
86 | if (process_arguments(argc, argv) == ERROR) { | 79 | check_ping_config_wrapper tmp_config = process_arguments(argc, argv); |
80 | if (tmp_config.errorcode == ERROR) { | ||
87 | usage4(_("Could not parse arguments")); | 81 | usage4(_("Could not parse arguments")); |
88 | } | 82 | } |
89 | 83 | ||
84 | const check_ping_config config = tmp_config.config; | ||
85 | |||
90 | /* Set signal handling and alarm */ | 86 | /* Set signal handling and alarm */ |
91 | if (signal(SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) { | 87 | if (signal(SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) { |
92 | usage4(_("Cannot catch SIGALRM")); | 88 | usage4(_("Cannot catch SIGALRM")); |
@@ -102,9 +98,9 @@ int main(int argc, char **argv) { | |||
102 | 98 | ||
103 | int result = STATE_UNKNOWN; | 99 | int result = STATE_UNKNOWN; |
104 | char *rawcmd = NULL; | 100 | char *rawcmd = NULL; |
105 | for (int i = 0; i < n_addresses; i++) { | 101 | for (size_t i = 0; i < config.n_addresses; i++) { |
106 | #ifdef PING6_COMMAND | 102 | #ifdef PING6_COMMAND |
107 | if (address_family != AF_INET && is_inet6_addr(addresses[i])) { | 103 | if (address_family != AF_INET && is_inet6_addr(config.addresses[i])) { |
108 | rawcmd = strdup(PING6_COMMAND); | 104 | rawcmd = strdup(PING6_COMMAND); |
109 | } else { | 105 | } else { |
110 | rawcmd = strdup(PING_COMMAND); | 106 | rawcmd = strdup(PING_COMMAND); |
@@ -118,12 +114,12 @@ int main(int argc, char **argv) { | |||
118 | /* does the host address of number of packets argument come first? */ | 114 | /* does the host address of number of packets argument come first? */ |
119 | #ifdef PING_PACKETS_FIRST | 115 | #ifdef PING_PACKETS_FIRST |
120 | # ifdef PING_HAS_TIMEOUT | 116 | # ifdef PING_HAS_TIMEOUT |
121 | xasprintf(&cmd, rawcmd, timeout_interval, max_packets, addresses[i]); | 117 | xasprintf(&cmd, rawcmd, timeout_interval, config.max_packets, config.addresses[i]); |
122 | # else | 118 | # else |
123 | xasprintf(&cmd, rawcmd, max_packets, addresses[i]); | 119 | xasprintf(&cmd, rawcmd, config.max_packets, addresses[i]); |
124 | # endif | 120 | # endif |
125 | #else | 121 | #else |
126 | xasprintf(&cmd, rawcmd, addresses[i], max_packets); | 122 | xasprintf(&cmd, rawcmd, addresses[i], config.max_packets); |
127 | #endif | 123 | #endif |
128 | 124 | ||
129 | if (verbose >= 2) { | 125 | if (verbose >= 2) { |
@@ -131,53 +127,55 @@ int main(int argc, char **argv) { | |||
131 | } | 127 | } |
132 | 128 | ||
133 | /* run the command */ | 129 | /* run the command */ |
134 | int this_result = run_ping(cmd, addresses[i]); | ||
135 | 130 | ||
136 | if (packet_loss == UNKNOWN_PACKET_LOSS || round_trip_average < 0.0) { | 131 | ping_result pinged = run_ping(cmd, config.addresses[i], config.crta); |
132 | |||
133 | if (pinged.packet_loss == UNKNOWN_PACKET_LOSS || pinged.round_trip_average < 0.0) { | ||
137 | printf("%s\n", cmd); | 134 | printf("%s\n", cmd); |
138 | die(STATE_UNKNOWN, _("CRITICAL - Could not interpret output from ping command\n")); | 135 | die(STATE_UNKNOWN, _("CRITICAL - Could not interpret output from ping command\n")); |
139 | } | 136 | } |
140 | 137 | ||
141 | if (packet_loss >= cpl || round_trip_average >= crta || round_trip_average < 0) { | 138 | if (pinged.packet_loss >= config.cpl || pinged.round_trip_average >= config.crta || pinged.round_trip_average < 0) { |
142 | this_result = STATE_CRITICAL; | 139 | pinged.state = STATE_CRITICAL; |
143 | } else if (packet_loss >= wpl || round_trip_average >= wrta) { | 140 | } else if (pinged.packet_loss >= config.wpl || pinged.round_trip_average >= config.wrta) { |
144 | this_result = STATE_WARNING; | 141 | pinged.state = STATE_WARNING; |
145 | } else if (packet_loss >= 0 && round_trip_average >= 0) { | 142 | } else if (pinged.packet_loss >= 0 && pinged.round_trip_average >= 0) { |
146 | this_result = max_state(STATE_OK, this_result); | 143 | pinged.state = max_state(STATE_OK, pinged.state); |
147 | } | 144 | } |
148 | 145 | ||
149 | if (n_addresses > 1 && this_result != STATE_UNKNOWN) { | 146 | if (config.n_addresses > 1 && pinged.state != STATE_UNKNOWN) { |
150 | die(STATE_OK, "%s is alive\n", addresses[i]); | 147 | die(STATE_OK, "%s is alive\n", config.addresses[i]); |
151 | } | 148 | } |
152 | 149 | ||
153 | if (display_html) { | 150 | if (config.display_html) { |
154 | printf("<A HREF='%s/traceroute.cgi?%s'>", CGIURL, addresses[i]); | 151 | printf("<A HREF='%s/traceroute.cgi?%s'>", CGIURL, config.addresses[i]); |
155 | } | 152 | } |
156 | if (packet_loss == 100) { | 153 | if (pinged.packet_loss == 100) { |
157 | printf(_("PING %s - %sPacket loss = %d%%"), state_text(this_result), warn_text, packet_loss); | 154 | printf(_("PING %s - %sPacket loss = %d%%"), state_text(pinged.state), warn_text, pinged.packet_loss); |
158 | } else { | 155 | } else { |
159 | printf(_("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms"), state_text(this_result), warn_text, packet_loss, | 156 | printf(_("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms"), state_text(pinged.state), warn_text, pinged.packet_loss, |
160 | round_trip_average); | 157 | pinged.round_trip_average); |
161 | } | 158 | } |
162 | if (display_html) { | 159 | if (config.display_html) { |
163 | printf("</A>"); | 160 | printf("</A>"); |
164 | } | 161 | } |
165 | 162 | ||
166 | /* Print performance data */ | 163 | /* Print performance data */ |
167 | if (packet_loss != 100) { | 164 | if (pinged.packet_loss != 100) { |
168 | printf("|%s", | 165 | printf("|%s", fperfdata("rta", pinged.round_trip_average, "ms", (bool)(config.wrta > 0), config.wrta, |
169 | fperfdata("rta", (double)round_trip_average, "ms", (bool)(wrta > 0), wrta, (bool)(crta > 0), crta, true, 0, false, 0)); | 166 | (bool)(config.crta > 0), config.crta, true, 0, false, 0)); |
170 | } else { | 167 | } else { |
171 | printf("| rta=U;%f;%f;;", wrta, crta); | 168 | printf("| rta=U;%f;%f;;", config.wrta, config.crta); |
172 | } | 169 | } |
173 | 170 | ||
174 | printf(" %s\n", perfdata("pl", (long)packet_loss, "%", (bool)(wpl > 0), wpl, (bool)(cpl > 0), cpl, true, 0, false, 0)); | 171 | printf(" %s\n", perfdata("pl", (long)pinged.packet_loss, "%", (bool)(config.wpl > 0), config.wpl, (bool)(config.cpl > 0), |
172 | config.cpl, true, 0, false, 0)); | ||
175 | 173 | ||
176 | if (verbose >= 2) { | 174 | if (verbose >= 2) { |
177 | printf("%f:%d%% %f:%d%%\n", wrta, wpl, crta, cpl); | 175 | printf("%f:%d%% %f:%d%%\n", config.wrta, config.wpl, config.crta, config.cpl); |
178 | } | 176 | } |
179 | 177 | ||
180 | result = max_state(result, this_result); | 178 | result = max_state(result, pinged.state); |
181 | free(rawcmd); | 179 | free(rawcmd); |
182 | free(cmd); | 180 | free(cmd); |
183 | } | 181 | } |
@@ -186,7 +184,7 @@ int main(int argc, char **argv) { | |||
186 | } | 184 | } |
187 | 185 | ||
188 | /* process command-line arguments */ | 186 | /* process command-line arguments */ |
189 | int process_arguments(int argc, char **argv) { | 187 | check_ping_config_wrapper process_arguments(int argc, char **argv) { |
190 | static struct option longopts[] = {STD_LONG_OPTS, | 188 | static struct option longopts[] = {STD_LONG_OPTS, |
191 | {"packets", required_argument, 0, 'p'}, | 189 | {"packets", required_argument, 0, 'p'}, |
192 | {"nohtml", no_argument, 0, 'n'}, | 190 | {"nohtml", no_argument, 0, 'n'}, |
@@ -195,8 +193,14 @@ int process_arguments(int argc, char **argv) { | |||
195 | {"use-ipv6", no_argument, 0, '6'}, | 193 | {"use-ipv6", no_argument, 0, '6'}, |
196 | {0, 0, 0, 0}}; | 194 | {0, 0, 0, 0}}; |
197 | 195 | ||
196 | check_ping_config_wrapper result = { | ||
197 | .errorcode = OK, | ||
198 | .config = check_ping_config_init(), | ||
199 | }; | ||
200 | |||
198 | if (argc < 2) { | 201 | if (argc < 2) { |
199 | return ERROR; | 202 | result.errorcode = ERROR; |
203 | return result; | ||
200 | } | 204 | } |
201 | 205 | ||
202 | for (int index = 1; index < argc; index++) { | 206 | for (int index = 1; index < argc; index++) { |
@@ -209,6 +213,7 @@ int process_arguments(int argc, char **argv) { | |||
209 | } | 213 | } |
210 | 214 | ||
211 | int option = 0; | 215 | int option = 0; |
216 | size_t max_addr = MAX_ADDR_START; | ||
212 | while (true) { | 217 | while (true) { |
213 | int option_index = getopt_long(argc, argv, "VvhnL46t:c:w:H:p:", longopts, &option); | 218 | int option_index = getopt_long(argc, argv, "VvhnL46t:c:w:H:p:", longopts, &option); |
214 | 219 | ||
@@ -246,15 +251,15 @@ int process_arguments(int argc, char **argv) { | |||
246 | case 'H': /* hostname */ { | 251 | case 'H': /* hostname */ { |
247 | char *ptr = optarg; | 252 | char *ptr = optarg; |
248 | while (true) { | 253 | while (true) { |
249 | n_addresses++; | 254 | result.config.n_addresses++; |
250 | if (n_addresses > max_addr) { | 255 | if (result.config.n_addresses > max_addr) { |
251 | max_addr *= 2; | 256 | max_addr *= 2; |
252 | addresses = realloc(addresses, sizeof(char *) * max_addr); | 257 | result.config.addresses = realloc(result.config.addresses, sizeof(char *) * max_addr); |
253 | if (addresses == NULL) { | 258 | if (result.config.addresses == NULL) { |
254 | die(STATE_UNKNOWN, _("Could not realloc() addresses\n")); | 259 | die(STATE_UNKNOWN, _("Could not realloc() addresses\n")); |
255 | } | 260 | } |
256 | } | 261 | } |
257 | addresses[n_addresses - 1] = ptr; | 262 | result.config.addresses[result.config.n_addresses - 1] = ptr; |
258 | if ((ptr = index(ptr, ','))) { | 263 | if ((ptr = index(ptr, ','))) { |
259 | strcpy(ptr, ""); | 264 | strcpy(ptr, ""); |
260 | ptr += sizeof(char); | 265 | ptr += sizeof(char); |
@@ -265,105 +270,110 @@ int process_arguments(int argc, char **argv) { | |||
265 | } break; | 270 | } break; |
266 | case 'p': /* number of packets to send */ | 271 | case 'p': /* number of packets to send */ |
267 | if (is_intnonneg(optarg)) { | 272 | if (is_intnonneg(optarg)) { |
268 | max_packets = atoi(optarg); | 273 | result.config.max_packets = atoi(optarg); |
269 | } else { | 274 | } else { |
270 | usage2(_("<max_packets> (%s) must be a non-negative number\n"), optarg); | 275 | usage2(_("<max_packets> (%s) must be a non-negative number\n"), optarg); |
271 | } | 276 | } |
272 | break; | 277 | break; |
273 | case 'n': /* no HTML */ | 278 | case 'n': /* no HTML */ |
274 | display_html = false; | 279 | result.config.display_html = false; |
275 | break; | 280 | break; |
276 | case 'L': /* show HTML */ | 281 | case 'L': /* show HTML */ |
277 | display_html = true; | 282 | result.config.display_html = true; |
278 | break; | 283 | break; |
279 | case 'c': | 284 | case 'c': |
280 | get_threshold(optarg, &crta, &cpl); | 285 | get_threshold(optarg, &result.config.crta, &result.config.cpl); |
281 | break; | 286 | break; |
282 | case 'w': | 287 | case 'w': |
283 | get_threshold(optarg, &wrta, &wpl); | 288 | get_threshold(optarg, &result.config.wrta, &result.config.wpl); |
284 | break; | 289 | break; |
285 | } | 290 | } |
286 | } | 291 | } |
287 | 292 | ||
288 | int arg_counter = optind; | 293 | int arg_counter = optind; |
289 | if (arg_counter == argc) { | 294 | if (arg_counter == argc) { |
290 | return validate_arguments(); | 295 | return validate_arguments(result); |
291 | } | 296 | } |
292 | 297 | ||
293 | if (addresses[0] == NULL) { | 298 | if (result.config.addresses[0] == NULL) { |
294 | if (!is_host(argv[arg_counter])) { | 299 | if (!is_host(argv[arg_counter])) { |
295 | usage2(_("Invalid hostname/address"), argv[arg_counter]); | 300 | usage2(_("Invalid hostname/address"), argv[arg_counter]); |
296 | } else { | 301 | } else { |
297 | addresses[0] = argv[arg_counter++]; | 302 | result.config.addresses[0] = argv[arg_counter++]; |
298 | n_addresses++; | 303 | result.config.n_addresses++; |
299 | if (arg_counter == argc) { | 304 | if (arg_counter == argc) { |
300 | return validate_arguments(); | 305 | return validate_arguments(result); |
301 | } | 306 | } |
302 | } | 307 | } |
303 | } | 308 | } |
304 | 309 | ||
305 | if (wpl == UNKNOWN_PACKET_LOSS) { | 310 | if (result.config.wpl == UNKNOWN_PACKET_LOSS) { |
306 | if (!is_intpercent(argv[arg_counter])) { | 311 | if (!is_intpercent(argv[arg_counter])) { |
307 | printf(_("<wpl> (%s) must be an integer percentage\n"), argv[arg_counter]); | 312 | printf(_("<wpl> (%s) must be an integer percentage\n"), argv[arg_counter]); |
308 | return ERROR; | 313 | result.errorcode = ERROR; |
314 | return result; | ||
309 | } | 315 | } |
310 | wpl = atoi(argv[arg_counter++]); | 316 | result.config.wpl = atoi(argv[arg_counter++]); |
311 | if (arg_counter == argc) { | 317 | if (arg_counter == argc) { |
312 | return validate_arguments(); | 318 | return validate_arguments(result); |
313 | } | 319 | } |
314 | } | 320 | } |
315 | 321 | ||
316 | if (cpl == UNKNOWN_PACKET_LOSS) { | 322 | if (result.config.cpl == UNKNOWN_PACKET_LOSS) { |
317 | if (!is_intpercent(argv[arg_counter])) { | 323 | if (!is_intpercent(argv[arg_counter])) { |
318 | printf(_("<cpl> (%s) must be an integer percentage\n"), argv[arg_counter]); | 324 | printf(_("<cpl> (%s) must be an integer percentage\n"), argv[arg_counter]); |
319 | return ERROR; | 325 | result.errorcode = ERROR; |
326 | return result; | ||
320 | } | 327 | } |
321 | cpl = atoi(argv[arg_counter++]); | 328 | result.config.cpl = atoi(argv[arg_counter++]); |
322 | if (arg_counter == argc) { | 329 | if (arg_counter == argc) { |
323 | return validate_arguments(); | 330 | return validate_arguments(result); |
324 | } | 331 | } |
325 | } | 332 | } |
326 | 333 | ||
327 | if (wrta < 0.0) { | 334 | if (result.config.wrta < 0.0) { |
328 | if (is_negative(argv[arg_counter])) { | 335 | if (is_negative(argv[arg_counter])) { |
329 | printf(_("<wrta> (%s) must be a non-negative number\n"), argv[arg_counter]); | 336 | printf(_("<wrta> (%s) must be a non-negative number\n"), argv[arg_counter]); |
330 | return ERROR; | 337 | result.errorcode = ERROR; |
338 | return result; | ||
331 | } | 339 | } |
332 | wrta = atof(argv[arg_counter++]); | 340 | result.config.wrta = atof(argv[arg_counter++]); |
333 | if (arg_counter == argc) { | 341 | if (arg_counter == argc) { |
334 | return validate_arguments(); | 342 | return validate_arguments(result); |
335 | } | 343 | } |
336 | } | 344 | } |
337 | 345 | ||
338 | if (crta < 0.0) { | 346 | if (result.config.crta < 0.0) { |
339 | if (is_negative(argv[arg_counter])) { | 347 | if (is_negative(argv[arg_counter])) { |
340 | printf(_("<crta> (%s) must be a non-negative number\n"), argv[arg_counter]); | 348 | printf(_("<crta> (%s) must be a non-negative number\n"), argv[arg_counter]); |
341 | return ERROR; | 349 | result.errorcode = ERROR; |
350 | return result; | ||
342 | } | 351 | } |
343 | crta = atof(argv[arg_counter++]); | 352 | result.config.crta = atof(argv[arg_counter++]); |
344 | if (arg_counter == argc) { | 353 | if (arg_counter == argc) { |
345 | return validate_arguments(); | 354 | return validate_arguments(result); |
346 | } | 355 | } |
347 | } | 356 | } |
348 | 357 | ||
349 | if (max_packets == -1) { | 358 | if (result.config.max_packets == -1) { |
350 | if (is_intnonneg(argv[arg_counter])) { | 359 | if (is_intnonneg(argv[arg_counter])) { |
351 | max_packets = atoi(argv[arg_counter++]); | 360 | result.config.max_packets = atoi(argv[arg_counter++]); |
352 | } else { | 361 | } else { |
353 | printf(_("<max_packets> (%s) must be a non-negative number\n"), argv[arg_counter]); | 362 | printf(_("<max_packets> (%s) must be a non-negative number\n"), argv[arg_counter]); |
354 | return ERROR; | 363 | result.errorcode = ERROR; |
364 | return result; | ||
355 | } | 365 | } |
356 | } | 366 | } |
357 | 367 | ||
358 | return validate_arguments(); | 368 | return validate_arguments(result); |
359 | } | 369 | } |
360 | 370 | ||
361 | int get_threshold(char *arg, float *trta, int *tpl) { | 371 | int get_threshold(char *arg, double *trta, int *tpl) { |
362 | if (is_intnonneg(arg) && sscanf(arg, "%f", trta) == 1) { | 372 | if (is_intnonneg(arg) && sscanf(arg, "%lf", trta) == 1) { |
363 | return OK; | 373 | return OK; |
364 | } | 374 | } |
365 | 375 | ||
366 | if (strpbrk(arg, ",:") && strstr(arg, "%") && sscanf(arg, "%f%*[:,]%d%%", trta, tpl) == 2) { | 376 | if (strpbrk(arg, ",:") && strstr(arg, "%") && sscanf(arg, "%lf%*[:,]%d%%", trta, tpl) == 2) { |
367 | return OK; | 377 | return OK; |
368 | } | 378 | } |
369 | 379 | ||
@@ -375,60 +385,66 @@ int get_threshold(char *arg, float *trta, int *tpl) { | |||
375 | return STATE_UNKNOWN; | 385 | return STATE_UNKNOWN; |
376 | } | 386 | } |
377 | 387 | ||
378 | int validate_arguments() { | 388 | check_ping_config_wrapper validate_arguments(check_ping_config_wrapper config_wrapper) { |
379 | if (wrta < 0.0) { | 389 | if (config_wrapper.config.wrta < 0.0) { |
380 | printf(_("<wrta> was not set\n")); | 390 | printf(_("<wrta> was not set\n")); |
381 | return ERROR; | 391 | config_wrapper.errorcode = ERROR; |
392 | return config_wrapper; | ||
382 | } | 393 | } |
383 | 394 | ||
384 | if (crta < 0.0) { | 395 | if (config_wrapper.config.crta < 0.0) { |
385 | printf(_("<crta> was not set\n")); | 396 | printf(_("<crta> was not set\n")); |
386 | return ERROR; | 397 | config_wrapper.errorcode = ERROR; |
398 | return config_wrapper; | ||
387 | } | 399 | } |
388 | 400 | ||
389 | if (wpl == UNKNOWN_PACKET_LOSS) { | 401 | if (config_wrapper.config.wpl == UNKNOWN_PACKET_LOSS) { |
390 | printf(_("<wpl> was not set\n")); | 402 | printf(_("<wpl> was not set\n")); |
391 | return ERROR; | 403 | config_wrapper.errorcode = ERROR; |
404 | return config_wrapper; | ||
392 | } | 405 | } |
393 | 406 | ||
394 | if (cpl == UNKNOWN_PACKET_LOSS) { | 407 | if (config_wrapper.config.cpl == UNKNOWN_PACKET_LOSS) { |
395 | printf(_("<cpl> was not set\n")); | 408 | printf(_("<cpl> was not set\n")); |
396 | return ERROR; | 409 | config_wrapper.errorcode = ERROR; |
410 | return config_wrapper; | ||
397 | } | 411 | } |
398 | 412 | ||
399 | if (wrta > crta) { | 413 | if (config_wrapper.config.wrta > config_wrapper.config.crta) { |
400 | printf(_("<wrta> (%f) cannot be larger than <crta> (%f)\n"), wrta, crta); | 414 | printf(_("<wrta> (%f) cannot be larger than <crta> (%f)\n"), config_wrapper.config.wrta, config_wrapper.config.crta); |
401 | return ERROR; | 415 | config_wrapper.errorcode = ERROR; |
416 | return config_wrapper; | ||
402 | } | 417 | } |
403 | 418 | ||
404 | if (wpl > cpl) { | 419 | if (config_wrapper.config.wpl > config_wrapper.config.cpl) { |
405 | printf(_("<wpl> (%d) cannot be larger than <cpl> (%d)\n"), wpl, cpl); | 420 | printf(_("<wpl> (%d) cannot be larger than <cpl> (%d)\n"), config_wrapper.config.wpl, config_wrapper.config.cpl); |
406 | return ERROR; | 421 | config_wrapper.errorcode = ERROR; |
422 | return config_wrapper; | ||
407 | } | 423 | } |
408 | 424 | ||
409 | if (max_packets == -1) { | 425 | if (config_wrapper.config.max_packets == -1) { |
410 | max_packets = DEFAULT_MAX_PACKETS; | 426 | config_wrapper.config.max_packets = DEFAULT_MAX_PACKETS; |
411 | } | 427 | } |
412 | 428 | ||
413 | float 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; |
414 | if (max_seconds > timeout_interval) { | 430 | if (max_seconds > timeout_interval) { |
415 | timeout_interval = (unsigned int)max_seconds; | 431 | timeout_interval = (unsigned int)max_seconds; |
416 | } | 432 | } |
417 | 433 | ||
418 | for (int i = 0; i < n_addresses; i++) { | 434 | for (size_t i = 0; i < config_wrapper.config.n_addresses; i++) { |
419 | if (!is_host(addresses[i])) { | 435 | if (!is_host(config_wrapper.config.addresses[i])) { |
420 | usage2(_("Invalid hostname/address"), addresses[i]); | 436 | usage2(_("Invalid hostname/address"), config_wrapper.config.addresses[i]); |
421 | } | 437 | } |
422 | } | 438 | } |
423 | 439 | ||
424 | if (n_addresses == 0) { | 440 | if (config_wrapper.config.n_addresses == 0) { |
425 | usage(_("You must specify a server address or host name")); | 441 | usage(_("You must specify a server address or host name")); |
426 | } | 442 | } |
427 | 443 | ||
428 | return OK; | 444 | return config_wrapper; |
429 | } | 445 | } |
430 | 446 | ||
431 | int run_ping(const char *cmd, const char *addr) { | 447 | ping_result run_ping(const char *cmd, const char *addr, double crta) { |
432 | if ((child_process = spopen(cmd)) == NULL) { | 448 | if ((child_process = spopen(cmd)) == NULL) { |
433 | die(STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd); | 449 | die(STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd); |
434 | } | 450 | } |
@@ -439,48 +455,55 @@ int run_ping(const char *cmd, const char *addr) { | |||
439 | } | 455 | } |
440 | 456 | ||
441 | char buf[MAX_INPUT_BUFFER]; | 457 | char buf[MAX_INPUT_BUFFER]; |
442 | int result = STATE_UNKNOWN; | 458 | ping_result result = { |
459 | .state = STATE_UNKNOWN, | ||
460 | .packet_loss = UNKNOWN_PACKET_LOSS, | ||
461 | .round_trip_average = UNKNOWN_TRIP_TIME, | ||
462 | }; | ||
463 | |||
443 | while (fgets(buf, MAX_INPUT_BUFFER - 1, child_process)) { | 464 | while (fgets(buf, MAX_INPUT_BUFFER - 1, child_process)) { |
444 | if (verbose >= 3) { | 465 | if (verbose >= 3) { |
445 | printf("Output: %s", buf); | 466 | printf("Output: %s", buf); |
446 | } | 467 | } |
447 | 468 | ||
448 | result = max_state(result, error_scan(buf, addr)); | 469 | result.state = max_state(result.state, error_scan(buf, addr)); |
449 | 470 | ||
450 | /* get the percent loss statistics */ | 471 | /* get the percent loss statistics */ |
451 | int match = 0; | 472 | int match = 0; |
452 | if ((sscanf(buf, "%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss%n", &packet_loss, &match) && | 473 | if ((sscanf(buf, "%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss%n", &result.packet_loss, &match) && |
474 | match) || | ||
475 | (sscanf(buf, "%*d packets transmitted, %*d packets received, +%*d duplicates, %d%% packet loss%n", &result.packet_loss, | ||
476 | &match) && | ||
453 | match) || | 477 | match) || |
454 | (sscanf(buf, "%*d packets transmitted, %*d packets received, +%*d duplicates, %d%% packet loss%n", &packet_loss, &match) && | 478 | (sscanf(buf, "%*d packets transmitted, %*d received, +%*d duplicates, %d%% packet loss%n", &result.packet_loss, &match) && |
455 | match) || | 479 | match) || |
456 | (sscanf(buf, "%*d packets transmitted, %*d received, +%*d duplicates, %d%% packet loss%n", &packet_loss, &match) && match) || | 480 | (sscanf(buf, "%*d packets transmitted, %*d packets received, %d%% packet loss%n", &result.packet_loss, &match) && match) || |
457 | (sscanf(buf, "%*d packets transmitted, %*d packets received, %d%% packet loss%n", &packet_loss, &match) && match) || | 481 | (sscanf(buf, "%*d packets transmitted, %*d packets received, %d%% loss, time%n", &result.packet_loss, &match) && match) || |
458 | (sscanf(buf, "%*d packets transmitted, %*d packets received, %d%% loss, time%n", &packet_loss, &match) && match) || | 482 | (sscanf(buf, "%*d packets transmitted, %*d received, %d%% loss, time%n", &result.packet_loss, &match) && match) || |
459 | (sscanf(buf, "%*d packets transmitted, %*d received, %d%% loss, time%n", &packet_loss, &match) && match) || | 483 | (sscanf(buf, "%*d packets transmitted, %*d received, %d%% packet loss, time%n", &result.packet_loss, &match) && match) || |
460 | (sscanf(buf, "%*d packets transmitted, %*d received, %d%% packet loss, time%n", &packet_loss, &match) && match) || | 484 | (sscanf(buf, "%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss%n", &result.packet_loss, &match) && match) || |
461 | (sscanf(buf, "%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss%n", &packet_loss, &match) && match) || | 485 | (sscanf(buf, "%*d packets transmitted %*d received, +%*d errors, %d%% packet loss%n", &result.packet_loss, &match) && match) || |
462 | (sscanf(buf, "%*d packets transmitted %*d received, +%*d errors, %d%% packet loss%n", &packet_loss, &match) && match) || | 486 | (sscanf(buf, "%*[^(](%d%% %*[^)])%n", &result.packet_loss, &match) && match)) { |
463 | (sscanf(buf, "%*[^(](%d%% %*[^)])%n", &packet_loss, &match) && match)) { | ||
464 | continue; | 487 | continue; |
465 | } | 488 | } |
466 | 489 | ||
467 | /* get the round trip average */ | 490 | /* get the round trip average */ |
468 | if ((sscanf(buf, "round-trip min/avg/max = %*f/%f/%*f%n", &round_trip_average, &match) && match) || | 491 | if ((sscanf(buf, "round-trip min/avg/max = %*f/%lf/%*f%n", &result.round_trip_average, &match) && match) || |
469 | (sscanf(buf, "round-trip min/avg/max/mdev = %*f/%f/%*f/%*f%n", &round_trip_average, &match) && match) || | 492 | (sscanf(buf, "round-trip min/avg/max/mdev = %*f/%lf/%*f/%*f%n", &result.round_trip_average, &match) && match) || |
470 | (sscanf(buf, "round-trip min/avg/max/sdev = %*f/%f/%*f/%*f%n", &round_trip_average, &match) && match) || | 493 | (sscanf(buf, "round-trip min/avg/max/sdev = %*f/%lf/%*f/%*f%n", &result.round_trip_average, &match) && match) || |
471 | (sscanf(buf, "round-trip min/avg/max/stddev = %*f/%f/%*f/%*f%n", &round_trip_average, &match) && match) || | 494 | (sscanf(buf, "round-trip min/avg/max/stddev = %*f/%lf/%*f/%*f%n", &result.round_trip_average, &match) && match) || |
472 | (sscanf(buf, "round-trip min/avg/max/std-dev = %*f/%f/%*f/%*f%n", &round_trip_average, &match) && match) || | 495 | (sscanf(buf, "round-trip min/avg/max/std-dev = %*f/%lf/%*f/%*f%n", &result.round_trip_average, &match) && match) || |
473 | (sscanf(buf, "round-trip (ms) min/avg/max = %*f/%f/%*f%n", &round_trip_average, &match) && match) || | 496 | (sscanf(buf, "round-trip (ms) min/avg/max = %*f/%lf/%*f%n", &result.round_trip_average, &match) && match) || |
474 | (sscanf(buf, "round-trip (ms) min/avg/max/stddev = %*f/%f/%*f/%*f%n", &round_trip_average, &match) && match) || | 497 | (sscanf(buf, "round-trip (ms) min/avg/max/stddev = %*f/%lf/%*f/%*f%n", &result.round_trip_average, &match) && match) || |
475 | (sscanf(buf, "rtt min/avg/max/mdev = %*f/%f/%*f/%*f ms%n", &round_trip_average, &match) && match) || | 498 | (sscanf(buf, "rtt min/avg/max/mdev = %*f/%lf/%*f/%*f ms%n", &result.round_trip_average, &match) && match) || |
476 | (sscanf(buf, "%*[^=] = %*fms, %*[^=] = %*fms, %*[^=] = %fms%n", &round_trip_average, &match) && match)) { | 499 | (sscanf(buf, "%*[^=] = %*fms, %*[^=] = %*fms, %*[^=] = %lfms%n", &result.round_trip_average, &match) && match)) { |
477 | continue; | 500 | continue; |
478 | } | 501 | } |
479 | } | 502 | } |
480 | 503 | ||
481 | /* this is needed because there is no rta if all packets are lost */ | 504 | /* this is needed because there is no rta if all packets are lost */ |
482 | if (packet_loss == 100) { | 505 | if (result.packet_loss == 100) { |
483 | round_trip_average = crta; | 506 | result.round_trip_average = crta; |
484 | } | 507 | } |
485 | 508 | ||
486 | /* check stderr, setting at least WARNING if there is output here */ | 509 | /* check stderr, setting at least WARNING if there is output here */ |
@@ -492,8 +515,8 @@ int run_ping(const char *cmd, const char *addr) { | |||
492 | if (verbose >= 3) { | 515 | if (verbose >= 3) { |
493 | printf("Got stderr: %s", buf); | 516 | printf("Got stderr: %s", buf); |
494 | } | 517 | } |
495 | if ((result = error_scan(buf, addr)) == STATE_OK) { | 518 | if ((result.state = error_scan(buf, addr)) == STATE_OK) { |
496 | result = STATE_WARNING; | 519 | result.state = STATE_WARNING; |
497 | if (warn_text == NULL) { | 520 | if (warn_text == NULL) { |
498 | warn_text = strdup(_("System call sent warnings to stderr ")); | 521 | warn_text = strdup(_("System call sent warnings to stderr ")); |
499 | } else { | 522 | } else { |
@@ -514,7 +537,7 @@ int run_ping(const char *cmd, const char *addr) { | |||
514 | return result; | 537 | return result; |
515 | } | 538 | } |
516 | 539 | ||
517 | int error_scan(char buf[MAX_INPUT_BUFFER], const char *addr) { | 540 | mp_state_enum error_scan(char buf[MAX_INPUT_BUFFER], const char *addr) { |
518 | if (strstr(buf, "Network is unreachable") || strstr(buf, "Destination Net Unreachable") || strstr(buf, "No route")) { | 541 | if (strstr(buf, "Network is unreachable") || strstr(buf, "Destination Net Unreachable") || strstr(buf, "No route")) { |
519 | die(STATE_CRITICAL, _("CRITICAL - Network Unreachable (%s)\n"), addr); | 542 | die(STATE_CRITICAL, _("CRITICAL - Network Unreachable (%s)\n"), addr); |
520 | } else if (strstr(buf, "Destination Host Unreachable") || strstr(buf, "Address unreachable")) { | 543 | } else if (strstr(buf, "Destination Host Unreachable") || strstr(buf, "Address unreachable")) { |
@@ -543,10 +566,10 @@ int error_scan(char buf[MAX_INPUT_BUFFER], const char *addr) { | |||
543 | } else if (!strstr(warn_text, _(WARN_DUPLICATES)) && xasprintf(&warn_text, "%s %s", warn_text, _(WARN_DUPLICATES)) == -1) { | 566 | } else if (!strstr(warn_text, _(WARN_DUPLICATES)) && xasprintf(&warn_text, "%s %s", warn_text, _(WARN_DUPLICATES)) == -1) { |
544 | die(STATE_UNKNOWN, _("Unable to realloc warn_text\n")); | 567 | die(STATE_UNKNOWN, _("Unable to realloc warn_text\n")); |
545 | } | 568 | } |
546 | return (STATE_WARNING); | 569 | return STATE_WARNING; |
547 | } | 570 | } |
548 | 571 | ||
549 | return (STATE_OK); | 572 | return STATE_OK; |
550 | } | 573 | } |
551 | 574 | ||
552 | void print_help(void) { | 575 | void print_help(void) { |