]> git.decadent.org.uk Git - odhcp6c.git/commitdiff
Merge pull request #44 from bwhacks/alignment-fixes
authorSteven Barth <steven@midlink.org>
Sun, 31 Jan 2016 15:18:16 +0000 (16:18 +0100)
committerSteven Barth <steven@midlink.org>
Sun, 31 Jan 2016 15:18:16 +0000 (16:18 +0100)
Alignment fixes

src/dhcpv6.c
src/odhcp6c.c
src/odhcp6c.h
src/ra.c
src/script.c

index c5f11f13141dfeb87c4eff4ddb82890ae49b16c2..3e128bcfa151c1001d56ccd6661b3eb880bbfc77 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,12 +815,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;
@@ -1027,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)) {
@@ -1044,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;
index 59f6390801152d82264e3a45516e8979a8ca5a4e..ba568bd4499acd962e975edebc7ace89561bcfef 100644 (file)
@@ -570,8 +570,9 @@ static struct odhcp6c_entry* odhcp6c_find_entry(enum odhcp6c_state state, const
        uint8_t *start = odhcp6c_get_state(state, &len);
 
        for (struct odhcp6c_entry *c = (struct odhcp6c_entry*)start;
-                       (uint8_t*)c < &start[len] && &c->auxtarget[c->auxlen] <= &start[len];
-                       c = (struct odhcp6c_entry*)(&c->auxtarget[c->auxlen]))
+                       (uint8_t*)c < &start[len] &&
+                       (uint8_t*)odhcp6c_next_entry(c) <= &start[len];
+                       c = odhcp6c_next_entry(c))
                if (!memcmp(c, new, cmplen) && !memcmp(c->auxtarget, new->auxtarget, new->auxlen))
                        return c;
 
@@ -604,10 +605,10 @@ bool odhcp6c_update_entry(enum odhcp6c_state state, struct odhcp6c_entry *new,
                        x->t2 = new->t2;
                        x->iaid = new->iaid;
                } else {
-                       odhcp6c_add_state(state, new, sizeof(*new) + new->auxlen);
+                       odhcp6c_add_state(state, new, odhcp6c_entry_size(new));
                }
        } else if (x) {
-               odhcp6c_remove_state(state, ((uint8_t*)x) - start, sizeof(*x) + x->auxlen);
+               odhcp6c_remove_state(state, ((uint8_t*)x) - start, odhcp6c_entry_size(x));
        }
        return true;
 }
@@ -618,7 +619,8 @@ static void odhcp6c_expire_list(enum odhcp6c_state state, uint32_t elapsed)
        size_t len;
        uint8_t *start = odhcp6c_get_state(state, &len);
        for (struct odhcp6c_entry *c = (struct odhcp6c_entry*)start;
-                       (uint8_t*)c < &start[len] && &c->auxtarget[c->auxlen] <= &start[len];
+                       (uint8_t*)c < &start[len] &&
+                       (uint8_t*)odhcp6c_next_entry(c) <= &start[len];
                        ) {
                if (c->t1 < elapsed)
                        c->t1 = 0;
@@ -641,10 +643,10 @@ static void odhcp6c_expire_list(enum odhcp6c_state state, uint32_t elapsed)
                        c->valid -= elapsed;
 
                if (!c->valid) {
-                       odhcp6c_remove_state(state, ((uint8_t*)c) - start, sizeof(*c) + c->auxlen);
+                       odhcp6c_remove_state(state, ((uint8_t*)c) - start, odhcp6c_entry_size(c));
                        start = odhcp6c_get_state(state, &len);
                } else {
-                       c = (struct odhcp6c_entry*)(&c->auxtarget[c->auxlen]);
+                       c = odhcp6c_next_entry(c);
                }
        }
 }
index 928f82f32e1004502ecaf2b61e8439af9e9716d5..08a816f4446dd893d89db315bf6f8932200ab2b8 100644 (file)
@@ -18,6 +18,7 @@
 
 #define _unused __attribute__((unused))
 #define _packed __attribute__((packed))
+#define __aligned(n) __attribute__((aligned(n)))
 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
 
@@ -302,6 +303,14 @@ struct odhcp6c_entry {
        uint8_t auxtarget[];
 };
 
+// Include padding after auxtarget to align the next entry
+#define odhcp6c_entry_size(entry) \
+       (sizeof(struct odhcp6c_entry) + (((entry)->auxlen + 3) & ~3))
+
+#define odhcp6c_next_entry(entry) \
+       ((struct odhcp6c_entry *)((uint8_t *)(entry) + odhcp6c_entry_size(entry)))
+
+
 struct odhcp6c_request_prefix {
        uint32_t iaid;
        uint16_t length;
index 1c121e63e3f8153064886293b3b8d5bcc72533b0..dd5962a29e750dba87bd39c33664e8e531efc7d5 100644 (file)
--- a/src/ra.c
+++ b/src/ra.c
@@ -274,7 +274,8 @@ bool ra_process(void)
 {
        bool found = false;
        bool changed = false;
-       uint8_t buf[1500], cmsg_buf[128];
+       uint8_t buf[1500] __aligned(4);
+       uint8_t cmsg_buf[128] __aligned(__alignof__(struct cmsghdr));
        struct nd_router_advert *adv = (struct nd_router_advert*)buf;
        struct odhcp6c_entry *entry = alloca(sizeof(*entry) + 256);
        const struct in6_addr any = IN6ADDR_ANY_INIT;
@@ -444,8 +445,9 @@ bool ra_process(void)
                        size_t ra_dns_len;
                        uint8_t *start = odhcp6c_get_state(states[i], &ra_dns_len);
                        for (struct odhcp6c_entry *c = (struct odhcp6c_entry*)start;
-                                               (uint8_t*)c < &start[ra_dns_len] && &c->auxtarget[c->auxlen] <= &start[ra_dns_len];
-                                               c = (struct odhcp6c_entry*)(&c->auxtarget[c->auxlen]))
+                                               (uint8_t*)c < &start[ra_dns_len] &&
+                                               (uint8_t*)odhcp6c_next_entry(c) <= &start[ra_dns_len];
+                                               c = odhcp6c_next_entry(c))
                                if (IN6_ARE_ADDR_EQUAL(&c->router, &from.sin6_addr) &&
                                                c->valid > router_valid)
                                        c->valid = router_valid;
index b20e94c9460c92ae45312bf48436ad73e0dd2d89..fdc050bbccb6d5f02ce24c594af2d0d0a3e6c6de 100644 (file)
@@ -220,8 +220,9 @@ static void search_to_env(const char *name, const uint8_t *start, size_t len)
        *c++ = '=';
 
        for (struct odhcp6c_entry *e = (struct odhcp6c_entry*)start;
-                               (uint8_t*)e < &start[len] && &e->auxtarget[e->auxlen] <= &start[len];
-                               e = (struct odhcp6c_entry*)(&e->auxtarget[e->auxlen])) {
+                               (uint8_t*)e < &start[len] &&
+                               (uint8_t*)odhcp6c_next_entry(e) <= &start[len];
+                               e = odhcp6c_next_entry(e)) {
                c = mempcpy(c, e->auxtarget, e->auxlen);
                *c++ = ' ';
        }