summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/nm-device.c31
-rw-r--r--src/nm-config.c186
-rw-r--r--src/nm-config.h5
-rw-r--r--src/nm-manager.c5
4 files changed, 156 insertions, 71 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index cbd3aee02d..61f7395c60 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -13639,6 +13639,7 @@ nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze)
gboolean success_read;
int ifindex;
const NMPlatformLink *pllink;
+ const NMConfigDeviceStateData *dev_state;
if (priv->hw_addr_perm) {
/* the permanent hardware address is only read once and not
@@ -13698,23 +13699,19 @@ nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze)
/* We also persist our choice of the fake address to the device state
* file to use the same address on restart of NetworkManager.
* First, try to reload the address from the state file. */
- {
- gs_free NMConfigDeviceStateData *dev_state = NULL;
-
- dev_state = nm_config_device_state_load (ifindex);
- if ( dev_state
- && dev_state->perm_hw_addr_fake
- && nm_utils_hwaddr_aton (dev_state->perm_hw_addr_fake, buf, priv->hw_addr_len)
- && !nm_utils_hwaddr_matches (buf, priv->hw_addr_len, priv->hw_addr, -1)) {
- _LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use from statefile: %s, current: %s)",
- success_read
- ? "read HW addr length of permanent MAC address differs"
- : "unable to read permanent MAC address",
- dev_state->perm_hw_addr_fake,
- priv->hw_addr);
- priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, priv->hw_addr_len);
- goto notify_and_out;
- }
+ dev_state = nm_config_device_state_get (nm_config_get (), ifindex);
+ if ( dev_state
+ && dev_state->perm_hw_addr_fake
+ && nm_utils_hwaddr_aton (dev_state->perm_hw_addr_fake, buf, priv->hw_addr_len)
+ && !nm_utils_hwaddr_matches (buf, priv->hw_addr_len, priv->hw_addr, -1)) {
+ _LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use from statefile: %s, current: %s)",
+ success_read
+ ? "read HW addr length of permanent MAC address differs"
+ : "unable to read permanent MAC address",
+ dev_state->perm_hw_addr_fake,
+ priv->hw_addr);
+ priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, priv->hw_addr_len);
+ goto notify_and_out;
}
_LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use current: %s)",
diff --git a/src/nm-config.c b/src/nm-config.c
index c344d5cd15..771d74f2ac 100644
--- a/src/nm-config.c
+++ b/src/nm-config.c
@@ -121,6 +121,14 @@ typedef struct {
* because the state changes only on explicit actions from the daemon
* itself. */
State *state;
+
+ /* the hash table of device states. It is only loaded from disk
+ * once and kept immutable afterwards.
+ *
+ * We also read all state file at once. We don't want to support
+ * that they are changed outside of NM (at least not while NM is running).
+ * Hence, we read them once, that's it. */
+ GHashTable *device_states;
} NMConfigPrivate;
struct _NMConfig {
@@ -1945,46 +1953,45 @@ _config_device_state_data_new (int ifindex, GKeyFile *kf)
gint nm_owned = -1;
char *p;
+ nm_assert (kf);
nm_assert (ifindex > 0);
- if (kf) {
- switch (nm_config_keyfile_get_boolean (kf,
- DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
- DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_MANAGED,
- -1)) {
- case TRUE:
- managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED;
- connection_uuid = nm_config_keyfile_get_value (kf,
- DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
- DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_CONNECTION_UUID,
- NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY);
- break;
- case FALSE:
- managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNMANAGED;
- break;
- case -1:
- /* missing property in keyfile. */
- break;
- }
-
- perm_hw_addr_fake = nm_config_keyfile_get_value (kf,
- DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
- DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_PERM_HW_ADDR_FAKE,
- NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY);
- if (perm_hw_addr_fake) {
- char *normalized;
+ switch (nm_config_keyfile_get_boolean (kf,
+ DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
+ DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_MANAGED,
+ -1)) {
+ case TRUE:
+ managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED;
+ connection_uuid = nm_config_keyfile_get_value (kf,
+ DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
+ DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_CONNECTION_UUID,
+ NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY);
+ break;
+ case FALSE:
+ managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNMANAGED;
+ break;
+ case -1:
+ /* missing property in keyfile. */
+ break;
+ }
- normalized = nm_utils_hwaddr_canonical (perm_hw_addr_fake, -1);
- g_free (perm_hw_addr_fake);
- perm_hw_addr_fake = normalized;
- }
+ perm_hw_addr_fake = nm_config_keyfile_get_value (kf,
+ DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
+ DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_PERM_HW_ADDR_FAKE,
+ NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY);
+ if (perm_hw_addr_fake) {
+ char *normalized;
- nm_owned = nm_config_keyfile_get_boolean (kf,
- DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
- DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_NM_OWNED,
- -1);
+ normalized = nm_utils_hwaddr_canonical (perm_hw_addr_fake, -1);
+ g_free (perm_hw_addr_fake);
+ perm_hw_addr_fake = normalized;
}
+ nm_owned = nm_config_keyfile_get_boolean (kf,
+ DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
+ DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_NM_OWNED,
+ -1);
+
connection_uuid_len = connection_uuid ? strlen (connection_uuid) + 1 : 0;
perm_hw_addr_fake_len = perm_hw_addr_fake ? strlen (perm_hw_addr_fake) + 1 : 0;
@@ -2034,14 +2041,13 @@ nm_config_device_state_load (int ifindex)
kf = nm_config_create_keyfile ();
if (!g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, NULL))
- g_clear_pointer (&kf, g_key_file_unref);
+ return NULL;
device_state = _config_device_state_data_new (ifindex, kf);
nm_owned_str = device_state->nm_owned == TRUE ?
", nm-owned=1" :
(device_state->nm_owned == FALSE ? ", nm-owned=0" : "");
-
_LOGT ("device-state: %s #%d (%s); managed=%s%s%s%s%s%s%s%s",
kf ? "read" : "miss",
ifindex, path,
@@ -2053,6 +2059,49 @@ nm_config_device_state_load (int ifindex)
return device_state;
}
+static int
+_device_state_parse_filename (const char *filename)
+{
+ if (!filename || !filename[0])
+ return 0;
+ if (!NM_STRCHAR_ALL (filename, ch, g_ascii_isdigit (ch)))
+ return 0;
+ return _nm_utils_ascii_str_to_int64 (filename, 10, 1, G_MAXINT, 0);
+}
+
+GHashTable *
+nm_config_device_state_load_all (void)
+{
+ GHashTable *states;
+ GDir *dir;
+ const char *fn;
+ int ifindex;
+
+ states = g_hash_table_new_full (nm_direct_hash, NULL, NULL, g_free);
+
+ dir = g_dir_open (NM_CONFIG_DEVICE_STATE_DIR, 0, NULL);
+ if (!dir)
+ return states;
+
+ while ((fn = g_dir_read_name (dir))) {
+ NMConfigDeviceStateData *state;
+
+ ifindex = _device_state_parse_filename (fn);
+ if (ifindex <= 0)
+ continue;
+
+ state = nm_config_device_state_load (ifindex);
+ if (!state)
+ continue;
+
+ if (!nm_g_hash_table_insert (states, GINT_TO_POINTER (ifindex), state))
+ nm_assert_not_reached ();
+ }
+ g_dir_close (dir);
+
+ return states;
+}
+
gboolean
nm_config_device_state_write (int ifindex,
NMConfigDeviceStateManagedType managed,
@@ -2121,7 +2170,6 @@ nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes)
const char *fn;
int ifindex;
gsize fn_len;
- gsize i;
char buf[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR"/") + 30 + 3] = NM_CONFIG_DEVICE_STATE_DIR"/";
char *buf_p = &buf[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR"/")];
@@ -2132,24 +2180,20 @@ nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes)
return;
while ((fn = g_dir_read_name (dir))) {
- fn_len = strlen (fn);
-
- /* skip over file names that are not plain integers. */
- for (i = 0; i < fn_len; i++) {
- if (!g_ascii_isdigit (fn[i]))
- break;
- }
- if (fn_len == 0 || i != fn_len)
+ ifindex = _device_state_parse_filename (fn);
+ if (ifindex <= 0)
continue;
-
- ifindex = _nm_utils_ascii_str_to_int64 (fn, 10, 1, G_MAXINT, 0);
- if (!ifindex)
- continue;
-
if (g_hash_table_contains (seen_ifindexes, GINT_TO_POINTER (ifindex)))
continue;
- memcpy (buf_p, fn, fn_len + 1);
+ fn_len = strlen (fn) + 1;
+ nm_assert (&buf_p[fn_len] < &buf[G_N_ELEMENTS (buf)]);
+ memcpy (buf_p, fn, fn_len);
+ nm_assert (({
+ char bb[30];
+ nm_sprintf_buf (bb, "%d", ifindex);
+ nm_streq0 (bb, buf_p);
+ }));
_LOGT ("device-state: prune #%d (%s)", ifindex, buf);
(void) unlink (buf);
}
@@ -2159,6 +2203,46 @@ nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes)
/*****************************************************************************/
+static GHashTable *
+_device_state_get_all (NMConfig *self)
+{
+ NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self);
+
+ if (G_UNLIKELY (!priv->device_states))
+ priv->device_states = nm_config_device_state_load_all ();
+ return priv->device_states;
+}
+
+/**
+ * nm_config_device_state_get_all:
+ * @self: the #NMConfig
+ *
+ * This function exists to give convenient access to all
+ * device states. Do not ever try to modify the returned
+ * hash, it's supposed to be immutable.
+ *
+ * Returns: the internal #GHashTable object with all device states.
+ */
+const GHashTable *
+nm_config_device_state_get_all (NMConfig *self)
+{
+ g_return_val_if_fail (NM_IS_CONFIG (self), NULL);
+
+ return _device_state_get_all (self);
+}
+
+const NMConfigDeviceStateData *
+nm_config_device_state_get (NMConfig *self,
+ int ifindex)
+{
+ g_return_val_if_fail (NM_IS_CONFIG (self), NULL);
+ g_return_val_if_fail (ifindex > 0 , NULL);
+
+ return g_hash_table_lookup (_device_state_get_all (self), GINT_TO_POINTER (ifindex));
+}
+
+/*****************************************************************************/
+
void
nm_config_reload (NMConfig *self, NMConfigChangeFlags reload_flags)
{
diff --git a/src/nm-config.h b/src/nm-config.h
index 389a5e30de..698db3dce7 100644
--- a/src/nm-config.h
+++ b/src/nm-config.h
@@ -225,6 +225,7 @@ struct _NMConfigDeviceStateData {
};
NMConfigDeviceStateData *nm_config_device_state_load (int ifindex);
+GHashTable *nm_config_device_state_load_all (void);
gboolean nm_config_device_state_write (int ifindex,
NMConfigDeviceStateManagedType managed,
const char *perm_hw_addr_fake,
@@ -232,6 +233,10 @@ gboolean nm_config_device_state_write (int ifindex,
gint nm_owned);
void nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes);
+const GHashTable *nm_config_device_state_get_all (NMConfig *self);
+const NMConfigDeviceStateData *nm_config_device_state_get (NMConfig *self,
+ int ifindex);
+
/*****************************************************************************/
#endif /* __NETWORKMANAGER_CONFIG_H__ */
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 04d17f9b23..034f9e76ff 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -2641,10 +2641,9 @@ platform_query_devices (NMManager *self)
return;
for (i = 0; i < links->len; i++) {
const NMPlatformLink *link = NMP_OBJECT_CAST_LINK (links->pdata[i]);
- gs_free NMConfigDeviceStateData *dev_state = NULL;
-
- dev_state = nm_config_device_state_load (link->ifindex);
+ const NMConfigDeviceStateData *dev_state;
+ dev_state = nm_config_device_state_get (priv->config, link->ifindex);
platform_link_added (self,
link->ifindex,
link,