]> git.ipfire.org Git - people/ms/libloc.git/commitdiff
address: Fix bit length calculation
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 22 Mar 2024 14:41:44 +0000 (14:41 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 22 Mar 2024 14:41:44 +0000 (14:41 +0000)
I have no idea what the previous version computed, but it wasn't the
right thing.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libloc/address.h

index f4c0ee330bc0df62b1dfcc4a2476800d081d2bc2..d6d7ca5a0bbdc2e58997759f3a90a1196b0030c0 100644 (file)
@@ -131,10 +131,30 @@ static inline struct in6_addr loc_prefix_to_bitmask(const unsigned int prefix) {
 }
 
 static inline unsigned int loc_address_bit_length(const struct in6_addr* address) {
+       unsigned int bitlength = 0;
+
        int octet = 0;
-       foreach_octet_in_address(octet, address) {
-               if (address->s6_addr[octet])
-                       return (15 - octet) * 8 + 32 - __builtin_clz(address->s6_addr[octet]);
+
+       // Initialize the bit length
+       if (IN6_IS_ADDR_V4MAPPED(address))
+               bitlength = 32;
+       else
+               bitlength = 128;
+
+       // Walk backwards until we find the first one
+       foreach_octet_in_address_reverse(octet, address) {
+               // Count all trailing zeroes
+               int trailing_zeroes = __builtin_ctz(address->s6_addr[octet]);
+
+               // We only have one byte
+               if (trailing_zeroes > 8)
+                       trailing_zeroes = 8;
+
+               // Remove any trailing zeroes from the total length
+               bitlength -= trailing_zeroes;
+
+               if (trailing_zeroes < 8)
+                       return bitlength;
        }
 
        return 0;