diff options
Diffstat (limited to 'plugins-root')
| -rw-r--r-- | plugins-root/check_icmp.c | 89 |
1 files changed, 73 insertions, 16 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c index 8b563e40..f4208371 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,11 @@ 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 | (unsigned long)sizeof(data), ntohs(icp.icmp_id), |
| 790 | ntohs(icp.icmp_seq), icp.icmp_cksum); | ||
| 782 | 791 | ||
| 783 | host = table[ntohs(icp.icmp_seq)/packets]; | 792 | host = table[ntohs(icp.icmp_seq)/packets]; |
| 784 | gettimeofday(&now, &tz); | ||
| 785 | tdiff = get_timevaldiff(&data.stime, &now); | 793 | tdiff = get_timevaldiff(&data.stime, &now); |
| 786 | 794 | ||
| 787 | host->time_waited += tdiff; | 795 | host->time_waited += tdiff; |
| @@ -823,6 +831,8 @@ send_icmp_ping(int sock, struct rta_host *host) | |||
| 823 | } packet = { NULL }; | 831 | } packet = { NULL }; |
| 824 | long int len; | 832 | long int len; |
| 825 | struct icmp_ping_data data; | 833 | struct icmp_ping_data data; |
| 834 | struct msghdr hdr; | ||
| 835 | struct iovec iov; | ||
| 826 | struct timeval tv; | 836 | struct timeval tv; |
| 827 | struct sockaddr *addr; | 837 | struct sockaddr *addr; |
| 828 | 838 | ||
| @@ -855,11 +865,27 @@ send_icmp_ping(int sock, struct rta_host *host) | |||
| 855 | packet.icp->icmp_cksum = icmp_checksum(packet.cksum_in, icmp_pkt_size); | 865 | packet.icp->icmp_cksum = icmp_checksum(packet.cksum_in, icmp_pkt_size); |
| 856 | 866 | ||
| 857 | if (debug > 2) | 867 | if (debug > 2) |
| 858 | printf("Sending ICMP echo-request of len %u, id %u, seq %u, cksum 0x%X to host %s\n", | 868 | 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); | 869 | (unsigned long)sizeof(data), ntohs(packet.icp->icmp_id), |
| 860 | 870 | ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum, | |
| 861 | len = sendto(sock, packet.buf, icmp_pkt_size, 0, (struct sockaddr *)addr, | 871 | host->name); |
| 862 | sizeof(struct sockaddr)); | 872 | |
| 873 | memset(&iov, 0, sizeof(iov)); | ||
| 874 | iov.iov_base = packet.buf; | ||
| 875 | iov.iov_len = icmp_pkt_size; | ||
| 876 | |||
| 877 | memset(&hdr, 0, sizeof(hdr)); | ||
| 878 | hdr.msg_name = addr; | ||
| 879 | hdr.msg_namelen = sizeof(struct sockaddr); | ||
| 880 | hdr.msg_iov = &iov; | ||
| 881 | hdr.msg_iovlen = 1; | ||
| 882 | |||
| 883 | /* MSG_CONFIRM is a linux thing and only available on linux kernels >= 2.3.15, see send(2) */ | ||
| 884 | #ifdef MSG_CONFIRM | ||
| 885 | len = sendmsg(sock, &hdr, MSG_CONFIRM); | ||
| 886 | #else | ||
| 887 | len = sendmsg(sock, &hdr, 0); | ||
| 888 | #endif | ||
| 863 | 889 | ||
| 864 | if(len < 0 || (unsigned int)len != icmp_pkt_size) { | 890 | if(len < 0 || (unsigned int)len != icmp_pkt_size) { |
| 865 | if(debug) printf("Failed to send ping to %s\n", | 891 | if(debug) printf("Failed to send ping to %s\n", |
| @@ -875,12 +901,18 @@ send_icmp_ping(int sock, struct rta_host *host) | |||
| 875 | 901 | ||
| 876 | static int | 902 | static int |
| 877 | recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, | 903 | recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, |
| 878 | u_int *timo) | 904 | u_int *timo, struct timeval* tv) |
| 879 | { | 905 | { |
| 880 | u_int slen; | 906 | u_int slen; |
| 881 | int n; | 907 | int n, ret; |
| 882 | struct timeval to, then, now; | 908 | struct timeval to, then, now; |
| 883 | fd_set rd, wr; | 909 | fd_set rd, wr; |
| 910 | char ans_data[4096]; | ||
| 911 | struct msghdr hdr; | ||
| 912 | struct iovec iov; | ||
| 913 | #ifdef SO_TIMESTAMP | ||
| 914 | struct cmsghdr* chdr; | ||
| 915 | #endif | ||
| 884 | 916 | ||
| 885 | if(!*timo) { | 917 | if(!*timo) { |
| 886 | if(debug) printf("*timo is not\n"); | 918 | if(debug) printf("*timo is not\n"); |
| @@ -904,7 +936,32 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, | |||
| 904 | 936 | ||
| 905 | slen = sizeof(struct sockaddr); | 937 | slen = sizeof(struct sockaddr); |
| 906 | 938 | ||
| 907 | return recvfrom(sock, buf, len, 0, saddr, &slen); | 939 | memset(&iov, 0, sizeof(iov)); |
| 940 | iov.iov_base = buf; | ||
| 941 | iov.iov_len = len; | ||
| 942 | |||
| 943 | memset(&hdr, 0, sizeof(hdr)); | ||
| 944 | hdr.msg_name = saddr; | ||
| 945 | hdr.msg_namelen = slen; | ||
| 946 | hdr.msg_iov = &iov; | ||
| 947 | hdr.msg_iovlen = 1; | ||
| 948 | hdr.msg_control = ans_data; | ||
| 949 | hdr.msg_controllen = sizeof(ans_data); | ||
| 950 | |||
| 951 | ret = recvmsg(sock, &hdr, 0); | ||
| 952 | #ifdef SO_TIMESTAMP | ||
| 953 | for(chdr = CMSG_FIRSTHDR(&hdr); chdr; chdr = CMSG_NXTHDR(&hdr, chdr)) { | ||
| 954 | if(chdr->cmsg_level == SOL_SOCKET | ||
| 955 | && chdr->cmsg_type == SO_TIMESTAMP | ||
| 956 | && chdr->cmsg_len >= CMSG_LEN(sizeof(struct timeval))) { | ||
| 957 | memcpy(tv, CMSG_DATA(chdr), sizeof(*tv)); | ||
| 958 | break ; | ||
| 959 | } | ||
| 960 | } | ||
| 961 | if (!chdr) | ||
| 962 | #endif // SO_TIMESTAMP | ||
| 963 | gettimeofday(tv, &tz); | ||
| 964 | return (ret); | ||
| 908 | } | 965 | } |
| 909 | 966 | ||
| 910 | static void | 967 | static void |
| @@ -1183,7 +1240,7 @@ static u_int | |||
| 1183 | get_timevar(const char *str) | 1240 | get_timevar(const char *str) |
| 1184 | { | 1241 | { |
| 1185 | char p, u, *ptr; | 1242 | char p, u, *ptr; |
| 1186 | unsigned int len; | 1243 | size_t len; |
| 1187 | u_int i, d; /* integer and decimal, respectively */ | 1244 | u_int i, d; /* integer and decimal, respectively */ |
| 1188 | u_int factor = 1000; /* default to milliseconds */ | 1245 | u_int factor = 1000; /* default to milliseconds */ |
| 1189 | 1246 | ||
