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.c98
1 files changed, 64 insertions, 34 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index a57edef4..dad03ffa 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -138,7 +138,11 @@ void print_help();
138void print_usage(void); 138void print_usage(void);
139 139
140/* Time related */ 140/* Time related */
141static unsigned int get_timevar(const char *str); 141typedef struct {
142 int error_code;
143 time_t time_range;
144} get_timevar_wrapper;
145static get_timevar_wrapper get_timevar(const char *str);
142static time_t get_timevaldiff(struct timeval earlier, struct timeval later); 146static time_t get_timevaldiff(struct timeval earlier, struct timeval later);
143static time_t get_timevaldiff_to_now(struct timeval earlier); 147static time_t get_timevaldiff_to_now(struct timeval earlier);
144 148
@@ -196,8 +200,8 @@ static parse_threshold2_helper_wrapper parse_threshold2_helper(char *threshold_s
196/* main test function */ 200/* main test function */
197static void run_checks(unsigned short icmp_pkt_size, time_t *pkt_interval, time_t *target_interval, 201static void run_checks(unsigned short icmp_pkt_size, time_t *pkt_interval, time_t *target_interval,
198 uint16_t sender_id, check_icmp_execution_mode mode, 202 uint16_t sender_id, check_icmp_execution_mode mode,
199 unsigned int max_completion_time, struct timeval prog_start, 203 time_t max_completion_time, struct timeval prog_start, ping_target **table,
200 ping_target **table, unsigned short packets, check_icmp_socket_set sockset, 204 unsigned short packets, check_icmp_socket_set sockset,
201 unsigned short number_of_targets, check_icmp_state *program_state); 205 unsigned short number_of_targets, check_icmp_state *program_state);
202mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, 206mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
203 check_icmp_threshold warn, check_icmp_threshold crit); 207 check_icmp_threshold warn, check_icmp_threshold crit);
@@ -249,7 +253,7 @@ static void finish(int sign, check_icmp_mode_switches modes, int min_hosts_alive
249 mp_check overall[static 1]); 253 mp_check overall[static 1]);
250 254
251/* Error exit */ 255/* Error exit */
252static void crash(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); 256static void crash(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
253 257
254/** global variables **/ 258/** global variables **/
255static int debug = 0; 259static int debug = 0;
@@ -384,12 +388,24 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) {
384 MAX_PING_DATA - 1); 388 MAX_PING_DATA - 1);
385 } 389 }
386 } break; 390 } break;
387 case 'i': 391 case 'i': {
388 result.config.pkt_interval = get_timevar(optarg); 392 get_timevar_wrapper parsed_time = get_timevar(optarg);
389 break; 393
390 case 'I': 394 if (parsed_time.error_code == OK) {
391 result.config.target_interval = get_timevar(optarg); 395 result.config.pkt_interval = parsed_time.time_range;
392 break; 396 } else {
397 crash("failed to parse packet interval");
398 }
399 } break;
400 case 'I': {
401 get_timevar_wrapper parsed_time = get_timevar(optarg);
402
403 if (parsed_time.error_code == OK) {
404 result.config.target_interval = parsed_time.time_range;
405 } else {
406 crash("failed to parse target interval");
407 }
408 } break;
393 case 'w': { 409 case 'w': {
394 get_threshold_wrapper warn = get_threshold(optarg, result.config.warn); 410 get_threshold_wrapper warn = get_threshold(optarg, result.config.warn);
395 if (warn.errorcode == OK) { 411 if (warn.errorcode == OK) {
@@ -575,7 +591,7 @@ static void crash(const char *fmt, ...) {
575 puts(""); 591 puts("");
576 592
577 exit(3); 593 exit(3);
578} 594}
579 595
580static const char *get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code) { 596static const char *get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code) {
581 const char *msg = "unreachable"; 597 const char *msg = "unreachable";
@@ -743,8 +759,8 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad
743 /* source quench means we're sending too fast, so increase the 759 /* source quench means we're sending too fast, so increase the
744 * interval and mark this packet lost */ 760 * interval and mark this packet lost */
745 if (icmp_packet.icmp_type == ICMP_SOURCEQUENCH) { 761 if (icmp_packet.icmp_type == ICMP_SOURCEQUENCH) {
746 *pkt_interval = (unsigned int)(*pkt_interval * PACKET_BACKOFF_FACTOR); 762 *pkt_interval = (unsigned int)((double)*pkt_interval * PACKET_BACKOFF_FACTOR);
747 *target_interval = (unsigned int)(*target_interval * TARGET_BACKOFF_FACTOR); 763 *target_interval = (unsigned int)((double)*target_interval * TARGET_BACKOFF_FACTOR);
748 } else { 764 } else {
749 program_state->targets_down++; 765 program_state->targets_down++;
750 host->flags |= FLAG_LOST_CAUSE; 766 host->flags |= FLAG_LOST_CAUSE;
@@ -899,7 +915,7 @@ int main(int argc, char **argv) {
899 gettimeofday(&prog_start, NULL); 915 gettimeofday(&prog_start, NULL);
900 916
901 time_t max_completion_time = 917 time_t max_completion_time =
902 ((config.pkt_interval *config.number_of_targets * config.number_of_packets) + 918 ((config.pkt_interval * config.number_of_targets * config.number_of_packets) +
903 (config.target_interval * config.number_of_targets)) + 919 (config.target_interval * config.number_of_targets)) +
904 (config.number_of_targets * config.number_of_packets * config.crit.rta) + config.crit.rta; 920 (config.number_of_targets * config.number_of_packets * config.crit.rta) + config.crit.rta;
905 921
@@ -921,7 +937,7 @@ int main(int argc, char **argv) {
921 } 937 }
922 938
923 if (debug) { 939 if (debug) {
924 printf("crit = {%u, %u%%}, warn = {%u, %u%%}\n", config.crit.rta, config.crit.pl, 940 printf("crit = {%ld, %u%%}, warn = {%ld, %u%%}\n", config.crit.rta, config.crit.pl,
925 config.warn.rta, config.warn.pl); 941 config.warn.rta, config.warn.pl);
926 printf("pkt_interval: %ld target_interval: %ld\n", config.pkt_interval, 942 printf("pkt_interval: %ld target_interval: %ld\n", config.pkt_interval,
927 config.target_interval); 943 config.target_interval);
@@ -976,7 +992,7 @@ int main(int argc, char **argv) {
976 992
977static void run_checks(unsigned short icmp_pkt_size, time_t *pkt_interval, time_t *target_interval, 993static void run_checks(unsigned short icmp_pkt_size, time_t *pkt_interval, time_t *target_interval,
978 const uint16_t sender_id, const check_icmp_execution_mode mode, 994 const uint16_t sender_id, const check_icmp_execution_mode mode,
979 const unsigned int max_completion_time, const struct timeval prog_start, 995 const time_t max_completion_time, const struct timeval prog_start,
980 ping_target **table, const unsigned short packets, 996 ping_target **table, const unsigned short packets,
981 const check_icmp_socket_set sockset, const unsigned short number_of_targets, 997 const check_icmp_socket_set sockset, const unsigned short number_of_targets,
982 check_icmp_state *program_state) { 998 check_icmp_state *program_state) {
@@ -1028,7 +1044,7 @@ static void run_checks(unsigned short icmp_pkt_size, time_t *pkt_interval, time_
1028 time_t final_wait = max_completion_time - time_passed; 1044 time_t final_wait = max_completion_time - time_passed;
1029 1045
1030 if (debug) { 1046 if (debug) {
1031 printf("time_passed: %ld final_wait: %ld max_completion_time: %u\n", time_passed, 1047 printf("time_passed: %ld final_wait: %ld max_completion_time: %ld\n", time_passed,
1032 final_wait, max_completion_time); 1048 final_wait, max_completion_time);
1033 } 1049 }
1034 if (time_passed > max_completion_time) { 1050 if (time_passed > max_completion_time) {
@@ -1138,7 +1154,6 @@ static int wait_for_reply(check_icmp_socket_set sockset, const time_t time_inter
1138 parse_address(&resp_addr, address, sizeof(address)); 1154 parse_address(&resp_addr, address, sizeof(address));
1139 crash("received packet too short for ICMP (%ld bytes, expected %d) from %s\n", 1155 crash("received packet too short for ICMP (%ld bytes, expected %d) from %s\n",
1140 recv_foo.received, hlen + icmp_pkt_size, address); 1156 recv_foo.received, hlen + icmp_pkt_size, address);
1141
1142 } 1157 }
1143 /* check the response */ 1158 /* check the response */
1144 memcpy(packet.buf, buf + hlen, icmp_pkt_size); 1159 memcpy(packet.buf, buf + hlen, icmp_pkt_size);
@@ -1272,7 +1287,7 @@ static int send_icmp_ping(const check_icmp_socket_set sockset, ping_target *host
1272 data.ping_id = 10; /* host->icmp.icmp_sent; */ 1287 data.ping_id = 10; /* host->icmp.icmp_sent; */
1273 memcpy(&data.stime, &current_time, sizeof(current_time)); 1288 memcpy(&data.stime, &current_time, sizeof(current_time));
1274 1289
1275 socklen_t addrlen; 1290 socklen_t addrlen = 0;
1276 1291
1277 if (host->address.ss_family == AF_INET) { 1292 if (host->address.ss_family == AF_INET) {
1278 struct icmp *icp = (struct icmp *)buf; 1293 struct icmp *icp = (struct icmp *)buf;
@@ -1789,14 +1804,21 @@ static in_addr_t get_ip_address(const char *ifname) {
1789 * s = seconds 1804 * s = seconds
1790 * return value is in microseconds 1805 * return value is in microseconds
1791 */ 1806 */
1792static unsigned int get_timevar(const char *str) { 1807static get_timevar_wrapper get_timevar(const char *str) {
1808 get_timevar_wrapper result = {
1809 .error_code = OK,
1810 .time_range = 0,
1811 };
1812
1793 if (!str) { 1813 if (!str) {
1794 return 0; 1814 result.error_code = ERROR;
1815 return result;
1795 } 1816 }
1796 1817
1797 size_t len = strlen(str); 1818 size_t len = strlen(str);
1798 if (!len) { 1819 if (!len) {
1799 return 0; 1820 result.error_code = ERROR;
1821 return result;
1800 } 1822 }
1801 1823
1802 /* unit might be given as ms|m (millisec), 1824 /* unit might be given as ms|m (millisec),
@@ -1834,12 +1856,14 @@ static unsigned int get_timevar(const char *str) {
1834 unsigned long pre_radix; 1856 unsigned long pre_radix;
1835 pre_radix = strtoul(str, &ptr, 0); 1857 pre_radix = strtoul(str, &ptr, 0);
1836 if (!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1) { 1858 if (!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1) {
1837 return (unsigned int)(pre_radix * factor); 1859 result.time_range = (unsigned int)(pre_radix * factor);
1860 return result;
1838 } 1861 }
1839 1862
1840 /* time specified in usecs can't have decimal points, so ignore them */ 1863 /* time specified in usecs can't have decimal points, so ignore them */
1841 if (factor == 1) { 1864 if (factor == 1) {
1842 return (unsigned int)pre_radix; 1865 result.time_range = (unsigned int)pre_radix;
1866 return result;
1843 } 1867 }
1844 1868
1845 /* integer and decimal, respectively */ 1869 /* integer and decimal, respectively */
@@ -1851,10 +1875,10 @@ static unsigned int get_timevar(const char *str) {
1851 } 1875 }
1852 1876
1853 /* the last parenthesis avoids floating point exceptions. */ 1877 /* the last parenthesis avoids floating point exceptions. */
1854 return (unsigned int)((pre_radix * factor) + (post_radix * (factor / 10))); 1878 result.time_range = (unsigned int)((pre_radix * factor) + (post_radix * (factor / 10)));
1879 return result;
1855} 1880}
1856 1881
1857/* not too good at checking errors, but it'll do (main() should barfe on -1) */
1858static get_threshold_wrapper get_threshold(char *str, check_icmp_threshold threshold) { 1882static get_threshold_wrapper get_threshold(char *str, check_icmp_threshold threshold) {
1859 get_threshold_wrapper result = { 1883 get_threshold_wrapper result = {
1860 .errorcode = OK, 1884 .errorcode = OK,
@@ -1880,9 +1904,15 @@ static get_threshold_wrapper get_threshold(char *str, check_icmp_threshold thres
1880 is_at_last_char = true; 1904 is_at_last_char = true;
1881 tmp--; 1905 tmp--;
1882 } 1906 }
1883 result.threshold.rta = get_timevar(str);
1884 1907
1885 if (!result.threshold.rta) { 1908 get_timevar_wrapper parsed_time = get_timevar(str);
1909
1910 if (parsed_time.error_code == OK) {
1911 result.threshold.rta = parsed_time.time_range;
1912 } else {
1913 if (debug > 1) {
1914 printf("%s: failed to parse rta threshold\n", __FUNCTION__);
1915 }
1886 result.errorcode = ERROR; 1916 result.errorcode = ERROR;
1887 return result; 1917 return result;
1888 } 1918 }
@@ -2170,7 +2200,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
2170 xasprintf(&result.output, "%s", address); 2200 xasprintf(&result.output, "%s", address);
2171 2201
2172 double packet_loss; 2202 double packet_loss;
2173 double rta; 2203 time_t rta;
2174 if (!target.icmp_recv) { 2204 if (!target.icmp_recv) {
2175 /* rta 0 is of course not entirely correct, but will still show up 2205 /* rta 0 is of course not entirely correct, but will still show up
2176 * conspicuously as missing entries in perfparse and cacti */ 2206 * conspicuously as missing entries in perfparse and cacti */
@@ -2188,7 +2218,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
2188 } else { 2218 } else {
2189 packet_loss = 2219 packet_loss =
2190 (unsigned char)((target.icmp_sent - target.icmp_recv) * 100) / target.icmp_sent; 2220 (unsigned char)((target.icmp_sent - target.icmp_recv) * 100) / target.icmp_sent;
2191 rta = (double)target.time_waited / target.icmp_recv; 2221 rta = target.time_waited / target.icmp_recv;
2192 } 2222 }
2193 2223
2194 double EffectiveLatency; 2224 double EffectiveLatency;
@@ -2219,7 +2249,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
2219 * round trip jitter, but double the impact to latency 2249 * round trip jitter, but double the impact to latency
2220 * then add 10 for protocol latencies (in milliseconds). 2250 * then add 10 for protocol latencies (in milliseconds).
2221 */ 2251 */
2222 EffectiveLatency = (rta / 1000) + target.jitter * 2 + 10; 2252 EffectiveLatency = ((double)rta / 1000) + target.jitter * 2 + 10;
2223 2253
2224 double R; 2254 double R;
2225 if (EffectiveLatency < 160) { 2255 if (EffectiveLatency < 160) {
@@ -2249,14 +2279,14 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
2249 if (modes.rta_mode) { 2279 if (modes.rta_mode) {
2250 mp_subcheck sc_rta = mp_subcheck_init(); 2280 mp_subcheck sc_rta = mp_subcheck_init();
2251 sc_rta = mp_set_subcheck_default_state(sc_rta, STATE_OK); 2281 sc_rta = mp_set_subcheck_default_state(sc_rta, STATE_OK);
2252 xasprintf(&sc_rta.output, "rta %0.3fms", rta / 1000); 2282 xasprintf(&sc_rta.output, "rta %0.3fms", (double)rta / 1000);
2253 2283
2254 if (rta >= crit.rta) { 2284 if (rta >= crit.rta) {
2255 sc_rta = mp_set_subcheck_state(sc_rta, STATE_CRITICAL); 2285 sc_rta = mp_set_subcheck_state(sc_rta, STATE_CRITICAL);
2256 xasprintf(&sc_rta.output, "%s > %0.3fms", sc_rta.output, (double) crit.rta / 1000); 2286 xasprintf(&sc_rta.output, "%s > %0.3fms", sc_rta.output, (double)crit.rta / 1000);
2257 } else if (rta >= warn.rta) { 2287 } else if (rta >= warn.rta) {
2258 sc_rta = mp_set_subcheck_state(sc_rta, STATE_WARNING); 2288 sc_rta = mp_set_subcheck_state(sc_rta, STATE_WARNING);
2259 xasprintf(&sc_rta.output, "%s > %0.3fms", sc_rta.output, (double) warn.rta / 1000); 2289 xasprintf(&sc_rta.output, "%s > %0.3fms", sc_rta.output, (double)warn.rta / 1000);
2260 } 2290 }
2261 2291
2262 if (packet_loss < 100) { 2292 if (packet_loss < 100) {