]> git.decadent.org.uk Git - odhcp6c.git/blobdiff - src/dhcpv6.c
Fix alignment of hash buffer in dhcpv6_response_is_valid
[odhcp6c.git] / src / dhcpv6.c
index 08fe236f80db53b2ad785b87760778e38bed26eb..f91f2cf16b8c8ff6fe881310433b98b68e2d8780 100644 (file)
@@ -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;
@@ -577,7 +585,9 @@ int dhcpv6_request(enum dhcpv6_msg type)
                // Receive rounds
                for (; len < 0 && (round_start < round_end);
                                round_start = odhcp6c_get_milli_time()) {
-                       uint8_t buf[1536], cmsg_buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
+                       uint8_t buf[1536];
+                       uint8_t cmsg_buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]
+                               __aligned(__alignof__(struct cmsghdr));
                        struct iovec iov = {buf, sizeof(buf)};
                        struct sockaddr_in6 addr;
                        struct msghdr msg = {.msg_name = &addr, .msg_namelen = sizeof(addr),
@@ -692,7 +702,8 @@ static bool dhcpv6_response_is_valid(const void *buf, ssize_t len,
                                continue;
 
                        md5_ctx_t md5;
-                       uint8_t serverhash[16], secretbytes[64], hash[16];
+                       uint8_t serverhash[16], secretbytes[64];
+                       uint32_t hash[4];
                        memcpy(serverhash, r->key, sizeof(serverhash));
                        memset(r->key, 0, sizeof(r->key));
 
@@ -804,16 +815,17 @@ 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;
-               } else if (otype == DHCPV6_OPT_IA_PD && request_prefix) {
+               } else if (otype == DHCPV6_OPT_IA_PD && request_prefix &&
+                                       olen >= -4 + sizeof(struct dhcpv6_ia_hdr)) {
                        struct dhcpv6_ia_hdr *h = (struct dhcpv6_ia_hdr*)&odata[-4];
                        uint8_t *oend = odata + olen, *d;
                        dhcpv6_for_each_option(&h[1], oend, otype, olen, d) {
@@ -823,7 +835,8 @@ static int dhcpv6_handle_advert(enum dhcpv6_msg orig, const int rc,
                                        have_pd = p->prefix;
                                }
                        }
-               } else if (otype == DHCPV6_OPT_IA_NA) {
+               } else if (otype == DHCPV6_OPT_IA_NA &&
+                                       olen >= -4 + sizeof(struct dhcpv6_ia_hdr)) {
                        struct dhcpv6_ia_hdr *h = (struct dhcpv6_ia_hdr*)&odata[-4];
                        uint8_t *oend = odata + olen, *d;
                        dhcpv6_for_each_option(&h[1], oend, otype, olen, d)
@@ -1025,7 +1038,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)) {
@@ -1042,13 +1055,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;