Commit ce4dbd7d authored by Lubomir Rintel's avatar Lubomir Rintel 🥕
Browse files

keyfile: write in-memory connections to /run

This is useful for in-memory connections to persist NetworkManager
restarts (as opposed to machine restarts).

Perhaps most improtantly, this allows generating in-memory connections outside
NetworkManager, e.g. passing configuration from early boot firmware in initrd.

Note that this does *not* aspire to do more than it says on the tin:
Notably, it doesn't touch the problem of provisioning connections in multiple
persistent connection directories and thus doesn't have to deal with the
problem of deleting or overlaying the connections tha (rh #772414) deals
with.
parent e98ebc7e
......@@ -66,6 +66,7 @@ commit_changes (NMSettingsConnection *connection,
nm_assert (!out_logmsg_change || !*out_logmsg_change);
if (!nms_keyfile_writer_connection (new_connection,
TRUE,
nm_settings_connection_get_filename (connection),
NM_FLAGS_ALL (commit_reason, NM_SETTINGS_CONNECTION_COMMIT_REASON_USER_ACTION
| NM_SETTINGS_CONNECTION_COMMIT_REASON_ID_CHANGED),
......
......@@ -171,6 +171,7 @@ update_connection (NMSKeyfilePlugin *self,
NMSKeyfileConnection *connection_by_uuid;
GError *local = NULL;
const char *uuid;
int dir_len;
g_return_val_if_fail (!source || NM_IS_CONNECTION (source), NULL);
g_return_val_if_fail (full_path || source, NULL);
......@@ -178,6 +179,22 @@ update_connection (NMSKeyfilePlugin *self,
if (full_path)
_LOGD ("loading from file \"%s\"...", full_path);
if (g_str_has_prefix (full_path, nms_keyfile_utils_get_path ())) {
dir_len = strlen (nms_keyfile_utils_get_path ());
} else if (g_str_has_prefix (full_path, NM_CONFIG_KEYFILE_PATH_IN_MEMORY)) {
dir_len = NM_STRLEN (NM_CONFIG_KEYFILE_PATH_IN_MEMORY);
} else {
/* Just make sure the file name is not going go pass the following check. */
dir_len = strlen (full_path);
}
if ( full_path[dir_len] != '/'
|| strchr (full_path + dir_len + 1, '/') != NULL) {
g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
"File not in recognized system-connections directory");
return FALSE;
}
connection_new = nms_keyfile_connection_new (source, full_path, &local);
if (!connection_new) {
/* Error; remove the connection */
......@@ -411,39 +428,47 @@ _sort_paths (const char **f1, const char **f2, GHashTable *paths)
}
static void
read_connections (NMSettingsPlugin *config)
_read_dir (GPtrArray *filenames, const char *path)
{
NMSKeyfilePlugin *self = NMS_KEYFILE_PLUGIN (config);
NMSKeyfilePluginPrivate *priv = NMS_KEYFILE_PLUGIN_GET_PRIVATE (self);
GDir *dir;
GError *error = NULL;
const char *item;
GHashTable *alive_connections;
GHashTableIter iter;
NMSKeyfileConnection *connection;
GPtrArray *dead_connections = NULL;
guint i;
GPtrArray *filenames;
GHashTable *paths;
GError *error = NULL;
dir = g_dir_open (nms_keyfile_utils_get_path (), 0, &error);
dir = g_dir_open (path, 0, &error);
if (!dir) {
_LOGW ("cannot read directory '%s': %s",
nms_keyfile_utils_get_path (),
error->message);
_LOGD ("cannot read directory '%s': %s", path, error->message);
g_clear_error (&error);
return;
}
alive_connections = g_hash_table_new (nm_direct_hash, NULL);
filenames = g_ptr_array_new_with_free_func (g_free);
while ((item = g_dir_read_name (dir))) {
if (nms_keyfile_utils_should_ignore_file (item))
continue;
g_ptr_array_add (filenames, g_build_filename (nms_keyfile_utils_get_path (), item, NULL));
g_ptr_array_add (filenames, g_build_filename (path, item, NULL));
}
g_dir_close (dir);
}
static void
read_connections (NMSettingsPlugin *config)
{
NMSKeyfilePlugin *self = NMS_KEYFILE_PLUGIN (config);
NMSKeyfilePluginPrivate *priv = NMS_KEYFILE_PLUGIN_GET_PRIVATE (self);
GHashTable *alive_connections;
GHashTableIter iter;
NMSKeyfileConnection *connection;
GPtrArray *dead_connections = NULL;
guint i;
GPtrArray *filenames;
GHashTable *paths;
filenames = g_ptr_array_new_with_free_func (g_free);
_read_dir (filenames, NM_CONFIG_KEYFILE_PATH_IN_MEMORY);
_read_dir (filenames, nms_keyfile_utils_get_path ());
alive_connections = g_hash_table_new (nm_direct_hash, NULL);
/* While reloading, we don't replace connections that we already loaded while
* iterating over the files.
......@@ -501,14 +526,8 @@ load_connection (NMSettingsPlugin *config,
{
NMSKeyfilePlugin *self = NMS_KEYFILE_PLUGIN ((NMSKeyfilePlugin *) config);
NMSKeyfileConnection *connection;
int dir_len = strlen (nms_keyfile_utils_get_path ());
if ( strncmp (filename, nms_keyfile_utils_get_path (), dir_len) != 0
|| filename[dir_len] != '/'
|| strchr (filename + dir_len + 1, '/') != NULL)
return FALSE;
if (nms_keyfile_utils_should_ignore_file (filename + dir_len + 1))
if (nms_keyfile_utils_should_ignore_file (filename))
return FALSE;
connection = update_connection (self, NULL, filename, find_by_path (self, filename), TRUE, NULL, NULL);
......@@ -532,16 +551,16 @@ add_connection (NMSettingsPlugin *config,
gs_free char *path = NULL;
gs_unref_object NMConnection *reread = NULL;
if (save_to_disk) {
if (!nms_keyfile_writer_connection (connection,
NULL,
FALSE,
&path,
&reread,
NULL,
error))
return NULL;
}
if (!nms_keyfile_writer_connection (connection,
save_to_disk,
NULL,
FALSE,
&path,
&reread,
NULL,
error))
return NULL;
return NM_SETTINGS_CONNECTION (update_connection (self, reread ?: connection, path, NULL, FALSE, NULL, error));
}
......
......@@ -23,6 +23,8 @@
#include "NetworkManagerUtils.h"
#define NM_CONFIG_KEYFILE_PATH_IN_MEMORY NMRUNDIR "/system-connections"
#define NMS_KEYFILE_CONNECTION_LOG_PATH(path) ((path) ?: "in-memory")
#define NMS_KEYFILE_CONNECTION_LOG_FMT "%s (%s,\"%s\")"
#define NMS_KEYFILE_CONNECTION_LOG_ARG(con) NMS_KEYFILE_CONNECTION_LOG_PATH (nm_settings_connection_get_filename ((NMSettingsConnection *) (con))), nm_settings_connection_get_uuid ((NMSettingsConnection *) (con)), nm_settings_connection_get_id ((NMSettingsConnection *) (con))
......
......@@ -189,10 +189,14 @@ _internal_write_connection (NMConnection *connection,
WriteInfo info = { 0 };
GError *local_err = NULL;
int errsv;
gboolean rename = force_rename;
g_return_val_if_fail (!out_path || !*out_path, FALSE);
g_return_val_if_fail (keyfile_dir && keyfile_dir[0] == '/', FALSE);
if (existing_path && !g_str_has_prefix (existing_path, keyfile_dir))
rename = TRUE;
switch (_nm_connection_verify (connection, error)) {
case NM_SETTING_VERIFY_NORMALIZABLE:
nm_assert_not_reached ();
......@@ -221,7 +225,7 @@ _internal_write_connection (NMConnection *connection,
/* If we have existing file path, use it. Else generate one from
* connection's ID.
*/
if (existing_path != NULL && !force_rename) {
if (existing_path != NULL && !rename) {
path = g_strdup (existing_path);
} else {
char *filename_escaped = nms_keyfile_utils_escape_filename (id);
......@@ -337,6 +341,7 @@ _internal_write_connection (NMConnection *connection,
gboolean
nms_keyfile_writer_connection (NMConnection *connection,
gboolean save_to_disk,
const char *existing_path,
gboolean force_rename,
char **out_path,
......@@ -344,8 +349,15 @@ nms_keyfile_writer_connection (NMConnection *connection,
gboolean *out_reread_same,
GError **error)
{
const char *keyfile_dir;
if (save_to_disk)
keyfile_dir = nms_keyfile_utils_get_path ();
else
keyfile_dir = NM_CONFIG_KEYFILE_PATH_IN_MEMORY;
return _internal_write_connection (connection,
nms_keyfile_utils_get_path (),
keyfile_dir,
0, 0,
existing_path,
force_rename,
......
......@@ -25,6 +25,7 @@
#include "nm-connection.h"
gboolean nms_keyfile_writer_connection (NMConnection *connection,
gboolean save_to_disk,
const char *existing_path,
gboolean force_rename,
char **out_path,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment