summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthieu Kermagoret <mkermagoret@merethis.com>2014-02-03 16:49:21 +0100
committerHolger Weiss <holger@zedat.fu-berlin.de>2014-11-28 16:23:27 +0100
commit5265fabeb98dc2af702a56f1a4b45627c3d4d93f (patch)
tree3b110e12f18d46e015a4b27fc09c3e117ce854b9
parent8b272a7f7baa7d743841da713a27284b0479d0e1 (diff)
downloadmonitoring-plugins-5265fabeb98dc2af702a56f1a4b45627c3d4d93f.tar.gz
Use kernel reception time on ICMP packets to compute rtt.
This commit uses the SO_TIMESTAMP feature of setsockopt to fetch kernel reception time of ICMP packets. This avoids invalid computations of rtt on machines with heavy load and/or heavy network traffic.
-rw-r--r--plugins-root/check_icmp.c55
1 files changed, 48 insertions, 7 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index 8b563e40..d2f637fd 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -184,7 +184,7 @@ static u_int get_timevar(const char *);
184static u_int get_timevaldiff(struct timeval *, struct timeval *); 184static u_int get_timevaldiff(struct timeval *, struct timeval *);
185static in_addr_t get_ip_address(const char *); 185static in_addr_t get_ip_address(const char *);
186static int wait_for_reply(int, u_int); 186static int wait_for_reply(int, u_int);
187static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *); 187static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*);
188static int send_icmp_ping(int, struct rta_host *); 188static int send_icmp_ping(int, struct rta_host *);
189static int get_threshold(char *str, threshold *th); 189static int get_threshold(char *str, threshold *th);
190static void run_checks(void); 190static void run_checks(void);
@@ -402,6 +402,12 @@ main(int argc, char **argv)
402 /* now drop privileges (no effect if not setsuid or geteuid() == 0) */ 402 /* now drop privileges (no effect if not setsuid or geteuid() == 0) */
403 setuid(getuid()); 403 setuid(getuid());
404 404
405#ifdef SO_TIMESTAMP
406 int on = 1;
407 if(setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
408 if(debug) printf("Warning: no SO_TIMESTAMP support\n");
409#endif // SO_TIMESTAMP
410
405 /* POSIXLY_CORRECT might break things, so unset it (the portable way) */ 411 /* POSIXLY_CORRECT might break things, so unset it (the portable way) */
406 environ = NULL; 412 environ = NULL;
407 413
@@ -727,7 +733,7 @@ wait_for_reply(int sock, u_int t)
727 733
728 /* reap responses until we hit a timeout */ 734 /* reap responses until we hit a timeout */
729 n = recvfrom_wto(sock, buf, sizeof(buf), 735 n = recvfrom_wto(sock, buf, sizeof(buf),
730 (struct sockaddr *)&resp_addr, &t); 736 (struct sockaddr *)&resp_addr, &t, &now);
731 if(!n) { 737 if(!n) {
732 if(debug > 1) { 738 if(debug > 1) {
733 printf("recvfrom_wto() timed out during a %u usecs wait\n", 739 printf("recvfrom_wto() timed out during a %u usecs wait\n",
@@ -781,7 +787,6 @@ wait_for_reply(int sock, u_int t)
781 sizeof(data), ntohs(icp.icmp_id), ntohs(icp.icmp_seq), icp.icmp_cksum); 787 sizeof(data), ntohs(icp.icmp_id), ntohs(icp.icmp_seq), icp.icmp_cksum);
782 788
783 host = table[ntohs(icp.icmp_seq)/packets]; 789 host = table[ntohs(icp.icmp_seq)/packets];
784 gettimeofday(&now, &tz);
785 tdiff = get_timevaldiff(&data.stime, &now); 790 tdiff = get_timevaldiff(&data.stime, &now);
786 791
787 host->time_waited += tdiff; 792 host->time_waited += tdiff;
@@ -858,8 +863,17 @@ send_icmp_ping(int sock, struct rta_host *host)
858 printf("Sending ICMP echo-request of len %u, id %u, seq %u, cksum 0x%X to host %s\n", 863 printf("Sending ICMP echo-request of len %u, 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); 864 sizeof(data), ntohs(packet.icp->icmp_id), ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum, host->name);
860 865
861 len = sendto(sock, packet.buf, icmp_pkt_size, 0, (struct sockaddr *)addr, 866 struct msghdr hdr;
862 sizeof(struct sockaddr)); 867 memset(&hdr, 0, sizeof(hdr));
868 hdr.msg_name = addr;
869 hdr.msg_namelen = sizeof(struct sockaddr);
870 struct iovec iov;
871 memset(&iov, 0, sizeof(iov));
872 iov.iov_base = packet.buf;
873 iov.iov_len = icmp_pkt_size;
874 hdr.msg_iov = &iov;
875 hdr.msg_iovlen = 1;
876 len = sendmsg(sock, &hdr, MSG_CONFIRM);
863 877
864 if(len < 0 || (unsigned int)len != icmp_pkt_size) { 878 if(len < 0 || (unsigned int)len != icmp_pkt_size) {
865 if(debug) printf("Failed to send ping to %s\n", 879 if(debug) printf("Failed to send ping to %s\n",
@@ -875,7 +889,7 @@ send_icmp_ping(int sock, struct rta_host *host)
875 889
876static int 890static int
877recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, 891recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
878 u_int *timo) 892 u_int *timo, struct timeval* tv)
879{ 893{
880 u_int slen; 894 u_int slen;
881 int n; 895 int n;
@@ -904,7 +918,34 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
904 918
905 slen = sizeof(struct sockaddr); 919 slen = sizeof(struct sockaddr);
906 920
907 return recvfrom(sock, buf, len, 0, saddr, &slen); 921 struct msghdr hdr;
922 memset(&hdr, 0, sizeof(hdr));
923 hdr.msg_name = saddr;
924 hdr.msg_namelen = slen;
925 struct iovec iov;
926 memset(&iov, 0, sizeof(iov));
927 iov.iov_base = buf;
928 iov.iov_len = len;
929 hdr.msg_iov = &iov;
930 hdr.msg_iovlen = 1;
931 char ans_data[4096];
932 hdr.msg_control = ans_data;
933 hdr.msg_controllen = sizeof(ans_data);
934 int ret = recvmsg(sock, &hdr, 0);
935#ifdef SO_TIMESTAMP
936 struct cmsghdr* chdr;
937 for(chdr = CMSG_FIRSTHDR(&hdr); chdr; chdr = CMSG_NXTHDR(&hdr, chdr)) {
938 if(chdr->cmsg_level == SOL_SOCKET
939 && chdr->cmsg_type == SO_TIMESTAMP
940 && chdr->cmsg_len >= CMSG_LEN(sizeof(struct timeval))) {
941 memcpy(tv, CMSG_DATA(chdr), sizeof(*tv));
942 break ;
943 }
944 }
945 if (!chdr)
946#endif // SO_TIMESTAMP
947 gettimeofday(tv, &tz);
948 return (ret);
908} 949}
909 950
910static void 951static void