summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-07-25 21:43:53 +0200
committerThomas Haller <thaller@redhat.com>2019-07-25 21:43:53 +0200
commit40355d03a49920b4c87119d306d7216ee0990b41 (patch)
tree097f1c02d6da4c4651c59793a134ab866f05e931
parent9dfc3ff5af44324abe92001d2588dced3372da1b (diff)
parent360d26e27c0872b2bc96e9dd9d49c4eb6187180d (diff)
downloadNetworkManager-40355d03a49920b4c87119d306d7216ee0990b41.tar.gz
libnm,core: merge branch 'th/settings-add2-and-update2-options'
https://bugzilla.redhat.com/show_bug.cgi?id=1677068 https://bugzilla.redhat.com/show_bug.cgi?id=1677070 https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/201
-rw-r--r--Makefile.examples1
-rw-r--r--clients/cli/connections.c230
-rwxr-xr-xexamples/python/gi/nm-add-connection2.py156
-rw-r--r--introspection/org.freedesktop.NetworkManager.Settings.xml35
-rw-r--r--libnm-core/nm-dbus-interface.h29
-rw-r--r--libnm/libnm.ver3
-rw-r--r--libnm/nm-client.c174
-rw-r--r--libnm/nm-client.h16
-rw-r--r--libnm/nm-remote-settings.c257
-rw-r--r--libnm/nm-remote-settings.h23
-rw-r--r--shared/nm-glib-aux/nm-macros-internal.h5
-rw-r--r--src/devices/bluetooth/nm-bluez-device.c1
-rw-r--r--src/devices/wifi/nm-iwd-manager.c1
-rw-r--r--src/nm-checkpoint.c1
-rw-r--r--src/nm-manager.c2
-rw-r--r--src/settings/nm-settings-connection.c32
-rw-r--r--src/settings/nm-settings-connection.h15
-rw-r--r--src/settings/nm-settings.c133
-rw-r--r--src/settings/nm-settings.h2
19 files changed, 848 insertions, 268 deletions
diff --git a/Makefile.examples b/Makefile.examples
index 92923a8db6..dcd1ac9d18 100644
--- a/Makefile.examples
+++ b/Makefile.examples
@@ -176,6 +176,7 @@ EXTRA_DIST += \
examples/python/gi/get-active-connections.py \
examples/python/gi/get_ips.py \
examples/python/gi/list-connections.py \
+ examples/python/gi/nm-add-connection2.py \
examples/python/gi/nm-connection-update-stable-id.py \
examples/python/gi/nm-wg-set \
examples/python/gi/setting-user-data.py \
diff --git a/clients/cli/connections.c b/clients/cli/connections.c
index 25622c7d5d..53105f957f 100644
--- a/clients/cli/connections.c
+++ b/clients/cli/connections.c
@@ -41,6 +41,8 @@
#include "devices.h"
#include "polkit-agent.h"
+/*****************************************************************************/
+
typedef enum {
PROPERTY_INF_FLAG_NONE = 0x0,
PROPERTY_INF_FLAG_DISABLED = 0x1, /* Don't ask due to runtime decision. */
@@ -50,14 +52,13 @@ typedef enum {
typedef char *(*CompEntryFunc) (const char *, int);
-typedef struct _OptionInfo OptionInfo;
-struct _OptionInfo {
+typedef struct _OptionInfo {
const NMMetaSettingInfoEditor *setting_info;
const char *property;
const char *option;
- gboolean (*check_and_set)(NmCli *nmc, NMConnection *connection, const OptionInfo *option, const char *value, GError **error);
+ gboolean (*check_and_set)(NmCli *nmc, NMConnection *connection, const struct _OptionInfo *option, const char *value, GError **error);
CompEntryFunc generator_func;
-};
+} OptionInfo;
/* define some prompts for connection editor */
#define EDITOR_PROMPT_SETTING _("Setting name? ")
@@ -96,6 +97,47 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (vpn_connection_state_to_string, NMVpnConnecti
NM_UTILS_LOOKUP_ITEM_IGNORE (NM_VPN_CONNECTION_STATE_UNKNOWN),
)
+/*****************************************************************************/
+
+typedef struct {
+ NmCli *nmc;
+ char *orig_id;
+ char *orig_uuid;
+ char *new_id;
+} AddConnectionInfo;
+
+static AddConnectionInfo *
+_add_connection_info_new (NmCli *nmc,
+ NMConnection *orig_connection,
+ NMConnection *new_connection)
+{
+ AddConnectionInfo *info;
+
+ info = g_slice_new (AddConnectionInfo);
+ *info = (AddConnectionInfo) {
+ .nmc = nmc,
+ .orig_id = orig_connection ? g_strdup (nm_connection_get_id (orig_connection)) : NULL,
+ .orig_uuid = orig_connection ? g_strdup (nm_connection_get_uuid (orig_connection)) : NULL,
+ .new_id = g_strdup (nm_connection_get_id (new_connection)),
+ };
+ return info;
+}
+
+static void
+_add_connection_info_free (AddConnectionInfo *info)
+{
+ g_free (info->orig_id);
+ g_free (info->orig_uuid);
+ g_free (info->new_id);
+ nm_g_slice_free (info);
+}
+
+NM_AUTO_DEFINE_FCN (AddConnectionInfo *, _nm_auto_free_add_connection_info, _add_connection_info_free)
+
+#define nm_auto_free_add_connection_info nm_auto (_nm_auto_free_add_connection_info)
+
+/*****************************************************************************/
+
/* Essentially a version of nm_setting_connection_get_connection_type() that
* prefers an alias instead of the settings name when in pretty print mode.
* That is so that we print "wifi" instead of "802-11-wireless" in "nmcli c". */
@@ -4755,28 +4797,23 @@ nmc_read_connection_properties (NmCli *nmc,
return TRUE;
}
-typedef struct {
- NmCli *nmc;
- char *con_name;
-} AddConnectionInfo;
-
static void
add_connection_cb (GObject *client,
GAsyncResult *result,
gpointer user_data)
{
- AddConnectionInfo *info = (AddConnectionInfo *) user_data;
+ nm_auto_free_add_connection_info AddConnectionInfo *info = user_data;
NmCli *nmc = info->nmc;
NMRemoteConnection *connection;
GError *error = NULL;
const GPtrArray *connections;
guint i, found;
- connection = nm_client_add_connection_finish (NM_CLIENT (client), result, &error);
+ connection = nm_client_add_connection2_finish (NM_CLIENT (client), result, NULL, &error);
if (error) {
g_string_printf (nmc->return_text,
_("Error: Failed to add '%s' connection: %s"),
- info->con_name, error->message);
+ info->new_id, error->message);
g_error_free (error);
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
} else {
@@ -4788,7 +4825,7 @@ add_connection_cb (GObject *client,
if ((NMConnection *) connection == candidate)
continue;
- if (nm_streq0 (nm_connection_get_id (candidate), info->con_name))
+ if (nm_streq0 (nm_connection_get_id (candidate), info->new_id))
found++;
}
if (found > 0) {
@@ -4796,7 +4833,7 @@ add_connection_cb (GObject *client,
"Warning: There is another connection with the name '%1$s'. Reference the connection by its uuid '%2$s'\n",
"Warning: There are %3$u other connections with the name '%1$s'. Reference the connection by its uuid '%2$s'\n",
found),
- info->con_name,
+ info->new_id,
nm_connection_get_uuid (NM_CONNECTION (connection)),
found);
}
@@ -4808,30 +4845,39 @@ add_connection_cb (GObject *client,
g_object_unref (connection);
}
- g_free (info->con_name);
- g_free (info);
quit ();
}
static void
-add_new_connection (gboolean persistent,
- NMClient *client,
- NMConnection *connection,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- nm_client_add_connection_async (client, connection, persistent,
- NULL, callback, user_data);
+add_connection (NMClient *client,
+ NMConnection *connection,
+ gboolean temporary,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ nm_client_add_connection2 (client,
+ nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL),
+ temporary
+ ? NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY
+ : NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK,
+ NULL,
+ TRUE,
+ NULL,
+ callback,
+ user_data);
}
static void
-update_connection (gboolean persistent,
- NMRemoteConnection *connection,
+update_connection (NMRemoteConnection *connection,
+ gboolean temporary,
GAsyncReadyCallback callback,
gpointer user_data)
{
- nm_remote_connection_commit_changes_async (connection, persistent,
- NULL, callback, user_data);
+ nm_remote_connection_commit_changes_async (connection,
+ !temporary,
+ NULL,
+ callback,
+ user_data);
}
static gboolean
@@ -5150,7 +5196,6 @@ do_connection_add (NmCli *nmc, int argc, char **argv)
gs_unref_object NMConnection *connection = NULL;
NMSettingConnection *s_con;
gs_free_error GError *error = NULL;
- AddConnectionInfo *info = NULL;
gboolean save_bool = TRUE;
gboolean seen_dash_dash = FALSE;
NMMetaSettingType s;
@@ -5295,19 +5340,13 @@ read_properties:
}
}
+ add_connection (nmc->client,
+ connection,
+ !save_bool,
+ add_connection_cb,
+ _add_connection_info_new (nmc, NULL, connection));
nmc->should_wait++;
- info = g_malloc0 (sizeof (AddConnectionInfo));
- info->nmc = nmc;
- info->con_name = g_strdup (nm_connection_get_id (connection));
-
- /* Tell the settings service to add the new connection */
- add_new_connection (save_bool,
- nmc->client,
- connection,
- add_connection_cb,
- info);
-
finish:
reset_options ();
return nmc->return_value;
@@ -6656,14 +6695,11 @@ add_connection_editor_cb (GObject *client,
GAsyncResult *result,
gpointer user_data)
{
- NMRemoteConnection *connection;
- GError *error = NULL;
+ gs_unref_object NMRemoteConnection *connection = NULL;
+ gs_free_error GError *error = NULL;
- connection = nm_client_add_connection_finish (NM_CLIENT (client), result, &error);
+ connection = nm_client_add_connection2_finish (NM_CLIENT (client), result, NULL, &error);
set_info_and_signal_editor_thread (error, NULL);
-
- g_clear_object (&connection);
- g_clear_error (&error);
}
static void
@@ -7242,7 +7278,6 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
const NMMetaSettingValidPartItem *const*valid_settings_slave;
gs_free char *valid_settings_str = NULL;
const char *s_type = NULL;
- AddConnectionInfo *info = NULL;
gboolean temp_changes;
GError *err1 = NULL;
NmcEditorMenuContext menu_ctx = { 0 };
@@ -7761,7 +7796,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
case NMC_EDITOR_MAIN_CMD_SAVE:
/* Save the connection */
if (nm_connection_verify (connection, &err1)) {
- gboolean persistent = TRUE;
+ gboolean temporary = FALSE;
gboolean connection_changed;
nm_auto_unref_gsource GSource *source = NULL;
gboolean timeout = FALSE;
@@ -7770,9 +7805,9 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
/* parse argument */
if (cmd_arg) {
if (matches (cmd_arg, "temporary"))
- persistent = FALSE;
+ temporary = TRUE;
else if (matches (cmd_arg, "persistent"))
- persistent = TRUE;
+ temporary = FALSE;
else {
g_print (_("Error: invalid argument '%s'\n"), cmd_arg);
break;
@@ -7788,21 +7823,17 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
}
if (!rem_con) {
- /* Tell the settings service to add the new connection */
- info = g_malloc0 (sizeof (AddConnectionInfo));
- info->nmc = nmc;
- info->con_name = g_strdup (nm_connection_get_id (connection));
- add_new_connection (persistent,
- nmc->client,
- connection,
- add_connection_editor_cb,
- info);
+ add_connection (nmc->client,
+ connection,
+ temporary,
+ add_connection_editor_cb,
+ NULL);
connection_changed = TRUE;
} else {
/* Save/update already saved (existing) connection */
nm_connection_replace_settings_from_connection (NM_CONNECTION (rem_con),
connection);
- update_connection (persistent, rem_con, update_connection_editor_cb, NULL);
+ update_connection (rem_con, temporary, update_connection_editor_cb, NULL);
handler_id = g_signal_connect (rem_con,
NM_CONNECTION_CHANGED,
@@ -8403,35 +8434,27 @@ do_connection_modify (NmCli *nmc,
if (nmc->complete)
return nmc->return_value;
- update_connection (!temporary, rc, modify_connection_cb, nmc);
+ update_connection (rc, temporary, modify_connection_cb, nmc);
nmc->should_wait++;
return nmc->return_value;
}
-typedef struct {
- NmCli *nmc;
- char *orig_id;
- char *orig_uuid;
- char *con_id;
-} CloneConnectionInfo;
-
static void
clone_connection_cb (GObject *client,
GAsyncResult *result,
gpointer user_data)
{
- CloneConnectionInfo *info = (CloneConnectionInfo *) user_data;
+ nm_auto_free_add_connection_info AddConnectionInfo *info = user_data;
NmCli *nmc = info->nmc;
- NMRemoteConnection *connection;
- GError *error = NULL;
+ gs_unref_object NMRemoteConnection *connection = NULL;
+ gs_free_error GError *error = NULL;
- connection = nm_client_add_connection_finish (NM_CLIENT (client), result, &error);
+ connection = nm_client_add_connection2_finish (NM_CLIENT (client), result, NULL, &error);
if (error) {
g_string_printf (nmc->return_text,
_("Error: Failed to add '%s' connection: %s"),
- info->con_id, error->message);
- g_error_free (error);
+ info->new_id, error->message);
nmc->return_value = NMC_RESULT_ERROR_CON_ACTIVATION;
} else {
g_print (_("%s (%s) cloned as %s (%s).\n"),
@@ -8439,13 +8462,8 @@ clone_connection_cb (GObject *client,
info->orig_uuid,
nm_connection_get_id (NM_CONNECTION (connection)),
nm_connection_get_uuid (NM_CONNECTION (connection)));
- g_object_unref (connection);
}
- g_free (info->con_id);
- g_free (info->orig_id);
- g_free (info->orig_uuid);
- g_slice_free (CloneConnectionInfo, info);
quit ();
}
@@ -8454,11 +8472,9 @@ do_connection_clone (NmCli *nmc, int argc, char **argv)
{
NMConnection *connection = NULL;
gs_unref_object NMConnection *new_connection = NULL;
- NMSettingConnection *s_con;
- CloneConnectionInfo *info;
const char *new_name;
- gs_free char *new_name_ask = NULL;
- char *uuid;
+ gs_free char *new_name_free = NULL;
+ gs_free char *uuid = NULL;
gboolean temporary = FALSE;
char **arg_arr = NULL;
int arg_num;
@@ -8499,8 +8515,8 @@ do_connection_clone (NmCli *nmc, int argc, char **argv)
if (argv[0])
new_name = *argv;
else if (nmc->ask) {
- new_name = new_name_ask = nmc_readline (&nmc->nmc_config,
- _("New connection name: "));
+ new_name = new_name_free = nmc_readline (&nmc->nmc_config,
+ _("New connection name: "));
} else {
g_string_printf (nmc->return_text, _("Error: <new name> argument is missing."));
NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT);
@@ -8511,35 +8527,23 @@ do_connection_clone (NmCli *nmc, int argc, char **argv)
NMC_RETURN (nmc, NMC_RESULT_ERROR_USER_INPUT);
}
- /* Copy the connection */
new_connection = nm_simple_connection_new_clone (connection);
- s_con = nm_connection_get_setting_connection (new_connection);
- g_assert (s_con);
uuid = nm_utils_uuid_generate ();
- g_object_set (s_con,
+ g_object_set (nm_connection_get_setting_connection (new_connection),
NM_SETTING_CONNECTION_ID, new_name,
NM_SETTING_CONNECTION_UUID, uuid,
NULL);
- g_free (uuid);
- /* Merge secrets into the new connection */
update_secrets_in_connection (NM_REMOTE_CONNECTION (connection), new_connection);
- info = g_slice_new0 (CloneConnectionInfo);
- info->nmc = nmc;
- info->orig_id = g_strdup (nm_connection_get_id (connection));
- info->orig_uuid = g_strdup (nm_connection_get_uuid (connection));
- info->con_id = g_strdup (nm_connection_get_id (new_connection));
-
- /* Add the new cloned connection to NetworkManager */
- add_new_connection (!temporary,
- nmc->client,
- new_connection,
- clone_connection_cb,
- info);
-
+ add_connection (nmc->client,
+ new_connection,
+ temporary,
+ clone_connection_cb,
+ _add_connection_info_new (nmc, connection, new_connection));
nmc->should_wait++;
+
return nmc->return_value;
}
@@ -8826,7 +8830,6 @@ do_connection_import (NmCli *nmc, int argc, char **argv)
const char *type = NULL, *filename = NULL;
gs_free char *type_ask = NULL;
gs_free char *filename_ask = NULL;
- AddConnectionInfo *info;
gs_unref_object NMConnection *connection = NULL;
NMVpnEditorPlugin *plugin;
gs_free char *service_type = NULL;
@@ -8943,18 +8946,13 @@ do_connection_import (NmCli *nmc, int argc, char **argv)
NMC_RETURN (nmc, NMC_RESULT_ERROR_UNKNOWN);
}
- info = g_malloc0 (sizeof (AddConnectionInfo));
- info->nmc = nmc;
- info->con_name = g_strdup (nm_connection_get_id (connection));
-
- /* Add the new imported connection to NetworkManager */
- add_new_connection (!temporary,
- nmc->client,
- connection,
- add_connection_cb,
- info);
-
+ add_connection (nmc->client,
+ connection,
+ temporary,
+ add_connection_cb,
+ _add_connection_info_new (nmc, NULL, connection));
nmc->should_wait++;
+
return nmc->return_value;
}
diff --git a/examples/python/gi/nm-add-connection2.py b/examples/python/gi/nm-add-connection2.py
new file mode 100755
index 0000000000..b78016dba4
--- /dev/null
+++ b/examples/python/gi/nm-add-connection2.py
@@ -0,0 +1,156 @@
+#!/usr/bin/env python
+#
+# 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 2019 Red Hat, Inc.
+#
+
+import sys
+import re
+
+import gi
+gi.require_version('NM', '1.0')
+from gi.repository import GLib, NM
+
+def find_connections(nm_client, arg_type, arg_id):
+ for c in nm_client.get_connections():
+ if arg_type in [None, 'id'] and c.get_id() == arg_id:
+ yield c
+ if arg_type in [None, 'uuid'] and c.get_uuid() == arg_id:
+ yield c
+
+def find_connection_first(nm_client, arg_type, arg_id):
+ for f in find_connections(nm_client, arg_type, arg_id):
+ return f
+
+def con_to_str(con):
+ s_con = con.get_setting_connection()
+ return '"%s" (%s)' % (s_con.get_id(), s_con.get_uuid())
+
+def usage():
+ print('Usage: %s --clone [[id] <id>]' % (sys.argv[0]))
+ print(' %s --clone [[uuid] <uuid>]' % (sys.argv[0]))
+ return 1
+
+def die(msg, print_usage=False):
+ print(msg)
+ if print_usage:
+ usage()
+ sys.exit(1)
+
+def main():
+
+ main_loop = GLib.MainLoop()
+
+ nm_client = NM.Client.new(None)
+
+ arg_mode = None
+ arg_block_autoconnect = NM.SettingsAddConnection2Flags.NONE
+ arg_id = None
+ arg_uuid = None
+
+ cons = []
+
+ argv = list(sys.argv[1:])
+ while argv:
+ if argv[0] == '--clone':
+ match_type = None
+ if len(argv) < 2:
+ die('missing argument for --clone option')
+ if argv[0] in ['id', 'uuid']:
+ match_type = argv[0]
+ if len(argv) < 3:
+ die('missing argument for "--clone %s" option' % (match_type))
+ argv = argv[1:]
+ if cons:
+ die('cannot specify --clone argument more than once')
+ cons.extend(find_connections(nm_client, match_type, argv[1]))
+ if len(cons) == 0:
+ die('could not find connection for "--clone %s%s"' % ((match_type or ''), argv[1]))
+ if len(cons) != 1:
+ die('could not find unique connection for "--clone %s%s"' % ((match_type or ''), argv[1]))
+ argv = argv[2:]
+ continue
+ if argv[0] in ['--block-autoconnect']:
+ arg_block_autoconnect = NM.SettingsAddConnection2Flags.BLOCK_AUTOCONNECT
+ argv = argv[1:]
+ continue
+ if argv[0] in ['--to-disk', '--in-memory']:
+ if argv[0] == '--to-disk':
+ v = NM.SettingsAddConnection2Flags.TO_DISK
+ elif argv[0] == '--in-memory':
+ v = NM.SettingsAddConnection2Flags.IN_MEMORY
+ else:
+ assert(False)
+ if arg_mode is not None:
+ die('duplicate storage modes ("%s")' % (argv[0]))
+ arg_mode = v
+ argv = argv[1:]
+ continue
+ if argv[0] in ['--id']:
+ if len(argv) < 2:
+ die('missing argument for --id option')
+ arg_id = argv[1]
+ argv = argv[2:]
+ continue
+ if argv[0] in ['--uuid']:
+ if len(argv) < 2:
+ die('missing argument for --uuid option')
+ arg_uuid = argv[1]
+ argv = argv[2:]
+ continue
+ die('unknown argument "%s"' % (argv[0]))
+
+ if len(cons) != 1:
+ die('missing --clone argument', True)
+
+ con = cons[0]
+
+ con2 = NM.SimpleConnection.new_clone(con)
+
+ s_con = con2.get_setting_connection()
+ if arg_id:
+ s_con.set_property(NM.SETTING_CONNECTION_ID, arg_id)
+ s_con.set_property(NM.SETTING_CONNECTION_UUID, arg_uuid or NM.utils_uuid_generate())
+
+ result = {}
+ def _add_connection2_cb(cl, async_result, user_data):
+ try:
+ c, r = nm_client.add_connection2_finish(async_result)
+ except Exception as e:
+ result['error'] = e
+ else:
+ result['result'] = r
+ result['connection'] = c
+ main_loop.quit()
+
+ nm_client.add_connection2(con2.to_dbus(NM.ConnectionSerializationFlags.ALL),
+ (arg_mode if arg_mode is not None else NM.SettingsAddConnection2Flags.TO_DISK)
+ | arg_block_autoconnect,
+ None,
+ False,
+ None,
+ _add_connection2_cb,
+ None)
+
+ main_loop.run()
+
+ if 'error' in result:
+ die('update connection %s failed [%s]: %s' % (con_to_str(con2), ' '.join(sys.argv), result['error']))
+
+ print('update connection %s succeeded [%s]: %s, %s' % (con_to_str(con2), ' '.join(sys.argv), result['connection'].get_path(), result['result']))
+
+if __name__ == '__main__':
+ main()
diff --git a/introspection/org.freedesktop.NetworkManager.Settings.xml b/introspection/org.freedesktop.NetworkManager.Settings.xml
index 73da345ceb..f7be2717b8 100644
--- a/introspection/org.freedesktop.NetworkManager.Settings.xml
+++ b/introspection/org.freedesktop.NetworkManager.Settings.xml
@@ -64,6 +64,41 @@
</method>
<!--
+ AddConnection2:
+ @settings: New connection settings, properties, and (optionally) secrets.
+ @flags: optional flags argument. Currently the following flags are supported:
+ "0x1" (to-disk),
+ "0x2" (in-memory),
+ "0x20" (block-autoconnect).
+ Unknown flags cause the call to fail.
+ @args: optional arguments dictionary, for extensibility. Currently no
+ arguments are accepted. Specifying unknown keys causes the call
+ to fail.
+ @path: Object path of the new connection that was just added.
+ @result: output argument, currently no additional results are returned.
+
+ Add a new connection profile.
+
+ Either the flags 0x1 (to-disk) or 0x2 (in-memory) must be specified.
+ The effect is whether to behave like AddConnection or AddConnectionUnsaved.
+ If 0x20 (block-autoconnect) is specified, autoconnect for the new profile
+ is blocked from the beginnin. Otherwise, the profile might automatically
+ connect if a suitable device is around.
+
+ AddConnection2 is a extensible alternative to AddConnection, and AddConnectionUnsaved.
+ The new variant can do everything that the older variants could, and more.
+
+ Since: 1.20
+ -->
+ <method name="AddConnection2">
+ <arg name="settings" type="a{sa{sv}}" direction="in"/>
+ <arg name="flags" type="u" direction="in"/>
+ <arg name="args" type="a{sv}" direction="in"/>
+ <arg name="path" type="o" direction="out"/>
+ <arg name="result" type="a{sv}" direction="out"/>
+ </method>
+
+ <!--
LoadConnections:
@filenames: Array of paths to on-disk connection profiles in directories monitored by NetworkManager.
@status: Success or failure of the operation as a whole. True if NetworkManager at least tried to load the indicated connections, even if it did not succeed. False if an error occurred before trying to load the connections (eg, permission denied).
diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h
index c68c7757b2..b2569af1ef 100644
--- a/libnm-core/nm-dbus-interface.h
+++ b/libnm-core/nm-dbus-interface.h
@@ -1006,6 +1006,27 @@ typedef enum { /*< flags >*/
} NMActivationStateFlags;
/**
+ * NMSettingsAddConnection2Flags:
+ * @NM_SETTINGS_ADD_CONNECTION2_FLAG_NONE: an alias for numeric zero, no flags set.
+ * @NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK: to persist the connection to disk.
+ * @NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY: to make the connection in-memory only.
+ * @NM_SETTINGS_ADD_CONNECTION2_FLAG_BLOCK_AUTOCONNECT: usually, when the connection
+ * has autoconnect enabled and gets added, it becomes eligible to autoconnect
+ * right away. Setting this flag, disables autoconnect until the connection
+ * is manually activated.
+ *
+ * Numeric flags for the "flags" argument of AddConnection2() D-Bus API.
+ *
+ * Since: 1.20
+ */
+typedef enum { /*< flags >*/
+ NM_SETTINGS_ADD_CONNECTION2_FLAG_NONE = 0,
+ NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK = 0x1,
+ NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY = 0x2,
+ NM_SETTINGS_ADD_CONNECTION2_FLAG_BLOCK_AUTOCONNECT = 0x20,
+} NMSettingsAddConnection2Flags;
+
+/**
* NMSettingsUpdate2Flags:
* @NM_SETTINGS_UPDATE2_FLAG_NONE: an alias for numeric zero, no flags set.
* @NM_SETTINGS_UPDATE2_FLAG_TO_DISK: to persist the connection to disk.
@@ -1039,6 +1060,13 @@ typedef enum { /*< flags >*/
* has autoconnect enabled and is modified, it becomes eligible to autoconnect
* right away. Setting this flag, disables autoconnect until the connection
* is manually activated.
+ * @NM_SETTINGS_UPDATE2_FLAG_NO_REAPPLY: when a profile gets modified that is
+ * currently active, then these changes don't take effect for the active
+ * device unless the profile gets reactivated or the configuration reapplied.
+ * There are two exceptions: by default "connection.zone" and "connection.metered"
+ * properties take effect immediately. Specify this flag to prevent these
+ * properties to take effect, so that the change is restricted to modify
+ * the profile. Since: 1.20.
*
* Since: 1.12
*/
@@ -1050,6 +1078,7 @@ typedef enum { /*< flags >*/
NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_ONLY = 0x8,
NM_SETTINGS_UPDATE2_FLAG_VOLATILE = 0x10,
NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT = 0x20,
+ NM_SETTINGS_UPDATE2_FLAG_NO_REAPPLY = 0x40,
} NMSettingsUpdate2Flags;
/**
diff --git a/libnm/libnm.ver b/libnm/libnm.ver
index 7118bf2bc8..fb5c06b6e6 100644
--- a/libnm/libnm.ver
+++ b/libnm/libnm.ver
@@ -1611,6 +1611,8 @@ global:
libnm_1_20_0 {
global:
+ nm_client_add_connection2;
+ nm_client_add_connection2_finish;
nm_client_connectivity_check_get_uri;
nm_device_modem_get_apn;
nm_device_modem_get_device_id;
@@ -1622,4 +1624,5 @@ global:
nm_setting_ovs_dpdk_get_devargs;
nm_setting_ovs_dpdk_get_type;
nm_setting_ovs_dpdk_new;
+ nm_settings_add_connection2_flags_get_type;
} libnm_1_18_0;
diff --git a/libnm/nm-client.c b/libnm/nm-client.c
index a95540ed19..c39f62675b 100644
--- a/libnm/nm-client.c
+++ b/libnm/nm-client.c
@@ -1631,23 +1631,55 @@ nm_client_get_connection_by_uuid (NMClient *client, const char *uuid)
return nm_remote_settings_get_connection_by_uuid (NM_CLIENT_GET_PRIVATE (client)->settings, uuid);
}
+typedef struct {
+ NMRemoteConnection *connection;
+ GVariant *results;
+} AddConnection2CbData;
+
static void
-add_connection_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
+add_connection2_cb_data_destroy (gpointer user_data)
{
- GSimpleAsyncResult *simple = user_data;
- NMRemoteConnection *conn;
- GError *error = NULL;
+ AddConnection2CbData *data = user_data;
- conn = nm_remote_settings_add_connection_finish (NM_REMOTE_SETTINGS (object), result, &error);
- if (conn)
- g_simple_async_result_set_op_res_gpointer (simple, conn, g_object_unref);
- else
- g_simple_async_result_take_error (simple, error);
+ g_object_unref (data->connection);
+ nm_g_variant_unref (data->results);
+ nm_g_slice_free (data);
+}
+
+static void
+add_connection2_cb (NMRemoteSettings *self,
+ NMRemoteConnection *connection,
+ GVariant *results,
+ GError *error,
+ gpointer user_data)
+{
+ gs_unref_object GSimpleAsyncResult *simple = user_data;
+
+ if (error) {
+ g_simple_async_result_take_error (simple,
+ g_error_new_literal (error->domain,
+ error->code,
+ error->message));
+ } else if (g_simple_async_result_get_source_tag (simple) == nm_client_add_connection_async) {
+ g_simple_async_result_set_op_res_gpointer (simple,
+ g_object_ref (connection),
+ g_object_unref);
+ } else {
+ AddConnection2CbData *data;
+
+ nm_assert (g_simple_async_result_get_source_tag (simple) == nm_client_add_connection2);
+
+ data = g_slice_new (AddConnection2CbData);
+ *data = (AddConnection2CbData) {
+ .connection = g_object_ref (connection),
+ .results = nm_g_variant_ref (results),
+ };
+ g_simple_async_result_set_op_res_gpointer (simple,
+ data,
+ add_connection2_cb_data_destroy);
+ }
g_simple_async_result_complete (simple);
- g_object_unref (simple);
}
/**
@@ -1698,9 +1730,17 @@ nm_client_add_connection_async (NMClient *client,
nm_client_add_connection_async);
if (cancellable)
g_simple_async_result_set_check_cancellable (simple, cancellable);
- nm_remote_settings_add_connection_async (NM_CLIENT_GET_PRIVATE (client)->settings,
- connection, save_to_disk,
- cancellable, add_connection_cb, simple);
+
+ nm_remote_settings_add_connection2 (NM_CLIENT_GET_PRIVATE (client)->settings,
+ nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL),
+ save_to_disk
+ ? NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK
+ : NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY,
+ NULL,
+ TRUE,
+ cancellable,
+ add_connection2_cb,
+ simple);
}
/**
@@ -1722,13 +1762,111 @@ nm_client_add_connection_finish (NMClient *client,
GSimpleAsyncResult *simple;
g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
- g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), nm_client_add_connection_async), NULL);
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return NULL;
- else
- return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
+ return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
+}
+
+/**
+ * nm_client_add_connection2:
+ * @client: the %NMClient
+ * @settings: the "a{sa{sv}}" #GVariant with the content of the setting.
+ * @flags: the %NMSettingsAddConnection2Flags argument.
+ * @args: (allow-none): the "a{sv}" #GVariant with extra argument or %NULL
+ * for no extra arguments.
+ * @ignore_out_result: this function wraps AddConnection2(), which has an
+ * additional result "a{sv}" output parameter. By setting this to %TRUE,
+ * you signal that you are not interested in that output parameter.
+ * This allows the function to fall back to AddConnection() and AddConnectionUnsaved(),
+ * which is interesting if you run against an older server version that does
+ * not yet provide AddConnection2(). By setting this to %FALSE, the function
+ * under the hood always calls AddConnection2().
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: (scope async): callback to be called when the add operation completes
+ * @user_data: (closure): caller-specific data passed to @callback
+ *
+ * Call AddConnection2() D-Bus API asynchronously.
+ *
+ * Since: 1.20
+ **/
+void
+nm_client_add_connection2 (NMClient *client,
+ GVariant *settings,
+ NMSettingsAddConnection2Flags flags,
+ GVariant *args,
+ gboolean ignore_out_result,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ GError *error = NULL;
+
+ g_return_if_fail (NM_IS_CLIENT (client));
+ g_return_if_fail (g_variant_is_of_type (settings, G_VARIANT_TYPE ("a{sa{sv}}")));
+ g_return_if_fail (!args || g_variant_is_of_type (args, G_VARIANT_TYPE ("a{sv}")));
+
+ if (!_nm_client_check_nm_running (client, &error)) {
+ g_simple_async_report_take_gerror_in_idle (G_OBJECT (client), callback, user_data, error);
+ return;
+ }
+
+ simple = g_simple_async_result_new (G_OBJECT (client),
+ callback,
+ user_data,
+ nm_client_add_connection2);
+ if (cancellable)
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ nm_remote_settings_add_connection2 (NM_CLIENT_GET_PRIVATE (client)->settings,
+ settings,
+ flags,
+ args,
+ ignore_out_result,
+ cancellable,
+ add_connection2_cb,
+ simple);
+}
+
+/**
+ * nm_client_add_connection2_finish:
+ * @client: the #NMClient
+ * @result: the #GAsyncResult
+ * @out_result: (allow-none) (transfer full) (out): the output #GVariant
+ * from AddConnection2().
+ * If you care about the output result, then the "ignore_out_result"
+ * parameter of nm_client_add_connection2() must not be set to %TRUE.
+ * @error: (allow-none): the error argument.
+ *
+ * Returns: (transfer full): on success, a pointer to the added
+ * #NMRemoteConnection.
+ *
+ * Since: 1.20
+ */
+NMRemoteConnection *
+nm_client_add_connection2_finish (NMClient *client,
+ GAsyncResult *result,
+ GVariant **out_result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ AddConnection2CbData *data;
+
+ g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), nm_client_add_connection2), NULL);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ if (g_simple_async_result_propagate_error (simple, error)) {
+ NM_SET_OUT (out_result, NULL);
+ return NULL;
+ }
+
+ data = g_simple_async_result_get_op_res_gpointer (simple);
+ NM_SET_OUT (out_result, g_variant_ref (data->results));
+ return g_object_ref (data->connection);
}
/**
diff --git a/libnm/nm-client.h b/libnm/nm-client.h
index f3835864c8..ec7022ff6b 100644
--- a/libnm/nm-client.h
+++ b/libnm/nm-client.h
@@ -389,6 +389,22 @@ NMRemoteConnection *nm_client_add_connection_finish (NMClient *client,
GAsyncResult *result,
GError **error);
+NM_AVAILABLE_IN_1_20
+void nm_client_add_connection2 (NMClient *client,
+ GVariant *settings,
+ NMSettingsAddConnection2Flags flags,
+ GVariant *args,
+ gboolean ignore_out_result,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+NM_AVAILABLE_IN_1_20
+NMRemoteConnection *nm_client_add_connection2_finish (NMClient *client,
+ GAsyncResult *result,
+ GVariant **out_result,
+ GError **error);
+
gboolean nm_client_load_connections (NMClient *client,
char **filenames,
char ***failures,
diff --git a/libnm/nm-remote-settings.c b/libnm/nm-remote-settings.c
index 6b1d4c264e..916884ea08 100644
--- a/libnm/nm-remote-settings.c
+++ b/libnm/nm-remote-settings.c
@@ -22,6 +22,7 @@
#include "nm-remote-settings.h"
+#include "c-list/src/c-list.h"
#include "nm-dbus-interface.h"
#include "nm-connection.h"
#include "nm-client.h"
@@ -43,7 +44,7 @@ typedef struct {
GPtrArray *visible_connections;
/* AddConnectionInfo objects that are waiting for the connection to become initialized */
- GSList *add_list;
+ CList add_lst_head;
char *hostname;
gboolean can_modify;
@@ -70,51 +71,78 @@ static guint signals[LAST_SIGNAL] = { 0 };
/*****************************************************************************/
typedef struct {
+ CList add_lst;
NMRemoteSettings *self;
- GSimpleAsyncResult *simple;
+ NMRemoteSettingAddConnection2Callback callback;
+ gpointer user_data;
+ GCancellable *cancellable;
char *path;
- gboolean saved;
+ GVariant *results;
+ gulong cancellable_id;
+ NMSettingsAddConnection2Flags flags;
+ bool ignore_out_result:1;
} AddConnectionInfo;
static AddConnectionInfo *
-add_connection_info_find (NMRemoteSettings *self, const char *path)
+_add_connection_info_find (NMRemoteSettings *self, const char *path)
{
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
- GSList *iter;
-
- for (iter = priv->add_list; iter; iter = g_slist_next (iter)) {
- AddConnectionInfo *info = iter->data;
+ AddConnectionInfo *info;
- if (!g_strcmp0 (info->path, path))
+ c_list_for_each_entry (info, &priv->add_lst_head, add_lst) {
+ if (nm_streq0 (info->path, path))
return info;
}
-
return NULL;
}
static void
-add_connection_info_complete (NMRemoteSettings *self,
- AddConnectionInfo *info,
- NMRemoteConnection *connection,
- GError *error)
+_add_connection_info_complete (AddConnectionInfo *info,
+ NMRemoteConnection *connection,
+ GError *error_take)
{
- NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
+ nm_assert (info);
+
+ c_list_unlink_stale (&info->add_lst);
+
+ nm_clear_g_signal_handler (info->cancellable, &info->cancellable_id);
+
+ if ( info->cancellable
+ && !nm_utils_error_is_cancelled (error_take, FALSE)) {
+ GError *error2 = NULL;
+
+ if (g_cancellable_set_error_if_cancelled (info->cancellable, &error2)) {
+ g_clear_error (&error_take);
+ error_take = error2;
+ connection = NULL;
+ }
+ }
+
+ info->callback (info->self,
+ connection,
+ connection ? info->results : NULL,
+ error_take,
+ info->user_data);
- g_return_if_fail (info != NULL);
+ g_clear_error (&error_take);
- if (connection) {
- g_simple_async_result_set_op_res_gpointer (info->simple,
- g_object_ref (connection),
- g_object_unref);
- } else
- g_simple_async_result_set_from_error (info->simple, error);
- g_simple_async_result_complete (info->simple);
+ g_object_unref (info->self);
+ nm_g_object_unref (info->cancellable);
+ nm_clear_g_free (&info->path);
+ nm_g_variant_unref (info->results);
- g_object_unref (info->simple);
- priv->add_list = g_slist_remove (priv->add_list, info);
+ nm_g_slice_free (info);
+}
- g_free (info->path);
- g_slice_free (AddConnectionInfo, info);
+static void
+_add_connection_info_cancelled (GCancellable *cancellable,
+ AddConnectionInfo *info)
+{
+ _add_connection_info_complete (info,
+ NULL,
+ g_error_new_literal (G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ "Operation was cancelled"));
}
typedef const char * (*ConnectionStringGetter) (NMConnection *);
@@ -216,7 +244,7 @@ connection_added (NMRemoteSettings *self,
NMRemoteConnection *remote)
{
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
- AddConnectionInfo *addinfo;
+ AddConnectionInfo *info;
const char *path;
if (!g_signal_handler_find (remote, G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL,
@@ -233,26 +261,27 @@ connection_added (NMRemoteSettings *self,
g_signal_stop_emission (self, signals[CONNECTION_ADDED], 0);
path = nm_connection_get_path (NM_CONNECTION (remote));
- addinfo = add_connection_info_find (self, path);
- if (addinfo)
- add_connection_info_complete (self, addinfo, remote, NULL);
+ info = _add_connection_info_find (self, path);
+ if (info)
+ _add_connection_info_complete (info, remote, NULL);
}
static void
-object_creation_failed (NMObject *object, const char *failed_path)
+object_creation_failed (NMObject *object,
+ const char *failed_path)
{
NMRemoteSettings *self = NM_REMOTE_SETTINGS (object);
- AddConnectionInfo *addinfo;
- GError *add_error;
-
- addinfo = add_connection_info_find (self, failed_path);
- if (addinfo) {
- add_error = g_error_new_literal (NM_CLIENT_ERROR,
- NM_CLIENT_ERROR_OBJECT_CREATION_FAILED,
- _("Connection removed before it was initialized"));
- add_connection_info_complete (self, addinfo, NULL, add_error);
- g_error_free (add_error);
- }
+ AddConnectionInfo *info;
+
+ info = _add_connection_info_find (self, failed_path);
+ if (!info)
+ return;
+
+ _add_connection_info_complete (info,
+ NULL,
+ g_error_new_literal (NM_CLIENT_ERROR,
+ NM_CLIENT_ERROR_OBJECT_CREATION_FAILED,
+ _("Connection removed before it was initialized")));
}
const GPtrArray *
@@ -269,83 +298,114 @@ add_connection_done (GObject *proxy, GAsyncResult *result, gpointer user_data)
AddConnectionInfo *info = user_data;
GError *error = NULL;
- if (info->saved) {
+ if ( info->ignore_out_result
+ && info->flags == NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK) {
nmdbus_settings_call_add_connection_finish (NMDBUS_SETTINGS (proxy),
&info->path,
- result, &error);
- } else {
+ result,
+ &error);
+ } else if ( info->ignore_out_result
+ && info->flags == NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY) {
nmdbus_settings_call_add_connection_unsaved_finish (NMDBUS_SETTINGS (proxy),
&info->path,
- result, &error);
+ result,
+ &error);
+ } else {
+ nmdbus_settings_call_add_connection2_finish (NMDBUS_SETTINGS (proxy),
+ &info->path,
+ &info->results,
+ result,
+ &error);
+ if (info->ignore_out_result) {
+ /* despite we have the result, the caller didn't ask for it.
+ * Through it away, so we consistently don't return a result. */
+ nm_clear_pointer (&info->results, g_variant_unref);
+ }
}
if (error) {
g_dbus_error_strip_remote_error (error);
- add_connection_info_complete (info->self, info, NULL, error);
- g_clear_error (&error);
+ _add_connection_info_complete (info, NULL, error);
+ return;
}
/* On success, we still have to wait until the connection is fully
* initialized before calling the callback.
*/
+ if (info->cancellable) {
+ gulong id;
+
+ id = g_cancellable_connect (info->cancellable,
+ G_CALLBACK (_add_connection_info_cancelled),
+ info,
+ NULL);
+ if (id == 0) {
+ /* the callback was invoked synchronously, which destroyed @info.
+ * We must not touch @info anymore. */
+ } else
+ info->cancellable_id = id;
+ }
}
void
-nm_remote_settings_add_connection_async (NMRemoteSettings *settings,
- NMConnection *connection,
- gboolean save_to_disk,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+nm_remote_settings_add_connection2 (NMRemoteSettings *self,
+ GVariant *settings,
+ NMSettingsAddConnection2Flags flags,
+ GVariant *args,
+ gboolean ignore_out_result,
+ GCancellable *cancellable,
+ NMRemoteSettingAddConnection2Callback callback,
+ gpointer user_data)
{
NMRemoteSettingsPrivate *priv;
AddConnectionInfo *info;
- GVariant *new_settings;
- g_return_if_fail (NM_IS_REMOTE_SETTINGS (settings));
- g_return_if_fail (NM_IS_CONNECTION (connection));
-
- priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
-
- info = g_slice_new0 (AddConnectionInfo);
- info->self = settings;
- info->simple = g_simple_async_result_new (G_OBJECT (settings), callback, user_data,
- nm_remote_settings_add_connection_async);
- if (cancellable)
- g_simple_async_result_set_check_cancellable (info->simple, cancellable);
- info->saved = save_to_disk;
-
- new_settings = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
-
- if (save_to_disk) {
+ nm_assert (NM_IS_REMOTE_SETTINGS (self));
+ nm_assert (g_variant_is_of_type (settings, G_VARIANT_TYPE ("a{sa{sv}}")));
+ nm_assert (!args || g_variant_is_of_type (args, G_VARIANT_TYPE ("a{sv}")));
+ nm_assert (callback);
+
+ priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
+
+ info = g_slice_new (AddConnectionInfo);
+ *info = (AddConnectionInfo) {
+ .self = g_object_ref (self),
+ .cancellable = nm_g_object_ref (cancellable),
+ .flags = flags,
+ .ignore_out_result = ignore_out_result,
+ .callback = callback,
+ .user_data = user_data,
+ };
+ c_list_link_tail (&priv->add_lst_head, &info->add_lst);
+
+ /* Although AddConnection2() being capable to handle also AddConnection() and
+ * AddConnectionUnsaved() variants, we prefer to use the old D-Bus methods when
+ * they are sufficient. The reason is that libnm should avoid hard dependencies
+ * on 1.20 API whenever possible. */
+ if ( ignore_out_result
+ && flags == NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK) {
nmdbus_settings_call_add_connection (priv->proxy,
- new_settings,
- NULL,
- add_connection_done, info);
- } else {
+ settings,
+ cancellable,
+ add_connection_done,
+ info);
+ } else if ( ignore_out_result
+ && flags == NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY) {
nmdbus_settings_call_add_connection_unsaved (priv->proxy,
- new_settings,
- NULL,
- add_connection_done, info);
+ settings,
+ cancellable,
+ add_connection_done,
+ info);
+ } else {
+ nmdbus_settings_call_add_connection2 (priv->proxy,
+ settings,
+ flags,
+ args
+ ?: g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0),
+ cancellable,
+ add_connection_done,
+ info);
}
-
- priv->add_list = g_slist_append (priv->add_list, info);
-}
-
-NMRemoteConnection *
-nm_remote_settings_add_connection_finish (NMRemoteSettings *settings,
- GAsyncResult *result,
- GError **error)
-{
- GSimpleAsyncResult *simple;
-
- g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (settings), nm_remote_settings_add_connection_async), NULL);
-
- simple = G_SIMPLE_ASYNC_RESULT (result);
- if (g_simple_async_result_propagate_error (simple, error))
- return NULL;
- else
- return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
}
gboolean
@@ -606,6 +666,7 @@ nm_remote_settings_init (NMRemoteSettings *self)
{
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
+ c_list_init (&priv->add_lst_head);
priv->all_connections = g_ptr_array_new ();
priv->visible_connections = g_ptr_array_new ();
}
@@ -664,7 +725,7 @@ dispose (GObject *object)
{
NMRemoteSettings *self = NM_REMOTE_SETTINGS (object);
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
- int i;
+ guint i;
if (priv->all_connections) {
for (i = 0; i < priv->all_connections->len; i++)
diff --git a/libnm/nm-remote-settings.h b/libnm/nm-remote-settings.h
index ac0008a942..bd89cf8c68 100644
--- a/libnm/nm-remote-settings.h
+++ b/libnm/nm-remote-settings.h
@@ -73,15 +73,20 @@ NMRemoteConnection *nm_remote_settings_get_connection_by_path (NMRemoteSettings
NMRemoteConnection *nm_remote_settings_get_connection_by_uuid (NMRemoteSettings *settings,
const char *uuid);
-void nm_remote_settings_add_connection_async (NMRemoteSettings *settings,
- NMConnection *connection,
- gboolean save_to_disk,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-NMRemoteConnection *nm_remote_settings_add_connection_finish (NMRemoteSettings *settings,
- GAsyncResult *result,
- GError **error);
+typedef void (*NMRemoteSettingAddConnection2Callback) (NMRemoteSettings *self,
+ NMRemoteConnection *connection,
+ GVariant *results,
+ GError *error,
+ gpointer user_data);
+
+void nm_remote_settings_add_connection2 (NMRemoteSettings *self,
+ GVariant *settings,
+ NMSettingsAddConnection2Flags flags,
+ GVariant *args,
+ gboolean ignore_out_result,
+ GCancellable *cancellable,
+ NMRemoteSettingAddConnection2Callback callback,
+ gpointer user_data);
gboolean nm_remote_settings_load_connections (NMRemoteSettings *settings,
char **filenames,
diff --git a/shared/nm-glib-aux/nm-macros-internal.h b/shared/nm-glib-aux/nm-macros-internal.h
index 9062fe8d98..9502c442ec 100644
--- a/shared/nm-glib-aux/nm-macros-internal.h
+++ b/shared/nm-glib-aux/nm-macros-internal.h
@@ -1569,6 +1569,11 @@ nm_strcmp_p (gconstpointer a, gconstpointer b)
/*****************************************************************************/
+#define nm_g_slice_free(ptr) \
+ g_slice_free (typeof (*(ptr)), ptr)
+
+/*****************************************************************************/
+
/* like g_memdup(). The difference is that the @size argument is of type
* gsize, while g_memdup() has type guint. Since, the size of container types
* like GArray is guint as well, this means trying to g_memdup() an
diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c
index e8ca6dd159..fb0a72c40f 100644
--- a/src/devices/bluetooth/nm-bluez-device.c
+++ b/src/devices/bluetooth/nm-bluez-device.c
@@ -238,6 +238,7 @@ pan_connection_check_create (NMBluezDevice *self)
nm_settings_add_connection (priv->settings,
connection,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY,
+ NM_SETTINGS_CONNECTION_ADD_REASON_NONE,
NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED,
&added,
&error);
diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/devices/wifi/nm-iwd-manager.c
index 8889bb204a..b696f128a7 100644
--- a/src/devices/wifi/nm-iwd-manager.c
+++ b/src/devices/wifi/nm-iwd-manager.c
@@ -472,6 +472,7 @@ mirror_8021x_connection (NMIwdManager *self,
if (!nm_settings_add_connection (priv->settings,
connection,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY,
+ NM_SETTINGS_CONNECTION_ADD_REASON_NONE,
NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED,
&settings_connection,
&error)) {
diff --git a/src/nm-checkpoint.c b/src/nm-checkpoint.c
index d2cc52e7af..1f7723c539 100644
--- a/src/nm-checkpoint.c
+++ b/src/nm-checkpoint.c
@@ -258,6 +258,7 @@ restore_and_activate_connection (NMCheckpoint *self,
if (!nm_settings_add_connection (NM_SETTINGS_GET,
dev_checkpoint->settings_connection,
persist_mode,
+ NM_SETTINGS_CONNECTION_ADD_REASON_NONE,
sett_flags,
&connection,
&local_error)) {
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 93bfb14720..4f114e4d13 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -2674,6 +2674,7 @@ get_existing_connection (NMManager *self,
if (!nm_settings_add_connection (priv->settings,
connection,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY,
+ NM_SETTINGS_CONNECTION_ADD_REASON_NONE,
NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE
| NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED,
&added,
@@ -5419,6 +5420,7 @@ _add_and_activate_auth_done (NMManager *self,
nm_settings_add_connection_dbus (priv->settings,
connection,
persist_mode,
+ NM_SETTINGS_CONNECTION_ADD_REASON_NONE,
( is_volatile
? NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE
: NM_SETTINGS_CONNECTION_INT_FLAGS_NONE),
diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c
index 06b1561b6b..2093342c9c 100644
--- a/src/settings/nm-settings-connection.c
+++ b/src/settings/nm-settings-connection.c
@@ -1438,7 +1438,7 @@ update_complete (NMSettingsConnection *self,
g_variant_builder_init (&result, G_VARIANT_TYPE ("a{sv}"));
g_dbus_method_invocation_return_value (info->context,
- g_variant_new ("(@a{sv})", g_variant_builder_end (&result)));
+ g_variant_new ("(a{sv})", &result));
} else
g_dbus_method_invocation_return_value (info->context, NULL);
@@ -1514,12 +1514,6 @@ update_auth_cb (NMSettingsConnection *self,
} else
persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP;
- if (NM_FLAGS_HAS (info->flags, NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT)) {
- nm_settings_connection_autoconnect_blocked_reason_set (self,
- NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST,
- TRUE);
- }
-
nm_settings_connection_update (self,
info->new_settings,
persist_mode,
@@ -1529,9 +1523,14 @@ update_auth_cb (NMSettingsConnection *self,
NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED
| NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE,
NM_SETTINGS_CONNECTION_UPDATE_REASON_FORCE_RENAME
- | NM_SETTINGS_CONNECTION_UPDATE_REASON_REAPPLY_PARTIAL
+ | ( NM_FLAGS_HAS (info->flags, NM_SETTINGS_UPDATE2_FLAG_NO_REAPPLY)
+ ? NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE
+ : NM_SETTINGS_CONNECTION_UPDATE_REASON_REAPPLY_PARTIAL)
| NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS
- | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS,
+ | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS
+ | ( NM_FLAGS_HAS (info->flags, NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT)
+ ? NM_SETTINGS_CONNECTION_UPDATE_REASON_BLOCK_AUTOCONNECT
+ : NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE),
"update-from-dbus",
&local);
@@ -1733,9 +1732,10 @@ impl_settings_connection_update2 (NMDBusObject *obj,
g_variant_get (parameters, "(@a{sa{sv}}u@a{sv})", &settings, &flags_u, &args);
- if (NM_FLAGS_ANY (flags_u, ~((guint32) (ALL_PERSIST_MODES |
- NM_SETTINGS_UPDATE2_FLAG_VOLATILE |
- NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT)))) {
+ if (NM_FLAGS_ANY (flags_u, ~((guint32) ( ALL_PERSIST_MODES
+ | NM_SETTINGS_UPDATE2_FLAG_VOLATILE
+ | NM_SETTINGS_UPDATE2_FLAG_BLOCK_AUTOCONNECT
+ | NM_SETTINGS_UPDATE2_FLAG_NO_REAPPLY)))) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_INVALID_ARGUMENTS,
"Unknown flags");
@@ -1757,13 +1757,7 @@ impl_settings_connection_update2 (NMDBusObject *obj,
return;
}
- if (!g_variant_is_of_type (args, G_VARIANT_TYPE ("a{sv}"))) {
- error = g_error_new_literal (NM_SETTINGS_ERROR,
- NM_SETTINGS_ERROR_INVALID_ARGUMENTS,
- "args is of invalid type");
- g_dbus_method_invocation_take_error (invocation, error);
- return;
- }
+ nm_assert (g_variant_is_of_type (args, G_VARIANT_TYPE ("a{sv}")));
g_variant_iter_init (&iter, args);
while (g_variant_iter_next (&iter, "{&sv}", &args_name, NULL)) {
diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h
index 9dfc473da7..ab23dc1ff5 100644
--- a/src/settings/nm-settings-connection.h
+++ b/src/settings/nm-settings-connection.h
@@ -30,6 +30,14 @@
typedef enum {
+ NM_SETTINGS_CONNECTION_ADD_REASON_NONE = 0,
+
+ NM_SETTINGS_CONNECTION_ADD_REASON_BLOCK_AUTOCONNECT = (1u << 0),
+
+} NMSettingsConnectionAddReason;
+
+typedef enum {
+
NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE = 0,
/* with persist-mode != NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY, and
@@ -50,7 +58,10 @@ typedef enum {
/* 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. */
+ * right away.
+ *
+ * See also %NM_SETTINGS_UPDATE2_FLAG_NO_REAPPLY flag, to prevent partial reapply
+ * during Update2(). */
NM_SETTINGS_CONNECTION_UPDATE_REASON_REAPPLY_PARTIAL = (1u << 2),
NM_SETTINGS_CONNECTION_UPDATE_REASON_CLEAR_SYSTEM_SECRETS = (1u << 3),
@@ -64,6 +75,8 @@ typedef enum {
* to disk and it the purpose why the profile was created should be forgotten. */
NM_SETTINGS_CONNECTION_UPDATE_REASON_CLEAR_DEFAULT_WIRED = (1u << 7),
+ NM_SETTINGS_CONNECTION_UPDATE_REASON_BLOCK_AUTOCONNECT = (1u << 8),
+
} NMSettingsConnectionUpdateReason;
typedef enum {
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index e24814b1d8..6961134c6c 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -923,7 +923,12 @@ _connection_changed_update (NMSettings *self,
priv->connections_generation++;
g_signal_connect (sett_conn, NM_SETTINGS_CONNECTION_FLAGS_CHANGED, G_CALLBACK (connection_flags_changed), self);
+ }
+ if (NM_FLAGS_HAS (update_reason, NM_SETTINGS_CONNECTION_UPDATE_REASON_BLOCK_AUTOCONNECT)) {
+ nm_settings_connection_autoconnect_blocked_reason_set (sett_conn,
+ NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST,
+ TRUE);
}
sett_mask |= NM_SETTINGS_CONNECTION_INT_FLAGS_VISIBLE;
@@ -1371,6 +1376,7 @@ _add_connection_to_first_plugin (NMSettings *self,
* @self: the #NMSettings object
* @connection: the source connection to create a new #NMSettingsConnection from
* @persist_mode: the persist-mode for this profile.
+ * @add_reason: the add-reason flags.
* @sett_flags: the settings flags to set.
* @out_sett_conn: (allow-none) (transfer none): the added settings connection on success.
* @error: on return, a location to store any errors that may occur
@@ -1385,6 +1391,7 @@ gboolean
nm_settings_add_connection (NMSettings *self,
NMConnection *connection,
NMSettingsConnectionPersistMode persist_mode,
+ NMSettingsConnectionAddReason add_reason,
NMSettingsConnectionIntFlags sett_flags,
NMSettingsConnection **out_sett_conn,
GError **error)
@@ -1408,6 +1415,8 @@ nm_settings_add_connection (NMSettings *self,
nm_assert ( !NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE)
|| persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY);
+ nm_assert (!NM_FLAGS_ANY (add_reason, ~NM_SETTINGS_CONNECTION_ADD_REASON_BLOCK_AUTOCONNECT));
+
NM_SET_OUT (out_sett_conn, NULL);
uuid = nm_connection_get_uuid (connection);
@@ -1486,7 +1495,10 @@ nm_settings_add_connection (NMSettings *self,
_NM_SETTINGS_CONNECTION_INT_FLAGS_PERSISTENT_MASK,
FALSE,
NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS
- | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS);
+ | NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS
+ | ( NM_FLAGS_HAS (add_reason, NM_SETTINGS_CONNECTION_ADD_REASON_BLOCK_AUTOCONNECT)
+ ? NM_SETTINGS_CONNECTION_UPDATE_REASON_BLOCK_AUTOCONNECT
+ : NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE));
nm_assert (sett_conn_entry == _sett_conn_entries_get (self, sett_conn_entry->uuid));
nm_assert (NM_IS_SETTINGS_CONNECTION (sett_conn_entry->sett_conn));
@@ -1972,6 +1984,7 @@ pk_add_cb (NMAuthChain *chain,
nm_settings_add_connection (self,
connection,
GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "persist-mode")),
+ GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "add-reason")),
GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "sett-flags")),
&added,
&error);
@@ -1999,6 +2012,7 @@ void
nm_settings_add_connection_dbus (NMSettings *self,
NMConnection *connection,
NMSettingsConnectionPersistMode persist_mode,
+ NMSettingsConnectionAddReason add_reason,
NMSettingsConnectionIntFlags sett_flags,
NMAuthSubject *subject,
GDBusMethodInvocation *context,
@@ -2073,6 +2087,7 @@ nm_settings_add_connection_dbus (NMSettings *self,
nm_auth_chain_set_data (chain, "callback-data", user_data, NULL);
nm_auth_chain_set_data (chain, "subject", g_object_ref (subject), g_object_unref);
nm_auth_chain_set_data (chain, "persist-mode", GUINT_TO_POINTER (persist_mode), NULL);
+ nm_auth_chain_set_data (chain, "add-reason", GUINT_TO_POINTER (add_reason), NULL);
nm_auth_chain_set_data (chain, "sett-flags", GUINT_TO_POINTER (sett_flags), NULL);
nm_auth_chain_add_call_unsafe (chain, perm, TRUE);
return;
@@ -2091,27 +2106,42 @@ settings_add_connection_add_cb (NMSettings *self,
NMAuthSubject *subject,
gpointer user_data)
{
+ gboolean is_add_connection_2 = GPOINTER_TO_INT (user_data);
+
if (error) {
g_dbus_method_invocation_return_gerror (context, error);
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD, NULL, FALSE, NULL, subject, error->message);
+ return;
+ }
+
+ if (is_add_connection_2) {
+ GVariantBuilder builder;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
+ g_dbus_method_invocation_return_value (context,
+ g_variant_new ("(oa{sv})",
+ nm_dbus_object_get_path (NM_DBUS_OBJECT (connection)),
+ &builder));
} else {
g_dbus_method_invocation_return_value (context,
g_variant_new ("(o)",
nm_dbus_object_get_path (NM_DBUS_OBJECT (connection))));
- nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD, connection, TRUE, NULL,
- subject, NULL);
}
+ nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD, connection, TRUE, NULL,
+ subject, NULL);
}
static void
settings_add_connection_helper (NMSettings *self,
GDBusMethodInvocation *context,
+ gboolean is_add_connection_2,
GVariant *settings,
- NMSettingsConnectionPersistMode persist_mode)
+ NMSettingsAddConnection2Flags flags)
{
gs_unref_object NMConnection *connection = NULL;
GError *error = NULL;
gs_unref_object NMAuthSubject *subject = NULL;
+ NMSettingsConnectionPersistMode persist_mode;
connection = _nm_simple_connection_new_from_dbus (settings,
NM_SETTING_PARSE_FLAGS_STRICT
@@ -2133,14 +2163,24 @@ settings_add_connection_helper (NMSettings *self,
return;
}
+ if (NM_FLAGS_HAS (flags, NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK))
+ persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK;
+ else {
+ nm_assert (NM_FLAGS_HAS (flags, NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY));
+ persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY;
+ }
+
nm_settings_add_connection_dbus (self,
connection,
persist_mode,
+ NM_FLAGS_HAS (flags, NM_SETTINGS_ADD_CONNECTION2_FLAG_BLOCK_AUTOCONNECT)
+ ? NM_SETTINGS_CONNECTION_ADD_REASON_BLOCK_AUTOCONNECT
+ : NM_SETTINGS_CONNECTION_ADD_REASON_NONE,
NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
subject,
context,
settings_add_connection_add_cb,
- NULL);
+ GINT_TO_POINTER (!!is_add_connection_2));
}
static void
@@ -2156,7 +2196,7 @@ impl_settings_add_connection (NMDBusObject *obj,
gs_unref_variant GVariant *settings = NULL;
g_variant_get (parameters, "(@a{sa{sv}})", &settings);
- settings_add_connection_helper (self, invocation, settings, NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK);
+ settings_add_connection_helper (self, invocation, FALSE, settings, NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK);
}
static void
@@ -2172,7 +2212,70 @@ impl_settings_add_connection_unsaved (NMDBusObject *obj,
gs_unref_variant GVariant *settings = NULL;
g_variant_get (parameters, "(@a{sa{sv}})", &settings);
- settings_add_connection_helper (self, invocation, settings, NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY);
+ settings_add_connection_helper (self, invocation, FALSE, settings, NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY);
+}
+
+static void
+impl_settings_add_connection2 (NMDBusObject *obj,
+ const NMDBusInterfaceInfoExtended *interface_info,
+ const NMDBusMethodInfoExtended *method_info,
+ GDBusConnection *connection,
+ const char *sender,
+ GDBusMethodInvocation *invocation,
+ GVariant *parameters)
+{
+ NMSettings *self = NM_SETTINGS (obj);
+ gs_unref_variant GVariant *settings = NULL;
+ gs_unref_variant GVariant *args = NULL;
+ NMSettingsAddConnection2Flags flags;
+ const char *args_name;
+ GVariantIter iter;
+ guint32 flags_u;
+
+ g_variant_get (parameters, "(@a{sa{sv}}u@a{sv})", &settings, &flags_u, &args);
+
+ if (NM_FLAGS_ANY (flags_u, ~((guint32) ( NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK
+ | NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY
+ | NM_SETTINGS_ADD_CONNECTION2_FLAG_BLOCK_AUTOCONNECT)))) {
+ g_dbus_method_invocation_take_error (invocation,
+ g_error_new_literal (NM_SETTINGS_ERROR,
+ NM_SETTINGS_ERROR_INVALID_ARGUMENTS,
+ "Unknown flags"));
+ return;
+ }
+
+ flags = flags_u;
+
+ if (!NM_FLAGS_ANY (flags, NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK
+ | NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY)) {
+ g_dbus_method_invocation_take_error (invocation,
+ g_error_new_literal (NM_SETTINGS_ERROR,
+ NM_SETTINGS_ERROR_INVALID_ARGUMENTS,
+ "Requires either to-disk (0x1) or in-memory (0x2) flags"));
+ return;
+ }
+
+ if (NM_FLAGS_ALL (flags, NM_SETTINGS_ADD_CONNECTION2_FLAG_TO_DISK
+ | NM_SETTINGS_ADD_CONNECTION2_FLAG_IN_MEMORY)) {
+ g_dbus_method_invocation_take_error (invocation,
+ g_error_new_literal (NM_SETTINGS_ERROR,
+ NM_SETTINGS_ERROR_INVALID_ARGUMENTS,
+ "Cannot set to-disk (0x1) and in-memory (0x2) flags together"));
+ return;
+ }
+
+ nm_assert (g_variant_is_of_type (args, G_VARIANT_TYPE ("a{sv}")));
+
+ g_variant_iter_init (&iter, args);
+ while (g_variant_iter_next (&iter, "{&sv}", &args_name, NULL)) {
+ g_dbus_method_invocation_take_error (invocation,
+ g_error_new (NM_SETTINGS_ERROR,
+ NM_SETTINGS_ERROR_INVALID_ARGUMENTS,
+ "Unsupported argument '%s'", args_name));
+ return;
+ }
+
+ settings_add_connection_helper (self, invocation, TRUE, settings, flags);
}
/*****************************************************************************/
@@ -2941,6 +3044,7 @@ device_realized (NMDevice *device, GParamSpec *pspec, NMSettings *self)
nm_settings_add_connection (self,
connection,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY,
+ NM_SETTINGS_CONNECTION_ADD_REASON_NONE,
NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED,
&added,
&error);
@@ -3440,6 +3544,21 @@ static const NMDBusInterfaceInfoExtended interface_info_settings = {
),
NM_DEFINE_DBUS_METHOD_INFO_EXTENDED (
NM_DEFINE_GDBUS_METHOD_INFO_INIT (
+ "AddConnection2",
+ .in_args = NM_DEFINE_GDBUS_ARG_INFOS (
+ NM_DEFINE_GDBUS_ARG_INFO ("settings", "a{sa{sv}}"),
+ NM_DEFINE_GDBUS_ARG_INFO ("flags", "u"),
+ NM_DEFINE_GDBUS_ARG_INFO ("args", "a{sv}"),
+ ),
+ .out_args = NM_DEFINE_GDBUS_ARG_INFOS (
+ NM_DEFINE_GDBUS_ARG_INFO ("path", "o"),
+ NM_DEFINE_GDBUS_ARG_INFO ("result", "a{sv}"),
+ ),
+ ),
+ .handle = impl_settings_add_connection2,
+ ),
+ NM_DEFINE_DBUS_METHOD_INFO_EXTENDED (
+ NM_DEFINE_GDBUS_METHOD_INFO_INIT (
"LoadConnections",
.in_args = NM_DEFINE_GDBUS_ARG_INFOS (
NM_DEFINE_GDBUS_ARG_INFO ("filenames", "as"),
diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h
index bcb30dff2a..d2bf72d693 100644
--- a/src/settings/nm-settings.h
+++ b/src/settings/nm-settings.h
@@ -82,6 +82,7 @@ typedef void (*NMSettingsAddCallback) (NMSettings *settings,
void nm_settings_add_connection_dbus (NMSettings *self,
NMConnection *connection,
NMSettingsConnectionPersistMode persist_mode,
+ NMSettingsConnectionAddReason add_reason,
NMSettingsConnectionIntFlags sett_flags,
NMAuthSubject *subject,
GDBusMethodInvocation *context,
@@ -100,6 +101,7 @@ NMSettingsConnection **nm_settings_get_connections_clone (NMSettings *self,
gboolean nm_settings_add_connection (NMSettings *settings,
NMConnection *connection,
NMSettingsConnectionPersistMode persist_mode,
+ NMSettingsConnectionAddReason add_reason,
NMSettingsConnectionIntFlags sett_flags,
NMSettingsConnection **out_sett_conn,
GError **error);