diff options
| -rw-r--r-- | plugins/Makefile.am | 1 | ||||
| -rw-r--r-- | plugins/check_ping.c | 319 | ||||
| -rw-r--r-- | plugins/check_ping.d/config.h | 46 |
3 files changed, 218 insertions, 148 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 9ea6e85e..10a12168 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am | |||
| @@ -63,6 +63,7 @@ EXTRA_DIST = t \ | |||
| 63 | check_mrtg.d \ | 63 | check_mrtg.d \ |
| 64 | check_apt.d \ | 64 | check_apt.d \ |
| 65 | check_pgsql.d \ | 65 | check_pgsql.d \ |
| 66 | check_ping.d \ | ||
| 66 | check_by_ssh.d \ | 67 | check_by_ssh.d \ |
| 67 | check_smtp.d \ | 68 | check_smtp.d \ |
| 68 | check_mysql.d \ | 69 | check_mysql.d \ |
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) { |
diff --git a/plugins/check_ping.d/config.h b/plugins/check_ping.d/config.h new file mode 100644 index 00000000..eb2735a7 --- /dev/null +++ b/plugins/check_ping.d/config.h | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include "../../config.h" | ||
| 4 | #include <stddef.h> | ||
| 5 | #include <stdlib.h> | ||
| 6 | |||
| 7 | enum { | ||
| 8 | UNKNOWN_PACKET_LOSS = 200, /* 200% */ | ||
| 9 | DEFAULT_MAX_PACKETS = 5 /* default no. of ICMP ECHO packets */ | ||
| 10 | }; | ||
| 11 | |||
| 12 | #define UNKNOWN_TRIP_TIME -1.0 /* -1 seconds */ | ||
| 13 | |||
| 14 | #define MAX_ADDR_START 1 | ||
| 15 | |||
| 16 | typedef struct { | ||
| 17 | bool display_html; | ||
| 18 | int max_packets; | ||
| 19 | |||
| 20 | char **addresses; | ||
| 21 | size_t n_addresses; | ||
| 22 | |||
| 23 | int wpl; | ||
| 24 | int cpl; | ||
| 25 | double wrta; | ||
| 26 | double crta; | ||
| 27 | } check_ping_config; | ||
| 28 | |||
| 29 | check_ping_config check_ping_config_init() { | ||
| 30 | check_ping_config tmp = { | ||
| 31 | .display_html = false, | ||
| 32 | .max_packets = -1, | ||
| 33 | |||
| 34 | .addresses = NULL, | ||
| 35 | .n_addresses = 0, | ||
| 36 | |||
| 37 | .wpl = UNKNOWN_PACKET_LOSS, | ||
| 38 | .cpl = UNKNOWN_PACKET_LOSS, | ||
| 39 | .wrta = UNKNOWN_TRIP_TIME, | ||
| 40 | .crta = UNKNOWN_TRIP_TIME, | ||
| 41 | }; | ||
| 42 | |||
| 43 | tmp.addresses = calloc(MAX_ADDR_START, sizeof(char *)); | ||
| 44 | tmp.addresses[0] = NULL; | ||
| 45 | return tmp; | ||
| 46 | } | ||
