From f69e0c8bcbc23f38bc2c7aaace389500a4f4f747 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Sun, 6 Mar 2022 14:28:26 +0000 Subject: [PATCH] network: Add function that counts the bit length of an addres Signed-off-by: Michael Tremer --- src/libloc/private.h | 14 ++++++++++++++ src/test-network.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/libloc/private.h b/src/libloc/private.h index 675e14b..6b43990 100644 --- a/src/libloc/private.h +++ b/src/libloc/private.h @@ -94,6 +94,20 @@ static inline struct in6_addr loc_prefix_to_bitmask(const unsigned int prefix) { return bitmask; } +static inline unsigned int loc_address_bit_length(const struct in6_addr* address) { + unsigned int length = 128; + + for (int octet = 0; octet <= 15; octet++) { + if (address->s6_addr[octet]) { + length -= __builtin_clz(address->s6_addr[octet]) - 24; + break; + } else + length -= 8; + } + + return length; +} + static inline struct in6_addr loc_address_and( const struct in6_addr* address, const struct in6_addr* bitmask) { struct in6_addr a; diff --git a/src/test-network.c b/src/test-network.c index 4582fbe..92088ee 100644 --- a/src/test-network.c +++ b/src/test-network.c @@ -25,6 +25,7 @@ #include #include #include +#include #include int main(int argc, char** argv) { @@ -311,6 +312,36 @@ int main(int argc, char** argv) { } loc_network_unref(network1); + const struct bit_length_test { + const char* network; + unsigned int bit_length; + } bit_length_tests[] = { + { "::/0", 0 }, + { "2001::/128", 126 }, + { NULL, 0, }, + }; + + for (const struct bit_length_test* t = bit_length_tests; t->network; t++) { + err = loc_network_new_from_string(ctx, &network1, t->network); + if (err) { + fprintf(stderr, "Could not create network %s: %m\n", t->network); + exit(EXIT_FAILURE); + } + + const struct in6_addr* addr = loc_network_get_first_address(network1); + + unsigned int bit_length = loc_address_bit_length(addr); + + if (bit_length != t->bit_length) { + printf("Bit length of %s didn't match: %u != %u\n", + t->network, t->bit_length, bit_length); + loc_network_unref(network1); + exit(EXIT_FAILURE); + } + + loc_network_unref(network1); + } + loc_unref(ctx); fclose(f); -- 2.39.2