summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-05-18 18:10:25 +0200
committerLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-05-18 18:10:25 +0200
commitb5de682309589ddb230e04beaaa54d74f2fe70d5 (patch)
tree70c2557e7ad1605ef216a7cb6e1a5e8eb843a016
parent8f08e7ab3ecc03ea38062fe4442668fbea30bb73 (diff)
downloadmonitoring-plugins-b5de682309589ddb230e04beaaa54d74f2fe70d5.tar.gz
WIP - check_icmp refactor 8
-rw-r--r--plugins-root/check_icmp.c505
-rw-r--r--plugins-root/check_icmp.d/check_icmp_helpers.c64
-rw-r--r--plugins-root/check_icmp.d/check_icmp_helpers.h15
-rw-r--r--plugins-root/check_icmp.d/config.h3
4 files changed, 332 insertions, 255 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index 0614d6aa..d4e55b0d 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -71,6 +71,9 @@ const char *email = "devel@monitoring-plugins.org";
71#include <sys/types.h> 71#include <sys/types.h>
72#include <unistd.h> 72#include <unistd.h>
73#include <stdint.h> 73#include <stdint.h>
74#include <sys/socket.h>
75#include <assert.h>
76#include <sys/select.h>
74 77
75#include "../lib/states.h" 78#include "../lib/states.h"
76#include "./check_icmp.d/config.h" 79#include "./check_icmp.d/config.h"
@@ -140,24 +143,31 @@ static time_t get_timevaldiff(struct timeval earlier, struct timeval later);
140static time_t get_timevaldiff_to_now(struct timeval earlier); 143static time_t get_timevaldiff_to_now(struct timeval earlier);
141 144
142static in_addr_t get_ip_address(const char *ifname); 145static in_addr_t get_ip_address(const char *ifname);
143static void set_source_ip(char *arg, int icmp_sock); 146static void set_source_ip(char *arg, int icmp_sock, sa_family_t addr_family);
144 147
145/* Receiving data */ 148/* Receiving data */
146static int wait_for_reply(int socket, time_t time_interval, unsigned short icmp_pkt_size, 149static int wait_for_reply(check_icmp_socket_set sockset, time_t time_interval,
147 unsigned int *pkt_interval, unsigned int *target_interval, 150 unsigned short icmp_pkt_size, unsigned int *pkt_interval,
148 uint16_t sender_id, ping_target **table, unsigned short packets, 151 unsigned int *target_interval, uint16_t sender_id, ping_target **table,
149 unsigned short number_of_targets, check_icmp_state *program_state); 152 unsigned short packets, unsigned short number_of_targets,
153 check_icmp_state *program_state);
150 154
151static ssize_t recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, 155typedef struct {
152 time_t *timeout, struct timeval *received_timestamp); 156 sa_family_t recv_proto;
157 ssize_t received;
158} recvfrom_wto_wrapper;
159static recvfrom_wto_wrapper recvfrom_wto(check_icmp_socket_set sockset, void *buf, unsigned int len,
160 struct sockaddr *saddr, time_t *timeout,
161 struct timeval *received_timestamp);
153static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr, 162static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr,
154 unsigned int *pkt_interval, unsigned int *target_interval, 163 unsigned int *pkt_interval, unsigned int *target_interval,
155 uint16_t sender_id, ping_target **table, unsigned short packets, 164 uint16_t sender_id, ping_target **table, unsigned short packets,
156 unsigned short number_of_targets, check_icmp_state *program_state); 165 unsigned short number_of_targets, check_icmp_state *program_state);
157 166
158/* Sending data */ 167/* Sending data */
159static int send_icmp_ping(int socket, ping_target *host, unsigned short icmp_pkt_size, 168static int send_icmp_ping(check_icmp_socket_set socket, ping_target *host,
160 uint16_t sender_id, check_icmp_state *program_state); 169 unsigned short icmp_pkt_size, uint16_t sender_id,
170 check_icmp_state *program_state);
161 171
162/* Threshold related */ 172/* Threshold related */
163typedef struct { 173typedef struct {
@@ -188,7 +198,7 @@ static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval,
188 unsigned int *target_interval, uint16_t sender_id, 198 unsigned int *target_interval, uint16_t sender_id,
189 check_icmp_execution_mode mode, unsigned int max_completion_time, 199 check_icmp_execution_mode mode, unsigned int max_completion_time,
190 struct timeval prog_start, ping_target **table, unsigned short packets, 200 struct timeval prog_start, ping_target **table, unsigned short packets,
191 int icmp_sock, unsigned short number_of_targets, 201 check_icmp_socket_set sockset, unsigned short number_of_targets,
192 check_icmp_state *program_state); 202 check_icmp_state *program_state);
193mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes, 203mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
194 check_icmp_threshold warn, check_icmp_threshold crit); 204 check_icmp_threshold warn, check_icmp_threshold crit);
@@ -206,15 +216,21 @@ evaluate_host_wrapper evaluate_host(check_icmp_target_container host,
206typedef struct { 216typedef struct {
207 int error_code; 217 int error_code;
208 check_icmp_target_container host; 218 check_icmp_target_container host;
219 bool has_v4;
220 bool has_v6;
209} add_host_wrapper; 221} add_host_wrapper;
210static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode); 222static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode,
223 sa_family_t enforced_proto);
211 224
212typedef struct { 225typedef struct {
213 int error_code; 226 int error_code;
214 ping_target *targets; 227 ping_target *targets;
215 unsigned int number_of_targets; 228 unsigned int number_of_targets;
229 bool has_v4;
230 bool has_v6;
216} add_target_wrapper; 231} add_target_wrapper;
217static add_target_wrapper add_target(char *arg, check_icmp_execution_mode mode); 232static add_target_wrapper add_target(char *arg, check_icmp_execution_mode mode,
233 sa_family_t enforced_proto);
218 234
219typedef struct { 235typedef struct {
220 int error_code; 236 int error_code;
@@ -222,13 +238,13 @@ typedef struct {
222} add_target_ip_wrapper; 238} add_target_ip_wrapper;
223static add_target_ip_wrapper add_target_ip(struct sockaddr_storage address); 239static add_target_ip_wrapper add_target_ip(struct sockaddr_storage address);
224 240
225static void parse_address(struct sockaddr_storage *addr, char *address, socklen_t size); 241static void parse_address(const struct sockaddr_storage *addr, char *dst, socklen_t size);
226 242
227static unsigned short icmp_checksum(uint16_t *packet, size_t packet_size); 243static unsigned short icmp_checksum(uint16_t *packet, size_t packet_size);
228 244
229/* End of run function */ 245/* End of run function */
230static void finish(int sign, check_icmp_mode_switches modes, int min_hosts_alive, 246static void finish(int sign, check_icmp_mode_switches modes, int min_hosts_alive,
231 check_icmp_threshold warn, check_icmp_threshold crit, int icmp_sock, 247 check_icmp_threshold warn, check_icmp_threshold crit,
232 unsigned short number_of_targets, check_icmp_state *program_state, 248 unsigned short number_of_targets, check_icmp_state *program_state,
233 check_icmp_target_container host_list[], unsigned short number_of_hosts, 249 check_icmp_target_container host_list[], unsigned short number_of_hosts,
234 mp_check overall[static 1]); 250 mp_check overall[static 1]);
@@ -298,6 +314,8 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) {
298 } 314 }
299 } 315 }
300 316
317 sa_family_t enforced_ai_family = AF_UNSPEC;
318
301 // Parse protocol arguments first 319 // Parse protocol arguments first
302 // and count hosts here 320 // and count hosts here
303 char *opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64"; 321 char *opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64";
@@ -306,16 +324,16 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) {
306 while ((arg = getopt(argc, argv, opts_str)) != EOF) { 324 while ((arg = getopt(argc, argv, opts_str)) != EOF) {
307 switch (arg) { 325 switch (arg) {
308 case '4': 326 case '4':
309 if (address_family != -1) { 327 if (enforced_ai_family != AF_UNSPEC) {
310 crash("Multiple protocol versions not supported"); 328 crash("Multiple protocol versions not supported");
311 } 329 }
312 address_family = AF_INET; 330 enforced_ai_family = AF_INET;
313 break; 331 break;
314 case '6': 332 case '6':
315 if (address_family != -1) { 333 if (enforced_ai_family != AF_UNSPEC) {
316 crash("Multiple protocol versions not supported"); 334 crash("Multiple protocol versions not supported");
317 } 335 }
318 address_family = AF_INET6; 336 enforced_ai_family = AF_INET6;
319 break; 337 break;
320 case 'H': { 338 case 'H': {
321 result.config.number_of_hosts++; 339 result.config.number_of_hosts++;
@@ -402,7 +420,8 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) {
402 // TODO die here and complain about wrong input 420 // TODO die here and complain about wrong input
403 break; 421 break;
404 case 'H': { 422 case 'H': {
405 add_host_wrapper host_add_result = add_host(optarg, result.config.mode); 423 add_host_wrapper host_add_result =
424 add_host(optarg, result.config.mode, enforced_ai_family);
406 if (host_add_result.error_code == OK) { 425 if (host_add_result.error_code == OK) {
407 result.config.hosts[host_counter] = host_add_result.host; 426 result.config.hosts[host_counter] = host_add_result.host;
408 host_counter++; 427 host_counter++;
@@ -414,6 +433,13 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) {
414 result.config.targets = host_add_result.host.target_list; 433 result.config.targets = host_add_result.host.target_list;
415 result.config.number_of_targets += host_add_result.host.number_of_targets; 434 result.config.number_of_targets += host_add_result.host.number_of_targets;
416 } 435 }
436
437 if (host_add_result.has_v4) {
438 result.config.need_v4 = true;
439 }
440 if (host_add_result.has_v6) {
441 result.config.need_v6 = true;
442 }
417 } else { 443 } else {
418 // TODO adding host failed, crash here 444 // TODO adding host failed, crash here
419 } 445 }
@@ -502,7 +528,7 @@ check_icmp_config_wrapper process_arguments(int argc, char **argv) {
502 528
503 argv = &argv[optind]; 529 argv = &argv[optind];
504 while (*argv) { 530 while (*argv) {
505 add_target(*argv, result.config.mode); 531 add_target(*argv, result.config.mode, enforced_ai_family);
506 argv++; 532 argv++;
507 } 533 }
508 534
@@ -704,9 +730,8 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad
704 if (debug) { 730 if (debug) {
705 char address[INET6_ADDRSTRLEN]; 731 char address[INET6_ADDRSTRLEN];
706 parse_address(addr, address, sizeof(address)); 732 parse_address(addr, address, sizeof(address));
707 printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n", 733 printf("Received \"%s\" from %s for ICMP ECHO sent.\n",
708 get_icmp_error_msg(icmp_packet.icmp_type, icmp_packet.icmp_code), address, 734 get_icmp_error_msg(icmp_packet.icmp_type, icmp_packet.icmp_code), address);
709 host->name);
710 } 735 }
711 736
712 program_state->icmp_lost++; 737 program_state->icmp_lost++;
@@ -732,14 +757,16 @@ static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *ad
732 return 0; 757 return 0;
733} 758}
734 759
735void parse_address(struct sockaddr_storage *addr, char *address, socklen_t size) { 760void parse_address(const struct sockaddr_storage *addr, char *dst, socklen_t size) {
736 switch (address_family) { 761 switch (addr->ss_family) {
737 case AF_INET: 762 case AF_INET:
738 inet_ntop(address_family, &((struct sockaddr_in *)addr)->sin_addr, address, size); 763 inet_ntop(AF_INET, &((struct sockaddr_in *)addr)->sin_addr, dst, size);
739 break; 764 break;
740 case AF_INET6: 765 case AF_INET6:
741 inet_ntop(address_family, &((struct sockaddr_in6 *)addr)->sin6_addr, address, size); 766 inet_ntop(AF_INET6, &((struct sockaddr_in6 *)addr)->sin6_addr, dst, size);
742 break; 767 break;
768 default:
769 assert(false);
743 } 770 }
744} 771}
745 772
@@ -748,9 +775,6 @@ int main(int argc, char **argv) {
748 bindtextdomain(PACKAGE, LOCALEDIR); 775 bindtextdomain(PACKAGE, LOCALEDIR);
749 textdomain(PACKAGE); 776 textdomain(PACKAGE);
750 777
751 address_family = -1;
752 int icmp_proto = IPPROTO_ICMP;
753
754 /* POSIXLY_CORRECT might break things, so unset it (the portable way) */ 778 /* POSIXLY_CORRECT might break things, so unset it (the portable way) */
755 environ = NULL; 779 environ = NULL;
756 780
@@ -765,35 +789,68 @@ int main(int argc, char **argv) {
765 789
766 const check_icmp_config config = tmp_config.config; 790 const check_icmp_config config = tmp_config.config;
767 791
792 // int icmp_proto = IPPROTO_ICMP;
768 // add_target might change address_family 793 // add_target might change address_family
769 switch (address_family) { 794 // switch (address_family) {
770 case AF_INET: 795 // case AF_INET:
771 icmp_proto = IPPROTO_ICMP; 796 // icmp_proto = IPPROTO_ICMP;
772 break; 797 // break;
773 case AF_INET6: 798 // case AF_INET6:
774 icmp_proto = IPPROTO_ICMPV6; 799 // icmp_proto = IPPROTO_ICMPV6;
775 break; 800 // break;
776 default: 801 // default:
777 crash("Address family not supported"); 802 // crash("Address family not supported");
778 } 803 // }
804
805 check_icmp_socket_set sockset = {
806 .socket4 = -1,
807 .socket6 = -1,
808 };
779 809
780 int icmp_sock = socket(address_family, SOCK_RAW, icmp_proto); 810 if (config.need_v4) {
781 if (icmp_sock == -1) { 811 sockset.socket4 = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
782 crash("Failed to obtain ICMP socket"); 812 if (sockset.socket4 == -1) {
783 } 813 crash("Failed to obtain ICMP v4 socket");
814 }
784 815
785 if (config.source_ip) { 816 if (config.source_ip) {
786 set_source_ip(config.source_ip, icmp_sock); 817
787 } 818 struct in_addr tmp = {};
819 int error_code = inet_pton(AF_INET, config.source_ip, &tmp);
820 if (error_code == 1) {
821 set_source_ip(config.source_ip, sockset.socket4, AF_INET);
822 } else {
823 // just try this mindlessly if it's not a v4 address
824 set_source_ip(config.source_ip, sockset.socket6, AF_INET6);
825 }
826 }
788 827
789#ifdef SO_TIMESTAMP 828#ifdef SO_TIMESTAMP
790 int on = 1; 829 if (sockset.socket4 != -1) {
791 if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) { 830 int on = 1;
792 if (debug) { 831 if (setsockopt(sockset.socket4, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) {
793 printf("Warning: no SO_TIMESTAMP support\n"); 832 if (debug) {
833 printf("Warning: no SO_TIMESTAMP support\n");
834 }
835 }
836 }
837 if (sockset.socket6 != -1) {
838 int on = 1;
839 if (setsockopt(sockset.socket6, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) {
840 if (debug) {
841 printf("Warning: no SO_TIMESTAMP support\n");
842 }
843 }
794 } 844 }
795 }
796#endif // SO_TIMESTAMP 845#endif // SO_TIMESTAMP
846 }
847
848 if (config.need_v6) {
849 sockset.socket6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
850 if (sockset.socket6 == -1) {
851 crash("Failed to obtain ICMP v6 socket");
852 }
853 }
797 854
798 /* now drop privileges (no effect if not setsuid or geteuid() == 0) */ 855 /* now drop privileges (no effect if not setsuid or geteuid() == 0) */
799 if (setuid(getuid()) == -1) { 856 if (setuid(getuid()) == -1) {
@@ -801,8 +858,19 @@ int main(int argc, char **argv) {
801 return 1; 858 return 1;
802 } 859 }
803 860
804 if (icmp_sock) { 861 if (sockset.socket4) {
805 int result = setsockopt(icmp_sock, SOL_IP, IP_TTL, &config.ttl, sizeof(config.ttl)); 862 int result = setsockopt(sockset.socket4, SOL_IP, IP_TTL, &config.ttl, sizeof(config.ttl));
863 if (debug) {
864 if (result == -1) {
865 printf("setsockopt failed\n");
866 } else {
867 printf("ttl set to %lu\n", config.ttl);
868 }
869 }
870 }
871
872 if (sockset.socket6) {
873 int result = setsockopt(sockset.socket6, SOL_IP, IP_TTL, &config.ttl, sizeof(config.ttl));
806 if (debug) { 874 if (debug) {
807 if (result == -1) { 875 if (result == -1) {
808 printf("setsockopt failed\n"); 876 printf("setsockopt failed\n");
@@ -888,15 +956,22 @@ int main(int argc, char **argv) {
888 956
889 run_checks(config.icmp_data_size, &pkt_interval, &target_interval, config.sender_id, 957 run_checks(config.icmp_data_size, &pkt_interval, &target_interval, config.sender_id,
890 config.mode, max_completion_time, prog_start, table, config.number_of_packets, 958 config.mode, max_completion_time, prog_start, table, config.number_of_packets,
891 icmp_sock, config.number_of_targets, &program_state); 959 sockset, config.number_of_targets, &program_state);
892 960
893 errno = 0; 961 errno = 0;
894 962
895 mp_check overall = mp_check_init(); 963 mp_check overall = mp_check_init();
896 finish(0, config.modes, config.min_hosts_alive, config.warn, config.crit, icmp_sock, 964 finish(0, config.modes, config.min_hosts_alive, config.warn, config.crit,
897 config.number_of_targets, &program_state, config.hosts, config.number_of_hosts, 965 config.number_of_targets, &program_state, config.hosts, config.number_of_hosts,
898 &overall); 966 &overall);
899 967
968 if (sockset.socket4) {
969 close(sockset.socket4);
970 }
971 if (sockset.socket6) {
972 close(sockset.socket6);
973 }
974
900 mp_exit(overall); 975 mp_exit(overall);
901} 976}
902 977
@@ -904,7 +979,7 @@ static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval,
904 unsigned int *target_interval, const uint16_t sender_id, 979 unsigned int *target_interval, const uint16_t sender_id,
905 const check_icmp_execution_mode mode, const unsigned int max_completion_time, 980 const check_icmp_execution_mode mode, const unsigned int max_completion_time,
906 const struct timeval prog_start, ping_target **table, 981 const struct timeval prog_start, ping_target **table,
907 const unsigned short packets, const int icmp_sock, 982 const unsigned short packets, const check_icmp_socket_set sockset,
908 const unsigned short number_of_targets, check_icmp_state *program_state) { 983 const unsigned short number_of_targets, check_icmp_state *program_state) {
909 /* this loop might actually violate the pkt_interval or target_interval 984 /* this loop might actually violate the pkt_interval or target_interval
910 * settings, but only if there aren't any packets on the wire which 985 * settings, but only if there aren't any packets on the wire which
@@ -917,20 +992,23 @@ static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval,
917 } 992 }
918 if (table[target_index]->flags & FLAG_LOST_CAUSE) { 993 if (table[target_index]->flags & FLAG_LOST_CAUSE) {
919 if (debug) { 994 if (debug) {
920 printf("%s is a lost cause. not sending any more\n", table[target_index]->name); 995
996 char address[INET6_ADDRSTRLEN];
997 parse_address(&table[target_index]->address, address, sizeof(address));
998 printf("%s is a lost cause. not sending any more\n", address);
921 } 999 }
922 continue; 1000 continue;
923 } 1001 }
924 1002
925 /* we're still in the game, so send next packet */ 1003 /* we're still in the game, so send next packet */
926 (void)send_icmp_ping(icmp_sock, table[target_index], icmp_pkt_size, sender_id, 1004 (void)send_icmp_ping(sockset, table[target_index], icmp_pkt_size, sender_id,
927 program_state); 1005 program_state);
928 1006
929 /* wrap up if all targets are declared dead */ 1007 /* wrap up if all targets are declared dead */
930 if (targets_alive(number_of_targets, program_state->targets_down) || 1008 if (targets_alive(number_of_targets, program_state->targets_down) ||
931 get_timevaldiff(prog_start, prog_start) < max_completion_time || 1009 get_timevaldiff(prog_start, prog_start) < max_completion_time ||
932 !(mode == MODE_HOSTCHECK && program_state->targets_down)) { 1010 !(mode == MODE_HOSTCHECK && program_state->targets_down)) {
933 wait_for_reply(icmp_sock, *target_interval, icmp_pkt_size, pkt_interval, 1011 wait_for_reply(sockset, *target_interval, icmp_pkt_size, pkt_interval,
934 target_interval, sender_id, table, packets, number_of_targets, 1012 target_interval, sender_id, table, packets, number_of_targets,
935 program_state); 1013 program_state);
936 } 1014 }
@@ -938,9 +1016,9 @@ static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval,
938 if (targets_alive(number_of_targets, program_state->targets_down) || 1016 if (targets_alive(number_of_targets, program_state->targets_down) ||
939 get_timevaldiff_to_now(prog_start) < max_completion_time || 1017 get_timevaldiff_to_now(prog_start) < max_completion_time ||
940 !(mode == MODE_HOSTCHECK && program_state->targets_down)) { 1018 !(mode == MODE_HOSTCHECK && program_state->targets_down)) {
941 wait_for_reply(icmp_sock, *pkt_interval * number_of_targets, icmp_pkt_size, 1019 wait_for_reply(sockset, *pkt_interval * number_of_targets, icmp_pkt_size, pkt_interval,
942 pkt_interval, target_interval, sender_id, table, packets, 1020 target_interval, sender_id, table, packets, number_of_targets,
943 number_of_targets, program_state); 1021 program_state);
944 } 1022 }
945 } 1023 }
946 1024
@@ -970,7 +1048,7 @@ static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval,
970 if (targets_alive(number_of_targets, program_state->targets_down) || 1048 if (targets_alive(number_of_targets, program_state->targets_down) ||
971 get_timevaldiff_to_now(prog_start) < max_completion_time || 1049 get_timevaldiff_to_now(prog_start) < max_completion_time ||
972 !(mode == MODE_HOSTCHECK && program_state->targets_down)) { 1050 !(mode == MODE_HOSTCHECK && program_state->targets_down)) {
973 wait_for_reply(icmp_sock, final_wait, icmp_pkt_size, pkt_interval, target_interval, 1051 wait_for_reply(sockset, final_wait, icmp_pkt_size, pkt_interval, target_interval,
974 sender_id, table, packets, number_of_targets, program_state); 1052 sender_id, table, packets, number_of_targets, program_state);
975 } 1053 }
976 } 1054 }
@@ -986,10 +1064,11 @@ static void run_checks(unsigned short icmp_pkt_size, unsigned int *pkt_interval,
986 * both: 1064 * both:
987 * icmp echo reply : the rest 1065 * icmp echo reply : the rest
988 */ 1066 */
989static int wait_for_reply(int sock, const time_t time_interval, unsigned short icmp_pkt_size, 1067static int wait_for_reply(check_icmp_socket_set sockset, const time_t time_interval,
990 unsigned int *pkt_interval, unsigned int *target_interval, 1068 unsigned short icmp_pkt_size, unsigned int *pkt_interval,
991 uint16_t sender_id, ping_target **table, const unsigned short packets, 1069 unsigned int *target_interval, uint16_t sender_id, ping_target **table,
992 const unsigned short number_of_targets, check_icmp_state *program_state) { 1070 const unsigned short packets, const unsigned short number_of_targets,
1071 check_icmp_state *program_state) {
993 union icmp_packet packet; 1072 union icmp_packet packet;
994 if (!(packet.buf = malloc(icmp_pkt_size))) { 1073 if (!(packet.buf = malloc(icmp_pkt_size))) {
995 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size); 1074 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size);
@@ -1022,25 +1101,25 @@ static int wait_for_reply(int sock, const time_t time_interval, unsigned short i
1022 time_t loop_time_interval = per_pkt_wait; 1101 time_t loop_time_interval = per_pkt_wait;
1023 1102
1024 /* reap responses until we hit a timeout */ 1103 /* reap responses until we hit a timeout */
1025 ssize_t n = recvfrom_wto(sock, buf, sizeof(buf), (struct sockaddr *)&resp_addr, 1104 recvfrom_wto_wrapper recv_foo =
1026 &loop_time_interval, &packet_received_timestamp); 1105 recvfrom_wto(sockset, buf, sizeof(buf), (struct sockaddr *)&resp_addr,
1027 if (!n) { 1106 &loop_time_interval, &packet_received_timestamp);
1107 if (!recv_foo.received) {
1028 if (debug > 1) { 1108 if (debug > 1) {
1029 printf("recvfrom_wto() timed out during a %ld usecs wait\n", per_pkt_wait); 1109 printf("recvfrom_wto() timed out during a %ld usecs wait\n", per_pkt_wait);
1030 } 1110 }
1031 continue; /* timeout for this one, so keep trying */ 1111 continue; /* timeout for this one, so keep trying */
1032 } 1112 }
1033 1113
1034 if (n < 0) { 1114 if (recv_foo.received < 0) {
1035 if (debug) { 1115 if (debug) {
1036 printf("recvfrom_wto() returned errors\n"); 1116 printf("recvfrom_wto() returned errors\n");
1037 } 1117 }
1038 free(packet.buf); 1118 free(packet.buf);
1039 return (int)n; 1119 return (int)recv_foo.received;
1040 } 1120 }
1041 1121
1042 // FIXME: with ipv6 we don't have an ip header here 1122 if (recv_foo.recv_proto != AF_INET6) {
1043 if (address_family != AF_INET6) {
1044 ip_header = (union ip_hdr *)buf; 1123 ip_header = (union ip_hdr *)buf;
1045 1124
1046 if (debug > 1) { 1125 if (debug > 1) {
@@ -1053,38 +1132,21 @@ static int wait_for_reply(int sock, const time_t time_interval, unsigned short i
1053 } 1132 }
1054 } 1133 }
1055 1134
1056 /* obsolete. alpha on tru64 provides the necessary defines, but isn't broken */ 1135 int hlen = (recv_foo.recv_proto == AF_INET6) ? 0 : ip_header->ip.ip_hl << 2;
1057 /* #if defined( __alpha__ ) && __STDC__ && !defined( __GLIBC__ ) */ 1136
1058 /* alpha headers are decidedly broken. Using an ansi compiler, 1137 if (recv_foo.received < (hlen + ICMP_MINLEN)) {
1059 * they provide ip_vhl instead of ip_hl and ip_v, so we mask
1060 * off the bottom 4 bits */
1061 /* hlen = (ip->ip_vhl & 0x0f) << 2; */
1062 /* #else */
1063 int hlen = (address_family == AF_INET6) ? 0 : ip_header->ip.ip_hl << 2;
1064 /* #endif */
1065
1066 if (n < (hlen + ICMP_MINLEN)) {
1067 char address[INET6_ADDRSTRLEN]; 1138 char address[INET6_ADDRSTRLEN];
1068 parse_address(&resp_addr, address, sizeof(address)); 1139 parse_address(&resp_addr, address, sizeof(address));
1069 crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n", n, 1140 crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n",
1070 hlen + icmp_pkt_size, address); 1141 recv_foo.received, hlen + icmp_pkt_size, address);
1071 } 1142 }
1072 /* else if(debug) { */
1073 /* printf("ip header size: %u, packet size: %u (expected %u, %u)\n", */
1074 /* hlen, ntohs(ip->ip_len) - hlen, */
1075 /* sizeof(struct ip), icmp_pkt_size); */
1076 /* } */
1077
1078 /* check the response */ 1143 /* check the response */
1079
1080 memcpy(packet.buf, buf + hlen, icmp_pkt_size); 1144 memcpy(packet.buf, buf + hlen, icmp_pkt_size);
1081 /* address_family == AF_INET6 ? sizeof(struct icmp6_hdr)
1082 : sizeof(struct icmp));*/
1083 1145
1084 if ((address_family == PF_INET && 1146 if ((recv_foo.recv_proto == AF_INET &&
1085 (ntohs(packet.icp->icmp_id) != sender_id || packet.icp->icmp_type != ICMP_ECHOREPLY || 1147 (ntohs(packet.icp->icmp_id) != sender_id || packet.icp->icmp_type != ICMP_ECHOREPLY ||
1086 ntohs(packet.icp->icmp_seq) >= number_of_targets * packets)) || 1148 ntohs(packet.icp->icmp_seq) >= number_of_targets * packets)) ||
1087 (address_family == PF_INET6 && 1149 (recv_foo.recv_proto == AF_INET6 &&
1088 (ntohs(packet.icp6->icmp6_id) != sender_id || 1150 (ntohs(packet.icp6->icmp6_id) != sender_id ||
1089 packet.icp6->icmp6_type != ICMP6_ECHO_REPLY || 1151 packet.icp6->icmp6_type != ICMP6_ECHO_REPLY ||
1090 ntohs(packet.icp6->icmp6_seq) >= number_of_targets * packets))) { 1152 ntohs(packet.icp6->icmp6_seq) >= number_of_targets * packets))) {
@@ -1101,7 +1163,7 @@ static int wait_for_reply(int sock, const time_t time_interval, unsigned short i
1101 /* this is indeed a valid response */ 1163 /* this is indeed a valid response */
1102 ping_target *target; 1164 ping_target *target;
1103 struct icmp_ping_data data; 1165 struct icmp_ping_data data;
1104 if (address_family == PF_INET) { 1166 if (address_family == AF_INET) {
1105 memcpy(&data, packet.icp->icmp_data, sizeof(data)); 1167 memcpy(&data, packet.icp->icmp_data, sizeof(data));
1106 if (debug > 2) { 1168 if (debug > 2) {
1107 printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", sizeof(data), 1169 printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", sizeof(data),
@@ -1171,7 +1233,7 @@ static int wait_for_reply(int sock, const time_t time_interval, unsigned short i
1171 char address[INET6_ADDRSTRLEN]; 1233 char address[INET6_ADDRSTRLEN];
1172 parse_address(&resp_addr, address, sizeof(address)); 1234 parse_address(&resp_addr, address, sizeof(address));
1173 1235
1174 switch (address_family) { 1236 switch (recv_foo.recv_proto) {
1175 case AF_INET: { 1237 case AF_INET: {
1176 printf("%0.3f ms rtt from %s, incoming ttl: %u, max: %0.3f, min: %0.3f\n", 1238 printf("%0.3f ms rtt from %s, incoming ttl: %u, max: %0.3f, min: %0.3f\n",
1177 (float)tdiff / 1000, address, ip_header->ip.ip_ttl, 1239 (float)tdiff / 1000, address, ip_header->ip.ip_ttl,
@@ -1191,23 +1253,14 @@ static int wait_for_reply(int sock, const time_t time_interval, unsigned short i
1191} 1253}
1192 1254
1193/* the ping functions */ 1255/* the ping functions */
1194static int send_icmp_ping(const int sock, ping_target *host, const unsigned short icmp_pkt_size, 1256static int send_icmp_ping(const check_icmp_socket_set sockset, ping_target *host,
1195 const uint16_t sender_id, check_icmp_state *program_state) { 1257 const unsigned short icmp_pkt_size, const uint16_t sender_id,
1196 if (sock == -1) { 1258 check_icmp_state *program_state) {
1197 errno = 0; 1259 void *buf = calloc(1, icmp_pkt_size);
1198 crash("Attempt to send on bogus socket");
1199 return -1;
1200 }
1201
1202 void *buf = NULL;
1203
1204 if (!buf) { 1260 if (!buf) {
1205 if (!(buf = malloc(icmp_pkt_size))) { 1261 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size);
1206 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size); 1262 return -1; /* might be reached if we're in debug mode */
1207 return -1; /* might be reached if we're in debug mode */
1208 }
1209 } 1263 }
1210 memset(buf, 0, icmp_pkt_size);
1211 1264
1212 struct timeval current_time; 1265 struct timeval current_time;
1213 if ((gettimeofday(&current_time, NULL)) == -1) { 1266 if ((gettimeofday(&current_time, NULL)) == -1) {
@@ -1221,7 +1274,7 @@ static int send_icmp_ping(const int sock, ping_target *host, const unsigned shor
1221 1274
1222 socklen_t addrlen; 1275 socklen_t addrlen;
1223 1276
1224 if (address_family == AF_INET) { 1277 if (host->address.ss_family == AF_INET) {
1225 struct icmp *icp = (struct icmp *)buf; 1278 struct icmp *icp = (struct icmp *)buf;
1226 addrlen = sizeof(struct sockaddr_in); 1279 addrlen = sizeof(struct sockaddr_in);
1227 1280
@@ -1235,11 +1288,14 @@ static int send_icmp_ping(const int sock, ping_target *host, const unsigned shor
1235 icp->icmp_cksum = icmp_checksum((uint16_t *)buf, (size_t)icmp_pkt_size); 1288 icp->icmp_cksum = icmp_checksum((uint16_t *)buf, (size_t)icmp_pkt_size);
1236 1289
1237 if (debug > 2) { 1290 if (debug > 2) {
1291 char address[INET6_ADDRSTRLEN];
1292 parse_address((&host->address), address, sizeof(address));
1293
1238 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", 1294 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n",
1239 sizeof(data), ntohs(icp->icmp_id), ntohs(icp->icmp_seq), icp->icmp_cksum, 1295 sizeof(data), ntohs(icp->icmp_id), ntohs(icp->icmp_seq), icp->icmp_cksum,
1240 host->name); 1296 address);
1241 } 1297 }
1242 } else { 1298 } else if (host->address.ss_family == AF_INET6) {
1243 struct icmp6_hdr *icp6 = (struct icmp6_hdr *)buf; 1299 struct icmp6_hdr *icp6 = (struct icmp6_hdr *)buf;
1244 addrlen = sizeof(struct sockaddr_in6); 1300 addrlen = sizeof(struct sockaddr_in6);
1245 1301
@@ -1253,10 +1309,16 @@ static int send_icmp_ping(const int sock, ping_target *host, const unsigned shor
1253 // let checksum be calculated automatically 1309 // let checksum be calculated automatically
1254 1310
1255 if (debug > 2) { 1311 if (debug > 2) {
1256 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", 1312 char address[INET6_ADDRSTRLEN];
1313 parse_address((&host->address), address, sizeof(address));
1314
1315 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to target %s\n",
1257 sizeof(data), ntohs(icp6->icmp6_id), ntohs(icp6->icmp6_seq), icp6->icmp6_cksum, 1316 sizeof(data), ntohs(icp6->icmp6_id), ntohs(icp6->icmp6_seq), icp6->icmp6_cksum,
1258 host->name); 1317 address);
1259 } 1318 }
1319 } else {
1320 // unknown address family
1321 crash("unknown address family in ", __func__);
1260 } 1322 }
1261 1323
1262 struct iovec iov; 1324 struct iovec iov;
@@ -1266,7 +1328,7 @@ static int send_icmp_ping(const int sock, ping_target *host, const unsigned shor
1266 1328
1267 struct msghdr hdr; 1329 struct msghdr hdr;
1268 memset(&hdr, 0, sizeof(hdr)); 1330 memset(&hdr, 0, sizeof(hdr));
1269 hdr.msg_name = (struct sockaddr *)&host->saddr_in; 1331 hdr.msg_name = (struct sockaddr *)&host->address;
1270 hdr.msg_namelen = addrlen; 1332 hdr.msg_namelen = addrlen;
1271 hdr.msg_iov = &iov; 1333 hdr.msg_iov = &iov;
1272 hdr.msg_iovlen = 1; 1334 hdr.msg_iovlen = 1;
@@ -1274,19 +1336,29 @@ static int send_icmp_ping(const int sock, ping_target *host, const unsigned shor
1274 errno = 0; 1336 errno = 0;
1275 1337
1276 long int len; 1338 long int len;
1277/* MSG_CONFIRM is a linux thing and only available on linux kernels >= 2.3.15, see send(2) */ 1339 /* MSG_CONFIRM is a linux thing and only available on linux kernels >= 2.3.15, see send(2) */
1340 if (host->address.ss_family == AF_INET) {
1278#ifdef MSG_CONFIRM 1341#ifdef MSG_CONFIRM
1279 len = sendmsg(sock, &hdr, MSG_CONFIRM); 1342 len = sendmsg(sockset.socket4, &hdr, MSG_CONFIRM);
1280#else 1343#else
1281 len = sendmsg(sock, &hdr, 0); 1344 len = sendmsg(sockset.socket4, &hdr, 0);
1282#endif 1345#endif
1346 } else if (host->address.ss_family == AF_INET6) {
1347#ifdef MSG_CONFIRM
1348 len = sendmsg(sockset.socket6, &hdr, MSG_CONFIRM);
1349#else
1350 len = sendmsg(sockset.socket6, &hdr, 0);
1351#endif
1352 } else {
1353 assert(false);
1354 }
1283 1355
1284 free(buf); 1356 free(buf);
1285 1357
1286 if (len < 0 || (unsigned int)len != icmp_pkt_size) { 1358 if (len < 0 || (unsigned int)len != icmp_pkt_size) {
1287 if (debug) { 1359 if (debug) {
1288 char address[INET6_ADDRSTRLEN]; 1360 char address[INET6_ADDRSTRLEN];
1289 parse_address((&host->saddr_in), address, sizeof(address)); 1361 parse_address((&host->address), address, sizeof(address));
1290 printf("Failed to send ping to %s: %s\n", address, strerror(errno)); 1362 printf("Failed to send ping to %s: %s\n", address, strerror(errno));
1291 } 1363 }
1292 errno = 0; 1364 errno = 0;
@@ -1299,9 +1371,9 @@ static int send_icmp_ping(const int sock, ping_target *host, const unsigned shor
1299 return 0; 1371 return 0;
1300} 1372}
1301 1373
1302static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len, 1374static recvfrom_wto_wrapper recvfrom_wto(const check_icmp_socket_set sockset, void *buf,
1303 struct sockaddr *saddr, time_t *timeout, 1375 const unsigned int len, struct sockaddr *saddr,
1304 struct timeval *received_timestamp) { 1376 time_t *timeout, struct timeval *received_timestamp) {
1305#ifdef HAVE_MSGHDR_MSG_CONTROL 1377#ifdef HAVE_MSGHDR_MSG_CONTROL
1306 char ans_data[4096]; 1378 char ans_data[4096];
1307#endif // HAVE_MSGHDR_MSG_CONTROL 1379#endif // HAVE_MSGHDR_MSG_CONTROL
@@ -1309,11 +1381,16 @@ static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len,
1309 struct cmsghdr *chdr; 1381 struct cmsghdr *chdr;
1310#endif 1382#endif
1311 1383
1384 recvfrom_wto_wrapper result = {
1385 .received = 0,
1386 .recv_proto = AF_UNSPEC,
1387 };
1388
1312 if (!*timeout) { 1389 if (!*timeout) {
1313 if (debug) { 1390 if (debug) {
1314 printf("*timeout is not\n"); 1391 printf("*timeout is not\n");
1315 } 1392 }
1316 return 0; 1393 return result;
1317 } 1394 }
1318 1395
1319 struct timeval real_timeout; 1396 struct timeval real_timeout;
@@ -1327,13 +1404,21 @@ static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len,
1327 // Read fds for select with the socket 1404 // Read fds for select with the socket
1328 fd_set read_fds; 1405 fd_set read_fds;
1329 FD_ZERO(&read_fds); 1406 FD_ZERO(&read_fds);
1330 FD_SET(sock, &read_fds); 1407
1408 if (sockset.socket4 != -1) {
1409 FD_SET(sockset.socket4, &read_fds);
1410 }
1411 if (sockset.socket6 != -1) {
1412 FD_SET(sockset.socket6, &read_fds);
1413 }
1414
1415 int nfds = (sockset.socket4 > sockset.socket6 ? sockset.socket4 : sockset.socket6) + 1;
1331 1416
1332 struct timeval then; 1417 struct timeval then;
1333 gettimeofday(&then, NULL); 1418 gettimeofday(&then, NULL);
1334 1419
1335 errno = 0; 1420 errno = 0;
1336 int select_return = select(sock + 1, &read_fds, &dummy_write_fds, NULL, &real_timeout); 1421 int select_return = select(nfds, &read_fds, &dummy_write_fds, NULL, &real_timeout);
1337 if (select_return < 0) { 1422 if (select_return < 0) {
1338 crash("select() in recvfrom_wto"); 1423 crash("select() in recvfrom_wto");
1339 } 1424 }
@@ -1343,7 +1428,7 @@ static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len,
1343 *timeout = get_timevaldiff(then, now); 1428 *timeout = get_timevaldiff(then, now);
1344 1429
1345 if (!select_return) { 1430 if (!select_return) {
1346 return 0; /* timeout */ 1431 return result; /* timeout */
1347 } 1432 }
1348 1433
1349 unsigned int slen = sizeof(struct sockaddr_storage); 1434 unsigned int slen = sizeof(struct sockaddr_storage);
@@ -1364,7 +1449,18 @@ static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len,
1364#endif 1449#endif
1365 }; 1450 };
1366 1451
1367 ssize_t ret = recvmsg(sock, &hdr, 0); 1452 ssize_t ret;
1453 if (FD_ISSET(sockset.socket4, &read_fds)) {
1454 ret = recvmsg(sockset.socket4, &hdr, 0);
1455 result.recv_proto = AF_INET;
1456 } else if (FD_ISSET(sockset.socket6, &read_fds)) {
1457 ret = recvmsg(sockset.socket6, &hdr, 0);
1458 result.recv_proto = AF_INET6;
1459 } else {
1460 assert(false);
1461 }
1462
1463 result.received = ret;
1368 1464
1369#ifdef SO_TIMESTAMP 1465#ifdef SO_TIMESTAMP
1370 for (chdr = CMSG_FIRSTHDR(&hdr); chdr; chdr = CMSG_NXTHDR(&hdr, chdr)) { 1466 for (chdr = CMSG_FIRSTHDR(&hdr); chdr; chdr = CMSG_NXTHDR(&hdr, chdr)) {
@@ -1382,11 +1478,11 @@ static ssize_t recvfrom_wto(const int sock, void *buf, const unsigned int len,
1382 gettimeofday(tv, NULL); 1478 gettimeofday(tv, NULL);
1383#endif // SO_TIMESTAMP 1479#endif // SO_TIMESTAMP
1384 1480
1385 return (ret); 1481 return (result);
1386} 1482}
1387 1483
1388static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive, 1484static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive,
1389 check_icmp_threshold warn, check_icmp_threshold crit, const int icmp_sock, 1485 check_icmp_threshold warn, check_icmp_threshold crit,
1390 const unsigned short number_of_targets, check_icmp_state *program_state, 1486 const unsigned short number_of_targets, check_icmp_state *program_state,
1391 check_icmp_target_container host_list[], unsigned short number_of_hosts, 1487 check_icmp_target_container host_list[], unsigned short number_of_hosts,
1392 mp_check overall[static 1]) { 1488 mp_check overall[static 1]) {
@@ -1397,10 +1493,6 @@ static void finish(int sig, check_icmp_mode_switches modes, int min_hosts_alive,
1397 printf("finish(%d) called\n", sig); 1493 printf("finish(%d) called\n", sig);
1398 } 1494 }
1399 1495
1400 if (icmp_sock != -1) {
1401 close(icmp_sock);
1402 }
1403
1404 if (debug) { 1496 if (debug) {
1405 printf("icmp_sent: %u icmp_recv: %u icmp_lost: %u\n", program_state->icmp_sent, 1497 printf("icmp_sent: %u icmp_recv: %u icmp_lost: %u\n", program_state->icmp_sent,
1406 program_state->icmp_recv, program_state->icmp_lost); 1498 program_state->icmp_recv, program_state->icmp_lost);
@@ -1476,17 +1568,21 @@ static time_t get_timevaldiff_to_now(struct timeval earlier) {
1476} 1568}
1477 1569
1478static add_target_ip_wrapper add_target_ip(struct sockaddr_storage address) { 1570static add_target_ip_wrapper add_target_ip(struct sockaddr_storage address) {
1571 assert((address.ss_family == AF_INET) || (address.ss_family == AF_INET6));
1572
1479 if (debug) { 1573 if (debug) {
1480 char straddr[INET6_ADDRSTRLEN]; 1574 char straddr[INET6_ADDRSTRLEN];
1481 parse_address((struct sockaddr_storage *)&address, straddr, sizeof(straddr)); 1575 parse_address((&address), straddr, sizeof(straddr));
1482 printf("add_target_ip called with: %s\n", straddr); 1576 printf("add_target_ip called with: %s\n", straddr);
1483 } 1577 }
1484 struct sockaddr_in *sin; 1578 struct sockaddr_in *sin;
1485 struct sockaddr_in6 *sin6; 1579 struct sockaddr_in6 *sin6;
1486 if (address_family == AF_INET) { 1580 if (address.ss_family == AF_INET) {
1487 sin = (struct sockaddr_in *)&address; 1581 sin = (struct sockaddr_in *)&address;
1488 } else { 1582 } else if (address.ss_family == AF_INET6) {
1489 sin6 = (struct sockaddr_in6 *)&address; 1583 sin6 = (struct sockaddr_in6 *)&address;
1584 } else {
1585 assert(false);
1490 } 1586 }
1491 1587
1492 add_target_ip_wrapper result = { 1588 add_target_ip_wrapper result = {
@@ -1496,9 +1592,9 @@ static add_target_ip_wrapper add_target_ip(struct sockaddr_storage address) {
1496 1592
1497 /* disregard obviously stupid addresses 1593 /* disregard obviously stupid addresses
1498 * (I didn't find an ipv6 equivalent to INADDR_NONE) */ 1594 * (I didn't find an ipv6 equivalent to INADDR_NONE) */
1499 if (((address_family == AF_INET && 1595 if (((address.ss_family == AF_INET &&
1500 (sin->sin_addr.s_addr == INADDR_NONE || sin->sin_addr.s_addr == INADDR_ANY))) || 1596 (sin->sin_addr.s_addr == INADDR_NONE || sin->sin_addr.s_addr == INADDR_ANY))) ||
1501 (address_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) { 1597 (address.ss_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) {
1502 result.error_code = ERROR; 1598 result.error_code = ERROR;
1503 return result; 1599 return result;
1504 } 1600 }
@@ -1513,32 +1609,21 @@ static add_target_ip_wrapper add_target_ip(struct sockaddr_storage address) {
1513 crash("add_target_ip(%s): malloc(%lu) failed", straddr, sizeof(ping_target)); 1609 crash("add_target_ip(%s): malloc(%lu) failed", straddr, sizeof(ping_target));
1514 } 1610 }
1515 1611
1516 *target = ping_target_init(); 1612 ping_target_create_wrapper target_wrapper = ping_target_create(address);
1517 1613
1518 /* set the values. use calling name for output */ 1614 if (target_wrapper.errorcode == OK) {
1519 target->name = strdup(straddr); 1615 *target = target_wrapper.host;
1520 1616 result.target = target;
1521 /* fill out the sockaddr_storage struct */
1522 struct sockaddr_in *host_sin;
1523 struct sockaddr_in6 *host_sin6;
1524 if (address_family == AF_INET) {
1525 host_sin = (struct sockaddr_in *)&target->saddr_in;
1526 host_sin->sin_family = AF_INET;
1527 host_sin->sin_addr.s_addr = sin->sin_addr.s_addr;
1528 } else { 1617 } else {
1529 host_sin6 = (struct sockaddr_in6 *)&target->saddr_in; 1618 result.error_code = target_wrapper.errorcode;
1530 host_sin6->sin6_family = AF_INET6;
1531 memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr,
1532 sizeof host_sin6->sin6_addr.s6_addr);
1533 } 1619 }
1534 1620
1535 result.target = target;
1536
1537 return result; 1621 return result;
1538} 1622}
1539 1623
1540/* wrapper for add_target_ip */ 1624/* wrapper for add_target_ip */
1541static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode mode) { 1625static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode mode,
1626 sa_family_t enforced_proto) {
1542 if (debug > 0) { 1627 if (debug > 0) {
1543 printf("add_target called with argument %s\n", arg); 1628 printf("add_target called with argument %s\n", arg);
1544 } 1629 }
@@ -1548,30 +1633,31 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode
1548 struct sockaddr_in6 *sin6 = NULL; 1633 struct sockaddr_in6 *sin6 = NULL;
1549 int error_code = -1; 1634 int error_code = -1;
1550 1635
1551 switch (address_family) { 1636 switch (enforced_proto) {
1552 case -1: 1637 case AF_UNSPEC:
1553 /* -4 and -6 are not specified on cmdline */ 1638 /*
1554 address_family = AF_INET; 1639 * no enforced protocoll family
1640 * try to parse the address with each one
1641 */
1555 sin = (struct sockaddr_in *)&address_storage; 1642 sin = (struct sockaddr_in *)&address_storage;
1556 error_code = inet_pton(address_family, arg, &sin->sin_addr); 1643 error_code = inet_pton(AF_INET, arg, &sin->sin_addr);
1644 address_storage.ss_family = AF_INET;
1557 1645
1558 if (error_code != 1) { 1646 if (error_code != 1) {
1559 address_family = AF_INET6;
1560 sin6 = (struct sockaddr_in6 *)&address_storage; 1647 sin6 = (struct sockaddr_in6 *)&address_storage;
1561 error_code = inet_pton(address_family, arg, &sin6->sin6_addr); 1648 error_code = inet_pton(AF_INET6, arg, &sin6->sin6_addr);
1562 } 1649 address_storage.ss_family = AF_INET6;
1563 /* If we don't find any valid addresses, we still don't know the address_family */
1564 if (error_code != 1) {
1565 address_family = -1;
1566 } 1650 }
1567 break; 1651 break;
1568 case AF_INET: 1652 case AF_INET:
1569 sin = (struct sockaddr_in *)&address_storage; 1653 sin = (struct sockaddr_in *)&address_storage;
1570 error_code = inet_pton(address_family, arg, &sin->sin_addr); 1654 error_code = inet_pton(AF_INET, arg, &sin->sin_addr);
1655 address_storage.ss_family = AF_INET;
1571 break; 1656 break;
1572 case AF_INET6: 1657 case AF_INET6:
1573 sin6 = (struct sockaddr_in6 *)&address_storage; 1658 sin6 = (struct sockaddr_in6 *)&address_storage;
1574 error_code = inet_pton(address_family, arg, &sin6->sin6_addr); 1659 error_code = inet_pton(AF_INET, arg, &sin6->sin6_addr);
1660 address_storage.ss_family = AF_INET6;
1575 break; 1661 break;
1576 default: 1662 default:
1577 crash("Address family not supported"); 1663 crash("Address family not supported");
@@ -1580,9 +1666,11 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode
1580 add_target_wrapper result = { 1666 add_target_wrapper result = {
1581 .error_code = OK, 1667 .error_code = OK,
1582 .targets = NULL, 1668 .targets = NULL,
1669 .has_v4 = false,
1670 .has_v6 = false,
1583 }; 1671 };
1584 1672
1585 /* don't resolve if we don't have to */ 1673 // if error_code == 1 the address was a valid address parsed above
1586 if (error_code == 1) { 1674 if (error_code == 1) {
1587 /* don't add all ip's if we were given a specific one */ 1675 /* don't add all ip's if we were given a specific one */
1588 add_target_ip_wrapper targeted = add_target_ip(address_storage); 1676 add_target_ip_wrapper targeted = add_target_ip(address_storage);
@@ -1592,19 +1680,21 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode
1592 return result; 1680 return result;
1593 } 1681 }
1594 1682
1683 if (targeted.target->address.ss_family == AF_INET) {
1684 result.has_v4 = true;
1685 } else if (targeted.target->address.ss_family == AF_INET6) {
1686 result.has_v6 = true;
1687 } else {
1688 assert(false);
1689 }
1595 result.targets = targeted.target; 1690 result.targets = targeted.target;
1596 result.number_of_targets = 1; 1691 result.number_of_targets = 1;
1597 return result; 1692 return result;
1598 } 1693 }
1599 1694
1600 struct addrinfo hints; 1695 struct addrinfo hints = {};
1601 errno = 0; 1696 errno = 0;
1602 memset(&hints, 0, sizeof(hints)); 1697 hints.ai_family = enforced_proto;
1603 if (address_family == -1) {
1604 hints.ai_family = AF_UNSPEC;
1605 } else {
1606 hints.ai_family = address_family == AF_INET ? PF_INET : PF_INET6;
1607 }
1608 hints.ai_socktype = SOCK_RAW; 1698 hints.ai_socktype = SOCK_RAW;
1609 1699
1610 int error; 1700 int error;
@@ -1615,7 +1705,6 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode
1615 result.error_code = ERROR; 1705 result.error_code = ERROR;
1616 return result; 1706 return result;
1617 } 1707 }
1618 address_family = res->ai_family;
1619 1708
1620 /* possibly add all the IP's as targets */ 1709 /* possibly add all the IP's as targets */
1621 for (struct addrinfo *address = res; address != NULL; address = address->ai_next) { 1710 for (struct addrinfo *address = res; address != NULL; address = address->ai_next) {
@@ -1634,6 +1723,11 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode
1634 } else { 1723 } else {
1635 result.number_of_targets += ping_target_list_append(result.targets, tmp.target); 1724 result.number_of_targets += ping_target_list_append(result.targets, tmp.target);
1636 } 1725 }
1726 if (address->ai_family == AF_INET) {
1727 result.has_v4 = true;
1728 } else if (address->ai_family == AF_INET6) {
1729 result.has_v6 = true;
1730 }
1637 } 1731 }
1638 1732
1639 /* this is silly, but it works */ 1733 /* this is silly, but it works */
@@ -1652,11 +1746,11 @@ static add_target_wrapper add_target(char *arg, const check_icmp_execution_mode
1652 return result; 1746 return result;
1653} 1747}
1654 1748
1655static void set_source_ip(char *arg, const int icmp_sock) { 1749static void set_source_ip(char *arg, const int icmp_sock, sa_family_t addr_family) {
1656 struct sockaddr_in src; 1750 struct sockaddr_in src;
1657 1751
1658 memset(&src, 0, sizeof(src)); 1752 memset(&src, 0, sizeof(src));
1659 src.sin_family = address_family; 1753 src.sin_family = addr_family;
1660 if ((src.sin_addr.s_addr = inet_addr(arg)) == INADDR_NONE) { 1754 if ((src.sin_addr.s_addr = inet_addr(arg)) == INADDR_NONE) {
1661 src.sin_addr.s_addr = get_ip_address(arg); 1755 src.sin_addr.s_addr = get_ip_address(arg);
1662 } 1756 }
@@ -2026,7 +2120,8 @@ void print_usage(void) {
2026 printf(" %s [options] [-H] host1 host2 hostN\n", progname); 2120 printf(" %s [options] [-H] host1 host2 hostN\n", progname);
2027} 2121}
2028 2122
2029static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode) { 2123static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode,
2124 sa_family_t enforced_proto) {
2030 if (debug) { 2125 if (debug) {
2031 printf("add_host called with argument %s\n", arg); 2126 printf("add_host called with argument %s\n", arg);
2032 } 2127 }
@@ -2034,15 +2129,20 @@ static add_host_wrapper add_host(char *arg, check_icmp_execution_mode mode) {
2034 add_host_wrapper result = { 2129 add_host_wrapper result = {
2035 .error_code = OK, 2130 .error_code = OK,
2036 .host = check_icmp_target_container_init(), 2131 .host = check_icmp_target_container_init(),
2132 .has_v4 = false,
2133 .has_v6 = false,
2037 }; 2134 };
2038 2135
2039 add_target_wrapper targets = add_target(arg, mode); 2136 add_target_wrapper targets = add_target(arg, mode, enforced_proto);
2040 2137
2041 if (targets.error_code != OK) { 2138 if (targets.error_code != OK) {
2042 result.error_code = targets.error_code; 2139 result.error_code = targets.error_code;
2043 return result; 2140 return result;
2044 } 2141 }
2045 2142
2143 result.has_v4 = targets.has_v4;
2144 result.has_v6 = targets.has_v6;
2145
2046 result.host = check_icmp_target_container_init(); 2146 result.host = check_icmp_target_container_init();
2047 2147
2048 result.host.name = strdup(arg); 2148 result.host.name = strdup(arg);
@@ -2063,7 +2163,12 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
2063 2163
2064 mp_subcheck result = mp_subcheck_init(); 2164 mp_subcheck result = mp_subcheck_init();
2065 result = mp_set_subcheck_default_state(result, STATE_OK); 2165 result = mp_set_subcheck_default_state(result, STATE_OK);
2066 xasprintf(&result.output, "%s", target.name); 2166
2167 char address[INET6_ADDRSTRLEN];
2168 memset(address, 0, INET6_ADDRSTRLEN);
2169 parse_address(&target.address, address, sizeof(address));
2170
2171 xasprintf(&result.output, "%s", address);
2067 2172
2068 double packet_loss; 2173 double packet_loss;
2069 double rta; 2174 double rta;
@@ -2076,8 +2181,6 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
2076 /* up the down counter if not already counted */ 2181 /* up the down counter if not already counted */
2077 2182
2078 if (target.flags & FLAG_LOST_CAUSE) { 2183 if (target.flags & FLAG_LOST_CAUSE) {
2079 char address[INET6_ADDRSTRLEN];
2080 parse_address(&target.error_addr, address, sizeof(address));
2081 xasprintf(&result.output, "%s: %s @ %s", result.output, 2184 xasprintf(&result.output, "%s: %s @ %s", result.output,
2082 get_icmp_error_msg(target.icmp_type, target.icmp_code), address); 2185 get_icmp_error_msg(target.icmp_type, target.icmp_code), address);
2083 } else { /* not marked as lost cause, so we have no flags for it */ 2186 } else { /* not marked as lost cause, so we have no flags for it */
@@ -2159,7 +2262,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
2159 2262
2160 if (packet_loss < 100) { 2263 if (packet_loss < 100) {
2161 mp_perfdata pd_rta = perfdata_init(); 2264 mp_perfdata pd_rta = perfdata_init();
2162 xasprintf(&pd_rta.label, "%srta", target.name); 2265 xasprintf(&pd_rta.label, "%srta", address);
2163 pd_rta.uom = strdup("ms"); 2266 pd_rta.uom = strdup("ms");
2164 pd_rta.value = mp_create_pd_value(rta / 1000); 2267 pd_rta.value = mp_create_pd_value(rta / 1000);
2165 pd_rta.min = mp_create_pd_value(0); 2268 pd_rta.min = mp_create_pd_value(0);
@@ -2169,13 +2272,13 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
2169 mp_add_perfdata_to_subcheck(&sc_rta, pd_rta); 2272 mp_add_perfdata_to_subcheck(&sc_rta, pd_rta);
2170 2273
2171 mp_perfdata pd_rt_min = perfdata_init(); 2274 mp_perfdata pd_rt_min = perfdata_init();
2172 xasprintf(&pd_rt_min.label, "%srtmin", target.name); 2275 xasprintf(&pd_rt_min.label, "%srtmin", address);
2173 pd_rt_min.value = mp_create_pd_value(target.rtmin / 1000); 2276 pd_rt_min.value = mp_create_pd_value(target.rtmin / 1000);
2174 pd_rt_min.uom = strdup("ms"); 2277 pd_rt_min.uom = strdup("ms");
2175 mp_add_perfdata_to_subcheck(&sc_rta, pd_rt_min); 2278 mp_add_perfdata_to_subcheck(&sc_rta, pd_rt_min);
2176 2279
2177 mp_perfdata pd_rt_max = perfdata_init(); 2280 mp_perfdata pd_rt_max = perfdata_init();
2178 xasprintf(&pd_rt_max.label, "%srtmax", target.name); 2281 xasprintf(&pd_rt_max.label, "%srtmax", address);
2179 pd_rt_max.value = mp_create_pd_value(target.rtmax / 1000); 2282 pd_rt_max.value = mp_create_pd_value(target.rtmax / 1000);
2180 pd_rt_max.uom = strdup("ms"); 2283 pd_rt_max.uom = strdup("ms");
2181 mp_add_perfdata_to_subcheck(&sc_rta, pd_rt_max); 2284 mp_add_perfdata_to_subcheck(&sc_rta, pd_rt_max);
@@ -2198,7 +2301,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
2198 } 2301 }
2199 2302
2200 mp_perfdata pd_pl = perfdata_init(); 2303 mp_perfdata pd_pl = perfdata_init();
2201 xasprintf(&pd_pl.label, "%spl", target.name); 2304 xasprintf(&pd_pl.label, "%spl", address);
2202 pd_pl.uom = strdup("%"); 2305 pd_pl.uom = strdup("%");
2203 2306
2204 pd_pl.warn = mp_range_set_end(pd_pl.warn, mp_create_pd_value(warn.pl)); 2307 pd_pl.warn = mp_range_set_end(pd_pl.warn, mp_create_pd_value(warn.pl));
@@ -2226,7 +2329,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
2226 if (packet_loss < 100) { 2329 if (packet_loss < 100) {
2227 mp_perfdata pd_jitter = perfdata_init(); 2330 mp_perfdata pd_jitter = perfdata_init();
2228 pd_jitter.uom = strdup("ms"); 2331 pd_jitter.uom = strdup("ms");
2229 xasprintf(&pd_jitter.label, "%sjitter_avg", target.name); 2332 xasprintf(&pd_jitter.label, "%sjitter_avg", address);
2230 pd_jitter.value = mp_create_pd_value(target.jitter); 2333 pd_jitter.value = mp_create_pd_value(target.jitter);
2231 pd_jitter.warn = mp_range_set_end(pd_jitter.warn, mp_create_pd_value(warn.jitter)); 2334 pd_jitter.warn = mp_range_set_end(pd_jitter.warn, mp_create_pd_value(warn.jitter));
2232 pd_jitter.crit = mp_range_set_end(pd_jitter.crit, mp_create_pd_value(crit.jitter)); 2335 pd_jitter.crit = mp_range_set_end(pd_jitter.crit, mp_create_pd_value(crit.jitter));
@@ -2234,13 +2337,13 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
2234 2337
2235 mp_perfdata pd_jitter_min = perfdata_init(); 2338 mp_perfdata pd_jitter_min = perfdata_init();
2236 pd_jitter_min.uom = strdup("ms"); 2339 pd_jitter_min.uom = strdup("ms");
2237 xasprintf(&pd_jitter_min.label, "%sjitter_min", target.name); 2340 xasprintf(&pd_jitter_min.label, "%sjitter_min", address);
2238 pd_jitter_min.value = mp_create_pd_value(target.jitter_min); 2341 pd_jitter_min.value = mp_create_pd_value(target.jitter_min);
2239 mp_add_perfdata_to_subcheck(&sc_jitter, pd_jitter_min); 2342 mp_add_perfdata_to_subcheck(&sc_jitter, pd_jitter_min);
2240 2343
2241 mp_perfdata pd_jitter_max = perfdata_init(); 2344 mp_perfdata pd_jitter_max = perfdata_init();
2242 pd_jitter_max.uom = strdup("ms"); 2345 pd_jitter_max.uom = strdup("ms");
2243 xasprintf(&pd_jitter_max.label, "%sjitter_max", target.name); 2346 xasprintf(&pd_jitter_max.label, "%sjitter_max", address);
2244 pd_jitter_max.value = mp_create_pd_value(target.jitter_max); 2347 pd_jitter_max.value = mp_create_pd_value(target.jitter_max);
2245 mp_add_perfdata_to_subcheck(&sc_jitter, pd_jitter_max); 2348 mp_add_perfdata_to_subcheck(&sc_jitter, pd_jitter_max);
2246 } 2349 }
@@ -2262,7 +2365,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
2262 2365
2263 if (packet_loss < 100) { 2366 if (packet_loss < 100) {
2264 mp_perfdata pd_mos = perfdata_init(); 2367 mp_perfdata pd_mos = perfdata_init();
2265 xasprintf(&pd_mos.label, "%smos", target.name); 2368 xasprintf(&pd_mos.label, "%smos", address);
2266 pd_mos.value = mp_create_pd_value(mos); 2369 pd_mos.value = mp_create_pd_value(mos);
2267 pd_mos.warn = mp_range_set_end(pd_mos.warn, mp_create_pd_value(warn.mos)); 2370 pd_mos.warn = mp_range_set_end(pd_mos.warn, mp_create_pd_value(warn.mos));
2268 pd_mos.crit = mp_range_set_end(pd_mos.crit, mp_create_pd_value(crit.mos)); 2371 pd_mos.crit = mp_range_set_end(pd_mos.crit, mp_create_pd_value(crit.mos));
@@ -2288,7 +2391,7 @@ mp_subcheck evaluate_target(ping_target target, check_icmp_mode_switches modes,
2288 2391
2289 if (packet_loss < 100) { 2392 if (packet_loss < 100) {
2290 mp_perfdata pd_score = perfdata_init(); 2393 mp_perfdata pd_score = perfdata_init();
2291 xasprintf(&pd_score.label, "%sscore", target.name); 2394 xasprintf(&pd_score.label, "%sscore", address);
2292 pd_score.value = mp_create_pd_value(score); 2395 pd_score.value = mp_create_pd_value(score);
2293 pd_score.warn = mp_range_set_end(pd_score.warn, mp_create_pd_value(warn.score)); 2396 pd_score.warn = mp_range_set_end(pd_score.warn, mp_create_pd_value(warn.score));
2294 pd_score.crit = mp_range_set_end(pd_score.crit, mp_create_pd_value(crit.score)); 2397 pd_score.crit = mp_range_set_end(pd_score.crit, mp_create_pd_value(crit.score));
diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.c b/plugins-root/check_icmp.d/check_icmp_helpers.c
index a2b54c6a..47604952 100644
--- a/plugins-root/check_icmp.d/check_icmp_helpers.c
+++ b/plugins-root/check_icmp.d/check_icmp_helpers.c
@@ -1,7 +1,7 @@
1#include "./config.h" 1#include "./config.h"
2#include "states.h"
3#include <math.h> 2#include <math.h>
4#include <netinet/in.h> 3#include <netinet/in.h>
4#include <sys/socket.h>
5#include "./check_icmp_helpers.h" 5#include "./check_icmp_helpers.h"
6#include "../../plugins/netutils.h" 6#include "../../plugins/netutils.h"
7 7
@@ -38,7 +38,10 @@ check_icmp_config check_icmp_config_init() {
38 .pkt_interval = DEFAULT_PKT_INTERVAL, 38 .pkt_interval = DEFAULT_PKT_INTERVAL,
39 .target_interval = 0, 39 .target_interval = 0,
40 .number_of_packets = DEFAULT_NUMBER_OF_PACKETS, 40 .number_of_packets = DEFAULT_NUMBER_OF_PACKETS,
41
41 .source_ip = NULL, 42 .source_ip = NULL,
43 .need_v4 = false,
44 .need_v6 = false,
42 45
43 .sender_id = {}, 46 .sender_id = {},
44 47
@@ -71,68 +74,31 @@ check_icmp_state check_icmp_state_init() {
71 return tmp; 74 return tmp;
72} 75}
73 76
74ping_target_create_wrapper ping_target_create(char *name, struct sockaddr_storage *address) { 77ping_target_create_wrapper ping_target_create(struct sockaddr_storage address) {
75 struct sockaddr_in *sin;
76 struct sockaddr_in6 *sin6;
77 if (address_family == AF_INET) {
78 sin = (struct sockaddr_in *)address;
79 } else {
80 sin6 = (struct sockaddr_in6 *)address;
81 }
82
83 ping_target_create_wrapper result = { 78 ping_target_create_wrapper result = {
84 .errorcode = OK, 79 .errorcode = OK,
85 }; 80 };
86 81
82 struct sockaddr_storage *tmp_addr = &address;
83
87 /* disregard obviously stupid addresses 84 /* disregard obviously stupid addresses
88 * (I didn't find an ipv6 equivalent to INADDR_NONE) */ 85 * (I didn't find an ipv6 equivalent to INADDR_NONE) */
89 if (((address_family == AF_INET && 86 if (((tmp_addr->ss_family == AF_INET &&
90 (sin->sin_addr.s_addr == INADDR_NONE || sin->sin_addr.s_addr == INADDR_ANY))) || 87 (((struct sockaddr_in *)tmp_addr)->sin_addr.s_addr == INADDR_NONE ||
91 (address_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) { 88 ((struct sockaddr_in *)tmp_addr)->sin_addr.s_addr == INADDR_ANY))) ||
89 (tmp_addr->ss_family == AF_INET6 &&
90 (((struct sockaddr_in6 *)tmp_addr)->sin6_addr.s6_addr == in6addr_any.s6_addr))) {
92 result.errorcode = ERROR; 91 result.errorcode = ERROR;
93 return result; 92 return result;
94 } 93 }
95 94
96 // TODO: Maybe add the following back in as a sanity check for the config
97 // /* no point in adding two identical IP's, so don't. ;) */
98 // struct sockaddr_in *host_sin;
99 // struct sockaddr_in6 *host_sin6;
100 // struct rta_host *host = host_list;
101
102 // while (host) {
103 // host_sin = (struct sockaddr_in *)&host->saddr_in;
104 // host_sin6 = (struct sockaddr_in6 *)&host->saddr_in;
105
106 // if ((address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr) ||
107 // (address_family == AF_INET6 &&
108 // host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) {
109 // if (debug) {
110 // printf("Identical IP already exists. Not adding %s\n", name);
111 // }
112 // return -1;
113 // }
114 // host = host->next;
115 // }
116
117 /* add the fresh ip */ 95 /* add the fresh ip */
118 ping_target host = ping_target_init(); 96 ping_target target = ping_target_init();
119
120 /* set the values. use calling name for output */
121 host.name = strdup(name);
122 97
123 /* fill out the sockaddr_storage struct */ 98 /* fill out the sockaddr_storage struct */
124 if (address_family == AF_INET) { 99 target.address = address;
125 struct sockaddr_in *host_sin = (struct sockaddr_in *)&host.saddr_in;
126 host_sin->sin_family = AF_INET;
127 host_sin->sin_addr.s_addr = sin->sin_addr.s_addr;
128 } else {
129 struct sockaddr_in6 *host_sin6 = (struct sockaddr_in6 *)&host.saddr_in;
130 host_sin6->sin6_family = AF_INET6;
131 memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr,
132 sizeof host_sin6->sin6_addr.s6_addr);
133 }
134 100
135 result.host = host; 101 result.host = target;
136 102
137 return result; 103 return result;
138} 104}
diff --git a/plugins-root/check_icmp.d/check_icmp_helpers.h b/plugins-root/check_icmp.d/check_icmp_helpers.h
index 5f771635..713dd8ce 100644
--- a/plugins-root/check_icmp.d/check_icmp_helpers.h
+++ b/plugins-root/check_icmp.d/check_icmp_helpers.h
@@ -10,10 +10,10 @@
10#include <arpa/inet.h> 10#include <arpa/inet.h>
11 11
12typedef struct rta_host { 12typedef struct rta_host {
13 unsigned short id; /* id in **table, and icmp pkts */ 13 unsigned short id; /* id in **table, and icmp pkts */
14 char *name; /* arg used for adding this host */ 14 char *msg; /* icmp error message, if any */
15 char *msg; /* icmp error message, if any */ 15
16 struct sockaddr_storage saddr_in; /* the address of this host */ 16 struct sockaddr_storage address; /* the address of this host */
17 struct sockaddr_storage error_addr; /* stores address of error replies */ 17 struct sockaddr_storage error_addr; /* stores address of error replies */
18 time_t time_waited; /* total time waited, in usecs */ 18 time_t time_waited; /* total time waited, in usecs */
19 unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */ 19 unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */
@@ -59,7 +59,12 @@ typedef struct {
59 ping_target host; 59 ping_target host;
60} ping_target_create_wrapper; 60} ping_target_create_wrapper;
61 61
62ping_target_create_wrapper ping_target_create(char *name, struct sockaddr_storage *address); 62typedef struct {
63 int socket4;
64 int socket6;
65} check_icmp_socket_set;
66
67ping_target_create_wrapper ping_target_create(struct sockaddr_storage address);
63unsigned int ping_target_list_append(ping_target *list, ping_target *elem); 68unsigned int ping_target_list_append(ping_target *list, ping_target *elem);
64 69
65void check_icmp_timeout_handler(int, siginfo_t *, void *); 70void check_icmp_timeout_handler(int, siginfo_t *, void *);
diff --git a/plugins-root/check_icmp.d/config.h b/plugins-root/check_icmp.d/config.h
index aa33c991..8e9c96b2 100644
--- a/plugins-root/check_icmp.d/config.h
+++ b/plugins-root/check_icmp.d/config.h
@@ -63,7 +63,10 @@ typedef struct {
63 unsigned int pkt_interval; 63 unsigned int pkt_interval;
64 unsigned int target_interval; 64 unsigned int target_interval;
65 unsigned short number_of_packets; 65 unsigned short number_of_packets;
66
66 char *source_ip; 67 char *source_ip;
68 bool need_v4;
69 bool need_v6;
67 70
68 uint16_t sender_id; // PID of the main process, which is used as an ID in packets 71 uint16_t sender_id; // PID of the main process, which is used as an ID in packets
69 72