diff options
Diffstat (limited to 'plugins-root')
-rw-r--r-- | plugins-root/check_icmp.c | 75 |
1 files changed, 62 insertions, 13 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 8b563e40..44c6826c 100644 --- a/plugins-root/check_icmp.c +++ b/plugins-root/check_icmp.c | |||
@@ -184,7 +184,7 @@ static u_int get_timevar(const char *); | |||
184 | static u_int get_timevaldiff(struct timeval *, struct timeval *); | 184 | static u_int get_timevaldiff(struct timeval *, struct timeval *); |
185 | static in_addr_t get_ip_address(const char *); | 185 | static in_addr_t get_ip_address(const char *); |
186 | static int wait_for_reply(int, u_int); | 186 | static int wait_for_reply(int, u_int); |
187 | static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *); | 187 | static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*); |
188 | static int send_icmp_ping(int, struct rta_host *); | 188 | static int send_icmp_ping(int, struct rta_host *); |
189 | static int get_threshold(char *str, threshold *th); | 189 | static int get_threshold(char *str, threshold *th); |
190 | static void run_checks(void); | 190 | static void run_checks(void); |
@@ -378,6 +378,9 @@ main(int argc, char **argv) | |||
378 | int icmp_sockerrno, udp_sockerrno, tcp_sockerrno; | 378 | int icmp_sockerrno, udp_sockerrno, tcp_sockerrno; |
379 | int result; | 379 | int result; |
380 | struct rta_host *host; | 380 | struct rta_host *host; |
381 | #ifdef SO_TIMESTAMP | ||
382 | int on = 1; | ||
383 | #endif | ||
381 | 384 | ||
382 | setlocale (LC_ALL, ""); | 385 | setlocale (LC_ALL, ""); |
383 | bindtextdomain (PACKAGE, LOCALEDIR); | 386 | bindtextdomain (PACKAGE, LOCALEDIR); |
@@ -402,6 +405,11 @@ main(int argc, char **argv) | |||
402 | /* now drop privileges (no effect if not setsuid or geteuid() == 0) */ | 405 | /* now drop privileges (no effect if not setsuid or geteuid() == 0) */ |
403 | setuid(getuid()); | 406 | setuid(getuid()); |
404 | 407 | ||
408 | #ifdef SO_TIMESTAMP | ||
409 | if(setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) | ||
410 | if(debug) printf("Warning: no SO_TIMESTAMP support\n"); | ||
411 | #endif // SO_TIMESTAMP | ||
412 | |||
405 | /* POSIXLY_CORRECT might break things, so unset it (the portable way) */ | 413 | /* POSIXLY_CORRECT might break things, so unset it (the portable way) */ |
406 | environ = NULL; | 414 | environ = NULL; |
407 | 415 | ||
@@ -462,13 +470,13 @@ main(int argc, char **argv) | |||
462 | /* parse the arguments */ | 470 | /* parse the arguments */ |
463 | for(i = 1; i < argc; i++) { | 471 | for(i = 1; i < argc; i++) { |
464 | while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:s:i:b:I:l:m:")) != EOF) { | 472 | while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:s:i:b:I:l:m:")) != EOF) { |
465 | long size; | 473 | unsigned short size; |
466 | switch(arg) { | 474 | switch(arg) { |
467 | case 'v': | 475 | case 'v': |
468 | debug++; | 476 | debug++; |
469 | break; | 477 | break; |
470 | case 'b': | 478 | case 'b': |
471 | size = strtol(optarg,NULL,0); | 479 | size = (unsigned short)strtol(optarg,NULL,0); |
472 | if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && | 480 | if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && |
473 | size < MAX_PING_DATA) { | 481 | size < MAX_PING_DATA) { |
474 | icmp_data_size = size; | 482 | icmp_data_size = size; |
@@ -727,7 +735,7 @@ wait_for_reply(int sock, u_int t) | |||
727 | 735 | ||
728 | /* reap responses until we hit a timeout */ | 736 | /* reap responses until we hit a timeout */ |
729 | n = recvfrom_wto(sock, buf, sizeof(buf), | 737 | n = recvfrom_wto(sock, buf, sizeof(buf), |
730 | (struct sockaddr *)&resp_addr, &t); | 738 | (struct sockaddr *)&resp_addr, &t, &now); |
731 | if(!n) { | 739 | if(!n) { |
732 | if(debug > 1) { | 740 | if(debug > 1) { |
733 | printf("recvfrom_wto() timed out during a %u usecs wait\n", | 741 | printf("recvfrom_wto() timed out during a %u usecs wait\n", |
@@ -777,11 +785,10 @@ wait_for_reply(int sock, u_int t) | |||
777 | /* this is indeed a valid response */ | 785 | /* this is indeed a valid response */ |
778 | memcpy(&data, icp.icmp_data, sizeof(data)); | 786 | memcpy(&data, icp.icmp_data, sizeof(data)); |
779 | if (debug > 2) | 787 | if (debug > 2) |
780 | printf("ICMP echo-reply of len %u, id %u, seq %u, cksum 0x%X\n", | 788 | printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", |
781 | sizeof(data), ntohs(icp.icmp_id), ntohs(icp.icmp_seq), icp.icmp_cksum); | 789 | sizeof(data), ntohs(icp.icmp_id), ntohs(icp.icmp_seq), icp.icmp_cksum); |
782 | 790 | ||
783 | host = table[ntohs(icp.icmp_seq)/packets]; | 791 | host = table[ntohs(icp.icmp_seq)/packets]; |
784 | gettimeofday(&now, &tz); | ||
785 | tdiff = get_timevaldiff(&data.stime, &now); | 792 | tdiff = get_timevaldiff(&data.stime, &now); |
786 | 793 | ||
787 | host->time_waited += tdiff; | 794 | host->time_waited += tdiff; |
@@ -823,6 +830,8 @@ send_icmp_ping(int sock, struct rta_host *host) | |||
823 | } packet = { NULL }; | 830 | } packet = { NULL }; |
824 | long int len; | 831 | long int len; |
825 | struct icmp_ping_data data; | 832 | struct icmp_ping_data data; |
833 | struct msghdr hdr; | ||
834 | struct iovec iov; | ||
826 | struct timeval tv; | 835 | struct timeval tv; |
827 | struct sockaddr *addr; | 836 | struct sockaddr *addr; |
828 | 837 | ||
@@ -855,11 +864,20 @@ send_icmp_ping(int sock, struct rta_host *host) | |||
855 | packet.icp->icmp_cksum = icmp_checksum(packet.cksum_in, icmp_pkt_size); | 864 | packet.icp->icmp_cksum = icmp_checksum(packet.cksum_in, icmp_pkt_size); |
856 | 865 | ||
857 | if (debug > 2) | 866 | if (debug > 2) |
858 | printf("Sending ICMP echo-request of len %u, id %u, seq %u, cksum 0x%X to host %s\n", | 867 | printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", |
859 | sizeof(data), ntohs(packet.icp->icmp_id), ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum, host->name); | 868 | sizeof(data), ntohs(packet.icp->icmp_id), ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum, host->name); |
860 | 869 | ||
861 | len = sendto(sock, packet.buf, icmp_pkt_size, 0, (struct sockaddr *)addr, | 870 | memset(&iov, 0, sizeof(iov)); |
862 | sizeof(struct sockaddr)); | 871 | iov.iov_base = packet.buf; |
872 | iov.iov_len = icmp_pkt_size; | ||
873 | |||
874 | memset(&hdr, 0, sizeof(hdr)); | ||
875 | hdr.msg_name = addr; | ||
876 | hdr.msg_namelen = sizeof(struct sockaddr); | ||
877 | hdr.msg_iov = &iov; | ||
878 | hdr.msg_iovlen = 1; | ||
879 | |||
880 | len = sendmsg(sock, &hdr, MSG_CONFIRM); | ||
863 | 881 | ||
864 | if(len < 0 || (unsigned int)len != icmp_pkt_size) { | 882 | if(len < 0 || (unsigned int)len != icmp_pkt_size) { |
865 | if(debug) printf("Failed to send ping to %s\n", | 883 | if(debug) printf("Failed to send ping to %s\n", |
@@ -875,12 +893,18 @@ send_icmp_ping(int sock, struct rta_host *host) | |||
875 | 893 | ||
876 | static int | 894 | static int |
877 | recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, | 895 | recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, |
878 | u_int *timo) | 896 | u_int *timo, struct timeval* tv) |
879 | { | 897 | { |
880 | u_int slen; | 898 | u_int slen; |
881 | int n; | 899 | int n, ret; |
882 | struct timeval to, then, now; | 900 | struct timeval to, then, now; |
883 | fd_set rd, wr; | 901 | fd_set rd, wr; |
902 | char ans_data[4096]; | ||
903 | struct msghdr hdr; | ||
904 | struct iovec iov; | ||
905 | #ifdef SO_TIMESTAMP | ||
906 | struct cmsghdr* chdr; | ||
907 | #endif | ||
884 | 908 | ||
885 | if(!*timo) { | 909 | if(!*timo) { |
886 | if(debug) printf("*timo is not\n"); | 910 | if(debug) printf("*timo is not\n"); |
@@ -904,7 +928,32 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, | |||
904 | 928 | ||
905 | slen = sizeof(struct sockaddr); | 929 | slen = sizeof(struct sockaddr); |
906 | 930 | ||
907 | return recvfrom(sock, buf, len, 0, saddr, &slen); | 931 | memset(&iov, 0, sizeof(iov)); |
932 | iov.iov_base = buf; | ||
933 | iov.iov_len = len; | ||
934 | |||
935 | memset(&hdr, 0, sizeof(hdr)); | ||
936 | hdr.msg_name = saddr; | ||
937 | hdr.msg_namelen = slen; | ||
938 | hdr.msg_iov = &iov; | ||
939 | hdr.msg_iovlen = 1; | ||
940 | hdr.msg_control = ans_data; | ||
941 | hdr.msg_controllen = sizeof(ans_data); | ||
942 | |||
943 | ret = recvmsg(sock, &hdr, 0); | ||
944 | #ifdef SO_TIMESTAMP | ||
945 | for(chdr = CMSG_FIRSTHDR(&hdr); chdr; chdr = CMSG_NXTHDR(&hdr, chdr)) { | ||
946 | if(chdr->cmsg_level == SOL_SOCKET | ||
947 | && chdr->cmsg_type == SO_TIMESTAMP | ||
948 | && chdr->cmsg_len >= CMSG_LEN(sizeof(struct timeval))) { | ||
949 | memcpy(tv, CMSG_DATA(chdr), sizeof(*tv)); | ||
950 | break ; | ||
951 | } | ||
952 | } | ||
953 | if (!chdr) | ||
954 | #endif // SO_TIMESTAMP | ||
955 | gettimeofday(tv, &tz); | ||
956 | return (ret); | ||
908 | } | 957 | } |
909 | 958 | ||
910 | static void | 959 | static void |
@@ -1183,7 +1232,7 @@ static u_int | |||
1183 | get_timevar(const char *str) | 1232 | get_timevar(const char *str) |
1184 | { | 1233 | { |
1185 | char p, u, *ptr; | 1234 | char p, u, *ptr; |
1186 | unsigned int len; | 1235 | size_t len; |
1187 | u_int i, d; /* integer and decimal, respectively */ | 1236 | u_int i, d; /* integer and decimal, respectively */ |
1188 | u_int factor = 1000; /* default to milliseconds */ | 1237 | u_int factor = 1000; /* default to milliseconds */ |
1189 | 1238 | ||