mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-27 02:20:12 +01:00
libnm-glib-aux: add nm_ip6_addr_get_subnet_id()
Add function nm_ip6_addr_get_subnet_id() to get the subnet ID of a IPv6 address.
This commit is contained in:
parent
4ed1d04aff
commit
dbc4ff0a1d
3 changed files with 86 additions and 0 deletions
|
|
@ -238,6 +238,42 @@ nm_ip6_addr_clear_host_address(struct in6_addr *dst, const struct in6_addr *src,
|
|||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_ip6_addr_get_subnet_id:
|
||||
* @addr: the IPv6 address
|
||||
* @plen: the prefix length
|
||||
*
|
||||
* Given an IPv6 address and a prefix length, returns the subnet ID,
|
||||
* defined as follows:
|
||||
*
|
||||
* | plen bits | (64 - plen) bits | 64 bits |
|
||||
* +-----------------+------------------+-------------------------------+
|
||||
* | prefix | subnet ID | interface ID |
|
||||
* +-----------------+------------------+-------------------------------+
|
||||
*
|
||||
* The prefix length must be a value between 0 and 64.
|
||||
*/
|
||||
guint64
|
||||
nm_ip6_addr_get_subnet_id(struct in6_addr *addr, guint8 plen)
|
||||
{
|
||||
int nbits = 64 - plen;
|
||||
guint64 res = 0;
|
||||
guint64 tmp;
|
||||
guint64 i;
|
||||
|
||||
g_return_val_if_fail(addr, 0);
|
||||
g_return_val_if_fail(plen <= 64, 0);
|
||||
|
||||
for (i = 0; i < 2 && nbits > 0; i++, nbits -= 32) {
|
||||
tmp = htonl(addr->s6_addr32[1 - i]);
|
||||
tmp = tmp & ((1ULL << NM_MIN(32U, (guint) nbits)) - 1);
|
||||
tmp = tmp << (32 * i);
|
||||
res += tmp;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
nm_ip6_addr_same_prefix_cmp(const struct in6_addr *addr_a,
|
||||
const struct in6_addr *addr_b,
|
||||
|
|
|
|||
|
|
@ -218,6 +218,8 @@ nm_ip4_addr_clear_host_address(in_addr_t addr, guint32 plen)
|
|||
const struct in6_addr *
|
||||
nm_ip6_addr_clear_host_address(struct in6_addr *dst, const struct in6_addr *src, guint32 plen);
|
||||
|
||||
guint64 nm_ip6_addr_get_subnet_id(struct in6_addr *addr, guint8 plen);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static inline int
|
||||
|
|
|
|||
|
|
@ -397,6 +397,53 @@ test_nm_ip4_addr_netmask_from_prefix(void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_nm_ip6_addr_get_subnet_id(void)
|
||||
{
|
||||
#define check_subnet_id(_addrstr, _plen, _subnet_id) \
|
||||
{ \
|
||||
struct in6_addr addr; \
|
||||
\
|
||||
addr = nmtst_inet6_from_string(_addrstr); \
|
||||
g_assert_cmpint(nm_ip6_addr_get_subnet_id(&addr, _plen), ==, _subnet_id); \
|
||||
}
|
||||
|
||||
check_subnet_id("aaaa:bbbb:cccc:ffff::", 64, 0);
|
||||
check_subnet_id("aaaa:bbbb:cccc:fffe::", 63, 0);
|
||||
check_subnet_id("aaaa:bbbb:cccc:ffff::", 63, 1);
|
||||
check_subnet_id("aaaa:bbbb:cccc:fffc::", 62, 0);
|
||||
check_subnet_id("aaaa:bbbb:cccc:fffd::", 62, 1);
|
||||
check_subnet_id("aaaa:bbbb:cccc:fffe::", 62, 2);
|
||||
check_subnet_id("aaaa:bbbb:cccc:ffff::", 62, 3);
|
||||
check_subnet_id("aaaa:bbbb:cccc:fff8::", 61, 0);
|
||||
check_subnet_id("aaaa:bbbb:cccc:ffff::", 61, 7);
|
||||
check_subnet_id("aaaa:bbbb:cccc:fff0::", 60, 0);
|
||||
check_subnet_id("aaaa:bbbb:cccc:fff2::", 60, 2);
|
||||
check_subnet_id("aaaa:bbbb:cccc:ffff::", 60, 15);
|
||||
check_subnet_id("aaaa:bbbb:cccc:0000::", 48, 0);
|
||||
check_subnet_id("aaaa:bbbb:cccc:f000::", 48, 61440);
|
||||
check_subnet_id("aaaa:bbbb:cccc:ffff::", 48, 65535);
|
||||
check_subnet_id("aaaa:bbbb:cccc:0000::", 46, 0);
|
||||
check_subnet_id("aaaa:bbbb:cccc:0001::", 46, 1);
|
||||
check_subnet_id("aaaa:bbbb:ccce:5555::", 46, 152917);
|
||||
check_subnet_id("aaaa:bbbb:0000:0000::", 32, 0);
|
||||
check_subnet_id("aaaa:bbbb:0000:0001::", 32, 1);
|
||||
check_subnet_id("aaaa:bbbb:0001:0001::", 32, 65537);
|
||||
check_subnet_id("aaaa:bbbb:ffff:ffff::", 32, 0xffffffff);
|
||||
check_subnet_id("aaaa:bbb8:0000:0000::", 30, 0);
|
||||
check_subnet_id("aaaa:bbb8:0000:0001::", 30, 1);
|
||||
check_subnet_id("aaaa:bbb8:0001:0001::", 30, 65537);
|
||||
check_subnet_id("aaaa:bbbb:0000:0000::", 30, 0x300000000ULL);
|
||||
check_subnet_id("aaaa:bbbb:0001:0001::", 30, 0x300010001ULL);
|
||||
check_subnet_id("aaaa:bbbb:0001:0001::", 8, 0xAABBBB00010001ULL);
|
||||
check_subnet_id("abaa:bbbb:0001:0001::", 7, 0x1AABBBB00010001ULL);
|
||||
check_subnet_id("abaa:bbbb:0001:0001::", 0, 0xABAABBBB00010001ULL);
|
||||
check_subnet_id("abaa:bbbb:0001:0001:5555:5555:5555:5555", 0, 0xABAABBBB00010001ULL);
|
||||
check_subnet_id("::", 0, 0);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_unaligned(void)
|
||||
{
|
||||
|
|
@ -2864,6 +2911,7 @@ main(int argc, char **argv)
|
|||
g_test_add_func("/general/test_nm_ip4_addr_is_loopback", test_nm_ip4_addr_is_loopback);
|
||||
g_test_add_func("/general/test_nm_ip4_addr_netmask_from_prefix",
|
||||
test_nm_ip4_addr_netmask_from_prefix);
|
||||
g_test_add_func("/general/test_nm_ip6_addr_get_subnet_id", test_nm_ip6_addr_get_subnet_id);
|
||||
g_test_add_func("/general/test_unaligned", test_unaligned);
|
||||
g_test_add_func("/general/test_strv_cmp", test_strv_cmp);
|
||||
g_test_add_func("/general/test_strstrip_avoid_copy", test_strstrip_avoid_copy);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue