settings: rework tracking settings connections and settings plugins

Completely rework how settings plugin handle connections and how
NMSettings tracks the list of connections.

Previously, settings plugins would return objects of (a subtype of) type
NMSettingsConnection. The NMSettingsConnection was tightly coupled with
the settings plugin. That has a lot of downsides.

Change that. When changing this basic relation how settings connections
are tracked, everything falls appart. That's why this is a huge change.
Also, since I have to largely rewrite the settings plugins, I also
added support for multiple keyfile directories, handle in-memory
connections only by keyfile plugin and (partly) use copy-on-write NMConnection
instances. I don't want to spend effort rewriting large parts while
preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh,
I don't want to let it handle in-memory connections because that's not right
long-term.

--

If the settings plugins themself create subtypes of NMSettingsConnection
instances, then a lot of knowledge about tracking connections moves
to the plugins.
Just try to follow the code what happend during nm_settings_add_connection().
Note how the logic is spread out:
 - nm_settings_add_connection() calls plugin's add_connection()
 - add_connection() creates a NMSettingsConnection subtype
 - the plugin has to know that it's called during add-connection and
   not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal
 - NMSettings calls claim_connection() which hocks up the new
   NMSettingsConnection instance and configures the instance
   (like calling nm_settings_connection_added()).
This summary does not sound like a lot, but try to follow that code. The logic
is all over the place.

Instead, settings plugins should have a very simple API for adding, modifying,
deleting, loading and reloading connections. All the plugin does is to return a
NMSettingsStorage handle. The storage instance is a handle to identify a profile
in storage (e.g. a particular file). The settings plugin is free to subtype
NMSettingsStorage, but it's not necessary.
There are no more events raised, and the settings plugin implements the small
API in a straightforward manner.
NMSettings now drives all of this. Even NMSettingsConnection has now
very little concern about how it's tracked and delegates only to NMSettings.

This should make settings plugins simpler. Currently settings plugins
are so cumbersome to implement, that we avoid having them. It should not be
like that and it should be easy, beneficial and lightweight to create a new
settings plugin.

Note also how the settings plugins no longer care about duplicate UUIDs.
Duplicated UUIDs are a fact of life and NMSettings must handle them. No
need to overly concern settings plugins with that.

--

NMSettingsConnection is exposed directly on D-Bus (being a subtype of
NMDBusObject) but it was also a GObject type provided by the settings
plugin. Hence, it was not possible to migrate a profile from one plugin to
another.
However that would be useful when one profile does not support a
connection type (like ifcfg-rh not supporting VPN). Currently such
migration is not implemented except for migrating them to/from keyfile's
run directory. The problem is that migrating profiles in general is
complicated but in some cases it is important to do.

For example checkpoint rollback should recreate the profile in the right
settings plugin, not just add it to persistent storage. This is not yet
properly implemented.

--

Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved)
profiles, while ifupdown plugin cannot handle them. That meant duplication of code
and a ifupdown profile could not be modified or made unsaved.
This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711).
Also, NMSettings is aware of such profiles and treats them specially.
In particular, NMSettings drives the migration between persistent and non-persistent
storage.

Note that a settings plugins may create truly generated, in-memory profiles.
The settings plugin is free to generate and persist the profiles in any way it
wishes. But the concept of "unsaved" profiles is now something explicitly handled
by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system
too, to the /run directory. This is great for two reasons: first of all, all
profiles from keyfile storage in fact have a backing file -- even the
unsaved ones. It also means you can create "unsaved" profiles in /run
and load them with `nmcli connection load`, meaning there is a file
based API for creating unsaved profiles.
The other advantage is that these profiles now survive restarting
NetworkManager. It's paramount that restarting the daemon is as
non-disruptive as possible. Persisting unsaved files to /run improves
here significantly.

--

In the past, NMSettingsConnection also implemented NMConnection interface.
That was already changed a while ago and instead users call now
nm_settings_connection_get_connection() to delegate to a
NMSimpleConnection. What however still happened was that the NMConnection
instance gets never swapped but instead the instance was modified with
nm_connection_replace_settings_from_connection(), clear-secrets, etc.
Change that and treat the NMConnection instance immutable. Instead of modifying
it, reference/clone a new instance. This changes that previously when somebody
wanted to keep a reference to an NMConnection, then the profile would be cloned.
Now, it is supposed to be safe to reference the instance directly and everybody
must ensure not to modify the instance. nmtst_connection_assert_unchanging()
should help with that.
The point is that the settings plugins may keep references to the
NMConnection instance, and so does the NMSettingsConnection. We want
to avoid cloning the instances as long as they are the same.
Likewise, the device's applied connection can now also be referenced
instead of cloning it. This is not yet done, and possibly there are
further improvements possible.

--

Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545,
bgo #772414).

