mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-08 12:28:11 +02:00
core: add nm_utils_ip6_address_same_prefix() util
This commit is contained in:
parent
a18fca36a5
commit
db3175d9c0
3 changed files with 144 additions and 1 deletions
|
|
@ -233,7 +233,6 @@ nm_ethernet_address_is_valid (gconstpointer addr, gssize len)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* nm_utils_ip4_address_clear_host_address:
|
/* nm_utils_ip4_address_clear_host_address:
|
||||||
* @addr: source ip6 address
|
* @addr: source ip6 address
|
||||||
* @plen: prefix length of network
|
* @plen: prefix length of network
|
||||||
|
|
@ -279,6 +278,32 @@ nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_utils_ip6_address_same_prefix (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen)
|
||||||
|
{
|
||||||
|
int nbytes;
|
||||||
|
guint8 t, m;
|
||||||
|
|
||||||
|
if (plen >= 128)
|
||||||
|
return memcmp (addr_a, addr_b, sizeof (struct in6_addr)) == 0;
|
||||||
|
|
||||||
|
nbytes = plen / 8;
|
||||||
|
if (nbytes) {
|
||||||
|
if (memcmp (addr_a, addr_b, nbytes) != 0)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
plen = plen % 8;
|
||||||
|
if (plen == 0)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
m = ~((1 << (8 - plen)) - 1);
|
||||||
|
t = ((((const guint8 *) addr_a))[nbytes]) ^ ((((const guint8 *) addr_b))[nbytes]);
|
||||||
|
return (t & m) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
void
|
void
|
||||||
nm_utils_array_remove_at_indexes (GArray *array, const guint *indexes_to_delete, gsize len)
|
nm_utils_array_remove_at_indexes (GArray *array, const guint *indexes_to_delete, gsize len)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,7 @@ gboolean nm_ethernet_address_is_valid (gconstpointer addr, gssize len);
|
||||||
|
|
||||||
in_addr_t nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen);
|
in_addr_t nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen);
|
||||||
const struct in6_addr *nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen);
|
const struct in6_addr *nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen);
|
||||||
|
gboolean nm_utils_ip6_address_same_prefix (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nm_utils_ip6_route_metric_normalize:
|
* nm_utils_ip6_route_metric_normalize:
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,122 @@ test_nm_utils_ip6_address_clear_host_address (void)
|
||||||
g_rand_free (r);
|
g_rand_free (r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
_test_same_prefix (const char *a1, const char *a2, guint8 plen)
|
||||||
|
{
|
||||||
|
struct in6_addr a = *nmtst_inet6_from_string (a1);
|
||||||
|
struct in6_addr b = *nmtst_inet6_from_string (a2);
|
||||||
|
|
||||||
|
g_assert (nm_utils_ip6_address_same_prefix (&a, &b, plen));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_nm_utils_ip6_address_same_prefix (void)
|
||||||
|
{
|
||||||
|
guint n, i;
|
||||||
|
const guint N = 100;
|
||||||
|
union {
|
||||||
|
guint8 ptr[sizeof (struct in6_addr)];
|
||||||
|
struct in6_addr val;
|
||||||
|
} a, b, addrmask, addrmask_bit;
|
||||||
|
guint8 plen;
|
||||||
|
|
||||||
|
/* test#1 */
|
||||||
|
for (n = 0; n < N; n++) {
|
||||||
|
gboolean is_same = n < N / 2;
|
||||||
|
gboolean result;
|
||||||
|
|
||||||
|
nmtst_rand_buf (NULL, a.ptr, sizeof (a));
|
||||||
|
nmtst_rand_buf (NULL, b.ptr, sizeof (b));
|
||||||
|
again_plen:
|
||||||
|
plen = nmtst_get_rand_int () % 129;
|
||||||
|
if (!is_same && NM_IN_SET (plen, 0, 128))
|
||||||
|
goto again_plen;
|
||||||
|
|
||||||
|
if (plen < 128) {
|
||||||
|
for (i = 0; (i + 1) * 8 <= plen; i++)
|
||||||
|
b.ptr[i] = a.ptr[i];
|
||||||
|
if (plen % 8) {
|
||||||
|
guint8 mask;
|
||||||
|
|
||||||
|
g_assert (i < sizeof (a));
|
||||||
|
mask = ~((1 << (8 - (plen % 8))) - 1);
|
||||||
|
b.ptr[i] = (a.ptr[i] & mask) | (b.ptr[i] & ~mask);
|
||||||
|
if (!is_same) {
|
||||||
|
mask = (1 << (8 - (plen % 8)));
|
||||||
|
b.ptr[i] = (b.ptr[i] & ~mask) | ~(b.ptr[i] & mask);
|
||||||
|
}
|
||||||
|
} else if (!is_same) {
|
||||||
|
g_assert (i > 0);
|
||||||
|
|
||||||
|
b.ptr[i - 1] = (b.ptr[i - 1] & ~0x1) | ~(b.ptr[i - 1] & 0x1);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
b = a;
|
||||||
|
|
||||||
|
result = nm_utils_ip6_address_same_prefix (&a.val, &b.val, plen);
|
||||||
|
g_assert (result == is_same);
|
||||||
|
g_assert (NM_IN_SET (result, TRUE, FALSE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test#2 */
|
||||||
|
for (n = 0; n < N; n++) {
|
||||||
|
nmtst_rand_buf (NULL, a.ptr, sizeof (a));
|
||||||
|
nmtst_rand_buf (NULL, b.ptr, sizeof (b));
|
||||||
|
plen = nmtst_get_rand_int () % 129;
|
||||||
|
|
||||||
|
memset (addrmask.ptr, 0xFF, sizeof (addrmask));
|
||||||
|
nm_utils_ip6_address_clear_host_address (&addrmask.val, &addrmask.val, plen);
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof (a); i++)
|
||||||
|
b.ptr[i] = (a.ptr[i] & addrmask.ptr[i]) | (b.ptr[i] & ~addrmask.ptr[i]);
|
||||||
|
|
||||||
|
g_assert (nm_utils_ip6_address_same_prefix (&a.val, &b.val, plen) == TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test#3 */
|
||||||
|
for (n = 0; n < N; n++) {
|
||||||
|
gboolean reached = FALSE;
|
||||||
|
|
||||||
|
nmtst_rand_buf (NULL, a.ptr, sizeof (a));
|
||||||
|
nmtst_rand_buf (NULL, b.ptr, sizeof (b));
|
||||||
|
plen = nmtst_get_rand_int () % 129;
|
||||||
|
|
||||||
|
if (!plen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
memset (addrmask.ptr, 0xFF, sizeof (addrmask));
|
||||||
|
nm_utils_ip6_address_clear_host_address (&addrmask.val, &addrmask.val, plen);
|
||||||
|
|
||||||
|
memset (addrmask_bit.ptr, 0xFF, sizeof (addrmask_bit));
|
||||||
|
nm_utils_ip6_address_clear_host_address (&addrmask_bit.val, &addrmask_bit.val, plen - 1);
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof (a); i++)
|
||||||
|
b.ptr[i] = (a.ptr[i] & addrmask.ptr[i]) | (b.ptr[i] & ~addrmask.ptr[i]);
|
||||||
|
|
||||||
|
/* flip the last bit. */
|
||||||
|
for (i = 0; i < sizeof (a); i++) {
|
||||||
|
guint8 mask = addrmask.ptr[i] ^ addrmask_bit.ptr[i];
|
||||||
|
if (mask) {
|
||||||
|
g_assert (!reached);
|
||||||
|
g_assert (nm_utils_is_power_of_two (mask));
|
||||||
|
reached = TRUE;
|
||||||
|
b.ptr[i] = (b.ptr[i] & ~mask) | ~(b.ptr[i] & mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_assert (reached);
|
||||||
|
|
||||||
|
g_assert (nm_utils_ip6_address_same_prefix (&a.val, &b.val, plen) == FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test#4 */
|
||||||
|
_test_same_prefix ("::", "::1", 10);
|
||||||
|
_test_same_prefix ("abcd::", "abcd::1", 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_nm_utils_log_connection_diff (void)
|
test_nm_utils_log_connection_diff (void)
|
||||||
|
|
@ -1257,6 +1373,7 @@ main (int argc, char **argv)
|
||||||
g_test_add_func ("/general/nm_utils_strbuf_append", test_nm_utils_strbuf_append);
|
g_test_add_func ("/general/nm_utils_strbuf_append", test_nm_utils_strbuf_append);
|
||||||
|
|
||||||
g_test_add_func ("/general/nm_utils_ip6_address_clear_host_address", test_nm_utils_ip6_address_clear_host_address);
|
g_test_add_func ("/general/nm_utils_ip6_address_clear_host_address", test_nm_utils_ip6_address_clear_host_address);
|
||||||
|
g_test_add_func ("/general/nm_utils_ip6_address_same_prefix", test_nm_utils_ip6_address_same_prefix);
|
||||||
g_test_add_func ("/general/nm_utils_log_connection_diff", test_nm_utils_log_connection_diff);
|
g_test_add_func ("/general/nm_utils_log_connection_diff", test_nm_utils_log_connection_diff);
|
||||||
|
|
||||||
g_test_add_func ("/general/connection-match/basic", test_connection_match_basic);
|
g_test_add_func ("/general/connection-match/basic", test_connection_match_basic);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue