]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Alterative ipv6 masking to work round alignment issues
authorNick Porter <nick@portercomputing.co.uk>
Wed, 4 Sep 2024 08:26:31 +0000 (09:26 +0100)
committerNick Porter <nick@portercomputing.co.uk>
Wed, 4 Sep 2024 08:37:05 +0000 (09:37 +0100)
src/lib/util/inet.c

index c1f206feed1046511c5d7eb58c2cf0c853f7418d..82f1b87746856c63fed8ba4bef97c5308254766b 100644 (file)
@@ -166,9 +166,9 @@ static struct in_addr fr_inaddr_mask(struct in_addr const *ipaddr, uint8_t prefi
  */
 static struct in6_addr fr_in6addr_mask(struct in6_addr const *ipaddr, uint8_t prefix)
 {
-       uint64_t const *p = (uint64_t const *) ipaddr;
        uint64_t addr;                                  /* Needed for alignment */
        uint64_t ret[2], *o = ret;
+       uint8_t i = 0;
 
        if (prefix > 128) prefix = 128;
 
@@ -177,16 +177,30 @@ static struct in6_addr fr_in6addr_mask(struct in6_addr const *ipaddr, uint8_t pr
 
        if (prefix >= 64) {
                prefix -= 64;
-               memcpy(&addr, p, sizeof(addr));         /* Needed for aligned access (ubsan) */
+               addr = (uint64_t)ipaddr->s6_addr[i] |
+                       ((uint64_t)ipaddr->s6_addr[i + 1] << 8) |
+                       ((uint64_t)ipaddr->s6_addr[i + 2] << 16) |
+                       ((uint64_t)ipaddr->s6_addr[i + 3] << 24) |
+                       ((uint64_t)ipaddr->s6_addr[i + 4] << 32) |
+                       ((uint64_t)ipaddr->s6_addr[i + 5] << 40) |
+                       ((uint64_t)ipaddr->s6_addr[i + 6] << 48) |
+                       ((uint64_t)ipaddr->s6_addr[i + 7] << 56);
                *o++ = 0xffffffffffffffffULL & addr;    /* lhs portion masked */
-               p++;
+               i += 8;
        } else {
                ret[1] = 0;                             /* rhs portion zeroed */
        }
 
        /* Max left shift is 63 else we get overflow */
        if (prefix > 0) {
-               memcpy(&addr, p, sizeof(addr));         /* Needed for aligned access (ubsan) */
+               addr = (uint64_t)ipaddr->s6_addr[i] |
+                       ((uint64_t)ipaddr->s6_addr[i + 1] << 8) |
+                       ((uint64_t)ipaddr->s6_addr[i + 2] << 16) |
+                       ((uint64_t)ipaddr->s6_addr[i + 3] << 24) |
+                       ((uint64_t)ipaddr->s6_addr[i + 4] << 32) |
+                       ((uint64_t)ipaddr->s6_addr[i + 5] << 40) |
+                       ((uint64_t)ipaddr->s6_addr[i + 6] << 48) |
+                       ((uint64_t)ipaddr->s6_addr[i + 7] << 56);
                *o = htonll(~((uint64_t)(0x0000000000000001ULL << (64 - prefix)) - 1)) & addr;
        } else {
                *o = 0;