mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-14 20:18:39 +00:00
core: add monitor-connection-files=false and ReloadConnections
Add a "monitor-connection-files" config option, which can be set to "false" to disable automatic reloading of connections on file change. To go with this, add a new ReloadConnections method on o.fd.NM.Settings that can be used to manually reload connections, and add an nm-cli command to call it.
This commit is contained in:
parent
4b74009b23
commit
1f81851017
|
@ -205,7 +205,8 @@ usage (void)
|
||||||
#endif
|
#endif
|
||||||
" down [ id | uuid | path | apath ] <ID>\n\n"
|
" down [ id | uuid | path | apath ] <ID>\n\n"
|
||||||
" add COMMON_OPTIONS TYPE_SPECIFIC_OPTIONS IP_OPTIONS\n\n"
|
" add COMMON_OPTIONS TYPE_SPECIFIC_OPTIONS IP_OPTIONS\n\n"
|
||||||
" delete [ id | uuid | path ] <ID>\n\n\n"
|
" delete [ id | uuid | path ] <ID>\n\n"
|
||||||
|
" reload\n\n\n"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,6 +285,7 @@ static const char *real_con_commands[] = {
|
||||||
"down",
|
"down",
|
||||||
"add",
|
"add",
|
||||||
"delete",
|
"delete",
|
||||||
|
"reload",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3221,6 +3223,32 @@ finish:
|
||||||
return nmc->return_value;
|
return nmc->return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NMCResultCode
|
||||||
|
do_connection_reload (NmCli *nmc, int argc, char **argv)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
nmc->return_value = NMC_RESULT_SUCCESS;
|
||||||
|
nmc->should_wait = FALSE;
|
||||||
|
|
||||||
|
if (!nm_client_get_manager_running (nmc->client)) {
|
||||||
|
g_string_printf (nmc->return_text, _("Error: NetworkManager is not running."));
|
||||||
|
nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING;
|
||||||
|
return nmc->return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nm_remote_settings_reload_connections (nmc->system_settings, &error)) {
|
||||||
|
g_string_printf (nmc->return_text, _("Error: %s."), error->message);
|
||||||
|
if (error->code == NM_REMOTE_SETTINGS_ERROR_SERVICE_UNAVAILABLE)
|
||||||
|
nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING;
|
||||||
|
else
|
||||||
|
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nmc->return_value;
|
||||||
|
}
|
||||||
|
|
||||||
static NMCResultCode
|
static NMCResultCode
|
||||||
parse_cmd (NmCli *nmc, int argc, char **argv)
|
parse_cmd (NmCli *nmc, int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
@ -3263,6 +3291,9 @@ parse_cmd (NmCli *nmc, int argc, char **argv)
|
||||||
else if (matches(*argv, "delete") == 0) {
|
else if (matches(*argv, "delete") == 0) {
|
||||||
nmc->return_value = do_connection_delete (nmc, argc-1, argv+1);
|
nmc->return_value = do_connection_delete (nmc, argc-1, argv+1);
|
||||||
}
|
}
|
||||||
|
else if (matches(*argv, "reload") == 0) {
|
||||||
|
nmc->return_value = do_connection_reload (nmc, argc-1, argv+1);
|
||||||
|
}
|
||||||
else if (nmc_arg_is_help (*argv)) {
|
else if (nmc_arg_is_help (*argv)) {
|
||||||
usage ();
|
usage ();
|
||||||
nmc->should_wait = FALSE;
|
nmc->should_wait = FALSE;
|
||||||
|
|
|
@ -4,6 +4,15 @@
|
||||||
|
|
||||||
[main]
|
[main]
|
||||||
|
|
||||||
|
# Normally, NetworkManager reloads connection files on disk any time
|
||||||
|
# they are changed. Setting "monitor-connection-files=false" will
|
||||||
|
# disable this behavior, and NetworkManager will then only read
|
||||||
|
# connection files at startup, and when explicitly requested via
|
||||||
|
# D-Bus.
|
||||||
|
|
||||||
|
#monitor-connection-files=false
|
||||||
|
|
||||||
|
|
||||||
# Normally, if there is an ethernet device that is not matched by any
|
# Normally, if there is an ethernet device that is not matched by any
|
||||||
# existing configured connection, NetworkManager will create a
|
# existing configured connection, NetworkManager will create a
|
||||||
# "default" connection for that device, using automatic (DHCP/SLAAC)
|
# "default" connection for that device, using automatic (DHCP/SLAAC)
|
||||||
|
|
|
@ -31,6 +31,11 @@
|
||||||
the connection to disk. Secrets may be part of the update request
|
the connection to disk. Secrets may be part of the update request
|
||||||
and may sent to a Secret Agent for storage, depending on the the
|
and may sent to a Secret Agent for storage, depending on the the
|
||||||
flags associated with each secret.
|
flags associated with each secret.
|
||||||
|
|
||||||
|
Use the 'Save' method 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).
|
||||||
</tp:docstring>
|
</tp:docstring>
|
||||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_settings_connection_update_unsaved"/>
|
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_settings_connection_update_unsaved"/>
|
||||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||||
|
|
|
@ -62,6 +62,11 @@
|
||||||
operation does not start the network connection unless (1) device is
|
operation does not start the network connection unless (1) device is
|
||||||
idle and able to connect to the network described by the new connection,
|
idle and able to connect to the network described by the new connection,
|
||||||
and (2) the connection is allowed to be started automatically.
|
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).
|
||||||
</tp:docstring>
|
</tp:docstring>
|
||||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_settings_add_connection_unsaved"/>
|
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_settings_add_connection_unsaved"/>
|
||||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||||
|
@ -77,6 +82,23 @@
|
||||||
</arg>
|
</arg>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
<method name="ReloadConnections">
|
||||||
|
<tp:docstring>
|
||||||
|
Tells NetworkManager to reload all connection files from disk,
|
||||||
|
including noticing any added or deleted connection files. By
|
||||||
|
default, connections are re-read automatically any time they
|
||||||
|
change, so you only need to use this command if you have set
|
||||||
|
"monitor-connection-files=false" in NetworkManager.conf.
|
||||||
|
</tp:docstring>
|
||||||
|
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_settings_reload_connections"/>
|
||||||
|
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||||
|
<arg name="status" type="b" direction="out">
|
||||||
|
<tp:docstring>
|
||||||
|
Success or failure.
|
||||||
|
</tp:docstring>
|
||||||
|
</arg>
|
||||||
|
</method>
|
||||||
|
|
||||||
<method name="SaveHostname">
|
<method name="SaveHostname">
|
||||||
<tp:docstring>
|
<tp:docstring>
|
||||||
Save the hostname to persistent configuration.
|
Save the hostname to persistent configuration.
|
||||||
|
|
|
@ -231,6 +231,7 @@ global:
|
||||||
nm_remote_settings_new;
|
nm_remote_settings_new;
|
||||||
nm_remote_settings_new_async;
|
nm_remote_settings_new_async;
|
||||||
nm_remote_settings_new_finish;
|
nm_remote_settings_new_finish;
|
||||||
|
nm_remote_settings_reload_connections;
|
||||||
nm_remote_settings_save_hostname;
|
nm_remote_settings_save_hostname;
|
||||||
nm_secret_agent_delete_secrets;
|
nm_secret_agent_delete_secrets;
|
||||||
nm_secret_agent_error_get_type;
|
nm_secret_agent_error_get_type;
|
||||||
|
|
|
@ -629,6 +629,47 @@ nm_remote_settings_add_connection_unsaved (NMRemoteSettings *settings,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_remote_settings_reload_connections:
|
||||||
|
* @settings: the #NMRemoteSettings
|
||||||
|
* @error: return location for #GError
|
||||||
|
*
|
||||||
|
* Requests that the remote settings service reload all connection
|
||||||
|
* files from disk, adding, updating, and removing connections until
|
||||||
|
* the in-memory state matches the on-disk state.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE on success, %FALSE on failure
|
||||||
|
*
|
||||||
|
* Since: 0.9.10
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
nm_remote_settings_reload_connections (NMRemoteSettings *settings,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
NMRemoteSettingsPrivate *priv;
|
||||||
|
gboolean success;
|
||||||
|
|
||||||
|
g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), FALSE);
|
||||||
|
|
||||||
|
priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
|
||||||
|
|
||||||
|
_nm_remote_settings_ensure_inited (settings);
|
||||||
|
|
||||||
|
if (!priv->service_running) {
|
||||||
|
g_set_error_literal (error, NM_REMOTE_SETTINGS_ERROR,
|
||||||
|
NM_REMOTE_SETTINGS_ERROR_SERVICE_UNAVAILABLE,
|
||||||
|
"NetworkManager is not running.");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dbus_g_proxy_call (priv->proxy, "ReloadConnections", error,
|
||||||
|
G_TYPE_INVALID,
|
||||||
|
G_TYPE_BOOLEAN, &success,
|
||||||
|
G_TYPE_INVALID))
|
||||||
|
return FALSE;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clear_one_hash (GHashTable *table)
|
clear_one_hash (GHashTable *table)
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,6 +45,8 @@ G_BEGIN_DECLS
|
||||||
* was removed before it was completely initialized
|
* was removed before it was completely initialized
|
||||||
* @NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE: the #NMRemoteConnection object
|
* @NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE: the #NMRemoteConnection object
|
||||||
* is not visible or otherwise unreadable
|
* is not visible or otherwise unreadable
|
||||||
|
* @NM_REMOTE_SETTINGS_ERROR_SERVICE_UNAVAILABLE: NetworkManager is not running.
|
||||||
|
* (Since 0.9.10)
|
||||||
*
|
*
|
||||||
* Describes errors that may result from operations involving a #NMRemoteSettings.
|
* Describes errors that may result from operations involving a #NMRemoteSettings.
|
||||||
*
|
*
|
||||||
|
@ -53,6 +55,7 @@ typedef enum {
|
||||||
NM_REMOTE_SETTINGS_ERROR_UNKNOWN = 0, /*< nick=UnknownError >*/
|
NM_REMOTE_SETTINGS_ERROR_UNKNOWN = 0, /*< nick=UnknownError >*/
|
||||||
NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED, /*< nick=ConnectionRemoved >*/
|
NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED, /*< nick=ConnectionRemoved >*/
|
||||||
NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE, /*< nick=ConnectionUnavailable >*/
|
NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE, /*< nick=ConnectionUnavailable >*/
|
||||||
|
NM_REMOTE_SETTINGS_ERROR_SERVICE_UNAVAILABLE, /*< nick=ServiceUnavailable >*/
|
||||||
} NMRemoteSettingsError;
|
} NMRemoteSettingsError;
|
||||||
|
|
||||||
#define NM_REMOTE_SETTINGS_ERROR nm_remote_settings_error_quark ()
|
#define NM_REMOTE_SETTINGS_ERROR nm_remote_settings_error_quark ()
|
||||||
|
@ -132,6 +135,9 @@ gboolean nm_remote_settings_add_connection_unsaved (NMRemoteSettings *settings,
|
||||||
NMRemoteSettingsAddConnectionFunc callback,
|
NMRemoteSettingsAddConnectionFunc callback,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
|
||||||
|
gboolean nm_remote_settings_reload_connections (NMRemoteSettings *settings,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
gboolean nm_remote_settings_save_hostname (NMRemoteSettings *settings,
|
gboolean nm_remote_settings_save_hostname (NMRemoteSettings *settings,
|
||||||
const char *hostname,
|
const char *hostname,
|
||||||
NMRemoteSettingsSaveHostnameFunc callback,
|
NMRemoteSettingsSaveHostnameFunc callback,
|
||||||
|
|
|
@ -96,6 +96,16 @@ Copyright (C) 2010 - 2013 Red Hat, Inc.
|
||||||
connection, the error is returned to the user. See below
|
connection, the error is returned to the user. See below
|
||||||
for available plugins.</para></listitem>
|
for available plugins.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>monitor-connection-files</varname></term>
|
||||||
|
<listitem><para>Whether the configured settings plugin(s)
|
||||||
|
should set up file monitors and immediately pick up changes
|
||||||
|
made to connection files while NetworkManager is running. This
|
||||||
|
is enabled by default; if this key is set to
|
||||||
|
'<literal>false</literal>', then NetworkManager will only read
|
||||||
|
the connection files at startup, and when explicitly requested
|
||||||
|
via the ReloadConnections D-Bus call.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>dhcp</varname></term>
|
<term><varname>dhcp</varname></term>
|
||||||
<listitem><para>This key sets up what DHCP client
|
<listitem><para>This key sets up what DHCP client
|
||||||
|
|
|
@ -238,7 +238,7 @@ NetworkManager connections
|
||||||
.br
|
.br
|
||||||
Get information about \fINetworkManager\fP connections and manage them.
|
Get information about \fINetworkManager\fP connections and manage them.
|
||||||
.TP
|
.TP
|
||||||
.SS \fICOMMAND\fP := { show | up | down | add | delete }
|
.SS \fICOMMAND\fP := { show | up | down | add | delete | reload }
|
||||||
.sp
|
.sp
|
||||||
.RS
|
.RS
|
||||||
.TP
|
.TP
|
||||||
|
@ -501,6 +501,13 @@ its name, UUID or D-Bus path. If <ID> is ambiguous, a keyword \fIid\fP,
|
||||||
\fIuuid\fP or \fIpath\fP can be used.
|
\fIuuid\fP or \fIpath\fP can be used.
|
||||||
.br
|
.br
|
||||||
See \fBshow active\fP above for the description of the <ID>-specifying keywords.
|
See \fBshow active\fP above for the description of the <ID>-specifying keywords.
|
||||||
|
.TP
|
||||||
|
.B reload
|
||||||
|
.br
|
||||||
|
Reload all connection files from disk. By default, connections are re-read
|
||||||
|
automatically any time they change, so you only need to use this command when
|
||||||
|
the auto-loading feature is disabled ("monitor-connection-files=false"
|
||||||
|
in NetworkManager.conf).
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
|
|
|
@ -43,6 +43,7 @@ typedef struct {
|
||||||
GKeyFile *keyfile;
|
GKeyFile *keyfile;
|
||||||
|
|
||||||
char **plugins;
|
char **plugins;
|
||||||
|
gboolean monitor_connection_files;
|
||||||
char *dhcp_client;
|
char *dhcp_client;
|
||||||
char *dns_mode;
|
char *dns_mode;
|
||||||
|
|
||||||
|
@ -81,6 +82,14 @@ nm_config_get_plugins (NMConfig *config)
|
||||||
return (const char **) NM_CONFIG_GET_PRIVATE (config)->plugins;
|
return (const char **) NM_CONFIG_GET_PRIVATE (config)->plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_config_get_monitor_connection_files (NMConfig *config)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (config != NULL, FALSE);
|
||||||
|
|
||||||
|
return NM_CONFIG_GET_PRIVATE (config)->monitor_connection_files;
|
||||||
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
nm_config_get_dhcp_client (NMConfig *config)
|
nm_config_get_dhcp_client (NMConfig *config)
|
||||||
{
|
{
|
||||||
|
@ -434,6 +443,7 @@ nm_config_new (GError **error)
|
||||||
GFileInfo *info;
|
GFileInfo *info;
|
||||||
GPtrArray *confs;
|
GPtrArray *confs;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
char *value;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
g_assert (!singleton);
|
g_assert (!singleton);
|
||||||
|
@ -492,6 +502,20 @@ nm_config_new (GError **error)
|
||||||
g_key_file_set_value (priv->keyfile, "main", "plugins", cli_plugins);
|
g_key_file_set_value (priv->keyfile, "main", "plugins", cli_plugins);
|
||||||
priv->plugins = g_key_file_get_string_list (priv->keyfile, "main", "plugins", NULL, NULL);
|
priv->plugins = g_key_file_get_string_list (priv->keyfile, "main", "plugins", NULL, NULL);
|
||||||
|
|
||||||
|
value = g_key_file_get_value (priv->keyfile, "main", "monitor-connection-files", NULL);
|
||||||
|
if (value) {
|
||||||
|
if (!strcmp (value, "true") || !strcmp (value, "yes") || !strcmp (value, "on"))
|
||||||
|
priv->monitor_connection_files = TRUE;
|
||||||
|
else if (!strcmp (value, "false") || !strcmp (value, "no") || !strcmp (value, "off"))
|
||||||
|
priv->monitor_connection_files = FALSE;
|
||||||
|
else {
|
||||||
|
g_warning ("Unrecognized value for main.monitor-connection-files: %s. Assuming 'false'", value);
|
||||||
|
priv->monitor_connection_files = FALSE;
|
||||||
|
}
|
||||||
|
g_free (value);
|
||||||
|
} else
|
||||||
|
priv->monitor_connection_files = TRUE;
|
||||||
|
|
||||||
priv->dhcp_client = g_key_file_get_value (priv->keyfile, "main", "dhcp", NULL);
|
priv->dhcp_client = g_key_file_get_value (priv->keyfile, "main", "dhcp", NULL);
|
||||||
priv->dns_mode = g_key_file_get_value (priv->keyfile, "main", "dns", NULL);
|
priv->dns_mode = g_key_file_get_value (priv->keyfile, "main", "dns", NULL);
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ NMConfig *nm_config_get (void);
|
||||||
|
|
||||||
const char *nm_config_get_path (NMConfig *config);
|
const char *nm_config_get_path (NMConfig *config);
|
||||||
const char **nm_config_get_plugins (NMConfig *config);
|
const char **nm_config_get_plugins (NMConfig *config);
|
||||||
|
gboolean nm_config_get_monitor_connection_files (NMConfig *config);
|
||||||
const char *nm_config_get_dhcp_client (NMConfig *config);
|
const char *nm_config_get_dhcp_client (NMConfig *config);
|
||||||
const char *nm_config_get_dns_mode (NMConfig *config);
|
const char *nm_config_get_dns_mode (NMConfig *config);
|
||||||
const char *nm_config_get_log_level (NMConfig *config);
|
const char *nm_config_get_log_level (NMConfig *config);
|
||||||
|
|
|
@ -104,6 +104,9 @@ static void impl_settings_add_connection_unsaved (NMSettings *self,
|
||||||
GHashTable *settings,
|
GHashTable *settings,
|
||||||
DBusGMethodInvocation *context);
|
DBusGMethodInvocation *context);
|
||||||
|
|
||||||
|
static void impl_settings_reload_connections (NMSettings *self,
|
||||||
|
DBusGMethodInvocation *context);
|
||||||
|
|
||||||
static void impl_settings_save_hostname (NMSettings *self,
|
static void impl_settings_save_hostname (NMSettings *self,
|
||||||
const char *hostname,
|
const char *hostname,
|
||||||
DBusGMethodInvocation *context);
|
DBusGMethodInvocation *context);
|
||||||
|
@ -1213,6 +1216,46 @@ impl_settings_add_connection_unsaved (NMSettings *self,
|
||||||
impl_settings_add_connection_helper (self, settings, FALSE, context);
|
impl_settings_add_connection_helper (self, settings, FALSE, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
impl_settings_reload_connections (NMSettings *self,
|
||||||
|
DBusGMethodInvocation *context)
|
||||||
|
{
|
||||||
|
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||||
|
GSList *iter;
|
||||||
|
gulong caller_uid;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
if (!nm_dbus_manager_get_caller_info (priv->dbus_mgr, context, NULL, &caller_uid)) {
|
||||||
|
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||||
|
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||||
|
"Unable to determine request UID.");
|
||||||
|
dbus_g_method_return_error (context, error);
|
||||||
|
g_error_free (error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (caller_uid != 0) {
|
||||||
|
nm_log_warn (LOGD_SETTINGS, "ReloadConnections: permission denied to %lu", caller_uid);
|
||||||
|
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||||
|
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||||
|
"Permission denied");
|
||||||
|
dbus_g_method_return_error (context, error);
|
||||||
|
g_error_free (error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!priv->connections_loaded) {
|
||||||
|
load_connections (self);
|
||||||
|
} else {
|
||||||
|
for (iter = priv->plugins; iter; iter = g_slist_next (iter)) {
|
||||||
|
NMSystemConfigInterface *plugin = NM_SYSTEM_CONFIG_INTERFACE (iter->data);
|
||||||
|
|
||||||
|
nm_system_config_interface_reload_connections (plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_g_method_return (context, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pk_hostname_cb (NMAuthChain *chain,
|
pk_hostname_cb (NMAuthChain *chain,
|
||||||
GError *chain_error,
|
GError *chain_error,
|
||||||
|
|
|
@ -137,6 +137,15 @@ nm_system_config_interface_get_connections (NMSystemConfigInterface *config)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nm_system_config_interface_reload_connections (NMSystemConfigInterface *config)
|
||||||
|
{
|
||||||
|
g_return_if_fail (config != NULL);
|
||||||
|
|
||||||
|
if (NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->reload_connections)
|
||||||
|
NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->reload_connections (config);
|
||||||
|
}
|
||||||
|
|
||||||
GSList *
|
GSList *
|
||||||
nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface *config)
|
nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface *config)
|
||||||
{
|
{
|
||||||
|
|
|
@ -89,6 +89,11 @@ struct _NMSystemConfigInterface {
|
||||||
*/
|
*/
|
||||||
GSList * (*get_connections) (NMSystemConfigInterface *config);
|
GSList * (*get_connections) (NMSystemConfigInterface *config);
|
||||||
|
|
||||||
|
/* Requests that the plugin reload all connection files from disk,
|
||||||
|
* and emit signals reflecting new, changed, and removed connections.
|
||||||
|
*/
|
||||||
|
void (*reload_connections) (NMSystemConfigInterface *config);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return a string list of specifications of devices which NetworkManager
|
* Return a string list of specifications of devices which NetworkManager
|
||||||
* should not manage. Returned list will be freed by the system settings
|
* should not manage. Returned list will be freed by the system settings
|
||||||
|
@ -137,6 +142,8 @@ void nm_system_config_interface_init (NMSystemConfigInterface *config,
|
||||||
|
|
||||||
GSList *nm_system_config_interface_get_connections (NMSystemConfigInterface *config);
|
GSList *nm_system_config_interface_get_connections (NMSystemConfigInterface *config);
|
||||||
|
|
||||||
|
void nm_system_config_interface_reload_connections (NMSystemConfigInterface *config);
|
||||||
|
|
||||||
GSList *nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface *config);
|
GSList *nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface *config);
|
||||||
|
|
||||||
NMSettingsConnection *nm_system_config_interface_add_connection (NMSystemConfigInterface *config,
|
NMSettingsConnection *nm_system_config_interface_add_connection (NMSystemConfigInterface *config,
|
||||||
|
|
|
@ -421,10 +421,9 @@ conf_file_changed (GFileMonitor *monitor,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function starts the inotify monitors that watch the plugin's config
|
/* This function starts the inotify monitors that watch the plugin's config
|
||||||
* file directory for new connections and changes to existing connections.
|
* file directory for new connections and changes to existing connections
|
||||||
* At this time all plugins are expected to make NM aware of changes on-the-fly
|
* (if not disabled by NetworkManager.conf), and for changes to the plugin's
|
||||||
* instead of requiring a SIGHUP or SIGUSR1 or some D-Bus method to say
|
* non-connection config files.
|
||||||
* "reload".
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
setup_monitoring (NMSystemConfigInterface *config)
|
setup_monitoring (NMSystemConfigInterface *config)
|
||||||
|
@ -438,16 +437,18 @@ setup_monitoring (NMSystemConfigInterface *config)
|
||||||
*/
|
*/
|
||||||
priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
|
priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
|
||||||
|
|
||||||
/* Set up the watch for our config directory */
|
if (nm_config_get_monitor_connection_files (nm_config_get ())) {
|
||||||
file = g_file_new_for_path (EXAMPLE_DIR);
|
/* Set up the watch for our config directory */
|
||||||
monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
|
file = g_file_new_for_path (EXAMPLE_DIR);
|
||||||
g_object_unref (file);
|
monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
|
||||||
if (monitor) {
|
g_object_unref (file);
|
||||||
/* This registers the dir_changed() function to be called whenever
|
if (monitor) {
|
||||||
* the GFileMonitor object notices a change in the directory.
|
/* This registers the dir_changed() function to be called whenever
|
||||||
*/
|
* the GFileMonitor object notices a change in the directory.
|
||||||
priv->monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (dir_changed), config);
|
*/
|
||||||
priv->monitor = monitor;
|
priv->monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (dir_changed), config);
|
||||||
|
priv->monitor = monitor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up a watch on our configuration file, basically just for watching
|
/* Set up a watch on our configuration file, basically just for watching
|
||||||
|
|
|
@ -28,6 +28,7 @@ INCLUDES = \
|
||||||
-I$(top_srcdir)/src/wifi \
|
-I$(top_srcdir)/src/wifi \
|
||||||
-I$(top_srcdir)/src/settings \
|
-I$(top_srcdir)/src/settings \
|
||||||
-I$(top_srcdir)/src/posix-signals \
|
-I$(top_srcdir)/src/posix-signals \
|
||||||
|
-I$(top_srcdir)/src/config \
|
||||||
-I$(top_srcdir)/include \
|
-I$(top_srcdir)/include \
|
||||||
-I$(top_builddir)/include \
|
-I$(top_builddir)/include \
|
||||||
-I$(top_srcdir)/libnm-glib \
|
-I$(top_srcdir)/libnm-glib \
|
||||||
|
|
|
@ -44,10 +44,12 @@
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "nm-system-config-interface.h"
|
#include "nm-system-config-interface.h"
|
||||||
#include "nm-settings-error.h"
|
#include "nm-settings-error.h"
|
||||||
|
#include "nm-config.h"
|
||||||
|
|
||||||
#include "nm-ifcfg-connection.h"
|
#include "nm-ifcfg-connection.h"
|
||||||
#include "nm-inotify-helper.h"
|
#include "nm-inotify-helper.h"
|
||||||
#include "shvar.h"
|
#include "shvar.h"
|
||||||
|
#include "reader.h"
|
||||||
#include "writer.h"
|
#include "writer.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
@ -64,7 +66,8 @@ static gboolean impl_ifcfgrh_get_ifcfg_details (SCPluginIfcfg *plugin,
|
||||||
|
|
||||||
static void connection_new_or_changed (SCPluginIfcfg *plugin,
|
static void connection_new_or_changed (SCPluginIfcfg *plugin,
|
||||||
const char *path,
|
const char *path,
|
||||||
NMIfcfgConnection *existing);
|
NMIfcfgConnection *existing,
|
||||||
|
char **out_old_path);
|
||||||
|
|
||||||
static void system_config_interface_init (NMSystemConfigInterface *system_config_interface_class);
|
static void system_config_interface_init (NMSystemConfigInterface *system_config_interface_class);
|
||||||
|
|
||||||
|
@ -109,7 +112,7 @@ connection_ifcfg_changed (NMIfcfgConnection *connection, gpointer user_data)
|
||||||
path = nm_ifcfg_connection_get_path (connection);
|
path = nm_ifcfg_connection_get_path (connection);
|
||||||
g_return_if_fail (path != NULL);
|
g_return_if_fail (path != NULL);
|
||||||
|
|
||||||
connection_new_or_changed (plugin, path, connection);
|
connection_new_or_changed (plugin, path, connection, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NMIfcfgConnection *
|
static NMIfcfgConnection *
|
||||||
|
@ -173,35 +176,6 @@ _internal_new_connection (SCPluginIfcfg *self,
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
read_connections (SCPluginIfcfg *plugin)
|
|
||||||
{
|
|
||||||
GDir *dir;
|
|
||||||
GError *err = NULL;
|
|
||||||
|
|
||||||
dir = g_dir_open (IFCFG_DIR, 0, &err);
|
|
||||||
if (dir) {
|
|
||||||
const char *item;
|
|
||||||
|
|
||||||
while ((item = g_dir_read_name (dir))) {
|
|
||||||
char *full_path;
|
|
||||||
|
|
||||||
if (utils_should_ignore_file (item, TRUE))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
full_path = g_build_filename (IFCFG_DIR, item, NULL);
|
|
||||||
if (utils_get_ifcfg_name (full_path, TRUE))
|
|
||||||
_internal_new_connection (plugin, full_path, NULL, NULL);
|
|
||||||
g_free (full_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_dir_close (dir);
|
|
||||||
} else {
|
|
||||||
PLUGIN_WARN (IFCFG_PLUGIN_NAME, "Can not read directory '%s': %s", IFCFG_DIR, err->message);
|
|
||||||
g_error_free (err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Monitoring */
|
/* Monitoring */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -242,10 +216,26 @@ find_by_path (SCPluginIfcfg *self, const char *path)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NMIfcfgConnection *
|
||||||
|
find_by_uuid_from_path (SCPluginIfcfg *self, const char *path)
|
||||||
|
{
|
||||||
|
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
|
||||||
|
char *uuid;
|
||||||
|
|
||||||
|
g_return_val_if_fail (path != NULL, NULL);
|
||||||
|
|
||||||
|
uuid = uuid_from_file (path);
|
||||||
|
if (uuid)
|
||||||
|
return g_hash_table_lookup (priv->connections, uuid);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
connection_new_or_changed (SCPluginIfcfg *self,
|
connection_new_or_changed (SCPluginIfcfg *self,
|
||||||
const char *path,
|
const char *path,
|
||||||
NMIfcfgConnection *existing)
|
NMIfcfgConnection *existing,
|
||||||
|
char **out_old_path)
|
||||||
{
|
{
|
||||||
NMIfcfgConnection *new;
|
NMIfcfgConnection *new;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
@ -255,6 +245,21 @@ connection_new_or_changed (SCPluginIfcfg *self,
|
||||||
g_return_if_fail (self != NULL);
|
g_return_if_fail (self != NULL);
|
||||||
g_return_if_fail (path != NULL);
|
g_return_if_fail (path != NULL);
|
||||||
|
|
||||||
|
if (out_old_path)
|
||||||
|
*out_old_path = NULL;
|
||||||
|
|
||||||
|
if (!existing) {
|
||||||
|
/* See if it's a rename */
|
||||||
|
existing = find_by_uuid_from_path (self, path);
|
||||||
|
if (existing) {
|
||||||
|
const char *old_path = nm_ifcfg_connection_get_path (existing);
|
||||||
|
PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "renaming %s -> %s", old_path, path);
|
||||||
|
if (out_old_path)
|
||||||
|
*out_old_path = g_strdup (old_path);
|
||||||
|
nm_ifcfg_connection_set_path (existing, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
/* New connection */
|
/* New connection */
|
||||||
new = _internal_new_connection (self, path, NULL, NULL);
|
new = _internal_new_connection (self, path, NULL, NULL);
|
||||||
|
@ -371,7 +376,7 @@ ifcfg_dir_changed (GFileMonitor *monitor,
|
||||||
case G_FILE_MONITOR_EVENT_CREATED:
|
case G_FILE_MONITOR_EVENT_CREATED:
|
||||||
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
|
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
|
||||||
/* Update or new */
|
/* Update or new */
|
||||||
connection_new_or_changed (plugin, ifcfg_path, connection);
|
connection_new_or_changed (plugin, ifcfg_path, connection, NULL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -399,6 +404,65 @@ setup_ifcfg_monitoring (SCPluginIfcfg *plugin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
read_connections (SCPluginIfcfg *plugin)
|
||||||
|
{
|
||||||
|
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
|
||||||
|
GDir *dir;
|
||||||
|
GError *err = NULL;
|
||||||
|
const char *item;
|
||||||
|
GHashTable *oldconns;
|
||||||
|
GHashTableIter iter;
|
||||||
|
gpointer key, value;
|
||||||
|
NMIfcfgConnection *connection;
|
||||||
|
|
||||||
|
dir = g_dir_open (IFCFG_DIR, 0, &err);
|
||||||
|
if (!dir) {
|
||||||
|
PLUGIN_WARN (IFCFG_PLUGIN_NAME, "Can not read directory '%s': %s", IFCFG_DIR, err->message);
|
||||||
|
g_error_free (err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
oldconns = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||||
|
g_hash_table_iter_init (&iter, priv->connections);
|
||||||
|
while (g_hash_table_iter_next (&iter, NULL, &value))
|
||||||
|
g_hash_table_insert (oldconns, g_strdup (nm_ifcfg_connection_get_path (value)), value);
|
||||||
|
|
||||||
|
while ((item = g_dir_read_name (dir))) {
|
||||||
|
char *full_path, *old_path;
|
||||||
|
|
||||||
|
if (utils_should_ignore_file (item, TRUE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
full_path = g_build_filename (IFCFG_DIR, item, NULL);
|
||||||
|
if (!utils_get_ifcfg_name (full_path, TRUE))
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
connection = g_hash_table_lookup (oldconns, full_path);
|
||||||
|
g_hash_table_remove (oldconns, full_path);
|
||||||
|
connection_new_or_changed (plugin, full_path, connection, &old_path);
|
||||||
|
|
||||||
|
if (old_path) {
|
||||||
|
g_hash_table_remove (oldconns, old_path);
|
||||||
|
g_free (old_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
next:
|
||||||
|
g_free (full_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_dir_close (dir);
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, oldconns);
|
||||||
|
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
||||||
|
PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "removed %s.", (char *)key);
|
||||||
|
g_hash_table_iter_remove (&iter);
|
||||||
|
remove_connection (plugin, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_destroy (oldconns);
|
||||||
|
}
|
||||||
|
|
||||||
static GSList *
|
static GSList *
|
||||||
get_connections (NMSystemConfigInterface *config)
|
get_connections (NMSystemConfigInterface *config)
|
||||||
{
|
{
|
||||||
|
@ -409,7 +473,8 @@ get_connections (NMSystemConfigInterface *config)
|
||||||
NMIfcfgConnection *connection;
|
NMIfcfgConnection *connection;
|
||||||
|
|
||||||
if (!priv->initialized) {
|
if (!priv->initialized) {
|
||||||
setup_ifcfg_monitoring (plugin);
|
if (nm_config_get_monitor_connection_files (nm_config_get ()))
|
||||||
|
setup_ifcfg_monitoring (plugin);
|
||||||
read_connections (plugin);
|
read_connections (plugin);
|
||||||
priv->initialized = TRUE;
|
priv->initialized = TRUE;
|
||||||
}
|
}
|
||||||
|
@ -423,6 +488,14 @@ get_connections (NMSystemConfigInterface *config)
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reload_connections (NMSystemConfigInterface *config)
|
||||||
|
{
|
||||||
|
SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config);
|
||||||
|
|
||||||
|
read_connections (plugin);
|
||||||
|
}
|
||||||
|
|
||||||
static GSList *
|
static GSList *
|
||||||
get_unmanaged_specs (NMSystemConfigInterface *config)
|
get_unmanaged_specs (NMSystemConfigInterface *config)
|
||||||
{
|
{
|
||||||
|
@ -854,6 +927,7 @@ system_config_interface_init (NMSystemConfigInterface *system_config_interface_c
|
||||||
/* interface implementation */
|
/* interface implementation */
|
||||||
system_config_interface_class->get_connections = get_connections;
|
system_config_interface_class->get_connections = get_connections;
|
||||||
system_config_interface_class->add_connection = add_connection;
|
system_config_interface_class->add_connection = add_connection;
|
||||||
|
system_config_interface_class->reload_connections = reload_connections;
|
||||||
system_config_interface_class->get_unmanaged_specs = get_unmanaged_specs;
|
system_config_interface_class->get_unmanaged_specs = get_unmanaged_specs;
|
||||||
system_config_interface_class->init = init;
|
system_config_interface_class->init = init;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4251,6 +4251,34 @@ ensure_unmanaged (shvarFile *ifcfg,
|
||||||
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: NM_CONTROLLED was false but device was not uniquely identified; device will be managed");
|
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: NM_CONTROLLED was false but device was not uniquely identified; device will be managed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
uuid_from_file (const char *filename)
|
||||||
|
{
|
||||||
|
const char *ifcfg_name = NULL;
|
||||||
|
shvarFile *ifcfg;
|
||||||
|
char *uuid;
|
||||||
|
|
||||||
|
g_return_val_if_fail (filename != NULL, NULL);
|
||||||
|
|
||||||
|
ifcfg_name = utils_get_ifcfg_name (filename, TRUE);
|
||||||
|
if (!ifcfg_name)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ifcfg = svNewFile (filename);
|
||||||
|
if (!ifcfg)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Try for a UUID key before falling back to hashing the file name */
|
||||||
|
uuid = svGetValue (ifcfg, "UUID", FALSE);
|
||||||
|
if (!uuid || !strlen (uuid)) {
|
||||||
|
g_free (uuid);
|
||||||
|
uuid = nm_utils_uuid_generate_from_string (ifcfg->fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
svCloseFile (ifcfg);
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
NMConnection *
|
NMConnection *
|
||||||
connection_from_file (const char *filename,
|
connection_from_file (const char *filename,
|
||||||
const char *network_file, /* for unit tests only */
|
const char *network_file, /* for unit tests only */
|
||||||
|
|
|
@ -37,4 +37,6 @@ NMConnection *connection_from_file (const char *filename,
|
||||||
GError **error,
|
GError **error,
|
||||||
gboolean *ignore_error);
|
gboolean *ignore_error);
|
||||||
|
|
||||||
|
char *uuid_from_file (const char *filename);
|
||||||
|
|
||||||
#endif /* __READER_H__ */
|
#endif /* __READER_H__ */
|
||||||
|
|
|
@ -66,7 +66,7 @@ typedef struct {
|
||||||
|
|
||||||
static void system_config_interface_init (NMSystemConfigInterface *class);
|
static void system_config_interface_init (NMSystemConfigInterface *class);
|
||||||
|
|
||||||
static void reload_connections (gpointer config);
|
static void reload_connections (NMSystemConfigInterface *config);
|
||||||
|
|
||||||
G_DEFINE_TYPE_EXTENDED (SCPluginIfnet, sc_plugin_ifnet, G_TYPE_OBJECT, 0,
|
G_DEFINE_TYPE_EXTENDED (SCPluginIfnet, sc_plugin_ifnet, G_TYPE_OBJECT, 0,
|
||||||
G_IMPLEMENT_INTERFACE (NM_TYPE_SYSTEM_CONFIG_INTERFACE, system_config_interface_init))
|
G_IMPLEMENT_INTERFACE (NM_TYPE_SYSTEM_CONFIG_INTERFACE, system_config_interface_init))
|
||||||
|
@ -191,12 +191,15 @@ setup_monitors (NMIfnetConnection * connection, gpointer user_data)
|
||||||
|
|
||||||
priv->hostname_monitor =
|
priv->hostname_monitor =
|
||||||
monitor_file_changes (IFNET_SYSTEM_HOSTNAME_FILE,
|
monitor_file_changes (IFNET_SYSTEM_HOSTNAME_FILE,
|
||||||
update_system_hostname, user_data);
|
update_system_hostname, user_data);
|
||||||
priv->net_monitor =
|
if (nm_config_get_monitor_connection_files (nm_config_get ())) {
|
||||||
monitor_file_changes (CONF_NET_FILE, reload_connections, user_data);
|
priv->net_monitor =
|
||||||
priv->wpa_monitor =
|
monitor_file_changes (CONF_NET_FILE, (FileChangedFn) reload_connections,
|
||||||
monitor_file_changes (WPA_SUPPLICANT_CONF, reload_connections,
|
user_data);
|
||||||
user_data);
|
priv->wpa_monitor =
|
||||||
|
monitor_file_changes (WPA_SUPPLICANT_CONF, (FileChangedFn) reload_connections,
|
||||||
|
user_data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -220,7 +223,7 @@ cancel_monitors (NMIfnetConnection * connection, gpointer user_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reload_connections (gpointer config)
|
reload_connections (NMSystemConfigInterface *config)
|
||||||
{
|
{
|
||||||
SCPluginIfnet *self = SC_PLUGIN_IFNET (config);
|
SCPluginIfnet *self = SC_PLUGIN_IFNET (config);
|
||||||
SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (self);
|
SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (self);
|
||||||
|
@ -460,6 +463,7 @@ system_config_interface_init (NMSystemConfigInterface *class)
|
||||||
class->get_connections = get_connections;
|
class->get_connections = get_connections;
|
||||||
class->get_unmanaged_specs = get_unmanaged_specs;
|
class->get_unmanaged_specs = get_unmanaged_specs;
|
||||||
class->add_connection = add_connection;
|
class->add_connection = add_connection;
|
||||||
|
class->reload_connections = reload_connections;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -88,48 +88,6 @@ _internal_new_connection (SCPluginKeyfile *self,
|
||||||
return (NMSettingsConnection *) connection;
|
return (NMSettingsConnection *) connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
read_connections (NMSystemConfigInterface *config)
|
|
||||||
{
|
|
||||||
SCPluginKeyfile *self = SC_PLUGIN_KEYFILE (config);
|
|
||||||
GDir *dir;
|
|
||||||
GError *error = NULL;
|
|
||||||
const char *item;
|
|
||||||
|
|
||||||
dir = g_dir_open (KEYFILE_DIR, 0, &error);
|
|
||||||
if (!dir) {
|
|
||||||
PLUGIN_WARN (KEYFILE_PLUGIN_NAME, "Cannot read directory '%s': (%d) %s",
|
|
||||||
KEYFILE_DIR,
|
|
||||||
error ? error->code : -1,
|
|
||||||
error && error->message ? error->message : "(unknown)");
|
|
||||||
g_clear_error (&error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((item = g_dir_read_name (dir))) {
|
|
||||||
NMSettingsConnection *connection;
|
|
||||||
char *full_path;
|
|
||||||
|
|
||||||
if (nm_keyfile_plugin_utils_should_ignore_file (item))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
full_path = g_build_filename (KEYFILE_DIR, item, NULL);
|
|
||||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "parsing %s ... ", item);
|
|
||||||
|
|
||||||
connection = _internal_new_connection (self, full_path, NULL, &error);
|
|
||||||
if (connection) {
|
|
||||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, " read connection '%s'",
|
|
||||||
nm_connection_get_id (NM_CONNECTION (connection)));
|
|
||||||
} else {
|
|
||||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, " error: %s",
|
|
||||||
(error && error->message) ? error->message : "(unknown)");
|
|
||||||
}
|
|
||||||
g_clear_error (&error);
|
|
||||||
g_free (full_path);
|
|
||||||
}
|
|
||||||
g_dir_close (dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Monitoring */
|
/* Monitoring */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -137,6 +95,8 @@ remove_connection (SCPluginKeyfile *self, NMKeyfileConnection *connection)
|
||||||
{
|
{
|
||||||
g_return_if_fail (connection != NULL);
|
g_return_if_fail (connection != NULL);
|
||||||
|
|
||||||
|
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "removed %s.", nm_keyfile_connection_get_path (connection));
|
||||||
|
|
||||||
/* Removing from the hash table should drop the last reference */
|
/* Removing from the hash table should drop the last reference */
|
||||||
g_object_ref (connection);
|
g_object_ref (connection);
|
||||||
g_hash_table_remove (SC_PLUGIN_KEYFILE_GET_PRIVATE (self)->connections,
|
g_hash_table_remove (SC_PLUGIN_KEYFILE_GET_PRIVATE (self)->connections,
|
||||||
|
@ -145,6 +105,40 @@ remove_connection (SCPluginKeyfile *self, NMKeyfileConnection *connection)
|
||||||
g_object_unref (connection);
|
g_object_unref (connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_connection (SCPluginKeyfile *self,
|
||||||
|
NMKeyfileConnection *connection,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
NMKeyfileConnection *tmp;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
tmp = nm_keyfile_connection_new (NULL, name, &error);
|
||||||
|
if (!tmp) {
|
||||||
|
/* Error; remove the connection */
|
||||||
|
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, " error: %s",
|
||||||
|
(error && error->message) ? error->message : "(unknown)");
|
||||||
|
g_clear_error (&error);
|
||||||
|
remove_connection (self, connection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nm_connection_compare (NM_CONNECTION (connection),
|
||||||
|
NM_CONNECTION (tmp),
|
||||||
|
NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS |
|
||||||
|
NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) {
|
||||||
|
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "updating %s", name);
|
||||||
|
if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (connection),
|
||||||
|
NM_CONNECTION (tmp),
|
||||||
|
FALSE, /* don't set Unsaved */
|
||||||
|
&error)) {
|
||||||
|
/* Shouldn't ever get here as 'new' was verified by the reader already */
|
||||||
|
g_assert_no_error (error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_object_unref (tmp);
|
||||||
|
}
|
||||||
|
|
||||||
static NMKeyfileConnection *
|
static NMKeyfileConnection *
|
||||||
find_by_path (SCPluginKeyfile *self, const char *path)
|
find_by_path (SCPluginKeyfile *self, const char *path)
|
||||||
{
|
{
|
||||||
|
@ -162,6 +156,51 @@ find_by_path (SCPluginKeyfile *self, const char *path)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
new_connection (SCPluginKeyfile *self,
|
||||||
|
const char *name,
|
||||||
|
char **out_old_path)
|
||||||
|
{
|
||||||
|
SCPluginKeyfilePrivate *priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (self);
|
||||||
|
NMKeyfileConnection *tmp, *connection;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
if (out_old_path)
|
||||||
|
*out_old_path = NULL;
|
||||||
|
|
||||||
|
tmp = nm_keyfile_connection_new (NULL, name, &error);
|
||||||
|
if (!tmp) {
|
||||||
|
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, " error in connection %s: %s", name,
|
||||||
|
(error && error->message) ? error->message : "(unknown)");
|
||||||
|
g_clear_error (&error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connection renames will show as different paths but same UUID */
|
||||||
|
connection = g_hash_table_lookup (priv->connections, nm_connection_get_uuid (NM_CONNECTION (tmp)));
|
||||||
|
if (connection) {
|
||||||
|
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "rename %s -> %s",
|
||||||
|
nm_keyfile_connection_get_path (connection), name);
|
||||||
|
if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (connection),
|
||||||
|
NM_CONNECTION (tmp),
|
||||||
|
FALSE, /* don't set Unsaved */
|
||||||
|
&error)) {
|
||||||
|
/* Shouldn't ever get here as 'tmp' was verified by the reader already */
|
||||||
|
g_assert_no_error (error);
|
||||||
|
}
|
||||||
|
g_object_unref (tmp);
|
||||||
|
if (out_old_path)
|
||||||
|
*out_old_path = g_strdup (nm_keyfile_connection_get_path (connection));
|
||||||
|
nm_keyfile_connection_set_path (connection, name);
|
||||||
|
} else {
|
||||||
|
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "new connection %s", name);
|
||||||
|
g_hash_table_insert (priv->connections,
|
||||||
|
(gpointer) nm_connection_get_uuid (NM_CONNECTION (tmp)),
|
||||||
|
tmp);
|
||||||
|
g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dir_changed (GFileMonitor *monitor,
|
dir_changed (GFileMonitor *monitor,
|
||||||
GFile *file,
|
GFile *file,
|
||||||
|
@ -171,10 +210,8 @@ dir_changed (GFileMonitor *monitor,
|
||||||
{
|
{
|
||||||
NMSystemConfigInterface *config = NM_SYSTEM_CONFIG_INTERFACE (user_data);
|
NMSystemConfigInterface *config = NM_SYSTEM_CONFIG_INTERFACE (user_data);
|
||||||
SCPluginKeyfile *self = SC_PLUGIN_KEYFILE (config);
|
SCPluginKeyfile *self = SC_PLUGIN_KEYFILE (config);
|
||||||
SCPluginKeyfilePrivate *priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (self);
|
NMKeyfileConnection *connection;
|
||||||
char *full_path;
|
char *full_path;
|
||||||
NMKeyfileConnection *connection, *tmp;
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
full_path = g_file_get_path (file);
|
full_path = g_file_get_path (file);
|
||||||
if (nm_keyfile_plugin_utils_should_ignore_file (full_path)) {
|
if (nm_keyfile_plugin_utils_should_ignore_file (full_path)) {
|
||||||
|
@ -186,67 +223,15 @@ dir_changed (GFileMonitor *monitor,
|
||||||
|
|
||||||
switch (event_type) {
|
switch (event_type) {
|
||||||
case G_FILE_MONITOR_EVENT_DELETED:
|
case G_FILE_MONITOR_EVENT_DELETED:
|
||||||
if (connection) {
|
if (connection)
|
||||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "removed %s.", full_path);
|
|
||||||
remove_connection (SC_PLUGIN_KEYFILE (config), connection);
|
remove_connection (SC_PLUGIN_KEYFILE (config), connection);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case G_FILE_MONITOR_EVENT_CREATED:
|
case G_FILE_MONITOR_EVENT_CREATED:
|
||||||
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
|
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
|
||||||
if (connection) {
|
if (connection)
|
||||||
/* Update */
|
update_connection (SC_PLUGIN_KEYFILE (config), connection, full_path);
|
||||||
tmp = nm_keyfile_connection_new (NULL, full_path, &error);
|
else
|
||||||
if (tmp) {
|
new_connection (SC_PLUGIN_KEYFILE (config), full_path, NULL);
|
||||||
if (!nm_connection_compare (NM_CONNECTION (connection),
|
|
||||||
NM_CONNECTION (tmp),
|
|
||||||
NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS |
|
|
||||||
NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) {
|
|
||||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "updating %s", full_path);
|
|
||||||
if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (connection),
|
|
||||||
NM_CONNECTION (tmp),
|
|
||||||
FALSE, /* don't set Unsaved */
|
|
||||||
&error)) {
|
|
||||||
/* Shouldn't ever get here as 'new' was verified by the reader already */
|
|
||||||
g_assert_no_error (error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_object_unref (tmp);
|
|
||||||
} else {
|
|
||||||
/* Error; remove the connection */
|
|
||||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, " error: %s",
|
|
||||||
(error && error->message) ? error->message : "(unknown)");
|
|
||||||
g_clear_error (&error);
|
|
||||||
remove_connection (SC_PLUGIN_KEYFILE (config), connection);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* New */
|
|
||||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "updating %s", full_path);
|
|
||||||
tmp = nm_keyfile_connection_new (NULL, full_path, &error);
|
|
||||||
if (tmp) {
|
|
||||||
/* Connection renames will show as different paths but same UUID */
|
|
||||||
connection = g_hash_table_lookup (priv->connections, nm_connection_get_uuid (NM_CONNECTION (tmp)));
|
|
||||||
if (connection) {
|
|
||||||
if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (connection),
|
|
||||||
NM_CONNECTION (tmp),
|
|
||||||
FALSE, /* don't set Unsaved */
|
|
||||||
&error)) {
|
|
||||||
/* Shouldn't ever get here as 'tmp' was verified by the reader already */
|
|
||||||
g_assert_no_error (error);
|
|
||||||
}
|
|
||||||
g_object_unref (tmp);
|
|
||||||
nm_keyfile_connection_set_path (connection, full_path);
|
|
||||||
} else {
|
|
||||||
g_hash_table_insert (priv->connections,
|
|
||||||
(gpointer) nm_connection_get_uuid (NM_CONNECTION (tmp)),
|
|
||||||
tmp);
|
|
||||||
g_signal_emit_by_name (config, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, tmp);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, " error: %s",
|
|
||||||
(error && error->message) ? error->message : "(unknown)");
|
|
||||||
g_clear_error (&error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -299,13 +284,15 @@ setup_monitoring (NMSystemConfigInterface *config)
|
||||||
GFile *file;
|
GFile *file;
|
||||||
GFileMonitor *monitor;
|
GFileMonitor *monitor;
|
||||||
|
|
||||||
file = g_file_new_for_path (KEYFILE_DIR);
|
if (nm_config_get_monitor_connection_files (nm_config_get ())) {
|
||||||
monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
|
file = g_file_new_for_path (KEYFILE_DIR);
|
||||||
g_object_unref (file);
|
monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
|
||||||
|
g_object_unref (file);
|
||||||
|
|
||||||
if (monitor) {
|
if (monitor) {
|
||||||
priv->monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (dir_changed), config);
|
priv->monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (dir_changed), config);
|
||||||
priv->monitor = monitor;
|
priv->monitor = monitor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->conf_file) {
|
if (priv->conf_file) {
|
||||||
|
@ -320,6 +307,66 @@ setup_monitoring (NMSystemConfigInterface *config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
read_connections (NMSystemConfigInterface *config)
|
||||||
|
{
|
||||||
|
SCPluginKeyfile *self = SC_PLUGIN_KEYFILE (config);
|
||||||
|
SCPluginKeyfilePrivate *priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (self);
|
||||||
|
GDir *dir;
|
||||||
|
GError *error = NULL;
|
||||||
|
const char *item;
|
||||||
|
GHashTable *oldconns;
|
||||||
|
GHashTableIter iter;
|
||||||
|
gpointer data;
|
||||||
|
|
||||||
|
dir = g_dir_open (KEYFILE_DIR, 0, &error);
|
||||||
|
if (!dir) {
|
||||||
|
PLUGIN_WARN (KEYFILE_PLUGIN_NAME, "Cannot read directory '%s': (%d) %s",
|
||||||
|
KEYFILE_DIR,
|
||||||
|
error ? error->code : -1,
|
||||||
|
error && error->message ? error->message : "(unknown)");
|
||||||
|
g_clear_error (&error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
oldconns = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||||
|
g_hash_table_iter_init (&iter, priv->connections);
|
||||||
|
while (g_hash_table_iter_next (&iter, NULL, &data))
|
||||||
|
g_hash_table_insert (oldconns, g_strdup (nm_keyfile_connection_get_path (data)), data);
|
||||||
|
|
||||||
|
while ((item = g_dir_read_name (dir))) {
|
||||||
|
NMKeyfileConnection *connection;
|
||||||
|
char *full_path, *old_path;
|
||||||
|
|
||||||
|
if (nm_keyfile_plugin_utils_should_ignore_file (item))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
full_path = g_build_filename (KEYFILE_DIR, item, NULL);
|
||||||
|
|
||||||
|
connection = g_hash_table_lookup (oldconns, full_path);
|
||||||
|
if (connection) {
|
||||||
|
g_hash_table_remove (oldconns, full_path);
|
||||||
|
update_connection (self, connection, full_path);
|
||||||
|
} else {
|
||||||
|
new_connection (self, full_path, &old_path);
|
||||||
|
if (old_path) {
|
||||||
|
g_hash_table_remove (oldconns, old_path);
|
||||||
|
g_free (old_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (full_path);
|
||||||
|
}
|
||||||
|
g_dir_close (dir);
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, oldconns);
|
||||||
|
while (g_hash_table_iter_next (&iter, NULL, &data)) {
|
||||||
|
g_hash_table_iter_remove (&iter);
|
||||||
|
remove_connection (self, data);
|
||||||
|
}
|
||||||
|
g_hash_table_destroy (oldconns);
|
||||||
|
}
|
||||||
|
|
||||||
/* Plugin */
|
/* Plugin */
|
||||||
|
|
||||||
static GSList *
|
static GSList *
|
||||||
|
@ -342,6 +389,12 @@ get_connections (NMSystemConfigInterface *config)
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reload_connections (NMSystemConfigInterface *config)
|
||||||
|
{
|
||||||
|
read_connections (config);
|
||||||
|
}
|
||||||
|
|
||||||
static NMSettingsConnection *
|
static NMSettingsConnection *
|
||||||
add_connection (NMSystemConfigInterface *config,
|
add_connection (NMSystemConfigInterface *config,
|
||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
|
@ -634,6 +687,7 @@ system_config_interface_init (NMSystemConfigInterface *system_config_interface_c
|
||||||
{
|
{
|
||||||
/* interface implementation */
|
/* interface implementation */
|
||||||
system_config_interface_class->get_connections = get_connections;
|
system_config_interface_class->get_connections = get_connections;
|
||||||
|
system_config_interface_class->reload_connections = reload_connections;
|
||||||
system_config_interface_class->add_connection = add_connection;
|
system_config_interface_class->add_connection = add_connection;
|
||||||
system_config_interface_class->get_unmanaged_specs = get_unmanaged_specs;
|
system_config_interface_class->get_unmanaged_specs = get_unmanaged_specs;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue