diff options
Diffstat (limited to 'plugins-root/check_icmp.c')
| -rw-r--r-- | plugins-root/check_icmp.c | 94 |
1 files changed, 62 insertions, 32 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 35cae3ed..1390a03e 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c | |||
| @@ -55,7 +55,7 @@ const char *email = "devel@monitoring-plugins.org"; | |||
| 55 | 55 | ||
| 56 | #include <sys/time.h> | 56 | #include <sys/time.h> |
| 57 | #if defined(SIOCGIFADDR) | 57 | #if defined(SIOCGIFADDR) |
| 58 | #include <sys/ioctl.h> | 58 | # include <sys/ioctl.h> |
| 59 | #endif /* SIOCGIFADDR */ | 59 | #endif /* SIOCGIFADDR */ |
| 60 | #include <errno.h> | 60 | #include <errno.h> |
| 61 | #include <signal.h> | 61 | #include <signal.h> |
| @@ -277,15 +277,6 @@ typedef struct { | |||
| 277 | check_icmp_config config; | 277 | check_icmp_config config; |
| 278 | } check_icmp_config_wrapper; | 278 | } check_icmp_config_wrapper; |
| 279 | check_icmp_config_wrapper process_arguments(int argc, char **argv) { | 279 | check_icmp_config_wrapper process_arguments(int argc, char **argv) { |
| 280 | /* get calling name the old-fashioned way for portability instead | ||
| 281 | * of relying on the glibc-ism __progname */ | ||
| 282 | char *ptr = strrchr(argv[0], '/'); | ||
| 283 | if (ptr) { | ||
| 284 | progname = &ptr[1]; | ||
| 285 | } else { | ||
| 286 | progname = argv[0]; | ||
| 287 | } | ||
| 288 | |||
| 289 | check_icmp_config_wrapper result = { | 280 | check_icmp_config_wrapper result = { |
| 290 | .errorcode = OK, | 281 | .errorcode = OK, |
| 291 | .config = check_icmp_config_init(), | 282 | .config = check_icmp_config_init(), |
| @@ -821,6 +812,15 @@ void parse_address(const struct sockaddr_storage *addr, char *dst, socklen_t siz | |||
| 821 | } | 812 | } |
| 822 | 813 | ||
| 823 | int main(int argc, char **argv) { | 814 | int main(int argc, char **argv) { |
| 815 | #ifdef __OpenBSD__ | ||
| 816 | /* - rpath is required to read --extra-opts (given up later) | ||
| 817 | * - inet is required for sockets | ||
| 818 | * - dns is required for name lookups (given up later) | ||
| 819 | * - id is required for temporary privilege drops in configparsing and for | ||
| 820 | * permanent privilege dropping after opening the socket (given up later) */ | ||
| 821 | pledge("stdio rpath inet dns id", NULL); | ||
| 822 | #endif // __OpenBSD__ | ||
| 823 | |||
| 824 | setlocale(LC_ALL, ""); | 824 | setlocale(LC_ALL, ""); |
| 825 | bindtextdomain(PACKAGE, LOCALEDIR); | 825 | bindtextdomain(PACKAGE, LOCALEDIR); |
| 826 | textdomain(PACKAGE); | 826 | textdomain(PACKAGE); |
| @@ -828,6 +828,14 @@ int main(int argc, char **argv) { | |||
| 828 | /* POSIXLY_CORRECT might break things, so unset it (the portable way) */ | 828 | /* POSIXLY_CORRECT might break things, so unset it (the portable way) */ |
| 829 | environ = NULL; | 829 | environ = NULL; |
| 830 | 830 | ||
| 831 | /* determine program- and service-name quickly */ | ||
| 832 | progname = strrchr(argv[0], '/'); | ||
| 833 | if (progname != NULL) { | ||
| 834 | progname++; | ||
| 835 | } else { | ||
| 836 | progname = argv[0]; | ||
| 837 | } | ||
| 838 | |||
| 831 | /* Parse extra opts if any */ | 839 | /* Parse extra opts if any */ |
| 832 | argv = np_extra_opts(&argc, argv, progname); | 840 | argv = np_extra_opts(&argc, argv, progname); |
| 833 | 841 | ||
| @@ -837,6 +845,10 @@ int main(int argc, char **argv) { | |||
| 837 | crash("failed to parse config"); | 845 | crash("failed to parse config"); |
| 838 | } | 846 | } |
| 839 | 847 | ||
| 848 | #ifdef __OpenBSD__ | ||
| 849 | pledge("stdio inet dns id", NULL); | ||
| 850 | #endif // __OpenBSD__ | ||
| 851 | |||
| 840 | const check_icmp_config config = tmp_config.config; | 852 | const check_icmp_config config = tmp_config.config; |
| 841 | 853 | ||
| 842 | if (config.output_format_is_set) { | 854 | if (config.output_format_is_set) { |
| @@ -899,6 +911,10 @@ int main(int argc, char **argv) { | |||
| 899 | return 1; | 911 | return 1; |
| 900 | } | 912 | } |
| 901 | 913 | ||
| 914 | #ifdef __OpenBSD__ | ||
| 915 | pledge("stdio inet", NULL); | ||
| 916 | #endif // __OpenBSD__ | ||
| 917 | |||
| 902 | if (sockset.socket4) { | 918 | if (sockset.socket4) { |
| 903 | int result = setsockopt(sockset.socket4, SOL_IP, IP_TTL, &config.ttl, sizeof(config.ttl)); | 919 | int result = setsockopt(sockset.socket4, SOL_IP, IP_TTL, &config.ttl, sizeof(config.ttl)); |
| 904 | if (debug) { | 920 | if (debug) { |
| @@ -1470,10 +1486,13 @@ static recvfrom_wto_wrapper recvfrom_wto(const check_icmp_socket_set sockset, vo | |||
| 1470 | }; | 1486 | }; |
| 1471 | 1487 | ||
| 1472 | ssize_t ret; | 1488 | ssize_t ret; |
| 1473 | if (FD_ISSET(sockset.socket4, &read_fds)) { | 1489 | |
| 1490 | // Test explicitly whether sockets are in use | ||
| 1491 | // this is necessary at least on OpenBSD where FD_ISSET will segfault otherwise | ||
| 1492 | if ((sockset.socket4 != -1) && FD_ISSET(sockset.socket4, &read_fds)) { | ||
| 1474 | ret = recvmsg(sockset.socket4, &hdr, 0); | 1493 | ret = recvmsg(sockset.socket4, &hdr, 0); |
| 1475 | result.recv_proto = AF_INET; | 1494 | result.recv_proto = AF_INET; |
| 1476 | } else if (FD_ISSET(sockset.socket6, &read_fds)) { | 1495 | } else if ((sockset.socket6 != -1) && FD_ISSET(sockset.socket6, &read_fds)) { |
| 1477 | ret = recvmsg(sockset.socket6, &hdr, 0); | 1496 | ret = recvmsg(sockset.socket6, &hdr, 0); |
| 1478 | result.recv_proto = AF_INET6; | 1497 | result.recv_proto = AF_INET6; |
| 1479 | } else { | 1498 | } else { |
| @@ -1782,6 +1801,7 @@ static void set_source_ip(char *arg, const int icmp_sock, sa_family_t addr_famil | |||
| 1782 | /* TODO: Move this to netutils.c and also change check_dhcp to use that. */ | 1801 | /* TODO: Move this to netutils.c and also change check_dhcp to use that. */ |
| 1783 | static in_addr_t get_ip_address(const char *ifname, const int icmp_sock) { | 1802 | static in_addr_t get_ip_address(const char *ifname, const int icmp_sock) { |
| 1784 | // TODO: Rewrite this so the function return an error and we exit somewhere else | 1803 | // TODO: Rewrite this so the function return an error and we exit somewhere else |
| 1804 | |||
| 1785 | struct sockaddr_in ip_address; | 1805 | struct sockaddr_in ip_address; |
| 1786 | ip_address.sin_addr.s_addr = 0; // Fake initialization to make compiler happy | 1806 | ip_address.sin_addr.s_addr = 0; // Fake initialization to make compiler happy |
| 1787 | #if defined(SIOCGIFADDR) | 1807 | #if defined(SIOCGIFADDR) |
| @@ -1797,6 +1817,9 @@ static in_addr_t get_ip_address(const char *ifname, const int icmp_sock) { | |||
| 1797 | 1817 | ||
| 1798 | memcpy(&ip_address, &ifr.ifr_addr, sizeof(ip_address)); | 1818 | memcpy(&ip_address, &ifr.ifr_addr, sizeof(ip_address)); |
| 1799 | #else | 1819 | #else |
| 1820 | // fake operation to make the compiler happy | ||
| 1821 | (void)icmp_sock; | ||
| 1822 | |||
| 1800 | (void)ifname; | 1823 | (void)ifname; |
| 1801 | errno = 0; | 1824 | errno = 0; |
| 1802 | crash("Cannot get interface IP address on this platform."); | 1825 | crash("Cannot get interface IP address on this platform."); |
| @@ -2046,7 +2069,7 @@ unsigned short icmp_checksum(uint16_t *packet, size_t packet_size) { | |||
| 2046 | 2069 | ||
| 2047 | /* mop up the occasional odd byte */ | 2070 | /* mop up the occasional odd byte */ |
| 2048 | if (packet_size == 1) { | 2071 | if (packet_size == 1) { |
| 2049 | sum += *((uint8_t *)packet - 1); | 2072 | sum += *((uint8_t *)packet); |
| 2050 | } | 2073 | } |
| 2051 | 2074 | ||
| 2052 | sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ | 2075 | sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ |
| @@ -2245,7 +2268,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, | |||
| 2245 | * round trip jitter, but double the impact to latency | 2268 | * round trip jitter, but double the impact to latency |
| 2246 | * then add 10 for protocol latencies (in milliseconds). | 2269 | * then add 10 for protocol latencies (in milliseconds). |
| 2247 | */ | 2270 | */ |
| 2248 | EffectiveLatency = ((double)rta / 1000) + target.jitter * 2 + 10; | 2271 | EffectiveLatency = ((double)rta / 1000) + (target.jitter * 2) + 10; |
| 2249 | 2272 | ||
| 2250 | double R; | 2273 | double R; |
| 2251 | if (EffectiveLatency < 160) { | 2274 | if (EffectiveLatency < 160) { |
| @@ -2404,25 +2427,32 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, | |||
| 2404 | if (modes.score_mode) { | 2427 | if (modes.score_mode) { |
| 2405 | mp_subcheck sc_score = mp_subcheck_init(); | 2428 | mp_subcheck sc_score = mp_subcheck_init(); |
| 2406 | sc_score = mp_set_subcheck_default_state(sc_score, STATE_OK); | 2429 | sc_score = mp_set_subcheck_default_state(sc_score, STATE_OK); |
| 2407 | xasprintf(&sc_score.output, "Score %f", score); | ||
| 2408 | |||
| 2409 | if (score <= crit.score) { | ||
| 2410 | sc_score = mp_set_subcheck_state(sc_score, STATE_CRITICAL); | ||
| 2411 | xasprintf(&sc_score.output, "%s <= %f", sc_score.output, crit.score); | ||
| 2412 | } else if (score <= warn.score) { | ||
| 2413 | sc_score = mp_set_subcheck_state(sc_score, STATE_WARNING); | ||
| 2414 | xasprintf(&sc_score.output, "%s <= %f", sc_score.output, warn.score); | ||
| 2415 | } | ||
| 2416 | 2430 | ||
| 2417 | if (packet_loss < 100) { | 2431 | if (target.icmp_recv > 1) { |
| 2418 | mp_perfdata pd_score = perfdata_init(); | 2432 | xasprintf(&sc_score.output, "Score %f", score); |
| 2419 | xasprintf(&pd_score.label, "%sscore", address); | 2433 | |
| 2420 | pd_score.value = mp_create_pd_value(score); | 2434 | if (score <= crit.score) { |
| 2421 | pd_score.warn = mp_range_set_end(pd_score.warn, mp_create_pd_value(warn.score)); | 2435 | sc_score = mp_set_subcheck_state(sc_score, STATE_CRITICAL); |
| 2422 | pd_score.crit = mp_range_set_end(pd_score.crit, mp_create_pd_value(crit.score)); | 2436 | xasprintf(&sc_score.output, "%s <= %f", sc_score.output, crit.score); |
| 2423 | pd_score.min = mp_create_pd_value(0); | 2437 | } else if (score <= warn.score) { |
| 2424 | pd_score.max = mp_create_pd_value(100); | 2438 | sc_score = mp_set_subcheck_state(sc_score, STATE_WARNING); |
| 2425 | mp_add_perfdata_to_subcheck(&sc_score, pd_score); | 2439 | xasprintf(&sc_score.output, "%s <= %f", sc_score.output, warn.score); |
| 2440 | } | ||
| 2441 | |||
| 2442 | if (packet_loss < 100) { | ||
| 2443 | mp_perfdata pd_score = perfdata_init(); | ||
| 2444 | xasprintf(&pd_score.label, "%sscore", address); | ||
| 2445 | pd_score.value = mp_create_pd_value(score); | ||
| 2446 | pd_score.warn = mp_range_set_end(pd_score.warn, mp_create_pd_value(warn.score)); | ||
| 2447 | pd_score.crit = mp_range_set_end(pd_score.crit, mp_create_pd_value(crit.score)); | ||
| 2448 | pd_score.min = mp_create_pd_value(0); | ||
| 2449 | pd_score.max = mp_create_pd_value(100); | ||
| 2450 | mp_add_perfdata_to_subcheck(&sc_score, pd_score); | ||
| 2451 | } | ||
| 2452 | |||
| 2453 | } else { | ||
| 2454 | // score mode disabled due to not enough received packages | ||
| 2455 | xasprintf(&sc_score.output, "Score mode disabled, not enough packets received"); | ||
| 2426 | } | 2456 | } |
| 2427 | 2457 | ||
| 2428 | mp_add_subcheck_to_subcheck(&result, sc_score); | 2458 | mp_add_subcheck_to_subcheck(&result, sc_score); |
