aboutsummaryrefslogtreecommitdiff
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.c93
1 files changed, 75 insertions, 18 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index 8b563e40..9ed12ba1 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -184,7 +184,7 @@ static u_int get_timevar(const char *);
static u_int get_timevaldiff(struct timeval *, struct timeval *);
static in_addr_t get_ip_address(const char *);
static int wait_for_reply(int, u_int);
-static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *);
+static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*);
static int send_icmp_ping(int, struct rta_host *);
static int get_threshold(char *str, threshold *th);
static void run_checks(void);
@@ -378,6 +378,9 @@ main(int argc, char **argv)
int icmp_sockerrno, udp_sockerrno, tcp_sockerrno;
int result;
struct rta_host *host;
+#ifdef SO_TIMESTAMP
+ int on = 1;
+#endif
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
@@ -402,6 +405,11 @@ main(int argc, char **argv)
/* now drop privileges (no effect if not setsuid or geteuid() == 0) */
setuid(getuid());
+#ifdef SO_TIMESTAMP
+ if(setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
+ if(debug) printf("Warning: no SO_TIMESTAMP support\n");
+#endif // SO_TIMESTAMP
+
/* POSIXLY_CORRECT might break things, so unset it (the portable way) */
environ = NULL;
@@ -462,13 +470,13 @@ main(int argc, char **argv)
/* parse the arguments */
for(i = 1; i < argc; i++) {
while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:s:i:b:I:l:m:")) != EOF) {
- long size;
+ unsigned short size;
switch(arg) {
case 'v':
debug++;
break;
case 'b':
- size = strtol(optarg,NULL,0);
+ size = (unsigned short)strtol(optarg,NULL,0);
if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) &&
size < MAX_PING_DATA) {
icmp_data_size = size;
@@ -518,10 +526,10 @@ main(int argc, char **argv)
break;
case 'V': /* version */
print_revision (progname, NP_VERSION);
- exit (STATE_OK);
+ exit (STATE_UNKNOWN);
case 'h': /* help */
print_help ();
- exit (STATE_OK);
+ exit (STATE_UNKNOWN);
}
}
}
@@ -727,7 +735,7 @@ wait_for_reply(int sock, u_int t)
/* reap responses until we hit a timeout */
n = recvfrom_wto(sock, buf, sizeof(buf),
- (struct sockaddr *)&resp_addr, &t);
+ (struct sockaddr *)&resp_addr, &t, &now);
if(!n) {
if(debug > 1) {
printf("recvfrom_wto() timed out during a %u usecs wait\n",
@@ -777,11 +785,11 @@ wait_for_reply(int sock, u_int t)
/* this is indeed a valid response */
memcpy(&data, icp.icmp_data, sizeof(data));
if (debug > 2)
- printf("ICMP echo-reply of len %u, id %u, seq %u, cksum 0x%X\n",
- sizeof(data), ntohs(icp.icmp_id), ntohs(icp.icmp_seq), icp.icmp_cksum);
+ printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n",
+ (unsigned long)sizeof(data), ntohs(icp.icmp_id),
+ ntohs(icp.icmp_seq), icp.icmp_cksum);
host = table[ntohs(icp.icmp_seq)/packets];
- gettimeofday(&now, &tz);
tdiff = get_timevaldiff(&data.stime, &now);
host->time_waited += tdiff;
@@ -823,6 +831,8 @@ send_icmp_ping(int sock, struct rta_host *host)
} packet = { NULL };
long int len;
struct icmp_ping_data data;
+ struct msghdr hdr;
+ struct iovec iov;
struct timeval tv;
struct sockaddr *addr;
@@ -855,11 +865,27 @@ send_icmp_ping(int sock, struct rta_host *host)
packet.icp->icmp_cksum = icmp_checksum(packet.cksum_in, icmp_pkt_size);
if (debug > 2)
- printf("Sending ICMP echo-request of len %u, id %u, seq %u, cksum 0x%X to host %s\n",
- sizeof(data), ntohs(packet.icp->icmp_id), ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum, host->name);
-
- len = sendto(sock, packet.buf, icmp_pkt_size, 0, (struct sockaddr *)addr,
- sizeof(struct sockaddr));
+ printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n",
+ (unsigned long)sizeof(data), ntohs(packet.icp->icmp_id),
+ ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum,
+ host->name);
+
+ memset(&iov, 0, sizeof(iov));
+ iov.iov_base = packet.buf;
+ iov.iov_len = icmp_pkt_size;
+
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.msg_name = addr;
+ hdr.msg_namelen = sizeof(struct sockaddr);
+ hdr.msg_iov = &iov;
+ hdr.msg_iovlen = 1;
+
+/* MSG_CONFIRM is a linux thing and only available on linux kernels >= 2.3.15, see send(2) */
+#ifdef MSG_CONFIRM
+ len = sendmsg(sock, &hdr, MSG_CONFIRM);
+#else
+ len = sendmsg(sock, &hdr, 0);
+#endif
if(len < 0 || (unsigned int)len != icmp_pkt_size) {
if(debug) printf("Failed to send ping to %s\n",
@@ -875,12 +901,18 @@ send_icmp_ping(int sock, struct rta_host *host)
static int
recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
- u_int *timo)
+ u_int *timo, struct timeval* tv)
{
u_int slen;
- int n;
+ int n, ret;
struct timeval to, then, now;
fd_set rd, wr;
+ char ans_data[4096];
+ struct msghdr hdr;
+ struct iovec iov;
+#ifdef SO_TIMESTAMP
+ struct cmsghdr* chdr;
+#endif
if(!*timo) {
if(debug) printf("*timo is not\n");
@@ -904,7 +936,32 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
slen = sizeof(struct sockaddr);
- return recvfrom(sock, buf, len, 0, saddr, &slen);
+ memset(&iov, 0, sizeof(iov));
+ iov.iov_base = buf;
+ iov.iov_len = len;
+
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.msg_name = saddr;
+ hdr.msg_namelen = slen;
+ hdr.msg_iov = &iov;
+ hdr.msg_iovlen = 1;
+ hdr.msg_control = ans_data;
+ hdr.msg_controllen = sizeof(ans_data);
+
+ ret = recvmsg(sock, &hdr, 0);
+#ifdef SO_TIMESTAMP
+ for(chdr = CMSG_FIRSTHDR(&hdr); chdr; chdr = CMSG_NXTHDR(&hdr, chdr)) {
+ if(chdr->cmsg_level == SOL_SOCKET
+ && chdr->cmsg_type == SO_TIMESTAMP
+ && chdr->cmsg_len >= CMSG_LEN(sizeof(struct timeval))) {
+ memcpy(tv, CMSG_DATA(chdr), sizeof(*tv));
+ break ;
+ }
+ }
+ if (!chdr)
+#endif // SO_TIMESTAMP
+ gettimeofday(tv, &tz);
+ return (ret);
}
static void
@@ -1183,7 +1240,7 @@ static u_int
get_timevar(const char *str)
{
char p, u, *ptr;
- unsigned int len;
+ size_t len;
u_int i, d; /* integer and decimal, respectively */
u_int factor = 1000; /* default to milliseconds */