It was always the case that multiple files could provide the same UUID
(both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in
read-only storage in /usr/lib gets modified, then it gets actually stored in
/etc (or /run, if the profile is unsaved).

--

While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable.

--

https://bugzilla.gnome.org/show_bug.cgi?id=772414
https://bugzilla.gnome.org/show_bug.cgi?id=744711
https://bugzilla.redhat.com/show_bug.cgi?id=1674545
This commit is contained in:
Thomas Haller 2019-06-13 17:12:20 +02:00
parent 0631129ca6
commit d35d3c468a
58 changed files with 6475 additions and 3367 deletions

View File

@ -2094,13 +2094,17 @@ src_libNetworkManager_la_SOURCES = \
src/settings/nm-secret-agent.h \
src/settings/nm-settings-connection.c \
src/settings/nm-settings-connection.h \
src/settings/nm-settings-storage.c \
src/settings/nm-settings-storage.h \
src/settings/nm-settings-plugin.c \
src/settings/nm-settings-plugin.h \
src/settings/nm-settings.c \
src/settings/nm-settings.h \
src/settings/nm-settings-utils.c \
src/settings/nm-settings-utils.h \
\
src/settings/plugins/keyfile/nms-keyfile-connection.c \
src/settings/plugins/keyfile/nms-keyfile-connection.h \
src/settings/plugins/keyfile/nms-keyfile-storage.c \
src/settings/plugins/keyfile/nms-keyfile-storage.h \
src/settings/plugins/keyfile/nms-keyfile-plugin.c \
src/settings/plugins/keyfile/nms-keyfile-plugin.h \
src/settings/plugins/keyfile/nms-keyfile-reader.c \
@ -2819,10 +2823,11 @@ $(src_settings_plugins_ifcfg_rh_libnms_ifcfg_rh_core_la_OBJECTS): $(libnm_core_l
###############################################################################
src_settings_plugins_ifcfg_rh_libnm_settings_plugin_ifcfg_rh_la_SOURCES = \
src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c \
src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.h \
src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c \
src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.h \
src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c \
src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.h
src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.h \
$(NULL)
src_settings_plugins_ifcfg_rh_libnm_settings_plugin_ifcfg_rh_la_CPPFLAGS = $(src_cppflags_base)
@ -3135,8 +3140,6 @@ src_settings_plugins_ifupdown_libnms_ifupdown_core_la_LIBADD = \
$(NULL)
src_settings_plugins_ifupdown_libnm_settings_plugin_ifupdown_la_SOURCES = \
src/settings/plugins/ifupdown/nms-ifupdown-connection.c \
src/settings/plugins/ifupdown/nms-ifupdown-connection.h \
src/settings/plugins/ifupdown/nms-ifupdown-plugin.c \
src/settings/plugins/ifupdown/nms-ifupdown-plugin.h \
$(NULL)
@ -4834,6 +4837,7 @@ install-data-hook: $(install_data_hook)
$(mkinstalldirs) -m 0755 $(DESTDIR)$(nmconfdir)/dnsmasq-shared.d
$(mkinstalldirs) -m 0755 $(DESTDIR)$(nmlibdir)/conf.d
$(mkinstalldirs) -m 0755 $(DESTDIR)$(nmlibdir)/VPN
$(mkinstalldirs) -m 0755 $(DESTDIR)$(nmlibdir)/system-connections
$(mkinstalldirs) -m 0700 $(DESTDIR)$(nmstatedir)
$(mkinstalldirs) -m 0755 $(DESTDIR)$(plugindir)

View File

@ -847,6 +847,7 @@ fi
%dir %{nmlibdir}
%dir %{nmlibdir}/conf.d
%dir %{nmlibdir}/VPN
%dir %{nmlibdir}/system-connections
%{_mandir}/man1/*
%{_mandir}/man5/*
%{_mandir}/man7/nmcli-examples.7*

View File

@ -56,9 +56,7 @@
does not start the network connection unless (1) device is idle and able
to connect to the network described by the new connection, and (2) the
connection is allowed to be started automatically. Use the 'Save' method
on the connection to save these changes to disk. Note that unsaved changes
will be lost if the connection is reloaded from disk (either automatically
on file change or due to an explicit ReloadConnections call).
on the connection to save these changes to disk.
-->
<method name="AddConnectionUnsaved">
<arg name="connection" type="a{sa{sv}}" direction="in"/>

View File

@ -1014,6 +1014,9 @@ typedef enum { /*< flags >*/
* is not deleted but merely the connection is decoupled from the file
* on disk. If you later delete an in-memory connection, the connection
* on disk will be deleted as well.
* Note: with 1.20, this flag is no longer implemented because in-memory connections
* are also persisted under /run. For the moment, this behaves the same as
* @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED.
* @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED: this is like @NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY,
* but if the connection has a corresponding file on disk, the association between
* the connection and the file is forgotten but the file is not modified.

View File

@ -171,8 +171,13 @@ gboolean _nm_keyfile_has_values (GKeyFile *keyfile);
/*****************************************************************************/
#define NM_KEYFILE_GROUP_NMMETA ".nmmeta"
#define NM_KEYFILE_KEY_NMMETA_NM_GENERATED "nm-generated"
#define NM_KEYFILE_KEY_NMMETA_VOLATILE "volatile"
#define NM_KEYFILE_PATH_NAME_LIB NMLIBDIR "/system-connections"
#define NM_KEYFILE_PATH_NAME_ETC_DEFAULT NMCONFDIR "/system-connections"
#define NM_KEYFILE_PATH_NAME_RUN NMRUNDIR "/system-connections"
#define NM_KEYFILE_PATH_NAME_RUN NMRUNDIR "/system-connections"
#define NM_KEYFILE_PATH_SUFFIX_NMCONNECTION ".nmconnection"

View File

@ -3537,7 +3537,9 @@ nm_keyfile_read (GKeyFile *keyfile,
vpn_secrets = TRUE;
} else if (NM_STR_HAS_PREFIX (groups[i], NM_KEYFILE_GROUPPREFIX_WIREGUARD_PEER))
_read_setting_wireguard_peer (&info);
else
else if (nm_streq (groups[i], NM_KEYFILE_GROUP_NMMETA)) {
/* pass */
} else
_read_setting (&info);
info.group = NULL;

View File

@ -235,15 +235,17 @@ pan_connection_check_create (NMBluezDevice *self)
* which then already finds the suitable connection in priv->connections. This is confusing,
* so block the signal. check_emit_usable will succeed after this function call returns. */
g_signal_handlers_block_by_func (priv->settings, cp_connection_added, self);
added = nm_settings_add_connection (priv->settings, connection, FALSE, &error);
nm_settings_add_connection (priv->settings,
connection,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY,
NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED,
&added,
&error);
g_signal_handlers_unblock_by_func (priv->settings, cp_connection_added, self);
if (added) {
nm_assert (!g_slist_find (priv->connections, added));
nm_assert (connection_compatible (self, added));
nm_settings_connection_set_flags (added, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED, TRUE);
priv->connections = g_slist_prepend (priv->connections, g_object_ref (added));
priv->pan_connection = added;
nm_log_dbg (LOGD_BT, "bluez[%s] added new Bluetooth connection for NAP device: '%s' (%s)", priv->path, id, uuid);
@ -392,7 +394,7 @@ cp_connection_removed (NMSettings *settings,
static void
cp_connection_updated (NMSettings *settings,
NMSettingsConnection *sett_conn,
gboolean by_user,
guint update_reason_u,
NMBluezDevice *self)
{
if (_internal_track_connection (self, sett_conn,
@ -1225,7 +1227,7 @@ dispose (GObject *object)
if (to_delete) {
nm_log_dbg (LOGD_BT, "bluez[%s] removing Bluetooth connection for NAP device: '%s' (%s)", priv->path,
nm_settings_connection_get_id (to_delete), nm_settings_connection_get_uuid (to_delete));
nm_settings_connection_delete (to_delete, NULL);
nm_settings_connection_delete (to_delete, FALSE);
g_object_unref (to_delete);
}

View File

@ -12404,16 +12404,28 @@ nm_device_set_ip_config (NMDevice *self,
if ( nm_device_sys_iface_state_is_external (self)
&& (settings_connection = nm_device_get_settings_connection (self))
&& NM_FLAGS_HAS (nm_settings_connection_get_flags (settings_connection),
NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)
&& NM_FLAGS_ALL (nm_settings_connection_get_flags (settings_connection),
NM_SETTINGS_CONNECTION_INT_FLAGS_UNSAVED
| NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE
| NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)
&& nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request.obj)) == NM_ACTIVATION_TYPE_EXTERNAL) {
g_object_freeze_notify (G_OBJECT (settings_connection));
/* FIXME(copy-on-write-connection): avoid modifying NMConnection instances and share them via copy-on-write. */
nm_connection_add_setting (nm_settings_connection_get_connection (settings_connection),
gs_unref_object NMConnection *new_connection = NULL;
new_connection = nm_simple_connection_new_clone (nm_settings_connection_get_connection (settings_connection));
nm_connection_add_setting (new_connection,
IS_IPv4
? nm_ip4_config_create_setting (priv->ip_config_4)
: nm_ip6_config_create_setting (priv->ip_config_6));
g_object_thaw_notify (G_OBJECT (settings_connection));
nm_settings_connection_update (settings_connection,
new_connection,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED,
NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE,
"update-external",
NULL);
}
nm_device_queue_recheck_assume (self);
@ -14365,7 +14377,7 @@ cp_connection_added (NMSettings *settings, NMSettingsConnection *sett_conn, gpoi
}
static void
cp_connection_updated (NMSettings *settings, NMSettingsConnection *sett_conn, gboolean by_user, gpointer user_data)
cp_connection_updated (NMSettings *settings, NMSettingsConnection *sett_conn, guint update_reason_u, gpointer user_data)
{
cp_connection_added_or_updated (user_data, sett_conn);
}

View File

@ -1760,9 +1760,10 @@ supplicant_iface_wps_credentials_cb (NMSupplicantInterface *iface,
}
if (secrets) {
if (nm_settings_connection_new_secrets (nm_act_request_get_settings_connection (req),
nm_act_request_get_applied_connection (req),
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
secrets, &error)) {
nm_act_request_get_applied_connection (req),
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
secrets,
&error)) {
wifi_secrets_cancel (self);
nm_device_activate_schedule_stage1_device_prepare (NM_DEVICE (self));
} else {

View File

@ -469,19 +469,18 @@ mirror_8021x_connection (NMIwdManager *self,
if (!nm_connection_normalize (connection, NULL, NULL, NULL))
return NULL;
settings_connection = nm_settings_add_connection (priv->settings, connection,
FALSE, &error);
if (!settings_connection) {
if (!nm_settings_add_connection (priv->settings,
connection,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY,
NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED,
&settings_connection,
&error)) {
_LOGW ("failed to add a mirror NMConnection for IWD's Known Network '%s': %s",
name, error->message);
g_error_free (error);
return NULL;
}
nm_settings_connection_set_flags (settings_connection,
NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED |
NM_SETTINGS_CONNECTION_INT_FLAGS_UNSAVED,
TRUE);
return settings_connection;
}
@ -498,7 +497,7 @@ mirror_8021x_connection_take_and_delete (NMSettingsConnection *sett_conn)
/* If connection has not been saved since we created it
* in interface_added it too can be removed now. */
if (NM_FLAGS_HAS (flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED))
nm_settings_connection_delete (sett_conn, NULL);
nm_settings_connection_delete (sett_conn, FALSE);
g_object_unref (sett_conn);
}

View File

@ -103,7 +103,7 @@ sources = files(
'dnsmasq/nm-dnsmasq-manager.c',
'dnsmasq/nm-dnsmasq-utils.c',
'ppp/nm-ppp-manager-call.c',
'settings/plugins/keyfile/nms-keyfile-connection.c',
'settings/plugins/keyfile/nms-keyfile-storage.c',
'settings/plugins/keyfile/nms-keyfile-plugin.c',
'settings/plugins/keyfile/nms-keyfile-reader.c',
'settings/plugins/keyfile/nms-keyfile-utils.c',
@ -113,6 +113,8 @@ sources = files(
'settings/nm-settings.c',
'settings/nm-settings-connection.c',
'settings/nm-settings-plugin.c',
'settings/nm-settings-storage.c',
'settings/nm-settings-utils.c',
'supplicant/nm-supplicant-config.c',
'supplicant/nm-supplicant-interface.c',
'supplicant/nm-supplicant-manager.c',

View File

@ -181,7 +181,7 @@ NM_UTILS_FLAGS2STR_DEFINE_STATIC (_state_flags_to_string, NMActivationStateFlags
static void
_settings_connection_updated (NMSettingsConnection *sett_conn,
gboolean by_user,
guint update_reason_u,
gpointer user_data)
{
NMActiveConnection *self = user_data;
@ -522,8 +522,9 @@ nm_active_connection_clear_secrets (NMActiveConnection *self)
if (nm_settings_connection_has_unmodified_applied_connection (priv->settings_connection.obj,
priv->applied_connection,
NM_SETTING_COMPARE_FLAG_NONE)) {
/* FIXME(copy-on-write-connection): avoid modifying NMConnection instances and share them via copy-on-write. */
nm_connection_clear_secrets (nm_settings_connection_get_connection (priv->settings_connection.obj));
nm_settings_connection_clear_secrets (priv->settings_connection.obj,
FALSE,
FALSE);
}
nm_connection_clear_secrets (priv->applied_connection);
}

View File

@ -217,19 +217,35 @@ restore_and_activate_connection (NMCheckpoint *self,
gs_unref_object NMAuthSubject *subject = NULL;
GError *local_error = NULL;
gboolean need_update, need_activation;
NMSettingsConnectionPersistMode persist_mode;
NMSettingsConnectionIntFlags sett_flags;
NMSettingsConnectionIntFlags sett_mask;
connection = find_settings_connection (self,
dev_checkpoint,
&need_update,
&need_activation);
/* FIXME: we need to ensure to re-create/update the profile for the
* same settings plugin. E.g. if it was a keyfile in /run or /etc,
* it must be again. If it was previously handled by a certain settings plugin,
* so it must again.
*
* FIXME: preserve and restore the right settings flags (volatile, nm-generated). */
sett_flags = NM_SETTINGS_CONNECTION_INT_FLAGS_NONE;
sett_mask = NM_SETTINGS_CONNECTION_INT_FLAGS_NONE;
if (connection) {
if (need_update) {
_LOGD ("rollback: updating connection %s",
nm_settings_connection_get_uuid (connection));
persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP;
nm_settings_connection_update (connection,
dev_checkpoint->settings_connection,
NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK,
NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE,
persist_mode,
sett_flags,
sett_mask,
NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE,
"checkpoint-rollback",
NULL);
}
@ -238,11 +254,13 @@ restore_and_activate_connection (NMCheckpoint *self,
_LOGD ("rollback: adding connection %s again",
nm_connection_get_uuid (dev_checkpoint->settings_connection));
connection = nm_settings_add_connection (NM_SETTINGS_GET,
dev_checkpoint->settings_connection,
TRUE,
&local_error);
if (!connection) {
persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK;
if (!nm_settings_add_connection (NM_SETTINGS_GET,
dev_checkpoint->settings_connection,
persist_mode,
sett_flags,
&connection,
&local_error)) {
_LOGD ("rollback: connection add failure: %s", local_error->message);
g_clear_error (&local_error);
return FALSE;
@ -428,7 +446,7 @@ next_dev:
nm_settings_connection_get_uuid (con))) {
_LOGD ("rollback: deleting new connection %s",
nm_settings_connection_get_uuid (con));
nm_settings_connection_delete (con, NULL);
nm_settings_connection_delete (con, FALSE);
}
}
}

View File

@ -94,7 +94,8 @@ typedef struct {
struct {
GDBusMethodInvocation *invocation;
NMConnection *connection;
NMSettingsConnectionPersistMode persist;
NMSettingsConnectionPersistMode persist_mode;
bool is_volatile:1;
} add_and_activate;
};
} ac_auth;
@ -378,7 +379,8 @@ static void _add_and_activate_auth_done (NMManager *self,
NMActiveConnection *active,
NMConnection *connection,
GDBusMethodInvocation *invocation,
NMSettingsConnectionPersistMode persist,
NMSettingsConnectionPersistMode persist_mode,
gboolean is_volatile,
gboolean success,
const char *error_desc);
static void _activation_auth_done (NMManager *self,
@ -495,7 +497,8 @@ _async_op_data_new_ac_auth_add_and_activate (NMManager *self,
NMActiveConnection *active_take,
GDBusMethodInvocation *invocation_take,
NMConnection *connection_take,
NMSettingsConnectionPersistMode persist)
NMSettingsConnectionPersistMode persist_mode,
gboolean is_volatile)
{
AsyncOpData *async_op_data;
@ -508,7 +511,8 @@ _async_op_data_new_ac_auth_add_and_activate (NMManager *self,
async_op_data->ac_auth.active = active_take;
async_op_data->ac_auth.add_and_activate.invocation = invocation_take;
async_op_data->ac_auth.add_and_activate.connection = connection_take;
async_op_data->ac_auth.add_and_activate.persist = persist;
async_op_data->ac_auth.add_and_activate.persist_mode = persist_mode;
async_op_data->ac_auth.add_and_activate.is_volatile = is_volatile;
c_list_link_tail (&NM_MANAGER_GET_PRIVATE (self)->async_op_lst_head, &async_op_data->async_op_lst);
return async_op_data;
}
@ -550,7 +554,8 @@ _async_op_complete_ac_auth_cb (NMActiveConnection *active,
async_op_data->ac_auth.active,
async_op_data->ac_auth.add_and_activate.connection,
async_op_data->ac_auth.add_and_activate.invocation,
async_op_data->ac_auth.add_and_activate.persist,
async_op_data->ac_auth.add_and_activate.persist_mode,
async_op_data->ac_auth.add_and_activate.is_volatile,
success,
error_desc);
g_object_unref (async_op_data->ac_auth.add_and_activate.connection);
@ -831,7 +836,7 @@ _delete_volatile_connection_do (NMManager *self,
_LOGD (LOGD_DEVICE, "volatile connection disconnected. Deleting connection '%s' (%s)",
nm_settings_connection_get_id (connection), nm_settings_connection_get_uuid (connection));
nm_settings_connection_delete (connection, NULL);
nm_settings_connection_delete (connection, FALSE);
}
/* Returns: whether to notify D-Bus of the removal or not */
@ -2140,7 +2145,7 @@ connection_added_cb (NMSettings *settings,
static void
connection_updated_cb (NMSettings *settings,
NMSettingsConnection *sett_conn,
gboolean by_user,
guint update_reason_u,
NMManager *self)
{
connection_changed_on_idle (self, sett_conn);
@ -2660,8 +2665,13 @@ get_existing_connection (NMManager *self,
nm_device_assume_state_reset (device);
added = nm_settings_add_connection (priv->settings, connection, FALSE, &error);
if (!added) {
if (!nm_settings_add_connection (priv->settings,
connection,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY,
NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE
| NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED,
&added,
&error)) {
_LOG2W (LOGD_SETTINGS, device, "assume: failure to save generated connection '%s': %s",
nm_connection_get_id (connection),
error->message);
@ -2669,10 +2679,6 @@ get_existing_connection (NMManager *self,
return NULL;
}
nm_settings_connection_set_flags (added,
NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED |
NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE,
TRUE);
NM_SET_OUT (out_generated, TRUE);
return added;
}
@ -2774,7 +2780,7 @@ recheck_assume_connection (NMManager *self,
if (generated) {
_LOG2D (LOGD_DEVICE, device, "assume: deleting generated connection after assuming failed");
nm_settings_connection_delete (sett_conn, NULL);
nm_settings_connection_delete (sett_conn, FALSE);
} else {
if (nm_device_sys_iface_state_get (device) == NM_DEVICE_SYS_IFACE_STATE_ASSUME)
nm_device_sys_iface_state_set (device, NM_DEVICE_SYS_IFACE_STATE_EXTERNAL);
@ -5315,14 +5321,11 @@ activation_add_done (NMSettings *settings,
NMManager *self;
gs_unref_object NMActiveConnection *active = NULL;
gs_free_error GError *local = NULL;
gpointer persist_ptr;
NMSettingsConnectionPersistMode persist;
gpointer async_op_type_ptr;
AsyncOpType async_op_type;
GVariant *result_floating;
nm_utils_user_data_unpack (user_data, &self, &active, &persist_ptr, &async_op_type_ptr);
persist = GPOINTER_TO_INT (persist_ptr);
nm_utils_user_data_unpack (user_data, &self, &active, &async_op_type_ptr);
async_op_type = GPOINTER_TO_INT (async_op_type_ptr);
if (error)
@ -5330,17 +5333,8 @@ activation_add_done (NMSettings *settings,
nm_active_connection_set_settings_connection (active, new_connection);
if (!_internal_activate_generic (self, active, &local)) {
error = local;
if (!_internal_activate_generic (self, active, &local))
goto fail;
}
nm_settings_connection_update (new_connection,
NULL,
persist,
NM_SETTINGS_CONNECTION_COMMIT_REASON_USER_ACTION | NM_SETTINGS_CONNECTION_COMMIT_REASON_ID_CHANGED,
"add-and-activate",
NULL);
if (async_op_type == ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE) {
result_floating = g_variant_new ("(oo)",
@ -5363,13 +5357,17 @@ activation_add_done (NMSettings *settings,
return;
fail:
nm_assert (error);
if (local) {
nm_assert (!error);
error = local;
} else
nm_assert (error);
nm_active_connection_set_state_fail (active,
NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN,
error->message);
if (new_connection)
nm_settings_connection_delete (new_connection, NULL);
nm_settings_connection_delete (new_connection, FALSE);
g_dbus_method_invocation_return_gerror (context, error);
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE,
NULL,
@ -5385,7 +5383,8 @@ _add_and_activate_auth_done (NMManager *self,
NMActiveConnection *active,
NMConnection *connection,
GDBusMethodInvocation *invocation,
NMSettingsConnectionPersistMode persist,
NMSettingsConnectionPersistMode persist_mode,
gboolean is_volatile,
gboolean success,
const char *error_desc)
{
@ -5413,13 +5412,15 @@ _add_and_activate_auth_done (NMManager *self,
* shutdown. */
nm_settings_add_connection_dbus (priv->settings,
connection,
FALSE,
persist_mode,
( is_volatile
? NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE
: NM_SETTINGS_CONNECTION_INT_FLAGS_NONE),
nm_active_connection_get_subject (active),
invocation,
activation_add_done,
nm_utils_user_data_pack (self,
g_object_ref (active),
GINT_TO_POINTER (persist),
GINT_TO_POINTER (async_op_type)));
}
@ -5445,7 +5446,8 @@ impl_manager_add_and_activate_connection (NMDBusObject *obj,
const char *device_path;
const char *specific_object_path;
gs_free NMConnection **conns = NULL;
NMSettingsConnectionPersistMode persist = NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK;
NMSettingsConnectionPersistMode persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK;
gboolean is_volatile = FALSE;
gboolean bind_dbus_client = FALSE;
AsyncOpType async_op_type;
@ -5474,13 +5476,17 @@ impl_manager_add_and_activate_connection (NMDBusObject *obj,
&& g_variant_is_of_type (option_value, G_VARIANT_TYPE_STRING)) {
s = g_variant_get_string (option_value, NULL);
if (nm_streq (s, "volatile"))
persist = NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_ONLY;
else if (nm_streq (s, "memory"))
persist = NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY;
else if (nm_streq (s, "disk"))
persist = NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK;
else {
is_volatile = FALSE;
persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK;
if (nm_streq (s, "volatile")) {
persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY;
is_volatile = TRUE;
} else if (nm_streq (s, "memory"))
persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY;
else if (nm_streq (s, "disk")) {
/* pass */
} else {
error = g_error_new_literal (NM_MANAGER_ERROR,
NM_MANAGER_ERROR_INVALID_ARGUMENTS,
"Option \"persist\" must be one of \"volatile\", \"memory\" or \"disk\"");
@ -5599,7 +5605,8 @@ impl_manager_add_and_activate_connection (NMDBusObject *obj,
active,
invocation,
incompl_conn,
persist));
persist_mode,
is_volatile));
/* we passed the pointers on to _async_op_data_new_ac_auth_add_and_activate() */
g_steal_pointer (&incompl_conn);
@ -6549,8 +6556,9 @@ nm_manager_start (NMManager *self, GError **error)
gs_free NMSettingsConnection **connections = NULL;
guint i;
if (!nm_settings_start (priv->settings, error))
return FALSE;
nm_device_factory_manager_load_factories (_register_device_factory, self);
nm_device_factory_manager_for_each_factory (start_factory, NULL);
/* Set initial radio enabled/disabled state */
for (i = 0; i < RFKILL_TYPE_MAX; i++) {
@ -6573,16 +6581,15 @@ nm_manager_start (NMManager *self, GError **error)
manager_update_radio_enabled (self, rstate, enabled);
}
/* Log overall networking status - enabled/disabled */
_LOGI (LOGD_CORE, "Networking is %s by state file",
priv->net_enabled ? "enabled" : "disabled");
system_unmanaged_devices_changed_cb (priv->settings, NULL, self);
hostname_changed_cb (priv->hostname_manager, NULL, self);
/* Start device factories */
nm_device_factory_manager_load_factories (_register_device_factory, self);
nm_device_factory_manager_for_each_factory (start_factory, NULL);
if (!nm_settings_start (priv->settings, error))
return FALSE;
nm_platform_process_events (priv->platform);
@ -6596,10 +6603,11 @@ nm_manager_start (NMManager *self, GError **error)
/* Load VPN plugins */
priv->vpn_manager = g_object_ref (nm_vpn_manager_get ());
/* Connections added before the manager is started do not emit
* connection-added signals thus devices have to be created manually.
*/
_LOGD (LOGD_CORE, "creating virtual devices...");
g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED,
G_CALLBACK (connection_added_cb), self);
g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED,
G_CALLBACK (connection_updated_cb), self);
connections = nm_settings_get_connections_clone (priv->settings, NULL,
NULL, NULL,
nm_settings_connection_cmp_autoconnect_priority_p_with_data, NULL);
@ -7334,10 +7342,6 @@ constructed (GObject *object)
G_CALLBACK (settings_startup_complete_changed), self);
g_signal_connect (priv->settings, "notify::" NM_SETTINGS_UNMANAGED_SPECS,
G_CALLBACK (system_unmanaged_devices_changed_cb), self);
g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED,
G_CALLBACK (connection_added_cb), self);
g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED,
G_CALLBACK (connection_updated_cb), self);
g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_FLAGS_CHANGED, G_CALLBACK (connection_flags_changed), self);
priv->hostname_manager = g_object_ref (nm_hostname_manager_get ());

View File

@ -1846,8 +1846,7 @@ device_state_changed (NMDevice *device,
}
}
/* FIXME(copy-on-write-connection): avoid modifying NMConnection instances and share them via copy-on-write. */
nm_connection_clear_secrets (nm_settings_connection_get_connection (sett_conn));
nm_settings_connection_clear_secrets (sett_conn, FALSE, FALSE);
}
break;
case NM_DEVICE_STATE_ACTIVATED:
@ -1858,9 +1857,7 @@ device_state_changed (NMDevice *device,
/* And clear secrets so they will always be requested from the
* settings service when the next connection is made.
*/
/* FIXME(copy-on-write-connection): avoid modifying NMConnection instances and share them via copy-on-write. */
nm_connection_clear_secrets (nm_settings_connection_get_connection (sett_conn));
nm_settings_connection_clear_secrets (sett_conn, FALSE, FALSE);
}
/* Add device's new IPv4 and IPv6 configs to DNS */
@ -2399,13 +2396,14 @@ dns_config_changed (NMDnsManager *dns_manager, gpointer user_data)
static void
connection_updated (NMSettings *settings,
NMSettingsConnection *connection,
gboolean by_user,
guint update_reason_u,
gpointer user_data)
{
NMPolicyPrivate *priv = user_data;
NMPolicy *self = _PRIV_TO_SELF (priv);
NMSettingsConnectionUpdateReason update_reason = update_reason_u;
if (by_user) {
if (NM_FLAGS_HAS (update_reason, NM_SETTINGS_CONNECTION_UPDATE_REASON_REAPPLY_PARTIAL)) {
const CList *tmp_lst;
NMDevice *device;
@ -2414,9 +2412,6 @@ connection_updated (NMSettings *settings,
if (nm_device_get_settings_connection (device) == connection)
nm_device_reapply_settings_immediately (device);
}
/* Reset auto retries back to default since connection was updated */
nm_settings_connection_autoconnect_retries_reset (connection);
}
schedule_activate_all (self);

File diff suppressed because it is too large Load Diff

View File

@ -21,11 +21,78 @@
#ifndef __NETWORKMANAGER_SETTINGS_CONNECTION_H__
#define __NETWORKMANAGER_SETTINGS_CONNECTION_H__
#include <net/ethernet.h>
#include "nm-dbus-object.h"
#include "nm-connection.h"
#include "nm-settings-storage.h"
/*****************************************************************************/
typedef enum {
NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE = 0,
/* with persist-mode != NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY, and
* update tries to update the profile on disk (which can always fail).
* In some cases we want to ignore such failure and proceed. For example,
* when we receive secrets from a secret-agent, we want to update the connection
* at all cost and ignore failures to write them to disk. */
NM_SETTINGS_CONNECTION_UPDATE_REASON_IGNORE_PERSIST_FAILURE = (1u << 0),
/* When updating the profile, force renaming the file on disk. That matters
* only for keyfile plugin. Keyfile prefers a filename based on connection.id.
* When the connection.id changes we might want to rename the file on disk
* (that is, don't overwrite the existing file, but delete it and write it
* with the new name).
* This flag forces such rename. */
NM_SETTINGS_CONNECTION_UPDATE_REASON_FORCE_RENAME = (1u << 1),
/* Usually, changing a profile that is currently active does not immediately
* reapply the changes. The exception are connection.zone and connection.metered
* properties. When this flag is set, then these two properties are reapplied
* right away. */
NM_SETTINGS_CONNECTION_UPDATE_REASON_REAPPLY_PARTIAL = (1u << 2),
NM_SETTINGS_CONNECTION_UPDATE_REASON_CLEAR_SYSTEM_SECRETS = (1u << 3),
NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS = (1u << 4),
NM_SETTINGS_CONNECTION_UPDATE_REASON_CLEAR_AGENT_SECRETS = (1u << 5),
NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS = (1u << 6),
/* if a profile was greated as default-wired connection for a device, then
* when the user modifies it via D-Bus, the profile should become persisted
* to disk and it the purpose why the profile was created should be forgotten. */
NM_SETTINGS_CONNECTION_UPDATE_REASON_CLEAR_DEFAULT_WIRED = (1u << 7),
} NMSettingsConnectionUpdateReason;
typedef enum {
/* if the profile is in-memory, update it in-memory and keep it.
* if the profile is on-disk, update it on-disk, and keep it. */
NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP,
/* persist to disk. If the profile is currenly in-memory, remove
* it from /run. */
NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK,
/* persist to /run (in-memory). If the profile is currently on disk,
* delete it from disk. */
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY,
/* persist to /run (in-memory). If the profile is currently on disk,
* forget about it, but don't delete it from disk. */
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED,
/* this only updates the connection in-memory. Note that "in-memory" above
* means to write to keyfile in /run. This really means to not notify the
* settings plugin about the change. */
NM_SETTINGS_CONNECTION_PERSIST_MODE_NO_PERSIST,
} NMSettingsConnectionPersistMode;
/*****************************************************************************/
#define NM_TYPE_SETTINGS_CONNECTION (nm_settings_connection_get_type ())
#define NM_SETTINGS_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_CONNECTION, NMSettingsConnection))
#define NM_SETTINGS_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTINGS_CONNECTION, NMSettingsConnectionClass))
@ -33,7 +100,6 @@
#define NM_IS_SETTINGS_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTINGS_CONNECTION))
#define NM_SETTINGS_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTINGS_CONNECTION, NMSettingsConnectionClass))
#define NM_SETTINGS_CONNECTION_REMOVED "removed"
#define NM_SETTINGS_CONNECTION_GET_SECRETS "get-secrets"
#define NM_SETTINGS_CONNECTION_CANCEL_SECRETS "cancel-secrets"
#define NM_SETTINGS_CONNECTION_UPDATED_INTERNAL "updated-internal"
@ -44,9 +110,6 @@
#define NM_SETTINGS_CONNECTION_FLAGS "flags"
#define NM_SETTINGS_CONNECTION_FILENAME "filename"
/* Internal properties */
#define NM_SETTINGS_CONNECTION_READY "ready"
/**
* NMSettingsConnectionIntFlags:
* @NM_SETTINGS_CONNECTION_INT_FLAGS_NONE: no flag set
@ -61,38 +124,37 @@
* currently active but cleanup on disconnect.
* See also #NM_SETTINGS_CONNECTION_FLAG_VOLATILE.
* @NM_SETTINGS_CONNECTION_INT_FLAGS_VISIBLE: The connection is visible
* @NM_SETTINGS_CONNECTION_INT_FLAGS_EXPORTED_MASK: the entire enum is
* @_NM_SETTINGS_CONNECTION_INT_FLAGS_EXPORTED_MASK: the entire enum is
* internal, however, parts of it is public API as #NMSettingsConnectionFlags.
* This mask, are the public flags.
* @NM_SETTINGS_CONNECTION_INT_FLAGS_ALL: special mask, for all known flags
* @_NM_SETTINGS_CONNECTION_INT_FLAGS_ALL: special mask, for all known flags
*
* #NMSettingsConnection flags.
**/
typedef enum {
typedef enum _NMSettingsConnectionIntFlags {
NM_SETTINGS_CONNECTION_INT_FLAGS_NONE = 0,
NM_SETTINGS_CONNECTION_INT_FLAGS_UNSAVED = NM_SETTINGS_CONNECTION_FLAG_UNSAVED,
NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED = NM_SETTINGS_CONNECTION_FLAG_NM_GENERATED,
NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE = NM_SETTINGS_CONNECTION_FLAG_VOLATILE,
NM_SETTINGS_CONNECTION_INT_FLAGS_VISIBLE = (1LL << 3),
NM_SETTINGS_CONNECTION_INT_FLAGS_VISIBLE = 0x08,
__NM_SETTINGS_CONNECTION_INT_FLAGS_LAST,
_NM_SETTINGS_CONNECTION_INT_FLAGS_LAST,
NM_SETTINGS_CONNECTION_INT_FLAGS_EXPORTED_MASK = 0
_NM_SETTINGS_CONNECTION_INT_FLAGS_EXPORTED_MASK = 0
| NM_SETTINGS_CONNECTION_INT_FLAGS_UNSAVED
| NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED
| NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE
| 0,
NM_SETTINGS_CONNECTION_INT_FLAGS_ALL = ((__NM_SETTINGS_CONNECTION_INT_FLAGS_LAST - 1) << 1) - 1,
} NMSettingsConnectionIntFlags;
_NM_SETTINGS_CONNECTION_INT_FLAGS_PERSISTENT_MASK = 0
| NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED
| NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE
| 0,
typedef enum {
NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE = 0,
NM_SETTINGS_CONNECTION_COMMIT_REASON_USER_ACTION = (1LL << 0),
NM_SETTINGS_CONNECTION_COMMIT_REASON_ID_CHANGED = (1LL << 1),
} NMSettingsConnectionCommitReason;
_NM_SETTINGS_CONNECTION_INT_FLAGS_ALL = ((_NM_SETTINGS_CONNECTION_INT_FLAGS_LAST - 1) << 1) - 1,
} NMSettingsConnectionIntFlags;
typedef enum {
NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE = 0,
@ -106,7 +168,6 @@ typedef enum {
| NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS),
} NMSettingsAutoconnectBlockedReason;
struct _NMSettingsConnectionCallId;
typedef struct _NMSettingsConnectionCallId NMSettingsConnectionCallId;
typedef struct _NMSettingsConnectionClass NMSettingsConnectionClass;
@ -115,62 +176,48 @@ struct _NMSettingsConnectionPrivate;
struct _NMSettingsConnection {
NMDBusObject parent;
struct _NMSettingsConnectionPrivate *_priv;
CList _connections_lst;
};
struct _NMSettingsConnectionClass {
NMDBusObjectClass parent;
gboolean (*commit_changes) (NMSettingsConnection *self,
NMConnection *new_connection,
NMSettingsConnectionCommitReason commit_reason,
NMConnection **out_reread_connection,
char **out_logmsg_change,
GError **error);
gboolean (*delete) (NMSettingsConnection *self,
GError **error);
struct _NMSettingsConnectionPrivate *_priv;
};
GType nm_settings_connection_get_type (void);
NMSettingsConnection *nm_settings_connection_new (void);
NMConnection *nm_settings_connection_get_connection (NMSettingsConnection *self);
void _nm_settings_connection_set_connection (NMSettingsConnection *self,
NMConnection *new_connection,
NMConnection **out_old_connection,
NMSettingsConnectionUpdateReason update_reason);
NMSettingsStorage *nm_settings_connection_get_storage (NMSettingsConnection *self);
void _nm_settings_connection_set_storage (NMSettingsConnection *self,
NMSettingsStorage *storage);
gboolean nm_settings_connection_still_valid (NMSettingsConnection *self);
const char *nm_settings_connection_get_filename (NMSettingsConnection *self);
guint64 nm_settings_connection_get_last_secret_agent_version_id (NMSettingsConnection *self);
gboolean nm_settings_connection_has_unmodified_applied_connection (NMSettingsConnection *self,
NMConnection *applied_connection,
NMSettingCompareFlags compare_flage);
typedef enum {
NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP,
/* like KEEP, but always clears the UNSAVED flag */
NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP_SAVED,
NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK,
/* unsaved, only sets the unsaved flag, but it doesn't touch
* the NM_GENERATED nor VOLATILE flag. */
NM_SETTINGS_CONNECTION_PERSIST_MODE_UNSAVED,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY,
NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_DETACHED,
NM_SETTINGS_CONNECTION_PERSIST_MODE_VOLATILE_ONLY,
} NMSettingsConnectionPersistMode;
gboolean nm_settings_connection_update (NMSettingsConnection *self,
NMConnection *new_connection,
NMSettingsConnectionPersistMode persist_mode,
NMSettingsConnectionCommitReason commit_reason,
const char *log_diff_name,
GError **error);
gboolean nm_settings_connection_delete (NMSettingsConnection *self,
gboolean nm_settings_connection_update (NMSettingsConnection *self,
NMConnection *new_connection,
NMSettingsConnectionPersistMode persist_mode,
NMSettingsConnectionIntFlags sett_flags,
NMSettingsConnectionIntFlags sett_mask,
NMSettingsConnectionUpdateReason update_reason,
const char *log_context_name,
GError **error);
void nm_settings_connection_delete (NMSettingsConnection *self,
gboolean allow_add_to_no_auto_default);
typedef void (*NMSettingsConnectionSecretsFunc) (NMSettingsConnection *self,
NMSettingsConnectionCallId *call_id,
const char *agent_username,
@ -196,21 +243,44 @@ NMSettingsConnectionCallId *nm_settings_connection_get_secrets (NMSettingsConnec
void nm_settings_connection_cancel_secrets (NMSettingsConnection *self,
NMSettingsConnectionCallId *call_id);
void nm_settings_connection_recheck_visibility (NMSettingsConnection *self);
void nm_settings_connection_clear_secrets (NMSettingsConnection *self,
gboolean clear_cached_system_secrets,
gboolean persist);
gboolean nm_settings_connection_check_visibility (NMSettingsConnection *self,
NMSessionMonitor *session_monitor);
gboolean nm_settings_connection_check_permission (NMSettingsConnection *self,
const char *permission);
void nm_settings_connection_added (NMSettingsConnection *self);
/*****************************************************************************/
void nm_settings_connection_signal_remove (NMSettingsConnection *self);
NMDevice *nm_settings_connection_default_wired_get_device (NMSettingsConnection *self);
void nm_settings_connection_default_wired_set_device (NMSettingsConnection *self,
NMDevice *device);
gboolean nm_settings_connection_get_unsaved (NMSettingsConnection *self);
/*****************************************************************************/
NMSettingsConnectionIntFlags nm_settings_connection_get_flags (NMSettingsConnection *self);
NMSettingsConnectionIntFlags nm_settings_connection_set_flags (NMSettingsConnection *self, NMSettingsConnectionIntFlags flags, gboolean set);
static inline gboolean
nm_settings_connection_get_unsaved (NMSettingsConnection *self)
{
return NM_FLAGS_HAS (nm_settings_connection_get_flags (self), NM_SETTINGS_CONNECTION_INT_FLAGS_UNSAVED);
}
NMSettingsConnectionIntFlags nm_settings_connection_set_flags_full (NMSettingsConnection *self, NMSettingsConnectionIntFlags mask, NMSettingsConnectionIntFlags value);
static inline NMSettingsConnectionIntFlags
nm_settings_connection_set_flags (NMSettingsConnection *self, NMSettingsConnectionIntFlags flags, gboolean set)
{
return nm_settings_connection_set_flags_full (self,
flags,
set ? flags : NM_SETTINGS_CONNECTION_INT_FLAGS_NONE);
}
/*****************************************************************************/
int nm_settings_connection_cmp_timestamp (NMSettingsConnection *ac, NMSettingsConnection *ab);
int nm_settings_connection_cmp_timestamp_p_with_data (gconstpointer pa, gconstpointer pb, gpointer user_data);
int nm_settings_connection_cmp_autoconnect_priority (NMSettingsConnection *a, NMSettingsConnection *b);
@ -218,9 +288,9 @@ int nm_settings_connection_cmp_autoconnect_priority_p_with_data (gconstpointer p
struct _NMKeyFileDB;
void nm_settings_connection_register_kf_dbs (NMSettingsConnection *self,
struct _NMKeyFileDB *kf_db_timestamps,
struct _NMKeyFileDB *kf_db_seen_bssids);
void _nm_settings_connection_register_kf_dbs (NMSettingsConnection *self,
struct _NMKeyFileDB *kf_db_timestamps,
struct _NMKeyFileDB *kf_db_seen_bssids);
gboolean nm_settings_connection_get_timestamp (NMSettingsConnection *self,
guint64 *out_timestamp);
@ -259,14 +329,6 @@ nm_settings_connection_autoconnect_blocked_reason_set (NMSettingsConnection *sel
gboolean nm_settings_connection_autoconnect_is_blocked (NMSettingsConnection *self);
gboolean nm_settings_connection_get_ready (NMSettingsConnection *self);
void nm_settings_connection_set_ready (NMSettingsConnection *self,
gboolean ready);
void nm_settings_connection_set_filename (NMSettingsConnection *self,
const char *filename);
const char *nm_settings_connection_get_filename (NMSettingsConnection *self);
const char *nm_settings_connection_get_id (NMSettingsConnection *connection);
const char *nm_settings_connection_get_uuid (NMSettingsConnection *connection);
const char *nm_settings_connection_get_connection_type (NMSettingsConnection *connection);
@ -276,4 +338,14 @@ const char *nm_settings_connection_get_connection_type (NMSettingsConnection *co
NMConnection **nm_settings_connections_array_to_connections (NMSettingsConnection *const*connections,
gssize n_connections);
/*****************************************************************************/
void _nm_settings_connection_emit_dbus_signal_updated (NMSettingsConnection *self);
void _nm_settings_connection_emit_dbus_signal_removed (NMSettingsConnection *self);
void _nm_settings_connection_emit_signal_updated_internal (NMSettingsConnection *self,
NMSettingsConnectionUpdateReason update_reason);
void _nm_settings_connection_cleanup_after_remove (NMSettingsConnection *self);
#endif /* __NETWORKMANAGER_SETTINGS_CONNECTION_H__ */

View File

@ -22,12 +22,14 @@
#include "nm-settings-plugin.h"
#include "nm-utils.h"
#include "nm-core-internal.h"
#include "nm-settings-connection.h"
/*****************************************************************************/
enum {
CONNECTION_ADDED,
UNMANAGED_SPECS_CHANGED,
UNRECOGNIZED_SPECS_CHANGED,
@ -40,105 +42,202 @@ G_DEFINE_TYPE (NMSettingsPlugin, nm_settings_plugin, G_TYPE_OBJECT)
/*****************************************************************************/
GSList *
nm_settings_plugin_get_connections (NMSettingsPlugin *self)
{
g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), NULL);
if (NM_SETTINGS_PLUGIN_GET_CLASS (self)->get_connections)
return NM_SETTINGS_PLUGIN_GET_CLASS (self)->get_connections (self);
return NULL;
}
gboolean
nm_settings_plugin_load_connection (NMSettingsPlugin *self,
const char *filename)
{
g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), FALSE);
if (NM_SETTINGS_PLUGIN_GET_CLASS (self)->load_connection)
return NM_SETTINGS_PLUGIN_GET_CLASS (self)->load_connection (self, filename);
return FALSE;
}
void
nm_settings_plugin_reload_connections (NMSettingsPlugin *self)
{
g_return_if_fail (NM_IS_SETTINGS_PLUGIN (self));
if (NM_SETTINGS_PLUGIN_GET_CLASS (self)->reload_connections)
NM_SETTINGS_PLUGIN_GET_CLASS (self)->reload_connections (self);
}
GSList *
nm_settings_plugin_get_unmanaged_specs (NMSettingsPlugin *self)
{
NMSettingsPluginClass *klass;
g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), NULL);
if (NM_SETTINGS_PLUGIN_GET_CLASS (self)->get_unmanaged_specs)
return NM_SETTINGS_PLUGIN_GET_CLASS (self)->get_unmanaged_specs (self);
return NULL;
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
if (!klass->get_unmanaged_specs)
return NULL;
return klass->get_unmanaged_specs (self);
}
GSList *
nm_settings_plugin_get_unrecognized_specs (NMSettingsPlugin *self)
{
NMSettingsPluginClass *klass;
g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), NULL);
if (NM_SETTINGS_PLUGIN_GET_CLASS (self)->get_unrecognized_specs)
return NM_SETTINGS_PLUGIN_GET_CLASS (self)->get_unrecognized_specs (self);
return NULL;
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
if (!klass->get_unrecognized_specs)
return NULL;
return klass->get_unrecognized_specs (self);
}
/**
* nm_settings_plugin_add_connection:
* @self: the #NMSettingsPlugin
* @connection: the source connection to create a plugin-specific
* #NMSettingsConnection from
* @save_to_disk: %TRUE to save the connection to disk immediately, %FALSE to
* not save to disk
* @error: on return, a location to store any errors that may occur
*
* Creates a new #NMSettingsConnection for the given source @connection. If the
* plugin cannot handle the given connection type, it should return %NULL and
* set @error. The plugin owns the returned object and the caller must reference
* the object if it wishes to continue using it.
*
* Returns: the new #NMSettingsConnection or %NULL
*/
NMSettingsConnection *
void
nm_settings_plugin_reload_connections (NMSettingsPlugin *self,
NMSettingsPluginConnectionLoadCallback callback,
gpointer user_data)
{
NMSettingsPluginClass *klass;
g_return_if_fail (NM_IS_SETTINGS_PLUGIN (self));
g_return_if_fail (callback);
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
if (klass->reload_connections)
klass->reload_connections (self, callback, user_data);
}
NMSettingsPluginConnectionLoadEntry *
nm_settings_plugin_create_connection_load_entries (const char *const*filenames,
gsize *out_len)
{
NMSettingsPluginConnectionLoadEntry *entries;
gsize len;
gsize i;
len = NM_PTRARRAY_LEN (filenames);
if (len == 0) {
*out_len = 0;
return NULL;
}
entries = g_new (NMSettingsPluginConnectionLoadEntry, len);
for (i = 0; i < len; i++) {
entries[i] = (NMSettingsPluginConnectionLoadEntry) {
.filename = filenames[i],
.error = NULL,
.handled = FALSE,
};
}
*out_len = len;
return entries;
}
void
nm_settings_plugin_load_connections (NMSettingsPlugin *self,
NMSettingsPluginConnectionLoadEntry *entries,
gsize n_entries,
NMSettingsPluginConnectionLoadCallback callback,
gpointer user_data)
{
NMSettingsPluginClass *klass;
g_return_if_fail (NM_IS_SETTINGS_PLUGIN (self));
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
if (klass->load_connections)
klass->load_connections (self, entries, n_entries, callback, user_data);
}
void
nm_settings_plugin_load_connections_done (NMSettingsPlugin *self)
{
NMSettingsPluginClass *klass;
g_return_if_fail (NM_IS_SETTINGS_PLUGIN (self));
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
if (klass->load_connections_done)
klass->load_connections_done (self);
}
gboolean
nm_settings_plugin_add_connection (NMSettingsPlugin *self,
NMConnection *connection,
gboolean save_to_disk,
NMSettingsStorage **out_storage,
NMConnection **out_connection,
GError **error)
{
NMSettingsPluginClass *klass;
g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), NULL);
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), FALSE);
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
#if NM_MORE_ASSERTS > 5
nm_assert (nm_connection_verify (connection, NULL));
#endif
NM_SET_OUT (out_storage, NULL);
NM_SET_OUT (out_connection, NULL);
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
if (!klass->add_connection) {
g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_NOT_SUPPORTED,
"Plugin does not support adding connections");
return NULL;
"settings plugin does not support adding connections");
return FALSE;
}
return klass->add_connection (self,
connection,
out_storage,
out_connection,
error);
}
gboolean
nm_settings_plugin_update_connection (NMSettingsPlugin *self,
NMSettingsStorage *storage,
NMConnection *connection,
NMSettingsStorage **out_storage,
NMConnection **out_connection,
GError **error)
{
NMSettingsPluginClass *klass = NULL;
g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), FALSE);
g_return_val_if_fail (NM_IS_SETTINGS_STORAGE (storage), FALSE);
g_return_val_if_fail (nm_settings_storage_get_plugin (storage) == self, FALSE);
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
#if NM_MORE_ASSERTS > 5
nm_assert (nm_connection_verify (connection, NULL));
nm_assert (nm_streq (nm_connection_get_uuid (connection), nm_settings_storage_get_uuid (storage)));
#endif
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
NM_SET_OUT (out_storage, NULL);
NM_SET_OUT (out_connection, NULL);
if (!klass->update_connection) {
g_set_error (error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_NOT_SUPPORTED,
"settings plugin does not support modifying connections");
return FALSE;
}
return klass->update_connection (self,
storage,
connection,
out_storage,
out_connection,
error);
}
gboolean
nm_settings_plugin_delete_connection (NMSettingsPlugin *self,
NMSettingsStorage *storage,
GError **error)
{
NMSettingsPluginClass *klass = NULL;
g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), FALSE);
g_return_val_if_fail (NM_IS_SETTINGS_STORAGE (storage), FALSE);
g_return_val_if_fail (nm_settings_storage_get_plugin (storage) == self, FALSE);
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
if (!klass->delete_connection) {
g_set_error (error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_NOT_SUPPORTED,
"settings plugin does not support deleting connections");
return FALSE;
}
return klass->add_connection (self, connection, save_to_disk, error);
return klass->delete_connection (self,
storage,
error);
}
/*****************************************************************************/
void
_nm_settings_plugin_emit_signal_connection_added (NMSettingsPlugin *self,
NMSettingsConnection *sett_conn)
{
nm_assert (NM_IS_SETTINGS_PLUGIN (self));
nm_assert (NM_IS_SETTINGS_CONNECTION (sett_conn));
g_signal_emit (self, signals[CONNECTION_ADDED], 0, sett_conn);
}
void
_nm_settings_plugin_emit_signal_unmanaged_specs_changed (NMSettingsPlugin *self)
{
@ -167,15 +266,6 @@ nm_settings_plugin_class_init (NMSettingsPluginClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
signals[CONNECTION_ADDED] =
g_signal_new (NM_SETTINGS_PLUGIN_CONNECTION_ADDED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
NM_TYPE_SETTINGS_CONNECTION);
signals[UNMANAGED_SPECS_CHANGED] =
g_signal_new (NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED,
G_OBJECT_CLASS_TYPE (object_class),

View File

@ -23,6 +23,21 @@
#include "nm-connection.h"
#include "nm-settings-storage.h"
typedef struct _NMSettingsPlugin NMSettingsPlugin;
typedef void (*NMSettingsPluginConnectionLoadCallback) (NMSettingsPlugin *self,
NMSettingsStorage *storage,
NMConnection *connection,
gpointer user_data);
typedef struct {
const char *filename;
GError *error;
bool handled:1;
} NMSettingsPluginConnectionLoadEntry;
#define NM_TYPE_SETTINGS_PLUGIN (nm_settings_plugin_get_type ())
#define NM_SETTINGS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_PLUGIN, NMSettingsPlugin))
#define NM_SETTINGS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTINGS_PLUGIN, NMSettingsPluginClass))
@ -32,32 +47,14 @@
#define NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED "unmanaged-specs-changed"
#define NM_SETTINGS_PLUGIN_UNRECOGNIZED_SPECS_CHANGED "unrecognized-specs-changed"
#define NM_SETTINGS_PLUGIN_CONNECTION_ADDED "connection-added"
typedef struct {
struct _NMSettingsPlugin {
GObject parent;
} NMSettingsPlugin;
};
typedef struct {
GObjectClass parent;
/* Returns a GSList of NMSettingsConnection objects that represent
* connections the plugin knows about. The returned list is freed by the
* system settings service.
*/
GSList * (*get_connections) (NMSettingsPlugin *plugin);
/* Requests that the plugin load/reload a single connection, if it
* recognizes the filename. Returns success or failure.
*/
gboolean (*load_connection) (NMSettingsPlugin *plugin,
const char *filename);
/* Requests that the plugin reload all connection files from disk,
* and emit signals reflecting new, changed, and removed connections.
*/
void (*reload_connections) (NMSettingsPlugin *plugin);
/*
* Return a string list of specifications of devices which NetworkManager
* should not manage. Returned list will be freed by the system settings
@ -67,7 +64,7 @@ typedef struct {
* Each string in the list must be in one of the formats recognized by
* nm_device_spec_match_list().
*/
GSList * (*get_unmanaged_specs) (NMSettingsPlugin *plugin);
GSList * (*get_unmanaged_specs) (NMSettingsPlugin *self);
/*
* Return a string list of specifications of devices for which at least
@ -79,49 +76,131 @@ typedef struct {
* Each string in the list must be in one of the formats recognized by
* nm_device_spec_match_list().
*/
GSList * (*get_unrecognized_specs) (NMSettingsPlugin *plugin);
GSList * (*get_unrecognized_specs) (NMSettingsPlugin *self);
/*
* Initialize the plugin-specific connection and return a new
* NMSettingsConnection subclass that contains the same settings as the
* original connection. The connection should only be saved to backing
* storage if @save_to_disk is TRUE. The returned object is owned by the
* plugin and must be referenced by the owner if necessary.
/* Requests that the plugin load/reload a set of filenames.
*/
NMSettingsConnection * (*add_connection) (NMSettingsPlugin *plugin,
NMConnection *connection,
gboolean save_to_disk,
GError **error);
void (*load_connections) (NMSettingsPlugin *self,
NMSettingsPluginConnectionLoadEntry *entries,
gsize n_entries,
NMSettingsPluginConnectionLoadCallback callback,
gpointer user_data);
/* Requests that the plugin reload all connection files from disk,
* and emit signals reflecting new, changed, and removed connections.
*/
void (*reload_connections) (NMSettingsPlugin *self,
NMSettingsPluginConnectionLoadCallback callback,
gpointer user_data);
void (*load_connections_done) (NMSettingsPlugin *self);
gboolean (*add_connection) (NMSettingsPlugin *self,
NMConnection *connection,
NMSettingsStorage **out_storage,
NMConnection **out_connection,
GError **error);
gboolean (*update_connection) (NMSettingsPlugin *self,
NMSettingsStorage *storage,
NMConnection *connection,
NMSettingsStorage **out_storage,
NMConnection **out_connection,
GError **error);
gboolean (*delete_connection) (NMSettingsPlugin *self,
NMSettingsStorage *storage,
GError **error);
const char *plugin_name;
} NMSettingsPluginClass;
/*****************************************************************************/
GType nm_settings_plugin_get_type (void);
/*****************************************************************************/
#define NM_SETTINGS_STORAGE_PRINT_FMT \
NM_HASH_OBFUSCATE_PTR_FMT"/%s"
#define NM_SETTINGS_STORAGE_PRINT_ARG(storage) \
NM_HASH_OBFUSCATE_PTR (storage), \
nm_settings_plugin_get_plugin_name (nm_settings_storage_get_plugin (storage))
static inline const char *
nm_settings_plugin_get_plugin_name (NMSettingsPlugin *self)
{
NMSettingsPluginClass *klass;
nm_assert (NM_SETTINGS_PLUGIN (self));
klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
nm_assert (klass && klass->plugin_name && strlen (klass->plugin_name) > 0);
return klass->plugin_name;
}
/*****************************************************************************/
GSList *nm_settings_plugin_get_unmanaged_specs (NMSettingsPlugin *self);
GSList *nm_settings_plugin_get_unrecognized_specs (NMSettingsPlugin *self);
void nm_settings_plugin_reload_connections (NMSettingsPlugin *self,
NMSettingsPluginConnectionLoadCallback callback,
gpointer user_data);
NMSettingsPluginConnectionLoadEntry *nm_settings_plugin_create_connection_load_entries (const char *const*filenames,
gsize *out_len);
void nm_settings_plugin_load_connections (NMSettingsPlugin *self,
NMSettingsPluginConnectionLoadEntry *entries,
gsize n_entries,
NMSettingsPluginConnectionLoadCallback callback,
gpointer user_data);
void nm_settings_plugin_load_connections_done (NMSettingsPlugin *self);
gboolean nm_settings_plugin_add_connection (NMSettingsPlugin *self,
NMConnection *connection,
NMSettingsStorage **out_storage,
NMConnection **out_connection,
GError **error);
gboolean nm_settings_plugin_update_connection (NMSettingsPlugin *self,
NMSettingsStorage *storage,
NMConnection *connection,
NMSettingsStorage **out_storage,
NMConnection **out_connection,
GError **error);
gboolean nm_settings_plugin_delete_connection (NMSettingsPlugin *self,
NMSettingsStorage *storage,
GError **error);
/*****************************************************************************/
typedef NMSettingsPlugin *(*NMSettingsPluginFactoryFunc) (void);
/* Plugin's factory function that returns a #NMSettingsPlugin */
NMSettingsPlugin *nm_settings_plugin_factory (void);
GSList *nm_settings_plugin_get_connections (NMSettingsPlugin *plugin);
/*****************************************************************************
* Internal API
*****************************************************************************/
gboolean nm_settings_plugin_load_connection (NMSettingsPlugin *plugin,
const char *filename);
void nm_settings_plugin_reload_connections (NMSettingsPlugin *plugin);
void _nm_settings_plugin_emit_signal_unmanaged_specs_changed (NMSettingsPlugin *self);
GSList *nm_settings_plugin_get_unmanaged_specs (NMSettingsPlugin *plugin);
GSList *nm_settings_plugin_get_unrecognized_specs (NMSettingsPlugin *plugin);
void _nm_settings_plugin_emit_signal_unrecognized_specs_changed (NMSettingsPlugin *self);
NMSettingsConnection *nm_settings_plugin_add_connection (NMSettingsPlugin *plugin,
NMConnection *connection,
gboolean save_to_disk,
GError **error);
/*****************************************************************************/
/* internal API */
/* forward declare this function from NMSettings. It's used by the ifcfg-rh plugin,
* but that shouldn't include all "nm-settings.h" header. */
NMSettings *nm_settings_get (void);
void _nm_settings_plugin_emit_signal_connection_added (NMSettingsPlugin *plugin,
NMSettingsConnection *sett_conn);
void _nm_settings_plugin_emit_signal_unmanaged_specs_changed (NMSettingsPlugin *plugin);
void _nm_settings_plugin_emit_signal_unrecognized_specs_changed (NMSettingsPlugin *plugin);
const char *nm_settings_get_dbus_path_for_uuid (NMSettings *self,
const char *uuid);
#endif /* __NM_SETTINGS_PLUGIN_H__ */

View File

@ -0,0 +1,197 @@
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2018 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-settings-storage.h"
#include "nm-utils.h"
#include "nm-settings-plugin.h"
#include "settings/plugins/keyfile/nms-keyfile-storage.h"
/*****************************************************************************/
int
nm_settings_storage_cmp (NMSettingsStorage *a,
NMSettingsStorage *b,
const GSList *plugin_list)
{
NMSettingsStorageClass *klass;
NMSettingsPlugin *plugin_a;
NMSettingsPlugin *plugin_b;
/* Sort by priority.
*
* If a > b (by priority), we return a positive number (as one
* would expect by a cmp() function). */
nm_assert (NM_IS_SETTINGS_STORAGE (a));
nm_assert (NM_IS_SETTINGS_STORAGE (b));
nm_assert (a != b);
nm_assert (nm_streq (nm_settings_storage_get_uuid (a), nm_settings_storage_get_uuid (b)));
/* in-memory has always higher priority */
NM_CMP_DIRECT (nm_settings_storage_is_keyfile_run (a),
nm_settings_storage_is_keyfile_run (b));
plugin_a = nm_settings_storage_get_plugin (a);
plugin_b = nm_settings_storage_get_plugin (b);
if (plugin_a != plugin_b) {
int idx_a = g_slist_index ((GSList *) plugin_list, plugin_a);
int idx_b = g_slist_index ((GSList *) plugin_list, plugin_b);
/* the plugins must be found in the list. */
nm_assert (idx_a >= 0);
nm_assert (idx_b >= 0);
nm_assert (idx_a != idx_b);
/* plugins that appear first in @plugin_list have higher priority.
* That means: smaller index -> higher priority. Reverse sort. */
NM_CMP_DIRECT (idx_b, idx_a);
/* undecided. We really don't expect unknown plugins here. */
return 0;
}
klass = NM_SETTINGS_STORAGE_GET_CLASS (a);
if (klass != NM_SETTINGS_STORAGE_GET_CLASS (b)) {
/* one plugin must return storages of the same type. Otherwise, it's
* unclear how cmp_fcn() should compare them. */
nm_assert_not_reached ();
return 0;
}
if (klass->cmp_fcn)
NM_CMP_RETURN (klass->cmp_fcn (a, b));
return 0;
}
/*****************************************************************************/
NM_GOBJECT_PROPERTIES_DEFINE_BASE (
PROP_PLUGIN,
PROP_UUID,
PROP_FILENAME,
);
G_DEFINE_TYPE (NMSettingsStorage, nm_settings_storage, G_TYPE_OBJECT)
/*****************************************************************************/
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMSettingsStorage *self = NM_SETTINGS_STORAGE (object);
switch (prop_id) {
case PROP_PLUGIN:
/* construct-only */
self->_plugin = g_object_ref (g_value_get_object (value));
nm_assert (NM_IS_SETTINGS_PLUGIN (self->_plugin));
break;
case PROP_UUID:
/* construct-only */
self->_uuid = g_value_dup_string (value);
nm_assert (!self->_uuid || nm_utils_is_uuid (self->_uuid));
break;
case PROP_FILENAME:
/* construct-only */
self->_filename = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/*****************************************************************************/
static void
nm_settings_storage_init (NMSettingsStorage *self)
{
c_list_init (&self->_storage_lst);
c_list_init (&self->_storage_by_uuid_lst);
}
NMSettingsStorage *
nm_settings_storage_new (NMSettingsPlugin *plugin,
const char *uuid,
const char *filename)
{
nm_assert (NM_IS_SETTINGS_PLUGIN (plugin));
nm_assert (nm_utils_is_uuid (uuid));
return g_object_new (NM_TYPE_SETTINGS_STORAGE,
NM_SETTINGS_STORAGE_PLUGIN, plugin,
NM_SETTINGS_STORAGE_UUID, uuid,
NM_SETTINGS_STORAGE_FILENAME, filename,
NULL);
}
static void
finalize (GObject *object)
{
NMSettingsStorage *self = NM_SETTINGS_STORAGE (object);
c_list_unlink_stale (&self->_storage_lst);
c_list_unlink_stale (&self->_storage_by_uuid_lst);
g_object_unref (self->_plugin);
g_free (self->_uuid);
g_free (self->_filename);
G_OBJECT_CLASS (nm_settings_storage_parent_class)->finalize (object);
}
static void
nm_settings_storage_class_init (NMSettingsStorageClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = set_property;
object_class->finalize = finalize;
obj_properties[PROP_PLUGIN] =
g_param_spec_object (NM_SETTINGS_STORAGE_PLUGIN, "", "",
NM_TYPE_SETTINGS_PLUGIN,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_UUID] =
g_param_spec_string (NM_SETTINGS_STORAGE_UUID, "", "",
NULL,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_FILENAME] =
g_param_spec_string (NM_SETTINGS_STORAGE_FILENAME, "", "",
NULL,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
}

View File

@ -0,0 +1,122 @@
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2018 Red Hat, Inc.
*/
#ifndef __NM_SETTINGS_STORAGE_H__
#define __NM_SETTINGS_STORAGE_H__
/*****************************************************************************/
#include "c-list/src/c-list.h"
#define NM_TYPE_SETTINGS_STORAGE (nm_settings_storage_get_type ())
#define NM_SETTINGS_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_STORAGE, NMSettingsStorage))
#define NM_SETTINGS_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTINGS_STORAGE, NMSettingsStorageClass))
#define NM_IS_SETTINGS_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_STORAGE))
#define NM_IS_SETTINGS_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTINGS_STORAGE))
#define NM_SETTINGS_STORAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTINGS_STORAGE, NMSettingsStorageClass))
#define NM_SETTINGS_STORAGE_PLUGIN "plugin"
#define NM_SETTINGS_STORAGE_UUID "uuid"
#define NM_SETTINGS_STORAGE_FILENAME "filename"
struct _NMSettingsPlugin;
typedef struct NMSettingsStorage {
GObject parent;
struct _NMSettingsPlugin *_plugin;
char *_uuid;
char *_filename;
CList _storage_lst;
CList _storage_by_uuid_lst;
} NMSettingsStorage;
typedef struct {
GObjectClass parent;
int (*cmp_fcn) (NMSettingsStorage *a,
NMSettingsStorage *b);
} NMSettingsStorageClass;
GType nm_settings_storage_get_type (void);
NMSettingsStorage *nm_settings_storage_new (struct _NMSettingsPlugin *plugin,
const char *uuid,
const char *filename);
static inline struct _NMSettingsPlugin *
nm_settings_storage_get_plugin (const NMSettingsStorage *self)
{
GType nm_settings_plugin_get_type (void);
g_return_val_if_fail (NM_IS_SETTINGS_STORAGE (self), NULL);
nm_assert (G_TYPE_CHECK_INSTANCE_TYPE (self->_plugin, nm_settings_plugin_get_type ()));
return self->_plugin;
}
static inline const char *
nm_settings_storage_get_uuid (const NMSettingsStorage *self)
{
gboolean nm_utils_is_uuid (const char *str);
g_return_val_if_fail (NM_IS_SETTINGS_STORAGE (self), NULL);
nm_assert (nm_utils_is_uuid (self->_uuid));
return self->_uuid;
}
static inline const char *
nm_settings_storage_get_uuid_opt (const NMSettingsStorage *self)
{
gboolean nm_utils_is_uuid (const char *str);
g_return_val_if_fail (NM_IS_SETTINGS_STORAGE (self), NULL);
nm_assert (!self->_uuid || nm_utils_is_uuid (self->_uuid));
return self->_uuid;
}
static inline const char *
nm_settings_storage_get_filename (const NMSettingsStorage *self)
{
g_return_val_if_fail (NM_IS_SETTINGS_STORAGE (self), NULL);
return self->_filename;
}
/*****************************************************************************/
#define nm_assert_valid_settings_storage(plugin, storage) \
G_STMT_START { \
NMSettingsPlugin *const _plugin = (plugin); \
NMSettingsStorage *const _storage = (storage); \
\
nm_assert (!_plugin || NM_IS_SETTINGS_PLUGIN (_plugin)); \
nm_assert (NM_IS_SETTINGS_STORAGE (_storage)); \
nm_assert (!_plugin || nm_settings_storage_get_plugin (_storage) == _plugin); \
} G_STMT_END
/*****************************************************************************/
int nm_settings_storage_cmp (NMSettingsStorage *sd_a,
NMSettingsStorage *sd_b,
const GSList *plugin_list);
#endif /* __NM_SETTINGS_STORAGE_H__ */

View File

@ -0,0 +1,175 @@
/* NetworkManager system settings service - keyfile plugin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2019 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-settings-utils.h"
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include "nm-settings-plugin.h"
/*****************************************************************************/
const struct timespec *
nm_sett_util_stat_mtime (const char *filename,
gboolean do_lstat,
struct timespec *out_val)
{
struct stat st;
struct timeval now_tv;
if (filename) {
if (do_lstat) {
if (lstat (filename, &st) == 0) {
*out_val = st.st_mtim;
return out_val;
}
} else {
if (stat (filename, &st) == 0) {
*out_val = st.st_mtim;
return out_val;
}
}
}
if (gettimeofday (&now_tv, NULL) == 0) {
*out_val = (struct timespec) {
.tv_sec = now_tv.tv_sec,
.tv_nsec = now_tv.tv_usec * 1000u,
};
return out_val;
}
*out_val = (struct timespec) { };
return out_val;
}
/*****************************************************************************/
gboolean
nm_sett_util_allow_filename_cb (const char *filename,
gpointer user_data)
{
const NMSettUtilAllowFilenameData *allow_filename_data = user_data;
if ( allow_filename_data->allowed_filename
&& nm_streq (allow_filename_data->allowed_filename, filename))
return TRUE;
return !g_hash_table_contains (allow_filename_data->idx_by_filename, filename);
}
/*****************************************************************************/
void
nm_sett_util_storage_by_uuid_head_destroy (NMSettUtilStorageByUuidHead *sbuh)
{
CList *iter;
while ((iter = c_list_first (&sbuh->_storage_by_uuid_lst_head)))
c_list_unlink (iter);
g_free (sbuh);
}
/*****************************************************************************/
void
nm_sett_util_storages_clear (NMSettUtilStorages *storages)
{
nm_clear_pointer (&storages->idx_by_uuid, g_hash_table_destroy);
nm_clear_pointer (&storages->idx_by_filename, g_hash_table_destroy);
nm_assert (c_list_is_empty (&storages->_storage_lst_head));
}
void
nm_sett_util_storages_add_take (NMSettUtilStorages *storages,
gpointer storage_take_p /* NMSettingsStorage *, take reference */)
{
NMSettingsStorage *storage_take = storage_take_p;
NMSettUtilStorageByUuidHead *sbuh;
const char *uuid;
nm_assert (storage_take);
nm_assert (c_list_is_empty (&storage_take->_storage_lst));
nm_assert (c_list_is_empty (&storage_take->_storage_by_uuid_lst));
nm_assert (nm_settings_storage_get_filename (storage_take));
if (!g_hash_table_replace (storages->idx_by_filename,
(char *) nm_settings_storage_get_filename (storage_take),
storage_take /* takes ownership of reference. */))
nm_assert_not_reached ();
uuid = nm_settings_storage_get_uuid_opt (storage_take);
if (uuid) {
sbuh = nm_sett_util_storages_lookup_by_uuid (storages, uuid);
if (!sbuh) {
gsize l = strlen (uuid) + 1;
sbuh = g_malloc (sizeof (NMSettUtilStorageByUuidHead) + l);
sbuh->uuid = sbuh->uuid_data;
c_list_init (&sbuh->_storage_by_uuid_lst_head);
memcpy (sbuh->uuid_data, uuid, l);
g_hash_table_add (storages->idx_by_uuid, sbuh);
}
c_list_link_tail (&sbuh->_storage_by_uuid_lst_head, &storage_take->_storage_by_uuid_lst);
}
c_list_link_tail (&storages->_storage_lst_head, &storage_take->_storage_lst);
}
gpointer /* NMSettingsStorage * */
nm_sett_util_storages_steal (NMSettUtilStorages *storages,
gpointer storage_p /* NMSettingsStorage **/)
{
NMSettingsStorage *storage = storage_p;
NMSettUtilStorageByUuidHead *sbuh;
const char *uuid;
nm_assert (storage);
nm_assert (nm_sett_util_storages_lookup_by_filename (storages, nm_settings_storage_get_filename (storage)) == storage);
nm_assert (c_list_contains (&storages->_storage_lst_head, &storage->_storage_lst));
uuid = nm_settings_storage_get_uuid_opt (storage);
if (!uuid) {
nm_assert (c_list_is_empty (&storage->_storage_by_uuid_lst));
} else {
nm_assert (!c_list_is_empty (&storage->_storage_by_uuid_lst));
sbuh = nm_sett_util_storages_lookup_by_uuid (storages, uuid);
nm_assert (sbuh);
nm_assert (c_list_contains (&sbuh->_storage_by_uuid_lst_head, &storage->_storage_by_uuid_lst));
c_list_unlink (&storage->_storage_by_uuid_lst);
if (c_list_is_empty (&sbuh->_storage_by_uuid_lst_head))
g_hash_table_remove (storages->idx_by_uuid, sbuh);
}
c_list_unlink (&storage->_storage_lst);
g_hash_table_steal (storages->idx_by_filename, nm_settings_storage_get_filename (storage));
return storage;
}

View File

@ -0,0 +1,110 @@
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2019 Red Hat, Inc.
*/
#ifndef __NM_SETTINGS_UTILS_H__
#define __NM_SETTINGS_UTILS_H__
#include "nm-settings-storage.h"
/*****************************************************************************/
struct timespec;
const struct timespec *nm_sett_util_stat_mtime (const char *filename,
gboolean do_lstat,
struct timespec *out_val);
/*****************************************************************************/
typedef struct {
const char *uuid;
CList _storage_by_uuid_lst_head;
char uuid_data[];
} NMSettUtilStorageByUuidHead;
typedef struct {
CList _storage_lst_head;
GHashTable *idx_by_filename;
GHashTable *idx_by_uuid;
} NMSettUtilStorages;
void nm_sett_util_storage_by_uuid_head_destroy (NMSettUtilStorageByUuidHead *sbuh);
#define NM_SETT_UTIL_STORAGES_INIT(storages, storage_destroy_fcn) \
{ \
._storage_lst_head = C_LIST_INIT (((storages)._storage_lst_head)), \
.idx_by_filename = g_hash_table_new_full (nm_str_hash, \
g_str_equal, \
NULL, \
(GDestroyNotify) storage_destroy_fcn), \
.idx_by_uuid = g_hash_table_new_full (nm_pstr_hash, \
nm_pstr_equal, \
NULL, \
(GDestroyNotify) nm_sett_util_storage_by_uuid_head_destroy), \
}
void nm_sett_util_storages_clear (NMSettUtilStorages *storages);
#define nm_auto_clear_sett_util_storages nm_auto(nm_sett_util_storages_clear)
void nm_sett_util_storages_add_take (NMSettUtilStorages *storages,
gpointer storage_take_p);
gpointer nm_sett_util_storages_steal (NMSettUtilStorages *storages,
gpointer storage_p);
/*****************************************************************************/
static inline gpointer /* NMSettingsStorage * */
nm_sett_util_storages_lookup_by_filename (NMSettUtilStorages *storages,
const char *filename)
{
nm_assert (filename);
return g_hash_table_lookup (storages->idx_by_filename, filename);
}
static inline NMSettUtilStorageByUuidHead *
nm_sett_util_storages_lookup_by_uuid (NMSettUtilStorages *storages,
const char *uuid)
{
nm_assert (uuid);
return g_hash_table_lookup (storages->idx_by_uuid, &uuid);
}
/*****************************************************************************/
typedef struct {
GHashTable *idx_by_filename;
const char *allowed_filename;
} NMSettUtilAllowFilenameData;
#define NM_SETT_UTIL_ALLOW_FILENAME_DATA(_storages, _allowed_filename) \
(&((NMSettUtilAllowFilenameData) { \
.idx_by_filename = (_storages)->idx_by_filename, \
.allowed_filename = (_allowed_filename), \
}))
gboolean nm_sett_util_allow_filename_cb (const char *filename,
gpointer user_data);
#endif /* __NM_SETTINGS_UTILS_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,8 @@
#include "nm-connection.h"
#include "nm-settings-connection.h"
#define NM_TYPE_SETTINGS (nm_settings_get_type ())
#define NM_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS, NMSettings))
#define NM_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTINGS, NMSettingsClass))
@ -67,6 +69,7 @@ NMSettings *nm_settings_get (void);
#define NM_SETTINGS_GET (nm_settings_get ())
NMSettings *nm_settings_new (void);
gboolean nm_settings_start (NMSettings *self, GError **error);
typedef void (*NMSettingsAddCallback) (NMSettings *settings,
@ -78,7 +81,8 @@ typedef void (*NMSettingsAddCallback) (NMSettings *settings,
void nm_settings_add_connection_dbus (NMSettings *self,
NMConnection *connection,
gboolean save_to_disk,
NMSettingsConnectionPersistMode persist_mode,
NMSettingsConnectionIntFlags sett_flags,
NMAuthSubject *subject,
GDBusMethodInvocation *context,
NMSettingsAddCallback callback,
@ -93,16 +97,36 @@ NMSettingsConnection **nm_settings_get_connections_clone (NMSettings *self,
GCompareDataFunc sort_compare_func,
gpointer sort_data);
NMSettingsConnection *nm_settings_add_connection (NMSettings *settings,
NMConnection *connection,
gboolean save_to_disk,
GError **error);
gboolean nm_settings_add_connection (NMSettings *settings,
NMConnection *connection,
NMSettingsConnectionPersistMode persist_mode,
NMSettingsConnectionIntFlags sett_flags,
NMSettingsConnection **out_sett_conn,
GError **error);
gboolean nm_settings_update_connection (NMSettings *self,
NMSettingsConnection *sett_conn,
NMConnection *new_connection,
NMSettingsConnectionPersistMode persist_mode,
NMSettingsConnectionIntFlags sett_flags,
NMSettingsConnectionIntFlags sett_mask,
NMSettingsConnectionUpdateReason update_reason,
const char *log_context_name,
GError **error);
void nm_settings_delete_connection (NMSettings *self,
NMSettingsConnection *sett_conn,
gboolean allow_add_to_no_auto_default);
NMSettingsConnection *nm_settings_get_connection_by_path (NMSettings *settings,
const char *path);
NMSettingsConnection *nm_settings_get_connection_by_uuid (NMSettings *settings,
const char *uuid);
const char *nm_settings_get_dbus_path_for_uuid (NMSettings *self,
const char *uuid);
gboolean nm_settings_has_connection (NMSettings *self, NMSettingsConnection *connection);
const GSList *nm_settings_get_unmanaged_specs (NMSettings *self);

View File

@ -35,7 +35,7 @@ libnms_ifcfg_rh_core = static_library(
dependencies: deps,
)
sources = [dbus_sources] + core_sources + files('nms-ifcfg-rh-connection.c', 'nms-ifcfg-rh-plugin.c')
sources = [dbus_sources] + core_sources + files('nms-ifcfg-rh-storage.c', 'nms-ifcfg-rh-plugin.c')
libnm_settings_plugin_ifcfg_rh = shared_module(
'nm-settings-plugin-ifcfg-rh',

View File

@ -1,400 +0,0 @@
/* NetworkManager system settings service
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 - 2011 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nms-ifcfg-rh-connection.h"
#include <sys/inotify.h>
#include <glib/gstdio.h>
#include "nm-dbus-interface.h"
#include "nm-setting-connection.h"
#include "nm-setting-wired.h"
#include "nm-setting-wireless.h"
#include "nm-setting-gsm.h"
#include "nm-setting-cdma.h"
#include "nm-setting-pppoe.h"
#include "nm-setting-wireless-security.h"
#include "nm-setting-8021x.h"
#include "platform/nm-platform.h"
#include "nm-config.h"
#include "nms-ifcfg-rh-common.h"
#include "nms-ifcfg-rh-reader.h"
#include "nms-ifcfg-rh-writer.h"
#include "nms-ifcfg-rh-utils.h"
/*****************************************************************************/
NM_GOBJECT_PROPERTIES_DEFINE_BASE (
PROP_UNMANAGED_SPEC,
PROP_UNRECOGNIZED_SPEC,
);
typedef struct {
char *unmanaged_spec;
char *unrecognized_spec;
gulong devtimeout_link_changed_handler;
guint devtimeout_timeout_id;
} NMIfcfgConnectionPrivate;
struct _NMIfcfgConnection {
NMSettingsConnection parent;
NMIfcfgConnectionPrivate _priv;
};
struct _NMIfcfgConnectionClass {
NMSettingsConnectionClass parent;
};
G_DEFINE_TYPE (NMIfcfgConnection, nm_ifcfg_connection, NM_TYPE_SETTINGS_CONNECTION)
#define NM_IFCFG_CONNECTION_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMIfcfgConnection, NM_IS_IFCFG_CONNECTION)
/*****************************************************************************/
static gboolean
devtimeout_ready (gpointer user_data)
{
NMIfcfgConnection *self = user_data;
NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self);
priv->devtimeout_timeout_id = 0;
nm_settings_connection_set_ready (NM_SETTINGS_CONNECTION (self), TRUE);
return FALSE;
}
static void
link_changed (NMPlatform *platform, int obj_type_i, int ifindex, const NMPlatformLink *link,
int change_type_i,
NMConnection *self)
{
const NMPlatformSignalChangeType change_type = change_type_i;
NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE ((NMIfcfgConnection *) self);
const char *ifname;
ifname = nm_connection_get_interface_name (self);
if (g_strcmp0 (link->name, ifname) != 0)
return;
if (change_type == NM_PLATFORM_SIGNAL_REMOVED)
return;
nm_log_info (LOGD_SETTINGS, "Device %s appeared; connection '%s' now ready",
ifname, nm_connection_get_id (self));
g_signal_handler_disconnect (platform, priv->devtimeout_link_changed_handler);
priv->devtimeout_link_changed_handler = 0;
g_source_remove (priv->devtimeout_timeout_id);
/* Don't declare the connection ready right away, since NMManager may not have
* started processing the device yet.
*/
priv->devtimeout_timeout_id = g_idle_add (devtimeout_ready, self);
}
static gboolean
devtimeout_expired (gpointer user_data)
{
NMIfcfgConnection *self = user_data;
NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self);
nm_log_info (LOGD_SETTINGS, "Device for connection '%s' did not appear before timeout",
nm_settings_connection_get_id (NM_SETTINGS_CONNECTION (self)));
g_signal_handler_disconnect (NM_PLATFORM_GET, priv->devtimeout_link_changed_handler);
priv->devtimeout_link_changed_handler = 0;
priv->devtimeout_timeout_id = 0;
nm_settings_connection_set_ready (NM_SETTINGS_CONNECTION (self), TRUE);
return FALSE;
}
static void
nm_ifcfg_connection_check_devtimeout (NMIfcfgConnection *self)
{
NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self);
NMSettingConnection *s_con;
const char *ifname;
const char *filename;
guint devtimeout;
const NMPlatformLink *pllink;
s_con = nm_connection_get_setting_connection (nm_settings_connection_get_connection (NM_SETTINGS_CONNECTION (self)));
if (!nm_setting_connection_get_autoconnect (s_con))
return;
ifname = nm_setting_connection_get_interface_name (s_con);
if (!ifname)
return;
filename = nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (self));
if (!filename)
return;
pllink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, ifname);
if (pllink && pllink->initialized)
return;
devtimeout = devtimeout_from_file (filename);
if (!devtimeout)
return;
/* ONBOOT=yes, DEVICE and DEVTIMEOUT are set, but device is not present */
nm_settings_connection_set_ready (NM_SETTINGS_CONNECTION (self), FALSE);
nm_log_info (LOGD_SETTINGS, "Waiting %u seconds for %s to appear for connection '%s'",
devtimeout, ifname, nm_settings_connection_get_id (NM_SETTINGS_CONNECTION (self)));
priv->devtimeout_link_changed_handler =
g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_LINK_CHANGED,
G_CALLBACK (link_changed), self);
priv->devtimeout_timeout_id = g_timeout_add_seconds (devtimeout, devtimeout_expired, self);
}
const char *
nm_ifcfg_connection_get_unmanaged_spec (NMIfcfgConnection *self)
{
g_return_val_if_fail (NM_IS_IFCFG_CONNECTION (self), NULL);
return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unmanaged_spec;
}
const char *
nm_ifcfg_connection_get_unrecognized_spec (NMIfcfgConnection *self)
{
g_return_val_if_fail (NM_IS_IFCFG_CONNECTION (self), NULL);
return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unrecognized_spec;
}
static gboolean
commit_changes (NMSettingsConnection *connection,
NMConnection *new_connection,
NMSettingsConnectionCommitReason commit_reason,
NMConnection **out_reread_connection,
char **out_logmsg_change,
GError **error)
{
const char *filename;
gs_unref_object NMConnection *reread = NULL;
gboolean reread_same = TRUE;
const char *operation_message;
gs_free char *ifcfg_path = NULL;
nm_assert (out_reread_connection && !*out_reread_connection);
nm_assert (!out_logmsg_change || !*out_logmsg_change);
filename = nm_settings_connection_get_filename (connection);
if (!nms_ifcfg_rh_writer_write_connection (new_connection,
IFCFG_DIR,
filename,
NULL,
NULL,
&ifcfg_path,
&reread,
&reread_same,
error))
return FALSE;
nm_assert ((!filename && ifcfg_path) || (filename && !ifcfg_path));
if (ifcfg_path) {
nm_settings_connection_set_filename (connection, ifcfg_path);
operation_message = "persist";
} else
operation_message = "update";
if (reread && !reread_same)
*out_reread_connection = g_steal_pointer (&reread);
NM_SET_OUT (out_logmsg_change,
g_strdup_printf ("ifcfg-rh: %s %s",
operation_message, filename));
return TRUE;
}
static gboolean
delete (NMSettingsConnection *connection,
GError **error)
{
const char *filename;
filename = nm_settings_connection_get_filename (connection);
if (filename) {
gs_free char *keyfile = utils_get_keys_path (filename);
gs_free char *routefile = utils_get_route_path (filename);
gs_free char *route6file = utils_get_route6_path (filename);
g_unlink (filename);
if (keyfile)
g_unlink (keyfile);
if (routefile)
g_unlink (routefile);
if (route6file)
g_unlink (route6file);
}
return TRUE;
}
/*****************************************************************************/
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE ((NMIfcfgConnection *) object);
switch (prop_id) {
case PROP_UNMANAGED_SPEC:
g_value_set_string (value, priv->unmanaged_spec);
break;
case PROP_UNRECOGNIZED_SPEC:
g_value_set_string (value, priv->unrecognized_spec);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE ((NMIfcfgConnection *) object);
switch (prop_id) {
case PROP_UNMANAGED_SPEC:
priv->unmanaged_spec = g_value_dup_string (value);
break;
case PROP_UNRECOGNIZED_SPEC:
priv->unrecognized_spec = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/*****************************************************************************/
static void
nm_ifcfg_connection_init (NMIfcfgConnection *self)
{
}
NMIfcfgConnection *
nm_ifcfg_connection_new (NMConnection *source,
const char *full_path,
GError **error,
gboolean *out_ignore_error)
{
GObject *object;
NMConnection *tmp;
char *unhandled_spec = NULL;
const char *unmanaged_spec = NULL, *unrecognized_spec = NULL;
g_assert (source || full_path);
if (out_ignore_error)
*out_ignore_error = FALSE;
/* If we're given a connection already, prefer that instead of re-reading */
if (source)
tmp = g_object_ref (source);
else {
tmp = connection_from_file (full_path,
&unhandled_spec,
error,
out_ignore_error);
if (!tmp)
return NULL;
}
if (unhandled_spec && g_str_has_prefix (unhandled_spec, "unmanaged:"))
unmanaged_spec = unhandled_spec + strlen ("unmanaged:");
else if (unhandled_spec && g_str_has_prefix (unhandled_spec, "unrecognized:"))
unrecognized_spec = unhandled_spec + strlen ("unrecognized:");
object = (GObject *) g_object_new (NM_TYPE_IFCFG_CONNECTION,
NM_SETTINGS_CONNECTION_FILENAME, full_path,
NM_IFCFG_CONNECTION_UNMANAGED_SPEC, unmanaged_spec,
NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC, unrecognized_spec,
NULL);
/* Update our settings with what was read from the file */
if (nm_settings_connection_update (NM_SETTINGS_CONNECTION (object),
tmp,
full_path
? NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP_SAVED
: NM_SETTINGS_CONNECTION_PERSIST_MODE_UNSAVED,
NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE,
NULL,
error))
nm_ifcfg_connection_check_devtimeout (NM_IFCFG_CONNECTION (object));
else
g_clear_object (&object);
g_object_unref (tmp);
g_free (unhandled_spec);
return (NMIfcfgConnection *) object;
}
static void
dispose (GObject *object)
{
NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE ((NMIfcfgConnection *) object);
nm_clear_g_signal_handler (NM_PLATFORM_GET, &priv->devtimeout_link_changed_handler);
nm_clear_g_source (&priv->devtimeout_timeout_id);
g_clear_pointer (&priv->unmanaged_spec, g_free);
g_clear_pointer (&priv->unrecognized_spec, g_free);
G_OBJECT_CLASS (nm_ifcfg_connection_parent_class)->dispose (object);
}
static void
nm_ifcfg_connection_class_init (NMIfcfgConnectionClass *ifcfg_connection_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (ifcfg_connection_class);
NMSettingsConnectionClass *settings_class = NM_SETTINGS_CONNECTION_CLASS (ifcfg_connection_class);
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->dispose = dispose;
settings_class->delete = delete;
settings_class->commit_changes = commit_changes;
obj_properties[PROP_UNMANAGED_SPEC] =
g_param_spec_string (NM_IFCFG_CONNECTION_UNMANAGED_SPEC, "", "",
NULL,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_UNRECOGNIZED_SPEC] =
g_param_spec_string (NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC, "", "",
NULL,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
}

View File

@ -1,53 +0,0 @@
/* NetworkManager system settings service
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 - 2011 Red Hat, Inc.
*/
#ifndef __NETWORKMANAGER_IFCFG_CONNECTION_H__
#define __NETWORKMANAGER_IFCFG_CONNECTION_H__
#include "nm-dbus-interface.h"
#include "settings/nm-settings-connection.h"
#define NM_TYPE_IFCFG_CONNECTION (nm_ifcfg_connection_get_type ())
#define NM_IFCFG_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IFCFG_CONNECTION, NMIfcfgConnection))
#define NM_IFCFG_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IFCFG_CONNECTION, NMIfcfgConnectionClass))
#define NM_IS_IFCFG_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IFCFG_CONNECTION))
#define NM_IS_IFCFG_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_IFCFG_CONNECTION))
#define NM_IFCFG_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IFCFG_CONNECTION, NMIfcfgConnectionClass))
#define NM_IFCFG_CONNECTION_UNMANAGED_SPEC "unmanaged-spec"
#define NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC "unrecognized-spec"
typedef struct _NMIfcfgConnection NMIfcfgConnection;
typedef struct _NMIfcfgConnectionClass NMIfcfgConnectionClass;
GType nm_ifcfg_connection_get_type (void);
NMIfcfgConnection *nm_ifcfg_connection_new (NMConnection *source,
const char *full_path,
GError **error,
gboolean *out_ignore_error);
const char *nm_ifcfg_connection_get_unmanaged_spec (NMIfcfgConnection *self);
const char *nm_ifcfg_connection_get_unrecognized_spec (NMIfcfgConnection *self);
gboolean nm_ifcfg_connection_update (NMIfcfgConnection *self,
GHashTable *new_settings,
GError **error);
#endif /* __NETWORKMANAGER_IFCFG_CONNECTION_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -20,19 +20,19 @@
* Copyright (C) 2007 - 2008 Red Hat, Inc.
*/
#ifndef _PLUGIN_H_
#define _PLUGIN_H_
#ifndef __NMS_IFCFG_RH_PLUGIN_H__
#define __NMS_IFCFG_RH_PLUGIN_H__
#define SETTINGS_TYPE_PLUGIN_IFCFG (settings_plugin_ifcfg_get_type ())
#define SETTINGS_PLUGIN_IFCFG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SETTINGS_TYPE_PLUGIN_IFCFG, SettingsPluginIfcfg))
#define SETTINGS_PLUGIN_IFCFG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SETTINGS_TYPE_PLUGIN_IFCFG, SettingsPluginIfcfgClass))
#define SETTINGS_IS_PLUGIN_IFCFG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SETTINGS_TYPE_PLUGIN_IFCFG))
#define SETTINGS_IS_PLUGIN_IFCFG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SETTINGS_TYPE_PLUGIN_IFCFG))
#define SETTINGS_PLUGIN_IFCFG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SETTINGS_TYPE_PLUGIN_IFCFG, SettingsPluginIfcfgClass))
#define NMS_TYPE_IFCFG_RH_PLUGIN (nms_ifcfg_rh_plugin_get_type ())
#define NMS_IFCFG_RH_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMS_TYPE_IFCFG_RH_PLUGIN, NMSIfcfgRHPlugin))
#define NMS_IFCFG_RH_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMS_TYPE_IFCFG_RH_PLUGIN, NMSIfcfgRHPluginClass))
#define NMS_IS_IFCFG_RH_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMS_TYPE_IFCFG_RH_PLUGIN))
#define NMS_IS_IFCFG_RH_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMS_TYPE_IFCFG_RH_PLUGIN))
#define NMS_IFCFG_RH_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMS_TYPE_IFCFG_RH_PLUGIN, NMSIfcfgRHPluginClass))
typedef struct _SettingsPluginIfcfg SettingsPluginIfcfg;
typedef struct _SettingsPluginIfcfgClass SettingsPluginIfcfgClass;
typedef struct _NMSIfcfgRHPlugin NMSIfcfgRHPlugin;
typedef struct _NMSIfcfgRHPluginClass NMSIfcfgRHPluginClass;
GType settings_plugin_ifcfg_get_type (void);
GType nms_ifcfg_rh_plugin_get_type (void);
#endif /* _PLUGIN_H_ */
#endif /* __NMS_IFCFG_RH_PLUGIN_H__ */

View File

@ -6028,20 +6028,3 @@ nmtst_connection_from_file (const char *filename,
error,
NULL);
}
guint
devtimeout_from_file (const char *filename)
{
shvarFile *ifcfg;
guint devtimeout;
g_return_val_if_fail (filename != NULL, 0);
ifcfg = svOpenFile (filename, NULL);
if (!ifcfg)
return 0;
devtimeout = svGetValueInt64 (ifcfg, "DEVTIMEOUT", 10, 0, G_MAXUINT, 0);
svCloseFile (ifcfg);
return devtimeout;
}

View File

@ -17,8 +17,8 @@
* Copyright (C) 2008 Red Hat, Inc.
*/
#ifndef __READER_H__
#define __READER_H__
#ifndef __NMS_IFCFG_RH_READER_H__
#define __NMS_IFCFG_RH_READER_H__
#include "nm-connection.h"
@ -27,12 +27,10 @@ NMConnection *connection_from_file (const char *filename,
GError **error,
gboolean *out_ignore_error);
guint devtimeout_from_file (const char *filename);
NMConnection *nmtst_connection_from_file (const char *filename,
const char *network_file,
const char *test_type,
char **out_unhandled,
GError **error);
#endif /* __READER_H__ */
#endif /* __NMS_IFCFG_RH_READER_H__ */

View File

@ -0,0 +1,198 @@
/* NetworkManager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2018 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nms-ifcfg-rh-storage.h"
#include "nm-utils.h"
#include "nm-core-internal.h"
#include "nm-connection.h"
#include "nms-ifcfg-rh-plugin.h"
/*****************************************************************************/
struct _NMSIfcfgRHStorageClass {
NMSettingsStorageClass parent;
};
G_DEFINE_TYPE (NMSIfcfgRHStorage, nms_ifcfg_rh_storage, NM_TYPE_SETTINGS_STORAGE)
/*****************************************************************************/
gboolean
nms_ifcfg_rh_storage_equal_type (const NMSIfcfgRHStorage *self_a,
const NMSIfcfgRHStorage *self_b)
{
return (self_a == self_b)
|| ( self_a
&& self_b
&& nm_streq0 (nms_ifcfg_rh_storage_get_uuid_opt (self_a),
nms_ifcfg_rh_storage_get_uuid_opt (self_b))
&& nm_streq0 (self_a->unmanaged_spec,
self_b->unmanaged_spec)
&& nm_streq0 (self_a->unrecognized_spec,
self_b->unrecognized_spec));
}
void
nms_ifcfg_rh_storage_copy_content (NMSIfcfgRHStorage *dst,
const NMSIfcfgRHStorage *src)
{
nm_assert (src != dst);
nm_assert (src && dst);
nm_assert (nms_ifcfg_rh_storage_equal_type (dst, src));
nm_assert ( nms_ifcfg_rh_storage_get_filename (dst)
&& nm_streq (nms_ifcfg_rh_storage_get_filename (dst),
nms_ifcfg_rh_storage_get_filename (src)));
nm_g_object_ref_set (&dst->connection, src->connection);
g_free (dst->unmanaged_spec);
g_free (dst->unrecognized_spec);
dst->unmanaged_spec = g_strdup (src->unmanaged_spec);
dst->unrecognized_spec = g_strdup (src->unrecognized_spec);
dst->stat_mtime = src->stat_mtime;
}
NMConnection *
nms_ifcfg_rh_storage_steal_connection (NMSIfcfgRHStorage *self)
{
nm_assert (NMS_IS_IFCFG_RH_STORAGE (self));
return g_steal_pointer (&self->connection);
}
/*****************************************************************************/
static int
cmp_fcn (const NMSIfcfgRHStorage *a,
const NMSIfcfgRHStorage *b)
{
nm_assert (NMS_IS_IFCFG_RH_STORAGE (a));
nm_assert (NMS_IS_IFCFG_RH_STORAGE (b));
nm_assert (a != b);
/* newer files are more important. */
NM_CMP_FIELD (b, a, stat_mtime.tv_sec);
NM_CMP_FIELD (b, a, stat_mtime.tv_nsec);
NM_CMP_DIRECT_STRCMP (nms_ifcfg_rh_storage_get_filename (a), nms_ifcfg_rh_storage_get_filename (b));
return 0;
}
/*****************************************************************************/
static void
nms_ifcfg_rh_storage_init (NMSIfcfgRHStorage *self)
{
}
static NMSIfcfgRHStorage *
_storage_new (NMSIfcfgRHPlugin *plugin,
const char *uuid,
const char *filename)
{
nm_assert (NMS_IS_IFCFG_RH_PLUGIN (plugin));
nm_assert (!uuid || nm_utils_is_uuid (uuid));
nm_assert (filename && filename[0] == '/');
return g_object_new (NMS_TYPE_IFCFG_RH_STORAGE,
NM_SETTINGS_STORAGE_PLUGIN, plugin,
NM_SETTINGS_STORAGE_UUID, uuid,
NM_SETTINGS_STORAGE_FILENAME, filename,
NULL);
}
NMSIfcfgRHStorage *
nms_ifcfg_rh_storage_new_connection (NMSIfcfgRHPlugin *plugin,
const char *filename,
NMConnection *connection_take,
const struct timespec *mtime)
{
NMSIfcfgRHStorage *self;
nm_assert (NM_IS_CONNECTION (connection_take));
nm_assert (_nm_connection_verify (connection_take, NULL) == NM_SETTING_VERIFY_SUCCESS);
nmtst_connection_assert_unchanging (connection_take);
self = _storage_new (plugin,
nm_connection_get_uuid (connection_take),
filename);
self->connection = connection_take;
if (mtime)
self->stat_mtime = *mtime;
return self;
}
NMSIfcfgRHStorage *
nms_ifcfg_rh_storage_new_unhandled (NMSIfcfgRHPlugin *plugin,
const char *filename,
const char *unmanaged_spec,
const char *unrecognized_spec)
{
NMSIfcfgRHStorage *self;
nm_assert (unmanaged_spec || unrecognized_spec);
self = _storage_new (plugin,
NULL,
filename);
self->unmanaged_spec = g_strdup (unmanaged_spec);
self->unrecognized_spec = g_strdup (unrecognized_spec);
return self;
}
static void
_storage_clear (NMSIfcfgRHStorage *self)
{
c_list_unlink (&self->parent._storage_lst);
c_list_unlink (&self->parent._storage_by_uuid_lst);
nm_clear_g_free (&self->unmanaged_spec);
nm_clear_g_free (&self->unrecognized_spec);
g_clear_object (&self->connection);
}
static void
dispose (GObject *object)
{
NMSIfcfgRHStorage *self = NMS_IFCFG_RH_STORAGE (object);
_storage_clear (self);
G_OBJECT_CLASS (nms_ifcfg_rh_storage_parent_class)->dispose (object);
}
void
nms_ifcfg_rh_storage_destroy (NMSIfcfgRHStorage *self)
{
_storage_clear (self);
g_object_unref (self);
}
static void
nms_ifcfg_rh_storage_class_init (NMSIfcfgRHStorageClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMSettingsStorageClass *storage_class = NM_SETTINGS_STORAGE_CLASS (klass);
object_class->dispose = dispose;
storage_class->cmp_fcn = (int (*) (NMSettingsStorage *, NMSettingsStorage *)) cmp_fcn;
}

View File

@ -0,0 +1,93 @@
/* NetworkManager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2019 Red Hat, Inc.
*/
#ifndef __NMS_IFCFG_RH_STORAGE_H__
#define __NMS_IFCFG_RH_STORAGE_H__
#include "c-list/src/c-list.h"
#include "settings/nm-settings-storage.h"
/*****************************************************************************/
#define NMS_TYPE_IFCFG_RH_STORAGE (nms_ifcfg_rh_storage_get_type ())
#define NMS_IFCFG_RH_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMS_TYPE_IFCFG_RH_STORAGE, NMSIfcfgRHStorage))
#define NMS_IFCFG_RH_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMS_TYPE_IFCFG_RH_STORAGE, NMSIfcfgRHStorageClass))
#define NMS_IS_IFCFG_RH_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMS_TYPE_IFCFG_RH_STORAGE))
#define NMS_IS_IFCFG_RH_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMS_TYPE_IFCFG_RH_STORAGE))
#define NMS_IFCFG_RH_STORAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMS_TYPE_IFCFG_RH_STORAGE, NMSIfcfgRHStorageClass))
typedef struct {
NMSettingsStorage parent;
NMConnection *connection;
char *unmanaged_spec;
char *unrecognized_spec;
/* The timestamp (stat's mtime) of the file. Newer files have
* higher priority. */
struct timespec stat_mtime;
bool dirty:1;
} NMSIfcfgRHStorage;
typedef struct _NMSIfcfgRHStorageClass NMSIfcfgRHStorageClass;
GType nms_ifcfg_rh_storage_get_type (void);
struct _NMSIfcfgRHPlugin;
NMSIfcfgRHStorage *nms_ifcfg_rh_storage_new_connection (struct _NMSIfcfgRHPlugin *plugin,
const char *filename,
NMConnection *connection_take,
const struct timespec *mtime);
NMSIfcfgRHStorage *nms_ifcfg_rh_storage_new_unhandled (struct _NMSIfcfgRHPlugin *plugin,
const char *filename,
const char *unmanaged_spec,
const char *unrecognized_spec);
void nms_ifcfg_rh_storage_destroy (NMSIfcfgRHStorage *self);
/*****************************************************************************/
gboolean nms_ifcfg_rh_storage_equal_type (const NMSIfcfgRHStorage *self_a,
const NMSIfcfgRHStorage *self_b);
void nms_ifcfg_rh_storage_copy_content (NMSIfcfgRHStorage *dst,
const NMSIfcfgRHStorage *src);
NMConnection *nms_ifcfg_rh_storage_steal_connection (NMSIfcfgRHStorage *self);
/*****************************************************************************/
static inline const char *
nms_ifcfg_rh_storage_get_uuid_opt (const NMSIfcfgRHStorage *self)
{
return nm_settings_storage_get_uuid_opt ((const NMSettingsStorage *) self);
}
static inline const char *
nms_ifcfg_rh_storage_get_filename (const NMSIfcfgRHStorage *self)
{
return nm_settings_storage_get_filename ((const NMSettingsStorage *) self);
}
#endif /* __NMS_IFCFG_RH_STORAGE_H__ */

View File

@ -28,6 +28,32 @@
#include "nms-ifcfg-rh-common.h"
/*****************************************************************************/
gboolean
nms_ifcfg_rh_util_parse_unhandled_spec (const char *unhandled_spec,
const char **out_unmanaged_spec,
const char **out_unrecognized_spec)
{
if (unhandled_spec) {
if (NM_STR_HAS_PREFIX (unhandled_spec, "unmanaged:")) {
NM_SET_OUT (out_unmanaged_spec, &unhandled_spec[NM_STRLEN ("unmanaged:")]);
NM_SET_OUT (out_unrecognized_spec, NULL);
return TRUE;
}
if (NM_STR_HAS_PREFIX (unhandled_spec, "unrecognized:")) {
NM_SET_OUT (out_unmanaged_spec, NULL);
NM_SET_OUT (out_unrecognized_spec, &unhandled_spec[NM_STRLEN ("unrecognized:")]);
return TRUE;
}
}
NM_SET_OUT (out_unmanaged_spec, NULL);
NM_SET_OUT (out_unrecognized_spec, NULL);
return FALSE;
}
/*****************************************************************************/
/*
* Check ';[a-fA-F0-9]{8}' file suffix used for temporary files by rpm when
* installing packages.

View File

@ -25,6 +25,10 @@
#include "shvar.h"
gboolean nms_ifcfg_rh_util_parse_unhandled_spec (const char *unhandled_spec,
const char **out_unmanaged_spec,
const char **out_unrecognized_spec);
#define NM_IFCFG_CONNECTION_LOG_PATH(path) ((path) ?: "in-memory")
#define NM_IFCFG_CONNECTION_LOG_FMT "%s (%s,\"%s\")"
#define NM_IFCFG_CONNECTION_LOG_ARG(con) NM_IFCFG_CONNECTION_LOG_PATH (nm_settings_connection_get_filename ((NMSettingsConnection *) (con))), nm_settings_connection_get_uuid ((NMSettingsConnection *) (con)), nm_settings_connection_get_id ((NMSettingsConnection *) (con))

View File

@ -15,7 +15,6 @@ libnms_ifupdown_core = static_library(
)
sources = files(
'nms-ifupdown-connection.c',
'nms-ifupdown-plugin.c',
)

View File

@ -1,91 +0,0 @@
/* NetworkManager system settings service (ifupdown)
*
* Alexander Sack <asac@ubuntu.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2007,2008 Canonical Ltd.
*/
#include "nm-default.h"
#include "nms-ifupdown-connection.h"
#include <glib/gstdio.h>
#include "nm-dbus-interface.h"
#include "nm-utils.h"
#include "nm-setting-wireless-security.h"
#include "settings/nm-settings-connection.h"
#include "settings/nm-settings-plugin.h"
#include "nms-ifupdown-parser.h"
/*****************************************************************************/
struct _NMIfupdownConnection {
NMSettingsConnection parent;
};
struct _NMIfupdownConnectionClass {
NMSettingsConnectionClass parent;
};
G_DEFINE_TYPE (NMIfupdownConnection, nm_ifupdown_connection, NM_TYPE_SETTINGS_CONNECTION)
/*****************************************************************************/
#define _NMLOG_PREFIX_NAME "ifupdown"
#define _NMLOG_DOMAIN LOGD_SETTINGS
#define _NMLOG(level, ...) \
nm_log ((level), _NMLOG_DOMAIN, NULL, NULL, \
"%s" _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
_NMLOG_PREFIX_NAME": " \
_NM_UTILS_MACRO_REST (__VA_ARGS__))
/*****************************************************************************/
static void
nm_ifupdown_connection_init (NMIfupdownConnection *connection)
{
}
NMIfupdownConnection *
nm_ifupdown_connection_new (if_block *block)
{
NMIfupdownConnection *connection;
GError *error = NULL;
g_return_val_if_fail (block != NULL, NULL);
connection = g_object_new (NM_TYPE_IFUPDOWN_CONNECTION, NULL);
/* FIXME(copy-on-write-connection): avoid modifying NMConnection instances and share them via copy-on-write. */
if (!ifupdown_update_connection_from_if_block (nm_settings_connection_get_connection (NM_SETTINGS_CONNECTION (connection)),
block,
&error)) {
_LOGW ("invalid connection read from /etc/network/interfaces: %s",
error->message);
g_object_unref (connection);
return NULL;
}
return connection;
}
static void
nm_ifupdown_connection_class_init (NMIfupdownConnectionClass *ifupdown_connection_class)
{
}

View File

@ -1,43 +0,0 @@
/* NetworkManager system settings service (ifupdown)
*
* Alexander Sack <asac@ubuntu.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2008 Canonical Ltd.
*/
#ifndef __NETWORKMANAGER_IFUPDOWN_CONNECTION_H__
#define __NETWORKMANAGER_IFUPDOWN_CONNECTION_H__
#include "settings/nm-settings-connection.h"
#include "nms-ifupdown-interface-parser.h"
#define NM_TYPE_IFUPDOWN_CONNECTION (nm_ifupdown_connection_get_type ())
#define NM_IFUPDOWN_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IFUPDOWN_CONNECTION, NMIfupdownConnection))
#define NM_IFUPDOWN_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IFUPDOWN_CONNECTION, NMIfupdownConnectionClass))
#define NM_IS_IFUPDOWN_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IFUPDOWN_CONNECTION))
#define NM_IS_IFUPDOWN_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_IFUPDOWN_CONNECTION))
#define NM_IFUPDOWN_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IFUPDOWN_CONNECTION, NMIfupdownConnectionClass))
typedef struct _NMIfupdownConnection NMIfupdownConnection;
typedef struct _NMIfupdownConnectionClass NMIfupdownConnectionClass;
GType nm_ifupdown_connection_get_type (void);
NMIfupdownConnection *nm_ifupdown_connection_new (if_block *block);
#endif /* __NETWORKMANAGER_IFUPDOWN_CONNECTION_H__ */

View File

@ -651,22 +651,21 @@ update_ip6_setting_from_if_block (NMConnection *connection,
return TRUE;
}
gboolean
ifupdown_update_connection_from_if_block (NMConnection *connection,
if_block *block,
GError **error)
NMConnection *
ifupdown_new_connection_from_if_block (if_block *block,
gboolean autoconnect,
GError **error)
{
gs_unref_object NMConnection *connection = NULL;
const char *type;
gs_free char *idstr = NULL;
gs_free char *uuid = NULL;
NMSettingConnection *s_con;
gboolean success = FALSE;
s_con = nm_connection_get_setting_connection (connection);
if (!s_con) {
s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
nm_connection_add_setting (connection, NM_SETTING (s_con));
}
connection = nm_simple_connection_new ();
s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
nm_connection_add_setting (connection, NM_SETTING (s_con));
type = _ifupdownplugin_guess_connection_type (block);
idstr = g_strconcat ("Ifupdown (", block->name, ")", NULL);
@ -678,10 +677,10 @@ ifupdown_update_connection_from_if_block (NMConnection *connection,
NM_SETTING_CONNECTION_ID, idstr,
NM_SETTING_CONNECTION_UUID, uuid,
NM_SETTING_CONNECTION_READ_ONLY, TRUE,
NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
NM_SETTING_CONNECTION_AUTOCONNECT, (gboolean) (!!autoconnect),
NULL);
_LOGI ("update_connection_setting_from_if_block: name:%s, type:%s, id:%s, uuid: %s",
_LOGD ("update_connection_setting_from_if_block: name:%s, type:%s, id:%s, uuid: %s",
block->name, type, idstr, nm_setting_connection_get_uuid (s_con));
if (nm_streq (type, NM_SETTING_WIRED_SETTING_NAME))
@ -691,13 +690,16 @@ ifupdown_update_connection_from_if_block (NMConnection *connection,
update_wireless_security_setting_from_if_block (connection, block);
}
if (ifparser_haskey (block, "inet6"))
success = update_ip6_setting_from_if_block (connection, block, error);
else
success = update_ip4_setting_from_if_block (connection, block, error);
if (ifparser_haskey (block, "inet6")) {
if (!update_ip6_setting_from_if_block (connection, block, error))
return FALSE;
} else {
if (!update_ip4_setting_from_if_block (connection, block, error))
return FALSE;
}
if (success == TRUE)
success = nm_connection_verify (connection, error);
if (!nm_connection_normalize (connection, NULL, NULL, error))
return NULL;
return success;
return g_steal_pointer (&connection);
}

View File

@ -19,16 +19,14 @@
* (C) Copyright 2008 Canonical Ltd.
*/
#ifndef __PARSER_H__
#define __PARSER_H__
#ifndef __NMS_IFUPDOWN_PARSER_H__
#define __NMS_IFUPDOWN_PARSER_H__
#include "nm-connection.h"
#include "nms-ifupdown-interface-parser.h"
gboolean
ifupdown_update_connection_from_if_block (NMConnection *connection,
if_block *block,
GError **error);
NMConnection *ifupdown_new_connection_from_if_block (if_block *block,
gboolean autoconnect,
GError **error);
#endif /* __PARSER_H__ */
#endif /* __NMS_IFUPDOWN_PARSER_H__ */

View File

@ -24,23 +24,12 @@
#include "nms-ifupdown-plugin.h"
#include <arpa/inet.h>
#include <gmodule.h>
#include "nm-setting-connection.h"
#include "nm-dbus-interface.h"
#include "settings/nm-settings-plugin.h"
#include "nm-setting-ip4-config.h"
#include "nm-setting-wireless.h"
#include "nm-setting-wired.h"
#include "nm-setting-ppp.h"
#include "nm-utils.h"
#include "nm-core-internal.h"
#include "NetworkManagerUtils.h"
#include "nm-config.h"
#include "settings/nm-settings-plugin.h"
#include "settings/nm-settings-storage.h"
#include "nms-ifupdown-interface-parser.h"
#include "nms-ifupdown-connection.h"
#include "nms-ifupdown-parser.h"
#define ENI_INTERFACES_FILE "/etc/network/interfaces"
@ -49,29 +38,36 @@
/*****************************************************************************/
typedef struct {
NMConnection *connection;
NMSettingsStorage *storage;
} StorageData;
typedef struct {
/* Stores an entry for blocks/interfaces read from /e/n/i and (if exists)
* the NMIfupdownConnection associated with the block.
* the StorageData associated with the block.
*/
GHashTable *eni_ifaces;
bool ifupdown_managed:1;
bool initialized:1;
} SettingsPluginIfupdownPrivate;
struct _SettingsPluginIfupdown {
bool already_reloaded:1;
} NMSIfupdownPluginPrivate;
struct _NMSIfupdownPlugin {
NMSettingsPlugin parent;
SettingsPluginIfupdownPrivate _priv;
NMSIfupdownPluginPrivate _priv;
};
struct _SettingsPluginIfupdownClass {
struct _NMSIfupdownPluginClass {
NMSettingsPluginClass parent;
};
G_DEFINE_TYPE (SettingsPluginIfupdown, settings_plugin_ifupdown, NM_TYPE_SETTINGS_PLUGIN)
G_DEFINE_TYPE (NMSIfupdownPlugin, nms_ifupdown_plugin, NM_TYPE_SETTINGS_PLUGIN)
#define SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE(self) _NM_GET_PRIVATE (self, SettingsPluginIfupdown, SETTINGS_IS_PLUGIN_IFUPDOWN)
#define NMS_IFUPDOWN_PLUGIN_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMSIfupdownPlugin, NMS_IS_IFUPDOWN_PLUGIN)
/*****************************************************************************/
@ -85,53 +81,143 @@ G_DEFINE_TYPE (SettingsPluginIfupdown, settings_plugin_ifupdown, NM_TYPE_SETTING
/*****************************************************************************/
static void initialize (SettingsPluginIfupdown *self);
static GHashTable *load_eni_ifaces (NMSIfupdownPlugin *self);
/*****************************************************************************/
/* Returns the plugins currently known list of connections. The returned
* list is freed by the system settings service.
*/
static GSList*
get_connections (NMSettingsPlugin *plugin)
static void
_storage_data_destroy (StorageData *sd)
{
SettingsPluginIfupdown *self = SETTINGS_PLUGIN_IFUPDOWN (plugin);
SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self);
GSList *list = NULL;
GHashTableIter iter;
void *value;
if (G_UNLIKELY (!priv->initialized))
initialize (self);
if (!priv->ifupdown_managed) {
_LOGD ("get_connections: not connections due to managed=false");
return NULL;
}
g_hash_table_iter_init (&iter, priv->eni_ifaces);
while (g_hash_table_iter_next (&iter, NULL, &value)) {
if (value)
list = g_slist_prepend (list, value);
}
_LOGD ("get_connections: %u connections", g_slist_length (list));
return list;
nm_g_object_unref (sd->connection);
nm_g_object_unref (sd->storage);
g_slice_free (StorageData, sd);
}
/*****************************************************************************/
static void
initialize (NMSIfupdownPlugin *self)
{
NMSIfupdownPluginPrivate *priv = NMS_IFUPDOWN_PLUGIN_GET_PRIVATE (self);
gboolean ifupdown_managed;
nm_assert (!priv->initialized);
priv->initialized = TRUE;
ifupdown_managed = nm_config_data_get_value_boolean (NM_CONFIG_GET_DATA_ORIG,
NM_CONFIG_KEYFILE_GROUP_IFUPDOWN,
NM_CONFIG_KEYFILE_KEY_IFUPDOWN_MANAGED,
!IFUPDOWN_UNMANAGE_WELL_KNOWN_DEFAULT);
_LOGI ("management mode: %s", ifupdown_managed ? "managed" : "unmanaged");
priv->ifupdown_managed = ifupdown_managed;
priv->eni_ifaces = load_eni_ifaces (self);
}
static void
reload_connections (NMSettingsPlugin *plugin,
NMSettingsPluginConnectionLoadCallback callback,
gpointer user_data)
{
NMSIfupdownPlugin *self = NMS_IFUPDOWN_PLUGIN (plugin);
NMSIfupdownPluginPrivate *priv = NMS_IFUPDOWN_PLUGIN_GET_PRIVATE (self);
gs_unref_hashtable GHashTable *eni_ifaces_old = NULL;
GHashTableIter iter;
StorageData *sd;
StorageData *sd2;
const char *block_name;
if (!priv->initialized)
initialize (self);
else if (!priv->already_reloaded) {
/* This is the first call to reload, but we are already initialized.
*
* This happens because during start NMSettings first queries unmanaged-specs,
* and then issues a reload call right away.
*
* On future reloads, we really want to load /e/n/i again. */
priv->already_reloaded = TRUE;
} else {
eni_ifaces_old = priv->eni_ifaces;
priv->eni_ifaces = load_eni_ifaces (self);
g_hash_table_iter_init (&iter, eni_ifaces_old);
while (g_hash_table_iter_next (&iter, (gpointer *) &block_name, (gpointer *) &sd)) {
if (!sd)
continue;
sd2 = g_hash_table_lookup (priv->eni_ifaces, block_name);
if (!sd2)
continue;
nm_assert (nm_streq (nm_settings_storage_get_uuid (sd->storage), nm_settings_storage_get_uuid (sd2->storage)));
nm_g_object_ref_set (&sd2->storage, sd->storage);
g_hash_table_iter_remove (&iter);
}
}
if (!priv->ifupdown_managed)
_LOGD ("load: no connections due to managed=false");
g_hash_table_iter_init (&iter, priv->eni_ifaces);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &sd)) {
gs_unref_object NMConnection *connection = NULL;
if (!sd)
continue;
connection = g_steal_pointer (&sd->connection);
if (!priv->ifupdown_managed)
continue;
_LOGD ("load: %s (%s)",
nm_settings_storage_get_uuid (sd->storage),
nm_connection_get_id (connection));
callback (plugin,
sd->storage,
connection,
user_data);
}
if ( eni_ifaces_old
&& priv->ifupdown_managed) {
g_hash_table_iter_init (&iter, eni_ifaces_old);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &sd)) {
if (!sd)
continue;
_LOGD ("unload: %s",
nm_settings_storage_get_uuid (sd->storage));
callback (plugin,
sd->storage,
NULL,
user_data);
}
}
}
/*****************************************************************************/
static GSList *
_unmanaged_specs (GHashTable *eni_ifaces)
{
gs_free const char **keys = NULL;
GSList *specs = NULL;
guint i, len;
keys = nm_utils_strdict_get_keys (eni_ifaces, TRUE, &len);
for (i = len; i > 0; ) {
i--;
specs = g_slist_prepend (specs, g_strdup_printf ("interface-name:=%s", keys[i]));
}
return specs;
}
/*
* Return a list of device specifications which NetworkManager should not
* manage. Returned list will be freed by the system settings service, and
* each element must be allocated using g_malloc() or its variants.
*/
static GSList*
get_unmanaged_specs (NMSettingsPlugin *plugin)
{
SettingsPluginIfupdown *self = SETTINGS_PLUGIN_IFUPDOWN (plugin);
SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self);
GSList *specs = NULL;
GHashTableIter iter;
const char *iface;
NMSIfupdownPlugin *self = NMS_IFUPDOWN_PLUGIN (plugin);
NMSIfupdownPluginPrivate *priv = NMS_IFUPDOWN_PLUGIN_GET_PRIVATE (self);
if (G_UNLIKELY (!priv->initialized))
initialize (self);
@ -142,40 +228,46 @@ get_unmanaged_specs (NMSettingsPlugin *plugin)
_LOGD ("unmanaged-specs: unmanaged devices count %u",
g_hash_table_size (priv->eni_ifaces));
g_hash_table_iter_init (&iter, priv->eni_ifaces);
while (g_hash_table_iter_next (&iter, (gpointer) &iface, NULL))
specs = g_slist_append (specs, g_strdup_printf ("interface-name:=%s", iface));
return specs;
return _unmanaged_specs (priv->eni_ifaces);
}
/*****************************************************************************/
static void
initialize (SettingsPluginIfupdown *self)
static GHashTable *
load_eni_ifaces (NMSIfupdownPlugin *self)
{
SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self);
gs_unref_hashtable GHashTable *eni_ifaces = NULL;
gs_unref_hashtable GHashTable *auto_ifaces = NULL;
nm_auto_ifparser if_parser *parser = NULL;
if_block *block;
GHashTableIter con_iter;
const char *block_name;
NMIfupdownConnection *conn;
StorageData *sd;
nm_assert (!priv->initialized);
priv->initialized = TRUE;
eni_ifaces = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) _storage_data_destroy);
parser = ifparser_parse (ENI_INTERFACES_FILE, 0);
c_list_for_each_entry (block, &parser->block_lst_head, block_lst) {
if (NM_IN_STRSET (block->type, "auto", "allow-hotplug")) {
if (NM_IN_STRSET (block->type, "auto",
"allow-hotplug")) {
if (!auto_ifaces)
auto_ifaces = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, NULL);
g_hash_table_add (auto_ifaces, g_strdup (block->name));
continue;
auto_ifaces = g_hash_table_new (nm_str_hash, g_str_equal);
g_hash_table_add (auto_ifaces, (char *) block->name);
}
}
c_list_for_each_entry (block, &parser->block_lst_head, block_lst) {
if (NM_IN_STRSET (block->type, "auto",
"allow-hotplug"))
continue;
if (nm_streq (block->type, "iface")) {
gs_free_error GError *local = NULL;
gs_unref_object NMConnection *connection = NULL;
gs_unref_object NMSettingsStorage *storage = NULL;
const char *uuid = NULL;
StorageData *sd_repl;
/* Bridge configuration */
if (g_str_has_prefix (block->name, "br")) {
/* Try to find bridge ports */
@ -208,13 +300,13 @@ initialize (SettingsPluginIfupdown *self)
if (nm_streq (token, "none"))
continue;
if (state == 0) {
conn = g_hash_table_lookup (priv->eni_ifaces, block->name);
if (!conn) {
sd = g_hash_table_lookup (eni_ifaces, block->name);
if (!sd) {
_LOGD ("parse: adding bridge port \"%s\"", token);
g_hash_table_insert (priv->eni_ifaces, g_strdup (token), NULL);
g_hash_table_insert (eni_ifaces, g_strdup (token), NULL);
} else {
_LOGD ("parse: adding bridge port \"%s\" (have connection %s)", token,
nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (conn)));
nm_settings_storage_get_uuid (sd->storage));
}
}
}
@ -226,106 +318,91 @@ initialize (SettingsPluginIfupdown *self)
if (nm_streq (block->name, "lo"))
continue;
/* Remove any connection for this block that was previously found */
conn = g_hash_table_lookup (priv->eni_ifaces, block->name);
if (conn) {
sd_repl = g_hash_table_lookup (eni_ifaces, block->name);
if (sd_repl) {
storage = g_steal_pointer (&sd_repl->storage);
_LOGD ("parse: replace connection \"%s\" (%s)",
block->name,
nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (conn)));
nm_settings_connection_delete (NM_SETTINGS_CONNECTION (conn), NULL);
g_hash_table_remove (priv->eni_ifaces, block->name);
nm_settings_storage_get_uuid (sd_repl->storage));
g_hash_table_remove (eni_ifaces, block->name);
}
/* add the new connection */
conn = nm_ifupdown_connection_new (block);
if (conn) {
_LOGD ("parse: adding connection \"%s\" (%s)", block->name,
nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (conn)));
} else
_LOGD ("parse: adding place holder for connection \"%s\"", block->name);
g_hash_table_insert (priv->eni_ifaces, g_strdup (block->name), conn);
connection = ifupdown_new_connection_from_if_block (block,
auto_ifaces
&& g_hash_table_contains (auto_ifaces, block->name),
&local);
if (!connection) {
_LOGD ("parse: adding place holder for \"%s\"%s%s%s",
block->name,
NM_PRINT_FMT_QUOTED (local, " (", local->message, ")", ""));
sd = NULL;
} else {
nmtst_connection_assert_unchanging (connection);
uuid = nm_connection_get_uuid (connection);
if (!storage)
storage = nm_settings_storage_new (NM_SETTINGS_PLUGIN (self), uuid, NULL);
sd = g_slice_new (StorageData);
*sd = (StorageData) {
.connection = g_steal_pointer (&connection),
.storage = g_steal_pointer (&storage),
};
_LOGD ("parse: adding connection \"%s\" (%s)", block->name, uuid);
}
g_hash_table_replace (eni_ifaces, g_strdup (block->name), sd);
continue;
}
if (nm_streq (block->type, "mapping")) {
conn = g_hash_table_lookup (priv->eni_ifaces, block->name);
if (!conn) {
sd = g_hash_table_lookup (eni_ifaces, block->name);
if (!sd) {
_LOGD ("parse: adding mapping \"%s\"", block->name);
g_hash_table_insert (priv->eni_ifaces, g_strdup (block->name), NULL);
g_hash_table_insert (eni_ifaces, g_strdup (block->name), NULL);
} else {
_LOGD ("parse: adding mapping \"%s\" (have connection %s)", block->name,
nm_settings_connection_get_uuid (NM_SETTINGS_CONNECTION (conn)));
nm_settings_storage_get_uuid (sd->storage));
}
continue;
}
}
/* Make 'auto' interfaces autoconnect=TRUE */
g_hash_table_iter_init (&con_iter, priv->eni_ifaces);
while (g_hash_table_iter_next (&con_iter, (gpointer) &block_name, (gpointer) &conn)) {
NMSettingConnection *setting;
nm_clear_pointer (&auto_ifaces, g_hash_table_destroy);
if ( !conn
|| !auto_ifaces
|| !g_hash_table_contains (auto_ifaces, block_name))
continue;
/* FIXME(copy-on-write-connection): avoid modifying NMConnection instances and share them via copy-on-write. */
setting = nm_connection_get_setting_connection (nm_settings_connection_get_connection (NM_SETTINGS_CONNECTION (conn)));
g_object_set (setting, NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NULL);
}
/* Check the config file to find out whether to manage interfaces */
priv->ifupdown_managed = nm_config_data_get_value_boolean (NM_CONFIG_GET_DATA_ORIG,
NM_CONFIG_KEYFILE_GROUP_IFUPDOWN,
NM_CONFIG_KEYFILE_KEY_IFUPDOWN_MANAGED,
!IFUPDOWN_UNMANAGE_WELL_KNOWN_DEFAULT);
_LOGI ("management mode: %s", priv->ifupdown_managed ? "managed" : "unmanaged");
/* Now if we're running in managed mode, let NM know there are new connections */
if (priv->ifupdown_managed) {
GHashTableIter iter;
g_hash_table_iter_init (&iter, priv->eni_ifaces);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &conn)) {
if (conn) {
_nm_settings_plugin_emit_signal_connection_added (NM_SETTINGS_PLUGIN (self),
NM_SETTINGS_CONNECTION (conn));
}
}
}
return g_steal_pointer (&eni_ifaces);
}
/*****************************************************************************/
static void
settings_plugin_ifupdown_init (SettingsPluginIfupdown *self)
nms_ifupdown_plugin_init (NMSIfupdownPlugin *self)
{
SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (self);
priv->eni_ifaces = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_object_unref);
}
static void
dispose (GObject *object)
{
SettingsPluginIfupdown *plugin = SETTINGS_PLUGIN_IFUPDOWN (object);
SettingsPluginIfupdownPrivate *priv = SETTINGS_PLUGIN_IFUPDOWN_GET_PRIVATE (plugin);
NMSIfupdownPlugin *plugin = NMS_IFUPDOWN_PLUGIN (object);
NMSIfupdownPluginPrivate *priv = NMS_IFUPDOWN_PLUGIN_GET_PRIVATE (plugin);
g_clear_pointer (&priv->eni_ifaces, g_hash_table_destroy);
G_OBJECT_CLASS (settings_plugin_ifupdown_parent_class)->dispose (object);
G_OBJECT_CLASS (nms_ifupdown_plugin_parent_class)->dispose (object);
}
static void
settings_plugin_ifupdown_class_init (SettingsPluginIfupdownClass *klass)
nms_ifupdown_plugin_class_init (NMSIfupdownPluginClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMSettingsPluginClass *plugin_class = NM_SETTINGS_PLUGIN_CLASS (klass);
object_class->dispose = dispose;
plugin_class->get_connections = get_connections;
plugin_class->plugin_name = "ifupdown";
plugin_class->reload_connections = reload_connections;
plugin_class->get_unmanaged_specs = get_unmanaged_specs;
}
@ -334,5 +411,5 @@ settings_plugin_ifupdown_class_init (SettingsPluginIfupdownClass *klass)
G_MODULE_EXPORT NMSettingsPlugin *
nm_settings_plugin_factory (void)
{
return g_object_new (SETTINGS_TYPE_PLUGIN_IFUPDOWN, NULL);
return g_object_new (NMS_TYPE_IFUPDOWN_PLUGIN, NULL);
}

View File

@ -19,21 +19,21 @@
* (C) Copyright 2008 Canonical Ltd.
*/
#ifndef _PLUGIN_H_
#define _PLUGIN_H_
#ifndef __NMS_IFUPDOWN_PLUGIN_H__
#define __NMS_IFUPDOWN_PLUGIN_H__
#define PLUGIN_NAME "ifupdown"
#define SETTINGS_TYPE_PLUGIN_IFUPDOWN (settings_plugin_ifupdown_get_type ())
#define SETTINGS_PLUGIN_IFUPDOWN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SETTINGS_TYPE_PLUGIN_IFUPDOWN, SettingsPluginIfupdown))
#define SETTINGS_PLUGIN_IFUPDOWN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SETTINGS_TYPE_PLUGIN_IFUPDOWN, SettingsPluginIfupdownClass))
#define SETTINGS_IS_PLUGIN_IFUPDOWN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SETTINGS_TYPE_PLUGIN_IFUPDOWN))
#define SETTINGS_IS_PLUGIN_IFUPDOWN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SETTINGS_TYPE_PLUGIN_IFUPDOWN))
#define SETTINGS_PLUGIN_IFUPDOWN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SETTINGS_TYPE_PLUGIN_IFUPDOWN, SettingsPluginIfupdownClass))
#define NMS_TYPE_IFUPDOWN_PLUGIN (nms_ifupdown_plugin_get_type ())
#define NMS_IFUPDOWN_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMS_TYPE_IFUPDOWN_PLUGIN, NMSIfupdownPlugin))
#define NMS_IFUPDOWN_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMS_TYPE_IFUPDOWN_PLUGIN, NMSIfupdownPluginClass))
#define NMS_IS_IFUPDOWN_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMS_TYPE_IFUPDOWN_PLUGIN))
#define NMS_IS_IFUPDOWN_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMS_TYPE_IFUPDOWN_PLUGIN))
#define NMS_IFUPDOWN_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMS_TYPE_IFUPDOWN_PLUGIN, NMSIfupdownPluginClass))
typedef struct _SettingsPluginIfupdown SettingsPluginIfupdown;
typedef struct _SettingsPluginIfupdownClass SettingsPluginIfupdownClass;
typedef struct _NMSIfupdownPlugin NMSIfupdownPlugin;
typedef struct _NMSIfupdownPluginClass NMSIfupdownPluginClass;
GType settings_plugin_ifupdown_get_type (void);
GType nms_ifupdown_plugin_get_type (void);
#endif /* _PLUGIN_H_ */
#endif /* __NMS_IFUPDOWN_PLUGIN_H__ */

View File

@ -30,6 +30,29 @@
/*****************************************************************************/
#define _connection_from_if_block(block) \
({ \
NMConnection *_con; \
if_block *_block = (block); \
GError *_local = NULL; \
\
g_assert (_block); \
_con = ifupdown_new_connection_from_if_block (_block, FALSE, &_local); \
nmtst_assert_success (NM_IS_CONNECTION (_con), _local); \
nmtst_assert_connection_verifies_without_normalization (_con); \
_con; \
})
#define _connection_first_from_parser(parser) \
({ \
if_parser *_parser = (parser); \
\
g_assert (_parser); \
_connection_from_if_block (ifparser_getfirst (_parser)); \
})
/*****************************************************************************/
typedef struct {
char *key;
char *data;
@ -452,26 +475,14 @@ test16_missing_newline (void)
static void
test17_read_static_ipv4 (void)
{
NMConnection *connection;
gs_unref_object NMConnection *connection = NULL;
NMSettingConnection *s_con;
NMSettingIPConfig *s_ip4;
NMSettingWired *s_wired;
GError *error = NULL;
gboolean success;
NMIPAddress *ip4_addr;
if_block *block = NULL;
nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test17-wired-static-verify-ip4");
block = ifparser_getfirst (parser);
connection = nm_simple_connection_new();
g_assert (connection);
ifupdown_update_connection_from_if_block (connection, block, &error);
g_assert_no_error (error);
success = nm_connection_verify (connection, &error);
g_assert_no_error (error);
g_assert (success);
connection = _connection_first_from_parser (parser);
/* ===== CONNECTION SETTING ===== */
s_con = nm_connection_get_setting_connection (connection);
@ -500,32 +511,19 @@ test17_read_static_ipv4 (void)
g_assert_cmpint (nm_setting_ip_config_get_num_dns_searches (s_ip4), ==, 2);
g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip4, 0), ==, "example.com");
g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip4, 1), ==, "foo.example.com");
g_object_unref (connection);
}
static void
test18_read_static_ipv6 (void)
{
NMConnection *connection;
gs_unref_object NMConnection *connection = NULL;
NMSettingConnection *s_con;
NMSettingIPConfig *s_ip6;
NMSettingWired *s_wired;
GError *error = NULL;
gboolean success;
NMIPAddress *ip6_addr;
if_block *block = NULL;
nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test18-wired-static-verify-ip6");
block = ifparser_getfirst (parser);
connection = nm_simple_connection_new();
g_assert (connection);
ifupdown_update_connection_from_if_block (connection, block, &error);
g_assert_no_error (error);
success = nm_connection_verify (connection, &error);
g_assert_no_error (error);
g_assert (success);
connection = _connection_first_from_parser (parser);
/* ===== CONNECTION SETTING ===== */
s_con = nm_connection_get_setting_connection (connection);
@ -554,30 +552,17 @@ test18_read_static_ipv6 (void)
g_assert_cmpint (nm_setting_ip_config_get_num_dns_searches (s_ip6), ==, 2);
g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip6, 0), ==, "example.com");
g_assert_cmpstr (nm_setting_ip_config_get_dns_search (s_ip6, 1), ==, "foo.example.com");
g_object_unref (connection);
}
static void
test19_read_static_ipv4_plen (void)
{
NMConnection *connection;
gs_unref_object NMConnection *connection = NULL;
NMSettingIPConfig *s_ip4;
GError *error = NULL;
NMIPAddress *ip4_addr;
if_block *block = NULL;
gboolean success;
nm_auto_ifparser if_parser *parser = init_ifparser_with_file ("test19-wired-static-verify-ip4-plen");
block = ifparser_getfirst (parser);
connection = nm_simple_connection_new();
g_assert (connection);
ifupdown_update_connection_from_if_block (connection, block, &error);
g_assert_no_error (error);
success = nm_connection_verify (connection, &error);
g_assert_no_error (error);
g_assert (success);
connection = _connection_first_from_parser (parser);
/* ===== IPv4 SETTING ===== */
s_ip4 = nm_connection_get_setting_ip4_config (connection);
@ -588,8 +573,6 @@ test19_read_static_ipv4_plen (void)
g_assert (ip4_addr != NULL);
g_assert_cmpstr (nm_ip_address_get_address (ip4_addr), ==, "10.0.0.3");
g_assert_cmpint (nm_ip_address_get_prefix (ip4_addr), ==, 8);
g_object_unref (connection);
}
static void
@ -670,4 +653,3 @@ main (int argc, char **argv)
return g_test_run ();
}

