From c11f63ff7eeb72ea220faec778e1b8bd6651b9f7 Mon Sep 17 00:00:00 2001
From: Holger Weiss <hweiss@users.sourceforge.net>
Date: Sat, 15 Sep 2007 11:55:12 +0000
Subject: Correct all instances of misaligned memory access.  This fixes bus
 erros on platforms which require alignment (such as SPARC and MIPS).

git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@1779 f882894a-f735-0410-b71e-b25c423dba1c

diff --git a/NEWS b/NEWS
index 7170b19..b687f6f 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,7 @@ This file documents the major additions and syntax changes between releases.
 	New check_dhcp -m/--mac option which allows for specifying the MAC
 	  address to use in the DHCP request
 	The check_dhcp -r and -s options now accept host names, too
+	Fix possible check_icmp bus errors on some (non-x86/AMD64) platforms
 
 1.4.9 4th June 2006
 	Inclusion of contrib/check_cluster2 as check_cluster with some improvements
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index 7f9160c..f0ba9d0 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -294,7 +294,7 @@ get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code)
 static int
 handle_random_icmp(struct icmp *p, struct sockaddr_in *addr)
 {
-	struct icmp *sent_icmp = NULL;
+	struct icmp sent_icmp;
 	struct rta_host *host = NULL;
 	unsigned char *ptr;
 
@@ -324,16 +324,16 @@ handle_random_icmp(struct icmp *p, struct sockaddr_in *addr)
 
 	/* might be for us. At least it holds the original package (according
 	 * to RFC 792). If it isn't, just ignore it */
-	sent_icmp = (struct icmp *)(ptr + 28);
-	if(sent_icmp->icmp_type != ICMP_ECHO || sent_icmp->icmp_id != pid ||
-	   sent_icmp->icmp_seq >= targets)
+	memcpy(&sent_icmp, ptr + 28, sizeof(sent_icmp));
+	if(sent_icmp.icmp_type != ICMP_ECHO || sent_icmp.icmp_id != pid ||
+	   sent_icmp.icmp_seq >= targets)
 	{
 		if(debug) printf("Packet is no response to a packet we sent\n");
 		return 0;
 	}
 
 	/* it is indeed a response for us */
-	host = table[sent_icmp->icmp_seq];
+	host = table[sent_icmp.icmp_seq];
 	if(debug) {
 		printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n",
 			   get_icmp_error_msg(p->icmp_type, p->icmp_code),
@@ -677,9 +677,9 @@ wait_for_reply(int sock, u_int t)
 	static char buf[4096];
 	struct sockaddr_in resp_addr;
 	struct ip *ip;
-	struct icmp *icp, *sent_icmp;
+	struct icmp icp;
 	struct rta_host *host;
-	struct icmp_ping_data *data;
+	struct icmp_ping_data data;
 	struct timeval wait_start, now;
 	u_int tdiff, i, per_pkt_wait;
 
@@ -741,32 +741,25 @@ wait_for_reply(int sock, u_int t)
 		/* } */
 
 		/* check the response */
-		icp = (struct icmp *)(buf + hlen);
-		sent_icmp = (struct icmp *)(buf + hlen + ICMP_MINLEN);
-		/* printf("buf: %p, icp: %p, distance: %u (expected %u)\n", */
-		/* 	   buf, icp, */
-		/* 	   (u_int)icp - (u_int)buf, hlen); */
-		/* printf("buf: %p, sent_icmp: %p, distance: %u (expected %u)\n", */
-		/* 	   buf, sent_icmp, */
-		/* 	   (u_int)sent_icmp - (u_int)buf, hlen + ICMP_MINLEN); */
-
-		if(icp->icmp_id != pid) {
-			handle_random_icmp(icp, &resp_addr);
+		memcpy(&icp, buf + hlen, sizeof(icp));
+
+		if(icp.icmp_id != pid) {
+			handle_random_icmp(&icp, &resp_addr);
 			continue;
 		}
 
-		if(icp->icmp_type != ICMP_ECHOREPLY || icp->icmp_seq >= targets) {
+		if(icp.icmp_type != ICMP_ECHOREPLY || icp.icmp_seq >= targets) {
 			if(debug > 2) printf("not a proper ICMP_ECHOREPLY\n");
-			handle_random_icmp(icp, &resp_addr);
+			handle_random_icmp(&icp, &resp_addr);
 			continue;
 		}
 
 		/* this is indeed a valid response */
-		data = (struct icmp_ping_data *)(icp->icmp_data);
+		memcpy(&data, icp.icmp_data, sizeof(data));
 
-		host = table[icp->icmp_seq];
+		host = table[icp.icmp_seq];
 		gettimeofday(&now, &tz);
-		tdiff = get_timevaldiff(&data->stime, &now);
+		tdiff = get_timevaldiff(&data.stime, &now);
 
 		host->time_waited += tdiff;
 		host->icmp_recv++;
@@ -796,14 +789,16 @@ wait_for_reply(int sock, u_int t)
 static int
 send_icmp_ping(int sock, struct rta_host *host)
 {
-	static char *buf = NULL; /* re-use so we prevent leaks */
+	static union {
+		char *buf; /* re-use so we prevent leaks */
+		struct icmp *icp;
+		u_short *cksum_in;
+	} packet = { NULL };
 	long int len;
-	struct icmp *icp;
-	struct icmp_ping_data *data;
+	struct icmp_ping_data data;
 	struct timeval tv;
 	struct sockaddr *addr;
 
-	
 	if(sock == -1) {
 		errno = 0;
 		crash("Attempt to send on bogus socket");
@@ -811,30 +806,28 @@ send_icmp_ping(int sock, struct rta_host *host)
 	}
 	addr = (struct sockaddr *)&host->saddr_in;
 
-	if(!buf) {
-		buf = (char *)malloc(icmp_pkt_size + sizeof(struct ip));
-		if(!buf) {
+	if(!packet.buf) {
+		if (!(packet.buf = malloc(icmp_pkt_size))) {
 			crash("send_icmp_ping(): failed to malloc %d bytes for send buffer",
 				  icmp_pkt_size);
 			return -1;	/* might be reached if we're in debug mode */
 		}
 	}
-	memset(buf, 0, icmp_pkt_size + sizeof(struct ip));
+	memset(packet.buf, 0, icmp_pkt_size);
 
 	if((gettimeofday(&tv, &tz)) == -1) return -1;
 
-	icp = (struct icmp *)buf;
-	icp->icmp_type = ICMP_ECHO;
-	icp->icmp_code = 0;
-	icp->icmp_cksum = 0;
-	icp->icmp_id = pid;
-	icp->icmp_seq = host->id;
-	data = (struct icmp_ping_data *)icp->icmp_data;
-	data->ping_id = 10; /* host->icmp.icmp_sent; */
-	memcpy(&data->stime, &tv, sizeof(struct timeval));
-	icp->icmp_cksum = icmp_checksum((u_short *)icp, icmp_pkt_size);
-
-	len = sendto(sock, buf, icmp_pkt_size, 0, (struct sockaddr *)addr,
+	data.ping_id = 10; /* host->icmp.icmp_sent; */
+	memcpy(&data.stime, &tv, sizeof(tv));
+	memcpy(&packet.icp->icmp_data, &data, sizeof(data));
+	packet.icp->icmp_type = ICMP_ECHO;
+	packet.icp->icmp_code = 0;
+	packet.icp->icmp_cksum = 0;
+	packet.icp->icmp_id = pid;
+	packet.icp->icmp_seq = host->id;
+	packet.icp->icmp_cksum = icmp_checksum(packet.cksum_in, icmp_pkt_size);
+
+	len = sendto(sock, packet.buf, icmp_pkt_size, 0, (struct sockaddr *)addr,
 				 sizeof(struct sockaddr));
 
 	if(len < 0 || (unsigned int)len != icmp_pkt_size) {
-- 
cgit v0.10-9-g596f

