summaryrefslogtreecommitdiffstats
path: root/plugins-root/check_icmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins-root/check_icmp.c')
-rw-r--r--plugins-root/check_icmp.c103
1 files changed, 68 insertions, 35 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index d46d2ccc..1390a03e 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -54,6 +54,9 @@ const char *email = "devel@monitoring-plugins.org";
54#endif 54#endif
55 55
56#include <sys/time.h> 56#include <sys/time.h>
57#if defined(SIOCGIFADDR)
58# include <sys/ioctl.h>
59#endif /* SIOCGIFADDR */
57#include <errno.h> 60#include <errno.h>
58#include <signal.h> 61#include <signal.h>
59#include <ctype.h> 62#include <ctype.h>
@@ -146,7 +149,7 @@ static get_timevar_wrapper get_timevar(const char *str);
146static time_t get_timevaldiff(struct timeval earlier, struct timeval later); 149static time_t get_timevaldiff(struct timeval earlier, struct timeval later);
147static time_t get_timevaldiff_to_now(struct timeval earlier); 150static time_t get_timevaldiff_to_now(struct timeval earlier);
148 151
149static in_addr_t get_ip_address(const char *ifname); 152static in_addr_t get_ip_address(const char *ifname, const int icmp_sock);
150static void set_source_ip(char *arg, int icmp_sock, sa_family_t addr_family); 153static void set_source_ip(char *arg, int icmp_sock, sa_family_t addr_family);
151 154
152/* Receiving data */ 155/* Receiving data */
@@ -274,15 +277,6 @@ typedef struct {
274 check_icmp_config config; 277 check_icmp_config config;
275} check_icmp_config_wrapper; 278} check_icmp_config_wrapper;
276check_icmp_config_wrapper process_arguments(int argc, char **argv) { 279check_icmp_config_wrapper process_arguments(int argc, char **argv) {
277 /* get calling name the old-fashioned way for portability instead
278 * of relying on the glibc-ism __progname */
279 char *ptr = strrchr(argv[0], '/');
280 if (ptr) {
281 progname = &ptr[1];
282 } else {
283 progname = argv[0];
284 }
285
286 check_icmp_config_wrapper result = { 280 check_icmp_config_wrapper result = {
287 .errorcode = OK, 281 .errorcode = OK,
288 .config = check_icmp_config_init(), 282 .config = check_icmp_config_init(),
@@ -818,6 +812,15 @@ void parse_address(const struct sockaddr_storage *addr, char *dst, socklen_t siz
818} 812}
819 813
820int main(int argc, char **argv) { 814int 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
821 setlocale(LC_ALL, ""); 824 setlocale(LC_ALL, "");
822 bindtextdomain(PACKAGE, LOCALEDIR); 825 bindtextdomain(PACKAGE, LOCALEDIR);
823 textdomain(PACKAGE); 826 textdomain(PACKAGE);
@@ -825,6 +828,14 @@ int main(int argc, char **argv) {
825 /* POSIXLY_CORRECT might break things, so unset it (the portable way) */ 828 /* POSIXLY_CORRECT might break things, so unset it (the portable way) */
826 environ = NULL; 829 environ = NULL;
827 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
828 /* Parse extra opts if any */ 839 /* Parse extra opts if any */
829 argv = np_extra_opts(&argc, argv, progname); 840 argv = np_extra_opts(&argc, argv, progname);
830 841
@@ -834,6 +845,10 @@ int main(int argc, char **argv) {
834 crash("failed to parse config"); 845 crash("failed to parse config");
835 } 846 }
836 847
848#ifdef __OpenBSD__
849 pledge("stdio inet dns id", NULL);
850#endif // __OpenBSD__
851
837 const check_icmp_config config = tmp_config.config; 852 const check_icmp_config config = tmp_config.config;
838 853
839 if (config.output_format_is_set) { 854 if (config.output_format_is_set) {
@@ -896,6 +911,10 @@ int main(int argc, char **argv) {
896 return 1; 911 return 1;
897 } 912 }
898 913
914#ifdef __OpenBSD__
915 pledge("stdio inet", NULL);
916#endif // __OpenBSD__
917
899 if (sockset.socket4) { 918 if (sockset.socket4) {
900 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));
901 if (debug) { 920 if (debug) {
@@ -1467,10 +1486,13 @@ static recvfrom_wto_wrapper recvfrom_wto(const check_icmp_socket_set sockset, vo
1467 }; 1486 };
1468 1487
1469 ssize_t ret; 1488 ssize_t ret;
1470 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)) {
1471 ret = recvmsg(sockset.socket4, &hdr, 0); 1493 ret = recvmsg(sockset.socket4, &hdr, 0);
1472 result.recv_proto = AF_INET; 1494 result.recv_proto = AF_INET;
1473 } else if (FD_ISSET(sockset.socket6, &read_fds)) { 1495 } else if ((sockset.socket6 != -1) && FD_ISSET(sockset.socket6, &read_fds)) {
1474 ret = recvmsg(sockset.socket6, &hdr, 0); 1496 ret = recvmsg(sockset.socket6, &hdr, 0);
1475 result.recv_proto = AF_INET6; 1497 result.recv_proto = AF_INET6;
1476 } else { 1498 } else {
@@ -1769,7 +1791,7 @@ static void set_source_ip(char *arg, const int icmp_sock, sa_family_t addr_famil
1769 memset(&src, 0, sizeof(src)); 1791 memset(&src, 0, sizeof(src));
1770 src.sin_family = addr_family; 1792 src.sin_family = addr_family;
1771 if ((src.sin_addr.s_addr = inet_addr(arg)) == INADDR_NONE) { 1793 if ((src.sin_addr.s_addr = inet_addr(arg)) == INADDR_NONE) {
1772 src.sin_addr.s_addr = get_ip_address(arg); 1794 src.sin_addr.s_addr = get_ip_address(arg, icmp_sock);
1773 } 1795 }
1774 if (bind(icmp_sock, (struct sockaddr *)&src, sizeof(src)) == -1) { 1796 if (bind(icmp_sock, (struct sockaddr *)&src, sizeof(src)) == -1) {
1775 crash("Cannot bind to IP address %s", arg); 1797 crash("Cannot bind to IP address %s", arg);
@@ -1777,8 +1799,9 @@ static void set_source_ip(char *arg, const int icmp_sock, sa_family_t addr_famil
1777} 1799}
1778 1800
1779/* 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. */
1780static in_addr_t get_ip_address(const char *ifname) { 1802static in_addr_t get_ip_address(const char *ifname, const int icmp_sock) {
1781 // 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
1782 struct sockaddr_in ip_address; 1805 struct sockaddr_in ip_address;
1783 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
1784#if defined(SIOCGIFADDR) 1807#if defined(SIOCGIFADDR)
@@ -1792,8 +1815,11 @@ static in_addr_t get_ip_address(const char *ifname) {
1792 crash("Cannot determine IP address of interface %s", ifname); 1815 crash("Cannot determine IP address of interface %s", ifname);
1793 } 1816 }
1794 1817
1795 memcpy(&ip, &ifr.ifr_addr, sizeof(ip)); 1818 memcpy(&ip_address, &ifr.ifr_addr, sizeof(ip_address));
1796#else 1819#else
1820 // fake operation to make the compiler happy
1821 (void)icmp_sock;
1822
1797 (void)ifname; 1823 (void)ifname;
1798 errno = 0; 1824 errno = 0;
1799 crash("Cannot get interface IP address on this platform."); 1825 crash("Cannot get interface IP address on this platform.");
@@ -2043,7 +2069,7 @@ unsigned short icmp_checksum(uint16_t *packet, size_t packet_size) {
2043 2069
2044 /* mop up the occasional odd byte */ 2070 /* mop up the occasional odd byte */
2045 if (packet_size == 1) { 2071 if (packet_size == 1) {
2046 sum += *((uint8_t *)packet - 1); 2072 sum += *((uint8_t *)packet);
2047 } 2073 }
2048 2074
2049 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 2075 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
@@ -2242,7 +2268,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
2242 * round trip jitter, but double the impact to latency 2268 * round trip jitter, but double the impact to latency
2243 * then add 10 for protocol latencies (in milliseconds). 2269 * then add 10 for protocol latencies (in milliseconds).
2244 */ 2270 */
2245 EffectiveLatency = ((double)rta / 1000) + target.jitter * 2 + 10; 2271 EffectiveLatency = ((double)rta / 1000) + (target.jitter * 2) + 10;
2246 2272
2247 double R; 2273 double R;
2248 if (EffectiveLatency < 160) { 2274 if (EffectiveLatency < 160) {
@@ -2401,25 +2427,32 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
2401 if (modes.score_mode) { 2427 if (modes.score_mode) {
2402 mp_subcheck sc_score = mp_subcheck_init(); 2428 mp_subcheck sc_score = mp_subcheck_init();
2403 sc_score = mp_set_subcheck_default_state(sc_score, STATE_OK); 2429 sc_score = mp_set_subcheck_default_state(sc_score, STATE_OK);
2404 xasprintf(&sc_score.output, "Score %f", score);
2405
2406 if (score <= crit.score) {
2407 sc_score = mp_set_subcheck_state(sc_score, STATE_CRITICAL);
2408 xasprintf(&sc_score.output, "%s <= %f", sc_score.output, crit.score);
2409 } else if (score <= warn.score) {
2410 sc_score = mp_set_subcheck_state(sc_score, STATE_WARNING);
2411 xasprintf(&sc_score.output, "%s <= %f", sc_score.output, warn.score);
2412 }
2413 2430
2414 if (packet_loss < 100) { 2431 if (target.icmp_recv > 1) {
2415 mp_perfdata pd_score = perfdata_init(); 2432 xasprintf(&sc_score.output, "Score %f", score);
2416 xasprintf(&pd_score.label, "%sscore", address); 2433
2417 pd_score.value = mp_create_pd_value(score); 2434 if (score <= crit.score) {
2418 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);
2419 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);
2420 pd_score.min = mp_create_pd_value(0); 2437 } else if (score <= warn.score) {
2421 pd_score.max = mp_create_pd_value(100); 2438 sc_score = mp_set_subcheck_state(sc_score, STATE_WARNING);
2422 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");
2423 } 2456 }
2424 2457
2425 mp_add_subcheck_to_subcheck(&result, sc_score); 2458 mp_add_subcheck_to_subcheck(&result, sc_score);