View File

@ -1,187 +0,0 @@
/* NetworkManager system settings service - keyfile plugin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 Novell, Inc.
* Copyright (C) 2008 - 2012 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nms-keyfile-connection.h"
#include <glib/gstdio.h>
#include "nm-dbus-interface.h"
#include "nm-setting-connection.h"
#include "nm-utils.h"
#include "settings/nm-settings-plugin.h"
#include "nms-keyfile-reader.h"
#include "nms-keyfile-writer.h"
#include "nms-keyfile-utils.h"
/*****************************************************************************/
struct _NMSKeyfileConnection {
NMSettingsConnection parent;
};
struct _NMSKeyfileConnectionClass {
NMSettingsConnectionClass parent;
};
G_DEFINE_TYPE (NMSKeyfileConnection, nms_keyfile_connection, NM_TYPE_SETTINGS_CONNECTION)
/*****************************************************************************/
static gboolean
commit_changes (NMSettingsConnection *connection,
NMConnection *new_connection,
NMSettingsConnectionCommitReason commit_reason,
NMConnection **out_reread_connection,
char **out_logmsg_change,
GError **error)
{
gs_free char *path = NULL;
gs_unref_object NMConnection *reread = NULL;
gboolean reread_same = FALSE;
nm_assert (out_reread_connection && !*out_reread_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),
NULL,
NULL,
&path,
&reread,
&reread_same,
error))
return FALSE;
if (!nm_streq0 (path, nm_settings_connection_get_filename (connection))) {
gs_free char *old_path = g_strdup (nm_settings_connection_get_filename (connection));
nm_settings_connection_set_filename (connection, path);
if (old_path) {
NM_SET_OUT (out_logmsg_change,
g_strdup_printf ("keyfile: update "NMS_KEYFILE_CONNECTION_LOG_FMT" and rename from \"%s\"",
NMS_KEYFILE_CONNECTION_LOG_ARG (connection),
old_path));
} else {
NM_SET_OUT (out_logmsg_change,
g_strdup_printf ("keyfile: update "NMS_KEYFILE_CONNECTION_LOG_FMT" and persist connection",
NMS_KEYFILE_CONNECTION_LOG_ARG (connection)));
}
} else {
NM_SET_OUT (out_logmsg_change,
g_strdup_printf ("keyfile: update "NMS_KEYFILE_CONNECTION_LOG_FMT,
NMS_KEYFILE_CONNECTION_LOG_ARG (connection)));
}
if (reread && !reread_same)
*out_reread_connection = g_steal_pointer (&reread);
return TRUE;
}
static gboolean
delete (NMSettingsConnection *connection,
GError **error)
{
const char *path;
path = nm_settings_connection_get_filename (connection);
if (path)
g_unlink (path);
return TRUE;
}
/*****************************************************************************/
static void
nms_keyfile_connection_init (NMSKeyfileConnection *connection)
{
}
NMSKeyfileConnection *
nms_keyfile_connection_new (NMConnection *source,
const char *full_path,
const char *profile_dir,
GError **error)
{
GObject *object;
NMConnection *tmp;
const char *uuid;
gboolean update_unsaved = TRUE;
nm_assert (source || full_path);
nm_assert (!full_path || full_path[0] == '/');
nm_assert (!profile_dir || profile_dir[0] == '/');
/* If we're given a connection already, prefer that instead of re-reading */
if (source)
tmp = g_object_ref (source);
else {
tmp = nms_keyfile_reader_from_file (full_path, profile_dir, error);
if (!tmp)
return NULL;
uuid = nm_connection_get_uuid (tmp);
if (!uuid) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Connection in file %s had no UUID", full_path);
g_object_unref (tmp);
return NULL;
}
/* If we just read the connection from disk, it's clearly not Unsaved */
update_unsaved = FALSE;
}
object = g_object_new (NMS_TYPE_KEYFILE_CONNECTION,
NM_SETTINGS_CONNECTION_FILENAME, full_path,
NULL);
/* Update our settings with what was read from the file */
if (!nm_settings_connection_update (NM_SETTINGS_CONNECTION (object),
tmp,
update_unsaved
? NM_SETTINGS_CONNECTION_PERSIST_MODE_UNSAVED
: NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP_SAVED,
NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE,
NULL,
error)) {
g_object_unref (object);
object = NULL;
}
g_object_unref (tmp);
return (NMSKeyfileConnection *) object;
}
static void
nms_keyfile_connection_class_init (NMSKeyfileConnectionClass *keyfile_connection_class)
{
NMSettingsConnectionClass *settings_class = NM_SETTINGS_CONNECTION_CLASS (keyfile_connection_class);
settings_class->commit_changes = commit_changes;
settings_class->delete = delete;
}

