From ecb466590600a2442d167c8b4b80d6c545e63134 Mon Sep 17 00:00:00 2001
From: Ben Hutchings <ben@decadent.org.uk>
Date: Thu, 28 Jan 2016 01:59:14 +0000
Subject: [PATCH] Fix unaligned 32-bit reads from DHCP packets

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 src/dhcpv6.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/src/dhcpv6.c b/src/dhcpv6.c
index 8a1231d..cbf6991 100644
--- a/src/dhcpv6.c
+++ b/src/dhcpv6.c
@@ -110,6 +110,14 @@ static uint8_t reconf_key[16];
 static unsigned int client_options = 0;
 
 
+static uint32_t ntohl_unaligned(const uint8_t *data)
+{
+	uint32_t buf;
+
+	memcpy(&buf, data, sizeof(buf));
+	return ntohl(buf);
+}
+
 int init_dhcpv6(const char *ifname, unsigned int options, int sol_timeout)
 {
 	client_options = options;
@@ -806,12 +814,12 @@ static int dhcpv6_handle_advert(enum dhcpv6_msg orig, const int rc,
 		} else if (otype == DHCPV6_OPT_RECONF_ACCEPT) {
 			cand.wants_reconfigure = true;
 		} else if (otype == DHCPV6_OPT_SOL_MAX_RT && olen == 4) {
-			uint32_t sol_max_rt = ntohl(*((uint32_t *)odata));
+			uint32_t sol_max_rt = ntohl_unaligned(odata);
 			if (sol_max_rt >= DHCPV6_SOL_MAX_RT_MIN &&
 					sol_max_rt <= DHCPV6_SOL_MAX_RT_MAX)
 				cand.sol_max_rt = sol_max_rt;
 		} else if (otype == DHCPV6_OPT_INF_MAX_RT && olen == 4) {
-			uint32_t inf_max_rt = ntohl(*((uint32_t *)odata));
+			uint32_t inf_max_rt = ntohl_unaligned(odata);
 			if (inf_max_rt >= DHCPV6_INF_MAX_RT_MIN &&
 					inf_max_rt <= DHCPV6_INF_MAX_RT_MAX)
 				cand.inf_max_rt = inf_max_rt;
@@ -1029,7 +1037,7 @@ static int dhcpv6_handle_reply(enum dhcpv6_msg orig, _unused const int rc,
 			} else if (otype == DHCPV6_OPT_SIP_SERVER_D) {
 				odhcp6c_add_state(STATE_SIP_FQDN, odata, olen);
 			} else if (otype == DHCPV6_OPT_INFO_REFRESH && olen >= 4) {
-				refresh = ntohl(*((uint32_t*)odata));
+				refresh = ntohl_unaligned(odata);
 				passthru = false;
 			} else if (otype == DHCPV6_OPT_AUTH) {
 				if (olen == -4 + sizeof(struct dhcpv6_auth_reconfigure)) {
@@ -1046,13 +1054,13 @@ static int dhcpv6_handle_reply(enum dhcpv6_msg orig, _unused const int rc,
 					odhcp6c_add_state(STATE_AFTR_NAME, odata, olen);
 				passthru = false;
 			} else if (otype == DHCPV6_OPT_SOL_MAX_RT && olen == 4) {
-				uint32_t sol_max_rt = ntohl(*((uint32_t *)odata));
+				uint32_t sol_max_rt = ntohl_unaligned(odata);
 				if (sol_max_rt >= DHCPV6_SOL_MAX_RT_MIN &&
 						sol_max_rt <= DHCPV6_SOL_MAX_RT_MAX)
 					dhcpv6_retx[DHCPV6_MSG_SOLICIT].max_timeo = sol_max_rt;
 				passthru = false;
 			} else if (otype == DHCPV6_OPT_INF_MAX_RT && olen == 4) {
-				uint32_t inf_max_rt = ntohl(*((uint32_t *)odata));
+				uint32_t inf_max_rt = ntohl_unaligned(odata);
 				if (inf_max_rt >= DHCPV6_INF_MAX_RT_MIN &&
 						inf_max_rt <= DHCPV6_INF_MAX_RT_MAX)
 					dhcpv6_retx[DHCPV6_MSG_INFO_REQ].max_timeo = inf_max_rt;
-- 
2.25.1