mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-25 16:30:07 +01:00
l3cfg: merge branch 'th/l3cfg-8'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/623
This commit is contained in:
commit
ebd07a809c
21 changed files with 1916 additions and 1300 deletions
|
|
@ -3294,33 +3294,253 @@ nm_utils_hash_values_to_array (GHashTable *hash,
|
|||
return arr;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_utils_hashtable_same_keys (const GHashTable *a,
|
||||
const GHashTable *b)
|
||||
static gboolean
|
||||
_utils_hashtable_equal (GHashTable *hash_a,
|
||||
GHashTable *hash_b,
|
||||
GCompareDataFunc cmp_values,
|
||||
gpointer user_data)
|
||||
{
|
||||
GHashTableIter h;
|
||||
const char *k;
|
||||
gpointer a_key;
|
||||
gpointer a_val;
|
||||
gpointer b_val;
|
||||
|
||||
if (a == b)
|
||||
return TRUE;
|
||||
if (!a || !b)
|
||||
return FALSE;
|
||||
if (g_hash_table_size ((GHashTable *) a) != g_hash_table_size ((GHashTable *) b))
|
||||
return FALSE;
|
||||
nm_assert (hash_a);
|
||||
nm_assert (hash_b);
|
||||
nm_assert (hash_a != hash_b);
|
||||
nm_assert (g_hash_table_size (hash_a) == g_hash_table_size (hash_b));
|
||||
|
||||
g_hash_table_iter_init (&h, (GHashTable *) a);
|
||||
while (g_hash_table_iter_next (&h, (gpointer) &k, NULL)) {
|
||||
if (!g_hash_table_contains ((GHashTable *) b, k))
|
||||
/* We rely on both hashes to have the same hash/equal function. Otherwise, we would have to iterate
|
||||
* both hashes and check whether all keys/values are present in the respective other hash (which
|
||||
* would be O(n^2), since we couldn't use the plain lookup function. That is not a useful thing
|
||||
* for this function. */
|
||||
|
||||
g_hash_table_iter_init (&h, hash_a);
|
||||
while (g_hash_table_iter_next (&h, &a_key, &a_val)) {
|
||||
|
||||
if (!g_hash_table_lookup_extended (hash_b, a_key, NULL, &b_val))
|
||||
return FALSE;
|
||||
|
||||
if (!cmp_values) {
|
||||
/* we accept %NULL compare function to indicate that we don't care about the key. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cmp_values (a_val, b_val, user_data) != 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_utils_hashtable_equal:
|
||||
* @a: (allow-none): the hash table or %NULL
|
||||
* @b: (allow-none): the other hash table or %NULL
|
||||
* @cmp_values: (allow-none): if %NULL, only the keys
|
||||
* will be compared. Otherwise, this function is used to
|
||||
* check whether all keys are equal.
|
||||
* @user_data: the argument for @cmp_values.
|
||||
*
|
||||
* It is required that both @a and @b have the same hash and equals
|
||||
* function.
|
||||
*
|
||||
* Returns: %TRUE, if both keys have the same keys and (if
|
||||
* @cmp_values is given) all values are the same.
|
||||
*/
|
||||
gboolean
|
||||
nm_utils_hashtable_equal (const GHashTable *a,
|
||||
const GHashTable *b,
|
||||
GCompareDataFunc cmp_values,
|
||||
gpointer user_data)
|
||||
{
|
||||
GHashTable *hash_a = (GHashTable *) a;
|
||||
GHashTable *hash_b = (GHashTable *) b;
|
||||
gboolean same;
|
||||
guint size;
|
||||
|
||||
if (hash_a == hash_b)
|
||||
return TRUE;
|
||||
|
||||
if (!hash_a || !hash_b)
|
||||
return FALSE;
|
||||
|
||||
size = g_hash_table_size (hash_a);
|
||||
if (size != g_hash_table_size (hash_b))
|
||||
return FALSE;
|
||||
|
||||
if (size == 0)
|
||||
return TRUE;
|
||||
|
||||
same = _utils_hashtable_equal (hash_a, hash_b, cmp_values, user_data);
|
||||
|
||||
#if NM_MORE_ASSERTS > 5
|
||||
g_hash_table_iter_init (&h, (GHashTable *) b);
|
||||
while (g_hash_table_iter_next (&h, (gpointer) &k, NULL))
|
||||
nm_assert (g_hash_table_contains ((GHashTable *) a, k));
|
||||
nm_assert (same == _utils_hashtable_equal (hash_b, hash_a, cmp_values, user_data));
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
return same;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
gpointer key;
|
||||
gpointer val;
|
||||
} HashTableCmpData;
|
||||
|
||||
typedef struct {
|
||||
GCompareDataFunc cmp_keys;
|
||||
gpointer user_data;
|
||||
} HashTableUserData;
|
||||
|
||||
static int
|
||||
_hashtable_cmp_func (gconstpointer a,
|
||||
gconstpointer b,
|
||||
gpointer user_data)
|
||||
{
|
||||
const HashTableUserData *d = user_data;
|
||||
const HashTableCmpData *d_a = *((const HashTableCmpData *const*) a);
|
||||
const HashTableCmpData *d_b = *((const HashTableCmpData *const*) b);
|
||||
|
||||
NM_CMP_RETURN (d->cmp_keys (d_a, d_b, d->user_data));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_utils_hashtable_cmp:
|
||||
* @a: (allow-none): the hash to compare. May be %NULL.
|
||||
* @b: (allow-none): the other hash to compare. May be %NULL.
|
||||
* @do_fast_precheck: if %TRUE, assume that the hashes are equal
|
||||
* and that it is worth calling nm_utils_hashtable_equal() first.
|
||||
* That requires, that both hashes have the same equals function
|
||||
* which is compatible with the @cmp_keys function.
|
||||
* @cmp_keys: the compare function for keys. Usually, the hash/equal function
|
||||
* of both hashes corresponds to this function. If you set @do_fast_precheck
|
||||
* to false, then this is not a requirement.
|
||||
* @cmp_values: (allow-none): if %NULL, only the keys are compared.
|
||||
* Otherwise, the values must are also compared with this function.
|
||||
*
|
||||
* Both hashes must have keys/values of the same domain, so that
|
||||
* they can be effectively compared with @cmp_keys and @cmp_values.
|
||||
*
|
||||
* %NULL hashes compare equal to %NULL, but not to empty hashes.
|
||||
*
|
||||
* Returns: 0 if both hashes are equal, or -1 or 1 if one of the hashes
|
||||
* sorts before/after.
|
||||
*/
|
||||
int
|
||||
nm_utils_hashtable_cmp (const GHashTable *a,
|
||||
const GHashTable *b,
|
||||
gboolean do_fast_precheck,
|
||||
GCompareDataFunc cmp_keys,
|
||||
GCompareDataFunc cmp_values,
|
||||
gpointer user_data)
|
||||
{
|
||||
GHashTable *hash_a = (GHashTable *) a;
|
||||
GHashTable *hash_b = (GHashTable *) b;
|
||||
gs_free HashTableCmpData *cmp_array_free = NULL;
|
||||
HashTableCmpData *cmp_array_a;
|
||||
HashTableCmpData *cmp_array_b;
|
||||
GHashTableIter h;
|
||||
gpointer i_key;
|
||||
gpointer i_val;
|
||||
gsize size2;
|
||||
guint size;
|
||||
guint i;
|
||||
|
||||
nm_assert (cmp_keys);
|
||||
|
||||
NM_CMP_SELF (hash_a, hash_b);
|
||||
|
||||
size = g_hash_table_size (hash_a);
|
||||
|
||||
NM_CMP_DIRECT (size, g_hash_table_size (hash_b));
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
if (do_fast_precheck) {
|
||||
gboolean same;
|
||||
|
||||
/* we expect that the hashes are equal and the caller ensures us that they
|
||||
* use the same hash/equal functions. Do a fast path check first...
|
||||
*
|
||||
* It's unclear whether this is worth it. The full comparison is O(n*ln(n)),
|
||||
* while the fast check (using the hash lookup) is O(n). But then, the pre-check
|
||||
* makes additional requirements on the hash's hash/equal functions -- the
|
||||
* full comparison does not make such requirements. */
|
||||
same = _utils_hashtable_equal (hash_a, hash_b, cmp_values, user_data);
|
||||
#if NM_MORE_ASSERTS > 5
|
||||
nm_assert (same == _utils_hashtable_equal (hash_b, hash_a, cmp_values, user_data));
|
||||
#endif
|
||||
if (same)
|
||||
return 0;
|
||||
}
|
||||
|
||||
size2 = ((gsize) size) * 2u;
|
||||
if (size2 > 600u / sizeof (HashTableCmpData)) {
|
||||
cmp_array_free = g_new (HashTableCmpData, size2);
|
||||
cmp_array_a = cmp_array_free;
|
||||
} else
|
||||
cmp_array_a = g_newa (HashTableCmpData, size2);
|
||||
cmp_array_b = &cmp_array_a[size];
|
||||
|
||||
i = 0;
|
||||
g_hash_table_iter_init (&h, hash_a);
|
||||
while (g_hash_table_iter_next (&h, &i_key, &i_val)) {
|
||||
nm_assert (i < size);
|
||||
cmp_array_a[i++] = (HashTableCmpData) {
|
||||
.key = i_key,
|
||||
.val = i_val,
|
||||
};
|
||||
}
|
||||
nm_assert (i == size);
|
||||
|
||||
i = 0;
|
||||
g_hash_table_iter_init (&h, hash_b);
|
||||
while (g_hash_table_iter_next (&h, &i_key, &i_val)) {
|
||||
nm_assert (i < size);
|
||||
cmp_array_b[i++] = (HashTableCmpData) {
|
||||
.key = i_key,
|
||||
.val = i_val,
|
||||
};
|
||||
}
|
||||
nm_assert (i == size);
|
||||
|
||||
g_qsort_with_data (cmp_array_a,
|
||||
size,
|
||||
sizeof (HashTableCmpData),
|
||||
_hashtable_cmp_func,
|
||||
&((HashTableUserData) {
|
||||
.cmp_keys = cmp_keys,
|
||||
.user_data = user_data,
|
||||
}));
|
||||
|
||||
g_qsort_with_data (cmp_array_b,
|
||||
size,
|
||||
sizeof (HashTableCmpData),
|
||||
_hashtable_cmp_func,
|
||||
&((HashTableUserData) {
|
||||
.cmp_keys = cmp_keys,
|
||||
.user_data = user_data,
|
||||
}));
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
NM_CMP_RETURN (cmp_keys (cmp_array_a[i].key,
|
||||
cmp_array_b[i].key,
|
||||
user_data));
|
||||
}
|
||||
|
||||
if (cmp_values) {
|
||||
for (i = 0; i < size; i++) {
|
||||
NM_CMP_RETURN (cmp_values (cmp_array_a[i].val,
|
||||
cmp_array_b[i].val,
|
||||
user_data));
|
||||
}
|
||||
}
|
||||
|
||||
/* the fast-precheck should have already told that the arrays are equal. */
|
||||
nm_assert (!do_fast_precheck);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char **
|
||||
|
|
|
|||
|
|
@ -1521,8 +1521,24 @@ nm_utils_strdict_get_keys (const GHashTable *hash,
|
|||
out_length);
|
||||
}
|
||||
|
||||
gboolean nm_utils_hashtable_same_keys (const GHashTable *a,
|
||||
const GHashTable *b);
|
||||
gboolean nm_utils_hashtable_equal (const GHashTable *a,
|
||||
const GHashTable *b,
|
||||
GCompareDataFunc cmp_values,
|
||||
gpointer user_data);
|
||||
|
||||
static inline gboolean
|
||||
nm_utils_hashtable_same_keys (const GHashTable *a,
|
||||
const GHashTable *b)
|
||||
{
|
||||
return nm_utils_hashtable_equal (a, b, NULL, NULL);
|
||||
}
|
||||
|
||||
int nm_utils_hashtable_cmp (const GHashTable *a,
|
||||
const GHashTable *b,
|
||||
gboolean do_fast_precheck,
|
||||
GCompareDataFunc cmp_keys,
|
||||
GCompareDataFunc cmp_values,
|
||||
gpointer user_data);
|
||||
|
||||
char **nm_utils_strv_make_deep_copied (const char **strv);
|
||||
|
||||
|
|
@ -1564,14 +1580,14 @@ nm_g_array_len (const GArray *arr)
|
|||
|
||||
#define nm_g_array_append_new(arr, type) \
|
||||
({ \
|
||||
GArray *_arr = (arr); \
|
||||
gsize _l; \
|
||||
GArray *const _arr = (arr); \
|
||||
guint _len; \
|
||||
\
|
||||
nm_assert (_arr); \
|
||||
_l = ((gsize) _arr->len) + 1u; \
|
||||
nm_assert (_l > _arr->len); \
|
||||
g_array_set_size (_arr, _l); \
|
||||
&g_array_index (arr, type, _l); \
|
||||
_len = _arr->len; \
|
||||
nm_assert (_len < G_MAXUINT); \
|
||||
g_array_set_size (_arr, _len + 1u); \
|
||||
&g_array_index (arr, type, _len); \
|
||||
})
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -986,6 +986,122 @@ test_strv_dup_packed (void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static int
|
||||
_hash_func_cmp_direct (gconstpointer a,
|
||||
gconstpointer b,
|
||||
gpointer user_data)
|
||||
{
|
||||
NM_CMP_DIRECT (GPOINTER_TO_INT (a), GPOINTER_TO_INT (b));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_utils_hashtable_cmp (void)
|
||||
{
|
||||
static struct {
|
||||
int val_i;
|
||||
const char *val_s;
|
||||
} vals[] = {
|
||||
{ 0, "0", },
|
||||
{ 1, "1", },
|
||||
{ 2, "2", },
|
||||
{ 3, "3", },
|
||||
{ 4, "4", },
|
||||
{ 5, "5", },
|
||||
{ 6, "6", },
|
||||
{ 7, "7", },
|
||||
{ 8, "8", },
|
||||
{ 9, "9", },
|
||||
{ 0, "a", },
|
||||
{ 1, "a", },
|
||||
{ 2, "a", },
|
||||
{ 3, "a", },
|
||||
{ 4, "a", },
|
||||
{ 5, "a", },
|
||||
{ 0, "0", },
|
||||
{ 0, "1", },
|
||||
{ 0, "2", },
|
||||
{ 0, "3", },
|
||||
{ 0, "4", },
|
||||
{ 0, "5", },
|
||||
};
|
||||
guint test_run;
|
||||
int is_num_key;
|
||||
|
||||
for (test_run = 0; test_run < 30; test_run++) {
|
||||
for (is_num_key = 0; is_num_key < 2; is_num_key++) {
|
||||
GHashFunc func_key_hash = is_num_key ? nm_direct_hash : nm_str_hash;
|
||||
GEqualFunc func_key_equal = is_num_key ? g_direct_equal : g_str_equal;
|
||||
GCompareDataFunc func_key_cmp = is_num_key ? _hash_func_cmp_direct : (GCompareDataFunc) nm_strcmp_with_data;
|
||||
GCompareDataFunc func_val_cmp = !is_num_key ? _hash_func_cmp_direct : (GCompareDataFunc) nm_strcmp_with_data;
|
||||
gs_unref_hashtable GHashTable *h1 = NULL;
|
||||
gs_unref_hashtable GHashTable *h2 = NULL;
|
||||
gboolean has_same_keys;
|
||||
guint i, n;
|
||||
|
||||
h1 = g_hash_table_new (func_key_hash, func_key_equal);
|
||||
h2 = g_hash_table_new (func_key_hash, func_key_equal);
|
||||
|
||||
n = nmtst_get_rand_word_length (NULL);
|
||||
for (i = 0; i < n; i++) {
|
||||
typeof (vals[0]) *v = &vals[nmtst_get_rand_uint32 () % G_N_ELEMENTS (vals)];
|
||||
gconstpointer v_key = is_num_key ? GINT_TO_POINTER (v->val_i) : v->val_s;
|
||||
gconstpointer v_val = !is_num_key ? GINT_TO_POINTER (v->val_i) : v->val_s;
|
||||
|
||||
g_hash_table_insert (h1, (gpointer) v_key, (gpointer) v_val);
|
||||
g_hash_table_insert (h2, (gpointer) v_key, (gpointer) v_val);
|
||||
}
|
||||
|
||||
g_assert (nm_utils_hashtable_same_keys (h1, h2));
|
||||
g_assert (nm_utils_hashtable_equal (h1, h2, NULL, NULL));
|
||||
g_assert (nm_utils_hashtable_equal (h1, h2, func_val_cmp, NULL));
|
||||
g_assert (nm_utils_hashtable_cmp (h1, h2, FALSE, func_key_cmp, NULL, NULL) == 0);
|
||||
g_assert (nm_utils_hashtable_cmp (h1, h2, TRUE, func_key_cmp, NULL, NULL) == 0);
|
||||
g_assert (nm_utils_hashtable_cmp (h1, h2, FALSE, func_key_cmp, func_val_cmp, NULL) == 0);
|
||||
g_assert (nm_utils_hashtable_cmp (h1, h2, TRUE, func_key_cmp, func_val_cmp, NULL) == 0);
|
||||
|
||||
n = nmtst_get_rand_word_length (NULL) + 1;
|
||||
has_same_keys = TRUE;
|
||||
for (i = 0; i < n; i++) {
|
||||
again:
|
||||
{
|
||||
typeof (vals[0]) *v = &vals[nmtst_get_rand_uint32 () % G_N_ELEMENTS (vals)];
|
||||
gconstpointer v_key = is_num_key ? GINT_TO_POINTER (v->val_i) : v->val_s;
|
||||
gconstpointer v_val = !is_num_key ? GINT_TO_POINTER (v->val_i) : v->val_s;
|
||||
gpointer v_key2;
|
||||
gpointer v_val2;
|
||||
|
||||
if (g_hash_table_lookup_extended (h1, v_key, &v_key2, &v_val2)) {
|
||||
g_assert (func_key_cmp (v_key, v_key2, NULL) == 0);
|
||||
if (func_val_cmp (v_val, v_val2, NULL) == 0)
|
||||
goto again;
|
||||
} else
|
||||
has_same_keys = FALSE;
|
||||
|
||||
g_hash_table_insert (h2, (gpointer) v_key, (gpointer) v_val);
|
||||
}
|
||||
}
|
||||
|
||||
if (has_same_keys) {
|
||||
g_assert (nm_utils_hashtable_same_keys (h1, h2));
|
||||
g_assert (nm_utils_hashtable_equal (h1, h2, NULL, NULL));
|
||||
g_assert (nm_utils_hashtable_cmp (h1, h2, FALSE, func_key_cmp, NULL, NULL) == 0);
|
||||
g_assert (nm_utils_hashtable_cmp (h1, h2, TRUE, func_key_cmp, NULL, NULL) == 0);
|
||||
} else {
|
||||
g_assert (!nm_utils_hashtable_same_keys (h1, h2));
|
||||
g_assert (!nm_utils_hashtable_equal (h1, h2, NULL, NULL));
|
||||
g_assert (nm_utils_hashtable_cmp (h1, h2, FALSE, func_key_cmp, NULL, NULL) != 0);
|
||||
g_assert (nm_utils_hashtable_cmp (h1, h2, TRUE, func_key_cmp, NULL, NULL) != 0);
|
||||
}
|
||||
g_assert (!nm_utils_hashtable_equal (h1, h2, func_val_cmp, NULL));
|
||||
g_assert (nm_utils_hashtable_cmp (h1, h2, FALSE, func_key_cmp, func_val_cmp, NULL) != 0);
|
||||
g_assert (nm_utils_hashtable_cmp (h1, h2, TRUE, func_key_cmp, func_val_cmp, NULL) != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMTST_DEFINE ();
|
||||
|
||||
int main (int argc, char **argv)
|
||||
|
|
@ -1011,6 +1127,7 @@ int main (int argc, char **argv)
|
|||
g_test_add_func ("/general/test_in_strset_ascii_case", test_in_strset_ascii_case);
|
||||
g_test_add_func ("/general/test_is_specific_hostname", test_is_specific_hostname);
|
||||
g_test_add_func ("/general/test_strv_dup_packed", test_strv_dup_packed);
|
||||
g_test_add_func ("/general/test_utils_hashtable_cmp", test_utils_hashtable_cmp);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,4 +159,65 @@ void nm_utils_ip_routes_to_dbus (int addr_family,
|
|||
GVariant **out_route_data,
|
||||
GVariant **out_routes);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* For now, all we track about a DHCP lease is the GHashTable with
|
||||
* the options.
|
||||
*
|
||||
* We don't add a separate type for that, but we also don't want to use
|
||||
* GHashTable directly (because most importantly leases should be immutable
|
||||
* and passing a GHashTable pointer around neither makes it clear that
|
||||
* this is a lease nor that it's immutable.
|
||||
*
|
||||
* Instead, add a simple opaque pointer and accessors that cast to a GHashTable.
|
||||
*
|
||||
* It has no overhead at run time, but gives some rudimentary type safety. */
|
||||
|
||||
typedef struct _NMDhcpLease NMDhcpLease;
|
||||
|
||||
static inline NMDhcpLease *
|
||||
nm_dhcp_lease_new_from_options (GHashTable *options_take)
|
||||
{
|
||||
/* a NMDhcpLease is really just a GHashTable. But it's also supposed to be *immutable*.
|
||||
*
|
||||
* Hence, the API here takes over ownership of the reference to @options_take, that
|
||||
* is to emphasize that we acquire ownership of the hash, and it should not be modified
|
||||
* anymore. */
|
||||
return (NMDhcpLease *) options_take;
|
||||
}
|
||||
|
||||
static inline GHashTable *
|
||||
nm_dhcp_lease_get_options (NMDhcpLease *lease)
|
||||
{
|
||||
return (GHashTable *) lease;
|
||||
}
|
||||
|
||||
static inline void
|
||||
nm_dhcp_lease_ref (NMDhcpLease *lease)
|
||||
{
|
||||
if (lease)
|
||||
g_hash_table_ref ((GHashTable *) lease);
|
||||
}
|
||||
|
||||
static inline void
|
||||
nm_dhcp_lease_unref (NMDhcpLease *lease)
|
||||
{
|
||||
if (lease)
|
||||
g_hash_table_unref ((GHashTable *) lease);
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
nm_dhcp_lease_lookup_option (NMDhcpLease *lease,
|
||||
const char *option)
|
||||
{
|
||||
nm_assert (option);
|
||||
|
||||
return nm_g_hash_table_lookup ((GHashTable *) lease, option);
|
||||
}
|
||||
|
||||
NM_AUTO_DEFINE_FCN (NMDhcpLease *, _nm_auto_unref_dhcplease, nm_dhcp_lease_unref);
|
||||
#define nm_auto_unref_dhcplease nm_auto (_nm_auto_unref_dhcplease)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* __NETWORKMANAGER_UTILS_H__ */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -16,7 +16,7 @@
|
|||
#include "nm-rfkill-manager.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
||||
typedef enum {
|
||||
typedef enum _nm_packed {
|
||||
NM_DEVICE_SYS_IFACE_STATE_EXTERNAL,
|
||||
NM_DEVICE_SYS_IFACE_STATE_ASSUME,
|
||||
NM_DEVICE_SYS_IFACE_STATE_MANAGED,
|
||||
|
|
|
|||
|
|
@ -480,15 +480,8 @@ nm_dhcp_client_set_state (NMDhcpClient *self,
|
|||
}
|
||||
}
|
||||
|
||||
if ( priv->addr_family == AF_INET6
|
||||
&& NM_IN_SET (new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) {
|
||||
char *start, *iaid;
|
||||
|
||||
iaid = g_hash_table_lookup (options, "iaid");
|
||||
start = g_hash_table_lookup (options, "life_starts");
|
||||
if (iaid && start)
|
||||
event_id = g_strdup_printf ("%s|%s", iaid, start);
|
||||
}
|
||||
if (priv->addr_family == AF_INET6)
|
||||
event_id = nm_dhcp_utils_get_dhcp6_event_id (options);
|
||||
|
||||
_LOGI ("state changed %s -> %s%s%s%s",
|
||||
state_to_string (priv->state),
|
||||
|
|
@ -500,8 +493,7 @@ nm_dhcp_client_set_state (NMDhcpClient *self,
|
|||
signals[SIGNAL_STATE_CHANGED], 0,
|
||||
new_state,
|
||||
ip_config,
|
||||
options,
|
||||
event_id);
|
||||
options);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -1319,7 +1311,11 @@ nm_dhcp_client_class_init (NMDhcpClientClass *client_class)
|
|||
G_SIGNAL_RUN_FIRST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 4, G_TYPE_UINT, G_TYPE_OBJECT, G_TYPE_HASH_TABLE, G_TYPE_STRING);
|
||||
G_TYPE_NONE,
|
||||
3,
|
||||
G_TYPE_UINT,
|
||||
G_TYPE_OBJECT,
|
||||
G_TYPE_HASH_TABLE);
|
||||
|
||||
signals[SIGNAL_PREFIX_DELEGATED] =
|
||||
g_signal_new (NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED,
|
||||
|
|
|
|||
|
|
@ -45,6 +45,14 @@ G_DEFINE_TYPE (NMDhcpManager, nm_dhcp_manager, G_TYPE_OBJECT)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void client_state_changed (NMDhcpClient *client,
|
||||
NMDhcpState state,
|
||||
GObject *ip_config,
|
||||
GVariant *options,
|
||||
NMDhcpManager *self);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* default to installed helper, but can be modified for testing */
|
||||
const char *nm_dhcp_helper_path = LIBEXECDIR "/nm-dhcp-helper";
|
||||
|
||||
|
|
@ -161,13 +169,6 @@ get_client_for_ifindex (NMDhcpManager *manager, int addr_family, int ifindex)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void client_state_changed (NMDhcpClient *client,
|
||||
NMDhcpState state,
|
||||
GObject *ip_config,
|
||||
GVariant *options,
|
||||
const char *event_id,
|
||||
NMDhcpManager *self);
|
||||
|
||||
static void
|
||||
remove_client (NMDhcpManager *self, NMDhcpClient *client)
|
||||
{
|
||||
|
|
@ -192,7 +193,6 @@ client_state_changed (NMDhcpClient *client,
|
|||
NMDhcpState state,
|
||||
GObject *ip_config,
|
||||
GVariant *options,
|
||||
const char *event_id,
|
||||
NMDhcpManager *self)
|
||||
{
|
||||
if (state >= NM_DHCP_STATE_TIMEOUT)
|
||||
|
|
|
|||
|
|
@ -219,9 +219,9 @@ nm_dhcp_option_request_string (const NMDhcpOption *requests, guint option)
|
|||
|
||||
void
|
||||
nm_dhcp_option_take_option (GHashTable *options,
|
||||
const NMDhcpOption *requests,
|
||||
guint option,
|
||||
char *value)
|
||||
const NMDhcpOption *requests,
|
||||
guint option,
|
||||
char *value)
|
||||
{
|
||||
nm_assert (options);
|
||||
nm_assert (requests);
|
||||
|
|
|
|||
|
|
@ -786,3 +786,23 @@ nm_dhcp_utils_get_leasefile_path (int addr_family,
|
|||
*out_leasefile_path = g_steal_pointer (&statedir_path);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
char *
|
||||
nm_dhcp_utils_get_dhcp6_event_id (GHashTable *lease)
|
||||
{
|
||||
const char *start;
|
||||
const char *iaid;
|
||||
|
||||
if (!lease)
|
||||
return NULL;
|
||||
|
||||
iaid = g_hash_table_lookup (lease, "iaid");
|
||||
if (!iaid)
|
||||
return NULL;
|
||||
|
||||
start = g_hash_table_lookup (lease, "life_starts");
|
||||
if (!start)
|
||||
return NULL;
|
||||
|
||||
return g_strdup_printf ("%s|%s", iaid, start);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,5 +38,7 @@ gboolean nm_dhcp_utils_get_leasefile_path (int addr_family,
|
|||
|
||||
char **nm_dhcp_parse_search_list (guint8 *data, size_t n_data);
|
||||
|
||||
char *nm_dhcp_utils_get_dhcp6_event_id (GHashTable *lease);
|
||||
|
||||
#endif /* __NETWORKMANAGER_DHCP_UTILS_H__ */
|
||||
|
||||
|
|
|
|||
|
|
@ -3757,6 +3757,113 @@ nm_utils_dhcp_client_id_systemd_node_specific (guint32 iaid)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
GBytes *
|
||||
nm_utils_generate_duid_llt (int arp_type,
|
||||
const guint8 *hwaddr,
|
||||
gsize hwaddr_len,
|
||||
gint64 time)
|
||||
{
|
||||
guint8 *arr;
|
||||
const guint16 duid_type = htons (1);
|
||||
const guint16 hw_type = htons (arp_type);
|
||||
const guint32 duid_time = htonl (NM_MAX (0, time - NM_UTILS_EPOCH_DATETIME_200001010000));
|
||||
|
||||
if (!nm_utils_arp_type_get_hwaddr_relevant_part (arp_type, &hwaddr, &hwaddr_len))
|
||||
nm_assert_not_reached ();
|
||||
|
||||
arr = g_new (guint8, (2u + 2u + 4u) + hwaddr_len);
|
||||
|
||||
memcpy (&arr[0], &duid_type, 2);
|
||||
memcpy (&arr[2], &hw_type, 2);
|
||||
memcpy (&arr[4], &duid_time, 4);
|
||||
memcpy (&arr[8], hwaddr, hwaddr_len);
|
||||
|
||||
return g_bytes_new_take (arr, (2u + 2u + 4u) + hwaddr_len);
|
||||
}
|
||||
|
||||
GBytes *
|
||||
nm_utils_generate_duid_ll (int arp_type,
|
||||
const guint8 *hwaddr,
|
||||
gsize hwaddr_len)
|
||||
{
|
||||
guint8 *arr;
|
||||
const guint16 duid_type = htons (3);
|
||||
const guint16 hw_type = htons (arp_type);
|
||||
|
||||
if (!nm_utils_arp_type_get_hwaddr_relevant_part (arp_type, &hwaddr, &hwaddr_len))
|
||||
nm_assert_not_reached ();
|
||||
|
||||
arr = g_new (guint8, (2u + 2u) + hwaddr_len);
|
||||
|
||||
memcpy (&arr[0], &duid_type, 2);
|
||||
memcpy (&arr[2], &hw_type, 2);
|
||||
memcpy (&arr[4], hwaddr, hwaddr_len);
|
||||
|
||||
return g_bytes_new_take (arr, (2u + 2u) + hwaddr_len);
|
||||
}
|
||||
|
||||
GBytes *
|
||||
nm_utils_generate_duid_uuid (const NMUuid *uuid)
|
||||
{
|
||||
const guint16 duid_type = htons (4);
|
||||
guint8 *duid_buffer;
|
||||
|
||||
nm_assert (uuid);
|
||||
|
||||
/* Generate a DHCP Unique Identifier for DHCPv6 using the
|
||||
* DUID-UUID method (see RFC 6355 section 4). Format is:
|
||||
*
|
||||
* u16: type (DUID-UUID = 4)
|
||||
* u8[16]: UUID bytes
|
||||
*/
|
||||
G_STATIC_ASSERT_EXPR (sizeof (duid_type) == 2);
|
||||
G_STATIC_ASSERT_EXPR (sizeof (*uuid) == 16);
|
||||
duid_buffer = g_malloc (18);
|
||||
memcpy (&duid_buffer[0], &duid_type, 2);
|
||||
memcpy (&duid_buffer[2], uuid, 16);
|
||||
return g_bytes_new_take (duid_buffer, 18);
|
||||
}
|
||||
|
||||
GBytes *
|
||||
nm_utils_generate_duid_from_machine_id (void)
|
||||
{
|
||||
static GBytes *volatile global_duid = NULL;
|
||||
GBytes *p;
|
||||
|
||||
again:
|
||||
p = g_atomic_pointer_get (&global_duid);
|
||||
if (G_UNLIKELY (!p)) {
|
||||
nm_auto_free_checksum GChecksum *sum = NULL;
|
||||
const NMUuid *machine_id;
|
||||
union {
|
||||
guint8 sha256[NM_UTILS_CHECKSUM_LENGTH_SHA256];
|
||||
NMUuid uuid;
|
||||
} digest;
|
||||
|
||||
machine_id = nm_utils_machine_id_bin ();
|
||||
|
||||
/* Hash the machine ID so it's not leaked to the network.
|
||||
*
|
||||
* Optimally, we would choose an use case specific seed, but for historic
|
||||
* reasons we didn't. */
|
||||
sum = g_checksum_new (G_CHECKSUM_SHA256);
|
||||
g_checksum_update (sum, (const guchar *) machine_id, sizeof (*machine_id));
|
||||
nm_utils_checksum_get_digest (sum, digest.sha256);
|
||||
|
||||
G_STATIC_ASSERT_EXPR (sizeof (digest.sha256) > sizeof (digest.uuid));
|
||||
p = nm_utils_generate_duid_uuid (&digest.uuid);
|
||||
|
||||
if (!g_atomic_pointer_compare_and_exchange (&global_duid, NULL, p)) {
|
||||
g_bytes_unref (p);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
||||
return g_bytes_ref (p);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* nm_utils_setpgid:
|
||||
* @unused: unused
|
||||
|
|
|
|||
|
|
@ -430,6 +430,26 @@ GBytes *nm_utils_dhcp_client_id_systemd_node_specific (guint32 iaid);
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* RFC 3315 defines the epoch for the DUID-LLT time field on Jan 1st 2000. */
|
||||
#define NM_UTILS_EPOCH_DATETIME_200001010000 946684800
|
||||
|
||||
struct _NMUuid;
|
||||
|
||||
GBytes *nm_utils_generate_duid_llt (int arp_type,
|
||||
const guint8 *hwaddr,
|
||||
gsize hwaddr_len,
|
||||
gint64 time);
|
||||
|
||||
GBytes *nm_utils_generate_duid_ll (int arp_type,
|
||||
const guint8 *hwaddr,
|
||||
gsize hwaddr_len);
|
||||
|
||||
GBytes *nm_utils_generate_duid_uuid (const struct _NMUuid *uuid);
|
||||
|
||||
GBytes *nm_utils_generate_duid_from_machine_id (void);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void nm_utils_array_remove_at_indexes (GArray *array, const guint *indexes_to_delete, gsize len);
|
||||
|
||||
void nm_utils_setpgid (gpointer unused);
|
||||
|
|
|
|||
|
|
@ -95,7 +95,6 @@ dhcp4_state_changed (NMDhcpClient *client,
|
|||
NMDhcpState state,
|
||||
NMIP4Config *ip4_config,
|
||||
GHashTable *options,
|
||||
const char *event_id,
|
||||
gpointer user_data)
|
||||
{
|
||||
static NMIP4Config *last_config = NULL;
|
||||
|
|
|
|||
|
|
@ -1656,30 +1656,9 @@ nm_ip6_config_find_first_address (const NMIP6Config *self,
|
|||
nm_assert (NM_FLAGS_ANY (match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY));
|
||||
|
||||
nm_ip_config_iter_ip6_address_for_each (&iter, self, &addr) {
|
||||
|
||||
if (IN6_IS_ADDR_LINKLOCAL (&addr->address)) {
|
||||
if (!NM_FLAGS_HAS (match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL))
|
||||
continue;
|
||||
} else {
|
||||
if (!NM_FLAGS_HAS (match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_DADFAILED)) {
|
||||
if (!NM_FLAGS_HAS (match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED))
|
||||
continue;
|
||||
} else if ( NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_TENTATIVE)
|
||||
&& !NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_OPTIMISTIC)) {
|
||||
if (!NM_FLAGS_HAS (match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE))
|
||||
continue;
|
||||
} else {
|
||||
if (!NM_FLAGS_HAS (match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL))
|
||||
continue;
|
||||
}
|
||||
|
||||
return addr;
|
||||
if (nm_platform_ip6_address_match (addr, match_flag))
|
||||
return addr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,14 @@ struct _NML3ConfigData {
|
|||
|
||||
char *nis_domain;
|
||||
|
||||
union {
|
||||
struct {
|
||||
NMDhcpLease *dhcp_lease_6;
|
||||
NMDhcpLease *dhcp_lease_4;
|
||||
};
|
||||
NMDhcpLease *dhcp_lease_x[2];
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
GArray *nameservers_6;
|
||||
|
|
@ -472,6 +480,9 @@ nm_l3_config_data_unref (const NML3ConfigData *self)
|
|||
nm_clear_pointer (&mutable->wins, g_array_unref);
|
||||
nm_clear_pointer (&mutable->nis_servers, g_array_unref);
|
||||
|
||||
nm_clear_pointer (&mutable->dhcp_lease_4, nm_dhcp_lease_unref);
|
||||
nm_clear_pointer (&mutable->dhcp_lease_6, nm_dhcp_lease_unref);
|
||||
|
||||
nm_clear_pointer (&mutable->nameservers_4, g_array_unref);
|
||||
nm_clear_pointer (&mutable->nameservers_6, g_array_unref);
|
||||
|
||||
|
|
@ -572,6 +583,8 @@ nm_l3_config_data_lookup_index (const NML3ConfigData *self, NMPObjectType obj_ty
|
|||
const NMDedupMultiHeadEntry *
|
||||
nm_l3_config_data_lookup_objs (const NML3ConfigData *self, NMPObjectType obj_type)
|
||||
{
|
||||
if (!self)
|
||||
return NULL;
|
||||
return nm_dedup_multi_index_lookup_head (self->multi_idx,
|
||||
nm_l3_config_data_lookup_index (self, obj_type),
|
||||
NULL);
|
||||
|
|
@ -1324,6 +1337,63 @@ nm_l3_config_data_set_source (NML3ConfigData *self,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMDhcpLease *
|
||||
nm_l3_config_data_get_dhcp_lease (const NML3ConfigData *self,
|
||||
int addr_family)
|
||||
{
|
||||
nm_assert (_NM_IS_L3_CONFIG_DATA (self, TRUE));
|
||||
|
||||
return self->dhcp_lease_x[NM_IS_IPv4 (addr_family)];
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_l3_config_data_set_dhcp_lease (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
NMDhcpLease *lease)
|
||||
{
|
||||
nm_auto_unref_dhcplease NMDhcpLease *lease_old = NULL;
|
||||
NMDhcpLease **p_lease;
|
||||
|
||||
nm_assert (_NM_IS_L3_CONFIG_DATA (self, FALSE));
|
||||
|
||||
p_lease = &self->dhcp_lease_x[NM_IS_IPv4 (addr_family)];
|
||||
|
||||
if (*p_lease == lease)
|
||||
return FALSE;
|
||||
|
||||
if (lease)
|
||||
nm_dhcp_lease_ref (lease);
|
||||
lease_old = *p_lease;
|
||||
*p_lease = lease;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_l3_config_data_set_dhcp_lease_from_options (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
GHashTable *options_take)
|
||||
{
|
||||
nm_auto_unref_dhcplease NMDhcpLease *lease = NULL;
|
||||
nm_auto_unref_dhcplease NMDhcpLease *lease_old = NULL;
|
||||
NMDhcpLease **p_lease;
|
||||
|
||||
nm_assert (_NM_IS_L3_CONFIG_DATA (self, FALSE));
|
||||
|
||||
if (options_take)
|
||||
lease = nm_dhcp_lease_new_from_options (g_steal_pointer (&options_take));
|
||||
|
||||
p_lease = &self->dhcp_lease_x[NM_IS_IPv4 (addr_family)];
|
||||
|
||||
if (*p_lease == lease)
|
||||
return FALSE;
|
||||
|
||||
lease_old = *p_lease;
|
||||
*p_lease = g_steal_pointer (&lease);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static int
|
||||
_dedup_multi_index_cmp (const NML3ConfigData *a,
|
||||
const NML3ConfigData *b,
|
||||
|
|
@ -1386,6 +1456,13 @@ nm_l3_config_data_cmp (const NML3ConfigData *a, const NML3ConfigData *b)
|
|||
|
||||
NM_CMP_RETURN (_garray_inaddr_cmp (a->nameservers_x[IS_IPv4], b->nameservers_x[IS_IPv4], addr_family));
|
||||
|
||||
NM_CMP_RETURN (nm_utils_hashtable_cmp (nm_dhcp_lease_get_options (a->dhcp_lease_x[IS_IPv4]),
|
||||
nm_dhcp_lease_get_options (b->dhcp_lease_x[IS_IPv4]),
|
||||
TRUE,
|
||||
nm_strcmp_with_data,
|
||||
nm_strcmp_with_data,
|
||||
NULL));
|
||||
|
||||
NM_CMP_RETURN (nm_strv_ptrarray_cmp (a->domains_x[IS_IPv4], b->domains_x[IS_IPv4]));
|
||||
NM_CMP_RETURN (nm_strv_ptrarray_cmp (a->searches_x[IS_IPv4], b->searches_x[IS_IPv4]));
|
||||
NM_CMP_RETURN (nm_strv_ptrarray_cmp (a->dns_options_x[IS_IPv4], b->dns_options_x[IS_IPv4]));
|
||||
|
|
@ -2177,6 +2254,7 @@ nm_l3_config_data_merge (NML3ConfigData *self,
|
|||
self->mtu = src->mtu;
|
||||
|
||||
/* self->source does not get merged. */
|
||||
/* self->dhcp_lease_x does not get merged. */
|
||||
}
|
||||
|
||||
NML3ConfigData *
|
||||
|
|
|
|||
|
|
@ -486,6 +486,17 @@ gboolean nm_l3_config_data_set_dns_priority (NML3ConfigData *self,
|
|||
int addr_family,
|
||||
int dns_priority);
|
||||
|
||||
struct _NMDhcpLease *nm_l3_config_data_get_dhcp_lease (const NML3ConfigData *self,
|
||||
int addr_family);
|
||||
|
||||
gboolean nm_l3_config_data_set_dhcp_lease (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
struct _NMDhcpLease *lease);
|
||||
|
||||
gboolean nm_l3_config_data_set_dhcp_lease_from_options (NML3ConfigData *self,
|
||||
int addr_family,
|
||||
GHashTable *options_take);
|
||||
|
||||
static inline const NMIPAddr *
|
||||
nmtst_l3_config_data_get_best_gateway (const NML3ConfigData *self,
|
||||
int addr_family)
|
||||
|
|
|
|||
|
|
@ -3018,6 +3018,34 @@ nm_l3cfg_commit_type_unregister (NML3Cfg *self,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
const NML3ConfigData *
|
||||
nm_l3cfg_get_combined_l3cd (NML3Cfg *self)
|
||||
{
|
||||
nm_assert (NM_IS_L3CFG (self));
|
||||
|
||||
return self->priv.p->combined_l3cd;
|
||||
}
|
||||
|
||||
const NMPObject *
|
||||
nm_l3cfg_get_best_default_route (NML3Cfg *self,
|
||||
int addr_family)
|
||||
{
|
||||
nm_assert (NM_IS_L3CFG (self));
|
||||
|
||||
/* we only consider the combined_l3cd. This is a merge of all the l3cd, and the one
|
||||
* with which we called nm_l3cfg_platform_commit() the last time.
|
||||
*
|
||||
* In the meantime, we might have changed the tracked l3_config_datas, but we didn't
|
||||
* nm_l3cfg_platform_commit() yet. These changes are ignored for this purpose, until
|
||||
* the user call nm_l3cfg_platform_commit() to re-commit the changes. */
|
||||
if (!self->priv.p->combined_l3cd)
|
||||
return NULL;
|
||||
|
||||
return nm_l3_config_data_get_best_default_route (self->priv.p->combined_l3cd, addr_family);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
set_property (GObject *object,
|
||||
guint prop_id,
|
||||
|
|
|
|||
|
|
@ -87,6 +87,28 @@ nm_l3cfg_get_ifname (const NML3Cfg *self)
|
|||
return nmp_object_link_get_ifname (self->priv.pllink);
|
||||
}
|
||||
|
||||
static inline const NMPObject *
|
||||
nm_l3cfg_get_plobj (const NML3Cfg *self)
|
||||
{
|
||||
if (!self)
|
||||
return NULL;
|
||||
|
||||
nm_assert (NM_IS_L3CFG (self));
|
||||
|
||||
return self->priv.pllink;
|
||||
}
|
||||
|
||||
static inline const NMPlatformLink *
|
||||
nm_l3cfg_get_pllink (const NML3Cfg *self)
|
||||
{
|
||||
if (!self)
|
||||
return NULL;
|
||||
|
||||
nm_assert (NM_IS_L3CFG (self));
|
||||
|
||||
return NMP_OBJECT_CAST_LINK (self->priv.pllink);
|
||||
}
|
||||
|
||||
static inline NMNetns *
|
||||
nm_l3cfg_get_netns (const NML3Cfg *self)
|
||||
{
|
||||
|
|
@ -198,4 +220,11 @@ void nm_l3cfg_commit_type_unregister (NML3Cfg *self,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
const NML3ConfigData *nm_l3cfg_get_combined_l3cd (NML3Cfg *self);
|
||||
|
||||
const NMPObject *nm_l3cfg_get_best_default_route (NML3Cfg *self,
|
||||
int addr_family);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* __NM_L3CFG_H__ */
|
||||
|
|
|
|||
|
|
@ -3400,6 +3400,38 @@ nm_platform_ip6_address_get_peer (const NMPlatformIP6Address *addr)
|
|||
return &addr->peer_address;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_platform_ip6_address_match (const NMPlatformIP6Address *addr,
|
||||
NMPlatformMatchFlags match_flag)
|
||||
{
|
||||
nm_assert (!NM_FLAGS_ANY (match_flag, ~( NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY
|
||||
| NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY)));
|
||||
nm_assert (NM_FLAGS_ANY (match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY));
|
||||
nm_assert (NM_FLAGS_ANY (match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY));
|
||||
|
||||
if (IN6_IS_ADDR_LINKLOCAL (&addr->address)) {
|
||||
if (!NM_FLAGS_HAS (match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL))
|
||||
return FALSE;
|
||||
} else {
|
||||
if (!NM_FLAGS_HAS (match_flag, NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_DADFAILED)) {
|
||||
if (!NM_FLAGS_HAS (match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED))
|
||||
return FALSE;
|
||||
} else if ( NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_TENTATIVE)
|
||||
&& !NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_OPTIMISTIC)) {
|
||||
if (!NM_FLAGS_HAS (match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE))
|
||||
return FALSE;
|
||||
} else {
|
||||
if (!NM_FLAGS_HAS (match_flag, NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_platform_ip4_address_add (NMPlatform *self,
|
||||
int ifindex,
|
||||
|
|
|
|||
|
|
@ -1668,6 +1668,11 @@ struct _NMPLookup;
|
|||
const struct _NMDedupMultiHeadEntry *nm_platform_lookup (NMPlatform *self,
|
||||
const struct _NMPLookup *lookup);
|
||||
|
||||
#define nm_platform_iter_obj_for_each(iter, self, lookup, obj) \
|
||||
for (nm_dedup_multi_iter_init ((iter), nm_platform_lookup ((self), (lookup))); \
|
||||
nm_platform_dedup_multi_iter_next_obj ((iter), (obj), NMP_OBJECT_TYPE_UNKNOWN); \
|
||||
)
|
||||
|
||||
gboolean nm_platform_lookup_predicate_routes_main (const NMPObject *obj,
|
||||
gpointer user_data);
|
||||
gboolean nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel (const NMPObject *obj,
|
||||
|
|
@ -2158,4 +2163,9 @@ void nm_platform_ip4_dev_route_blacklist_set (NMPlatform *self,
|
|||
|
||||
struct _NMDedupMultiIndex *nm_platform_get_multi_idx (NMPlatform *self);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean nm_platform_ip6_address_match (const NMPlatformIP6Address *addr,
|
||||
NMPlatformMatchFlags match_flag);
|
||||
|
||||
#endif /* __NETWORKMANAGER_PLATFORM_H__ */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue