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.c724
1 files changed, 386 insertions, 338 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index 87dac21d..99414014 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -66,6 +66,9 @@ const char *email = "devel@monitoring-plugins.org";
66#include <arpa/inet.h> 66#include <arpa/inet.h>
67#include <math.h> 67#include <math.h>
68#include <netdb.h> 68#include <netdb.h>
69#include <sys/types.h>
70#include <unistd.h>
71#include <stdint.h>
69 72
70#include "../lib/states.h" 73#include "../lib/states.h"
71#include "./check_icmp.d/config.h" 74#include "./check_icmp.d/config.h"
@@ -131,76 +134,79 @@ void print_usage(void);
131 134
132/* Time related */ 135/* Time related */
133static unsigned int get_timevar(const char * /*str*/); 136static unsigned int get_timevar(const char * /*str*/);
134static time_t get_timevaldiff(struct timeval * /*early*/, struct timeval * /*later*/, 137static time_t get_timevaldiff(struct timeval earlier, struct timeval later);
135 struct timeval *prog_start); 138static time_t get_timevaldiff_to_now(struct timeval earlier);
136 139
137static in_addr_t get_ip_address(const char * /*ifname*/); 140static in_addr_t get_ip_address(const char * /*ifname*/);
138static void set_source_ip(char * /*arg*/, const int icmp_sock); 141static void set_source_ip(char * /*arg*/, int icmp_sock);
139 142
140/* Receiving data */ 143/* Receiving data */
141static int wait_for_reply(int /*sock*/, unsigned int /*t*/, bool order_mode, bool mos_mode, 144static int wait_for_reply(int socket, time_t time_interval, unsigned short icmp_pkt_size,
142 bool rta_mode, bool pl_mode, bool jitter_mode, bool score_mode, 145 unsigned int *pkt_interval, unsigned int *target_interval, pid_t pid,
143 int min_hosts_alive, unsigned short icmp_pkt_size, 146 ping_target **table, unsigned short packets,
144 unsigned int *pkt_interval, unsigned int *target_interval, threshold warn, 147 unsigned short number_of_targets, check_icmp_state *program_state);
145 threshold crit, pid_t pid, int mode, 148
146 unsigned long long max_completion_time, struct timeval *prog_start, 149static ssize_t recvfrom_wto(int /*sock*/, void * /*buf*/, unsigned int /*len*/,
147 struct rta_host **table, const unsigned short packets, 150 struct sockaddr * /*saddr*/, time_t *timeout, struct timeval * /*tv*/);
148 const int icmp_sock, const unsigned short number_of_targets,
149 check_icmp_state *program_state);
150
151static int recvfrom_wto(int /*sock*/, void * /*buf*/, unsigned int /*len*/,
152 struct sockaddr * /*saddr*/, unsigned int * /*timo*/,
153 struct timeval * /*tv*/, struct timeval *prog_start);
154static int handle_random_icmp(unsigned char * /*packet*/, struct sockaddr_storage * /*addr*/, 151static int handle_random_icmp(unsigned char * /*packet*/, struct sockaddr_storage * /*addr*/,
155 unsigned int *pkt_interval, unsigned int *target_interval, pid_t pid, 152 unsigned int *pkt_interval, unsigned int *target_interval, pid_t pid,
156 struct rta_host **table, unsigned short packets, 153 ping_target **table, unsigned short packets,
157 const unsigned short number_of_targets, 154 unsigned short number_of_targets, check_icmp_state *program_state);
158 check_icmp_state *program_state);
159 155
160/* Sending data */ 156/* Sending data */
161static int send_icmp_ping(int /*sock*/, struct rta_host * /*host*/, unsigned short icmp_pkt_size, 157static int send_icmp_ping(int /*sock*/, ping_target * /*host*/, unsigned short icmp_pkt_size,
162 pid_t pid, check_icmp_state *program_state); 158 pid_t pid, check_icmp_state *program_state);
163 159
164/* Threshold related */ 160/* Threshold related */
165static int get_threshold(char *str, threshold *th); 161static int get_threshold(char *str, threshold *threshold);
166static bool get_threshold2(char *str, size_t length, threshold * /*warn*/, threshold * /*crit*/, 162static bool get_threshold2(char *str, size_t length, threshold * /*warn*/, threshold * /*crit*/,
167 threshold_mode mode); 163 threshold_mode mode);
168static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, threshold_mode mode); 164static bool parse_threshold2_helper(char *threshold_string, size_t length, threshold *thr,
165 threshold_mode mode);
169 166
170/* main test function */ 167/* main test function */
171static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, 168static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode,
172 bool jitter_mode, bool score_mode, int min_hosts_alive, 169 bool jitter_mode, bool score_mode, int min_hosts_alive,
173 unsigned short icmp_pkt_size, unsigned int *pkt_interval, 170 unsigned short icmp_pkt_size, unsigned int *pkt_interval,
174 unsigned int *target_interval, threshold warn, threshold crit, pid_t pid, 171 unsigned int *target_interval, threshold warn, threshold crit, pid_t pid,
175 int mode, unsigned int max_completion_time, const struct timeval *prog_start, 172 int mode, unsigned int max_completion_time, struct timeval prog_start,
176 struct rta_host **table, const unsigned short packets, const int icmp_sock, 173 ping_target **table, unsigned short packets, int icmp_sock,
177 const unsigned short number_of_targets, check_icmp_state *program_state); 174 unsigned short number_of_targets, check_icmp_state *program_state,
175 ping_target *target_list);
178 176
179/* Target aquisition */ 177/* Target aquisition */
180static int add_target(char * /*arg*/, int mode); 178typedef struct {
181static int add_target_ip(char * /*arg*/, struct sockaddr_storage * /*in*/); 179 int error_code;
180 ping_target *targets;
181 unsigned int number_of_targets;
182} add_target_wrapper;
183static add_target_wrapper add_target(char * /*arg*/, int mode);
184
185typedef struct {
186 int error_code;
187 ping_target *target;
188} add_target_ip_wrapper;
189static add_target_ip_wrapper add_target_ip(char * /*arg*/, struct sockaddr_storage * /*in*/);
182 190
183static void parse_address(struct sockaddr_storage * /*addr*/, char * /*address*/, int /*size*/); 191static void parse_address(struct sockaddr_storage * /*addr*/, char * /*address*/, socklen_t size);
184 192
185static unsigned short icmp_checksum(uint16_t * /*p*/, size_t /*n*/); 193static unsigned short icmp_checksum(uint16_t * /*p*/, size_t /*n*/);
186 194
187/* End of run function */ 195/* End of run function */
188static void finish(int /*sig*/, bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, 196static void finish(int /*sig*/, bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode,
189 bool jitter_mode, bool score_mode, int min_hosts_alive, threshold warn, 197 bool jitter_mode, bool score_mode, int min_hosts_alive, threshold warn,
190 threshold crit, const int icmp_sock, const unsigned short number_of_targets, 198 threshold crit, int icmp_sock, unsigned short number_of_targets,
191 check_icmp_state *program_state); 199 check_icmp_state *program_state, ping_target *target_list);
192 200
193/* Error exit */ 201/* Error exit */
194static void crash(const char * /*fmt*/, ...); 202static void crash(const char * /*fmt*/, ...);
195 203
196/** global variables **/ 204/** global variables **/
197static struct rta_host *cursor = NULL;
198static struct rta_host *host_list = NULL;
199
200static int debug = 0; 205static int debug = 0;
201 206
202/** the working code **/ 207extern unsigned int timeout;
203 208
209/** the working code **/
204static inline unsigned short targets_alive(unsigned short targets, unsigned short targets_down) { 210static inline unsigned short targets_alive(unsigned short targets, unsigned short targets_down) {
205 return targets - targets_down; 211 return targets - targets_down;
206} 212}
@@ -259,7 +265,8 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) {
259 } 265 }
260 } 266 }
261 267
262 /* Parse protocol arguments first */ 268 // Parse protocol arguments first
269 // and count hosts here
263 char *opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64"; 270 char *opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64";
264 for (int i = 1; i < argc; i++) { 271 for (int i = 1; i < argc; i++) {
265 long int arg; 272 long int arg;
@@ -281,10 +288,31 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) {
281 usage(_("IPv6 support not available\n")); 288 usage(_("IPv6 support not available\n"));
282#endif 289#endif
283 break; 290 break;
291 case 'H': {
292 result.config.number_of_hosts++;
293 }
284 } 294 }
285 } 295 }
286 } 296 }
287 297
298 char **tmp = &argv[optind];
299 while (*tmp) {
300 result.config.number_of_hosts++;
301 tmp++;
302 }
303
304 // Sanity check: if hostmode is selected,only a single host is allowed
305 if (result.config.mode == MODE_HOSTCHECK && result.config.number_of_hosts > 1) {
306 usage("check_host only allows a single host");
307 }
308
309 // Allocate hosts
310 result.config.hosts =
311 calloc(result.config.number_of_hosts, sizeof(check_icmp_target_container));
312 if (result.config.hosts == NULL) {
313 crash("failed to allocate memory");
314 }
315
288 /* Reset argument scanning */ 316 /* Reset argument scanning */
289 optind = 1; 317 optind = 1;
290 318
@@ -301,8 +329,8 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) {
301 long size = strtol(optarg, NULL, 0); 329 long size = strtol(optarg, NULL, 0);
302 if ((unsigned long)size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && 330 if ((unsigned long)size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) &&
303 size < MAX_PING_DATA) { 331 size < MAX_PING_DATA) {
304 result.config.icmp_data_size = size; 332 result.config.icmp_data_size = (unsigned short)size;
305 result.config.icmp_pkt_size = size + ICMP_MINLEN; 333 result.config.icmp_pkt_size = (unsigned short)(size + ICMP_MINLEN);
306 } else { 334 } else {
307 usage_va("ICMP data length must be between: %lu and %lu", 335 usage_va("ICMP data length must be between: %lu and %lu",
308 sizeof(struct icmp) + sizeof(struct icmp_ping_data), 336 sizeof(struct icmp) + sizeof(struct icmp_ping_data),
@@ -323,24 +351,26 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) {
323 break; 351 break;
324 case 'n': 352 case 'n':
325 case 'p': 353 case 'p':
326 result.config.packets = strtoul(optarg, NULL, 0); 354 result.config.packets = (unsigned short)strtoul(optarg, NULL, 0);
327 if (result.config.packets > 20) { 355 if (result.config.packets > 20) {
328 errno = 0; 356 errno = 0;
329 crash("packets is > 20 (%d)", result.config.packets); 357 crash("packets is > 20 (%d)", result.config.packets);
330 } 358 }
331 break; 359 break;
332 case 't': 360 case 't':
333 result.config.timeout = strtoul(optarg, NULL, 0); 361 timeout = (unsigned int)strtoul(optarg, NULL, 0);
334 // TODO die here and complain about wrong input 362 // TODO die here and complain about wrong input
335 // instead of:
336 if (!result.config.timeout) {
337 result.config.timeout = 10;
338 }
339 break; 363 break;
340 case 'H': { 364 case 'H': {
341 int add_result = add_target(optarg, result.config.mode); 365 add_target_wrapper add_result = add_target(optarg, result.config.mode);
342 if (add_result == 0) { 366 if (add_result.error_code == OK) {
343 result.config.number_of_targets++; 367 if (result.config.targets != NULL) {
368 result.config.number_of_targets +=
369 ping_target_list_append(result.config.targets, add_result.targets);
370 } else {
371 result.config.targets = add_result.targets;
372 result.config.number_of_targets += add_result.number_of_targets;
373 }
344 } 374 }
345 } break; 375 } break;
346 case 'l': 376 case 'l':
@@ -569,7 +599,7 @@ static const char *get_icmp_error_msg(unsigned char icmp_type, unsigned char icm
569 599
570static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr, 600static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr,
571 unsigned int *pkt_interval, unsigned int *target_interval, 601 unsigned int *pkt_interval, unsigned int *target_interval,
572 const pid_t pid, struct rta_host **table, unsigned short packets, 602 const pid_t pid, ping_target **table, unsigned short packets,
573 const unsigned short number_of_targets, 603 const unsigned short number_of_targets,
574 check_icmp_state *program_state) { 604 check_icmp_state *program_state) {
575 struct icmp p; 605 struct icmp p;
@@ -611,7 +641,7 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad
611 } 641 }
612 642
613 /* it is indeed a response for us */ 643 /* it is indeed a response for us */
614 struct rta_host *host = table[ntohs(sent_icmp.icmp_seq) / packets]; 644 ping_target *host = table[ntohs(sent_icmp.icmp_seq) / packets];
615 if (debug) { 645 if (debug) {
616 char address[INET6_ADDRSTRLEN]; 646 char address[INET6_ADDRSTRLEN];
617 parse_address(addr, address, sizeof(address)); 647 parse_address(addr, address, sizeof(address));
@@ -629,8 +659,8 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad
629 /* source quench means we're sending too fast, so increase the 659 /* source quench means we're sending too fast, so increase the
630 * interval and mark this packet lost */ 660 * interval and mark this packet lost */
631 if (p.icmp_type == ICMP_SOURCEQUENCH) { 661 if (p.icmp_type == ICMP_SOURCEQUENCH) {
632 *pkt_interval *= PACKET_BACKOFF_FACTOR; 662 *pkt_interval = (unsigned int)(*pkt_interval * PACKET_BACKOFF_FACTOR);
633 *target_interval *= TARGET_BACKOFF_FACTOR; 663 *target_interval = (unsigned int)(*target_interval * TARGET_BACKOFF_FACTOR);
634 } else { 664 } else {
635 program_state->targets_down++; 665 program_state->targets_down++;
636 host->flags |= FLAG_LOST_CAUSE; 666 host->flags |= FLAG_LOST_CAUSE;
@@ -642,7 +672,7 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad
642 return 0; 672 return 0;
643} 673}
644 674
645void parse_address(struct sockaddr_storage *addr, char *address, int size) { 675void parse_address(struct sockaddr_storage *addr, char *address, socklen_t size) {
646 switch (address_family) { 676 switch (address_family) {
647 case AF_INET: 677 case AF_INET:
648 inet_ntop(address_family, &((struct sockaddr_in *)addr)->sin_addr, address, size); 678 inet_ntop(address_family, &((struct sockaddr_in *)addr)->sin_addr, address, size);
@@ -722,32 +752,24 @@ int main(int argc, char **argv) {
722 } 752 }
723 } 753 }
724 754
725#ifdef HAVE_SIGACTION
726 struct sigaction sig_action; 755 struct sigaction sig_action;
727 sig_action.sa_sigaction = NULL; 756 sig_action.sa_handler = NULL;
728 sig_action.sa_handler = finish; 757 sig_action.sa_sigaction = check_icmp_timeout_handler;
729 sigfillset(&sig_action.sa_mask); 758 sigfillset(&sig_action.sa_mask);
730 sig_action.sa_flags = SA_NODEFER | SA_RESTART; 759 sig_action.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
731 760
732 sigaction(SIGINT, &sig_action, NULL); 761 sigaction(SIGINT, &sig_action, NULL);
733 sigaction(SIGHUP, &sig_action, NULL); 762 sigaction(SIGHUP, &sig_action, NULL);
734 sigaction(SIGTERM, &sig_action, NULL); 763 sigaction(SIGTERM, &sig_action, NULL);
735 sigaction(SIGALRM, &sig_action, NULL); 764 sigaction(SIGALRM, &sig_action, NULL);
736#else /* HAVE_SIGACTION */
737 // signal(SIGINT, finish);
738 // signal(SIGHUP, finish);
739 // signal(SIGTERM, finish);
740 // signal(SIGALRM, finish);
741#endif /* HAVE_SIGACTION */
742 if (debug) { 765 if (debug) {
743 printf("Setting alarm timeout to %u seconds\n", config.timeout); 766 printf("Setting alarm timeout to %u seconds\n", timeout);
744 } 767 }
745 alarm(config.timeout); 768 alarm(timeout);
746 769
747 /* make sure we don't wait any longer than necessary */ 770 /* make sure we don't wait any longer than necessary */
748 struct timezone time_zone_dummy;
749 struct timeval prog_start; 771 struct timeval prog_start;
750 gettimeofday(&prog_start, &time_zone_dummy); 772 gettimeofday(&prog_start, NULL);
751 773
752 unsigned int max_completion_time = 774 unsigned int max_completion_time =
753 ((config.number_of_targets * config.packets * config.pkt_interval) + 775 ((config.number_of_targets * config.packets * config.pkt_interval) +
@@ -765,8 +787,8 @@ int main(int argc, char **argv) {
765 } 787 }
766 788
767 if (debug) { 789 if (debug) {
768 if (max_completion_time > (unsigned int)config.timeout * 1000000) { 790 if (max_completion_time > (timeout * 1000000)) {
769 printf("max_completion_time: %u timeout: %u\n", max_completion_time, config.timeout); 791 printf("max_completion_time: %u timeout: %u\n", max_completion_time, timeout);
770 printf("Timeout must be at least %u\n", (max_completion_time / 1000000) + 1); 792 printf("Timeout must be at least %u\n", (max_completion_time / 1000000) + 1);
771 } 793 }
772 } 794 }
@@ -776,7 +798,7 @@ int main(int argc, char **argv) {
776 config.warn.rta, config.warn.pl); 798 config.warn.rta, config.warn.pl);
777 printf("pkt_interval: %u target_interval: %u\n", config.pkt_interval, 799 printf("pkt_interval: %u target_interval: %u\n", config.pkt_interval,
778 config.target_interval); 800 config.target_interval);
779 printf("icmp_pkt_size: %u timeout: %u\n", config.icmp_pkt_size, config.timeout); 801 printf("icmp_pkt_size: %u timeout: %u\n", config.icmp_pkt_size, timeout);
780 } 802 }
781 803
782 if (config.min_hosts_alive < -1) { 804 if (config.min_hosts_alive < -1) {
@@ -784,18 +806,18 @@ int main(int argc, char **argv) {
784 crash("minimum alive hosts is negative (%i)", config.min_hosts_alive); 806 crash("minimum alive hosts is negative (%i)", config.min_hosts_alive);
785 } 807 }
786 808
787 struct rta_host *host = host_list; 809 ping_target *host = config.targets;
788 struct rta_host **table = malloc(sizeof(struct rta_host *) * config.number_of_targets); 810 ping_target **table = malloc(sizeof(ping_target *) * config.number_of_targets);
789 if (!table) { 811 if (!table) {
790 crash("main(): malloc failed for host table"); 812 crash("main(): malloc failed for host table");
791 } 813 }
792 814
793 unsigned short i = 0; 815 unsigned short target_index = 0;
794 while (host) { 816 while (host) {
795 host->id = i * config.packets; 817 host->id = target_index * config.packets;
796 table[i] = host; 818 table[target_index] = host;
797 host = host->next; 819 host = host->next;
798 i++; 820 target_index++;
799 } 821 }
800 822
801 unsigned int pkt_interval = config.pkt_interval; 823 unsigned int pkt_interval = config.pkt_interval;
@@ -806,13 +828,13 @@ int main(int argc, char **argv) {
806 run_checks(config.order_mode, config.mos_mode, config.rta_mode, config.pl_mode, 828 run_checks(config.order_mode, config.mos_mode, config.rta_mode, config.pl_mode,
807 config.jitter_mode, config.score_mode, config.min_hosts_alive, config.icmp_data_size, 829 config.jitter_mode, config.score_mode, config.min_hosts_alive, config.icmp_data_size,
808 &pkt_interval, &target_interval, config.warn, config.crit, config.pid, config.mode, 830 &pkt_interval, &target_interval, config.warn, config.crit, config.pid, config.mode,
809 max_completion_time, &prog_start, table, config.packets, icmp_sock, 831 max_completion_time, prog_start, table, config.packets, icmp_sock,
810 config.number_of_targets, &program_state); 832 config.number_of_targets, &program_state, config.targets);
811 833
812 errno = 0; 834 errno = 0;
813 finish(0, config.order_mode, config.mos_mode, config.rta_mode, config.pl_mode, 835 finish(0, config.order_mode, config.mos_mode, config.rta_mode, config.pl_mode,
814 config.jitter_mode, config.score_mode, config.min_hosts_alive, config.warn, config.crit, 836 config.jitter_mode, config.score_mode, config.min_hosts_alive, config.warn, config.crit,
815 icmp_sock, config.number_of_targets, &program_state); 837 icmp_sock, config.number_of_targets, &program_state, config.targets);
816 838
817 return (0); 839 return (0);
818} 840}
@@ -822,9 +844,10 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo
822 unsigned short icmp_pkt_size, unsigned int *pkt_interval, 844 unsigned short icmp_pkt_size, unsigned int *pkt_interval,
823 unsigned int *target_interval, threshold warn, threshold crit, 845 unsigned int *target_interval, threshold warn, threshold crit,
824 const pid_t pid, const int mode, const unsigned int max_completion_time, 846 const pid_t pid, const int mode, const unsigned int max_completion_time,
825 const struct timeval *prog_start, struct rta_host **table, 847 const struct timeval prog_start, ping_target **table,
826 const unsigned short packets, const int icmp_sock, 848 const unsigned short packets, const int icmp_sock,
827 const unsigned short number_of_targets, check_icmp_state *program_state) { 849 const unsigned short number_of_targets, check_icmp_state *program_state,
850 ping_target *target_list) {
828 /* this loop might actually violate the pkt_interval or target_interval 851 /* this loop might actually violate the pkt_interval or target_interval
829 * settings, but only if there aren't any packets on the wire which 852 * settings, but only if there aren't any packets on the wire which
830 * indicates that the target can handle an increased packet rate */ 853 * indicates that the target can handle an increased packet rate */
@@ -833,7 +856,8 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo
833 /* don't send useless packets */ 856 /* don't send useless packets */
834 if (!targets_alive(number_of_targets, program_state->targets_down)) { 857 if (!targets_alive(number_of_targets, program_state->targets_down)) {
835 finish(0, order_mode, mos_mode, rta_mode, pl_mode, jitter_mode, score_mode, 858 finish(0, order_mode, mos_mode, rta_mode, pl_mode, jitter_mode, score_mode,
836 min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state); 859 min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state,
860 target_list);
837 } 861 }
838 if (table[target_index]->flags & FLAG_LOST_CAUSE) { 862 if (table[target_index]->flags & FLAG_LOST_CAUSE) {
839 if (debug) { 863 if (debug) {
@@ -845,25 +869,32 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo
845 /* we're still in the game, so send next packet */ 869 /* we're still in the game, so send next packet */
846 (void)send_icmp_ping(icmp_sock, table[target_index], icmp_pkt_size, pid, program_state); 870 (void)send_icmp_ping(icmp_sock, table[target_index], icmp_pkt_size, pid, program_state);
847 871
848 wait_for_reply(icmp_sock, *target_interval, order_mode, mos_mode, rta_mode, pl_mode, 872 /* wrap up if all targets are declared dead */
849 jitter_mode, score_mode, min_hosts_alive, icmp_pkt_size, pkt_interval, 873 if (targets_alive(number_of_targets, program_state->targets_down) ||
850 target_interval, warn, crit, pid, mode, max_completion_time, prog_start, 874 get_timevaldiff(prog_start, prog_start) < max_completion_time ||
851 table, packets, icmp_sock, number_of_targets, program_state); 875 !(mode == MODE_HOSTCHECK && program_state->targets_down)) {
876 wait_for_reply(icmp_sock, *target_interval, icmp_pkt_size, pkt_interval,
877 target_interval, pid, table, packets, number_of_targets,
878 program_state);
879 }
880 }
881 if (targets_alive(number_of_targets, program_state->targets_down) ||
882 get_timevaldiff_to_now(prog_start) < max_completion_time ||
883 !(mode == MODE_HOSTCHECK && program_state->targets_down)) {
884 wait_for_reply(icmp_sock, *pkt_interval * number_of_targets, icmp_pkt_size,
885 pkt_interval, target_interval, pid, table, packets, number_of_targets,
886 program_state);
852 } 887 }
853 wait_for_reply(icmp_sock, *pkt_interval * number_of_targets, order_mode, mos_mode, rta_mode,
854 pl_mode, jitter_mode, score_mode, min_hosts_alive, icmp_pkt_size,
855 pkt_interval, target_interval, warn, crit, pid, mode, max_completion_time,
856 prog_start, table, packets, icmp_sock, number_of_targets, program_state);
857 } 888 }
858 889
859 if (icmp_pkts_en_route(program_state->icmp_sent, program_state->icmp_recv, 890 if (icmp_pkts_en_route(program_state->icmp_sent, program_state->icmp_recv,
860 program_state->icmp_lost) && 891 program_state->icmp_lost) &&
861 targets_alive(number_of_targets, program_state->targets_down)) { 892 targets_alive(number_of_targets, program_state->targets_down)) {
862 unsigned int time_passed = get_timevaldiff(NULL, NULL, prog_start); 893 time_t time_passed = get_timevaldiff_to_now(prog_start);
863 unsigned int final_wait = max_completion_time - time_passed; 894 time_t final_wait = max_completion_time - time_passed;
864 895
865 if (debug) { 896 if (debug) {
866 printf("time_passed: %u final_wait: %u max_completion_time: %u\n", time_passed, 897 printf("time_passed: %ld final_wait: %ld max_completion_time: %u\n", time_passed,
867 final_wait, max_completion_time); 898 final_wait, max_completion_time);
868 } 899 }
869 if (time_passed > max_completion_time) { 900 if (time_passed > max_completion_time) {
@@ -871,19 +902,22 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo
871 printf("Time passed. Finishing up\n"); 902 printf("Time passed. Finishing up\n");
872 } 903 }
873 finish(0, order_mode, mos_mode, rta_mode, pl_mode, jitter_mode, score_mode, 904 finish(0, order_mode, mos_mode, rta_mode, pl_mode, jitter_mode, score_mode,
874 min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state); 905 min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state,
906 target_list);
875 } 907 }
876 908
877 /* catch the packets that might come in within the timeframe, but 909 /* catch the packets that might come in within the timeframe, but
878 * haven't yet */ 910 * haven't yet */
879 if (debug) { 911 if (debug) {
880 printf("Waiting for %u micro-seconds (%0.3f msecs)\n", final_wait, 912 printf("Waiting for %ld micro-seconds (%0.3f msecs)\n", final_wait,
881 (float)final_wait / 1000); 913 (float)final_wait / 1000);
882 } 914 }
883 wait_for_reply(icmp_sock, final_wait, order_mode, mos_mode, rta_mode, pl_mode, jitter_mode, 915 if (targets_alive(number_of_targets, program_state->targets_down) ||
884 score_mode, min_hosts_alive, icmp_pkt_size, pkt_interval, target_interval, 916 get_timevaldiff_to_now(prog_start) < max_completion_time ||
885 warn, crit, pid, mode, max_completion_time, prog_start, table, packets, 917 !(mode == MODE_HOSTCHECK && program_state->targets_down)) {
886 icmp_sock, number_of_targets, program_state); 918 wait_for_reply(icmp_sock, final_wait, icmp_pkt_size, pkt_interval, target_interval, pid,
919 table, packets, number_of_targets, program_state);
920 }
887 } 921 }
888} 922}
889 923
@@ -897,15 +931,10 @@ static void run_checks(bool order_mode, bool mos_mode, bool rta_mode, bool pl_mo
897 * both: 931 * both:
898 * icmp echo reply : the rest 932 * icmp echo reply : the rest
899 */ 933 */
900static int wait_for_reply(int sock, const unsigned int time_interval, bool order_mode, 934static int wait_for_reply(int sock, const time_t time_interval, unsigned short icmp_pkt_size,
901 bool mos_mode, bool rta_mode, bool pl_mode, bool jitter_mode, 935 unsigned int *pkt_interval, unsigned int *target_interval, pid_t pid,
902 bool score_mode, int min_hosts_alive, unsigned short icmp_pkt_size, 936 ping_target **table, const unsigned short packets,
903 unsigned int *pkt_interval, unsigned int *target_interval, threshold warn, 937 const unsigned short number_of_targets, check_icmp_state *program_state) {
904 threshold crit, const pid_t pid, const int mode,
905 const unsigned long long max_completion_time, struct timeval *prog_start,
906 struct rta_host **table, const unsigned short packets,
907 const int icmp_sock, const unsigned short number_of_targets,
908 check_icmp_state *program_state) {
909 union icmp_packet packet; 938 union icmp_packet packet;
910 if (!(packet.buf = malloc(icmp_pkt_size))) { 939 if (!(packet.buf = malloc(icmp_pkt_size))) {
911 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size); 940 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size);
@@ -921,56 +950,50 @@ static int wait_for_reply(int sock, const unsigned int time_interval, bool order
921 return 0; 950 return 0;
922 } 951 }
923 952
953 // Get current time stamp
924 struct timeval wait_start; 954 struct timeval wait_start;
925 struct timezone time_zone_dummy; 955 gettimeofday(&wait_start, NULL);
926 gettimeofday(&wait_start, &time_zone_dummy);
927 956
928 struct sockaddr_storage resp_addr; 957 struct sockaddr_storage resp_addr;
929 unsigned int per_pkt_wait = 958 time_t per_pkt_wait =
930 time_interval / icmp_pkts_en_route(program_state->icmp_sent, program_state->icmp_recv, 959 time_interval / icmp_pkts_en_route(program_state->icmp_sent, program_state->icmp_recv,
931 program_state->icmp_lost); 960 program_state->icmp_lost);
932 static unsigned char buf[65536]; 961 static unsigned char buf[65536];
933 union ip_hdr *ip; 962 union ip_hdr *ip_header;
934 struct timeval now; 963 struct timeval packet_received_timestamp;
935 while (icmp_pkts_en_route(program_state->icmp_sent, program_state->icmp_recv, 964 while (icmp_pkts_en_route(program_state->icmp_sent, program_state->icmp_recv,
936 program_state->icmp_lost) && 965 program_state->icmp_lost) &&
937 get_timevaldiff(&wait_start, NULL, prog_start) < time_interval) { 966 get_timevaldiff_to_now(wait_start) < time_interval) {
938 unsigned int loop_time_interval = per_pkt_wait; 967 time_t loop_time_interval = per_pkt_wait;
939
940 /* wrap up if all targets are declared dead */
941 if (!targets_alive(number_of_targets, program_state->targets_down) ||
942 get_timevaldiff(prog_start, NULL, prog_start) >= max_completion_time ||
943 (mode == MODE_HOSTCHECK && program_state->targets_down)) {
944 finish(0, order_mode, mos_mode, rta_mode, pl_mode, jitter_mode, score_mode,
945 min_hosts_alive, warn, crit, icmp_sock, number_of_targets, program_state);
946 }
947 968
948 /* reap responses until we hit a timeout */ 969 /* reap responses until we hit a timeout */
949 int n = recvfrom_wto(sock, buf, sizeof(buf), (struct sockaddr *)&resp_addr, 970 ssize_t n = recvfrom_wto(sock, buf, sizeof(buf), (struct sockaddr *)&resp_addr,
950 &loop_time_interval, &now, prog_start); 971 &loop_time_interval, &packet_received_timestamp);
951 if (!n) { 972 if (!n) {
952 if (debug > 1) { 973 if (debug > 1) {
953 printf("recvfrom_wto() timed out during a %u usecs wait\n", per_pkt_wait); 974 printf("recvfrom_wto() timed out during a %ld usecs wait\n", per_pkt_wait);
954 } 975 }
955 continue; /* timeout for this one, so keep trying */ 976 continue; /* timeout for this one, so keep trying */
956 } 977 }
978
957 if (n < 0) { 979 if (n < 0) {
958 if (debug) { 980 if (debug) {
959 printf("recvfrom_wto() returned errors\n"); 981 printf("recvfrom_wto() returned errors\n");
960 } 982 }
961 free(packet.buf); 983 free(packet.buf);
962 return n; 984 return (int)n;
963 } 985 }
964 986
965 // FIXME: with ipv6 we don't have an ip header here 987 // FIXME: with ipv6 we don't have an ip header here
966 if (address_family != AF_INET6) { 988 if (address_family != AF_INET6) {
967 ip = (union ip_hdr *)buf; 989 ip_header = (union ip_hdr *)buf;
968 990
969 if (debug > 1) { 991 if (debug > 1) {
970 char address[INET6_ADDRSTRLEN]; 992 char address[INET6_ADDRSTRLEN];
971 parse_address(&resp_addr, address, sizeof(address)); 993 parse_address(&resp_addr, address, sizeof(address));
972 printf("received %u bytes from %s\n", 994 printf("received %u bytes from %s\n",
973 address_family == AF_INET6 ? ntohs(ip->ip6.ip6_plen) : ntohs(ip->ip.ip_len), 995 address_family == AF_INET6 ? ntohs(ip_header->ip6.ip6_plen)
996 : ntohs(ip_header->ip.ip_len),
974 address); 997 address);
975 } 998 }
976 } 999 }
@@ -982,7 +1005,7 @@ static int wait_for_reply(int sock, const unsigned int time_interval, bool order
982 * off the bottom 4 bits */ 1005 * off the bottom 4 bits */
983 /* hlen = (ip->ip_vhl & 0x0f) << 2; */ 1006 /* hlen = (ip->ip_vhl & 0x0f) << 2; */
984 /* #else */ 1007 /* #else */
985 int hlen = (address_family == AF_INET6) ? 0 : ip->ip.ip_hl << 2; 1008 int hlen = (address_family == AF_INET6) ? 0 : ip_header->ip.ip_hl << 2;
986 /* #endif */ 1009 /* #endif */
987 1010
988 if (n < (hlen + ICMP_MINLEN)) { 1011 if (n < (hlen + ICMP_MINLEN)) {
@@ -1020,7 +1043,7 @@ static int wait_for_reply(int sock, const unsigned int time_interval, bool order
1020 } 1043 }
1021 1044
1022 /* this is indeed a valid response */ 1045 /* this is indeed a valid response */
1023 struct rta_host *host; 1046 ping_target *target;
1024 struct icmp_ping_data data; 1047 struct icmp_ping_data data;
1025 if (address_family == PF_INET) { 1048 if (address_family == PF_INET) {
1026 memcpy(&data, packet.icp->icmp_data, sizeof(data)); 1049 memcpy(&data, packet.icp->icmp_data, sizeof(data));
@@ -1029,7 +1052,7 @@ static int wait_for_reply(int sock, const unsigned int time_interval, bool order
1029 ntohs(packet.icp->icmp_id), ntohs(packet.icp->icmp_seq), 1052 ntohs(packet.icp->icmp_id), ntohs(packet.icp->icmp_seq),
1030 packet.icp->icmp_cksum); 1053 packet.icp->icmp_cksum);
1031 } 1054 }
1032 host = table[ntohs(packet.icp->icmp_seq) / packets]; 1055 target = table[ntohs(packet.icp->icmp_seq) / packets];
1033 } else { 1056 } else {
1034 memcpy(&data, &packet.icp6->icmp6_dataun.icmp6_un_data8[4], sizeof(data)); 1057 memcpy(&data, &packet.icp6->icmp6_dataun.icmp6_un_data8[4], sizeof(data));
1035 if (debug > 2) { 1058 if (debug > 2) {
@@ -1037,55 +1060,55 @@ static int wait_for_reply(int sock, const unsigned int time_interval, bool order
1037 ntohs(packet.icp6->icmp6_id), ntohs(packet.icp6->icmp6_seq), 1060 ntohs(packet.icp6->icmp6_id), ntohs(packet.icp6->icmp6_seq),
1038 packet.icp6->icmp6_cksum); 1061 packet.icp6->icmp6_cksum);
1039 } 1062 }
1040 host = table[ntohs(packet.icp6->icmp6_seq) / packets]; 1063 target = table[ntohs(packet.icp6->icmp6_seq) / packets];
1041 } 1064 }
1042 1065
1043 unsigned int tdiff = get_timevaldiff(&data.stime, &now, prog_start); 1066 time_t tdiff = get_timevaldiff(data.stime, packet_received_timestamp);
1044 1067
1045 if (host->last_tdiff > 0) { 1068 if (target->last_tdiff > 0) {
1046 /* Calculate jitter */ 1069 /* Calculate jitter */
1047 double jitter_tmp; 1070 double jitter_tmp;
1048 if (host->last_tdiff > tdiff) { 1071 if (target->last_tdiff > tdiff) {
1049 jitter_tmp = host->last_tdiff - tdiff; 1072 jitter_tmp = (double)(target->last_tdiff - tdiff);
1050 } else { 1073 } else {
1051 jitter_tmp = tdiff - host->last_tdiff; 1074 jitter_tmp = (double)(tdiff - target->last_tdiff);
1052 } 1075 }
1053 1076
1054 if (host->jitter == 0) { 1077 if (target->jitter == 0) {
1055 host->jitter = jitter_tmp; 1078 target->jitter = jitter_tmp;
1056 host->jitter_max = jitter_tmp; 1079 target->jitter_max = jitter_tmp;
1057 host->jitter_min = jitter_tmp; 1080 target->jitter_min = jitter_tmp;
1058 } else { 1081 } else {
1059 host->jitter += jitter_tmp; 1082 target->jitter += jitter_tmp;
1060 1083
1061 if (jitter_tmp < host->jitter_min) { 1084 if (jitter_tmp < target->jitter_min) {
1062 host->jitter_min = jitter_tmp; 1085 target->jitter_min = jitter_tmp;
1063 } 1086 }
1064 1087
1065 if (jitter_tmp > host->jitter_max) { 1088 if (jitter_tmp > target->jitter_max) {
1066 host->jitter_max = jitter_tmp; 1089 target->jitter_max = jitter_tmp;
1067 } 1090 }
1068 } 1091 }
1069 1092
1070 /* Check if packets in order */ 1093 /* Check if packets in order */
1071 if (host->last_icmp_seq >= packet.icp->icmp_seq) { 1094 if (target->last_icmp_seq >= packet.icp->icmp_seq) {
1072 host->order_status = STATE_CRITICAL; 1095 target->order_status = STATE_CRITICAL;
1073 } 1096 }
1074 } 1097 }
1075 host->last_tdiff = tdiff; 1098 target->last_tdiff = tdiff;
1076 1099
1077 host->last_icmp_seq = packet.icp->icmp_seq; 1100 target->last_icmp_seq = packet.icp->icmp_seq;
1078 1101
1079 host->time_waited += tdiff; 1102 target->time_waited += tdiff;
1080 host->icmp_recv++; 1103 target->icmp_recv++;
1081 program_state->icmp_recv++; 1104 program_state->icmp_recv++;
1082 1105
1083 if (tdiff > (unsigned int)host->rtmax) { 1106 if (tdiff > (unsigned int)target->rtmax) {
1084 host->rtmax = tdiff; 1107 target->rtmax = (double)tdiff;
1085 } 1108 }
1086 1109
1087 if ((host->rtmin == INFINITY) || (tdiff < (unsigned int)host->rtmin)) { 1110 if ((target->rtmin == INFINITY) || (tdiff < (unsigned int)target->rtmin)) {
1088 host->rtmin = tdiff; 1111 target->rtmin = (double)tdiff;
1089 } 1112 }
1090 1113
1091 if (debug) { 1114 if (debug) {
@@ -1095,26 +1118,16 @@ static int wait_for_reply(int sock, const unsigned int time_interval, bool order
1095 switch (address_family) { 1118 switch (address_family) {
1096 case AF_INET: { 1119 case AF_INET: {
1097 printf("%0.3f ms rtt from %s, incoming ttl: %u, max: %0.3f, min: %0.3f\n", 1120 printf("%0.3f ms rtt from %s, incoming ttl: %u, max: %0.3f, min: %0.3f\n",
1098 (float)tdiff / 1000, address, ip->ip.ip_ttl, (float)host->rtmax / 1000, 1121 (float)tdiff / 1000, address, ip_header->ip.ip_ttl,
1099 (float)host->rtmin / 1000); 1122 (float)target->rtmax / 1000, (float)target->rtmin / 1000);
1100 break; 1123 break;
1101 }; 1124 };
1102 case AF_INET6: { 1125 case AF_INET6: {
1103 printf("%0.3f ms rtt from %s, max: %0.3f, min: %0.3f\n", (float)tdiff / 1000, 1126 printf("%0.3f ms rtt from %s, max: %0.3f, min: %0.3f\n", (float)tdiff / 1000,
1104 address, (float)host->rtmax / 1000, (float)host->rtmin / 1000); 1127 address, (float)target->rtmax / 1000, (float)target->rtmin / 1000);
1105 }; 1128 };
1106 } 1129 }
1107 } 1130 }
1108
1109 /* if we're in hostcheck mode, exit with limited printouts */
1110 if (mode == MODE_HOSTCHECK) {
1111 printf("OK - %s responds to ICMP. Packet %u, rta %0.3fms|"
1112 "pkt=%u;;;0;%u rta=%0.3f;%0.3f;%0.3f;;\n",
1113 host->name, program_state->icmp_recv, (float)tdiff / 1000,
1114 program_state->icmp_recv, packets, (float)tdiff / 1000, (float)warn.rta / 1000,
1115 (float)crit.rta / 1000);
1116 exit(STATE_OK);
1117 }
1118 } 1131 }
1119 1132
1120 free(packet.buf); 1133 free(packet.buf);
@@ -1122,7 +1135,7 @@ static int wait_for_reply(int sock, const unsigned int time_interval, bool order
1122} 1135}
1123 1136
1124/* the ping functions */ 1137/* the ping functions */
1125static int send_icmp_ping(const int sock, struct rta_host *host, const unsigned short icmp_pkt_size, 1138static int send_icmp_ping(const int sock, ping_target *host, const unsigned short icmp_pkt_size,
1126 const pid_t pid, check_icmp_state *program_state) { 1139 const pid_t pid, check_icmp_state *program_state) {
1127 if (sock == -1) { 1140 if (sock == -1) {
1128 errno = 0; 1141 errno = 0;
@@ -1140,18 +1153,17 @@ static int send_icmp_ping(const int sock, struct rta_host *host, const unsigned
1140 } 1153 }
1141 memset(buf, 0, icmp_pkt_size); 1154 memset(buf, 0, icmp_pkt_size);
1142 1155
1143 struct timeval tv; 1156 struct timeval current_time;
1144 struct timezone tz; 1157 if ((gettimeofday(&current_time, NULL)) == -1) {
1145 if ((gettimeofday(&tv, &tz)) == -1) {
1146 free(buf); 1158 free(buf);
1147 return -1; 1159 return -1;
1148 } 1160 }
1149 1161
1150 struct icmp_ping_data data; 1162 struct icmp_ping_data data;
1151 data.ping_id = 10; /* host->icmp.icmp_sent; */ 1163 data.ping_id = 10; /* host->icmp.icmp_sent; */
1152 memcpy(&data.stime, &tv, sizeof(tv)); 1164 memcpy(&data.stime, &current_time, sizeof(current_time));
1153 1165
1154 size_t addrlen; 1166 socklen_t addrlen;
1155 1167
1156 if (address_family == AF_INET) { 1168 if (address_family == AF_INET) {
1157 struct icmp *icp = (struct icmp *)buf; 1169 struct icmp *icp = (struct icmp *)buf;
@@ -1162,7 +1174,7 @@ static int send_icmp_ping(const int sock, struct rta_host *host, const unsigned
1162 icp->icmp_type = ICMP_ECHO; 1174 icp->icmp_type = ICMP_ECHO;
1163 icp->icmp_code = 0; 1175 icp->icmp_code = 0;
1164 icp->icmp_cksum = 0; 1176 icp->icmp_cksum = 0;
1165 icp->icmp_id = htons(pid); 1177 icp->icmp_id = htons((uint16_t)pid);
1166 icp->icmp_seq = htons(host->id++); 1178 icp->icmp_seq = htons(host->id++);
1167 icp->icmp_cksum = icmp_checksum((uint16_t *)buf, (size_t)icmp_pkt_size); 1179 icp->icmp_cksum = icmp_checksum((uint16_t *)buf, (size_t)icmp_pkt_size);
1168 1180
@@ -1180,7 +1192,7 @@ static int send_icmp_ping(const int sock, struct rta_host *host, const unsigned
1180 icp6->icmp6_type = ICMP6_ECHO_REQUEST; 1192 icp6->icmp6_type = ICMP6_ECHO_REQUEST;
1181 icp6->icmp6_code = 0; 1193 icp6->icmp6_code = 0;
1182 icp6->icmp6_cksum = 0; 1194 icp6->icmp6_cksum = 0;
1183 icp6->icmp6_id = htons(pid); 1195 icp6->icmp6_id = htons((uint16_t)pid);
1184 icp6->icmp6_seq = htons(host->id++); 1196 icp6->icmp6_seq = htons(host->id++);
1185 // let checksum be calculated automatically 1197 // let checksum be calculated automatically
1186 1198
@@ -1231,8 +1243,9 @@ static int send_icmp_ping(const int sock, struct rta_host *host, const unsigned
1231 return 0; 1243 return 0;
1232} 1244}
1233 1245
1234static int recvfrom_wto(const int sock, void *buf, const unsigned int len, struct sockaddr *saddr, 1246static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len,
1235 unsigned int *timeout, struct timeval *tv, struct timeval *prog_start) { 1247 struct sockaddr *saddr, time_t *timeout,
1248 struct timeval *received_timestamp) {
1236#ifdef HAVE_MSGHDR_MSG_CONTROL 1249#ifdef HAVE_MSGHDR_MSG_CONTROL
1237 char ans_data[4096]; 1250 char ans_data[4096];
1238#endif // HAVE_MSGHDR_MSG_CONTROL 1251#endif // HAVE_MSGHDR_MSG_CONTROL
@@ -1247,31 +1260,33 @@ static int recvfrom_wto(const int sock, void *buf, const unsigned int len, struc
1247 return 0; 1260 return 0;
1248 } 1261 }
1249 1262
1250 struct timeval to; 1263 struct timeval real_timeout;
1251 to.tv_sec = *timeout / 1000000; 1264 real_timeout.tv_sec = *timeout / 1000000;
1252 to.tv_usec = (*timeout - (to.tv_sec * 1000000)); 1265 real_timeout.tv_usec = (*timeout - (real_timeout.tv_sec * 1000000));
1253 1266
1254 fd_set rd; 1267 // Dummy fds for select
1255 fd_set wr; 1268 fd_set dummy_write_fds;
1256 FD_ZERO(&rd); 1269 FD_ZERO(&dummy_write_fds);
1257 FD_ZERO(&wr); 1270
1258 FD_SET(sock, &rd); 1271 // Read fds for select with the socket
1259 errno = 0; 1272 fd_set read_fds;
1273 FD_ZERO(&read_fds);
1274 FD_SET(sock, &read_fds);
1260 1275
1261 struct timeval then; 1276 struct timeval then;
1262 struct timezone time_zone_dummy; 1277 gettimeofday(&then, NULL);
1263 gettimeofday(&then, &time_zone_dummy);
1264 1278
1265 int n = select(sock + 1, &rd, &wr, NULL, &to); 1279 errno = 0;
1266 if (n < 0) { 1280 int select_return = select(sock + 1, &read_fds, &dummy_write_fds, NULL, &real_timeout);
1281 if (select_return < 0) {
1267 crash("select() in recvfrom_wto"); 1282 crash("select() in recvfrom_wto");
1268 } 1283 }
1269 1284
1270 struct timeval now; 1285 struct timeval now;
1271 gettimeofday(&now, &time_zone_dummy); 1286 gettimeofday(&now, NULL);
1272 *timeout = get_timevaldiff(&then, &now, prog_start); 1287 *timeout = get_timevaldiff(then, now);
1273 1288
1274 if (!n) { 1289 if (!select_return) {
1275 return 0; /* timeout */ 1290 return 0; /* timeout */
1276 } 1291 }
1277 1292
@@ -1299,16 +1314,16 @@ static int recvfrom_wto(const int sock, void *buf, const unsigned int len, struc
1299 for (chdr = CMSG_FIRSTHDR(&hdr); chdr; chdr = CMSG_NXTHDR(&hdr, chdr)) { 1314 for (chdr = CMSG_FIRSTHDR(&hdr); chdr; chdr = CMSG_NXTHDR(&hdr, chdr)) {
1300 if (chdr->cmsg_level == SOL_SOCKET && chdr->cmsg_type == SO_TIMESTAMP && 1315 if (chdr->cmsg_level == SOL_SOCKET && chdr->cmsg_type == SO_TIMESTAMP &&
1301 chdr->cmsg_len >= CMSG_LEN(sizeof(struct timeval))) { 1316 chdr->cmsg_len >= CMSG_LEN(sizeof(struct timeval))) {
1302 memcpy(tv, CMSG_DATA(chdr), sizeof(*tv)); 1317 memcpy(received_timestamp, CMSG_DATA(chdr), sizeof(*received_timestamp));
1303 break; 1318 break;
1304 } 1319 }
1305 } 1320 }
1306 1321
1307 if (!chdr) { 1322 if (!chdr) {
1308 gettimeofday(tv, &time_zone_dummy); 1323 gettimeofday(received_timestamp, NULL);
1309 } 1324 }
1310#else 1325#else
1311 gettimeofday(tv, &time_zone_dummy); 1326 gettimeofday(tv, NULL);
1312#endif // SO_TIMESTAMP 1327#endif // SO_TIMESTAMP
1313 1328
1314 return (ret); 1329 return (ret);
@@ -1317,7 +1332,7 @@ static int recvfrom_wto(const int sock, void *buf, const unsigned int len, struc
1317static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode, 1332static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool pl_mode,
1318 bool jitter_mode, bool score_mode, int min_hosts_alive, threshold warn, 1333 bool jitter_mode, bool score_mode, int min_hosts_alive, threshold warn,
1319 threshold crit, const int icmp_sock, const unsigned short number_of_targets, 1334 threshold crit, const int icmp_sock, const unsigned short number_of_targets,
1320 check_icmp_state *program_state) { 1335 check_icmp_state *program_state, ping_target *target_list) {
1321 // Deactivate alarm 1336 // Deactivate alarm
1322 alarm(0); 1337 alarm(0);
1323 1338
@@ -1338,7 +1353,7 @@ static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool
1338 1353
1339 /* iterate thrice to calculate values, give output, and print perfparse */ 1354 /* iterate thrice to calculate values, give output, and print perfparse */
1340 mp_state_enum status = STATE_OK; 1355 mp_state_enum status = STATE_OK;
1341 struct rta_host *host = host_list; 1356 ping_target *host = target_list;
1342 1357
1343 unsigned int target_counter = 0; 1358 unsigned int target_counter = 0;
1344 const char *status_string[] = {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"}; 1359 const char *status_string[] = {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"};
@@ -1361,7 +1376,8 @@ static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool
1361 program_state->targets_down++; 1376 program_state->targets_down++;
1362 } 1377 }
1363 } else { 1378 } else {
1364 packet_loss = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent; 1379 packet_loss =
1380 (unsigned char)((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent;
1365 rta = (double)host->time_waited / host->icmp_recv; 1381 rta = (double)host->time_waited / host->icmp_recv;
1366 } 1382 }
1367 1383
@@ -1507,7 +1523,7 @@ static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool
1507 } 1523 }
1508 printf("%s - ", status_string[status]); 1524 printf("%s - ", status_string[status]);
1509 1525
1510 host = host_list; 1526 host = target_list;
1511 while (host) { 1527 while (host) {
1512 if (debug) { 1528 if (debug) {
1513 puts(""); 1529 puts("");
@@ -1611,8 +1627,9 @@ static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool
1611 if (!(!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && order_mode)) { 1627 if (!(!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && order_mode)) {
1612 printf("|"); 1628 printf("|");
1613 } 1629 }
1630
1614 target_counter = 0; 1631 target_counter = 0;
1615 host = host_list; 1632 host = target_list;
1616 while (host) { 1633 while (host) {
1617 if (debug) { 1634 if (debug) {
1618 puts(""); 1635 puts("");
@@ -1696,32 +1713,27 @@ static void finish(int sig, bool order_mode, bool mos_mode, bool rta_mode, bool
1696 exit(status); 1713 exit(status);
1697} 1714}
1698 1715
1699static time_t get_timevaldiff(struct timeval *earlier, struct timeval *later, 1716static time_t get_timevaldiff(const struct timeval earlier, const struct timeval later) {
1700 struct timeval *prog_start) {
1701 struct timeval now;
1702
1703 if (!later) {
1704 struct timezone time_zone_dummy;
1705 gettimeofday(&now, &time_zone_dummy);
1706 later = &now;
1707 }
1708 if (!earlier) {
1709 earlier = prog_start;
1710 }
1711
1712 /* if early > later we return 0 so as to indicate a timeout */ 1717 /* if early > later we return 0 so as to indicate a timeout */
1713 if (earlier->tv_sec > later->tv_sec || 1718 if (earlier.tv_sec > later.tv_sec ||
1714 (earlier->tv_sec == later->tv_sec && earlier->tv_usec > later->tv_usec)) { 1719 (earlier.tv_sec == later.tv_sec && earlier.tv_usec > later.tv_usec)) {
1715 return 0; 1720 return 0;
1716 } 1721 }
1717 1722
1718 time_t ret = (later->tv_sec - earlier->tv_sec) * 1000000; 1723 time_t ret = (later.tv_sec - earlier.tv_sec) * 1000000;
1719 ret += later->tv_usec - earlier->tv_usec; 1724 ret += later.tv_usec - earlier.tv_usec;
1720 1725
1721 return ret; 1726 return ret;
1722} 1727}
1723 1728
1724static int add_target_ip(char *arg, struct sockaddr_storage *address) { 1729static time_t get_timevaldiff_to_now(struct timeval earlier) {
1730 struct timeval now;
1731 gettimeofday(&now, NULL);
1732
1733 return get_timevaldiff(earlier, now);
1734}
1735
1736static add_target_ip_wrapper add_target_ip(char *arg, struct sockaddr_storage *address) {
1725 struct sockaddr_in *sin; 1737 struct sockaddr_in *sin;
1726 struct sockaddr_in6 *sin6; 1738 struct sockaddr_in6 *sin6;
1727 if (address_family == AF_INET) { 1739 if (address_family == AF_INET) {
@@ -1730,110 +1742,127 @@ static int add_target_ip(char *arg, struct sockaddr_storage *address) {
1730 sin6 = (struct sockaddr_in6 *)address; 1742 sin6 = (struct sockaddr_in6 *)address;
1731 } 1743 }
1732 1744
1745 add_target_ip_wrapper result = {
1746 .error_code = OK,
1747 .target = NULL,
1748 };
1749
1733 /* disregard obviously stupid addresses 1750 /* disregard obviously stupid addresses
1734 * (I didn't find an ipv6 equivalent to INADDR_NONE) */ 1751 * (I didn't find an ipv6 equivalent to INADDR_NONE) */
1735 if (((address_family == AF_INET && 1752 if (((address_family == AF_INET &&
1736 (sin->sin_addr.s_addr == INADDR_NONE || sin->sin_addr.s_addr == INADDR_ANY))) || 1753 (sin->sin_addr.s_addr == INADDR_NONE || sin->sin_addr.s_addr == INADDR_ANY))) ||
1737 (address_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) { 1754 (address_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) {
1738 return -1; 1755 result.error_code = ERROR;
1756 return result;
1739 } 1757 }
1740 1758
1759 // TODO: allow duplicate targets for now, might be on purpose
1741 /* no point in adding two identical IP's, so don't. ;) */ 1760 /* no point in adding two identical IP's, so don't. ;) */
1742 struct sockaddr_in *host_sin; 1761 // struct sockaddr_in *host_sin;
1743 struct sockaddr_in6 *host_sin6; 1762 // struct sockaddr_in6 *host_sin6;
1744 struct rta_host *host = host_list; 1763 // ping_target *host = host_list;
1745 while (host) { 1764 // while (host) {
1746 host_sin = (struct sockaddr_in *)&host->saddr_in; 1765 // host_sin = (struct sockaddr_in *)&host->saddr_in;
1747 host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; 1766 // host_sin6 = (struct sockaddr_in6 *)&host->saddr_in;
1748 1767
1749 if ((address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr) || 1768 // if ((address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr) ||
1750 (address_family == AF_INET6 && 1769 // (address_family == AF_INET6 &&
1751 host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) { 1770 // host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) {
1752 if (debug) { 1771 // if (debug) {
1753 printf("Identical IP already exists. Not adding %s\n", arg); 1772 // printf("Identical IP already exists. Not adding %s\n", arg);
1754 } 1773 // }
1755 return -1; 1774 // return -1;
1756 } 1775 // }
1757 host = host->next; 1776 // host = host->next;
1758 } 1777 // }
1759 1778
1760 /* add the fresh ip */ 1779 /* add the fresh ip */
1761 host = (struct rta_host *)malloc(sizeof(struct rta_host)); 1780 ping_target *target = (ping_target *)malloc(sizeof(ping_target));
1762 if (!host) { 1781 if (!target) {
1763 char straddr[INET6_ADDRSTRLEN]; 1782 char straddr[INET6_ADDRSTRLEN];
1764 parse_address((struct sockaddr_storage *)&address, straddr, sizeof(straddr)); 1783 parse_address((struct sockaddr_storage *)&address, straddr, sizeof(straddr));
1765 crash("add_target_ip(%s, %s): malloc(%lu) failed", arg, straddr, sizeof(struct rta_host)); 1784 crash("add_target_ip(%s, %s): malloc(%lu) failed", arg, straddr, sizeof(ping_target));
1766 } 1785 }
1767 1786
1768 *host = ping_target_init(); 1787 *target = ping_target_init();
1769 1788
1770 /* set the values. use calling name for output */ 1789 /* set the values. use calling name for output */
1771 host->name = strdup(arg); 1790 target->name = strdup(arg);
1772 1791
1773 /* fill out the sockaddr_storage struct */ 1792 /* fill out the sockaddr_storage struct */
1793 struct sockaddr_in *host_sin;
1794 struct sockaddr_in6 *host_sin6;
1774 if (address_family == AF_INET) { 1795 if (address_family == AF_INET) {
1775 host_sin = (struct sockaddr_in *)&host->saddr_in; 1796 host_sin = (struct sockaddr_in *)&target->saddr_in;
1776 host_sin->sin_family = AF_INET; 1797 host_sin->sin_family = AF_INET;
1777 host_sin->sin_addr.s_addr = sin->sin_addr.s_addr; 1798 host_sin->sin_addr.s_addr = sin->sin_addr.s_addr;
1778 } else { 1799 } else {
1779 host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; 1800 host_sin6 = (struct sockaddr_in6 *)&target->saddr_in;
1780 host_sin6->sin6_family = AF_INET6; 1801 host_sin6->sin6_family = AF_INET6;
1781 memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, 1802 memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr,
1782 sizeof host_sin6->sin6_addr.s6_addr); 1803 sizeof host_sin6->sin6_addr.s6_addr);
1783 } 1804 }
1784 1805
1785 if (!host_list) { 1806 result.target = target;
1786 host_list = cursor = host;
1787 } else {
1788 cursor->next = host;
1789 }
1790
1791 cursor = host;
1792 1807
1793 return 0; 1808 return result;
1794} 1809}
1795 1810
1796/* wrapper for add_target_ip */ 1811/* wrapper for add_target_ip */
1797static int add_target(char *arg, const int mode) { 1812static add_target_wrapper add_target(char *arg, const int mode) {
1798 struct sockaddr_storage ip; 1813 struct sockaddr_storage address_storage;
1799 struct sockaddr_in *sin; 1814 struct sockaddr_in *sin;
1800 struct sockaddr_in6 *sin6; 1815 struct sockaddr_in6 *sin6;
1801 int result = -1; 1816 int error_code = -1;
1802 1817
1803 switch (address_family) { 1818 switch (address_family) {
1804 case -1: 1819 case -1:
1805 /* -4 and -6 are not specified on cmdline */ 1820 /* -4 and -6 are not specified on cmdline */
1806 address_family = AF_INET; 1821 address_family = AF_INET;
1807 sin = (struct sockaddr_in *)&ip; 1822 sin = (struct sockaddr_in *)&address_storage;
1808 result = inet_pton(address_family, arg, &sin->sin_addr); 1823 error_code = inet_pton(address_family, arg, &sin->sin_addr);
1809#ifdef USE_IPV6 1824#ifdef USE_IPV6
1810 if (result != 1) { 1825 if (error_code != 1) {
1811 address_family = AF_INET6; 1826 address_family = AF_INET6;
1812 sin6 = (struct sockaddr_in6 *)&ip; 1827 sin6 = (struct sockaddr_in6 *)&address_storage;
1813 result = inet_pton(address_family, arg, &sin6->sin6_addr); 1828 error_code = inet_pton(address_family, arg, &sin6->sin6_addr);
1814 } 1829 }
1815#endif 1830#endif
1816 /* If we don't find any valid addresses, we still don't know the address_family */ 1831 /* If we don't find any valid addresses, we still don't know the address_family */
1817 if (result != 1) { 1832 if (error_code != 1) {
1818 address_family = -1; 1833 address_family = -1;
1819 } 1834 }
1820 break; 1835 break;
1821 case AF_INET: 1836 case AF_INET:
1822 sin = (struct sockaddr_in *)&ip; 1837 sin = (struct sockaddr_in *)&address_storage;
1823 result = inet_pton(address_family, arg, &sin->sin_addr); 1838 error_code = inet_pton(address_family, arg, &sin->sin_addr);
1824 break; 1839 break;
1825 case AF_INET6: 1840 case AF_INET6:
1826 sin6 = (struct sockaddr_in6 *)&ip; 1841 sin6 = (struct sockaddr_in6 *)&address_storage;
1827 result = inet_pton(address_family, arg, &sin6->sin6_addr); 1842 error_code = inet_pton(address_family, arg, &sin6->sin6_addr);
1828 break; 1843 break;
1829 default: 1844 default:
1830 crash("Address family not supported"); 1845 crash("Address family not supported");
1831 } 1846 }
1832 1847
1848 add_target_wrapper result = {
1849 .error_code = OK,
1850 .targets = NULL,
1851 };
1852
1833 /* don't resolve if we don't have to */ 1853 /* don't resolve if we don't have to */
1834 if (result == 1) { 1854 if (error_code == 1) {
1835 /* don't add all ip's if we were given a specific one */ 1855 /* don't add all ip's if we were given a specific one */
1836 return add_target_ip(arg, &ip); 1856 add_target_ip_wrapper targeted = add_target_ip(arg, &address_storage);
1857
1858 if (targeted.error_code != OK) {
1859 result.error_code = ERROR;
1860 return result;
1861 }
1862
1863 result.targets = targeted.target;
1864 result.number_of_targets = 1;
1865 return result;
1837 } 1866 }
1838 1867
1839 struct addrinfo hints; 1868 struct addrinfo hints;
@@ -1851,14 +1880,28 @@ static int add_target(char *arg, const int mode) {
1851 if ((error = getaddrinfo(arg, NULL, &hints, &res)) != 0) { 1880 if ((error = getaddrinfo(arg, NULL, &hints, &res)) != 0) {
1852 errno = 0; 1881 errno = 0;
1853 crash("Failed to resolve %s: %s", arg, gai_strerror(error)); 1882 crash("Failed to resolve %s: %s", arg, gai_strerror(error));
1854 return -1; 1883 result.error_code = ERROR;
1884 return result;
1855 } 1885 }
1856 address_family = res->ai_family; 1886 address_family = res->ai_family;
1857 1887
1858 /* possibly add all the IP's as targets */ 1888 /* possibly add all the IP's as targets */
1859 for (struct addrinfo *p = res; p != NULL; p = p->ai_next) { 1889 for (struct addrinfo *address = res; address != NULL; address = address->ai_next) {
1860 memcpy(&ip, p->ai_addr, p->ai_addrlen); 1890 struct sockaddr_storage temporary_ip_address;
1861 add_target_ip(arg, &ip); 1891 memcpy(&temporary_ip_address, address->ai_addr, address->ai_addrlen);
1892 add_target_ip_wrapper tmp = add_target_ip(arg, &temporary_ip_address);
1893
1894 if (tmp.error_code != OK) {
1895 // No proper error handling
1896 // What to do?
1897 } else {
1898 if (result.targets == NULL) {
1899 result.targets = tmp.target;
1900 result.number_of_targets = 1;
1901 } else {
1902 result.number_of_targets += ping_target_list_append(result.targets, tmp.target);
1903 }
1904 }
1862 1905
1863 /* this is silly, but it works */ 1906 /* this is silly, but it works */
1864 if (mode == MODE_HOSTCHECK || mode == MODE_ALL) { 1907 if (mode == MODE_HOSTCHECK || mode == MODE_ALL) {
@@ -1867,11 +1910,13 @@ static int add_target(char *arg, const int mode) {
1867 } 1910 }
1868 continue; 1911 continue;
1869 } 1912 }
1913
1914 // Abort after first hit if not in of the modes above
1870 break; 1915 break;
1871 } 1916 }
1872 freeaddrinfo(res); 1917 freeaddrinfo(res);
1873 1918
1874 return 0; 1919 return result;
1875} 1920}
1876 1921
1877static void set_source_ip(char *arg, const int icmp_sock) { 1922static void set_source_ip(char *arg, const int icmp_sock) {
@@ -1890,8 +1935,8 @@ static void set_source_ip(char *arg, const int icmp_sock) {
1890/* TODO: Move this to netutils.c and also change check_dhcp to use that. */ 1935/* TODO: Move this to netutils.c and also change check_dhcp to use that. */
1891static in_addr_t get_ip_address(const char *ifname) { 1936static in_addr_t get_ip_address(const char *ifname) {
1892 // TODO: Rewrite this so the function return an error and we exit somewhere else 1937 // TODO: Rewrite this so the function return an error and we exit somewhere else
1893 struct sockaddr_in ip; 1938 struct sockaddr_in ip_address;
1894 ip.sin_addr.s_addr = 0; // Fake initialization to make compiler happy 1939 ip_address.sin_addr.s_addr = 0; // Fake initialization to make compiler happy
1895#if defined(SIOCGIFADDR) 1940#if defined(SIOCGIFADDR)
1896 struct ifreq ifr; 1941 struct ifreq ifr;
1897 1942
@@ -1909,7 +1954,7 @@ static in_addr_t get_ip_address(const char *ifname) {
1909 errno = 0; 1954 errno = 0;
1910 crash("Cannot get interface IP address on this platform."); 1955 crash("Cannot get interface IP address on this platform.");
1911#endif 1956#endif
1912 return ip.sin_addr.s_addr; 1957 return ip_address.sin_addr.s_addr;
1913} 1958}
1914 1959
1915/* 1960/*
@@ -1930,87 +1975,90 @@ static unsigned int get_timevar(const char *str) {
1930 1975
1931 /* unit might be given as ms|m (millisec), 1976 /* unit might be given as ms|m (millisec),
1932 * us|u (microsec) or just plain s, for seconds */ 1977 * us|u (microsec) or just plain s, for seconds */
1933 char p = '\0'; 1978 char tmp = '\0';
1934 char u = str[len - 1]; 1979 char unit = str[len - 1];
1935 if (len >= 2 && !isdigit((int)str[len - 2])) { 1980 if (len >= 2 && !isdigit((int)str[len - 2])) {
1936 p = str[len - 2]; 1981 tmp = str[len - 2];
1937 } 1982 }
1938 if (p && u == 's') { 1983
1939 u = p; 1984 if (tmp && unit == 's') {
1940 } else if (!p) { 1985 unit = tmp;
1941 p = u; 1986 } else if (!tmp) {
1987 tmp = unit;
1942 } 1988 }
1989
1943 if (debug > 2) { 1990 if (debug > 2) {
1944 printf("evaluating %s, u: %c, p: %c\n", str, u, p); 1991 printf("evaluating %s, u: %c, p: %c\n", str, unit, tmp);
1945 } 1992 }
1946 1993
1947 unsigned int factor = 1000; /* default to milliseconds */ 1994 unsigned int factor = 1000; /* default to milliseconds */
1948 if (u == 'u') { 1995 if (unit == 'u') {
1949 factor = 1; /* microseconds */ 1996 factor = 1; /* microseconds */
1950 } else if (u == 'm') { 1997 } else if (unit == 'm') {
1951 factor = 1000; /* milliseconds */ 1998 factor = 1000; /* milliseconds */
1952 } else if (u == 's') { 1999 } else if (unit == 's') {
1953 factor = 1000000; /* seconds */ 2000 factor = 1000000; /* seconds */
1954 } 2001 }
2002
1955 if (debug > 2) { 2003 if (debug > 2) {
1956 printf("factor is %u\n", factor); 2004 printf("factor is %u\n", factor);
1957 } 2005 }
1958 2006
1959 char *ptr; 2007 char *ptr;
1960 unsigned int i; 2008 unsigned long pre_radix;
1961 i = strtoul(str, &ptr, 0); 2009 pre_radix = strtoul(str, &ptr, 0);
1962 if (!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1) { 2010 if (!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1) {
1963 return i * factor; 2011 return (unsigned int)(pre_radix * factor);
1964 } 2012 }
1965 2013
1966 /* time specified in usecs can't have decimal points, so ignore them */ 2014 /* time specified in usecs can't have decimal points, so ignore them */
1967 if (factor == 1) { 2015 if (factor == 1) {
1968 return i; 2016 return (unsigned int)pre_radix;
1969 } 2017 }
1970 2018
1971 /* integer and decimal, respectively */ 2019 /* integer and decimal, respectively */
1972 unsigned int d = strtoul(ptr + 1, NULL, 0); 2020 unsigned int post_radix = (unsigned int)strtoul(ptr + 1, NULL, 0);
1973 2021
1974 /* d is decimal, so get rid of excess digits */ 2022 /* d is decimal, so get rid of excess digits */
1975 while (d >= factor) { 2023 while (post_radix >= factor) {
1976 d /= 10; 2024 post_radix /= 10;
1977 } 2025 }
1978 2026
1979 /* the last parenthesis avoids floating point exceptions. */ 2027 /* the last parenthesis avoids floating point exceptions. */
1980 return ((i * factor) + (d * (factor / 10))); 2028 return (unsigned int)((pre_radix * factor) + (post_radix * (factor / 10)));
1981} 2029}
1982 2030
1983/* not too good at checking errors, but it'll do (main() should barfe on -1) */ 2031/* not too good at checking errors, but it'll do (main() should barfe on -1) */
1984static int get_threshold(char *str, threshold *th) { 2032static int get_threshold(char *str, threshold *threshold) {
1985 if (!str || !strlen(str) || !th) { 2033 if (!str || !strlen(str) || !threshold) {
1986 return -1; 2034 return -1;
1987 } 2035 }
1988 2036
1989 /* pointer magic slims code by 10 lines. i is bof-stop on stupid libc's */ 2037 /* pointer magic slims code by 10 lines. i is bof-stop on stupid libc's */
1990 char i = 0; 2038 bool is_at_last_char = false;
1991 char *p = &str[strlen(str) - 1]; 2039 char *tmp = &str[strlen(str) - 1];
1992 while (p != &str[1]) { 2040 while (tmp != &str[1]) {
1993 if (*p == '%') { 2041 if (*tmp == '%') {
1994 *p = '\0'; 2042 *tmp = '\0';
1995 } else if (*p == ',' && i) { 2043 } else if (*tmp == ',' && is_at_last_char) {
1996 *p = '\0'; /* reset it so get_timevar(str) works nicely later */ 2044 *tmp = '\0'; /* reset it so get_timevar(str) works nicely later */
1997 th->pl = (unsigned char)strtoul(p + 1, NULL, 0); 2045 threshold->pl = (unsigned char)strtoul(tmp + 1, NULL, 0);
1998 break; 2046 break;
1999 } 2047 }
2000 i = 1; 2048 is_at_last_char = true;
2001 p--; 2049 tmp--;
2002 } 2050 }
2003 th->rta = get_timevar(str); 2051 threshold->rta = get_timevar(str);
2004 2052
2005 if (!th->rta) { 2053 if (!threshold->rta) {
2006 return -1; 2054 return -1;
2007 } 2055 }
2008 2056
2009 if (th->rta > MAXTTL * 1000000) { 2057 if (threshold->rta > MAXTTL * 1000000) {
2010 th->rta = MAXTTL * 1000000; 2058 threshold->rta = MAXTTL * 1000000;
2011 } 2059 }
2012 if (th->pl > 100) { 2060 if (threshold->pl > 100) {
2013 th->pl = 100; 2061 threshold->pl = 100;
2014 } 2062 }
2015 2063
2016 return 0; 2064 return 0;
@@ -2034,58 +2082,58 @@ static bool get_threshold2(char *str, size_t length, threshold *warn, threshold
2034 } 2082 }
2035 2083
2036 // p points to the last char in str 2084 // p points to the last char in str
2037 char *p = &str[length - 1]; 2085 char *work_pointer = &str[length - 1];
2038 2086
2039 // first_iteration is bof-stop on stupid libc's 2087 // first_iteration is bof-stop on stupid libc's
2040 bool first_iteration = true; 2088 bool first_iteration = true;
2041 2089
2042 while (p != &str[0]) { 2090 while (work_pointer != &str[0]) {
2043 if ((*p == 'm') || (*p == '%')) { 2091 if ((*work_pointer == 'm') || (*work_pointer == '%')) {
2044 *p = '\0'; 2092 *work_pointer = '\0';
2045 } else if (*p == ',' && !first_iteration) { 2093 } else if (*work_pointer == ',' && !first_iteration) {
2046 *p = '\0'; /* reset it so get_timevar(str) works nicely later */ 2094 *work_pointer = '\0'; /* reset it so get_timevar(str) works nicely later */
2047 2095
2048 char *start_of_value = p + 1; 2096 char *start_of_value = work_pointer + 1;
2049 2097
2050 if (!parse_threshold2_helper(start_of_value, strlen(start_of_value), crit, mode)) { 2098 if (!parse_threshold2_helper(start_of_value, strlen(start_of_value), crit, mode)) {
2051 return false; 2099 return false;
2052 } 2100 }
2053 } 2101 }
2054 first_iteration = false; 2102 first_iteration = false;
2055 p--; 2103 work_pointer--;
2056 } 2104 }
2057 2105
2058 return parse_threshold2_helper(p, strlen(p), warn, mode); 2106 return parse_threshold2_helper(work_pointer, strlen(work_pointer), warn, mode);
2059} 2107}
2060 2108
2061static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, threshold_mode mode) { 2109static bool parse_threshold2_helper(char *threshold_string, size_t length, threshold *thr,
2110 threshold_mode mode) {
2062 char *resultChecker = {0}; 2111 char *resultChecker = {0};
2063 2112
2064 switch (mode) { 2113 switch (mode) {
2065 case const_rta_mode: 2114 case const_rta_mode:
2066 thr->rta = strtod(s, &resultChecker) * 1000; 2115 thr->rta = (unsigned int)(strtod(threshold_string, &resultChecker) * 1000);
2067 break; 2116 break;
2068 case const_packet_loss_mode: 2117 case const_packet_loss_mode:
2069 thr->pl = (unsigned char)strtoul(s, &resultChecker, 0); 2118 thr->pl = (unsigned char)strtoul(threshold_string, &resultChecker, 0);
2070 break; 2119 break;
2071 case const_jitter_mode: 2120 case const_jitter_mode:
2072 thr->jitter = strtod(s, &resultChecker); 2121 thr->jitter = strtod(threshold_string, &resultChecker);
2073
2074 break; 2122 break;
2075 case const_mos_mode: 2123 case const_mos_mode:
2076 thr->mos = strtod(s, &resultChecker); 2124 thr->mos = strtod(threshold_string, &resultChecker);
2077 break; 2125 break;
2078 case const_score_mode: 2126 case const_score_mode:
2079 thr->score = strtod(s, &resultChecker); 2127 thr->score = strtod(threshold_string, &resultChecker);
2080 break; 2128 break;
2081 } 2129 }
2082 2130
2083 if (resultChecker == s) { 2131 if (resultChecker == threshold_string) {
2084 // Failed to parse 2132 // Failed to parse
2085 return false; 2133 return false;
2086 } 2134 }
2087 2135
2088 if (resultChecker != (s + length)) { 2136 if (resultChecker != (threshold_string + length)) {
2089 // Trailing symbols 2137 // Trailing symbols
2090 return false; 2138 return false;
2091 } 2139 }
@@ -2093,24 +2141,24 @@ static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, thre
2093 return true; 2141 return true;
2094} 2142}
2095 2143
2096unsigned short icmp_checksum(uint16_t *p, size_t n) { 2144unsigned short icmp_checksum(uint16_t *packet, size_t packet_size) {
2097 long sum = 0; 2145 long sum = 0;
2098 2146
2099 /* sizeof(uint16_t) == 2 */ 2147 /* sizeof(uint16_t) == 2 */
2100 while (n >= 2) { 2148 while (packet_size >= 2) {
2101 sum += *(p++); 2149 sum += *(packet++);
2102 n -= 2; 2150 packet_size -= 2;
2103 } 2151 }
2104 2152
2105 /* mop up the occasional odd byte */ 2153 /* mop up the occasional odd byte */
2106 if (n == 1) { 2154 if (packet_size == 1) {
2107 sum += *((uint8_t *)p - 1); 2155 sum += *((uint8_t *)packet - 1);
2108 } 2156 }
2109 2157
2110 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 2158 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
2111 sum += (sum >> 16); /* add carry */ 2159 sum += (sum >> 16); /* add carry */
2112 unsigned short cksum; 2160 unsigned short cksum;
2113 cksum = ~sum; /* ones-complement, trunc to 16 bits */ 2161 cksum = (unsigned short)~sum; /* ones-complement, trunc to 16 bits */
2114 2162
2115 return cksum; 2163 return cksum;
2116} 2164}