View File

@ -1,43 +0,0 @@
/* NetworkManager system settings service - keyfile plugin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 Novell, Inc.
* Copyright (C) 2008 - 2012 Red Hat, Inc.
*/
#ifndef __NMS_KEYFILE_CONNECTION_H__
#define __NMS_KEYFILE_CONNECTION_H__
#include "settings/nm-settings-connection.h"
#define NMS_TYPE_KEYFILE_CONNECTION (nms_keyfile_connection_get_type ())
#define NMS_KEYFILE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMS_TYPE_KEYFILE_CONNECTION, NMSKeyfileConnection))
#define NMS_KEYFILE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMS_TYPE_KEYFILE_CONNECTION, NMSKeyfileConnectionClass))
#define NMS_IS_KEYFILE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMS_TYPE_KEYFILE_CONNECTION))
#define NMS_IS_KEYFILE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMS_TYPE_KEYFILE_CONNECTION))
#define NMS_KEYFILE_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMS_TYPE_KEYFILE_CONNECTION, NMSKeyfileConnectionClass))
typedef struct _NMSKeyfileConnection NMSKeyfileConnection;
typedef struct _NMSKeyfileConnectionClass NMSKeyfileConnectionClass;
GType nms_keyfile_connection_get_type (void);
NMSKeyfileConnection *nms_keyfile_connection_new (NMConnection *source,
const char *full_path,
const char *profile_dir,
GError **error);
#endif /* __NMS_KEYFILE_CONNECTION_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,11 @@
#ifndef __NMS_KEYFILE_PLUGIN_H__
#define __NMS_KEYFILE_PLUGIN_H__
#include "settings/nm-settings-plugin.h"
#include "settings/nm-settings-storage.h"
#include "nms-keyfile-utils.h"
#define NMS_TYPE_KEYFILE_PLUGIN (nms_keyfile_plugin_get_type ())
#define NMS_KEYFILE_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMS_TYPE_KEYFILE_PLUGIN, NMSKeyfilePlugin))
#define NMS_KEYFILE_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMS_TYPE_KEYFILE_PLUGIN, NMSKeyfilePluginClass))
@ -35,4 +40,31 @@ GType nms_keyfile_plugin_get_type (void);
NMSKeyfilePlugin *nms_keyfile_plugin_new (void);
gboolean nms_keyfile_plugin_add_connection (NMSKeyfilePlugin *self,
NMConnection *connection,
gboolean is_nm_generated,
gboolean is_volatile,
gboolean in_memory,
NMSettingsStorage **out_storage,
NMConnection **out_connection,
GError **error);
gboolean nms_keyfile_plugin_update_connection (NMSKeyfilePlugin *self,
NMSettingsStorage *storage,
NMConnection *connection,
gboolean is_nm_generated,
gboolean is_volatile,
gboolean force_rename,
NMSettingsStorage **out_storage,
NMConnection **out_connection,
GError **error);
gboolean nms_keyfile_plugin_set_nmmeta_tombstone (NMSKeyfilePlugin *self,
gboolean simulate,
const char *uuid,
gboolean in_memory,
gboolean set,
NMSettingsStorage **out_storage,
gboolean *out_hard_failure);
#endif /* __NMS_KEYFILE_PLUGIN_H__ */

