summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins-root/check_icmp.c193
1 files changed, 108 insertions, 85 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index 58f5ae70..0614d6aa 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -184,17 +184,24 @@ static parse_threshold2_helper_wrapper parse_threshold2_helper(char *threshold_s
184 threshold_mode mode); 184 threshold_mode mode);
185 185
186/* main test function */ 186/* main test function */
187static void run_checks(check_icmp_mode_switches modes, int min_hosts_alive, 187static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval,
188 unsigned short icmp_pkt_size, unsigned int *pkt_interval, 188 unsigned int *target_interval, uint16_t sender_id,
189 unsigned int *target_interval, check_icmp_threshold warn,
190 check_icmp_threshold crit, uint16_t sender_id,
191 check_icmp_execution_mode mode, unsigned int max_completion_time, 189 check_icmp_execution_mode mode, unsigned int max_completion_time,
192 struct timeval prog_start, ping_target **table, unsigned short packets, 190 struct timeval prog_start, ping_target **table, unsigned short packets,
193 int icmp_sock, unsigned short number_of_targets, 191 int icmp_sock, unsigned short number_of_targets,
194 check_icmp_state *program_state, ping_target *target_list); 192 check_icmp_state *program_state);
195mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, 193mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
196 check_icmp_threshold warn, check_icmp_threshold crit); 194 check_icmp_threshold warn, check_icmp_threshold crit);
197 195
196typedef struct {
197 int targets_ok;
198 int targets_warn;
199 mp_subcheck sc_host;
200} evaluate_host_wrapper;
201evaluate_host_wrapper evaluate_host(check_icmp_target_container host,
202 check_icmp_mode_switches modes, check_icmp_threshold warn,
203 check_icmp_threshold crit);
204
198/* Target aquisition */ 205/* Target aquisition */
199typedef struct { 206typedef struct {
200 int error_code; 207 int error_code;
@@ -213,7 +220,7 @@ typedef struct {
213 int error_code; 220 int error_code;
214 ping_target *target; 221 ping_target *target;
215} add_target_ip_wrapper; 222} add_target_ip_wrapper;
216static add_target_ip_wrapper add_target_ip(char *arg, struct sockaddr_storage *address); 223static add_target_ip_wrapper add_target_ip(struct sockaddr_storage address);
217 224
218static void parse_address(struct sockaddr_storage *addr, char *address, socklen_t size); 225static void parse_address(struct sockaddr_storage *addr, char *address, socklen_t size);
219 226
@@ -223,7 +230,8 @@ static unsigned short icmp_checksum(uint16_t *packet, size_t packet_size);
223static void finish(int sign, check_icmp_mode_switches modes, int min_hosts_alive, 230static void finish(int sign, check_icmp_mode_switches modes, int min_hosts_alive,
224 check_icmp_threshold warn, check_icmp_threshold crit, int icmp_sock, 231 check_icmp_threshold warn, check_icmp_threshold crit, int icmp_sock,
225 unsigned short number_of_targets, check_icmp_state *program_state, 232 unsigned short number_of_targets, check_icmp_state *program_state,
226 ping_target *target_list) __attribute__((noreturn)); 233 check_icmp_target_container host_list[], unsigned short number_of_hosts,
234 mp_check overall[static 1]);
227 235
228/* Error exit */ 236/* Error exit */
229static void crash(const char *fmt, ...); 237static void crash(const char *fmt, ...);
@@ -247,8 +255,6 @@ typedef struct {
247 int errorcode; 255 int errorcode;
248 check_icmp_config config; 256 check_icmp_config config;
249} check_icmp_config_wrapper; 257} check_icmp_config_wrapper;
250check_icmp_config_wrapper process_arguments(int argc, char **argv);
251
252check_icmp_config_wrapper process_arguments(int argc, char **argv) { 258check_icmp_config_wrapper process_arguments(int argc, char **argv) {
253 /* get calling name the old-fashioned way for portability instead 259 /* get calling name the old-fashioned way for portability instead
254 * of relying on the glibc-ism __progname */ 260 * of relying on the glibc-ism __progname */
@@ -313,7 +319,11 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) {
313 break; 319 break;
314 case 'H': { 320 case 'H': {
315 result.config.number_of_hosts++; 321 result.config.number_of_hosts++;
322 break;
316 } 323 }
324 case 'v':
325 debug++;
326 break;
317 } 327 }
318 } 328 }
319 } 329 }
@@ -345,9 +355,6 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) {
345 long int arg; 355 long int arg;
346 while ((arg = getopt(argc, argv, opts_str)) != EOF) { 356 while ((arg = getopt(argc, argv, opts_str)) != EOF) {
347 switch (arg) { 357 switch (arg) {
348 case 'v':
349 debug++;
350 break;
351 case 'b': { 358 case 'b': {
352 long size = strtol(optarg, NULL, 0); 359 long size = strtol(optarg, NULL, 0);
353 if ((unsigned long)size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && 360 if ((unsigned long)size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) &&
@@ -859,6 +866,7 @@ int main(int argc, char **argv) {
859 crash("minimum alive hosts is negative (%i)", config.min_hosts_alive); 866 crash("minimum alive hosts is negative (%i)", config.min_hosts_alive);
860 } 867 }
861 868
869 // Build an index table of all targets
862 ping_target *host = config.targets; 870 ping_target *host = config.targets;
863 ping_target **table = malloc(sizeof(ping_target *) * config.number_of_targets); 871 ping_target **table = malloc(sizeof(ping_target *) * config.number_of_targets);
864 if (!table) { 872 if (!table) {
@@ -878,27 +886,26 @@ int main(int argc, char **argv) {
878 886
879 check_icmp_state program_state = check_icmp_state_init(); 887 check_icmp_state program_state = check_icmp_state_init();
880 888
881 run_checks(config.modes, config.min_hosts_alive, config.icmp_data_size, &pkt_interval, 889 run_checks(config.icmp_data_size, &pkt_interval, &target_interval, config.sender_id,
882 &target_interval, config.warn, config.crit, config.sender_id, config.mode, 890 config.mode, max_completion_time, prog_start, table, config.number_of_packets,
883 max_completion_time, prog_start, table, config.number_of_packets, icmp_sock, 891 icmp_sock, config.number_of_targets, &program_state);
884 config.number_of_targets, &program_state, config.targets);
885 892
886 errno = 0; 893 errno = 0;
894
895 mp_check overall = mp_check_init();
887 finish(0, config.modes, config.min_hosts_alive, config.warn, config.crit, icmp_sock, 896 finish(0, config.modes, config.min_hosts_alive, config.warn, config.crit, icmp_sock,
888 config.number_of_targets, &program_state, config.targets); 897 config.number_of_targets, &program_state, config.hosts, config.number_of_hosts,
898 &overall);
889 899
890 return (0); 900 mp_exit(overall);
891} 901}
892 902
893static void run_checks(check_icmp_mode_switches modes, int min_hosts_alive, 903static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval,
894 unsigned short icmp_pkt_size, unsigned int *pkt_interval, 904 unsigned int *target_interval, const uint16_t sender_id,
895 unsigned int *target_interval, check_icmp_threshold warn,
896 check_icmp_threshold crit, const uint16_t sender_id,
897 const check_icmp_execution_mode mode, const unsigned int max_completion_time, 905 const check_icmp_execution_mode mode, const unsigned int max_completion_time,
898 const struct timeval prog_start, ping_target **table, 906 const struct timeval prog_start, ping_target **table,
899 const unsigned short packets, const int icmp_sock, 907 const unsigned short packets, const int icmp_sock,
900 const unsigned short number_of_targets, check_icmp_state *program_state, 908 const unsigned short number_of_targets, check_icmp_state *program_state) {
901 ping_target *target_list) {
902 /* this loop might actually violate the pkt_interval or target_interval 909 /* this loop might actually violate the pkt_interval or target_interval
903 * settings, but only if there aren't any packets on the wire which 910 * settings, but only if there aren't any packets on the wire which
904 * indicates that the target can handle an increased packet rate */ 911 * indicates that the target can handle an increased packet rate */
@@ -906,8 +913,7 @@ static void run_checks(check_icmp_mode_switches modes, int min_hosts_alive,
906 for (unsigned int target_index = 0; target_index < number_of_targets; target_index++) { 913 for (unsigned int target_index = 0; target_index < number_of_targets; target_index++) {
907 /* don't send useless packets */ 914 /* don't send useless packets */
908 if (!targets_alive(number_of_targets, program_state->targets_down)) { 915 if (!targets_alive(number_of_targets, program_state->targets_down)) {
909 finish(0, modes, min_hosts_alive, warn, crit, icmp_sock, number_of_targets, 916 return;
910 program_state, target_list);
911 } 917 }
912 if (table[target_index]->flags & FLAG_LOST_CAUSE) { 918 if (table[target_index]->flags & FLAG_LOST_CAUSE) {
913 if (debug) { 919 if (debug) {
@@ -952,8 +958,7 @@ static void run_checks(check_icmp_mode_switches modes, int min_hosts_alive,
952 if (debug) { 958 if (debug) {
953 printf("Time passed. Finishing up\n"); 959 printf("Time passed. Finishing up\n");
954 } 960 }
955 finish(0, modes, min_hosts_alive, warn, crit, icmp_sock, number_of_targets, 961 return;
956 program_state, target_list);
957 } 962 }
958 963
959 /* catch the packets that might come in within the timeframe, but 964 /* catch the packets that might come in within the timeframe, but
@@ -1383,7 +1388,8 @@ static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len,
1383static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, 1388static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive,
1384 check_icmp_threshold warn, check_icmp_threshold crit, const int icmp_sock, 1389 check_icmp_threshold warn, check_icmp_threshold crit, const int icmp_sock,
1385 const unsigned short number_of_targets, check_icmp_state *program_state, 1390 const unsigned short number_of_targets, check_icmp_state *program_state,
1386 ping_target *target_list) { 1391 check_icmp_target_container host_list[], unsigned short number_of_hosts,
1392 mp_check overall[static 1]) {
1387 // Deactivate alarm 1393 // Deactivate alarm
1388 alarm(0); 1394 alarm(0);
1389 1395
@@ -1402,29 +1408,21 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive,
1402 targets_alive(number_of_targets, program_state->targets_down)); 1408 targets_alive(number_of_targets, program_state->targets_down));
1403 } 1409 }
1404 1410
1405 mp_check overall = mp_check_init();
1406
1407 // loop over targets to evaluate each one 1411 // loop over targets to evaluate each one
1408 ping_target *host = target_list; 1412 int targets_ok = 0;
1409 int hosts_ok = 0; 1413 int targets_warn = 0;
1410 int hosts_warn = 0; 1414 for (unsigned short i = 0; i < number_of_hosts; i++) {
1411 while (host) { 1415 evaluate_host_wrapper host_check = evaluate_host(host_list[i], modes, warn, crit);
1412 if (host->flags & FLAG_LOST_CAUSE) {
1413 program_state->targets_down++;
1414 }
1415 // TODO call evaluate here
1416 mp_subcheck sc_target = evaluate_target(*host, modes, warn, crit);
1417 1416
1418 mp_add_subcheck_to_check(&overall, sc_target); 1417 targets_ok += host_check.targets_ok;
1418 targets_warn += host_check.targets_warn;
1419 1419
1420 mp_state_enum target_state = mp_compute_subcheck_state(sc_target); 1420 mp_add_subcheck_to_check(overall, host_check.sc_host);
1421 if (target_state == STATE_OK) { 1421 }
1422 hosts_ok++;
1423 } else if (target_state == STATE_WARNING) {
1424 hosts_warn++;
1425 }
1426 1422
1427 host = host->next; 1423 if (number_of_hosts == 1) {
1424 // Exit early here, since the other checks only make sense for multiple hosts
1425 return;
1428 } 1426 }
1429 1427
1430 /* this is inevitable */ 1428 /* this is inevitable */
@@ -1432,7 +1430,7 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive,
1432 mp_subcheck sc_no_target_alive = mp_subcheck_init(); 1430 mp_subcheck sc_no_target_alive = mp_subcheck_init();
1433 sc_no_target_alive = mp_set_subcheck_state(sc_no_target_alive, STATE_CRITICAL); 1431 sc_no_target_alive = mp_set_subcheck_state(sc_no_target_alive, STATE_CRITICAL);
1434 sc_no_target_alive.output = strdup("No target is alive!"); 1432 sc_no_target_alive.output = strdup("No target is alive!");
1435 mp_add_subcheck_to_check(&overall, sc_no_target_alive); 1433 mp_add_subcheck_to_check(overall, sc_no_target_alive);
1436 } 1434 }
1437 1435
1438 if (min_hosts_alive > -1) { 1436 if (min_hosts_alive > -1) {
@@ -1440,10 +1438,10 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive,
1440 sc_min_targets_alive = mp_set_subcheck_default_state(sc_min_targets_alive, STATE_OK); 1438 sc_min_targets_alive = mp_set_subcheck_default_state(sc_min_targets_alive, STATE_OK);
1441 1439
1442 // TODO problably broken now 1440 // TODO problably broken now
1443 if (hosts_ok >= min_hosts_alive) { 1441 if (targets_ok >= min_hosts_alive) {
1444 // TODO this should overwrite the main state 1442 // TODO this should overwrite the main state
1445 sc_min_targets_alive = mp_set_subcheck_state(sc_min_targets_alive, STATE_OK); 1443 sc_min_targets_alive = mp_set_subcheck_state(sc_min_targets_alive, STATE_OK);
1446 } else if ((hosts_ok + hosts_warn) >= min_hosts_alive) { 1444 } else if ((targets_ok + targets_warn) >= min_hosts_alive) {
1447 sc_min_targets_alive = mp_set_subcheck_state(sc_min_targets_alive, STATE_WARNING); 1445 sc_min_targets_alive = mp_set_subcheck_state(sc_min_targets_alive, STATE_WARNING);
1448 } 1446 }
1449 } 1447 }
@@ -1453,10 +1451,8 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive,
1453 printf( 1451 printf(
1454 "targets: %u, targets_alive: %u, hosts_ok: %u, hosts_warn: %u, min_hosts_alive: %i\n", 1452 "targets: %u, targets_alive: %u, hosts_ok: %u, hosts_warn: %u, min_hosts_alive: %i\n",
1455 number_of_targets, targets_alive(number_of_targets, program_state->targets_down), 1453 number_of_targets, targets_alive(number_of_targets, program_state->targets_down),
1456 hosts_ok, hosts_warn, min_hosts_alive); 1454 targets_ok, targets_warn, min_hosts_alive);
1457 } 1455 }
1458
1459 mp_exit(overall);
1460} 1456}
1461 1457
1462static time_t get_timevaldiff(const struct timeval earlier, const struct timeval later) { 1458static time_t get_timevaldiff(const struct timeval earlier, const struct timeval later) {
@@ -1479,13 +1475,18 @@ static time_t get_timevaldiff_to_now(struct timeval earlier) {
1479 return get_timevaldiff(earlier, now); 1475 return get_timevaldiff(earlier, now);
1480} 1476}
1481 1477
1482static add_target_ip_wrapper add_target_ip(char *arg, struct sockaddr_storage *address) { 1478static add_target_ip_wrapper add_target_ip(struct sockaddr_storage address) {
1479 if (debug) {
1480 char straddr[INET6_ADDRSTRLEN];
1481 parse_address((struct sockaddr_storage *)&address, straddr, sizeof(straddr));
1482 printf("add_target_ip called with: %s\n", straddr);
1483 }
1483 struct sockaddr_in *sin; 1484 struct sockaddr_in *sin;
1484 struct sockaddr_in6 *sin6; 1485 struct sockaddr_in6 *sin6;
1485 if (address_family == AF_INET) { 1486 if (address_family == AF_INET) {
1486 sin = (struct sockaddr_in *)address; 1487 sin = (struct sockaddr_in *)&address;
1487 } else { 1488 } else {
1488 sin6 = (struct sockaddr_in6 *)address; 1489 sin6 = (struct sockaddr_in6 *)&address;
1489 } 1490 }
1490 1491
1491 add_target_ip_wrapper result = { 1492 add_target_ip_wrapper result = {
@@ -1502,38 +1503,20 @@ static add_target_ip_wrapper add_target_ip(char *arg, struct sockaddr_storage *a
1502 return result; 1503 return result;
1503 } 1504 }
1504 1505
1505 // TODO: allow duplicate targets for now, might be on purpose 1506 // get string representation of address
1506 /* no point in adding two identical IP's, so don't. ;) */ 1507 char straddr[INET6_ADDRSTRLEN];
1507 // struct sockaddr_in *host_sin; 1508 parse_address((&address), straddr, sizeof(straddr));
1508 // struct sockaddr_in6 *host_sin6;
1509 // ping_target *host = host_list;
1510 // while (host) {
1511 // host_sin = (struct sockaddr_in *)&host->saddr_in;
1512 // host_sin6 = (struct sockaddr_in6 *)&host->saddr_in;
1513
1514 // if ((address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr) ||
1515 // (address_family == AF_INET6 &&
1516 // host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) {
1517 // if (debug) {
1518 // printf("Identical IP already exists. Not adding %s\n", arg);
1519 // }
1520 // return -1;
1521 // }
1522 // host = host->next;
1523 // }
1524 1509
1525 /* add the fresh ip */ 1510 /* add the fresh ip */
1526 ping_target *target = (ping_target *)calloc(1, sizeof(ping_target)); 1511 ping_target *target = (ping_target *)calloc(1, sizeof(ping_target));
1527 if (!target) { 1512 if (!target) {
1528 char straddr[INET6_ADDRSTRLEN]; 1513 crash("add_target_ip(%s): malloc(%lu) failed", straddr, sizeof(ping_target));
1529 parse_address((struct sockaddr_storage *)&address, straddr, sizeof(straddr));
1530 crash("add_target_ip(%s, %s): malloc(%lu) failed", arg, straddr, sizeof(ping_target));
1531 } 1514 }
1532 1515
1533 *target = ping_target_init(); 1516 *target = ping_target_init();
1534 1517
1535 /* set the values. use calling name for output */ 1518 /* set the values. use calling name for output */
1536 target->name = strdup(arg); 1519 target->name = strdup(straddr);
1537 1520
1538 /* fill out the sockaddr_storage struct */ 1521 /* fill out the sockaddr_storage struct */
1539 struct sockaddr_in *host_sin; 1522 struct sockaddr_in *host_sin;
@@ -1556,9 +1539,13 @@ static add_target_ip_wrapper add_target_ip(char *arg, struct sockaddr_storage *a
1556 1539
1557/* wrapper for add_target_ip */ 1540/* wrapper for add_target_ip */
1558static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode mode) { 1541static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode mode) {
1559 struct sockaddr_storage address_storage; 1542 if (debug > 0) {
1560 struct sockaddr_in *sin; 1543 printf("add_target called with argument %s\n", arg);
1561 struct sockaddr_in6 *sin6; 1544 }
1545
1546 struct sockaddr_storage address_storage = {};
1547 struct sockaddr_in *sin = NULL;
1548 struct sockaddr_in6 *sin6 = NULL;
1562 int error_code = -1; 1549 int error_code = -1;
1563 1550
1564 switch (address_family) { 1551 switch (address_family) {
@@ -1598,7 +1585,7 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode
1598 /* don't resolve if we don't have to */ 1585 /* don't resolve if we don't have to */
1599 if (error_code == 1) { 1586 if (error_code == 1) {
1600 /* don't add all ip's if we were given a specific one */ 1587 /* don't add all ip's if we were given a specific one */
1601 add_target_ip_wrapper targeted = add_target_ip(arg, &address_storage); 1588 add_target_ip_wrapper targeted = add_target_ip(address_storage);
1602 1589
1603 if (targeted.error_code != OK) { 1590 if (targeted.error_code != OK) {
1604 result.error_code = ERROR; 1591 result.error_code = ERROR;
@@ -1634,7 +1621,8 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode
1634 for (struct addrinfo *address = res; address != NULL; address = address->ai_next) { 1621 for (struct addrinfo *address = res; address != NULL; address = address->ai_next) {
1635 struct sockaddr_storage temporary_ip_address; 1622 struct sockaddr_storage temporary_ip_address;
1636 memcpy(&temporary_ip_address, address->ai_addr, address->ai_addrlen); 1623 memcpy(&temporary_ip_address, address->ai_addr, address->ai_addrlen);
1637 add_target_ip_wrapper tmp = add_target_ip(arg, &temporary_ip_address); 1624
1625 add_target_ip_wrapper tmp = add_target_ip(temporary_ip_address);
1638 1626
1639 if (tmp.error_code != OK) { 1627 if (tmp.error_code != OK) {
1640 // No proper error handling 1628 // No proper error handling
@@ -2039,6 +2027,10 @@ void print_usage(void) {
2039} 2027}
2040 2028
2041static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode) { 2029static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode) {
2030 if (debug) {
2031 printf("add_host called with argument %s\n", arg);
2032 }
2033
2042 add_host_wrapper result = { 2034 add_host_wrapper result = {
2043 .error_code = OK, 2035 .error_code = OK,
2044 .host = check_icmp_target_container_init(), 2036 .host = check_icmp_target_container_init(),
@@ -2324,3 +2316,34 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
2324 2316
2325 return result; 2317 return result;
2326} 2318}
2319
2320evaluate_host_wrapper evaluate_host(check_icmp_target_container host,
2321 check_icmp_mode_switches modes, check_icmp_threshold warn,
2322 check_icmp_threshold crit) {
2323 evaluate_host_wrapper result = {
2324 .targets_warn = 0,
2325 .targets_ok = 0,
2326 .sc_host = mp_subcheck_init(),
2327 };
2328 result.sc_host = mp_set_subcheck_default_state(result.sc_host, STATE_OK);
2329
2330 result.sc_host.output = strdup(host.name);
2331
2332 ping_target *target = host.target_list;
2333 for (unsigned int i = 0; i < host.number_of_targets; i++) {
2334 mp_subcheck sc_target = evaluate_target(*target, modes, warn, crit);
2335
2336 mp_state_enum target_state = mp_compute_subcheck_state(sc_target);
2337
2338 if (target_state == STATE_WARNING) {
2339 result.targets_warn++;
2340 } else if (target_state == STATE_OK) {
2341 result.targets_ok++;
2342 }
2343 mp_add_subcheck_to_subcheck(&result.sc_host, sc_target);
2344
2345 target = target->next;
2346 }
2347
2348 return result;
2349}