From: Yu Watanabe Date: Tue, 23 Apr 2024 03:29:38 +0000 (+0900) Subject: in-addr-util: introduce in{4,6}_addr_prefix_intersect() X-Git-Tag: v256-rc1~34^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=21ae0b4b3cc82d4f63d4426ce9ff78167b69122c;p=thirdparty%2Fsystemd.git in-addr-util: introduce in{4,6}_addr_prefix_intersect() --- diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c index 82c8ff9a2d4..c077f0aa7db 100644 --- a/src/basic/in-addr-util.c +++ b/src/basic/in-addr-util.c @@ -194,58 +194,69 @@ int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_ return -EAFNOSUPPORT; } -int in_addr_prefix_intersect( - int family, - const union in_addr_union *a, +bool in4_addr_prefix_intersect( + const struct in_addr *a, unsigned aprefixlen, - const union in_addr_union *b, + const struct in_addr *b, unsigned bprefixlen) { - unsigned m; - assert(a); assert(b); - /* Checks whether there are any addresses that are in both networks */ + unsigned m = MIN3(aprefixlen, bprefixlen, (unsigned) (sizeof(struct in_addr) * 8)); + if (m == 0) + return true; /* Let's return earlier, to avoid shift by 32. */ - m = MIN(aprefixlen, bprefixlen); + uint32_t x = be32toh(a->s_addr ^ b->s_addr); + uint32_t n = 0xFFFFFFFFUL << (32 - m); + return (x & n) == 0; +} - if (family == AF_INET) { - uint32_t x, nm; +bool in6_addr_prefix_intersect( + const struct in6_addr *a, + unsigned aprefixlen, + const struct in6_addr *b, + unsigned bprefixlen) { - x = be32toh(a->in.s_addr ^ b->in.s_addr); - nm = m == 0 ? 0 : 0xFFFFFFFFUL << (32 - m); + assert(a); + assert(b); - return (x & nm) == 0; - } + unsigned m = MIN3(aprefixlen, bprefixlen, (unsigned) (sizeof(struct in6_addr) * 8)); + if (m == 0) + return true; - if (family == AF_INET6) { - unsigned i; + for (size_t i = 0; i < sizeof(struct in6_addr); i++) { + uint8_t x = a->s6_addr[i] ^ b->s6_addr[i]; + uint8_t n = m < 8 ? (0xFF << (8 - m)) : 0xFF; + if ((x & n) != 0) + return false; - if (m > 128) - m = 128; + if (m <= 8) + break; - for (i = 0; i < 16; i++) { - uint8_t x, nm; + m -= 8; + } - x = a->in6.s6_addr[i] ^ b->in6.s6_addr[i]; + return true; +} - if (m < 8) - nm = 0xFF << (8 - m); - else - nm = 0xFF; +int in_addr_prefix_intersect( + int family, + const union in_addr_union *a, + unsigned aprefixlen, + const union in_addr_union *b, + unsigned bprefixlen) { + + assert(a); + assert(b); - if ((x & nm) != 0) - return 0; + /* Checks whether there are any addresses that are in both networks. */ - if (m > 8) - m -= 8; - else - m = 0; - } + if (family == AF_INET) + return in4_addr_prefix_intersect(&a->in, aprefixlen, &b->in, bprefixlen); - return 1; - } + if (family == AF_INET6) + return in6_addr_prefix_intersect(&a->in6, aprefixlen, &b->in6, bprefixlen); return -EAFNOSUPPORT; } diff --git a/src/basic/in-addr-util.h b/src/basic/in-addr-util.h index 5c820c6ec6a..9cd0aca9a4e 100644 --- a/src/basic/in-addr-util.h +++ b/src/basic/in-addr-util.h @@ -61,7 +61,22 @@ bool in6_addr_is_ipv4_mapped_address(const struct in6_addr *a); bool in4_addr_equal(const struct in_addr *a, const struct in_addr *b); bool in6_addr_equal(const struct in6_addr *a, const struct in6_addr *b); int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_union *b); -int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen); +bool in4_addr_prefix_intersect( + const struct in_addr *a, + unsigned aprefixlen, + const struct in_addr *b, + unsigned bprefixlen); +bool in6_addr_prefix_intersect( + const struct in6_addr *a, + unsigned aprefixlen, + const struct in6_addr *b, + unsigned bprefixlen); +int in_addr_prefix_intersect( + int family, + const union in_addr_union *a, + unsigned aprefixlen, + const union in_addr_union *b, + unsigned bprefixlen); int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen); int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, uint64_t nth); int in_addr_random_prefix(int family, union in_addr_union *u, unsigned prefixlen_fixed_part, unsigned prefixlen);