View File

@ -161,6 +161,9 @@ nms_keyfile_reader_from_keyfile (GKeyFile *key_file,
NMConnection *
nms_keyfile_reader_from_file (const char *full_filename,
const char *profile_dir,
struct stat *out_stat,
NMTernary *out_is_nm_generated,
NMTernary *out_is_volatile,
GError **error)
{
gs_unref_keyfile GKeyFile *key_file = NULL;
@ -170,9 +173,12 @@ nms_keyfile_reader_from_file (const char *full_filename,
nm_assert (full_filename && full_filename[0] == '/');
nm_assert (!profile_dir || profile_dir[0] == '/');
NM_SET_OUT (out_is_nm_generated, NM_TERNARY_DEFAULT);
NM_SET_OUT (out_is_volatile, NM_TERNARY_DEFAULT);
if (!nms_keyfile_utils_check_file_permissions (NMS_KEYFILE_FILETYPE_KEYFILE,
full_filename,
NULL,
out_stat,
error))
return NULL;
@ -194,6 +200,16 @@ nms_keyfile_reader_from_file (const char *full_filename,
connection = NULL;
}
NM_SET_OUT (out_is_nm_generated, nm_key_file_get_boolean (key_file,
NM_KEYFILE_GROUP_NMMETA,
NM_KEYFILE_KEY_NMMETA_NM_GENERATED,
NM_TERNARY_DEFAULT));
NM_SET_OUT (out_is_volatile, nm_key_file_get_boolean (key_file,
NM_KEYFILE_GROUP_NMMETA,
NM_KEYFILE_KEY_NMMETA_VOLATILE,
NM_TERNARY_DEFAULT));
return connection;
}

View File

@ -30,8 +30,13 @@ NMConnection *nms_keyfile_reader_from_keyfile (GKeyFile *key_file,
gboolean verbose,
GError **error);
struct stat;
NMConnection *nms_keyfile_reader_from_file (const char *full_filename,
const char *profile_dir,
struct stat *out_stat,
NMTernary *out_is_nm_generated,
NMTernary *out_is_volatile,
GError **error);
#endif /* __NMS_KEYFILE_READER_H__ */

View File

@ -0,0 +1,236 @@
/* NetworkManager system settings service - keyfile plugin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2018 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nms-keyfile-storage.h"
#include "nm-utils.h"
#include "nm-core-internal.h"
#include "nms-keyfile-plugin.h"
/*****************************************************************************/
struct _NMSKeyfileStorageClass {
NMSettingsStorageClass parent;
};
G_DEFINE_TYPE (NMSKeyfileStorage, nms_keyfile_storage, NM_TYPE_SETTINGS_STORAGE)
/*****************************************************************************/
void
nms_keyfile_storage_copy_content (NMSKeyfileStorage *dst,
const NMSKeyfileStorage *src)
{
nm_assert (src != dst);
nm_assert (nm_streq (nms_keyfile_storage_get_uuid (dst), nms_keyfile_storage_get_uuid (src)));
nm_assert (nms_keyfile_storage_get_filename (dst) && nm_streq (nms_keyfile_storage_get_filename (dst), nms_keyfile_storage_get_filename (src)));
nm_g_object_ref_set (&dst->connection, src->connection);
dst->storage_type = src->storage_type;
dst->stat_mtime = src->stat_mtime;
dst->is_nm_generated = src->is_nm_generated;
dst->is_volatile = src->is_volatile;
dst->is_tombstone = src->is_tombstone;
}
NMConnection *
nms_keyfile_storage_steal_connection (NMSKeyfileStorage *self)
{
nm_assert (NMS_IS_KEYFILE_STORAGE (self));
nm_assert (NM_IS_CONNECTION (self->connection));
return g_steal_pointer (&self->connection);
}
/*****************************************************************************/
static int
cmp_fcn (const NMSKeyfileStorage *a,
const NMSKeyfileStorage *b)
{
nm_assert (NMS_IS_KEYFILE_STORAGE (a));
nm_assert (NMS_IS_KEYFILE_STORAGE (b));
nm_assert (a != b);
/* sort by storage-type, which also has a numeric value according to their
* (inverse) priority. */
NM_CMP_FIELD_UNSAFE (b, a, storage_type);
/* tombstones are more important. */
nm_assert (a->is_tombstone == nm_settings_storage_is_keyfile_tombstone (NM_SETTINGS_STORAGE (a)));
nm_assert (b->is_tombstone == nm_settings_storage_is_keyfile_tombstone (NM_SETTINGS_STORAGE (b)));
NM_CMP_FIELD_UNSAFE (a, b, is_tombstone);
/* newer files are more important. */
NM_CMP_FIELD (b, a, stat_mtime.tv_sec);
NM_CMP_FIELD (b, a, stat_mtime.tv_nsec);
NM_CMP_DIRECT_STRCMP (nms_keyfile_storage_get_filename (a), nms_keyfile_storage_get_filename (b));
return 0;
}
/*****************************************************************************/
static void
nms_keyfile_storage_init (NMSKeyfileStorage *self)
{
}
static NMSKeyfileStorage *
_storage_new (NMSKeyfilePlugin *plugin,
const char *uuid,
const char *filename)
{
nm_assert (NMS_IS_KEYFILE_PLUGIN (plugin));
nm_assert (nm_utils_is_uuid (uuid));
nm_assert (filename && filename[0] == '/');
return g_object_new (NMS_TYPE_KEYFILE_STORAGE,
NM_SETTINGS_STORAGE_PLUGIN, plugin,
NM_SETTINGS_STORAGE_UUID, uuid,
NM_SETTINGS_STORAGE_FILENAME, filename,
NULL);
}
NMSKeyfileStorage *
nms_keyfile_storage_new_tombstone (NMSKeyfilePlugin *plugin,
const char *uuid,
const char *filename,
NMSKeyfileStorageType storage_type)
{
NMSKeyfileStorage *self;
nm_assert (nm_utils_is_uuid (uuid));
nm_assert (filename && filename[0] == '/');
nm_assert (nms_keyfile_nmmeta_check_filename (filename, NULL));
nm_assert (NM_IN_SET (storage_type, NMS_KEYFILE_STORAGE_TYPE_ETC,
NMS_KEYFILE_STORAGE_TYPE_RUN));
self = _storage_new (plugin, uuid, filename);
self->is_tombstone = TRUE;
self->storage_type = storage_type;
return self;
}
NMSKeyfileStorage *
nms_keyfile_storage_new_connection (NMSKeyfilePlugin *plugin,
NMConnection *connection_take /* pass reference */,
const char *filename,
NMSKeyfileStorageType storage_type,
NMTernary is_nm_generated_opt,
NMTernary is_volatile_opt,
const struct timespec *stat_mtime)
{
NMSKeyfileStorage *self;
nm_assert (NMS_IS_KEYFILE_PLUGIN (plugin));
nm_assert (NM_IS_CONNECTION (connection_take));
nm_assert (_nm_connection_verify (connection_take, NULL) == NM_SETTING_VERIFY_SUCCESS);
nm_assert (filename && filename[0] == '/');
nm_assert ( storage_type >= NMS_KEYFILE_STORAGE_TYPE_RUN
&& storage_type <= _NMS_KEYFILE_STORAGE_TYPE_LIB_LAST);
nmtst_connection_assert_unchanging (connection_take);
self = _storage_new (plugin, nm_connection_get_uuid (connection_take), filename);
self->connection = connection_take; /* take reference. */
if (storage_type == NMS_KEYFILE_STORAGE_TYPE_RUN) {
self->is_nm_generated = (is_nm_generated_opt == NM_TERNARY_TRUE);
self->is_volatile = (is_volatile_opt == NM_TERNARY_TRUE);
}
if (stat_mtime)
self->stat_mtime = *stat_mtime;
self->storage_type = storage_type;
return self;
}
static void
_storage_clear (NMSKeyfileStorage *self)
{
c_list_unlink (&self->parent._storage_lst);
c_list_unlink (&self->parent._storage_by_uuid_lst);
g_clear_object (&self->connection);
}
static void
dispose (GObject *object)
{
NMSKeyfileStorage *self = NMS_KEYFILE_STORAGE (object);
_storage_clear (self);
G_OBJECT_CLASS (nms_keyfile_storage_parent_class)->dispose (object);
}
void
nms_keyfile_storage_destroy (NMSKeyfileStorage *self)
{
_storage_clear (self);
g_object_unref (self);
}
static void
nms_keyfile_storage_class_init (NMSKeyfileStorageClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
NMSettingsStorageClass *storage_class = NM_SETTINGS_STORAGE_CLASS (klass);
object_class->dispose = dispose;
storage_class->cmp_fcn = (int (*) (NMSettingsStorage *, NMSettingsStorage *)) cmp_fcn;
}
/*****************************************************************************/
#include "settings/nm-settings-connection.h"
void
nm_settings_storage_load_sett_flags (NMSettingsStorage *self,
NMSettingsConnectionIntFlags *sett_flags,
NMSettingsConnectionIntFlags *sett_mask)
{
NMSKeyfileStorage *s;
*sett_flags = NM_SETTINGS_CONNECTION_INT_FLAGS_NONE;
*sett_mask = NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED
| NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE;
if (!NMS_IS_KEYFILE_STORAGE (self))
return;
s = NMS_KEYFILE_STORAGE (self);
if (s->storage_type != NMS_KEYFILE_STORAGE_TYPE_RUN)
return;
if (s->is_nm_generated)
*sett_flags |= NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED;
if (s->is_volatile)
*sett_flags |= NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE;
}

View File

@ -0,0 +1,157 @@
/* NetworkManager system settings service - keyfile plugin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2018 Red Hat, Inc.
*/
#ifndef __NMS_KEYFILE_STORAGE_H__
#define __NMS_KEYFILE_STORAGE_H__
#include "c-list/src/c-list.h"
#include "settings/nm-settings-storage.h"
#include "nms-keyfile-utils.h"
/*****************************************************************************/
#define NMS_TYPE_KEYFILE_STORAGE (nms_keyfile_storage_get_type ())
#define NMS_KEYFILE_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NMS_TYPE_KEYFILE_STORAGE, NMSKeyfileStorage))
#define NMS_KEYFILE_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NMS_TYPE_KEYFILE_STORAGE, NMSKeyfileStorageClass))
#define NMS_IS_KEYFILE_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NMS_TYPE_KEYFILE_STORAGE))
#define NMS_IS_KEYFILE_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NMS_TYPE_KEYFILE_STORAGE))
#define NMS_KEYFILE_STORAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NMS_TYPE_KEYFILE_STORAGE, NMSKeyfileStorageClass))
typedef struct {
NMSettingsStorage parent;
/* The connection. Note that there are tombstones (loaded-uuid files to /dev/null)
* that don't have a connection.
*
* Also, we don't actually remember the loaded connection after returning it
* to NMSettings. So, also for regular storages (non-tombstones) this field
* is often cleared. */
NMConnection *connection;
NMSKeyfileStorageType storage_type;
/* the timestamp (stat's mtime) of the keyfile. For tombstones this
* is irrelevant. The purpose is that if the same storage type (directory) has
* multiple files with the same UUID, then the newer file gets preferred. */
struct timespec stat_mtime;
/* these flags are only relevant for storages with %NMS_KEYFILE_STORAGE_TYPE_RUN
* (and non-tombstones). This is to persist and reload these settings flags to
* /run. */
bool is_nm_generated:1;
bool is_volatile:1;
/* whether this is a tombstone to hide a UUID (via the loaded uuid symlinks).
* If this is falls, the storage contains a profile, though note that
* the connection field will be cleared when it's not used. So, a non-tombstone
* has a connection in principle, but the connection field may still be %NULL.
*
* Note that a tombstone instance doesn't have a connection, but NMSettings
* considers it alive because is_tombstone is %TRUE. That means, once a tombstone
* gets removed, this flag is cleared. Then the storage instance has no connnection
* and is no longer a tombstone, and NMSettings considers it ready for deletion.
*/
bool is_tombstone:1;
/* this flag is only used during reload to mark and prune old entries. */
bool dirty:1;
} NMSKeyfileStorage;
typedef struct _NMSKeyfileStorageClass NMSKeyfileStorageClass;
GType nms_keyfile_storage_get_type (void);
struct _NMSKeyfilePlugin;
NMSKeyfileStorage *nms_keyfile_storage_new_tombstone (struct _NMSKeyfilePlugin *self,
const char *uuid,
const char *filename,
NMSKeyfileStorageType storage_type);
NMSKeyfileStorage *nms_keyfile_storage_new_connection (struct _NMSKeyfilePlugin *self,
NMConnection *connection_take /* pass reference */,
const char *filename,
NMSKeyfileStorageType storage_type,
NMTernary is_nm_generated_opt,
NMTernary is_volatile_opt,
const struct timespec *stat_mtime);
void nms_keyfile_storage_destroy (NMSKeyfileStorage *storage);
/*****************************************************************************/
void nms_keyfile_storage_copy_content (NMSKeyfileStorage *dst,
const NMSKeyfileStorage *src);
NMConnection *nms_keyfile_storage_steal_connection (NMSKeyfileStorage *storage);
/*****************************************************************************/
static inline const char *
nms_keyfile_storage_get_uuid (const NMSKeyfileStorage *self)
{
return nm_settings_storage_get_uuid ((const NMSettingsStorage *) self);
}
static inline const char *
nms_keyfile_storage_get_filename (const NMSKeyfileStorage *self)
{
return nm_settings_storage_get_filename ((const NMSettingsStorage *) self);
}
/*****************************************************************************/
static inline gboolean
nm_settings_storage_is_keyfile_run (const NMSettingsStorage *self)
{
return NMS_IS_KEYFILE_STORAGE (self)
&& (((NMSKeyfileStorage *) self)->storage_type == NMS_KEYFILE_STORAGE_TYPE_RUN);
}
static inline gboolean
nm_settings_storage_is_keyfile_lib (const NMSettingsStorage *self)
{
return NMS_IS_KEYFILE_STORAGE (self)
&& (((NMSKeyfileStorage *) self)->storage_type >= NMS_KEYFILE_STORAGE_TYPE_LIB_BASE);
}
static inline gboolean
nm_settings_storage_is_keyfile_tombstone (const NMSettingsStorage *self)
{
/* Only keyfile storage supports tombstones. They indicate that a uuid
* is shadowed via a symlink to /dev/null.
*
* Note that tombstones don't have a NMConnection instead they shadow
* a UUID. As such, NMSettings considers them alive also if they have
* not profile. That means, when a tombstone gets removed for good,
* the is_tombstone must be cleared (so that it becomes truly dead). */
return NMS_IS_KEYFILE_STORAGE (self)
&& ((NMSKeyfileStorage *) self)->is_tombstone;
}
/*****************************************************************************/
enum _NMSettingsConnectionIntFlags;
void nm_settings_storage_load_sett_flags (NMSettingsStorage *self,
enum _NMSettingsConnectionIntFlags *sett_flags,
enum _NMSettingsConnectionIntFlags *sett_mask);
#endif /* __NMS_KEYFILE_STORAGE_H__ */

View File

@ -14,7 +14,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2010 Red Hat, Inc.
* (C) Copyright 2010 - 2018 Red Hat, Inc.
*/
#include "nm-default.h"
@ -305,22 +305,3 @@ nms_keyfile_utils_check_file_permissions (NMSKeyfileFiletype filetype,
NM_SET_OUT (out_st, st);
return TRUE;
}
/*****************************************************************************/
const char *
nms_keyfile_utils_get_path (void)
{
static char *path = NULL;
if (G_UNLIKELY (!path)) {
path = nm_config_data_get_value (NM_CONFIG_GET_DATA_ORIG,
NM_CONFIG_KEYFILE_GROUP_KEYFILE,
NM_CONFIG_KEYFILE_KEY_KEYFILE_PATH,
NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY);
if (!path)
path = g_strdup (""NM_KEYFILE_PATH_NAME_ETC_DEFAULT"");
}
return path;
}

View File

@ -14,7 +14,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2010-2016 Red Hat, Inc.
* (C) Copyright 2010 - 2018 Red Hat, Inc.
*/
#ifndef __NMS_KEYFILE_UTILS_H__
@ -22,18 +22,25 @@
#include "NetworkManagerUtils.h"
#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))
#define NMS_KEYFILE_CONNECTION_LOG_FMTD "%s (%s,\"%s\",%p)"
#define NMS_KEYFILE_CONNECTION_LOG_ARGD(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)), (con)
typedef enum {
NMS_KEYFILE_FILETYPE_KEYFILE,
NMS_KEYFILE_FILETYPE_NMLOADED,
} NMSKeyfileFiletype;
const char *nms_keyfile_utils_get_path (void);
typedef enum {
NMS_KEYFILE_STORAGE_TYPE_RUN = 1, /* read-write, runtime only, e.g. /run */
NMS_KEYFILE_STORAGE_TYPE_ETC = 2, /* read-write, persistent, e.g. /etc */
NMS_KEYFILE_STORAGE_TYPE_LIB_BASE = 3, /* read-only, e.g. /usr/lib */
_NMS_KEYFILE_STORAGE_TYPE_LIB_LAST = 1000,
} NMSKeyfileStorageType;
static inline NMSKeyfileStorageType
NMS_KEYFILE_STORAGE_TYPE_LIB (guint run_idx)
{
nm_assert (run_idx <= (_NMS_KEYFILE_STORAGE_TYPE_LIB_LAST - NMS_KEYFILE_STORAGE_TYPE_LIB_BASE));
return NMS_KEYFILE_STORAGE_TYPE_LIB_BASE + run_idx;
}
/*****************************************************************************/

View File

@ -168,6 +168,8 @@ _handler_write (NMConnection *connection,
static gboolean
_internal_write_connection (NMConnection *connection,
gboolean is_nm_generated,
gboolean is_volatile,
const char *keyfile_dir,
const char *profile_dir,
gboolean with_extension,
@ -212,6 +214,21 @@ _internal_write_connection (NMConnection *connection,
kf_file = nm_keyfile_write (connection, _handler_write, &info, error);
if (!kf_file)
return FALSE;
if (is_nm_generated) {
g_key_file_set_boolean (kf_file,
NM_KEYFILE_GROUP_NMMETA,
NM_KEYFILE_KEY_NMMETA_NM_GENERATED,
TRUE);
}
if (is_volatile) {
g_key_file_set_boolean (kf_file,
NM_KEYFILE_GROUP_NMMETA,
NM_KEYFILE_KEY_NMMETA_VOLATILE,
TRUE);
}
kf_content_buf = g_key_file_to_data (kf_file, &kf_content_len, error);
if (!kf_content_buf)
return FALSE;
@ -337,8 +354,12 @@ _internal_write_connection (NMConnection *connection,
gboolean
nms_keyfile_writer_connection (NMConnection *connection,
gboolean save_to_disk,
gboolean is_nm_generated,
gboolean is_volatile,
const char *keyfile_dir,
const char *profile_dir,
const char *existing_path,
gboolean existing_path_read_only,
gboolean force_rename,
NMSKeyfileWriterAllowFilenameCb allow_filename_cb,
gpointer allow_filename_user_data,
@ -347,21 +368,16 @@ 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_KEYFILE_PATH_NAME_RUN;
return _internal_write_connection (connection,
is_nm_generated,
is_volatile,
keyfile_dir,
nms_keyfile_utils_get_path (),
profile_dir,
TRUE,
0,
0,
existing_path,
FALSE,
existing_path_read_only,
force_rename,
allow_filename_cb,
allow_filename_user_data,
@ -382,6 +398,8 @@ nms_keyfile_writer_test_connection (NMConnection *connection,
GError **error)
{
return _internal_write_connection (connection,
FALSE,
FALSE,
keyfile_dir,
keyfile_dir,
FALSE,

View File

@ -27,8 +27,12 @@ typedef gboolean (*NMSKeyfileWriterAllowFilenameCb) (const char *check_filename,
gpointer allow_filename_user_data);
gboolean nms_keyfile_writer_connection (NMConnection *connection,
gboolean save_to_disk,
gboolean is_nm_generated,
gboolean is_volatile,
const char *keyfile_dir,
const char *profile_dir,
const char *existing_path,
gboolean existing_path_read_only,
gboolean force_rename,
NMSKeyfileWriterAllowFilenameCb allow_filename_cb,
gpointer allow_filename_user_data,

View File

@ -71,6 +71,9 @@ check_ip_route (NMSettingIPConfig *config, int idx, const char *destination, int
g_assert (full_filename && full_filename[0] == '/'); \
\
_connection = nms_keyfile_reader_from_file (full_filename, \
NULL, \
NULL, \
NULL, \
NULL, \
(nmtst_get_rand_uint32 () % 2) ? &_error : NULL); \
nmtst_assert_success (_connection, _error); \

View File

@ -30,6 +30,7 @@ for dir in "${pkgconfdir}/conf.d" \
"${pkglibdir}/dispatcher.d/no-wait.d" \
"${pkglibdir}/dispatcher.d/pre-down.d" \
"${pkglibdir}/dispatcher.d/pre-up.d" \
"${pkglibdir}/system-connections" \
"${pkglibdir}/VPN"; do
mkdir -p "${DESTDIR}${dir}"
chmod 0755 "${DESTDIR}${dir}"