summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-09-11 16:21:57 +0200
committerThomas Haller <thaller@redhat.com>2020-09-11 16:21:57 +0200
commitebd07a809c26962eaa936e3a2ebb4133e7f4b399 (patch)
tree1bffdc94c657fb31d39d7d9374cb46e7796ea4c7
parent75ff7a6daf705957d91054ae435f57b49a2437cc (diff)
parent2535b3a5396724ab451daa19ea059c2866b32f9a (diff)
downloadNetworkManager-ebd07a809c26962eaa936e3a2ebb4133e7f4b399.tar.gz
l3cfg: merge branch 'th/l3cfg-8'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/623
-rw-r--r--shared/nm-glib-aux/nm-shared-utils.c252
-rw-r--r--shared/nm-glib-aux/nm-shared-utils.h32
-rw-r--r--shared/nm-glib-aux/tests/test-shared-general.c117
-rw-r--r--src/NetworkManagerUtils.h61
-rw-r--r--src/devices/nm-device.c2345
-rw-r--r--src/devices/nm-device.h2
-rw-r--r--src/dhcp/nm-dhcp-client.c20
-rw-r--r--src/dhcp/nm-dhcp-manager.c16
-rw-r--r--src/dhcp/nm-dhcp-options.c6
-rw-r--r--src/dhcp/nm-dhcp-utils.c20
-rw-r--r--src/dhcp/nm-dhcp-utils.h2
-rw-r--r--src/nm-core-utils.c107
-rw-r--r--src/nm-core-utils.h20
-rw-r--r--src/nm-iface-helper.c1
-rw-r--r--src/nm-ip6-config.c25
-rw-r--r--src/nm-l3-config-data.c78
-rw-r--r--src/nm-l3-config-data.h11
-rw-r--r--src/nm-l3cfg.c28
-rw-r--r--src/nm-l3cfg.h29
-rw-r--r--src/platform/nm-platform.c32
-rw-r--r--src/platform/nm-platform.h10
21 files changed, 1915 insertions, 1299 deletions
diff --git a/shared/nm-glib-aux/nm-shared-utils.c b/shared/nm-glib-aux/nm-shared-utils.c
index 21fb72dfb3..242719ffed 100644
--- a/shared/nm-glib-aux/nm-shared-utils.c
+++ b/shared/nm-glib-aux/nm-shared-utils.c
@@ -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)
+ 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));
+
+ /* 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 (!a || !b)
+
+ if (!hash_a || !hash_b)
return FALSE;
- if (g_hash_table_size ((GHashTable *) a) != g_hash_table_size ((GHashTable *) b))
+
+ size = g_hash_table_size (hash_a);
+ if (size != g_hash_table_size (hash_b))
return FALSE;
- 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))
- 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 **
diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h
index aa6169d43b..e413531fd8 100644
--- a/shared/nm-glib-aux/nm-shared-utils.h
+++ b/shared/nm-glib-aux/nm-shared-utils.h
@@ -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); \
})
/*****************************************************************************/
diff --git a/shared/nm-glib-aux/tests/test-shared-general.c b/shared/nm-glib-aux/tests/test-shared-general.c
index 2d5bbd2220..4e31ade8a7 100644
--- a/shared/nm-glib-aux/tests/test-shared-general.c
+++ b/shared/nm-glib-aux/tests/test-shared-general.c
@@ -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 ();
}
diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h
index 7d2b81dd49..5b3a9f9489 100644
--- a/src/NetworkManagerUtils.h
+++ b/src/NetworkManagerUtils.h
@@ -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__ */
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 832116bd05..c1a2bab12b 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -442,6 +442,11 @@ typedef struct _NMDevicePrivate {
NML3ConfigMergeFlags l3config_merge_flags_x[2];
};
+ union {
+ const NMDeviceSysIfaceState sys_iface_state;
+ NMDeviceSysIfaceState sys_iface_state_;
+ };
+
bool carrier:1;
bool ignore_carrier:1;
@@ -453,8 +458,6 @@ typedef struct _NMDevicePrivate {
bool default_route_metric_penalty_ip4_has:1;
bool default_route_metric_penalty_ip6_has:1;
- NMDeviceSysIfaceState sys_iface_state:2;
-
bool v4_route_table_initialized:1;
bool v6_route_table_initialized:1;
@@ -537,7 +540,6 @@ typedef struct _NMDevicePrivate {
/* DHCPv4 tracking */
struct {
char * pac_url;
- char * root_path;
} dhcp4;
struct {
@@ -705,7 +707,7 @@ static gboolean linklocal6_start (NMDevice *self);
static guint32 default_route_metric_penalty_get (NMDevice *self, int addr_family);
-static guint get_ipv4_dad_timeout (NMDevice *self);
+static guint _prop_get_ipv4_dad_timeout (NMDevice *self);
static void _carrier_wait_check_queued_act_request (NMDevice *self);
static gint64 _get_carrier_wait_ms (NMDevice *self);
@@ -869,6 +871,1076 @@ NM_UTILS_LOOKUP_STR_DEFINE (mtu_source_to_str, NMDeviceMtuSource,
/*****************************************************************************/
+static NMSettingIP6ConfigPrivacy
+_ip6_privacy_clamp (NMSettingIP6ConfigPrivacy use_tempaddr)
+{
+ switch (use_tempaddr) {
+ case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED:
+ case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR:
+ case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR:
+ return use_tempaddr;
+ default:
+ return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
+ }
+}
+
+/*****************************************************************************/
+
+static const char *
+_prop_get_connection_stable_id (NMDevice *self,
+ NMConnection *connection,
+ NMUtilsStableType *out_stable_type)
+{
+ NMDevicePrivate *priv;
+
+ nm_assert (NM_IS_DEVICE (self));
+ nm_assert (NM_IS_CONNECTION (connection));
+ nm_assert (out_stable_type);
+
+ priv = NM_DEVICE_GET_PRIVATE (self);
+
+ /* we cache the generated stable ID for the time of an activation.
+ *
+ * The reason is, that we don't want the stable-id to change as long
+ * as the device is active.
+ *
+ * Especially with ${RANDOM} stable-id we want to generate *one* configuration
+ * for each activation. */
+ if (G_UNLIKELY (!priv->current_stable_id)) {
+ gs_free char *default_id = NULL;
+ gs_free char *generated = NULL;
+ NMUtilsStableType stable_type;
+ NMSettingConnection *s_con;
+ gboolean hwaddr_is_fake;
+ const char *hwaddr;
+ const char *stable_id;
+ const char *uuid;
+
+ s_con = nm_connection_get_setting_connection (connection);
+
+ stable_id = nm_setting_connection_get_stable_id (s_con);
+
+ if (!stable_id) {
+ default_id = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
+ NM_CON_DEFAULT ("connection.stable-id"),
+ self);
+ stable_id = default_id;
+ }
+
+ uuid = nm_connection_get_uuid (connection);
+
+ /* the cloned-mac-address may be generated based on the stable-id.
+ * Thus, at this point, we can only use the permanent MAC address
+ * as seed. */
+ hwaddr = nm_device_get_permanent_hw_address_full (self, TRUE, &hwaddr_is_fake);
+
+ stable_type = nm_utils_stable_id_parse (stable_id,
+ nm_device_get_ip_iface (self),
+ !hwaddr_is_fake ? hwaddr : NULL,
+ nm_utils_boot_id_str (),
+ uuid,
+ &generated);
+
+ /* current_stable_id_type is a bitfield! */
+ priv->current_stable_id_type = stable_type;
+ nm_assert (stable_type <= (NMUtilsStableType) 0x3);
+ nm_assert (stable_type + (NMUtilsStableType) 1 > (NMUtilsStableType) 0);
+ nm_assert (priv->current_stable_id_type == stable_type);
+
+ if (stable_type == NM_UTILS_STABLE_TYPE_UUID)
+ priv->current_stable_id = g_strdup (uuid);
+ else if (stable_type == NM_UTILS_STABLE_TYPE_STABLE_ID)
+ priv->current_stable_id = g_strdup (stable_id);
+ else if (stable_type == NM_UTILS_STABLE_TYPE_GENERATED)
+ priv->current_stable_id = nm_str_realloc (nm_utils_stable_id_generated_complete (generated));
+ else {
+ nm_assert (stable_type == NM_UTILS_STABLE_TYPE_RANDOM);
+ priv->current_stable_id = nm_str_realloc (nm_utils_stable_id_random ());
+ }
+ _LOGT (LOGD_DEVICE,
+ "stable-id: type=%d, \"%s\""
+ "%s%s%s",
+ (int) priv->current_stable_id_type,
+ priv->current_stable_id,
+ NM_PRINT_FMT_QUOTED (stable_type == NM_UTILS_STABLE_TYPE_GENERATED, " from \"", generated, "\"", ""));
+ }
+
+ nm_assert (priv->current_stable_id);
+ *out_stable_type = priv->current_stable_id_type;
+ return priv->current_stable_id;
+}
+
+static GBytes *
+_prop_get_ipv6_dhcp_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboolean *out_enforce)
+{
+ NMSettingIPConfig *s_ip6;
+ const char *duid;
+ gs_free char *duid_default = NULL;
+ const char *duid_error;
+ GBytes *duid_out;
+ gboolean duid_enforce = TRUE;
+ gs_free char *logstr1 = NULL;
+ const guint8 *hwaddr_bin;
+ gsize hwaddr_len;
+ int arp_type;
+
+ s_ip6 = nm_connection_get_setting_ip6_config (connection);
+ duid = nm_setting_ip6_config_get_dhcp_duid (NM_SETTING_IP6_CONFIG (s_ip6));
+
+ if (!duid) {
+ duid_default = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
+ NM_CON_DEFAULT ("ipv6.dhcp-duid"),
+ self);
+ duid = duid_default;
+ if (!duid)
+ duid = "lease";
+ }
+
+ if (nm_streq (duid, "lease")) {
+ duid_enforce = FALSE;
+ duid_out = nm_utils_generate_duid_from_machine_id ();
+ goto out_good;
+ }
+
+ if (!_nm_utils_dhcp_duid_valid (duid, &duid_out)) {
+ duid_error = "invalid duid";
+ goto out_fail;
+ }
+
+ if (duid_out)
+ goto out_good;
+
+ if (NM_IN_STRSET (duid, "ll", "llt")) {
+ if (!hwaddr) {
+ duid_error = "missing link-layer address";
+ goto out_fail;
+ }
+
+ hwaddr_bin = g_bytes_get_data (hwaddr, &hwaddr_len);
+ arp_type = nm_utils_arp_type_detect_from_hwaddrlen (hwaddr_len);
+ if (arp_type < 0) {
+ duid_error = "unsupported link-layer address";
+ goto out_fail;
+ }
+
+ if (nm_streq (duid, "ll"))
+ duid_out = nm_utils_generate_duid_ll (arp_type, hwaddr_bin, hwaddr_len);
+ else {
+ duid_out = nm_utils_generate_duid_llt (arp_type, hwaddr_bin, hwaddr_len,
+ nm_utils_host_id_get_timestamp_ns () / NM_UTILS_NSEC_PER_SEC);
+ }
+
+ goto out_good;
+ }
+
+ if (NM_IN_STRSET (duid, "stable-ll", "stable-llt", "stable-uuid")) {
+ /* preferably, we would salt the checksum differently for each @duid type. We missed
+ * to do that initially, so most types use the DEFAULT_SALT.
+ *
+ * Implementations that are added later, should use a distinct salt instead,
+ * like "stable-ll"/"stable-llt" with ARPHRD_INFINIBAND below. */
+ const guint32 DEFAULT_SALT = 670531087u;
+ nm_auto_free_checksum GChecksum *sum = NULL;
+ NMUtilsStableType stable_type;
+ const char *stable_id = NULL;
+ guint32 salted_header;
+ const guint8 *host_id;
+ gsize host_id_len;
+ union {
+ guint8 sha256[NM_UTILS_CHECKSUM_LENGTH_SHA256];
+ guint8 hwaddr_eth[ETH_ALEN];
+ guint8 hwaddr_infiniband[INFINIBAND_ALEN];
+ NMUuid uuid;
+ struct _nm_packed {
+ guint8 hwaddr[ETH_ALEN];
+ guint32 timestamp;
+ } llt_eth;
+ struct _nm_packed {
+ guint8 hwaddr[INFINIBAND_ALEN];
+ guint32 timestamp;
+ } llt_infiniband;
+ } digest;
+
+ stable_id = _prop_get_connection_stable_id (self, connection, &stable_type);
+
+ if (NM_IN_STRSET (duid, "stable-ll", "stable-llt")) {
+ /* for stable LL/LLT DUIDs, we still need a hardware address to detect
+ * the arp-type. Alternatively, we would be able to detect it based on
+ * other means (e.g. NMDevice type), but instead require the hardware
+ * address to be present. This is at least consistent with the "ll"/"llt"
+ * modes above. */
+ if (!hwaddr) {
+ duid_error = "missing link-layer address";
+ goto out_fail;
+ }
+ if ((arp_type = nm_utils_arp_type_detect_from_hwaddrlen (g_bytes_get_size (hwaddr))) < 0) {
+ duid_error = "unsupported link-layer address";
+ goto out_fail;
+ }
+
+ if (arp_type == ARPHRD_ETHER)
+ salted_header = DEFAULT_SALT;
+ else {
+ nm_assert (arp_type == ARPHRD_INFINIBAND);
+ salted_header = 0x42492CEFu + ((guint32) arp_type);
+ }
+ } else {
+ salted_header = DEFAULT_SALT;
+ arp_type = -1;
+ }
+
+ salted_header = htonl (salted_header + ((guint32) stable_type));
+
+ nm_utils_host_id_get (&host_id, &host_id_len);
+
+ sum = g_checksum_new (G_CHECKSUM_SHA256);
+ g_checksum_update (sum, (const guchar *) &salted_header, sizeof (salted_header));
+ g_checksum_update (sum, (const guchar *) stable_id, -1);
+ g_checksum_update (sum, (const guchar *) host_id, host_id_len);
+ nm_utils_checksum_get_digest (sum, digest.sha256);
+
+ G_STATIC_ASSERT_EXPR (sizeof (digest) == sizeof (digest.sha256));
+
+ if (nm_streq (duid, "stable-ll")) {
+ switch (arp_type) {
+ case ARPHRD_ETHER:
+ duid_out = nm_utils_generate_duid_ll (arp_type, digest.hwaddr_eth, sizeof (digest.hwaddr_eth));
+ break;
+ case ARPHRD_INFINIBAND:
+ duid_out = nm_utils_generate_duid_ll (arp_type, digest.hwaddr_infiniband, sizeof (digest.hwaddr_infiniband));
+ break;
+ default:
+ g_return_val_if_reached (NULL);
+ }
+ } else if (nm_streq (duid, "stable-llt")) {
+ gint64 time;
+ guint32 timestamp;
+
+#define EPOCH_DATETIME_THREE_YEARS (356 * 24 * 3600 * 3)
+
+ /* We want a variable time between the host_id timestamp and three years
+ * before. Let's compute the time (in seconds) from 0 to 3 years; then we'll
+ * subtract it from the host_id timestamp.
+ */
+ time = nm_utils_host_id_get_timestamp_ns () / NM_UTILS_NSEC_PER_SEC;
+
+ /* don't use too old timestamps. They cannot be expressed in DUID-LLT and
+ * would all be truncated to zero. */
+ time = NM_MAX (time, NM_UTILS_EPOCH_DATETIME_200001010000 + EPOCH_DATETIME_THREE_YEARS);
+
+ switch (arp_type) {
+ case ARPHRD_ETHER:
+ timestamp = unaligned_read_be32 (&digest.llt_eth.timestamp);
+ time -= timestamp % EPOCH_DATETIME_THREE_YEARS;
+ duid_out = nm_utils_generate_duid_llt (arp_type, digest.llt_eth.hwaddr, sizeof (digest.llt_eth.hwaddr), time);
+ break;
+ case ARPHRD_INFINIBAND:
+ timestamp = unaligned_read_be32 (&digest.llt_infiniband.timestamp);
+ time -= timestamp % EPOCH_DATETIME_THREE_YEARS;
+ duid_out = nm_utils_generate_duid_llt (arp_type, digest.llt_infiniband.hwaddr, sizeof (digest.llt_infiniband.hwaddr), time);
+ break;
+ default:
+ g_return_val_if_reached (NULL);
+ }
+ } else {
+ nm_assert (nm_streq (duid, "stable-uuid"));
+ duid_out = nm_utils_generate_duid_uuid (&digest.uuid);
+ }
+
+ goto out_good;
+ }
+
+ g_return_val_if_reached (NULL);
+
+out_fail:
+ nm_assert (!duid_out && duid_error);
+ {
+ NMUuid uuid;
+
+ _LOGW (LOGD_IP6 | LOGD_DHCP6,
+ "ipv6.dhcp-duid: failure to generate %s DUID: %s. Fallback to random DUID-UUID.",
+ duid, duid_error);
+
+ nm_utils_random_bytes (&uuid, sizeof (uuid));
+ duid_out = nm_utils_generate_duid_uuid (&uuid);
+ }
+
+out_good:
+ nm_assert (duid_out);
+ _LOGD (LOGD_IP6 | LOGD_DHCP6,
+ "ipv6.dhcp-duid: generate %s DUID '%s' (%s)",
+ duid,
+ (logstr1 = nm_dhcp_utils_duid_to_string (duid_out)),
+ duid_enforce ? "enforcing" : "prefer lease");
+
+ NM_SET_OUT (out_enforce, duid_enforce);
+ return duid_out;
+}
+
+static gint32
+_prop_get_ipv6_ra_timeout (NMDevice *self)
+{
+ NMConnection *connection;
+ gint32 timeout;
+
+ G_STATIC_ASSERT_EXPR (NM_RA_TIMEOUT_DEFAULT == 0);
+ G_STATIC_ASSERT_EXPR (NM_RA_TIMEOUT_INFINITY == G_MAXINT32);
+
+ connection = nm_device_get_applied_connection (self);
+
+ timeout = nm_setting_ip6_config_get_ra_timeout (NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection)));
+ nm_assert (timeout >= 0);
+ if (timeout)
+ return timeout;
+
+ return nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
+ NM_CON_DEFAULT ("ipv6.ra-timeout"),
+ self,
+ 0, G_MAXINT32, 0);
+}
+
+static NMSettingConnectionMdns
+_prop_get_connection_mdns (NMDevice *self)
+{
+ NMConnection *connection;
+ NMSettingConnectionMdns mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT;
+
+ g_return_val_if_fail (NM_IS_DEVICE (self), NM_SETTING_CONNECTION_MDNS_DEFAULT);
+
+ connection = nm_device_get_applied_connection (self);
+ if (connection)
+ mdns = nm_setting_connection_get_mdns (nm_connection_get_setting_connection (connection));
+ if (mdns != NM_SETTING_CONNECTION_MDNS_DEFAULT)
+ return mdns;
+
+ return nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
+ NM_CON_DEFAULT ("connection.mdns"),
+ self,
+ NM_SETTING_CONNECTION_MDNS_NO,
+ NM_SETTING_CONNECTION_MDNS_YES,
+ NM_SETTING_CONNECTION_MDNS_DEFAULT);
+}
+
+static NMSettingConnectionLlmnr
+_prop_get_connection_llmnr (NMDevice *self)
+{
+ NMConnection *connection;
+ NMSettingConnectionLlmnr llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT;
+
+ g_return_val_if_fail (NM_IS_DEVICE (self), NM_SETTING_CONNECTION_LLMNR_DEFAULT);
+
+ connection = nm_device_get_applied_connection (self);
+ if (connection)
+ llmnr = nm_setting_connection_get_llmnr (nm_connection_get_setting_connection (connection));
+ if (llmnr != NM_SETTING_CONNECTION_LLMNR_DEFAULT)
+ return llmnr;
+
+ return nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
+ NM_CON_DEFAULT ("connection.llmnr"),
+ self,
+ NM_SETTING_CONNECTION_LLMNR_NO,
+ NM_SETTING_CONNECTION_LLMNR_YES,
+ NM_SETTING_CONNECTION_LLMNR_DEFAULT);
+}
+
+static guint32
+_prop_get_ipvx_route_table (NMDevice *self,
+ int addr_family)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ NMDeviceClass *klass;
+ NMConnection *connection;
+ NMSettingIPConfig *s_ip;
+ guint32 route_table = 0;
+ gboolean is_user_config = TRUE;
+ NMSettingConnection *s_con;
+ NMSettingVrf *s_vrf;
+
+ nm_assert_addr_family (addr_family);
+
+ /* the route table setting affects how we sync routes. We shall
+ * not change it while the device is active, hence, cache it. */
+ if (addr_family == AF_INET) {
+ if (priv->v4_route_table_initialized)
+ return priv->v4_route_table;
+ } else {
+ if (priv->v6_route_table_initialized)
+ return priv->v6_route_table;
+ }
+
+ connection = nm_device_get_applied_connection (self);
+ if (connection) {
+ s_ip = nm_connection_get_setting_ip_config (connection, addr_family);
+ if (s_ip)
+ route_table = nm_setting_ip_config_get_route_table (s_ip);
+ }
+ if (route_table == 0u) {
+ gint64 v;
+
+ v = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
+ addr_family == AF_INET
+ ? NM_CON_DEFAULT ("ipv4.route-table")
+ : NM_CON_DEFAULT ("ipv6.route-table"),
+ self,
+ 0,
+ G_MAXUINT32,
+ -1);
+ if (v != -1) {
+ route_table = v;
+ is_user_config = FALSE;
+ }
+ }
+
+ if ( route_table == 0u
+ && connection
+ && (s_con = nm_connection_get_setting_connection (connection))
+ && (nm_streq0 (nm_setting_connection_get_slave_type (s_con), NM_SETTING_VRF_SETTING_NAME)
+ && priv->master
+ && nm_device_get_device_type (priv->master) == NM_DEVICE_TYPE_VRF)) {
+ const NMPlatformLnkVrf *lnk;
+
+ lnk = nm_platform_link_get_lnk_vrf (nm_device_get_platform (self),
+ nm_device_get_ifindex (priv->master),
+ NULL);
+
+ if (lnk)
+ route_table = lnk->table;
+ }
+
+ if ( route_table == 0u
+ && connection
+ && (s_vrf = (NMSettingVrf *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VRF))) {
+ route_table = nm_setting_vrf_get_table (s_vrf);
+ }
+
+ klass = NM_DEVICE_GET_CLASS (self);
+ if (klass->coerce_route_table)
+ route_table = klass->coerce_route_table (self, addr_family, route_table, is_user_config);
+
+ if (addr_family == AF_INET) {
+ priv->v4_route_table_initialized = TRUE;
+ priv->v4_route_table = route_table;
+ } else {
+ priv->v6_route_table_initialized = TRUE;
+ priv->v6_route_table = route_table;
+ }
+
+ _LOGT (LOGD_DEVICE,
+ "ipv%c.route-table = %u%s",
+ addr_family == AF_INET ? '4' : '6',
+ (guint) (route_table ?: RT_TABLE_MAIN),
+ route_table != 0u ? "" : " (policy routing not enabled)");
+
+ return route_table;
+}
+
+static gboolean
+_prop_get_connection_lldp (NMDevice *self)
+{
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSettingConnectionLldp lldp = NM_SETTING_CONNECTION_LLDP_DEFAULT;
+
+ connection = nm_device_get_applied_connection (self);
+ g_return_val_if_fail (connection, FALSE);
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_return_val_if_fail (s_con, FALSE);
+
+ lldp = nm_setting_connection_get_lldp (s_con);
+ if (lldp == NM_SETTING_CONNECTION_LLDP_DEFAULT) {
+ lldp = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
+ NM_CON_DEFAULT ("connection.lldp"),
+ self,
+ NM_SETTING_CONNECTION_LLDP_DEFAULT,
+ NM_SETTING_CONNECTION_LLDP_ENABLE_RX,
+ NM_SETTING_CONNECTION_LLDP_DEFAULT);
+ if (lldp == NM_SETTING_CONNECTION_LLDP_DEFAULT)
+ lldp = NM_SETTING_CONNECTION_LLDP_DISABLE;
+ }
+ return lldp == NM_SETTING_CONNECTION_LLDP_ENABLE_RX;
+}
+
+static guint
+_prop_get_ipv4_dad_timeout (NMDevice *self)
+{
+ NMConnection *connection;
+ NMSettingIPConfig *s_ip4 = NULL;
+ int timeout = -1;
+
+ connection = nm_device_get_applied_connection (self);
+ if (connection)
+ s_ip4 = nm_connection_get_setting_ip4_config (connection);
+ if (s_ip4)
+ timeout = nm_setting_ip_config_get_dad_timeout (s_ip4);
+ if (timeout >= 0)
+ return timeout;
+
+ return nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
+ NM_CON_DEFAULT ("ipv4.dad-timeout"),
+ self,
+ 0,
+ NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX,
+ 0);
+}
+
+static guint32
+_prop_get_ipvx_dhcp_timeout (NMDevice *self, int addr_family)
+{
+ NMDeviceClass *klass;
+ NMConnection *connection;
+ int timeout_i;
+ guint32 timeout;
+
+ nm_assert (NM_IS_DEVICE (self));
+ nm_assert_addr_family (addr_family);
+
+ connection = nm_device_get_applied_connection (self);
+
+ timeout_i = nm_setting_ip_config_get_dhcp_timeout (nm_connection_get_setting_ip_config (connection, addr_family));
+ nm_assert (timeout_i >= 0 && timeout_i <= G_MAXINT32);
+
+ timeout = (guint32) timeout_i;
+ if (timeout)
+ goto out;
+
+ timeout = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
+ addr_family == AF_INET
+ ? NM_CON_DEFAULT ("ipv4.dhcp-timeout")
+ : NM_CON_DEFAULT ("ipv6.dhcp-timeout"),
+ self,
+ 0, G_MAXINT32, 0);
+ if (timeout)
+ goto out;
+
+ klass = NM_DEVICE_GET_CLASS (self);
+ if (klass->get_dhcp_timeout_for_device) {
+ timeout = klass->get_dhcp_timeout_for_device (self, addr_family);
+ if (timeout)
+ goto out;
+ }
+
+ timeout = NM_DHCP_TIMEOUT_DEFAULT;
+
+out:
+ G_STATIC_ASSERT_EXPR (G_MAXINT32 == NM_DHCP_TIMEOUT_INFINITY);
+ nm_assert (timeout > 0);
+ nm_assert (timeout <= G_MAXINT32);
+ return timeout;
+}
+
+/**
+ * _prop_get_ipvx_dhcp_iaid:
+ * @self: the #NMDevice
+ * @addr_family: the address family
+ * @connection: the connection
+ * @out_is_explicit: on return, %TRUE if the user set a valid IAID in
+ * the connection or in global configuration; %FALSE if the connection
+ * property was empty and no valid global configuration was provided.
+ *
+ * Returns: a IAID value for this device and the given connection.
+ */
+static guint32
+_prop_get_ipvx_dhcp_iaid (NMDevice *self,
+ int addr_family,
+ NMConnection *connection,
+ gboolean *out_is_explicit)
+{
+ NMSettingIPConfig *s_ip;
+ const char *iaid_str;
+ gs_free char *iaid_str_free = NULL;
+ guint32 iaid;
+ const char *iface;
+ const char *fail_reason;
+ gboolean is_explicit = TRUE;
+
+ s_ip = nm_connection_get_setting_ip_config (connection, addr_family);
+ iaid_str = nm_setting_ip_config_get_dhcp_iaid (s_ip);
+ if (!iaid_str) {
+ iaid_str_free = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
+ addr_family == AF_INET
+ ? NM_CON_DEFAULT ("ipv4.dhcp-iaid")
+ : NM_CON_DEFAULT ("ipv6.dhcp-iaid"),
+ self);
+ iaid_str = iaid_str_free;
+ if (!iaid_str) {
+ iaid_str = NM_IAID_IFNAME;
+ is_explicit = FALSE;
+ } else if (!_nm_utils_iaid_verify (iaid_str, NULL)) {
+ _LOGW (LOGD_DEVICE, "invalid global default '%s' for ipv%c.dhcp-iaid",
+ iaid_str,
+ nm_utils_addr_family_to_char (addr_family));
+ iaid_str = NM_IAID_IFNAME;
+ is_explicit = FALSE;
+ }
+ }
+
+ if (nm_streq0 (iaid_str, NM_IAID_MAC)) {
+ const NMPlatformLink *pllink;
+
+ pllink = nm_platform_link_get (nm_device_get_platform (self),
+ nm_device_get_ip_ifindex (self));
+ if (!pllink || pllink->l_address.len < 4) {
+ fail_reason = "invalid link-layer address";
+ goto out_fail;
+ }
+
+ /* @iaid is in native endianness. Use unaligned_read_be32()
+ * so that the IAID for a given MAC address is the same on
+ * BE and LE machines. */
+ iaid = unaligned_read_be32 (&pllink->l_address.data[pllink->l_address.len - 4]);
+ goto out_good;
+ } else if (nm_streq0 (iaid_str, NM_IAID_PERM_MAC)) {
+ guint8 hwaddr_buf[NM_UTILS_HWADDR_LEN_MAX];
+ const char *hwaddr_str;
+ gsize hwaddr_len;
+
+ hwaddr_str = nm_device_get_permanent_hw_address (self);
+ if (!hwaddr_str) {
+ fail_reason = "no permanent link-layer address";
+ goto out_fail;
+ }
+
+ if (!_nm_utils_hwaddr_aton (hwaddr_str, hwaddr_buf, sizeof (hwaddr_buf), &hwaddr_len))
+ g_return_val_if_reached (0);
+
+ if (hwaddr_len < 4) {
+ fail_reason = "invalid link-layer address";
+ goto out_fail;
+ }
+
+ iaid = unaligned_read_be32 (&hwaddr_buf[hwaddr_len - 4]);
+ goto out_good;
+ } else if (nm_streq (iaid_str, "stable")) {
+ nm_auto_free_checksum GChecksum *sum = NULL;
+ guint8 digest[NM_UTILS_CHECKSUM_LENGTH_SHA1];
+ NMUtilsStableType stable_type;
+ const char *stable_id;
+ guint32 salted_header;
+ const guint8 *host_id;
+ gsize host_id_len;
+
+ stable_id = _prop_get_connection_stable_id (self, connection, &stable_type);
+ salted_header = htonl (53390459 + stable_type);
+ nm_utils_host_id_get (&host_id, &host_id_len);
+ iface = nm_device_get_ip_iface (self);
+
+ sum = g_checksum_new (G_CHECKSUM_SHA1);
+ g_checksum_update (sum, (const guchar *) &salted_header, sizeof (salted_header));
+ g_checksum_update (sum, (const guchar *) stable_id, strlen (stable_id) + 1);
+ g_checksum_update (sum, (const guchar *) iface, strlen (iface) + 1);
+ g_checksum_update (sum, (const guchar *) host_id, host_id_len);
+ nm_utils_checksum_get_digest (sum, digest);
+
+ iaid = unaligned_read_be32 (digest);
+ goto out_good;
+ } else if ((iaid = _nm_utils_ascii_str_to_int64 (iaid_str, 10, 0, G_MAXUINT32, -1)) != -1) {
+ goto out_good;
+ } else {
+ iface = nm_device_get_ip_iface (self);
+ iaid = nm_utils_create_dhcp_iaid (TRUE,
+ (const guint8 *) iface,
+ strlen (iface));
+ goto out_good;
+ }
+
+out_fail:
+ nm_assert (fail_reason);
+ _LOGW ( addr_family == AF_INET
+ ? (LOGD_DEVICE | LOGD_DHCP4 | LOGD_IP4)
+ : (LOGD_DEVICE | LOGD_DHCP6 | LOGD_IP6),
+ "ipv%c.dhcp-iaid: failure to generate IAID: %s. Using interface-name based IAID",
+ nm_utils_addr_family_to_char (addr_family), fail_reason);
+ is_explicit = FALSE;
+ iface = nm_device_get_ip_iface (self);
+ iaid = nm_utils_create_dhcp_iaid (TRUE,
+ (const guint8 *) iface,
+ strlen (iface));
+out_good:
+ _LOGD ( addr_family == AF_INET
+ ? (LOGD_DEVICE | LOGD_DHCP4 | LOGD_IP4)
+ : (LOGD_DEVICE | LOGD_DHCP6 | LOGD_IP6),
+ "ipv%c.dhcp-iaid: using %u (0x%08x) IAID (str: '%s', explicit %d)",
+ nm_utils_addr_family_to_char (addr_family), iaid, iaid,
+ iaid_str, is_explicit);
+ NM_SET_OUT (out_is_explicit, is_explicit);
+ return iaid;
+}
+
+static NMDhcpHostnameFlags
+_prop_get_ipvx_dhcp_hostname_flags (NMDevice *self, int addr_family)
+{
+ NMConnection *connection;
+ NMSettingIPConfig *s_ip;
+ NMDhcpHostnameFlags flags;
+ gs_free_error GError *error = NULL;
+
+ g_return_val_if_fail (NM_IS_DEVICE (self), NM_DHCP_HOSTNAME_FLAG_NONE);
+
+ connection = nm_device_get_applied_connection (self);
+ s_ip = nm_connection_get_setting_ip_config (connection, addr_family);
+ g_return_val_if_fail (s_ip, NM_DHCP_HOSTNAME_FLAG_NONE);
+
+ if (!nm_setting_ip_config_get_dhcp_send_hostname (s_ip))
+ return NM_DHCP_HOSTNAME_FLAG_NONE;
+
+ flags = nm_setting_ip_config_get_dhcp_hostname_flags (s_ip);
+ if (flags != NM_DHCP_HOSTNAME_FLAG_NONE)
+ return flags;
+
+ flags = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
+ addr_family == AF_INET
+ ? NM_CON_DEFAULT ("ipv4.dhcp-hostname-flags")
+ : NM_CON_DEFAULT ("ipv6.dhcp-hostname-flags"),
+ self,
+ 0, NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS,
+ 0);
+
+ if (!_nm_utils_validate_dhcp_hostname_flags (flags, addr_family, &error)) {
+ _LOGW (LOGD_DEVICE, "invalid global default value 0x%x for ipv%d.%s: %s",
+ (guint) flags,
+ addr_family == AF_INET ? 4 : 6,
+ NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS,
+ error->message);
+ flags = NM_DHCP_HOSTNAME_FLAG_NONE;
+ }
+
+ if (flags != NM_DHCP_HOSTNAME_FLAG_NONE)
+ return flags;
+
+ if (addr_family == AF_INET)
+ return NM_DHCP_HOSTNAME_FLAGS_FQDN_DEFAULT_IP4;
+ else
+ return NM_DHCP_HOSTNAME_FLAGS_FQDN_DEFAULT_IP6;
+}
+
+static const char *
+_prop_get_connection_mud_url (NMDevice *self,
+ NMSettingConnection *s_con,
+ char **out_mud_url)
+{
+ const char *mud_url;
+ gs_free char *s = NULL;
+
+ nm_assert (out_mud_url && !*out_mud_url);
+
+ mud_url = nm_setting_connection_get_mud_url (s_con);
+
+ if (mud_url) {
+ if (nm_streq (mud_url, NM_CONNECTION_MUD_URL_NONE))
+ return NULL;
+ return mud_url;
+ }
+
+ s = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
+ NM_CON_DEFAULT ("connection.mud-url"),
+ self);
+ if (s) {
+ if (nm_streq (s, NM_CONNECTION_MUD_URL_NONE))
+ return NULL;
+ if (nm_sd_http_url_is_valid_https (s))
+ return (*out_mud_url = g_steal_pointer (&s));
+ }
+
+ return NULL;
+}
+
+static GBytes *
+_prop_get_ipv4_dhcp_client_id (NMDevice *self,
+ NMConnection *connection,
+ GBytes *hwaddr)
+{
+ NMSettingIPConfig *s_ip4;
+ const char *client_id;
+ gs_free char *client_id_default = NULL;
+ guint8 *client_id_buf;
+ const char *fail_reason;
+ guint8 hwaddr_bin_buf[NM_UTILS_HWADDR_LEN_MAX];
+ const guint8 *hwaddr_bin;
+ int arp_type;
+ gsize hwaddr_len;
+ GBytes *result;
+ gs_free char *logstr1 = NULL;
+
+ s_ip4 = nm_connection_get_setting_ip4_config (connection);
+ client_id = nm_setting_ip4_config_get_dhcp_client_id (NM_SETTING_IP4_CONFIG (s_ip4));
+
+ if (!client_id) {
+ client_id_default = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
+ NM_CON_DEFAULT ("ipv4.dhcp-client-id"),
+ self);
+ if (client_id_default && client_id_default[0]) {
+ /* a non-empty client-id is always valid, see nm_dhcp_utils_client_id_string_to_bytes(). */
+ client_id = client_id_default;
+ }
+ }
+
+ if (!client_id) {
+ _LOGD (LOGD_DEVICE | LOGD_DHCP4 | LOGD_IP4,
+ "ipv4.dhcp-client-id: no explicit client-id configured");
+ return NULL;
+ }
+
+ if (nm_streq (client_id, "mac")) {
+ if (!hwaddr) {
+ fail_reason = "missing link-layer address";
+ goto out_fail;
+ }
+
+ hwaddr_bin = g_bytes_get_data (hwaddr, &hwaddr_len);
+ arp_type = nm_utils_arp_type_detect_from_hwaddrlen (hwaddr_len);
+ if (arp_type < 0) {
+ fail_reason = "unsupported link-layer address";
+ goto out_fail;
+ }
+
+ result = nm_utils_dhcp_client_id_mac (arp_type, hwaddr_bin, hwaddr_len);
+ goto out_good;
+ }
+
+ if (nm_streq (client_id, "perm-mac")) {
+ const char *hwaddr_str;
+
+ hwaddr_str = nm_device_get_permanent_hw_address (self);
+ if (!hwaddr_str) {
+ fail_reason = "missing permanent link-layer address";
+ goto out_fail;
+ }
+
+ if (!_nm_utils_hwaddr_aton (hwaddr_str, hwaddr_bin_buf, sizeof (hwaddr_bin_buf), &hwaddr_len))
+ g_return_val_if_reached (NULL);
+
+ arp_type = nm_utils_arp_type_detect_from_hwaddrlen (hwaddr_len);
+ if (arp_type < 0) {
+ fail_reason = "unsupported permanent link-layer address";
+ goto out_fail;
+ }
+
+ result = nm_utils_dhcp_client_id_mac (arp_type, hwaddr_bin_buf, hwaddr_len);
+ goto out_good;
+ }
+
+ if (nm_streq (client_id, "duid")) {
+ guint32 iaid = _prop_get_ipvx_dhcp_iaid (self, AF_INET, connection, NULL);
+
+ result = nm_utils_dhcp_client_id_systemd_node_specific (iaid);
+ goto out_good;
+ }
+
+ if (nm_streq (client_id, "stable")) {
+ nm_auto_free_checksum GChecksum *sum = NULL;
+ guint8 digest[NM_UTILS_CHECKSUM_LENGTH_SHA1];
+ NMUtilsStableType stable_type;
+ const char *stable_id;
+ guint32 salted_header;
+ const guint8 *host_id;
+ gsize host_id_len;
+
+ stable_id = _prop_get_connection_stable_id (self, connection, &stable_type);
+ salted_header = htonl (2011610591 + stable_type);
+ nm_utils_host_id_get (&host_id, &host_id_len);
+
+ sum = g_checksum_new (G_CHECKSUM_SHA1);
+ g_checksum_update (sum, (const guchar *) &salted_header, sizeof (salted_header));
+ g_checksum_update (sum, (const guchar *) stable_id, strlen (stable_id) + 1);
+ g_checksum_update (sum, (const guchar *) host_id, host_id_len);
+ nm_utils_checksum_get_digest (sum, digest);
+
+ client_id_buf = g_malloc (1 + 15);
+ client_id_buf[0] = 0;
+ memcpy (&client_id_buf[1], digest, 15);
+ result = g_bytes_new_take (client_id_buf, 1 + 15);
+ goto out_good;
+ }
+
+ result = nm_dhcp_utils_client_id_string_to_bytes (client_id);
+ goto out_good;
+
+out_fail:
+ nm_assert (fail_reason);
+ _LOGW (LOGD_DEVICE | LOGD_DHCP4 | LOGD_IP4,
+ "ipv4.dhcp-client-id: failure to generate client id (%s). Use random client id",
+ fail_reason);
+ client_id_buf = g_malloc (1 + 15);
+ client_id_buf[0] = 0;
+ nm_utils_random_bytes (&client_id_buf[1], 15);
+ result = g_bytes_new_take (client_id_buf, 1 + 15);
+
+out_good:
+ nm_assert (result);
+ _LOGD (LOGD_DEVICE | LOGD_DHCP4 | LOGD_IP4,
+ "ipv4.dhcp-client-id: use \"%s\" client ID: %s",
+ client_id,
+ (logstr1 = nm_dhcp_utils_duid_to_string (result)));
+ return result;
+}
+
+static GBytes *
+_prop_get_ipv4_dhcp_vendor_class_identifier (NMDevice *self, NMSettingIP4Config *s_ip4)
+{
+ gs_free char *config_data_prop = NULL;
+ gs_free char *to_free = NULL;
+ const char *conn_prop;
+ GBytes *bytes = NULL;
+ const char *bin;
+ gsize len;
+
+ conn_prop = nm_setting_ip4_config_get_dhcp_vendor_class_identifier (s_ip4);
+
+ if (!conn_prop) {
+ /* set in NetworkManager.conf ? */
+ config_data_prop = nm_config_data_get_connection_default (
+ NM_CONFIG_GET_DATA,
+ NM_CON_DEFAULT ("ipv4.dhcp-vendor-class-identifier"),
+ self);
+
+ if ( config_data_prop
+ && nm_utils_validate_dhcp4_vendor_class_id (config_data_prop, NULL))
+ conn_prop = config_data_prop;
+ }
+
+ if (conn_prop) {
+ bin = nm_utils_buf_utf8safe_unescape (conn_prop,
+ NM_UTILS_STR_UTF8_SAFE_FLAG_NONE,
+ &len,
+ (gpointer *) &to_free);
+ if (to_free)
+ bytes = g_bytes_new_take (g_steal_pointer (&to_free), len);
+ else
+ bytes = g_bytes_new (bin, len);
+ }
+
+ return bytes;
+}
+
+static NMSettingIP6ConfigPrivacy
+_prop_get_ipv6_ip6_privacy (NMDevice *self)
+{
+ NMSettingIP6ConfigPrivacy ip6_privacy;
+ NMConnection *connection;
+
+ g_return_val_if_fail (self, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
+
+ /* 1.) First look at the per-connection setting. If it is not -1 (unknown),
+ * use it. */
+ connection = nm_device_get_applied_connection (self);
+ if (connection) {
+ NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config (connection);
+
+ if (s_ip6) {
+ ip6_privacy = nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6));
+ ip6_privacy = _ip6_privacy_clamp (ip6_privacy);
+ if (ip6_privacy != NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN)
+ return ip6_privacy;
+ }
+ }
+
+ /* 2.) use the default value from the configuration. */
+ ip6_privacy = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
+ NM_CON_DEFAULT ("ipv6.ip6-privacy"),
+ self,
+ NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
+ NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
+ NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
+ if (ip6_privacy != NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN)
+ return ip6_privacy;
+
+ if (!nm_device_get_ip_ifindex (self))
+ return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
+
+ /* 3.) No valid default-value configured. Fallback to reading sysctl.
+ *
+ * Instead of reading static config files in /etc, just read the current sysctl value.
+ * This works as NM only writes to "/proc/sys/net/ipv6/conf/IFNAME/use_tempaddr", but leaves
+ * the "default" entry untouched. */
+ ip6_privacy = nm_platform_sysctl_get_int32 (nm_device_get_platform (self),
+ NMP_SYSCTL_PATHID_ABSOLUTE ("/proc/sys/net/ipv6/conf/default/use_tempaddr"),
+ NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
+ return _ip6_privacy_clamp (ip6_privacy);
+}
+
+static const char *
+_prop_get_x_cloned_mac_address (NMDevice *self, NMConnection *connection, gboolean is_wifi, char **out_addr)
+{
+ NMSetting *setting;
+ const char *addr = NULL;
+
+ nm_assert (out_addr && !*out_addr);
+
+ setting = nm_connection_get_setting (connection,
+ is_wifi ? NM_TYPE_SETTING_WIRELESS : NM_TYPE_SETTING_WIRED);
+ if (setting) {
+ addr = is_wifi
+ ? nm_setting_wireless_get_cloned_mac_address ((NMSettingWireless *) setting)
+ : nm_setting_wired_get_cloned_mac_address ((NMSettingWired *) setting);
+ }
+
+ if (!addr) {
+ gs_free char *a = NULL;
+
+ a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
+ is_wifi
+ ? NM_CON_DEFAULT ("wifi.cloned-mac-address")
+ : NM_CON_DEFAULT ("ethernet.cloned-mac-address"),
+ self);
+
+ addr = NM_CLONED_MAC_PRESERVE;
+
+ if (!a) {
+ if (is_wifi) {
+ NMSettingMacRandomization v;
+
+ /* for backward compatibility, read the deprecated wifi.mac-address-randomization setting. */
+ a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
+ NM_CON_DEFAULT ("wifi.mac-address-randomization"),
+ self);
+ v = _nm_utils_ascii_str_to_int64 (a, 10,
+ NM_SETTING_MAC_RANDOMIZATION_DEFAULT,
+ NM_SETTING_MAC_RANDOMIZATION_ALWAYS,
+ NM_SETTING_MAC_RANDOMIZATION_DEFAULT);
+ if (v == NM_SETTING_MAC_RANDOMIZATION_ALWAYS)
+ addr = NM_CLONED_MAC_RANDOM;
+ }
+ } else if ( NM_CLONED_MAC_IS_SPECIAL (a)
+ || nm_utils_hwaddr_valid (a, ETH_ALEN))
+ addr = *out_addr = g_steal_pointer (&a);
+ }
+
+ return addr;
+}
+
+static const char *
+_prop_get_x_generate_mac_address_mask (NMDevice *self, NMConnection *connection, gboolean is_wifi, char **out_value)
+{
+ NMSetting *setting;
+ const char *value = NULL;
+ char *a;
+
+ nm_assert (out_value && !*out_value);
+
+ setting = nm_connection_get_setting (connection,
+ is_wifi ? NM_TYPE_SETTING_WIRELESS : NM_TYPE_SETTING_WIRED);
+ if (setting) {
+ value = is_wifi
+ ? nm_setting_wireless_get_generate_mac_address_mask ((NMSettingWireless *) setting)
+ : nm_setting_wired_get_generate_mac_address_mask ((NMSettingWired *) setting);
+ if (value)
+ return value;
+ }
+
+ a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
+ is_wifi
+ ? NM_CON_DEFAULT ("wifi.generate-mac-address-mask")
+ : NM_CON_DEFAULT ("ethernet.generate-mac-address-mask"),
+ self);
+ if (!a)
+ return NULL;
+ *out_value = a;
+ return a;
+}
+
+/*****************************************************************************/
+
static void
_ethtool_features_reset (NMDevice *self,
NMPlatform *platform,
@@ -1424,7 +2496,7 @@ nm_device_sys_iface_state_set (NMDevice *self,
_LOGT (LOGD_DEVICE, "sys-iface-state: %s -> %s",
_sys_iface_state_to_str (priv->sys_iface_state),
_sys_iface_state_to_str (sys_iface_state));
- priv->sys_iface_state = sys_iface_state;
+ priv->sys_iface_state_ = sys_iface_state;
}
/* this function only sets a flag, no immediate actions are initiated.
@@ -1507,9 +2579,9 @@ init_ip_config_dns_priority (NMDevice *self, NMIPConfig *config)
const char *property;
int priority;
- property = (nm_ip_config_get_addr_family (config) == AF_INET)
- ? NM_CON_DEFAULT ("ipv4.dns-priority")
- : NM_CON_DEFAULT ("ipv6.dns-priority");
+ property = (nm_ip_config_get_addr_family (config) == AF_INET)
+ ? NM_CON_DEFAULT ("ipv4.dns-priority")
+ : NM_CON_DEFAULT ("ipv6.dns-priority");
priority = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
property,
@@ -1671,92 +2743,6 @@ _add_capabilities (NMDevice *self, NMDeviceCapabilities capabilities)
/*****************************************************************************/
-static const char *
-_get_stable_id (NMDevice *self,
- NMConnection *connection,
- NMUtilsStableType *out_stable_type)
-{
- NMDevicePrivate *priv;
-
- nm_assert (NM_IS_DEVICE (self));
- nm_assert (NM_IS_CONNECTION (connection));
- nm_assert (out_stable_type);
-
- priv = NM_DEVICE_GET_PRIVATE (self);
-
- /* we cache the generated stable ID for the time of an activation.
- *
- * The reason is, that we don't want the stable-id to change as long
- * as the device is active.
- *
- * Especially with ${RANDOM} stable-id we want to generate *one* configuration
- * for each activation. */
- if (G_UNLIKELY (!priv->current_stable_id)) {
- gs_free char *default_id = NULL;
- gs_free char *generated = NULL;
- NMUtilsStableType stable_type;
- NMSettingConnection *s_con;
- gboolean hwaddr_is_fake;
- const char *hwaddr;
- const char *stable_id;
- const char *uuid;
-
- s_con = nm_connection_get_setting_connection (connection);
-
- stable_id = nm_setting_connection_get_stable_id (s_con);
-
- if (!stable_id) {
- default_id = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
- NM_CON_DEFAULT ("connection.stable-id"),
- self);
- stable_id = default_id;
- }
-
- uuid = nm_connection_get_uuid (connection);
-
- /* the cloned-mac-address may be generated based on the stable-id.
- * Thus, at this point, we can only use the permanent MAC address
- * as seed. */
- hwaddr = nm_device_get_permanent_hw_address_full (self, TRUE, &hwaddr_is_fake);
-
- stable_type = nm_utils_stable_id_parse (stable_id,
- nm_device_get_ip_iface (self),
- !hwaddr_is_fake ? hwaddr : NULL,
- nm_utils_boot_id_str (),
- uuid,
- &generated);
-
- /* current_stable_id_type is a bitfield! */
- priv->current_stable_id_type = stable_type;
- nm_assert (stable_type <= (NMUtilsStableType) 0x3);
- nm_assert (stable_type + (NMUtilsStableType) 1 > (NMUtilsStableType) 0);
- nm_assert (priv->current_stable_id_type == stable_type);
-
- if (stable_type == NM_UTILS_STABLE_TYPE_UUID)
- priv->current_stable_id = g_strdup (uuid);
- else if (stable_type == NM_UTILS_STABLE_TYPE_STABLE_ID)
- priv->current_stable_id = g_strdup (stable_id);
- else if (stable_type == NM_UTILS_STABLE_TYPE_GENERATED)
- priv->current_stable_id = nm_str_realloc (nm_utils_stable_id_generated_complete (generated));
- else {
- nm_assert (stable_type == NM_UTILS_STABLE_TYPE_RANDOM);
- priv->current_stable_id = nm_str_realloc (nm_utils_stable_id_random ());
- }
- _LOGT (LOGD_DEVICE,
- "stable-id: type=%d, \"%s\""
- "%s%s%s",
- (int) priv->current_stable_id_type,
- priv->current_stable_id,
- NM_PRINT_FMT_QUOTED (stable_type == NM_UTILS_STABLE_TYPE_GENERATED, " from \"", generated, "\"", ""));
- }
-
- nm_assert (priv->current_stable_id);
- *out_stable_type = priv->current_stable_id_type;
- return priv->current_stable_id;
-}
-
-/*****************************************************************************/
-
static
NM_UTILS_LOOKUP_STR_DEFINE (_ip_state_to_string, NMDeviceIPState,
NM_UTILS_LOOKUP_DEFAULT_WARN ("unknown"),
@@ -1905,7 +2891,7 @@ _dev_l3_register_l3cds_set_one (NMDevice *self,
l3cd_type,
default_route_metric_penalty_get (self, AF_INET),
default_route_metric_penalty_get (self, AF_INET6),
- get_ipv4_dad_timeout (self),
+ _prop_get_ipv4_dad_timeout (self),
_dev_l3_get_merge_flags (self, l3cd_type)))
changed = TRUE;
@@ -1939,7 +2925,7 @@ _dev_l3_register_l3cds (NMDevice *self,
if (!is_external) {
default_route_penalty_4 = default_route_metric_penalty_get (self, AF_INET);
default_route_penalty_6 = default_route_metric_penalty_get (self, AF_INET6);
- acd_timeout_msec = get_ipv4_dad_timeout (self);
+ acd_timeout_msec = _prop_get_ipv4_dad_timeout (self);
}
changed = FALSE;
@@ -2935,141 +3921,6 @@ out:
return nm_utils_ip_route_metric_normalize (addr_family, route_metric);
}
-static NMSettingConnectionMdns
-_get_mdns (NMDevice *self)
-{
- NMConnection *connection;
- NMSettingConnectionMdns mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT;
-
- g_return_val_if_fail (NM_IS_DEVICE (self), NM_SETTING_CONNECTION_MDNS_DEFAULT);
-
- connection = nm_device_get_applied_connection (self);
- if (connection)
- mdns = nm_setting_connection_get_mdns (nm_connection_get_setting_connection (connection));
- if (mdns != NM_SETTING_CONNECTION_MDNS_DEFAULT)
- return mdns;
-
- return nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
- NM_CON_DEFAULT ("connection.mdns"),
- self,
- NM_SETTING_CONNECTION_MDNS_NO,
- NM_SETTING_CONNECTION_MDNS_YES,
- NM_SETTING_CONNECTION_MDNS_DEFAULT);
-}
-
-static NMSettingConnectionLlmnr
-_get_llmnr (NMDevice *self)
-{
- NMConnection *connection;
- NMSettingConnectionLlmnr llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT;
-
- g_return_val_if_fail (NM_IS_DEVICE (self), NM_SETTING_CONNECTION_LLMNR_DEFAULT);
-
- connection = nm_device_get_applied_connection (self);
- if (connection)
- llmnr = nm_setting_connection_get_llmnr (nm_connection_get_setting_connection (connection));
- if (llmnr != NM_SETTING_CONNECTION_LLMNR_DEFAULT)
- return llmnr;
-
- return nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
- NM_CON_DEFAULT ("connection.llmnr"),
- self,
- NM_SETTING_CONNECTION_LLMNR_NO,
- NM_SETTING_CONNECTION_LLMNR_YES,
- NM_SETTING_CONNECTION_LLMNR_DEFAULT);
-}
-
-static guint32
-_get_route_table (NMDevice *self,
- int addr_family)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
- NMDeviceClass *klass;
- NMConnection *connection;
- NMSettingIPConfig *s_ip;
- guint32 route_table = 0;
- gboolean is_user_config = TRUE;
- NMSettingConnection *s_con;
- NMSettingVrf *s_vrf;
-
- nm_assert_addr_family (addr_family);
-
- /* the route table setting affects how we sync routes. We shall
- * not change it while the device is active, hence, cache it. */
- if (addr_family == AF_INET) {
- if (priv->v4_route_table_initialized)
- return priv->v4_route_table;
- } else {
- if (priv->v6_route_table_initialized)
- return priv->v6_route_table;
- }
-
- connection = nm_device_get_applied_connection (self);
- if (connection) {
- s_ip = nm_connection_get_setting_ip_config (connection, addr_family);
- if (s_ip)
- route_table = nm_setting_ip_config_get_route_table (s_ip);
- }
- if (route_table == 0u) {
- gint64 v;
-
- v = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
- addr_family == AF_INET
- ? NM_CON_DEFAULT ("ipv4.route-table")
- : NM_CON_DEFAULT ("ipv6.route-table"),
- self,
- 0,
- G_MAXUINT32,
- -1);
- if (v != -1) {
- route_table = v;
- is_user_config = FALSE;
- }
- }
-
- if ( route_table == 0u
- && connection
- && (s_con = nm_connection_get_setting_connection (connection))
- && (nm_streq0 (nm_setting_connection_get_slave_type (s_con), NM_SETTING_VRF_SETTING_NAME)
- && priv->master
- && nm_device_get_device_type (priv->master) == NM_DEVICE_TYPE_VRF)) {
- const NMPlatformLnkVrf *lnk;
-
- lnk = nm_platform_link_get_lnk_vrf (nm_device_get_platform (self),
- nm_device_get_ifindex (priv->master),
- NULL);
-
- if (lnk)
- route_table = lnk->table;
- }
-
- if ( route_table == 0u
- && connection
- && (s_vrf = (NMSettingVrf *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VRF))) {
- route_table = nm_setting_vrf_get_table (s_vrf);
- }
-
- klass = NM_DEVICE_GET_CLASS (self);
- if (klass->coerce_route_table)
- route_table = klass->coerce_route_table (self, addr_family, route_table, is_user_config);
-
- if (addr_family == AF_INET) {
- priv->v4_route_table_initialized = TRUE;
- priv->v4_route_table = route_table;
- } else {
- priv->v6_route_table_initialized = TRUE;
- priv->v6_route_table = route_table;
- }
-
- _LOGT (LOGD_DEVICE,
- "ipv%c.route-table = %u%s",
- addr_family == AF_INET ? '4' : '6',
- (guint) (route_table ?: RT_TABLE_MAIN),
- route_table != 0u ? "" : " (policy routing not enabled)");
-
- return route_table;
-}
-
guint32
nm_device_get_route_table (NMDevice *self,
int addr_family)
@@ -3078,7 +3929,7 @@ nm_device_get_route_table (NMDevice *self,
g_return_val_if_fail (NM_IS_DEVICE (self), RT_TABLE_MAIN);
- route_table = _get_route_table (self, addr_family);
+ route_table = _prop_get_ipvx_route_table (self, addr_family);
return route_table ?: (guint32) RT_TABLE_MAIN;
}
@@ -3091,7 +3942,7 @@ _get_route_table_sync_mode_stateful (NMDevice *self,
gboolean all_sync_now;
gboolean all_sync_eff;
- all_sync_now = _get_route_table (self, addr_family) != 0u;
+ all_sync_now = _prop_get_ipvx_route_table (self, addr_family) != 0u;
if (!all_sync_now) {
/* If there's a local route switch to all-sync in order
@@ -7251,33 +8102,6 @@ lldp_neighbors_changed (NMLldpListener *lldp_listener, GParamSpec *pspec,
_notify (self, PROP_LLDP_NEIGHBORS);
}
-static gboolean
-lldp_rx_enabled (NMDevice *self)
-{
- NMConnection *connection;
- NMSettingConnection *s_con;
- NMSettingConnectionLldp lldp = NM_SETTING_CONNECTION_LLDP_DEFAULT;
-
- connection = nm_device_get_applied_connection (self);
- g_return_val_if_fail (connection, FALSE);
-
- s_con = nm_connection_get_setting_connection (connection);
- g_return_val_if_fail (s_con, FALSE);
-
- lldp = nm_setting_connection_get_lldp (s_con);
- if (lldp == NM_SETTING_CONNECTION_LLDP_DEFAULT) {
- lldp = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
- NM_CON_DEFAULT ("connection.lldp"),
- self,
- NM_SETTING_CONNECTION_LLDP_DEFAULT,
- NM_SETTING_CONNECTION_LLDP_ENABLE_RX,
- NM_SETTING_CONNECTION_LLDP_DEFAULT);
- if (lldp == NM_SETTING_CONNECTION_LLDP_DEFAULT)
- lldp = NM_SETTING_CONNECTION_LLDP_DISABLE;
- }
- return lldp == NM_SETTING_CONNECTION_LLDP_ENABLE_RX;
-}
-
static NMPlatformVF *
sriov_vf_config_to_platform (NMDevice *self,
NMSriovVF *vf,
@@ -7568,7 +8392,7 @@ lldp_init (NMDevice *self, gboolean restart)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
- if (priv->ifindex > 0 && lldp_rx_enabled (self)) {
+ if (priv->ifindex > 0 && _prop_get_connection_lldp (self)) {
gs_free_error GError *error = NULL;
if (priv->lldp_listener) {
@@ -7842,30 +8666,6 @@ nm_device_ip_method_failed (NMDevice *self,
}
/*****************************************************************************/
-/* IPv4 DAD stuff */
-
-static guint
-get_ipv4_dad_timeout (NMDevice *self)
-{
- NMConnection *connection;
- NMSettingIPConfig *s_ip4 = NULL;
- int timeout = -1;
-
- connection = nm_device_get_applied_connection (self);
- if (connection)
- s_ip4 = nm_connection_get_setting_ip4_config (connection);
- if (s_ip4)
- timeout = nm_setting_ip_config_get_dad_timeout (s_ip4);
- if (timeout >= 0)
- return timeout;
-
- return nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
- NM_CON_DEFAULT ("ipv4.dad-timeout"),
- self,
- 0,
- NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX,
- 0);
-}
static void
acd_data_destroy (gpointer ptr)
@@ -7982,7 +8782,7 @@ ipv4_dad_start (NMDevice *self, NMIP4Config **configs, AcdCallback cb)
}
}
- timeout = get_ipv4_dad_timeout (self);
+ timeout = _prop_get_ipv4_dad_timeout (self);
hwaddr_arr = nm_platform_link_get_address (nm_device_get_platform (self),
nm_device_get_ip_ifindex (self),
&length);
@@ -8233,8 +9033,8 @@ ensure_con_ip_config (NMDevice *self, int addr_family)
if (IS_IPv4) {
nm_ip4_config_merge_setting (NM_IP4_CONFIG (con_ip_config),
nm_connection_get_setting_ip4_config (connection),
- _get_mdns (self),
- _get_llmnr (self),
+ _prop_get_connection_mdns (self),
+ _prop_get_connection_llmnr (self),
nm_device_get_route_table (self, addr_family),
nm_device_get_route_metric (self, addr_family));
} else {
@@ -8254,52 +9054,6 @@ ensure_con_ip_config (NMDevice *self, int addr_family)
}
/*****************************************************************************/
-/* DHCPv4 stuff */
-
-static guint32
-get_dhcp_timeout (NMDevice *self, int addr_family)
-{
- NMDeviceClass *klass;
- NMConnection *connection;
- int timeout_i;
- guint32 timeout;
-
- nm_assert (NM_IS_DEVICE (self));
- nm_assert_addr_family (addr_family);
-
- connection = nm_device_get_applied_connection (self);
-
- timeout_i = nm_setting_ip_config_get_dhcp_timeout (nm_connection_get_setting_ip_config (connection, addr_family));
- nm_assert (timeout_i >= 0 && timeout_i <= G_MAXINT32);
-
- timeout = (guint32) timeout_i;
- if (timeout)
- goto out;
-
- timeout = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
- addr_family == AF_INET
- ? NM_CON_DEFAULT ("ipv4.dhcp-timeout")
- : NM_CON_DEFAULT ("ipv6.dhcp-timeout"),
- self,
- 0, G_MAXINT32, 0);
- if (timeout)
- goto out;
-
- klass = NM_DEVICE_GET_CLASS (self);
- if (klass->get_dhcp_timeout_for_device) {
- timeout = klass->get_dhcp_timeout_for_device (self, addr_family);
- if (timeout)
- goto out;
- }
-
- timeout = NM_DHCP_TIMEOUT_DEFAULT;
-
-out:
- G_STATIC_ASSERT_EXPR (G_MAXINT32 == NM_DHCP_TIMEOUT_INFINITY);
- nm_assert (timeout > 0);
- nm_assert (timeout <= G_MAXINT32);
- return timeout;
-}
static void
dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release)
@@ -8310,7 +9064,6 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release)
nm_clear_g_source (&priv->dhcp_data_4.grace_id);
priv->dhcp_data_4.grace_pending = FALSE;
nm_clear_g_free (&priv->dhcp4.pac_url);
- nm_clear_g_free (&priv->dhcp4.root_path);
if (priv->dhcp_data_4.client) {
/* Stop any ongoing DHCP transaction on this device */
@@ -8628,7 +9381,7 @@ dhcp_grace_period_start (NMDevice *self, int addr_family)
/* Start a grace period equal to the DHCP timeout multiplied
* by a constant factor. */
- timeout = get_dhcp_timeout (self, addr_family);
+ timeout = _prop_get_ipvx_dhcp_timeout (self, addr_family);
if (timeout == NM_DHCP_TIMEOUT_INFINITY)
_LOGI (LOGD_DHCP_from_addr_family (addr_family),
"DHCPv%c: trying to acquire a new lease",
@@ -8720,7 +9473,6 @@ dhcp4_state_changed (NMDhcpClient *client,
NMDhcpState state,
NMIP4Config *ip4_config,
GHashTable *options,
- const char *event_id,
gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
@@ -8755,9 +9507,6 @@ dhcp4_state_changed (NMDhcpClient *client,
priv->dhcp4.pac_url = g_strdup (g_hash_table_lookup (options, "wpad"));
nm_device_set_proxy_config (self, priv->dhcp4.pac_url);
- g_free (priv->dhcp4.root_path);
- priv->dhcp4.root_path = g_strdup (g_hash_table_lookup (options, "root_path"));
-
nm_dhcp_config_set_options (priv->dhcp_data_4.config, options);
_notify (self, PROP_DHCP4_CONFIG);
@@ -8804,390 +9553,6 @@ dhcp4_state_changed (NMDhcpClient *client,
}
}
-/**
- * dhcp_get_iaid:
- * @self: the #NMDevice
- * @addr_family: the address family
- * @connection: the connection
- * @out_is_explicit: on return, %TRUE if the user set a valid IAID in
- * the connection or in global configuration; %FALSE if the connection
- * property was empty and no valid global configuration was provided.
- *
- * Returns: a IAID value for this device and the given connection.
- */
-static guint32
-dhcp_get_iaid (NMDevice *self,
- int addr_family,
- NMConnection *connection,
- gboolean *out_is_explicit)
-{
- NMSettingIPConfig *s_ip;
- const char *iaid_str;
- gs_free char *iaid_str_free = NULL;
- guint32 iaid;
- const char *iface;
- const char *fail_reason;
- gboolean is_explicit = TRUE;
-
- s_ip = nm_connection_get_setting_ip_config (connection, addr_family);
- iaid_str = nm_setting_ip_config_get_dhcp_iaid (s_ip);
- if (!iaid_str) {
- iaid_str_free = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
- addr_family == AF_INET
- ? NM_CON_DEFAULT ("ipv4.dhcp-iaid")
- : NM_CON_DEFAULT ("ipv6.dhcp-iaid"),
- self);
- iaid_str = iaid_str_free;
- if (!iaid_str) {
- iaid_str = NM_IAID_IFNAME;
- is_explicit = FALSE;
- } else if (!_nm_utils_iaid_verify (iaid_str, NULL)) {
- _LOGW (LOGD_DEVICE, "invalid global default '%s' for ipv%c.dhcp-iaid",
- iaid_str,
- nm_utils_addr_family_to_char (addr_family));
- iaid_str = NM_IAID_IFNAME;
- is_explicit = FALSE;
- }
- }
-
- if (nm_streq0 (iaid_str, NM_IAID_MAC)) {
- const NMPlatformLink *pllink;
-
- pllink = nm_platform_link_get (nm_device_get_platform (self),
- nm_device_get_ip_ifindex (self));
- if (!pllink || pllink->l_address.len < 4) {
- fail_reason = "invalid link-layer address";
- goto out_fail;
- }
-
- /* @iaid is in native endianness. Use unaligned_read_be32()
- * so that the IAID for a given MAC address is the same on
- * BE and LE machines. */
- iaid = unaligned_read_be32 (&pllink->l_address.data[pllink->l_address.len - 4]);
- goto out_good;
- } else if (nm_streq0 (iaid_str, NM_IAID_PERM_MAC)) {
- guint8 hwaddr_buf[NM_UTILS_HWADDR_LEN_MAX];
- const char *hwaddr_str;
- gsize hwaddr_len;
-
- hwaddr_str = nm_device_get_permanent_hw_address (self);
- if (!hwaddr_str) {
- fail_reason = "no permanent link-layer address";
- goto out_fail;
- }
-
- if (!_nm_utils_hwaddr_aton (hwaddr_str, hwaddr_buf, sizeof (hwaddr_buf), &hwaddr_len))
- g_return_val_if_reached (0);
-
- if (hwaddr_len < 4) {
- fail_reason = "invalid link-layer address";
- goto out_fail;
- }
-
- iaid = unaligned_read_be32 (&hwaddr_buf[hwaddr_len - 4]);
- goto out_good;
- } else if (nm_streq (iaid_str, "stable")) {
- nm_auto_free_checksum GChecksum *sum = NULL;
- guint8 digest[NM_UTILS_CHECKSUM_LENGTH_SHA1];
- NMUtilsStableType stable_type;
- const char *stable_id;
- guint32 salted_header;
- const guint8 *host_id;
- gsize host_id_len;
-
- stable_id = _get_stable_id (self, connection, &stable_type);
- salted_header = htonl (53390459 + stable_type);
- nm_utils_host_id_get (&host_id, &host_id_len);
- iface = nm_device_get_ip_iface (self);
-
- sum = g_checksum_new (G_CHECKSUM_SHA1);
- g_checksum_update (sum, (const guchar *) &salted_header, sizeof (salted_header));
- g_checksum_update (sum, (const guchar *) stable_id, strlen (stable_id) + 1);
- g_checksum_update (sum, (const guchar *) iface, strlen (iface) + 1);
- g_checksum_update (sum, (const guchar *) host_id, host_id_len);
- nm_utils_checksum_get_digest (sum, digest);
-
- iaid = unaligned_read_be32 (digest);
- goto out_good;
- } else if ((iaid = _nm_utils_ascii_str_to_int64 (iaid_str, 10, 0, G_MAXUINT32, -1)) != -1) {
- goto out_good;
- } else {
- iface = nm_device_get_ip_iface (self);
- iaid = nm_utils_create_dhcp_iaid (TRUE,
- (const guint8 *) iface,
- strlen (iface));
- goto out_good;
- }
-
-out_fail:
- nm_assert (fail_reason);
- _LOGW ( addr_family == AF_INET
- ? (LOGD_DEVICE | LOGD_DHCP4 | LOGD_IP4)
- : (LOGD_DEVICE | LOGD_DHCP6 | LOGD_IP6),
- "ipv%c.dhcp-iaid: failure to generate IAID: %s. Using interface-name based IAID",
- nm_utils_addr_family_to_char (addr_family), fail_reason);
- is_explicit = FALSE;
- iface = nm_device_get_ip_iface (self);
- iaid = nm_utils_create_dhcp_iaid (TRUE,
- (const guint8 *) iface,
- strlen (iface));
-out_good:
- _LOGD ( addr_family == AF_INET
- ? (LOGD_DEVICE | LOGD_DHCP4 | LOGD_IP4)
- : (LOGD_DEVICE | LOGD_DHCP6 | LOGD_IP6),
- "ipv%c.dhcp-iaid: using %u (0x%08x) IAID (str: '%s', explicit %d)",
- nm_utils_addr_family_to_char (addr_family), iaid, iaid,
- iaid_str, is_explicit);
- NM_SET_OUT (out_is_explicit, is_explicit);
- return iaid;
-}
-
-static NMDhcpHostnameFlags
-get_dhcp_hostname_flags (NMDevice *self, int addr_family)
-{
- NMConnection *connection;
- NMSettingIPConfig *s_ip;
- NMDhcpHostnameFlags flags;
- gs_free_error GError *error = NULL;
-
- g_return_val_if_fail (NM_IS_DEVICE (self), NM_DHCP_HOSTNAME_FLAG_NONE);
-
- connection = nm_device_get_applied_connection (self);
- s_ip = nm_connection_get_setting_ip_config (connection, addr_family);
- g_return_val_if_fail (s_ip, NM_DHCP_HOSTNAME_FLAG_NONE);
-
- if (!nm_setting_ip_config_get_dhcp_send_hostname (s_ip))
- return NM_DHCP_HOSTNAME_FLAG_NONE;
-
- flags = nm_setting_ip_config_get_dhcp_hostname_flags (s_ip);
- if (flags != NM_DHCP_HOSTNAME_FLAG_NONE)
- return flags;
-
- flags = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
- addr_family == AF_INET
- ? NM_CON_DEFAULT ("ipv4.dhcp-hostname-flags")
- : NM_CON_DEFAULT ("ipv6.dhcp-hostname-flags"),
- self,
- 0, NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS,
- 0);
-
- if (!_nm_utils_validate_dhcp_hostname_flags (flags, addr_family, &error)) {
- _LOGW (LOGD_DEVICE, "invalid global default value 0x%x for ipv%d.%s: %s",
- (guint) flags,
- addr_family == AF_INET ? 4 : 6,
- NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS,
- error->message);
- flags = NM_DHCP_HOSTNAME_FLAG_NONE;
- }
-
- if (flags != NM_DHCP_HOSTNAME_FLAG_NONE)
- return flags;
-
- if (addr_family == AF_INET)
- return NM_DHCP_HOSTNAME_FLAGS_FQDN_DEFAULT_IP4;
- else
- return NM_DHCP_HOSTNAME_FLAGS_FQDN_DEFAULT_IP6;
-}
-
-static const char *
-connection_get_mud_url (NMDevice *self,
- NMSettingConnection *s_con,
- char **out_mud_url)
-{
- const char *mud_url;
- gs_free char *s = NULL;
-
- nm_assert (out_mud_url && !*out_mud_url);
-
- mud_url = nm_setting_connection_get_mud_url (s_con);
-
- if (mud_url) {
- if (nm_streq (mud_url, NM_CONNECTION_MUD_URL_NONE))
- return NULL;
- return mud_url;
- }
-
- s = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
- NM_CON_DEFAULT ("connection.mud-url"),
- self);
- if (s) {
- if (nm_streq (s, NM_CONNECTION_MUD_URL_NONE))
- return NULL;
- if (nm_sd_http_url_is_valid_https (s))
- return (*out_mud_url = g_steal_pointer (&s));
- }
-
- return NULL;
-}
-
-static GBytes *
-dhcp4_get_client_id (NMDevice *self,
- NMConnection *connection,
- GBytes *hwaddr)
-{
- NMSettingIPConfig *s_ip4;
- const char *client_id;
- gs_free char *client_id_default = NULL;
- guint8 *client_id_buf;
- const char *fail_reason;
- guint8 hwaddr_bin_buf[NM_UTILS_HWADDR_LEN_MAX];
- const guint8 *hwaddr_bin;
- int arp_type;
- gsize hwaddr_len;
- GBytes *result;
- gs_free char *logstr1 = NULL;
-
- s_ip4 = nm_connection_get_setting_ip4_config (connection);
- client_id = nm_setting_ip4_config_get_dhcp_client_id (NM_SETTING_IP4_CONFIG (s_ip4));
-
- if (!client_id) {
- client_id_default = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
- NM_CON_DEFAULT ("ipv4.dhcp-client-id"),
- self);
- if (client_id_default && client_id_default[0]) {
- /* a non-empty client-id is always valid, see nm_dhcp_utils_client_id_string_to_bytes(). */
- client_id = client_id_default;
- }
- }
-
- if (!client_id) {
- _LOGD (LOGD_DEVICE | LOGD_DHCP4 | LOGD_IP4,
- "ipv4.dhcp-client-id: no explicit client-id configured");
- return NULL;
- }
-
- if (nm_streq (client_id, "mac")) {
- if (!hwaddr) {
- fail_reason = "missing link-layer address";
- goto out_fail;
- }
-
- hwaddr_bin = g_bytes_get_data (hwaddr, &hwaddr_len);
- arp_type = nm_utils_arp_type_detect_from_hwaddrlen (hwaddr_len);
- if (arp_type < 0) {
- fail_reason = "unsupported link-layer address";
- goto out_fail;
- }
-
- result = nm_utils_dhcp_client_id_mac (arp_type, hwaddr_bin, hwaddr_len);
- goto out_good;
- }
-
- if (nm_streq (client_id, "perm-mac")) {
- const char *hwaddr_str;
-
- hwaddr_str = nm_device_get_permanent_hw_address (self);
- if (!hwaddr_str) {
- fail_reason = "missing permanent link-layer address";
- goto out_fail;
- }
-
- if (!_nm_utils_hwaddr_aton (hwaddr_str, hwaddr_bin_buf, sizeof (hwaddr_bin_buf), &hwaddr_len))
- g_return_val_if_reached (NULL);
-
- arp_type = nm_utils_arp_type_detect_from_hwaddrlen (hwaddr_len);
- if (arp_type < 0) {
- fail_reason = "unsupported permanent link-layer address";
- goto out_fail;
- }
-
- result = nm_utils_dhcp_client_id_mac (arp_type, hwaddr_bin_buf, hwaddr_len);
- goto out_good;
- }
-
- if (nm_streq (client_id, "duid")) {
- guint32 iaid = dhcp_get_iaid (self, AF_INET, connection, NULL);
-
- result = nm_utils_dhcp_client_id_systemd_node_specific (iaid);
- goto out_good;
- }
-
- if (nm_streq (client_id, "stable")) {
- nm_auto_free_checksum GChecksum *sum = NULL;
- guint8 digest[NM_UTILS_CHECKSUM_LENGTH_SHA1];
- NMUtilsStableType stable_type;
- const char *stable_id;
- guint32 salted_header;
- const guint8 *host_id;
- gsize host_id_len;
-
- stable_id = _get_stable_id (self, connection, &stable_type);
- salted_header = htonl (2011610591 + stable_type);
- nm_utils_host_id_get (&host_id, &host_id_len);
-
- sum = g_checksum_new (G_CHECKSUM_SHA1);
- g_checksum_update (sum, (const guchar *) &salted_header, sizeof (salted_header));
- g_checksum_update (sum, (const guchar *) stable_id, strlen (stable_id) + 1);
- g_checksum_update (sum, (const guchar *) host_id, host_id_len);
- nm_utils_checksum_get_digest (sum, digest);
-
- client_id_buf = g_malloc (1 + 15);
- client_id_buf[0] = 0;
- memcpy (&client_id_buf[1], digest, 15);
- result = g_bytes_new_take (client_id_buf, 1 + 15);
- goto out_good;
- }
-
- result = nm_dhcp_utils_client_id_string_to_bytes (client_id);
- goto out_good;
-
-out_fail:
- nm_assert (fail_reason);
- _LOGW (LOGD_DEVICE | LOGD_DHCP4 | LOGD_IP4,
- "ipv4.dhcp-client-id: failure to generate client id (%s). Use random client id",
- fail_reason);
- client_id_buf = g_malloc (1 + 15);
- client_id_buf[0] = 0;
- nm_utils_random_bytes (&client_id_buf[1], 15);
- result = g_bytes_new_take (client_id_buf, 1 + 15);
-
-out_good:
- nm_assert (result);
- _LOGD (LOGD_DEVICE | LOGD_DHCP4 | LOGD_IP4,
- "ipv4.dhcp-client-id: use \"%s\" client ID: %s",
- client_id,
- (logstr1 = nm_dhcp_utils_duid_to_string (result)));
- return result;
-}
-
-static GBytes *
-dhcp4_get_vendor_class_identifier (NMDevice *self, NMSettingIP4Config *s_ip4)
-{
- gs_free char *config_data_prop = NULL;
- gs_free char *to_free = NULL;
- const char *conn_prop;
- GBytes *bytes = NULL;
- const char *bin;
- gsize len;
-
- conn_prop = nm_setting_ip4_config_get_dhcp_vendor_class_identifier (s_ip4);
-
- if (!conn_prop) {
- /* set in NetworkManager.conf ? */
- config_data_prop = nm_config_data_get_connection_default (
- NM_CONFIG_GET_DATA,
- NM_CON_DEFAULT ("ipv4.dhcp-vendor-class-identifier"),
- self);
-
- if ( config_data_prop
- && nm_utils_validate_dhcp4_vendor_class_id (config_data_prop, NULL))
- conn_prop = config_data_prop;
- }
-
- if (conn_prop) {
- bin = nm_utils_buf_utf8safe_unescape (conn_prop,
- NM_UTILS_STR_UTF8_SAFE_FLAG_NONE,
- &len,
- (gpointer *) &to_free);
- if (to_free)
- bytes = g_bytes_new_take (g_steal_pointer (&to_free), len);
- else
- bytes = g_bytes_new (bin, len);
- }
-
- return bytes;
-}
-
static NMActStageReturn
dhcp4_start (NMDevice *self)
{
@@ -9222,9 +9587,8 @@ dhcp4_start (NMDevice *self)
bcast_hwaddr = nmp_link_address_get_as_bytes (&pllink->l_broadcast);
}
- client_id = dhcp4_get_client_id (self, connection, hwaddr);
- vendor_class_identifier
- = dhcp4_get_vendor_class_identifier (self, NM_SETTING_IP4_CONFIG (s_ip4));
+ client_id = _prop_get_ipv4_dhcp_client_id (self, connection, hwaddr);
+ vendor_class_identifier = _prop_get_ipv4_dhcp_vendor_class_identifier (self, NM_SETTING_IP4_CONFIG (s_ip4));
reject_servers = nm_setting_ip_config_get_dhcp_reject_servers (s_ip4, NULL);
g_warn_if_fail (priv->dhcp_data_4.client == NULL);
@@ -9240,10 +9604,10 @@ dhcp4_start (NMDevice *self)
nm_setting_ip_config_get_dhcp_send_hostname (s_ip4),
nm_setting_ip_config_get_dhcp_hostname (s_ip4),
nm_setting_ip4_config_get_dhcp_fqdn (NM_SETTING_IP4_CONFIG (s_ip4)),
- get_dhcp_hostname_flags (self, AF_INET),
- connection_get_mud_url (self, s_con, &mud_url_free),
+ _prop_get_ipvx_dhcp_hostname_flags (self, AF_INET),
+ _prop_get_connection_mud_url (self, s_con, &mud_url_free),
client_id,
- get_dhcp_timeout (self, AF_INET),
+ _prop_get_ipvx_dhcp_timeout (self, AF_INET),
priv->dhcp_anycast_address,
NULL,
vendor_class_identifier,
@@ -9564,11 +9928,11 @@ dhcp6_state_changed (NMDhcpClient *client,
NMDhcpState state,
NMIP6Config *ip6_config,
GHashTable *options,
- const char *event_id,
gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ gs_free char *event_id = NULL;
g_return_if_fail (nm_dhcp_client_get_addr_family (client) == AF_INET6);
g_return_if_fail (!ip6_config || NM_IS_IP6_CONFIG (ip6_config));
@@ -9584,6 +9948,9 @@ dhcp6_state_changed (NMDhcpClient *client,
* changed event for each of them. Use the event ID to merge IPv6
* addresses from the same transaction into a single configuration.
*/
+
+ event_id = nm_dhcp_utils_get_dhcp6_event_id (options);
+
if ( ip6_config
&& event_id
&& priv->dhcp6.event_id
@@ -9667,320 +10034,6 @@ dhcp6_prefix_delegated (NMDhcpClient *client,
/*****************************************************************************/
-/* RFC 3315 defines the epoch for the DUID-LLT time field on Jan 1st 2000. */
-#define EPOCH_DATETIME_200001010000 946684800
-
-static GBytes *
-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 - 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, 2 + 2 + 4 + 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, 2 + 2 + 4 + hwaddr_len);
-}
-
-static GBytes *
-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, 2 + 2 + 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, 2 + 2 + hwaddr_len);
-}
-
-static GBytes *
-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);
-}
-
-static GBytes *
-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 */
- 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 = 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);
-}
-
-static GBytes *
-dhcp6_get_duid (NMDevice *self, NMConnection *connection, GBytes *hwaddr, gboolean *out_enforce)
-{
- NMSettingIPConfig *s_ip6;
- const char *duid;
- gs_free char *duid_default = NULL;
- const char *duid_error;
- GBytes *duid_out;
- gboolean duid_enforce = TRUE;
- gs_free char *logstr1 = NULL;
- const guint8 *hwaddr_bin;
- gsize hwaddr_len;
- int arp_type;
-
- s_ip6 = nm_connection_get_setting_ip6_config (connection);
- duid = nm_setting_ip6_config_get_dhcp_duid (NM_SETTING_IP6_CONFIG (s_ip6));
-
- if (!duid) {
- duid_default = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
- NM_CON_DEFAULT ("ipv6.dhcp-duid"),
- self);
- duid = duid_default;
- if (!duid)
- duid = "lease";
- }
-
- if (nm_streq (duid, "lease")) {
- duid_enforce = FALSE;
- duid_out = generate_duid_from_machine_id ();
- goto out_good;
- }
-
- if (!_nm_utils_dhcp_duid_valid (duid, &duid_out)) {
- duid_error = "invalid duid";
- goto out_fail;
- }
-
- if (duid_out)
- goto out_good;
-
- if (NM_IN_STRSET (duid, "ll", "llt")) {
- if (!hwaddr) {
- duid_error = "missing link-layer address";
- goto out_fail;
- }
-
- hwaddr_bin = g_bytes_get_data (hwaddr, &hwaddr_len);
- arp_type = nm_utils_arp_type_detect_from_hwaddrlen (hwaddr_len);
- if (arp_type < 0) {
- duid_error = "unsupported link-layer address";
- goto out_fail;
- }
-
- if (nm_streq (duid, "ll"))
- duid_out = generate_duid_ll (arp_type, hwaddr_bin, hwaddr_len);
- else {
- duid_out = generate_duid_llt (arp_type, hwaddr_bin, hwaddr_len,
- nm_utils_host_id_get_timestamp_ns () / NM_UTILS_NSEC_PER_SEC);
- }
-
- goto out_good;
- }
-
- if (NM_IN_STRSET (duid, "stable-ll", "stable-llt", "stable-uuid")) {
- /* preferably, we would salt the checksum differently for each @duid type. We missed
- * to do that initially, so most types use the DEFAULT_SALT.
- *
- * Implementations that are added later, should use a distinct salt instead,
- * like "stable-ll"/"stable-llt" with ARPHRD_INFINIBAND below. */
- const guint32 DEFAULT_SALT = 670531087u;
- nm_auto_free_checksum GChecksum *sum = NULL;
- NMUtilsStableType stable_type;
- const char *stable_id = NULL;
- guint32 salted_header;
- const guint8 *host_id;
- gsize host_id_len;
- union {
- guint8 sha256[NM_UTILS_CHECKSUM_LENGTH_SHA256];
- guint8 hwaddr_eth[ETH_ALEN];
- guint8 hwaddr_infiniband[INFINIBAND_ALEN];
- NMUuid uuid;
- struct _nm_packed {
- guint8 hwaddr[ETH_ALEN];
- guint32 timestamp;
- } llt_eth;
- struct _nm_packed {
- guint8 hwaddr[INFINIBAND_ALEN];
- guint32 timestamp;
- } llt_infiniband;
- } digest;
-
- stable_id = _get_stable_id (self, connection, &stable_type);
-
- if (NM_IN_STRSET (duid, "stable-ll", "stable-llt")) {
- /* for stable LL/LLT DUIDs, we still need a hardware address to detect
- * the arp-type. Alternatively, we would be able to detect it based on
- * other means (e.g. NMDevice type), but instead require the hardware
- * address to be present. This is at least consistent with the "ll"/"llt"
- * modes above. */
- if (!hwaddr) {
- duid_error = "missing link-layer address";
- goto out_fail;
- }
- if ((arp_type = nm_utils_arp_type_detect_from_hwaddrlen (g_bytes_get_size (hwaddr))) < 0) {
- duid_error = "unsupported link-layer address";
- goto out_fail;
- }
-
- if (arp_type == ARPHRD_ETHER)
- salted_header = DEFAULT_SALT;
- else {
- nm_assert (arp_type == ARPHRD_INFINIBAND);
- salted_header = 0x42492CEFu + ((guint32) arp_type);
- }
- } else {
- salted_header = DEFAULT_SALT;
- arp_type = -1;
- }
-
- salted_header = htonl (salted_header + ((guint32) stable_type));
-
- nm_utils_host_id_get (&host_id, &host_id_len);
-
- sum = g_checksum_new (G_CHECKSUM_SHA256);
- g_checksum_update (sum, (const guchar *) &salted_header, sizeof (salted_header));
- g_checksum_update (sum, (const guchar *) stable_id, -1);
- g_checksum_update (sum, (const guchar *) host_id, host_id_len);
- nm_utils_checksum_get_digest (sum, digest.sha256);
-
- G_STATIC_ASSERT_EXPR (sizeof (digest) == sizeof (digest.sha256));
-
- if (nm_streq (duid, "stable-ll")) {
- switch (arp_type) {
- case ARPHRD_ETHER:
- duid_out = generate_duid_ll (arp_type, digest.hwaddr_eth, sizeof (digest.hwaddr_eth));
- break;
- case ARPHRD_INFINIBAND:
- duid_out = generate_duid_ll (arp_type, digest.hwaddr_infiniband, sizeof (digest.hwaddr_infiniband));
- break;
- default:
- g_return_val_if_reached (NULL);
- }
- } else if (nm_streq (duid, "stable-llt")) {
- gint64 time;
- guint32 timestamp;
-
-#define EPOCH_DATETIME_THREE_YEARS (356 * 24 * 3600 * 3)
-
- /* We want a variable time between the host_id timestamp and three years
- * before. Let's compute the time (in seconds) from 0 to 3 years; then we'll
- * subtract it from the host_id timestamp.
- */
- time = nm_utils_host_id_get_timestamp_ns () / NM_UTILS_NSEC_PER_SEC;
-
- /* don't use too old timestamps. They cannot be expressed in DUID-LLT and
- * would all be truncated to zero. */
- time = NM_MAX (time, EPOCH_DATETIME_200001010000 + EPOCH_DATETIME_THREE_YEARS);
-
- switch (arp_type) {
- case ARPHRD_ETHER:
- timestamp = unaligned_read_be32 (&digest.llt_eth.timestamp);
- time -= timestamp % EPOCH_DATETIME_THREE_YEARS;
- duid_out = generate_duid_llt (arp_type, digest.llt_eth.hwaddr, sizeof (digest.llt_eth.hwaddr), time);
- break;
- case ARPHRD_INFINIBAND:
- timestamp = unaligned_read_be32 (&digest.llt_infiniband.timestamp);
- time -= timestamp % EPOCH_DATETIME_THREE_YEARS;
- duid_out = generate_duid_llt (arp_type, digest.llt_infiniband.hwaddr, sizeof (digest.llt_infiniband.hwaddr), time);
- break;
- default:
- g_return_val_if_reached (NULL);
- }
- } else {
- nm_assert (nm_streq (duid, "stable-uuid"));
- duid_out = generate_duid_uuid (&digest.uuid);
- }
-
- goto out_good;
- }
-
- g_return_val_if_reached (NULL);
-
-out_fail:
- nm_assert (!duid_out && duid_error);
- {
- NMUuid uuid;
-
- _LOGW (LOGD_IP6 | LOGD_DHCP6,
- "ipv6.dhcp-duid: failure to generate %s DUID: %s. Fallback to random DUID-UUID.",
- duid, duid_error);
-
- nm_utils_random_bytes (&uuid, sizeof (uuid));
- duid_out = generate_duid_uuid (&uuid);
- }
-
-out_good:
- nm_assert (duid_out);
- _LOGD (LOGD_IP6 | LOGD_DHCP6,
- "ipv6.dhcp-duid: generate %s DUID '%s' (%s)",
- duid,
- (logstr1 = nm_dhcp_utils_duid_to_string (duid_out)),
- duid_enforce ? "enforcing" : "prefer lease");
-
- NM_SET_OUT (out_enforce, duid_enforce);
- return duid_out;
-}
-
-/*****************************************************************************/
-
static gboolean
dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection)
{
@@ -10019,8 +10072,8 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection)
if (pllink)
hwaddr = nmp_link_address_get_as_bytes (&pllink->l_address);
- iaid = dhcp_get_iaid (self, AF_INET6, connection, &iaid_explicit);
- duid = dhcp6_get_duid (self, connection, hwaddr, &enforce_duid);
+ iaid = _prop_get_ipvx_dhcp_iaid (self, AF_INET6, connection, &iaid_explicit);
+ duid = _prop_get_ipv6_dhcp_duid (self, connection, hwaddr, &enforce_duid);
priv->dhcp_data_6.client = nm_dhcp_manager_start_ip6 (nm_dhcp_manager_get (),
nm_device_get_multi_index (self),
@@ -10032,13 +10085,13 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection)
nm_device_get_route_metric (self, AF_INET6),
nm_setting_ip_config_get_dhcp_send_hostname (s_ip6),
nm_setting_ip_config_get_dhcp_hostname (s_ip6),
- get_dhcp_hostname_flags (self, AF_INET6),
- connection_get_mud_url (self, s_con, &mud_url_free),
+ _prop_get_ipvx_dhcp_hostname_flags (self, AF_INET6),
+ _prop_get_connection_mud_url (self, s_con, &mud_url_free),
duid,
enforce_duid,
iaid,
iaid_explicit,
- get_dhcp_timeout (self, AF_INET6),
+ _prop_get_ipvx_dhcp_timeout (self, AF_INET6),
priv->dhcp_anycast_address,
(priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF) ? TRUE : FALSE,
nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6)),
@@ -10307,7 +10360,7 @@ check_and_add_ipv6ll_addr (NMDevice *self)
NMUtilsStableType stable_type;
const char *stable_id;
- stable_id = _get_stable_id (self, connection, &stable_type);
+ stable_id = _prop_get_connection_stable_id (self, connection, &stable_type);
if (!nm_utils_ipv6_addr_set_stable_privacy (stable_type,
&lladdr,
nm_device_get_iface (self),
@@ -10963,28 +11016,6 @@ ndisc_node_type (NMDevice *self)
return NM_NDISC_NODE_TYPE_HOST;
}
-static gint32
-get_ra_timeout (NMDevice *self)
-{
- NMConnection *connection;
- gint32 timeout;
-
- G_STATIC_ASSERT_EXPR (NM_RA_TIMEOUT_DEFAULT == 0);
- G_STATIC_ASSERT_EXPR (NM_RA_TIMEOUT_INFINITY == G_MAXINT32);
-
- connection = nm_device_get_applied_connection (self);
-
- timeout = nm_setting_ip6_config_get_ra_timeout (NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection)));
- nm_assert (timeout >= 0);
- if (timeout)
- return timeout;
-
- return nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
- NM_CON_DEFAULT ("ipv6.ra-timeout"),
- self,
- 0, G_MAXINT32, 0);
-}
-
static gboolean
addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
{
@@ -11007,7 +11038,7 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection));
g_assert (s_ip6);
- stable_id = _get_stable_id (self, connection, &stable_type);
+ stable_id = _prop_get_connection_stable_id (self, connection, &stable_type);
priv->ndisc = nm_lndp_ndisc_new (nm_device_get_platform (self),
nm_device_get_ip_ifindex (self),
nm_device_get_ip_iface (self),
@@ -11015,7 +11046,7 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
stable_id,
nm_setting_ip6_config_get_addr_gen_mode (s_ip6),
ndisc_node_type (self),
- get_ra_timeout (self),
+ _prop_get_ipv6_ra_timeout (self),
&error);
if (!priv->ndisc) {
_LOGE (LOGD_IP6, "addrconf6: failed to start neighbor discovery: %s", error->message);
@@ -11165,67 +11196,6 @@ set_nm_ipv6ll (NMDevice *self, gboolean enable)
/*****************************************************************************/
-static NMSettingIP6ConfigPrivacy
-_ip6_privacy_clamp (NMSettingIP6ConfigPrivacy use_tempaddr)
-{
- switch (use_tempaddr) {
- case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED:
- case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR:
- case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR:
- return use_tempaddr;
- default:
- return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
- }
-}
-
-static NMSettingIP6ConfigPrivacy
-_ip6_privacy_get (NMDevice *self)
-{
- NMSettingIP6ConfigPrivacy ip6_privacy;
- NMConnection *connection;
-
- g_return_val_if_fail (self, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
-
- /* 1.) First look at the per-connection setting. If it is not -1 (unknown),
- * use it. */
- connection = nm_device_get_applied_connection (self);
- if (connection) {
- NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config (connection);
-
- if (s_ip6) {
- ip6_privacy = nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6));
- ip6_privacy = _ip6_privacy_clamp (ip6_privacy);
- if (ip6_privacy != NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN)
- return ip6_privacy;
- }
- }
-
- /* 2.) use the default value from the configuration. */
- ip6_privacy = nm_config_data_get_connection_default_int64 (NM_CONFIG_GET_DATA,
- NM_CON_DEFAULT ("ipv6.ip6-privacy"),
- self,
- NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
- NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
- NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
- if (ip6_privacy != NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN)
- return ip6_privacy;
-
- if (!nm_device_get_ip_ifindex (self))
- return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
-
- /* 3.) No valid default-value configured. Fallback to reading sysctl.
- *
- * Instead of reading static config files in /etc, just read the current sysctl value.
- * This works as NM only writes to "/proc/sys/net/ipv6/conf/IFNAME/use_tempaddr", but leaves
- * the "default" entry untouched. */
- ip6_privacy = nm_platform_sysctl_get_int32 (nm_device_get_platform (self),
- NMP_SYSCTL_PATHID_ABSOLUTE ("/proc/sys/net/ipv6/conf/default/use_tempaddr"),
- NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
- return _ip6_privacy_clamp (ip6_privacy);
-}
-
-/*****************************************************************************/
-
static gboolean
ip_requires_slaves (NMDevice *self, int addr_family)
{
@@ -11424,7 +11394,7 @@ act_stage3_ip_config_start (NMDevice *self,
nm_device_get_ip_ifindex (self),
NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
- ip6_privacy = _ip6_privacy_get (self);
+ ip6_privacy = _prop_get_ipv6_ip6_privacy (self);
if (NM_IN_STRSET (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
@@ -12553,8 +12523,8 @@ nm_device_reactivate_ip4_config (NMDevice *self,
priv->con_ip_config_4 = nm_device_ip4_config_new (self);
nm_ip4_config_merge_setting (priv->con_ip_config_4,
s_ip4_new,
- _get_mdns (self),
- _get_llmnr (self),
+ _prop_get_connection_mdns (self),
+ _prop_get_connection_llmnr (self),
nm_device_get_route_table (self, AF_INET),
nm_device_get_route_metric (self, AF_INET));
@@ -16220,7 +16190,7 @@ nm_device_spawn_iface_helper (NMDevice *self)
g_ptr_array_add (argv, g_strdup ("--uuid"));
g_ptr_array_add (argv, g_strdup (nm_connection_get_uuid (connection)));
- stable_id = _get_stable_id (self, connection, &stable_type);
+ stable_id = _prop_get_connection_stable_id (self, connection, &stable_type);
if (stable_type != NM_UTILS_STABLE_TYPE_UUID) {
g_ptr_array_add (argv, g_strdup ("--stable-id"));
g_ptr_array_add (argv, g_strdup_printf ("%d %s", (int) stable_type, stable_id));
@@ -17193,86 +17163,6 @@ notify_and_out:
_notify (self, PROP_PERM_HW_ADDRESS);
}
-static const char *
-_get_cloned_mac_address_setting (NMDevice *self, NMConnection *connection, gboolean is_wifi, char **out_addr)
-{
- NMSetting *setting;
- const char *addr = NULL;
-
- nm_assert (out_addr && !*out_addr);
-
- setting = nm_connection_get_setting (connection,
- is_wifi ? NM_TYPE_SETTING_WIRELESS : NM_TYPE_SETTING_WIRED);
- if (setting) {
- addr = is_wifi
- ? nm_setting_wireless_get_cloned_mac_address ((NMSettingWireless *) setting)
- : nm_setting_wired_get_cloned_mac_address ((NMSettingWired *) setting);
- }
-
- if (!addr) {
- gs_free char *a = NULL;
-
- a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
- is_wifi
- ? NM_CON_DEFAULT ("wifi.cloned-mac-address")
- : NM_CON_DEFAULT ("ethernet.cloned-mac-address"),
- self);
-
- addr = NM_CLONED_MAC_PRESERVE;
-
- if (!a) {
- if (is_wifi) {
- NMSettingMacRandomization v;
-
- /* for backward compatibility, read the deprecated wifi.mac-address-randomization setting. */
- a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
- NM_CON_DEFAULT ("wifi.mac-address-randomization"),
- self);
- v = _nm_utils_ascii_str_to_int64 (a, 10,
- NM_SETTING_MAC_RANDOMIZATION_DEFAULT,
- NM_SETTING_MAC_RANDOMIZATION_ALWAYS,
- NM_SETTING_MAC_RANDOMIZATION_DEFAULT);
- if (v == NM_SETTING_MAC_RANDOMIZATION_ALWAYS)
- addr = NM_CLONED_MAC_RANDOM;
- }
- } else if ( NM_CLONED_MAC_IS_SPECIAL (a)
- || nm_utils_hwaddr_valid (a, ETH_ALEN))
- addr = *out_addr = g_steal_pointer (&a);
- }
-
- return addr;
-}
-
-static const char *
-_get_generate_mac_address_mask_setting (NMDevice *self, NMConnection *connection, gboolean is_wifi, char **out_value)
-{
- NMSetting *setting;
- const char *value = NULL;
- char *a;
-
- nm_assert (out_value && !*out_value);
-
- setting = nm_connection_get_setting (connection,
- is_wifi ? NM_TYPE_SETTING_WIRELESS : NM_TYPE_SETTING_WIRED);
- if (setting) {
- value = is_wifi
- ? nm_setting_wireless_get_generate_mac_address_mask ((NMSettingWireless *) setting)
- : nm_setting_wired_get_generate_mac_address_mask ((NMSettingWired *) setting);
- if (value)
- return value;
- }
-
- a = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
- is_wifi
- ? NM_CON_DEFAULT ("wifi.generate-mac-address-mask")
- : NM_CON_DEFAULT ("ethernet.generate-mac-address-mask"),
- self);
- if (!a)
- return NULL;
- *out_value = a;
- return a;
-}
-
gboolean
nm_device_hw_addr_is_explict (NMDevice *self)
{
@@ -17513,7 +17403,7 @@ _hw_addr_get_cloned (NMDevice *self, NMConnection *connection, gboolean is_wifi,
if (!connection)
g_return_val_if_reached (FALSE);
- addr = addr_setting = _get_cloned_mac_address_setting (self, connection, is_wifi, &addr_setting_free);
+ addr = addr_setting = _prop_get_x_cloned_mac_address (self, connection, is_wifi, &addr_setting_free);
if (nm_streq (addr, NM_CLONED_MAC_PRESERVE)) {
/* "preserve" means to reset the initial MAC address. */
@@ -17552,9 +17442,10 @@ _hw_addr_get_cloned (NMDevice *self, NMConnection *connection, gboolean is_wifi,
goto out_no_action;
}
hw_addr_generated = nm_utils_hw_addr_gen_random_eth (nm_device_get_initial_hw_address (self),
- _get_generate_mac_address_mask_setting (self, connection,
- is_wifi,
- &generate_mac_address_mask_tmp));
+ _prop_get_x_generate_mac_address_mask (self,
+ connection,
+ is_wifi,
+ &generate_mac_address_mask_tmp));
if (!hw_addr_generated) {
g_set_error (error,
NM_DEVICE_ERROR,
@@ -17575,11 +17466,11 @@ _hw_addr_get_cloned (NMDevice *self, NMConnection *connection, gboolean is_wifi,
goto out_no_action;
}
- stable_id = _get_stable_id (self, connection, &stable_type);
+ stable_id = _prop_get_connection_stable_id (self, connection, &stable_type);
hw_addr_generated = nm_utils_hw_addr_gen_stable_eth (stable_type, stable_id,
nm_device_get_ip_iface (self),
nm_device_get_initial_hw_address (self),
- _get_generate_mac_address_mask_setting (self, connection, is_wifi, &generate_mac_address_mask_tmp));
+ _prop_get_x_generate_mac_address_mask (self, connection, is_wifi, &generate_mac_address_mask_tmp));
if (!hw_addr_generated) {
g_set_error (error,
NM_DEVICE_ERROR,
@@ -18201,7 +18092,7 @@ nm_device_init (NMDevice *self)
priv->unmanaged_mask = priv->unmanaged_flags;
priv->available_connections = g_hash_table_new_full (nm_direct_hash, NULL, g_object_unref, NULL);
priv->ip6_saved_properties = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, g_free);
- priv->sys_iface_state = NM_DEVICE_SYS_IFACE_STATE_EXTERNAL;
+ priv->sys_iface_state_ = NM_DEVICE_SYS_IFACE_STATE_EXTERNAL;
priv->v4_commit_first_time = TRUE;
priv->v6_commit_first_time = TRUE;
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index 36cae7a3aa..d9ac0022f8 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -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,
diff --git a/src/dhcp/nm-dhcp-client.c b/src/dhcp/nm-dhcp-client.c
index b02ff93426..9f937ac13e 100644
--- a/src/dhcp/nm-dhcp-client.c
+++ b/src/dhcp/nm-dhcp-client.c
@@ -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,
diff --git a/src/dhcp/nm-dhcp-manager.c b/src/dhcp/nm-dhcp-manager.c
index 5148d641f1..78677d8eec 100644
--- a/src/dhcp/nm-dhcp-manager.c
+++ b/src/dhcp/nm-dhcp-manager.c
@@ -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)
diff --git a/src/dhcp/nm-dhcp-options.c b/src/dhcp/nm-dhcp-options.c
index d902c77c8c..6051135cea 100644
--- a/src/dhcp/nm-dhcp-options.c
+++ b/src/dhcp/nm-dhcp-options.c
@@ -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);
diff --git a/src/dhcp/nm-dhcp-utils.c b/src/dhcp/nm-dhcp-utils.c
index 88ced0548e..c4bb7872ce 100644
--- a/src/dhcp/nm-dhcp-utils.c
+++ b/src/dhcp/nm-dhcp-utils.c
@@ -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);
+}
diff --git a/src/dhcp/nm-dhcp-utils.h b/src/dhcp/nm-dhcp-utils.h
index ecb91809be..c773262d80 100644
--- a/src/dhcp/nm-dhcp-utils.h
+++ b/src/dhcp/nm-dhcp-utils.h
@@ -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__ */
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
index 1f976f2c30..3e785c38a5 100644
--- a/src/nm-core-utils.c
+++ b/src/nm-core-utils.c
@@ -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
diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h
index 8b5e69916d..0ac95e285e 100644
--- a/src/nm-core-utils.h
+++ b/src/nm-core-utils.h
@@ -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);
diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c
index 5904e8fc0b..0335b7617a 100644
--- a/src/nm-iface-helper.c
+++ b/src/nm-iface-helper.c
@@ -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;
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index 69b74c7298..7b5046d253 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -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;
}
diff --git a/src/nm-l3-config-data.c b/src/nm-l3-config-data.c
index d547b5bd60..bff22c578f 100644
--- a/src/nm-l3-config-data.c
+++ b/src/nm-l3-config-data.c
@@ -54,6 +54,14 @@ struct _NML3ConfigData {
union {
struct {
+ NMDhcpLease *dhcp_lease_6;
+ NMDhcpLease *dhcp_lease_4;
+ };
+ NMDhcpLease *dhcp_lease_x[2];
+ };
+
+ union {
+ struct {
GArray *nameservers_6;
GArray *nameservers_4;
};
@@ -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 *
diff --git a/src/nm-l3-config-data.h b/src/nm-l3-config-data.h
index 429325626c..2a29fad0df 100644
--- a/src/nm-l3-config-data.h
+++ b/src/nm-l3-config-data.h
@@ -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)
diff --git a/src/nm-l3cfg.c b/src/nm-l3cfg.c
index 2086cd00e7..5354a5dbbf 100644
--- a/src/nm-l3cfg.c
+++ b/src/nm-l3cfg.c
@@ -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,
diff --git a/src/nm-l3cfg.h b/src/nm-l3cfg.h
index 4a3bab1111..7f0a9de8fa 100644
--- a/src/nm-l3cfg.h
+++ b/src/nm-l3cfg.h
@@ -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__ */
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index b8302fea95..c75fb1a947 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -3401,6 +3401,38 @@ nm_platform_ip6_address_get_peer (const NMPlatformIP6Address *addr)
}
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,
in_addr_t address,
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 53bfcaf486..41b950ea02 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -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__ */